drm-misc-next for v6.4-rc1: Note: Only changes since pull request from 2023-02-23 are included here. UAPI Changes: - Convert rockchip bindings to YAML. - Constify kobj_type structure in dma-buf. - FBDEV cmdline parser fixes, and other small fbdev fixes for mode parsing. Cross-subsystem Changes: - Add Neil Armstrong as linaro maintainer. - Actually signal the private stub dma-fence. Core Changes: - Add function for adding syncobj dep to sched_job and use it in panfrost, v3d. - Improve DisplayID 2.0 topology parsing and EDID parsing in general. - Add a gem eviction function and callback for generic GEM shrinker purposes. - Prepare to convert shmem helper to use the GEM reservation lock instead of own locking. (Actual commit itself got reverted for now) - Move the suballocator from radeon and amdgpu drivers to core in preparation for Xe. - Assorted small fixes and documentation. - Fixes to HPD polling. - Assorted small fixes in simpledrm, bridge, accel, shmem-helper, and the selftest of format-helper. - Remove dummy resource when ttm bo is created, and during pipelined gutting. Fix all drivers to accept a NULL ttm_bo->resource. - Handle pinned BO moving prevention in ttm core. - Set drm panel-bridge orientation before connector is registered. - Remove dumb_destroy callback. - Add documentation to GEM_CLOSE, PRIME_HANDLE_TO_FD, PRIME_FD_TO_HANDLE, GETFB2 ioctl's. - Add atomic enable_plane callback, use it in ast, mgag200, tidss. Driver Changes: - Use drm_gem_objects_lookup in vc4. - Assorted small fixes to virtio, ast, bridge/tc358762, meson, nouveau. - Allow virtio KMS to be disabled and compiled out. - Add Radxa 8/10HD, Samsung AMS495QA01 panels. - Fix ivpu compiler errors. - Assorted fixes to drm/panel, malidp, rockchip, ivpu, amdgpu, vgem, nouveau, vc4. - Assorted cleanups, simplifications and fixes to vmwgfx. Signed-off-by: Dave Airlie <airlied@redhat.com>
Unified · Split
| @@ -0,0 +1,63 @@ | |||
| 1 | # SPDX-License-Identifier: GPL-2.0 | ||
| 2 | %YAML 1.2 | ||
| 3 | --- | ||
| 4 | $id: http://devicetree.org/schemas/display/bridge/analogix,dp.yaml# | ||
| 5 | $schema: http://devicetree.org/meta-schemas/core.yaml# | ||
| 6 | |||
| 7 | title: Analogix Display Port bridge | ||
| 8 | |||
| 9 | maintainers: | ||
| 10 | - Rob Herring <robh@kernel.org> | ||
| 11 | |||
| 12 | properties: | ||
| 13 | reg: | ||
| 14 | maxItems: 1 | ||
| 15 | |||
| 16 | interrupts: | ||
| 17 | maxItems: 1 | ||
| 18 | |||
| 19 | clocks: true | ||
| 20 | |||
| 21 | clock-names: true | ||
| 22 | |||
| 23 | phys: true | ||
| 24 | |||
| 25 | phy-names: | ||
| 26 | const: dp | ||
| 27 | |||
| 28 | force-hpd: | ||
| 29 | description: | ||
| 30 | Indicate driver need force hpd when hpd detect failed, this | ||
| 31 | is used for some eDP screen which don not have a hpd signal. | ||
| 32 | |||
| 33 | hpd-gpios: | ||
| 34 | description: | ||
| 35 | Hotplug detect GPIO. | ||
| 36 | Indicates which GPIO should be used for hotplug detection | ||
| 37 | |||
| 38 | ports: | ||
| 39 | $ref: /schemas/graph.yaml#/properties/ports | ||
| 40 | |||
| 41 | properties: | ||
| 42 | port@0: | ||
| 43 | $ref: /schemas/graph.yaml#/properties/port | ||
| 44 | description: | ||
| 45 | Input node to receive pixel data. | ||
| 46 | |||
| 47 | port@1: | ||
| 48 | $ref: /schemas/graph.yaml#/properties/port | ||
| 49 | description: | ||
| 50 | Port node with one endpoint connected to a dp-connector node. | ||
| 51 | |||
| 52 | required: | ||
| 53 | - port@0 | ||
| 54 | - port@1 | ||
| 55 | |||
| 56 | required: | ||
| 57 | - reg | ||
| 58 | - interrupts | ||
| 59 | - clock-names | ||
| 60 | - clocks | ||
| 61 | - ports | ||
| 62 | |||
| 63 | additionalProperties: true | ||
| @@ -1,51 +0,0 @@ | |||
| 1 | Analogix Display Port bridge bindings | ||
| 2 | |||
| 3 | Required properties for dp-controller: | ||
| 4 | -compatible: | ||
| 5 | platform specific such as: | ||
| 6 | * "samsung,exynos5-dp" | ||
| 7 | * "rockchip,rk3288-dp" | ||
| 8 | * "rockchip,rk3399-edp" | ||
| 9 | -reg: | ||
| 10 | physical base address of the controller and length | ||
| 11 | of memory mapped region. | ||
| 12 | -interrupts: | ||
| 13 | interrupt combiner values. | ||
| 14 | -clocks: | ||
| 15 | from common clock binding: handle to dp clock. | ||
| 16 | -clock-names: | ||
| 17 | from common clock binding: Shall be "dp". | ||
| 18 | -phys: | ||
| 19 | from general PHY binding: the phandle for the PHY device. | ||
| 20 | -phy-names: | ||
| 21 | from general PHY binding: Should be "dp". | ||
| 22 | |||
| 23 | Optional properties for dp-controller: | ||
| 24 | -force-hpd: | ||
| 25 | Indicate driver need force hpd when hpd detect failed, this | ||
| 26 | is used for some eDP screen which don't have hpd signal. | ||
| 27 | -hpd-gpios: | ||
| 28 | Hotplug detect GPIO. | ||
| 29 | Indicates which GPIO should be used for hotplug detection | ||
| 30 | -port@[X]: SoC specific port nodes with endpoint definitions as defined | ||
| 31 | in Documentation/devicetree/bindings/media/video-interfaces.txt, | ||
| 32 | please refer to the SoC specific binding document: | ||
| 33 | * Documentation/devicetree/bindings/display/exynos/exynos_dp.txt | ||
| 34 | * Documentation/devicetree/bindings/display/rockchip/analogix_dp-rockchip.txt | ||
| 35 | |||
| 36 | [1]: Documentation/devicetree/bindings/media/video-interfaces.txt | ||
| 37 | ------------------------------------------------------------------------------- | ||
| 38 | |||
| 39 | Example: | ||
| 40 | |||
| 41 | dp-controller { | ||
| 42 | compatible = "samsung,exynos5-dp"; | ||
| 43 | reg = <0x145b0000 0x10000>; | ||
| 44 | interrupts = <10 3>; | ||
| 45 | interrupt-parent = <&combiner>; | ||
| 46 | clocks = <&clock 342>; | ||
| 47 | clock-names = "dp"; | ||
| 48 | |||
| 49 | phys = <&dp_phy>; | ||
| 50 | phy-names = "dp"; | ||
| 51 | }; | ||
| @@ -26,19 +26,9 @@ properties: · 25 unmodified lines | |||
| 26 | reg: | 26 | reg: |
| 27 | maxItems: 1 | 27 | maxItems: 1 |
| 28 | 28 | ||
| 29 | clocks: | 29 | clocks: true |
| 30 | items: | 30 | |
| 31 | - description: Module clock | 31 | clock-names: true |
| 32 | - description: DSI bus clock for either AHB and APB | ||
| 33 | - description: Pixel clock for the DPI/RGB input | ||
| 34 | minItems: 2 | ||
| 35 | |||
| 36 | clock-names: | ||
| 37 | items: | ||
| 38 | - const: ref | ||
| 39 | - const: pclk | ||
| 40 | - const: px_clk | ||
| 41 | minItems: 2 | ||
| 42 | 32 | ||
| 43 | resets: | 33 | resets: |
| 44 | maxItems: 1 | 34 | maxItems: 1 |
| @@ -30,6 +30,15 @@ properties: · 29 unmodified lines | |||
| 30 | $nodename: | 30 | $nodename: |
| 31 | pattern: "^dsi(@.*)?$" | 31 | pattern: "^dsi(@.*)?$" |
| 32 | 32 | ||
| 33 | clock-master: | ||
| 34 | type: boolean | ||
| 35 | description: | ||
| 36 | Should be enabled if the host is being used in conjunction with | ||
| 37 | another DSI host to drive the same peripheral. Hardware supporting | ||
| 38 | such a configuration generally requires the data on both the busses | ||
| 39 | to be driven by the same clock. Only the DSI host instance | ||
| 40 | controlling this clock should contain this property. | ||
| 41 | |||
| 33 | "#address-cells": | 42 | "#address-cells": |
| 34 | const: 1 | 43 | const: 1 |
| 35 | 44 | ||
| @@ -52,15 +61,6 @@ patternProperties: · 16 unmodified lines | |||
| 52 | case the reg property can take multiple entries, one for each virtual | 61 | case the reg property can take multiple entries, one for each virtual |
| 53 | channel that the peripheral responds to. | 62 | channel that the peripheral responds to. |
| 54 | 63 | ||
| 55 | clock-master: | ||
| 56 | type: boolean | ||
| 57 | description: | ||
| 58 | Should be enabled if the host is being used in conjunction with | ||
| 59 | another DSI host to drive the same peripheral. Hardware supporting | ||
| 60 | such a configuration generally requires the data on both the busses | ||
| 61 | to be driven by the same clock. Only the DSI host instance | ||
| 62 | controlling this clock should contain this property. | ||
| 63 | |||
| 64 | enforce-video-mode: | 64 | enforce-video-mode: |
| 65 | type: boolean | 65 | type: boolean |
| 66 | description: | 66 | description: |
| @@ -50,7 +50,7 @@ Optional properties for dp-controller: · 49 unmodified lines | |||
| 50 | Documentation/devicetree/bindings/display/panel/display-timing.txt | 50 | Documentation/devicetree/bindings/display/panel/display-timing.txt |
| 51 | 51 | ||
| 52 | For the below properties, please refer to Analogix DP binding document: | 52 | For the below properties, please refer to Analogix DP binding document: |
| 53 | * Documentation/devicetree/bindings/display/bridge/analogix_dp.txt | 53 | * Documentation/devicetree/bindings/display/bridge/analogix,dp.yaml |
| 54 | -phys (required) | 54 | -phys (required) |
| 55 | -phy-names (required) | 55 | -phy-names (required) |
| 56 | -hpd-gpios (optional) | 56 | -hpd-gpios (optional) |
| @@ -17,6 +17,8 @@ properties: · 16 unmodified lines | |||
| 17 | items: | 17 | items: |
| 18 | - enum: | 18 | - enum: |
| 19 | - chongzhou,cz101b4001 | 19 | - chongzhou,cz101b4001 |
| 20 | - radxa,display-10hd-ad001 | ||
| 21 | - radxa,display-8hd-ad002 | ||
| 20 | - const: jadard,jd9365da-h3 | 22 | - const: jadard,jd9365da-h3 |
| 21 | 23 | ||
| 22 | reg: true | 24 | reg: true |
| @@ -0,0 +1,57 @@ | |||
| 1 | # SPDX-License-Identifier: (GPL-2.0-only OR BSD-2-Clause) | ||
| 2 | %YAML 1.2 | ||
| 3 | --- | ||
| 4 | $id: http://devicetree.org/schemas/display/panel/samsung,ams495qa01.yaml# | ||
| 5 | $schema: http://devicetree.org/meta-schemas/core.yaml# | ||
| 6 | |||
| 7 | title: Samsung AMS495QA01 panel with Magnachip D53E6EA8966 controller | ||
| 8 | |||
| 9 | maintainers: | ||
| 10 | - Chris Morgan <macromorgan@hotmail.com> | ||
| 11 | |||
| 12 | allOf: | ||
| 13 | - $ref: panel-common.yaml# | ||
| 14 | |||
| 15 | properties: | ||
| 16 | compatible: | ||
| 17 | const: samsung,ams495qa01 | ||
| 18 | |||
| 19 | reg: true | ||
| 20 | reset-gpios: | ||
| 21 | description: reset gpio, must be GPIO_ACTIVE_LOW | ||
| 22 | elvdd-supply: | ||
| 23 | description: regulator that supplies voltage to the panel display | ||
| 24 | enable-gpios: true | ||
| 25 | port: true | ||
| 26 | vdd-supply: | ||
| 27 | description: regulator that supplies voltage to panel logic | ||
| 28 | |||
| 29 | required: | ||
| 30 | - compatible | ||
| 31 | - reg | ||
| 32 | - reset-gpios | ||
| 33 | - vdd-supply | ||
| 34 | |||
| 35 | additionalProperties: false | ||
| 36 | |||
| 37 | examples: | ||
| 38 | - | | ||
| 39 | #include <dt-bindings/gpio/gpio.h> | ||
| 40 | spi { | ||
| 41 | #address-cells = <1>; | ||
| 42 | #size-cells = <0>; | ||
| 43 | panel@0 { | ||
| 44 | compatible = "samsung,ams495qa01"; | ||
| 45 | reg = <0>; | ||
| 46 | reset-gpios = <&gpio4 0 GPIO_ACTIVE_LOW>; | ||
| 47 | vdd-supply = <&vcc_3v3>; | ||
| 48 | |||
| 49 | port { | ||
| 50 | mipi_in_panel: endpoint { | ||
| 51 | remote-endpoint = <&mipi_out_panel>; | ||
| 52 | }; | ||
| 53 | }; | ||
| 54 | }; | ||
| 55 | }; | ||
| 56 | |||
| 57 | ... | ||
| @@ -1,98 +0,0 @@ | |||
| 1 | Rockchip RK3288 specific extensions to the Analogix Display Port | ||
| 2 | ================================ | ||
| 3 | |||
| 4 | Required properties: | ||
| 5 | - compatible: "rockchip,rk3288-dp", | ||
| 6 | "rockchip,rk3399-edp"; | ||
| 7 | |||
| 8 | - reg: physical base address of the controller and length | ||
| 9 | |||
| 10 | - clocks: from common clock binding: handle to dp clock. | ||
| 11 | of memory mapped region. | ||
| 12 | |||
| 13 | - clock-names: from common clock binding: | ||
| 14 | Required elements: "dp" "pclk" | ||
| 15 | |||
| 16 | - resets: Must contain an entry for each entry in reset-names. | ||
| 17 | See ../reset/reset.txt for details. | ||
| 18 | |||
| 19 | - pinctrl-names: Names corresponding to the chip hotplug pinctrl states. | ||
| 20 | - pinctrl-0: pin-control mode. should be <&edp_hpd> | ||
| 21 | |||
| 22 | - reset-names: Must include the name "dp" | ||
| 23 | |||
| 24 | - rockchip,grf: this soc should set GRF regs, so need get grf here. | ||
| 25 | |||
| 26 | - ports: there are 2 port nodes with endpoint definitions as defined in | ||
| 27 | Documentation/devicetree/bindings/media/video-interfaces.txt. | ||
| 28 | Port 0: contained 2 endpoints, connecting to the output of vop. | ||
| 29 | Port 1: contained 1 endpoint, connecting to the input of panel. | ||
| 30 | |||
| 31 | Optional property for different chips: | ||
| 32 | - clocks: from common clock binding: handle to grf_vio clock. | ||
| 33 | |||
| 34 | - clock-names: from common clock binding: | ||
| 35 | Required elements: "grf" | ||
| 36 | |||
| 37 | For the below properties, please refer to Analogix DP binding document: | ||
| 38 | * Documentation/devicetree/bindings/display/bridge/analogix_dp.txt | ||
| 39 | - phys (required) | ||
| 40 | - phy-names (required) | ||
| 41 | - hpd-gpios (optional) | ||
| 42 | - force-hpd (optional) | ||
| 43 | ------------------------------------------------------------------------------- | ||
| 44 | |||
| 45 | Example: | ||
| 46 | dp-controller: dp@ff970000 { | ||
| 47 | compatible = "rockchip,rk3288-dp"; | ||
| 48 | reg = <0xff970000 0x4000>; | ||
| 49 | interrupts = <GIC_SPI 98 IRQ_TYPE_LEVEL_HIGH>; | ||
| 50 | clocks = <&cru SCLK_EDP>, <&cru PCLK_EDP_CTRL>; | ||
| 51 | clock-names = "dp", "pclk"; | ||
| 52 | phys = <&dp_phy>; | ||
| 53 | phy-names = "dp"; | ||
| 54 | |||
| 55 | rockchip,grf = <&grf>; | ||
| 56 | resets = <&cru 111>; | ||
| 57 | reset-names = "dp"; | ||
| 58 | |||
| 59 | pinctrl-names = "default"; | ||
| 60 | pinctrl-0 = <&edp_hpd>; | ||
| 61 | |||
| 62 | |||
| 63 | ports { | ||
| 64 | #address-cells = <1>; | ||
| 65 | #size-cells = <0>; | ||
| 66 | edp_in: port@0 { | ||
| 67 | reg = <0>; | ||
| 68 | #address-cells = <1>; | ||
| 69 | #size-cells = <0>; | ||
| 70 | edp_in_vopb: endpoint@0 { | ||
| 71 | reg = <0>; | ||
| 72 | remote-endpoint = <&vopb_out_edp>; | ||
| 73 | }; | ||
| 74 | edp_in_vopl: endpoint@1 { | ||
| 75 | reg = <1>; | ||
| 76 | remote-endpoint = <&vopl_out_edp>; | ||
| 77 | }; | ||
| 78 | }; | ||
| 79 | |||
| 80 | edp_out: port@1 { | ||
| 81 | reg = <1>; | ||
| 82 | #address-cells = <1>; | ||
| 83 | #size-cells = <0>; | ||
| 84 | edp_out_panel: endpoint { | ||
| 85 | reg = <0>; | ||
| 86 | remote-endpoint = <&panel_in_edp> | ||
| 87 | }; | ||
| 88 | }; | ||
| 89 | }; | ||
| 90 | }; | ||
| 91 | |||
| 92 | pinctrl { | ||
| 93 | edp { | ||
| 94 | edp_hpd: edp-hpd { | ||
| 95 | rockchip,pins = <7 11 RK_FUNC_2 &pcfg_pull_none>; | ||
| 96 | }; | ||
| 97 | }; | ||
| 98 | }; | ||
| @@ -1,94 +0,0 @@ | |||
| 1 | Rockchip specific extensions to the Synopsys Designware MIPI DSI | ||
| 2 | ================================ | ||
| 3 | |||
| 4 | Required properties: | ||
| 5 | - #address-cells: Should be <1>. | ||
| 6 | - #size-cells: Should be <0>. | ||
| 7 | - compatible: one of | ||
| 8 | "rockchip,px30-mipi-dsi", "snps,dw-mipi-dsi" | ||
| 9 | "rockchip,rk3288-mipi-dsi", "snps,dw-mipi-dsi" | ||
| 10 | "rockchip,rk3399-mipi-dsi", "snps,dw-mipi-dsi" | ||
| 11 | "rockchip,rk3568-mipi-dsi", "snps,dw-mipi-dsi" | ||
| 12 | - reg: Represent the physical address range of the controller. | ||
| 13 | - interrupts: Represent the controller's interrupt to the CPU(s). | ||
| 14 | - clocks, clock-names: Phandles to the controller's pll reference | ||
| 15 | clock(ref) when using an internal dphy and APB clock(pclk). | ||
| 16 | For RK3399, a phy config clock (phy_cfg) and a grf clock(grf) | ||
| 17 | are required. As described in [1]. | ||
| 18 | - rockchip,grf: this soc should set GRF regs to mux vopl/vopb. | ||
| 19 | - ports: contain a port node with endpoint definitions as defined in [2]. | ||
| 20 | For vopb,set the reg = <0> and set the reg = <1> for vopl. | ||
| 21 | - video port 0 for the VOP input, the remote endpoint maybe vopb or vopl | ||
| 22 | - video port 1 for either a panel or subsequent encoder | ||
| 23 | |||
| 24 | Optional properties: | ||
| 25 | - phys: from general PHY binding: the phandle for the PHY device. | ||
| 26 | - phy-names: Should be "dphy" if phys references an external phy. | ||
| 27 | - #phy-cells: Defined when used as ISP phy, should be 0. | ||
| 28 | - power-domains: a phandle to mipi dsi power domain node. | ||
| 29 | - resets: list of phandle + reset specifier pairs, as described in [3]. | ||
| 30 | - reset-names: string reset name, must be "apb". | ||
| 31 | |||
| 32 | [1] Documentation/devicetree/bindings/clock/clock-bindings.txt | ||
| 33 | [2] Documentation/devicetree/bindings/media/video-interfaces.txt | ||
| 34 | [3] Documentation/devicetree/bindings/reset/reset.txt | ||
| 35 | |||
| 36 | Example: | ||
| 37 | mipi_dsi: mipi@ff960000 { | ||
| 38 | #address-cells = <1>; | ||
| 39 | #size-cells = <0>; | ||
| 40 | compatible = "rockchip,rk3288-mipi-dsi", "snps,dw-mipi-dsi"; | ||
| 41 | reg = <0xff960000 0x4000>; | ||
| 42 | interrupts = <GIC_SPI 83 IRQ_TYPE_LEVEL_HIGH>; | ||
| 43 | clocks = <&cru SCLK_MIPI_24M>, <&cru PCLK_MIPI_DSI0>; | ||
| 44 | clock-names = "ref", "pclk"; | ||
| 45 | resets = <&cru SRST_MIPIDSI0>; | ||
| 46 | reset-names = "apb"; | ||
| 47 | rockchip,grf = <&grf>; | ||
| 48 | |||
| 49 | ports { | ||
| 50 | #address-cells = <1>; | ||
| 51 | #size-cells = <0>; | ||
| 52 | |||
| 53 | mipi_in: port@0 { | ||
| 54 | reg = <0>; | ||
| 55 | #address-cells = <1>; | ||
| 56 | #size-cells = <0>; | ||
| 57 | |||
| 58 | mipi_in_vopb: endpoint@0 { | ||
| 59 | reg = <0>; | ||
| 60 | remote-endpoint = <&vopb_out_mipi>; | ||
| 61 | }; | ||
| 62 | mipi_in_vopl: endpoint@1 { | ||
| 63 | reg = <1>; | ||
| 64 | remote-endpoint = <&vopl_out_mipi>; | ||
| 65 | }; | ||
| 66 | }; | ||
| 67 | |||
| 68 | mipi_out: port@1 { | ||
| 69 | reg = <1>; | ||
| 70 | #address-cells = <1>; | ||
| 71 | #size-cells = <0>; | ||
| 72 | |||
| 73 | mipi_out_panel: endpoint { | ||
| 74 | remote-endpoint = <&panel_in_mipi>; | ||
| 75 | }; | ||
| 76 | }; | ||
| 77 | }; | ||
| 78 | |||
| 79 | panel { | ||
| 80 | compatible ="boe,tv080wum-nl0"; | ||
| 81 | reg = <0>; | ||
| 82 | |||
| 83 | enable-gpios = <&gpio7 3 GPIO_ACTIVE_HIGH>; | ||
| 84 | pinctrl-names = "default"; | ||
| 85 | pinctrl-0 = <&lcd_en>; | ||
| 86 | backlight = <&backlight>; | ||
| 87 | |||
| 88 | port { | ||
| 89 | panel_in_mipi: endpoint { | ||
| 90 | remote-endpoint = <&mipi_out_panel>; | ||
| 91 | }; | ||
| 92 | }; | ||
| 93 | }; | ||
| 94 | }; | ||
| @@ -0,0 +1,103 @@ | |||
| 1 | # SPDX-License-Identifier: GPL-2.0 | ||
| 2 | %YAML 1.2 | ||
| 3 | --- | ||
| 4 | $id: http://devicetree.org/schemas/display/rockchip/rockchip,analogix-dp.yaml# | ||
| 5 | $schema: http://devicetree.org/meta-schemas/core.yaml# | ||
| 6 | |||
| 7 | title: Rockchip specific extensions to the Analogix Display Port | ||
| 8 | |||
| 9 | maintainers: | ||
| 10 | - Sandy Huang <hjc@rock-chips.com> | ||
| 11 | - Heiko Stuebner <heiko@sntech.de> | ||
| 12 | |||
| 13 | properties: | ||
| 14 | compatible: | ||
| 15 | enum: | ||
| 16 | - rockchip,rk3288-dp | ||
| 17 | - rockchip,rk3399-edp | ||
| 18 | |||
| 19 | clocks: | ||
| 20 | minItems: 2 | ||
| 21 | maxItems: 3 | ||
| 22 | |||
| 23 | clock-names: | ||
| 24 | minItems: 2 | ||
| 25 | items: | ||
| 26 | - const: dp | ||
| 27 | - const: pclk | ||
| 28 | - const: grf | ||
| 29 | |||
| 30 | power-domains: | ||
| 31 | maxItems: 1 | ||
| 32 | |||
| 33 | resets: | ||
| 34 | maxItems: 1 | ||
| 35 | |||
| 36 | reset-names: | ||
| 37 | const: dp | ||
| 38 | |||
| 39 | rockchip,grf: | ||
| 40 | $ref: /schemas/types.yaml#/definitions/phandle | ||
| 41 | description: | ||
| 42 | This SoC makes use of GRF regs. | ||
| 43 | |||
| 44 | required: | ||
| 45 | - compatible | ||
| 46 | - clocks | ||
| 47 | - clock-names | ||
| 48 | - resets | ||
| 49 | - reset-names | ||
| 50 | - rockchip,grf | ||
| 51 | |||
| 52 | allOf: | ||
| 53 | - $ref: /schemas/display/bridge/analogix,dp.yaml# | ||
| 54 | |||
| 55 | unevaluatedProperties: false | ||
| 56 | |||
| 57 | examples: | ||
| 58 | - | | ||
| 59 | #include <dt-bindings/clock/rk3288-cru.h> | ||
| 60 | #include <dt-bindings/interrupt-controller/arm-gic.h> | ||
| 61 | #include <dt-bindings/interrupt-controller/irq.h> | ||
| 62 | dp@ff970000 { | ||
| 63 | compatible = "rockchip,rk3288-dp"; | ||
| 64 | reg = <0xff970000 0x4000>; | ||
| 65 | interrupts = <GIC_SPI 98 IRQ_TYPE_LEVEL_HIGH>; | ||
| 66 | clocks = <&cru SCLK_EDP>, <&cru PCLK_EDP_CTRL>; | ||
| 67 | clock-names = "dp", "pclk"; | ||
| 68 | phys = <&dp_phy>; | ||
| 69 | phy-names = "dp"; | ||
| 70 | resets = <&cru 111>; | ||
| 71 | reset-names = "dp"; | ||
| 72 | rockchip,grf = <&grf>; | ||
| 73 | pinctrl-0 = <&edp_hpd>; | ||
| 74 | pinctrl-names = "default"; | ||
| 75 | |||
| 76 | ports { | ||
| 77 | #address-cells = <1>; | ||
| 78 | #size-cells = <0>; | ||
| 79 | |||
| 80 | edp_in: port@0 { | ||
| 81 | reg = <0>; | ||
| 82 | #address-cells = <1>; | ||
| 83 | #size-cells = <0>; | ||
| 84 | |||
| 85 | edp_in_vopb: endpoint@0 { | ||
| 86 | reg = <0>; | ||
| 87 | remote-endpoint = <&vopb_out_edp>; | ||
| 88 | }; | ||
| 89 | edp_in_vopl: endpoint@1 { | ||
| 90 | reg = <1>; | ||
| 91 | remote-endpoint = <&vopl_out_edp>; | ||
| 92 | }; | ||
| 93 | }; | ||
| 94 | |||
| 95 | edp_out: port@1 { | ||
| 96 | reg = <1>; | ||
| 97 | |||
| 98 | edp_out_panel: endpoint { | ||
| 99 | remote-endpoint = <&panel_in_edp>; | ||
| 100 | }; | ||
| 101 | }; | ||
| 102 | }; | ||
| 103 | }; | ||
| @@ -0,0 +1,166 @@ | |||
| 1 | # SPDX-License-Identifier: GPL-2.0 | ||
| 2 | %YAML 1.2 | ||
| 3 | --- | ||
| 4 | $id: http://devicetree.org/schemas/display/rockchip/rockchip,dw-mipi-dsi.yaml# | ||
| 5 | $schema: http://devicetree.org/meta-schemas/core.yaml# | ||
| 6 | |||
| 7 | title: Rockchip specific extensions to the Synopsys Designware MIPI DSI | ||
| 8 | |||
| 9 | maintainers: | ||
| 10 | - Sandy Huang <hjc@rock-chips.com> | ||
| 11 | - Heiko Stuebner <heiko@sntech.de> | ||
| 12 | |||
| 13 | properties: | ||
| 14 | compatible: | ||
| 15 | items: | ||
| 16 | - enum: | ||
| 17 | - rockchip,px30-mipi-dsi | ||
| 18 | - rockchip,rk3288-mipi-dsi | ||
| 19 | - rockchip,rk3399-mipi-dsi | ||
| 20 | - rockchip,rk3568-mipi-dsi | ||
| 21 | - const: snps,dw-mipi-dsi | ||
| 22 | |||
| 23 | interrupts: | ||
| 24 | maxItems: 1 | ||
| 25 | |||
| 26 | clocks: | ||
| 27 | minItems: 1 | ||
| 28 | maxItems: 4 | ||
| 29 | |||
| 30 | clock-names: | ||
| 31 | oneOf: | ||
| 32 | - minItems: 2 | ||
| 33 | items: | ||
| 34 | - const: ref | ||
| 35 | - const: pclk | ||
| 36 | - const: phy_cfg | ||
| 37 | - const: grf | ||
| 38 | - const: pclk | ||
| 39 | |||
| 40 | rockchip,grf: | ||
| 41 | $ref: /schemas/types.yaml#/definitions/phandle | ||
| 42 | description: | ||
| 43 | This SoC uses GRF regs to switch between vopl/vopb. | ||
| 44 | |||
| 45 | phys: | ||
| 46 | maxItems: 1 | ||
| 47 | |||
| 48 | phy-names: | ||
| 49 | const: dphy | ||
| 50 | |||
| 51 | "#phy-cells": | ||
| 52 | const: 0 | ||
| 53 | description: | ||
| 54 | Defined when in use as ISP phy. | ||
| 55 | |||
| 56 | power-domains: | ||
| 57 | maxItems: 1 | ||
| 58 | |||
| 59 | "#address-cells": | ||
| 60 | const: 1 | ||
| 61 | |||
| 62 | "#size-cells": | ||
| 63 | const: 0 | ||
| 64 | |||
| 65 | required: | ||
| 66 | - compatible | ||
| 67 | - clocks | ||
| 68 | - clock-names | ||
| 69 | - rockchip,grf | ||
| 70 | |||
| 71 | allOf: | ||
| 72 | - $ref: /schemas/display/bridge/snps,dw-mipi-dsi.yaml# | ||
| 73 | - if: | ||
| 74 | properties: | ||
| 75 | compatible: | ||
| 76 | contains: | ||
| 77 | enum: | ||
| 78 | - rockchip,px30-mipi-dsi | ||
| 79 | - rockchip,rk3568-mipi-dsi | ||
| 80 | |||
| 81 | then: | ||
| 82 | properties: | ||
| 83 | clocks: | ||
| 84 | maxItems: 1 | ||
| 85 | |||
| 86 | clock-names: | ||
| 87 | maxItems: 1 | ||
| 88 | |||
| 89 | required: | ||
| 90 | - phys | ||
| 91 | - phy-names | ||
| 92 | |||
| 93 | - if: | ||
| 94 | properties: | ||
| 95 | compatible: | ||
| 96 | contains: | ||
| 97 | const: rockchip,rk3288-mipi-dsi | ||
| 98 | |||
| 99 | then: | ||
| 100 | properties: | ||
| 101 | clocks: | ||
| 102 | maxItems: 2 | ||
| 103 | |||
| 104 | clock-names: | ||
| 105 | maxItems: 2 | ||
| 106 | |||
| 107 | - if: | ||
| 108 | properties: | ||
| 109 | compatible: | ||
| 110 | contains: | ||
| 111 | const: rockchip,rk3399-mipi-dsi | ||
| 112 | |||
| 113 | then: | ||
| 114 | properties: | ||
| 115 | clocks: | ||
| 116 | minItems: 4 | ||
| 117 | |||
| 118 | clock-names: | ||
| 119 | minItems: 4 | ||
| 120 | |||
| 121 | unevaluatedProperties: false | ||
| 122 | |||
| 123 | examples: | ||
| 124 | - | | ||
| 125 | #include <dt-bindings/clock/rk3288-cru.h> | ||
| 126 | #include <dt-bindings/interrupt-controller/arm-gic.h> | ||
| 127 | #include <dt-bindings/interrupt-controller/irq.h> | ||
| 128 | |||
| 129 | mipi_dsi: dsi@ff960000 { | ||
| 130 | compatible = "rockchip,rk3288-mipi-dsi", "snps,dw-mipi-dsi"; | ||
| 131 | reg = <0xff960000 0x4000>; | ||
| 132 | interrupts = <GIC_SPI 83 IRQ_TYPE_LEVEL_HIGH>; | ||
| 133 | clocks = <&cru SCLK_MIPIDSI_24M>, <&cru PCLK_MIPI_DSI0>; | ||
| 134 | clock-names = "ref", "pclk"; | ||
| 135 | resets = <&cru SRST_MIPIDSI0>; | ||
| 136 | reset-names = "apb"; | ||
| 137 | rockchip,grf = <&grf>; | ||
| 138 | |||
| 139 | ports { | ||
| 140 | #address-cells = <1>; | ||
| 141 | #size-cells = <0>; | ||
| 142 | |||
| 143 | mipi_in: port@0 { | ||
| 144 | reg = <0>; | ||
| 145 | #address-cells = <1>; | ||
| 146 | #size-cells = <0>; | ||
| 147 | |||
| 148 | mipi_in_vopb: endpoint@0 { | ||
| 149 | reg = <0>; | ||
| 150 | remote-endpoint = <&vopb_out_mipi>; | ||
| 151 | }; | ||
| 152 | mipi_in_vopl: endpoint@1 { | ||
| 153 | reg = <1>; | ||
| 154 | remote-endpoint = <&vopl_out_mipi>; | ||
| 155 | }; | ||
| 156 | }; | ||
| 157 | |||
| 158 | mipi_out: port@1 { | ||
| 159 | reg = <1>; | ||
| 160 | |||
| 161 | mipi_out_panel: endpoint { | ||
| 162 | remote-endpoint = <&panel_in_mipi>; | ||
| 163 | }; | ||
| 164 | }; | ||
| 165 | }; | ||
| 166 | }; | ||
| @@ -0,0 +1,170 @@ | |||
| 1 | # SPDX-License-Identifier: GPL-2.0 | ||
| 2 | %YAML 1.2 | ||
| 3 | --- | ||
| 4 | $id: http://devicetree.org/schemas/display/rockchip/rockchip,lvds.yaml# | ||
| 5 | $schema: http://devicetree.org/meta-schemas/core.yaml# | ||
| 6 | |||
| 7 | title: Rockchip low-voltage differential signal (LVDS) transmitter | ||
| 8 | |||
| 9 | maintainers: | ||
| 10 | - Sandy Huang <hjc@rock-chips.com> | ||
| 11 | - Heiko Stuebner <heiko@sntech.de> | ||
| 12 | |||
| 13 | properties: | ||
| 14 | compatible: | ||
| 15 | enum: | ||
| 16 | - rockchip,px30-lvds | ||
| 17 | - rockchip,rk3288-lvds | ||
| 18 | |||
| 19 | reg: | ||
| 20 | maxItems: 1 | ||
| 21 | |||
| 22 | clocks: | ||
| 23 | maxItems: 1 | ||
| 24 | |||
| 25 | clock-names: | ||
| 26 | const: pclk_lvds | ||
| 27 | |||
| 28 | avdd1v0-supply: | ||
| 29 | description: 1.0V analog power. | ||
| 30 | |||
| 31 | avdd1v8-supply: | ||
| 32 | description: 1.8V analog power. | ||
| 33 | |||
| 34 | avdd3v3-supply: | ||
| 35 | description: 3.3V analog power. | ||
| 36 | |||
| 37 | rockchip,grf: | ||
| 38 | $ref: /schemas/types.yaml#/definitions/phandle | ||
| 39 | description: Phandle to the general register files syscon. | ||
| 40 | |||
| 41 | rockchip,output: | ||
| 42 | $ref: /schemas/types.yaml#/definitions/string | ||
| 43 | enum: [rgb, lvds, duallvds] | ||
| 44 | description: This describes the output interface. | ||
| 45 | |||
| 46 | phys: | ||
| 47 | maxItems: 1 | ||
| 48 | |||
| 49 | phy-names: | ||
| 50 | const: dphy | ||
| 51 | |||
| 52 | pinctrl-names: | ||
| 53 | const: lcdc | ||
| 54 | |||
| 55 | pinctrl-0: true | ||
| 56 | |||
| 57 | power-domains: | ||
| 58 | maxItems: 1 | ||
| 59 | |||
| 60 | ports: | ||
| 61 | $ref: /schemas/graph.yaml#/properties/ports | ||
| 62 | |||
| 63 | properties: | ||
| 64 | port@0: | ||
| 65 | $ref: /schemas/graph.yaml#/properties/port | ||
| 66 | description: | ||
| 67 | Video port 0 for the VOP input. | ||
| 68 | The remote endpoint maybe vopb or vopl. | ||
| 69 | |||
| 70 | port@1: | ||
| 71 | $ref: /schemas/graph.yaml#/properties/port | ||
| 72 | description: | ||
| 73 | Video port 1 for either a panel or subsequent encoder. | ||
| 74 | |||
| 75 | required: | ||
| 76 | - port@0 | ||
| 77 | - port@1 | ||
| 78 | |||
| 79 | required: | ||
| 80 | - compatible | ||
| 81 | - rockchip,grf | ||
| 82 | - rockchip,output | ||
| 83 | - ports | ||
| 84 | |||
| 85 | allOf: | ||
| 86 | - if: | ||
| 87 | properties: | ||
| 88 | compatible: | ||
| 89 | contains: | ||
| 90 | const: rockchip,px30-lvds | ||
| 91 | |||
| 92 | then: | ||
| 93 | properties: | ||
| 94 | reg: false | ||
| 95 | clocks: false | ||
| 96 | clock-names: false | ||
| 97 | avdd1v0-supply: false | ||
| 98 | avdd1v8-supply: false | ||
| 99 | avdd3v3-supply: false | ||
| 100 | |||
| 101 | required: | ||
| 102 | - phys | ||
| 103 | - phy-names | ||
| 104 | |||
| 105 | - if: | ||
| 106 | properties: | ||
| 107 | compatible: | ||
| 108 | contains: | ||
| 109 | const: rockchip,rk3288-lvds | ||
| 110 | |||
| 111 | then: | ||
| 112 | properties: | ||
| 113 | phys: false | ||
| 114 | phy-names: false | ||
| 115 | |||
| 116 | required: | ||
| 117 | - reg | ||
| 118 | - clocks | ||
| 119 | - clock-names | ||
| 120 | - avdd1v0-supply | ||
| 121 | - avdd1v8-supply | ||
| 122 | - avdd3v3-supply | ||
| 123 | |||
| 124 | additionalProperties: false | ||
| 125 | |||
| 126 | examples: | ||
| 127 | - | | ||
| 128 | #include <dt-bindings/clock/rk3288-cru.h> | ||
| 129 | |||
| 130 | lvds: lvds@ff96c000 { | ||
| 131 | compatible = "rockchip,rk3288-lvds"; | ||
| 132 | reg = <0xff96c000 0x4000>; | ||
| 133 | clocks = <&cru PCLK_LVDS_PHY>; | ||
| 134 | clock-names = "pclk_lvds"; | ||
| 135 | avdd1v0-supply = <&vdd10_lcd>; | ||
| 136 | avdd1v8-supply = <&vcc18_lcd>; | ||
| 137 | avdd3v3-supply = <&vcca_33>; | ||
| 138 | pinctrl-names = "lcdc"; | ||
| 139 | pinctrl-0 = <&lcdc_ctl>; | ||
| 140 | rockchip,grf = <&grf>; | ||
| 141 | rockchip,output = "rgb"; | ||
| 142 | |||
| 143 | ports { | ||
| 144 | #address-cells = <1>; | ||
| 145 | #size-cells = <0>; | ||
| 146 | |||
| 147 | lvds_in: port@0 { | ||
| 148 | reg = <0>; | ||
| 149 | #address-cells = <1>; | ||
| 150 | #size-cells = <0>; | ||
| 151 | |||
| 152 | lvds_in_vopb: endpoint@0 { | ||
| 153 | reg = <0>; | ||
| 154 | remote-endpoint = <&vopb_out_lvds>; | ||
| 155 | }; | ||
| 156 | lvds_in_vopl: endpoint@1 { | ||
| 157 | reg = <1>; | ||
| 158 | remote-endpoint = <&vopl_out_lvds>; | ||
| 159 | }; | ||
| 160 | }; | ||
| 161 | |||
| 162 | lvds_out: port@1 { | ||
| 163 | reg = <1>; | ||
| 164 | |||
| 165 | lvds_out_panel: endpoint { | ||
| 166 | remote-endpoint = <&panel_in_lvds>; | ||
| 167 | }; | ||
| 168 | }; | ||
| 169 | }; | ||
| 170 | }; | ||
| @@ -1,92 +0,0 @@ | |||
| 1 | Rockchip RK3288 LVDS interface | ||
| 2 | ================================ | ||
| 3 | |||
| 4 | Required properties: | ||
| 5 | - compatible: matching the soc type, one of | ||
| 6 | - "rockchip,rk3288-lvds"; | ||
| 7 | - "rockchip,px30-lvds"; | ||
| 8 | |||
| 9 | - reg: physical base address of the controller and length | ||
| 10 | of memory mapped region. | ||
| 11 | - clocks: must include clock specifiers corresponding to entries in the | ||
| 12 | clock-names property. | ||
| 13 | - clock-names: must contain "pclk_lvds" | ||
| 14 | |||
| 15 | - avdd1v0-supply: regulator phandle for 1.0V analog power | ||
| 16 | - avdd1v8-supply: regulator phandle for 1.8V analog power | ||
| 17 | - avdd3v3-supply: regulator phandle for 3.3V analog power | ||
| 18 | |||
| 19 | - rockchip,grf: phandle to the general register files syscon | ||
| 20 | - rockchip,output: "rgb", "lvds" or "duallvds", This describes the output interface | ||
| 21 | |||
| 22 | - phys: LVDS/DSI DPHY (px30 only) | ||
| 23 | - phy-names: name of the PHY, must be "dphy" (px30 only) | ||
| 24 | |||
| 25 | Optional properties: | ||
| 26 | - pinctrl-names: must contain a "lcdc" entry. | ||
| 27 | - pinctrl-0: pin control group to be used for this controller. | ||
| 28 | |||
| 29 | Required nodes: | ||
| 30 | |||
| 31 | The lvds has two video ports as described by | ||
| 32 | Documentation/devicetree/bindings/media/video-interfaces.txt | ||
| 33 | Their connections are modeled using the OF graph bindings specified in | ||
| 34 | Documentation/devicetree/bindings/graph.txt. | ||
| 35 | |||
| 36 | - video port 0 for the VOP input, the remote endpoint maybe vopb or vopl | ||
| 37 | - video port 1 for either a panel or subsequent encoder | ||
| 38 | |||
| 39 | Example: | ||
| 40 | |||
| 41 | lvds_panel: lvds-panel { | ||
| 42 | compatible = "auo,b101ean01"; | ||
| 43 | enable-gpios = <&gpio7 21 GPIO_ACTIVE_HIGH>; | ||
| 44 | data-mapping = "jeida-24"; | ||
| 45 | |||
| 46 | ports { | ||
| 47 | panel_in_lvds: endpoint { | ||
| 48 | remote-endpoint = <&lvds_out_panel>; | ||
| 49 | }; | ||
| 50 | }; | ||
| 51 | }; | ||
| 52 | |||
| 53 | For Rockchip RK3288: | ||
| 54 | |||
| 55 | lvds: lvds@ff96c000 { | ||
| 56 | compatible = "rockchip,rk3288-lvds"; | ||
| 57 | rockchip,grf = <&grf>; | ||
| 58 | reg = <0xff96c000 0x4000>; | ||
| 59 | clocks = <&cru PCLK_LVDS_PHY>; | ||
| 60 | clock-names = "pclk_lvds"; | ||
| 61 | pinctrl-names = "lcdc"; | ||
| 62 | pinctrl-0 = <&lcdc_ctl>; | ||
| 63 | avdd1v0-supply = <&vdd10_lcd>; | ||
| 64 | avdd1v8-supply = <&vcc18_lcd>; | ||
| 65 | avdd3v3-supply = <&vcca_33>; | ||
| 66 | rockchip,output = "rgb"; | ||
| 67 | ports { | ||
| 68 | #address-cells = <1>; | ||
| 69 | #size-cells = <0>; | ||
| 70 | |||
| 71 | lvds_in: port@0 { | ||
| 72 | reg = <0>; | ||
| 73 | |||
| 74 | lvds_in_vopb: endpoint@0 { | ||
| 75 | reg = <0>; | ||
| 76 | remote-endpoint = <&vopb_out_lvds>; | ||
| 77 | }; | ||
| 78 | lvds_in_vopl: endpoint@1 { | ||
| 79 | reg = <1>; | ||
| 80 | remote-endpoint = <&vopl_out_lvds>; | ||
| 81 | }; | ||
| 82 | }; | ||
| 83 | |||
| 84 | lvds_out: port@1 { | ||
| 85 | reg = <1>; | ||
| 86 | |||
| 87 | lvds_out_panel: endpoint { | ||
| 88 | remote-endpoint = <&panel_in_lvds>; | ||
| 89 | }; | ||
| 90 | }; | ||
| 91 | }; | ||
| 92 | }; | ||
| @@ -26,6 +26,11 @@ description: |+ · 25 unmodified lines | |||
| 26 | over control to a driver for the real hardware. The bindings for the | 26 | over control to a driver for the real hardware. The bindings for the |
| 27 | hw nodes must specify which node is considered the primary node. | 27 | hw nodes must specify which node is considered the primary node. |
| 28 | 28 | ||
| 29 | If a panel node is given, then the driver uses this to configure the | ||
| 30 | physical width and height of the display. If no panel node is given, | ||
| 31 | then the driver uses the width and height properties of the simplefb | ||
| 32 | node to estimate it. | ||
| 33 | |||
| 29 | It is advised to add display# aliases to help the OS determine how | 34 | It is advised to add display# aliases to help the OS determine how |
| 30 | to number things. If display# aliases are used, then if the simplefb | 35 | to number things. If display# aliases are used, then if the simplefb |
| 31 | node contains a display property then the /aliases/display# path | 36 | node contains a display property then the /aliases/display# path |
| @@ -117,6 +122,10 @@ properties: · 85 unmodified lines | |||
| 117 | $ref: /schemas/types.yaml#/definitions/phandle | 122 | $ref: /schemas/types.yaml#/definitions/phandle |
| 118 | description: Primary display hardware node | 123 | description: Primary display hardware node |
| 119 | 124 | ||
| 125 | panel: | ||
| 126 | $ref: /schemas/types.yaml#/definitions/phandle | ||
| 127 | description: Display panel node | ||
| 128 | |||
| 120 | allwinner,pipeline: | 129 | allwinner,pipeline: |
| 121 | description: Pipeline used by the framebuffer on Allwinner SoCs | 130 | description: Pipeline used by the framebuffer on Allwinner SoCs |
| 122 | enum: | 131 | enum: |
| @@ -80,13 +80,17 @@ allOf: · 79 unmodified lines | |||
| 80 | properties: | 80 | properties: |
| 81 | compatible: | 81 | compatible: |
| 82 | contains: | 82 | contains: |
| 83 | const: rockchip,px30-grf | 83 | enum: |
| 84 | - rockchip,px30-grf | ||
| 84 | 85 | ||
| 85 | then: | 86 | then: |
| 86 | properties: | 87 | properties: |
| 87 | lvds: | 88 | lvds: |
| 88 | description: | 89 | type: object |
| 89 | Documentation/devicetree/bindings/display/rockchip/rockchip-lvds.txt | 90 | |
| 91 | $ref: /schemas/display/rockchip/rockchip,lvds.yaml# | ||
| 92 | |||
| 93 | unevaluatedProperties: false | ||
| 90 | 94 | ||
| 91 | - if: | 95 | - if: |
| 92 | properties: | 96 | properties: |
| @@ -7044,7 +7044,7 @@ F: Documentation/devicetree/bindings/display/xlnx/ · 7043 unmodified lines | |||
| 7044 | F: drivers/gpu/drm/xlnx/ | 7044 | F: drivers/gpu/drm/xlnx/ |
| 7045 | 7045 | ||
| 7046 | DRM PANEL DRIVERS | 7046 | DRM PANEL DRIVERS |
| 7047 | M: Thierry Reding <thierry.reding@gmail.com> | 7047 | M: Neil Armstrong <neil.armstrong@linaro.org> |
| 7048 | R: Sam Ravnborg <sam@ravnborg.org> | 7048 | R: Sam Ravnborg <sam@ravnborg.org> |
| 7049 | L: dri-devel@lists.freedesktop.org | 7049 | L: dri-devel@lists.freedesktop.org |
| 7050 | S: Maintained | 7050 | S: Maintained |
| @@ -237,8 +237,6 @@ int ivpu_rpm_get(struct ivpu_device *vdev) · 236 unmodified lines | |||
| 237 | { | 237 | { |
| 238 | int ret; | 238 | int ret; |
| 239 | 239 | ||
| 240 | ivpu_dbg(vdev, RPM, "rpm_get count %d\n", atomic_read(&vdev->drm.dev->power.usage_count)); | ||
| 241 | |||
| 242 | ret = pm_runtime_resume_and_get(vdev->drm.dev); | 240 | ret = pm_runtime_resume_and_get(vdev->drm.dev); |
| 243 | if (!drm_WARN_ON(&vdev->drm, ret < 0)) | 241 | if (!drm_WARN_ON(&vdev->drm, ret < 0)) |
| 244 | vdev->pm->suspend_reschedule_counter = PM_RESCHEDULE_LIMIT; | 242 | vdev->pm->suspend_reschedule_counter = PM_RESCHEDULE_LIMIT; |
| @@ -248,8 +246,6 @@ int ivpu_rpm_get(struct ivpu_device *vdev) · 3 unmodified lines | |||
| 248 | 246 | ||
| 249 | void ivpu_rpm_put(struct ivpu_device *vdev) | 247 | void ivpu_rpm_put(struct ivpu_device *vdev) |
| 250 | { | 248 | { |
| 251 | ivpu_dbg(vdev, RPM, "rpm_put count %d\n", atomic_read(&vdev->drm.dev->power.usage_count)); | ||
| 252 | |||
| 253 | pm_runtime_mark_last_busy(vdev->drm.dev); | 249 | pm_runtime_mark_last_busy(vdev->drm.dev); |
| 254 | pm_runtime_put_autosuspend(vdev->drm.dev); | 250 | pm_runtime_put_autosuspend(vdev->drm.dev); |
| 255 | } | 251 | } |
| @@ -314,16 +310,10 @@ void ivpu_pm_enable(struct ivpu_device *vdev) · 58 unmodified lines | |||
| 314 | pm_runtime_allow(dev); | 310 | pm_runtime_allow(dev); |
| 315 | pm_runtime_mark_last_busy(dev); | 311 | pm_runtime_mark_last_busy(dev); |
| 316 | pm_runtime_put_autosuspend(dev); | 312 | pm_runtime_put_autosuspend(dev); |
| 317 | |||
| 318 | ivpu_dbg(vdev, RPM, "Enable RPM count %d\n", atomic_read(&dev->power.usage_count)); | ||
| 319 | } | 313 | } |
| 320 | 314 | ||
| 321 | void ivpu_pm_disable(struct ivpu_device *vdev) | 315 | void ivpu_pm_disable(struct ivpu_device *vdev) |
| 322 | { | 316 | { |
| 323 | struct device *dev = vdev->drm.dev; | ||
| 324 | |||
| 325 | ivpu_dbg(vdev, RPM, "Disable RPM count %d\n", atomic_read(&dev->power.usage_count)); | ||
| 326 | |||
| 327 | pm_runtime_get_noresume(vdev->drm.dev); | 317 | pm_runtime_get_noresume(vdev->drm.dev); |
| 328 | pm_runtime_forbid(vdev->drm.dev); | 318 | pm_runtime_forbid(vdev->drm.dev); |
| 329 | } | 319 | } |
| @@ -828,7 +828,7 @@ static struct sg_table * __map_dma_buf(struct dma_buf_attachment *attach, · 827 unmodified lines | |||
| 828 | * - dma_buf_attach() | 828 | * - dma_buf_attach() |
| 829 | * - dma_buf_dynamic_attach() | 829 | * - dma_buf_dynamic_attach() |
| 830 | * - dma_buf_detach() | 830 | * - dma_buf_detach() |
| 831 | * - dma_buf_export( | 831 | * - dma_buf_export() |
| 832 | * - dma_buf_fd() | 832 | * - dma_buf_fd() |
| 833 | * - dma_buf_get() | 833 | * - dma_buf_get() |
| 834 | * - dma_buf_put() | 834 | * - dma_buf_put() |
| @@ -10,13 +10,13 @@ menuconfig DRM · 9 unmodified lines | |||
| 10 | depends on (AGP || AGP=n) && !EMULATED_CMPXCHG && HAS_DMA | 10 | depends on (AGP || AGP=n) && !EMULATED_CMPXCHG && HAS_DMA |
| 11 | select DRM_PANEL_ORIENTATION_QUIRKS | 11 | select DRM_PANEL_ORIENTATION_QUIRKS |
| 12 | select HDMI | 12 | select HDMI |
| 13 | select FB_CMDLINE | ||
| 14 | select I2C | 13 | select I2C |
| 15 | select DMA_SHARED_BUFFER | 14 | select DMA_SHARED_BUFFER |
| 16 | select SYNC_FILE | 15 | select SYNC_FILE |
| 17 | # gallium uses SYS_kcmp for os_same_file_description() to de-duplicate | 16 | # gallium uses SYS_kcmp for os_same_file_description() to de-duplicate |
| 18 | # device and dmabuf fd. Let's make sure that is available for our userspace. | 17 | # device and dmabuf fd. Let's make sure that is available for our userspace. |
| 19 | select KCMP | 18 | select KCMP |
| 19 | select VIDEO_CMDLINE | ||
| 20 | select VIDEO_NOMODESET | 20 | select VIDEO_NOMODESET |
| 21 | help | 21 | help |
| 22 | Kernel-level support for the Direct Rendering Infrastructure (DRI) | 22 | Kernel-level support for the Direct Rendering Infrastructure (DRI) |
| @@ -232,6 +232,10 @@ config DRM_GEM_SHMEM_HELPER · 209 unmodified lines | |||
| 232 | help | 232 | help |
| 233 | Choose this if you need the GEM shmem helper functions | 233 | Choose this if you need the GEM shmem helper functions |
| 234 | 234 | ||
| 235 | config DRM_SUBALLOC_HELPER | ||
| 236 | tristate | ||
| 237 | depends on DRM | ||
| 238 | |||
| 235 | config DRM_SCHED | 239 | config DRM_SCHED |
| 236 | tristate | 240 | tristate |
| 237 | depends on DRM | 241 | depends on DRM |
| @@ -88,6 +88,9 @@ obj-$(CONFIG_DRM_GEM_DMA_HELPER) += drm_dma_helper.o · 87 unmodified lines | |||
| 88 | drm_shmem_helper-y := drm_gem_shmem_helper.o | 88 | drm_shmem_helper-y := drm_gem_shmem_helper.o |
| 89 | obj-$(CONFIG_DRM_GEM_SHMEM_HELPER) += drm_shmem_helper.o | 89 | obj-$(CONFIG_DRM_GEM_SHMEM_HELPER) += drm_shmem_helper.o |
| 90 | 90 | ||
| 91 | drm_suballoc_helper-y := drm_suballoc.o | ||
| 92 | obj-$(CONFIG_DRM_SUBALLOC_HELPER) += drm_suballoc_helper.o | ||
| 93 | |||
| 91 | drm_vram_helper-y := drm_gem_vram_helper.o | 94 | drm_vram_helper-y := drm_gem_vram_helper.o |
| 92 | obj-$(CONFIG_DRM_VRAM_HELPER) += drm_vram_helper.o | 95 | obj-$(CONFIG_DRM_VRAM_HELPER) += drm_vram_helper.o |
| 93 | 96 | ||
| @@ -19,6 +19,7 @@ config DRM_AMDGPU · 18 unmodified lines | |||
| 19 | select BACKLIGHT_CLASS_DEVICE | 19 | select BACKLIGHT_CLASS_DEVICE |
| 20 | select INTERVAL_TREE | 20 | select INTERVAL_TREE |
| 21 | select DRM_BUDDY | 21 | select DRM_BUDDY |
| 22 | select DRM_SUBALLOC_HELPER | ||
| 22 | # amdgpu depends on ACPI_VIDEO when ACPI is enabled, for select to work | 23 | # amdgpu depends on ACPI_VIDEO when ACPI is enabled, for select to work |
| 23 | # ACPI_VIDEO's dependencies must also be selected. | 24 | # ACPI_VIDEO's dependencies must also be selected. |
| 24 | select INPUT if ACPI | 25 | select INPUT if ACPI |
| @@ -424,29 +424,11 @@ struct amdgpu_clock { · 423 unmodified lines | |||
| 424 | * alignment). | 424 | * alignment). |
| 425 | */ | 425 | */ |
| 426 | 426 | ||
| 427 | #define AMDGPU_SA_NUM_FENCE_LISTS 32 | ||
| 428 | |||
| 429 | struct amdgpu_sa_manager { | 427 | struct amdgpu_sa_manager { |
| 430 | wait_queue_head_t wq; | 428 | struct drm_suballoc_manager base; |
| 431 | struct amdgpu_bo *bo; | 429 | struct amdgpu_bo *bo; |
| 432 | struct list_head *hole; | 430 | uint64_t gpu_addr; |
| 433 | struct list_head flist[AMDGPU_SA_NUM_FENCE_LISTS]; | 431 | void *cpu_ptr; |
| 434 | struct list_head olist; | ||
| 435 | unsigned size; | ||
| 436 | uint64_t gpu_addr; | ||
| 437 | void *cpu_ptr; | ||
| 438 | uint32_t domain; | ||
| 439 | uint32_t align; | ||
| 440 | }; | ||
| 441 | |||
| 442 | /* sub-allocation buffer */ | ||
| 443 | struct amdgpu_sa_bo { | ||
| 444 | struct list_head olist; | ||
| 445 | struct list_head flist; | ||
| 446 | struct amdgpu_sa_manager *manager; | ||
| 447 | unsigned soffset; | ||
| 448 | unsigned eoffset; | ||
| 449 | struct dma_fence *fence; | ||
| 450 | }; | 432 | }; |
| 451 | 433 | ||
| 452 | int amdgpu_fence_slab_init(void); | 434 | int amdgpu_fence_slab_init(void); |
| @@ -69,7 +69,7 @@ int amdgpu_ib_get(struct amdgpu_device *adev, struct amdgpu_vm *vm, · 68 unmodified lines | |||
| 69 | 69 | ||
| 70 | if (size) { | 70 | if (size) { |
| 71 | r = amdgpu_sa_bo_new(&adev->ib_pools[pool_type], | 71 | r = amdgpu_sa_bo_new(&adev->ib_pools[pool_type], |
| 72 | &ib->sa_bo, size, 256); | 72 | &ib->sa_bo, size); |
| 73 | if (r) { | 73 | if (r) { |
| 74 | dev_err(adev->dev, "failed to get a new IB (%d)\n", r); | 74 | dev_err(adev->dev, "failed to get a new IB (%d)\n", r); |
| 75 | return r; | 75 | return r; |
| @@ -309,8 +309,7 @@ int amdgpu_ib_pool_init(struct amdgpu_device *adev) · 233 unmodified lines | |||
| 309 | 309 | ||
| 310 | for (i = 0; i < AMDGPU_IB_POOL_MAX; i++) { | 310 | for (i = 0; i < AMDGPU_IB_POOL_MAX; i++) { |
| 311 | r = amdgpu_sa_bo_manager_init(adev, &adev->ib_pools[i], | 311 | r = amdgpu_sa_bo_manager_init(adev, &adev->ib_pools[i], |
| 312 | AMDGPU_IB_POOL_SIZE, | 312 | AMDGPU_IB_POOL_SIZE, 256, |
| 313 | AMDGPU_GPU_PAGE_SIZE, | ||
| 314 | AMDGPU_GEM_DOMAIN_GTT); | 313 | AMDGPU_GEM_DOMAIN_GTT); |
| 315 | if (r) | 314 | if (r) |
| 316 | goto error; | 315 | goto error; |
| @@ -600,7 +600,7 @@ int amdgpu_bo_create(struct amdgpu_device *adev, · 599 unmodified lines | |||
| 600 | 600 | ||
| 601 | if (!amdgpu_gmc_vram_full_visible(&adev->gmc) && | 601 | if (!amdgpu_gmc_vram_full_visible(&adev->gmc) && |
| 602 | bo->tbo.resource->mem_type == TTM_PL_VRAM && | 602 | bo->tbo.resource->mem_type == TTM_PL_VRAM && |
| 603 | bo->tbo.resource->start < adev->gmc.visible_vram_size >> PAGE_SHIFT) | 603 | amdgpu_bo_in_cpu_visible_vram(bo)) |
| 604 | amdgpu_cs_report_moved_bytes(adev, ctx.bytes_moved, | 604 | amdgpu_cs_report_moved_bytes(adev, ctx.bytes_moved, |
| 605 | ctx.bytes_moved); | 605 | ctx.bytes_moved); |
| 606 | else | 606 | else |
| @@ -1346,7 +1346,6 @@ vm_fault_t amdgpu_bo_fault_reserve_notify(struct ttm_buffer_object *bo) · 739 unmodified lines | |||
| 1346 | struct amdgpu_device *adev = amdgpu_ttm_adev(bo->bdev); | 1346 | struct amdgpu_device *adev = amdgpu_ttm_adev(bo->bdev); |
| 1347 | struct ttm_operation_ctx ctx = { false, false }; | 1347 | struct ttm_operation_ctx ctx = { false, false }; |
| 1348 | struct amdgpu_bo *abo = ttm_to_amdgpu_bo(bo); | 1348 | struct amdgpu_bo *abo = ttm_to_amdgpu_bo(bo); |
| 1349 | unsigned long offset; | ||
| 1350 | int r; | 1349 | int r; |
| 1351 | 1350 | ||
| 1352 | /* Remember that this BO was accessed by the CPU */ | 1351 | /* Remember that this BO was accessed by the CPU */ |
| @@ -1355,8 +1354,7 @@ vm_fault_t amdgpu_bo_fault_reserve_notify(struct ttm_buffer_object *bo) · 2 unmodified lines | |||
| 1355 | if (bo->resource->mem_type != TTM_PL_VRAM) | 1354 | if (bo->resource->mem_type != TTM_PL_VRAM) |
| 1356 | return 0; | 1355 | return 0; |
| 1357 | 1356 | ||
| 1358 | offset = bo->resource->start << PAGE_SHIFT; | 1357 | if (amdgpu_bo_in_cpu_visible_vram(abo)) |
| 1359 | if ((offset + bo->base.size) <= adev->gmc.visible_vram_size) | ||
| 1360 | return 0; | 1358 | return 0; |
| 1361 | 1359 | ||
| 1362 | /* Can't move a pinned BO to visible VRAM */ | 1360 | /* Can't move a pinned BO to visible VRAM */ |
| @@ -1378,10 +1376,9 @@ vm_fault_t amdgpu_bo_fault_reserve_notify(struct ttm_buffer_object *bo) · 15 unmodified lines | |||
| 1378 | else if (unlikely(r)) | 1376 | else if (unlikely(r)) |
| 1379 | return VM_FAULT_SIGBUS; | 1377 | return VM_FAULT_SIGBUS; |
| 1380 | 1378 | ||
| 1381 | offset = bo->resource->start << PAGE_SHIFT; | ||
| 1382 | /* this should never happen */ | 1379 | /* this should never happen */ |
| 1383 | if (bo->resource->mem_type == TTM_PL_VRAM && | 1380 | if (bo->resource->mem_type == TTM_PL_VRAM && |
| 1384 | (offset + bo->base.size) > adev->gmc.visible_vram_size) | 1381 | !amdgpu_bo_in_cpu_visible_vram(abo)) |
| 1385 | return VM_FAULT_SIGBUS; | 1382 | return VM_FAULT_SIGBUS; |
| 1386 | 1383 | ||
| 1387 | ttm_bo_move_to_lru_tail_unlocked(bo); | 1384 | ttm_bo_move_to_lru_tail_unlocked(bo); |
| @@ -336,15 +336,22 @@ uint32_t amdgpu_bo_get_preferred_domain(struct amdgpu_device *adev, · 335 unmodified lines | |||
| 336 | /* | 336 | /* |
| 337 | * sub allocation | 337 | * sub allocation |
| 338 | */ | 338 | */ |
| 339 | static inline struct amdgpu_sa_manager * | ||
| 340 | to_amdgpu_sa_manager(struct drm_suballoc_manager *manager) | ||
| 341 | { | ||
| 342 | return container_of(manager, struct amdgpu_sa_manager, base); | ||
| 343 | } | ||
| 339 | 344 | ||
| 340 | static inline uint64_t amdgpu_sa_bo_gpu_addr(struct amdgpu_sa_bo *sa_bo) | 345 | static inline uint64_t amdgpu_sa_bo_gpu_addr(struct drm_suballoc *sa_bo) |
| 341 | { | 346 | { |
| 342 | return sa_bo->manager->gpu_addr + sa_bo->soffset; | 347 | return to_amdgpu_sa_manager(sa_bo->manager)->gpu_addr + |
| 348 | drm_suballoc_soffset(sa_bo); | ||
| 343 | } | 349 | } |
| 344 | 350 | ||
| 345 | static inline void * amdgpu_sa_bo_cpu_addr(struct amdgpu_sa_bo *sa_bo) | 351 | static inline void *amdgpu_sa_bo_cpu_addr(struct drm_suballoc *sa_bo) |
| 346 | { | 352 | { |
| 347 | return sa_bo->manager->cpu_ptr + sa_bo->soffset; | 353 | return to_amdgpu_sa_manager(sa_bo->manager)->cpu_ptr + |
| 354 | drm_suballoc_soffset(sa_bo); | ||
| 348 | } | 355 | } |
| 349 | 356 | ||
| 350 | int amdgpu_sa_bo_manager_init(struct amdgpu_device *adev, | 357 | int amdgpu_sa_bo_manager_init(struct amdgpu_device *adev, |
| @@ -355,11 +362,11 @@ void amdgpu_sa_bo_manager_fini(struct amdgpu_device *adev, · 4 unmodified lines | |||
| 355 | int amdgpu_sa_bo_manager_start(struct amdgpu_device *adev, | 362 | int amdgpu_sa_bo_manager_start(struct amdgpu_device *adev, |
| 356 | struct amdgpu_sa_manager *sa_manager); | 363 | struct amdgpu_sa_manager *sa_manager); |
| 357 | int amdgpu_sa_bo_new(struct amdgpu_sa_manager *sa_manager, | 364 | int amdgpu_sa_bo_new(struct amdgpu_sa_manager *sa_manager, |
| 358 | struct amdgpu_sa_bo **sa_bo, | 365 | struct drm_suballoc **sa_bo, |
| 359 | unsigned size, unsigned align); | 366 | unsigned int size); |
| 360 | void amdgpu_sa_bo_free(struct amdgpu_device *adev, | 367 | void amdgpu_sa_bo_free(struct amdgpu_device *adev, |
| 361 | struct amdgpu_sa_bo **sa_bo, | 368 | struct drm_suballoc **sa_bo, |
| 362 | struct dma_fence *fence); | 369 | struct dma_fence *fence); |
| 363 | #if defined(CONFIG_DEBUG_FS) | 370 | #if defined(CONFIG_DEBUG_FS) |
| 364 | void amdgpu_sa_bo_dump_debug_info(struct amdgpu_sa_manager *sa_manager, | 371 | void amdgpu_sa_bo_dump_debug_info(struct amdgpu_sa_manager *sa_manager, |
| 365 | struct seq_file *m); | 372 | struct seq_file *m); |
| @@ -27,6 +27,7 @@ · 26 unmodified lines | |||
| 27 | #include <drm/amdgpu_drm.h> | 27 | #include <drm/amdgpu_drm.h> |
| 28 | #include <drm/gpu_scheduler.h> | 28 | #include <drm/gpu_scheduler.h> |
| 29 | #include <drm/drm_print.h> | 29 | #include <drm/drm_print.h> |
| 30 | #include <drm/drm_suballoc.h> | ||
| 30 | 31 | ||
| 31 | struct amdgpu_device; | 32 | struct amdgpu_device; |
| 32 | struct amdgpu_ring; | 33 | struct amdgpu_ring; |
| @@ -92,7 +93,7 @@ enum amdgpu_ib_pool_type { · 59 unmodified lines | |||
| 92 | }; | 93 | }; |
| 93 | 94 | ||
| 94 | struct amdgpu_ib { | 95 | struct amdgpu_ib { |
| 95 | struct amdgpu_sa_bo *sa_bo; | 96 | struct drm_suballoc *sa_bo; |
| 96 | uint32_t length_dw; | 97 | uint32_t length_dw; |
| 97 | uint64_t gpu_addr; | 98 | uint64_t gpu_addr; |
| 98 | uint32_t *ptr; | 99 | uint32_t *ptr; |
| @@ -44,327 +44,63 @@ · 43 unmodified lines | |||
| 44 | 44 | ||
| 45 | #include "amdgpu.h" | 45 | #include "amdgpu.h" |
| 46 | 46 | ||
| 47 | static void amdgpu_sa_bo_remove_locked(struct amdgpu_sa_bo *sa_bo); | ||
| 48 | static void amdgpu_sa_bo_try_free(struct amdgpu_sa_manager *sa_manager); | ||
| 49 | |||
| 50 | int amdgpu_sa_bo_manager_init(struct amdgpu_device *adev, | 47 | int amdgpu_sa_bo_manager_init(struct amdgpu_device *adev, |
| 51 | struct amdgpu_sa_manager *sa_manager, | 48 | struct amdgpu_sa_manager *sa_manager, |
| 52 | unsigned size, u32 align, u32 domain) | 49 | unsigned int size, u32 suballoc_align, u32 domain) |
| 53 | { | 50 | { |
| 54 | int i, r; | 51 | int r; |
| 55 | |||
| 56 | init_waitqueue_head(&sa_manager->wq); | ||
| 57 | sa_manager->bo = NULL; | ||
| 58 | sa_manager->size = size; | ||
| 59 | sa_manager->domain = domain; | ||
| 60 | sa_manager->align = align; | ||
| 61 | sa_manager->hole = &sa_manager->olist; | ||
| 62 | INIT_LIST_HEAD(&sa_manager->olist); | ||
| 63 | for (i = 0; i < AMDGPU_SA_NUM_FENCE_LISTS; ++i) | ||
| 64 | INIT_LIST_HEAD(&sa_manager->flist[i]); | ||
| 65 | 52 | ||
| 66 | r = amdgpu_bo_create_kernel(adev, size, align, domain, &sa_manager->bo, | 53 | r = amdgpu_bo_create_kernel(adev, size, AMDGPU_GPU_PAGE_SIZE, domain, |
| 67 | &sa_manager->gpu_addr, &sa_manager->cpu_ptr); | 54 | &sa_manager->bo, &sa_manager->gpu_addr, |
| 55 | &sa_manager->cpu_ptr); | ||
| 68 | if (r) { | 56 | if (r) { |
| 69 | dev_err(adev->dev, "(%d) failed to allocate bo for manager\n", r); | 57 | dev_err(adev->dev, "(%d) failed to allocate bo for manager\n", r); |
| 70 | return r; | 58 | return r; |
| 71 | } | 59 | } |
| 72 | 60 | ||
| 73 | memset(sa_manager->cpu_ptr, 0, sa_manager->size); | 61 | memset(sa_manager->cpu_ptr, 0, size); |
| 62 | drm_suballoc_manager_init(&sa_manager->base, size, suballoc_align); | ||
| 74 | return r; | 63 | return r; |
| 75 | } | 64 | } |
| 76 | 65 | ||
| 77 | void amdgpu_sa_bo_manager_fini(struct amdgpu_device *adev, | 66 | void amdgpu_sa_bo_manager_fini(struct amdgpu_device *adev, |
| 78 | struct amdgpu_sa_manager *sa_manager) | 67 | struct amdgpu_sa_manager *sa_manager) |
| 79 | { | 68 | { |
| 80 | struct amdgpu_sa_bo *sa_bo, *tmp; | ||
| 81 | |||
| 82 | if (sa_manager->bo == NULL) { | 69 | if (sa_manager->bo == NULL) { |
| 83 | dev_err(adev->dev, "no bo for sa manager\n"); | 70 | dev_err(adev->dev, "no bo for sa manager\n"); |
| 84 | return; | 71 | return; |
| 85 | } | 72 | } |
| 86 | 73 | ||
| 87 | if (!list_empty(&sa_manager->olist)) { | 74 | drm_suballoc_manager_fini(&sa_manager->base); |
| 88 | sa_manager->hole = &sa_manager->olist, | ||
| 89 | amdgpu_sa_bo_try_free(sa_manager); | ||
| 90 | if (!list_empty(&sa_manager->olist)) { | ||
| 91 | dev_err(adev->dev, "sa_manager is not empty, clearing anyway\n"); | ||
| 92 | } | ||
| 93 | } | ||
| 94 | list_for_each_entry_safe(sa_bo, tmp, &sa_manager->olist, olist) { | ||
| 95 | amdgpu_sa_bo_remove_locked(sa_bo); | ||
| 96 | } | ||
| 97 | 75 | ||
| 98 | amdgpu_bo_free_kernel(&sa_manager->bo, &sa_manager->gpu_addr, &sa_manager->cpu_ptr); | 76 | amdgpu_bo_free_kernel(&sa_manager->bo, &sa_manager->gpu_addr, &sa_manager->cpu_ptr); |
| 99 | sa_manager->size = 0; | ||
| 100 | } | 77 | } |
| 101 | 78 | ||
| 102 | static void amdgpu_sa_bo_remove_locked(struct amdgpu_sa_bo *sa_bo) | 79 | int amdgpu_sa_bo_new(struct amdgpu_sa_manager *sa_manager, |
| 103 | { | 80 | struct drm_suballoc **sa_bo, |
| 104 | struct amdgpu_sa_manager *sa_manager = sa_bo->manager; | 81 | unsigned int size) |
| 105 | if (sa_manager->hole == &sa_bo->olist) { | ||
| 106 | sa_manager->hole = sa_bo->olist.prev; | ||
| 107 | } | ||
| 108 | list_del_init(&sa_bo->olist); | ||
| 109 | list_del_init(&sa_bo->flist); | ||
| 110 | dma_fence_put(sa_bo->fence); | ||
| 111 | kfree(sa_bo); | ||
| 112 | } | ||
| 113 | |||
| 114 | static void amdgpu_sa_bo_try_free(struct amdgpu_sa_manager *sa_manager) | ||
| 115 | { | 82 | { |
| 116 | struct amdgpu_sa_bo *sa_bo, *tmp; | 83 | struct drm_suballoc *sa = drm_suballoc_new(&sa_manager->base, size, |
| 84 | GFP_KERNEL, true, 0); | ||
| 117 | 85 | ||
| 118 | if (sa_manager->hole->next == &sa_manager->olist) | 86 | if (IS_ERR(sa)) { |
| 119 | return; | 87 | *sa_bo = NULL; |
| 120 | 88 | ||
| 121 | sa_bo = list_entry(sa_manager->hole->next, struct amdgpu_sa_bo, olist); | 89 | return PTR_ERR(sa); |
| 122 | list_for_each_entry_safe_from(sa_bo, tmp, &sa_manager->olist, olist) { | ||
| 123 | if (sa_bo->fence == NULL || | ||
| 124 | !dma_fence_is_signaled(sa_bo->fence)) { | ||
| 125 | return; | ||
| 126 | } | ||
| 127 | amdgpu_sa_bo_remove_locked(sa_bo); | ||
| 128 | } | 90 | } |
| 129 | } | ||
| 130 | 91 | ||
| 131 | static inline unsigned amdgpu_sa_bo_hole_soffset(struct amdgpu_sa_manager *sa_manager) | 92 | *sa_bo = sa; |
| 132 | { | ||
| 133 | struct list_head *hole = sa_manager->hole; | ||
| 134 | |||
| 135 | if (hole != &sa_manager->olist) { | ||
| 136 | return list_entry(hole, struct amdgpu_sa_bo, olist)->eoffset; | ||
| 137 | } | ||
| 138 | return 0; | 93 | return 0; |
| 139 | } | 94 | } |
| 140 | 95 | ||
| 141 | static inline unsigned amdgpu_sa_bo_hole_eoffset(struct amdgpu_sa_manager *sa_manager) | 96 | void amdgpu_sa_bo_free(struct amdgpu_device *adev, struct drm_suballoc **sa_bo, |
| 142 | { | ||
| 143 | struct list_head *hole = sa_manager->hole; | ||
| 144 | |||
| 145 | if (hole->next != &sa_manager->olist) { | ||
| 146 | return list_entry(hole->next, struct amdgpu_sa_bo, olist)->soffset; | ||
| 147 | } | ||
| 148 | return sa_manager->size; | ||
| 149 | } | ||
| 150 | |||
| 151 | static bool amdgpu_sa_bo_try_alloc(struct amdgpu_sa_manager *sa_manager, | ||
| 152 | struct amdgpu_sa_bo *sa_bo, | ||
| 153 | unsigned size, unsigned align) | ||
| 154 | { | ||
| 155 | unsigned soffset, eoffset, wasted; | ||
| 156 | |||
| 157 | soffset = amdgpu_sa_bo_hole_soffset(sa_manager); | ||
| 158 | eoffset = amdgpu_sa_bo_hole_eoffset(sa_manager); | ||
| 159 | wasted = (align - (soffset % align)) % align; | ||
| 160 | |||
| 161 | if ((eoffset - soffset) >= (size + wasted)) { | ||
| 162 | soffset += wasted; | ||
| 163 | |||
| 164 | sa_bo->manager = sa_manager; | ||
| 165 | sa_bo->soffset = soffset; | ||
| 166 | sa_bo->eoffset = soffset + size; | ||
| 167 | list_add(&sa_bo->olist, sa_manager->hole); | ||
| 168 | INIT_LIST_HEAD(&sa_bo->flist); | ||
| 169 | sa_manager->hole = &sa_bo->olist; | ||
| 170 | return true; | ||
| 171 | } | ||
| 172 | return false; | ||
| 173 | } | ||
| 174 | |||
| 175 | /** | ||
| 176 | * amdgpu_sa_event - Check if we can stop waiting | ||
| 177 | * | ||
| 178 | * @sa_manager: pointer to the sa_manager | ||
| 179 | * @size: number of bytes we want to allocate | ||
| 180 | * @align: alignment we need to match | ||
| 181 | * | ||
| 182 | * Check if either there is a fence we can wait for or | ||
| 183 | * enough free memory to satisfy the allocation directly | ||
| 184 | */ | ||
| 185 | static bool amdgpu_sa_event(struct amdgpu_sa_manager *sa_manager, | ||
| 186 | unsigned size, unsigned align) | ||
| 187 | { | ||
| 188 | unsigned soffset, eoffset, wasted; | ||
| 189 | int i; | ||
| 190 | |||
| 191 | for (i = 0; i < AMDGPU_SA_NUM_FENCE_LISTS; ++i) | ||
| 192 | if (!list_empty(&sa_manager->flist[i])) | ||
| 193 | return true; | ||
| 194 | |||
| 195 | soffset = amdgpu_sa_bo_hole_soffset(sa_manager); | ||
| 196 | eoffset = amdgpu_sa_bo_hole_eoffset(sa_manager); | ||
| 197 | wasted = (align - (soffset % align)) % align; | ||
| 198 | |||
| 199 | if ((eoffset - soffset) >= (size + wasted)) { | ||
| 200 | return true; | ||
| 201 | } | ||
| 202 | |||
| 203 | return false; | ||
| 204 | } | ||
| 205 | |||
| 206 | static bool amdgpu_sa_bo_next_hole(struct amdgpu_sa_manager *sa_manager, | ||
| 207 | struct dma_fence **fences, | ||
| 208 | unsigned *tries) | ||
| 209 | { | ||
| 210 | struct amdgpu_sa_bo *best_bo = NULL; | ||
| 211 | unsigned i, soffset, best, tmp; | ||
| 212 | |||
| 213 | /* if hole points to the end of the buffer */ | ||
| 214 | if (sa_manager->hole->next == &sa_manager->olist) { | ||
| 215 | /* try again with its beginning */ | ||
| 216 | sa_manager->hole = &sa_manager->olist; | ||
| 217 | return true; | ||
| 218 | } | ||
| 219 | |||
| 220 | soffset = amdgpu_sa_bo_hole_soffset(sa_manager); | ||
| 221 | /* to handle wrap around we add sa_manager->size */ | ||
| 222 | best = sa_manager->size * 2; | ||
| 223 | /* go over all fence list and try to find the closest sa_bo | ||
| 224 | * of the current last | ||
| 225 | */ | ||
| 226 | for (i = 0; i < AMDGPU_SA_NUM_FENCE_LISTS; ++i) { | ||
| 227 | struct amdgpu_sa_bo *sa_bo; | ||
| 228 | |||
| 229 | fences[i] = NULL; | ||
| 230 | |||
| 231 | if (list_empty(&sa_manager->flist[i])) | ||
| 232 | continue; | ||
| 233 | |||
| 234 | sa_bo = list_first_entry(&sa_manager->flist[i], | ||
| 235 | struct amdgpu_sa_bo, flist); | ||
| 236 | |||
| 237 | if (!dma_fence_is_signaled(sa_bo->fence)) { | ||
| 238 | fences[i] = sa_bo->fence; | ||
| 239 | continue; | ||
| 240 | } | ||
| 241 | |||
| 242 | /* limit the number of tries each ring gets */ | ||
| 243 | if (tries[i] > 2) { | ||
| 244 | continue; | ||
| 245 | } | ||
| 246 | |||
| 247 | tmp = sa_bo->soffset; | ||
| 248 | if (tmp < soffset) { | ||
| 249 | /* wrap around, pretend it's after */ | ||
| 250 | tmp += sa_manager->size; | ||
| 251 | } | ||
| 252 | tmp -= soffset; | ||
| 253 | if (tmp < best) { | ||
| 254 | /* this sa bo is the closest one */ | ||
| 255 | best = tmp; | ||
| 256 | best_bo = sa_bo; | ||
| 257 | } | ||
| 258 | } | ||
| 259 | |||
| 260 | if (best_bo) { | ||
| 261 | uint32_t idx = best_bo->fence->context; | ||
| 262 | |||
| 263 | idx %= AMDGPU_SA_NUM_FENCE_LISTS; | ||
| 264 | ++tries[idx]; | ||
| 265 | sa_manager->hole = best_bo->olist.prev; | ||
| 266 | |||
| 267 | /* we knew that this one is signaled, | ||
| 268 | so it's save to remote it */ | ||
| 269 | amdgpu_sa_bo_remove_locked(best_bo); | ||
| 270 | return true; | ||
| 271 | } | ||
| 272 | return false; | ||
| 273 | } | ||
| 274 | |||
| 275 | int amdgpu_sa_bo_new(struct amdgpu_sa_manager *sa_manager, | ||
| 276 | struct amdgpu_sa_bo **sa_bo, | ||
| 277 | unsigned size, unsigned align) | ||
| 278 | { | ||
| 279 | struct dma_fence *fences[AMDGPU_SA_NUM_FENCE_LISTS]; | ||
| 280 | unsigned tries[AMDGPU_SA_NUM_FENCE_LISTS]; | ||
| 281 | unsigned count; | ||
| 282 | int i, r; | ||
| 283 | signed long t; | ||
| 284 | |||
| 285 | if (WARN_ON_ONCE(align > sa_manager->align)) | ||
| 286 | return -EINVAL; | ||
| 287 | |||
| 288 | if (WARN_ON_ONCE(size > sa_manager->size)) | ||
| 289 | return -EINVAL; | ||
| 290 | |||
| 291 | *sa_bo = kmalloc(sizeof(struct amdgpu_sa_bo), GFP_KERNEL); | ||
| 292 | if (!(*sa_bo)) | ||
| 293 | return -ENOMEM; | ||
| 294 | (*sa_bo)->manager = sa_manager; | ||
| 295 | (*sa_bo)->fence = NULL; | ||
| 296 | INIT_LIST_HEAD(&(*sa_bo)->olist); | ||
| 297 | INIT_LIST_HEAD(&(*sa_bo)->flist); | ||
| 298 | |||
| 299 | spin_lock(&sa_manager->wq.lock); | ||
| 300 | do { | ||
| 301 | for (i = 0; i < AMDGPU_SA_NUM_FENCE_LISTS; ++i) | ||
| 302 | tries[i] = 0; | ||
| 303 | |||
| 304 | do { | ||
| 305 | amdgpu_sa_bo_try_free(sa_manager); | ||
| 306 | |||
| 307 | if (amdgpu_sa_bo_try_alloc(sa_manager, *sa_bo, | ||
| 308 | size, align)) { | ||
| 309 | spin_unlock(&sa_manager->wq.lock); | ||
| 310 | return 0; | ||
| 311 | } | ||
| 312 | |||
| 313 | /* see if we can skip over some allocations */ | ||
| 314 | } while (amdgpu_sa_bo_next_hole(sa_manager, fences, tries)); | ||
| 315 | |||
| 316 | for (i = 0, count = 0; i < AMDGPU_SA_NUM_FENCE_LISTS; ++i) | ||
| 317 | if (fences[i]) | ||
| 318 | fences[count++] = dma_fence_get(fences[i]); | ||
| 319 | |||
| 320 | if (count) { | ||
| 321 | spin_unlock(&sa_manager->wq.lock); | ||
| 322 | t = dma_fence_wait_any_timeout(fences, count, false, | ||
| 323 | MAX_SCHEDULE_TIMEOUT, | ||
| 324 | NULL); | ||
| 325 | for (i = 0; i < count; ++i) | ||
| 326 | dma_fence_put(fences[i]); | ||
| 327 | |||
| 328 | r = (t > 0) ? 0 : t; | ||
| 329 | spin_lock(&sa_manager->wq.lock); | ||
| 330 | } else { | ||
| 331 | /* if we have nothing to wait for block */ | ||
| 332 | r = wait_event_interruptible_locked( | ||
| 333 | sa_manager->wq, | ||
| 334 | amdgpu_sa_event(sa_manager, size, align) | ||
| 335 | ); | ||
| 336 | } | ||
| 337 | |||
| 338 | } while (!r); | ||
| 339 | |||
| 340 | spin_unlock(&sa_manager->wq.lock); | ||
| 341 | kfree(*sa_bo); | ||
| 342 | *sa_bo = NULL; | ||
| 343 | return r; | ||
| 344 | } | ||
| 345 | |||
| 346 | void amdgpu_sa_bo_free(struct amdgpu_device *adev, struct amdgpu_sa_bo **sa_bo, | ||
| 347 | struct dma_fence *fence) | 97 | struct dma_fence *fence) |
| 348 | { | 98 | { |
| 349 | struct amdgpu_sa_manager *sa_manager; | ||
| 350 | |||
| 351 | if (sa_bo == NULL || *sa_bo == NULL) { | 99 | if (sa_bo == NULL || *sa_bo == NULL) { |
| 352 | return; | 100 | return; |
| 353 | } | 101 | } |
| 354 | 102 | ||
| 355 | sa_manager = (*sa_bo)->manager; | 103 | drm_suballoc_free(*sa_bo, fence); |
| 356 | spin_lock(&sa_manager->wq.lock); | ||
| 357 | if (fence && !dma_fence_is_signaled(fence)) { | ||
| 358 | uint32_t idx; | ||
| 359 | |||
| 360 | (*sa_bo)->fence = dma_fence_get(fence); | ||
| 361 | idx = fence->context % AMDGPU_SA_NUM_FENCE_LISTS; | ||
| 362 | list_add_tail(&(*sa_bo)->flist, &sa_manager->flist[idx]); | ||
| 363 | } else { | ||
| 364 | amdgpu_sa_bo_remove_locked(*sa_bo); | ||
| 365 | } | ||
| 366 | wake_up_all_locked(&sa_manager->wq); | ||
| 367 | spin_unlock(&sa_manager->wq.lock); | ||
| 368 | *sa_bo = NULL; | 104 | *sa_bo = NULL; |
| 369 | } | 105 | } |
| 370 | 106 | ||
| @@ -373,26 +109,8 @@ void amdgpu_sa_bo_free(struct amdgpu_device *adev, struct amdgpu_sa_bo **sa_bo, · 2 unmodified lines | |||
| 373 | void amdgpu_sa_bo_dump_debug_info(struct amdgpu_sa_manager *sa_manager, | 109 | void amdgpu_sa_bo_dump_debug_info(struct amdgpu_sa_manager *sa_manager, |
| 374 | struct seq_file *m) | 110 | struct seq_file *m) |
| 375 | { | 111 | { |
| 376 | struct amdgpu_sa_bo *i; | 112 | struct drm_printer p = drm_seq_file_printer(m); |
| 377 | |||
| 378 | spin_lock(&sa_manager->wq.lock); | ||
| 379 | list_for_each_entry(i, &sa_manager->olist, olist) { | ||
| 380 | uint64_t soffset = i->soffset + sa_manager->gpu_addr; | ||
| 381 | uint64_t eoffset = i->eoffset + sa_manager->gpu_addr; | ||
| 382 | if (&i->olist == sa_manager->hole) { | ||
| 383 | seq_printf(m, ">"); | ||
| 384 | } else { | ||
| 385 | seq_printf(m, " "); | ||
| 386 | } | ||
| 387 | seq_printf(m, "[0x%010llx 0x%010llx] size %8lld", | ||
| 388 | soffset, eoffset, eoffset - soffset); | ||
| 389 | 113 | ||
| 390 | if (i->fence) | 114 | drm_suballoc_dump_debug_info(&sa_manager->base, &p, sa_manager->gpu_addr); |
| 391 | seq_printf(m, " protected by 0x%016llx on context %llu", | ||
| 392 | i->fence->seqno, i->fence->context); | ||
| 393 | |||
| 394 | seq_printf(m, "\n"); | ||
| 395 | } | ||
| 396 | spin_unlock(&sa_manager->wq.lock); | ||
| 397 | } | 115 | } |
| 398 | #endif | 116 | #endif |
| @@ -466,11 +466,7 @@ static int amdgpu_bo_move(struct ttm_buffer_object *bo, bool evict, · 465 unmodified lines | |||
| 466 | return r; | 466 | return r; |
| 467 | } | 467 | } |
| 468 | 468 | ||
| 469 | /* Can't move a pinned BO */ | ||
| 470 | abo = ttm_to_amdgpu_bo(bo); | 469 | abo = ttm_to_amdgpu_bo(bo); |
| 471 | if (WARN_ON_ONCE(abo->tbo.pin_count > 0)) | ||
| 472 | return -EINVAL; | ||
| 473 | |||
| 474 | adev = amdgpu_ttm_adev(bo->bdev); | 470 | adev = amdgpu_ttm_adev(bo->bdev); |
| 475 | 471 | ||
| 476 | if (!old_mem || (old_mem->mem_type == TTM_PL_SYSTEM && | 472 | if (!old_mem || (old_mem->mem_type == TTM_PL_SYSTEM && |
| @@ -649,7 +649,7 @@ static ssize_t core_id_show(struct device *dev, struct device_attribute *attr, · 648 unmodified lines | |||
| 649 | struct drm_device *drm = dev_get_drvdata(dev); | 649 | struct drm_device *drm = dev_get_drvdata(dev); |
| 650 | struct malidp_drm *malidp = drm_to_malidp(drm); | 650 | struct malidp_drm *malidp = drm_to_malidp(drm); |
| 651 | 651 | ||
| 652 | return snprintf(buf, PAGE_SIZE, "%08x\n", malidp->core_id); | 652 | return sysfs_emit(buf, "%08x\n", malidp->core_id); |
| 653 | } | 653 | } |
| 654 | 654 | ||
| 655 | static DEVICE_ATTR_RO(core_id); | 655 | static DEVICE_ATTR_RO(core_id); |
| @@ -9,7 +9,7 @@ · 8 unmodified lines | |||
| 9 | 9 | ||
| 10 | int ast_astdp_read_edid(struct drm_device *dev, u8 *ediddata) | 10 | int ast_astdp_read_edid(struct drm_device *dev, u8 *ediddata) |
| 11 | { | 11 | { |
| 12 | struct ast_private *ast = to_ast_private(dev); | 12 | struct ast_device *ast = to_ast_device(dev); |
| 13 | u8 i = 0, j = 0; | 13 | u8 i = 0, j = 0; |
| 14 | 14 | ||
| 15 | /* | 15 | /* |
| @@ -125,7 +125,7 @@ void ast_dp_launch(struct drm_device *dev, u8 bPower) · 109 unmodified lines | |||
| 125 | u8 bDPTX = 0; | 125 | u8 bDPTX = 0; |
| 126 | u8 bDPExecute = 1; | 126 | u8 bDPExecute = 1; |
| 127 | 127 | ||
| 128 | struct ast_private *ast = to_ast_private(dev); | 128 | struct ast_device *ast = to_ast_device(dev); |
| 129 | // S3 come back, need more time to wait BMC ready. | 129 | // S3 come back, need more time to wait BMC ready. |
| 130 | if (bPower) | 130 | if (bPower) |
| 131 | WaitCount = 300; | 131 | WaitCount = 300; |
| @@ -172,7 +172,7 @@ void ast_dp_launch(struct drm_device *dev, u8 bPower) · 40 unmodified lines | |||
| 172 | 172 | ||
| 173 | void ast_dp_power_on_off(struct drm_device *dev, bool on) | 173 | void ast_dp_power_on_off(struct drm_device *dev, bool on) |
| 174 | { | 174 | { |
| 175 | struct ast_private *ast = to_ast_private(dev); | 175 | struct ast_device *ast = to_ast_device(dev); |
| 176 | // Read and Turn off DP PHY sleep | 176 | // Read and Turn off DP PHY sleep |
| 177 | u8 bE3 = ast_get_index_reg_mask(ast, AST_IO_CRTC_PORT, 0xE3, AST_DP_VIDEO_ENABLE); | 177 | u8 bE3 = ast_get_index_reg_mask(ast, AST_IO_CRTC_PORT, 0xE3, AST_DP_VIDEO_ENABLE); |
| 178 | 178 | ||
| @@ -188,7 +188,7 @@ void ast_dp_power_on_off(struct drm_device *dev, bool on) · 9 unmodified lines | |||
| 188 | 188 | ||
| 189 | void ast_dp_set_on_off(struct drm_device *dev, bool on) | 189 | void ast_dp_set_on_off(struct drm_device *dev, bool on) |
| 190 | { | 190 | { |
| 191 | struct ast_private *ast = to_ast_private(dev); | 191 | struct ast_device *ast = to_ast_device(dev); |
| 192 | u8 video_on_off = on; | 192 | u8 video_on_off = on; |
| 193 | 193 | ||
| 194 | // Video On/Off | 194 | // Video On/Off |
| @@ -208,7 +208,7 @@ void ast_dp_set_on_off(struct drm_device *dev, bool on) · 13 unmodified lines | |||
| 208 | 208 | ||
| 209 | void ast_dp_set_mode(struct drm_crtc *crtc, struct ast_vbios_mode_info *vbios_mode) | 209 | void ast_dp_set_mode(struct drm_crtc *crtc, struct ast_vbios_mode_info *vbios_mode) |
| 210 | { | 210 | { |
| 211 | struct ast_private *ast = to_ast_private(crtc->dev); | 211 | struct ast_device *ast = to_ast_device(crtc->dev); |
| 212 | 212 | ||
| 213 | u32 ulRefreshRateIndex; | 213 | u32 ulRefreshRateIndex; |
| 214 | u8 ModeIdx; | 214 | u8 ModeIdx; |
| @@ -10,7 +10,7 @@ MODULE_FIRMWARE("ast_dp501_fw.bin"); · 9 unmodified lines | |||
| 10 | 10 | ||
| 11 | static void ast_release_firmware(void *data) | 11 | static void ast_release_firmware(void *data) |
| 12 | { | 12 | { |
| 13 | struct ast_private *ast = data; | 13 | struct ast_device *ast = data; |
| 14 | 14 | ||
| 15 | release_firmware(ast->dp501_fw); | 15 | release_firmware(ast->dp501_fw); |
| 16 | ast->dp501_fw = NULL; | 16 | ast->dp501_fw = NULL; |
| @@ -18,7 +18,7 @@ static void ast_release_firmware(void *data) · 1 unmodified line | |||
| 18 | 18 | ||
| 19 | static int ast_load_dp501_microcode(struct drm_device *dev) | 19 | static int ast_load_dp501_microcode(struct drm_device *dev) |
| 20 | { | 20 | { |
| 21 | struct ast_private *ast = to_ast_private(dev); | 21 | struct ast_device *ast = to_ast_device(dev); |
| 22 | int ret; | 22 | int ret; |
| 23 | 23 | ||
| 24 | ret = request_firmware(&ast->dp501_fw, "ast_dp501_fw.bin", dev->dev); | 24 | ret = request_firmware(&ast->dp501_fw, "ast_dp501_fw.bin", dev->dev); |
| @@ -28,7 +28,7 @@ static int ast_load_dp501_microcode(struct drm_device *dev) · 3 unmodified lines | |||
| 28 | return devm_add_action_or_reset(dev->dev, ast_release_firmware, ast); | 28 | return devm_add_action_or_reset(dev->dev, ast_release_firmware, ast); |
| 29 | } | 29 | } |
| 30 | 30 | ||
| 31 | static void send_ack(struct ast_private *ast) | 31 | static void send_ack(struct ast_device *ast) |
| 32 | { | 32 | { |
| 33 | u8 sendack; | 33 | u8 sendack; |
| 34 | sendack = ast_get_index_reg_mask(ast, AST_IO_CRTC_PORT, 0x9b, 0xff); | 34 | sendack = ast_get_index_reg_mask(ast, AST_IO_CRTC_PORT, 0x9b, 0xff); |
| @@ -36,7 +36,7 @@ static void send_ack(struct ast_private *ast) · 1 unmodified line | |||
| 36 | ast_set_index_reg_mask(ast, AST_IO_CRTC_PORT, 0x9b, 0x00, sendack); | 36 | ast_set_index_reg_mask(ast, AST_IO_CRTC_PORT, 0x9b, 0x00, sendack); |
| 37 | } | 37 | } |
| 38 | 38 | ||
| 39 | static void send_nack(struct ast_private *ast) | 39 | static void send_nack(struct ast_device *ast) |
| 40 | { | 40 | { |
| 41 | u8 sendack; | 41 | u8 sendack; |
| 42 | sendack = ast_get_index_reg_mask(ast, AST_IO_CRTC_PORT, 0x9b, 0xff); | 42 | sendack = ast_get_index_reg_mask(ast, AST_IO_CRTC_PORT, 0x9b, 0xff); |
| @@ -44,7 +44,7 @@ static void send_nack(struct ast_private *ast) · 1 unmodified line | |||
| 44 | ast_set_index_reg_mask(ast, AST_IO_CRTC_PORT, 0x9b, 0x00, sendack); | 44 | ast_set_index_reg_mask(ast, AST_IO_CRTC_PORT, 0x9b, 0x00, sendack); |
| 45 | } | 45 | } |
| 46 | 46 | ||
| 47 | static bool wait_ack(struct ast_private *ast) | 47 | static bool wait_ack(struct ast_device *ast) |
| 48 | { | 48 | { |
| 49 | u8 waitack; | 49 | u8 waitack; |
| 50 | u32 retry = 0; | 50 | u32 retry = 0; |
| @@ -60,7 +60,7 @@ static bool wait_ack(struct ast_private *ast) · 9 unmodified lines | |||
| 60 | return false; | 60 | return false; |
| 61 | } | 61 | } |
| 62 | 62 | ||
| 63 | static bool wait_nack(struct ast_private *ast) | 63 | static bool wait_nack(struct ast_device *ast) |
| 64 | { | 64 | { |
| 65 | u8 waitack; | 65 | u8 waitack; |
| 66 | u32 retry = 0; | 66 | u32 retry = 0; |
| @@ -76,18 +76,18 @@ static bool wait_nack(struct ast_private *ast) · 9 unmodified lines | |||
| 76 | return false; | 76 | return false; |
| 77 | } | 77 | } |
| 78 | 78 | ||
| 79 | static void set_cmd_trigger(struct ast_private *ast) | 79 | static void set_cmd_trigger(struct ast_device *ast) |
| 80 | { | 80 | { |
| 81 | ast_set_index_reg_mask(ast, AST_IO_CRTC_PORT, 0x9b, ~0x40, 0x40); | 81 | ast_set_index_reg_mask(ast, AST_IO_CRTC_PORT, 0x9b, ~0x40, 0x40); |
| 82 | } | 82 | } |
| 83 | 83 | ||
| 84 | static void clear_cmd_trigger(struct ast_private *ast) | 84 | static void clear_cmd_trigger(struct ast_device *ast) |
| 85 | { | 85 | { |
| 86 | ast_set_index_reg_mask(ast, AST_IO_CRTC_PORT, 0x9b, ~0x40, 0x00); | 86 | ast_set_index_reg_mask(ast, AST_IO_CRTC_PORT, 0x9b, ~0x40, 0x00); |
| 87 | } | 87 | } |
| 88 | 88 | ||
| 89 | #if 0 | 89 | #if 0 |
| 90 | static bool wait_fw_ready(struct ast_private *ast) | 90 | static bool wait_fw_ready(struct ast_device *ast) |
| 91 | { | 91 | { |
| 92 | u8 waitready; | 92 | u8 waitready; |
| 93 | u32 retry = 0; | 93 | u32 retry = 0; |
| @@ -106,7 +106,7 @@ static bool wait_fw_ready(struct ast_private *ast) · 12 unmodified lines | |||
| 106 | 106 | ||
| 107 | static bool ast_write_cmd(struct drm_device *dev, u8 data) | 107 | static bool ast_write_cmd(struct drm_device *dev, u8 data) |
| 108 | { | 108 | { |
| 109 | struct ast_private *ast = to_ast_private(dev); | 109 | struct ast_device *ast = to_ast_device(dev); |
| 110 | int retry = 0; | 110 | int retry = 0; |
| 111 | if (wait_nack(ast)) { | 111 | if (wait_nack(ast)) { |
| 112 | send_nack(ast); | 112 | send_nack(ast); |
| @@ -128,7 +128,7 @@ static bool ast_write_cmd(struct drm_device *dev, u8 data) · 15 unmodified lines | |||
| 128 | 128 | ||
| 129 | static bool ast_write_data(struct drm_device *dev, u8 data) | 129 | static bool ast_write_data(struct drm_device *dev, u8 data) |
| 130 | { | 130 | { |
| 131 | struct ast_private *ast = to_ast_private(dev); | 131 | struct ast_device *ast = to_ast_device(dev); |
| 132 | 132 | ||
| 133 | if (wait_nack(ast)) { | 133 | if (wait_nack(ast)) { |
| 134 | send_nack(ast); | 134 | send_nack(ast); |
| @@ -146,7 +146,7 @@ static bool ast_write_data(struct drm_device *dev, u8 data) · 11 unmodified lines | |||
| 146 | #if 0 | 146 | #if 0 |
| 147 | static bool ast_read_data(struct drm_device *dev, u8 *data) | 147 | static bool ast_read_data(struct drm_device *dev, u8 *data) |
| 148 | { | 148 | { |
| 149 | struct ast_private *ast = to_ast_private(dev); | 149 | struct ast_device *ast = to_ast_device(dev); |
| 150 | u8 tmp; | 150 | u8 tmp; |
| 151 | 151 | ||
| 152 | *data = 0; | 152 | *data = 0; |
| @@ -163,7 +163,7 @@ static bool ast_read_data(struct drm_device *dev, u8 *data) · 10 unmodified lines | |||
| 163 | return true; | 163 | return true; |
| 164 | } | 164 | } |
| 165 | 165 | ||
| 166 | static void clear_cmd(struct ast_private *ast) | 166 | static void clear_cmd(struct ast_device *ast) |
| 167 | { | 167 | { |
| 168 | send_nack(ast); | 168 | send_nack(ast); |
| 169 | ast_set_index_reg_mask(ast, AST_IO_CRTC_PORT, 0x9a, 0x00, 0x00); | 169 | ast_set_index_reg_mask(ast, AST_IO_CRTC_PORT, 0x9a, 0x00, 0x00); |
| @@ -178,14 +178,14 @@ void ast_set_dp501_video_output(struct drm_device *dev, u8 mode) · 8 unmodified lines | |||
| 178 | msleep(10); | 178 | msleep(10); |
| 179 | } | 179 | } |
| 180 | 180 | ||
| 181 | static u32 get_fw_base(struct ast_private *ast) | 181 | static u32 get_fw_base(struct ast_device *ast) |
| 182 | { | 182 | { |
| 183 | return ast_mindwm(ast, 0x1e6e2104) & 0x7fffffff; | 183 | return ast_mindwm(ast, 0x1e6e2104) & 0x7fffffff; |
| 184 | } | 184 | } |
| 185 | 185 | ||
| 186 | bool ast_backup_fw(struct drm_device *dev, u8 *addr, u32 size) | 186 | bool ast_backup_fw(struct drm_device *dev, u8 *addr, u32 size) |
| 187 | { | 187 | { |
| 188 | struct ast_private *ast = to_ast_private(dev); | 188 | struct ast_device *ast = to_ast_device(dev); |
| 189 | u32 i, data; | 189 | u32 i, data; |
| 190 | u32 boot_address; | 190 | u32 boot_address; |
| 191 | 191 | ||
| @@ -204,7 +204,7 @@ bool ast_backup_fw(struct drm_device *dev, u8 *addr, u32 size) · 12 unmodified lines | |||
| 204 | 204 | ||
| 205 | static bool ast_launch_m68k(struct drm_device *dev) | 205 | static bool ast_launch_m68k(struct drm_device *dev) |
| 206 | { | 206 | { |
| 207 | struct ast_private *ast = to_ast_private(dev); | 207 | struct ast_device *ast = to_ast_device(dev); |
| 208 | u32 i, data, len = 0; | 208 | u32 i, data, len = 0; |
| 209 | u32 boot_address; | 209 | u32 boot_address; |
| 210 | u8 *fw_addr = NULL; | 210 | u8 *fw_addr = NULL; |
| @@ -274,7 +274,7 @@ static bool ast_launch_m68k(struct drm_device *dev) · 63 unmodified lines | |||
| 274 | 274 | ||
| 275 | bool ast_dp501_read_edid(struct drm_device *dev, u8 *ediddata) | 275 | bool ast_dp501_read_edid(struct drm_device *dev, u8 *ediddata) |
| 276 | { | 276 | { |
| 277 | struct ast_private *ast = to_ast_private(dev); | 277 | struct ast_device *ast = to_ast_device(dev); |
| 278 | u32 i, boot_address, offset, data; | 278 | u32 i, boot_address, offset, data; |
| 279 | u32 *pEDIDidx; | 279 | u32 *pEDIDidx; |
| 280 | 280 | ||
| @@ -334,7 +334,7 @@ bool ast_dp501_read_edid(struct drm_device *dev, u8 *ediddata) · 53 unmodified lines | |||
| 334 | 334 | ||
| 335 | static bool ast_init_dvo(struct drm_device *dev) | 335 | static bool ast_init_dvo(struct drm_device *dev) |
| 336 | { | 336 | { |
| 337 | struct ast_private *ast = to_ast_private(dev); | 337 | struct ast_device *ast = to_ast_device(dev); |
| 338 | u8 jreg; | 338 | u8 jreg; |
| 339 | u32 data; | 339 | u32 data; |
| 340 | ast_write32(ast, 0xf004, 0x1e6e0000); | 340 | ast_write32(ast, 0xf004, 0x1e6e0000); |
| @@ -407,7 +407,7 @@ static bool ast_init_dvo(struct drm_device *dev) · 66 unmodified lines | |||
| 407 | 407 | ||
| 408 | static void ast_init_analog(struct drm_device *dev) | 408 | static void ast_init_analog(struct drm_device *dev) |
| 409 | { | 409 | { |
| 410 | struct ast_private *ast = to_ast_private(dev); | 410 | struct ast_device *ast = to_ast_device(dev); |
| 411 | u32 data; | 411 | u32 data; |
| 412 | 412 | ||
| 413 | /* | 413 | /* |
| @@ -434,7 +434,7 @@ static void ast_init_analog(struct drm_device *dev) · 20 unmodified lines | |||
| 434 | 434 | ||
| 435 | void ast_init_3rdtx(struct drm_device *dev) | 435 | void ast_init_3rdtx(struct drm_device *dev) |
| 436 | { | 436 | { |
| 437 | struct ast_private *ast = to_ast_private(dev); | 437 | struct ast_device *ast = to_ast_device(dev); |
| 438 | u8 jreg; | 438 | u8 jreg; |
| 439 | 439 | ||
| 440 | if (ast->chip == AST2300 || ast->chip == AST2400) { | 440 | if (ast->chip == AST2300 || ast->chip == AST2400) { |
| @@ -105,7 +105,7 @@ static int ast_remove_conflicting_framebuffers(struct pci_dev *pdev) · 104 unmodified lines | |||
| 105 | 105 | ||
| 106 | static int ast_pci_probe(struct pci_dev *pdev, const struct pci_device_id *ent) | 106 | static int ast_pci_probe(struct pci_dev *pdev, const struct pci_device_id *ent) |
| 107 | { | 107 | { |
| 108 | struct ast_private *ast; | 108 | struct ast_device *ast; |
| 109 | struct drm_device *dev; | 109 | struct drm_device *dev; |
| 110 | int ret; | 110 | int ret; |
| 111 | 111 | ||
| @@ -157,7 +157,7 @@ to_ast_sil164_connector(struct drm_connector *connector) · 156 unmodified lines | |||
| 157 | * Device | 157 | * Device |
| 158 | */ | 158 | */ |
| 159 | 159 | ||
| 160 | struct ast_private { | 160 | struct ast_device { |
| 161 | struct drm_device base; | 161 | struct drm_device base; |
| 162 | 162 | ||
| 163 | struct mutex ioregs_lock; /* Protects access to I/O registers in ioregs */ | 163 | struct mutex ioregs_lock; /* Protects access to I/O registers in ioregs */ |
| @@ -210,14 +210,14 @@ struct ast_private { · 46 unmodified lines | |||
| 210 | const struct firmware *dp501_fw; /* dp501 fw */ | 210 | const struct firmware *dp501_fw; /* dp501 fw */ |
| 211 | }; | 211 | }; |
| 212 | 212 | ||
| 213 | static inline struct ast_private *to_ast_private(struct drm_device *dev) | 213 | static inline struct ast_device *to_ast_device(struct drm_device *dev) |
| 214 | { | 214 | { |
| 215 | return container_of(dev, struct ast_private, base); | 215 | return container_of(dev, struct ast_device, base); |
| 216 | } | 216 | } |
| 217 | 217 | ||
| 218 | struct ast_private *ast_device_create(const struct drm_driver *drv, | 218 | struct ast_device *ast_device_create(const struct drm_driver *drv, |
| 219 | struct pci_dev *pdev, | 219 | struct pci_dev *pdev, |
| 220 | unsigned long flags); | 220 | unsigned long flags); |
| 221 | 221 | ||
| 222 | #define AST_IO_AR_PORT_WRITE (0x40) | 222 | #define AST_IO_AR_PORT_WRITE (0x40) |
| 223 | #define AST_IO_MISC_PORT_WRITE (0x42) | 223 | #define AST_IO_MISC_PORT_WRITE (0x42) |
| @@ -238,62 +238,44 @@ struct ast_private *ast_device_create(const struct drm_driver *drv, · 14 unmodified lines | |||
| 238 | #define AST_IO_VGACRCB_HWC_ENABLED BIT(1) | 238 | #define AST_IO_VGACRCB_HWC_ENABLED BIT(1) |
| 239 | #define AST_IO_VGACRCB_HWC_16BPP BIT(0) /* set: ARGB4444, cleared: 2bpp palette */ | 239 | #define AST_IO_VGACRCB_HWC_16BPP BIT(0) /* set: ARGB4444, cleared: 2bpp palette */ |
| 240 | 240 | ||
| 241 | #define __ast_read(x) \ | 241 | static inline u32 ast_read32(struct ast_device *ast, u32 reg) |
| 242 | static inline u##x ast_read##x(struct ast_private *ast, u32 reg) { \ | 242 | { |
| 243 | u##x val = 0;\ | 243 | return ioread32(ast->regs + reg); |
| 244 | val = ioread##x(ast->regs + reg); \ | ||
| 245 | return val;\ | ||
| 246 | } | 244 | } |
| 247 | 245 | ||
| 248 | __ast_read(8); | 246 | static inline void ast_write32(struct ast_device *ast, u32 reg, u32 val) |
| 249 | __ast_read(16); | 247 | { |
| 250 | __ast_read(32) | 248 | iowrite32(val, ast->regs + reg); |
| 251 | |||
| 252 | #define __ast_io_read(x) \ | ||
| 253 | static inline u##x ast_io_read##x(struct ast_private *ast, u32 reg) { \ | ||
| 254 | u##x val = 0;\ | ||
| 255 | val = ioread##x(ast->ioregs + reg); \ | ||
| 256 | return val;\ | ||
| 257 | } | 249 | } |
| 258 | 250 | ||
| 259 | __ast_io_read(8); | 251 | static inline u8 ast_io_read8(struct ast_device *ast, u32 reg) |
| 260 | __ast_io_read(16); | 252 | { |
| 261 | __ast_io_read(32); | 253 | return ioread8(ast->ioregs + reg); |
| 262 | 254 | } | |
| 263 | #define __ast_write(x) \ | ||
| 264 | static inline void ast_write##x(struct ast_private *ast, u32 reg, u##x val) {\ | ||
| 265 | iowrite##x(val, ast->regs + reg);\ | ||
| 266 | } | ||
| 267 | |||
| 268 | __ast_write(8); | ||
| 269 | __ast_write(16); | ||
| 270 | __ast_write(32); | ||
| 271 | |||
| 272 | #define __ast_io_write(x) \ | ||
| 273 | static inline void ast_io_write##x(struct ast_private *ast, u32 reg, u##x val) {\ | ||
| 274 | iowrite##x(val, ast->ioregs + reg);\ | ||
| 275 | } | ||
| 276 | 255 | ||
| 277 | __ast_io_write(8); | 256 | static inline void ast_io_write8(struct ast_device *ast, u32 reg, u8 val) |
| 278 | __ast_io_write(16); | 257 | { |
| 279 | #undef __ast_io_write | 258 | iowrite8(val, ast->ioregs + reg); |
| 259 | } | ||
| 280 | 260 | ||
| 281 | static inline void ast_set_index_reg(struct ast_private *ast, | 261 | static inline void ast_set_index_reg(struct ast_device *ast, |
| 282 | uint32_t base, uint8_t index, | 262 | uint32_t base, uint8_t index, |
| 283 | uint8_t val) | 263 | uint8_t val) |
| 284 | { | 264 | { |
| 285 | ast_io_write16(ast, base, ((u16)val << 8) | index); | 265 | ast_io_write8(ast, base, index); |
| 266 | ++base; | ||
| 267 | ast_io_write8(ast, base, val); | ||
| 286 | } | 268 | } |
| 287 | 269 | ||
| 288 | void ast_set_index_reg_mask(struct ast_private *ast, | 270 | void ast_set_index_reg_mask(struct ast_device *ast, |
| 289 | uint32_t base, uint8_t index, | 271 | uint32_t base, uint8_t index, |
| 290 | uint8_t mask, uint8_t val); | 272 | uint8_t mask, uint8_t val); |
| 291 | uint8_t ast_get_index_reg(struct ast_private *ast, | 273 | uint8_t ast_get_index_reg(struct ast_device *ast, |
| 292 | uint32_t base, uint8_t index); | 274 | uint32_t base, uint8_t index); |
| 293 | uint8_t ast_get_index_reg_mask(struct ast_private *ast, | 275 | uint8_t ast_get_index_reg_mask(struct ast_device *ast, |
| 294 | uint32_t base, uint8_t index, uint8_t mask); | 276 | uint32_t base, uint8_t index, uint8_t mask); |
| 295 | 277 | ||
| 296 | static inline void ast_open_key(struct ast_private *ast) | 278 | static inline void ast_open_key(struct ast_device *ast) |
| 297 | { | 279 | { |
| 298 | ast_set_index_reg(ast, AST_IO_CRTC_PORT, 0x80, 0xA8); | 280 | ast_set_index_reg(ast, AST_IO_CRTC_PORT, 0x80, 0xA8); |
| 299 | } | 281 | } |
| @@ -352,7 +334,7 @@ struct ast_crtc_state { · 52 unmodified lines | |||
| 352 | 334 | ||
| 353 | #define to_ast_crtc_state(state) container_of(state, struct ast_crtc_state, base) | 335 | #define to_ast_crtc_state(state) container_of(state, struct ast_crtc_state, base) |
| 354 | 336 | ||
| 355 | int ast_mode_config_init(struct ast_private *ast); | 337 | int ast_mode_config_init(struct ast_device *ast); |
| 356 | 338 | ||
| 357 | #define AST_MM_ALIGN_SHIFT 4 | 339 | #define AST_MM_ALIGN_SHIFT 4 |
| 358 | #define AST_MM_ALIGN_MASK ((1 << AST_MM_ALIGN_SHIFT) - 1) | 340 | #define AST_MM_ALIGN_MASK ((1 << AST_MM_ALIGN_SHIFT) - 1) |
| @@ -476,16 +458,16 @@ int ast_mode_config_init(struct ast_private *ast); · 117 unmodified lines | |||
| 476 | #define ASTDP_1366x768_60 0x1E | 458 | #define ASTDP_1366x768_60 0x1E |
| 477 | #define ASTDP_1152x864_75 0x1F | 459 | #define ASTDP_1152x864_75 0x1F |
| 478 | 460 | ||
| 479 | int ast_mm_init(struct ast_private *ast); | 461 | int ast_mm_init(struct ast_device *ast); |
| 480 | 462 | ||
| 481 | /* ast post */ | 463 | /* ast post */ |
| 482 | void ast_enable_vga(struct drm_device *dev); | 464 | void ast_enable_vga(struct drm_device *dev); |
| 483 | void ast_enable_mmio(struct drm_device *dev); | 465 | void ast_enable_mmio(struct drm_device *dev); |
| 484 | bool ast_is_vga_enabled(struct drm_device *dev); | 466 | bool ast_is_vga_enabled(struct drm_device *dev); |
| 485 | void ast_post_gpu(struct drm_device *dev); | 467 | void ast_post_gpu(struct drm_device *dev); |
| 486 | u32 ast_mindwm(struct ast_private *ast, u32 r); | 468 | u32 ast_mindwm(struct ast_device *ast, u32 r); |
| 487 | void ast_moutdwm(struct ast_private *ast, u32 r, u32 v); | 469 | void ast_moutdwm(struct ast_device *ast, u32 r, u32 v); |
| 488 | void ast_patch_ahb_2500(struct ast_private *ast); | 470 | void ast_patch_ahb_2500(struct ast_device *ast); |
| 489 | /* ast dp501 */ | 471 | /* ast dp501 */ |
| 490 | void ast_set_dp501_video_output(struct drm_device *dev, u8 mode); | 472 | void ast_set_dp501_video_output(struct drm_device *dev, u8 mode); |
| 491 | bool ast_backup_fw(struct drm_device *dev, u8 *addr, u32 size); | 473 | bool ast_backup_fw(struct drm_device *dev, u8 *addr, u32 size); |
| @@ -29,7 +29,7 @@ · 28 unmodified lines | |||
| 29 | static void ast_i2c_setsda(void *i2c_priv, int data) | 29 | static void ast_i2c_setsda(void *i2c_priv, int data) |
| 30 | { | 30 | { |
| 31 | struct ast_i2c_chan *i2c = i2c_priv; | 31 | struct ast_i2c_chan *i2c = i2c_priv; |
| 32 | struct ast_private *ast = to_ast_private(i2c->dev); | 32 | struct ast_device *ast = to_ast_device(i2c->dev); |
| 33 | int i; | 33 | int i; |
| 34 | u8 ujcrb7, jtemp; | 34 | u8 ujcrb7, jtemp; |
| 35 | 35 | ||
| @@ -45,7 +45,7 @@ static void ast_i2c_setsda(void *i2c_priv, int data) · 9 unmodified lines | |||
| 45 | static void ast_i2c_setscl(void *i2c_priv, int clock) | 45 | static void ast_i2c_setscl(void *i2c_priv, int clock) |
| 46 | { | 46 | { |
| 47 | struct ast_i2c_chan *i2c = i2c_priv; | 47 | struct ast_i2c_chan *i2c = i2c_priv; |
| 48 | struct ast_private *ast = to_ast_private(i2c->dev); | 48 | struct ast_device *ast = to_ast_device(i2c->dev); |
| 49 | int i; | 49 | int i; |
| 50 | u8 ujcrb7, jtemp; | 50 | u8 ujcrb7, jtemp; |
| 51 | 51 | ||
| @@ -61,7 +61,7 @@ static void ast_i2c_setscl(void *i2c_priv, int clock) · 9 unmodified lines | |||
| 61 | static int ast_i2c_getsda(void *i2c_priv) | 61 | static int ast_i2c_getsda(void *i2c_priv) |
| 62 | { | 62 | { |
| 63 | struct ast_i2c_chan *i2c = i2c_priv; | 63 | struct ast_i2c_chan *i2c = i2c_priv; |
| 64 | struct ast_private *ast = to_ast_private(i2c->dev); | 64 | struct ast_device *ast = to_ast_device(i2c->dev); |
| 65 | uint32_t val, val2, count, pass; | 65 | uint32_t val, val2, count, pass; |
| 66 | 66 | ||
| 67 | count = 0; | 67 | count = 0; |
| @@ -83,7 +83,7 @@ static int ast_i2c_getsda(void *i2c_priv) · 15 unmodified lines | |||
| 83 | static int ast_i2c_getscl(void *i2c_priv) | 83 | static int ast_i2c_getscl(void *i2c_priv) |
| 84 | { | 84 | { |
| 85 | struct ast_i2c_chan *i2c = i2c_priv; | 85 | struct ast_i2c_chan *i2c = i2c_priv; |
| 86 | struct ast_private *ast = to_ast_private(i2c->dev); | 86 | struct ast_device *ast = to_ast_device(i2c->dev); |
| 87 | uint32_t val, val2, count, pass; | 87 | uint32_t val, val2, count, pass; |
| 88 | 88 | ||
| 89 | count = 0; | 89 | count = 0; |
| @@ -35,7 +35,7 @@ · 34 unmodified lines | |||
| 35 | 35 | ||
| 36 | #include "ast_drv.h" | 36 | #include "ast_drv.h" |
| 37 | 37 | ||
| 38 | void ast_set_index_reg_mask(struct ast_private *ast, | 38 | void ast_set_index_reg_mask(struct ast_device *ast, |
| 39 | uint32_t base, uint8_t index, | 39 | uint32_t base, uint8_t index, |
| 40 | uint8_t mask, uint8_t val) | 40 | uint8_t mask, uint8_t val) |
| 41 | { | 41 | { |
| @@ -45,7 +45,7 @@ void ast_set_index_reg_mask(struct ast_private *ast, · 3 unmodified lines | |||
| 45 | ast_set_index_reg(ast, base, index, tmp); | 45 | ast_set_index_reg(ast, base, index, tmp); |
| 46 | } | 46 | } |
| 47 | 47 | ||
| 48 | uint8_t ast_get_index_reg(struct ast_private *ast, | 48 | uint8_t ast_get_index_reg(struct ast_device *ast, |
| 49 | uint32_t base, uint8_t index) | 49 | uint32_t base, uint8_t index) |
| 50 | { | 50 | { |
| 51 | uint8_t ret; | 51 | uint8_t ret; |
| @@ -54,7 +54,7 @@ uint8_t ast_get_index_reg(struct ast_private *ast, · 2 unmodified lines | |||
| 54 | return ret; | 54 | return ret; |
| 55 | } | 55 | } |
| 56 | 56 | ||
| 57 | uint8_t ast_get_index_reg_mask(struct ast_private *ast, | 57 | uint8_t ast_get_index_reg_mask(struct ast_device *ast, |
| 58 | uint32_t base, uint8_t index, uint8_t mask) | 58 | uint32_t base, uint8_t index, uint8_t mask) |
| 59 | { | 59 | { |
| 60 | uint8_t ret; | 60 | uint8_t ret; |
| @@ -66,7 +66,7 @@ uint8_t ast_get_index_reg_mask(struct ast_private *ast, · 5 unmodified lines | |||
| 66 | static void ast_detect_config_mode(struct drm_device *dev, u32 *scu_rev) | 66 | static void ast_detect_config_mode(struct drm_device *dev, u32 *scu_rev) |
| 67 | { | 67 | { |
| 68 | struct device_node *np = dev->dev->of_node; | 68 | struct device_node *np = dev->dev->of_node; |
| 69 | struct ast_private *ast = to_ast_private(dev); | 69 | struct ast_device *ast = to_ast_device(dev); |
| 70 | struct pci_dev *pdev = to_pci_dev(dev->dev); | 70 | struct pci_dev *pdev = to_pci_dev(dev->dev); |
| 71 | uint32_t data, jregd0, jregd1; | 71 | uint32_t data, jregd0, jregd1; |
| 72 | 72 | ||
| @@ -122,7 +122,7 @@ static void ast_detect_config_mode(struct drm_device *dev, u32 *scu_rev) · 49 unmodified lines | |||
| 122 | 122 | ||
| 123 | static int ast_detect_chip(struct drm_device *dev, bool *need_post) | 123 | static int ast_detect_chip(struct drm_device *dev, bool *need_post) |
| 124 | { | 124 | { |
| 125 | struct ast_private *ast = to_ast_private(dev); | 125 | struct ast_device *ast = to_ast_device(dev); |
| 126 | struct pci_dev *pdev = to_pci_dev(dev->dev); | 126 | struct pci_dev *pdev = to_pci_dev(dev->dev); |
| 127 | uint32_t jreg, scu_rev; | 127 | uint32_t jreg, scu_rev; |
| 128 | 128 | ||
| @@ -271,7 +271,7 @@ static int ast_detect_chip(struct drm_device *dev, bool *need_post) · 142 unmodified lines | |||
| 271 | static int ast_get_dram_info(struct drm_device *dev) | 271 | static int ast_get_dram_info(struct drm_device *dev) |
| 272 | { | 272 | { |
| 273 | struct device_node *np = dev->dev->of_node; | 273 | struct device_node *np = dev->dev->of_node; |
| 274 | struct ast_private *ast = to_ast_private(dev); | 274 | struct ast_device *ast = to_ast_device(dev); |
| 275 | uint32_t mcr_cfg, mcr_scu_mpll, mcr_scu_strap; | 275 | uint32_t mcr_cfg, mcr_scu_mpll, mcr_scu_strap; |
| 276 | uint32_t denum, num, div, ref_pll, dsel; | 276 | uint32_t denum, num, div, ref_pll, dsel; |
| 277 | 277 | ||
| @@ -394,22 +394,22 @@ static int ast_get_dram_info(struct drm_device *dev) · 116 unmodified lines | |||
| 394 | */ | 394 | */ |
| 395 | static void ast_device_release(void *data) | 395 | static void ast_device_release(void *data) |
| 396 | { | 396 | { |
| 397 | struct ast_private *ast = data; | 397 | struct ast_device *ast = data; |
| 398 | 398 | ||
| 399 | /* enable standard VGA decode */ | 399 | /* enable standard VGA decode */ |
| 400 | ast_set_index_reg(ast, AST_IO_CRTC_PORT, 0xa1, 0x04); | 400 | ast_set_index_reg(ast, AST_IO_CRTC_PORT, 0xa1, 0x04); |
| 401 | } | 401 | } |
| 402 | 402 | ||
| 403 | struct ast_private *ast_device_create(const struct drm_driver *drv, | 403 | struct ast_device *ast_device_create(const struct drm_driver *drv, |
| 404 | struct pci_dev *pdev, | 404 | struct pci_dev *pdev, |
| 405 | unsigned long flags) | 405 | unsigned long flags) |
| 406 | { | 406 | { |
| 407 | struct drm_device *dev; | 407 | struct drm_device *dev; |
| 408 | struct ast_private *ast; | 408 | struct ast_device *ast; |
| 409 | bool need_post; | 409 | bool need_post; |
| 410 | int ret = 0; | 410 | int ret = 0; |
| 411 | 411 | ||
| 412 | ast = devm_drm_dev_alloc(&pdev->dev, drv, struct ast_private, base); | 412 | ast = devm_drm_dev_alloc(&pdev->dev, drv, struct ast_device, base); |
| 413 | if (IS_ERR(ast)) | 413 | if (IS_ERR(ast)) |
| 414 | return ast; | 414 | return ast; |
| 415 | dev = &ast->base; | 415 | dev = &ast->base; |
| @@ -33,7 +33,7 @@ · 32 unmodified lines | |||
| 33 | 33 | ||
| 34 | #include "ast_drv.h" | 34 | #include "ast_drv.h" |
| 35 | 35 | ||
| 36 | static u32 ast_get_vram_size(struct ast_private *ast) | 36 | static u32 ast_get_vram_size(struct ast_device *ast) |
| 37 | { | 37 | { |
| 38 | u8 jreg; | 38 | u8 jreg; |
| 39 | u32 vram_size; | 39 | u32 vram_size; |
| @@ -73,7 +73,7 @@ static u32 ast_get_vram_size(struct ast_private *ast) · 33 unmodified lines | |||
| 73 | return vram_size; | 73 | return vram_size; |
| 74 | } | 74 | } |
| 75 | 75 | ||
| 76 | int ast_mm_init(struct ast_private *ast) | 76 | int ast_mm_init(struct ast_device *ast) |
| 77 | { | 77 | { |
| 78 | struct drm_device *dev = &ast->base; | 78 | struct drm_device *dev = &ast->base; |
| 79 | struct pci_dev *pdev = to_pci_dev(dev->dev); | 79 | struct pci_dev *pdev = to_pci_dev(dev->dev); |
| @@ -51,7 +51,7 @@ · 50 unmodified lines | |||
| 51 | 51 | ||
| 52 | #define AST_LUT_SIZE 256 | 52 | #define AST_LUT_SIZE 256 |
| 53 | 53 | ||
| 54 | static inline void ast_load_palette_index(struct ast_private *ast, | 54 | static inline void ast_load_palette_index(struct ast_device *ast, |
| 55 | u8 index, u8 red, u8 green, | 55 | u8 index, u8 red, u8 green, |
| 56 | u8 blue) | 56 | u8 blue) |
| 57 | { | 57 | { |
| @@ -65,7 +65,7 @@ static inline void ast_load_palette_index(struct ast_private *ast, · 7 unmodified lines | |||
| 65 | ast_io_read8(ast, AST_IO_SEQ_PORT); | 65 | ast_io_read8(ast, AST_IO_SEQ_PORT); |
| 66 | } | 66 | } |
| 67 | 67 | ||
| 68 | static void ast_crtc_set_gamma_linear(struct ast_private *ast, | 68 | static void ast_crtc_set_gamma_linear(struct ast_device *ast, |
| 69 | const struct drm_format_info *format) | 69 | const struct drm_format_info *format) |
| 70 | { | 70 | { |
| 71 | int i; | 71 | int i; |
| @@ -84,7 +84,7 @@ static void ast_crtc_set_gamma_linear(struct ast_private *ast, · 12 unmodified lines | |||
| 84 | } | 84 | } |
| 85 | } | 85 | } |
| 86 | 86 | ||
| 87 | static void ast_crtc_set_gamma(struct ast_private *ast, | 87 | static void ast_crtc_set_gamma(struct ast_device *ast, |
| 88 | const struct drm_format_info *format, | 88 | const struct drm_format_info *format, |
| 89 | struct drm_color_lut *lut) | 89 | struct drm_color_lut *lut) |
| 90 | { | 90 | { |
| @@ -232,7 +232,7 @@ static bool ast_get_vbios_mode_info(const struct drm_format_info *format, · 141 unmodified lines | |||
| 232 | return true; | 232 | return true; |
| 233 | } | 233 | } |
| 234 | 234 | ||
| 235 | static void ast_set_vbios_color_reg(struct ast_private *ast, | 235 | static void ast_set_vbios_color_reg(struct ast_device *ast, |
| 236 | const struct drm_format_info *format, | 236 | const struct drm_format_info *format, |
| 237 | const struct ast_vbios_mode_info *vbios_mode) | 237 | const struct ast_vbios_mode_info *vbios_mode) |
| 238 | { | 238 | { |
| @@ -263,7 +263,7 @@ static void ast_set_vbios_color_reg(struct ast_private *ast, · 24 unmodified lines | |||
| 263 | } | 263 | } |
| 264 | } | 264 | } |
| 265 | 265 | ||
| 266 | static void ast_set_vbios_mode_reg(struct ast_private *ast, | 266 | static void ast_set_vbios_mode_reg(struct ast_device *ast, |
| 267 | const struct drm_display_mode *adjusted_mode, | 267 | const struct drm_display_mode *adjusted_mode, |
| 268 | const struct ast_vbios_mode_info *vbios_mode) | 268 | const struct ast_vbios_mode_info *vbios_mode) |
| 269 | { | 269 | { |
| @@ -287,7 +287,7 @@ static void ast_set_vbios_mode_reg(struct ast_private *ast, · 17 unmodified lines | |||
| 287 | } | 287 | } |
| 288 | } | 288 | } |
| 289 | 289 | ||
| 290 | static void ast_set_std_reg(struct ast_private *ast, | 290 | static void ast_set_std_reg(struct ast_device *ast, |
| 291 | struct drm_display_mode *mode, | 291 | struct drm_display_mode *mode, |
| 292 | struct ast_vbios_mode_info *vbios_mode) | 292 | struct ast_vbios_mode_info *vbios_mode) |
| 293 | { | 293 | { |
| @@ -335,7 +335,7 @@ static void ast_set_std_reg(struct ast_private *ast, · 41 unmodified lines | |||
| 335 | ast_set_index_reg(ast, AST_IO_GR_PORT, i, stdtable->gr[i]); | 335 | ast_set_index_reg(ast, AST_IO_GR_PORT, i, stdtable->gr[i]); |
| 336 | } | 336 | } |
| 337 | 337 | ||
| 338 | static void ast_set_crtc_reg(struct ast_private *ast, | 338 | static void ast_set_crtc_reg(struct ast_device *ast, |
| 339 | struct drm_display_mode *mode, | 339 | struct drm_display_mode *mode, |
| 340 | struct ast_vbios_mode_info *vbios_mode) | 340 | struct ast_vbios_mode_info *vbios_mode) |
| 341 | { | 341 | { |
| @@ -450,7 +450,7 @@ static void ast_set_crtc_reg(struct ast_private *ast, · 108 unmodified lines | |||
| 450 | ast_set_index_reg_mask(ast, AST_IO_CRTC_PORT, 0x11, 0x7f, 0x80); | 450 | ast_set_index_reg_mask(ast, AST_IO_CRTC_PORT, 0x11, 0x7f, 0x80); |
| 451 | } | 451 | } |
| 452 | 452 | ||
| 453 | static void ast_set_offset_reg(struct ast_private *ast, | 453 | static void ast_set_offset_reg(struct ast_device *ast, |
| 454 | struct drm_framebuffer *fb) | 454 | struct drm_framebuffer *fb) |
| 455 | { | 455 | { |
| 456 | u16 offset; | 456 | u16 offset; |
| @@ -460,7 +460,7 @@ static void ast_set_offset_reg(struct ast_private *ast, · 3 unmodified lines | |||
| 460 | ast_set_index_reg(ast, AST_IO_CRTC_PORT, 0xb0, (offset >> 8) & 0x3f); | 460 | ast_set_index_reg(ast, AST_IO_CRTC_PORT, 0xb0, (offset >> 8) & 0x3f); |
| 461 | } | 461 | } |
| 462 | 462 | ||
| 463 | static void ast_set_dclk_reg(struct ast_private *ast, | 463 | static void ast_set_dclk_reg(struct ast_device *ast, |
| 464 | struct drm_display_mode *mode, | 464 | struct drm_display_mode *mode, |
| 465 | struct ast_vbios_mode_info *vbios_mode) | 465 | struct ast_vbios_mode_info *vbios_mode) |
| 466 | { | 466 | { |
| @@ -478,7 +478,7 @@ static void ast_set_dclk_reg(struct ast_private *ast, · 11 unmodified lines | |||
| 478 | ((clk_info->param3 & 0x3) << 4)); | 478 | ((clk_info->param3 & 0x3) << 4)); |
| 479 | } | 479 | } |
| 480 | 480 | ||
| 481 | static void ast_set_color_reg(struct ast_private *ast, | 481 | static void ast_set_color_reg(struct ast_device *ast, |
| 482 | const struct drm_format_info *format) | 482 | const struct drm_format_info *format) |
| 483 | { | 483 | { |
| 484 | u8 jregA0 = 0, jregA3 = 0, jregA8 = 0; | 484 | u8 jregA0 = 0, jregA3 = 0, jregA8 = 0; |
| @@ -507,7 +507,7 @@ static void ast_set_color_reg(struct ast_private *ast, · 22 unmodified lines | |||
| 507 | ast_set_index_reg_mask(ast, AST_IO_CRTC_PORT, 0xa8, 0xfd, jregA8); | 507 | ast_set_index_reg_mask(ast, AST_IO_CRTC_PORT, 0xa8, 0xfd, jregA8); |
| 508 | } | 508 | } |
| 509 | 509 | ||
| 510 | static void ast_set_crtthd_reg(struct ast_private *ast) | 510 | static void ast_set_crtthd_reg(struct ast_device *ast) |
| 511 | { | 511 | { |
| 512 | /* Set Threshold */ | 512 | /* Set Threshold */ |
| 513 | if (ast->chip == AST2600) { | 513 | if (ast->chip == AST2600) { |
| @@ -529,7 +529,7 @@ static void ast_set_crtthd_reg(struct ast_private *ast) · 15 unmodified lines | |||
| 529 | } | 529 | } |
| 530 | } | 530 | } |
| 531 | 531 | ||
| 532 | static void ast_set_sync_reg(struct ast_private *ast, | 532 | static void ast_set_sync_reg(struct ast_device *ast, |
| 533 | struct drm_display_mode *mode, | 533 | struct drm_display_mode *mode, |
| 534 | struct ast_vbios_mode_info *vbios_mode) | 534 | struct ast_vbios_mode_info *vbios_mode) |
| 535 | { | 535 | { |
| @@ -544,7 +544,7 @@ static void ast_set_sync_reg(struct ast_private *ast, · 8 unmodified lines | |||
| 544 | ast_io_write8(ast, AST_IO_MISC_PORT_WRITE, jreg); | 544 | ast_io_write8(ast, AST_IO_MISC_PORT_WRITE, jreg); |
| 545 | } | 545 | } |
| 546 | 546 | ||
| 547 | static void ast_set_start_address_crt1(struct ast_private *ast, | 547 | static void ast_set_start_address_crt1(struct ast_device *ast, |
| 548 | unsigned int offset) | 548 | unsigned int offset) |
| 549 | { | 549 | { |
| 550 | u32 addr; | 550 | u32 addr; |
| @@ -556,7 +556,7 @@ static void ast_set_start_address_crt1(struct ast_private *ast, · 5 unmodified lines | |||
| 556 | 556 | ||
| 557 | } | 557 | } |
| 558 | 558 | ||
| 559 | static void ast_wait_for_vretrace(struct ast_private *ast) | 559 | static void ast_wait_for_vretrace(struct ast_device *ast) |
| 560 | { | 560 | { |
| 561 | unsigned long timeout = jiffies + HZ; | 561 | unsigned long timeout = jiffies + HZ; |
| 562 | u8 vgair1; | 562 | u8 vgair1; |
| @@ -645,7 +645,7 @@ static void ast_primary_plane_helper_atomic_update(struct drm_plane *plane, · 82 unmodified lines | |||
| 645 | struct drm_atomic_state *state) | 645 | struct drm_atomic_state *state) |
| 646 | { | 646 | { |
| 647 | struct drm_device *dev = plane->dev; | 647 | struct drm_device *dev = plane->dev; |
| 648 | struct ast_private *ast = to_ast_private(dev); | 648 | struct ast_device *ast = to_ast_device(dev); |
| 649 | struct drm_plane_state *plane_state = drm_atomic_get_new_plane_state(state, plane); | 649 | struct drm_plane_state *plane_state = drm_atomic_get_new_plane_state(state, plane); |
| 650 | struct drm_shadow_plane_state *shadow_plane_state = to_drm_shadow_plane_state(plane_state); | 650 | struct drm_shadow_plane_state *shadow_plane_state = to_drm_shadow_plane_state(plane_state); |
| 651 | struct drm_framebuffer *fb = plane_state->fb; | 651 | struct drm_framebuffer *fb = plane_state->fb; |
| @@ -672,23 +672,34 @@ static void ast_primary_plane_helper_atomic_update(struct drm_plane *plane, · 20 unmodified lines | |||
| 672 | 672 | ||
| 673 | /* | 673 | /* |
| 674 | * Some BMCs stop scanning out the video signal after the driver | 674 | * Some BMCs stop scanning out the video signal after the driver |
| 675 | * reprogrammed the offset or scanout address. This stalls display | 675 | * reprogrammed the offset. This stalls display output for several |
| 676 | * output for several seconds and makes the display unusable. | 676 | * seconds and makes the display unusable. Therefore only update |
| 677 | * Therefore only update the offset if it changes and reprogram the | 677 | * the offset if it changes. |
| 678 | * address after enabling the plane. | ||
| 679 | */ | 678 | */ |
| 680 | if (!old_fb || old_fb->pitches[0] != fb->pitches[0]) | 679 | if (!old_fb || old_fb->pitches[0] != fb->pitches[0]) |
| 681 | ast_set_offset_reg(ast, fb); | 680 | ast_set_offset_reg(ast, fb); |
| 682 | if (!old_fb) { | 681 | } |
| 683 | ast_set_start_address_crt1(ast, (u32)ast_plane->offset); | 682 | |
| 684 | ast_set_index_reg_mask(ast, AST_IO_SEQ_PORT, 0x1, 0xdf, 0x00); | 683 | static void ast_primary_plane_helper_atomic_enable(struct drm_plane *plane, |
| 685 | } | 684 | struct drm_atomic_state *state) |
| 685 | { | ||
| 686 | struct ast_device *ast = to_ast_device(plane->dev); | ||
| 687 | struct ast_plane *ast_plane = to_ast_plane(plane); | ||
| 688 | |||
| 689 | /* | ||
| 690 | * Some BMCs stop scanning out the video signal after the driver | ||
| 691 | * reprogrammed the scanout address. This stalls display | ||
| 692 | * output for several seconds and makes the display unusable. | ||
| 693 | * Therefore only reprogram the address after enabling the plane. | ||
| 694 | */ | ||
| 695 | ast_set_start_address_crt1(ast, (u32)ast_plane->offset); | ||
| 696 | ast_set_index_reg_mask(ast, AST_IO_SEQ_PORT, 0x1, 0xdf, 0x00); | ||
| 686 | } | 697 | } |
| 687 | 698 | ||
| 688 | static void ast_primary_plane_helper_atomic_disable(struct drm_plane *plane, | 699 | static void ast_primary_plane_helper_atomic_disable(struct drm_plane *plane, |
| 689 | struct drm_atomic_state *state) | 700 | struct drm_atomic_state *state) |
| 690 | { | 701 | { |
| 691 | struct ast_private *ast = to_ast_private(plane->dev); | 702 | struct ast_device *ast = to_ast_device(plane->dev); |
| 692 | 703 | ||
| 693 | ast_set_index_reg_mask(ast, AST_IO_SEQ_PORT, 0x1, 0xdf, 0x20); | 704 | ast_set_index_reg_mask(ast, AST_IO_SEQ_PORT, 0x1, 0xdf, 0x20); |
| 694 | } | 705 | } |
| @@ -697,6 +708,7 @@ static const struct drm_plane_helper_funcs ast_primary_plane_helper_funcs = { · 2 unmodified lines | |||
| 697 | DRM_GEM_SHADOW_PLANE_HELPER_FUNCS, | 708 | DRM_GEM_SHADOW_PLANE_HELPER_FUNCS, |
| 698 | .atomic_check = ast_primary_plane_helper_atomic_check, | 709 | .atomic_check = ast_primary_plane_helper_atomic_check, |
| 699 | .atomic_update = ast_primary_plane_helper_atomic_update, | 710 | .atomic_update = ast_primary_plane_helper_atomic_update, |
| 711 | .atomic_enable = ast_primary_plane_helper_atomic_enable, | ||
| 700 | .atomic_disable = ast_primary_plane_helper_atomic_disable, | 712 | .atomic_disable = ast_primary_plane_helper_atomic_disable, |
| 701 | }; | 713 | }; |
| 702 | 714 | ||
| @@ -707,7 +719,7 @@ static const struct drm_plane_funcs ast_primary_plane_funcs = { · 4 unmodified lines | |||
| 707 | DRM_GEM_SHADOW_PLANE_FUNCS, | 719 | DRM_GEM_SHADOW_PLANE_FUNCS, |
| 708 | }; | 720 | }; |
| 709 | 721 | ||
| 710 | static int ast_primary_plane_init(struct ast_private *ast) | 722 | static int ast_primary_plane_init(struct ast_device *ast) |
| 711 | { | 723 | { |
| 712 | struct drm_device *dev = &ast->base; | 724 | struct drm_device *dev = &ast->base; |
| 713 | struct ast_plane *ast_primary_plane = &ast->primary_plane; | 725 | struct ast_plane *ast_primary_plane = &ast->primary_plane; |
| @@ -800,7 +812,7 @@ static void ast_update_cursor_image(u8 __iomem *dst, const u8 *src, int width, i · 86 unmodified lines | |||
| 800 | writel(0, dst + AST_HWC_SIGNATURE_HOTSPOTY); | 812 | writel(0, dst + AST_HWC_SIGNATURE_HOTSPOTY); |
| 801 | } | 813 | } |
| 802 | 814 | ||
| 803 | static void ast_set_cursor_base(struct ast_private *ast, u64 address) | 815 | static void ast_set_cursor_base(struct ast_device *ast, u64 address) |
| 804 | { | 816 | { |
| 805 | u8 addr0 = (address >> 3) & 0xff; | 817 | u8 addr0 = (address >> 3) & 0xff; |
| 806 | u8 addr1 = (address >> 11) & 0xff; | 818 | u8 addr1 = (address >> 11) & 0xff; |
| @@ -811,7 +823,7 @@ static void ast_set_cursor_base(struct ast_private *ast, u64 address) · 4 unmodified lines | |||
| 811 | ast_set_index_reg(ast, AST_IO_CRTC_PORT, 0xca, addr2); | 823 | ast_set_index_reg(ast, AST_IO_CRTC_PORT, 0xca, addr2); |
| 812 | } | 824 | } |
| 813 | 825 | ||
| 814 | static void ast_set_cursor_location(struct ast_private *ast, u16 x, u16 y, | 826 | static void ast_set_cursor_location(struct ast_device *ast, u16 x, u16 y, |
| 815 | u8 x_offset, u8 y_offset) | 827 | u8 x_offset, u8 y_offset) |
| 816 | { | 828 | { |
| 817 | u8 x0 = (x & 0x00ff); | 829 | u8 x0 = (x & 0x00ff); |
| @@ -827,7 +839,7 @@ static void ast_set_cursor_location(struct ast_private *ast, u16 x, u16 y, · 9 unmodified lines | |||
| 827 | ast_set_index_reg(ast, AST_IO_CRTC_PORT, 0xc7, y1); | 839 | ast_set_index_reg(ast, AST_IO_CRTC_PORT, 0xc7, y1); |
| 828 | } | 840 | } |
| 829 | 841 | ||
| 830 | static void ast_set_cursor_enabled(struct ast_private *ast, bool enabled) | 842 | static void ast_set_cursor_enabled(struct ast_device *ast, bool enabled) |
| 831 | { | 843 | { |
| 832 | static const u8 mask = (u8)~(AST_IO_VGACRCB_HWC_16BPP | | 844 | static const u8 mask = (u8)~(AST_IO_VGACRCB_HWC_16BPP | |
| 833 | AST_IO_VGACRCB_HWC_ENABLED); | 845 | AST_IO_VGACRCB_HWC_ENABLED); |
| @@ -876,7 +888,7 @@ static void ast_cursor_plane_helper_atomic_update(struct drm_plane *plane, · 42 unmodified lines | |||
| 876 | struct drm_shadow_plane_state *shadow_plane_state = to_drm_shadow_plane_state(plane_state); | 888 | struct drm_shadow_plane_state *shadow_plane_state = to_drm_shadow_plane_state(plane_state); |
| 877 | struct drm_framebuffer *fb = plane_state->fb; | 889 | struct drm_framebuffer *fb = plane_state->fb; |
| 878 | struct drm_plane_state *old_plane_state = drm_atomic_get_old_plane_state(state, plane); | 890 | struct drm_plane_state *old_plane_state = drm_atomic_get_old_plane_state(state, plane); |
| 879 | struct ast_private *ast = to_ast_private(plane->dev); | 891 | struct ast_device *ast = to_ast_device(plane->dev); |
| 880 | struct iosys_map src_map = shadow_plane_state->data[0]; | 892 | struct iosys_map src_map = shadow_plane_state->data[0]; |
| 881 | struct drm_rect damage; | 893 | struct drm_rect damage; |
| 882 | const u8 *src = src_map.vaddr; /* TODO: Use mapping abstraction properly */ | 894 | const u8 *src = src_map.vaddr; /* TODO: Use mapping abstraction properly */ |
| @@ -931,7 +943,7 @@ static void ast_cursor_plane_helper_atomic_update(struct drm_plane *plane, · 48 unmodified lines | |||
| 931 | static void ast_cursor_plane_helper_atomic_disable(struct drm_plane *plane, | 943 | static void ast_cursor_plane_helper_atomic_disable(struct drm_plane *plane, |
| 932 | struct drm_atomic_state *state) | 944 | struct drm_atomic_state *state) |
| 933 | { | 945 | { |
| 934 | struct ast_private *ast = to_ast_private(plane->dev); | 946 | struct ast_device *ast = to_ast_device(plane->dev); |
| 935 | 947 | ||
| 936 | ast_set_cursor_enabled(ast, false); | 948 | ast_set_cursor_enabled(ast, false); |
| 937 | } | 949 | } |
| @@ -950,7 +962,7 @@ static const struct drm_plane_funcs ast_cursor_plane_funcs = { · 12 unmodified lines | |||
| 950 | DRM_GEM_SHADOW_PLANE_FUNCS, | 962 | DRM_GEM_SHADOW_PLANE_FUNCS, |
| 951 | }; | 963 | }; |
| 952 | 964 | ||
| 953 | static int ast_cursor_plane_init(struct ast_private *ast) | 965 | static int ast_cursor_plane_init(struct ast_device *ast) |
| 954 | { | 966 | { |
| 955 | struct drm_device *dev = &ast->base; | 967 | struct drm_device *dev = &ast->base; |
| 956 | struct ast_plane *ast_cursor_plane = &ast->cursor_plane; | 968 | struct ast_plane *ast_cursor_plane = &ast->cursor_plane; |
| @@ -995,7 +1007,7 @@ static int ast_cursor_plane_init(struct ast_private *ast) · 38 unmodified lines | |||
| 995 | 1007 | ||
| 996 | static void ast_crtc_dpms(struct drm_crtc *crtc, int mode) | 1008 | static void ast_crtc_dpms(struct drm_crtc *crtc, int mode) |
| 997 | { | 1009 | { |
| 998 | struct ast_private *ast = to_ast_private(crtc->dev); | 1010 | struct ast_device *ast = to_ast_device(crtc->dev); |
| 999 | u8 ch = AST_DPMS_VSYNC_OFF | AST_DPMS_HSYNC_OFF; | 1011 | u8 ch = AST_DPMS_VSYNC_OFF | AST_DPMS_HSYNC_OFF; |
| 1000 | struct ast_crtc_state *ast_state; | 1012 | struct ast_crtc_state *ast_state; |
| 1001 | const struct drm_format_info *format; | 1013 | const struct drm_format_info *format; |
| @@ -1052,7 +1064,7 @@ static void ast_crtc_dpms(struct drm_crtc *crtc, int mode) · 50 unmodified lines | |||
| 1052 | static enum drm_mode_status | 1064 | static enum drm_mode_status |
| 1053 | ast_crtc_helper_mode_valid(struct drm_crtc *crtc, const struct drm_display_mode *mode) | 1065 | ast_crtc_helper_mode_valid(struct drm_crtc *crtc, const struct drm_display_mode *mode) |
| 1054 | { | 1066 | { |
| 1055 | struct ast_private *ast = to_ast_private(crtc->dev); | 1067 | struct ast_device *ast = to_ast_device(crtc->dev); |
| 1056 | enum drm_mode_status status; | 1068 | enum drm_mode_status status; |
| 1057 | uint32_t jtemp; | 1069 | uint32_t jtemp; |
| 1058 | 1070 | ||
| @@ -1177,7 +1189,7 @@ ast_crtc_helper_atomic_flush(struct drm_crtc *crtc, · 118 unmodified lines | |||
| 1177 | struct drm_crtc_state *crtc_state = drm_atomic_get_new_crtc_state(state, | 1189 | struct drm_crtc_state *crtc_state = drm_atomic_get_new_crtc_state(state, |
| 1178 | crtc); | 1190 | crtc); |
| 1179 | struct drm_device *dev = crtc->dev; | 1191 | struct drm_device *dev = crtc->dev; |
| 1180 | struct ast_private *ast = to_ast_private(dev); | 1192 | struct ast_device *ast = to_ast_device(dev); |
| 1181 | struct ast_crtc_state *ast_crtc_state = to_ast_crtc_state(crtc_state); | 1193 | struct ast_crtc_state *ast_crtc_state = to_ast_crtc_state(crtc_state); |
| 1182 | struct ast_vbios_mode_info *vbios_mode_info = &ast_crtc_state->vbios_mode_info; | 1194 | struct ast_vbios_mode_info *vbios_mode_info = &ast_crtc_state->vbios_mode_info; |
| 1183 | 1195 | ||
| @@ -1202,7 +1214,7 @@ ast_crtc_helper_atomic_flush(struct drm_crtc *crtc, · 18 unmodified lines | |||
| 1202 | static void ast_crtc_helper_atomic_enable(struct drm_crtc *crtc, struct drm_atomic_state *state) | 1214 | static void ast_crtc_helper_atomic_enable(struct drm_crtc *crtc, struct drm_atomic_state *state) |
| 1203 | { | 1215 | { |
| 1204 | struct drm_device *dev = crtc->dev; | 1216 | struct drm_device *dev = crtc->dev; |
| 1205 | struct ast_private *ast = to_ast_private(dev); | 1217 | struct ast_device *ast = to_ast_device(dev); |
| 1206 | struct drm_crtc_state *crtc_state = drm_atomic_get_new_crtc_state(state, crtc); | 1218 | struct drm_crtc_state *crtc_state = drm_atomic_get_new_crtc_state(state, crtc); |
| 1207 | struct ast_crtc_state *ast_crtc_state = to_ast_crtc_state(crtc_state); | 1219 | struct ast_crtc_state *ast_crtc_state = to_ast_crtc_state(crtc_state); |
| 1208 | struct ast_vbios_mode_info *vbios_mode_info = | 1220 | struct ast_vbios_mode_info *vbios_mode_info = |
| @@ -1224,7 +1236,7 @@ static void ast_crtc_helper_atomic_disable(struct drm_crtc *crtc, struct drm_ato · 15 unmodified lines | |||
| 1224 | { | 1236 | { |
| 1225 | struct drm_crtc_state *old_crtc_state = drm_atomic_get_old_crtc_state(state, crtc); | 1237 | struct drm_crtc_state *old_crtc_state = drm_atomic_get_old_crtc_state(state, crtc); |
| 1226 | struct drm_device *dev = crtc->dev; | 1238 | struct drm_device *dev = crtc->dev; |
| 1227 | struct ast_private *ast = to_ast_private(dev); | 1239 | struct ast_device *ast = to_ast_device(dev); |
| 1228 | 1240 | ||
| 1229 | ast_crtc_dpms(crtc, DRM_MODE_DPMS_OFF); | 1241 | ast_crtc_dpms(crtc, DRM_MODE_DPMS_OFF); |
| 1230 | 1242 | ||
| @@ -1312,7 +1324,7 @@ static const struct drm_crtc_funcs ast_crtc_funcs = { · 81 unmodified lines | |||
| 1312 | 1324 | ||
| 1313 | static int ast_crtc_init(struct drm_device *dev) | 1325 | static int ast_crtc_init(struct drm_device *dev) |
| 1314 | { | 1326 | { |
| 1315 | struct ast_private *ast = to_ast_private(dev); | 1327 | struct ast_device *ast = to_ast_device(dev); |
| 1316 | struct drm_crtc *crtc = &ast->crtc; | 1328 | struct drm_crtc *crtc = &ast->crtc; |
| 1317 | int ret; | 1329 | int ret; |
| 1318 | 1330 | ||
| @@ -1338,7 +1350,7 @@ static int ast_vga_connector_helper_get_modes(struct drm_connector *connector) · 19 unmodified lines | |||
| 1338 | { | 1350 | { |
| 1339 | struct ast_vga_connector *ast_vga_connector = to_ast_vga_connector(connector); | 1351 | struct ast_vga_connector *ast_vga_connector = to_ast_vga_connector(connector); |
| 1340 | struct drm_device *dev = connector->dev; | 1352 | struct drm_device *dev = connector->dev; |
| 1341 | struct ast_private *ast = to_ast_private(dev); | 1353 | struct ast_device *ast = to_ast_device(dev); |
| 1342 | struct edid *edid; | 1354 | struct edid *edid; |
| 1343 | int count; | 1355 | int count; |
| 1344 | 1356 | ||
| @@ -1411,7 +1423,7 @@ static int ast_vga_connector_init(struct drm_device *dev, · 66 unmodified lines | |||
| 1411 | return 0; | 1423 | return 0; |
| 1412 | } | 1424 | } |
| 1413 | 1425 | ||
| 1414 | static int ast_vga_output_init(struct ast_private *ast) | 1426 | static int ast_vga_output_init(struct ast_device *ast) |
| 1415 | { | 1427 | { |
| 1416 | struct drm_device *dev = &ast->base; | 1428 | struct drm_device *dev = &ast->base; |
| 1417 | struct drm_crtc *crtc = &ast->crtc; | 1429 | struct drm_crtc *crtc = &ast->crtc; |
| @@ -1444,7 +1456,7 @@ static int ast_sil164_connector_helper_get_modes(struct drm_connector *connector · 26 unmodified lines | |||
| 1444 | { | 1456 | { |
| 1445 | struct ast_sil164_connector *ast_sil164_connector = to_ast_sil164_connector(connector); | 1457 | struct ast_sil164_connector *ast_sil164_connector = to_ast_sil164_connector(connector); |
| 1446 | struct drm_device *dev = connector->dev; | 1458 | struct drm_device *dev = connector->dev; |
| 1447 | struct ast_private *ast = to_ast_private(dev); | 1459 | struct ast_device *ast = to_ast_device(dev); |
| 1448 | struct edid *edid; | 1460 | struct edid *edid; |
| 1449 | int count; | 1461 | int count; |
| 1450 | 1462 | ||
| @@ -1517,7 +1529,7 @@ static int ast_sil164_connector_init(struct drm_device *dev, · 66 unmodified lines | |||
| 1517 | return 0; | 1529 | return 0; |
| 1518 | } | 1530 | } |
| 1519 | 1531 | ||
| 1520 | static int ast_sil164_output_init(struct ast_private *ast) | 1532 | static int ast_sil164_output_init(struct ast_device *ast) |
| 1521 | { | 1533 | { |
| 1522 | struct drm_device *dev = &ast->base; | 1534 | struct drm_device *dev = &ast->base; |
| 1523 | struct drm_crtc *crtc = &ast->crtc; | 1535 | struct drm_crtc *crtc = &ast->crtc; |
| @@ -1604,7 +1616,7 @@ static int ast_dp501_connector_init(struct drm_device *dev, struct drm_connector · 80 unmodified lines | |||
| 1604 | return 0; | 1616 | return 0; |
| 1605 | } | 1617 | } |
| 1606 | 1618 | ||
| 1607 | static int ast_dp501_output_init(struct ast_private *ast) | 1619 | static int ast_dp501_output_init(struct ast_device *ast) |
| 1608 | { | 1620 | { |
| 1609 | struct drm_device *dev = &ast->base; | 1621 | struct drm_device *dev = &ast->base; |
| 1610 | struct drm_crtc *crtc = &ast->crtc; | 1622 | struct drm_crtc *crtc = &ast->crtc; |
| @@ -1691,7 +1703,7 @@ static int ast_astdp_connector_init(struct drm_device *dev, struct drm_connector · 80 unmodified lines | |||
| 1691 | return 0; | 1703 | return 0; |
| 1692 | } | 1704 | } |
| 1693 | 1705 | ||
| 1694 | static int ast_astdp_output_init(struct ast_private *ast) | 1706 | static int ast_astdp_output_init(struct ast_device *ast) |
| 1695 | { | 1707 | { |
| 1696 | struct drm_device *dev = &ast->base; | 1708 | struct drm_device *dev = &ast->base; |
| 1697 | struct drm_crtc *crtc = &ast->crtc; | 1709 | struct drm_crtc *crtc = &ast->crtc; |
| @@ -1721,7 +1733,7 @@ static int ast_astdp_output_init(struct ast_private *ast) · 23 unmodified lines | |||
| 1721 | 1733 | ||
| 1722 | static void ast_mode_config_helper_atomic_commit_tail(struct drm_atomic_state *state) | 1734 | static void ast_mode_config_helper_atomic_commit_tail(struct drm_atomic_state *state) |
| 1723 | { | 1735 | { |
| 1724 | struct ast_private *ast = to_ast_private(state->dev); | 1736 | struct ast_device *ast = to_ast_device(state->dev); |
| 1725 | 1737 | ||
| 1726 | /* | 1738 | /* |
| 1727 | * Concurrent operations could possibly trigger a call to | 1739 | * Concurrent operations could possibly trigger a call to |
| @@ -1742,7 +1754,7 @@ static enum drm_mode_status ast_mode_config_mode_valid(struct drm_device *dev, · 14 unmodified lines | |||
| 1742 | const struct drm_display_mode *mode) | 1754 | const struct drm_display_mode *mode) |
| 1743 | { | 1755 | { |
| 1744 | static const unsigned long max_bpp = 4; /* DRM_FORMAT_XRGB8888 */ | 1756 | static const unsigned long max_bpp = 4; /* DRM_FORMAT_XRGB8888 */ |
| 1745 | struct ast_private *ast = to_ast_private(dev); | 1757 | struct ast_device *ast = to_ast_device(dev); |
| 1746 | unsigned long fbsize, fbpages, max_fbpages; | 1758 | unsigned long fbsize, fbpages, max_fbpages; |
| 1747 | 1759 | ||
| 1748 | max_fbpages = (ast->vram_fb_available) >> PAGE_SHIFT; | 1760 | max_fbpages = (ast->vram_fb_available) >> PAGE_SHIFT; |
| @@ -1763,7 +1775,7 @@ static const struct drm_mode_config_funcs ast_mode_config_funcs = { · 14 unmodified lines | |||
| 1763 | .atomic_commit = drm_atomic_helper_commit, | 1775 | .atomic_commit = drm_atomic_helper_commit, |
| 1764 | }; | 1776 | }; |
| 1765 | 1777 | ||
| 1766 | int ast_mode_config_init(struct ast_private *ast) | 1778 | int ast_mode_config_init(struct ast_device *ast) |
| 1767 | { | 1779 | { |
| 1768 | struct drm_device *dev = &ast->base; | 1780 | struct drm_device *dev = &ast->base; |
| 1769 | int ret; | 1781 | int ret; |
| @@ -39,7 +39,7 @@ static void ast_post_chip_2500(struct drm_device *dev); · 38 unmodified lines | |||
| 39 | 39 | ||
| 40 | void ast_enable_vga(struct drm_device *dev) | 40 | void ast_enable_vga(struct drm_device *dev) |
| 41 | { | 41 | { |
| 42 | struct ast_private *ast = to_ast_private(dev); | 42 | struct ast_device *ast = to_ast_device(dev); |
| 43 | 43 | ||
| 44 | ast_io_write8(ast, AST_IO_VGA_ENABLE_PORT, 0x01); | 44 | ast_io_write8(ast, AST_IO_VGA_ENABLE_PORT, 0x01); |
| 45 | ast_io_write8(ast, AST_IO_MISC_PORT_WRITE, 0x01); | 45 | ast_io_write8(ast, AST_IO_MISC_PORT_WRITE, 0x01); |
| @@ -47,7 +47,7 @@ void ast_enable_vga(struct drm_device *dev) · 1 unmodified line | |||
| 47 | 47 | ||
| 48 | void ast_enable_mmio(struct drm_device *dev) | 48 | void ast_enable_mmio(struct drm_device *dev) |
| 49 | { | 49 | { |
| 50 | struct ast_private *ast = to_ast_private(dev); | 50 | struct ast_device *ast = to_ast_device(dev); |
| 51 | 51 | ||
| 52 | ast_set_index_reg(ast, AST_IO_CRTC_PORT, 0xa1, 0x06); | 52 | ast_set_index_reg(ast, AST_IO_CRTC_PORT, 0xa1, 0x06); |
| 53 | } | 53 | } |
| @@ -55,7 +55,7 @@ void ast_enable_mmio(struct drm_device *dev) · 1 unmodified line | |||
| 55 | 55 | ||
| 56 | bool ast_is_vga_enabled(struct drm_device *dev) | 56 | bool ast_is_vga_enabled(struct drm_device *dev) |
| 57 | { | 57 | { |
| 58 | struct ast_private *ast = to_ast_private(dev); | 58 | struct ast_device *ast = to_ast_device(dev); |
| 59 | u8 ch; | 59 | u8 ch; |
| 60 | 60 | ||
| 61 | ch = ast_io_read8(ast, AST_IO_VGA_ENABLE_PORT); | 61 | ch = ast_io_read8(ast, AST_IO_VGA_ENABLE_PORT); |
| @@ -70,7 +70,7 @@ static const u8 extreginfo_ast2300[] = { 0x0f, 0x04, 0x1f, 0xff }; · 8 unmodified lines | |||
| 70 | static void | 70 | static void |
| 71 | ast_set_def_ext_reg(struct drm_device *dev) | 71 | ast_set_def_ext_reg(struct drm_device *dev) |
| 72 | { | 72 | { |
| 73 | struct ast_private *ast = to_ast_private(dev); | 73 | struct ast_device *ast = to_ast_device(dev); |
| 74 | struct pci_dev *pdev = to_pci_dev(dev->dev); | 74 | struct pci_dev *pdev = to_pci_dev(dev->dev); |
| 75 | u8 i, index, reg; | 75 | u8 i, index, reg; |
| 76 | const u8 *ext_reg_info; | 76 | const u8 *ext_reg_info; |
| @@ -110,7 +110,7 @@ ast_set_def_ext_reg(struct drm_device *dev) · 33 unmodified lines | |||
| 110 | ast_set_index_reg_mask(ast, AST_IO_CRTC_PORT, 0xb6, 0xff, reg); | 110 | ast_set_index_reg_mask(ast, AST_IO_CRTC_PORT, 0xb6, 0xff, reg); |
| 111 | } | 111 | } |
| 112 | 112 | ||
| 113 | u32 ast_mindwm(struct ast_private *ast, u32 r) | 113 | u32 ast_mindwm(struct ast_device *ast, u32 r) |
| 114 | { | 114 | { |
| 115 | uint32_t data; | 115 | uint32_t data; |
| 116 | 116 | ||
| @@ -123,7 +123,7 @@ u32 ast_mindwm(struct ast_private *ast, u32 r) · 6 unmodified lines | |||
| 123 | return ast_read32(ast, 0x10000 + (r & 0x0000ffff)); | 123 | return ast_read32(ast, 0x10000 + (r & 0x0000ffff)); |
| 124 | } | 124 | } |
| 125 | 125 | ||
| 126 | void ast_moutdwm(struct ast_private *ast, u32 r, u32 v) | 126 | void ast_moutdwm(struct ast_device *ast, u32 r, u32 v) |
| 127 | { | 127 | { |
| 128 | uint32_t data; | 128 | uint32_t data; |
| 129 | ast_write32(ast, 0xf004, r & 0xffff0000); | 129 | ast_write32(ast, 0xf004, r & 0xffff0000); |
| @@ -162,7 +162,7 @@ static const u32 pattern_AST2150[14] = { · 32 unmodified lines | |||
| 162 | 0x20F050E0 | 162 | 0x20F050E0 |
| 163 | }; | 163 | }; |
| 164 | 164 | ||
| 165 | static u32 mmctestburst2_ast2150(struct ast_private *ast, u32 datagen) | 165 | static u32 mmctestburst2_ast2150(struct ast_device *ast, u32 datagen) |
| 166 | { | 166 | { |
| 167 | u32 data, timeout; | 167 | u32 data, timeout; |
| 168 | 168 | ||
| @@ -192,7 +192,7 @@ static u32 mmctestburst2_ast2150(struct ast_private *ast, u32 datagen) · 23 unmodified lines | |||
| 192 | } | 192 | } |
| 193 | 193 | ||
| 194 | #if 0 /* unused in DDX driver - here for completeness */ | 194 | #if 0 /* unused in DDX driver - here for completeness */ |
| 195 | static u32 mmctestsingle2_ast2150(struct ast_private *ast, u32 datagen) | 195 | static u32 mmctestsingle2_ast2150(struct ast_device *ast, u32 datagen) |
| 196 | { | 196 | { |
| 197 | u32 data, timeout; | 197 | u32 data, timeout; |
| 198 | 198 | ||
| @@ -212,7 +212,7 @@ static u32 mmctestsingle2_ast2150(struct ast_private *ast, u32 datagen) · 13 unmodified lines | |||
| 212 | } | 212 | } |
| 213 | #endif | 213 | #endif |
| 214 | 214 | ||
| 215 | static int cbrtest_ast2150(struct ast_private *ast) | 215 | static int cbrtest_ast2150(struct ast_device *ast) |
| 216 | { | 216 | { |
| 217 | int i; | 217 | int i; |
| 218 | 218 | ||
| @@ -222,7 +222,7 @@ static int cbrtest_ast2150(struct ast_private *ast) · 3 unmodified lines | |||
| 222 | return 1; | 222 | return 1; |
| 223 | } | 223 | } |
| 224 | 224 | ||
| 225 | static int cbrscan_ast2150(struct ast_private *ast, int busw) | 225 | static int cbrscan_ast2150(struct ast_device *ast, int busw) |
| 226 | { | 226 | { |
| 227 | u32 patcnt, loop; | 227 | u32 patcnt, loop; |
| 228 | 228 | ||
| @@ -239,7 +239,7 @@ static int cbrscan_ast2150(struct ast_private *ast, int busw) · 10 unmodified lines | |||
| 239 | } | 239 | } |
| 240 | 240 | ||
| 241 | 241 | ||
| 242 | static void cbrdlli_ast2150(struct ast_private *ast, int busw) | 242 | static void cbrdlli_ast2150(struct ast_device *ast, int busw) |
| 243 | { | 243 | { |
| 244 | u32 dll_min[4], dll_max[4], dlli, data, passcnt; | 244 | u32 dll_min[4], dll_max[4], dlli, data, passcnt; |
| 245 | 245 | ||
| @@ -273,7 +273,7 @@ cbr_start: · 27 unmodified lines | |||
| 273 | 273 | ||
| 274 | static void ast_init_dram_reg(struct drm_device *dev) | 274 | static void ast_init_dram_reg(struct drm_device *dev) |
| 275 | { | 275 | { |
| 276 | struct ast_private *ast = to_ast_private(dev); | 276 | struct ast_device *ast = to_ast_device(dev); |
| 277 | u8 j; | 277 | u8 j; |
| 278 | u32 data, temp, i; | 278 | u32 data, temp, i; |
| 279 | const struct ast_dramstruct *dram_reg_info; | 279 | const struct ast_dramstruct *dram_reg_info; |
| @@ -366,7 +366,7 @@ static void ast_init_dram_reg(struct drm_device *dev) · 86 unmodified lines | |||
| 366 | 366 | ||
| 367 | void ast_post_gpu(struct drm_device *dev) | 367 | void ast_post_gpu(struct drm_device *dev) |
| 368 | { | 368 | { |
| 369 | struct ast_private *ast = to_ast_private(dev); | 369 | struct ast_device *ast = to_ast_device(dev); |
| 370 | struct pci_dev *pdev = to_pci_dev(dev->dev); | 370 | struct pci_dev *pdev = to_pci_dev(dev->dev); |
| 371 | u32 reg; | 371 | u32 reg; |
| 372 | 372 | ||
| @@ -449,7 +449,7 @@ static const u32 pattern[8] = { · 76 unmodified lines | |||
| 449 | 0x7C61D253 | 449 | 0x7C61D253 |
| 450 | }; | 450 | }; |
| 451 | 451 | ||
| 452 | static bool mmc_test(struct ast_private *ast, u32 datagen, u8 test_ctl) | 452 | static bool mmc_test(struct ast_device *ast, u32 datagen, u8 test_ctl) |
| 453 | { | 453 | { |
| 454 | u32 data, timeout; | 454 | u32 data, timeout; |
| 455 | 455 | ||
| @@ -469,7 +469,7 @@ static bool mmc_test(struct ast_private *ast, u32 datagen, u8 test_ctl) · 13 unmodified lines | |||
| 469 | return true; | 469 | return true; |
| 470 | } | 470 | } |
| 471 | 471 | ||
| 472 | static u32 mmc_test2(struct ast_private *ast, u32 datagen, u8 test_ctl) | 472 | static u32 mmc_test2(struct ast_device *ast, u32 datagen, u8 test_ctl) |
| 473 | { | 473 | { |
| 474 | u32 data, timeout; | 474 | u32 data, timeout; |
| 475 | 475 | ||
| @@ -490,32 +490,32 @@ static u32 mmc_test2(struct ast_private *ast, u32 datagen, u8 test_ctl) · 14 unmodified lines | |||
| 490 | } | 490 | } |
| 491 | 491 | ||
| 492 | 492 | ||
| 493 | static bool mmc_test_burst(struct ast_private *ast, u32 datagen) | 493 | static bool mmc_test_burst(struct ast_device *ast, u32 datagen) |
| 494 | { | 494 | { |
| 495 | return mmc_test(ast, datagen, 0xc1); | 495 | return mmc_test(ast, datagen, 0xc1); |
| 496 | } | 496 | } |
| 497 | 497 | ||
| 498 | static u32 mmc_test_burst2(struct ast_private *ast, u32 datagen) | 498 | static u32 mmc_test_burst2(struct ast_device *ast, u32 datagen) |
| 499 | { | 499 | { |
| 500 | return mmc_test2(ast, datagen, 0x41); | 500 | return mmc_test2(ast, datagen, 0x41); |
| 501 | } | 501 | } |
| 502 | 502 | ||
| 503 | static bool mmc_test_single(struct ast_private *ast, u32 datagen) | 503 | static bool mmc_test_single(struct ast_device *ast, u32 datagen) |
| 504 | { | 504 | { |
| 505 | return mmc_test(ast, datagen, 0xc5); | 505 | return mmc_test(ast, datagen, 0xc5); |
| 506 | } | 506 | } |
| 507 | 507 | ||
| 508 | static u32 mmc_test_single2(struct ast_private *ast, u32 datagen) | 508 | static u32 mmc_test_single2(struct ast_device *ast, u32 datagen) |
| 509 | { | 509 | { |
| 510 | return mmc_test2(ast, datagen, 0x05); | 510 | return mmc_test2(ast, datagen, 0x05); |
| 511 | } | 511 | } |
| 512 | 512 | ||
| 513 | static bool mmc_test_single_2500(struct ast_private *ast, u32 datagen) | 513 | static bool mmc_test_single_2500(struct ast_device *ast, u32 datagen) |
| 514 | { | 514 | { |
| 515 | return mmc_test(ast, datagen, 0x85); | 515 | return mmc_test(ast, datagen, 0x85); |
| 516 | } | 516 | } |
| 517 | 517 | ||
| 518 | static int cbr_test(struct ast_private *ast) | 518 | static int cbr_test(struct ast_device *ast) |
| 519 | { | 519 | { |
| 520 | u32 data; | 520 | u32 data; |
| 521 | int i; | 521 | int i; |
| @@ -534,7 +534,7 @@ static int cbr_test(struct ast_private *ast) · 12 unmodified lines | |||
| 534 | return 1; | 534 | return 1; |
| 535 | } | 535 | } |
| 536 | 536 | ||
| 537 | static int cbr_scan(struct ast_private *ast) | 537 | static int cbr_scan(struct ast_device *ast) |
| 538 | { | 538 | { |
| 539 | u32 data, data2, patcnt, loop; | 539 | u32 data, data2, patcnt, loop; |
| 540 | 540 | ||
| @@ -555,7 +555,7 @@ static int cbr_scan(struct ast_private *ast) · 14 unmodified lines | |||
| 555 | return data2; | 555 | return data2; |
| 556 | } | 556 | } |
| 557 | 557 | ||
| 558 | static u32 cbr_test2(struct ast_private *ast) | 558 | static u32 cbr_test2(struct ast_device *ast) |
| 559 | { | 559 | { |
| 560 | u32 data; | 560 | u32 data; |
| 561 | 561 | ||
| @@ -569,7 +569,7 @@ static u32 cbr_test2(struct ast_private *ast) · 7 unmodified lines | |||
| 569 | return ~data & 0xffff; | 569 | return ~data & 0xffff; |
| 570 | } | 570 | } |
| 571 | 571 | ||
| 572 | static u32 cbr_scan2(struct ast_private *ast) | 572 | static u32 cbr_scan2(struct ast_device *ast) |
| 573 | { | 573 | { |
| 574 | u32 data, data2, patcnt, loop; | 574 | u32 data, data2, patcnt, loop; |
| 575 | 575 | ||
| @@ -590,7 +590,7 @@ static u32 cbr_scan2(struct ast_private *ast) · 14 unmodified lines | |||
| 590 | return data2; | 590 | return data2; |
| 591 | } | 591 | } |
| 592 | 592 | ||
| 593 | static bool cbr_test3(struct ast_private *ast) | 593 | static bool cbr_test3(struct ast_device *ast) |
| 594 | { | 594 | { |
| 595 | if (!mmc_test_burst(ast, 0)) | 595 | if (!mmc_test_burst(ast, 0)) |
| 596 | return false; | 596 | return false; |
| @@ -599,7 +599,7 @@ static bool cbr_test3(struct ast_private *ast) · 2 unmodified lines | |||
| 599 | return true; | 599 | return true; |
| 600 | } | 600 | } |
| 601 | 601 | ||
| 602 | static bool cbr_scan3(struct ast_private *ast) | 602 | static bool cbr_scan3(struct ast_device *ast) |
| 603 | { | 603 | { |
| 604 | u32 patcnt, loop; | 604 | u32 patcnt, loop; |
| 605 | 605 | ||
| @@ -615,7 +615,7 @@ static bool cbr_scan3(struct ast_private *ast) · 9 unmodified lines | |||
| 615 | return true; | 615 | return true; |
| 616 | } | 616 | } |
| 617 | 617 | ||
| 618 | static bool finetuneDQI_L(struct ast_private *ast, struct ast2300_dram_param *param) | 618 | static bool finetuneDQI_L(struct ast_device *ast, struct ast2300_dram_param *param) |
| 619 | { | 619 | { |
| 620 | u32 gold_sadj[2], dllmin[16], dllmax[16], dlli, data, cnt, mask, passcnt, retry = 0; | 620 | u32 gold_sadj[2], dllmin[16], dllmax[16], dlli, data, cnt, mask, passcnt, retry = 0; |
| 621 | bool status = false; | 621 | bool status = false; |
| @@ -714,7 +714,7 @@ FINETUNE_DONE: · 92 unmodified lines | |||
| 714 | return status; | 714 | return status; |
| 715 | } /* finetuneDQI_L */ | 715 | } /* finetuneDQI_L */ |
| 716 | 716 | ||
| 717 | static void finetuneDQSI(struct ast_private *ast) | 717 | static void finetuneDQSI(struct ast_device *ast) |
| 718 | { | 718 | { |
| 719 | u32 dlli, dqsip, dqidly; | 719 | u32 dlli, dqsip, dqidly; |
| 720 | u32 reg_mcr18, reg_mcr0c, passcnt[2], diff; | 720 | u32 reg_mcr18, reg_mcr0c, passcnt[2], diff; |
| @@ -804,7 +804,7 @@ static void finetuneDQSI(struct ast_private *ast) · 83 unmodified lines | |||
| 804 | ast_moutdwm(ast, 0x1E6E0018, reg_mcr18); | 804 | ast_moutdwm(ast, 0x1E6E0018, reg_mcr18); |
| 805 | 805 | ||
| 806 | } | 806 | } |
| 807 | static bool cbr_dll2(struct ast_private *ast, struct ast2300_dram_param *param) | 807 | static bool cbr_dll2(struct ast_device *ast, struct ast2300_dram_param *param) |
| 808 | { | 808 | { |
| 809 | u32 dllmin[2], dllmax[2], dlli, data, passcnt, retry = 0; | 809 | u32 dllmin[2], dllmax[2], dlli, data, passcnt, retry = 0; |
| 810 | bool status = false; | 810 | bool status = false; |
| @@ -860,7 +860,7 @@ CBR_DONE2: · 49 unmodified lines | |||
| 860 | return status; | 860 | return status; |
| 861 | } /* CBRDLL2 */ | 861 | } /* CBRDLL2 */ |
| 862 | 862 | ||
| 863 | static void get_ddr3_info(struct ast_private *ast, struct ast2300_dram_param *param) | 863 | static void get_ddr3_info(struct ast_device *ast, struct ast2300_dram_param *param) |
| 864 | { | 864 | { |
| 865 | u32 trap, trap_AC2, trap_MRS; | 865 | u32 trap, trap_AC2, trap_MRS; |
| 866 | 866 | ||
| @@ -1102,7 +1102,7 @@ static void get_ddr3_info(struct ast_private *ast, struct ast2300_dram_param *pa · 235 unmodified lines | |||
| 1102 | 1102 | ||
| 1103 | } | 1103 | } |
| 1104 | 1104 | ||
| 1105 | static void ddr3_init(struct ast_private *ast, struct ast2300_dram_param *param) | 1105 | static void ddr3_init(struct ast_device *ast, struct ast2300_dram_param *param) |
| 1106 | { | 1106 | { |
| 1107 | u32 data, data2, retry = 0; | 1107 | u32 data, data2, retry = 0; |
| 1108 | 1108 | ||
| @@ -1225,7 +1225,7 @@ ddr3_init_start: · 116 unmodified lines | |||
| 1225 | 1225 | ||
| 1226 | } | 1226 | } |
| 1227 | 1227 | ||
| 1228 | static void get_ddr2_info(struct ast_private *ast, struct ast2300_dram_param *param) | 1228 | static void get_ddr2_info(struct ast_device *ast, struct ast2300_dram_param *param) |
| 1229 | { | 1229 | { |
| 1230 | u32 trap, trap_AC2, trap_MRS; | 1230 | u32 trap, trap_AC2, trap_MRS; |
| 1231 | 1231 | ||
| @@ -1472,7 +1472,7 @@ static void get_ddr2_info(struct ast_private *ast, struct ast2300_dram_param *pa · 240 unmodified lines | |||
| 1472 | } | 1472 | } |
| 1473 | } | 1473 | } |
| 1474 | 1474 | ||
| 1475 | static void ddr2_init(struct ast_private *ast, struct ast2300_dram_param *param) | 1475 | static void ddr2_init(struct ast_device *ast, struct ast2300_dram_param *param) |
| 1476 | { | 1476 | { |
| 1477 | u32 data, data2, retry = 0; | 1477 | u32 data, data2, retry = 0; |
| 1478 | 1478 | ||
| @@ -1600,7 +1600,7 @@ ddr2_init_start: · 121 unmodified lines | |||
| 1600 | 1600 | ||
| 1601 | static void ast_post_chip_2300(struct drm_device *dev) | 1601 | static void ast_post_chip_2300(struct drm_device *dev) |
| 1602 | { | 1602 | { |
| 1603 | struct ast_private *ast = to_ast_private(dev); | 1603 | struct ast_device *ast = to_ast_device(dev); |
| 1604 | struct ast2300_dram_param param; | 1604 | struct ast2300_dram_param param; |
| 1605 | u32 temp; | 1605 | u32 temp; |
| 1606 | u8 reg; | 1606 | u8 reg; |
| @@ -1681,7 +1681,7 @@ static void ast_post_chip_2300(struct drm_device *dev) · 74 unmodified lines | |||
| 1681 | } while ((reg & 0x40) == 0); | 1681 | } while ((reg & 0x40) == 0); |
| 1682 | } | 1682 | } |
| 1683 | 1683 | ||
| 1684 | static bool cbr_test_2500(struct ast_private *ast) | 1684 | static bool cbr_test_2500(struct ast_device *ast) |
| 1685 | { | 1685 | { |
| 1686 | ast_moutdwm(ast, 0x1E6E0074, 0x0000FFFF); | 1686 | ast_moutdwm(ast, 0x1E6E0074, 0x0000FFFF); |
| 1687 | ast_moutdwm(ast, 0x1E6E007C, 0xFF00FF00); | 1687 | ast_moutdwm(ast, 0x1E6E007C, 0xFF00FF00); |
| @@ -1692,7 +1692,7 @@ static bool cbr_test_2500(struct ast_private *ast) · 4 unmodified lines | |||
| 1692 | return true; | 1692 | return true; |
| 1693 | } | 1693 | } |
| 1694 | 1694 | ||
| 1695 | static bool ddr_test_2500(struct ast_private *ast) | 1695 | static bool ddr_test_2500(struct ast_device *ast) |
| 1696 | { | 1696 | { |
| 1697 | ast_moutdwm(ast, 0x1E6E0074, 0x0000FFFF); | 1697 | ast_moutdwm(ast, 0x1E6E0074, 0x0000FFFF); |
| 1698 | ast_moutdwm(ast, 0x1E6E007C, 0xFF00FF00); | 1698 | ast_moutdwm(ast, 0x1E6E007C, 0xFF00FF00); |
| @@ -1709,7 +1709,7 @@ static bool ddr_test_2500(struct ast_private *ast) · 10 unmodified lines | |||
| 1709 | return true; | 1709 | return true; |
| 1710 | } | 1710 | } |
| 1711 | 1711 | ||
| 1712 | static void ddr_init_common_2500(struct ast_private *ast) | 1712 | static void ddr_init_common_2500(struct ast_device *ast) |
| 1713 | { | 1713 | { |
| 1714 | ast_moutdwm(ast, 0x1E6E0034, 0x00020080); | 1714 | ast_moutdwm(ast, 0x1E6E0034, 0x00020080); |
| 1715 | ast_moutdwm(ast, 0x1E6E0008, 0x2003000F); | 1715 | ast_moutdwm(ast, 0x1E6E0008, 0x2003000F); |
| @@ -1732,7 +1732,7 @@ static void ddr_init_common_2500(struct ast_private *ast) · 16 unmodified lines | |||
| 1732 | ast_moutdwm(ast, 0x1E6E024C, 0x80808080); | 1732 | ast_moutdwm(ast, 0x1E6E024C, 0x80808080); |
| 1733 | } | 1733 | } |
| 1734 | 1734 | ||
| 1735 | static void ddr_phy_init_2500(struct ast_private *ast) | 1735 | static void ddr_phy_init_2500(struct ast_device *ast) |
| 1736 | { | 1736 | { |
| 1737 | u32 data, pass, timecnt; | 1737 | u32 data, pass, timecnt; |
| 1738 | 1738 | ||
| @@ -1766,7 +1766,7 @@ static void ddr_phy_init_2500(struct ast_private *ast) · 27 unmodified lines | |||
| 1766 | * 4Gb : 0x80000000 ~ 0x9FFFFFFF | 1766 | * 4Gb : 0x80000000 ~ 0x9FFFFFFF |
| 1767 | * 8Gb : 0x80000000 ~ 0xBFFFFFFF | 1767 | * 8Gb : 0x80000000 ~ 0xBFFFFFFF |
| 1768 | */ | 1768 | */ |
| 1769 | static void check_dram_size_2500(struct ast_private *ast, u32 tRFC) | 1769 | static void check_dram_size_2500(struct ast_device *ast, u32 tRFC) |
| 1770 | { | 1770 | { |
| 1771 | u32 reg_04, reg_14; | 1771 | u32 reg_04, reg_14; |
| 1772 | 1772 | ||
| @@ -1797,7 +1797,7 @@ static void check_dram_size_2500(struct ast_private *ast, u32 tRFC) · 24 unmodified lines | |||
| 1797 | ast_moutdwm(ast, 0x1E6E0014, reg_14); | 1797 | ast_moutdwm(ast, 0x1E6E0014, reg_14); |
| 1798 | } | 1798 | } |
| 1799 | 1799 | ||
| 1800 | static void enable_cache_2500(struct ast_private *ast) | 1800 | static void enable_cache_2500(struct ast_device *ast) |
| 1801 | { | 1801 | { |
| 1802 | u32 reg_04, data; | 1802 | u32 reg_04, data; |
| 1803 | 1803 | ||
| @@ -1810,7 +1810,7 @@ static void enable_cache_2500(struct ast_private *ast) · 6 unmodified lines | |||
| 1810 | ast_moutdwm(ast, 0x1E6E0004, reg_04 | 0x400); | 1810 | ast_moutdwm(ast, 0x1E6E0004, reg_04 | 0x400); |
| 1811 | } | 1811 | } |
| 1812 | 1812 | ||
| 1813 | static void set_mpll_2500(struct ast_private *ast) | 1813 | static void set_mpll_2500(struct ast_device *ast) |
| 1814 | { | 1814 | { |
| 1815 | u32 addr, data, param; | 1815 | u32 addr, data, param; |
| 1816 | 1816 | ||
| @@ -1837,7 +1837,7 @@ static void set_mpll_2500(struct ast_private *ast) · 20 unmodified lines | |||
| 1837 | udelay(100); | 1837 | udelay(100); |
| 1838 | } | 1838 | } |
| 1839 | 1839 | ||
| 1840 | static void reset_mmc_2500(struct ast_private *ast) | 1840 | static void reset_mmc_2500(struct ast_device *ast) |
| 1841 | { | 1841 | { |
| 1842 | ast_moutdwm(ast, 0x1E78505C, 0x00000004); | 1842 | ast_moutdwm(ast, 0x1E78505C, 0x00000004); |
| 1843 | ast_moutdwm(ast, 0x1E785044, 0x00000001); | 1843 | ast_moutdwm(ast, 0x1E785044, 0x00000001); |
| @@ -1848,7 +1848,7 @@ static void reset_mmc_2500(struct ast_private *ast) · 4 unmodified lines | |||
| 1848 | ast_moutdwm(ast, 0x1E6E0000, 0xFC600309); | 1848 | ast_moutdwm(ast, 0x1E6E0000, 0xFC600309); |
| 1849 | } | 1849 | } |
| 1850 | 1850 | ||
| 1851 | static void ddr3_init_2500(struct ast_private *ast, const u32 *ddr_table) | 1851 | static void ddr3_init_2500(struct ast_device *ast, const u32 *ddr_table) |
| 1852 | { | 1852 | { |
| 1853 | 1853 | ||
| 1854 | ast_moutdwm(ast, 0x1E6E0004, 0x00000303); | 1854 | ast_moutdwm(ast, 0x1E6E0004, 0x00000303); |
| @@ -1892,7 +1892,7 @@ static void ddr3_init_2500(struct ast_private *ast, const u32 *ddr_table) · 37 unmodified lines | |||
| 1892 | ast_moutdwm(ast, 0x1E6E0038, 0xFFFFFF00); | 1892 | ast_moutdwm(ast, 0x1E6E0038, 0xFFFFFF00); |
| 1893 | } | 1893 | } |
| 1894 | 1894 | ||
| 1895 | static void ddr4_init_2500(struct ast_private *ast, const u32 *ddr_table) | 1895 | static void ddr4_init_2500(struct ast_device *ast, const u32 *ddr_table) |
| 1896 | { | 1896 | { |
| 1897 | u32 data, data2, pass, retrycnt; | 1897 | u32 data, data2, pass, retrycnt; |
| 1898 | u32 ddr_vref, phy_vref; | 1898 | u32 ddr_vref, phy_vref; |
| @@ -2002,7 +2002,7 @@ static void ddr4_init_2500(struct ast_private *ast, const u32 *ddr_table) · 103 unmodified lines | |||
| 2002 | ast_moutdwm(ast, 0x1E6E0038, 0xFFFFFF00); | 2002 | ast_moutdwm(ast, 0x1E6E0038, 0xFFFFFF00); |
| 2003 | } | 2003 | } |
| 2004 | 2004 | ||
| 2005 | static bool ast_dram_init_2500(struct ast_private *ast) | 2005 | static bool ast_dram_init_2500(struct ast_device *ast) |
| 2006 | { | 2006 | { |
| 2007 | u32 data; | 2007 | u32 data; |
| 2008 | u32 max_tries = 5; | 2008 | u32 max_tries = 5; |
| @@ -2030,7 +2030,7 @@ static bool ast_dram_init_2500(struct ast_private *ast) · 21 unmodified lines | |||
| 2030 | return true; | 2030 | return true; |
| 2031 | } | 2031 | } |
| 2032 | 2032 | ||
| 2033 | void ast_patch_ahb_2500(struct ast_private *ast) | 2033 | void ast_patch_ahb_2500(struct ast_device *ast) |
| 2034 | { | 2034 | { |
| 2035 | u32 data; | 2035 | u32 data; |
| 2036 | 2036 | ||
| @@ -2066,7 +2066,7 @@ void ast_patch_ahb_2500(struct ast_private *ast) · 29 unmodified lines | |||
| 2066 | 2066 | ||
| 2067 | void ast_post_chip_2500(struct drm_device *dev) | 2067 | void ast_post_chip_2500(struct drm_device *dev) |
| 2068 | { | 2068 | { |
| 2069 | struct ast_private *ast = to_ast_private(dev); | 2069 | struct ast_device *ast = to_ast_device(dev); |
| 2070 | u32 temp; | 2070 | u32 temp; |
| 2071 | u8 reg; | 2071 | u8 reg; |
| 2072 | 2072 | ||
| @@ -326,7 +326,7 @@ config DRM_TI_DLPC3433 · 325 unmodified lines | |||
| 326 | input that produces a DMD output in RGB565, RGB666, RGB888 | 326 | input that produces a DMD output in RGB565, RGB666, RGB888 |
| 327 | formats. | 327 | formats. |
| 328 | 328 | ||
| 329 | It supports upto 720p resolution with 60 and 120 Hz refresh | 329 | It supports up to 720p resolution with 60 and 120 Hz refresh |
| 330 | rates. | 330 | rates. |
| 331 | 331 | ||
| 332 | config DRM_TI_TFP410 | 332 | config DRM_TI_TFP410 |
| @@ -81,6 +81,8 @@ static int panel_bridge_attach(struct drm_bridge *bridge, · 80 unmodified lines | |||
| 81 | return ret; | 81 | return ret; |
| 82 | } | 82 | } |
| 83 | 83 | ||
| 84 | drm_panel_bridge_set_orientation(connector, bridge); | ||
| 85 | |||
| 84 | drm_connector_attach_encoder(&panel_bridge->connector, | 86 | drm_connector_attach_encoder(&panel_bridge->connector, |
| 85 | bridge->encoder); | 87 | bridge->encoder); |
| 86 | 88 | ||
| @@ -229,6 +229,7 @@ static int tc358762_probe(struct mipi_dsi_device *dsi) · 228 unmodified lines | |||
| 229 | ctx->bridge.funcs = &tc358762_bridge_funcs; | 229 | ctx->bridge.funcs = &tc358762_bridge_funcs; |
| 230 | ctx->bridge.type = DRM_MODE_CONNECTOR_DPI; | 230 | ctx->bridge.type = DRM_MODE_CONNECTOR_DPI; |
| 231 | ctx->bridge.of_node = dev->of_node; | 231 | ctx->bridge.of_node = dev->of_node; |
| 232 | ctx->bridge.pre_enable_prev_first = true; | ||
| 232 | 233 | ||
| 233 | drm_bridge_add(&ctx->bridge); | 234 | drm_bridge_add(&ctx->bridge); |
| 234 | 235 | ||
| @@ -2702,6 +2702,11 @@ void drm_atomic_helper_commit_planes(struct drm_device *dev, · 2701 unmodified lines | |||
| 2702 | funcs->atomic_disable(plane, old_state); | 2702 | funcs->atomic_disable(plane, old_state); |
| 2703 | } else if (new_plane_state->crtc || disabling) { | 2703 | } else if (new_plane_state->crtc || disabling) { |
| 2704 | funcs->atomic_update(plane, old_state); | 2704 | funcs->atomic_update(plane, old_state); |
| 2705 | |||
| 2706 | if (!disabling && funcs->atomic_enable) { | ||
| 2707 | if (drm_atomic_plane_enabling(old_plane_state, new_plane_state)) | ||
| 2708 | funcs->atomic_enable(plane, old_state); | ||
| 2709 | } | ||
| 2705 | } | 2710 | } |
| 2706 | } | 2711 | } |
| 2707 | 2712 | ||
| @@ -2762,6 +2767,7 @@ drm_atomic_helper_commit_planes_on_crtc(struct drm_crtc_state *old_crtc_state) · 54 unmodified lines | |||
| 2762 | struct drm_plane_state *new_plane_state = | 2767 | struct drm_plane_state *new_plane_state = |
| 2763 | drm_atomic_get_new_plane_state(old_state, plane); | 2768 | drm_atomic_get_new_plane_state(old_state, plane); |
| 2764 | const struct drm_plane_helper_funcs *plane_funcs; | 2769 | const struct drm_plane_helper_funcs *plane_funcs; |
| 2770 | bool disabling; | ||
| 2765 | 2771 | ||
| 2766 | plane_funcs = plane->helper_private; | 2772 | plane_funcs = plane->helper_private; |
| 2767 | 2773 | ||
| @@ -2771,12 +2777,18 @@ drm_atomic_helper_commit_planes_on_crtc(struct drm_crtc_state *old_crtc_state) · 3 unmodified lines | |||
| 2771 | WARN_ON(new_plane_state->crtc && | 2777 | WARN_ON(new_plane_state->crtc && |
| 2772 | new_plane_state->crtc != crtc); | 2778 | new_plane_state->crtc != crtc); |
| 2773 | 2779 | ||
| 2774 | if (drm_atomic_plane_disabling(old_plane_state, new_plane_state) && | 2780 | disabling = drm_atomic_plane_disabling(old_plane_state, new_plane_state); |
| 2775 | plane_funcs->atomic_disable) | 2781 | |
| 2782 | if (disabling && plane_funcs->atomic_disable) { | ||
| 2776 | plane_funcs->atomic_disable(plane, old_state); | 2783 | plane_funcs->atomic_disable(plane, old_state); |
| 2777 | else if (new_plane_state->crtc || | 2784 | } else if (new_plane_state->crtc || disabling) { |
| 2778 | drm_atomic_plane_disabling(old_plane_state, new_plane_state)) | ||
| 2779 | plane_funcs->atomic_update(plane, old_state); | 2785 | plane_funcs->atomic_update(plane, old_state); |
| 2786 | |||
| 2787 | if (!disabling && plane_funcs->atomic_enable) { | ||
| 2788 | if (drm_atomic_plane_enabling(old_plane_state, new_plane_state)) | ||
| 2789 | plane_funcs->atomic_enable(plane, old_state); | ||
| 2790 | } | ||
| 2791 | } | ||
| 2780 | } | 2792 | } |
| 2781 | 2793 | ||
| 2782 | if (crtc_funcs && crtc_funcs->atomic_flush) | 2794 | if (crtc_funcs && crtc_funcs->atomic_flush) |
| @@ -33,9 +33,11 @@ · 32 unmodified lines | |||
| 33 | #include <drm/drm_sysfs.h> | 33 | #include <drm/drm_sysfs.h> |
| 34 | #include <drm/drm_utils.h> | 34 | #include <drm/drm_utils.h> |
| 35 | 35 | ||
| 36 | #include <linux/fb.h> | 36 | #include <linux/property.h> |
| 37 | #include <linux/uaccess.h> | 37 | #include <linux/uaccess.h> |
| 38 | 38 | ||
| 39 | #include <video/cmdline.h> | ||
| 40 | |||
| 39 | #include "drm_crtc_internal.h" | 41 | #include "drm_crtc_internal.h" |
| 40 | #include "drm_internal.h" | 42 | #include "drm_internal.h" |
| 41 | 43 | ||
| @@ -154,9 +156,10 @@ EXPORT_SYMBOL(drm_get_connector_type_name); · 112 unmodified lines | |||
| 154 | static void drm_connector_get_cmdline_mode(struct drm_connector *connector) | 156 | static void drm_connector_get_cmdline_mode(struct drm_connector *connector) |
| 155 | { | 157 | { |
| 156 | struct drm_cmdline_mode *mode = &connector->cmdline_mode; | 158 | struct drm_cmdline_mode *mode = &connector->cmdline_mode; |
| 157 | char *option = NULL; | 159 | const char *option; |
| 158 | 160 | ||
| 159 | if (fb_get_options(connector->name, &option)) | 161 | option = video_get_options(connector->name); |
| 162 | if (!option) | ||
| 160 | return; | 163 | return; |
| 161 | 164 | ||
| 162 | if (!drm_mode_parse_command_line_for_connector(option, | 165 | if (!drm_mode_parse_command_line_for_connector(option, |
| @@ -1446,6 +1449,20 @@ static const struct drm_prop_enum_list dp_colorspaces[] = { · 1283 unmodified lines | |||
| 1446 | * a firmware handled hotkey. Therefor userspace must not include the | 1449 | * a firmware handled hotkey. Therefor userspace must not include the |
| 1447 | * privacy-screen sw-state in an atomic commit unless it wants to change | 1450 | * privacy-screen sw-state in an atomic commit unless it wants to change |
| 1448 | * its value. | 1451 | * its value. |
| 1452 | * | ||
| 1453 | * left margin, right margin, top margin, bottom margin: | ||
| 1454 | * Add margins to the connector's viewport. This is typically used to | ||
| 1455 | * mitigate underscan on TVs. | ||
| 1456 | * | ||
| 1457 | * The value is the size in pixels of the black border which will be | ||
| 1458 | * added. The attached CRTC's content will be scaled to fill the whole | ||
| 1459 | * area inside the margin. | ||
| 1460 | * | ||
| 1461 | * The margins configuration might be sent to the sink, e.g. via HDMI AVI | ||
| 1462 | * InfoFrames. | ||
| 1463 | * | ||
| 1464 | * Drivers can set up these properties by calling | ||
| 1465 | * drm_mode_create_tv_margin_properties(). | ||
| 1449 | */ | 1466 | */ |
| 1450 | 1467 | ||
| 1451 | int drm_connector_create_standard_properties(struct drm_device *dev) | 1468 | int drm_connector_create_standard_properties(struct drm_device *dev) |
| @@ -1590,10 +1607,6 @@ EXPORT_SYMBOL(drm_connector_attach_dp_subconnector_property); · 138 unmodified lines | |||
| 1590 | 1607 | ||
| 1591 | /* | 1608 | /* |
| 1592 | * TODO: Document the properties: | 1609 | * TODO: Document the properties: |
| 1593 | * - left margin | ||
| 1594 | * - right margin | ||
| 1595 | * - top margin | ||
| 1596 | * - bottom margin | ||
| 1597 | * - brightness | 1610 | * - brightness |
| 1598 | * - contrast | 1611 | * - contrast |
| 1599 | * - flicker reduction | 1612 | * - flicker reduction |
| @@ -1602,7 +1615,6 @@ EXPORT_SYMBOL(drm_connector_attach_dp_subconnector_property); · 2 unmodified lines | |||
| 1602 | * - overscan | 1615 | * - overscan |
| 1603 | * - saturation | 1616 | * - saturation |
| 1604 | * - select subconnector | 1617 | * - select subconnector |
| 1605 | * - subconnector | ||
| 1606 | */ | 1618 | */ |
| 1607 | /** | 1619 | /** |
| 1608 | * DOC: Analog TV Connector Properties | 1620 | * DOC: Analog TV Connector Properties |
| @@ -7,13 +7,29 @@ · 6 unmodified lines | |||
| 7 | #include <drm/drm_edid.h> | 7 | #include <drm/drm_edid.h> |
| 8 | #include <drm/drm_print.h> | 8 | #include <drm/drm_print.h> |
| 9 | 9 | ||
| 10 | static int validate_displayid(const u8 *displayid, int length, int idx) | 10 | static const struct displayid_header * |
| 11 | displayid_get_header(const u8 *displayid, int length, int index) | ||
| 12 | { | ||
| 13 | const struct displayid_header *base; | ||
| 14 | |||
| 15 | if (sizeof(*base) > length - index) | ||
| 16 | return ERR_PTR(-EINVAL); | ||
| 17 | |||
| 18 | base = (const struct displayid_header *)&displayid[index]; | ||
| 19 | |||
| 20 | return base; | ||
| 21 | } | ||
| 22 | |||
| 23 | static const struct displayid_header * | ||
| 24 | validate_displayid(const u8 *displayid, int length, int idx) | ||
| 11 | { | 25 | { |
| 12 | int i, dispid_length; | 26 | int i, dispid_length; |
| 13 | u8 csum = 0; | 27 | u8 csum = 0; |
| 14 | const struct displayid_header *base; | 28 | const struct displayid_header *base; |
| 15 | 29 | ||
| 16 | base = (const struct displayid_header *)&displayid[idx]; | 30 | base = displayid_get_header(displayid, length, idx); |
| 31 | if (IS_ERR(base)) | ||
| 32 | return base; | ||
| 17 | 33 | ||
| 18 | DRM_DEBUG_KMS("base revision 0x%x, length %d, %d %d\n", | 34 | DRM_DEBUG_KMS("base revision 0x%x, length %d, %d %d\n", |
| 19 | base->rev, base->bytes, base->prod_id, base->ext_count); | 35 | base->rev, base->bytes, base->prod_id, base->ext_count); |
| @@ -21,16 +37,16 @@ static int validate_displayid(const u8 *displayid, int length, int idx) · 1 unmodified line | |||
| 21 | /* +1 for DispID checksum */ | 37 | /* +1 for DispID checksum */ |
| 22 | dispid_length = sizeof(*base) + base->bytes + 1; | 38 | dispid_length = sizeof(*base) + base->bytes + 1; |
| 23 | if (dispid_length > length - idx) | 39 | if (dispid_length > length - idx) |
| 24 | return -EINVAL; | 40 | return ERR_PTR(-EINVAL); |
| 25 | 41 | ||
| 26 | for (i = 0; i < dispid_length; i++) | 42 | for (i = 0; i < dispid_length; i++) |
| 27 | csum += displayid[idx + i]; | 43 | csum += displayid[idx + i]; |
| 28 | if (csum) { | 44 | if (csum) { |
| 29 | DRM_NOTE("DisplayID checksum invalid, remainder is %d\n", csum); | 45 | DRM_NOTE("DisplayID checksum invalid, remainder is %d\n", csum); |
| 30 | return -EINVAL; | 46 | return ERR_PTR(-EINVAL); |
| 31 | } | 47 | } |
| 32 | 48 | ||
| 33 | return 0; | 49 | return base; |
| 34 | } | 50 | } |
| 35 | 51 | ||
| 36 | static const u8 *drm_find_displayid_extension(const struct drm_edid *drm_edid, | 52 | static const u8 *drm_find_displayid_extension(const struct drm_edid *drm_edid, |
| @@ -39,7 +55,6 @@ static const u8 *drm_find_displayid_extension(const struct drm_edid *drm_edid, · 2 unmodified lines | |||
| 39 | { | 55 | { |
| 40 | const u8 *displayid = drm_find_edid_extension(drm_edid, DISPLAYID_EXT, ext_index); | 56 | const u8 *displayid = drm_find_edid_extension(drm_edid, DISPLAYID_EXT, ext_index); |
| 41 | const struct displayid_header *base; | 57 | const struct displayid_header *base; |
| 42 | int ret; | ||
| 43 | 58 | ||
| 44 | if (!displayid) | 59 | if (!displayid) |
| 45 | return NULL; | 60 | return NULL; |
| @@ -48,11 +63,10 @@ static const u8 *drm_find_displayid_extension(const struct drm_edid *drm_edid, · 2 unmodified lines | |||
| 48 | *length = EDID_LENGTH - 1; | 63 | *length = EDID_LENGTH - 1; |
| 49 | *idx = 1; | 64 | *idx = 1; |
| 50 | 65 | ||
| 51 | ret = validate_displayid(displayid, *length, *idx); | 66 | base = validate_displayid(displayid, *length, *idx); |
| 52 | if (ret) | 67 | if (IS_ERR(base)) |
| 53 | return NULL; | 68 | return NULL; |
| 54 | 69 | ||
| 55 | base = (const struct displayid_header *)&displayid[*idx]; | ||
| 56 | *length = *idx + sizeof(*base) + base->bytes; | 70 | *length = *idx + sizeof(*base) + base->bytes; |
| 57 | 71 | ||
| 58 | return displayid; | 72 | return displayid; |
| @@ -109,6 +123,9 @@ __displayid_iter_next(struct displayid_iter *iter) · 50 unmodified lines | |||
| 109 | } | 123 | } |
| 110 | 124 | ||
| 111 | for (;;) { | 125 | for (;;) { |
| 126 | /* The first section we encounter is the base section */ | ||
| 127 | bool base_section = !iter->section; | ||
| 128 | |||
| 112 | iter->section = drm_find_displayid_extension(iter->drm_edid, | 129 | iter->section = drm_find_displayid_extension(iter->drm_edid, |
| 113 | &iter->length, | 130 | &iter->length, |
| 114 | &iter->idx, | 131 | &iter->idx, |
| @@ -118,6 +135,18 @@ __displayid_iter_next(struct displayid_iter *iter) · 3 unmodified lines | |||
| 118 | return NULL; | 135 | return NULL; |
| 119 | } | 136 | } |
| 120 | 137 | ||
| 138 | /* Save the structure version and primary use case. */ | ||
| 139 | if (base_section) { | ||
| 140 | const struct displayid_header *base; | ||
| 141 | |||
| 142 | base = displayid_get_header(iter->section, iter->length, | ||
| 143 | iter->idx); | ||
| 144 | if (!IS_ERR(base)) { | ||
| 145 | iter->version = base->rev; | ||
| 146 | iter->primary_use = base->prod_id; | ||
| 147 | } | ||
| 148 | } | ||
| 149 | |||
| 121 | iter->idx += sizeof(struct displayid_header); | 150 | iter->idx += sizeof(struct displayid_header); |
| 122 | 151 | ||
| 123 | block = displayid_iter_block(iter); | 152 | block = displayid_iter_block(iter); |
| @@ -130,3 +159,18 @@ void displayid_iter_end(struct displayid_iter *iter) · 6 unmodified lines | |||
| 130 | { | 159 | { |
| 131 | memset(iter, 0, sizeof(*iter)); | 160 | memset(iter, 0, sizeof(*iter)); |
| 132 | } | 161 | } |
| 162 | |||
| 163 | /* DisplayID Structure Version/Revision from the Base Section. */ | ||
| 164 | u8 displayid_version(const struct displayid_iter *iter) | ||
| 165 | { | ||
| 166 | return iter->version; | ||
| 167 | } | ||
| 168 | |||
| 169 | /* | ||
| 170 | * DisplayID Primary Use Case (2.0+) or Product Type Identifier (1.0-1.3) from | ||
| 171 | * the Base Section. | ||
| 172 | */ | ||
| 173 | u8 displayid_primary_use(const struct displayid_iter *iter) | ||
| 174 | { | ||
| 175 | return iter->primary_use; | ||
| 176 | } | ||
| @@ -139,10 +139,7 @@ int drm_mode_destroy_dumb(struct drm_device *dev, u32 handle, · 138 unmodified lines | |||
| 139 | if (!dev->driver->dumb_create) | 139 | if (!dev->driver->dumb_create) |
| 140 | return -ENOSYS; | 140 | return -ENOSYS; |
| 141 | 141 | ||
| 142 | if (dev->driver->dumb_destroy) | 142 | return drm_gem_handle_delete(file_priv, handle); |
| 143 | return dev->driver->dumb_destroy(file_priv, dev, handle); | ||
| 144 | else | ||
| 145 | return drm_gem_dumb_destroy(file_priv, dev, handle); | ||
| 146 | } | 143 | } |
| 147 | 144 | ||
| 148 | int drm_mode_destroy_dumb_ioctl(struct drm_device *dev, | 145 | int drm_mode_destroy_dumb_ioctl(struct drm_device *dev, |
| @@ -3424,10 +3424,6 @@ static struct drm_display_mode *drm_mode_detailed(struct drm_connector *connecto · 3423 unmodified lines | |||
| 3424 | connector->base.id, connector->name); | 3424 | connector->base.id, connector->name); |
| 3425 | return NULL; | 3425 | return NULL; |
| 3426 | } | 3426 | } |
| 3427 | if (!(pt->misc & DRM_EDID_PT_SEPARATE_SYNC)) { | ||
| 3428 | drm_dbg_kms(dev, "[CONNECTOR:%d:%s] Composite sync not supported\n", | ||
| 3429 | connector->base.id, connector->name); | ||
| 3430 | } | ||
| 3431 | 3427 | ||
| 3432 | /* it is incorrect if hsync/vsync width is zero */ | 3428 | /* it is incorrect if hsync/vsync width is zero */ |
| 3433 | if (!hsync_pulse_width || !vsync_pulse_width) { | 3429 | if (!hsync_pulse_width || !vsync_pulse_width) { |
| @@ -3474,10 +3470,27 @@ static struct drm_display_mode *drm_mode_detailed(struct drm_connector *connecto · 40 unmodified lines | |||
| 3474 | if (info->quirks & EDID_QUIRK_DETAILED_SYNC_PP) { | 3470 | if (info->quirks & EDID_QUIRK_DETAILED_SYNC_PP) { |
| 3475 | mode->flags |= DRM_MODE_FLAG_PHSYNC | DRM_MODE_FLAG_PVSYNC; | 3471 | mode->flags |= DRM_MODE_FLAG_PHSYNC | DRM_MODE_FLAG_PVSYNC; |
| 3476 | } else { | 3472 | } else { |
| 3477 | mode->flags |= (pt->misc & DRM_EDID_PT_HSYNC_POSITIVE) ? | 3473 | switch (pt->misc & DRM_EDID_PT_SYNC_MASK) { |
| 3478 | DRM_MODE_FLAG_PHSYNC : DRM_MODE_FLAG_NHSYNC; | 3474 | case DRM_EDID_PT_ANALOG_CSYNC: |
| 3479 | mode->flags |= (pt->misc & DRM_EDID_PT_VSYNC_POSITIVE) ? | 3475 | case DRM_EDID_PT_BIPOLAR_ANALOG_CSYNC: |
| 3480 | DRM_MODE_FLAG_PVSYNC : DRM_MODE_FLAG_NVSYNC; | 3476 | drm_dbg_kms(dev, "[CONNECTOR:%d:%s] Analog composite sync!\n", |
| 3477 | connector->base.id, connector->name); | ||
| 3478 | mode->flags |= DRM_MODE_FLAG_CSYNC | DRM_MODE_FLAG_NCSYNC; | ||
| 3479 | break; | ||
| 3480 | case DRM_EDID_PT_DIGITAL_CSYNC: | ||
| 3481 | drm_dbg_kms(dev, "[CONNECTOR:%d:%s] Digital composite sync!\n", | ||
| 3482 | connector->base.id, connector->name); | ||
| 3483 | mode->flags |= DRM_MODE_FLAG_CSYNC; | ||
| 3484 | mode->flags |= (pt->misc & DRM_EDID_PT_HSYNC_POSITIVE) ? | ||
| 3485 | DRM_MODE_FLAG_PCSYNC : DRM_MODE_FLAG_NCSYNC; | ||
| 3486 | break; | ||
| 3487 | case DRM_EDID_PT_DIGITAL_SEPARATE_SYNC: | ||
| 3488 | mode->flags |= (pt->misc & DRM_EDID_PT_HSYNC_POSITIVE) ? | ||
| 3489 | DRM_MODE_FLAG_PHSYNC : DRM_MODE_FLAG_NHSYNC; | ||
| 3490 | mode->flags |= (pt->misc & DRM_EDID_PT_VSYNC_POSITIVE) ? | ||
| 3491 | DRM_MODE_FLAG_PVSYNC : DRM_MODE_FLAG_NVSYNC; | ||
| 3492 | break; | ||
| 3493 | } | ||
| 3481 | } | 3494 | } |
| 3482 | 3495 | ||
| 3483 | set_size: | 3496 | set_size: |
| @@ -6433,6 +6446,29 @@ static void drm_reset_display_info(struct drm_connector *connector) · 2949 unmodified lines | |||
| 6433 | info->quirks = 0; | 6446 | info->quirks = 0; |
| 6434 | } | 6447 | } |
| 6435 | 6448 | ||
| 6449 | static void update_displayid_info(struct drm_connector *connector, | ||
| 6450 | const struct drm_edid *drm_edid) | ||
| 6451 | { | ||
| 6452 | struct drm_display_info *info = &connector->display_info; | ||
| 6453 | const struct displayid_block *block; | ||
| 6454 | struct displayid_iter iter; | ||
| 6455 | |||
| 6456 | displayid_iter_edid_begin(drm_edid, &iter); | ||
| 6457 | displayid_iter_for_each(block, &iter) { | ||
| 6458 | if (displayid_version(&iter) == DISPLAY_ID_STRUCTURE_VER_20 && | ||
| 6459 | (displayid_primary_use(&iter) == PRIMARY_USE_HEAD_MOUNTED_VR || | ||
| 6460 | displayid_primary_use(&iter) == PRIMARY_USE_HEAD_MOUNTED_AR)) | ||
| 6461 | info->non_desktop = true; | ||
| 6462 | |||
| 6463 | /* | ||
| 6464 | * We're only interested in the base section here, no need to | ||
| 6465 | * iterate further. | ||
| 6466 | */ | ||
| 6467 | break; | ||
| 6468 | } | ||
| 6469 | displayid_iter_end(&iter); | ||
| 6470 | } | ||
| 6471 | |||
| 6436 | static void update_display_info(struct drm_connector *connector, | 6472 | static void update_display_info(struct drm_connector *connector, |
| 6437 | const struct drm_edid *drm_edid) | 6473 | const struct drm_edid *drm_edid) |
| 6438 | { | 6474 | { |
| @@ -6463,6 +6499,8 @@ static void update_display_info(struct drm_connector *connector, · 24 unmodified lines | |||
| 6463 | info->color_formats |= DRM_COLOR_FORMAT_RGB444; | 6499 | info->color_formats |= DRM_COLOR_FORMAT_RGB444; |
| 6464 | drm_parse_cea_ext(connector, drm_edid); | 6500 | drm_parse_cea_ext(connector, drm_edid); |
| 6465 | 6501 | ||
| 6502 | update_displayid_info(connector, drm_edid); | ||
| 6503 | |||
| 6466 | /* | 6504 | /* |
| 6467 | * Digital sink with "DFP 1.x compliant TMDS" according to EDID 1.3? | 6505 | * Digital sink with "DFP 1.x compliant TMDS" according to EDID 1.3? |
| 6468 | * | 6506 | * |
| @@ -7242,6 +7280,15 @@ static void drm_parse_tiled_block(struct drm_connector *connector, · 773 unmodified lines | |||
| 7242 | } | 7280 | } |
| 7243 | } | 7281 | } |
| 7244 | 7282 | ||
| 7283 | static bool displayid_is_tiled_block(const struct displayid_iter *iter, | ||
| 7284 | const struct displayid_block *block) | ||
| 7285 | { | ||
| 7286 | return (displayid_version(iter) == DISPLAY_ID_STRUCTURE_VER_12 && | ||
| 7287 | block->tag == DATA_BLOCK_TILED_DISPLAY) || | ||
| 7288 | (displayid_version(iter) == DISPLAY_ID_STRUCTURE_VER_20 && | ||
| 7289 | block->tag == DATA_BLOCK_2_TILED_DISPLAY_TOPOLOGY); | ||
| 7290 | } | ||
| 7291 | |||
| 7245 | static void _drm_update_tile_info(struct drm_connector *connector, | 7292 | static void _drm_update_tile_info(struct drm_connector *connector, |
| 7246 | const struct drm_edid *drm_edid) | 7293 | const struct drm_edid *drm_edid) |
| 7247 | { | 7294 | { |
| @@ -7252,7 +7299,7 @@ static void _drm_update_tile_info(struct drm_connector *connector, · 4 unmodified lines | |||
| 7252 | 7299 | ||
| 7253 | displayid_iter_edid_begin(drm_edid, &iter); | 7300 | displayid_iter_edid_begin(drm_edid, &iter); |
| 7254 | displayid_iter_for_each(block, &iter) { | 7301 | displayid_iter_for_each(block, &iter) { |
| 7255 | if (block->tag == DATA_BLOCK_TILED_DISPLAY) | 7302 | if (displayid_is_tiled_block(&iter, block)) |
| 7256 | drm_parse_tiled_block(connector, block); | 7303 | drm_parse_tiled_block(connector, block); |
| 7257 | } | 7304 | } |
| 7258 | displayid_iter_end(&iter); | 7305 | displayid_iter_end(&iter); |
| @@ -336,13 +336,6 @@ out: · 335 unmodified lines | |||
| 336 | } | 336 | } |
| 337 | EXPORT_SYMBOL_GPL(drm_gem_dumb_map_offset); | 337 | EXPORT_SYMBOL_GPL(drm_gem_dumb_map_offset); |
| 338 | 338 | ||
| 339 | int drm_gem_dumb_destroy(struct drm_file *file, | ||
| 340 | struct drm_device *dev, | ||
| 341 | u32 handle) | ||
| 342 | { | ||
| 343 | return drm_gem_handle_delete(file, handle); | ||
| 344 | } | ||
| 345 | |||
| 346 | /** | 339 | /** |
| 347 | * drm_gem_handle_create_tail - internal functions to create a handle | 340 | * drm_gem_handle_create_tail - internal functions to create a handle |
| 348 | * @file_priv: drm file-private structure to register the handle for | 341 | * @file_priv: drm file-private structure to register the handle for |
| @@ -1466,3 +1459,21 @@ tail: · 1117 unmodified lines | |||
| 1466 | return freed; | 1459 | return freed; |
| 1467 | } | 1460 | } |
| 1468 | EXPORT_SYMBOL(drm_gem_lru_scan); | 1461 | EXPORT_SYMBOL(drm_gem_lru_scan); |
| 1462 | |||
| 1463 | /** | ||
| 1464 | * drm_gem_evict - helper to evict backing pages for a GEM object | ||
| 1465 | * @obj: obj in question | ||
| 1466 | */ | ||
| 1467 | int drm_gem_evict(struct drm_gem_object *obj) | ||
| 1468 | { | ||
| 1469 | dma_resv_assert_held(obj->resv); | ||
| 1470 | |||
| 1471 | if (!dma_resv_test_signaled(obj->resv, DMA_RESV_USAGE_READ)) | ||
| 1472 | return -EBUSY; | ||
| 1473 | |||
| 1474 | if (obj->funcs->evict) | ||
| 1475 | return obj->funcs->evict(obj); | ||
| 1476 | |||
| 1477 | return 0; | ||
| 1478 | } | ||
| 1479 | EXPORT_SYMBOL(drm_gem_evict); | ||
| @@ -141,7 +141,7 @@ void drm_gem_shmem_free(struct drm_gem_shmem_object *shmem) · 140 unmodified lines | |||
| 141 | { | 141 | { |
| 142 | struct drm_gem_object *obj = &shmem->base; | 142 | struct drm_gem_object *obj = &shmem->base; |
| 143 | 143 | ||
| 144 | WARN_ON(shmem->vmap_use_count); | 144 | drm_WARN_ON(obj->dev, shmem->vmap_use_count); |
| 145 | 145 | ||
| 146 | if (obj->import_attach) { | 146 | if (obj->import_attach) { |
| 147 | drm_prime_gem_destroy(obj, shmem->sgt); | 147 | drm_prime_gem_destroy(obj, shmem->sgt); |
| @@ -156,7 +156,7 @@ void drm_gem_shmem_free(struct drm_gem_shmem_object *shmem) · 8 unmodified lines | |||
| 156 | drm_gem_shmem_put_pages(shmem); | 156 | drm_gem_shmem_put_pages(shmem); |
| 157 | } | 157 | } |
| 158 | 158 | ||
| 159 | WARN_ON(shmem->pages_use_count); | 159 | drm_WARN_ON(obj->dev, shmem->pages_use_count); |
| 160 | 160 | ||
| 161 | drm_gem_object_release(obj); | 161 | drm_gem_object_release(obj); |
| 162 | mutex_destroy(&shmem->pages_lock); | 162 | mutex_destroy(&shmem->pages_lock); |
| @@ -175,7 +175,8 @@ static int drm_gem_shmem_get_pages_locked(struct drm_gem_shmem_object *shmem) · 12 unmodified lines | |||
| 175 | 175 | ||
| 176 | pages = drm_gem_get_pages(obj); | 176 | pages = drm_gem_get_pages(obj); |
| 177 | if (IS_ERR(pages)) { | 177 | if (IS_ERR(pages)) { |
| 178 | DRM_DEBUG_KMS("Failed to get pages (%ld)\n", PTR_ERR(pages)); | 178 | drm_dbg_kms(obj->dev, "Failed to get pages (%ld)\n", |
| 179 | PTR_ERR(pages)); | ||
| 179 | shmem->pages_use_count = 0; | 180 | shmem->pages_use_count = 0; |
| 180 | return PTR_ERR(pages); | 181 | return PTR_ERR(pages); |
| 181 | } | 182 | } |
| @@ -207,9 +208,10 @@ static int drm_gem_shmem_get_pages_locked(struct drm_gem_shmem_object *shmem) · 25 unmodified lines | |||
| 207 | */ | 208 | */ |
| 208 | int drm_gem_shmem_get_pages(struct drm_gem_shmem_object *shmem) | 209 | int drm_gem_shmem_get_pages(struct drm_gem_shmem_object *shmem) |
| 209 | { | 210 | { |
| 211 | struct drm_gem_object *obj = &shmem->base; | ||
| 210 | int ret; | 212 | int ret; |
| 211 | 213 | ||
| 212 | WARN_ON(shmem->base.import_attach); | 214 | drm_WARN_ON(obj->dev, obj->import_attach); |
| 213 | 215 | ||
| 214 | ret = mutex_lock_interruptible(&shmem->pages_lock); | 216 | ret = mutex_lock_interruptible(&shmem->pages_lock); |
| 215 | if (ret) | 217 | if (ret) |
| @@ -225,7 +227,7 @@ static void drm_gem_shmem_put_pages_locked(struct drm_gem_shmem_object *shmem) · 9 unmodified lines | |||
| 225 | { | 227 | { |
| 226 | struct drm_gem_object *obj = &shmem->base; | 228 | struct drm_gem_object *obj = &shmem->base; |
| 227 | 229 | ||
| 228 | if (WARN_ON_ONCE(!shmem->pages_use_count)) | 230 | if (drm_WARN_ON_ONCE(obj->dev, !shmem->pages_use_count)) |
| 229 | return; | 231 | return; |
| 230 | 232 | ||
| 231 | if (--shmem->pages_use_count > 0) | 233 | if (--shmem->pages_use_count > 0) |
| @@ -268,7 +270,9 @@ EXPORT_SYMBOL(drm_gem_shmem_put_pages); · 36 unmodified lines | |||
| 268 | */ | 270 | */ |
| 269 | int drm_gem_shmem_pin(struct drm_gem_shmem_object *shmem) | 271 | int drm_gem_shmem_pin(struct drm_gem_shmem_object *shmem) |
| 270 | { | 272 | { |
| 271 | WARN_ON(shmem->base.import_attach); | 273 | struct drm_gem_object *obj = &shmem->base; |
| 274 | |||
| 275 | drm_WARN_ON(obj->dev, obj->import_attach); | ||
| 272 | 276 | ||
| 273 | return drm_gem_shmem_get_pages(shmem); | 277 | return drm_gem_shmem_get_pages(shmem); |
| 274 | } | 278 | } |
| @@ -283,7 +287,9 @@ EXPORT_SYMBOL(drm_gem_shmem_pin); · 8 unmodified lines | |||
| 283 | */ | 287 | */ |
| 284 | void drm_gem_shmem_unpin(struct drm_gem_shmem_object *shmem) | 288 | void drm_gem_shmem_unpin(struct drm_gem_shmem_object *shmem) |
| 285 | { | 289 | { |
| 286 | WARN_ON(shmem->base.import_attach); | 290 | struct drm_gem_object *obj = &shmem->base; |
| 291 | |||
| 292 | drm_WARN_ON(obj->dev, obj->import_attach); | ||
| 287 | 293 | ||
| 288 | drm_gem_shmem_put_pages(shmem); | 294 | drm_gem_shmem_put_pages(shmem); |
| 289 | } | 295 | } |
| @@ -295,24 +301,22 @@ static int drm_gem_shmem_vmap_locked(struct drm_gem_shmem_object *shmem, · 5 unmodified lines | |||
| 295 | struct drm_gem_object *obj = &shmem->base; | 301 | struct drm_gem_object *obj = &shmem->base; |
| 296 | int ret = 0; | 302 | int ret = 0; |
| 297 | 303 | ||
| 298 | if (shmem->vmap_use_count++ > 0) { | ||
| 299 | iosys_map_set_vaddr(map, shmem->vaddr); | ||
| 300 | return 0; | ||
| 301 | } | ||
| 302 | |||
| 303 | if (obj->import_attach) { | 304 | if (obj->import_attach) { |
| 304 | ret = dma_buf_vmap(obj->import_attach->dmabuf, map); | 305 | ret = dma_buf_vmap(obj->import_attach->dmabuf, map); |
| 305 | if (!ret) { | 306 | if (!ret) { |
| 306 | if (WARN_ON(map->is_iomem)) { | 307 | if (drm_WARN_ON(obj->dev, map->is_iomem)) { |
| 307 | dma_buf_vunmap(obj->import_attach->dmabuf, map); | 308 | dma_buf_vunmap(obj->import_attach->dmabuf, map); |
| 308 | ret = -EIO; | 309 | return -EIO; |
| 309 | goto err_put_pages; | ||
| 310 | } | 310 | } |
| 311 | shmem->vaddr = map->vaddr; | ||
| 312 | } | 311 | } |
| 313 | } else { | 312 | } else { |
| 314 | pgprot_t prot = PAGE_KERNEL; | 313 | pgprot_t prot = PAGE_KERNEL; |
| 315 | 314 | ||
| 315 | if (shmem->vmap_use_count++ > 0) { | ||
| 316 | iosys_map_set_vaddr(map, shmem->vaddr); | ||
| 317 | return 0; | ||
| 318 | } | ||
| 319 | |||
| 316 | ret = drm_gem_shmem_get_pages(shmem); | 320 | ret = drm_gem_shmem_get_pages(shmem); |
| 317 | if (ret) | 321 | if (ret) |
| 318 | goto err_zero_use; | 322 | goto err_zero_use; |
| @@ -328,7 +332,7 @@ static int drm_gem_shmem_vmap_locked(struct drm_gem_shmem_object *shmem, · 9 unmodified lines | |||
| 328 | } | 332 | } |
| 329 | 333 | ||
| 330 | if (ret) { | 334 | if (ret) { |
| 331 | DRM_DEBUG_KMS("Failed to vmap pages, error %d\n", ret); | 335 | drm_dbg_kms(obj->dev, "Failed to vmap pages, error %d\n", ret); |
| 332 | goto err_put_pages; | 336 | goto err_put_pages; |
| 333 | } | 337 | } |
| 334 | 338 | ||
| @@ -378,15 +382,15 @@ static void drm_gem_shmem_vunmap_locked(struct drm_gem_shmem_object *shmem, · 43 unmodified lines | |||
| 378 | { | 382 | { |
| 379 | struct drm_gem_object *obj = &shmem->base; | 383 | struct drm_gem_object *obj = &shmem->base; |
| 380 | 384 | ||
| 381 | if (WARN_ON_ONCE(!shmem->vmap_use_count)) | ||
| 382 | return; | ||
| 383 | |||
| 384 | if (--shmem->vmap_use_count > 0) | ||
| 385 | return; | ||
| 386 | |||
| 387 | if (obj->import_attach) { | 385 | if (obj->import_attach) { |
| 388 | dma_buf_vunmap(obj->import_attach->dmabuf, map); | 386 | dma_buf_vunmap(obj->import_attach->dmabuf, map); |
| 389 | } else { | 387 | } else { |
| 388 | if (drm_WARN_ON_ONCE(obj->dev, !shmem->vmap_use_count)) | ||
| 389 | return; | ||
| 390 | |||
| 391 | if (--shmem->vmap_use_count > 0) | ||
| 392 | return; | ||
| 393 | |||
| 390 | vunmap(shmem->vaddr); | 394 | vunmap(shmem->vaddr); |
| 391 | drm_gem_shmem_put_pages(shmem); | 395 | drm_gem_shmem_put_pages(shmem); |
| 392 | } | 396 | } |
| @@ -461,7 +465,7 @@ void drm_gem_shmem_purge_locked(struct drm_gem_shmem_object *shmem) · 68 unmodified lines | |||
| 461 | struct drm_gem_object *obj = &shmem->base; | 465 | struct drm_gem_object *obj = &shmem->base; |
| 462 | struct drm_device *dev = obj->dev; | 466 | struct drm_device *dev = obj->dev; |
| 463 | 467 | ||
| 464 | WARN_ON(!drm_gem_shmem_is_purgeable(shmem)); | 468 | drm_WARN_ON(obj->dev, !drm_gem_shmem_is_purgeable(shmem)); |
| 465 | 469 | ||
| 466 | dma_unmap_sgtable(dev->dev, shmem->sgt, DMA_BIDIRECTIONAL, 0); | 470 | dma_unmap_sgtable(dev->dev, shmem->sgt, DMA_BIDIRECTIONAL, 0); |
| 467 | sg_free_table(shmem->sgt); | 471 | sg_free_table(shmem->sgt); |
| @@ -550,7 +554,7 @@ static vm_fault_t drm_gem_shmem_fault(struct vm_fault *vmf) · 82 unmodified lines | |||
| 550 | mutex_lock(&shmem->pages_lock); | 554 | mutex_lock(&shmem->pages_lock); |
| 551 | 555 | ||
| 552 | if (page_offset >= num_pages || | 556 | if (page_offset >= num_pages || |
| 553 | WARN_ON_ONCE(!shmem->pages) || | 557 | drm_WARN_ON_ONCE(obj->dev, !shmem->pages) || |
| 554 | shmem->madv < 0) { | 558 | shmem->madv < 0) { |
| 555 | ret = VM_FAULT_SIGBUS; | 559 | ret = VM_FAULT_SIGBUS; |
| 556 | } else { | 560 | } else { |
| @@ -569,7 +573,7 @@ static void drm_gem_shmem_vm_open(struct vm_area_struct *vma) · 12 unmodified lines | |||
| 569 | struct drm_gem_object *obj = vma->vm_private_data; | 573 | struct drm_gem_object *obj = vma->vm_private_data; |
| 570 | struct drm_gem_shmem_object *shmem = to_drm_gem_shmem_obj(obj); | 574 | struct drm_gem_shmem_object *shmem = to_drm_gem_shmem_obj(obj); |
| 571 | 575 | ||
| 572 | WARN_ON(shmem->base.import_attach); | 576 | drm_WARN_ON(obj->dev, obj->import_attach); |
| 573 | 577 | ||
| 574 | mutex_lock(&shmem->pages_lock); | 578 | mutex_lock(&shmem->pages_lock); |
| 575 | 579 | ||
| @@ -578,7 +582,7 @@ static void drm_gem_shmem_vm_open(struct vm_area_struct *vma) · 2 unmodified lines | |||
| 578 | * mmap'd, vm_open() just grabs an additional reference for the new | 582 | * mmap'd, vm_open() just grabs an additional reference for the new |
| 579 | * mm the vma is getting copied into (ie. on fork()). | 583 | * mm the vma is getting copied into (ie. on fork()). |
| 580 | */ | 584 | */ |
| 581 | if (!WARN_ON_ONCE(!shmem->pages_use_count)) | 585 | if (!drm_WARN_ON_ONCE(obj->dev, !shmem->pages_use_count)) |
| 582 | shmem->pages_use_count++; | 586 | shmem->pages_use_count++; |
| 583 | 587 | ||
| 584 | mutex_unlock(&shmem->pages_lock); | 588 | mutex_unlock(&shmem->pages_lock); |
| @@ -648,6 +652,9 @@ EXPORT_SYMBOL_GPL(drm_gem_shmem_mmap); · 63 unmodified lines | |||
| 648 | void drm_gem_shmem_print_info(const struct drm_gem_shmem_object *shmem, | 652 | void drm_gem_shmem_print_info(const struct drm_gem_shmem_object *shmem, |
| 649 | struct drm_printer *p, unsigned int indent) | 653 | struct drm_printer *p, unsigned int indent) |
| 650 | { | 654 | { |
| 655 | if (shmem->base.import_attach) | ||
| 656 | return; | ||
| 657 | |||
| 651 | drm_printf_indent(p, indent, "pages_use_count=%u\n", shmem->pages_use_count); | 658 | drm_printf_indent(p, indent, "pages_use_count=%u\n", shmem->pages_use_count); |
| 652 | drm_printf_indent(p, indent, "vmap_use_count=%u\n", shmem->vmap_use_count); | 659 | drm_printf_indent(p, indent, "vmap_use_count=%u\n", shmem->vmap_use_count); |
| 653 | drm_printf_indent(p, indent, "vaddr=%p\n", shmem->vaddr); | 660 | drm_printf_indent(p, indent, "vaddr=%p\n", shmem->vaddr); |
| @@ -672,7 +679,7 @@ struct sg_table *drm_gem_shmem_get_sg_table(struct drm_gem_shmem_object *shmem) · 18 unmodified lines | |||
| 672 | { | 679 | { |
| 673 | struct drm_gem_object *obj = &shmem->base; | 680 | struct drm_gem_object *obj = &shmem->base; |
| 674 | 681 | ||
| 675 | WARN_ON(shmem->base.import_attach); | 682 | drm_WARN_ON(obj->dev, obj->import_attach); |
| 676 | 683 | ||
| 677 | return drm_prime_pages_to_sg(obj->dev, shmem->pages, obj->size >> PAGE_SHIFT); | 684 | return drm_prime_pages_to_sg(obj->dev, shmem->pages, obj->size >> PAGE_SHIFT); |
| 678 | } | 685 | } |
| @@ -687,7 +694,7 @@ static struct sg_table *drm_gem_shmem_get_pages_sgt_locked(struct drm_gem_shmem_ · 8 unmodified lines | |||
| 687 | if (shmem->sgt) | 694 | if (shmem->sgt) |
| 688 | return shmem->sgt; | 695 | return shmem->sgt; |
| 689 | 696 | ||
| 690 | WARN_ON(obj->import_attach); | 697 | drm_WARN_ON(obj->dev, obj->import_attach); |
| 691 | 698 | ||
| 692 | ret = drm_gem_shmem_get_pages_locked(shmem); | 699 | ret = drm_gem_shmem_get_pages_locked(shmem); |
| 693 | if (ret) | 700 | if (ret) |
| @@ -916,6 +916,17 @@ static int bo_driver_move(struct ttm_buffer_object *bo, · 915 unmodified lines | |||
| 916 | { | 916 | { |
| 917 | struct drm_gem_vram_object *gbo; | 917 | struct drm_gem_vram_object *gbo; |
| 918 | 918 | ||
| 919 | if (!bo->resource) { | ||
| 920 | if (new_mem->mem_type != TTM_PL_SYSTEM) { | ||
| 921 | hop->mem_type = TTM_PL_SYSTEM; | ||
| 922 | hop->flags = TTM_PL_FLAG_TEMPORARY; | ||
| 923 | return -EMULTIHOP; | ||
| 924 | } | ||
| 925 | |||
| 926 | ttm_bo_move_null(bo, new_mem); | ||
| 927 | return 0; | ||
| 928 | } | ||
| 929 | |||
| 919 | gbo = drm_gem_vram_of_bo(bo); | 930 | gbo = drm_gem_vram_of_bo(bo); |
| 920 | 931 | ||
| 921 | return drm_gem_vram_bo_driver_move(gbo, evict, ctx, new_mem); | 932 | return drm_gem_vram_bo_driver_move(gbo, evict, ctx, new_mem); |
| @@ -178,9 +178,6 @@ void drm_gem_unpin(struct drm_gem_object *obj); · 177 unmodified lines | |||
| 178 | int drm_gem_vmap(struct drm_gem_object *obj, struct iosys_map *map); | 178 | int drm_gem_vmap(struct drm_gem_object *obj, struct iosys_map *map); |
| 179 | void drm_gem_vunmap(struct drm_gem_object *obj, struct iosys_map *map); | 179 | void drm_gem_vunmap(struct drm_gem_object *obj, struct iosys_map *map); |
| 180 | 180 | ||
| 181 | int drm_gem_dumb_destroy(struct drm_file *file, struct drm_device *dev, | ||
| 182 | u32 handle); | ||
| 183 | |||
| 184 | /* drm_debugfs.c drm_debugfs_crc.c */ | 181 | /* drm_debugfs.c drm_debugfs_crc.c */ |
| 185 | #if defined(CONFIG_DEBUG_FS) | 182 | #if defined(CONFIG_DEBUG_FS) |
| 186 | int drm_debugfs_init(struct drm_minor *minor, int minor_id, | 183 | int drm_debugfs_init(struct drm_minor *minor, int minor_id, |
| @@ -2339,8 +2339,7 @@ static int drm_mode_parse_cmdline_named_mode(const char *name, · 2338 unmodified lines | |||
| 2339 | * @mode: preallocated drm_cmdline_mode structure to fill out | 2339 | * @mode: preallocated drm_cmdline_mode structure to fill out |
| 2340 | * | 2340 | * |
| 2341 | * This parses @mode_option command line modeline for modes and options to | 2341 | * This parses @mode_option command line modeline for modes and options to |
| 2342 | * configure the connector. If @mode_option is NULL the default command line | 2342 | * configure the connector. |
| 2343 | * modeline in fb_mode_option will be parsed instead. | ||
| 2344 | * | 2343 | * |
| 2345 | * This uses the same parameters as the fb modedb.c, except for an extra | 2344 | * This uses the same parameters as the fb modedb.c, except for an extra |
| 2346 | * force-enable, force-enable-digital and force-disable bit at the end:: | 2345 | * force-enable, force-enable-digital and force-disable bit at the end:: |
| @@ -10,6 +10,7 @@ · 9 unmodified lines | |||
| 10 | #include <drm/drm_crtc.h> | 10 | #include <drm/drm_crtc.h> |
| 11 | #include <drm/drm_device.h> | 11 | #include <drm/drm_device.h> |
| 12 | #include <drm/drm_encoder.h> | 12 | #include <drm/drm_encoder.h> |
| 13 | #include <drm/drm_mipi_dsi.h> | ||
| 13 | #include <drm/drm_of.h> | 14 | #include <drm/drm_of.h> |
| 14 | #include <drm/drm_panel.h> | 15 | #include <drm/drm_panel.h> |
| 15 | 16 | ||
| @@ -493,3 +494,53 @@ int drm_of_get_data_lanes_count_ep(const struct device_node *port, · 477 unmodified lines | |||
| 493 | return ret; | 494 | return ret; |
| 494 | } | 495 | } |
| 495 | EXPORT_SYMBOL_GPL(drm_of_get_data_lanes_count_ep); | 496 | EXPORT_SYMBOL_GPL(drm_of_get_data_lanes_count_ep); |
| 497 | |||
| 498 | #if IS_ENABLED(CONFIG_DRM_MIPI_DSI) | ||
| 499 | |||
| 500 | /** | ||
| 501 | * drm_of_get_dsi_bus - find the DSI bus for a given device | ||
| 502 | * @dev: parent device of display (SPI, I2C) | ||
| 503 | * | ||
| 504 | * Gets parent DSI bus for a DSI device controlled through a bus other | ||
| 505 | * than MIPI-DCS (SPI, I2C, etc.) using the Device Tree. | ||
| 506 | * | ||
| 507 | * Returns pointer to mipi_dsi_host if successful, -EINVAL if the | ||
| 508 | * request is unsupported, -EPROBE_DEFER if the DSI host is found but | ||
| 509 | * not available, or -ENODEV otherwise. | ||
| 510 | */ | ||
| 511 | struct mipi_dsi_host *drm_of_get_dsi_bus(struct device *dev) | ||
| 512 | { | ||
| 513 | struct mipi_dsi_host *dsi_host; | ||
| 514 | struct device_node *endpoint, *dsi_host_node; | ||
| 515 | |||
| 516 | /* | ||
| 517 | * Get first endpoint child from device. | ||
| 518 | */ | ||
| 519 | endpoint = of_graph_get_next_endpoint(dev->of_node, NULL); | ||
| 520 | if (!endpoint) | ||
| 521 | return ERR_PTR(-ENODEV); | ||
| 522 | |||
| 523 | /* | ||
| 524 | * Follow the first endpoint to get the DSI host node and then | ||
| 525 | * release the endpoint since we no longer need it. | ||
| 526 | */ | ||
| 527 | dsi_host_node = of_graph_get_remote_port_parent(endpoint); | ||
| 528 | of_node_put(endpoint); | ||
| 529 | if (!dsi_host_node) | ||
| 530 | return ERR_PTR(-ENODEV); | ||
| 531 | |||
| 532 | /* | ||
| 533 | * Get the DSI host from the DSI host node. If we get an error | ||
| 534 | * or the return is null assume we're not ready to probe just | ||
| 535 | * yet. Release the DSI host node since we're done with it. | ||
| 536 | */ | ||
| 537 | dsi_host = of_find_mipi_dsi_host_by_node(dsi_host_node); | ||
| 538 | of_node_put(dsi_host_node); | ||
| 539 | if (IS_ERR_OR_NULL(dsi_host)) | ||
| 540 | return ERR_PTR(-EPROBE_DEFER); | ||
| 541 | |||
| 542 | return dsi_host; | ||
| 543 | } | ||
| 544 | EXPORT_SYMBOL_GPL(drm_of_get_dsi_bus); | ||
| 545 | |||
| 546 | #endif /* CONFIG_DRM_MIPI_DSI */ | ||
| @@ -590,8 +590,9 @@ retry: · 589 unmodified lines | |||
| 590 | */ | 590 | */ |
| 591 | dev->mode_config.delayed_event = true; | 591 | dev->mode_config.delayed_event = true; |
| 592 | if (dev->mode_config.poll_enabled) | 592 | if (dev->mode_config.poll_enabled) |
| 593 | schedule_delayed_work(&dev->mode_config.output_poll_work, | 593 | mod_delayed_work(system_wq, |
| 594 | 0); | 594 | &dev->mode_config.output_poll_work, |
| 595 | 0); | ||
| 595 | } | 596 | } |
| 596 | 597 | ||
| 597 | /* Re-enable polling in case the global poll config changed. */ | 598 | /* Re-enable polling in case the global poll config changed. */ |
| @@ -0,0 +1,457 @@ | |||
| 1 | // SPDX-License-Identifier: GPL-2.0 OR MIT | ||
| 2 | /* | ||
| 3 | * Copyright 2011 Red Hat Inc. | ||
| 4 | * Copyright 2023 Intel Corporation. | ||
| 5 | * All Rights Reserved. | ||
| 6 | * | ||
| 7 | * Permission is hereby granted, free of charge, to any person obtaining a | ||
| 8 | * copy of this software and associated documentation files (the | ||
| 9 | * "Software"), to deal in the Software without restriction, including | ||
| 10 | * without limitation the rights to use, copy, modify, merge, publish, | ||
| 11 | * distribute, sub license, and/or sell copies of the Software, and to | ||
| 12 | * permit persons to whom the Software is furnished to do so, subject to | ||
| 13 | * the following conditions: | ||
| 14 | * | ||
| 15 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR | ||
| 16 | * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, | ||
| 17 | * FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. IN NO EVENT SHALL | ||
| 18 | * THE COPYRIGHT HOLDERS, AUTHORS AND/OR ITS SUPPLIERS BE LIABLE FOR ANY CLAIM, | ||
| 19 | * DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR | ||
| 20 | * OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE | ||
| 21 | * USE OR OTHER DEALINGS IN THE SOFTWARE. | ||
| 22 | * | ||
| 23 | * The above copyright notice and this permission notice (including the | ||
| 24 | * next paragraph) shall be included in all copies or substantial portions | ||
| 25 | * of the Software. | ||
| 26 | * | ||
| 27 | */ | ||
| 28 | /* Algorithm: | ||
| 29 | * | ||
| 30 | * We store the last allocated bo in "hole", we always try to allocate | ||
| 31 | * after the last allocated bo. Principle is that in a linear GPU ring | ||
| 32 | * progression was is after last is the oldest bo we allocated and thus | ||
| 33 | * the first one that should no longer be in use by the GPU. | ||
| 34 | * | ||
| 35 | * If it's not the case we skip over the bo after last to the closest | ||
| 36 | * done bo if such one exist. If none exist and we are not asked to | ||
| 37 | * block we report failure to allocate. | ||
| 38 | * | ||
| 39 | * If we are asked to block we wait on all the oldest fence of all | ||
| 40 | * rings. We just wait for any of those fence to complete. | ||
| 41 | */ | ||
| 42 | |||
| 43 | #include <drm/drm_suballoc.h> | ||
| 44 | #include <drm/drm_print.h> | ||
| 45 | #include <linux/slab.h> | ||
| 46 | #include <linux/sched.h> | ||
| 47 | #include <linux/wait.h> | ||
| 48 | #include <linux/dma-fence.h> | ||
| 49 | |||
| 50 | static void drm_suballoc_remove_locked(struct drm_suballoc *sa); | ||
| 51 | static void drm_suballoc_try_free(struct drm_suballoc_manager *sa_manager); | ||
| 52 | |||
| 53 | /** | ||
| 54 | * drm_suballoc_manager_init() - Initialise the drm_suballoc_manager | ||
| 55 | * @sa_manager: pointer to the sa_manager | ||
| 56 | * @size: number of bytes we want to suballocate | ||
| 57 | * @align: alignment for each suballocated chunk | ||
| 58 | * | ||
| 59 | * Prepares the suballocation manager for suballocations. | ||
| 60 | */ | ||
| 61 | void drm_suballoc_manager_init(struct drm_suballoc_manager *sa_manager, | ||
| 62 | size_t size, size_t align) | ||
| 63 | { | ||
| 64 | unsigned int i; | ||
| 65 | |||
| 66 | BUILD_BUG_ON(!is_power_of_2(DRM_SUBALLOC_MAX_QUEUES)); | ||
| 67 | |||
| 68 | if (!align) | ||
| 69 | align = 1; | ||
| 70 | |||
| 71 | /* alignment must be a power of 2 */ | ||
| 72 | if (WARN_ON_ONCE(align & (align - 1))) | ||
| 73 | align = roundup_pow_of_two(align); | ||
| 74 | |||
| 75 | init_waitqueue_head(&sa_manager->wq); | ||
| 76 | sa_manager->size = size; | ||
| 77 | sa_manager->align = align; | ||
| 78 | sa_manager->hole = &sa_manager->olist; | ||
| 79 | INIT_LIST_HEAD(&sa_manager->olist); | ||
| 80 | for (i = 0; i < DRM_SUBALLOC_MAX_QUEUES; ++i) | ||
| 81 | INIT_LIST_HEAD(&sa_manager->flist[i]); | ||
| 82 | } | ||
| 83 | EXPORT_SYMBOL(drm_suballoc_manager_init); | ||
| 84 | |||
| 85 | /** | ||
| 86 | * drm_suballoc_manager_fini() - Destroy the drm_suballoc_manager | ||
| 87 | * @sa_manager: pointer to the sa_manager | ||
| 88 | * | ||
| 89 | * Cleans up the suballocation manager after use. All fences added | ||
| 90 | * with drm_suballoc_free() must be signaled, or we cannot clean up | ||
| 91 | * the entire manager. | ||
| 92 | */ | ||
| 93 | void drm_suballoc_manager_fini(struct drm_suballoc_manager *sa_manager) | ||
| 94 | { | ||
| 95 | struct drm_suballoc *sa, *tmp; | ||
| 96 | |||
| 97 | if (!sa_manager->size) | ||
| 98 | return; | ||
| 99 | |||
| 100 | if (!list_empty(&sa_manager->olist)) { | ||
| 101 | sa_manager->hole = &sa_manager->olist; | ||
| 102 | drm_suballoc_try_free(sa_manager); | ||
| 103 | if (!list_empty(&sa_manager->olist)) | ||
| 104 | DRM_ERROR("sa_manager is not empty, clearing anyway\n"); | ||
| 105 | } | ||
| 106 | list_for_each_entry_safe(sa, tmp, &sa_manager->olist, olist) { | ||
| 107 | drm_suballoc_remove_locked(sa); | ||
| 108 | } | ||
| 109 | |||
| 110 | sa_manager->size = 0; | ||
| 111 | } | ||
| 112 | EXPORT_SYMBOL(drm_suballoc_manager_fini); | ||
| 113 | |||
| 114 | static void drm_suballoc_remove_locked(struct drm_suballoc *sa) | ||
| 115 | { | ||
| 116 | struct drm_suballoc_manager *sa_manager = sa->manager; | ||
| 117 | |||
| 118 | if (sa_manager->hole == &sa->olist) | ||
| 119 | sa_manager->hole = sa->olist.prev; | ||
| 120 | |||
| 121 | list_del_init(&sa->olist); | ||
| 122 | list_del_init(&sa->flist); | ||
| 123 | dma_fence_put(sa->fence); | ||
| 124 | kfree(sa); | ||
| 125 | } | ||
| 126 | |||
| 127 | static void drm_suballoc_try_free(struct drm_suballoc_manager *sa_manager) | ||
| 128 | { | ||
| 129 | struct drm_suballoc *sa, *tmp; | ||
| 130 | |||
| 131 | if (sa_manager->hole->next == &sa_manager->olist) | ||
| 132 | return; | ||
| 133 | |||
| 134 | sa = list_entry(sa_manager->hole->next, struct drm_suballoc, olist); | ||
| 135 | list_for_each_entry_safe_from(sa, tmp, &sa_manager->olist, olist) { | ||
| 136 | if (!sa->fence || !dma_fence_is_signaled(sa->fence)) | ||
| 137 | return; | ||
| 138 | |||
| 139 | drm_suballoc_remove_locked(sa); | ||
| 140 | } | ||
| 141 | } | ||
| 142 | |||
| 143 | static size_t drm_suballoc_hole_soffset(struct drm_suballoc_manager *sa_manager) | ||
| 144 | { | ||
| 145 | struct list_head *hole = sa_manager->hole; | ||
| 146 | |||
| 147 | if (hole != &sa_manager->olist) | ||
| 148 | return list_entry(hole, struct drm_suballoc, olist)->eoffset; | ||
| 149 | |||
| 150 | return 0; | ||
| 151 | } | ||
| 152 | |||
| 153 | static size_t drm_suballoc_hole_eoffset(struct drm_suballoc_manager *sa_manager) | ||
| 154 | { | ||
| 155 | struct list_head *hole = sa_manager->hole; | ||
| 156 | |||
| 157 | if (hole->next != &sa_manager->olist) | ||
| 158 | return list_entry(hole->next, struct drm_suballoc, olist)->soffset; | ||
| 159 | return sa_manager->size; | ||
| 160 | } | ||
| 161 | |||
| 162 | static bool drm_suballoc_try_alloc(struct drm_suballoc_manager *sa_manager, | ||
| 163 | struct drm_suballoc *sa, | ||
| 164 | size_t size, size_t align) | ||
| 165 | { | ||
| 166 | size_t soffset, eoffset, wasted; | ||
| 167 | |||
| 168 | soffset = drm_suballoc_hole_soffset(sa_manager); | ||
| 169 | eoffset = drm_suballoc_hole_eoffset(sa_manager); | ||
| 170 | wasted = round_up(soffset, align) - soffset; | ||
| 171 | |||
| 172 | if ((eoffset - soffset) >= (size + wasted)) { | ||
| 173 | soffset += wasted; | ||
| 174 | |||
| 175 | sa->manager = sa_manager; | ||
| 176 | sa->soffset = soffset; | ||
| 177 | sa->eoffset = soffset + size; | ||
| 178 | list_add(&sa->olist, sa_manager->hole); | ||
| 179 | INIT_LIST_HEAD(&sa->flist); | ||
| 180 | sa_manager->hole = &sa->olist; | ||
| 181 | return true; | ||
| 182 | } | ||
| 183 | return false; | ||
| 184 | } | ||
| 185 | |||
| 186 | static bool __drm_suballoc_event(struct drm_suballoc_manager *sa_manager, | ||
| 187 | size_t size, size_t align) | ||
| 188 | { | ||
| 189 | size_t soffset, eoffset, wasted; | ||
| 190 | unsigned int i; | ||
| 191 | |||
| 192 | for (i = 0; i < DRM_SUBALLOC_MAX_QUEUES; ++i) | ||
| 193 | if (!list_empty(&sa_manager->flist[i])) | ||
| 194 | return true; | ||
| 195 | |||
| 196 | soffset = drm_suballoc_hole_soffset(sa_manager); | ||
| 197 | eoffset = drm_suballoc_hole_eoffset(sa_manager); | ||
| 198 | wasted = round_up(soffset, align) - soffset; | ||
| 199 | |||
| 200 | return ((eoffset - soffset) >= (size + wasted)); | ||
| 201 | } | ||
| 202 | |||
| 203 | /** | ||
| 204 | * drm_suballoc_event() - Check if we can stop waiting | ||
| 205 | * @sa_manager: pointer to the sa_manager | ||
| 206 | * @size: number of bytes we want to allocate | ||
| 207 | * @align: alignment we need to match | ||
| 208 | * | ||
| 209 | * Return: true if either there is a fence we can wait for or | ||
| 210 | * enough free memory to satisfy the allocation directly. | ||
| 211 | * false otherwise. | ||
| 212 | */ | ||
| 213 | static bool drm_suballoc_event(struct drm_suballoc_manager *sa_manager, | ||
| 214 | size_t size, size_t align) | ||
| 215 | { | ||
| 216 | bool ret; | ||
| 217 | |||
| 218 | spin_lock(&sa_manager->wq.lock); | ||
| 219 | ret = __drm_suballoc_event(sa_manager, size, align); | ||
| 220 | spin_unlock(&sa_manager->wq.lock); | ||
| 221 | return ret; | ||
| 222 | } | ||
| 223 | |||
| 224 | static bool drm_suballoc_next_hole(struct drm_suballoc_manager *sa_manager, | ||
| 225 | struct dma_fence **fences, | ||
| 226 | unsigned int *tries) | ||
| 227 | { | ||
| 228 | struct drm_suballoc *best_bo = NULL; | ||
| 229 | unsigned int i, best_idx; | ||
| 230 | size_t soffset, best, tmp; | ||
| 231 | |||
| 232 | /* if hole points to the end of the buffer */ | ||
| 233 | if (sa_manager->hole->next == &sa_manager->olist) { | ||
| 234 | /* try again with its beginning */ | ||
| 235 | sa_manager->hole = &sa_manager->olist; | ||
| 236 | return true; | ||
| 237 | } | ||
| 238 | |||
| 239 | soffset = drm_suballoc_hole_soffset(sa_manager); | ||
| 240 | /* to handle wrap around we add sa_manager->size */ | ||
| 241 | best = sa_manager->size * 2; | ||
| 242 | /* go over all fence list and try to find the closest sa | ||
| 243 | * of the current last | ||
| 244 | */ | ||
| 245 | for (i = 0; i < DRM_SUBALLOC_MAX_QUEUES; ++i) { | ||
| 246 | struct drm_suballoc *sa; | ||
| 247 | |||
| 248 | fences[i] = NULL; | ||
| 249 | |||
| 250 | if (list_empty(&sa_manager->flist[i])) | ||
| 251 | continue; | ||
| 252 | |||
| 253 | sa = list_first_entry(&sa_manager->flist[i], | ||
| 254 | struct drm_suballoc, flist); | ||
| 255 | |||
| 256 | if (!dma_fence_is_signaled(sa->fence)) { | ||
| 257 | fences[i] = sa->fence; | ||
| 258 | continue; | ||
| 259 | } | ||
| 260 | |||
| 261 | /* limit the number of tries each freelist gets */ | ||
| 262 | if (tries[i] > 2) | ||
| 263 | continue; | ||
| 264 | |||
| 265 | tmp = sa->soffset; | ||
| 266 | if (tmp < soffset) { | ||
| 267 | /* wrap around, pretend it's after */ | ||
| 268 | tmp += sa_manager->size; | ||
| 269 | } | ||
| 270 | tmp -= soffset; | ||
| 271 | if (tmp < best) { | ||
| 272 | /* this sa bo is the closest one */ | ||
| 273 | best = tmp; | ||
| 274 | best_idx = i; | ||
| 275 | best_bo = sa; | ||
| 276 | } | ||
| 277 | } | ||
| 278 | |||
| 279 | if (best_bo) { | ||
| 280 | ++tries[best_idx]; | ||
| 281 | sa_manager->hole = best_bo->olist.prev; | ||
| 282 | |||
| 283 | /* | ||
| 284 | * We know that this one is signaled, | ||
| 285 | * so it's safe to remove it. | ||
| 286 | */ | ||
| 287 | drm_suballoc_remove_locked(best_bo); | ||
| 288 | return true; | ||
| 289 | } | ||
| 290 | return false; | ||
| 291 | } | ||
| 292 | |||
| 293 | /** | ||
| 294 | * drm_suballoc_new() - Make a suballocation. | ||
| 295 | * @sa_manager: pointer to the sa_manager | ||
| 296 | * @size: number of bytes we want to suballocate. | ||
| 297 | * @gfp: gfp flags used for memory allocation. Typically GFP_KERNEL but | ||
| 298 | * the argument is provided for suballocations from reclaim context or | ||
| 299 | * where the caller wants to avoid pipelining rather than wait for | ||
| 300 | * reclaim. | ||
| 301 | * @intr: Whether to perform waits interruptible. This should typically | ||
| 302 | * always be true, unless the caller needs to propagate a | ||
| 303 | * non-interruptible context from above layers. | ||
| 304 | * @align: Alignment. Must not exceed the default manager alignment. | ||
| 305 | * If @align is zero, then the manager alignment is used. | ||
| 306 | * | ||
| 307 | * Try to make a suballocation of size @size, which will be rounded | ||
| 308 | * up to the alignment specified in specified in drm_suballoc_manager_init(). | ||
| 309 | * | ||
| 310 | * Return: a new suballocated bo, or an ERR_PTR. | ||
| 311 | */ | ||
| 312 | struct drm_suballoc * | ||
| 313 | drm_suballoc_new(struct drm_suballoc_manager *sa_manager, size_t size, | ||
| 314 | gfp_t gfp, bool intr, size_t align) | ||
| 315 | { | ||
| 316 | struct dma_fence *fences[DRM_SUBALLOC_MAX_QUEUES]; | ||
| 317 | unsigned int tries[DRM_SUBALLOC_MAX_QUEUES]; | ||
| 318 | unsigned int count; | ||
| 319 | int i, r; | ||
| 320 | struct drm_suballoc *sa; | ||
| 321 | |||
| 322 | if (WARN_ON_ONCE(align > sa_manager->align)) | ||
| 323 | return ERR_PTR(-EINVAL); | ||
| 324 | if (WARN_ON_ONCE(size > sa_manager->size || !size)) | ||
| 325 | return ERR_PTR(-EINVAL); | ||
| 326 | |||
| 327 | if (!align) | ||
| 328 | align = sa_manager->align; | ||
| 329 | |||
| 330 | sa = kmalloc(sizeof(*sa), gfp); | ||
| 331 | if (!sa) | ||
| 332 | return ERR_PTR(-ENOMEM); | ||
| 333 | sa->manager = sa_manager; | ||
| 334 | sa->fence = NULL; | ||
| 335 | INIT_LIST_HEAD(&sa->olist); | ||
| 336 | INIT_LIST_HEAD(&sa->flist); | ||
| 337 | |||
| 338 | spin_lock(&sa_manager->wq.lock); | ||
| 339 | do { | ||
| 340 | for (i = 0; i < DRM_SUBALLOC_MAX_QUEUES; ++i) | ||
| 341 | tries[i] = 0; | ||
| 342 | |||
| 343 | do { | ||
| 344 | drm_suballoc_try_free(sa_manager); | ||
| 345 | |||
| 346 | if (drm_suballoc_try_alloc(sa_manager, sa, | ||
| 347 | size, align)) { | ||
| 348 | spin_unlock(&sa_manager->wq.lock); | ||
| 349 | return sa; | ||
| 350 | } | ||
| 351 | |||
| 352 | /* see if we can skip over some allocations */ | ||
| 353 | } while (drm_suballoc_next_hole(sa_manager, fences, tries)); | ||
| 354 | |||
| 355 | for (i = 0, count = 0; i < DRM_SUBALLOC_MAX_QUEUES; ++i) | ||
| 356 | if (fences[i]) | ||
| 357 | fences[count++] = dma_fence_get(fences[i]); | ||
| 358 | |||
| 359 | if (count) { | ||
| 360 | long t; | ||
| 361 | |||
| 362 | spin_unlock(&sa_manager->wq.lock); | ||
| 363 | t = dma_fence_wait_any_timeout(fences, count, intr, | ||
| 364 | MAX_SCHEDULE_TIMEOUT, | ||
| 365 | NULL); | ||
| 366 | for (i = 0; i < count; ++i) | ||
| 367 | dma_fence_put(fences[i]); | ||
| 368 | |||
| 369 | r = (t > 0) ? 0 : t; | ||
| 370 | spin_lock(&sa_manager->wq.lock); | ||
| 371 | } else if (intr) { | ||
| 372 | /* if we have nothing to wait for block */ | ||
| 373 | r = wait_event_interruptible_locked | ||
| 374 | (sa_manager->wq, | ||
| 375 | __drm_suballoc_event(sa_manager, size, align)); | ||
| 376 | } else { | ||
| 377 | spin_unlock(&sa_manager->wq.lock); | ||
| 378 | wait_event(sa_manager->wq, | ||
| 379 | drm_suballoc_event(sa_manager, size, align)); | ||
| 380 | r = 0; | ||
| 381 | spin_lock(&sa_manager->wq.lock); | ||
| 382 | } | ||
| 383 | } while (!r); | ||
| 384 | |||
| 385 | spin_unlock(&sa_manager->wq.lock); | ||
| 386 | kfree(sa); | ||
| 387 | return ERR_PTR(r); | ||
| 388 | } | ||
| 389 | EXPORT_SYMBOL(drm_suballoc_new); | ||
| 390 | |||
| 391 | /** | ||
| 392 | * drm_suballoc_free - Free a suballocation | ||
| 393 | * @suballoc: pointer to the suballocation | ||
| 394 | * @fence: fence that signals when suballocation is idle | ||
| 395 | * | ||
| 396 | * Free the suballocation. The suballocation can be re-used after @fence signals. | ||
| 397 | */ | ||
| 398 | void drm_suballoc_free(struct drm_suballoc *suballoc, | ||
| 399 | struct dma_fence *fence) | ||
| 400 | { | ||
| 401 | struct drm_suballoc_manager *sa_manager; | ||
| 402 | |||
| 403 | if (!suballoc) | ||
| 404 | return; | ||
| 405 | |||
| 406 | sa_manager = suballoc->manager; | ||
| 407 | |||
| 408 | spin_lock(&sa_manager->wq.lock); | ||
| 409 | if (fence && !dma_fence_is_signaled(fence)) { | ||
| 410 | u32 idx; | ||
| 411 | |||
| 412 | suballoc->fence = dma_fence_get(fence); | ||
| 413 | idx = fence->context & (DRM_SUBALLOC_MAX_QUEUES - 1); | ||
| 414 | list_add_tail(&suballoc->flist, &sa_manager->flist[idx]); | ||
| 415 | } else { | ||
| 416 | drm_suballoc_remove_locked(suballoc); | ||
| 417 | } | ||
| 418 | wake_up_all_locked(&sa_manager->wq); | ||
| 419 | spin_unlock(&sa_manager->wq.lock); | ||
| 420 | } | ||
| 421 | EXPORT_SYMBOL(drm_suballoc_free); | ||
| 422 | |||
| 423 | #ifdef CONFIG_DEBUG_FS | ||
| 424 | void drm_suballoc_dump_debug_info(struct drm_suballoc_manager *sa_manager, | ||
| 425 | struct drm_printer *p, | ||
| 426 | unsigned long long suballoc_base) | ||
| 427 | { | ||
| 428 | struct drm_suballoc *i; | ||
| 429 | |||
| 430 | spin_lock(&sa_manager->wq.lock); | ||
| 431 | list_for_each_entry(i, &sa_manager->olist, olist) { | ||
| 432 | unsigned long long soffset = i->soffset; | ||
| 433 | unsigned long long eoffset = i->eoffset; | ||
| 434 | |||
| 435 | if (&i->olist == sa_manager->hole) | ||
| 436 | drm_puts(p, ">"); | ||
| 437 | else | ||
| 438 | drm_puts(p, " "); | ||
| 439 | |||
| 440 | drm_printf(p, "[0x%010llx 0x%010llx] size %8lld", | ||
| 441 | suballoc_base + soffset, suballoc_base + eoffset, | ||
| 442 | eoffset - soffset); | ||
| 443 | |||
| 444 | if (i->fence) | ||
| 445 | drm_printf(p, " protected by 0x%016llx on context %llu", | ||
| 446 | (unsigned long long)i->fence->seqno, | ||
| 447 | (unsigned long long)i->fence->context); | ||
| 448 | |||
| 449 | drm_puts(p, "\n"); | ||
| 450 | } | ||
| 451 | spin_unlock(&sa_manager->wq.lock); | ||
| 452 | } | ||
| 453 | EXPORT_SYMBOL(drm_suballoc_dump_debug_info); | ||
| 454 | #endif | ||
| 455 | MODULE_AUTHOR("Multiple"); | ||
| 456 | MODULE_DESCRIPTION("Range suballocator helper"); | ||
| 457 | MODULE_LICENSE("Dual MIT/GPL"); | ||
| @@ -472,7 +472,7 @@ static int i915_ttm_shrink(struct drm_i915_gem_object *obj, unsigned int flags) · 471 unmodified lines | |||
| 472 | struct ttm_placement place = {}; | 472 | struct ttm_placement place = {}; |
| 473 | int ret; | 473 | int ret; |
| 474 | 474 | ||
| 475 | if (!bo->ttm || bo->resource->mem_type != TTM_PL_SYSTEM) | 475 | if (!bo->ttm || i915_ttm_cpu_maps_iomem(bo->resource)) |
| 476 | return 0; | 476 | return 0; |
| 477 | 477 | ||
| 478 | GEM_BUG_ON(!i915_tt->is_shmem); | 478 | GEM_BUG_ON(!i915_tt->is_shmem); |
| @@ -511,7 +511,13 @@ static void i915_ttm_delete_mem_notify(struct ttm_buffer_object *bo) · 32 unmodified lines | |||
| 511 | { | 511 | { |
| 512 | struct drm_i915_gem_object *obj = i915_ttm_to_gem(bo); | 512 | struct drm_i915_gem_object *obj = i915_ttm_to_gem(bo); |
| 513 | 513 | ||
| 514 | if (bo->resource && !i915_ttm_is_ghost_object(bo)) { | 514 | /* |
| 515 | * This gets called twice by ttm, so long as we have a ttm resource or | ||
| 516 | * ttm_tt then we can still safely call this. Due to pipeline-gutting, | ||
| 517 | * we maybe have NULL bo->resource, but in that case we should always | ||
| 518 | * have a ttm alive (like if the pages are swapped out). | ||
| 519 | */ | ||
| 520 | if ((bo->resource || bo->ttm) && !i915_ttm_is_ghost_object(bo)) { | ||
| 515 | __i915_gem_object_pages_fini(obj); | 521 | __i915_gem_object_pages_fini(obj); |
| 516 | i915_ttm_free_cached_io_rsgt(obj); | 522 | i915_ttm_free_cached_io_rsgt(obj); |
| 517 | } | 523 | } |
| @@ -1067,11 +1073,12 @@ static vm_fault_t vm_fault_ttm(struct vm_fault *vmf) · 549 unmodified lines | |||
| 1067 | .interruptible = true, | 1073 | .interruptible = true, |
| 1068 | .no_wait_gpu = true, /* should be idle already */ | 1074 | .no_wait_gpu = true, /* should be idle already */ |
| 1069 | }; | 1075 | }; |
| 1076 | int err; | ||
| 1070 | 1077 | ||
| 1071 | GEM_BUG_ON(!bo->ttm || !(bo->ttm->page_flags & TTM_TT_FLAG_SWAPPED)); | 1078 | GEM_BUG_ON(!bo->ttm || !(bo->ttm->page_flags & TTM_TT_FLAG_SWAPPED)); |
| 1072 | 1079 | ||
| 1073 | ret = ttm_bo_validate(bo, i915_ttm_sys_placement(), &ctx); | 1080 | err = ttm_bo_validate(bo, i915_ttm_sys_placement(), &ctx); |
| 1074 | if (ret) { | 1081 | if (err) { |
| 1075 | dma_resv_unlock(bo->base.resv); | 1082 | dma_resv_unlock(bo->base.resv); |
| 1076 | return VM_FAULT_SIGBUS; | 1083 | return VM_FAULT_SIGBUS; |
| 1077 | } | 1084 | } |
| @@ -98,7 +98,7 @@ static inline bool i915_ttm_gtt_binds_lmem(struct ttm_resource *mem) · 97 unmodified lines | |||
| 98 | static inline bool i915_ttm_cpu_maps_iomem(struct ttm_resource *mem) | 98 | static inline bool i915_ttm_cpu_maps_iomem(struct ttm_resource *mem) |
| 99 | { | 99 | { |
| 100 | /* Once / if we support GGTT, this is also false for cached ttm_tts */ | 100 | /* Once / if we support GGTT, this is also false for cached ttm_tts */ |
| 101 | return mem->mem_type != I915_PL_SYSTEM; | 101 | return mem && mem->mem_type != I915_PL_SYSTEM; |
| 102 | } | 102 | } |
| 103 | 103 | ||
| 104 | bool i915_ttm_resource_mappable(struct ttm_resource *res); | 104 | bool i915_ttm_resource_mappable(struct ttm_resource *res); |
| @@ -711,6 +711,10 @@ int i915_gem_obj_copy_ttm(struct drm_i915_gem_object *dst, · 710 unmodified lines | |||
| 711 | 711 | ||
| 712 | assert_object_held(dst); | 712 | assert_object_held(dst); |
| 713 | assert_object_held(src); | 713 | assert_object_held(src); |
| 714 | |||
| 715 | if (GEM_WARN_ON(!src_bo->resource || !dst_bo->resource)) | ||
| 716 | return -EINVAL; | ||
| 717 | |||
| 714 | i915_deps_init(&deps, GFP_KERNEL | __GFP_NORETRY | __GFP_NOWARN); | 718 | i915_deps_init(&deps, GFP_KERNEL | __GFP_NORETRY | __GFP_NOWARN); |
| 715 | 719 | ||
| 716 | ret = dma_resv_reserve_fences(src_bo->base.resv, 1); | 720 | ret = dma_resv_reserve_fences(src_bo->base.resv, 1); |
| @@ -53,7 +53,7 @@ static int i915_ttm_backup(struct i915_gem_apply_to_region *apply, · 52 unmodified lines | |||
| 53 | unsigned int flags; | 53 | unsigned int flags; |
| 54 | int err = 0; | 54 | int err = 0; |
| 55 | 55 | ||
| 56 | if (bo->resource->mem_type == I915_PL_SYSTEM || obj->ttm.backup) | 56 | if (!i915_ttm_cpu_maps_iomem(bo->resource) || obj->ttm.backup) |
| 57 | return 0; | 57 | return 0; |
| 58 | 58 | ||
| 59 | if (pm_apply->allow_gpu && i915_gem_object_evictable(obj)) | 59 | if (pm_apply->allow_gpu && i915_gem_object_evictable(obj)) |
| @@ -187,7 +187,10 @@ static int i915_ttm_restore(struct i915_gem_apply_to_region *apply, · 127 unmodified lines | |||
| 187 | return err; | 187 | return err; |
| 188 | 188 | ||
| 189 | /* Content may have been swapped. */ | 189 | /* Content may have been swapped. */ |
| 190 | err = ttm_tt_populate(backup_bo->bdev, backup_bo->ttm, &ctx); | 190 | if (!backup_bo->resource) |
| 191 | err = ttm_bo_validate(backup_bo, i915_ttm_sys_placement(), &ctx); | ||
| 192 | if (!err) | ||
| 193 | err = ttm_tt_populate(backup_bo->bdev, backup_bo->ttm, &ctx); | ||
| 191 | if (!err) { | 194 | if (!err) { |
| 192 | err = i915_gem_obj_copy_ttm(obj, backup, pm_apply->allow_gpu, | 195 | err = i915_gem_obj_copy_ttm(obj, backup, pm_apply->allow_gpu, |
| 193 | false); | 196 | false); |
| @@ -866,10 +866,10 @@ meson_venc_hdmi_supported_mode(const struct drm_display_mode *mode) · 865 unmodified lines | |||
| 866 | DRM_MODE_FLAG_PVSYNC | DRM_MODE_FLAG_NVSYNC)) | 866 | DRM_MODE_FLAG_PVSYNC | DRM_MODE_FLAG_NVSYNC)) |
| 867 | return MODE_BAD; | 867 | return MODE_BAD; |
| 868 | 868 | ||
| 869 | if (mode->hdisplay < 640 || mode->hdisplay > 1920) | 869 | if (mode->hdisplay < 400 || mode->hdisplay > 1920) |
| 870 | return MODE_BAD_HVALUE; | 870 | return MODE_BAD_HVALUE; |
| 871 | 871 | ||
| 872 | if (mode->vdisplay < 480 || mode->vdisplay > 1200) | 872 | if (mode->vdisplay < 480 || mode->vdisplay > 1920) |
| 873 | return MODE_BAD_VVALUE; | 873 | return MODE_BAD_VVALUE; |
| 874 | 874 | ||
| 875 | return MODE_OK; | 875 | return MODE_OK; |
| @@ -375,12 +375,15 @@ int mgag200_primary_plane_helper_atomic_check(struct drm_plane *plane, · 374 unmodified lines | |||
| 375 | struct drm_atomic_state *new_state); | 375 | struct drm_atomic_state *new_state); |
| 376 | void mgag200_primary_plane_helper_atomic_update(struct drm_plane *plane, | 376 | void mgag200_primary_plane_helper_atomic_update(struct drm_plane *plane, |
| 377 | struct drm_atomic_state *old_state); | 377 | struct drm_atomic_state *old_state); |
| 378 | void mgag200_primary_plane_helper_atomic_enable(struct drm_plane *plane, | ||
| 379 | struct drm_atomic_state *state); | ||
| 378 | void mgag200_primary_plane_helper_atomic_disable(struct drm_plane *plane, | 380 | void mgag200_primary_plane_helper_atomic_disable(struct drm_plane *plane, |
| 379 | struct drm_atomic_state *old_state); | 381 | struct drm_atomic_state *old_state); |
| 380 | #define MGAG200_PRIMARY_PLANE_HELPER_FUNCS \ | 382 | #define MGAG200_PRIMARY_PLANE_HELPER_FUNCS \ |
| 381 | DRM_GEM_SHADOW_PLANE_HELPER_FUNCS, \ | 383 | DRM_GEM_SHADOW_PLANE_HELPER_FUNCS, \ |
| 382 | .atomic_check = mgag200_primary_plane_helper_atomic_check, \ | 384 | .atomic_check = mgag200_primary_plane_helper_atomic_check, \ |
| 383 | .atomic_update = mgag200_primary_plane_helper_atomic_update, \ | 385 | .atomic_update = mgag200_primary_plane_helper_atomic_update, \ |
| 386 | .atomic_enable = mgag200_primary_plane_helper_atomic_enable, \ | ||
| 384 | .atomic_disable = mgag200_primary_plane_helper_atomic_disable | 387 | .atomic_disable = mgag200_primary_plane_helper_atomic_disable |
| 385 | 388 | ||
| 386 | #define MGAG200_PRIMARY_PLANE_FUNCS \ | 389 | #define MGAG200_PRIMARY_PLANE_FUNCS \ |
| @@ -501,10 +501,6 @@ void mgag200_primary_plane_helper_atomic_update(struct drm_plane *plane, · 500 unmodified lines | |||
| 501 | struct drm_framebuffer *fb = plane_state->fb; | 501 | struct drm_framebuffer *fb = plane_state->fb; |
| 502 | struct drm_atomic_helper_damage_iter iter; | 502 | struct drm_atomic_helper_damage_iter iter; |
| 503 | struct drm_rect damage; | 503 | struct drm_rect damage; |
| 504 | u8 seq1; | ||
| 505 | |||
| 506 | if (!fb) | ||
| 507 | return; | ||
| 508 | 504 | ||
| 509 | drm_atomic_helper_damage_iter_init(&iter, old_plane_state, plane_state); | 505 | drm_atomic_helper_damage_iter_init(&iter, old_plane_state, plane_state); |
| 510 | drm_atomic_for_each_plane_damage(&iter, &damage) { | 506 | drm_atomic_for_each_plane_damage(&iter, &damage) { |
| @@ -514,13 +510,19 @@ void mgag200_primary_plane_helper_atomic_update(struct drm_plane *plane, · 3 unmodified lines | |||
| 514 | /* Always scanout image at VRAM offset 0 */ | 510 | /* Always scanout image at VRAM offset 0 */ |
| 515 | mgag200_set_startadd(mdev, (u32)0); | 511 | mgag200_set_startadd(mdev, (u32)0); |
| 516 | mgag200_set_offset(mdev, fb); | 512 | mgag200_set_offset(mdev, fb); |
| 513 | } | ||
| 517 | 514 | ||
| 518 | if (!old_plane_state->crtc && plane_state->crtc) { // enabling | 515 | void mgag200_primary_plane_helper_atomic_enable(struct drm_plane *plane, |
| 519 | RREG_SEQ(0x01, seq1); | 516 | struct drm_atomic_state *state) |
| 520 | seq1 &= ~MGAREG_SEQ1_SCROFF; | 517 | { |
| 521 | WREG_SEQ(0x01, seq1); | 518 | struct drm_device *dev = plane->dev; |
| 522 | msleep(20); | 519 | struct mga_device *mdev = to_mga_device(dev); |
| 523 | } | 520 | u8 seq1; |
| 521 | |||
| 522 | RREG_SEQ(0x01, seq1); | ||
| 523 | seq1 &= ~MGAREG_SEQ1_SCROFF; | ||
| 524 | WREG_SEQ(0x01, seq1); | ||
| 525 | msleep(20); | ||
| 524 | } | 526 | } |
| 525 | 527 | ||
| 526 | void mgag200_primary_plane_helper_atomic_disable(struct drm_plane *plane, | 528 | void mgag200_primary_plane_helper_atomic_disable(struct drm_plane *plane, |
| @@ -1015,9 +1015,6 @@ nouveau_bo_move(struct ttm_buffer_object *bo, bool evict, · 1014 unmodified lines | |||
| 1015 | if (ret) | 1015 | if (ret) |
| 1016 | goto out_ntfy; | 1016 | goto out_ntfy; |
| 1017 | 1017 | ||
| 1018 | if (nvbo->bo.pin_count) | ||
| 1019 | NV_WARN(drm, "Moving pinned object %p!\n", nvbo); | ||
| 1020 | |||
| 1021 | if (drm->client.device.info.family < NV_DEVICE_INFO_V0_TESLA) { | 1018 | if (drm->client.device.info.family < NV_DEVICE_INFO_V0_TESLA) { |
| 1022 | ret = nouveau_bo_vm_bind(bo, new_reg, &new_tile); | 1019 | ret = nouveau_bo_vm_bind(bo, new_reg, &new_tile); |
| 1023 | if (ret) | 1020 | if (ret) |
| @@ -41,7 +41,7 @@ static ssize_t · 40 unmodified lines | |||
| 41 | nouveau_hwmon_show_temp1_auto_point1_pwm(struct device *d, | 41 | nouveau_hwmon_show_temp1_auto_point1_pwm(struct device *d, |
| 42 | struct device_attribute *a, char *buf) | 42 | struct device_attribute *a, char *buf) |
| 43 | { | 43 | { |
| 44 | return snprintf(buf, PAGE_SIZE, "%d\n", 100); | 44 | return sysfs_emit(buf, "%d\n", 100); |
| 45 | } | 45 | } |
| 46 | static SENSOR_DEVICE_ATTR(temp1_auto_point1_pwm, 0444, | 46 | static SENSOR_DEVICE_ATTR(temp1_auto_point1_pwm, 0444, |
| 47 | nouveau_hwmon_show_temp1_auto_point1_pwm, NULL, 0); | 47 | nouveau_hwmon_show_temp1_auto_point1_pwm, NULL, 0); |
| @@ -54,8 +54,8 @@ nouveau_hwmon_temp1_auto_point1_temp(struct device *d, · 6 unmodified lines | |||
| 54 | struct nouveau_drm *drm = nouveau_drm(dev); | 54 | struct nouveau_drm *drm = nouveau_drm(dev); |
| 55 | struct nvkm_therm *therm = nvxx_therm(&drm->client.device); | 55 | struct nvkm_therm *therm = nvxx_therm(&drm->client.device); |
| 56 | 56 | ||
| 57 | return snprintf(buf, PAGE_SIZE, "%d\n", | 57 | return sysfs_emit(buf, "%d\n", |
| 58 | therm->attr_get(therm, NVKM_THERM_ATTR_THRS_FAN_BOOST) * 1000); | 58 | therm->attr_get(therm, NVKM_THERM_ATTR_THRS_FAN_BOOST) * 1000); |
| 59 | } | 59 | } |
| 60 | static ssize_t | 60 | static ssize_t |
| 61 | nouveau_hwmon_set_temp1_auto_point1_temp(struct device *d, | 61 | nouveau_hwmon_set_temp1_auto_point1_temp(struct device *d, |
| @@ -87,8 +87,8 @@ nouveau_hwmon_temp1_auto_point1_temp_hyst(struct device *d, · 25 unmodified lines | |||
| 87 | struct nouveau_drm *drm = nouveau_drm(dev); | 87 | struct nouveau_drm *drm = nouveau_drm(dev); |
| 88 | struct nvkm_therm *therm = nvxx_therm(&drm->client.device); | 88 | struct nvkm_therm *therm = nvxx_therm(&drm->client.device); |
| 89 | 89 | ||
| 90 | return snprintf(buf, PAGE_SIZE, "%d\n", | 90 | return sysfs_emit(buf, "%d\n", |
| 91 | therm->attr_get(therm, NVKM_THERM_ATTR_THRS_FAN_BOOST_HYST) * 1000); | 91 | therm->attr_get(therm, NVKM_THERM_ATTR_THRS_FAN_BOOST_HYST) * 1000); |
| 92 | } | 92 | } |
| 93 | static ssize_t | 93 | static ssize_t |
| 94 | nouveau_hwmon_set_temp1_auto_point1_temp_hyst(struct device *d, | 94 | nouveau_hwmon_set_temp1_auto_point1_temp_hyst(struct device *d, |
| @@ -27,7 +27,7 @@ · 26 unmodified lines | |||
| 27 | 27 | ||
| 28 | #include "nouveau_drv.h" | 28 | #include "nouveau_drv.h" |
| 29 | 29 | ||
| 30 | struct led_classdev; | 30 | #include <linux/leds.h> |
| 31 | 31 | ||
| 32 | struct nouveau_led { | 32 | struct nouveau_led { |
| 33 | struct drm_device *dev; | 33 | struct drm_device *dev; |
| @@ -318,6 +318,17 @@ config DRM_PANEL_LG_LG4573 · 317 unmodified lines | |||
| 318 | Say Y here if you want to enable support for LG4573 RGB panel. | 318 | Say Y here if you want to enable support for LG4573 RGB panel. |
| 319 | To compile this driver as a module, choose M here. | 319 | To compile this driver as a module, choose M here. |
| 320 | 320 | ||
| 321 | config DRM_PANEL_MAGNACHIP_D53E6EA8966 | ||
| 322 | tristate "Magnachip D53E6EA8966 DSI panel" | ||
| 323 | depends on OF && SPI | ||
| 324 | depends on DRM_MIPI_DSI | ||
| 325 | depends on BACKLIGHT_CLASS_DEVICE | ||
| 326 | select DRM_MIPI_DBI | ||
| 327 | help | ||
| 328 | DRM panel driver for the Samsung AMS495QA01 panel controlled | ||
| 329 | with the Magnachip D53E6EA8966 panel IC. This panel receives | ||
| 330 | video data via DSI but commands via 9-bit SPI using DBI. | ||
| 331 | |||
| 321 | config DRM_PANEL_NEC_NL8048HL11 | 332 | config DRM_PANEL_NEC_NL8048HL11 |
| 322 | tristate "NEC NL8048HL11 RGB panel" | 333 | tristate "NEC NL8048HL11 RGB panel" |
| 323 | depends on GPIOLIB && OF && SPI | 334 | depends on GPIOLIB && OF && SPI |
| @@ -29,6 +29,7 @@ obj-$(CONFIG_DRM_PANEL_LEADTEK_LTK050H3146W) += panel-leadtek-ltk050h3146w.o · 28 unmodified lines | |||
| 29 | obj-$(CONFIG_DRM_PANEL_LEADTEK_LTK500HD1829) += panel-leadtek-ltk500hd1829.o | 29 | obj-$(CONFIG_DRM_PANEL_LEADTEK_LTK500HD1829) += panel-leadtek-ltk500hd1829.o |
| 30 | obj-$(CONFIG_DRM_PANEL_LG_LB035Q02) += panel-lg-lb035q02.o | 30 | obj-$(CONFIG_DRM_PANEL_LG_LB035Q02) += panel-lg-lb035q02.o |
| 31 | obj-$(CONFIG_DRM_PANEL_LG_LG4573) += panel-lg-lg4573.o | 31 | obj-$(CONFIG_DRM_PANEL_LG_LG4573) += panel-lg-lg4573.o |
| 32 | obj-$(CONFIG_DRM_PANEL_MAGNACHIP_D53E6EA8966) += panel-magnachip-d53e6ea8966.o | ||
| 32 | obj-$(CONFIG_DRM_PANEL_NEC_NL8048HL11) += panel-nec-nl8048hl11.o | 33 | obj-$(CONFIG_DRM_PANEL_NEC_NL8048HL11) += panel-nec-nl8048hl11.o |
| 33 | obj-$(CONFIG_DRM_PANEL_NEWVISION_NV3051D) += panel-newvision-nv3051d.o | 34 | obj-$(CONFIG_DRM_PANEL_NEWVISION_NV3051D) += panel-newvision-nv3051d.o |
| 34 | obj-$(CONFIG_DRM_PANEL_NEWVISION_NV3052C) += panel-newvision-nv3052c.o | 35 | obj-$(CONFIG_DRM_PANEL_NEWVISION_NV3052C) += panel-newvision-nv3052c.o |
| @@ -167,6 +167,202 @@ static const struct drm_panel_funcs jadard_funcs = { · 166 unmodified lines | |||
| 167 | .get_modes = jadard_get_modes, | 167 | .get_modes = jadard_get_modes, |
| 168 | }; | 168 | }; |
| 169 | 169 | ||
| 170 | static const struct jadard_init_cmd radxa_display_8hd_ad002_init_cmds[] = { | ||
| 171 | { .data = { 0xE0, 0x00 } }, | ||
| 172 | { .data = { 0xE1, 0x93 } }, | ||
| 173 | { .data = { 0xE2, 0x65 } }, | ||
| 174 | { .data = { 0xE3, 0xF8 } }, | ||
| 175 | { .data = { 0x80, 0x03 } }, | ||
| 176 | { .data = { 0xE0, 0x01 } }, | ||
| 177 | { .data = { 0x00, 0x00 } }, | ||
| 178 | { .data = { 0x01, 0x7E } }, | ||
| 179 | { .data = { 0x03, 0x00 } }, | ||
| 180 | { .data = { 0x04, 0x65 } }, | ||
| 181 | { .data = { 0x0C, 0x74 } }, | ||
| 182 | { .data = { 0x17, 0x00 } }, | ||
| 183 | { .data = { 0x18, 0xB7 } }, | ||
| 184 | { .data = { 0x19, 0x00 } }, | ||
| 185 | { .data = { 0x1A, 0x00 } }, | ||
| 186 | { .data = { 0x1B, 0xB7 } }, | ||
| 187 | { .data = { 0x1C, 0x00 } }, | ||
| 188 | { .data = { 0x24, 0xFE } }, | ||
| 189 | { .data = { 0x37, 0x19 } }, | ||
| 190 | { .data = { 0x38, 0x05 } }, | ||
| 191 | { .data = { 0x39, 0x00 } }, | ||
| 192 | { .data = { 0x3A, 0x01 } }, | ||
| 193 | { .data = { 0x3B, 0x01 } }, | ||
| 194 | { .data = { 0x3C, 0x70 } }, | ||
| 195 | { .data = { 0x3D, 0xFF } }, | ||
| 196 | { .data = { 0x3E, 0xFF } }, | ||
| 197 | { .data = { 0x3F, 0xFF } }, | ||
| 198 | { .data = { 0x40, 0x06 } }, | ||
| 199 | { .data = { 0x41, 0xA0 } }, | ||
| 200 | { .data = { 0x43, 0x1E } }, | ||
| 201 | { .data = { 0x44, 0x0F } }, | ||
| 202 | { .data = { 0x45, 0x28 } }, | ||
| 203 | { .data = { 0x4B, 0x04 } }, | ||
| 204 | { .data = { 0x55, 0x02 } }, | ||
| 205 | { .data = { 0x56, 0x01 } }, | ||
| 206 | { .data = { 0x57, 0xA9 } }, | ||
| 207 | { .data = { 0x58, 0x0A } }, | ||
| 208 | { .data = { 0x59, 0x0A } }, | ||
| 209 | { .data = { 0x5A, 0x37 } }, | ||
| 210 | { .data = { 0x5B, 0x19 } }, | ||
| 211 | { .data = { 0x5D, 0x78 } }, | ||
| 212 | { .data = { 0x5E, 0x63 } }, | ||
| 213 | { .data = { 0x5F, 0x54 } }, | ||
| 214 | { .data = { 0x60, 0x49 } }, | ||
| 215 | { .data = { 0x61, 0x45 } }, | ||
| 216 | { .data = { 0x62, 0x38 } }, | ||
| 217 | { .data = { 0x63, 0x3D } }, | ||
| 218 | { .data = { 0x64, 0x28 } }, | ||
| 219 | { .data = { 0x65, 0x43 } }, | ||
| 220 | { .data = { 0x66, 0x41 } }, | ||
| 221 | { .data = { 0x67, 0x43 } }, | ||
| 222 | { .data = { 0x68, 0x62 } }, | ||
| 223 | { .data = { 0x69, 0x50 } }, | ||
| 224 | { .data = { 0x6A, 0x57 } }, | ||
| 225 | { .data = { 0x6B, 0x49 } }, | ||
| 226 | { .data = { 0x6C, 0x44 } }, | ||
| 227 | { .data = { 0x6D, 0x37 } }, | ||
| 228 | { .data = { 0x6E, 0x23 } }, | ||
| 229 | { .data = { 0x6F, 0x10 } }, | ||
| 230 | { .data = { 0x70, 0x78 } }, | ||
| 231 | { .data = { 0x71, 0x63 } }, | ||
| 232 | { .data = { 0x72, 0x54 } }, | ||
| 233 | { .data = { 0x73, 0x49 } }, | ||
| 234 | { .data = { 0x74, 0x45 } }, | ||
| 235 | { .data = { 0x75, 0x38 } }, | ||
| 236 | { .data = { 0x76, 0x3D } }, | ||
| 237 | { .data = { 0x77, 0x28 } }, | ||
| 238 | { .data = { 0x78, 0x43 } }, | ||
| 239 | { .data = { 0x79, 0x41 } }, | ||
| 240 | { .data = { 0x7A, 0x43 } }, | ||
| 241 | { .data = { 0x7B, 0x62 } }, | ||
| 242 | { .data = { 0x7C, 0x50 } }, | ||
| 243 | { .data = { 0x7D, 0x57 } }, | ||
| 244 | { .data = { 0x7E, 0x49 } }, | ||
| 245 | { .data = { 0x7F, 0x44 } }, | ||
| 246 | { .data = { 0x80, 0x37 } }, | ||
| 247 | { .data = { 0x81, 0x23 } }, | ||
| 248 | { .data = { 0x82, 0x10 } }, | ||
| 249 | { .data = { 0xE0, 0x02 } }, | ||
| 250 | { .data = { 0x00, 0x47 } }, | ||
| 251 | { .data = { 0x01, 0x47 } }, | ||
| 252 | { .data = { 0x02, 0x45 } }, | ||
| 253 | { .data = { 0x03, 0x45 } }, | ||
| 254 | { .data = { 0x04, 0x4B } }, | ||
| 255 | { .data = { 0x05, 0x4B } }, | ||
| 256 | { .data = { 0x06, 0x49 } }, | ||
| 257 | { .data = { 0x07, 0x49 } }, | ||
| 258 | { .data = { 0x08, 0x41 } }, | ||
| 259 | { .data = { 0x09, 0x1F } }, | ||
| 260 | { .data = { 0x0A, 0x1F } }, | ||
| 261 | { .data = { 0x0B, 0x1F } }, | ||
| 262 | { .data = { 0x0C, 0x1F } }, | ||
| 263 | { .data = { 0x0D, 0x1F } }, | ||
| 264 | { .data = { 0x0E, 0x1F } }, | ||
| 265 | { .data = { 0x0F, 0x5F } }, | ||
| 266 | { .data = { 0x10, 0x5F } }, | ||
| 267 | { .data = { 0x11, 0x57 } }, | ||
| 268 | { .data = { 0x12, 0x77 } }, | ||
| 269 | { .data = { 0x13, 0x35 } }, | ||
| 270 | { .data = { 0x14, 0x1F } }, | ||
| 271 | { .data = { 0x15, 0x1F } }, | ||
| 272 | { .data = { 0x16, 0x46 } }, | ||
| 273 | { .data = { 0x17, 0x46 } }, | ||
| 274 | { .data = { 0x18, 0x44 } }, | ||
| 275 | { .data = { 0x19, 0x44 } }, | ||
| 276 | { .data = { 0x1A, 0x4A } }, | ||
| 277 | { .data = { 0x1B, 0x4A } }, | ||
| 278 | { .data = { 0x1C, 0x48 } }, | ||
| 279 | { .data = { 0x1D, 0x48 } }, | ||
| 280 | { .data = { 0x1E, 0x40 } }, | ||
| 281 | { .data = { 0x1F, 0x1F } }, | ||
| 282 | { .data = { 0x20, 0x1F } }, | ||
| 283 | { .data = { 0x21, 0x1F } }, | ||
| 284 | { .data = { 0x22, 0x1F } }, | ||
| 285 | { .data = { 0x23, 0x1F } }, | ||
| 286 | { .data = { 0x24, 0x1F } }, | ||
| 287 | { .data = { 0x25, 0x5F } }, | ||
| 288 | { .data = { 0x26, 0x5F } }, | ||
| 289 | { .data = { 0x27, 0x57 } }, | ||
| 290 | { .data = { 0x28, 0x77 } }, | ||
| 291 | { .data = { 0x29, 0x35 } }, | ||
| 292 | { .data = { 0x2A, 0x1F } }, | ||
| 293 | { .data = { 0x2B, 0x1F } }, | ||
| 294 | { .data = { 0x58, 0x40 } }, | ||
| 295 | { .data = { 0x59, 0x00 } }, | ||
| 296 | { .data = { 0x5A, 0x00 } }, | ||
| 297 | { .data = { 0x5B, 0x10 } }, | ||
| 298 | { .data = { 0x5C, 0x06 } }, | ||
| 299 | { .data = { 0x5D, 0x40 } }, | ||
| 300 | { .data = { 0x5E, 0x01 } }, | ||
| 301 | { .data = { 0x5F, 0x02 } }, | ||
| 302 | { .data = { 0x60, 0x30 } }, | ||
| 303 | { .data = { 0x61, 0x01 } }, | ||
| 304 | { .data = { 0x62, 0x02 } }, | ||
| 305 | { .data = { 0x63, 0x03 } }, | ||
| 306 | { .data = { 0x64, 0x6B } }, | ||
| 307 | { .data = { 0x65, 0x05 } }, | ||
| 308 | { .data = { 0x66, 0x0C } }, | ||
| 309 | { .data = { 0x67, 0x73 } }, | ||
| 310 | { .data = { 0x68, 0x09 } }, | ||
| 311 | { .data = { 0x69, 0x03 } }, | ||
| 312 | { .data = { 0x6A, 0x56 } }, | ||
| 313 | { .data = { 0x6B, 0x08 } }, | ||
| 314 | { .data = { 0x6C, 0x00 } }, | ||
| 315 | { .data = { 0x6D, 0x04 } }, | ||
| 316 | { .data = { 0x6E, 0x04 } }, | ||
| 317 | { .data = { 0x6F, 0x88 } }, | ||
| 318 | { .data = { 0x70, 0x00 } }, | ||
| 319 | { .data = { 0x71, 0x00 } }, | ||
| 320 | { .data = { 0x72, 0x06 } }, | ||
| 321 | { .data = { 0x73, 0x7B } }, | ||
| 322 | { .data = { 0x74, 0x00 } }, | ||
| 323 | { .data = { 0x75, 0xF8 } }, | ||
| 324 | { .data = { 0x76, 0x00 } }, | ||
| 325 | { .data = { 0x77, 0xD5 } }, | ||
| 326 | { .data = { 0x78, 0x2E } }, | ||
| 327 | { .data = { 0x79, 0x12 } }, | ||
| 328 | { .data = { 0x7A, 0x03 } }, | ||
| 329 | { .data = { 0x7B, 0x00 } }, | ||
| 330 | { .data = { 0x7C, 0x00 } }, | ||
| 331 | { .data = { 0x7D, 0x03 } }, | ||
| 332 | { .data = { 0x7E, 0x7B } }, | ||
| 333 | { .data = { 0xE0, 0x04 } }, | ||
| 334 | { .data = { 0x00, 0x0E } }, | ||
| 335 | { .data = { 0x02, 0xB3 } }, | ||
| 336 | { .data = { 0x09, 0x60 } }, | ||
| 337 | { .data = { 0x0E, 0x2A } }, | ||
| 338 | { .data = { 0x36, 0x59 } }, | ||
| 339 | { .data = { 0xE0, 0x00 } }, | ||
| 340 | }; | ||
| 341 | |||
| 342 | static const struct jadard_panel_desc radxa_display_8hd_ad002_desc = { | ||
| 343 | .mode = { | ||
| 344 | .clock = 70000, | ||
| 345 | |||
| 346 | .hdisplay = 800, | ||
| 347 | .hsync_start = 800 + 40, | ||
| 348 | .hsync_end = 800 + 40 + 18, | ||
| 349 | .htotal = 800 + 40 + 18 + 20, | ||
| 350 | |||
| 351 | .vdisplay = 1280, | ||
| 352 | .vsync_start = 1280 + 20, | ||
| 353 | .vsync_end = 1280 + 20 + 4, | ||
| 354 | .vtotal = 1280 + 20 + 4 + 20, | ||
| 355 | |||
| 356 | .width_mm = 127, | ||
| 357 | .height_mm = 199, | ||
| 358 | .type = DRM_MODE_TYPE_DRIVER | DRM_MODE_TYPE_PREFERRED, | ||
| 359 | }, | ||
| 360 | .lanes = 4, | ||
| 361 | .format = MIPI_DSI_FMT_RGB888, | ||
| 362 | .init_cmds = radxa_display_8hd_ad002_init_cmds, | ||
| 363 | .num_init_cmds = ARRAY_SIZE(radxa_display_8hd_ad002_init_cmds), | ||
| 364 | }; | ||
| 365 | |||
| 170 | static const struct jadard_init_cmd cz101b4001_init_cmds[] = { | 366 | static const struct jadard_init_cmd cz101b4001_init_cmds[] = { |
| 171 | { .data = { 0xE0, 0x00 } }, | 367 | { .data = { 0xE0, 0x00 } }, |
| 172 | { .data = { 0xE1, 0x93 } }, | 368 | { .data = { 0xE1, 0x93 } }, |
| @@ -452,7 +648,18 @@ static void jadard_dsi_remove(struct mipi_dsi_device *dsi) · 279 unmodified lines | |||
| 452 | } | 648 | } |
| 453 | 649 | ||
| 454 | static const struct of_device_id jadard_of_match[] = { | 650 | static const struct of_device_id jadard_of_match[] = { |
| 455 | { .compatible = "chongzhou,cz101b4001", .data = &cz101b4001_desc }, | 651 | { |
| 652 | .compatible = "chongzhou,cz101b4001", | ||
| 653 | .data = &cz101b4001_desc | ||
| 654 | }, | ||
| 655 | { | ||
| 656 | .compatible = "radxa,display-10hd-ad001", | ||
| 657 | .data = &cz101b4001_desc | ||
| 658 | }, | ||
| 659 | { | ||
| 660 | .compatible = "radxa,display-8hd-ad002", | ||
| 661 | .data = &radxa_display_8hd_ad002_desc | ||
| 662 | }, | ||
| 456 | { /* sentinel */ } | 663 | { /* sentinel */ } |
| 457 | }; | 664 | }; |
| 458 | MODULE_DEVICE_TABLE(of, jadard_of_match); | 665 | MODULE_DEVICE_TABLE(of, jadard_of_match); |
| @@ -0,0 +1,522 @@ | |||
| 1 | // SPDX-License-Identifier: GPL-2.0 | ||
| 2 | /* | ||
| 3 | * Magnachip d53e6ea8966 MIPI-DSI panel driver | ||
| 4 | * Copyright (C) 2023 Chris Morgan | ||
| 5 | */ | ||
| 6 | |||
| 7 | #include <drm/drm_mipi_dbi.h> | ||
| 8 | #include <drm/drm_mipi_dsi.h> | ||
| 9 | #include <drm/drm_modes.h> | ||
| 10 | #include <drm/drm_of.h> | ||
| 11 | #include <drm/drm_panel.h> | ||
| 12 | |||
| 13 | #include <linux/backlight.h> | ||
| 14 | #include <linux/delay.h> | ||
| 15 | #include <linux/gpio/consumer.h> | ||
| 16 | #include <linux/init.h> | ||
| 17 | #include <linux/kernel.h> | ||
| 18 | #include <linux/media-bus-format.h> | ||
| 19 | #include <linux/module.h> | ||
| 20 | #include <linux/of.h> | ||
| 21 | #include <linux/of_device.h> | ||
| 22 | #include <linux/regulator/consumer.h> | ||
| 23 | #include <linux/spi/spi.h> | ||
| 24 | |||
| 25 | #include <video/mipi_display.h> | ||
| 26 | |||
| 27 | /* Forward declaration for use in backlight function */ | ||
| 28 | struct d53e6ea8966; | ||
| 29 | |||
| 30 | /* Panel info, unique to each panel */ | ||
| 31 | struct d53e6ea8966_panel_info { | ||
| 32 | /** @display_modes: the supported display modes */ | ||
| 33 | const struct drm_display_mode *display_modes; | ||
| 34 | /** @num_modes: the number of supported display modes */ | ||
| 35 | unsigned int num_modes; | ||
| 36 | /** @width_mm: panel width in mm */ | ||
| 37 | u16 width_mm; | ||
| 38 | /** @height_mm: panel height in mm */ | ||
| 39 | u16 height_mm; | ||
| 40 | /** @bus_flags: drm bus flags for panel */ | ||
| 41 | u32 bus_flags; | ||
| 42 | /** @panel_init_seq: panel specific init sequence */ | ||
| 43 | void (*panel_init_seq)(struct d53e6ea8966 *db); | ||
| 44 | /** @backlight_register: panel backlight registration or NULL */ | ||
| 45 | int (*backlight_register)(struct d53e6ea8966 *db); | ||
| 46 | }; | ||
| 47 | |||
| 48 | struct d53e6ea8966 { | ||
| 49 | /** @dev: the container device */ | ||
| 50 | struct device *dev; | ||
| 51 | /** @dbi: the DBI bus abstraction handle */ | ||
| 52 | struct mipi_dbi dbi; | ||
| 53 | /** @panel: the DRM panel instance for this device */ | ||
| 54 | struct drm_panel panel; | ||
| 55 | /** @reset: reset GPIO line */ | ||
| 56 | struct gpio_desc *reset; | ||
| 57 | /** @enable: enable GPIO line */ | ||
| 58 | struct gpio_desc *enable; | ||
| 59 | /** @reg_vdd: VDD supply regulator for panel logic */ | ||
| 60 | struct regulator *reg_vdd; | ||
| 61 | /** @reg_elvdd: ELVDD supply regulator for panel display */ | ||
| 62 | struct regulator *reg_elvdd; | ||
| 63 | /** @dsi_dev: DSI child device (panel) */ | ||
| 64 | struct mipi_dsi_device *dsi_dev; | ||
| 65 | /** @bl_dev: pseudo-backlight device for oled panel */ | ||
| 66 | struct backlight_device *bl_dev; | ||
| 67 | /** @panel_info: struct containing panel timing and info */ | ||
| 68 | const struct d53e6ea8966_panel_info *panel_info; | ||
| 69 | }; | ||
| 70 | |||
| 71 | #define NUM_GAMMA_LEVELS 16 | ||
| 72 | #define GAMMA_TABLE_COUNT 23 | ||
| 73 | #define MAX_BRIGHTNESS (NUM_GAMMA_LEVELS - 1) | ||
| 74 | |||
| 75 | #define MCS_ELVSS_ON 0xb1 | ||
| 76 | #define MCS_TEMP_SWIRE 0xb2 | ||
| 77 | #define MCS_PASSWORD_0 0xf0 | ||
| 78 | #define MCS_PASSWORD_1 0xf1 | ||
| 79 | #define MCS_ANALOG_PWR_CTL_0 0xf4 | ||
| 80 | #define MCS_ANALOG_PWR_CTL_1 0xf5 | ||
| 81 | #define MCS_GTCON_SET 0xf7 | ||
| 82 | #define MCS_GATELESS_SIGNAL_SET 0xf8 | ||
| 83 | #define MCS_SET_GAMMA 0xf9 | ||
| 84 | |||
| 85 | static inline struct d53e6ea8966 *to_d53e6ea8966(struct drm_panel *panel) | ||
| 86 | { | ||
| 87 | return container_of(panel, struct d53e6ea8966, panel); | ||
| 88 | } | ||
| 89 | |||
| 90 | /* Table of gamma values provided in datasheet */ | ||
| 91 | static u8 ams495qa01_gamma[NUM_GAMMA_LEVELS][GAMMA_TABLE_COUNT] = { | ||
| 92 | {0x01, 0x79, 0x78, 0x8d, 0xd9, 0xdf, 0xd5, 0xcb, 0xcf, 0xc5, | ||
| 93 | 0xe5, 0xe0, 0xe4, 0xdc, 0xb8, 0xd4, 0xfa, 0xed, 0xe6, 0x2f, | ||
| 94 | 0x00, 0x2f}, | ||
| 95 | {0x01, 0x7d, 0x7c, 0x92, 0xd7, 0xdd, 0xd2, 0xcb, 0xd0, 0xc6, | ||
| 96 | 0xe5, 0xe1, 0xe3, 0xda, 0xbd, 0xd3, 0xfa, 0xed, 0xe6, 0x2f, | ||
| 97 | 0x00, 0x2f}, | ||
| 98 | {0x01, 0x7f, 0x7e, 0x95, 0xd7, 0xde, 0xd2, 0xcb, 0xcf, 0xc5, | ||
| 99 | 0xe5, 0xe3, 0xe3, 0xda, 0xbf, 0xd3, 0xfa, 0xed, 0xe6, 0x2f, | ||
| 100 | 0x00, 0x2f}, | ||
| 101 | {0x01, 0x82, 0x81, 0x99, 0xd6, 0xdd, 0xd1, 0xca, 0xcf, 0xc3, | ||
| 102 | 0xe4, 0xe3, 0xe3, 0xda, 0xc2, 0xd3, 0xfa, 0xed, 0xe6, 0x2f, | ||
| 103 | 0x00, 0x2f}, | ||
| 104 | {0x01, 0x84, 0x83, 0x9b, 0xd7, 0xde, 0xd2, 0xc8, 0xce, 0xc2, | ||
| 105 | 0xe4, 0xe3, 0xe2, 0xd9, 0xc3, 0xd3, 0xfa, 0xed, 0xe6, 0x2f, | ||
| 106 | 0x00, 0x2f}, | ||
| 107 | {0x01, 0x87, 0x86, 0x9f, 0xd6, 0xdd, 0xd1, 0xc7, 0xce, 0xc1, | ||
| 108 | 0xe4, 0xe3, 0xe2, 0xd9, 0xc6, 0xd3, 0xfa, 0xed, 0xe6, 0x2f, | ||
| 109 | 0x00, 0x2f}, | ||
| 110 | {0x01, 0x89, 0x89, 0xa2, 0xd5, 0xdb, 0xcf, 0xc8, 0xcf, 0xc2, | ||
| 111 | 0xe3, 0xe3, 0xe1, 0xd9, 0xc7, 0xd3, 0xfa, 0xed, 0xe6, 0x2f, | ||
| 112 | 0x00, 0x2f}, | ||
| 113 | {0x01, 0x8b, 0x8b, 0xa5, 0xd5, 0xdb, 0xcf, 0xc7, 0xce, 0xc0, | ||
| 114 | 0xe3, 0xe3, 0xe1, 0xd8, 0xc7, 0xd3, 0xfa, 0xed, 0xe6, 0x2f, | ||
| 115 | 0x00, 0x2f}, | ||
| 116 | {0x01, 0x8d, 0x8d, 0xa7, 0xd5, 0xdb, 0xcf, 0xc6, 0xce, 0xc0, | ||
| 117 | 0xe4, 0xe4, 0xe1, 0xd7, 0xc8, 0xd3, 0xfa, 0xed, 0xe6, 0x2f, | ||
| 118 | 0x00, 0x2f}, | ||
| 119 | {0x01, 0x8f, 0x8f, 0xaa, 0xd4, 0xdb, 0xce, 0xc6, 0xcd, 0xbf, | ||
| 120 | 0xe3, 0xe3, 0xe1, 0xd7, 0xca, 0xd3, 0xfa, 0xed, 0xe6, 0x2f, | ||
| 121 | 0x00, 0x2f}, | ||
| 122 | {0x01, 0x91, 0x91, 0xac, 0xd3, 0xda, 0xce, 0xc5, 0xcd, 0xbe, | ||
| 123 | 0xe3, 0xe3, 0xe0, 0xd7, 0xca, 0xd3, 0xfa, 0xed, 0xe6, 0x2f, | ||
| 124 | 0x00, 0x2f}, | ||
| 125 | {0x01, 0x93, 0x93, 0xaf, 0xd3, 0xda, 0xcd, 0xc5, 0xcd, 0xbe, | ||
| 126 | 0xe2, 0xe3, 0xdf, 0xd6, 0xca, 0xd3, 0xfa, 0xed, 0xe6, 0x2f, | ||
| 127 | 0x00, 0x2f}, | ||
| 128 | {0x01, 0x95, 0x95, 0xb1, 0xd2, 0xd9, 0xcc, 0xc4, 0xcd, 0xbe, | ||
| 129 | 0xe2, 0xe3, 0xdf, 0xd7, 0xcc, 0xd3, 0xfa, 0xed, 0xe6, 0x2f, | ||
| 130 | 0x00, 0x2f}, | ||
| 131 | {0x01, 0x99, 0x99, 0xb6, 0xd1, 0xd9, 0xcc, 0xc3, 0xcb, 0xbc, | ||
| 132 | 0xe2, 0xe4, 0xdf, 0xd6, 0xcc, 0xd3, 0xfa, 0xed, 0xe6, 0x2f, | ||
| 133 | 0x00, 0x2f}, | ||
| 134 | {0x01, 0x9c, 0x9c, 0xba, 0xd0, 0xd8, 0xcb, 0xc3, 0xcb, 0xbb, | ||
| 135 | 0xe2, 0xe4, 0xdf, 0xd6, 0xce, 0xd3, 0xfa, 0xed, 0xe6, 0x2f, | ||
| 136 | 0x00, 0x2f}, | ||
| 137 | {0x01, 0x9f, 0x9f, 0xbe, 0xcf, 0xd7, 0xc9, 0xc2, 0xcb, 0xbb, | ||
| 138 | 0xe1, 0xe3, 0xde, 0xd6, 0xd0, 0xd3, 0xfa, 0xed, 0xe6, 0x2f, | ||
| 139 | 0x00, 0x2f}, | ||
| 140 | }; | ||
| 141 | |||
| 142 | /* | ||
| 143 | * Table of elvss values provided in datasheet and corresponds to | ||
| 144 | * gamma values. | ||
| 145 | */ | ||
| 146 | static u8 ams495qa01_elvss[NUM_GAMMA_LEVELS] = { | ||
| 147 | 0x15, 0x15, 0x15, 0x15, 0x15, 0x15, 0x15, 0x15, 0x15, 0x15, | ||
| 148 | 0x15, 0x15, 0x14, 0x14, 0x13, 0x12, | ||
| 149 | }; | ||
| 150 | |||
| 151 | static int ams495qa01_update_gamma(struct mipi_dbi *dbi, int brightness) | ||
| 152 | { | ||
| 153 | int tmp = brightness; | ||
| 154 | |||
| 155 | mipi_dbi_command_buf(dbi, MCS_SET_GAMMA, ams495qa01_gamma[tmp], | ||
| 156 | ARRAY_SIZE(ams495qa01_gamma[tmp])); | ||
| 157 | mipi_dbi_command(dbi, MCS_SET_GAMMA, 0x00); | ||
| 158 | |||
| 159 | /* Undocumented command */ | ||
| 160 | mipi_dbi_command(dbi, 0x26, 0x00); | ||
| 161 | |||
| 162 | mipi_dbi_command(dbi, MCS_TEMP_SWIRE, ams495qa01_elvss[tmp]); | ||
| 163 | |||
| 164 | return 0; | ||
| 165 | } | ||
| 166 | |||
| 167 | static void ams495qa01_panel_init(struct d53e6ea8966 *db) | ||
| 168 | { | ||
| 169 | struct mipi_dbi *dbi = &db->dbi; | ||
| 170 | |||
| 171 | mipi_dbi_command(dbi, MCS_PASSWORD_0, 0x5a, 0x5a); | ||
| 172 | mipi_dbi_command(dbi, MCS_PASSWORD_1, 0x5a, 0x5a); | ||
| 173 | |||
| 174 | /* Undocumented commands */ | ||
| 175 | mipi_dbi_command(dbi, 0xb0, 0x02); | ||
| 176 | mipi_dbi_command(dbi, 0xf3, 0x3b); | ||
| 177 | |||
| 178 | mipi_dbi_command(dbi, MCS_ANALOG_PWR_CTL_0, 0x33, 0x42, 0x00, 0x08); | ||
| 179 | mipi_dbi_command(dbi, MCS_ANALOG_PWR_CTL_1, 0x00, 0x06, 0x26, 0x35, 0x03); | ||
| 180 | |||
| 181 | /* Undocumented commands */ | ||
| 182 | mipi_dbi_command(dbi, 0xf6, 0x02); | ||
| 183 | mipi_dbi_command(dbi, 0xc6, 0x0b, 0x00, 0x00, 0x3c, 0x00, 0x22, | ||
| 184 | 0x00, 0x00, 0x00, 0x00); | ||
| 185 | |||
| 186 | mipi_dbi_command(dbi, MCS_GTCON_SET, 0x20); | ||
| 187 | mipi_dbi_command(dbi, MCS_TEMP_SWIRE, 0x06, 0x06, 0x06, 0x06); | ||
| 188 | mipi_dbi_command(dbi, MCS_ELVSS_ON, 0x07, 0x00, 0x10); | ||
| 189 | mipi_dbi_command(dbi, MCS_GATELESS_SIGNAL_SET, 0x7f, 0x7a, | ||
| 190 | 0x89, 0x67, 0x26, 0x38, 0x00, 0x00, 0x09, | ||
| 191 | 0x67, 0x70, 0x88, 0x7a, 0x76, 0x05, 0x09, | ||
| 192 | 0x23, 0x23, 0x23); | ||
| 193 | |||
| 194 | /* Undocumented commands */ | ||
| 195 | mipi_dbi_command(dbi, 0xb5, 0xff, 0xef, 0x35, 0x42, 0x0d, 0xd7, | ||
| 196 | 0xff, 0x07, 0xff, 0xff, 0xfd, 0x00, 0x01, | ||
| 197 | 0xff, 0x05, 0x12, 0x0f, 0xff, 0xff, 0xff, | ||
| 198 | 0xff); | ||
| 199 | mipi_dbi_command(dbi, 0xb4, 0x15); | ||
| 200 | mipi_dbi_command(dbi, 0xb3, 0x00); | ||
| 201 | |||
| 202 | ams495qa01_update_gamma(dbi, MAX_BRIGHTNESS); | ||
| 203 | } | ||
| 204 | |||
| 205 | static int d53e6ea8966_prepare(struct drm_panel *panel) | ||
| 206 | { | ||
| 207 | struct d53e6ea8966 *db = to_d53e6ea8966(panel); | ||
| 208 | int ret; | ||
| 209 | |||
| 210 | /* Power up */ | ||
| 211 | ret = regulator_enable(db->reg_vdd); | ||
| 212 | if (ret) { | ||
| 213 | dev_err(db->dev, "failed to enable vdd regulator: %d\n", ret); | ||
| 214 | return ret; | ||
| 215 | } | ||
| 216 | |||
| 217 | if (db->reg_elvdd) { | ||
| 218 | ret = regulator_enable(db->reg_elvdd); | ||
| 219 | if (ret) { | ||
| 220 | dev_err(db->dev, | ||
| 221 | "failed to enable elvdd regulator: %d\n", ret); | ||
| 222 | regulator_disable(db->reg_vdd); | ||
| 223 | return ret; | ||
| 224 | } | ||
| 225 | } | ||
| 226 | |||
| 227 | /* Enable */ | ||
| 228 | if (db->enable) | ||
| 229 | gpiod_set_value_cansleep(db->enable, 1); | ||
| 230 | |||
| 231 | msleep(50); | ||
| 232 | |||
| 233 | /* Reset */ | ||
| 234 | gpiod_set_value_cansleep(db->reset, 1); | ||
| 235 | usleep_range(1000, 5000); | ||
| 236 | gpiod_set_value_cansleep(db->reset, 0); | ||
| 237 | msleep(20); | ||
| 238 | |||
| 239 | db->panel_info->panel_init_seq(db); | ||
| 240 | |||
| 241 | return 0; | ||
| 242 | } | ||
| 243 | |||
| 244 | static int d53e6ea8966_enable(struct drm_panel *panel) | ||
| 245 | { | ||
| 246 | struct d53e6ea8966 *db = to_d53e6ea8966(panel); | ||
| 247 | struct mipi_dbi *dbi = &db->dbi; | ||
| 248 | |||
| 249 | mipi_dbi_command(dbi, MIPI_DCS_EXIT_SLEEP_MODE); | ||
| 250 | msleep(200); | ||
| 251 | mipi_dbi_command(dbi, MIPI_DCS_SET_DISPLAY_ON); | ||
| 252 | usleep_range(10000, 15000); | ||
| 253 | |||
| 254 | return 0; | ||
| 255 | } | ||
| 256 | |||
| 257 | static int d53e6ea8966_disable(struct drm_panel *panel) | ||
| 258 | { | ||
| 259 | struct d53e6ea8966 *db = to_d53e6ea8966(panel); | ||
| 260 | struct mipi_dbi *dbi = &db->dbi; | ||
| 261 | |||
| 262 | mipi_dbi_command(dbi, MIPI_DCS_SET_DISPLAY_OFF); | ||
| 263 | msleep(20); | ||
| 264 | mipi_dbi_command(dbi, MIPI_DCS_ENTER_SLEEP_MODE); | ||
| 265 | msleep(100); | ||
| 266 | |||
| 267 | return 0; | ||
| 268 | } | ||
| 269 | |||
| 270 | static int d53e6ea8966_unprepare(struct drm_panel *panel) | ||
| 271 | { | ||
| 272 | struct d53e6ea8966 *db = to_d53e6ea8966(panel); | ||
| 273 | |||
| 274 | if (db->enable) | ||
| 275 | gpiod_set_value_cansleep(db->enable, 0); | ||
| 276 | |||
| 277 | gpiod_set_value_cansleep(db->reset, 1); | ||
| 278 | |||
| 279 | if (db->reg_elvdd) | ||
| 280 | regulator_disable(db->reg_elvdd); | ||
| 281 | |||
| 282 | regulator_disable(db->reg_vdd); | ||
| 283 | msleep(100); | ||
| 284 | |||
| 285 | return 0; | ||
| 286 | } | ||
| 287 | |||
| 288 | static int d53e6ea8966_get_modes(struct drm_panel *panel, | ||
| 289 | struct drm_connector *connector) | ||
| 290 | { | ||
| 291 | struct d53e6ea8966 *db = to_d53e6ea8966(panel); | ||
| 292 | const struct d53e6ea8966_panel_info *panel_info = db->panel_info; | ||
| 293 | struct drm_display_mode *mode; | ||
| 294 | static const u32 bus_format = MEDIA_BUS_FMT_RGB888_1X24; | ||
| 295 | unsigned int i; | ||
| 296 | |||
| 297 | for (i = 0; i < panel_info->num_modes; i++) { | ||
| 298 | mode = drm_mode_duplicate(connector->dev, | ||
| 299 | &panel_info->display_modes[i]); | ||
| 300 | if (!mode) | ||
| 301 | return -ENOMEM; | ||
| 302 | |||
| 303 | drm_mode_set_name(mode); | ||
| 304 | drm_mode_probed_add(connector, mode); | ||
| 305 | } | ||
| 306 | |||
| 307 | connector->display_info.bpc = 8; | ||
| 308 | connector->display_info.width_mm = panel_info->width_mm; | ||
| 309 | connector->display_info.height_mm = panel_info->height_mm; | ||
| 310 | connector->display_info.bus_flags = panel_info->bus_flags; | ||
| 311 | |||
| 312 | drm_display_info_set_bus_formats(&connector->display_info, | ||
| 313 | &bus_format, 1); | ||
| 314 | |||
| 315 | return 1; | ||
| 316 | } | ||
| 317 | |||
| 318 | static const struct drm_panel_funcs d53e6ea8966_panel_funcs = { | ||
| 319 | .disable = d53e6ea8966_disable, | ||
| 320 | .enable = d53e6ea8966_enable, | ||
| 321 | .get_modes = d53e6ea8966_get_modes, | ||
| 322 | .prepare = d53e6ea8966_prepare, | ||
| 323 | .unprepare = d53e6ea8966_unprepare, | ||
| 324 | }; | ||
| 325 | |||
| 326 | static int ams495qa01_set_brightness(struct backlight_device *bd) | ||
| 327 | { | ||
| 328 | struct d53e6ea8966 *db = bl_get_data(bd); | ||
| 329 | struct mipi_dbi *dbi = &db->dbi; | ||
| 330 | int brightness = backlight_get_brightness(bd); | ||
| 331 | |||
| 332 | ams495qa01_update_gamma(dbi, brightness); | ||
| 333 | |||
| 334 | return 0; | ||
| 335 | } | ||
| 336 | |||
| 337 | static const struct backlight_ops ams495qa01_backlight_ops = { | ||
| 338 | .update_status = ams495qa01_set_brightness, | ||
| 339 | }; | ||
| 340 | |||
| 341 | static int ams495qa01_backlight_register(struct d53e6ea8966 *db) | ||
| 342 | { | ||
| 343 | struct backlight_properties props = { | ||
| 344 | .type = BACKLIGHT_RAW, | ||
| 345 | .brightness = MAX_BRIGHTNESS, | ||
| 346 | .max_brightness = MAX_BRIGHTNESS, | ||
| 347 | }; | ||
| 348 | struct device *dev = db->dev; | ||
| 349 | int ret = 0; | ||
| 350 | |||
| 351 | db->bl_dev = devm_backlight_device_register(dev, "panel", dev, db, | ||
| 352 | &ams495qa01_backlight_ops, | ||
| 353 | &props); | ||
| 354 | if (IS_ERR(db->bl_dev)) { | ||
| 355 | ret = PTR_ERR(db->bl_dev); | ||
| 356 | dev_err(dev, "error registering backlight device (%d)\n", ret); | ||
| 357 | } | ||
| 358 | |||
| 359 | return ret; | ||
| 360 | } | ||
| 361 | |||
| 362 | static int d53e6ea8966_probe(struct spi_device *spi) | ||
| 363 | { | ||
| 364 | struct device *dev = &spi->dev; | ||
| 365 | struct mipi_dsi_host *dsi_host; | ||
| 366 | struct d53e6ea8966 *db; | ||
| 367 | int ret; | ||
| 368 | struct mipi_dsi_device_info info = { | ||
| 369 | .type = "d53e6ea8966", | ||
| 370 | .channel = 0, | ||
| 371 | .node = NULL, | ||
| 372 | }; | ||
| 373 | |||
| 374 | db = devm_kzalloc(dev, sizeof(*db), GFP_KERNEL); | ||
| 375 | if (!db) | ||
| 376 | return -ENOMEM; | ||
| 377 | |||
| 378 | spi_set_drvdata(spi, db); | ||
| 379 | |||
| 380 | db->dev = dev; | ||
| 381 | |||
| 382 | db->panel_info = of_device_get_match_data(dev); | ||
| 383 | if (!db->panel_info) | ||
| 384 | return -EINVAL; | ||
| 385 | |||
| 386 | db->reg_vdd = devm_regulator_get(dev, "vdd"); | ||
| 387 | if (IS_ERR(db->reg_vdd)) | ||
| 388 | return dev_err_probe(dev, PTR_ERR(db->reg_vdd), | ||
| 389 | "Failed to get vdd supply\n"); | ||
| 390 | |||
| 391 | db->reg_elvdd = devm_regulator_get_optional(dev, "elvdd"); | ||
| 392 | if (IS_ERR(db->reg_elvdd)) | ||
| 393 | db->reg_elvdd = NULL; | ||
| 394 | |||
| 395 | db->reset = devm_gpiod_get(dev, "reset", GPIOD_OUT_HIGH); | ||
| 396 | if (IS_ERR(db->reset)) { | ||
| 397 | ret = PTR_ERR(db->reset); | ||
| 398 | return dev_err_probe(dev, ret, "no RESET GPIO\n"); | ||
| 399 | } | ||
| 400 | |||
| 401 | db->enable = devm_gpiod_get_optional(dev, "enable", GPIOD_OUT_LOW); | ||
| 402 | if (IS_ERR(db->enable)) { | ||
| 403 | ret = PTR_ERR(db->enable); | ||
| 404 | return dev_err_probe(dev, ret, "cannot get ENABLE GPIO\n"); | ||
| 405 | } | ||
| 406 | |||
| 407 | ret = mipi_dbi_spi_init(spi, &db->dbi, NULL); | ||
| 408 | if (ret) | ||
| 409 | return dev_err_probe(dev, ret, "MIPI DBI init failed\n"); | ||
| 410 | |||
| 411 | dsi_host = drm_of_get_dsi_bus(dev); | ||
| 412 | if (IS_ERR(dsi_host)) { | ||
| 413 | ret = PTR_ERR(dsi_host); | ||
| 414 | return dev_err_probe(dev, ret, "Error attaching DSI bus\n"); | ||
| 415 | } | ||
| 416 | |||
| 417 | db->dsi_dev = devm_mipi_dsi_device_register_full(dev, dsi_host, &info); | ||
| 418 | if (IS_ERR(db->dsi_dev)) { | ||
| 419 | dev_err(dev, "failed to register dsi device: %ld\n", | ||
| 420 | PTR_ERR(db->dsi_dev)); | ||
| 421 | ret = PTR_ERR(db->dsi_dev); | ||
| 422 | } | ||
| 423 | |||
| 424 | db->dsi_dev->lanes = 2; | ||
| 425 | db->dsi_dev->format = MIPI_DSI_FMT_RGB888; | ||
| 426 | db->dsi_dev->mode_flags = MIPI_DSI_MODE_VIDEO | MIPI_DSI_MODE_VIDEO_BURST | | ||
| 427 | MIPI_DSI_MODE_LPM | MIPI_DSI_MODE_NO_EOT_PACKET; | ||
| 428 | |||
| 429 | drm_panel_init(&db->panel, dev, &d53e6ea8966_panel_funcs, | ||
| 430 | DRM_MODE_CONNECTOR_DSI); | ||
| 431 | |||
| 432 | if (db->panel_info->backlight_register) { | ||
| 433 | ret = db->panel_info->backlight_register(db); | ||
| 434 | if (ret < 0) | ||
| 435 | return ret; | ||
| 436 | db->panel.backlight = db->bl_dev; | ||
| 437 | } | ||
| 438 | |||
| 439 | drm_panel_add(&db->panel); | ||
| 440 | |||
| 441 | ret = devm_mipi_dsi_attach(dev, db->dsi_dev); | ||
| 442 | if (ret < 0) { | ||
| 443 | dev_err(dev, "mipi_dsi_attach failed: %d\n", ret); | ||
| 444 | drm_panel_remove(&db->panel); | ||
| 445 | return ret; | ||
| 446 | } | ||
| 447 | |||
| 448 | return 0; | ||
| 449 | } | ||
| 450 | |||
| 451 | static void d53e6ea8966_remove(struct spi_device *spi) | ||
| 452 | { | ||
| 453 | struct d53e6ea8966 *db = spi_get_drvdata(spi); | ||
| 454 | |||
| 455 | drm_panel_remove(&db->panel); | ||
| 456 | } | ||
| 457 | |||
| 458 | static const struct drm_display_mode ams495qa01_modes[] = { | ||
| 459 | { /* 60hz */ | ||
| 460 | .clock = 33500, | ||
| 461 | .hdisplay = 960, | ||
| 462 | .hsync_start = 960 + 10, | ||
| 463 | .hsync_end = 960 + 10 + 2, | ||
| 464 | .htotal = 960 + 10 + 2 + 10, | ||
| 465 | .vdisplay = 544, | ||
| 466 | .vsync_start = 544 + 10, | ||
| 467 | .vsync_end = 544 + 10 + 2, | ||
| 468 | .vtotal = 544 + 10 + 2 + 10, | ||
| 469 | .flags = DRM_MODE_FLAG_NHSYNC | DRM_MODE_FLAG_NVSYNC, | ||
| 470 | .type = DRM_MODE_TYPE_DRIVER | DRM_MODE_TYPE_PREFERRED, | ||
| 471 | }, | ||
| 472 | { /* 50hz */ | ||
| 473 | .clock = 27800, | ||
| 474 | .hdisplay = 960, | ||
| 475 | .hsync_start = 960 + 10, | ||
| 476 | .hsync_end = 960 + 10 + 2, | ||
| 477 | .htotal = 960 + 10 + 2 + 10, | ||
| 478 | .vdisplay = 544, | ||
| 479 | .vsync_start = 544 + 10, | ||
| 480 | .vsync_end = 544 + 10 + 2, | ||
| 481 | .vtotal = 544 + 10 + 2 + 10, | ||
| 482 | .flags = DRM_MODE_FLAG_NHSYNC | DRM_MODE_FLAG_NVSYNC, | ||
| 483 | .type = DRM_MODE_TYPE_DRIVER, | ||
| 484 | }, | ||
| 485 | }; | ||
| 486 | |||
| 487 | static const struct d53e6ea8966_panel_info ams495qa01_info = { | ||
| 488 | .display_modes = ams495qa01_modes, | ||
| 489 | .num_modes = ARRAY_SIZE(ams495qa01_modes), | ||
| 490 | .width_mm = 117, | ||
| 491 | .height_mm = 74, | ||
| 492 | .bus_flags = DRM_BUS_FLAG_DE_LOW | DRM_BUS_FLAG_PIXDATA_DRIVE_NEGEDGE, | ||
| 493 | .panel_init_seq = ams495qa01_panel_init, | ||
| 494 | .backlight_register = ams495qa01_backlight_register, | ||
| 495 | }; | ||
| 496 | |||
| 497 | static const struct of_device_id d53e6ea8966_match[] = { | ||
| 498 | { .compatible = "samsung,ams495qa01", .data = &ams495qa01_info }, | ||
| 499 | { /* sentinel */ }, | ||
| 500 | }; | ||
| 501 | MODULE_DEVICE_TABLE(of, d53e6ea8966_match); | ||
| 502 | |||
| 503 | static const struct spi_device_id d53e6ea8966_ids[] = { | ||
| 504 | { "ams495qa01", 0 }, | ||
| 505 | { /* sentinel */ }, | ||
| 506 | }; | ||
| 507 | MODULE_DEVICE_TABLE(spi, d53e6ea8966_ids); | ||
| 508 | |||
| 509 | static struct spi_driver d53e6ea8966_driver = { | ||
| 510 | .driver = { | ||
| 511 | .name = "d53e6ea8966-panel", | ||
| 512 | .of_match_table = d53e6ea8966_match, | ||
| 513 | }, | ||
| 514 | .id_table = d53e6ea8966_ids, | ||
| 515 | .probe = d53e6ea8966_probe, | ||
| 516 | .remove = d53e6ea8966_remove, | ||
| 517 | }; | ||
| 518 | module_spi_driver(d53e6ea8966_driver); | ||
| 519 | |||
| 520 | MODULE_AUTHOR("Chris Morgan <macromorgan@hotmail.com>"); | ||
| 521 | MODULE_DESCRIPTION("Magnachip d53e6ea8966 panel driver"); | ||
| 522 | MODULE_LICENSE("GPL"); | ||
| @@ -220,15 +220,8 @@ panfrost_copy_in_sync(struct drm_device *dev, · 219 unmodified lines | |||
| 220 | } | 220 | } |
| 221 | 221 | ||
| 222 | for (i = 0; i < in_fence_count; i++) { | 222 | for (i = 0; i < in_fence_count; i++) { |
| 223 | struct dma_fence *fence; | 223 | ret = drm_sched_job_add_syncobj_dependency(&job->base, file_priv, |
| 224 | 224 | handles[i], 0); | |
| 225 | ret = drm_syncobj_find_fence(file_priv, handles[i], 0, 0, | ||
| 226 | &fence); | ||
| 227 | if (ret) | ||
| 228 | goto fail; | ||
| 229 | |||
| 230 | ret = drm_sched_job_add_dependency(&job->base, fence); | ||
| 231 | |||
| 232 | if (ret) | 225 | if (ret) |
| 233 | goto fail; | 226 | goto fail; |
| 234 | } | 227 | } |
| @@ -143,6 +143,17 @@ static int qxl_bo_move(struct ttm_buffer_object *bo, bool evict, · 142 unmodified lines | |||
| 143 | struct ttm_resource *old_mem = bo->resource; | 143 | struct ttm_resource *old_mem = bo->resource; |
| 144 | int ret; | 144 | int ret; |
| 145 | 145 | ||
| 146 | if (!old_mem) { | ||
| 147 | if (new_mem->mem_type != TTM_PL_SYSTEM) { | ||
| 148 | hop->mem_type = TTM_PL_SYSTEM; | ||
| 149 | hop->flags = TTM_PL_FLAG_TEMPORARY; | ||
| 150 | return -EMULTIHOP; | ||
| 151 | } | ||
| 152 | |||
| 153 | ttm_bo_move_null(bo, new_mem); | ||
| 154 | return 0; | ||
| 155 | } | ||
| 156 | |||
| 146 | qxl_bo_move_notify(bo, new_mem); | 157 | qxl_bo_move_notify(bo, new_mem); |
| 147 | 158 | ||
| 148 | ret = ttm_bo_wait_ctx(bo, ctx); | 159 | ret = ttm_bo_wait_ctx(bo, ctx); |
| @@ -8,6 +8,7 @@ config DRM_RADEON · 7 unmodified lines | |||
| 8 | select DRM_DISPLAY_DP_HELPER | 8 | select DRM_DISPLAY_DP_HELPER |
| 9 | select DRM_DISPLAY_HELPER | 9 | select DRM_DISPLAY_HELPER |
| 10 | select DRM_KMS_HELPER | 10 | select DRM_KMS_HELPER |
| 11 | select DRM_SUBALLOC_HELPER | ||
| 11 | select DRM_TTM | 12 | select DRM_TTM |
| 12 | select DRM_TTM_HELPER | 13 | select DRM_TTM_HELPER |
| 13 | select SND_HDA_COMPONENT if SND_HDA_CORE | 14 | select SND_HDA_COMPONENT if SND_HDA_CORE |
| @@ -79,6 +79,7 @@ · 78 unmodified lines | |||
| 79 | 79 | ||
| 80 | #include <drm/drm_gem.h> | 80 | #include <drm/drm_gem.h> |
| 81 | #include <drm/drm_audio_component.h> | 81 | #include <drm/drm_audio_component.h> |
| 82 | #include <drm/drm_suballoc.h> | ||
| 82 | 83 | ||
| 83 | #include "radeon_family.h" | 84 | #include "radeon_family.h" |
| 84 | #include "radeon_mode.h" | 85 | #include "radeon_mode.h" |
| @@ -511,52 +512,12 @@ struct radeon_bo { · 426 unmodified lines | |||
| 511 | }; | 512 | }; |
| 512 | #define gem_to_radeon_bo(gobj) container_of((gobj), struct radeon_bo, tbo.base) | 513 | #define gem_to_radeon_bo(gobj) container_of((gobj), struct radeon_bo, tbo.base) |
| 513 | 514 | ||
| 514 | /* sub-allocation manager, it has to be protected by another lock. | ||
| 515 | * By conception this is an helper for other part of the driver | ||
| 516 | * like the indirect buffer or semaphore, which both have their | ||
| 517 | * locking. | ||
| 518 | * | ||
| 519 | * Principe is simple, we keep a list of sub allocation in offset | ||
| 520 | * order (first entry has offset == 0, last entry has the highest | ||
| 521 | * offset). | ||
| 522 | * | ||
| 523 | * When allocating new object we first check if there is room at | ||
| 524 | * the end total_size - (last_object_offset + last_object_size) >= | ||
| 525 | * alloc_size. If so we allocate new object there. | ||
| 526 | * | ||
| 527 | * When there is not enough room at the end, we start waiting for | ||
| 528 | * each sub object until we reach object_offset+object_size >= | ||
| 529 | * alloc_size, this object then become the sub object we return. | ||
| 530 | * | ||
| 531 | * Alignment can't be bigger than page size. | ||
| 532 | * | ||
| 533 | * Hole are not considered for allocation to keep things simple. | ||
| 534 | * Assumption is that there won't be hole (all object on same | ||
| 535 | * alignment). | ||
| 536 | */ | ||
| 537 | struct radeon_sa_manager { | 515 | struct radeon_sa_manager { |
| 538 | wait_queue_head_t wq; | 516 | struct drm_suballoc_manager base; |
| 539 | struct radeon_bo *bo; | 517 | struct radeon_bo *bo; |
| 540 | struct list_head *hole; | 518 | uint64_t gpu_addr; |
| 541 | struct list_head flist[RADEON_NUM_RINGS]; | 519 | void *cpu_ptr; |
| 542 | struct list_head olist; | 520 | u32 domain; |
| 543 | unsigned size; | ||
| 544 | uint64_t gpu_addr; | ||
| 545 | void *cpu_ptr; | ||
| 546 | uint32_t domain; | ||
| 547 | uint32_t align; | ||
| 548 | }; | ||
| 549 | |||
| 550 | struct radeon_sa_bo; | ||
| 551 | |||
| 552 | /* sub-allocation buffer */ | ||
| 553 | struct radeon_sa_bo { | ||
| 554 | struct list_head olist; | ||
| 555 | struct list_head flist; | ||
| 556 | struct radeon_sa_manager *manager; | ||
| 557 | unsigned soffset; | ||
| 558 | unsigned eoffset; | ||
| 559 | struct radeon_fence *fence; | ||
| 560 | }; | 521 | }; |
| 561 | 522 | ||
| 562 | /* | 523 | /* |
| @@ -587,7 +548,7 @@ int radeon_mode_dumb_mmap(struct drm_file *filp, · 24 unmodified lines | |||
| 587 | * Semaphores. | 548 | * Semaphores. |
| 588 | */ | 549 | */ |
| 589 | struct radeon_semaphore { | 550 | struct radeon_semaphore { |
| 590 | struct radeon_sa_bo *sa_bo; | 551 | struct drm_suballoc *sa_bo; |
| 591 | signed waiters; | 552 | signed waiters; |
| 592 | uint64_t gpu_addr; | 553 | uint64_t gpu_addr; |
| 593 | }; | 554 | }; |
| @@ -816,7 +777,7 @@ void radeon_irq_kms_disable_hpd(struct radeon_device *rdev, unsigned hpd_mask); · 222 unmodified lines | |||
| 816 | */ | 777 | */ |
| 817 | 778 | ||
| 818 | struct radeon_ib { | 779 | struct radeon_ib { |
| 819 | struct radeon_sa_bo *sa_bo; | 780 | struct drm_suballoc *sa_bo; |
| 820 | uint32_t length_dw; | 781 | uint32_t length_dw; |
| 821 | uint64_t gpu_addr; | 782 | uint64_t gpu_addr; |
| 822 | uint32_t *ptr; | 783 | uint32_t *ptr; |
| @@ -61,7 +61,7 @@ int radeon_ib_get(struct radeon_device *rdev, int ring, · 60 unmodified lines | |||
| 61 | { | 61 | { |
| 62 | int r; | 62 | int r; |
| 63 | 63 | ||
| 64 | r = radeon_sa_bo_new(rdev, &rdev->ring_tmp_bo, &ib->sa_bo, size, 256); | 64 | r = radeon_sa_bo_new(&rdev->ring_tmp_bo, &ib->sa_bo, size, 256); |
| 65 | if (r) { | 65 | if (r) { |
| 66 | dev_err(rdev->dev, "failed to get a new IB (%d)\n", r); | 66 | dev_err(rdev->dev, "failed to get a new IB (%d)\n", r); |
| 67 | return r; | 67 | return r; |
| @@ -77,7 +77,7 @@ int radeon_ib_get(struct radeon_device *rdev, int ring, · 9 unmodified lines | |||
| 77 | /* ib pool is bound at RADEON_VA_IB_OFFSET in virtual address | 77 | /* ib pool is bound at RADEON_VA_IB_OFFSET in virtual address |
| 78 | * space and soffset is the offset inside the pool bo | 78 | * space and soffset is the offset inside the pool bo |
| 79 | */ | 79 | */ |
| 80 | ib->gpu_addr = ib->sa_bo->soffset + RADEON_VA_IB_OFFSET; | 80 | ib->gpu_addr = drm_suballoc_soffset(ib->sa_bo) + RADEON_VA_IB_OFFSET; |
| 81 | } else { | 81 | } else { |
| 82 | ib->gpu_addr = radeon_sa_bo_gpu_addr(ib->sa_bo); | 82 | ib->gpu_addr = radeon_sa_bo_gpu_addr(ib->sa_bo); |
| 83 | } | 83 | } |
| @@ -97,7 +97,7 @@ int radeon_ib_get(struct radeon_device *rdev, int ring, · 13 unmodified lines | |||
| 97 | void radeon_ib_free(struct radeon_device *rdev, struct radeon_ib *ib) | 97 | void radeon_ib_free(struct radeon_device *rdev, struct radeon_ib *ib) |
| 98 | { | 98 | { |
| 99 | radeon_sync_free(rdev, &ib->sync, ib->fence); | 99 | radeon_sync_free(rdev, &ib->sync, ib->fence); |
| 100 | radeon_sa_bo_free(rdev, &ib->sa_bo, ib->fence); | 100 | radeon_sa_bo_free(&ib->sa_bo, ib->fence); |
| 101 | radeon_fence_unref(&ib->fence); | 101 | radeon_fence_unref(&ib->fence); |
| 102 | } | 102 | } |
| 103 | 103 | ||
| @@ -201,8 +201,7 @@ int radeon_ib_pool_init(struct radeon_device *rdev) · 97 unmodified lines | |||
| 201 | 201 | ||
| 202 | if (rdev->family >= CHIP_BONAIRE) { | 202 | if (rdev->family >= CHIP_BONAIRE) { |
| 203 | r = radeon_sa_bo_manager_init(rdev, &rdev->ring_tmp_bo, | 203 | r = radeon_sa_bo_manager_init(rdev, &rdev->ring_tmp_bo, |
| 204 | RADEON_IB_POOL_SIZE*64*1024, | 204 | RADEON_IB_POOL_SIZE*64*1024, 256, |
| 205 | RADEON_GPU_PAGE_SIZE, | ||
| 206 | RADEON_GEM_DOMAIN_GTT, | 205 | RADEON_GEM_DOMAIN_GTT, |
| 207 | RADEON_GEM_GTT_WC); | 206 | RADEON_GEM_GTT_WC); |
| 208 | } else { | 207 | } else { |
| @@ -210,8 +209,7 @@ int radeon_ib_pool_init(struct radeon_device *rdev) · 1 unmodified line | |||
| 210 | * to the command stream checking | 209 | * to the command stream checking |
| 211 | */ | 210 | */ |
| 212 | r = radeon_sa_bo_manager_init(rdev, &rdev->ring_tmp_bo, | 211 | r = radeon_sa_bo_manager_init(rdev, &rdev->ring_tmp_bo, |
| 213 | RADEON_IB_POOL_SIZE*64*1024, | 212 | RADEON_IB_POOL_SIZE*64*1024, 256, |
| 214 | RADEON_GPU_PAGE_SIZE, | ||
| 215 | RADEON_GEM_DOMAIN_GTT, 0); | 213 | RADEON_GEM_DOMAIN_GTT, 0); |
| 216 | } | 214 | } |
| 217 | if (r) { | 215 | if (r) { |
| @@ -169,15 +169,22 @@ extern void radeon_bo_fence(struct radeon_bo *bo, struct radeon_fence *fence, · 168 unmodified lines | |||
| 169 | /* | 169 | /* |
| 170 | * sub allocation | 170 | * sub allocation |
| 171 | */ | 171 | */ |
| 172 | static inline struct radeon_sa_manager * | ||
| 173 | to_radeon_sa_manager(struct drm_suballoc_manager *manager) | ||
| 174 | { | ||
| 175 | return container_of(manager, struct radeon_sa_manager, base); | ||
| 176 | } | ||
| 172 | 177 | ||
| 173 | static inline uint64_t radeon_sa_bo_gpu_addr(struct radeon_sa_bo *sa_bo) | 178 | static inline uint64_t radeon_sa_bo_gpu_addr(struct drm_suballoc *sa_bo) |
| 174 | { | 179 | { |
| 175 | return sa_bo->manager->gpu_addr + sa_bo->soffset; | 180 | return to_radeon_sa_manager(sa_bo->manager)->gpu_addr + |
| 181 | drm_suballoc_soffset(sa_bo); | ||
| 176 | } | 182 | } |
| 177 | 183 | ||
| 178 | static inline void * radeon_sa_bo_cpu_addr(struct radeon_sa_bo *sa_bo) | 184 | static inline void *radeon_sa_bo_cpu_addr(struct drm_suballoc *sa_bo) |
| 179 | { | 185 | { |
| 180 | return sa_bo->manager->cpu_ptr + sa_bo->soffset; | 186 | return to_radeon_sa_manager(sa_bo->manager)->cpu_ptr + |
| 187 | drm_suballoc_soffset(sa_bo); | ||
| 181 | } | 188 | } |
| 182 | 189 | ||
| 183 | extern int radeon_sa_bo_manager_init(struct radeon_device *rdev, | 190 | extern int radeon_sa_bo_manager_init(struct radeon_device *rdev, |
| @@ -190,12 +197,10 @@ extern int radeon_sa_bo_manager_start(struct radeon_device *rdev, · 6 unmodified lines | |||
| 190 | struct radeon_sa_manager *sa_manager); | 197 | struct radeon_sa_manager *sa_manager); |
| 191 | extern int radeon_sa_bo_manager_suspend(struct radeon_device *rdev, | 198 | extern int radeon_sa_bo_manager_suspend(struct radeon_device *rdev, |
| 192 | struct radeon_sa_manager *sa_manager); | 199 | struct radeon_sa_manager *sa_manager); |
| 193 | extern int radeon_sa_bo_new(struct radeon_device *rdev, | 200 | extern int radeon_sa_bo_new(struct radeon_sa_manager *sa_manager, |
| 194 | struct radeon_sa_manager *sa_manager, | 201 | struct drm_suballoc **sa_bo, |
| 195 | struct radeon_sa_bo **sa_bo, | 202 | unsigned int size, unsigned int align); |
| 196 | unsigned size, unsigned align); | 203 | extern void radeon_sa_bo_free(struct drm_suballoc **sa_bo, |
| 197 | extern void radeon_sa_bo_free(struct radeon_device *rdev, | ||
| 198 | struct radeon_sa_bo **sa_bo, | ||
| 199 | struct radeon_fence *fence); | 204 | struct radeon_fence *fence); |
| 200 | #if defined(CONFIG_DEBUG_FS) | 205 | #if defined(CONFIG_DEBUG_FS) |
| 201 | extern void radeon_sa_bo_dump_debug_info(struct radeon_sa_manager *sa_manager, | 206 | extern void radeon_sa_bo_dump_debug_info(struct radeon_sa_manager *sa_manager, |
| @@ -44,53 +44,32 @@ · 43 unmodified lines | |||
| 44 | 44 | ||
| 45 | #include "radeon.h" | 45 | #include "radeon.h" |
| 46 | 46 | ||
| 47 | static void radeon_sa_bo_remove_locked(struct radeon_sa_bo *sa_bo); | ||
| 48 | static void radeon_sa_bo_try_free(struct radeon_sa_manager *sa_manager); | ||
| 49 | |||
| 50 | int radeon_sa_bo_manager_init(struct radeon_device *rdev, | 47 | int radeon_sa_bo_manager_init(struct radeon_device *rdev, |
| 51 | struct radeon_sa_manager *sa_manager, | 48 | struct radeon_sa_manager *sa_manager, |
| 52 | unsigned size, u32 align, u32 domain, u32 flags) | 49 | unsigned int size, u32 sa_align, u32 domain, |
| 50 | u32 flags) | ||
| 53 | { | 51 | { |
| 54 | int i, r; | 52 | int r; |
| 55 | |||
| 56 | init_waitqueue_head(&sa_manager->wq); | ||
| 57 | sa_manager->bo = NULL; | ||
| 58 | sa_manager->size = size; | ||
| 59 | sa_manager->domain = domain; | ||
| 60 | sa_manager->align = align; | ||
| 61 | sa_manager->hole = &sa_manager->olist; | ||
| 62 | INIT_LIST_HEAD(&sa_manager->olist); | ||
| 63 | for (i = 0; i < RADEON_NUM_RINGS; ++i) { | ||
| 64 | INIT_LIST_HEAD(&sa_manager->flist[i]); | ||
| 65 | } | ||
| 66 | 53 | ||
| 67 | r = radeon_bo_create(rdev, size, align, true, | 54 | r = radeon_bo_create(rdev, size, RADEON_GPU_PAGE_SIZE, true, |
| 68 | domain, flags, NULL, NULL, &sa_manager->bo); | 55 | domain, flags, NULL, NULL, &sa_manager->bo); |
| 69 | if (r) { | 56 | if (r) { |
| 70 | dev_err(rdev->dev, "(%d) failed to allocate bo for manager\n", r); | 57 | dev_err(rdev->dev, "(%d) failed to allocate bo for manager\n", r); |
| 71 | return r; | 58 | return r; |
| 72 | } | 59 | } |
| 73 | 60 | ||
| 61 | sa_manager->domain = domain; | ||
| 62 | |||
| 63 | drm_suballoc_manager_init(&sa_manager->base, size, sa_align); | ||
| 64 | |||
| 74 | return r; | 65 | return r; |
| 75 | } | 66 | } |
| 76 | 67 | ||
| 77 | void radeon_sa_bo_manager_fini(struct radeon_device *rdev, | 68 | void radeon_sa_bo_manager_fini(struct radeon_device *rdev, |
| 78 | struct radeon_sa_manager *sa_manager) | 69 | struct radeon_sa_manager *sa_manager) |
| 79 | { | 70 | { |
| 80 | struct radeon_sa_bo *sa_bo, *tmp; | 71 | drm_suballoc_manager_fini(&sa_manager->base); |
| 81 | |||
| 82 | if (!list_empty(&sa_manager->olist)) { | ||
| 83 | sa_manager->hole = &sa_manager->olist, | ||
| 84 | radeon_sa_bo_try_free(sa_manager); | ||
| 85 | if (!list_empty(&sa_manager->olist)) { | ||
| 86 | dev_err(rdev->dev, "sa_manager is not empty, clearing anyway\n"); | ||
| 87 | } | ||
| 88 | } | ||
| 89 | list_for_each_entry_safe(sa_bo, tmp, &sa_manager->olist, olist) { | ||
| 90 | radeon_sa_bo_remove_locked(sa_bo); | ||
| 91 | } | ||
| 92 | radeon_bo_unref(&sa_manager->bo); | 72 | radeon_bo_unref(&sa_manager->bo); |
| 93 | sa_manager->size = 0; | ||
| 94 | } | 73 | } |
| 95 | 74 | ||
| 96 | int radeon_sa_bo_manager_start(struct radeon_device *rdev, | 75 | int radeon_sa_bo_manager_start(struct radeon_device *rdev, |
| @@ -139,260 +118,34 @@ int radeon_sa_bo_manager_suspend(struct radeon_device *rdev, · 42 unmodified lines | |||
| 139 | return r; | 118 | return r; |
| 140 | } | 119 | } |
| 141 | 120 | ||
| 142 | static void radeon_sa_bo_remove_locked(struct radeon_sa_bo *sa_bo) | 121 | int radeon_sa_bo_new(struct radeon_sa_manager *sa_manager, |
| 122 | struct drm_suballoc **sa_bo, | ||
| 123 | unsigned int size, unsigned int align) | ||
| 143 | { | 124 | { |
| 144 | struct radeon_sa_manager *sa_manager = sa_bo->manager; | 125 | struct drm_suballoc *sa = drm_suballoc_new(&sa_manager->base, size, |
| 145 | if (sa_manager->hole == &sa_bo->olist) { | 126 | GFP_KERNEL, true, align); |
| 146 | sa_manager->hole = sa_bo->olist.prev; | ||
| 147 | } | ||
| 148 | list_del_init(&sa_bo->olist); | ||
| 149 | list_del_init(&sa_bo->flist); | ||
| 150 | radeon_fence_unref(&sa_bo->fence); | ||
| 151 | kfree(sa_bo); | ||
| 152 | } | ||
| 153 | |||
| 154 | static void radeon_sa_bo_try_free(struct radeon_sa_manager *sa_manager) | ||
| 155 | { | ||
| 156 | struct radeon_sa_bo *sa_bo, *tmp; | ||
| 157 | |||
| 158 | if (sa_manager->hole->next == &sa_manager->olist) | ||
| 159 | return; | ||
| 160 | 127 | ||
| 161 | sa_bo = list_entry(sa_manager->hole->next, struct radeon_sa_bo, olist); | 128 | if (IS_ERR(sa)) { |
| 162 | list_for_each_entry_safe_from(sa_bo, tmp, &sa_manager->olist, olist) { | 129 | *sa_bo = NULL; |
| 163 | if (sa_bo->fence == NULL || !radeon_fence_signaled(sa_bo->fence)) { | 130 | return PTR_ERR(sa); |
| 164 | return; | ||
| 165 | } | ||
| 166 | radeon_sa_bo_remove_locked(sa_bo); | ||
| 167 | } | 131 | } |
| 168 | } | ||
| 169 | 132 | ||
| 170 | static inline unsigned radeon_sa_bo_hole_soffset(struct radeon_sa_manager *sa_manager) | 133 | *sa_bo = sa; |
| 171 | { | ||
| 172 | struct list_head *hole = sa_manager->hole; | ||
| 173 | |||
| 174 | if (hole != &sa_manager->olist) { | ||
| 175 | return list_entry(hole, struct radeon_sa_bo, olist)->eoffset; | ||
| 176 | } | ||
| 177 | return 0; | 134 | return 0; |
| 178 | } | 135 | } |
| 179 | 136 | ||
| 180 | static inline unsigned radeon_sa_bo_hole_eoffset(struct radeon_sa_manager *sa_manager) | 137 | void radeon_sa_bo_free(struct drm_suballoc **sa_bo, |
| 181 | { | ||
| 182 | struct list_head *hole = sa_manager->hole; | ||
| 183 | |||
| 184 | if (hole->next != &sa_manager->olist) { | ||
| 185 | return list_entry(hole->next, struct radeon_sa_bo, olist)->soffset; | ||
| 186 | } | ||
| 187 | return sa_manager->size; | ||
| 188 | } | ||
| 189 | |||
| 190 | static bool radeon_sa_bo_try_alloc(struct radeon_sa_manager *sa_manager, | ||
| 191 | struct radeon_sa_bo *sa_bo, | ||
| 192 | unsigned size, unsigned align) | ||
| 193 | { | ||
| 194 | unsigned soffset, eoffset, wasted; | ||
| 195 | |||
| 196 | soffset = radeon_sa_bo_hole_soffset(sa_manager); | ||
| 197 | eoffset = radeon_sa_bo_hole_eoffset(sa_manager); | ||
| 198 | wasted = (align - (soffset % align)) % align; | ||
| 199 | |||
| 200 | if ((eoffset - soffset) >= (size + wasted)) { | ||
| 201 | soffset += wasted; | ||
| 202 | |||
| 203 | sa_bo->manager = sa_manager; | ||
| 204 | sa_bo->soffset = soffset; | ||
| 205 | sa_bo->eoffset = soffset + size; | ||
| 206 | list_add(&sa_bo->olist, sa_manager->hole); | ||
| 207 | INIT_LIST_HEAD(&sa_bo->flist); | ||
| 208 | sa_manager->hole = &sa_bo->olist; | ||
| 209 | return true; | ||
| 210 | } | ||
| 211 | return false; | ||
| 212 | } | ||
| 213 | |||
| 214 | /** | ||
| 215 | * radeon_sa_event - Check if we can stop waiting | ||
| 216 | * | ||
| 217 | * @sa_manager: pointer to the sa_manager | ||
| 218 | * @size: number of bytes we want to allocate | ||
| 219 | * @align: alignment we need to match | ||
| 220 | * | ||
| 221 | * Check if either there is a fence we can wait for or | ||
| 222 | * enough free memory to satisfy the allocation directly | ||
| 223 | */ | ||
| 224 | static bool radeon_sa_event(struct radeon_sa_manager *sa_manager, | ||
| 225 | unsigned size, unsigned align) | ||
| 226 | { | ||
| 227 | unsigned soffset, eoffset, wasted; | ||
| 228 | int i; | ||
| 229 | |||
| 230 | for (i = 0; i < RADEON_NUM_RINGS; ++i) { | ||
| 231 | if (!list_empty(&sa_manager->flist[i])) { | ||
| 232 | return true; | ||
| 233 | } | ||
| 234 | } | ||
| 235 | |||
| 236 | soffset = radeon_sa_bo_hole_soffset(sa_manager); | ||
| 237 | eoffset = radeon_sa_bo_hole_eoffset(sa_manager); | ||
| 238 | wasted = (align - (soffset % align)) % align; | ||
| 239 | |||
| 240 | if ((eoffset - soffset) >= (size + wasted)) { | ||
| 241 | return true; | ||
| 242 | } | ||
| 243 | |||
| 244 | return false; | ||
| 245 | } | ||
| 246 | |||
| 247 | static bool radeon_sa_bo_next_hole(struct radeon_sa_manager *sa_manager, | ||
| 248 | struct radeon_fence **fences, | ||
| 249 | unsigned *tries) | ||
| 250 | { | ||
| 251 | struct radeon_sa_bo *best_bo = NULL; | ||
| 252 | unsigned i, soffset, best, tmp; | ||
| 253 | |||
| 254 | /* if hole points to the end of the buffer */ | ||
| 255 | if (sa_manager->hole->next == &sa_manager->olist) { | ||
| 256 | /* try again with its beginning */ | ||
| 257 | sa_manager->hole = &sa_manager->olist; | ||
| 258 | return true; | ||
| 259 | } | ||
| 260 | |||
| 261 | soffset = radeon_sa_bo_hole_soffset(sa_manager); | ||
| 262 | /* to handle wrap around we add sa_manager->size */ | ||
| 263 | best = sa_manager->size * 2; | ||
| 264 | /* go over all fence list and try to find the closest sa_bo | ||
| 265 | * of the current last | ||
| 266 | */ | ||
| 267 | for (i = 0; i < RADEON_NUM_RINGS; ++i) { | ||
| 268 | struct radeon_sa_bo *sa_bo; | ||
| 269 | |||
| 270 | fences[i] = NULL; | ||
| 271 | |||
| 272 | if (list_empty(&sa_manager->flist[i])) { | ||
| 273 | continue; | ||
| 274 | } | ||
| 275 | |||
| 276 | sa_bo = list_first_entry(&sa_manager->flist[i], | ||
| 277 | struct radeon_sa_bo, flist); | ||
| 278 | |||
| 279 | if (!radeon_fence_signaled(sa_bo->fence)) { | ||
| 280 | fences[i] = sa_bo->fence; | ||
| 281 | continue; | ||
| 282 | } | ||
| 283 | |||
| 284 | /* limit the number of tries each ring gets */ | ||
| 285 | if (tries[i] > 2) { | ||
| 286 | continue; | ||
| 287 | } | ||
| 288 | |||
| 289 | tmp = sa_bo->soffset; | ||
| 290 | if (tmp < soffset) { | ||
| 291 | /* wrap around, pretend it's after */ | ||
| 292 | tmp += sa_manager->size; | ||
| 293 | } | ||
| 294 | tmp -= soffset; | ||
| 295 | if (tmp < best) { | ||
| 296 | /* this sa bo is the closest one */ | ||
| 297 | best = tmp; | ||
| 298 | best_bo = sa_bo; | ||
| 299 | } | ||
| 300 | } | ||
| 301 | |||
| 302 | if (best_bo) { | ||
| 303 | ++tries[best_bo->fence->ring]; | ||
| 304 | sa_manager->hole = best_bo->olist.prev; | ||
| 305 | |||
| 306 | /* we knew that this one is signaled, | ||
| 307 | so it's save to remote it */ | ||
| 308 | radeon_sa_bo_remove_locked(best_bo); | ||
| 309 | return true; | ||
| 310 | } | ||
| 311 | return false; | ||
| 312 | } | ||
| 313 | |||
| 314 | int radeon_sa_bo_new(struct radeon_device *rdev, | ||
| 315 | struct radeon_sa_manager *sa_manager, | ||
| 316 | struct radeon_sa_bo **sa_bo, | ||
| 317 | unsigned size, unsigned align) | ||
| 318 | { | ||
| 319 | struct radeon_fence *fences[RADEON_NUM_RINGS]; | ||
| 320 | unsigned tries[RADEON_NUM_RINGS]; | ||
| 321 | int i, r; | ||
| 322 | |||
| 323 | BUG_ON(align > sa_manager->align); | ||
| 324 | BUG_ON(size > sa_manager->size); | ||
| 325 | |||
| 326 | *sa_bo = kmalloc(sizeof(struct radeon_sa_bo), GFP_KERNEL); | ||
| 327 | if ((*sa_bo) == NULL) { | ||
| 328 | return -ENOMEM; | ||
| 329 | } | ||
| 330 | (*sa_bo)->manager = sa_manager; | ||
| 331 | (*sa_bo)->fence = NULL; | ||
| 332 | INIT_LIST_HEAD(&(*sa_bo)->olist); | ||
| 333 | INIT_LIST_HEAD(&(*sa_bo)->flist); | ||
| 334 | |||
| 335 | spin_lock(&sa_manager->wq.lock); | ||
| 336 | do { | ||
| 337 | for (i = 0; i < RADEON_NUM_RINGS; ++i) | ||
| 338 | tries[i] = 0; | ||
| 339 | |||
| 340 | do { | ||
| 341 | radeon_sa_bo_try_free(sa_manager); | ||
| 342 | |||
| 343 | if (radeon_sa_bo_try_alloc(sa_manager, *sa_bo, | ||
| 344 | size, align)) { | ||
| 345 | spin_unlock(&sa_manager->wq.lock); | ||
| 346 | return 0; | ||
| 347 | } | ||
| 348 | |||
| 349 | /* see if we can skip over some allocations */ | ||
| 350 | } while (radeon_sa_bo_next_hole(sa_manager, fences, tries)); | ||
| 351 | |||
| 352 | for (i = 0; i < RADEON_NUM_RINGS; ++i) | ||
| 353 | radeon_fence_ref(fences[i]); | ||
| 354 | |||
| 355 | spin_unlock(&sa_manager->wq.lock); | ||
| 356 | r = radeon_fence_wait_any(rdev, fences, false); | ||
| 357 | for (i = 0; i < RADEON_NUM_RINGS; ++i) | ||
| 358 | radeon_fence_unref(&fences[i]); | ||
| 359 | spin_lock(&sa_manager->wq.lock); | ||
| 360 | /* if we have nothing to wait for block */ | ||
| 361 | if (r == -ENOENT) { | ||
| 362 | r = wait_event_interruptible_locked( | ||
| 363 | sa_manager->wq, | ||
| 364 | radeon_sa_event(sa_manager, size, align) | ||
| 365 | ); | ||
| 366 | } | ||
| 367 | |||
| 368 | } while (!r); | ||
| 369 | |||
| 370 | spin_unlock(&sa_manager->wq.lock); | ||
| 371 | kfree(*sa_bo); | ||
| 372 | *sa_bo = NULL; | ||
| 373 | return r; | ||
| 374 | } | ||
| 375 | |||
| 376 | void radeon_sa_bo_free(struct radeon_device *rdev, struct radeon_sa_bo **sa_bo, | ||
| 377 | struct radeon_fence *fence) | 138 | struct radeon_fence *fence) |
| 378 | { | 139 | { |
| 379 | struct radeon_sa_manager *sa_manager; | ||
| 380 | |||
| 381 | if (sa_bo == NULL || *sa_bo == NULL) { | 140 | if (sa_bo == NULL || *sa_bo == NULL) { |
| 382 | return; | 141 | return; |
| 383 | } | 142 | } |
| 384 | 143 | ||
| 385 | sa_manager = (*sa_bo)->manager; | 144 | if (fence) |
| 386 | spin_lock(&sa_manager->wq.lock); | 145 | drm_suballoc_free(*sa_bo, &fence->base); |
| 387 | if (fence && !radeon_fence_signaled(fence)) { | 146 | else |
| 388 | (*sa_bo)->fence = radeon_fence_ref(fence); | 147 | drm_suballoc_free(*sa_bo, NULL); |
| 389 | list_add_tail(&(*sa_bo)->flist, | 148 | |
| 390 | &sa_manager->flist[fence->ring]); | ||
| 391 | } else { | ||
| 392 | radeon_sa_bo_remove_locked(*sa_bo); | ||
| 393 | } | ||
| 394 | wake_up_all_locked(&sa_manager->wq); | ||
| 395 | spin_unlock(&sa_manager->wq.lock); | ||
| 396 | *sa_bo = NULL; | 149 | *sa_bo = NULL; |
| 397 | } | 150 | } |
| 398 | 151 | ||
| @@ -400,25 +153,8 @@ void radeon_sa_bo_free(struct radeon_device *rdev, struct radeon_sa_bo **sa_bo, · 1 unmodified line | |||
| 400 | void radeon_sa_bo_dump_debug_info(struct radeon_sa_manager *sa_manager, | 153 | void radeon_sa_bo_dump_debug_info(struct radeon_sa_manager *sa_manager, |
| 401 | struct seq_file *m) | 154 | struct seq_file *m) |
| 402 | { | 155 | { |
| 403 | struct radeon_sa_bo *i; | 156 | struct drm_printer p = drm_seq_file_printer(m); |
| 404 | 157 | ||
| 405 | spin_lock(&sa_manager->wq.lock); | 158 | drm_suballoc_dump_debug_info(&sa_manager->base, &p, sa_manager->gpu_addr); |
| 406 | list_for_each_entry(i, &sa_manager->olist, olist) { | ||
| 407 | uint64_t soffset = i->soffset + sa_manager->gpu_addr; | ||
| 408 | uint64_t eoffset = i->eoffset + sa_manager->gpu_addr; | ||
| 409 | if (&i->olist == sa_manager->hole) { | ||
| 410 | seq_printf(m, ">"); | ||
| 411 | } else { | ||
| 412 | seq_printf(m, " "); | ||
| 413 | } | ||
| 414 | seq_printf(m, "[0x%010llx 0x%010llx] size %8lld", | ||
| 415 | soffset, eoffset, eoffset - soffset); | ||
| 416 | if (i->fence) { | ||
| 417 | seq_printf(m, " protected by 0x%016llx on ring %d", | ||
| 418 | i->fence->seq, i->fence->ring); | ||
| 419 | } | ||
| 420 | seq_printf(m, "\n"); | ||
| 421 | } | ||
| 422 | spin_unlock(&sa_manager->wq.lock); | ||
| 423 | } | 159 | } |
| 424 | #endif | 160 | #endif |
| @@ -40,7 +40,7 @@ int radeon_semaphore_create(struct radeon_device *rdev, · 39 unmodified lines | |||
| 40 | if (*semaphore == NULL) { | 40 | if (*semaphore == NULL) { |
| 41 | return -ENOMEM; | 41 | return -ENOMEM; |
| 42 | } | 42 | } |
| 43 | r = radeon_sa_bo_new(rdev, &rdev->ring_tmp_bo, | 43 | r = radeon_sa_bo_new(&rdev->ring_tmp_bo, |
| 44 | &(*semaphore)->sa_bo, 8, 8); | 44 | &(*semaphore)->sa_bo, 8, 8); |
| 45 | if (r) { | 45 | if (r) { |
| 46 | kfree(*semaphore); | 46 | kfree(*semaphore); |
| @@ -100,7 +100,7 @@ void radeon_semaphore_free(struct radeon_device *rdev, · 53 unmodified lines | |||
| 100 | dev_err(rdev->dev, "semaphore %p has more waiters than signalers," | 100 | dev_err(rdev->dev, "semaphore %p has more waiters than signalers," |
| 101 | " hardware lockup imminent!\n", *semaphore); | 101 | " hardware lockup imminent!\n", *semaphore); |
| 102 | } | 102 | } |
| 103 | radeon_sa_bo_free(rdev, &(*semaphore)->sa_bo, fence); | 103 | radeon_sa_bo_free(&(*semaphore)->sa_bo, fence); |
| 104 | kfree(*semaphore); | 104 | kfree(*semaphore); |
| 105 | *semaphore = NULL; | 105 | *semaphore = NULL; |
| 106 | } | 106 | } |
| @@ -211,13 +211,10 @@ static int radeon_bo_move(struct ttm_buffer_object *bo, bool evict, · 210 unmodified lines | |||
| 211 | if (r) | 211 | if (r) |
| 212 | return r; | 212 | return r; |
| 213 | 213 | ||
| 214 | /* Can't move a pinned BO */ | ||
| 215 | rbo = container_of(bo, struct radeon_bo, tbo); | 214 | rbo = container_of(bo, struct radeon_bo, tbo); |
| 216 | if (WARN_ON_ONCE(rbo->tbo.pin_count > 0)) | ||
| 217 | return -EINVAL; | ||
| 218 | |||
| 219 | rdev = radeon_get_rdev(bo->bdev); | 215 | rdev = radeon_get_rdev(bo->bdev); |
| 220 | if (old_mem->mem_type == TTM_PL_SYSTEM && bo->ttm == NULL) { | 216 | if (!old_mem || (old_mem->mem_type == TTM_PL_SYSTEM && |
| 217 | bo->ttm == NULL)) { | ||
| 221 | ttm_bo_move_null(bo, new_mem); | 218 | ttm_bo_move_null(bo, new_mem); |
| 222 | goto out; | 219 | goto out; |
| 223 | } | 220 | } |
| @@ -261,9 +261,6 @@ static int rockchip_drm_gem_object_mmap(struct drm_gem_object *obj, · 260 unmodified lines | |||
| 261 | else | 261 | else |
| 262 | ret = rockchip_drm_gem_object_mmap_dma(obj, vma); | 262 | ret = rockchip_drm_gem_object_mmap_dma(obj, vma); |
| 263 | 263 | ||
| 264 | if (ret) | ||
| 265 | drm_gem_vm_close(vma); | ||
| 266 | |||
| 267 | return ret; | 264 | return ret; |
| 268 | } | 265 | } |
| 269 | 266 | ||
| @@ -518,8 +515,14 @@ int rockchip_gem_prime_vmap(struct drm_gem_object *obj, struct iosys_map *map) · 248 unmodified lines | |||
| 518 | struct rockchip_gem_object *rk_obj = to_rockchip_obj(obj); | 515 | struct rockchip_gem_object *rk_obj = to_rockchip_obj(obj); |
| 519 | 516 | ||
| 520 | if (rk_obj->pages) { | 517 | if (rk_obj->pages) { |
| 521 | void *vaddr = vmap(rk_obj->pages, rk_obj->num_pages, VM_MAP, | 518 | void *vaddr; |
| 522 | pgprot_writecombine(PAGE_KERNEL)); | 519 | |
| 520 | if (rk_obj->kvaddr) | ||
| 521 | vaddr = rk_obj->kvaddr; | ||
| 522 | else | ||
| 523 | vaddr = vmap(rk_obj->pages, rk_obj->num_pages, VM_MAP, | ||
| 524 | pgprot_writecombine(PAGE_KERNEL)); | ||
| 525 | |||
| 523 | if (!vaddr) | 526 | if (!vaddr) |
| 524 | return -ENOMEM; | 527 | return -ENOMEM; |
| 525 | iosys_map_set_vaddr(map, vaddr); | 528 | iosys_map_set_vaddr(map, vaddr); |
| @@ -539,7 +542,8 @@ void rockchip_gem_prime_vunmap(struct drm_gem_object *obj, · 13 unmodified lines | |||
| 539 | struct rockchip_gem_object *rk_obj = to_rockchip_obj(obj); | 542 | struct rockchip_gem_object *rk_obj = to_rockchip_obj(obj); |
| 540 | 543 | ||
| 541 | if (rk_obj->pages) { | 544 | if (rk_obj->pages) { |
| 542 | vunmap(map->vaddr); | 545 | if (map->vaddr != rk_obj->kvaddr) |
| 546 | vunmap(map->vaddr); | ||
| 543 | return; | 547 | return; |
| 544 | } | 548 | } |
| 545 | 549 | ||
| @@ -316,13 +316,10 @@ static int vop_convert_afbc_format(uint32_t format) · 315 unmodified lines | |||
| 316 | case DRM_FORMAT_RGB565: | 316 | case DRM_FORMAT_RGB565: |
| 317 | case DRM_FORMAT_BGR565: | 317 | case DRM_FORMAT_BGR565: |
| 318 | return AFBC_FMT_RGB565; | 318 | return AFBC_FMT_RGB565; |
| 319 | /* either of the below should not be reachable */ | ||
| 320 | default: | 319 | default: |
| 321 | DRM_WARN_ONCE("unsupported AFBC format[%08x]\n", format); | 320 | DRM_DEBUG_KMS("unsupported AFBC format[%08x]\n", format); |
| 322 | return -EINVAL; | 321 | return -EINVAL; |
| 323 | } | 322 | } |
| 324 | |||
| 325 | return -EINVAL; | ||
| 326 | } | 323 | } |
| 327 | 324 | ||
| 328 | static uint16_t scl_vop_cal_scale(enum scale_mode mode, uint32_t src, | 325 | static uint16_t scl_vop_cal_scale(enum scale_mode mode, uint32_t src, |
| @@ -2221,7 +2218,7 @@ static int vop_bind(struct device *dev, struct device *master, void *data) · 1892 unmodified lines | |||
| 2221 | goto err_disable_pm_runtime; | 2218 | goto err_disable_pm_runtime; |
| 2222 | 2219 | ||
| 2223 | if (vop->data->feature & VOP_FEATURE_INTERNAL_RGB) { | 2220 | if (vop->data->feature & VOP_FEATURE_INTERNAL_RGB) { |
| 2224 | vop->rgb = rockchip_rgb_init(dev, &vop->crtc, vop->drm_dev); | 2221 | vop->rgb = rockchip_rgb_init(dev, &vop->crtc, vop->drm_dev, 0); |
| 2225 | if (IS_ERR(vop->rgb)) { | 2222 | if (IS_ERR(vop->rgb)) { |
| 2226 | ret = PTR_ERR(vop->rgb); | 2223 | ret = PTR_ERR(vop->rgb); |
| 2227 | goto err_disable_pm_runtime; | 2224 | goto err_disable_pm_runtime; |
| @@ -38,6 +38,7 @@ · 37 unmodified lines | |||
| 38 | #include "rockchip_drm_gem.h" | 38 | #include "rockchip_drm_gem.h" |
| 39 | #include "rockchip_drm_fb.h" | 39 | #include "rockchip_drm_fb.h" |
| 40 | #include "rockchip_drm_vop2.h" | 40 | #include "rockchip_drm_vop2.h" |
| 41 | #include "rockchip_rgb.h" | ||
| 41 | 42 | ||
| 42 | /* | 43 | /* |
| 43 | * VOP2 architecture | 44 | * VOP2 architecture |
| @@ -211,6 +212,9 @@ struct vop2 { · 167 unmodified lines | |||
| 211 | struct clk *hclk; | 212 | struct clk *hclk; |
| 212 | struct clk *aclk; | 213 | struct clk *aclk; |
| 213 | 214 | ||
| 215 | /* optional internal rgb encoder */ | ||
| 216 | struct rockchip_rgb *rgb; | ||
| 217 | |||
| 214 | /* must be put at the end of the struct */ | 218 | /* must be put at the end of the struct */ |
| 215 | struct vop2_win win[]; | 219 | struct vop2_win win[]; |
| 216 | }; | 220 | }; |
| @@ -2245,7 +2249,7 @@ static struct vop2_video_port *find_vp_without_primary(struct vop2 *vop2) · 2028 unmodified lines | |||
| 2245 | 2249 | ||
| 2246 | #define NR_LAYERS 6 | 2250 | #define NR_LAYERS 6 |
| 2247 | 2251 | ||
| 2248 | static int vop2_create_crtc(struct vop2 *vop2) | 2252 | static int vop2_create_crtcs(struct vop2 *vop2) |
| 2249 | { | 2253 | { |
| 2250 | const struct vop2_data *vop2_data = vop2->data; | 2254 | const struct vop2_data *vop2_data = vop2->data; |
| 2251 | struct drm_device *drm = vop2->drm; | 2255 | struct drm_device *drm = vop2->drm; |
| @@ -2321,10 +2325,11 @@ static int vop2_create_crtc(struct vop2 *vop2) · 69 unmodified lines | |||
| 2321 | /* change the unused primary window to overlay window */ | 2325 | /* change the unused primary window to overlay window */ |
| 2322 | win->type = DRM_PLANE_TYPE_OVERLAY; | 2326 | win->type = DRM_PLANE_TYPE_OVERLAY; |
| 2323 | } | 2327 | } |
| 2324 | } | 2328 | } else if (win->type == DRM_PLANE_TYPE_OVERLAY) { |
| 2325 | |||
| 2326 | if (win->type == DRM_PLANE_TYPE_OVERLAY) | ||
| 2327 | possible_crtcs = (1 << nvps) - 1; | 2329 | possible_crtcs = (1 << nvps) - 1; |
| 2330 | } else { | ||
| 2331 | possible_crtcs = 0; | ||
| 2332 | } | ||
| 2328 | 2333 | ||
| 2329 | ret = vop2_plane_init(vop2, win, possible_crtcs); | 2334 | ret = vop2_plane_init(vop2, win, possible_crtcs); |
| 2330 | if (ret) { | 2335 | if (ret) { |
| @@ -2370,15 +2375,44 @@ static int vop2_create_crtc(struct vop2 *vop2) · 39 unmodified lines | |||
| 2370 | return 0; | 2375 | return 0; |
| 2371 | } | 2376 | } |
| 2372 | 2377 | ||
| 2373 | static void vop2_destroy_crtc(struct drm_crtc *crtc) | 2378 | static void vop2_destroy_crtcs(struct vop2 *vop2) |
| 2374 | { | 2379 | { |
| 2375 | of_node_put(crtc->port); | 2380 | struct drm_device *drm = vop2->drm; |
| 2381 | struct list_head *crtc_list = &drm->mode_config.crtc_list; | ||
| 2382 | struct list_head *plane_list = &drm->mode_config.plane_list; | ||
| 2383 | struct drm_crtc *crtc, *tmpc; | ||
| 2384 | struct drm_plane *plane, *tmpp; | ||
| 2385 | |||
| 2386 | list_for_each_entry_safe(plane, tmpp, plane_list, head) | ||
| 2387 | drm_plane_cleanup(plane); | ||
| 2376 | 2388 | ||
| 2377 | /* | 2389 | /* |
| 2378 | * Destroy CRTC after vop2_plane_destroy() since vop2_disable_plane() | 2390 | * Destroy CRTC after vop2_plane_destroy() since vop2_disable_plane() |
| 2379 | * references the CRTC. | 2391 | * references the CRTC. |
| 2380 | */ | 2392 | */ |
| 2381 | drm_crtc_cleanup(crtc); | 2393 | list_for_each_entry_safe(crtc, tmpc, crtc_list, head) { |
| 2394 | of_node_put(crtc->port); | ||
| 2395 | drm_crtc_cleanup(crtc); | ||
| 2396 | } | ||
| 2397 | } | ||
| 2398 | |||
| 2399 | static int vop2_find_rgb_encoder(struct vop2 *vop2) | ||
| 2400 | { | ||
| 2401 | struct device_node *node = vop2->dev->of_node; | ||
| 2402 | struct device_node *endpoint; | ||
| 2403 | int i; | ||
| 2404 | |||
| 2405 | for (i = 0; i < vop2->data->nr_vps; i++) { | ||
| 2406 | endpoint = of_graph_get_endpoint_by_regs(node, i, | ||
| 2407 | ROCKCHIP_VOP2_EP_RGB0); | ||
| 2408 | if (!endpoint) | ||
| 2409 | continue; | ||
| 2410 | |||
| 2411 | of_node_put(endpoint); | ||
| 2412 | return i; | ||
| 2413 | } | ||
| 2414 | |||
| 2415 | return -ENOENT; | ||
| 2382 | } | 2416 | } |
| 2383 | 2417 | ||
| 2384 | static struct reg_field vop2_cluster_regs[VOP2_WIN_MAX_REG] = { | 2418 | static struct reg_field vop2_cluster_regs[VOP2_WIN_MAX_REG] = { |
| @@ -2682,33 +2716,45 @@ static int vop2_bind(struct device *dev, struct device *master, void *data) · 297 unmodified lines | |||
| 2682 | if (ret) | 2716 | if (ret) |
| 2683 | return ret; | 2717 | return ret; |
| 2684 | 2718 | ||
| 2685 | ret = vop2_create_crtc(vop2); | 2719 | ret = vop2_create_crtcs(vop2); |
| 2686 | if (ret) | 2720 | if (ret) |
| 2687 | return ret; | 2721 | return ret; |
| 2688 | 2722 | ||
| 2723 | ret = vop2_find_rgb_encoder(vop2); | ||
| 2724 | if (ret >= 0) { | ||
| 2725 | vop2->rgb = rockchip_rgb_init(dev, &vop2->vps[ret].crtc, | ||
| 2726 | vop2->drm, ret); | ||
| 2727 | if (IS_ERR(vop2->rgb)) { | ||
| 2728 | if (PTR_ERR(vop2->rgb) == -EPROBE_DEFER) { | ||
| 2729 | ret = PTR_ERR(vop2->rgb); | ||
| 2730 | goto err_crtcs; | ||
| 2731 | } | ||
| 2732 | vop2->rgb = NULL; | ||
| 2733 | } | ||
| 2734 | } | ||
| 2735 | |||
| 2689 | rockchip_drm_dma_init_device(vop2->drm, vop2->dev); | 2736 | rockchip_drm_dma_init_device(vop2->drm, vop2->dev); |
| 2690 | 2737 | ||
| 2691 | pm_runtime_enable(&pdev->dev); | 2738 | pm_runtime_enable(&pdev->dev); |
| 2692 | 2739 | ||
| 2693 | return 0; | 2740 | return 0; |
| 2741 | |||
| 2742 | err_crtcs: | ||
| 2743 | vop2_destroy_crtcs(vop2); | ||
| 2744 | |||
| 2745 | return ret; | ||
| 2694 | } | 2746 | } |
| 2695 | 2747 | ||
| 2696 | static void vop2_unbind(struct device *dev, struct device *master, void *data) | 2748 | static void vop2_unbind(struct device *dev, struct device *master, void *data) |
| 2697 | { | 2749 | { |
| 2698 | struct vop2 *vop2 = dev_get_drvdata(dev); | 2750 | struct vop2 *vop2 = dev_get_drvdata(dev); |
| 2699 | struct drm_device *drm = vop2->drm; | ||
| 2700 | struct list_head *plane_list = &drm->mode_config.plane_list; | ||
| 2701 | struct list_head *crtc_list = &drm->mode_config.crtc_list; | ||
| 2702 | struct drm_crtc *crtc, *tmpc; | ||
| 2703 | struct drm_plane *plane, *tmpp; | ||
| 2704 | 2751 | ||
| 2705 | pm_runtime_disable(dev); | 2752 | pm_runtime_disable(dev); |
| 2706 | 2753 | ||
| 2707 | list_for_each_entry_safe(plane, tmpp, plane_list, head) | 2754 | if (vop2->rgb) |
| 2708 | drm_plane_cleanup(plane); | 2755 | rockchip_rgb_fini(vop2->rgb); |
| 2709 | 2756 | ||
| 2710 | list_for_each_entry_safe(crtc, tmpc, crtc_list, head) | 2757 | vop2_destroy_crtcs(vop2); |
| 2711 | vop2_destroy_crtc(crtc); | ||
| 2712 | } | 2758 | } |
| 2713 | 2759 | ||
| 2714 | const struct component_ops vop2_component_ops = { | 2760 | const struct component_ops vop2_component_ops = { |
| @@ -22,13 +22,11 @@ · 21 unmodified lines | |||
| 22 | #include "rockchip_drm_vop.h" | 22 | #include "rockchip_drm_vop.h" |
| 23 | #include "rockchip_rgb.h" | 23 | #include "rockchip_rgb.h" |
| 24 | 24 | ||
| 25 | #define encoder_to_rgb(c) container_of(c, struct rockchip_rgb, encoder) | ||
| 26 | |||
| 27 | struct rockchip_rgb { | 25 | struct rockchip_rgb { |
| 28 | struct device *dev; | 26 | struct device *dev; |
| 29 | struct drm_device *drm_dev; | 27 | struct drm_device *drm_dev; |
| 30 | struct drm_bridge *bridge; | 28 | struct drm_bridge *bridge; |
| 31 | struct drm_encoder encoder; | 29 | struct rockchip_encoder encoder; |
| 32 | struct drm_connector connector; | 30 | struct drm_connector connector; |
| 33 | int output_mode; | 31 | int output_mode; |
| 34 | }; | 32 | }; |
| @@ -74,7 +72,8 @@ struct drm_encoder_helper_funcs rockchip_rgb_encoder_helper_funcs = { · 39 unmodified lines | |||
| 74 | 72 | ||
| 75 | struct rockchip_rgb *rockchip_rgb_init(struct device *dev, | 73 | struct rockchip_rgb *rockchip_rgb_init(struct device *dev, |
| 76 | struct drm_crtc *crtc, | 74 | struct drm_crtc *crtc, |
| 77 | struct drm_device *drm_dev) | 75 | struct drm_device *drm_dev, |
| 76 | int video_port) | ||
| 78 | { | 77 | { |
| 79 | struct rockchip_rgb *rgb; | 78 | struct rockchip_rgb *rgb; |
| 80 | struct drm_encoder *encoder; | 79 | struct drm_encoder *encoder; |
| @@ -92,7 +91,7 @@ struct rockchip_rgb *rockchip_rgb_init(struct device *dev, · 11 unmodified lines | |||
| 92 | rgb->dev = dev; | 91 | rgb->dev = dev; |
| 93 | rgb->drm_dev = drm_dev; | 92 | rgb->drm_dev = drm_dev; |
| 94 | 93 | ||
| 95 | port = of_graph_get_port_by_id(dev->of_node, 0); | 94 | port = of_graph_get_port_by_id(dev->of_node, video_port); |
| 96 | if (!port) | 95 | if (!port) |
| 97 | return ERR_PTR(-EINVAL); | 96 | return ERR_PTR(-EINVAL); |
| 98 | 97 | ||
| @@ -105,8 +104,8 @@ struct rockchip_rgb *rockchip_rgb_init(struct device *dev, · 6 unmodified lines | |||
| 105 | continue; | 104 | continue; |
| 106 | 105 | ||
| 107 | child_count++; | 106 | child_count++; |
| 108 | ret = drm_of_find_panel_or_bridge(dev->of_node, 0, endpoint_id, | 107 | ret = drm_of_find_panel_or_bridge(dev->of_node, video_port, |
| 109 | &panel, &bridge); | 108 | endpoint_id, &panel, &bridge); |
| 110 | if (!ret) { | 109 | if (!ret) { |
| 111 | of_node_put(endpoint); | 110 | of_node_put(endpoint); |
| 112 | break; | 111 | break; |
| @@ -125,7 +124,7 @@ struct rockchip_rgb *rockchip_rgb_init(struct device *dev, · 12 unmodified lines | |||
| 125 | return ERR_PTR(ret); | 124 | return ERR_PTR(ret); |
| 126 | } | 125 | } |
| 127 | 126 | ||
| 128 | encoder = &rgb->encoder; | 127 | encoder = &rgb->encoder.encoder; |
| 129 | encoder->possible_crtcs = drm_crtc_mask(crtc); | 128 | encoder->possible_crtcs = drm_crtc_mask(crtc); |
| 130 | 129 | ||
| 131 | ret = drm_simple_encoder_init(drm_dev, encoder, DRM_MODE_ENCODER_NONE); | 130 | ret = drm_simple_encoder_init(drm_dev, encoder, DRM_MODE_ENCODER_NONE); |
| @@ -161,6 +160,8 @@ struct rockchip_rgb *rockchip_rgb_init(struct device *dev, · 29 unmodified lines | |||
| 161 | goto err_free_encoder; | 160 | goto err_free_encoder; |
| 162 | } | 161 | } |
| 163 | 162 | ||
| 163 | rgb->encoder.crtc_endpoint_id = endpoint_id; | ||
| 164 | |||
| 164 | ret = drm_connector_attach_encoder(connector, encoder); | 165 | ret = drm_connector_attach_encoder(connector, encoder); |
| 165 | if (ret < 0) { | 166 | if (ret < 0) { |
| 166 | DRM_DEV_ERROR(drm_dev->dev, | 167 | DRM_DEV_ERROR(drm_dev->dev, |
| @@ -182,6 +183,6 @@ void rockchip_rgb_fini(struct rockchip_rgb *rgb) · 15 unmodified lines | |||
| 182 | { | 183 | { |
| 183 | drm_panel_bridge_remove(rgb->bridge); | 184 | drm_panel_bridge_remove(rgb->bridge); |
| 184 | drm_connector_cleanup(&rgb->connector); | 185 | drm_connector_cleanup(&rgb->connector); |
| 185 | drm_encoder_cleanup(&rgb->encoder); | 186 | drm_encoder_cleanup(&rgb->encoder.encoder); |
| 186 | } | 187 | } |
| 187 | EXPORT_SYMBOL_GPL(rockchip_rgb_fini); | 188 | EXPORT_SYMBOL_GPL(rockchip_rgb_fini); |
| @@ -8,12 +8,14 @@ · 7 unmodified lines | |||
| 8 | #ifdef CONFIG_ROCKCHIP_RGB | 8 | #ifdef CONFIG_ROCKCHIP_RGB |
| 9 | struct rockchip_rgb *rockchip_rgb_init(struct device *dev, | 9 | struct rockchip_rgb *rockchip_rgb_init(struct device *dev, |
| 10 | struct drm_crtc *crtc, | 10 | struct drm_crtc *crtc, |
| 11 | struct drm_device *drm_dev); | 11 | struct drm_device *drm_dev, |
| 12 | int video_port); | ||
| 12 | void rockchip_rgb_fini(struct rockchip_rgb *rgb); | 13 | void rockchip_rgb_fini(struct rockchip_rgb *rgb); |
| 13 | #else | 14 | #else |
| 14 | static inline struct rockchip_rgb *rockchip_rgb_init(struct device *dev, | 15 | static inline struct rockchip_rgb *rockchip_rgb_init(struct device *dev, |
| 15 | struct drm_crtc *crtc, | 16 | struct drm_crtc *crtc, |
| 16 | struct drm_device *drm_dev) | 17 | struct drm_device *drm_dev, |
| 18 | int video_port) | ||
| 17 | { | 19 | { |
| 18 | return NULL; | 20 | return NULL; |
| 19 | } | 21 | } |
| @@ -53,6 +53,7 @@ · 52 unmodified lines | |||
| 53 | 53 | ||
| 54 | #include <drm/drm_print.h> | 54 | #include <drm/drm_print.h> |
| 55 | #include <drm/drm_gem.h> | 55 | #include <drm/drm_gem.h> |
| 56 | #include <drm/drm_syncobj.h> | ||
| 56 | #include <drm/gpu_scheduler.h> | 57 | #include <drm/gpu_scheduler.h> |
| 57 | #include <drm/spsc_queue.h> | 58 | #include <drm/spsc_queue.h> |
| 58 | 59 | ||
| @@ -718,6 +719,34 @@ int drm_sched_job_add_dependency(struct drm_sched_job *job, · 659 unmodified lines | |||
| 718 | } | 719 | } |
| 719 | EXPORT_SYMBOL(drm_sched_job_add_dependency); | 720 | EXPORT_SYMBOL(drm_sched_job_add_dependency); |
| 720 | 721 | ||
| 722 | /** | ||
| 723 | * drm_sched_job_add_syncobj_dependency - adds a syncobj's fence as a job dependency | ||
| 724 | * @job: scheduler job to add the dependencies to | ||
| 725 | * @file_private: drm file private pointer | ||
| 726 | * @handle: syncobj handle to lookup | ||
| 727 | * @point: timeline point | ||
| 728 | * | ||
| 729 | * This adds the fence matching the given syncobj to @job. | ||
| 730 | * | ||
| 731 | * Returns: | ||
| 732 | * 0 on success, or an error on failing to expand the array. | ||
| 733 | */ | ||
| 734 | int drm_sched_job_add_syncobj_dependency(struct drm_sched_job *job, | ||
| 735 | struct drm_file *file, | ||
| 736 | u32 handle, | ||
| 737 | u32 point) | ||
| 738 | { | ||
| 739 | struct dma_fence *fence; | ||
| 740 | int ret; | ||
| 741 | |||
| 742 | ret = drm_syncobj_find_fence(file, handle, point, 0, &fence); | ||
| 743 | if (ret) | ||
| 744 | return ret; | ||
| 745 | |||
| 746 | return drm_sched_job_add_dependency(job, fence); | ||
| 747 | } | ||
| 748 | EXPORT_SYMBOL(drm_sched_job_add_syncobj_dependency); | ||
| 749 | |||
| 721 | /** | 750 | /** |
| 722 | * drm_sched_job_add_resv_dependencies - add all fences from the resv to the job | 751 | * drm_sched_job_add_resv_dependencies - add all fences from the resv to the job |
| 723 | * @job: scheduler job to add the dependencies to | 752 | * @job: scheduler job to add the dependencies to |
| @@ -597,7 +597,7 @@ static void drm_test_fb_xrgb8888_to_xrgb1555(struct kunit *test) · 596 unmodified lines | |||
| 597 | 597 | ||
| 598 | drm_fb_xrgb8888_to_xrgb1555(&dst, &result->dst_pitch, &src, &fb, ¶ms->clip); | 598 | drm_fb_xrgb8888_to_xrgb1555(&dst, &result->dst_pitch, &src, &fb, ¶ms->clip); |
| 599 | buf = le16buf_to_cpu(test, (__force const __le16 *)buf, dst_size / sizeof(__le16)); | 599 | buf = le16buf_to_cpu(test, (__force const __le16 *)buf, dst_size / sizeof(__le16)); |
| 600 | KUNIT_EXPECT_EQ(test, memcmp(buf, result->expected, dst_size), 0); | 600 | KUNIT_EXPECT_MEMEQ(test, buf, result->expected, dst_size); |
| 601 | } | 601 | } |
| 602 | 602 | ||
| 603 | static void drm_test_fb_xrgb8888_to_argb1555(struct kunit *test) | 603 | static void drm_test_fb_xrgb8888_to_argb1555(struct kunit *test) |
| @@ -628,7 +628,7 @@ static void drm_test_fb_xrgb8888_to_argb1555(struct kunit *test) · 24 unmodified lines | |||
| 628 | 628 | ||
| 629 | drm_fb_xrgb8888_to_argb1555(&dst, &result->dst_pitch, &src, &fb, ¶ms->clip); | 629 | drm_fb_xrgb8888_to_argb1555(&dst, &result->dst_pitch, &src, &fb, ¶ms->clip); |
| 630 | buf = le16buf_to_cpu(test, (__force const __le16 *)buf, dst_size / sizeof(__le16)); | 630 | buf = le16buf_to_cpu(test, (__force const __le16 *)buf, dst_size / sizeof(__le16)); |
| 631 | KUNIT_EXPECT_EQ(test, memcmp(buf, result->expected, dst_size), 0); | 631 | KUNIT_EXPECT_MEMEQ(test, buf, result->expected, dst_size); |
| 632 | } | 632 | } |
| 633 | 633 | ||
| 634 | static void drm_test_fb_xrgb8888_to_rgba5551(struct kunit *test) | 634 | static void drm_test_fb_xrgb8888_to_rgba5551(struct kunit *test) |
| @@ -659,7 +659,7 @@ static void drm_test_fb_xrgb8888_to_rgba5551(struct kunit *test) · 24 unmodified lines | |||
| 659 | 659 | ||
| 660 | drm_fb_xrgb8888_to_rgba5551(&dst, &result->dst_pitch, &src, &fb, ¶ms->clip); | 660 | drm_fb_xrgb8888_to_rgba5551(&dst, &result->dst_pitch, &src, &fb, ¶ms->clip); |
| 661 | buf = le16buf_to_cpu(test, (__force const __le16 *)buf, dst_size / sizeof(__le16)); | 661 | buf = le16buf_to_cpu(test, (__force const __le16 *)buf, dst_size / sizeof(__le16)); |
| 662 | KUNIT_EXPECT_EQ(test, memcmp(buf, result->expected, dst_size), 0); | 662 | KUNIT_EXPECT_MEMEQ(test, buf, result->expected, dst_size); |
| 663 | } | 663 | } |
| 664 | 664 | ||
| 665 | static void drm_test_fb_xrgb8888_to_rgb888(struct kunit *test) | 665 | static void drm_test_fb_xrgb8888_to_rgb888(struct kunit *test) |
| @@ -724,7 +724,7 @@ static void drm_test_fb_xrgb8888_to_argb8888(struct kunit *test) · 58 unmodified lines | |||
| 724 | 724 | ||
| 725 | drm_fb_xrgb8888_to_argb8888(&dst, &result->dst_pitch, &src, &fb, ¶ms->clip); | 725 | drm_fb_xrgb8888_to_argb8888(&dst, &result->dst_pitch, &src, &fb, ¶ms->clip); |
| 726 | buf = le32buf_to_cpu(test, (__force const __le32 *)buf, dst_size / sizeof(u32)); | 726 | buf = le32buf_to_cpu(test, (__force const __le32 *)buf, dst_size / sizeof(u32)); |
| 727 | KUNIT_EXPECT_EQ(test, memcmp(buf, result->expected, dst_size), 0); | 727 | KUNIT_EXPECT_MEMEQ(test, buf, result->expected, dst_size); |
| 728 | } | 728 | } |
| 729 | 729 | ||
| 730 | static void drm_test_fb_xrgb8888_to_xrgb2101010(struct kunit *test) | 730 | static void drm_test_fb_xrgb8888_to_xrgb2101010(struct kunit *test) |
| @@ -786,7 +786,7 @@ static void drm_test_fb_xrgb8888_to_argb2101010(struct kunit *test) · 55 unmodified lines | |||
| 786 | 786 | ||
| 787 | drm_fb_xrgb8888_to_argb2101010(&dst, &result->dst_pitch, &src, &fb, ¶ms->clip); | 787 | drm_fb_xrgb8888_to_argb2101010(&dst, &result->dst_pitch, &src, &fb, ¶ms->clip); |
| 788 | buf = le32buf_to_cpu(test, (__force const __le32 *)buf, dst_size / sizeof(u32)); | 788 | buf = le32buf_to_cpu(test, (__force const __le32 *)buf, dst_size / sizeof(u32)); |
| 789 | KUNIT_EXPECT_EQ(test, memcmp(buf, result->expected, dst_size), 0); | 789 | KUNIT_EXPECT_MEMEQ(test, buf, result->expected, dst_size); |
| 790 | } | 790 | } |
| 791 | 791 | ||
| 792 | static struct kunit_case drm_format_helper_test_cases[] = { | 792 | static struct kunit_case drm_format_helper_test_cases[] = { |
| @@ -1985,9 +1985,9 @@ dma_addr_t dispc_plane_state_p_uv_addr(const struct drm_plane_state *state) · 1984 unmodified lines | |||
| 1985 | (y * fb->pitches[1] / fb->format->vsub); | 1985 | (y * fb->pitches[1] / fb->format->vsub); |
| 1986 | } | 1986 | } |
| 1987 | 1987 | ||
| 1988 | int dispc_plane_setup(struct dispc_device *dispc, u32 hw_plane, | 1988 | void dispc_plane_setup(struct dispc_device *dispc, u32 hw_plane, |
| 1989 | const struct drm_plane_state *state, | 1989 | const struct drm_plane_state *state, |
| 1990 | u32 hw_videoport) | 1990 | u32 hw_videoport) |
| 1991 | { | 1991 | { |
| 1992 | bool lite = dispc->feat->vid_lite[hw_plane]; | 1992 | bool lite = dispc->feat->vid_lite[hw_plane]; |
| 1993 | u32 fourcc = state->fb->format->format; | 1993 | u32 fourcc = state->fb->format->format; |
| @@ -2066,15 +2066,11 @@ int dispc_plane_setup(struct dispc_device *dispc, u32 hw_plane, · 72 unmodified lines | |||
| 2066 | else | 2066 | else |
| 2067 | VID_REG_FLD_MOD(dispc, hw_plane, DISPC_VID_ATTRIBUTES, 0, | 2067 | VID_REG_FLD_MOD(dispc, hw_plane, DISPC_VID_ATTRIBUTES, 0, |
| 2068 | 28, 28); | 2068 | 28, 28); |
| 2069 | |||
| 2070 | return 0; | ||
| 2071 | } | 2069 | } |
| 2072 | 2070 | ||
| 2073 | int dispc_plane_enable(struct dispc_device *dispc, u32 hw_plane, bool enable) | 2071 | void dispc_plane_enable(struct dispc_device *dispc, u32 hw_plane, bool enable) |
| 2074 | { | 2072 | { |
| 2075 | VID_REG_FLD_MOD(dispc, hw_plane, DISPC_VID_ATTRIBUTES, !!enable, 0, 0); | 2073 | VID_REG_FLD_MOD(dispc, hw_plane, DISPC_VID_ATTRIBUTES, !!enable, 0, 0); |
| 2076 | |||
| 2077 | return 0; | ||
| 2078 | } | 2074 | } |
| 2079 | 2075 | ||
| 2080 | static u32 dispc_vid_get_fifo_size(struct dispc_device *dispc, u32 hw_plane) | 2076 | static u32 dispc_vid_get_fifo_size(struct dispc_device *dispc, u32 hw_plane) |
| @@ -123,10 +123,10 @@ int dispc_runtime_resume(struct dispc_device *dispc); · 122 unmodified lines | |||
| 123 | int dispc_plane_check(struct dispc_device *dispc, u32 hw_plane, | 123 | int dispc_plane_check(struct dispc_device *dispc, u32 hw_plane, |
| 124 | const struct drm_plane_state *state, | 124 | const struct drm_plane_state *state, |
| 125 | u32 hw_videoport); | 125 | u32 hw_videoport); |
| 126 | int dispc_plane_setup(struct dispc_device *dispc, u32 hw_plane, | 126 | void dispc_plane_setup(struct dispc_device *dispc, u32 hw_plane, |
| 127 | const struct drm_plane_state *state, | 127 | const struct drm_plane_state *state, |
| 128 | u32 hw_videoport); | 128 | u32 hw_videoport); |
| 129 | int dispc_plane_enable(struct dispc_device *dispc, u32 hw_plane, bool enable); | 129 | void dispc_plane_enable(struct dispc_device *dispc, u32 hw_plane, bool enable); |
| 130 | const u32 *dispc_plane_formats(struct dispc_device *dispc, unsigned int *len); | 130 | const u32 *dispc_plane_formats(struct dispc_device *dispc, unsigned int *len); |
| 131 | 131 | ||
| 132 | int dispc_init(struct tidss_device *tidss); | 132 | int dispc_init(struct tidss_device *tidss); |
| @@ -113,7 +113,6 @@ static void tidss_plane_atomic_update(struct drm_plane *plane, · 112 unmodified lines | |||
| 113 | struct drm_plane_state *new_state = drm_atomic_get_new_plane_state(state, | 113 | struct drm_plane_state *new_state = drm_atomic_get_new_plane_state(state, |
| 114 | plane); | 114 | plane); |
| 115 | u32 hw_videoport; | 115 | u32 hw_videoport; |
| 116 | int ret; | ||
| 117 | 116 | ||
| 118 | dev_dbg(ddev->dev, "%s\n", __func__); | 117 | dev_dbg(ddev->dev, "%s\n", __func__); |
| 119 | 118 | ||
| @@ -124,15 +123,17 @@ static void tidss_plane_atomic_update(struct drm_plane *plane, · 4 unmodified lines | |||
| 124 | 123 | ||
| 125 | hw_videoport = to_tidss_crtc(new_state->crtc)->hw_videoport; | 124 | hw_videoport = to_tidss_crtc(new_state->crtc)->hw_videoport; |
| 126 | 125 | ||
| 127 | ret = dispc_plane_setup(tidss->dispc, tplane->hw_plane_id, | 126 | dispc_plane_setup(tidss->dispc, tplane->hw_plane_id, new_state, hw_videoport); |
| 128 | new_state, hw_videoport); | 127 | } |
| 129 | 128 | ||
| 130 | if (ret) { | 129 | static void tidss_plane_atomic_enable(struct drm_plane *plane, |
| 131 | dev_err(plane->dev->dev, "%s: Failed to setup plane %d\n", | 130 | struct drm_atomic_state *state) |
| 132 | __func__, tplane->hw_plane_id); | 131 | { |
| 133 | dispc_plane_enable(tidss->dispc, tplane->hw_plane_id, false); | 132 | struct drm_device *ddev = plane->dev; |
| 134 | return; | 133 | struct tidss_device *tidss = to_tidss(ddev); |
| 135 | } | 134 | struct tidss_plane *tplane = to_tidss_plane(plane); |
| 135 | |||
| 136 | dev_dbg(ddev->dev, "%s\n", __func__); | ||
| 136 | 137 | ||
| 137 | dispc_plane_enable(tidss->dispc, tplane->hw_plane_id, true); | 138 | dispc_plane_enable(tidss->dispc, tplane->hw_plane_id, true); |
| 138 | } | 139 | } |
| @@ -160,6 +161,7 @@ static void drm_plane_destroy(struct drm_plane *plane) · 21 unmodified lines | |||
| 160 | static const struct drm_plane_helper_funcs tidss_plane_helper_funcs = { | 161 | static const struct drm_plane_helper_funcs tidss_plane_helper_funcs = { |
| 161 | .atomic_check = tidss_plane_atomic_check, | 162 | .atomic_check = tidss_plane_atomic_check, |
| 162 | .atomic_update = tidss_plane_atomic_update, | 163 | .atomic_update = tidss_plane_atomic_update, |
| 164 | .atomic_enable = tidss_plane_atomic_enable, | ||
| 163 | .atomic_disable = tidss_plane_atomic_disable, | 165 | .atomic_disable = tidss_plane_atomic_disable, |
| 164 | }; | 166 | }; |
| 165 | 167 | ||
| @@ -606,16 +606,12 @@ static const struct drm_mode_config_funcs simpledrm_mode_config_funcs = { · 605 unmodified lines | |||
| 606 | */ | 606 | */ |
| 607 | 607 | ||
| 608 | static struct drm_display_mode simpledrm_mode(unsigned int width, | 608 | static struct drm_display_mode simpledrm_mode(unsigned int width, |
| 609 | unsigned int height) | 609 | unsigned int height, |
| 610 | unsigned int width_mm, | ||
| 611 | unsigned int height_mm) | ||
| 610 | { | 612 | { |
| 611 | /* | ||
| 612 | * Assume a monitor resolution of 96 dpi to | ||
| 613 | * get a somewhat reasonable screen size. | ||
| 614 | */ | ||
| 615 | const struct drm_display_mode mode = { | 613 | const struct drm_display_mode mode = { |
| 616 | DRM_MODE_INIT(60, width, height, | 614 | DRM_MODE_INIT(60, width, height, width_mm, height_mm) |
| 617 | DRM_MODE_RES_MM(width, 96ul), | ||
| 618 | DRM_MODE_RES_MM(height, 96ul)) | ||
| 619 | }; | 615 | }; |
| 620 | 616 | ||
| 621 | return mode; | 617 | return mode; |
| @@ -629,6 +625,8 @@ static struct simpledrm_device *simpledrm_device_create(struct drm_driver *drv, · 7 unmodified lines | |||
| 629 | struct simpledrm_device *sdev; | 625 | struct simpledrm_device *sdev; |
| 630 | struct drm_device *dev; | 626 | struct drm_device *dev; |
| 631 | int width, height, stride; | 627 | int width, height, stride; |
| 628 | int width_mm = 0, height_mm = 0; | ||
| 629 | struct device_node *panel_node; | ||
| 632 | const struct drm_format_info *format; | 630 | const struct drm_format_info *format; |
| 633 | struct resource *res, *mem = NULL; | 631 | struct resource *res, *mem = NULL; |
| 634 | struct drm_plane *primary_plane; | 632 | struct drm_plane *primary_plane; |
| @@ -685,6 +683,12 @@ static struct simpledrm_device *simpledrm_device_create(struct drm_driver *drv, · 50 unmodified lines | |||
| 685 | mem = simplefb_get_memory_of(dev, of_node); | 683 | mem = simplefb_get_memory_of(dev, of_node); |
| 686 | if (IS_ERR(mem)) | 684 | if (IS_ERR(mem)) |
| 687 | return ERR_CAST(mem); | 685 | return ERR_CAST(mem); |
| 686 | panel_node = of_parse_phandle(of_node, "panel", 0); | ||
| 687 | if (panel_node) { | ||
| 688 | simplefb_read_u32_of(dev, panel_node, "width-mm", &width_mm); | ||
| 689 | simplefb_read_u32_of(dev, panel_node, "height-mm", &height_mm); | ||
| 690 | of_node_put(panel_node); | ||
| 691 | } | ||
| 688 | } else { | 692 | } else { |
| 689 | drm_err(dev, "no simplefb configuration found\n"); | 693 | drm_err(dev, "no simplefb configuration found\n"); |
| 690 | return ERR_PTR(-ENODEV); | 694 | return ERR_PTR(-ENODEV); |
| @@ -695,7 +699,16 @@ static struct simpledrm_device *simpledrm_device_create(struct drm_driver *drv, · 4 unmodified lines | |||
| 695 | return ERR_PTR(-EINVAL); | 699 | return ERR_PTR(-EINVAL); |
| 696 | } | 700 | } |
| 697 | 701 | ||
| 698 | sdev->mode = simpledrm_mode(width, height); | 702 | /* |
| 703 | * Assume a monitor resolution of 96 dpi if physical dimensions | ||
| 704 | * are not specified to get a somewhat reasonable screen size. | ||
| 705 | */ | ||
| 706 | if (!width_mm) | ||
| 707 | width_mm = DRM_MODE_RES_MM(width, 96ul); | ||
| 708 | if (!height_mm) | ||
| 709 | height_mm = DRM_MODE_RES_MM(height, 96ul); | ||
| 710 | |||
| 711 | sdev->mode = simpledrm_mode(width, height, width_mm, height_mm); | ||
| 699 | sdev->format = format; | 712 | sdev->format = format; |
| 700 | sdev->pitch = stride; | 713 | sdev->pitch = stride; |
| 701 | 714 | ||
| @@ -120,8 +120,7 @@ static int ttm_bo_handle_move_mem(struct ttm_buffer_object *bo, · 119 unmodified lines | |||
| 120 | bool old_use_tt, new_use_tt; | 120 | bool old_use_tt, new_use_tt; |
| 121 | int ret; | 121 | int ret; |
| 122 | 122 | ||
| 123 | old_use_tt = bo->resource && | 123 | old_use_tt = !bo->resource || ttm_manager_type(bdev, bo->resource->mem_type)->use_tt; |
| 124 | ttm_manager_type(bdev, bo->resource->mem_type)->use_tt; | ||
| 125 | new_use_tt = ttm_manager_type(bdev, mem->mem_type)->use_tt; | 124 | new_use_tt = ttm_manager_type(bdev, mem->mem_type)->use_tt; |
| 126 | 125 | ||
| 127 | ttm_bo_unmap_virtual(bo); | 126 | ttm_bo_unmap_virtual(bo); |
| @@ -894,14 +893,18 @@ int ttm_bo_validate(struct ttm_buffer_object *bo, · 766 unmodified lines | |||
| 894 | if (!placement->num_placement && !placement->num_busy_placement) | 893 | if (!placement->num_placement && !placement->num_busy_placement) |
| 895 | return ttm_bo_pipeline_gutting(bo); | 894 | return ttm_bo_pipeline_gutting(bo); |
| 896 | 895 | ||
| 897 | /* | 896 | /* Check whether we need to move buffer. */ |
| 898 | * Check whether we need to move buffer. | 897 | if (bo->resource && ttm_resource_compat(bo->resource, placement)) |
| 899 | */ | 898 | return 0; |
| 900 | if (!bo->resource || !ttm_resource_compat(bo->resource, placement)) { | 899 | |
| 901 | ret = ttm_bo_move_buffer(bo, placement, ctx); | 900 | /* Moving of pinned BOs is forbidden */ |
| 902 | if (ret) | 901 | if (bo->pin_count) |
| 903 | return ret; | 902 | return -EINVAL; |
| 904 | } | 903 | |
| 904 | ret = ttm_bo_move_buffer(bo, placement, ctx); | ||
| 905 | if (ret) | ||
| 906 | return ret; | ||
| 907 | |||
| 905 | /* | 908 | /* |
| 906 | * We might need to add a TTM. | 909 | * We might need to add a TTM. |
| 907 | */ | 910 | */ |
| @@ -953,7 +956,6 @@ int ttm_bo_init_reserved(struct ttm_device *bdev, struct ttm_buffer_object *bo, · 45 unmodified lines | |||
| 953 | struct sg_table *sg, struct dma_resv *resv, | 956 | struct sg_table *sg, struct dma_resv *resv, |
| 954 | void (*destroy) (struct ttm_buffer_object *)) | 957 | void (*destroy) (struct ttm_buffer_object *)) |
| 955 | { | 958 | { |
| 956 | static const struct ttm_place sys_mem = { .mem_type = TTM_PL_SYSTEM }; | ||
| 957 | int ret; | 959 | int ret; |
| 958 | 960 | ||
| 959 | kref_init(&bo->kref); | 961 | kref_init(&bo->kref); |
| @@ -970,12 +972,6 @@ int ttm_bo_init_reserved(struct ttm_device *bdev, struct ttm_buffer_object *bo, · 10 unmodified lines | |||
| 970 | bo->base.resv = &bo->base._resv; | 972 | bo->base.resv = &bo->base._resv; |
| 971 | atomic_inc(&ttm_glob.bo_count); | 973 | atomic_inc(&ttm_glob.bo_count); |
| 972 | 974 | ||
| 973 | ret = ttm_resource_alloc(bo, &sys_mem, &bo->resource); | ||
| 974 | if (unlikely(ret)) { | ||
| 975 | ttm_bo_put(bo); | ||
| 976 | return ret; | ||
| 977 | } | ||
| 978 | |||
| 979 | /* | 975 | /* |
| 980 | * For ttm_bo_type_device buffers, allocate | 976 | * For ttm_bo_type_device buffers, allocate |
| 981 | * address space from the device. | 977 | * address space from the device. |
| @@ -157,8 +157,8 @@ int ttm_bo_move_memcpy(struct ttm_buffer_object *bo, · 156 unmodified lines | |||
| 157 | bool clear; | 157 | bool clear; |
| 158 | int ret = 0; | 158 | int ret = 0; |
| 159 | 159 | ||
| 160 | if (!src_mem) | 160 | if (WARN_ON(!src_mem)) |
| 161 | return 0; | 161 | return -EINVAL; |
| 162 | 162 | ||
| 163 | src_man = ttm_manager_type(bdev, src_mem->mem_type); | 163 | src_man = ttm_manager_type(bdev, src_mem->mem_type); |
| 164 | if (ttm && ((ttm->page_flags & TTM_TT_FLAG_SWAPPED) || | 164 | if (ttm && ((ttm->page_flags & TTM_TT_FLAG_SWAPPED) || |
| @@ -704,30 +704,23 @@ EXPORT_SYMBOL(ttm_bo_move_sync_cleanup); · 539 unmodified lines | |||
| 704 | */ | 704 | */ |
| 705 | int ttm_bo_pipeline_gutting(struct ttm_buffer_object *bo) | 705 | int ttm_bo_pipeline_gutting(struct ttm_buffer_object *bo) |
| 706 | { | 706 | { |
| 707 | static const struct ttm_place sys_mem = { .mem_type = TTM_PL_SYSTEM }; | ||
| 708 | struct ttm_buffer_object *ghost; | 707 | struct ttm_buffer_object *ghost; |
| 709 | struct ttm_resource *sys_res; | ||
| 710 | struct ttm_tt *ttm; | 708 | struct ttm_tt *ttm; |
| 711 | int ret; | 709 | int ret; |
| 712 | 710 | ||
| 713 | ret = ttm_resource_alloc(bo, &sys_mem, &sys_res); | ||
| 714 | if (ret) | ||
| 715 | return ret; | ||
| 716 | |||
| 717 | /* If already idle, no need for ghost object dance. */ | 711 | /* If already idle, no need for ghost object dance. */ |
| 718 | if (dma_resv_test_signaled(bo->base.resv, DMA_RESV_USAGE_BOOKKEEP)) { | 712 | if (dma_resv_test_signaled(bo->base.resv, DMA_RESV_USAGE_BOOKKEEP)) { |
| 719 | if (!bo->ttm) { | 713 | if (!bo->ttm) { |
| 720 | /* See comment below about clearing. */ | 714 | /* See comment below about clearing. */ |
| 721 | ret = ttm_tt_create(bo, true); | 715 | ret = ttm_tt_create(bo, true); |
| 722 | if (ret) | 716 | if (ret) |
| 723 | goto error_free_sys_mem; | 717 | return ret; |
| 724 | } else { | 718 | } else { |
| 725 | ttm_tt_unpopulate(bo->bdev, bo->ttm); | 719 | ttm_tt_unpopulate(bo->bdev, bo->ttm); |
| 726 | if (bo->type == ttm_bo_type_device) | 720 | if (bo->type == ttm_bo_type_device) |
| 727 | ttm_tt_mark_for_clear(bo->ttm); | 721 | ttm_tt_mark_for_clear(bo->ttm); |
| 728 | } | 722 | } |
| 729 | ttm_resource_free(bo, &bo->resource); | 723 | ttm_resource_free(bo, &bo->resource); |
| 730 | ttm_bo_assign_mem(bo, sys_res); | ||
| 731 | return 0; | 724 | return 0; |
| 732 | } | 725 | } |
| 733 | 726 | ||
| @@ -744,7 +737,7 @@ int ttm_bo_pipeline_gutting(struct ttm_buffer_object *bo) · 10 unmodified lines | |||
| 744 | ret = ttm_tt_create(bo, true); | 737 | ret = ttm_tt_create(bo, true); |
| 745 | swap(bo->ttm, ttm); | 738 | swap(bo->ttm, ttm); |
| 746 | if (ret) | 739 | if (ret) |
| 747 | goto error_free_sys_mem; | 740 | return ret; |
| 748 | 741 | ||
| 749 | ret = ttm_buffer_object_transfer(bo, &ghost); | 742 | ret = ttm_buffer_object_transfer(bo, &ghost); |
| 750 | if (ret) | 743 | if (ret) |
| @@ -760,13 +753,9 @@ int ttm_bo_pipeline_gutting(struct ttm_buffer_object *bo) · 9 unmodified lines | |||
| 760 | dma_resv_unlock(&ghost->base._resv); | 753 | dma_resv_unlock(&ghost->base._resv); |
| 761 | ttm_bo_put(ghost); | 754 | ttm_bo_put(ghost); |
| 762 | bo->ttm = ttm; | 755 | bo->ttm = ttm; |
| 763 | ttm_bo_assign_mem(bo, sys_res); | ||
| 764 | return 0; | 756 | return 0; |
| 765 | 757 | ||
| 766 | error_destroy_tt: | 758 | error_destroy_tt: |
| 767 | ttm_tt_destroy(bo->bdev, ttm); | 759 | ttm_tt_destroy(bo->bdev, ttm); |
| 768 | |||
| 769 | error_free_sys_mem: | ||
| 770 | ttm_resource_free(bo, &sys_res); | ||
| 771 | return ret; | 760 | return ret; |
| 772 | } | 761 | } |
| @@ -361,7 +361,6 @@ bool ttm_resource_compat(struct ttm_resource *res, · 360 unmodified lines | |||
| 361 | 361 | ||
| 362 | return false; | 362 | return false; |
| 363 | } | 363 | } |
| 364 | EXPORT_SYMBOL(ttm_resource_compat); | ||
| 365 | 364 | ||
| 366 | void ttm_resource_set_bo(struct ttm_resource *res, | 365 | void ttm_resource_set_bo(struct ttm_resource *res, |
| 367 | struct ttm_buffer_object *bo) | 366 | struct ttm_buffer_object *bo) |
| @@ -396,20 +396,6 @@ v3d_wait_bo_ioctl(struct drm_device *dev, void *data, · 395 unmodified lines | |||
| 396 | return ret; | 396 | return ret; |
| 397 | } | 397 | } |
| 398 | 398 | ||
| 399 | static int | ||
| 400 | v3d_job_add_deps(struct drm_file *file_priv, struct v3d_job *job, | ||
| 401 | u32 in_sync, u32 point) | ||
| 402 | { | ||
| 403 | struct dma_fence *in_fence = NULL; | ||
| 404 | int ret; | ||
| 405 | |||
| 406 | ret = drm_syncobj_find_fence(file_priv, in_sync, point, 0, &in_fence); | ||
| 407 | if (ret == -EINVAL) | ||
| 408 | return ret; | ||
| 409 | |||
| 410 | return drm_sched_job_add_dependency(&job->base, in_fence); | ||
| 411 | } | ||
| 412 | |||
| 413 | static int | 399 | static int |
| 414 | v3d_job_init(struct v3d_dev *v3d, struct drm_file *file_priv, | 400 | v3d_job_init(struct v3d_dev *v3d, struct drm_file *file_priv, |
| 415 | void **container, size_t size, void (*free)(struct kref *ref), | 401 | void **container, size_t size, void (*free)(struct kref *ref), |
| @@ -447,14 +433,18 @@ v3d_job_init(struct v3d_dev *v3d, struct drm_file *file_priv, · 31 unmodified lines | |||
| 447 | DRM_DEBUG("Failed to copy wait dep handle.\n"); | 433 | DRM_DEBUG("Failed to copy wait dep handle.\n"); |
| 448 | goto fail_deps; | 434 | goto fail_deps; |
| 449 | } | 435 | } |
| 450 | ret = v3d_job_add_deps(file_priv, job, in.handle, 0); | 436 | ret = drm_sched_job_add_syncobj_dependency(&job->base, file_priv, in.handle, 0); |
| 451 | if (ret) | 437 | |
| 438 | // TODO: Investigate why this was filtered out for the IOCTL. | ||
| 439 | if (ret && ret != -ENOENT) | ||
| 452 | goto fail_deps; | 440 | goto fail_deps; |
| 453 | } | 441 | } |
| 454 | } | 442 | } |
| 455 | } else { | 443 | } else { |
| 456 | ret = v3d_job_add_deps(file_priv, job, in_sync, 0); | 444 | ret = drm_sched_job_add_syncobj_dependency(&job->base, file_priv, in_sync, 0); |
| 457 | if (ret) | 445 | |
| 446 | // TODO: Investigate why this was filtered out for the IOCTL. | ||
| 447 | if (ret && ret != -ENOENT) | ||
| 458 | goto fail_deps; | 448 | goto fail_deps; |
| 459 | } | 449 | } |
| 460 | 450 | ||
| @@ -690,7 +690,7 @@ struct vc4_exec_info { · 689 unmodified lines | |||
| 690 | /* This is the array of BOs that were looked up at the start of exec. | 690 | /* This is the array of BOs that were looked up at the start of exec. |
| 691 | * Command validation will use indices into this array. | 691 | * Command validation will use indices into this array. |
| 692 | */ | 692 | */ |
| 693 | struct drm_gem_dma_object **bo; | 693 | struct drm_gem_object **bo; |
| 694 | uint32_t bo_count; | 694 | uint32_t bo_count; |
| 695 | 695 | ||
| 696 | /* List of BOs that are being written by the RCL. Other than | 696 | /* List of BOs that are being written by the RCL. Other than |
| @@ -199,7 +199,7 @@ vc4_save_hang_state(struct drm_device *dev) · 198 unmodified lines | |||
| 199 | continue; | 199 | continue; |
| 200 | 200 | ||
| 201 | for (j = 0; j < exec[i]->bo_count; j++) { | 201 | for (j = 0; j < exec[i]->bo_count; j++) { |
| 202 | bo = to_vc4_bo(&exec[i]->bo[j]->base); | 202 | bo = to_vc4_bo(exec[i]->bo[j]); |
| 203 | 203 | ||
| 204 | /* Retain BOs just in case they were marked purgeable. | 204 | /* Retain BOs just in case they were marked purgeable. |
| 205 | * This prevents the BO from being purged before | 205 | * This prevents the BO from being purged before |
| @@ -207,8 +207,8 @@ vc4_save_hang_state(struct drm_device *dev) · 1 unmodified line | |||
| 207 | */ | 207 | */ |
| 208 | WARN_ON(!refcount_read(&bo->usecnt)); | 208 | WARN_ON(!refcount_read(&bo->usecnt)); |
| 209 | refcount_inc(&bo->usecnt); | 209 | refcount_inc(&bo->usecnt); |
| 210 | drm_gem_object_get(&exec[i]->bo[j]->base); | 210 | drm_gem_object_get(exec[i]->bo[j]); |
| 211 | kernel_state->bo[k++] = &exec[i]->bo[j]->base; | 211 | kernel_state->bo[k++] = exec[i]->bo[j]; |
| 212 | } | 212 | } |
| 213 | 213 | ||
| 214 | list_for_each_entry(bo, &exec[i]->unref_list, unref_head) { | 214 | list_for_each_entry(bo, &exec[i]->unref_list, unref_head) { |
| @@ -558,7 +558,7 @@ vc4_update_bo_seqnos(struct vc4_exec_info *exec, uint64_t seqno) · 343 unmodified lines | |||
| 558 | unsigned i; | 558 | unsigned i; |
| 559 | 559 | ||
| 560 | for (i = 0; i < exec->bo_count; i++) { | 560 | for (i = 0; i < exec->bo_count; i++) { |
| 561 | bo = to_vc4_bo(&exec->bo[i]->base); | 561 | bo = to_vc4_bo(exec->bo[i]); |
| 562 | bo->seqno = seqno; | 562 | bo->seqno = seqno; |
| 563 | 563 | ||
| 564 | dma_resv_add_fence(bo->base.base.resv, exec->fence, | 564 | dma_resv_add_fence(bo->base.base.resv, exec->fence, |
| @@ -585,11 +585,8 @@ vc4_unlock_bo_reservations(struct drm_device *dev, · 20 unmodified lines | |||
| 585 | { | 585 | { |
| 586 | int i; | 586 | int i; |
| 587 | 587 | ||
| 588 | for (i = 0; i < exec->bo_count; i++) { | 588 | for (i = 0; i < exec->bo_count; i++) |
| 589 | struct drm_gem_object *bo = &exec->bo[i]->base; | 589 | dma_resv_unlock(exec->bo[i]->resv); |
| 590 | |||
| 591 | dma_resv_unlock(bo->resv); | ||
| 592 | } | ||
| 593 | 590 | ||
| 594 | ww_acquire_fini(acquire_ctx); | 591 | ww_acquire_fini(acquire_ctx); |
| 595 | } | 592 | } |
| @@ -614,7 +611,7 @@ vc4_lock_bo_reservations(struct drm_device *dev, · 18 unmodified lines | |||
| 614 | 611 | ||
| 615 | retry: | 612 | retry: |
| 616 | if (contended_lock != -1) { | 613 | if (contended_lock != -1) { |
| 617 | bo = &exec->bo[contended_lock]->base; | 614 | bo = exec->bo[contended_lock]; |
| 618 | ret = dma_resv_lock_slow_interruptible(bo->resv, acquire_ctx); | 615 | ret = dma_resv_lock_slow_interruptible(bo->resv, acquire_ctx); |
| 619 | if (ret) { | 616 | if (ret) { |
| 620 | ww_acquire_done(acquire_ctx); | 617 | ww_acquire_done(acquire_ctx); |
| @@ -626,19 +623,19 @@ retry: · 5 unmodified lines | |||
| 626 | if (i == contended_lock) | 623 | if (i == contended_lock) |
| 627 | continue; | 624 | continue; |
| 628 | 625 | ||
| 629 | bo = &exec->bo[i]->base; | 626 | bo = exec->bo[i]; |
| 630 | 627 | ||
| 631 | ret = dma_resv_lock_interruptible(bo->resv, acquire_ctx); | 628 | ret = dma_resv_lock_interruptible(bo->resv, acquire_ctx); |
| 632 | if (ret) { | 629 | if (ret) { |
| 633 | int j; | 630 | int j; |
| 634 | 631 | ||
| 635 | for (j = 0; j < i; j++) { | 632 | for (j = 0; j < i; j++) { |
| 636 | bo = &exec->bo[j]->base; | 633 | bo = exec->bo[j]; |
| 637 | dma_resv_unlock(bo->resv); | 634 | dma_resv_unlock(bo->resv); |
| 638 | } | 635 | } |
| 639 | 636 | ||
| 640 | if (contended_lock != -1 && contended_lock >= i) { | 637 | if (contended_lock != -1 && contended_lock >= i) { |
| 641 | bo = &exec->bo[contended_lock]->base; | 638 | bo = exec->bo[contended_lock]; |
| 642 | 639 | ||
| 643 | dma_resv_unlock(bo->resv); | 640 | dma_resv_unlock(bo->resv); |
| 644 | } | 641 | } |
| @@ -659,7 +656,7 @@ retry: · 14 unmodified lines | |||
| 659 | * before we commit the CL to the hardware. | 656 | * before we commit the CL to the hardware. |
| 660 | */ | 657 | */ |
| 661 | for (i = 0; i < exec->bo_count; i++) { | 658 | for (i = 0; i < exec->bo_count; i++) { |
| 662 | bo = &exec->bo[i]->base; | 659 | bo = exec->bo[i]; |
| 663 | 660 | ||
| 664 | ret = dma_resv_reserve_fences(bo->resv, 1); | 661 | ret = dma_resv_reserve_fences(bo->resv, 1); |
| 665 | if (ret) { | 662 | if (ret) { |
| @@ -749,7 +746,6 @@ vc4_cl_lookup_bos(struct drm_device *dev, · 83 unmodified lines | |||
| 749 | struct vc4_exec_info *exec) | 746 | struct vc4_exec_info *exec) |
| 750 | { | 747 | { |
| 751 | struct drm_vc4_submit_cl *args = exec->args; | 748 | struct drm_vc4_submit_cl *args = exec->args; |
| 752 | uint32_t *handles; | ||
| 753 | int ret = 0; | 749 | int ret = 0; |
| 754 | int i; | 750 | int i; |
| 755 | 751 | ||
| @@ -763,54 +759,18 @@ vc4_cl_lookup_bos(struct drm_device *dev, · 7 unmodified lines | |||
| 763 | return -EINVAL; | 759 | return -EINVAL; |
| 764 | } | 760 | } |
| 765 | 761 | ||
| 766 | exec->bo = kvmalloc_array(exec->bo_count, | 762 | ret = drm_gem_objects_lookup(file_priv, u64_to_user_ptr(args->bo_handles), |
| 767 | sizeof(struct drm_gem_dma_object *), | 763 | exec->bo_count, &exec->bo); |
| 768 | GFP_KERNEL | __GFP_ZERO); | ||
| 769 | if (!exec->bo) { | ||
| 770 | DRM_ERROR("Failed to allocate validated BO pointers\n"); | ||
| 771 | return -ENOMEM; | ||
| 772 | } | ||
| 773 | |||
| 774 | handles = kvmalloc_array(exec->bo_count, sizeof(uint32_t), GFP_KERNEL); | ||
| 775 | if (!handles) { | ||
| 776 | ret = -ENOMEM; | ||
| 777 | DRM_ERROR("Failed to allocate incoming GEM handles\n"); | ||
| 778 | goto fail; | ||
| 779 | } | ||
| 780 | |||
| 781 | if (copy_from_user(handles, u64_to_user_ptr(args->bo_handles), | ||
| 782 | exec->bo_count * sizeof(uint32_t))) { | ||
| 783 | ret = -EFAULT; | ||
| 784 | DRM_ERROR("Failed to copy in GEM handles\n"); | ||
| 785 | goto fail; | ||
| 786 | } | ||
| 787 | |||
| 788 | spin_lock(&file_priv->table_lock); | ||
| 789 | for (i = 0; i < exec->bo_count; i++) { | ||
| 790 | struct drm_gem_object *bo = idr_find(&file_priv->object_idr, | ||
| 791 | handles[i]); | ||
| 792 | if (!bo) { | ||
| 793 | DRM_DEBUG("Failed to look up GEM BO %d: %d\n", | ||
| 794 | i, handles[i]); | ||
| 795 | ret = -EINVAL; | ||
| 796 | break; | ||
| 797 | } | ||
| 798 | |||
| 799 | drm_gem_object_get(bo); | ||
| 800 | exec->bo[i] = (struct drm_gem_dma_object *)bo; | ||
| 801 | } | ||
| 802 | spin_unlock(&file_priv->table_lock); | ||
| 803 | 764 | ||
| 804 | if (ret) | 765 | if (ret) |
| 805 | goto fail_put_bo; | 766 | goto fail_put_bo; |
| 806 | 767 | ||
| 807 | for (i = 0; i < exec->bo_count; i++) { | 768 | for (i = 0; i < exec->bo_count; i++) { |
| 808 | ret = vc4_bo_inc_usecnt(to_vc4_bo(&exec->bo[i]->base)); | 769 | ret = vc4_bo_inc_usecnt(to_vc4_bo(exec->bo[i])); |
| 809 | if (ret) | 770 | if (ret) |
| 810 | goto fail_dec_usecnt; | 771 | goto fail_dec_usecnt; |
| 811 | } | 772 | } |
| 812 | 773 | ||
| 813 | kvfree(handles); | ||
| 814 | return 0; | 774 | return 0; |
| 815 | 775 | ||
| 816 | fail_dec_usecnt: | 776 | fail_dec_usecnt: |
| @@ -823,15 +783,13 @@ fail_dec_usecnt: · 6 unmodified lines | |||
| 823 | * step. | 783 | * step. |
| 824 | */ | 784 | */ |
| 825 | for (i-- ; i >= 0; i--) | 785 | for (i-- ; i >= 0; i--) |
| 826 | vc4_bo_dec_usecnt(to_vc4_bo(&exec->bo[i]->base)); | 786 | vc4_bo_dec_usecnt(to_vc4_bo(exec->bo[i])); |
| 827 | 787 | ||
| 828 | fail_put_bo: | 788 | fail_put_bo: |
| 829 | /* Release any reference to acquired objects. */ | 789 | /* Release any reference to acquired objects. */ |
| 830 | for (i = 0; i < exec->bo_count && exec->bo[i]; i++) | 790 | for (i = 0; i < exec->bo_count && exec->bo[i]; i++) |
| 831 | drm_gem_object_put(&exec->bo[i]->base); | 791 | drm_gem_object_put(exec->bo[i]); |
| 832 | 792 | ||
| 833 | fail: | ||
| 834 | kvfree(handles); | ||
| 835 | kvfree(exec->bo); | 793 | kvfree(exec->bo); |
| 836 | exec->bo = NULL; | 794 | exec->bo = NULL; |
| 837 | return ret; | 795 | return ret; |
| @@ -974,10 +932,10 @@ vc4_complete_exec(struct drm_device *dev, struct vc4_exec_info *exec) · 136 unmodified lines | |||
| 974 | 932 | ||
| 975 | if (exec->bo) { | 933 | if (exec->bo) { |
| 976 | for (i = 0; i < exec->bo_count; i++) { | 934 | for (i = 0; i < exec->bo_count; i++) { |
| 977 | struct vc4_bo *bo = to_vc4_bo(&exec->bo[i]->base); | 935 | struct vc4_bo *bo = to_vc4_bo(exec->bo[i]); |
| 978 | 936 | ||
| 979 | vc4_bo_dec_usecnt(bo); | 937 | vc4_bo_dec_usecnt(bo); |
| 980 | drm_gem_object_put(&exec->bo[i]->base); | 938 | drm_gem_object_put(exec->bo[i]); |
| 981 | } | 939 | } |
| 982 | kvfree(exec->bo); | 940 | kvfree(exec->bo); |
| 983 | } | 941 | } |
| @@ -1466,6 +1466,12 @@ static void vc4_hdmi_encoder_pre_crtc_configure(struct drm_encoder *encoder, · 1465 unmodified lines | |||
| 1466 | if (!drm_dev_enter(drm, &idx)) | 1466 | if (!drm_dev_enter(drm, &idx)) |
| 1467 | goto out; | 1467 | goto out; |
| 1468 | 1468 | ||
| 1469 | ret = pm_runtime_resume_and_get(&vc4_hdmi->pdev->dev); | ||
| 1470 | if (ret < 0) { | ||
| 1471 | DRM_ERROR("Failed to retain power domain: %d\n", ret); | ||
| 1472 | goto err_dev_exit; | ||
| 1473 | } | ||
| 1474 | |||
| 1469 | /* | 1475 | /* |
| 1470 | * As stated in RPi's vc4 firmware "HDMI state machine (HSM) clock must | 1476 | * As stated in RPi's vc4 firmware "HDMI state machine (HSM) clock must |
| 1471 | * be faster than pixel clock, infinitesimally faster, tested in | 1477 | * be faster than pixel clock, infinitesimally faster, tested in |
| @@ -1482,17 +1488,13 @@ static void vc4_hdmi_encoder_pre_crtc_configure(struct drm_encoder *encoder, · 10 unmodified lines | |||
| 1482 | * Additionally, the AXI clock needs to be at least 25% of | 1488 | * Additionally, the AXI clock needs to be at least 25% of |
| 1483 | * pixel clock, but HSM ends up being the limiting factor. | 1489 | * pixel clock, but HSM ends up being the limiting factor. |
| 1484 | */ | 1490 | */ |
| 1485 | hsm_rate = max_t(unsigned long, 120000000, (tmds_char_rate / 100) * 101); | 1491 | hsm_rate = max_t(unsigned long, |
| 1492 | HSM_MIN_CLOCK_FREQ, | ||
| 1493 | (tmds_char_rate / 100) * 101); | ||
| 1486 | ret = clk_set_min_rate(vc4_hdmi->hsm_clock, hsm_rate); | 1494 | ret = clk_set_min_rate(vc4_hdmi->hsm_clock, hsm_rate); |
| 1487 | if (ret) { | 1495 | if (ret) { |
| 1488 | DRM_ERROR("Failed to set HSM clock rate: %d\n", ret); | 1496 | DRM_ERROR("Failed to set HSM clock rate: %d\n", ret); |
| 1489 | goto err_dev_exit; | 1497 | goto err_put_runtime_pm; |
| 1490 | } | ||
| 1491 | |||
| 1492 | ret = pm_runtime_resume_and_get(&vc4_hdmi->pdev->dev); | ||
| 1493 | if (ret < 0) { | ||
| 1494 | DRM_ERROR("Failed to retain power domain: %d\n", ret); | ||
| 1495 | goto err_dev_exit; | ||
| 1496 | } | 1498 | } |
| 1497 | 1499 | ||
| 1498 | ret = clk_set_rate(vc4_hdmi->pixel_clock, tmds_char_rate); | 1500 | ret = clk_set_rate(vc4_hdmi->pixel_clock, tmds_char_rate); |
| @@ -3188,16 +3190,9 @@ static int vc4_hdmi_init_resources(struct drm_device *drm, · 1689 unmodified lines | |||
| 3188 | DRM_ERROR("Failed to get HDMI state machine clock\n"); | 3190 | DRM_ERROR("Failed to get HDMI state machine clock\n"); |
| 3189 | return PTR_ERR(vc4_hdmi->hsm_clock); | 3191 | return PTR_ERR(vc4_hdmi->hsm_clock); |
| 3190 | } | 3192 | } |
| 3191 | |||
| 3192 | vc4_hdmi->audio_clock = vc4_hdmi->hsm_clock; | 3193 | vc4_hdmi->audio_clock = vc4_hdmi->hsm_clock; |
| 3193 | vc4_hdmi->cec_clock = vc4_hdmi->hsm_clock; | 3194 | vc4_hdmi->cec_clock = vc4_hdmi->hsm_clock; |
| 3194 | 3195 | ||
| 3195 | vc4_hdmi->hsm_rpm_clock = devm_clk_get(dev, "hdmi"); | ||
| 3196 | if (IS_ERR(vc4_hdmi->hsm_rpm_clock)) { | ||
| 3197 | DRM_ERROR("Failed to get HDMI state machine clock\n"); | ||
| 3198 | return PTR_ERR(vc4_hdmi->hsm_rpm_clock); | ||
| 3199 | } | ||
| 3200 | |||
| 3201 | return 0; | 3196 | return 0; |
| 3202 | } | 3197 | } |
| 3203 | 3198 | ||
| @@ -3280,12 +3275,6 @@ static int vc5_hdmi_init_resources(struct drm_device *drm, · 76 unmodified lines | |||
| 3280 | return PTR_ERR(vc4_hdmi->hsm_clock); | 3275 | return PTR_ERR(vc4_hdmi->hsm_clock); |
| 3281 | } | 3276 | } |
| 3282 | 3277 | ||
| 3283 | vc4_hdmi->hsm_rpm_clock = devm_clk_get(dev, "hdmi"); | ||
| 3284 | if (IS_ERR(vc4_hdmi->hsm_rpm_clock)) { | ||
| 3285 | DRM_ERROR("Failed to get HDMI state machine clock\n"); | ||
| 3286 | return PTR_ERR(vc4_hdmi->hsm_rpm_clock); | ||
| 3287 | } | ||
| 3288 | |||
| 3289 | vc4_hdmi->pixel_bvb_clock = devm_clk_get(dev, "bvb"); | 3278 | vc4_hdmi->pixel_bvb_clock = devm_clk_get(dev, "bvb"); |
| 3290 | if (IS_ERR(vc4_hdmi->pixel_bvb_clock)) { | 3279 | if (IS_ERR(vc4_hdmi->pixel_bvb_clock)) { |
| 3291 | DRM_ERROR("Failed to get pixel bvb clock\n"); | 3280 | DRM_ERROR("Failed to get pixel bvb clock\n"); |
| @@ -3349,7 +3338,7 @@ static int vc4_hdmi_runtime_suspend(struct device *dev) · 57 unmodified lines | |||
| 3349 | { | 3338 | { |
| 3350 | struct vc4_hdmi *vc4_hdmi = dev_get_drvdata(dev); | 3339 | struct vc4_hdmi *vc4_hdmi = dev_get_drvdata(dev); |
| 3351 | 3340 | ||
| 3352 | clk_disable_unprepare(vc4_hdmi->hsm_rpm_clock); | 3341 | clk_disable_unprepare(vc4_hdmi->hsm_clock); |
| 3353 | 3342 | ||
| 3354 | return 0; | 3343 | return 0; |
| 3355 | } | 3344 | } |
| @@ -3362,16 +3351,7 @@ static int vc4_hdmi_runtime_resume(struct device *dev) · 6 unmodified lines | |||
| 3362 | unsigned long rate; | 3351 | unsigned long rate; |
| 3363 | int ret; | 3352 | int ret; |
| 3364 | 3353 | ||
| 3365 | /* | 3354 | ret = clk_prepare_enable(vc4_hdmi->hsm_clock); |
| 3366 | * The HSM clock is in the HDMI power domain, so we need to set | ||
| 3367 | * its frequency while the power domain is active so that it | ||
| 3368 | * keeps its rate. | ||
| 3369 | */ | ||
| 3370 | ret = clk_set_min_rate(vc4_hdmi->hsm_rpm_clock, HSM_MIN_CLOCK_FREQ); | ||
| 3371 | if (ret) | ||
| 3372 | return ret; | ||
| 3373 | |||
| 3374 | ret = clk_prepare_enable(vc4_hdmi->hsm_rpm_clock); | ||
| 3375 | if (ret) | 3355 | if (ret) |
| 3376 | return ret; | 3356 | return ret; |
| 3377 | 3357 | ||
| @@ -3384,7 +3364,7 @@ static int vc4_hdmi_runtime_resume(struct device *dev) · 6 unmodified lines | |||
| 3384 | * case, it will lead to a silent CPU stall. Let's make sure we | 3364 | * case, it will lead to a silent CPU stall. Let's make sure we |
| 3385 | * prevent such a case. | 3365 | * prevent such a case. |
| 3386 | */ | 3366 | */ |
| 3387 | rate = clk_get_rate(vc4_hdmi->hsm_rpm_clock); | 3367 | rate = clk_get_rate(vc4_hdmi->hsm_clock); |
| 3388 | if (!rate) { | 3368 | if (!rate) { |
| 3389 | ret = -EINVAL; | 3369 | ret = -EINVAL; |
| 3390 | goto err_disable_clk; | 3370 | goto err_disable_clk; |
| @@ -164,7 +164,6 @@ struct vc4_hdmi { · 163 unmodified lines | |||
| 164 | struct clk *cec_clock; | 164 | struct clk *cec_clock; |
| 165 | struct clk *pixel_clock; | 165 | struct clk *pixel_clock; |
| 166 | struct clk *hsm_clock; | 166 | struct clk *hsm_clock; |
| 167 | struct clk *hsm_rpm_clock; | ||
| 168 | struct clk *audio_clock; | 167 | struct clk *audio_clock; |
| 169 | struct clk *pixel_bvb_clock; | 168 | struct clk *pixel_bvb_clock; |
| 170 | 169 | ||
| @@ -117,7 +117,7 @@ vc4_use_bo(struct vc4_exec_info *exec, uint32_t hindex) · 116 unmodified lines | |||
| 117 | hindex, exec->bo_count); | 117 | hindex, exec->bo_count); |
| 118 | return NULL; | 118 | return NULL; |
| 119 | } | 119 | } |
| 120 | obj = exec->bo[hindex]; | 120 | obj = to_drm_gem_dma_obj(exec->bo[hindex]); |
| 121 | bo = to_vc4_bo(&obj->base); | 121 | bo = to_vc4_bo(&obj->base); |
| 122 | 122 | ||
| 123 | if (bo->validated_shader) { | 123 | if (bo->validated_shader) { |
| @@ -810,7 +810,7 @@ validate_gl_shader_rec(struct drm_device *dev, · 686 unmodified lines | |||
| 810 | return -EINVAL; | 810 | return -EINVAL; |
| 811 | } | 811 | } |
| 812 | 812 | ||
| 813 | bo[i] = exec->bo[src_handles[i]]; | 813 | bo[i] = to_drm_gem_dma_obj(exec->bo[src_handles[i]]); |
| 814 | if (!bo[i]) | 814 | if (!bo[i]) |
| 815 | return -EINVAL; | 815 | return -EINVAL; |
| 816 | } | 816 | } |
| @@ -249,4 +249,5 @@ void vgem_fence_close(struct vgem_file *vfile) · 248 unmodified lines | |||
| 249 | { | 249 | { |
| 250 | idr_for_each(&vfile->fence_idr, __vgem_fence_idr_fini, vfile); | 250 | idr_for_each(&vfile->fence_idr, __vgem_fence_idr_fini, vfile); |
| 251 | idr_destroy(&vfile->fence_idr); | 251 | idr_destroy(&vfile->fence_idr); |
| 252 | mutex_destroy(&vfile->fence_mutex); | ||
| 252 | } | 253 | } |
| @@ -11,3 +11,14 @@ config DRM_VIRTIO_GPU · 10 unmodified lines | |||
| 11 | QEMU based VMMs (like KVM or Xen). | 11 | QEMU based VMMs (like KVM or Xen). |
| 12 | 12 | ||
| 13 | If unsure say M. | 13 | If unsure say M. |
| 14 | |||
| 15 | config DRM_VIRTIO_GPU_KMS | ||
| 16 | bool "Virtio GPU driver modesetting support" | ||
| 17 | depends on DRM_VIRTIO_GPU | ||
| 18 | default y | ||
| 19 | help | ||
| 20 | Enable modesetting support for virtio GPU driver. This can be | ||
| 21 | disabled in cases where only "headless" usage of the GPU is | ||
| 22 | required. | ||
| 23 | |||
| 24 | If unsure, say Y. | ||
| @@ -336,6 +336,9 @@ int virtio_gpu_modeset_init(struct virtio_gpu_device *vgdev) · 335 unmodified lines | |||
| 336 | { | 336 | { |
| 337 | int i, ret; | 337 | int i, ret; |
| 338 | 338 | ||
| 339 | if (!vgdev->num_scanouts) | ||
| 340 | return 0; | ||
| 341 | |||
| 339 | ret = drmm_mode_config_init(vgdev->ddev); | 342 | ret = drmm_mode_config_init(vgdev->ddev); |
| 340 | if (ret) | 343 | if (ret) |
| 341 | return ret; | 344 | return ret; |
| @@ -362,6 +365,9 @@ void virtio_gpu_modeset_fini(struct virtio_gpu_device *vgdev) · 20 unmodified lines | |||
| 362 | { | 365 | { |
| 363 | int i; | 366 | int i; |
| 364 | 367 | ||
| 368 | if (!vgdev->num_scanouts) | ||
| 369 | return; | ||
| 370 | |||
| 365 | for (i = 0 ; i < vgdev->num_scanouts; ++i) | 371 | for (i = 0 ; i < vgdev->num_scanouts; ++i) |
| 366 | kfree(vgdev->outputs[i].edid); | 372 | kfree(vgdev->outputs[i].edid); |
| 367 | } | 373 | } |
| @@ -172,6 +172,10 @@ MODULE_AUTHOR("Alon Levy"); · 171 unmodified lines | |||
| 172 | DEFINE_DRM_GEM_FOPS(virtio_gpu_driver_fops); | 172 | DEFINE_DRM_GEM_FOPS(virtio_gpu_driver_fops); |
| 173 | 173 | ||
| 174 | static const struct drm_driver driver = { | 174 | static const struct drm_driver driver = { |
| 175 | /* | ||
| 176 | * If KMS is disabled DRIVER_MODESET and DRIVER_ATOMIC are masked | ||
| 177 | * out via drm_device::driver_features: | ||
| 178 | */ | ||
| 175 | .driver_features = DRIVER_MODESET | DRIVER_GEM | DRIVER_RENDER | DRIVER_ATOMIC, | 179 | .driver_features = DRIVER_MODESET | DRIVER_GEM | DRIVER_RENDER | DRIVER_ATOMIC, |
| 176 | .open = virtio_gpu_driver_open, | 180 | .open = virtio_gpu_driver_open, |
| 177 | .postclose = virtio_gpu_driver_postclose, | 181 | .postclose = virtio_gpu_driver_postclose, |
| @@ -43,11 +43,13 @@ static void virtio_gpu_config_changed_work_func(struct work_struct *work) · 42 unmodified lines | |||
| 43 | virtio_cread_le(vgdev->vdev, struct virtio_gpu_config, | 43 | virtio_cread_le(vgdev->vdev, struct virtio_gpu_config, |
| 44 | events_read, &events_read); | 44 | events_read, &events_read); |
| 45 | if (events_read & VIRTIO_GPU_EVENT_DISPLAY) { | 45 | if (events_read & VIRTIO_GPU_EVENT_DISPLAY) { |
| 46 | if (vgdev->has_edid) | 46 | if (vgdev->num_scanouts) { |
| 47 | virtio_gpu_cmd_get_edids(vgdev); | 47 | if (vgdev->has_edid) |
| 48 | virtio_gpu_cmd_get_display_info(vgdev); | 48 | virtio_gpu_cmd_get_edids(vgdev); |
| 49 | virtio_gpu_notify(vgdev); | 49 | virtio_gpu_cmd_get_display_info(vgdev); |
| 50 | drm_helper_hpd_irq_event(vgdev->ddev); | 50 | virtio_gpu_notify(vgdev); |
| 51 | drm_helper_hpd_irq_event(vgdev->ddev); | ||
| 52 | } | ||
| 51 | events_clear |= VIRTIO_GPU_EVENT_DISPLAY; | 53 | events_clear |= VIRTIO_GPU_EVENT_DISPLAY; |
| 52 | } | 54 | } |
| 53 | virtio_cwrite_le(vgdev->vdev, struct virtio_gpu_config, | 55 | virtio_cwrite_le(vgdev->vdev, struct virtio_gpu_config, |
| @@ -223,12 +225,15 @@ int virtio_gpu_init(struct virtio_device *vdev, struct drm_device *dev) · 169 unmodified lines | |||
| 223 | num_scanouts, &num_scanouts); | 225 | num_scanouts, &num_scanouts); |
| 224 | vgdev->num_scanouts = min_t(uint32_t, num_scanouts, | 226 | vgdev->num_scanouts = min_t(uint32_t, num_scanouts, |
| 225 | VIRTIO_GPU_MAX_SCANOUTS); | 227 | VIRTIO_GPU_MAX_SCANOUTS); |
| 226 | if (!vgdev->num_scanouts) { | 228 | |
| 227 | DRM_ERROR("num_scanouts is zero\n"); | 229 | if (!IS_ENABLED(CONFIG_DRM_VIRTIO_GPU_KMS) || !vgdev->num_scanouts) { |
| 228 | ret = -EINVAL; | 230 | DRM_INFO("KMS disabled\n"); |
| 229 | goto err_scanouts; | 231 | vgdev->num_scanouts = 0; |
| 232 | vgdev->has_edid = false; | ||
| 233 | dev->driver_features &= ~(DRIVER_MODESET | DRIVER_ATOMIC); | ||
| 234 | } else { | ||
| 235 | DRM_INFO("number of scanouts: %d\n", num_scanouts); | ||
| 230 | } | 236 | } |
| 231 | DRM_INFO("number of scanouts: %d\n", num_scanouts); | ||
| 232 | 237 | ||
| 233 | virtio_cread_le(vgdev->vdev, struct virtio_gpu_config, | 238 | virtio_cread_le(vgdev->vdev, struct virtio_gpu_config, |
| 234 | num_capsets, &num_capsets); | 239 | num_capsets, &num_capsets); |
| @@ -244,12 +249,14 @@ int virtio_gpu_init(struct virtio_device *vdev, struct drm_device *dev) · 9 unmodified lines | |||
| 244 | 249 | ||
| 245 | if (num_capsets) | 250 | if (num_capsets) |
| 246 | virtio_gpu_get_capsets(vgdev, num_capsets); | 251 | virtio_gpu_get_capsets(vgdev, num_capsets); |
| 247 | if (vgdev->has_edid) | 252 | if (vgdev->num_scanouts) { |
| 248 | virtio_gpu_cmd_get_edids(vgdev); | 253 | if (vgdev->has_edid) |
| 249 | virtio_gpu_cmd_get_display_info(vgdev); | 254 | virtio_gpu_cmd_get_edids(vgdev); |
| 250 | virtio_gpu_notify(vgdev); | 255 | virtio_gpu_cmd_get_display_info(vgdev); |
| 251 | wait_event_timeout(vgdev->resp_wq, !vgdev->display_info_pending, | 256 | virtio_gpu_notify(vgdev); |
| 252 | 5 * HZ); | 257 | wait_event_timeout(vgdev->resp_wq, !vgdev->display_info_pending, |
| 258 | 5 * HZ); | ||
| 259 | } | ||
| 253 | return 0; | 260 | return 0; |
| 254 | 261 | ||
| 255 | err_scanouts: | 262 | err_scanouts: |
| @@ -923,8 +923,7 @@ void virtio_gpu_cmd_context_create(struct virtio_gpu_device *vgdev, uint32_t id, · 922 unmodified lines | |||
| 923 | cmd_p->hdr.ctx_id = cpu_to_le32(id); | 923 | cmd_p->hdr.ctx_id = cpu_to_le32(id); |
| 924 | cmd_p->nlen = cpu_to_le32(nlen); | 924 | cmd_p->nlen = cpu_to_le32(nlen); |
| 925 | cmd_p->context_init = cpu_to_le32(context_init); | 925 | cmd_p->context_init = cpu_to_le32(context_init); |
| 926 | strncpy(cmd_p->debug_name, name, sizeof(cmd_p->debug_name) - 1); | 926 | strscpy(cmd_p->debug_name, name, sizeof(cmd_p->debug_name)); |
| 927 | cmd_p->debug_name[sizeof(cmd_p->debug_name) - 1] = 0; | ||
| 928 | virtio_gpu_queue_ctrl_buffer(vgdev, vbuf); | 927 | virtio_gpu_queue_ctrl_buffer(vgdev, vbuf); |
| 929 | } | 928 | } |
| 930 | 929 | ||
| @@ -1,7 +1,7 @@ | |||
| 1 | # SPDX-License-Identifier: GPL-2.0 | 1 | # SPDX-License-Identifier: GPL-2.0 |
| 2 | vmwgfx-y := vmwgfx_execbuf.o vmwgfx_gmr.o vmwgfx_kms.o vmwgfx_drv.o \ | 2 | vmwgfx-y := vmwgfx_execbuf.o vmwgfx_gmr.o vmwgfx_kms.o vmwgfx_drv.o \ |
| 3 | vmwgfx_ioctl.o vmwgfx_resource.o vmwgfx_ttm_buffer.o \ | 3 | vmwgfx_ioctl.o vmwgfx_resource.o vmwgfx_ttm_buffer.o \ |
| 4 | vmwgfx_cmd.o vmwgfx_irq.o vmwgfx_ldu.o vmwgfx_ttm_glue.o \ | 4 | vmwgfx_cmd.o vmwgfx_irq.o vmwgfx_ldu.o \ |
| 5 | vmwgfx_overlay.o vmwgfx_gmrid_manager.o vmwgfx_fence.o \ | 5 | vmwgfx_overlay.o vmwgfx_gmrid_manager.o vmwgfx_fence.o \ |
| 6 | vmwgfx_bo.o vmwgfx_scrn.o vmwgfx_context.o \ | 6 | vmwgfx_bo.o vmwgfx_scrn.o vmwgfx_context.o \ |
| 7 | vmwgfx_surface.o vmwgfx_prime.o vmwgfx_mob.o vmwgfx_shader.o \ | 7 | vmwgfx_surface.o vmwgfx_prime.o vmwgfx_mob.o vmwgfx_shader.o \ |
| @@ -1,7 +1,7 @@ | |||
| 1 | // SPDX-License-Identifier: GPL-2.0 OR MIT | 1 | // SPDX-License-Identifier: GPL-2.0 OR MIT |
| 2 | /************************************************************************** | 2 | /************************************************************************** |
| 3 | * | 3 | * |
| 4 | * Copyright © 2011-2018 VMware, Inc., Palo Alto, CA., USA | 4 | * Copyright © 2011-2023 VMware, Inc., Palo Alto, CA., USA |
| 5 | * All Rights Reserved. | 5 | * All Rights Reserved. |
| 6 | * | 6 | * |
| 7 | * Permission is hereby granted, free of charge, to any person obtaining a | 7 | * Permission is hereby granted, free of charge, to any person obtaining a |
| @@ -26,40 +26,31 @@ · 18 unmodified lines | |||
| 26 | * | 26 | * |
| 27 | **************************************************************************/ | 27 | **************************************************************************/ |
| 28 | 28 | ||
| 29 | #include <drm/ttm/ttm_placement.h> | 29 | #include "vmwgfx_bo.h" |
| 30 | |||
| 31 | #include "vmwgfx_drv.h" | 30 | #include "vmwgfx_drv.h" |
| 32 | #include "ttm_object.h" | ||
| 33 | 31 | ||
| 34 | 32 | ||
| 35 | /** | 33 | #include <drm/ttm/ttm_placement.h> |
| 36 | * vmw_buffer_object - Convert a struct ttm_buffer_object to a struct | 34 | |
| 37 | * vmw_buffer_object. | 35 | static void vmw_bo_release(struct vmw_bo *vbo) |
| 38 | * | ||
| 39 | * @bo: Pointer to the TTM buffer object. | ||
| 40 | * Return: Pointer to the struct vmw_buffer_object embedding the | ||
| 41 | * TTM buffer object. | ||
| 42 | */ | ||
| 43 | static struct vmw_buffer_object * | ||
| 44 | vmw_buffer_object(struct ttm_buffer_object *bo) | ||
| 45 | { | 36 | { |
| 46 | return container_of(bo, struct vmw_buffer_object, base); | 37 | vmw_bo_unmap(vbo); |
| 38 | drm_gem_object_release(&vbo->tbo.base); | ||
| 47 | } | 39 | } |
| 48 | 40 | ||
| 49 | /** | 41 | /** |
| 50 | * bo_is_vmw - check if the buffer object is a &vmw_buffer_object | 42 | * vmw_bo_free - vmw_bo destructor |
| 51 | * @bo: ttm buffer object to be checked | ||
| 52 | * | 43 | * |
| 53 | * Uses destroy function associated with the object to determine if this is | 44 | * @bo: Pointer to the embedded struct ttm_buffer_object |
| 54 | * a &vmw_buffer_object. | ||
| 55 | * | ||
| 56 | * Returns: | ||
| 57 | * true if the object is of &vmw_buffer_object type, false if not. | ||
| 58 | */ | 45 | */ |
| 59 | static bool bo_is_vmw(struct ttm_buffer_object *bo) | 46 | static void vmw_bo_free(struct ttm_buffer_object *bo) |
| 60 | { | 47 | { |
| 61 | return bo->destroy == &vmw_bo_bo_free || | 48 | struct vmw_bo *vbo = to_vmw_bo(&bo->base); |
| 62 | bo->destroy == &vmw_gem_destroy; | 49 | |
| 50 | WARN_ON(vbo->dirty); | ||
| 51 | WARN_ON(!RB_EMPTY_ROOT(&vbo->res_tree)); | ||
| 52 | vmw_bo_release(vbo); | ||
| 53 | kfree(vbo); | ||
| 63 | } | 54 | } |
| 64 | 55 | ||
| 65 | /** | 56 | /** |
| @@ -72,13 +63,13 @@ static bool bo_is_vmw(struct ttm_buffer_object *bo) · 6 unmodified lines | |||
| 72 | * Return: Zero on success, Negative error code on failure. In particular | 63 | * Return: Zero on success, Negative error code on failure. In particular |
| 73 | * -ERESTARTSYS if interrupted by a signal | 64 | * -ERESTARTSYS if interrupted by a signal |
| 74 | */ | 65 | */ |
| 75 | int vmw_bo_pin_in_placement(struct vmw_private *dev_priv, | 66 | static int vmw_bo_pin_in_placement(struct vmw_private *dev_priv, |
| 76 | struct vmw_buffer_object *buf, | 67 | struct vmw_bo *buf, |
| 77 | struct ttm_placement *placement, | 68 | struct ttm_placement *placement, |
| 78 | bool interruptible) | 69 | bool interruptible) |
| 79 | { | 70 | { |
| 80 | struct ttm_operation_ctx ctx = {interruptible, false }; | 71 | struct ttm_operation_ctx ctx = {interruptible, false }; |
| 81 | struct ttm_buffer_object *bo = &buf->base; | 72 | struct ttm_buffer_object *bo = &buf->tbo; |
| 82 | int ret; | 73 | int ret; |
| 83 | 74 | ||
| 84 | vmw_execbuf_release_pinned_bo(dev_priv); | 75 | vmw_execbuf_release_pinned_bo(dev_priv); |
| @@ -87,12 +78,7 @@ int vmw_bo_pin_in_placement(struct vmw_private *dev_priv, · 2 unmodified lines | |||
| 87 | if (unlikely(ret != 0)) | 78 | if (unlikely(ret != 0)) |
| 88 | goto err; | 79 | goto err; |
| 89 | 80 | ||
| 90 | if (buf->base.pin_count > 0) | 81 | ret = ttm_bo_validate(bo, placement, &ctx); |
| 91 | ret = ttm_resource_compat(bo->resource, placement) | ||
| 92 | ? 0 : -EINVAL; | ||
| 93 | else | ||
| 94 | ret = ttm_bo_validate(bo, placement, &ctx); | ||
| 95 | |||
| 96 | if (!ret) | 82 | if (!ret) |
| 97 | vmw_bo_pin_reserved(buf, true); | 83 | vmw_bo_pin_reserved(buf, true); |
| 98 | 84 | ||
| @@ -115,11 +101,11 @@ err: · 16 unmodified lines | |||
| 115 | * -ERESTARTSYS if interrupted by a signal | 101 | * -ERESTARTSYS if interrupted by a signal |
| 116 | */ | 102 | */ |
| 117 | int vmw_bo_pin_in_vram_or_gmr(struct vmw_private *dev_priv, | 103 | int vmw_bo_pin_in_vram_or_gmr(struct vmw_private *dev_priv, |
| 118 | struct vmw_buffer_object *buf, | 104 | struct vmw_bo *buf, |
| 119 | bool interruptible) | 105 | bool interruptible) |
| 120 | { | 106 | { |
| 121 | struct ttm_operation_ctx ctx = {interruptible, false }; | 107 | struct ttm_operation_ctx ctx = {interruptible, false }; |
| 122 | struct ttm_buffer_object *bo = &buf->base; | 108 | struct ttm_buffer_object *bo = &buf->tbo; |
| 123 | int ret; | 109 | int ret; |
| 124 | 110 | ||
| 125 | vmw_execbuf_release_pinned_bo(dev_priv); | 111 | vmw_execbuf_release_pinned_bo(dev_priv); |
| @@ -128,17 +114,17 @@ int vmw_bo_pin_in_vram_or_gmr(struct vmw_private *dev_priv, · 2 unmodified lines | |||
| 128 | if (unlikely(ret != 0)) | 114 | if (unlikely(ret != 0)) |
| 129 | goto err; | 115 | goto err; |
| 130 | 116 | ||
| 131 | if (buf->base.pin_count > 0) { | 117 | vmw_bo_placement_set(buf, |
| 132 | ret = ttm_resource_compat(bo->resource, &vmw_vram_gmr_placement) | 118 | VMW_BO_DOMAIN_GMR | VMW_BO_DOMAIN_VRAM, |
| 133 | ? 0 : -EINVAL; | 119 | VMW_BO_DOMAIN_GMR); |
| 134 | goto out_unreserve; | 120 | ret = ttm_bo_validate(bo, &buf->placement, &ctx); |
| 135 | } | ||
| 136 | |||
| 137 | ret = ttm_bo_validate(bo, &vmw_vram_gmr_placement, &ctx); | ||
| 138 | if (likely(ret == 0) || ret == -ERESTARTSYS) | 121 | if (likely(ret == 0) || ret == -ERESTARTSYS) |
| 139 | goto out_unreserve; | 122 | goto out_unreserve; |
| 140 | 123 | ||
| 141 | ret = ttm_bo_validate(bo, &vmw_vram_placement, &ctx); | 124 | vmw_bo_placement_set(buf, |
| 125 | VMW_BO_DOMAIN_VRAM, | ||
| 126 | VMW_BO_DOMAIN_VRAM); | ||
| 127 | ret = ttm_bo_validate(bo, &buf->placement, &ctx); | ||
| 142 | 128 | ||
| 143 | out_unreserve: | 129 | out_unreserve: |
| 144 | if (!ret) | 130 | if (!ret) |
| @@ -163,7 +149,7 @@ err: · 18 unmodified lines | |||
| 163 | * -ERESTARTSYS if interrupted by a signal | 149 | * -ERESTARTSYS if interrupted by a signal |
| 164 | */ | 150 | */ |
| 165 | int vmw_bo_pin_in_vram(struct vmw_private *dev_priv, | 151 | int vmw_bo_pin_in_vram(struct vmw_private *dev_priv, |
| 166 | struct vmw_buffer_object *buf, | 152 | struct vmw_bo *buf, |
| 167 | bool interruptible) | 153 | bool interruptible) |
| 168 | { | 154 | { |
| 169 | return vmw_bo_pin_in_placement(dev_priv, buf, &vmw_vram_placement, | 155 | return vmw_bo_pin_in_placement(dev_priv, buf, &vmw_vram_placement, |
| @@ -184,22 +170,13 @@ int vmw_bo_pin_in_vram(struct vmw_private *dev_priv, · 14 unmodified lines | |||
| 184 | * -ERESTARTSYS if interrupted by a signal | 170 | * -ERESTARTSYS if interrupted by a signal |
| 185 | */ | 171 | */ |
| 186 | int vmw_bo_pin_in_start_of_vram(struct vmw_private *dev_priv, | 172 | int vmw_bo_pin_in_start_of_vram(struct vmw_private *dev_priv, |
| 187 | struct vmw_buffer_object *buf, | 173 | struct vmw_bo *buf, |
| 188 | bool interruptible) | 174 | bool interruptible) |
| 189 | { | 175 | { |
| 190 | struct ttm_operation_ctx ctx = {interruptible, false }; | 176 | struct ttm_operation_ctx ctx = {interruptible, false }; |
| 191 | struct ttm_buffer_object *bo = &buf->base; | 177 | struct ttm_buffer_object *bo = &buf->tbo; |
| 192 | struct ttm_placement placement; | ||
| 193 | struct ttm_place place; | ||
| 194 | int ret = 0; | 178 | int ret = 0; |
| 195 | 179 | ||
| 196 | place = vmw_vram_placement.placement[0]; | ||
| 197 | place.lpfn = PFN_UP(bo->resource->size); | ||
| 198 | placement.num_placement = 1; | ||
| 199 | placement.placement = &place; | ||
| 200 | placement.num_busy_placement = 1; | ||
| 201 | placement.busy_placement = &place; | ||
| 202 | |||
| 203 | vmw_execbuf_release_pinned_bo(dev_priv); | 180 | vmw_execbuf_release_pinned_bo(dev_priv); |
| 204 | ret = ttm_bo_reserve(bo, interruptible, false, NULL); | 181 | ret = ttm_bo_reserve(bo, interruptible, false, NULL); |
| 205 | if (unlikely(ret != 0)) | 182 | if (unlikely(ret != 0)) |
| @@ -213,16 +190,19 @@ int vmw_bo_pin_in_start_of_vram(struct vmw_private *dev_priv, · 7 unmodified lines | |||
| 213 | if (bo->resource->mem_type == TTM_PL_VRAM && | 190 | if (bo->resource->mem_type == TTM_PL_VRAM && |
| 214 | bo->resource->start < PFN_UP(bo->resource->size) && | 191 | bo->resource->start < PFN_UP(bo->resource->size) && |
| 215 | bo->resource->start > 0 && | 192 | bo->resource->start > 0 && |
| 216 | buf->base.pin_count == 0) { | 193 | buf->tbo.pin_count == 0) { |
| 217 | ctx.interruptible = false; | 194 | ctx.interruptible = false; |
| 218 | (void) ttm_bo_validate(bo, &vmw_sys_placement, &ctx); | 195 | vmw_bo_placement_set(buf, |
| 196 | VMW_BO_DOMAIN_SYS, | ||
| 197 | VMW_BO_DOMAIN_SYS); | ||
| 198 | (void)ttm_bo_validate(bo, &buf->placement, &ctx); | ||
| 219 | } | 199 | } |
| 220 | 200 | ||
| 221 | if (buf->base.pin_count > 0) | 201 | vmw_bo_placement_set(buf, |
| 222 | ret = ttm_resource_compat(bo->resource, &placement) | 202 | VMW_BO_DOMAIN_VRAM, |
| 223 | ? 0 : -EINVAL; | 203 | VMW_BO_DOMAIN_VRAM); |
| 224 | else | 204 | buf->places[0].lpfn = PFN_UP(bo->resource->size); |
| 225 | ret = ttm_bo_validate(bo, &placement, &ctx); | 205 | ret = ttm_bo_validate(bo, &buf->placement, &ctx); |
| 226 | 206 | ||
| 227 | /* For some reason we didn't end up at the start of vram */ | 207 | /* For some reason we didn't end up at the start of vram */ |
| 228 | WARN_ON(ret == 0 && bo->resource->start != 0); | 208 | WARN_ON(ret == 0 && bo->resource->start != 0); |
| @@ -248,10 +228,10 @@ err_unlock: · 19 unmodified lines | |||
| 248 | * -ERESTARTSYS if interrupted by a signal | 228 | * -ERESTARTSYS if interrupted by a signal |
| 249 | */ | 229 | */ |
| 250 | int vmw_bo_unpin(struct vmw_private *dev_priv, | 230 | int vmw_bo_unpin(struct vmw_private *dev_priv, |
| 251 | struct vmw_buffer_object *buf, | 231 | struct vmw_bo *buf, |
| 252 | bool interruptible) | 232 | bool interruptible) |
| 253 | { | 233 | { |
| 254 | struct ttm_buffer_object *bo = &buf->base; | 234 | struct ttm_buffer_object *bo = &buf->tbo; |
| 255 | int ret; | 235 | int ret; |
| 256 | 236 | ||
| 257 | ret = ttm_bo_reserve(bo, interruptible, false, NULL); | 237 | ret = ttm_bo_reserve(bo, interruptible, false, NULL); |
| @@ -293,12 +273,12 @@ void vmw_bo_get_guest_ptr(const struct ttm_buffer_object *bo, · 35 unmodified lines | |||
| 293 | * @pin: Whether to pin or unpin. | 273 | * @pin: Whether to pin or unpin. |
| 294 | * | 274 | * |
| 295 | */ | 275 | */ |
| 296 | void vmw_bo_pin_reserved(struct vmw_buffer_object *vbo, bool pin) | 276 | void vmw_bo_pin_reserved(struct vmw_bo *vbo, bool pin) |
| 297 | { | 277 | { |
| 298 | struct ttm_operation_ctx ctx = { false, true }; | 278 | struct ttm_operation_ctx ctx = { false, true }; |
| 299 | struct ttm_place pl; | 279 | struct ttm_place pl; |
| 300 | struct ttm_placement placement; | 280 | struct ttm_placement placement; |
| 301 | struct ttm_buffer_object *bo = &vbo->base; | 281 | struct ttm_buffer_object *bo = &vbo->tbo; |
| 302 | uint32_t old_mem_type = bo->resource->mem_type; | 282 | uint32_t old_mem_type = bo->resource->mem_type; |
| 303 | int ret; | 283 | int ret; |
| 304 | 284 | ||
| @@ -341,9 +321,9 @@ void vmw_bo_pin_reserved(struct vmw_buffer_object *vbo, bool pin) · 36 unmodified lines | |||
| 341 | * 3) Buffer object destruction | 321 | * 3) Buffer object destruction |
| 342 | * | 322 | * |
| 343 | */ | 323 | */ |
| 344 | void *vmw_bo_map_and_cache(struct vmw_buffer_object *vbo) | 324 | void *vmw_bo_map_and_cache(struct vmw_bo *vbo) |
| 345 | { | 325 | { |
| 346 | struct ttm_buffer_object *bo = &vbo->base; | 326 | struct ttm_buffer_object *bo = &vbo->tbo; |
| 347 | bool not_used; | 327 | bool not_used; |
| 348 | void *virtual; | 328 | void *virtual; |
| 349 | int ret; | 329 | int ret; |
| @@ -366,96 +346,70 @@ void *vmw_bo_map_and_cache(struct vmw_buffer_object *vbo) · 16 unmodified lines | |||
| 366 | * @vbo: The buffer object whose map we are tearing down. | 346 | * @vbo: The buffer object whose map we are tearing down. |
| 367 | * | 347 | * |
| 368 | * This function tears down a cached map set up using | 348 | * This function tears down a cached map set up using |
| 369 | * vmw_buffer_object_map_and_cache(). | 349 | * vmw_bo_map_and_cache(). |
| 370 | */ | 350 | */ |
| 371 | void vmw_bo_unmap(struct vmw_buffer_object *vbo) | 351 | void vmw_bo_unmap(struct vmw_bo *vbo) |
| 372 | { | 352 | { |
| 373 | if (vbo->map.bo == NULL) | 353 | if (vbo->map.bo == NULL) |
| 374 | return; | 354 | return; |
| 375 | 355 | ||
| 376 | ttm_bo_kunmap(&vbo->map); | 356 | ttm_bo_kunmap(&vbo->map); |
| 357 | vbo->map.bo = NULL; | ||
| 377 | } | 358 | } |
| 378 | 359 | ||
| 379 | 360 | ||
| 380 | /** | 361 | /** |
| 381 | * vmw_bo_bo_free - vmw buffer object destructor | 362 | * vmw_bo_init - Initialize a vmw buffer object |
| 382 | * | ||
| 383 | * @bo: Pointer to the embedded struct ttm_buffer_object | ||
| 384 | */ | ||
| 385 | void vmw_bo_bo_free(struct ttm_buffer_object *bo) | ||
| 386 | { | ||
| 387 | struct vmw_buffer_object *vmw_bo = vmw_buffer_object(bo); | ||
| 388 | |||
| 389 | WARN_ON(vmw_bo->dirty); | ||
| 390 | WARN_ON(!RB_EMPTY_ROOT(&vmw_bo->res_tree)); | ||
| 391 | vmw_bo_unmap(vmw_bo); | ||
| 392 | drm_gem_object_release(&bo->base); | ||
| 393 | kfree(vmw_bo); | ||
| 394 | } | ||
| 395 | |||
| 396 | /* default destructor */ | ||
| 397 | static void vmw_bo_default_destroy(struct ttm_buffer_object *bo) | ||
| 398 | { | ||
| 399 | kfree(bo); | ||
| 400 | } | ||
| 401 | |||
| 402 | /** | ||
| 403 | * vmw_bo_create_kernel - Create a pinned BO for internal kernel use. | ||
| 404 | * | 363 | * |
| 405 | * @dev_priv: Pointer to the device private struct | 364 | * @dev_priv: Pointer to the device private struct |
| 406 | * @size: size of the BO we need | 365 | * @vmw_bo: Buffer object to initialize |
| 407 | * @placement: where to put it | 366 | * @params: Parameters used to initialize the buffer object |
| 408 | * @p_bo: resulting BO | 367 | * @destroy: The function used to delete the buffer object |
| 368 | * Returns: Zero on success, negative error code on error. | ||
| 409 | * | 369 | * |
| 410 | * Creates and pin a simple BO for in kernel use. | ||
| 411 | */ | 370 | */ |
| 412 | int vmw_bo_create_kernel(struct vmw_private *dev_priv, unsigned long size, | 371 | static int vmw_bo_init(struct vmw_private *dev_priv, |
| 413 | struct ttm_placement *placement, | 372 | struct vmw_bo *vmw_bo, |
| 414 | struct ttm_buffer_object **p_bo) | 373 | struct vmw_bo_params *params, |
| 374 | void (*destroy)(struct ttm_buffer_object *)) | ||
| 415 | { | 375 | { |
| 416 | struct ttm_operation_ctx ctx = { | 376 | struct ttm_operation_ctx ctx = { |
| 417 | .interruptible = false, | 377 | .interruptible = params->bo_type != ttm_bo_type_kernel, |
| 418 | .no_wait_gpu = false | 378 | .no_wait_gpu = false |
| 419 | }; | 379 | }; |
| 420 | struct ttm_buffer_object *bo; | 380 | struct ttm_device *bdev = &dev_priv->bdev; |
| 421 | struct drm_device *vdev = &dev_priv->drm; | 381 | struct drm_device *vdev = &dev_priv->drm; |
| 422 | int ret; | 382 | int ret; |
| 423 | 383 | ||
| 424 | bo = kzalloc(sizeof(*bo), GFP_KERNEL); | 384 | memset(vmw_bo, 0, sizeof(*vmw_bo)); |
| 425 | if (unlikely(!bo)) | ||
| 426 | return -ENOMEM; | ||
| 427 | 385 | ||
| 428 | size = ALIGN(size, PAGE_SIZE); | 386 | BUILD_BUG_ON(TTM_MAX_BO_PRIORITY <= 3); |
| 387 | vmw_bo->tbo.priority = 3; | ||
| 388 | vmw_bo->res_tree = RB_ROOT; | ||
| 429 | 389 | ||
| 430 | drm_gem_private_object_init(vdev, &bo->base, size); | 390 | params->size = ALIGN(params->size, PAGE_SIZE); |
| 391 | drm_gem_private_object_init(vdev, &vmw_bo->tbo.base, params->size); | ||
| 431 | 392 | ||
| 432 | ret = ttm_bo_init_reserved(&dev_priv->bdev, bo, ttm_bo_type_kernel, | 393 | vmw_bo_placement_set(vmw_bo, params->domain, params->busy_domain); |
| 433 | placement, 0, &ctx, NULL, NULL, | 394 | ret = ttm_bo_init_reserved(bdev, &vmw_bo->tbo, params->bo_type, |
| 434 | vmw_bo_default_destroy); | 395 | &vmw_bo->placement, 0, &ctx, NULL, |
| 396 | NULL, destroy); | ||
| 435 | if (unlikely(ret)) | 397 | if (unlikely(ret)) |
| 436 | goto error_free; | 398 | return ret; |
| 437 | 399 | ||
| 438 | ttm_bo_pin(bo); | 400 | if (params->pin) |
| 439 | ttm_bo_unreserve(bo); | 401 | ttm_bo_pin(&vmw_bo->tbo); |
| 440 | *p_bo = bo; | 402 | ttm_bo_unreserve(&vmw_bo->tbo); |
| 441 | 403 | ||
| 442 | return 0; | 404 | return 0; |
| 443 | |||
| 444 | error_free: | ||
| 445 | kfree(bo); | ||
| 446 | return ret; | ||
| 447 | } | 405 | } |
| 448 | 406 | ||
| 449 | int vmw_bo_create(struct vmw_private *vmw, | 407 | int vmw_bo_create(struct vmw_private *vmw, |
| 450 | size_t size, struct ttm_placement *placement, | 408 | struct vmw_bo_params *params, |
| 451 | bool interruptible, bool pin, | 409 | struct vmw_bo **p_bo) |
| 452 | void (*bo_free)(struct ttm_buffer_object *bo), | ||
| 453 | struct vmw_buffer_object **p_bo) | ||
| 454 | { | 410 | { |
| 455 | int ret; | 411 | int ret; |
| 456 | 412 | ||
| 457 | BUG_ON(!bo_free); | ||
| 458 | |||
| 459 | *p_bo = kmalloc(sizeof(**p_bo), GFP_KERNEL); | 413 | *p_bo = kmalloc(sizeof(**p_bo), GFP_KERNEL); |
| 460 | if (unlikely(!*p_bo)) { | 414 | if (unlikely(!*p_bo)) { |
| 461 | DRM_ERROR("Failed to allocate a buffer.\n"); | 415 | DRM_ERROR("Failed to allocate a buffer.\n"); |
| @@ -465,9 +419,7 @@ int vmw_bo_create(struct vmw_private *vmw, · 3 unmodified lines | |||
| 465 | /* | 419 | /* |
| 466 | * vmw_bo_init will delete the *p_bo object if it fails | 420 | * vmw_bo_init will delete the *p_bo object if it fails |
| 467 | */ | 421 | */ |
| 468 | ret = vmw_bo_init(vmw, *p_bo, size, | 422 | ret = vmw_bo_init(vmw, *p_bo, params, vmw_bo_free); |
| 469 | placement, interruptible, pin, | ||
| 470 | bo_free); | ||
| 471 | if (unlikely(ret != 0)) | 423 | if (unlikely(ret != 0)) |
| 472 | goto out_error; | 424 | goto out_error; |
| 473 | 425 | ||
| @@ -478,57 +430,7 @@ out_error: · 4 unmodified lines | |||
| 478 | } | 430 | } |
| 479 | 431 | ||
| 480 | /** | 432 | /** |
| 481 | * vmw_bo_init - Initialize a vmw buffer object | 433 | * vmw_user_bo_synccpu_grab - Grab a struct vmw_bo for cpu |
| 482 | * | ||
| 483 | * @dev_priv: Pointer to the device private struct | ||
| 484 | * @vmw_bo: Pointer to the struct vmw_buffer_object to initialize. | ||
| 485 | * @size: Buffer object size in bytes. | ||
| 486 | * @placement: Initial placement. | ||
| 487 | * @interruptible: Whether waits should be performed interruptible. | ||
| 488 | * @pin: If the BO should be created pinned at a fixed location. | ||
| 489 | * @bo_free: The buffer object destructor. | ||
| 490 | * Returns: Zero on success, negative error code on error. | ||
| 491 | * | ||
| 492 | * Note that on error, the code will free the buffer object. | ||
| 493 | */ | ||
| 494 | int vmw_bo_init(struct vmw_private *dev_priv, | ||
| 495 | struct vmw_buffer_object *vmw_bo, | ||
| 496 | size_t size, struct ttm_placement *placement, | ||
| 497 | bool interruptible, bool pin, | ||
| 498 | void (*bo_free)(struct ttm_buffer_object *bo)) | ||
| 499 | { | ||
| 500 | struct ttm_operation_ctx ctx = { | ||
| 501 | .interruptible = interruptible, | ||
| 502 | .no_wait_gpu = false | ||
| 503 | }; | ||
| 504 | struct ttm_device *bdev = &dev_priv->bdev; | ||
| 505 | struct drm_device *vdev = &dev_priv->drm; | ||
| 506 | int ret; | ||
| 507 | |||
| 508 | WARN_ON_ONCE(!bo_free); | ||
| 509 | memset(vmw_bo, 0, sizeof(*vmw_bo)); | ||
| 510 | BUILD_BUG_ON(TTM_MAX_BO_PRIORITY <= 3); | ||
| 511 | vmw_bo->base.priority = 3; | ||
| 512 | vmw_bo->res_tree = RB_ROOT; | ||
| 513 | |||
| 514 | size = ALIGN(size, PAGE_SIZE); | ||
| 515 | drm_gem_private_object_init(vdev, &vmw_bo->base.base, size); | ||
| 516 | |||
| 517 | ret = ttm_bo_init_reserved(bdev, &vmw_bo->base, ttm_bo_type_device, | ||
| 518 | placement, 0, &ctx, NULL, NULL, bo_free); | ||
| 519 | if (unlikely(ret)) { | ||
| 520 | return ret; | ||
| 521 | } | ||
| 522 | |||
| 523 | if (pin) | ||
| 524 | ttm_bo_pin(&vmw_bo->base); | ||
| 525 | ttm_bo_unreserve(&vmw_bo->base); | ||
| 526 | |||
| 527 | return 0; | ||
| 528 | } | ||
| 529 | |||
| 530 | /** | ||
| 531 | * vmw_user_bo_synccpu_grab - Grab a struct vmw_buffer_object for cpu | ||
| 532 | * access, idling previous GPU operations on the buffer and optionally | 434 | * access, idling previous GPU operations on the buffer and optionally |
| 533 | * blocking it for further command submissions. | 435 | * blocking it for further command submissions. |
| 534 | * | 436 | * |
| @@ -541,11 +443,11 @@ int vmw_bo_init(struct vmw_private *dev_priv, · 6 unmodified lines | |||
| 541 | * | 443 | * |
| 542 | * A blocking grab will be automatically released when @tfile is closed. | 444 | * A blocking grab will be automatically released when @tfile is closed. |
| 543 | */ | 445 | */ |
| 544 | static int vmw_user_bo_synccpu_grab(struct vmw_buffer_object *vmw_bo, | 446 | static int vmw_user_bo_synccpu_grab(struct vmw_bo *vmw_bo, |
| 545 | uint32_t flags) | 447 | uint32_t flags) |
| 546 | { | 448 | { |
| 547 | bool nonblock = !!(flags & drm_vmw_synccpu_dontblock); | 449 | bool nonblock = !!(flags & drm_vmw_synccpu_dontblock); |
| 548 | struct ttm_buffer_object *bo = &vmw_bo->base; | 450 | struct ttm_buffer_object *bo = &vmw_bo->tbo; |
| 549 | int ret; | 451 | int ret; |
| 550 | 452 | ||
| 551 | if (flags & drm_vmw_synccpu_allow_cs) { | 453 | if (flags & drm_vmw_synccpu_allow_cs) { |
| @@ -588,17 +490,17 @@ static int vmw_user_bo_synccpu_release(struct drm_file *filp, · 36 unmodified lines | |||
| 588 | uint32_t handle, | 490 | uint32_t handle, |
| 589 | uint32_t flags) | 491 | uint32_t flags) |
| 590 | { | 492 | { |
| 591 | struct vmw_buffer_object *vmw_bo; | 493 | struct vmw_bo *vmw_bo; |
| 592 | int ret = vmw_user_bo_lookup(filp, handle, &vmw_bo); | 494 | int ret = vmw_user_bo_lookup(filp, handle, &vmw_bo); |
| 593 | 495 | ||
| 594 | if (!ret) { | 496 | if (!ret) { |
| 595 | if (!(flags & drm_vmw_synccpu_allow_cs)) { | 497 | if (!(flags & drm_vmw_synccpu_allow_cs)) { |
| 596 | atomic_dec(&vmw_bo->cpu_writers); | 498 | atomic_dec(&vmw_bo->cpu_writers); |
| 597 | } | 499 | } |
| 598 | ttm_bo_put(&vmw_bo->base); | 500 | ttm_bo_put(&vmw_bo->tbo); |
| 599 | } | 501 | } |
| 600 | 502 | ||
| 601 | drm_gem_object_put(&vmw_bo->base.base); | 503 | drm_gem_object_put(&vmw_bo->tbo.base); |
| 602 | return ret; | 504 | return ret; |
| 603 | } | 505 | } |
| 604 | 506 | ||
| @@ -620,7 +522,7 @@ int vmw_user_bo_synccpu_ioctl(struct drm_device *dev, void *data, · 15 unmodified lines | |||
| 620 | { | 522 | { |
| 621 | struct drm_vmw_synccpu_arg *arg = | 523 | struct drm_vmw_synccpu_arg *arg = |
| 622 | (struct drm_vmw_synccpu_arg *) data; | 524 | (struct drm_vmw_synccpu_arg *) data; |
| 623 | struct vmw_buffer_object *vbo; | 525 | struct vmw_bo *vbo; |
| 624 | int ret; | 526 | int ret; |
| 625 | 527 | ||
| 626 | if ((arg->flags & (drm_vmw_synccpu_read | drm_vmw_synccpu_write)) == 0 | 528 | if ((arg->flags & (drm_vmw_synccpu_read | drm_vmw_synccpu_write)) == 0 |
| @@ -639,7 +541,7 @@ int vmw_user_bo_synccpu_ioctl(struct drm_device *dev, void *data, · 12 unmodified lines | |||
| 639 | 541 | ||
| 640 | ret = vmw_user_bo_synccpu_grab(vbo, arg->flags); | 542 | ret = vmw_user_bo_synccpu_grab(vbo, arg->flags); |
| 641 | vmw_bo_unreference(&vbo); | 543 | vmw_bo_unreference(&vbo); |
| 642 | drm_gem_object_put(&vbo->base.base); | 544 | drm_gem_object_put(&vbo->tbo.base); |
| 643 | if (unlikely(ret != 0)) { | 545 | if (unlikely(ret != 0)) { |
| 644 | if (ret == -ERESTARTSYS || ret == -EBUSY) | 546 | if (ret == -ERESTARTSYS || ret == -EBUSY) |
| 645 | return -EBUSY; | 547 | return -EBUSY; |
| @@ -683,8 +585,7 @@ int vmw_bo_unref_ioctl(struct drm_device *dev, void *data, · 37 unmodified lines | |||
| 683 | struct drm_vmw_unref_dmabuf_arg *arg = | 585 | struct drm_vmw_unref_dmabuf_arg *arg = |
| 684 | (struct drm_vmw_unref_dmabuf_arg *)data; | 586 | (struct drm_vmw_unref_dmabuf_arg *)data; |
| 685 | 587 | ||
| 686 | drm_gem_handle_delete(file_priv, arg->handle); | 588 | return drm_gem_handle_delete(file_priv, arg->handle); |
| 687 | return 0; | ||
| 688 | } | 589 | } |
| 689 | 590 | ||
| 690 | 591 | ||
| @@ -694,14 +595,14 @@ int vmw_bo_unref_ioctl(struct drm_device *dev, void *data, · 3 unmodified lines | |||
| 694 | * @filp: The file the handle is registered with. | 595 | * @filp: The file the handle is registered with. |
| 695 | * @handle: The user buffer object handle | 596 | * @handle: The user buffer object handle |
| 696 | * @out: Pointer to a where a pointer to the embedded | 597 | * @out: Pointer to a where a pointer to the embedded |
| 697 | * struct vmw_buffer_object should be placed. | 598 | * struct vmw_bo should be placed. |
| 698 | * Return: Zero on success, Negative error code on error. | 599 | * Return: Zero on success, Negative error code on error. |
| 699 | * | 600 | * |
| 700 | * The vmw buffer object pointer will be refcounted (both ttm and gem) | 601 | * The vmw buffer object pointer will be refcounted (both ttm and gem) |
| 701 | */ | 602 | */ |
| 702 | int vmw_user_bo_lookup(struct drm_file *filp, | 603 | int vmw_user_bo_lookup(struct drm_file *filp, |
| 703 | uint32_t handle, | 604 | u32 handle, |
| 704 | struct vmw_buffer_object **out) | 605 | struct vmw_bo **out) |
| 705 | { | 606 | { |
| 706 | struct drm_gem_object *gobj; | 607 | struct drm_gem_object *gobj; |
| 707 | 608 | ||
| @@ -712,8 +613,8 @@ int vmw_user_bo_lookup(struct drm_file *filp, · 4 unmodified lines | |||
| 712 | return -ESRCH; | 613 | return -ESRCH; |
| 713 | } | 614 | } |
| 714 | 615 | ||
| 715 | *out = gem_to_vmw_bo(gobj); | 616 | *out = to_vmw_bo(gobj); |
| 716 | ttm_bo_get(&(*out)->base); | 617 | ttm_bo_get(&(*out)->tbo); |
| 717 | 618 | ||
| 718 | return 0; | 619 | return 0; |
| 719 | } | 620 | } |
| @@ -734,8 +635,7 @@ void vmw_bo_fence_single(struct ttm_buffer_object *bo, · 14 unmodified lines | |||
| 734 | struct vmw_fence_obj *fence) | 635 | struct vmw_fence_obj *fence) |
| 735 | { | 636 | { |
| 736 | struct ttm_device *bdev = bo->bdev; | 637 | struct ttm_device *bdev = bo->bdev; |
| 737 | struct vmw_private *dev_priv = | 638 | struct vmw_private *dev_priv = vmw_priv_from_ttm(bdev); |
| 738 | container_of(bdev, struct vmw_private, bdev); | ||
| 739 | int ret; | 639 | int ret; |
| 740 | 640 | ||
| 741 | if (fence == NULL) | 641 | if (fence == NULL) |
| @@ -771,7 +671,7 @@ int vmw_dumb_create(struct drm_file *file_priv, · 29 unmodified lines | |||
| 771 | struct drm_mode_create_dumb *args) | 671 | struct drm_mode_create_dumb *args) |
| 772 | { | 672 | { |
| 773 | struct vmw_private *dev_priv = vmw_priv(dev); | 673 | struct vmw_private *dev_priv = vmw_priv(dev); |
| 774 | struct vmw_buffer_object *vbo; | 674 | struct vmw_bo *vbo; |
| 775 | int cpp = DIV_ROUND_UP(args->bpp, 8); | 675 | int cpp = DIV_ROUND_UP(args->bpp, 8); |
| 776 | int ret; | 676 | int ret; |
| 777 | 677 | ||
| @@ -795,7 +695,7 @@ int vmw_dumb_create(struct drm_file *file_priv, · 17 unmodified lines | |||
| 795 | args->size, &args->handle, | 695 | args->size, &args->handle, |
| 796 | &vbo); | 696 | &vbo); |
| 797 | /* drop reference from allocate - handle holds it now */ | 697 | /* drop reference from allocate - handle holds it now */ |
| 798 | drm_gem_object_put(&vbo->base.base); | 698 | drm_gem_object_put(&vbo->tbo.base); |
| 799 | return ret; | 699 | return ret; |
| 800 | } | 700 | } |
| 801 | 701 | ||
| @@ -806,12 +706,8 @@ int vmw_dumb_create(struct drm_file *file_priv, · 4 unmodified lines | |||
| 806 | */ | 706 | */ |
| 807 | void vmw_bo_swap_notify(struct ttm_buffer_object *bo) | 707 | void vmw_bo_swap_notify(struct ttm_buffer_object *bo) |
| 808 | { | 708 | { |
| 809 | /* Is @bo embedded in a struct vmw_buffer_object? */ | ||
| 810 | if (!bo_is_vmw(bo)) | ||
| 811 | return; | ||
| 812 | |||
| 813 | /* Kill any cached kernel maps before swapout */ | 709 | /* Kill any cached kernel maps before swapout */ |
| 814 | vmw_bo_unmap(vmw_buffer_object(bo)); | 710 | vmw_bo_unmap(to_vmw_bo(&bo->base)); |
| 815 | } | 711 | } |
| 816 | 712 | ||
| 817 | 713 | ||
| @@ -828,13 +724,7 @@ void vmw_bo_swap_notify(struct ttm_buffer_object *bo) · 10 unmodified lines | |||
| 828 | void vmw_bo_move_notify(struct ttm_buffer_object *bo, | 724 | void vmw_bo_move_notify(struct ttm_buffer_object *bo, |
| 829 | struct ttm_resource *mem) | 725 | struct ttm_resource *mem) |
| 830 | { | 726 | { |
| 831 | struct vmw_buffer_object *vbo; | 727 | struct vmw_bo *vbo = to_vmw_bo(&bo->base); |
| 832 | |||
| 833 | /* Make sure @bo is embedded in a struct vmw_buffer_object? */ | ||
| 834 | if (!bo_is_vmw(bo)) | ||
| 835 | return; | ||
| 836 | |||
| 837 | vbo = container_of(bo, struct vmw_buffer_object, base); | ||
| 838 | 728 | ||
| 839 | /* | 729 | /* |
| 840 | * Kill any cached kernel maps before move to or from VRAM. | 730 | * Kill any cached kernel maps before move to or from VRAM. |
| @@ -852,3 +742,98 @@ void vmw_bo_move_notify(struct ttm_buffer_object *bo, · 11 unmodified lines | |||
| 852 | if (mem->mem_type != VMW_PL_MOB && bo->resource->mem_type == VMW_PL_MOB) | 742 | if (mem->mem_type != VMW_PL_MOB && bo->resource->mem_type == VMW_PL_MOB) |
| 853 | vmw_resource_unbind_list(vbo); | 743 | vmw_resource_unbind_list(vbo); |
| 854 | } | 744 | } |
| 745 | |||
| 746 | static u32 | ||
| 747 | set_placement_list(struct ttm_place *pl, u32 domain) | ||
| 748 | { | ||
| 749 | u32 n = 0; | ||
| 750 | |||
| 751 | /* | ||
| 752 | * The placements are ordered according to our preferences | ||
| 753 | */ | ||
| 754 | if (domain & VMW_BO_DOMAIN_MOB) { | ||
| 755 | pl[n].mem_type = VMW_PL_MOB; | ||
| 756 | pl[n].flags = 0; | ||
| 757 | pl[n].fpfn = 0; | ||
| 758 | pl[n].lpfn = 0; | ||
| 759 | n++; | ||
| 760 | } | ||
| 761 | if (domain & VMW_BO_DOMAIN_GMR) { | ||
| 762 | pl[n].mem_type = VMW_PL_GMR; | ||
| 763 | pl[n].flags = 0; | ||
| 764 | pl[n].fpfn = 0; | ||
| 765 | pl[n].lpfn = 0; | ||
| 766 | n++; | ||
| 767 | } | ||
| 768 | if (domain & VMW_BO_DOMAIN_VRAM) { | ||
| 769 | pl[n].mem_type = TTM_PL_VRAM; | ||
| 770 | pl[n].flags = 0; | ||
| 771 | pl[n].fpfn = 0; | ||
| 772 | pl[n].lpfn = 0; | ||
| 773 | n++; | ||
| 774 | } | ||
| 775 | if (domain & VMW_BO_DOMAIN_WAITABLE_SYS) { | ||
| 776 | pl[n].mem_type = VMW_PL_SYSTEM; | ||
| 777 | pl[n].flags = 0; | ||
| 778 | pl[n].fpfn = 0; | ||
| 779 | pl[n].lpfn = 0; | ||
| 780 | n++; | ||
| 781 | } | ||
| 782 | if (domain & VMW_BO_DOMAIN_SYS) { | ||
| 783 | pl[n].mem_type = TTM_PL_SYSTEM; | ||
| 784 | pl[n].flags = 0; | ||
| 785 | pl[n].fpfn = 0; | ||
| 786 | pl[n].lpfn = 0; | ||
| 787 | n++; | ||
| 788 | } | ||
| 789 | |||
| 790 | WARN_ON(!n); | ||
| 791 | if (!n) { | ||
| 792 | pl[n].mem_type = TTM_PL_SYSTEM; | ||
| 793 | pl[n].flags = 0; | ||
| 794 | pl[n].fpfn = 0; | ||
| 795 | pl[n].lpfn = 0; | ||
| 796 | n++; | ||
| 797 | } | ||
| 798 | return n; | ||
| 799 | } | ||
| 800 | |||
| 801 | void vmw_bo_placement_set(struct vmw_bo *bo, u32 domain, u32 busy_domain) | ||
| 802 | { | ||
| 803 | struct ttm_device *bdev = bo->tbo.bdev; | ||
| 804 | struct vmw_private *vmw = vmw_priv_from_ttm(bdev); | ||
| 805 | struct ttm_placement *pl = &bo->placement; | ||
| 806 | bool mem_compatible = false; | ||
| 807 | u32 i; | ||
| 808 | |||
| 809 | pl->placement = bo->places; | ||
| 810 | pl->num_placement = set_placement_list(bo->places, domain); | ||
| 811 | |||
| 812 | if (drm_debug_enabled(DRM_UT_DRIVER) && bo->tbo.resource) { | ||
| 813 | for (i = 0; i < pl->num_placement; ++i) { | ||
| 814 | if (bo->tbo.resource->mem_type == TTM_PL_SYSTEM || | ||
| 815 | bo->tbo.resource->mem_type == pl->placement[i].mem_type) | ||
| 816 | mem_compatible = true; | ||
| 817 | } | ||
| 818 | if (!mem_compatible) | ||
| 819 | drm_warn(&vmw->drm, | ||
| 820 | "%s: Incompatible transition from " | ||
| 821 | "bo->base.resource->mem_type = %u to domain = %u\n", | ||
| 822 | __func__, bo->tbo.resource->mem_type, domain); | ||
| 823 | } | ||
| 824 | |||
| 825 | pl->busy_placement = bo->busy_places; | ||
| 826 | pl->num_busy_placement = set_placement_list(bo->busy_places, busy_domain); | ||
| 827 | } | ||
| 828 | |||
| 829 | void vmw_bo_placement_set_default_accelerated(struct vmw_bo *bo) | ||
| 830 | { | ||
| 831 | struct ttm_device *bdev = bo->tbo.bdev; | ||
| 832 | struct vmw_private *vmw = vmw_priv_from_ttm(bdev); | ||
| 833 | u32 domain = VMW_BO_DOMAIN_GMR | VMW_BO_DOMAIN_VRAM; | ||
| 834 | |||
| 835 | if (vmw->has_mob) | ||
| 836 | domain = VMW_BO_DOMAIN_MOB; | ||
| 837 | |||
| 838 | vmw_bo_placement_set(bo, domain, domain); | ||
| 839 | } | ||
| @@ -0,0 +1,203 @@ | |||
| 1 | /* SPDX-License-Identifier: GPL-2.0 OR MIT */ | ||
| 2 | /************************************************************************** | ||
| 3 | * | ||
| 4 | * Copyright 2023 VMware, Inc., Palo Alto, CA., USA | ||
| 5 | * | ||
| 6 | * Permission is hereby granted, free of charge, to any person obtaining a | ||
| 7 | * copy of this software and associated documentation files (the | ||
| 8 | * "Software"), to deal in the Software without restriction, including | ||
| 9 | * without limitation the rights to use, copy, modify, merge, publish, | ||
| 10 | * distribute, sub license, and/or sell copies of the Software, and to | ||
| 11 | * permit persons to whom the Software is furnished to do so, subject to | ||
| 12 | * the following conditions: | ||
| 13 | * | ||
| 14 | * The above copyright notice and this permission notice (including the | ||
| 15 | * next paragraph) shall be included in all copies or substantial portions | ||
| 16 | * of the Software. | ||
| 17 | * | ||
| 18 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR | ||
| 19 | * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, | ||
| 20 | * FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. IN NO EVENT SHALL | ||
| 21 | * THE COPYRIGHT HOLDERS, AUTHORS AND/OR ITS SUPPLIERS BE LIABLE FOR ANY CLAIM, | ||
| 22 | * DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR | ||
| 23 | * OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE | ||
| 24 | * USE OR OTHER DEALINGS IN THE SOFTWARE. | ||
| 25 | * | ||
| 26 | **************************************************************************/ | ||
| 27 | |||
| 28 | #ifndef VMWGFX_BO_H | ||
| 29 | #define VMWGFX_BO_H | ||
| 30 | |||
| 31 | #include "device_include/svga_reg.h" | ||
| 32 | |||
| 33 | #include <drm/ttm/ttm_bo.h> | ||
| 34 | #include <drm/ttm/ttm_placement.h> | ||
| 35 | |||
| 36 | #include <linux/rbtree_types.h> | ||
| 37 | #include <linux/types.h> | ||
| 38 | |||
| 39 | struct vmw_bo_dirty; | ||
| 40 | struct vmw_fence_obj; | ||
| 41 | struct vmw_private; | ||
| 42 | struct vmw_resource; | ||
| 43 | |||
| 44 | enum vmw_bo_domain { | ||
| 45 | VMW_BO_DOMAIN_SYS = BIT(0), | ||
| 46 | VMW_BO_DOMAIN_WAITABLE_SYS = BIT(1), | ||
| 47 | VMW_BO_DOMAIN_VRAM = BIT(2), | ||
| 48 | VMW_BO_DOMAIN_GMR = BIT(3), | ||
| 49 | VMW_BO_DOMAIN_MOB = BIT(4), | ||
| 50 | }; | ||
| 51 | |||
| 52 | struct vmw_bo_params { | ||
| 53 | u32 domain; | ||
| 54 | u32 busy_domain; | ||
| 55 | enum ttm_bo_type bo_type; | ||
| 56 | size_t size; | ||
| 57 | bool pin; | ||
| 58 | }; | ||
| 59 | |||
| 60 | /** | ||
| 61 | * struct vmw_bo - TTM buffer object with vmwgfx additions | ||
| 62 | * @tbo: The TTM buffer object | ||
| 63 | * @placement: The preferred placement for this buffer object | ||
| 64 | * @places: The chosen places for the preferred placement. | ||
| 65 | * @busy_places: Chosen busy places for the preferred placement | ||
| 66 | * @map: Kmap object for semi-persistent mappings | ||
| 67 | * @res_tree: RB tree of resources using this buffer object as a backing MOB | ||
| 68 | * @res_prios: Eviction priority counts for attached resources | ||
| 69 | * @cpu_writers: Number of synccpu write grabs. Protected by reservation when | ||
| 70 | * increased. May be decreased without reservation. | ||
| 71 | * @dx_query_ctx: DX context if this buffer object is used as a DX query MOB | ||
| 72 | * @dirty: structure for user-space dirty-tracking | ||
| 73 | */ | ||
| 74 | struct vmw_bo { | ||
| 75 | struct ttm_buffer_object tbo; | ||
| 76 | |||
| 77 | struct ttm_placement placement; | ||
| 78 | struct ttm_place places[5]; | ||
| 79 | struct ttm_place busy_places[5]; | ||
| 80 | |||
| 81 | /* Protected by reservation */ | ||
| 82 | struct ttm_bo_kmap_obj map; | ||
| 83 | |||
| 84 | struct rb_root res_tree; | ||
| 85 | u32 res_prios[TTM_MAX_BO_PRIORITY]; | ||
| 86 | |||
| 87 | atomic_t cpu_writers; | ||
| 88 | /* Not ref-counted. Protected by binding_mutex */ | ||
| 89 | struct vmw_resource *dx_query_ctx; | ||
| 90 | struct vmw_bo_dirty *dirty; | ||
| 91 | }; | ||
| 92 | |||
| 93 | void vmw_bo_placement_set(struct vmw_bo *bo, u32 domain, u32 busy_domain); | ||
| 94 | void vmw_bo_placement_set_default_accelerated(struct vmw_bo *bo); | ||
| 95 | |||
| 96 | int vmw_bo_create(struct vmw_private *dev_priv, | ||
| 97 | struct vmw_bo_params *params, | ||
| 98 | struct vmw_bo **p_bo); | ||
| 99 | |||
| 100 | int vmw_bo_unref_ioctl(struct drm_device *dev, void *data, | ||
| 101 | struct drm_file *file_priv); | ||
| 102 | |||
| 103 | int vmw_bo_pin_in_vram(struct vmw_private *dev_priv, | ||
| 104 | struct vmw_bo *buf, | ||
| 105 | bool interruptible); | ||
| 106 | int vmw_bo_pin_in_vram_or_gmr(struct vmw_private *dev_priv, | ||
| 107 | struct vmw_bo *buf, | ||
| 108 | bool interruptible); | ||
| 109 | int vmw_bo_pin_in_start_of_vram(struct vmw_private *vmw_priv, | ||
| 110 | struct vmw_bo *bo, | ||
| 111 | bool interruptible); | ||
| 112 | void vmw_bo_pin_reserved(struct vmw_bo *bo, bool pin); | ||
| 113 | int vmw_bo_unpin(struct vmw_private *vmw_priv, | ||
| 114 | struct vmw_bo *bo, | ||
| 115 | bool interruptible); | ||
| 116 | |||
| 117 | void vmw_bo_get_guest_ptr(const struct ttm_buffer_object *buf, | ||
| 118 | SVGAGuestPtr *ptr); | ||
| 119 | int vmw_user_bo_synccpu_ioctl(struct drm_device *dev, void *data, | ||
| 120 | struct drm_file *file_priv); | ||
| 121 | void vmw_bo_fence_single(struct ttm_buffer_object *bo, | ||
| 122 | struct vmw_fence_obj *fence); | ||
| 123 | |||
| 124 | void *vmw_bo_map_and_cache(struct vmw_bo *vbo); | ||
| 125 | void vmw_bo_unmap(struct vmw_bo *vbo); | ||
| 126 | |||
| 127 | void vmw_bo_move_notify(struct ttm_buffer_object *bo, | ||
| 128 | struct ttm_resource *mem); | ||
| 129 | void vmw_bo_swap_notify(struct ttm_buffer_object *bo); | ||
| 130 | |||
| 131 | int vmw_user_bo_lookup(struct drm_file *filp, | ||
| 132 | u32 handle, | ||
| 133 | struct vmw_bo **out); | ||
| 134 | /** | ||
| 135 | * vmw_bo_adjust_prio - Adjust the buffer object eviction priority | ||
| 136 | * according to attached resources | ||
| 137 | * @vbo: The struct vmw_bo | ||
| 138 | */ | ||
| 139 | static inline void vmw_bo_prio_adjust(struct vmw_bo *vbo) | ||
| 140 | { | ||
| 141 | int i = ARRAY_SIZE(vbo->res_prios); | ||
| 142 | |||
| 143 | while (i--) { | ||
| 144 | if (vbo->res_prios[i]) { | ||
| 145 | vbo->tbo.priority = i; | ||
| 146 | return; | ||
| 147 | } | ||
| 148 | } | ||
| 149 | |||
| 150 | vbo->tbo.priority = 3; | ||
| 151 | } | ||
| 152 | |||
| 153 | /** | ||
| 154 | * vmw_bo_prio_add - Notify a buffer object of a newly attached resource | ||
| 155 | * eviction priority | ||
| 156 | * @vbo: The struct vmw_bo | ||
| 157 | * @prio: The resource priority | ||
| 158 | * | ||
| 159 | * After being notified, the code assigns the highest resource eviction priority | ||
| 160 | * to the backing buffer object (mob). | ||
| 161 | */ | ||
| 162 | static inline void vmw_bo_prio_add(struct vmw_bo *vbo, int prio) | ||
| 163 | { | ||
| 164 | if (vbo->res_prios[prio]++ == 0) | ||
| 165 | vmw_bo_prio_adjust(vbo); | ||
| 166 | } | ||
| 167 | |||
| 168 | /** | ||
| 169 | * vmw_bo_used_prio_del - Notify a buffer object of a resource with a certain | ||
| 170 | * priority being removed | ||
| 171 | * @vbo: The struct vmw_bo | ||
| 172 | * @prio: The resource priority | ||
| 173 | * | ||
| 174 | * After being notified, the code assigns the highest resource eviction priority | ||
| 175 | * to the backing buffer object (mob). | ||
| 176 | */ | ||
| 177 | static inline void vmw_bo_prio_del(struct vmw_bo *vbo, int prio) | ||
| 178 | { | ||
| 179 | if (--vbo->res_prios[prio] == 0) | ||
| 180 | vmw_bo_prio_adjust(vbo); | ||
| 181 | } | ||
| 182 | |||
| 183 | static inline void vmw_bo_unreference(struct vmw_bo **buf) | ||
| 184 | { | ||
| 185 | struct vmw_bo *tmp_buf = *buf; | ||
| 186 | |||
| 187 | *buf = NULL; | ||
| 188 | if (tmp_buf) | ||
| 189 | ttm_bo_put(&tmp_buf->tbo); | ||
| 190 | } | ||
| 191 | |||
| 192 | static inline struct vmw_bo *vmw_bo_reference(struct vmw_bo *buf) | ||
| 193 | { | ||
| 194 | ttm_bo_get(&buf->tbo); | ||
| 195 | return buf; | ||
| 196 | } | ||
| 197 | |||
| 198 | static inline struct vmw_bo *to_vmw_bo(struct drm_gem_object *gobj) | ||
| 199 | { | ||
| 200 | return container_of((gobj), struct vmw_bo, tbo.base); | ||
| 201 | } | ||
| 202 | |||
| 203 | #endif // VMWGFX_BO_H | ||
| @@ -1,7 +1,7 @@ | |||
| 1 | // SPDX-License-Identifier: GPL-2.0 OR MIT | 1 | // SPDX-License-Identifier: GPL-2.0 OR MIT |
| 2 | /************************************************************************** | 2 | /************************************************************************** |
| 3 | * | 3 | * |
| 4 | * Copyright 2009-2020 VMware, Inc., Palo Alto, CA., USA | 4 | * Copyright 2009-2023 VMware, Inc., Palo Alto, CA., USA |
| 5 | * | 5 | * |
| 6 | * Permission is hereby granted, free of charge, to any person obtaining a | 6 | * Permission is hereby granted, free of charge, to any person obtaining a |
| 7 | * copy of this software and associated documentation files (the | 7 | * copy of this software and associated documentation files (the |
| @@ -24,13 +24,13 @@ · 16 unmodified lines | |||
| 24 | * USE OR OTHER DEALINGS IN THE SOFTWARE. | 24 | * USE OR OTHER DEALINGS IN THE SOFTWARE. |
| 25 | * | 25 | * |
| 26 | **************************************************************************/ | 26 | **************************************************************************/ |
| 27 | 27 | #include "vmwgfx_bo.h" | |
| 28 | #include <linux/sched/signal.h> | 28 | #include "vmwgfx_drv.h" |
| 29 | #include "vmwgfx_devcaps.h" | ||
| 29 | 30 | ||
| 30 | #include <drm/ttm/ttm_placement.h> | 31 | #include <drm/ttm/ttm_placement.h> |
| 31 | 32 | ||
| 32 | #include "vmwgfx_drv.h" | 33 | #include <linux/sched/signal.h> |
| 33 | #include "vmwgfx_devcaps.h" | ||
| 34 | 34 | ||
| 35 | bool vmw_supports_3d(struct vmw_private *dev_priv) | 35 | bool vmw_supports_3d(struct vmw_private *dev_priv) |
| 36 | { | 36 | { |
| @@ -567,7 +567,7 @@ static int vmw_cmd_emit_dummy_legacy_query(struct vmw_private *dev_priv, · 530 unmodified lines | |||
| 567 | * without writing to the query result structure. | 567 | * without writing to the query result structure. |
| 568 | */ | 568 | */ |
| 569 | 569 | ||
| 570 | struct ttm_buffer_object *bo = &dev_priv->dummy_query_bo->base; | 570 | struct ttm_buffer_object *bo = &dev_priv->dummy_query_bo->tbo; |
| 571 | struct { | 571 | struct { |
| 572 | SVGA3dCmdHeader header; | 572 | SVGA3dCmdHeader header; |
| 573 | SVGA3dCmdWaitForQuery body; | 573 | SVGA3dCmdWaitForQuery body; |
| @@ -613,7 +613,7 @@ static int vmw_cmd_emit_dummy_gb_query(struct vmw_private *dev_priv, · 39 unmodified lines | |||
| 613 | * without writing to the query result structure. | 613 | * without writing to the query result structure. |
| 614 | */ | 614 | */ |
| 615 | 615 | ||
| 616 | struct ttm_buffer_object *bo = &dev_priv->dummy_query_bo->base; | 616 | struct ttm_buffer_object *bo = &dev_priv->dummy_query_bo->tbo; |
| 617 | struct { | 617 | struct { |
| 618 | SVGA3dCmdHeader header; | 618 | SVGA3dCmdHeader header; |
| 619 | SVGA3dCmdWaitForGBQuery body; | 619 | SVGA3dCmdWaitForGBQuery body; |
| @@ -1,7 +1,7 @@ | |||
| 1 | // SPDX-License-Identifier: GPL-2.0 OR MIT | 1 | // SPDX-License-Identifier: GPL-2.0 OR MIT |
| 2 | /************************************************************************** | 2 | /************************************************************************** |
| 3 | * | 3 | * |
| 4 | * Copyright 2015 VMware, Inc., Palo Alto, CA., USA | 4 | * Copyright 2015-2023 VMware, Inc., Palo Alto, CA., USA |
| 5 | * | 5 | * |
| 6 | * Permission is hereby granted, free of charge, to any person obtaining a | 6 | * Permission is hereby granted, free of charge, to any person obtaining a |
| 7 | * copy of this software and associated documentation files (the | 7 | * copy of this software and associated documentation files (the |
| @@ -25,12 +25,13 @@ · 17 unmodified lines | |||
| 25 | * | 25 | * |
| 26 | **************************************************************************/ | 26 | **************************************************************************/ |
| 27 | 27 | ||
| 28 | #include <linux/dmapool.h> | 28 | #include "vmwgfx_bo.h" |
| 29 | #include <linux/pci.h> | 29 | #include "vmwgfx_drv.h" |
| 30 | 30 | ||
| 31 | #include <drm/ttm/ttm_bo.h> | 31 | #include <drm/ttm/ttm_bo.h> |
| 32 | 32 | ||
| 33 | #include "vmwgfx_drv.h" | 33 | #include <linux/dmapool.h> |
| 34 | #include <linux/pci.h> | ||
| 34 | 35 | ||
| 35 | /* | 36 | /* |
| 36 | * Size of inline command buffers. Try to make sure that a page size is a | 37 | * Size of inline command buffers. Try to make sure that a page size is a |
| @@ -79,7 +80,6 @@ struct vmw_cmdbuf_context { · 42 unmodified lines | |||
| 79 | * frees are protected by @lock. | 80 | * frees are protected by @lock. |
| 80 | * @cmd_space: Buffer object for the command buffer space, unless we were | 81 | * @cmd_space: Buffer object for the command buffer space, unless we were |
| 81 | * able to make a contigous coherent DMA memory allocation, @handle. Immutable. | 82 | * able to make a contigous coherent DMA memory allocation, @handle. Immutable. |
| 82 | * @map_obj: Mapping state for @cmd_space. Immutable. | ||
| 83 | * @map: Pointer to command buffer space. May be a mapped buffer object or | 83 | * @map: Pointer to command buffer space. May be a mapped buffer object or |
| 84 | * a contigous coherent DMA memory allocation. Immutable. | 84 | * a contigous coherent DMA memory allocation. Immutable. |
| 85 | * @cur: Command buffer for small kernel command submissions. Protected by | 85 | * @cur: Command buffer for small kernel command submissions. Protected by |
| @@ -116,8 +116,7 @@ struct vmw_cmdbuf_man { · 30 unmodified lines | |||
| 116 | struct vmw_cmdbuf_context ctx[SVGA_CB_CONTEXT_MAX]; | 116 | struct vmw_cmdbuf_context ctx[SVGA_CB_CONTEXT_MAX]; |
| 117 | struct list_head error; | 117 | struct list_head error; |
| 118 | struct drm_mm mm; | 118 | struct drm_mm mm; |
| 119 | struct ttm_buffer_object *cmd_space; | 119 | struct vmw_bo *cmd_space; |
| 120 | struct ttm_bo_kmap_obj map_obj; | ||
| 121 | u8 *map; | 120 | u8 *map; |
| 122 | struct vmw_cmdbuf_header *cur; | 121 | struct vmw_cmdbuf_header *cur; |
| 123 | size_t cur_pos; | 122 | size_t cur_pos; |
| @@ -888,7 +887,7 @@ static int vmw_cmdbuf_space_pool(struct vmw_cmdbuf_man *man, · 764 unmodified lines | |||
| 888 | header->cmd = man->map + offset; | 887 | header->cmd = man->map + offset; |
| 889 | if (man->using_mob) { | 888 | if (man->using_mob) { |
| 890 | cb_hdr->flags = SVGA_CB_FLAG_MOB; | 889 | cb_hdr->flags = SVGA_CB_FLAG_MOB; |
| 891 | cb_hdr->ptr.mob.mobid = man->cmd_space->resource->start; | 890 | cb_hdr->ptr.mob.mobid = man->cmd_space->tbo.resource->start; |
| 892 | cb_hdr->ptr.mob.mobOffset = offset; | 891 | cb_hdr->ptr.mob.mobOffset = offset; |
| 893 | } else { | 892 | } else { |
| 894 | cb_hdr->ptr.pa = (u64)man->handle + (u64)offset; | 893 | cb_hdr->ptr.pa = (u64)man->handle + (u64)offset; |
| @@ -1221,7 +1220,6 @@ static int vmw_cmdbuf_startstop(struct vmw_cmdbuf_man *man, u32 context, · 326 unmodified lines | |||
| 1221 | int vmw_cmdbuf_set_pool_size(struct vmw_cmdbuf_man *man, size_t size) | 1220 | int vmw_cmdbuf_set_pool_size(struct vmw_cmdbuf_man *man, size_t size) |
| 1222 | { | 1221 | { |
| 1223 | struct vmw_private *dev_priv = man->dev_priv; | 1222 | struct vmw_private *dev_priv = man->dev_priv; |
| 1224 | bool dummy; | ||
| 1225 | int ret; | 1223 | int ret; |
| 1226 | 1224 | ||
| 1227 | if (man->has_pool) | 1225 | if (man->has_pool) |
| @@ -1234,6 +1232,13 @@ int vmw_cmdbuf_set_pool_size(struct vmw_cmdbuf_man *man, size_t size) · 6 unmodified lines | |||
| 1234 | if (man->map) { | 1232 | if (man->map) { |
| 1235 | man->using_mob = false; | 1233 | man->using_mob = false; |
| 1236 | } else { | 1234 | } else { |
| 1235 | struct vmw_bo_params bo_params = { | ||
| 1236 | .domain = VMW_BO_DOMAIN_MOB, | ||
| 1237 | .busy_domain = VMW_BO_DOMAIN_MOB, | ||
| 1238 | .bo_type = ttm_bo_type_kernel, | ||
| 1239 | .size = size, | ||
| 1240 | .pin = true | ||
| 1241 | }; | ||
| 1237 | /* | 1242 | /* |
| 1238 | * DMA memory failed. If we can have command buffers in a | 1243 | * DMA memory failed. If we can have command buffers in a |
| 1239 | * MOB, try to use that instead. Note that this will | 1244 | * MOB, try to use that instead. Note that this will |
| @@ -1244,19 +1249,12 @@ int vmw_cmdbuf_set_pool_size(struct vmw_cmdbuf_man *man, size_t size) · 4 unmodified lines | |||
| 1244 | !dev_priv->has_mob) | 1249 | !dev_priv->has_mob) |
| 1245 | return -ENOMEM; | 1250 | return -ENOMEM; |
| 1246 | 1251 | ||
| 1247 | ret = vmw_bo_create_kernel(dev_priv, size, | 1252 | ret = vmw_bo_create(dev_priv, &bo_params, &man->cmd_space); |
| 1248 | &vmw_mob_placement, | ||
| 1249 | &man->cmd_space); | ||
| 1250 | if (ret) | 1253 | if (ret) |
| 1251 | return ret; | 1254 | return ret; |
| 1252 | 1255 | ||
| 1253 | man->using_mob = true; | 1256 | man->map = vmw_bo_map_and_cache(man->cmd_space); |
| 1254 | ret = ttm_bo_kmap(man->cmd_space, 0, size >> PAGE_SHIFT, | 1257 | man->using_mob = man->map; |
| 1255 | &man->map_obj); | ||
| 1256 | if (ret) | ||
| 1257 | goto out_no_map; | ||
| 1258 | |||
| 1259 | man->map = ttm_kmap_obj_virtual(&man->map_obj, &dummy); | ||
| 1260 | } | 1258 | } |
| 1261 | 1259 | ||
| 1262 | man->size = size; | 1260 | man->size = size; |
| @@ -1276,14 +1274,6 @@ int vmw_cmdbuf_set_pool_size(struct vmw_cmdbuf_man *man, size_t size) · 13 unmodified lines | |||
| 1276 | (man->using_mob) ? "MOB" : "DMA"); | 1274 | (man->using_mob) ? "MOB" : "DMA"); |
| 1277 | 1275 | ||
| 1278 | return 0; | 1276 | return 0; |
| 1279 | |||
| 1280 | out_no_map: | ||
| 1281 | if (man->using_mob) { | ||
| 1282 | ttm_bo_put(man->cmd_space); | ||
| 1283 | man->cmd_space = NULL; | ||
| 1284 | } | ||
| 1285 | |||
| 1286 | return ret; | ||
| 1287 | } | 1277 | } |
| 1288 | 1278 | ||
| 1289 | /** | 1279 | /** |
| @@ -1382,14 +1372,11 @@ void vmw_cmdbuf_remove_pool(struct vmw_cmdbuf_man *man) · 92 unmodified lines | |||
| 1382 | man->has_pool = false; | 1372 | man->has_pool = false; |
| 1383 | man->default_size = VMW_CMDBUF_INLINE_SIZE; | 1373 | man->default_size = VMW_CMDBUF_INLINE_SIZE; |
| 1384 | (void) vmw_cmdbuf_idle(man, false, 10*HZ); | 1374 | (void) vmw_cmdbuf_idle(man, false, 10*HZ); |
| 1385 | if (man->using_mob) { | 1375 | if (man->using_mob) |
| 1386 | (void) ttm_bo_kunmap(&man->map_obj); | 1376 | vmw_bo_unreference(&man->cmd_space); |
| 1387 | ttm_bo_put(man->cmd_space); | 1377 | else |
| 1388 | man->cmd_space = NULL; | ||
| 1389 | } else { | ||
| 1390 | dma_free_coherent(man->dev_priv->drm.dev, | 1378 | dma_free_coherent(man->dev_priv->drm.dev, |
| 1391 | man->size, man->map, man->handle); | 1379 | man->size, man->map, man->handle); |
| 1392 | } | ||
| 1393 | } | 1380 | } |
| 1394 | 1381 | ||
| 1395 | /** | 1382 | /** |
| @@ -1,7 +1,7 @@ | |||
| 1 | // SPDX-License-Identifier: GPL-2.0 OR MIT | 1 | // SPDX-License-Identifier: GPL-2.0 OR MIT |
| 2 | /************************************************************************** | 2 | /************************************************************************** |
| 3 | * | 3 | * |
| 4 | * Copyright 2009-2015 VMware, Inc., Palo Alto, CA., USA | 4 | * Copyright 2009-2023 VMware, Inc., Palo Alto, CA., USA |
| 5 | * | 5 | * |
| 6 | * Permission is hereby granted, free of charge, to any person obtaining a | 6 | * Permission is hereby granted, free of charge, to any person obtaining a |
| 7 | * copy of this software and associated documentation files (the | 7 | * copy of this software and associated documentation files (the |
| @@ -27,9 +27,10 @@ · 19 unmodified lines | |||
| 27 | 27 | ||
| 28 | #include <drm/ttm/ttm_placement.h> | 28 | #include <drm/ttm/ttm_placement.h> |
| 29 | 29 | ||
| 30 | #include "vmwgfx_binding.h" | ||
| 31 | #include "vmwgfx_bo.h" | ||
| 30 | #include "vmwgfx_drv.h" | 32 | #include "vmwgfx_drv.h" |
| 31 | #include "vmwgfx_resource_priv.h" | 33 | #include "vmwgfx_resource_priv.h" |
| 32 | #include "vmwgfx_binding.h" | ||
| 33 | 34 | ||
| 34 | struct vmw_user_context { | 35 | struct vmw_user_context { |
| 35 | struct ttm_base_object base; | 36 | struct ttm_base_object base; |
| @@ -38,7 +39,7 @@ struct vmw_user_context { · 2 unmodified lines | |||
| 38 | struct vmw_cmdbuf_res_manager *man; | 39 | struct vmw_cmdbuf_res_manager *man; |
| 39 | struct vmw_resource *cotables[SVGA_COTABLE_MAX]; | 40 | struct vmw_resource *cotables[SVGA_COTABLE_MAX]; |
| 40 | spinlock_t cotable_lock; | 41 | spinlock_t cotable_lock; |
| 41 | struct vmw_buffer_object *dx_query_mob; | 42 | struct vmw_bo *dx_query_mob; |
| 42 | }; | 43 | }; |
| 43 | 44 | ||
| 44 | static void vmw_user_context_free(struct vmw_resource *res); | 45 | static void vmw_user_context_free(struct vmw_resource *res); |
| @@ -72,10 +73,11 @@ const struct vmw_user_resource_conv *user_context_converter = · 27 unmodified lines | |||
| 72 | 73 | ||
| 73 | static const struct vmw_res_func vmw_legacy_context_func = { | 74 | static const struct vmw_res_func vmw_legacy_context_func = { |
| 74 | .res_type = vmw_res_context, | 75 | .res_type = vmw_res_context, |
| 75 | .needs_backup = false, | 76 | .needs_guest_memory = false, |
| 76 | .may_evict = false, | 77 | .may_evict = false, |
| 77 | .type_name = "legacy contexts", | 78 | .type_name = "legacy contexts", |
| 78 | .backup_placement = NULL, | 79 | .domain = VMW_BO_DOMAIN_SYS, |
| 80 | .busy_domain = VMW_BO_DOMAIN_SYS, | ||
| 79 | .create = NULL, | 81 | .create = NULL, |
| 80 | .destroy = NULL, | 82 | .destroy = NULL, |
| 81 | .bind = NULL, | 83 | .bind = NULL, |
| @@ -84,12 +86,13 @@ static const struct vmw_res_func vmw_legacy_context_func = { · 2 unmodified lines | |||
| 84 | 86 | ||
| 85 | static const struct vmw_res_func vmw_gb_context_func = { | 87 | static const struct vmw_res_func vmw_gb_context_func = { |
| 86 | .res_type = vmw_res_context, | 88 | .res_type = vmw_res_context, |
| 87 | .needs_backup = true, | 89 | .needs_guest_memory = true, |
| 88 | .may_evict = true, | 90 | .may_evict = true, |
| 89 | .prio = 3, | 91 | .prio = 3, |
| 90 | .dirty_prio = 3, | 92 | .dirty_prio = 3, |
| 91 | .type_name = "guest backed contexts", | 93 | .type_name = "guest backed contexts", |
| 92 | .backup_placement = &vmw_mob_placement, | 94 | .domain = VMW_BO_DOMAIN_MOB, |
| 95 | .busy_domain = VMW_BO_DOMAIN_MOB, | ||
| 93 | .create = vmw_gb_context_create, | 96 | .create = vmw_gb_context_create, |
| 94 | .destroy = vmw_gb_context_destroy, | 97 | .destroy = vmw_gb_context_destroy, |
| 95 | .bind = vmw_gb_context_bind, | 98 | .bind = vmw_gb_context_bind, |
| @@ -98,12 +101,13 @@ static const struct vmw_res_func vmw_gb_context_func = { · 2 unmodified lines | |||
| 98 | 101 | ||
| 99 | static const struct vmw_res_func vmw_dx_context_func = { | 102 | static const struct vmw_res_func vmw_dx_context_func = { |
| 100 | .res_type = vmw_res_dx_context, | 103 | .res_type = vmw_res_dx_context, |
| 101 | .needs_backup = true, | 104 | .needs_guest_memory = true, |
| 102 | .may_evict = true, | 105 | .may_evict = true, |
| 103 | .prio = 3, | 106 | .prio = 3, |
| 104 | .dirty_prio = 3, | 107 | .dirty_prio = 3, |
| 105 | .type_name = "dx contexts", | 108 | .type_name = "dx contexts", |
| 106 | .backup_placement = &vmw_mob_placement, | 109 | .domain = VMW_BO_DOMAIN_MOB, |
| 110 | .busy_domain = VMW_BO_DOMAIN_MOB, | ||
| 107 | .create = vmw_dx_context_create, | 111 | .create = vmw_dx_context_create, |
| 108 | .destroy = vmw_dx_context_destroy, | 112 | .destroy = vmw_dx_context_destroy, |
| 109 | .bind = vmw_dx_context_bind, | 113 | .bind = vmw_dx_context_bind, |
| @@ -182,7 +186,7 @@ static int vmw_gb_context_init(struct vmw_private *dev_priv, · 72 unmodified lines | |||
| 182 | struct vmw_user_context *uctx = | 186 | struct vmw_user_context *uctx = |
| 183 | container_of(res, struct vmw_user_context, res); | 187 | container_of(res, struct vmw_user_context, res); |
| 184 | 188 | ||
| 185 | res->backup_size = (dx ? sizeof(SVGADXContextMobFormat) : | 189 | res->guest_memory_size = (dx ? sizeof(SVGADXContextMobFormat) : |
| 186 | sizeof(SVGAGBContextData)); | 190 | sizeof(SVGAGBContextData)); |
| 187 | ret = vmw_resource_init(dev_priv, res, true, | 191 | ret = vmw_resource_init(dev_priv, res, true, |
| 188 | res_free, | 192 | res_free, |
| @@ -354,8 +358,8 @@ static int vmw_gb_context_bind(struct vmw_resource *res, · 165 unmodified lines | |||
| 354 | cmd->header.size = sizeof(cmd->body); | 358 | cmd->header.size = sizeof(cmd->body); |
| 355 | cmd->body.cid = res->id; | 359 | cmd->body.cid = res->id; |
| 356 | cmd->body.mobid = bo->resource->start; | 360 | cmd->body.mobid = bo->resource->start; |
| 357 | cmd->body.validContents = res->backup_dirty; | 361 | cmd->body.validContents = res->guest_memory_dirty; |
| 358 | res->backup_dirty = false; | 362 | res->guest_memory_dirty = false; |
| 359 | vmw_cmd_commit(dev_priv, sizeof(*cmd)); | 363 | vmw_cmd_commit(dev_priv, sizeof(*cmd)); |
| 360 | 364 | ||
| 361 | return 0; | 365 | return 0; |
| @@ -521,8 +525,8 @@ static int vmw_dx_context_bind(struct vmw_resource *res, · 159 unmodified lines | |||
| 521 | cmd->header.size = sizeof(cmd->body); | 525 | cmd->header.size = sizeof(cmd->body); |
| 522 | cmd->body.cid = res->id; | 526 | cmd->body.cid = res->id; |
| 523 | cmd->body.mobid = bo->resource->start; | 527 | cmd->body.mobid = bo->resource->start; |
| 524 | cmd->body.validContents = res->backup_dirty; | 528 | cmd->body.validContents = res->guest_memory_dirty; |
| 525 | res->backup_dirty = false; | 529 | res->guest_memory_dirty = false; |
| 526 | vmw_cmd_commit(dev_priv, sizeof(*cmd)); | 530 | vmw_cmd_commit(dev_priv, sizeof(*cmd)); |
| 527 | 531 | ||
| 528 | 532 | ||
| @@ -853,7 +857,7 @@ vmw_context_binding_state(struct vmw_resource *ctx) · 324 unmodified lines | |||
| 853 | * specified in the parameter. 0 otherwise. | 857 | * specified in the parameter. 0 otherwise. |
| 854 | */ | 858 | */ |
| 855 | int vmw_context_bind_dx_query(struct vmw_resource *ctx_res, | 859 | int vmw_context_bind_dx_query(struct vmw_resource *ctx_res, |
| 856 | struct vmw_buffer_object *mob) | 860 | struct vmw_bo *mob) |
| 857 | { | 861 | { |
| 858 | struct vmw_user_context *uctx = | 862 | struct vmw_user_context *uctx = |
| 859 | container_of(ctx_res, struct vmw_user_context, res); | 863 | container_of(ctx_res, struct vmw_user_context, res); |
| @@ -885,7 +889,7 @@ int vmw_context_bind_dx_query(struct vmw_resource *ctx_res, · 25 unmodified lines | |||
| 885 | * | 889 | * |
| 886 | * @ctx_res: The context resource | 890 | * @ctx_res: The context resource |
| 887 | */ | 891 | */ |
| 888 | struct vmw_buffer_object * | 892 | struct vmw_bo * |
| 889 | vmw_context_get_dx_query_mob(struct vmw_resource *ctx_res) | 893 | vmw_context_get_dx_query_mob(struct vmw_resource *ctx_res) |
| 890 | { | 894 | { |
| 891 | struct vmw_user_context *uctx = | 895 | struct vmw_user_context *uctx = |
| @@ -1,7 +1,7 @@ | |||
| 1 | // SPDX-License-Identifier: GPL-2.0 OR MIT | 1 | // SPDX-License-Identifier: GPL-2.0 OR MIT |
| 2 | /************************************************************************** | 2 | /************************************************************************** |
| 3 | * | 3 | * |
| 4 | * Copyright 2014-2015 VMware, Inc., Palo Alto, CA., USA | 4 | * Copyright 2014-2023 VMware, Inc., Palo Alto, CA., USA |
| 5 | * | 5 | * |
| 6 | * Permission is hereby granted, free of charge, to any person obtaining a | 6 | * Permission is hereby granted, free of charge, to any person obtaining a |
| 7 | * copy of this software and associated documentation files (the | 7 | * copy of this software and associated documentation files (the |
| @@ -30,13 +30,14 @@ · 22 unmodified lines | |||
| 30 | * whenever the backing MOB is evicted. | 30 | * whenever the backing MOB is evicted. |
| 31 | */ | 31 | */ |
| 32 | 32 | ||
| 33 | #include <drm/ttm/ttm_placement.h> | 33 | #include "vmwgfx_bo.h" |
| 34 | |||
| 35 | #include "vmwgfx_drv.h" | 34 | #include "vmwgfx_drv.h" |
| 36 | #include "vmwgfx_mksstat.h" | 35 | #include "vmwgfx_mksstat.h" |
| 37 | #include "vmwgfx_resource_priv.h" | 36 | #include "vmwgfx_resource_priv.h" |
| 38 | #include "vmwgfx_so.h" | 37 | #include "vmwgfx_so.h" |
| 39 | 38 | ||
| 39 | #include <drm/ttm/ttm_placement.h> | ||
| 40 | |||
| 40 | /** | 41 | /** |
| 41 | * struct vmw_cotable - Context Object Table resource | 42 | * struct vmw_cotable - Context Object Table resource |
| 42 | * | 43 | * |
| @@ -130,12 +131,13 @@ static int vmw_cotable_destroy(struct vmw_resource *res); · 87 unmodified lines | |||
| 130 | 131 | ||
| 131 | static const struct vmw_res_func vmw_cotable_func = { | 132 | static const struct vmw_res_func vmw_cotable_func = { |
| 132 | .res_type = vmw_res_cotable, | 133 | .res_type = vmw_res_cotable, |
| 133 | .needs_backup = true, | 134 | .needs_guest_memory = true, |
| 134 | .may_evict = true, | 135 | .may_evict = true, |
| 135 | .prio = 3, | 136 | .prio = 3, |
| 136 | .dirty_prio = 3, | 137 | .dirty_prio = 3, |
| 137 | .type_name = "context guest backed object tables", | 138 | .type_name = "context guest backed object tables", |
| 138 | .backup_placement = &vmw_mob_placement, | 139 | .domain = VMW_BO_DOMAIN_MOB, |
| 140 | .busy_domain = VMW_BO_DOMAIN_MOB, | ||
| 139 | .create = vmw_cotable_create, | 141 | .create = vmw_cotable_create, |
| 140 | .destroy = vmw_cotable_destroy, | 142 | .destroy = vmw_cotable_destroy, |
| 141 | .bind = vmw_cotable_bind, | 143 | .bind = vmw_cotable_bind, |
| @@ -180,7 +182,7 @@ static int vmw_cotable_unscrub(struct vmw_resource *res) · 38 unmodified lines | |||
| 180 | { | 182 | { |
| 181 | struct vmw_cotable *vcotbl = vmw_cotable(res); | 183 | struct vmw_cotable *vcotbl = vmw_cotable(res); |
| 182 | struct vmw_private *dev_priv = res->dev_priv; | 184 | struct vmw_private *dev_priv = res->dev_priv; |
| 183 | struct ttm_buffer_object *bo = &res->backup->base; | 185 | struct ttm_buffer_object *bo = &res->guest_memory_bo->tbo; |
| 184 | struct { | 186 | struct { |
| 185 | SVGA3dCmdHeader header; | 187 | SVGA3dCmdHeader header; |
| 186 | SVGA3dCmdDXSetCOTable body; | 188 | SVGA3dCmdDXSetCOTable body; |
| @@ -228,7 +230,7 @@ static int vmw_cotable_bind(struct vmw_resource *res, · 41 unmodified lines | |||
| 228 | * take the opportunity to correct the value here so that it's not | 230 | * take the opportunity to correct the value here so that it's not |
| 229 | * misused in the future. | 231 | * misused in the future. |
| 230 | */ | 232 | */ |
| 231 | val_buf->bo = &res->backup->base; | 233 | val_buf->bo = &res->guest_memory_bo->tbo; |
| 232 | 234 | ||
| 233 | return vmw_cotable_unscrub(res); | 235 | return vmw_cotable_unscrub(res); |
| 234 | } | 236 | } |
| @@ -289,7 +291,7 @@ int vmw_cotable_scrub(struct vmw_resource *res, bool readback) · 54 unmodified lines | |||
| 289 | cmd0->body.cid = vcotbl->ctx->id; | 291 | cmd0->body.cid = vcotbl->ctx->id; |
| 290 | cmd0->body.type = vcotbl->type; | 292 | cmd0->body.type = vcotbl->type; |
| 291 | cmd1 = (void *) &cmd0[1]; | 293 | cmd1 = (void *) &cmd0[1]; |
| 292 | vcotbl->size_read_back = res->backup_size; | 294 | vcotbl->size_read_back = res->guest_memory_size; |
| 293 | } | 295 | } |
| 294 | cmd1->header.id = SVGA_3D_CMD_DX_SET_COTABLE; | 296 | cmd1->header.id = SVGA_3D_CMD_DX_SET_COTABLE; |
| 295 | cmd1->header.size = sizeof(cmd1->body); | 297 | cmd1->header.size = sizeof(cmd1->body); |
| @@ -371,12 +373,12 @@ static int vmw_cotable_readback(struct vmw_resource *res) · 75 unmodified lines | |||
| 371 | cmd->header.size = sizeof(cmd->body); | 373 | cmd->header.size = sizeof(cmd->body); |
| 372 | cmd->body.cid = vcotbl->ctx->id; | 374 | cmd->body.cid = vcotbl->ctx->id; |
| 373 | cmd->body.type = vcotbl->type; | 375 | cmd->body.type = vcotbl->type; |
| 374 | vcotbl->size_read_back = res->backup_size; | 376 | vcotbl->size_read_back = res->guest_memory_size; |
| 375 | vmw_cmd_commit(dev_priv, sizeof(*cmd)); | 377 | vmw_cmd_commit(dev_priv, sizeof(*cmd)); |
| 376 | } | 378 | } |
| 377 | 379 | ||
| 378 | (void) vmw_execbuf_fence_commands(NULL, dev_priv, &fence, NULL); | 380 | (void) vmw_execbuf_fence_commands(NULL, dev_priv, &fence, NULL); |
| 379 | vmw_bo_fence_single(&res->backup->base, fence); | 381 | vmw_bo_fence_single(&res->guest_memory_bo->tbo, fence); |
| 380 | vmw_fence_obj_unreference(&fence); | 382 | vmw_fence_obj_unreference(&fence); |
| 381 | 383 | ||
| 382 | return 0; | 384 | return 0; |
| @@ -399,14 +401,21 @@ static int vmw_cotable_resize(struct vmw_resource *res, size_t new_size) · 16 unmodified lines | |||
| 399 | struct ttm_operation_ctx ctx = { false, false }; | 401 | struct ttm_operation_ctx ctx = { false, false }; |
| 400 | struct vmw_private *dev_priv = res->dev_priv; | 402 | struct vmw_private *dev_priv = res->dev_priv; |
| 401 | struct vmw_cotable *vcotbl = vmw_cotable(res); | 403 | struct vmw_cotable *vcotbl = vmw_cotable(res); |
| 402 | struct vmw_buffer_object *buf, *old_buf = res->backup; | 404 | struct vmw_bo *buf, *old_buf = res->guest_memory_bo; |
| 403 | struct ttm_buffer_object *bo, *old_bo = &res->backup->base; | 405 | struct ttm_buffer_object *bo, *old_bo = &res->guest_memory_bo->tbo; |
| 404 | size_t old_size = res->backup_size; | 406 | size_t old_size = res->guest_memory_size; |
| 405 | size_t old_size_read_back = vcotbl->size_read_back; | 407 | size_t old_size_read_back = vcotbl->size_read_back; |
| 406 | size_t cur_size_read_back; | 408 | size_t cur_size_read_back; |
| 407 | struct ttm_bo_kmap_obj old_map, new_map; | 409 | struct ttm_bo_kmap_obj old_map, new_map; |
| 408 | int ret; | 410 | int ret; |
| 409 | size_t i; | 411 | size_t i; |
| 412 | struct vmw_bo_params bo_params = { | ||
| 413 | .domain = VMW_BO_DOMAIN_MOB, | ||
| 414 | .busy_domain = VMW_BO_DOMAIN_MOB, | ||
| 415 | .bo_type = ttm_bo_type_device, | ||
| 416 | .size = new_size, | ||
| 417 | .pin = true | ||
| 418 | }; | ||
| 410 | 419 | ||
| 411 | MKS_STAT_TIME_DECL(MKSSTAT_KERN_COTABLE_RESIZE); | 420 | MKS_STAT_TIME_DECL(MKSSTAT_KERN_COTABLE_RESIZE); |
| 412 | MKS_STAT_TIME_PUSH(MKSSTAT_KERN_COTABLE_RESIZE); | 421 | MKS_STAT_TIME_PUSH(MKSSTAT_KERN_COTABLE_RESIZE); |
| @@ -423,14 +432,13 @@ static int vmw_cotable_resize(struct vmw_resource *res, size_t new_size) · 10 unmodified lines | |||
| 423 | * for the new COTable. Initially pin the buffer object to make sure | 432 | * for the new COTable. Initially pin the buffer object to make sure |
| 424 | * we can use tryreserve without failure. | 433 | * we can use tryreserve without failure. |
| 425 | */ | 434 | */ |
| 426 | ret = vmw_bo_create(dev_priv, new_size, &vmw_mob_placement, | 435 | ret = vmw_bo_create(dev_priv, &bo_params, &buf); |
| 427 | true, true, vmw_bo_bo_free, &buf); | ||
| 428 | if (ret) { | 436 | if (ret) { |
| 429 | DRM_ERROR("Failed initializing new cotable MOB.\n"); | 437 | DRM_ERROR("Failed initializing new cotable MOB.\n"); |
| 430 | goto out_done; | 438 | goto out_done; |
| 431 | } | 439 | } |
| 432 | 440 | ||
| 433 | bo = &buf->base; | 441 | bo = &buf->tbo; |
| 434 | WARN_ON_ONCE(ttm_bo_reserve(bo, false, true, NULL)); | 442 | WARN_ON_ONCE(ttm_bo_reserve(bo, false, true, NULL)); |
| 435 | 443 | ||
| 436 | ret = ttm_bo_wait(old_bo, false, false); | 444 | ret = ttm_bo_wait(old_bo, false, false); |
| @@ -464,15 +472,18 @@ static int vmw_cotable_resize(struct vmw_resource *res, size_t new_size) · 27 unmodified lines | |||
| 464 | } | 472 | } |
| 465 | 473 | ||
| 466 | /* Unpin new buffer, and switch backup buffers. */ | 474 | /* Unpin new buffer, and switch backup buffers. */ |
| 467 | ret = ttm_bo_validate(bo, &vmw_mob_placement, &ctx); | 475 | vmw_bo_placement_set(buf, |
| 476 | VMW_BO_DOMAIN_MOB, | ||
| 477 | VMW_BO_DOMAIN_MOB); | ||
| 478 | ret = ttm_bo_validate(bo, &buf->placement, &ctx); | ||
| 468 | if (unlikely(ret != 0)) { | 479 | if (unlikely(ret != 0)) { |
| 469 | DRM_ERROR("Failed validating new COTable backup buffer.\n"); | 480 | DRM_ERROR("Failed validating new COTable backup buffer.\n"); |
| 470 | goto out_wait; | 481 | goto out_wait; |
| 471 | } | 482 | } |
| 472 | 483 | ||
| 473 | vmw_resource_mob_detach(res); | 484 | vmw_resource_mob_detach(res); |
| 474 | res->backup = buf; | 485 | res->guest_memory_bo = buf; |
| 475 | res->backup_size = new_size; | 486 | res->guest_memory_size = new_size; |
| 476 | vcotbl->size_read_back = cur_size_read_back; | 487 | vcotbl->size_read_back = cur_size_read_back; |
| 477 | 488 | ||
| 478 | /* | 489 | /* |
| @@ -482,8 +493,8 @@ static int vmw_cotable_resize(struct vmw_resource *res, size_t new_size) · 3 unmodified lines | |||
| 482 | ret = vmw_cotable_unscrub(res); | 493 | ret = vmw_cotable_unscrub(res); |
| 483 | if (ret) { | 494 | if (ret) { |
| 484 | DRM_ERROR("Failed switching COTable backup buffer.\n"); | 495 | DRM_ERROR("Failed switching COTable backup buffer.\n"); |
| 485 | res->backup = old_buf; | 496 | res->guest_memory_bo = old_buf; |
| 486 | res->backup_size = old_size; | 497 | res->guest_memory_size = old_size; |
| 487 | vcotbl->size_read_back = old_size_read_back; | 498 | vcotbl->size_read_back = old_size_read_back; |
| 488 | vmw_resource_mob_attach(res); | 499 | vmw_resource_mob_attach(res); |
| 489 | goto out_wait; | 500 | goto out_wait; |
| @@ -498,7 +509,7 @@ static int vmw_cotable_resize(struct vmw_resource *res, size_t new_size) · 8 unmodified lines | |||
| 498 | if (unlikely(ret)) | 509 | if (unlikely(ret)) |
| 499 | goto out_wait; | 510 | goto out_wait; |
| 500 | 511 | ||
| 501 | /* Release the pin acquired in vmw_bo_init */ | 512 | /* Release the pin acquired in vmw_bo_create */ |
| 502 | ttm_bo_unpin(bo); | 513 | ttm_bo_unpin(bo); |
| 503 | 514 | ||
| 504 | MKS_STAT_TIME_POP(MKSSTAT_KERN_COTABLE_RESIZE); | 515 | MKS_STAT_TIME_POP(MKSSTAT_KERN_COTABLE_RESIZE); |
| @@ -533,7 +544,7 @@ out_done: · 28 unmodified lines | |||
| 533 | static int vmw_cotable_create(struct vmw_resource *res) | 544 | static int vmw_cotable_create(struct vmw_resource *res) |
| 534 | { | 545 | { |
| 535 | struct vmw_cotable *vcotbl = vmw_cotable(res); | 546 | struct vmw_cotable *vcotbl = vmw_cotable(res); |
| 536 | size_t new_size = res->backup_size; | 547 | size_t new_size = res->guest_memory_size; |
| 537 | size_t needed_size; | 548 | size_t needed_size; |
| 538 | int ret; | 549 | int ret; |
| 539 | 550 | ||
| @@ -542,7 +553,7 @@ static int vmw_cotable_create(struct vmw_resource *res) · 2 unmodified lines | |||
| 542 | while (needed_size > new_size) | 553 | while (needed_size > new_size) |
| 543 | new_size *= 2; | 554 | new_size *= 2; |
| 544 | 555 | ||
| 545 | if (likely(new_size <= res->backup_size)) { | 556 | if (likely(new_size <= res->guest_memory_size)) { |
| 546 | if (vcotbl->scrubbed && vmw_resource_mob_attached(res)) { | 557 | if (vcotbl->scrubbed && vmw_resource_mob_attached(res)) { |
| 547 | ret = vmw_cotable_unscrub(res); | 558 | ret = vmw_cotable_unscrub(res); |
| 548 | if (ret) | 559 | if (ret) |
| @@ -606,12 +617,12 @@ struct vmw_resource *vmw_cotable_alloc(struct vmw_private *dev_priv, · 57 unmodified lines | |||
| 606 | 617 | ||
| 607 | INIT_LIST_HEAD(&vcotbl->resource_list); | 618 | INIT_LIST_HEAD(&vcotbl->resource_list); |
| 608 | vcotbl->res.id = type; | 619 | vcotbl->res.id = type; |
| 609 | vcotbl->res.backup_size = PAGE_SIZE; | 620 | vcotbl->res.guest_memory_size = PAGE_SIZE; |
| 610 | num_entries = PAGE_SIZE / co_info[type].size; | 621 | num_entries = PAGE_SIZE / co_info[type].size; |
| 611 | if (num_entries < co_info[type].min_initial_entries) { | 622 | if (num_entries < co_info[type].min_initial_entries) { |
| 612 | vcotbl->res.backup_size = co_info[type].min_initial_entries * | 623 | vcotbl->res.guest_memory_size = co_info[type].min_initial_entries * |
| 613 | co_info[type].size; | 624 | co_info[type].size; |
| 614 | vcotbl->res.backup_size = PFN_ALIGN(vcotbl->res.backup_size); | 625 | vcotbl->res.guest_memory_size = PFN_ALIGN(vcotbl->res.guest_memory_size); |
| 615 | } | 626 | } |
| 616 | 627 | ||
| 617 | vcotbl->scrubbed = true; | 628 | vcotbl->scrubbed = true; |
| @@ -1,7 +1,7 @@ | |||
| 1 | // SPDX-License-Identifier: GPL-2.0 OR MIT | 1 | // SPDX-License-Identifier: GPL-2.0 OR MIT |
| 2 | /************************************************************************** | 2 | /************************************************************************** |
| 3 | * | 3 | * |
| 4 | * Copyright 2009-2022 VMware, Inc., Palo Alto, CA., USA | 4 | * Copyright 2009-2023 VMware, Inc., Palo Alto, CA., USA |
| 5 | * | 5 | * |
| 6 | * Permission is hereby granted, free of charge, to any person obtaining a | 6 | * Permission is hereby granted, free of charge, to any person obtaining a |
| 7 | * copy of this software and associated documentation files (the | 7 | * copy of this software and associated documentation files (the |
| @@ -28,9 +28,10 @@ · 20 unmodified lines | |||
| 28 | 28 | ||
| 29 | #include "vmwgfx_drv.h" | 29 | #include "vmwgfx_drv.h" |
| 30 | 30 | ||
| 31 | #include "vmwgfx_bo.h" | ||
| 32 | #include "vmwgfx_binding.h" | ||
| 31 | #include "vmwgfx_devcaps.h" | 33 | #include "vmwgfx_devcaps.h" |
| 32 | #include "vmwgfx_mksstat.h" | 34 | #include "vmwgfx_mksstat.h" |
| 33 | #include "vmwgfx_binding.h" | ||
| 34 | #include "ttm_object.h" | 35 | #include "ttm_object.h" |
| 35 | 36 | ||
| 36 | #include <drm/drm_aperture.h> | 37 | #include <drm/drm_aperture.h> |
| @@ -386,27 +387,32 @@ static void vmw_print_sm_type(struct vmw_private *dev_priv) · 349 unmodified lines | |||
| 386 | static int vmw_dummy_query_bo_create(struct vmw_private *dev_priv) | 387 | static int vmw_dummy_query_bo_create(struct vmw_private *dev_priv) |
| 387 | { | 388 | { |
| 388 | int ret; | 389 | int ret; |
| 389 | struct vmw_buffer_object *vbo; | 390 | struct vmw_bo *vbo; |
| 390 | struct ttm_bo_kmap_obj map; | 391 | struct ttm_bo_kmap_obj map; |
| 391 | volatile SVGA3dQueryResult *result; | 392 | volatile SVGA3dQueryResult *result; |
| 392 | bool dummy; | 393 | bool dummy; |
| 394 | struct vmw_bo_params bo_params = { | ||
| 395 | .domain = VMW_BO_DOMAIN_SYS, | ||
| 396 | .busy_domain = VMW_BO_DOMAIN_SYS, | ||
| 397 | .bo_type = ttm_bo_type_kernel, | ||
| 398 | .size = PAGE_SIZE, | ||
| 399 | .pin = true | ||
| 400 | }; | ||
| 393 | 401 | ||
| 394 | /* | 402 | /* |
| 395 | * Create the vbo as pinned, so that a tryreserve will | 403 | * Create the vbo as pinned, so that a tryreserve will |
| 396 | * immediately succeed. This is because we're the only | 404 | * immediately succeed. This is because we're the only |
| 397 | * user of the bo currently. | 405 | * user of the bo currently. |
| 398 | */ | 406 | */ |
| 399 | ret = vmw_bo_create(dev_priv, PAGE_SIZE, | 407 | ret = vmw_bo_create(dev_priv, &bo_params, &vbo); |
| 400 | &vmw_sys_placement, false, true, | ||
| 401 | &vmw_bo_bo_free, &vbo); | ||
| 402 | if (unlikely(ret != 0)) | 408 | if (unlikely(ret != 0)) |
| 403 | return ret; | 409 | return ret; |
| 404 | 410 | ||
| 405 | ret = ttm_bo_reserve(&vbo->base, false, true, NULL); | 411 | ret = ttm_bo_reserve(&vbo->tbo, false, true, NULL); |
| 406 | BUG_ON(ret != 0); | 412 | BUG_ON(ret != 0); |
| 407 | vmw_bo_pin_reserved(vbo, true); | 413 | vmw_bo_pin_reserved(vbo, true); |
| 408 | 414 | ||
| 409 | ret = ttm_bo_kmap(&vbo->base, 0, 1, &map); | 415 | ret = ttm_bo_kmap(&vbo->tbo, 0, 1, &map); |
| 410 | if (likely(ret == 0)) { | 416 | if (likely(ret == 0)) { |
| 411 | result = ttm_kmap_obj_virtual(&map, &dummy); | 417 | result = ttm_kmap_obj_virtual(&map, &dummy); |
| 412 | result->totalSize = sizeof(*result); | 418 | result->totalSize = sizeof(*result); |
| @@ -415,7 +421,7 @@ static int vmw_dummy_query_bo_create(struct vmw_private *dev_priv) · 2 unmodified lines | |||
| 415 | ttm_bo_kunmap(&map); | 421 | ttm_bo_kunmap(&map); |
| 416 | } | 422 | } |
| 417 | vmw_bo_pin_reserved(vbo, false); | 423 | vmw_bo_pin_reserved(vbo, false); |
| 418 | ttm_bo_unreserve(&vbo->base); | 424 | ttm_bo_unreserve(&vbo->tbo); |
| 419 | 425 | ||
| 420 | if (unlikely(ret != 0)) { | 426 | if (unlikely(ret != 0)) { |
| 421 | DRM_ERROR("Dummy query buffer map failed.\n"); | 427 | DRM_ERROR("Dummy query buffer map failed.\n"); |
| @@ -1565,7 +1571,7 @@ static const struct file_operations vmwgfx_driver_fops = { · 1143 unmodified lines | |||
| 1565 | .open = drm_open, | 1571 | .open = drm_open, |
| 1566 | .release = drm_release, | 1572 | .release = drm_release, |
| 1567 | .unlocked_ioctl = vmw_unlocked_ioctl, | 1573 | .unlocked_ioctl = vmw_unlocked_ioctl, |
| 1568 | .mmap = vmw_mmap, | 1574 | .mmap = drm_gem_mmap, |
| 1569 | .poll = drm_poll, | 1575 | .poll = drm_poll, |
| 1570 | .read = drm_read, | 1576 | .read = drm_read, |
| 1571 | #if defined(CONFIG_COMPAT) | 1577 | #if defined(CONFIG_COMPAT) |
| @@ -1,7 +1,7 @@ | |||
| 1 | /* SPDX-License-Identifier: GPL-2.0 OR MIT */ | 1 | /* SPDX-License-Identifier: GPL-2.0 OR MIT */ |
| 2 | /************************************************************************** | 2 | /************************************************************************** |
| 3 | * | 3 | * |
| 4 | * Copyright 2009-2022 VMware, Inc., Palo Alto, CA., USA | 4 | * Copyright 2009-2023 VMware, Inc., Palo Alto, CA., USA |
| 5 | * | 5 | * |
| 6 | * Permission is hereby granted, free of charge, to any person obtaining a | 6 | * Permission is hereby granted, free of charge, to any person obtaining a |
| 7 | * copy of this software and associated documentation files (the | 7 | * copy of this software and associated documentation files (the |
| @@ -117,32 +117,6 @@ struct vmwgfx_hash_item { · 109 unmodified lines | |||
| 117 | unsigned long key; | 117 | unsigned long key; |
| 118 | }; | 118 | }; |
| 119 | 119 | ||
| 120 | /** | ||
| 121 | * struct vmw_buffer_object - TTM buffer object with vmwgfx additions | ||
| 122 | * @base: The TTM buffer object | ||
| 123 | * @res_tree: RB tree of resources using this buffer object as a backing MOB | ||
| 124 | * @base_mapped_count: ttm BO mapping count; used by KMS atomic helpers. | ||
| 125 | * @cpu_writers: Number of synccpu write grabs. Protected by reservation when | ||
| 126 | * increased. May be decreased without reservation. | ||
| 127 | * @dx_query_ctx: DX context if this buffer object is used as a DX query MOB | ||
| 128 | * @map: Kmap object for semi-persistent mappings | ||
| 129 | * @res_prios: Eviction priority counts for attached resources | ||
| 130 | * @dirty: structure for user-space dirty-tracking | ||
| 131 | */ | ||
| 132 | struct vmw_buffer_object { | ||
| 133 | struct ttm_buffer_object base; | ||
| 134 | struct rb_root res_tree; | ||
| 135 | /* For KMS atomic helpers: ttm bo mapping count */ | ||
| 136 | atomic_t base_mapped_count; | ||
| 137 | |||
| 138 | atomic_t cpu_writers; | ||
| 139 | /* Not ref-counted. Protected by binding_mutex */ | ||
| 140 | struct vmw_resource *dx_query_ctx; | ||
| 141 | /* Protected by reservation */ | ||
| 142 | struct ttm_bo_kmap_obj map; | ||
| 143 | u32 res_prios[TTM_MAX_BO_PRIORITY]; | ||
| 144 | struct vmw_bo_dirty *dirty; | ||
| 145 | }; | ||
| 146 | 120 | ||
| 147 | /** | 121 | /** |
| 148 | * struct vmw_validate_buffer - Carries validation info about buffers. | 122 | * struct vmw_validate_buffer - Carries validation info about buffers. |
| @@ -168,21 +142,23 @@ struct vmw_res_func; · 19 unmodified lines | |||
| 168 | * @kref: For refcounting. | 142 | * @kref: For refcounting. |
| 169 | * @dev_priv: Pointer to the device private for this resource. Immutable. | 143 | * @dev_priv: Pointer to the device private for this resource. Immutable. |
| 170 | * @id: Device id. Protected by @dev_priv::resource_lock. | 144 | * @id: Device id. Protected by @dev_priv::resource_lock. |
| 171 | * @backup_size: Backup buffer size. Immutable. | 145 | * @guest_memory_size: Guest memory buffer size. Immutable. |
| 172 | * @res_dirty: Resource contains data not yet in the backup buffer. Protected | 146 | * @res_dirty: Resource contains data not yet in the guest memory buffer. |
| 173 | * by resource reserved. | ||
| 174 | * @backup_dirty: Backup buffer contains data not yet in the HW resource. | ||
| 175 | * Protected by resource reserved. | 147 | * Protected by resource reserved. |
| 148 | * @guest_memory_dirty: Guest memory buffer contains data not yet in the HW | ||
| 149 | * resource. Protected by resource reserved. | ||
| 176 | * @coherent: Emulate coherency by tracking vm accesses. | 150 | * @coherent: Emulate coherency by tracking vm accesses. |
| 177 | * @backup: The backup buffer if any. Protected by resource reserved. | 151 | * @guest_memory_bo: The guest memory buffer if any. Protected by resource |
| 178 | * @backup_offset: Offset into the backup buffer if any. Protected by resource | 152 | * reserved. |
| 179 | * reserved. Note that only a few resource types can have a @backup_offset | 153 | * @guest_memory_offset: Offset into the guest memory buffer if any. Protected |
| 180 | * different from zero. | 154 | * by resource reserved. Note that only a few resource types can have a |
| 155 | * @guest_memory_offset different from zero. | ||
| 181 | * @pin_count: The pin count for this resource. A pinned resource has a | 156 | * @pin_count: The pin count for this resource. A pinned resource has a |
| 182 | * pin-count greater than zero. It is not on the resource LRU lists and its | 157 | * pin-count greater than zero. It is not on the resource LRU lists and its |
| 183 | * backup buffer is pinned. Hence it can't be evicted. | 158 | * guest memory buffer is pinned. Hence it can't be evicted. |
| 184 | * @func: Method vtable for this resource. Immutable. | 159 | * @func: Method vtable for this resource. Immutable. |
| 185 | * @mob_node; Node for the MOB backup rbtree. Protected by @backup reserved. | 160 | * @mob_node; Node for the MOB guest memory rbtree. Protected by |
| 161 | * @guest_memory_bo reserved. | ||
| 186 | * @lru_head: List head for the LRU list. Protected by @dev_priv::resource_lock. | 162 | * @lru_head: List head for the LRU list. Protected by @dev_priv::resource_lock. |
| 187 | * @binding_head: List head for the context binding list. Protected by | 163 | * @binding_head: List head for the context binding list. Protected by |
| 188 | * the @dev_priv::binding_mutex | 164 | * the @dev_priv::binding_mutex |
| @@ -190,18 +166,20 @@ struct vmw_res_func; · 1 unmodified line | |||
| 190 | * @hw_destroy: Callback to destroy the resource on the device, as part of | 166 | * @hw_destroy: Callback to destroy the resource on the device, as part of |
| 191 | * resource destruction. | 167 | * resource destruction. |
| 192 | */ | 168 | */ |
| 169 | struct vmw_bo; | ||
| 170 | struct vmw_bo; | ||
| 193 | struct vmw_resource_dirty; | 171 | struct vmw_resource_dirty; |
| 194 | struct vmw_resource { | 172 | struct vmw_resource { |
| 195 | struct kref kref; | 173 | struct kref kref; |
| 196 | struct vmw_private *dev_priv; | 174 | struct vmw_private *dev_priv; |
| 197 | int id; | 175 | int id; |
| 198 | u32 used_prio; | 176 | u32 used_prio; |
| 199 | unsigned long backup_size; | 177 | unsigned long guest_memory_size; |
| 200 | u32 res_dirty : 1; | 178 | u32 res_dirty : 1; |
| 201 | u32 backup_dirty : 1; | 179 | u32 guest_memory_dirty : 1; |
| 202 | u32 coherent : 1; | 180 | u32 coherent : 1; |
| 203 | struct vmw_buffer_object *backup; | 181 | struct vmw_bo *guest_memory_bo; |
| 204 | unsigned long backup_offset; | 182 | unsigned long guest_memory_offset; |
| 205 | unsigned long pin_count; | 183 | unsigned long pin_count; |
| 206 | const struct vmw_res_func *func; | 184 | const struct vmw_res_func *func; |
| 207 | struct rb_node mob_node; | 185 | struct rb_node mob_node; |
| @@ -446,7 +424,7 @@ struct vmw_sw_context{ · 238 unmodified lines | |||
| 446 | struct drm_file *filp; | 424 | struct drm_file *filp; |
| 447 | uint32_t *cmd_bounce; | 425 | uint32_t *cmd_bounce; |
| 448 | uint32_t cmd_bounce_size; | 426 | uint32_t cmd_bounce_size; |
| 449 | struct vmw_buffer_object *cur_query_bo; | 427 | struct vmw_bo *cur_query_bo; |
| 450 | struct list_head bo_relocations; | 428 | struct list_head bo_relocations; |
| 451 | struct list_head res_relocations; | 429 | struct list_head res_relocations; |
| 452 | uint32_t *buf_start; | 430 | uint32_t *buf_start; |
| @@ -458,7 +436,7 @@ struct vmw_sw_context{ · 5 unmodified lines | |||
| 458 | struct list_head staged_cmd_res; | 436 | struct list_head staged_cmd_res; |
| 459 | struct list_head ctx_list; | 437 | struct list_head ctx_list; |
| 460 | struct vmw_ctx_validation_info *dx_ctx_node; | 438 | struct vmw_ctx_validation_info *dx_ctx_node; |
| 461 | struct vmw_buffer_object *dx_query_mob; | 439 | struct vmw_bo *dx_query_mob; |
| 462 | struct vmw_resource *dx_query_ctx; | 440 | struct vmw_resource *dx_query_ctx; |
| 463 | struct vmw_cmdbuf_res_manager *man; | 441 | struct vmw_cmdbuf_res_manager *man; |
| 464 | struct vmw_validation_context *ctx; | 442 | struct vmw_validation_context *ctx; |
| @@ -492,7 +470,7 @@ struct vmw_otable_batch { · 27 unmodified lines | |||
| 492 | unsigned num_otables; | 470 | unsigned num_otables; |
| 493 | struct vmw_otable *otables; | 471 | struct vmw_otable *otables; |
| 494 | struct vmw_resource *context; | 472 | struct vmw_resource *context; |
| 495 | struct ttm_buffer_object *otable_bo; | 473 | struct vmw_bo *otable_bo; |
| 496 | }; | 474 | }; |
| 497 | 475 | ||
| 498 | enum { | 476 | enum { |
| @@ -632,8 +610,8 @@ struct vmw_private { · 133 unmodified lines | |||
| 632 | * are protected by the cmdbuf mutex. | 610 | * are protected by the cmdbuf mutex. |
| 633 | */ | 611 | */ |
| 634 | 612 | ||
| 635 | struct vmw_buffer_object *dummy_query_bo; | 613 | struct vmw_bo *dummy_query_bo; |
| 636 | struct vmw_buffer_object *pinned_bo; | 614 | struct vmw_bo *pinned_bo; |
| 637 | uint32_t query_cid; | 615 | uint32_t query_cid; |
| 638 | uint32_t query_cid_valid; | 616 | uint32_t query_cid_valid; |
| 639 | bool dummy_query_bo_pinned; | 617 | bool dummy_query_bo_pinned; |
| @@ -677,11 +655,6 @@ struct vmw_private { · 37 unmodified lines | |||
| 677 | #endif | 655 | #endif |
| 678 | }; | 656 | }; |
| 679 | 657 | ||
| 680 | static inline struct vmw_buffer_object *gem_to_vmw_bo(struct drm_gem_object *gobj) | ||
| 681 | { | ||
| 682 | return container_of((gobj), struct vmw_buffer_object, base.base); | ||
| 683 | } | ||
| 684 | |||
| 685 | static inline struct vmw_surface *vmw_res_to_srf(struct vmw_resource *res) | 658 | static inline struct vmw_surface *vmw_res_to_srf(struct vmw_resource *res) |
| 686 | { | 659 | { |
| 687 | return container_of(res, struct vmw_surface, res); | 660 | return container_of(res, struct vmw_surface, res); |
| @@ -692,6 +665,11 @@ static inline struct vmw_private *vmw_priv(struct drm_device *dev) · 4 unmodified lines | |||
| 692 | return (struct vmw_private *)dev->dev_private; | 665 | return (struct vmw_private *)dev->dev_private; |
| 693 | } | 666 | } |
| 694 | 667 | ||
| 668 | static inline struct vmw_private *vmw_priv_from_ttm(struct ttm_device *bdev) | ||
| 669 | { | ||
| 670 | return container_of(bdev, struct vmw_private, bdev); | ||
| 671 | } | ||
| 672 | |||
| 695 | static inline struct vmw_fpriv *vmw_fpriv(struct drm_file *file_priv) | 673 | static inline struct vmw_fpriv *vmw_fpriv(struct drm_file *file_priv) |
| 696 | { | 674 | { |
| 697 | return (struct vmw_fpriv *)file_priv->driver_priv; | 675 | return (struct vmw_fpriv *)file_priv->driver_priv; |
| @@ -825,7 +803,7 @@ extern int vmw_user_lookup_handle(struct vmw_private *dev_priv, · 127 unmodified lines | |||
| 825 | struct drm_file *filp, | 803 | struct drm_file *filp, |
| 826 | uint32_t handle, | 804 | uint32_t handle, |
| 827 | struct vmw_surface **out_surf, | 805 | struct vmw_surface **out_surf, |
| 828 | struct vmw_buffer_object **out_buf); | 806 | struct vmw_bo **out_buf); |
| 829 | extern int vmw_user_resource_lookup_handle( | 807 | extern int vmw_user_resource_lookup_handle( |
| 830 | struct vmw_private *dev_priv, | 808 | struct vmw_private *dev_priv, |
| 831 | struct ttm_object_file *tfile, | 809 | struct ttm_object_file *tfile, |
| @@ -844,20 +822,20 @@ extern int vmw_user_stream_lookup(struct vmw_private *dev_priv, · 12 unmodified lines | |||
| 844 | extern void vmw_resource_unreserve(struct vmw_resource *res, | 822 | extern void vmw_resource_unreserve(struct vmw_resource *res, |
| 845 | bool dirty_set, | 823 | bool dirty_set, |
| 846 | bool dirty, | 824 | bool dirty, |
| 847 | bool switch_backup, | 825 | bool switch_guest_memory, |
| 848 | struct vmw_buffer_object *new_backup, | 826 | struct vmw_bo *new_guest_memory, |
| 849 | unsigned long new_backup_offset); | 827 | unsigned long new_guest_memory_offset); |
| 850 | extern void vmw_query_move_notify(struct ttm_buffer_object *bo, | 828 | extern void vmw_query_move_notify(struct ttm_buffer_object *bo, |
| 851 | struct ttm_resource *old_mem, | 829 | struct ttm_resource *old_mem, |
| 852 | struct ttm_resource *new_mem); | 830 | struct ttm_resource *new_mem); |
| 853 | extern int vmw_query_readback_all(struct vmw_buffer_object *dx_query_mob); | 831 | int vmw_query_readback_all(struct vmw_bo *dx_query_mob); |
| 854 | extern void vmw_resource_evict_all(struct vmw_private *dev_priv); | 832 | void vmw_resource_evict_all(struct vmw_private *dev_priv); |
| 855 | extern void vmw_resource_unbind_list(struct vmw_buffer_object *vbo); | 833 | void vmw_resource_unbind_list(struct vmw_bo *vbo); |
| 856 | void vmw_resource_mob_attach(struct vmw_resource *res); | 834 | void vmw_resource_mob_attach(struct vmw_resource *res); |
| 857 | void vmw_resource_mob_detach(struct vmw_resource *res); | 835 | void vmw_resource_mob_detach(struct vmw_resource *res); |
| 858 | void vmw_resource_dirty_update(struct vmw_resource *res, pgoff_t start, | 836 | void vmw_resource_dirty_update(struct vmw_resource *res, pgoff_t start, |
| 859 | pgoff_t end); | 837 | pgoff_t end); |
| 860 | int vmw_resources_clean(struct vmw_buffer_object *vbo, pgoff_t start, | 838 | int vmw_resources_clean(struct vmw_bo *vbo, pgoff_t start, |
| 861 | pgoff_t end, pgoff_t *num_prefault); | 839 | pgoff_t end, pgoff_t *num_prefault); |
| 862 | 840 | ||
| 863 | /** | 841 | /** |
| @@ -871,107 +849,6 @@ static inline bool vmw_resource_mob_attached(const struct vmw_resource *res) · 7 unmodified lines | |||
| 871 | return !RB_EMPTY_NODE(&res->mob_node); | 849 | return !RB_EMPTY_NODE(&res->mob_node); |
| 872 | } | 850 | } |
| 873 | 851 | ||
| 874 | /** | ||
| 875 | * Buffer object helper functions - vmwgfx_bo.c | ||
| 876 | */ | ||
| 877 | extern int vmw_bo_pin_in_placement(struct vmw_private *vmw_priv, | ||
| 878 | struct vmw_buffer_object *bo, | ||
| 879 | struct ttm_placement *placement, | ||
| 880 | bool interruptible); | ||
| 881 | extern int vmw_bo_pin_in_vram(struct vmw_private *dev_priv, | ||
| 882 | struct vmw_buffer_object *buf, | ||
| 883 | bool interruptible); | ||
| 884 | extern int vmw_bo_pin_in_vram_or_gmr(struct vmw_private *dev_priv, | ||
| 885 | struct vmw_buffer_object *buf, | ||
| 886 | bool interruptible); | ||
| 887 | extern int vmw_bo_pin_in_start_of_vram(struct vmw_private *vmw_priv, | ||
| 888 | struct vmw_buffer_object *bo, | ||
| 889 | bool interruptible); | ||
| 890 | extern int vmw_bo_unpin(struct vmw_private *vmw_priv, | ||
| 891 | struct vmw_buffer_object *bo, | ||
| 892 | bool interruptible); | ||
| 893 | extern void vmw_bo_get_guest_ptr(const struct ttm_buffer_object *buf, | ||
| 894 | SVGAGuestPtr *ptr); | ||
| 895 | extern void vmw_bo_pin_reserved(struct vmw_buffer_object *bo, bool pin); | ||
| 896 | extern void vmw_bo_bo_free(struct ttm_buffer_object *bo); | ||
| 897 | extern int vmw_bo_create_kernel(struct vmw_private *dev_priv, | ||
| 898 | unsigned long size, | ||
| 899 | struct ttm_placement *placement, | ||
| 900 | struct ttm_buffer_object **p_bo); | ||
| 901 | extern int vmw_bo_create(struct vmw_private *dev_priv, | ||
| 902 | size_t size, struct ttm_placement *placement, | ||
| 903 | bool interruptible, bool pin, | ||
| 904 | void (*bo_free)(struct ttm_buffer_object *bo), | ||
| 905 | struct vmw_buffer_object **p_bo); | ||
| 906 | extern int vmw_bo_init(struct vmw_private *dev_priv, | ||
| 907 | struct vmw_buffer_object *vmw_bo, | ||
| 908 | size_t size, struct ttm_placement *placement, | ||
| 909 | bool interruptible, bool pin, | ||
| 910 | void (*bo_free)(struct ttm_buffer_object *bo)); | ||
| 911 | extern int vmw_bo_unref_ioctl(struct drm_device *dev, void *data, | ||
| 912 | struct drm_file *file_priv); | ||
| 913 | extern int vmw_user_bo_synccpu_ioctl(struct drm_device *dev, void *data, | ||
| 914 | struct drm_file *file_priv); | ||
| 915 | extern int vmw_user_bo_lookup(struct drm_file *filp, | ||
| 916 | uint32_t handle, | ||
| 917 | struct vmw_buffer_object **out); | ||
| 918 | extern void vmw_bo_fence_single(struct ttm_buffer_object *bo, | ||
| 919 | struct vmw_fence_obj *fence); | ||
| 920 | extern void *vmw_bo_map_and_cache(struct vmw_buffer_object *vbo); | ||
| 921 | extern void vmw_bo_unmap(struct vmw_buffer_object *vbo); | ||
| 922 | extern void vmw_bo_move_notify(struct ttm_buffer_object *bo, | ||
| 923 | struct ttm_resource *mem); | ||
| 924 | extern void vmw_bo_swap_notify(struct ttm_buffer_object *bo); | ||
| 925 | |||
| 926 | /** | ||
| 927 | * vmw_bo_adjust_prio - Adjust the buffer object eviction priority | ||
| 928 | * according to attached resources | ||
| 929 | * @vbo: The struct vmw_buffer_object | ||
| 930 | */ | ||
| 931 | static inline void vmw_bo_prio_adjust(struct vmw_buffer_object *vbo) | ||
| 932 | { | ||
| 933 | int i = ARRAY_SIZE(vbo->res_prios); | ||
| 934 | |||
| 935 | while (i--) { | ||
| 936 | if (vbo->res_prios[i]) { | ||
| 937 | vbo->base.priority = i; | ||
| 938 | return; | ||
| 939 | } | ||
| 940 | } | ||
| 941 | |||
| 942 | vbo->base.priority = 3; | ||
| 943 | } | ||
| 944 | |||
| 945 | /** | ||
| 946 | * vmw_bo_prio_add - Notify a buffer object of a newly attached resource | ||
| 947 | * eviction priority | ||
| 948 | * @vbo: The struct vmw_buffer_object | ||
| 949 | * @prio: The resource priority | ||
| 950 | * | ||
| 951 | * After being notified, the code assigns the highest resource eviction priority | ||
| 952 | * to the backing buffer object (mob). | ||
| 953 | */ | ||
| 954 | static inline void vmw_bo_prio_add(struct vmw_buffer_object *vbo, int prio) | ||
| 955 | { | ||
| 956 | if (vbo->res_prios[prio]++ == 0) | ||
| 957 | vmw_bo_prio_adjust(vbo); | ||
| 958 | } | ||
| 959 | |||
| 960 | /** | ||
| 961 | * vmw_bo_prio_del - Notify a buffer object of a resource with a certain | ||
| 962 | * priority being removed | ||
| 963 | * @vbo: The struct vmw_buffer_object | ||
| 964 | * @prio: The resource priority | ||
| 965 | * | ||
| 966 | * After being notified, the code assigns the highest resource eviction priority | ||
| 967 | * to the backing buffer object (mob). | ||
| 968 | */ | ||
| 969 | static inline void vmw_bo_prio_del(struct vmw_buffer_object *vbo, int prio) | ||
| 970 | { | ||
| 971 | if (--vbo->res_prios[prio] == 0) | ||
| 972 | vmw_bo_prio_adjust(vbo); | ||
| 973 | } | ||
| 974 | |||
| 975 | /** | 852 | /** |
| 976 | * GEM related functionality - vmwgfx_gem.c | 853 | * GEM related functionality - vmwgfx_gem.c |
| 977 | */ | 854 | */ |
| @@ -979,10 +856,9 @@ extern int vmw_gem_object_create_with_handle(struct vmw_private *dev_priv, · 1 unmodified line | |||
| 979 | struct drm_file *filp, | 856 | struct drm_file *filp, |
| 980 | uint32_t size, | 857 | uint32_t size, |
| 981 | uint32_t *handle, | 858 | uint32_t *handle, |
| 982 | struct vmw_buffer_object **p_vbo); | 859 | struct vmw_bo **p_vbo); |
| 983 | extern int vmw_gem_object_create_ioctl(struct drm_device *dev, void *data, | 860 | extern int vmw_gem_object_create_ioctl(struct drm_device *dev, void *data, |
| 984 | struct drm_file *filp); | 861 | struct drm_file *filp); |
| 985 | extern void vmw_gem_destroy(struct ttm_buffer_object *bo); | ||
| 986 | extern void vmw_debugfs_gem_init(struct vmw_private *vdev); | 862 | extern void vmw_debugfs_gem_init(struct vmw_private *vdev); |
| 987 | 863 | ||
| 988 | /** | 864 | /** |
| @@ -1055,30 +931,21 @@ vmw_is_cursor_bypass3_enabled(const struct vmw_private *dev_priv) · 66 unmodified lines | |||
| 1055 | return (vmw_fifo_caps(dev_priv) & SVGA_FIFO_CAP_CURSOR_BYPASS_3) != 0; | 931 | return (vmw_fifo_caps(dev_priv) & SVGA_FIFO_CAP_CURSOR_BYPASS_3) != 0; |
| 1056 | } | 932 | } |
| 1057 | 933 | ||
| 1058 | /** | ||
| 1059 | * TTM glue - vmwgfx_ttm_glue.c | ||
| 1060 | */ | ||
| 1061 | |||
| 1062 | extern int vmw_mmap(struct file *filp, struct vm_area_struct *vma); | ||
| 1063 | |||
| 1064 | /** | 934 | /** |
| 1065 | * TTM buffer object driver - vmwgfx_ttm_buffer.c | 935 | * TTM buffer object driver - vmwgfx_ttm_buffer.c |
| 1066 | */ | 936 | */ |
| 1067 | 937 | ||
| 1068 | extern const size_t vmw_tt_size; | 938 | extern const size_t vmw_tt_size; |
| 1069 | extern struct ttm_placement vmw_vram_placement; | 939 | extern struct ttm_placement vmw_vram_placement; |
| 1070 | extern struct ttm_placement vmw_vram_sys_placement; | ||
| 1071 | extern struct ttm_placement vmw_vram_gmr_placement; | 940 | extern struct ttm_placement vmw_vram_gmr_placement; |
| 1072 | extern struct ttm_placement vmw_sys_placement; | 941 | extern struct ttm_placement vmw_sys_placement; |
| 1073 | extern struct ttm_placement vmw_srf_placement; | ||
| 1074 | extern struct ttm_placement vmw_mob_placement; | ||
| 1075 | extern struct ttm_placement vmw_nonfixed_placement; | ||
| 1076 | extern struct ttm_device_funcs vmw_bo_driver; | 942 | extern struct ttm_device_funcs vmw_bo_driver; |
| 1077 | extern const struct vmw_sg_table * | 943 | extern const struct vmw_sg_table * |
| 1078 | vmw_bo_sg_table(struct ttm_buffer_object *bo); | 944 | vmw_bo_sg_table(struct ttm_buffer_object *bo); |
| 1079 | extern int vmw_bo_create_and_populate(struct vmw_private *dev_priv, | 945 | int vmw_bo_create_and_populate(struct vmw_private *dev_priv, |
| 1080 | unsigned long bo_size, | 946 | size_t bo_size, |
| 1081 | struct ttm_buffer_object **bo_p); | 947 | u32 domain, |
| 948 | struct vmw_bo **bo_p); | ||
| 1082 | 949 | ||
| 1083 | extern void vmw_piter_start(struct vmw_piter *viter, | 950 | extern void vmw_piter_start(struct vmw_piter *viter, |
| 1084 | const struct vmw_sg_table *vsgt, | 951 | const struct vmw_sg_table *vsgt, |
| @@ -1297,8 +1164,8 @@ vmw_context_binding_state(struct vmw_resource *ctx); · 212 unmodified lines | |||
| 1297 | extern void vmw_dx_context_scrub_cotables(struct vmw_resource *ctx, | 1164 | extern void vmw_dx_context_scrub_cotables(struct vmw_resource *ctx, |
| 1298 | bool readback); | 1165 | bool readback); |
| 1299 | extern int vmw_context_bind_dx_query(struct vmw_resource *ctx_res, | 1166 | extern int vmw_context_bind_dx_query(struct vmw_resource *ctx_res, |
| 1300 | struct vmw_buffer_object *mob); | 1167 | struct vmw_bo *mob); |
| 1301 | extern struct vmw_buffer_object * | 1168 | extern struct vmw_bo * |
| 1302 | vmw_context_get_dx_query_mob(struct vmw_resource *ctx_res); | 1169 | vmw_context_get_dx_query_mob(struct vmw_resource *ctx_res); |
| 1303 | 1170 | ||
| 1304 | 1171 | ||
| @@ -1523,12 +1390,12 @@ int vmw_mksstat_remove_all(struct vmw_private *dev_priv); · 218 unmodified lines | |||
| 1523 | DRM_DEBUG_DRIVER(fmt, ##__VA_ARGS__) | 1390 | DRM_DEBUG_DRIVER(fmt, ##__VA_ARGS__) |
| 1524 | 1391 | ||
| 1525 | /* Resource dirtying - vmwgfx_page_dirty.c */ | 1392 | /* Resource dirtying - vmwgfx_page_dirty.c */ |
| 1526 | void vmw_bo_dirty_scan(struct vmw_buffer_object *vbo); | 1393 | void vmw_bo_dirty_scan(struct vmw_bo *vbo); |
| 1527 | int vmw_bo_dirty_add(struct vmw_buffer_object *vbo); | 1394 | int vmw_bo_dirty_add(struct vmw_bo *vbo); |
| 1528 | void vmw_bo_dirty_transfer_to_res(struct vmw_resource *res); | 1395 | void vmw_bo_dirty_transfer_to_res(struct vmw_resource *res); |
| 1529 | void vmw_bo_dirty_clear_res(struct vmw_resource *res); | 1396 | void vmw_bo_dirty_clear_res(struct vmw_resource *res); |
| 1530 | void vmw_bo_dirty_release(struct vmw_buffer_object *vbo); | 1397 | void vmw_bo_dirty_release(struct vmw_bo *vbo); |
| 1531 | void vmw_bo_dirty_unmap(struct vmw_buffer_object *vbo, | 1398 | void vmw_bo_dirty_unmap(struct vmw_bo *vbo, |
| 1532 | pgoff_t start, pgoff_t end); | 1399 | pgoff_t start, pgoff_t end); |
| 1533 | vm_fault_t vmw_bo_vm_fault(struct vm_fault *vmf); | 1400 | vm_fault_t vmw_bo_vm_fault(struct vm_fault *vmf); |
| 1534 | vm_fault_t vmw_bo_vm_mkwrite(struct vm_fault *vmf); | 1401 | vm_fault_t vmw_bo_vm_mkwrite(struct vm_fault *vmf); |
| @@ -1561,22 +1428,6 @@ static inline struct vmw_surface *vmw_surface_reference(struct vmw_surface *srf) · 26 unmodified lines | |||
| 1561 | return srf; | 1428 | return srf; |
| 1562 | } | 1429 | } |
| 1563 | 1430 | ||
| 1564 | static inline void vmw_bo_unreference(struct vmw_buffer_object **buf) | ||
| 1565 | { | ||
| 1566 | struct vmw_buffer_object *tmp_buf = *buf; | ||
| 1567 | |||
| 1568 | *buf = NULL; | ||
| 1569 | if (tmp_buf != NULL) | ||
| 1570 | ttm_bo_put(&tmp_buf->base); | ||
| 1571 | } | ||
| 1572 | |||
| 1573 | static inline struct vmw_buffer_object * | ||
| 1574 | vmw_bo_reference(struct vmw_buffer_object *buf) | ||
| 1575 | { | ||
| 1576 | ttm_bo_get(&buf->base); | ||
| 1577 | return buf; | ||
| 1578 | } | ||
| 1579 | |||
| 1580 | static inline void vmw_fifo_resource_inc(struct vmw_private *dev_priv) | 1431 | static inline void vmw_fifo_resource_inc(struct vmw_private *dev_priv) |
| 1581 | { | 1432 | { |
| 1582 | atomic_inc(&dev_priv->num_fifo_resources); | 1433 | atomic_inc(&dev_priv->num_fifo_resources); |
| @@ -1,7 +1,7 @@ | |||
| 1 | // SPDX-License-Identifier: GPL-2.0 OR MIT | 1 | // SPDX-License-Identifier: GPL-2.0 OR MIT |
| 2 | /************************************************************************** | 2 | /************************************************************************** |
| 3 | * | 3 | * |
| 4 | * Copyright 2009 - 2022 VMware, Inc., Palo Alto, CA., USA | 4 | * Copyright 2009 - 2023 VMware, Inc., Palo Alto, CA., USA |
| 5 | * | 5 | * |
| 6 | * Permission is hereby granted, free of charge, to any person obtaining a | 6 | * Permission is hereby granted, free of charge, to any person obtaining a |
| 7 | * copy of this software and associated documentation files (the | 7 | * copy of this software and associated documentation files (the |
| @@ -24,17 +24,17 @@ · 16 unmodified lines | |||
| 24 | * USE OR OTHER DEALINGS IN THE SOFTWARE. | 24 | * USE OR OTHER DEALINGS IN THE SOFTWARE. |
| 25 | * | 25 | * |
| 26 | **************************************************************************/ | 26 | **************************************************************************/ |
| 27 | #include <linux/sync_file.h> | 27 | #include "vmwgfx_binding.h" |
| 28 | #include <linux/hashtable.h> | 28 | #include "vmwgfx_bo.h" |
| 29 | |||
| 30 | #include "vmwgfx_drv.h" | 29 | #include "vmwgfx_drv.h" |
| 31 | #include "vmwgfx_reg.h" | 30 | #include "vmwgfx_mksstat.h" |
| 31 | #include "vmwgfx_so.h" | ||
| 32 | |||
| 32 | #include <drm/ttm/ttm_bo.h> | 33 | #include <drm/ttm/ttm_bo.h> |
| 33 | #include <drm/ttm/ttm_placement.h> | 34 | #include <drm/ttm/ttm_placement.h> |
| 34 | #include "vmwgfx_so.h" | ||
| 35 | #include "vmwgfx_binding.h" | ||
| 36 | #include "vmwgfx_mksstat.h" | ||
| 37 | 35 | ||
| 36 | #include <linux/sync_file.h> | ||
| 37 | #include <linux/hashtable.h> | ||
| 38 | 38 | ||
| 39 | /* | 39 | /* |
| 40 | * Helper macro to get dx_ctx_node if available otherwise print an error | 40 | * Helper macro to get dx_ctx_node if available otherwise print an error |
| @@ -65,7 +65,7 @@ · 24 unmodified lines | |||
| 65 | */ | 65 | */ |
| 66 | struct vmw_relocation { | 66 | struct vmw_relocation { |
| 67 | struct list_head head; | 67 | struct list_head head; |
| 68 | struct vmw_buffer_object *vbo; | 68 | struct vmw_bo *vbo; |
| 69 | union { | 69 | union { |
| 70 | SVGAMobId *mob_loc; | 70 | SVGAMobId *mob_loc; |
| 71 | SVGAGuestPtr *location; | 71 | SVGAGuestPtr *location; |
| @@ -149,7 +149,7 @@ static int vmw_resource_context_res_add(struct vmw_private *dev_priv, · 77 unmodified lines | |||
| 149 | static int vmw_translate_mob_ptr(struct vmw_private *dev_priv, | 149 | static int vmw_translate_mob_ptr(struct vmw_private *dev_priv, |
| 150 | struct vmw_sw_context *sw_context, | 150 | struct vmw_sw_context *sw_context, |
| 151 | SVGAMobId *id, | 151 | SVGAMobId *id, |
| 152 | struct vmw_buffer_object **vmw_bo_p); | 152 | struct vmw_bo **vmw_bo_p); |
| 153 | /** | 153 | /** |
| 154 | * vmw_ptr_diff - Compute the offset from a to b in bytes | 154 | * vmw_ptr_diff - Compute the offset from a to b in bytes |
| 155 | * | 155 | * |
| @@ -475,12 +475,16 @@ static int vmw_resource_context_res_add(struct vmw_private *dev_priv, · 319 unmodified lines | |||
| 475 | 475 | ||
| 476 | if (has_sm4_context(dev_priv) && | 476 | if (has_sm4_context(dev_priv) && |
| 477 | vmw_res_type(ctx) == vmw_res_dx_context) { | 477 | vmw_res_type(ctx) == vmw_res_dx_context) { |
| 478 | struct vmw_buffer_object *dx_query_mob; | 478 | struct vmw_bo *dx_query_mob; |
| 479 | 479 | ||
| 480 | dx_query_mob = vmw_context_get_dx_query_mob(ctx); | 480 | dx_query_mob = vmw_context_get_dx_query_mob(ctx); |
| 481 | if (dx_query_mob) | 481 | if (dx_query_mob) { |
| 482 | vmw_bo_placement_set(dx_query_mob, | ||
| 483 | VMW_BO_DOMAIN_MOB, | ||
| 484 | VMW_BO_DOMAIN_MOB); | ||
| 482 | ret = vmw_validation_add_bo(sw_context->ctx, | 485 | ret = vmw_validation_add_bo(sw_context->ctx, |
| 483 | dx_query_mob, true, false); | 486 | dx_query_mob); |
| 487 | } | ||
| 484 | } | 488 | } |
| 485 | 489 | ||
| 486 | mutex_unlock(&dev_priv->binding_mutex); | 490 | mutex_unlock(&dev_priv->binding_mutex); |
| @@ -596,7 +600,7 @@ static int vmw_resources_reserve(struct vmw_sw_context *sw_context) · 109 unmodified lines | |||
| 596 | return ret; | 600 | return ret; |
| 597 | 601 | ||
| 598 | if (sw_context->dx_query_mob) { | 602 | if (sw_context->dx_query_mob) { |
| 599 | struct vmw_buffer_object *expected_dx_query_mob; | 603 | struct vmw_bo *expected_dx_query_mob; |
| 600 | 604 | ||
| 601 | expected_dx_query_mob = | 605 | expected_dx_query_mob = |
| 602 | vmw_context_get_dx_query_mob(sw_context->dx_query_ctx); | 606 | vmw_context_get_dx_query_mob(sw_context->dx_query_ctx); |
| @@ -703,7 +707,7 @@ res_check_done: · 100 unmodified lines | |||
| 703 | static int vmw_rebind_all_dx_query(struct vmw_resource *ctx_res) | 707 | static int vmw_rebind_all_dx_query(struct vmw_resource *ctx_res) |
| 704 | { | 708 | { |
| 705 | struct vmw_private *dev_priv = ctx_res->dev_priv; | 709 | struct vmw_private *dev_priv = ctx_res->dev_priv; |
| 706 | struct vmw_buffer_object *dx_query_mob; | 710 | struct vmw_bo *dx_query_mob; |
| 707 | VMW_DECLARE_CMD_VAR(*cmd, SVGA3dCmdDXBindAllQuery); | 711 | VMW_DECLARE_CMD_VAR(*cmd, SVGA3dCmdDXBindAllQuery); |
| 708 | 712 | ||
| 709 | dx_query_mob = vmw_context_get_dx_query_mob(ctx_res); | 713 | dx_query_mob = vmw_context_get_dx_query_mob(ctx_res); |
| @@ -718,7 +722,7 @@ static int vmw_rebind_all_dx_query(struct vmw_resource *ctx_res) · 8 unmodified lines | |||
| 718 | cmd->header.id = SVGA_3D_CMD_DX_BIND_ALL_QUERY; | 722 | cmd->header.id = SVGA_3D_CMD_DX_BIND_ALL_QUERY; |
| 719 | cmd->header.size = sizeof(cmd->body); | 723 | cmd->header.size = sizeof(cmd->body); |
| 720 | cmd->body.cid = ctx_res->id; | 724 | cmd->body.cid = ctx_res->id; |
| 721 | cmd->body.mobid = dx_query_mob->base.resource->start; | 725 | cmd->body.mobid = dx_query_mob->tbo.resource->start; |
| 722 | vmw_cmd_commit(dev_priv, sizeof(*cmd)); | 726 | vmw_cmd_commit(dev_priv, sizeof(*cmd)); |
| 723 | 727 | ||
| 724 | vmw_context_bind_dx_query(ctx_res, dx_query_mob); | 728 | vmw_context_bind_dx_query(ctx_res, dx_query_mob); |
| @@ -1017,7 +1021,7 @@ static int vmw_cmd_present_check(struct vmw_private *dev_priv, · 292 unmodified lines | |||
| 1017 | * after successful submission of the current command batch. | 1021 | * after successful submission of the current command batch. |
| 1018 | */ | 1022 | */ |
| 1019 | static int vmw_query_bo_switch_prepare(struct vmw_private *dev_priv, | 1023 | static int vmw_query_bo_switch_prepare(struct vmw_private *dev_priv, |
| 1020 | struct vmw_buffer_object *new_query_bo, | 1024 | struct vmw_bo *new_query_bo, |
| 1021 | struct vmw_sw_context *sw_context) | 1025 | struct vmw_sw_context *sw_context) |
| 1022 | { | 1026 | { |
| 1023 | struct vmw_res_cache_entry *ctx_entry = | 1027 | struct vmw_res_cache_entry *ctx_entry = |
| @@ -1029,24 +1033,24 @@ static int vmw_query_bo_switch_prepare(struct vmw_private *dev_priv, · 5 unmodified lines | |||
| 1029 | 1033 | ||
| 1030 | if (unlikely(new_query_bo != sw_context->cur_query_bo)) { | 1034 | if (unlikely(new_query_bo != sw_context->cur_query_bo)) { |
| 1031 | 1035 | ||
| 1032 | if (unlikely(PFN_UP(new_query_bo->base.resource->size) > 4)) { | 1036 | if (unlikely(PFN_UP(new_query_bo->tbo.resource->size) > 4)) { |
| 1033 | VMW_DEBUG_USER("Query buffer too large.\n"); | 1037 | VMW_DEBUG_USER("Query buffer too large.\n"); |
| 1034 | return -EINVAL; | 1038 | return -EINVAL; |
| 1035 | } | 1039 | } |
| 1036 | 1040 | ||
| 1037 | if (unlikely(sw_context->cur_query_bo != NULL)) { | 1041 | if (unlikely(sw_context->cur_query_bo != NULL)) { |
| 1038 | sw_context->needs_post_query_barrier = true; | 1042 | sw_context->needs_post_query_barrier = true; |
| 1043 | vmw_bo_placement_set_default_accelerated(sw_context->cur_query_bo); | ||
| 1039 | ret = vmw_validation_add_bo(sw_context->ctx, | 1044 | ret = vmw_validation_add_bo(sw_context->ctx, |
| 1040 | sw_context->cur_query_bo, | 1045 | sw_context->cur_query_bo); |
| 1041 | dev_priv->has_mob, false); | ||
| 1042 | if (unlikely(ret != 0)) | 1046 | if (unlikely(ret != 0)) |
| 1043 | return ret; | 1047 | return ret; |
| 1044 | } | 1048 | } |
| 1045 | sw_context->cur_query_bo = new_query_bo; | 1049 | sw_context->cur_query_bo = new_query_bo; |
| 1046 | 1050 | ||
| 1051 | vmw_bo_placement_set_default_accelerated(dev_priv->dummy_query_bo); | ||
| 1047 | ret = vmw_validation_add_bo(sw_context->ctx, | 1052 | ret = vmw_validation_add_bo(sw_context->ctx, |
| 1048 | dev_priv->dummy_query_bo, | 1053 | dev_priv->dummy_query_bo); |
| 1049 | dev_priv->has_mob, false); | ||
| 1050 | if (unlikely(ret != 0)) | 1054 | if (unlikely(ret != 0)) |
| 1051 | return ret; | 1055 | return ret; |
| 1052 | } | 1056 | } |
| @@ -1145,9 +1149,9 @@ static void vmw_query_bo_switch_commit(struct vmw_private *dev_priv, · 92 unmodified lines | |||
| 1145 | static int vmw_translate_mob_ptr(struct vmw_private *dev_priv, | 1149 | static int vmw_translate_mob_ptr(struct vmw_private *dev_priv, |
| 1146 | struct vmw_sw_context *sw_context, | 1150 | struct vmw_sw_context *sw_context, |
| 1147 | SVGAMobId *id, | 1151 | SVGAMobId *id, |
| 1148 | struct vmw_buffer_object **vmw_bo_p) | 1152 | struct vmw_bo **vmw_bo_p) |
| 1149 | { | 1153 | { |
| 1150 | struct vmw_buffer_object *vmw_bo; | 1154 | struct vmw_bo *vmw_bo; |
| 1151 | uint32_t handle = *id; | 1155 | uint32_t handle = *id; |
| 1152 | struct vmw_relocation *reloc; | 1156 | struct vmw_relocation *reloc; |
| 1153 | int ret; | 1157 | int ret; |
| @@ -1158,9 +1162,10 @@ static int vmw_translate_mob_ptr(struct vmw_private *dev_priv, · 4 unmodified lines | |||
| 1158 | drm_dbg(&dev_priv->drm, "Could not find or use MOB buffer.\n"); | 1162 | drm_dbg(&dev_priv->drm, "Could not find or use MOB buffer.\n"); |
| 1159 | return PTR_ERR(vmw_bo); | 1163 | return PTR_ERR(vmw_bo); |
| 1160 | } | 1164 | } |
| 1161 | ret = vmw_validation_add_bo(sw_context->ctx, vmw_bo, true, false); | 1165 | vmw_bo_placement_set(vmw_bo, VMW_BO_DOMAIN_MOB, VMW_BO_DOMAIN_MOB); |
| 1162 | ttm_bo_put(&vmw_bo->base); | 1166 | ret = vmw_validation_add_bo(sw_context->ctx, vmw_bo); |
| 1163 | drm_gem_object_put(&vmw_bo->base.base); | 1167 | ttm_bo_put(&vmw_bo->tbo); |
| 1168 | drm_gem_object_put(&vmw_bo->tbo.base); | ||
| 1164 | if (unlikely(ret != 0)) | 1169 | if (unlikely(ret != 0)) |
| 1165 | return ret; | 1170 | return ret; |
| 1166 | 1171 | ||
| @@ -1200,9 +1205,9 @@ static int vmw_translate_mob_ptr(struct vmw_private *dev_priv, · 33 unmodified lines | |||
| 1200 | static int vmw_translate_guest_ptr(struct vmw_private *dev_priv, | 1205 | static int vmw_translate_guest_ptr(struct vmw_private *dev_priv, |
| 1201 | struct vmw_sw_context *sw_context, | 1206 | struct vmw_sw_context *sw_context, |
| 1202 | SVGAGuestPtr *ptr, | 1207 | SVGAGuestPtr *ptr, |
| 1203 | struct vmw_buffer_object **vmw_bo_p) | 1208 | struct vmw_bo **vmw_bo_p) |
| 1204 | { | 1209 | { |
| 1205 | struct vmw_buffer_object *vmw_bo; | 1210 | struct vmw_bo *vmw_bo; |
| 1206 | uint32_t handle = ptr->gmrId; | 1211 | uint32_t handle = ptr->gmrId; |
| 1207 | struct vmw_relocation *reloc; | 1212 | struct vmw_relocation *reloc; |
| 1208 | int ret; | 1213 | int ret; |
| @@ -1213,9 +1218,11 @@ static int vmw_translate_guest_ptr(struct vmw_private *dev_priv, · 4 unmodified lines | |||
| 1213 | drm_dbg(&dev_priv->drm, "Could not find or use GMR region.\n"); | 1218 | drm_dbg(&dev_priv->drm, "Could not find or use GMR region.\n"); |
| 1214 | return PTR_ERR(vmw_bo); | 1219 | return PTR_ERR(vmw_bo); |
| 1215 | } | 1220 | } |
| 1216 | ret = vmw_validation_add_bo(sw_context->ctx, vmw_bo, false, false); | 1221 | vmw_bo_placement_set(vmw_bo, VMW_BO_DOMAIN_GMR | VMW_BO_DOMAIN_VRAM, |
| 1217 | ttm_bo_put(&vmw_bo->base); | 1222 | VMW_BO_DOMAIN_GMR | VMW_BO_DOMAIN_VRAM); |
| 1218 | drm_gem_object_put(&vmw_bo->base.base); | 1223 | ret = vmw_validation_add_bo(sw_context->ctx, vmw_bo); |
| 1224 | ttm_bo_put(&vmw_bo->tbo); | ||
| 1225 | drm_gem_object_put(&vmw_bo->tbo.base); | ||
| 1219 | if (unlikely(ret != 0)) | 1226 | if (unlikely(ret != 0)) |
| 1220 | return ret; | 1227 | return ret; |
| 1221 | 1228 | ||
| @@ -1280,7 +1287,7 @@ static int vmw_cmd_dx_bind_query(struct vmw_private *dev_priv, · 58 unmodified lines | |||
| 1280 | SVGA3dCmdHeader *header) | 1287 | SVGA3dCmdHeader *header) |
| 1281 | { | 1288 | { |
| 1282 | VMW_DECLARE_CMD_VAR(*cmd, SVGA3dCmdDXBindQuery); | 1289 | VMW_DECLARE_CMD_VAR(*cmd, SVGA3dCmdDXBindQuery); |
| 1283 | struct vmw_buffer_object *vmw_bo; | 1290 | struct vmw_bo *vmw_bo; |
| 1284 | int ret; | 1291 | int ret; |
| 1285 | 1292 | ||
| 1286 | cmd = container_of(header, typeof(*cmd), header); | 1293 | cmd = container_of(header, typeof(*cmd), header); |
| @@ -1363,7 +1370,7 @@ static int vmw_cmd_end_gb_query(struct vmw_private *dev_priv, · 76 unmodified lines | |||
| 1363 | struct vmw_sw_context *sw_context, | 1370 | struct vmw_sw_context *sw_context, |
| 1364 | SVGA3dCmdHeader *header) | 1371 | SVGA3dCmdHeader *header) |
| 1365 | { | 1372 | { |
| 1366 | struct vmw_buffer_object *vmw_bo; | 1373 | struct vmw_bo *vmw_bo; |
| 1367 | VMW_DECLARE_CMD_VAR(*cmd, SVGA3dCmdEndGBQuery); | 1374 | VMW_DECLARE_CMD_VAR(*cmd, SVGA3dCmdEndGBQuery); |
| 1368 | int ret; | 1375 | int ret; |
| 1369 | 1376 | ||
| @@ -1393,7 +1400,7 @@ static int vmw_cmd_end_query(struct vmw_private *dev_priv, · 23 unmodified lines | |||
| 1393 | struct vmw_sw_context *sw_context, | 1400 | struct vmw_sw_context *sw_context, |
| 1394 | SVGA3dCmdHeader *header) | 1401 | SVGA3dCmdHeader *header) |
| 1395 | { | 1402 | { |
| 1396 | struct vmw_buffer_object *vmw_bo; | 1403 | struct vmw_bo *vmw_bo; |
| 1397 | VMW_DECLARE_CMD_VAR(*cmd, SVGA3dCmdEndQuery); | 1404 | VMW_DECLARE_CMD_VAR(*cmd, SVGA3dCmdEndQuery); |
| 1398 | int ret; | 1405 | int ret; |
| 1399 | 1406 | ||
| @@ -1439,7 +1446,7 @@ static int vmw_cmd_wait_gb_query(struct vmw_private *dev_priv, · 39 unmodified lines | |||
| 1439 | struct vmw_sw_context *sw_context, | 1446 | struct vmw_sw_context *sw_context, |
| 1440 | SVGA3dCmdHeader *header) | 1447 | SVGA3dCmdHeader *header) |
| 1441 | { | 1448 | { |
| 1442 | struct vmw_buffer_object *vmw_bo; | 1449 | struct vmw_bo *vmw_bo; |
| 1443 | VMW_DECLARE_CMD_VAR(*cmd, SVGA3dCmdWaitForGBQuery); | 1450 | VMW_DECLARE_CMD_VAR(*cmd, SVGA3dCmdWaitForGBQuery); |
| 1444 | int ret; | 1451 | int ret; |
| 1445 | 1452 | ||
| @@ -1467,7 +1474,7 @@ static int vmw_cmd_wait_query(struct vmw_private *dev_priv, · 21 unmodified lines | |||
| 1467 | struct vmw_sw_context *sw_context, | 1474 | struct vmw_sw_context *sw_context, |
| 1468 | SVGA3dCmdHeader *header) | 1475 | SVGA3dCmdHeader *header) |
| 1469 | { | 1476 | { |
| 1470 | struct vmw_buffer_object *vmw_bo; | 1477 | struct vmw_bo *vmw_bo; |
| 1471 | VMW_DECLARE_CMD_VAR(*cmd, SVGA3dCmdWaitForQuery); | 1478 | VMW_DECLARE_CMD_VAR(*cmd, SVGA3dCmdWaitForQuery); |
| 1472 | int ret; | 1479 | int ret; |
| 1473 | 1480 | ||
| @@ -1504,7 +1511,7 @@ static int vmw_cmd_dma(struct vmw_private *dev_priv, · 30 unmodified lines | |||
| 1504 | struct vmw_sw_context *sw_context, | 1511 | struct vmw_sw_context *sw_context, |
| 1505 | SVGA3dCmdHeader *header) | 1512 | SVGA3dCmdHeader *header) |
| 1506 | { | 1513 | { |
| 1507 | struct vmw_buffer_object *vmw_bo = NULL; | 1514 | struct vmw_bo *vmw_bo = NULL; |
| 1508 | struct vmw_surface *srf = NULL; | 1515 | struct vmw_surface *srf = NULL; |
| 1509 | VMW_DECLARE_CMD_VAR(*cmd, SVGA3dCmdSurfaceDMA); | 1516 | VMW_DECLARE_CMD_VAR(*cmd, SVGA3dCmdSurfaceDMA); |
| 1510 | int ret; | 1517 | int ret; |
| @@ -1528,7 +1535,7 @@ static int vmw_cmd_dma(struct vmw_private *dev_priv, · 17 unmodified lines | |||
| 1528 | return ret; | 1535 | return ret; |
| 1529 | 1536 | ||
| 1530 | /* Make sure DMA doesn't cross BO boundaries. */ | 1537 | /* Make sure DMA doesn't cross BO boundaries. */ |
| 1531 | bo_size = vmw_bo->base.base.size; | 1538 | bo_size = vmw_bo->tbo.base.size; |
| 1532 | if (unlikely(cmd->body.guest.ptr.offset > bo_size)) { | 1539 | if (unlikely(cmd->body.guest.ptr.offset > bo_size)) { |
| 1533 | VMW_DEBUG_USER("Invalid DMA offset.\n"); | 1540 | VMW_DEBUG_USER("Invalid DMA offset.\n"); |
| 1534 | return -EINVAL; | 1541 | return -EINVAL; |
| @@ -1551,7 +1558,7 @@ static int vmw_cmd_dma(struct vmw_private *dev_priv, · 16 unmodified lines | |||
| 1551 | 1558 | ||
| 1552 | srf = vmw_res_to_srf(sw_context->res_cache[vmw_res_surface].res); | 1559 | srf = vmw_res_to_srf(sw_context->res_cache[vmw_res_surface].res); |
| 1553 | 1560 | ||
| 1554 | vmw_kms_cursor_snoop(srf, sw_context->fp->tfile, &vmw_bo->base, header); | 1561 | vmw_kms_cursor_snoop(srf, sw_context->fp->tfile, &vmw_bo->tbo, header); |
| 1555 | 1562 | ||
| 1556 | return 0; | 1563 | return 0; |
| 1557 | } | 1564 | } |
| @@ -1670,7 +1677,7 @@ static int vmw_cmd_check_define_gmrfb(struct vmw_private *dev_priv, · 112 unmodified lines | |||
| 1670 | struct vmw_sw_context *sw_context, | 1677 | struct vmw_sw_context *sw_context, |
| 1671 | void *buf) | 1678 | void *buf) |
| 1672 | { | 1679 | { |
| 1673 | struct vmw_buffer_object *vmw_bo; | 1680 | struct vmw_bo *vmw_bo; |
| 1674 | 1681 | ||
| 1675 | struct { | 1682 | struct { |
| 1676 | uint32_t header; | 1683 | uint32_t header; |
| @@ -1701,7 +1708,7 @@ static int vmw_cmd_res_switch_backup(struct vmw_private *dev_priv, · 24 unmodified lines | |||
| 1701 | struct vmw_resource *res, uint32_t *buf_id, | 1708 | struct vmw_resource *res, uint32_t *buf_id, |
| 1702 | unsigned long backup_offset) | 1709 | unsigned long backup_offset) |
| 1703 | { | 1710 | { |
| 1704 | struct vmw_buffer_object *vbo; | 1711 | struct vmw_bo *vbo; |
| 1705 | void *info; | 1712 | void *info; |
| 1706 | int ret; | 1713 | int ret; |
| 1707 | 1714 | ||
| @@ -3754,7 +3761,7 @@ static void vmw_apply_relocations(struct vmw_sw_context *sw_context) · 2046 unmodified lines | |||
| 3754 | struct ttm_buffer_object *bo; | 3761 | struct ttm_buffer_object *bo; |
| 3755 | 3762 | ||
| 3756 | list_for_each_entry(reloc, &sw_context->bo_relocations, head) { | 3763 | list_for_each_entry(reloc, &sw_context->bo_relocations, head) { |
| 3757 | bo = &reloc->vbo->base; | 3764 | bo = &reloc->vbo->tbo; |
| 3758 | switch (bo->resource->mem_type) { | 3765 | switch (bo->resource->mem_type) { |
| 3759 | case TTM_PL_VRAM: | 3766 | case TTM_PL_VRAM: |
| 3760 | reloc->location->offset += bo->resource->start << PAGE_SHIFT; | 3767 | reloc->location->offset += bo->resource->start << PAGE_SHIFT; |
| @@ -4364,13 +4371,17 @@ void __vmw_execbuf_release_pinned_bo(struct vmw_private *dev_priv, · 603 unmodified lines | |||
| 4364 | if (dev_priv->pinned_bo == NULL) | 4371 | if (dev_priv->pinned_bo == NULL) |
| 4365 | goto out_unlock; | 4372 | goto out_unlock; |
| 4366 | 4373 | ||
| 4367 | ret = vmw_validation_add_bo(&val_ctx, dev_priv->pinned_bo, false, | 4374 | vmw_bo_placement_set(dev_priv->pinned_bo, |
| 4368 | false); | 4375 | VMW_BO_DOMAIN_GMR | VMW_BO_DOMAIN_VRAM, |
| 4376 | VMW_BO_DOMAIN_GMR | VMW_BO_DOMAIN_VRAM); | ||
| 4377 | ret = vmw_validation_add_bo(&val_ctx, dev_priv->pinned_bo); | ||
| 4369 | if (ret) | 4378 | if (ret) |
| 4370 | goto out_no_reserve; | 4379 | goto out_no_reserve; |
| 4371 | 4380 | ||
| 4372 | ret = vmw_validation_add_bo(&val_ctx, dev_priv->dummy_query_bo, false, | 4381 | vmw_bo_placement_set(dev_priv->dummy_query_bo, |
| 4373 | false); | 4382 | VMW_BO_DOMAIN_GMR | VMW_BO_DOMAIN_VRAM, |
| 4383 | VMW_BO_DOMAIN_GMR | VMW_BO_DOMAIN_VRAM); | ||
| 4384 | ret = vmw_validation_add_bo(&val_ctx, dev_priv->dummy_query_bo); | ||
| 4374 | if (ret) | 4385 | if (ret) |
| 4375 | goto out_no_reserve; | 4386 | goto out_no_reserve; |
| 4376 | 4387 | ||
| @@ -1,7 +1,7 @@ | |||
| 1 | // SPDX-License-Identifier: GPL-2.0 OR MIT | 1 | // SPDX-License-Identifier: GPL-2.0 OR MIT |
| 2 | /************************************************************************** | 2 | /************************************************************************** |
| 3 | * | 3 | * |
| 4 | * Copyright 2011-2014 VMware, Inc., Palo Alto, CA., USA | 4 | * Copyright 2011-2023 VMware, Inc., Palo Alto, CA., USA |
| 5 | * | 5 | * |
| 6 | * Permission is hereby granted, free of charge, to any person obtaining a | 6 | * Permission is hereby granted, free of charge, to any person obtaining a |
| 7 | * copy of this software and associated documentation files (the | 7 | * copy of this software and associated documentation files (the |
| @@ -1,6 +1,6 @@ | |||
| 1 | /* SPDX-License-Identifier: GPL-2.0 OR MIT */ | 1 | /* SPDX-License-Identifier: GPL-2.0 OR MIT */ |
| 2 | /* | 2 | /* |
| 3 | * Copyright 2021 VMware, Inc. | 3 | * Copyright 2021-2023 VMware, Inc. |
| 4 | * | 4 | * |
| 5 | * Permission is hereby granted, free of charge, to any person | 5 | * Permission is hereby granted, free of charge, to any person |
| 6 | * obtaining a copy of this software and associated documentation | 6 | * obtaining a copy of this software and associated documentation |
| @@ -24,31 +24,17 @@ · 17 unmodified lines | |||
| 24 | * | 24 | * |
| 25 | */ | 25 | */ |
| 26 | 26 | ||
| 27 | #include "vmwgfx_bo.h" | ||
| 27 | #include "vmwgfx_drv.h" | 28 | #include "vmwgfx_drv.h" |
| 28 | 29 | ||
| 29 | #include "drm/drm_prime.h" | 30 | #include "drm/drm_prime.h" |
| 30 | #include "drm/drm_gem_ttm_helper.h" | 31 | #include "drm/drm_gem_ttm_helper.h" |
| 31 | 32 | ||
| 32 | /** | ||
| 33 | * vmw_buffer_object - Convert a struct ttm_buffer_object to a struct | ||
| 34 | * vmw_buffer_object. | ||
| 35 | * | ||
| 36 | * @bo: Pointer to the TTM buffer object. | ||
| 37 | * Return: Pointer to the struct vmw_buffer_object embedding the | ||
| 38 | * TTM buffer object. | ||
| 39 | */ | ||
| 40 | static struct vmw_buffer_object * | ||
| 41 | vmw_buffer_object(struct ttm_buffer_object *bo) | ||
| 42 | { | ||
| 43 | return container_of(bo, struct vmw_buffer_object, base); | ||
| 44 | } | ||
| 45 | |||
| 46 | static void vmw_gem_object_free(struct drm_gem_object *gobj) | 33 | static void vmw_gem_object_free(struct drm_gem_object *gobj) |
| 47 | { | 34 | { |
| 48 | struct ttm_buffer_object *bo = drm_gem_ttm_of_gem(gobj); | 35 | struct ttm_buffer_object *bo = drm_gem_ttm_of_gem(gobj); |
| 49 | if (bo) { | 36 | if (bo) |
| 50 | ttm_bo_put(bo); | 37 | ttm_bo_put(bo); |
| 51 | } | ||
| 52 | } | 38 | } |
| 53 | 39 | ||
| 54 | static int vmw_gem_object_open(struct drm_gem_object *obj, | 40 | static int vmw_gem_object_open(struct drm_gem_object *obj, |
| @@ -65,7 +51,7 @@ static void vmw_gem_object_close(struct drm_gem_object *obj, · 10 unmodified lines | |||
| 65 | static int vmw_gem_pin_private(struct drm_gem_object *obj, bool do_pin) | 51 | static int vmw_gem_pin_private(struct drm_gem_object *obj, bool do_pin) |
| 66 | { | 52 | { |
| 67 | struct ttm_buffer_object *bo = drm_gem_ttm_of_gem(obj); | 53 | struct ttm_buffer_object *bo = drm_gem_ttm_of_gem(obj); |
| 68 | struct vmw_buffer_object *vbo = vmw_buffer_object(bo); | 54 | struct vmw_bo *vbo = to_vmw_bo(obj); |
| 69 | int ret; | 55 | int ret; |
| 70 | 56 | ||
| 71 | ret = ttm_bo_reserve(bo, false, false, NULL); | 57 | ret = ttm_bo_reserve(bo, false, false, NULL); |
| @@ -103,6 +89,13 @@ static struct sg_table *vmw_gem_object_get_sg_table(struct drm_gem_object *obj) · 31 unmodified lines | |||
| 103 | return drm_prime_pages_to_sg(obj->dev, vmw_tt->dma_ttm.pages, vmw_tt->dma_ttm.num_pages); | 89 | return drm_prime_pages_to_sg(obj->dev, vmw_tt->dma_ttm.pages, vmw_tt->dma_ttm.num_pages); |
| 104 | } | 90 | } |
| 105 | 91 | ||
| 92 | static const struct vm_operations_struct vmw_vm_ops = { | ||
| 93 | .pfn_mkwrite = vmw_bo_vm_mkwrite, | ||
| 94 | .page_mkwrite = vmw_bo_vm_mkwrite, | ||
| 95 | .fault = vmw_bo_vm_fault, | ||
| 96 | .open = ttm_bo_vm_open, | ||
| 97 | .close = ttm_bo_vm_close, | ||
| 98 | }; | ||
| 106 | 99 | ||
| 107 | static const struct drm_gem_object_funcs vmw_gem_object_funcs = { | 100 | static const struct drm_gem_object_funcs vmw_gem_object_funcs = { |
| 108 | .free = vmw_gem_object_free, | 101 | .free = vmw_gem_object_free, |
| @@ -115,43 +108,31 @@ static const struct drm_gem_object_funcs vmw_gem_object_funcs = { · 6 unmodified lines | |||
| 115 | .vmap = drm_gem_ttm_vmap, | 108 | .vmap = drm_gem_ttm_vmap, |
| 116 | .vunmap = drm_gem_ttm_vunmap, | 109 | .vunmap = drm_gem_ttm_vunmap, |
| 117 | .mmap = drm_gem_ttm_mmap, | 110 | .mmap = drm_gem_ttm_mmap, |
| 111 | .vm_ops = &vmw_vm_ops, | ||
| 118 | }; | 112 | }; |
| 119 | 113 | ||
| 120 | /** | ||
| 121 | * vmw_gem_destroy - vmw buffer object destructor | ||
| 122 | * | ||
| 123 | * @bo: Pointer to the embedded struct ttm_buffer_object | ||
| 124 | */ | ||
| 125 | void vmw_gem_destroy(struct ttm_buffer_object *bo) | ||
| 126 | { | ||
| 127 | struct vmw_buffer_object *vbo = vmw_buffer_object(bo); | ||
| 128 | |||
| 129 | WARN_ON(vbo->dirty); | ||
| 130 | WARN_ON(!RB_EMPTY_ROOT(&vbo->res_tree)); | ||
| 131 | vmw_bo_unmap(vbo); | ||
| 132 | drm_gem_object_release(&vbo->base.base); | ||
| 133 | kfree(vbo); | ||
| 134 | } | ||
| 135 | |||
| 136 | int vmw_gem_object_create_with_handle(struct vmw_private *dev_priv, | 114 | int vmw_gem_object_create_with_handle(struct vmw_private *dev_priv, |
| 137 | struct drm_file *filp, | 115 | struct drm_file *filp, |
| 138 | uint32_t size, | 116 | uint32_t size, |
| 139 | uint32_t *handle, | 117 | uint32_t *handle, |
| 140 | struct vmw_buffer_object **p_vbo) | 118 | struct vmw_bo **p_vbo) |
| 141 | { | 119 | { |
| 142 | int ret; | 120 | int ret; |
| 143 | 121 | struct vmw_bo_params params = { | |
| 144 | ret = vmw_bo_create(dev_priv, size, | 122 | .domain = (dev_priv->has_mob) ? VMW_BO_DOMAIN_SYS : VMW_BO_DOMAIN_VRAM, |
| 145 | (dev_priv->has_mob) ? | 123 | .busy_domain = VMW_BO_DOMAIN_SYS, |
| 146 | &vmw_sys_placement : | 124 | .bo_type = ttm_bo_type_device, |
| 147 | &vmw_vram_sys_placement, | 125 | .size = size, |
| 148 | true, false, &vmw_gem_destroy, p_vbo); | 126 | .pin = false |
| 127 | }; | ||
| 128 | |||
| 129 | ret = vmw_bo_create(dev_priv, ¶ms, p_vbo); | ||
| 149 | if (ret != 0) | 130 | if (ret != 0) |
| 150 | goto out_no_bo; | 131 | goto out_no_bo; |
| 151 | 132 | ||
| 152 | (*p_vbo)->base.base.funcs = &vmw_gem_object_funcs; | 133 | (*p_vbo)->tbo.base.funcs = &vmw_gem_object_funcs; |
| 153 | 134 | ||
| 154 | ret = drm_gem_handle_create(filp, &(*p_vbo)->base.base, handle); | 135 | ret = drm_gem_handle_create(filp, &(*p_vbo)->tbo.base, handle); |
| 155 | out_no_bo: | 136 | out_no_bo: |
| 156 | return ret; | 137 | return ret; |
| 157 | } | 138 | } |
| @@ -165,7 +146,7 @@ int vmw_gem_object_create_ioctl(struct drm_device *dev, void *data, · 7 unmodified lines | |||
| 165 | (union drm_vmw_alloc_dmabuf_arg *)data; | 146 | (union drm_vmw_alloc_dmabuf_arg *)data; |
| 166 | struct drm_vmw_alloc_dmabuf_req *req = &arg->req; | 147 | struct drm_vmw_alloc_dmabuf_req *req = &arg->req; |
| 167 | struct drm_vmw_dmabuf_rep *rep = &arg->rep; | 148 | struct drm_vmw_dmabuf_rep *rep = &arg->rep; |
| 168 | struct vmw_buffer_object *vbo; | 149 | struct vmw_bo *vbo; |
| 169 | uint32_t handle; | 150 | uint32_t handle; |
| 170 | int ret; | 151 | int ret; |
| 171 | 152 | ||
| @@ -175,23 +156,23 @@ int vmw_gem_object_create_ioctl(struct drm_device *dev, void *data, · 3 unmodified lines | |||
| 175 | goto out_no_bo; | 156 | goto out_no_bo; |
| 176 | 157 | ||
| 177 | rep->handle = handle; | 158 | rep->handle = handle; |
| 178 | rep->map_handle = drm_vma_node_offset_addr(&vbo->base.base.vma_node); | 159 | rep->map_handle = drm_vma_node_offset_addr(&vbo->tbo.base.vma_node); |
| 179 | rep->cur_gmr_id = handle; | 160 | rep->cur_gmr_id = handle; |
| 180 | rep->cur_gmr_offset = 0; | 161 | rep->cur_gmr_offset = 0; |
| 181 | /* drop reference from allocate - handle holds it now */ | 162 | /* drop reference from allocate - handle holds it now */ |
| 182 | drm_gem_object_put(&vbo->base.base); | 163 | drm_gem_object_put(&vbo->tbo.base); |
| 183 | out_no_bo: | 164 | out_no_bo: |
| 184 | return ret; | 165 | return ret; |
| 185 | } | 166 | } |
| 186 | 167 | ||
| 187 | #if defined(CONFIG_DEBUG_FS) | 168 | #if defined(CONFIG_DEBUG_FS) |
| 188 | 169 | ||
| 189 | static void vmw_bo_print_info(int id, struct vmw_buffer_object *bo, struct seq_file *m) | 170 | static void vmw_bo_print_info(int id, struct vmw_bo *bo, struct seq_file *m) |
| 190 | { | 171 | { |
| 191 | const char *placement; | 172 | const char *placement; |
| 192 | const char *type; | 173 | const char *type; |
| 193 | 174 | ||
| 194 | switch (bo->base.resource->mem_type) { | 175 | switch (bo->tbo.resource->mem_type) { |
| 195 | case TTM_PL_SYSTEM: | 176 | case TTM_PL_SYSTEM: |
| 196 | placement = " CPU"; | 177 | placement = " CPU"; |
| 197 | break; | 178 | break; |
| @@ -212,7 +193,7 @@ static void vmw_bo_print_info(int id, struct vmw_buffer_object *bo, struct seq_f · 14 unmodified lines | |||
| 212 | break; | 193 | break; |
| 213 | } | 194 | } |
| 214 | 195 | ||
| 215 | switch (bo->base.type) { | 196 | switch (bo->tbo.type) { |
| 216 | case ttm_bo_type_device: | 197 | case ttm_bo_type_device: |
| 217 | type = "device"; | 198 | type = "device"; |
| 218 | break; | 199 | break; |
| @@ -228,12 +209,12 @@ static void vmw_bo_print_info(int id, struct vmw_buffer_object *bo, struct seq_f · 9 unmodified lines | |||
| 228 | } | 209 | } |
| 229 | 210 | ||
| 230 | seq_printf(m, "\t\t0x%08x: %12zu bytes %s, type = %s", | 211 | seq_printf(m, "\t\t0x%08x: %12zu bytes %s, type = %s", |
| 231 | id, bo->base.base.size, placement, type); | 212 | id, bo->tbo.base.size, placement, type); |
| 232 | seq_printf(m, ", priority = %u, pin_count = %u, GEM refs = %d, TTM refs = %d", | 213 | seq_printf(m, ", priority = %u, pin_count = %u, GEM refs = %d, TTM refs = %d", |
| 233 | bo->base.priority, | 214 | bo->tbo.priority, |
| 234 | bo->base.pin_count, | 215 | bo->tbo.pin_count, |
| 235 | kref_read(&bo->base.base.refcount), | 216 | kref_read(&bo->tbo.base.refcount), |
| 236 | kref_read(&bo->base.kref)); | 217 | kref_read(&bo->tbo.kref)); |
| 237 | seq_puts(m, "\n"); | 218 | seq_puts(m, "\n"); |
| 238 | } | 219 | } |
| 239 | 220 | ||
| @@ -267,7 +248,7 @@ static int vmw_debugfs_gem_info_show(struct seq_file *m, void *unused) · 27 unmodified lines | |||
| 267 | 248 | ||
| 268 | spin_lock(&file->table_lock); | 249 | spin_lock(&file->table_lock); |
| 269 | idr_for_each_entry(&file->object_idr, gobj, id) { | 250 | idr_for_each_entry(&file->object_idr, gobj, id) { |
| 270 | struct vmw_buffer_object *bo = gem_to_vmw_bo(gobj); | 251 | struct vmw_bo *bo = to_vmw_bo(gobj); |
| 271 | 252 | ||
| 272 | vmw_bo_print_info(id, bo, m); | 253 | vmw_bo_print_info(id, bo, m); |
| 273 | } | 254 | } |
| @@ -1,7 +1,7 @@ | |||
| 1 | // SPDX-License-Identifier: GPL-2.0 OR MIT | 1 | // SPDX-License-Identifier: GPL-2.0 OR MIT |
| 2 | /************************************************************************** | 2 | /************************************************************************** |
| 3 | * | 3 | * |
| 4 | * Copyright 2009-2022 VMware, Inc., Palo Alto, CA., USA | 4 | * Copyright 2009-2023 VMware, Inc., Palo Alto, CA., USA |
| 5 | * | 5 | * |
| 6 | * Permission is hereby granted, free of charge, to any person obtaining a | 6 | * Permission is hereby granted, free of charge, to any person obtaining a |
| 7 | * copy of this software and associated documentation files (the | 7 | * copy of this software and associated documentation files (the |
| @@ -24,8 +24,9 @@ · 16 unmodified lines | |||
| 24 | * USE OR OTHER DEALINGS IN THE SOFTWARE. | 24 | * USE OR OTHER DEALINGS IN THE SOFTWARE. |
| 25 | * | 25 | * |
| 26 | **************************************************************************/ | 26 | **************************************************************************/ |
| 27 | |||
| 28 | #include "vmwgfx_kms.h" | 27 | #include "vmwgfx_kms.h" |
| 28 | |||
| 29 | #include "vmwgfx_bo.h" | ||
| 29 | #include "vmw_surface_cache.h" | 30 | #include "vmw_surface_cache.h" |
| 30 | 31 | ||
| 31 | #include <drm/drm_atomic.h> | 32 | #include <drm/drm_atomic.h> |
| @@ -152,9 +153,8 @@ static void vmw_cursor_update_mob(struct vmw_private *dev_priv, · 120 unmodified lines | |||
| 152 | SVGAGBCursorHeader *header; | 153 | SVGAGBCursorHeader *header; |
| 153 | SVGAGBAlphaCursorHeader *alpha_header; | 154 | SVGAGBAlphaCursorHeader *alpha_header; |
| 154 | const u32 image_size = width * height * sizeof(*image); | 155 | const u32 image_size = width * height * sizeof(*image); |
| 155 | bool dummy; | ||
| 156 | 156 | ||
| 157 | header = ttm_kmap_obj_virtual(&vps->cursor.map, &dummy); | 157 | header = vmw_bo_map_and_cache(vps->cursor.bo); |
| 158 | alpha_header = &header->header.alphaHeader; | 158 | alpha_header = &header->header.alphaHeader; |
| 159 | 159 | ||
| 160 | memset(header, 0, sizeof(*header)); | 160 | memset(header, 0, sizeof(*header)); |
| @@ -169,7 +169,7 @@ static void vmw_cursor_update_mob(struct vmw_private *dev_priv, · 8 unmodified lines | |||
| 169 | 169 | ||
| 170 | memcpy(header + 1, image, image_size); | 170 | memcpy(header + 1, image, image_size); |
| 171 | vmw_write(dev_priv, SVGA_REG_CURSOR_MOBID, | 171 | vmw_write(dev_priv, SVGA_REG_CURSOR_MOBID, |
| 172 | vps->cursor.bo->resource->start); | 172 | vps->cursor.bo->tbo.resource->start); |
| 173 | } | 173 | } |
| 174 | 174 | ||
| 175 | 175 | ||
| @@ -184,13 +184,13 @@ static u32 vmw_du_cursor_mob_size(u32 w, u32 h) · 8 unmodified lines | |||
| 184 | */ | 184 | */ |
| 185 | static u32 *vmw_du_cursor_plane_acquire_image(struct vmw_plane_state *vps) | 185 | static u32 *vmw_du_cursor_plane_acquire_image(struct vmw_plane_state *vps) |
| 186 | { | 186 | { |
| 187 | bool dummy; | 187 | bool is_iomem; |
| 188 | if (vps->surf) { | 188 | if (vps->surf) { |
| 189 | if (vps->surf_mapped) | 189 | if (vps->surf_mapped) |
| 190 | return vmw_bo_map_and_cache(vps->surf->res.backup); | 190 | return vmw_bo_map_and_cache(vps->surf->res.guest_memory_bo); |
| 191 | return vps->surf->snooper.image; | 191 | return vps->surf->snooper.image; |
| 192 | } else if (vps->bo) | 192 | } else if (vps->bo) |
| 193 | return ttm_kmap_obj_virtual(&vps->bo->map, &dummy); | 193 | return ttm_kmap_obj_virtual(&vps->bo->map, &is_iomem); |
| 194 | return NULL; | 194 | return NULL; |
| 195 | } | 195 | } |
| 196 | 196 | ||
| @@ -222,15 +222,13 @@ static bool vmw_du_cursor_plane_has_changed(struct vmw_plane_state *old_vps, · 25 unmodified lines | |||
| 222 | return changed; | 222 | return changed; |
| 223 | } | 223 | } |
| 224 | 224 | ||
| 225 | static void vmw_du_destroy_cursor_mob(struct ttm_buffer_object **bo) | 225 | static void vmw_du_destroy_cursor_mob(struct vmw_bo **vbo) |
| 226 | { | 226 | { |
| 227 | if (!(*bo)) | 227 | if (!(*vbo)) |
| 228 | return; | 228 | return; |
| 229 | 229 | ||
| 230 | ttm_bo_unpin(*bo); | 230 | ttm_bo_unpin(&(*vbo)->tbo); |
| 231 | ttm_bo_put(*bo); | 231 | vmw_bo_unreference(vbo); |
| 232 | kfree(*bo); | ||
| 233 | *bo = NULL; | ||
| 234 | } | 232 | } |
| 235 | 233 | ||
| 236 | static void vmw_du_put_cursor_mob(struct vmw_cursor_plane *vcp, | 234 | static void vmw_du_put_cursor_mob(struct vmw_cursor_plane *vcp, |
| @@ -254,8 +252,8 @@ static void vmw_du_put_cursor_mob(struct vmw_cursor_plane *vcp, · 17 unmodified lines | |||
| 254 | 252 | ||
| 255 | /* Cache is full: See if this mob is bigger than an existing mob. */ | 253 | /* Cache is full: See if this mob is bigger than an existing mob. */ |
| 256 | for (i = 0; i < ARRAY_SIZE(vcp->cursor_mobs); i++) { | 254 | for (i = 0; i < ARRAY_SIZE(vcp->cursor_mobs); i++) { |
| 257 | if (vcp->cursor_mobs[i]->base.size < | 255 | if (vcp->cursor_mobs[i]->tbo.base.size < |
| 258 | vps->cursor.bo->base.size) { | 256 | vps->cursor.bo->tbo.base.size) { |
| 259 | vmw_du_destroy_cursor_mob(&vcp->cursor_mobs[i]); | 257 | vmw_du_destroy_cursor_mob(&vcp->cursor_mobs[i]); |
| 260 | vcp->cursor_mobs[i] = vps->cursor.bo; | 258 | vcp->cursor_mobs[i] = vps->cursor.bo; |
| 261 | vps->cursor.bo = NULL; | 259 | vps->cursor.bo = NULL; |
| @@ -288,7 +286,7 @@ static int vmw_du_get_cursor_mob(struct vmw_cursor_plane *vcp, · 26 unmodified lines | |||
| 288 | return -EINVAL; | 286 | return -EINVAL; |
| 289 | 287 | ||
| 290 | if (vps->cursor.bo) { | 288 | if (vps->cursor.bo) { |
| 291 | if (vps->cursor.bo->base.size >= size) | 289 | if (vps->cursor.bo->tbo.base.size >= size) |
| 292 | return 0; | 290 | return 0; |
| 293 | vmw_du_put_cursor_mob(vcp, vps); | 291 | vmw_du_put_cursor_mob(vcp, vps); |
| 294 | } | 292 | } |
| @@ -296,26 +294,27 @@ static int vmw_du_get_cursor_mob(struct vmw_cursor_plane *vcp, · 1 unmodified line | |||
| 296 | /* Look for an unused mob in the cache. */ | 294 | /* Look for an unused mob in the cache. */ |
| 297 | for (i = 0; i < ARRAY_SIZE(vcp->cursor_mobs); i++) { | 295 | for (i = 0; i < ARRAY_SIZE(vcp->cursor_mobs); i++) { |
| 298 | if (vcp->cursor_mobs[i] && | 296 | if (vcp->cursor_mobs[i] && |
| 299 | vcp->cursor_mobs[i]->base.size >= size) { | 297 | vcp->cursor_mobs[i]->tbo.base.size >= size) { |
| 300 | vps->cursor.bo = vcp->cursor_mobs[i]; | 298 | vps->cursor.bo = vcp->cursor_mobs[i]; |
| 301 | vcp->cursor_mobs[i] = NULL; | 299 | vcp->cursor_mobs[i] = NULL; |
| 302 | return 0; | 300 | return 0; |
| 303 | } | 301 | } |
| 304 | } | 302 | } |
| 305 | /* Create a new mob if we can't find an existing one. */ | 303 | /* Create a new mob if we can't find an existing one. */ |
| 306 | ret = vmw_bo_create_kernel(dev_priv, size, &vmw_mob_placement, | 304 | ret = vmw_bo_create_and_populate(dev_priv, size, |
| 307 | &vps->cursor.bo); | 305 | VMW_BO_DOMAIN_MOB, |
| 306 | &vps->cursor.bo); | ||
| 308 | 307 | ||
| 309 | if (ret != 0) | 308 | if (ret != 0) |
| 310 | return ret; | 309 | return ret; |
| 311 | 310 | ||
| 312 | /* Fence the mob creation so we are guarateed to have the mob */ | 311 | /* Fence the mob creation so we are guarateed to have the mob */ |
| 313 | ret = ttm_bo_reserve(vps->cursor.bo, false, false, NULL); | 312 | ret = ttm_bo_reserve(&vps->cursor.bo->tbo, false, false, NULL); |
| 314 | if (ret != 0) | 313 | if (ret != 0) |
| 315 | goto teardown; | 314 | goto teardown; |
| 316 | 315 | ||
| 317 | vmw_bo_fence_single(vps->cursor.bo, NULL); | 316 | vmw_bo_fence_single(&vps->cursor.bo->tbo, NULL); |
| 318 | ttm_bo_unreserve(vps->cursor.bo); | 317 | ttm_bo_unreserve(&vps->cursor.bo->tbo); |
| 319 | return 0; | 318 | return 0; |
| 320 | 319 | ||
| 321 | teardown: | 320 | teardown: |
| @@ -363,7 +362,7 @@ void vmw_kms_cursor_snoop(struct vmw_surface *srf, · 41 unmodified lines | |||
| 363 | SVGA3dCopyBox *box; | 362 | SVGA3dCopyBox *box; |
| 364 | unsigned box_count; | 363 | unsigned box_count; |
| 365 | void *virtual; | 364 | void *virtual; |
| 366 | bool dummy; | 365 | bool is_iomem; |
| 367 | struct vmw_dma_cmd { | 366 | struct vmw_dma_cmd { |
| 368 | SVGA3dCmdHeader header; | 367 | SVGA3dCmdHeader header; |
| 369 | SVGA3dCmdSurfaceDMA dma; | 368 | SVGA3dCmdSurfaceDMA dma; |
| @@ -423,7 +422,7 @@ void vmw_kms_cursor_snoop(struct vmw_surface *srf, · 53 unmodified lines | |||
| 423 | if (unlikely(ret != 0)) | 422 | if (unlikely(ret != 0)) |
| 424 | goto err_unreserve; | 423 | goto err_unreserve; |
| 425 | 424 | ||
| 426 | virtual = ttm_kmap_obj_virtual(&map, &dummy); | 425 | virtual = ttm_kmap_obj_virtual(&map, &is_iomem); |
| 427 | 426 | ||
| 428 | if (box->w == VMW_CURSOR_SNOOP_WIDTH && cmd->dma.guest.pitch == image_pitch) { | 427 | if (box->w == VMW_CURSOR_SNOOP_WIDTH && cmd->dma.guest.pitch == image_pitch) { |
| 429 | memcpy(srf->snooper.image, virtual, | 428 | memcpy(srf->snooper.image, virtual, |
| @@ -573,39 +572,30 @@ vmw_du_cursor_plane_map_cm(struct vmw_plane_state *vps) · 143 unmodified lines | |||
| 573 | { | 572 | { |
| 574 | int ret; | 573 | int ret; |
| 575 | u32 size = vmw_du_cursor_mob_size(vps->base.crtc_w, vps->base.crtc_h); | 574 | u32 size = vmw_du_cursor_mob_size(vps->base.crtc_w, vps->base.crtc_h); |
| 576 | struct ttm_buffer_object *bo = vps->cursor.bo; | 575 | struct ttm_buffer_object *bo; |
| 577 | 576 | ||
| 578 | if (!bo) | 577 | if (!vps->cursor.bo) |
| 579 | return -EINVAL; | 578 | return -EINVAL; |
| 580 | 579 | ||
| 580 | bo = &vps->cursor.bo->tbo; | ||
| 581 | |||
| 581 | if (bo->base.size < size) | 582 | if (bo->base.size < size) |
| 582 | return -EINVAL; | 583 | return -EINVAL; |
| 583 | 584 | ||
| 584 | if (vps->cursor.mapped) | 585 | if (vps->cursor.bo->map.virtual) |
| 585 | return 0; | 586 | return 0; |
| 586 | 587 | ||
| 587 | ret = ttm_bo_reserve(bo, false, false, NULL); | 588 | ret = ttm_bo_reserve(bo, false, false, NULL); |
| 588 | |||
| 589 | if (unlikely(ret != 0)) | 589 | if (unlikely(ret != 0)) |
| 590 | return -ENOMEM; | 590 | return -ENOMEM; |
| 591 | 591 | ||
| 592 | ret = ttm_bo_kmap(bo, 0, PFN_UP(size), &vps->cursor.map); | 592 | vmw_bo_map_and_cache(vps->cursor.bo); |
| 593 | |||
| 594 | /* | ||
| 595 | * We just want to try to get mob bind to finish | ||
| 596 | * so that the first write to SVGA_REG_CURSOR_MOBID | ||
| 597 | * is done with a buffer that the device has already | ||
| 598 | * seen | ||
| 599 | */ | ||
| 600 | (void) ttm_bo_wait(bo, false, false); | ||
| 601 | 593 | ||
| 602 | ttm_bo_unreserve(bo); | 594 | ttm_bo_unreserve(bo); |
| 603 | 595 | ||
| 604 | if (unlikely(ret != 0)) | 596 | if (unlikely(ret != 0)) |
| 605 | return -ENOMEM; | 597 | return -ENOMEM; |
| 606 | 598 | ||
| 607 | vps->cursor.mapped = true; | ||
| 608 | |||
| 609 | return 0; | 599 | return 0; |
| 610 | } | 600 | } |
| 611 | 601 | ||
| @@ -622,19 +612,15 @@ static int · 10 unmodified lines | |||
| 622 | vmw_du_cursor_plane_unmap_cm(struct vmw_plane_state *vps) | 612 | vmw_du_cursor_plane_unmap_cm(struct vmw_plane_state *vps) |
| 623 | { | 613 | { |
| 624 | int ret = 0; | 614 | int ret = 0; |
| 625 | struct ttm_buffer_object *bo = vps->cursor.bo; | 615 | struct vmw_bo *vbo = vps->cursor.bo; |
| 626 | |||
| 627 | if (!vps->cursor.mapped) | ||
| 628 | return 0; | ||
| 629 | 616 | ||
| 630 | if (!bo) | 617 | if (!vbo || !vbo->map.virtual) |
| 631 | return 0; | 618 | return 0; |
| 632 | 619 | ||
| 633 | ret = ttm_bo_reserve(bo, true, false, NULL); | 620 | ret = ttm_bo_reserve(&vbo->tbo, true, false, NULL); |
| 634 | if (likely(ret == 0)) { | 621 | if (likely(ret == 0)) { |
| 635 | ttm_bo_kunmap(&vps->cursor.map); | 622 | vmw_bo_unmap(vbo); |
| 636 | ttm_bo_unreserve(bo); | 623 | ttm_bo_unreserve(&vbo->tbo); |
| 637 | vps->cursor.mapped = false; | ||
| 638 | } | 624 | } |
| 639 | 625 | ||
| 640 | return ret; | 626 | return ret; |
| @@ -657,20 +643,19 @@ vmw_du_cursor_plane_cleanup_fb(struct drm_plane *plane, · 16 unmodified lines | |||
| 657 | { | 643 | { |
| 658 | struct vmw_cursor_plane *vcp = vmw_plane_to_vcp(plane); | 644 | struct vmw_cursor_plane *vcp = vmw_plane_to_vcp(plane); |
| 659 | struct vmw_plane_state *vps = vmw_plane_state_to_vps(old_state); | 645 | struct vmw_plane_state *vps = vmw_plane_state_to_vps(old_state); |
| 660 | bool dummy; | 646 | bool is_iomem; |
| 661 | 647 | ||
| 662 | if (vps->surf_mapped) { | 648 | if (vps->surf_mapped) { |
| 663 | vmw_bo_unmap(vps->surf->res.backup); | 649 | vmw_bo_unmap(vps->surf->res.guest_memory_bo); |
| 664 | vps->surf_mapped = false; | 650 | vps->surf_mapped = false; |
| 665 | } | 651 | } |
| 666 | 652 | ||
| 667 | if (vps->bo && ttm_kmap_obj_virtual(&vps->bo->map, &dummy)) { | 653 | if (vps->bo && ttm_kmap_obj_virtual(&vps->bo->map, &is_iomem)) { |
| 668 | const int ret = ttm_bo_reserve(&vps->bo->base, true, false, NULL); | 654 | const int ret = ttm_bo_reserve(&vps->bo->tbo, true, false, NULL); |
| 669 | 655 | ||
| 670 | if (likely(ret == 0)) { | 656 | if (likely(ret == 0)) { |
| 671 | if (atomic_read(&vps->bo->base_mapped_count) == 0) | 657 | ttm_bo_kunmap(&vps->bo->map); |
| 672 | ttm_bo_kunmap(&vps->bo->map); | 658 | ttm_bo_unreserve(&vps->bo->tbo); |
| 673 | ttm_bo_unreserve(&vps->bo->base); | ||
| 674 | } | 659 | } |
| 675 | } | 660 | } |
| 676 | 661 | ||
| @@ -736,29 +721,26 @@ vmw_du_cursor_plane_prepare_fb(struct drm_plane *plane, · 59 unmodified lines | |||
| 736 | * reserve the ttm_buffer_object first which | 721 | * reserve the ttm_buffer_object first which |
| 737 | * vmw_bo_map_and_cache() omits. | 722 | * vmw_bo_map_and_cache() omits. |
| 738 | */ | 723 | */ |
| 739 | ret = ttm_bo_reserve(&vps->bo->base, true, false, NULL); | 724 | ret = ttm_bo_reserve(&vps->bo->tbo, true, false, NULL); |
| 740 | 725 | ||
| 741 | if (unlikely(ret != 0)) | 726 | if (unlikely(ret != 0)) |
| 742 | return -ENOMEM; | 727 | return -ENOMEM; |
| 743 | 728 | ||
| 744 | ret = ttm_bo_kmap(&vps->bo->base, 0, PFN_UP(size), &vps->bo->map); | 729 | ret = ttm_bo_kmap(&vps->bo->tbo, 0, PFN_UP(size), &vps->bo->map); |
| 745 | |||
| 746 | if (likely(ret == 0)) | ||
| 747 | atomic_inc(&vps->bo->base_mapped_count); | ||
| 748 | 730 | ||
| 749 | ttm_bo_unreserve(&vps->bo->base); | 731 | ttm_bo_unreserve(&vps->bo->tbo); |
| 750 | 732 | ||
| 751 | if (unlikely(ret != 0)) | 733 | if (unlikely(ret != 0)) |
| 752 | return -ENOMEM; | 734 | return -ENOMEM; |
| 753 | } else if (vps->surf && !vps->bo && vps->surf->res.backup) { | 735 | } else if (vps->surf && !vps->bo && vps->surf->res.guest_memory_bo) { |
| 754 | 736 | ||
| 755 | WARN_ON(vps->surf->snooper.image); | 737 | WARN_ON(vps->surf->snooper.image); |
| 756 | ret = ttm_bo_reserve(&vps->surf->res.backup->base, true, false, | 738 | ret = ttm_bo_reserve(&vps->surf->res.guest_memory_bo->tbo, true, false, |
| 757 | NULL); | 739 | NULL); |
| 758 | if (unlikely(ret != 0)) | 740 | if (unlikely(ret != 0)) |
| 759 | return -ENOMEM; | 741 | return -ENOMEM; |
| 760 | vmw_bo_map_and_cache(vps->surf->res.backup); | 742 | vmw_bo_map_and_cache(vps->surf->res.guest_memory_bo); |
| 761 | ttm_bo_unreserve(&vps->surf->res.backup->base); | 743 | ttm_bo_unreserve(&vps->surf->res.guest_memory_bo->tbo); |
| 762 | vps->surf_mapped = true; | 744 | vps->surf_mapped = true; |
| 763 | } | 745 | } |
| 764 | 746 | ||
| @@ -785,7 +767,6 @@ vmw_du_cursor_plane_atomic_update(struct drm_plane *plane, · 20 unmodified lines | |||
| 785 | struct vmw_plane_state *vps = vmw_plane_state_to_vps(new_state); | 767 | struct vmw_plane_state *vps = vmw_plane_state_to_vps(new_state); |
| 786 | struct vmw_plane_state *old_vps = vmw_plane_state_to_vps(old_state); | 768 | struct vmw_plane_state *old_vps = vmw_plane_state_to_vps(old_state); |
| 787 | s32 hotspot_x, hotspot_y; | 769 | s32 hotspot_x, hotspot_y; |
| 788 | bool dummy; | ||
| 789 | 770 | ||
| 790 | hotspot_x = du->hotspot_x; | 771 | hotspot_x = du->hotspot_x; |
| 791 | hotspot_y = du->hotspot_y; | 772 | hotspot_y = du->hotspot_y; |
| @@ -827,11 +808,6 @@ vmw_du_cursor_plane_atomic_update(struct drm_plane *plane, · 35 unmodified lines | |||
| 827 | hotspot_x, hotspot_y); | 808 | hotspot_x, hotspot_y); |
| 828 | } | 809 | } |
| 829 | 810 | ||
| 830 | if (vps->bo) { | ||
| 831 | if (ttm_kmap_obj_virtual(&vps->bo->map, &dummy)) | ||
| 832 | atomic_dec(&vps->bo->base_mapped_count); | ||
| 833 | } | ||
| 834 | |||
| 835 | du->cursor_x = new_state->crtc_x + du->set_gui_x; | 811 | du->cursor_x = new_state->crtc_x + du->set_gui_x; |
| 836 | du->cursor_y = new_state->crtc_y + du->set_gui_y; | 812 | du->cursor_y = new_state->crtc_y + du->set_gui_y; |
| 837 | 813 | ||
| @@ -935,7 +911,7 @@ int vmw_du_cursor_plane_atomic_check(struct drm_plane *plane, · 97 unmodified lines | |||
| 935 | WARN_ON(!surface); | 911 | WARN_ON(!surface); |
| 936 | 912 | ||
| 937 | if (!surface || | 913 | if (!surface || |
| 938 | (!surface->snooper.image && !surface->res.backup)) { | 914 | (!surface->snooper.image && !surface->res.guest_memory_bo)) { |
| 939 | DRM_ERROR("surface not suitable for cursor\n"); | 915 | DRM_ERROR("surface not suitable for cursor\n"); |
| 940 | return -EINVAL; | 916 | return -EINVAL; |
| 941 | } | 917 | } |
| @@ -1279,9 +1255,9 @@ int vmw_kms_readback(struct vmw_private *dev_priv, · 337 unmodified lines | |||
| 1279 | user_fence_rep, vclips, num_clips, | 1255 | user_fence_rep, vclips, num_clips, |
| 1280 | NULL); | 1256 | NULL); |
| 1281 | case vmw_du_screen_target: | 1257 | case vmw_du_screen_target: |
| 1282 | return vmw_kms_stdu_dma(dev_priv, file_priv, vfb, | 1258 | return vmw_kms_stdu_readback(dev_priv, file_priv, vfb, |
| 1283 | user_fence_rep, NULL, vclips, num_clips, | 1259 | user_fence_rep, NULL, vclips, num_clips, |
| 1284 | 1, false, true, NULL); | 1260 | 1, NULL); |
| 1285 | default: | 1261 | default: |
| 1286 | WARN_ONCE(true, | 1262 | WARN_ONCE(true, |
| 1287 | "Readback called with invalid display system.\n"); | 1263 | "Readback called with invalid display system.\n"); |
| @@ -1406,7 +1382,7 @@ static int vmw_framebuffer_bo_create_handle(struct drm_framebuffer *fb, · 118 unmodified lines | |||
| 1406 | struct vmw_framebuffer_bo *vfbd = | 1382 | struct vmw_framebuffer_bo *vfbd = |
| 1407 | vmw_framebuffer_to_vfbd(fb); | 1383 | vmw_framebuffer_to_vfbd(fb); |
| 1408 | 1384 | ||
| 1409 | return drm_gem_handle_create(file_priv, &vfbd->buffer->base.base, handle); | 1385 | return drm_gem_handle_create(file_priv, &vfbd->buffer->tbo.base, handle); |
| 1410 | } | 1386 | } |
| 1411 | 1387 | ||
| 1412 | static void vmw_framebuffer_bo_destroy(struct drm_framebuffer *framebuffer) | 1388 | static void vmw_framebuffer_bo_destroy(struct drm_framebuffer *framebuffer) |
| @@ -1486,69 +1462,6 @@ static const struct drm_framebuffer_funcs vmw_framebuffer_bo_funcs = { · 73 unmodified lines | |||
| 1486 | .dirty = vmw_framebuffer_bo_dirty_ext, | 1462 | .dirty = vmw_framebuffer_bo_dirty_ext, |
| 1487 | }; | 1463 | }; |
| 1488 | 1464 | ||
| 1489 | /* | ||
| 1490 | * Pin the bofer in a location suitable for access by the | ||
| 1491 | * display system. | ||
| 1492 | */ | ||
| 1493 | static int vmw_framebuffer_pin(struct vmw_framebuffer *vfb) | ||
| 1494 | { | ||
| 1495 | struct vmw_private *dev_priv = vmw_priv(vfb->base.dev); | ||
| 1496 | struct vmw_buffer_object *buf; | ||
| 1497 | struct ttm_placement *placement; | ||
| 1498 | int ret; | ||
| 1499 | |||
| 1500 | buf = vfb->bo ? vmw_framebuffer_to_vfbd(&vfb->base)->buffer : | ||
| 1501 | vmw_framebuffer_to_vfbs(&vfb->base)->surface->res.backup; | ||
| 1502 | |||
| 1503 | if (!buf) | ||
| 1504 | return 0; | ||
| 1505 | |||
| 1506 | switch (dev_priv->active_display_unit) { | ||
| 1507 | case vmw_du_legacy: | ||
| 1508 | vmw_overlay_pause_all(dev_priv); | ||
| 1509 | ret = vmw_bo_pin_in_start_of_vram(dev_priv, buf, false); | ||
| 1510 | vmw_overlay_resume_all(dev_priv); | ||
| 1511 | break; | ||
| 1512 | case vmw_du_screen_object: | ||
| 1513 | case vmw_du_screen_target: | ||
| 1514 | if (vfb->bo) { | ||
| 1515 | if (dev_priv->capabilities & SVGA_CAP_3D) { | ||
| 1516 | /* | ||
| 1517 | * Use surface DMA to get content to | ||
| 1518 | * sreen target surface. | ||
| 1519 | */ | ||
| 1520 | placement = &vmw_vram_gmr_placement; | ||
| 1521 | } else { | ||
| 1522 | /* Use CPU blit. */ | ||
| 1523 | placement = &vmw_sys_placement; | ||
| 1524 | } | ||
| 1525 | } else { | ||
| 1526 | /* Use surface / image update */ | ||
| 1527 | placement = &vmw_mob_placement; | ||
| 1528 | } | ||
| 1529 | |||
| 1530 | return vmw_bo_pin_in_placement(dev_priv, buf, placement, false); | ||
| 1531 | default: | ||
| 1532 | return -EINVAL; | ||
| 1533 | } | ||
| 1534 | |||
| 1535 | return ret; | ||
| 1536 | } | ||
| 1537 | |||
| 1538 | static int vmw_framebuffer_unpin(struct vmw_framebuffer *vfb) | ||
| 1539 | { | ||
| 1540 | struct vmw_private *dev_priv = vmw_priv(vfb->base.dev); | ||
| 1541 | struct vmw_buffer_object *buf; | ||
| 1542 | |||
| 1543 | buf = vfb->bo ? vmw_framebuffer_to_vfbd(&vfb->base)->buffer : | ||
| 1544 | vmw_framebuffer_to_vfbs(&vfb->base)->surface->res.backup; | ||
| 1545 | |||
| 1546 | if (WARN_ON(!buf)) | ||
| 1547 | return 0; | ||
| 1548 | |||
| 1549 | return vmw_bo_unpin(dev_priv, buf, false); | ||
| 1550 | } | ||
| 1551 | |||
| 1552 | /** | 1465 | /** |
| 1553 | * vmw_create_bo_proxy - create a proxy surface for the buffer object | 1466 | * vmw_create_bo_proxy - create a proxy surface for the buffer object |
| 1554 | * | 1467 | * |
| @@ -1566,7 +1479,7 @@ static int vmw_framebuffer_unpin(struct vmw_framebuffer *vfb) · 11 unmodified lines | |||
| 1566 | */ | 1479 | */ |
| 1567 | static int vmw_create_bo_proxy(struct drm_device *dev, | 1480 | static int vmw_create_bo_proxy(struct drm_device *dev, |
| 1568 | const struct drm_mode_fb_cmd2 *mode_cmd, | 1481 | const struct drm_mode_fb_cmd2 *mode_cmd, |
| 1569 | struct vmw_buffer_object *bo_mob, | 1482 | struct vmw_bo *bo_mob, |
| 1570 | struct vmw_surface **srf_out) | 1483 | struct vmw_surface **srf_out) |
| 1571 | { | 1484 | { |
| 1572 | struct vmw_surface_metadata metadata = {0}; | 1485 | struct vmw_surface_metadata metadata = {0}; |
| @@ -1618,9 +1531,9 @@ static int vmw_create_bo_proxy(struct drm_device *dev, · 45 unmodified lines | |||
| 1618 | /* Reserve and switch the backing mob. */ | 1531 | /* Reserve and switch the backing mob. */ |
| 1619 | mutex_lock(&res->dev_priv->cmdbuf_mutex); | 1532 | mutex_lock(&res->dev_priv->cmdbuf_mutex); |
| 1620 | (void) vmw_resource_reserve(res, false, true); | 1533 | (void) vmw_resource_reserve(res, false, true); |
| 1621 | vmw_bo_unreference(&res->backup); | 1534 | vmw_bo_unreference(&res->guest_memory_bo); |
| 1622 | res->backup = vmw_bo_reference(bo_mob); | 1535 | res->guest_memory_bo = vmw_bo_reference(bo_mob); |
| 1623 | res->backup_offset = 0; | 1536 | res->guest_memory_offset = 0; |
| 1624 | vmw_resource_unreserve(res, false, false, false, NULL, 0); | 1537 | vmw_resource_unreserve(res, false, false, false, NULL, 0); |
| 1625 | mutex_unlock(&res->dev_priv->cmdbuf_mutex); | 1538 | mutex_unlock(&res->dev_priv->cmdbuf_mutex); |
| 1626 | 1539 | ||
| @@ -1630,7 +1543,7 @@ static int vmw_create_bo_proxy(struct drm_device *dev, · 3 unmodified lines | |||
| 1630 | 1543 | ||
| 1631 | 1544 | ||
| 1632 | static int vmw_kms_new_framebuffer_bo(struct vmw_private *dev_priv, | 1545 | static int vmw_kms_new_framebuffer_bo(struct vmw_private *dev_priv, |
| 1633 | struct vmw_buffer_object *bo, | 1546 | struct vmw_bo *bo, |
| 1634 | struct vmw_framebuffer **out, | 1547 | struct vmw_framebuffer **out, |
| 1635 | const struct drm_mode_fb_cmd2 | 1548 | const struct drm_mode_fb_cmd2 |
| 1636 | *mode_cmd) | 1549 | *mode_cmd) |
| @@ -1642,7 +1555,7 @@ static int vmw_kms_new_framebuffer_bo(struct vmw_private *dev_priv, · 5 unmodified lines | |||
| 1642 | int ret; | 1555 | int ret; |
| 1643 | 1556 | ||
| 1644 | requested_size = mode_cmd->height * mode_cmd->pitches[0]; | 1557 | requested_size = mode_cmd->height * mode_cmd->pitches[0]; |
| 1645 | if (unlikely(requested_size > bo->base.base.size)) { | 1558 | if (unlikely(requested_size > bo->tbo.base.size)) { |
| 1646 | DRM_ERROR("Screen buffer object size is too small " | 1559 | DRM_ERROR("Screen buffer object size is too small " |
| 1647 | "for requested mode.\n"); | 1560 | "for requested mode.\n"); |
| 1648 | return -EINVAL; | 1561 | return -EINVAL; |
| @@ -1663,7 +1576,7 @@ static int vmw_kms_new_framebuffer_bo(struct vmw_private *dev_priv, · 14 unmodified lines | |||
| 1663 | goto out_err1; | 1576 | goto out_err1; |
| 1664 | } | 1577 | } |
| 1665 | 1578 | ||
| 1666 | vfbd->base.base.obj[0] = &bo->base.base; | 1579 | vfbd->base.base.obj[0] = &bo->tbo.base; |
| 1667 | drm_helper_mode_fill_fb_struct(dev, &vfbd->base.base, mode_cmd); | 1580 | drm_helper_mode_fill_fb_struct(dev, &vfbd->base.base, mode_cmd); |
| 1668 | vfbd->base.bo = true; | 1581 | vfbd->base.bo = true; |
| 1669 | vfbd->buffer = vmw_bo_reference(bo); | 1582 | vfbd->buffer = vmw_bo_reference(bo); |
| @@ -1718,7 +1631,7 @@ vmw_kms_srf_ok(struct vmw_private *dev_priv, uint32_t width, uint32_t height) · 48 unmodified lines | |||
| 1718 | */ | 1631 | */ |
| 1719 | struct vmw_framebuffer * | 1632 | struct vmw_framebuffer * |
| 1720 | vmw_kms_new_framebuffer(struct vmw_private *dev_priv, | 1633 | vmw_kms_new_framebuffer(struct vmw_private *dev_priv, |
| 1721 | struct vmw_buffer_object *bo, | 1634 | struct vmw_bo *bo, |
| 1722 | struct vmw_surface *surface, | 1635 | struct vmw_surface *surface, |
| 1723 | bool only_2d, | 1636 | bool only_2d, |
| 1724 | const struct drm_mode_fb_cmd2 *mode_cmd) | 1637 | const struct drm_mode_fb_cmd2 *mode_cmd) |
| @@ -1765,9 +1678,6 @@ vmw_kms_new_framebuffer(struct vmw_private *dev_priv, · 40 unmodified lines | |||
| 1765 | if (ret) | 1678 | if (ret) |
| 1766 | return ERR_PTR(ret); | 1679 | return ERR_PTR(ret); |
| 1767 | 1680 | ||
| 1768 | vfb->pin = vmw_framebuffer_pin; | ||
| 1769 | vfb->unpin = vmw_framebuffer_unpin; | ||
| 1770 | |||
| 1771 | return vfb; | 1681 | return vfb; |
| 1772 | } | 1682 | } |
| 1773 | 1683 | ||
| @@ -1782,7 +1692,7 @@ static struct drm_framebuffer *vmw_kms_fb_create(struct drm_device *dev, · 8 unmodified lines | |||
| 1782 | struct vmw_private *dev_priv = vmw_priv(dev); | 1692 | struct vmw_private *dev_priv = vmw_priv(dev); |
| 1783 | struct vmw_framebuffer *vfb = NULL; | 1693 | struct vmw_framebuffer *vfb = NULL; |
| 1784 | struct vmw_surface *surface = NULL; | 1694 | struct vmw_surface *surface = NULL; |
| 1785 | struct vmw_buffer_object *bo = NULL; | 1695 | struct vmw_bo *bo = NULL; |
| 1786 | int ret; | 1696 | int ret; |
| 1787 | 1697 | ||
| 1788 | /* returns either a bo or surface */ | 1698 | /* returns either a bo or surface */ |
| @@ -1817,7 +1727,7 @@ err_out: · 28 unmodified lines | |||
| 1817 | /* vmw_user_lookup_handle takes one ref so does new_fb */ | 1727 | /* vmw_user_lookup_handle takes one ref so does new_fb */ |
| 1818 | if (bo) { | 1728 | if (bo) { |
| 1819 | vmw_bo_unreference(&bo); | 1729 | vmw_bo_unreference(&bo); |
| 1820 | drm_gem_object_put(&bo->base.base); | 1730 | drm_gem_object_put(&bo->tbo.base); |
| 1821 | } | 1731 | } |
| 1822 | if (surface) | 1732 | if (surface) |
| 1823 | vmw_surface_unreference(&surface); | 1733 | vmw_surface_unreference(&surface); |
| @@ -3076,8 +2986,20 @@ int vmw_du_helper_plane_update(struct vmw_du_update_plane *update) · 1252 unmodified lines | |||
| 3076 | struct vmw_framebuffer_bo *vfbbo = | 2986 | struct vmw_framebuffer_bo *vfbbo = |
| 3077 | container_of(update->vfb, typeof(*vfbbo), base); | 2987 | container_of(update->vfb, typeof(*vfbbo), base); |
| 3078 | 2988 | ||
| 3079 | ret = vmw_validation_add_bo(&val_ctx, vfbbo->buffer, false, | 2989 | /* |
| 3080 | update->cpu_blit); | 2990 | * For screen targets we want a mappable bo, for everything else we want |
| 2991 | * accelerated i.e. host backed (vram or gmr) bo. If the display unit | ||
| 2992 | * is not screen target then mob's shouldn't be available. | ||
| 2993 | */ | ||
| 2994 | if (update->dev_priv->active_display_unit == vmw_du_screen_target) { | ||
| 2995 | vmw_bo_placement_set(vfbbo->buffer, | ||
| 2996 | VMW_BO_DOMAIN_SYS | VMW_BO_DOMAIN_MOB | VMW_BO_DOMAIN_GMR, | ||
| 2997 | VMW_BO_DOMAIN_SYS | VMW_BO_DOMAIN_MOB | VMW_BO_DOMAIN_GMR); | ||
| 2998 | } else { | ||
| 2999 | WARN_ON(update->dev_priv->has_mob); | ||
| 3000 | vmw_bo_placement_set_default_accelerated(vfbbo->buffer); | ||
| 3001 | } | ||
| 3002 | ret = vmw_validation_add_bo(&val_ctx, vfbbo->buffer); | ||
| 3081 | } else { | 3003 | } else { |
| 3082 | struct vmw_framebuffer_surface *vfbs = | 3004 | struct vmw_framebuffer_surface *vfbs = |
| 3083 | container_of(update->vfb, typeof(*vfbs), base); | 3005 | container_of(update->vfb, typeof(*vfbs), base); |
| @@ -1,7 +1,7 @@ | |||
| 1 | /* SPDX-License-Identifier: GPL-2.0 OR MIT */ | 1 | /* SPDX-License-Identifier: GPL-2.0 OR MIT */ |
| 2 | /************************************************************************** | 2 | /************************************************************************** |
| 3 | * | 3 | * |
| 4 | * Copyright 2009-2022 VMware, Inc., Palo Alto, CA., USA | 4 | * Copyright 2009-2023 VMware, Inc., Palo Alto, CA., USA |
| 5 | * | 5 | * |
| 6 | * Permission is hereby granted, free of charge, to any person obtaining a | 6 | * Permission is hereby granted, free of charge, to any person obtaining a |
| 7 | * copy of this software and associated documentation files (the | 7 | * copy of this software and associated documentation files (the |
| @@ -126,7 +126,6 @@ struct vmw_du_update_plane { · 118 unmodified lines | |||
| 126 | struct vmw_framebuffer *vfb; | 126 | struct vmw_framebuffer *vfb; |
| 127 | struct vmw_fence_obj **out_fence; | 127 | struct vmw_fence_obj **out_fence; |
| 128 | struct mutex *mutex; | 128 | struct mutex *mutex; |
| 129 | bool cpu_blit; | ||
| 130 | bool intr; | 129 | bool intr; |
| 131 | }; | 130 | }; |
| 132 | 131 | ||
| @@ -217,8 +216,6 @@ struct vmw_kms_dirty { · 84 unmodified lines | |||
| 217 | */ | 216 | */ |
| 218 | struct vmw_framebuffer { | 217 | struct vmw_framebuffer { |
| 219 | struct drm_framebuffer base; | 218 | struct drm_framebuffer base; |
| 220 | int (*pin)(struct vmw_framebuffer *fb); | ||
| 221 | int (*unpin)(struct vmw_framebuffer *fb); | ||
| 222 | bool bo; | 219 | bool bo; |
| 223 | uint32_t user_handle; | 220 | uint32_t user_handle; |
| 224 | }; | 221 | }; |
| @@ -233,7 +230,7 @@ struct vmw_clip_rect { · 8 unmodified lines | |||
| 233 | struct vmw_framebuffer_surface { | 230 | struct vmw_framebuffer_surface { |
| 234 | struct vmw_framebuffer base; | 231 | struct vmw_framebuffer base; |
| 235 | struct vmw_surface *surface; | 232 | struct vmw_surface *surface; |
| 236 | struct vmw_buffer_object *buffer; | 233 | struct vmw_bo *buffer; |
| 237 | struct list_head head; | 234 | struct list_head head; |
| 238 | bool is_bo_proxy; /* true if this is proxy surface for DMA buf */ | 235 | bool is_bo_proxy; /* true if this is proxy surface for DMA buf */ |
| 239 | }; | 236 | }; |
| @@ -241,7 +238,7 @@ struct vmw_framebuffer_surface { · 1 unmodified line | |||
| 241 | 238 | ||
| 242 | struct vmw_framebuffer_bo { | 239 | struct vmw_framebuffer_bo { |
| 243 | struct vmw_framebuffer base; | 240 | struct vmw_framebuffer base; |
| 244 | struct vmw_buffer_object *buffer; | 241 | struct vmw_bo *buffer; |
| 245 | }; | 242 | }; |
| 246 | 243 | ||
| 247 | 244 | ||
| @@ -273,9 +270,7 @@ struct vmw_crtc_state { · 25 unmodified lines | |||
| 273 | }; | 270 | }; |
| 274 | 271 | ||
| 275 | struct vmw_cursor_plane_state { | 272 | struct vmw_cursor_plane_state { |
| 276 | struct ttm_buffer_object *bo; | 273 | struct vmw_bo *bo; |
| 277 | struct ttm_bo_kmap_obj map; | ||
| 278 | bool mapped; | ||
| 279 | s32 hotspot_x; | 274 | s32 hotspot_x; |
| 280 | s32 hotspot_y; | 275 | s32 hotspot_y; |
| 281 | }; | 276 | }; |
| @@ -293,7 +288,7 @@ struct vmw_cursor_plane_state { · 11 unmodified lines | |||
| 293 | struct vmw_plane_state { | 288 | struct vmw_plane_state { |
| 294 | struct drm_plane_state base; | 289 | struct drm_plane_state base; |
| 295 | struct vmw_surface *surf; | 290 | struct vmw_surface *surf; |
| 296 | struct vmw_buffer_object *bo; | 291 | struct vmw_bo *bo; |
| 297 | 292 | ||
| 298 | int content_fb_type; | 293 | int content_fb_type; |
| 299 | unsigned long bo_size; | 294 | unsigned long bo_size; |
| @@ -346,7 +341,7 @@ struct vmw_connector_state { · 46 unmodified lines | |||
| 346 | struct vmw_cursor_plane { | 341 | struct vmw_cursor_plane { |
| 347 | struct drm_plane base; | 342 | struct drm_plane base; |
| 348 | 343 | ||
| 349 | struct ttm_buffer_object *cursor_mobs[3]; | 344 | struct vmw_bo *cursor_mobs[3]; |
| 350 | }; | 345 | }; |
| 351 | 346 | ||
| 352 | /** | 347 | /** |
| @@ -364,7 +359,7 @@ struct vmw_display_unit { · 11 unmodified lines | |||
| 364 | struct vmw_cursor_plane cursor; | 359 | struct vmw_cursor_plane cursor; |
| 365 | 360 | ||
| 366 | struct vmw_surface *cursor_surface; | 361 | struct vmw_surface *cursor_surface; |
| 367 | struct vmw_buffer_object *cursor_bo; | 362 | struct vmw_bo *cursor_bo; |
| 368 | size_t cursor_age; | 363 | size_t cursor_age; |
| 369 | 364 | ||
| 370 | int cursor_x; | 365 | int cursor_x; |
| @@ -397,7 +392,7 @@ struct vmw_display_unit { · 26 unmodified lines | |||
| 397 | 392 | ||
| 398 | struct vmw_validation_ctx { | 393 | struct vmw_validation_ctx { |
| 399 | struct vmw_resource *res; | 394 | struct vmw_resource *res; |
| 400 | struct vmw_buffer_object *buf; | 395 | struct vmw_bo *buf; |
| 401 | }; | 396 | }; |
| 402 | 397 | ||
| 403 | #define vmw_crtc_to_du(x) \ | 398 | #define vmw_crtc_to_du(x) \ |
| @@ -458,7 +453,7 @@ int vmw_kms_readback(struct vmw_private *dev_priv, · 54 unmodified lines | |||
| 458 | uint32_t num_clips); | 453 | uint32_t num_clips); |
| 459 | struct vmw_framebuffer * | 454 | struct vmw_framebuffer * |
| 460 | vmw_kms_new_framebuffer(struct vmw_private *dev_priv, | 455 | vmw_kms_new_framebuffer(struct vmw_private *dev_priv, |
| 461 | struct vmw_buffer_object *bo, | 456 | struct vmw_bo *bo, |
| 462 | struct vmw_surface *surface, | 457 | struct vmw_surface *surface, |
| 463 | bool only_2d, | 458 | bool only_2d, |
| 464 | const struct drm_mode_fb_cmd2 *mode_cmd); | 459 | const struct drm_mode_fb_cmd2 *mode_cmd); |
| @@ -566,17 +561,15 @@ int vmw_kms_stdu_surface_dirty(struct vmw_private *dev_priv, · 101 unmodified lines | |||
| 566 | unsigned num_clips, int inc, | 561 | unsigned num_clips, int inc, |
| 567 | struct vmw_fence_obj **out_fence, | 562 | struct vmw_fence_obj **out_fence, |
| 568 | struct drm_crtc *crtc); | 563 | struct drm_crtc *crtc); |
| 569 | int vmw_kms_stdu_dma(struct vmw_private *dev_priv, | 564 | int vmw_kms_stdu_readback(struct vmw_private *dev_priv, |
| 570 | struct drm_file *file_priv, | 565 | struct drm_file *file_priv, |
| 571 | struct vmw_framebuffer *vfb, | 566 | struct vmw_framebuffer *vfb, |
| 572 | struct drm_vmw_fence_rep __user *user_fence_rep, | 567 | struct drm_vmw_fence_rep __user *user_fence_rep, |
| 573 | struct drm_clip_rect *clips, | 568 | struct drm_clip_rect *clips, |
| 574 | struct drm_vmw_rect *vclips, | 569 | struct drm_vmw_rect *vclips, |
| 575 | uint32_t num_clips, | 570 | uint32_t num_clips, |
| 576 | int increment, | 571 | int increment, |
| 577 | bool to_surface, | 572 | struct drm_crtc *crtc); |
| 578 | bool interruptible, | ||
| 579 | struct drm_crtc *crtc); | ||
| 580 | 573 | ||
| 581 | int vmw_du_helper_plane_update(struct vmw_du_update_plane *update); | 574 | int vmw_du_helper_plane_update(struct vmw_du_update_plane *update); |
| 582 | 575 | ||
| @@ -1,7 +1,7 @@ | |||
| 1 | // SPDX-License-Identifier: GPL-2.0 OR MIT | 1 | // SPDX-License-Identifier: GPL-2.0 OR MIT |
| 2 | /************************************************************************** | 2 | /************************************************************************** |
| 3 | * | 3 | * |
| 4 | * Copyright 2009-2022 VMware, Inc., Palo Alto, CA., USA | 4 | * Copyright 2009-2023 VMware, Inc., Palo Alto, CA., USA |
| 5 | * | 5 | * |
| 6 | * Permission is hereby granted, free of charge, to any person obtaining a | 6 | * Permission is hereby granted, free of charge, to any person obtaining a |
| 7 | * copy of this software and associated documentation files (the | 7 | * copy of this software and associated documentation files (the |
| @@ -25,11 +25,13 @@ · 17 unmodified lines | |||
| 25 | * | 25 | * |
| 26 | **************************************************************************/ | 26 | **************************************************************************/ |
| 27 | 27 | ||
| 28 | #include "vmwgfx_bo.h" | ||
| 29 | #include "vmwgfx_kms.h" | ||
| 30 | |||
| 28 | #include <drm/drm_atomic.h> | 31 | #include <drm/drm_atomic.h> |
| 29 | #include <drm/drm_atomic_helper.h> | 32 | #include <drm/drm_atomic_helper.h> |
| 30 | #include <drm/drm_fourcc.h> | 33 | #include <drm/drm_fourcc.h> |
| 31 | 34 | ||
| 32 | #include "vmwgfx_kms.h" | ||
| 33 | 35 | ||
| 34 | #define vmw_crtc_to_ldu(x) \ | 36 | #define vmw_crtc_to_ldu(x) \ |
| 35 | container_of(x, struct vmw_legacy_display_unit, base.crtc) | 37 | container_of(x, struct vmw_legacy_display_unit, base.crtc) |
| @@ -134,6 +136,47 @@ static int vmw_ldu_commit_list(struct vmw_private *dev_priv) · 98 unmodified lines | |||
| 134 | return 0; | 136 | return 0; |
| 135 | } | 137 | } |
| 136 | 138 | ||
| 139 | /* | ||
| 140 | * Pin the buffer in a location suitable for access by the | ||
| 141 | * display system. | ||
| 142 | */ | ||
| 143 | static int vmw_ldu_fb_pin(struct vmw_framebuffer *vfb) | ||
| 144 | { | ||
| 145 | struct vmw_private *dev_priv = vmw_priv(vfb->base.dev); | ||
| 146 | struct vmw_bo *buf; | ||
| 147 | int ret; | ||
| 148 | |||
| 149 | buf = vfb->bo ? vmw_framebuffer_to_vfbd(&vfb->base)->buffer : | ||
| 150 | vmw_framebuffer_to_vfbs(&vfb->base)->surface->res.guest_memory_bo; | ||
| 151 | |||
| 152 | if (!buf) | ||
| 153 | return 0; | ||
| 154 | WARN_ON(dev_priv->active_display_unit != vmw_du_legacy); | ||
| 155 | |||
| 156 | if (dev_priv->active_display_unit == vmw_du_legacy) { | ||
| 157 | vmw_overlay_pause_all(dev_priv); | ||
| 158 | ret = vmw_bo_pin_in_start_of_vram(dev_priv, buf, false); | ||
| 159 | vmw_overlay_resume_all(dev_priv); | ||
| 160 | } else | ||
| 161 | ret = -EINVAL; | ||
| 162 | |||
| 163 | return ret; | ||
| 164 | } | ||
| 165 | |||
| 166 | static int vmw_ldu_fb_unpin(struct vmw_framebuffer *vfb) | ||
| 167 | { | ||
| 168 | struct vmw_private *dev_priv = vmw_priv(vfb->base.dev); | ||
| 169 | struct vmw_bo *buf; | ||
| 170 | |||
| 171 | buf = vfb->bo ? vmw_framebuffer_to_vfbd(&vfb->base)->buffer : | ||
| 172 | vmw_framebuffer_to_vfbs(&vfb->base)->surface->res.guest_memory_bo; | ||
| 173 | |||
| 174 | if (WARN_ON(!buf)) | ||
| 175 | return 0; | ||
| 176 | |||
| 177 | return vmw_bo_unpin(dev_priv, buf, false); | ||
| 178 | } | ||
| 179 | |||
| 137 | static int vmw_ldu_del_active(struct vmw_private *vmw_priv, | 180 | static int vmw_ldu_del_active(struct vmw_private *vmw_priv, |
| 138 | struct vmw_legacy_display_unit *ldu) | 181 | struct vmw_legacy_display_unit *ldu) |
| 139 | { | 182 | { |
| @@ -145,8 +188,7 @@ static int vmw_ldu_del_active(struct vmw_private *vmw_priv, · 5 unmodified lines | |||
| 145 | list_del_init(&ldu->active); | 188 | list_del_init(&ldu->active); |
| 146 | if (--(ld->num_active) == 0) { | 189 | if (--(ld->num_active) == 0) { |
| 147 | BUG_ON(!ld->fb); | 190 | BUG_ON(!ld->fb); |
| 148 | if (ld->fb->unpin) | 191 | WARN_ON(vmw_ldu_fb_unpin(ld->fb)); |
| 149 | ld->fb->unpin(ld->fb); | ||
| 150 | ld->fb = NULL; | 192 | ld->fb = NULL; |
| 151 | } | 193 | } |
| 152 | 194 | ||
| @@ -163,11 +205,10 @@ static int vmw_ldu_add_active(struct vmw_private *vmw_priv, · 10 unmodified lines | |||
| 163 | 205 | ||
| 164 | BUG_ON(!ld->num_active && ld->fb); | 206 | BUG_ON(!ld->num_active && ld->fb); |
| 165 | if (vfb != ld->fb) { | 207 | if (vfb != ld->fb) { |
| 166 | if (ld->fb && ld->fb->unpin) | 208 | if (ld->fb) |
| 167 | ld->fb->unpin(ld->fb); | 209 | WARN_ON(vmw_ldu_fb_unpin(ld->fb)); |
| 168 | vmw_svga_enable(vmw_priv); | 210 | vmw_svga_enable(vmw_priv); |
| 169 | if (vfb->pin) | 211 | WARN_ON(vmw_ldu_fb_pin(vfb)); |
| 170 | vfb->pin(vfb); | ||
| 171 | ld->fb = vfb; | 212 | ld->fb = vfb; |
| 172 | } | 213 | } |
| 173 | 214 | ||
| @@ -1,7 +1,7 @@ | |||
| 1 | // SPDX-License-Identifier: GPL-2.0 OR MIT | 1 | // SPDX-License-Identifier: GPL-2.0 OR MIT |
| 2 | /************************************************************************** | 2 | /************************************************************************** |
| 3 | * | 3 | * |
| 4 | * Copyright 2012-2021 VMware, Inc., Palo Alto, CA., USA | 4 | * Copyright 2012-2023 VMware, Inc., Palo Alto, CA., USA |
| 5 | * | 5 | * |
| 6 | * Permission is hereby granted, free of charge, to any person obtaining a | 6 | * Permission is hereby granted, free of charge, to any person obtaining a |
| 7 | * copy of this software and associated documentation files (the | 7 | * copy of this software and associated documentation files (the |
| @@ -25,10 +25,11 @@ · 17 unmodified lines | |||
| 25 | * | 25 | * |
| 26 | **************************************************************************/ | 26 | **************************************************************************/ |
| 27 | 27 | ||
| 28 | #include <linux/highmem.h> | 28 | #include "vmwgfx_bo.h" |
| 29 | |||
| 30 | #include "vmwgfx_drv.h" | 29 | #include "vmwgfx_drv.h" |
| 31 | 30 | ||
| 31 | #include <linux/highmem.h> | ||
| 32 | |||
| 32 | #ifdef CONFIG_64BIT | 33 | #ifdef CONFIG_64BIT |
| 33 | #define VMW_PPN_SIZE 8 | 34 | #define VMW_PPN_SIZE 8 |
| 34 | #define VMW_MOBFMT_PTDEPTH_0 SVGA3D_MOBFMT_PT64_0 | 35 | #define VMW_MOBFMT_PTDEPTH_0 SVGA3D_MOBFMT_PT64_0 |
| @@ -50,7 +51,7 @@ · 15 unmodified lines | |||
| 50 | * @pt_root_page DMA address of the level 0 page of the page table. | 51 | * @pt_root_page DMA address of the level 0 page of the page table. |
| 51 | */ | 52 | */ |
| 52 | struct vmw_mob { | 53 | struct vmw_mob { |
| 53 | struct ttm_buffer_object *pt_bo; | 54 | struct vmw_bo *pt_bo; |
| 54 | unsigned long num_pages; | 55 | unsigned long num_pages; |
| 55 | unsigned pt_level; | 56 | unsigned pt_level; |
| 56 | dma_addr_t pt_root_page; | 57 | dma_addr_t pt_root_page; |
| @@ -203,7 +204,7 @@ static void vmw_takedown_otable_base(struct vmw_private *dev_priv, · 146 unmodified lines | |||
| 203 | if (otable->page_table == NULL) | 204 | if (otable->page_table == NULL) |
| 204 | return; | 205 | return; |
| 205 | 206 | ||
| 206 | bo = otable->page_table->pt_bo; | 207 | bo = &otable->page_table->pt_bo->tbo; |
| 207 | cmd = VMW_CMD_RESERVE(dev_priv, sizeof(*cmd)); | 208 | cmd = VMW_CMD_RESERVE(dev_priv, sizeof(*cmd)); |
| 208 | if (unlikely(cmd == NULL)) | 209 | if (unlikely(cmd == NULL)) |
| 209 | return; | 210 | return; |
| @@ -251,7 +252,9 @@ static int vmw_otable_batch_setup(struct vmw_private *dev_priv, · 41 unmodified lines | |||
| 251 | bo_size += otables[i].size; | 252 | bo_size += otables[i].size; |
| 252 | } | 253 | } |
| 253 | 254 | ||
| 254 | ret = vmw_bo_create_and_populate(dev_priv, bo_size, &batch->otable_bo); | 255 | ret = vmw_bo_create_and_populate(dev_priv, bo_size, |
| 256 | VMW_BO_DOMAIN_WAITABLE_SYS, | ||
| 257 | &batch->otable_bo); | ||
| 255 | if (unlikely(ret != 0)) | 258 | if (unlikely(ret != 0)) |
| 256 | return ret; | 259 | return ret; |
| 257 | 260 | ||
| @@ -260,7 +263,8 @@ static int vmw_otable_batch_setup(struct vmw_private *dev_priv, · 2 unmodified lines | |||
| 260 | if (!batch->otables[i].enabled) | 263 | if (!batch->otables[i].enabled) |
| 261 | continue; | 264 | continue; |
| 262 | 265 | ||
| 263 | ret = vmw_setup_otable_base(dev_priv, i, batch->otable_bo, | 266 | ret = vmw_setup_otable_base(dev_priv, i, |
| 267 | &batch->otable_bo->tbo, | ||
| 264 | offset, | 268 | offset, |
| 265 | &otables[i]); | 269 | &otables[i]); |
| 266 | if (unlikely(ret != 0)) | 270 | if (unlikely(ret != 0)) |
| @@ -277,8 +281,8 @@ out_no_setup: · 10 unmodified lines | |||
| 277 | &batch->otables[i]); | 281 | &batch->otables[i]); |
| 278 | } | 282 | } |
| 279 | 283 | ||
| 280 | vmw_bo_unpin_unlocked(batch->otable_bo); | 284 | vmw_bo_unpin_unlocked(&batch->otable_bo->tbo); |
| 281 | ttm_bo_put(batch->otable_bo); | 285 | ttm_bo_put(&batch->otable_bo->tbo); |
| 282 | batch->otable_bo = NULL; | 286 | batch->otable_bo = NULL; |
| 283 | return ret; | 287 | return ret; |
| 284 | } | 288 | } |
| @@ -329,7 +333,7 @@ static void vmw_otable_batch_takedown(struct vmw_private *dev_priv, · 44 unmodified lines | |||
| 329 | struct vmw_otable_batch *batch) | 333 | struct vmw_otable_batch *batch) |
| 330 | { | 334 | { |
| 331 | SVGAOTableType i; | 335 | SVGAOTableType i; |
| 332 | struct ttm_buffer_object *bo = batch->otable_bo; | 336 | struct ttm_buffer_object *bo = &batch->otable_bo->tbo; |
| 333 | int ret; | 337 | int ret; |
| 334 | 338 | ||
| 335 | for (i = 0; i < batch->num_otables; ++i) | 339 | for (i = 0; i < batch->num_otables; ++i) |
| @@ -344,8 +348,7 @@ static void vmw_otable_batch_takedown(struct vmw_private *dev_priv, · 8 unmodified lines | |||
| 344 | ttm_bo_unpin(bo); | 348 | ttm_bo_unpin(bo); |
| 345 | ttm_bo_unreserve(bo); | 349 | ttm_bo_unreserve(bo); |
| 346 | 350 | ||
| 347 | ttm_bo_put(batch->otable_bo); | 351 | vmw_bo_unreference(&batch->otable_bo); |
| 348 | batch->otable_bo = NULL; | ||
| 349 | } | 352 | } |
| 350 | 353 | ||
| 351 | /* | 354 | /* |
| @@ -413,7 +416,9 @@ static int vmw_mob_pt_populate(struct vmw_private *dev_priv, · 61 unmodified lines | |||
| 413 | { | 416 | { |
| 414 | BUG_ON(mob->pt_bo != NULL); | 417 | BUG_ON(mob->pt_bo != NULL); |
| 415 | 418 | ||
| 416 | return vmw_bo_create_and_populate(dev_priv, mob->num_pages * PAGE_SIZE, &mob->pt_bo); | 419 | return vmw_bo_create_and_populate(dev_priv, mob->num_pages * PAGE_SIZE, |
| 420 | VMW_BO_DOMAIN_WAITABLE_SYS, | ||
| 421 | &mob->pt_bo); | ||
| 417 | } | 422 | } |
| 418 | 423 | ||
| 419 | /** | 424 | /** |
| @@ -494,7 +499,7 @@ static void vmw_mob_pt_setup(struct vmw_mob *mob, · 74 unmodified lines | |||
| 494 | unsigned long num_data_pages) | 499 | unsigned long num_data_pages) |
| 495 | { | 500 | { |
| 496 | unsigned long num_pt_pages = 0; | 501 | unsigned long num_pt_pages = 0; |
| 497 | struct ttm_buffer_object *bo = mob->pt_bo; | 502 | struct ttm_buffer_object *bo = &mob->pt_bo->tbo; |
| 498 | struct vmw_piter save_pt_iter = {0}; | 503 | struct vmw_piter save_pt_iter = {0}; |
| 499 | struct vmw_piter pt_iter; | 504 | struct vmw_piter pt_iter; |
| 500 | const struct vmw_sg_table *vsgt; | 505 | const struct vmw_sg_table *vsgt; |
| @@ -531,9 +536,8 @@ static void vmw_mob_pt_setup(struct vmw_mob *mob, · 30 unmodified lines | |||
| 531 | void vmw_mob_destroy(struct vmw_mob *mob) | 536 | void vmw_mob_destroy(struct vmw_mob *mob) |
| 532 | { | 537 | { |
| 533 | if (mob->pt_bo) { | 538 | if (mob->pt_bo) { |
| 534 | vmw_bo_unpin_unlocked(mob->pt_bo); | 539 | vmw_bo_unpin_unlocked(&mob->pt_bo->tbo); |
| 535 | ttm_bo_put(mob->pt_bo); | 540 | vmw_bo_unreference(&mob->pt_bo); |
| 536 | mob->pt_bo = NULL; | ||
| 537 | } | 541 | } |
| 538 | kfree(mob); | 542 | kfree(mob); |
| 539 | } | 543 | } |
| @@ -552,7 +556,7 @@ void vmw_mob_unbind(struct vmw_private *dev_priv, · 12 unmodified lines | |||
| 552 | SVGA3dCmdDestroyGBMob body; | 556 | SVGA3dCmdDestroyGBMob body; |
| 553 | } *cmd; | 557 | } *cmd; |
| 554 | int ret; | 558 | int ret; |
| 555 | struct ttm_buffer_object *bo = mob->pt_bo; | 559 | struct ttm_buffer_object *bo = &mob->pt_bo->tbo; |
| 556 | 560 | ||
| 557 | if (bo) { | 561 | if (bo) { |
| 558 | ret = ttm_bo_reserve(bo, false, true, NULL); | 562 | ret = ttm_bo_reserve(bo, false, true, NULL); |
| @@ -644,9 +648,8 @@ int vmw_mob_bind(struct vmw_private *dev_priv, · 85 unmodified lines | |||
| 644 | out_no_cmd_space: | 648 | out_no_cmd_space: |
| 645 | vmw_fifo_resource_dec(dev_priv); | 649 | vmw_fifo_resource_dec(dev_priv); |
| 646 | if (pt_set_up) { | 650 | if (pt_set_up) { |
| 647 | vmw_bo_unpin_unlocked(mob->pt_bo); | 651 | vmw_bo_unpin_unlocked(&mob->pt_bo->tbo); |
| 648 | ttm_bo_put(mob->pt_bo); | 652 | vmw_bo_unreference(&mob->pt_bo); |
| 649 | mob->pt_bo = NULL; | ||
| 650 | } | 653 | } |
| 651 | 654 | ||
| 652 | return -ENOMEM; | 655 | return -ENOMEM; |
| @@ -1,7 +1,7 @@ | |||
| 1 | // SPDX-License-Identifier: GPL-2.0 OR MIT | 1 | // SPDX-License-Identifier: GPL-2.0 OR MIT |
| 2 | /************************************************************************** | 2 | /************************************************************************** |
| 3 | * | 3 | * |
| 4 | * Copyright 2009-2014 VMware, Inc., Palo Alto, CA., USA | 4 | * Copyright 2009-2023 VMware, Inc., Palo Alto, CA., USA |
| 5 | * | 5 | * |
| 6 | * Permission is hereby granted, free of charge, to any person obtaining a | 6 | * Permission is hereby granted, free of charge, to any person obtaining a |
| 7 | * copy of this software and associated documentation files (the | 7 | * copy of this software and associated documentation files (the |
| @@ -24,19 +24,19 @@ · 16 unmodified lines | |||
| 24 | * USE OR OTHER DEALINGS IN THE SOFTWARE. | 24 | * USE OR OTHER DEALINGS IN THE SOFTWARE. |
| 25 | * | 25 | * |
| 26 | **************************************************************************/ | 26 | **************************************************************************/ |
| 27 | 27 | #include "vmwgfx_bo.h" | |
| 28 | #include <drm/ttm/ttm_placement.h> | 28 | #include "vmwgfx_drv.h" |
| 29 | 29 | ||
| 30 | #include "device_include/svga_overlay.h" | 30 | #include "device_include/svga_overlay.h" |
| 31 | #include "device_include/svga_escape.h" | 31 | #include "device_include/svga_escape.h" |
| 32 | 32 | ||
| 33 | #include "vmwgfx_drv.h" | 33 | #include <drm/ttm/ttm_placement.h> |
| 34 | 34 | ||
| 35 | #define VMW_MAX_NUM_STREAMS 1 | 35 | #define VMW_MAX_NUM_STREAMS 1 |
| 36 | #define VMW_OVERLAY_CAP_MASK (SVGA_FIFO_CAP_VIDEO | SVGA_FIFO_CAP_ESCAPE) | 36 | #define VMW_OVERLAY_CAP_MASK (SVGA_FIFO_CAP_VIDEO | SVGA_FIFO_CAP_ESCAPE) |
| 37 | 37 | ||
| 38 | struct vmw_stream { | 38 | struct vmw_stream { |
| 39 | struct vmw_buffer_object *buf; | 39 | struct vmw_bo *buf; |
| 40 | bool claimed; | 40 | bool claimed; |
| 41 | bool paused; | 41 | bool paused; |
| 42 | struct drm_vmw_control_stream_arg saved; | 42 | struct drm_vmw_control_stream_arg saved; |
| @@ -92,7 +92,7 @@ static inline void fill_flush(struct vmw_escape_video_flush *cmd, · 49 unmodified lines | |||
| 92 | * -ERESTARTSYS if interrupted by a signal. | 92 | * -ERESTARTSYS if interrupted by a signal. |
| 93 | */ | 93 | */ |
| 94 | static int vmw_overlay_send_put(struct vmw_private *dev_priv, | 94 | static int vmw_overlay_send_put(struct vmw_private *dev_priv, |
| 95 | struct vmw_buffer_object *buf, | 95 | struct vmw_bo *buf, |
| 96 | struct drm_vmw_control_stream_arg *arg, | 96 | struct drm_vmw_control_stream_arg *arg, |
| 97 | bool interruptible) | 97 | bool interruptible) |
| 98 | { | 98 | { |
| @@ -140,7 +140,7 @@ static int vmw_overlay_send_put(struct vmw_private *dev_priv, · 41 unmodified lines | |||
| 140 | for (i = 0; i < num_items; i++) | 140 | for (i = 0; i < num_items; i++) |
| 141 | items[i].registerId = i; | 141 | items[i].registerId = i; |
| 142 | 142 | ||
| 143 | vmw_bo_get_guest_ptr(&buf->base, &ptr); | 143 | vmw_bo_get_guest_ptr(&buf->tbo, &ptr); |
| 144 | ptr.offset += arg->offset; | 144 | ptr.offset += arg->offset; |
| 145 | 145 | ||
| 146 | items[SVGA_VIDEO_ENABLED].value = true; | 146 | items[SVGA_VIDEO_ENABLED].value = true; |
| @@ -223,7 +223,7 @@ static int vmw_overlay_send_stop(struct vmw_private *dev_priv, · 76 unmodified lines | |||
| 223 | * used with GMRs instead of being locked to vram. | 223 | * used with GMRs instead of being locked to vram. |
| 224 | */ | 224 | */ |
| 225 | static int vmw_overlay_move_buffer(struct vmw_private *dev_priv, | 225 | static int vmw_overlay_move_buffer(struct vmw_private *dev_priv, |
| 226 | struct vmw_buffer_object *buf, | 226 | struct vmw_bo *buf, |
| 227 | bool pin, bool inter) | 227 | bool pin, bool inter) |
| 228 | { | 228 | { |
| 229 | if (!pin) | 229 | if (!pin) |
| @@ -295,7 +295,7 @@ static int vmw_overlay_stop(struct vmw_private *dev_priv, · 65 unmodified lines | |||
| 295 | * -ERESTARTSYS if interrupted. | 295 | * -ERESTARTSYS if interrupted. |
| 296 | */ | 296 | */ |
| 297 | static int vmw_overlay_update_stream(struct vmw_private *dev_priv, | 297 | static int vmw_overlay_update_stream(struct vmw_private *dev_priv, |
| 298 | struct vmw_buffer_object *buf, | 298 | struct vmw_bo *buf, |
| 299 | struct drm_vmw_control_stream_arg *arg, | 299 | struct drm_vmw_control_stream_arg *arg, |
| 300 | bool interruptible) | 300 | bool interruptible) |
| 301 | { | 301 | { |
| @@ -433,7 +433,7 @@ int vmw_overlay_ioctl(struct drm_device *dev, void *data, · 131 unmodified lines | |||
| 433 | struct vmw_overlay *overlay = dev_priv->overlay_priv; | 433 | struct vmw_overlay *overlay = dev_priv->overlay_priv; |
| 434 | struct drm_vmw_control_stream_arg *arg = | 434 | struct drm_vmw_control_stream_arg *arg = |
| 435 | (struct drm_vmw_control_stream_arg *)data; | 435 | (struct drm_vmw_control_stream_arg *)data; |
| 436 | struct vmw_buffer_object *buf; | 436 | struct vmw_bo *buf; |
| 437 | struct vmw_resource *res; | 437 | struct vmw_resource *res; |
| 438 | int ret; | 438 | int ret; |
| 439 | 439 | ||
| @@ -458,7 +458,7 @@ int vmw_overlay_ioctl(struct drm_device *dev, void *data, · 18 unmodified lines | |||
| 458 | ret = vmw_overlay_update_stream(dev_priv, buf, arg, true); | 458 | ret = vmw_overlay_update_stream(dev_priv, buf, arg, true); |
| 459 | 459 | ||
| 460 | vmw_bo_unreference(&buf); | 460 | vmw_bo_unreference(&buf); |
| 461 | drm_gem_object_put(&buf->base.base); | 461 | drm_gem_object_put(&buf->tbo.base); |
| 462 | 462 | ||
| 463 | out_unlock: | 463 | out_unlock: |
| 464 | mutex_unlock(&overlay->mutex); | 464 | mutex_unlock(&overlay->mutex); |
| @@ -1,7 +1,7 @@ | |||
| 1 | // SPDX-License-Identifier: GPL-2.0 OR MIT | 1 | // SPDX-License-Identifier: GPL-2.0 OR MIT |
| 2 | /************************************************************************** | 2 | /************************************************************************** |
| 3 | * | 3 | * |
| 4 | * Copyright 2019 VMware, Inc., Palo Alto, CA., USA | 4 | * Copyright 2019-2023 VMware, Inc., Palo Alto, CA., USA |
| 5 | * | 5 | * |
| 6 | * Permission is hereby granted, free of charge, to any person obtaining a | 6 | * Permission is hereby granted, free of charge, to any person obtaining a |
| 7 | * copy of this software and associated documentation files (the | 7 | * copy of this software and associated documentation files (the |
| @@ -24,6 +24,7 @@ · 16 unmodified lines | |||
| 24 | * USE OR OTHER DEALINGS IN THE SOFTWARE. | 24 | * USE OR OTHER DEALINGS IN THE SOFTWARE. |
| 25 | * | 25 | * |
| 26 | **************************************************************************/ | 26 | **************************************************************************/ |
| 27 | #include "vmwgfx_bo.h" | ||
| 27 | #include "vmwgfx_drv.h" | 28 | #include "vmwgfx_drv.h" |
| 28 | 29 | ||
| 29 | /* | 30 | /* |
| @@ -78,11 +79,11 @@ struct vmw_bo_dirty { · 48 unmodified lines | |||
| 78 | * dirty structure with the results. This function may change the | 79 | * dirty structure with the results. This function may change the |
| 79 | * dirty-tracking method. | 80 | * dirty-tracking method. |
| 80 | */ | 81 | */ |
| 81 | static void vmw_bo_dirty_scan_pagetable(struct vmw_buffer_object *vbo) | 82 | static void vmw_bo_dirty_scan_pagetable(struct vmw_bo *vbo) |
| 82 | { | 83 | { |
| 83 | struct vmw_bo_dirty *dirty = vbo->dirty; | 84 | struct vmw_bo_dirty *dirty = vbo->dirty; |
| 84 | pgoff_t offset = drm_vma_node_start(&vbo->base.base.vma_node); | 85 | pgoff_t offset = drm_vma_node_start(&vbo->tbo.base.vma_node); |
| 85 | struct address_space *mapping = vbo->base.bdev->dev_mapping; | 86 | struct address_space *mapping = vbo->tbo.bdev->dev_mapping; |
| 86 | pgoff_t num_marked; | 87 | pgoff_t num_marked; |
| 87 | 88 | ||
| 88 | num_marked = clean_record_shared_mapping_range | 89 | num_marked = clean_record_shared_mapping_range |
| @@ -116,26 +117,25 @@ static void vmw_bo_dirty_scan_pagetable(struct vmw_buffer_object *vbo) · 27 unmodified lines | |||
| 116 | * | 117 | * |
| 117 | * This function may change the dirty-tracking method. | 118 | * This function may change the dirty-tracking method. |
| 118 | */ | 119 | */ |
| 119 | static void vmw_bo_dirty_scan_mkwrite(struct vmw_buffer_object *vbo) | 120 | static void vmw_bo_dirty_scan_mkwrite(struct vmw_bo *vbo) |
| 120 | { | 121 | { |
| 121 | struct vmw_bo_dirty *dirty = vbo->dirty; | 122 | struct vmw_bo_dirty *dirty = vbo->dirty; |
| 122 | unsigned long offset = drm_vma_node_start(&vbo->base.base.vma_node); | 123 | unsigned long offset = drm_vma_node_start(&vbo->tbo.base.vma_node); |
| 123 | struct address_space *mapping = vbo->base.bdev->dev_mapping; | 124 | struct address_space *mapping = vbo->tbo.bdev->dev_mapping; |
| 124 | pgoff_t num_marked; | 125 | pgoff_t num_marked; |
| 125 | 126 | ||
| 126 | if (dirty->end <= dirty->start) | 127 | if (dirty->end <= dirty->start) |
| 127 | return; | 128 | return; |
| 128 | 129 | ||
| 129 | num_marked = wp_shared_mapping_range(vbo->base.bdev->dev_mapping, | 130 | num_marked = wp_shared_mapping_range(vbo->tbo.bdev->dev_mapping, |
| 130 | dirty->start + offset, | 131 | dirty->start + offset, |
| 131 | dirty->end - dirty->start); | 132 | dirty->end - dirty->start); |
| 132 | 133 | ||
| 133 | if (100UL * num_marked / dirty->bitmap_size > | 134 | if (100UL * num_marked / dirty->bitmap_size > |
| 134 | VMW_DIRTY_PERCENTAGE) { | 135 | VMW_DIRTY_PERCENTAGE) |
| 135 | dirty->change_count++; | 136 | dirty->change_count++; |
| 136 | } else { | 137 | else |
| 137 | dirty->change_count = 0; | 138 | dirty->change_count = 0; |
| 138 | } | ||
| 139 | 139 | ||
| 140 | if (dirty->change_count > VMW_DIRTY_NUM_CHANGE_TRIGGERS) { | 140 | if (dirty->change_count > VMW_DIRTY_NUM_CHANGE_TRIGGERS) { |
| 141 | pgoff_t start = 0; | 141 | pgoff_t start = 0; |
| @@ -160,7 +160,7 @@ static void vmw_bo_dirty_scan_mkwrite(struct vmw_buffer_object *vbo) · 18 unmodified lines | |||
| 160 | * | 160 | * |
| 161 | * This function may change the dirty tracking method. | 161 | * This function may change the dirty tracking method. |
| 162 | */ | 162 | */ |
| 163 | void vmw_bo_dirty_scan(struct vmw_buffer_object *vbo) | 163 | void vmw_bo_dirty_scan(struct vmw_bo *vbo) |
| 164 | { | 164 | { |
| 165 | struct vmw_bo_dirty *dirty = vbo->dirty; | 165 | struct vmw_bo_dirty *dirty = vbo->dirty; |
| 166 | 166 | ||
| @@ -181,12 +181,12 @@ void vmw_bo_dirty_scan(struct vmw_buffer_object *vbo) · 14 unmodified lines | |||
| 181 | * when calling unmap_mapping_range(). This function makes sure we pick | 181 | * when calling unmap_mapping_range(). This function makes sure we pick |
| 182 | * up all dirty pages. | 182 | * up all dirty pages. |
| 183 | */ | 183 | */ |
| 184 | static void vmw_bo_dirty_pre_unmap(struct vmw_buffer_object *vbo, | 184 | static void vmw_bo_dirty_pre_unmap(struct vmw_bo *vbo, |
| 185 | pgoff_t start, pgoff_t end) | 185 | pgoff_t start, pgoff_t end) |
| 186 | { | 186 | { |
| 187 | struct vmw_bo_dirty *dirty = vbo->dirty; | 187 | struct vmw_bo_dirty *dirty = vbo->dirty; |
| 188 | unsigned long offset = drm_vma_node_start(&vbo->base.base.vma_node); | 188 | unsigned long offset = drm_vma_node_start(&vbo->tbo.base.vma_node); |
| 189 | struct address_space *mapping = vbo->base.bdev->dev_mapping; | 189 | struct address_space *mapping = vbo->tbo.bdev->dev_mapping; |
| 190 | 190 | ||
| 191 | if (dirty->method != VMW_BO_DIRTY_PAGETABLE || start >= end) | 191 | if (dirty->method != VMW_BO_DIRTY_PAGETABLE || start >= end) |
| 192 | return; | 192 | return; |
| @@ -206,11 +206,11 @@ static void vmw_bo_dirty_pre_unmap(struct vmw_buffer_object *vbo, · 13 unmodified lines | |||
| 206 | * | 206 | * |
| 207 | * This is similar to ttm_bo_unmap_virtual() except it takes a subrange. | 207 | * This is similar to ttm_bo_unmap_virtual() except it takes a subrange. |
| 208 | */ | 208 | */ |
| 209 | void vmw_bo_dirty_unmap(struct vmw_buffer_object *vbo, | 209 | void vmw_bo_dirty_unmap(struct vmw_bo *vbo, |
| 210 | pgoff_t start, pgoff_t end) | 210 | pgoff_t start, pgoff_t end) |
| 211 | { | 211 | { |
| 212 | unsigned long offset = drm_vma_node_start(&vbo->base.base.vma_node); | 212 | unsigned long offset = drm_vma_node_start(&vbo->tbo.base.vma_node); |
| 213 | struct address_space *mapping = vbo->base.bdev->dev_mapping; | 213 | struct address_space *mapping = vbo->tbo.bdev->dev_mapping; |
| 214 | 214 | ||
| 215 | vmw_bo_dirty_pre_unmap(vbo, start, end); | 215 | vmw_bo_dirty_pre_unmap(vbo, start, end); |
| 216 | unmap_shared_mapping_range(mapping, (offset + start) << PAGE_SHIFT, | 216 | unmap_shared_mapping_range(mapping, (offset + start) << PAGE_SHIFT, |
| @@ -227,10 +227,10 @@ void vmw_bo_dirty_unmap(struct vmw_buffer_object *vbo, · 10 unmodified lines | |||
| 227 | * | 227 | * |
| 228 | * Return: Zero on success, -ENOMEM on memory allocation failure. | 228 | * Return: Zero on success, -ENOMEM on memory allocation failure. |
| 229 | */ | 229 | */ |
| 230 | int vmw_bo_dirty_add(struct vmw_buffer_object *vbo) | 230 | int vmw_bo_dirty_add(struct vmw_bo *vbo) |
| 231 | { | 231 | { |
| 232 | struct vmw_bo_dirty *dirty = vbo->dirty; | 232 | struct vmw_bo_dirty *dirty = vbo->dirty; |
| 233 | pgoff_t num_pages = PFN_UP(vbo->base.resource->size); | 233 | pgoff_t num_pages = PFN_UP(vbo->tbo.resource->size); |
| 234 | size_t size; | 234 | size_t size; |
| 235 | int ret; | 235 | int ret; |
| 236 | 236 | ||
| @@ -253,8 +253,8 @@ int vmw_bo_dirty_add(struct vmw_buffer_object *vbo) · 16 unmodified lines | |||
| 253 | if (num_pages < PAGE_SIZE / sizeof(pte_t)) { | 253 | if (num_pages < PAGE_SIZE / sizeof(pte_t)) { |
| 254 | dirty->method = VMW_BO_DIRTY_PAGETABLE; | 254 | dirty->method = VMW_BO_DIRTY_PAGETABLE; |
| 255 | } else { | 255 | } else { |
| 256 | struct address_space *mapping = vbo->base.bdev->dev_mapping; | 256 | struct address_space *mapping = vbo->tbo.bdev->dev_mapping; |
| 257 | pgoff_t offset = drm_vma_node_start(&vbo->base.base.vma_node); | 257 | pgoff_t offset = drm_vma_node_start(&vbo->tbo.base.vma_node); |
| 258 | 258 | ||
| 259 | dirty->method = VMW_BO_DIRTY_MKWRITE; | 259 | dirty->method = VMW_BO_DIRTY_MKWRITE; |
| 260 | 260 | ||
| @@ -284,7 +284,7 @@ out_no_dirty: · 23 unmodified lines | |||
| 284 | * | 284 | * |
| 285 | * Return: Zero on success, -ENOMEM on memory allocation failure. | 285 | * Return: Zero on success, -ENOMEM on memory allocation failure. |
| 286 | */ | 286 | */ |
| 287 | void vmw_bo_dirty_release(struct vmw_buffer_object *vbo) | 287 | void vmw_bo_dirty_release(struct vmw_bo *vbo) |
| 288 | { | 288 | { |
| 289 | struct vmw_bo_dirty *dirty = vbo->dirty; | 289 | struct vmw_bo_dirty *dirty = vbo->dirty; |
| 290 | 290 | ||
| @@ -306,11 +306,11 @@ void vmw_bo_dirty_release(struct vmw_buffer_object *vbo) · 15 unmodified lines | |||
| 306 | */ | 306 | */ |
| 307 | void vmw_bo_dirty_transfer_to_res(struct vmw_resource *res) | 307 | void vmw_bo_dirty_transfer_to_res(struct vmw_resource *res) |
| 308 | { | 308 | { |
| 309 | struct vmw_buffer_object *vbo = res->backup; | 309 | struct vmw_bo *vbo = res->guest_memory_bo; |
| 310 | struct vmw_bo_dirty *dirty = vbo->dirty; | 310 | struct vmw_bo_dirty *dirty = vbo->dirty; |
| 311 | pgoff_t start, cur, end; | 311 | pgoff_t start, cur, end; |
| 312 | unsigned long res_start = res->backup_offset; | 312 | unsigned long res_start = res->guest_memory_offset; |
| 313 | unsigned long res_end = res->backup_offset + res->backup_size; | 313 | unsigned long res_end = res->guest_memory_offset + res->guest_memory_size; |
| 314 | 314 | ||
| 315 | WARN_ON_ONCE(res_start & ~PAGE_MASK); | 315 | WARN_ON_ONCE(res_start & ~PAGE_MASK); |
| 316 | res_start >>= PAGE_SHIFT; | 316 | res_start >>= PAGE_SHIFT; |
| @@ -351,9 +351,9 @@ void vmw_bo_dirty_transfer_to_res(struct vmw_resource *res) · 34 unmodified lines | |||
| 351 | */ | 351 | */ |
| 352 | void vmw_bo_dirty_clear_res(struct vmw_resource *res) | 352 | void vmw_bo_dirty_clear_res(struct vmw_resource *res) |
| 353 | { | 353 | { |
| 354 | unsigned long res_start = res->backup_offset; | 354 | unsigned long res_start = res->guest_memory_offset; |
| 355 | unsigned long res_end = res->backup_offset + res->backup_size; | 355 | unsigned long res_end = res->guest_memory_offset + res->guest_memory_size; |
| 356 | struct vmw_buffer_object *vbo = res->backup; | 356 | struct vmw_bo *vbo = res->guest_memory_bo; |
| 357 | struct vmw_bo_dirty *dirty = vbo->dirty; | 357 | struct vmw_bo_dirty *dirty = vbo->dirty; |
| 358 | 358 | ||
| 359 | res_start >>= PAGE_SHIFT; | 359 | res_start >>= PAGE_SHIFT; |
| @@ -380,8 +380,7 @@ vm_fault_t vmw_bo_vm_mkwrite(struct vm_fault *vmf) · 20 unmodified lines | |||
| 380 | vm_fault_t ret; | 380 | vm_fault_t ret; |
| 381 | unsigned long page_offset; | 381 | unsigned long page_offset; |
| 382 | unsigned int save_flags; | 382 | unsigned int save_flags; |
| 383 | struct vmw_buffer_object *vbo = | 383 | struct vmw_bo *vbo = to_vmw_bo(&bo->base); |
| 384 | container_of(bo, typeof(*vbo), base); | ||
| 385 | 384 | ||
| 386 | /* | 385 | /* |
| 387 | * mkwrite() doesn't handle the VM_FAULT_RETRY return value correctly. | 386 | * mkwrite() doesn't handle the VM_FAULT_RETRY return value correctly. |
| @@ -419,8 +418,7 @@ vm_fault_t vmw_bo_vm_fault(struct vm_fault *vmf) · 31 unmodified lines | |||
| 419 | struct vm_area_struct *vma = vmf->vma; | 418 | struct vm_area_struct *vma = vmf->vma; |
| 420 | struct ttm_buffer_object *bo = (struct ttm_buffer_object *) | 419 | struct ttm_buffer_object *bo = (struct ttm_buffer_object *) |
| 421 | vma->vm_private_data; | 420 | vma->vm_private_data; |
| 422 | struct vmw_buffer_object *vbo = | 421 | struct vmw_bo *vbo = to_vmw_bo(&bo->base); |
| 423 | container_of(bo, struct vmw_buffer_object, base); | ||
| 424 | pgoff_t num_prefault; | 422 | pgoff_t num_prefault; |
| 425 | pgprot_t prot; | 423 | pgprot_t prot; |
| 426 | vm_fault_t ret; | 424 | vm_fault_t ret; |
| @@ -1,7 +1,7 @@ | |||
| 1 | // SPDX-License-Identifier: GPL-2.0 OR MIT | 1 | // SPDX-License-Identifier: GPL-2.0 OR MIT |
| 2 | /************************************************************************** | 2 | /************************************************************************** |
| 3 | * | 3 | * |
| 4 | * Copyright 2009-2015 VMware, Inc., Palo Alto, CA., USA | 4 | * Copyright 2009-2023 VMware, Inc., Palo Alto, CA., USA |
| 5 | * | 5 | * |
| 6 | * Permission is hereby granted, free of charge, to any person obtaining a | 6 | * Permission is hereby granted, free of charge, to any person obtaining a |
| 7 | * copy of this software and associated documentation files (the | 7 | * copy of this software and associated documentation files (the |
| @@ -27,9 +27,10 @@ · 19 unmodified lines | |||
| 27 | 27 | ||
| 28 | #include <drm/ttm/ttm_placement.h> | 28 | #include <drm/ttm/ttm_placement.h> |
| 29 | 29 | ||
| 30 | #include "vmwgfx_resource_priv.h" | ||
| 31 | #include "vmwgfx_binding.h" | 30 | #include "vmwgfx_binding.h" |
| 31 | #include "vmwgfx_bo.h" | ||
| 32 | #include "vmwgfx_drv.h" | 32 | #include "vmwgfx_drv.h" |
| 33 | #include "vmwgfx_resource_priv.h" | ||
| 33 | 34 | ||
| 34 | #define VMW_RES_EVICT_ERR_COUNT 10 | 35 | #define VMW_RES_EVICT_ERR_COUNT 10 |
| 35 | 36 | ||
| @@ -39,10 +40,10 @@ · 3 unmodified lines | |||
| 39 | */ | 40 | */ |
| 40 | void vmw_resource_mob_attach(struct vmw_resource *res) | 41 | void vmw_resource_mob_attach(struct vmw_resource *res) |
| 41 | { | 42 | { |
| 42 | struct vmw_buffer_object *backup = res->backup; | 43 | struct vmw_bo *gbo = res->guest_memory_bo; |
| 43 | struct rb_node **new = &backup->res_tree.rb_node, *parent = NULL; | 44 | struct rb_node **new = &gbo->res_tree.rb_node, *parent = NULL; |
| 44 | 45 | ||
| 45 | dma_resv_assert_held(res->backup->base.base.resv); | 46 | dma_resv_assert_held(gbo->tbo.base.resv); |
| 46 | res->used_prio = (res->res_dirty) ? res->func->dirty_prio : | 47 | res->used_prio = (res->res_dirty) ? res->func->dirty_prio : |
| 47 | res->func->prio; | 48 | res->func->prio; |
| 48 | 49 | ||
| @@ -51,14 +52,14 @@ void vmw_resource_mob_attach(struct vmw_resource *res) · 2 unmodified lines | |||
| 51 | container_of(*new, struct vmw_resource, mob_node); | 52 | container_of(*new, struct vmw_resource, mob_node); |
| 52 | 53 | ||
| 53 | parent = *new; | 54 | parent = *new; |
| 54 | new = (res->backup_offset < this->backup_offset) ? | 55 | new = (res->guest_memory_offset < this->guest_memory_offset) ? |
| 55 | &((*new)->rb_left) : &((*new)->rb_right); | 56 | &((*new)->rb_left) : &((*new)->rb_right); |
| 56 | } | 57 | } |
| 57 | 58 | ||
| 58 | rb_link_node(&res->mob_node, parent, new); | 59 | rb_link_node(&res->mob_node, parent, new); |
| 59 | rb_insert_color(&res->mob_node, &backup->res_tree); | 60 | rb_insert_color(&res->mob_node, &gbo->res_tree); |
| 60 | 61 | ||
| 61 | vmw_bo_prio_add(backup, res->used_prio); | 62 | vmw_bo_prio_add(gbo, res->used_prio); |
| 62 | } | 63 | } |
| 63 | 64 | ||
| 64 | /** | 65 | /** |
| @@ -67,13 +68,13 @@ void vmw_resource_mob_attach(struct vmw_resource *res) · 2 unmodified lines | |||
| 67 | */ | 68 | */ |
| 68 | void vmw_resource_mob_detach(struct vmw_resource *res) | 69 | void vmw_resource_mob_detach(struct vmw_resource *res) |
| 69 | { | 70 | { |
| 70 | struct vmw_buffer_object *backup = res->backup; | 71 | struct vmw_bo *gbo = res->guest_memory_bo; |
| 71 | 72 | ||
| 72 | dma_resv_assert_held(backup->base.base.resv); | 73 | dma_resv_assert_held(gbo->tbo.base.resv); |
| 73 | if (vmw_resource_mob_attached(res)) { | 74 | if (vmw_resource_mob_attached(res)) { |
| 74 | rb_erase(&res->mob_node, &backup->res_tree); | 75 | rb_erase(&res->mob_node, &gbo->res_tree); |
| 75 | RB_CLEAR_NODE(&res->mob_node); | 76 | RB_CLEAR_NODE(&res->mob_node); |
| 76 | vmw_bo_prio_del(backup, res->used_prio); | 77 | vmw_bo_prio_del(gbo, res->used_prio); |
| 77 | } | 78 | } |
| 78 | } | 79 | } |
| 79 | 80 | ||
| @@ -120,8 +121,8 @@ static void vmw_resource_release(struct kref *kref) · 40 unmodified lines | |||
| 120 | spin_lock(&dev_priv->resource_lock); | 121 | spin_lock(&dev_priv->resource_lock); |
| 121 | list_del_init(&res->lru_head); | 122 | list_del_init(&res->lru_head); |
| 122 | spin_unlock(&dev_priv->resource_lock); | 123 | spin_unlock(&dev_priv->resource_lock); |
| 123 | if (res->backup) { | 124 | if (res->guest_memory_bo) { |
| 124 | struct ttm_buffer_object *bo = &res->backup->base; | 125 | struct ttm_buffer_object *bo = &res->guest_memory_bo->tbo; |
| 125 | 126 | ||
| 126 | ret = ttm_bo_reserve(bo, false, false, NULL); | 127 | ret = ttm_bo_reserve(bo, false, false, NULL); |
| 127 | BUG_ON(ret); | 128 | BUG_ON(ret); |
| @@ -133,14 +134,14 @@ static void vmw_resource_release(struct kref *kref) · 5 unmodified lines | |||
| 133 | val_buf.num_shared = 0; | 134 | val_buf.num_shared = 0; |
| 134 | res->func->unbind(res, false, &val_buf); | 135 | res->func->unbind(res, false, &val_buf); |
| 135 | } | 136 | } |
| 136 | res->backup_dirty = false; | 137 | res->guest_memory_size = false; |
| 137 | vmw_resource_mob_detach(res); | 138 | vmw_resource_mob_detach(res); |
| 138 | if (res->dirty) | 139 | if (res->dirty) |
| 139 | res->func->dirty_free(res); | 140 | res->func->dirty_free(res); |
| 140 | if (res->coherent) | 141 | if (res->coherent) |
| 141 | vmw_bo_dirty_release(res->backup); | 142 | vmw_bo_dirty_release(res->guest_memory_bo); |
| 142 | ttm_bo_unreserve(bo); | 143 | ttm_bo_unreserve(bo); |
| 143 | vmw_bo_unreference(&res->backup); | 144 | vmw_bo_unreference(&res->guest_memory_bo); |
| 144 | } | 145 | } |
| 145 | 146 | ||
| 146 | if (likely(res->hw_destroy != NULL)) { | 147 | if (likely(res->hw_destroy != NULL)) { |
| @@ -223,9 +224,9 @@ int vmw_resource_init(struct vmw_private *dev_priv, struct vmw_resource *res, · 76 unmodified lines | |||
| 223 | INIT_LIST_HEAD(&res->lru_head); | 224 | INIT_LIST_HEAD(&res->lru_head); |
| 224 | INIT_LIST_HEAD(&res->binding_head); | 225 | INIT_LIST_HEAD(&res->binding_head); |
| 225 | res->id = -1; | 226 | res->id = -1; |
| 226 | res->backup = NULL; | 227 | res->guest_memory_bo = NULL; |
| 227 | res->backup_offset = 0; | 228 | res->guest_memory_offset = 0; |
| 228 | res->backup_dirty = false; | 229 | res->guest_memory_dirty = false; |
| 229 | res->res_dirty = false; | 230 | res->res_dirty = false; |
| 230 | res->coherent = false; | 231 | res->coherent = false; |
| 231 | res->used_prio = 3; | 232 | res->used_prio = 3; |
| @@ -263,7 +264,7 @@ int vmw_user_resource_lookup_handle(struct vmw_private *dev_priv, · 31 unmodified lines | |||
| 263 | int ret = -EINVAL; | 264 | int ret = -EINVAL; |
| 264 | 265 | ||
| 265 | base = ttm_base_object_lookup(tfile, handle); | 266 | base = ttm_base_object_lookup(tfile, handle); |
| 266 | if (unlikely(base == NULL)) | 267 | if (unlikely(!base)) |
| 267 | return -EINVAL; | 268 | return -EINVAL; |
| 268 | 269 | ||
| 269 | if (unlikely(ttm_base_object_type(base) != converter->object_type)) | 270 | if (unlikely(ttm_base_object_type(base) != converter->object_type)) |
| @@ -290,7 +291,7 @@ int vmw_user_lookup_handle(struct vmw_private *dev_priv, · 20 unmodified lines | |||
| 290 | struct drm_file *filp, | 291 | struct drm_file *filp, |
| 291 | uint32_t handle, | 292 | uint32_t handle, |
| 292 | struct vmw_surface **out_surf, | 293 | struct vmw_surface **out_surf, |
| 293 | struct vmw_buffer_object **out_buf) | 294 | struct vmw_bo **out_buf) |
| 294 | { | 295 | { |
| 295 | struct ttm_object_file *tfile = vmw_fpriv(filp)->tfile; | 296 | struct ttm_object_file *tfile = vmw_fpriv(filp)->tfile; |
| 296 | struct vmw_resource *res; | 297 | struct vmw_resource *res; |
| @@ -312,32 +313,36 @@ int vmw_user_lookup_handle(struct vmw_private *dev_priv, · 15 unmodified lines | |||
| 312 | } | 313 | } |
| 313 | 314 | ||
| 314 | /** | 315 | /** |
| 315 | * vmw_resource_buf_alloc - Allocate a backup buffer for a resource. | 316 | * vmw_resource_buf_alloc - Allocate a guest memory buffer for a resource. |
| 316 | * | 317 | * |
| 317 | * @res: The resource for which to allocate a backup buffer. | 318 | * @res: The resource for which to allocate a gbo buffer. |
| 318 | * @interruptible: Whether any sleeps during allocation should be | 319 | * @interruptible: Whether any sleeps during allocation should be |
| 319 | * performed while interruptible. | 320 | * performed while interruptible. |
| 320 | */ | 321 | */ |
| 321 | static int vmw_resource_buf_alloc(struct vmw_resource *res, | 322 | static int vmw_resource_buf_alloc(struct vmw_resource *res, |
| 322 | bool interruptible) | 323 | bool interruptible) |
| 323 | { | 324 | { |
| 324 | unsigned long size = PFN_ALIGN(res->backup_size); | 325 | unsigned long size = PFN_ALIGN(res->guest_memory_size); |
| 325 | struct vmw_buffer_object *backup; | 326 | struct vmw_bo *gbo; |
| 327 | struct vmw_bo_params bo_params = { | ||
| 328 | .domain = res->func->domain, | ||
| 329 | .busy_domain = res->func->busy_domain, | ||
| 330 | .bo_type = ttm_bo_type_device, | ||
| 331 | .size = res->guest_memory_size, | ||
| 332 | .pin = false | ||
| 333 | }; | ||
| 326 | int ret; | 334 | int ret; |
| 327 | 335 | ||
| 328 | if (likely(res->backup)) { | 336 | if (likely(res->guest_memory_bo)) { |
| 329 | BUG_ON(res->backup->base.base.size < size); | 337 | BUG_ON(res->guest_memory_bo->tbo.base.size < size); |
| 330 | return 0; | 338 | return 0; |
| 331 | } | 339 | } |
| 332 | 340 | ||
| 333 | ret = vmw_bo_create(res->dev_priv, res->backup_size, | 341 | ret = vmw_bo_create(res->dev_priv, &bo_params, &gbo); |
| 334 | res->func->backup_placement, | ||
| 335 | interruptible, false, | ||
| 336 | &vmw_bo_bo_free, &backup); | ||
| 337 | if (unlikely(ret != 0)) | 342 | if (unlikely(ret != 0)) |
| 338 | goto out_no_bo; | 343 | goto out_no_bo; |
| 339 | 344 | ||
| 340 | res->backup = backup; | 345 | res->guest_memory_bo = gbo; |
| 341 | 346 | ||
| 342 | out_no_bo: | 347 | out_no_bo: |
| 343 | return ret; | 348 | return ret; |
| @@ -369,13 +374,13 @@ static int vmw_resource_do_validate(struct vmw_resource *res, · 25 unmodified lines | |||
| 369 | } | 374 | } |
| 370 | 375 | ||
| 371 | if (func->bind && | 376 | if (func->bind && |
| 372 | ((func->needs_backup && !vmw_resource_mob_attached(res) && | 377 | ((func->needs_guest_memory && !vmw_resource_mob_attached(res) && |
| 373 | val_buf->bo != NULL) || | 378 | val_buf->bo) || |
| 374 | (!func->needs_backup && val_buf->bo != NULL))) { | 379 | (!func->needs_guest_memory && val_buf->bo))) { |
| 375 | ret = func->bind(res, val_buf); | 380 | ret = func->bind(res, val_buf); |
| 376 | if (unlikely(ret != 0)) | 381 | if (unlikely(ret != 0)) |
| 377 | goto out_bind_failed; | 382 | goto out_bind_failed; |
| 378 | if (func->needs_backup) | 383 | if (func->needs_guest_memory) |
| 379 | vmw_resource_mob_attach(res); | 384 | vmw_resource_mob_attach(res); |
| 380 | } | 385 | } |
| 381 | 386 | ||
| @@ -385,11 +390,11 @@ static int vmw_resource_do_validate(struct vmw_resource *res, · 3 unmodified lines | |||
| 385 | */ | 390 | */ |
| 386 | if (func->dirty_alloc && vmw_resource_mob_attached(res) && | 391 | if (func->dirty_alloc && vmw_resource_mob_attached(res) && |
| 387 | !res->coherent) { | 392 | !res->coherent) { |
| 388 | if (res->backup->dirty && !res->dirty) { | 393 | if (res->guest_memory_bo->dirty && !res->dirty) { |
| 389 | ret = func->dirty_alloc(res); | 394 | ret = func->dirty_alloc(res); |
| 390 | if (ret) | 395 | if (ret) |
| 391 | return ret; | 396 | return ret; |
| 392 | } else if (!res->backup->dirty && res->dirty) { | 397 | } else if (!res->guest_memory_bo->dirty && res->dirty) { |
| 393 | func->dirty_free(res); | 398 | func->dirty_free(res); |
| 394 | } | 399 | } |
| 395 | } | 400 | } |
| @@ -400,12 +405,12 @@ static int vmw_resource_do_validate(struct vmw_resource *res, · 4 unmodified lines | |||
| 400 | */ | 405 | */ |
| 401 | if (res->dirty) { | 406 | if (res->dirty) { |
| 402 | if (dirtying && !res->res_dirty) { | 407 | if (dirtying && !res->res_dirty) { |
| 403 | pgoff_t start = res->backup_offset >> PAGE_SHIFT; | 408 | pgoff_t start = res->guest_memory_offset >> PAGE_SHIFT; |
| 404 | pgoff_t end = __KERNEL_DIV_ROUND_UP | 409 | pgoff_t end = __KERNEL_DIV_ROUND_UP |
| 405 | (res->backup_offset + res->backup_size, | 410 | (res->guest_memory_offset + res->guest_memory_size, |
| 406 | PAGE_SIZE); | 411 | PAGE_SIZE); |
| 407 | 412 | ||
| 408 | vmw_bo_dirty_unmap(res->backup, start, end); | 413 | vmw_bo_dirty_unmap(res->guest_memory_bo, start, end); |
| 409 | } | 414 | } |
| 410 | 415 | ||
| 411 | vmw_bo_dirty_transfer_to_res(res); | 416 | vmw_bo_dirty_transfer_to_res(res); |
| @@ -427,10 +432,10 @@ out_bind_failed: · 15 unmodified lines | |||
| 427 | * @res: Pointer to the struct vmw_resource to unreserve. | 432 | * @res: Pointer to the struct vmw_resource to unreserve. |
| 428 | * @dirty_set: Change dirty status of the resource. | 433 | * @dirty_set: Change dirty status of the resource. |
| 429 | * @dirty: When changing dirty status indicates the new status. | 434 | * @dirty: When changing dirty status indicates the new status. |
| 430 | * @switch_backup: Backup buffer has been switched. | 435 | * @switch_guest_memory: Guest memory buffer has been switched. |
| 431 | * @new_backup: Pointer to new backup buffer if command submission | 436 | * @new_guest_memory_bo: Pointer to new guest memory buffer if command submission |
| 432 | * switched. May be NULL. | 437 | * switched. May be NULL. |
| 433 | * @new_backup_offset: New backup offset if @switch_backup is true. | 438 | * @new_guest_memory_offset: New gbo offset if @switch_guest_memory is true. |
| 434 | * | 439 | * |
| 435 | * Currently unreserving a resource means putting it back on the device's | 440 | * Currently unreserving a resource means putting it back on the device's |
| 436 | * resource lru list, so that it can be evicted if necessary. | 441 | * resource lru list, so that it can be evicted if necessary. |
| @@ -438,42 +443,42 @@ out_bind_failed: · 1 unmodified line | |||
| 438 | void vmw_resource_unreserve(struct vmw_resource *res, | 443 | void vmw_resource_unreserve(struct vmw_resource *res, |
| 439 | bool dirty_set, | 444 | bool dirty_set, |
| 440 | bool dirty, | 445 | bool dirty, |
| 441 | bool switch_backup, | 446 | bool switch_guest_memory, |
| 442 | struct vmw_buffer_object *new_backup, | 447 | struct vmw_bo *new_guest_memory_bo, |
| 443 | unsigned long new_backup_offset) | 448 | unsigned long new_guest_memory_offset) |
| 444 | { | 449 | { |
| 445 | struct vmw_private *dev_priv = res->dev_priv; | 450 | struct vmw_private *dev_priv = res->dev_priv; |
| 446 | 451 | ||
| 447 | if (!list_empty(&res->lru_head)) | 452 | if (!list_empty(&res->lru_head)) |
| 448 | return; | 453 | return; |
| 449 | 454 | ||
| 450 | if (switch_backup && new_backup != res->backup) { | 455 | if (switch_guest_memory && new_guest_memory_bo != res->guest_memory_bo) { |
| 451 | if (res->backup) { | 456 | if (res->guest_memory_bo) { |
| 452 | vmw_resource_mob_detach(res); | 457 | vmw_resource_mob_detach(res); |
| 453 | if (res->coherent) | 458 | if (res->coherent) |
| 454 | vmw_bo_dirty_release(res->backup); | 459 | vmw_bo_dirty_release(res->guest_memory_bo); |
| 455 | vmw_bo_unreference(&res->backup); | 460 | vmw_bo_unreference(&res->guest_memory_bo); |
| 456 | } | 461 | } |
| 457 | 462 | ||
| 458 | if (new_backup) { | 463 | if (new_guest_memory_bo) { |
| 459 | res->backup = vmw_bo_reference(new_backup); | 464 | res->guest_memory_bo = vmw_bo_reference(new_guest_memory_bo); |
| 460 | 465 | ||
| 461 | /* | 466 | /* |
| 462 | * The validation code should already have added a | 467 | * The validation code should already have added a |
| 463 | * dirty tracker here. | 468 | * dirty tracker here. |
| 464 | */ | 469 | */ |
| 465 | WARN_ON(res->coherent && !new_backup->dirty); | 470 | WARN_ON(res->coherent && !new_guest_memory_bo->dirty); |
| 466 | 471 | ||
| 467 | vmw_resource_mob_attach(res); | 472 | vmw_resource_mob_attach(res); |
| 468 | } else { | 473 | } else { |
| 469 | res->backup = NULL; | 474 | res->guest_memory_bo = NULL; |
| 470 | } | 475 | } |
| 471 | } else if (switch_backup && res->coherent) { | 476 | } else if (switch_guest_memory && res->coherent) { |
| 472 | vmw_bo_dirty_release(res->backup); | 477 | vmw_bo_dirty_release(res->guest_memory_bo); |
| 473 | } | 478 | } |
| 474 | 479 | ||
| 475 | if (switch_backup) | 480 | if (switch_guest_memory) |
| 476 | res->backup_offset = new_backup_offset; | 481 | res->guest_memory_offset = new_guest_memory_offset; |
| 477 | 482 | ||
| 478 | if (dirty_set) | 483 | if (dirty_set) |
| 479 | res->res_dirty = dirty; | 484 | res->res_dirty = dirty; |
| @@ -507,30 +512,32 @@ vmw_resource_check_buffer(struct ww_acquire_ctx *ticket, · 27 unmodified lines | |||
| 507 | { | 512 | { |
| 508 | struct ttm_operation_ctx ctx = { true, false }; | 513 | struct ttm_operation_ctx ctx = { true, false }; |
| 509 | struct list_head val_list; | 514 | struct list_head val_list; |
| 510 | bool backup_dirty = false; | 515 | bool guest_memory_dirty = false; |
| 511 | int ret; | 516 | int ret; |
| 512 | 517 | ||
| 513 | if (unlikely(res->backup == NULL)) { | 518 | if (unlikely(!res->guest_memory_bo)) { |
| 514 | ret = vmw_resource_buf_alloc(res, interruptible); | 519 | ret = vmw_resource_buf_alloc(res, interruptible); |
| 515 | if (unlikely(ret != 0)) | 520 | if (unlikely(ret != 0)) |
| 516 | return ret; | 521 | return ret; |
| 517 | } | 522 | } |
| 518 | 523 | ||
| 519 | INIT_LIST_HEAD(&val_list); | 524 | INIT_LIST_HEAD(&val_list); |
| 520 | ttm_bo_get(&res->backup->base); | 525 | ttm_bo_get(&res->guest_memory_bo->tbo); |
| 521 | val_buf->bo = &res->backup->base; | 526 | val_buf->bo = &res->guest_memory_bo->tbo; |
| 522 | val_buf->num_shared = 0; | 527 | val_buf->num_shared = 0; |
| 523 | list_add_tail(&val_buf->head, &val_list); | 528 | list_add_tail(&val_buf->head, &val_list); |
| 524 | ret = ttm_eu_reserve_buffers(ticket, &val_list, interruptible, NULL); | 529 | ret = ttm_eu_reserve_buffers(ticket, &val_list, interruptible, NULL); |
| 525 | if (unlikely(ret != 0)) | 530 | if (unlikely(ret != 0)) |
| 526 | goto out_no_reserve; | 531 | goto out_no_reserve; |
| 527 | 532 | ||
| 528 | if (res->func->needs_backup && !vmw_resource_mob_attached(res)) | 533 | if (res->func->needs_guest_memory && !vmw_resource_mob_attached(res)) |
| 529 | return 0; | 534 | return 0; |
| 530 | 535 | ||
| 531 | backup_dirty = res->backup_dirty; | 536 | guest_memory_dirty = res->guest_memory_dirty; |
| 532 | ret = ttm_bo_validate(&res->backup->base, | 537 | vmw_bo_placement_set(res->guest_memory_bo, res->func->domain, |
| 533 | res->func->backup_placement, | 538 | res->func->busy_domain); |
| 539 | ret = ttm_bo_validate(&res->guest_memory_bo->tbo, | ||
| 540 | &res->guest_memory_bo->placement, | ||
| 534 | &ctx); | 541 | &ctx); |
| 535 | 542 | ||
| 536 | if (unlikely(ret != 0)) | 543 | if (unlikely(ret != 0)) |
| @@ -543,8 +550,8 @@ out_no_validate: · 6 unmodified lines | |||
| 543 | out_no_reserve: | 550 | out_no_reserve: |
| 544 | ttm_bo_put(val_buf->bo); | 551 | ttm_bo_put(val_buf->bo); |
| 545 | val_buf->bo = NULL; | 552 | val_buf->bo = NULL; |
| 546 | if (backup_dirty) | 553 | if (guest_memory_dirty) |
| 547 | vmw_bo_unreference(&res->backup); | 554 | vmw_bo_unreference(&res->guest_memory_bo); |
| 548 | 555 | ||
| 549 | return ret; | 556 | return ret; |
| 550 | } | 557 | } |
| @@ -555,12 +562,13 @@ out_no_reserve: · 4 unmodified lines | |||
| 555 | * @res: The resource to reserve. | 562 | * @res: The resource to reserve. |
| 556 | * | 563 | * |
| 557 | * This function takes the resource off the LRU list and make sure | 564 | * This function takes the resource off the LRU list and make sure |
| 558 | * a backup buffer is present for guest-backed resources. However, | 565 | * a guest memory buffer is present for guest-backed resources. |
| 559 | * the buffer may not be bound to the resource at this point. | 566 | * However, the buffer may not be bound to the resource at this |
| 567 | * point. | ||
| 560 | * | 568 | * |
| 561 | */ | 569 | */ |
| 562 | int vmw_resource_reserve(struct vmw_resource *res, bool interruptible, | 570 | int vmw_resource_reserve(struct vmw_resource *res, bool interruptible, |
| 563 | bool no_backup) | 571 | bool no_guest_memory) |
| 564 | { | 572 | { |
| 565 | struct vmw_private *dev_priv = res->dev_priv; | 573 | struct vmw_private *dev_priv = res->dev_priv; |
| 566 | int ret; | 574 | int ret; |
| @@ -569,13 +577,13 @@ int vmw_resource_reserve(struct vmw_resource *res, bool interruptible, · 2 unmodified lines | |||
| 569 | list_del_init(&res->lru_head); | 577 | list_del_init(&res->lru_head); |
| 570 | spin_unlock(&dev_priv->resource_lock); | 578 | spin_unlock(&dev_priv->resource_lock); |
| 571 | 579 | ||
| 572 | if (res->func->needs_backup && res->backup == NULL && | 580 | if (res->func->needs_guest_memory && !res->guest_memory_bo && |
| 573 | !no_backup) { | 581 | !no_guest_memory) { |
| 574 | ret = vmw_resource_buf_alloc(res, interruptible); | 582 | ret = vmw_resource_buf_alloc(res, interruptible); |
| 575 | if (unlikely(ret != 0)) { | 583 | if (unlikely(ret != 0)) { |
| 576 | DRM_ERROR("Failed to allocate a backup buffer " | 584 | DRM_ERROR("Failed to allocate a guest memory buffer " |
| 577 | "of size %lu. bytes\n", | 585 | "of size %lu. bytes\n", |
| 578 | (unsigned long) res->backup_size); | 586 | (unsigned long) res->guest_memory_size); |
| 579 | return ret; | 587 | return ret; |
| 580 | } | 588 | } |
| 581 | } | 589 | } |
| @@ -585,10 +593,10 @@ int vmw_resource_reserve(struct vmw_resource *res, bool interruptible, · 3 unmodified lines | |||
| 585 | 593 | ||
| 586 | /** | 594 | /** |
| 587 | * vmw_resource_backoff_reservation - Unreserve and unreference a | 595 | * vmw_resource_backoff_reservation - Unreserve and unreference a |
| 588 | * backup buffer | 596 | * guest memory buffer |
| 589 | *. | 597 | *. |
| 590 | * @ticket: The ww acquire ctx used for reservation. | 598 | * @ticket: The ww acquire ctx used for reservation. |
| 591 | * @val_buf: Backup buffer information. | 599 | * @val_buf: Guest memory buffer information. |
| 592 | */ | 600 | */ |
| 593 | static void | 601 | static void |
| 594 | vmw_resource_backoff_reservation(struct ww_acquire_ctx *ticket, | 602 | vmw_resource_backoff_reservation(struct ww_acquire_ctx *ticket, |
| @@ -630,14 +638,14 @@ static int vmw_resource_do_evict(struct ww_acquire_ctx *ticket, · 35 unmodified lines | |||
| 630 | return ret; | 638 | return ret; |
| 631 | 639 | ||
| 632 | if (unlikely(func->unbind != NULL && | 640 | if (unlikely(func->unbind != NULL && |
| 633 | (!func->needs_backup || vmw_resource_mob_attached(res)))) { | 641 | (!func->needs_guest_memory || vmw_resource_mob_attached(res)))) { |
| 634 | ret = func->unbind(res, res->res_dirty, &val_buf); | 642 | ret = func->unbind(res, res->res_dirty, &val_buf); |
| 635 | if (unlikely(ret != 0)) | 643 | if (unlikely(ret != 0)) |
| 636 | goto out_no_unbind; | 644 | goto out_no_unbind; |
| 637 | vmw_resource_mob_detach(res); | 645 | vmw_resource_mob_detach(res); |
| 638 | } | 646 | } |
| 639 | ret = func->destroy(res); | 647 | ret = func->destroy(res); |
| 640 | res->backup_dirty = true; | 648 | res->guest_memory_dirty = true; |
| 641 | res->res_dirty = false; | 649 | res->res_dirty = false; |
| 642 | out_no_unbind: | 650 | out_no_unbind: |
| 643 | vmw_resource_backoff_reservation(ticket, &val_buf); | 651 | vmw_resource_backoff_reservation(ticket, &val_buf); |
| @@ -676,8 +684,8 @@ int vmw_resource_validate(struct vmw_resource *res, bool intr, · 32 unmodified lines | |||
| 676 | 684 | ||
| 677 | val_buf.bo = NULL; | 685 | val_buf.bo = NULL; |
| 678 | val_buf.num_shared = 0; | 686 | val_buf.num_shared = 0; |
| 679 | if (res->backup) | 687 | if (res->guest_memory_bo) |
| 680 | val_buf.bo = &res->backup->base; | 688 | val_buf.bo = &res->guest_memory_bo->tbo; |
| 681 | do { | 689 | do { |
| 682 | ret = vmw_resource_do_validate(res, &val_buf, dirtying); | 690 | ret = vmw_resource_do_validate(res, &val_buf, dirtying); |
| 683 | if (likely(ret != -EBUSY)) | 691 | if (likely(ret != -EBUSY)) |
| @@ -717,9 +725,9 @@ int vmw_resource_validate(struct vmw_resource *res, bool intr, · 33 unmodified lines | |||
| 717 | 725 | ||
| 718 | if (unlikely(ret != 0)) | 726 | if (unlikely(ret != 0)) |
| 719 | goto out_no_validate; | 727 | goto out_no_validate; |
| 720 | else if (!res->func->needs_backup && res->backup) { | 728 | else if (!res->func->needs_guest_memory && res->guest_memory_bo) { |
| 721 | WARN_ON_ONCE(vmw_resource_mob_attached(res)); | 729 | WARN_ON_ONCE(vmw_resource_mob_attached(res)); |
| 722 | vmw_bo_unreference(&res->backup); | 730 | vmw_bo_unreference(&res->guest_memory_bo); |
| 723 | } | 731 | } |
| 724 | 732 | ||
| 725 | return 0; | 733 | return 0; |
| @@ -740,14 +748,14 @@ out_no_validate: · 14 unmodified lines | |||
| 740 | * validation code, since resource validation and eviction | 748 | * validation code, since resource validation and eviction |
| 741 | * both require the backup buffer to be reserved. | 749 | * both require the backup buffer to be reserved. |
| 742 | */ | 750 | */ |
| 743 | void vmw_resource_unbind_list(struct vmw_buffer_object *vbo) | 751 | void vmw_resource_unbind_list(struct vmw_bo *vbo) |
| 744 | { | 752 | { |
| 745 | struct ttm_validate_buffer val_buf = { | 753 | struct ttm_validate_buffer val_buf = { |
| 746 | .bo = &vbo->base, | 754 | .bo = &vbo->tbo, |
| 747 | .num_shared = 0 | 755 | .num_shared = 0 |
| 748 | }; | 756 | }; |
| 749 | 757 | ||
| 750 | dma_resv_assert_held(vbo->base.base.resv); | 758 | dma_resv_assert_held(vbo->tbo.base.resv); |
| 751 | while (!RB_EMPTY_ROOT(&vbo->res_tree)) { | 759 | while (!RB_EMPTY_ROOT(&vbo->res_tree)) { |
| 752 | struct rb_node *node = vbo->res_tree.rb_node; | 760 | struct rb_node *node = vbo->res_tree.rb_node; |
| 753 | struct vmw_resource *res = | 761 | struct vmw_resource *res = |
| @@ -756,12 +764,12 @@ void vmw_resource_unbind_list(struct vmw_buffer_object *vbo) · 2 unmodified lines | |||
| 756 | if (!WARN_ON_ONCE(!res->func->unbind)) | 764 | if (!WARN_ON_ONCE(!res->func->unbind)) |
| 757 | (void) res->func->unbind(res, res->res_dirty, &val_buf); | 765 | (void) res->func->unbind(res, res->res_dirty, &val_buf); |
| 758 | 766 | ||
| 759 | res->backup_dirty = true; | 767 | res->guest_memory_size = true; |
| 760 | res->res_dirty = false; | 768 | res->res_dirty = false; |
| 761 | vmw_resource_mob_detach(res); | 769 | vmw_resource_mob_detach(res); |
| 762 | } | 770 | } |
| 763 | 771 | ||
| 764 | (void) ttm_bo_wait(&vbo->base, false, false); | 772 | (void) ttm_bo_wait(&vbo->tbo, false, false); |
| 765 | } | 773 | } |
| 766 | 774 | ||
| 767 | 775 | ||
| @@ -773,7 +781,7 @@ void vmw_resource_unbind_list(struct vmw_buffer_object *vbo) · 5 unmodified lines | |||
| 773 | * Read back cached states from the device if they exist. This function | 781 | * Read back cached states from the device if they exist. This function |
| 774 | * assumes binding_mutex is held. | 782 | * assumes binding_mutex is held. |
| 775 | */ | 783 | */ |
| 776 | int vmw_query_readback_all(struct vmw_buffer_object *dx_query_mob) | 784 | int vmw_query_readback_all(struct vmw_bo *dx_query_mob) |
| 777 | { | 785 | { |
| 778 | struct vmw_resource *dx_query_ctx; | 786 | struct vmw_resource *dx_query_ctx; |
| 779 | struct vmw_private *dev_priv; | 787 | struct vmw_private *dev_priv; |
| @@ -822,20 +830,19 @@ void vmw_query_move_notify(struct ttm_buffer_object *bo, · 42 unmodified lines | |||
| 822 | struct ttm_resource *old_mem, | 830 | struct ttm_resource *old_mem, |
| 823 | struct ttm_resource *new_mem) | 831 | struct ttm_resource *new_mem) |
| 824 | { | 832 | { |
| 825 | struct vmw_buffer_object *dx_query_mob; | 833 | struct vmw_bo *dx_query_mob; |
| 826 | struct ttm_device *bdev = bo->bdev; | 834 | struct ttm_device *bdev = bo->bdev; |
| 827 | struct vmw_private *dev_priv; | 835 | struct vmw_private *dev_priv = vmw_priv_from_ttm(bdev); |
| 828 | |||
| 829 | dev_priv = container_of(bdev, struct vmw_private, bdev); | ||
| 830 | 836 | ||
| 831 | mutex_lock(&dev_priv->binding_mutex); | 837 | mutex_lock(&dev_priv->binding_mutex); |
| 832 | 838 | ||
| 833 | /* If BO is being moved from MOB to system memory */ | 839 | /* If BO is being moved from MOB to system memory */ |
| 834 | if (new_mem->mem_type == TTM_PL_SYSTEM && | 840 | if (old_mem && |
| 841 | new_mem->mem_type == TTM_PL_SYSTEM && | ||
| 835 | old_mem->mem_type == VMW_PL_MOB) { | 842 | old_mem->mem_type == VMW_PL_MOB) { |
| 836 | struct vmw_fence_obj *fence; | 843 | struct vmw_fence_obj *fence; |
| 837 | 844 | ||
| 838 | dx_query_mob = container_of(bo, struct vmw_buffer_object, base); | 845 | dx_query_mob = to_vmw_bo(&bo->base); |
| 839 | if (!dx_query_mob || !dx_query_mob->dx_query_ctx) { | 846 | if (!dx_query_mob || !dx_query_mob->dx_query_ctx) { |
| 840 | mutex_unlock(&dev_priv->binding_mutex); | 847 | mutex_unlock(&dev_priv->binding_mutex); |
| 841 | return; | 848 | return; |
| @@ -863,7 +870,7 @@ void vmw_query_move_notify(struct ttm_buffer_object *bo, · 21 unmodified lines | |||
| 863 | */ | 870 | */ |
| 864 | bool vmw_resource_needs_backup(const struct vmw_resource *res) | 871 | bool vmw_resource_needs_backup(const struct vmw_resource *res) |
| 865 | { | 872 | { |
| 866 | return res->func->needs_backup; | 873 | return res->func->needs_guest_memory; |
| 867 | } | 874 | } |
| 868 | 875 | ||
| 869 | /** | 876 | /** |
| @@ -959,21 +966,24 @@ int vmw_resource_pin(struct vmw_resource *res, bool interruptible) · 89 unmodified lines | |||
| 959 | goto out_no_reserve; | 966 | goto out_no_reserve; |
| 960 | 967 | ||
| 961 | if (res->pin_count == 0) { | 968 | if (res->pin_count == 0) { |
| 962 | struct vmw_buffer_object *vbo = NULL; | 969 | struct vmw_bo *vbo = NULL; |
| 963 | 970 | ||
| 964 | if (res->backup) { | 971 | if (res->guest_memory_bo) { |
| 965 | vbo = res->backup; | 972 | vbo = res->guest_memory_bo; |
| 966 | 973 | ||
| 967 | ret = ttm_bo_reserve(&vbo->base, interruptible, false, NULL); | 974 | ret = ttm_bo_reserve(&vbo->tbo, interruptible, false, NULL); |
| 968 | if (ret) | 975 | if (ret) |
| 969 | goto out_no_validate; | 976 | goto out_no_validate; |
| 970 | if (!vbo->base.pin_count) { | 977 | if (!vbo->tbo.pin_count) { |
| 978 | vmw_bo_placement_set(vbo, | ||
| 979 | res->func->domain, | ||
| 980 | res->func->busy_domain); | ||
| 971 | ret = ttm_bo_validate | 981 | ret = ttm_bo_validate |
| 972 | (&vbo->base, | 982 | (&vbo->tbo, |
| 973 | res->func->backup_placement, | 983 | &vbo->placement, |
| 974 | &ctx); | 984 | &ctx); |
| 975 | if (ret) { | 985 | if (ret) { |
| 976 | ttm_bo_unreserve(&vbo->base); | 986 | ttm_bo_unreserve(&vbo->tbo); |
| 977 | goto out_no_validate; | 987 | goto out_no_validate; |
| 978 | } | 988 | } |
| 979 | } | 989 | } |
| @@ -983,7 +993,7 @@ int vmw_resource_pin(struct vmw_resource *res, bool interruptible) · 3 unmodified lines | |||
| 983 | } | 993 | } |
| 984 | ret = vmw_resource_validate(res, interruptible, true); | 994 | ret = vmw_resource_validate(res, interruptible, true); |
| 985 | if (vbo) | 995 | if (vbo) |
| 986 | ttm_bo_unreserve(&vbo->base); | 996 | ttm_bo_unreserve(&vbo->tbo); |
| 987 | if (ret) | 997 | if (ret) |
| 988 | goto out_no_validate; | 998 | goto out_no_validate; |
| 989 | } | 999 | } |
| @@ -1016,12 +1026,12 @@ void vmw_resource_unpin(struct vmw_resource *res) · 26 unmodified lines | |||
| 1016 | WARN_ON(ret); | 1026 | WARN_ON(ret); |
| 1017 | 1027 | ||
| 1018 | WARN_ON(res->pin_count == 0); | 1028 | WARN_ON(res->pin_count == 0); |
| 1019 | if (--res->pin_count == 0 && res->backup) { | 1029 | if (--res->pin_count == 0 && res->guest_memory_bo) { |
| 1020 | struct vmw_buffer_object *vbo = res->backup; | 1030 | struct vmw_bo *vbo = res->guest_memory_bo; |
| 1021 | 1031 | ||
| 1022 | (void) ttm_bo_reserve(&vbo->base, false, false, NULL); | 1032 | (void) ttm_bo_reserve(&vbo->tbo, false, false, NULL); |
| 1023 | vmw_bo_pin_reserved(vbo, false); | 1033 | vmw_bo_pin_reserved(vbo, false); |
| 1024 | ttm_bo_unreserve(&vbo->base); | 1034 | ttm_bo_unreserve(&vbo->tbo); |
| 1025 | } | 1035 | } |
| 1026 | 1036 | ||
| 1027 | vmw_resource_unreserve(res, false, false, false, NULL, 0UL); | 1037 | vmw_resource_unreserve(res, false, false, false, NULL, 0UL); |
| @@ -1062,7 +1072,7 @@ void vmw_resource_dirty_update(struct vmw_resource *res, pgoff_t start, · 34 unmodified lines | |||
| 1062 | * @num_prefault: Returns how many pages including the first have been | 1072 | * @num_prefault: Returns how many pages including the first have been |
| 1063 | * cleaned and are ok to prefault | 1073 | * cleaned and are ok to prefault |
| 1064 | */ | 1074 | */ |
| 1065 | int vmw_resources_clean(struct vmw_buffer_object *vbo, pgoff_t start, | 1075 | int vmw_resources_clean(struct vmw_bo *vbo, pgoff_t start, |
| 1066 | pgoff_t end, pgoff_t *num_prefault) | 1076 | pgoff_t end, pgoff_t *num_prefault) |
| 1067 | { | 1077 | { |
| 1068 | struct rb_node *cur = vbo->res_tree.rb_node; | 1078 | struct rb_node *cur = vbo->res_tree.rb_node; |
| @@ -1079,9 +1089,9 @@ int vmw_resources_clean(struct vmw_buffer_object *vbo, pgoff_t start, · 10 unmodified lines | |||
| 1079 | struct vmw_resource *cur_res = | 1089 | struct vmw_resource *cur_res = |
| 1080 | container_of(cur, struct vmw_resource, mob_node); | 1090 | container_of(cur, struct vmw_resource, mob_node); |
| 1081 | 1091 | ||
| 1082 | if (cur_res->backup_offset >= res_end) { | 1092 | if (cur_res->guest_memory_offset >= res_end) { |
| 1083 | cur = cur->rb_left; | 1093 | cur = cur->rb_left; |
| 1084 | } else if (cur_res->backup_offset + cur_res->backup_size <= | 1094 | } else if (cur_res->guest_memory_offset + cur_res->guest_memory_size <= |
| 1085 | res_start) { | 1095 | res_start) { |
| 1086 | cur = cur->rb_right; | 1096 | cur = cur->rb_right; |
| 1087 | } else { | 1097 | } else { |
| @@ -1092,7 +1102,7 @@ int vmw_resources_clean(struct vmw_buffer_object *vbo, pgoff_t start, · 4 unmodified lines | |||
| 1092 | } | 1102 | } |
| 1093 | 1103 | ||
| 1094 | /* | 1104 | /* |
| 1095 | * In order of increasing backup_offset, clean dirty resources | 1105 | * In order of increasing guest_memory_offset, clean dirty resources |
| 1096 | * intersecting the range. | 1106 | * intersecting the range. |
| 1097 | */ | 1107 | */ |
| 1098 | while (found) { | 1108 | while (found) { |
| @@ -1108,13 +1118,13 @@ int vmw_resources_clean(struct vmw_buffer_object *vbo, pgoff_t start, · 9 unmodified lines | |||
| 1108 | 1118 | ||
| 1109 | found->res_dirty = false; | 1119 | found->res_dirty = false; |
| 1110 | } | 1120 | } |
| 1111 | last_cleaned = found->backup_offset + found->backup_size; | 1121 | last_cleaned = found->guest_memory_offset + found->guest_memory_size; |
| 1112 | cur = rb_next(&found->mob_node); | 1122 | cur = rb_next(&found->mob_node); |
| 1113 | if (!cur) | 1123 | if (!cur) |
| 1114 | break; | 1124 | break; |
| 1115 | 1125 | ||
| 1116 | found = container_of(cur, struct vmw_resource, mob_node); | 1126 | found = container_of(cur, struct vmw_resource, mob_node); |
| 1117 | if (found->backup_offset >= res_end) | 1127 | if (found->guest_memory_offset >= res_end) |
| 1118 | break; | 1128 | break; |
| 1119 | } | 1129 | } |
| 1120 | 1130 | ||
| @@ -1123,7 +1133,7 @@ int vmw_resources_clean(struct vmw_buffer_object *vbo, pgoff_t start, · 2 unmodified lines | |||
| 1123 | */ | 1133 | */ |
| 1124 | *num_prefault = 1; | 1134 | *num_prefault = 1; |
| 1125 | if (last_cleaned > res_start) { | 1135 | if (last_cleaned > res_start) { |
| 1126 | struct ttm_buffer_object *bo = &vbo->base; | 1136 | struct ttm_buffer_object *bo = &vbo->tbo; |
| 1127 | 1137 | ||
| 1128 | *num_prefault = __KERNEL_DIV_ROUND_UP(last_cleaned - res_start, | 1138 | *num_prefault = __KERNEL_DIV_ROUND_UP(last_cleaned - res_start, |
| 1129 | PAGE_SIZE); | 1139 | PAGE_SIZE); |
| @@ -58,10 +58,11 @@ struct vmw_user_resource_conv { · 57 unmodified lines | |||
| 58 | * struct vmw_res_func - members and functions common for a resource type | 58 | * struct vmw_res_func - members and functions common for a resource type |
| 59 | * | 59 | * |
| 60 | * @res_type: Enum that identifies the lru list to use for eviction. | 60 | * @res_type: Enum that identifies the lru list to use for eviction. |
| 61 | * @needs_backup: Whether the resource is guest-backed and needs | 61 | * @needs_guest_memory:Whether the resource is guest-backed and needs |
| 62 | * persistent buffer storage. | 62 | * persistent buffer storage. |
| 63 | * @type_name: String that identifies the resource type. | 63 | * @type_name: String that identifies the resource type. |
| 64 | * @backup_placement: TTM placement for backup buffers. | 64 | * @domain: TTM placement for guest memory buffers. |
| 65 | * @busy_domain: TTM busy placement for guest memory buffers. | ||
| 65 | * @may_evict Whether the resource may be evicted. | 66 | * @may_evict Whether the resource may be evicted. |
| 66 | * @create: Create a hardware resource. | 67 | * @create: Create a hardware resource. |
| 67 | * @destroy: Destroy a hardware resource. | 68 | * @destroy: Destroy a hardware resource. |
| @@ -81,9 +82,10 @@ struct vmw_user_resource_conv { · 13 unmodified lines | |||
| 81 | */ | 82 | */ |
| 82 | struct vmw_res_func { | 83 | struct vmw_res_func { |
| 83 | enum vmw_res_type res_type; | 84 | enum vmw_res_type res_type; |
| 84 | bool needs_backup; | 85 | bool needs_guest_memory; |
| 85 | const char *type_name; | 86 | const char *type_name; |
| 86 | struct ttm_placement *backup_placement; | 87 | u32 domain; |
| 88 | u32 busy_domain; | ||
| 87 | bool may_evict; | 89 | bool may_evict; |
| 88 | u32 prio; | 90 | u32 prio; |
| 89 | u32 dirty_prio; | 91 | u32 dirty_prio; |
| @@ -1,7 +1,7 @@ | |||
| 1 | // SPDX-License-Identifier: GPL-2.0 OR MIT | 1 | // SPDX-License-Identifier: GPL-2.0 OR MIT |
| 2 | /************************************************************************** | 2 | /************************************************************************** |
| 3 | * | 3 | * |
| 4 | * Copyright 2011-2022 VMware, Inc., Palo Alto, CA., USA | 4 | * Copyright 2011-2023 VMware, Inc., Palo Alto, CA., USA |
| 5 | * | 5 | * |
| 6 | * Permission is hereby granted, free of charge, to any person obtaining a | 6 | * Permission is hereby granted, free of charge, to any person obtaining a |
| 7 | * copy of this software and associated documentation files (the | 7 | * copy of this software and associated documentation files (the |
| @@ -25,13 +25,14 @@ · 17 unmodified lines | |||
| 25 | * | 25 | * |
| 26 | **************************************************************************/ | 26 | **************************************************************************/ |
| 27 | 27 | ||
| 28 | #include "vmwgfx_bo.h" | ||
| 29 | #include "vmwgfx_kms.h" | ||
| 30 | |||
| 28 | #include <drm/drm_atomic.h> | 31 | #include <drm/drm_atomic.h> |
| 29 | #include <drm/drm_atomic_helper.h> | 32 | #include <drm/drm_atomic_helper.h> |
| 30 | #include <drm/drm_damage_helper.h> | 33 | #include <drm/drm_damage_helper.h> |
| 31 | #include <drm/drm_fourcc.h> | 34 | #include <drm/drm_fourcc.h> |
| 32 | 35 | ||
| 33 | #include "vmwgfx_kms.h" | ||
| 34 | |||
| 35 | #define vmw_crtc_to_sou(x) \ | 36 | #define vmw_crtc_to_sou(x) \ |
| 36 | container_of(x, struct vmw_screen_object_unit, base.crtc) | 37 | container_of(x, struct vmw_screen_object_unit, base.crtc) |
| 37 | #define vmw_encoder_to_sou(x) \ | 38 | #define vmw_encoder_to_sou(x) \ |
| @@ -89,7 +90,7 @@ struct vmw_screen_object_unit { · 51 unmodified lines | |||
| 89 | struct vmw_display_unit base; | 90 | struct vmw_display_unit base; |
| 90 | 91 | ||
| 91 | unsigned long buffer_size; /**< Size of allocated buffer */ | 92 | unsigned long buffer_size; /**< Size of allocated buffer */ |
| 92 | struct vmw_buffer_object *buffer; /**< Backing store buffer */ | 93 | struct vmw_bo *buffer; /**< Backing store buffer */ |
| 93 | 94 | ||
| 94 | bool defined; | 95 | bool defined; |
| 95 | }; | 96 | }; |
| @@ -148,7 +149,7 @@ static int vmw_sou_fifo_create(struct vmw_private *dev_priv, · 52 unmodified lines | |||
| 148 | sou->base.set_gui_y = cmd->obj.root.y; | 149 | sou->base.set_gui_y = cmd->obj.root.y; |
| 149 | 150 | ||
| 150 | /* Ok to assume that buffer is pinned in vram */ | 151 | /* Ok to assume that buffer is pinned in vram */ |
| 151 | vmw_bo_get_guest_ptr(&sou->buffer->base, &cmd->obj.backingStore.ptr); | 152 | vmw_bo_get_guest_ptr(&sou->buffer->tbo, &cmd->obj.backingStore.ptr); |
| 152 | cmd->obj.backingStore.pitch = mode->hdisplay * 4; | 153 | cmd->obj.backingStore.pitch = mode->hdisplay * 4; |
| 153 | 154 | ||
| 154 | vmw_cmd_commit(dev_priv, fifo_size); | 155 | vmw_cmd_commit(dev_priv, fifo_size); |
| @@ -409,9 +410,13 @@ vmw_sou_primary_plane_prepare_fb(struct drm_plane *plane, · 254 unmodified lines | |||
| 409 | struct drm_crtc *crtc = plane->state->crtc ?: new_state->crtc; | 410 | struct drm_crtc *crtc = plane->state->crtc ?: new_state->crtc; |
| 410 | struct vmw_plane_state *vps = vmw_plane_state_to_vps(new_state); | 411 | struct vmw_plane_state *vps = vmw_plane_state_to_vps(new_state); |
| 411 | struct vmw_private *dev_priv; | 412 | struct vmw_private *dev_priv; |
| 412 | size_t size; | ||
| 413 | int ret; | 413 | int ret; |
| 414 | 414 | struct vmw_bo_params bo_params = { | |
| 415 | .domain = VMW_BO_DOMAIN_VRAM, | ||
| 416 | .busy_domain = VMW_BO_DOMAIN_VRAM, | ||
| 417 | .bo_type = ttm_bo_type_device, | ||
| 418 | .pin = true | ||
| 419 | }; | ||
| 415 | 420 | ||
| 416 | if (!new_fb) { | 421 | if (!new_fb) { |
| 417 | vmw_bo_unreference(&vps->bo); | 422 | vmw_bo_unreference(&vps->bo); |
| @@ -420,11 +425,11 @@ vmw_sou_primary_plane_prepare_fb(struct drm_plane *plane, · 2 unmodified lines | |||
| 420 | return 0; | 425 | return 0; |
| 421 | } | 426 | } |
| 422 | 427 | ||
| 423 | size = new_state->crtc_w * new_state->crtc_h * 4; | 428 | bo_params.size = new_state->crtc_w * new_state->crtc_h * 4; |
| 424 | dev_priv = vmw_priv(crtc->dev); | 429 | dev_priv = vmw_priv(crtc->dev); |
| 425 | 430 | ||
| 426 | if (vps->bo) { | 431 | if (vps->bo) { |
| 427 | if (vps->bo_size == size) { | 432 | if (vps->bo_size == bo_params.size) { |
| 428 | /* | 433 | /* |
| 429 | * Note that this might temporarily up the pin-count | 434 | * Note that this might temporarily up the pin-count |
| 430 | * to 2, until cleanup_fb() is called. | 435 | * to 2, until cleanup_fb() is called. |
| @@ -443,16 +448,12 @@ vmw_sou_primary_plane_prepare_fb(struct drm_plane *plane, · 12 unmodified lines | |||
| 443 | * resume the overlays, this is preferred to failing to alloc. | 448 | * resume the overlays, this is preferred to failing to alloc. |
| 444 | */ | 449 | */ |
| 445 | vmw_overlay_pause_all(dev_priv); | 450 | vmw_overlay_pause_all(dev_priv); |
| 446 | ret = vmw_bo_create(dev_priv, size, | 451 | ret = vmw_bo_create(dev_priv, &bo_params, &vps->bo); |
| 447 | &vmw_vram_placement, | ||
| 448 | false, true, &vmw_bo_bo_free, &vps->bo); | ||
| 449 | vmw_overlay_resume_all(dev_priv); | 452 | vmw_overlay_resume_all(dev_priv); |
| 450 | if (ret) { | 453 | if (ret) |
| 451 | vps->bo = NULL; /* vmw_bo_init frees on error */ | ||
| 452 | return ret; | 454 | return ret; |
| 453 | } | ||
| 454 | 455 | ||
| 455 | vps->bo_size = size; | 456 | vps->bo_size = bo_params.size; |
| 456 | 457 | ||
| 457 | /* | 458 | /* |
| 458 | * TTM already thinks the buffer is pinned, but make sure the | 459 | * TTM already thinks the buffer is pinned, but make sure the |
| @@ -489,7 +490,7 @@ static uint32_t vmw_sou_bo_define_gmrfb(struct vmw_du_update_plane *update, · 30 unmodified lines | |||
| 489 | gmr->body.format.colorDepth = depth; | 490 | gmr->body.format.colorDepth = depth; |
| 490 | gmr->body.format.reserved = 0; | 491 | gmr->body.format.reserved = 0; |
| 491 | gmr->body.bytesPerLine = update->vfb->base.pitches[0]; | 492 | gmr->body.bytesPerLine = update->vfb->base.pitches[0]; |
| 492 | vmw_bo_get_guest_ptr(&vfbbo->buffer->base, &gmr->body.ptr); | 493 | vmw_bo_get_guest_ptr(&vfbbo->buffer->tbo, &gmr->body.ptr); |
| 493 | 494 | ||
| 494 | return sizeof(*gmr); | 495 | return sizeof(*gmr); |
| 495 | } | 496 | } |
| @@ -546,7 +547,6 @@ static int vmw_sou_plane_update_bo(struct vmw_private *dev_priv, · 50 unmodified lines | |||
| 546 | bo_update.base.vfb = vfb; | 547 | bo_update.base.vfb = vfb; |
| 547 | bo_update.base.out_fence = out_fence; | 548 | bo_update.base.out_fence = out_fence; |
| 548 | bo_update.base.mutex = NULL; | 549 | bo_update.base.mutex = NULL; |
| 549 | bo_update.base.cpu_blit = false; | ||
| 550 | bo_update.base.intr = true; | 550 | bo_update.base.intr = true; |
| 551 | 551 | ||
| 552 | bo_update.base.calc_fifo_size = vmw_sou_bo_fifo_size; | 552 | bo_update.base.calc_fifo_size = vmw_sou_bo_fifo_size; |
| @@ -707,7 +707,6 @@ static int vmw_sou_plane_update_surface(struct vmw_private *dev_priv, · 154 unmodified lines | |||
| 707 | srf_update.base.vfb = vfb; | 707 | srf_update.base.vfb = vfb; |
| 708 | srf_update.base.out_fence = out_fence; | 708 | srf_update.base.out_fence = out_fence; |
| 709 | srf_update.base.mutex = &dev_priv->cmdbuf_mutex; | 709 | srf_update.base.mutex = &dev_priv->cmdbuf_mutex; |
| 710 | srf_update.base.cpu_blit = false; | ||
| 711 | srf_update.base.intr = true; | 710 | srf_update.base.intr = true; |
| 712 | 711 | ||
| 713 | srf_update.base.calc_fifo_size = vmw_sou_surface_fifo_size; | 712 | srf_update.base.calc_fifo_size = vmw_sou_surface_fifo_size; |
| @@ -947,7 +946,7 @@ int vmw_kms_sou_init_display(struct vmw_private *dev_priv) · 233 unmodified lines | |||
| 947 | static int do_bo_define_gmrfb(struct vmw_private *dev_priv, | 946 | static int do_bo_define_gmrfb(struct vmw_private *dev_priv, |
| 948 | struct vmw_framebuffer *framebuffer) | 947 | struct vmw_framebuffer *framebuffer) |
| 949 | { | 948 | { |
| 950 | struct vmw_buffer_object *buf = | 949 | struct vmw_bo *buf = |
| 951 | container_of(framebuffer, struct vmw_framebuffer_bo, | 950 | container_of(framebuffer, struct vmw_framebuffer_bo, |
| 952 | base)->buffer; | 951 | base)->buffer; |
| 953 | int depth = framebuffer->base.format->depth; | 952 | int depth = framebuffer->base.format->depth; |
| @@ -973,7 +972,7 @@ static int do_bo_define_gmrfb(struct vmw_private *dev_priv, · 19 unmodified lines | |||
| 973 | cmd->body.format.reserved = 0; | 972 | cmd->body.format.reserved = 0; |
| 974 | cmd->body.bytesPerLine = framebuffer->base.pitches[0]; | 973 | cmd->body.bytesPerLine = framebuffer->base.pitches[0]; |
| 975 | /* Buffer is reserved in vram or GMR */ | 974 | /* Buffer is reserved in vram or GMR */ |
| 976 | vmw_bo_get_guest_ptr(&buf->base, &cmd->body.ptr); | 975 | vmw_bo_get_guest_ptr(&buf->tbo, &cmd->body.ptr); |
| 977 | vmw_cmd_commit(dev_priv, sizeof(*cmd)); | 976 | vmw_cmd_commit(dev_priv, sizeof(*cmd)); |
| 978 | 977 | ||
| 979 | return 0; | 978 | return 0; |
| @@ -1216,14 +1215,16 @@ int vmw_kms_sou_do_bo_dirty(struct vmw_private *dev_priv, · 236 unmodified lines | |||
| 1216 | struct vmw_fence_obj **out_fence, | 1215 | struct vmw_fence_obj **out_fence, |
| 1217 | struct drm_crtc *crtc) | 1216 | struct drm_crtc *crtc) |
| 1218 | { | 1217 | { |
| 1219 | struct vmw_buffer_object *buf = | 1218 | struct vmw_bo *buf = |
| 1220 | container_of(framebuffer, struct vmw_framebuffer_bo, | 1219 | container_of(framebuffer, struct vmw_framebuffer_bo, |
| 1221 | base)->buffer; | 1220 | base)->buffer; |
| 1222 | struct vmw_kms_dirty dirty; | 1221 | struct vmw_kms_dirty dirty; |
| 1223 | DECLARE_VAL_CONTEXT(val_ctx, NULL, 0); | 1222 | DECLARE_VAL_CONTEXT(val_ctx, NULL, 0); |
| 1224 | int ret; | 1223 | int ret; |
| 1225 | 1224 | ||
| 1226 | ret = vmw_validation_add_bo(&val_ctx, buf, false, false); | 1225 | vmw_bo_placement_set(buf, VMW_BO_DOMAIN_GMR | VMW_BO_DOMAIN_VRAM, |
| 1226 | VMW_BO_DOMAIN_GMR | VMW_BO_DOMAIN_VRAM); | ||
| 1227 | ret = vmw_validation_add_bo(&val_ctx, buf); | ||
| 1227 | if (ret) | 1228 | if (ret) |
| 1228 | return ret; | 1229 | return ret; |
| 1229 | 1230 | ||
| @@ -1323,13 +1324,15 @@ int vmw_kms_sou_readback(struct vmw_private *dev_priv, · 93 unmodified lines | |||
| 1323 | uint32_t num_clips, | 1324 | uint32_t num_clips, |
| 1324 | struct drm_crtc *crtc) | 1325 | struct drm_crtc *crtc) |
| 1325 | { | 1326 | { |
| 1326 | struct vmw_buffer_object *buf = | 1327 | struct vmw_bo *buf = |
| 1327 | container_of(vfb, struct vmw_framebuffer_bo, base)->buffer; | 1328 | container_of(vfb, struct vmw_framebuffer_bo, base)->buffer; |
| 1328 | struct vmw_kms_dirty dirty; | 1329 | struct vmw_kms_dirty dirty; |
| 1329 | DECLARE_VAL_CONTEXT(val_ctx, NULL, 0); | 1330 | DECLARE_VAL_CONTEXT(val_ctx, NULL, 0); |
| 1330 | int ret; | 1331 | int ret; |
| 1331 | 1332 | ||
| 1332 | ret = vmw_validation_add_bo(&val_ctx, buf, false, false); | 1333 | vmw_bo_placement_set(buf, VMW_BO_DOMAIN_GMR | VMW_BO_DOMAIN_VRAM, |
| 1334 | VMW_BO_DOMAIN_GMR | VMW_BO_DOMAIN_VRAM); | ||
| 1335 | ret = vmw_validation_add_bo(&val_ctx, buf); | ||
| 1333 | if (ret) | 1336 | if (ret) |
| 1334 | return ret; | 1337 | return ret; |
| 1335 | 1338 | ||
| @@ -1,7 +1,7 @@ | |||
| 1 | // SPDX-License-Identifier: GPL-2.0 OR MIT | 1 | // SPDX-License-Identifier: GPL-2.0 OR MIT |
| 2 | /************************************************************************** | 2 | /************************************************************************** |
| 3 | * | 3 | * |
| 4 | * Copyright 2009-2015 VMware, Inc., Palo Alto, CA., USA | 4 | * Copyright 2009-2023 VMware, Inc., Palo Alto, CA., USA |
| 5 | * | 5 | * |
| 6 | * Permission is hereby granted, free of charge, to any person obtaining a | 6 | * Permission is hereby granted, free of charge, to any person obtaining a |
| 7 | * copy of this software and associated documentation files (the | 7 | * copy of this software and associated documentation files (the |
| @@ -27,9 +27,10 @@ · 19 unmodified lines | |||
| 27 | 27 | ||
| 28 | #include <drm/ttm/ttm_placement.h> | 28 | #include <drm/ttm/ttm_placement.h> |
| 29 | 29 | ||
| 30 | #include "vmwgfx_binding.h" | ||
| 31 | #include "vmwgfx_bo.h" | ||
| 30 | #include "vmwgfx_drv.h" | 32 | #include "vmwgfx_drv.h" |
| 31 | #include "vmwgfx_resource_priv.h" | 33 | #include "vmwgfx_resource_priv.h" |
| 32 | #include "vmwgfx_binding.h" | ||
| 33 | 34 | ||
| 34 | struct vmw_shader { | 35 | struct vmw_shader { |
| 35 | struct vmw_resource res; | 36 | struct vmw_resource res; |
| @@ -88,12 +89,13 @@ const struct vmw_user_resource_conv *user_shader_converter = · 52 unmodified lines | |||
| 88 | 89 | ||
| 89 | static const struct vmw_res_func vmw_gb_shader_func = { | 90 | static const struct vmw_res_func vmw_gb_shader_func = { |
| 90 | .res_type = vmw_res_shader, | 91 | .res_type = vmw_res_shader, |
| 91 | .needs_backup = true, | 92 | .needs_guest_memory = true, |
| 92 | .may_evict = true, | 93 | .may_evict = true, |
| 93 | .prio = 3, | 94 | .prio = 3, |
| 94 | .dirty_prio = 3, | 95 | .dirty_prio = 3, |
| 95 | .type_name = "guest backed shaders", | 96 | .type_name = "guest backed shaders", |
| 96 | .backup_placement = &vmw_mob_placement, | 97 | .domain = VMW_BO_DOMAIN_MOB, |
| 98 | .busy_domain = VMW_BO_DOMAIN_MOB, | ||
| 97 | .create = vmw_gb_shader_create, | 99 | .create = vmw_gb_shader_create, |
| 98 | .destroy = vmw_gb_shader_destroy, | 100 | .destroy = vmw_gb_shader_destroy, |
| 99 | .bind = vmw_gb_shader_bind, | 101 | .bind = vmw_gb_shader_bind, |
| @@ -102,12 +104,13 @@ static const struct vmw_res_func vmw_gb_shader_func = { · 2 unmodified lines | |||
| 102 | 104 | ||
| 103 | static const struct vmw_res_func vmw_dx_shader_func = { | 105 | static const struct vmw_res_func vmw_dx_shader_func = { |
| 104 | .res_type = vmw_res_shader, | 106 | .res_type = vmw_res_shader, |
| 105 | .needs_backup = true, | 107 | .needs_guest_memory = true, |
| 106 | .may_evict = true, | 108 | .may_evict = true, |
| 107 | .prio = 3, | 109 | .prio = 3, |
| 108 | .dirty_prio = 3, | 110 | .dirty_prio = 3, |
| 109 | .type_name = "dx shaders", | 111 | .type_name = "dx shaders", |
| 110 | .backup_placement = &vmw_mob_placement, | 112 | .domain = VMW_BO_DOMAIN_MOB, |
| 113 | .busy_domain = VMW_BO_DOMAIN_MOB, | ||
| 111 | .create = vmw_dx_shader_create, | 114 | .create = vmw_dx_shader_create, |
| 112 | /* | 115 | /* |
| 113 | * The destroy callback is only called with a committed resource on | 116 | * The destroy callback is only called with a committed resource on |
| @@ -158,7 +161,7 @@ static int vmw_gb_shader_init(struct vmw_private *dev_priv, · 44 unmodified lines | |||
| 158 | SVGA3dShaderType type, | 161 | SVGA3dShaderType type, |
| 159 | uint8_t num_input_sig, | 162 | uint8_t num_input_sig, |
| 160 | uint8_t num_output_sig, | 163 | uint8_t num_output_sig, |
| 161 | struct vmw_buffer_object *byte_code, | 164 | struct vmw_bo *byte_code, |
| 162 | void (*res_free) (struct vmw_resource *res)) | 165 | void (*res_free) (struct vmw_resource *res)) |
| 163 | { | 166 | { |
| 164 | struct vmw_shader *shader = vmw_res_to_shader(res); | 167 | struct vmw_shader *shader = vmw_res_to_shader(res); |
| @@ -175,10 +178,10 @@ static int vmw_gb_shader_init(struct vmw_private *dev_priv, · 10 unmodified lines | |||
| 175 | return ret; | 178 | return ret; |
| 176 | } | 179 | } |
| 177 | 180 | ||
| 178 | res->backup_size = size; | 181 | res->guest_memory_size = size; |
| 179 | if (byte_code) { | 182 | if (byte_code) { |
| 180 | res->backup = vmw_bo_reference(byte_code); | 183 | res->guest_memory_bo = vmw_bo_reference(byte_code); |
| 181 | res->backup_offset = offset; | 184 | res->guest_memory_offset = offset; |
| 182 | } | 185 | } |
| 183 | shader->size = size; | 186 | shader->size = size; |
| 184 | shader->type = type; | 187 | shader->type = type; |
| @@ -259,8 +262,8 @@ static int vmw_gb_shader_bind(struct vmw_resource *res, · 74 unmodified lines | |||
| 259 | cmd->header.size = sizeof(cmd->body); | 262 | cmd->header.size = sizeof(cmd->body); |
| 260 | cmd->body.shid = res->id; | 263 | cmd->body.shid = res->id; |
| 261 | cmd->body.mobid = bo->resource->start; | 264 | cmd->body.mobid = bo->resource->start; |
| 262 | cmd->body.offsetInBytes = res->backup_offset; | 265 | cmd->body.offsetInBytes = res->guest_memory_offset; |
| 263 | res->backup_dirty = false; | 266 | res->guest_memory_dirty = false; |
| 264 | vmw_cmd_commit(dev_priv, sizeof(*cmd)); | 267 | vmw_cmd_commit(dev_priv, sizeof(*cmd)); |
| 265 | 268 | ||
| 266 | return 0; | 269 | return 0; |
| @@ -277,7 +280,7 @@ static int vmw_gb_shader_unbind(struct vmw_resource *res, · 10 unmodified lines | |||
| 277 | } *cmd; | 280 | } *cmd; |
| 278 | struct vmw_fence_obj *fence; | 281 | struct vmw_fence_obj *fence; |
| 279 | 282 | ||
| 280 | BUG_ON(res->backup->base.resource->mem_type != VMW_PL_MOB); | 283 | BUG_ON(res->guest_memory_bo->tbo.resource->mem_type != VMW_PL_MOB); |
| 281 | 284 | ||
| 282 | cmd = VMW_CMD_RESERVE(dev_priv, sizeof(*cmd)); | 285 | cmd = VMW_CMD_RESERVE(dev_priv, sizeof(*cmd)); |
| 283 | if (unlikely(cmd == NULL)) | 286 | if (unlikely(cmd == NULL)) |
| @@ -397,8 +400,8 @@ static int vmw_dx_shader_unscrub(struct vmw_resource *res) · 113 unmodified lines | |||
| 397 | cmd->header.size = sizeof(cmd->body); | 400 | cmd->header.size = sizeof(cmd->body); |
| 398 | cmd->body.cid = shader->ctx->id; | 401 | cmd->body.cid = shader->ctx->id; |
| 399 | cmd->body.shid = shader->id; | 402 | cmd->body.shid = shader->id; |
| 400 | cmd->body.mobid = res->backup->base.resource->start; | 403 | cmd->body.mobid = res->guest_memory_bo->tbo.resource->start; |
| 401 | cmd->body.offsetInBytes = res->backup_offset; | 404 | cmd->body.offsetInBytes = res->guest_memory_offset; |
| 402 | vmw_cmd_commit(dev_priv, sizeof(*cmd)); | 405 | vmw_cmd_commit(dev_priv, sizeof(*cmd)); |
| 403 | 406 | ||
| 404 | vmw_cotable_add_resource(shader->cotable, &shader->cotable_head); | 407 | vmw_cotable_add_resource(shader->cotable, &shader->cotable_head); |
| @@ -508,7 +511,7 @@ static int vmw_dx_shader_unbind(struct vmw_resource *res, · 103 unmodified lines | |||
| 508 | struct vmw_fence_obj *fence; | 511 | struct vmw_fence_obj *fence; |
| 509 | int ret; | 512 | int ret; |
| 510 | 513 | ||
| 511 | BUG_ON(res->backup->base.resource->mem_type != VMW_PL_MOB); | 514 | BUG_ON(res->guest_memory_bo->tbo.resource->mem_type != VMW_PL_MOB); |
| 512 | 515 | ||
| 513 | mutex_lock(&dev_priv->binding_mutex); | 516 | mutex_lock(&dev_priv->binding_mutex); |
| 514 | ret = vmw_dx_shader_scrub(res); | 517 | ret = vmw_dx_shader_scrub(res); |
| @@ -680,7 +683,7 @@ int vmw_shader_destroy_ioctl(struct drm_device *dev, void *data, · 165 unmodified lines | |||
| 680 | } | 683 | } |
| 681 | 684 | ||
| 682 | static int vmw_user_shader_alloc(struct vmw_private *dev_priv, | 685 | static int vmw_user_shader_alloc(struct vmw_private *dev_priv, |
| 683 | struct vmw_buffer_object *buffer, | 686 | struct vmw_bo *buffer, |
| 684 | size_t shader_size, | 687 | size_t shader_size, |
| 685 | size_t offset, | 688 | size_t offset, |
| 686 | SVGA3dShaderType shader_type, | 689 | SVGA3dShaderType shader_type, |
| @@ -734,7 +737,7 @@ out: · 47 unmodified lines | |||
| 734 | 737 | ||
| 735 | 738 | ||
| 736 | static struct vmw_resource *vmw_shader_alloc(struct vmw_private *dev_priv, | 739 | static struct vmw_resource *vmw_shader_alloc(struct vmw_private *dev_priv, |
| 737 | struct vmw_buffer_object *buffer, | 740 | struct vmw_bo *buffer, |
| 738 | size_t shader_size, | 741 | size_t shader_size, |
| 739 | size_t offset, | 742 | size_t offset, |
| 740 | SVGA3dShaderType shader_type) | 743 | SVGA3dShaderType shader_type) |
| @@ -771,7 +774,7 @@ static int vmw_shader_define(struct drm_device *dev, struct drm_file *file_priv, · 30 unmodified lines | |||
| 771 | { | 774 | { |
| 772 | struct vmw_private *dev_priv = vmw_priv(dev); | 775 | struct vmw_private *dev_priv = vmw_priv(dev); |
| 773 | struct ttm_object_file *tfile = vmw_fpriv(file_priv)->tfile; | 776 | struct ttm_object_file *tfile = vmw_fpriv(file_priv)->tfile; |
| 774 | struct vmw_buffer_object *buffer = NULL; | 777 | struct vmw_bo *buffer = NULL; |
| 775 | SVGA3dShaderType shader_type; | 778 | SVGA3dShaderType shader_type; |
| 776 | int ret; | 779 | int ret; |
| 777 | 780 | ||
| @@ -782,7 +785,7 @@ static int vmw_shader_define(struct drm_device *dev, struct drm_file *file_priv, · 4 unmodified lines | |||
| 782 | return ret; | 785 | return ret; |
| 783 | } | 786 | } |
| 784 | 787 | ||
| 785 | if ((u64)buffer->base.base.size < (u64)size + (u64)offset) { | 788 | if ((u64)buffer->tbo.base.size < (u64)size + (u64)offset) { |
| 786 | VMW_DEBUG_USER("Illegal buffer- or shader size.\n"); | 789 | VMW_DEBUG_USER("Illegal buffer- or shader size.\n"); |
| 787 | ret = -EINVAL; | 790 | ret = -EINVAL; |
| 788 | goto out_bad_arg; | 791 | goto out_bad_arg; |
| @@ -807,7 +810,7 @@ static int vmw_shader_define(struct drm_device *dev, struct drm_file *file_priv, · 18 unmodified lines | |||
| 807 | num_output_sig, tfile, shader_handle); | 810 | num_output_sig, tfile, shader_handle); |
| 808 | out_bad_arg: | 811 | out_bad_arg: |
| 809 | vmw_bo_unreference(&buffer); | 812 | vmw_bo_unreference(&buffer); |
| 810 | drm_gem_object_put(&buffer->base.base); | 813 | drm_gem_object_put(&buffer->tbo.base); |
| 811 | return ret; | 814 | return ret; |
| 812 | } | 815 | } |
| 813 | 816 | ||
| @@ -884,28 +887,34 @@ int vmw_compat_shader_add(struct vmw_private *dev_priv, · 70 unmodified lines | |||
| 884 | struct list_head *list) | 887 | struct list_head *list) |
| 885 | { | 888 | { |
| 886 | struct ttm_operation_ctx ctx = { false, true }; | 889 | struct ttm_operation_ctx ctx = { false, true }; |
| 887 | struct vmw_buffer_object *buf; | 890 | struct vmw_bo *buf; |
| 888 | struct ttm_bo_kmap_obj map; | 891 | struct ttm_bo_kmap_obj map; |
| 889 | bool is_iomem; | 892 | bool is_iomem; |
| 890 | int ret; | 893 | int ret; |
| 891 | struct vmw_resource *res; | 894 | struct vmw_resource *res; |
| 895 | struct vmw_bo_params bo_params = { | ||
| 896 | .domain = VMW_BO_DOMAIN_SYS, | ||
| 897 | .busy_domain = VMW_BO_DOMAIN_SYS, | ||
| 898 | .bo_type = ttm_bo_type_device, | ||
| 899 | .size = size, | ||
| 900 | .pin = true | ||
| 901 | }; | ||
| 892 | 902 | ||
| 893 | if (!vmw_shader_id_ok(user_key, shader_type)) | 903 | if (!vmw_shader_id_ok(user_key, shader_type)) |
| 894 | return -EINVAL; | 904 | return -EINVAL; |
| 895 | 905 | ||
| 896 | ret = vmw_bo_create(dev_priv, size, &vmw_sys_placement, | 906 | ret = vmw_bo_create(dev_priv, &bo_params, &buf); |
| 897 | true, true, vmw_bo_bo_free, &buf); | ||
| 898 | if (unlikely(ret != 0)) | 907 | if (unlikely(ret != 0)) |
| 899 | goto out; | 908 | goto out; |
| 900 | 909 | ||
| 901 | ret = ttm_bo_reserve(&buf->base, false, true, NULL); | 910 | ret = ttm_bo_reserve(&buf->tbo, false, true, NULL); |
| 902 | if (unlikely(ret != 0)) | 911 | if (unlikely(ret != 0)) |
| 903 | goto no_reserve; | 912 | goto no_reserve; |
| 904 | 913 | ||
| 905 | /* Map and copy shader bytecode. */ | 914 | /* Map and copy shader bytecode. */ |
| 906 | ret = ttm_bo_kmap(&buf->base, 0, PFN_UP(size), &map); | 915 | ret = ttm_bo_kmap(&buf->tbo, 0, PFN_UP(size), &map); |
| 907 | if (unlikely(ret != 0)) { | 916 | if (unlikely(ret != 0)) { |
| 908 | ttm_bo_unreserve(&buf->base); | 917 | ttm_bo_unreserve(&buf->tbo); |
| 909 | goto no_reserve; | 918 | goto no_reserve; |
| 910 | } | 919 | } |
| 911 | 920 | ||
| @@ -913,9 +922,9 @@ int vmw_compat_shader_add(struct vmw_private *dev_priv, · 1 unmodified line | |||
| 913 | WARN_ON(is_iomem); | 922 | WARN_ON(is_iomem); |
| 914 | 923 | ||
| 915 | ttm_bo_kunmap(&map); | 924 | ttm_bo_kunmap(&map); |
| 916 | ret = ttm_bo_validate(&buf->base, &vmw_sys_placement, &ctx); | 925 | ret = ttm_bo_validate(&buf->tbo, &buf->placement, &ctx); |
| 917 | WARN_ON(ret != 0); | 926 | WARN_ON(ret != 0); |
| 918 | ttm_bo_unreserve(&buf->base); | 927 | ttm_bo_unreserve(&buf->tbo); |
| 919 | 928 | ||
| 920 | res = vmw_shader_alloc(dev_priv, buf, size, 0, shader_type); | 929 | res = vmw_shader_alloc(dev_priv, buf, size, 0, shader_type); |
| 921 | if (unlikely(ret != 0)) | 930 | if (unlikely(ret != 0)) |
| @@ -24,6 +24,7 @@ · 23 unmodified lines | |||
| 24 | * | 24 | * |
| 25 | **************************************************************************/ | 25 | **************************************************************************/ |
| 26 | 26 | ||
| 27 | #include "vmwgfx_bo.h" | ||
| 27 | #include "vmwgfx_drv.h" | 28 | #include "vmwgfx_drv.h" |
| 28 | #include "vmwgfx_resource_priv.h" | 29 | #include "vmwgfx_resource_priv.h" |
| 29 | #include "vmwgfx_so.h" | 30 | #include "vmwgfx_so.h" |
| @@ -81,10 +82,11 @@ static void vmw_view_commit_notify(struct vmw_resource *res, · 51 unmodified lines | |||
| 81 | 82 | ||
| 82 | static const struct vmw_res_func vmw_view_func = { | 83 | static const struct vmw_res_func vmw_view_func = { |
| 83 | .res_type = vmw_res_view, | 84 | .res_type = vmw_res_view, |
| 84 | .needs_backup = false, | 85 | .needs_guest_memory = false, |
| 85 | .may_evict = false, | 86 | .may_evict = false, |
| 86 | .type_name = "DX view", | 87 | .type_name = "DX view", |
| 87 | .backup_placement = NULL, | 88 | .domain = VMW_BO_DOMAIN_SYS, |
| 89 | .busy_domain = VMW_BO_DOMAIN_SYS, | ||
| 88 | .create = vmw_view_create, | 90 | .create = vmw_view_create, |
| 89 | .commit_notify = vmw_view_commit_notify, | 91 | .commit_notify = vmw_view_commit_notify, |
| 90 | }; | 92 | }; |
| @@ -1,7 +1,7 @@ | |||
| 1 | // SPDX-License-Identifier: GPL-2.0 OR MIT | 1 | // SPDX-License-Identifier: GPL-2.0 OR MIT |
| 2 | /****************************************************************************** | 2 | /****************************************************************************** |
| 3 | * | 3 | * |
| 4 | * COPYRIGHT (C) 2014-2022 VMware, Inc., Palo Alto, CA., USA | 4 | * COPYRIGHT (C) 2014-2023 VMware, Inc., Palo Alto, CA., USA |
| 5 | * | 5 | * |
| 6 | * Permission is hereby granted, free of charge, to any person obtaining a | 6 | * Permission is hereby granted, free of charge, to any person obtaining a |
| 7 | * copy of this software and associated documentation files (the | 7 | * copy of this software and associated documentation files (the |
| @@ -25,14 +25,15 @@ · 17 unmodified lines | |||
| 25 | * | 25 | * |
| 26 | ******************************************************************************/ | 26 | ******************************************************************************/ |
| 27 | 27 | ||
| 28 | #include "vmwgfx_bo.h" | ||
| 29 | #include "vmwgfx_kms.h" | ||
| 30 | #include "vmw_surface_cache.h" | ||
| 31 | |||
| 28 | #include <drm/drm_atomic.h> | 32 | #include <drm/drm_atomic.h> |
| 29 | #include <drm/drm_atomic_helper.h> | 33 | #include <drm/drm_atomic_helper.h> |
| 30 | #include <drm/drm_damage_helper.h> | 34 | #include <drm/drm_damage_helper.h> |
| 31 | #include <drm/drm_fourcc.h> | 35 | #include <drm/drm_fourcc.h> |
| 32 | 36 | ||
| 33 | #include "vmwgfx_kms.h" | ||
| 34 | #include "vmw_surface_cache.h" | ||
| 35 | |||
| 36 | #define vmw_crtc_to_stdu(x) \ | 37 | #define vmw_crtc_to_stdu(x) \ |
| 37 | container_of(x, struct vmw_screen_target_display_unit, base.crtc) | 38 | container_of(x, struct vmw_screen_target_display_unit, base.crtc) |
| 38 | #define vmw_encoder_to_stdu(x) \ | 39 | #define vmw_encoder_to_stdu(x) \ |
| @@ -65,12 +66,11 @@ enum stdu_content_type { · 26 unmodified lines | |||
| 65 | */ | 66 | */ |
| 66 | struct vmw_stdu_dirty { | 67 | struct vmw_stdu_dirty { |
| 67 | struct vmw_kms_dirty base; | 68 | struct vmw_kms_dirty base; |
| 68 | SVGA3dTransferType transfer; | ||
| 69 | s32 left, right, top, bottom; | 69 | s32 left, right, top, bottom; |
| 70 | s32 fb_left, fb_top; | 70 | s32 fb_left, fb_top; |
| 71 | u32 pitch; | 71 | u32 pitch; |
| 72 | union { | 72 | union { |
| 73 | struct vmw_buffer_object *buf; | 73 | struct vmw_bo *buf; |
| 74 | u32 sid; | 74 | u32 sid; |
| 75 | }; | 75 | }; |
| 76 | }; | 76 | }; |
| @@ -136,12 +136,6 @@ static void vmw_stdu_destroy(struct vmw_screen_target_display_unit *stdu); · 59 unmodified lines | |||
| 136 | * Screen Target Display Unit CRTC Functions | 136 | * Screen Target Display Unit CRTC Functions |
| 137 | *****************************************************************************/ | 137 | *****************************************************************************/ |
| 138 | 138 | ||
| 139 | static bool vmw_stdu_use_cpu_blit(const struct vmw_private *vmw) | ||
| 140 | { | ||
| 141 | return !(vmw->capabilities & SVGA_CAP_3D) || vmw->vram_size < (32 * 1024 * 1024); | ||
| 142 | } | ||
| 143 | |||
| 144 | |||
| 145 | /** | 139 | /** |
| 146 | * vmw_stdu_crtc_destroy - cleans up the STDU | 140 | * vmw_stdu_crtc_destroy - cleans up the STDU |
| 147 | * | 141 | * |
| @@ -450,93 +444,6 @@ static void vmw_stdu_crtc_atomic_disable(struct drm_crtc *crtc, · 302 unmodified lines | |||
| 450 | } | 444 | } |
| 451 | } | 445 | } |
| 452 | 446 | ||
| 453 | /** | ||
| 454 | * vmw_stdu_bo_clip - Callback to encode a suface DMA command cliprect | ||
| 455 | * | ||
| 456 | * @dirty: The closure structure. | ||
| 457 | * | ||
| 458 | * Encodes a surface DMA command cliprect and updates the bounding box | ||
| 459 | * for the DMA. | ||
| 460 | */ | ||
| 461 | static void vmw_stdu_bo_clip(struct vmw_kms_dirty *dirty) | ||
| 462 | { | ||
| 463 | struct vmw_stdu_dirty *ddirty = | ||
| 464 | container_of(dirty, struct vmw_stdu_dirty, base); | ||
| 465 | struct vmw_stdu_dma *cmd = dirty->cmd; | ||
| 466 | struct SVGA3dCopyBox *blit = (struct SVGA3dCopyBox *) &cmd[1]; | ||
| 467 | |||
| 468 | blit += dirty->num_hits; | ||
| 469 | blit->srcx = dirty->fb_x; | ||
| 470 | blit->srcy = dirty->fb_y; | ||
| 471 | blit->x = dirty->unit_x1; | ||
| 472 | blit->y = dirty->unit_y1; | ||
| 473 | blit->d = 1; | ||
| 474 | blit->w = dirty->unit_x2 - dirty->unit_x1; | ||
| 475 | blit->h = dirty->unit_y2 - dirty->unit_y1; | ||
| 476 | dirty->num_hits++; | ||
| 477 | |||
| 478 | if (ddirty->transfer != SVGA3D_WRITE_HOST_VRAM) | ||
| 479 | return; | ||
| 480 | |||
| 481 | /* Destination bounding box */ | ||
| 482 | ddirty->left = min_t(s32, ddirty->left, dirty->unit_x1); | ||
| 483 | ddirty->top = min_t(s32, ddirty->top, dirty->unit_y1); | ||
| 484 | ddirty->right = max_t(s32, ddirty->right, dirty->unit_x2); | ||
| 485 | ddirty->bottom = max_t(s32, ddirty->bottom, dirty->unit_y2); | ||
| 486 | } | ||
| 487 | |||
| 488 | /** | ||
| 489 | * vmw_stdu_bo_fifo_commit - Callback to fill in and submit a DMA command. | ||
| 490 | * | ||
| 491 | * @dirty: The closure structure. | ||
| 492 | * | ||
| 493 | * Fills in the missing fields in a DMA command, and optionally encodes | ||
| 494 | * a screen target update command, depending on transfer direction. | ||
| 495 | */ | ||
| 496 | static void vmw_stdu_bo_fifo_commit(struct vmw_kms_dirty *dirty) | ||
| 497 | { | ||
| 498 | struct vmw_stdu_dirty *ddirty = | ||
| 499 | container_of(dirty, struct vmw_stdu_dirty, base); | ||
| 500 | struct vmw_screen_target_display_unit *stdu = | ||
| 501 | container_of(dirty->unit, typeof(*stdu), base); | ||
| 502 | struct vmw_stdu_dma *cmd = dirty->cmd; | ||
| 503 | struct SVGA3dCopyBox *blit = (struct SVGA3dCopyBox *) &cmd[1]; | ||
| 504 | SVGA3dCmdSurfaceDMASuffix *suffix = | ||
| 505 | (SVGA3dCmdSurfaceDMASuffix *) &blit[dirty->num_hits]; | ||
| 506 | size_t blit_size = sizeof(*blit) * dirty->num_hits + sizeof(*suffix); | ||
| 507 | |||
| 508 | if (!dirty->num_hits) { | ||
| 509 | vmw_cmd_commit(dirty->dev_priv, 0); | ||
| 510 | return; | ||
| 511 | } | ||
| 512 | |||
| 513 | cmd->header.id = SVGA_3D_CMD_SURFACE_DMA; | ||
| 514 | cmd->header.size = sizeof(cmd->body) + blit_size; | ||
| 515 | vmw_bo_get_guest_ptr(&ddirty->buf->base, &cmd->body.guest.ptr); | ||
| 516 | cmd->body.guest.pitch = ddirty->pitch; | ||
| 517 | cmd->body.host.sid = stdu->display_srf->res.id; | ||
| 518 | cmd->body.host.face = 0; | ||
| 519 | cmd->body.host.mipmap = 0; | ||
| 520 | cmd->body.transfer = ddirty->transfer; | ||
| 521 | suffix->suffixSize = sizeof(*suffix); | ||
| 522 | suffix->maximumOffset = ddirty->buf->base.base.size; | ||
| 523 | |||
| 524 | if (ddirty->transfer == SVGA3D_WRITE_HOST_VRAM) { | ||
| 525 | blit_size += sizeof(struct vmw_stdu_update); | ||
| 526 | |||
| 527 | vmw_stdu_populate_update(&suffix[1], stdu->base.unit, | ||
| 528 | ddirty->left, ddirty->right, | ||
| 529 | ddirty->top, ddirty->bottom); | ||
| 530 | } | ||
| 531 | |||
| 532 | vmw_cmd_commit(dirty->dev_priv, sizeof(*cmd) + blit_size); | ||
| 533 | |||
| 534 | stdu->display_srf->res.res_dirty = true; | ||
| 535 | ddirty->left = ddirty->top = S32_MAX; | ||
| 536 | ddirty->right = ddirty->bottom = S32_MIN; | ||
| 537 | } | ||
| 538 | |||
| 539 | |||
| 540 | /** | 447 | /** |
| 541 | * vmw_stdu_bo_cpu_clip - Callback to encode a CPU blit | 448 | * vmw_stdu_bo_cpu_clip - Callback to encode a CPU blit |
| 542 | * | 449 | * |
| @@ -597,62 +504,21 @@ static void vmw_stdu_bo_cpu_commit(struct vmw_kms_dirty *dirty) · 54 unmodified lines | |||
| 597 | return; | 504 | return; |
| 598 | 505 | ||
| 599 | /* Assume we are blitting from Guest (bo) to Host (display_srf) */ | 506 | /* Assume we are blitting from Guest (bo) to Host (display_srf) */ |
| 600 | dst_pitch = stdu->display_srf->metadata.base_size.width * stdu->cpp; | 507 | src_pitch = stdu->display_srf->metadata.base_size.width * stdu->cpp; |
| 601 | dst_bo = &stdu->display_srf->res.backup->base; | 508 | src_bo = &stdu->display_srf->res.guest_memory_bo->tbo; |
| 602 | dst_offset = ddirty->top * dst_pitch + ddirty->left * stdu->cpp; | 509 | src_offset = ddirty->top * dst_pitch + ddirty->left * stdu->cpp; |
| 603 | 510 | ||
| 604 | src_pitch = ddirty->pitch; | 511 | dst_pitch = ddirty->pitch; |
| 605 | src_bo = &ddirty->buf->base; | 512 | dst_bo = &ddirty->buf->tbo; |
| 606 | src_offset = ddirty->fb_top * src_pitch + ddirty->fb_left * stdu->cpp; | 513 | dst_offset = ddirty->fb_top * src_pitch + ddirty->fb_left * stdu->cpp; |
| 607 | |||
| 608 | /* Swap src and dst if the assumption was wrong. */ | ||
| 609 | if (ddirty->transfer != SVGA3D_WRITE_HOST_VRAM) { | ||
| 610 | swap(dst_pitch, src_pitch); | ||
| 611 | swap(dst_bo, src_bo); | ||
| 612 | swap(src_offset, dst_offset); | ||
| 613 | } | ||
| 614 | 514 | ||
| 615 | (void) vmw_bo_cpu_blit(dst_bo, dst_offset, dst_pitch, | 515 | (void) vmw_bo_cpu_blit(dst_bo, dst_offset, dst_pitch, |
| 616 | src_bo, src_offset, src_pitch, | 516 | src_bo, src_offset, src_pitch, |
| 617 | width * stdu->cpp, height, &diff); | 517 | width * stdu->cpp, height, &diff); |
| 618 | |||
| 619 | if (ddirty->transfer == SVGA3D_WRITE_HOST_VRAM && | ||
| 620 | drm_rect_visible(&diff.rect)) { | ||
| 621 | struct vmw_private *dev_priv; | ||
| 622 | struct vmw_stdu_update *cmd; | ||
| 623 | struct drm_clip_rect region; | ||
| 624 | int ret; | ||
| 625 | |||
| 626 | /* We are updating the actual surface, not a proxy */ | ||
| 627 | region.x1 = diff.rect.x1; | ||
| 628 | region.x2 = diff.rect.x2; | ||
| 629 | region.y1 = diff.rect.y1; | ||
| 630 | region.y2 = diff.rect.y2; | ||
| 631 | ret = vmw_kms_update_proxy(&stdu->display_srf->res, ®ion, | ||
| 632 | 1, 1); | ||
| 633 | if (ret) | ||
| 634 | goto out_cleanup; | ||
| 635 | |||
| 636 | |||
| 637 | dev_priv = vmw_priv(stdu->base.crtc.dev); | ||
| 638 | cmd = VMW_CMD_RESERVE(dev_priv, sizeof(*cmd)); | ||
| 639 | if (!cmd) | ||
| 640 | goto out_cleanup; | ||
| 641 | |||
| 642 | vmw_stdu_populate_update(cmd, stdu->base.unit, | ||
| 643 | region.x1, region.x2, | ||
| 644 | region.y1, region.y2); | ||
| 645 | |||
| 646 | vmw_cmd_commit(dev_priv, sizeof(*cmd)); | ||
| 647 | } | ||
| 648 | |||
| 649 | out_cleanup: | ||
| 650 | ddirty->left = ddirty->top = ddirty->fb_left = ddirty->fb_top = S32_MAX; | ||
| 651 | ddirty->right = ddirty->bottom = S32_MIN; | ||
| 652 | } | 518 | } |
| 653 | 519 | ||
| 654 | /** | 520 | /** |
| 655 | * vmw_kms_stdu_dma - Perform a DMA transfer between a buffer-object backed | 521 | * vmw_kms_stdu_readback - Perform a readback from a buffer-object backed |
| 656 | * framebuffer and the screen target system. | 522 | * framebuffer and the screen target system. |
| 657 | * | 523 | * |
| 658 | * @dev_priv: Pointer to the device private structure. | 524 | * @dev_priv: Pointer to the device private structure. |
| @@ -665,9 +531,6 @@ out_cleanup: · 6 unmodified lines | |||
| 665 | * be NULL. | 531 | * be NULL. |
| 666 | * @num_clips: Number of clip rects in @clips or @vclips. | 532 | * @num_clips: Number of clip rects in @clips or @vclips. |
| 667 | * @increment: Increment to use when looping over @clips or @vclips. | 533 | * @increment: Increment to use when looping over @clips or @vclips. |
| 668 | * @to_surface: Whether to DMA to the screen target system as opposed to | ||
| 669 | * from the screen target system. | ||
| 670 | * @interruptible: Whether to perform waits interruptible if possible. | ||
| 671 | * @crtc: If crtc is passed, perform stdu dma on that crtc only. | 534 | * @crtc: If crtc is passed, perform stdu dma on that crtc only. |
| 672 | * | 535 | * |
| 673 | * If DMA-ing till the screen target system, the function will also notify | 536 | * If DMA-ing till the screen target system, the function will also notify |
| @@ -676,59 +539,49 @@ out_cleanup: · 2 unmodified lines | |||
| 676 | * Returns 0 on success, negative error code on failure. -ERESTARTSYS if | 539 | * Returns 0 on success, negative error code on failure. -ERESTARTSYS if |
| 677 | * interrupted. | 540 | * interrupted. |
| 678 | */ | 541 | */ |
| 679 | int vmw_kms_stdu_dma(struct vmw_private *dev_priv, | 542 | int vmw_kms_stdu_readback(struct vmw_private *dev_priv, |
| 680 | struct drm_file *file_priv, | 543 | struct drm_file *file_priv, |
| 681 | struct vmw_framebuffer *vfb, | 544 | struct vmw_framebuffer *vfb, |
| 682 | struct drm_vmw_fence_rep __user *user_fence_rep, | 545 | struct drm_vmw_fence_rep __user *user_fence_rep, |
| 683 | struct drm_clip_rect *clips, | 546 | struct drm_clip_rect *clips, |
| 684 | struct drm_vmw_rect *vclips, | 547 | struct drm_vmw_rect *vclips, |
| 685 | uint32_t num_clips, | 548 | uint32_t num_clips, |
| 686 | int increment, | 549 | int increment, |
| 687 | bool to_surface, | 550 | struct drm_crtc *crtc) |
| 688 | bool interruptible, | ||
| 689 | struct drm_crtc *crtc) | ||
| 690 | { | 551 | { |
| 691 | struct vmw_buffer_object *buf = | 552 | struct vmw_bo *buf = |
| 692 | container_of(vfb, struct vmw_framebuffer_bo, base)->buffer; | 553 | container_of(vfb, struct vmw_framebuffer_bo, base)->buffer; |
| 693 | struct vmw_stdu_dirty ddirty; | 554 | struct vmw_stdu_dirty ddirty; |
| 694 | int ret; | 555 | int ret; |
| 695 | bool cpu_blit = vmw_stdu_use_cpu_blit(dev_priv); | ||
| 696 | DECLARE_VAL_CONTEXT(val_ctx, NULL, 0); | 556 | DECLARE_VAL_CONTEXT(val_ctx, NULL, 0); |
| 697 | 557 | ||
| 698 | /* | 558 | /* |
| 699 | * VMs without 3D support don't have the surface DMA command and | 559 | * The GMR domain might seem confusing because it might seem like it should |
| 700 | * we'll be using a CPU blit, and the framebuffer should be moved out | 560 | * never happen with screen targets but e.g. the xorg vmware driver issues |
| 701 | * of VRAM. | 561 | * CMD_SURFACE_DMA for various pixmap updates which might transition our bo to |
| 562 | * a GMR. Instead of forcing another transition we can optimize the readback | ||
| 563 | * by reading directly from the GMR. | ||
| 702 | */ | 564 | */ |
| 703 | ret = vmw_validation_add_bo(&val_ctx, buf, false, cpu_blit); | 565 | vmw_bo_placement_set(buf, |
| 566 | VMW_BO_DOMAIN_MOB | VMW_BO_DOMAIN_SYS | VMW_BO_DOMAIN_GMR, | ||
| 567 | VMW_BO_DOMAIN_MOB | VMW_BO_DOMAIN_SYS | VMW_BO_DOMAIN_GMR); | ||
| 568 | ret = vmw_validation_add_bo(&val_ctx, buf); | ||
| 704 | if (ret) | 569 | if (ret) |
| 705 | return ret; | 570 | return ret; |
| 706 | 571 | ||
| 707 | ret = vmw_validation_prepare(&val_ctx, NULL, interruptible); | 572 | ret = vmw_validation_prepare(&val_ctx, NULL, true); |
| 708 | if (ret) | 573 | if (ret) |
| 709 | goto out_unref; | 574 | goto out_unref; |
| 710 | 575 | ||
| 711 | ddirty.transfer = (to_surface) ? SVGA3D_WRITE_HOST_VRAM : | ||
| 712 | SVGA3D_READ_HOST_VRAM; | ||
| 713 | ddirty.left = ddirty.top = S32_MAX; | 576 | ddirty.left = ddirty.top = S32_MAX; |
| 714 | ddirty.right = ddirty.bottom = S32_MIN; | 577 | ddirty.right = ddirty.bottom = S32_MIN; |
| 715 | ddirty.fb_left = ddirty.fb_top = S32_MAX; | 578 | ddirty.fb_left = ddirty.fb_top = S32_MAX; |
| 716 | ddirty.pitch = vfb->base.pitches[0]; | 579 | ddirty.pitch = vfb->base.pitches[0]; |
| 717 | ddirty.buf = buf; | 580 | ddirty.buf = buf; |
| 718 | ddirty.base.fifo_commit = vmw_stdu_bo_fifo_commit; | 581 | |
| 719 | ddirty.base.clip = vmw_stdu_bo_clip; | 582 | ddirty.base.fifo_commit = vmw_stdu_bo_cpu_commit; |
| 720 | ddirty.base.fifo_reserve_size = sizeof(struct vmw_stdu_dma) + | 583 | ddirty.base.clip = vmw_stdu_bo_cpu_clip; |
| 721 | num_clips * sizeof(SVGA3dCopyBox) + | 584 | ddirty.base.fifo_reserve_size = 0; |
| 722 | sizeof(SVGA3dCmdSurfaceDMASuffix); | ||
| 723 | if (to_surface) | ||
| 724 | ddirty.base.fifo_reserve_size += sizeof(struct vmw_stdu_update); | ||
| 725 | |||
| 726 | |||
| 727 | if (cpu_blit) { | ||
| 728 | ddirty.base.fifo_commit = vmw_stdu_bo_cpu_commit; | ||
| 729 | ddirty.base.clip = vmw_stdu_bo_cpu_clip; | ||
| 730 | ddirty.base.fifo_reserve_size = 0; | ||
| 731 | } | ||
| 732 | 585 | ||
| 733 | ddirty.base.crtc = crtc; | 586 | ddirty.base.crtc = crtc; |
| 734 | 587 | ||
| @@ -1160,11 +1013,8 @@ vmw_stdu_primary_plane_prepare_fb(struct drm_plane *plane, · 425 unmodified lines | |||
| 1160 | /* | 1013 | /* |
| 1161 | * This should only happen if the buffer object is too large to create a | 1014 | * This should only happen if the buffer object is too large to create a |
| 1162 | * proxy surface for. | 1015 | * proxy surface for. |
| 1163 | * If we are a 2D VM with a buffer object then we have to use CPU blit | ||
| 1164 | * so cache these mappings | ||
| 1165 | */ | 1016 | */ |
| 1166 | if (vps->content_fb_type == SEPARATE_BO && | 1017 | if (vps->content_fb_type == SEPARATE_BO) |
| 1167 | vmw_stdu_use_cpu_blit(dev_priv)) | ||
| 1168 | vps->cpp = new_fb->pitches[0] / new_fb->width; | 1018 | vps->cpp = new_fb->pitches[0] / new_fb->width; |
| 1169 | 1019 | ||
| 1170 | return 0; | 1020 | return 0; |
| @@ -1174,14 +1024,6 @@ out_srf_unref: · 3 unmodified lines | |||
| 1174 | return ret; | 1024 | return ret; |
| 1175 | } | 1025 | } |
| 1176 | 1026 | ||
| 1177 | static uint32_t vmw_stdu_bo_fifo_size(struct vmw_du_update_plane *update, | ||
| 1178 | uint32_t num_hits) | ||
| 1179 | { | ||
| 1180 | return sizeof(struct vmw_stdu_dma) + sizeof(SVGA3dCopyBox) * num_hits + | ||
| 1181 | sizeof(SVGA3dCmdSurfaceDMASuffix) + | ||
| 1182 | sizeof(struct vmw_stdu_update); | ||
| 1183 | } | ||
| 1184 | |||
| 1185 | static uint32_t vmw_stdu_bo_fifo_size_cpu(struct vmw_du_update_plane *update, | 1027 | static uint32_t vmw_stdu_bo_fifo_size_cpu(struct vmw_du_update_plane *update, |
| 1186 | uint32_t num_hits) | 1028 | uint32_t num_hits) |
| 1187 | { | 1029 | { |
| @@ -1189,68 +1031,6 @@ static uint32_t vmw_stdu_bo_fifo_size_cpu(struct vmw_du_update_plane *update, · 1 unmodified line | |||
| 1189 | sizeof(struct vmw_stdu_update); | 1031 | sizeof(struct vmw_stdu_update); |
| 1190 | } | 1032 | } |
| 1191 | 1033 | ||
| 1192 | static uint32_t vmw_stdu_bo_populate_dma(struct vmw_du_update_plane *update, | ||
| 1193 | void *cmd, uint32_t num_hits) | ||
| 1194 | { | ||
| 1195 | struct vmw_screen_target_display_unit *stdu; | ||
| 1196 | struct vmw_framebuffer_bo *vfbbo; | ||
| 1197 | struct vmw_stdu_dma *cmd_dma = cmd; | ||
| 1198 | |||
| 1199 | stdu = container_of(update->du, typeof(*stdu), base); | ||
| 1200 | vfbbo = container_of(update->vfb, typeof(*vfbbo), base); | ||
| 1201 | |||
| 1202 | cmd_dma->header.id = SVGA_3D_CMD_SURFACE_DMA; | ||
| 1203 | cmd_dma->header.size = sizeof(cmd_dma->body) + | ||
| 1204 | sizeof(struct SVGA3dCopyBox) * num_hits + | ||
| 1205 | sizeof(SVGA3dCmdSurfaceDMASuffix); | ||
| 1206 | vmw_bo_get_guest_ptr(&vfbbo->buffer->base, &cmd_dma->body.guest.ptr); | ||
| 1207 | cmd_dma->body.guest.pitch = update->vfb->base.pitches[0]; | ||
| 1208 | cmd_dma->body.host.sid = stdu->display_srf->res.id; | ||
| 1209 | cmd_dma->body.host.face = 0; | ||
| 1210 | cmd_dma->body.host.mipmap = 0; | ||
| 1211 | cmd_dma->body.transfer = SVGA3D_WRITE_HOST_VRAM; | ||
| 1212 | |||
| 1213 | return sizeof(*cmd_dma); | ||
| 1214 | } | ||
| 1215 | |||
| 1216 | static uint32_t vmw_stdu_bo_populate_clip(struct vmw_du_update_plane *update, | ||
| 1217 | void *cmd, struct drm_rect *clip, | ||
| 1218 | uint32_t fb_x, uint32_t fb_y) | ||
| 1219 | { | ||
| 1220 | struct SVGA3dCopyBox *box = cmd; | ||
| 1221 | |||
| 1222 | box->srcx = fb_x; | ||
| 1223 | box->srcy = fb_y; | ||
| 1224 | box->srcz = 0; | ||
| 1225 | box->x = clip->x1; | ||
| 1226 | box->y = clip->y1; | ||
| 1227 | box->z = 0; | ||
| 1228 | box->w = drm_rect_width(clip); | ||
| 1229 | box->h = drm_rect_height(clip); | ||
| 1230 | box->d = 1; | ||
| 1231 | |||
| 1232 | return sizeof(*box); | ||
| 1233 | } | ||
| 1234 | |||
| 1235 | static uint32_t vmw_stdu_bo_populate_update(struct vmw_du_update_plane *update, | ||
| 1236 | void *cmd, struct drm_rect *bb) | ||
| 1237 | { | ||
| 1238 | struct vmw_screen_target_display_unit *stdu; | ||
| 1239 | struct vmw_framebuffer_bo *vfbbo; | ||
| 1240 | SVGA3dCmdSurfaceDMASuffix *suffix = cmd; | ||
| 1241 | |||
| 1242 | stdu = container_of(update->du, typeof(*stdu), base); | ||
| 1243 | vfbbo = container_of(update->vfb, typeof(*vfbbo), base); | ||
| 1244 | |||
| 1245 | suffix->suffixSize = sizeof(*suffix); | ||
| 1246 | suffix->maximumOffset = vfbbo->buffer->base.base.size; | ||
| 1247 | |||
| 1248 | vmw_stdu_populate_update(&suffix[1], stdu->base.unit, bb->x1, bb->x2, | ||
| 1249 | bb->y1, bb->y2); | ||
| 1250 | |||
| 1251 | return sizeof(*suffix) + sizeof(struct vmw_stdu_update); | ||
| 1252 | } | ||
| 1253 | |||
| 1254 | static uint32_t vmw_stdu_bo_pre_clip_cpu(struct vmw_du_update_plane *update, | 1034 | static uint32_t vmw_stdu_bo_pre_clip_cpu(struct vmw_du_update_plane *update, |
| 1255 | void *cmd, uint32_t num_hits) | 1035 | void *cmd, uint32_t num_hits) |
| 1256 | { | 1036 | { |
| @@ -1300,11 +1080,11 @@ vmw_stdu_bo_populate_update_cpu(struct vmw_du_update_plane *update, void *cmd, · 43 unmodified lines | |||
| 1300 | 1080 | ||
| 1301 | diff.cpp = stdu->cpp; | 1081 | diff.cpp = stdu->cpp; |
| 1302 | 1082 | ||
| 1303 | dst_bo = &stdu->display_srf->res.backup->base; | 1083 | dst_bo = &stdu->display_srf->res.guest_memory_bo->tbo; |
| 1304 | dst_pitch = stdu->display_srf->metadata.base_size.width * stdu->cpp; | 1084 | dst_pitch = stdu->display_srf->metadata.base_size.width * stdu->cpp; |
| 1305 | dst_offset = bb->y1 * dst_pitch + bb->x1 * stdu->cpp; | 1085 | dst_offset = bb->y1 * dst_pitch + bb->x1 * stdu->cpp; |
| 1306 | 1086 | ||
| 1307 | src_bo = &vfbbo->buffer->base; | 1087 | src_bo = &vfbbo->buffer->tbo; |
| 1308 | src_pitch = update->vfb->base.pitches[0]; | 1088 | src_pitch = update->vfb->base.pitches[0]; |
| 1309 | src_offset = bo_update->fb_top * src_pitch + bo_update->fb_left * | 1089 | src_offset = bo_update->fb_top * src_pitch + bo_update->fb_left * |
| 1310 | stdu->cpp; | 1090 | stdu->cpp; |
| @@ -1368,24 +1148,12 @@ static int vmw_stdu_plane_update_bo(struct vmw_private *dev_priv, · 57 unmodified lines | |||
| 1368 | bo_update.base.vfb = vfb; | 1148 | bo_update.base.vfb = vfb; |
| 1369 | bo_update.base.out_fence = out_fence; | 1149 | bo_update.base.out_fence = out_fence; |
| 1370 | bo_update.base.mutex = NULL; | 1150 | bo_update.base.mutex = NULL; |
| 1371 | bo_update.base.cpu_blit = vmw_stdu_use_cpu_blit(dev_priv); | ||
| 1372 | bo_update.base.intr = false; | 1151 | bo_update.base.intr = false; |
| 1373 | 1152 | ||
| 1374 | /* | 1153 | bo_update.base.calc_fifo_size = vmw_stdu_bo_fifo_size_cpu; |
| 1375 | * VM without 3D support don't have surface DMA command and framebuffer | 1154 | bo_update.base.pre_clip = vmw_stdu_bo_pre_clip_cpu; |
| 1376 | * should be moved out of VRAM. | 1155 | bo_update.base.clip = vmw_stdu_bo_clip_cpu; |
| 1377 | */ | 1156 | bo_update.base.post_clip = vmw_stdu_bo_populate_update_cpu; |
| 1378 | if (bo_update.base.cpu_blit) { | ||
| 1379 | bo_update.base.calc_fifo_size = vmw_stdu_bo_fifo_size_cpu; | ||
| 1380 | bo_update.base.pre_clip = vmw_stdu_bo_pre_clip_cpu; | ||
| 1381 | bo_update.base.clip = vmw_stdu_bo_clip_cpu; | ||
| 1382 | bo_update.base.post_clip = vmw_stdu_bo_populate_update_cpu; | ||
| 1383 | } else { | ||
| 1384 | bo_update.base.calc_fifo_size = vmw_stdu_bo_fifo_size; | ||
| 1385 | bo_update.base.pre_clip = vmw_stdu_bo_populate_dma; | ||
| 1386 | bo_update.base.clip = vmw_stdu_bo_populate_clip; | ||
| 1387 | bo_update.base.post_clip = vmw_stdu_bo_populate_update; | ||
| 1388 | } | ||
| 1389 | 1157 | ||
| 1390 | return vmw_du_helper_plane_update(&bo_update.base); | 1158 | return vmw_du_helper_plane_update(&bo_update.base); |
| 1391 | } | 1159 | } |
| @@ -1548,7 +1316,6 @@ static int vmw_stdu_plane_update_surface(struct vmw_private *dev_priv, · 156 unmodified lines | |||
| 1548 | srf_update.vfb = vfb; | 1316 | srf_update.vfb = vfb; |
| 1549 | srf_update.out_fence = out_fence; | 1317 | srf_update.out_fence = out_fence; |
| 1550 | srf_update.mutex = &dev_priv->cmdbuf_mutex; | 1318 | srf_update.mutex = &dev_priv->cmdbuf_mutex; |
| 1551 | srf_update.cpu_blit = false; | ||
| 1552 | srf_update.intr = true; | 1319 | srf_update.intr = true; |
| 1553 | 1320 | ||
| 1554 | if (vfbs->is_bo_proxy) | 1321 | if (vfbs->is_bo_proxy) |
| @@ -1,7 +1,7 @@ | |||
| 1 | // SPDX-License-Identifier: GPL-2.0 OR MIT | 1 | // SPDX-License-Identifier: GPL-2.0 OR MIT |
| 2 | /************************************************************************** | 2 | /************************************************************************** |
| 3 | * | 3 | * |
| 4 | * Copyright © 2018-2019 VMware, Inc., Palo Alto, CA., USA | 4 | * Copyright © 2018-2023 VMware, Inc., Palo Alto, CA., USA |
| 5 | * All Rights Reserved. | 5 | * All Rights Reserved. |
| 6 | * | 6 | * |
| 7 | * Permission is hereby granted, free of charge, to any person obtaining a | 7 | * Permission is hereby granted, free of charge, to any person obtaining a |
| @@ -26,11 +26,12 @@ · 18 unmodified lines | |||
| 26 | * | 26 | * |
| 27 | **************************************************************************/ | 27 | **************************************************************************/ |
| 28 | 28 | ||
| 29 | #include <drm/ttm/ttm_placement.h> | 29 | #include "vmwgfx_binding.h" |
| 30 | 30 | #include "vmwgfx_bo.h" | |
| 31 | #include "vmwgfx_drv.h" | 31 | #include "vmwgfx_drv.h" |
| 32 | #include "vmwgfx_resource_priv.h" | 32 | #include "vmwgfx_resource_priv.h" |
| 33 | #include "vmwgfx_binding.h" | 33 | |
| 34 | #include <drm/ttm/ttm_placement.h> | ||
| 34 | 35 | ||
| 35 | /** | 36 | /** |
| 36 | * struct vmw_dx_streamoutput - Streamoutput resource metadata. | 37 | * struct vmw_dx_streamoutput - Streamoutput resource metadata. |
| @@ -62,10 +63,11 @@ static void vmw_dx_streamoutput_commit_notify(struct vmw_resource *res, · 25 unmodified lines | |||
| 62 | 63 | ||
| 63 | static const struct vmw_res_func vmw_dx_streamoutput_func = { | 64 | static const struct vmw_res_func vmw_dx_streamoutput_func = { |
| 64 | .res_type = vmw_res_streamoutput, | 65 | .res_type = vmw_res_streamoutput, |
| 65 | .needs_backup = true, | 66 | .needs_guest_memory = true, |
| 66 | .may_evict = false, | 67 | .may_evict = false, |
| 67 | .type_name = "DX streamoutput", | 68 | .type_name = "DX streamoutput", |
| 68 | .backup_placement = &vmw_mob_placement, | 69 | .domain = VMW_BO_DOMAIN_MOB, |
| 70 | .busy_domain = VMW_BO_DOMAIN_MOB, | ||
| 69 | .create = vmw_dx_streamoutput_create, | 71 | .create = vmw_dx_streamoutput_create, |
| 70 | .destroy = NULL, /* Command buffer managed resource. */ | 72 | .destroy = NULL, /* Command buffer managed resource. */ |
| 71 | .bind = vmw_dx_streamoutput_bind, | 73 | .bind = vmw_dx_streamoutput_bind, |
| @@ -104,8 +106,8 @@ static int vmw_dx_streamoutput_unscrub(struct vmw_resource *res) · 32 unmodified lines | |||
| 104 | cmd->header.id = SVGA_3D_CMD_DX_BIND_STREAMOUTPUT; | 106 | cmd->header.id = SVGA_3D_CMD_DX_BIND_STREAMOUTPUT; |
| 105 | cmd->header.size = sizeof(cmd->body); | 107 | cmd->header.size = sizeof(cmd->body); |
| 106 | cmd->body.soid = so->id; | 108 | cmd->body.soid = so->id; |
| 107 | cmd->body.mobid = res->backup->base.resource->start; | 109 | cmd->body.mobid = res->guest_memory_bo->tbo.resource->start; |
| 108 | cmd->body.offsetInBytes = res->backup_offset; | 110 | cmd->body.offsetInBytes = res->guest_memory_offset; |
| 109 | cmd->body.sizeInBytes = so->size; | 111 | cmd->body.sizeInBytes = so->size; |
| 110 | vmw_cmd_commit(dev_priv, sizeof(*cmd)); | 112 | vmw_cmd_commit(dev_priv, sizeof(*cmd)); |
| 111 | 113 | ||
| @@ -195,7 +197,7 @@ static int vmw_dx_streamoutput_unbind(struct vmw_resource *res, bool readback, · 83 unmodified lines | |||
| 195 | struct vmw_fence_obj *fence; | 197 | struct vmw_fence_obj *fence; |
| 196 | int ret; | 198 | int ret; |
| 197 | 199 | ||
| 198 | if (WARN_ON(res->backup->base.resource->mem_type != VMW_PL_MOB)) | 200 | if (WARN_ON(res->guest_memory_bo->tbo.resource->mem_type != VMW_PL_MOB)) |
| 199 | return -EINVAL; | 201 | return -EINVAL; |
| 200 | 202 | ||
| 201 | mutex_lock(&dev_priv->binding_mutex); | 203 | mutex_lock(&dev_priv->binding_mutex); |
| @@ -1,7 +1,7 @@ | |||
| 1 | // SPDX-License-Identifier: GPL-2.0 OR MIT | 1 | // SPDX-License-Identifier: GPL-2.0 OR MIT |
| 2 | /************************************************************************** | 2 | /************************************************************************** |
| 3 | * | 3 | * |
| 4 | * Copyright 2009-2015 VMware, Inc., Palo Alto, CA., USA | 4 | * Copyright 2009-2023 VMware, Inc., Palo Alto, CA., USA |
| 5 | * | 5 | * |
| 6 | * Permission is hereby granted, free of charge, to any person obtaining a | 6 | * Permission is hereby granted, free of charge, to any person obtaining a |
| 7 | * copy of this software and associated documentation files (the | 7 | * copy of this software and associated documentation files (the |
| @@ -25,8 +25,7 @@ · 17 unmodified lines | |||
| 25 | * | 25 | * |
| 26 | **************************************************************************/ | 26 | **************************************************************************/ |
| 27 | 27 | ||
| 28 | #include <drm/ttm/ttm_placement.h> | 28 | #include "vmwgfx_bo.h" |
| 29 | |||
| 30 | #include "vmwgfx_drv.h" | 29 | #include "vmwgfx_drv.h" |
| 31 | #include "vmwgfx_resource_priv.h" | 30 | #include "vmwgfx_resource_priv.h" |
| 32 | #include "vmwgfx_so.h" | 31 | #include "vmwgfx_so.h" |
| @@ -34,6 +33,8 @@ · 1 unmodified line | |||
| 34 | #include "vmw_surface_cache.h" | 33 | #include "vmw_surface_cache.h" |
| 35 | #include "device_include/svga3d_surfacedefs.h" | 34 | #include "device_include/svga3d_surfacedefs.h" |
| 36 | 35 | ||
| 36 | #include <drm/ttm/ttm_placement.h> | ||
| 37 | |||
| 37 | #define SVGA3D_FLAGS_64(upper32, lower32) (((uint64_t)upper32 << 32) | lower32) | 38 | #define SVGA3D_FLAGS_64(upper32, lower32) (((uint64_t)upper32 << 32) | lower32) |
| 38 | #define SVGA3D_FLAGS_UPPER_32(svga3d_flags) (svga3d_flags >> 32) | 39 | #define SVGA3D_FLAGS_UPPER_32(svga3d_flags) (svga3d_flags >> 32) |
| 39 | #define SVGA3D_FLAGS_LOWER_32(svga3d_flags) \ | 40 | #define SVGA3D_FLAGS_LOWER_32(svga3d_flags) \ |
| @@ -125,12 +126,13 @@ const struct vmw_user_resource_conv *user_surface_converter = · 85 unmodified lines | |||
| 125 | 126 | ||
| 126 | static const struct vmw_res_func vmw_legacy_surface_func = { | 127 | static const struct vmw_res_func vmw_legacy_surface_func = { |
| 127 | .res_type = vmw_res_surface, | 128 | .res_type = vmw_res_surface, |
| 128 | .needs_backup = false, | 129 | .needs_guest_memory = false, |
| 129 | .may_evict = true, | 130 | .may_evict = true, |
| 130 | .prio = 1, | 131 | .prio = 1, |
| 131 | .dirty_prio = 1, | 132 | .dirty_prio = 1, |
| 132 | .type_name = "legacy surfaces", | 133 | .type_name = "legacy surfaces", |
| 133 | .backup_placement = &vmw_srf_placement, | 134 | .domain = VMW_BO_DOMAIN_GMR, |
| 135 | .busy_domain = VMW_BO_DOMAIN_GMR | VMW_BO_DOMAIN_VRAM, | ||
| 134 | .create = &vmw_legacy_srf_create, | 136 | .create = &vmw_legacy_srf_create, |
| 135 | .destroy = &vmw_legacy_srf_destroy, | 137 | .destroy = &vmw_legacy_srf_destroy, |
| 136 | .bind = &vmw_legacy_srf_bind, | 138 | .bind = &vmw_legacy_srf_bind, |
| @@ -139,12 +141,13 @@ static const struct vmw_res_func vmw_legacy_surface_func = { · 2 unmodified lines | |||
| 139 | 141 | ||
| 140 | static const struct vmw_res_func vmw_gb_surface_func = { | 142 | static const struct vmw_res_func vmw_gb_surface_func = { |
| 141 | .res_type = vmw_res_surface, | 143 | .res_type = vmw_res_surface, |
| 142 | .needs_backup = true, | 144 | .needs_guest_memory = true, |
| 143 | .may_evict = true, | 145 | .may_evict = true, |
| 144 | .prio = 1, | 146 | .prio = 1, |
| 145 | .dirty_prio = 2, | 147 | .dirty_prio = 2, |
| 146 | .type_name = "guest backed surfaces", | 148 | .type_name = "guest backed surfaces", |
| 147 | .backup_placement = &vmw_mob_placement, | 149 | .domain = VMW_BO_DOMAIN_MOB, |
| 150 | .busy_domain = VMW_BO_DOMAIN_MOB, | ||
| 148 | .create = vmw_gb_surface_create, | 151 | .create = vmw_gb_surface_create, |
| 149 | .destroy = vmw_gb_surface_destroy, | 152 | .destroy = vmw_gb_surface_destroy, |
| 150 | .bind = vmw_gb_surface_bind, | 153 | .bind = vmw_gb_surface_bind, |
| @@ -379,7 +382,7 @@ static void vmw_hw_surface_destroy(struct vmw_resource *res) · 228 unmodified lines | |||
| 379 | */ | 382 | */ |
| 380 | 383 | ||
| 381 | mutex_lock(&dev_priv->cmdbuf_mutex); | 384 | mutex_lock(&dev_priv->cmdbuf_mutex); |
| 382 | dev_priv->used_memory_size -= res->backup_size; | 385 | dev_priv->used_memory_size -= res->guest_memory_size; |
| 383 | mutex_unlock(&dev_priv->cmdbuf_mutex); | 386 | mutex_unlock(&dev_priv->cmdbuf_mutex); |
| 384 | } | 387 | } |
| 385 | } | 388 | } |
| @@ -409,7 +412,7 @@ static int vmw_legacy_srf_create(struct vmw_resource *res) · 23 unmodified lines | |||
| 409 | return 0; | 412 | return 0; |
| 410 | 413 | ||
| 411 | srf = vmw_res_to_srf(res); | 414 | srf = vmw_res_to_srf(res); |
| 412 | if (unlikely(dev_priv->used_memory_size + res->backup_size >= | 415 | if (unlikely(dev_priv->used_memory_size + res->guest_memory_size >= |
| 413 | dev_priv->memory_size)) | 416 | dev_priv->memory_size)) |
| 414 | return -EBUSY; | 417 | return -EBUSY; |
| 415 | 418 | ||
| @@ -447,7 +450,7 @@ static int vmw_legacy_srf_create(struct vmw_resource *res) · 31 unmodified lines | |||
| 447 | * Surface memory usage accounting. | 450 | * Surface memory usage accounting. |
| 448 | */ | 451 | */ |
| 449 | 452 | ||
| 450 | dev_priv->used_memory_size += res->backup_size; | 453 | dev_priv->used_memory_size += res->guest_memory_size; |
| 451 | return 0; | 454 | return 0; |
| 452 | 455 | ||
| 453 | out_no_fifo: | 456 | out_no_fifo: |
| @@ -524,7 +527,7 @@ static int vmw_legacy_srf_dma(struct vmw_resource *res, · 70 unmodified lines | |||
| 524 | static int vmw_legacy_srf_bind(struct vmw_resource *res, | 527 | static int vmw_legacy_srf_bind(struct vmw_resource *res, |
| 525 | struct ttm_validate_buffer *val_buf) | 528 | struct ttm_validate_buffer *val_buf) |
| 526 | { | 529 | { |
| 527 | if (!res->backup_dirty) | 530 | if (!res->guest_memory_dirty) |
| 528 | return 0; | 531 | return 0; |
| 529 | 532 | ||
| 530 | return vmw_legacy_srf_dma(res, val_buf, true); | 533 | return vmw_legacy_srf_dma(res, val_buf, true); |
| @@ -583,7 +586,7 @@ static int vmw_legacy_srf_destroy(struct vmw_resource *res) · 52 unmodified lines | |||
| 583 | * Surface memory usage accounting. | 586 | * Surface memory usage accounting. |
| 584 | */ | 587 | */ |
| 585 | 588 | ||
| 586 | dev_priv->used_memory_size -= res->backup_size; | 589 | dev_priv->used_memory_size -= res->guest_memory_size; |
| 587 | 590 | ||
| 588 | /* | 591 | /* |
| 589 | * Release the surface ID. | 592 | * Release the surface ID. |
| @@ -683,8 +686,8 @@ static void vmw_user_surface_base_release(struct ttm_base_object **p_base) · 93 unmodified lines | |||
| 683 | container_of(base, struct vmw_user_surface, prime.base); | 686 | container_of(base, struct vmw_user_surface, prime.base); |
| 684 | struct vmw_resource *res = &user_srf->srf.res; | 687 | struct vmw_resource *res = &user_srf->srf.res; |
| 685 | 688 | ||
| 686 | if (res && res->backup) | 689 | if (res->guest_memory_bo) |
| 687 | drm_gem_object_put(&res->backup->base.base); | 690 | drm_gem_object_put(&res->guest_memory_bo->tbo.base); |
| 688 | 691 | ||
| 689 | *p_base = NULL; | 692 | *p_base = NULL; |
| 690 | vmw_resource_unreference(&res); | 693 | vmw_resource_unreference(&res); |
| @@ -812,7 +815,7 @@ int vmw_surface_define_ioctl(struct drm_device *dev, void *data, · 121 unmodified lines | |||
| 812 | ++cur_size; | 815 | ++cur_size; |
| 813 | } | 816 | } |
| 814 | } | 817 | } |
| 815 | res->backup_size = cur_bo_offset; | 818 | res->guest_memory_size = cur_bo_offset; |
| 816 | if (metadata->scanout && | 819 | if (metadata->scanout && |
| 817 | metadata->num_sizes == 1 && | 820 | metadata->num_sizes == 1 && |
| 818 | metadata->sizes[0].width == VMW_CURSOR_SNOOP_WIDTH && | 821 | metadata->sizes[0].width == VMW_CURSOR_SNOOP_WIDTH && |
| @@ -856,14 +859,14 @@ int vmw_surface_define_ioctl(struct drm_device *dev, void *data, · 37 unmodified lines | |||
| 856 | 859 | ||
| 857 | ret = vmw_gem_object_create_with_handle(dev_priv, | 860 | ret = vmw_gem_object_create_with_handle(dev_priv, |
| 858 | file_priv, | 861 | file_priv, |
| 859 | res->backup_size, | 862 | res->guest_memory_size, |
| 860 | &backup_handle, | 863 | &backup_handle, |
| 861 | &res->backup); | 864 | &res->guest_memory_bo); |
| 862 | if (unlikely(ret != 0)) { | 865 | if (unlikely(ret != 0)) { |
| 863 | vmw_resource_unreference(&res); | 866 | vmw_resource_unreference(&res); |
| 864 | goto out_unlock; | 867 | goto out_unlock; |
| 865 | } | 868 | } |
| 866 | vmw_bo_reference(res->backup); | 869 | vmw_bo_reference(res->guest_memory_bo); |
| 867 | /* | 870 | /* |
| 868 | * We don't expose the handle to the userspace and surface | 871 | * We don't expose the handle to the userspace and surface |
| 869 | * already holds a gem reference | 872 | * already holds a gem reference |
| @@ -872,7 +875,7 @@ int vmw_surface_define_ioctl(struct drm_device *dev, void *data, · 2 unmodified lines | |||
| 872 | } | 875 | } |
| 873 | 876 | ||
| 874 | tmp = vmw_resource_reference(&srf->res); | 877 | tmp = vmw_resource_reference(&srf->res); |
| 875 | ret = ttm_prime_object_init(tfile, res->backup_size, &user_srf->prime, | 878 | ret = ttm_prime_object_init(tfile, res->guest_memory_size, &user_srf->prime, |
| 876 | req->shareable, VMW_RES_SURFACE, | 879 | req->shareable, VMW_RES_SURFACE, |
| 877 | &vmw_user_surface_base_release); | 880 | &vmw_user_surface_base_release); |
| 878 | 881 | ||
| @@ -1186,7 +1189,7 @@ static int vmw_gb_surface_bind(struct vmw_resource *res, · 307 unmodified lines | |||
| 1186 | 1189 | ||
| 1187 | BUG_ON(bo->resource->mem_type != VMW_PL_MOB); | 1190 | BUG_ON(bo->resource->mem_type != VMW_PL_MOB); |
| 1188 | 1191 | ||
| 1189 | submit_size = sizeof(*cmd1) + (res->backup_dirty ? sizeof(*cmd2) : 0); | 1192 | submit_size = sizeof(*cmd1) + (res->guest_memory_dirty ? sizeof(*cmd2) : 0); |
| 1190 | 1193 | ||
| 1191 | cmd1 = VMW_CMD_RESERVE(dev_priv, submit_size); | 1194 | cmd1 = VMW_CMD_RESERVE(dev_priv, submit_size); |
| 1192 | if (unlikely(!cmd1)) | 1195 | if (unlikely(!cmd1)) |
| @@ -1196,7 +1199,7 @@ static int vmw_gb_surface_bind(struct vmw_resource *res, · 3 unmodified lines | |||
| 1196 | cmd1->header.size = sizeof(cmd1->body); | 1199 | cmd1->header.size = sizeof(cmd1->body); |
| 1197 | cmd1->body.sid = res->id; | 1200 | cmd1->body.sid = res->id; |
| 1198 | cmd1->body.mobid = bo->resource->start; | 1201 | cmd1->body.mobid = bo->resource->start; |
| 1199 | if (res->backup_dirty) { | 1202 | if (res->guest_memory_dirty) { |
| 1200 | cmd2 = (void *) &cmd1[1]; | 1203 | cmd2 = (void *) &cmd1[1]; |
| 1201 | cmd2->header.id = SVGA_3D_CMD_UPDATE_GB_SURFACE; | 1204 | cmd2->header.id = SVGA_3D_CMD_UPDATE_GB_SURFACE; |
| 1202 | cmd2->header.size = sizeof(cmd2->body); | 1205 | cmd2->header.size = sizeof(cmd2->body); |
| @@ -1204,12 +1207,12 @@ static int vmw_gb_surface_bind(struct vmw_resource *res, · 1 unmodified line | |||
| 1204 | } | 1207 | } |
| 1205 | vmw_cmd_commit(dev_priv, submit_size); | 1208 | vmw_cmd_commit(dev_priv, submit_size); |
| 1206 | 1209 | ||
| 1207 | if (res->backup->dirty && res->backup_dirty) { | 1210 | if (res->guest_memory_bo->dirty && res->guest_memory_dirty) { |
| 1208 | /* We've just made a full upload. Cear dirty regions. */ | 1211 | /* We've just made a full upload. Cear dirty regions. */ |
| 1209 | vmw_bo_dirty_clear_res(res); | 1212 | vmw_bo_dirty_clear_res(res); |
| 1210 | } | 1213 | } |
| 1211 | 1214 | ||
| 1212 | res->backup_dirty = false; | 1215 | res->guest_memory_dirty = false; |
| 1213 | 1216 | ||
| 1214 | return 0; | 1217 | return 0; |
| 1215 | } | 1218 | } |
| @@ -1505,11 +1508,11 @@ vmw_gb_surface_define_internal(struct drm_device *dev, · 289 unmodified lines | |||
| 1505 | 1508 | ||
| 1506 | if (req->base.buffer_handle != SVGA3D_INVALID_ID) { | 1509 | if (req->base.buffer_handle != SVGA3D_INVALID_ID) { |
| 1507 | ret = vmw_user_bo_lookup(file_priv, req->base.buffer_handle, | 1510 | ret = vmw_user_bo_lookup(file_priv, req->base.buffer_handle, |
| 1508 | &res->backup); | 1511 | &res->guest_memory_bo); |
| 1509 | if (ret == 0) { | 1512 | if (ret == 0) { |
| 1510 | if (res->backup->base.base.size < res->backup_size) { | 1513 | if (res->guest_memory_bo->tbo.base.size < res->guest_memory_size) { |
| 1511 | VMW_DEBUG_USER("Surface backup buffer too small.\n"); | 1514 | VMW_DEBUG_USER("Surface backup buffer too small.\n"); |
| 1512 | vmw_bo_unreference(&res->backup); | 1515 | vmw_bo_unreference(&res->guest_memory_bo); |
| 1513 | ret = -EINVAL; | 1516 | ret = -EINVAL; |
| 1514 | goto out_unlock; | 1517 | goto out_unlock; |
| 1515 | } else { | 1518 | } else { |
| @@ -1520,11 +1523,11 @@ vmw_gb_surface_define_internal(struct drm_device *dev, · 4 unmodified lines | |||
| 1520 | (drm_vmw_surface_flag_create_buffer | | 1523 | (drm_vmw_surface_flag_create_buffer | |
| 1521 | drm_vmw_surface_flag_coherent)) { | 1524 | drm_vmw_surface_flag_coherent)) { |
| 1522 | ret = vmw_gem_object_create_with_handle(dev_priv, file_priv, | 1525 | ret = vmw_gem_object_create_with_handle(dev_priv, file_priv, |
| 1523 | res->backup_size, | 1526 | res->guest_memory_size, |
| 1524 | &backup_handle, | 1527 | &backup_handle, |
| 1525 | &res->backup); | 1528 | &res->guest_memory_bo); |
| 1526 | if (ret == 0) | 1529 | if (ret == 0) |
| 1527 | vmw_bo_reference(res->backup); | 1530 | vmw_bo_reference(res->guest_memory_bo); |
| 1528 | } | 1531 | } |
| 1529 | 1532 | ||
| 1530 | if (unlikely(ret != 0)) { | 1533 | if (unlikely(ret != 0)) { |
| @@ -1533,9 +1536,9 @@ vmw_gb_surface_define_internal(struct drm_device *dev, · 2 unmodified lines | |||
| 1533 | } | 1536 | } |
| 1534 | 1537 | ||
| 1535 | if (req->base.drm_surface_flags & drm_vmw_surface_flag_coherent) { | 1538 | if (req->base.drm_surface_flags & drm_vmw_surface_flag_coherent) { |
| 1536 | struct vmw_buffer_object *backup = res->backup; | 1539 | struct vmw_bo *backup = res->guest_memory_bo; |
| 1537 | 1540 | ||
| 1538 | ttm_bo_reserve(&backup->base, false, false, NULL); | 1541 | ttm_bo_reserve(&backup->tbo, false, false, NULL); |
| 1539 | if (!res->func->dirty_alloc) | 1542 | if (!res->func->dirty_alloc) |
| 1540 | ret = -EINVAL; | 1543 | ret = -EINVAL; |
| 1541 | if (!ret) | 1544 | if (!ret) |
| @@ -1544,7 +1547,7 @@ vmw_gb_surface_define_internal(struct drm_device *dev, · 2 unmodified lines | |||
| 1544 | res->coherent = true; | 1547 | res->coherent = true; |
| 1545 | ret = res->func->dirty_alloc(res); | 1548 | ret = res->func->dirty_alloc(res); |
| 1546 | } | 1549 | } |
| 1547 | ttm_bo_unreserve(&backup->base); | 1550 | ttm_bo_unreserve(&backup->tbo); |
| 1548 | if (ret) { | 1551 | if (ret) { |
| 1549 | vmw_resource_unreference(&res); | 1552 | vmw_resource_unreference(&res); |
| 1550 | goto out_unlock; | 1553 | goto out_unlock; |
| @@ -1553,7 +1556,7 @@ vmw_gb_surface_define_internal(struct drm_device *dev, · 2 unmodified lines | |||
| 1553 | } | 1556 | } |
| 1554 | 1557 | ||
| 1555 | tmp = vmw_resource_reference(res); | 1558 | tmp = vmw_resource_reference(res); |
| 1556 | ret = ttm_prime_object_init(tfile, res->backup_size, &user_srf->prime, | 1559 | ret = ttm_prime_object_init(tfile, res->guest_memory_size, &user_srf->prime, |
| 1557 | req->base.drm_surface_flags & | 1560 | req->base.drm_surface_flags & |
| 1558 | drm_vmw_surface_flag_shareable, | 1561 | drm_vmw_surface_flag_shareable, |
| 1559 | VMW_RES_SURFACE, | 1562 | VMW_RES_SURFACE, |
| @@ -1566,11 +1569,11 @@ vmw_gb_surface_define_internal(struct drm_device *dev, · 6 unmodified lines | |||
| 1566 | } | 1569 | } |
| 1567 | 1570 | ||
| 1568 | rep->handle = user_srf->prime.base.handle; | 1571 | rep->handle = user_srf->prime.base.handle; |
| 1569 | rep->backup_size = res->backup_size; | 1572 | rep->backup_size = res->guest_memory_size; |
| 1570 | if (res->backup) { | 1573 | if (res->guest_memory_bo) { |
| 1571 | rep->buffer_map_handle = | 1574 | rep->buffer_map_handle = |
| 1572 | drm_vma_node_offset_addr(&res->backup->base.base.vma_node); | 1575 | drm_vma_node_offset_addr(&res->guest_memory_bo->tbo.base.vma_node); |
| 1573 | rep->buffer_size = res->backup->base.base.size; | 1576 | rep->buffer_size = res->guest_memory_bo->tbo.base.size; |
| 1574 | rep->buffer_handle = backup_handle; | 1577 | rep->buffer_handle = backup_handle; |
| 1575 | } else { | 1578 | } else { |
| 1576 | rep->buffer_map_handle = 0; | 1579 | rep->buffer_map_handle = 0; |
| @@ -1613,14 +1616,14 @@ vmw_gb_surface_reference_internal(struct drm_device *dev, · 36 unmodified lines | |||
| 1613 | 1616 | ||
| 1614 | user_srf = container_of(base, struct vmw_user_surface, prime.base); | 1617 | user_srf = container_of(base, struct vmw_user_surface, prime.base); |
| 1615 | srf = &user_srf->srf; | 1618 | srf = &user_srf->srf; |
| 1616 | if (!srf->res.backup) { | 1619 | if (!srf->res.guest_memory_bo) { |
| 1617 | DRM_ERROR("Shared GB surface is missing a backup buffer.\n"); | 1620 | DRM_ERROR("Shared GB surface is missing a backup buffer.\n"); |
| 1618 | goto out_bad_resource; | 1621 | goto out_bad_resource; |
| 1619 | } | 1622 | } |
| 1620 | metadata = &srf->metadata; | 1623 | metadata = &srf->metadata; |
| 1621 | 1624 | ||
| 1622 | mutex_lock(&dev_priv->cmdbuf_mutex); /* Protect res->backup */ | 1625 | mutex_lock(&dev_priv->cmdbuf_mutex); /* Protect res->backup */ |
| 1623 | ret = drm_gem_handle_create(file_priv, &srf->res.backup->base.base, | 1626 | ret = drm_gem_handle_create(file_priv, &srf->res.guest_memory_bo->tbo.base, |
| 1624 | &backup_handle); | 1627 | &backup_handle); |
| 1625 | mutex_unlock(&dev_priv->cmdbuf_mutex); | 1628 | mutex_unlock(&dev_priv->cmdbuf_mutex); |
| 1626 | if (ret != 0) { | 1629 | if (ret != 0) { |
| @@ -1639,11 +1642,11 @@ vmw_gb_surface_reference_internal(struct drm_device *dev, · 12 unmodified lines | |||
| 1639 | rep->creq.base.buffer_handle = backup_handle; | 1642 | rep->creq.base.buffer_handle = backup_handle; |
| 1640 | rep->creq.base.base_size = metadata->base_size; | 1643 | rep->creq.base.base_size = metadata->base_size; |
| 1641 | rep->crep.handle = user_srf->prime.base.handle; | 1644 | rep->crep.handle = user_srf->prime.base.handle; |
| 1642 | rep->crep.backup_size = srf->res.backup_size; | 1645 | rep->crep.backup_size = srf->res.guest_memory_size; |
| 1643 | rep->crep.buffer_handle = backup_handle; | 1646 | rep->crep.buffer_handle = backup_handle; |
| 1644 | rep->crep.buffer_map_handle = | 1647 | rep->crep.buffer_map_handle = |
| 1645 | drm_vma_node_offset_addr(&srf->res.backup->base.base.vma_node); | 1648 | drm_vma_node_offset_addr(&srf->res.guest_memory_bo->tbo.base.vma_node); |
| 1646 | rep->crep.buffer_size = srf->res.backup->base.base.size; | 1649 | rep->crep.buffer_size = srf->res.guest_memory_bo->tbo.base.size; |
| 1647 | 1650 | ||
| 1648 | rep->creq.version = drm_vmw_gb_surface_v1; | 1651 | rep->creq.version = drm_vmw_gb_surface_v1; |
| 1649 | rep->creq.svga3d_flags_upper_32_bits = | 1652 | rep->creq.svga3d_flags_upper_32_bits = |
| @@ -1742,12 +1745,12 @@ static void vmw_surface_tex_dirty_range_add(struct vmw_resource *res, · 92 unmodified lines | |||
| 1742 | { | 1745 | { |
| 1743 | struct vmw_surface_dirty *dirty = | 1746 | struct vmw_surface_dirty *dirty = |
| 1744 | (struct vmw_surface_dirty *) res->dirty; | 1747 | (struct vmw_surface_dirty *) res->dirty; |
| 1745 | size_t backup_end = res->backup_offset + res->backup_size; | 1748 | size_t backup_end = res->guest_memory_offset + res->guest_memory_size; |
| 1746 | struct vmw_surface_loc loc1, loc2; | 1749 | struct vmw_surface_loc loc1, loc2; |
| 1747 | const struct vmw_surface_cache *cache; | 1750 | const struct vmw_surface_cache *cache; |
| 1748 | 1751 | ||
| 1749 | start = max_t(size_t, start, res->backup_offset) - res->backup_offset; | 1752 | start = max_t(size_t, start, res->guest_memory_offset) - res->guest_memory_offset; |
| 1750 | end = min(end, backup_end) - res->backup_offset; | 1753 | end = min(end, backup_end) - res->guest_memory_offset; |
| 1751 | cache = &dirty->cache; | 1754 | cache = &dirty->cache; |
| 1752 | vmw_surface_get_loc(cache, &loc1, start); | 1755 | vmw_surface_get_loc(cache, &loc1, start); |
| 1753 | vmw_surface_get_loc(cache, &loc2, end - 1); | 1756 | vmw_surface_get_loc(cache, &loc2, end - 1); |
| @@ -1794,13 +1797,13 @@ static void vmw_surface_buf_dirty_range_add(struct vmw_resource *res, · 40 unmodified lines | |||
| 1794 | struct vmw_surface_dirty *dirty = | 1797 | struct vmw_surface_dirty *dirty = |
| 1795 | (struct vmw_surface_dirty *) res->dirty; | 1798 | (struct vmw_surface_dirty *) res->dirty; |
| 1796 | const struct vmw_surface_cache *cache = &dirty->cache; | 1799 | const struct vmw_surface_cache *cache = &dirty->cache; |
| 1797 | size_t backup_end = res->backup_offset + cache->mip_chain_bytes; | 1800 | size_t backup_end = res->guest_memory_offset + cache->mip_chain_bytes; |
| 1798 | SVGA3dBox *box = &dirty->boxes[0]; | 1801 | SVGA3dBox *box = &dirty->boxes[0]; |
| 1799 | u32 box_c2; | 1802 | u32 box_c2; |
| 1800 | 1803 | ||
| 1801 | box->h = box->d = 1; | 1804 | box->h = box->d = 1; |
| 1802 | start = max_t(size_t, start, res->backup_offset) - res->backup_offset; | 1805 | start = max_t(size_t, start, res->guest_memory_offset) - res->guest_memory_offset; |
| 1803 | end = min(end, backup_end) - res->backup_offset; | 1806 | end = min(end, backup_end) - res->guest_memory_offset; |
| 1804 | box_c2 = box->x + box->w; | 1807 | box_c2 = box->x + box->w; |
| 1805 | if (box->w == 0 || box->x > start) | 1808 | if (box->w == 0 || box->x > start) |
| 1806 | box->x = start; | 1809 | box->x = start; |
| @@ -1816,8 +1819,8 @@ static void vmw_surface_dirty_range_add(struct vmw_resource *res, size_t start, · 9 unmodified lines | |||
| 1816 | { | 1819 | { |
| 1817 | struct vmw_surface *srf = vmw_res_to_srf(res); | 1820 | struct vmw_surface *srf = vmw_res_to_srf(res); |
| 1818 | 1821 | ||
| 1819 | if (WARN_ON(end <= res->backup_offset || | 1822 | if (WARN_ON(end <= res->guest_memory_offset || |
| 1820 | start >= res->backup_offset + res->backup_size)) | 1823 | start >= res->guest_memory_offset + res->guest_memory_size)) |
| 1821 | return; | 1824 | return; |
| 1822 | 1825 | ||
| 1823 | if (srf->metadata.format == SVGA3D_BUFFER) | 1826 | if (srf->metadata.format == SVGA3D_BUFFER) |
| @@ -2074,7 +2077,7 @@ int vmw_gb_surface_define(struct vmw_private *dev_priv, · 250 unmodified lines | |||
| 2074 | if (metadata->flags & SVGA3D_SURFACE_MULTISAMPLE) | 2077 | if (metadata->flags & SVGA3D_SURFACE_MULTISAMPLE) |
| 2075 | sample_count = metadata->multisample_count; | 2078 | sample_count = metadata->multisample_count; |
| 2076 | 2079 | ||
| 2077 | srf->res.backup_size = | 2080 | srf->res.guest_memory_size = |
| 2078 | vmw_surface_get_serialized_size_extended( | 2081 | vmw_surface_get_serialized_size_extended( |
| 2079 | metadata->format, | 2082 | metadata->format, |
| 2080 | metadata->base_size, | 2083 | metadata->base_size, |
| @@ -2083,7 +2086,7 @@ int vmw_gb_surface_define(struct vmw_private *dev_priv, · 2 unmodified lines | |||
| 2083 | sample_count); | 2086 | sample_count); |
| 2084 | 2087 | ||
| 2085 | if (metadata->flags & SVGA3D_SURFACE_BIND_STREAM_OUTPUT) | 2088 | if (metadata->flags & SVGA3D_SURFACE_BIND_STREAM_OUTPUT) |
| 2086 | srf->res.backup_size += sizeof(SVGA3dDXSOState); | 2089 | srf->res.guest_memory_size += sizeof(SVGA3dDXSOState); |
| 2087 | 2090 | ||
| 2088 | /* | 2091 | /* |
| 2089 | * Don't set SVGA3D_SURFACE_SCREENTARGET flag for a scanout surface with | 2092 | * Don't set SVGA3D_SURFACE_SCREENTARGET flag for a scanout surface with |
| @@ -1,7 +1,7 @@ | |||
| 1 | // SPDX-License-Identifier: GPL-2.0 OR MIT | 1 | // SPDX-License-Identifier: GPL-2.0 OR MIT |
| 2 | /************************************************************************** | 2 | /************************************************************************** |
| 3 | * | 3 | * |
| 4 | * Copyright 2009-2015 VMware, Inc., Palo Alto, CA., USA | 4 | * Copyright 2009-2023 VMware, Inc., Palo Alto, CA., USA |
| 5 | * | 5 | * |
| 6 | * Permission is hereby granted, free of charge, to any person obtaining a | 6 | * Permission is hereby granted, free of charge, to any person obtaining a |
| 7 | * copy of this software and associated documentation files (the | 7 | * copy of this software and associated documentation files (the |
| @@ -25,6 +25,7 @@ · 17 unmodified lines | |||
| 25 | * | 25 | * |
| 26 | **************************************************************************/ | 26 | **************************************************************************/ |
| 27 | 27 | ||
| 28 | #include "vmwgfx_bo.h" | ||
| 28 | #include "vmwgfx_drv.h" | 29 | #include "vmwgfx_drv.h" |
| 29 | #include <drm/ttm/ttm_placement.h> | 30 | #include <drm/ttm/ttm_placement.h> |
| 30 | 31 | ||
| @@ -49,13 +50,6 @@ static const struct ttm_place gmr_placement_flags = { · 18 unmodified lines | |||
| 49 | .flags = 0 | 50 | .flags = 0 |
| 50 | }; | 51 | }; |
| 51 | 52 | ||
| 52 | static const struct ttm_place mob_placement_flags = { | ||
| 53 | .fpfn = 0, | ||
| 54 | .lpfn = 0, | ||
| 55 | .mem_type = VMW_PL_MOB, | ||
| 56 | .flags = 0 | ||
| 57 | }; | ||
| 58 | |||
| 59 | struct ttm_placement vmw_vram_placement = { | 53 | struct ttm_placement vmw_vram_placement = { |
| 60 | .num_placement = 1, | 54 | .num_placement = 1, |
| 61 | .placement = &vram_placement_flags, | 55 | .placement = &vram_placement_flags, |
| @@ -77,27 +71,6 @@ static const struct ttm_place vram_gmr_placement_flags[] = { · 15 unmodified lines | |||
| 77 | } | 71 | } |
| 78 | }; | 72 | }; |
| 79 | 73 | ||
| 80 | static const struct ttm_place gmr_vram_placement_flags[] = { | ||
| 81 | { | ||
| 82 | .fpfn = 0, | ||
| 83 | .lpfn = 0, | ||
| 84 | .mem_type = VMW_PL_GMR, | ||
| 85 | .flags = 0 | ||
| 86 | }, { | ||
| 87 | .fpfn = 0, | ||
| 88 | .lpfn = 0, | ||
| 89 | .mem_type = TTM_PL_VRAM, | ||
| 90 | .flags = 0 | ||
| 91 | } | ||
| 92 | }; | ||
| 93 | |||
| 94 | static const struct ttm_place vmw_sys_placement_flags = { | ||
| 95 | .fpfn = 0, | ||
| 96 | .lpfn = 0, | ||
| 97 | .mem_type = VMW_PL_SYSTEM, | ||
| 98 | .flags = 0 | ||
| 99 | }; | ||
| 100 | |||
| 101 | struct ttm_placement vmw_vram_gmr_placement = { | 74 | struct ttm_placement vmw_vram_gmr_placement = { |
| 102 | .num_placement = 2, | 75 | .num_placement = 2, |
| 103 | .placement = vram_gmr_placement_flags, | 76 | .placement = vram_gmr_placement_flags, |
| @@ -105,13 +78,6 @@ struct ttm_placement vmw_vram_gmr_placement = { · 1 unmodified line | |||
| 105 | .busy_placement = &gmr_placement_flags | 78 | .busy_placement = &gmr_placement_flags |
| 106 | }; | 79 | }; |
| 107 | 80 | ||
| 108 | struct ttm_placement vmw_vram_sys_placement = { | ||
| 109 | .num_placement = 1, | ||
| 110 | .placement = &vram_placement_flags, | ||
| 111 | .num_busy_placement = 1, | ||
| 112 | .busy_placement = &sys_placement_flags | ||
| 113 | }; | ||
| 114 | |||
| 115 | struct ttm_placement vmw_sys_placement = { | 81 | struct ttm_placement vmw_sys_placement = { |
| 116 | .num_placement = 1, | 82 | .num_placement = 1, |
| 117 | .placement = &sys_placement_flags, | 83 | .placement = &sys_placement_flags, |
| @@ -119,53 +85,6 @@ struct ttm_placement vmw_sys_placement = { · 1 unmodified line | |||
| 119 | .busy_placement = &sys_placement_flags | 85 | .busy_placement = &sys_placement_flags |
| 120 | }; | 86 | }; |
| 121 | 87 | ||
| 122 | struct ttm_placement vmw_pt_sys_placement = { | ||
| 123 | .num_placement = 1, | ||
| 124 | .placement = &vmw_sys_placement_flags, | ||
| 125 | .num_busy_placement = 1, | ||
| 126 | .busy_placement = &vmw_sys_placement_flags | ||
| 127 | }; | ||
| 128 | |||
| 129 | static const struct ttm_place nonfixed_placement_flags[] = { | ||
| 130 | { | ||
| 131 | .fpfn = 0, | ||
| 132 | .lpfn = 0, | ||
| 133 | .mem_type = TTM_PL_SYSTEM, | ||
| 134 | .flags = 0 | ||
| 135 | }, { | ||
| 136 | .fpfn = 0, | ||
| 137 | .lpfn = 0, | ||
| 138 | .mem_type = VMW_PL_GMR, | ||
| 139 | .flags = 0 | ||
| 140 | }, { | ||
| 141 | .fpfn = 0, | ||
| 142 | .lpfn = 0, | ||
| 143 | .mem_type = VMW_PL_MOB, | ||
| 144 | .flags = 0 | ||
| 145 | } | ||
| 146 | }; | ||
| 147 | |||
| 148 | struct ttm_placement vmw_srf_placement = { | ||
| 149 | .num_placement = 1, | ||
| 150 | .num_busy_placement = 2, | ||
| 151 | .placement = &gmr_placement_flags, | ||
| 152 | .busy_placement = gmr_vram_placement_flags | ||
| 153 | }; | ||
| 154 | |||
| 155 | struct ttm_placement vmw_mob_placement = { | ||
| 156 | .num_placement = 1, | ||
| 157 | .num_busy_placement = 1, | ||
| 158 | .placement = &mob_placement_flags, | ||
| 159 | .busy_placement = &mob_placement_flags | ||
| 160 | }; | ||
| 161 | |||
| 162 | struct ttm_placement vmw_nonfixed_placement = { | ||
| 163 | .num_placement = 3, | ||
| 164 | .placement = nonfixed_placement_flags, | ||
| 165 | .num_busy_placement = 1, | ||
| 166 | .busy_placement = &sys_placement_flags | ||
| 167 | }; | ||
| 168 | |||
| 169 | const size_t vmw_tt_size = sizeof(struct vmw_ttm_tt); | 88 | const size_t vmw_tt_size = sizeof(struct vmw_ttm_tt); |
| 170 | 89 | ||
| 171 | /** | 90 | /** |
| @@ -508,7 +427,7 @@ static struct ttm_tt *vmw_ttm_tt_create(struct ttm_buffer_object *bo, · 336 unmodified lines | |||
| 508 | if (!vmw_be) | 427 | if (!vmw_be) |
| 509 | return NULL; | 428 | return NULL; |
| 510 | 429 | ||
| 511 | vmw_be->dev_priv = container_of(bo->bdev, struct vmw_private, bdev); | 430 | vmw_be->dev_priv = vmw_priv_from_ttm(bo->bdev); |
| 512 | vmw_be->mob = NULL; | 431 | vmw_be->mob = NULL; |
| 513 | 432 | ||
| 514 | if (vmw_be->dev_priv->map_mode == vmw_dma_alloc_coherent) | 433 | if (vmw_be->dev_priv->map_mode == vmw_dma_alloc_coherent) |
| @@ -534,7 +453,7 @@ static void vmw_evict_flags(struct ttm_buffer_object *bo, · 19 unmodified lines | |||
| 534 | 453 | ||
| 535 | static int vmw_ttm_io_mem_reserve(struct ttm_device *bdev, struct ttm_resource *mem) | 454 | static int vmw_ttm_io_mem_reserve(struct ttm_device *bdev, struct ttm_resource *mem) |
| 536 | { | 455 | { |
| 537 | struct vmw_private *dev_priv = container_of(bdev, struct vmw_private, bdev); | 456 | struct vmw_private *dev_priv = vmw_priv_from_ttm(bdev); |
| 538 | 457 | ||
| 539 | switch (mem->mem_type) { | 458 | switch (mem->mem_type) { |
| 540 | case TTM_PL_SYSTEM: | 459 | case TTM_PL_SYSTEM: |
| @@ -596,9 +515,13 @@ static int vmw_move(struct ttm_buffer_object *bo, · 55 unmodified lines | |||
| 596 | struct ttm_resource *new_mem, | 515 | struct ttm_resource *new_mem, |
| 597 | struct ttm_place *hop) | 516 | struct ttm_place *hop) |
| 598 | { | 517 | { |
| 599 | struct ttm_resource_manager *old_man = ttm_manager_type(bo->bdev, bo->resource->mem_type); | 518 | struct ttm_resource_manager *new_man; |
| 600 | struct ttm_resource_manager *new_man = ttm_manager_type(bo->bdev, new_mem->mem_type); | 519 | struct ttm_resource_manager *old_man = NULL; |
| 601 | int ret; | 520 | int ret = 0; |
| 521 | |||
| 522 | new_man = ttm_manager_type(bo->bdev, new_mem->mem_type); | ||
| 523 | if (bo->resource) | ||
| 524 | old_man = ttm_manager_type(bo->bdev, bo->resource->mem_type); | ||
| 602 | 525 | ||
| 603 | if (new_man->use_tt && !vmw_memtype_is_system(new_mem->mem_type)) { | 526 | if (new_man->use_tt && !vmw_memtype_is_system(new_mem->mem_type)) { |
| 604 | ret = vmw_ttm_bind(bo->bdev, bo->ttm, new_mem); | 527 | ret = vmw_ttm_bind(bo->bdev, bo->ttm, new_mem); |
| @@ -606,9 +529,15 @@ static int vmw_move(struct ttm_buffer_object *bo, · 1 unmodified line | |||
| 606 | return ret; | 529 | return ret; |
| 607 | } | 530 | } |
| 608 | 531 | ||
| 532 | if (!bo->resource || (bo->resource->mem_type == TTM_PL_SYSTEM && | ||
| 533 | bo->ttm == NULL)) { | ||
| 534 | ttm_bo_move_null(bo, new_mem); | ||
| 535 | return 0; | ||
| 536 | } | ||
| 537 | |||
| 609 | vmw_move_notify(bo, bo->resource, new_mem); | 538 | vmw_move_notify(bo, bo->resource, new_mem); |
| 610 | 539 | ||
| 611 | if (old_man->use_tt && new_man->use_tt) { | 540 | if (old_man && old_man->use_tt && new_man->use_tt) { |
| 612 | if (vmw_memtype_is_system(bo->resource->mem_type)) { | 541 | if (vmw_memtype_is_system(bo->resource->mem_type)) { |
| 613 | ttm_bo_move_null(bo, new_mem); | 542 | ttm_bo_move_null(bo, new_mem); |
| 614 | return 0; | 543 | return 0; |
| @@ -645,34 +574,39 @@ struct ttm_device_funcs vmw_bo_driver = { · 30 unmodified lines | |||
| 645 | }; | 574 | }; |
| 646 | 575 | ||
| 647 | int vmw_bo_create_and_populate(struct vmw_private *dev_priv, | 576 | int vmw_bo_create_and_populate(struct vmw_private *dev_priv, |
| 648 | unsigned long bo_size, | 577 | size_t bo_size, u32 domain, |
| 649 | struct ttm_buffer_object **bo_p) | 578 | struct vmw_bo **bo_p) |
| 650 | { | 579 | { |
| 651 | struct ttm_operation_ctx ctx = { | 580 | struct ttm_operation_ctx ctx = { |
| 652 | .interruptible = false, | 581 | .interruptible = false, |
| 653 | .no_wait_gpu = false | 582 | .no_wait_gpu = false |
| 654 | }; | 583 | }; |
| 655 | struct ttm_buffer_object *bo; | 584 | struct vmw_bo *vbo; |
| 656 | int ret; | 585 | int ret; |
| 586 | struct vmw_bo_params bo_params = { | ||
| 587 | .domain = domain, | ||
| 588 | .busy_domain = domain, | ||
| 589 | .bo_type = ttm_bo_type_kernel, | ||
| 590 | .size = bo_size, | ||
| 591 | .pin = true | ||
| 592 | }; | ||
| 657 | 593 | ||
| 658 | ret = vmw_bo_create_kernel(dev_priv, bo_size, | 594 | ret = vmw_bo_create(dev_priv, &bo_params, &vbo); |
| 659 | &vmw_pt_sys_placement, | ||
| 660 | &bo); | ||
| 661 | if (unlikely(ret != 0)) | 595 | if (unlikely(ret != 0)) |
| 662 | return ret; | 596 | return ret; |
| 663 | 597 | ||
| 664 | ret = ttm_bo_reserve(bo, false, true, NULL); | 598 | ret = ttm_bo_reserve(&vbo->tbo, false, true, NULL); |
| 665 | BUG_ON(ret != 0); | 599 | BUG_ON(ret != 0); |
| 666 | ret = vmw_ttm_populate(bo->bdev, bo->ttm, &ctx); | 600 | ret = vmw_ttm_populate(vbo->tbo.bdev, vbo->tbo.ttm, &ctx); |
| 667 | if (likely(ret == 0)) { | 601 | if (likely(ret == 0)) { |
| 668 | struct vmw_ttm_tt *vmw_tt = | 602 | struct vmw_ttm_tt *vmw_tt = |
| 669 | container_of(bo->ttm, struct vmw_ttm_tt, dma_ttm); | 603 | container_of(vbo->tbo.ttm, struct vmw_ttm_tt, dma_ttm); |
| 670 | ret = vmw_ttm_map_dma(vmw_tt); | 604 | ret = vmw_ttm_map_dma(vmw_tt); |
| 671 | } | 605 | } |
| 672 | 606 | ||
| 673 | ttm_bo_unreserve(bo); | 607 | ttm_bo_unreserve(&vbo->tbo); |
| 674 | 608 | ||
| 675 | if (likely(ret == 0)) | 609 | if (likely(ret == 0)) |
| 676 | *bo_p = bo; | 610 | *bo_p = vbo; |
| 677 | return ret; | 611 | return ret; |
| 678 | } | 612 | } |
| @@ -25,6 +25,7 @@ · 24 unmodified lines | |||
| 25 | * | 25 | * |
| 26 | **************************************************************************/ | 26 | **************************************************************************/ |
| 27 | 27 | ||
| 28 | #include "vmwgfx_bo.h" | ||
| 28 | #include "vmwgfx_drv.h" | 29 | #include "vmwgfx_drv.h" |
| 29 | #include "vmwgfx_resource_priv.h" | 30 | #include "vmwgfx_resource_priv.h" |
| 30 | 31 | ||
| @@ -80,10 +81,11 @@ static void vmw_stream_set_arg_handle(void *data, u32 handle) · 49 unmodified lines | |||
| 80 | static const struct vmw_simple_resource_func va_stream_func = { | 81 | static const struct vmw_simple_resource_func va_stream_func = { |
| 81 | .res_func = { | 82 | .res_func = { |
| 82 | .res_type = vmw_res_stream, | 83 | .res_type = vmw_res_stream, |
| 83 | .needs_backup = false, | 84 | .needs_guest_memory = false, |
| 84 | .may_evict = false, | 85 | .may_evict = false, |
| 85 | .type_name = "overlay stream", | 86 | .type_name = "overlay stream", |
| 86 | .backup_placement = NULL, | 87 | .domain = VMW_BO_DOMAIN_SYS, |
| 88 | .busy_domain = VMW_BO_DOMAIN_SYS, | ||
| 87 | .create = NULL, | 89 | .create = NULL, |
| 88 | .destroy = NULL, | 90 | .destroy = NULL, |
| 89 | .bind = NULL, | 91 | .bind = NULL, |
| @@ -1,7 +1,7 @@ | |||
| 1 | // SPDX-License-Identifier: GPL-2.0 OR MIT | 1 | // SPDX-License-Identifier: GPL-2.0 OR MIT |
| 2 | /************************************************************************** | 2 | /************************************************************************** |
| 3 | * | 3 | * |
| 4 | * Copyright © 2018 - 2022 VMware, Inc., Palo Alto, CA., USA | 4 | * Copyright © 2018 - 2023 VMware, Inc., Palo Alto, CA., USA |
| 5 | * All Rights Reserved. | 5 | * All Rights Reserved. |
| 6 | * | 6 | * |
| 7 | * Permission is hereby granted, free of charge, to any person obtaining a | 7 | * Permission is hereby granted, free of charge, to any person obtaining a |
| @@ -25,9 +25,12 @@ · 17 unmodified lines | |||
| 25 | * USE OR OTHER DEALINGS IN THE SOFTWARE. | 25 | * USE OR OTHER DEALINGS IN THE SOFTWARE. |
| 26 | * | 26 | * |
| 27 | **************************************************************************/ | 27 | **************************************************************************/ |
| 28 | #include <linux/slab.h> | 28 | #include "vmwgfx_bo.h" |
| 29 | #include "vmwgfx_validation.h" | ||
| 30 | #include "vmwgfx_drv.h" | 29 | #include "vmwgfx_drv.h" |
| 30 | #include "vmwgfx_resource_priv.h" | ||
| 31 | #include "vmwgfx_validation.h" | ||
| 32 | |||
| 33 | #include <linux/slab.h> | ||
| 31 | 34 | ||
| 32 | 35 | ||
| 33 | #define VMWGFX_VALIDATION_MEM_GRAN (16*PAGE_SIZE) | 36 | #define VMWGFX_VALIDATION_MEM_GRAN (16*PAGE_SIZE) |
| @@ -38,8 +41,6 @@ · 4 unmodified lines | |||
| 38 | * @hash: A hash entry used for the duplicate detection hash table. | 41 | * @hash: A hash entry used for the duplicate detection hash table. |
| 39 | * @coherent_count: If switching backup buffers, number of new coherent | 42 | * @coherent_count: If switching backup buffers, number of new coherent |
| 40 | * resources that will have this buffer as a backup buffer. | 43 | * resources that will have this buffer as a backup buffer. |
| 41 | * @as_mob: Validate as mob. | ||
| 42 | * @cpu_blit: Validate for cpu blit access. | ||
| 43 | * | 44 | * |
| 44 | * Bit fields are used since these structures are allocated and freed in | 45 | * Bit fields are used since these structures are allocated and freed in |
| 45 | * large numbers and space conservation is desired. | 46 | * large numbers and space conservation is desired. |
| @@ -48,21 +49,19 @@ struct vmw_validation_bo_node { · 2 unmodified lines | |||
| 48 | struct ttm_validate_buffer base; | 49 | struct ttm_validate_buffer base; |
| 49 | struct vmwgfx_hash_item hash; | 50 | struct vmwgfx_hash_item hash; |
| 50 | unsigned int coherent_count; | 51 | unsigned int coherent_count; |
| 51 | u32 as_mob : 1; | ||
| 52 | u32 cpu_blit : 1; | ||
| 53 | }; | 52 | }; |
| 54 | /** | 53 | /** |
| 55 | * struct vmw_validation_res_node - Resource validation metadata. | 54 | * struct vmw_validation_res_node - Resource validation metadata. |
| 56 | * @head: List head for the resource validation list. | 55 | * @head: List head for the resource validation list. |
| 57 | * @hash: A hash entry used for the duplicate detection hash table. | 56 | * @hash: A hash entry used for the duplicate detection hash table. |
| 58 | * @res: Reference counted resource pointer. | 57 | * @res: Reference counted resource pointer. |
| 59 | * @new_backup: Non ref-counted pointer to new backup buffer to be assigned | 58 | * @new_guest_memory_bo: Non ref-counted pointer to new guest memory buffer |
| 60 | * to a resource. | 59 | * to be assigned to a resource. |
| 61 | * @new_backup_offset: Offset into the new backup mob for resources that can | 60 | * @new_guest_memory_offset: Offset into the new backup mob for resources |
| 62 | * share MOBs. | 61 | * that can share MOBs. |
| 63 | * @no_buffer_needed: Kernel does not need to allocate a MOB during validation, | 62 | * @no_buffer_needed: Kernel does not need to allocate a MOB during validation, |
| 64 | * the command stream provides a mob bind operation. | 63 | * the command stream provides a mob bind operation. |
| 65 | * @switching_backup: The validation process is switching backup MOB. | 64 | * @switching_guest_memory_bo: The validation process is switching backup MOB. |
| 66 | * @first_usage: True iff the resource has been seen only once in the current | 65 | * @first_usage: True iff the resource has been seen only once in the current |
| 67 | * validation batch. | 66 | * validation batch. |
| 68 | * @reserved: Whether the resource is currently reserved by this process. | 67 | * @reserved: Whether the resource is currently reserved by this process. |
| @@ -77,10 +76,10 @@ struct vmw_validation_res_node { · 8 unmodified lines | |||
| 77 | struct list_head head; | 76 | struct list_head head; |
| 78 | struct vmwgfx_hash_item hash; | 77 | struct vmwgfx_hash_item hash; |
| 79 | struct vmw_resource *res; | 78 | struct vmw_resource *res; |
| 80 | struct vmw_buffer_object *new_backup; | 79 | struct vmw_bo *new_guest_memory_bo; |
| 81 | unsigned long new_backup_offset; | 80 | unsigned long new_guest_memory_offset; |
| 82 | u32 no_buffer_needed : 1; | 81 | u32 no_buffer_needed : 1; |
| 83 | u32 switching_backup : 1; | 82 | u32 switching_guest_memory_bo : 1; |
| 84 | u32 first_usage : 1; | 83 | u32 first_usage : 1; |
| 85 | u32 reserved : 1; | 84 | u32 reserved : 1; |
| 86 | u32 dirty : 1; | 85 | u32 dirty : 1; |
| @@ -173,7 +172,7 @@ static void vmw_validation_mem_free(struct vmw_validation_context *ctx) · 86 unmodified lines | |||
| 173 | */ | 172 | */ |
| 174 | static struct vmw_validation_bo_node * | 173 | static struct vmw_validation_bo_node * |
| 175 | vmw_validation_find_bo_dup(struct vmw_validation_context *ctx, | 174 | vmw_validation_find_bo_dup(struct vmw_validation_context *ctx, |
| 176 | struct vmw_buffer_object *vbo) | 175 | struct vmw_bo *vbo) |
| 177 | { | 176 | { |
| 178 | struct vmw_validation_bo_node *bo_node = NULL; | 177 | struct vmw_validation_bo_node *bo_node = NULL; |
| 179 | 178 | ||
| @@ -194,7 +193,7 @@ vmw_validation_find_bo_dup(struct vmw_validation_context *ctx, · 14 unmodified lines | |||
| 194 | struct vmw_validation_bo_node *entry; | 193 | struct vmw_validation_bo_node *entry; |
| 195 | 194 | ||
| 196 | list_for_each_entry(entry, &ctx->bo_list, base.head) { | 195 | list_for_each_entry(entry, &ctx->bo_list, base.head) { |
| 197 | if (entry->base.bo == &vbo->base) { | 196 | if (entry->base.bo == &vbo->tbo) { |
| 198 | bo_node = entry; | 197 | bo_node = entry; |
| 199 | break; | 198 | break; |
| 200 | } | 199 | } |
| @@ -258,26 +257,16 @@ out: · 57 unmodified lines | |||
| 258 | * vmw_validation_add_bo - Add a buffer object to the validation context. | 257 | * vmw_validation_add_bo - Add a buffer object to the validation context. |
| 259 | * @ctx: The validation context. | 258 | * @ctx: The validation context. |
| 260 | * @vbo: The buffer object. | 259 | * @vbo: The buffer object. |
| 261 | * @as_mob: Validate as mob, otherwise suitable for GMR operations. | ||
| 262 | * @cpu_blit: Validate in a page-mappable location. | ||
| 263 | * | 260 | * |
| 264 | * Return: Zero on success, negative error code otherwise. | 261 | * Return: Zero on success, negative error code otherwise. |
| 265 | */ | 262 | */ |
| 266 | int vmw_validation_add_bo(struct vmw_validation_context *ctx, | 263 | int vmw_validation_add_bo(struct vmw_validation_context *ctx, |
| 267 | struct vmw_buffer_object *vbo, | 264 | struct vmw_bo *vbo) |
| 268 | bool as_mob, | ||
| 269 | bool cpu_blit) | ||
| 270 | { | 265 | { |
| 271 | struct vmw_validation_bo_node *bo_node; | 266 | struct vmw_validation_bo_node *bo_node; |
| 272 | 267 | ||
| 273 | bo_node = vmw_validation_find_bo_dup(ctx, vbo); | 268 | bo_node = vmw_validation_find_bo_dup(ctx, vbo); |
| 274 | if (bo_node) { | 269 | if (!bo_node) { |
| 275 | if (bo_node->as_mob != as_mob || | ||
| 276 | bo_node->cpu_blit != cpu_blit) { | ||
| 277 | DRM_ERROR("Inconsistent buffer usage.\n"); | ||
| 278 | return -EINVAL; | ||
| 279 | } | ||
| 280 | } else { | ||
| 281 | struct ttm_validate_buffer *val_buf; | 270 | struct ttm_validate_buffer *val_buf; |
| 282 | 271 | ||
| 283 | bo_node = vmw_validation_mem_alloc(ctx, sizeof(*bo_node)); | 272 | bo_node = vmw_validation_mem_alloc(ctx, sizeof(*bo_node)); |
| @@ -290,13 +279,11 @@ int vmw_validation_add_bo(struct vmw_validation_context *ctx, · 6 unmodified lines | |||
| 290 | bo_node->hash.key); | 279 | bo_node->hash.key); |
| 291 | } | 280 | } |
| 292 | val_buf = &bo_node->base; | 281 | val_buf = &bo_node->base; |
| 293 | val_buf->bo = ttm_bo_get_unless_zero(&vbo->base); | 282 | val_buf->bo = ttm_bo_get_unless_zero(&vbo->tbo); |
| 294 | if (!val_buf->bo) | 283 | if (!val_buf->bo) |
| 295 | return -ESRCH; | 284 | return -ESRCH; |
| 296 | val_buf->num_shared = 0; | 285 | val_buf->num_shared = 0; |
| 297 | list_add_tail(&val_buf->head, &ctx->bo_list); | 286 | list_add_tail(&val_buf->head, &ctx->bo_list); |
| 298 | bo_node->as_mob = as_mob; | ||
| 299 | bo_node->cpu_blit = cpu_blit; | ||
| 300 | } | 287 | } |
| 301 | 288 | ||
| 302 | return 0; | 289 | return 0; |
| @@ -406,23 +393,23 @@ void vmw_validation_res_set_dirty(struct vmw_validation_context *ctx, · 103 unmodified lines | |||
| 406 | * the resource. | 393 | * the resource. |
| 407 | * @vbo: The new backup buffer object MOB. This buffer object needs to have | 394 | * @vbo: The new backup buffer object MOB. This buffer object needs to have |
| 408 | * already been registered with the validation context. | 395 | * already been registered with the validation context. |
| 409 | * @backup_offset: Offset into the new backup MOB. | 396 | * @guest_memory_offset: Offset into the new backup MOB. |
| 410 | */ | 397 | */ |
| 411 | void vmw_validation_res_switch_backup(struct vmw_validation_context *ctx, | 398 | void vmw_validation_res_switch_backup(struct vmw_validation_context *ctx, |
| 412 | void *val_private, | 399 | void *val_private, |
| 413 | struct vmw_buffer_object *vbo, | 400 | struct vmw_bo *vbo, |
| 414 | unsigned long backup_offset) | 401 | unsigned long guest_memory_offset) |
| 415 | { | 402 | { |
| 416 | struct vmw_validation_res_node *val; | 403 | struct vmw_validation_res_node *val; |
| 417 | 404 | ||
| 418 | val = container_of(val_private, typeof(*val), private); | 405 | val = container_of(val_private, typeof(*val), private); |
| 419 | 406 | ||
| 420 | val->switching_backup = 1; | 407 | val->switching_guest_memory_bo = 1; |
| 421 | if (val->first_usage) | 408 | if (val->first_usage) |
| 422 | val->no_buffer_needed = 1; | 409 | val->no_buffer_needed = 1; |
| 423 | 410 | ||
| 424 | val->new_backup = vbo; | 411 | val->new_guest_memory_bo = vbo; |
| 425 | val->new_backup_offset = backup_offset; | 412 | val->new_guest_memory_offset = guest_memory_offset; |
| 426 | } | 413 | } |
| 427 | 414 | ||
| 428 | /** | 415 | /** |
| @@ -450,21 +437,22 @@ int vmw_validation_res_reserve(struct vmw_validation_context *ctx, · 21 unmodified lines | |||
| 450 | goto out_unreserve; | 437 | goto out_unreserve; |
| 451 | 438 | ||
| 452 | val->reserved = 1; | 439 | val->reserved = 1; |
| 453 | if (res->backup) { | 440 | if (res->guest_memory_bo) { |
| 454 | struct vmw_buffer_object *vbo = res->backup; | 441 | struct vmw_bo *vbo = res->guest_memory_bo; |
| 455 | 442 | ||
| 456 | ret = vmw_validation_add_bo | 443 | vmw_bo_placement_set(vbo, |
| 457 | (ctx, vbo, vmw_resource_needs_backup(res), | 444 | res->func->domain, |
| 458 | false); | 445 | res->func->busy_domain); |
| 446 | ret = vmw_validation_add_bo(ctx, vbo); | ||
| 459 | if (ret) | 447 | if (ret) |
| 460 | goto out_unreserve; | 448 | goto out_unreserve; |
| 461 | } | 449 | } |
| 462 | 450 | ||
| 463 | if (val->switching_backup && val->new_backup && | 451 | if (val->switching_guest_memory_bo && val->new_guest_memory_bo && |
| 464 | res->coherent) { | 452 | res->coherent) { |
| 465 | struct vmw_validation_bo_node *bo_node = | 453 | struct vmw_validation_bo_node *bo_node = |
| 466 | vmw_validation_find_bo_dup(ctx, | 454 | vmw_validation_find_bo_dup(ctx, |
| 467 | val->new_backup); | 455 | val->new_guest_memory_bo); |
| 468 | 456 | ||
| 469 | if (WARN_ON(!bo_node)) { | 457 | if (WARN_ON(!bo_node)) { |
| 470 | ret = -EINVAL; | 458 | ret = -EINVAL; |
| @@ -507,9 +495,9 @@ void vmw_validation_res_unreserve(struct vmw_validation_context *ctx, · 36 unmodified lines | |||
| 507 | vmw_resource_unreserve(val->res, | 495 | vmw_resource_unreserve(val->res, |
| 508 | val->dirty_set, | 496 | val->dirty_set, |
| 509 | val->dirty, | 497 | val->dirty, |
| 510 | val->switching_backup, | 498 | val->switching_guest_memory_bo, |
| 511 | val->new_backup, | 499 | val->new_guest_memory_bo, |
| 512 | val->new_backup_offset); | 500 | val->new_guest_memory_offset); |
| 513 | } | 501 | } |
| 514 | } | 502 | } |
| 515 | 503 | ||
| @@ -517,17 +505,14 @@ void vmw_validation_res_unreserve(struct vmw_validation_context *ctx, · 1 unmodified line | |||
| 517 | * vmw_validation_bo_validate_single - Validate a single buffer object. | 505 | * vmw_validation_bo_validate_single - Validate a single buffer object. |
| 518 | * @bo: The TTM buffer object base. | 506 | * @bo: The TTM buffer object base. |
| 519 | * @interruptible: Whether to perform waits interruptible if possible. | 507 | * @interruptible: Whether to perform waits interruptible if possible. |
| 520 | * @validate_as_mob: Whether to validate in MOB memory. | ||
| 521 | * | 508 | * |
| 522 | * Return: Zero on success, -ERESTARTSYS if interrupted. Negative error | 509 | * Return: Zero on success, -ERESTARTSYS if interrupted. Negative error |
| 523 | * code on failure. | 510 | * code on failure. |
| 524 | */ | 511 | */ |
| 525 | int vmw_validation_bo_validate_single(struct ttm_buffer_object *bo, | 512 | static int vmw_validation_bo_validate_single(struct ttm_buffer_object *bo, |
| 526 | bool interruptible, | 513 | bool interruptible) |
| 527 | bool validate_as_mob) | ||
| 528 | { | 514 | { |
| 529 | struct vmw_buffer_object *vbo = | 515 | struct vmw_bo *vbo = to_vmw_bo(&bo->base); |
| 530 | container_of(bo, struct vmw_buffer_object, base); | ||
| 531 | struct ttm_operation_ctx ctx = { | 516 | struct ttm_operation_ctx ctx = { |
| 532 | .interruptible = interruptible, | 517 | .interruptible = interruptible, |
| 533 | .no_wait_gpu = false | 518 | .no_wait_gpu = false |
| @@ -537,30 +522,20 @@ int vmw_validation_bo_validate_single(struct ttm_buffer_object *bo, · 3 unmodified lines | |||
| 537 | if (atomic_read(&vbo->cpu_writers)) | 522 | if (atomic_read(&vbo->cpu_writers)) |
| 538 | return -EBUSY; | 523 | return -EBUSY; |
| 539 | 524 | ||
| 540 | if (vbo->base.pin_count > 0) | 525 | if (vbo->tbo.pin_count > 0) |
| 541 | return 0; | 526 | return 0; |
| 542 | 527 | ||
| 543 | if (validate_as_mob) | 528 | ret = ttm_bo_validate(bo, &vbo->placement, &ctx); |
| 544 | return ttm_bo_validate(bo, &vmw_mob_placement, &ctx); | ||
| 545 | |||
| 546 | /** | ||
| 547 | * Put BO in VRAM if there is space, otherwise as a GMR. | ||
| 548 | * If there is no space in VRAM and GMR ids are all used up, | ||
| 549 | * start evicting GMRs to make room. If the DMA buffer can't be | ||
| 550 | * used as a GMR, this will return -ENOMEM. | ||
| 551 | */ | ||
| 552 | |||
| 553 | ret = ttm_bo_validate(bo, &vmw_vram_gmr_placement, &ctx); | ||
| 554 | if (ret == 0 || ret == -ERESTARTSYS) | 529 | if (ret == 0 || ret == -ERESTARTSYS) |
| 555 | return ret; | 530 | return ret; |
| 556 | 531 | ||
| 557 | /** | 532 | /* |
| 558 | * If that failed, try VRAM again, this time evicting | 533 | * If that failed, try again, this time evicting |
| 559 | * previous contents. | 534 | * previous contents. |
| 560 | */ | 535 | */ |
| 536 | ctx.allow_res_evict = true; | ||
| 561 | 537 | ||
| 562 | ret = ttm_bo_validate(bo, &vmw_vram_placement, &ctx); | 538 | return ttm_bo_validate(bo, &vbo->placement, &ctx); |
| 563 | return ret; | ||
| 564 | } | 539 | } |
| 565 | 540 | ||
| 566 | /** | 541 | /** |
| @@ -578,21 +553,10 @@ int vmw_validation_bo_validate(struct vmw_validation_context *ctx, bool intr) · 11 unmodified lines | |||
| 578 | int ret; | 553 | int ret; |
| 579 | 554 | ||
| 580 | list_for_each_entry(entry, &ctx->bo_list, base.head) { | 555 | list_for_each_entry(entry, &ctx->bo_list, base.head) { |
| 581 | struct vmw_buffer_object *vbo = | 556 | struct vmw_bo *vbo = to_vmw_bo(&entry->base.bo->base); |
| 582 | container_of(entry->base.bo, typeof(*vbo), base); | 557 | |
| 583 | 558 | ret = vmw_validation_bo_validate_single(entry->base.bo, intr); | |
| 584 | if (entry->cpu_blit) { | 559 | |
| 585 | struct ttm_operation_ctx ttm_ctx = { | ||
| 586 | .interruptible = intr, | ||
| 587 | .no_wait_gpu = false | ||
| 588 | }; | ||
| 589 | |||
| 590 | ret = ttm_bo_validate(entry->base.bo, | ||
| 591 | &vmw_nonfixed_placement, &ttm_ctx); | ||
| 592 | } else { | ||
| 593 | ret = vmw_validation_bo_validate_single | ||
| 594 | (entry->base.bo, intr, entry->as_mob); | ||
| 595 | } | ||
| 596 | if (ret) | 560 | if (ret) |
| 597 | return ret; | 561 | return ret; |
| 598 | 562 | ||
| @@ -639,7 +603,7 @@ int vmw_validation_res_validate(struct vmw_validation_context *ctx, bool intr) · 40 unmodified lines | |||
| 639 | 603 | ||
| 640 | list_for_each_entry(val, &ctx->resource_list, head) { | 604 | list_for_each_entry(val, &ctx->resource_list, head) { |
| 641 | struct vmw_resource *res = val->res; | 605 | struct vmw_resource *res = val->res; |
| 642 | struct vmw_buffer_object *backup = res->backup; | 606 | struct vmw_bo *backup = res->guest_memory_bo; |
| 643 | 607 | ||
| 644 | ret = vmw_resource_validate(res, intr, val->dirty_set && | 608 | ret = vmw_resource_validate(res, intr, val->dirty_set && |
| 645 | val->dirty); | 609 | val->dirty); |
| @@ -650,12 +614,12 @@ int vmw_validation_res_validate(struct vmw_validation_context *ctx, bool intr) · 4 unmodified lines | |||
| 650 | } | 614 | } |
| 651 | 615 | ||
| 652 | /* Check if the resource switched backup buffer */ | 616 | /* Check if the resource switched backup buffer */ |
| 653 | if (backup && res->backup && (backup != res->backup)) { | 617 | if (backup && res->guest_memory_bo && backup != res->guest_memory_bo) { |
| 654 | struct vmw_buffer_object *vbo = res->backup; | 618 | struct vmw_bo *vbo = res->guest_memory_bo; |
| 655 | 619 | ||
| 656 | ret = vmw_validation_add_bo | 620 | vmw_bo_placement_set(vbo, res->func->domain, |
| 657 | (ctx, vbo, vmw_resource_needs_backup(res), | 621 | res->func->busy_domain); |
| 658 | false); | 622 | ret = vmw_validation_add_bo(ctx, vbo); |
| 659 | if (ret) | 623 | if (ret) |
| 660 | return ret; | 624 | return ret; |
| 661 | } | 625 | } |
| @@ -889,9 +853,7 @@ void vmw_validation_bo_backoff(struct vmw_validation_context *ctx) · 227 unmodified lines | |||
| 889 | list_for_each_entry(entry, &ctx->bo_list, base.head) { | 853 | list_for_each_entry(entry, &ctx->bo_list, base.head) { |
| 890 | if (entry->coherent_count) { | 854 | if (entry->coherent_count) { |
| 891 | unsigned int coherent_count = entry->coherent_count; | 855 | unsigned int coherent_count = entry->coherent_count; |
| 892 | struct vmw_buffer_object *vbo = | 856 | struct vmw_bo *vbo = to_vmw_bo(&entry->base.bo->base); |
| 893 | container_of(entry->base.bo, typeof(*vbo), | ||
| 894 | base); | ||
| 895 | 857 | ||
| 896 | while (coherent_count--) | 858 | while (coherent_count--) |
| 897 | vmw_bo_dirty_release(vbo); | 859 | vmw_bo_dirty_release(vbo); |
| @@ -73,7 +73,7 @@ struct vmw_validation_context { · 72 unmodified lines | |||
| 73 | size_t total_mem; | 73 | size_t total_mem; |
| 74 | }; | 74 | }; |
| 75 | 75 | ||
| 76 | struct vmw_buffer_object; | 76 | struct vmw_bo; |
| 77 | struct vmw_resource; | 77 | struct vmw_resource; |
| 78 | struct vmw_fence_obj; | 78 | struct vmw_fence_obj; |
| 79 | 79 | ||
| @@ -159,11 +159,7 @@ static inline unsigned int vmw_validation_align(unsigned int val) · 79 unmodified lines | |||
| 159 | } | 159 | } |
| 160 | 160 | ||
| 161 | int vmw_validation_add_bo(struct vmw_validation_context *ctx, | 161 | int vmw_validation_add_bo(struct vmw_validation_context *ctx, |
| 162 | struct vmw_buffer_object *vbo, | 162 | struct vmw_bo *vbo); |
| 163 | bool as_mob, bool cpu_blit); | ||
| 164 | int vmw_validation_bo_validate_single(struct ttm_buffer_object *bo, | ||
| 165 | bool interruptible, | ||
| 166 | bool validate_as_mob); | ||
| 167 | int vmw_validation_bo_validate(struct vmw_validation_context *ctx, bool intr); | 163 | int vmw_validation_bo_validate(struct vmw_validation_context *ctx, bool intr); |
| 168 | void vmw_validation_unref_lists(struct vmw_validation_context *ctx); | 164 | void vmw_validation_unref_lists(struct vmw_validation_context *ctx); |
| 169 | int vmw_validation_add_resource(struct vmw_validation_context *ctx, | 165 | int vmw_validation_add_resource(struct vmw_validation_context *ctx, |
| @@ -179,7 +175,7 @@ void vmw_validation_res_unreserve(struct vmw_validation_context *ctx, · 9 unmodified lines | |||
| 179 | bool backoff); | 175 | bool backoff); |
| 180 | void vmw_validation_res_switch_backup(struct vmw_validation_context *ctx, | 176 | void vmw_validation_res_switch_backup(struct vmw_validation_context *ctx, |
| 181 | void *val_private, | 177 | void *val_private, |
| 182 | struct vmw_buffer_object *vbo, | 178 | struct vmw_bo *vbo, |
| 183 | unsigned long backup_offset); | 179 | unsigned long backup_offset); |
| 184 | int vmw_validation_res_validate(struct vmw_validation_context *ctx, bool intr); | 180 | int vmw_validation_res_validate(struct vmw_validation_context *ctx, bool intr); |
| 185 | 181 | ||
| @@ -11,13 +11,14 @@ · 10 unmodified lines | |||
| 11 | #include <linux/delay.h> | 11 | #include <linux/delay.h> |
| 12 | #include <linux/notifier.h> | 12 | #include <linux/notifier.h> |
| 13 | #include <linux/ioctl.h> | 13 | #include <linux/ioctl.h> |
| 14 | #include <linux/fb.h> | ||
| 15 | #include <linux/slab.h> | 14 | #include <linux/slab.h> |
| 16 | 15 | ||
| 17 | #include <asm/firmware.h> | 16 | #include <asm/firmware.h> |
| 18 | #include <asm/ps3av.h> | 17 | #include <asm/ps3av.h> |
| 19 | #include <asm/ps3.h> | 18 | #include <asm/ps3.h> |
| 20 | 19 | ||
| 20 | #include <video/cmdline.h> | ||
| 21 | |||
| 21 | #include "vuart.h" | 22 | #include "vuart.h" |
| 22 | 23 | ||
| 23 | #define BUFSIZE 4096 /* vuart buf size */ | 24 | #define BUFSIZE 4096 /* vuart buf size */ |
| @@ -921,6 +922,7 @@ EXPORT_SYMBOL_GPL(ps3av_audio_mute); · 897 unmodified lines | |||
| 921 | 922 | ||
| 922 | static int ps3av_probe(struct ps3_system_bus_device *dev) | 923 | static int ps3av_probe(struct ps3_system_bus_device *dev) |
| 923 | { | 924 | { |
| 925 | const char *mode_option; | ||
| 924 | int res; | 926 | int res; |
| 925 | int id; | 927 | int id; |
| 926 | 928 | ||
| @@ -968,10 +970,9 @@ static int ps3av_probe(struct ps3_system_bus_device *dev) · 41 unmodified lines | |||
| 968 | 970 | ||
| 969 | ps3av_get_hw_conf(ps3av); | 971 | ps3av_get_hw_conf(ps3av); |
| 970 | 972 | ||
| 971 | #ifdef CONFIG_FB | 973 | mode_option = video_get_options(NULL); |
| 972 | if (fb_mode_option && !strcmp(fb_mode_option, "safe")) | 974 | if (mode_option && !strcmp(mode_option, "safe")) |
| 973 | safe_mode = 1; | 975 | safe_mode = 1; |
| 974 | #endif /* CONFIG_FB */ | ||
| 975 | id = ps3av_auto_videomode(&ps3av->av_hw_conf); | 976 | id = ps3av_auto_videomode(&ps3av->av_hw_conf); |
| 976 | if (id < 0) { | 977 | if (id < 0) { |
| 977 | printk(KERN_ERR "%s: invalid id :%d\n", __func__, id); | 978 | printk(KERN_ERR "%s: invalid id :%d\n", __func__, id); |
| @@ -11,6 +11,9 @@ config APERTURE_HELPERS · 10 unmodified lines | |||
| 11 | Support tracking and hand-over of aperture ownership. Required | 11 | Support tracking and hand-over of aperture ownership. Required |
| 12 | by graphics drivers for firmware-provided framebuffers. | 12 | by graphics drivers for firmware-provided framebuffers. |
| 13 | 13 | ||
| 14 | config VIDEO_CMDLINE | ||
| 15 | bool | ||
| 16 | |||
| 14 | config VIDEO_NOMODESET | 17 | config VIDEO_NOMODESET |
| 15 | bool | 18 | bool |
| 16 | default n | 19 | default n |
| @@ -2,6 +2,7 @@ · 1 unmodified line | |||
| 2 | 2 | ||
| 3 | obj-$(CONFIG_APERTURE_HELPERS) += aperture.o | 3 | obj-$(CONFIG_APERTURE_HELPERS) += aperture.o |
| 4 | obj-$(CONFIG_VGASTATE) += vgastate.o | 4 | obj-$(CONFIG_VGASTATE) += vgastate.o |
| 5 | obj-$(CONFIG_VIDEO_CMDLINE) += cmdline.o | ||
| 5 | obj-$(CONFIG_VIDEO_NOMODESET) += nomodeset.o | 6 | obj-$(CONFIG_VIDEO_NOMODESET) += nomodeset.o |
| 6 | obj-$(CONFIG_HDMI) += hdmi.o | 7 | obj-$(CONFIG_HDMI) += hdmi.o |
| 7 | 8 | ||
| @@ -0,0 +1,133 @@ | |||
| 1 | // SPDX-License-Identifier: GPL-2.0 | ||
| 2 | /* | ||
| 3 | * Based on the fbdev code in drivers/video/fbdev/core/fb_cmdline: | ||
| 4 | * | ||
| 5 | * Copyright (C) 2014 Intel Corp | ||
| 6 | * Copyright (C) 1994 Martin Schaller | ||
| 7 | * | ||
| 8 | * 2001 - Documented with DocBook | ||
| 9 | * - Brad Douglas <brad@neruo.com> | ||
| 10 | * | ||
| 11 | * This file is subject to the terms and conditions of the GNU General Public | ||
| 12 | * License. See the file COPYING in the main directory of this archive | ||
| 13 | * for more details. | ||
| 14 | * | ||
| 15 | * Authors: | ||
| 16 | * Daniel Vetter <daniel.vetter@ffwll.ch> | ||
| 17 | */ | ||
| 18 | |||
| 19 | #include <linux/fb.h> /* for FB_MAX */ | ||
| 20 | #include <linux/init.h> | ||
| 21 | |||
| 22 | #include <video/cmdline.h> | ||
| 23 | |||
| 24 | /* | ||
| 25 | * FB_MAX is the maximum number of framebuffer devices and also | ||
| 26 | * the maximum number of video= parameters. Although not directly | ||
| 27 | * related to each other, it makes sense to keep it that way. | ||
| 28 | */ | ||
| 29 | static const char *video_options[FB_MAX] __read_mostly; | ||
| 30 | static const char *video_option __read_mostly; | ||
| 31 | static int video_of_only __read_mostly; | ||
| 32 | |||
| 33 | static const char *__video_get_option_string(const char *name) | ||
| 34 | { | ||
| 35 | const char *options = NULL; | ||
| 36 | size_t name_len = 0; | ||
| 37 | |||
| 38 | if (name) | ||
| 39 | name_len = strlen(name); | ||
| 40 | |||
| 41 | if (name_len) { | ||
| 42 | unsigned int i; | ||
| 43 | const char *opt; | ||
| 44 | |||
| 45 | for (i = 0; i < ARRAY_SIZE(video_options); ++i) { | ||
| 46 | if (!video_options[i]) | ||
| 47 | continue; | ||
| 48 | if (video_options[i][0] == '\0') | ||
| 49 | continue; | ||
| 50 | opt = video_options[i]; | ||
| 51 | if (!strncmp(opt, name, name_len) && opt[name_len] == ':') | ||
| 52 | options = opt + name_len + 1; | ||
| 53 | } | ||
| 54 | } | ||
| 55 | |||
| 56 | /* No match, return global options */ | ||
| 57 | if (!options) | ||
| 58 | options = video_option; | ||
| 59 | |||
| 60 | return options; | ||
| 61 | } | ||
| 62 | |||
| 63 | /** | ||
| 64 | * video_get_options - get kernel boot parameters | ||
| 65 | * @name: name of the output as it would appear in the boot parameter | ||
| 66 | * line (video=<name>:<options>) | ||
| 67 | * | ||
| 68 | * Looks up the video= options for the given name. Names are connector | ||
| 69 | * names with DRM, or driver names with fbdev. If no video option for | ||
| 70 | * the name has been specified, the function returns the global video= | ||
| 71 | * setting. A @name of NULL always returns the global video setting. | ||
| 72 | * | ||
| 73 | * Returns: | ||
| 74 | * The string of video options for the given name, or NULL if no video | ||
| 75 | * option has been specified. | ||
| 76 | */ | ||
| 77 | const char *video_get_options(const char *name) | ||
| 78 | { | ||
| 79 | return __video_get_option_string(name); | ||
| 80 | } | ||
| 81 | EXPORT_SYMBOL(video_get_options); | ||
| 82 | |||
| 83 | bool __video_get_options(const char *name, const char **options, bool is_of) | ||
| 84 | { | ||
| 85 | bool enabled = true; | ||
| 86 | const char *opt = NULL; | ||
| 87 | |||
| 88 | if (video_of_only && !is_of) | ||
| 89 | enabled = false; | ||
| 90 | |||
| 91 | opt = __video_get_option_string(name); | ||
| 92 | |||
| 93 | if (options) | ||
| 94 | *options = opt; | ||
| 95 | |||
| 96 | return enabled; | ||
| 97 | } | ||
| 98 | EXPORT_SYMBOL(__video_get_options); | ||
| 99 | |||
| 100 | /* | ||
| 101 | * Process command line options for video adapters. This function is | ||
| 102 | * a __setup and __init function. It only stores the options. Drivers | ||
| 103 | * have to call video_get_options() as necessary. | ||
| 104 | */ | ||
| 105 | static int __init video_setup(char *options) | ||
| 106 | { | ||
| 107 | if (!options || !*options) | ||
| 108 | goto out; | ||
| 109 | |||
| 110 | if (!strncmp(options, "ofonly", 6)) { | ||
| 111 | video_of_only = true; | ||
| 112 | goto out; | ||
| 113 | } | ||
| 114 | |||
| 115 | if (strchr(options, ':')) { | ||
| 116 | /* named */ | ||
| 117 | size_t i; | ||
| 118 | |||
| 119 | for (i = 0; i < ARRAY_SIZE(video_options); i++) { | ||
| 120 | if (!video_options[i]) { | ||
| 121 | video_options[i] = options; | ||
| 122 | break; | ||
| 123 | } | ||
| 124 | } | ||
| 125 | } else { | ||
| 126 | /* global */ | ||
| 127 | video_option = options; | ||
| 128 | } | ||
| 129 | |||
| 130 | out: | ||
| 131 | return 1; | ||
| 132 | } | ||
| 133 | __setup("video=", video_setup); | ||
| @@ -3,16 +3,13 @@ · 2 unmodified lines | |||
| 3 | # fbdev configuration | 3 | # fbdev configuration |
| 4 | # | 4 | # |
| 5 | 5 | ||
| 6 | config FB_CMDLINE | ||
| 7 | bool | ||
| 8 | |||
| 9 | config FB_NOTIFY | 6 | config FB_NOTIFY |
| 10 | bool | 7 | bool |
| 11 | 8 | ||
| 12 | menuconfig FB | 9 | menuconfig FB |
| 13 | tristate "Support for frame buffer devices" | 10 | tristate "Support for frame buffer devices" |
| 14 | select FB_CMDLINE | ||
| 15 | select FB_NOTIFY | 11 | select FB_NOTIFY |
| 12 | select VIDEO_CMDLINE | ||
| 16 | help | 13 | help |
| 17 | The frame buffer device provides an abstraction for the graphics | 14 | The frame buffer device provides an abstraction for the graphics |
| 18 | hardware. It represents the frame buffer of some video hardware and | 15 | hardware. It represents the frame buffer of some video hardware and |
| @@ -1,9 +1,8 @@ | |||
| 1 | # SPDX-License-Identifier: GPL-2.0 | 1 | # SPDX-License-Identifier: GPL-2.0 |
| 2 | obj-$(CONFIG_FB_CMDLINE) += fb_cmdline.o | ||
| 3 | obj-$(CONFIG_FB_NOTIFY) += fb_notify.o | 2 | obj-$(CONFIG_FB_NOTIFY) += fb_notify.o |
| 4 | obj-$(CONFIG_FB) += fb.o | 3 | obj-$(CONFIG_FB) += fb.o |
| 5 | fb-y := fbmem.o fbmon.o fbcmap.o fbsysfs.o \ | 4 | fb-y := fbmem.o fbmon.o fbcmap.o fbsysfs.o \ |
| 6 | modedb.o fbcvt.o | 5 | modedb.o fbcvt.o fb_cmdline.o |
| 7 | fb-$(CONFIG_FB_DEFERRED_IO) += fb_defio.o | 6 | fb-$(CONFIG_FB_DEFERRED_IO) += fb_defio.o |
| 8 | 7 | ||
| 9 | ifeq ($(CONFIG_FRAMEBUFFER_CONSOLE),y) | 8 | ifeq ($(CONFIG_FRAMEBUFFER_CONSOLE),y) |
| @@ -12,16 +12,14 @@ · 11 unmodified lines | |||
| 12 | * for more details. | 12 | * for more details. |
| 13 | * | 13 | * |
| 14 | * Authors: | 14 | * Authors: |
| 15 | * Vetter <danie.vetter@ffwll.ch> | 15 | * Daniel Vetter <daniel.vetter@ffwll.ch> |
| 16 | */ | 16 | */ |
| 17 | #include <linux/init.h> | ||
| 18 | #include <linux/fb.h> | ||
| 19 | 17 | ||
| 20 | static char *video_options[FB_MAX] __read_mostly; | 18 | #include <linux/export.h> |
| 21 | static int ofonly __read_mostly; | 19 | #include <linux/fb.h> |
| 20 | #include <linux/string.h> | ||
| 22 | 21 | ||
| 23 | const char *fb_mode_option; | 22 | #include <video/cmdline.h> |
| 24 | EXPORT_SYMBOL_GPL(fb_mode_option); | ||
| 25 | 23 | ||
| 26 | /** | 24 | /** |
| 27 | * fb_get_options - get kernel boot parameters | 25 | * fb_get_options - get kernel boot parameters |
| @@ -30,78 +28,34 @@ EXPORT_SYMBOL_GPL(fb_mode_option); · 2 unmodified lines | |||
| 30 | * (video=<name>:<options>) | 28 | * (video=<name>:<options>) |
| 31 | * @option: the option will be stored here | 29 | * @option: the option will be stored here |
| 32 | * | 30 | * |
| 31 | * The caller owns the string returned in @option and is | ||
| 32 | * responsible for releasing the memory. | ||
| 33 | * | ||
| 33 | * NOTE: Needed to maintain backwards compatibility | 34 | * NOTE: Needed to maintain backwards compatibility |
| 34 | */ | 35 | */ |
| 35 | int fb_get_options(const char *name, char **option) | 36 | int fb_get_options(const char *name, char **option) |
| 36 | { | 37 | { |
| 37 | char *opt, *options = NULL; | 38 | const char *options = NULL; |
| 38 | int retval = 0; | 39 | bool is_of = false; |
| 39 | int name_len = strlen(name), i; | 40 | bool enabled; |
| 40 | |||
| 41 | if (name_len && ofonly && strncmp(name, "offb", 4)) | ||
| 42 | retval = 1; | ||
| 43 | 41 | ||
| 44 | if (name_len && !retval) { | 42 | if (name) |
| 45 | for (i = 0; i < FB_MAX; i++) { | 43 | is_of = strncmp(name, "offb", 4); |
| 46 | if (video_options[i] == NULL) | ||
| 47 | continue; | ||
| 48 | if (!video_options[i][0]) | ||
| 49 | continue; | ||
| 50 | opt = video_options[i]; | ||
| 51 | if (!strncmp(name, opt, name_len) && | ||
| 52 | opt[name_len] == ':') | ||
| 53 | options = opt + name_len + 1; | ||
| 54 | } | ||
| 55 | } | ||
| 56 | /* No match, pass global option */ | ||
| 57 | if (!options && option && fb_mode_option) | ||
| 58 | options = kstrdup(fb_mode_option, GFP_KERNEL); | ||
| 59 | if (options && !strncmp(options, "off", 3)) | ||
| 60 | retval = 1; | ||
| 61 | |||
| 62 | if (option) | ||
| 63 | *option = options; | ||
| 64 | |||
| 65 | return retval; | ||
| 66 | } | ||
| 67 | EXPORT_SYMBOL(fb_get_options); | ||
| 68 | 44 | ||
| 69 | /** | 45 | enabled = __video_get_options(name, &options, is_of); |
| 70 | * video_setup - process command line options | ||
| 71 | * @options: string of options | ||
| 72 | * | ||
| 73 | * Process command line options for frame buffer subsystem. | ||
| 74 | * | ||
| 75 | * NOTE: This function is a __setup and __init function. | ||
| 76 | * It only stores the options. Drivers have to call | ||
| 77 | * fb_get_options() as necessary. | ||
| 78 | */ | ||
| 79 | static int __init video_setup(char *options) | ||
| 80 | { | ||
| 81 | if (!options || !*options) | ||
| 82 | goto out; | ||
| 83 | 46 | ||
| 84 | if (!strncmp(options, "ofonly", 6)) { | 47 | if (options) { |
| 85 | ofonly = 1; | 48 | if (!strncmp(options, "off", 3)) |
| 86 | goto out; | 49 | enabled = false; |
| 87 | } | 50 | } |
| 88 | 51 | ||
| 89 | if (strchr(options, ':')) { | 52 | if (option) { |
| 90 | /* named */ | 53 | if (options) |
| 91 | int i; | 54 | *option = kstrdup(options, GFP_KERNEL); |
| 92 | 55 | else | |
| 93 | for (i = 0; i < FB_MAX; i++) { | 56 | *option = NULL; |
| 94 | if (video_options[i] == NULL) { | ||
| 95 | video_options[i] = options; | ||
| 96 | break; | ||
| 97 | } | ||
| 98 | } | ||
| 99 | } else { | ||
| 100 | /* global */ | ||
| 101 | fb_mode_option = options; | ||
| 102 | } | 57 | } |
| 103 | 58 | ||
| 104 | out: | 59 | return enabled ? 0 : 1; // 0 on success, 1 otherwise |
| 105 | return 1; | ||
| 106 | } | 60 | } |
| 107 | __setup("video=", video_setup); | 61 | EXPORT_SYMBOL(fb_get_options); |
| @@ -620,6 +620,7 @@ int fb_find_mode(struct fb_var_screeninfo *var, · 619 unmodified lines | |||
| 620 | const struct fb_videomode *default_mode, | 620 | const struct fb_videomode *default_mode, |
| 621 | unsigned int default_bpp) | 621 | unsigned int default_bpp) |
| 622 | { | 622 | { |
| 623 | char *mode_option_buf = NULL; | ||
| 623 | int i; | 624 | int i; |
| 624 | 625 | ||
| 625 | /* Set up defaults */ | 626 | /* Set up defaults */ |
| @@ -635,8 +636,10 @@ int fb_find_mode(struct fb_var_screeninfo *var, · 9 unmodified lines | |||
| 635 | default_bpp = 8; | 636 | default_bpp = 8; |
| 636 | 637 | ||
| 637 | /* Did the user specify a video mode? */ | 638 | /* Did the user specify a video mode? */ |
| 638 | if (!mode_option) | 639 | if (!mode_option) { |
| 639 | mode_option = fb_mode_option; | 640 | fb_get_options(NULL, &mode_option_buf); |
| 641 | mode_option = mode_option_buf; | ||
| 642 | } | ||
| 640 | if (mode_option) { | 643 | if (mode_option) { |
| 641 | const char *name = mode_option; | 644 | const char *name = mode_option; |
| 642 | unsigned int namelen = strlen(name); | 645 | unsigned int namelen = strlen(name); |
| @@ -715,6 +718,7 @@ int fb_find_mode(struct fb_var_screeninfo *var, · 72 unmodified lines | |||
| 715 | res_specified = 1; | 718 | res_specified = 1; |
| 716 | } | 719 | } |
| 717 | done: | 720 | done: |
| 721 | kfree(mode_option_buf); | ||
| 718 | if (cvt) { | 722 | if (cvt) { |
| 719 | struct fb_videomode cvt_mode; | 723 | struct fb_videomode cvt_mode; |
| 720 | int ret; | 724 | int ret; |
| @@ -209,6 +209,32 @@ int drm_atomic_helper_page_flip_target( · 208 unmodified lines | |||
| 209 | __drm_atomic_get_current_plane_state((crtc_state)->state, \ | 209 | __drm_atomic_get_current_plane_state((crtc_state)->state, \ |
| 210 | plane))) | 210 | plane))) |
| 211 | 211 | ||
| 212 | /** | ||
| 213 | * drm_atomic_plane_enabling - check whether a plane is being enabled | ||
| 214 | * @old_plane_state: old atomic plane state | ||
| 215 | * @new_plane_state: new atomic plane state | ||
| 216 | * | ||
| 217 | * Checks the atomic state of a plane to determine whether it's being enabled | ||
| 218 | * or not. This also WARNs if it detects an invalid state (both CRTC and FB | ||
| 219 | * need to either both be NULL or both be non-NULL). | ||
| 220 | * | ||
| 221 | * RETURNS: | ||
| 222 | * True if the plane is being enabled, false otherwise. | ||
| 223 | */ | ||
| 224 | static inline bool drm_atomic_plane_enabling(struct drm_plane_state *old_plane_state, | ||
| 225 | struct drm_plane_state *new_plane_state) | ||
| 226 | { | ||
| 227 | /* | ||
| 228 | * When enabling a plane, CRTC and FB should always be set together. | ||
| 229 | * Anything else should be considered a bug in the atomic core, so we | ||
| 230 | * gently warn about it. | ||
| 231 | */ | ||
| 232 | WARN_ON((!new_plane_state->crtc && new_plane_state->fb) || | ||
| 233 | (new_plane_state->crtc && !new_plane_state->fb)); | ||
| 234 | |||
| 235 | return !old_plane_state->crtc && new_plane_state->crtc; | ||
| 236 | } | ||
| 237 | |||
| 212 | /** | 238 | /** |
| 213 | * drm_atomic_plane_disabling - check whether a plane is being disabled | 239 | * drm_atomic_plane_disabling - check whether a plane is being disabled |
| 214 | * @old_plane_state: old atomic plane state | 240 | * @old_plane_state: old atomic plane state |
| @@ -139,7 +139,11 @@ struct displayid_vesa_vendor_specific_block { · 138 unmodified lines | |||
| 139 | u8 mso; | 139 | u8 mso; |
| 140 | } __packed; | 140 | } __packed; |
| 141 | 141 | ||
| 142 | /* DisplayID iteration */ | 142 | /* |
| 143 | * DisplayID iteration. | ||
| 144 | * | ||
| 145 | * Do not access directly, this is private. | ||
| 146 | */ | ||
| 143 | struct displayid_iter { | 147 | struct displayid_iter { |
| 144 | const struct drm_edid *drm_edid; | 148 | const struct drm_edid *drm_edid; |
| 145 | 149 | ||
| @@ -147,6 +151,9 @@ struct displayid_iter { · 1 unmodified line | |||
| 147 | int length; | 151 | int length; |
| 148 | int idx; | 152 | int idx; |
| 149 | int ext_index; | 153 | int ext_index; |
| 154 | |||
| 155 | u8 version; | ||
| 156 | u8 primary_use; | ||
| 150 | }; | 157 | }; |
| 151 | 158 | ||
| 152 | void displayid_iter_edid_begin(const struct drm_edid *drm_edid, | 159 | void displayid_iter_edid_begin(const struct drm_edid *drm_edid, |
| @@ -157,4 +164,7 @@ __displayid_iter_next(struct displayid_iter *iter); · 4 unmodified lines | |||
| 157 | while (((__block) = __displayid_iter_next(__iter))) | 164 | while (((__block) = __displayid_iter_next(__iter))) |
| 158 | void displayid_iter_end(struct displayid_iter *iter); | 165 | void displayid_iter_end(struct displayid_iter *iter); |
| 159 | 166 | ||
| 167 | u8 displayid_version(const struct displayid_iter *iter); | ||
| 168 | u8 displayid_primary_use(const struct displayid_iter *iter); | ||
| 169 | |||
| 160 | #endif | 170 | #endif |
| @@ -400,25 +400,6 @@ struct drm_driver { · 399 unmodified lines | |||
| 400 | int (*dumb_map_offset)(struct drm_file *file_priv, | 400 | int (*dumb_map_offset)(struct drm_file *file_priv, |
| 401 | struct drm_device *dev, uint32_t handle, | 401 | struct drm_device *dev, uint32_t handle, |
| 402 | uint64_t *offset); | 402 | uint64_t *offset); |
| 403 | /** | ||
| 404 | * @dumb_destroy: | ||
| 405 | * | ||
| 406 | * This destroys the userspace handle for the given dumb backing storage buffer. | ||
| 407 | * Since buffer objects must be reference counted in the kernel a buffer object | ||
| 408 | * won't be immediately freed if a framebuffer modeset object still uses it. | ||
| 409 | * | ||
| 410 | * Called by the user via ioctl. | ||
| 411 | * | ||
| 412 | * The default implementation is drm_gem_dumb_destroy(). GEM based drivers | ||
| 413 | * must not overwrite this. | ||
| 414 | * | ||
| 415 | * Returns: | ||
| 416 | * | ||
| 417 | * Zero on success, negative errno on failure. | ||
| 418 | */ | ||
| 419 | int (*dumb_destroy)(struct drm_file *file_priv, | ||
| 420 | struct drm_device *dev, | ||
| 421 | uint32_t handle); | ||
| 422 | 403 | ||
| 423 | /** @major: driver major number */ | 404 | /** @major: driver major number */ |
| 424 | int major; | 405 | int major; |
| @@ -61,9 +61,15 @@ struct std_timing { · 60 unmodified lines | |||
| 61 | u8 vfreq_aspect; | 61 | u8 vfreq_aspect; |
| 62 | } __attribute__((packed)); | 62 | } __attribute__((packed)); |
| 63 | 63 | ||
| 64 | #define DRM_EDID_PT_HSYNC_POSITIVE (1 << 1) | 64 | #define DRM_EDID_PT_SYNC_MASK (3 << 3) |
| 65 | #define DRM_EDID_PT_VSYNC_POSITIVE (1 << 2) | 65 | # define DRM_EDID_PT_ANALOG_CSYNC (0 << 3) |
| 66 | #define DRM_EDID_PT_SEPARATE_SYNC (3 << 3) | 66 | # define DRM_EDID_PT_BIPOLAR_ANALOG_CSYNC (1 << 3) |
| 67 | # define DRM_EDID_PT_DIGITAL_CSYNC (2 << 3) | ||
| 68 | # define DRM_EDID_PT_CSYNC_ON_RGB (1 << 1) /* analog csync only */ | ||
| 69 | # define DRM_EDID_PT_CSYNC_SERRATE (1 << 2) | ||
| 70 | # define DRM_EDID_PT_DIGITAL_SEPARATE_SYNC (3 << 3) | ||
| 71 | # define DRM_EDID_PT_HSYNC_POSITIVE (1 << 1) /* also digital csync */ | ||
| 72 | # define DRM_EDID_PT_VSYNC_POSITIVE (1 << 2) | ||
| 67 | #define DRM_EDID_PT_STEREO (1 << 5) | 73 | #define DRM_EDID_PT_STEREO (1 << 5) |
| 68 | #define DRM_EDID_PT_INTERLACED (1 << 7) | 74 | #define DRM_EDID_PT_INTERLACED (1 << 7) |
| 69 | 75 | ||
| @@ -164,6 +164,16 @@ struct drm_gem_object_funcs { · 163 unmodified lines | |||
| 164 | */ | 164 | */ |
| 165 | int (*mmap)(struct drm_gem_object *obj, struct vm_area_struct *vma); | 165 | int (*mmap)(struct drm_gem_object *obj, struct vm_area_struct *vma); |
| 166 | 166 | ||
| 167 | /** | ||
| 168 | * @evict: | ||
| 169 | * | ||
| 170 | * Evicts gem object out from memory. Used by the drm_gem_object_evict() | ||
| 171 | * helper. Returns 0 on success, -errno otherwise. | ||
| 172 | * | ||
| 173 | * This callback is optional. | ||
| 174 | */ | ||
| 175 | int (*evict)(struct drm_gem_object *obj); | ||
| 176 | |||
| 167 | /** | 177 | /** |
| 168 | * @vm_ops: | 178 | * @vm_ops: |
| 169 | * | 179 | * |
| @@ -479,4 +489,6 @@ void drm_gem_lru_move_tail(struct drm_gem_lru *lru, struct drm_gem_object *obj); · 309 unmodified lines | |||
| 479 | unsigned long drm_gem_lru_scan(struct drm_gem_lru *lru, unsigned nr_to_scan, | 489 | unsigned long drm_gem_lru_scan(struct drm_gem_lru *lru, unsigned nr_to_scan, |
| 480 | bool (*shrink)(struct drm_gem_object *obj)); | 490 | bool (*shrink)(struct drm_gem_object *obj)); |
| 481 | 491 | ||
| 492 | int drm_gem_evict(struct drm_gem_object *obj); | ||
| 493 | |||
| 482 | #endif /* __DRM_GEM_H__ */ | 494 | #endif /* __DRM_GEM_H__ */ |
| @@ -60,20 +60,6 @@ struct drm_gem_shmem_object { · 59 unmodified lines | |||
| 60 | */ | 60 | */ |
| 61 | struct list_head madv_list; | 61 | struct list_head madv_list; |
| 62 | 62 | ||
| 63 | /** | ||
| 64 | * @pages_mark_dirty_on_put: | ||
| 65 | * | ||
| 66 | * Mark pages as dirty when they are put. | ||
| 67 | */ | ||
| 68 | unsigned int pages_mark_dirty_on_put : 1; | ||
| 69 | |||
| 70 | /** | ||
| 71 | * @pages_mark_accessed_on_put: | ||
| 72 | * | ||
| 73 | * Mark pages as accessed when they are put. | ||
| 74 | */ | ||
| 75 | unsigned int pages_mark_accessed_on_put : 1; | ||
| 76 | |||
| 77 | /** | 63 | /** |
| 78 | * @sgt: Scatter/gather table for imported PRIME buffers | 64 | * @sgt: Scatter/gather table for imported PRIME buffers |
| 79 | */ | 65 | */ |
| @@ -97,10 +83,24 @@ struct drm_gem_shmem_object { · 17 unmodified lines | |||
| 97 | */ | 83 | */ |
| 98 | unsigned int vmap_use_count; | 84 | unsigned int vmap_use_count; |
| 99 | 85 | ||
| 86 | /** | ||
| 87 | * @pages_mark_dirty_on_put: | ||
| 88 | * | ||
| 89 | * Mark pages as dirty when they are put. | ||
| 90 | */ | ||
| 91 | bool pages_mark_dirty_on_put : 1; | ||
| 92 | |||
| 93 | /** | ||
| 94 | * @pages_mark_accessed_on_put: | ||
| 95 | * | ||
| 96 | * Mark pages as accessed when they are put. | ||
| 97 | */ | ||
| 98 | bool pages_mark_accessed_on_put : 1; | ||
| 99 | |||
| 100 | /** | 100 | /** |
| 101 | * @map_wc: map object write-combined (instead of using shmem defaults). | 101 | * @map_wc: map object write-combined (instead of using shmem defaults). |
| 102 | */ | 102 | */ |
| 103 | bool map_wc; | 103 | bool map_wc : 1; |
| 104 | }; | 104 | }; |
| 105 | 105 | ||
| 106 | #define to_drm_gem_shmem_obj(obj) \ | 106 | #define to_drm_gem_shmem_obj(obj) \ |
| @@ -1331,6 +1331,32 @@ struct drm_plane_helper_funcs { · 1330 unmodified lines | |||
| 1331 | */ | 1331 | */ |
| 1332 | void (*atomic_update)(struct drm_plane *plane, | 1332 | void (*atomic_update)(struct drm_plane *plane, |
| 1333 | struct drm_atomic_state *state); | 1333 | struct drm_atomic_state *state); |
| 1334 | |||
| 1335 | /** | ||
| 1336 | * @atomic_enable: | ||
| 1337 | * | ||
| 1338 | * Drivers should use this function to unconditionally enable a plane. | ||
| 1339 | * This hook is called in-between the &drm_crtc_helper_funcs.atomic_begin | ||
| 1340 | * and drm_crtc_helper_funcs.atomic_flush callbacks. It is called after | ||
| 1341 | * @atomic_update, which will be called for all enabled planes. Drivers | ||
| 1342 | * that use @atomic_enable should set up a plane in @atomic_update and | ||
| 1343 | * afterwards enable the plane in @atomic_enable. If a plane needs to be | ||
| 1344 | * enabled before installing the scanout buffer, drivers can still do | ||
| 1345 | * so in @atomic_update. | ||
| 1346 | * | ||
| 1347 | * Note that the power state of the display pipe when this function is | ||
| 1348 | * called depends upon the exact helpers and calling sequence the driver | ||
| 1349 | * has picked. See drm_atomic_helper_commit_planes() for a discussion of | ||
| 1350 | * the tradeoffs and variants of plane commit helpers. | ||
| 1351 | * | ||
| 1352 | * This callback is used by the atomic modeset helpers, but it is | ||
| 1353 | * optional. If implemented, @atomic_enable should be the inverse of | ||
| 1354 | * @atomic_disable. Drivers that don't want to use either can still | ||
| 1355 | * implement the complete plane update in @atomic_update. | ||
| 1356 | */ | ||
| 1357 | void (*atomic_enable)(struct drm_plane *plane, | ||
| 1358 | struct drm_atomic_state *state); | ||
| 1359 | |||
| 1334 | /** | 1360 | /** |
| 1335 | * @atomic_disable: | 1361 | * @atomic_disable: |
| 1336 | * | 1362 | * |
| @@ -1351,7 +1377,8 @@ struct drm_plane_helper_funcs { · 14 unmodified lines | |||
| 1351 | * the tradeoffs and variants of plane commit helpers. | 1377 | * the tradeoffs and variants of plane commit helpers. |
| 1352 | * | 1378 | * |
| 1353 | * This callback is used by the atomic modeset helpers and by the | 1379 | * This callback is used by the atomic modeset helpers and by the |
| 1354 | * transitional plane helpers, but it is optional. | 1380 | * transitional plane helpers, but it is optional. It's intended to |
| 1381 | * reverse the effects of @atomic_enable. | ||
| 1355 | */ | 1382 | */ |
| 1356 | void (*atomic_disable)(struct drm_plane *plane, | 1383 | void (*atomic_disable)(struct drm_plane *plane, |
| 1357 | struct drm_atomic_state *state); | 1384 | struct drm_atomic_state *state); |
| @@ -15,6 +15,8 @@ struct drm_encoder; · 14 unmodified lines | |||
| 15 | struct drm_panel; | 15 | struct drm_panel; |
| 16 | struct drm_bridge; | 16 | struct drm_bridge; |
| 17 | struct device_node; | 17 | struct device_node; |
| 18 | struct mipi_dsi_device_info; | ||
| 19 | struct mipi_dsi_host; | ||
| 18 | 20 | ||
| 19 | /** | 21 | /** |
| 20 | * enum drm_lvds_dual_link_pixels - Pixel order of an LVDS dual-link connection | 22 | * enum drm_lvds_dual_link_pixels - Pixel order of an LVDS dual-link connection |
| @@ -129,6 +131,16 @@ drm_of_get_data_lanes_count_ep(const struct device_node *port, · 108 unmodified lines | |||
| 129 | } | 131 | } |
| 130 | #endif | 132 | #endif |
| 131 | 133 | ||
| 134 | #if IS_ENABLED(CONFIG_OF) && IS_ENABLED(CONFIG_DRM_MIPI_DSI) | ||
| 135 | struct mipi_dsi_host *drm_of_get_dsi_bus(struct device *dev); | ||
| 136 | #else | ||
| 137 | static inline struct | ||
| 138 | mipi_dsi_host *drm_of_get_dsi_bus(struct device *dev) | ||
| 139 | { | ||
| 140 | return ERR_PTR(-EINVAL); | ||
| 141 | } | ||
| 142 | #endif /* CONFIG_OF && CONFIG_DRM_MIPI_DSI */ | ||
| 143 | |||
| 132 | /* | 144 | /* |
| 133 | * drm_of_panel_bridge_remove - remove panel bridge | 145 | * drm_of_panel_bridge_remove - remove panel bridge |
| 134 | * @np: device tree node containing panel bridge output ports | 146 | * @np: device tree node containing panel bridge output ports |
| @@ -0,0 +1,108 @@ | |||
| 1 | /* SPDX-License-Identifier: GPL-2.0 OR MIT */ | ||
| 2 | /* | ||
| 3 | * Copyright 2011 Red Hat Inc. | ||
| 4 | * Copyright © 2022 Intel Corporation | ||
| 5 | */ | ||
| 6 | #ifndef _DRM_SUBALLOC_H_ | ||
| 7 | #define _DRM_SUBALLOC_H_ | ||
| 8 | |||
| 9 | #include <drm/drm_mm.h> | ||
| 10 | |||
| 11 | #include <linux/dma-fence.h> | ||
| 12 | #include <linux/types.h> | ||
| 13 | |||
| 14 | #define DRM_SUBALLOC_MAX_QUEUES 32 | ||
| 15 | /** | ||
| 16 | * struct drm_suballoc_manager - fenced range allocations | ||
| 17 | * @wq: Wait queue for sleeping allocations on contention. | ||
| 18 | * @hole: Pointer to first hole node. | ||
| 19 | * @olist: List of allocated ranges. | ||
| 20 | * @flist: Array[fence context hash] of queues of fenced allocated ranges. | ||
| 21 | * @size: Size of the managed range. | ||
| 22 | * @align: Default alignment for the managed range. | ||
| 23 | */ | ||
| 24 | struct drm_suballoc_manager { | ||
| 25 | wait_queue_head_t wq; | ||
| 26 | struct list_head *hole; | ||
| 27 | struct list_head olist; | ||
| 28 | struct list_head flist[DRM_SUBALLOC_MAX_QUEUES]; | ||
| 29 | size_t size; | ||
| 30 | size_t align; | ||
| 31 | }; | ||
| 32 | |||
| 33 | /** | ||
| 34 | * struct drm_suballoc - Sub-allocated range | ||
| 35 | * @olist: List link for list of allocated ranges. | ||
| 36 | * @flist: List linkk for the manager fenced allocated ranges queues. | ||
| 37 | * @manager: The drm_suballoc_manager. | ||
| 38 | * @soffset: Start offset. | ||
| 39 | * @eoffset: End offset + 1 so that @eoffset - @soffset = size. | ||
| 40 | * @dma_fence: The fence protecting the allocation. | ||
| 41 | */ | ||
| 42 | struct drm_suballoc { | ||
| 43 | struct list_head olist; | ||
| 44 | struct list_head flist; | ||
| 45 | struct drm_suballoc_manager *manager; | ||
| 46 | size_t soffset; | ||
| 47 | size_t eoffset; | ||
| 48 | struct dma_fence *fence; | ||
| 49 | }; | ||
| 50 | |||
| 51 | void drm_suballoc_manager_init(struct drm_suballoc_manager *sa_manager, | ||
| 52 | size_t size, size_t align); | ||
| 53 | |||
| 54 | void drm_suballoc_manager_fini(struct drm_suballoc_manager *sa_manager); | ||
| 55 | |||
| 56 | struct drm_suballoc * | ||
| 57 | drm_suballoc_new(struct drm_suballoc_manager *sa_manager, size_t size, | ||
| 58 | gfp_t gfp, bool intr, size_t align); | ||
| 59 | |||
| 60 | void drm_suballoc_free(struct drm_suballoc *sa, struct dma_fence *fence); | ||
| 61 | |||
| 62 | /** | ||
| 63 | * drm_suballoc_soffset - Range start. | ||
| 64 | * @sa: The struct drm_suballoc. | ||
| 65 | * | ||
| 66 | * Return: The start of the allocated range. | ||
| 67 | */ | ||
| 68 | static inline size_t drm_suballoc_soffset(struct drm_suballoc *sa) | ||
| 69 | { | ||
| 70 | return sa->soffset; | ||
| 71 | } | ||
| 72 | |||
| 73 | /** | ||
| 74 | * drm_suballoc_eoffset - Range end. | ||
| 75 | * @sa: The struct drm_suballoc. | ||
| 76 | * | ||
| 77 | * Return: The end of the allocated range + 1. | ||
| 78 | */ | ||
| 79 | static inline size_t drm_suballoc_eoffset(struct drm_suballoc *sa) | ||
| 80 | { | ||
| 81 | return sa->eoffset; | ||
| 82 | } | ||
| 83 | |||
| 84 | /** | ||
| 85 | * drm_suballoc_size - Range size. | ||
| 86 | * @sa: The struct drm_suballoc. | ||
| 87 | * | ||
| 88 | * Return: The size of the allocated range. | ||
| 89 | */ | ||
| 90 | static inline size_t drm_suballoc_size(struct drm_suballoc *sa) | ||
| 91 | { | ||
| 92 | return sa->eoffset - sa->soffset; | ||
| 93 | } | ||
| 94 | |||
| 95 | #ifdef CONFIG_DEBUG_FS | ||
| 96 | void drm_suballoc_dump_debug_info(struct drm_suballoc_manager *sa_manager, | ||
| 97 | struct drm_printer *p, | ||
| 98 | unsigned long long suballoc_base); | ||
| 99 | #else | ||
| 100 | static inline void | ||
| 101 | drm_suballoc_dump_debug_info(struct drm_suballoc_manager *sa_manager, | ||
| 102 | struct drm_printer *p, | ||
| 103 | unsigned long long suballoc_base) | ||
| 104 | { } | ||
| 105 | |||
| 106 | #endif | ||
| 107 | |||
| 108 | #endif /* _DRM_SUBALLOC_H_ */ | ||
| @@ -48,6 +48,8 @@ struct drm_gem_object; · 47 unmodified lines | |||
| 48 | struct drm_gpu_scheduler; | 48 | struct drm_gpu_scheduler; |
| 49 | struct drm_sched_rq; | 49 | struct drm_sched_rq; |
| 50 | 50 | ||
| 51 | struct drm_file; | ||
| 52 | |||
| 51 | /* These are often used as an (initial) index | 53 | /* These are often used as an (initial) index |
| 52 | * to an array, and as such should start at 0. | 54 | * to an array, and as such should start at 0. |
| 53 | */ | 55 | */ |
| @@ -522,6 +524,10 @@ int drm_sched_job_init(struct drm_sched_job *job, · 468 unmodified lines | |||
| 522 | void drm_sched_job_arm(struct drm_sched_job *job); | 524 | void drm_sched_job_arm(struct drm_sched_job *job); |
| 523 | int drm_sched_job_add_dependency(struct drm_sched_job *job, | 525 | int drm_sched_job_add_dependency(struct drm_sched_job *job, |
| 524 | struct dma_fence *fence); | 526 | struct dma_fence *fence); |
| 527 | int drm_sched_job_add_syncobj_dependency(struct drm_sched_job *job, | ||
| 528 | struct drm_file *file, | ||
| 529 | u32 handle, | ||
| 530 | u32 point); | ||
| 525 | int drm_sched_job_add_resv_dependencies(struct drm_sched_job *job, | 531 | int drm_sched_job_add_resv_dependencies(struct drm_sched_job *job, |
| 526 | struct dma_resv *resv, | 532 | struct dma_resv *resv, |
| 527 | enum dma_resv_usage usage); | 533 | enum dma_resv_usage usage); |
| @@ -141,7 +141,7 @@ struct ttm_device_funcs { · 140 unmodified lines | |||
| 141 | * the graphics address space | 141 | * the graphics address space |
| 142 | * @ctx: context for this move with parameters | 142 | * @ctx: context for this move with parameters |
| 143 | * @new_mem: the new memory region receiving the buffer | 143 | * @new_mem: the new memory region receiving the buffer |
| 144 | @ @hop: placement for driver directed intermediate hop | 144 | * @hop: placement for driver directed intermediate hop |
| 145 | * | 145 | * |
| 146 | * Move a buffer between two memory regions. | 146 | * Move a buffer between two memory regions. |
| 147 | * Returns errno -EMULTIHOP if driver requests a hop | 147 | * Returns errno -EMULTIHOP if driver requests a hop |
| @@ -765,7 +765,6 @@ struct dmt_videomode { · 764 unmodified lines | |||
| 765 | const struct fb_videomode *mode; | 765 | const struct fb_videomode *mode; |
| 766 | }; | 766 | }; |
| 767 | 767 | ||
| 768 | extern const char *fb_mode_option; | ||
| 769 | extern const struct fb_videomode vesa_modes[]; | 768 | extern const struct fb_videomode vesa_modes[]; |
| 770 | extern const struct dmt_videomode dmt_modes[]; | 769 | extern const struct dmt_videomode dmt_modes[]; |
| 771 | 770 | ||
| @@ -972,6 +972,19 @@ extern "C" { · 971 unmodified lines | |||
| 972 | #define DRM_IOCTL_GET_STATS DRM_IOR( 0x06, struct drm_stats) | 972 | #define DRM_IOCTL_GET_STATS DRM_IOR( 0x06, struct drm_stats) |
| 973 | #define DRM_IOCTL_SET_VERSION DRM_IOWR(0x07, struct drm_set_version) | 973 | #define DRM_IOCTL_SET_VERSION DRM_IOWR(0x07, struct drm_set_version) |
| 974 | #define DRM_IOCTL_MODESET_CTL DRM_IOW(0x08, struct drm_modeset_ctl) | 974 | #define DRM_IOCTL_MODESET_CTL DRM_IOW(0x08, struct drm_modeset_ctl) |
| 975 | /** | ||
| 976 | * DRM_IOCTL_GEM_CLOSE - Close a GEM handle. | ||
| 977 | * | ||
| 978 | * GEM handles are not reference-counted by the kernel. User-space is | ||
| 979 | * responsible for managing their lifetime. For example, if user-space imports | ||
| 980 | * the same memory object twice on the same DRM file description, the same GEM | ||
| 981 | * handle is returned by both imports, and user-space needs to ensure | ||
| 982 | * &DRM_IOCTL_GEM_CLOSE is performed once only. The same situation can happen | ||
| 983 | * when a memory object is allocated, then exported and imported again on the | ||
| 984 | * same DRM file description. The &DRM_IOCTL_MODE_GETFB2 IOCTL is an exception | ||
| 985 | * and always returns fresh new GEM handles even if an existing GEM handle | ||
| 986 | * already refers to the same memory object before the IOCTL is performed. | ||
| 987 | */ | ||
| 975 | #define DRM_IOCTL_GEM_CLOSE DRM_IOW (0x09, struct drm_gem_close) | 988 | #define DRM_IOCTL_GEM_CLOSE DRM_IOW (0x09, struct drm_gem_close) |
| 976 | #define DRM_IOCTL_GEM_FLINK DRM_IOWR(0x0a, struct drm_gem_flink) | 989 | #define DRM_IOCTL_GEM_FLINK DRM_IOWR(0x0a, struct drm_gem_flink) |
| 977 | #define DRM_IOCTL_GEM_OPEN DRM_IOWR(0x0b, struct drm_gem_open) | 990 | #define DRM_IOCTL_GEM_OPEN DRM_IOWR(0x0b, struct drm_gem_open) |
| @@ -1012,7 +1025,37 @@ extern "C" { · 34 unmodified lines | |||
| 1012 | #define DRM_IOCTL_UNLOCK DRM_IOW( 0x2b, struct drm_lock) | 1025 | #define DRM_IOCTL_UNLOCK DRM_IOW( 0x2b, struct drm_lock) |
| 1013 | #define DRM_IOCTL_FINISH DRM_IOW( 0x2c, struct drm_lock) | 1026 | #define DRM_IOCTL_FINISH DRM_IOW( 0x2c, struct drm_lock) |
| 1014 | 1027 | ||
| 1028 | /** | ||
| 1029 | * DRM_IOCTL_PRIME_HANDLE_TO_FD - Convert a GEM handle to a DMA-BUF FD. | ||
| 1030 | * | ||
| 1031 | * User-space sets &drm_prime_handle.handle with the GEM handle to export and | ||
| 1032 | * &drm_prime_handle.flags, and gets back a DMA-BUF file descriptor in | ||
| 1033 | * &drm_prime_handle.fd. | ||
| 1034 | * | ||
| 1035 | * The export can fail for any driver-specific reason, e.g. because export is | ||
| 1036 | * not supported for this specific GEM handle (but might be for others). | ||
| 1037 | * | ||
| 1038 | * Support for exporting DMA-BUFs is advertised via &DRM_PRIME_CAP_EXPORT. | ||
| 1039 | */ | ||
| 1015 | #define DRM_IOCTL_PRIME_HANDLE_TO_FD DRM_IOWR(0x2d, struct drm_prime_handle) | 1040 | #define DRM_IOCTL_PRIME_HANDLE_TO_FD DRM_IOWR(0x2d, struct drm_prime_handle) |
| 1041 | /** | ||
| 1042 | * DRM_IOCTL_PRIME_FD_TO_HANDLE - Convert a DMA-BUF FD to a GEM handle. | ||
| 1043 | * | ||
| 1044 | * User-space sets &drm_prime_handle.fd with a DMA-BUF file descriptor to | ||
| 1045 | * import, and gets back a GEM handle in &drm_prime_handle.handle. | ||
| 1046 | * &drm_prime_handle.flags is unused. | ||
| 1047 | * | ||
| 1048 | * If an existing GEM handle refers to the memory object backing the DMA-BUF, | ||
| 1049 | * that GEM handle is returned. Therefore user-space which needs to handle | ||
| 1050 | * arbitrary DMA-BUFs must have a user-space lookup data structure to manually | ||
| 1051 | * reference-count duplicated GEM handles. For more information see | ||
| 1052 | * &DRM_IOCTL_GEM_CLOSE. | ||
| 1053 | * | ||
| 1054 | * The import can fail for any driver-specific reason, e.g. because import is | ||
| 1055 | * only supported for DMA-BUFs allocated on this DRM device. | ||
| 1056 | * | ||
| 1057 | * Support for importing DMA-BUFs is advertised via &DRM_PRIME_CAP_IMPORT. | ||
| 1058 | */ | ||
| 1016 | #define DRM_IOCTL_PRIME_FD_TO_HANDLE DRM_IOWR(0x2e, struct drm_prime_handle) | 1059 | #define DRM_IOCTL_PRIME_FD_TO_HANDLE DRM_IOWR(0x2e, struct drm_prime_handle) |
| 1017 | 1060 | ||
| 1018 | #define DRM_IOCTL_AGP_ACQUIRE DRM_IO( 0x30) | 1061 | #define DRM_IOCTL_AGP_ACQUIRE DRM_IO( 0x30) |
| @@ -1104,8 +1147,13 @@ extern "C" { · 85 unmodified lines | |||
| 1104 | * struct as the output. | 1147 | * struct as the output. |
| 1105 | * | 1148 | * |
| 1106 | * If the client is DRM master or has &CAP_SYS_ADMIN, &drm_mode_fb_cmd2.handles | 1149 | * If the client is DRM master or has &CAP_SYS_ADMIN, &drm_mode_fb_cmd2.handles |
| 1107 | * will be filled with GEM buffer handles. Planes are valid until one has a | 1150 | * will be filled with GEM buffer handles. Fresh new GEM handles are always |
| 1108 | * zero handle -- this can be used to compute the number of planes. | 1151 | * returned, even if another GEM handle referring to the same memory object |
| 1152 | * already exists on the DRM file description. The caller is responsible for | ||
| 1153 | * removing the new handles, e.g. via the &DRM_IOCTL_GEM_CLOSE IOCTL. The same | ||
| 1154 | * new handle will be returned for multiple planes in case they use the same | ||
| 1155 | * memory object. Planes are valid until one has a zero handle -- this can be | ||
| 1156 | * used to compute the number of planes. | ||
| 1109 | * | 1157 | * |
| 1110 | * Otherwise, &drm_mode_fb_cmd2.handles will be zeroed and planes are valid | 1158 | * Otherwise, &drm_mode_fb_cmd2.handles will be zeroed and planes are valid |
| 1111 | * until one has a zero &drm_mode_fb_cmd2.pitches. | 1159 | * until one has a zero &drm_mode_fb_cmd2.pitches. |
| @@ -1113,6 +1161,11 @@ extern "C" { · 1 unmodified line | |||
| 1113 | * If the framebuffer has a format modifier, &DRM_MODE_FB_MODIFIERS will be set | 1161 | * If the framebuffer has a format modifier, &DRM_MODE_FB_MODIFIERS will be set |
| 1114 | * in &drm_mode_fb_cmd2.flags and &drm_mode_fb_cmd2.modifier will contain the | 1162 | * in &drm_mode_fb_cmd2.flags and &drm_mode_fb_cmd2.modifier will contain the |
| 1115 | * modifier. Otherwise, user-space must ignore &drm_mode_fb_cmd2.modifier. | 1163 | * modifier. Otherwise, user-space must ignore &drm_mode_fb_cmd2.modifier. |
| 1164 | * | ||
| 1165 | * To obtain DMA-BUF FDs for each plane without leaking GEM handles, user-space | ||
| 1166 | * can export each handle via &DRM_IOCTL_PRIME_HANDLE_TO_FD, then immediately | ||
| 1167 | * close each unique handle via &DRM_IOCTL_GEM_CLOSE, making sure to not | ||
| 1168 | * double-close handles which are specified multiple times in the array. | ||
| 1116 | */ | 1169 | */ |
| 1117 | #define DRM_IOCTL_MODE_GETFB2 DRM_IOWR(0xCE, struct drm_mode_fb_cmd2) | 1170 | #define DRM_IOCTL_MODE_GETFB2 DRM_IOWR(0xCE, struct drm_mode_fb_cmd2) |
| 1118 | 1171 | ||
| @@ -0,0 +1,20 @@ | |||
| 1 | /* SPDX-License-Identifier: GPL-2.0 */ | ||
| 2 | |||
| 3 | #ifndef VIDEO_CMDLINE_H | ||
| 4 | #define VIDEO_CMDLINE_H | ||
| 5 | |||
| 6 | #include <linux/types.h> | ||
| 7 | |||
| 8 | #if defined(CONFIG_VIDEO_CMDLINE) | ||
| 9 | const char *video_get_options(const char *name); | ||
| 10 | |||
| 11 | /* exported for compatibility with fbdev; don't use in new code */ | ||
| 12 | bool __video_get_options(const char *name, const char **option, bool is_of); | ||
| 13 | #else | ||
| 14 | static inline const char *video_get_options(const char *name) | ||
| 15 | { | ||
| 16 | return NULL; | ||
| 17 | } | ||
| 18 | #endif | ||
| 19 | |||
| 20 | #endif | ||