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 | 26 | reg: |
| 27 | 27 | maxItems: 1 |
| 28 | 28 | |
| 29 | − clocks: | |
| 30 | − items: | |
| 31 | − - description: Module clock | |
| 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 | |
| 29 | + clocks: true | |
| 30 | + | |
| 31 | + clock-names: true | |
| 42 | 32 | |
| 43 | 33 | resets: |
| 44 | 34 | maxItems: 1 |
| @@ -30,6 +30,15 @@ properties: · 29 unmodified lines | ||
| 30 | 30 | $nodename: |
| 31 | 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 | 42 | "#address-cells": |
| 34 | 43 | const: 1 |
| 35 | 44 | |
| @@ -52,15 +61,6 @@ patternProperties: · 16 unmodified lines | ||
| 52 | 61 | case the reg property can take multiple entries, one for each virtual |
| 53 | 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 | 64 | enforce-video-mode: |
| 65 | 65 | type: boolean |
| 66 | 66 | description: |
| @@ -50,7 +50,7 @@ Optional properties for dp-controller: · 49 unmodified lines | ||
| 50 | 50 | Documentation/devicetree/bindings/display/panel/display-timing.txt |
| 51 | 51 | |
| 52 | 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 | 54 | -phys (required) |
| 55 | 55 | -phy-names (required) |
| 56 | 56 | -hpd-gpios (optional) |
| @@ -17,6 +17,8 @@ properties: · 16 unmodified lines | ||
| 17 | 17 | items: |
| 18 | 18 | - enum: |
| 19 | 19 | - chongzhou,cz101b4001 |
| 20 | + - radxa,display-10hd-ad001 | |
| 21 | + - radxa,display-8hd-ad002 | |
| 20 | 22 | - const: jadard,jd9365da-h3 |
| 21 | 23 | |
| 22 | 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 | 26 | over control to a driver for the real hardware. The bindings for the |
| 27 | 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 | 34 | It is advised to add display# aliases to help the OS determine how |
| 30 | 35 | to number things. If display# aliases are used, then if the simplefb |
| 31 | 36 | node contains a display property then the /aliases/display# path |
| @@ -117,6 +122,10 @@ properties: · 85 unmodified lines | ||
| 117 | 122 | $ref: /schemas/types.yaml#/definitions/phandle |
| 118 | 123 | description: Primary display hardware node |
| 119 | 124 | |
| 125 | + panel: | |
| 126 | + $ref: /schemas/types.yaml#/definitions/phandle | |
| 127 | + description: Display panel node | |
| 128 | + | |
| 120 | 129 | allwinner,pipeline: |
| 121 | 130 | description: Pipeline used by the framebuffer on Allwinner SoCs |
| 122 | 131 | enum: |
| @@ -80,13 +80,17 @@ allOf: · 79 unmodified lines | ||
| 80 | 80 | properties: |
| 81 | 81 | compatible: |
| 82 | 82 | contains: |
| 83 | − const: rockchip,px30-grf | |
| 83 | + enum: | |
| 84 | + - rockchip,px30-grf | |
| 84 | 85 | |
| 85 | 86 | then: |
| 86 | 87 | properties: |
| 87 | 88 | lvds: |
| 88 | − description: | |
| 89 | − Documentation/devicetree/bindings/display/rockchip/rockchip-lvds.txt | |
| 89 | + type: object | |
| 90 | + | |
| 91 | + $ref: /schemas/display/rockchip/rockchip,lvds.yaml# | |
| 92 | + | |
| 93 | + unevaluatedProperties: false | |
| 90 | 94 | |
| 91 | 95 | - if: |
| 92 | 96 | properties: |
| @@ -7044,7 +7044,7 @@ F: Documentation/devicetree/bindings/display/xlnx/ · 7043 unmodified lines | ||
| 7044 | 7044 | F: drivers/gpu/drm/xlnx/ |
| 7045 | 7045 | |
| 7046 | 7046 | DRM PANEL DRIVERS |
| 7047 | −M: Thierry Reding <thierry.reding@gmail.com> | |
| 7047 | +M: Neil Armstrong <neil.armstrong@linaro.org> | |
| 7048 | 7048 | R: Sam Ravnborg <sam@ravnborg.org> |
| 7049 | 7049 | L: dri-devel@lists.freedesktop.org |
| 7050 | 7050 | S: Maintained |
| @@ -237,8 +237,6 @@ int ivpu_rpm_get(struct ivpu_device *vdev) · 236 unmodified lines | ||
| 237 | 237 | { |
| 238 | 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 | 240 | ret = pm_runtime_resume_and_get(vdev->drm.dev); |
| 243 | 241 | if (!drm_WARN_ON(&vdev->drm, ret < 0)) |
| 244 | 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 | 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 | 249 | pm_runtime_mark_last_busy(vdev->drm.dev); |
| 254 | 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 | 310 | pm_runtime_allow(dev); |
| 315 | 311 | pm_runtime_mark_last_busy(dev); |
| 316 | 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 | 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 | 317 | pm_runtime_get_noresume(vdev->drm.dev); |
| 328 | 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 | 828 | * - dma_buf_attach() |
| 829 | 829 | * - dma_buf_dynamic_attach() |
| 830 | 830 | * - dma_buf_detach() |
| 831 | − * - dma_buf_export( | |
| 831 | + * - dma_buf_export() | |
| 832 | 832 | * - dma_buf_fd() |
| 833 | 833 | * - dma_buf_get() |
| 834 | 834 | * - dma_buf_put() |
| @@ -10,13 +10,13 @@ menuconfig DRM · 9 unmodified lines | ||
| 10 | 10 | depends on (AGP || AGP=n) && !EMULATED_CMPXCHG && HAS_DMA |
| 11 | 11 | select DRM_PANEL_ORIENTATION_QUIRKS |
| 12 | 12 | select HDMI |
| 13 | − select FB_CMDLINE | |
| 14 | 13 | select I2C |
| 15 | 14 | select DMA_SHARED_BUFFER |
| 16 | 15 | select SYNC_FILE |
| 17 | 16 | # gallium uses SYS_kcmp for os_same_file_description() to de-duplicate |
| 18 | 17 | # device and dmabuf fd. Let's make sure that is available for our userspace. |
| 19 | 18 | select KCMP |
| 19 | + select VIDEO_CMDLINE | |
| 20 | 20 | select VIDEO_NOMODESET |
| 21 | 21 | help |
| 22 | 22 | Kernel-level support for the Direct Rendering Infrastructure (DRI) |
| @@ -232,6 +232,10 @@ config DRM_GEM_SHMEM_HELPER · 209 unmodified lines | ||
| 232 | 232 | help |
| 233 | 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 | 239 | config DRM_SCHED |
| 236 | 240 | tristate |
| 237 | 241 | depends on DRM |
| @@ -88,6 +88,9 @@ obj-$(CONFIG_DRM_GEM_DMA_HELPER) += drm_dma_helper.o · 87 unmodified lines | ||
| 88 | 88 | drm_shmem_helper-y := drm_gem_shmem_helper.o |
| 89 | 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 | 94 | drm_vram_helper-y := drm_gem_vram_helper.o |
| 92 | 95 | obj-$(CONFIG_DRM_VRAM_HELPER) += drm_vram_helper.o |
| 93 | 96 | |
| @@ -19,6 +19,7 @@ config DRM_AMDGPU · 18 unmodified lines | ||
| 19 | 19 | select BACKLIGHT_CLASS_DEVICE |
| 20 | 20 | select INTERVAL_TREE |
| 21 | 21 | select DRM_BUDDY |
| 22 | + select DRM_SUBALLOC_HELPER | |
| 22 | 23 | # amdgpu depends on ACPI_VIDEO when ACPI is enabled, for select to work |
| 23 | 24 | # ACPI_VIDEO's dependencies must also be selected. |
| 24 | 25 | select INPUT if ACPI |
| @@ -424,29 +424,11 @@ struct amdgpu_clock { · 423 unmodified lines | ||
| 424 | 424 | * alignment). |
| 425 | 425 | */ |
| 426 | 426 | |
| 427 | −#define AMDGPU_SA_NUM_FENCE_LISTS 32 | |
| 428 | − | |
| 429 | 427 | struct amdgpu_sa_manager { |
| 430 | − wait_queue_head_t wq; | |
| 431 | − struct amdgpu_bo *bo; | |
| 432 | − struct list_head *hole; | |
| 433 | − struct list_head flist[AMDGPU_SA_NUM_FENCE_LISTS]; | |
| 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; | |
| 428 | + struct drm_suballoc_manager base; | |
| 429 | + struct amdgpu_bo *bo; | |
| 430 | + uint64_t gpu_addr; | |
| 431 | + void *cpu_ptr; | |
| 450 | 432 | }; |
| 451 | 433 | |
| 452 | 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 | 70 | if (size) { |
| 71 | 71 | r = amdgpu_sa_bo_new(&adev->ib_pools[pool_type], |
| 72 | − &ib->sa_bo, size, 256); | |
| 72 | + &ib->sa_bo, size); | |
| 73 | 73 | if (r) { |
| 74 | 74 | dev_err(adev->dev, "failed to get a new IB (%d)\n", r); |
| 75 | 75 | return r; |
| @@ -309,8 +309,7 @@ int amdgpu_ib_pool_init(struct amdgpu_device *adev) · 233 unmodified lines | ||
| 309 | 309 | |
| 310 | 310 | for (i = 0; i < AMDGPU_IB_POOL_MAX; i++) { |
| 311 | 311 | r = amdgpu_sa_bo_manager_init(adev, &adev->ib_pools[i], |
| 312 | − AMDGPU_IB_POOL_SIZE, | |
| 313 | − AMDGPU_GPU_PAGE_SIZE, | |
| 312 | + AMDGPU_IB_POOL_SIZE, 256, | |
| 314 | 313 | AMDGPU_GEM_DOMAIN_GTT); |
| 315 | 314 | if (r) |
| 316 | 315 | goto error; |
| @@ -600,7 +600,7 @@ int amdgpu_bo_create(struct amdgpu_device *adev, · 599 unmodified lines | ||
| 600 | 600 | |
| 601 | 601 | if (!amdgpu_gmc_vram_full_visible(&adev->gmc) && |
| 602 | 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 | 604 | amdgpu_cs_report_moved_bytes(adev, ctx.bytes_moved, |
| 605 | 605 | ctx.bytes_moved); |
| 606 | 606 | else |
| @@ -1346,7 +1346,6 @@ vm_fault_t amdgpu_bo_fault_reserve_notify(struct ttm_buffer_object *bo) · 739 unmodified lines | ||
| 1346 | 1346 | struct amdgpu_device *adev = amdgpu_ttm_adev(bo->bdev); |
| 1347 | 1347 | struct ttm_operation_ctx ctx = { false, false }; |
| 1348 | 1348 | struct amdgpu_bo *abo = ttm_to_amdgpu_bo(bo); |
| 1349 | − unsigned long offset; | |
| 1350 | 1349 | int r; |
| 1351 | 1350 | |
| 1352 | 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 | 1354 | if (bo->resource->mem_type != TTM_PL_VRAM) |
| 1356 | 1355 | return 0; |
| 1357 | 1356 | |
| 1358 | − offset = bo->resource->start << PAGE_SHIFT; | |
| 1359 | − if ((offset + bo->base.size) <= adev->gmc.visible_vram_size) | |
| 1357 | + if (amdgpu_bo_in_cpu_visible_vram(abo)) | |
| 1360 | 1358 | return 0; |
| 1361 | 1359 | |
| 1362 | 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 | 1376 | else if (unlikely(r)) |
| 1379 | 1377 | return VM_FAULT_SIGBUS; |
| 1380 | 1378 | |
| 1381 | − offset = bo->resource->start << PAGE_SHIFT; | |
| 1382 | 1379 | /* this should never happen */ |
| 1383 | 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 | 1382 | return VM_FAULT_SIGBUS; |
| 1386 | 1383 | |
| 1387 | 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 | 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 | 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 | 362 | int amdgpu_sa_bo_manager_start(struct amdgpu_device *adev, |
| 356 | 363 | struct amdgpu_sa_manager *sa_manager); |
| 357 | 364 | int amdgpu_sa_bo_new(struct amdgpu_sa_manager *sa_manager, |
| 358 | − struct amdgpu_sa_bo **sa_bo, | |
| 359 | − unsigned size, unsigned align); | |
| 365 | + struct drm_suballoc **sa_bo, | |
| 366 | + unsigned int size); | |
| 360 | 367 | void amdgpu_sa_bo_free(struct amdgpu_device *adev, |
| 361 | − struct amdgpu_sa_bo **sa_bo, | |
| 362 | − struct dma_fence *fence); | |
| 368 | + struct drm_suballoc **sa_bo, | |
| 369 | + struct dma_fence *fence); | |
| 363 | 370 | #if defined(CONFIG_DEBUG_FS) |
| 364 | 371 | void amdgpu_sa_bo_dump_debug_info(struct amdgpu_sa_manager *sa_manager, |
| 365 | 372 | struct seq_file *m); |
| @@ -27,6 +27,7 @@ · 26 unmodified lines | ||
| 27 | 27 | #include <drm/amdgpu_drm.h> |
| 28 | 28 | #include <drm/gpu_scheduler.h> |
| 29 | 29 | #include <drm/drm_print.h> |
| 30 | +#include <drm/drm_suballoc.h> | |
| 30 | 31 | |
| 31 | 32 | struct amdgpu_device; |
| 32 | 33 | struct amdgpu_ring; |
| @@ -92,7 +93,7 @@ enum amdgpu_ib_pool_type { · 59 unmodified lines | ||
| 92 | 93 | }; |
| 93 | 94 | |
| 94 | 95 | struct amdgpu_ib { |
| 95 | − struct amdgpu_sa_bo *sa_bo; | |
| 96 | + struct drm_suballoc *sa_bo; | |
| 96 | 97 | uint32_t length_dw; |
| 97 | 98 | uint64_t gpu_addr; |
| 98 | 99 | uint32_t *ptr; |
| @@ -44,327 +44,63 @@ · 43 unmodified lines | ||
| 44 | 44 | |
| 45 | 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 | 47 | int amdgpu_sa_bo_manager_init(struct amdgpu_device *adev, |
| 51 | 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; | |
| 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]); | |
| 51 | + int r; | |
| 65 | 52 | |
| 66 | − r = amdgpu_bo_create_kernel(adev, size, align, domain, &sa_manager->bo, | |
| 67 | − &sa_manager->gpu_addr, &sa_manager->cpu_ptr); | |
| 53 | + r = amdgpu_bo_create_kernel(adev, size, AMDGPU_GPU_PAGE_SIZE, domain, | |
| 54 | + &sa_manager->bo, &sa_manager->gpu_addr, | |
| 55 | + &sa_manager->cpu_ptr); | |
| 68 | 56 | if (r) { |
| 69 | 57 | dev_err(adev->dev, "(%d) failed to allocate bo for manager\n", r); |
| 70 | 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 | 63 | return r; |
| 75 | 64 | } |
| 76 | 65 | |
| 77 | 66 | void amdgpu_sa_bo_manager_fini(struct amdgpu_device *adev, |
| 78 | 67 | struct amdgpu_sa_manager *sa_manager) |
| 79 | 68 | { |
| 80 | − struct amdgpu_sa_bo *sa_bo, *tmp; | |
| 81 | − | |
| 82 | 69 | if (sa_manager->bo == NULL) { |
| 83 | 70 | dev_err(adev->dev, "no bo for sa manager\n"); |
| 84 | 71 | return; |
| 85 | 72 | } |
| 86 | 73 | |
| 87 | − if (!list_empty(&sa_manager->olist)) { | |
| 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 | − } | |
| 74 | + drm_suballoc_manager_fini(&sa_manager->base); | |
| 97 | 75 | |
| 98 | 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) | |
| 103 | −{ | |
| 104 | − struct amdgpu_sa_manager *sa_manager = sa_bo->manager; | |
| 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) | |
| 79 | +int amdgpu_sa_bo_new(struct amdgpu_sa_manager *sa_manager, | |
| 80 | + struct drm_suballoc **sa_bo, | |
| 81 | + unsigned int size) | |
| 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) | |
| 119 | − return; | |
| 86 | + if (IS_ERR(sa)) { | |
| 87 | + *sa_bo = NULL; | |
| 120 | 88 | |
| 121 | − sa_bo = list_entry(sa_manager->hole->next, struct amdgpu_sa_bo, olist); | |
| 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); | |
| 89 | + return PTR_ERR(sa); | |
| 128 | 90 | } |
| 129 | −} | |
| 130 | 91 | |
| 131 | −static inline unsigned amdgpu_sa_bo_hole_soffset(struct amdgpu_sa_manager *sa_manager) | |
| 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 | − } | |
| 92 | + *sa_bo = sa; | |
| 138 | 93 | return 0; |
| 139 | 94 | } |
| 140 | 95 | |
| 141 | −static inline unsigned amdgpu_sa_bo_hole_eoffset(struct amdgpu_sa_manager *sa_manager) | |
| 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, | |
| 96 | +void amdgpu_sa_bo_free(struct amdgpu_device *adev, struct drm_suballoc **sa_bo, | |
| 347 | 97 | struct dma_fence *fence) |
| 348 | 98 | { |
| 349 | − struct amdgpu_sa_manager *sa_manager; | |
| 350 | − | |
| 351 | 99 | if (sa_bo == NULL || *sa_bo == NULL) { |
| 352 | 100 | return; |
| 353 | 101 | } |
| 354 | 102 | |
| 355 | − sa_manager = (*sa_bo)->manager; | |
| 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); | |
| 103 | + drm_suballoc_free(*sa_bo, fence); | |
| 368 | 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 | 109 | void amdgpu_sa_bo_dump_debug_info(struct amdgpu_sa_manager *sa_manager, |
| 374 | 110 | struct seq_file *m) |
| 375 | 111 | { |
| 376 | − struct amdgpu_sa_bo *i; | |
| 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); | |
| 112 | + struct drm_printer p = drm_seq_file_printer(m); | |
| 389 | 113 | |
| 390 | − if (i->fence) | |
| 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); | |
| 114 | + drm_suballoc_dump_debug_info(&sa_manager->base, &p, sa_manager->gpu_addr); | |
| 397 | 115 | } |
| 398 | 116 | #endif |
| @@ -466,11 +466,7 @@ static int amdgpu_bo_move(struct ttm_buffer_object *bo, bool evict, · 465 unmodified lines | ||
| 466 | 466 | return r; |
| 467 | 467 | } |
| 468 | 468 | |
| 469 | − /* Can't move a pinned BO */ | |
| 470 | 469 | abo = ttm_to_amdgpu_bo(bo); |
| 471 | − if (WARN_ON_ONCE(abo->tbo.pin_count > 0)) | |
| 472 | − return -EINVAL; | |
| 473 | − | |
| 474 | 470 | adev = amdgpu_ttm_adev(bo->bdev); |
| 475 | 471 | |
| 476 | 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 | 649 | struct drm_device *drm = dev_get_drvdata(dev); |
| 650 | 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 | 655 | static DEVICE_ATTR_RO(core_id); |
| @@ -9,7 +9,7 @@ · 8 unmodified lines | ||
| 9 | 9 | |
| 10 | 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 | 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 | 125 | u8 bDPTX = 0; |
| 126 | 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 | 129 | // S3 come back, need more time to wait BMC ready. |
| 130 | 130 | if (bPower) |
| 131 | 131 | WaitCount = 300; |
| @@ -172,7 +172,7 @@ void ast_dp_launch(struct drm_device *dev, u8 bPower) · 40 unmodified lines | ||
| 172 | 172 | |
| 173 | 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 | 176 | // Read and Turn off DP PHY sleep |
| 177 | 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 | 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 | 192 | u8 video_on_off = on; |
| 193 | 193 | |
| 194 | 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 | 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 | 213 | u32 ulRefreshRateIndex; |
| 214 | 214 | u8 ModeIdx; |
| @@ -10,7 +10,7 @@ MODULE_FIRMWARE("ast_dp501_fw.bin"); · 9 unmodified lines | ||
| 10 | 10 | |
| 11 | 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 | 15 | release_firmware(ast->dp501_fw); |
| 16 | 16 | ast->dp501_fw = NULL; |
| @@ -18,7 +18,7 @@ static void ast_release_firmware(void *data) · 1 unmodified line | ||
| 18 | 18 | |
| 19 | 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 | 22 | int ret; |
| 23 | 23 | |
| 24 | 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 | 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 | 33 | u8 sendack; |
| 34 | 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 | 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 | 41 | u8 sendack; |
| 42 | 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 | 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 | 49 | u8 waitack; |
| 50 | 50 | u32 retry = 0; |
| @@ -60,7 +60,7 @@ static bool wait_ack(struct ast_private *ast) · 9 unmodified lines | ||
| 60 | 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 | 65 | u8 waitack; |
| 66 | 66 | u32 retry = 0; |
| @@ -76,18 +76,18 @@ static bool wait_nack(struct ast_private *ast) · 9 unmodified lines | ||
| 76 | 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 | 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 | 86 | ast_set_index_reg_mask(ast, AST_IO_CRTC_PORT, 0x9b, ~0x40, 0x00); |
| 87 | 87 | } |
| 88 | 88 | |
| 89 | 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 | 92 | u8 waitready; |
| 93 | 93 | u32 retry = 0; |
| @@ -106,7 +106,7 @@ static bool wait_fw_ready(struct ast_private *ast) · 12 unmodified lines | ||
| 106 | 106 | |
| 107 | 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 | 110 | int retry = 0; |
| 111 | 111 | if (wait_nack(ast)) { |
| 112 | 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 | 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 | 133 | if (wait_nack(ast)) { |
| 134 | 134 | send_nack(ast); |
| @@ -146,7 +146,7 @@ static bool ast_write_data(struct drm_device *dev, u8 data) · 11 unmodified lines | ||
| 146 | 146 | #if 0 |
| 147 | 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 | 150 | u8 tmp; |
| 151 | 151 | |
| 152 | 152 | *data = 0; |
| @@ -163,7 +163,7 @@ static bool ast_read_data(struct drm_device *dev, u8 *data) · 10 unmodified lines | ||
| 163 | 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 | 168 | send_nack(ast); |
| 169 | 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 | 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 | 183 | return ast_mindwm(ast, 0x1e6e2104) & 0x7fffffff; |
| 184 | 184 | } |
| 185 | 185 | |
| 186 | 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 | 189 | u32 i, data; |
| 190 | 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 | 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 | 208 | u32 i, data, len = 0; |
| 209 | 209 | u32 boot_address; |
| 210 | 210 | u8 *fw_addr = NULL; |
| @@ -274,7 +274,7 @@ static bool ast_launch_m68k(struct drm_device *dev) · 63 unmodified lines | ||
| 274 | 274 | |
| 275 | 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 | 278 | u32 i, boot_address, offset, data; |
| 279 | 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 | 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 | 338 | u8 jreg; |
| 339 | 339 | u32 data; |
| 340 | 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 | 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 | 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 | 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 | 438 | u8 jreg; |
| 439 | 439 | |
| 440 | 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 | 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 | 109 | struct drm_device *dev; |
| 110 | 110 | int ret; |
| 111 | 111 | |
| @@ -157,7 +157,7 @@ to_ast_sil164_connector(struct drm_connector *connector) · 156 unmodified lines | ||
| 157 | 157 | * Device |
| 158 | 158 | */ |
| 159 | 159 | |
| 160 | −struct ast_private { | |
| 160 | +struct ast_device { | |
| 161 | 161 | struct drm_device base; |
| 162 | 162 | |
| 163 | 163 | struct mutex ioregs_lock; /* Protects access to I/O registers in ioregs */ |
| @@ -210,14 +210,14 @@ struct ast_private { · 46 unmodified lines | ||
| 210 | 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, | |
| 219 | − struct pci_dev *pdev, | |
| 220 | − unsigned long flags); | |
| 218 | +struct ast_device *ast_device_create(const struct drm_driver *drv, | |
| 219 | + struct pci_dev *pdev, | |
| 220 | + unsigned long flags); | |
| 221 | 221 | |
| 222 | 222 | #define AST_IO_AR_PORT_WRITE (0x40) |
| 223 | 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 | 238 | #define AST_IO_VGACRCB_HWC_ENABLED BIT(1) |
| 239 | 239 | #define AST_IO_VGACRCB_HWC_16BPP BIT(0) /* set: ARGB4444, cleared: 2bpp palette */ |
| 240 | 240 | |
| 241 | −#define __ast_read(x) \ | |
| 242 | −static inline u##x ast_read##x(struct ast_private *ast, u32 reg) { \ | |
| 243 | −u##x val = 0;\ | |
| 244 | −val = ioread##x(ast->regs + reg); \ | |
| 245 | −return val;\ | |
| 241 | +static inline u32 ast_read32(struct ast_device *ast, u32 reg) | |
| 242 | +{ | |
| 243 | + return ioread32(ast->regs + reg); | |
| 246 | 244 | } |
| 247 | 245 | |
| 248 | −__ast_read(8); | |
| 249 | −__ast_read(16); | |
| 250 | −__ast_read(32) | |
| 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;\ | |
| 246 | +static inline void ast_write32(struct ast_device *ast, u32 reg, u32 val) | |
| 247 | +{ | |
| 248 | + iowrite32(val, ast->regs + reg); | |
| 257 | 249 | } |
| 258 | 250 | |
| 259 | −__ast_io_read(8); | |
| 260 | −__ast_io_read(16); | |
| 261 | −__ast_io_read(32); | |
| 262 | − | |
| 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 | − } | |
| 251 | +static inline u8 ast_io_read8(struct ast_device *ast, u32 reg) | |
| 252 | +{ | |
| 253 | + return ioread8(ast->ioregs + reg); | |
| 254 | +} | |
| 276 | 255 | |
| 277 | −__ast_io_write(8); | |
| 278 | −__ast_io_write(16); | |
| 279 | −#undef __ast_io_write | |
| 256 | +static inline void ast_io_write8(struct ast_device *ast, u32 reg, u8 val) | |
| 257 | +{ | |
| 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 | 262 | uint32_t base, uint8_t index, |
| 283 | 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 | 271 | uint32_t base, uint8_t index, |
| 290 | 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 | 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 | 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 | 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 | 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 | 339 | #define AST_MM_ALIGN_SHIFT 4 |
| 358 | 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 | 458 | #define ASTDP_1366x768_60 0x1E |
| 477 | 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 | 463 | /* ast post */ |
| 482 | 464 | void ast_enable_vga(struct drm_device *dev); |
| 483 | 465 | void ast_enable_mmio(struct drm_device *dev); |
| 484 | 466 | bool ast_is_vga_enabled(struct drm_device *dev); |
| 485 | 467 | void ast_post_gpu(struct drm_device *dev); |
| 486 | −u32 ast_mindwm(struct ast_private *ast, u32 r); | |
| 487 | −void ast_moutdwm(struct ast_private *ast, u32 r, u32 v); | |
| 488 | −void ast_patch_ahb_2500(struct ast_private *ast); | |
| 468 | +u32 ast_mindwm(struct ast_device *ast, u32 r); | |
| 469 | +void ast_moutdwm(struct ast_device *ast, u32 r, u32 v); | |
| 470 | +void ast_patch_ahb_2500(struct ast_device *ast); | |
| 489 | 471 | /* ast dp501 */ |
| 490 | 472 | void ast_set_dp501_video_output(struct drm_device *dev, u8 mode); |
| 491 | 473 | bool ast_backup_fw(struct drm_device *dev, u8 *addr, u32 size); |
| @@ -29,7 +29,7 @@ · 28 unmodified lines | ||
| 29 | 29 | static void ast_i2c_setsda(void *i2c_priv, int data) |
| 30 | 30 | { |
| 31 | 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 | 33 | int i; |
| 34 | 34 | u8 ujcrb7, jtemp; |
| 35 | 35 | |
| @@ -45,7 +45,7 @@ static void ast_i2c_setsda(void *i2c_priv, int data) · 9 unmodified lines | ||
| 45 | 45 | static void ast_i2c_setscl(void *i2c_priv, int clock) |
| 46 | 46 | { |
| 47 | 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 | 49 | int i; |
| 50 | 50 | u8 ujcrb7, jtemp; |
| 51 | 51 | |
| @@ -61,7 +61,7 @@ static void ast_i2c_setscl(void *i2c_priv, int clock) · 9 unmodified lines | ||
| 61 | 61 | static int ast_i2c_getsda(void *i2c_priv) |
| 62 | 62 | { |
| 63 | 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 | 65 | uint32_t val, val2, count, pass; |
| 66 | 66 | |
| 67 | 67 | count = 0; |
| @@ -83,7 +83,7 @@ static int ast_i2c_getsda(void *i2c_priv) · 15 unmodified lines | ||
| 83 | 83 | static int ast_i2c_getscl(void *i2c_priv) |
| 84 | 84 | { |
| 85 | 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 | 87 | uint32_t val, val2, count, pass; |
| 88 | 88 | |
| 89 | 89 | count = 0; |
| @@ -35,7 +35,7 @@ · 34 unmodified lines | ||
| 35 | 35 | |
| 36 | 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 | 39 | uint32_t base, uint8_t index, |
| 40 | 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 | 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 | 49 | uint32_t base, uint8_t index) |
| 50 | 50 | { |
| 51 | 51 | uint8_t ret; |
| @@ -54,7 +54,7 @@ uint8_t ast_get_index_reg(struct ast_private *ast, · 2 unmodified lines | ||
| 54 | 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 | 58 | uint32_t base, uint8_t index, uint8_t mask) |
| 59 | 59 | { |
| 60 | 60 | uint8_t ret; |
| @@ -66,7 +66,7 @@ uint8_t ast_get_index_reg_mask(struct ast_private *ast, · 5 unmodified lines | ||
| 66 | 66 | static void ast_detect_config_mode(struct drm_device *dev, u32 *scu_rev) |
| 67 | 67 | { |
| 68 | 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 | 70 | struct pci_dev *pdev = to_pci_dev(dev->dev); |
| 71 | 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 | 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 | 126 | struct pci_dev *pdev = to_pci_dev(dev->dev); |
| 127 | 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 | 271 | static int ast_get_dram_info(struct drm_device *dev) |
| 272 | 272 | { |
| 273 | 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 | 275 | uint32_t mcr_cfg, mcr_scu_mpll, mcr_scu_strap; |
| 276 | 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 | 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 | 399 | /* enable standard VGA decode */ |
| 400 | 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, | |
| 404 | − struct pci_dev *pdev, | |
| 405 | − unsigned long flags) | |
| 403 | +struct ast_device *ast_device_create(const struct drm_driver *drv, | |
| 404 | + struct pci_dev *pdev, | |
| 405 | + unsigned long flags) | |
| 406 | 406 | { |
| 407 | 407 | struct drm_device *dev; |
| 408 | − struct ast_private *ast; | |
| 408 | + struct ast_device *ast; | |
| 409 | 409 | bool need_post; |
| 410 | 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 | 413 | if (IS_ERR(ast)) |
| 414 | 414 | return ast; |
| 415 | 415 | dev = &ast->base; |
| @@ -33,7 +33,7 @@ · 32 unmodified lines | ||
| 33 | 33 | |
| 34 | 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 | 38 | u8 jreg; |
| 39 | 39 | u32 vram_size; |
| @@ -73,7 +73,7 @@ static u32 ast_get_vram_size(struct ast_private *ast) · 33 unmodified lines | ||
| 73 | 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 | 78 | struct drm_device *dev = &ast->base; |
| 79 | 79 | struct pci_dev *pdev = to_pci_dev(dev->dev); |
| @@ -51,7 +51,7 @@ · 50 unmodified lines | ||
| 51 | 51 | |
| 52 | 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 | 55 | u8 index, u8 red, u8 green, |
| 56 | 56 | u8 blue) |
| 57 | 57 | { |
| @@ -65,7 +65,7 @@ static inline void ast_load_palette_index(struct ast_private *ast, · 7 unmodified lines | ||
| 65 | 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 | 69 | const struct drm_format_info *format) |
| 70 | 70 | { |
| 71 | 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 | 88 | const struct drm_format_info *format, |
| 89 | 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 | 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 | 236 | const struct drm_format_info *format, |
| 237 | 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 | 267 | const struct drm_display_mode *adjusted_mode, |
| 268 | 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 | 291 | struct drm_display_mode *mode, |
| 292 | 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 | 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 | 339 | struct drm_display_mode *mode, |
| 340 | 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 | 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 | 454 | struct drm_framebuffer *fb) |
| 455 | 455 | { |
| 456 | 456 | u16 offset; |
| @@ -460,7 +460,7 @@ static void ast_set_offset_reg(struct ast_private *ast, · 3 unmodified lines | ||
| 460 | 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 | 464 | struct drm_display_mode *mode, |
| 465 | 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 | 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 | 482 | const struct drm_format_info *format) |
| 483 | 483 | { |
| 484 | 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 | 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 | 512 | /* Set Threshold */ |
| 513 | 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 | 533 | struct drm_display_mode *mode, |
| 534 | 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 | 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 | 548 | unsigned int offset) |
| 549 | 549 | { |
| 550 | 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 | 561 | unsigned long timeout = jiffies + HZ; |
| 562 | 562 | u8 vgair1; |
| @@ -645,7 +645,7 @@ static void ast_primary_plane_helper_atomic_update(struct drm_plane *plane, · 82 unmodified lines | ||
| 645 | 645 | struct drm_atomic_state *state) |
| 646 | 646 | { |
| 647 | 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 | 649 | struct drm_plane_state *plane_state = drm_atomic_get_new_plane_state(state, plane); |
| 650 | 650 | struct drm_shadow_plane_state *shadow_plane_state = to_drm_shadow_plane_state(plane_state); |
| 651 | 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 | 674 | * Some BMCs stop scanning out the video signal after the driver |
| 675 | − * reprogrammed the offset or scanout address. This stalls display | |
| 676 | − * output for several seconds and makes the display unusable. | |
| 677 | − * Therefore only update the offset if it changes and reprogram the | |
| 678 | − * address after enabling the plane. | |
| 675 | + * reprogrammed the offset. This stalls display output for several | |
| 676 | + * seconds and makes the display unusable. Therefore only update | |
| 677 | + * the offset if it changes. | |
| 679 | 678 | */ |
| 680 | 679 | if (!old_fb || old_fb->pitches[0] != fb->pitches[0]) |
| 681 | 680 | ast_set_offset_reg(ast, fb); |
| 682 | − if (!old_fb) { | |
| 683 | − ast_set_start_address_crt1(ast, (u32)ast_plane->offset); | |
| 684 | − ast_set_index_reg_mask(ast, AST_IO_SEQ_PORT, 0x1, 0xdf, 0x00); | |
| 685 | − } | |
| 681 | +} | |
| 682 | + | |
| 683 | +static void ast_primary_plane_helper_atomic_enable(struct drm_plane *plane, | |
| 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 | 699 | static void ast_primary_plane_helper_atomic_disable(struct drm_plane *plane, |
| 689 | 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 | 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 | 708 | DRM_GEM_SHADOW_PLANE_HELPER_FUNCS, |
| 698 | 709 | .atomic_check = ast_primary_plane_helper_atomic_check, |
| 699 | 710 | .atomic_update = ast_primary_plane_helper_atomic_update, |
| 711 | + .atomic_enable = ast_primary_plane_helper_atomic_enable, | |
| 700 | 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 | 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 | 724 | struct drm_device *dev = &ast->base; |
| 713 | 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 | 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 | 817 | u8 addr0 = (address >> 3) & 0xff; |
| 806 | 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 | 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 | 827 | u8 x_offset, u8 y_offset) |
| 816 | 828 | { |
| 817 | 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 | 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 | 844 | static const u8 mask = (u8)~(AST_IO_VGACRCB_HWC_16BPP | |
| 833 | 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 | 888 | struct drm_shadow_plane_state *shadow_plane_state = to_drm_shadow_plane_state(plane_state); |
| 877 | 889 | struct drm_framebuffer *fb = plane_state->fb; |
| 878 | 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 | 892 | struct iosys_map src_map = shadow_plane_state->data[0]; |
| 881 | 893 | struct drm_rect damage; |
| 882 | 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 | 943 | static void ast_cursor_plane_helper_atomic_disable(struct drm_plane *plane, |
| 932 | 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 | 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 | 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 | 967 | struct drm_device *dev = &ast->base; |
| 956 | 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 | 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 | 1011 | u8 ch = AST_DPMS_VSYNC_OFF | AST_DPMS_HSYNC_OFF; |
| 1000 | 1012 | struct ast_crtc_state *ast_state; |
| 1001 | 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 | 1064 | static enum drm_mode_status |
| 1053 | 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 | 1068 | enum drm_mode_status status; |
| 1057 | 1069 | uint32_t jtemp; |
| 1058 | 1070 | |
| @@ -1177,7 +1189,7 @@ ast_crtc_helper_atomic_flush(struct drm_crtc *crtc, · 118 unmodified lines | ||
| 1177 | 1189 | struct drm_crtc_state *crtc_state = drm_atomic_get_new_crtc_state(state, |
| 1178 | 1190 | crtc); |
| 1179 | 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 | 1193 | struct ast_crtc_state *ast_crtc_state = to_ast_crtc_state(crtc_state); |
| 1182 | 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 | 1214 | static void ast_crtc_helper_atomic_enable(struct drm_crtc *crtc, struct drm_atomic_state *state) |
| 1203 | 1215 | { |
| 1204 | 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 | 1218 | struct drm_crtc_state *crtc_state = drm_atomic_get_new_crtc_state(state, crtc); |
| 1207 | 1219 | struct ast_crtc_state *ast_crtc_state = to_ast_crtc_state(crtc_state); |
| 1208 | 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 | 1237 | struct drm_crtc_state *old_crtc_state = drm_atomic_get_old_crtc_state(state, crtc); |
| 1226 | 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 | 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 | 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 | 1328 | struct drm_crtc *crtc = &ast->crtc; |
| 1317 | 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 | 1351 | struct ast_vga_connector *ast_vga_connector = to_ast_vga_connector(connector); |
| 1340 | 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 | 1354 | struct edid *edid; |
| 1343 | 1355 | int count; |
| 1344 | 1356 | |
| @@ -1411,7 +1423,7 @@ static int ast_vga_connector_init(struct drm_device *dev, · 66 unmodified lines | ||
| 1411 | 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 | 1428 | struct drm_device *dev = &ast->base; |
| 1417 | 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 | 1457 | struct ast_sil164_connector *ast_sil164_connector = to_ast_sil164_connector(connector); |
| 1446 | 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 | 1460 | struct edid *edid; |
| 1449 | 1461 | int count; |
| 1450 | 1462 | |
| @@ -1517,7 +1529,7 @@ static int ast_sil164_connector_init(struct drm_device *dev, · 66 unmodified lines | ||
| 1517 | 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 | 1534 | struct drm_device *dev = &ast->base; |
| 1523 | 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 | 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 | 1621 | struct drm_device *dev = &ast->base; |
| 1610 | 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 | 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 | 1708 | struct drm_device *dev = &ast->base; |
| 1697 | 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 | 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 | 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 | 1754 | const struct drm_display_mode *mode) |
| 1743 | 1755 | { |
| 1744 | 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 | 1758 | unsigned long fbsize, fbpages, max_fbpages; |
| 1747 | 1759 | |
| 1748 | 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 | 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 | 1780 | struct drm_device *dev = &ast->base; |
| 1769 | 1781 | int ret; |
| @@ -39,7 +39,7 @@ static void ast_post_chip_2500(struct drm_device *dev); · 38 unmodified lines | ||
| 39 | 39 | |
| 40 | 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 | 44 | ast_io_write8(ast, AST_IO_VGA_ENABLE_PORT, 0x01); |
| 45 | 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 | 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 | 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 | 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 | 59 | u8 ch; |
| 60 | 60 | |
| 61 | 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 | 70 | static void |
| 71 | 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 | 74 | struct pci_dev *pdev = to_pci_dev(dev->dev); |
| 75 | 75 | u8 i, index, reg; |
| 76 | 76 | const u8 *ext_reg_info; |
| @@ -110,7 +110,7 @@ ast_set_def_ext_reg(struct drm_device *dev) · 33 unmodified lines | ||
| 110 | 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 | 115 | uint32_t data; |
| 116 | 116 | |
| @@ -123,7 +123,7 @@ u32 ast_mindwm(struct ast_private *ast, u32 r) · 6 unmodified lines | ||
| 123 | 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 | 128 | uint32_t data; |
| 129 | 129 | ast_write32(ast, 0xf004, r & 0xffff0000); |
| @@ -162,7 +162,7 @@ static const u32 pattern_AST2150[14] = { · 32 unmodified lines | ||
| 162 | 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 | 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 | 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 | 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 | 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 | 217 | int i; |
| 218 | 218 | |
| @@ -222,7 +222,7 @@ static int cbrtest_ast2150(struct ast_private *ast) · 3 unmodified lines | ||
| 222 | 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 | 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 | 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 | 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 | 277 | u8 j; |
| 278 | 278 | u32 data, temp, i; |
| 279 | 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 | 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 | 370 | struct pci_dev *pdev = to_pci_dev(dev->dev); |
| 371 | 371 | u32 reg; |
| 372 | 372 | |
| @@ -449,7 +449,7 @@ static const u32 pattern[8] = { · 76 unmodified lines | ||
| 449 | 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 | 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 | 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 | 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 | 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 | 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 | 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 | 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 | 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 | 520 | u32 data; |
| 521 | 521 | int i; |
| @@ -534,7 +534,7 @@ static int cbr_test(struct ast_private *ast) · 12 unmodified lines | ||
| 534 | 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 | 539 | u32 data, data2, patcnt, loop; |
| 540 | 540 | |
| @@ -555,7 +555,7 @@ static int cbr_scan(struct ast_private *ast) · 14 unmodified lines | ||
| 555 | 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 | 560 | u32 data; |
| 561 | 561 | |
| @@ -569,7 +569,7 @@ static u32 cbr_test2(struct ast_private *ast) · 7 unmodified lines | ||
| 569 | 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 | 574 | u32 data, data2, patcnt, loop; |
| 575 | 575 | |
| @@ -590,7 +590,7 @@ static u32 cbr_scan2(struct ast_private *ast) · 14 unmodified lines | ||
| 590 | 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 | 595 | if (!mmc_test_burst(ast, 0)) |
| 596 | 596 | return false; |
| @@ -599,7 +599,7 @@ static bool cbr_test3(struct ast_private *ast) · 2 unmodified lines | ||
| 599 | 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 | 604 | u32 patcnt, loop; |
| 605 | 605 | |
| @@ -615,7 +615,7 @@ static bool cbr_scan3(struct ast_private *ast) · 9 unmodified lines | ||
| 615 | 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 | 620 | u32 gold_sadj[2], dllmin[16], dllmax[16], dlli, data, cnt, mask, passcnt, retry = 0; |
| 621 | 621 | bool status = false; |
| @@ -714,7 +714,7 @@ FINETUNE_DONE: · 92 unmodified lines | ||
| 714 | 714 | return status; |
| 715 | 715 | } /* finetuneDQI_L */ |
| 716 | 716 | |
| 717 | −static void finetuneDQSI(struct ast_private *ast) | |
| 717 | +static void finetuneDQSI(struct ast_device *ast) | |
| 718 | 718 | { |
| 719 | 719 | u32 dlli, dqsip, dqidly; |
| 720 | 720 | u32 reg_mcr18, reg_mcr0c, passcnt[2], diff; |
| @@ -804,7 +804,7 @@ static void finetuneDQSI(struct ast_private *ast) · 83 unmodified lines | ||
| 804 | 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 | 809 | u32 dllmin[2], dllmax[2], dlli, data, passcnt, retry = 0; |
| 810 | 810 | bool status = false; |
| @@ -860,7 +860,7 @@ CBR_DONE2: · 49 unmodified lines | ||
| 860 | 860 | return status; |
| 861 | 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 | 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 | 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 | 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 | 1477 | u32 data, data2, retry = 0; |
| 1478 | 1478 | |
| @@ -1600,7 +1600,7 @@ ddr2_init_start: · 121 unmodified lines | ||
| 1600 | 1600 | |
| 1601 | 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 | 1604 | struct ast2300_dram_param param; |
| 1605 | 1605 | u32 temp; |
| 1606 | 1606 | u8 reg; |
| @@ -1681,7 +1681,7 @@ static void ast_post_chip_2300(struct drm_device *dev) · 74 unmodified lines | ||
| 1681 | 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 | 1686 | ast_moutdwm(ast, 0x1E6E0074, 0x0000FFFF); |
| 1687 | 1687 | ast_moutdwm(ast, 0x1E6E007C, 0xFF00FF00); |
| @@ -1692,7 +1692,7 @@ static bool cbr_test_2500(struct ast_private *ast) · 4 unmodified lines | ||
| 1692 | 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 | 1697 | ast_moutdwm(ast, 0x1E6E0074, 0x0000FFFF); |
| 1698 | 1698 | ast_moutdwm(ast, 0x1E6E007C, 0xFF00FF00); |
| @@ -1709,7 +1709,7 @@ static bool ddr_test_2500(struct ast_private *ast) · 10 unmodified lines | ||
| 1709 | 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 | 1714 | ast_moutdwm(ast, 0x1E6E0034, 0x00020080); |
| 1715 | 1715 | ast_moutdwm(ast, 0x1E6E0008, 0x2003000F); |
| @@ -1732,7 +1732,7 @@ static void ddr_init_common_2500(struct ast_private *ast) · 16 unmodified lines | ||
| 1732 | 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 | 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 | 1766 | * 4Gb : 0x80000000 ~ 0x9FFFFFFF |
| 1767 | 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 | 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 | 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 | 1802 | u32 reg_04, data; |
| 1803 | 1803 | |
| @@ -1810,7 +1810,7 @@ static void enable_cache_2500(struct ast_private *ast) · 6 unmodified lines | ||
| 1810 | 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 | 1815 | u32 addr, data, param; |
| 1816 | 1816 | |
| @@ -1837,7 +1837,7 @@ static void set_mpll_2500(struct ast_private *ast) · 20 unmodified lines | ||
| 1837 | 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 | 1842 | ast_moutdwm(ast, 0x1E78505C, 0x00000004); |
| 1843 | 1843 | ast_moutdwm(ast, 0x1E785044, 0x00000001); |
| @@ -1848,7 +1848,7 @@ static void reset_mmc_2500(struct ast_private *ast) · 4 unmodified lines | ||
| 1848 | 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 | 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 | 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 | 1897 | u32 data, data2, pass, retrycnt; |
| 1898 | 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 | 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 | 2007 | u32 data; |
| 2008 | 2008 | u32 max_tries = 5; |
| @@ -2030,7 +2030,7 @@ static bool ast_dram_init_2500(struct ast_private *ast) · 21 unmodified lines | ||
| 2030 | 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 | 2035 | u32 data; |
| 2036 | 2036 | |
| @@ -2066,7 +2066,7 @@ void ast_patch_ahb_2500(struct ast_private *ast) · 29 unmodified lines | ||
| 2066 | 2066 | |
| 2067 | 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 | 2070 | u32 temp; |
| 2071 | 2071 | u8 reg; |
| 2072 | 2072 | |
| @@ -326,7 +326,7 @@ config DRM_TI_DLPC3433 · 325 unmodified lines | ||
| 326 | 326 | input that produces a DMD output in RGB565, RGB666, RGB888 |
| 327 | 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 | 330 | rates. |
| 331 | 331 | |
| 332 | 332 | config DRM_TI_TFP410 |
| @@ -81,6 +81,8 @@ static int panel_bridge_attach(struct drm_bridge *bridge, · 80 unmodified lines | ||
| 81 | 81 | return ret; |
| 82 | 82 | } |
| 83 | 83 | |
| 84 | + drm_panel_bridge_set_orientation(connector, bridge); | |
| 85 | + | |
| 84 | 86 | drm_connector_attach_encoder(&panel_bridge->connector, |
| 85 | 87 | bridge->encoder); |
| 86 | 88 | |
| @@ -229,6 +229,7 @@ static int tc358762_probe(struct mipi_dsi_device *dsi) · 228 unmodified lines | ||
| 229 | 229 | ctx->bridge.funcs = &tc358762_bridge_funcs; |
| 230 | 230 | ctx->bridge.type = DRM_MODE_CONNECTOR_DPI; |
| 231 | 231 | ctx->bridge.of_node = dev->of_node; |
| 232 | + ctx->bridge.pre_enable_prev_first = true; | |
| 232 | 233 | |
| 233 | 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 | 2702 | funcs->atomic_disable(plane, old_state); |
| 2703 | 2703 | } else if (new_plane_state->crtc || disabling) { |
| 2704 | 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 | 2767 | struct drm_plane_state *new_plane_state = |
| 2763 | 2768 | drm_atomic_get_new_plane_state(old_state, plane); |
| 2764 | 2769 | const struct drm_plane_helper_funcs *plane_funcs; |
| 2770 | + bool disabling; | |
| 2765 | 2771 | |
| 2766 | 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 | 2777 | WARN_ON(new_plane_state->crtc && |
| 2772 | 2778 | new_plane_state->crtc != crtc); |
| 2773 | 2779 | |
| 2774 | − if (drm_atomic_plane_disabling(old_plane_state, new_plane_state) && | |
| 2775 | − plane_funcs->atomic_disable) | |
| 2780 | + disabling = drm_atomic_plane_disabling(old_plane_state, new_plane_state); | |
| 2781 | + | |
| 2782 | + if (disabling && plane_funcs->atomic_disable) { | |
| 2776 | 2783 | plane_funcs->atomic_disable(plane, old_state); |
| 2777 | − else if (new_plane_state->crtc || | |
| 2778 | − drm_atomic_plane_disabling(old_plane_state, new_plane_state)) | |
| 2784 | + } else if (new_plane_state->crtc || disabling) { | |
| 2779 | 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 | 2794 | if (crtc_funcs && crtc_funcs->atomic_flush) |
| @@ -33,9 +33,11 @@ · 32 unmodified lines | ||
| 33 | 33 | #include <drm/drm_sysfs.h> |
| 34 | 34 | #include <drm/drm_utils.h> |
| 35 | 35 | |
| 36 | −#include <linux/fb.h> | |
| 36 | +#include <linux/property.h> | |
| 37 | 37 | #include <linux/uaccess.h> |
| 38 | 38 | |
| 39 | +#include <video/cmdline.h> | |
| 40 | + | |
| 39 | 41 | #include "drm_crtc_internal.h" |
| 40 | 42 | #include "drm_internal.h" |
| 41 | 43 | |
| @@ -154,9 +156,10 @@ EXPORT_SYMBOL(drm_get_connector_type_name); · 112 unmodified lines | ||
| 154 | 156 | static void drm_connector_get_cmdline_mode(struct drm_connector *connector) |
| 155 | 157 | { |
| 156 | 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 | 163 | return; |
| 161 | 164 | |
| 162 | 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 | 1449 | * a firmware handled hotkey. Therefor userspace must not include the |
| 1447 | 1450 | * privacy-screen sw-state in an atomic commit unless it wants to change |
| 1448 | 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 | 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 | 1609 | * TODO: Document the properties: |
| 1593 | − * - left margin | |
| 1594 | − * - right margin | |
| 1595 | − * - top margin | |
| 1596 | − * - bottom margin | |
| 1597 | 1610 | * - brightness |
| 1598 | 1611 | * - contrast |
| 1599 | 1612 | * - flicker reduction |
| @@ -1602,7 +1615,6 @@ EXPORT_SYMBOL(drm_connector_attach_dp_subconnector_property); · 2 unmodified lines | ||
| 1602 | 1615 | * - overscan |
| 1603 | 1616 | * - saturation |
| 1604 | 1617 | * - select subconnector |
| 1605 | − * - subconnector | |
| 1606 | 1618 | */ |
| 1607 | 1619 | /** |
| 1608 | 1620 | * DOC: Analog TV Connector Properties |
| @@ -7,13 +7,29 @@ · 6 unmodified lines | ||
| 7 | 7 | #include <drm/drm_edid.h> |
| 8 | 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 | 26 | int i, dispid_length; |
| 13 | 27 | u8 csum = 0; |
| 14 | 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 | 34 | DRM_DEBUG_KMS("base revision 0x%x, length %d, %d %d\n", |
| 19 | 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 | 37 | /* +1 for DispID checksum */ |
| 22 | 38 | dispid_length = sizeof(*base) + base->bytes + 1; |
| 23 | 39 | if (dispid_length > length - idx) |
| 24 | − return -EINVAL; | |
| 40 | + return ERR_PTR(-EINVAL); | |
| 25 | 41 | |
| 26 | 42 | for (i = 0; i < dispid_length; i++) |
| 27 | 43 | csum += displayid[idx + i]; |
| 28 | 44 | if (csum) { |
| 29 | 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 | 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 | 56 | const u8 *displayid = drm_find_edid_extension(drm_edid, DISPLAYID_EXT, ext_index); |
| 41 | 57 | const struct displayid_header *base; |
| 42 | − int ret; | |
| 43 | 58 | |
| 44 | 59 | if (!displayid) |
| 45 | 60 | return NULL; |
| @@ -48,11 +63,10 @@ static const u8 *drm_find_displayid_extension(const struct drm_edid *drm_edid, · 2 unmodified lines | ||
| 48 | 63 | *length = EDID_LENGTH - 1; |
| 49 | 64 | *idx = 1; |
| 50 | 65 | |
| 51 | − ret = validate_displayid(displayid, *length, *idx); | |
| 52 | − if (ret) | |
| 66 | + base = validate_displayid(displayid, *length, *idx); | |
| 67 | + if (IS_ERR(base)) | |
| 53 | 68 | return NULL; |
| 54 | 69 | |
| 55 | − base = (const struct displayid_header *)&displayid[*idx]; | |
| 56 | 70 | *length = *idx + sizeof(*base) + base->bytes; |
| 57 | 71 | |
| 58 | 72 | return displayid; |
| @@ -109,6 +123,9 @@ __displayid_iter_next(struct displayid_iter *iter) · 50 unmodified lines | ||
| 109 | 123 | } |
| 110 | 124 | |
| 111 | 125 | for (;;) { |
| 126 | + /* The first section we encounter is the base section */ | |
| 127 | + bool base_section = !iter->section; | |
| 128 | + | |
| 112 | 129 | iter->section = drm_find_displayid_extension(iter->drm_edid, |
| 113 | 130 | &iter->length, |
| 114 | 131 | &iter->idx, |
| @@ -118,6 +135,18 @@ __displayid_iter_next(struct displayid_iter *iter) · 3 unmodified lines | ||
| 118 | 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 | 150 | iter->idx += sizeof(struct displayid_header); |
| 122 | 151 | |
| 123 | 152 | block = displayid_iter_block(iter); |
| @@ -130,3 +159,18 @@ void displayid_iter_end(struct displayid_iter *iter) · 6 unmodified lines | ||
| 130 | 159 | { |
| 131 | 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 | 139 | if (!dev->driver->dumb_create) |
| 140 | 140 | return -ENOSYS; |
| 141 | 141 | |
| 142 | − if (dev->driver->dumb_destroy) | |
| 143 | − return dev->driver->dumb_destroy(file_priv, dev, handle); | |
| 144 | − else | |
| 145 | − return drm_gem_dumb_destroy(file_priv, dev, handle); | |
| 142 | + return drm_gem_handle_delete(file_priv, handle); | |
| 146 | 143 | } |
| 147 | 144 | |
| 148 | 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 | 3424 | connector->base.id, connector->name); |
| 3425 | 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 | 3428 | /* it is incorrect if hsync/vsync width is zero */ |
| 3433 | 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 | 3470 | if (info->quirks & EDID_QUIRK_DETAILED_SYNC_PP) { |
| 3475 | 3471 | mode->flags |= DRM_MODE_FLAG_PHSYNC | DRM_MODE_FLAG_PVSYNC; |
| 3476 | 3472 | } else { |
| 3477 | − mode->flags |= (pt->misc & DRM_EDID_PT_HSYNC_POSITIVE) ? | |
| 3478 | − DRM_MODE_FLAG_PHSYNC : DRM_MODE_FLAG_NHSYNC; | |
| 3479 | − mode->flags |= (pt->misc & DRM_EDID_PT_VSYNC_POSITIVE) ? | |
| 3480 | − DRM_MODE_FLAG_PVSYNC : DRM_MODE_FLAG_NVSYNC; | |
| 3473 | + switch (pt->misc & DRM_EDID_PT_SYNC_MASK) { | |
| 3474 | + case DRM_EDID_PT_ANALOG_CSYNC: | |
| 3475 | + case DRM_EDID_PT_BIPOLAR_ANALOG_CSYNC: | |
| 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 | 3496 | set_size: |
| @@ -6433,6 +6446,29 @@ static void drm_reset_display_info(struct drm_connector *connector) · 2949 unmodified lines | ||
| 6433 | 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 | 6472 | static void update_display_info(struct drm_connector *connector, |
| 6437 | 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 | 6499 | info->color_formats |= DRM_COLOR_FORMAT_RGB444; |
| 6464 | 6500 | drm_parse_cea_ext(connector, drm_edid); |
| 6465 | 6501 | |
| 6502 | + update_displayid_info(connector, drm_edid); | |
| 6503 | + | |
| 6466 | 6504 | /* |
| 6467 | 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 | 7292 | static void _drm_update_tile_info(struct drm_connector *connector, |
| 7246 | 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 | 7300 | displayid_iter_edid_begin(drm_edid, &iter); |
| 7254 | 7301 | displayid_iter_for_each(block, &iter) { |
| 7255 | − if (block->tag == DATA_BLOCK_TILED_DISPLAY) | |
| 7302 | + if (displayid_is_tiled_block(&iter, block)) | |
| 7256 | 7303 | drm_parse_tiled_block(connector, block); |
| 7257 | 7304 | } |
| 7258 | 7305 | displayid_iter_end(&iter); |
| @@ -336,13 +336,6 @@ out: · 335 unmodified lines | ||
| 336 | 336 | } |
| 337 | 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 | 340 | * drm_gem_handle_create_tail - internal functions to create a handle |
| 348 | 341 | * @file_priv: drm file-private structure to register the handle for |
| @@ -1466,3 +1459,21 @@ tail: · 1117 unmodified lines | ||
| 1466 | 1459 | return freed; |
| 1467 | 1460 | } |
| 1468 | 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 | 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 | 146 | if (obj->import_attach) { |
| 147 | 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 | 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 | 161 | drm_gem_object_release(obj); |
| 162 | 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 | 176 | pages = drm_gem_get_pages(obj); |
| 177 | 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 | 180 | shmem->pages_use_count = 0; |
| 180 | 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 | 209 | int drm_gem_shmem_get_pages(struct drm_gem_shmem_object *shmem) |
| 209 | 210 | { |
| 211 | + struct drm_gem_object *obj = &shmem->base; | |
| 210 | 212 | int ret; |
| 211 | 213 | |
| 212 | − WARN_ON(shmem->base.import_attach); | |
| 214 | + drm_WARN_ON(obj->dev, obj->import_attach); | |
| 213 | 215 | |
| 214 | 216 | ret = mutex_lock_interruptible(&shmem->pages_lock); |
| 215 | 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 | 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 | 231 | return; |
| 230 | 232 | |
| 231 | 233 | if (--shmem->pages_use_count > 0) |
| @@ -268,7 +270,9 @@ EXPORT_SYMBOL(drm_gem_shmem_put_pages); · 36 unmodified lines | ||
| 268 | 270 | */ |
| 269 | 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 | 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 | 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 | 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 | 301 | struct drm_gem_object *obj = &shmem->base; |
| 296 | 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 | 304 | if (obj->import_attach) { |
| 304 | 305 | ret = dma_buf_vmap(obj->import_attach->dmabuf, map); |
| 305 | 306 | if (!ret) { |
| 306 | − if (WARN_ON(map->is_iomem)) { | |
| 307 | + if (drm_WARN_ON(obj->dev, map->is_iomem)) { | |
| 307 | 308 | dma_buf_vunmap(obj->import_attach->dmabuf, map); |
| 308 | − ret = -EIO; | |
| 309 | − goto err_put_pages; | |
| 309 | + return -EIO; | |
| 310 | 310 | } |
| 311 | − shmem->vaddr = map->vaddr; | |
| 312 | 311 | } |
| 313 | 312 | } else { |
| 314 | 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 | 320 | ret = drm_gem_shmem_get_pages(shmem); |
| 317 | 321 | if (ret) |
| 318 | 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 | 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 | 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 | 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 | 385 | if (obj->import_attach) { |
| 388 | 386 | dma_buf_vunmap(obj->import_attach->dmabuf, map); |
| 389 | 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 | 394 | vunmap(shmem->vaddr); |
| 391 | 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 | 465 | struct drm_gem_object *obj = &shmem->base; |
| 462 | 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 | 470 | dma_unmap_sgtable(dev->dev, shmem->sgt, DMA_BIDIRECTIONAL, 0); |
| 467 | 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 | 554 | mutex_lock(&shmem->pages_lock); |
| 551 | 555 | |
| 552 | 556 | if (page_offset >= num_pages || |
| 553 | − WARN_ON_ONCE(!shmem->pages) || | |
| 557 | + drm_WARN_ON_ONCE(obj->dev, !shmem->pages) || | |
| 554 | 558 | shmem->madv < 0) { |
| 555 | 559 | ret = VM_FAULT_SIGBUS; |
| 556 | 560 | } else { |
| @@ -569,7 +573,7 @@ static void drm_gem_shmem_vm_open(struct vm_area_struct *vma) · 12 unmodified lines | ||
| 569 | 573 | struct drm_gem_object *obj = vma->vm_private_data; |
| 570 | 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 | 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 | 582 | * mmap'd, vm_open() just grabs an additional reference for the new |
| 579 | 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 | 586 | shmem->pages_use_count++; |
| 583 | 587 | |
| 584 | 588 | mutex_unlock(&shmem->pages_lock); |
| @@ -648,6 +652,9 @@ EXPORT_SYMBOL_GPL(drm_gem_shmem_mmap); · 63 unmodified lines | ||
| 648 | 652 | void drm_gem_shmem_print_info(const struct drm_gem_shmem_object *shmem, |
| 649 | 653 | struct drm_printer *p, unsigned int indent) |
| 650 | 654 | { |
| 655 | + if (shmem->base.import_attach) | |
| 656 | + return; | |
| 657 | + | |
| 651 | 658 | drm_printf_indent(p, indent, "pages_use_count=%u\n", shmem->pages_use_count); |
| 652 | 659 | drm_printf_indent(p, indent, "vmap_use_count=%u\n", shmem->vmap_use_count); |
| 653 | 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 | 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 | 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 | 694 | if (shmem->sgt) |
| 688 | 695 | return shmem->sgt; |
| 689 | 696 | |
| 690 | − WARN_ON(obj->import_attach); | |
| 697 | + drm_WARN_ON(obj->dev, obj->import_attach); | |
| 691 | 698 | |
| 692 | 699 | ret = drm_gem_shmem_get_pages_locked(shmem); |
| 693 | 700 | if (ret) |
| @@ -916,6 +916,17 @@ static int bo_driver_move(struct ttm_buffer_object *bo, · 915 unmodified lines | ||
| 916 | 916 | { |
| 917 | 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 | 930 | gbo = drm_gem_vram_of_bo(bo); |
| 920 | 931 | |
| 921 | 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 | 178 | int drm_gem_vmap(struct drm_gem_object *obj, struct iosys_map *map); |
| 179 | 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 | 181 | /* drm_debugfs.c drm_debugfs_crc.c */ |
| 185 | 182 | #if defined(CONFIG_DEBUG_FS) |
| 186 | 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 | 2339 | * @mode: preallocated drm_cmdline_mode structure to fill out |
| 2340 | 2340 | * |
| 2341 | 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 | |
| 2343 | − * modeline in fb_mode_option will be parsed instead. | |
| 2342 | + * configure the connector. | |
| 2344 | 2343 | * |
| 2345 | 2344 | * This uses the same parameters as the fb modedb.c, except for an extra |
| 2346 | 2345 | * force-enable, force-enable-digital and force-disable bit at the end:: |
| @@ -10,6 +10,7 @@ · 9 unmodified lines | ||
| 10 | 10 | #include <drm/drm_crtc.h> |
| 11 | 11 | #include <drm/drm_device.h> |
| 12 | 12 | #include <drm/drm_encoder.h> |
| 13 | +#include <drm/drm_mipi_dsi.h> | |
| 13 | 14 | #include <drm/drm_of.h> |
| 14 | 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 | 494 | return ret; |
| 494 | 495 | } |
| 495 | 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 | 591 | dev->mode_config.delayed_event = true; |
| 592 | 592 | if (dev->mode_config.poll_enabled) |
| 593 | − schedule_delayed_work(&dev->mode_config.output_poll_work, | |
| 594 | − 0); | |
| 593 | + mod_delayed_work(system_wq, | |
| 594 | + &dev->mode_config.output_poll_work, | |
| 595 | + 0); | |
| 595 | 596 | } |
| 596 | 597 | |
| 597 | 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 | 472 | struct ttm_placement place = {}; |
| 473 | 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 | 476 | return 0; |
| 477 | 477 | |
| 478 | 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 | 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 | 521 | __i915_gem_object_pages_fini(obj); |
| 516 | 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 | 1073 | .interruptible = true, |
| 1068 | 1074 | .no_wait_gpu = true, /* should be idle already */ |
| 1069 | 1075 | }; |
| 1076 | + int err; | |
| 1070 | 1077 | |
| 1071 | 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); | |
| 1074 | − if (ret) { | |
| 1080 | + err = ttm_bo_validate(bo, i915_ttm_sys_placement(), &ctx); | |
| 1081 | + if (err) { | |
| 1075 | 1082 | dma_resv_unlock(bo->base.resv); |
| 1076 | 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 | 98 | static inline bool i915_ttm_cpu_maps_iomem(struct ttm_resource *mem) |
| 99 | 99 | { |
| 100 | 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 | 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 | 712 | assert_object_held(dst); |
| 713 | 713 | assert_object_held(src); |
| 714 | + | |
| 715 | + if (GEM_WARN_ON(!src_bo->resource || !dst_bo->resource)) | |
| 716 | + return -EINVAL; | |
| 717 | + | |
| 714 | 718 | i915_deps_init(&deps, GFP_KERNEL | __GFP_NORETRY | __GFP_NOWARN); |
| 715 | 719 | |
| 716 | 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 | 53 | unsigned int flags; |
| 54 | 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 | 57 | return 0; |
| 58 | 58 | |
| 59 | 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 | 187 | return err; |
| 188 | 188 | |
| 189 | 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 | 194 | if (!err) { |
| 192 | 195 | err = i915_gem_obj_copy_ttm(obj, backup, pm_apply->allow_gpu, |
| 193 | 196 | false); |
| @@ -866,10 +866,10 @@ meson_venc_hdmi_supported_mode(const struct drm_display_mode *mode) · 865 unmodified lines | ||
| 866 | 866 | DRM_MODE_FLAG_PVSYNC | DRM_MODE_FLAG_NVSYNC)) |
| 867 | 867 | return MODE_BAD; |
| 868 | 868 | |
| 869 | − if (mode->hdisplay < 640 || mode->hdisplay > 1920) | |
| 869 | + if (mode->hdisplay < 400 || mode->hdisplay > 1920) | |
| 870 | 870 | return MODE_BAD_HVALUE; |
| 871 | 871 | |
| 872 | − if (mode->vdisplay < 480 || mode->vdisplay > 1200) | |
| 872 | + if (mode->vdisplay < 480 || mode->vdisplay > 1920) | |
| 873 | 873 | return MODE_BAD_VVALUE; |
| 874 | 874 | |
| 875 | 875 | return MODE_OK; |
| @@ -375,12 +375,15 @@ int mgag200_primary_plane_helper_atomic_check(struct drm_plane *plane, · 374 unmodified lines | ||
| 375 | 375 | struct drm_atomic_state *new_state); |
| 376 | 376 | void mgag200_primary_plane_helper_atomic_update(struct drm_plane *plane, |
| 377 | 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 | 380 | void mgag200_primary_plane_helper_atomic_disable(struct drm_plane *plane, |
| 379 | 381 | struct drm_atomic_state *old_state); |
| 380 | 382 | #define MGAG200_PRIMARY_PLANE_HELPER_FUNCS \ |
| 381 | 383 | DRM_GEM_SHADOW_PLANE_HELPER_FUNCS, \ |
| 382 | 384 | .atomic_check = mgag200_primary_plane_helper_atomic_check, \ |
| 383 | 385 | .atomic_update = mgag200_primary_plane_helper_atomic_update, \ |
| 386 | + .atomic_enable = mgag200_primary_plane_helper_atomic_enable, \ | |
| 384 | 387 | .atomic_disable = mgag200_primary_plane_helper_atomic_disable |
| 385 | 388 | |
| 386 | 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 | 501 | struct drm_framebuffer *fb = plane_state->fb; |
| 502 | 502 | struct drm_atomic_helper_damage_iter iter; |
| 503 | 503 | struct drm_rect damage; |
| 504 | − u8 seq1; | |
| 505 | − | |
| 506 | − if (!fb) | |
| 507 | − return; | |
| 508 | 504 | |
| 509 | 505 | drm_atomic_helper_damage_iter_init(&iter, old_plane_state, plane_state); |
| 510 | 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 | 510 | /* Always scanout image at VRAM offset 0 */ |
| 515 | 511 | mgag200_set_startadd(mdev, (u32)0); |
| 516 | 512 | mgag200_set_offset(mdev, fb); |
| 513 | +} | |
| 517 | 514 | |
| 518 | − if (!old_plane_state->crtc && plane_state->crtc) { // enabling | |
| 519 | − RREG_SEQ(0x01, seq1); | |
| 520 | − seq1 &= ~MGAREG_SEQ1_SCROFF; | |
| 521 | − WREG_SEQ(0x01, seq1); | |
| 522 | − msleep(20); | |
| 523 | − } | |
| 515 | +void mgag200_primary_plane_helper_atomic_enable(struct drm_plane *plane, | |
| 516 | + struct drm_atomic_state *state) | |
| 517 | +{ | |
| 518 | + struct drm_device *dev = plane->dev; | |
| 519 | + struct mga_device *mdev = to_mga_device(dev); | |
| 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 | 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 | 1015 | if (ret) |
| 1016 | 1016 | goto out_ntfy; |
| 1017 | 1017 | |
| 1018 | − if (nvbo->bo.pin_count) | |
| 1019 | − NV_WARN(drm, "Moving pinned object %p!\n", nvbo); | |
| 1020 | − | |
| 1021 | 1018 | if (drm->client.device.info.family < NV_DEVICE_INFO_V0_TESLA) { |
| 1022 | 1019 | ret = nouveau_bo_vm_bind(bo, new_reg, &new_tile); |
| 1023 | 1020 | if (ret) |
| @@ -41,7 +41,7 @@ static ssize_t · 40 unmodified lines | ||
| 41 | 41 | nouveau_hwmon_show_temp1_auto_point1_pwm(struct device *d, |
| 42 | 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 | 46 | static SENSOR_DEVICE_ATTR(temp1_auto_point1_pwm, 0444, |
| 47 | 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 | 54 | struct nouveau_drm *drm = nouveau_drm(dev); |
| 55 | 55 | struct nvkm_therm *therm = nvxx_therm(&drm->client.device); |
| 56 | 56 | |
| 57 | − return snprintf(buf, PAGE_SIZE, "%d\n", | |
| 58 | − therm->attr_get(therm, NVKM_THERM_ATTR_THRS_FAN_BOOST) * 1000); | |
| 57 | + return sysfs_emit(buf, "%d\n", | |
| 58 | + therm->attr_get(therm, NVKM_THERM_ATTR_THRS_FAN_BOOST) * 1000); | |
| 59 | 59 | } |
| 60 | 60 | static ssize_t |
| 61 | 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 | 87 | struct nouveau_drm *drm = nouveau_drm(dev); |
| 88 | 88 | struct nvkm_therm *therm = nvxx_therm(&drm->client.device); |
| 89 | 89 | |
| 90 | − return snprintf(buf, PAGE_SIZE, "%d\n", | |
| 91 | − therm->attr_get(therm, NVKM_THERM_ATTR_THRS_FAN_BOOST_HYST) * 1000); | |
| 90 | + return sysfs_emit(buf, "%d\n", | |
| 91 | + therm->attr_get(therm, NVKM_THERM_ATTR_THRS_FAN_BOOST_HYST) * 1000); | |
| 92 | 92 | } |
| 93 | 93 | static ssize_t |
| 94 | 94 | nouveau_hwmon_set_temp1_auto_point1_temp_hyst(struct device *d, |
| @@ -27,7 +27,7 @@ · 26 unmodified lines | ||
| 27 | 27 | |
| 28 | 28 | #include "nouveau_drv.h" |
| 29 | 29 | |
| 30 | −struct led_classdev; | |
| 30 | +#include <linux/leds.h> | |
| 31 | 31 | |
| 32 | 32 | struct nouveau_led { |
| 33 | 33 | struct drm_device *dev; |
| @@ -318,6 +318,17 @@ config DRM_PANEL_LG_LG4573 · 317 unmodified lines | ||
| 318 | 318 | Say Y here if you want to enable support for LG4573 RGB panel. |
| 319 | 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 | 332 | config DRM_PANEL_NEC_NL8048HL11 |
| 322 | 333 | tristate "NEC NL8048HL11 RGB panel" |
| 323 | 334 | depends on GPIOLIB && OF && SPI |
| @@ -29,6 +29,7 @@ obj-$(CONFIG_DRM_PANEL_LEADTEK_LTK050H3146W) += panel-leadtek-ltk050h3146w.o · 28 unmodified lines | ||
| 29 | 29 | obj-$(CONFIG_DRM_PANEL_LEADTEK_LTK500HD1829) += panel-leadtek-ltk500hd1829.o |
| 30 | 30 | obj-$(CONFIG_DRM_PANEL_LG_LB035Q02) += panel-lg-lb035q02.o |
| 31 | 31 | obj-$(CONFIG_DRM_PANEL_LG_LG4573) += panel-lg-lg4573.o |
| 32 | +obj-$(CONFIG_DRM_PANEL_MAGNACHIP_D53E6EA8966) += panel-magnachip-d53e6ea8966.o | |
| 32 | 33 | obj-$(CONFIG_DRM_PANEL_NEC_NL8048HL11) += panel-nec-nl8048hl11.o |
| 33 | 34 | obj-$(CONFIG_DRM_PANEL_NEWVISION_NV3051D) += panel-newvision-nv3051d.o |
| 34 | 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 | 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 | 366 | static const struct jadard_init_cmd cz101b4001_init_cmds[] = { |
| 171 | 367 | { .data = { 0xE0, 0x00 } }, |
| 172 | 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 | 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 | 663 | { /* sentinel */ } |
| 457 | 664 | }; |
| 458 | 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 | 222 | for (i = 0; i < in_fence_count; i++) { |
| 223 | − struct dma_fence *fence; | |
| 224 | − | |
| 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 | − | |
| 223 | + ret = drm_sched_job_add_syncobj_dependency(&job->base, file_priv, | |
| 224 | + handles[i], 0); | |
| 232 | 225 | if (ret) |
| 233 | 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 | 143 | struct ttm_resource *old_mem = bo->resource; |
| 144 | 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 | 157 | qxl_bo_move_notify(bo, new_mem); |
| 147 | 158 | |
| 148 | 159 | ret = ttm_bo_wait_ctx(bo, ctx); |
| @@ -8,6 +8,7 @@ config DRM_RADEON · 7 unmodified lines | ||
| 8 | 8 | select DRM_DISPLAY_DP_HELPER |
| 9 | 9 | select DRM_DISPLAY_HELPER |
| 10 | 10 | select DRM_KMS_HELPER |
| 11 | + select DRM_SUBALLOC_HELPER | |
| 11 | 12 | select DRM_TTM |
| 12 | 13 | select DRM_TTM_HELPER |
| 13 | 14 | select SND_HDA_COMPONENT if SND_HDA_CORE |
| @@ -79,6 +79,7 @@ · 78 unmodified lines | ||
| 79 | 79 | |
| 80 | 80 | #include <drm/drm_gem.h> |
| 81 | 81 | #include <drm/drm_audio_component.h> |
| 82 | +#include <drm/drm_suballoc.h> | |
| 82 | 83 | |
| 83 | 84 | #include "radeon_family.h" |
| 84 | 85 | #include "radeon_mode.h" |
| @@ -511,52 +512,12 @@ struct radeon_bo { · 426 unmodified lines | ||
| 511 | 512 | }; |
| 512 | 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 | 515 | struct radeon_sa_manager { |
| 538 | − wait_queue_head_t wq; | |
| 539 | − struct radeon_bo *bo; | |
| 540 | − struct list_head *hole; | |
| 541 | − struct list_head flist[RADEON_NUM_RINGS]; | |
| 542 | − struct list_head olist; | |
| 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; | |
| 516 | + struct drm_suballoc_manager base; | |
| 517 | + struct radeon_bo *bo; | |
| 518 | + uint64_t gpu_addr; | |
| 519 | + void *cpu_ptr; | |
| 520 | + u32 domain; | |
| 560 | 521 | }; |
| 561 | 522 | |
| 562 | 523 | /* |
| @@ -587,7 +548,7 @@ int radeon_mode_dumb_mmap(struct drm_file *filp, · 24 unmodified lines | ||
| 587 | 548 | * Semaphores. |
| 588 | 549 | */ |
| 589 | 550 | struct radeon_semaphore { |
| 590 | − struct radeon_sa_bo *sa_bo; | |
| 551 | + struct drm_suballoc *sa_bo; | |
| 591 | 552 | signed waiters; |
| 592 | 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 | 779 | struct radeon_ib { |
| 819 | − struct radeon_sa_bo *sa_bo; | |
| 780 | + struct drm_suballoc *sa_bo; | |
| 820 | 781 | uint32_t length_dw; |
| 821 | 782 | uint64_t gpu_addr; |
| 822 | 783 | uint32_t *ptr; |
| @@ -61,7 +61,7 @@ int radeon_ib_get(struct radeon_device *rdev, int ring, · 60 unmodified lines | ||
| 61 | 61 | { |
| 62 | 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 | 65 | if (r) { |
| 66 | 66 | dev_err(rdev->dev, "failed to get a new IB (%d)\n", r); |
| 67 | 67 | return r; |
| @@ -77,7 +77,7 @@ int radeon_ib_get(struct radeon_device *rdev, int ring, · 9 unmodified lines | ||
| 77 | 77 | /* ib pool is bound at RADEON_VA_IB_OFFSET in virtual address |
| 78 | 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 | 81 | } else { |
| 82 | 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 | 97 | void radeon_ib_free(struct radeon_device *rdev, struct radeon_ib *ib) |
| 98 | 98 | { |
| 99 | 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 | 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 | 202 | if (rdev->family >= CHIP_BONAIRE) { |
| 203 | 203 | r = radeon_sa_bo_manager_init(rdev, &rdev->ring_tmp_bo, |
| 204 | − RADEON_IB_POOL_SIZE*64*1024, | |
| 205 | − RADEON_GPU_PAGE_SIZE, | |
| 204 | + RADEON_IB_POOL_SIZE*64*1024, 256, | |
| 206 | 205 | RADEON_GEM_DOMAIN_GTT, |
| 207 | 206 | RADEON_GEM_GTT_WC); |
| 208 | 207 | } else { |
| @@ -210,8 +209,7 @@ int radeon_ib_pool_init(struct radeon_device *rdev) · 1 unmodified line | ||
| 210 | 209 | * to the command stream checking |
| 211 | 210 | */ |
| 212 | 211 | r = radeon_sa_bo_manager_init(rdev, &rdev->ring_tmp_bo, |
| 213 | − RADEON_IB_POOL_SIZE*64*1024, | |
| 214 | − RADEON_GPU_PAGE_SIZE, | |
| 212 | + RADEON_IB_POOL_SIZE*64*1024, 256, | |
| 215 | 213 | RADEON_GEM_DOMAIN_GTT, 0); |
| 216 | 214 | } |
| 217 | 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 | 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 | 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 | 197 | struct radeon_sa_manager *sa_manager); |
| 191 | 198 | extern int radeon_sa_bo_manager_suspend(struct radeon_device *rdev, |
| 192 | 199 | struct radeon_sa_manager *sa_manager); |
| 193 | −extern int radeon_sa_bo_new(struct radeon_device *rdev, | |
| 194 | − struct radeon_sa_manager *sa_manager, | |
| 195 | − struct radeon_sa_bo **sa_bo, | |
| 196 | − unsigned size, unsigned align); | |
| 197 | −extern void radeon_sa_bo_free(struct radeon_device *rdev, | |
| 198 | − struct radeon_sa_bo **sa_bo, | |
| 200 | +extern int radeon_sa_bo_new(struct radeon_sa_manager *sa_manager, | |
| 201 | + struct drm_suballoc **sa_bo, | |
| 202 | + unsigned int size, unsigned int align); | |
| 203 | +extern void radeon_sa_bo_free(struct drm_suballoc **sa_bo, | |
| 199 | 204 | struct radeon_fence *fence); |
| 200 | 205 | #if defined(CONFIG_DEBUG_FS) |
| 201 | 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 | 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 | 47 | int radeon_sa_bo_manager_init(struct radeon_device *rdev, |
| 51 | 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; | |
| 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 | − } | |
| 52 | + int r; | |
| 66 | 53 | |
| 67 | − r = radeon_bo_create(rdev, size, align, true, | |
| 54 | + r = radeon_bo_create(rdev, size, RADEON_GPU_PAGE_SIZE, true, | |
| 68 | 55 | domain, flags, NULL, NULL, &sa_manager->bo); |
| 69 | 56 | if (r) { |
| 70 | 57 | dev_err(rdev->dev, "(%d) failed to allocate bo for manager\n", r); |
| 71 | 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 | 65 | return r; |
| 75 | 66 | } |
| 76 | 67 | |
| 77 | 68 | void radeon_sa_bo_manager_fini(struct radeon_device *rdev, |
| 78 | 69 | struct radeon_sa_manager *sa_manager) |
| 79 | 70 | { |
| 80 | − struct radeon_sa_bo *sa_bo, *tmp; | |
| 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 | − } | |
| 71 | + drm_suballoc_manager_fini(&sa_manager->base); | |
| 92 | 72 | radeon_bo_unref(&sa_manager->bo); |
| 93 | − sa_manager->size = 0; | |
| 94 | 73 | } |
| 95 | 74 | |
| 96 | 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 | 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; | |
| 145 | − if (sa_manager->hole == &sa_bo->olist) { | |
| 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; | |
| 125 | + struct drm_suballoc *sa = drm_suballoc_new(&sa_manager->base, size, | |
| 126 | + GFP_KERNEL, true, align); | |
| 160 | 127 | |
| 161 | − sa_bo = list_entry(sa_manager->hole->next, struct radeon_sa_bo, olist); | |
| 162 | − list_for_each_entry_safe_from(sa_bo, tmp, &sa_manager->olist, olist) { | |
| 163 | − if (sa_bo->fence == NULL || !radeon_fence_signaled(sa_bo->fence)) { | |
| 164 | − return; | |
| 165 | − } | |
| 166 | − radeon_sa_bo_remove_locked(sa_bo); | |
| 128 | + if (IS_ERR(sa)) { | |
| 129 | + *sa_bo = NULL; | |
| 130 | + return PTR_ERR(sa); | |
| 167 | 131 | } |
| 168 | −} | |
| 169 | 132 | |
| 170 | −static inline unsigned radeon_sa_bo_hole_soffset(struct radeon_sa_manager *sa_manager) | |
| 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 | − } | |
| 133 | + *sa_bo = sa; | |
| 177 | 134 | return 0; |
| 178 | 135 | } |
| 179 | 136 | |
| 180 | −static inline unsigned radeon_sa_bo_hole_eoffset(struct radeon_sa_manager *sa_manager) | |
| 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, | |
| 137 | +void radeon_sa_bo_free(struct drm_suballoc **sa_bo, | |
| 377 | 138 | struct radeon_fence *fence) |
| 378 | 139 | { |
| 379 | − struct radeon_sa_manager *sa_manager; | |
| 380 | − | |
| 381 | 140 | if (sa_bo == NULL || *sa_bo == NULL) { |
| 382 | 141 | return; |
| 383 | 142 | } |
| 384 | 143 | |
| 385 | − sa_manager = (*sa_bo)->manager; | |
| 386 | − spin_lock(&sa_manager->wq.lock); | |
| 387 | − if (fence && !radeon_fence_signaled(fence)) { | |
| 388 | − (*sa_bo)->fence = radeon_fence_ref(fence); | |
| 389 | − list_add_tail(&(*sa_bo)->flist, | |
| 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); | |
| 144 | + if (fence) | |
| 145 | + drm_suballoc_free(*sa_bo, &fence->base); | |
| 146 | + else | |
| 147 | + drm_suballoc_free(*sa_bo, NULL); | |
| 148 | + | |
| 396 | 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 | 153 | void radeon_sa_bo_dump_debug_info(struct radeon_sa_manager *sa_manager, |
| 401 | 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); | |
| 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); | |
| 158 | + drm_suballoc_dump_debug_info(&sa_manager->base, &p, sa_manager->gpu_addr); | |
| 423 | 159 | } |
| 424 | 160 | #endif |
| @@ -40,7 +40,7 @@ int radeon_semaphore_create(struct radeon_device *rdev, · 39 unmodified lines | ||
| 40 | 40 | if (*semaphore == NULL) { |
| 41 | 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 | 44 | &(*semaphore)->sa_bo, 8, 8); |
| 45 | 45 | if (r) { |
| 46 | 46 | kfree(*semaphore); |
| @@ -100,7 +100,7 @@ void radeon_semaphore_free(struct radeon_device *rdev, · 53 unmodified lines | ||
| 100 | 100 | dev_err(rdev->dev, "semaphore %p has more waiters than signalers," |
| 101 | 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 | 104 | kfree(*semaphore); |
| 105 | 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 | 211 | if (r) |
| 212 | 212 | return r; |
| 213 | 213 | |
| 214 | − /* Can't move a pinned BO */ | |
| 215 | 214 | rbo = container_of(bo, struct radeon_bo, tbo); |
| 216 | − if (WARN_ON_ONCE(rbo->tbo.pin_count > 0)) | |
| 217 | − return -EINVAL; | |
| 218 | − | |
| 219 | 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 | 218 | ttm_bo_move_null(bo, new_mem); |
| 222 | 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 | 261 | else |
| 262 | 262 | ret = rockchip_drm_gem_object_mmap_dma(obj, vma); |
| 263 | 263 | |
| 264 | − if (ret) | |
| 265 | − drm_gem_vm_close(vma); | |
| 266 | − | |
| 267 | 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 | 515 | struct rockchip_gem_object *rk_obj = to_rockchip_obj(obj); |
| 519 | 516 | |
| 520 | 517 | if (rk_obj->pages) { |
| 521 | − void *vaddr = vmap(rk_obj->pages, rk_obj->num_pages, VM_MAP, | |
| 522 | − pgprot_writecombine(PAGE_KERNEL)); | |
| 518 | + void *vaddr; | |
| 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 | 526 | if (!vaddr) |
| 524 | 527 | return -ENOMEM; |
| 525 | 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 | 542 | struct rockchip_gem_object *rk_obj = to_rockchip_obj(obj); |
| 540 | 543 | |
| 541 | 544 | if (rk_obj->pages) { |
| 542 | − vunmap(map->vaddr); | |
| 545 | + if (map->vaddr != rk_obj->kvaddr) | |
| 546 | + vunmap(map->vaddr); | |
| 543 | 547 | return; |
| 544 | 548 | } |
| 545 | 549 | |
| @@ -316,13 +316,10 @@ static int vop_convert_afbc_format(uint32_t format) · 315 unmodified lines | ||
| 316 | 316 | case DRM_FORMAT_RGB565: |
| 317 | 317 | case DRM_FORMAT_BGR565: |
| 318 | 318 | return AFBC_FMT_RGB565; |
| 319 | − /* either of the below should not be reachable */ | |
| 320 | 319 | default: |
| 321 | − DRM_WARN_ONCE("unsupported AFBC format[%08x]\n", format); | |
| 320 | + DRM_DEBUG_KMS("unsupported AFBC format[%08x]\n", format); | |
| 322 | 321 | return -EINVAL; |
| 323 | 322 | } |
| 324 | − | |
| 325 | − return -EINVAL; | |
| 326 | 323 | } |
| 327 | 324 | |
| 328 | 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 | 2218 | goto err_disable_pm_runtime; |
| 2222 | 2219 | |
| 2223 | 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 | 2222 | if (IS_ERR(vop->rgb)) { |
| 2226 | 2223 | ret = PTR_ERR(vop->rgb); |
| 2227 | 2224 | goto err_disable_pm_runtime; |
| @@ -38,6 +38,7 @@ · 37 unmodified lines | ||
| 38 | 38 | #include "rockchip_drm_gem.h" |
| 39 | 39 | #include "rockchip_drm_fb.h" |
| 40 | 40 | #include "rockchip_drm_vop2.h" |
| 41 | +#include "rockchip_rgb.h" | |
| 41 | 42 | |
| 42 | 43 | /* |
| 43 | 44 | * VOP2 architecture |
| @@ -211,6 +212,9 @@ struct vop2 { · 167 unmodified lines | ||
| 211 | 212 | struct clk *hclk; |
| 212 | 213 | struct clk *aclk; |
| 213 | 214 | |
| 215 | + /* optional internal rgb encoder */ | |
| 216 | + struct rockchip_rgb *rgb; | |
| 217 | + | |
| 214 | 218 | /* must be put at the end of the struct */ |
| 215 | 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 | 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 | 2254 | const struct vop2_data *vop2_data = vop2->data; |
| 2251 | 2255 | struct drm_device *drm = vop2->drm; |
| @@ -2321,10 +2325,11 @@ static int vop2_create_crtc(struct vop2 *vop2) · 69 unmodified lines | ||
| 2321 | 2325 | /* change the unused primary window to overlay window */ |
| 2322 | 2326 | win->type = DRM_PLANE_TYPE_OVERLAY; |
| 2323 | 2327 | } |
| 2324 | − } | |
| 2325 | − | |
| 2326 | − if (win->type == DRM_PLANE_TYPE_OVERLAY) | |
| 2328 | + } else if (win->type == DRM_PLANE_TYPE_OVERLAY) { | |
| 2327 | 2329 | possible_crtcs = (1 << nvps) - 1; |
| 2330 | + } else { | |
| 2331 | + possible_crtcs = 0; | |
| 2332 | + } | |
| 2328 | 2333 | |
| 2329 | 2334 | ret = vop2_plane_init(vop2, win, possible_crtcs); |
| 2330 | 2335 | if (ret) { |
| @@ -2370,15 +2375,44 @@ static int vop2_create_crtc(struct vop2 *vop2) · 39 unmodified lines | ||
| 2370 | 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 | 2390 | * Destroy CRTC after vop2_plane_destroy() since vop2_disable_plane() |
| 2379 | 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 | 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 | 2716 | if (ret) |
| 2683 | 2717 | return ret; |
| 2684 | 2718 | |
| 2685 | − ret = vop2_create_crtc(vop2); | |
| 2719 | + ret = vop2_create_crtcs(vop2); | |
| 2686 | 2720 | if (ret) |
| 2687 | 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 | 2736 | rockchip_drm_dma_init_device(vop2->drm, vop2->dev); |
| 2690 | 2737 | |
| 2691 | 2738 | pm_runtime_enable(&pdev->dev); |
| 2692 | 2739 | |
| 2693 | 2740 | return 0; |
| 2741 | + | |
| 2742 | +err_crtcs: | |
| 2743 | + vop2_destroy_crtcs(vop2); | |
| 2744 | + | |
| 2745 | + return ret; | |
| 2694 | 2746 | } |
| 2695 | 2747 | |
| 2696 | 2748 | static void vop2_unbind(struct device *dev, struct device *master, void *data) |
| 2697 | 2749 | { |
| 2698 | 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 | 2752 | pm_runtime_disable(dev); |
| 2706 | 2753 | |
| 2707 | − list_for_each_entry_safe(plane, tmpp, plane_list, head) | |
| 2708 | − drm_plane_cleanup(plane); | |
| 2754 | + if (vop2->rgb) | |
| 2755 | + rockchip_rgb_fini(vop2->rgb); | |
| 2709 | 2756 | |
| 2710 | − list_for_each_entry_safe(crtc, tmpc, crtc_list, head) | |
| 2711 | − vop2_destroy_crtc(crtc); | |
| 2757 | + vop2_destroy_crtcs(vop2); | |
| 2712 | 2758 | } |
| 2713 | 2759 | |
| 2714 | 2760 | const struct component_ops vop2_component_ops = { |
| @@ -22,13 +22,11 @@ · 21 unmodified lines | ||
| 22 | 22 | #include "rockchip_drm_vop.h" |
| 23 | 23 | #include "rockchip_rgb.h" |
| 24 | 24 | |
| 25 | −#define encoder_to_rgb(c) container_of(c, struct rockchip_rgb, encoder) | |
| 26 | − | |
| 27 | 25 | struct rockchip_rgb { |
| 28 | 26 | struct device *dev; |
| 29 | 27 | struct drm_device *drm_dev; |
| 30 | 28 | struct drm_bridge *bridge; |
| 31 | − struct drm_encoder encoder; | |
| 29 | + struct rockchip_encoder encoder; | |
| 32 | 30 | struct drm_connector connector; |
| 33 | 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 | 73 | struct rockchip_rgb *rockchip_rgb_init(struct device *dev, |
| 76 | 74 | struct drm_crtc *crtc, |
| 77 | − struct drm_device *drm_dev) | |
| 75 | + struct drm_device *drm_dev, | |
| 76 | + int video_port) | |
| 78 | 77 | { |
| 79 | 78 | struct rockchip_rgb *rgb; |
| 80 | 79 | struct drm_encoder *encoder; |
| @@ -92,7 +91,7 @@ struct rockchip_rgb *rockchip_rgb_init(struct device *dev, · 11 unmodified lines | ||
| 92 | 91 | rgb->dev = dev; |
| 93 | 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 | 95 | if (!port) |
| 97 | 96 | return ERR_PTR(-EINVAL); |
| 98 | 97 | |
| @@ -105,8 +104,8 @@ struct rockchip_rgb *rockchip_rgb_init(struct device *dev, · 6 unmodified lines | ||
| 105 | 104 | continue; |
| 106 | 105 | |
| 107 | 106 | child_count++; |
| 108 | − ret = drm_of_find_panel_or_bridge(dev->of_node, 0, endpoint_id, | |
| 109 | − &panel, &bridge); | |
| 107 | + ret = drm_of_find_panel_or_bridge(dev->of_node, video_port, | |
| 108 | + endpoint_id, &panel, &bridge); | |
| 110 | 109 | if (!ret) { |
| 111 | 110 | of_node_put(endpoint); |
| 112 | 111 | break; |
| @@ -125,7 +124,7 @@ struct rockchip_rgb *rockchip_rgb_init(struct device *dev, · 12 unmodified lines | ||
| 125 | 124 | return ERR_PTR(ret); |
| 126 | 125 | } |
| 127 | 126 | |
| 128 | − encoder = &rgb->encoder; | |
| 127 | + encoder = &rgb->encoder.encoder; | |
| 129 | 128 | encoder->possible_crtcs = drm_crtc_mask(crtc); |
| 130 | 129 | |
| 131 | 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 | 160 | goto err_free_encoder; |
| 162 | 161 | } |
| 163 | 162 | |
| 163 | + rgb->encoder.crtc_endpoint_id = endpoint_id; | |
| 164 | + | |
| 164 | 165 | ret = drm_connector_attach_encoder(connector, encoder); |
| 165 | 166 | if (ret < 0) { |
| 166 | 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 | 184 | drm_panel_bridge_remove(rgb->bridge); |
| 184 | 185 | drm_connector_cleanup(&rgb->connector); |
| 185 | − drm_encoder_cleanup(&rgb->encoder); | |
| 186 | + drm_encoder_cleanup(&rgb->encoder.encoder); | |
| 186 | 187 | } |
| 187 | 188 | EXPORT_SYMBOL_GPL(rockchip_rgb_fini); |
| @@ -8,12 +8,14 @@ · 7 unmodified lines | ||
| 8 | 8 | #ifdef CONFIG_ROCKCHIP_RGB |
| 9 | 9 | struct rockchip_rgb *rockchip_rgb_init(struct device *dev, |
| 10 | 10 | struct drm_crtc *crtc, |
| 11 | − struct drm_device *drm_dev); | |
| 11 | + struct drm_device *drm_dev, | |
| 12 | + int video_port); | |
| 12 | 13 | void rockchip_rgb_fini(struct rockchip_rgb *rgb); |
| 13 | 14 | #else |
| 14 | 15 | static inline struct rockchip_rgb *rockchip_rgb_init(struct device *dev, |
| 15 | 16 | struct drm_crtc *crtc, |
| 16 | − struct drm_device *drm_dev) | |
| 17 | + struct drm_device *drm_dev, | |
| 18 | + int video_port) | |
| 17 | 19 | { |
| 18 | 20 | return NULL; |
| 19 | 21 | } |
| @@ -53,6 +53,7 @@ · 52 unmodified lines | ||
| 53 | 53 | |
| 54 | 54 | #include <drm/drm_print.h> |
| 55 | 55 | #include <drm/drm_gem.h> |
| 56 | +#include <drm/drm_syncobj.h> | |
| 56 | 57 | #include <drm/gpu_scheduler.h> |
| 57 | 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 | 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 | 751 | * drm_sched_job_add_resv_dependencies - add all fences from the resv to the job |
| 723 | 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 | 598 | drm_fb_xrgb8888_to_xrgb1555(&dst, &result->dst_pitch, &src, &fb, ¶ms->clip); |
| 599 | 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 | 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 | 629 | drm_fb_xrgb8888_to_argb1555(&dst, &result->dst_pitch, &src, &fb, ¶ms->clip); |
| 630 | 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 | 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 | 660 | drm_fb_xrgb8888_to_rgba5551(&dst, &result->dst_pitch, &src, &fb, ¶ms->clip); |
| 661 | 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 | 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 | 725 | drm_fb_xrgb8888_to_argb8888(&dst, &result->dst_pitch, &src, &fb, ¶ms->clip); |
| 726 | 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 | 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 | 787 | drm_fb_xrgb8888_to_argb2101010(&dst, &result->dst_pitch, &src, &fb, ¶ms->clip); |
| 788 | 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 | 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 | 1985 | (y * fb->pitches[1] / fb->format->vsub); |
| 1986 | 1986 | } |
| 1987 | 1987 | |
| 1988 | −int dispc_plane_setup(struct dispc_device *dispc, u32 hw_plane, | |
| 1989 | − const struct drm_plane_state *state, | |
| 1990 | − u32 hw_videoport) | |
| 1988 | +void dispc_plane_setup(struct dispc_device *dispc, u32 hw_plane, | |
| 1989 | + const struct drm_plane_state *state, | |
| 1990 | + u32 hw_videoport) | |
| 1991 | 1991 | { |
| 1992 | 1992 | bool lite = dispc->feat->vid_lite[hw_plane]; |
| 1993 | 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 | 2066 | else |
| 2067 | 2067 | VID_REG_FLD_MOD(dispc, hw_plane, DISPC_VID_ATTRIBUTES, 0, |
| 2068 | 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 | 2073 | VID_REG_FLD_MOD(dispc, hw_plane, DISPC_VID_ATTRIBUTES, !!enable, 0, 0); |
| 2076 | − | |
| 2077 | − return 0; | |
| 2078 | 2074 | } |
| 2079 | 2075 | |
| 2080 | 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 | 123 | int dispc_plane_check(struct dispc_device *dispc, u32 hw_plane, |
| 124 | 124 | const struct drm_plane_state *state, |
| 125 | 125 | u32 hw_videoport); |
| 126 | −int dispc_plane_setup(struct dispc_device *dispc, u32 hw_plane, | |
| 127 | − const struct drm_plane_state *state, | |
| 128 | − u32 hw_videoport); | |
| 129 | −int dispc_plane_enable(struct dispc_device *dispc, u32 hw_plane, bool enable); | |
| 126 | +void dispc_plane_setup(struct dispc_device *dispc, u32 hw_plane, | |
| 127 | + const struct drm_plane_state *state, | |
| 128 | + u32 hw_videoport); | |
| 129 | +void dispc_plane_enable(struct dispc_device *dispc, u32 hw_plane, bool enable); | |
| 130 | 130 | const u32 *dispc_plane_formats(struct dispc_device *dispc, unsigned int *len); |
| 131 | 131 | |
| 132 | 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 | 113 | struct drm_plane_state *new_state = drm_atomic_get_new_plane_state(state, |
| 114 | 114 | plane); |
| 115 | 115 | u32 hw_videoport; |
| 116 | − int ret; | |
| 117 | 116 | |
| 118 | 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 | 124 | hw_videoport = to_tidss_crtc(new_state->crtc)->hw_videoport; |
| 126 | 125 | |
| 127 | − ret = dispc_plane_setup(tidss->dispc, tplane->hw_plane_id, | |
| 128 | − new_state, hw_videoport); | |
| 126 | + dispc_plane_setup(tidss->dispc, tplane->hw_plane_id, new_state, hw_videoport); | |
| 127 | +} | |
| 129 | 128 | |
| 130 | − if (ret) { | |
| 131 | − dev_err(plane->dev->dev, "%s: Failed to setup plane %d\n", | |
| 132 | − __func__, tplane->hw_plane_id); | |
| 133 | − dispc_plane_enable(tidss->dispc, tplane->hw_plane_id, false); | |
| 134 | − return; | |
| 135 | − } | |
| 129 | +static void tidss_plane_atomic_enable(struct drm_plane *plane, | |
| 130 | + struct drm_atomic_state *state) | |
| 131 | +{ | |
| 132 | + struct drm_device *ddev = plane->dev; | |
| 133 | + struct tidss_device *tidss = to_tidss(ddev); | |
| 134 | + struct tidss_plane *tplane = to_tidss_plane(plane); | |
| 135 | + | |
| 136 | + dev_dbg(ddev->dev, "%s\n", __func__); | |
| 136 | 137 | |
| 137 | 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 | 161 | static const struct drm_plane_helper_funcs tidss_plane_helper_funcs = { |
| 161 | 162 | .atomic_check = tidss_plane_atomic_check, |
| 162 | 163 | .atomic_update = tidss_plane_atomic_update, |
| 164 | + .atomic_enable = tidss_plane_atomic_enable, | |
| 163 | 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 | 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 | 613 | const struct drm_display_mode mode = { |
| 616 | − DRM_MODE_INIT(60, width, height, | |
| 617 | − DRM_MODE_RES_MM(width, 96ul), | |
| 618 | − DRM_MODE_RES_MM(height, 96ul)) | |
| 614 | + DRM_MODE_INIT(60, width, height, width_mm, height_mm) | |
| 619 | 615 | }; |
| 620 | 616 | |
| 621 | 617 | return mode; |
| @@ -629,6 +625,8 @@ static struct simpledrm_device *simpledrm_device_create(struct drm_driver *drv, · 7 unmodified lines | ||
| 629 | 625 | struct simpledrm_device *sdev; |
| 630 | 626 | struct drm_device *dev; |
| 631 | 627 | int width, height, stride; |
| 628 | + int width_mm = 0, height_mm = 0; | |
| 629 | + struct device_node *panel_node; | |
| 632 | 630 | const struct drm_format_info *format; |
| 633 | 631 | struct resource *res, *mem = NULL; |
| 634 | 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 | 683 | mem = simplefb_get_memory_of(dev, of_node); |
| 686 | 684 | if (IS_ERR(mem)) |
| 687 | 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 | 692 | } else { |
| 689 | 693 | drm_err(dev, "no simplefb configuration found\n"); |
| 690 | 694 | return ERR_PTR(-ENODEV); |
| @@ -695,7 +699,16 @@ static struct simpledrm_device *simpledrm_device_create(struct drm_driver *drv, · 4 unmodified lines | ||
| 695 | 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 | 712 | sdev->format = format; |
| 700 | 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 | 120 | bool old_use_tt, new_use_tt; |
| 121 | 121 | int ret; |
| 122 | 122 | |
| 123 | − old_use_tt = bo->resource && | |
| 124 | − ttm_manager_type(bdev, bo->resource->mem_type)->use_tt; | |
| 123 | + old_use_tt = !bo->resource || ttm_manager_type(bdev, bo->resource->mem_type)->use_tt; | |
| 125 | 124 | new_use_tt = ttm_manager_type(bdev, mem->mem_type)->use_tt; |
| 126 | 125 | |
| 127 | 126 | ttm_bo_unmap_virtual(bo); |
| @@ -894,14 +893,18 @@ int ttm_bo_validate(struct ttm_buffer_object *bo, · 766 unmodified lines | ||
| 894 | 893 | if (!placement->num_placement && !placement->num_busy_placement) |
| 895 | 894 | return ttm_bo_pipeline_gutting(bo); |
| 896 | 895 | |
| 897 | − /* | |
| 898 | − * Check whether we need to move buffer. | |
| 899 | − */ | |
| 900 | − if (!bo->resource || !ttm_resource_compat(bo->resource, placement)) { | |
| 901 | − ret = ttm_bo_move_buffer(bo, placement, ctx); | |
| 902 | − if (ret) | |
| 903 | − return ret; | |
| 904 | − } | |
| 896 | + /* Check whether we need to move buffer. */ | |
| 897 | + if (bo->resource && ttm_resource_compat(bo->resource, placement)) | |
| 898 | + return 0; | |
| 899 | + | |
| 900 | + /* Moving of pinned BOs is forbidden */ | |
| 901 | + if (bo->pin_count) | |
| 902 | + return -EINVAL; | |
| 903 | + | |
| 904 | + ret = ttm_bo_move_buffer(bo, placement, ctx); | |
| 905 | + if (ret) | |
| 906 | + return ret; | |
| 907 | + | |
| 905 | 908 | /* |
| 906 | 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 | 956 | struct sg_table *sg, struct dma_resv *resv, |
| 954 | 957 | void (*destroy) (struct ttm_buffer_object *)) |
| 955 | 958 | { |
| 956 | − static const struct ttm_place sys_mem = { .mem_type = TTM_PL_SYSTEM }; | |
| 957 | 959 | int ret; |
| 958 | 960 | |
| 959 | 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 | 972 | bo->base.resv = &bo->base._resv; |
| 971 | 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 | 976 | * For ttm_bo_type_device buffers, allocate |
| 981 | 977 | * address space from the device. |
| @@ -157,8 +157,8 @@ int ttm_bo_move_memcpy(struct ttm_buffer_object *bo, · 156 unmodified lines | ||
| 157 | 157 | bool clear; |
| 158 | 158 | int ret = 0; |
| 159 | 159 | |
| 160 | − if (!src_mem) | |
| 161 | − return 0; | |
| 160 | + if (WARN_ON(!src_mem)) | |
| 161 | + return -EINVAL; | |
| 162 | 162 | |
| 163 | 163 | src_man = ttm_manager_type(bdev, src_mem->mem_type); |
| 164 | 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 | 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 | 707 | struct ttm_buffer_object *ghost; |
| 709 | − struct ttm_resource *sys_res; | |
| 710 | 708 | struct ttm_tt *ttm; |
| 711 | 709 | int ret; |
| 712 | 710 | |
| 713 | − ret = ttm_resource_alloc(bo, &sys_mem, &sys_res); | |
| 714 | − if (ret) | |
| 715 | − return ret; | |
| 716 | − | |
| 717 | 711 | /* If already idle, no need for ghost object dance. */ |
| 718 | 712 | if (dma_resv_test_signaled(bo->base.resv, DMA_RESV_USAGE_BOOKKEEP)) { |
| 719 | 713 | if (!bo->ttm) { |
| 720 | 714 | /* See comment below about clearing. */ |
| 721 | 715 | ret = ttm_tt_create(bo, true); |
| 722 | 716 | if (ret) |
| 723 | − goto error_free_sys_mem; | |
| 717 | + return ret; | |
| 724 | 718 | } else { |
| 725 | 719 | ttm_tt_unpopulate(bo->bdev, bo->ttm); |
| 726 | 720 | if (bo->type == ttm_bo_type_device) |
| 727 | 721 | ttm_tt_mark_for_clear(bo->ttm); |
| 728 | 722 | } |
| 729 | 723 | ttm_resource_free(bo, &bo->resource); |
| 730 | − ttm_bo_assign_mem(bo, sys_res); | |
| 731 | 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 | 737 | ret = ttm_tt_create(bo, true); |
| 745 | 738 | swap(bo->ttm, ttm); |
| 746 | 739 | if (ret) |
| 747 | − goto error_free_sys_mem; | |
| 740 | + return ret; | |
| 748 | 741 | |
| 749 | 742 | ret = ttm_buffer_object_transfer(bo, &ghost); |
| 750 | 743 | if (ret) |
| @@ -760,13 +753,9 @@ int ttm_bo_pipeline_gutting(struct ttm_buffer_object *bo) · 9 unmodified lines | ||
| 760 | 753 | dma_resv_unlock(&ghost->base._resv); |
| 761 | 754 | ttm_bo_put(ghost); |
| 762 | 755 | bo->ttm = ttm; |
| 763 | − ttm_bo_assign_mem(bo, sys_res); | |
| 764 | 756 | return 0; |
| 765 | 757 | |
| 766 | 758 | error_destroy_tt: |
| 767 | 759 | ttm_tt_destroy(bo->bdev, ttm); |
| 768 | − | |
| 769 | −error_free_sys_mem: | |
| 770 | − ttm_resource_free(bo, &sys_res); | |
| 771 | 760 | return ret; |
| 772 | 761 | } |
| @@ -361,7 +361,6 @@ bool ttm_resource_compat(struct ttm_resource *res, · 360 unmodified lines | ||
| 361 | 361 | |
| 362 | 362 | return false; |
| 363 | 363 | } |
| 364 | −EXPORT_SYMBOL(ttm_resource_compat); | |
| 365 | 364 | |
| 366 | 365 | void ttm_resource_set_bo(struct ttm_resource *res, |
| 367 | 366 | struct ttm_buffer_object *bo) |
| @@ -396,20 +396,6 @@ v3d_wait_bo_ioctl(struct drm_device *dev, void *data, · 395 unmodified lines | ||
| 396 | 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 | 399 | static int |
| 414 | 400 | v3d_job_init(struct v3d_dev *v3d, struct drm_file *file_priv, |
| 415 | 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 | 433 | DRM_DEBUG("Failed to copy wait dep handle.\n"); |
| 448 | 434 | goto fail_deps; |
| 449 | 435 | } |
| 450 | − ret = v3d_job_add_deps(file_priv, job, in.handle, 0); | |
| 451 | − if (ret) | |
| 436 | + ret = drm_sched_job_add_syncobj_dependency(&job->base, file_priv, in.handle, 0); | |
| 437 | + | |
| 438 | + // TODO: Investigate why this was filtered out for the IOCTL. | |
| 439 | + if (ret && ret != -ENOENT) | |
| 452 | 440 | goto fail_deps; |
| 453 | 441 | } |
| 454 | 442 | } |
| 455 | 443 | } else { |
| 456 | − ret = v3d_job_add_deps(file_priv, job, in_sync, 0); | |
| 457 | − if (ret) | |
| 444 | + ret = drm_sched_job_add_syncobj_dependency(&job->base, file_priv, in_sync, 0); | |
| 445 | + | |
| 446 | + // TODO: Investigate why this was filtered out for the IOCTL. | |
| 447 | + if (ret && ret != -ENOENT) | |
| 458 | 448 | goto fail_deps; |
| 459 | 449 | } |
| 460 | 450 | |
| @@ -690,7 +690,7 @@ struct vc4_exec_info { · 689 unmodified lines | ||
| 690 | 690 | /* This is the array of BOs that were looked up at the start of exec. |
| 691 | 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 | 694 | uint32_t bo_count; |
| 695 | 695 | |
| 696 | 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 | 199 | continue; |
| 200 | 200 | |
| 201 | 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 | 204 | /* Retain BOs just in case they were marked purgeable. |
| 205 | 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 | 208 | WARN_ON(!refcount_read(&bo->usecnt)); |
| 209 | 209 | refcount_inc(&bo->usecnt); |
| 210 | − drm_gem_object_get(&exec[i]->bo[j]->base); | |
| 211 | − kernel_state->bo[k++] = &exec[i]->bo[j]->base; | |
| 210 | + drm_gem_object_get(exec[i]->bo[j]); | |
| 211 | + kernel_state->bo[k++] = exec[i]->bo[j]; | |
| 212 | 212 | } |
| 213 | 213 | |
| 214 | 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 | 558 | unsigned i; |
| 559 | 559 | |
| 560 | 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 | 562 | bo->seqno = seqno; |
| 563 | 563 | |
| 564 | 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 | 586 | int i; |
| 587 | 587 | |
| 588 | − for (i = 0; i < exec->bo_count; i++) { | |
| 589 | − struct drm_gem_object *bo = &exec->bo[i]->base; | |
| 590 | − | |
| 591 | − dma_resv_unlock(bo->resv); | |
| 592 | − } | |
| 588 | + for (i = 0; i < exec->bo_count; i++) | |
| 589 | + dma_resv_unlock(exec->bo[i]->resv); | |
| 593 | 590 | |
| 594 | 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 | 612 | retry: |
| 616 | 613 | if (contended_lock != -1) { |
| 617 | − bo = &exec->bo[contended_lock]->base; | |
| 614 | + bo = exec->bo[contended_lock]; | |
| 618 | 615 | ret = dma_resv_lock_slow_interruptible(bo->resv, acquire_ctx); |
| 619 | 616 | if (ret) { |
| 620 | 617 | ww_acquire_done(acquire_ctx); |
| @@ -626,19 +623,19 @@ retry: · 5 unmodified lines | ||
| 626 | 623 | if (i == contended_lock) |
| 627 | 624 | continue; |
| 628 | 625 | |
| 629 | − bo = &exec->bo[i]->base; | |
| 626 | + bo = exec->bo[i]; | |
| 630 | 627 | |
| 631 | 628 | ret = dma_resv_lock_interruptible(bo->resv, acquire_ctx); |
| 632 | 629 | if (ret) { |
| 633 | 630 | int j; |
| 634 | 631 | |
| 635 | 632 | for (j = 0; j < i; j++) { |
| 636 | − bo = &exec->bo[j]->base; | |
| 633 | + bo = exec->bo[j]; | |
| 637 | 634 | dma_resv_unlock(bo->resv); |
| 638 | 635 | } |
| 639 | 636 | |
| 640 | 637 | if (contended_lock != -1 && contended_lock >= i) { |
| 641 | − bo = &exec->bo[contended_lock]->base; | |
| 638 | + bo = exec->bo[contended_lock]; | |
| 642 | 639 | |
| 643 | 640 | dma_resv_unlock(bo->resv); |
| 644 | 641 | } |
| @@ -659,7 +656,7 @@ retry: · 14 unmodified lines | ||
| 659 | 656 | * before we commit the CL to the hardware. |
| 660 | 657 | */ |
| 661 | 658 | for (i = 0; i < exec->bo_count; i++) { |
| 662 | − bo = &exec->bo[i]->base; | |
| 659 | + bo = exec->bo[i]; | |
| 663 | 660 | |
| 664 | 661 | ret = dma_resv_reserve_fences(bo->resv, 1); |
| 665 | 662 | if (ret) { |
| @@ -749,7 +746,6 @@ vc4_cl_lookup_bos(struct drm_device *dev, · 83 unmodified lines | ||
| 749 | 746 | struct vc4_exec_info *exec) |
| 750 | 747 | { |
| 751 | 748 | struct drm_vc4_submit_cl *args = exec->args; |
| 752 | − uint32_t *handles; | |
| 753 | 749 | int ret = 0; |
| 754 | 750 | int i; |
| 755 | 751 | |
| @@ -763,54 +759,18 @@ vc4_cl_lookup_bos(struct drm_device *dev, · 7 unmodified lines | ||
| 763 | 759 | return -EINVAL; |
| 764 | 760 | } |
| 765 | 761 | |
| 766 | − exec->bo = kvmalloc_array(exec->bo_count, | |
| 767 | − sizeof(struct drm_gem_dma_object *), | |
| 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); | |
| 762 | + ret = drm_gem_objects_lookup(file_priv, u64_to_user_ptr(args->bo_handles), | |
| 763 | + exec->bo_count, &exec->bo); | |
| 803 | 764 | |
| 804 | 765 | if (ret) |
| 805 | 766 | goto fail_put_bo; |
| 806 | 767 | |
| 807 | 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 | 770 | if (ret) |
| 810 | 771 | goto fail_dec_usecnt; |
| 811 | 772 | } |
| 812 | 773 | |
| 813 | − kvfree(handles); | |
| 814 | 774 | return 0; |
| 815 | 775 | |
| 816 | 776 | fail_dec_usecnt: |
| @@ -823,15 +783,13 @@ fail_dec_usecnt: · 6 unmodified lines | ||
| 823 | 783 | * step. |
| 824 | 784 | */ |
| 825 | 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 | 788 | fail_put_bo: |
| 829 | 789 | /* Release any reference to acquired objects. */ |
| 830 | 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 | 793 | kvfree(exec->bo); |
| 836 | 794 | exec->bo = NULL; |
| 837 | 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 | 933 | if (exec->bo) { |
| 976 | 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 | 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 | 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 | 1466 | if (!drm_dev_enter(drm, &idx)) |
| 1467 | 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 | 1476 | * As stated in RPi's vc4 firmware "HDMI state machine (HSM) clock must |
| 1471 | 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 | 1488 | * Additionally, the AXI clock needs to be at least 25% of |
| 1483 | 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 | 1494 | ret = clk_set_min_rate(vc4_hdmi->hsm_clock, hsm_rate); |
| 1487 | 1495 | if (ret) { |
| 1488 | 1496 | DRM_ERROR("Failed to set HSM clock rate: %d\n", ret); |
| 1489 | − goto err_dev_exit; | |
| 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; | |
| 1497 | + goto err_put_runtime_pm; | |
| 1496 | 1498 | } |
| 1497 | 1499 | |
| 1498 | 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 | 3190 | DRM_ERROR("Failed to get HDMI state machine clock\n"); |
| 3189 | 3191 | return PTR_ERR(vc4_hdmi->hsm_clock); |
| 3190 | 3192 | } |
| 3191 | − | |
| 3192 | 3193 | vc4_hdmi->audio_clock = vc4_hdmi->hsm_clock; |
| 3193 | 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 | 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 | 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 | 3278 | vc4_hdmi->pixel_bvb_clock = devm_clk_get(dev, "bvb"); |
| 3290 | 3279 | if (IS_ERR(vc4_hdmi->pixel_bvb_clock)) { |
| 3291 | 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 | 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 | 3343 | return 0; |
| 3355 | 3344 | } |
| @@ -3362,16 +3351,7 @@ static int vc4_hdmi_runtime_resume(struct device *dev) · 6 unmodified lines | ||
| 3362 | 3351 | unsigned long rate; |
| 3363 | 3352 | int ret; |
| 3364 | 3353 | |
| 3365 | − /* | |
| 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); | |
| 3354 | + ret = clk_prepare_enable(vc4_hdmi->hsm_clock); | |
| 3375 | 3355 | if (ret) |
| 3376 | 3356 | return ret; |
| 3377 | 3357 | |
| @@ -3384,7 +3364,7 @@ static int vc4_hdmi_runtime_resume(struct device *dev) · 6 unmodified lines | ||
| 3384 | 3364 | * case, it will lead to a silent CPU stall. Let's make sure we |
| 3385 | 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 | 3368 | if (!rate) { |
| 3389 | 3369 | ret = -EINVAL; |
| 3390 | 3370 | goto err_disable_clk; |
| @@ -164,7 +164,6 @@ struct vc4_hdmi { · 163 unmodified lines | ||
| 164 | 164 | struct clk *cec_clock; |
| 165 | 165 | struct clk *pixel_clock; |
| 166 | 166 | struct clk *hsm_clock; |
| 167 | − struct clk *hsm_rpm_clock; | |
| 168 | 167 | struct clk *audio_clock; |
| 169 | 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 | 117 | hindex, exec->bo_count); |
| 118 | 118 | return NULL; |
| 119 | 119 | } |
| 120 | − obj = exec->bo[hindex]; | |
| 120 | + obj = to_drm_gem_dma_obj(exec->bo[hindex]); | |
| 121 | 121 | bo = to_vc4_bo(&obj->base); |
| 122 | 122 | |
| 123 | 123 | if (bo->validated_shader) { |
| @@ -810,7 +810,7 @@ validate_gl_shader_rec(struct drm_device *dev, · 686 unmodified lines | ||
| 810 | 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 | 814 | if (!bo[i]) |
| 815 | 815 | return -EINVAL; |
| 816 | 816 | } |
| @@ -249,4 +249,5 @@ void vgem_fence_close(struct vgem_file *vfile) · 248 unmodified lines | ||
| 249 | 249 | { |
| 250 | 250 | idr_for_each(&vfile->fence_idr, __vgem_fence_idr_fini, vfile); |
| 251 | 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 | 11 | QEMU based VMMs (like KVM or Xen). |
| 12 | 12 | |
| 13 | 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 | 337 | int i, ret; |
| 338 | 338 | |
| 339 | + if (!vgdev->num_scanouts) | |
| 340 | + return 0; | |
| 341 | + | |
| 339 | 342 | ret = drmm_mode_config_init(vgdev->ddev); |
| 340 | 343 | if (ret) |
| 341 | 344 | return ret; |
| @@ -362,6 +365,9 @@ void virtio_gpu_modeset_fini(struct virtio_gpu_device *vgdev) · 20 unmodified lines | ||
| 362 | 365 | { |
| 363 | 366 | int i; |
| 364 | 367 | |
| 368 | + if (!vgdev->num_scanouts) | |
| 369 | + return; | |
| 370 | + | |
| 365 | 371 | for (i = 0 ; i < vgdev->num_scanouts; ++i) |
| 366 | 372 | kfree(vgdev->outputs[i].edid); |
| 367 | 373 | } |
| @@ -172,6 +172,10 @@ MODULE_AUTHOR("Alon Levy"); · 171 unmodified lines | ||
| 172 | 172 | DEFINE_DRM_GEM_FOPS(virtio_gpu_driver_fops); |
| 173 | 173 | |
| 174 | 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 | 179 | .driver_features = DRIVER_MODESET | DRIVER_GEM | DRIVER_RENDER | DRIVER_ATOMIC, |
| 176 | 180 | .open = virtio_gpu_driver_open, |
| 177 | 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 | 43 | virtio_cread_le(vgdev->vdev, struct virtio_gpu_config, |
| 44 | 44 | events_read, &events_read); |
| 45 | 45 | if (events_read & VIRTIO_GPU_EVENT_DISPLAY) { |
| 46 | − if (vgdev->has_edid) | |
| 47 | − virtio_gpu_cmd_get_edids(vgdev); | |
| 48 | − virtio_gpu_cmd_get_display_info(vgdev); | |
| 49 | − virtio_gpu_notify(vgdev); | |
| 50 | − drm_helper_hpd_irq_event(vgdev->ddev); | |
| 46 | + if (vgdev->num_scanouts) { | |
| 47 | + if (vgdev->has_edid) | |
| 48 | + virtio_gpu_cmd_get_edids(vgdev); | |
| 49 | + virtio_gpu_cmd_get_display_info(vgdev); | |
| 50 | + virtio_gpu_notify(vgdev); | |
| 51 | + drm_helper_hpd_irq_event(vgdev->ddev); | |
| 52 | + } | |
| 51 | 53 | events_clear |= VIRTIO_GPU_EVENT_DISPLAY; |
| 52 | 54 | } |
| 53 | 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 | 225 | num_scanouts, &num_scanouts); |
| 224 | 226 | vgdev->num_scanouts = min_t(uint32_t, num_scanouts, |
| 225 | 227 | VIRTIO_GPU_MAX_SCANOUTS); |
| 226 | − if (!vgdev->num_scanouts) { | |
| 227 | − DRM_ERROR("num_scanouts is zero\n"); | |
| 228 | − ret = -EINVAL; | |
| 229 | − goto err_scanouts; | |
| 228 | + | |
| 229 | + if (!IS_ENABLED(CONFIG_DRM_VIRTIO_GPU_KMS) || !vgdev->num_scanouts) { | |
| 230 | + DRM_INFO("KMS disabled\n"); | |
| 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 | 238 | virtio_cread_le(vgdev->vdev, struct virtio_gpu_config, |
| 234 | 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 | 250 | if (num_capsets) |
| 246 | 251 | virtio_gpu_get_capsets(vgdev, num_capsets); |
| 247 | − if (vgdev->has_edid) | |
| 248 | − virtio_gpu_cmd_get_edids(vgdev); | |
| 249 | − virtio_gpu_cmd_get_display_info(vgdev); | |
| 250 | − virtio_gpu_notify(vgdev); | |
| 251 | − wait_event_timeout(vgdev->resp_wq, !vgdev->display_info_pending, | |
| 252 | − 5 * HZ); | |
| 252 | + if (vgdev->num_scanouts) { | |
| 253 | + if (vgdev->has_edid) | |
| 254 | + virtio_gpu_cmd_get_edids(vgdev); | |
| 255 | + virtio_gpu_cmd_get_display_info(vgdev); | |
| 256 | + virtio_gpu_notify(vgdev); | |
| 257 | + wait_event_timeout(vgdev->resp_wq, !vgdev->display_info_pending, | |
| 258 | + 5 * HZ); | |
| 259 | + } | |
| 253 | 260 | return 0; |
| 254 | 261 | |
| 255 | 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 | 923 | cmd_p->hdr.ctx_id = cpu_to_le32(id); |
| 924 | 924 | cmd_p->nlen = cpu_to_le32(nlen); |
| 925 | 925 | cmd_p->context_init = cpu_to_le32(context_init); |
| 926 | − strncpy(cmd_p->debug_name, name, sizeof(cmd_p->debug_name) - 1); | |
| 927 | − cmd_p->debug_name[sizeof(cmd_p->debug_name) - 1] = 0; | |
| 926 | + strscpy(cmd_p->debug_name, name, sizeof(cmd_p->debug_name)); | |
| 928 | 927 | virtio_gpu_queue_ctrl_buffer(vgdev, vbuf); |
| 929 | 928 | } |
| 930 | 929 | |
| @@ -1,7 +1,7 @@ | ||
| 1 | 1 | # SPDX-License-Identifier: GPL-2.0 |
| 2 | 2 | vmwgfx-y := vmwgfx_execbuf.o vmwgfx_gmr.o vmwgfx_kms.o vmwgfx_drv.o \ |
| 3 | 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 | 5 | vmwgfx_overlay.o vmwgfx_gmrid_manager.o vmwgfx_fence.o \ |
| 6 | 6 | vmwgfx_bo.o vmwgfx_scrn.o vmwgfx_context.o \ |
| 7 | 7 | vmwgfx_surface.o vmwgfx_prime.o vmwgfx_mob.o vmwgfx_shader.o \ |
| @@ -1,7 +1,7 @@ | ||
| 1 | 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 | 5 | * All Rights Reserved. |
| 6 | 6 | * |
| 7 | 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> | |
| 30 | − | |
| 29 | +#include "vmwgfx_bo.h" | |
| 31 | 30 | #include "vmwgfx_drv.h" |
| 32 | −#include "ttm_object.h" | |
| 33 | 31 | |
| 34 | 32 | |
| 35 | −/** | |
| 36 | − * vmw_buffer_object - Convert a struct ttm_buffer_object to a struct | |
| 37 | − * vmw_buffer_object. | |
| 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) | |
| 33 | +#include <drm/ttm/ttm_placement.h> | |
| 34 | + | |
| 35 | +static void vmw_bo_release(struct vmw_bo *vbo) | |
| 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 | |
| 51 | − * @bo: ttm buffer object to be checked | |
| 42 | + * vmw_bo_free - vmw_bo destructor | |
| 52 | 43 | * |
| 53 | − * Uses destroy function associated with the object to determine if this is | |
| 54 | − * a &vmw_buffer_object. | |
| 55 | − * | |
| 56 | − * Returns: | |
| 57 | − * true if the object is of &vmw_buffer_object type, false if not. | |
| 44 | + * @bo: Pointer to the embedded struct ttm_buffer_object | |
| 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 || | |
| 62 | − bo->destroy == &vmw_gem_destroy; | |
| 48 | + struct vmw_bo *vbo = to_vmw_bo(&bo->base); | |
| 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 | 63 | * Return: Zero on success, Negative error code on failure. In particular |
| 73 | 64 | * -ERESTARTSYS if interrupted by a signal |
| 74 | 65 | */ |
| 75 | −int vmw_bo_pin_in_placement(struct vmw_private *dev_priv, | |
| 76 | − struct vmw_buffer_object *buf, | |
| 77 | − struct ttm_placement *placement, | |
| 78 | − bool interruptible) | |
| 66 | +static int vmw_bo_pin_in_placement(struct vmw_private *dev_priv, | |
| 67 | + struct vmw_bo *buf, | |
| 68 | + struct ttm_placement *placement, | |
| 69 | + bool interruptible) | |
| 79 | 70 | { |
| 80 | 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 | 73 | int ret; |
| 83 | 74 | |
| 84 | 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 | 78 | if (unlikely(ret != 0)) |
| 88 | 79 | goto err; |
| 89 | 80 | |
| 90 | − if (buf->base.pin_count > 0) | |
| 91 | − ret = ttm_resource_compat(bo->resource, placement) | |
| 92 | − ? 0 : -EINVAL; | |
| 93 | − else | |
| 94 | − ret = ttm_bo_validate(bo, placement, &ctx); | |
| 95 | − | |
| 81 | + ret = ttm_bo_validate(bo, placement, &ctx); | |
| 96 | 82 | if (!ret) |
| 97 | 83 | vmw_bo_pin_reserved(buf, true); |
| 98 | 84 | |
| @@ -115,11 +101,11 @@ err: · 16 unmodified lines | ||
| 115 | 101 | * -ERESTARTSYS if interrupted by a signal |
| 116 | 102 | */ |
| 117 | 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 | 105 | bool interruptible) |
| 120 | 106 | { |
| 121 | 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 | 109 | int ret; |
| 124 | 110 | |
| 125 | 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 | 114 | if (unlikely(ret != 0)) |
| 129 | 115 | goto err; |
| 130 | 116 | |
| 131 | − if (buf->base.pin_count > 0) { | |
| 132 | − ret = ttm_resource_compat(bo->resource, &vmw_vram_gmr_placement) | |
| 133 | − ? 0 : -EINVAL; | |
| 134 | − goto out_unreserve; | |
| 135 | − } | |
| 136 | − | |
| 137 | − ret = ttm_bo_validate(bo, &vmw_vram_gmr_placement, &ctx); | |
| 117 | + vmw_bo_placement_set(buf, | |
| 118 | + VMW_BO_DOMAIN_GMR | VMW_BO_DOMAIN_VRAM, | |
| 119 | + VMW_BO_DOMAIN_GMR); | |
| 120 | + ret = ttm_bo_validate(bo, &buf->placement, &ctx); | |
| 138 | 121 | if (likely(ret == 0) || ret == -ERESTARTSYS) |
| 139 | 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 | 129 | out_unreserve: |
| 144 | 130 | if (!ret) |
| @@ -163,7 +149,7 @@ err: · 18 unmodified lines | ||
| 163 | 149 | * -ERESTARTSYS if interrupted by a signal |
| 164 | 150 | */ |
| 165 | 151 | int vmw_bo_pin_in_vram(struct vmw_private *dev_priv, |
| 166 | − struct vmw_buffer_object *buf, | |
| 152 | + struct vmw_bo *buf, | |
| 167 | 153 | bool interruptible) |
| 168 | 154 | { |
| 169 | 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 | 170 | * -ERESTARTSYS if interrupted by a signal |
| 185 | 171 | */ |
| 186 | 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 | 174 | bool interruptible) |
| 189 | 175 | { |
| 190 | 176 | struct ttm_operation_ctx ctx = {interruptible, false }; |
| 191 | − struct ttm_buffer_object *bo = &buf->base; | |
| 192 | − struct ttm_placement placement; | |
| 193 | − struct ttm_place place; | |
| 177 | + struct ttm_buffer_object *bo = &buf->tbo; | |
| 194 | 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 | 180 | vmw_execbuf_release_pinned_bo(dev_priv); |
| 204 | 181 | ret = ttm_bo_reserve(bo, interruptible, false, NULL); |
| 205 | 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 | 190 | if (bo->resource->mem_type == TTM_PL_VRAM && |
| 214 | 191 | bo->resource->start < PFN_UP(bo->resource->size) && |
| 215 | 192 | bo->resource->start > 0 && |
| 216 | − buf->base.pin_count == 0) { | |
| 193 | + buf->tbo.pin_count == 0) { | |
| 217 | 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) | |
| 222 | − ret = ttm_resource_compat(bo->resource, &placement) | |
| 223 | − ? 0 : -EINVAL; | |
| 224 | − else | |
| 225 | − ret = ttm_bo_validate(bo, &placement, &ctx); | |
| 201 | + vmw_bo_placement_set(buf, | |
| 202 | + VMW_BO_DOMAIN_VRAM, | |
| 203 | + VMW_BO_DOMAIN_VRAM); | |
| 204 | + buf->places[0].lpfn = PFN_UP(bo->resource->size); | |
| 205 | + ret = ttm_bo_validate(bo, &buf->placement, &ctx); | |
| 226 | 206 | |
| 227 | 207 | /* For some reason we didn't end up at the start of vram */ |
| 228 | 208 | WARN_ON(ret == 0 && bo->resource->start != 0); |
| @@ -248,10 +228,10 @@ err_unlock: · 19 unmodified lines | ||
| 248 | 228 | * -ERESTARTSYS if interrupted by a signal |
| 249 | 229 | */ |
| 250 | 230 | int vmw_bo_unpin(struct vmw_private *dev_priv, |
| 251 | − struct vmw_buffer_object *buf, | |
| 231 | + struct vmw_bo *buf, | |
| 252 | 232 | bool interruptible) |
| 253 | 233 | { |
| 254 | − struct ttm_buffer_object *bo = &buf->base; | |
| 234 | + struct ttm_buffer_object *bo = &buf->tbo; | |
| 255 | 235 | int ret; |
| 256 | 236 | |
| 257 | 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 | 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 | 278 | struct ttm_operation_ctx ctx = { false, true }; |
| 299 | 279 | struct ttm_place pl; |
| 300 | 280 | struct ttm_placement placement; |
| 301 | − struct ttm_buffer_object *bo = &vbo->base; | |
| 281 | + struct ttm_buffer_object *bo = &vbo->tbo; | |
| 302 | 282 | uint32_t old_mem_type = bo->resource->mem_type; |
| 303 | 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 | 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 | 327 | bool not_used; |
| 348 | 328 | void *virtual; |
| 349 | 329 | int ret; |
| @@ -366,96 +346,70 @@ void *vmw_bo_map_and_cache(struct vmw_buffer_object *vbo) · 16 unmodified lines | ||
| 366 | 346 | * @vbo: The buffer object whose map we are tearing down. |
| 367 | 347 | * |
| 368 | 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 | 353 | if (vbo->map.bo == NULL) |
| 374 | 354 | return; |
| 375 | 355 | |
| 376 | 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 | |
| 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. | |
| 362 | + * vmw_bo_init - Initialize a vmw buffer object | |
| 404 | 363 | * |
| 405 | 364 | * @dev_priv: Pointer to the device private struct |
| 406 | − * @size: size of the BO we need | |
| 407 | − * @placement: where to put it | |
| 408 | − * @p_bo: resulting BO | |
| 365 | + * @vmw_bo: Buffer object to initialize | |
| 366 | + * @params: Parameters used to initialize the buffer object | |
| 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, | |
| 413 | − struct ttm_placement *placement, | |
| 414 | − struct ttm_buffer_object **p_bo) | |
| 371 | +static int vmw_bo_init(struct vmw_private *dev_priv, | |
| 372 | + struct vmw_bo *vmw_bo, | |
| 373 | + struct vmw_bo_params *params, | |
| 374 | + void (*destroy)(struct ttm_buffer_object *)) | |
| 415 | 375 | { |
| 416 | 376 | struct ttm_operation_ctx ctx = { |
| 417 | − .interruptible = false, | |
| 377 | + .interruptible = params->bo_type != ttm_bo_type_kernel, | |
| 418 | 378 | .no_wait_gpu = false |
| 419 | 379 | }; |
| 420 | − struct ttm_buffer_object *bo; | |
| 380 | + struct ttm_device *bdev = &dev_priv->bdev; | |
| 421 | 381 | struct drm_device *vdev = &dev_priv->drm; |
| 422 | 382 | int ret; |
| 423 | 383 | |
| 424 | − bo = kzalloc(sizeof(*bo), GFP_KERNEL); | |
| 425 | − if (unlikely(!bo)) | |
| 426 | − return -ENOMEM; | |
| 384 | + memset(vmw_bo, 0, sizeof(*vmw_bo)); | |
| 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, | |
| 433 | − placement, 0, &ctx, NULL, NULL, | |
| 434 | − vmw_bo_default_destroy); | |
| 393 | + vmw_bo_placement_set(vmw_bo, params->domain, params->busy_domain); | |
| 394 | + ret = ttm_bo_init_reserved(bdev, &vmw_bo->tbo, params->bo_type, | |
| 395 | + &vmw_bo->placement, 0, &ctx, NULL, | |
| 396 | + NULL, destroy); | |
| 435 | 397 | if (unlikely(ret)) |
| 436 | − goto error_free; | |
| 398 | + return ret; | |
| 437 | 399 | |
| 438 | − ttm_bo_pin(bo); | |
| 439 | − ttm_bo_unreserve(bo); | |
| 440 | − *p_bo = bo; | |
| 400 | + if (params->pin) | |
| 401 | + ttm_bo_pin(&vmw_bo->tbo); | |
| 402 | + ttm_bo_unreserve(&vmw_bo->tbo); | |
| 441 | 403 | |
| 442 | 404 | return 0; |
| 443 | − | |
| 444 | −error_free: | |
| 445 | − kfree(bo); | |
| 446 | − return ret; | |
| 447 | 405 | } |
| 448 | 406 | |
| 449 | 407 | int vmw_bo_create(struct vmw_private *vmw, |
| 450 | − size_t size, struct ttm_placement *placement, | |
| 451 | − bool interruptible, bool pin, | |
| 452 | − void (*bo_free)(struct ttm_buffer_object *bo), | |
| 453 | − struct vmw_buffer_object **p_bo) | |
| 408 | + struct vmw_bo_params *params, | |
| 409 | + struct vmw_bo **p_bo) | |
| 454 | 410 | { |
| 455 | 411 | int ret; |
| 456 | 412 | |
| 457 | − BUG_ON(!bo_free); | |
| 458 | − | |
| 459 | 413 | *p_bo = kmalloc(sizeof(**p_bo), GFP_KERNEL); |
| 460 | 414 | if (unlikely(!*p_bo)) { |
| 461 | 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 | 420 | * vmw_bo_init will delete the *p_bo object if it fails |
| 467 | 421 | */ |
| 468 | − ret = vmw_bo_init(vmw, *p_bo, size, | |
| 469 | − placement, interruptible, pin, | |
| 470 | − bo_free); | |
| 422 | + ret = vmw_bo_init(vmw, *p_bo, params, vmw_bo_free); | |
| 471 | 423 | if (unlikely(ret != 0)) |
| 472 | 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 | |
| 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 | |
| 433 | + * vmw_user_bo_synccpu_grab - Grab a struct vmw_bo for cpu | |
| 532 | 434 | * access, idling previous GPU operations on the buffer and optionally |
| 533 | 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 | 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 | 447 | uint32_t flags) |
| 546 | 448 | { |
| 547 | 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 | 451 | int ret; |
| 550 | 452 | |
| 551 | 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 | 490 | uint32_t handle, |
| 589 | 491 | uint32_t flags) |
| 590 | 492 | { |
| 591 | − struct vmw_buffer_object *vmw_bo; | |
| 493 | + struct vmw_bo *vmw_bo; | |
| 592 | 494 | int ret = vmw_user_bo_lookup(filp, handle, &vmw_bo); |
| 593 | 495 | |
| 594 | 496 | if (!ret) { |
| 595 | 497 | if (!(flags & drm_vmw_synccpu_allow_cs)) { |
| 596 | 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 | 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 | 523 | struct drm_vmw_synccpu_arg *arg = |
| 622 | 524 | (struct drm_vmw_synccpu_arg *) data; |
| 623 | − struct vmw_buffer_object *vbo; | |
| 525 | + struct vmw_bo *vbo; | |
| 624 | 526 | int ret; |
| 625 | 527 | |
| 626 | 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 | 542 | ret = vmw_user_bo_synccpu_grab(vbo, arg->flags); |
| 641 | 543 | vmw_bo_unreference(&vbo); |
| 642 | − drm_gem_object_put(&vbo->base.base); | |
| 544 | + drm_gem_object_put(&vbo->tbo.base); | |
| 643 | 545 | if (unlikely(ret != 0)) { |
| 644 | 546 | if (ret == -ERESTARTSYS || ret == -EBUSY) |
| 645 | 547 | return -EBUSY; |
| @@ -683,8 +585,7 @@ int vmw_bo_unref_ioctl(struct drm_device *dev, void *data, · 37 unmodified lines | ||
| 683 | 585 | struct drm_vmw_unref_dmabuf_arg *arg = |
| 684 | 586 | (struct drm_vmw_unref_dmabuf_arg *)data; |
| 685 | 587 | |
| 686 | − drm_gem_handle_delete(file_priv, arg->handle); | |
| 687 | − return 0; | |
| 588 | + return drm_gem_handle_delete(file_priv, arg->handle); | |
| 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 | 595 | * @filp: The file the handle is registered with. |
| 695 | 596 | * @handle: The user buffer object handle |
| 696 | 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 | 599 | * Return: Zero on success, Negative error code on error. |
| 699 | 600 | * |
| 700 | 601 | * The vmw buffer object pointer will be refcounted (both ttm and gem) |
| 701 | 602 | */ |
| 702 | 603 | int vmw_user_bo_lookup(struct drm_file *filp, |
| 703 | − uint32_t handle, | |
| 704 | − struct vmw_buffer_object **out) | |
| 604 | + u32 handle, | |
| 605 | + struct vmw_bo **out) | |
| 705 | 606 | { |
| 706 | 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 | 613 | return -ESRCH; |
| 713 | 614 | } |
| 714 | 615 | |
| 715 | − *out = gem_to_vmw_bo(gobj); | |
| 716 | − ttm_bo_get(&(*out)->base); | |
| 616 | + *out = to_vmw_bo(gobj); | |
| 617 | + ttm_bo_get(&(*out)->tbo); | |
| 717 | 618 | |
| 718 | 619 | return 0; |
| 719 | 620 | } |
| @@ -734,8 +635,7 @@ void vmw_bo_fence_single(struct ttm_buffer_object *bo, · 14 unmodified lines | ||
| 734 | 635 | struct vmw_fence_obj *fence) |
| 735 | 636 | { |
| 736 | 637 | struct ttm_device *bdev = bo->bdev; |
| 737 | − struct vmw_private *dev_priv = | |
| 738 | − container_of(bdev, struct vmw_private, bdev); | |
| 638 | + struct vmw_private *dev_priv = vmw_priv_from_ttm(bdev); | |
| 739 | 639 | int ret; |
| 740 | 640 | |
| 741 | 641 | if (fence == NULL) |
| @@ -771,7 +671,7 @@ int vmw_dumb_create(struct drm_file *file_priv, · 29 unmodified lines | ||
| 771 | 671 | struct drm_mode_create_dumb *args) |
| 772 | 672 | { |
| 773 | 673 | struct vmw_private *dev_priv = vmw_priv(dev); |
| 774 | − struct vmw_buffer_object *vbo; | |
| 674 | + struct vmw_bo *vbo; | |
| 775 | 675 | int cpp = DIV_ROUND_UP(args->bpp, 8); |
| 776 | 676 | int ret; |
| 777 | 677 | |
| @@ -795,7 +695,7 @@ int vmw_dumb_create(struct drm_file *file_priv, · 17 unmodified lines | ||
| 795 | 695 | args->size, &args->handle, |
| 796 | 696 | &vbo); |
| 797 | 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 | 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 | 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 | 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 | 724 | void vmw_bo_move_notify(struct ttm_buffer_object *bo, |
| 829 | 725 | struct ttm_resource *mem) |
| 830 | 726 | { |
| 831 | − struct vmw_buffer_object *vbo; | |
| 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); | |
| 727 | + struct vmw_bo *vbo = to_vmw_bo(&bo->base); | |
| 838 | 728 | |
| 839 | 729 | /* |
| 840 | 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 | 742 | if (mem->mem_type != VMW_PL_MOB && bo->resource->mem_type == VMW_PL_MOB) |
| 853 | 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 | 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 | 6 | * Permission is hereby granted, free of charge, to any person obtaining a |
| 7 | 7 | * copy of this software and associated documentation files (the |
| @@ -24,13 +24,13 @@ · 16 unmodified lines | ||
| 24 | 24 | * USE OR OTHER DEALINGS IN THE SOFTWARE. |
| 25 | 25 | * |
| 26 | 26 | **************************************************************************/ |
| 27 | − | |
| 28 | −#include <linux/sched/signal.h> | |
| 27 | +#include "vmwgfx_bo.h" | |
| 28 | +#include "vmwgfx_drv.h" | |
| 29 | +#include "vmwgfx_devcaps.h" | |
| 29 | 30 | |
| 30 | 31 | #include <drm/ttm/ttm_placement.h> |
| 31 | 32 | |
| 32 | −#include "vmwgfx_drv.h" | |
| 33 | −#include "vmwgfx_devcaps.h" | |
| 33 | +#include <linux/sched/signal.h> | |
| 34 | 34 | |
| 35 | 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 | 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 | 571 | struct { |
| 572 | 572 | SVGA3dCmdHeader header; |
| 573 | 573 | SVGA3dCmdWaitForQuery body; |
| @@ -613,7 +613,7 @@ static int vmw_cmd_emit_dummy_gb_query(struct vmw_private *dev_priv, · 39 unmodified lines | ||
| 613 | 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 | 617 | struct { |
| 618 | 618 | SVGA3dCmdHeader header; |
| 619 | 619 | SVGA3dCmdWaitForGBQuery body; |
| @@ -1,7 +1,7 @@ | ||
| 1 | 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 | 6 | * Permission is hereby granted, free of charge, to any person obtaining a |
| 7 | 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> | |
| 29 | −#include <linux/pci.h> | |
| 28 | +#include "vmwgfx_bo.h" | |
| 29 | +#include "vmwgfx_drv.h" | |
| 30 | 30 | |
| 31 | 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 | 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 | 80 | * frees are protected by @lock. |
| 80 | 81 | * @cmd_space: Buffer object for the command buffer space, unless we were |
| 81 | 82 | * able to make a contigous coherent DMA memory allocation, @handle. Immutable. |
| 82 | − * @map_obj: Mapping state for @cmd_space. Immutable. | |
| 83 | 83 | * @map: Pointer to command buffer space. May be a mapped buffer object or |
| 84 | 84 | * a contigous coherent DMA memory allocation. Immutable. |
| 85 | 85 | * @cur: Command buffer for small kernel command submissions. Protected by |
| @@ -116,8 +116,7 @@ struct vmw_cmdbuf_man { · 30 unmodified lines | ||
| 116 | 116 | struct vmw_cmdbuf_context ctx[SVGA_CB_CONTEXT_MAX]; |
| 117 | 117 | struct list_head error; |
| 118 | 118 | struct drm_mm mm; |
| 119 | − struct ttm_buffer_object *cmd_space; | |
| 120 | − struct ttm_bo_kmap_obj map_obj; | |
| 119 | + struct vmw_bo *cmd_space; | |
| 121 | 120 | u8 *map; |
| 122 | 121 | struct vmw_cmdbuf_header *cur; |
| 123 | 122 | size_t cur_pos; |
| @@ -888,7 +887,7 @@ static int vmw_cmdbuf_space_pool(struct vmw_cmdbuf_man *man, · 764 unmodified lines | ||
| 888 | 887 | header->cmd = man->map + offset; |
| 889 | 888 | if (man->using_mob) { |
| 890 | 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 | 891 | cb_hdr->ptr.mob.mobOffset = offset; |
| 893 | 892 | } else { |
| 894 | 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 | 1220 | int vmw_cmdbuf_set_pool_size(struct vmw_cmdbuf_man *man, size_t size) |
| 1222 | 1221 | { |
| 1223 | 1222 | struct vmw_private *dev_priv = man->dev_priv; |
| 1224 | − bool dummy; | |
| 1225 | 1223 | int ret; |
| 1226 | 1224 | |
| 1227 | 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 | 1232 | if (man->map) { |
| 1235 | 1233 | man->using_mob = false; |
| 1236 | 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 | 1243 | * DMA memory failed. If we can have command buffers in a |
| 1239 | 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 | 1249 | !dev_priv->has_mob) |
| 1245 | 1250 | return -ENOMEM; |
| 1246 | 1251 | |
| 1247 | − ret = vmw_bo_create_kernel(dev_priv, size, | |
| 1248 | − &vmw_mob_placement, | |
| 1249 | − &man->cmd_space); | |
| 1252 | + ret = vmw_bo_create(dev_priv, &bo_params, &man->cmd_space); | |
| 1250 | 1253 | if (ret) |
| 1251 | 1254 | return ret; |
| 1252 | 1255 | |
| 1253 | − man->using_mob = true; | |
| 1254 | − ret = ttm_bo_kmap(man->cmd_space, 0, size >> PAGE_SHIFT, | |
| 1255 | − &man->map_obj); | |
| 1256 | − if (ret) | |
| 1257 | − goto out_no_map; | |
| 1258 | − | |
| 1259 | − man->map = ttm_kmap_obj_virtual(&man->map_obj, &dummy); | |
| 1256 | + man->map = vmw_bo_map_and_cache(man->cmd_space); | |
| 1257 | + man->using_mob = man->map; | |
| 1260 | 1258 | } |
| 1261 | 1259 | |
| 1262 | 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 | 1274 | (man->using_mob) ? "MOB" : "DMA"); |
| 1277 | 1275 | |
| 1278 | 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 | 1372 | man->has_pool = false; |
| 1383 | 1373 | man->default_size = VMW_CMDBUF_INLINE_SIZE; |
| 1384 | 1374 | (void) vmw_cmdbuf_idle(man, false, 10*HZ); |
| 1385 | − if (man->using_mob) { | |
| 1386 | − (void) ttm_bo_kunmap(&man->map_obj); | |
| 1387 | − ttm_bo_put(man->cmd_space); | |
| 1388 | − man->cmd_space = NULL; | |
| 1389 | − } else { | |
| 1375 | + if (man->using_mob) | |
| 1376 | + vmw_bo_unreference(&man->cmd_space); | |
| 1377 | + else | |
| 1390 | 1378 | dma_free_coherent(man->dev_priv->drm.dev, |
| 1391 | 1379 | man->size, man->map, man->handle); |
| 1392 | − } | |
| 1393 | 1380 | } |
| 1394 | 1381 | |
| 1395 | 1382 | /** |
| @@ -1,7 +1,7 @@ | ||
| 1 | 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 | 6 | * Permission is hereby granted, free of charge, to any person obtaining a |
| 7 | 7 | * copy of this software and associated documentation files (the |
| @@ -27,9 +27,10 @@ · 19 unmodified lines | ||
| 27 | 27 | |
| 28 | 28 | #include <drm/ttm/ttm_placement.h> |
| 29 | 29 | |
| 30 | +#include "vmwgfx_binding.h" | |
| 31 | +#include "vmwgfx_bo.h" | |
| 30 | 32 | #include "vmwgfx_drv.h" |
| 31 | 33 | #include "vmwgfx_resource_priv.h" |
| 32 | −#include "vmwgfx_binding.h" | |
| 33 | 34 | |
| 34 | 35 | struct vmw_user_context { |
| 35 | 36 | struct ttm_base_object base; |
| @@ -38,7 +39,7 @@ struct vmw_user_context { · 2 unmodified lines | ||
| 38 | 39 | struct vmw_cmdbuf_res_manager *man; |
| 39 | 40 | struct vmw_resource *cotables[SVGA_COTABLE_MAX]; |
| 40 | 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 | 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 | 74 | static const struct vmw_res_func vmw_legacy_context_func = { |
| 74 | 75 | .res_type = vmw_res_context, |
| 75 | − .needs_backup = false, | |
| 76 | + .needs_guest_memory = false, | |
| 76 | 77 | .may_evict = false, |
| 77 | 78 | .type_name = "legacy contexts", |
| 78 | − .backup_placement = NULL, | |
| 79 | + .domain = VMW_BO_DOMAIN_SYS, | |
| 80 | + .busy_domain = VMW_BO_DOMAIN_SYS, | |
| 79 | 81 | .create = NULL, |
| 80 | 82 | .destroy = NULL, |
| 81 | 83 | .bind = NULL, |
| @@ -84,12 +86,13 @@ static const struct vmw_res_func vmw_legacy_context_func = { · 2 unmodified lines | ||
| 84 | 86 | |
| 85 | 87 | static const struct vmw_res_func vmw_gb_context_func = { |
| 86 | 88 | .res_type = vmw_res_context, |
| 87 | − .needs_backup = true, | |
| 89 | + .needs_guest_memory = true, | |
| 88 | 90 | .may_evict = true, |
| 89 | 91 | .prio = 3, |
| 90 | 92 | .dirty_prio = 3, |
| 91 | 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 | 96 | .create = vmw_gb_context_create, |
| 94 | 97 | .destroy = vmw_gb_context_destroy, |
| 95 | 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 | 102 | static const struct vmw_res_func vmw_dx_context_func = { |
| 100 | 103 | .res_type = vmw_res_dx_context, |
| 101 | − .needs_backup = true, | |
| 104 | + .needs_guest_memory = true, | |
| 102 | 105 | .may_evict = true, |
| 103 | 106 | .prio = 3, |
| 104 | 107 | .dirty_prio = 3, |
| 105 | 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 | 111 | .create = vmw_dx_context_create, |
| 108 | 112 | .destroy = vmw_dx_context_destroy, |
| 109 | 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 | 186 | struct vmw_user_context *uctx = |
| 183 | 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 | 190 | sizeof(SVGAGBContextData)); |
| 187 | 191 | ret = vmw_resource_init(dev_priv, res, true, |
| 188 | 192 | res_free, |
| @@ -354,8 +358,8 @@ static int vmw_gb_context_bind(struct vmw_resource *res, · 165 unmodified lines | ||
| 354 | 358 | cmd->header.size = sizeof(cmd->body); |
| 355 | 359 | cmd->body.cid = res->id; |
| 356 | 360 | cmd->body.mobid = bo->resource->start; |
| 357 | − cmd->body.validContents = res->backup_dirty; | |
| 358 | − res->backup_dirty = false; | |
| 361 | + cmd->body.validContents = res->guest_memory_dirty; | |
| 362 | + res->guest_memory_dirty = false; | |
| 359 | 363 | vmw_cmd_commit(dev_priv, sizeof(*cmd)); |
| 360 | 364 | |
| 361 | 365 | return 0; |
| @@ -521,8 +525,8 @@ static int vmw_dx_context_bind(struct vmw_resource *res, · 159 unmodified lines | ||
| 521 | 525 | cmd->header.size = sizeof(cmd->body); |
| 522 | 526 | cmd->body.cid = res->id; |
| 523 | 527 | cmd->body.mobid = bo->resource->start; |
| 524 | − cmd->body.validContents = res->backup_dirty; | |
| 525 | − res->backup_dirty = false; | |
| 528 | + cmd->body.validContents = res->guest_memory_dirty; | |
| 529 | + res->guest_memory_dirty = false; | |
| 526 | 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 | 857 | * specified in the parameter. 0 otherwise. |
| 854 | 858 | */ |
| 855 | 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 | 862 | struct vmw_user_context *uctx = |
| 859 | 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 | 890 | * @ctx_res: The context resource |
| 887 | 891 | */ |
| 888 | −struct vmw_buffer_object * | |
| 892 | +struct vmw_bo * | |
| 889 | 893 | vmw_context_get_dx_query_mob(struct vmw_resource *ctx_res) |
| 890 | 894 | { |
| 891 | 895 | struct vmw_user_context *uctx = |
| @@ -1,7 +1,7 @@ | ||
| 1 | 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 | 6 | * Permission is hereby granted, free of charge, to any person obtaining a |
| 7 | 7 | * copy of this software and associated documentation files (the |
| @@ -30,13 +30,14 @@ · 22 unmodified lines | ||
| 30 | 30 | * whenever the backing MOB is evicted. |
| 31 | 31 | */ |
| 32 | 32 | |
| 33 | −#include <drm/ttm/ttm_placement.h> | |
| 34 | − | |
| 33 | +#include "vmwgfx_bo.h" | |
| 35 | 34 | #include "vmwgfx_drv.h" |
| 36 | 35 | #include "vmwgfx_mksstat.h" |
| 37 | 36 | #include "vmwgfx_resource_priv.h" |
| 38 | 37 | #include "vmwgfx_so.h" |
| 39 | 38 | |
| 39 | +#include <drm/ttm/ttm_placement.h> | |
| 40 | + | |
| 40 | 41 | /** |
| 41 | 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 | 132 | static const struct vmw_res_func vmw_cotable_func = { |
| 132 | 133 | .res_type = vmw_res_cotable, |
| 133 | − .needs_backup = true, | |
| 134 | + .needs_guest_memory = true, | |
| 134 | 135 | .may_evict = true, |
| 135 | 136 | .prio = 3, |
| 136 | 137 | .dirty_prio = 3, |
| 137 | 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 | 141 | .create = vmw_cotable_create, |
| 140 | 142 | .destroy = vmw_cotable_destroy, |
| 141 | 143 | .bind = vmw_cotable_bind, |
| @@ -180,7 +182,7 @@ static int vmw_cotable_unscrub(struct vmw_resource *res) · 38 unmodified lines | ||
| 180 | 182 | { |
| 181 | 183 | struct vmw_cotable *vcotbl = vmw_cotable(res); |
| 182 | 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 | 186 | struct { |
| 185 | 187 | SVGA3dCmdHeader header; |
| 186 | 188 | SVGA3dCmdDXSetCOTable body; |
| @@ -228,7 +230,7 @@ static int vmw_cotable_bind(struct vmw_resource *res, · 41 unmodified lines | ||
| 228 | 230 | * take the opportunity to correct the value here so that it's not |
| 229 | 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 | 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 | 291 | cmd0->body.cid = vcotbl->ctx->id; |
| 290 | 292 | cmd0->body.type = vcotbl->type; |
| 291 | 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 | 296 | cmd1->header.id = SVGA_3D_CMD_DX_SET_COTABLE; |
| 295 | 297 | cmd1->header.size = sizeof(cmd1->body); |
| @@ -371,12 +373,12 @@ static int vmw_cotable_readback(struct vmw_resource *res) · 75 unmodified lines | ||
| 371 | 373 | cmd->header.size = sizeof(cmd->body); |
| 372 | 374 | cmd->body.cid = vcotbl->ctx->id; |
| 373 | 375 | cmd->body.type = vcotbl->type; |
| 374 | − vcotbl->size_read_back = res->backup_size; | |
| 376 | + vcotbl->size_read_back = res->guest_memory_size; | |
| 375 | 377 | vmw_cmd_commit(dev_priv, sizeof(*cmd)); |
| 376 | 378 | } |
| 377 | 379 | |
| 378 | 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 | 382 | vmw_fence_obj_unreference(&fence); |
| 381 | 383 | |
| 382 | 384 | return 0; |
| @@ -399,14 +401,21 @@ static int vmw_cotable_resize(struct vmw_resource *res, size_t new_size) · 16 unmodified lines | ||
| 399 | 401 | struct ttm_operation_ctx ctx = { false, false }; |
| 400 | 402 | struct vmw_private *dev_priv = res->dev_priv; |
| 401 | 403 | struct vmw_cotable *vcotbl = vmw_cotable(res); |
| 402 | − struct vmw_buffer_object *buf, *old_buf = res->backup; | |
| 403 | − struct ttm_buffer_object *bo, *old_bo = &res->backup->base; | |
| 404 | − size_t old_size = res->backup_size; | |
| 404 | + struct vmw_bo *buf, *old_buf = res->guest_memory_bo; | |
| 405 | + struct ttm_buffer_object *bo, *old_bo = &res->guest_memory_bo->tbo; | |
| 406 | + size_t old_size = res->guest_memory_size; | |
| 405 | 407 | size_t old_size_read_back = vcotbl->size_read_back; |
| 406 | 408 | size_t cur_size_read_back; |
| 407 | 409 | struct ttm_bo_kmap_obj old_map, new_map; |
| 408 | 410 | int ret; |
| 409 | 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 | 420 | MKS_STAT_TIME_DECL(MKSSTAT_KERN_COTABLE_RESIZE); |
| 412 | 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 | 432 | * for the new COTable. Initially pin the buffer object to make sure |
| 424 | 433 | * we can use tryreserve without failure. |
| 425 | 434 | */ |
| 426 | − ret = vmw_bo_create(dev_priv, new_size, &vmw_mob_placement, | |
| 427 | − true, true, vmw_bo_bo_free, &buf); | |
| 435 | + ret = vmw_bo_create(dev_priv, &bo_params, &buf); | |
| 428 | 436 | if (ret) { |
| 429 | 437 | DRM_ERROR("Failed initializing new cotable MOB.\n"); |
| 430 | 438 | goto out_done; |
| 431 | 439 | } |
| 432 | 440 | |
| 433 | − bo = &buf->base; | |
| 441 | + bo = &buf->tbo; | |
| 434 | 442 | WARN_ON_ONCE(ttm_bo_reserve(bo, false, true, NULL)); |
| 435 | 443 | |
| 436 | 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 | 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 | 479 | if (unlikely(ret != 0)) { |
| 469 | 480 | DRM_ERROR("Failed validating new COTable backup buffer.\n"); |
| 470 | 481 | goto out_wait; |
| 471 | 482 | } |
| 472 | 483 | |
| 473 | 484 | vmw_resource_mob_detach(res); |
| 474 | − res->backup = buf; | |
| 475 | − res->backup_size = new_size; | |
| 485 | + res->guest_memory_bo = buf; | |
| 486 | + res->guest_memory_size = new_size; | |
| 476 | 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 | 493 | ret = vmw_cotable_unscrub(res); |
| 483 | 494 | if (ret) { |
| 484 | 495 | DRM_ERROR("Failed switching COTable backup buffer.\n"); |
| 485 | − res->backup = old_buf; | |
| 486 | − res->backup_size = old_size; | |
| 496 | + res->guest_memory_bo = old_buf; | |
| 497 | + res->guest_memory_size = old_size; | |
| 487 | 498 | vcotbl->size_read_back = old_size_read_back; |
| 488 | 499 | vmw_resource_mob_attach(res); |
| 489 | 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 | 509 | if (unlikely(ret)) |
| 499 | 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 | 513 | ttm_bo_unpin(bo); |
| 503 | 514 | |
| 504 | 515 | MKS_STAT_TIME_POP(MKSSTAT_KERN_COTABLE_RESIZE); |
| @@ -533,7 +544,7 @@ out_done: · 28 unmodified lines | ||
| 533 | 544 | static int vmw_cotable_create(struct vmw_resource *res) |
| 534 | 545 | { |
| 535 | 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 | 548 | size_t needed_size; |
| 538 | 549 | int ret; |
| 539 | 550 | |
| @@ -542,7 +553,7 @@ static int vmw_cotable_create(struct vmw_resource *res) · 2 unmodified lines | ||
| 542 | 553 | while (needed_size > new_size) |
| 543 | 554 | new_size *= 2; |
| 544 | 555 | |
| 545 | − if (likely(new_size <= res->backup_size)) { | |
| 556 | + if (likely(new_size <= res->guest_memory_size)) { | |
| 546 | 557 | if (vcotbl->scrubbed && vmw_resource_mob_attached(res)) { |
| 547 | 558 | ret = vmw_cotable_unscrub(res); |
| 548 | 559 | if (ret) |
| @@ -606,12 +617,12 @@ struct vmw_resource *vmw_cotable_alloc(struct vmw_private *dev_priv, · 57 unmodified lines | ||
| 606 | 617 | |
| 607 | 618 | INIT_LIST_HEAD(&vcotbl->resource_list); |
| 608 | 619 | vcotbl->res.id = type; |
| 609 | − vcotbl->res.backup_size = PAGE_SIZE; | |
| 620 | + vcotbl->res.guest_memory_size = PAGE_SIZE; | |
| 610 | 621 | num_entries = PAGE_SIZE / co_info[type].size; |
| 611 | 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 | 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 | 628 | vcotbl->scrubbed = true; |
| @@ -1,7 +1,7 @@ | ||
| 1 | 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 | 6 | * Permission is hereby granted, free of charge, to any person obtaining a |
| 7 | 7 | * copy of this software and associated documentation files (the |
| @@ -28,9 +28,10 @@ · 20 unmodified lines | ||
| 28 | 28 | |
| 29 | 29 | #include "vmwgfx_drv.h" |
| 30 | 30 | |
| 31 | +#include "vmwgfx_bo.h" | |
| 32 | +#include "vmwgfx_binding.h" | |
| 31 | 33 | #include "vmwgfx_devcaps.h" |
| 32 | 34 | #include "vmwgfx_mksstat.h" |
| 33 | −#include "vmwgfx_binding.h" | |
| 34 | 35 | #include "ttm_object.h" |
| 35 | 36 | |
| 36 | 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 | 387 | static int vmw_dummy_query_bo_create(struct vmw_private *dev_priv) |
| 387 | 388 | { |
| 388 | 389 | int ret; |
| 389 | − struct vmw_buffer_object *vbo; | |
| 390 | + struct vmw_bo *vbo; | |
| 390 | 391 | struct ttm_bo_kmap_obj map; |
| 391 | 392 | volatile SVGA3dQueryResult *result; |
| 392 | 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 | 403 | * Create the vbo as pinned, so that a tryreserve will |
| 396 | 404 | * immediately succeed. This is because we're the only |
| 397 | 405 | * user of the bo currently. |
| 398 | 406 | */ |
| 399 | − ret = vmw_bo_create(dev_priv, PAGE_SIZE, | |
| 400 | − &vmw_sys_placement, false, true, | |
| 401 | − &vmw_bo_bo_free, &vbo); | |
| 407 | + ret = vmw_bo_create(dev_priv, &bo_params, &vbo); | |
| 402 | 408 | if (unlikely(ret != 0)) |
| 403 | 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 | 412 | BUG_ON(ret != 0); |
| 407 | 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 | 416 | if (likely(ret == 0)) { |
| 411 | 417 | result = ttm_kmap_obj_virtual(&map, &dummy); |
| 412 | 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 | 421 | ttm_bo_kunmap(&map); |
| 416 | 422 | } |
| 417 | 423 | vmw_bo_pin_reserved(vbo, false); |
| 418 | − ttm_bo_unreserve(&vbo->base); | |
| 424 | + ttm_bo_unreserve(&vbo->tbo); | |
| 419 | 425 | |
| 420 | 426 | if (unlikely(ret != 0)) { |
| 421 | 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 | 1571 | .open = drm_open, |
| 1566 | 1572 | .release = drm_release, |
| 1567 | 1573 | .unlocked_ioctl = vmw_unlocked_ioctl, |
| 1568 | − .mmap = vmw_mmap, | |
| 1574 | + .mmap = drm_gem_mmap, | |
| 1569 | 1575 | .poll = drm_poll, |
| 1570 | 1576 | .read = drm_read, |
| 1571 | 1577 | #if defined(CONFIG_COMPAT) |
| @@ -1,7 +1,7 @@ | ||
| 1 | 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 | 6 | * Permission is hereby granted, free of charge, to any person obtaining a |
| 7 | 7 | * copy of this software and associated documentation files (the |
| @@ -117,32 +117,6 @@ struct vmwgfx_hash_item { · 109 unmodified lines | ||
| 117 | 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 | 122 | * struct vmw_validate_buffer - Carries validation info about buffers. |
| @@ -168,21 +142,23 @@ struct vmw_res_func; · 19 unmodified lines | ||
| 168 | 142 | * @kref: For refcounting. |
| 169 | 143 | * @dev_priv: Pointer to the device private for this resource. Immutable. |
| 170 | 144 | * @id: Device id. Protected by @dev_priv::resource_lock. |
| 171 | − * @backup_size: Backup buffer size. Immutable. | |
| 172 | − * @res_dirty: Resource contains data not yet in the backup buffer. Protected | |
| 173 | − * by resource reserved. | |
| 174 | − * @backup_dirty: Backup buffer contains data not yet in the HW resource. | |
| 145 | + * @guest_memory_size: Guest memory buffer size. Immutable. | |
| 146 | + * @res_dirty: Resource contains data not yet in the guest memory buffer. | |
| 175 | 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 | 150 | * @coherent: Emulate coherency by tracking vm accesses. |
| 177 | − * @backup: The backup buffer if any. Protected by resource reserved. | |
| 178 | − * @backup_offset: Offset into the backup buffer if any. Protected by resource | |
| 179 | − * reserved. Note that only a few resource types can have a @backup_offset | |
| 180 | − * different from zero. | |
| 151 | + * @guest_memory_bo: The guest memory buffer if any. Protected by resource | |
| 152 | + * reserved. | |
| 153 | + * @guest_memory_offset: Offset into the guest memory buffer if any. Protected | |
| 154 | + * by resource reserved. Note that only a few resource types can have a | |
| 155 | + * @guest_memory_offset different from zero. | |
| 181 | 156 | * @pin_count: The pin count for this resource. A pinned resource has a |
| 182 | 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 | 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 | 162 | * @lru_head: List head for the LRU list. Protected by @dev_priv::resource_lock. |
| 187 | 163 | * @binding_head: List head for the context binding list. Protected by |
| 188 | 164 | * the @dev_priv::binding_mutex |
| @@ -190,18 +166,20 @@ struct vmw_res_func; · 1 unmodified line | ||
| 190 | 166 | * @hw_destroy: Callback to destroy the resource on the device, as part of |
| 191 | 167 | * resource destruction. |
| 192 | 168 | */ |
| 169 | +struct vmw_bo; | |
| 170 | +struct vmw_bo; | |
| 193 | 171 | struct vmw_resource_dirty; |
| 194 | 172 | struct vmw_resource { |
| 195 | 173 | struct kref kref; |
| 196 | 174 | struct vmw_private *dev_priv; |
| 197 | 175 | int id; |
| 198 | 176 | u32 used_prio; |
| 199 | − unsigned long backup_size; | |
| 177 | + unsigned long guest_memory_size; | |
| 200 | 178 | u32 res_dirty : 1; |
| 201 | − u32 backup_dirty : 1; | |
| 179 | + u32 guest_memory_dirty : 1; | |
| 202 | 180 | u32 coherent : 1; |
| 203 | − struct vmw_buffer_object *backup; | |
| 204 | − unsigned long backup_offset; | |
| 181 | + struct vmw_bo *guest_memory_bo; | |
| 182 | + unsigned long guest_memory_offset; | |
| 205 | 183 | unsigned long pin_count; |
| 206 | 184 | const struct vmw_res_func *func; |
| 207 | 185 | struct rb_node mob_node; |
| @@ -446,7 +424,7 @@ struct vmw_sw_context{ · 238 unmodified lines | ||
| 446 | 424 | struct drm_file *filp; |
| 447 | 425 | uint32_t *cmd_bounce; |
| 448 | 426 | uint32_t cmd_bounce_size; |
| 449 | − struct vmw_buffer_object *cur_query_bo; | |
| 427 | + struct vmw_bo *cur_query_bo; | |
| 450 | 428 | struct list_head bo_relocations; |
| 451 | 429 | struct list_head res_relocations; |
| 452 | 430 | uint32_t *buf_start; |
| @@ -458,7 +436,7 @@ struct vmw_sw_context{ · 5 unmodified lines | ||
| 458 | 436 | struct list_head staged_cmd_res; |
| 459 | 437 | struct list_head ctx_list; |
| 460 | 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 | 440 | struct vmw_resource *dx_query_ctx; |
| 463 | 441 | struct vmw_cmdbuf_res_manager *man; |
| 464 | 442 | struct vmw_validation_context *ctx; |
| @@ -492,7 +470,7 @@ struct vmw_otable_batch { · 27 unmodified lines | ||
| 492 | 470 | unsigned num_otables; |
| 493 | 471 | struct vmw_otable *otables; |
| 494 | 472 | struct vmw_resource *context; |
| 495 | − struct ttm_buffer_object *otable_bo; | |
| 473 | + struct vmw_bo *otable_bo; | |
| 496 | 474 | }; |
| 497 | 475 | |
| 498 | 476 | enum { |
| @@ -632,8 +610,8 @@ struct vmw_private { · 133 unmodified lines | ||
| 632 | 610 | * are protected by the cmdbuf mutex. |
| 633 | 611 | */ |
| 634 | 612 | |
| 635 | − struct vmw_buffer_object *dummy_query_bo; | |
| 636 | − struct vmw_buffer_object *pinned_bo; | |
| 613 | + struct vmw_bo *dummy_query_bo; | |
| 614 | + struct vmw_bo *pinned_bo; | |
| 637 | 615 | uint32_t query_cid; |
| 638 | 616 | uint32_t query_cid_valid; |
| 639 | 617 | bool dummy_query_bo_pinned; |
| @@ -677,11 +655,6 @@ struct vmw_private { · 37 unmodified lines | ||
| 677 | 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 | 658 | static inline struct vmw_surface *vmw_res_to_srf(struct vmw_resource *res) |
| 686 | 659 | { |
| 687 | 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 | 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 | 673 | static inline struct vmw_fpriv *vmw_fpriv(struct drm_file *file_priv) |
| 696 | 674 | { |
| 697 | 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 | 803 | struct drm_file *filp, |
| 826 | 804 | uint32_t handle, |
| 827 | 805 | struct vmw_surface **out_surf, |
| 828 | − struct vmw_buffer_object **out_buf); | |
| 806 | + struct vmw_bo **out_buf); | |
| 829 | 807 | extern int vmw_user_resource_lookup_handle( |
| 830 | 808 | struct vmw_private *dev_priv, |
| 831 | 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 | 822 | extern void vmw_resource_unreserve(struct vmw_resource *res, |
| 845 | 823 | bool dirty_set, |
| 846 | 824 | bool dirty, |
| 847 | − bool switch_backup, | |
| 848 | − struct vmw_buffer_object *new_backup, | |
| 849 | − unsigned long new_backup_offset); | |
| 825 | + bool switch_guest_memory, | |
| 826 | + struct vmw_bo *new_guest_memory, | |
| 827 | + unsigned long new_guest_memory_offset); | |
| 850 | 828 | extern void vmw_query_move_notify(struct ttm_buffer_object *bo, |
| 851 | 829 | struct ttm_resource *old_mem, |
| 852 | 830 | struct ttm_resource *new_mem); |
| 853 | −extern int vmw_query_readback_all(struct vmw_buffer_object *dx_query_mob); | |
| 854 | −extern void vmw_resource_evict_all(struct vmw_private *dev_priv); | |
| 855 | −extern void vmw_resource_unbind_list(struct vmw_buffer_object *vbo); | |
| 831 | +int vmw_query_readback_all(struct vmw_bo *dx_query_mob); | |
| 832 | +void vmw_resource_evict_all(struct vmw_private *dev_priv); | |
| 833 | +void vmw_resource_unbind_list(struct vmw_bo *vbo); | |
| 856 | 834 | void vmw_resource_mob_attach(struct vmw_resource *res); |
| 857 | 835 | void vmw_resource_mob_detach(struct vmw_resource *res); |
| 858 | 836 | void vmw_resource_dirty_update(struct vmw_resource *res, pgoff_t start, |
| 859 | 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 | 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 | 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 | 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 | 856 | struct drm_file *filp, |
| 980 | 857 | uint32_t size, |
| 981 | 858 | uint32_t *handle, |
| 982 | − struct vmw_buffer_object **p_vbo); | |
| 859 | + struct vmw_bo **p_vbo); | |
| 983 | 860 | extern int vmw_gem_object_create_ioctl(struct drm_device *dev, void *data, |
| 984 | 861 | struct drm_file *filp); |
| 985 | −extern void vmw_gem_destroy(struct ttm_buffer_object *bo); | |
| 986 | 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 | 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 | 935 | * TTM buffer object driver - vmwgfx_ttm_buffer.c |
| 1066 | 936 | */ |
| 1067 | 937 | |
| 1068 | 938 | extern const size_t vmw_tt_size; |
| 1069 | 939 | extern struct ttm_placement vmw_vram_placement; |
| 1070 | −extern struct ttm_placement vmw_vram_sys_placement; | |
| 1071 | 940 | extern struct ttm_placement vmw_vram_gmr_placement; |
| 1072 | 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 | 942 | extern struct ttm_device_funcs vmw_bo_driver; |
| 1077 | 943 | extern const struct vmw_sg_table * |
| 1078 | 944 | vmw_bo_sg_table(struct ttm_buffer_object *bo); |
| 1079 | −extern int vmw_bo_create_and_populate(struct vmw_private *dev_priv, | |
| 1080 | − unsigned long bo_size, | |
| 1081 | − struct ttm_buffer_object **bo_p); | |
| 945 | +int vmw_bo_create_and_populate(struct vmw_private *dev_priv, | |
| 946 | + size_t bo_size, | |
| 947 | + u32 domain, | |
| 948 | + struct vmw_bo **bo_p); | |
| 1082 | 949 | |
| 1083 | 950 | extern void vmw_piter_start(struct vmw_piter *viter, |
| 1084 | 951 | const struct vmw_sg_table *vsgt, |
| @@ -1297,8 +1164,8 @@ vmw_context_binding_state(struct vmw_resource *ctx); · 212 unmodified lines | ||
| 1297 | 1164 | extern void vmw_dx_context_scrub_cotables(struct vmw_resource *ctx, |
| 1298 | 1165 | bool readback); |
| 1299 | 1166 | extern int vmw_context_bind_dx_query(struct vmw_resource *ctx_res, |
| 1300 | − struct vmw_buffer_object *mob); | |
| 1301 | −extern struct vmw_buffer_object * | |
| 1167 | + struct vmw_bo *mob); | |
| 1168 | +extern struct vmw_bo * | |
| 1302 | 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 | 1390 | DRM_DEBUG_DRIVER(fmt, ##__VA_ARGS__) |
| 1524 | 1391 | |
| 1525 | 1392 | /* Resource dirtying - vmwgfx_page_dirty.c */ |
| 1526 | −void vmw_bo_dirty_scan(struct vmw_buffer_object *vbo); | |
| 1527 | −int vmw_bo_dirty_add(struct vmw_buffer_object *vbo); | |
| 1393 | +void vmw_bo_dirty_scan(struct vmw_bo *vbo); | |
| 1394 | +int vmw_bo_dirty_add(struct vmw_bo *vbo); | |
| 1528 | 1395 | void vmw_bo_dirty_transfer_to_res(struct vmw_resource *res); |
| 1529 | 1396 | void vmw_bo_dirty_clear_res(struct vmw_resource *res); |
| 1530 | −void vmw_bo_dirty_release(struct vmw_buffer_object *vbo); | |
| 1531 | −void vmw_bo_dirty_unmap(struct vmw_buffer_object *vbo, | |
| 1397 | +void vmw_bo_dirty_release(struct vmw_bo *vbo); | |
| 1398 | +void vmw_bo_dirty_unmap(struct vmw_bo *vbo, | |
| 1532 | 1399 | pgoff_t start, pgoff_t end); |
| 1533 | 1400 | vm_fault_t vmw_bo_vm_fault(struct vm_fault *vmf); |
| 1534 | 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 | 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 | 1431 | static inline void vmw_fifo_resource_inc(struct vmw_private *dev_priv) |
| 1581 | 1432 | { |
| 1582 | 1433 | atomic_inc(&dev_priv->num_fifo_resources); |
| @@ -1,7 +1,7 @@ | ||
| 1 | 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 | 6 | * Permission is hereby granted, free of charge, to any person obtaining a |
| 7 | 7 | * copy of this software and associated documentation files (the |
| @@ -24,17 +24,17 @@ · 16 unmodified lines | ||
| 24 | 24 | * USE OR OTHER DEALINGS IN THE SOFTWARE. |
| 25 | 25 | * |
| 26 | 26 | **************************************************************************/ |
| 27 | −#include <linux/sync_file.h> | |
| 28 | −#include <linux/hashtable.h> | |
| 29 | − | |
| 27 | +#include "vmwgfx_binding.h" | |
| 28 | +#include "vmwgfx_bo.h" | |
| 30 | 29 | #include "vmwgfx_drv.h" |
| 31 | −#include "vmwgfx_reg.h" | |
| 30 | +#include "vmwgfx_mksstat.h" | |
| 31 | +#include "vmwgfx_so.h" | |
| 32 | + | |
| 32 | 33 | #include <drm/ttm/ttm_bo.h> |
| 33 | 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 | 40 | * Helper macro to get dx_ctx_node if available otherwise print an error |
| @@ -65,7 +65,7 @@ · 24 unmodified lines | ||
| 65 | 65 | */ |
| 66 | 66 | struct vmw_relocation { |
| 67 | 67 | struct list_head head; |
| 68 | − struct vmw_buffer_object *vbo; | |
| 68 | + struct vmw_bo *vbo; | |
| 69 | 69 | union { |
| 70 | 70 | SVGAMobId *mob_loc; |
| 71 | 71 | SVGAGuestPtr *location; |
| @@ -149,7 +149,7 @@ static int vmw_resource_context_res_add(struct vmw_private *dev_priv, · 77 unmodified lines | ||
| 149 | 149 | static int vmw_translate_mob_ptr(struct vmw_private *dev_priv, |
| 150 | 150 | struct vmw_sw_context *sw_context, |
| 151 | 151 | SVGAMobId *id, |
| 152 | − struct vmw_buffer_object **vmw_bo_p); | |
| 152 | + struct vmw_bo **vmw_bo_p); | |
| 153 | 153 | /** |
| 154 | 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 | 476 | if (has_sm4_context(dev_priv) && |
| 477 | 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 | 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 | 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 | 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 | 600 | return ret; |
| 597 | 601 | |
| 598 | 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 | 605 | expected_dx_query_mob = |
| 602 | 606 | vmw_context_get_dx_query_mob(sw_context->dx_query_ctx); |
| @@ -703,7 +707,7 @@ res_check_done: · 100 unmodified lines | ||
| 703 | 707 | static int vmw_rebind_all_dx_query(struct vmw_resource *ctx_res) |
| 704 | 708 | { |
| 705 | 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 | 711 | VMW_DECLARE_CMD_VAR(*cmd, SVGA3dCmdDXBindAllQuery); |
| 708 | 712 | |
| 709 | 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 | 722 | cmd->header.id = SVGA_3D_CMD_DX_BIND_ALL_QUERY; |
| 719 | 723 | cmd->header.size = sizeof(cmd->body); |
| 720 | 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 | 726 | vmw_cmd_commit(dev_priv, sizeof(*cmd)); |
| 723 | 727 | |
| 724 | 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 | 1021 | * after successful submission of the current command batch. |
| 1018 | 1022 | */ |
| 1019 | 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 | 1025 | struct vmw_sw_context *sw_context) |
| 1022 | 1026 | { |
| 1023 | 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 | 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 | 1037 | VMW_DEBUG_USER("Query buffer too large.\n"); |
| 1034 | 1038 | return -EINVAL; |
| 1035 | 1039 | } |
| 1036 | 1040 | |
| 1037 | 1041 | if (unlikely(sw_context->cur_query_bo != NULL)) { |
| 1038 | 1042 | sw_context->needs_post_query_barrier = true; |
| 1043 | + vmw_bo_placement_set_default_accelerated(sw_context->cur_query_bo); | |
| 1039 | 1044 | ret = vmw_validation_add_bo(sw_context->ctx, |
| 1040 | − sw_context->cur_query_bo, | |
| 1041 | − dev_priv->has_mob, false); | |
| 1045 | + sw_context->cur_query_bo); | |
| 1042 | 1046 | if (unlikely(ret != 0)) |
| 1043 | 1047 | return ret; |
| 1044 | 1048 | } |
| 1045 | 1049 | sw_context->cur_query_bo = new_query_bo; |
| 1046 | 1050 | |
| 1051 | + vmw_bo_placement_set_default_accelerated(dev_priv->dummy_query_bo); | |
| 1047 | 1052 | ret = vmw_validation_add_bo(sw_context->ctx, |
| 1048 | − dev_priv->dummy_query_bo, | |
| 1049 | − dev_priv->has_mob, false); | |
| 1053 | + dev_priv->dummy_query_bo); | |
| 1050 | 1054 | if (unlikely(ret != 0)) |
| 1051 | 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 | 1149 | static int vmw_translate_mob_ptr(struct vmw_private *dev_priv, |
| 1146 | 1150 | struct vmw_sw_context *sw_context, |
| 1147 | 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 | 1155 | uint32_t handle = *id; |
| 1152 | 1156 | struct vmw_relocation *reloc; |
| 1153 | 1157 | int ret; |
| @@ -1158,9 +1162,10 @@ static int vmw_translate_mob_ptr(struct vmw_private *dev_priv, · 4 unmodified lines | ||
| 1158 | 1162 | drm_dbg(&dev_priv->drm, "Could not find or use MOB buffer.\n"); |
| 1159 | 1163 | return PTR_ERR(vmw_bo); |
| 1160 | 1164 | } |
| 1161 | − ret = vmw_validation_add_bo(sw_context->ctx, vmw_bo, true, false); | |
| 1162 | − ttm_bo_put(&vmw_bo->base); | |
| 1163 | − drm_gem_object_put(&vmw_bo->base.base); | |
| 1165 | + vmw_bo_placement_set(vmw_bo, VMW_BO_DOMAIN_MOB, VMW_BO_DOMAIN_MOB); | |
| 1166 | + ret = vmw_validation_add_bo(sw_context->ctx, vmw_bo); | |
| 1167 | + ttm_bo_put(&vmw_bo->tbo); | |
| 1168 | + drm_gem_object_put(&vmw_bo->tbo.base); | |
| 1164 | 1169 | if (unlikely(ret != 0)) |
| 1165 | 1170 | return ret; |
| 1166 | 1171 | |
| @@ -1200,9 +1205,9 @@ static int vmw_translate_mob_ptr(struct vmw_private *dev_priv, · 33 unmodified lines | ||
| 1200 | 1205 | static int vmw_translate_guest_ptr(struct vmw_private *dev_priv, |
| 1201 | 1206 | struct vmw_sw_context *sw_context, |
| 1202 | 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 | 1211 | uint32_t handle = ptr->gmrId; |
| 1207 | 1212 | struct vmw_relocation *reloc; |
| 1208 | 1213 | int ret; |
| @@ -1213,9 +1218,11 @@ static int vmw_translate_guest_ptr(struct vmw_private *dev_priv, · 4 unmodified lines | ||
| 1213 | 1218 | drm_dbg(&dev_priv->drm, "Could not find or use GMR region.\n"); |
| 1214 | 1219 | return PTR_ERR(vmw_bo); |
| 1215 | 1220 | } |
| 1216 | − ret = vmw_validation_add_bo(sw_context->ctx, vmw_bo, false, false); | |
| 1217 | − ttm_bo_put(&vmw_bo->base); | |
| 1218 | − drm_gem_object_put(&vmw_bo->base.base); | |
| 1221 | + vmw_bo_placement_set(vmw_bo, VMW_BO_DOMAIN_GMR | VMW_BO_DOMAIN_VRAM, | |
| 1222 | + VMW_BO_DOMAIN_GMR | VMW_BO_DOMAIN_VRAM); | |
| 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 | 1226 | if (unlikely(ret != 0)) |
| 1220 | 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 | 1287 | SVGA3dCmdHeader *header) |
| 1281 | 1288 | { |
| 1282 | 1289 | VMW_DECLARE_CMD_VAR(*cmd, SVGA3dCmdDXBindQuery); |
| 1283 | − struct vmw_buffer_object *vmw_bo; | |
| 1290 | + struct vmw_bo *vmw_bo; | |
| 1284 | 1291 | int ret; |
| 1285 | 1292 | |
| 1286 | 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 | 1370 | struct vmw_sw_context *sw_context, |
| 1364 | 1371 | SVGA3dCmdHeader *header) |
| 1365 | 1372 | { |
| 1366 | − struct vmw_buffer_object *vmw_bo; | |
| 1373 | + struct vmw_bo *vmw_bo; | |
| 1367 | 1374 | VMW_DECLARE_CMD_VAR(*cmd, SVGA3dCmdEndGBQuery); |
| 1368 | 1375 | int ret; |
| 1369 | 1376 | |
| @@ -1393,7 +1400,7 @@ static int vmw_cmd_end_query(struct vmw_private *dev_priv, · 23 unmodified lines | ||
| 1393 | 1400 | struct vmw_sw_context *sw_context, |
| 1394 | 1401 | SVGA3dCmdHeader *header) |
| 1395 | 1402 | { |
| 1396 | − struct vmw_buffer_object *vmw_bo; | |
| 1403 | + struct vmw_bo *vmw_bo; | |
| 1397 | 1404 | VMW_DECLARE_CMD_VAR(*cmd, SVGA3dCmdEndQuery); |
| 1398 | 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 | 1446 | struct vmw_sw_context *sw_context, |
| 1440 | 1447 | SVGA3dCmdHeader *header) |
| 1441 | 1448 | { |
| 1442 | − struct vmw_buffer_object *vmw_bo; | |
| 1449 | + struct vmw_bo *vmw_bo; | |
| 1443 | 1450 | VMW_DECLARE_CMD_VAR(*cmd, SVGA3dCmdWaitForGBQuery); |
| 1444 | 1451 | int ret; |
| 1445 | 1452 | |
| @@ -1467,7 +1474,7 @@ static int vmw_cmd_wait_query(struct vmw_private *dev_priv, · 21 unmodified lines | ||
| 1467 | 1474 | struct vmw_sw_context *sw_context, |
| 1468 | 1475 | SVGA3dCmdHeader *header) |
| 1469 | 1476 | { |
| 1470 | − struct vmw_buffer_object *vmw_bo; | |
| 1477 | + struct vmw_bo *vmw_bo; | |
| 1471 | 1478 | VMW_DECLARE_CMD_VAR(*cmd, SVGA3dCmdWaitForQuery); |
| 1472 | 1479 | int ret; |
| 1473 | 1480 | |
| @@ -1504,7 +1511,7 @@ static int vmw_cmd_dma(struct vmw_private *dev_priv, · 30 unmodified lines | ||
| 1504 | 1511 | struct vmw_sw_context *sw_context, |
| 1505 | 1512 | SVGA3dCmdHeader *header) |
| 1506 | 1513 | { |
| 1507 | − struct vmw_buffer_object *vmw_bo = NULL; | |
| 1514 | + struct vmw_bo *vmw_bo = NULL; | |
| 1508 | 1515 | struct vmw_surface *srf = NULL; |
| 1509 | 1516 | VMW_DECLARE_CMD_VAR(*cmd, SVGA3dCmdSurfaceDMA); |
| 1510 | 1517 | int ret; |
| @@ -1528,7 +1535,7 @@ static int vmw_cmd_dma(struct vmw_private *dev_priv, · 17 unmodified lines | ||
| 1528 | 1535 | return ret; |
| 1529 | 1536 | |
| 1530 | 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 | 1539 | if (unlikely(cmd->body.guest.ptr.offset > bo_size)) { |
| 1533 | 1540 | VMW_DEBUG_USER("Invalid DMA offset.\n"); |
| 1534 | 1541 | return -EINVAL; |
| @@ -1551,7 +1558,7 @@ static int vmw_cmd_dma(struct vmw_private *dev_priv, · 16 unmodified lines | ||
| 1551 | 1558 | |
| 1552 | 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 | 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 | 1677 | struct vmw_sw_context *sw_context, |
| 1671 | 1678 | void *buf) |
| 1672 | 1679 | { |
| 1673 | − struct vmw_buffer_object *vmw_bo; | |
| 1680 | + struct vmw_bo *vmw_bo; | |
| 1674 | 1681 | |
| 1675 | 1682 | struct { |
| 1676 | 1683 | uint32_t header; |
| @@ -1701,7 +1708,7 @@ static int vmw_cmd_res_switch_backup(struct vmw_private *dev_priv, · 24 unmodified lines | ||
| 1701 | 1708 | struct vmw_resource *res, uint32_t *buf_id, |
| 1702 | 1709 | unsigned long backup_offset) |
| 1703 | 1710 | { |
| 1704 | − struct vmw_buffer_object *vbo; | |
| 1711 | + struct vmw_bo *vbo; | |
| 1705 | 1712 | void *info; |
| 1706 | 1713 | int ret; |
| 1707 | 1714 | |
| @@ -3754,7 +3761,7 @@ static void vmw_apply_relocations(struct vmw_sw_context *sw_context) · 2046 unmodified lines | ||
| 3754 | 3761 | struct ttm_buffer_object *bo; |
| 3755 | 3762 | |
| 3756 | 3763 | list_for_each_entry(reloc, &sw_context->bo_relocations, head) { |
| 3757 | − bo = &reloc->vbo->base; | |
| 3764 | + bo = &reloc->vbo->tbo; | |
| 3758 | 3765 | switch (bo->resource->mem_type) { |
| 3759 | 3766 | case TTM_PL_VRAM: |
| 3760 | 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 | 4371 | if (dev_priv->pinned_bo == NULL) |
| 4365 | 4372 | goto out_unlock; |
| 4366 | 4373 | |
| 4367 | − ret = vmw_validation_add_bo(&val_ctx, dev_priv->pinned_bo, false, | |
| 4368 | − false); | |
| 4374 | + vmw_bo_placement_set(dev_priv->pinned_bo, | |
| 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 | 4378 | if (ret) |
| 4370 | 4379 | goto out_no_reserve; |
| 4371 | 4380 | |
| 4372 | − ret = vmw_validation_add_bo(&val_ctx, dev_priv->dummy_query_bo, false, | |
| 4373 | − false); | |
| 4381 | + vmw_bo_placement_set(dev_priv->dummy_query_bo, | |
| 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 | 4385 | if (ret) |
| 4375 | 4386 | goto out_no_reserve; |
| 4376 | 4387 | |
| @@ -1,7 +1,7 @@ | ||
| 1 | 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 | 6 | * Permission is hereby granted, free of charge, to any person obtaining a |
| 7 | 7 | * copy of this software and associated documentation files (the |
| @@ -1,6 +1,6 @@ | ||
| 1 | 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 | 5 | * Permission is hereby granted, free of charge, to any person |
| 6 | 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 | 28 | #include "vmwgfx_drv.h" |
| 28 | 29 | |
| 29 | 30 | #include "drm/drm_prime.h" |
| 30 | 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 | 33 | static void vmw_gem_object_free(struct drm_gem_object *gobj) |
| 47 | 34 | { |
| 48 | 35 | struct ttm_buffer_object *bo = drm_gem_ttm_of_gem(gobj); |
| 49 | − if (bo) { | |
| 36 | + if (bo) | |
| 50 | 37 | ttm_bo_put(bo); |
| 51 | − } | |
| 52 | 38 | } |
| 53 | 39 | |
| 54 | 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 | 51 | static int vmw_gem_pin_private(struct drm_gem_object *obj, bool do_pin) |
| 66 | 52 | { |
| 67 | 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 | 55 | int ret; |
| 70 | 56 | |
| 71 | 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 | 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 | 100 | static const struct drm_gem_object_funcs vmw_gem_object_funcs = { |
| 108 | 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 | 108 | .vmap = drm_gem_ttm_vmap, |
| 116 | 109 | .vunmap = drm_gem_ttm_vunmap, |
| 117 | 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 | 114 | int vmw_gem_object_create_with_handle(struct vmw_private *dev_priv, |
| 137 | 115 | struct drm_file *filp, |
| 138 | 116 | uint32_t size, |
| 139 | 117 | uint32_t *handle, |
| 140 | − struct vmw_buffer_object **p_vbo) | |
| 118 | + struct vmw_bo **p_vbo) | |
| 141 | 119 | { |
| 142 | 120 | int ret; |
| 143 | − | |
| 144 | − ret = vmw_bo_create(dev_priv, size, | |
| 145 | − (dev_priv->has_mob) ? | |
| 146 | − &vmw_sys_placement : | |
| 147 | − &vmw_vram_sys_placement, | |
| 148 | − true, false, &vmw_gem_destroy, p_vbo); | |
| 121 | + struct vmw_bo_params params = { | |
| 122 | + .domain = (dev_priv->has_mob) ? VMW_BO_DOMAIN_SYS : VMW_BO_DOMAIN_VRAM, | |
| 123 | + .busy_domain = VMW_BO_DOMAIN_SYS, | |
| 124 | + .bo_type = ttm_bo_type_device, | |
| 125 | + .size = size, | |
| 126 | + .pin = false | |
| 127 | + }; | |
| 128 | + | |
| 129 | + ret = vmw_bo_create(dev_priv, ¶ms, p_vbo); | |
| 149 | 130 | if (ret != 0) |
| 150 | 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 | 136 | out_no_bo: |
| 156 | 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 | 146 | (union drm_vmw_alloc_dmabuf_arg *)data; |
| 166 | 147 | struct drm_vmw_alloc_dmabuf_req *req = &arg->req; |
| 167 | 148 | struct drm_vmw_dmabuf_rep *rep = &arg->rep; |
| 168 | − struct vmw_buffer_object *vbo; | |
| 149 | + struct vmw_bo *vbo; | |
| 169 | 150 | uint32_t handle; |
| 170 | 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 | 156 | goto out_no_bo; |
| 176 | 157 | |
| 177 | 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 | 160 | rep->cur_gmr_id = handle; |
| 180 | 161 | rep->cur_gmr_offset = 0; |
| 181 | 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 | 164 | out_no_bo: |
| 184 | 165 | return ret; |
| 185 | 166 | } |
| 186 | 167 | |
| 187 | 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 | 172 | const char *placement; |
| 192 | 173 | const char *type; |
| 193 | 174 | |
| 194 | − switch (bo->base.resource->mem_type) { | |
| 175 | + switch (bo->tbo.resource->mem_type) { | |
| 195 | 176 | case TTM_PL_SYSTEM: |
| 196 | 177 | placement = " CPU"; |
| 197 | 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 | 193 | break; |
| 213 | 194 | } |
| 214 | 195 | |
| 215 | − switch (bo->base.type) { | |
| 196 | + switch (bo->tbo.type) { | |
| 216 | 197 | case ttm_bo_type_device: |
| 217 | 198 | type = "device"; |
| 218 | 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 | 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 | 213 | seq_printf(m, ", priority = %u, pin_count = %u, GEM refs = %d, TTM refs = %d", |
| 233 | − bo->base.priority, | |
| 234 | − bo->base.pin_count, | |
| 235 | − kref_read(&bo->base.base.refcount), | |
| 236 | − kref_read(&bo->base.kref)); | |
| 214 | + bo->tbo.priority, | |
| 215 | + bo->tbo.pin_count, | |
| 216 | + kref_read(&bo->tbo.base.refcount), | |
| 217 | + kref_read(&bo->tbo.kref)); | |
| 237 | 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 | 249 | spin_lock(&file->table_lock); |
| 269 | 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 | 253 | vmw_bo_print_info(id, bo, m); |
| 273 | 254 | } |
| @@ -1,7 +1,7 @@ | ||
| 1 | 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 | 6 | * Permission is hereby granted, free of charge, to any person obtaining a |
| 7 | 7 | * copy of this software and associated documentation files (the |
| @@ -24,8 +24,9 @@ · 16 unmodified lines | ||
| 24 | 24 | * USE OR OTHER DEALINGS IN THE SOFTWARE. |
| 25 | 25 | * |
| 26 | 26 | **************************************************************************/ |
| 27 | − | |
| 28 | 27 | #include "vmwgfx_kms.h" |
| 28 | + | |
| 29 | +#include "vmwgfx_bo.h" | |
| 29 | 30 | #include "vmw_surface_cache.h" |
| 30 | 31 | |
| 31 | 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 | 153 | SVGAGBCursorHeader *header; |
| 153 | 154 | SVGAGBAlphaCursorHeader *alpha_header; |
| 154 | 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 | 158 | alpha_header = &header->header.alphaHeader; |
| 159 | 159 | |
| 160 | 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 | 170 | memcpy(header + 1, image, image_size); |
| 171 | 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 | 185 | static u32 *vmw_du_cursor_plane_acquire_image(struct vmw_plane_state *vps) |
| 186 | 186 | { |
| 187 | − bool dummy; | |
| 187 | + bool is_iomem; | |
| 188 | 188 | if (vps->surf) { |
| 189 | 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 | 191 | return vps->surf->snooper.image; |
| 192 | 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 | 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 | 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 | 228 | return; |
| 229 | 229 | |
| 230 | − ttm_bo_unpin(*bo); | |
| 231 | − ttm_bo_put(*bo); | |
| 232 | − kfree(*bo); | |
| 233 | − *bo = NULL; | |
| 230 | + ttm_bo_unpin(&(*vbo)->tbo); | |
| 231 | + vmw_bo_unreference(vbo); | |
| 234 | 232 | } |
| 235 | 233 | |
| 236 | 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 | 253 | /* Cache is full: See if this mob is bigger than an existing mob. */ |
| 256 | 254 | for (i = 0; i < ARRAY_SIZE(vcp->cursor_mobs); i++) { |
| 257 | − if (vcp->cursor_mobs[i]->base.size < | |
| 258 | − vps->cursor.bo->base.size) { | |
| 255 | + if (vcp->cursor_mobs[i]->tbo.base.size < | |
| 256 | + vps->cursor.bo->tbo.base.size) { | |
| 259 | 257 | vmw_du_destroy_cursor_mob(&vcp->cursor_mobs[i]); |
| 260 | 258 | vcp->cursor_mobs[i] = vps->cursor.bo; |
| 261 | 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 | 286 | return -EINVAL; |
| 289 | 287 | |
| 290 | 288 | if (vps->cursor.bo) { |
| 291 | − if (vps->cursor.bo->base.size >= size) | |
| 289 | + if (vps->cursor.bo->tbo.base.size >= size) | |
| 292 | 290 | return 0; |
| 293 | 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 | 294 | /* Look for an unused mob in the cache. */ |
| 297 | 295 | for (i = 0; i < ARRAY_SIZE(vcp->cursor_mobs); i++) { |
| 298 | 296 | if (vcp->cursor_mobs[i] && |
| 299 | − vcp->cursor_mobs[i]->base.size >= size) { | |
| 297 | + vcp->cursor_mobs[i]->tbo.base.size >= size) { | |
| 300 | 298 | vps->cursor.bo = vcp->cursor_mobs[i]; |
| 301 | 299 | vcp->cursor_mobs[i] = NULL; |
| 302 | 300 | return 0; |
| 303 | 301 | } |
| 304 | 302 | } |
| 305 | 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, | |
| 307 | − &vps->cursor.bo); | |
| 304 | + ret = vmw_bo_create_and_populate(dev_priv, size, | |
| 305 | + VMW_BO_DOMAIN_MOB, | |
| 306 | + &vps->cursor.bo); | |
| 308 | 307 | |
| 309 | 308 | if (ret != 0) |
| 310 | 309 | return ret; |
| 311 | 310 | |
| 312 | 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 | 313 | if (ret != 0) |
| 315 | 314 | goto teardown; |
| 316 | 315 | |
| 317 | − vmw_bo_fence_single(vps->cursor.bo, NULL); | |
| 318 | − ttm_bo_unreserve(vps->cursor.bo); | |
| 316 | + vmw_bo_fence_single(&vps->cursor.bo->tbo, NULL); | |
| 317 | + ttm_bo_unreserve(&vps->cursor.bo->tbo); | |
| 319 | 318 | return 0; |
| 320 | 319 | |
| 321 | 320 | teardown: |
| @@ -363,7 +362,7 @@ void vmw_kms_cursor_snoop(struct vmw_surface *srf, · 41 unmodified lines | ||
| 363 | 362 | SVGA3dCopyBox *box; |
| 364 | 363 | unsigned box_count; |
| 365 | 364 | void *virtual; |
| 366 | − bool dummy; | |
| 365 | + bool is_iomem; | |
| 367 | 366 | struct vmw_dma_cmd { |
| 368 | 367 | SVGA3dCmdHeader header; |
| 369 | 368 | SVGA3dCmdSurfaceDMA dma; |
| @@ -423,7 +422,7 @@ void vmw_kms_cursor_snoop(struct vmw_surface *srf, · 53 unmodified lines | ||
| 423 | 422 | if (unlikely(ret != 0)) |
| 424 | 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 | 427 | if (box->w == VMW_CURSOR_SNOOP_WIDTH && cmd->dma.guest.pitch == image_pitch) { |
| 429 | 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 | 573 | int ret; |
| 575 | 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 | 578 | return -EINVAL; |
| 580 | 579 | |
| 580 | + bo = &vps->cursor.bo->tbo; | |
| 581 | + | |
| 581 | 582 | if (bo->base.size < size) |
| 582 | 583 | return -EINVAL; |
| 583 | 584 | |
| 584 | − if (vps->cursor.mapped) | |
| 585 | + if (vps->cursor.bo->map.virtual) | |
| 585 | 586 | return 0; |
| 586 | 587 | |
| 587 | 588 | ret = ttm_bo_reserve(bo, false, false, NULL); |
| 588 | − | |
| 589 | 589 | if (unlikely(ret != 0)) |
| 590 | 590 | return -ENOMEM; |
| 591 | 591 | |
| 592 | − ret = ttm_bo_kmap(bo, 0, PFN_UP(size), &vps->cursor.map); | |
| 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); | |
| 592 | + vmw_bo_map_and_cache(vps->cursor.bo); | |
| 601 | 593 | |
| 602 | 594 | ttm_bo_unreserve(bo); |
| 603 | 595 | |
| 604 | 596 | if (unlikely(ret != 0)) |
| 605 | 597 | return -ENOMEM; |
| 606 | 598 | |
| 607 | − vps->cursor.mapped = true; | |
| 608 | − | |
| 609 | 599 | return 0; |
| 610 | 600 | } |
| 611 | 601 | |
| @@ -622,19 +612,15 @@ static int · 10 unmodified lines | ||
| 622 | 612 | vmw_du_cursor_plane_unmap_cm(struct vmw_plane_state *vps) |
| 623 | 613 | { |
| 624 | 614 | int ret = 0; |
| 625 | − struct ttm_buffer_object *bo = vps->cursor.bo; | |
| 626 | − | |
| 627 | − if (!vps->cursor.mapped) | |
| 628 | − return 0; | |
| 615 | + struct vmw_bo *vbo = vps->cursor.bo; | |
| 629 | 616 | |
| 630 | − if (!bo) | |
| 617 | + if (!vbo || !vbo->map.virtual) | |
| 631 | 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 | 621 | if (likely(ret == 0)) { |
| 635 | − ttm_bo_kunmap(&vps->cursor.map); | |
| 636 | − ttm_bo_unreserve(bo); | |
| 637 | − vps->cursor.mapped = false; | |
| 622 | + vmw_bo_unmap(vbo); | |
| 623 | + ttm_bo_unreserve(&vbo->tbo); | |
| 638 | 624 | } |
| 639 | 625 | |
| 640 | 626 | return ret; |
| @@ -657,20 +643,19 @@ vmw_du_cursor_plane_cleanup_fb(struct drm_plane *plane, · 16 unmodified lines | ||
| 657 | 643 | { |
| 658 | 644 | struct vmw_cursor_plane *vcp = vmw_plane_to_vcp(plane); |
| 659 | 645 | struct vmw_plane_state *vps = vmw_plane_state_to_vps(old_state); |
| 660 | − bool dummy; | |
| 646 | + bool is_iomem; | |
| 661 | 647 | |
| 662 | 648 | if (vps->surf_mapped) { |
| 663 | − vmw_bo_unmap(vps->surf->res.backup); | |
| 649 | + vmw_bo_unmap(vps->surf->res.guest_memory_bo); | |
| 664 | 650 | vps->surf_mapped = false; |
| 665 | 651 | } |
| 666 | 652 | |
| 667 | − if (vps->bo && ttm_kmap_obj_virtual(&vps->bo->map, &dummy)) { | |
| 668 | − const int ret = ttm_bo_reserve(&vps->bo->base, true, false, NULL); | |
| 653 | + if (vps->bo && ttm_kmap_obj_virtual(&vps->bo->map, &is_iomem)) { | |
| 654 | + const int ret = ttm_bo_reserve(&vps->bo->tbo, true, false, NULL); | |
| 669 | 655 | |
| 670 | 656 | if (likely(ret == 0)) { |
| 671 | − if (atomic_read(&vps->bo->base_mapped_count) == 0) | |
| 672 | − ttm_bo_kunmap(&vps->bo->map); | |
| 673 | − ttm_bo_unreserve(&vps->bo->base); | |
| 657 | + ttm_bo_kunmap(&vps->bo->map); | |
| 658 | + ttm_bo_unreserve(&vps->bo->tbo); | |
| 674 | 659 | } |
| 675 | 660 | } |
| 676 | 661 | |
| @@ -736,29 +721,26 @@ vmw_du_cursor_plane_prepare_fb(struct drm_plane *plane, · 59 unmodified lines | ||
| 736 | 721 | * reserve the ttm_buffer_object first which |
| 737 | 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 | 726 | if (unlikely(ret != 0)) |
| 742 | 727 | return -ENOMEM; |
| 743 | 728 | |
| 744 | − ret = ttm_bo_kmap(&vps->bo->base, 0, PFN_UP(size), &vps->bo->map); | |
| 745 | − | |
| 746 | − if (likely(ret == 0)) | |
| 747 | − atomic_inc(&vps->bo->base_mapped_count); | |
| 729 | + ret = ttm_bo_kmap(&vps->bo->tbo, 0, PFN_UP(size), &vps->bo->map); | |
| 748 | 730 | |
| 749 | − ttm_bo_unreserve(&vps->bo->base); | |
| 731 | + ttm_bo_unreserve(&vps->bo->tbo); | |
| 750 | 732 | |
| 751 | 733 | if (unlikely(ret != 0)) |
| 752 | 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 | 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 | 739 | NULL); |
| 758 | 740 | if (unlikely(ret != 0)) |
| 759 | 741 | return -ENOMEM; |
| 760 | − vmw_bo_map_and_cache(vps->surf->res.backup); | |
| 761 | − ttm_bo_unreserve(&vps->surf->res.backup->base); | |
| 742 | + vmw_bo_map_and_cache(vps->surf->res.guest_memory_bo); | |
| 743 | + ttm_bo_unreserve(&vps->surf->res.guest_memory_bo->tbo); | |
| 762 | 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 | 767 | struct vmw_plane_state *vps = vmw_plane_state_to_vps(new_state); |
| 786 | 768 | struct vmw_plane_state *old_vps = vmw_plane_state_to_vps(old_state); |
| 787 | 769 | s32 hotspot_x, hotspot_y; |
| 788 | − bool dummy; | |
| 789 | 770 | |
| 790 | 771 | hotspot_x = du->hotspot_x; |
| 791 | 772 | hotspot_y = du->hotspot_y; |
| @@ -827,11 +808,6 @@ vmw_du_cursor_plane_atomic_update(struct drm_plane *plane, · 35 unmodified lines | ||
| 827 | 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 | 811 | du->cursor_x = new_state->crtc_x + du->set_gui_x; |
| 836 | 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 | 911 | WARN_ON(!surface); |
| 936 | 912 | |
| 937 | 913 | if (!surface || |
| 938 | − (!surface->snooper.image && !surface->res.backup)) { | |
| 914 | + (!surface->snooper.image && !surface->res.guest_memory_bo)) { | |
| 939 | 915 | DRM_ERROR("surface not suitable for cursor\n"); |
| 940 | 916 | return -EINVAL; |
| 941 | 917 | } |
| @@ -1279,9 +1255,9 @@ int vmw_kms_readback(struct vmw_private *dev_priv, · 337 unmodified lines | ||
| 1279 | 1255 | user_fence_rep, vclips, num_clips, |
| 1280 | 1256 | NULL); |
| 1281 | 1257 | case vmw_du_screen_target: |
| 1282 | − return vmw_kms_stdu_dma(dev_priv, file_priv, vfb, | |
| 1283 | − user_fence_rep, NULL, vclips, num_clips, | |
| 1284 | − 1, false, true, NULL); | |
| 1258 | + return vmw_kms_stdu_readback(dev_priv, file_priv, vfb, | |
| 1259 | + user_fence_rep, NULL, vclips, num_clips, | |
| 1260 | + 1, NULL); | |
| 1285 | 1261 | default: |
| 1286 | 1262 | WARN_ONCE(true, |
| 1287 | 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 | 1382 | struct vmw_framebuffer_bo *vfbd = |
| 1407 | 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 | 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 | 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 | 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 | 1480 | static int vmw_create_bo_proxy(struct drm_device *dev, |
| 1568 | 1481 | const struct drm_mode_fb_cmd2 *mode_cmd, |
| 1569 | − struct vmw_buffer_object *bo_mob, | |
| 1482 | + struct vmw_bo *bo_mob, | |
| 1570 | 1483 | struct vmw_surface **srf_out) |
| 1571 | 1484 | { |
| 1572 | 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 | 1531 | /* Reserve and switch the backing mob. */ |
| 1619 | 1532 | mutex_lock(&res->dev_priv->cmdbuf_mutex); |
| 1620 | 1533 | (void) vmw_resource_reserve(res, false, true); |
| 1621 | − vmw_bo_unreference(&res->backup); | |
| 1622 | − res->backup = vmw_bo_reference(bo_mob); | |
| 1623 | − res->backup_offset = 0; | |
| 1534 | + vmw_bo_unreference(&res->guest_memory_bo); | |
| 1535 | + res->guest_memory_bo = vmw_bo_reference(bo_mob); | |
| 1536 | + res->guest_memory_offset = 0; | |
| 1624 | 1537 | vmw_resource_unreserve(res, false, false, false, NULL, 0); |
| 1625 | 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 | 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 | 1547 | struct vmw_framebuffer **out, |
| 1635 | 1548 | const struct drm_mode_fb_cmd2 |
| 1636 | 1549 | *mode_cmd) |
| @@ -1642,7 +1555,7 @@ static int vmw_kms_new_framebuffer_bo(struct vmw_private *dev_priv, · 5 unmodified lines | ||
| 1642 | 1555 | int ret; |
| 1643 | 1556 | |
| 1644 | 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 | 1559 | DRM_ERROR("Screen buffer object size is too small " |
| 1647 | 1560 | "for requested mode.\n"); |
| 1648 | 1561 | return -EINVAL; |
| @@ -1663,7 +1576,7 @@ static int vmw_kms_new_framebuffer_bo(struct vmw_private *dev_priv, · 14 unmodified lines | ||
| 1663 | 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 | 1580 | drm_helper_mode_fill_fb_struct(dev, &vfbd->base.base, mode_cmd); |
| 1668 | 1581 | vfbd->base.bo = true; |
| 1669 | 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 | 1632 | struct vmw_framebuffer * |
| 1720 | 1633 | vmw_kms_new_framebuffer(struct vmw_private *dev_priv, |
| 1721 | − struct vmw_buffer_object *bo, | |
| 1634 | + struct vmw_bo *bo, | |
| 1722 | 1635 | struct vmw_surface *surface, |
| 1723 | 1636 | bool only_2d, |
| 1724 | 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 | 1678 | if (ret) |
| 1766 | 1679 | return ERR_PTR(ret); |
| 1767 | 1680 | |
| 1768 | − vfb->pin = vmw_framebuffer_pin; | |
| 1769 | − vfb->unpin = vmw_framebuffer_unpin; | |
| 1770 | − | |
| 1771 | 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 | 1692 | struct vmw_private *dev_priv = vmw_priv(dev); |
| 1783 | 1693 | struct vmw_framebuffer *vfb = NULL; |
| 1784 | 1694 | struct vmw_surface *surface = NULL; |
| 1785 | − struct vmw_buffer_object *bo = NULL; | |
| 1695 | + struct vmw_bo *bo = NULL; | |
| 1786 | 1696 | int ret; |
| 1787 | 1697 | |
| 1788 | 1698 | /* returns either a bo or surface */ |
| @@ -1817,7 +1727,7 @@ err_out: · 28 unmodified lines | ||
| 1817 | 1727 | /* vmw_user_lookup_handle takes one ref so does new_fb */ |
| 1818 | 1728 | if (bo) { |
| 1819 | 1729 | vmw_bo_unreference(&bo); |
| 1820 | − drm_gem_object_put(&bo->base.base); | |
| 1730 | + drm_gem_object_put(&bo->tbo.base); | |
| 1821 | 1731 | } |
| 1822 | 1732 | if (surface) |
| 1823 | 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 | 2986 | struct vmw_framebuffer_bo *vfbbo = |
| 3077 | 2987 | container_of(update->vfb, typeof(*vfbbo), base); |
| 3078 | 2988 | |
| 3079 | − ret = vmw_validation_add_bo(&val_ctx, vfbbo->buffer, false, | |
| 3080 | − update->cpu_blit); | |
| 2989 | + /* | |
| 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 | 3003 | } else { |
| 3082 | 3004 | struct vmw_framebuffer_surface *vfbs = |
| 3083 | 3005 | container_of(update->vfb, typeof(*vfbs), base); |
| @@ -1,7 +1,7 @@ | ||
| 1 | 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 | 6 | * Permission is hereby granted, free of charge, to any person obtaining a |
| 7 | 7 | * copy of this software and associated documentation files (the |
| @@ -126,7 +126,6 @@ struct vmw_du_update_plane { · 118 unmodified lines | ||
| 126 | 126 | struct vmw_framebuffer *vfb; |
| 127 | 127 | struct vmw_fence_obj **out_fence; |
| 128 | 128 | struct mutex *mutex; |
| 129 | − bool cpu_blit; | |
| 130 | 129 | bool intr; |
| 131 | 130 | }; |
| 132 | 131 | |
| @@ -217,8 +216,6 @@ struct vmw_kms_dirty { · 84 unmodified lines | ||
| 217 | 216 | */ |
| 218 | 217 | struct vmw_framebuffer { |
| 219 | 218 | struct drm_framebuffer base; |
| 220 | − int (*pin)(struct vmw_framebuffer *fb); | |
| 221 | − int (*unpin)(struct vmw_framebuffer *fb); | |
| 222 | 219 | bool bo; |
| 223 | 220 | uint32_t user_handle; |
| 224 | 221 | }; |
| @@ -233,7 +230,7 @@ struct vmw_clip_rect { · 8 unmodified lines | ||
| 233 | 230 | struct vmw_framebuffer_surface { |
| 234 | 231 | struct vmw_framebuffer base; |
| 235 | 232 | struct vmw_surface *surface; |
| 236 | − struct vmw_buffer_object *buffer; | |
| 233 | + struct vmw_bo *buffer; | |
| 237 | 234 | struct list_head head; |
| 238 | 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 | 239 | struct vmw_framebuffer_bo { |
| 243 | 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 | 272 | struct vmw_cursor_plane_state { |
| 276 | − struct ttm_buffer_object *bo; | |
| 277 | − struct ttm_bo_kmap_obj map; | |
| 278 | − bool mapped; | |
| 273 | + struct vmw_bo *bo; | |
| 279 | 274 | s32 hotspot_x; |
| 280 | 275 | s32 hotspot_y; |
| 281 | 276 | }; |
| @@ -293,7 +288,7 @@ struct vmw_cursor_plane_state { · 11 unmodified lines | ||
| 293 | 288 | struct vmw_plane_state { |
| 294 | 289 | struct drm_plane_state base; |
| 295 | 290 | struct vmw_surface *surf; |
| 296 | − struct vmw_buffer_object *bo; | |
| 291 | + struct vmw_bo *bo; | |
| 297 | 292 | |
| 298 | 293 | int content_fb_type; |
| 299 | 294 | unsigned long bo_size; |
| @@ -346,7 +341,7 @@ struct vmw_connector_state { · 46 unmodified lines | ||
| 346 | 341 | struct vmw_cursor_plane { |
| 347 | 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 | 359 | struct vmw_cursor_plane cursor; |
| 365 | 360 | |
| 366 | 361 | struct vmw_surface *cursor_surface; |
| 367 | − struct vmw_buffer_object *cursor_bo; | |
| 362 | + struct vmw_bo *cursor_bo; | |
| 368 | 363 | size_t cursor_age; |
| 369 | 364 | |
| 370 | 365 | int cursor_x; |
| @@ -397,7 +392,7 @@ struct vmw_display_unit { · 26 unmodified lines | ||
| 397 | 392 | |
| 398 | 393 | struct vmw_validation_ctx { |
| 399 | 394 | struct vmw_resource *res; |
| 400 | − struct vmw_buffer_object *buf; | |
| 395 | + struct vmw_bo *buf; | |
| 401 | 396 | }; |
| 402 | 397 | |
| 403 | 398 | #define vmw_crtc_to_du(x) \ |
| @@ -458,7 +453,7 @@ int vmw_kms_readback(struct vmw_private *dev_priv, · 54 unmodified lines | ||
| 458 | 453 | uint32_t num_clips); |
| 459 | 454 | struct vmw_framebuffer * |
| 460 | 455 | vmw_kms_new_framebuffer(struct vmw_private *dev_priv, |
| 461 | − struct vmw_buffer_object *bo, | |
| 456 | + struct vmw_bo *bo, | |
| 462 | 457 | struct vmw_surface *surface, |
| 463 | 458 | bool only_2d, |
| 464 | 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 | 561 | unsigned num_clips, int inc, |
| 567 | 562 | struct vmw_fence_obj **out_fence, |
| 568 | 563 | struct drm_crtc *crtc); |
| 569 | −int vmw_kms_stdu_dma(struct vmw_private *dev_priv, | |
| 570 | − struct drm_file *file_priv, | |
| 571 | − struct vmw_framebuffer *vfb, | |
| 572 | − struct drm_vmw_fence_rep __user *user_fence_rep, | |
| 573 | − struct drm_clip_rect *clips, | |
| 574 | − struct drm_vmw_rect *vclips, | |
| 575 | − uint32_t num_clips, | |
| 576 | − int increment, | |
| 577 | − bool to_surface, | |
| 578 | − bool interruptible, | |
| 579 | − struct drm_crtc *crtc); | |
| 564 | +int vmw_kms_stdu_readback(struct vmw_private *dev_priv, | |
| 565 | + struct drm_file *file_priv, | |
| 566 | + struct vmw_framebuffer *vfb, | |
| 567 | + struct drm_vmw_fence_rep __user *user_fence_rep, | |
| 568 | + struct drm_clip_rect *clips, | |
| 569 | + struct drm_vmw_rect *vclips, | |
| 570 | + uint32_t num_clips, | |
| 571 | + int increment, | |
| 572 | + struct drm_crtc *crtc); | |
| 580 | 573 | |
| 581 | 574 | int vmw_du_helper_plane_update(struct vmw_du_update_plane *update); |
| 582 | 575 | |
| @@ -1,7 +1,7 @@ | ||
| 1 | 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 | 6 | * Permission is hereby granted, free of charge, to any person obtaining a |
| 7 | 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 | 31 | #include <drm/drm_atomic.h> |
| 29 | 32 | #include <drm/drm_atomic_helper.h> |
| 30 | 33 | #include <drm/drm_fourcc.h> |
| 31 | 34 | |
| 32 | −#include "vmwgfx_kms.h" | |
| 33 | 35 | |
| 34 | 36 | #define vmw_crtc_to_ldu(x) \ |
| 35 | 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 | 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 | 180 | static int vmw_ldu_del_active(struct vmw_private *vmw_priv, |
| 138 | 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 | 188 | list_del_init(&ldu->active); |
| 146 | 189 | if (--(ld->num_active) == 0) { |
| 147 | 190 | BUG_ON(!ld->fb); |
| 148 | − if (ld->fb->unpin) | |
| 149 | − ld->fb->unpin(ld->fb); | |
| 191 | + WARN_ON(vmw_ldu_fb_unpin(ld->fb)); | |
| 150 | 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 | 206 | BUG_ON(!ld->num_active && ld->fb); |
| 165 | 207 | if (vfb != ld->fb) { |
| 166 | − if (ld->fb && ld->fb->unpin) | |
| 167 | − ld->fb->unpin(ld->fb); | |
| 208 | + if (ld->fb) | |
| 209 | + WARN_ON(vmw_ldu_fb_unpin(ld->fb)); | |
| 168 | 210 | vmw_svga_enable(vmw_priv); |
| 169 | − if (vfb->pin) | |
| 170 | − vfb->pin(vfb); | |
| 211 | + WARN_ON(vmw_ldu_fb_pin(vfb)); | |
| 171 | 212 | ld->fb = vfb; |
| 172 | 213 | } |
| 173 | 214 | |
| @@ -1,7 +1,7 @@ | ||
| 1 | 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 | 6 | * Permission is hereby granted, free of charge, to any person obtaining a |
| 7 | 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> | |
| 29 | − | |
| 28 | +#include "vmwgfx_bo.h" | |
| 30 | 29 | #include "vmwgfx_drv.h" |
| 31 | 30 | |
| 31 | +#include <linux/highmem.h> | |
| 32 | + | |
| 32 | 33 | #ifdef CONFIG_64BIT |
| 33 | 34 | #define VMW_PPN_SIZE 8 |
| 34 | 35 | #define VMW_MOBFMT_PTDEPTH_0 SVGA3D_MOBFMT_PT64_0 |
| @@ -50,7 +51,7 @@ · 15 unmodified lines | ||
| 50 | 51 | * @pt_root_page DMA address of the level 0 page of the page table. |
| 51 | 52 | */ |
| 52 | 53 | struct vmw_mob { |
| 53 | − struct ttm_buffer_object *pt_bo; | |
| 54 | + struct vmw_bo *pt_bo; | |
| 54 | 55 | unsigned long num_pages; |
| 55 | 56 | unsigned pt_level; |
| 56 | 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 | 204 | if (otable->page_table == NULL) |
| 204 | 205 | return; |
| 205 | 206 | |
| 206 | − bo = otable->page_table->pt_bo; | |
| 207 | + bo = &otable->page_table->pt_bo->tbo; | |
| 207 | 208 | cmd = VMW_CMD_RESERVE(dev_priv, sizeof(*cmd)); |
| 208 | 209 | if (unlikely(cmd == NULL)) |
| 209 | 210 | return; |
| @@ -251,7 +252,9 @@ static int vmw_otable_batch_setup(struct vmw_private *dev_priv, · 41 unmodified lines | ||
| 251 | 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 | 258 | if (unlikely(ret != 0)) |
| 256 | 259 | return ret; |
| 257 | 260 | |
| @@ -260,7 +263,8 @@ static int vmw_otable_batch_setup(struct vmw_private *dev_priv, · 2 unmodified lines | ||
| 260 | 263 | if (!batch->otables[i].enabled) |
| 261 | 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 | 268 | offset, |
| 265 | 269 | &otables[i]); |
| 266 | 270 | if (unlikely(ret != 0)) |
| @@ -277,8 +281,8 @@ out_no_setup: · 10 unmodified lines | ||
| 277 | 281 | &batch->otables[i]); |
| 278 | 282 | } |
| 279 | 283 | |
| 280 | − vmw_bo_unpin_unlocked(batch->otable_bo); | |
| 281 | − ttm_bo_put(batch->otable_bo); | |
| 284 | + vmw_bo_unpin_unlocked(&batch->otable_bo->tbo); | |
| 285 | + ttm_bo_put(&batch->otable_bo->tbo); | |
| 282 | 286 | batch->otable_bo = NULL; |
| 283 | 287 | return ret; |
| 284 | 288 | } |
| @@ -329,7 +333,7 @@ static void vmw_otable_batch_takedown(struct vmw_private *dev_priv, · 44 unmodified lines | ||
| 329 | 333 | struct vmw_otable_batch *batch) |
| 330 | 334 | { |
| 331 | 335 | SVGAOTableType i; |
| 332 | − struct ttm_buffer_object *bo = batch->otable_bo; | |
| 336 | + struct ttm_buffer_object *bo = &batch->otable_bo->tbo; | |
| 333 | 337 | int ret; |
| 334 | 338 | |
| 335 | 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 | 348 | ttm_bo_unpin(bo); |
| 345 | 349 | ttm_bo_unreserve(bo); |
| 346 | 350 | |
| 347 | − ttm_bo_put(batch->otable_bo); | |
| 348 | − batch->otable_bo = NULL; | |
| 351 | + vmw_bo_unreference(&batch->otable_bo); | |
| 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 | 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 | 499 | unsigned long num_data_pages) |
| 495 | 500 | { |
| 496 | 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 | 503 | struct vmw_piter save_pt_iter = {0}; |
| 499 | 504 | struct vmw_piter pt_iter; |
| 500 | 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 | 536 | void vmw_mob_destroy(struct vmw_mob *mob) |
| 532 | 537 | { |
| 533 | 538 | if (mob->pt_bo) { |
| 534 | − vmw_bo_unpin_unlocked(mob->pt_bo); | |
| 535 | − ttm_bo_put(mob->pt_bo); | |
| 536 | − mob->pt_bo = NULL; | |
| 539 | + vmw_bo_unpin_unlocked(&mob->pt_bo->tbo); | |
| 540 | + vmw_bo_unreference(&mob->pt_bo); | |
| 537 | 541 | } |
| 538 | 542 | kfree(mob); |
| 539 | 543 | } |
| @@ -552,7 +556,7 @@ void vmw_mob_unbind(struct vmw_private *dev_priv, · 12 unmodified lines | ||
| 552 | 556 | SVGA3dCmdDestroyGBMob body; |
| 553 | 557 | } *cmd; |
| 554 | 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 | 561 | if (bo) { |
| 558 | 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 | 648 | out_no_cmd_space: |
| 645 | 649 | vmw_fifo_resource_dec(dev_priv); |
| 646 | 650 | if (pt_set_up) { |
| 647 | − vmw_bo_unpin_unlocked(mob->pt_bo); | |
| 648 | − ttm_bo_put(mob->pt_bo); | |
| 649 | − mob->pt_bo = NULL; | |
| 651 | + vmw_bo_unpin_unlocked(&mob->pt_bo->tbo); | |
| 652 | + vmw_bo_unreference(&mob->pt_bo); | |
| 650 | 653 | } |
| 651 | 654 | |
| 652 | 655 | return -ENOMEM; |
| @@ -1,7 +1,7 @@ | ||
| 1 | 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 | 6 | * Permission is hereby granted, free of charge, to any person obtaining a |
| 7 | 7 | * copy of this software and associated documentation files (the |
| @@ -24,19 +24,19 @@ · 16 unmodified lines | ||
| 24 | 24 | * USE OR OTHER DEALINGS IN THE SOFTWARE. |
| 25 | 25 | * |
| 26 | 26 | **************************************************************************/ |
| 27 | − | |
| 28 | −#include <drm/ttm/ttm_placement.h> | |
| 27 | +#include "vmwgfx_bo.h" | |
| 28 | +#include "vmwgfx_drv.h" | |
| 29 | 29 | |
| 30 | 30 | #include "device_include/svga_overlay.h" |
| 31 | 31 | #include "device_include/svga_escape.h" |
| 32 | 32 | |
| 33 | −#include "vmwgfx_drv.h" | |
| 33 | +#include <drm/ttm/ttm_placement.h> | |
| 34 | 34 | |
| 35 | 35 | #define VMW_MAX_NUM_STREAMS 1 |
| 36 | 36 | #define VMW_OVERLAY_CAP_MASK (SVGA_FIFO_CAP_VIDEO | SVGA_FIFO_CAP_ESCAPE) |
| 37 | 37 | |
| 38 | 38 | struct vmw_stream { |
| 39 | − struct vmw_buffer_object *buf; | |
| 39 | + struct vmw_bo *buf; | |
| 40 | 40 | bool claimed; |
| 41 | 41 | bool paused; |
| 42 | 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 | 92 | * -ERESTARTSYS if interrupted by a signal. |
| 93 | 93 | */ |
| 94 | 94 | static int vmw_overlay_send_put(struct vmw_private *dev_priv, |
| 95 | − struct vmw_buffer_object *buf, | |
| 95 | + struct vmw_bo *buf, | |
| 96 | 96 | struct drm_vmw_control_stream_arg *arg, |
| 97 | 97 | bool interruptible) |
| 98 | 98 | { |
| @@ -140,7 +140,7 @@ static int vmw_overlay_send_put(struct vmw_private *dev_priv, · 41 unmodified lines | ||
| 140 | 140 | for (i = 0; i < num_items; i++) |
| 141 | 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 | 144 | ptr.offset += arg->offset; |
| 145 | 145 | |
| 146 | 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 | 223 | * used with GMRs instead of being locked to vram. |
| 224 | 224 | */ |
| 225 | 225 | static int vmw_overlay_move_buffer(struct vmw_private *dev_priv, |
| 226 | − struct vmw_buffer_object *buf, | |
| 226 | + struct vmw_bo *buf, | |
| 227 | 227 | bool pin, bool inter) |
| 228 | 228 | { |
| 229 | 229 | if (!pin) |
| @@ -295,7 +295,7 @@ static int vmw_overlay_stop(struct vmw_private *dev_priv, · 65 unmodified lines | ||
| 295 | 295 | * -ERESTARTSYS if interrupted. |
| 296 | 296 | */ |
| 297 | 297 | static int vmw_overlay_update_stream(struct vmw_private *dev_priv, |
| 298 | − struct vmw_buffer_object *buf, | |
| 298 | + struct vmw_bo *buf, | |
| 299 | 299 | struct drm_vmw_control_stream_arg *arg, |
| 300 | 300 | bool interruptible) |
| 301 | 301 | { |
| @@ -433,7 +433,7 @@ int vmw_overlay_ioctl(struct drm_device *dev, void *data, · 131 unmodified lines | ||
| 433 | 433 | struct vmw_overlay *overlay = dev_priv->overlay_priv; |
| 434 | 434 | struct drm_vmw_control_stream_arg *arg = |
| 435 | 435 | (struct drm_vmw_control_stream_arg *)data; |
| 436 | − struct vmw_buffer_object *buf; | |
| 436 | + struct vmw_bo *buf; | |
| 437 | 437 | struct vmw_resource *res; |
| 438 | 438 | int ret; |
| 439 | 439 | |
| @@ -458,7 +458,7 @@ int vmw_overlay_ioctl(struct drm_device *dev, void *data, · 18 unmodified lines | ||
| 458 | 458 | ret = vmw_overlay_update_stream(dev_priv, buf, arg, true); |
| 459 | 459 | |
| 460 | 460 | vmw_bo_unreference(&buf); |
| 461 | − drm_gem_object_put(&buf->base.base); | |
| 461 | + drm_gem_object_put(&buf->tbo.base); | |
| 462 | 462 | |
| 463 | 463 | out_unlock: |
| 464 | 464 | mutex_unlock(&overlay->mutex); |
| @@ -1,7 +1,7 @@ | ||
| 1 | 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 | 6 | * Permission is hereby granted, free of charge, to any person obtaining a |
| 7 | 7 | * copy of this software and associated documentation files (the |
| @@ -24,6 +24,7 @@ · 16 unmodified lines | ||
| 24 | 24 | * USE OR OTHER DEALINGS IN THE SOFTWARE. |
| 25 | 25 | * |
| 26 | 26 | **************************************************************************/ |
| 27 | +#include "vmwgfx_bo.h" | |
| 27 | 28 | #include "vmwgfx_drv.h" |
| 28 | 29 | |
| 29 | 30 | /* |
| @@ -78,11 +79,11 @@ struct vmw_bo_dirty { · 48 unmodified lines | ||
| 78 | 79 | * dirty structure with the results. This function may change the |
| 79 | 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 | 84 | struct vmw_bo_dirty *dirty = vbo->dirty; |
| 84 | − pgoff_t offset = drm_vma_node_start(&vbo->base.base.vma_node); | |
| 85 | − struct address_space *mapping = vbo->base.bdev->dev_mapping; | |
| 85 | + pgoff_t offset = drm_vma_node_start(&vbo->tbo.base.vma_node); | |
| 86 | + struct address_space *mapping = vbo->tbo.bdev->dev_mapping; | |
| 86 | 87 | pgoff_t num_marked; |
| 87 | 88 | |
| 88 | 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 | 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 | 122 | struct vmw_bo_dirty *dirty = vbo->dirty; |
| 122 | − unsigned long offset = drm_vma_node_start(&vbo->base.base.vma_node); | |
| 123 | − struct address_space *mapping = vbo->base.bdev->dev_mapping; | |
| 123 | + unsigned long offset = drm_vma_node_start(&vbo->tbo.base.vma_node); | |
| 124 | + struct address_space *mapping = vbo->tbo.bdev->dev_mapping; | |
| 124 | 125 | pgoff_t num_marked; |
| 125 | 126 | |
| 126 | 127 | if (dirty->end <= dirty->start) |
| 127 | 128 | return; |
| 128 | 129 | |
| 129 | − num_marked = wp_shared_mapping_range(vbo->base.bdev->dev_mapping, | |
| 130 | − dirty->start + offset, | |
| 131 | − dirty->end - dirty->start); | |
| 130 | + num_marked = wp_shared_mapping_range(vbo->tbo.bdev->dev_mapping, | |
| 131 | + dirty->start + offset, | |
| 132 | + dirty->end - dirty->start); | |
| 132 | 133 | |
| 133 | 134 | if (100UL * num_marked / dirty->bitmap_size > |
| 134 | − VMW_DIRTY_PERCENTAGE) { | |
| 135 | + VMW_DIRTY_PERCENTAGE) | |
| 135 | 136 | dirty->change_count++; |
| 136 | − } else { | |
| 137 | + else | |
| 137 | 138 | dirty->change_count = 0; |
| 138 | − } | |
| 139 | 139 | |
| 140 | 140 | if (dirty->change_count > VMW_DIRTY_NUM_CHANGE_TRIGGERS) { |
| 141 | 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 | 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 | 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 | 181 | * when calling unmap_mapping_range(). This function makes sure we pick |
| 182 | 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 | 185 | pgoff_t start, pgoff_t end) |
| 186 | 186 | { |
| 187 | 187 | struct vmw_bo_dirty *dirty = vbo->dirty; |
| 188 | − unsigned long offset = drm_vma_node_start(&vbo->base.base.vma_node); | |
| 189 | − struct address_space *mapping = vbo->base.bdev->dev_mapping; | |
| 188 | + unsigned long offset = drm_vma_node_start(&vbo->tbo.base.vma_node); | |
| 189 | + struct address_space *mapping = vbo->tbo.bdev->dev_mapping; | |
| 190 | 190 | |
| 191 | 191 | if (dirty->method != VMW_BO_DIRTY_PAGETABLE || start >= end) |
| 192 | 192 | return; |
| @@ -206,11 +206,11 @@ static void vmw_bo_dirty_pre_unmap(struct vmw_buffer_object *vbo, · 13 unmodified lines | ||
| 206 | 206 | * |
| 207 | 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 | 210 | pgoff_t start, pgoff_t end) |
| 211 | 211 | { |
| 212 | − unsigned long offset = drm_vma_node_start(&vbo->base.base.vma_node); | |
| 213 | − struct address_space *mapping = vbo->base.bdev->dev_mapping; | |
| 212 | + unsigned long offset = drm_vma_node_start(&vbo->tbo.base.vma_node); | |
| 213 | + struct address_space *mapping = vbo->tbo.bdev->dev_mapping; | |
| 214 | 214 | |
| 215 | 215 | vmw_bo_dirty_pre_unmap(vbo, start, end); |
| 216 | 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 | 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 | 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 | 234 | size_t size; |
| 235 | 235 | int ret; |
| 236 | 236 | |
| @@ -253,8 +253,8 @@ int vmw_bo_dirty_add(struct vmw_buffer_object *vbo) · 16 unmodified lines | ||
| 253 | 253 | if (num_pages < PAGE_SIZE / sizeof(pte_t)) { |
| 254 | 254 | dirty->method = VMW_BO_DIRTY_PAGETABLE; |
| 255 | 255 | } else { |
| 256 | − struct address_space *mapping = vbo->base.bdev->dev_mapping; | |
| 257 | − pgoff_t offset = drm_vma_node_start(&vbo->base.base.vma_node); | |
| 256 | + struct address_space *mapping = vbo->tbo.bdev->dev_mapping; | |
| 257 | + pgoff_t offset = drm_vma_node_start(&vbo->tbo.base.vma_node); | |
| 258 | 258 | |
| 259 | 259 | dirty->method = VMW_BO_DIRTY_MKWRITE; |
| 260 | 260 | |
| @@ -284,7 +284,7 @@ out_no_dirty: · 23 unmodified lines | ||
| 284 | 284 | * |
| 285 | 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 | 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 | 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 | 310 | struct vmw_bo_dirty *dirty = vbo->dirty; |
| 311 | 311 | pgoff_t start, cur, end; |
| 312 | − unsigned long res_start = res->backup_offset; | |
| 313 | − unsigned long res_end = res->backup_offset + res->backup_size; | |
| 312 | + unsigned long res_start = res->guest_memory_offset; | |
| 313 | + unsigned long res_end = res->guest_memory_offset + res->guest_memory_size; | |
| 314 | 314 | |
| 315 | 315 | WARN_ON_ONCE(res_start & ~PAGE_MASK); |
| 316 | 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 | 352 | void vmw_bo_dirty_clear_res(struct vmw_resource *res) |
| 353 | 353 | { |
| 354 | − unsigned long res_start = res->backup_offset; | |
| 355 | − unsigned long res_end = res->backup_offset + res->backup_size; | |
| 356 | − struct vmw_buffer_object *vbo = res->backup; | |
| 354 | + unsigned long res_start = res->guest_memory_offset; | |
| 355 | + unsigned long res_end = res->guest_memory_offset + res->guest_memory_size; | |
| 356 | + struct vmw_bo *vbo = res->guest_memory_bo; | |
| 357 | 357 | struct vmw_bo_dirty *dirty = vbo->dirty; |
| 358 | 358 | |
| 359 | 359 | res_start >>= PAGE_SHIFT; |
| @@ -380,8 +380,7 @@ vm_fault_t vmw_bo_vm_mkwrite(struct vm_fault *vmf) · 20 unmodified lines | ||
| 380 | 380 | vm_fault_t ret; |
| 381 | 381 | unsigned long page_offset; |
| 382 | 382 | unsigned int save_flags; |
| 383 | − struct vmw_buffer_object *vbo = | |
| 384 | − container_of(bo, typeof(*vbo), base); | |
| 383 | + struct vmw_bo *vbo = to_vmw_bo(&bo->base); | |
| 385 | 384 | |
| 386 | 385 | /* |
| 387 | 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 | 418 | struct vm_area_struct *vma = vmf->vma; |
| 420 | 419 | struct ttm_buffer_object *bo = (struct ttm_buffer_object *) |
| 421 | 420 | vma->vm_private_data; |
| 422 | − struct vmw_buffer_object *vbo = | |
| 423 | − container_of(bo, struct vmw_buffer_object, base); | |
| 421 | + struct vmw_bo *vbo = to_vmw_bo(&bo->base); | |
| 424 | 422 | pgoff_t num_prefault; |
| 425 | 423 | pgprot_t prot; |
| 426 | 424 | vm_fault_t ret; |
| @@ -1,7 +1,7 @@ | ||
| 1 | 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 | 6 | * Permission is hereby granted, free of charge, to any person obtaining a |
| 7 | 7 | * copy of this software and associated documentation files (the |
| @@ -27,9 +27,10 @@ · 19 unmodified lines | ||
| 27 | 27 | |
| 28 | 28 | #include <drm/ttm/ttm_placement.h> |
| 29 | 29 | |
| 30 | −#include "vmwgfx_resource_priv.h" | |
| 31 | 30 | #include "vmwgfx_binding.h" |
| 31 | +#include "vmwgfx_bo.h" | |
| 32 | 32 | #include "vmwgfx_drv.h" |
| 33 | +#include "vmwgfx_resource_priv.h" | |
| 33 | 34 | |
| 34 | 35 | #define VMW_RES_EVICT_ERR_COUNT 10 |
| 35 | 36 | |
| @@ -39,10 +40,10 @@ · 3 unmodified lines | ||
| 39 | 40 | */ |
| 40 | 41 | void vmw_resource_mob_attach(struct vmw_resource *res) |
| 41 | 42 | { |
| 42 | − struct vmw_buffer_object *backup = res->backup; | |
| 43 | − struct rb_node **new = &backup->res_tree.rb_node, *parent = NULL; | |
| 43 | + struct vmw_bo *gbo = res->guest_memory_bo; | |
| 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 | 47 | res->used_prio = (res->res_dirty) ? res->func->dirty_prio : |
| 47 | 48 | res->func->prio; |
| 48 | 49 | |
| @@ -51,14 +52,14 @@ void vmw_resource_mob_attach(struct vmw_resource *res) · 2 unmodified lines | ||
| 51 | 52 | container_of(*new, struct vmw_resource, mob_node); |
| 52 | 53 | |
| 53 | 54 | parent = *new; |
| 54 | − new = (res->backup_offset < this->backup_offset) ? | |
| 55 | + new = (res->guest_memory_offset < this->guest_memory_offset) ? | |
| 55 | 56 | &((*new)->rb_left) : &((*new)->rb_right); |
| 56 | 57 | } |
| 57 | 58 | |
| 58 | 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 | 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 | 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 | 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 | 121 | spin_lock(&dev_priv->resource_lock); |
| 121 | 122 | list_del_init(&res->lru_head); |
| 122 | 123 | spin_unlock(&dev_priv->resource_lock); |
| 123 | − if (res->backup) { | |
| 124 | − struct ttm_buffer_object *bo = &res->backup->base; | |
| 124 | + if (res->guest_memory_bo) { | |
| 125 | + struct ttm_buffer_object *bo = &res->guest_memory_bo->tbo; | |
| 125 | 126 | |
| 126 | 127 | ret = ttm_bo_reserve(bo, false, false, NULL); |
| 127 | 128 | BUG_ON(ret); |
| @@ -133,14 +134,14 @@ static void vmw_resource_release(struct kref *kref) · 5 unmodified lines | ||
| 133 | 134 | val_buf.num_shared = 0; |
| 134 | 135 | res->func->unbind(res, false, &val_buf); |
| 135 | 136 | } |
| 136 | − res->backup_dirty = false; | |
| 137 | + res->guest_memory_size = false; | |
| 137 | 138 | vmw_resource_mob_detach(res); |
| 138 | 139 | if (res->dirty) |
| 139 | 140 | res->func->dirty_free(res); |
| 140 | 141 | if (res->coherent) |
| 141 | − vmw_bo_dirty_release(res->backup); | |
| 142 | + vmw_bo_dirty_release(res->guest_memory_bo); | |
| 142 | 143 | ttm_bo_unreserve(bo); |
| 143 | − vmw_bo_unreference(&res->backup); | |
| 144 | + vmw_bo_unreference(&res->guest_memory_bo); | |
| 144 | 145 | } |
| 145 | 146 | |
| 146 | 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 | 224 | INIT_LIST_HEAD(&res->lru_head); |
| 224 | 225 | INIT_LIST_HEAD(&res->binding_head); |
| 225 | 226 | res->id = -1; |
| 226 | − res->backup = NULL; | |
| 227 | − res->backup_offset = 0; | |
| 228 | − res->backup_dirty = false; | |
| 227 | + res->guest_memory_bo = NULL; | |
| 228 | + res->guest_memory_offset = 0; | |
| 229 | + res->guest_memory_dirty = false; | |
| 229 | 230 | res->res_dirty = false; |
| 230 | 231 | res->coherent = false; |
| 231 | 232 | res->used_prio = 3; |
| @@ -263,7 +264,7 @@ int vmw_user_resource_lookup_handle(struct vmw_private *dev_priv, · 31 unmodified lines | ||
| 263 | 264 | int ret = -EINVAL; |
| 264 | 265 | |
| 265 | 266 | base = ttm_base_object_lookup(tfile, handle); |
| 266 | − if (unlikely(base == NULL)) | |
| 267 | + if (unlikely(!base)) | |
| 267 | 268 | return -EINVAL; |
| 268 | 269 | |
| 269 | 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 | 291 | struct drm_file *filp, |
| 291 | 292 | uint32_t handle, |
| 292 | 293 | struct vmw_surface **out_surf, |
| 293 | − struct vmw_buffer_object **out_buf) | |
| 294 | + struct vmw_bo **out_buf) | |
| 294 | 295 | { |
| 295 | 296 | struct ttm_object_file *tfile = vmw_fpriv(filp)->tfile; |
| 296 | 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 | 319 | * @interruptible: Whether any sleeps during allocation should be |
| 319 | 320 | * performed while interruptible. |
| 320 | 321 | */ |
| 321 | 322 | static int vmw_resource_buf_alloc(struct vmw_resource *res, |
| 322 | 323 | bool interruptible) |
| 323 | 324 | { |
| 324 | − unsigned long size = PFN_ALIGN(res->backup_size); | |
| 325 | − struct vmw_buffer_object *backup; | |
| 325 | + unsigned long size = PFN_ALIGN(res->guest_memory_size); | |
| 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 | 334 | int ret; |
| 327 | 335 | |
| 328 | − if (likely(res->backup)) { | |
| 329 | − BUG_ON(res->backup->base.base.size < size); | |
| 336 | + if (likely(res->guest_memory_bo)) { | |
| 337 | + BUG_ON(res->guest_memory_bo->tbo.base.size < size); | |
| 330 | 338 | return 0; |
| 331 | 339 | } |
| 332 | 340 | |
| 333 | − ret = vmw_bo_create(res->dev_priv, res->backup_size, | |
| 334 | − res->func->backup_placement, | |
| 335 | − interruptible, false, | |
| 336 | − &vmw_bo_bo_free, &backup); | |
| 341 | + ret = vmw_bo_create(res->dev_priv, &bo_params, &gbo); | |
| 337 | 342 | if (unlikely(ret != 0)) |
| 338 | 343 | goto out_no_bo; |
| 339 | 344 | |
| 340 | − res->backup = backup; | |
| 345 | + res->guest_memory_bo = gbo; | |
| 341 | 346 | |
| 342 | 347 | out_no_bo: |
| 343 | 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 | 376 | if (func->bind && |
| 372 | − ((func->needs_backup && !vmw_resource_mob_attached(res) && | |
| 373 | − val_buf->bo != NULL) || | |
| 374 | − (!func->needs_backup && val_buf->bo != NULL))) { | |
| 377 | + ((func->needs_guest_memory && !vmw_resource_mob_attached(res) && | |
| 378 | + val_buf->bo) || | |
| 379 | + (!func->needs_guest_memory && val_buf->bo))) { | |
| 375 | 380 | ret = func->bind(res, val_buf); |
| 376 | 381 | if (unlikely(ret != 0)) |
| 377 | 382 | goto out_bind_failed; |
| 378 | − if (func->needs_backup) | |
| 383 | + if (func->needs_guest_memory) | |
| 379 | 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 | 391 | if (func->dirty_alloc && vmw_resource_mob_attached(res) && |
| 387 | 392 | !res->coherent) { |
| 388 | − if (res->backup->dirty && !res->dirty) { | |
| 393 | + if (res->guest_memory_bo->dirty && !res->dirty) { | |
| 389 | 394 | ret = func->dirty_alloc(res); |
| 390 | 395 | if (ret) |
| 391 | 396 | return ret; |
| 392 | − } else if (!res->backup->dirty && res->dirty) { | |
| 397 | + } else if (!res->guest_memory_bo->dirty && res->dirty) { | |
| 393 | 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 | 406 | if (res->dirty) { |
| 402 | 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 | 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 | 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 | 416 | vmw_bo_dirty_transfer_to_res(res); |
| @@ -427,10 +432,10 @@ out_bind_failed: · 15 unmodified lines | ||
| 427 | 432 | * @res: Pointer to the struct vmw_resource to unreserve. |
| 428 | 433 | * @dirty_set: Change dirty status of the resource. |
| 429 | 434 | * @dirty: When changing dirty status indicates the new status. |
| 430 | − * @switch_backup: Backup buffer has been switched. | |
| 431 | − * @new_backup: Pointer to new backup buffer if command submission | |
| 435 | + * @switch_guest_memory: Guest memory buffer has been switched. | |
| 436 | + * @new_guest_memory_bo: Pointer to new guest memory buffer if command submission | |
| 432 | 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 | 440 | * Currently unreserving a resource means putting it back on the device's |
| 436 | 441 | * resource lru list, so that it can be evicted if necessary. |
| @@ -438,42 +443,42 @@ out_bind_failed: · 1 unmodified line | ||
| 438 | 443 | void vmw_resource_unreserve(struct vmw_resource *res, |
| 439 | 444 | bool dirty_set, |
| 440 | 445 | bool dirty, |
| 441 | − bool switch_backup, | |
| 442 | − struct vmw_buffer_object *new_backup, | |
| 443 | − unsigned long new_backup_offset) | |
| 446 | + bool switch_guest_memory, | |
| 447 | + struct vmw_bo *new_guest_memory_bo, | |
| 448 | + unsigned long new_guest_memory_offset) | |
| 444 | 449 | { |
| 445 | 450 | struct vmw_private *dev_priv = res->dev_priv; |
| 446 | 451 | |
| 447 | 452 | if (!list_empty(&res->lru_head)) |
| 448 | 453 | return; |
| 449 | 454 | |
| 450 | − if (switch_backup && new_backup != res->backup) { | |
| 451 | − if (res->backup) { | |
| 455 | + if (switch_guest_memory && new_guest_memory_bo != res->guest_memory_bo) { | |
| 456 | + if (res->guest_memory_bo) { | |
| 452 | 457 | vmw_resource_mob_detach(res); |
| 453 | 458 | if (res->coherent) |
| 454 | − vmw_bo_dirty_release(res->backup); | |
| 455 | − vmw_bo_unreference(&res->backup); | |
| 459 | + vmw_bo_dirty_release(res->guest_memory_bo); | |
| 460 | + vmw_bo_unreference(&res->guest_memory_bo); | |
| 456 | 461 | } |
| 457 | 462 | |
| 458 | − if (new_backup) { | |
| 459 | − res->backup = vmw_bo_reference(new_backup); | |
| 463 | + if (new_guest_memory_bo) { | |
| 464 | + res->guest_memory_bo = vmw_bo_reference(new_guest_memory_bo); | |
| 460 | 465 | |
| 461 | 466 | /* |
| 462 | 467 | * The validation code should already have added a |
| 463 | 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 | 472 | vmw_resource_mob_attach(res); |
| 468 | 473 | } else { |
| 469 | − res->backup = NULL; | |
| 474 | + res->guest_memory_bo = NULL; | |
| 470 | 475 | } |
| 471 | − } else if (switch_backup && res->coherent) { | |
| 472 | − vmw_bo_dirty_release(res->backup); | |
| 476 | + } else if (switch_guest_memory && res->coherent) { | |
| 477 | + vmw_bo_dirty_release(res->guest_memory_bo); | |
| 473 | 478 | } |
| 474 | 479 | |
| 475 | − if (switch_backup) | |
| 476 | − res->backup_offset = new_backup_offset; | |
| 480 | + if (switch_guest_memory) | |
| 481 | + res->guest_memory_offset = new_guest_memory_offset; | |
| 477 | 482 | |
| 478 | 483 | if (dirty_set) |
| 479 | 484 | res->res_dirty = dirty; |
| @@ -507,30 +512,32 @@ vmw_resource_check_buffer(struct ww_acquire_ctx *ticket, · 27 unmodified lines | ||
| 507 | 512 | { |
| 508 | 513 | struct ttm_operation_ctx ctx = { true, false }; |
| 509 | 514 | struct list_head val_list; |
| 510 | − bool backup_dirty = false; | |
| 515 | + bool guest_memory_dirty = false; | |
| 511 | 516 | int ret; |
| 512 | 517 | |
| 513 | − if (unlikely(res->backup == NULL)) { | |
| 518 | + if (unlikely(!res->guest_memory_bo)) { | |
| 514 | 519 | ret = vmw_resource_buf_alloc(res, interruptible); |
| 515 | 520 | if (unlikely(ret != 0)) |
| 516 | 521 | return ret; |
| 517 | 522 | } |
| 518 | 523 | |
| 519 | 524 | INIT_LIST_HEAD(&val_list); |
| 520 | − ttm_bo_get(&res->backup->base); | |
| 521 | − val_buf->bo = &res->backup->base; | |
| 525 | + ttm_bo_get(&res->guest_memory_bo->tbo); | |
| 526 | + val_buf->bo = &res->guest_memory_bo->tbo; | |
| 522 | 527 | val_buf->num_shared = 0; |
| 523 | 528 | list_add_tail(&val_buf->head, &val_list); |
| 524 | 529 | ret = ttm_eu_reserve_buffers(ticket, &val_list, interruptible, NULL); |
| 525 | 530 | if (unlikely(ret != 0)) |
| 526 | 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 | 534 | return 0; |
| 530 | 535 | |
| 531 | − backup_dirty = res->backup_dirty; | |
| 532 | − ret = ttm_bo_validate(&res->backup->base, | |
| 533 | − res->func->backup_placement, | |
| 536 | + guest_memory_dirty = res->guest_memory_dirty; | |
| 537 | + vmw_bo_placement_set(res->guest_memory_bo, res->func->domain, | |
| 538 | + res->func->busy_domain); | |
| 539 | + ret = ttm_bo_validate(&res->guest_memory_bo->tbo, | |
| 540 | + &res->guest_memory_bo->placement, | |
| 534 | 541 | &ctx); |
| 535 | 542 | |
| 536 | 543 | if (unlikely(ret != 0)) |
| @@ -543,8 +550,8 @@ out_no_validate: · 6 unmodified lines | ||
| 543 | 550 | out_no_reserve: |
| 544 | 551 | ttm_bo_put(val_buf->bo); |
| 545 | 552 | val_buf->bo = NULL; |
| 546 | − if (backup_dirty) | |
| 547 | − vmw_bo_unreference(&res->backup); | |
| 553 | + if (guest_memory_dirty) | |
| 554 | + vmw_bo_unreference(&res->guest_memory_bo); | |
| 548 | 555 | |
| 549 | 556 | return ret; |
| 550 | 557 | } |
| @@ -555,12 +562,13 @@ out_no_reserve: · 4 unmodified lines | ||
| 555 | 562 | * @res: The resource to reserve. |
| 556 | 563 | * |
| 557 | 564 | * This function takes the resource off the LRU list and make sure |
| 558 | − * a backup buffer is present for guest-backed resources. However, | |
| 559 | − * the buffer may not be bound to the resource at this point. | |
| 565 | + * a guest memory buffer is present for guest-backed resources. | |
| 566 | + * However, the buffer may not be bound to the resource at this | |
| 567 | + * point. | |
| 560 | 568 | * |
| 561 | 569 | */ |
| 562 | 570 | int vmw_resource_reserve(struct vmw_resource *res, bool interruptible, |
| 563 | − bool no_backup) | |
| 571 | + bool no_guest_memory) | |
| 564 | 572 | { |
| 565 | 573 | struct vmw_private *dev_priv = res->dev_priv; |
| 566 | 574 | int ret; |
| @@ -569,13 +577,13 @@ int vmw_resource_reserve(struct vmw_resource *res, bool interruptible, · 2 unmodified lines | ||
| 569 | 577 | list_del_init(&res->lru_head); |
| 570 | 578 | spin_unlock(&dev_priv->resource_lock); |
| 571 | 579 | |
| 572 | − if (res->func->needs_backup && res->backup == NULL && | |
| 573 | − !no_backup) { | |
| 580 | + if (res->func->needs_guest_memory && !res->guest_memory_bo && | |
| 581 | + !no_guest_memory) { | |
| 574 | 582 | ret = vmw_resource_buf_alloc(res, interruptible); |
| 575 | 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 | 585 | "of size %lu. bytes\n", |
| 578 | − (unsigned long) res->backup_size); | |
| 586 | + (unsigned long) res->guest_memory_size); | |
| 579 | 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 | 595 | * vmw_resource_backoff_reservation - Unreserve and unreference a |
| 588 | − * backup buffer | |
| 596 | + * guest memory buffer | |
| 589 | 597 | *. |
| 590 | 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 | 601 | static void |
| 594 | 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 | 638 | return ret; |
| 631 | 639 | |
| 632 | 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 | 642 | ret = func->unbind(res, res->res_dirty, &val_buf); |
| 635 | 643 | if (unlikely(ret != 0)) |
| 636 | 644 | goto out_no_unbind; |
| 637 | 645 | vmw_resource_mob_detach(res); |
| 638 | 646 | } |
| 639 | 647 | ret = func->destroy(res); |
| 640 | − res->backup_dirty = true; | |
| 648 | + res->guest_memory_dirty = true; | |
| 641 | 649 | res->res_dirty = false; |
| 642 | 650 | out_no_unbind: |
| 643 | 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 | 685 | val_buf.bo = NULL; |
| 678 | 686 | val_buf.num_shared = 0; |
| 679 | − if (res->backup) | |
| 680 | − val_buf.bo = &res->backup->base; | |
| 687 | + if (res->guest_memory_bo) | |
| 688 | + val_buf.bo = &res->guest_memory_bo->tbo; | |
| 681 | 689 | do { |
| 682 | 690 | ret = vmw_resource_do_validate(res, &val_buf, dirtying); |
| 683 | 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 | 726 | if (unlikely(ret != 0)) |
| 719 | 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 | 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 | 733 | return 0; |
| @@ -740,14 +748,14 @@ out_no_validate: · 14 unmodified lines | ||
| 740 | 748 | * validation code, since resource validation and eviction |
| 741 | 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 | 753 | struct ttm_validate_buffer val_buf = { |
| 746 | − .bo = &vbo->base, | |
| 754 | + .bo = &vbo->tbo, | |
| 747 | 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 | 759 | while (!RB_EMPTY_ROOT(&vbo->res_tree)) { |
| 752 | 760 | struct rb_node *node = vbo->res_tree.rb_node; |
| 753 | 761 | struct vmw_resource *res = |
| @@ -756,12 +764,12 @@ void vmw_resource_unbind_list(struct vmw_buffer_object *vbo) · 2 unmodified lines | ||
| 756 | 764 | if (!WARN_ON_ONCE(!res->func->unbind)) |
| 757 | 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 | 768 | res->res_dirty = false; |
| 761 | 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 | 781 | * Read back cached states from the device if they exist. This function |
| 774 | 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 | 786 | struct vmw_resource *dx_query_ctx; |
| 779 | 787 | struct vmw_private *dev_priv; |
| @@ -822,20 +830,19 @@ void vmw_query_move_notify(struct ttm_buffer_object *bo, · 42 unmodified lines | ||
| 822 | 830 | struct ttm_resource *old_mem, |
| 823 | 831 | struct ttm_resource *new_mem) |
| 824 | 832 | { |
| 825 | − struct vmw_buffer_object *dx_query_mob; | |
| 833 | + struct vmw_bo *dx_query_mob; | |
| 826 | 834 | struct ttm_device *bdev = bo->bdev; |
| 827 | − struct vmw_private *dev_priv; | |
| 828 | − | |
| 829 | − dev_priv = container_of(bdev, struct vmw_private, bdev); | |
| 835 | + struct vmw_private *dev_priv = vmw_priv_from_ttm(bdev); | |
| 830 | 836 | |
| 831 | 837 | mutex_lock(&dev_priv->binding_mutex); |
| 832 | 838 | |
| 833 | 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 | 842 | old_mem->mem_type == VMW_PL_MOB) { |
| 836 | 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 | 846 | if (!dx_query_mob || !dx_query_mob->dx_query_ctx) { |
| 840 | 847 | mutex_unlock(&dev_priv->binding_mutex); |
| 841 | 848 | return; |
| @@ -863,7 +870,7 @@ void vmw_query_move_notify(struct ttm_buffer_object *bo, · 21 unmodified lines | ||
| 863 | 870 | */ |
| 864 | 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 | 966 | goto out_no_reserve; |
| 960 | 967 | |
| 961 | 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) { | |
| 965 | − vbo = res->backup; | |
| 971 | + if (res->guest_memory_bo) { | |
| 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 | 975 | if (ret) |
| 969 | 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 | 981 | ret = ttm_bo_validate |
| 972 | − (&vbo->base, | |
| 973 | − res->func->backup_placement, | |
| 982 | + (&vbo->tbo, | |
| 983 | + &vbo->placement, | |
| 974 | 984 | &ctx); |
| 975 | 985 | if (ret) { |
| 976 | − ttm_bo_unreserve(&vbo->base); | |
| 986 | + ttm_bo_unreserve(&vbo->tbo); | |
| 977 | 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 | 994 | ret = vmw_resource_validate(res, interruptible, true); |
| 985 | 995 | if (vbo) |
| 986 | − ttm_bo_unreserve(&vbo->base); | |
| 996 | + ttm_bo_unreserve(&vbo->tbo); | |
| 987 | 997 | if (ret) |
| 988 | 998 | goto out_no_validate; |
| 989 | 999 | } |
| @@ -1016,12 +1026,12 @@ void vmw_resource_unpin(struct vmw_resource *res) · 26 unmodified lines | ||
| 1016 | 1026 | WARN_ON(ret); |
| 1017 | 1027 | |
| 1018 | 1028 | WARN_ON(res->pin_count == 0); |
| 1019 | − if (--res->pin_count == 0 && res->backup) { | |
| 1020 | − struct vmw_buffer_object *vbo = res->backup; | |
| 1029 | + if (--res->pin_count == 0 && res->guest_memory_bo) { | |
| 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 | 1033 | vmw_bo_pin_reserved(vbo, false); |
| 1024 | − ttm_bo_unreserve(&vbo->base); | |
| 1034 | + ttm_bo_unreserve(&vbo->tbo); | |
| 1025 | 1035 | } |
| 1026 | 1036 | |
| 1027 | 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 | 1072 | * @num_prefault: Returns how many pages including the first have been |
| 1063 | 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 | 1076 | pgoff_t end, pgoff_t *num_prefault) |
| 1067 | 1077 | { |
| 1068 | 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 | 1089 | struct vmw_resource *cur_res = |
| 1080 | 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 | 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 | 1095 | res_start) { |
| 1086 | 1096 | cur = cur->rb_right; |
| 1087 | 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 | 1106 | * intersecting the range. |
| 1097 | 1107 | */ |
| 1098 | 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 | 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 | 1122 | cur = rb_next(&found->mob_node); |
| 1113 | 1123 | if (!cur) |
| 1114 | 1124 | break; |
| 1115 | 1125 | |
| 1116 | 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 | 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 | 1134 | *num_prefault = 1; |
| 1125 | 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 | 1138 | *num_prefault = __KERNEL_DIV_ROUND_UP(last_cleaned - res_start, |
| 1129 | 1139 | PAGE_SIZE); |
| @@ -58,10 +58,11 @@ struct vmw_user_resource_conv { · 57 unmodified lines | ||
| 58 | 58 | * struct vmw_res_func - members and functions common for a resource type |
| 59 | 59 | * |
| 60 | 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 | 62 | * persistent buffer storage. |
| 63 | 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 | 66 | * @may_evict Whether the resource may be evicted. |
| 66 | 67 | * @create: Create a hardware resource. |
| 67 | 68 | * @destroy: Destroy a hardware resource. |
| @@ -81,9 +82,10 @@ struct vmw_user_resource_conv { · 13 unmodified lines | ||
| 81 | 82 | */ |
| 82 | 83 | struct vmw_res_func { |
| 83 | 84 | enum vmw_res_type res_type; |
| 84 | − bool needs_backup; | |
| 85 | + bool needs_guest_memory; | |
| 85 | 86 | const char *type_name; |
| 86 | − struct ttm_placement *backup_placement; | |
| 87 | + u32 domain; | |
| 88 | + u32 busy_domain; | |
| 87 | 89 | bool may_evict; |
| 88 | 90 | u32 prio; |
| 89 | 91 | u32 dirty_prio; |
| @@ -1,7 +1,7 @@ | ||
| 1 | 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 | 6 | * Permission is hereby granted, free of charge, to any person obtaining a |
| 7 | 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 | 31 | #include <drm/drm_atomic.h> |
| 29 | 32 | #include <drm/drm_atomic_helper.h> |
| 30 | 33 | #include <drm/drm_damage_helper.h> |
| 31 | 34 | #include <drm/drm_fourcc.h> |
| 32 | 35 | |
| 33 | −#include "vmwgfx_kms.h" | |
| 34 | − | |
| 35 | 36 | #define vmw_crtc_to_sou(x) \ |
| 36 | 37 | container_of(x, struct vmw_screen_object_unit, base.crtc) |
| 37 | 38 | #define vmw_encoder_to_sou(x) \ |
| @@ -89,7 +90,7 @@ struct vmw_screen_object_unit { · 51 unmodified lines | ||
| 89 | 90 | struct vmw_display_unit base; |
| 90 | 91 | |
| 91 | 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 | 95 | bool defined; |
| 95 | 96 | }; |
| @@ -148,7 +149,7 @@ static int vmw_sou_fifo_create(struct vmw_private *dev_priv, · 52 unmodified lines | ||
| 148 | 149 | sou->base.set_gui_y = cmd->obj.root.y; |
| 149 | 150 | |
| 150 | 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 | 153 | cmd->obj.backingStore.pitch = mode->hdisplay * 4; |
| 153 | 154 | |
| 154 | 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 | 410 | struct drm_crtc *crtc = plane->state->crtc ?: new_state->crtc; |
| 410 | 411 | struct vmw_plane_state *vps = vmw_plane_state_to_vps(new_state); |
| 411 | 412 | struct vmw_private *dev_priv; |
| 412 | − size_t size; | |
| 413 | 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 | 421 | if (!new_fb) { |
| 417 | 422 | vmw_bo_unreference(&vps->bo); |
| @@ -420,11 +425,11 @@ vmw_sou_primary_plane_prepare_fb(struct drm_plane *plane, · 2 unmodified lines | ||
| 420 | 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 | 429 | dev_priv = vmw_priv(crtc->dev); |
| 425 | 430 | |
| 426 | 431 | if (vps->bo) { |
| 427 | − if (vps->bo_size == size) { | |
| 432 | + if (vps->bo_size == bo_params.size) { | |
| 428 | 433 | /* |
| 429 | 434 | * Note that this might temporarily up the pin-count |
| 430 | 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 | 448 | * resume the overlays, this is preferred to failing to alloc. |
| 444 | 449 | */ |
| 445 | 450 | vmw_overlay_pause_all(dev_priv); |
| 446 | − ret = vmw_bo_create(dev_priv, size, | |
| 447 | − &vmw_vram_placement, | |
| 448 | − false, true, &vmw_bo_bo_free, &vps->bo); | |
| 451 | + ret = vmw_bo_create(dev_priv, &bo_params, &vps->bo); | |
| 449 | 452 | vmw_overlay_resume_all(dev_priv); |
| 450 | − if (ret) { | |
| 451 | − vps->bo = NULL; /* vmw_bo_init frees on error */ | |
| 453 | + if (ret) | |
| 452 | 454 | return ret; |
| 453 | − } | |
| 454 | 455 | |
| 455 | − vps->bo_size = size; | |
| 456 | + vps->bo_size = bo_params.size; | |
| 456 | 457 | |
| 457 | 458 | /* |
| 458 | 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 | 490 | gmr->body.format.colorDepth = depth; |
| 490 | 491 | gmr->body.format.reserved = 0; |
| 491 | 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 | 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 | 547 | bo_update.base.vfb = vfb; |
| 547 | 548 | bo_update.base.out_fence = out_fence; |
| 548 | 549 | bo_update.base.mutex = NULL; |
| 549 | − bo_update.base.cpu_blit = false; | |
| 550 | 550 | bo_update.base.intr = true; |
| 551 | 551 | |
| 552 | 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 | 707 | srf_update.base.vfb = vfb; |
| 708 | 708 | srf_update.base.out_fence = out_fence; |
| 709 | 709 | srf_update.base.mutex = &dev_priv->cmdbuf_mutex; |
| 710 | − srf_update.base.cpu_blit = false; | |
| 711 | 710 | srf_update.base.intr = true; |
| 712 | 711 | |
| 713 | 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 | 946 | static int do_bo_define_gmrfb(struct vmw_private *dev_priv, |
| 948 | 947 | struct vmw_framebuffer *framebuffer) |
| 949 | 948 | { |
| 950 | − struct vmw_buffer_object *buf = | |
| 949 | + struct vmw_bo *buf = | |
| 951 | 950 | container_of(framebuffer, struct vmw_framebuffer_bo, |
| 952 | 951 | base)->buffer; |
| 953 | 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 | 972 | cmd->body.format.reserved = 0; |
| 974 | 973 | cmd->body.bytesPerLine = framebuffer->base.pitches[0]; |
| 975 | 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 | 976 | vmw_cmd_commit(dev_priv, sizeof(*cmd)); |
| 978 | 977 | |
| 979 | 978 | return 0; |
| @@ -1216,14 +1215,16 @@ int vmw_kms_sou_do_bo_dirty(struct vmw_private *dev_priv, · 236 unmodified lines | ||
| 1216 | 1215 | struct vmw_fence_obj **out_fence, |
| 1217 | 1216 | struct drm_crtc *crtc) |
| 1218 | 1217 | { |
| 1219 | − struct vmw_buffer_object *buf = | |
| 1218 | + struct vmw_bo *buf = | |
| 1220 | 1219 | container_of(framebuffer, struct vmw_framebuffer_bo, |
| 1221 | 1220 | base)->buffer; |
| 1222 | 1221 | struct vmw_kms_dirty dirty; |
| 1223 | 1222 | DECLARE_VAL_CONTEXT(val_ctx, NULL, 0); |
| 1224 | 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 | 1228 | if (ret) |
| 1228 | 1229 | return ret; |
| 1229 | 1230 | |
| @@ -1323,13 +1324,15 @@ int vmw_kms_sou_readback(struct vmw_private *dev_priv, · 93 unmodified lines | ||
| 1323 | 1324 | uint32_t num_clips, |
| 1324 | 1325 | struct drm_crtc *crtc) |
| 1325 | 1326 | { |
| 1326 | − struct vmw_buffer_object *buf = | |
| 1327 | + struct vmw_bo *buf = | |
| 1327 | 1328 | container_of(vfb, struct vmw_framebuffer_bo, base)->buffer; |
| 1328 | 1329 | struct vmw_kms_dirty dirty; |
| 1329 | 1330 | DECLARE_VAL_CONTEXT(val_ctx, NULL, 0); |
| 1330 | 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 | 1336 | if (ret) |
| 1334 | 1337 | return ret; |
| 1335 | 1338 | |
| @@ -1,7 +1,7 @@ | ||
| 1 | 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 | 6 | * Permission is hereby granted, free of charge, to any person obtaining a |
| 7 | 7 | * copy of this software and associated documentation files (the |
| @@ -27,9 +27,10 @@ · 19 unmodified lines | ||
| 27 | 27 | |
| 28 | 28 | #include <drm/ttm/ttm_placement.h> |
| 29 | 29 | |
| 30 | +#include "vmwgfx_binding.h" | |
| 31 | +#include "vmwgfx_bo.h" | |
| 30 | 32 | #include "vmwgfx_drv.h" |
| 31 | 33 | #include "vmwgfx_resource_priv.h" |
| 32 | −#include "vmwgfx_binding.h" | |
| 33 | 34 | |
| 34 | 35 | struct vmw_shader { |
| 35 | 36 | struct vmw_resource res; |
| @@ -88,12 +89,13 @@ const struct vmw_user_resource_conv *user_shader_converter = · 52 unmodified lines | ||
| 88 | 89 | |
| 89 | 90 | static const struct vmw_res_func vmw_gb_shader_func = { |
| 90 | 91 | .res_type = vmw_res_shader, |
| 91 | − .needs_backup = true, | |
| 92 | + .needs_guest_memory = true, | |
| 92 | 93 | .may_evict = true, |
| 93 | 94 | .prio = 3, |
| 94 | 95 | .dirty_prio = 3, |
| 95 | 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 | 99 | .create = vmw_gb_shader_create, |
| 98 | 100 | .destroy = vmw_gb_shader_destroy, |
| 99 | 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 | 105 | static const struct vmw_res_func vmw_dx_shader_func = { |
| 104 | 106 | .res_type = vmw_res_shader, |
| 105 | − .needs_backup = true, | |
| 107 | + .needs_guest_memory = true, | |
| 106 | 108 | .may_evict = true, |
| 107 | 109 | .prio = 3, |
| 108 | 110 | .dirty_prio = 3, |
| 109 | 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 | 114 | .create = vmw_dx_shader_create, |
| 112 | 115 | /* |
| 113 | 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 | 161 | SVGA3dShaderType type, |
| 159 | 162 | uint8_t num_input_sig, |
| 160 | 163 | uint8_t num_output_sig, |
| 161 | − struct vmw_buffer_object *byte_code, | |
| 164 | + struct vmw_bo *byte_code, | |
| 162 | 165 | void (*res_free) (struct vmw_resource *res)) |
| 163 | 166 | { |
| 164 | 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 | 178 | return ret; |
| 176 | 179 | } |
| 177 | 180 | |
| 178 | − res->backup_size = size; | |
| 181 | + res->guest_memory_size = size; | |
| 179 | 182 | if (byte_code) { |
| 180 | − res->backup = vmw_bo_reference(byte_code); | |
| 181 | − res->backup_offset = offset; | |
| 183 | + res->guest_memory_bo = vmw_bo_reference(byte_code); | |
| 184 | + res->guest_memory_offset = offset; | |
| 182 | 185 | } |
| 183 | 186 | shader->size = size; |
| 184 | 187 | shader->type = type; |
| @@ -259,8 +262,8 @@ static int vmw_gb_shader_bind(struct vmw_resource *res, · 74 unmodified lines | ||
| 259 | 262 | cmd->header.size = sizeof(cmd->body); |
| 260 | 263 | cmd->body.shid = res->id; |
| 261 | 264 | cmd->body.mobid = bo->resource->start; |
| 262 | − cmd->body.offsetInBytes = res->backup_offset; | |
| 263 | − res->backup_dirty = false; | |
| 265 | + cmd->body.offsetInBytes = res->guest_memory_offset; | |
| 266 | + res->guest_memory_dirty = false; | |
| 264 | 267 | vmw_cmd_commit(dev_priv, sizeof(*cmd)); |
| 265 | 268 | |
| 266 | 269 | return 0; |
| @@ -277,7 +280,7 @@ static int vmw_gb_shader_unbind(struct vmw_resource *res, · 10 unmodified lines | ||
| 277 | 280 | } *cmd; |
| 278 | 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 | 285 | cmd = VMW_CMD_RESERVE(dev_priv, sizeof(*cmd)); |
| 283 | 286 | if (unlikely(cmd == NULL)) |
| @@ -397,8 +400,8 @@ static int vmw_dx_shader_unscrub(struct vmw_resource *res) · 113 unmodified lines | ||
| 397 | 400 | cmd->header.size = sizeof(cmd->body); |
| 398 | 401 | cmd->body.cid = shader->ctx->id; |
| 399 | 402 | cmd->body.shid = shader->id; |
| 400 | − cmd->body.mobid = res->backup->base.resource->start; | |
| 401 | − cmd->body.offsetInBytes = res->backup_offset; | |
| 403 | + cmd->body.mobid = res->guest_memory_bo->tbo.resource->start; | |
| 404 | + cmd->body.offsetInBytes = res->guest_memory_offset; | |
| 402 | 405 | vmw_cmd_commit(dev_priv, sizeof(*cmd)); |
| 403 | 406 | |
| 404 | 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 | 511 | struct vmw_fence_obj *fence; |
| 509 | 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 | 516 | mutex_lock(&dev_priv->binding_mutex); |
| 514 | 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 | 685 | static int vmw_user_shader_alloc(struct vmw_private *dev_priv, |
| 683 | − struct vmw_buffer_object *buffer, | |
| 686 | + struct vmw_bo *buffer, | |
| 684 | 687 | size_t shader_size, |
| 685 | 688 | size_t offset, |
| 686 | 689 | SVGA3dShaderType shader_type, |
| @@ -734,7 +737,7 @@ out: · 47 unmodified lines | ||
| 734 | 737 | |
| 735 | 738 | |
| 736 | 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 | 741 | size_t shader_size, |
| 739 | 742 | size_t offset, |
| 740 | 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 | 775 | struct vmw_private *dev_priv = vmw_priv(dev); |
| 773 | 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 | 778 | SVGA3dShaderType shader_type; |
| 776 | 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 | 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 | 789 | VMW_DEBUG_USER("Illegal buffer- or shader size.\n"); |
| 787 | 790 | ret = -EINVAL; |
| 788 | 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 | 810 | num_output_sig, tfile, shader_handle); |
| 808 | 811 | out_bad_arg: |
| 809 | 812 | vmw_bo_unreference(&buffer); |
| 810 | − drm_gem_object_put(&buffer->base.base); | |
| 813 | + drm_gem_object_put(&buffer->tbo.base); | |
| 811 | 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 | 887 | struct list_head *list) |
| 885 | 888 | { |
| 886 | 889 | struct ttm_operation_ctx ctx = { false, true }; |
| 887 | − struct vmw_buffer_object *buf; | |
| 890 | + struct vmw_bo *buf; | |
| 888 | 891 | struct ttm_bo_kmap_obj map; |
| 889 | 892 | bool is_iomem; |
| 890 | 893 | int ret; |
| 891 | 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 | 903 | if (!vmw_shader_id_ok(user_key, shader_type)) |
| 894 | 904 | return -EINVAL; |
| 895 | 905 | |
| 896 | − ret = vmw_bo_create(dev_priv, size, &vmw_sys_placement, | |
| 897 | − true, true, vmw_bo_bo_free, &buf); | |
| 906 | + ret = vmw_bo_create(dev_priv, &bo_params, &buf); | |
| 898 | 907 | if (unlikely(ret != 0)) |
| 899 | 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 | 911 | if (unlikely(ret != 0)) |
| 903 | 912 | goto no_reserve; |
| 904 | 913 | |
| 905 | 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 | 916 | if (unlikely(ret != 0)) { |
| 908 | − ttm_bo_unreserve(&buf->base); | |
| 917 | + ttm_bo_unreserve(&buf->tbo); | |
| 909 | 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 | 922 | WARN_ON(is_iomem); |
| 914 | 923 | |
| 915 | 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 | 926 | WARN_ON(ret != 0); |
| 918 | − ttm_bo_unreserve(&buf->base); | |
| 927 | + ttm_bo_unreserve(&buf->tbo); | |
| 919 | 928 | |
| 920 | 929 | res = vmw_shader_alloc(dev_priv, buf, size, 0, shader_type); |
| 921 | 930 | if (unlikely(ret != 0)) |
| @@ -24,6 +24,7 @@ · 23 unmodified lines | ||
| 24 | 24 | * |
| 25 | 25 | **************************************************************************/ |
| 26 | 26 | |
| 27 | +#include "vmwgfx_bo.h" | |
| 27 | 28 | #include "vmwgfx_drv.h" |
| 28 | 29 | #include "vmwgfx_resource_priv.h" |
| 29 | 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 | 83 | static const struct vmw_res_func vmw_view_func = { |
| 83 | 84 | .res_type = vmw_res_view, |
| 84 | − .needs_backup = false, | |
| 85 | + .needs_guest_memory = false, | |
| 85 | 86 | .may_evict = false, |
| 86 | 87 | .type_name = "DX view", |
| 87 | − .backup_placement = NULL, | |
| 88 | + .domain = VMW_BO_DOMAIN_SYS, | |
| 89 | + .busy_domain = VMW_BO_DOMAIN_SYS, | |
| 88 | 90 | .create = vmw_view_create, |
| 89 | 91 | .commit_notify = vmw_view_commit_notify, |
| 90 | 92 | }; |
| @@ -1,7 +1,7 @@ | ||
| 1 | 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 | 6 | * Permission is hereby granted, free of charge, to any person obtaining a |
| 7 | 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 | 32 | #include <drm/drm_atomic.h> |
| 29 | 33 | #include <drm/drm_atomic_helper.h> |
| 30 | 34 | #include <drm/drm_damage_helper.h> |
| 31 | 35 | #include <drm/drm_fourcc.h> |
| 32 | 36 | |
| 33 | −#include "vmwgfx_kms.h" | |
| 34 | −#include "vmw_surface_cache.h" | |
| 35 | − | |
| 36 | 37 | #define vmw_crtc_to_stdu(x) \ |
| 37 | 38 | container_of(x, struct vmw_screen_target_display_unit, base.crtc) |
| 38 | 39 | #define vmw_encoder_to_stdu(x) \ |
| @@ -65,12 +66,11 @@ enum stdu_content_type { · 26 unmodified lines | ||
| 65 | 66 | */ |
| 66 | 67 | struct vmw_stdu_dirty { |
| 67 | 68 | struct vmw_kms_dirty base; |
| 68 | − SVGA3dTransferType transfer; | |
| 69 | 69 | s32 left, right, top, bottom; |
| 70 | 70 | s32 fb_left, fb_top; |
| 71 | 71 | u32 pitch; |
| 72 | 72 | union { |
| 73 | − struct vmw_buffer_object *buf; | |
| 73 | + struct vmw_bo *buf; | |
| 74 | 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 | 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 | 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 | 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 | 504 | return; |
| 598 | 505 | |
| 599 | 506 | /* Assume we are blitting from Guest (bo) to Host (display_srf) */ |
| 600 | − dst_pitch = stdu->display_srf->metadata.base_size.width * stdu->cpp; | |
| 601 | − dst_bo = &stdu->display_srf->res.backup->base; | |
| 602 | − dst_offset = ddirty->top * dst_pitch + ddirty->left * stdu->cpp; | |
| 603 | − | |
| 604 | − src_pitch = ddirty->pitch; | |
| 605 | − src_bo = &ddirty->buf->base; | |
| 606 | − src_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 | − } | |
| 507 | + src_pitch = stdu->display_srf->metadata.base_size.width * stdu->cpp; | |
| 508 | + src_bo = &stdu->display_srf->res.guest_memory_bo->tbo; | |
| 509 | + src_offset = ddirty->top * dst_pitch + ddirty->left * stdu->cpp; | |
| 510 | + | |
| 511 | + dst_pitch = ddirty->pitch; | |
| 512 | + dst_bo = &ddirty->buf->tbo; | |
| 513 | + dst_offset = ddirty->fb_top * src_pitch + ddirty->fb_left * stdu->cpp; | |
| 614 | 514 | |
| 615 | 515 | (void) vmw_bo_cpu_blit(dst_bo, dst_offset, dst_pitch, |
| 616 | 516 | src_bo, src_offset, src_pitch, |
| 617 | 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 | 522 | * framebuffer and the screen target system. |
| 657 | 523 | * |
| 658 | 524 | * @dev_priv: Pointer to the device private structure. |
| @@ -665,9 +531,6 @@ out_cleanup: · 6 unmodified lines | ||
| 665 | 531 | * be NULL. |
| 666 | 532 | * @num_clips: Number of clip rects in @clips or @vclips. |
| 667 | 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 | 534 | * @crtc: If crtc is passed, perform stdu dma on that crtc only. |
| 672 | 535 | * |
| 673 | 536 | * If DMA-ing till the screen target system, the function will also notify |
| @@ -676,59 +539,49 @@ out_cleanup: · 2 unmodified lines | ||
| 676 | 539 | * Returns 0 on success, negative error code on failure. -ERESTARTSYS if |
| 677 | 540 | * interrupted. |
| 678 | 541 | */ |
| 679 | −int vmw_kms_stdu_dma(struct vmw_private *dev_priv, | |
| 680 | − struct drm_file *file_priv, | |
| 681 | − struct vmw_framebuffer *vfb, | |
| 682 | − struct drm_vmw_fence_rep __user *user_fence_rep, | |
| 683 | − struct drm_clip_rect *clips, | |
| 684 | − struct drm_vmw_rect *vclips, | |
| 685 | − uint32_t num_clips, | |
| 686 | − int increment, | |
| 687 | − bool to_surface, | |
| 688 | − bool interruptible, | |
| 689 | − struct drm_crtc *crtc) | |
| 542 | +int vmw_kms_stdu_readback(struct vmw_private *dev_priv, | |
| 543 | + struct drm_file *file_priv, | |
| 544 | + struct vmw_framebuffer *vfb, | |
| 545 | + struct drm_vmw_fence_rep __user *user_fence_rep, | |
| 546 | + struct drm_clip_rect *clips, | |
| 547 | + struct drm_vmw_rect *vclips, | |
| 548 | + uint32_t num_clips, | |
| 549 | + int increment, | |
| 550 | + struct drm_crtc *crtc) | |
| 690 | 551 | { |
| 691 | − struct vmw_buffer_object *buf = | |
| 552 | + struct vmw_bo *buf = | |
| 692 | 553 | container_of(vfb, struct vmw_framebuffer_bo, base)->buffer; |
| 693 | 554 | struct vmw_stdu_dirty ddirty; |
| 694 | 555 | int ret; |
| 695 | − bool cpu_blit = vmw_stdu_use_cpu_blit(dev_priv); | |
| 696 | 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 | |
| 700 | − * we'll be using a CPU blit, and the framebuffer should be moved out | |
| 701 | − * of VRAM. | |
| 559 | + * The GMR domain might seem confusing because it might seem like it should | |
| 560 | + * never happen with screen targets but e.g. the xorg vmware driver issues | |
| 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 | 569 | if (ret) |
| 705 | 570 | return ret; |
| 706 | 571 | |
| 707 | − ret = vmw_validation_prepare(&val_ctx, NULL, interruptible); | |
| 572 | + ret = vmw_validation_prepare(&val_ctx, NULL, true); | |
| 708 | 573 | if (ret) |
| 709 | 574 | goto out_unref; |
| 710 | 575 | |
| 711 | − ddirty.transfer = (to_surface) ? SVGA3D_WRITE_HOST_VRAM : | |
| 712 | − SVGA3D_READ_HOST_VRAM; | |
| 713 | 576 | ddirty.left = ddirty.top = S32_MAX; |
| 714 | 577 | ddirty.right = ddirty.bottom = S32_MIN; |
| 715 | 578 | ddirty.fb_left = ddirty.fb_top = S32_MAX; |
| 716 | 579 | ddirty.pitch = vfb->base.pitches[0]; |
| 717 | 580 | ddirty.buf = buf; |
| 718 | − ddirty.base.fifo_commit = vmw_stdu_bo_fifo_commit; | |
| 719 | − ddirty.base.clip = vmw_stdu_bo_clip; | |
| 720 | − ddirty.base.fifo_reserve_size = sizeof(struct vmw_stdu_dma) + | |
| 721 | − num_clips * sizeof(SVGA3dCopyBox) + | |
| 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 | − } | |
| 581 | + | |
| 582 | + ddirty.base.fifo_commit = vmw_stdu_bo_cpu_commit; | |
| 583 | + ddirty.base.clip = vmw_stdu_bo_cpu_clip; | |
| 584 | + ddirty.base.fifo_reserve_size = 0; | |
| 732 | 585 | |
| 733 | 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 | 1014 | * This should only happen if the buffer object is too large to create a |
| 1162 | 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 && | |
| 1167 | − vmw_stdu_use_cpu_blit(dev_priv)) | |
| 1017 | + if (vps->content_fb_type == SEPARATE_BO) | |
| 1168 | 1018 | vps->cpp = new_fb->pitches[0] / new_fb->width; |
| 1169 | 1019 | |
| 1170 | 1020 | return 0; |
| @@ -1174,14 +1024,6 @@ out_srf_unref: · 3 unmodified lines | ||
| 1174 | 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 | 1027 | static uint32_t vmw_stdu_bo_fifo_size_cpu(struct vmw_du_update_plane *update, |
| 1186 | 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 | 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 | 1034 | static uint32_t vmw_stdu_bo_pre_clip_cpu(struct vmw_du_update_plane *update, |
| 1255 | 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 | 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 | 1084 | dst_pitch = stdu->display_srf->metadata.base_size.width * stdu->cpp; |
| 1305 | 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 | 1088 | src_pitch = update->vfb->base.pitches[0]; |
| 1309 | 1089 | src_offset = bo_update->fb_top * src_pitch + bo_update->fb_left * |
| 1310 | 1090 | stdu->cpp; |
| @@ -1368,24 +1148,12 @@ static int vmw_stdu_plane_update_bo(struct vmw_private *dev_priv, · 57 unmodified lines | ||
| 1368 | 1148 | bo_update.base.vfb = vfb; |
| 1369 | 1149 | bo_update.base.out_fence = out_fence; |
| 1370 | 1150 | bo_update.base.mutex = NULL; |
| 1371 | − bo_update.base.cpu_blit = vmw_stdu_use_cpu_blit(dev_priv); | |
| 1372 | 1151 | bo_update.base.intr = false; |
| 1373 | 1152 | |
| 1374 | − /* | |
| 1375 | − * VM without 3D support don't have surface DMA command and framebuffer | |
| 1376 | − * should be moved out of VRAM. | |
| 1377 | − */ | |
| 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 | − } | |
| 1153 | + bo_update.base.calc_fifo_size = vmw_stdu_bo_fifo_size_cpu; | |
| 1154 | + bo_update.base.pre_clip = vmw_stdu_bo_pre_clip_cpu; | |
| 1155 | + bo_update.base.clip = vmw_stdu_bo_clip_cpu; | |
| 1156 | + bo_update.base.post_clip = vmw_stdu_bo_populate_update_cpu; | |
| 1389 | 1157 | |
| 1390 | 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 | 1316 | srf_update.vfb = vfb; |
| 1549 | 1317 | srf_update.out_fence = out_fence; |
| 1550 | 1318 | srf_update.mutex = &dev_priv->cmdbuf_mutex; |
| 1551 | − srf_update.cpu_blit = false; | |
| 1552 | 1319 | srf_update.intr = true; |
| 1553 | 1320 | |
| 1554 | 1321 | if (vfbs->is_bo_proxy) |
| @@ -1,7 +1,7 @@ | ||
| 1 | 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 | 5 | * All Rights Reserved. |
| 6 | 6 | * |
| 7 | 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> | |
| 30 | − | |
| 29 | +#include "vmwgfx_binding.h" | |
| 30 | +#include "vmwgfx_bo.h" | |
| 31 | 31 | #include "vmwgfx_drv.h" |
| 32 | 32 | #include "vmwgfx_resource_priv.h" |
| 33 | −#include "vmwgfx_binding.h" | |
| 33 | + | |
| 34 | +#include <drm/ttm/ttm_placement.h> | |
| 34 | 35 | |
| 35 | 36 | /** |
| 36 | 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 | 64 | static const struct vmw_res_func vmw_dx_streamoutput_func = { |
| 64 | 65 | .res_type = vmw_res_streamoutput, |
| 65 | − .needs_backup = true, | |
| 66 | + .needs_guest_memory = true, | |
| 66 | 67 | .may_evict = false, |
| 67 | 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 | 71 | .create = vmw_dx_streamoutput_create, |
| 70 | 72 | .destroy = NULL, /* Command buffer managed resource. */ |
| 71 | 73 | .bind = vmw_dx_streamoutput_bind, |
| @@ -104,8 +106,8 @@ static int vmw_dx_streamoutput_unscrub(struct vmw_resource *res) · 32 unmodified lines | ||
| 104 | 106 | cmd->header.id = SVGA_3D_CMD_DX_BIND_STREAMOUTPUT; |
| 105 | 107 | cmd->header.size = sizeof(cmd->body); |
| 106 | 108 | cmd->body.soid = so->id; |
| 107 | − cmd->body.mobid = res->backup->base.resource->start; | |
| 108 | − cmd->body.offsetInBytes = res->backup_offset; | |
| 109 | + cmd->body.mobid = res->guest_memory_bo->tbo.resource->start; | |
| 110 | + cmd->body.offsetInBytes = res->guest_memory_offset; | |
| 109 | 111 | cmd->body.sizeInBytes = so->size; |
| 110 | 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 | 197 | struct vmw_fence_obj *fence; |
| 196 | 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 | 201 | return -EINVAL; |
| 200 | 202 | |
| 201 | 203 | mutex_lock(&dev_priv->binding_mutex); |
| @@ -1,7 +1,7 @@ | ||
| 1 | 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 | 6 | * Permission is hereby granted, free of charge, to any person obtaining a |
| 7 | 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> | |
| 29 | − | |
| 28 | +#include "vmwgfx_bo.h" | |
| 30 | 29 | #include "vmwgfx_drv.h" |
| 31 | 30 | #include "vmwgfx_resource_priv.h" |
| 32 | 31 | #include "vmwgfx_so.h" |
| @@ -34,6 +33,8 @@ · 1 unmodified line | ||
| 34 | 33 | #include "vmw_surface_cache.h" |
| 35 | 34 | #include "device_include/svga3d_surfacedefs.h" |
| 36 | 35 | |
| 36 | +#include <drm/ttm/ttm_placement.h> | |
| 37 | + | |
| 37 | 38 | #define SVGA3D_FLAGS_64(upper32, lower32) (((uint64_t)upper32 << 32) | lower32) |
| 38 | 39 | #define SVGA3D_FLAGS_UPPER_32(svga3d_flags) (svga3d_flags >> 32) |
| 39 | 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 | 127 | static const struct vmw_res_func vmw_legacy_surface_func = { |
| 127 | 128 | .res_type = vmw_res_surface, |
| 128 | − .needs_backup = false, | |
| 129 | + .needs_guest_memory = false, | |
| 129 | 130 | .may_evict = true, |
| 130 | 131 | .prio = 1, |
| 131 | 132 | .dirty_prio = 1, |
| 132 | 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 | 136 | .create = &vmw_legacy_srf_create, |
| 135 | 137 | .destroy = &vmw_legacy_srf_destroy, |
| 136 | 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 | 142 | static const struct vmw_res_func vmw_gb_surface_func = { |
| 141 | 143 | .res_type = vmw_res_surface, |
| 142 | − .needs_backup = true, | |
| 144 | + .needs_guest_memory = true, | |
| 143 | 145 | .may_evict = true, |
| 144 | 146 | .prio = 1, |
| 145 | 147 | .dirty_prio = 2, |
| 146 | 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 | 151 | .create = vmw_gb_surface_create, |
| 149 | 152 | .destroy = vmw_gb_surface_destroy, |
| 150 | 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 | 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 | 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 | 412 | return 0; |
| 410 | 413 | |
| 411 | 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 | 416 | dev_priv->memory_size)) |
| 414 | 417 | return -EBUSY; |
| 415 | 418 | |
| @@ -447,7 +450,7 @@ static int vmw_legacy_srf_create(struct vmw_resource *res) · 31 unmodified lines | ||
| 447 | 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 | 454 | return 0; |
| 452 | 455 | |
| 453 | 456 | out_no_fifo: |
| @@ -524,7 +527,7 @@ static int vmw_legacy_srf_dma(struct vmw_resource *res, · 70 unmodified lines | ||
| 524 | 527 | static int vmw_legacy_srf_bind(struct vmw_resource *res, |
| 525 | 528 | struct ttm_validate_buffer *val_buf) |
| 526 | 529 | { |
| 527 | − if (!res->backup_dirty) | |
| 530 | + if (!res->guest_memory_dirty) | |
| 528 | 531 | return 0; |
| 529 | 532 | |
| 530 | 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 | 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 | 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 | 686 | container_of(base, struct vmw_user_surface, prime.base); |
| 684 | 687 | struct vmw_resource *res = &user_srf->srf.res; |
| 685 | 688 | |
| 686 | − if (res && res->backup) | |
| 687 | − drm_gem_object_put(&res->backup->base.base); | |
| 689 | + if (res->guest_memory_bo) | |
| 690 | + drm_gem_object_put(&res->guest_memory_bo->tbo.base); | |
| 688 | 691 | |
| 689 | 692 | *p_base = NULL; |
| 690 | 693 | vmw_resource_unreference(&res); |
| @@ -812,7 +815,7 @@ int vmw_surface_define_ioctl(struct drm_device *dev, void *data, · 121 unmodified lines | ||
| 812 | 815 | ++cur_size; |
| 813 | 816 | } |
| 814 | 817 | } |
| 815 | − res->backup_size = cur_bo_offset; | |
| 818 | + res->guest_memory_size = cur_bo_offset; | |
| 816 | 819 | if (metadata->scanout && |
| 817 | 820 | metadata->num_sizes == 1 && |
| 818 | 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 | 860 | ret = vmw_gem_object_create_with_handle(dev_priv, |
| 858 | 861 | file_priv, |
| 859 | − res->backup_size, | |
| 862 | + res->guest_memory_size, | |
| 860 | 863 | &backup_handle, |
| 861 | − &res->backup); | |
| 864 | + &res->guest_memory_bo); | |
| 862 | 865 | if (unlikely(ret != 0)) { |
| 863 | 866 | vmw_resource_unreference(&res); |
| 864 | 867 | goto out_unlock; |
| 865 | 868 | } |
| 866 | − vmw_bo_reference(res->backup); | |
| 869 | + vmw_bo_reference(res->guest_memory_bo); | |
| 867 | 870 | /* |
| 868 | 871 | * We don't expose the handle to the userspace and surface |
| 869 | 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 | 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 | 879 | req->shareable, VMW_RES_SURFACE, |
| 877 | 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 | 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 | 1194 | cmd1 = VMW_CMD_RESERVE(dev_priv, submit_size); |
| 1192 | 1195 | if (unlikely(!cmd1)) |
| @@ -1196,7 +1199,7 @@ static int vmw_gb_surface_bind(struct vmw_resource *res, · 3 unmodified lines | ||
| 1196 | 1199 | cmd1->header.size = sizeof(cmd1->body); |
| 1197 | 1200 | cmd1->body.sid = res->id; |
| 1198 | 1201 | cmd1->body.mobid = bo->resource->start; |
| 1199 | − if (res->backup_dirty) { | |
| 1202 | + if (res->guest_memory_dirty) { | |
| 1200 | 1203 | cmd2 = (void *) &cmd1[1]; |
| 1201 | 1204 | cmd2->header.id = SVGA_3D_CMD_UPDATE_GB_SURFACE; |
| 1202 | 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 | 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 | 1211 | /* We've just made a full upload. Cear dirty regions. */ |
| 1209 | 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 | 1217 | return 0; |
| 1215 | 1218 | } |
| @@ -1505,11 +1508,11 @@ vmw_gb_surface_define_internal(struct drm_device *dev, · 289 unmodified lines | ||
| 1505 | 1508 | |
| 1506 | 1509 | if (req->base.buffer_handle != SVGA3D_INVALID_ID) { |
| 1507 | 1510 | ret = vmw_user_bo_lookup(file_priv, req->base.buffer_handle, |
| 1508 | − &res->backup); | |
| 1511 | + &res->guest_memory_bo); | |
| 1509 | 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 | 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 | 1516 | ret = -EINVAL; |
| 1514 | 1517 | goto out_unlock; |
| 1515 | 1518 | } else { |
| @@ -1520,11 +1523,11 @@ vmw_gb_surface_define_internal(struct drm_device *dev, · 4 unmodified lines | ||
| 1520 | 1523 | (drm_vmw_surface_flag_create_buffer | |
| 1521 | 1524 | drm_vmw_surface_flag_coherent)) { |
| 1522 | 1525 | ret = vmw_gem_object_create_with_handle(dev_priv, file_priv, |
| 1523 | − res->backup_size, | |
| 1526 | + res->guest_memory_size, | |
| 1524 | 1527 | &backup_handle, |
| 1525 | − &res->backup); | |
| 1528 | + &res->guest_memory_bo); | |
| 1526 | 1529 | if (ret == 0) |
| 1527 | − vmw_bo_reference(res->backup); | |
| 1530 | + vmw_bo_reference(res->guest_memory_bo); | |
| 1528 | 1531 | } |
| 1529 | 1532 | |
| 1530 | 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 | 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 | 1542 | if (!res->func->dirty_alloc) |
| 1540 | 1543 | ret = -EINVAL; |
| 1541 | 1544 | if (!ret) |
| @@ -1544,7 +1547,7 @@ vmw_gb_surface_define_internal(struct drm_device *dev, · 2 unmodified lines | ||
| 1544 | 1547 | res->coherent = true; |
| 1545 | 1548 | ret = res->func->dirty_alloc(res); |
| 1546 | 1549 | } |
| 1547 | − ttm_bo_unreserve(&backup->base); | |
| 1550 | + ttm_bo_unreserve(&backup->tbo); | |
| 1548 | 1551 | if (ret) { |
| 1549 | 1552 | vmw_resource_unreference(&res); |
| 1550 | 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 | 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 | 1560 | req->base.drm_surface_flags & |
| 1558 | 1561 | drm_vmw_surface_flag_shareable, |
| 1559 | 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 | 1571 | rep->handle = user_srf->prime.base.handle; |
| 1569 | − rep->backup_size = res->backup_size; | |
| 1570 | − if (res->backup) { | |
| 1572 | + rep->backup_size = res->guest_memory_size; | |
| 1573 | + if (res->guest_memory_bo) { | |
| 1571 | 1574 | rep->buffer_map_handle = |
| 1572 | − drm_vma_node_offset_addr(&res->backup->base.base.vma_node); | |
| 1573 | − rep->buffer_size = res->backup->base.base.size; | |
| 1575 | + drm_vma_node_offset_addr(&res->guest_memory_bo->tbo.base.vma_node); | |
| 1576 | + rep->buffer_size = res->guest_memory_bo->tbo.base.size; | |
| 1574 | 1577 | rep->buffer_handle = backup_handle; |
| 1575 | 1578 | } else { |
| 1576 | 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 | 1617 | user_srf = container_of(base, struct vmw_user_surface, prime.base); |
| 1615 | 1618 | srf = &user_srf->srf; |
| 1616 | − if (!srf->res.backup) { | |
| 1619 | + if (!srf->res.guest_memory_bo) { | |
| 1617 | 1620 | DRM_ERROR("Shared GB surface is missing a backup buffer.\n"); |
| 1618 | 1621 | goto out_bad_resource; |
| 1619 | 1622 | } |
| 1620 | 1623 | metadata = &srf->metadata; |
| 1621 | 1624 | |
| 1622 | 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 | 1627 | &backup_handle); |
| 1625 | 1628 | mutex_unlock(&dev_priv->cmdbuf_mutex); |
| 1626 | 1629 | if (ret != 0) { |
| @@ -1639,11 +1642,11 @@ vmw_gb_surface_reference_internal(struct drm_device *dev, · 12 unmodified lines | ||
| 1639 | 1642 | rep->creq.base.buffer_handle = backup_handle; |
| 1640 | 1643 | rep->creq.base.base_size = metadata->base_size; |
| 1641 | 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 | 1646 | rep->crep.buffer_handle = backup_handle; |
| 1644 | 1647 | rep->crep.buffer_map_handle = |
| 1645 | − drm_vma_node_offset_addr(&srf->res.backup->base.base.vma_node); | |
| 1646 | − rep->crep.buffer_size = srf->res.backup->base.base.size; | |
| 1648 | + drm_vma_node_offset_addr(&srf->res.guest_memory_bo->tbo.base.vma_node); | |
| 1649 | + rep->crep.buffer_size = srf->res.guest_memory_bo->tbo.base.size; | |
| 1647 | 1650 | |
| 1648 | 1651 | rep->creq.version = drm_vmw_gb_surface_v1; |
| 1649 | 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 | 1746 | struct vmw_surface_dirty *dirty = |
| 1744 | 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 | 1749 | struct vmw_surface_loc loc1, loc2; |
| 1747 | 1750 | const struct vmw_surface_cache *cache; |
| 1748 | 1751 | |
| 1749 | − start = max_t(size_t, start, res->backup_offset) - res->backup_offset; | |
| 1750 | − end = min(end, backup_end) - res->backup_offset; | |
| 1752 | + start = max_t(size_t, start, res->guest_memory_offset) - res->guest_memory_offset; | |
| 1753 | + end = min(end, backup_end) - res->guest_memory_offset; | |
| 1751 | 1754 | cache = &dirty->cache; |
| 1752 | 1755 | vmw_surface_get_loc(cache, &loc1, start); |
| 1753 | 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 | 1797 | struct vmw_surface_dirty *dirty = |
| 1795 | 1798 | (struct vmw_surface_dirty *) res->dirty; |
| 1796 | 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 | 1801 | SVGA3dBox *box = &dirty->boxes[0]; |
| 1799 | 1802 | u32 box_c2; |
| 1800 | 1803 | |
| 1801 | 1804 | box->h = box->d = 1; |
| 1802 | − start = max_t(size_t, start, res->backup_offset) - res->backup_offset; | |
| 1803 | − end = min(end, backup_end) - res->backup_offset; | |
| 1805 | + start = max_t(size_t, start, res->guest_memory_offset) - res->guest_memory_offset; | |
| 1806 | + end = min(end, backup_end) - res->guest_memory_offset; | |
| 1804 | 1807 | box_c2 = box->x + box->w; |
| 1805 | 1808 | if (box->w == 0 || box->x > start) |
| 1806 | 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 | 1820 | struct vmw_surface *srf = vmw_res_to_srf(res); |
| 1818 | 1821 | |
| 1819 | − if (WARN_ON(end <= res->backup_offset || | |
| 1820 | − start >= res->backup_offset + res->backup_size)) | |
| 1822 | + if (WARN_ON(end <= res->guest_memory_offset || | |
| 1823 | + start >= res->guest_memory_offset + res->guest_memory_size)) | |
| 1821 | 1824 | return; |
| 1822 | 1825 | |
| 1823 | 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 | 2077 | if (metadata->flags & SVGA3D_SURFACE_MULTISAMPLE) |
| 2075 | 2078 | sample_count = metadata->multisample_count; |
| 2076 | 2079 | |
| 2077 | − srf->res.backup_size = | |
| 2080 | + srf->res.guest_memory_size = | |
| 2078 | 2081 | vmw_surface_get_serialized_size_extended( |
| 2079 | 2082 | metadata->format, |
| 2080 | 2083 | metadata->base_size, |
| @@ -2083,7 +2086,7 @@ int vmw_gb_surface_define(struct vmw_private *dev_priv, · 2 unmodified lines | ||
| 2083 | 2086 | sample_count); |
| 2084 | 2087 | |
| 2085 | 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 | 2092 | * Don't set SVGA3D_SURFACE_SCREENTARGET flag for a scanout surface with |
| @@ -1,7 +1,7 @@ | ||
| 1 | 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 | 6 | * Permission is hereby granted, free of charge, to any person obtaining a |
| 7 | 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 | 29 | #include "vmwgfx_drv.h" |
| 29 | 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 | 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 | 53 | struct ttm_placement vmw_vram_placement = { |
| 60 | 54 | .num_placement = 1, |
| 61 | 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 | 74 | struct ttm_placement vmw_vram_gmr_placement = { |
| 102 | 75 | .num_placement = 2, |
| 103 | 76 | .placement = vram_gmr_placement_flags, |
| @@ -105,13 +78,6 @@ struct ttm_placement vmw_vram_gmr_placement = { · 1 unmodified line | ||
| 105 | 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 | 81 | struct ttm_placement vmw_sys_placement = { |
| 116 | 82 | .num_placement = 1, |
| 117 | 83 | .placement = &sys_placement_flags, |
| @@ -119,53 +85,6 @@ struct ttm_placement vmw_sys_placement = { · 1 unmodified line | ||
| 119 | 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 | 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 | 427 | if (!vmw_be) |
| 509 | 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 | 431 | vmw_be->mob = NULL; |
| 513 | 432 | |
| 514 | 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 | 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 | 458 | switch (mem->mem_type) { |
| 540 | 459 | case TTM_PL_SYSTEM: |
| @@ -596,9 +515,13 @@ static int vmw_move(struct ttm_buffer_object *bo, · 55 unmodified lines | ||
| 596 | 515 | struct ttm_resource *new_mem, |
| 597 | 516 | struct ttm_place *hop) |
| 598 | 517 | { |
| 599 | − struct ttm_resource_manager *old_man = ttm_manager_type(bo->bdev, bo->resource->mem_type); | |
| 600 | − struct ttm_resource_manager *new_man = ttm_manager_type(bo->bdev, new_mem->mem_type); | |
| 601 | − int ret; | |
| 518 | + struct ttm_resource_manager *new_man; | |
| 519 | + struct ttm_resource_manager *old_man = NULL; | |
| 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 | 526 | if (new_man->use_tt && !vmw_memtype_is_system(new_mem->mem_type)) { |
| 604 | 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 | 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 | 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 | 541 | if (vmw_memtype_is_system(bo->resource->mem_type)) { |
| 613 | 542 | ttm_bo_move_null(bo, new_mem); |
| 614 | 543 | return 0; |
| @@ -645,34 +574,39 @@ struct ttm_device_funcs vmw_bo_driver = { · 30 unmodified lines | ||
| 645 | 574 | }; |
| 646 | 575 | |
| 647 | 576 | int vmw_bo_create_and_populate(struct vmw_private *dev_priv, |
| 648 | − unsigned long bo_size, | |
| 649 | − struct ttm_buffer_object **bo_p) | |
| 577 | + size_t bo_size, u32 domain, | |
| 578 | + struct vmw_bo **bo_p) | |
| 650 | 579 | { |
| 651 | 580 | struct ttm_operation_ctx ctx = { |
| 652 | 581 | .interruptible = false, |
| 653 | 582 | .no_wait_gpu = false |
| 654 | 583 | }; |
| 655 | − struct ttm_buffer_object *bo; | |
| 584 | + struct vmw_bo *vbo; | |
| 656 | 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, | |
| 659 | − &vmw_pt_sys_placement, | |
| 660 | − &bo); | |
| 594 | + ret = vmw_bo_create(dev_priv, &bo_params, &vbo); | |
| 661 | 595 | if (unlikely(ret != 0)) |
| 662 | 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 | 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 | 601 | if (likely(ret == 0)) { |
| 668 | 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 | 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 | 609 | if (likely(ret == 0)) |
| 676 | − *bo_p = bo; | |
| 610 | + *bo_p = vbo; | |
| 677 | 611 | return ret; |
| 678 | 612 | } |
| @@ -25,6 +25,7 @@ · 24 unmodified lines | ||
| 25 | 25 | * |
| 26 | 26 | **************************************************************************/ |
| 27 | 27 | |
| 28 | +#include "vmwgfx_bo.h" | |
| 28 | 29 | #include "vmwgfx_drv.h" |
| 29 | 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 | 81 | static const struct vmw_simple_resource_func va_stream_func = { |
| 81 | 82 | .res_func = { |
| 82 | 83 | .res_type = vmw_res_stream, |
| 83 | − .needs_backup = false, | |
| 84 | + .needs_guest_memory = false, | |
| 84 | 85 | .may_evict = false, |
| 85 | 86 | .type_name = "overlay stream", |
| 86 | − .backup_placement = NULL, | |
| 87 | + .domain = VMW_BO_DOMAIN_SYS, | |
| 88 | + .busy_domain = VMW_BO_DOMAIN_SYS, | |
| 87 | 89 | .create = NULL, |
| 88 | 90 | .destroy = NULL, |
| 89 | 91 | .bind = NULL, |
| @@ -1,7 +1,7 @@ | ||
| 1 | 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 | 5 | * All Rights Reserved. |
| 6 | 6 | * |
| 7 | 7 | * Permission is hereby granted, free of charge, to any person obtaining a |
| @@ -25,9 +25,12 @@ · 17 unmodified lines | ||
| 25 | 25 | * USE OR OTHER DEALINGS IN THE SOFTWARE. |
| 26 | 26 | * |
| 27 | 27 | **************************************************************************/ |
| 28 | −#include <linux/slab.h> | |
| 29 | −#include "vmwgfx_validation.h" | |
| 28 | +#include "vmwgfx_bo.h" | |
| 30 | 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 | 36 | #define VMWGFX_VALIDATION_MEM_GRAN (16*PAGE_SIZE) |
| @@ -38,8 +41,6 @@ · 4 unmodified lines | ||
| 38 | 41 | * @hash: A hash entry used for the duplicate detection hash table. |
| 39 | 42 | * @coherent_count: If switching backup buffers, number of new coherent |
| 40 | 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 | 45 | * Bit fields are used since these structures are allocated and freed in |
| 45 | 46 | * large numbers and space conservation is desired. |
| @@ -48,21 +49,19 @@ struct vmw_validation_bo_node { · 2 unmodified lines | ||
| 48 | 49 | struct ttm_validate_buffer base; |
| 49 | 50 | struct vmwgfx_hash_item hash; |
| 50 | 51 | unsigned int coherent_count; |
| 51 | − u32 as_mob : 1; | |
| 52 | − u32 cpu_blit : 1; | |
| 53 | 52 | }; |
| 54 | 53 | /** |
| 55 | 54 | * struct vmw_validation_res_node - Resource validation metadata. |
| 56 | 55 | * @head: List head for the resource validation list. |
| 57 | 56 | * @hash: A hash entry used for the duplicate detection hash table. |
| 58 | 57 | * @res: Reference counted resource pointer. |
| 59 | − * @new_backup: Non ref-counted pointer to new backup buffer to be assigned | |
| 60 | − * to a resource. | |
| 61 | − * @new_backup_offset: Offset into the new backup mob for resources that can | |
| 62 | − * share MOBs. | |
| 58 | + * @new_guest_memory_bo: Non ref-counted pointer to new guest memory buffer | |
| 59 | + * to be assigned to a resource. | |
| 60 | + * @new_guest_memory_offset: Offset into the new backup mob for resources | |
| 61 | + * that can share MOBs. | |
| 63 | 62 | * @no_buffer_needed: Kernel does not need to allocate a MOB during validation, |
| 64 | 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 | 65 | * @first_usage: True iff the resource has been seen only once in the current |
| 67 | 66 | * validation batch. |
| 68 | 67 | * @reserved: Whether the resource is currently reserved by this process. |
| @@ -77,10 +76,10 @@ struct vmw_validation_res_node { · 8 unmodified lines | ||
| 77 | 76 | struct list_head head; |
| 78 | 77 | struct vmwgfx_hash_item hash; |
| 79 | 78 | struct vmw_resource *res; |
| 80 | − struct vmw_buffer_object *new_backup; | |
| 81 | − unsigned long new_backup_offset; | |
| 79 | + struct vmw_bo *new_guest_memory_bo; | |
| 80 | + unsigned long new_guest_memory_offset; | |
| 82 | 81 | u32 no_buffer_needed : 1; |
| 83 | − u32 switching_backup : 1; | |
| 82 | + u32 switching_guest_memory_bo : 1; | |
| 84 | 83 | u32 first_usage : 1; |
| 85 | 84 | u32 reserved : 1; |
| 86 | 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 | 173 | static struct vmw_validation_bo_node * |
| 175 | 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 | 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 | 193 | struct vmw_validation_bo_node *entry; |
| 195 | 194 | |
| 196 | 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 | 197 | bo_node = entry; |
| 199 | 198 | break; |
| 200 | 199 | } |
| @@ -258,26 +257,16 @@ out: · 57 unmodified lines | ||
| 258 | 257 | * vmw_validation_add_bo - Add a buffer object to the validation context. |
| 259 | 258 | * @ctx: The validation context. |
| 260 | 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 | 261 | * Return: Zero on success, negative error code otherwise. |
| 265 | 262 | */ |
| 266 | 263 | int vmw_validation_add_bo(struct vmw_validation_context *ctx, |
| 267 | − struct vmw_buffer_object *vbo, | |
| 268 | − bool as_mob, | |
| 269 | − bool cpu_blit) | |
| 264 | + struct vmw_bo *vbo) | |
| 270 | 265 | { |
| 271 | 266 | struct vmw_validation_bo_node *bo_node; |
| 272 | 267 | |
| 273 | 268 | bo_node = vmw_validation_find_bo_dup(ctx, vbo); |
| 274 | − 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 { | |
| 269 | + if (!bo_node) { | |
| 281 | 270 | struct ttm_validate_buffer *val_buf; |
| 282 | 271 | |
| 283 | 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 | 279 | bo_node->hash.key); |
| 291 | 280 | } |
| 292 | 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 | 283 | if (!val_buf->bo) |
| 295 | 284 | return -ESRCH; |
| 296 | 285 | val_buf->num_shared = 0; |
| 297 | 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 | 289 | return 0; |
| @@ -406,23 +393,23 @@ void vmw_validation_res_set_dirty(struct vmw_validation_context *ctx, · 103 unmodified lines | ||
| 406 | 393 | * the resource. |
| 407 | 394 | * @vbo: The new backup buffer object MOB. This buffer object needs to have |
| 408 | 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 | 398 | void vmw_validation_res_switch_backup(struct vmw_validation_context *ctx, |
| 412 | 399 | void *val_private, |
| 413 | − struct vmw_buffer_object *vbo, | |
| 414 | − unsigned long backup_offset) | |
| 400 | + struct vmw_bo *vbo, | |
| 401 | + unsigned long guest_memory_offset) | |
| 415 | 402 | { |
| 416 | 403 | struct vmw_validation_res_node *val; |
| 417 | 404 | |
| 418 | 405 | val = container_of(val_private, typeof(*val), private); |
| 419 | 406 | |
| 420 | − val->switching_backup = 1; | |
| 407 | + val->switching_guest_memory_bo = 1; | |
| 421 | 408 | if (val->first_usage) |
| 422 | 409 | val->no_buffer_needed = 1; |
| 423 | 410 | |
| 424 | − val->new_backup = vbo; | |
| 425 | − val->new_backup_offset = backup_offset; | |
| 411 | + val->new_guest_memory_bo = vbo; | |
| 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 | 437 | goto out_unreserve; |
| 451 | 438 | |
| 452 | 439 | val->reserved = 1; |
| 453 | − if (res->backup) { | |
| 454 | − struct vmw_buffer_object *vbo = res->backup; | |
| 440 | + if (res->guest_memory_bo) { | |
| 441 | + struct vmw_bo *vbo = res->guest_memory_bo; | |
| 455 | 442 | |
| 456 | − ret = vmw_validation_add_bo | |
| 457 | − (ctx, vbo, vmw_resource_needs_backup(res), | |
| 458 | − false); | |
| 443 | + vmw_bo_placement_set(vbo, | |
| 444 | + res->func->domain, | |
| 445 | + res->func->busy_domain); | |
| 446 | + ret = vmw_validation_add_bo(ctx, vbo); | |
| 459 | 447 | if (ret) |
| 460 | 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 | 452 | res->coherent) { |
| 465 | 453 | struct vmw_validation_bo_node *bo_node = |
| 466 | 454 | vmw_validation_find_bo_dup(ctx, |
| 467 | − val->new_backup); | |
| 455 | + val->new_guest_memory_bo); | |
| 468 | 456 | |
| 469 | 457 | if (WARN_ON(!bo_node)) { |
| 470 | 458 | ret = -EINVAL; |
| @@ -507,9 +495,9 @@ void vmw_validation_res_unreserve(struct vmw_validation_context *ctx, · 36 unmodified lines | ||
| 507 | 495 | vmw_resource_unreserve(val->res, |
| 508 | 496 | val->dirty_set, |
| 509 | 497 | val->dirty, |
| 510 | − val->switching_backup, | |
| 511 | − val->new_backup, | |
| 512 | − val->new_backup_offset); | |
| 498 | + val->switching_guest_memory_bo, | |
| 499 | + val->new_guest_memory_bo, | |
| 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 | 505 | * vmw_validation_bo_validate_single - Validate a single buffer object. |
| 518 | 506 | * @bo: The TTM buffer object base. |
| 519 | 507 | * @interruptible: Whether to perform waits interruptible if possible. |
| 520 | − * @validate_as_mob: Whether to validate in MOB memory. | |
| 521 | 508 | * |
| 522 | 509 | * Return: Zero on success, -ERESTARTSYS if interrupted. Negative error |
| 523 | 510 | * code on failure. |
| 524 | 511 | */ |
| 525 | −int vmw_validation_bo_validate_single(struct ttm_buffer_object *bo, | |
| 526 | − bool interruptible, | |
| 527 | − bool validate_as_mob) | |
| 512 | +static int vmw_validation_bo_validate_single(struct ttm_buffer_object *bo, | |
| 513 | + bool interruptible) | |
| 528 | 514 | { |
| 529 | − struct vmw_buffer_object *vbo = | |
| 530 | − container_of(bo, struct vmw_buffer_object, base); | |
| 515 | + struct vmw_bo *vbo = to_vmw_bo(&bo->base); | |
| 531 | 516 | struct ttm_operation_ctx ctx = { |
| 532 | 517 | .interruptible = interruptible, |
| 533 | 518 | .no_wait_gpu = false |
| @@ -537,30 +522,20 @@ int vmw_validation_bo_validate_single(struct ttm_buffer_object *bo, · 3 unmodified lines | ||
| 537 | 522 | if (atomic_read(&vbo->cpu_writers)) |
| 538 | 523 | return -EBUSY; |
| 539 | 524 | |
| 540 | − if (vbo->base.pin_count > 0) | |
| 525 | + if (vbo->tbo.pin_count > 0) | |
| 541 | 526 | return 0; |
| 542 | 527 | |
| 543 | − if (validate_as_mob) | |
| 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); | |
| 528 | + ret = ttm_bo_validate(bo, &vbo->placement, &ctx); | |
| 554 | 529 | if (ret == 0 || ret == -ERESTARTSYS) |
| 555 | 530 | return ret; |
| 556 | 531 | |
| 557 | − /** | |
| 558 | − * If that failed, try VRAM again, this time evicting | |
| 532 | + /* | |
| 533 | + * If that failed, try again, this time evicting | |
| 559 | 534 | * previous contents. |
| 560 | 535 | */ |
| 536 | + ctx.allow_res_evict = true; | |
| 561 | 537 | |
| 562 | − ret = ttm_bo_validate(bo, &vmw_vram_placement, &ctx); | |
| 563 | − return ret; | |
| 538 | + return ttm_bo_validate(bo, &vbo->placement, &ctx); | |
| 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 | 553 | int ret; |
| 579 | 554 | |
| 580 | 555 | list_for_each_entry(entry, &ctx->bo_list, base.head) { |
| 581 | − struct vmw_buffer_object *vbo = | |
| 582 | − container_of(entry->base.bo, typeof(*vbo), base); | |
| 583 | − | |
| 584 | − if (entry->cpu_blit) { | |
| 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 | − } | |
| 556 | + struct vmw_bo *vbo = to_vmw_bo(&entry->base.bo->base); | |
| 557 | + | |
| 558 | + ret = vmw_validation_bo_validate_single(entry->base.bo, intr); | |
| 559 | + | |
| 596 | 560 | if (ret) |
| 597 | 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 | 604 | list_for_each_entry(val, &ctx->resource_list, head) { |
| 641 | 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 | 608 | ret = vmw_resource_validate(res, intr, val->dirty_set && |
| 645 | 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 | 616 | /* Check if the resource switched backup buffer */ |
| 653 | − if (backup && res->backup && (backup != res->backup)) { | |
| 654 | − struct vmw_buffer_object *vbo = res->backup; | |
| 617 | + if (backup && res->guest_memory_bo && backup != res->guest_memory_bo) { | |
| 618 | + struct vmw_bo *vbo = res->guest_memory_bo; | |
| 655 | 619 | |
| 656 | − ret = vmw_validation_add_bo | |
| 657 | − (ctx, vbo, vmw_resource_needs_backup(res), | |
| 658 | − false); | |
| 620 | + vmw_bo_placement_set(vbo, res->func->domain, | |
| 621 | + res->func->busy_domain); | |
| 622 | + ret = vmw_validation_add_bo(ctx, vbo); | |
| 659 | 623 | if (ret) |
| 660 | 624 | return ret; |
| 661 | 625 | } |
| @@ -889,9 +853,7 @@ void vmw_validation_bo_backoff(struct vmw_validation_context *ctx) · 227 unmodified lines | ||
| 889 | 853 | list_for_each_entry(entry, &ctx->bo_list, base.head) { |
| 890 | 854 | if (entry->coherent_count) { |
| 891 | 855 | unsigned int coherent_count = entry->coherent_count; |
| 892 | − struct vmw_buffer_object *vbo = | |
| 893 | − container_of(entry->base.bo, typeof(*vbo), | |
| 894 | − base); | |
| 856 | + struct vmw_bo *vbo = to_vmw_bo(&entry->base.bo->base); | |
| 895 | 857 | |
| 896 | 858 | while (coherent_count--) |
| 897 | 859 | vmw_bo_dirty_release(vbo); |
| @@ -73,7 +73,7 @@ struct vmw_validation_context { · 72 unmodified lines | ||
| 73 | 73 | size_t total_mem; |
| 74 | 74 | }; |
| 75 | 75 | |
| 76 | −struct vmw_buffer_object; | |
| 76 | +struct vmw_bo; | |
| 77 | 77 | struct vmw_resource; |
| 78 | 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 | 161 | int vmw_validation_add_bo(struct vmw_validation_context *ctx, |
| 162 | − struct vmw_buffer_object *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); | |
| 162 | + struct vmw_bo *vbo); | |
| 167 | 163 | int vmw_validation_bo_validate(struct vmw_validation_context *ctx, bool intr); |
| 168 | 164 | void vmw_validation_unref_lists(struct vmw_validation_context *ctx); |
| 169 | 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 | 175 | bool backoff); |
| 180 | 176 | void vmw_validation_res_switch_backup(struct vmw_validation_context *ctx, |
| 181 | 177 | void *val_private, |
| 182 | − struct vmw_buffer_object *vbo, | |
| 178 | + struct vmw_bo *vbo, | |
| 183 | 179 | unsigned long backup_offset); |
| 184 | 180 | int vmw_validation_res_validate(struct vmw_validation_context *ctx, bool intr); |
| 185 | 181 | |
| @@ -11,13 +11,14 @@ · 10 unmodified lines | ||
| 11 | 11 | #include <linux/delay.h> |
| 12 | 12 | #include <linux/notifier.h> |
| 13 | 13 | #include <linux/ioctl.h> |
| 14 | −#include <linux/fb.h> | |
| 15 | 14 | #include <linux/slab.h> |
| 16 | 15 | |
| 17 | 16 | #include <asm/firmware.h> |
| 18 | 17 | #include <asm/ps3av.h> |
| 19 | 18 | #include <asm/ps3.h> |
| 20 | 19 | |
| 20 | +#include <video/cmdline.h> | |
| 21 | + | |
| 21 | 22 | #include "vuart.h" |
| 22 | 23 | |
| 23 | 24 | #define BUFSIZE 4096 /* vuart buf size */ |
| @@ -921,6 +922,7 @@ EXPORT_SYMBOL_GPL(ps3av_audio_mute); · 897 unmodified lines | ||
| 921 | 922 | |
| 922 | 923 | static int ps3av_probe(struct ps3_system_bus_device *dev) |
| 923 | 924 | { |
| 925 | + const char *mode_option; | |
| 924 | 926 | int res; |
| 925 | 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 | 971 | ps3av_get_hw_conf(ps3av); |
| 970 | 972 | |
| 971 | −#ifdef CONFIG_FB | |
| 972 | − if (fb_mode_option && !strcmp(fb_mode_option, "safe")) | |
| 973 | + mode_option = video_get_options(NULL); | |
| 974 | + if (mode_option && !strcmp(mode_option, "safe")) | |
| 973 | 975 | safe_mode = 1; |
| 974 | −#endif /* CONFIG_FB */ | |
| 975 | 976 | id = ps3av_auto_videomode(&ps3av->av_hw_conf); |
| 976 | 977 | if (id < 0) { |
| 977 | 978 | printk(KERN_ERR "%s: invalid id :%d\n", __func__, id); |
| @@ -11,6 +11,9 @@ config APERTURE_HELPERS · 10 unmodified lines | ||
| 11 | 11 | Support tracking and hand-over of aperture ownership. Required |
| 12 | 12 | by graphics drivers for firmware-provided framebuffers. |
| 13 | 13 | |
| 14 | +config VIDEO_CMDLINE | |
| 15 | + bool | |
| 16 | + | |
| 14 | 17 | config VIDEO_NOMODESET |
| 15 | 18 | bool |
| 16 | 19 | default n |
| @@ -2,6 +2,7 @@ · 1 unmodified line | ||
| 2 | 2 | |
| 3 | 3 | obj-$(CONFIG_APERTURE_HELPERS) += aperture.o |
| 4 | 4 | obj-$(CONFIG_VGASTATE) += vgastate.o |
| 5 | +obj-$(CONFIG_VIDEO_CMDLINE) += cmdline.o | |
| 5 | 6 | obj-$(CONFIG_VIDEO_NOMODESET) += nomodeset.o |
| 6 | 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 | 3 | # fbdev configuration |
| 4 | 4 | # |
| 5 | 5 | |
| 6 | −config FB_CMDLINE | |
| 7 | − bool | |
| 8 | − | |
| 9 | 6 | config FB_NOTIFY |
| 10 | 7 | bool |
| 11 | 8 | |
| 12 | 9 | menuconfig FB |
| 13 | 10 | tristate "Support for frame buffer devices" |
| 14 | − select FB_CMDLINE | |
| 15 | 11 | select FB_NOTIFY |
| 12 | + select VIDEO_CMDLINE | |
| 16 | 13 | help |
| 17 | 14 | The frame buffer device provides an abstraction for the graphics |
| 18 | 15 | hardware. It represents the frame buffer of some video hardware and |
| @@ -1,9 +1,8 @@ | ||
| 1 | 1 | # SPDX-License-Identifier: GPL-2.0 |
| 2 | −obj-$(CONFIG_FB_CMDLINE) += fb_cmdline.o | |
| 3 | 2 | obj-$(CONFIG_FB_NOTIFY) += fb_notify.o |
| 4 | 3 | obj-$(CONFIG_FB) += fb.o |
| 5 | 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 | 6 | fb-$(CONFIG_FB_DEFERRED_IO) += fb_defio.o |
| 8 | 7 | |
| 9 | 8 | ifeq ($(CONFIG_FRAMEBUFFER_CONSOLE),y) |
| @@ -12,16 +12,14 @@ · 11 unmodified lines | ||
| 12 | 12 | * for more details. |
| 13 | 13 | * |
| 14 | 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; | |
| 21 | −static int ofonly __read_mostly; | |
| 18 | +#include <linux/export.h> | |
| 19 | +#include <linux/fb.h> | |
| 20 | +#include <linux/string.h> | |
| 22 | 21 | |
| 23 | −const char *fb_mode_option; | |
| 24 | −EXPORT_SYMBOL_GPL(fb_mode_option); | |
| 22 | +#include <video/cmdline.h> | |
| 25 | 23 | |
| 26 | 24 | /** |
| 27 | 25 | * fb_get_options - get kernel boot parameters |
| @@ -30,78 +28,34 @@ EXPORT_SYMBOL_GPL(fb_mode_option); · 2 unmodified lines | ||
| 30 | 28 | * (video=<name>:<options>) |
| 31 | 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 | 34 | * NOTE: Needed to maintain backwards compatibility |
| 34 | 35 | */ |
| 35 | 36 | int fb_get_options(const char *name, char **option) |
| 36 | 37 | { |
| 37 | − char *opt, *options = NULL; | |
| 38 | − int retval = 0; | |
| 39 | − int name_len = strlen(name), i; | |
| 40 | − | |
| 41 | − if (name_len && ofonly && strncmp(name, "offb", 4)) | |
| 42 | − retval = 1; | |
| 38 | + const char *options = NULL; | |
| 39 | + bool is_of = false; | |
| 40 | + bool enabled; | |
| 43 | 41 | |
| 44 | − if (name_len && !retval) { | |
| 45 | − for (i = 0; i < FB_MAX; i++) { | |
| 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); | |
| 42 | + if (name) | |
| 43 | + is_of = strncmp(name, "offb", 4); | |
| 68 | 44 | |
| 69 | −/** | |
| 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; | |
| 45 | + enabled = __video_get_options(name, &options, is_of); | |
| 83 | 46 | |
| 84 | − if (!strncmp(options, "ofonly", 6)) { | |
| 85 | − ofonly = 1; | |
| 86 | − goto out; | |
| 47 | + if (options) { | |
| 48 | + if (!strncmp(options, "off", 3)) | |
| 49 | + enabled = false; | |
| 87 | 50 | } |
| 88 | 51 | |
| 89 | − if (strchr(options, ':')) { | |
| 90 | − /* named */ | |
| 91 | − int i; | |
| 92 | − | |
| 93 | − for (i = 0; i < FB_MAX; i++) { | |
| 94 | − if (video_options[i] == NULL) { | |
| 95 | − video_options[i] = options; | |
| 96 | − break; | |
| 97 | − } | |
| 98 | − } | |
| 99 | − } else { | |
| 100 | − /* global */ | |
| 101 | − fb_mode_option = options; | |
| 52 | + if (option) { | |
| 53 | + if (options) | |
| 54 | + *option = kstrdup(options, GFP_KERNEL); | |
| 55 | + else | |
| 56 | + *option = NULL; | |
| 102 | 57 | } |
| 103 | 58 | |
| 104 | −out: | |
| 105 | − return 1; | |
| 59 | + return enabled ? 0 : 1; // 0 on success, 1 otherwise | |
| 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 | 620 | const struct fb_videomode *default_mode, |
| 621 | 621 | unsigned int default_bpp) |
| 622 | 622 | { |
| 623 | + char *mode_option_buf = NULL; | |
| 623 | 624 | int i; |
| 624 | 625 | |
| 625 | 626 | /* Set up defaults */ |
| @@ -635,8 +636,10 @@ int fb_find_mode(struct fb_var_screeninfo *var, · 9 unmodified lines | ||
| 635 | 636 | default_bpp = 8; |
| 636 | 637 | |
| 637 | 638 | /* Did the user specify a video mode? */ |
| 638 | − if (!mode_option) | |
| 639 | − mode_option = fb_mode_option; | |
| 639 | + if (!mode_option) { | |
| 640 | + fb_get_options(NULL, &mode_option_buf); | |
| 641 | + mode_option = mode_option_buf; | |
| 642 | + } | |
| 640 | 643 | if (mode_option) { |
| 641 | 644 | const char *name = mode_option; |
| 642 | 645 | unsigned int namelen = strlen(name); |
| @@ -715,6 +718,7 @@ int fb_find_mode(struct fb_var_screeninfo *var, · 72 unmodified lines | ||
| 715 | 718 | res_specified = 1; |
| 716 | 719 | } |
| 717 | 720 | done: |
| 721 | + kfree(mode_option_buf); | |
| 718 | 722 | if (cvt) { |
| 719 | 723 | struct fb_videomode cvt_mode; |
| 720 | 724 | int ret; |
| @@ -209,6 +209,32 @@ int drm_atomic_helper_page_flip_target( · 208 unmodified lines | ||
| 209 | 209 | __drm_atomic_get_current_plane_state((crtc_state)->state, \ |
| 210 | 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 | 239 | * drm_atomic_plane_disabling - check whether a plane is being disabled |
| 214 | 240 | * @old_plane_state: old atomic plane state |
| @@ -139,7 +139,11 @@ struct displayid_vesa_vendor_specific_block { · 138 unmodified lines | ||
| 139 | 139 | u8 mso; |
| 140 | 140 | } __packed; |
| 141 | 141 | |
| 142 | −/* DisplayID iteration */ | |
| 142 | +/* | |
| 143 | + * DisplayID iteration. | |
| 144 | + * | |
| 145 | + * Do not access directly, this is private. | |
| 146 | + */ | |
| 143 | 147 | struct displayid_iter { |
| 144 | 148 | const struct drm_edid *drm_edid; |
| 145 | 149 | |
| @@ -147,6 +151,9 @@ struct displayid_iter { · 1 unmodified line | ||
| 147 | 151 | int length; |
| 148 | 152 | int idx; |
| 149 | 153 | int ext_index; |
| 154 | + | |
| 155 | + u8 version; | |
| 156 | + u8 primary_use; | |
| 150 | 157 | }; |
| 151 | 158 | |
| 152 | 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 | 164 | while (((__block) = __displayid_iter_next(__iter))) |
| 158 | 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 | 170 | #endif |
| @@ -400,25 +400,6 @@ struct drm_driver { · 399 unmodified lines | ||
| 400 | 400 | int (*dumb_map_offset)(struct drm_file *file_priv, |
| 401 | 401 | struct drm_device *dev, uint32_t handle, |
| 402 | 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 | 404 | /** @major: driver major number */ |
| 424 | 405 | int major; |
| @@ -61,9 +61,15 @@ struct std_timing { · 60 unmodified lines | ||
| 61 | 61 | u8 vfreq_aspect; |
| 62 | 62 | } __attribute__((packed)); |
| 63 | 63 | |
| 64 | −#define DRM_EDID_PT_HSYNC_POSITIVE (1 << 1) | |
| 65 | −#define DRM_EDID_PT_VSYNC_POSITIVE (1 << 2) | |
| 66 | −#define DRM_EDID_PT_SEPARATE_SYNC (3 << 3) | |
| 64 | +#define DRM_EDID_PT_SYNC_MASK (3 << 3) | |
| 65 | +# define DRM_EDID_PT_ANALOG_CSYNC (0 << 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 | 73 | #define DRM_EDID_PT_STEREO (1 << 5) |
| 68 | 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 | 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 | 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 | 489 | unsigned long drm_gem_lru_scan(struct drm_gem_lru *lru, unsigned nr_to_scan, |
| 480 | 490 | bool (*shrink)(struct drm_gem_object *obj)); |
| 481 | 491 | |
| 492 | +int drm_gem_evict(struct drm_gem_object *obj); | |
| 493 | + | |
| 482 | 494 | #endif /* __DRM_GEM_H__ */ |
| @@ -60,20 +60,6 @@ struct drm_gem_shmem_object { · 59 unmodified lines | ||
| 60 | 60 | */ |
| 61 | 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 | 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 | 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 | 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 | 106 | #define to_drm_gem_shmem_obj(obj) \ |
| @@ -1331,6 +1331,32 @@ struct drm_plane_helper_funcs { · 1330 unmodified lines | ||
| 1331 | 1331 | */ |
| 1332 | 1332 | void (*atomic_update)(struct drm_plane *plane, |
| 1333 | 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 | 1361 | * @atomic_disable: |
| 1336 | 1362 | * |
| @@ -1351,7 +1377,8 @@ struct drm_plane_helper_funcs { · 14 unmodified lines | ||
| 1351 | 1377 | * the tradeoffs and variants of plane commit helpers. |
| 1352 | 1378 | * |
| 1353 | 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 | 1383 | void (*atomic_disable)(struct drm_plane *plane, |
| 1357 | 1384 | struct drm_atomic_state *state); |
| @@ -15,6 +15,8 @@ struct drm_encoder; · 14 unmodified lines | ||
| 15 | 15 | struct drm_panel; |
| 16 | 16 | struct drm_bridge; |
| 17 | 17 | struct device_node; |
| 18 | +struct mipi_dsi_device_info; | |
| 19 | +struct mipi_dsi_host; | |
| 18 | 20 | |
| 19 | 21 | /** |
| 20 | 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 | 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 | 145 | * drm_of_panel_bridge_remove - remove panel bridge |
| 134 | 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 | 48 | struct drm_gpu_scheduler; |
| 49 | 49 | struct drm_sched_rq; |
| 50 | 50 | |
| 51 | +struct drm_file; | |
| 52 | + | |
| 51 | 53 | /* These are often used as an (initial) index |
| 52 | 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 | 524 | void drm_sched_job_arm(struct drm_sched_job *job); |
| 523 | 525 | int drm_sched_job_add_dependency(struct drm_sched_job *job, |
| 524 | 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 | 531 | int drm_sched_job_add_resv_dependencies(struct drm_sched_job *job, |
| 526 | 532 | struct dma_resv *resv, |
| 527 | 533 | enum dma_resv_usage usage); |
| @@ -141,7 +141,7 @@ struct ttm_device_funcs { · 140 unmodified lines | ||
| 141 | 141 | * the graphics address space |
| 142 | 142 | * @ctx: context for this move with parameters |
| 143 | 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 | 146 | * Move a buffer between two memory regions. |
| 147 | 147 | * Returns errno -EMULTIHOP if driver requests a hop |
| @@ -765,7 +765,6 @@ struct dmt_videomode { · 764 unmodified lines | ||
| 765 | 765 | const struct fb_videomode *mode; |
| 766 | 766 | }; |
| 767 | 767 | |
| 768 | −extern const char *fb_mode_option; | |
| 769 | 768 | extern const struct fb_videomode vesa_modes[]; |
| 770 | 769 | extern const struct dmt_videomode dmt_modes[]; |
| 771 | 770 | |
| @@ -972,6 +972,19 @@ extern "C" { · 971 unmodified lines | ||
| 972 | 972 | #define DRM_IOCTL_GET_STATS DRM_IOR( 0x06, struct drm_stats) |
| 973 | 973 | #define DRM_IOCTL_SET_VERSION DRM_IOWR(0x07, struct drm_set_version) |
| 974 | 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 | 988 | #define DRM_IOCTL_GEM_CLOSE DRM_IOW (0x09, struct drm_gem_close) |
| 976 | 989 | #define DRM_IOCTL_GEM_FLINK DRM_IOWR(0x0a, struct drm_gem_flink) |
| 977 | 990 | #define DRM_IOCTL_GEM_OPEN DRM_IOWR(0x0b, struct drm_gem_open) |
| @@ -1012,7 +1025,37 @@ extern "C" { · 34 unmodified lines | ||
| 1012 | 1025 | #define DRM_IOCTL_UNLOCK DRM_IOW( 0x2b, struct drm_lock) |
| 1013 | 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 | 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 | 1059 | #define DRM_IOCTL_PRIME_FD_TO_HANDLE DRM_IOWR(0x2e, struct drm_prime_handle) |
| 1017 | 1060 | |
| 1018 | 1061 | #define DRM_IOCTL_AGP_ACQUIRE DRM_IO( 0x30) |
| @@ -1104,8 +1147,13 @@ extern "C" { · 85 unmodified lines | ||
| 1104 | 1147 | * struct as the output. |
| 1105 | 1148 | * |
| 1106 | 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 | |
| 1108 | − * zero handle -- this can be used to compute the number of planes. | |
| 1150 | + * will be filled with GEM buffer handles. Fresh new GEM handles are always | |
| 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 | 1158 | * Otherwise, &drm_mode_fb_cmd2.handles will be zeroed and planes are valid |
| 1111 | 1159 | * until one has a zero &drm_mode_fb_cmd2.pitches. |
| @@ -1113,6 +1161,11 @@ extern "C" { · 1 unmodified line | ||
| 1113 | 1161 | * If the framebuffer has a format modifier, &DRM_MODE_FB_MODIFIERS will be set |
| 1114 | 1162 | * in &drm_mode_fb_cmd2.flags and &drm_mode_fb_cmd2.modifier will contain the |
| 1115 | 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 | 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 | |