History

Merge tag 'drm-misc-next-2023-03-07' of git://anongit.freedesktop.org/drm/drm-misc into drm-next

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>

Dave Airlie committed 3 years ago

Commit faf0d832 parents eeac8ed 9228742155 files · +4430 −3332Browse files

Unified · Split

155 files
  1. Documentation/devicetree/bindings/display/bridge/analogix,dp.yaml +63 −0
  2. Documentation/devicetree/bindings/display/bridge/analogix_dp.txt +0 −51
  3. Documentation/devicetree/bindings/display/bridge/snps,dw-mipi-dsi.yaml +3 −13
  4. Documentation/devicetree/bindings/display/dsi-controller.yaml +9 −9
  5. Documentation/devicetree/bindings/display/exynos/exynos_dp.txt +1 −1
  6. Documentation/devicetree/bindings/display/panel/jadard,jd9365da-h3.yaml +2 −0
  7. Documentation/devicetree/bindings/display/panel/samsung,ams495qa01.yaml +57 −0
  8. Documentation/devicetree/bindings/display/rockchip/analogix_dp-rockchip.txt +0 −98
  9. Documentation/devicetree/bindings/display/rockchip/dw_mipi_dsi_rockchip.txt +0 −94
  10. Documentation/devicetree/bindings/display/rockchip/rockchip,analogix-dp.yaml +103 −0
  11. Documentation/devicetree/bindings/display/rockchip/rockchip,dw-mipi-dsi.yaml +166 −0
  12. Documentation/devicetree/bindings/display/rockchip/rockchip,lvds.yaml +170 −0
  13. Documentation/devicetree/bindings/display/rockchip/rockchip-lvds.txt +0 −92
  14. Documentation/devicetree/bindings/display/simple-framebuffer.yaml +9 −0
  15. Documentation/devicetree/bindings/soc/rockchip/grf.yaml +7 −3
  16. MAINTAINERS +1 −1
  17. drivers/accel/ivpu/ivpu_pm.c +0 −10
  18. drivers/dma-buf/dma-buf.c +1 −1
  19. drivers/gpu/drm/Kconfig +5 −1
  20. drivers/gpu/drm/Makefile +3 −0
  21. drivers/gpu/drm/amd/amdgpu/Kconfig +1 −0
  22. drivers/gpu/drm/amd/amdgpu/amdgpu.h +4 −22
  23. drivers/gpu/drm/amd/amdgpu/amdgpu_ib.c +2 −3
  24. drivers/gpu/drm/amd/amdgpu/amdgpu_object.c +3 −6
  25. drivers/gpu/drm/amd/amdgpu/amdgpu_object.h +15 −8
  26. drivers/gpu/drm/amd/amdgpu/amdgpu_ring.h +2 −1
  27. drivers/gpu/drm/amd/amdgpu/amdgpu_sa.c +21 −303
  28. drivers/gpu/drm/amd/amdgpu/amdgpu_ttm.c +0 −4
  29. drivers/gpu/drm/arm/malidp_drv.c +1 −1
  30. drivers/gpu/drm/ast/ast_dp.c +5 −5
  31. drivers/gpu/drm/ast/ast_dp501.c +20 −20
  32. drivers/gpu/drm/ast/ast_drv.c +1 −1
  33. drivers/gpu/drm/ast/ast_drv.h +33 −51
  34. drivers/gpu/drm/ast/ast_i2c.c +4 −4
  35. drivers/gpu/drm/ast/ast_main.c +12 −12
  36. drivers/gpu/drm/ast/ast_mm.c +2 −2
  37. drivers/gpu/drm/ast/ast_mode.c +58 −46
  38. drivers/gpu/drm/ast/ast_post.c +47 −47
  39. drivers/gpu/drm/bridge/Kconfig +1 −1
  40. drivers/gpu/drm/bridge/panel.c +2 −0
  41. drivers/gpu/drm/bridge/tc358762.c +1 −0
  42. drivers/gpu/drm/drm_atomic_helper.c +16 −4
  43. drivers/gpu/drm/drm_connector.c +20 −8
  44. drivers/gpu/drm/drm_displayid.c +53 −9
  45. drivers/gpu/drm/drm_dumb_buffers.c +1 −4
  46. drivers/gpu/drm/drm_edid.c +56 −9
  47. drivers/gpu/drm/drm_gem.c +18 −7
  48. drivers/gpu/drm/drm_gem_shmem_helper.c +36 −29
  49. drivers/gpu/drm/drm_gem_vram_helper.c +11 −0
  50. drivers/gpu/drm/drm_internal.h +0 −3
  51. drivers/gpu/drm/drm_modes.c +1 −2
  52. drivers/gpu/drm/drm_of.c +51 −0
  53. drivers/gpu/drm/drm_probe_helper.c +3 −2
  54. drivers/gpu/drm/drm_suballoc.c +457 −0
  55. drivers/gpu/drm/i915/gem/i915_gem_ttm.c +11 −4
  56. drivers/gpu/drm/i915/gem/i915_gem_ttm.h +1 −1
  57. drivers/gpu/drm/i915/gem/i915_gem_ttm_move.c +4 −0
  58. drivers/gpu/drm/i915/gem/i915_gem_ttm_pm.c +5 −2
  59. drivers/gpu/drm/meson/meson_venc.c +2 −2
  60. drivers/gpu/drm/mgag200/mgag200_drv.h +3 −0
  61. drivers/gpu/drm/mgag200/mgag200_mode.c +12 −10
  62. drivers/gpu/drm/nouveau/nouveau_bo.c +0 −3
  63. drivers/gpu/drm/nouveau/nouveau_hwmon.c +5 −5
  64. drivers/gpu/drm/nouveau/nouveau_led.h +1 −1
  65. drivers/gpu/drm/panel/Kconfig +11 −0
  66. drivers/gpu/drm/panel/Makefile +1 −0
  67. drivers/gpu/drm/panel/panel-jadard-jd9365da-h3.c +208 −1
  68. drivers/gpu/drm/panel/panel-magnachip-d53e6ea8966.c +522 −0
  69. drivers/gpu/drm/panfrost/panfrost_drv.c +2 −9
  70. drivers/gpu/drm/qxl/qxl_ttm.c +11 −0
  71. drivers/gpu/drm/radeon/Kconfig +1 −0
  72. drivers/gpu/drm/radeon/radeon.h +8 −47
  73. drivers/gpu/drm/radeon/radeon_ib.c +5 −7
  74. drivers/gpu/drm/radeon/radeon_object.h +15 −10
  75. drivers/gpu/drm/radeon/radeon_sa.c +26 −290
  76. drivers/gpu/drm/radeon/radeon_semaphore.c +2 −2
  77. drivers/gpu/drm/radeon/radeon_ttm.c +2 −5
  78. drivers/gpu/drm/rockchip/rockchip_drm_gem.c +10 −6
  79. drivers/gpu/drm/rockchip/rockchip_drm_vop.c +2 −5
  80. drivers/gpu/drm/rockchip/rockchip_drm_vop2.c +63 −17
  81. drivers/gpu/drm/rockchip/rockchip_rgb.c +10 −9
  82. drivers/gpu/drm/rockchip/rockchip_rgb.h +4 −2
  83. drivers/gpu/drm/scheduler/sched_main.c +29 −0
  84. drivers/gpu/drm/tests/drm_format_helper_test.c +5 −5
  85. drivers/gpu/drm/tidss/tidss_dispc.c +4 −8
  86. drivers/gpu/drm/tidss/tidss_dispc.h +4 −4
  87. drivers/gpu/drm/tidss/tidss_plane.c +11 −9
  88. drivers/gpu/drm/tiny/simpledrm.c +22 −9
  89. drivers/gpu/drm/ttm/ttm_bo.c +13 −17
  90. drivers/gpu/drm/ttm/ttm_bo_util.c +4 −15
  91. drivers/gpu/drm/ttm/ttm_resource.c +0 −1
  92. drivers/gpu/drm/v3d/v3d_gem.c +8 −18
  93. drivers/gpu/drm/vc4/vc4_drv.h +1 −1
  94. drivers/gpu/drm/vc4/vc4_gem.c +18 −60
  95. drivers/gpu/drm/vc4/vc4_hdmi.c +13 −33
  96. drivers/gpu/drm/vc4/vc4_hdmi.h +0 −1
  97. drivers/gpu/drm/vc4/vc4_validate.c +2 −2
  98. drivers/gpu/drm/vgem/vgem_fence.c +1 −0
  99. drivers/gpu/drm/virtio/Kconfig +11 −0
  100. drivers/gpu/drm/virtio/virtgpu_display.c +6 −0
  101. drivers/gpu/drm/virtio/virtgpu_drv.c +4 −0
  102. drivers/gpu/drm/virtio/virtgpu_kms.c +23 −16
  103. drivers/gpu/drm/virtio/virtgpu_vq.c +1 −2
  104. drivers/gpu/drm/vmwgfx/Makefile +1 −1
  105. drivers/gpu/drm/vmwgfx/vmwgfx_bo.c +196 −211
  106. drivers/gpu/drm/vmwgfx/vmwgfx_bo.h +203 −0
  107. drivers/gpu/drm/vmwgfx/vmwgfx_cmd.c +7 −7
  108. drivers/gpu/drm/vmwgfx/vmwgfx_cmdbuf.c +20 −33
  109. drivers/gpu/drm/vmwgfx/vmwgfx_context.c +20 −16
  110. drivers/gpu/drm/vmwgfx/vmwgfx_cotable.c +38 −27
  111. drivers/gpu/drm/vmwgfx/vmwgfx_drv.c +16 −10
  112. drivers/gpu/drm/vmwgfx/vmwgfx_drv.h +48 −197
  113. drivers/gpu/drm/vmwgfx/vmwgfx_execbuf.c +58 −47
  114. drivers/gpu/drm/vmwgfx/vmwgfx_fence.c +1 −1
  115. drivers/gpu/drm/vmwgfx/vmwgfx_gem.c +36 −55
  116. drivers/gpu/drm/vmwgfx/vmwgfx_kms.c +77 −155
  117. drivers/gpu/drm/vmwgfx/vmwgfx_kms.h +18 −25
  118. drivers/gpu/drm/vmwgfx/vmwgfx_ldu.c +49 −8
  119. drivers/gpu/drm/vmwgfx/vmwgfx_mob.c +24 −21
  120. drivers/gpu/drm/vmwgfx/vmwgfx_overlay.c +11 −11
  121. drivers/gpu/drm/vmwgfx/vmwgfx_page_dirty.c +33 −35
  122. drivers/gpu/drm/vmwgfx/vmwgfx_resource.c +128 −118
  123. drivers/gpu/drm/vmwgfx/vmwgfx_resource_priv.h +6 −4
  124. drivers/gpu/drm/vmwgfx/vmwgfx_scrn.c +28 −25
  125. drivers/gpu/drm/vmwgfx/vmwgfx_shader.c +38 −29
  126. drivers/gpu/drm/vmwgfx/vmwgfx_so.c +4 −2
  127. drivers/gpu/drm/vmwgfx/vmwgfx_stdu.c +45 −278
  128. drivers/gpu/drm/vmwgfx/vmwgfx_streamoutput.c +11 −9
  129. drivers/gpu/drm/vmwgfx/vmwgfx_surface.c +55 −52
  130. drivers/gpu/drm/vmwgfx/vmwgfx_ttm_buffer.c +34 −100
  131. drivers/gpu/drm/vmwgfx/vmwgfx_va.c +4 −2
  132. drivers/gpu/drm/vmwgfx/vmwgfx_validation.c +56 −94
  133. drivers/gpu/drm/vmwgfx/vmwgfx_validation.h +3 −7
  134. drivers/ps3/ps3av.c +5 −4
  135. drivers/video/Kconfig +3 −0
  136. drivers/video/Makefile +1 −0
  137. drivers/video/cmdline.c +133 −0
  138. drivers/video/fbdev/Kconfig +1 −4
  139. drivers/video/fbdev/core/Makefile +1 −2
  140. drivers/video/fbdev/core/fb_cmdline.c +24 −70
  141. drivers/video/fbdev/core/modedb.c +6 −2
  142. include/drm/drm_atomic_helper.h +26 −0
  143. include/drm/drm_displayid.h +11 −1
  144. include/drm/drm_drv.h +0 −19
  145. include/drm/drm_edid.h +9 −3
  146. include/drm/drm_gem.h +12 −0
  147. include/drm/drm_gem_shmem_helper.h +15 −15
  148. include/drm/drm_modeset_helper_vtables.h +28 −1
  149. include/drm/drm_of.h +12 −0
  150. include/drm/drm_suballoc.h +108 −0
  151. include/drm/gpu_scheduler.h +6 −0
  152. include/drm/ttm/ttm_device.h +1 −1
  153. include/linux/fb.h +0 −1
  154. include/uapi/drm/drm.h +55 −2
  155. include/video/cmdline.h +20 −0
Documentation/devicetree/bindings/display/bridge/analogix,dp.yaml+63−0
@@ -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
7title: Analogix Display Port bridge
8
9maintainers:
10 - Rob Herring <robh@kernel.org>
11
12properties:
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
56required:
57 - reg
58 - interrupts
59 - clock-names
60 - clocks
61 - ports
62
63additionalProperties: true
Documentation/devicetree/bindings/display/bridge/analogix_dp.txt+0−51
@@ -1,51 +0,0 @@
1Analogix Display Port bridge bindings
2
3Required 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
23Optional 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
39Example:
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 };
Documentation/devicetree/bindings/display/bridge/snps,dw-mipi-dsi.yaml+3−13
@@ -26,19 +26,9 @@ properties: · 25 unmodified lines
26 reg:26 reg:
27 maxItems: 127 maxItems: 1
28 28
29 clocks:29 clocks: true
30 items:30
31 - description: Module clock31 clock-names: true
32 - description: DSI bus clock for either AHB and APB
33 - description: Pixel clock for the DPI/RGB input
34 minItems: 2
35
36 clock-names:
37 items:
38 - const: ref
39 - const: pclk
40 - const: px_clk
41 minItems: 2
42 32
43 resets:33 resets:
44 maxItems: 134 maxItems: 1
Documentation/devicetree/bindings/display/dsi-controller.yaml+9−9
@@ -30,6 +30,15 @@ properties: · 29 unmodified lines
30 $nodename:30 $nodename:
31 pattern: "^dsi(@.*)?$"31 pattern: "^dsi(@.*)?$"
32 32
33 clock-master:
34 type: boolean
35 description:
36 Should be enabled if the host is being used in conjunction with
37 another DSI host to drive the same peripheral. Hardware supporting
38 such a configuration generally requires the data on both the busses
39 to be driven by the same clock. Only the DSI host instance
40 controlling this clock should contain this property.
41
33 "#address-cells":42 "#address-cells":
34 const: 143 const: 1
35 44
@@ -52,15 +61,6 @@ patternProperties: · 16 unmodified lines
52 case the reg property can take multiple entries, one for each virtual61 case the reg property can take multiple entries, one for each virtual
53 channel that the peripheral responds to.62 channel that the peripheral responds to.
54 63
55 clock-master:
56 type: boolean
57 description:
58 Should be enabled if the host is being used in conjunction with
59 another DSI host to drive the same peripheral. Hardware supporting
60 such a configuration generally requires the data on both the busses
61 to be driven by the same clock. Only the DSI host instance
62 controlling this clock should contain this property.
63
64 enforce-video-mode:64 enforce-video-mode:
65 type: boolean65 type: boolean
66 description:66 description:
Documentation/devicetree/bindings/display/exynos/exynos_dp.txt+1−1
@@ -50,7 +50,7 @@ Optional properties for dp-controller: · 49 unmodified lines
50 Documentation/devicetree/bindings/display/panel/display-timing.txt50 Documentation/devicetree/bindings/display/panel/display-timing.txt
51 51
52For the below properties, please refer to Analogix DP binding document:52For the below properties, please refer to Analogix DP binding document:
53 * Documentation/devicetree/bindings/display/bridge/analogix_dp.txt53 * Documentation/devicetree/bindings/display/bridge/analogix,dp.yaml
54 -phys (required)54 -phys (required)
55 -phy-names (required)55 -phy-names (required)
56 -hpd-gpios (optional)56 -hpd-gpios (optional)
Documentation/devicetree/bindings/display/panel/jadard,jd9365da-h3.yaml+2−0
@@ -17,6 +17,8 @@ properties: · 16 unmodified lines
17 items:17 items:
18 - enum:18 - enum:
19 - chongzhou,cz101b400119 - chongzhou,cz101b4001
20 - radxa,display-10hd-ad001
21 - radxa,display-8hd-ad002
20 - const: jadard,jd9365da-h322 - const: jadard,jd9365da-h3
21 23
22 reg: true24 reg: true
Documentation/devicetree/bindings/display/panel/samsung,ams495qa01.yaml+57−0
@@ -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
7title: Samsung AMS495QA01 panel with Magnachip D53E6EA8966 controller
8
9maintainers:
10 - Chris Morgan <macromorgan@hotmail.com>
11
12allOf:
13 - $ref: panel-common.yaml#
14
15properties:
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
29required:
30 - compatible
31 - reg
32 - reset-gpios
33 - vdd-supply
34
35additionalProperties: false
36
37examples:
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...
Documentation/devicetree/bindings/display/rockchip/analogix_dp-rockchip.txt+0−98
@@ -1,98 +0,0 @@
1Rockchip RK3288 specific extensions to the Analogix Display Port
2================================
3
4Required 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
31Optional 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
37For 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
45Example:
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 };
Documentation/devicetree/bindings/display/rockchip/dw_mipi_dsi_rockchip.txt+0−94
@@ -1,94 +0,0 @@
1Rockchip specific extensions to the Synopsys Designware MIPI DSI
2================================
3
4Required 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
24Optional 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
36Example:
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 };
Documentation/devicetree/bindings/display/rockchip/rockchip,analogix-dp.yaml+103−0
@@ -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
7title: Rockchip specific extensions to the Analogix Display Port
8
9maintainers:
10 - Sandy Huang <hjc@rock-chips.com>
11 - Heiko Stuebner <heiko@sntech.de>
12
13properties:
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
44required:
45 - compatible
46 - clocks
47 - clock-names
48 - resets
49 - reset-names
50 - rockchip,grf
51
52allOf:
53 - $ref: /schemas/display/bridge/analogix,dp.yaml#
54
55unevaluatedProperties: false
56
57examples:
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 };
Documentation/devicetree/bindings/display/rockchip/rockchip,dw-mipi-dsi.yaml+166−0
@@ -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
7title: Rockchip specific extensions to the Synopsys Designware MIPI DSI
8
9maintainers:
10 - Sandy Huang <hjc@rock-chips.com>
11 - Heiko Stuebner <heiko@sntech.de>
12
13properties:
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
65required:
66 - compatible
67 - clocks
68 - clock-names
69 - rockchip,grf
70
71allOf:
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
121unevaluatedProperties: false
122
123examples:
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 };
Documentation/devicetree/bindings/display/rockchip/rockchip,lvds.yaml+170−0
@@ -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
7title: Rockchip low-voltage differential signal (LVDS) transmitter
8
9maintainers:
10 - Sandy Huang <hjc@rock-chips.com>
11 - Heiko Stuebner <heiko@sntech.de>
12
13properties:
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
79required:
80 - compatible
81 - rockchip,grf
82 - rockchip,output
83 - ports
84
85allOf:
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
124additionalProperties: false
125
126examples:
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 };
Documentation/devicetree/bindings/display/rockchip/rockchip-lvds.txt+0−92
@@ -1,92 +0,0 @@
1Rockchip RK3288 LVDS interface
2================================
3
4Required 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
25Optional properties:
26- pinctrl-names: must contain a "lcdc" entry.
27- pinctrl-0: pin control group to be used for this controller.
28
29Required nodes:
30
31The lvds has two video ports as described by
32 Documentation/devicetree/bindings/media/video-interfaces.txt
33Their 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
39Example:
40
41lvds_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
53For 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 };
Documentation/devicetree/bindings/display/simple-framebuffer.yaml+9−0
@@ -26,6 +26,11 @@ description: |+ · 25 unmodified lines
26 over control to a driver for the real hardware. The bindings for the26 over control to a driver for the real hardware. The bindings for the
27 hw nodes must specify which node is considered the primary node.27 hw nodes must specify which node is considered the primary node.
28 28
29 If a panel node is given, then the driver uses this to configure the
30 physical width and height of the display. If no panel node is given,
31 then the driver uses the width and height properties of the simplefb
32 node to estimate it.
33
29 It is advised to add display# aliases to help the OS determine how34 It is advised to add display# aliases to help the OS determine how
30 to number things. If display# aliases are used, then if the simplefb35 to number things. If display# aliases are used, then if the simplefb
31 node contains a display property then the /aliases/display# path36 node contains a display property then the /aliases/display# path
@@ -117,6 +122,10 @@ properties: · 85 unmodified lines
117 $ref: /schemas/types.yaml#/definitions/phandle122 $ref: /schemas/types.yaml#/definitions/phandle
118 description: Primary display hardware node123 description: Primary display hardware node
119 124
125 panel:
126 $ref: /schemas/types.yaml#/definitions/phandle
127 description: Display panel node
128
120 allwinner,pipeline:129 allwinner,pipeline:
121 description: Pipeline used by the framebuffer on Allwinner SoCs130 description: Pipeline used by the framebuffer on Allwinner SoCs
122 enum:131 enum:
Documentation/devicetree/bindings/soc/rockchip/grf.yaml+7−3
@@ -80,13 +80,17 @@ allOf: · 79 unmodified lines
80 properties:80 properties:
81 compatible:81 compatible:
82 contains:82 contains:
83 const: rockchip,px30-grf83 enum:
84 - rockchip,px30-grf
84 85
85 then:86 then:
86 properties:87 properties:
87 lvds:88 lvds:
88 description:89 type: object
89 Documentation/devicetree/bindings/display/rockchip/rockchip-lvds.txt90
91 $ref: /schemas/display/rockchip/rockchip,lvds.yaml#
92
93 unevaluatedProperties: false
90 94
91 - if:95 - if:
92 properties:96 properties:
MAINTAINERS+1−1
@@ -7044,7 +7044,7 @@ F: Documentation/devicetree/bindings/display/xlnx/ · 7043 unmodified lines
7044F: drivers/gpu/drm/xlnx/7044F: drivers/gpu/drm/xlnx/
7045 7045
7046DRM PANEL DRIVERS7046DRM PANEL DRIVERS
7047M: Thierry Reding <thierry.reding@gmail.com>7047M: Neil Armstrong <neil.armstrong@linaro.org>
7048R: Sam Ravnborg <sam@ravnborg.org>7048R: Sam Ravnborg <sam@ravnborg.org>
7049L: dri-devel@lists.freedesktop.org7049L: dri-devel@lists.freedesktop.org
7050S: Maintained7050S: Maintained
drivers/accel/ivpu/ivpu_pm.c+0−10
@@ -237,8 +237,6 @@ int ivpu_rpm_get(struct ivpu_device *vdev) · 236 unmodified lines
237{237{
238 int ret;238 int ret;
239 239
240 ivpu_dbg(vdev, RPM, "rpm_get count %d\n", atomic_read(&vdev->drm.dev->power.usage_count));
241
242 ret = pm_runtime_resume_and_get(vdev->drm.dev);240 ret = pm_runtime_resume_and_get(vdev->drm.dev);
243 if (!drm_WARN_ON(&vdev->drm, ret < 0))241 if (!drm_WARN_ON(&vdev->drm, ret < 0))
244 vdev->pm->suspend_reschedule_counter = PM_RESCHEDULE_LIMIT;242 vdev->pm->suspend_reschedule_counter = PM_RESCHEDULE_LIMIT;
@@ -248,8 +246,6 @@ int ivpu_rpm_get(struct ivpu_device *vdev) · 3 unmodified lines
248 246
249void ivpu_rpm_put(struct ivpu_device *vdev)247void ivpu_rpm_put(struct ivpu_device *vdev)
250{248{
251 ivpu_dbg(vdev, RPM, "rpm_put count %d\n", atomic_read(&vdev->drm.dev->power.usage_count));
252
253 pm_runtime_mark_last_busy(vdev->drm.dev);249 pm_runtime_mark_last_busy(vdev->drm.dev);
254 pm_runtime_put_autosuspend(vdev->drm.dev);250 pm_runtime_put_autosuspend(vdev->drm.dev);
255}251}
@@ -314,16 +310,10 @@ void ivpu_pm_enable(struct ivpu_device *vdev) · 58 unmodified lines
314 pm_runtime_allow(dev);310 pm_runtime_allow(dev);
315 pm_runtime_mark_last_busy(dev);311 pm_runtime_mark_last_busy(dev);
316 pm_runtime_put_autosuspend(dev);312 pm_runtime_put_autosuspend(dev);
317
318 ivpu_dbg(vdev, RPM, "Enable RPM count %d\n", atomic_read(&dev->power.usage_count));
319}313}
320 314
321void ivpu_pm_disable(struct ivpu_device *vdev)315void ivpu_pm_disable(struct ivpu_device *vdev)
322{316{
323 struct device *dev = vdev->drm.dev;
324
325 ivpu_dbg(vdev, RPM, "Disable RPM count %d\n", atomic_read(&dev->power.usage_count));
326
327 pm_runtime_get_noresume(vdev->drm.dev);317 pm_runtime_get_noresume(vdev->drm.dev);
328 pm_runtime_forbid(vdev->drm.dev);318 pm_runtime_forbid(vdev->drm.dev);
329}319}
drivers/dma-buf/dma-buf.c+1−1
@@ -828,7 +828,7 @@ static struct sg_table * __map_dma_buf(struct dma_buf_attachment *attach, · 827 unmodified lines
828 * - dma_buf_attach()828 * - dma_buf_attach()
829 * - dma_buf_dynamic_attach()829 * - dma_buf_dynamic_attach()
830 * - dma_buf_detach()830 * - dma_buf_detach()
831 * - dma_buf_export(831 * - dma_buf_export()
832 * - dma_buf_fd()832 * - dma_buf_fd()
833 * - dma_buf_get()833 * - dma_buf_get()
834 * - dma_buf_put()834 * - dma_buf_put()
drivers/gpu/drm/Kconfig+5−1
@@ -10,13 +10,13 @@ menuconfig DRM · 9 unmodified lines
10 depends on (AGP || AGP=n) && !EMULATED_CMPXCHG && HAS_DMA10 depends on (AGP || AGP=n) && !EMULATED_CMPXCHG && HAS_DMA
11 select DRM_PANEL_ORIENTATION_QUIRKS11 select DRM_PANEL_ORIENTATION_QUIRKS
12 select HDMI12 select HDMI
13 select FB_CMDLINE
14 select I2C13 select I2C
15 select DMA_SHARED_BUFFER14 select DMA_SHARED_BUFFER
16 select SYNC_FILE15 select SYNC_FILE
17# gallium uses SYS_kcmp for os_same_file_description() to de-duplicate16# gallium uses SYS_kcmp for os_same_file_description() to de-duplicate
18# device and dmabuf fd. Let's make sure that is available for our userspace.17# device and dmabuf fd. Let's make sure that is available for our userspace.
19 select KCMP18 select KCMP
19 select VIDEO_CMDLINE
20 select VIDEO_NOMODESET20 select VIDEO_NOMODESET
21 help21 help
22 Kernel-level support for the Direct Rendering Infrastructure (DRI)22 Kernel-level support for the Direct Rendering Infrastructure (DRI)
@@ -232,6 +232,10 @@ config DRM_GEM_SHMEM_HELPER · 209 unmodified lines
232 help232 help
233 Choose this if you need the GEM shmem helper functions233 Choose this if you need the GEM shmem helper functions
234 234
235config DRM_SUBALLOC_HELPER
236 tristate
237 depends on DRM
238
235config DRM_SCHED239config DRM_SCHED
236 tristate240 tristate
237 depends on DRM241 depends on DRM
drivers/gpu/drm/Makefile+3−0
@@ -88,6 +88,9 @@ obj-$(CONFIG_DRM_GEM_DMA_HELPER) += drm_dma_helper.o · 87 unmodified lines
88drm_shmem_helper-y := drm_gem_shmem_helper.o88drm_shmem_helper-y := drm_gem_shmem_helper.o
89obj-$(CONFIG_DRM_GEM_SHMEM_HELPER) += drm_shmem_helper.o89obj-$(CONFIG_DRM_GEM_SHMEM_HELPER) += drm_shmem_helper.o
90 90
91drm_suballoc_helper-y := drm_suballoc.o
92obj-$(CONFIG_DRM_SUBALLOC_HELPER) += drm_suballoc_helper.o
93
91drm_vram_helper-y := drm_gem_vram_helper.o94drm_vram_helper-y := drm_gem_vram_helper.o
92obj-$(CONFIG_DRM_VRAM_HELPER) += drm_vram_helper.o95obj-$(CONFIG_DRM_VRAM_HELPER) += drm_vram_helper.o
93 96
drivers/gpu/drm/amd/amdgpu/Kconfig+1−0
@@ -19,6 +19,7 @@ config DRM_AMDGPU · 18 unmodified lines
19 select BACKLIGHT_CLASS_DEVICE19 select BACKLIGHT_CLASS_DEVICE
20 select INTERVAL_TREE20 select INTERVAL_TREE
21 select DRM_BUDDY21 select DRM_BUDDY
22 select DRM_SUBALLOC_HELPER
22 # amdgpu depends on ACPI_VIDEO when ACPI is enabled, for select to work23 # amdgpu depends on ACPI_VIDEO when ACPI is enabled, for select to work
23 # ACPI_VIDEO's dependencies must also be selected.24 # ACPI_VIDEO's dependencies must also be selected.
24 select INPUT if ACPI25 select INPUT if ACPI
drivers/gpu/drm/amd/amdgpu/amdgpu.h+4−22
@@ -424,29 +424,11 @@ struct amdgpu_clock { · 423 unmodified lines
424 * alignment).424 * alignment).
425 */425 */
426 426
427#define AMDGPU_SA_NUM_FENCE_LISTS 32
428
429struct amdgpu_sa_manager {427struct amdgpu_sa_manager {
430 wait_queue_head_t wq;428 struct drm_suballoc_manager base;
431 struct amdgpu_bo *bo;429 struct amdgpu_bo *bo;
432 struct list_head *hole;430 uint64_t gpu_addr;
433 struct list_head flist[AMDGPU_SA_NUM_FENCE_LISTS];431 void *cpu_ptr;
434 struct list_head olist;
435 unsigned size;
436 uint64_t gpu_addr;
437 void *cpu_ptr;
438 uint32_t domain;
439 uint32_t align;
440};
441
442/* sub-allocation buffer */
443struct amdgpu_sa_bo {
444 struct list_head olist;
445 struct list_head flist;
446 struct amdgpu_sa_manager *manager;
447 unsigned soffset;
448 unsigned eoffset;
449 struct dma_fence *fence;
450};432};
451 433
452int amdgpu_fence_slab_init(void);434int amdgpu_fence_slab_init(void);
drivers/gpu/drm/amd/amdgpu/amdgpu_ib.c+2−3
@@ -69,7 +69,7 @@ int amdgpu_ib_get(struct amdgpu_device *adev, struct amdgpu_vm *vm, · 68 unmodified lines
69 69
70 if (size) {70 if (size) {
71 r = amdgpu_sa_bo_new(&adev->ib_pools[pool_type],71 r = amdgpu_sa_bo_new(&adev->ib_pools[pool_type],
72 &ib->sa_bo, size, 256);72 &ib->sa_bo, size);
73 if (r) {73 if (r) {
74 dev_err(adev->dev, "failed to get a new IB (%d)\n", r);74 dev_err(adev->dev, "failed to get a new IB (%d)\n", r);
75 return r;75 return r;
@@ -309,8 +309,7 @@ int amdgpu_ib_pool_init(struct amdgpu_device *adev) · 233 unmodified lines
309 309
310 for (i = 0; i < AMDGPU_IB_POOL_MAX; i++) {310 for (i = 0; i < AMDGPU_IB_POOL_MAX; i++) {
311 r = amdgpu_sa_bo_manager_init(adev, &adev->ib_pools[i],311 r = amdgpu_sa_bo_manager_init(adev, &adev->ib_pools[i],
312 AMDGPU_IB_POOL_SIZE,312 AMDGPU_IB_POOL_SIZE, 256,
313 AMDGPU_GPU_PAGE_SIZE,
314 AMDGPU_GEM_DOMAIN_GTT);313 AMDGPU_GEM_DOMAIN_GTT);
315 if (r)314 if (r)
316 goto error;315 goto error;
drivers/gpu/drm/amd/amdgpu/amdgpu_object.c+3−6
@@ -600,7 +600,7 @@ int amdgpu_bo_create(struct amdgpu_device *adev, · 599 unmodified lines
600 600
601 if (!amdgpu_gmc_vram_full_visible(&adev->gmc) &&601 if (!amdgpu_gmc_vram_full_visible(&adev->gmc) &&
602 bo->tbo.resource->mem_type == TTM_PL_VRAM &&602 bo->tbo.resource->mem_type == TTM_PL_VRAM &&
603 bo->tbo.resource->start < adev->gmc.visible_vram_size >> PAGE_SHIFT)603 amdgpu_bo_in_cpu_visible_vram(bo))
604 amdgpu_cs_report_moved_bytes(adev, ctx.bytes_moved,604 amdgpu_cs_report_moved_bytes(adev, ctx.bytes_moved,
605 ctx.bytes_moved);605 ctx.bytes_moved);
606 else606 else
@@ -1346,7 +1346,6 @@ vm_fault_t amdgpu_bo_fault_reserve_notify(struct ttm_buffer_object *bo) · 739 unmodified lines
1346 struct amdgpu_device *adev = amdgpu_ttm_adev(bo->bdev);1346 struct amdgpu_device *adev = amdgpu_ttm_adev(bo->bdev);
1347 struct ttm_operation_ctx ctx = { false, false };1347 struct ttm_operation_ctx ctx = { false, false };
1348 struct amdgpu_bo *abo = ttm_to_amdgpu_bo(bo);1348 struct amdgpu_bo *abo = ttm_to_amdgpu_bo(bo);
1349 unsigned long offset;
1350 int r;1349 int r;
1351 1350
1352 /* Remember that this BO was accessed by the CPU */1351 /* Remember that this BO was accessed by the CPU */
@@ -1355,8 +1354,7 @@ vm_fault_t amdgpu_bo_fault_reserve_notify(struct ttm_buffer_object *bo) · 2 unmodified lines
1355 if (bo->resource->mem_type != TTM_PL_VRAM)1354 if (bo->resource->mem_type != TTM_PL_VRAM)
1356 return 0;1355 return 0;
1357 1356
1358 offset = bo->resource->start << PAGE_SHIFT;1357 if (amdgpu_bo_in_cpu_visible_vram(abo))
1359 if ((offset + bo->base.size) <= adev->gmc.visible_vram_size)
1360 return 0;1358 return 0;
1361 1359
1362 /* Can't move a pinned BO to visible VRAM */1360 /* Can't move a pinned BO to visible VRAM */
@@ -1378,10 +1376,9 @@ vm_fault_t amdgpu_bo_fault_reserve_notify(struct ttm_buffer_object *bo) · 15 unmodified lines
1378 else if (unlikely(r))1376 else if (unlikely(r))
1379 return VM_FAULT_SIGBUS;1377 return VM_FAULT_SIGBUS;
1380 1378
1381 offset = bo->resource->start << PAGE_SHIFT;
1382 /* this should never happen */1379 /* this should never happen */
1383 if (bo->resource->mem_type == TTM_PL_VRAM &&1380 if (bo->resource->mem_type == TTM_PL_VRAM &&
1384 (offset + bo->base.size) > adev->gmc.visible_vram_size)1381 !amdgpu_bo_in_cpu_visible_vram(abo))
1385 return VM_FAULT_SIGBUS;1382 return VM_FAULT_SIGBUS;
1386 1383
1387 ttm_bo_move_to_lru_tail_unlocked(bo);1384 ttm_bo_move_to_lru_tail_unlocked(bo);
drivers/gpu/drm/amd/amdgpu/amdgpu_object.h+15−8
@@ -336,15 +336,22 @@ uint32_t amdgpu_bo_get_preferred_domain(struct amdgpu_device *adev, · 335 unmodified lines
336/*336/*
337 * sub allocation337 * sub allocation
338 */338 */
339static inline struct amdgpu_sa_manager *
340to_amdgpu_sa_manager(struct drm_suballoc_manager *manager)
341{
342 return container_of(manager, struct amdgpu_sa_manager, base);
343}
339 344
340static inline uint64_t amdgpu_sa_bo_gpu_addr(struct amdgpu_sa_bo *sa_bo)345static 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
345static inline void * amdgpu_sa_bo_cpu_addr(struct amdgpu_sa_bo *sa_bo)351static 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
350int amdgpu_sa_bo_manager_init(struct amdgpu_device *adev,357int 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
355int amdgpu_sa_bo_manager_start(struct amdgpu_device *adev,362int amdgpu_sa_bo_manager_start(struct amdgpu_device *adev,
356 struct amdgpu_sa_manager *sa_manager);363 struct amdgpu_sa_manager *sa_manager);
357int amdgpu_sa_bo_new(struct amdgpu_sa_manager *sa_manager,364int amdgpu_sa_bo_new(struct amdgpu_sa_manager *sa_manager,
358 struct amdgpu_sa_bo **sa_bo,365 struct drm_suballoc **sa_bo,
359 unsigned size, unsigned align);366 unsigned int size);
360void amdgpu_sa_bo_free(struct amdgpu_device *adev,367void amdgpu_sa_bo_free(struct amdgpu_device *adev,
361 struct amdgpu_sa_bo **sa_bo,368 struct drm_suballoc **sa_bo,
362 struct dma_fence *fence);369 struct dma_fence *fence);
363#if defined(CONFIG_DEBUG_FS)370#if defined(CONFIG_DEBUG_FS)
364void amdgpu_sa_bo_dump_debug_info(struct amdgpu_sa_manager *sa_manager,371void amdgpu_sa_bo_dump_debug_info(struct amdgpu_sa_manager *sa_manager,
365 struct seq_file *m);372 struct seq_file *m);
drivers/gpu/drm/amd/amdgpu/amdgpu_ring.h+2−1
@@ -27,6 +27,7 @@ · 26 unmodified lines
27#include <drm/amdgpu_drm.h>27#include <drm/amdgpu_drm.h>
28#include <drm/gpu_scheduler.h>28#include <drm/gpu_scheduler.h>
29#include <drm/drm_print.h>29#include <drm/drm_print.h>
30#include <drm/drm_suballoc.h>
30 31
31struct amdgpu_device;32struct amdgpu_device;
32struct amdgpu_ring;33struct amdgpu_ring;
@@ -92,7 +93,7 @@ enum amdgpu_ib_pool_type { · 59 unmodified lines
92};93};
93 94
94struct amdgpu_ib {95struct amdgpu_ib {
95 struct amdgpu_sa_bo *sa_bo;96 struct drm_suballoc *sa_bo;
96 uint32_t length_dw;97 uint32_t length_dw;
97 uint64_t gpu_addr;98 uint64_t gpu_addr;
98 uint32_t *ptr;99 uint32_t *ptr;
drivers/gpu/drm/amd/amdgpu/amdgpu_sa.c+21−303
@@ -44,327 +44,63 @@ · 43 unmodified lines
44 44
45#include "amdgpu.h"45#include "amdgpu.h"
46 46
47static void amdgpu_sa_bo_remove_locked(struct amdgpu_sa_bo *sa_bo);
48static void amdgpu_sa_bo_try_free(struct amdgpu_sa_manager *sa_manager);
49
50int amdgpu_sa_bo_manager_init(struct amdgpu_device *adev,47int amdgpu_sa_bo_manager_init(struct amdgpu_device *adev,
51 struct amdgpu_sa_manager *sa_manager,48 struct amdgpu_sa_manager *sa_manager,
52 unsigned size, u32 align, u32 domain)49 unsigned int size, u32 suballoc_align, u32 domain)
53{50{
54 int i, r;51 int r;
55
56 init_waitqueue_head(&sa_manager->wq);
57 sa_manager->bo = NULL;
58 sa_manager->size = size;
59 sa_manager->domain = domain;
60 sa_manager->align = align;
61 sa_manager->hole = &sa_manager->olist;
62 INIT_LIST_HEAD(&sa_manager->olist);
63 for (i = 0; i < AMDGPU_SA_NUM_FENCE_LISTS; ++i)
64 INIT_LIST_HEAD(&sa_manager->flist[i]);
65 52
66 r = amdgpu_bo_create_kernel(adev, size, align, domain, &sa_manager->bo,53 r = amdgpu_bo_create_kernel(adev, size, AMDGPU_GPU_PAGE_SIZE, domain,
67 &sa_manager->gpu_addr, &sa_manager->cpu_ptr);54 &sa_manager->bo, &sa_manager->gpu_addr,
55 &sa_manager->cpu_ptr);
68 if (r) {56 if (r) {
69 dev_err(adev->dev, "(%d) failed to allocate bo for manager\n", r);57 dev_err(adev->dev, "(%d) failed to allocate bo for manager\n", r);
70 return r;58 return r;
71 }59 }
72 60
73 memset(sa_manager->cpu_ptr, 0, sa_manager->size);61 memset(sa_manager->cpu_ptr, 0, size);
62 drm_suballoc_manager_init(&sa_manager->base, size, suballoc_align);
74 return r;63 return r;
75}64}
76 65
77void amdgpu_sa_bo_manager_fini(struct amdgpu_device *adev,66void amdgpu_sa_bo_manager_fini(struct amdgpu_device *adev,
78 struct amdgpu_sa_manager *sa_manager)67 struct amdgpu_sa_manager *sa_manager)
79{68{
80 struct amdgpu_sa_bo *sa_bo, *tmp;
81
82 if (sa_manager->bo == NULL) {69 if (sa_manager->bo == NULL) {
83 dev_err(adev->dev, "no bo for sa manager\n");70 dev_err(adev->dev, "no bo for sa manager\n");
84 return;71 return;
85 }72 }
86 73
87 if (!list_empty(&sa_manager->olist)) {74 drm_suballoc_manager_fini(&sa_manager->base);
88 sa_manager->hole = &sa_manager->olist,
89 amdgpu_sa_bo_try_free(sa_manager);
90 if (!list_empty(&sa_manager->olist)) {
91 dev_err(adev->dev, "sa_manager is not empty, clearing anyway\n");
92 }
93 }
94 list_for_each_entry_safe(sa_bo, tmp, &sa_manager->olist, olist) {
95 amdgpu_sa_bo_remove_locked(sa_bo);
96 }
97 75
98 amdgpu_bo_free_kernel(&sa_manager->bo, &sa_manager->gpu_addr, &sa_manager->cpu_ptr);76 amdgpu_bo_free_kernel(&sa_manager->bo, &sa_manager->gpu_addr, &sa_manager->cpu_ptr);
99 sa_manager->size = 0;
100}77}
101 78
102static void amdgpu_sa_bo_remove_locked(struct amdgpu_sa_bo *sa_bo)79int amdgpu_sa_bo_new(struct amdgpu_sa_manager *sa_manager,
103{80 struct drm_suballoc **sa_bo,
104 struct amdgpu_sa_manager *sa_manager = sa_bo->manager;81 unsigned int size)
105 if (sa_manager->hole == &sa_bo->olist) {
106 sa_manager->hole = sa_bo->olist.prev;
107 }
108 list_del_init(&sa_bo->olist);
109 list_del_init(&sa_bo->flist);
110 dma_fence_put(sa_bo->fence);
111 kfree(sa_bo);
112}
113
114static void amdgpu_sa_bo_try_free(struct amdgpu_sa_manager *sa_manager)
115{82{
116 struct amdgpu_sa_bo *sa_bo, *tmp;83 struct drm_suballoc *sa = drm_suballoc_new(&sa_manager->base, size,
84 GFP_KERNEL, true, 0);
117 85
118 if (sa_manager->hole->next == &sa_manager->olist)86 if (IS_ERR(sa)) {
119 return;87 *sa_bo = NULL;
120 88
121 sa_bo = list_entry(sa_manager->hole->next, struct amdgpu_sa_bo, olist);89 return PTR_ERR(sa);
122 list_for_each_entry_safe_from(sa_bo, tmp, &sa_manager->olist, olist) {
123 if (sa_bo->fence == NULL ||
124 !dma_fence_is_signaled(sa_bo->fence)) {
125 return;
126 }
127 amdgpu_sa_bo_remove_locked(sa_bo);
128 }90 }
129}
130 91
131static inline unsigned amdgpu_sa_bo_hole_soffset(struct amdgpu_sa_manager *sa_manager)92 *sa_bo = sa;
132{
133 struct list_head *hole = sa_manager->hole;
134
135 if (hole != &sa_manager->olist) {
136 return list_entry(hole, struct amdgpu_sa_bo, olist)->eoffset;
137 }
138 return 0;93 return 0;
139}94}
140 95
141static inline unsigned amdgpu_sa_bo_hole_eoffset(struct amdgpu_sa_manager *sa_manager)96void amdgpu_sa_bo_free(struct amdgpu_device *adev, struct drm_suballoc **sa_bo,
142{
143 struct list_head *hole = sa_manager->hole;
144
145 if (hole->next != &sa_manager->olist) {
146 return list_entry(hole->next, struct amdgpu_sa_bo, olist)->soffset;
147 }
148 return sa_manager->size;
149}
150
151static 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 */
185static 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
206static 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
275int 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
346void amdgpu_sa_bo_free(struct amdgpu_device *adev, struct amdgpu_sa_bo **sa_bo,
347 struct dma_fence *fence)97 struct dma_fence *fence)
348{98{
349 struct amdgpu_sa_manager *sa_manager;
350
351 if (sa_bo == NULL || *sa_bo == NULL) {99 if (sa_bo == NULL || *sa_bo == NULL) {
352 return;100 return;
353 }101 }
354 102
355 sa_manager = (*sa_bo)->manager;103 drm_suballoc_free(*sa_bo, fence);
356 spin_lock(&sa_manager->wq.lock);
357 if (fence && !dma_fence_is_signaled(fence)) {
358 uint32_t idx;
359
360 (*sa_bo)->fence = dma_fence_get(fence);
361 idx = fence->context % AMDGPU_SA_NUM_FENCE_LISTS;
362 list_add_tail(&(*sa_bo)->flist, &sa_manager->flist[idx]);
363 } else {
364 amdgpu_sa_bo_remove_locked(*sa_bo);
365 }
366 wake_up_all_locked(&sa_manager->wq);
367 spin_unlock(&sa_manager->wq.lock);
368 *sa_bo = NULL;104 *sa_bo = NULL;
369}105}
370 106
@@ -373,26 +109,8 @@ void amdgpu_sa_bo_free(struct amdgpu_device *adev, struct amdgpu_sa_bo **sa_bo, · 2 unmodified lines
373void amdgpu_sa_bo_dump_debug_info(struct amdgpu_sa_manager *sa_manager,109void amdgpu_sa_bo_dump_debug_info(struct amdgpu_sa_manager *sa_manager,
374 struct seq_file *m)110 struct seq_file *m)
375{111{
376 struct amdgpu_sa_bo *i;112 struct drm_printer p = drm_seq_file_printer(m);
377
378 spin_lock(&sa_manager->wq.lock);
379 list_for_each_entry(i, &sa_manager->olist, olist) {
380 uint64_t soffset = i->soffset + sa_manager->gpu_addr;
381 uint64_t eoffset = i->eoffset + sa_manager->gpu_addr;
382 if (&i->olist == sa_manager->hole) {
383 seq_printf(m, ">");
384 } else {
385 seq_printf(m, " ");
386 }
387 seq_printf(m, "[0x%010llx 0x%010llx] size %8lld",
388 soffset, eoffset, eoffset - soffset);
389 113
390 if (i->fence)114 drm_suballoc_dump_debug_info(&sa_manager->base, &p, sa_manager->gpu_addr);
391 seq_printf(m, " protected by 0x%016llx on context %llu",
392 i->fence->seqno, i->fence->context);
393
394 seq_printf(m, "\n");
395 }
396 spin_unlock(&sa_manager->wq.lock);
397}115}
398#endif116#endif
drivers/gpu/drm/amd/amdgpu/amdgpu_ttm.c+0−4
@@ -466,11 +466,7 @@ static int amdgpu_bo_move(struct ttm_buffer_object *bo, bool evict, · 465 unmodified lines
466 return r;466 return r;
467 }467 }
468 468
469 /* Can't move a pinned BO */
470 abo = ttm_to_amdgpu_bo(bo);469 abo = ttm_to_amdgpu_bo(bo);
471 if (WARN_ON_ONCE(abo->tbo.pin_count > 0))
472 return -EINVAL;
473
474 adev = amdgpu_ttm_adev(bo->bdev);470 adev = amdgpu_ttm_adev(bo->bdev);
475 471
476 if (!old_mem || (old_mem->mem_type == TTM_PL_SYSTEM &&472 if (!old_mem || (old_mem->mem_type == TTM_PL_SYSTEM &&
drivers/gpu/drm/arm/malidp_drv.c+1−1
@@ -649,7 +649,7 @@ static ssize_t core_id_show(struct device *dev, struct device_attribute *attr, · 648 unmodified lines
649 struct drm_device *drm = dev_get_drvdata(dev);649 struct drm_device *drm = dev_get_drvdata(dev);
650 struct malidp_drm *malidp = drm_to_malidp(drm);650 struct malidp_drm *malidp = drm_to_malidp(drm);
651 651
652 return snprintf(buf, PAGE_SIZE, "%08x\n", malidp->core_id);652 return sysfs_emit(buf, "%08x\n", malidp->core_id);
653}653}
654 654
655static DEVICE_ATTR_RO(core_id);655static DEVICE_ATTR_RO(core_id);
drivers/gpu/drm/ast/ast_dp.c+5−5
@@ -9,7 +9,7 @@ · 8 unmodified lines
9 9
10int ast_astdp_read_edid(struct drm_device *dev, u8 *ediddata)10int ast_astdp_read_edid(struct drm_device *dev, u8 *ediddata)
11{11{
12 struct ast_private *ast = to_ast_private(dev);12 struct ast_device *ast = to_ast_device(dev);
13 u8 i = 0, j = 0;13 u8 i = 0, j = 0;
14 14
15 /*15 /*
@@ -125,7 +125,7 @@ void ast_dp_launch(struct drm_device *dev, u8 bPower) · 109 unmodified lines
125 u8 bDPTX = 0;125 u8 bDPTX = 0;
126 u8 bDPExecute = 1;126 u8 bDPExecute = 1;
127 127
128 struct ast_private *ast = to_ast_private(dev);128 struct ast_device *ast = to_ast_device(dev);
129 // S3 come back, need more time to wait BMC ready.129 // S3 come back, need more time to wait BMC ready.
130 if (bPower)130 if (bPower)
131 WaitCount = 300;131 WaitCount = 300;
@@ -172,7 +172,7 @@ void ast_dp_launch(struct drm_device *dev, u8 bPower) · 40 unmodified lines
172 172
173void ast_dp_power_on_off(struct drm_device *dev, bool on)173void ast_dp_power_on_off(struct drm_device *dev, bool on)
174{174{
175 struct ast_private *ast = to_ast_private(dev);175 struct ast_device *ast = to_ast_device(dev);
176 // Read and Turn off DP PHY sleep176 // Read and Turn off DP PHY sleep
177 u8 bE3 = ast_get_index_reg_mask(ast, AST_IO_CRTC_PORT, 0xE3, AST_DP_VIDEO_ENABLE);177 u8 bE3 = ast_get_index_reg_mask(ast, AST_IO_CRTC_PORT, 0xE3, AST_DP_VIDEO_ENABLE);
178 178
@@ -188,7 +188,7 @@ void ast_dp_power_on_off(struct drm_device *dev, bool on) · 9 unmodified lines
188 188
189void ast_dp_set_on_off(struct drm_device *dev, bool on)189void ast_dp_set_on_off(struct drm_device *dev, bool on)
190{190{
191 struct ast_private *ast = to_ast_private(dev);191 struct ast_device *ast = to_ast_device(dev);
192 u8 video_on_off = on;192 u8 video_on_off = on;
193 193
194 // Video On/Off194 // Video On/Off
@@ -208,7 +208,7 @@ void ast_dp_set_on_off(struct drm_device *dev, bool on) · 13 unmodified lines
208 208
209void ast_dp_set_mode(struct drm_crtc *crtc, struct ast_vbios_mode_info *vbios_mode)209void ast_dp_set_mode(struct drm_crtc *crtc, struct ast_vbios_mode_info *vbios_mode)
210{210{
211 struct ast_private *ast = to_ast_private(crtc->dev);211 struct ast_device *ast = to_ast_device(crtc->dev);
212 212
213 u32 ulRefreshRateIndex;213 u32 ulRefreshRateIndex;
214 u8 ModeIdx;214 u8 ModeIdx;
drivers/gpu/drm/ast/ast_dp501.c+20−20
@@ -10,7 +10,7 @@ MODULE_FIRMWARE("ast_dp501_fw.bin"); · 9 unmodified lines
10 10
11static void ast_release_firmware(void *data)11static void ast_release_firmware(void *data)
12{12{
13 struct ast_private *ast = data;13 struct ast_device *ast = data;
14 14
15 release_firmware(ast->dp501_fw);15 release_firmware(ast->dp501_fw);
16 ast->dp501_fw = NULL;16 ast->dp501_fw = NULL;
@@ -18,7 +18,7 @@ static void ast_release_firmware(void *data) · 1 unmodified line
18 18
19static int ast_load_dp501_microcode(struct drm_device *dev)19static int ast_load_dp501_microcode(struct drm_device *dev)
20{20{
21 struct ast_private *ast = to_ast_private(dev);21 struct ast_device *ast = to_ast_device(dev);
22 int ret;22 int ret;
23 23
24 ret = request_firmware(&ast->dp501_fw, "ast_dp501_fw.bin", dev->dev);24 ret = request_firmware(&ast->dp501_fw, "ast_dp501_fw.bin", dev->dev);
@@ -28,7 +28,7 @@ static int ast_load_dp501_microcode(struct drm_device *dev) · 3 unmodified lines
28 return devm_add_action_or_reset(dev->dev, ast_release_firmware, ast);28 return devm_add_action_or_reset(dev->dev, ast_release_firmware, ast);
29}29}
30 30
31static void send_ack(struct ast_private *ast)31static void send_ack(struct ast_device *ast)
32{32{
33 u8 sendack;33 u8 sendack;
34 sendack = ast_get_index_reg_mask(ast, AST_IO_CRTC_PORT, 0x9b, 0xff);34 sendack = ast_get_index_reg_mask(ast, AST_IO_CRTC_PORT, 0x9b, 0xff);
@@ -36,7 +36,7 @@ static void send_ack(struct ast_private *ast) · 1 unmodified line
36 ast_set_index_reg_mask(ast, AST_IO_CRTC_PORT, 0x9b, 0x00, sendack);36 ast_set_index_reg_mask(ast, AST_IO_CRTC_PORT, 0x9b, 0x00, sendack);
37}37}
38 38
39static void send_nack(struct ast_private *ast)39static void send_nack(struct ast_device *ast)
40{40{
41 u8 sendack;41 u8 sendack;
42 sendack = ast_get_index_reg_mask(ast, AST_IO_CRTC_PORT, 0x9b, 0xff);42 sendack = ast_get_index_reg_mask(ast, AST_IO_CRTC_PORT, 0x9b, 0xff);
@@ -44,7 +44,7 @@ static void send_nack(struct ast_private *ast) · 1 unmodified line
44 ast_set_index_reg_mask(ast, AST_IO_CRTC_PORT, 0x9b, 0x00, sendack);44 ast_set_index_reg_mask(ast, AST_IO_CRTC_PORT, 0x9b, 0x00, sendack);
45}45}
46 46
47static bool wait_ack(struct ast_private *ast)47static bool wait_ack(struct ast_device *ast)
48{48{
49 u8 waitack;49 u8 waitack;
50 u32 retry = 0;50 u32 retry = 0;
@@ -60,7 +60,7 @@ static bool wait_ack(struct ast_private *ast) · 9 unmodified lines
60 return false;60 return false;
61}61}
62 62
63static bool wait_nack(struct ast_private *ast)63static bool wait_nack(struct ast_device *ast)
64{64{
65 u8 waitack;65 u8 waitack;
66 u32 retry = 0;66 u32 retry = 0;
@@ -76,18 +76,18 @@ static bool wait_nack(struct ast_private *ast) · 9 unmodified lines
76 return false;76 return false;
77}77}
78 78
79static void set_cmd_trigger(struct ast_private *ast)79static void set_cmd_trigger(struct ast_device *ast)
80{80{
81 ast_set_index_reg_mask(ast, AST_IO_CRTC_PORT, 0x9b, ~0x40, 0x40);81 ast_set_index_reg_mask(ast, AST_IO_CRTC_PORT, 0x9b, ~0x40, 0x40);
82}82}
83 83
84static void clear_cmd_trigger(struct ast_private *ast)84static void clear_cmd_trigger(struct ast_device *ast)
85{85{
86 ast_set_index_reg_mask(ast, AST_IO_CRTC_PORT, 0x9b, ~0x40, 0x00);86 ast_set_index_reg_mask(ast, AST_IO_CRTC_PORT, 0x9b, ~0x40, 0x00);
87}87}
88 88
89#if 089#if 0
90static bool wait_fw_ready(struct ast_private *ast)90static bool wait_fw_ready(struct ast_device *ast)
91{91{
92 u8 waitready;92 u8 waitready;
93 u32 retry = 0;93 u32 retry = 0;
@@ -106,7 +106,7 @@ static bool wait_fw_ready(struct ast_private *ast) · 12 unmodified lines
106 106
107static bool ast_write_cmd(struct drm_device *dev, u8 data)107static bool ast_write_cmd(struct drm_device *dev, u8 data)
108{108{
109 struct ast_private *ast = to_ast_private(dev);109 struct ast_device *ast = to_ast_device(dev);
110 int retry = 0;110 int retry = 0;
111 if (wait_nack(ast)) {111 if (wait_nack(ast)) {
112 send_nack(ast);112 send_nack(ast);
@@ -128,7 +128,7 @@ static bool ast_write_cmd(struct drm_device *dev, u8 data) · 15 unmodified lines
128 128
129static bool ast_write_data(struct drm_device *dev, u8 data)129static bool ast_write_data(struct drm_device *dev, u8 data)
130{130{
131 struct ast_private *ast = to_ast_private(dev);131 struct ast_device *ast = to_ast_device(dev);
132 132
133 if (wait_nack(ast)) {133 if (wait_nack(ast)) {
134 send_nack(ast);134 send_nack(ast);
@@ -146,7 +146,7 @@ static bool ast_write_data(struct drm_device *dev, u8 data) · 11 unmodified lines
146#if 0146#if 0
147static bool ast_read_data(struct drm_device *dev, u8 *data)147static bool ast_read_data(struct drm_device *dev, u8 *data)
148{148{
149 struct ast_private *ast = to_ast_private(dev);149 struct ast_device *ast = to_ast_device(dev);
150 u8 tmp;150 u8 tmp;
151 151
152 *data = 0;152 *data = 0;
@@ -163,7 +163,7 @@ static bool ast_read_data(struct drm_device *dev, u8 *data) · 10 unmodified lines
163 return true;163 return true;
164}164}
165 165
166static void clear_cmd(struct ast_private *ast)166static void clear_cmd(struct ast_device *ast)
167{167{
168 send_nack(ast);168 send_nack(ast);
169 ast_set_index_reg_mask(ast, AST_IO_CRTC_PORT, 0x9a, 0x00, 0x00);169 ast_set_index_reg_mask(ast, AST_IO_CRTC_PORT, 0x9a, 0x00, 0x00);
@@ -178,14 +178,14 @@ void ast_set_dp501_video_output(struct drm_device *dev, u8 mode) · 8 unmodified lines
178 msleep(10);178 msleep(10);
179}179}
180 180
181static u32 get_fw_base(struct ast_private *ast)181static u32 get_fw_base(struct ast_device *ast)
182{182{
183 return ast_mindwm(ast, 0x1e6e2104) & 0x7fffffff;183 return ast_mindwm(ast, 0x1e6e2104) & 0x7fffffff;
184}184}
185 185
186bool ast_backup_fw(struct drm_device *dev, u8 *addr, u32 size)186bool ast_backup_fw(struct drm_device *dev, u8 *addr, u32 size)
187{187{
188 struct ast_private *ast = to_ast_private(dev);188 struct ast_device *ast = to_ast_device(dev);
189 u32 i, data;189 u32 i, data;
190 u32 boot_address;190 u32 boot_address;
191 191
@@ -204,7 +204,7 @@ bool ast_backup_fw(struct drm_device *dev, u8 *addr, u32 size) · 12 unmodified lines
204 204
205static bool ast_launch_m68k(struct drm_device *dev)205static bool ast_launch_m68k(struct drm_device *dev)
206{206{
207 struct ast_private *ast = to_ast_private(dev);207 struct ast_device *ast = to_ast_device(dev);
208 u32 i, data, len = 0;208 u32 i, data, len = 0;
209 u32 boot_address;209 u32 boot_address;
210 u8 *fw_addr = NULL;210 u8 *fw_addr = NULL;
@@ -274,7 +274,7 @@ static bool ast_launch_m68k(struct drm_device *dev) · 63 unmodified lines
274 274
275bool ast_dp501_read_edid(struct drm_device *dev, u8 *ediddata)275bool ast_dp501_read_edid(struct drm_device *dev, u8 *ediddata)
276{276{
277 struct ast_private *ast = to_ast_private(dev);277 struct ast_device *ast = to_ast_device(dev);
278 u32 i, boot_address, offset, data;278 u32 i, boot_address, offset, data;
279 u32 *pEDIDidx;279 u32 *pEDIDidx;
280 280
@@ -334,7 +334,7 @@ bool ast_dp501_read_edid(struct drm_device *dev, u8 *ediddata) · 53 unmodified lines
334 334
335static bool ast_init_dvo(struct drm_device *dev)335static bool ast_init_dvo(struct drm_device *dev)
336{336{
337 struct ast_private *ast = to_ast_private(dev);337 struct ast_device *ast = to_ast_device(dev);
338 u8 jreg;338 u8 jreg;
339 u32 data;339 u32 data;
340 ast_write32(ast, 0xf004, 0x1e6e0000);340 ast_write32(ast, 0xf004, 0x1e6e0000);
@@ -407,7 +407,7 @@ static bool ast_init_dvo(struct drm_device *dev) · 66 unmodified lines
407 407
408static void ast_init_analog(struct drm_device *dev)408static void ast_init_analog(struct drm_device *dev)
409{409{
410 struct ast_private *ast = to_ast_private(dev);410 struct ast_device *ast = to_ast_device(dev);
411 u32 data;411 u32 data;
412 412
413 /*413 /*
@@ -434,7 +434,7 @@ static void ast_init_analog(struct drm_device *dev) · 20 unmodified lines
434 434
435void ast_init_3rdtx(struct drm_device *dev)435void ast_init_3rdtx(struct drm_device *dev)
436{436{
437 struct ast_private *ast = to_ast_private(dev);437 struct ast_device *ast = to_ast_device(dev);
438 u8 jreg;438 u8 jreg;
439 439
440 if (ast->chip == AST2300 || ast->chip == AST2400) {440 if (ast->chip == AST2300 || ast->chip == AST2400) {
drivers/gpu/drm/ast/ast_drv.c+1−1
@@ -105,7 +105,7 @@ static int ast_remove_conflicting_framebuffers(struct pci_dev *pdev) · 104 unmodified lines
105 105
106static int ast_pci_probe(struct pci_dev *pdev, const struct pci_device_id *ent)106static int ast_pci_probe(struct pci_dev *pdev, const struct pci_device_id *ent)
107{107{
108 struct ast_private *ast;108 struct ast_device *ast;
109 struct drm_device *dev;109 struct drm_device *dev;
110 int ret;110 int ret;
111 111
drivers/gpu/drm/ast/ast_drv.h+33−51
@@ -157,7 +157,7 @@ to_ast_sil164_connector(struct drm_connector *connector) · 156 unmodified lines
157 * Device157 * Device
158 */158 */
159 159
160struct ast_private {160struct ast_device {
161 struct drm_device base;161 struct drm_device base;
162 162
163 struct mutex ioregs_lock; /* Protects access to I/O registers in ioregs */163 struct mutex ioregs_lock; /* Protects access to I/O registers in ioregs */
@@ -210,14 +210,14 @@ struct ast_private { · 46 unmodified lines
210 const struct firmware *dp501_fw; /* dp501 fw */210 const struct firmware *dp501_fw; /* dp501 fw */
211};211};
212 212
213static inline struct ast_private *to_ast_private(struct drm_device *dev)213static 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
218struct ast_private *ast_device_create(const struct drm_driver *drv,218struct ast_device *ast_device_create(const struct drm_driver *drv,
219 struct pci_dev *pdev,219 struct pci_dev *pdev,
220 unsigned long flags);220 unsigned long flags);
221 221
222#define AST_IO_AR_PORT_WRITE (0x40)222#define AST_IO_AR_PORT_WRITE (0x40)
223#define AST_IO_MISC_PORT_WRITE (0x42)223#define AST_IO_MISC_PORT_WRITE (0x42)
@@ -238,62 +238,44 @@ struct ast_private *ast_device_create(const struct drm_driver *drv, · 14 unmodified lines
238#define AST_IO_VGACRCB_HWC_ENABLED BIT(1)238#define AST_IO_VGACRCB_HWC_ENABLED BIT(1)
239#define AST_IO_VGACRCB_HWC_16BPP BIT(0) /* set: ARGB4444, cleared: 2bpp palette */239#define AST_IO_VGACRCB_HWC_16BPP BIT(0) /* set: ARGB4444, cleared: 2bpp palette */
240 240
241#define __ast_read(x) \241static inline u32 ast_read32(struct ast_device *ast, u32 reg)
242static inline u##x ast_read##x(struct ast_private *ast, u32 reg) { \242{
243u##x val = 0;\243 return ioread32(ast->regs + reg);
244val = ioread##x(ast->regs + reg); \
245return val;\
246}244}
247 245
248__ast_read(8);246static inline void ast_write32(struct ast_device *ast, u32 reg, u32 val)
249__ast_read(16);247{
250__ast_read(32)248 iowrite32(val, ast->regs + reg);
251
252#define __ast_io_read(x) \
253static inline u##x ast_io_read##x(struct ast_private *ast, u32 reg) { \
254u##x val = 0;\
255val = ioread##x(ast->ioregs + reg); \
256return val;\
257}249}
258 250
259__ast_io_read(8);251static inline u8 ast_io_read8(struct ast_device *ast, u32 reg)
260__ast_io_read(16);252{
261__ast_io_read(32);253 return ioread8(ast->ioregs + reg);
262 254}
263#define __ast_write(x) \
264static 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) \
273static inline void ast_io_write##x(struct ast_private *ast, u32 reg, u##x val) {\
274 iowrite##x(val, ast->ioregs + reg);\
275 }
276 255
277__ast_io_write(8);256static inline void ast_io_write8(struct ast_device *ast, u32 reg, u8 val)
278__ast_io_write(16);257{
279#undef __ast_io_write258 iowrite8(val, ast->ioregs + reg);
259}
280 260
281static inline void ast_set_index_reg(struct ast_private *ast,261static inline void ast_set_index_reg(struct ast_device *ast,
282 uint32_t base, uint8_t index,262 uint32_t base, uint8_t index,
283 uint8_t val)263 uint8_t val)
284{264{
285 ast_io_write16(ast, base, ((u16)val << 8) | index);265 ast_io_write8(ast, base, index);
266 ++base;
267 ast_io_write8(ast, base, val);
286}268}
287 269
288void ast_set_index_reg_mask(struct ast_private *ast,270void ast_set_index_reg_mask(struct ast_device *ast,
289 uint32_t base, uint8_t index,271 uint32_t base, uint8_t index,
290 uint8_t mask, uint8_t val);272 uint8_t mask, uint8_t val);
291uint8_t ast_get_index_reg(struct ast_private *ast,273uint8_t ast_get_index_reg(struct ast_device *ast,
292 uint32_t base, uint8_t index);274 uint32_t base, uint8_t index);
293uint8_t ast_get_index_reg_mask(struct ast_private *ast,275uint8_t ast_get_index_reg_mask(struct ast_device *ast,
294 uint32_t base, uint8_t index, uint8_t mask);276 uint32_t base, uint8_t index, uint8_t mask);
295 277
296static inline void ast_open_key(struct ast_private *ast)278static inline void ast_open_key(struct ast_device *ast)
297{279{
298 ast_set_index_reg(ast, AST_IO_CRTC_PORT, 0x80, 0xA8);280 ast_set_index_reg(ast, AST_IO_CRTC_PORT, 0x80, 0xA8);
299}281}
@@ -352,7 +334,7 @@ struct ast_crtc_state { · 52 unmodified lines
352 334
353#define to_ast_crtc_state(state) container_of(state, struct ast_crtc_state, base)335#define to_ast_crtc_state(state) container_of(state, struct ast_crtc_state, base)
354 336
355int ast_mode_config_init(struct ast_private *ast);337int ast_mode_config_init(struct ast_device *ast);
356 338
357#define AST_MM_ALIGN_SHIFT 4339#define AST_MM_ALIGN_SHIFT 4
358#define AST_MM_ALIGN_MASK ((1 << AST_MM_ALIGN_SHIFT) - 1)340#define AST_MM_ALIGN_MASK ((1 << AST_MM_ALIGN_SHIFT) - 1)
@@ -476,16 +458,16 @@ int ast_mode_config_init(struct ast_private *ast); · 117 unmodified lines
476#define ASTDP_1366x768_60 0x1E458#define ASTDP_1366x768_60 0x1E
477#define ASTDP_1152x864_75 0x1F459#define ASTDP_1152x864_75 0x1F
478 460
479int ast_mm_init(struct ast_private *ast);461int ast_mm_init(struct ast_device *ast);
480 462
481/* ast post */463/* ast post */
482void ast_enable_vga(struct drm_device *dev);464void ast_enable_vga(struct drm_device *dev);
483void ast_enable_mmio(struct drm_device *dev);465void ast_enable_mmio(struct drm_device *dev);
484bool ast_is_vga_enabled(struct drm_device *dev);466bool ast_is_vga_enabled(struct drm_device *dev);
485void ast_post_gpu(struct drm_device *dev);467void ast_post_gpu(struct drm_device *dev);
486u32 ast_mindwm(struct ast_private *ast, u32 r);468u32 ast_mindwm(struct ast_device *ast, u32 r);
487void ast_moutdwm(struct ast_private *ast, u32 r, u32 v);469void ast_moutdwm(struct ast_device *ast, u32 r, u32 v);
488void ast_patch_ahb_2500(struct ast_private *ast);470void ast_patch_ahb_2500(struct ast_device *ast);
489/* ast dp501 */471/* ast dp501 */
490void ast_set_dp501_video_output(struct drm_device *dev, u8 mode);472void ast_set_dp501_video_output(struct drm_device *dev, u8 mode);
491bool ast_backup_fw(struct drm_device *dev, u8 *addr, u32 size);473bool ast_backup_fw(struct drm_device *dev, u8 *addr, u32 size);
drivers/gpu/drm/ast/ast_i2c.c+4−4
@@ -29,7 +29,7 @@ · 28 unmodified lines
29static void ast_i2c_setsda(void *i2c_priv, int data)29static void ast_i2c_setsda(void *i2c_priv, int data)
30{30{
31 struct ast_i2c_chan *i2c = i2c_priv;31 struct ast_i2c_chan *i2c = i2c_priv;
32 struct ast_private *ast = to_ast_private(i2c->dev);32 struct ast_device *ast = to_ast_device(i2c->dev);
33 int i;33 int i;
34 u8 ujcrb7, jtemp;34 u8 ujcrb7, jtemp;
35 35
@@ -45,7 +45,7 @@ static void ast_i2c_setsda(void *i2c_priv, int data) · 9 unmodified lines
45static void ast_i2c_setscl(void *i2c_priv, int clock)45static void ast_i2c_setscl(void *i2c_priv, int clock)
46{46{
47 struct ast_i2c_chan *i2c = i2c_priv;47 struct ast_i2c_chan *i2c = i2c_priv;
48 struct ast_private *ast = to_ast_private(i2c->dev);48 struct ast_device *ast = to_ast_device(i2c->dev);
49 int i;49 int i;
50 u8 ujcrb7, jtemp;50 u8 ujcrb7, jtemp;
51 51
@@ -61,7 +61,7 @@ static void ast_i2c_setscl(void *i2c_priv, int clock) · 9 unmodified lines
61static int ast_i2c_getsda(void *i2c_priv)61static int ast_i2c_getsda(void *i2c_priv)
62{62{
63 struct ast_i2c_chan *i2c = i2c_priv;63 struct ast_i2c_chan *i2c = i2c_priv;
64 struct ast_private *ast = to_ast_private(i2c->dev);64 struct ast_device *ast = to_ast_device(i2c->dev);
65 uint32_t val, val2, count, pass;65 uint32_t val, val2, count, pass;
66 66
67 count = 0;67 count = 0;
@@ -83,7 +83,7 @@ static int ast_i2c_getsda(void *i2c_priv) · 15 unmodified lines
83static int ast_i2c_getscl(void *i2c_priv)83static int ast_i2c_getscl(void *i2c_priv)
84{84{
85 struct ast_i2c_chan *i2c = i2c_priv;85 struct ast_i2c_chan *i2c = i2c_priv;
86 struct ast_private *ast = to_ast_private(i2c->dev);86 struct ast_device *ast = to_ast_device(i2c->dev);
87 uint32_t val, val2, count, pass;87 uint32_t val, val2, count, pass;
88 88
89 count = 0;89 count = 0;
drivers/gpu/drm/ast/ast_main.c+12−12
@@ -35,7 +35,7 @@ · 34 unmodified lines
35 35
36#include "ast_drv.h"36#include "ast_drv.h"
37 37
38void ast_set_index_reg_mask(struct ast_private *ast,38void ast_set_index_reg_mask(struct ast_device *ast,
39 uint32_t base, uint8_t index,39 uint32_t base, uint8_t index,
40 uint8_t mask, uint8_t val)40 uint8_t mask, uint8_t val)
41{41{
@@ -45,7 +45,7 @@ void ast_set_index_reg_mask(struct ast_private *ast, · 3 unmodified lines
45 ast_set_index_reg(ast, base, index, tmp);45 ast_set_index_reg(ast, base, index, tmp);
46}46}
47 47
48uint8_t ast_get_index_reg(struct ast_private *ast,48uint8_t ast_get_index_reg(struct ast_device *ast,
49 uint32_t base, uint8_t index)49 uint32_t base, uint8_t index)
50{50{
51 uint8_t ret;51 uint8_t ret;
@@ -54,7 +54,7 @@ uint8_t ast_get_index_reg(struct ast_private *ast, · 2 unmodified lines
54 return ret;54 return ret;
55}55}
56 56
57uint8_t ast_get_index_reg_mask(struct ast_private *ast,57uint8_t ast_get_index_reg_mask(struct ast_device *ast,
58 uint32_t base, uint8_t index, uint8_t mask)58 uint32_t base, uint8_t index, uint8_t mask)
59{59{
60 uint8_t ret;60 uint8_t ret;
@@ -66,7 +66,7 @@ uint8_t ast_get_index_reg_mask(struct ast_private *ast, · 5 unmodified lines
66static void ast_detect_config_mode(struct drm_device *dev, u32 *scu_rev)66static void ast_detect_config_mode(struct drm_device *dev, u32 *scu_rev)
67{67{
68 struct device_node *np = dev->dev->of_node;68 struct device_node *np = dev->dev->of_node;
69 struct ast_private *ast = to_ast_private(dev);69 struct ast_device *ast = to_ast_device(dev);
70 struct pci_dev *pdev = to_pci_dev(dev->dev);70 struct pci_dev *pdev = to_pci_dev(dev->dev);
71 uint32_t data, jregd0, jregd1;71 uint32_t data, jregd0, jregd1;
72 72
@@ -122,7 +122,7 @@ static void ast_detect_config_mode(struct drm_device *dev, u32 *scu_rev) · 49 unmodified lines
122 122
123static int ast_detect_chip(struct drm_device *dev, bool *need_post)123static int ast_detect_chip(struct drm_device *dev, bool *need_post)
124{124{
125 struct ast_private *ast = to_ast_private(dev);125 struct ast_device *ast = to_ast_device(dev);
126 struct pci_dev *pdev = to_pci_dev(dev->dev);126 struct pci_dev *pdev = to_pci_dev(dev->dev);
127 uint32_t jreg, scu_rev;127 uint32_t jreg, scu_rev;
128 128
@@ -271,7 +271,7 @@ static int ast_detect_chip(struct drm_device *dev, bool *need_post) · 142 unmodified lines
271static int ast_get_dram_info(struct drm_device *dev)271static int ast_get_dram_info(struct drm_device *dev)
272{272{
273 struct device_node *np = dev->dev->of_node;273 struct device_node *np = dev->dev->of_node;
274 struct ast_private *ast = to_ast_private(dev);274 struct ast_device *ast = to_ast_device(dev);
275 uint32_t mcr_cfg, mcr_scu_mpll, mcr_scu_strap;275 uint32_t mcr_cfg, mcr_scu_mpll, mcr_scu_strap;
276 uint32_t denum, num, div, ref_pll, dsel;276 uint32_t denum, num, div, ref_pll, dsel;
277 277
@@ -394,22 +394,22 @@ static int ast_get_dram_info(struct drm_device *dev) · 116 unmodified lines
394 */394 */
395static void ast_device_release(void *data)395static void ast_device_release(void *data)
396{396{
397 struct ast_private *ast = data;397 struct ast_device *ast = data;
398 398
399 /* enable standard VGA decode */399 /* enable standard VGA decode */
400 ast_set_index_reg(ast, AST_IO_CRTC_PORT, 0xa1, 0x04);400 ast_set_index_reg(ast, AST_IO_CRTC_PORT, 0xa1, 0x04);
401}401}
402 402
403struct ast_private *ast_device_create(const struct drm_driver *drv,403struct ast_device *ast_device_create(const struct drm_driver *drv,
404 struct pci_dev *pdev,404 struct pci_dev *pdev,
405 unsigned long flags)405 unsigned long flags)
406{406{
407 struct drm_device *dev;407 struct drm_device *dev;
408 struct ast_private *ast;408 struct ast_device *ast;
409 bool need_post;409 bool need_post;
410 int ret = 0;410 int ret = 0;
411 411
412 ast = devm_drm_dev_alloc(&pdev->dev, drv, struct ast_private, base);412 ast = devm_drm_dev_alloc(&pdev->dev, drv, struct ast_device, base);
413 if (IS_ERR(ast))413 if (IS_ERR(ast))
414 return ast;414 return ast;
415 dev = &ast->base;415 dev = &ast->base;
drivers/gpu/drm/ast/ast_mm.c+2−2
@@ -33,7 +33,7 @@ · 32 unmodified lines
33 33
34#include "ast_drv.h"34#include "ast_drv.h"
35 35
36static u32 ast_get_vram_size(struct ast_private *ast)36static u32 ast_get_vram_size(struct ast_device *ast)
37{37{
38 u8 jreg;38 u8 jreg;
39 u32 vram_size;39 u32 vram_size;
@@ -73,7 +73,7 @@ static u32 ast_get_vram_size(struct ast_private *ast) · 33 unmodified lines
73 return vram_size;73 return vram_size;
74}74}
75 75
76int ast_mm_init(struct ast_private *ast)76int ast_mm_init(struct ast_device *ast)
77{77{
78 struct drm_device *dev = &ast->base;78 struct drm_device *dev = &ast->base;
79 struct pci_dev *pdev = to_pci_dev(dev->dev);79 struct pci_dev *pdev = to_pci_dev(dev->dev);
drivers/gpu/drm/ast/ast_mode.c+58−46
@@ -51,7 +51,7 @@ · 50 unmodified lines
51 51
52#define AST_LUT_SIZE 25652#define AST_LUT_SIZE 256
53 53
54static inline void ast_load_palette_index(struct ast_private *ast,54static inline void ast_load_palette_index(struct ast_device *ast,
55 u8 index, u8 red, u8 green,55 u8 index, u8 red, u8 green,
56 u8 blue)56 u8 blue)
57{57{
@@ -65,7 +65,7 @@ static inline void ast_load_palette_index(struct ast_private *ast, · 7 unmodified lines
65 ast_io_read8(ast, AST_IO_SEQ_PORT);65 ast_io_read8(ast, AST_IO_SEQ_PORT);
66}66}
67 67
68static void ast_crtc_set_gamma_linear(struct ast_private *ast,68static void ast_crtc_set_gamma_linear(struct ast_device *ast,
69 const struct drm_format_info *format)69 const struct drm_format_info *format)
70{70{
71 int i;71 int i;
@@ -84,7 +84,7 @@ static void ast_crtc_set_gamma_linear(struct ast_private *ast, · 12 unmodified lines
84 }84 }
85}85}
86 86
87static void ast_crtc_set_gamma(struct ast_private *ast,87static void ast_crtc_set_gamma(struct ast_device *ast,
88 const struct drm_format_info *format,88 const struct drm_format_info *format,
89 struct drm_color_lut *lut)89 struct drm_color_lut *lut)
90{90{
@@ -232,7 +232,7 @@ static bool ast_get_vbios_mode_info(const struct drm_format_info *format, · 141 unmodified lines
232 return true;232 return true;
233}233}
234 234
235static void ast_set_vbios_color_reg(struct ast_private *ast,235static void ast_set_vbios_color_reg(struct ast_device *ast,
236 const struct drm_format_info *format,236 const struct drm_format_info *format,
237 const struct ast_vbios_mode_info *vbios_mode)237 const struct ast_vbios_mode_info *vbios_mode)
238{238{
@@ -263,7 +263,7 @@ static void ast_set_vbios_color_reg(struct ast_private *ast, · 24 unmodified lines
263 }263 }
264}264}
265 265
266static void ast_set_vbios_mode_reg(struct ast_private *ast,266static void ast_set_vbios_mode_reg(struct ast_device *ast,
267 const struct drm_display_mode *adjusted_mode,267 const struct drm_display_mode *adjusted_mode,
268 const struct ast_vbios_mode_info *vbios_mode)268 const struct ast_vbios_mode_info *vbios_mode)
269{269{
@@ -287,7 +287,7 @@ static void ast_set_vbios_mode_reg(struct ast_private *ast, · 17 unmodified lines
287 }287 }
288}288}
289 289
290static void ast_set_std_reg(struct ast_private *ast,290static void ast_set_std_reg(struct ast_device *ast,
291 struct drm_display_mode *mode,291 struct drm_display_mode *mode,
292 struct ast_vbios_mode_info *vbios_mode)292 struct ast_vbios_mode_info *vbios_mode)
293{293{
@@ -335,7 +335,7 @@ static void ast_set_std_reg(struct ast_private *ast, · 41 unmodified lines
335 ast_set_index_reg(ast, AST_IO_GR_PORT, i, stdtable->gr[i]);335 ast_set_index_reg(ast, AST_IO_GR_PORT, i, stdtable->gr[i]);
336}336}
337 337
338static void ast_set_crtc_reg(struct ast_private *ast,338static void ast_set_crtc_reg(struct ast_device *ast,
339 struct drm_display_mode *mode,339 struct drm_display_mode *mode,
340 struct ast_vbios_mode_info *vbios_mode)340 struct ast_vbios_mode_info *vbios_mode)
341{341{
@@ -450,7 +450,7 @@ static void ast_set_crtc_reg(struct ast_private *ast, · 108 unmodified lines
450 ast_set_index_reg_mask(ast, AST_IO_CRTC_PORT, 0x11, 0x7f, 0x80);450 ast_set_index_reg_mask(ast, AST_IO_CRTC_PORT, 0x11, 0x7f, 0x80);
451}451}
452 452
453static void ast_set_offset_reg(struct ast_private *ast,453static void ast_set_offset_reg(struct ast_device *ast,
454 struct drm_framebuffer *fb)454 struct drm_framebuffer *fb)
455{455{
456 u16 offset;456 u16 offset;
@@ -460,7 +460,7 @@ static void ast_set_offset_reg(struct ast_private *ast, · 3 unmodified lines
460 ast_set_index_reg(ast, AST_IO_CRTC_PORT, 0xb0, (offset >> 8) & 0x3f);460 ast_set_index_reg(ast, AST_IO_CRTC_PORT, 0xb0, (offset >> 8) & 0x3f);
461}461}
462 462
463static void ast_set_dclk_reg(struct ast_private *ast,463static void ast_set_dclk_reg(struct ast_device *ast,
464 struct drm_display_mode *mode,464 struct drm_display_mode *mode,
465 struct ast_vbios_mode_info *vbios_mode)465 struct ast_vbios_mode_info *vbios_mode)
466{466{
@@ -478,7 +478,7 @@ static void ast_set_dclk_reg(struct ast_private *ast, · 11 unmodified lines
478 ((clk_info->param3 & 0x3) << 4));478 ((clk_info->param3 & 0x3) << 4));
479}479}
480 480
481static void ast_set_color_reg(struct ast_private *ast,481static void ast_set_color_reg(struct ast_device *ast,
482 const struct drm_format_info *format)482 const struct drm_format_info *format)
483{483{
484 u8 jregA0 = 0, jregA3 = 0, jregA8 = 0;484 u8 jregA0 = 0, jregA3 = 0, jregA8 = 0;
@@ -507,7 +507,7 @@ static void ast_set_color_reg(struct ast_private *ast, · 22 unmodified lines
507 ast_set_index_reg_mask(ast, AST_IO_CRTC_PORT, 0xa8, 0xfd, jregA8);507 ast_set_index_reg_mask(ast, AST_IO_CRTC_PORT, 0xa8, 0xfd, jregA8);
508}508}
509 509
510static void ast_set_crtthd_reg(struct ast_private *ast)510static void ast_set_crtthd_reg(struct ast_device *ast)
511{511{
512 /* Set Threshold */512 /* Set Threshold */
513 if (ast->chip == AST2600) {513 if (ast->chip == AST2600) {
@@ -529,7 +529,7 @@ static void ast_set_crtthd_reg(struct ast_private *ast) · 15 unmodified lines
529 }529 }
530}530}
531 531
532static void ast_set_sync_reg(struct ast_private *ast,532static void ast_set_sync_reg(struct ast_device *ast,
533 struct drm_display_mode *mode,533 struct drm_display_mode *mode,
534 struct ast_vbios_mode_info *vbios_mode)534 struct ast_vbios_mode_info *vbios_mode)
535{535{
@@ -544,7 +544,7 @@ static void ast_set_sync_reg(struct ast_private *ast, · 8 unmodified lines
544 ast_io_write8(ast, AST_IO_MISC_PORT_WRITE, jreg);544 ast_io_write8(ast, AST_IO_MISC_PORT_WRITE, jreg);
545}545}
546 546
547static void ast_set_start_address_crt1(struct ast_private *ast,547static void ast_set_start_address_crt1(struct ast_device *ast,
548 unsigned int offset)548 unsigned int offset)
549{549{
550 u32 addr;550 u32 addr;
@@ -556,7 +556,7 @@ static void ast_set_start_address_crt1(struct ast_private *ast, · 5 unmodified lines
556 556
557}557}
558 558
559static void ast_wait_for_vretrace(struct ast_private *ast)559static void ast_wait_for_vretrace(struct ast_device *ast)
560{560{
561 unsigned long timeout = jiffies + HZ;561 unsigned long timeout = jiffies + HZ;
562 u8 vgair1;562 u8 vgair1;
@@ -645,7 +645,7 @@ static void ast_primary_plane_helper_atomic_update(struct drm_plane *plane, · 82 unmodified lines
645 struct drm_atomic_state *state)645 struct drm_atomic_state *state)
646{646{
647 struct drm_device *dev = plane->dev;647 struct drm_device *dev = plane->dev;
648 struct ast_private *ast = to_ast_private(dev);648 struct ast_device *ast = to_ast_device(dev);
649 struct drm_plane_state *plane_state = drm_atomic_get_new_plane_state(state, plane);649 struct drm_plane_state *plane_state = drm_atomic_get_new_plane_state(state, plane);
650 struct drm_shadow_plane_state *shadow_plane_state = to_drm_shadow_plane_state(plane_state);650 struct drm_shadow_plane_state *shadow_plane_state = to_drm_shadow_plane_state(plane_state);
651 struct drm_framebuffer *fb = plane_state->fb;651 struct drm_framebuffer *fb = plane_state->fb;
@@ -672,23 +672,34 @@ static void ast_primary_plane_helper_atomic_update(struct drm_plane *plane, · 20 unmodified lines
672 672
673 /*673 /*
674 * Some BMCs stop scanning out the video signal after the driver674 * Some BMCs stop scanning out the video signal after the driver
675 * reprogrammed the offset or scanout address. This stalls display675 * reprogrammed the offset. This stalls display output for several
676 * output for several seconds and makes the display unusable.676 * seconds and makes the display unusable. Therefore only update
677 * Therefore only update the offset if it changes and reprogram the677 * the offset if it changes.
678 * address after enabling the plane.
679 */678 */
680 if (!old_fb || old_fb->pitches[0] != fb->pitches[0])679 if (!old_fb || old_fb->pitches[0] != fb->pitches[0])
681 ast_set_offset_reg(ast, fb);680 ast_set_offset_reg(ast, fb);
682 if (!old_fb) {681}
683 ast_set_start_address_crt1(ast, (u32)ast_plane->offset);682
684 ast_set_index_reg_mask(ast, AST_IO_SEQ_PORT, 0x1, 0xdf, 0x00);683static void ast_primary_plane_helper_atomic_enable(struct drm_plane *plane,
685 }684 struct drm_atomic_state *state)
685{
686 struct ast_device *ast = to_ast_device(plane->dev);
687 struct ast_plane *ast_plane = to_ast_plane(plane);
688
689 /*
690 * Some BMCs stop scanning out the video signal after the driver
691 * reprogrammed the scanout address. This stalls display
692 * output for several seconds and makes the display unusable.
693 * Therefore only reprogram the address after enabling the plane.
694 */
695 ast_set_start_address_crt1(ast, (u32)ast_plane->offset);
696 ast_set_index_reg_mask(ast, AST_IO_SEQ_PORT, 0x1, 0xdf, 0x00);
686}697}
687 698
688static void ast_primary_plane_helper_atomic_disable(struct drm_plane *plane,699static void ast_primary_plane_helper_atomic_disable(struct drm_plane *plane,
689 struct drm_atomic_state *state)700 struct drm_atomic_state *state)
690{701{
691 struct ast_private *ast = to_ast_private(plane->dev);702 struct ast_device *ast = to_ast_device(plane->dev);
692 703
693 ast_set_index_reg_mask(ast, AST_IO_SEQ_PORT, 0x1, 0xdf, 0x20);704 ast_set_index_reg_mask(ast, AST_IO_SEQ_PORT, 0x1, 0xdf, 0x20);
694}705}
@@ -697,6 +708,7 @@ static const struct drm_plane_helper_funcs ast_primary_plane_helper_funcs = { · 2 unmodified lines
697 DRM_GEM_SHADOW_PLANE_HELPER_FUNCS,708 DRM_GEM_SHADOW_PLANE_HELPER_FUNCS,
698 .atomic_check = ast_primary_plane_helper_atomic_check,709 .atomic_check = ast_primary_plane_helper_atomic_check,
699 .atomic_update = ast_primary_plane_helper_atomic_update,710 .atomic_update = ast_primary_plane_helper_atomic_update,
711 .atomic_enable = ast_primary_plane_helper_atomic_enable,
700 .atomic_disable = ast_primary_plane_helper_atomic_disable,712 .atomic_disable = ast_primary_plane_helper_atomic_disable,
701};713};
702 714
@@ -707,7 +719,7 @@ static const struct drm_plane_funcs ast_primary_plane_funcs = { · 4 unmodified lines
707 DRM_GEM_SHADOW_PLANE_FUNCS,719 DRM_GEM_SHADOW_PLANE_FUNCS,
708};720};
709 721
710static int ast_primary_plane_init(struct ast_private *ast)722static int ast_primary_plane_init(struct ast_device *ast)
711{723{
712 struct drm_device *dev = &ast->base;724 struct drm_device *dev = &ast->base;
713 struct ast_plane *ast_primary_plane = &ast->primary_plane;725 struct ast_plane *ast_primary_plane = &ast->primary_plane;
@@ -800,7 +812,7 @@ static void ast_update_cursor_image(u8 __iomem *dst, const u8 *src, int width, i · 86 unmodified lines
800 writel(0, dst + AST_HWC_SIGNATURE_HOTSPOTY);812 writel(0, dst + AST_HWC_SIGNATURE_HOTSPOTY);
801}813}
802 814
803static void ast_set_cursor_base(struct ast_private *ast, u64 address)815static void ast_set_cursor_base(struct ast_device *ast, u64 address)
804{816{
805 u8 addr0 = (address >> 3) & 0xff;817 u8 addr0 = (address >> 3) & 0xff;
806 u8 addr1 = (address >> 11) & 0xff;818 u8 addr1 = (address >> 11) & 0xff;
@@ -811,7 +823,7 @@ static void ast_set_cursor_base(struct ast_private *ast, u64 address) · 4 unmodified lines
811 ast_set_index_reg(ast, AST_IO_CRTC_PORT, 0xca, addr2);823 ast_set_index_reg(ast, AST_IO_CRTC_PORT, 0xca, addr2);
812}824}
813 825
814static void ast_set_cursor_location(struct ast_private *ast, u16 x, u16 y,826static void ast_set_cursor_location(struct ast_device *ast, u16 x, u16 y,
815 u8 x_offset, u8 y_offset)827 u8 x_offset, u8 y_offset)
816{828{
817 u8 x0 = (x & 0x00ff);829 u8 x0 = (x & 0x00ff);
@@ -827,7 +839,7 @@ static void ast_set_cursor_location(struct ast_private *ast, u16 x, u16 y, · 9 unmodified lines
827 ast_set_index_reg(ast, AST_IO_CRTC_PORT, 0xc7, y1);839 ast_set_index_reg(ast, AST_IO_CRTC_PORT, 0xc7, y1);
828}840}
829 841
830static void ast_set_cursor_enabled(struct ast_private *ast, bool enabled)842static void ast_set_cursor_enabled(struct ast_device *ast, bool enabled)
831{843{
832 static const u8 mask = (u8)~(AST_IO_VGACRCB_HWC_16BPP |844 static const u8 mask = (u8)~(AST_IO_VGACRCB_HWC_16BPP |
833 AST_IO_VGACRCB_HWC_ENABLED);845 AST_IO_VGACRCB_HWC_ENABLED);
@@ -876,7 +888,7 @@ static void ast_cursor_plane_helper_atomic_update(struct drm_plane *plane, · 42 unmodified lines
876 struct drm_shadow_plane_state *shadow_plane_state = to_drm_shadow_plane_state(plane_state);888 struct drm_shadow_plane_state *shadow_plane_state = to_drm_shadow_plane_state(plane_state);
877 struct drm_framebuffer *fb = plane_state->fb;889 struct drm_framebuffer *fb = plane_state->fb;
878 struct drm_plane_state *old_plane_state = drm_atomic_get_old_plane_state(state, plane);890 struct drm_plane_state *old_plane_state = drm_atomic_get_old_plane_state(state, plane);
879 struct ast_private *ast = to_ast_private(plane->dev);891 struct ast_device *ast = to_ast_device(plane->dev);
880 struct iosys_map src_map = shadow_plane_state->data[0];892 struct iosys_map src_map = shadow_plane_state->data[0];
881 struct drm_rect damage;893 struct drm_rect damage;
882 const u8 *src = src_map.vaddr; /* TODO: Use mapping abstraction properly */894 const u8 *src = src_map.vaddr; /* TODO: Use mapping abstraction properly */
@@ -931,7 +943,7 @@ static void ast_cursor_plane_helper_atomic_update(struct drm_plane *plane, · 48 unmodified lines
931static void ast_cursor_plane_helper_atomic_disable(struct drm_plane *plane,943static void ast_cursor_plane_helper_atomic_disable(struct drm_plane *plane,
932 struct drm_atomic_state *state)944 struct drm_atomic_state *state)
933{945{
934 struct ast_private *ast = to_ast_private(plane->dev);946 struct ast_device *ast = to_ast_device(plane->dev);
935 947
936 ast_set_cursor_enabled(ast, false);948 ast_set_cursor_enabled(ast, false);
937}949}
@@ -950,7 +962,7 @@ static const struct drm_plane_funcs ast_cursor_plane_funcs = { · 12 unmodified lines
950 DRM_GEM_SHADOW_PLANE_FUNCS,962 DRM_GEM_SHADOW_PLANE_FUNCS,
951};963};
952 964
953static int ast_cursor_plane_init(struct ast_private *ast)965static int ast_cursor_plane_init(struct ast_device *ast)
954{966{
955 struct drm_device *dev = &ast->base;967 struct drm_device *dev = &ast->base;
956 struct ast_plane *ast_cursor_plane = &ast->cursor_plane;968 struct ast_plane *ast_cursor_plane = &ast->cursor_plane;
@@ -995,7 +1007,7 @@ static int ast_cursor_plane_init(struct ast_private *ast) · 38 unmodified lines
995 1007
996static void ast_crtc_dpms(struct drm_crtc *crtc, int mode)1008static void ast_crtc_dpms(struct drm_crtc *crtc, int mode)
997{1009{
998 struct ast_private *ast = to_ast_private(crtc->dev);1010 struct ast_device *ast = to_ast_device(crtc->dev);
999 u8 ch = AST_DPMS_VSYNC_OFF | AST_DPMS_HSYNC_OFF;1011 u8 ch = AST_DPMS_VSYNC_OFF | AST_DPMS_HSYNC_OFF;
1000 struct ast_crtc_state *ast_state;1012 struct ast_crtc_state *ast_state;
1001 const struct drm_format_info *format;1013 const struct drm_format_info *format;
@@ -1052,7 +1064,7 @@ static void ast_crtc_dpms(struct drm_crtc *crtc, int mode) · 50 unmodified lines
1052static enum drm_mode_status1064static enum drm_mode_status
1053ast_crtc_helper_mode_valid(struct drm_crtc *crtc, const struct drm_display_mode *mode)1065ast_crtc_helper_mode_valid(struct drm_crtc *crtc, const struct drm_display_mode *mode)
1054{1066{
1055 struct ast_private *ast = to_ast_private(crtc->dev);1067 struct ast_device *ast = to_ast_device(crtc->dev);
1056 enum drm_mode_status status;1068 enum drm_mode_status status;
1057 uint32_t jtemp;1069 uint32_t jtemp;
1058 1070
@@ -1177,7 +1189,7 @@ ast_crtc_helper_atomic_flush(struct drm_crtc *crtc, · 118 unmodified lines
1177 struct drm_crtc_state *crtc_state = drm_atomic_get_new_crtc_state(state,1189 struct drm_crtc_state *crtc_state = drm_atomic_get_new_crtc_state(state,
1178 crtc);1190 crtc);
1179 struct drm_device *dev = crtc->dev;1191 struct drm_device *dev = crtc->dev;
1180 struct ast_private *ast = to_ast_private(dev);1192 struct ast_device *ast = to_ast_device(dev);
1181 struct ast_crtc_state *ast_crtc_state = to_ast_crtc_state(crtc_state);1193 struct ast_crtc_state *ast_crtc_state = to_ast_crtc_state(crtc_state);
1182 struct ast_vbios_mode_info *vbios_mode_info = &ast_crtc_state->vbios_mode_info;1194 struct ast_vbios_mode_info *vbios_mode_info = &ast_crtc_state->vbios_mode_info;
1183 1195
@@ -1202,7 +1214,7 @@ ast_crtc_helper_atomic_flush(struct drm_crtc *crtc, · 18 unmodified lines
1202static void ast_crtc_helper_atomic_enable(struct drm_crtc *crtc, struct drm_atomic_state *state)1214static void ast_crtc_helper_atomic_enable(struct drm_crtc *crtc, struct drm_atomic_state *state)
1203{1215{
1204 struct drm_device *dev = crtc->dev;1216 struct drm_device *dev = crtc->dev;
1205 struct ast_private *ast = to_ast_private(dev);1217 struct ast_device *ast = to_ast_device(dev);
1206 struct drm_crtc_state *crtc_state = drm_atomic_get_new_crtc_state(state, crtc);1218 struct drm_crtc_state *crtc_state = drm_atomic_get_new_crtc_state(state, crtc);
1207 struct ast_crtc_state *ast_crtc_state = to_ast_crtc_state(crtc_state);1219 struct ast_crtc_state *ast_crtc_state = to_ast_crtc_state(crtc_state);
1208 struct ast_vbios_mode_info *vbios_mode_info =1220 struct ast_vbios_mode_info *vbios_mode_info =
@@ -1224,7 +1236,7 @@ static void ast_crtc_helper_atomic_disable(struct drm_crtc *crtc, struct drm_ato · 15 unmodified lines
1224{1236{
1225 struct drm_crtc_state *old_crtc_state = drm_atomic_get_old_crtc_state(state, crtc);1237 struct drm_crtc_state *old_crtc_state = drm_atomic_get_old_crtc_state(state, crtc);
1226 struct drm_device *dev = crtc->dev;1238 struct drm_device *dev = crtc->dev;
1227 struct ast_private *ast = to_ast_private(dev);1239 struct ast_device *ast = to_ast_device(dev);
1228 1240
1229 ast_crtc_dpms(crtc, DRM_MODE_DPMS_OFF);1241 ast_crtc_dpms(crtc, DRM_MODE_DPMS_OFF);
1230 1242
@@ -1312,7 +1324,7 @@ static const struct drm_crtc_funcs ast_crtc_funcs = { · 81 unmodified lines
1312 1324
1313static int ast_crtc_init(struct drm_device *dev)1325static int ast_crtc_init(struct drm_device *dev)
1314{1326{
1315 struct ast_private *ast = to_ast_private(dev);1327 struct ast_device *ast = to_ast_device(dev);
1316 struct drm_crtc *crtc = &ast->crtc;1328 struct drm_crtc *crtc = &ast->crtc;
1317 int ret;1329 int ret;
1318 1330
@@ -1338,7 +1350,7 @@ static int ast_vga_connector_helper_get_modes(struct drm_connector *connector) · 19 unmodified lines
1338{1350{
1339 struct ast_vga_connector *ast_vga_connector = to_ast_vga_connector(connector);1351 struct ast_vga_connector *ast_vga_connector = to_ast_vga_connector(connector);
1340 struct drm_device *dev = connector->dev;1352 struct drm_device *dev = connector->dev;
1341 struct ast_private *ast = to_ast_private(dev);1353 struct ast_device *ast = to_ast_device(dev);
1342 struct edid *edid;1354 struct edid *edid;
1343 int count;1355 int count;
1344 1356
@@ -1411,7 +1423,7 @@ static int ast_vga_connector_init(struct drm_device *dev, · 66 unmodified lines
1411 return 0;1423 return 0;
1412}1424}
1413 1425
1414static int ast_vga_output_init(struct ast_private *ast)1426static int ast_vga_output_init(struct ast_device *ast)
1415{1427{
1416 struct drm_device *dev = &ast->base;1428 struct drm_device *dev = &ast->base;
1417 struct drm_crtc *crtc = &ast->crtc;1429 struct drm_crtc *crtc = &ast->crtc;
@@ -1444,7 +1456,7 @@ static int ast_sil164_connector_helper_get_modes(struct drm_connector *connector · 26 unmodified lines
1444{1456{
1445 struct ast_sil164_connector *ast_sil164_connector = to_ast_sil164_connector(connector);1457 struct ast_sil164_connector *ast_sil164_connector = to_ast_sil164_connector(connector);
1446 struct drm_device *dev = connector->dev;1458 struct drm_device *dev = connector->dev;
1447 struct ast_private *ast = to_ast_private(dev);1459 struct ast_device *ast = to_ast_device(dev);
1448 struct edid *edid;1460 struct edid *edid;
1449 int count;1461 int count;
1450 1462
@@ -1517,7 +1529,7 @@ static int ast_sil164_connector_init(struct drm_device *dev, · 66 unmodified lines
1517 return 0;1529 return 0;
1518}1530}
1519 1531
1520static int ast_sil164_output_init(struct ast_private *ast)1532static int ast_sil164_output_init(struct ast_device *ast)
1521{1533{
1522 struct drm_device *dev = &ast->base;1534 struct drm_device *dev = &ast->base;
1523 struct drm_crtc *crtc = &ast->crtc;1535 struct drm_crtc *crtc = &ast->crtc;
@@ -1604,7 +1616,7 @@ static int ast_dp501_connector_init(struct drm_device *dev, struct drm_connector · 80 unmodified lines
1604 return 0;1616 return 0;
1605}1617}
1606 1618
1607static int ast_dp501_output_init(struct ast_private *ast)1619static int ast_dp501_output_init(struct ast_device *ast)
1608{1620{
1609 struct drm_device *dev = &ast->base;1621 struct drm_device *dev = &ast->base;
1610 struct drm_crtc *crtc = &ast->crtc;1622 struct drm_crtc *crtc = &ast->crtc;
@@ -1691,7 +1703,7 @@ static int ast_astdp_connector_init(struct drm_device *dev, struct drm_connector · 80 unmodified lines
1691 return 0;1703 return 0;
1692}1704}
1693 1705
1694static int ast_astdp_output_init(struct ast_private *ast)1706static int ast_astdp_output_init(struct ast_device *ast)
1695{1707{
1696 struct drm_device *dev = &ast->base;1708 struct drm_device *dev = &ast->base;
1697 struct drm_crtc *crtc = &ast->crtc;1709 struct drm_crtc *crtc = &ast->crtc;
@@ -1721,7 +1733,7 @@ static int ast_astdp_output_init(struct ast_private *ast) · 23 unmodified lines
1721 1733
1722static void ast_mode_config_helper_atomic_commit_tail(struct drm_atomic_state *state)1734static void ast_mode_config_helper_atomic_commit_tail(struct drm_atomic_state *state)
1723{1735{
1724 struct ast_private *ast = to_ast_private(state->dev);1736 struct ast_device *ast = to_ast_device(state->dev);
1725 1737
1726 /*1738 /*
1727 * Concurrent operations could possibly trigger a call to1739 * Concurrent operations could possibly trigger a call to
@@ -1742,7 +1754,7 @@ static enum drm_mode_status ast_mode_config_mode_valid(struct drm_device *dev, · 14 unmodified lines
1742 const struct drm_display_mode *mode)1754 const struct drm_display_mode *mode)
1743{1755{
1744 static const unsigned long max_bpp = 4; /* DRM_FORMAT_XRGB8888 */1756 static const unsigned long max_bpp = 4; /* DRM_FORMAT_XRGB8888 */
1745 struct ast_private *ast = to_ast_private(dev);1757 struct ast_device *ast = to_ast_device(dev);
1746 unsigned long fbsize, fbpages, max_fbpages;1758 unsigned long fbsize, fbpages, max_fbpages;
1747 1759
1748 max_fbpages = (ast->vram_fb_available) >> PAGE_SHIFT;1760 max_fbpages = (ast->vram_fb_available) >> PAGE_SHIFT;
@@ -1763,7 +1775,7 @@ static const struct drm_mode_config_funcs ast_mode_config_funcs = { · 14 unmodified lines
1763 .atomic_commit = drm_atomic_helper_commit,1775 .atomic_commit = drm_atomic_helper_commit,
1764};1776};
1765 1777
1766int ast_mode_config_init(struct ast_private *ast)1778int ast_mode_config_init(struct ast_device *ast)
1767{1779{
1768 struct drm_device *dev = &ast->base;1780 struct drm_device *dev = &ast->base;
1769 int ret;1781 int ret;
drivers/gpu/drm/ast/ast_post.c+47−47
@@ -39,7 +39,7 @@ static void ast_post_chip_2500(struct drm_device *dev); · 38 unmodified lines
39 39
40void ast_enable_vga(struct drm_device *dev)40void ast_enable_vga(struct drm_device *dev)
41{41{
42 struct ast_private *ast = to_ast_private(dev);42 struct ast_device *ast = to_ast_device(dev);
43 43
44 ast_io_write8(ast, AST_IO_VGA_ENABLE_PORT, 0x01);44 ast_io_write8(ast, AST_IO_VGA_ENABLE_PORT, 0x01);
45 ast_io_write8(ast, AST_IO_MISC_PORT_WRITE, 0x01);45 ast_io_write8(ast, AST_IO_MISC_PORT_WRITE, 0x01);
@@ -47,7 +47,7 @@ void ast_enable_vga(struct drm_device *dev) · 1 unmodified line
47 47
48void ast_enable_mmio(struct drm_device *dev)48void ast_enable_mmio(struct drm_device *dev)
49{49{
50 struct ast_private *ast = to_ast_private(dev);50 struct ast_device *ast = to_ast_device(dev);
51 51
52 ast_set_index_reg(ast, AST_IO_CRTC_PORT, 0xa1, 0x06);52 ast_set_index_reg(ast, AST_IO_CRTC_PORT, 0xa1, 0x06);
53}53}
@@ -55,7 +55,7 @@ void ast_enable_mmio(struct drm_device *dev) · 1 unmodified line
55 55
56bool ast_is_vga_enabled(struct drm_device *dev)56bool ast_is_vga_enabled(struct drm_device *dev)
57{57{
58 struct ast_private *ast = to_ast_private(dev);58 struct ast_device *ast = to_ast_device(dev);
59 u8 ch;59 u8 ch;
60 60
61 ch = ast_io_read8(ast, AST_IO_VGA_ENABLE_PORT);61 ch = ast_io_read8(ast, AST_IO_VGA_ENABLE_PORT);
@@ -70,7 +70,7 @@ static const u8 extreginfo_ast2300[] = { 0x0f, 0x04, 0x1f, 0xff }; · 8 unmodified lines
70static void70static void
71ast_set_def_ext_reg(struct drm_device *dev)71ast_set_def_ext_reg(struct drm_device *dev)
72{72{
73 struct ast_private *ast = to_ast_private(dev);73 struct ast_device *ast = to_ast_device(dev);
74 struct pci_dev *pdev = to_pci_dev(dev->dev);74 struct pci_dev *pdev = to_pci_dev(dev->dev);
75 u8 i, index, reg;75 u8 i, index, reg;
76 const u8 *ext_reg_info;76 const u8 *ext_reg_info;
@@ -110,7 +110,7 @@ ast_set_def_ext_reg(struct drm_device *dev) · 33 unmodified lines
110 ast_set_index_reg_mask(ast, AST_IO_CRTC_PORT, 0xb6, 0xff, reg);110 ast_set_index_reg_mask(ast, AST_IO_CRTC_PORT, 0xb6, 0xff, reg);
111}111}
112 112
113u32 ast_mindwm(struct ast_private *ast, u32 r)113u32 ast_mindwm(struct ast_device *ast, u32 r)
114{114{
115 uint32_t data;115 uint32_t data;
116 116
@@ -123,7 +123,7 @@ u32 ast_mindwm(struct ast_private *ast, u32 r) · 6 unmodified lines
123 return ast_read32(ast, 0x10000 + (r & 0x0000ffff));123 return ast_read32(ast, 0x10000 + (r & 0x0000ffff));
124}124}
125 125
126void ast_moutdwm(struct ast_private *ast, u32 r, u32 v)126void ast_moutdwm(struct ast_device *ast, u32 r, u32 v)
127{127{
128 uint32_t data;128 uint32_t data;
129 ast_write32(ast, 0xf004, r & 0xffff0000);129 ast_write32(ast, 0xf004, r & 0xffff0000);
@@ -162,7 +162,7 @@ static const u32 pattern_AST2150[14] = { · 32 unmodified lines
162 0x20F050E0162 0x20F050E0
163};163};
164 164
165static u32 mmctestburst2_ast2150(struct ast_private *ast, u32 datagen)165static u32 mmctestburst2_ast2150(struct ast_device *ast, u32 datagen)
166{166{
167 u32 data, timeout;167 u32 data, timeout;
168 168
@@ -192,7 +192,7 @@ static u32 mmctestburst2_ast2150(struct ast_private *ast, u32 datagen) · 23 unmodified lines
192}192}
193 193
194#if 0 /* unused in DDX driver - here for completeness */194#if 0 /* unused in DDX driver - here for completeness */
195static u32 mmctestsingle2_ast2150(struct ast_private *ast, u32 datagen)195static u32 mmctestsingle2_ast2150(struct ast_device *ast, u32 datagen)
196{196{
197 u32 data, timeout;197 u32 data, timeout;
198 198
@@ -212,7 +212,7 @@ static u32 mmctestsingle2_ast2150(struct ast_private *ast, u32 datagen) · 13 unmodified lines
212}212}
213#endif213#endif
214 214
215static int cbrtest_ast2150(struct ast_private *ast)215static int cbrtest_ast2150(struct ast_device *ast)
216{216{
217 int i;217 int i;
218 218
@@ -222,7 +222,7 @@ static int cbrtest_ast2150(struct ast_private *ast) · 3 unmodified lines
222 return 1;222 return 1;
223}223}
224 224
225static int cbrscan_ast2150(struct ast_private *ast, int busw)225static int cbrscan_ast2150(struct ast_device *ast, int busw)
226{226{
227 u32 patcnt, loop;227 u32 patcnt, loop;
228 228
@@ -239,7 +239,7 @@ static int cbrscan_ast2150(struct ast_private *ast, int busw) · 10 unmodified lines
239}239}
240 240
241 241
242static void cbrdlli_ast2150(struct ast_private *ast, int busw)242static void cbrdlli_ast2150(struct ast_device *ast, int busw)
243{243{
244 u32 dll_min[4], dll_max[4], dlli, data, passcnt;244 u32 dll_min[4], dll_max[4], dlli, data, passcnt;
245 245
@@ -273,7 +273,7 @@ cbr_start: · 27 unmodified lines
273 273
274static void ast_init_dram_reg(struct drm_device *dev)274static void ast_init_dram_reg(struct drm_device *dev)
275{275{
276 struct ast_private *ast = to_ast_private(dev);276 struct ast_device *ast = to_ast_device(dev);
277 u8 j;277 u8 j;
278 u32 data, temp, i;278 u32 data, temp, i;
279 const struct ast_dramstruct *dram_reg_info;279 const struct ast_dramstruct *dram_reg_info;
@@ -366,7 +366,7 @@ static void ast_init_dram_reg(struct drm_device *dev) · 86 unmodified lines
366 366
367void ast_post_gpu(struct drm_device *dev)367void ast_post_gpu(struct drm_device *dev)
368{368{
369 struct ast_private *ast = to_ast_private(dev);369 struct ast_device *ast = to_ast_device(dev);
370 struct pci_dev *pdev = to_pci_dev(dev->dev);370 struct pci_dev *pdev = to_pci_dev(dev->dev);
371 u32 reg;371 u32 reg;
372 372
@@ -449,7 +449,7 @@ static const u32 pattern[8] = { · 76 unmodified lines
449 0x7C61D253449 0x7C61D253
450};450};
451 451
452static bool mmc_test(struct ast_private *ast, u32 datagen, u8 test_ctl)452static bool mmc_test(struct ast_device *ast, u32 datagen, u8 test_ctl)
453{453{
454 u32 data, timeout;454 u32 data, timeout;
455 455
@@ -469,7 +469,7 @@ static bool mmc_test(struct ast_private *ast, u32 datagen, u8 test_ctl) · 13 unmodified lines
469 return true;469 return true;
470}470}
471 471
472static u32 mmc_test2(struct ast_private *ast, u32 datagen, u8 test_ctl)472static u32 mmc_test2(struct ast_device *ast, u32 datagen, u8 test_ctl)
473{473{
474 u32 data, timeout;474 u32 data, timeout;
475 475
@@ -490,32 +490,32 @@ static u32 mmc_test2(struct ast_private *ast, u32 datagen, u8 test_ctl) · 14 unmodified lines
490}490}
491 491
492 492
493static bool mmc_test_burst(struct ast_private *ast, u32 datagen)493static bool mmc_test_burst(struct ast_device *ast, u32 datagen)
494{494{
495 return mmc_test(ast, datagen, 0xc1);495 return mmc_test(ast, datagen, 0xc1);
496}496}
497 497
498static u32 mmc_test_burst2(struct ast_private *ast, u32 datagen)498static u32 mmc_test_burst2(struct ast_device *ast, u32 datagen)
499{499{
500 return mmc_test2(ast, datagen, 0x41);500 return mmc_test2(ast, datagen, 0x41);
501}501}
502 502
503static bool mmc_test_single(struct ast_private *ast, u32 datagen)503static bool mmc_test_single(struct ast_device *ast, u32 datagen)
504{504{
505 return mmc_test(ast, datagen, 0xc5);505 return mmc_test(ast, datagen, 0xc5);
506}506}
507 507
508static u32 mmc_test_single2(struct ast_private *ast, u32 datagen)508static u32 mmc_test_single2(struct ast_device *ast, u32 datagen)
509{509{
510 return mmc_test2(ast, datagen, 0x05);510 return mmc_test2(ast, datagen, 0x05);
511}511}
512 512
513static bool mmc_test_single_2500(struct ast_private *ast, u32 datagen)513static bool mmc_test_single_2500(struct ast_device *ast, u32 datagen)
514{514{
515 return mmc_test(ast, datagen, 0x85);515 return mmc_test(ast, datagen, 0x85);
516}516}
517 517
518static int cbr_test(struct ast_private *ast)518static int cbr_test(struct ast_device *ast)
519{519{
520 u32 data;520 u32 data;
521 int i;521 int i;
@@ -534,7 +534,7 @@ static int cbr_test(struct ast_private *ast) · 12 unmodified lines
534 return 1;534 return 1;
535}535}
536 536
537static int cbr_scan(struct ast_private *ast)537static int cbr_scan(struct ast_device *ast)
538{538{
539 u32 data, data2, patcnt, loop;539 u32 data, data2, patcnt, loop;
540 540
@@ -555,7 +555,7 @@ static int cbr_scan(struct ast_private *ast) · 14 unmodified lines
555 return data2;555 return data2;
556}556}
557 557
558static u32 cbr_test2(struct ast_private *ast)558static u32 cbr_test2(struct ast_device *ast)
559{559{
560 u32 data;560 u32 data;
561 561
@@ -569,7 +569,7 @@ static u32 cbr_test2(struct ast_private *ast) · 7 unmodified lines
569 return ~data & 0xffff;569 return ~data & 0xffff;
570}570}
571 571
572static u32 cbr_scan2(struct ast_private *ast)572static u32 cbr_scan2(struct ast_device *ast)
573{573{
574 u32 data, data2, patcnt, loop;574 u32 data, data2, patcnt, loop;
575 575
@@ -590,7 +590,7 @@ static u32 cbr_scan2(struct ast_private *ast) · 14 unmodified lines
590 return data2;590 return data2;
591}591}
592 592
593static bool cbr_test3(struct ast_private *ast)593static bool cbr_test3(struct ast_device *ast)
594{594{
595 if (!mmc_test_burst(ast, 0))595 if (!mmc_test_burst(ast, 0))
596 return false;596 return false;
@@ -599,7 +599,7 @@ static bool cbr_test3(struct ast_private *ast) · 2 unmodified lines
599 return true;599 return true;
600}600}
601 601
602static bool cbr_scan3(struct ast_private *ast)602static bool cbr_scan3(struct ast_device *ast)
603{603{
604 u32 patcnt, loop;604 u32 patcnt, loop;
605 605
@@ -615,7 +615,7 @@ static bool cbr_scan3(struct ast_private *ast) · 9 unmodified lines
615 return true;615 return true;
616}616}
617 617
618static bool finetuneDQI_L(struct ast_private *ast, struct ast2300_dram_param *param)618static bool finetuneDQI_L(struct ast_device *ast, struct ast2300_dram_param *param)
619{619{
620 u32 gold_sadj[2], dllmin[16], dllmax[16], dlli, data, cnt, mask, passcnt, retry = 0;620 u32 gold_sadj[2], dllmin[16], dllmax[16], dlli, data, cnt, mask, passcnt, retry = 0;
621 bool status = false;621 bool status = false;
@@ -714,7 +714,7 @@ FINETUNE_DONE: · 92 unmodified lines
714 return status;714 return status;
715} /* finetuneDQI_L */715} /* finetuneDQI_L */
716 716
717static void finetuneDQSI(struct ast_private *ast)717static void finetuneDQSI(struct ast_device *ast)
718{718{
719 u32 dlli, dqsip, dqidly;719 u32 dlli, dqsip, dqidly;
720 u32 reg_mcr18, reg_mcr0c, passcnt[2], diff;720 u32 reg_mcr18, reg_mcr0c, passcnt[2], diff;
@@ -804,7 +804,7 @@ static void finetuneDQSI(struct ast_private *ast) · 83 unmodified lines
804 ast_moutdwm(ast, 0x1E6E0018, reg_mcr18);804 ast_moutdwm(ast, 0x1E6E0018, reg_mcr18);
805 805
806}806}
807static bool cbr_dll2(struct ast_private *ast, struct ast2300_dram_param *param)807static bool cbr_dll2(struct ast_device *ast, struct ast2300_dram_param *param)
808{808{
809 u32 dllmin[2], dllmax[2], dlli, data, passcnt, retry = 0;809 u32 dllmin[2], dllmax[2], dlli, data, passcnt, retry = 0;
810 bool status = false;810 bool status = false;
@@ -860,7 +860,7 @@ CBR_DONE2: · 49 unmodified lines
860 return status;860 return status;
861} /* CBRDLL2 */861} /* CBRDLL2 */
862 862
863static void get_ddr3_info(struct ast_private *ast, struct ast2300_dram_param *param)863static void get_ddr3_info(struct ast_device *ast, struct ast2300_dram_param *param)
864{864{
865 u32 trap, trap_AC2, trap_MRS;865 u32 trap, trap_AC2, trap_MRS;
866 866
@@ -1102,7 +1102,7 @@ static void get_ddr3_info(struct ast_private *ast, struct ast2300_dram_param *pa · 235 unmodified lines
1102 1102
1103}1103}
1104 1104
1105static void ddr3_init(struct ast_private *ast, struct ast2300_dram_param *param)1105static void ddr3_init(struct ast_device *ast, struct ast2300_dram_param *param)
1106{1106{
1107 u32 data, data2, retry = 0;1107 u32 data, data2, retry = 0;
1108 1108
@@ -1225,7 +1225,7 @@ ddr3_init_start: · 116 unmodified lines
1225 1225
1226}1226}
1227 1227
1228static void get_ddr2_info(struct ast_private *ast, struct ast2300_dram_param *param)1228static void get_ddr2_info(struct ast_device *ast, struct ast2300_dram_param *param)
1229{1229{
1230 u32 trap, trap_AC2, trap_MRS;1230 u32 trap, trap_AC2, trap_MRS;
1231 1231
@@ -1472,7 +1472,7 @@ static void get_ddr2_info(struct ast_private *ast, struct ast2300_dram_param *pa · 240 unmodified lines
1472 }1472 }
1473}1473}
1474 1474
1475static void ddr2_init(struct ast_private *ast, struct ast2300_dram_param *param)1475static void ddr2_init(struct ast_device *ast, struct ast2300_dram_param *param)
1476{1476{
1477 u32 data, data2, retry = 0;1477 u32 data, data2, retry = 0;
1478 1478
@@ -1600,7 +1600,7 @@ ddr2_init_start: · 121 unmodified lines
1600 1600
1601static void ast_post_chip_2300(struct drm_device *dev)1601static void ast_post_chip_2300(struct drm_device *dev)
1602{1602{
1603 struct ast_private *ast = to_ast_private(dev);1603 struct ast_device *ast = to_ast_device(dev);
1604 struct ast2300_dram_param param;1604 struct ast2300_dram_param param;
1605 u32 temp;1605 u32 temp;
1606 u8 reg;1606 u8 reg;
@@ -1681,7 +1681,7 @@ static void ast_post_chip_2300(struct drm_device *dev) · 74 unmodified lines
1681 } while ((reg & 0x40) == 0);1681 } while ((reg & 0x40) == 0);
1682}1682}
1683 1683
1684static bool cbr_test_2500(struct ast_private *ast)1684static bool cbr_test_2500(struct ast_device *ast)
1685{1685{
1686 ast_moutdwm(ast, 0x1E6E0074, 0x0000FFFF);1686 ast_moutdwm(ast, 0x1E6E0074, 0x0000FFFF);
1687 ast_moutdwm(ast, 0x1E6E007C, 0xFF00FF00);1687 ast_moutdwm(ast, 0x1E6E007C, 0xFF00FF00);
@@ -1692,7 +1692,7 @@ static bool cbr_test_2500(struct ast_private *ast) · 4 unmodified lines
1692 return true;1692 return true;
1693}1693}
1694 1694
1695static bool ddr_test_2500(struct ast_private *ast)1695static bool ddr_test_2500(struct ast_device *ast)
1696{1696{
1697 ast_moutdwm(ast, 0x1E6E0074, 0x0000FFFF);1697 ast_moutdwm(ast, 0x1E6E0074, 0x0000FFFF);
1698 ast_moutdwm(ast, 0x1E6E007C, 0xFF00FF00);1698 ast_moutdwm(ast, 0x1E6E007C, 0xFF00FF00);
@@ -1709,7 +1709,7 @@ static bool ddr_test_2500(struct ast_private *ast) · 10 unmodified lines
1709 return true;1709 return true;
1710}1710}
1711 1711
1712static void ddr_init_common_2500(struct ast_private *ast)1712static void ddr_init_common_2500(struct ast_device *ast)
1713{1713{
1714 ast_moutdwm(ast, 0x1E6E0034, 0x00020080);1714 ast_moutdwm(ast, 0x1E6E0034, 0x00020080);
1715 ast_moutdwm(ast, 0x1E6E0008, 0x2003000F);1715 ast_moutdwm(ast, 0x1E6E0008, 0x2003000F);
@@ -1732,7 +1732,7 @@ static void ddr_init_common_2500(struct ast_private *ast) · 16 unmodified lines
1732 ast_moutdwm(ast, 0x1E6E024C, 0x80808080);1732 ast_moutdwm(ast, 0x1E6E024C, 0x80808080);
1733}1733}
1734 1734
1735static void ddr_phy_init_2500(struct ast_private *ast)1735static void ddr_phy_init_2500(struct ast_device *ast)
1736{1736{
1737 u32 data, pass, timecnt;1737 u32 data, pass, timecnt;
1738 1738
@@ -1766,7 +1766,7 @@ static void ddr_phy_init_2500(struct ast_private *ast) · 27 unmodified lines
1766 * 4Gb : 0x80000000 ~ 0x9FFFFFFF1766 * 4Gb : 0x80000000 ~ 0x9FFFFFFF
1767 * 8Gb : 0x80000000 ~ 0xBFFFFFFF1767 * 8Gb : 0x80000000 ~ 0xBFFFFFFF
1768 */1768 */
1769static void check_dram_size_2500(struct ast_private *ast, u32 tRFC)1769static void check_dram_size_2500(struct ast_device *ast, u32 tRFC)
1770{1770{
1771 u32 reg_04, reg_14;1771 u32 reg_04, reg_14;
1772 1772
@@ -1797,7 +1797,7 @@ static void check_dram_size_2500(struct ast_private *ast, u32 tRFC) · 24 unmodified lines
1797 ast_moutdwm(ast, 0x1E6E0014, reg_14);1797 ast_moutdwm(ast, 0x1E6E0014, reg_14);
1798}1798}
1799 1799
1800static void enable_cache_2500(struct ast_private *ast)1800static void enable_cache_2500(struct ast_device *ast)
1801{1801{
1802 u32 reg_04, data;1802 u32 reg_04, data;
1803 1803
@@ -1810,7 +1810,7 @@ static void enable_cache_2500(struct ast_private *ast) · 6 unmodified lines
1810 ast_moutdwm(ast, 0x1E6E0004, reg_04 | 0x400);1810 ast_moutdwm(ast, 0x1E6E0004, reg_04 | 0x400);
1811}1811}
1812 1812
1813static void set_mpll_2500(struct ast_private *ast)1813static void set_mpll_2500(struct ast_device *ast)
1814{1814{
1815 u32 addr, data, param;1815 u32 addr, data, param;
1816 1816
@@ -1837,7 +1837,7 @@ static void set_mpll_2500(struct ast_private *ast) · 20 unmodified lines
1837 udelay(100);1837 udelay(100);
1838}1838}
1839 1839
1840static void reset_mmc_2500(struct ast_private *ast)1840static void reset_mmc_2500(struct ast_device *ast)
1841{1841{
1842 ast_moutdwm(ast, 0x1E78505C, 0x00000004);1842 ast_moutdwm(ast, 0x1E78505C, 0x00000004);
1843 ast_moutdwm(ast, 0x1E785044, 0x00000001);1843 ast_moutdwm(ast, 0x1E785044, 0x00000001);
@@ -1848,7 +1848,7 @@ static void reset_mmc_2500(struct ast_private *ast) · 4 unmodified lines
1848 ast_moutdwm(ast, 0x1E6E0000, 0xFC600309);1848 ast_moutdwm(ast, 0x1E6E0000, 0xFC600309);
1849}1849}
1850 1850
1851static void ddr3_init_2500(struct ast_private *ast, const u32 *ddr_table)1851static void ddr3_init_2500(struct ast_device *ast, const u32 *ddr_table)
1852{1852{
1853 1853
1854 ast_moutdwm(ast, 0x1E6E0004, 0x00000303);1854 ast_moutdwm(ast, 0x1E6E0004, 0x00000303);
@@ -1892,7 +1892,7 @@ static void ddr3_init_2500(struct ast_private *ast, const u32 *ddr_table) · 37 unmodified lines
1892 ast_moutdwm(ast, 0x1E6E0038, 0xFFFFFF00);1892 ast_moutdwm(ast, 0x1E6E0038, 0xFFFFFF00);
1893}1893}
1894 1894
1895static void ddr4_init_2500(struct ast_private *ast, const u32 *ddr_table)1895static void ddr4_init_2500(struct ast_device *ast, const u32 *ddr_table)
1896{1896{
1897 u32 data, data2, pass, retrycnt;1897 u32 data, data2, pass, retrycnt;
1898 u32 ddr_vref, phy_vref;1898 u32 ddr_vref, phy_vref;
@@ -2002,7 +2002,7 @@ static void ddr4_init_2500(struct ast_private *ast, const u32 *ddr_table) · 103 unmodified lines
2002 ast_moutdwm(ast, 0x1E6E0038, 0xFFFFFF00);2002 ast_moutdwm(ast, 0x1E6E0038, 0xFFFFFF00);
2003}2003}
2004 2004
2005static bool ast_dram_init_2500(struct ast_private *ast)2005static bool ast_dram_init_2500(struct ast_device *ast)
2006{2006{
2007 u32 data;2007 u32 data;
2008 u32 max_tries = 5;2008 u32 max_tries = 5;
@@ -2030,7 +2030,7 @@ static bool ast_dram_init_2500(struct ast_private *ast) · 21 unmodified lines
2030 return true;2030 return true;
2031}2031}
2032 2032
2033void ast_patch_ahb_2500(struct ast_private *ast)2033void ast_patch_ahb_2500(struct ast_device *ast)
2034{2034{
2035 u32 data;2035 u32 data;
2036 2036
@@ -2066,7 +2066,7 @@ void ast_patch_ahb_2500(struct ast_private *ast) · 29 unmodified lines
2066 2066
2067void ast_post_chip_2500(struct drm_device *dev)2067void ast_post_chip_2500(struct drm_device *dev)
2068{2068{
2069 struct ast_private *ast = to_ast_private(dev);2069 struct ast_device *ast = to_ast_device(dev);
2070 u32 temp;2070 u32 temp;
2071 u8 reg;2071 u8 reg;
2072 2072
drivers/gpu/drm/bridge/Kconfig+1−1
@@ -326,7 +326,7 @@ config DRM_TI_DLPC3433 · 325 unmodified lines
326 input that produces a DMD output in RGB565, RGB666, RGB888326 input that produces a DMD output in RGB565, RGB666, RGB888
327 formats.327 formats.
328 328
329 It supports upto 720p resolution with 60 and 120 Hz refresh329 It supports up to 720p resolution with 60 and 120 Hz refresh
330 rates.330 rates.
331 331
332config DRM_TI_TFP410332config DRM_TI_TFP410
drivers/gpu/drm/bridge/panel.c+2−0
@@ -81,6 +81,8 @@ static int panel_bridge_attach(struct drm_bridge *bridge, · 80 unmodified lines
81 return ret;81 return ret;
82 }82 }
83 83
84 drm_panel_bridge_set_orientation(connector, bridge);
85
84 drm_connector_attach_encoder(&panel_bridge->connector,86 drm_connector_attach_encoder(&panel_bridge->connector,
85 bridge->encoder);87 bridge->encoder);
86 88
drivers/gpu/drm/bridge/tc358762.c+1−0
@@ -229,6 +229,7 @@ static int tc358762_probe(struct mipi_dsi_device *dsi) · 228 unmodified lines
229 ctx->bridge.funcs = &tc358762_bridge_funcs;229 ctx->bridge.funcs = &tc358762_bridge_funcs;
230 ctx->bridge.type = DRM_MODE_CONNECTOR_DPI;230 ctx->bridge.type = DRM_MODE_CONNECTOR_DPI;
231 ctx->bridge.of_node = dev->of_node;231 ctx->bridge.of_node = dev->of_node;
232 ctx->bridge.pre_enable_prev_first = true;
232 233
233 drm_bridge_add(&ctx->bridge);234 drm_bridge_add(&ctx->bridge);
234 235
drivers/gpu/drm/drm_atomic_helper.c+16−4
@@ -2702,6 +2702,11 @@ void drm_atomic_helper_commit_planes(struct drm_device *dev, · 2701 unmodified lines
2702 funcs->atomic_disable(plane, old_state);2702 funcs->atomic_disable(plane, old_state);
2703 } else if (new_plane_state->crtc || disabling) {2703 } else if (new_plane_state->crtc || disabling) {
2704 funcs->atomic_update(plane, old_state);2704 funcs->atomic_update(plane, old_state);
2705
2706 if (!disabling && funcs->atomic_enable) {
2707 if (drm_atomic_plane_enabling(old_plane_state, new_plane_state))
2708 funcs->atomic_enable(plane, old_state);
2709 }
2705 }2710 }
2706 }2711 }
2707 2712
@@ -2762,6 +2767,7 @@ drm_atomic_helper_commit_planes_on_crtc(struct drm_crtc_state *old_crtc_state) · 54 unmodified lines
2762 struct drm_plane_state *new_plane_state =2767 struct drm_plane_state *new_plane_state =
2763 drm_atomic_get_new_plane_state(old_state, plane);2768 drm_atomic_get_new_plane_state(old_state, plane);
2764 const struct drm_plane_helper_funcs *plane_funcs;2769 const struct drm_plane_helper_funcs *plane_funcs;
2770 bool disabling;
2765 2771
2766 plane_funcs = plane->helper_private;2772 plane_funcs = plane->helper_private;
2767 2773
@@ -2771,12 +2777,18 @@ drm_atomic_helper_commit_planes_on_crtc(struct drm_crtc_state *old_crtc_state) · 3 unmodified lines
2771 WARN_ON(new_plane_state->crtc &&2777 WARN_ON(new_plane_state->crtc &&
2772 new_plane_state->crtc != crtc);2778 new_plane_state->crtc != crtc);
2773 2779
2774 if (drm_atomic_plane_disabling(old_plane_state, new_plane_state) &&2780 disabling = drm_atomic_plane_disabling(old_plane_state, new_plane_state);
2775 plane_funcs->atomic_disable)2781
2782 if (disabling && plane_funcs->atomic_disable) {
2776 plane_funcs->atomic_disable(plane, old_state);2783 plane_funcs->atomic_disable(plane, old_state);
2777 else if (new_plane_state->crtc ||2784 } else if (new_plane_state->crtc || disabling) {
2778 drm_atomic_plane_disabling(old_plane_state, new_plane_state))
2779 plane_funcs->atomic_update(plane, old_state);2785 plane_funcs->atomic_update(plane, old_state);
2786
2787 if (!disabling && plane_funcs->atomic_enable) {
2788 if (drm_atomic_plane_enabling(old_plane_state, new_plane_state))
2789 plane_funcs->atomic_enable(plane, old_state);
2790 }
2791 }
2780 }2792 }
2781 2793
2782 if (crtc_funcs && crtc_funcs->atomic_flush)2794 if (crtc_funcs && crtc_funcs->atomic_flush)
drivers/gpu/drm/drm_connector.c+20−8
@@ -33,9 +33,11 @@ · 32 unmodified lines
33#include <drm/drm_sysfs.h>33#include <drm/drm_sysfs.h>
34#include <drm/drm_utils.h>34#include <drm/drm_utils.h>
35 35
36#include <linux/fb.h>36#include <linux/property.h>
37#include <linux/uaccess.h>37#include <linux/uaccess.h>
38 38
39#include <video/cmdline.h>
40
39#include "drm_crtc_internal.h"41#include "drm_crtc_internal.h"
40#include "drm_internal.h"42#include "drm_internal.h"
41 43
@@ -154,9 +156,10 @@ EXPORT_SYMBOL(drm_get_connector_type_name); · 112 unmodified lines
154static void drm_connector_get_cmdline_mode(struct drm_connector *connector)156static void drm_connector_get_cmdline_mode(struct drm_connector *connector)
155{157{
156 struct drm_cmdline_mode *mode = &connector->cmdline_mode;158 struct drm_cmdline_mode *mode = &connector->cmdline_mode;
157 char *option = NULL;159 const char *option;
158 160
159 if (fb_get_options(connector->name, &option))161 option = video_get_options(connector->name);
162 if (!option)
160 return;163 return;
161 164
162 if (!drm_mode_parse_command_line_for_connector(option,165 if (!drm_mode_parse_command_line_for_connector(option,
@@ -1446,6 +1449,20 @@ static const struct drm_prop_enum_list dp_colorspaces[] = { · 1283 unmodified lines
1446 * a firmware handled hotkey. Therefor userspace must not include the1449 * a firmware handled hotkey. Therefor userspace must not include the
1447 * privacy-screen sw-state in an atomic commit unless it wants to change1450 * privacy-screen sw-state in an atomic commit unless it wants to change
1448 * its value.1451 * its value.
1452 *
1453 * left margin, right margin, top margin, bottom margin:
1454 * Add margins to the connector's viewport. This is typically used to
1455 * mitigate underscan on TVs.
1456 *
1457 * The value is the size in pixels of the black border which will be
1458 * added. The attached CRTC's content will be scaled to fill the whole
1459 * area inside the margin.
1460 *
1461 * The margins configuration might be sent to the sink, e.g. via HDMI AVI
1462 * InfoFrames.
1463 *
1464 * Drivers can set up these properties by calling
1465 * drm_mode_create_tv_margin_properties().
1449 */1466 */
1450 1467
1451int drm_connector_create_standard_properties(struct drm_device *dev)1468int drm_connector_create_standard_properties(struct drm_device *dev)
@@ -1590,10 +1607,6 @@ EXPORT_SYMBOL(drm_connector_attach_dp_subconnector_property); · 138 unmodified lines
1590 1607
1591/*1608/*
1592 * TODO: Document the properties:1609 * TODO: Document the properties:
1593 * - left margin
1594 * - right margin
1595 * - top margin
1596 * - bottom margin
1597 * - brightness1610 * - brightness
1598 * - contrast1611 * - contrast
1599 * - flicker reduction1612 * - flicker reduction
@@ -1602,7 +1615,6 @@ EXPORT_SYMBOL(drm_connector_attach_dp_subconnector_property); · 2 unmodified lines
1602 * - overscan1615 * - overscan
1603 * - saturation1616 * - saturation
1604 * - select subconnector1617 * - select subconnector
1605 * - subconnector
1606 */1618 */
1607/**1619/**
1608 * DOC: Analog TV Connector Properties1620 * DOC: Analog TV Connector Properties
drivers/gpu/drm/drm_displayid.c+53−9
@@ -7,13 +7,29 @@ · 6 unmodified lines
7#include <drm/drm_edid.h>7#include <drm/drm_edid.h>
8#include <drm/drm_print.h>8#include <drm/drm_print.h>
9 9
10static int validate_displayid(const u8 *displayid, int length, int idx)10static const struct displayid_header *
11displayid_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
23static const struct displayid_header *
24validate_displayid(const u8 *displayid, int length, int idx)
11{25{
12 int i, dispid_length;26 int i, dispid_length;
13 u8 csum = 0;27 u8 csum = 0;
14 const struct displayid_header *base;28 const struct displayid_header *base;
15 29
16 base = (const struct displayid_header *)&displayid[idx];30 base = displayid_get_header(displayid, length, idx);
31 if (IS_ERR(base))
32 return base;
17 33
18 DRM_DEBUG_KMS("base revision 0x%x, length %d, %d %d\n",34 DRM_DEBUG_KMS("base revision 0x%x, length %d, %d %d\n",
19 base->rev, base->bytes, base->prod_id, base->ext_count);35 base->rev, base->bytes, base->prod_id, base->ext_count);
@@ -21,16 +37,16 @@ static int validate_displayid(const u8 *displayid, int length, int idx) · 1 unmodified line
21 /* +1 for DispID checksum */37 /* +1 for DispID checksum */
22 dispid_length = sizeof(*base) + base->bytes + 1;38 dispid_length = sizeof(*base) + base->bytes + 1;
23 if (dispid_length > length - idx)39 if (dispid_length > length - idx)
24 return -EINVAL;40 return ERR_PTR(-EINVAL);
25 41
26 for (i = 0; i < dispid_length; i++)42 for (i = 0; i < dispid_length; i++)
27 csum += displayid[idx + i];43 csum += displayid[idx + i];
28 if (csum) {44 if (csum) {
29 DRM_NOTE("DisplayID checksum invalid, remainder is %d\n", csum);45 DRM_NOTE("DisplayID checksum invalid, remainder is %d\n", csum);
30 return -EINVAL;46 return ERR_PTR(-EINVAL);
31 }47 }
32 48
33 return 0;49 return base;
34}50}
35 51
36static const u8 *drm_find_displayid_extension(const struct drm_edid *drm_edid,52static const u8 *drm_find_displayid_extension(const struct drm_edid *drm_edid,
@@ -39,7 +55,6 @@ static const u8 *drm_find_displayid_extension(const struct drm_edid *drm_edid, · 2 unmodified lines
39{55{
40 const u8 *displayid = drm_find_edid_extension(drm_edid, DISPLAYID_EXT, ext_index);56 const u8 *displayid = drm_find_edid_extension(drm_edid, DISPLAYID_EXT, ext_index);
41 const struct displayid_header *base;57 const struct displayid_header *base;
42 int ret;
43 58
44 if (!displayid)59 if (!displayid)
45 return NULL;60 return NULL;
@@ -48,11 +63,10 @@ static const u8 *drm_find_displayid_extension(const struct drm_edid *drm_edid, · 2 unmodified lines
48 *length = EDID_LENGTH - 1;63 *length = EDID_LENGTH - 1;
49 *idx = 1;64 *idx = 1;
50 65
51 ret = validate_displayid(displayid, *length, *idx);66 base = validate_displayid(displayid, *length, *idx);
52 if (ret)67 if (IS_ERR(base))
53 return NULL;68 return NULL;
54 69
55 base = (const struct displayid_header *)&displayid[*idx];
56 *length = *idx + sizeof(*base) + base->bytes;70 *length = *idx + sizeof(*base) + base->bytes;
57 71
58 return displayid;72 return displayid;
@@ -109,6 +123,9 @@ __displayid_iter_next(struct displayid_iter *iter) · 50 unmodified lines
109 }123 }
110 124
111 for (;;) {125 for (;;) {
126 /* The first section we encounter is the base section */
127 bool base_section = !iter->section;
128
112 iter->section = drm_find_displayid_extension(iter->drm_edid,129 iter->section = drm_find_displayid_extension(iter->drm_edid,
113 &iter->length,130 &iter->length,
114 &iter->idx,131 &iter->idx,
@@ -118,6 +135,18 @@ __displayid_iter_next(struct displayid_iter *iter) · 3 unmodified lines
118 return NULL;135 return NULL;
119 }136 }
120 137
138 /* Save the structure version and primary use case. */
139 if (base_section) {
140 const struct displayid_header *base;
141
142 base = displayid_get_header(iter->section, iter->length,
143 iter->idx);
144 if (!IS_ERR(base)) {
145 iter->version = base->rev;
146 iter->primary_use = base->prod_id;
147 }
148 }
149
121 iter->idx += sizeof(struct displayid_header);150 iter->idx += sizeof(struct displayid_header);
122 151
123 block = displayid_iter_block(iter);152 block = displayid_iter_block(iter);
@@ -130,3 +159,18 @@ void displayid_iter_end(struct displayid_iter *iter) · 6 unmodified lines
130{159{
131 memset(iter, 0, sizeof(*iter));160 memset(iter, 0, sizeof(*iter));
132}161}
162
163/* DisplayID Structure Version/Revision from the Base Section. */
164u8 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 */
173u8 displayid_primary_use(const struct displayid_iter *iter)
174{
175 return iter->primary_use;
176}
drivers/gpu/drm/drm_dumb_buffers.c+1−4
@@ -139,10 +139,7 @@ int drm_mode_destroy_dumb(struct drm_device *dev, u32 handle, · 138 unmodified lines
139 if (!dev->driver->dumb_create)139 if (!dev->driver->dumb_create)
140 return -ENOSYS;140 return -ENOSYS;
141 141
142 if (dev->driver->dumb_destroy)142 return drm_gem_handle_delete(file_priv, handle);
143 return dev->driver->dumb_destroy(file_priv, dev, handle);
144 else
145 return drm_gem_dumb_destroy(file_priv, dev, handle);
146}143}
147 144
148int drm_mode_destroy_dumb_ioctl(struct drm_device *dev,145int drm_mode_destroy_dumb_ioctl(struct drm_device *dev,
drivers/gpu/drm/drm_edid.c+56−9
@@ -3424,10 +3424,6 @@ static struct drm_display_mode *drm_mode_detailed(struct drm_connector *connecto · 3423 unmodified lines
3424 connector->base.id, connector->name);3424 connector->base.id, connector->name);
3425 return NULL;3425 return NULL;
3426 }3426 }
3427 if (!(pt->misc & DRM_EDID_PT_SEPARATE_SYNC)) {
3428 drm_dbg_kms(dev, "[CONNECTOR:%d:%s] Composite sync not supported\n",
3429 connector->base.id, connector->name);
3430 }
3431 3427
3432 /* it is incorrect if hsync/vsync width is zero */3428 /* it is incorrect if hsync/vsync width is zero */
3433 if (!hsync_pulse_width || !vsync_pulse_width) {3429 if (!hsync_pulse_width || !vsync_pulse_width) {
@@ -3474,10 +3470,27 @@ static struct drm_display_mode *drm_mode_detailed(struct drm_connector *connecto · 40 unmodified lines
3474 if (info->quirks & EDID_QUIRK_DETAILED_SYNC_PP) {3470 if (info->quirks & EDID_QUIRK_DETAILED_SYNC_PP) {
3475 mode->flags |= DRM_MODE_FLAG_PHSYNC | DRM_MODE_FLAG_PVSYNC;3471 mode->flags |= DRM_MODE_FLAG_PHSYNC | DRM_MODE_FLAG_PVSYNC;
3476 } else {3472 } else {
3477 mode->flags |= (pt->misc & DRM_EDID_PT_HSYNC_POSITIVE) ?3473 switch (pt->misc & DRM_EDID_PT_SYNC_MASK) {
3478 DRM_MODE_FLAG_PHSYNC : DRM_MODE_FLAG_NHSYNC;3474 case DRM_EDID_PT_ANALOG_CSYNC:
3479 mode->flags |= (pt->misc & DRM_EDID_PT_VSYNC_POSITIVE) ?3475 case DRM_EDID_PT_BIPOLAR_ANALOG_CSYNC:
3480 DRM_MODE_FLAG_PVSYNC : DRM_MODE_FLAG_NVSYNC;3476 drm_dbg_kms(dev, "[CONNECTOR:%d:%s] Analog composite sync!\n",
3477 connector->base.id, connector->name);
3478 mode->flags |= DRM_MODE_FLAG_CSYNC | DRM_MODE_FLAG_NCSYNC;
3479 break;
3480 case DRM_EDID_PT_DIGITAL_CSYNC:
3481 drm_dbg_kms(dev, "[CONNECTOR:%d:%s] Digital composite sync!\n",
3482 connector->base.id, connector->name);
3483 mode->flags |= DRM_MODE_FLAG_CSYNC;
3484 mode->flags |= (pt->misc & DRM_EDID_PT_HSYNC_POSITIVE) ?
3485 DRM_MODE_FLAG_PCSYNC : DRM_MODE_FLAG_NCSYNC;
3486 break;
3487 case DRM_EDID_PT_DIGITAL_SEPARATE_SYNC:
3488 mode->flags |= (pt->misc & DRM_EDID_PT_HSYNC_POSITIVE) ?
3489 DRM_MODE_FLAG_PHSYNC : DRM_MODE_FLAG_NHSYNC;
3490 mode->flags |= (pt->misc & DRM_EDID_PT_VSYNC_POSITIVE) ?
3491 DRM_MODE_FLAG_PVSYNC : DRM_MODE_FLAG_NVSYNC;
3492 break;
3493 }
3481 }3494 }
3482 3495
3483set_size:3496set_size:
@@ -6433,6 +6446,29 @@ static void drm_reset_display_info(struct drm_connector *connector) · 2949 unmodified lines
6433 info->quirks = 0;6446 info->quirks = 0;
6434}6447}
6435 6448
6449static 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
6436static void update_display_info(struct drm_connector *connector,6472static void update_display_info(struct drm_connector *connector,
6437 const struct drm_edid *drm_edid)6473 const struct drm_edid *drm_edid)
6438{6474{
@@ -6463,6 +6499,8 @@ static void update_display_info(struct drm_connector *connector, · 24 unmodified lines
6463 info->color_formats |= DRM_COLOR_FORMAT_RGB444;6499 info->color_formats |= DRM_COLOR_FORMAT_RGB444;
6464 drm_parse_cea_ext(connector, drm_edid);6500 drm_parse_cea_ext(connector, drm_edid);
6465 6501
6502 update_displayid_info(connector, drm_edid);
6503
6466 /*6504 /*
6467 * Digital sink with "DFP 1.x compliant TMDS" according to EDID 1.3?6505 * Digital sink with "DFP 1.x compliant TMDS" according to EDID 1.3?
6468 *6506 *
@@ -7242,6 +7280,15 @@ static void drm_parse_tiled_block(struct drm_connector *connector, · 773 unmodified lines
7242 }7280 }
7243}7281}
7244 7282
7283static 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
7245static void _drm_update_tile_info(struct drm_connector *connector,7292static void _drm_update_tile_info(struct drm_connector *connector,
7246 const struct drm_edid *drm_edid)7293 const struct drm_edid *drm_edid)
7247{7294{
@@ -7252,7 +7299,7 @@ static void _drm_update_tile_info(struct drm_connector *connector, · 4 unmodified lines
7252 7299
7253 displayid_iter_edid_begin(drm_edid, &iter);7300 displayid_iter_edid_begin(drm_edid, &iter);
7254 displayid_iter_for_each(block, &iter) {7301 displayid_iter_for_each(block, &iter) {
7255 if (block->tag == DATA_BLOCK_TILED_DISPLAY)7302 if (displayid_is_tiled_block(&iter, block))
7256 drm_parse_tiled_block(connector, block);7303 drm_parse_tiled_block(connector, block);
7257 }7304 }
7258 displayid_iter_end(&iter);7305 displayid_iter_end(&iter);
drivers/gpu/drm/drm_gem.c+18−7
@@ -336,13 +336,6 @@ out: · 335 unmodified lines
336}336}
337EXPORT_SYMBOL_GPL(drm_gem_dumb_map_offset);337EXPORT_SYMBOL_GPL(drm_gem_dumb_map_offset);
338 338
339int drm_gem_dumb_destroy(struct drm_file *file,
340 struct drm_device *dev,
341 u32 handle)
342{
343 return drm_gem_handle_delete(file, handle);
344}
345
346/**339/**
347 * drm_gem_handle_create_tail - internal functions to create a handle340 * drm_gem_handle_create_tail - internal functions to create a handle
348 * @file_priv: drm file-private structure to register the handle for341 * @file_priv: drm file-private structure to register the handle for
@@ -1466,3 +1459,21 @@ tail: · 1117 unmodified lines
1466 return freed;1459 return freed;
1467}1460}
1468EXPORT_SYMBOL(drm_gem_lru_scan);1461EXPORT_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 */
1467int 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}
1479EXPORT_SYMBOL(drm_gem_evict);
drivers/gpu/drm/drm_gem_shmem_helper.c+36−29
@@ -141,7 +141,7 @@ void drm_gem_shmem_free(struct drm_gem_shmem_object *shmem) · 140 unmodified lines
141{141{
142 struct drm_gem_object *obj = &shmem->base;142 struct drm_gem_object *obj = &shmem->base;
143 143
144 WARN_ON(shmem->vmap_use_count);144 drm_WARN_ON(obj->dev, shmem->vmap_use_count);
145 145
146 if (obj->import_attach) {146 if (obj->import_attach) {
147 drm_prime_gem_destroy(obj, shmem->sgt);147 drm_prime_gem_destroy(obj, shmem->sgt);
@@ -156,7 +156,7 @@ void drm_gem_shmem_free(struct drm_gem_shmem_object *shmem) · 8 unmodified lines
156 drm_gem_shmem_put_pages(shmem);156 drm_gem_shmem_put_pages(shmem);
157 }157 }
158 158
159 WARN_ON(shmem->pages_use_count);159 drm_WARN_ON(obj->dev, shmem->pages_use_count);
160 160
161 drm_gem_object_release(obj);161 drm_gem_object_release(obj);
162 mutex_destroy(&shmem->pages_lock);162 mutex_destroy(&shmem->pages_lock);
@@ -175,7 +175,8 @@ static int drm_gem_shmem_get_pages_locked(struct drm_gem_shmem_object *shmem) · 12 unmodified lines
175 175
176 pages = drm_gem_get_pages(obj);176 pages = drm_gem_get_pages(obj);
177 if (IS_ERR(pages)) {177 if (IS_ERR(pages)) {
178 DRM_DEBUG_KMS("Failed to get pages (%ld)\n", PTR_ERR(pages));178 drm_dbg_kms(obj->dev, "Failed to get pages (%ld)\n",
179 PTR_ERR(pages));
179 shmem->pages_use_count = 0;180 shmem->pages_use_count = 0;
180 return PTR_ERR(pages);181 return PTR_ERR(pages);
181 }182 }
@@ -207,9 +208,10 @@ static int drm_gem_shmem_get_pages_locked(struct drm_gem_shmem_object *shmem) · 25 unmodified lines
207 */208 */
208int drm_gem_shmem_get_pages(struct drm_gem_shmem_object *shmem)209int drm_gem_shmem_get_pages(struct drm_gem_shmem_object *shmem)
209{210{
211 struct drm_gem_object *obj = &shmem->base;
210 int ret;212 int ret;
211 213
212 WARN_ON(shmem->base.import_attach);214 drm_WARN_ON(obj->dev, obj->import_attach);
213 215
214 ret = mutex_lock_interruptible(&shmem->pages_lock);216 ret = mutex_lock_interruptible(&shmem->pages_lock);
215 if (ret)217 if (ret)
@@ -225,7 +227,7 @@ static void drm_gem_shmem_put_pages_locked(struct drm_gem_shmem_object *shmem) · 9 unmodified lines
225{227{
226 struct drm_gem_object *obj = &shmem->base;228 struct drm_gem_object *obj = &shmem->base;
227 229
228 if (WARN_ON_ONCE(!shmem->pages_use_count))230 if (drm_WARN_ON_ONCE(obj->dev, !shmem->pages_use_count))
229 return;231 return;
230 232
231 if (--shmem->pages_use_count > 0)233 if (--shmem->pages_use_count > 0)
@@ -268,7 +270,9 @@ EXPORT_SYMBOL(drm_gem_shmem_put_pages); · 36 unmodified lines
268 */270 */
269int drm_gem_shmem_pin(struct drm_gem_shmem_object *shmem)271int drm_gem_shmem_pin(struct drm_gem_shmem_object *shmem)
270{272{
271 WARN_ON(shmem->base.import_attach);273 struct drm_gem_object *obj = &shmem->base;
274
275 drm_WARN_ON(obj->dev, obj->import_attach);
272 276
273 return drm_gem_shmem_get_pages(shmem);277 return drm_gem_shmem_get_pages(shmem);
274}278}
@@ -283,7 +287,9 @@ EXPORT_SYMBOL(drm_gem_shmem_pin); · 8 unmodified lines
283 */287 */
284void drm_gem_shmem_unpin(struct drm_gem_shmem_object *shmem)288void drm_gem_shmem_unpin(struct drm_gem_shmem_object *shmem)
285{289{
286 WARN_ON(shmem->base.import_attach);290 struct drm_gem_object *obj = &shmem->base;
291
292 drm_WARN_ON(obj->dev, obj->import_attach);
287 293
288 drm_gem_shmem_put_pages(shmem);294 drm_gem_shmem_put_pages(shmem);
289}295}
@@ -295,24 +301,22 @@ static int drm_gem_shmem_vmap_locked(struct drm_gem_shmem_object *shmem, · 5 unmodified lines
295 struct drm_gem_object *obj = &shmem->base;301 struct drm_gem_object *obj = &shmem->base;
296 int ret = 0;302 int ret = 0;
297 303
298 if (shmem->vmap_use_count++ > 0) {
299 iosys_map_set_vaddr(map, shmem->vaddr);
300 return 0;
301 }
302
303 if (obj->import_attach) {304 if (obj->import_attach) {
304 ret = dma_buf_vmap(obj->import_attach->dmabuf, map);305 ret = dma_buf_vmap(obj->import_attach->dmabuf, map);
305 if (!ret) {306 if (!ret) {
306 if (WARN_ON(map->is_iomem)) {307 if (drm_WARN_ON(obj->dev, map->is_iomem)) {
307 dma_buf_vunmap(obj->import_attach->dmabuf, map);308 dma_buf_vunmap(obj->import_attach->dmabuf, map);
308 ret = -EIO;309 return -EIO;
309 goto err_put_pages;
310 }310 }
311 shmem->vaddr = map->vaddr;
312 }311 }
313 } else {312 } else {
314 pgprot_t prot = PAGE_KERNEL;313 pgprot_t prot = PAGE_KERNEL;
315 314
315 if (shmem->vmap_use_count++ > 0) {
316 iosys_map_set_vaddr(map, shmem->vaddr);
317 return 0;
318 }
319
316 ret = drm_gem_shmem_get_pages(shmem);320 ret = drm_gem_shmem_get_pages(shmem);
317 if (ret)321 if (ret)
318 goto err_zero_use;322 goto err_zero_use;
@@ -328,7 +332,7 @@ static int drm_gem_shmem_vmap_locked(struct drm_gem_shmem_object *shmem, · 9 unmodified lines
328 }332 }
329 333
330 if (ret) {334 if (ret) {
331 DRM_DEBUG_KMS("Failed to vmap pages, error %d\n", ret);335 drm_dbg_kms(obj->dev, "Failed to vmap pages, error %d\n", ret);
332 goto err_put_pages;336 goto err_put_pages;
333 }337 }
334 338
@@ -378,15 +382,15 @@ static void drm_gem_shmem_vunmap_locked(struct drm_gem_shmem_object *shmem, · 43 unmodified lines
378{382{
379 struct drm_gem_object *obj = &shmem->base;383 struct drm_gem_object *obj = &shmem->base;
380 384
381 if (WARN_ON_ONCE(!shmem->vmap_use_count))
382 return;
383
384 if (--shmem->vmap_use_count > 0)
385 return;
386
387 if (obj->import_attach) {385 if (obj->import_attach) {
388 dma_buf_vunmap(obj->import_attach->dmabuf, map);386 dma_buf_vunmap(obj->import_attach->dmabuf, map);
389 } else {387 } else {
388 if (drm_WARN_ON_ONCE(obj->dev, !shmem->vmap_use_count))
389 return;
390
391 if (--shmem->vmap_use_count > 0)
392 return;
393
390 vunmap(shmem->vaddr);394 vunmap(shmem->vaddr);
391 drm_gem_shmem_put_pages(shmem);395 drm_gem_shmem_put_pages(shmem);
392 }396 }
@@ -461,7 +465,7 @@ void drm_gem_shmem_purge_locked(struct drm_gem_shmem_object *shmem) · 68 unmodified lines
461 struct drm_gem_object *obj = &shmem->base;465 struct drm_gem_object *obj = &shmem->base;
462 struct drm_device *dev = obj->dev;466 struct drm_device *dev = obj->dev;
463 467
464 WARN_ON(!drm_gem_shmem_is_purgeable(shmem));468 drm_WARN_ON(obj->dev, !drm_gem_shmem_is_purgeable(shmem));
465 469
466 dma_unmap_sgtable(dev->dev, shmem->sgt, DMA_BIDIRECTIONAL, 0);470 dma_unmap_sgtable(dev->dev, shmem->sgt, DMA_BIDIRECTIONAL, 0);
467 sg_free_table(shmem->sgt);471 sg_free_table(shmem->sgt);
@@ -550,7 +554,7 @@ static vm_fault_t drm_gem_shmem_fault(struct vm_fault *vmf) · 82 unmodified lines
550 mutex_lock(&shmem->pages_lock);554 mutex_lock(&shmem->pages_lock);
551 555
552 if (page_offset >= num_pages ||556 if (page_offset >= num_pages ||
553 WARN_ON_ONCE(!shmem->pages) ||557 drm_WARN_ON_ONCE(obj->dev, !shmem->pages) ||
554 shmem->madv < 0) {558 shmem->madv < 0) {
555 ret = VM_FAULT_SIGBUS;559 ret = VM_FAULT_SIGBUS;
556 } else {560 } else {
@@ -569,7 +573,7 @@ static void drm_gem_shmem_vm_open(struct vm_area_struct *vma) · 12 unmodified lines
569 struct drm_gem_object *obj = vma->vm_private_data;573 struct drm_gem_object *obj = vma->vm_private_data;
570 struct drm_gem_shmem_object *shmem = to_drm_gem_shmem_obj(obj);574 struct drm_gem_shmem_object *shmem = to_drm_gem_shmem_obj(obj);
571 575
572 WARN_ON(shmem->base.import_attach);576 drm_WARN_ON(obj->dev, obj->import_attach);
573 577
574 mutex_lock(&shmem->pages_lock);578 mutex_lock(&shmem->pages_lock);
575 579
@@ -578,7 +582,7 @@ static void drm_gem_shmem_vm_open(struct vm_area_struct *vma) · 2 unmodified lines
578 * mmap'd, vm_open() just grabs an additional reference for the new582 * mmap'd, vm_open() just grabs an additional reference for the new
579 * mm the vma is getting copied into (ie. on fork()).583 * mm the vma is getting copied into (ie. on fork()).
580 */584 */
581 if (!WARN_ON_ONCE(!shmem->pages_use_count))585 if (!drm_WARN_ON_ONCE(obj->dev, !shmem->pages_use_count))
582 shmem->pages_use_count++;586 shmem->pages_use_count++;
583 587
584 mutex_unlock(&shmem->pages_lock);588 mutex_unlock(&shmem->pages_lock);
@@ -648,6 +652,9 @@ EXPORT_SYMBOL_GPL(drm_gem_shmem_mmap); · 63 unmodified lines
648void drm_gem_shmem_print_info(const struct drm_gem_shmem_object *shmem,652void drm_gem_shmem_print_info(const struct drm_gem_shmem_object *shmem,
649 struct drm_printer *p, unsigned int indent)653 struct drm_printer *p, unsigned int indent)
650{654{
655 if (shmem->base.import_attach)
656 return;
657
651 drm_printf_indent(p, indent, "pages_use_count=%u\n", shmem->pages_use_count);658 drm_printf_indent(p, indent, "pages_use_count=%u\n", shmem->pages_use_count);
652 drm_printf_indent(p, indent, "vmap_use_count=%u\n", shmem->vmap_use_count);659 drm_printf_indent(p, indent, "vmap_use_count=%u\n", shmem->vmap_use_count);
653 drm_printf_indent(p, indent, "vaddr=%p\n", shmem->vaddr);660 drm_printf_indent(p, indent, "vaddr=%p\n", shmem->vaddr);
@@ -672,7 +679,7 @@ struct sg_table *drm_gem_shmem_get_sg_table(struct drm_gem_shmem_object *shmem) · 18 unmodified lines
672{679{
673 struct drm_gem_object *obj = &shmem->base;680 struct drm_gem_object *obj = &shmem->base;
674 681
675 WARN_ON(shmem->base.import_attach);682 drm_WARN_ON(obj->dev, obj->import_attach);
676 683
677 return drm_prime_pages_to_sg(obj->dev, shmem->pages, obj->size >> PAGE_SHIFT);684 return drm_prime_pages_to_sg(obj->dev, shmem->pages, obj->size >> PAGE_SHIFT);
678}685}
@@ -687,7 +694,7 @@ static struct sg_table *drm_gem_shmem_get_pages_sgt_locked(struct drm_gem_shmem_ · 8 unmodified lines
687 if (shmem->sgt)694 if (shmem->sgt)
688 return shmem->sgt;695 return shmem->sgt;
689 696
690 WARN_ON(obj->import_attach);697 drm_WARN_ON(obj->dev, obj->import_attach);
691 698
692 ret = drm_gem_shmem_get_pages_locked(shmem);699 ret = drm_gem_shmem_get_pages_locked(shmem);
693 if (ret)700 if (ret)
drivers/gpu/drm/drm_gem_vram_helper.c+11−0
@@ -916,6 +916,17 @@ static int bo_driver_move(struct ttm_buffer_object *bo, · 915 unmodified lines
916{916{
917 struct drm_gem_vram_object *gbo;917 struct drm_gem_vram_object *gbo;
918 918
919 if (!bo->resource) {
920 if (new_mem->mem_type != TTM_PL_SYSTEM) {
921 hop->mem_type = TTM_PL_SYSTEM;
922 hop->flags = TTM_PL_FLAG_TEMPORARY;
923 return -EMULTIHOP;
924 }
925
926 ttm_bo_move_null(bo, new_mem);
927 return 0;
928 }
929
919 gbo = drm_gem_vram_of_bo(bo);930 gbo = drm_gem_vram_of_bo(bo);
920 931
921 return drm_gem_vram_bo_driver_move(gbo, evict, ctx, new_mem);932 return drm_gem_vram_bo_driver_move(gbo, evict, ctx, new_mem);
drivers/gpu/drm/drm_internal.h+0−3
@@ -178,9 +178,6 @@ void drm_gem_unpin(struct drm_gem_object *obj); · 177 unmodified lines
178int drm_gem_vmap(struct drm_gem_object *obj, struct iosys_map *map);178int drm_gem_vmap(struct drm_gem_object *obj, struct iosys_map *map);
179void drm_gem_vunmap(struct drm_gem_object *obj, struct iosys_map *map);179void drm_gem_vunmap(struct drm_gem_object *obj, struct iosys_map *map);
180 180
181int drm_gem_dumb_destroy(struct drm_file *file, struct drm_device *dev,
182 u32 handle);
183
184/* drm_debugfs.c drm_debugfs_crc.c */181/* drm_debugfs.c drm_debugfs_crc.c */
185#if defined(CONFIG_DEBUG_FS)182#if defined(CONFIG_DEBUG_FS)
186int drm_debugfs_init(struct drm_minor *minor, int minor_id,183int drm_debugfs_init(struct drm_minor *minor, int minor_id,
drivers/gpu/drm/drm_modes.c+1−2
@@ -2339,8 +2339,7 @@ static int drm_mode_parse_cmdline_named_mode(const char *name, · 2338 unmodified lines
2339 * @mode: preallocated drm_cmdline_mode structure to fill out2339 * @mode: preallocated drm_cmdline_mode structure to fill out
2340 *2340 *
2341 * This parses @mode_option command line modeline for modes and options to2341 * This parses @mode_option command line modeline for modes and options to
2342 * configure the connector. If @mode_option is NULL the default command line2342 * configure the connector.
2343 * modeline in fb_mode_option will be parsed instead.
2344 *2343 *
2345 * This uses the same parameters as the fb modedb.c, except for an extra2344 * This uses the same parameters as the fb modedb.c, except for an extra
2346 * force-enable, force-enable-digital and force-disable bit at the end::2345 * force-enable, force-enable-digital and force-disable bit at the end::
drivers/gpu/drm/drm_of.c+51−0
@@ -10,6 +10,7 @@ · 9 unmodified lines
10#include <drm/drm_crtc.h>10#include <drm/drm_crtc.h>
11#include <drm/drm_device.h>11#include <drm/drm_device.h>
12#include <drm/drm_encoder.h>12#include <drm/drm_encoder.h>
13#include <drm/drm_mipi_dsi.h>
13#include <drm/drm_of.h>14#include <drm/drm_of.h>
14#include <drm/drm_panel.h>15#include <drm/drm_panel.h>
15 16
@@ -493,3 +494,53 @@ int drm_of_get_data_lanes_count_ep(const struct device_node *port, · 477 unmodified lines
493 return ret;494 return ret;
494}495}
495EXPORT_SYMBOL_GPL(drm_of_get_data_lanes_count_ep);496EXPORT_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 */
511struct 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}
544EXPORT_SYMBOL_GPL(drm_of_get_dsi_bus);
545
546#endif /* CONFIG_DRM_MIPI_DSI */
drivers/gpu/drm/drm_probe_helper.c+3−2
@@ -590,8 +590,9 @@ retry: · 589 unmodified lines
590 */590 */
591 dev->mode_config.delayed_event = true;591 dev->mode_config.delayed_event = true;
592 if (dev->mode_config.poll_enabled)592 if (dev->mode_config.poll_enabled)
593 schedule_delayed_work(&dev->mode_config.output_poll_work,593 mod_delayed_work(system_wq,
594 0);594 &dev->mode_config.output_poll_work,
595 0);
595 }596 }
596 597
597 /* Re-enable polling in case the global poll config changed. */598 /* Re-enable polling in case the global poll config changed. */
drivers/gpu/drm/drm_suballoc.c+457−0
@@ -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
50static void drm_suballoc_remove_locked(struct drm_suballoc *sa);
51static 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 */
61void 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}
83EXPORT_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 */
93void 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}
112EXPORT_SYMBOL(drm_suballoc_manager_fini);
113
114static 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
127static 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
143static 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
153static 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
162static 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
186static 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 */
213static 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
224static 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 */
312struct drm_suballoc *
313drm_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}
389EXPORT_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 */
398void 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}
421EXPORT_SYMBOL(drm_suballoc_free);
422
423#ifdef CONFIG_DEBUG_FS
424void 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}
453EXPORT_SYMBOL(drm_suballoc_dump_debug_info);
454#endif
455MODULE_AUTHOR("Multiple");
456MODULE_DESCRIPTION("Range suballocator helper");
457MODULE_LICENSE("Dual MIT/GPL");
drivers/gpu/drm/i915/gem/i915_gem_ttm.c+11−4
@@ -472,7 +472,7 @@ static int i915_ttm_shrink(struct drm_i915_gem_object *obj, unsigned int flags) · 471 unmodified lines
472 struct ttm_placement place = {};472 struct ttm_placement place = {};
473 int ret;473 int ret;
474 474
475 if (!bo->ttm || bo->resource->mem_type != TTM_PL_SYSTEM)475 if (!bo->ttm || i915_ttm_cpu_maps_iomem(bo->resource))
476 return 0;476 return 0;
477 477
478 GEM_BUG_ON(!i915_tt->is_shmem);478 GEM_BUG_ON(!i915_tt->is_shmem);
@@ -511,7 +511,13 @@ static void i915_ttm_delete_mem_notify(struct ttm_buffer_object *bo) · 32 unmodified lines
511{511{
512 struct drm_i915_gem_object *obj = i915_ttm_to_gem(bo);512 struct drm_i915_gem_object *obj = i915_ttm_to_gem(bo);
513 513
514 if (bo->resource && !i915_ttm_is_ghost_object(bo)) {514 /*
515 * This gets called twice by ttm, so long as we have a ttm resource or
516 * ttm_tt then we can still safely call this. Due to pipeline-gutting,
517 * we maybe have NULL bo->resource, but in that case we should always
518 * have a ttm alive (like if the pages are swapped out).
519 */
520 if ((bo->resource || bo->ttm) && !i915_ttm_is_ghost_object(bo)) {
515 __i915_gem_object_pages_fini(obj);521 __i915_gem_object_pages_fini(obj);
516 i915_ttm_free_cached_io_rsgt(obj);522 i915_ttm_free_cached_io_rsgt(obj);
517 }523 }
@@ -1067,11 +1073,12 @@ static vm_fault_t vm_fault_ttm(struct vm_fault *vmf) · 549 unmodified lines
1067 .interruptible = true,1073 .interruptible = true,
1068 .no_wait_gpu = true, /* should be idle already */1074 .no_wait_gpu = true, /* should be idle already */
1069 };1075 };
1076 int err;
1070 1077
1071 GEM_BUG_ON(!bo->ttm || !(bo->ttm->page_flags & TTM_TT_FLAG_SWAPPED));1078 GEM_BUG_ON(!bo->ttm || !(bo->ttm->page_flags & TTM_TT_FLAG_SWAPPED));
1072 1079
1073 ret = ttm_bo_validate(bo, i915_ttm_sys_placement(), &ctx);1080 err = ttm_bo_validate(bo, i915_ttm_sys_placement(), &ctx);
1074 if (ret) {1081 if (err) {
1075 dma_resv_unlock(bo->base.resv);1082 dma_resv_unlock(bo->base.resv);
1076 return VM_FAULT_SIGBUS;1083 return VM_FAULT_SIGBUS;
1077 }1084 }
drivers/gpu/drm/i915/gem/i915_gem_ttm.h+1−1
@@ -98,7 +98,7 @@ static inline bool i915_ttm_gtt_binds_lmem(struct ttm_resource *mem) · 97 unmodified lines
98static inline bool i915_ttm_cpu_maps_iomem(struct ttm_resource *mem)98static inline bool i915_ttm_cpu_maps_iomem(struct ttm_resource *mem)
99{99{
100 /* Once / if we support GGTT, this is also false for cached ttm_tts */100 /* Once / if we support GGTT, this is also false for cached ttm_tts */
101 return mem->mem_type != I915_PL_SYSTEM;101 return mem && mem->mem_type != I915_PL_SYSTEM;
102}102}
103 103
104bool i915_ttm_resource_mappable(struct ttm_resource *res);104bool i915_ttm_resource_mappable(struct ttm_resource *res);
drivers/gpu/drm/i915/gem/i915_gem_ttm_move.c+4−0
@@ -711,6 +711,10 @@ int i915_gem_obj_copy_ttm(struct drm_i915_gem_object *dst, · 710 unmodified lines
711 711
712 assert_object_held(dst);712 assert_object_held(dst);
713 assert_object_held(src);713 assert_object_held(src);
714
715 if (GEM_WARN_ON(!src_bo->resource || !dst_bo->resource))
716 return -EINVAL;
717
714 i915_deps_init(&deps, GFP_KERNEL | __GFP_NORETRY | __GFP_NOWARN);718 i915_deps_init(&deps, GFP_KERNEL | __GFP_NORETRY | __GFP_NOWARN);
715 719
716 ret = dma_resv_reserve_fences(src_bo->base.resv, 1);720 ret = dma_resv_reserve_fences(src_bo->base.resv, 1);
drivers/gpu/drm/i915/gem/i915_gem_ttm_pm.c+5−2
@@ -53,7 +53,7 @@ static int i915_ttm_backup(struct i915_gem_apply_to_region *apply, · 52 unmodified lines
53 unsigned int flags;53 unsigned int flags;
54 int err = 0;54 int err = 0;
55 55
56 if (bo->resource->mem_type == I915_PL_SYSTEM || obj->ttm.backup)56 if (!i915_ttm_cpu_maps_iomem(bo->resource) || obj->ttm.backup)
57 return 0;57 return 0;
58 58
59 if (pm_apply->allow_gpu && i915_gem_object_evictable(obj))59 if (pm_apply->allow_gpu && i915_gem_object_evictable(obj))
@@ -187,7 +187,10 @@ static int i915_ttm_restore(struct i915_gem_apply_to_region *apply, · 127 unmodified lines
187 return err;187 return err;
188 188
189 /* Content may have been swapped. */189 /* Content may have been swapped. */
190 err = ttm_tt_populate(backup_bo->bdev, backup_bo->ttm, &ctx);190 if (!backup_bo->resource)
191 err = ttm_bo_validate(backup_bo, i915_ttm_sys_placement(), &ctx);
192 if (!err)
193 err = ttm_tt_populate(backup_bo->bdev, backup_bo->ttm, &ctx);
191 if (!err) {194 if (!err) {
192 err = i915_gem_obj_copy_ttm(obj, backup, pm_apply->allow_gpu,195 err = i915_gem_obj_copy_ttm(obj, backup, pm_apply->allow_gpu,
193 false);196 false);
drivers/gpu/drm/meson/meson_venc.c+2−2
@@ -866,10 +866,10 @@ meson_venc_hdmi_supported_mode(const struct drm_display_mode *mode) · 865 unmodified lines
866 DRM_MODE_FLAG_PVSYNC | DRM_MODE_FLAG_NVSYNC))866 DRM_MODE_FLAG_PVSYNC | DRM_MODE_FLAG_NVSYNC))
867 return MODE_BAD;867 return MODE_BAD;
868 868
869 if (mode->hdisplay < 640 || mode->hdisplay > 1920)869 if (mode->hdisplay < 400 || mode->hdisplay > 1920)
870 return MODE_BAD_HVALUE;870 return MODE_BAD_HVALUE;
871 871
872 if (mode->vdisplay < 480 || mode->vdisplay > 1200)872 if (mode->vdisplay < 480 || mode->vdisplay > 1920)
873 return MODE_BAD_VVALUE;873 return MODE_BAD_VVALUE;
874 874
875 return MODE_OK;875 return MODE_OK;
drivers/gpu/drm/mgag200/mgag200_drv.h+3−0
@@ -375,12 +375,15 @@ int mgag200_primary_plane_helper_atomic_check(struct drm_plane *plane, · 374 unmodified lines
375 struct drm_atomic_state *new_state);375 struct drm_atomic_state *new_state);
376void mgag200_primary_plane_helper_atomic_update(struct drm_plane *plane,376void mgag200_primary_plane_helper_atomic_update(struct drm_plane *plane,
377 struct drm_atomic_state *old_state);377 struct drm_atomic_state *old_state);
378void mgag200_primary_plane_helper_atomic_enable(struct drm_plane *plane,
379 struct drm_atomic_state *state);
378void mgag200_primary_plane_helper_atomic_disable(struct drm_plane *plane,380void mgag200_primary_plane_helper_atomic_disable(struct drm_plane *plane,
379 struct drm_atomic_state *old_state);381 struct drm_atomic_state *old_state);
380#define MGAG200_PRIMARY_PLANE_HELPER_FUNCS \382#define MGAG200_PRIMARY_PLANE_HELPER_FUNCS \
381 DRM_GEM_SHADOW_PLANE_HELPER_FUNCS, \383 DRM_GEM_SHADOW_PLANE_HELPER_FUNCS, \
382 .atomic_check = mgag200_primary_plane_helper_atomic_check, \384 .atomic_check = mgag200_primary_plane_helper_atomic_check, \
383 .atomic_update = mgag200_primary_plane_helper_atomic_update, \385 .atomic_update = mgag200_primary_plane_helper_atomic_update, \
386 .atomic_enable = mgag200_primary_plane_helper_atomic_enable, \
384 .atomic_disable = mgag200_primary_plane_helper_atomic_disable387 .atomic_disable = mgag200_primary_plane_helper_atomic_disable
385 388
386#define MGAG200_PRIMARY_PLANE_FUNCS \389#define MGAG200_PRIMARY_PLANE_FUNCS \
drivers/gpu/drm/mgag200/mgag200_mode.c+12−10
@@ -501,10 +501,6 @@ void mgag200_primary_plane_helper_atomic_update(struct drm_plane *plane, · 500 unmodified lines
501 struct drm_framebuffer *fb = plane_state->fb;501 struct drm_framebuffer *fb = plane_state->fb;
502 struct drm_atomic_helper_damage_iter iter;502 struct drm_atomic_helper_damage_iter iter;
503 struct drm_rect damage;503 struct drm_rect damage;
504 u8 seq1;
505
506 if (!fb)
507 return;
508 504
509 drm_atomic_helper_damage_iter_init(&iter, old_plane_state, plane_state);505 drm_atomic_helper_damage_iter_init(&iter, old_plane_state, plane_state);
510 drm_atomic_for_each_plane_damage(&iter, &damage) {506 drm_atomic_for_each_plane_damage(&iter, &damage) {
@@ -514,13 +510,19 @@ void mgag200_primary_plane_helper_atomic_update(struct drm_plane *plane, · 3 unmodified lines
514 /* Always scanout image at VRAM offset 0 */510 /* Always scanout image at VRAM offset 0 */
515 mgag200_set_startadd(mdev, (u32)0);511 mgag200_set_startadd(mdev, (u32)0);
516 mgag200_set_offset(mdev, fb);512 mgag200_set_offset(mdev, fb);
513}
517 514
518 if (!old_plane_state->crtc && plane_state->crtc) { // enabling515void mgag200_primary_plane_helper_atomic_enable(struct drm_plane *plane,
519 RREG_SEQ(0x01, seq1);516 struct drm_atomic_state *state)
520 seq1 &= ~MGAREG_SEQ1_SCROFF;517{
521 WREG_SEQ(0x01, seq1);518 struct drm_device *dev = plane->dev;
522 msleep(20);519 struct mga_device *mdev = to_mga_device(dev);
523 }520 u8 seq1;
521
522 RREG_SEQ(0x01, seq1);
523 seq1 &= ~MGAREG_SEQ1_SCROFF;
524 WREG_SEQ(0x01, seq1);
525 msleep(20);
524}526}
525 527
526void mgag200_primary_plane_helper_atomic_disable(struct drm_plane *plane,528void mgag200_primary_plane_helper_atomic_disable(struct drm_plane *plane,
drivers/gpu/drm/nouveau/nouveau_bo.c+0−3
@@ -1015,9 +1015,6 @@ nouveau_bo_move(struct ttm_buffer_object *bo, bool evict, · 1014 unmodified lines
1015 if (ret)1015 if (ret)
1016 goto out_ntfy;1016 goto out_ntfy;
1017 1017
1018 if (nvbo->bo.pin_count)
1019 NV_WARN(drm, "Moving pinned object %p!\n", nvbo);
1020
1021 if (drm->client.device.info.family < NV_DEVICE_INFO_V0_TESLA) {1018 if (drm->client.device.info.family < NV_DEVICE_INFO_V0_TESLA) {
1022 ret = nouveau_bo_vm_bind(bo, new_reg, &new_tile);1019 ret = nouveau_bo_vm_bind(bo, new_reg, &new_tile);
1023 if (ret)1020 if (ret)
drivers/gpu/drm/nouveau/nouveau_hwmon.c+5−5
@@ -41,7 +41,7 @@ static ssize_t · 40 unmodified lines
41nouveau_hwmon_show_temp1_auto_point1_pwm(struct device *d,41nouveau_hwmon_show_temp1_auto_point1_pwm(struct device *d,
42 struct device_attribute *a, char *buf)42 struct device_attribute *a, char *buf)
43{43{
44 return snprintf(buf, PAGE_SIZE, "%d\n", 100);44 return sysfs_emit(buf, "%d\n", 100);
45}45}
46static SENSOR_DEVICE_ATTR(temp1_auto_point1_pwm, 0444,46static SENSOR_DEVICE_ATTR(temp1_auto_point1_pwm, 0444,
47 nouveau_hwmon_show_temp1_auto_point1_pwm, NULL, 0);47 nouveau_hwmon_show_temp1_auto_point1_pwm, NULL, 0);
@@ -54,8 +54,8 @@ nouveau_hwmon_temp1_auto_point1_temp(struct device *d, · 6 unmodified lines
54 struct nouveau_drm *drm = nouveau_drm(dev);54 struct nouveau_drm *drm = nouveau_drm(dev);
55 struct nvkm_therm *therm = nvxx_therm(&drm->client.device);55 struct nvkm_therm *therm = nvxx_therm(&drm->client.device);
56 56
57 return snprintf(buf, PAGE_SIZE, "%d\n",57 return sysfs_emit(buf, "%d\n",
58 therm->attr_get(therm, NVKM_THERM_ATTR_THRS_FAN_BOOST) * 1000);58 therm->attr_get(therm, NVKM_THERM_ATTR_THRS_FAN_BOOST) * 1000);
59}59}
60static ssize_t60static ssize_t
61nouveau_hwmon_set_temp1_auto_point1_temp(struct device *d,61nouveau_hwmon_set_temp1_auto_point1_temp(struct device *d,
@@ -87,8 +87,8 @@ nouveau_hwmon_temp1_auto_point1_temp_hyst(struct device *d, · 25 unmodified lines
87 struct nouveau_drm *drm = nouveau_drm(dev);87 struct nouveau_drm *drm = nouveau_drm(dev);
88 struct nvkm_therm *therm = nvxx_therm(&drm->client.device);88 struct nvkm_therm *therm = nvxx_therm(&drm->client.device);
89 89
90 return snprintf(buf, PAGE_SIZE, "%d\n",90 return sysfs_emit(buf, "%d\n",
91 therm->attr_get(therm, NVKM_THERM_ATTR_THRS_FAN_BOOST_HYST) * 1000);91 therm->attr_get(therm, NVKM_THERM_ATTR_THRS_FAN_BOOST_HYST) * 1000);
92}92}
93static ssize_t93static ssize_t
94nouveau_hwmon_set_temp1_auto_point1_temp_hyst(struct device *d,94nouveau_hwmon_set_temp1_auto_point1_temp_hyst(struct device *d,
drivers/gpu/drm/nouveau/nouveau_led.h+1−1
@@ -27,7 +27,7 @@ · 26 unmodified lines
27 27
28#include "nouveau_drv.h"28#include "nouveau_drv.h"
29 29
30struct led_classdev;30#include <linux/leds.h>
31 31
32struct nouveau_led {32struct nouveau_led {
33 struct drm_device *dev;33 struct drm_device *dev;
drivers/gpu/drm/panel/Kconfig+11−0
@@ -318,6 +318,17 @@ config DRM_PANEL_LG_LG4573 · 317 unmodified lines
318 Say Y here if you want to enable support for LG4573 RGB panel.318 Say Y here if you want to enable support for LG4573 RGB panel.
319 To compile this driver as a module, choose M here.319 To compile this driver as a module, choose M here.
320 320
321config 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
321config DRM_PANEL_NEC_NL8048HL11332config DRM_PANEL_NEC_NL8048HL11
322 tristate "NEC NL8048HL11 RGB panel"333 tristate "NEC NL8048HL11 RGB panel"
323 depends on GPIOLIB && OF && SPI334 depends on GPIOLIB && OF && SPI
drivers/gpu/drm/panel/Makefile+1−0
@@ -29,6 +29,7 @@ obj-$(CONFIG_DRM_PANEL_LEADTEK_LTK050H3146W) += panel-leadtek-ltk050h3146w.o · 28 unmodified lines
29obj-$(CONFIG_DRM_PANEL_LEADTEK_LTK500HD1829) += panel-leadtek-ltk500hd1829.o29obj-$(CONFIG_DRM_PANEL_LEADTEK_LTK500HD1829) += panel-leadtek-ltk500hd1829.o
30obj-$(CONFIG_DRM_PANEL_LG_LB035Q02) += panel-lg-lb035q02.o30obj-$(CONFIG_DRM_PANEL_LG_LB035Q02) += panel-lg-lb035q02.o
31obj-$(CONFIG_DRM_PANEL_LG_LG4573) += panel-lg-lg4573.o31obj-$(CONFIG_DRM_PANEL_LG_LG4573) += panel-lg-lg4573.o
32obj-$(CONFIG_DRM_PANEL_MAGNACHIP_D53E6EA8966) += panel-magnachip-d53e6ea8966.o
32obj-$(CONFIG_DRM_PANEL_NEC_NL8048HL11) += panel-nec-nl8048hl11.o33obj-$(CONFIG_DRM_PANEL_NEC_NL8048HL11) += panel-nec-nl8048hl11.o
33obj-$(CONFIG_DRM_PANEL_NEWVISION_NV3051D) += panel-newvision-nv3051d.o34obj-$(CONFIG_DRM_PANEL_NEWVISION_NV3051D) += panel-newvision-nv3051d.o
34obj-$(CONFIG_DRM_PANEL_NEWVISION_NV3052C) += panel-newvision-nv3052c.o35obj-$(CONFIG_DRM_PANEL_NEWVISION_NV3052C) += panel-newvision-nv3052c.o
drivers/gpu/drm/panel/panel-jadard-jd9365da-h3.c+208−1
@@ -167,6 +167,202 @@ static const struct drm_panel_funcs jadard_funcs = { · 166 unmodified lines
167 .get_modes = jadard_get_modes,167 .get_modes = jadard_get_modes,
168};168};
169 169
170static 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
342static 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
170static const struct jadard_init_cmd cz101b4001_init_cmds[] = {366static const struct jadard_init_cmd cz101b4001_init_cmds[] = {
171 { .data = { 0xE0, 0x00 } },367 { .data = { 0xE0, 0x00 } },
172 { .data = { 0xE1, 0x93 } },368 { .data = { 0xE1, 0x93 } },
@@ -452,7 +648,18 @@ static void jadard_dsi_remove(struct mipi_dsi_device *dsi) · 279 unmodified lines
452}648}
453 649
454static const struct of_device_id jadard_of_match[] = {650static const struct of_device_id jadard_of_match[] = {
455 { .compatible = "chongzhou,cz101b4001", .data = &cz101b4001_desc },651 {
652 .compatible = "chongzhou,cz101b4001",
653 .data = &cz101b4001_desc
654 },
655 {
656 .compatible = "radxa,display-10hd-ad001",
657 .data = &cz101b4001_desc
658 },
659 {
660 .compatible = "radxa,display-8hd-ad002",
661 .data = &radxa_display_8hd_ad002_desc
662 },
456 { /* sentinel */ }663 { /* sentinel */ }
457};664};
458MODULE_DEVICE_TABLE(of, jadard_of_match);665MODULE_DEVICE_TABLE(of, jadard_of_match);
drivers/gpu/drm/panel/panel-magnachip-d53e6ea8966.c+522−0
@@ -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 */
28struct d53e6ea8966;
29
30/* Panel info, unique to each panel */
31struct 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
48struct 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
85static 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 */
91static 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 */
146static 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
151static 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
167static 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
205static 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
244static 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
257static 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
270static 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
288static 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
318static 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
326static 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
337static const struct backlight_ops ams495qa01_backlight_ops = {
338 .update_status = ams495qa01_set_brightness,
339};
340
341static 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
362static 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
451static 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
458static 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
487static 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
497static const struct of_device_id d53e6ea8966_match[] = {
498 { .compatible = "samsung,ams495qa01", .data = &ams495qa01_info },
499 { /* sentinel */ },
500};
501MODULE_DEVICE_TABLE(of, d53e6ea8966_match);
502
503static const struct spi_device_id d53e6ea8966_ids[] = {
504 { "ams495qa01", 0 },
505 { /* sentinel */ },
506};
507MODULE_DEVICE_TABLE(spi, d53e6ea8966_ids);
508
509static 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};
518module_spi_driver(d53e6ea8966_driver);
519
520MODULE_AUTHOR("Chris Morgan <macromorgan@hotmail.com>");
521MODULE_DESCRIPTION("Magnachip d53e6ea8966 panel driver");
522MODULE_LICENSE("GPL");
drivers/gpu/drm/panfrost/panfrost_drv.c+2−9
@@ -220,15 +220,8 @@ panfrost_copy_in_sync(struct drm_device *dev, · 219 unmodified lines
220 }220 }
221 221
222 for (i = 0; i < in_fence_count; i++) {222 for (i = 0; i < in_fence_count; i++) {
223 struct dma_fence *fence;223 ret = drm_sched_job_add_syncobj_dependency(&job->base, file_priv,
224 224 handles[i], 0);
225 ret = drm_syncobj_find_fence(file_priv, handles[i], 0, 0,
226 &fence);
227 if (ret)
228 goto fail;
229
230 ret = drm_sched_job_add_dependency(&job->base, fence);
231
232 if (ret)225 if (ret)
233 goto fail;226 goto fail;
234 }227 }
drivers/gpu/drm/qxl/qxl_ttm.c+11−0
@@ -143,6 +143,17 @@ static int qxl_bo_move(struct ttm_buffer_object *bo, bool evict, · 142 unmodified lines
143 struct ttm_resource *old_mem = bo->resource;143 struct ttm_resource *old_mem = bo->resource;
144 int ret;144 int ret;
145 145
146 if (!old_mem) {
147 if (new_mem->mem_type != TTM_PL_SYSTEM) {
148 hop->mem_type = TTM_PL_SYSTEM;
149 hop->flags = TTM_PL_FLAG_TEMPORARY;
150 return -EMULTIHOP;
151 }
152
153 ttm_bo_move_null(bo, new_mem);
154 return 0;
155 }
156
146 qxl_bo_move_notify(bo, new_mem);157 qxl_bo_move_notify(bo, new_mem);
147 158
148 ret = ttm_bo_wait_ctx(bo, ctx);159 ret = ttm_bo_wait_ctx(bo, ctx);
drivers/gpu/drm/radeon/Kconfig+1−0
@@ -8,6 +8,7 @@ config DRM_RADEON · 7 unmodified lines
8 select DRM_DISPLAY_DP_HELPER8 select DRM_DISPLAY_DP_HELPER
9 select DRM_DISPLAY_HELPER9 select DRM_DISPLAY_HELPER
10 select DRM_KMS_HELPER10 select DRM_KMS_HELPER
11 select DRM_SUBALLOC_HELPER
11 select DRM_TTM12 select DRM_TTM
12 select DRM_TTM_HELPER13 select DRM_TTM_HELPER
13 select SND_HDA_COMPONENT if SND_HDA_CORE14 select SND_HDA_COMPONENT if SND_HDA_CORE
drivers/gpu/drm/radeon/radeon.h+8−47
@@ -79,6 +79,7 @@ · 78 unmodified lines
79 79
80#include <drm/drm_gem.h>80#include <drm/drm_gem.h>
81#include <drm/drm_audio_component.h>81#include <drm/drm_audio_component.h>
82#include <drm/drm_suballoc.h>
82 83
83#include "radeon_family.h"84#include "radeon_family.h"
84#include "radeon_mode.h"85#include "radeon_mode.h"
@@ -511,52 +512,12 @@ struct radeon_bo { · 426 unmodified lines
511};512};
512#define gem_to_radeon_bo(gobj) container_of((gobj), struct radeon_bo, tbo.base)513#define gem_to_radeon_bo(gobj) container_of((gobj), struct radeon_bo, tbo.base)
513 514
514/* sub-allocation manager, it has to be protected by another lock.
515 * By conception this is an helper for other part of the driver
516 * like the indirect buffer or semaphore, which both have their
517 * locking.
518 *
519 * Principe is simple, we keep a list of sub allocation in offset
520 * order (first entry has offset == 0, last entry has the highest
521 * offset).
522 *
523 * When allocating new object we first check if there is room at
524 * the end total_size - (last_object_offset + last_object_size) >=
525 * alloc_size. If so we allocate new object there.
526 *
527 * When there is not enough room at the end, we start waiting for
528 * each sub object until we reach object_offset+object_size >=
529 * alloc_size, this object then become the sub object we return.
530 *
531 * Alignment can't be bigger than page size.
532 *
533 * Hole are not considered for allocation to keep things simple.
534 * Assumption is that there won't be hole (all object on same
535 * alignment).
536 */
537struct radeon_sa_manager {515struct radeon_sa_manager {
538 wait_queue_head_t wq;516 struct drm_suballoc_manager base;
539 struct radeon_bo *bo;517 struct radeon_bo *bo;
540 struct list_head *hole;518 uint64_t gpu_addr;
541 struct list_head flist[RADEON_NUM_RINGS];519 void *cpu_ptr;
542 struct list_head olist;520 u32 domain;
543 unsigned size;
544 uint64_t gpu_addr;
545 void *cpu_ptr;
546 uint32_t domain;
547 uint32_t align;
548};
549
550struct radeon_sa_bo;
551
552/* sub-allocation buffer */
553struct radeon_sa_bo {
554 struct list_head olist;
555 struct list_head flist;
556 struct radeon_sa_manager *manager;
557 unsigned soffset;
558 unsigned eoffset;
559 struct radeon_fence *fence;
560};521};
561 522
562/*523/*
@@ -587,7 +548,7 @@ int radeon_mode_dumb_mmap(struct drm_file *filp, · 24 unmodified lines
587 * Semaphores.548 * Semaphores.
588 */549 */
589struct radeon_semaphore {550struct radeon_semaphore {
590 struct radeon_sa_bo *sa_bo;551 struct drm_suballoc *sa_bo;
591 signed waiters;552 signed waiters;
592 uint64_t gpu_addr;553 uint64_t gpu_addr;
593};554};
@@ -816,7 +777,7 @@ void radeon_irq_kms_disable_hpd(struct radeon_device *rdev, unsigned hpd_mask); · 222 unmodified lines
816 */777 */
817 778
818struct radeon_ib {779struct radeon_ib {
819 struct radeon_sa_bo *sa_bo;780 struct drm_suballoc *sa_bo;
820 uint32_t length_dw;781 uint32_t length_dw;
821 uint64_t gpu_addr;782 uint64_t gpu_addr;
822 uint32_t *ptr;783 uint32_t *ptr;
drivers/gpu/drm/radeon/radeon_ib.c+5−7
@@ -61,7 +61,7 @@ int radeon_ib_get(struct radeon_device *rdev, int ring, · 60 unmodified lines
61{61{
62 int r;62 int r;
63 63
64 r = radeon_sa_bo_new(rdev, &rdev->ring_tmp_bo, &ib->sa_bo, size, 256);64 r = radeon_sa_bo_new(&rdev->ring_tmp_bo, &ib->sa_bo, size, 256);
65 if (r) {65 if (r) {
66 dev_err(rdev->dev, "failed to get a new IB (%d)\n", r);66 dev_err(rdev->dev, "failed to get a new IB (%d)\n", r);
67 return r;67 return r;
@@ -77,7 +77,7 @@ int radeon_ib_get(struct radeon_device *rdev, int ring, · 9 unmodified lines
77 /* ib pool is bound at RADEON_VA_IB_OFFSET in virtual address77 /* ib pool is bound at RADEON_VA_IB_OFFSET in virtual address
78 * space and soffset is the offset inside the pool bo78 * space and soffset is the offset inside the pool bo
79 */79 */
80 ib->gpu_addr = ib->sa_bo->soffset + RADEON_VA_IB_OFFSET;80 ib->gpu_addr = drm_suballoc_soffset(ib->sa_bo) + RADEON_VA_IB_OFFSET;
81 } else {81 } else {
82 ib->gpu_addr = radeon_sa_bo_gpu_addr(ib->sa_bo);82 ib->gpu_addr = radeon_sa_bo_gpu_addr(ib->sa_bo);
83 }83 }
@@ -97,7 +97,7 @@ int radeon_ib_get(struct radeon_device *rdev, int ring, · 13 unmodified lines
97void radeon_ib_free(struct radeon_device *rdev, struct radeon_ib *ib)97void radeon_ib_free(struct radeon_device *rdev, struct radeon_ib *ib)
98{98{
99 radeon_sync_free(rdev, &ib->sync, ib->fence);99 radeon_sync_free(rdev, &ib->sync, ib->fence);
100 radeon_sa_bo_free(rdev, &ib->sa_bo, ib->fence);100 radeon_sa_bo_free(&ib->sa_bo, ib->fence);
101 radeon_fence_unref(&ib->fence);101 radeon_fence_unref(&ib->fence);
102}102}
103 103
@@ -201,8 +201,7 @@ int radeon_ib_pool_init(struct radeon_device *rdev) · 97 unmodified lines
201 201
202 if (rdev->family >= CHIP_BONAIRE) {202 if (rdev->family >= CHIP_BONAIRE) {
203 r = radeon_sa_bo_manager_init(rdev, &rdev->ring_tmp_bo,203 r = radeon_sa_bo_manager_init(rdev, &rdev->ring_tmp_bo,
204 RADEON_IB_POOL_SIZE*64*1024,204 RADEON_IB_POOL_SIZE*64*1024, 256,
205 RADEON_GPU_PAGE_SIZE,
206 RADEON_GEM_DOMAIN_GTT,205 RADEON_GEM_DOMAIN_GTT,
207 RADEON_GEM_GTT_WC);206 RADEON_GEM_GTT_WC);
208 } else {207 } else {
@@ -210,8 +209,7 @@ int radeon_ib_pool_init(struct radeon_device *rdev) · 1 unmodified line
210 * to the command stream checking209 * to the command stream checking
211 */210 */
212 r = radeon_sa_bo_manager_init(rdev, &rdev->ring_tmp_bo,211 r = radeon_sa_bo_manager_init(rdev, &rdev->ring_tmp_bo,
213 RADEON_IB_POOL_SIZE*64*1024,212 RADEON_IB_POOL_SIZE*64*1024, 256,
214 RADEON_GPU_PAGE_SIZE,
215 RADEON_GEM_DOMAIN_GTT, 0);213 RADEON_GEM_DOMAIN_GTT, 0);
216 }214 }
217 if (r) {215 if (r) {
drivers/gpu/drm/radeon/radeon_object.h+15−10
@@ -169,15 +169,22 @@ extern void radeon_bo_fence(struct radeon_bo *bo, struct radeon_fence *fence, · 168 unmodified lines
169/*169/*
170 * sub allocation170 * sub allocation
171 */171 */
172static inline struct radeon_sa_manager *
173to_radeon_sa_manager(struct drm_suballoc_manager *manager)
174{
175 return container_of(manager, struct radeon_sa_manager, base);
176}
172 177
173static inline uint64_t radeon_sa_bo_gpu_addr(struct radeon_sa_bo *sa_bo)178static 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
178static inline void * radeon_sa_bo_cpu_addr(struct radeon_sa_bo *sa_bo)184static 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
183extern int radeon_sa_bo_manager_init(struct radeon_device *rdev,190extern int radeon_sa_bo_manager_init(struct radeon_device *rdev,
@@ -190,12 +197,10 @@ extern int radeon_sa_bo_manager_start(struct radeon_device *rdev, · 6 unmodified lines
190 struct radeon_sa_manager *sa_manager);197 struct radeon_sa_manager *sa_manager);
191extern int radeon_sa_bo_manager_suspend(struct radeon_device *rdev,198extern int radeon_sa_bo_manager_suspend(struct radeon_device *rdev,
192 struct radeon_sa_manager *sa_manager);199 struct radeon_sa_manager *sa_manager);
193extern int radeon_sa_bo_new(struct radeon_device *rdev,200extern int radeon_sa_bo_new(struct radeon_sa_manager *sa_manager,
194 struct radeon_sa_manager *sa_manager,201 struct drm_suballoc **sa_bo,
195 struct radeon_sa_bo **sa_bo,202 unsigned int size, unsigned int align);
196 unsigned size, unsigned align);203extern void radeon_sa_bo_free(struct drm_suballoc **sa_bo,
197extern void radeon_sa_bo_free(struct radeon_device *rdev,
198 struct radeon_sa_bo **sa_bo,
199 struct radeon_fence *fence);204 struct radeon_fence *fence);
200#if defined(CONFIG_DEBUG_FS)205#if defined(CONFIG_DEBUG_FS)
201extern void radeon_sa_bo_dump_debug_info(struct radeon_sa_manager *sa_manager,206extern void radeon_sa_bo_dump_debug_info(struct radeon_sa_manager *sa_manager,
drivers/gpu/drm/radeon/radeon_sa.c+26−290
@@ -44,53 +44,32 @@ · 43 unmodified lines
44 44
45#include "radeon.h"45#include "radeon.h"
46 46
47static void radeon_sa_bo_remove_locked(struct radeon_sa_bo *sa_bo);
48static void radeon_sa_bo_try_free(struct radeon_sa_manager *sa_manager);
49
50int radeon_sa_bo_manager_init(struct radeon_device *rdev,47int radeon_sa_bo_manager_init(struct radeon_device *rdev,
51 struct radeon_sa_manager *sa_manager,48 struct radeon_sa_manager *sa_manager,
52 unsigned size, u32 align, u32 domain, u32 flags)49 unsigned int size, u32 sa_align, u32 domain,
50 u32 flags)
53{51{
54 int i, r;52 int r;
55
56 init_waitqueue_head(&sa_manager->wq);
57 sa_manager->bo = NULL;
58 sa_manager->size = size;
59 sa_manager->domain = domain;
60 sa_manager->align = align;
61 sa_manager->hole = &sa_manager->olist;
62 INIT_LIST_HEAD(&sa_manager->olist);
63 for (i = 0; i < RADEON_NUM_RINGS; ++i) {
64 INIT_LIST_HEAD(&sa_manager->flist[i]);
65 }
66 53
67 r = radeon_bo_create(rdev, size, align, true,54 r = radeon_bo_create(rdev, size, RADEON_GPU_PAGE_SIZE, true,
68 domain, flags, NULL, NULL, &sa_manager->bo);55 domain, flags, NULL, NULL, &sa_manager->bo);
69 if (r) {56 if (r) {
70 dev_err(rdev->dev, "(%d) failed to allocate bo for manager\n", r);57 dev_err(rdev->dev, "(%d) failed to allocate bo for manager\n", r);
71 return r;58 return r;
72 }59 }
73 60
61 sa_manager->domain = domain;
62
63 drm_suballoc_manager_init(&sa_manager->base, size, sa_align);
64
74 return r;65 return r;
75}66}
76 67
77void radeon_sa_bo_manager_fini(struct radeon_device *rdev,68void radeon_sa_bo_manager_fini(struct radeon_device *rdev,
78 struct radeon_sa_manager *sa_manager)69 struct radeon_sa_manager *sa_manager)
79{70{
80 struct radeon_sa_bo *sa_bo, *tmp;71 drm_suballoc_manager_fini(&sa_manager->base);
81
82 if (!list_empty(&sa_manager->olist)) {
83 sa_manager->hole = &sa_manager->olist,
84 radeon_sa_bo_try_free(sa_manager);
85 if (!list_empty(&sa_manager->olist)) {
86 dev_err(rdev->dev, "sa_manager is not empty, clearing anyway\n");
87 }
88 }
89 list_for_each_entry_safe(sa_bo, tmp, &sa_manager->olist, olist) {
90 radeon_sa_bo_remove_locked(sa_bo);
91 }
92 radeon_bo_unref(&sa_manager->bo);72 radeon_bo_unref(&sa_manager->bo);
93 sa_manager->size = 0;
94}73}
95 74
96int radeon_sa_bo_manager_start(struct radeon_device *rdev,75int radeon_sa_bo_manager_start(struct radeon_device *rdev,
@@ -139,260 +118,34 @@ int radeon_sa_bo_manager_suspend(struct radeon_device *rdev, · 42 unmodified lines
139 return r;118 return r;
140}119}
141 120
142static void radeon_sa_bo_remove_locked(struct radeon_sa_bo *sa_bo)121int radeon_sa_bo_new(struct radeon_sa_manager *sa_manager,
122 struct drm_suballoc **sa_bo,
123 unsigned int size, unsigned int align)
143{124{
144 struct radeon_sa_manager *sa_manager = sa_bo->manager;125 struct drm_suballoc *sa = drm_suballoc_new(&sa_manager->base, size,
145 if (sa_manager->hole == &sa_bo->olist) {126 GFP_KERNEL, true, align);
146 sa_manager->hole = sa_bo->olist.prev;
147 }
148 list_del_init(&sa_bo->olist);
149 list_del_init(&sa_bo->flist);
150 radeon_fence_unref(&sa_bo->fence);
151 kfree(sa_bo);
152}
153
154static void radeon_sa_bo_try_free(struct radeon_sa_manager *sa_manager)
155{
156 struct radeon_sa_bo *sa_bo, *tmp;
157
158 if (sa_manager->hole->next == &sa_manager->olist)
159 return;
160 127
161 sa_bo = list_entry(sa_manager->hole->next, struct radeon_sa_bo, olist);128 if (IS_ERR(sa)) {
162 list_for_each_entry_safe_from(sa_bo, tmp, &sa_manager->olist, olist) {129 *sa_bo = NULL;
163 if (sa_bo->fence == NULL || !radeon_fence_signaled(sa_bo->fence)) {130 return PTR_ERR(sa);
164 return;
165 }
166 radeon_sa_bo_remove_locked(sa_bo);
167 }131 }
168}
169 132
170static inline unsigned radeon_sa_bo_hole_soffset(struct radeon_sa_manager *sa_manager)133 *sa_bo = sa;
171{
172 struct list_head *hole = sa_manager->hole;
173
174 if (hole != &sa_manager->olist) {
175 return list_entry(hole, struct radeon_sa_bo, olist)->eoffset;
176 }
177 return 0;134 return 0;
178}135}
179 136
180static inline unsigned radeon_sa_bo_hole_eoffset(struct radeon_sa_manager *sa_manager)137void radeon_sa_bo_free(struct drm_suballoc **sa_bo,
181{
182 struct list_head *hole = sa_manager->hole;
183
184 if (hole->next != &sa_manager->olist) {
185 return list_entry(hole->next, struct radeon_sa_bo, olist)->soffset;
186 }
187 return sa_manager->size;
188}
189
190static 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 */
224static 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
247static 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
314int 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
376void radeon_sa_bo_free(struct radeon_device *rdev, struct radeon_sa_bo **sa_bo,
377 struct radeon_fence *fence)138 struct radeon_fence *fence)
378{139{
379 struct radeon_sa_manager *sa_manager;
380
381 if (sa_bo == NULL || *sa_bo == NULL) {140 if (sa_bo == NULL || *sa_bo == NULL) {
382 return;141 return;
383 }142 }
384 143
385 sa_manager = (*sa_bo)->manager;144 if (fence)
386 spin_lock(&sa_manager->wq.lock);145 drm_suballoc_free(*sa_bo, &fence->base);
387 if (fence && !radeon_fence_signaled(fence)) {146 else
388 (*sa_bo)->fence = radeon_fence_ref(fence);147 drm_suballoc_free(*sa_bo, NULL);
389 list_add_tail(&(*sa_bo)->flist,148
390 &sa_manager->flist[fence->ring]);
391 } else {
392 radeon_sa_bo_remove_locked(*sa_bo);
393 }
394 wake_up_all_locked(&sa_manager->wq);
395 spin_unlock(&sa_manager->wq.lock);
396 *sa_bo = NULL;149 *sa_bo = NULL;
397}150}
398 151
@@ -400,25 +153,8 @@ void radeon_sa_bo_free(struct radeon_device *rdev, struct radeon_sa_bo **sa_bo, · 1 unmodified line
400void radeon_sa_bo_dump_debug_info(struct radeon_sa_manager *sa_manager,153void radeon_sa_bo_dump_debug_info(struct radeon_sa_manager *sa_manager,
401 struct seq_file *m)154 struct seq_file *m)
402{155{
403 struct radeon_sa_bo *i;156 struct drm_printer p = drm_seq_file_printer(m);
404 157
405 spin_lock(&sa_manager->wq.lock);158 drm_suballoc_dump_debug_info(&sa_manager->base, &p, sa_manager->gpu_addr);
406 list_for_each_entry(i, &sa_manager->olist, olist) {
407 uint64_t soffset = i->soffset + sa_manager->gpu_addr;
408 uint64_t eoffset = i->eoffset + sa_manager->gpu_addr;
409 if (&i->olist == sa_manager->hole) {
410 seq_printf(m, ">");
411 } else {
412 seq_printf(m, " ");
413 }
414 seq_printf(m, "[0x%010llx 0x%010llx] size %8lld",
415 soffset, eoffset, eoffset - soffset);
416 if (i->fence) {
417 seq_printf(m, " protected by 0x%016llx on ring %d",
418 i->fence->seq, i->fence->ring);
419 }
420 seq_printf(m, "\n");
421 }
422 spin_unlock(&sa_manager->wq.lock);
423}159}
424#endif160#endif
drivers/gpu/drm/radeon/radeon_semaphore.c+2−2
@@ -40,7 +40,7 @@ int radeon_semaphore_create(struct radeon_device *rdev, · 39 unmodified lines
40 if (*semaphore == NULL) {40 if (*semaphore == NULL) {
41 return -ENOMEM;41 return -ENOMEM;
42 }42 }
43 r = radeon_sa_bo_new(rdev, &rdev->ring_tmp_bo,43 r = radeon_sa_bo_new(&rdev->ring_tmp_bo,
44 &(*semaphore)->sa_bo, 8, 8);44 &(*semaphore)->sa_bo, 8, 8);
45 if (r) {45 if (r) {
46 kfree(*semaphore);46 kfree(*semaphore);
@@ -100,7 +100,7 @@ void radeon_semaphore_free(struct radeon_device *rdev, · 53 unmodified lines
100 dev_err(rdev->dev, "semaphore %p has more waiters than signalers,"100 dev_err(rdev->dev, "semaphore %p has more waiters than signalers,"
101 " hardware lockup imminent!\n", *semaphore);101 " hardware lockup imminent!\n", *semaphore);
102 }102 }
103 radeon_sa_bo_free(rdev, &(*semaphore)->sa_bo, fence);103 radeon_sa_bo_free(&(*semaphore)->sa_bo, fence);
104 kfree(*semaphore);104 kfree(*semaphore);
105 *semaphore = NULL;105 *semaphore = NULL;
106}106}
drivers/gpu/drm/radeon/radeon_ttm.c+2−5
@@ -211,13 +211,10 @@ static int radeon_bo_move(struct ttm_buffer_object *bo, bool evict, · 210 unmodified lines
211 if (r)211 if (r)
212 return r;212 return r;
213 213
214 /* Can't move a pinned BO */
215 rbo = container_of(bo, struct radeon_bo, tbo);214 rbo = container_of(bo, struct radeon_bo, tbo);
216 if (WARN_ON_ONCE(rbo->tbo.pin_count > 0))
217 return -EINVAL;
218
219 rdev = radeon_get_rdev(bo->bdev);215 rdev = radeon_get_rdev(bo->bdev);
220 if (old_mem->mem_type == TTM_PL_SYSTEM && bo->ttm == NULL) {216 if (!old_mem || (old_mem->mem_type == TTM_PL_SYSTEM &&
217 bo->ttm == NULL)) {
221 ttm_bo_move_null(bo, new_mem);218 ttm_bo_move_null(bo, new_mem);
222 goto out;219 goto out;
223 }220 }
drivers/gpu/drm/rockchip/rockchip_drm_gem.c+10−6
@@ -261,9 +261,6 @@ static int rockchip_drm_gem_object_mmap(struct drm_gem_object *obj, · 260 unmodified lines
261 else261 else
262 ret = rockchip_drm_gem_object_mmap_dma(obj, vma);262 ret = rockchip_drm_gem_object_mmap_dma(obj, vma);
263 263
264 if (ret)
265 drm_gem_vm_close(vma);
266
267 return ret;264 return ret;
268}265}
269 266
@@ -518,8 +515,14 @@ int rockchip_gem_prime_vmap(struct drm_gem_object *obj, struct iosys_map *map) · 248 unmodified lines
518 struct rockchip_gem_object *rk_obj = to_rockchip_obj(obj);515 struct rockchip_gem_object *rk_obj = to_rockchip_obj(obj);
519 516
520 if (rk_obj->pages) {517 if (rk_obj->pages) {
521 void *vaddr = vmap(rk_obj->pages, rk_obj->num_pages, VM_MAP,518 void *vaddr;
522 pgprot_writecombine(PAGE_KERNEL));519
520 if (rk_obj->kvaddr)
521 vaddr = rk_obj->kvaddr;
522 else
523 vaddr = vmap(rk_obj->pages, rk_obj->num_pages, VM_MAP,
524 pgprot_writecombine(PAGE_KERNEL));
525
523 if (!vaddr)526 if (!vaddr)
524 return -ENOMEM;527 return -ENOMEM;
525 iosys_map_set_vaddr(map, vaddr);528 iosys_map_set_vaddr(map, vaddr);
@@ -539,7 +542,8 @@ void rockchip_gem_prime_vunmap(struct drm_gem_object *obj, · 13 unmodified lines
539 struct rockchip_gem_object *rk_obj = to_rockchip_obj(obj);542 struct rockchip_gem_object *rk_obj = to_rockchip_obj(obj);
540 543
541 if (rk_obj->pages) {544 if (rk_obj->pages) {
542 vunmap(map->vaddr);545 if (map->vaddr != rk_obj->kvaddr)
546 vunmap(map->vaddr);
543 return;547 return;
544 }548 }
545 549
drivers/gpu/drm/rockchip/rockchip_drm_vop.c+2−5
@@ -316,13 +316,10 @@ static int vop_convert_afbc_format(uint32_t format) · 315 unmodified lines
316 case DRM_FORMAT_RGB565:316 case DRM_FORMAT_RGB565:
317 case DRM_FORMAT_BGR565:317 case DRM_FORMAT_BGR565:
318 return AFBC_FMT_RGB565;318 return AFBC_FMT_RGB565;
319 /* either of the below should not be reachable */
320 default:319 default:
321 DRM_WARN_ONCE("unsupported AFBC format[%08x]\n", format);320 DRM_DEBUG_KMS("unsupported AFBC format[%08x]\n", format);
322 return -EINVAL;321 return -EINVAL;
323 }322 }
324
325 return -EINVAL;
326}323}
327 324
328static uint16_t scl_vop_cal_scale(enum scale_mode mode, uint32_t src,325static uint16_t scl_vop_cal_scale(enum scale_mode mode, uint32_t src,
@@ -2221,7 +2218,7 @@ static int vop_bind(struct device *dev, struct device *master, void *data) · 1892 unmodified lines
2221 goto err_disable_pm_runtime;2218 goto err_disable_pm_runtime;
2222 2219
2223 if (vop->data->feature & VOP_FEATURE_INTERNAL_RGB) {2220 if (vop->data->feature & VOP_FEATURE_INTERNAL_RGB) {
2224 vop->rgb = rockchip_rgb_init(dev, &vop->crtc, vop->drm_dev);2221 vop->rgb = rockchip_rgb_init(dev, &vop->crtc, vop->drm_dev, 0);
2225 if (IS_ERR(vop->rgb)) {2222 if (IS_ERR(vop->rgb)) {
2226 ret = PTR_ERR(vop->rgb);2223 ret = PTR_ERR(vop->rgb);
2227 goto err_disable_pm_runtime;2224 goto err_disable_pm_runtime;
drivers/gpu/drm/rockchip/rockchip_drm_vop2.c+63−17
@@ -38,6 +38,7 @@ · 37 unmodified lines
38#include "rockchip_drm_gem.h"38#include "rockchip_drm_gem.h"
39#include "rockchip_drm_fb.h"39#include "rockchip_drm_fb.h"
40#include "rockchip_drm_vop2.h"40#include "rockchip_drm_vop2.h"
41#include "rockchip_rgb.h"
41 42
42/*43/*
43 * VOP2 architecture44 * VOP2 architecture
@@ -211,6 +212,9 @@ struct vop2 { · 167 unmodified lines
211 struct clk *hclk;212 struct clk *hclk;
212 struct clk *aclk;213 struct clk *aclk;
213 214
215 /* optional internal rgb encoder */
216 struct rockchip_rgb *rgb;
217
214 /* must be put at the end of the struct */218 /* must be put at the end of the struct */
215 struct vop2_win win[];219 struct vop2_win win[];
216};220};
@@ -2245,7 +2249,7 @@ static struct vop2_video_port *find_vp_without_primary(struct vop2 *vop2) · 2028 unmodified lines
2245 2249
2246#define NR_LAYERS 62250#define NR_LAYERS 6
2247 2251
2248static int vop2_create_crtc(struct vop2 *vop2)2252static int vop2_create_crtcs(struct vop2 *vop2)
2249{2253{
2250 const struct vop2_data *vop2_data = vop2->data;2254 const struct vop2_data *vop2_data = vop2->data;
2251 struct drm_device *drm = vop2->drm;2255 struct drm_device *drm = vop2->drm;
@@ -2321,10 +2325,11 @@ static int vop2_create_crtc(struct vop2 *vop2) · 69 unmodified lines
2321 /* change the unused primary window to overlay window */2325 /* change the unused primary window to overlay window */
2322 win->type = DRM_PLANE_TYPE_OVERLAY;2326 win->type = DRM_PLANE_TYPE_OVERLAY;
2323 }2327 }
2324 }2328 } else if (win->type == DRM_PLANE_TYPE_OVERLAY) {
2325
2326 if (win->type == DRM_PLANE_TYPE_OVERLAY)
2327 possible_crtcs = (1 << nvps) - 1;2329 possible_crtcs = (1 << nvps) - 1;
2330 } else {
2331 possible_crtcs = 0;
2332 }
2328 2333
2329 ret = vop2_plane_init(vop2, win, possible_crtcs);2334 ret = vop2_plane_init(vop2, win, possible_crtcs);
2330 if (ret) {2335 if (ret) {
@@ -2370,15 +2375,44 @@ static int vop2_create_crtc(struct vop2 *vop2) · 39 unmodified lines
2370 return 0;2375 return 0;
2371}2376}
2372 2377
2373static void vop2_destroy_crtc(struct drm_crtc *crtc)2378static void vop2_destroy_crtcs(struct vop2 *vop2)
2374{2379{
2375 of_node_put(crtc->port);2380 struct drm_device *drm = vop2->drm;
2381 struct list_head *crtc_list = &drm->mode_config.crtc_list;
2382 struct list_head *plane_list = &drm->mode_config.plane_list;
2383 struct drm_crtc *crtc, *tmpc;
2384 struct drm_plane *plane, *tmpp;
2385
2386 list_for_each_entry_safe(plane, tmpp, plane_list, head)
2387 drm_plane_cleanup(plane);
2376 2388
2377 /*2389 /*
2378 * Destroy CRTC after vop2_plane_destroy() since vop2_disable_plane()2390 * Destroy CRTC after vop2_plane_destroy() since vop2_disable_plane()
2379 * references the CRTC.2391 * references the CRTC.
2380 */2392 */
2381 drm_crtc_cleanup(crtc);2393 list_for_each_entry_safe(crtc, tmpc, crtc_list, head) {
2394 of_node_put(crtc->port);
2395 drm_crtc_cleanup(crtc);
2396 }
2397}
2398
2399static 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
2384static struct reg_field vop2_cluster_regs[VOP2_WIN_MAX_REG] = {2418static struct reg_field vop2_cluster_regs[VOP2_WIN_MAX_REG] = {
@@ -2682,33 +2716,45 @@ static int vop2_bind(struct device *dev, struct device *master, void *data) · 297 unmodified lines
2682 if (ret)2716 if (ret)
2683 return ret;2717 return ret;
2684 2718
2685 ret = vop2_create_crtc(vop2);2719 ret = vop2_create_crtcs(vop2);
2686 if (ret)2720 if (ret)
2687 return ret;2721 return ret;
2688 2722
2723 ret = vop2_find_rgb_encoder(vop2);
2724 if (ret >= 0) {
2725 vop2->rgb = rockchip_rgb_init(dev, &vop2->vps[ret].crtc,
2726 vop2->drm, ret);
2727 if (IS_ERR(vop2->rgb)) {
2728 if (PTR_ERR(vop2->rgb) == -EPROBE_DEFER) {
2729 ret = PTR_ERR(vop2->rgb);
2730 goto err_crtcs;
2731 }
2732 vop2->rgb = NULL;
2733 }
2734 }
2735
2689 rockchip_drm_dma_init_device(vop2->drm, vop2->dev);2736 rockchip_drm_dma_init_device(vop2->drm, vop2->dev);
2690 2737
2691 pm_runtime_enable(&pdev->dev);2738 pm_runtime_enable(&pdev->dev);
2692 2739
2693 return 0;2740 return 0;
2741
2742err_crtcs:
2743 vop2_destroy_crtcs(vop2);
2744
2745 return ret;
2694}2746}
2695 2747
2696static void vop2_unbind(struct device *dev, struct device *master, void *data)2748static void vop2_unbind(struct device *dev, struct device *master, void *data)
2697{2749{
2698 struct vop2 *vop2 = dev_get_drvdata(dev);2750 struct vop2 *vop2 = dev_get_drvdata(dev);
2699 struct drm_device *drm = vop2->drm;
2700 struct list_head *plane_list = &drm->mode_config.plane_list;
2701 struct list_head *crtc_list = &drm->mode_config.crtc_list;
2702 struct drm_crtc *crtc, *tmpc;
2703 struct drm_plane *plane, *tmpp;
2704 2751
2705 pm_runtime_disable(dev);2752 pm_runtime_disable(dev);
2706 2753
2707 list_for_each_entry_safe(plane, tmpp, plane_list, head)2754 if (vop2->rgb)
2708 drm_plane_cleanup(plane);2755 rockchip_rgb_fini(vop2->rgb);
2709 2756
2710 list_for_each_entry_safe(crtc, tmpc, crtc_list, head)2757 vop2_destroy_crtcs(vop2);
2711 vop2_destroy_crtc(crtc);
2712}2758}
2713 2759
2714const struct component_ops vop2_component_ops = {2760const struct component_ops vop2_component_ops = {
drivers/gpu/drm/rockchip/rockchip_rgb.c+10−9
@@ -22,13 +22,11 @@ · 21 unmodified lines
22#include "rockchip_drm_vop.h"22#include "rockchip_drm_vop.h"
23#include "rockchip_rgb.h"23#include "rockchip_rgb.h"
24 24
25#define encoder_to_rgb(c) container_of(c, struct rockchip_rgb, encoder)
26
27struct rockchip_rgb {25struct rockchip_rgb {
28 struct device *dev;26 struct device *dev;
29 struct drm_device *drm_dev;27 struct drm_device *drm_dev;
30 struct drm_bridge *bridge;28 struct drm_bridge *bridge;
31 struct drm_encoder encoder;29 struct rockchip_encoder encoder;
32 struct drm_connector connector;30 struct drm_connector connector;
33 int output_mode;31 int output_mode;
34};32};
@@ -74,7 +72,8 @@ struct drm_encoder_helper_funcs rockchip_rgb_encoder_helper_funcs = { · 39 unmodified lines
74 72
75struct rockchip_rgb *rockchip_rgb_init(struct device *dev,73struct rockchip_rgb *rockchip_rgb_init(struct device *dev,
76 struct drm_crtc *crtc,74 struct drm_crtc *crtc,
77 struct drm_device *drm_dev)75 struct drm_device *drm_dev,
76 int video_port)
78{77{
79 struct rockchip_rgb *rgb;78 struct rockchip_rgb *rgb;
80 struct drm_encoder *encoder;79 struct drm_encoder *encoder;
@@ -92,7 +91,7 @@ struct rockchip_rgb *rockchip_rgb_init(struct device *dev, · 11 unmodified lines
92 rgb->dev = dev;91 rgb->dev = dev;
93 rgb->drm_dev = drm_dev;92 rgb->drm_dev = drm_dev;
94 93
95 port = of_graph_get_port_by_id(dev->of_node, 0);94 port = of_graph_get_port_by_id(dev->of_node, video_port);
96 if (!port)95 if (!port)
97 return ERR_PTR(-EINVAL);96 return ERR_PTR(-EINVAL);
98 97
@@ -105,8 +104,8 @@ struct rockchip_rgb *rockchip_rgb_init(struct device *dev, · 6 unmodified lines
105 continue;104 continue;
106 105
107 child_count++;106 child_count++;
108 ret = drm_of_find_panel_or_bridge(dev->of_node, 0, endpoint_id,107 ret = drm_of_find_panel_or_bridge(dev->of_node, video_port,
109 &panel, &bridge);108 endpoint_id, &panel, &bridge);
110 if (!ret) {109 if (!ret) {
111 of_node_put(endpoint);110 of_node_put(endpoint);
112 break;111 break;
@@ -125,7 +124,7 @@ struct rockchip_rgb *rockchip_rgb_init(struct device *dev, · 12 unmodified lines
125 return ERR_PTR(ret);124 return ERR_PTR(ret);
126 }125 }
127 126
128 encoder = &rgb->encoder;127 encoder = &rgb->encoder.encoder;
129 encoder->possible_crtcs = drm_crtc_mask(crtc);128 encoder->possible_crtcs = drm_crtc_mask(crtc);
130 129
131 ret = drm_simple_encoder_init(drm_dev, encoder, DRM_MODE_ENCODER_NONE);130 ret = drm_simple_encoder_init(drm_dev, encoder, DRM_MODE_ENCODER_NONE);
@@ -161,6 +160,8 @@ struct rockchip_rgb *rockchip_rgb_init(struct device *dev, · 29 unmodified lines
161 goto err_free_encoder;160 goto err_free_encoder;
162 }161 }
163 162
163 rgb->encoder.crtc_endpoint_id = endpoint_id;
164
164 ret = drm_connector_attach_encoder(connector, encoder);165 ret = drm_connector_attach_encoder(connector, encoder);
165 if (ret < 0) {166 if (ret < 0) {
166 DRM_DEV_ERROR(drm_dev->dev,167 DRM_DEV_ERROR(drm_dev->dev,
@@ -182,6 +183,6 @@ void rockchip_rgb_fini(struct rockchip_rgb *rgb) · 15 unmodified lines
182{183{
183 drm_panel_bridge_remove(rgb->bridge);184 drm_panel_bridge_remove(rgb->bridge);
184 drm_connector_cleanup(&rgb->connector);185 drm_connector_cleanup(&rgb->connector);
185 drm_encoder_cleanup(&rgb->encoder);186 drm_encoder_cleanup(&rgb->encoder.encoder);
186}187}
187EXPORT_SYMBOL_GPL(rockchip_rgb_fini);188EXPORT_SYMBOL_GPL(rockchip_rgb_fini);
drivers/gpu/drm/rockchip/rockchip_rgb.h+4−2
@@ -8,12 +8,14 @@ · 7 unmodified lines
8#ifdef CONFIG_ROCKCHIP_RGB8#ifdef CONFIG_ROCKCHIP_RGB
9struct rockchip_rgb *rockchip_rgb_init(struct device *dev,9struct rockchip_rgb *rockchip_rgb_init(struct device *dev,
10 struct drm_crtc *crtc,10 struct drm_crtc *crtc,
11 struct drm_device *drm_dev);11 struct drm_device *drm_dev,
12 int video_port);
12void rockchip_rgb_fini(struct rockchip_rgb *rgb);13void rockchip_rgb_fini(struct rockchip_rgb *rgb);
13#else14#else
14static inline struct rockchip_rgb *rockchip_rgb_init(struct device *dev,15static inline struct rockchip_rgb *rockchip_rgb_init(struct device *dev,
15 struct drm_crtc *crtc,16 struct drm_crtc *crtc,
16 struct drm_device *drm_dev)17 struct drm_device *drm_dev,
18 int video_port)
17{19{
18 return NULL;20 return NULL;
19}21}
drivers/gpu/drm/scheduler/sched_main.c+29−0
@@ -53,6 +53,7 @@ · 52 unmodified lines
53 53
54#include <drm/drm_print.h>54#include <drm/drm_print.h>
55#include <drm/drm_gem.h>55#include <drm/drm_gem.h>
56#include <drm/drm_syncobj.h>
56#include <drm/gpu_scheduler.h>57#include <drm/gpu_scheduler.h>
57#include <drm/spsc_queue.h>58#include <drm/spsc_queue.h>
58 59
@@ -718,6 +719,34 @@ int drm_sched_job_add_dependency(struct drm_sched_job *job, · 659 unmodified lines
718}719}
719EXPORT_SYMBOL(drm_sched_job_add_dependency);720EXPORT_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 */
734int 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}
748EXPORT_SYMBOL(drm_sched_job_add_syncobj_dependency);
749
721/**750/**
722 * drm_sched_job_add_resv_dependencies - add all fences from the resv to the job751 * drm_sched_job_add_resv_dependencies - add all fences from the resv to the job
723 * @job: scheduler job to add the dependencies to752 * @job: scheduler job to add the dependencies to
drivers/gpu/drm/tests/drm_format_helper_test.c+5−5
@@ -597,7 +597,7 @@ static void drm_test_fb_xrgb8888_to_xrgb1555(struct kunit *test) · 596 unmodified lines
597 597
598 drm_fb_xrgb8888_to_xrgb1555(&dst, &result->dst_pitch, &src, &fb, &params->clip);598 drm_fb_xrgb8888_to_xrgb1555(&dst, &result->dst_pitch, &src, &fb, &params->clip);
599 buf = le16buf_to_cpu(test, (__force const __le16 *)buf, dst_size / sizeof(__le16));599 buf = le16buf_to_cpu(test, (__force const __le16 *)buf, dst_size / sizeof(__le16));
600 KUNIT_EXPECT_EQ(test, memcmp(buf, result->expected, dst_size), 0);600 KUNIT_EXPECT_MEMEQ(test, buf, result->expected, dst_size);
601}601}
602 602
603static void drm_test_fb_xrgb8888_to_argb1555(struct kunit *test)603static void drm_test_fb_xrgb8888_to_argb1555(struct kunit *test)
@@ -628,7 +628,7 @@ static void drm_test_fb_xrgb8888_to_argb1555(struct kunit *test) · 24 unmodified lines
628 628
629 drm_fb_xrgb8888_to_argb1555(&dst, &result->dst_pitch, &src, &fb, &params->clip);629 drm_fb_xrgb8888_to_argb1555(&dst, &result->dst_pitch, &src, &fb, &params->clip);
630 buf = le16buf_to_cpu(test, (__force const __le16 *)buf, dst_size / sizeof(__le16));630 buf = le16buf_to_cpu(test, (__force const __le16 *)buf, dst_size / sizeof(__le16));
631 KUNIT_EXPECT_EQ(test, memcmp(buf, result->expected, dst_size), 0);631 KUNIT_EXPECT_MEMEQ(test, buf, result->expected, dst_size);
632}632}
633 633
634static void drm_test_fb_xrgb8888_to_rgba5551(struct kunit *test)634static void drm_test_fb_xrgb8888_to_rgba5551(struct kunit *test)
@@ -659,7 +659,7 @@ static void drm_test_fb_xrgb8888_to_rgba5551(struct kunit *test) · 24 unmodified lines
659 659
660 drm_fb_xrgb8888_to_rgba5551(&dst, &result->dst_pitch, &src, &fb, &params->clip);660 drm_fb_xrgb8888_to_rgba5551(&dst, &result->dst_pitch, &src, &fb, &params->clip);
661 buf = le16buf_to_cpu(test, (__force const __le16 *)buf, dst_size / sizeof(__le16));661 buf = le16buf_to_cpu(test, (__force const __le16 *)buf, dst_size / sizeof(__le16));
662 KUNIT_EXPECT_EQ(test, memcmp(buf, result->expected, dst_size), 0);662 KUNIT_EXPECT_MEMEQ(test, buf, result->expected, dst_size);
663}663}
664 664
665static void drm_test_fb_xrgb8888_to_rgb888(struct kunit *test)665static void drm_test_fb_xrgb8888_to_rgb888(struct kunit *test)
@@ -724,7 +724,7 @@ static void drm_test_fb_xrgb8888_to_argb8888(struct kunit *test) · 58 unmodified lines
724 724
725 drm_fb_xrgb8888_to_argb8888(&dst, &result->dst_pitch, &src, &fb, &params->clip);725 drm_fb_xrgb8888_to_argb8888(&dst, &result->dst_pitch, &src, &fb, &params->clip);
726 buf = le32buf_to_cpu(test, (__force const __le32 *)buf, dst_size / sizeof(u32));726 buf = le32buf_to_cpu(test, (__force const __le32 *)buf, dst_size / sizeof(u32));
727 KUNIT_EXPECT_EQ(test, memcmp(buf, result->expected, dst_size), 0);727 KUNIT_EXPECT_MEMEQ(test, buf, result->expected, dst_size);
728}728}
729 729
730static void drm_test_fb_xrgb8888_to_xrgb2101010(struct kunit *test)730static void drm_test_fb_xrgb8888_to_xrgb2101010(struct kunit *test)
@@ -786,7 +786,7 @@ static void drm_test_fb_xrgb8888_to_argb2101010(struct kunit *test) · 55 unmodified lines
786 786
787 drm_fb_xrgb8888_to_argb2101010(&dst, &result->dst_pitch, &src, &fb, &params->clip);787 drm_fb_xrgb8888_to_argb2101010(&dst, &result->dst_pitch, &src, &fb, &params->clip);
788 buf = le32buf_to_cpu(test, (__force const __le32 *)buf, dst_size / sizeof(u32));788 buf = le32buf_to_cpu(test, (__force const __le32 *)buf, dst_size / sizeof(u32));
789 KUNIT_EXPECT_EQ(test, memcmp(buf, result->expected, dst_size), 0);789 KUNIT_EXPECT_MEMEQ(test, buf, result->expected, dst_size);
790}790}
791 791
792static struct kunit_case drm_format_helper_test_cases[] = {792static struct kunit_case drm_format_helper_test_cases[] = {
drivers/gpu/drm/tidss/tidss_dispc.c+4−8
@@ -1985,9 +1985,9 @@ dma_addr_t dispc_plane_state_p_uv_addr(const struct drm_plane_state *state) · 1984 unmodified lines
1985 (y * fb->pitches[1] / fb->format->vsub);1985 (y * fb->pitches[1] / fb->format->vsub);
1986}1986}
1987 1987
1988int dispc_plane_setup(struct dispc_device *dispc, u32 hw_plane,1988void dispc_plane_setup(struct dispc_device *dispc, u32 hw_plane,
1989 const struct drm_plane_state *state,1989 const struct drm_plane_state *state,
1990 u32 hw_videoport)1990 u32 hw_videoport)
1991{1991{
1992 bool lite = dispc->feat->vid_lite[hw_plane];1992 bool lite = dispc->feat->vid_lite[hw_plane];
1993 u32 fourcc = state->fb->format->format;1993 u32 fourcc = state->fb->format->format;
@@ -2066,15 +2066,11 @@ int dispc_plane_setup(struct dispc_device *dispc, u32 hw_plane, · 72 unmodified lines
2066 else2066 else
2067 VID_REG_FLD_MOD(dispc, hw_plane, DISPC_VID_ATTRIBUTES, 0,2067 VID_REG_FLD_MOD(dispc, hw_plane, DISPC_VID_ATTRIBUTES, 0,
2068 28, 28);2068 28, 28);
2069
2070 return 0;
2071}2069}
2072 2070
2073int dispc_plane_enable(struct dispc_device *dispc, u32 hw_plane, bool enable)2071void dispc_plane_enable(struct dispc_device *dispc, u32 hw_plane, bool enable)
2074{2072{
2075 VID_REG_FLD_MOD(dispc, hw_plane, DISPC_VID_ATTRIBUTES, !!enable, 0, 0);2073 VID_REG_FLD_MOD(dispc, hw_plane, DISPC_VID_ATTRIBUTES, !!enable, 0, 0);
2076
2077 return 0;
2078}2074}
2079 2075
2080static u32 dispc_vid_get_fifo_size(struct dispc_device *dispc, u32 hw_plane)2076static u32 dispc_vid_get_fifo_size(struct dispc_device *dispc, u32 hw_plane)
drivers/gpu/drm/tidss/tidss_dispc.h+4−4
@@ -123,10 +123,10 @@ int dispc_runtime_resume(struct dispc_device *dispc); · 122 unmodified lines
123int dispc_plane_check(struct dispc_device *dispc, u32 hw_plane,123int dispc_plane_check(struct dispc_device *dispc, u32 hw_plane,
124 const struct drm_plane_state *state,124 const struct drm_plane_state *state,
125 u32 hw_videoport);125 u32 hw_videoport);
126int dispc_plane_setup(struct dispc_device *dispc, u32 hw_plane,126void dispc_plane_setup(struct dispc_device *dispc, u32 hw_plane,
127 const struct drm_plane_state *state,127 const struct drm_plane_state *state,
128 u32 hw_videoport);128 u32 hw_videoport);
129int dispc_plane_enable(struct dispc_device *dispc, u32 hw_plane, bool enable);129void dispc_plane_enable(struct dispc_device *dispc, u32 hw_plane, bool enable);
130const u32 *dispc_plane_formats(struct dispc_device *dispc, unsigned int *len);130const u32 *dispc_plane_formats(struct dispc_device *dispc, unsigned int *len);
131 131
132int dispc_init(struct tidss_device *tidss);132int dispc_init(struct tidss_device *tidss);
drivers/gpu/drm/tidss/tidss_plane.c+11−9
@@ -113,7 +113,6 @@ static void tidss_plane_atomic_update(struct drm_plane *plane, · 112 unmodified lines
113 struct drm_plane_state *new_state = drm_atomic_get_new_plane_state(state,113 struct drm_plane_state *new_state = drm_atomic_get_new_plane_state(state,
114 plane);114 plane);
115 u32 hw_videoport;115 u32 hw_videoport;
116 int ret;
117 116
118 dev_dbg(ddev->dev, "%s\n", __func__);117 dev_dbg(ddev->dev, "%s\n", __func__);
119 118
@@ -124,15 +123,17 @@ static void tidss_plane_atomic_update(struct drm_plane *plane, · 4 unmodified lines
124 123
125 hw_videoport = to_tidss_crtc(new_state->crtc)->hw_videoport;124 hw_videoport = to_tidss_crtc(new_state->crtc)->hw_videoport;
126 125
127 ret = dispc_plane_setup(tidss->dispc, tplane->hw_plane_id,126 dispc_plane_setup(tidss->dispc, tplane->hw_plane_id, new_state, hw_videoport);
128 new_state, hw_videoport);127}
129 128
130 if (ret) {129static void tidss_plane_atomic_enable(struct drm_plane *plane,
131 dev_err(plane->dev->dev, "%s: Failed to setup plane %d\n",130 struct drm_atomic_state *state)
132 __func__, tplane->hw_plane_id);131{
133 dispc_plane_enable(tidss->dispc, tplane->hw_plane_id, false);132 struct drm_device *ddev = plane->dev;
134 return;133 struct tidss_device *tidss = to_tidss(ddev);
135 }134 struct tidss_plane *tplane = to_tidss_plane(plane);
135
136 dev_dbg(ddev->dev, "%s\n", __func__);
136 137
137 dispc_plane_enable(tidss->dispc, tplane->hw_plane_id, true);138 dispc_plane_enable(tidss->dispc, tplane->hw_plane_id, true);
138}139}
@@ -160,6 +161,7 @@ static void drm_plane_destroy(struct drm_plane *plane) · 21 unmodified lines
160static const struct drm_plane_helper_funcs tidss_plane_helper_funcs = {161static const struct drm_plane_helper_funcs tidss_plane_helper_funcs = {
161 .atomic_check = tidss_plane_atomic_check,162 .atomic_check = tidss_plane_atomic_check,
162 .atomic_update = tidss_plane_atomic_update,163 .atomic_update = tidss_plane_atomic_update,
164 .atomic_enable = tidss_plane_atomic_enable,
163 .atomic_disable = tidss_plane_atomic_disable,165 .atomic_disable = tidss_plane_atomic_disable,
164};166};
165 167
drivers/gpu/drm/tiny/simpledrm.c+22−9
@@ -606,16 +606,12 @@ static const struct drm_mode_config_funcs simpledrm_mode_config_funcs = { · 605 unmodified lines
606 */606 */
607 607
608static struct drm_display_mode simpledrm_mode(unsigned int width,608static struct drm_display_mode simpledrm_mode(unsigned int width,
609 unsigned int height)609 unsigned int height,
610 unsigned int width_mm,
611 unsigned int height_mm)
610{612{
611 /*
612 * Assume a monitor resolution of 96 dpi to
613 * get a somewhat reasonable screen size.
614 */
615 const struct drm_display_mode mode = {613 const struct drm_display_mode mode = {
616 DRM_MODE_INIT(60, width, height,614 DRM_MODE_INIT(60, width, height, width_mm, height_mm)
617 DRM_MODE_RES_MM(width, 96ul),
618 DRM_MODE_RES_MM(height, 96ul))
619 };615 };
620 616
621 return mode;617 return mode;
@@ -629,6 +625,8 @@ static struct simpledrm_device *simpledrm_device_create(struct drm_driver *drv, · 7 unmodified lines
629 struct simpledrm_device *sdev;625 struct simpledrm_device *sdev;
630 struct drm_device *dev;626 struct drm_device *dev;
631 int width, height, stride;627 int width, height, stride;
628 int width_mm = 0, height_mm = 0;
629 struct device_node *panel_node;
632 const struct drm_format_info *format;630 const struct drm_format_info *format;
633 struct resource *res, *mem = NULL;631 struct resource *res, *mem = NULL;
634 struct drm_plane *primary_plane;632 struct drm_plane *primary_plane;
@@ -685,6 +683,12 @@ static struct simpledrm_device *simpledrm_device_create(struct drm_driver *drv, · 50 unmodified lines
685 mem = simplefb_get_memory_of(dev, of_node);683 mem = simplefb_get_memory_of(dev, of_node);
686 if (IS_ERR(mem))684 if (IS_ERR(mem))
687 return ERR_CAST(mem);685 return ERR_CAST(mem);
686 panel_node = of_parse_phandle(of_node, "panel", 0);
687 if (panel_node) {
688 simplefb_read_u32_of(dev, panel_node, "width-mm", &width_mm);
689 simplefb_read_u32_of(dev, panel_node, "height-mm", &height_mm);
690 of_node_put(panel_node);
691 }
688 } else {692 } else {
689 drm_err(dev, "no simplefb configuration found\n");693 drm_err(dev, "no simplefb configuration found\n");
690 return ERR_PTR(-ENODEV);694 return ERR_PTR(-ENODEV);
@@ -695,7 +699,16 @@ static struct simpledrm_device *simpledrm_device_create(struct drm_driver *drv, · 4 unmodified lines
695 return ERR_PTR(-EINVAL);699 return ERR_PTR(-EINVAL);
696 }700 }
697 701
698 sdev->mode = simpledrm_mode(width, height);702 /*
703 * Assume a monitor resolution of 96 dpi if physical dimensions
704 * are not specified to get a somewhat reasonable screen size.
705 */
706 if (!width_mm)
707 width_mm = DRM_MODE_RES_MM(width, 96ul);
708 if (!height_mm)
709 height_mm = DRM_MODE_RES_MM(height, 96ul);
710
711 sdev->mode = simpledrm_mode(width, height, width_mm, height_mm);
699 sdev->format = format;712 sdev->format = format;
700 sdev->pitch = stride;713 sdev->pitch = stride;
701 714
drivers/gpu/drm/ttm/ttm_bo.c+13−17
@@ -120,8 +120,7 @@ static int ttm_bo_handle_move_mem(struct ttm_buffer_object *bo, · 119 unmodified lines
120 bool old_use_tt, new_use_tt;120 bool old_use_tt, new_use_tt;
121 int ret;121 int ret;
122 122
123 old_use_tt = bo->resource &&123 old_use_tt = !bo->resource || ttm_manager_type(bdev, bo->resource->mem_type)->use_tt;
124 ttm_manager_type(bdev, bo->resource->mem_type)->use_tt;
125 new_use_tt = ttm_manager_type(bdev, mem->mem_type)->use_tt;124 new_use_tt = ttm_manager_type(bdev, mem->mem_type)->use_tt;
126 125
127 ttm_bo_unmap_virtual(bo);126 ttm_bo_unmap_virtual(bo);
@@ -894,14 +893,18 @@ int ttm_bo_validate(struct ttm_buffer_object *bo, · 766 unmodified lines
894 if (!placement->num_placement && !placement->num_busy_placement)893 if (!placement->num_placement && !placement->num_busy_placement)
895 return ttm_bo_pipeline_gutting(bo);894 return ttm_bo_pipeline_gutting(bo);
896 895
897 /*896 /* Check whether we need to move buffer. */
898 * Check whether we need to move buffer.897 if (bo->resource && ttm_resource_compat(bo->resource, placement))
899 */898 return 0;
900 if (!bo->resource || !ttm_resource_compat(bo->resource, placement)) {899
901 ret = ttm_bo_move_buffer(bo, placement, ctx);900 /* Moving of pinned BOs is forbidden */
902 if (ret)901 if (bo->pin_count)
903 return ret;902 return -EINVAL;
904 }903
904 ret = ttm_bo_move_buffer(bo, placement, ctx);
905 if (ret)
906 return ret;
907
905 /*908 /*
906 * We might need to add a TTM.909 * We might need to add a TTM.
907 */910 */
@@ -953,7 +956,6 @@ int ttm_bo_init_reserved(struct ttm_device *bdev, struct ttm_buffer_object *bo, · 45 unmodified lines
953 struct sg_table *sg, struct dma_resv *resv,956 struct sg_table *sg, struct dma_resv *resv,
954 void (*destroy) (struct ttm_buffer_object *))957 void (*destroy) (struct ttm_buffer_object *))
955{958{
956 static const struct ttm_place sys_mem = { .mem_type = TTM_PL_SYSTEM };
957 int ret;959 int ret;
958 960
959 kref_init(&bo->kref);961 kref_init(&bo->kref);
@@ -970,12 +972,6 @@ int ttm_bo_init_reserved(struct ttm_device *bdev, struct ttm_buffer_object *bo, · 10 unmodified lines
970 bo->base.resv = &bo->base._resv;972 bo->base.resv = &bo->base._resv;
971 atomic_inc(&ttm_glob.bo_count);973 atomic_inc(&ttm_glob.bo_count);
972 974
973 ret = ttm_resource_alloc(bo, &sys_mem, &bo->resource);
974 if (unlikely(ret)) {
975 ttm_bo_put(bo);
976 return ret;
977 }
978
979 /*975 /*
980 * For ttm_bo_type_device buffers, allocate976 * For ttm_bo_type_device buffers, allocate
981 * address space from the device.977 * address space from the device.
drivers/gpu/drm/ttm/ttm_bo_util.c+4−15
@@ -157,8 +157,8 @@ int ttm_bo_move_memcpy(struct ttm_buffer_object *bo, · 156 unmodified lines
157 bool clear;157 bool clear;
158 int ret = 0;158 int ret = 0;
159 159
160 if (!src_mem)160 if (WARN_ON(!src_mem))
161 return 0;161 return -EINVAL;
162 162
163 src_man = ttm_manager_type(bdev, src_mem->mem_type);163 src_man = ttm_manager_type(bdev, src_mem->mem_type);
164 if (ttm && ((ttm->page_flags & TTM_TT_FLAG_SWAPPED) ||164 if (ttm && ((ttm->page_flags & TTM_TT_FLAG_SWAPPED) ||
@@ -704,30 +704,23 @@ EXPORT_SYMBOL(ttm_bo_move_sync_cleanup); · 539 unmodified lines
704 */704 */
705int ttm_bo_pipeline_gutting(struct ttm_buffer_object *bo)705int ttm_bo_pipeline_gutting(struct ttm_buffer_object *bo)
706{706{
707 static const struct ttm_place sys_mem = { .mem_type = TTM_PL_SYSTEM };
708 struct ttm_buffer_object *ghost;707 struct ttm_buffer_object *ghost;
709 struct ttm_resource *sys_res;
710 struct ttm_tt *ttm;708 struct ttm_tt *ttm;
711 int ret;709 int ret;
712 710
713 ret = ttm_resource_alloc(bo, &sys_mem, &sys_res);
714 if (ret)
715 return ret;
716
717 /* If already idle, no need for ghost object dance. */711 /* If already idle, no need for ghost object dance. */
718 if (dma_resv_test_signaled(bo->base.resv, DMA_RESV_USAGE_BOOKKEEP)) {712 if (dma_resv_test_signaled(bo->base.resv, DMA_RESV_USAGE_BOOKKEEP)) {
719 if (!bo->ttm) {713 if (!bo->ttm) {
720 /* See comment below about clearing. */714 /* See comment below about clearing. */
721 ret = ttm_tt_create(bo, true);715 ret = ttm_tt_create(bo, true);
722 if (ret)716 if (ret)
723 goto error_free_sys_mem;717 return ret;
724 } else {718 } else {
725 ttm_tt_unpopulate(bo->bdev, bo->ttm);719 ttm_tt_unpopulate(bo->bdev, bo->ttm);
726 if (bo->type == ttm_bo_type_device)720 if (bo->type == ttm_bo_type_device)
727 ttm_tt_mark_for_clear(bo->ttm);721 ttm_tt_mark_for_clear(bo->ttm);
728 }722 }
729 ttm_resource_free(bo, &bo->resource);723 ttm_resource_free(bo, &bo->resource);
730 ttm_bo_assign_mem(bo, sys_res);
731 return 0;724 return 0;
732 }725 }
733 726
@@ -744,7 +737,7 @@ int ttm_bo_pipeline_gutting(struct ttm_buffer_object *bo) · 10 unmodified lines
744 ret = ttm_tt_create(bo, true);737 ret = ttm_tt_create(bo, true);
745 swap(bo->ttm, ttm);738 swap(bo->ttm, ttm);
746 if (ret)739 if (ret)
747 goto error_free_sys_mem;740 return ret;
748 741
749 ret = ttm_buffer_object_transfer(bo, &ghost);742 ret = ttm_buffer_object_transfer(bo, &ghost);
750 if (ret)743 if (ret)
@@ -760,13 +753,9 @@ int ttm_bo_pipeline_gutting(struct ttm_buffer_object *bo) · 9 unmodified lines
760 dma_resv_unlock(&ghost->base._resv);753 dma_resv_unlock(&ghost->base._resv);
761 ttm_bo_put(ghost);754 ttm_bo_put(ghost);
762 bo->ttm = ttm;755 bo->ttm = ttm;
763 ttm_bo_assign_mem(bo, sys_res);
764 return 0;756 return 0;
765 757
766error_destroy_tt:758error_destroy_tt:
767 ttm_tt_destroy(bo->bdev, ttm);759 ttm_tt_destroy(bo->bdev, ttm);
768
769error_free_sys_mem:
770 ttm_resource_free(bo, &sys_res);
771 return ret;760 return ret;
772}761}
drivers/gpu/drm/ttm/ttm_resource.c+0−1
@@ -361,7 +361,6 @@ bool ttm_resource_compat(struct ttm_resource *res, · 360 unmodified lines
361 361
362 return false;362 return false;
363}363}
364EXPORT_SYMBOL(ttm_resource_compat);
365 364
366void ttm_resource_set_bo(struct ttm_resource *res,365void ttm_resource_set_bo(struct ttm_resource *res,
367 struct ttm_buffer_object *bo)366 struct ttm_buffer_object *bo)
drivers/gpu/drm/v3d/v3d_gem.c+8−18
@@ -396,20 +396,6 @@ v3d_wait_bo_ioctl(struct drm_device *dev, void *data, · 395 unmodified lines
396 return ret;396 return ret;
397}397}
398 398
399static int
400v3d_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
413static int399static int
414v3d_job_init(struct v3d_dev *v3d, struct drm_file *file_priv,400v3d_job_init(struct v3d_dev *v3d, struct drm_file *file_priv,
415 void **container, size_t size, void (*free)(struct kref *ref),401 void **container, size_t size, void (*free)(struct kref *ref),
@@ -447,14 +433,18 @@ v3d_job_init(struct v3d_dev *v3d, struct drm_file *file_priv, · 31 unmodified lines
447 DRM_DEBUG("Failed to copy wait dep handle.\n");433 DRM_DEBUG("Failed to copy wait dep handle.\n");
448 goto fail_deps;434 goto fail_deps;
449 }435 }
450 ret = v3d_job_add_deps(file_priv, job, in.handle, 0);436 ret = drm_sched_job_add_syncobj_dependency(&job->base, file_priv, in.handle, 0);
451 if (ret)437
438 // TODO: Investigate why this was filtered out for the IOCTL.
439 if (ret && ret != -ENOENT)
452 goto fail_deps;440 goto fail_deps;
453 }441 }
454 }442 }
455 } else {443 } else {
456 ret = v3d_job_add_deps(file_priv, job, in_sync, 0);444 ret = drm_sched_job_add_syncobj_dependency(&job->base, file_priv, in_sync, 0);
457 if (ret)445
446 // TODO: Investigate why this was filtered out for the IOCTL.
447 if (ret && ret != -ENOENT)
458 goto fail_deps;448 goto fail_deps;
459 }449 }
460 450
drivers/gpu/drm/vc4/vc4_drv.h+1−1
@@ -690,7 +690,7 @@ struct vc4_exec_info { · 689 unmodified lines
690 /* This is the array of BOs that were looked up at the start of exec.690 /* This is the array of BOs that were looked up at the start of exec.
691 * Command validation will use indices into this array.691 * Command validation will use indices into this array.
692 */692 */
693 struct drm_gem_dma_object **bo;693 struct drm_gem_object **bo;
694 uint32_t bo_count;694 uint32_t bo_count;
695 695
696 /* List of BOs that are being written by the RCL. Other than696 /* List of BOs that are being written by the RCL. Other than
drivers/gpu/drm/vc4/vc4_gem.c+18−60
@@ -199,7 +199,7 @@ vc4_save_hang_state(struct drm_device *dev) · 198 unmodified lines
199 continue;199 continue;
200 200
201 for (j = 0; j < exec[i]->bo_count; j++) {201 for (j = 0; j < exec[i]->bo_count; j++) {
202 bo = to_vc4_bo(&exec[i]->bo[j]->base);202 bo = to_vc4_bo(exec[i]->bo[j]);
203 203
204 /* Retain BOs just in case they were marked purgeable.204 /* Retain BOs just in case they were marked purgeable.
205 * This prevents the BO from being purged before205 * This prevents the BO from being purged before
@@ -207,8 +207,8 @@ vc4_save_hang_state(struct drm_device *dev) · 1 unmodified line
207 */207 */
208 WARN_ON(!refcount_read(&bo->usecnt));208 WARN_ON(!refcount_read(&bo->usecnt));
209 refcount_inc(&bo->usecnt);209 refcount_inc(&bo->usecnt);
210 drm_gem_object_get(&exec[i]->bo[j]->base);210 drm_gem_object_get(exec[i]->bo[j]);
211 kernel_state->bo[k++] = &exec[i]->bo[j]->base;211 kernel_state->bo[k++] = exec[i]->bo[j];
212 }212 }
213 213
214 list_for_each_entry(bo, &exec[i]->unref_list, unref_head) {214 list_for_each_entry(bo, &exec[i]->unref_list, unref_head) {
@@ -558,7 +558,7 @@ vc4_update_bo_seqnos(struct vc4_exec_info *exec, uint64_t seqno) · 343 unmodified lines
558 unsigned i;558 unsigned i;
559 559
560 for (i = 0; i < exec->bo_count; i++) {560 for (i = 0; i < exec->bo_count; i++) {
561 bo = to_vc4_bo(&exec->bo[i]->base);561 bo = to_vc4_bo(exec->bo[i]);
562 bo->seqno = seqno;562 bo->seqno = seqno;
563 563
564 dma_resv_add_fence(bo->base.base.resv, exec->fence,564 dma_resv_add_fence(bo->base.base.resv, exec->fence,
@@ -585,11 +585,8 @@ vc4_unlock_bo_reservations(struct drm_device *dev, · 20 unmodified lines
585{585{
586 int i;586 int i;
587 587
588 for (i = 0; i < exec->bo_count; i++) {588 for (i = 0; i < exec->bo_count; i++)
589 struct drm_gem_object *bo = &exec->bo[i]->base;589 dma_resv_unlock(exec->bo[i]->resv);
590
591 dma_resv_unlock(bo->resv);
592 }
593 590
594 ww_acquire_fini(acquire_ctx);591 ww_acquire_fini(acquire_ctx);
595}592}
@@ -614,7 +611,7 @@ vc4_lock_bo_reservations(struct drm_device *dev, · 18 unmodified lines
614 611
615retry:612retry:
616 if (contended_lock != -1) {613 if (contended_lock != -1) {
617 bo = &exec->bo[contended_lock]->base;614 bo = exec->bo[contended_lock];
618 ret = dma_resv_lock_slow_interruptible(bo->resv, acquire_ctx);615 ret = dma_resv_lock_slow_interruptible(bo->resv, acquire_ctx);
619 if (ret) {616 if (ret) {
620 ww_acquire_done(acquire_ctx);617 ww_acquire_done(acquire_ctx);
@@ -626,19 +623,19 @@ retry: · 5 unmodified lines
626 if (i == contended_lock)623 if (i == contended_lock)
627 continue;624 continue;
628 625
629 bo = &exec->bo[i]->base;626 bo = exec->bo[i];
630 627
631 ret = dma_resv_lock_interruptible(bo->resv, acquire_ctx);628 ret = dma_resv_lock_interruptible(bo->resv, acquire_ctx);
632 if (ret) {629 if (ret) {
633 int j;630 int j;
634 631
635 for (j = 0; j < i; j++) {632 for (j = 0; j < i; j++) {
636 bo = &exec->bo[j]->base;633 bo = exec->bo[j];
637 dma_resv_unlock(bo->resv);634 dma_resv_unlock(bo->resv);
638 }635 }
639 636
640 if (contended_lock != -1 && contended_lock >= i) {637 if (contended_lock != -1 && contended_lock >= i) {
641 bo = &exec->bo[contended_lock]->base;638 bo = exec->bo[contended_lock];
642 639
643 dma_resv_unlock(bo->resv);640 dma_resv_unlock(bo->resv);
644 }641 }
@@ -659,7 +656,7 @@ retry: · 14 unmodified lines
659 * before we commit the CL to the hardware.656 * before we commit the CL to the hardware.
660 */657 */
661 for (i = 0; i < exec->bo_count; i++) {658 for (i = 0; i < exec->bo_count; i++) {
662 bo = &exec->bo[i]->base;659 bo = exec->bo[i];
663 660
664 ret = dma_resv_reserve_fences(bo->resv, 1);661 ret = dma_resv_reserve_fences(bo->resv, 1);
665 if (ret) {662 if (ret) {
@@ -749,7 +746,6 @@ vc4_cl_lookup_bos(struct drm_device *dev, · 83 unmodified lines
749 struct vc4_exec_info *exec)746 struct vc4_exec_info *exec)
750{747{
751 struct drm_vc4_submit_cl *args = exec->args;748 struct drm_vc4_submit_cl *args = exec->args;
752 uint32_t *handles;
753 int ret = 0;749 int ret = 0;
754 int i;750 int i;
755 751
@@ -763,54 +759,18 @@ vc4_cl_lookup_bos(struct drm_device *dev, · 7 unmodified lines
763 return -EINVAL;759 return -EINVAL;
764 }760 }
765 761
766 exec->bo = kvmalloc_array(exec->bo_count,762 ret = drm_gem_objects_lookup(file_priv, u64_to_user_ptr(args->bo_handles),
767 sizeof(struct drm_gem_dma_object *),763 exec->bo_count, &exec->bo);
768 GFP_KERNEL | __GFP_ZERO);
769 if (!exec->bo) {
770 DRM_ERROR("Failed to allocate validated BO pointers\n");
771 return -ENOMEM;
772 }
773
774 handles = kvmalloc_array(exec->bo_count, sizeof(uint32_t), GFP_KERNEL);
775 if (!handles) {
776 ret = -ENOMEM;
777 DRM_ERROR("Failed to allocate incoming GEM handles\n");
778 goto fail;
779 }
780
781 if (copy_from_user(handles, u64_to_user_ptr(args->bo_handles),
782 exec->bo_count * sizeof(uint32_t))) {
783 ret = -EFAULT;
784 DRM_ERROR("Failed to copy in GEM handles\n");
785 goto fail;
786 }
787
788 spin_lock(&file_priv->table_lock);
789 for (i = 0; i < exec->bo_count; i++) {
790 struct drm_gem_object *bo = idr_find(&file_priv->object_idr,
791 handles[i]);
792 if (!bo) {
793 DRM_DEBUG("Failed to look up GEM BO %d: %d\n",
794 i, handles[i]);
795 ret = -EINVAL;
796 break;
797 }
798
799 drm_gem_object_get(bo);
800 exec->bo[i] = (struct drm_gem_dma_object *)bo;
801 }
802 spin_unlock(&file_priv->table_lock);
803 764
804 if (ret)765 if (ret)
805 goto fail_put_bo;766 goto fail_put_bo;
806 767
807 for (i = 0; i < exec->bo_count; i++) {768 for (i = 0; i < exec->bo_count; i++) {
808 ret = vc4_bo_inc_usecnt(to_vc4_bo(&exec->bo[i]->base));769 ret = vc4_bo_inc_usecnt(to_vc4_bo(exec->bo[i]));
809 if (ret)770 if (ret)
810 goto fail_dec_usecnt;771 goto fail_dec_usecnt;
811 }772 }
812 773
813 kvfree(handles);
814 return 0;774 return 0;
815 775
816fail_dec_usecnt:776fail_dec_usecnt:
@@ -823,15 +783,13 @@ fail_dec_usecnt: · 6 unmodified lines
823 * step.783 * step.
824 */784 */
825 for (i-- ; i >= 0; i--)785 for (i-- ; i >= 0; i--)
826 vc4_bo_dec_usecnt(to_vc4_bo(&exec->bo[i]->base));786 vc4_bo_dec_usecnt(to_vc4_bo(exec->bo[i]));
827 787
828fail_put_bo:788fail_put_bo:
829 /* Release any reference to acquired objects. */789 /* Release any reference to acquired objects. */
830 for (i = 0; i < exec->bo_count && exec->bo[i]; i++)790 for (i = 0; i < exec->bo_count && exec->bo[i]; i++)
831 drm_gem_object_put(&exec->bo[i]->base);791 drm_gem_object_put(exec->bo[i]);
832 792
833fail:
834 kvfree(handles);
835 kvfree(exec->bo);793 kvfree(exec->bo);
836 exec->bo = NULL;794 exec->bo = NULL;
837 return ret;795 return ret;
@@ -974,10 +932,10 @@ vc4_complete_exec(struct drm_device *dev, struct vc4_exec_info *exec) · 136 unmodified lines
974 932
975 if (exec->bo) {933 if (exec->bo) {
976 for (i = 0; i < exec->bo_count; i++) {934 for (i = 0; i < exec->bo_count; i++) {
977 struct vc4_bo *bo = to_vc4_bo(&exec->bo[i]->base);935 struct vc4_bo *bo = to_vc4_bo(exec->bo[i]);
978 936
979 vc4_bo_dec_usecnt(bo);937 vc4_bo_dec_usecnt(bo);
980 drm_gem_object_put(&exec->bo[i]->base);938 drm_gem_object_put(exec->bo[i]);
981 }939 }
982 kvfree(exec->bo);940 kvfree(exec->bo);
983 }941 }
drivers/gpu/drm/vc4/vc4_hdmi.c+13−33
@@ -1466,6 +1466,12 @@ static void vc4_hdmi_encoder_pre_crtc_configure(struct drm_encoder *encoder, · 1465 unmodified lines
1466 if (!drm_dev_enter(drm, &idx))1466 if (!drm_dev_enter(drm, &idx))
1467 goto out;1467 goto out;
1468 1468
1469 ret = pm_runtime_resume_and_get(&vc4_hdmi->pdev->dev);
1470 if (ret < 0) {
1471 DRM_ERROR("Failed to retain power domain: %d\n", ret);
1472 goto err_dev_exit;
1473 }
1474
1469 /*1475 /*
1470 * As stated in RPi's vc4 firmware "HDMI state machine (HSM) clock must1476 * As stated in RPi's vc4 firmware "HDMI state machine (HSM) clock must
1471 * be faster than pixel clock, infinitesimally faster, tested in1477 * be faster than pixel clock, infinitesimally faster, tested in
@@ -1482,17 +1488,13 @@ static void vc4_hdmi_encoder_pre_crtc_configure(struct drm_encoder *encoder, · 10 unmodified lines
1482 * Additionally, the AXI clock needs to be at least 25% of1488 * Additionally, the AXI clock needs to be at least 25% of
1483 * pixel clock, but HSM ends up being the limiting factor.1489 * pixel clock, but HSM ends up being the limiting factor.
1484 */1490 */
1485 hsm_rate = max_t(unsigned long, 120000000, (tmds_char_rate / 100) * 101);1491 hsm_rate = max_t(unsigned long,
1492 HSM_MIN_CLOCK_FREQ,
1493 (tmds_char_rate / 100) * 101);
1486 ret = clk_set_min_rate(vc4_hdmi->hsm_clock, hsm_rate);1494 ret = clk_set_min_rate(vc4_hdmi->hsm_clock, hsm_rate);
1487 if (ret) {1495 if (ret) {
1488 DRM_ERROR("Failed to set HSM clock rate: %d\n", ret);1496 DRM_ERROR("Failed to set HSM clock rate: %d\n", ret);
1489 goto err_dev_exit;1497 goto err_put_runtime_pm;
1490 }
1491
1492 ret = pm_runtime_resume_and_get(&vc4_hdmi->pdev->dev);
1493 if (ret < 0) {
1494 DRM_ERROR("Failed to retain power domain: %d\n", ret);
1495 goto err_dev_exit;
1496 }1498 }
1497 1499
1498 ret = clk_set_rate(vc4_hdmi->pixel_clock, tmds_char_rate);1500 ret = clk_set_rate(vc4_hdmi->pixel_clock, tmds_char_rate);
@@ -3188,16 +3190,9 @@ static int vc4_hdmi_init_resources(struct drm_device *drm, · 1689 unmodified lines
3188 DRM_ERROR("Failed to get HDMI state machine clock\n");3190 DRM_ERROR("Failed to get HDMI state machine clock\n");
3189 return PTR_ERR(vc4_hdmi->hsm_clock);3191 return PTR_ERR(vc4_hdmi->hsm_clock);
3190 }3192 }
3191
3192 vc4_hdmi->audio_clock = vc4_hdmi->hsm_clock;3193 vc4_hdmi->audio_clock = vc4_hdmi->hsm_clock;
3193 vc4_hdmi->cec_clock = vc4_hdmi->hsm_clock;3194 vc4_hdmi->cec_clock = vc4_hdmi->hsm_clock;
3194 3195
3195 vc4_hdmi->hsm_rpm_clock = devm_clk_get(dev, "hdmi");
3196 if (IS_ERR(vc4_hdmi->hsm_rpm_clock)) {
3197 DRM_ERROR("Failed to get HDMI state machine clock\n");
3198 return PTR_ERR(vc4_hdmi->hsm_rpm_clock);
3199 }
3200
3201 return 0;3196 return 0;
3202}3197}
3203 3198
@@ -3280,12 +3275,6 @@ static int vc5_hdmi_init_resources(struct drm_device *drm, · 76 unmodified lines
3280 return PTR_ERR(vc4_hdmi->hsm_clock);3275 return PTR_ERR(vc4_hdmi->hsm_clock);
3281 }3276 }
3282 3277
3283 vc4_hdmi->hsm_rpm_clock = devm_clk_get(dev, "hdmi");
3284 if (IS_ERR(vc4_hdmi->hsm_rpm_clock)) {
3285 DRM_ERROR("Failed to get HDMI state machine clock\n");
3286 return PTR_ERR(vc4_hdmi->hsm_rpm_clock);
3287 }
3288
3289 vc4_hdmi->pixel_bvb_clock = devm_clk_get(dev, "bvb");3278 vc4_hdmi->pixel_bvb_clock = devm_clk_get(dev, "bvb");
3290 if (IS_ERR(vc4_hdmi->pixel_bvb_clock)) {3279 if (IS_ERR(vc4_hdmi->pixel_bvb_clock)) {
3291 DRM_ERROR("Failed to get pixel bvb clock\n");3280 DRM_ERROR("Failed to get pixel bvb clock\n");
@@ -3349,7 +3338,7 @@ static int vc4_hdmi_runtime_suspend(struct device *dev) · 57 unmodified lines
3349{3338{
3350 struct vc4_hdmi *vc4_hdmi = dev_get_drvdata(dev);3339 struct vc4_hdmi *vc4_hdmi = dev_get_drvdata(dev);
3351 3340
3352 clk_disable_unprepare(vc4_hdmi->hsm_rpm_clock);3341 clk_disable_unprepare(vc4_hdmi->hsm_clock);
3353 3342
3354 return 0;3343 return 0;
3355}3344}
@@ -3362,16 +3351,7 @@ static int vc4_hdmi_runtime_resume(struct device *dev) · 6 unmodified lines
3362 unsigned long rate;3351 unsigned long rate;
3363 int ret;3352 int ret;
3364 3353
3365 /*3354 ret = clk_prepare_enable(vc4_hdmi->hsm_clock);
3366 * The HSM clock is in the HDMI power domain, so we need to set
3367 * its frequency while the power domain is active so that it
3368 * keeps its rate.
3369 */
3370 ret = clk_set_min_rate(vc4_hdmi->hsm_rpm_clock, HSM_MIN_CLOCK_FREQ);
3371 if (ret)
3372 return ret;
3373
3374 ret = clk_prepare_enable(vc4_hdmi->hsm_rpm_clock);
3375 if (ret)3355 if (ret)
3376 return ret;3356 return ret;
3377 3357
@@ -3384,7 +3364,7 @@ static int vc4_hdmi_runtime_resume(struct device *dev) · 6 unmodified lines
3384 * case, it will lead to a silent CPU stall. Let's make sure we3364 * case, it will lead to a silent CPU stall. Let's make sure we
3385 * prevent such a case.3365 * prevent such a case.
3386 */3366 */
3387 rate = clk_get_rate(vc4_hdmi->hsm_rpm_clock);3367 rate = clk_get_rate(vc4_hdmi->hsm_clock);
3388 if (!rate) {3368 if (!rate) {
3389 ret = -EINVAL;3369 ret = -EINVAL;
3390 goto err_disable_clk;3370 goto err_disable_clk;
drivers/gpu/drm/vc4/vc4_hdmi.h+0−1
@@ -164,7 +164,6 @@ struct vc4_hdmi { · 163 unmodified lines
164 struct clk *cec_clock;164 struct clk *cec_clock;
165 struct clk *pixel_clock;165 struct clk *pixel_clock;
166 struct clk *hsm_clock;166 struct clk *hsm_clock;
167 struct clk *hsm_rpm_clock;
168 struct clk *audio_clock;167 struct clk *audio_clock;
169 struct clk *pixel_bvb_clock;168 struct clk *pixel_bvb_clock;
170 169
drivers/gpu/drm/vc4/vc4_validate.c+2−2
@@ -117,7 +117,7 @@ vc4_use_bo(struct vc4_exec_info *exec, uint32_t hindex) · 116 unmodified lines
117 hindex, exec->bo_count);117 hindex, exec->bo_count);
118 return NULL;118 return NULL;
119 }119 }
120 obj = exec->bo[hindex];120 obj = to_drm_gem_dma_obj(exec->bo[hindex]);
121 bo = to_vc4_bo(&obj->base);121 bo = to_vc4_bo(&obj->base);
122 122
123 if (bo->validated_shader) {123 if (bo->validated_shader) {
@@ -810,7 +810,7 @@ validate_gl_shader_rec(struct drm_device *dev, · 686 unmodified lines
810 return -EINVAL;810 return -EINVAL;
811 }811 }
812 812
813 bo[i] = exec->bo[src_handles[i]];813 bo[i] = to_drm_gem_dma_obj(exec->bo[src_handles[i]]);
814 if (!bo[i])814 if (!bo[i])
815 return -EINVAL;815 return -EINVAL;
816 }816 }
drivers/gpu/drm/vgem/vgem_fence.c+1−0
@@ -249,4 +249,5 @@ void vgem_fence_close(struct vgem_file *vfile) · 248 unmodified lines
249{249{
250 idr_for_each(&vfile->fence_idr, __vgem_fence_idr_fini, vfile);250 idr_for_each(&vfile->fence_idr, __vgem_fence_idr_fini, vfile);
251 idr_destroy(&vfile->fence_idr);251 idr_destroy(&vfile->fence_idr);
252 mutex_destroy(&vfile->fence_mutex);
252}253}
drivers/gpu/drm/virtio/Kconfig+11−0
@@ -11,3 +11,14 @@ config DRM_VIRTIO_GPU · 10 unmodified lines
11 QEMU based VMMs (like KVM or Xen).11 QEMU based VMMs (like KVM or Xen).
12 12
13 If unsure say M.13 If unsure say M.
14
15config 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.
drivers/gpu/drm/virtio/virtgpu_display.c+6−0
@@ -336,6 +336,9 @@ int virtio_gpu_modeset_init(struct virtio_gpu_device *vgdev) · 335 unmodified lines
336{336{
337 int i, ret;337 int i, ret;
338 338
339 if (!vgdev->num_scanouts)
340 return 0;
341
339 ret = drmm_mode_config_init(vgdev->ddev);342 ret = drmm_mode_config_init(vgdev->ddev);
340 if (ret)343 if (ret)
341 return ret;344 return ret;
@@ -362,6 +365,9 @@ void virtio_gpu_modeset_fini(struct virtio_gpu_device *vgdev) · 20 unmodified lines
362{365{
363 int i;366 int i;
364 367
368 if (!vgdev->num_scanouts)
369 return;
370
365 for (i = 0 ; i < vgdev->num_scanouts; ++i)371 for (i = 0 ; i < vgdev->num_scanouts; ++i)
366 kfree(vgdev->outputs[i].edid);372 kfree(vgdev->outputs[i].edid);
367}373}
drivers/gpu/drm/virtio/virtgpu_drv.c+4−0
@@ -172,6 +172,10 @@ MODULE_AUTHOR("Alon Levy"); · 171 unmodified lines
172DEFINE_DRM_GEM_FOPS(virtio_gpu_driver_fops);172DEFINE_DRM_GEM_FOPS(virtio_gpu_driver_fops);
173 173
174static const struct drm_driver driver = {174static const struct drm_driver driver = {
175 /*
176 * If KMS is disabled DRIVER_MODESET and DRIVER_ATOMIC are masked
177 * out via drm_device::driver_features:
178 */
175 .driver_features = DRIVER_MODESET | DRIVER_GEM | DRIVER_RENDER | DRIVER_ATOMIC,179 .driver_features = DRIVER_MODESET | DRIVER_GEM | DRIVER_RENDER | DRIVER_ATOMIC,
176 .open = virtio_gpu_driver_open,180 .open = virtio_gpu_driver_open,
177 .postclose = virtio_gpu_driver_postclose,181 .postclose = virtio_gpu_driver_postclose,
drivers/gpu/drm/virtio/virtgpu_kms.c+23−16
@@ -43,11 +43,13 @@ static void virtio_gpu_config_changed_work_func(struct work_struct *work) · 42 unmodified lines
43 virtio_cread_le(vgdev->vdev, struct virtio_gpu_config,43 virtio_cread_le(vgdev->vdev, struct virtio_gpu_config,
44 events_read, &events_read);44 events_read, &events_read);
45 if (events_read & VIRTIO_GPU_EVENT_DISPLAY) {45 if (events_read & VIRTIO_GPU_EVENT_DISPLAY) {
46 if (vgdev->has_edid)46 if (vgdev->num_scanouts) {
47 virtio_gpu_cmd_get_edids(vgdev);47 if (vgdev->has_edid)
48 virtio_gpu_cmd_get_display_info(vgdev);48 virtio_gpu_cmd_get_edids(vgdev);
49 virtio_gpu_notify(vgdev);49 virtio_gpu_cmd_get_display_info(vgdev);
50 drm_helper_hpd_irq_event(vgdev->ddev);50 virtio_gpu_notify(vgdev);
51 drm_helper_hpd_irq_event(vgdev->ddev);
52 }
51 events_clear |= VIRTIO_GPU_EVENT_DISPLAY;53 events_clear |= VIRTIO_GPU_EVENT_DISPLAY;
52 }54 }
53 virtio_cwrite_le(vgdev->vdev, struct virtio_gpu_config,55 virtio_cwrite_le(vgdev->vdev, struct virtio_gpu_config,
@@ -223,12 +225,15 @@ int virtio_gpu_init(struct virtio_device *vdev, struct drm_device *dev) · 169 unmodified lines
223 num_scanouts, &num_scanouts);225 num_scanouts, &num_scanouts);
224 vgdev->num_scanouts = min_t(uint32_t, num_scanouts,226 vgdev->num_scanouts = min_t(uint32_t, num_scanouts,
225 VIRTIO_GPU_MAX_SCANOUTS);227 VIRTIO_GPU_MAX_SCANOUTS);
226 if (!vgdev->num_scanouts) {228
227 DRM_ERROR("num_scanouts is zero\n");229 if (!IS_ENABLED(CONFIG_DRM_VIRTIO_GPU_KMS) || !vgdev->num_scanouts) {
228 ret = -EINVAL;230 DRM_INFO("KMS disabled\n");
229 goto err_scanouts;231 vgdev->num_scanouts = 0;
232 vgdev->has_edid = false;
233 dev->driver_features &= ~(DRIVER_MODESET | DRIVER_ATOMIC);
234 } else {
235 DRM_INFO("number of scanouts: %d\n", num_scanouts);
230 }236 }
231 DRM_INFO("number of scanouts: %d\n", num_scanouts);
232 237
233 virtio_cread_le(vgdev->vdev, struct virtio_gpu_config,238 virtio_cread_le(vgdev->vdev, struct virtio_gpu_config,
234 num_capsets, &num_capsets);239 num_capsets, &num_capsets);
@@ -244,12 +249,14 @@ int virtio_gpu_init(struct virtio_device *vdev, struct drm_device *dev) · 9 unmodified lines
244 249
245 if (num_capsets)250 if (num_capsets)
246 virtio_gpu_get_capsets(vgdev, num_capsets);251 virtio_gpu_get_capsets(vgdev, num_capsets);
247 if (vgdev->has_edid)252 if (vgdev->num_scanouts) {
248 virtio_gpu_cmd_get_edids(vgdev);253 if (vgdev->has_edid)
249 virtio_gpu_cmd_get_display_info(vgdev);254 virtio_gpu_cmd_get_edids(vgdev);
250 virtio_gpu_notify(vgdev);255 virtio_gpu_cmd_get_display_info(vgdev);
251 wait_event_timeout(vgdev->resp_wq, !vgdev->display_info_pending,256 virtio_gpu_notify(vgdev);
252 5 * HZ);257 wait_event_timeout(vgdev->resp_wq, !vgdev->display_info_pending,
258 5 * HZ);
259 }
253 return 0;260 return 0;
254 261
255err_scanouts:262err_scanouts:
drivers/gpu/drm/virtio/virtgpu_vq.c+1−2
@@ -923,8 +923,7 @@ void virtio_gpu_cmd_context_create(struct virtio_gpu_device *vgdev, uint32_t id, · 922 unmodified lines
923 cmd_p->hdr.ctx_id = cpu_to_le32(id);923 cmd_p->hdr.ctx_id = cpu_to_le32(id);
924 cmd_p->nlen = cpu_to_le32(nlen);924 cmd_p->nlen = cpu_to_le32(nlen);
925 cmd_p->context_init = cpu_to_le32(context_init);925 cmd_p->context_init = cpu_to_le32(context_init);
926 strncpy(cmd_p->debug_name, name, sizeof(cmd_p->debug_name) - 1);926 strscpy(cmd_p->debug_name, name, sizeof(cmd_p->debug_name));
927 cmd_p->debug_name[sizeof(cmd_p->debug_name) - 1] = 0;
928 virtio_gpu_queue_ctrl_buffer(vgdev, vbuf);927 virtio_gpu_queue_ctrl_buffer(vgdev, vbuf);
929}928}
930 929
drivers/gpu/drm/vmwgfx/Makefile+1−1
@@ -1,7 +1,7 @@
1# SPDX-License-Identifier: GPL-2.01# SPDX-License-Identifier: GPL-2.0
2vmwgfx-y := vmwgfx_execbuf.o vmwgfx_gmr.o vmwgfx_kms.o vmwgfx_drv.o \2vmwgfx-y := vmwgfx_execbuf.o vmwgfx_gmr.o vmwgfx_kms.o vmwgfx_drv.o \
3 vmwgfx_ioctl.o vmwgfx_resource.o vmwgfx_ttm_buffer.o \3 vmwgfx_ioctl.o vmwgfx_resource.o vmwgfx_ttm_buffer.o \
4 vmwgfx_cmd.o vmwgfx_irq.o vmwgfx_ldu.o vmwgfx_ttm_glue.o \4 vmwgfx_cmd.o vmwgfx_irq.o vmwgfx_ldu.o \
5 vmwgfx_overlay.o vmwgfx_gmrid_manager.o vmwgfx_fence.o \5 vmwgfx_overlay.o vmwgfx_gmrid_manager.o vmwgfx_fence.o \
6 vmwgfx_bo.o vmwgfx_scrn.o vmwgfx_context.o \6 vmwgfx_bo.o vmwgfx_scrn.o vmwgfx_context.o \
7 vmwgfx_surface.o vmwgfx_prime.o vmwgfx_mob.o vmwgfx_shader.o \7 vmwgfx_surface.o vmwgfx_prime.o vmwgfx_mob.o vmwgfx_shader.o \
drivers/gpu/drm/vmwgfx/vmwgfx_bo.c+196−211
@@ -1,7 +1,7 @@
1// SPDX-License-Identifier: GPL-2.0 OR MIT1// SPDX-License-Identifier: GPL-2.0 OR MIT
2/**************************************************************************2/**************************************************************************
3 *3 *
4 * Copyright © 2011-2018 VMware, Inc., Palo Alto, CA., USA4 * Copyright © 2011-2023 VMware, Inc., Palo Alto, CA., USA
5 * All Rights Reserved.5 * All Rights Reserved.
6 *6 *
7 * Permission is hereby granted, free of charge, to any person obtaining a7 * Permission is hereby granted, free of charge, to any person obtaining a
@@ -26,40 +26,31 @@ · 18 unmodified lines
26 *26 *
27 **************************************************************************/27 **************************************************************************/
28 28
29#include <drm/ttm/ttm_placement.h>29#include "vmwgfx_bo.h"
30
31#include "vmwgfx_drv.h"30#include "vmwgfx_drv.h"
32#include "ttm_object.h"
33 31
34 32
35/**33#include <drm/ttm/ttm_placement.h>
36 * vmw_buffer_object - Convert a struct ttm_buffer_object to a struct34
37 * vmw_buffer_object.35static void vmw_bo_release(struct vmw_bo *vbo)
38 *
39 * @bo: Pointer to the TTM buffer object.
40 * Return: Pointer to the struct vmw_buffer_object embedding the
41 * TTM buffer object.
42 */
43static struct vmw_buffer_object *
44vmw_buffer_object(struct ttm_buffer_object *bo)
45{36{
46 return container_of(bo, struct vmw_buffer_object, base);37 vmw_bo_unmap(vbo);
38 drm_gem_object_release(&vbo->tbo.base);
47}39}
48 40
49/**41/**
50 * bo_is_vmw - check if the buffer object is a &vmw_buffer_object42 * vmw_bo_free - vmw_bo destructor
51 * @bo: ttm buffer object to be checked
52 *43 *
53 * Uses destroy function associated with the object to determine if this is44 * @bo: Pointer to the embedded struct ttm_buffer_object
54 * a &vmw_buffer_object.
55 *
56 * Returns:
57 * true if the object is of &vmw_buffer_object type, false if not.
58 */45 */
59static bool bo_is_vmw(struct ttm_buffer_object *bo)46static void vmw_bo_free(struct ttm_buffer_object *bo)
60{47{
61 return bo->destroy == &vmw_bo_bo_free ||48 struct vmw_bo *vbo = to_vmw_bo(&bo->base);
62 bo->destroy == &vmw_gem_destroy;49
50 WARN_ON(vbo->dirty);
51 WARN_ON(!RB_EMPTY_ROOT(&vbo->res_tree));
52 vmw_bo_release(vbo);
53 kfree(vbo);
63}54}
64 55
65/**56/**
@@ -72,13 +63,13 @@ static bool bo_is_vmw(struct ttm_buffer_object *bo) · 6 unmodified lines
72 * Return: Zero on success, Negative error code on failure. In particular63 * Return: Zero on success, Negative error code on failure. In particular
73 * -ERESTARTSYS if interrupted by a signal64 * -ERESTARTSYS if interrupted by a signal
74 */65 */
75int vmw_bo_pin_in_placement(struct vmw_private *dev_priv,66static int vmw_bo_pin_in_placement(struct vmw_private *dev_priv,
76 struct vmw_buffer_object *buf,67 struct vmw_bo *buf,
77 struct ttm_placement *placement,68 struct ttm_placement *placement,
78 bool interruptible)69 bool interruptible)
79{70{
80 struct ttm_operation_ctx ctx = {interruptible, false };71 struct ttm_operation_ctx ctx = {interruptible, false };
81 struct ttm_buffer_object *bo = &buf->base;72 struct ttm_buffer_object *bo = &buf->tbo;
82 int ret;73 int ret;
83 74
84 vmw_execbuf_release_pinned_bo(dev_priv);75 vmw_execbuf_release_pinned_bo(dev_priv);
@@ -87,12 +78,7 @@ int vmw_bo_pin_in_placement(struct vmw_private *dev_priv, · 2 unmodified lines
87 if (unlikely(ret != 0))78 if (unlikely(ret != 0))
88 goto err;79 goto err;
89 80
90 if (buf->base.pin_count > 0)81 ret = ttm_bo_validate(bo, placement, &ctx);
91 ret = ttm_resource_compat(bo->resource, placement)
92 ? 0 : -EINVAL;
93 else
94 ret = ttm_bo_validate(bo, placement, &ctx);
95
96 if (!ret)82 if (!ret)
97 vmw_bo_pin_reserved(buf, true);83 vmw_bo_pin_reserved(buf, true);
98 84
@@ -115,11 +101,11 @@ err: · 16 unmodified lines
115 * -ERESTARTSYS if interrupted by a signal101 * -ERESTARTSYS if interrupted by a signal
116 */102 */
117int vmw_bo_pin_in_vram_or_gmr(struct vmw_private *dev_priv,103int vmw_bo_pin_in_vram_or_gmr(struct vmw_private *dev_priv,
118 struct vmw_buffer_object *buf,104 struct vmw_bo *buf,
119 bool interruptible)105 bool interruptible)
120{106{
121 struct ttm_operation_ctx ctx = {interruptible, false };107 struct ttm_operation_ctx ctx = {interruptible, false };
122 struct ttm_buffer_object *bo = &buf->base;108 struct ttm_buffer_object *bo = &buf->tbo;
123 int ret;109 int ret;
124 110
125 vmw_execbuf_release_pinned_bo(dev_priv);111 vmw_execbuf_release_pinned_bo(dev_priv);
@@ -128,17 +114,17 @@ int vmw_bo_pin_in_vram_or_gmr(struct vmw_private *dev_priv, · 2 unmodified lines
128 if (unlikely(ret != 0))114 if (unlikely(ret != 0))
129 goto err;115 goto err;
130 116
131 if (buf->base.pin_count > 0) {117 vmw_bo_placement_set(buf,
132 ret = ttm_resource_compat(bo->resource, &vmw_vram_gmr_placement)118 VMW_BO_DOMAIN_GMR | VMW_BO_DOMAIN_VRAM,
133 ? 0 : -EINVAL;119 VMW_BO_DOMAIN_GMR);
134 goto out_unreserve;120 ret = ttm_bo_validate(bo, &buf->placement, &ctx);
135 }
136
137 ret = ttm_bo_validate(bo, &vmw_vram_gmr_placement, &ctx);
138 if (likely(ret == 0) || ret == -ERESTARTSYS)121 if (likely(ret == 0) || ret == -ERESTARTSYS)
139 goto out_unreserve;122 goto out_unreserve;
140 123
141 ret = ttm_bo_validate(bo, &vmw_vram_placement, &ctx);124 vmw_bo_placement_set(buf,
125 VMW_BO_DOMAIN_VRAM,
126 VMW_BO_DOMAIN_VRAM);
127 ret = ttm_bo_validate(bo, &buf->placement, &ctx);
142 128
143out_unreserve:129out_unreserve:
144 if (!ret)130 if (!ret)
@@ -163,7 +149,7 @@ err: · 18 unmodified lines
163 * -ERESTARTSYS if interrupted by a signal149 * -ERESTARTSYS if interrupted by a signal
164 */150 */
165int vmw_bo_pin_in_vram(struct vmw_private *dev_priv,151int vmw_bo_pin_in_vram(struct vmw_private *dev_priv,
166 struct vmw_buffer_object *buf,152 struct vmw_bo *buf,
167 bool interruptible)153 bool interruptible)
168{154{
169 return vmw_bo_pin_in_placement(dev_priv, buf, &vmw_vram_placement,155 return vmw_bo_pin_in_placement(dev_priv, buf, &vmw_vram_placement,
@@ -184,22 +170,13 @@ int vmw_bo_pin_in_vram(struct vmw_private *dev_priv, · 14 unmodified lines
184 * -ERESTARTSYS if interrupted by a signal170 * -ERESTARTSYS if interrupted by a signal
185 */171 */
186int vmw_bo_pin_in_start_of_vram(struct vmw_private *dev_priv,172int vmw_bo_pin_in_start_of_vram(struct vmw_private *dev_priv,
187 struct vmw_buffer_object *buf,173 struct vmw_bo *buf,
188 bool interruptible)174 bool interruptible)
189{175{
190 struct ttm_operation_ctx ctx = {interruptible, false };176 struct ttm_operation_ctx ctx = {interruptible, false };
191 struct ttm_buffer_object *bo = &buf->base;177 struct ttm_buffer_object *bo = &buf->tbo;
192 struct ttm_placement placement;
193 struct ttm_place place;
194 int ret = 0;178 int ret = 0;
195 179
196 place = vmw_vram_placement.placement[0];
197 place.lpfn = PFN_UP(bo->resource->size);
198 placement.num_placement = 1;
199 placement.placement = &place;
200 placement.num_busy_placement = 1;
201 placement.busy_placement = &place;
202
203 vmw_execbuf_release_pinned_bo(dev_priv);180 vmw_execbuf_release_pinned_bo(dev_priv);
204 ret = ttm_bo_reserve(bo, interruptible, false, NULL);181 ret = ttm_bo_reserve(bo, interruptible, false, NULL);
205 if (unlikely(ret != 0))182 if (unlikely(ret != 0))
@@ -213,16 +190,19 @@ int vmw_bo_pin_in_start_of_vram(struct vmw_private *dev_priv, · 7 unmodified lines
213 if (bo->resource->mem_type == TTM_PL_VRAM &&190 if (bo->resource->mem_type == TTM_PL_VRAM &&
214 bo->resource->start < PFN_UP(bo->resource->size) &&191 bo->resource->start < PFN_UP(bo->resource->size) &&
215 bo->resource->start > 0 &&192 bo->resource->start > 0 &&
216 buf->base.pin_count == 0) {193 buf->tbo.pin_count == 0) {
217 ctx.interruptible = false;194 ctx.interruptible = false;
218 (void) ttm_bo_validate(bo, &vmw_sys_placement, &ctx);195 vmw_bo_placement_set(buf,
196 VMW_BO_DOMAIN_SYS,
197 VMW_BO_DOMAIN_SYS);
198 (void)ttm_bo_validate(bo, &buf->placement, &ctx);
219 }199 }
220 200
221 if (buf->base.pin_count > 0)201 vmw_bo_placement_set(buf,
222 ret = ttm_resource_compat(bo->resource, &placement)202 VMW_BO_DOMAIN_VRAM,
223 ? 0 : -EINVAL;203 VMW_BO_DOMAIN_VRAM);
224 else204 buf->places[0].lpfn = PFN_UP(bo->resource->size);
225 ret = ttm_bo_validate(bo, &placement, &ctx);205 ret = ttm_bo_validate(bo, &buf->placement, &ctx);
226 206
227 /* For some reason we didn't end up at the start of vram */207 /* For some reason we didn't end up at the start of vram */
228 WARN_ON(ret == 0 && bo->resource->start != 0);208 WARN_ON(ret == 0 && bo->resource->start != 0);
@@ -248,10 +228,10 @@ err_unlock: · 19 unmodified lines
248 * -ERESTARTSYS if interrupted by a signal228 * -ERESTARTSYS if interrupted by a signal
249 */229 */
250int vmw_bo_unpin(struct vmw_private *dev_priv,230int vmw_bo_unpin(struct vmw_private *dev_priv,
251 struct vmw_buffer_object *buf,231 struct vmw_bo *buf,
252 bool interruptible)232 bool interruptible)
253{233{
254 struct ttm_buffer_object *bo = &buf->base;234 struct ttm_buffer_object *bo = &buf->tbo;
255 int ret;235 int ret;
256 236
257 ret = ttm_bo_reserve(bo, interruptible, false, NULL);237 ret = ttm_bo_reserve(bo, interruptible, false, NULL);
@@ -293,12 +273,12 @@ void vmw_bo_get_guest_ptr(const struct ttm_buffer_object *bo, · 35 unmodified lines
293 * @pin: Whether to pin or unpin.273 * @pin: Whether to pin or unpin.
294 *274 *
295 */275 */
296void vmw_bo_pin_reserved(struct vmw_buffer_object *vbo, bool pin)276void vmw_bo_pin_reserved(struct vmw_bo *vbo, bool pin)
297{277{
298 struct ttm_operation_ctx ctx = { false, true };278 struct ttm_operation_ctx ctx = { false, true };
299 struct ttm_place pl;279 struct ttm_place pl;
300 struct ttm_placement placement;280 struct ttm_placement placement;
301 struct ttm_buffer_object *bo = &vbo->base;281 struct ttm_buffer_object *bo = &vbo->tbo;
302 uint32_t old_mem_type = bo->resource->mem_type;282 uint32_t old_mem_type = bo->resource->mem_type;
303 int ret;283 int ret;
304 284
@@ -341,9 +321,9 @@ void vmw_bo_pin_reserved(struct vmw_buffer_object *vbo, bool pin) · 36 unmodified lines
341 * 3) Buffer object destruction321 * 3) Buffer object destruction
342 *322 *
343 */323 */
344void *vmw_bo_map_and_cache(struct vmw_buffer_object *vbo)324void *vmw_bo_map_and_cache(struct vmw_bo *vbo)
345{325{
346 struct ttm_buffer_object *bo = &vbo->base;326 struct ttm_buffer_object *bo = &vbo->tbo;
347 bool not_used;327 bool not_used;
348 void *virtual;328 void *virtual;
349 int ret;329 int ret;
@@ -366,96 +346,70 @@ void *vmw_bo_map_and_cache(struct vmw_buffer_object *vbo) · 16 unmodified lines
366 * @vbo: The buffer object whose map we are tearing down.346 * @vbo: The buffer object whose map we are tearing down.
367 *347 *
368 * This function tears down a cached map set up using348 * 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 */
371void vmw_bo_unmap(struct vmw_buffer_object *vbo)351void vmw_bo_unmap(struct vmw_bo *vbo)
372{352{
373 if (vbo->map.bo == NULL)353 if (vbo->map.bo == NULL)
374 return;354 return;
375 355
376 ttm_bo_kunmap(&vbo->map);356 ttm_bo_kunmap(&vbo->map);
357 vbo->map.bo = NULL;
377}358}
378 359
379 360
380/**361/**
381 * vmw_bo_bo_free - vmw buffer object destructor362 * vmw_bo_init - Initialize a vmw buffer object
382 *
383 * @bo: Pointer to the embedded struct ttm_buffer_object
384 */
385void 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 */
397static void vmw_bo_default_destroy(struct ttm_buffer_object *bo)
398{
399 kfree(bo);
400}
401
402/**
403 * vmw_bo_create_kernel - Create a pinned BO for internal kernel use.
404 *363 *
405 * @dev_priv: Pointer to the device private struct364 * @dev_priv: Pointer to the device private struct
406 * @size: size of the BO we need365 * @vmw_bo: Buffer object to initialize
407 * @placement: where to put it366 * @params: Parameters used to initialize the buffer object
408 * @p_bo: resulting BO367 * @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 */
412int vmw_bo_create_kernel(struct vmw_private *dev_priv, unsigned long size,371static int vmw_bo_init(struct vmw_private *dev_priv,
413 struct ttm_placement *placement,372 struct vmw_bo *vmw_bo,
414 struct ttm_buffer_object **p_bo)373 struct vmw_bo_params *params,
374 void (*destroy)(struct ttm_buffer_object *))
415{375{
416 struct ttm_operation_ctx ctx = {376 struct ttm_operation_ctx ctx = {
417 .interruptible = false,377 .interruptible = params->bo_type != ttm_bo_type_kernel,
418 .no_wait_gpu = false378 .no_wait_gpu = false
419 };379 };
420 struct ttm_buffer_object *bo;380 struct ttm_device *bdev = &dev_priv->bdev;
421 struct drm_device *vdev = &dev_priv->drm;381 struct drm_device *vdev = &dev_priv->drm;
422 int ret;382 int ret;
423 383
424 bo = kzalloc(sizeof(*bo), GFP_KERNEL);384 memset(vmw_bo, 0, sizeof(*vmw_bo));
425 if (unlikely(!bo))
426 return -ENOMEM;
427 385
428 size = ALIGN(size, PAGE_SIZE);386 BUILD_BUG_ON(TTM_MAX_BO_PRIORITY <= 3);
387 vmw_bo->tbo.priority = 3;
388 vmw_bo->res_tree = RB_ROOT;
429 389
430 drm_gem_private_object_init(vdev, &bo->base, size);390 params->size = ALIGN(params->size, PAGE_SIZE);
391 drm_gem_private_object_init(vdev, &vmw_bo->tbo.base, params->size);
431 392
432 ret = ttm_bo_init_reserved(&dev_priv->bdev, bo, ttm_bo_type_kernel,393 vmw_bo_placement_set(vmw_bo, params->domain, params->busy_domain);
433 placement, 0, &ctx, NULL, NULL,394 ret = ttm_bo_init_reserved(bdev, &vmw_bo->tbo, params->bo_type,
434 vmw_bo_default_destroy);395 &vmw_bo->placement, 0, &ctx, NULL,
396 NULL, destroy);
435 if (unlikely(ret))397 if (unlikely(ret))
436 goto error_free;398 return ret;
437 399
438 ttm_bo_pin(bo);400 if (params->pin)
439 ttm_bo_unreserve(bo);401 ttm_bo_pin(&vmw_bo->tbo);
440 *p_bo = bo;402 ttm_bo_unreserve(&vmw_bo->tbo);
441 403
442 return 0;404 return 0;
443
444error_free:
445 kfree(bo);
446 return ret;
447}405}
448 406
449int vmw_bo_create(struct vmw_private *vmw,407int vmw_bo_create(struct vmw_private *vmw,
450 size_t size, struct ttm_placement *placement,408 struct vmw_bo_params *params,
451 bool interruptible, bool pin,409 struct vmw_bo **p_bo)
452 void (*bo_free)(struct ttm_buffer_object *bo),
453 struct vmw_buffer_object **p_bo)
454{410{
455 int ret;411 int ret;
456 412
457 BUG_ON(!bo_free);
458
459 *p_bo = kmalloc(sizeof(**p_bo), GFP_KERNEL);413 *p_bo = kmalloc(sizeof(**p_bo), GFP_KERNEL);
460 if (unlikely(!*p_bo)) {414 if (unlikely(!*p_bo)) {
461 DRM_ERROR("Failed to allocate a buffer.\n");415 DRM_ERROR("Failed to allocate a buffer.\n");
@@ -465,9 +419,7 @@ int vmw_bo_create(struct vmw_private *vmw, · 3 unmodified lines
465 /*419 /*
466 * vmw_bo_init will delete the *p_bo object if it fails420 * vmw_bo_init will delete the *p_bo object if it fails
467 */421 */
468 ret = vmw_bo_init(vmw, *p_bo, size,422 ret = vmw_bo_init(vmw, *p_bo, params, vmw_bo_free);
469 placement, interruptible, pin,
470 bo_free);
471 if (unlikely(ret != 0))423 if (unlikely(ret != 0))
472 goto out_error;424 goto out_error;
473 425
@@ -478,57 +430,7 @@ out_error: · 4 unmodified lines
478}430}
479 431
480/**432/**
481 * vmw_bo_init - Initialize a vmw buffer object433 * vmw_user_bo_synccpu_grab - Grab a struct vmw_bo for cpu
482 *
483 * @dev_priv: Pointer to the device private struct
484 * @vmw_bo: Pointer to the struct vmw_buffer_object to initialize.
485 * @size: Buffer object size in bytes.
486 * @placement: Initial placement.
487 * @interruptible: Whether waits should be performed interruptible.
488 * @pin: If the BO should be created pinned at a fixed location.
489 * @bo_free: The buffer object destructor.
490 * Returns: Zero on success, negative error code on error.
491 *
492 * Note that on error, the code will free the buffer object.
493 */
494int vmw_bo_init(struct vmw_private *dev_priv,
495 struct vmw_buffer_object *vmw_bo,
496 size_t size, struct ttm_placement *placement,
497 bool interruptible, bool pin,
498 void (*bo_free)(struct ttm_buffer_object *bo))
499{
500 struct ttm_operation_ctx ctx = {
501 .interruptible = interruptible,
502 .no_wait_gpu = false
503 };
504 struct ttm_device *bdev = &dev_priv->bdev;
505 struct drm_device *vdev = &dev_priv->drm;
506 int ret;
507
508 WARN_ON_ONCE(!bo_free);
509 memset(vmw_bo, 0, sizeof(*vmw_bo));
510 BUILD_BUG_ON(TTM_MAX_BO_PRIORITY <= 3);
511 vmw_bo->base.priority = 3;
512 vmw_bo->res_tree = RB_ROOT;
513
514 size = ALIGN(size, PAGE_SIZE);
515 drm_gem_private_object_init(vdev, &vmw_bo->base.base, size);
516
517 ret = ttm_bo_init_reserved(bdev, &vmw_bo->base, ttm_bo_type_device,
518 placement, 0, &ctx, NULL, NULL, bo_free);
519 if (unlikely(ret)) {
520 return ret;
521 }
522
523 if (pin)
524 ttm_bo_pin(&vmw_bo->base);
525 ttm_bo_unreserve(&vmw_bo->base);
526
527 return 0;
528}
529
530/**
531 * vmw_user_bo_synccpu_grab - Grab a struct vmw_buffer_object for cpu
532 * access, idling previous GPU operations on the buffer and optionally434 * access, idling previous GPU operations on the buffer and optionally
533 * blocking it for further command submissions.435 * blocking it for further command submissions.
534 *436 *
@@ -541,11 +443,11 @@ int vmw_bo_init(struct vmw_private *dev_priv, · 6 unmodified lines
541 *443 *
542 * A blocking grab will be automatically released when @tfile is closed.444 * A blocking grab will be automatically released when @tfile is closed.
543 */445 */
544static int vmw_user_bo_synccpu_grab(struct vmw_buffer_object *vmw_bo,446static int vmw_user_bo_synccpu_grab(struct vmw_bo *vmw_bo,
545 uint32_t flags)447 uint32_t flags)
546{448{
547 bool nonblock = !!(flags & drm_vmw_synccpu_dontblock);449 bool nonblock = !!(flags & drm_vmw_synccpu_dontblock);
548 struct ttm_buffer_object *bo = &vmw_bo->base;450 struct ttm_buffer_object *bo = &vmw_bo->tbo;
549 int ret;451 int ret;
550 452
551 if (flags & drm_vmw_synccpu_allow_cs) {453 if (flags & drm_vmw_synccpu_allow_cs) {
@@ -588,17 +490,17 @@ static int vmw_user_bo_synccpu_release(struct drm_file *filp, · 36 unmodified lines
588 uint32_t handle,490 uint32_t handle,
589 uint32_t flags)491 uint32_t flags)
590{492{
591 struct vmw_buffer_object *vmw_bo;493 struct vmw_bo *vmw_bo;
592 int ret = vmw_user_bo_lookup(filp, handle, &vmw_bo);494 int ret = vmw_user_bo_lookup(filp, handle, &vmw_bo);
593 495
594 if (!ret) {496 if (!ret) {
595 if (!(flags & drm_vmw_synccpu_allow_cs)) {497 if (!(flags & drm_vmw_synccpu_allow_cs)) {
596 atomic_dec(&vmw_bo->cpu_writers);498 atomic_dec(&vmw_bo->cpu_writers);
597 }499 }
598 ttm_bo_put(&vmw_bo->base);500 ttm_bo_put(&vmw_bo->tbo);
599 }501 }
600 502
601 drm_gem_object_put(&vmw_bo->base.base);503 drm_gem_object_put(&vmw_bo->tbo.base);
602 return ret;504 return ret;
603}505}
604 506
@@ -620,7 +522,7 @@ int vmw_user_bo_synccpu_ioctl(struct drm_device *dev, void *data, · 15 unmodified lines
620{522{
621 struct drm_vmw_synccpu_arg *arg =523 struct drm_vmw_synccpu_arg *arg =
622 (struct drm_vmw_synccpu_arg *) data;524 (struct drm_vmw_synccpu_arg *) data;
623 struct vmw_buffer_object *vbo;525 struct vmw_bo *vbo;
624 int ret;526 int ret;
625 527
626 if ((arg->flags & (drm_vmw_synccpu_read | drm_vmw_synccpu_write)) == 0528 if ((arg->flags & (drm_vmw_synccpu_read | drm_vmw_synccpu_write)) == 0
@@ -639,7 +541,7 @@ int vmw_user_bo_synccpu_ioctl(struct drm_device *dev, void *data, · 12 unmodified lines
639 541
640 ret = vmw_user_bo_synccpu_grab(vbo, arg->flags);542 ret = vmw_user_bo_synccpu_grab(vbo, arg->flags);
641 vmw_bo_unreference(&vbo);543 vmw_bo_unreference(&vbo);
642 drm_gem_object_put(&vbo->base.base);544 drm_gem_object_put(&vbo->tbo.base);
643 if (unlikely(ret != 0)) {545 if (unlikely(ret != 0)) {
644 if (ret == -ERESTARTSYS || ret == -EBUSY)546 if (ret == -ERESTARTSYS || ret == -EBUSY)
645 return -EBUSY;547 return -EBUSY;
@@ -683,8 +585,7 @@ int vmw_bo_unref_ioctl(struct drm_device *dev, void *data, · 37 unmodified lines
683 struct drm_vmw_unref_dmabuf_arg *arg =585 struct drm_vmw_unref_dmabuf_arg *arg =
684 (struct drm_vmw_unref_dmabuf_arg *)data;586 (struct drm_vmw_unref_dmabuf_arg *)data;
685 587
686 drm_gem_handle_delete(file_priv, arg->handle);588 return drm_gem_handle_delete(file_priv, arg->handle);
687 return 0;
688}589}
689 590
690 591
@@ -694,14 +595,14 @@ int vmw_bo_unref_ioctl(struct drm_device *dev, void *data, · 3 unmodified lines
694 * @filp: The file the handle is registered with.595 * @filp: The file the handle is registered with.
695 * @handle: The user buffer object handle596 * @handle: The user buffer object handle
696 * @out: Pointer to a where a pointer to the embedded597 * @out: Pointer to a where a pointer to the embedded
697 * struct vmw_buffer_object should be placed.598 * struct vmw_bo should be placed.
698 * Return: Zero on success, Negative error code on error.599 * Return: Zero on success, Negative error code on error.
699 *600 *
700 * The vmw buffer object pointer will be refcounted (both ttm and gem)601 * The vmw buffer object pointer will be refcounted (both ttm and gem)
701 */602 */
702int vmw_user_bo_lookup(struct drm_file *filp,603int vmw_user_bo_lookup(struct drm_file *filp,
703 uint32_t handle,604 u32 handle,
704 struct vmw_buffer_object **out)605 struct vmw_bo **out)
705{606{
706 struct drm_gem_object *gobj;607 struct drm_gem_object *gobj;
707 608
@@ -712,8 +613,8 @@ int vmw_user_bo_lookup(struct drm_file *filp, · 4 unmodified lines
712 return -ESRCH;613 return -ESRCH;
713 }614 }
714 615
715 *out = gem_to_vmw_bo(gobj);616 *out = to_vmw_bo(gobj);
716 ttm_bo_get(&(*out)->base);617 ttm_bo_get(&(*out)->tbo);
717 618
718 return 0;619 return 0;
719}620}
@@ -734,8 +635,7 @@ void vmw_bo_fence_single(struct ttm_buffer_object *bo, · 14 unmodified lines
734 struct vmw_fence_obj *fence)635 struct vmw_fence_obj *fence)
735{636{
736 struct ttm_device *bdev = bo->bdev;637 struct ttm_device *bdev = bo->bdev;
737 struct vmw_private *dev_priv =638 struct vmw_private *dev_priv = vmw_priv_from_ttm(bdev);
738 container_of(bdev, struct vmw_private, bdev);
739 int ret;639 int ret;
740 640
741 if (fence == NULL)641 if (fence == NULL)
@@ -771,7 +671,7 @@ int vmw_dumb_create(struct drm_file *file_priv, · 29 unmodified lines
771 struct drm_mode_create_dumb *args)671 struct drm_mode_create_dumb *args)
772{672{
773 struct vmw_private *dev_priv = vmw_priv(dev);673 struct vmw_private *dev_priv = vmw_priv(dev);
774 struct vmw_buffer_object *vbo;674 struct vmw_bo *vbo;
775 int cpp = DIV_ROUND_UP(args->bpp, 8);675 int cpp = DIV_ROUND_UP(args->bpp, 8);
776 int ret;676 int ret;
777 677
@@ -795,7 +695,7 @@ int vmw_dumb_create(struct drm_file *file_priv, · 17 unmodified lines
795 args->size, &args->handle,695 args->size, &args->handle,
796 &vbo);696 &vbo);
797 /* drop reference from allocate - handle holds it now */697 /* drop reference from allocate - handle holds it now */
798 drm_gem_object_put(&vbo->base.base);698 drm_gem_object_put(&vbo->tbo.base);
799 return ret;699 return ret;
800}700}
801 701
@@ -806,12 +706,8 @@ int vmw_dumb_create(struct drm_file *file_priv, · 4 unmodified lines
806 */706 */
807void vmw_bo_swap_notify(struct ttm_buffer_object *bo)707void vmw_bo_swap_notify(struct ttm_buffer_object *bo)
808{708{
809 /* Is @bo embedded in a struct vmw_buffer_object? */
810 if (!bo_is_vmw(bo))
811 return;
812
813 /* Kill any cached kernel maps before swapout */709 /* Kill any cached kernel maps before swapout */
814 vmw_bo_unmap(vmw_buffer_object(bo));710 vmw_bo_unmap(to_vmw_bo(&bo->base));
815}711}
816 712
817 713
@@ -828,13 +724,7 @@ void vmw_bo_swap_notify(struct ttm_buffer_object *bo) · 10 unmodified lines
828void vmw_bo_move_notify(struct ttm_buffer_object *bo,724void vmw_bo_move_notify(struct ttm_buffer_object *bo,
829 struct ttm_resource *mem)725 struct ttm_resource *mem)
830{726{
831 struct vmw_buffer_object *vbo;727 struct vmw_bo *vbo = to_vmw_bo(&bo->base);
832
833 /* Make sure @bo is embedded in a struct vmw_buffer_object? */
834 if (!bo_is_vmw(bo))
835 return;
836
837 vbo = container_of(bo, struct vmw_buffer_object, base);
838 728
839 /*729 /*
840 * Kill any cached kernel maps before move to or from VRAM.730 * Kill any cached kernel maps before move to or from VRAM.
@@ -852,3 +742,98 @@ void vmw_bo_move_notify(struct ttm_buffer_object *bo, · 11 unmodified lines
852 if (mem->mem_type != VMW_PL_MOB && bo->resource->mem_type == VMW_PL_MOB)742 if (mem->mem_type != VMW_PL_MOB && bo->resource->mem_type == VMW_PL_MOB)
853 vmw_resource_unbind_list(vbo);743 vmw_resource_unbind_list(vbo);
854}744}
745
746static u32
747set_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
801void 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
829void 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}
drivers/gpu/drm/vmwgfx/vmwgfx_bo.h+203−0
@@ -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
39struct vmw_bo_dirty;
40struct vmw_fence_obj;
41struct vmw_private;
42struct vmw_resource;
43
44enum 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
52struct 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 */
74struct 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
93void vmw_bo_placement_set(struct vmw_bo *bo, u32 domain, u32 busy_domain);
94void vmw_bo_placement_set_default_accelerated(struct vmw_bo *bo);
95
96int vmw_bo_create(struct vmw_private *dev_priv,
97 struct vmw_bo_params *params,
98 struct vmw_bo **p_bo);
99
100int vmw_bo_unref_ioctl(struct drm_device *dev, void *data,
101 struct drm_file *file_priv);
102
103int vmw_bo_pin_in_vram(struct vmw_private *dev_priv,
104 struct vmw_bo *buf,
105 bool interruptible);
106int vmw_bo_pin_in_vram_or_gmr(struct vmw_private *dev_priv,
107 struct vmw_bo *buf,
108 bool interruptible);
109int vmw_bo_pin_in_start_of_vram(struct vmw_private *vmw_priv,
110 struct vmw_bo *bo,
111 bool interruptible);
112void vmw_bo_pin_reserved(struct vmw_bo *bo, bool pin);
113int vmw_bo_unpin(struct vmw_private *vmw_priv,
114 struct vmw_bo *bo,
115 bool interruptible);
116
117void vmw_bo_get_guest_ptr(const struct ttm_buffer_object *buf,
118 SVGAGuestPtr *ptr);
119int vmw_user_bo_synccpu_ioctl(struct drm_device *dev, void *data,
120 struct drm_file *file_priv);
121void vmw_bo_fence_single(struct ttm_buffer_object *bo,
122 struct vmw_fence_obj *fence);
123
124void *vmw_bo_map_and_cache(struct vmw_bo *vbo);
125void vmw_bo_unmap(struct vmw_bo *vbo);
126
127void vmw_bo_move_notify(struct ttm_buffer_object *bo,
128 struct ttm_resource *mem);
129void vmw_bo_swap_notify(struct ttm_buffer_object *bo);
130
131int 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 */
139static 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 */
162static 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 */
177static 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
183static 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
192static inline struct vmw_bo *vmw_bo_reference(struct vmw_bo *buf)
193{
194 ttm_bo_get(&buf->tbo);
195 return buf;
196}
197
198static 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
drivers/gpu/drm/vmwgfx/vmwgfx_cmd.c+7−7
@@ -1,7 +1,7 @@
1// SPDX-License-Identifier: GPL-2.0 OR MIT1// SPDX-License-Identifier: GPL-2.0 OR MIT
2/**************************************************************************2/**************************************************************************
3 *3 *
4 * Copyright 2009-2020 VMware, Inc., Palo Alto, CA., USA4 * Copyright 2009-2023 VMware, Inc., Palo Alto, CA., USA
5 *5 *
6 * Permission is hereby granted, free of charge, to any person obtaining a6 * Permission is hereby granted, free of charge, to any person obtaining a
7 * copy of this software and associated documentation files (the7 * copy of this software and associated documentation files (the
@@ -24,13 +24,13 @@ · 16 unmodified lines
24 * USE OR OTHER DEALINGS IN THE SOFTWARE.24 * USE OR OTHER DEALINGS IN THE SOFTWARE.
25 *25 *
26 **************************************************************************/26 **************************************************************************/
27 27#include "vmwgfx_bo.h"
28#include <linux/sched/signal.h>28#include "vmwgfx_drv.h"
29#include "vmwgfx_devcaps.h"
29 30
30#include <drm/ttm/ttm_placement.h>31#include <drm/ttm/ttm_placement.h>
31 32
32#include "vmwgfx_drv.h"33#include <linux/sched/signal.h>
33#include "vmwgfx_devcaps.h"
34 34
35bool vmw_supports_3d(struct vmw_private *dev_priv)35bool vmw_supports_3d(struct vmw_private *dev_priv)
36{36{
@@ -567,7 +567,7 @@ static int vmw_cmd_emit_dummy_legacy_query(struct vmw_private *dev_priv, · 530 unmodified lines
567 * without writing to the query result structure.567 * without writing to the query result structure.
568 */568 */
569 569
570 struct ttm_buffer_object *bo = &dev_priv->dummy_query_bo->base;570 struct ttm_buffer_object *bo = &dev_priv->dummy_query_bo->tbo;
571 struct {571 struct {
572 SVGA3dCmdHeader header;572 SVGA3dCmdHeader header;
573 SVGA3dCmdWaitForQuery body;573 SVGA3dCmdWaitForQuery body;
@@ -613,7 +613,7 @@ static int vmw_cmd_emit_dummy_gb_query(struct vmw_private *dev_priv, · 39 unmodified lines
613 * without writing to the query result structure.613 * without writing to the query result structure.
614 */614 */
615 615
616 struct ttm_buffer_object *bo = &dev_priv->dummy_query_bo->base;616 struct ttm_buffer_object *bo = &dev_priv->dummy_query_bo->tbo;
617 struct {617 struct {
618 SVGA3dCmdHeader header;618 SVGA3dCmdHeader header;
619 SVGA3dCmdWaitForGBQuery body;619 SVGA3dCmdWaitForGBQuery body;
drivers/gpu/drm/vmwgfx/vmwgfx_cmdbuf.c+20−33
@@ -1,7 +1,7 @@
1// SPDX-License-Identifier: GPL-2.0 OR MIT1// SPDX-License-Identifier: GPL-2.0 OR MIT
2/**************************************************************************2/**************************************************************************
3 *3 *
4 * Copyright 2015 VMware, Inc., Palo Alto, CA., USA4 * Copyright 2015-2023 VMware, Inc., Palo Alto, CA., USA
5 *5 *
6 * Permission is hereby granted, free of charge, to any person obtaining a6 * Permission is hereby granted, free of charge, to any person obtaining a
7 * copy of this software and associated documentation files (the7 * copy of this software and associated documentation files (the
@@ -25,12 +25,13 @@ · 17 unmodified lines
25 *25 *
26 **************************************************************************/26 **************************************************************************/
27 27
28#include <linux/dmapool.h>28#include "vmwgfx_bo.h"
29#include <linux/pci.h>29#include "vmwgfx_drv.h"
30 30
31#include <drm/ttm/ttm_bo.h>31#include <drm/ttm/ttm_bo.h>
32 32
33#include "vmwgfx_drv.h"33#include <linux/dmapool.h>
34#include <linux/pci.h>
34 35
35/*36/*
36 * Size of inline command buffers. Try to make sure that a page size is a37 * Size of inline command buffers. Try to make sure that a page size is a
@@ -79,7 +80,6 @@ struct vmw_cmdbuf_context { · 42 unmodified lines
79 * frees are protected by @lock.80 * frees are protected by @lock.
80 * @cmd_space: Buffer object for the command buffer space, unless we were81 * @cmd_space: Buffer object for the command buffer space, unless we were
81 * able to make a contigous coherent DMA memory allocation, @handle. Immutable.82 * able to make a contigous coherent DMA memory allocation, @handle. Immutable.
82 * @map_obj: Mapping state for @cmd_space. Immutable.
83 * @map: Pointer to command buffer space. May be a mapped buffer object or83 * @map: Pointer to command buffer space. May be a mapped buffer object or
84 * a contigous coherent DMA memory allocation. Immutable.84 * a contigous coherent DMA memory allocation. Immutable.
85 * @cur: Command buffer for small kernel command submissions. Protected by85 * @cur: Command buffer for small kernel command submissions. Protected by
@@ -116,8 +116,7 @@ struct vmw_cmdbuf_man { · 30 unmodified lines
116 struct vmw_cmdbuf_context ctx[SVGA_CB_CONTEXT_MAX];116 struct vmw_cmdbuf_context ctx[SVGA_CB_CONTEXT_MAX];
117 struct list_head error;117 struct list_head error;
118 struct drm_mm mm;118 struct drm_mm mm;
119 struct ttm_buffer_object *cmd_space;119 struct vmw_bo *cmd_space;
120 struct ttm_bo_kmap_obj map_obj;
121 u8 *map;120 u8 *map;
122 struct vmw_cmdbuf_header *cur;121 struct vmw_cmdbuf_header *cur;
123 size_t cur_pos;122 size_t cur_pos;
@@ -888,7 +887,7 @@ static int vmw_cmdbuf_space_pool(struct vmw_cmdbuf_man *man, · 764 unmodified lines
888 header->cmd = man->map + offset;887 header->cmd = man->map + offset;
889 if (man->using_mob) {888 if (man->using_mob) {
890 cb_hdr->flags = SVGA_CB_FLAG_MOB;889 cb_hdr->flags = SVGA_CB_FLAG_MOB;
891 cb_hdr->ptr.mob.mobid = man->cmd_space->resource->start;890 cb_hdr->ptr.mob.mobid = man->cmd_space->tbo.resource->start;
892 cb_hdr->ptr.mob.mobOffset = offset;891 cb_hdr->ptr.mob.mobOffset = offset;
893 } else {892 } else {
894 cb_hdr->ptr.pa = (u64)man->handle + (u64)offset;893 cb_hdr->ptr.pa = (u64)man->handle + (u64)offset;
@@ -1221,7 +1220,6 @@ static int vmw_cmdbuf_startstop(struct vmw_cmdbuf_man *man, u32 context, · 326 unmodified lines
1221int vmw_cmdbuf_set_pool_size(struct vmw_cmdbuf_man *man, size_t size)1220int vmw_cmdbuf_set_pool_size(struct vmw_cmdbuf_man *man, size_t size)
1222{1221{
1223 struct vmw_private *dev_priv = man->dev_priv;1222 struct vmw_private *dev_priv = man->dev_priv;
1224 bool dummy;
1225 int ret;1223 int ret;
1226 1224
1227 if (man->has_pool)1225 if (man->has_pool)
@@ -1234,6 +1232,13 @@ int vmw_cmdbuf_set_pool_size(struct vmw_cmdbuf_man *man, size_t size) · 6 unmodified lines
1234 if (man->map) {1232 if (man->map) {
1235 man->using_mob = false;1233 man->using_mob = false;
1236 } else {1234 } else {
1235 struct vmw_bo_params bo_params = {
1236 .domain = VMW_BO_DOMAIN_MOB,
1237 .busy_domain = VMW_BO_DOMAIN_MOB,
1238 .bo_type = ttm_bo_type_kernel,
1239 .size = size,
1240 .pin = true
1241 };
1237 /*1242 /*
1238 * DMA memory failed. If we can have command buffers in a1243 * DMA memory failed. If we can have command buffers in a
1239 * MOB, try to use that instead. Note that this will1244 * MOB, try to use that instead. Note that this will
@@ -1244,19 +1249,12 @@ int vmw_cmdbuf_set_pool_size(struct vmw_cmdbuf_man *man, size_t size) · 4 unmodified lines
1244 !dev_priv->has_mob)1249 !dev_priv->has_mob)
1245 return -ENOMEM;1250 return -ENOMEM;
1246 1251
1247 ret = vmw_bo_create_kernel(dev_priv, size,1252 ret = vmw_bo_create(dev_priv, &bo_params, &man->cmd_space);
1248 &vmw_mob_placement,
1249 &man->cmd_space);
1250 if (ret)1253 if (ret)
1251 return ret;1254 return ret;
1252 1255
1253 man->using_mob = true;1256 man->map = vmw_bo_map_and_cache(man->cmd_space);
1254 ret = ttm_bo_kmap(man->cmd_space, 0, size >> PAGE_SHIFT,1257 man->using_mob = man->map;
1255 &man->map_obj);
1256 if (ret)
1257 goto out_no_map;
1258
1259 man->map = ttm_kmap_obj_virtual(&man->map_obj, &dummy);
1260 }1258 }
1261 1259
1262 man->size = size;1260 man->size = size;
@@ -1276,14 +1274,6 @@ int vmw_cmdbuf_set_pool_size(struct vmw_cmdbuf_man *man, size_t size) · 13 unmodified lines
1276 (man->using_mob) ? "MOB" : "DMA");1274 (man->using_mob) ? "MOB" : "DMA");
1277 1275
1278 return 0;1276 return 0;
1279
1280out_no_map:
1281 if (man->using_mob) {
1282 ttm_bo_put(man->cmd_space);
1283 man->cmd_space = NULL;
1284 }
1285
1286 return ret;
1287}1277}
1288 1278
1289/**1279/**
@@ -1382,14 +1372,11 @@ void vmw_cmdbuf_remove_pool(struct vmw_cmdbuf_man *man) · 92 unmodified lines
1382 man->has_pool = false;1372 man->has_pool = false;
1383 man->default_size = VMW_CMDBUF_INLINE_SIZE;1373 man->default_size = VMW_CMDBUF_INLINE_SIZE;
1384 (void) vmw_cmdbuf_idle(man, false, 10*HZ);1374 (void) vmw_cmdbuf_idle(man, false, 10*HZ);
1385 if (man->using_mob) {1375 if (man->using_mob)
1386 (void) ttm_bo_kunmap(&man->map_obj);1376 vmw_bo_unreference(&man->cmd_space);
1387 ttm_bo_put(man->cmd_space);1377 else
1388 man->cmd_space = NULL;
1389 } else {
1390 dma_free_coherent(man->dev_priv->drm.dev,1378 dma_free_coherent(man->dev_priv->drm.dev,
1391 man->size, man->map, man->handle);1379 man->size, man->map, man->handle);
1392 }
1393}1380}
1394 1381
1395/**1382/**
drivers/gpu/drm/vmwgfx/vmwgfx_context.c+20−16
@@ -1,7 +1,7 @@
1// SPDX-License-Identifier: GPL-2.0 OR MIT1// SPDX-License-Identifier: GPL-2.0 OR MIT
2/**************************************************************************2/**************************************************************************
3 *3 *
4 * Copyright 2009-2015 VMware, Inc., Palo Alto, CA., USA4 * Copyright 2009-2023 VMware, Inc., Palo Alto, CA., USA
5 *5 *
6 * Permission is hereby granted, free of charge, to any person obtaining a6 * Permission is hereby granted, free of charge, to any person obtaining a
7 * copy of this software and associated documentation files (the7 * copy of this software and associated documentation files (the
@@ -27,9 +27,10 @@ · 19 unmodified lines
27 27
28#include <drm/ttm/ttm_placement.h>28#include <drm/ttm/ttm_placement.h>
29 29
30#include "vmwgfx_binding.h"
31#include "vmwgfx_bo.h"
30#include "vmwgfx_drv.h"32#include "vmwgfx_drv.h"
31#include "vmwgfx_resource_priv.h"33#include "vmwgfx_resource_priv.h"
32#include "vmwgfx_binding.h"
33 34
34struct vmw_user_context {35struct vmw_user_context {
35 struct ttm_base_object base;36 struct ttm_base_object base;
@@ -38,7 +39,7 @@ struct vmw_user_context { · 2 unmodified lines
38 struct vmw_cmdbuf_res_manager *man;39 struct vmw_cmdbuf_res_manager *man;
39 struct vmw_resource *cotables[SVGA_COTABLE_MAX];40 struct vmw_resource *cotables[SVGA_COTABLE_MAX];
40 spinlock_t cotable_lock;41 spinlock_t cotable_lock;
41 struct vmw_buffer_object *dx_query_mob;42 struct vmw_bo *dx_query_mob;
42};43};
43 44
44static void vmw_user_context_free(struct vmw_resource *res);45static 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
73static const struct vmw_res_func vmw_legacy_context_func = {74static const struct vmw_res_func vmw_legacy_context_func = {
74 .res_type = vmw_res_context,75 .res_type = vmw_res_context,
75 .needs_backup = false,76 .needs_guest_memory = false,
76 .may_evict = false,77 .may_evict = false,
77 .type_name = "legacy contexts",78 .type_name = "legacy contexts",
78 .backup_placement = NULL,79 .domain = VMW_BO_DOMAIN_SYS,
80 .busy_domain = VMW_BO_DOMAIN_SYS,
79 .create = NULL,81 .create = NULL,
80 .destroy = NULL,82 .destroy = NULL,
81 .bind = NULL,83 .bind = NULL,
@@ -84,12 +86,13 @@ static const struct vmw_res_func vmw_legacy_context_func = { · 2 unmodified lines
84 86
85static const struct vmw_res_func vmw_gb_context_func = {87static const struct vmw_res_func vmw_gb_context_func = {
86 .res_type = vmw_res_context,88 .res_type = vmw_res_context,
87 .needs_backup = true,89 .needs_guest_memory = true,
88 .may_evict = true,90 .may_evict = true,
89 .prio = 3,91 .prio = 3,
90 .dirty_prio = 3,92 .dirty_prio = 3,
91 .type_name = "guest backed contexts",93 .type_name = "guest backed contexts",
92 .backup_placement = &vmw_mob_placement,94 .domain = VMW_BO_DOMAIN_MOB,
95 .busy_domain = VMW_BO_DOMAIN_MOB,
93 .create = vmw_gb_context_create,96 .create = vmw_gb_context_create,
94 .destroy = vmw_gb_context_destroy,97 .destroy = vmw_gb_context_destroy,
95 .bind = vmw_gb_context_bind,98 .bind = vmw_gb_context_bind,
@@ -98,12 +101,13 @@ static const struct vmw_res_func vmw_gb_context_func = { · 2 unmodified lines
98 101
99static const struct vmw_res_func vmw_dx_context_func = {102static const struct vmw_res_func vmw_dx_context_func = {
100 .res_type = vmw_res_dx_context,103 .res_type = vmw_res_dx_context,
101 .needs_backup = true,104 .needs_guest_memory = true,
102 .may_evict = true,105 .may_evict = true,
103 .prio = 3,106 .prio = 3,
104 .dirty_prio = 3,107 .dirty_prio = 3,
105 .type_name = "dx contexts",108 .type_name = "dx contexts",
106 .backup_placement = &vmw_mob_placement,109 .domain = VMW_BO_DOMAIN_MOB,
110 .busy_domain = VMW_BO_DOMAIN_MOB,
107 .create = vmw_dx_context_create,111 .create = vmw_dx_context_create,
108 .destroy = vmw_dx_context_destroy,112 .destroy = vmw_dx_context_destroy,
109 .bind = vmw_dx_context_bind,113 .bind = vmw_dx_context_bind,
@@ -182,7 +186,7 @@ static int vmw_gb_context_init(struct vmw_private *dev_priv, · 72 unmodified lines
182 struct vmw_user_context *uctx =186 struct vmw_user_context *uctx =
183 container_of(res, struct vmw_user_context, res);187 container_of(res, struct vmw_user_context, res);
184 188
185 res->backup_size = (dx ? sizeof(SVGADXContextMobFormat) :189 res->guest_memory_size = (dx ? sizeof(SVGADXContextMobFormat) :
186 sizeof(SVGAGBContextData));190 sizeof(SVGAGBContextData));
187 ret = vmw_resource_init(dev_priv, res, true,191 ret = vmw_resource_init(dev_priv, res, true,
188 res_free,192 res_free,
@@ -354,8 +358,8 @@ static int vmw_gb_context_bind(struct vmw_resource *res, · 165 unmodified lines
354 cmd->header.size = sizeof(cmd->body);358 cmd->header.size = sizeof(cmd->body);
355 cmd->body.cid = res->id;359 cmd->body.cid = res->id;
356 cmd->body.mobid = bo->resource->start;360 cmd->body.mobid = bo->resource->start;
357 cmd->body.validContents = res->backup_dirty;361 cmd->body.validContents = res->guest_memory_dirty;
358 res->backup_dirty = false;362 res->guest_memory_dirty = false;
359 vmw_cmd_commit(dev_priv, sizeof(*cmd));363 vmw_cmd_commit(dev_priv, sizeof(*cmd));
360 364
361 return 0;365 return 0;
@@ -521,8 +525,8 @@ static int vmw_dx_context_bind(struct vmw_resource *res, · 159 unmodified lines
521 cmd->header.size = sizeof(cmd->body);525 cmd->header.size = sizeof(cmd->body);
522 cmd->body.cid = res->id;526 cmd->body.cid = res->id;
523 cmd->body.mobid = bo->resource->start;527 cmd->body.mobid = bo->resource->start;
524 cmd->body.validContents = res->backup_dirty;528 cmd->body.validContents = res->guest_memory_dirty;
525 res->backup_dirty = false;529 res->guest_memory_dirty = false;
526 vmw_cmd_commit(dev_priv, sizeof(*cmd));530 vmw_cmd_commit(dev_priv, sizeof(*cmd));
527 531
528 532
@@ -853,7 +857,7 @@ vmw_context_binding_state(struct vmw_resource *ctx) · 324 unmodified lines
853 * specified in the parameter. 0 otherwise.857 * specified in the parameter. 0 otherwise.
854 */858 */
855int vmw_context_bind_dx_query(struct vmw_resource *ctx_res,859int vmw_context_bind_dx_query(struct vmw_resource *ctx_res,
856 struct vmw_buffer_object *mob)860 struct vmw_bo *mob)
857{861{
858 struct vmw_user_context *uctx =862 struct vmw_user_context *uctx =
859 container_of(ctx_res, struct vmw_user_context, res);863 container_of(ctx_res, struct vmw_user_context, res);
@@ -885,7 +889,7 @@ int vmw_context_bind_dx_query(struct vmw_resource *ctx_res, · 25 unmodified lines
885 *889 *
886 * @ctx_res: The context resource890 * @ctx_res: The context resource
887 */891 */
888struct vmw_buffer_object *892struct vmw_bo *
889vmw_context_get_dx_query_mob(struct vmw_resource *ctx_res)893vmw_context_get_dx_query_mob(struct vmw_resource *ctx_res)
890{894{
891 struct vmw_user_context *uctx =895 struct vmw_user_context *uctx =
drivers/gpu/drm/vmwgfx/vmwgfx_cotable.c+38−27
@@ -1,7 +1,7 @@
1// SPDX-License-Identifier: GPL-2.0 OR MIT1// SPDX-License-Identifier: GPL-2.0 OR MIT
2/**************************************************************************2/**************************************************************************
3 *3 *
4 * Copyright 2014-2015 VMware, Inc., Palo Alto, CA., USA4 * Copyright 2014-2023 VMware, Inc., Palo Alto, CA., USA
5 *5 *
6 * Permission is hereby granted, free of charge, to any person obtaining a6 * Permission is hereby granted, free of charge, to any person obtaining a
7 * copy of this software and associated documentation files (the7 * copy of this software and associated documentation files (the
@@ -30,13 +30,14 @@ · 22 unmodified lines
30 * whenever the backing MOB is evicted.30 * whenever the backing MOB is evicted.
31 */31 */
32 32
33#include <drm/ttm/ttm_placement.h>33#include "vmwgfx_bo.h"
34
35#include "vmwgfx_drv.h"34#include "vmwgfx_drv.h"
36#include "vmwgfx_mksstat.h"35#include "vmwgfx_mksstat.h"
37#include "vmwgfx_resource_priv.h"36#include "vmwgfx_resource_priv.h"
38#include "vmwgfx_so.h"37#include "vmwgfx_so.h"
39 38
39#include <drm/ttm/ttm_placement.h>
40
40/**41/**
41 * struct vmw_cotable - Context Object Table resource42 * 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
131static const struct vmw_res_func vmw_cotable_func = {132static const struct vmw_res_func vmw_cotable_func = {
132 .res_type = vmw_res_cotable,133 .res_type = vmw_res_cotable,
133 .needs_backup = true,134 .needs_guest_memory = true,
134 .may_evict = true,135 .may_evict = true,
135 .prio = 3,136 .prio = 3,
136 .dirty_prio = 3,137 .dirty_prio = 3,
137 .type_name = "context guest backed object tables",138 .type_name = "context guest backed object tables",
138 .backup_placement = &vmw_mob_placement,139 .domain = VMW_BO_DOMAIN_MOB,
140 .busy_domain = VMW_BO_DOMAIN_MOB,
139 .create = vmw_cotable_create,141 .create = vmw_cotable_create,
140 .destroy = vmw_cotable_destroy,142 .destroy = vmw_cotable_destroy,
141 .bind = vmw_cotable_bind,143 .bind = vmw_cotable_bind,
@@ -180,7 +182,7 @@ static int vmw_cotable_unscrub(struct vmw_resource *res) · 38 unmodified lines
180{182{
181 struct vmw_cotable *vcotbl = vmw_cotable(res);183 struct vmw_cotable *vcotbl = vmw_cotable(res);
182 struct vmw_private *dev_priv = res->dev_priv;184 struct vmw_private *dev_priv = res->dev_priv;
183 struct ttm_buffer_object *bo = &res->backup->base;185 struct ttm_buffer_object *bo = &res->guest_memory_bo->tbo;
184 struct {186 struct {
185 SVGA3dCmdHeader header;187 SVGA3dCmdHeader header;
186 SVGA3dCmdDXSetCOTable body;188 SVGA3dCmdDXSetCOTable body;
@@ -228,7 +230,7 @@ static int vmw_cotable_bind(struct vmw_resource *res, · 41 unmodified lines
228 * take the opportunity to correct the value here so that it's not230 * take the opportunity to correct the value here so that it's not
229 * misused in the future.231 * misused in the future.
230 */232 */
231 val_buf->bo = &res->backup->base;233 val_buf->bo = &res->guest_memory_bo->tbo;
232 234
233 return vmw_cotable_unscrub(res);235 return vmw_cotable_unscrub(res);
234}236}
@@ -289,7 +291,7 @@ int vmw_cotable_scrub(struct vmw_resource *res, bool readback) · 54 unmodified lines
289 cmd0->body.cid = vcotbl->ctx->id;291 cmd0->body.cid = vcotbl->ctx->id;
290 cmd0->body.type = vcotbl->type;292 cmd0->body.type = vcotbl->type;
291 cmd1 = (void *) &cmd0[1];293 cmd1 = (void *) &cmd0[1];
292 vcotbl->size_read_back = res->backup_size;294 vcotbl->size_read_back = res->guest_memory_size;
293 }295 }
294 cmd1->header.id = SVGA_3D_CMD_DX_SET_COTABLE;296 cmd1->header.id = SVGA_3D_CMD_DX_SET_COTABLE;
295 cmd1->header.size = sizeof(cmd1->body);297 cmd1->header.size = sizeof(cmd1->body);
@@ -371,12 +373,12 @@ static int vmw_cotable_readback(struct vmw_resource *res) · 75 unmodified lines
371 cmd->header.size = sizeof(cmd->body);373 cmd->header.size = sizeof(cmd->body);
372 cmd->body.cid = vcotbl->ctx->id;374 cmd->body.cid = vcotbl->ctx->id;
373 cmd->body.type = vcotbl->type;375 cmd->body.type = vcotbl->type;
374 vcotbl->size_read_back = res->backup_size;376 vcotbl->size_read_back = res->guest_memory_size;
375 vmw_cmd_commit(dev_priv, sizeof(*cmd));377 vmw_cmd_commit(dev_priv, sizeof(*cmd));
376 }378 }
377 379
378 (void) vmw_execbuf_fence_commands(NULL, dev_priv, &fence, NULL);380 (void) vmw_execbuf_fence_commands(NULL, dev_priv, &fence, NULL);
379 vmw_bo_fence_single(&res->backup->base, fence);381 vmw_bo_fence_single(&res->guest_memory_bo->tbo, fence);
380 vmw_fence_obj_unreference(&fence);382 vmw_fence_obj_unreference(&fence);
381 383
382 return 0;384 return 0;
@@ -399,14 +401,21 @@ static int vmw_cotable_resize(struct vmw_resource *res, size_t new_size) · 16 unmodified lines
399 struct ttm_operation_ctx ctx = { false, false };401 struct ttm_operation_ctx ctx = { false, false };
400 struct vmw_private *dev_priv = res->dev_priv;402 struct vmw_private *dev_priv = res->dev_priv;
401 struct vmw_cotable *vcotbl = vmw_cotable(res);403 struct vmw_cotable *vcotbl = vmw_cotable(res);
402 struct vmw_buffer_object *buf, *old_buf = res->backup;404 struct vmw_bo *buf, *old_buf = res->guest_memory_bo;
403 struct ttm_buffer_object *bo, *old_bo = &res->backup->base;405 struct ttm_buffer_object *bo, *old_bo = &res->guest_memory_bo->tbo;
404 size_t old_size = res->backup_size;406 size_t old_size = res->guest_memory_size;
405 size_t old_size_read_back = vcotbl->size_read_back;407 size_t old_size_read_back = vcotbl->size_read_back;
406 size_t cur_size_read_back;408 size_t cur_size_read_back;
407 struct ttm_bo_kmap_obj old_map, new_map;409 struct ttm_bo_kmap_obj old_map, new_map;
408 int ret;410 int ret;
409 size_t i;411 size_t i;
412 struct vmw_bo_params bo_params = {
413 .domain = VMW_BO_DOMAIN_MOB,
414 .busy_domain = VMW_BO_DOMAIN_MOB,
415 .bo_type = ttm_bo_type_device,
416 .size = new_size,
417 .pin = true
418 };
410 419
411 MKS_STAT_TIME_DECL(MKSSTAT_KERN_COTABLE_RESIZE);420 MKS_STAT_TIME_DECL(MKSSTAT_KERN_COTABLE_RESIZE);
412 MKS_STAT_TIME_PUSH(MKSSTAT_KERN_COTABLE_RESIZE);421 MKS_STAT_TIME_PUSH(MKSSTAT_KERN_COTABLE_RESIZE);
@@ -423,14 +432,13 @@ static int vmw_cotable_resize(struct vmw_resource *res, size_t new_size) · 10 unmodified lines
423 * for the new COTable. Initially pin the buffer object to make sure432 * for the new COTable. Initially pin the buffer object to make sure
424 * we can use tryreserve without failure.433 * we can use tryreserve without failure.
425 */434 */
426 ret = vmw_bo_create(dev_priv, new_size, &vmw_mob_placement,435 ret = vmw_bo_create(dev_priv, &bo_params, &buf);
427 true, true, vmw_bo_bo_free, &buf);
428 if (ret) {436 if (ret) {
429 DRM_ERROR("Failed initializing new cotable MOB.\n");437 DRM_ERROR("Failed initializing new cotable MOB.\n");
430 goto out_done;438 goto out_done;
431 }439 }
432 440
433 bo = &buf->base;441 bo = &buf->tbo;
434 WARN_ON_ONCE(ttm_bo_reserve(bo, false, true, NULL));442 WARN_ON_ONCE(ttm_bo_reserve(bo, false, true, NULL));
435 443
436 ret = ttm_bo_wait(old_bo, false, false);444 ret = ttm_bo_wait(old_bo, false, false);
@@ -464,15 +472,18 @@ static int vmw_cotable_resize(struct vmw_resource *res, size_t new_size) · 27 unmodified lines
464 }472 }
465 473
466 /* Unpin new buffer, and switch backup buffers. */474 /* Unpin new buffer, and switch backup buffers. */
467 ret = ttm_bo_validate(bo, &vmw_mob_placement, &ctx);475 vmw_bo_placement_set(buf,
476 VMW_BO_DOMAIN_MOB,
477 VMW_BO_DOMAIN_MOB);
478 ret = ttm_bo_validate(bo, &buf->placement, &ctx);
468 if (unlikely(ret != 0)) {479 if (unlikely(ret != 0)) {
469 DRM_ERROR("Failed validating new COTable backup buffer.\n");480 DRM_ERROR("Failed validating new COTable backup buffer.\n");
470 goto out_wait;481 goto out_wait;
471 }482 }
472 483
473 vmw_resource_mob_detach(res);484 vmw_resource_mob_detach(res);
474 res->backup = buf;485 res->guest_memory_bo = buf;
475 res->backup_size = new_size;486 res->guest_memory_size = new_size;
476 vcotbl->size_read_back = cur_size_read_back;487 vcotbl->size_read_back = cur_size_read_back;
477 488
478 /*489 /*
@@ -482,8 +493,8 @@ static int vmw_cotable_resize(struct vmw_resource *res, size_t new_size) · 3 unmodified lines
482 ret = vmw_cotable_unscrub(res);493 ret = vmw_cotable_unscrub(res);
483 if (ret) {494 if (ret) {
484 DRM_ERROR("Failed switching COTable backup buffer.\n");495 DRM_ERROR("Failed switching COTable backup buffer.\n");
485 res->backup = old_buf;496 res->guest_memory_bo = old_buf;
486 res->backup_size = old_size;497 res->guest_memory_size = old_size;
487 vcotbl->size_read_back = old_size_read_back;498 vcotbl->size_read_back = old_size_read_back;
488 vmw_resource_mob_attach(res);499 vmw_resource_mob_attach(res);
489 goto out_wait;500 goto out_wait;
@@ -498,7 +509,7 @@ static int vmw_cotable_resize(struct vmw_resource *res, size_t new_size) · 8 unmodified lines
498 if (unlikely(ret))509 if (unlikely(ret))
499 goto out_wait;510 goto out_wait;
500 511
501 /* Release the pin acquired in vmw_bo_init */512 /* Release the pin acquired in vmw_bo_create */
502 ttm_bo_unpin(bo);513 ttm_bo_unpin(bo);
503 514
504 MKS_STAT_TIME_POP(MKSSTAT_KERN_COTABLE_RESIZE);515 MKS_STAT_TIME_POP(MKSSTAT_KERN_COTABLE_RESIZE);
@@ -533,7 +544,7 @@ out_done: · 28 unmodified lines
533static int vmw_cotable_create(struct vmw_resource *res)544static int vmw_cotable_create(struct vmw_resource *res)
534{545{
535 struct vmw_cotable *vcotbl = vmw_cotable(res);546 struct vmw_cotable *vcotbl = vmw_cotable(res);
536 size_t new_size = res->backup_size;547 size_t new_size = res->guest_memory_size;
537 size_t needed_size;548 size_t needed_size;
538 int ret;549 int ret;
539 550
@@ -542,7 +553,7 @@ static int vmw_cotable_create(struct vmw_resource *res) · 2 unmodified lines
542 while (needed_size > new_size)553 while (needed_size > new_size)
543 new_size *= 2;554 new_size *= 2;
544 555
545 if (likely(new_size <= res->backup_size)) {556 if (likely(new_size <= res->guest_memory_size)) {
546 if (vcotbl->scrubbed && vmw_resource_mob_attached(res)) {557 if (vcotbl->scrubbed && vmw_resource_mob_attached(res)) {
547 ret = vmw_cotable_unscrub(res);558 ret = vmw_cotable_unscrub(res);
548 if (ret)559 if (ret)
@@ -606,12 +617,12 @@ struct vmw_resource *vmw_cotable_alloc(struct vmw_private *dev_priv, · 57 unmodified lines
606 617
607 INIT_LIST_HEAD(&vcotbl->resource_list);618 INIT_LIST_HEAD(&vcotbl->resource_list);
608 vcotbl->res.id = type;619 vcotbl->res.id = type;
609 vcotbl->res.backup_size = PAGE_SIZE;620 vcotbl->res.guest_memory_size = PAGE_SIZE;
610 num_entries = PAGE_SIZE / co_info[type].size;621 num_entries = PAGE_SIZE / co_info[type].size;
611 if (num_entries < co_info[type].min_initial_entries) {622 if (num_entries < co_info[type].min_initial_entries) {
612 vcotbl->res.backup_size = co_info[type].min_initial_entries *623 vcotbl->res.guest_memory_size = co_info[type].min_initial_entries *
613 co_info[type].size;624 co_info[type].size;
614 vcotbl->res.backup_size = PFN_ALIGN(vcotbl->res.backup_size);625 vcotbl->res.guest_memory_size = PFN_ALIGN(vcotbl->res.guest_memory_size);
615 }626 }
616 627
617 vcotbl->scrubbed = true;628 vcotbl->scrubbed = true;
drivers/gpu/drm/vmwgfx/vmwgfx_drv.c+16−10
@@ -1,7 +1,7 @@
1// SPDX-License-Identifier: GPL-2.0 OR MIT1// SPDX-License-Identifier: GPL-2.0 OR MIT
2/**************************************************************************2/**************************************************************************
3 *3 *
4 * Copyright 2009-2022 VMware, Inc., Palo Alto, CA., USA4 * Copyright 2009-2023 VMware, Inc., Palo Alto, CA., USA
5 *5 *
6 * Permission is hereby granted, free of charge, to any person obtaining a6 * Permission is hereby granted, free of charge, to any person obtaining a
7 * copy of this software and associated documentation files (the7 * copy of this software and associated documentation files (the
@@ -28,9 +28,10 @@ · 20 unmodified lines
28 28
29#include "vmwgfx_drv.h"29#include "vmwgfx_drv.h"
30 30
31#include "vmwgfx_bo.h"
32#include "vmwgfx_binding.h"
31#include "vmwgfx_devcaps.h"33#include "vmwgfx_devcaps.h"
32#include "vmwgfx_mksstat.h"34#include "vmwgfx_mksstat.h"
33#include "vmwgfx_binding.h"
34#include "ttm_object.h"35#include "ttm_object.h"
35 36
36#include <drm/drm_aperture.h>37#include <drm/drm_aperture.h>
@@ -386,27 +387,32 @@ static void vmw_print_sm_type(struct vmw_private *dev_priv) · 349 unmodified lines
386static int vmw_dummy_query_bo_create(struct vmw_private *dev_priv)387static int vmw_dummy_query_bo_create(struct vmw_private *dev_priv)
387{388{
388 int ret;389 int ret;
389 struct vmw_buffer_object *vbo;390 struct vmw_bo *vbo;
390 struct ttm_bo_kmap_obj map;391 struct ttm_bo_kmap_obj map;
391 volatile SVGA3dQueryResult *result;392 volatile SVGA3dQueryResult *result;
392 bool dummy;393 bool dummy;
394 struct vmw_bo_params bo_params = {
395 .domain = VMW_BO_DOMAIN_SYS,
396 .busy_domain = VMW_BO_DOMAIN_SYS,
397 .bo_type = ttm_bo_type_kernel,
398 .size = PAGE_SIZE,
399 .pin = true
400 };
393 401
394 /*402 /*
395 * Create the vbo as pinned, so that a tryreserve will403 * Create the vbo as pinned, so that a tryreserve will
396 * immediately succeed. This is because we're the only404 * immediately succeed. This is because we're the only
397 * user of the bo currently.405 * user of the bo currently.
398 */406 */
399 ret = vmw_bo_create(dev_priv, PAGE_SIZE,407 ret = vmw_bo_create(dev_priv, &bo_params, &vbo);
400 &vmw_sys_placement, false, true,
401 &vmw_bo_bo_free, &vbo);
402 if (unlikely(ret != 0))408 if (unlikely(ret != 0))
403 return ret;409 return ret;
404 410
405 ret = ttm_bo_reserve(&vbo->base, false, true, NULL);411 ret = ttm_bo_reserve(&vbo->tbo, false, true, NULL);
406 BUG_ON(ret != 0);412 BUG_ON(ret != 0);
407 vmw_bo_pin_reserved(vbo, true);413 vmw_bo_pin_reserved(vbo, true);
408 414
409 ret = ttm_bo_kmap(&vbo->base, 0, 1, &map);415 ret = ttm_bo_kmap(&vbo->tbo, 0, 1, &map);
410 if (likely(ret == 0)) {416 if (likely(ret == 0)) {
411 result = ttm_kmap_obj_virtual(&map, &dummy);417 result = ttm_kmap_obj_virtual(&map, &dummy);
412 result->totalSize = sizeof(*result);418 result->totalSize = sizeof(*result);
@@ -415,7 +421,7 @@ static int vmw_dummy_query_bo_create(struct vmw_private *dev_priv) · 2 unmodified lines
415 ttm_bo_kunmap(&map);421 ttm_bo_kunmap(&map);
416 }422 }
417 vmw_bo_pin_reserved(vbo, false);423 vmw_bo_pin_reserved(vbo, false);
418 ttm_bo_unreserve(&vbo->base);424 ttm_bo_unreserve(&vbo->tbo);
419 425
420 if (unlikely(ret != 0)) {426 if (unlikely(ret != 0)) {
421 DRM_ERROR("Dummy query buffer map failed.\n");427 DRM_ERROR("Dummy query buffer map failed.\n");
@@ -1565,7 +1571,7 @@ static const struct file_operations vmwgfx_driver_fops = { · 1143 unmodified lines
1565 .open = drm_open,1571 .open = drm_open,
1566 .release = drm_release,1572 .release = drm_release,
1567 .unlocked_ioctl = vmw_unlocked_ioctl,1573 .unlocked_ioctl = vmw_unlocked_ioctl,
1568 .mmap = vmw_mmap,1574 .mmap = drm_gem_mmap,
1569 .poll = drm_poll,1575 .poll = drm_poll,
1570 .read = drm_read,1576 .read = drm_read,
1571#if defined(CONFIG_COMPAT)1577#if defined(CONFIG_COMPAT)
drivers/gpu/drm/vmwgfx/vmwgfx_drv.h+48−197
@@ -1,7 +1,7 @@
1/* SPDX-License-Identifier: GPL-2.0 OR MIT */1/* SPDX-License-Identifier: GPL-2.0 OR MIT */
2/**************************************************************************2/**************************************************************************
3 *3 *
4 * Copyright 2009-2022 VMware, Inc., Palo Alto, CA., USA4 * Copyright 2009-2023 VMware, Inc., Palo Alto, CA., USA
5 *5 *
6 * Permission is hereby granted, free of charge, to any person obtaining a6 * Permission is hereby granted, free of charge, to any person obtaining a
7 * copy of this software and associated documentation files (the7 * copy of this software and associated documentation files (the
@@ -117,32 +117,6 @@ struct vmwgfx_hash_item { · 109 unmodified lines
117 unsigned long key;117 unsigned long key;
118};118};
119 119
120/**
121 * struct vmw_buffer_object - TTM buffer object with vmwgfx additions
122 * @base: The TTM buffer object
123 * @res_tree: RB tree of resources using this buffer object as a backing MOB
124 * @base_mapped_count: ttm BO mapping count; used by KMS atomic helpers.
125 * @cpu_writers: Number of synccpu write grabs. Protected by reservation when
126 * increased. May be decreased without reservation.
127 * @dx_query_ctx: DX context if this buffer object is used as a DX query MOB
128 * @map: Kmap object for semi-persistent mappings
129 * @res_prios: Eviction priority counts for attached resources
130 * @dirty: structure for user-space dirty-tracking
131 */
132struct vmw_buffer_object {
133 struct ttm_buffer_object base;
134 struct rb_root res_tree;
135 /* For KMS atomic helpers: ttm bo mapping count */
136 atomic_t base_mapped_count;
137
138 atomic_t cpu_writers;
139 /* Not ref-counted. Protected by binding_mutex */
140 struct vmw_resource *dx_query_ctx;
141 /* Protected by reservation */
142 struct ttm_bo_kmap_obj map;
143 u32 res_prios[TTM_MAX_BO_PRIORITY];
144 struct vmw_bo_dirty *dirty;
145};
146 120
147/**121/**
148 * struct vmw_validate_buffer - Carries validation info about buffers.122 * struct vmw_validate_buffer - Carries validation info about buffers.
@@ -168,21 +142,23 @@ struct vmw_res_func; · 19 unmodified lines
168 * @kref: For refcounting.142 * @kref: For refcounting.
169 * @dev_priv: Pointer to the device private for this resource. Immutable.143 * @dev_priv: Pointer to the device private for this resource. Immutable.
170 * @id: Device id. Protected by @dev_priv::resource_lock.144 * @id: Device id. Protected by @dev_priv::resource_lock.
171 * @backup_size: Backup buffer size. Immutable.145 * @guest_memory_size: Guest memory buffer size. Immutable.
172 * @res_dirty: Resource contains data not yet in the backup buffer. Protected146 * @res_dirty: Resource contains data not yet in the guest memory buffer.
173 * by resource reserved.
174 * @backup_dirty: Backup buffer contains data not yet in the HW resource.
175 * Protected by resource reserved.147 * Protected by resource reserved.
148 * @guest_memory_dirty: Guest memory buffer contains data not yet in the HW
149 * resource. Protected by resource reserved.
176 * @coherent: Emulate coherency by tracking vm accesses.150 * @coherent: Emulate coherency by tracking vm accesses.
177 * @backup: The backup buffer if any. Protected by resource reserved.151 * @guest_memory_bo: The guest memory buffer if any. Protected by resource
178 * @backup_offset: Offset into the backup buffer if any. Protected by resource152 * reserved.
179 * reserved. Note that only a few resource types can have a @backup_offset153 * @guest_memory_offset: Offset into the guest memory buffer if any. Protected
180 * different from zero.154 * by resource reserved. Note that only a few resource types can have a
155 * @guest_memory_offset different from zero.
181 * @pin_count: The pin count for this resource. A pinned resource has a156 * @pin_count: The pin count for this resource. A pinned resource has a
182 * pin-count greater than zero. It is not on the resource LRU lists and its157 * pin-count greater than zero. It is not on the resource LRU lists and its
183 * backup buffer is pinned. Hence it can't be evicted.158 * guest memory buffer is pinned. Hence it can't be evicted.
184 * @func: Method vtable for this resource. Immutable.159 * @func: Method vtable for this resource. Immutable.
185 * @mob_node; Node for the MOB backup rbtree. Protected by @backup reserved.160 * @mob_node; Node for the MOB guest memory rbtree. Protected by
161 * @guest_memory_bo reserved.
186 * @lru_head: List head for the LRU list. Protected by @dev_priv::resource_lock.162 * @lru_head: List head for the LRU list. Protected by @dev_priv::resource_lock.
187 * @binding_head: List head for the context binding list. Protected by163 * @binding_head: List head for the context binding list. Protected by
188 * the @dev_priv::binding_mutex164 * the @dev_priv::binding_mutex
@@ -190,18 +166,20 @@ struct vmw_res_func; · 1 unmodified line
190 * @hw_destroy: Callback to destroy the resource on the device, as part of166 * @hw_destroy: Callback to destroy the resource on the device, as part of
191 * resource destruction.167 * resource destruction.
192 */168 */
169struct vmw_bo;
170struct vmw_bo;
193struct vmw_resource_dirty;171struct vmw_resource_dirty;
194struct vmw_resource {172struct vmw_resource {
195 struct kref kref;173 struct kref kref;
196 struct vmw_private *dev_priv;174 struct vmw_private *dev_priv;
197 int id;175 int id;
198 u32 used_prio;176 u32 used_prio;
199 unsigned long backup_size;177 unsigned long guest_memory_size;
200 u32 res_dirty : 1;178 u32 res_dirty : 1;
201 u32 backup_dirty : 1;179 u32 guest_memory_dirty : 1;
202 u32 coherent : 1;180 u32 coherent : 1;
203 struct vmw_buffer_object *backup;181 struct vmw_bo *guest_memory_bo;
204 unsigned long backup_offset;182 unsigned long guest_memory_offset;
205 unsigned long pin_count;183 unsigned long pin_count;
206 const struct vmw_res_func *func;184 const struct vmw_res_func *func;
207 struct rb_node mob_node;185 struct rb_node mob_node;
@@ -446,7 +424,7 @@ struct vmw_sw_context{ · 238 unmodified lines
446 struct drm_file *filp;424 struct drm_file *filp;
447 uint32_t *cmd_bounce;425 uint32_t *cmd_bounce;
448 uint32_t cmd_bounce_size;426 uint32_t cmd_bounce_size;
449 struct vmw_buffer_object *cur_query_bo;427 struct vmw_bo *cur_query_bo;
450 struct list_head bo_relocations;428 struct list_head bo_relocations;
451 struct list_head res_relocations;429 struct list_head res_relocations;
452 uint32_t *buf_start;430 uint32_t *buf_start;
@@ -458,7 +436,7 @@ struct vmw_sw_context{ · 5 unmodified lines
458 struct list_head staged_cmd_res;436 struct list_head staged_cmd_res;
459 struct list_head ctx_list;437 struct list_head ctx_list;
460 struct vmw_ctx_validation_info *dx_ctx_node;438 struct vmw_ctx_validation_info *dx_ctx_node;
461 struct vmw_buffer_object *dx_query_mob;439 struct vmw_bo *dx_query_mob;
462 struct vmw_resource *dx_query_ctx;440 struct vmw_resource *dx_query_ctx;
463 struct vmw_cmdbuf_res_manager *man;441 struct vmw_cmdbuf_res_manager *man;
464 struct vmw_validation_context *ctx;442 struct vmw_validation_context *ctx;
@@ -492,7 +470,7 @@ struct vmw_otable_batch { · 27 unmodified lines
492 unsigned num_otables;470 unsigned num_otables;
493 struct vmw_otable *otables;471 struct vmw_otable *otables;
494 struct vmw_resource *context;472 struct vmw_resource *context;
495 struct ttm_buffer_object *otable_bo;473 struct vmw_bo *otable_bo;
496};474};
497 475
498enum {476enum {
@@ -632,8 +610,8 @@ struct vmw_private { · 133 unmodified lines
632 * are protected by the cmdbuf mutex.610 * are protected by the cmdbuf mutex.
633 */611 */
634 612
635 struct vmw_buffer_object *dummy_query_bo;613 struct vmw_bo *dummy_query_bo;
636 struct vmw_buffer_object *pinned_bo;614 struct vmw_bo *pinned_bo;
637 uint32_t query_cid;615 uint32_t query_cid;
638 uint32_t query_cid_valid;616 uint32_t query_cid_valid;
639 bool dummy_query_bo_pinned;617 bool dummy_query_bo_pinned;
@@ -677,11 +655,6 @@ struct vmw_private { · 37 unmodified lines
677#endif655#endif
678};656};
679 657
680static 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
685static inline struct vmw_surface *vmw_res_to_srf(struct vmw_resource *res)658static inline struct vmw_surface *vmw_res_to_srf(struct vmw_resource *res)
686{659{
687 return container_of(res, struct vmw_surface, res);660 return container_of(res, struct vmw_surface, res);
@@ -692,6 +665,11 @@ static inline struct vmw_private *vmw_priv(struct drm_device *dev) · 4 unmodified lines
692 return (struct vmw_private *)dev->dev_private;665 return (struct vmw_private *)dev->dev_private;
693}666}
694 667
668static inline struct vmw_private *vmw_priv_from_ttm(struct ttm_device *bdev)
669{
670 return container_of(bdev, struct vmw_private, bdev);
671}
672
695static inline struct vmw_fpriv *vmw_fpriv(struct drm_file *file_priv)673static inline struct vmw_fpriv *vmw_fpriv(struct drm_file *file_priv)
696{674{
697 return (struct vmw_fpriv *)file_priv->driver_priv;675 return (struct vmw_fpriv *)file_priv->driver_priv;
@@ -825,7 +803,7 @@ extern int vmw_user_lookup_handle(struct vmw_private *dev_priv, · 127 unmodified lines
825 struct drm_file *filp,803 struct drm_file *filp,
826 uint32_t handle,804 uint32_t handle,
827 struct vmw_surface **out_surf,805 struct vmw_surface **out_surf,
828 struct vmw_buffer_object **out_buf);806 struct vmw_bo **out_buf);
829extern int vmw_user_resource_lookup_handle(807extern int vmw_user_resource_lookup_handle(
830 struct vmw_private *dev_priv,808 struct vmw_private *dev_priv,
831 struct ttm_object_file *tfile,809 struct ttm_object_file *tfile,
@@ -844,20 +822,20 @@ extern int vmw_user_stream_lookup(struct vmw_private *dev_priv, · 12 unmodified lines
844extern void vmw_resource_unreserve(struct vmw_resource *res,822extern void vmw_resource_unreserve(struct vmw_resource *res,
845 bool dirty_set,823 bool dirty_set,
846 bool dirty,824 bool dirty,
847 bool switch_backup,825 bool switch_guest_memory,
848 struct vmw_buffer_object *new_backup,826 struct vmw_bo *new_guest_memory,
849 unsigned long new_backup_offset);827 unsigned long new_guest_memory_offset);
850extern void vmw_query_move_notify(struct ttm_buffer_object *bo,828extern void vmw_query_move_notify(struct ttm_buffer_object *bo,
851 struct ttm_resource *old_mem,829 struct ttm_resource *old_mem,
852 struct ttm_resource *new_mem);830 struct ttm_resource *new_mem);
853extern int vmw_query_readback_all(struct vmw_buffer_object *dx_query_mob);831int vmw_query_readback_all(struct vmw_bo *dx_query_mob);
854extern void vmw_resource_evict_all(struct vmw_private *dev_priv);832void vmw_resource_evict_all(struct vmw_private *dev_priv);
855extern void vmw_resource_unbind_list(struct vmw_buffer_object *vbo);833void vmw_resource_unbind_list(struct vmw_bo *vbo);
856void vmw_resource_mob_attach(struct vmw_resource *res);834void vmw_resource_mob_attach(struct vmw_resource *res);
857void vmw_resource_mob_detach(struct vmw_resource *res);835void vmw_resource_mob_detach(struct vmw_resource *res);
858void vmw_resource_dirty_update(struct vmw_resource *res, pgoff_t start,836void vmw_resource_dirty_update(struct vmw_resource *res, pgoff_t start,
859 pgoff_t end);837 pgoff_t end);
860int vmw_resources_clean(struct vmw_buffer_object *vbo, pgoff_t start,838int vmw_resources_clean(struct vmw_bo *vbo, pgoff_t start,
861 pgoff_t end, pgoff_t *num_prefault);839 pgoff_t end, pgoff_t *num_prefault);
862 840
863/**841/**
@@ -871,107 +849,6 @@ static inline bool vmw_resource_mob_attached(const struct vmw_resource *res) · 7 unmodified lines
871 return !RB_EMPTY_NODE(&res->mob_node);849 return !RB_EMPTY_NODE(&res->mob_node);
872}850}
873 851
874/**
875 * Buffer object helper functions - vmwgfx_bo.c
876 */
877extern 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);
881extern int vmw_bo_pin_in_vram(struct vmw_private *dev_priv,
882 struct vmw_buffer_object *buf,
883 bool interruptible);
884extern int vmw_bo_pin_in_vram_or_gmr(struct vmw_private *dev_priv,
885 struct vmw_buffer_object *buf,
886 bool interruptible);
887extern int vmw_bo_pin_in_start_of_vram(struct vmw_private *vmw_priv,
888 struct vmw_buffer_object *bo,
889 bool interruptible);
890extern int vmw_bo_unpin(struct vmw_private *vmw_priv,
891 struct vmw_buffer_object *bo,
892 bool interruptible);
893extern void vmw_bo_get_guest_ptr(const struct ttm_buffer_object *buf,
894 SVGAGuestPtr *ptr);
895extern void vmw_bo_pin_reserved(struct vmw_buffer_object *bo, bool pin);
896extern void vmw_bo_bo_free(struct ttm_buffer_object *bo);
897extern 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);
901extern 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);
906extern 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));
911extern int vmw_bo_unref_ioctl(struct drm_device *dev, void *data,
912 struct drm_file *file_priv);
913extern int vmw_user_bo_synccpu_ioctl(struct drm_device *dev, void *data,
914 struct drm_file *file_priv);
915extern int vmw_user_bo_lookup(struct drm_file *filp,
916 uint32_t handle,
917 struct vmw_buffer_object **out);
918extern void vmw_bo_fence_single(struct ttm_buffer_object *bo,
919 struct vmw_fence_obj *fence);
920extern void *vmw_bo_map_and_cache(struct vmw_buffer_object *vbo);
921extern void vmw_bo_unmap(struct vmw_buffer_object *vbo);
922extern void vmw_bo_move_notify(struct ttm_buffer_object *bo,
923 struct ttm_resource *mem);
924extern 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 */
931static 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 */
954static 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 */
969static inline void vmw_bo_prio_del(struct vmw_buffer_object *vbo, int prio)
970{
971 if (--vbo->res_prios[prio] == 0)
972 vmw_bo_prio_adjust(vbo);
973}
974
975/**852/**
976 * GEM related functionality - vmwgfx_gem.c853 * GEM related functionality - vmwgfx_gem.c
977 */854 */
@@ -979,10 +856,9 @@ extern int vmw_gem_object_create_with_handle(struct vmw_private *dev_priv, · 1 unmodified line
979 struct drm_file *filp,856 struct drm_file *filp,
980 uint32_t size,857 uint32_t size,
981 uint32_t *handle,858 uint32_t *handle,
982 struct vmw_buffer_object **p_vbo);859 struct vmw_bo **p_vbo);
983extern int vmw_gem_object_create_ioctl(struct drm_device *dev, void *data,860extern int vmw_gem_object_create_ioctl(struct drm_device *dev, void *data,
984 struct drm_file *filp);861 struct drm_file *filp);
985extern void vmw_gem_destroy(struct ttm_buffer_object *bo);
986extern void vmw_debugfs_gem_init(struct vmw_private *vdev);862extern void vmw_debugfs_gem_init(struct vmw_private *vdev);
987 863
988/**864/**
@@ -1055,30 +931,21 @@ vmw_is_cursor_bypass3_enabled(const struct vmw_private *dev_priv) · 66 unmodified lines
1055 return (vmw_fifo_caps(dev_priv) & SVGA_FIFO_CAP_CURSOR_BYPASS_3) != 0;931 return (vmw_fifo_caps(dev_priv) & SVGA_FIFO_CAP_CURSOR_BYPASS_3) != 0;
1056}932}
1057 933
1058/**
1059 * TTM glue - vmwgfx_ttm_glue.c
1060 */
1061
1062extern int vmw_mmap(struct file *filp, struct vm_area_struct *vma);
1063
1064/**934/**
1065 * TTM buffer object driver - vmwgfx_ttm_buffer.c935 * TTM buffer object driver - vmwgfx_ttm_buffer.c
1066 */936 */
1067 937
1068extern const size_t vmw_tt_size;938extern const size_t vmw_tt_size;
1069extern struct ttm_placement vmw_vram_placement;939extern struct ttm_placement vmw_vram_placement;
1070extern struct ttm_placement vmw_vram_sys_placement;
1071extern struct ttm_placement vmw_vram_gmr_placement;940extern struct ttm_placement vmw_vram_gmr_placement;
1072extern struct ttm_placement vmw_sys_placement;941extern struct ttm_placement vmw_sys_placement;
1073extern struct ttm_placement vmw_srf_placement;
1074extern struct ttm_placement vmw_mob_placement;
1075extern struct ttm_placement vmw_nonfixed_placement;
1076extern struct ttm_device_funcs vmw_bo_driver;942extern struct ttm_device_funcs vmw_bo_driver;
1077extern const struct vmw_sg_table *943extern const struct vmw_sg_table *
1078vmw_bo_sg_table(struct ttm_buffer_object *bo);944vmw_bo_sg_table(struct ttm_buffer_object *bo);
1079extern int vmw_bo_create_and_populate(struct vmw_private *dev_priv,945int vmw_bo_create_and_populate(struct vmw_private *dev_priv,
1080 unsigned long bo_size,946 size_t bo_size,
1081 struct ttm_buffer_object **bo_p);947 u32 domain,
948 struct vmw_bo **bo_p);
1082 949
1083extern void vmw_piter_start(struct vmw_piter *viter,950extern void vmw_piter_start(struct vmw_piter *viter,
1084 const struct vmw_sg_table *vsgt,951 const struct vmw_sg_table *vsgt,
@@ -1297,8 +1164,8 @@ vmw_context_binding_state(struct vmw_resource *ctx); · 212 unmodified lines
1297extern void vmw_dx_context_scrub_cotables(struct vmw_resource *ctx,1164extern void vmw_dx_context_scrub_cotables(struct vmw_resource *ctx,
1298 bool readback);1165 bool readback);
1299extern int vmw_context_bind_dx_query(struct vmw_resource *ctx_res,1166extern int vmw_context_bind_dx_query(struct vmw_resource *ctx_res,
1300 struct vmw_buffer_object *mob);1167 struct vmw_bo *mob);
1301extern struct vmw_buffer_object *1168extern struct vmw_bo *
1302vmw_context_get_dx_query_mob(struct vmw_resource *ctx_res);1169vmw_context_get_dx_query_mob(struct vmw_resource *ctx_res);
1303 1170
1304 1171
@@ -1523,12 +1390,12 @@ int vmw_mksstat_remove_all(struct vmw_private *dev_priv); · 218 unmodified lines
1523 DRM_DEBUG_DRIVER(fmt, ##__VA_ARGS__)1390 DRM_DEBUG_DRIVER(fmt, ##__VA_ARGS__)
1524 1391
1525/* Resource dirtying - vmwgfx_page_dirty.c */1392/* Resource dirtying - vmwgfx_page_dirty.c */
1526void vmw_bo_dirty_scan(struct vmw_buffer_object *vbo);1393void vmw_bo_dirty_scan(struct vmw_bo *vbo);
1527int vmw_bo_dirty_add(struct vmw_buffer_object *vbo);1394int vmw_bo_dirty_add(struct vmw_bo *vbo);
1528void vmw_bo_dirty_transfer_to_res(struct vmw_resource *res);1395void vmw_bo_dirty_transfer_to_res(struct vmw_resource *res);
1529void vmw_bo_dirty_clear_res(struct vmw_resource *res);1396void vmw_bo_dirty_clear_res(struct vmw_resource *res);
1530void vmw_bo_dirty_release(struct vmw_buffer_object *vbo);1397void vmw_bo_dirty_release(struct vmw_bo *vbo);
1531void vmw_bo_dirty_unmap(struct vmw_buffer_object *vbo,1398void vmw_bo_dirty_unmap(struct vmw_bo *vbo,
1532 pgoff_t start, pgoff_t end);1399 pgoff_t start, pgoff_t end);
1533vm_fault_t vmw_bo_vm_fault(struct vm_fault *vmf);1400vm_fault_t vmw_bo_vm_fault(struct vm_fault *vmf);
1534vm_fault_t vmw_bo_vm_mkwrite(struct vm_fault *vmf);1401vm_fault_t vmw_bo_vm_mkwrite(struct vm_fault *vmf);
@@ -1561,22 +1428,6 @@ static inline struct vmw_surface *vmw_surface_reference(struct vmw_surface *srf) · 26 unmodified lines
1561 return srf;1428 return srf;
1562}1429}
1563 1430
1564static 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
1573static inline struct vmw_buffer_object *
1574vmw_bo_reference(struct vmw_buffer_object *buf)
1575{
1576 ttm_bo_get(&buf->base);
1577 return buf;
1578}
1579
1580static inline void vmw_fifo_resource_inc(struct vmw_private *dev_priv)1431static inline void vmw_fifo_resource_inc(struct vmw_private *dev_priv)
1581{1432{
1582 atomic_inc(&dev_priv->num_fifo_resources);1433 atomic_inc(&dev_priv->num_fifo_resources);
drivers/gpu/drm/vmwgfx/vmwgfx_execbuf.c+58−47
@@ -1,7 +1,7 @@
1// SPDX-License-Identifier: GPL-2.0 OR MIT1// SPDX-License-Identifier: GPL-2.0 OR MIT
2/**************************************************************************2/**************************************************************************
3 *3 *
4 * Copyright 2009 - 2022 VMware, Inc., Palo Alto, CA., USA4 * Copyright 2009 - 2023 VMware, Inc., Palo Alto, CA., USA
5 *5 *
6 * Permission is hereby granted, free of charge, to any person obtaining a6 * Permission is hereby granted, free of charge, to any person obtaining a
7 * copy of this software and associated documentation files (the7 * copy of this software and associated documentation files (the
@@ -24,17 +24,17 @@ · 16 unmodified lines
24 * USE OR OTHER DEALINGS IN THE SOFTWARE.24 * USE OR OTHER DEALINGS IN THE SOFTWARE.
25 *25 *
26 **************************************************************************/26 **************************************************************************/
27#include <linux/sync_file.h>27#include "vmwgfx_binding.h"
28#include <linux/hashtable.h>28#include "vmwgfx_bo.h"
29
30#include "vmwgfx_drv.h"29#include "vmwgfx_drv.h"
31#include "vmwgfx_reg.h"30#include "vmwgfx_mksstat.h"
31#include "vmwgfx_so.h"
32
32#include <drm/ttm/ttm_bo.h>33#include <drm/ttm/ttm_bo.h>
33#include <drm/ttm/ttm_placement.h>34#include <drm/ttm/ttm_placement.h>
34#include "vmwgfx_so.h"
35#include "vmwgfx_binding.h"
36#include "vmwgfx_mksstat.h"
37 35
36#include <linux/sync_file.h>
37#include <linux/hashtable.h>
38 38
39/*39/*
40 * Helper macro to get dx_ctx_node if available otherwise print an error40 * Helper macro to get dx_ctx_node if available otherwise print an error
@@ -65,7 +65,7 @@ · 24 unmodified lines
65 */65 */
66struct vmw_relocation {66struct vmw_relocation {
67 struct list_head head;67 struct list_head head;
68 struct vmw_buffer_object *vbo;68 struct vmw_bo *vbo;
69 union {69 union {
70 SVGAMobId *mob_loc;70 SVGAMobId *mob_loc;
71 SVGAGuestPtr *location;71 SVGAGuestPtr *location;
@@ -149,7 +149,7 @@ static int vmw_resource_context_res_add(struct vmw_private *dev_priv, · 77 unmodified lines
149static int vmw_translate_mob_ptr(struct vmw_private *dev_priv,149static int vmw_translate_mob_ptr(struct vmw_private *dev_priv,
150 struct vmw_sw_context *sw_context,150 struct vmw_sw_context *sw_context,
151 SVGAMobId *id,151 SVGAMobId *id,
152 struct vmw_buffer_object **vmw_bo_p);152 struct vmw_bo **vmw_bo_p);
153/**153/**
154 * vmw_ptr_diff - Compute the offset from a to b in bytes154 * vmw_ptr_diff - Compute the offset from a to b in bytes
155 *155 *
@@ -475,12 +475,16 @@ static int vmw_resource_context_res_add(struct vmw_private *dev_priv, · 319 unmodified lines
475 475
476 if (has_sm4_context(dev_priv) &&476 if (has_sm4_context(dev_priv) &&
477 vmw_res_type(ctx) == vmw_res_dx_context) {477 vmw_res_type(ctx) == vmw_res_dx_context) {
478 struct vmw_buffer_object *dx_query_mob;478 struct vmw_bo *dx_query_mob;
479 479
480 dx_query_mob = vmw_context_get_dx_query_mob(ctx);480 dx_query_mob = vmw_context_get_dx_query_mob(ctx);
481 if (dx_query_mob)481 if (dx_query_mob) {
482 vmw_bo_placement_set(dx_query_mob,
483 VMW_BO_DOMAIN_MOB,
484 VMW_BO_DOMAIN_MOB);
482 ret = vmw_validation_add_bo(sw_context->ctx,485 ret = vmw_validation_add_bo(sw_context->ctx,
483 dx_query_mob, true, false);486 dx_query_mob);
487 }
484 }488 }
485 489
486 mutex_unlock(&dev_priv->binding_mutex);490 mutex_unlock(&dev_priv->binding_mutex);
@@ -596,7 +600,7 @@ static int vmw_resources_reserve(struct vmw_sw_context *sw_context) · 109 unmodified lines
596 return ret;600 return ret;
597 601
598 if (sw_context->dx_query_mob) {602 if (sw_context->dx_query_mob) {
599 struct vmw_buffer_object *expected_dx_query_mob;603 struct vmw_bo *expected_dx_query_mob;
600 604
601 expected_dx_query_mob =605 expected_dx_query_mob =
602 vmw_context_get_dx_query_mob(sw_context->dx_query_ctx);606 vmw_context_get_dx_query_mob(sw_context->dx_query_ctx);
@@ -703,7 +707,7 @@ res_check_done: · 100 unmodified lines
703static int vmw_rebind_all_dx_query(struct vmw_resource *ctx_res)707static int vmw_rebind_all_dx_query(struct vmw_resource *ctx_res)
704{708{
705 struct vmw_private *dev_priv = ctx_res->dev_priv;709 struct vmw_private *dev_priv = ctx_res->dev_priv;
706 struct vmw_buffer_object *dx_query_mob;710 struct vmw_bo *dx_query_mob;
707 VMW_DECLARE_CMD_VAR(*cmd, SVGA3dCmdDXBindAllQuery);711 VMW_DECLARE_CMD_VAR(*cmd, SVGA3dCmdDXBindAllQuery);
708 712
709 dx_query_mob = vmw_context_get_dx_query_mob(ctx_res);713 dx_query_mob = vmw_context_get_dx_query_mob(ctx_res);
@@ -718,7 +722,7 @@ static int vmw_rebind_all_dx_query(struct vmw_resource *ctx_res) · 8 unmodified lines
718 cmd->header.id = SVGA_3D_CMD_DX_BIND_ALL_QUERY;722 cmd->header.id = SVGA_3D_CMD_DX_BIND_ALL_QUERY;
719 cmd->header.size = sizeof(cmd->body);723 cmd->header.size = sizeof(cmd->body);
720 cmd->body.cid = ctx_res->id;724 cmd->body.cid = ctx_res->id;
721 cmd->body.mobid = dx_query_mob->base.resource->start;725 cmd->body.mobid = dx_query_mob->tbo.resource->start;
722 vmw_cmd_commit(dev_priv, sizeof(*cmd));726 vmw_cmd_commit(dev_priv, sizeof(*cmd));
723 727
724 vmw_context_bind_dx_query(ctx_res, dx_query_mob);728 vmw_context_bind_dx_query(ctx_res, dx_query_mob);
@@ -1017,7 +1021,7 @@ static int vmw_cmd_present_check(struct vmw_private *dev_priv, · 292 unmodified lines
1017 * after successful submission of the current command batch.1021 * after successful submission of the current command batch.
1018 */1022 */
1019static int vmw_query_bo_switch_prepare(struct vmw_private *dev_priv,1023static int vmw_query_bo_switch_prepare(struct vmw_private *dev_priv,
1020 struct vmw_buffer_object *new_query_bo,1024 struct vmw_bo *new_query_bo,
1021 struct vmw_sw_context *sw_context)1025 struct vmw_sw_context *sw_context)
1022{1026{
1023 struct vmw_res_cache_entry *ctx_entry =1027 struct vmw_res_cache_entry *ctx_entry =
@@ -1029,24 +1033,24 @@ static int vmw_query_bo_switch_prepare(struct vmw_private *dev_priv, · 5 unmodified lines
1029 1033
1030 if (unlikely(new_query_bo != sw_context->cur_query_bo)) {1034 if (unlikely(new_query_bo != sw_context->cur_query_bo)) {
1031 1035
1032 if (unlikely(PFN_UP(new_query_bo->base.resource->size) > 4)) {1036 if (unlikely(PFN_UP(new_query_bo->tbo.resource->size) > 4)) {
1033 VMW_DEBUG_USER("Query buffer too large.\n");1037 VMW_DEBUG_USER("Query buffer too large.\n");
1034 return -EINVAL;1038 return -EINVAL;
1035 }1039 }
1036 1040
1037 if (unlikely(sw_context->cur_query_bo != NULL)) {1041 if (unlikely(sw_context->cur_query_bo != NULL)) {
1038 sw_context->needs_post_query_barrier = true;1042 sw_context->needs_post_query_barrier = true;
1043 vmw_bo_placement_set_default_accelerated(sw_context->cur_query_bo);
1039 ret = vmw_validation_add_bo(sw_context->ctx,1044 ret = vmw_validation_add_bo(sw_context->ctx,
1040 sw_context->cur_query_bo,1045 sw_context->cur_query_bo);
1041 dev_priv->has_mob, false);
1042 if (unlikely(ret != 0))1046 if (unlikely(ret != 0))
1043 return ret;1047 return ret;
1044 }1048 }
1045 sw_context->cur_query_bo = new_query_bo;1049 sw_context->cur_query_bo = new_query_bo;
1046 1050
1051 vmw_bo_placement_set_default_accelerated(dev_priv->dummy_query_bo);
1047 ret = vmw_validation_add_bo(sw_context->ctx,1052 ret = vmw_validation_add_bo(sw_context->ctx,
1048 dev_priv->dummy_query_bo,1053 dev_priv->dummy_query_bo);
1049 dev_priv->has_mob, false);
1050 if (unlikely(ret != 0))1054 if (unlikely(ret != 0))
1051 return ret;1055 return ret;
1052 }1056 }
@@ -1145,9 +1149,9 @@ static void vmw_query_bo_switch_commit(struct vmw_private *dev_priv, · 92 unmodified lines
1145static int vmw_translate_mob_ptr(struct vmw_private *dev_priv,1149static int vmw_translate_mob_ptr(struct vmw_private *dev_priv,
1146 struct vmw_sw_context *sw_context,1150 struct vmw_sw_context *sw_context,
1147 SVGAMobId *id,1151 SVGAMobId *id,
1148 struct vmw_buffer_object **vmw_bo_p)1152 struct vmw_bo **vmw_bo_p)
1149{1153{
1150 struct vmw_buffer_object *vmw_bo;1154 struct vmw_bo *vmw_bo;
1151 uint32_t handle = *id;1155 uint32_t handle = *id;
1152 struct vmw_relocation *reloc;1156 struct vmw_relocation *reloc;
1153 int ret;1157 int ret;
@@ -1158,9 +1162,10 @@ static int vmw_translate_mob_ptr(struct vmw_private *dev_priv, · 4 unmodified lines
1158 drm_dbg(&dev_priv->drm, "Could not find or use MOB buffer.\n");1162 drm_dbg(&dev_priv->drm, "Could not find or use MOB buffer.\n");
1159 return PTR_ERR(vmw_bo);1163 return PTR_ERR(vmw_bo);
1160 }1164 }
1161 ret = vmw_validation_add_bo(sw_context->ctx, vmw_bo, true, false);1165 vmw_bo_placement_set(vmw_bo, VMW_BO_DOMAIN_MOB, VMW_BO_DOMAIN_MOB);
1162 ttm_bo_put(&vmw_bo->base);1166 ret = vmw_validation_add_bo(sw_context->ctx, vmw_bo);
1163 drm_gem_object_put(&vmw_bo->base.base);1167 ttm_bo_put(&vmw_bo->tbo);
1168 drm_gem_object_put(&vmw_bo->tbo.base);
1164 if (unlikely(ret != 0))1169 if (unlikely(ret != 0))
1165 return ret;1170 return ret;
1166 1171
@@ -1200,9 +1205,9 @@ static int vmw_translate_mob_ptr(struct vmw_private *dev_priv, · 33 unmodified lines
1200static int vmw_translate_guest_ptr(struct vmw_private *dev_priv,1205static int vmw_translate_guest_ptr(struct vmw_private *dev_priv,
1201 struct vmw_sw_context *sw_context,1206 struct vmw_sw_context *sw_context,
1202 SVGAGuestPtr *ptr,1207 SVGAGuestPtr *ptr,
1203 struct vmw_buffer_object **vmw_bo_p)1208 struct vmw_bo **vmw_bo_p)
1204{1209{
1205 struct vmw_buffer_object *vmw_bo;1210 struct vmw_bo *vmw_bo;
1206 uint32_t handle = ptr->gmrId;1211 uint32_t handle = ptr->gmrId;
1207 struct vmw_relocation *reloc;1212 struct vmw_relocation *reloc;
1208 int ret;1213 int ret;
@@ -1213,9 +1218,11 @@ static int vmw_translate_guest_ptr(struct vmw_private *dev_priv, · 4 unmodified lines
1213 drm_dbg(&dev_priv->drm, "Could not find or use GMR region.\n");1218 drm_dbg(&dev_priv->drm, "Could not find or use GMR region.\n");
1214 return PTR_ERR(vmw_bo);1219 return PTR_ERR(vmw_bo);
1215 }1220 }
1216 ret = vmw_validation_add_bo(sw_context->ctx, vmw_bo, false, false);1221 vmw_bo_placement_set(vmw_bo, VMW_BO_DOMAIN_GMR | VMW_BO_DOMAIN_VRAM,
1217 ttm_bo_put(&vmw_bo->base);1222 VMW_BO_DOMAIN_GMR | VMW_BO_DOMAIN_VRAM);
1218 drm_gem_object_put(&vmw_bo->base.base);1223 ret = vmw_validation_add_bo(sw_context->ctx, vmw_bo);
1224 ttm_bo_put(&vmw_bo->tbo);
1225 drm_gem_object_put(&vmw_bo->tbo.base);
1219 if (unlikely(ret != 0))1226 if (unlikely(ret != 0))
1220 return ret;1227 return ret;
1221 1228
@@ -1280,7 +1287,7 @@ static int vmw_cmd_dx_bind_query(struct vmw_private *dev_priv, · 58 unmodified lines
1280 SVGA3dCmdHeader *header)1287 SVGA3dCmdHeader *header)
1281{1288{
1282 VMW_DECLARE_CMD_VAR(*cmd, SVGA3dCmdDXBindQuery);1289 VMW_DECLARE_CMD_VAR(*cmd, SVGA3dCmdDXBindQuery);
1283 struct vmw_buffer_object *vmw_bo;1290 struct vmw_bo *vmw_bo;
1284 int ret;1291 int ret;
1285 1292
1286 cmd = container_of(header, typeof(*cmd), header);1293 cmd = container_of(header, typeof(*cmd), header);
@@ -1363,7 +1370,7 @@ static int vmw_cmd_end_gb_query(struct vmw_private *dev_priv, · 76 unmodified lines
1363 struct vmw_sw_context *sw_context,1370 struct vmw_sw_context *sw_context,
1364 SVGA3dCmdHeader *header)1371 SVGA3dCmdHeader *header)
1365{1372{
1366 struct vmw_buffer_object *vmw_bo;1373 struct vmw_bo *vmw_bo;
1367 VMW_DECLARE_CMD_VAR(*cmd, SVGA3dCmdEndGBQuery);1374 VMW_DECLARE_CMD_VAR(*cmd, SVGA3dCmdEndGBQuery);
1368 int ret;1375 int ret;
1369 1376
@@ -1393,7 +1400,7 @@ static int vmw_cmd_end_query(struct vmw_private *dev_priv, · 23 unmodified lines
1393 struct vmw_sw_context *sw_context,1400 struct vmw_sw_context *sw_context,
1394 SVGA3dCmdHeader *header)1401 SVGA3dCmdHeader *header)
1395{1402{
1396 struct vmw_buffer_object *vmw_bo;1403 struct vmw_bo *vmw_bo;
1397 VMW_DECLARE_CMD_VAR(*cmd, SVGA3dCmdEndQuery);1404 VMW_DECLARE_CMD_VAR(*cmd, SVGA3dCmdEndQuery);
1398 int ret;1405 int ret;
1399 1406
@@ -1439,7 +1446,7 @@ static int vmw_cmd_wait_gb_query(struct vmw_private *dev_priv, · 39 unmodified lines
1439 struct vmw_sw_context *sw_context,1446 struct vmw_sw_context *sw_context,
1440 SVGA3dCmdHeader *header)1447 SVGA3dCmdHeader *header)
1441{1448{
1442 struct vmw_buffer_object *vmw_bo;1449 struct vmw_bo *vmw_bo;
1443 VMW_DECLARE_CMD_VAR(*cmd, SVGA3dCmdWaitForGBQuery);1450 VMW_DECLARE_CMD_VAR(*cmd, SVGA3dCmdWaitForGBQuery);
1444 int ret;1451 int ret;
1445 1452
@@ -1467,7 +1474,7 @@ static int vmw_cmd_wait_query(struct vmw_private *dev_priv, · 21 unmodified lines
1467 struct vmw_sw_context *sw_context,1474 struct vmw_sw_context *sw_context,
1468 SVGA3dCmdHeader *header)1475 SVGA3dCmdHeader *header)
1469{1476{
1470 struct vmw_buffer_object *vmw_bo;1477 struct vmw_bo *vmw_bo;
1471 VMW_DECLARE_CMD_VAR(*cmd, SVGA3dCmdWaitForQuery);1478 VMW_DECLARE_CMD_VAR(*cmd, SVGA3dCmdWaitForQuery);
1472 int ret;1479 int ret;
1473 1480
@@ -1504,7 +1511,7 @@ static int vmw_cmd_dma(struct vmw_private *dev_priv, · 30 unmodified lines
1504 struct vmw_sw_context *sw_context,1511 struct vmw_sw_context *sw_context,
1505 SVGA3dCmdHeader *header)1512 SVGA3dCmdHeader *header)
1506{1513{
1507 struct vmw_buffer_object *vmw_bo = NULL;1514 struct vmw_bo *vmw_bo = NULL;
1508 struct vmw_surface *srf = NULL;1515 struct vmw_surface *srf = NULL;
1509 VMW_DECLARE_CMD_VAR(*cmd, SVGA3dCmdSurfaceDMA);1516 VMW_DECLARE_CMD_VAR(*cmd, SVGA3dCmdSurfaceDMA);
1510 int ret;1517 int ret;
@@ -1528,7 +1535,7 @@ static int vmw_cmd_dma(struct vmw_private *dev_priv, · 17 unmodified lines
1528 return ret;1535 return ret;
1529 1536
1530 /* Make sure DMA doesn't cross BO boundaries. */1537 /* Make sure DMA doesn't cross BO boundaries. */
1531 bo_size = vmw_bo->base.base.size;1538 bo_size = vmw_bo->tbo.base.size;
1532 if (unlikely(cmd->body.guest.ptr.offset > bo_size)) {1539 if (unlikely(cmd->body.guest.ptr.offset > bo_size)) {
1533 VMW_DEBUG_USER("Invalid DMA offset.\n");1540 VMW_DEBUG_USER("Invalid DMA offset.\n");
1534 return -EINVAL;1541 return -EINVAL;
@@ -1551,7 +1558,7 @@ static int vmw_cmd_dma(struct vmw_private *dev_priv, · 16 unmodified lines
1551 1558
1552 srf = vmw_res_to_srf(sw_context->res_cache[vmw_res_surface].res);1559 srf = vmw_res_to_srf(sw_context->res_cache[vmw_res_surface].res);
1553 1560
1554 vmw_kms_cursor_snoop(srf, sw_context->fp->tfile, &vmw_bo->base, header);1561 vmw_kms_cursor_snoop(srf, sw_context->fp->tfile, &vmw_bo->tbo, header);
1555 1562
1556 return 0;1563 return 0;
1557}1564}
@@ -1670,7 +1677,7 @@ static int vmw_cmd_check_define_gmrfb(struct vmw_private *dev_priv, · 112 unmodified lines
1670 struct vmw_sw_context *sw_context,1677 struct vmw_sw_context *sw_context,
1671 void *buf)1678 void *buf)
1672{1679{
1673 struct vmw_buffer_object *vmw_bo;1680 struct vmw_bo *vmw_bo;
1674 1681
1675 struct {1682 struct {
1676 uint32_t header;1683 uint32_t header;
@@ -1701,7 +1708,7 @@ static int vmw_cmd_res_switch_backup(struct vmw_private *dev_priv, · 24 unmodified lines
1701 struct vmw_resource *res, uint32_t *buf_id,1708 struct vmw_resource *res, uint32_t *buf_id,
1702 unsigned long backup_offset)1709 unsigned long backup_offset)
1703{1710{
1704 struct vmw_buffer_object *vbo;1711 struct vmw_bo *vbo;
1705 void *info;1712 void *info;
1706 int ret;1713 int ret;
1707 1714
@@ -3754,7 +3761,7 @@ static void vmw_apply_relocations(struct vmw_sw_context *sw_context) · 2046 unmodified lines
3754 struct ttm_buffer_object *bo;3761 struct ttm_buffer_object *bo;
3755 3762
3756 list_for_each_entry(reloc, &sw_context->bo_relocations, head) {3763 list_for_each_entry(reloc, &sw_context->bo_relocations, head) {
3757 bo = &reloc->vbo->base;3764 bo = &reloc->vbo->tbo;
3758 switch (bo->resource->mem_type) {3765 switch (bo->resource->mem_type) {
3759 case TTM_PL_VRAM:3766 case TTM_PL_VRAM:
3760 reloc->location->offset += bo->resource->start << PAGE_SHIFT;3767 reloc->location->offset += bo->resource->start << PAGE_SHIFT;
@@ -4364,13 +4371,17 @@ void __vmw_execbuf_release_pinned_bo(struct vmw_private *dev_priv, · 603 unmodified lines
4364 if (dev_priv->pinned_bo == NULL)4371 if (dev_priv->pinned_bo == NULL)
4365 goto out_unlock;4372 goto out_unlock;
4366 4373
4367 ret = vmw_validation_add_bo(&val_ctx, dev_priv->pinned_bo, false,4374 vmw_bo_placement_set(dev_priv->pinned_bo,
4368 false);4375 VMW_BO_DOMAIN_GMR | VMW_BO_DOMAIN_VRAM,
4376 VMW_BO_DOMAIN_GMR | VMW_BO_DOMAIN_VRAM);
4377 ret = vmw_validation_add_bo(&val_ctx, dev_priv->pinned_bo);
4369 if (ret)4378 if (ret)
4370 goto out_no_reserve;4379 goto out_no_reserve;
4371 4380
4372 ret = vmw_validation_add_bo(&val_ctx, dev_priv->dummy_query_bo, false,4381 vmw_bo_placement_set(dev_priv->dummy_query_bo,
4373 false);4382 VMW_BO_DOMAIN_GMR | VMW_BO_DOMAIN_VRAM,
4383 VMW_BO_DOMAIN_GMR | VMW_BO_DOMAIN_VRAM);
4384 ret = vmw_validation_add_bo(&val_ctx, dev_priv->dummy_query_bo);
4374 if (ret)4385 if (ret)
4375 goto out_no_reserve;4386 goto out_no_reserve;
4376 4387
drivers/gpu/drm/vmwgfx/vmwgfx_fence.c+1−1
@@ -1,7 +1,7 @@
1// SPDX-License-Identifier: GPL-2.0 OR MIT1// SPDX-License-Identifier: GPL-2.0 OR MIT
2/**************************************************************************2/**************************************************************************
3 *3 *
4 * Copyright 2011-2014 VMware, Inc., Palo Alto, CA., USA4 * Copyright 2011-2023 VMware, Inc., Palo Alto, CA., USA
5 *5 *
6 * Permission is hereby granted, free of charge, to any person obtaining a6 * Permission is hereby granted, free of charge, to any person obtaining a
7 * copy of this software and associated documentation files (the7 * copy of this software and associated documentation files (the
drivers/gpu/drm/vmwgfx/vmwgfx_gem.c+36−55
@@ -1,6 +1,6 @@
1/* SPDX-License-Identifier: GPL-2.0 OR MIT */1/* SPDX-License-Identifier: GPL-2.0 OR MIT */
2/*2/*
3 * Copyright 2021 VMware, Inc.3 * Copyright 2021-2023 VMware, Inc.
4 *4 *
5 * Permission is hereby granted, free of charge, to any person5 * Permission is hereby granted, free of charge, to any person
6 * obtaining a copy of this software and associated documentation6 * obtaining a copy of this software and associated documentation
@@ -24,31 +24,17 @@ · 17 unmodified lines
24 *24 *
25 */25 */
26 26
27#include "vmwgfx_bo.h"
27#include "vmwgfx_drv.h"28#include "vmwgfx_drv.h"
28 29
29#include "drm/drm_prime.h"30#include "drm/drm_prime.h"
30#include "drm/drm_gem_ttm_helper.h"31#include "drm/drm_gem_ttm_helper.h"
31 32
32/**
33 * vmw_buffer_object - Convert a struct ttm_buffer_object to a struct
34 * vmw_buffer_object.
35 *
36 * @bo: Pointer to the TTM buffer object.
37 * Return: Pointer to the struct vmw_buffer_object embedding the
38 * TTM buffer object.
39 */
40static struct vmw_buffer_object *
41vmw_buffer_object(struct ttm_buffer_object *bo)
42{
43 return container_of(bo, struct vmw_buffer_object, base);
44}
45
46static void vmw_gem_object_free(struct drm_gem_object *gobj)33static void vmw_gem_object_free(struct drm_gem_object *gobj)
47{34{
48 struct ttm_buffer_object *bo = drm_gem_ttm_of_gem(gobj);35 struct ttm_buffer_object *bo = drm_gem_ttm_of_gem(gobj);
49 if (bo) {36 if (bo)
50 ttm_bo_put(bo);37 ttm_bo_put(bo);
51 }
52}38}
53 39
54static int vmw_gem_object_open(struct drm_gem_object *obj,40static 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
65static int vmw_gem_pin_private(struct drm_gem_object *obj, bool do_pin)51static int vmw_gem_pin_private(struct drm_gem_object *obj, bool do_pin)
66{52{
67 struct ttm_buffer_object *bo = drm_gem_ttm_of_gem(obj);53 struct ttm_buffer_object *bo = drm_gem_ttm_of_gem(obj);
68 struct vmw_buffer_object *vbo = vmw_buffer_object(bo);54 struct vmw_bo *vbo = to_vmw_bo(obj);
69 int ret;55 int ret;
70 56
71 ret = ttm_bo_reserve(bo, false, false, NULL);57 ret = ttm_bo_reserve(bo, false, false, NULL);
@@ -103,6 +89,13 @@ static struct sg_table *vmw_gem_object_get_sg_table(struct drm_gem_object *obj) · 31 unmodified lines
103 return drm_prime_pages_to_sg(obj->dev, vmw_tt->dma_ttm.pages, vmw_tt->dma_ttm.num_pages);89 return drm_prime_pages_to_sg(obj->dev, vmw_tt->dma_ttm.pages, vmw_tt->dma_ttm.num_pages);
104}90}
105 91
92static 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
107static const struct drm_gem_object_funcs vmw_gem_object_funcs = {100static const struct drm_gem_object_funcs vmw_gem_object_funcs = {
108 .free = vmw_gem_object_free,101 .free = vmw_gem_object_free,
@@ -115,43 +108,31 @@ static const struct drm_gem_object_funcs vmw_gem_object_funcs = { · 6 unmodified lines
115 .vmap = drm_gem_ttm_vmap,108 .vmap = drm_gem_ttm_vmap,
116 .vunmap = drm_gem_ttm_vunmap,109 .vunmap = drm_gem_ttm_vunmap,
117 .mmap = drm_gem_ttm_mmap,110 .mmap = drm_gem_ttm_mmap,
111 .vm_ops = &vmw_vm_ops,
118};112};
119 113
120/**
121 * vmw_gem_destroy - vmw buffer object destructor
122 *
123 * @bo: Pointer to the embedded struct ttm_buffer_object
124 */
125void 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
136int vmw_gem_object_create_with_handle(struct vmw_private *dev_priv,114int vmw_gem_object_create_with_handle(struct vmw_private *dev_priv,
137 struct drm_file *filp,115 struct drm_file *filp,
138 uint32_t size,116 uint32_t size,
139 uint32_t *handle,117 uint32_t *handle,
140 struct vmw_buffer_object **p_vbo)118 struct vmw_bo **p_vbo)
141{119{
142 int ret;120 int ret;
143 121 struct vmw_bo_params params = {
144 ret = vmw_bo_create(dev_priv, size,122 .domain = (dev_priv->has_mob) ? VMW_BO_DOMAIN_SYS : VMW_BO_DOMAIN_VRAM,
145 (dev_priv->has_mob) ?123 .busy_domain = VMW_BO_DOMAIN_SYS,
146 &vmw_sys_placement :124 .bo_type = ttm_bo_type_device,
147 &vmw_vram_sys_placement,125 .size = size,
148 true, false, &vmw_gem_destroy, p_vbo);126 .pin = false
127 };
128
129 ret = vmw_bo_create(dev_priv, &params, p_vbo);
149 if (ret != 0)130 if (ret != 0)
150 goto out_no_bo;131 goto out_no_bo;
151 132
152 (*p_vbo)->base.base.funcs = &vmw_gem_object_funcs;133 (*p_vbo)->tbo.base.funcs = &vmw_gem_object_funcs;
153 134
154 ret = drm_gem_handle_create(filp, &(*p_vbo)->base.base, handle);135 ret = drm_gem_handle_create(filp, &(*p_vbo)->tbo.base, handle);
155out_no_bo:136out_no_bo:
156 return ret;137 return ret;
157}138}
@@ -165,7 +146,7 @@ int vmw_gem_object_create_ioctl(struct drm_device *dev, void *data, · 7 unmodified lines
165 (union drm_vmw_alloc_dmabuf_arg *)data;146 (union drm_vmw_alloc_dmabuf_arg *)data;
166 struct drm_vmw_alloc_dmabuf_req *req = &arg->req;147 struct drm_vmw_alloc_dmabuf_req *req = &arg->req;
167 struct drm_vmw_dmabuf_rep *rep = &arg->rep;148 struct drm_vmw_dmabuf_rep *rep = &arg->rep;
168 struct vmw_buffer_object *vbo;149 struct vmw_bo *vbo;
169 uint32_t handle;150 uint32_t handle;
170 int ret;151 int ret;
171 152
@@ -175,23 +156,23 @@ int vmw_gem_object_create_ioctl(struct drm_device *dev, void *data, · 3 unmodified lines
175 goto out_no_bo;156 goto out_no_bo;
176 157
177 rep->handle = handle;158 rep->handle = handle;
178 rep->map_handle = drm_vma_node_offset_addr(&vbo->base.base.vma_node);159 rep->map_handle = drm_vma_node_offset_addr(&vbo->tbo.base.vma_node);
179 rep->cur_gmr_id = handle;160 rep->cur_gmr_id = handle;
180 rep->cur_gmr_offset = 0;161 rep->cur_gmr_offset = 0;
181 /* drop reference from allocate - handle holds it now */162 /* drop reference from allocate - handle holds it now */
182 drm_gem_object_put(&vbo->base.base);163 drm_gem_object_put(&vbo->tbo.base);
183out_no_bo:164out_no_bo:
184 return ret;165 return ret;
185}166}
186 167
187#if defined(CONFIG_DEBUG_FS)168#if defined(CONFIG_DEBUG_FS)
188 169
189static void vmw_bo_print_info(int id, struct vmw_buffer_object *bo, struct seq_file *m)170static void vmw_bo_print_info(int id, struct vmw_bo *bo, struct seq_file *m)
190{171{
191 const char *placement;172 const char *placement;
192 const char *type;173 const char *type;
193 174
194 switch (bo->base.resource->mem_type) {175 switch (bo->tbo.resource->mem_type) {
195 case TTM_PL_SYSTEM:176 case TTM_PL_SYSTEM:
196 placement = " CPU";177 placement = " CPU";
197 break;178 break;
@@ -212,7 +193,7 @@ static void vmw_bo_print_info(int id, struct vmw_buffer_object *bo, struct seq_f · 14 unmodified lines
212 break;193 break;
213 }194 }
214 195
215 switch (bo->base.type) {196 switch (bo->tbo.type) {
216 case ttm_bo_type_device:197 case ttm_bo_type_device:
217 type = "device";198 type = "device";
218 break;199 break;
@@ -228,12 +209,12 @@ static void vmw_bo_print_info(int id, struct vmw_buffer_object *bo, struct seq_f · 9 unmodified lines
228 }209 }
229 210
230 seq_printf(m, "\t\t0x%08x: %12zu bytes %s, type = %s",211 seq_printf(m, "\t\t0x%08x: %12zu bytes %s, type = %s",
231 id, bo->base.base.size, placement, type);212 id, bo->tbo.base.size, placement, type);
232 seq_printf(m, ", priority = %u, pin_count = %u, GEM refs = %d, TTM refs = %d",213 seq_printf(m, ", priority = %u, pin_count = %u, GEM refs = %d, TTM refs = %d",
233 bo->base.priority,214 bo->tbo.priority,
234 bo->base.pin_count,215 bo->tbo.pin_count,
235 kref_read(&bo->base.base.refcount),216 kref_read(&bo->tbo.base.refcount),
236 kref_read(&bo->base.kref));217 kref_read(&bo->tbo.kref));
237 seq_puts(m, "\n");218 seq_puts(m, "\n");
238}219}
239 220
@@ -267,7 +248,7 @@ static int vmw_debugfs_gem_info_show(struct seq_file *m, void *unused) · 27 unmodified lines
267 248
268 spin_lock(&file->table_lock);249 spin_lock(&file->table_lock);
269 idr_for_each_entry(&file->object_idr, gobj, id) {250 idr_for_each_entry(&file->object_idr, gobj, id) {
270 struct vmw_buffer_object *bo = gem_to_vmw_bo(gobj);251 struct vmw_bo *bo = to_vmw_bo(gobj);
271 252
272 vmw_bo_print_info(id, bo, m);253 vmw_bo_print_info(id, bo, m);
273 }254 }
drivers/gpu/drm/vmwgfx/vmwgfx_kms.c+77−155
@@ -1,7 +1,7 @@
1// SPDX-License-Identifier: GPL-2.0 OR MIT1// SPDX-License-Identifier: GPL-2.0 OR MIT
2/**************************************************************************2/**************************************************************************
3 *3 *
4 * Copyright 2009-2022 VMware, Inc., Palo Alto, CA., USA4 * Copyright 2009-2023 VMware, Inc., Palo Alto, CA., USA
5 *5 *
6 * Permission is hereby granted, free of charge, to any person obtaining a6 * Permission is hereby granted, free of charge, to any person obtaining a
7 * copy of this software and associated documentation files (the7 * copy of this software and associated documentation files (the
@@ -24,8 +24,9 @@ · 16 unmodified lines
24 * USE OR OTHER DEALINGS IN THE SOFTWARE.24 * USE OR OTHER DEALINGS IN THE SOFTWARE.
25 *25 *
26 **************************************************************************/26 **************************************************************************/
27
28#include "vmwgfx_kms.h"27#include "vmwgfx_kms.h"
28
29#include "vmwgfx_bo.h"
29#include "vmw_surface_cache.h"30#include "vmw_surface_cache.h"
30 31
31#include <drm/drm_atomic.h>32#include <drm/drm_atomic.h>
@@ -152,9 +153,8 @@ static void vmw_cursor_update_mob(struct vmw_private *dev_priv, · 120 unmodified lines
152 SVGAGBCursorHeader *header;153 SVGAGBCursorHeader *header;
153 SVGAGBAlphaCursorHeader *alpha_header;154 SVGAGBAlphaCursorHeader *alpha_header;
154 const u32 image_size = width * height * sizeof(*image);155 const u32 image_size = width * height * sizeof(*image);
155 bool dummy;
156 156
157 header = ttm_kmap_obj_virtual(&vps->cursor.map, &dummy);157 header = vmw_bo_map_and_cache(vps->cursor.bo);
158 alpha_header = &header->header.alphaHeader;158 alpha_header = &header->header.alphaHeader;
159 159
160 memset(header, 0, sizeof(*header));160 memset(header, 0, sizeof(*header));
@@ -169,7 +169,7 @@ static void vmw_cursor_update_mob(struct vmw_private *dev_priv, · 8 unmodified lines
169 169
170 memcpy(header + 1, image, image_size);170 memcpy(header + 1, image, image_size);
171 vmw_write(dev_priv, SVGA_REG_CURSOR_MOBID,171 vmw_write(dev_priv, SVGA_REG_CURSOR_MOBID,
172 vps->cursor.bo->resource->start);172 vps->cursor.bo->tbo.resource->start);
173}173}
174 174
175 175
@@ -184,13 +184,13 @@ static u32 vmw_du_cursor_mob_size(u32 w, u32 h) · 8 unmodified lines
184 */184 */
185static u32 *vmw_du_cursor_plane_acquire_image(struct vmw_plane_state *vps)185static u32 *vmw_du_cursor_plane_acquire_image(struct vmw_plane_state *vps)
186{186{
187 bool dummy;187 bool is_iomem;
188 if (vps->surf) {188 if (vps->surf) {
189 if (vps->surf_mapped)189 if (vps->surf_mapped)
190 return vmw_bo_map_and_cache(vps->surf->res.backup);190 return vmw_bo_map_and_cache(vps->surf->res.guest_memory_bo);
191 return vps->surf->snooper.image;191 return vps->surf->snooper.image;
192 } else if (vps->bo)192 } else if (vps->bo)
193 return ttm_kmap_obj_virtual(&vps->bo->map, &dummy);193 return ttm_kmap_obj_virtual(&vps->bo->map, &is_iomem);
194 return NULL;194 return NULL;
195}195}
196 196
@@ -222,15 +222,13 @@ static bool vmw_du_cursor_plane_has_changed(struct vmw_plane_state *old_vps, · 25 unmodified lines
222 return changed;222 return changed;
223}223}
224 224
225static void vmw_du_destroy_cursor_mob(struct ttm_buffer_object **bo)225static void vmw_du_destroy_cursor_mob(struct vmw_bo **vbo)
226{226{
227 if (!(*bo))227 if (!(*vbo))
228 return;228 return;
229 229
230 ttm_bo_unpin(*bo);230 ttm_bo_unpin(&(*vbo)->tbo);
231 ttm_bo_put(*bo);231 vmw_bo_unreference(vbo);
232 kfree(*bo);
233 *bo = NULL;
234}232}
235 233
236static void vmw_du_put_cursor_mob(struct vmw_cursor_plane *vcp,234static void vmw_du_put_cursor_mob(struct vmw_cursor_plane *vcp,
@@ -254,8 +252,8 @@ static void vmw_du_put_cursor_mob(struct vmw_cursor_plane *vcp, · 17 unmodified lines
254 252
255 /* Cache is full: See if this mob is bigger than an existing mob. */253 /* Cache is full: See if this mob is bigger than an existing mob. */
256 for (i = 0; i < ARRAY_SIZE(vcp->cursor_mobs); i++) {254 for (i = 0; i < ARRAY_SIZE(vcp->cursor_mobs); i++) {
257 if (vcp->cursor_mobs[i]->base.size <255 if (vcp->cursor_mobs[i]->tbo.base.size <
258 vps->cursor.bo->base.size) {256 vps->cursor.bo->tbo.base.size) {
259 vmw_du_destroy_cursor_mob(&vcp->cursor_mobs[i]);257 vmw_du_destroy_cursor_mob(&vcp->cursor_mobs[i]);
260 vcp->cursor_mobs[i] = vps->cursor.bo;258 vcp->cursor_mobs[i] = vps->cursor.bo;
261 vps->cursor.bo = NULL;259 vps->cursor.bo = NULL;
@@ -288,7 +286,7 @@ static int vmw_du_get_cursor_mob(struct vmw_cursor_plane *vcp, · 26 unmodified lines
288 return -EINVAL;286 return -EINVAL;
289 287
290 if (vps->cursor.bo) {288 if (vps->cursor.bo) {
291 if (vps->cursor.bo->base.size >= size)289 if (vps->cursor.bo->tbo.base.size >= size)
292 return 0;290 return 0;
293 vmw_du_put_cursor_mob(vcp, vps);291 vmw_du_put_cursor_mob(vcp, vps);
294 }292 }
@@ -296,26 +294,27 @@ static int vmw_du_get_cursor_mob(struct vmw_cursor_plane *vcp, · 1 unmodified line
296 /* Look for an unused mob in the cache. */294 /* Look for an unused mob in the cache. */
297 for (i = 0; i < ARRAY_SIZE(vcp->cursor_mobs); i++) {295 for (i = 0; i < ARRAY_SIZE(vcp->cursor_mobs); i++) {
298 if (vcp->cursor_mobs[i] &&296 if (vcp->cursor_mobs[i] &&
299 vcp->cursor_mobs[i]->base.size >= size) {297 vcp->cursor_mobs[i]->tbo.base.size >= size) {
300 vps->cursor.bo = vcp->cursor_mobs[i];298 vps->cursor.bo = vcp->cursor_mobs[i];
301 vcp->cursor_mobs[i] = NULL;299 vcp->cursor_mobs[i] = NULL;
302 return 0;300 return 0;
303 }301 }
304 }302 }
305 /* Create a new mob if we can't find an existing one. */303 /* Create a new mob if we can't find an existing one. */
306 ret = vmw_bo_create_kernel(dev_priv, size, &vmw_mob_placement,304 ret = vmw_bo_create_and_populate(dev_priv, size,
307 &vps->cursor.bo);305 VMW_BO_DOMAIN_MOB,
306 &vps->cursor.bo);
308 307
309 if (ret != 0)308 if (ret != 0)
310 return ret;309 return ret;
311 310
312 /* Fence the mob creation so we are guarateed to have the mob */311 /* Fence the mob creation so we are guarateed to have the mob */
313 ret = ttm_bo_reserve(vps->cursor.bo, false, false, NULL);312 ret = ttm_bo_reserve(&vps->cursor.bo->tbo, false, false, NULL);
314 if (ret != 0)313 if (ret != 0)
315 goto teardown;314 goto teardown;
316 315
317 vmw_bo_fence_single(vps->cursor.bo, NULL);316 vmw_bo_fence_single(&vps->cursor.bo->tbo, NULL);
318 ttm_bo_unreserve(vps->cursor.bo);317 ttm_bo_unreserve(&vps->cursor.bo->tbo);
319 return 0;318 return 0;
320 319
321teardown:320teardown:
@@ -363,7 +362,7 @@ void vmw_kms_cursor_snoop(struct vmw_surface *srf, · 41 unmodified lines
363 SVGA3dCopyBox *box;362 SVGA3dCopyBox *box;
364 unsigned box_count;363 unsigned box_count;
365 void *virtual;364 void *virtual;
366 bool dummy;365 bool is_iomem;
367 struct vmw_dma_cmd {366 struct vmw_dma_cmd {
368 SVGA3dCmdHeader header;367 SVGA3dCmdHeader header;
369 SVGA3dCmdSurfaceDMA dma;368 SVGA3dCmdSurfaceDMA dma;
@@ -423,7 +422,7 @@ void vmw_kms_cursor_snoop(struct vmw_surface *srf, · 53 unmodified lines
423 if (unlikely(ret != 0))422 if (unlikely(ret != 0))
424 goto err_unreserve;423 goto err_unreserve;
425 424
426 virtual = ttm_kmap_obj_virtual(&map, &dummy);425 virtual = ttm_kmap_obj_virtual(&map, &is_iomem);
427 426
428 if (box->w == VMW_CURSOR_SNOOP_WIDTH && cmd->dma.guest.pitch == image_pitch) {427 if (box->w == VMW_CURSOR_SNOOP_WIDTH && cmd->dma.guest.pitch == image_pitch) {
429 memcpy(srf->snooper.image, virtual,428 memcpy(srf->snooper.image, virtual,
@@ -573,39 +572,30 @@ vmw_du_cursor_plane_map_cm(struct vmw_plane_state *vps) · 143 unmodified lines
573{572{
574 int ret;573 int ret;
575 u32 size = vmw_du_cursor_mob_size(vps->base.crtc_w, vps->base.crtc_h);574 u32 size = vmw_du_cursor_mob_size(vps->base.crtc_w, vps->base.crtc_h);
576 struct ttm_buffer_object *bo = vps->cursor.bo;575 struct ttm_buffer_object *bo;
577 576
578 if (!bo)577 if (!vps->cursor.bo)
579 return -EINVAL;578 return -EINVAL;
580 579
580 bo = &vps->cursor.bo->tbo;
581
581 if (bo->base.size < size)582 if (bo->base.size < size)
582 return -EINVAL;583 return -EINVAL;
583 584
584 if (vps->cursor.mapped)585 if (vps->cursor.bo->map.virtual)
585 return 0;586 return 0;
586 587
587 ret = ttm_bo_reserve(bo, false, false, NULL);588 ret = ttm_bo_reserve(bo, false, false, NULL);
588
589 if (unlikely(ret != 0))589 if (unlikely(ret != 0))
590 return -ENOMEM;590 return -ENOMEM;
591 591
592 ret = ttm_bo_kmap(bo, 0, PFN_UP(size), &vps->cursor.map);592 vmw_bo_map_and_cache(vps->cursor.bo);
593
594 /*
595 * We just want to try to get mob bind to finish
596 * so that the first write to SVGA_REG_CURSOR_MOBID
597 * is done with a buffer that the device has already
598 * seen
599 */
600 (void) ttm_bo_wait(bo, false, false);
601 593
602 ttm_bo_unreserve(bo);594 ttm_bo_unreserve(bo);
603 595
604 if (unlikely(ret != 0))596 if (unlikely(ret != 0))
605 return -ENOMEM;597 return -ENOMEM;
606 598
607 vps->cursor.mapped = true;
608
609 return 0;599 return 0;
610}600}
611 601
@@ -622,19 +612,15 @@ static int · 10 unmodified lines
622vmw_du_cursor_plane_unmap_cm(struct vmw_plane_state *vps)612vmw_du_cursor_plane_unmap_cm(struct vmw_plane_state *vps)
623{613{
624 int ret = 0;614 int ret = 0;
625 struct ttm_buffer_object *bo = vps->cursor.bo;615 struct vmw_bo *vbo = vps->cursor.bo;
626
627 if (!vps->cursor.mapped)
628 return 0;
629 616
630 if (!bo)617 if (!vbo || !vbo->map.virtual)
631 return 0;618 return 0;
632 619
633 ret = ttm_bo_reserve(bo, true, false, NULL);620 ret = ttm_bo_reserve(&vbo->tbo, true, false, NULL);
634 if (likely(ret == 0)) {621 if (likely(ret == 0)) {
635 ttm_bo_kunmap(&vps->cursor.map);622 vmw_bo_unmap(vbo);
636 ttm_bo_unreserve(bo);623 ttm_bo_unreserve(&vbo->tbo);
637 vps->cursor.mapped = false;
638 }624 }
639 625
640 return ret;626 return ret;
@@ -657,20 +643,19 @@ vmw_du_cursor_plane_cleanup_fb(struct drm_plane *plane, · 16 unmodified lines
657{643{
658 struct vmw_cursor_plane *vcp = vmw_plane_to_vcp(plane);644 struct vmw_cursor_plane *vcp = vmw_plane_to_vcp(plane);
659 struct vmw_plane_state *vps = vmw_plane_state_to_vps(old_state);645 struct vmw_plane_state *vps = vmw_plane_state_to_vps(old_state);
660 bool dummy;646 bool is_iomem;
661 647
662 if (vps->surf_mapped) {648 if (vps->surf_mapped) {
663 vmw_bo_unmap(vps->surf->res.backup);649 vmw_bo_unmap(vps->surf->res.guest_memory_bo);
664 vps->surf_mapped = false;650 vps->surf_mapped = false;
665 }651 }
666 652
667 if (vps->bo && ttm_kmap_obj_virtual(&vps->bo->map, &dummy)) {653 if (vps->bo && ttm_kmap_obj_virtual(&vps->bo->map, &is_iomem)) {
668 const int ret = ttm_bo_reserve(&vps->bo->base, true, false, NULL);654 const int ret = ttm_bo_reserve(&vps->bo->tbo, true, false, NULL);
669 655
670 if (likely(ret == 0)) {656 if (likely(ret == 0)) {
671 if (atomic_read(&vps->bo->base_mapped_count) == 0)657 ttm_bo_kunmap(&vps->bo->map);
672 ttm_bo_kunmap(&vps->bo->map);658 ttm_bo_unreserve(&vps->bo->tbo);
673 ttm_bo_unreserve(&vps->bo->base);
674 }659 }
675 }660 }
676 661
@@ -736,29 +721,26 @@ vmw_du_cursor_plane_prepare_fb(struct drm_plane *plane, · 59 unmodified lines
736 * reserve the ttm_buffer_object first which721 * reserve the ttm_buffer_object first which
737 * vmw_bo_map_and_cache() omits.722 * vmw_bo_map_and_cache() omits.
738 */723 */
739 ret = ttm_bo_reserve(&vps->bo->base, true, false, NULL);724 ret = ttm_bo_reserve(&vps->bo->tbo, true, false, NULL);
740 725
741 if (unlikely(ret != 0))726 if (unlikely(ret != 0))
742 return -ENOMEM;727 return -ENOMEM;
743 728
744 ret = ttm_bo_kmap(&vps->bo->base, 0, PFN_UP(size), &vps->bo->map);729 ret = ttm_bo_kmap(&vps->bo->tbo, 0, PFN_UP(size), &vps->bo->map);
745
746 if (likely(ret == 0))
747 atomic_inc(&vps->bo->base_mapped_count);
748 730
749 ttm_bo_unreserve(&vps->bo->base);731 ttm_bo_unreserve(&vps->bo->tbo);
750 732
751 if (unlikely(ret != 0))733 if (unlikely(ret != 0))
752 return -ENOMEM;734 return -ENOMEM;
753 } else if (vps->surf && !vps->bo && vps->surf->res.backup) {735 } else if (vps->surf && !vps->bo && vps->surf->res.guest_memory_bo) {
754 736
755 WARN_ON(vps->surf->snooper.image);737 WARN_ON(vps->surf->snooper.image);
756 ret = ttm_bo_reserve(&vps->surf->res.backup->base, true, false,738 ret = ttm_bo_reserve(&vps->surf->res.guest_memory_bo->tbo, true, false,
757 NULL);739 NULL);
758 if (unlikely(ret != 0))740 if (unlikely(ret != 0))
759 return -ENOMEM;741 return -ENOMEM;
760 vmw_bo_map_and_cache(vps->surf->res.backup);742 vmw_bo_map_and_cache(vps->surf->res.guest_memory_bo);
761 ttm_bo_unreserve(&vps->surf->res.backup->base);743 ttm_bo_unreserve(&vps->surf->res.guest_memory_bo->tbo);
762 vps->surf_mapped = true;744 vps->surf_mapped = true;
763 }745 }
764 746
@@ -785,7 +767,6 @@ vmw_du_cursor_plane_atomic_update(struct drm_plane *plane, · 20 unmodified lines
785 struct vmw_plane_state *vps = vmw_plane_state_to_vps(new_state);767 struct vmw_plane_state *vps = vmw_plane_state_to_vps(new_state);
786 struct vmw_plane_state *old_vps = vmw_plane_state_to_vps(old_state);768 struct vmw_plane_state *old_vps = vmw_plane_state_to_vps(old_state);
787 s32 hotspot_x, hotspot_y;769 s32 hotspot_x, hotspot_y;
788 bool dummy;
789 770
790 hotspot_x = du->hotspot_x;771 hotspot_x = du->hotspot_x;
791 hotspot_y = du->hotspot_y;772 hotspot_y = du->hotspot_y;
@@ -827,11 +808,6 @@ vmw_du_cursor_plane_atomic_update(struct drm_plane *plane, · 35 unmodified lines
827 hotspot_x, hotspot_y);808 hotspot_x, hotspot_y);
828 }809 }
829 810
830 if (vps->bo) {
831 if (ttm_kmap_obj_virtual(&vps->bo->map, &dummy))
832 atomic_dec(&vps->bo->base_mapped_count);
833 }
834
835 du->cursor_x = new_state->crtc_x + du->set_gui_x;811 du->cursor_x = new_state->crtc_x + du->set_gui_x;
836 du->cursor_y = new_state->crtc_y + du->set_gui_y;812 du->cursor_y = new_state->crtc_y + du->set_gui_y;
837 813
@@ -935,7 +911,7 @@ int vmw_du_cursor_plane_atomic_check(struct drm_plane *plane, · 97 unmodified lines
935 WARN_ON(!surface);911 WARN_ON(!surface);
936 912
937 if (!surface ||913 if (!surface ||
938 (!surface->snooper.image && !surface->res.backup)) {914 (!surface->snooper.image && !surface->res.guest_memory_bo)) {
939 DRM_ERROR("surface not suitable for cursor\n");915 DRM_ERROR("surface not suitable for cursor\n");
940 return -EINVAL;916 return -EINVAL;
941 }917 }
@@ -1279,9 +1255,9 @@ int vmw_kms_readback(struct vmw_private *dev_priv, · 337 unmodified lines
1279 user_fence_rep, vclips, num_clips,1255 user_fence_rep, vclips, num_clips,
1280 NULL);1256 NULL);
1281 case vmw_du_screen_target:1257 case vmw_du_screen_target:
1282 return vmw_kms_stdu_dma(dev_priv, file_priv, vfb,1258 return vmw_kms_stdu_readback(dev_priv, file_priv, vfb,
1283 user_fence_rep, NULL, vclips, num_clips,1259 user_fence_rep, NULL, vclips, num_clips,
1284 1, false, true, NULL);1260 1, NULL);
1285 default:1261 default:
1286 WARN_ONCE(true,1262 WARN_ONCE(true,
1287 "Readback called with invalid display system.\n");1263 "Readback called with invalid display system.\n");
@@ -1406,7 +1382,7 @@ static int vmw_framebuffer_bo_create_handle(struct drm_framebuffer *fb, · 118 unmodified lines
1406 struct vmw_framebuffer_bo *vfbd =1382 struct vmw_framebuffer_bo *vfbd =
1407 vmw_framebuffer_to_vfbd(fb);1383 vmw_framebuffer_to_vfbd(fb);
1408 1384
1409 return drm_gem_handle_create(file_priv, &vfbd->buffer->base.base, handle);1385 return drm_gem_handle_create(file_priv, &vfbd->buffer->tbo.base, handle);
1410}1386}
1411 1387
1412static void vmw_framebuffer_bo_destroy(struct drm_framebuffer *framebuffer)1388static void vmw_framebuffer_bo_destroy(struct drm_framebuffer *framebuffer)
@@ -1486,69 +1462,6 @@ static const struct drm_framebuffer_funcs vmw_framebuffer_bo_funcs = { · 73 unmodified lines
1486 .dirty = vmw_framebuffer_bo_dirty_ext,1462 .dirty = vmw_framebuffer_bo_dirty_ext,
1487};1463};
1488 1464
1489/*
1490 * Pin the bofer in a location suitable for access by the
1491 * display system.
1492 */
1493static 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
1538static int vmw_framebuffer_unpin(struct vmw_framebuffer *vfb)
1539{
1540 struct vmw_private *dev_priv = vmw_priv(vfb->base.dev);
1541 struct vmw_buffer_object *buf;
1542
1543 buf = vfb->bo ? vmw_framebuffer_to_vfbd(&vfb->base)->buffer :
1544 vmw_framebuffer_to_vfbs(&vfb->base)->surface->res.backup;
1545
1546 if (WARN_ON(!buf))
1547 return 0;
1548
1549 return vmw_bo_unpin(dev_priv, buf, false);
1550}
1551
1552/**1465/**
1553 * vmw_create_bo_proxy - create a proxy surface for the buffer object1466 * 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 */
1567static int vmw_create_bo_proxy(struct drm_device *dev,1480static int vmw_create_bo_proxy(struct drm_device *dev,
1568 const struct drm_mode_fb_cmd2 *mode_cmd,1481 const struct drm_mode_fb_cmd2 *mode_cmd,
1569 struct vmw_buffer_object *bo_mob,1482 struct vmw_bo *bo_mob,
1570 struct vmw_surface **srf_out)1483 struct vmw_surface **srf_out)
1571{1484{
1572 struct vmw_surface_metadata metadata = {0};1485 struct vmw_surface_metadata metadata = {0};
@@ -1618,9 +1531,9 @@ static int vmw_create_bo_proxy(struct drm_device *dev, · 45 unmodified lines
1618 /* Reserve and switch the backing mob. */1531 /* Reserve and switch the backing mob. */
1619 mutex_lock(&res->dev_priv->cmdbuf_mutex);1532 mutex_lock(&res->dev_priv->cmdbuf_mutex);
1620 (void) vmw_resource_reserve(res, false, true);1533 (void) vmw_resource_reserve(res, false, true);
1621 vmw_bo_unreference(&res->backup);1534 vmw_bo_unreference(&res->guest_memory_bo);
1622 res->backup = vmw_bo_reference(bo_mob);1535 res->guest_memory_bo = vmw_bo_reference(bo_mob);
1623 res->backup_offset = 0;1536 res->guest_memory_offset = 0;
1624 vmw_resource_unreserve(res, false, false, false, NULL, 0);1537 vmw_resource_unreserve(res, false, false, false, NULL, 0);
1625 mutex_unlock(&res->dev_priv->cmdbuf_mutex);1538 mutex_unlock(&res->dev_priv->cmdbuf_mutex);
1626 1539
@@ -1630,7 +1543,7 @@ static int vmw_create_bo_proxy(struct drm_device *dev, · 3 unmodified lines
1630 1543
1631 1544
1632static int vmw_kms_new_framebuffer_bo(struct vmw_private *dev_priv,1545static int vmw_kms_new_framebuffer_bo(struct vmw_private *dev_priv,
1633 struct vmw_buffer_object *bo,1546 struct vmw_bo *bo,
1634 struct vmw_framebuffer **out,1547 struct vmw_framebuffer **out,
1635 const struct drm_mode_fb_cmd21548 const struct drm_mode_fb_cmd2
1636 *mode_cmd)1549 *mode_cmd)
@@ -1642,7 +1555,7 @@ static int vmw_kms_new_framebuffer_bo(struct vmw_private *dev_priv, · 5 unmodified lines
1642 int ret;1555 int ret;
1643 1556
1644 requested_size = mode_cmd->height * mode_cmd->pitches[0];1557 requested_size = mode_cmd->height * mode_cmd->pitches[0];
1645 if (unlikely(requested_size > bo->base.base.size)) {1558 if (unlikely(requested_size > bo->tbo.base.size)) {
1646 DRM_ERROR("Screen buffer object size is too small "1559 DRM_ERROR("Screen buffer object size is too small "
1647 "for requested mode.\n");1560 "for requested mode.\n");
1648 return -EINVAL;1561 return -EINVAL;
@@ -1663,7 +1576,7 @@ static int vmw_kms_new_framebuffer_bo(struct vmw_private *dev_priv, · 14 unmodified lines
1663 goto out_err1;1576 goto out_err1;
1664 }1577 }
1665 1578
1666 vfbd->base.base.obj[0] = &bo->base.base;1579 vfbd->base.base.obj[0] = &bo->tbo.base;
1667 drm_helper_mode_fill_fb_struct(dev, &vfbd->base.base, mode_cmd);1580 drm_helper_mode_fill_fb_struct(dev, &vfbd->base.base, mode_cmd);
1668 vfbd->base.bo = true;1581 vfbd->base.bo = true;
1669 vfbd->buffer = vmw_bo_reference(bo);1582 vfbd->buffer = vmw_bo_reference(bo);
@@ -1718,7 +1631,7 @@ vmw_kms_srf_ok(struct vmw_private *dev_priv, uint32_t width, uint32_t height) · 48 unmodified lines
1718 */1631 */
1719struct vmw_framebuffer *1632struct vmw_framebuffer *
1720vmw_kms_new_framebuffer(struct vmw_private *dev_priv,1633vmw_kms_new_framebuffer(struct vmw_private *dev_priv,
1721 struct vmw_buffer_object *bo,1634 struct vmw_bo *bo,
1722 struct vmw_surface *surface,1635 struct vmw_surface *surface,
1723 bool only_2d,1636 bool only_2d,
1724 const struct drm_mode_fb_cmd2 *mode_cmd)1637 const struct drm_mode_fb_cmd2 *mode_cmd)
@@ -1765,9 +1678,6 @@ vmw_kms_new_framebuffer(struct vmw_private *dev_priv, · 40 unmodified lines
1765 if (ret)1678 if (ret)
1766 return ERR_PTR(ret);1679 return ERR_PTR(ret);
1767 1680
1768 vfb->pin = vmw_framebuffer_pin;
1769 vfb->unpin = vmw_framebuffer_unpin;
1770
1771 return vfb;1681 return vfb;
1772}1682}
1773 1683
@@ -1782,7 +1692,7 @@ static struct drm_framebuffer *vmw_kms_fb_create(struct drm_device *dev, · 8 unmodified lines
1782 struct vmw_private *dev_priv = vmw_priv(dev);1692 struct vmw_private *dev_priv = vmw_priv(dev);
1783 struct vmw_framebuffer *vfb = NULL;1693 struct vmw_framebuffer *vfb = NULL;
1784 struct vmw_surface *surface = NULL;1694 struct vmw_surface *surface = NULL;
1785 struct vmw_buffer_object *bo = NULL;1695 struct vmw_bo *bo = NULL;
1786 int ret;1696 int ret;
1787 1697
1788 /* returns either a bo or surface */1698 /* returns either a bo or surface */
@@ -1817,7 +1727,7 @@ err_out: · 28 unmodified lines
1817 /* vmw_user_lookup_handle takes one ref so does new_fb */1727 /* vmw_user_lookup_handle takes one ref so does new_fb */
1818 if (bo) {1728 if (bo) {
1819 vmw_bo_unreference(&bo);1729 vmw_bo_unreference(&bo);
1820 drm_gem_object_put(&bo->base.base);1730 drm_gem_object_put(&bo->tbo.base);
1821 }1731 }
1822 if (surface)1732 if (surface)
1823 vmw_surface_unreference(&surface);1733 vmw_surface_unreference(&surface);
@@ -3076,8 +2986,20 @@ int vmw_du_helper_plane_update(struct vmw_du_update_plane *update) · 1252 unmodified lines
3076 struct vmw_framebuffer_bo *vfbbo =2986 struct vmw_framebuffer_bo *vfbbo =
3077 container_of(update->vfb, typeof(*vfbbo), base);2987 container_of(update->vfb, typeof(*vfbbo), base);
3078 2988
3079 ret = vmw_validation_add_bo(&val_ctx, vfbbo->buffer, false,2989 /*
3080 update->cpu_blit);2990 * For screen targets we want a mappable bo, for everything else we want
2991 * accelerated i.e. host backed (vram or gmr) bo. If the display unit
2992 * is not screen target then mob's shouldn't be available.
2993 */
2994 if (update->dev_priv->active_display_unit == vmw_du_screen_target) {
2995 vmw_bo_placement_set(vfbbo->buffer,
2996 VMW_BO_DOMAIN_SYS | VMW_BO_DOMAIN_MOB | VMW_BO_DOMAIN_GMR,
2997 VMW_BO_DOMAIN_SYS | VMW_BO_DOMAIN_MOB | VMW_BO_DOMAIN_GMR);
2998 } else {
2999 WARN_ON(update->dev_priv->has_mob);
3000 vmw_bo_placement_set_default_accelerated(vfbbo->buffer);
3001 }
3002 ret = vmw_validation_add_bo(&val_ctx, vfbbo->buffer);
3081 } else {3003 } else {
3082 struct vmw_framebuffer_surface *vfbs =3004 struct vmw_framebuffer_surface *vfbs =
3083 container_of(update->vfb, typeof(*vfbs), base);3005 container_of(update->vfb, typeof(*vfbs), base);
drivers/gpu/drm/vmwgfx/vmwgfx_kms.h+18−25
@@ -1,7 +1,7 @@
1/* SPDX-License-Identifier: GPL-2.0 OR MIT */1/* SPDX-License-Identifier: GPL-2.0 OR MIT */
2/**************************************************************************2/**************************************************************************
3 *3 *
4 * Copyright 2009-2022 VMware, Inc., Palo Alto, CA., USA4 * Copyright 2009-2023 VMware, Inc., Palo Alto, CA., USA
5 *5 *
6 * Permission is hereby granted, free of charge, to any person obtaining a6 * Permission is hereby granted, free of charge, to any person obtaining a
7 * copy of this software and associated documentation files (the7 * copy of this software and associated documentation files (the
@@ -126,7 +126,6 @@ struct vmw_du_update_plane { · 118 unmodified lines
126 struct vmw_framebuffer *vfb;126 struct vmw_framebuffer *vfb;
127 struct vmw_fence_obj **out_fence;127 struct vmw_fence_obj **out_fence;
128 struct mutex *mutex;128 struct mutex *mutex;
129 bool cpu_blit;
130 bool intr;129 bool intr;
131};130};
132 131
@@ -217,8 +216,6 @@ struct vmw_kms_dirty { · 84 unmodified lines
217 */216 */
218struct vmw_framebuffer {217struct vmw_framebuffer {
219 struct drm_framebuffer base;218 struct drm_framebuffer base;
220 int (*pin)(struct vmw_framebuffer *fb);
221 int (*unpin)(struct vmw_framebuffer *fb);
222 bool bo;219 bool bo;
223 uint32_t user_handle;220 uint32_t user_handle;
224};221};
@@ -233,7 +230,7 @@ struct vmw_clip_rect { · 8 unmodified lines
233struct vmw_framebuffer_surface {230struct vmw_framebuffer_surface {
234 struct vmw_framebuffer base;231 struct vmw_framebuffer base;
235 struct vmw_surface *surface;232 struct vmw_surface *surface;
236 struct vmw_buffer_object *buffer;233 struct vmw_bo *buffer;
237 struct list_head head;234 struct list_head head;
238 bool is_bo_proxy; /* true if this is proxy surface for DMA buf */235 bool is_bo_proxy; /* true if this is proxy surface for DMA buf */
239};236};
@@ -241,7 +238,7 @@ struct vmw_framebuffer_surface { · 1 unmodified line
241 238
242struct vmw_framebuffer_bo {239struct vmw_framebuffer_bo {
243 struct vmw_framebuffer base;240 struct vmw_framebuffer base;
244 struct vmw_buffer_object *buffer;241 struct vmw_bo *buffer;
245};242};
246 243
247 244
@@ -273,9 +270,7 @@ struct vmw_crtc_state { · 25 unmodified lines
273};270};
274 271
275struct vmw_cursor_plane_state {272struct vmw_cursor_plane_state {
276 struct ttm_buffer_object *bo;273 struct vmw_bo *bo;
277 struct ttm_bo_kmap_obj map;
278 bool mapped;
279 s32 hotspot_x;274 s32 hotspot_x;
280 s32 hotspot_y;275 s32 hotspot_y;
281};276};
@@ -293,7 +288,7 @@ struct vmw_cursor_plane_state { · 11 unmodified lines
293struct vmw_plane_state {288struct vmw_plane_state {
294 struct drm_plane_state base;289 struct drm_plane_state base;
295 struct vmw_surface *surf;290 struct vmw_surface *surf;
296 struct vmw_buffer_object *bo;291 struct vmw_bo *bo;
297 292
298 int content_fb_type;293 int content_fb_type;
299 unsigned long bo_size;294 unsigned long bo_size;
@@ -346,7 +341,7 @@ struct vmw_connector_state { · 46 unmodified lines
346struct vmw_cursor_plane {341struct vmw_cursor_plane {
347 struct drm_plane base;342 struct drm_plane base;
348 343
349 struct ttm_buffer_object *cursor_mobs[3];344 struct vmw_bo *cursor_mobs[3];
350};345};
351 346
352/**347/**
@@ -364,7 +359,7 @@ struct vmw_display_unit { · 11 unmodified lines
364 struct vmw_cursor_plane cursor;359 struct vmw_cursor_plane cursor;
365 360
366 struct vmw_surface *cursor_surface;361 struct vmw_surface *cursor_surface;
367 struct vmw_buffer_object *cursor_bo;362 struct vmw_bo *cursor_bo;
368 size_t cursor_age;363 size_t cursor_age;
369 364
370 int cursor_x;365 int cursor_x;
@@ -397,7 +392,7 @@ struct vmw_display_unit { · 26 unmodified lines
397 392
398struct vmw_validation_ctx {393struct vmw_validation_ctx {
399 struct vmw_resource *res;394 struct vmw_resource *res;
400 struct vmw_buffer_object *buf;395 struct vmw_bo *buf;
401};396};
402 397
403#define vmw_crtc_to_du(x) \398#define vmw_crtc_to_du(x) \
@@ -458,7 +453,7 @@ int vmw_kms_readback(struct vmw_private *dev_priv, · 54 unmodified lines
458 uint32_t num_clips);453 uint32_t num_clips);
459struct vmw_framebuffer *454struct vmw_framebuffer *
460vmw_kms_new_framebuffer(struct vmw_private *dev_priv,455vmw_kms_new_framebuffer(struct vmw_private *dev_priv,
461 struct vmw_buffer_object *bo,456 struct vmw_bo *bo,
462 struct vmw_surface *surface,457 struct vmw_surface *surface,
463 bool only_2d,458 bool only_2d,
464 const struct drm_mode_fb_cmd2 *mode_cmd);459 const struct drm_mode_fb_cmd2 *mode_cmd);
@@ -566,17 +561,15 @@ int vmw_kms_stdu_surface_dirty(struct vmw_private *dev_priv, · 101 unmodified lines
566 unsigned num_clips, int inc,561 unsigned num_clips, int inc,
567 struct vmw_fence_obj **out_fence,562 struct vmw_fence_obj **out_fence,
568 struct drm_crtc *crtc);563 struct drm_crtc *crtc);
569int vmw_kms_stdu_dma(struct vmw_private *dev_priv,564int vmw_kms_stdu_readback(struct vmw_private *dev_priv,
570 struct drm_file *file_priv,565 struct drm_file *file_priv,
571 struct vmw_framebuffer *vfb,566 struct vmw_framebuffer *vfb,
572 struct drm_vmw_fence_rep __user *user_fence_rep,567 struct drm_vmw_fence_rep __user *user_fence_rep,
573 struct drm_clip_rect *clips,568 struct drm_clip_rect *clips,
574 struct drm_vmw_rect *vclips,569 struct drm_vmw_rect *vclips,
575 uint32_t num_clips,570 uint32_t num_clips,
576 int increment,571 int increment,
577 bool to_surface,572 struct drm_crtc *crtc);
578 bool interruptible,
579 struct drm_crtc *crtc);
580 573
581int vmw_du_helper_plane_update(struct vmw_du_update_plane *update);574int vmw_du_helper_plane_update(struct vmw_du_update_plane *update);
582 575
drivers/gpu/drm/vmwgfx/vmwgfx_ldu.c+49−8
@@ -1,7 +1,7 @@
1// SPDX-License-Identifier: GPL-2.0 OR MIT1// SPDX-License-Identifier: GPL-2.0 OR MIT
2/**************************************************************************2/**************************************************************************
3 *3 *
4 * Copyright 2009-2022 VMware, Inc., Palo Alto, CA., USA4 * Copyright 2009-2023 VMware, Inc., Palo Alto, CA., USA
5 *5 *
6 * Permission is hereby granted, free of charge, to any person obtaining a6 * Permission is hereby granted, free of charge, to any person obtaining a
7 * copy of this software and associated documentation files (the7 * copy of this software and associated documentation files (the
@@ -25,11 +25,13 @@ · 17 unmodified lines
25 *25 *
26 **************************************************************************/26 **************************************************************************/
27 27
28#include "vmwgfx_bo.h"
29#include "vmwgfx_kms.h"
30
28#include <drm/drm_atomic.h>31#include <drm/drm_atomic.h>
29#include <drm/drm_atomic_helper.h>32#include <drm/drm_atomic_helper.h>
30#include <drm/drm_fourcc.h>33#include <drm/drm_fourcc.h>
31 34
32#include "vmwgfx_kms.h"
33 35
34#define vmw_crtc_to_ldu(x) \36#define vmw_crtc_to_ldu(x) \
35 container_of(x, struct vmw_legacy_display_unit, base.crtc)37 container_of(x, struct vmw_legacy_display_unit, base.crtc)
@@ -134,6 +136,47 @@ static int vmw_ldu_commit_list(struct vmw_private *dev_priv) · 98 unmodified lines
134 return 0;136 return 0;
135}137}
136 138
139/*
140 * Pin the buffer in a location suitable for access by the
141 * display system.
142 */
143static 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
166static 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
137static int vmw_ldu_del_active(struct vmw_private *vmw_priv,180static int vmw_ldu_del_active(struct vmw_private *vmw_priv,
138 struct vmw_legacy_display_unit *ldu)181 struct vmw_legacy_display_unit *ldu)
139{182{
@@ -145,8 +188,7 @@ static int vmw_ldu_del_active(struct vmw_private *vmw_priv, · 5 unmodified lines
145 list_del_init(&ldu->active);188 list_del_init(&ldu->active);
146 if (--(ld->num_active) == 0) {189 if (--(ld->num_active) == 0) {
147 BUG_ON(!ld->fb);190 BUG_ON(!ld->fb);
148 if (ld->fb->unpin)191 WARN_ON(vmw_ldu_fb_unpin(ld->fb));
149 ld->fb->unpin(ld->fb);
150 ld->fb = NULL;192 ld->fb = NULL;
151 }193 }
152 194
@@ -163,11 +205,10 @@ static int vmw_ldu_add_active(struct vmw_private *vmw_priv, · 10 unmodified lines
163 205
164 BUG_ON(!ld->num_active && ld->fb);206 BUG_ON(!ld->num_active && ld->fb);
165 if (vfb != ld->fb) {207 if (vfb != ld->fb) {
166 if (ld->fb && ld->fb->unpin)208 if (ld->fb)
167 ld->fb->unpin(ld->fb);209 WARN_ON(vmw_ldu_fb_unpin(ld->fb));
168 vmw_svga_enable(vmw_priv);210 vmw_svga_enable(vmw_priv);
169 if (vfb->pin)211 WARN_ON(vmw_ldu_fb_pin(vfb));
170 vfb->pin(vfb);
171 ld->fb = vfb;212 ld->fb = vfb;
172 }213 }
173 214
drivers/gpu/drm/vmwgfx/vmwgfx_mob.c+24−21
@@ -1,7 +1,7 @@
1// SPDX-License-Identifier: GPL-2.0 OR MIT1// SPDX-License-Identifier: GPL-2.0 OR MIT
2/**************************************************************************2/**************************************************************************
3 *3 *
4 * Copyright 2012-2021 VMware, Inc., Palo Alto, CA., USA4 * Copyright 2012-2023 VMware, Inc., Palo Alto, CA., USA
5 *5 *
6 * Permission is hereby granted, free of charge, to any person obtaining a6 * Permission is hereby granted, free of charge, to any person obtaining a
7 * copy of this software and associated documentation files (the7 * copy of this software and associated documentation files (the
@@ -25,10 +25,11 @@ · 17 unmodified lines
25 *25 *
26 **************************************************************************/26 **************************************************************************/
27 27
28#include <linux/highmem.h>28#include "vmwgfx_bo.h"
29
30#include "vmwgfx_drv.h"29#include "vmwgfx_drv.h"
31 30
31#include <linux/highmem.h>
32
32#ifdef CONFIG_64BIT33#ifdef CONFIG_64BIT
33#define VMW_PPN_SIZE 834#define VMW_PPN_SIZE 8
34#define VMW_MOBFMT_PTDEPTH_0 SVGA3D_MOBFMT_PT64_035#define VMW_MOBFMT_PTDEPTH_0 SVGA3D_MOBFMT_PT64_0
@@ -50,7 +51,7 @@ · 15 unmodified lines
50 * @pt_root_page DMA address of the level 0 page of the page table.51 * @pt_root_page DMA address of the level 0 page of the page table.
51 */52 */
52struct vmw_mob {53struct vmw_mob {
53 struct ttm_buffer_object *pt_bo;54 struct vmw_bo *pt_bo;
54 unsigned long num_pages;55 unsigned long num_pages;
55 unsigned pt_level;56 unsigned pt_level;
56 dma_addr_t pt_root_page;57 dma_addr_t pt_root_page;
@@ -203,7 +204,7 @@ static void vmw_takedown_otable_base(struct vmw_private *dev_priv, · 146 unmodified lines
203 if (otable->page_table == NULL)204 if (otable->page_table == NULL)
204 return;205 return;
205 206
206 bo = otable->page_table->pt_bo;207 bo = &otable->page_table->pt_bo->tbo;
207 cmd = VMW_CMD_RESERVE(dev_priv, sizeof(*cmd));208 cmd = VMW_CMD_RESERVE(dev_priv, sizeof(*cmd));
208 if (unlikely(cmd == NULL))209 if (unlikely(cmd == NULL))
209 return;210 return;
@@ -251,7 +252,9 @@ static int vmw_otable_batch_setup(struct vmw_private *dev_priv, · 41 unmodified lines
251 bo_size += otables[i].size;252 bo_size += otables[i].size;
252 }253 }
253 254
254 ret = vmw_bo_create_and_populate(dev_priv, bo_size, &batch->otable_bo);255 ret = vmw_bo_create_and_populate(dev_priv, bo_size,
256 VMW_BO_DOMAIN_WAITABLE_SYS,
257 &batch->otable_bo);
255 if (unlikely(ret != 0))258 if (unlikely(ret != 0))
256 return ret;259 return ret;
257 260
@@ -260,7 +263,8 @@ static int vmw_otable_batch_setup(struct vmw_private *dev_priv, · 2 unmodified lines
260 if (!batch->otables[i].enabled)263 if (!batch->otables[i].enabled)
261 continue;264 continue;
262 265
263 ret = vmw_setup_otable_base(dev_priv, i, batch->otable_bo,266 ret = vmw_setup_otable_base(dev_priv, i,
267 &batch->otable_bo->tbo,
264 offset,268 offset,
265 &otables[i]);269 &otables[i]);
266 if (unlikely(ret != 0))270 if (unlikely(ret != 0))
@@ -277,8 +281,8 @@ out_no_setup: · 10 unmodified lines
277 &batch->otables[i]);281 &batch->otables[i]);
278 }282 }
279 283
280 vmw_bo_unpin_unlocked(batch->otable_bo);284 vmw_bo_unpin_unlocked(&batch->otable_bo->tbo);
281 ttm_bo_put(batch->otable_bo);285 ttm_bo_put(&batch->otable_bo->tbo);
282 batch->otable_bo = NULL;286 batch->otable_bo = NULL;
283 return ret;287 return ret;
284}288}
@@ -329,7 +333,7 @@ static void vmw_otable_batch_takedown(struct vmw_private *dev_priv, · 44 unmodified lines
329 struct vmw_otable_batch *batch)333 struct vmw_otable_batch *batch)
330{334{
331 SVGAOTableType i;335 SVGAOTableType i;
332 struct ttm_buffer_object *bo = batch->otable_bo;336 struct ttm_buffer_object *bo = &batch->otable_bo->tbo;
333 int ret;337 int ret;
334 338
335 for (i = 0; i < batch->num_otables; ++i)339 for (i = 0; i < batch->num_otables; ++i)
@@ -344,8 +348,7 @@ static void vmw_otable_batch_takedown(struct vmw_private *dev_priv, · 8 unmodified lines
344 ttm_bo_unpin(bo);348 ttm_bo_unpin(bo);
345 ttm_bo_unreserve(bo);349 ttm_bo_unreserve(bo);
346 350
347 ttm_bo_put(batch->otable_bo);351 vmw_bo_unreference(&batch->otable_bo);
348 batch->otable_bo = NULL;
349}352}
350 353
351/*354/*
@@ -413,7 +416,9 @@ static int vmw_mob_pt_populate(struct vmw_private *dev_priv, · 61 unmodified lines
413{416{
414 BUG_ON(mob->pt_bo != NULL);417 BUG_ON(mob->pt_bo != NULL);
415 418
416 return vmw_bo_create_and_populate(dev_priv, mob->num_pages * PAGE_SIZE, &mob->pt_bo);419 return vmw_bo_create_and_populate(dev_priv, mob->num_pages * PAGE_SIZE,
420 VMW_BO_DOMAIN_WAITABLE_SYS,
421 &mob->pt_bo);
417}422}
418 423
419/**424/**
@@ -494,7 +499,7 @@ static void vmw_mob_pt_setup(struct vmw_mob *mob, · 74 unmodified lines
494 unsigned long num_data_pages)499 unsigned long num_data_pages)
495{500{
496 unsigned long num_pt_pages = 0;501 unsigned long num_pt_pages = 0;
497 struct ttm_buffer_object *bo = mob->pt_bo;502 struct ttm_buffer_object *bo = &mob->pt_bo->tbo;
498 struct vmw_piter save_pt_iter = {0};503 struct vmw_piter save_pt_iter = {0};
499 struct vmw_piter pt_iter;504 struct vmw_piter pt_iter;
500 const struct vmw_sg_table *vsgt;505 const struct vmw_sg_table *vsgt;
@@ -531,9 +536,8 @@ static void vmw_mob_pt_setup(struct vmw_mob *mob, · 30 unmodified lines
531void vmw_mob_destroy(struct vmw_mob *mob)536void vmw_mob_destroy(struct vmw_mob *mob)
532{537{
533 if (mob->pt_bo) {538 if (mob->pt_bo) {
534 vmw_bo_unpin_unlocked(mob->pt_bo);539 vmw_bo_unpin_unlocked(&mob->pt_bo->tbo);
535 ttm_bo_put(mob->pt_bo);540 vmw_bo_unreference(&mob->pt_bo);
536 mob->pt_bo = NULL;
537 }541 }
538 kfree(mob);542 kfree(mob);
539}543}
@@ -552,7 +556,7 @@ void vmw_mob_unbind(struct vmw_private *dev_priv, · 12 unmodified lines
552 SVGA3dCmdDestroyGBMob body;556 SVGA3dCmdDestroyGBMob body;
553 } *cmd;557 } *cmd;
554 int ret;558 int ret;
555 struct ttm_buffer_object *bo = mob->pt_bo;559 struct ttm_buffer_object *bo = &mob->pt_bo->tbo;
556 560
557 if (bo) {561 if (bo) {
558 ret = ttm_bo_reserve(bo, false, true, NULL);562 ret = ttm_bo_reserve(bo, false, true, NULL);
@@ -644,9 +648,8 @@ int vmw_mob_bind(struct vmw_private *dev_priv, · 85 unmodified lines
644out_no_cmd_space:648out_no_cmd_space:
645 vmw_fifo_resource_dec(dev_priv);649 vmw_fifo_resource_dec(dev_priv);
646 if (pt_set_up) {650 if (pt_set_up) {
647 vmw_bo_unpin_unlocked(mob->pt_bo);651 vmw_bo_unpin_unlocked(&mob->pt_bo->tbo);
648 ttm_bo_put(mob->pt_bo);652 vmw_bo_unreference(&mob->pt_bo);
649 mob->pt_bo = NULL;
650 }653 }
651 654
652 return -ENOMEM;655 return -ENOMEM;
drivers/gpu/drm/vmwgfx/vmwgfx_overlay.c+11−11
@@ -1,7 +1,7 @@
1// SPDX-License-Identifier: GPL-2.0 OR MIT1// SPDX-License-Identifier: GPL-2.0 OR MIT
2/**************************************************************************2/**************************************************************************
3 *3 *
4 * Copyright 2009-2014 VMware, Inc., Palo Alto, CA., USA4 * Copyright 2009-2023 VMware, Inc., Palo Alto, CA., USA
5 *5 *
6 * Permission is hereby granted, free of charge, to any person obtaining a6 * Permission is hereby granted, free of charge, to any person obtaining a
7 * copy of this software and associated documentation files (the7 * copy of this software and associated documentation files (the
@@ -24,19 +24,19 @@ · 16 unmodified lines
24 * USE OR OTHER DEALINGS IN THE SOFTWARE.24 * USE OR OTHER DEALINGS IN THE SOFTWARE.
25 *25 *
26 **************************************************************************/26 **************************************************************************/
27 27#include "vmwgfx_bo.h"
28#include <drm/ttm/ttm_placement.h>28#include "vmwgfx_drv.h"
29 29
30#include "device_include/svga_overlay.h"30#include "device_include/svga_overlay.h"
31#include "device_include/svga_escape.h"31#include "device_include/svga_escape.h"
32 32
33#include "vmwgfx_drv.h"33#include <drm/ttm/ttm_placement.h>
34 34
35#define VMW_MAX_NUM_STREAMS 135#define VMW_MAX_NUM_STREAMS 1
36#define VMW_OVERLAY_CAP_MASK (SVGA_FIFO_CAP_VIDEO | SVGA_FIFO_CAP_ESCAPE)36#define VMW_OVERLAY_CAP_MASK (SVGA_FIFO_CAP_VIDEO | SVGA_FIFO_CAP_ESCAPE)
37 37
38struct vmw_stream {38struct vmw_stream {
39 struct vmw_buffer_object *buf;39 struct vmw_bo *buf;
40 bool claimed;40 bool claimed;
41 bool paused;41 bool paused;
42 struct drm_vmw_control_stream_arg saved;42 struct drm_vmw_control_stream_arg saved;
@@ -92,7 +92,7 @@ static inline void fill_flush(struct vmw_escape_video_flush *cmd, · 49 unmodified lines
92 * -ERESTARTSYS if interrupted by a signal.92 * -ERESTARTSYS if interrupted by a signal.
93 */93 */
94static int vmw_overlay_send_put(struct vmw_private *dev_priv,94static int vmw_overlay_send_put(struct vmw_private *dev_priv,
95 struct vmw_buffer_object *buf,95 struct vmw_bo *buf,
96 struct drm_vmw_control_stream_arg *arg,96 struct drm_vmw_control_stream_arg *arg,
97 bool interruptible)97 bool interruptible)
98{98{
@@ -140,7 +140,7 @@ static int vmw_overlay_send_put(struct vmw_private *dev_priv, · 41 unmodified lines
140 for (i = 0; i < num_items; i++)140 for (i = 0; i < num_items; i++)
141 items[i].registerId = i;141 items[i].registerId = i;
142 142
143 vmw_bo_get_guest_ptr(&buf->base, &ptr);143 vmw_bo_get_guest_ptr(&buf->tbo, &ptr);
144 ptr.offset += arg->offset;144 ptr.offset += arg->offset;
145 145
146 items[SVGA_VIDEO_ENABLED].value = true;146 items[SVGA_VIDEO_ENABLED].value = true;
@@ -223,7 +223,7 @@ static int vmw_overlay_send_stop(struct vmw_private *dev_priv, · 76 unmodified lines
223 * used with GMRs instead of being locked to vram.223 * used with GMRs instead of being locked to vram.
224 */224 */
225static int vmw_overlay_move_buffer(struct vmw_private *dev_priv,225static int vmw_overlay_move_buffer(struct vmw_private *dev_priv,
226 struct vmw_buffer_object *buf,226 struct vmw_bo *buf,
227 bool pin, bool inter)227 bool pin, bool inter)
228{228{
229 if (!pin)229 if (!pin)
@@ -295,7 +295,7 @@ static int vmw_overlay_stop(struct vmw_private *dev_priv, · 65 unmodified lines
295 * -ERESTARTSYS if interrupted.295 * -ERESTARTSYS if interrupted.
296 */296 */
297static int vmw_overlay_update_stream(struct vmw_private *dev_priv,297static int vmw_overlay_update_stream(struct vmw_private *dev_priv,
298 struct vmw_buffer_object *buf,298 struct vmw_bo *buf,
299 struct drm_vmw_control_stream_arg *arg,299 struct drm_vmw_control_stream_arg *arg,
300 bool interruptible)300 bool interruptible)
301{301{
@@ -433,7 +433,7 @@ int vmw_overlay_ioctl(struct drm_device *dev, void *data, · 131 unmodified lines
433 struct vmw_overlay *overlay = dev_priv->overlay_priv;433 struct vmw_overlay *overlay = dev_priv->overlay_priv;
434 struct drm_vmw_control_stream_arg *arg =434 struct drm_vmw_control_stream_arg *arg =
435 (struct drm_vmw_control_stream_arg *)data;435 (struct drm_vmw_control_stream_arg *)data;
436 struct vmw_buffer_object *buf;436 struct vmw_bo *buf;
437 struct vmw_resource *res;437 struct vmw_resource *res;
438 int ret;438 int ret;
439 439
@@ -458,7 +458,7 @@ int vmw_overlay_ioctl(struct drm_device *dev, void *data, · 18 unmodified lines
458 ret = vmw_overlay_update_stream(dev_priv, buf, arg, true);458 ret = vmw_overlay_update_stream(dev_priv, buf, arg, true);
459 459
460 vmw_bo_unreference(&buf);460 vmw_bo_unreference(&buf);
461 drm_gem_object_put(&buf->base.base);461 drm_gem_object_put(&buf->tbo.base);
462 462
463out_unlock:463out_unlock:
464 mutex_unlock(&overlay->mutex);464 mutex_unlock(&overlay->mutex);
drivers/gpu/drm/vmwgfx/vmwgfx_page_dirty.c+33−35
@@ -1,7 +1,7 @@
1// SPDX-License-Identifier: GPL-2.0 OR MIT1// SPDX-License-Identifier: GPL-2.0 OR MIT
2/**************************************************************************2/**************************************************************************
3 *3 *
4 * Copyright 2019 VMware, Inc., Palo Alto, CA., USA4 * Copyright 2019-2023 VMware, Inc., Palo Alto, CA., USA
5 *5 *
6 * Permission is hereby granted, free of charge, to any person obtaining a6 * Permission is hereby granted, free of charge, to any person obtaining a
7 * copy of this software and associated documentation files (the7 * copy of this software and associated documentation files (the
@@ -24,6 +24,7 @@ · 16 unmodified lines
24 * USE OR OTHER DEALINGS IN THE SOFTWARE.24 * USE OR OTHER DEALINGS IN THE SOFTWARE.
25 *25 *
26 **************************************************************************/26 **************************************************************************/
27#include "vmwgfx_bo.h"
27#include "vmwgfx_drv.h"28#include "vmwgfx_drv.h"
28 29
29/*30/*
@@ -78,11 +79,11 @@ struct vmw_bo_dirty { · 48 unmodified lines
78 * dirty structure with the results. This function may change the79 * dirty structure with the results. This function may change the
79 * dirty-tracking method.80 * dirty-tracking method.
80 */81 */
81static void vmw_bo_dirty_scan_pagetable(struct vmw_buffer_object *vbo)82static void vmw_bo_dirty_scan_pagetable(struct vmw_bo *vbo)
82{83{
83 struct vmw_bo_dirty *dirty = vbo->dirty;84 struct vmw_bo_dirty *dirty = vbo->dirty;
84 pgoff_t offset = drm_vma_node_start(&vbo->base.base.vma_node);85 pgoff_t offset = drm_vma_node_start(&vbo->tbo.base.vma_node);
85 struct address_space *mapping = vbo->base.bdev->dev_mapping;86 struct address_space *mapping = vbo->tbo.bdev->dev_mapping;
86 pgoff_t num_marked;87 pgoff_t num_marked;
87 88
88 num_marked = clean_record_shared_mapping_range89 num_marked = clean_record_shared_mapping_range
@@ -116,26 +117,25 @@ static void vmw_bo_dirty_scan_pagetable(struct vmw_buffer_object *vbo) · 27 unmodified lines
116 *117 *
117 * This function may change the dirty-tracking method.118 * This function may change the dirty-tracking method.
118 */119 */
119static void vmw_bo_dirty_scan_mkwrite(struct vmw_buffer_object *vbo)120static void vmw_bo_dirty_scan_mkwrite(struct vmw_bo *vbo)
120{121{
121 struct vmw_bo_dirty *dirty = vbo->dirty;122 struct vmw_bo_dirty *dirty = vbo->dirty;
122 unsigned long offset = drm_vma_node_start(&vbo->base.base.vma_node);123 unsigned long offset = drm_vma_node_start(&vbo->tbo.base.vma_node);
123 struct address_space *mapping = vbo->base.bdev->dev_mapping;124 struct address_space *mapping = vbo->tbo.bdev->dev_mapping;
124 pgoff_t num_marked;125 pgoff_t num_marked;
125 126
126 if (dirty->end <= dirty->start)127 if (dirty->end <= dirty->start)
127 return;128 return;
128 129
129 num_marked = wp_shared_mapping_range(vbo->base.bdev->dev_mapping,130 num_marked = wp_shared_mapping_range(vbo->tbo.bdev->dev_mapping,
130 dirty->start + offset,131 dirty->start + offset,
131 dirty->end - dirty->start);132 dirty->end - dirty->start);
132 133
133 if (100UL * num_marked / dirty->bitmap_size >134 if (100UL * num_marked / dirty->bitmap_size >
134 VMW_DIRTY_PERCENTAGE) {135 VMW_DIRTY_PERCENTAGE)
135 dirty->change_count++;136 dirty->change_count++;
136 } else {137 else
137 dirty->change_count = 0;138 dirty->change_count = 0;
138 }
139 139
140 if (dirty->change_count > VMW_DIRTY_NUM_CHANGE_TRIGGERS) {140 if (dirty->change_count > VMW_DIRTY_NUM_CHANGE_TRIGGERS) {
141 pgoff_t start = 0;141 pgoff_t start = 0;
@@ -160,7 +160,7 @@ static void vmw_bo_dirty_scan_mkwrite(struct vmw_buffer_object *vbo) · 18 unmodified lines
160 *160 *
161 * This function may change the dirty tracking method.161 * This function may change the dirty tracking method.
162 */162 */
163void vmw_bo_dirty_scan(struct vmw_buffer_object *vbo)163void vmw_bo_dirty_scan(struct vmw_bo *vbo)
164{164{
165 struct vmw_bo_dirty *dirty = vbo->dirty;165 struct vmw_bo_dirty *dirty = vbo->dirty;
166 166
@@ -181,12 +181,12 @@ void vmw_bo_dirty_scan(struct vmw_buffer_object *vbo) · 14 unmodified lines
181 * when calling unmap_mapping_range(). This function makes sure we pick181 * when calling unmap_mapping_range(). This function makes sure we pick
182 * up all dirty pages.182 * up all dirty pages.
183 */183 */
184static void vmw_bo_dirty_pre_unmap(struct vmw_buffer_object *vbo,184static void vmw_bo_dirty_pre_unmap(struct vmw_bo *vbo,
185 pgoff_t start, pgoff_t end)185 pgoff_t start, pgoff_t end)
186{186{
187 struct vmw_bo_dirty *dirty = vbo->dirty;187 struct vmw_bo_dirty *dirty = vbo->dirty;
188 unsigned long offset = drm_vma_node_start(&vbo->base.base.vma_node);188 unsigned long offset = drm_vma_node_start(&vbo->tbo.base.vma_node);
189 struct address_space *mapping = vbo->base.bdev->dev_mapping;189 struct address_space *mapping = vbo->tbo.bdev->dev_mapping;
190 190
191 if (dirty->method != VMW_BO_DIRTY_PAGETABLE || start >= end)191 if (dirty->method != VMW_BO_DIRTY_PAGETABLE || start >= end)
192 return;192 return;
@@ -206,11 +206,11 @@ static void vmw_bo_dirty_pre_unmap(struct vmw_buffer_object *vbo, · 13 unmodified lines
206 *206 *
207 * This is similar to ttm_bo_unmap_virtual() except it takes a subrange.207 * This is similar to ttm_bo_unmap_virtual() except it takes a subrange.
208 */208 */
209void vmw_bo_dirty_unmap(struct vmw_buffer_object *vbo,209void vmw_bo_dirty_unmap(struct vmw_bo *vbo,
210 pgoff_t start, pgoff_t end)210 pgoff_t start, pgoff_t end)
211{211{
212 unsigned long offset = drm_vma_node_start(&vbo->base.base.vma_node);212 unsigned long offset = drm_vma_node_start(&vbo->tbo.base.vma_node);
213 struct address_space *mapping = vbo->base.bdev->dev_mapping;213 struct address_space *mapping = vbo->tbo.bdev->dev_mapping;
214 214
215 vmw_bo_dirty_pre_unmap(vbo, start, end);215 vmw_bo_dirty_pre_unmap(vbo, start, end);
216 unmap_shared_mapping_range(mapping, (offset + start) << PAGE_SHIFT,216 unmap_shared_mapping_range(mapping, (offset + start) << PAGE_SHIFT,
@@ -227,10 +227,10 @@ void vmw_bo_dirty_unmap(struct vmw_buffer_object *vbo, · 10 unmodified lines
227 *227 *
228 * Return: Zero on success, -ENOMEM on memory allocation failure.228 * Return: Zero on success, -ENOMEM on memory allocation failure.
229 */229 */
230int vmw_bo_dirty_add(struct vmw_buffer_object *vbo)230int vmw_bo_dirty_add(struct vmw_bo *vbo)
231{231{
232 struct vmw_bo_dirty *dirty = vbo->dirty;232 struct vmw_bo_dirty *dirty = vbo->dirty;
233 pgoff_t num_pages = PFN_UP(vbo->base.resource->size);233 pgoff_t num_pages = PFN_UP(vbo->tbo.resource->size);
234 size_t size;234 size_t size;
235 int ret;235 int ret;
236 236
@@ -253,8 +253,8 @@ int vmw_bo_dirty_add(struct vmw_buffer_object *vbo) · 16 unmodified lines
253 if (num_pages < PAGE_SIZE / sizeof(pte_t)) {253 if (num_pages < PAGE_SIZE / sizeof(pte_t)) {
254 dirty->method = VMW_BO_DIRTY_PAGETABLE;254 dirty->method = VMW_BO_DIRTY_PAGETABLE;
255 } else {255 } else {
256 struct address_space *mapping = vbo->base.bdev->dev_mapping;256 struct address_space *mapping = vbo->tbo.bdev->dev_mapping;
257 pgoff_t offset = drm_vma_node_start(&vbo->base.base.vma_node);257 pgoff_t offset = drm_vma_node_start(&vbo->tbo.base.vma_node);
258 258
259 dirty->method = VMW_BO_DIRTY_MKWRITE;259 dirty->method = VMW_BO_DIRTY_MKWRITE;
260 260
@@ -284,7 +284,7 @@ out_no_dirty: · 23 unmodified lines
284 *284 *
285 * Return: Zero on success, -ENOMEM on memory allocation failure.285 * Return: Zero on success, -ENOMEM on memory allocation failure.
286 */286 */
287void vmw_bo_dirty_release(struct vmw_buffer_object *vbo)287void vmw_bo_dirty_release(struct vmw_bo *vbo)
288{288{
289 struct vmw_bo_dirty *dirty = vbo->dirty;289 struct vmw_bo_dirty *dirty = vbo->dirty;
290 290
@@ -306,11 +306,11 @@ void vmw_bo_dirty_release(struct vmw_buffer_object *vbo) · 15 unmodified lines
306 */306 */
307void vmw_bo_dirty_transfer_to_res(struct vmw_resource *res)307void vmw_bo_dirty_transfer_to_res(struct vmw_resource *res)
308{308{
309 struct vmw_buffer_object *vbo = res->backup;309 struct vmw_bo *vbo = res->guest_memory_bo;
310 struct vmw_bo_dirty *dirty = vbo->dirty;310 struct vmw_bo_dirty *dirty = vbo->dirty;
311 pgoff_t start, cur, end;311 pgoff_t start, cur, end;
312 unsigned long res_start = res->backup_offset;312 unsigned long res_start = res->guest_memory_offset;
313 unsigned long res_end = res->backup_offset + res->backup_size;313 unsigned long res_end = res->guest_memory_offset + res->guest_memory_size;
314 314
315 WARN_ON_ONCE(res_start & ~PAGE_MASK);315 WARN_ON_ONCE(res_start & ~PAGE_MASK);
316 res_start >>= PAGE_SHIFT;316 res_start >>= PAGE_SHIFT;
@@ -351,9 +351,9 @@ void vmw_bo_dirty_transfer_to_res(struct vmw_resource *res) · 34 unmodified lines
351 */351 */
352void vmw_bo_dirty_clear_res(struct vmw_resource *res)352void vmw_bo_dirty_clear_res(struct vmw_resource *res)
353{353{
354 unsigned long res_start = res->backup_offset;354 unsigned long res_start = res->guest_memory_offset;
355 unsigned long res_end = res->backup_offset + res->backup_size;355 unsigned long res_end = res->guest_memory_offset + res->guest_memory_size;
356 struct vmw_buffer_object *vbo = res->backup;356 struct vmw_bo *vbo = res->guest_memory_bo;
357 struct vmw_bo_dirty *dirty = vbo->dirty;357 struct vmw_bo_dirty *dirty = vbo->dirty;
358 358
359 res_start >>= PAGE_SHIFT;359 res_start >>= PAGE_SHIFT;
@@ -380,8 +380,7 @@ vm_fault_t vmw_bo_vm_mkwrite(struct vm_fault *vmf) · 20 unmodified lines
380 vm_fault_t ret;380 vm_fault_t ret;
381 unsigned long page_offset;381 unsigned long page_offset;
382 unsigned int save_flags;382 unsigned int save_flags;
383 struct vmw_buffer_object *vbo =383 struct vmw_bo *vbo = to_vmw_bo(&bo->base);
384 container_of(bo, typeof(*vbo), base);
385 384
386 /*385 /*
387 * mkwrite() doesn't handle the VM_FAULT_RETRY return value correctly.386 * mkwrite() doesn't handle the VM_FAULT_RETRY return value correctly.
@@ -419,8 +418,7 @@ vm_fault_t vmw_bo_vm_fault(struct vm_fault *vmf) · 31 unmodified lines
419 struct vm_area_struct *vma = vmf->vma;418 struct vm_area_struct *vma = vmf->vma;
420 struct ttm_buffer_object *bo = (struct ttm_buffer_object *)419 struct ttm_buffer_object *bo = (struct ttm_buffer_object *)
421 vma->vm_private_data;420 vma->vm_private_data;
422 struct vmw_buffer_object *vbo =421 struct vmw_bo *vbo = to_vmw_bo(&bo->base);
423 container_of(bo, struct vmw_buffer_object, base);
424 pgoff_t num_prefault;422 pgoff_t num_prefault;
425 pgprot_t prot;423 pgprot_t prot;
426 vm_fault_t ret;424 vm_fault_t ret;
drivers/gpu/drm/vmwgfx/vmwgfx_resource.c+128−118
@@ -1,7 +1,7 @@
1// SPDX-License-Identifier: GPL-2.0 OR MIT1// SPDX-License-Identifier: GPL-2.0 OR MIT
2/**************************************************************************2/**************************************************************************
3 *3 *
4 * Copyright 2009-2015 VMware, Inc., Palo Alto, CA., USA4 * Copyright 2009-2023 VMware, Inc., Palo Alto, CA., USA
5 *5 *
6 * Permission is hereby granted, free of charge, to any person obtaining a6 * Permission is hereby granted, free of charge, to any person obtaining a
7 * copy of this software and associated documentation files (the7 * copy of this software and associated documentation files (the
@@ -27,9 +27,10 @@ · 19 unmodified lines
27 27
28#include <drm/ttm/ttm_placement.h>28#include <drm/ttm/ttm_placement.h>
29 29
30#include "vmwgfx_resource_priv.h"
31#include "vmwgfx_binding.h"30#include "vmwgfx_binding.h"
31#include "vmwgfx_bo.h"
32#include "vmwgfx_drv.h"32#include "vmwgfx_drv.h"
33#include "vmwgfx_resource_priv.h"
33 34
34#define VMW_RES_EVICT_ERR_COUNT 1035#define VMW_RES_EVICT_ERR_COUNT 10
35 36
@@ -39,10 +40,10 @@ · 3 unmodified lines
39 */40 */
40void vmw_resource_mob_attach(struct vmw_resource *res)41void vmw_resource_mob_attach(struct vmw_resource *res)
41{42{
42 struct vmw_buffer_object *backup = res->backup;43 struct vmw_bo *gbo = res->guest_memory_bo;
43 struct rb_node **new = &backup->res_tree.rb_node, *parent = NULL;44 struct rb_node **new = &gbo->res_tree.rb_node, *parent = NULL;
44 45
45 dma_resv_assert_held(res->backup->base.base.resv);46 dma_resv_assert_held(gbo->tbo.base.resv);
46 res->used_prio = (res->res_dirty) ? res->func->dirty_prio :47 res->used_prio = (res->res_dirty) ? res->func->dirty_prio :
47 res->func->prio;48 res->func->prio;
48 49
@@ -51,14 +52,14 @@ void vmw_resource_mob_attach(struct vmw_resource *res) · 2 unmodified lines
51 container_of(*new, struct vmw_resource, mob_node);52 container_of(*new, struct vmw_resource, mob_node);
52 53
53 parent = *new;54 parent = *new;
54 new = (res->backup_offset < this->backup_offset) ?55 new = (res->guest_memory_offset < this->guest_memory_offset) ?
55 &((*new)->rb_left) : &((*new)->rb_right);56 &((*new)->rb_left) : &((*new)->rb_right);
56 }57 }
57 58
58 rb_link_node(&res->mob_node, parent, new);59 rb_link_node(&res->mob_node, parent, new);
59 rb_insert_color(&res->mob_node, &backup->res_tree);60 rb_insert_color(&res->mob_node, &gbo->res_tree);
60 61
61 vmw_bo_prio_add(backup, res->used_prio);62 vmw_bo_prio_add(gbo, res->used_prio);
62}63}
63 64
64/**65/**
@@ -67,13 +68,13 @@ void vmw_resource_mob_attach(struct vmw_resource *res) · 2 unmodified lines
67 */68 */
68void vmw_resource_mob_detach(struct vmw_resource *res)69void vmw_resource_mob_detach(struct vmw_resource *res)
69{70{
70 struct vmw_buffer_object *backup = res->backup;71 struct vmw_bo *gbo = res->guest_memory_bo;
71 72
72 dma_resv_assert_held(backup->base.base.resv);73 dma_resv_assert_held(gbo->tbo.base.resv);
73 if (vmw_resource_mob_attached(res)) {74 if (vmw_resource_mob_attached(res)) {
74 rb_erase(&res->mob_node, &backup->res_tree);75 rb_erase(&res->mob_node, &gbo->res_tree);
75 RB_CLEAR_NODE(&res->mob_node);76 RB_CLEAR_NODE(&res->mob_node);
76 vmw_bo_prio_del(backup, res->used_prio);77 vmw_bo_prio_del(gbo, res->used_prio);
77 }78 }
78}79}
79 80
@@ -120,8 +121,8 @@ static void vmw_resource_release(struct kref *kref) · 40 unmodified lines
120 spin_lock(&dev_priv->resource_lock);121 spin_lock(&dev_priv->resource_lock);
121 list_del_init(&res->lru_head);122 list_del_init(&res->lru_head);
122 spin_unlock(&dev_priv->resource_lock);123 spin_unlock(&dev_priv->resource_lock);
123 if (res->backup) {124 if (res->guest_memory_bo) {
124 struct ttm_buffer_object *bo = &res->backup->base;125 struct ttm_buffer_object *bo = &res->guest_memory_bo->tbo;
125 126
126 ret = ttm_bo_reserve(bo, false, false, NULL);127 ret = ttm_bo_reserve(bo, false, false, NULL);
127 BUG_ON(ret);128 BUG_ON(ret);
@@ -133,14 +134,14 @@ static void vmw_resource_release(struct kref *kref) · 5 unmodified lines
133 val_buf.num_shared = 0;134 val_buf.num_shared = 0;
134 res->func->unbind(res, false, &val_buf);135 res->func->unbind(res, false, &val_buf);
135 }136 }
136 res->backup_dirty = false;137 res->guest_memory_size = false;
137 vmw_resource_mob_detach(res);138 vmw_resource_mob_detach(res);
138 if (res->dirty)139 if (res->dirty)
139 res->func->dirty_free(res);140 res->func->dirty_free(res);
140 if (res->coherent)141 if (res->coherent)
141 vmw_bo_dirty_release(res->backup);142 vmw_bo_dirty_release(res->guest_memory_bo);
142 ttm_bo_unreserve(bo);143 ttm_bo_unreserve(bo);
143 vmw_bo_unreference(&res->backup);144 vmw_bo_unreference(&res->guest_memory_bo);
144 }145 }
145 146
146 if (likely(res->hw_destroy != NULL)) {147 if (likely(res->hw_destroy != NULL)) {
@@ -223,9 +224,9 @@ int vmw_resource_init(struct vmw_private *dev_priv, struct vmw_resource *res, · 76 unmodified lines
223 INIT_LIST_HEAD(&res->lru_head);224 INIT_LIST_HEAD(&res->lru_head);
224 INIT_LIST_HEAD(&res->binding_head);225 INIT_LIST_HEAD(&res->binding_head);
225 res->id = -1;226 res->id = -1;
226 res->backup = NULL;227 res->guest_memory_bo = NULL;
227 res->backup_offset = 0;228 res->guest_memory_offset = 0;
228 res->backup_dirty = false;229 res->guest_memory_dirty = false;
229 res->res_dirty = false;230 res->res_dirty = false;
230 res->coherent = false;231 res->coherent = false;
231 res->used_prio = 3;232 res->used_prio = 3;
@@ -263,7 +264,7 @@ int vmw_user_resource_lookup_handle(struct vmw_private *dev_priv, · 31 unmodified lines
263 int ret = -EINVAL;264 int ret = -EINVAL;
264 265
265 base = ttm_base_object_lookup(tfile, handle);266 base = ttm_base_object_lookup(tfile, handle);
266 if (unlikely(base == NULL))267 if (unlikely(!base))
267 return -EINVAL;268 return -EINVAL;
268 269
269 if (unlikely(ttm_base_object_type(base) != converter->object_type))270 if (unlikely(ttm_base_object_type(base) != converter->object_type))
@@ -290,7 +291,7 @@ int vmw_user_lookup_handle(struct vmw_private *dev_priv, · 20 unmodified lines
290 struct drm_file *filp,291 struct drm_file *filp,
291 uint32_t handle,292 uint32_t handle,
292 struct vmw_surface **out_surf,293 struct vmw_surface **out_surf,
293 struct vmw_buffer_object **out_buf)294 struct vmw_bo **out_buf)
294{295{
295 struct ttm_object_file *tfile = vmw_fpriv(filp)->tfile;296 struct ttm_object_file *tfile = vmw_fpriv(filp)->tfile;
296 struct vmw_resource *res;297 struct vmw_resource *res;
@@ -312,32 +313,36 @@ int vmw_user_lookup_handle(struct vmw_private *dev_priv, · 15 unmodified lines
312}313}
313 314
314/**315/**
315 * vmw_resource_buf_alloc - Allocate a backup buffer for a resource.316 * vmw_resource_buf_alloc - Allocate a guest memory buffer for a resource.
316 *317 *
317 * @res: The resource for which to allocate a backup buffer.318 * @res: The resource for which to allocate a gbo buffer.
318 * @interruptible: Whether any sleeps during allocation should be319 * @interruptible: Whether any sleeps during allocation should be
319 * performed while interruptible.320 * performed while interruptible.
320 */321 */
321static int vmw_resource_buf_alloc(struct vmw_resource *res,322static int vmw_resource_buf_alloc(struct vmw_resource *res,
322 bool interruptible)323 bool interruptible)
323{324{
324 unsigned long size = PFN_ALIGN(res->backup_size);325 unsigned long size = PFN_ALIGN(res->guest_memory_size);
325 struct vmw_buffer_object *backup;326 struct vmw_bo *gbo;
327 struct vmw_bo_params bo_params = {
328 .domain = res->func->domain,
329 .busy_domain = res->func->busy_domain,
330 .bo_type = ttm_bo_type_device,
331 .size = res->guest_memory_size,
332 .pin = false
333 };
326 int ret;334 int ret;
327 335
328 if (likely(res->backup)) {336 if (likely(res->guest_memory_bo)) {
329 BUG_ON(res->backup->base.base.size < size);337 BUG_ON(res->guest_memory_bo->tbo.base.size < size);
330 return 0;338 return 0;
331 }339 }
332 340
333 ret = vmw_bo_create(res->dev_priv, res->backup_size,341 ret = vmw_bo_create(res->dev_priv, &bo_params, &gbo);
334 res->func->backup_placement,
335 interruptible, false,
336 &vmw_bo_bo_free, &backup);
337 if (unlikely(ret != 0))342 if (unlikely(ret != 0))
338 goto out_no_bo;343 goto out_no_bo;
339 344
340 res->backup = backup;345 res->guest_memory_bo = gbo;
341 346
342out_no_bo:347out_no_bo:
343 return ret;348 return ret;
@@ -369,13 +374,13 @@ static int vmw_resource_do_validate(struct vmw_resource *res, · 25 unmodified lines
369 }374 }
370 375
371 if (func->bind &&376 if (func->bind &&
372 ((func->needs_backup && !vmw_resource_mob_attached(res) &&377 ((func->needs_guest_memory && !vmw_resource_mob_attached(res) &&
373 val_buf->bo != NULL) ||378 val_buf->bo) ||
374 (!func->needs_backup && val_buf->bo != NULL))) {379 (!func->needs_guest_memory && val_buf->bo))) {
375 ret = func->bind(res, val_buf);380 ret = func->bind(res, val_buf);
376 if (unlikely(ret != 0))381 if (unlikely(ret != 0))
377 goto out_bind_failed;382 goto out_bind_failed;
378 if (func->needs_backup)383 if (func->needs_guest_memory)
379 vmw_resource_mob_attach(res);384 vmw_resource_mob_attach(res);
380 }385 }
381 386
@@ -385,11 +390,11 @@ static int vmw_resource_do_validate(struct vmw_resource *res, · 3 unmodified lines
385 */390 */
386 if (func->dirty_alloc && vmw_resource_mob_attached(res) &&391 if (func->dirty_alloc && vmw_resource_mob_attached(res) &&
387 !res->coherent) {392 !res->coherent) {
388 if (res->backup->dirty && !res->dirty) {393 if (res->guest_memory_bo->dirty && !res->dirty) {
389 ret = func->dirty_alloc(res);394 ret = func->dirty_alloc(res);
390 if (ret)395 if (ret)
391 return ret;396 return ret;
392 } else if (!res->backup->dirty && res->dirty) {397 } else if (!res->guest_memory_bo->dirty && res->dirty) {
393 func->dirty_free(res);398 func->dirty_free(res);
394 }399 }
395 }400 }
@@ -400,12 +405,12 @@ static int vmw_resource_do_validate(struct vmw_resource *res, · 4 unmodified lines
400 */405 */
401 if (res->dirty) {406 if (res->dirty) {
402 if (dirtying && !res->res_dirty) {407 if (dirtying && !res->res_dirty) {
403 pgoff_t start = res->backup_offset >> PAGE_SHIFT;408 pgoff_t start = res->guest_memory_offset >> PAGE_SHIFT;
404 pgoff_t end = __KERNEL_DIV_ROUND_UP409 pgoff_t end = __KERNEL_DIV_ROUND_UP
405 (res->backup_offset + res->backup_size,410 (res->guest_memory_offset + res->guest_memory_size,
406 PAGE_SIZE);411 PAGE_SIZE);
407 412
408 vmw_bo_dirty_unmap(res->backup, start, end);413 vmw_bo_dirty_unmap(res->guest_memory_bo, start, end);
409 }414 }
410 415
411 vmw_bo_dirty_transfer_to_res(res);416 vmw_bo_dirty_transfer_to_res(res);
@@ -427,10 +432,10 @@ out_bind_failed: · 15 unmodified lines
427 * @res: Pointer to the struct vmw_resource to unreserve.432 * @res: Pointer to the struct vmw_resource to unreserve.
428 * @dirty_set: Change dirty status of the resource.433 * @dirty_set: Change dirty status of the resource.
429 * @dirty: When changing dirty status indicates the new status.434 * @dirty: When changing dirty status indicates the new status.
430 * @switch_backup: Backup buffer has been switched.435 * @switch_guest_memory: Guest memory buffer has been switched.
431 * @new_backup: Pointer to new backup buffer if command submission436 * @new_guest_memory_bo: Pointer to new guest memory buffer if command submission
432 * switched. May be NULL.437 * switched. May be NULL.
433 * @new_backup_offset: New backup offset if @switch_backup is true.438 * @new_guest_memory_offset: New gbo offset if @switch_guest_memory is true.
434 *439 *
435 * Currently unreserving a resource means putting it back on the device's440 * Currently unreserving a resource means putting it back on the device's
436 * resource lru list, so that it can be evicted if necessary.441 * resource lru list, so that it can be evicted if necessary.
@@ -438,42 +443,42 @@ out_bind_failed: · 1 unmodified line
438void vmw_resource_unreserve(struct vmw_resource *res,443void vmw_resource_unreserve(struct vmw_resource *res,
439 bool dirty_set,444 bool dirty_set,
440 bool dirty,445 bool dirty,
441 bool switch_backup,446 bool switch_guest_memory,
442 struct vmw_buffer_object *new_backup,447 struct vmw_bo *new_guest_memory_bo,
443 unsigned long new_backup_offset)448 unsigned long new_guest_memory_offset)
444{449{
445 struct vmw_private *dev_priv = res->dev_priv;450 struct vmw_private *dev_priv = res->dev_priv;
446 451
447 if (!list_empty(&res->lru_head))452 if (!list_empty(&res->lru_head))
448 return;453 return;
449 454
450 if (switch_backup && new_backup != res->backup) {455 if (switch_guest_memory && new_guest_memory_bo != res->guest_memory_bo) {
451 if (res->backup) {456 if (res->guest_memory_bo) {
452 vmw_resource_mob_detach(res);457 vmw_resource_mob_detach(res);
453 if (res->coherent)458 if (res->coherent)
454 vmw_bo_dirty_release(res->backup);459 vmw_bo_dirty_release(res->guest_memory_bo);
455 vmw_bo_unreference(&res->backup);460 vmw_bo_unreference(&res->guest_memory_bo);
456 }461 }
457 462
458 if (new_backup) {463 if (new_guest_memory_bo) {
459 res->backup = vmw_bo_reference(new_backup);464 res->guest_memory_bo = vmw_bo_reference(new_guest_memory_bo);
460 465
461 /*466 /*
462 * The validation code should already have added a467 * The validation code should already have added a
463 * dirty tracker here.468 * dirty tracker here.
464 */469 */
465 WARN_ON(res->coherent && !new_backup->dirty);470 WARN_ON(res->coherent && !new_guest_memory_bo->dirty);
466 471
467 vmw_resource_mob_attach(res);472 vmw_resource_mob_attach(res);
468 } else {473 } else {
469 res->backup = NULL;474 res->guest_memory_bo = NULL;
470 }475 }
471 } else if (switch_backup && res->coherent) {476 } else if (switch_guest_memory && res->coherent) {
472 vmw_bo_dirty_release(res->backup);477 vmw_bo_dirty_release(res->guest_memory_bo);
473 }478 }
474 479
475 if (switch_backup)480 if (switch_guest_memory)
476 res->backup_offset = new_backup_offset;481 res->guest_memory_offset = new_guest_memory_offset;
477 482
478 if (dirty_set)483 if (dirty_set)
479 res->res_dirty = dirty;484 res->res_dirty = dirty;
@@ -507,30 +512,32 @@ vmw_resource_check_buffer(struct ww_acquire_ctx *ticket, · 27 unmodified lines
507{512{
508 struct ttm_operation_ctx ctx = { true, false };513 struct ttm_operation_ctx ctx = { true, false };
509 struct list_head val_list;514 struct list_head val_list;
510 bool backup_dirty = false;515 bool guest_memory_dirty = false;
511 int ret;516 int ret;
512 517
513 if (unlikely(res->backup == NULL)) {518 if (unlikely(!res->guest_memory_bo)) {
514 ret = vmw_resource_buf_alloc(res, interruptible);519 ret = vmw_resource_buf_alloc(res, interruptible);
515 if (unlikely(ret != 0))520 if (unlikely(ret != 0))
516 return ret;521 return ret;
517 }522 }
518 523
519 INIT_LIST_HEAD(&val_list);524 INIT_LIST_HEAD(&val_list);
520 ttm_bo_get(&res->backup->base);525 ttm_bo_get(&res->guest_memory_bo->tbo);
521 val_buf->bo = &res->backup->base;526 val_buf->bo = &res->guest_memory_bo->tbo;
522 val_buf->num_shared = 0;527 val_buf->num_shared = 0;
523 list_add_tail(&val_buf->head, &val_list);528 list_add_tail(&val_buf->head, &val_list);
524 ret = ttm_eu_reserve_buffers(ticket, &val_list, interruptible, NULL);529 ret = ttm_eu_reserve_buffers(ticket, &val_list, interruptible, NULL);
525 if (unlikely(ret != 0))530 if (unlikely(ret != 0))
526 goto out_no_reserve;531 goto out_no_reserve;
527 532
528 if (res->func->needs_backup && !vmw_resource_mob_attached(res))533 if (res->func->needs_guest_memory && !vmw_resource_mob_attached(res))
529 return 0;534 return 0;
530 535
531 backup_dirty = res->backup_dirty;536 guest_memory_dirty = res->guest_memory_dirty;
532 ret = ttm_bo_validate(&res->backup->base,537 vmw_bo_placement_set(res->guest_memory_bo, res->func->domain,
533 res->func->backup_placement,538 res->func->busy_domain);
539 ret = ttm_bo_validate(&res->guest_memory_bo->tbo,
540 &res->guest_memory_bo->placement,
534 &ctx);541 &ctx);
535 542
536 if (unlikely(ret != 0))543 if (unlikely(ret != 0))
@@ -543,8 +550,8 @@ out_no_validate: · 6 unmodified lines
543out_no_reserve:550out_no_reserve:
544 ttm_bo_put(val_buf->bo);551 ttm_bo_put(val_buf->bo);
545 val_buf->bo = NULL;552 val_buf->bo = NULL;
546 if (backup_dirty)553 if (guest_memory_dirty)
547 vmw_bo_unreference(&res->backup);554 vmw_bo_unreference(&res->guest_memory_bo);
548 555
549 return ret;556 return ret;
550}557}
@@ -555,12 +562,13 @@ out_no_reserve: · 4 unmodified lines
555 * @res: The resource to reserve.562 * @res: The resource to reserve.
556 *563 *
557 * This function takes the resource off the LRU list and make sure564 * This function takes the resource off the LRU list and make sure
558 * a backup buffer is present for guest-backed resources. However,565 * a guest memory buffer is present for guest-backed resources.
559 * the buffer may not be bound to the resource at this point.566 * However, the buffer may not be bound to the resource at this
567 * point.
560 *568 *
561 */569 */
562int vmw_resource_reserve(struct vmw_resource *res, bool interruptible,570int vmw_resource_reserve(struct vmw_resource *res, bool interruptible,
563 bool no_backup)571 bool no_guest_memory)
564{572{
565 struct vmw_private *dev_priv = res->dev_priv;573 struct vmw_private *dev_priv = res->dev_priv;
566 int ret;574 int ret;
@@ -569,13 +577,13 @@ int vmw_resource_reserve(struct vmw_resource *res, bool interruptible, · 2 unmodified lines
569 list_del_init(&res->lru_head);577 list_del_init(&res->lru_head);
570 spin_unlock(&dev_priv->resource_lock);578 spin_unlock(&dev_priv->resource_lock);
571 579
572 if (res->func->needs_backup && res->backup == NULL &&580 if (res->func->needs_guest_memory && !res->guest_memory_bo &&
573 !no_backup) {581 !no_guest_memory) {
574 ret = vmw_resource_buf_alloc(res, interruptible);582 ret = vmw_resource_buf_alloc(res, interruptible);
575 if (unlikely(ret != 0)) {583 if (unlikely(ret != 0)) {
576 DRM_ERROR("Failed to allocate a backup buffer "584 DRM_ERROR("Failed to allocate a guest memory buffer "
577 "of size %lu. bytes\n",585 "of size %lu. bytes\n",
578 (unsigned long) res->backup_size);586 (unsigned long) res->guest_memory_size);
579 return ret;587 return ret;
580 }588 }
581 }589 }
@@ -585,10 +593,10 @@ int vmw_resource_reserve(struct vmw_resource *res, bool interruptible, · 3 unmodified lines
585 593
586/**594/**
587 * vmw_resource_backoff_reservation - Unreserve and unreference a595 * vmw_resource_backoff_reservation - Unreserve and unreference a
588 * backup buffer596 * guest memory buffer
589 *.597 *.
590 * @ticket: The ww acquire ctx used for reservation.598 * @ticket: The ww acquire ctx used for reservation.
591 * @val_buf: Backup buffer information.599 * @val_buf: Guest memory buffer information.
592 */600 */
593static void601static void
594vmw_resource_backoff_reservation(struct ww_acquire_ctx *ticket,602vmw_resource_backoff_reservation(struct ww_acquire_ctx *ticket,
@@ -630,14 +638,14 @@ static int vmw_resource_do_evict(struct ww_acquire_ctx *ticket, · 35 unmodified lines
630 return ret;638 return ret;
631 639
632 if (unlikely(func->unbind != NULL &&640 if (unlikely(func->unbind != NULL &&
633 (!func->needs_backup || vmw_resource_mob_attached(res)))) {641 (!func->needs_guest_memory || vmw_resource_mob_attached(res)))) {
634 ret = func->unbind(res, res->res_dirty, &val_buf);642 ret = func->unbind(res, res->res_dirty, &val_buf);
635 if (unlikely(ret != 0))643 if (unlikely(ret != 0))
636 goto out_no_unbind;644 goto out_no_unbind;
637 vmw_resource_mob_detach(res);645 vmw_resource_mob_detach(res);
638 }646 }
639 ret = func->destroy(res);647 ret = func->destroy(res);
640 res->backup_dirty = true;648 res->guest_memory_dirty = true;
641 res->res_dirty = false;649 res->res_dirty = false;
642out_no_unbind:650out_no_unbind:
643 vmw_resource_backoff_reservation(ticket, &val_buf);651 vmw_resource_backoff_reservation(ticket, &val_buf);
@@ -676,8 +684,8 @@ int vmw_resource_validate(struct vmw_resource *res, bool intr, · 32 unmodified lines
676 684
677 val_buf.bo = NULL;685 val_buf.bo = NULL;
678 val_buf.num_shared = 0;686 val_buf.num_shared = 0;
679 if (res->backup)687 if (res->guest_memory_bo)
680 val_buf.bo = &res->backup->base;688 val_buf.bo = &res->guest_memory_bo->tbo;
681 do {689 do {
682 ret = vmw_resource_do_validate(res, &val_buf, dirtying);690 ret = vmw_resource_do_validate(res, &val_buf, dirtying);
683 if (likely(ret != -EBUSY))691 if (likely(ret != -EBUSY))
@@ -717,9 +725,9 @@ int vmw_resource_validate(struct vmw_resource *res, bool intr, · 33 unmodified lines
717 725
718 if (unlikely(ret != 0))726 if (unlikely(ret != 0))
719 goto out_no_validate;727 goto out_no_validate;
720 else if (!res->func->needs_backup && res->backup) {728 else if (!res->func->needs_guest_memory && res->guest_memory_bo) {
721 WARN_ON_ONCE(vmw_resource_mob_attached(res));729 WARN_ON_ONCE(vmw_resource_mob_attached(res));
722 vmw_bo_unreference(&res->backup);730 vmw_bo_unreference(&res->guest_memory_bo);
723 }731 }
724 732
725 return 0;733 return 0;
@@ -740,14 +748,14 @@ out_no_validate: · 14 unmodified lines
740 * validation code, since resource validation and eviction748 * validation code, since resource validation and eviction
741 * both require the backup buffer to be reserved.749 * both require the backup buffer to be reserved.
742 */750 */
743void vmw_resource_unbind_list(struct vmw_buffer_object *vbo)751void vmw_resource_unbind_list(struct vmw_bo *vbo)
744{752{
745 struct ttm_validate_buffer val_buf = {753 struct ttm_validate_buffer val_buf = {
746 .bo = &vbo->base,754 .bo = &vbo->tbo,
747 .num_shared = 0755 .num_shared = 0
748 };756 };
749 757
750 dma_resv_assert_held(vbo->base.base.resv);758 dma_resv_assert_held(vbo->tbo.base.resv);
751 while (!RB_EMPTY_ROOT(&vbo->res_tree)) {759 while (!RB_EMPTY_ROOT(&vbo->res_tree)) {
752 struct rb_node *node = vbo->res_tree.rb_node;760 struct rb_node *node = vbo->res_tree.rb_node;
753 struct vmw_resource *res =761 struct vmw_resource *res =
@@ -756,12 +764,12 @@ void vmw_resource_unbind_list(struct vmw_buffer_object *vbo) · 2 unmodified lines
756 if (!WARN_ON_ONCE(!res->func->unbind))764 if (!WARN_ON_ONCE(!res->func->unbind))
757 (void) res->func->unbind(res, res->res_dirty, &val_buf);765 (void) res->func->unbind(res, res->res_dirty, &val_buf);
758 766
759 res->backup_dirty = true;767 res->guest_memory_size = true;
760 res->res_dirty = false;768 res->res_dirty = false;
761 vmw_resource_mob_detach(res);769 vmw_resource_mob_detach(res);
762 }770 }
763 771
764 (void) ttm_bo_wait(&vbo->base, false, false);772 (void) ttm_bo_wait(&vbo->tbo, false, false);
765}773}
766 774
767 775
@@ -773,7 +781,7 @@ void vmw_resource_unbind_list(struct vmw_buffer_object *vbo) · 5 unmodified lines
773 * Read back cached states from the device if they exist. This function781 * Read back cached states from the device if they exist. This function
774 * assumes binding_mutex is held.782 * assumes binding_mutex is held.
775 */783 */
776int vmw_query_readback_all(struct vmw_buffer_object *dx_query_mob)784int vmw_query_readback_all(struct vmw_bo *dx_query_mob)
777{785{
778 struct vmw_resource *dx_query_ctx;786 struct vmw_resource *dx_query_ctx;
779 struct vmw_private *dev_priv;787 struct vmw_private *dev_priv;
@@ -822,20 +830,19 @@ void vmw_query_move_notify(struct ttm_buffer_object *bo, · 42 unmodified lines
822 struct ttm_resource *old_mem,830 struct ttm_resource *old_mem,
823 struct ttm_resource *new_mem)831 struct ttm_resource *new_mem)
824{832{
825 struct vmw_buffer_object *dx_query_mob;833 struct vmw_bo *dx_query_mob;
826 struct ttm_device *bdev = bo->bdev;834 struct ttm_device *bdev = bo->bdev;
827 struct vmw_private *dev_priv;835 struct vmw_private *dev_priv = vmw_priv_from_ttm(bdev);
828
829 dev_priv = container_of(bdev, struct vmw_private, bdev);
830 836
831 mutex_lock(&dev_priv->binding_mutex);837 mutex_lock(&dev_priv->binding_mutex);
832 838
833 /* If BO is being moved from MOB to system memory */839 /* If BO is being moved from MOB to system memory */
834 if (new_mem->mem_type == TTM_PL_SYSTEM &&840 if (old_mem &&
841 new_mem->mem_type == TTM_PL_SYSTEM &&
835 old_mem->mem_type == VMW_PL_MOB) {842 old_mem->mem_type == VMW_PL_MOB) {
836 struct vmw_fence_obj *fence;843 struct vmw_fence_obj *fence;
837 844
838 dx_query_mob = container_of(bo, struct vmw_buffer_object, base);845 dx_query_mob = to_vmw_bo(&bo->base);
839 if (!dx_query_mob || !dx_query_mob->dx_query_ctx) {846 if (!dx_query_mob || !dx_query_mob->dx_query_ctx) {
840 mutex_unlock(&dev_priv->binding_mutex);847 mutex_unlock(&dev_priv->binding_mutex);
841 return;848 return;
@@ -863,7 +870,7 @@ void vmw_query_move_notify(struct ttm_buffer_object *bo, · 21 unmodified lines
863 */870 */
864bool vmw_resource_needs_backup(const struct vmw_resource *res)871bool vmw_resource_needs_backup(const struct vmw_resource *res)
865{872{
866 return res->func->needs_backup;873 return res->func->needs_guest_memory;
867}874}
868 875
869/**876/**
@@ -959,21 +966,24 @@ int vmw_resource_pin(struct vmw_resource *res, bool interruptible) · 89 unmodified lines
959 goto out_no_reserve;966 goto out_no_reserve;
960 967
961 if (res->pin_count == 0) {968 if (res->pin_count == 0) {
962 struct vmw_buffer_object *vbo = NULL;969 struct vmw_bo *vbo = NULL;
963 970
964 if (res->backup) {971 if (res->guest_memory_bo) {
965 vbo = res->backup;972 vbo = res->guest_memory_bo;
966 973
967 ret = ttm_bo_reserve(&vbo->base, interruptible, false, NULL);974 ret = ttm_bo_reserve(&vbo->tbo, interruptible, false, NULL);
968 if (ret)975 if (ret)
969 goto out_no_validate;976 goto out_no_validate;
970 if (!vbo->base.pin_count) {977 if (!vbo->tbo.pin_count) {
978 vmw_bo_placement_set(vbo,
979 res->func->domain,
980 res->func->busy_domain);
971 ret = ttm_bo_validate981 ret = ttm_bo_validate
972 (&vbo->base,982 (&vbo->tbo,
973 res->func->backup_placement,983 &vbo->placement,
974 &ctx);984 &ctx);
975 if (ret) {985 if (ret) {
976 ttm_bo_unreserve(&vbo->base);986 ttm_bo_unreserve(&vbo->tbo);
977 goto out_no_validate;987 goto out_no_validate;
978 }988 }
979 }989 }
@@ -983,7 +993,7 @@ int vmw_resource_pin(struct vmw_resource *res, bool interruptible) · 3 unmodified lines
983 }993 }
984 ret = vmw_resource_validate(res, interruptible, true);994 ret = vmw_resource_validate(res, interruptible, true);
985 if (vbo)995 if (vbo)
986 ttm_bo_unreserve(&vbo->base);996 ttm_bo_unreserve(&vbo->tbo);
987 if (ret)997 if (ret)
988 goto out_no_validate;998 goto out_no_validate;
989 }999 }
@@ -1016,12 +1026,12 @@ void vmw_resource_unpin(struct vmw_resource *res) · 26 unmodified lines
1016 WARN_ON(ret);1026 WARN_ON(ret);
1017 1027
1018 WARN_ON(res->pin_count == 0);1028 WARN_ON(res->pin_count == 0);
1019 if (--res->pin_count == 0 && res->backup) {1029 if (--res->pin_count == 0 && res->guest_memory_bo) {
1020 struct vmw_buffer_object *vbo = res->backup;1030 struct vmw_bo *vbo = res->guest_memory_bo;
1021 1031
1022 (void) ttm_bo_reserve(&vbo->base, false, false, NULL);1032 (void) ttm_bo_reserve(&vbo->tbo, false, false, NULL);
1023 vmw_bo_pin_reserved(vbo, false);1033 vmw_bo_pin_reserved(vbo, false);
1024 ttm_bo_unreserve(&vbo->base);1034 ttm_bo_unreserve(&vbo->tbo);
1025 }1035 }
1026 1036
1027 vmw_resource_unreserve(res, false, false, false, NULL, 0UL);1037 vmw_resource_unreserve(res, false, false, false, NULL, 0UL);
@@ -1062,7 +1072,7 @@ void vmw_resource_dirty_update(struct vmw_resource *res, pgoff_t start, · 34 unmodified lines
1062 * @num_prefault: Returns how many pages including the first have been1072 * @num_prefault: Returns how many pages including the first have been
1063 * cleaned and are ok to prefault1073 * cleaned and are ok to prefault
1064 */1074 */
1065int vmw_resources_clean(struct vmw_buffer_object *vbo, pgoff_t start,1075int vmw_resources_clean(struct vmw_bo *vbo, pgoff_t start,
1066 pgoff_t end, pgoff_t *num_prefault)1076 pgoff_t end, pgoff_t *num_prefault)
1067{1077{
1068 struct rb_node *cur = vbo->res_tree.rb_node;1078 struct rb_node *cur = vbo->res_tree.rb_node;
@@ -1079,9 +1089,9 @@ int vmw_resources_clean(struct vmw_buffer_object *vbo, pgoff_t start, · 10 unmodified lines
1079 struct vmw_resource *cur_res =1089 struct vmw_resource *cur_res =
1080 container_of(cur, struct vmw_resource, mob_node);1090 container_of(cur, struct vmw_resource, mob_node);
1081 1091
1082 if (cur_res->backup_offset >= res_end) {1092 if (cur_res->guest_memory_offset >= res_end) {
1083 cur = cur->rb_left;1093 cur = cur->rb_left;
1084 } else if (cur_res->backup_offset + cur_res->backup_size <=1094 } else if (cur_res->guest_memory_offset + cur_res->guest_memory_size <=
1085 res_start) {1095 res_start) {
1086 cur = cur->rb_right;1096 cur = cur->rb_right;
1087 } else {1097 } else {
@@ -1092,7 +1102,7 @@ int vmw_resources_clean(struct vmw_buffer_object *vbo, pgoff_t start, · 4 unmodified lines
1092 }1102 }
1093 1103
1094 /*1104 /*
1095 * In order of increasing backup_offset, clean dirty resources1105 * In order of increasing guest_memory_offset, clean dirty resources
1096 * intersecting the range.1106 * intersecting the range.
1097 */1107 */
1098 while (found) {1108 while (found) {
@@ -1108,13 +1118,13 @@ int vmw_resources_clean(struct vmw_buffer_object *vbo, pgoff_t start, · 9 unmodified lines
1108 1118
1109 found->res_dirty = false;1119 found->res_dirty = false;
1110 }1120 }
1111 last_cleaned = found->backup_offset + found->backup_size;1121 last_cleaned = found->guest_memory_offset + found->guest_memory_size;
1112 cur = rb_next(&found->mob_node);1122 cur = rb_next(&found->mob_node);
1113 if (!cur)1123 if (!cur)
1114 break;1124 break;
1115 1125
1116 found = container_of(cur, struct vmw_resource, mob_node);1126 found = container_of(cur, struct vmw_resource, mob_node);
1117 if (found->backup_offset >= res_end)1127 if (found->guest_memory_offset >= res_end)
1118 break;1128 break;
1119 }1129 }
1120 1130
@@ -1123,7 +1133,7 @@ int vmw_resources_clean(struct vmw_buffer_object *vbo, pgoff_t start, · 2 unmodified lines
1123 */1133 */
1124 *num_prefault = 1;1134 *num_prefault = 1;
1125 if (last_cleaned > res_start) {1135 if (last_cleaned > res_start) {
1126 struct ttm_buffer_object *bo = &vbo->base;1136 struct ttm_buffer_object *bo = &vbo->tbo;
1127 1137
1128 *num_prefault = __KERNEL_DIV_ROUND_UP(last_cleaned - res_start,1138 *num_prefault = __KERNEL_DIV_ROUND_UP(last_cleaned - res_start,
1129 PAGE_SIZE);1139 PAGE_SIZE);
drivers/gpu/drm/vmwgfx/vmwgfx_resource_priv.h+6−4
@@ -58,10 +58,11 @@ struct vmw_user_resource_conv { · 57 unmodified lines
58 * struct vmw_res_func - members and functions common for a resource type58 * struct vmw_res_func - members and functions common for a resource type
59 *59 *
60 * @res_type: Enum that identifies the lru list to use for eviction.60 * @res_type: Enum that identifies the lru list to use for eviction.
61 * @needs_backup: Whether the resource is guest-backed and needs61 * @needs_guest_memory:Whether the resource is guest-backed and needs
62 * persistent buffer storage.62 * persistent buffer storage.
63 * @type_name: String that identifies the resource type.63 * @type_name: String that identifies the resource type.
64 * @backup_placement: TTM placement for backup buffers.64 * @domain: TTM placement for guest memory buffers.
65 * @busy_domain: TTM busy placement for guest memory buffers.
65 * @may_evict Whether the resource may be evicted.66 * @may_evict Whether the resource may be evicted.
66 * @create: Create a hardware resource.67 * @create: Create a hardware resource.
67 * @destroy: Destroy a hardware resource.68 * @destroy: Destroy a hardware resource.
@@ -81,9 +82,10 @@ struct vmw_user_resource_conv { · 13 unmodified lines
81 */82 */
82struct vmw_res_func {83struct vmw_res_func {
83 enum vmw_res_type res_type;84 enum vmw_res_type res_type;
84 bool needs_backup;85 bool needs_guest_memory;
85 const char *type_name;86 const char *type_name;
86 struct ttm_placement *backup_placement;87 u32 domain;
88 u32 busy_domain;
87 bool may_evict;89 bool may_evict;
88 u32 prio;90 u32 prio;
89 u32 dirty_prio;91 u32 dirty_prio;
drivers/gpu/drm/vmwgfx/vmwgfx_scrn.c+28−25
@@ -1,7 +1,7 @@
1// SPDX-License-Identifier: GPL-2.0 OR MIT1// SPDX-License-Identifier: GPL-2.0 OR MIT
2/**************************************************************************2/**************************************************************************
3 *3 *
4 * Copyright 2011-2022 VMware, Inc., Palo Alto, CA., USA4 * Copyright 2011-2023 VMware, Inc., Palo Alto, CA., USA
5 *5 *
6 * Permission is hereby granted, free of charge, to any person obtaining a6 * Permission is hereby granted, free of charge, to any person obtaining a
7 * copy of this software and associated documentation files (the7 * copy of this software and associated documentation files (the
@@ -25,13 +25,14 @@ · 17 unmodified lines
25 *25 *
26 **************************************************************************/26 **************************************************************************/
27 27
28#include "vmwgfx_bo.h"
29#include "vmwgfx_kms.h"
30
28#include <drm/drm_atomic.h>31#include <drm/drm_atomic.h>
29#include <drm/drm_atomic_helper.h>32#include <drm/drm_atomic_helper.h>
30#include <drm/drm_damage_helper.h>33#include <drm/drm_damage_helper.h>
31#include <drm/drm_fourcc.h>34#include <drm/drm_fourcc.h>
32 35
33#include "vmwgfx_kms.h"
34
35#define vmw_crtc_to_sou(x) \36#define vmw_crtc_to_sou(x) \
36 container_of(x, struct vmw_screen_object_unit, base.crtc)37 container_of(x, struct vmw_screen_object_unit, base.crtc)
37#define vmw_encoder_to_sou(x) \38#define vmw_encoder_to_sou(x) \
@@ -89,7 +90,7 @@ struct vmw_screen_object_unit { · 51 unmodified lines
89 struct vmw_display_unit base;90 struct vmw_display_unit base;
90 91
91 unsigned long buffer_size; /**< Size of allocated buffer */92 unsigned long buffer_size; /**< Size of allocated buffer */
92 struct vmw_buffer_object *buffer; /**< Backing store buffer */93 struct vmw_bo *buffer; /**< Backing store buffer */
93 94
94 bool defined;95 bool defined;
95};96};
@@ -148,7 +149,7 @@ static int vmw_sou_fifo_create(struct vmw_private *dev_priv, · 52 unmodified lines
148 sou->base.set_gui_y = cmd->obj.root.y;149 sou->base.set_gui_y = cmd->obj.root.y;
149 150
150 /* Ok to assume that buffer is pinned in vram */151 /* Ok to assume that buffer is pinned in vram */
151 vmw_bo_get_guest_ptr(&sou->buffer->base, &cmd->obj.backingStore.ptr);152 vmw_bo_get_guest_ptr(&sou->buffer->tbo, &cmd->obj.backingStore.ptr);
152 cmd->obj.backingStore.pitch = mode->hdisplay * 4;153 cmd->obj.backingStore.pitch = mode->hdisplay * 4;
153 154
154 vmw_cmd_commit(dev_priv, fifo_size);155 vmw_cmd_commit(dev_priv, fifo_size);
@@ -409,9 +410,13 @@ vmw_sou_primary_plane_prepare_fb(struct drm_plane *plane, · 254 unmodified lines
409 struct drm_crtc *crtc = plane->state->crtc ?: new_state->crtc;410 struct drm_crtc *crtc = plane->state->crtc ?: new_state->crtc;
410 struct vmw_plane_state *vps = vmw_plane_state_to_vps(new_state);411 struct vmw_plane_state *vps = vmw_plane_state_to_vps(new_state);
411 struct vmw_private *dev_priv;412 struct vmw_private *dev_priv;
412 size_t size;
413 int ret;413 int ret;
414 414 struct vmw_bo_params bo_params = {
415 .domain = VMW_BO_DOMAIN_VRAM,
416 .busy_domain = VMW_BO_DOMAIN_VRAM,
417 .bo_type = ttm_bo_type_device,
418 .pin = true
419 };
415 420
416 if (!new_fb) {421 if (!new_fb) {
417 vmw_bo_unreference(&vps->bo);422 vmw_bo_unreference(&vps->bo);
@@ -420,11 +425,11 @@ vmw_sou_primary_plane_prepare_fb(struct drm_plane *plane, · 2 unmodified lines
420 return 0;425 return 0;
421 }426 }
422 427
423 size = new_state->crtc_w * new_state->crtc_h * 4;428 bo_params.size = new_state->crtc_w * new_state->crtc_h * 4;
424 dev_priv = vmw_priv(crtc->dev);429 dev_priv = vmw_priv(crtc->dev);
425 430
426 if (vps->bo) {431 if (vps->bo) {
427 if (vps->bo_size == size) {432 if (vps->bo_size == bo_params.size) {
428 /*433 /*
429 * Note that this might temporarily up the pin-count434 * Note that this might temporarily up the pin-count
430 * to 2, until cleanup_fb() is called.435 * to 2, until cleanup_fb() is called.
@@ -443,16 +448,12 @@ vmw_sou_primary_plane_prepare_fb(struct drm_plane *plane, · 12 unmodified lines
443 * resume the overlays, this is preferred to failing to alloc.448 * resume the overlays, this is preferred to failing to alloc.
444 */449 */
445 vmw_overlay_pause_all(dev_priv);450 vmw_overlay_pause_all(dev_priv);
446 ret = vmw_bo_create(dev_priv, size,451 ret = vmw_bo_create(dev_priv, &bo_params, &vps->bo);
447 &vmw_vram_placement,
448 false, true, &vmw_bo_bo_free, &vps->bo);
449 vmw_overlay_resume_all(dev_priv);452 vmw_overlay_resume_all(dev_priv);
450 if (ret) {453 if (ret)
451 vps->bo = NULL; /* vmw_bo_init frees on error */
452 return ret;454 return ret;
453 }
454 455
455 vps->bo_size = size;456 vps->bo_size = bo_params.size;
456 457
457 /*458 /*
458 * TTM already thinks the buffer is pinned, but make sure the459 * TTM already thinks the buffer is pinned, but make sure the
@@ -489,7 +490,7 @@ static uint32_t vmw_sou_bo_define_gmrfb(struct vmw_du_update_plane *update, · 30 unmodified lines
489 gmr->body.format.colorDepth = depth;490 gmr->body.format.colorDepth = depth;
490 gmr->body.format.reserved = 0;491 gmr->body.format.reserved = 0;
491 gmr->body.bytesPerLine = update->vfb->base.pitches[0];492 gmr->body.bytesPerLine = update->vfb->base.pitches[0];
492 vmw_bo_get_guest_ptr(&vfbbo->buffer->base, &gmr->body.ptr);493 vmw_bo_get_guest_ptr(&vfbbo->buffer->tbo, &gmr->body.ptr);
493 494
494 return sizeof(*gmr);495 return sizeof(*gmr);
495}496}
@@ -546,7 +547,6 @@ static int vmw_sou_plane_update_bo(struct vmw_private *dev_priv, · 50 unmodified lines
546 bo_update.base.vfb = vfb;547 bo_update.base.vfb = vfb;
547 bo_update.base.out_fence = out_fence;548 bo_update.base.out_fence = out_fence;
548 bo_update.base.mutex = NULL;549 bo_update.base.mutex = NULL;
549 bo_update.base.cpu_blit = false;
550 bo_update.base.intr = true;550 bo_update.base.intr = true;
551 551
552 bo_update.base.calc_fifo_size = vmw_sou_bo_fifo_size;552 bo_update.base.calc_fifo_size = vmw_sou_bo_fifo_size;
@@ -707,7 +707,6 @@ static int vmw_sou_plane_update_surface(struct vmw_private *dev_priv, · 154 unmodified lines
707 srf_update.base.vfb = vfb;707 srf_update.base.vfb = vfb;
708 srf_update.base.out_fence = out_fence;708 srf_update.base.out_fence = out_fence;
709 srf_update.base.mutex = &dev_priv->cmdbuf_mutex;709 srf_update.base.mutex = &dev_priv->cmdbuf_mutex;
710 srf_update.base.cpu_blit = false;
711 srf_update.base.intr = true;710 srf_update.base.intr = true;
712 711
713 srf_update.base.calc_fifo_size = vmw_sou_surface_fifo_size;712 srf_update.base.calc_fifo_size = vmw_sou_surface_fifo_size;
@@ -947,7 +946,7 @@ int vmw_kms_sou_init_display(struct vmw_private *dev_priv) · 233 unmodified lines
947static int do_bo_define_gmrfb(struct vmw_private *dev_priv,946static int do_bo_define_gmrfb(struct vmw_private *dev_priv,
948 struct vmw_framebuffer *framebuffer)947 struct vmw_framebuffer *framebuffer)
949{948{
950 struct vmw_buffer_object *buf =949 struct vmw_bo *buf =
951 container_of(framebuffer, struct vmw_framebuffer_bo,950 container_of(framebuffer, struct vmw_framebuffer_bo,
952 base)->buffer;951 base)->buffer;
953 int depth = framebuffer->base.format->depth;952 int depth = framebuffer->base.format->depth;
@@ -973,7 +972,7 @@ static int do_bo_define_gmrfb(struct vmw_private *dev_priv, · 19 unmodified lines
973 cmd->body.format.reserved = 0;972 cmd->body.format.reserved = 0;
974 cmd->body.bytesPerLine = framebuffer->base.pitches[0];973 cmd->body.bytesPerLine = framebuffer->base.pitches[0];
975 /* Buffer is reserved in vram or GMR */974 /* Buffer is reserved in vram or GMR */
976 vmw_bo_get_guest_ptr(&buf->base, &cmd->body.ptr);975 vmw_bo_get_guest_ptr(&buf->tbo, &cmd->body.ptr);
977 vmw_cmd_commit(dev_priv, sizeof(*cmd));976 vmw_cmd_commit(dev_priv, sizeof(*cmd));
978 977
979 return 0;978 return 0;
@@ -1216,14 +1215,16 @@ int vmw_kms_sou_do_bo_dirty(struct vmw_private *dev_priv, · 236 unmodified lines
1216 struct vmw_fence_obj **out_fence,1215 struct vmw_fence_obj **out_fence,
1217 struct drm_crtc *crtc)1216 struct drm_crtc *crtc)
1218{1217{
1219 struct vmw_buffer_object *buf =1218 struct vmw_bo *buf =
1220 container_of(framebuffer, struct vmw_framebuffer_bo,1219 container_of(framebuffer, struct vmw_framebuffer_bo,
1221 base)->buffer;1220 base)->buffer;
1222 struct vmw_kms_dirty dirty;1221 struct vmw_kms_dirty dirty;
1223 DECLARE_VAL_CONTEXT(val_ctx, NULL, 0);1222 DECLARE_VAL_CONTEXT(val_ctx, NULL, 0);
1224 int ret;1223 int ret;
1225 1224
1226 ret = vmw_validation_add_bo(&val_ctx, buf, false, false);1225 vmw_bo_placement_set(buf, VMW_BO_DOMAIN_GMR | VMW_BO_DOMAIN_VRAM,
1226 VMW_BO_DOMAIN_GMR | VMW_BO_DOMAIN_VRAM);
1227 ret = vmw_validation_add_bo(&val_ctx, buf);
1227 if (ret)1228 if (ret)
1228 return ret;1229 return ret;
1229 1230
@@ -1323,13 +1324,15 @@ int vmw_kms_sou_readback(struct vmw_private *dev_priv, · 93 unmodified lines
1323 uint32_t num_clips,1324 uint32_t num_clips,
1324 struct drm_crtc *crtc)1325 struct drm_crtc *crtc)
1325{1326{
1326 struct vmw_buffer_object *buf =1327 struct vmw_bo *buf =
1327 container_of(vfb, struct vmw_framebuffer_bo, base)->buffer;1328 container_of(vfb, struct vmw_framebuffer_bo, base)->buffer;
1328 struct vmw_kms_dirty dirty;1329 struct vmw_kms_dirty dirty;
1329 DECLARE_VAL_CONTEXT(val_ctx, NULL, 0);1330 DECLARE_VAL_CONTEXT(val_ctx, NULL, 0);
1330 int ret;1331 int ret;
1331 1332
1332 ret = vmw_validation_add_bo(&val_ctx, buf, false, false);1333 vmw_bo_placement_set(buf, VMW_BO_DOMAIN_GMR | VMW_BO_DOMAIN_VRAM,
1334 VMW_BO_DOMAIN_GMR | VMW_BO_DOMAIN_VRAM);
1335 ret = vmw_validation_add_bo(&val_ctx, buf);
1333 if (ret)1336 if (ret)
1334 return ret;1337 return ret;
1335 1338
drivers/gpu/drm/vmwgfx/vmwgfx_shader.c+38−29
@@ -1,7 +1,7 @@
1// SPDX-License-Identifier: GPL-2.0 OR MIT1// SPDX-License-Identifier: GPL-2.0 OR MIT
2/**************************************************************************2/**************************************************************************
3 *3 *
4 * Copyright 2009-2015 VMware, Inc., Palo Alto, CA., USA4 * Copyright 2009-2023 VMware, Inc., Palo Alto, CA., USA
5 *5 *
6 * Permission is hereby granted, free of charge, to any person obtaining a6 * Permission is hereby granted, free of charge, to any person obtaining a
7 * copy of this software and associated documentation files (the7 * copy of this software and associated documentation files (the
@@ -27,9 +27,10 @@ · 19 unmodified lines
27 27
28#include <drm/ttm/ttm_placement.h>28#include <drm/ttm/ttm_placement.h>
29 29
30#include "vmwgfx_binding.h"
31#include "vmwgfx_bo.h"
30#include "vmwgfx_drv.h"32#include "vmwgfx_drv.h"
31#include "vmwgfx_resource_priv.h"33#include "vmwgfx_resource_priv.h"
32#include "vmwgfx_binding.h"
33 34
34struct vmw_shader {35struct vmw_shader {
35 struct vmw_resource res;36 struct vmw_resource res;
@@ -88,12 +89,13 @@ const struct vmw_user_resource_conv *user_shader_converter = · 52 unmodified lines
88 89
89static const struct vmw_res_func vmw_gb_shader_func = {90static const struct vmw_res_func vmw_gb_shader_func = {
90 .res_type = vmw_res_shader,91 .res_type = vmw_res_shader,
91 .needs_backup = true,92 .needs_guest_memory = true,
92 .may_evict = true,93 .may_evict = true,
93 .prio = 3,94 .prio = 3,
94 .dirty_prio = 3,95 .dirty_prio = 3,
95 .type_name = "guest backed shaders",96 .type_name = "guest backed shaders",
96 .backup_placement = &vmw_mob_placement,97 .domain = VMW_BO_DOMAIN_MOB,
98 .busy_domain = VMW_BO_DOMAIN_MOB,
97 .create = vmw_gb_shader_create,99 .create = vmw_gb_shader_create,
98 .destroy = vmw_gb_shader_destroy,100 .destroy = vmw_gb_shader_destroy,
99 .bind = vmw_gb_shader_bind,101 .bind = vmw_gb_shader_bind,
@@ -102,12 +104,13 @@ static const struct vmw_res_func vmw_gb_shader_func = { · 2 unmodified lines
102 104
103static const struct vmw_res_func vmw_dx_shader_func = {105static const struct vmw_res_func vmw_dx_shader_func = {
104 .res_type = vmw_res_shader,106 .res_type = vmw_res_shader,
105 .needs_backup = true,107 .needs_guest_memory = true,
106 .may_evict = true,108 .may_evict = true,
107 .prio = 3,109 .prio = 3,
108 .dirty_prio = 3,110 .dirty_prio = 3,
109 .type_name = "dx shaders",111 .type_name = "dx shaders",
110 .backup_placement = &vmw_mob_placement,112 .domain = VMW_BO_DOMAIN_MOB,
113 .busy_domain = VMW_BO_DOMAIN_MOB,
111 .create = vmw_dx_shader_create,114 .create = vmw_dx_shader_create,
112 /*115 /*
113 * The destroy callback is only called with a committed resource on116 * The destroy callback is only called with a committed resource on
@@ -158,7 +161,7 @@ static int vmw_gb_shader_init(struct vmw_private *dev_priv, · 44 unmodified lines
158 SVGA3dShaderType type,161 SVGA3dShaderType type,
159 uint8_t num_input_sig,162 uint8_t num_input_sig,
160 uint8_t num_output_sig,163 uint8_t num_output_sig,
161 struct vmw_buffer_object *byte_code,164 struct vmw_bo *byte_code,
162 void (*res_free) (struct vmw_resource *res))165 void (*res_free) (struct vmw_resource *res))
163{166{
164 struct vmw_shader *shader = vmw_res_to_shader(res);167 struct vmw_shader *shader = vmw_res_to_shader(res);
@@ -175,10 +178,10 @@ static int vmw_gb_shader_init(struct vmw_private *dev_priv, · 10 unmodified lines
175 return ret;178 return ret;
176 }179 }
177 180
178 res->backup_size = size;181 res->guest_memory_size = size;
179 if (byte_code) {182 if (byte_code) {
180 res->backup = vmw_bo_reference(byte_code);183 res->guest_memory_bo = vmw_bo_reference(byte_code);
181 res->backup_offset = offset;184 res->guest_memory_offset = offset;
182 }185 }
183 shader->size = size;186 shader->size = size;
184 shader->type = type;187 shader->type = type;
@@ -259,8 +262,8 @@ static int vmw_gb_shader_bind(struct vmw_resource *res, · 74 unmodified lines
259 cmd->header.size = sizeof(cmd->body);262 cmd->header.size = sizeof(cmd->body);
260 cmd->body.shid = res->id;263 cmd->body.shid = res->id;
261 cmd->body.mobid = bo->resource->start;264 cmd->body.mobid = bo->resource->start;
262 cmd->body.offsetInBytes = res->backup_offset;265 cmd->body.offsetInBytes = res->guest_memory_offset;
263 res->backup_dirty = false;266 res->guest_memory_dirty = false;
264 vmw_cmd_commit(dev_priv, sizeof(*cmd));267 vmw_cmd_commit(dev_priv, sizeof(*cmd));
265 268
266 return 0;269 return 0;
@@ -277,7 +280,7 @@ static int vmw_gb_shader_unbind(struct vmw_resource *res, · 10 unmodified lines
277 } *cmd;280 } *cmd;
278 struct vmw_fence_obj *fence;281 struct vmw_fence_obj *fence;
279 282
280 BUG_ON(res->backup->base.resource->mem_type != VMW_PL_MOB);283 BUG_ON(res->guest_memory_bo->tbo.resource->mem_type != VMW_PL_MOB);
281 284
282 cmd = VMW_CMD_RESERVE(dev_priv, sizeof(*cmd));285 cmd = VMW_CMD_RESERVE(dev_priv, sizeof(*cmd));
283 if (unlikely(cmd == NULL))286 if (unlikely(cmd == NULL))
@@ -397,8 +400,8 @@ static int vmw_dx_shader_unscrub(struct vmw_resource *res) · 113 unmodified lines
397 cmd->header.size = sizeof(cmd->body);400 cmd->header.size = sizeof(cmd->body);
398 cmd->body.cid = shader->ctx->id;401 cmd->body.cid = shader->ctx->id;
399 cmd->body.shid = shader->id;402 cmd->body.shid = shader->id;
400 cmd->body.mobid = res->backup->base.resource->start;403 cmd->body.mobid = res->guest_memory_bo->tbo.resource->start;
401 cmd->body.offsetInBytes = res->backup_offset;404 cmd->body.offsetInBytes = res->guest_memory_offset;
402 vmw_cmd_commit(dev_priv, sizeof(*cmd));405 vmw_cmd_commit(dev_priv, sizeof(*cmd));
403 406
404 vmw_cotable_add_resource(shader->cotable, &shader->cotable_head);407 vmw_cotable_add_resource(shader->cotable, &shader->cotable_head);
@@ -508,7 +511,7 @@ static int vmw_dx_shader_unbind(struct vmw_resource *res, · 103 unmodified lines
508 struct vmw_fence_obj *fence;511 struct vmw_fence_obj *fence;
509 int ret;512 int ret;
510 513
511 BUG_ON(res->backup->base.resource->mem_type != VMW_PL_MOB);514 BUG_ON(res->guest_memory_bo->tbo.resource->mem_type != VMW_PL_MOB);
512 515
513 mutex_lock(&dev_priv->binding_mutex);516 mutex_lock(&dev_priv->binding_mutex);
514 ret = vmw_dx_shader_scrub(res);517 ret = vmw_dx_shader_scrub(res);
@@ -680,7 +683,7 @@ int vmw_shader_destroy_ioctl(struct drm_device *dev, void *data, · 165 unmodified lines
680}683}
681 684
682static int vmw_user_shader_alloc(struct vmw_private *dev_priv,685static int vmw_user_shader_alloc(struct vmw_private *dev_priv,
683 struct vmw_buffer_object *buffer,686 struct vmw_bo *buffer,
684 size_t shader_size,687 size_t shader_size,
685 size_t offset,688 size_t offset,
686 SVGA3dShaderType shader_type,689 SVGA3dShaderType shader_type,
@@ -734,7 +737,7 @@ out: · 47 unmodified lines
734 737
735 738
736static struct vmw_resource *vmw_shader_alloc(struct vmw_private *dev_priv,739static struct vmw_resource *vmw_shader_alloc(struct vmw_private *dev_priv,
737 struct vmw_buffer_object *buffer,740 struct vmw_bo *buffer,
738 size_t shader_size,741 size_t shader_size,
739 size_t offset,742 size_t offset,
740 SVGA3dShaderType shader_type)743 SVGA3dShaderType shader_type)
@@ -771,7 +774,7 @@ static int vmw_shader_define(struct drm_device *dev, struct drm_file *file_priv, · 30 unmodified lines
771{774{
772 struct vmw_private *dev_priv = vmw_priv(dev);775 struct vmw_private *dev_priv = vmw_priv(dev);
773 struct ttm_object_file *tfile = vmw_fpriv(file_priv)->tfile;776 struct ttm_object_file *tfile = vmw_fpriv(file_priv)->tfile;
774 struct vmw_buffer_object *buffer = NULL;777 struct vmw_bo *buffer = NULL;
775 SVGA3dShaderType shader_type;778 SVGA3dShaderType shader_type;
776 int ret;779 int ret;
777 780
@@ -782,7 +785,7 @@ static int vmw_shader_define(struct drm_device *dev, struct drm_file *file_priv, · 4 unmodified lines
782 return ret;785 return ret;
783 }786 }
784 787
785 if ((u64)buffer->base.base.size < (u64)size + (u64)offset) {788 if ((u64)buffer->tbo.base.size < (u64)size + (u64)offset) {
786 VMW_DEBUG_USER("Illegal buffer- or shader size.\n");789 VMW_DEBUG_USER("Illegal buffer- or shader size.\n");
787 ret = -EINVAL;790 ret = -EINVAL;
788 goto out_bad_arg;791 goto out_bad_arg;
@@ -807,7 +810,7 @@ static int vmw_shader_define(struct drm_device *dev, struct drm_file *file_priv, · 18 unmodified lines
807 num_output_sig, tfile, shader_handle);810 num_output_sig, tfile, shader_handle);
808out_bad_arg:811out_bad_arg:
809 vmw_bo_unreference(&buffer);812 vmw_bo_unreference(&buffer);
810 drm_gem_object_put(&buffer->base.base);813 drm_gem_object_put(&buffer->tbo.base);
811 return ret;814 return ret;
812}815}
813 816
@@ -884,28 +887,34 @@ int vmw_compat_shader_add(struct vmw_private *dev_priv, · 70 unmodified lines
884 struct list_head *list)887 struct list_head *list)
885{888{
886 struct ttm_operation_ctx ctx = { false, true };889 struct ttm_operation_ctx ctx = { false, true };
887 struct vmw_buffer_object *buf;890 struct vmw_bo *buf;
888 struct ttm_bo_kmap_obj map;891 struct ttm_bo_kmap_obj map;
889 bool is_iomem;892 bool is_iomem;
890 int ret;893 int ret;
891 struct vmw_resource *res;894 struct vmw_resource *res;
895 struct vmw_bo_params bo_params = {
896 .domain = VMW_BO_DOMAIN_SYS,
897 .busy_domain = VMW_BO_DOMAIN_SYS,
898 .bo_type = ttm_bo_type_device,
899 .size = size,
900 .pin = true
901 };
892 902
893 if (!vmw_shader_id_ok(user_key, shader_type))903 if (!vmw_shader_id_ok(user_key, shader_type))
894 return -EINVAL;904 return -EINVAL;
895 905
896 ret = vmw_bo_create(dev_priv, size, &vmw_sys_placement,906 ret = vmw_bo_create(dev_priv, &bo_params, &buf);
897 true, true, vmw_bo_bo_free, &buf);
898 if (unlikely(ret != 0))907 if (unlikely(ret != 0))
899 goto out;908 goto out;
900 909
901 ret = ttm_bo_reserve(&buf->base, false, true, NULL);910 ret = ttm_bo_reserve(&buf->tbo, false, true, NULL);
902 if (unlikely(ret != 0))911 if (unlikely(ret != 0))
903 goto no_reserve;912 goto no_reserve;
904 913
905 /* Map and copy shader bytecode. */914 /* Map and copy shader bytecode. */
906 ret = ttm_bo_kmap(&buf->base, 0, PFN_UP(size), &map);915 ret = ttm_bo_kmap(&buf->tbo, 0, PFN_UP(size), &map);
907 if (unlikely(ret != 0)) {916 if (unlikely(ret != 0)) {
908 ttm_bo_unreserve(&buf->base);917 ttm_bo_unreserve(&buf->tbo);
909 goto no_reserve;918 goto no_reserve;
910 }919 }
911 920
@@ -913,9 +922,9 @@ int vmw_compat_shader_add(struct vmw_private *dev_priv, · 1 unmodified line
913 WARN_ON(is_iomem);922 WARN_ON(is_iomem);
914 923
915 ttm_bo_kunmap(&map);924 ttm_bo_kunmap(&map);
916 ret = ttm_bo_validate(&buf->base, &vmw_sys_placement, &ctx);925 ret = ttm_bo_validate(&buf->tbo, &buf->placement, &ctx);
917 WARN_ON(ret != 0);926 WARN_ON(ret != 0);
918 ttm_bo_unreserve(&buf->base);927 ttm_bo_unreserve(&buf->tbo);
919 928
920 res = vmw_shader_alloc(dev_priv, buf, size, 0, shader_type);929 res = vmw_shader_alloc(dev_priv, buf, size, 0, shader_type);
921 if (unlikely(ret != 0))930 if (unlikely(ret != 0))
drivers/gpu/drm/vmwgfx/vmwgfx_so.c+4−2
@@ -24,6 +24,7 @@ · 23 unmodified lines
24 *24 *
25 **************************************************************************/25 **************************************************************************/
26 26
27#include "vmwgfx_bo.h"
27#include "vmwgfx_drv.h"28#include "vmwgfx_drv.h"
28#include "vmwgfx_resource_priv.h"29#include "vmwgfx_resource_priv.h"
29#include "vmwgfx_so.h"30#include "vmwgfx_so.h"
@@ -81,10 +82,11 @@ static void vmw_view_commit_notify(struct vmw_resource *res, · 51 unmodified lines
81 82
82static const struct vmw_res_func vmw_view_func = {83static const struct vmw_res_func vmw_view_func = {
83 .res_type = vmw_res_view,84 .res_type = vmw_res_view,
84 .needs_backup = false,85 .needs_guest_memory = false,
85 .may_evict = false,86 .may_evict = false,
86 .type_name = "DX view",87 .type_name = "DX view",
87 .backup_placement = NULL,88 .domain = VMW_BO_DOMAIN_SYS,
89 .busy_domain = VMW_BO_DOMAIN_SYS,
88 .create = vmw_view_create,90 .create = vmw_view_create,
89 .commit_notify = vmw_view_commit_notify,91 .commit_notify = vmw_view_commit_notify,
90};92};
drivers/gpu/drm/vmwgfx/vmwgfx_stdu.c+45−278
@@ -1,7 +1,7 @@
1// SPDX-License-Identifier: GPL-2.0 OR MIT1// SPDX-License-Identifier: GPL-2.0 OR MIT
2/******************************************************************************2/******************************************************************************
3 *3 *
4 * COPYRIGHT (C) 2014-2022 VMware, Inc., Palo Alto, CA., USA4 * COPYRIGHT (C) 2014-2023 VMware, Inc., Palo Alto, CA., USA
5 *5 *
6 * Permission is hereby granted, free of charge, to any person obtaining a6 * Permission is hereby granted, free of charge, to any person obtaining a
7 * copy of this software and associated documentation files (the7 * copy of this software and associated documentation files (the
@@ -25,14 +25,15 @@ · 17 unmodified lines
25 *25 *
26 ******************************************************************************/26 ******************************************************************************/
27 27
28#include "vmwgfx_bo.h"
29#include "vmwgfx_kms.h"
30#include "vmw_surface_cache.h"
31
28#include <drm/drm_atomic.h>32#include <drm/drm_atomic.h>
29#include <drm/drm_atomic_helper.h>33#include <drm/drm_atomic_helper.h>
30#include <drm/drm_damage_helper.h>34#include <drm/drm_damage_helper.h>
31#include <drm/drm_fourcc.h>35#include <drm/drm_fourcc.h>
32 36
33#include "vmwgfx_kms.h"
34#include "vmw_surface_cache.h"
35
36#define vmw_crtc_to_stdu(x) \37#define vmw_crtc_to_stdu(x) \
37 container_of(x, struct vmw_screen_target_display_unit, base.crtc)38 container_of(x, struct vmw_screen_target_display_unit, base.crtc)
38#define vmw_encoder_to_stdu(x) \39#define vmw_encoder_to_stdu(x) \
@@ -65,12 +66,11 @@ enum stdu_content_type { · 26 unmodified lines
65 */66 */
66struct vmw_stdu_dirty {67struct vmw_stdu_dirty {
67 struct vmw_kms_dirty base;68 struct vmw_kms_dirty base;
68 SVGA3dTransferType transfer;
69 s32 left, right, top, bottom;69 s32 left, right, top, bottom;
70 s32 fb_left, fb_top;70 s32 fb_left, fb_top;
71 u32 pitch;71 u32 pitch;
72 union {72 union {
73 struct vmw_buffer_object *buf;73 struct vmw_bo *buf;
74 u32 sid;74 u32 sid;
75 };75 };
76};76};
@@ -136,12 +136,6 @@ static void vmw_stdu_destroy(struct vmw_screen_target_display_unit *stdu); · 59 unmodified lines
136 * Screen Target Display Unit CRTC Functions136 * Screen Target Display Unit CRTC Functions
137 *****************************************************************************/137 *****************************************************************************/
138 138
139static bool vmw_stdu_use_cpu_blit(const struct vmw_private *vmw)
140{
141 return !(vmw->capabilities & SVGA_CAP_3D) || vmw->vram_size < (32 * 1024 * 1024);
142}
143
144
145/**139/**
146 * vmw_stdu_crtc_destroy - cleans up the STDU140 * 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 */
461static 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 */
496static void vmw_stdu_bo_fifo_commit(struct vmw_kms_dirty *dirty)
497{
498 struct vmw_stdu_dirty *ddirty =
499 container_of(dirty, struct vmw_stdu_dirty, base);
500 struct vmw_screen_target_display_unit *stdu =
501 container_of(dirty->unit, typeof(*stdu), base);
502 struct vmw_stdu_dma *cmd = dirty->cmd;
503 struct SVGA3dCopyBox *blit = (struct SVGA3dCopyBox *) &cmd[1];
504 SVGA3dCmdSurfaceDMASuffix *suffix =
505 (SVGA3dCmdSurfaceDMASuffix *) &blit[dirty->num_hits];
506 size_t blit_size = sizeof(*blit) * dirty->num_hits + sizeof(*suffix);
507
508 if (!dirty->num_hits) {
509 vmw_cmd_commit(dirty->dev_priv, 0);
510 return;
511 }
512
513 cmd->header.id = SVGA_3D_CMD_SURFACE_DMA;
514 cmd->header.size = sizeof(cmd->body) + blit_size;
515 vmw_bo_get_guest_ptr(&ddirty->buf->base, &cmd->body.guest.ptr);
516 cmd->body.guest.pitch = ddirty->pitch;
517 cmd->body.host.sid = stdu->display_srf->res.id;
518 cmd->body.host.face = 0;
519 cmd->body.host.mipmap = 0;
520 cmd->body.transfer = ddirty->transfer;
521 suffix->suffixSize = sizeof(*suffix);
522 suffix->maximumOffset = ddirty->buf->base.base.size;
523
524 if (ddirty->transfer == SVGA3D_WRITE_HOST_VRAM) {
525 blit_size += sizeof(struct vmw_stdu_update);
526
527 vmw_stdu_populate_update(&suffix[1], stdu->base.unit,
528 ddirty->left, ddirty->right,
529 ddirty->top, ddirty->bottom);
530 }
531
532 vmw_cmd_commit(dirty->dev_priv, sizeof(*cmd) + blit_size);
533
534 stdu->display_srf->res.res_dirty = true;
535 ddirty->left = ddirty->top = S32_MAX;
536 ddirty->right = ddirty->bottom = S32_MIN;
537}
538
539
540/**447/**
541 * vmw_stdu_bo_cpu_clip - Callback to encode a CPU blit448 * vmw_stdu_bo_cpu_clip - Callback to encode a CPU blit
542 *449 *
@@ -597,62 +504,21 @@ static void vmw_stdu_bo_cpu_commit(struct vmw_kms_dirty *dirty) · 54 unmodified lines
597 return;504 return;
598 505
599 /* Assume we are blitting from Guest (bo) to Host (display_srf) */506 /* Assume we are blitting from Guest (bo) to Host (display_srf) */
600 dst_pitch = stdu->display_srf->metadata.base_size.width * stdu->cpp;507 src_pitch = stdu->display_srf->metadata.base_size.width * stdu->cpp;
601 dst_bo = &stdu->display_srf->res.backup->base;508 src_bo = &stdu->display_srf->res.guest_memory_bo->tbo;
602 dst_offset = ddirty->top * dst_pitch + ddirty->left * stdu->cpp;509 src_offset = ddirty->top * dst_pitch + ddirty->left * stdu->cpp;
603 510
604 src_pitch = ddirty->pitch;511 dst_pitch = ddirty->pitch;
605 src_bo = &ddirty->buf->base;512 dst_bo = &ddirty->buf->tbo;
606 src_offset = ddirty->fb_top * src_pitch + ddirty->fb_left * stdu->cpp;513 dst_offset = ddirty->fb_top * src_pitch + ddirty->fb_left * stdu->cpp;
607
608 /* Swap src and dst if the assumption was wrong. */
609 if (ddirty->transfer != SVGA3D_WRITE_HOST_VRAM) {
610 swap(dst_pitch, src_pitch);
611 swap(dst_bo, src_bo);
612 swap(src_offset, dst_offset);
613 }
614 514
615 (void) vmw_bo_cpu_blit(dst_bo, dst_offset, dst_pitch,515 (void) vmw_bo_cpu_blit(dst_bo, dst_offset, dst_pitch,
616 src_bo, src_offset, src_pitch,516 src_bo, src_offset, src_pitch,
617 width * stdu->cpp, height, &diff);517 width * stdu->cpp, height, &diff);
618
619 if (ddirty->transfer == SVGA3D_WRITE_HOST_VRAM &&
620 drm_rect_visible(&diff.rect)) {
621 struct vmw_private *dev_priv;
622 struct vmw_stdu_update *cmd;
623 struct drm_clip_rect region;
624 int ret;
625
626 /* We are updating the actual surface, not a proxy */
627 region.x1 = diff.rect.x1;
628 region.x2 = diff.rect.x2;
629 region.y1 = diff.rect.y1;
630 region.y2 = diff.rect.y2;
631 ret = vmw_kms_update_proxy(&stdu->display_srf->res, &region,
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
649out_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 backed521 * vmw_kms_stdu_readback - Perform a readback from a buffer-object backed
656 * framebuffer and the screen target system.522 * framebuffer and the screen target system.
657 *523 *
658 * @dev_priv: Pointer to the device private structure.524 * @dev_priv: Pointer to the device private structure.
@@ -665,9 +531,6 @@ out_cleanup: · 6 unmodified lines
665 * be NULL.531 * be NULL.
666 * @num_clips: Number of clip rects in @clips or @vclips.532 * @num_clips: Number of clip rects in @clips or @vclips.
667 * @increment: Increment to use when looping over @clips or @vclips.533 * @increment: Increment to use when looping over @clips or @vclips.
668 * @to_surface: Whether to DMA to the screen target system as opposed to
669 * from the screen target system.
670 * @interruptible: Whether to perform waits interruptible if possible.
671 * @crtc: If crtc is passed, perform stdu dma on that crtc only.534 * @crtc: If crtc is passed, perform stdu dma on that crtc only.
672 *535 *
673 * If DMA-ing till the screen target system, the function will also notify536 * If DMA-ing till the screen target system, the function will also notify
@@ -676,59 +539,49 @@ out_cleanup: · 2 unmodified lines
676 * Returns 0 on success, negative error code on failure. -ERESTARTSYS if539 * Returns 0 on success, negative error code on failure. -ERESTARTSYS if
677 * interrupted.540 * interrupted.
678 */541 */
679int vmw_kms_stdu_dma(struct vmw_private *dev_priv,542int vmw_kms_stdu_readback(struct vmw_private *dev_priv,
680 struct drm_file *file_priv,543 struct drm_file *file_priv,
681 struct vmw_framebuffer *vfb,544 struct vmw_framebuffer *vfb,
682 struct drm_vmw_fence_rep __user *user_fence_rep,545 struct drm_vmw_fence_rep __user *user_fence_rep,
683 struct drm_clip_rect *clips,546 struct drm_clip_rect *clips,
684 struct drm_vmw_rect *vclips,547 struct drm_vmw_rect *vclips,
685 uint32_t num_clips,548 uint32_t num_clips,
686 int increment,549 int increment,
687 bool to_surface,550 struct drm_crtc *crtc)
688 bool interruptible,
689 struct drm_crtc *crtc)
690{551{
691 struct vmw_buffer_object *buf =552 struct vmw_bo *buf =
692 container_of(vfb, struct vmw_framebuffer_bo, base)->buffer;553 container_of(vfb, struct vmw_framebuffer_bo, base)->buffer;
693 struct vmw_stdu_dirty ddirty;554 struct vmw_stdu_dirty ddirty;
694 int ret;555 int ret;
695 bool cpu_blit = vmw_stdu_use_cpu_blit(dev_priv);
696 DECLARE_VAL_CONTEXT(val_ctx, NULL, 0);556 DECLARE_VAL_CONTEXT(val_ctx, NULL, 0);
697 557
698 /*558 /*
699 * VMs without 3D support don't have the surface DMA command and559 * The GMR domain might seem confusing because it might seem like it should
700 * we'll be using a CPU blit, and the framebuffer should be moved out560 * never happen with screen targets but e.g. the xorg vmware driver issues
701 * of VRAM.561 * CMD_SURFACE_DMA for various pixmap updates which might transition our bo to
562 * a GMR. Instead of forcing another transition we can optimize the readback
563 * by reading directly from the GMR.
702 */564 */
703 ret = vmw_validation_add_bo(&val_ctx, buf, false, cpu_blit);565 vmw_bo_placement_set(buf,
566 VMW_BO_DOMAIN_MOB | VMW_BO_DOMAIN_SYS | VMW_BO_DOMAIN_GMR,
567 VMW_BO_DOMAIN_MOB | VMW_BO_DOMAIN_SYS | VMW_BO_DOMAIN_GMR);
568 ret = vmw_validation_add_bo(&val_ctx, buf);
704 if (ret)569 if (ret)
705 return ret;570 return ret;
706 571
707 ret = vmw_validation_prepare(&val_ctx, NULL, interruptible);572 ret = vmw_validation_prepare(&val_ctx, NULL, true);
708 if (ret)573 if (ret)
709 goto out_unref;574 goto out_unref;
710 575
711 ddirty.transfer = (to_surface) ? SVGA3D_WRITE_HOST_VRAM :
712 SVGA3D_READ_HOST_VRAM;
713 ddirty.left = ddirty.top = S32_MAX;576 ddirty.left = ddirty.top = S32_MAX;
714 ddirty.right = ddirty.bottom = S32_MIN;577 ddirty.right = ddirty.bottom = S32_MIN;
715 ddirty.fb_left = ddirty.fb_top = S32_MAX;578 ddirty.fb_left = ddirty.fb_top = S32_MAX;
716 ddirty.pitch = vfb->base.pitches[0];579 ddirty.pitch = vfb->base.pitches[0];
717 ddirty.buf = buf;580 ddirty.buf = buf;
718 ddirty.base.fifo_commit = vmw_stdu_bo_fifo_commit;581
719 ddirty.base.clip = vmw_stdu_bo_clip;582 ddirty.base.fifo_commit = vmw_stdu_bo_cpu_commit;
720 ddirty.base.fifo_reserve_size = sizeof(struct vmw_stdu_dma) +583 ddirty.base.clip = vmw_stdu_bo_cpu_clip;
721 num_clips * sizeof(SVGA3dCopyBox) +584 ddirty.base.fifo_reserve_size = 0;
722 sizeof(SVGA3dCmdSurfaceDMASuffix);
723 if (to_surface)
724 ddirty.base.fifo_reserve_size += sizeof(struct vmw_stdu_update);
725
726
727 if (cpu_blit) {
728 ddirty.base.fifo_commit = vmw_stdu_bo_cpu_commit;
729 ddirty.base.clip = vmw_stdu_bo_cpu_clip;
730 ddirty.base.fifo_reserve_size = 0;
731 }
732 585
733 ddirty.base.crtc = crtc;586 ddirty.base.crtc = crtc;
734 587
@@ -1160,11 +1013,8 @@ vmw_stdu_primary_plane_prepare_fb(struct drm_plane *plane, · 425 unmodified lines
1160 /*1013 /*
1161 * This should only happen if the buffer object is too large to create a1014 * This should only happen if the buffer object is too large to create a
1162 * proxy surface for.1015 * proxy surface for.
1163 * If we are a 2D VM with a buffer object then we have to use CPU blit
1164 * so cache these mappings
1165 */1016 */
1166 if (vps->content_fb_type == SEPARATE_BO &&1017 if (vps->content_fb_type == SEPARATE_BO)
1167 vmw_stdu_use_cpu_blit(dev_priv))
1168 vps->cpp = new_fb->pitches[0] / new_fb->width;1018 vps->cpp = new_fb->pitches[0] / new_fb->width;
1169 1019
1170 return 0;1020 return 0;
@@ -1174,14 +1024,6 @@ out_srf_unref: · 3 unmodified lines
1174 return ret;1024 return ret;
1175}1025}
1176 1026
1177static 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
1185static uint32_t vmw_stdu_bo_fifo_size_cpu(struct vmw_du_update_plane *update,1027static uint32_t vmw_stdu_bo_fifo_size_cpu(struct vmw_du_update_plane *update,
1186 uint32_t num_hits)1028 uint32_t num_hits)
1187{1029{
@@ -1189,68 +1031,6 @@ static uint32_t vmw_stdu_bo_fifo_size_cpu(struct vmw_du_update_plane *update, · 1 unmodified line
1189 sizeof(struct vmw_stdu_update);1031 sizeof(struct vmw_stdu_update);
1190}1032}
1191 1033
1192static 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
1216static 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
1235static 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
1254static uint32_t vmw_stdu_bo_pre_clip_cpu(struct vmw_du_update_plane *update,1034static uint32_t vmw_stdu_bo_pre_clip_cpu(struct vmw_du_update_plane *update,
1255 void *cmd, uint32_t num_hits)1035 void *cmd, uint32_t num_hits)
1256{1036{
@@ -1300,11 +1080,11 @@ vmw_stdu_bo_populate_update_cpu(struct vmw_du_update_plane *update, void *cmd, · 43 unmodified lines
1300 1080
1301 diff.cpp = stdu->cpp;1081 diff.cpp = stdu->cpp;
1302 1082
1303 dst_bo = &stdu->display_srf->res.backup->base;1083 dst_bo = &stdu->display_srf->res.guest_memory_bo->tbo;
1304 dst_pitch = stdu->display_srf->metadata.base_size.width * stdu->cpp;1084 dst_pitch = stdu->display_srf->metadata.base_size.width * stdu->cpp;
1305 dst_offset = bb->y1 * dst_pitch + bb->x1 * stdu->cpp;1085 dst_offset = bb->y1 * dst_pitch + bb->x1 * stdu->cpp;
1306 1086
1307 src_bo = &vfbbo->buffer->base;1087 src_bo = &vfbbo->buffer->tbo;
1308 src_pitch = update->vfb->base.pitches[0];1088 src_pitch = update->vfb->base.pitches[0];
1309 src_offset = bo_update->fb_top * src_pitch + bo_update->fb_left *1089 src_offset = bo_update->fb_top * src_pitch + bo_update->fb_left *
1310 stdu->cpp;1090 stdu->cpp;
@@ -1368,24 +1148,12 @@ static int vmw_stdu_plane_update_bo(struct vmw_private *dev_priv, · 57 unmodified lines
1368 bo_update.base.vfb = vfb;1148 bo_update.base.vfb = vfb;
1369 bo_update.base.out_fence = out_fence;1149 bo_update.base.out_fence = out_fence;
1370 bo_update.base.mutex = NULL;1150 bo_update.base.mutex = NULL;
1371 bo_update.base.cpu_blit = vmw_stdu_use_cpu_blit(dev_priv);
1372 bo_update.base.intr = false;1151 bo_update.base.intr = false;
1373 1152
1374 /*1153 bo_update.base.calc_fifo_size = vmw_stdu_bo_fifo_size_cpu;
1375 * VM without 3D support don't have surface DMA command and framebuffer1154 bo_update.base.pre_clip = vmw_stdu_bo_pre_clip_cpu;
1376 * should be moved out of VRAM.1155 bo_update.base.clip = vmw_stdu_bo_clip_cpu;
1377 */1156 bo_update.base.post_clip = vmw_stdu_bo_populate_update_cpu;
1378 if (bo_update.base.cpu_blit) {
1379 bo_update.base.calc_fifo_size = vmw_stdu_bo_fifo_size_cpu;
1380 bo_update.base.pre_clip = vmw_stdu_bo_pre_clip_cpu;
1381 bo_update.base.clip = vmw_stdu_bo_clip_cpu;
1382 bo_update.base.post_clip = vmw_stdu_bo_populate_update_cpu;
1383 } else {
1384 bo_update.base.calc_fifo_size = vmw_stdu_bo_fifo_size;
1385 bo_update.base.pre_clip = vmw_stdu_bo_populate_dma;
1386 bo_update.base.clip = vmw_stdu_bo_populate_clip;
1387 bo_update.base.post_clip = vmw_stdu_bo_populate_update;
1388 }
1389 1157
1390 return vmw_du_helper_plane_update(&bo_update.base);1158 return vmw_du_helper_plane_update(&bo_update.base);
1391}1159}
@@ -1548,7 +1316,6 @@ static int vmw_stdu_plane_update_surface(struct vmw_private *dev_priv, · 156 unmodified lines
1548 srf_update.vfb = vfb;1316 srf_update.vfb = vfb;
1549 srf_update.out_fence = out_fence;1317 srf_update.out_fence = out_fence;
1550 srf_update.mutex = &dev_priv->cmdbuf_mutex;1318 srf_update.mutex = &dev_priv->cmdbuf_mutex;
1551 srf_update.cpu_blit = false;
1552 srf_update.intr = true;1319 srf_update.intr = true;
1553 1320
1554 if (vfbs->is_bo_proxy)1321 if (vfbs->is_bo_proxy)
drivers/gpu/drm/vmwgfx/vmwgfx_streamoutput.c+11−9
@@ -1,7 +1,7 @@
1// SPDX-License-Identifier: GPL-2.0 OR MIT1// SPDX-License-Identifier: GPL-2.0 OR MIT
2/**************************************************************************2/**************************************************************************
3 *3 *
4 * Copyright © 2018-2019 VMware, Inc., Palo Alto, CA., USA4 * Copyright © 2018-2023 VMware, Inc., Palo Alto, CA., USA
5 * All Rights Reserved.5 * All Rights Reserved.
6 *6 *
7 * Permission is hereby granted, free of charge, to any person obtaining a7 * Permission is hereby granted, free of charge, to any person obtaining a
@@ -26,11 +26,12 @@ · 18 unmodified lines
26 *26 *
27 **************************************************************************/27 **************************************************************************/
28 28
29#include <drm/ttm/ttm_placement.h>29#include "vmwgfx_binding.h"
30 30#include "vmwgfx_bo.h"
31#include "vmwgfx_drv.h"31#include "vmwgfx_drv.h"
32#include "vmwgfx_resource_priv.h"32#include "vmwgfx_resource_priv.h"
33#include "vmwgfx_binding.h"33
34#include <drm/ttm/ttm_placement.h>
34 35
35/**36/**
36 * struct vmw_dx_streamoutput - Streamoutput resource metadata.37 * struct vmw_dx_streamoutput - Streamoutput resource metadata.
@@ -62,10 +63,11 @@ static void vmw_dx_streamoutput_commit_notify(struct vmw_resource *res, · 25 unmodified lines
62 63
63static const struct vmw_res_func vmw_dx_streamoutput_func = {64static const struct vmw_res_func vmw_dx_streamoutput_func = {
64 .res_type = vmw_res_streamoutput,65 .res_type = vmw_res_streamoutput,
65 .needs_backup = true,66 .needs_guest_memory = true,
66 .may_evict = false,67 .may_evict = false,
67 .type_name = "DX streamoutput",68 .type_name = "DX streamoutput",
68 .backup_placement = &vmw_mob_placement,69 .domain = VMW_BO_DOMAIN_MOB,
70 .busy_domain = VMW_BO_DOMAIN_MOB,
69 .create = vmw_dx_streamoutput_create,71 .create = vmw_dx_streamoutput_create,
70 .destroy = NULL, /* Command buffer managed resource. */72 .destroy = NULL, /* Command buffer managed resource. */
71 .bind = vmw_dx_streamoutput_bind,73 .bind = vmw_dx_streamoutput_bind,
@@ -104,8 +106,8 @@ static int vmw_dx_streamoutput_unscrub(struct vmw_resource *res) · 32 unmodified lines
104 cmd->header.id = SVGA_3D_CMD_DX_BIND_STREAMOUTPUT;106 cmd->header.id = SVGA_3D_CMD_DX_BIND_STREAMOUTPUT;
105 cmd->header.size = sizeof(cmd->body);107 cmd->header.size = sizeof(cmd->body);
106 cmd->body.soid = so->id;108 cmd->body.soid = so->id;
107 cmd->body.mobid = res->backup->base.resource->start;109 cmd->body.mobid = res->guest_memory_bo->tbo.resource->start;
108 cmd->body.offsetInBytes = res->backup_offset;110 cmd->body.offsetInBytes = res->guest_memory_offset;
109 cmd->body.sizeInBytes = so->size;111 cmd->body.sizeInBytes = so->size;
110 vmw_cmd_commit(dev_priv, sizeof(*cmd));112 vmw_cmd_commit(dev_priv, sizeof(*cmd));
111 113
@@ -195,7 +197,7 @@ static int vmw_dx_streamoutput_unbind(struct vmw_resource *res, bool readback, · 83 unmodified lines
195 struct vmw_fence_obj *fence;197 struct vmw_fence_obj *fence;
196 int ret;198 int ret;
197 199
198 if (WARN_ON(res->backup->base.resource->mem_type != VMW_PL_MOB))200 if (WARN_ON(res->guest_memory_bo->tbo.resource->mem_type != VMW_PL_MOB))
199 return -EINVAL;201 return -EINVAL;
200 202
201 mutex_lock(&dev_priv->binding_mutex);203 mutex_lock(&dev_priv->binding_mutex);
drivers/gpu/drm/vmwgfx/vmwgfx_surface.c+55−52
@@ -1,7 +1,7 @@
1// SPDX-License-Identifier: GPL-2.0 OR MIT1// SPDX-License-Identifier: GPL-2.0 OR MIT
2/**************************************************************************2/**************************************************************************
3 *3 *
4 * Copyright 2009-2015 VMware, Inc., Palo Alto, CA., USA4 * Copyright 2009-2023 VMware, Inc., Palo Alto, CA., USA
5 *5 *
6 * Permission is hereby granted, free of charge, to any person obtaining a6 * Permission is hereby granted, free of charge, to any person obtaining a
7 * copy of this software and associated documentation files (the7 * copy of this software and associated documentation files (the
@@ -25,8 +25,7 @@ · 17 unmodified lines
25 *25 *
26 **************************************************************************/26 **************************************************************************/
27 27
28#include <drm/ttm/ttm_placement.h>28#include "vmwgfx_bo.h"
29
30#include "vmwgfx_drv.h"29#include "vmwgfx_drv.h"
31#include "vmwgfx_resource_priv.h"30#include "vmwgfx_resource_priv.h"
32#include "vmwgfx_so.h"31#include "vmwgfx_so.h"
@@ -34,6 +33,8 @@ · 1 unmodified line
34#include "vmw_surface_cache.h"33#include "vmw_surface_cache.h"
35#include "device_include/svga3d_surfacedefs.h"34#include "device_include/svga3d_surfacedefs.h"
36 35
36#include <drm/ttm/ttm_placement.h>
37
37#define SVGA3D_FLAGS_64(upper32, lower32) (((uint64_t)upper32 << 32) | lower32)38#define SVGA3D_FLAGS_64(upper32, lower32) (((uint64_t)upper32 << 32) | lower32)
38#define SVGA3D_FLAGS_UPPER_32(svga3d_flags) (svga3d_flags >> 32)39#define SVGA3D_FLAGS_UPPER_32(svga3d_flags) (svga3d_flags >> 32)
39#define SVGA3D_FLAGS_LOWER_32(svga3d_flags) \40#define SVGA3D_FLAGS_LOWER_32(svga3d_flags) \
@@ -125,12 +126,13 @@ const struct vmw_user_resource_conv *user_surface_converter = · 85 unmodified lines
125 126
126static const struct vmw_res_func vmw_legacy_surface_func = {127static const struct vmw_res_func vmw_legacy_surface_func = {
127 .res_type = vmw_res_surface,128 .res_type = vmw_res_surface,
128 .needs_backup = false,129 .needs_guest_memory = false,
129 .may_evict = true,130 .may_evict = true,
130 .prio = 1,131 .prio = 1,
131 .dirty_prio = 1,132 .dirty_prio = 1,
132 .type_name = "legacy surfaces",133 .type_name = "legacy surfaces",
133 .backup_placement = &vmw_srf_placement,134 .domain = VMW_BO_DOMAIN_GMR,
135 .busy_domain = VMW_BO_DOMAIN_GMR | VMW_BO_DOMAIN_VRAM,
134 .create = &vmw_legacy_srf_create,136 .create = &vmw_legacy_srf_create,
135 .destroy = &vmw_legacy_srf_destroy,137 .destroy = &vmw_legacy_srf_destroy,
136 .bind = &vmw_legacy_srf_bind,138 .bind = &vmw_legacy_srf_bind,
@@ -139,12 +141,13 @@ static const struct vmw_res_func vmw_legacy_surface_func = { · 2 unmodified lines
139 141
140static const struct vmw_res_func vmw_gb_surface_func = {142static const struct vmw_res_func vmw_gb_surface_func = {
141 .res_type = vmw_res_surface,143 .res_type = vmw_res_surface,
142 .needs_backup = true,144 .needs_guest_memory = true,
143 .may_evict = true,145 .may_evict = true,
144 .prio = 1,146 .prio = 1,
145 .dirty_prio = 2,147 .dirty_prio = 2,
146 .type_name = "guest backed surfaces",148 .type_name = "guest backed surfaces",
147 .backup_placement = &vmw_mob_placement,149 .domain = VMW_BO_DOMAIN_MOB,
150 .busy_domain = VMW_BO_DOMAIN_MOB,
148 .create = vmw_gb_surface_create,151 .create = vmw_gb_surface_create,
149 .destroy = vmw_gb_surface_destroy,152 .destroy = vmw_gb_surface_destroy,
150 .bind = vmw_gb_surface_bind,153 .bind = vmw_gb_surface_bind,
@@ -379,7 +382,7 @@ static void vmw_hw_surface_destroy(struct vmw_resource *res) · 228 unmodified lines
379 */382 */
380 383
381 mutex_lock(&dev_priv->cmdbuf_mutex);384 mutex_lock(&dev_priv->cmdbuf_mutex);
382 dev_priv->used_memory_size -= res->backup_size;385 dev_priv->used_memory_size -= res->guest_memory_size;
383 mutex_unlock(&dev_priv->cmdbuf_mutex);386 mutex_unlock(&dev_priv->cmdbuf_mutex);
384 }387 }
385}388}
@@ -409,7 +412,7 @@ static int vmw_legacy_srf_create(struct vmw_resource *res) · 23 unmodified lines
409 return 0;412 return 0;
410 413
411 srf = vmw_res_to_srf(res);414 srf = vmw_res_to_srf(res);
412 if (unlikely(dev_priv->used_memory_size + res->backup_size >=415 if (unlikely(dev_priv->used_memory_size + res->guest_memory_size >=
413 dev_priv->memory_size))416 dev_priv->memory_size))
414 return -EBUSY;417 return -EBUSY;
415 418
@@ -447,7 +450,7 @@ static int vmw_legacy_srf_create(struct vmw_resource *res) · 31 unmodified lines
447 * Surface memory usage accounting.450 * Surface memory usage accounting.
448 */451 */
449 452
450 dev_priv->used_memory_size += res->backup_size;453 dev_priv->used_memory_size += res->guest_memory_size;
451 return 0;454 return 0;
452 455
453out_no_fifo:456out_no_fifo:
@@ -524,7 +527,7 @@ static int vmw_legacy_srf_dma(struct vmw_resource *res, · 70 unmodified lines
524static int vmw_legacy_srf_bind(struct vmw_resource *res,527static int vmw_legacy_srf_bind(struct vmw_resource *res,
525 struct ttm_validate_buffer *val_buf)528 struct ttm_validate_buffer *val_buf)
526{529{
527 if (!res->backup_dirty)530 if (!res->guest_memory_dirty)
528 return 0;531 return 0;
529 532
530 return vmw_legacy_srf_dma(res, val_buf, true);533 return vmw_legacy_srf_dma(res, val_buf, true);
@@ -583,7 +586,7 @@ static int vmw_legacy_srf_destroy(struct vmw_resource *res) · 52 unmodified lines
583 * Surface memory usage accounting.586 * Surface memory usage accounting.
584 */587 */
585 588
586 dev_priv->used_memory_size -= res->backup_size;589 dev_priv->used_memory_size -= res->guest_memory_size;
587 590
588 /*591 /*
589 * Release the surface ID.592 * Release the surface ID.
@@ -683,8 +686,8 @@ static void vmw_user_surface_base_release(struct ttm_base_object **p_base) · 93 unmodified lines
683 container_of(base, struct vmw_user_surface, prime.base);686 container_of(base, struct vmw_user_surface, prime.base);
684 struct vmw_resource *res = &user_srf->srf.res;687 struct vmw_resource *res = &user_srf->srf.res;
685 688
686 if (res && res->backup)689 if (res->guest_memory_bo)
687 drm_gem_object_put(&res->backup->base.base);690 drm_gem_object_put(&res->guest_memory_bo->tbo.base);
688 691
689 *p_base = NULL;692 *p_base = NULL;
690 vmw_resource_unreference(&res);693 vmw_resource_unreference(&res);
@@ -812,7 +815,7 @@ int vmw_surface_define_ioctl(struct drm_device *dev, void *data, · 121 unmodified lines
812 ++cur_size;815 ++cur_size;
813 }816 }
814 }817 }
815 res->backup_size = cur_bo_offset;818 res->guest_memory_size = cur_bo_offset;
816 if (metadata->scanout &&819 if (metadata->scanout &&
817 metadata->num_sizes == 1 &&820 metadata->num_sizes == 1 &&
818 metadata->sizes[0].width == VMW_CURSOR_SNOOP_WIDTH &&821 metadata->sizes[0].width == VMW_CURSOR_SNOOP_WIDTH &&
@@ -856,14 +859,14 @@ int vmw_surface_define_ioctl(struct drm_device *dev, void *data, · 37 unmodified lines
856 859
857 ret = vmw_gem_object_create_with_handle(dev_priv,860 ret = vmw_gem_object_create_with_handle(dev_priv,
858 file_priv,861 file_priv,
859 res->backup_size,862 res->guest_memory_size,
860 &backup_handle,863 &backup_handle,
861 &res->backup);864 &res->guest_memory_bo);
862 if (unlikely(ret != 0)) {865 if (unlikely(ret != 0)) {
863 vmw_resource_unreference(&res);866 vmw_resource_unreference(&res);
864 goto out_unlock;867 goto out_unlock;
865 }868 }
866 vmw_bo_reference(res->backup);869 vmw_bo_reference(res->guest_memory_bo);
867 /*870 /*
868 * We don't expose the handle to the userspace and surface871 * We don't expose the handle to the userspace and surface
869 * already holds a gem reference872 * already holds a gem reference
@@ -872,7 +875,7 @@ int vmw_surface_define_ioctl(struct drm_device *dev, void *data, · 2 unmodified lines
872 }875 }
873 876
874 tmp = vmw_resource_reference(&srf->res);877 tmp = vmw_resource_reference(&srf->res);
875 ret = ttm_prime_object_init(tfile, res->backup_size, &user_srf->prime,878 ret = ttm_prime_object_init(tfile, res->guest_memory_size, &user_srf->prime,
876 req->shareable, VMW_RES_SURFACE,879 req->shareable, VMW_RES_SURFACE,
877 &vmw_user_surface_base_release);880 &vmw_user_surface_base_release);
878 881
@@ -1186,7 +1189,7 @@ static int vmw_gb_surface_bind(struct vmw_resource *res, · 307 unmodified lines
1186 1189
1187 BUG_ON(bo->resource->mem_type != VMW_PL_MOB);1190 BUG_ON(bo->resource->mem_type != VMW_PL_MOB);
1188 1191
1189 submit_size = sizeof(*cmd1) + (res->backup_dirty ? sizeof(*cmd2) : 0);1192 submit_size = sizeof(*cmd1) + (res->guest_memory_dirty ? sizeof(*cmd2) : 0);
1190 1193
1191 cmd1 = VMW_CMD_RESERVE(dev_priv, submit_size);1194 cmd1 = VMW_CMD_RESERVE(dev_priv, submit_size);
1192 if (unlikely(!cmd1))1195 if (unlikely(!cmd1))
@@ -1196,7 +1199,7 @@ static int vmw_gb_surface_bind(struct vmw_resource *res, · 3 unmodified lines
1196 cmd1->header.size = sizeof(cmd1->body);1199 cmd1->header.size = sizeof(cmd1->body);
1197 cmd1->body.sid = res->id;1200 cmd1->body.sid = res->id;
1198 cmd1->body.mobid = bo->resource->start;1201 cmd1->body.mobid = bo->resource->start;
1199 if (res->backup_dirty) {1202 if (res->guest_memory_dirty) {
1200 cmd2 = (void *) &cmd1[1];1203 cmd2 = (void *) &cmd1[1];
1201 cmd2->header.id = SVGA_3D_CMD_UPDATE_GB_SURFACE;1204 cmd2->header.id = SVGA_3D_CMD_UPDATE_GB_SURFACE;
1202 cmd2->header.size = sizeof(cmd2->body);1205 cmd2->header.size = sizeof(cmd2->body);
@@ -1204,12 +1207,12 @@ static int vmw_gb_surface_bind(struct vmw_resource *res, · 1 unmodified line
1204 }1207 }
1205 vmw_cmd_commit(dev_priv, submit_size);1208 vmw_cmd_commit(dev_priv, submit_size);
1206 1209
1207 if (res->backup->dirty && res->backup_dirty) {1210 if (res->guest_memory_bo->dirty && res->guest_memory_dirty) {
1208 /* We've just made a full upload. Cear dirty regions. */1211 /* We've just made a full upload. Cear dirty regions. */
1209 vmw_bo_dirty_clear_res(res);1212 vmw_bo_dirty_clear_res(res);
1210 }1213 }
1211 1214
1212 res->backup_dirty = false;1215 res->guest_memory_dirty = false;
1213 1216
1214 return 0;1217 return 0;
1215}1218}
@@ -1505,11 +1508,11 @@ vmw_gb_surface_define_internal(struct drm_device *dev, · 289 unmodified lines
1505 1508
1506 if (req->base.buffer_handle != SVGA3D_INVALID_ID) {1509 if (req->base.buffer_handle != SVGA3D_INVALID_ID) {
1507 ret = vmw_user_bo_lookup(file_priv, req->base.buffer_handle,1510 ret = vmw_user_bo_lookup(file_priv, req->base.buffer_handle,
1508 &res->backup);1511 &res->guest_memory_bo);
1509 if (ret == 0) {1512 if (ret == 0) {
1510 if (res->backup->base.base.size < res->backup_size) {1513 if (res->guest_memory_bo->tbo.base.size < res->guest_memory_size) {
1511 VMW_DEBUG_USER("Surface backup buffer too small.\n");1514 VMW_DEBUG_USER("Surface backup buffer too small.\n");
1512 vmw_bo_unreference(&res->backup);1515 vmw_bo_unreference(&res->guest_memory_bo);
1513 ret = -EINVAL;1516 ret = -EINVAL;
1514 goto out_unlock;1517 goto out_unlock;
1515 } else {1518 } else {
@@ -1520,11 +1523,11 @@ vmw_gb_surface_define_internal(struct drm_device *dev, · 4 unmodified lines
1520 (drm_vmw_surface_flag_create_buffer |1523 (drm_vmw_surface_flag_create_buffer |
1521 drm_vmw_surface_flag_coherent)) {1524 drm_vmw_surface_flag_coherent)) {
1522 ret = vmw_gem_object_create_with_handle(dev_priv, file_priv,1525 ret = vmw_gem_object_create_with_handle(dev_priv, file_priv,
1523 res->backup_size,1526 res->guest_memory_size,
1524 &backup_handle,1527 &backup_handle,
1525 &res->backup);1528 &res->guest_memory_bo);
1526 if (ret == 0)1529 if (ret == 0)
1527 vmw_bo_reference(res->backup);1530 vmw_bo_reference(res->guest_memory_bo);
1528 }1531 }
1529 1532
1530 if (unlikely(ret != 0)) {1533 if (unlikely(ret != 0)) {
@@ -1533,9 +1536,9 @@ vmw_gb_surface_define_internal(struct drm_device *dev, · 2 unmodified lines
1533 }1536 }
1534 1537
1535 if (req->base.drm_surface_flags & drm_vmw_surface_flag_coherent) {1538 if (req->base.drm_surface_flags & drm_vmw_surface_flag_coherent) {
1536 struct vmw_buffer_object *backup = res->backup;1539 struct vmw_bo *backup = res->guest_memory_bo;
1537 1540
1538 ttm_bo_reserve(&backup->base, false, false, NULL);1541 ttm_bo_reserve(&backup->tbo, false, false, NULL);
1539 if (!res->func->dirty_alloc)1542 if (!res->func->dirty_alloc)
1540 ret = -EINVAL;1543 ret = -EINVAL;
1541 if (!ret)1544 if (!ret)
@@ -1544,7 +1547,7 @@ vmw_gb_surface_define_internal(struct drm_device *dev, · 2 unmodified lines
1544 res->coherent = true;1547 res->coherent = true;
1545 ret = res->func->dirty_alloc(res);1548 ret = res->func->dirty_alloc(res);
1546 }1549 }
1547 ttm_bo_unreserve(&backup->base);1550 ttm_bo_unreserve(&backup->tbo);
1548 if (ret) {1551 if (ret) {
1549 vmw_resource_unreference(&res);1552 vmw_resource_unreference(&res);
1550 goto out_unlock;1553 goto out_unlock;
@@ -1553,7 +1556,7 @@ vmw_gb_surface_define_internal(struct drm_device *dev, · 2 unmodified lines
1553 }1556 }
1554 1557
1555 tmp = vmw_resource_reference(res);1558 tmp = vmw_resource_reference(res);
1556 ret = ttm_prime_object_init(tfile, res->backup_size, &user_srf->prime,1559 ret = ttm_prime_object_init(tfile, res->guest_memory_size, &user_srf->prime,
1557 req->base.drm_surface_flags &1560 req->base.drm_surface_flags &
1558 drm_vmw_surface_flag_shareable,1561 drm_vmw_surface_flag_shareable,
1559 VMW_RES_SURFACE,1562 VMW_RES_SURFACE,
@@ -1566,11 +1569,11 @@ vmw_gb_surface_define_internal(struct drm_device *dev, · 6 unmodified lines
1566 }1569 }
1567 1570
1568 rep->handle = user_srf->prime.base.handle;1571 rep->handle = user_srf->prime.base.handle;
1569 rep->backup_size = res->backup_size;1572 rep->backup_size = res->guest_memory_size;
1570 if (res->backup) {1573 if (res->guest_memory_bo) {
1571 rep->buffer_map_handle =1574 rep->buffer_map_handle =
1572 drm_vma_node_offset_addr(&res->backup->base.base.vma_node);1575 drm_vma_node_offset_addr(&res->guest_memory_bo->tbo.base.vma_node);
1573 rep->buffer_size = res->backup->base.base.size;1576 rep->buffer_size = res->guest_memory_bo->tbo.base.size;
1574 rep->buffer_handle = backup_handle;1577 rep->buffer_handle = backup_handle;
1575 } else {1578 } else {
1576 rep->buffer_map_handle = 0;1579 rep->buffer_map_handle = 0;
@@ -1613,14 +1616,14 @@ vmw_gb_surface_reference_internal(struct drm_device *dev, · 36 unmodified lines
1613 1616
1614 user_srf = container_of(base, struct vmw_user_surface, prime.base);1617 user_srf = container_of(base, struct vmw_user_surface, prime.base);
1615 srf = &user_srf->srf;1618 srf = &user_srf->srf;
1616 if (!srf->res.backup) {1619 if (!srf->res.guest_memory_bo) {
1617 DRM_ERROR("Shared GB surface is missing a backup buffer.\n");1620 DRM_ERROR("Shared GB surface is missing a backup buffer.\n");
1618 goto out_bad_resource;1621 goto out_bad_resource;
1619 }1622 }
1620 metadata = &srf->metadata;1623 metadata = &srf->metadata;
1621 1624
1622 mutex_lock(&dev_priv->cmdbuf_mutex); /* Protect res->backup */1625 mutex_lock(&dev_priv->cmdbuf_mutex); /* Protect res->backup */
1623 ret = drm_gem_handle_create(file_priv, &srf->res.backup->base.base,1626 ret = drm_gem_handle_create(file_priv, &srf->res.guest_memory_bo->tbo.base,
1624 &backup_handle);1627 &backup_handle);
1625 mutex_unlock(&dev_priv->cmdbuf_mutex);1628 mutex_unlock(&dev_priv->cmdbuf_mutex);
1626 if (ret != 0) {1629 if (ret != 0) {
@@ -1639,11 +1642,11 @@ vmw_gb_surface_reference_internal(struct drm_device *dev, · 12 unmodified lines
1639 rep->creq.base.buffer_handle = backup_handle;1642 rep->creq.base.buffer_handle = backup_handle;
1640 rep->creq.base.base_size = metadata->base_size;1643 rep->creq.base.base_size = metadata->base_size;
1641 rep->crep.handle = user_srf->prime.base.handle;1644 rep->crep.handle = user_srf->prime.base.handle;
1642 rep->crep.backup_size = srf->res.backup_size;1645 rep->crep.backup_size = srf->res.guest_memory_size;
1643 rep->crep.buffer_handle = backup_handle;1646 rep->crep.buffer_handle = backup_handle;
1644 rep->crep.buffer_map_handle =1647 rep->crep.buffer_map_handle =
1645 drm_vma_node_offset_addr(&srf->res.backup->base.base.vma_node);1648 drm_vma_node_offset_addr(&srf->res.guest_memory_bo->tbo.base.vma_node);
1646 rep->crep.buffer_size = srf->res.backup->base.base.size;1649 rep->crep.buffer_size = srf->res.guest_memory_bo->tbo.base.size;
1647 1650
1648 rep->creq.version = drm_vmw_gb_surface_v1;1651 rep->creq.version = drm_vmw_gb_surface_v1;
1649 rep->creq.svga3d_flags_upper_32_bits =1652 rep->creq.svga3d_flags_upper_32_bits =
@@ -1742,12 +1745,12 @@ static void vmw_surface_tex_dirty_range_add(struct vmw_resource *res, · 92 unmodified lines
1742{1745{
1743 struct vmw_surface_dirty *dirty =1746 struct vmw_surface_dirty *dirty =
1744 (struct vmw_surface_dirty *) res->dirty;1747 (struct vmw_surface_dirty *) res->dirty;
1745 size_t backup_end = res->backup_offset + res->backup_size;1748 size_t backup_end = res->guest_memory_offset + res->guest_memory_size;
1746 struct vmw_surface_loc loc1, loc2;1749 struct vmw_surface_loc loc1, loc2;
1747 const struct vmw_surface_cache *cache;1750 const struct vmw_surface_cache *cache;
1748 1751
1749 start = max_t(size_t, start, res->backup_offset) - res->backup_offset;1752 start = max_t(size_t, start, res->guest_memory_offset) - res->guest_memory_offset;
1750 end = min(end, backup_end) - res->backup_offset;1753 end = min(end, backup_end) - res->guest_memory_offset;
1751 cache = &dirty->cache;1754 cache = &dirty->cache;
1752 vmw_surface_get_loc(cache, &loc1, start);1755 vmw_surface_get_loc(cache, &loc1, start);
1753 vmw_surface_get_loc(cache, &loc2, end - 1);1756 vmw_surface_get_loc(cache, &loc2, end - 1);
@@ -1794,13 +1797,13 @@ static void vmw_surface_buf_dirty_range_add(struct vmw_resource *res, · 40 unmodified lines
1794 struct vmw_surface_dirty *dirty =1797 struct vmw_surface_dirty *dirty =
1795 (struct vmw_surface_dirty *) res->dirty;1798 (struct vmw_surface_dirty *) res->dirty;
1796 const struct vmw_surface_cache *cache = &dirty->cache;1799 const struct vmw_surface_cache *cache = &dirty->cache;
1797 size_t backup_end = res->backup_offset + cache->mip_chain_bytes;1800 size_t backup_end = res->guest_memory_offset + cache->mip_chain_bytes;
1798 SVGA3dBox *box = &dirty->boxes[0];1801 SVGA3dBox *box = &dirty->boxes[0];
1799 u32 box_c2;1802 u32 box_c2;
1800 1803
1801 box->h = box->d = 1;1804 box->h = box->d = 1;
1802 start = max_t(size_t, start, res->backup_offset) - res->backup_offset;1805 start = max_t(size_t, start, res->guest_memory_offset) - res->guest_memory_offset;
1803 end = min(end, backup_end) - res->backup_offset;1806 end = min(end, backup_end) - res->guest_memory_offset;
1804 box_c2 = box->x + box->w;1807 box_c2 = box->x + box->w;
1805 if (box->w == 0 || box->x > start)1808 if (box->w == 0 || box->x > start)
1806 box->x = start;1809 box->x = start;
@@ -1816,8 +1819,8 @@ static void vmw_surface_dirty_range_add(struct vmw_resource *res, size_t start, · 9 unmodified lines
1816{1819{
1817 struct vmw_surface *srf = vmw_res_to_srf(res);1820 struct vmw_surface *srf = vmw_res_to_srf(res);
1818 1821
1819 if (WARN_ON(end <= res->backup_offset ||1822 if (WARN_ON(end <= res->guest_memory_offset ||
1820 start >= res->backup_offset + res->backup_size))1823 start >= res->guest_memory_offset + res->guest_memory_size))
1821 return;1824 return;
1822 1825
1823 if (srf->metadata.format == SVGA3D_BUFFER)1826 if (srf->metadata.format == SVGA3D_BUFFER)
@@ -2074,7 +2077,7 @@ int vmw_gb_surface_define(struct vmw_private *dev_priv, · 250 unmodified lines
2074 if (metadata->flags & SVGA3D_SURFACE_MULTISAMPLE)2077 if (metadata->flags & SVGA3D_SURFACE_MULTISAMPLE)
2075 sample_count = metadata->multisample_count;2078 sample_count = metadata->multisample_count;
2076 2079
2077 srf->res.backup_size =2080 srf->res.guest_memory_size =
2078 vmw_surface_get_serialized_size_extended(2081 vmw_surface_get_serialized_size_extended(
2079 metadata->format,2082 metadata->format,
2080 metadata->base_size,2083 metadata->base_size,
@@ -2083,7 +2086,7 @@ int vmw_gb_surface_define(struct vmw_private *dev_priv, · 2 unmodified lines
2083 sample_count);2086 sample_count);
2084 2087
2085 if (metadata->flags & SVGA3D_SURFACE_BIND_STREAM_OUTPUT)2088 if (metadata->flags & SVGA3D_SURFACE_BIND_STREAM_OUTPUT)
2086 srf->res.backup_size += sizeof(SVGA3dDXSOState);2089 srf->res.guest_memory_size += sizeof(SVGA3dDXSOState);
2087 2090
2088 /*2091 /*
2089 * Don't set SVGA3D_SURFACE_SCREENTARGET flag for a scanout surface with2092 * Don't set SVGA3D_SURFACE_SCREENTARGET flag for a scanout surface with
drivers/gpu/drm/vmwgfx/vmwgfx_ttm_buffer.c+34−100
@@ -1,7 +1,7 @@
1// SPDX-License-Identifier: GPL-2.0 OR MIT1// SPDX-License-Identifier: GPL-2.0 OR MIT
2/**************************************************************************2/**************************************************************************
3 *3 *
4 * Copyright 2009-2015 VMware, Inc., Palo Alto, CA., USA4 * Copyright 2009-2023 VMware, Inc., Palo Alto, CA., USA
5 *5 *
6 * Permission is hereby granted, free of charge, to any person obtaining a6 * Permission is hereby granted, free of charge, to any person obtaining a
7 * copy of this software and associated documentation files (the7 * copy of this software and associated documentation files (the
@@ -25,6 +25,7 @@ · 17 unmodified lines
25 *25 *
26 **************************************************************************/26 **************************************************************************/
27 27
28#include "vmwgfx_bo.h"
28#include "vmwgfx_drv.h"29#include "vmwgfx_drv.h"
29#include <drm/ttm/ttm_placement.h>30#include <drm/ttm/ttm_placement.h>
30 31
@@ -49,13 +50,6 @@ static const struct ttm_place gmr_placement_flags = { · 18 unmodified lines
49 .flags = 050 .flags = 0
50};51};
51 52
52static const struct ttm_place mob_placement_flags = {
53 .fpfn = 0,
54 .lpfn = 0,
55 .mem_type = VMW_PL_MOB,
56 .flags = 0
57};
58
59struct ttm_placement vmw_vram_placement = {53struct ttm_placement vmw_vram_placement = {
60 .num_placement = 1,54 .num_placement = 1,
61 .placement = &vram_placement_flags,55 .placement = &vram_placement_flags,
@@ -77,27 +71,6 @@ static const struct ttm_place vram_gmr_placement_flags[] = { · 15 unmodified lines
77 }71 }
78};72};
79 73
80static 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
94static 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
101struct ttm_placement vmw_vram_gmr_placement = {74struct ttm_placement vmw_vram_gmr_placement = {
102 .num_placement = 2,75 .num_placement = 2,
103 .placement = vram_gmr_placement_flags,76 .placement = vram_gmr_placement_flags,
@@ -105,13 +78,6 @@ struct ttm_placement vmw_vram_gmr_placement = { · 1 unmodified line
105 .busy_placement = &gmr_placement_flags78 .busy_placement = &gmr_placement_flags
106};79};
107 80
108struct 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
115struct ttm_placement vmw_sys_placement = {81struct ttm_placement vmw_sys_placement = {
116 .num_placement = 1,82 .num_placement = 1,
117 .placement = &sys_placement_flags,83 .placement = &sys_placement_flags,
@@ -119,53 +85,6 @@ struct ttm_placement vmw_sys_placement = { · 1 unmodified line
119 .busy_placement = &sys_placement_flags85 .busy_placement = &sys_placement_flags
120};86};
121 87
122struct 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
129static 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
148struct 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
155struct 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
162struct 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
169const size_t vmw_tt_size = sizeof(struct vmw_ttm_tt);88const size_t vmw_tt_size = sizeof(struct vmw_ttm_tt);
170 89
171/**90/**
@@ -508,7 +427,7 @@ static struct ttm_tt *vmw_ttm_tt_create(struct ttm_buffer_object *bo, · 336 unmodified lines
508 if (!vmw_be)427 if (!vmw_be)
509 return NULL;428 return NULL;
510 429
511 vmw_be->dev_priv = container_of(bo->bdev, struct vmw_private, bdev);430 vmw_be->dev_priv = vmw_priv_from_ttm(bo->bdev);
512 vmw_be->mob = NULL;431 vmw_be->mob = NULL;
513 432
514 if (vmw_be->dev_priv->map_mode == vmw_dma_alloc_coherent)433 if (vmw_be->dev_priv->map_mode == vmw_dma_alloc_coherent)
@@ -534,7 +453,7 @@ static void vmw_evict_flags(struct ttm_buffer_object *bo, · 19 unmodified lines
534 453
535static int vmw_ttm_io_mem_reserve(struct ttm_device *bdev, struct ttm_resource *mem)454static int vmw_ttm_io_mem_reserve(struct ttm_device *bdev, struct ttm_resource *mem)
536{455{
537 struct vmw_private *dev_priv = container_of(bdev, struct vmw_private, bdev);456 struct vmw_private *dev_priv = vmw_priv_from_ttm(bdev);
538 457
539 switch (mem->mem_type) {458 switch (mem->mem_type) {
540 case TTM_PL_SYSTEM:459 case TTM_PL_SYSTEM:
@@ -596,9 +515,13 @@ static int vmw_move(struct ttm_buffer_object *bo, · 55 unmodified lines
596 struct ttm_resource *new_mem,515 struct ttm_resource *new_mem,
597 struct ttm_place *hop)516 struct ttm_place *hop)
598{517{
599 struct ttm_resource_manager *old_man = ttm_manager_type(bo->bdev, bo->resource->mem_type);518 struct ttm_resource_manager *new_man;
600 struct ttm_resource_manager *new_man = ttm_manager_type(bo->bdev, new_mem->mem_type);519 struct ttm_resource_manager *old_man = NULL;
601 int ret;520 int ret = 0;
521
522 new_man = ttm_manager_type(bo->bdev, new_mem->mem_type);
523 if (bo->resource)
524 old_man = ttm_manager_type(bo->bdev, bo->resource->mem_type);
602 525
603 if (new_man->use_tt && !vmw_memtype_is_system(new_mem->mem_type)) {526 if (new_man->use_tt && !vmw_memtype_is_system(new_mem->mem_type)) {
604 ret = vmw_ttm_bind(bo->bdev, bo->ttm, new_mem);527 ret = vmw_ttm_bind(bo->bdev, bo->ttm, new_mem);
@@ -606,9 +529,15 @@ static int vmw_move(struct ttm_buffer_object *bo, · 1 unmodified line
606 return ret;529 return ret;
607 }530 }
608 531
532 if (!bo->resource || (bo->resource->mem_type == TTM_PL_SYSTEM &&
533 bo->ttm == NULL)) {
534 ttm_bo_move_null(bo, new_mem);
535 return 0;
536 }
537
609 vmw_move_notify(bo, bo->resource, new_mem);538 vmw_move_notify(bo, bo->resource, new_mem);
610 539
611 if (old_man->use_tt && new_man->use_tt) {540 if (old_man && old_man->use_tt && new_man->use_tt) {
612 if (vmw_memtype_is_system(bo->resource->mem_type)) {541 if (vmw_memtype_is_system(bo->resource->mem_type)) {
613 ttm_bo_move_null(bo, new_mem);542 ttm_bo_move_null(bo, new_mem);
614 return 0;543 return 0;
@@ -645,34 +574,39 @@ struct ttm_device_funcs vmw_bo_driver = { · 30 unmodified lines
645};574};
646 575
647int vmw_bo_create_and_populate(struct vmw_private *dev_priv,576int vmw_bo_create_and_populate(struct vmw_private *dev_priv,
648 unsigned long bo_size,577 size_t bo_size, u32 domain,
649 struct ttm_buffer_object **bo_p)578 struct vmw_bo **bo_p)
650{579{
651 struct ttm_operation_ctx ctx = {580 struct ttm_operation_ctx ctx = {
652 .interruptible = false,581 .interruptible = false,
653 .no_wait_gpu = false582 .no_wait_gpu = false
654 };583 };
655 struct ttm_buffer_object *bo;584 struct vmw_bo *vbo;
656 int ret;585 int ret;
586 struct vmw_bo_params bo_params = {
587 .domain = domain,
588 .busy_domain = domain,
589 .bo_type = ttm_bo_type_kernel,
590 .size = bo_size,
591 .pin = true
592 };
657 593
658 ret = vmw_bo_create_kernel(dev_priv, bo_size,594 ret = vmw_bo_create(dev_priv, &bo_params, &vbo);
659 &vmw_pt_sys_placement,
660 &bo);
661 if (unlikely(ret != 0))595 if (unlikely(ret != 0))
662 return ret;596 return ret;
663 597
664 ret = ttm_bo_reserve(bo, false, true, NULL);598 ret = ttm_bo_reserve(&vbo->tbo, false, true, NULL);
665 BUG_ON(ret != 0);599 BUG_ON(ret != 0);
666 ret = vmw_ttm_populate(bo->bdev, bo->ttm, &ctx);600 ret = vmw_ttm_populate(vbo->tbo.bdev, vbo->tbo.ttm, &ctx);
667 if (likely(ret == 0)) {601 if (likely(ret == 0)) {
668 struct vmw_ttm_tt *vmw_tt =602 struct vmw_ttm_tt *vmw_tt =
669 container_of(bo->ttm, struct vmw_ttm_tt, dma_ttm);603 container_of(vbo->tbo.ttm, struct vmw_ttm_tt, dma_ttm);
670 ret = vmw_ttm_map_dma(vmw_tt);604 ret = vmw_ttm_map_dma(vmw_tt);
671 }605 }
672 606
673 ttm_bo_unreserve(bo);607 ttm_bo_unreserve(&vbo->tbo);
674 608
675 if (likely(ret == 0))609 if (likely(ret == 0))
676 *bo_p = bo;610 *bo_p = vbo;
677 return ret;611 return ret;
678}612}
drivers/gpu/drm/vmwgfx/vmwgfx_va.c+4−2
@@ -25,6 +25,7 @@ · 24 unmodified lines
25 *25 *
26 **************************************************************************/26 **************************************************************************/
27 27
28#include "vmwgfx_bo.h"
28#include "vmwgfx_drv.h"29#include "vmwgfx_drv.h"
29#include "vmwgfx_resource_priv.h"30#include "vmwgfx_resource_priv.h"
30 31
@@ -80,10 +81,11 @@ static void vmw_stream_set_arg_handle(void *data, u32 handle) · 49 unmodified lines
80static const struct vmw_simple_resource_func va_stream_func = {81static const struct vmw_simple_resource_func va_stream_func = {
81 .res_func = {82 .res_func = {
82 .res_type = vmw_res_stream,83 .res_type = vmw_res_stream,
83 .needs_backup = false,84 .needs_guest_memory = false,
84 .may_evict = false,85 .may_evict = false,
85 .type_name = "overlay stream",86 .type_name = "overlay stream",
86 .backup_placement = NULL,87 .domain = VMW_BO_DOMAIN_SYS,
88 .busy_domain = VMW_BO_DOMAIN_SYS,
87 .create = NULL,89 .create = NULL,
88 .destroy = NULL,90 .destroy = NULL,
89 .bind = NULL,91 .bind = NULL,
drivers/gpu/drm/vmwgfx/vmwgfx_validation.c+56−94
@@ -1,7 +1,7 @@
1// SPDX-License-Identifier: GPL-2.0 OR MIT1// SPDX-License-Identifier: GPL-2.0 OR MIT
2/**************************************************************************2/**************************************************************************
3 *3 *
4 * Copyright © 2018 - 2022 VMware, Inc., Palo Alto, CA., USA4 * Copyright © 2018 - 2023 VMware, Inc., Palo Alto, CA., USA
5 * All Rights Reserved.5 * All Rights Reserved.
6 *6 *
7 * Permission is hereby granted, free of charge, to any person obtaining a7 * Permission is hereby granted, free of charge, to any person obtaining a
@@ -25,9 +25,12 @@ · 17 unmodified lines
25 * USE OR OTHER DEALINGS IN THE SOFTWARE.25 * USE OR OTHER DEALINGS IN THE SOFTWARE.
26 *26 *
27 **************************************************************************/27 **************************************************************************/
28#include <linux/slab.h>28#include "vmwgfx_bo.h"
29#include "vmwgfx_validation.h"
30#include "vmwgfx_drv.h"29#include "vmwgfx_drv.h"
30#include "vmwgfx_resource_priv.h"
31#include "vmwgfx_validation.h"
32
33#include <linux/slab.h>
31 34
32 35
33#define VMWGFX_VALIDATION_MEM_GRAN (16*PAGE_SIZE)36#define VMWGFX_VALIDATION_MEM_GRAN (16*PAGE_SIZE)
@@ -38,8 +41,6 @@ · 4 unmodified lines
38 * @hash: A hash entry used for the duplicate detection hash table.41 * @hash: A hash entry used for the duplicate detection hash table.
39 * @coherent_count: If switching backup buffers, number of new coherent42 * @coherent_count: If switching backup buffers, number of new coherent
40 * resources that will have this buffer as a backup buffer.43 * resources that will have this buffer as a backup buffer.
41 * @as_mob: Validate as mob.
42 * @cpu_blit: Validate for cpu blit access.
43 *44 *
44 * Bit fields are used since these structures are allocated and freed in45 * Bit fields are used since these structures are allocated and freed in
45 * large numbers and space conservation is desired.46 * large numbers and space conservation is desired.
@@ -48,21 +49,19 @@ struct vmw_validation_bo_node { · 2 unmodified lines
48 struct ttm_validate_buffer base;49 struct ttm_validate_buffer base;
49 struct vmwgfx_hash_item hash;50 struct vmwgfx_hash_item hash;
50 unsigned int coherent_count;51 unsigned int coherent_count;
51 u32 as_mob : 1;
52 u32 cpu_blit : 1;
53};52};
54/**53/**
55 * struct vmw_validation_res_node - Resource validation metadata.54 * struct vmw_validation_res_node - Resource validation metadata.
56 * @head: List head for the resource validation list.55 * @head: List head for the resource validation list.
57 * @hash: A hash entry used for the duplicate detection hash table.56 * @hash: A hash entry used for the duplicate detection hash table.
58 * @res: Reference counted resource pointer.57 * @res: Reference counted resource pointer.
59 * @new_backup: Non ref-counted pointer to new backup buffer to be assigned58 * @new_guest_memory_bo: Non ref-counted pointer to new guest memory buffer
60 * to a resource.59 * to be assigned to a resource.
61 * @new_backup_offset: Offset into the new backup mob for resources that can60 * @new_guest_memory_offset: Offset into the new backup mob for resources
62 * share MOBs.61 * that can share MOBs.
63 * @no_buffer_needed: Kernel does not need to allocate a MOB during validation,62 * @no_buffer_needed: Kernel does not need to allocate a MOB during validation,
64 * the command stream provides a mob bind operation.63 * the command stream provides a mob bind operation.
65 * @switching_backup: The validation process is switching backup MOB.64 * @switching_guest_memory_bo: The validation process is switching backup MOB.
66 * @first_usage: True iff the resource has been seen only once in the current65 * @first_usage: True iff the resource has been seen only once in the current
67 * validation batch.66 * validation batch.
68 * @reserved: Whether the resource is currently reserved by this process.67 * @reserved: Whether the resource is currently reserved by this process.
@@ -77,10 +76,10 @@ struct vmw_validation_res_node { · 8 unmodified lines
77 struct list_head head;76 struct list_head head;
78 struct vmwgfx_hash_item hash;77 struct vmwgfx_hash_item hash;
79 struct vmw_resource *res;78 struct vmw_resource *res;
80 struct vmw_buffer_object *new_backup;79 struct vmw_bo *new_guest_memory_bo;
81 unsigned long new_backup_offset;80 unsigned long new_guest_memory_offset;
82 u32 no_buffer_needed : 1;81 u32 no_buffer_needed : 1;
83 u32 switching_backup : 1;82 u32 switching_guest_memory_bo : 1;
84 u32 first_usage : 1;83 u32 first_usage : 1;
85 u32 reserved : 1;84 u32 reserved : 1;
86 u32 dirty : 1;85 u32 dirty : 1;
@@ -173,7 +172,7 @@ static void vmw_validation_mem_free(struct vmw_validation_context *ctx) · 86 unmodified lines
173 */172 */
174static struct vmw_validation_bo_node *173static struct vmw_validation_bo_node *
175vmw_validation_find_bo_dup(struct vmw_validation_context *ctx,174vmw_validation_find_bo_dup(struct vmw_validation_context *ctx,
176 struct vmw_buffer_object *vbo)175 struct vmw_bo *vbo)
177{176{
178 struct vmw_validation_bo_node *bo_node = NULL;177 struct vmw_validation_bo_node *bo_node = NULL;
179 178
@@ -194,7 +193,7 @@ vmw_validation_find_bo_dup(struct vmw_validation_context *ctx, · 14 unmodified lines
194 struct vmw_validation_bo_node *entry;193 struct vmw_validation_bo_node *entry;
195 194
196 list_for_each_entry(entry, &ctx->bo_list, base.head) {195 list_for_each_entry(entry, &ctx->bo_list, base.head) {
197 if (entry->base.bo == &vbo->base) {196 if (entry->base.bo == &vbo->tbo) {
198 bo_node = entry;197 bo_node = entry;
199 break;198 break;
200 }199 }
@@ -258,26 +257,16 @@ out: · 57 unmodified lines
258 * vmw_validation_add_bo - Add a buffer object to the validation context.257 * vmw_validation_add_bo - Add a buffer object to the validation context.
259 * @ctx: The validation context.258 * @ctx: The validation context.
260 * @vbo: The buffer object.259 * @vbo: The buffer object.
261 * @as_mob: Validate as mob, otherwise suitable for GMR operations.
262 * @cpu_blit: Validate in a page-mappable location.
263 *260 *
264 * Return: Zero on success, negative error code otherwise.261 * Return: Zero on success, negative error code otherwise.
265 */262 */
266int vmw_validation_add_bo(struct vmw_validation_context *ctx,263int vmw_validation_add_bo(struct vmw_validation_context *ctx,
267 struct vmw_buffer_object *vbo,264 struct vmw_bo *vbo)
268 bool as_mob,
269 bool cpu_blit)
270{265{
271 struct vmw_validation_bo_node *bo_node;266 struct vmw_validation_bo_node *bo_node;
272 267
273 bo_node = vmw_validation_find_bo_dup(ctx, vbo);268 bo_node = vmw_validation_find_bo_dup(ctx, vbo);
274 if (bo_node) {269 if (!bo_node) {
275 if (bo_node->as_mob != as_mob ||
276 bo_node->cpu_blit != cpu_blit) {
277 DRM_ERROR("Inconsistent buffer usage.\n");
278 return -EINVAL;
279 }
280 } else {
281 struct ttm_validate_buffer *val_buf;270 struct ttm_validate_buffer *val_buf;
282 271
283 bo_node = vmw_validation_mem_alloc(ctx, sizeof(*bo_node));272 bo_node = vmw_validation_mem_alloc(ctx, sizeof(*bo_node));
@@ -290,13 +279,11 @@ int vmw_validation_add_bo(struct vmw_validation_context *ctx, · 6 unmodified lines
290 bo_node->hash.key);279 bo_node->hash.key);
291 }280 }
292 val_buf = &bo_node->base;281 val_buf = &bo_node->base;
293 val_buf->bo = ttm_bo_get_unless_zero(&vbo->base);282 val_buf->bo = ttm_bo_get_unless_zero(&vbo->tbo);
294 if (!val_buf->bo)283 if (!val_buf->bo)
295 return -ESRCH;284 return -ESRCH;
296 val_buf->num_shared = 0;285 val_buf->num_shared = 0;
297 list_add_tail(&val_buf->head, &ctx->bo_list);286 list_add_tail(&val_buf->head, &ctx->bo_list);
298 bo_node->as_mob = as_mob;
299 bo_node->cpu_blit = cpu_blit;
300 }287 }
301 288
302 return 0;289 return 0;
@@ -406,23 +393,23 @@ void vmw_validation_res_set_dirty(struct vmw_validation_context *ctx, · 103 unmodified lines
406 * the resource.393 * the resource.
407 * @vbo: The new backup buffer object MOB. This buffer object needs to have394 * @vbo: The new backup buffer object MOB. This buffer object needs to have
408 * already been registered with the validation context.395 * already been registered with the validation context.
409 * @backup_offset: Offset into the new backup MOB.396 * @guest_memory_offset: Offset into the new backup MOB.
410 */397 */
411void vmw_validation_res_switch_backup(struct vmw_validation_context *ctx,398void vmw_validation_res_switch_backup(struct vmw_validation_context *ctx,
412 void *val_private,399 void *val_private,
413 struct vmw_buffer_object *vbo,400 struct vmw_bo *vbo,
414 unsigned long backup_offset)401 unsigned long guest_memory_offset)
415{402{
416 struct vmw_validation_res_node *val;403 struct vmw_validation_res_node *val;
417 404
418 val = container_of(val_private, typeof(*val), private);405 val = container_of(val_private, typeof(*val), private);
419 406
420 val->switching_backup = 1;407 val->switching_guest_memory_bo = 1;
421 if (val->first_usage)408 if (val->first_usage)
422 val->no_buffer_needed = 1;409 val->no_buffer_needed = 1;
423 410
424 val->new_backup = vbo;411 val->new_guest_memory_bo = vbo;
425 val->new_backup_offset = backup_offset;412 val->new_guest_memory_offset = guest_memory_offset;
426}413}
427 414
428/**415/**
@@ -450,21 +437,22 @@ int vmw_validation_res_reserve(struct vmw_validation_context *ctx, · 21 unmodified lines
450 goto out_unreserve;437 goto out_unreserve;
451 438
452 val->reserved = 1;439 val->reserved = 1;
453 if (res->backup) {440 if (res->guest_memory_bo) {
454 struct vmw_buffer_object *vbo = res->backup;441 struct vmw_bo *vbo = res->guest_memory_bo;
455 442
456 ret = vmw_validation_add_bo443 vmw_bo_placement_set(vbo,
457 (ctx, vbo, vmw_resource_needs_backup(res),444 res->func->domain,
458 false);445 res->func->busy_domain);
446 ret = vmw_validation_add_bo(ctx, vbo);
459 if (ret)447 if (ret)
460 goto out_unreserve;448 goto out_unreserve;
461 }449 }
462 450
463 if (val->switching_backup && val->new_backup &&451 if (val->switching_guest_memory_bo && val->new_guest_memory_bo &&
464 res->coherent) {452 res->coherent) {
465 struct vmw_validation_bo_node *bo_node =453 struct vmw_validation_bo_node *bo_node =
466 vmw_validation_find_bo_dup(ctx,454 vmw_validation_find_bo_dup(ctx,
467 val->new_backup);455 val->new_guest_memory_bo);
468 456
469 if (WARN_ON(!bo_node)) {457 if (WARN_ON(!bo_node)) {
470 ret = -EINVAL;458 ret = -EINVAL;
@@ -507,9 +495,9 @@ void vmw_validation_res_unreserve(struct vmw_validation_context *ctx, · 36 unmodified lines
507 vmw_resource_unreserve(val->res,495 vmw_resource_unreserve(val->res,
508 val->dirty_set,496 val->dirty_set,
509 val->dirty,497 val->dirty,
510 val->switching_backup,498 val->switching_guest_memory_bo,
511 val->new_backup,499 val->new_guest_memory_bo,
512 val->new_backup_offset);500 val->new_guest_memory_offset);
513 }501 }
514}502}
515 503
@@ -517,17 +505,14 @@ void vmw_validation_res_unreserve(struct vmw_validation_context *ctx, · 1 unmodified line
517 * vmw_validation_bo_validate_single - Validate a single buffer object.505 * vmw_validation_bo_validate_single - Validate a single buffer object.
518 * @bo: The TTM buffer object base.506 * @bo: The TTM buffer object base.
519 * @interruptible: Whether to perform waits interruptible if possible.507 * @interruptible: Whether to perform waits interruptible if possible.
520 * @validate_as_mob: Whether to validate in MOB memory.
521 *508 *
522 * Return: Zero on success, -ERESTARTSYS if interrupted. Negative error509 * Return: Zero on success, -ERESTARTSYS if interrupted. Negative error
523 * code on failure.510 * code on failure.
524 */511 */
525int vmw_validation_bo_validate_single(struct ttm_buffer_object *bo,512static int vmw_validation_bo_validate_single(struct ttm_buffer_object *bo,
526 bool interruptible,513 bool interruptible)
527 bool validate_as_mob)
528{514{
529 struct vmw_buffer_object *vbo =515 struct vmw_bo *vbo = to_vmw_bo(&bo->base);
530 container_of(bo, struct vmw_buffer_object, base);
531 struct ttm_operation_ctx ctx = {516 struct ttm_operation_ctx ctx = {
532 .interruptible = interruptible,517 .interruptible = interruptible,
533 .no_wait_gpu = false518 .no_wait_gpu = false
@@ -537,30 +522,20 @@ int vmw_validation_bo_validate_single(struct ttm_buffer_object *bo, · 3 unmodified lines
537 if (atomic_read(&vbo->cpu_writers))522 if (atomic_read(&vbo->cpu_writers))
538 return -EBUSY;523 return -EBUSY;
539 524
540 if (vbo->base.pin_count > 0)525 if (vbo->tbo.pin_count > 0)
541 return 0;526 return 0;
542 527
543 if (validate_as_mob)528 ret = ttm_bo_validate(bo, &vbo->placement, &ctx);
544 return ttm_bo_validate(bo, &vmw_mob_placement, &ctx);
545
546 /**
547 * Put BO in VRAM if there is space, otherwise as a GMR.
548 * If there is no space in VRAM and GMR ids are all used up,
549 * start evicting GMRs to make room. If the DMA buffer can't be
550 * used as a GMR, this will return -ENOMEM.
551 */
552
553 ret = ttm_bo_validate(bo, &vmw_vram_gmr_placement, &ctx);
554 if (ret == 0 || ret == -ERESTARTSYS)529 if (ret == 0 || ret == -ERESTARTSYS)
555 return ret;530 return ret;
556 531
557 /**532 /*
558 * If that failed, try VRAM again, this time evicting533 * If that failed, try again, this time evicting
559 * previous contents.534 * previous contents.
560 */535 */
536 ctx.allow_res_evict = true;
561 537
562 ret = ttm_bo_validate(bo, &vmw_vram_placement, &ctx);538 return ttm_bo_validate(bo, &vbo->placement, &ctx);
563 return ret;
564}539}
565 540
566/**541/**
@@ -578,21 +553,10 @@ int vmw_validation_bo_validate(struct vmw_validation_context *ctx, bool intr) · 11 unmodified lines
578 int ret;553 int ret;
579 554
580 list_for_each_entry(entry, &ctx->bo_list, base.head) {555 list_for_each_entry(entry, &ctx->bo_list, base.head) {
581 struct vmw_buffer_object *vbo =556 struct vmw_bo *vbo = to_vmw_bo(&entry->base.bo->base);
582 container_of(entry->base.bo, typeof(*vbo), base);557
583 558 ret = vmw_validation_bo_validate_single(entry->base.bo, intr);
584 if (entry->cpu_blit) {559
585 struct ttm_operation_ctx ttm_ctx = {
586 .interruptible = intr,
587 .no_wait_gpu = false
588 };
589
590 ret = ttm_bo_validate(entry->base.bo,
591 &vmw_nonfixed_placement, &ttm_ctx);
592 } else {
593 ret = vmw_validation_bo_validate_single
594 (entry->base.bo, intr, entry->as_mob);
595 }
596 if (ret)560 if (ret)
597 return ret;561 return ret;
598 562
@@ -639,7 +603,7 @@ int vmw_validation_res_validate(struct vmw_validation_context *ctx, bool intr) · 40 unmodified lines
639 603
640 list_for_each_entry(val, &ctx->resource_list, head) {604 list_for_each_entry(val, &ctx->resource_list, head) {
641 struct vmw_resource *res = val->res;605 struct vmw_resource *res = val->res;
642 struct vmw_buffer_object *backup = res->backup;606 struct vmw_bo *backup = res->guest_memory_bo;
643 607
644 ret = vmw_resource_validate(res, intr, val->dirty_set &&608 ret = vmw_resource_validate(res, intr, val->dirty_set &&
645 val->dirty);609 val->dirty);
@@ -650,12 +614,12 @@ int vmw_validation_res_validate(struct vmw_validation_context *ctx, bool intr) · 4 unmodified lines
650 }614 }
651 615
652 /* Check if the resource switched backup buffer */616 /* Check if the resource switched backup buffer */
653 if (backup && res->backup && (backup != res->backup)) {617 if (backup && res->guest_memory_bo && backup != res->guest_memory_bo) {
654 struct vmw_buffer_object *vbo = res->backup;618 struct vmw_bo *vbo = res->guest_memory_bo;
655 619
656 ret = vmw_validation_add_bo620 vmw_bo_placement_set(vbo, res->func->domain,
657 (ctx, vbo, vmw_resource_needs_backup(res),621 res->func->busy_domain);
658 false);622 ret = vmw_validation_add_bo(ctx, vbo);
659 if (ret)623 if (ret)
660 return ret;624 return ret;
661 }625 }
@@ -889,9 +853,7 @@ void vmw_validation_bo_backoff(struct vmw_validation_context *ctx) · 227 unmodified lines
889 list_for_each_entry(entry, &ctx->bo_list, base.head) {853 list_for_each_entry(entry, &ctx->bo_list, base.head) {
890 if (entry->coherent_count) {854 if (entry->coherent_count) {
891 unsigned int coherent_count = entry->coherent_count;855 unsigned int coherent_count = entry->coherent_count;
892 struct vmw_buffer_object *vbo =856 struct vmw_bo *vbo = to_vmw_bo(&entry->base.bo->base);
893 container_of(entry->base.bo, typeof(*vbo),
894 base);
895 857
896 while (coherent_count--)858 while (coherent_count--)
897 vmw_bo_dirty_release(vbo);859 vmw_bo_dirty_release(vbo);
drivers/gpu/drm/vmwgfx/vmwgfx_validation.h+3−7
@@ -73,7 +73,7 @@ struct vmw_validation_context { · 72 unmodified lines
73 size_t total_mem;73 size_t total_mem;
74};74};
75 75
76struct vmw_buffer_object;76struct vmw_bo;
77struct vmw_resource;77struct vmw_resource;
78struct vmw_fence_obj;78struct 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
161int vmw_validation_add_bo(struct vmw_validation_context *ctx,161int vmw_validation_add_bo(struct vmw_validation_context *ctx,
162 struct vmw_buffer_object *vbo,162 struct vmw_bo *vbo);
163 bool as_mob, bool cpu_blit);
164int vmw_validation_bo_validate_single(struct ttm_buffer_object *bo,
165 bool interruptible,
166 bool validate_as_mob);
167int vmw_validation_bo_validate(struct vmw_validation_context *ctx, bool intr);163int vmw_validation_bo_validate(struct vmw_validation_context *ctx, bool intr);
168void vmw_validation_unref_lists(struct vmw_validation_context *ctx);164void vmw_validation_unref_lists(struct vmw_validation_context *ctx);
169int vmw_validation_add_resource(struct vmw_validation_context *ctx,165int vmw_validation_add_resource(struct vmw_validation_context *ctx,
@@ -179,7 +175,7 @@ void vmw_validation_res_unreserve(struct vmw_validation_context *ctx, · 9 unmodified lines
179 bool backoff);175 bool backoff);
180void vmw_validation_res_switch_backup(struct vmw_validation_context *ctx,176void vmw_validation_res_switch_backup(struct vmw_validation_context *ctx,
181 void *val_private,177 void *val_private,
182 struct vmw_buffer_object *vbo,178 struct vmw_bo *vbo,
183 unsigned long backup_offset);179 unsigned long backup_offset);
184int vmw_validation_res_validate(struct vmw_validation_context *ctx, bool intr);180int vmw_validation_res_validate(struct vmw_validation_context *ctx, bool intr);
185 181
drivers/ps3/ps3av.c+5−4
@@ -11,13 +11,14 @@ · 10 unmodified lines
11#include <linux/delay.h>11#include <linux/delay.h>
12#include <linux/notifier.h>12#include <linux/notifier.h>
13#include <linux/ioctl.h>13#include <linux/ioctl.h>
14#include <linux/fb.h>
15#include <linux/slab.h>14#include <linux/slab.h>
16 15
17#include <asm/firmware.h>16#include <asm/firmware.h>
18#include <asm/ps3av.h>17#include <asm/ps3av.h>
19#include <asm/ps3.h>18#include <asm/ps3.h>
20 19
20#include <video/cmdline.h>
21
21#include "vuart.h"22#include "vuart.h"
22 23
23#define BUFSIZE 4096 /* vuart buf size */24#define BUFSIZE 4096 /* vuart buf size */
@@ -921,6 +922,7 @@ EXPORT_SYMBOL_GPL(ps3av_audio_mute); · 897 unmodified lines
921 922
922static int ps3av_probe(struct ps3_system_bus_device *dev)923static int ps3av_probe(struct ps3_system_bus_device *dev)
923{924{
925 const char *mode_option;
924 int res;926 int res;
925 int id;927 int id;
926 928
@@ -968,10 +970,9 @@ static int ps3av_probe(struct ps3_system_bus_device *dev) · 41 unmodified lines
968 970
969 ps3av_get_hw_conf(ps3av);971 ps3av_get_hw_conf(ps3av);
970 972
971#ifdef CONFIG_FB973 mode_option = video_get_options(NULL);
972 if (fb_mode_option && !strcmp(fb_mode_option, "safe"))974 if (mode_option && !strcmp(mode_option, "safe"))
973 safe_mode = 1;975 safe_mode = 1;
974#endif /* CONFIG_FB */
975 id = ps3av_auto_videomode(&ps3av->av_hw_conf);976 id = ps3av_auto_videomode(&ps3av->av_hw_conf);
976 if (id < 0) {977 if (id < 0) {
977 printk(KERN_ERR "%s: invalid id :%d\n", __func__, id);978 printk(KERN_ERR "%s: invalid id :%d\n", __func__, id);
drivers/video/Kconfig+3−0
@@ -11,6 +11,9 @@ config APERTURE_HELPERS · 10 unmodified lines
11 Support tracking and hand-over of aperture ownership. Required11 Support tracking and hand-over of aperture ownership. Required
12 by graphics drivers for firmware-provided framebuffers.12 by graphics drivers for firmware-provided framebuffers.
13 13
14config VIDEO_CMDLINE
15 bool
16
14config VIDEO_NOMODESET17config VIDEO_NOMODESET
15 bool18 bool
16 default n19 default n
drivers/video/Makefile+1−0
@@ -2,6 +2,7 @@ · 1 unmodified line
2 2
3obj-$(CONFIG_APERTURE_HELPERS) += aperture.o3obj-$(CONFIG_APERTURE_HELPERS) += aperture.o
4obj-$(CONFIG_VGASTATE) += vgastate.o4obj-$(CONFIG_VGASTATE) += vgastate.o
5obj-$(CONFIG_VIDEO_CMDLINE) += cmdline.o
5obj-$(CONFIG_VIDEO_NOMODESET) += nomodeset.o6obj-$(CONFIG_VIDEO_NOMODESET) += nomodeset.o
6obj-$(CONFIG_HDMI) += hdmi.o7obj-$(CONFIG_HDMI) += hdmi.o
7 8
drivers/video/cmdline.c+133−0
@@ -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 */
29static const char *video_options[FB_MAX] __read_mostly;
30static const char *video_option __read_mostly;
31static int video_of_only __read_mostly;
32
33static 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 */
77const char *video_get_options(const char *name)
78{
79 return __video_get_option_string(name);
80}
81EXPORT_SYMBOL(video_get_options);
82
83bool __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}
98EXPORT_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 */
105static 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
130out:
131 return 1;
132}
133__setup("video=", video_setup);
drivers/video/fbdev/Kconfig+1−4
@@ -3,16 +3,13 @@ · 2 unmodified lines
3# fbdev configuration3# fbdev configuration
4#4#
5 5
6config FB_CMDLINE
7 bool
8
9config FB_NOTIFY6config FB_NOTIFY
10 bool7 bool
11 8
12menuconfig FB9menuconfig FB
13 tristate "Support for frame buffer devices"10 tristate "Support for frame buffer devices"
14 select FB_CMDLINE
15 select FB_NOTIFY11 select FB_NOTIFY
12 select VIDEO_CMDLINE
16 help13 help
17 The frame buffer device provides an abstraction for the graphics14 The frame buffer device provides an abstraction for the graphics
18 hardware. It represents the frame buffer of some video hardware and15 hardware. It represents the frame buffer of some video hardware and
drivers/video/fbdev/core/Makefile+1−2
@@ -1,9 +1,8 @@
1# SPDX-License-Identifier: GPL-2.01# SPDX-License-Identifier: GPL-2.0
2obj-$(CONFIG_FB_CMDLINE) += fb_cmdline.o
3obj-$(CONFIG_FB_NOTIFY) += fb_notify.o2obj-$(CONFIG_FB_NOTIFY) += fb_notify.o
4obj-$(CONFIG_FB) += fb.o3obj-$(CONFIG_FB) += fb.o
5fb-y := fbmem.o fbmon.o fbcmap.o fbsysfs.o \4fb-y := fbmem.o fbmon.o fbcmap.o fbsysfs.o \
6 modedb.o fbcvt.o5 modedb.o fbcvt.o fb_cmdline.o
7fb-$(CONFIG_FB_DEFERRED_IO) += fb_defio.o6fb-$(CONFIG_FB_DEFERRED_IO) += fb_defio.o
8 7
9ifeq ($(CONFIG_FRAMEBUFFER_CONSOLE),y)8ifeq ($(CONFIG_FRAMEBUFFER_CONSOLE),y)
drivers/video/fbdev/core/fb_cmdline.c+24−70
@@ -12,16 +12,14 @@ · 11 unmodified lines
12 * for more details.12 * for more details.
13 *13 *
14 * Authors:14 * Authors:
15 * Vetter <danie.vetter@ffwll.ch>15 * Daniel Vetter <daniel.vetter@ffwll.ch>
16 */16 */
17#include <linux/init.h>
18#include <linux/fb.h>
19 17
20static char *video_options[FB_MAX] __read_mostly;18#include <linux/export.h>
21static int ofonly __read_mostly;19#include <linux/fb.h>
20#include <linux/string.h>
22 21
23const char *fb_mode_option;22#include <video/cmdline.h>
24EXPORT_SYMBOL_GPL(fb_mode_option);
25 23
26/**24/**
27 * fb_get_options - get kernel boot parameters25 * fb_get_options - get kernel boot parameters
@@ -30,78 +28,34 @@ EXPORT_SYMBOL_GPL(fb_mode_option); · 2 unmodified lines
30 * (video=<name>:<options>)28 * (video=<name>:<options>)
31 * @option: the option will be stored here29 * @option: the option will be stored here
32 *30 *
31 * The caller owns the string returned in @option and is
32 * responsible for releasing the memory.
33 *
33 * NOTE: Needed to maintain backwards compatibility34 * NOTE: Needed to maintain backwards compatibility
34 */35 */
35int fb_get_options(const char *name, char **option)36int fb_get_options(const char *name, char **option)
36{37{
37 char *opt, *options = NULL;38 const char *options = NULL;
38 int retval = 0;39 bool is_of = false;
39 int name_len = strlen(name), i;40 bool enabled;
40
41 if (name_len && ofonly && strncmp(name, "offb", 4))
42 retval = 1;
43 41
44 if (name_len && !retval) {42 if (name)
45 for (i = 0; i < FB_MAX; i++) {43 is_of = strncmp(name, "offb", 4);
46 if (video_options[i] == NULL)
47 continue;
48 if (!video_options[i][0])
49 continue;
50 opt = video_options[i];
51 if (!strncmp(name, opt, name_len) &&
52 opt[name_len] == ':')
53 options = opt + name_len + 1;
54 }
55 }
56 /* No match, pass global option */
57 if (!options && option && fb_mode_option)
58 options = kstrdup(fb_mode_option, GFP_KERNEL);
59 if (options && !strncmp(options, "off", 3))
60 retval = 1;
61
62 if (option)
63 *option = options;
64
65 return retval;
66}
67EXPORT_SYMBOL(fb_get_options);
68 44
69/**45 enabled = __video_get_options(name, &options, is_of);
70 * video_setup - process command line options
71 * @options: string of options
72 *
73 * Process command line options for frame buffer subsystem.
74 *
75 * NOTE: This function is a __setup and __init function.
76 * It only stores the options. Drivers have to call
77 * fb_get_options() as necessary.
78 */
79static int __init video_setup(char *options)
80{
81 if (!options || !*options)
82 goto out;
83 46
84 if (!strncmp(options, "ofonly", 6)) {47 if (options) {
85 ofonly = 1;48 if (!strncmp(options, "off", 3))
86 goto out;49 enabled = false;
87 }50 }
88 51
89 if (strchr(options, ':')) {52 if (option) {
90 /* named */53 if (options)
91 int i;54 *option = kstrdup(options, GFP_KERNEL);
92 55 else
93 for (i = 0; i < FB_MAX; i++) {56 *option = NULL;
94 if (video_options[i] == NULL) {
95 video_options[i] = options;
96 break;
97 }
98 }
99 } else {
100 /* global */
101 fb_mode_option = options;
102 }57 }
103 58
104out:59 return enabled ? 0 : 1; // 0 on success, 1 otherwise
105 return 1;
106}60}
107__setup("video=", video_setup);61EXPORT_SYMBOL(fb_get_options);
drivers/video/fbdev/core/modedb.c+6−2
@@ -620,6 +620,7 @@ int fb_find_mode(struct fb_var_screeninfo *var, · 619 unmodified lines
620 const struct fb_videomode *default_mode,620 const struct fb_videomode *default_mode,
621 unsigned int default_bpp)621 unsigned int default_bpp)
622{622{
623 char *mode_option_buf = NULL;
623 int i;624 int i;
624 625
625 /* Set up defaults */626 /* Set up defaults */
@@ -635,8 +636,10 @@ int fb_find_mode(struct fb_var_screeninfo *var, · 9 unmodified lines
635 default_bpp = 8;636 default_bpp = 8;
636 637
637 /* Did the user specify a video mode? */638 /* Did the user specify a video mode? */
638 if (!mode_option)639 if (!mode_option) {
639 mode_option = fb_mode_option;640 fb_get_options(NULL, &mode_option_buf);
641 mode_option = mode_option_buf;
642 }
640 if (mode_option) {643 if (mode_option) {
641 const char *name = mode_option;644 const char *name = mode_option;
642 unsigned int namelen = strlen(name);645 unsigned int namelen = strlen(name);
@@ -715,6 +718,7 @@ int fb_find_mode(struct fb_var_screeninfo *var, · 72 unmodified lines
715 res_specified = 1;718 res_specified = 1;
716 }719 }
717done:720done:
721 kfree(mode_option_buf);
718 if (cvt) {722 if (cvt) {
719 struct fb_videomode cvt_mode;723 struct fb_videomode cvt_mode;
720 int ret;724 int ret;
include/drm/drm_atomic_helper.h+26−0
@@ -209,6 +209,32 @@ int drm_atomic_helper_page_flip_target( · 208 unmodified lines
209 __drm_atomic_get_current_plane_state((crtc_state)->state, \209 __drm_atomic_get_current_plane_state((crtc_state)->state, \
210 plane)))210 plane)))
211 211
212/**
213 * drm_atomic_plane_enabling - check whether a plane is being enabled
214 * @old_plane_state: old atomic plane state
215 * @new_plane_state: new atomic plane state
216 *
217 * Checks the atomic state of a plane to determine whether it's being enabled
218 * or not. This also WARNs if it detects an invalid state (both CRTC and FB
219 * need to either both be NULL or both be non-NULL).
220 *
221 * RETURNS:
222 * True if the plane is being enabled, false otherwise.
223 */
224static inline bool drm_atomic_plane_enabling(struct drm_plane_state *old_plane_state,
225 struct drm_plane_state *new_plane_state)
226{
227 /*
228 * When enabling a plane, CRTC and FB should always be set together.
229 * Anything else should be considered a bug in the atomic core, so we
230 * gently warn about it.
231 */
232 WARN_ON((!new_plane_state->crtc && new_plane_state->fb) ||
233 (new_plane_state->crtc && !new_plane_state->fb));
234
235 return !old_plane_state->crtc && new_plane_state->crtc;
236}
237
212/**238/**
213 * drm_atomic_plane_disabling - check whether a plane is being disabled239 * drm_atomic_plane_disabling - check whether a plane is being disabled
214 * @old_plane_state: old atomic plane state240 * @old_plane_state: old atomic plane state
include/drm/drm_displayid.h+11−1
@@ -139,7 +139,11 @@ struct displayid_vesa_vendor_specific_block { · 138 unmodified lines
139 u8 mso;139 u8 mso;
140} __packed;140} __packed;
141 141
142/* DisplayID iteration */142/*
143 * DisplayID iteration.
144 *
145 * Do not access directly, this is private.
146 */
143struct displayid_iter {147struct displayid_iter {
144 const struct drm_edid *drm_edid;148 const struct drm_edid *drm_edid;
145 149
@@ -147,6 +151,9 @@ struct displayid_iter { · 1 unmodified line
147 int length;151 int length;
148 int idx;152 int idx;
149 int ext_index;153 int ext_index;
154
155 u8 version;
156 u8 primary_use;
150};157};
151 158
152void displayid_iter_edid_begin(const struct drm_edid *drm_edid,159void displayid_iter_edid_begin(const struct drm_edid *drm_edid,
@@ -157,4 +164,7 @@ __displayid_iter_next(struct displayid_iter *iter); · 4 unmodified lines
157 while (((__block) = __displayid_iter_next(__iter)))164 while (((__block) = __displayid_iter_next(__iter)))
158void displayid_iter_end(struct displayid_iter *iter);165void displayid_iter_end(struct displayid_iter *iter);
159 166
167u8 displayid_version(const struct displayid_iter *iter);
168u8 displayid_primary_use(const struct displayid_iter *iter);
169
160#endif170#endif
include/drm/drm_drv.h+0−19
@@ -400,25 +400,6 @@ struct drm_driver { · 399 unmodified lines
400 int (*dumb_map_offset)(struct drm_file *file_priv,400 int (*dumb_map_offset)(struct drm_file *file_priv,
401 struct drm_device *dev, uint32_t handle,401 struct drm_device *dev, uint32_t handle,
402 uint64_t *offset);402 uint64_t *offset);
403 /**
404 * @dumb_destroy:
405 *
406 * This destroys the userspace handle for the given dumb backing storage buffer.
407 * Since buffer objects must be reference counted in the kernel a buffer object
408 * won't be immediately freed if a framebuffer modeset object still uses it.
409 *
410 * Called by the user via ioctl.
411 *
412 * The default implementation is drm_gem_dumb_destroy(). GEM based drivers
413 * must not overwrite this.
414 *
415 * Returns:
416 *
417 * Zero on success, negative errno on failure.
418 */
419 int (*dumb_destroy)(struct drm_file *file_priv,
420 struct drm_device *dev,
421 uint32_t handle);
422 403
423 /** @major: driver major number */404 /** @major: driver major number */
424 int major;405 int major;
include/drm/drm_edid.h+9−3
@@ -61,9 +61,15 @@ struct std_timing { · 60 unmodified lines
61 u8 vfreq_aspect;61 u8 vfreq_aspect;
62} __attribute__((packed));62} __attribute__((packed));
63 63
64#define DRM_EDID_PT_HSYNC_POSITIVE (1 << 1)64#define DRM_EDID_PT_SYNC_MASK (3 << 3)
65#define DRM_EDID_PT_VSYNC_POSITIVE (1 << 2)65# define DRM_EDID_PT_ANALOG_CSYNC (0 << 3)
66#define DRM_EDID_PT_SEPARATE_SYNC (3 << 3)66# define DRM_EDID_PT_BIPOLAR_ANALOG_CSYNC (1 << 3)
67# define DRM_EDID_PT_DIGITAL_CSYNC (2 << 3)
68# define DRM_EDID_PT_CSYNC_ON_RGB (1 << 1) /* analog csync only */
69# define DRM_EDID_PT_CSYNC_SERRATE (1 << 2)
70# define DRM_EDID_PT_DIGITAL_SEPARATE_SYNC (3 << 3)
71# define DRM_EDID_PT_HSYNC_POSITIVE (1 << 1) /* also digital csync */
72# define DRM_EDID_PT_VSYNC_POSITIVE (1 << 2)
67#define DRM_EDID_PT_STEREO (1 << 5)73#define DRM_EDID_PT_STEREO (1 << 5)
68#define DRM_EDID_PT_INTERLACED (1 << 7)74#define DRM_EDID_PT_INTERLACED (1 << 7)
69 75
include/drm/drm_gem.h+12−0
@@ -164,6 +164,16 @@ struct drm_gem_object_funcs { · 163 unmodified lines
164 */164 */
165 int (*mmap)(struct drm_gem_object *obj, struct vm_area_struct *vma);165 int (*mmap)(struct drm_gem_object *obj, struct vm_area_struct *vma);
166 166
167 /**
168 * @evict:
169 *
170 * Evicts gem object out from memory. Used by the drm_gem_object_evict()
171 * helper. Returns 0 on success, -errno otherwise.
172 *
173 * This callback is optional.
174 */
175 int (*evict)(struct drm_gem_object *obj);
176
167 /**177 /**
168 * @vm_ops:178 * @vm_ops:
169 *179 *
@@ -479,4 +489,6 @@ void drm_gem_lru_move_tail(struct drm_gem_lru *lru, struct drm_gem_object *obj); · 309 unmodified lines
479unsigned long drm_gem_lru_scan(struct drm_gem_lru *lru, unsigned nr_to_scan,489unsigned long drm_gem_lru_scan(struct drm_gem_lru *lru, unsigned nr_to_scan,
480 bool (*shrink)(struct drm_gem_object *obj));490 bool (*shrink)(struct drm_gem_object *obj));
481 491
492int drm_gem_evict(struct drm_gem_object *obj);
493
482#endif /* __DRM_GEM_H__ */494#endif /* __DRM_GEM_H__ */
include/drm/drm_gem_shmem_helper.h+15−15
@@ -60,20 +60,6 @@ struct drm_gem_shmem_object { · 59 unmodified lines
60 */60 */
61 struct list_head madv_list;61 struct list_head madv_list;
62 62
63 /**
64 * @pages_mark_dirty_on_put:
65 *
66 * Mark pages as dirty when they are put.
67 */
68 unsigned int pages_mark_dirty_on_put : 1;
69
70 /**
71 * @pages_mark_accessed_on_put:
72 *
73 * Mark pages as accessed when they are put.
74 */
75 unsigned int pages_mark_accessed_on_put : 1;
76
77 /**63 /**
78 * @sgt: Scatter/gather table for imported PRIME buffers64 * @sgt: Scatter/gather table for imported PRIME buffers
79 */65 */
@@ -97,10 +83,24 @@ struct drm_gem_shmem_object { · 17 unmodified lines
97 */83 */
98 unsigned int vmap_use_count;84 unsigned int vmap_use_count;
99 85
86 /**
87 * @pages_mark_dirty_on_put:
88 *
89 * Mark pages as dirty when they are put.
90 */
91 bool pages_mark_dirty_on_put : 1;
92
93 /**
94 * @pages_mark_accessed_on_put:
95 *
96 * Mark pages as accessed when they are put.
97 */
98 bool pages_mark_accessed_on_put : 1;
99
100 /**100 /**
101 * @map_wc: map object write-combined (instead of using shmem defaults).101 * @map_wc: map object write-combined (instead of using shmem defaults).
102 */102 */
103 bool map_wc;103 bool map_wc : 1;
104};104};
105 105
106#define to_drm_gem_shmem_obj(obj) \106#define to_drm_gem_shmem_obj(obj) \
include/drm/drm_modeset_helper_vtables.h+28−1
@@ -1331,6 +1331,32 @@ struct drm_plane_helper_funcs { · 1330 unmodified lines
1331 */1331 */
1332 void (*atomic_update)(struct drm_plane *plane,1332 void (*atomic_update)(struct drm_plane *plane,
1333 struct drm_atomic_state *state);1333 struct drm_atomic_state *state);
1334
1335 /**
1336 * @atomic_enable:
1337 *
1338 * Drivers should use this function to unconditionally enable a plane.
1339 * This hook is called in-between the &drm_crtc_helper_funcs.atomic_begin
1340 * and drm_crtc_helper_funcs.atomic_flush callbacks. It is called after
1341 * @atomic_update, which will be called for all enabled planes. Drivers
1342 * that use @atomic_enable should set up a plane in @atomic_update and
1343 * afterwards enable the plane in @atomic_enable. If a plane needs to be
1344 * enabled before installing the scanout buffer, drivers can still do
1345 * so in @atomic_update.
1346 *
1347 * Note that the power state of the display pipe when this function is
1348 * called depends upon the exact helpers and calling sequence the driver
1349 * has picked. See drm_atomic_helper_commit_planes() for a discussion of
1350 * the tradeoffs and variants of plane commit helpers.
1351 *
1352 * This callback is used by the atomic modeset helpers, but it is
1353 * optional. If implemented, @atomic_enable should be the inverse of
1354 * @atomic_disable. Drivers that don't want to use either can still
1355 * implement the complete plane update in @atomic_update.
1356 */
1357 void (*atomic_enable)(struct drm_plane *plane,
1358 struct drm_atomic_state *state);
1359
1334 /**1360 /**
1335 * @atomic_disable:1361 * @atomic_disable:
1336 *1362 *
@@ -1351,7 +1377,8 @@ struct drm_plane_helper_funcs { · 14 unmodified lines
1351 * the tradeoffs and variants of plane commit helpers.1377 * the tradeoffs and variants of plane commit helpers.
1352 *1378 *
1353 * This callback is used by the atomic modeset helpers and by the1379 * This callback is used by the atomic modeset helpers and by the
1354 * transitional plane helpers, but it is optional.1380 * transitional plane helpers, but it is optional. It's intended to
1381 * reverse the effects of @atomic_enable.
1355 */1382 */
1356 void (*atomic_disable)(struct drm_plane *plane,1383 void (*atomic_disable)(struct drm_plane *plane,
1357 struct drm_atomic_state *state);1384 struct drm_atomic_state *state);
include/drm/drm_of.h+12−0
@@ -15,6 +15,8 @@ struct drm_encoder; · 14 unmodified lines
15struct drm_panel;15struct drm_panel;
16struct drm_bridge;16struct drm_bridge;
17struct device_node;17struct device_node;
18struct mipi_dsi_device_info;
19struct mipi_dsi_host;
18 20
19/**21/**
20 * enum drm_lvds_dual_link_pixels - Pixel order of an LVDS dual-link connection22 * 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#endif132#endif
131 133
134#if IS_ENABLED(CONFIG_OF) && IS_ENABLED(CONFIG_DRM_MIPI_DSI)
135struct mipi_dsi_host *drm_of_get_dsi_bus(struct device *dev);
136#else
137static inline struct
138mipi_dsi_host *drm_of_get_dsi_bus(struct device *dev)
139{
140 return ERR_PTR(-EINVAL);
141}
142#endif /* CONFIG_OF && CONFIG_DRM_MIPI_DSI */
143
132/*144/*
133 * drm_of_panel_bridge_remove - remove panel bridge145 * drm_of_panel_bridge_remove - remove panel bridge
134 * @np: device tree node containing panel bridge output ports146 * @np: device tree node containing panel bridge output ports
include/drm/drm_suballoc.h+108−0
@@ -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 */
24struct 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 */
42struct 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
51void drm_suballoc_manager_init(struct drm_suballoc_manager *sa_manager,
52 size_t size, size_t align);
53
54void drm_suballoc_manager_fini(struct drm_suballoc_manager *sa_manager);
55
56struct drm_suballoc *
57drm_suballoc_new(struct drm_suballoc_manager *sa_manager, size_t size,
58 gfp_t gfp, bool intr, size_t align);
59
60void 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 */
68static 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 */
79static 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 */
90static inline size_t drm_suballoc_size(struct drm_suballoc *sa)
91{
92 return sa->eoffset - sa->soffset;
93}
94
95#ifdef CONFIG_DEBUG_FS
96void drm_suballoc_dump_debug_info(struct drm_suballoc_manager *sa_manager,
97 struct drm_printer *p,
98 unsigned long long suballoc_base);
99#else
100static inline void
101drm_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_ */
include/drm/gpu_scheduler.h+6−0
@@ -48,6 +48,8 @@ struct drm_gem_object; · 47 unmodified lines
48struct drm_gpu_scheduler;48struct drm_gpu_scheduler;
49struct drm_sched_rq;49struct drm_sched_rq;
50 50
51struct drm_file;
52
51/* These are often used as an (initial) index53/* These are often used as an (initial) index
52 * to an array, and as such should start at 0.54 * to an array, and as such should start at 0.
53 */55 */
@@ -522,6 +524,10 @@ int drm_sched_job_init(struct drm_sched_job *job, · 468 unmodified lines
522void drm_sched_job_arm(struct drm_sched_job *job);524void drm_sched_job_arm(struct drm_sched_job *job);
523int drm_sched_job_add_dependency(struct drm_sched_job *job,525int drm_sched_job_add_dependency(struct drm_sched_job *job,
524 struct dma_fence *fence);526 struct dma_fence *fence);
527int drm_sched_job_add_syncobj_dependency(struct drm_sched_job *job,
528 struct drm_file *file,
529 u32 handle,
530 u32 point);
525int drm_sched_job_add_resv_dependencies(struct drm_sched_job *job,531int drm_sched_job_add_resv_dependencies(struct drm_sched_job *job,
526 struct dma_resv *resv,532 struct dma_resv *resv,
527 enum dma_resv_usage usage);533 enum dma_resv_usage usage);
include/drm/ttm/ttm_device.h+1−1
@@ -141,7 +141,7 @@ struct ttm_device_funcs { · 140 unmodified lines
141 * the graphics address space141 * the graphics address space
142 * @ctx: context for this move with parameters142 * @ctx: context for this move with parameters
143 * @new_mem: the new memory region receiving the buffer143 * @new_mem: the new memory region receiving the buffer
144 @ @hop: placement for driver directed intermediate hop144 * @hop: placement for driver directed intermediate hop
145 *145 *
146 * Move a buffer between two memory regions.146 * Move a buffer between two memory regions.
147 * Returns errno -EMULTIHOP if driver requests a hop147 * Returns errno -EMULTIHOP if driver requests a hop
include/linux/fb.h+0−1
@@ -765,7 +765,6 @@ struct dmt_videomode { · 764 unmodified lines
765 const struct fb_videomode *mode;765 const struct fb_videomode *mode;
766};766};
767 767
768extern const char *fb_mode_option;
769extern const struct fb_videomode vesa_modes[];768extern const struct fb_videomode vesa_modes[];
770extern const struct dmt_videomode dmt_modes[];769extern const struct dmt_videomode dmt_modes[];
771 770
include/uapi/drm/drm.h+55−2
@@ -972,6 +972,19 @@ extern "C" { · 971 unmodified lines
972#define DRM_IOCTL_GET_STATS DRM_IOR( 0x06, struct drm_stats)972#define DRM_IOCTL_GET_STATS DRM_IOR( 0x06, struct drm_stats)
973#define DRM_IOCTL_SET_VERSION DRM_IOWR(0x07, struct drm_set_version)973#define DRM_IOCTL_SET_VERSION DRM_IOWR(0x07, struct drm_set_version)
974#define DRM_IOCTL_MODESET_CTL DRM_IOW(0x08, struct drm_modeset_ctl)974#define DRM_IOCTL_MODESET_CTL DRM_IOW(0x08, struct drm_modeset_ctl)
975/**
976 * DRM_IOCTL_GEM_CLOSE - Close a GEM handle.
977 *
978 * GEM handles are not reference-counted by the kernel. User-space is
979 * responsible for managing their lifetime. For example, if user-space imports
980 * the same memory object twice on the same DRM file description, the same GEM
981 * handle is returned by both imports, and user-space needs to ensure
982 * &DRM_IOCTL_GEM_CLOSE is performed once only. The same situation can happen
983 * when a memory object is allocated, then exported and imported again on the
984 * same DRM file description. The &DRM_IOCTL_MODE_GETFB2 IOCTL is an exception
985 * and always returns fresh new GEM handles even if an existing GEM handle
986 * already refers to the same memory object before the IOCTL is performed.
987 */
975#define DRM_IOCTL_GEM_CLOSE DRM_IOW (0x09, struct drm_gem_close)988#define DRM_IOCTL_GEM_CLOSE DRM_IOW (0x09, struct drm_gem_close)
976#define DRM_IOCTL_GEM_FLINK DRM_IOWR(0x0a, struct drm_gem_flink)989#define DRM_IOCTL_GEM_FLINK DRM_IOWR(0x0a, struct drm_gem_flink)
977#define DRM_IOCTL_GEM_OPEN DRM_IOWR(0x0b, struct drm_gem_open)990#define DRM_IOCTL_GEM_OPEN DRM_IOWR(0x0b, struct drm_gem_open)
@@ -1012,7 +1025,37 @@ extern "C" { · 34 unmodified lines
1012#define DRM_IOCTL_UNLOCK DRM_IOW( 0x2b, struct drm_lock)1025#define DRM_IOCTL_UNLOCK DRM_IOW( 0x2b, struct drm_lock)
1013#define DRM_IOCTL_FINISH DRM_IOW( 0x2c, struct drm_lock)1026#define DRM_IOCTL_FINISH DRM_IOW( 0x2c, struct drm_lock)
1014 1027
1028/**
1029 * DRM_IOCTL_PRIME_HANDLE_TO_FD - Convert a GEM handle to a DMA-BUF FD.
1030 *
1031 * User-space sets &drm_prime_handle.handle with the GEM handle to export and
1032 * &drm_prime_handle.flags, and gets back a DMA-BUF file descriptor in
1033 * &drm_prime_handle.fd.
1034 *
1035 * The export can fail for any driver-specific reason, e.g. because export is
1036 * not supported for this specific GEM handle (but might be for others).
1037 *
1038 * Support for exporting DMA-BUFs is advertised via &DRM_PRIME_CAP_EXPORT.
1039 */
1015#define DRM_IOCTL_PRIME_HANDLE_TO_FD DRM_IOWR(0x2d, struct drm_prime_handle)1040#define DRM_IOCTL_PRIME_HANDLE_TO_FD DRM_IOWR(0x2d, struct drm_prime_handle)
1041/**
1042 * DRM_IOCTL_PRIME_FD_TO_HANDLE - Convert a DMA-BUF FD to a GEM handle.
1043 *
1044 * User-space sets &drm_prime_handle.fd with a DMA-BUF file descriptor to
1045 * import, and gets back a GEM handle in &drm_prime_handle.handle.
1046 * &drm_prime_handle.flags is unused.
1047 *
1048 * If an existing GEM handle refers to the memory object backing the DMA-BUF,
1049 * that GEM handle is returned. Therefore user-space which needs to handle
1050 * arbitrary DMA-BUFs must have a user-space lookup data structure to manually
1051 * reference-count duplicated GEM handles. For more information see
1052 * &DRM_IOCTL_GEM_CLOSE.
1053 *
1054 * The import can fail for any driver-specific reason, e.g. because import is
1055 * only supported for DMA-BUFs allocated on this DRM device.
1056 *
1057 * Support for importing DMA-BUFs is advertised via &DRM_PRIME_CAP_IMPORT.
1058 */
1016#define DRM_IOCTL_PRIME_FD_TO_HANDLE DRM_IOWR(0x2e, struct drm_prime_handle)1059#define DRM_IOCTL_PRIME_FD_TO_HANDLE DRM_IOWR(0x2e, struct drm_prime_handle)
1017 1060
1018#define DRM_IOCTL_AGP_ACQUIRE DRM_IO( 0x30)1061#define DRM_IOCTL_AGP_ACQUIRE DRM_IO( 0x30)
@@ -1104,8 +1147,13 @@ extern "C" { · 85 unmodified lines
1104 * struct as the output.1147 * struct as the output.
1105 *1148 *
1106 * If the client is DRM master or has &CAP_SYS_ADMIN, &drm_mode_fb_cmd2.handles1149 * 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 a1150 * will be filled with GEM buffer handles. Fresh new GEM handles are always
1108 * zero handle -- this can be used to compute the number of planes.1151 * returned, even if another GEM handle referring to the same memory object
1152 * already exists on the DRM file description. The caller is responsible for
1153 * removing the new handles, e.g. via the &DRM_IOCTL_GEM_CLOSE IOCTL. The same
1154 * new handle will be returned for multiple planes in case they use the same
1155 * memory object. Planes are valid until one has a zero handle -- this can be
1156 * used to compute the number of planes.
1109 *1157 *
1110 * Otherwise, &drm_mode_fb_cmd2.handles will be zeroed and planes are valid1158 * Otherwise, &drm_mode_fb_cmd2.handles will be zeroed and planes are valid
1111 * until one has a zero &drm_mode_fb_cmd2.pitches.1159 * until one has a zero &drm_mode_fb_cmd2.pitches.
@@ -1113,6 +1161,11 @@ extern "C" { · 1 unmodified line
1113 * If the framebuffer has a format modifier, &DRM_MODE_FB_MODIFIERS will be set1161 * If the framebuffer has a format modifier, &DRM_MODE_FB_MODIFIERS will be set
1114 * in &drm_mode_fb_cmd2.flags and &drm_mode_fb_cmd2.modifier will contain the1162 * in &drm_mode_fb_cmd2.flags and &drm_mode_fb_cmd2.modifier will contain the
1115 * modifier. Otherwise, user-space must ignore &drm_mode_fb_cmd2.modifier.1163 * modifier. Otherwise, user-space must ignore &drm_mode_fb_cmd2.modifier.
1164 *
1165 * To obtain DMA-BUF FDs for each plane without leaking GEM handles, user-space
1166 * can export each handle via &DRM_IOCTL_PRIME_HANDLE_TO_FD, then immediately
1167 * close each unique handle via &DRM_IOCTL_GEM_CLOSE, making sure to not
1168 * double-close handles which are specified multiple times in the array.
1116 */1169 */
1117#define DRM_IOCTL_MODE_GETFB2 DRM_IOWR(0xCE, struct drm_mode_fb_cmd2)1170#define DRM_IOCTL_MODE_GETFB2 DRM_IOWR(0xCE, struct drm_mode_fb_cmd2)
1118 1171
include/video/cmdline.h+20−0
@@ -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)
9const char *video_get_options(const char *name);
10
11/* exported for compatibility with fbdev; don't use in new code */
12bool __video_get_options(const char *name, const char **option, bool is_of);
13#else
14static inline const char *video_get_options(const char *name)
15{
16 return NULL;
17}
18#endif
19
20#endif