From 258905cb9a6414be5c9ca4aa20ef855f8dc894d4 Mon Sep 17 00:00:00 2001 From: "hongchi.peng" Date: Mon, 26 Aug 2024 10:45:17 +0800 Subject: [PATCH 01/11] drm: komeda: Fix an issue related to normalized zpos We use komeda_crtc_normalize_zpos to normalize zpos of affected planes to their blending zorder in CU. If there's only one slave plane in affected planes and its layer_split property is enabled, order++ for its split layer, so that when calculating the normalized_zpos of master planes, the split layer of the slave plane is included, but the max_slave_zorder does not include the split layer and keep zero because there's only one slave plane in affacted planes, although we actually use two slave layers in this commit. In most cases, this bug does not result in a commit failure, but assume the following situation: slave_layer 0: zpos = 0, layer split enabled, normalized_zpos = 0;(use slave_layer 2 as its split layer) master_layer 0: zpos = 2, layer_split enabled, normalized_zpos = 2;(use master_layer 2 as its split layer) master_layer 1: zpos = 4, normalized_zpos = 4; master_layer 3: zpos = 5, normalized_zpos = 5; kcrtc_st->max_slave_zorder = 0; When we use master_layer 3 as a input of CU in function komeda_compiz_set_input and check it with function komeda_component_check_input, the parameter idx is equal to normailzed_zpos minus max_slave_zorder, the value of idx is 5 and is euqal to CU's max_active_inputs, so that komeda_component_check_input returns a -EINVAL value. To fix the bug described above, when calculating the max_slave_zorder with the layer_split enabled, count the split layer in this calculation directly. Signed-off-by: hongchi.peng Acked-by: Liviu Dudau Signed-off-by: Liviu Dudau Link: https://patchwork.freedesktop.org/patch/msgid/20240826024517.3739-1-hongchi.peng@siengine.com --- drivers/gpu/drm/arm/display/komeda/komeda_kms.c | 10 +++++++--- 1 file changed, 7 insertions(+), 3 deletions(-) diff --git a/drivers/gpu/drm/arm/display/komeda/komeda_kms.c b/drivers/gpu/drm/arm/display/komeda/komeda_kms.c index fe46b0ebefea..e5eb5d672bcd 100644 --- a/drivers/gpu/drm/arm/display/komeda/komeda_kms.c +++ b/drivers/gpu/drm/arm/display/komeda/komeda_kms.c @@ -160,6 +160,7 @@ static int komeda_crtc_normalize_zpos(struct drm_crtc *crtc, struct drm_plane *plane; struct list_head zorder_list; int order = 0, err; + u32 slave_zpos = 0; DRM_DEBUG_ATOMIC("[CRTC:%d:%s] calculating normalized zpos values\n", crtc->base.id, crtc->name); @@ -199,10 +200,13 @@ static int komeda_crtc_normalize_zpos(struct drm_crtc *crtc, plane_st->zpos, plane_st->normalized_zpos); /* calculate max slave zorder */ - if (has_bit(drm_plane_index(plane), kcrtc->slave_planes)) + if (has_bit(drm_plane_index(plane), kcrtc->slave_planes)) { + slave_zpos = plane_st->normalized_zpos; + if (to_kplane_st(plane_st)->layer_split) + slave_zpos++; kcrtc_st->max_slave_zorder = - max(plane_st->normalized_zpos, - kcrtc_st->max_slave_zorder); + max(slave_zpos, kcrtc_st->max_slave_zorder); + } } crtc_st->zpos_changed = true; From f33b9ab0495b7e3bb01bf6d76045f078e20ada65 Mon Sep 17 00:00:00 2001 From: Dave Airlie Date: Wed, 28 Aug 2024 12:37:19 +1000 Subject: [PATCH 02/11] nouveau: fix the fwsec sb verification register. This aligns with what open gpu does, the 0x15 hex is just to trick you. Fixes: 176fdcbddfd2 ("drm/nouveau/gsp/r535: add support for booting GSP-RM") Reviewed-by: Ben Skeggs Signed-off-by: Dave Airlie Signed-off-by: Danilo Krummrich Link: https://patchwork.freedesktop.org/patch/msgid/20240828023720.1596602-1-airlied@gmail.com --- drivers/gpu/drm/nouveau/nvkm/subdev/gsp/fwsec.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/gpu/drm/nouveau/nvkm/subdev/gsp/fwsec.c b/drivers/gpu/drm/nouveau/nvkm/subdev/gsp/fwsec.c index 330d72b1a4af..52412965fac1 100644 --- a/drivers/gpu/drm/nouveau/nvkm/subdev/gsp/fwsec.c +++ b/drivers/gpu/drm/nouveau/nvkm/subdev/gsp/fwsec.c @@ -324,7 +324,7 @@ nvkm_gsp_fwsec_sb(struct nvkm_gsp *gsp) return ret; /* Verify. */ - err = nvkm_rd32(device, 0x001400 + (0xf * 4)) & 0x0000ffff; + err = nvkm_rd32(device, 0x001400 + (0x15 * 4)) & 0x0000ffff; if (err) { nvkm_error(subdev, "fwsec-sb: 0x%04x\n", err); return -EIO; From 3f6b2f60b4631cd0c368da6a1587ab55a696164d Mon Sep 17 00:00:00 2001 From: Matt Coster Date: Mon, 2 Sep 2024 09:48:48 +0100 Subject: [PATCH 03/11] drm/imagination: Free pvr_vm_gpuva after unlink This caused a measurable memory leak. Although the individual allocations are small, the leaks occurs in a high-usage codepath (remapping or unmapping device memory) so they add up quickly. Fixes: ff5f643de0bf ("drm/imagination: Add GEM and VM related code") Cc: stable@vger.kernel.org Reviewed-by: Frank Binns Link: https://patchwork.freedesktop.org/patch/msgid/35867394-d8ce-4698-a8fd-919a018f1583@imgtec.com Signed-off-by: Matt Coster --- drivers/gpu/drm/imagination/pvr_vm.c | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/drivers/gpu/drm/imagination/pvr_vm.c b/drivers/gpu/drm/imagination/pvr_vm.c index e59517ba039e..97c0f772ed65 100644 --- a/drivers/gpu/drm/imagination/pvr_vm.c +++ b/drivers/gpu/drm/imagination/pvr_vm.c @@ -114,6 +114,8 @@ struct pvr_vm_gpuva { struct drm_gpuva base; }; +#define to_pvr_vm_gpuva(va) container_of_const(va, struct pvr_vm_gpuva, base) + enum pvr_vm_bind_type { PVR_VM_BIND_TYPE_MAP, PVR_VM_BIND_TYPE_UNMAP, @@ -386,6 +388,7 @@ pvr_vm_gpuva_unmap(struct drm_gpuva_op *op, void *op_ctx) drm_gpuva_unmap(&op->unmap); drm_gpuva_unlink(op->unmap.va); + kfree(to_pvr_vm_gpuva(op->unmap.va)); return 0; } @@ -433,6 +436,7 @@ pvr_vm_gpuva_remap(struct drm_gpuva_op *op, void *op_ctx) } drm_gpuva_unlink(op->remap.unmap->va); + kfree(to_pvr_vm_gpuva(op->remap.unmap->va)); return 0; } From 466cb3c630a51b04995c6247d2fb73b5ce7bfd7f Mon Sep 17 00:00:00 2001 From: Dmitry Baryshkov Date: Tue, 3 Sep 2024 05:01:56 +0300 Subject: [PATCH 04/11] drm/display: stop depending on DRM_DISPLAY_HELPER Kconfig symbols should not declare dependency on DRM_DISPLAY_HELPER. Move all parts of DRM_DISPLAY_HELPER to an if DRM_DISPLAY_HELPER block. It is not possible to make those symbols select DRM_DISPLAY_HELPER because of the link issues when a part of the helper is selected to be built-in, while other part is selected to be as module. In such a case the modular part doesn't get built at all, leading to undefined symbols. The only viable alternative is to split drm_display_helper.ko into several small modules, each of them having their own dependencies. Suggested-by: Maxime Ripard Signed-off-by: Dmitry Baryshkov Link: https://patchwork.freedesktop.org/patch/msgid/20240903-drm-bridge-connector-fix-hdmi-reset-v5-1-daebde6d9857@linaro.org Signed-off-by: Maxime Ripard --- drivers/gpu/drm/display/Kconfig | 18 ++++++++---------- 1 file changed, 8 insertions(+), 10 deletions(-) diff --git a/drivers/gpu/drm/display/Kconfig b/drivers/gpu/drm/display/Kconfig index 479e62690d75..e6fc253cb4b5 100644 --- a/drivers/gpu/drm/display/Kconfig +++ b/drivers/gpu/drm/display/Kconfig @@ -1,19 +1,20 @@ # SPDX-License-Identifier: MIT +config DRM_DISPLAY_DP_AUX_BUS + tristate + depends on DRM + depends on OF || COMPILE_TEST + config DRM_DISPLAY_HELPER tristate depends on DRM help DRM helpers for display adapters. -config DRM_DISPLAY_DP_AUX_BUS - tristate - depends on DRM - depends on OF || COMPILE_TEST +if DRM_DISPLAY_HELPER config DRM_DISPLAY_DP_AUX_CEC bool "Enable DisplayPort CEC-Tunneling-over-AUX HDMI support" - depends on DRM && DRM_DISPLAY_HELPER select DRM_DISPLAY_DP_HELPER select CEC_CORE help @@ -25,7 +26,6 @@ config DRM_DISPLAY_DP_AUX_CEC config DRM_DISPLAY_DP_AUX_CHARDEV bool "DRM DP AUX Interface" - depends on DRM && DRM_DISPLAY_HELPER select DRM_DISPLAY_DP_HELPER help Choose this option to enable a /dev/drm_dp_auxN node that allows to @@ -34,7 +34,6 @@ config DRM_DISPLAY_DP_AUX_CHARDEV config DRM_DISPLAY_DP_HELPER bool - depends on DRM_DISPLAY_HELPER help DRM display helpers for DisplayPort. @@ -61,19 +60,18 @@ config DRM_DISPLAY_DP_TUNNEL_STATE_DEBUG config DRM_DISPLAY_HDCP_HELPER bool - depends on DRM_DISPLAY_HELPER help DRM display helpers for HDCP. config DRM_DISPLAY_HDMI_HELPER bool - depends on DRM_DISPLAY_HELPER help DRM display helpers for HDMI. config DRM_DISPLAY_HDMI_STATE_HELPER bool - depends on DRM_DISPLAY_HELPER select DRM_DISPLAY_HDMI_HELPER help DRM KMS state helpers for HDMI. + +endif # DRM_DISPLAY_HELPER From 9da7ec9b19d8c1ad4f44e459fa5f93ad7a117dcd Mon Sep 17 00:00:00 2001 From: Dmitry Baryshkov Date: Tue, 3 Sep 2024 05:01:57 +0300 Subject: [PATCH 05/11] drm/bridge-connector: move to DRM_DISPLAY_HELPER module drm_bridge_connector is a "leaf" driver, belonging to the display helper, rather than the "CRTC" drm_kms_helper module. Move the driver to the drm/display and add necessary Kconfig selection clauses. Suggested-by: Maxime Ripard Acked-by: Maxime Ripard Signed-off-by: Dmitry Baryshkov Link: https://patchwork.freedesktop.org/patch/msgid/20240903-drm-bridge-connector-fix-hdmi-reset-v5-2-daebde6d9857@linaro.org Signed-off-by: Maxime Ripard --- MAINTAINERS | 2 +- drivers/gpu/drm/Makefile | 1 - drivers/gpu/drm/bridge/Kconfig | 1 + drivers/gpu/drm/display/Kconfig | 5 +++++ drivers/gpu/drm/display/Makefile | 2 ++ drivers/gpu/drm/{ => display}/drm_bridge_connector.c | 0 drivers/gpu/drm/imx/dcss/Kconfig | 2 ++ drivers/gpu/drm/imx/lcdc/Kconfig | 2 ++ drivers/gpu/drm/ingenic/Kconfig | 2 ++ drivers/gpu/drm/kmb/Kconfig | 2 ++ drivers/gpu/drm/mediatek/Kconfig | 2 ++ drivers/gpu/drm/meson/Kconfig | 2 ++ drivers/gpu/drm/msm/Kconfig | 1 + drivers/gpu/drm/omapdrm/Kconfig | 2 ++ drivers/gpu/drm/renesas/rcar-du/Kconfig | 2 ++ drivers/gpu/drm/renesas/rz-du/Kconfig | 2 ++ drivers/gpu/drm/renesas/shmobile/Kconfig | 2 ++ drivers/gpu/drm/rockchip/Kconfig | 4 ++++ drivers/gpu/drm/tegra/Kconfig | 1 + drivers/gpu/drm/tidss/Kconfig | 2 ++ drivers/gpu/drm/xlnx/Kconfig | 1 + 21 files changed, 38 insertions(+), 2 deletions(-) rename drivers/gpu/drm/{ => display}/drm_bridge_connector.c (100%) diff --git a/MAINTAINERS b/MAINTAINERS index 42decde38320..515e7f4b6cd9 100644 --- a/MAINTAINERS +++ b/MAINTAINERS @@ -7452,8 +7452,8 @@ S: Maintained T: git https://gitlab.freedesktop.org/drm/misc/kernel.git F: Documentation/devicetree/bindings/display/bridge/ F: drivers/gpu/drm/bridge/ +F: drivers/gpu/drm/display/drm_bridge_connector.c F: drivers/gpu/drm/drm_bridge.c -F: drivers/gpu/drm/drm_bridge_connector.c F: include/drm/drm_bridge.h F: include/drm/drm_bridge_connector.h diff --git a/drivers/gpu/drm/Makefile b/drivers/gpu/drm/Makefile index 68cc9258ffc4..fa432a1ac9e2 100644 --- a/drivers/gpu/drm/Makefile +++ b/drivers/gpu/drm/Makefile @@ -128,7 +128,6 @@ obj-$(CONFIG_DRM_TTM_HELPER) += drm_ttm_helper.o drm_kms_helper-y := \ drm_atomic_helper.o \ drm_atomic_state_helper.o \ - drm_bridge_connector.o \ drm_crtc_helper.o \ drm_damage_helper.o \ drm_encoder_slave.o \ diff --git a/drivers/gpu/drm/bridge/Kconfig b/drivers/gpu/drm/bridge/Kconfig index c621be1a99a8..3eb955333c80 100644 --- a/drivers/gpu/drm/bridge/Kconfig +++ b/drivers/gpu/drm/bridge/Kconfig @@ -390,6 +390,7 @@ config DRM_TI_SN65DSI86 depends on OF select DRM_DISPLAY_DP_HELPER select DRM_DISPLAY_HELPER + select DRM_BRIDGE_CONNECTOR select DRM_KMS_HELPER select REGMAP_I2C select DRM_PANEL diff --git a/drivers/gpu/drm/display/Kconfig b/drivers/gpu/drm/display/Kconfig index e6fc253cb4b5..1d73fdef2a33 100644 --- a/drivers/gpu/drm/display/Kconfig +++ b/drivers/gpu/drm/display/Kconfig @@ -13,6 +13,11 @@ config DRM_DISPLAY_HELPER if DRM_DISPLAY_HELPER +config DRM_BRIDGE_CONNECTOR + bool + help + DRM connector implementation terminating DRM bridge chains. + config DRM_DISPLAY_DP_AUX_CEC bool "Enable DisplayPort CEC-Tunneling-over-AUX HDMI support" select DRM_DISPLAY_DP_HELPER diff --git a/drivers/gpu/drm/display/Makefile b/drivers/gpu/drm/display/Makefile index 629df2f4d322..fbb9d2b8acd4 100644 --- a/drivers/gpu/drm/display/Makefile +++ b/drivers/gpu/drm/display/Makefile @@ -3,6 +3,8 @@ obj-$(CONFIG_DRM_DISPLAY_DP_AUX_BUS) += drm_dp_aux_bus.o drm_display_helper-y := drm_display_helper_mod.o +drm_display_helper-$(CONFIG_DRM_BRIDGE_CONNECTOR) += \ + drm_bridge_connector.o drm_display_helper-$(CONFIG_DRM_DISPLAY_DP_HELPER) += \ drm_dp_dual_mode_helper.o \ drm_dp_helper.o \ diff --git a/drivers/gpu/drm/drm_bridge_connector.c b/drivers/gpu/drm/display/drm_bridge_connector.c similarity index 100% rename from drivers/gpu/drm/drm_bridge_connector.c rename to drivers/gpu/drm/display/drm_bridge_connector.c diff --git a/drivers/gpu/drm/imx/dcss/Kconfig b/drivers/gpu/drm/imx/dcss/Kconfig index 3ffc061d392b..59e3b6a1dff0 100644 --- a/drivers/gpu/drm/imx/dcss/Kconfig +++ b/drivers/gpu/drm/imx/dcss/Kconfig @@ -2,6 +2,8 @@ config DRM_IMX_DCSS tristate "i.MX8MQ DCSS" select IMX_IRQSTEER select DRM_KMS_HELPER + select DRM_DISPLAY_HELPER + select DRM_BRIDGE_CONNECTOR select DRM_GEM_DMA_HELPER select VIDEOMODE_HELPERS depends on DRM && ARCH_MXC && ARM64 diff --git a/drivers/gpu/drm/imx/lcdc/Kconfig b/drivers/gpu/drm/imx/lcdc/Kconfig index 7e57922bbd9d..9c28bb0f4662 100644 --- a/drivers/gpu/drm/imx/lcdc/Kconfig +++ b/drivers/gpu/drm/imx/lcdc/Kconfig @@ -3,5 +3,7 @@ config DRM_IMX_LCDC depends on DRM && (ARCH_MXC || COMPILE_TEST) select DRM_GEM_DMA_HELPER select DRM_KMS_HELPER + select DRM_DISPLAY_HELPER + select DRM_BRIDGE_CONNECTOR help Found on i.MX1, i.MX21, i.MX25 and i.MX27. diff --git a/drivers/gpu/drm/ingenic/Kconfig b/drivers/gpu/drm/ingenic/Kconfig index 3db117c5edd9..8cd7b750dffe 100644 --- a/drivers/gpu/drm/ingenic/Kconfig +++ b/drivers/gpu/drm/ingenic/Kconfig @@ -8,6 +8,8 @@ config DRM_INGENIC select DRM_BRIDGE select DRM_PANEL_BRIDGE select DRM_KMS_HELPER + select DRM_DISPLAY_HELPER + select DRM_BRIDGE_CONNECTOR select DRM_GEM_DMA_HELPER select REGMAP select REGMAP_MMIO diff --git a/drivers/gpu/drm/kmb/Kconfig b/drivers/gpu/drm/kmb/Kconfig index fd011367db1d..e5ae3ec52392 100644 --- a/drivers/gpu/drm/kmb/Kconfig +++ b/drivers/gpu/drm/kmb/Kconfig @@ -3,6 +3,8 @@ config DRM_KMB_DISPLAY depends on DRM depends on ARCH_KEEMBAY || COMPILE_TEST select DRM_KMS_HELPER + select DRM_DISPLAY_HELPER + select DRM_BRIDGE_CONNECTOR select DRM_GEM_DMA_HELPER select DRM_MIPI_DSI help diff --git a/drivers/gpu/drm/mediatek/Kconfig b/drivers/gpu/drm/mediatek/Kconfig index d6449ebae838..417ac8c9af41 100644 --- a/drivers/gpu/drm/mediatek/Kconfig +++ b/drivers/gpu/drm/mediatek/Kconfig @@ -9,6 +9,8 @@ config DRM_MEDIATEK depends on MTK_MMSYS select DRM_GEM_DMA_HELPER if DRM_FBDEV_EMULATION select DRM_KMS_HELPER + select DRM_DISPLAY_HELPER + select DRM_BRIDGE_CONNECTOR select DRM_MIPI_DSI select DRM_PANEL select MEMORY diff --git a/drivers/gpu/drm/meson/Kconfig b/drivers/gpu/drm/meson/Kconfig index 615fdd0ce41b..2544756538cc 100644 --- a/drivers/gpu/drm/meson/Kconfig +++ b/drivers/gpu/drm/meson/Kconfig @@ -4,6 +4,8 @@ config DRM_MESON depends on DRM && OF && (ARM || ARM64) depends on ARCH_MESON || COMPILE_TEST select DRM_KMS_HELPER + select DRM_DISPLAY_HELPER + select DRM_BRIDGE_CONNECTOR select DRM_GEM_DMA_HELPER select DRM_DISPLAY_CONNECTOR select VIDEOMODE_HELPERS diff --git a/drivers/gpu/drm/msm/Kconfig b/drivers/gpu/drm/msm/Kconfig index 26a4c71da63a..90c68106b63b 100644 --- a/drivers/gpu/drm/msm/Kconfig +++ b/drivers/gpu/drm/msm/Kconfig @@ -17,6 +17,7 @@ config DRM_MSM select DRM_DISPLAY_DP_AUX_BUS select DRM_DISPLAY_DP_HELPER select DRM_DISPLAY_HELPER + select DRM_BRIDGE_CONNECTOR select DRM_EXEC select DRM_KMS_HELPER select DRM_PANEL diff --git a/drivers/gpu/drm/omapdrm/Kconfig b/drivers/gpu/drm/omapdrm/Kconfig index 64e440a2649b..fbd9af758581 100644 --- a/drivers/gpu/drm/omapdrm/Kconfig +++ b/drivers/gpu/drm/omapdrm/Kconfig @@ -5,6 +5,8 @@ config DRM_OMAP depends on DRM && OF depends on ARCH_OMAP2PLUS || (COMPILE_TEST && PAGE_SIZE_LESS_THAN_64KB) select DRM_KMS_HELPER + select DRM_DISPLAY_HELPER + select DRM_BRIDGE_CONNECTOR select FB_DMAMEM_HELPERS_DEFERRED if DRM_FBDEV_EMULATION select VIDEOMODE_HELPERS select HDMI diff --git a/drivers/gpu/drm/renesas/rcar-du/Kconfig b/drivers/gpu/drm/renesas/rcar-du/Kconfig index c17e7c50492c..025677fe88d3 100644 --- a/drivers/gpu/drm/renesas/rcar-du/Kconfig +++ b/drivers/gpu/drm/renesas/rcar-du/Kconfig @@ -5,6 +5,8 @@ config DRM_RCAR_DU depends on ARM || ARM64 || COMPILE_TEST depends on ARCH_RENESAS || COMPILE_TEST select DRM_KMS_HELPER + select DRM_DISPLAY_HELPER + select DRM_BRIDGE_CONNECTOR select DRM_GEM_DMA_HELPER select VIDEOMODE_HELPERS help diff --git a/drivers/gpu/drm/renesas/rz-du/Kconfig b/drivers/gpu/drm/renesas/rz-du/Kconfig index 5f0db2c5fee6..e1a6dd322caf 100644 --- a/drivers/gpu/drm/renesas/rz-du/Kconfig +++ b/drivers/gpu/drm/renesas/rz-du/Kconfig @@ -6,6 +6,8 @@ config DRM_RZG2L_DU depends on VIDEO_RENESAS_VSP1 select DRM_GEM_DMA_HELPER select DRM_KMS_HELPER + select DRM_DISPLAY_HELPER + select DRM_BRIDGE_CONNECTOR select VIDEOMODE_HELPERS help Choose this option if you have an RZ/G2L alike chipset. diff --git a/drivers/gpu/drm/renesas/shmobile/Kconfig b/drivers/gpu/drm/renesas/shmobile/Kconfig index 027220b8fe1c..c329ab8a7a8b 100644 --- a/drivers/gpu/drm/renesas/shmobile/Kconfig +++ b/drivers/gpu/drm/renesas/shmobile/Kconfig @@ -5,6 +5,8 @@ config DRM_SHMOBILE depends on ARCH_RENESAS || ARCH_SHMOBILE || COMPILE_TEST select BACKLIGHT_CLASS_DEVICE select DRM_KMS_HELPER + select DRM_DISPLAY_HELPER + select DRM_BRIDGE_CONNECTOR select DRM_GEM_DMA_HELPER select VIDEOMODE_HELPERS help diff --git a/drivers/gpu/drm/rockchip/Kconfig b/drivers/gpu/drm/rockchip/Kconfig index 7df875e38517..23c49e91f1cc 100644 --- a/drivers/gpu/drm/rockchip/Kconfig +++ b/drivers/gpu/drm/rockchip/Kconfig @@ -86,6 +86,8 @@ config ROCKCHIP_LVDS bool "Rockchip LVDS support" depends on DRM_ROCKCHIP depends on PINCTRL && OF + select DRM_DISPLAY_HELPER + select DRM_BRIDGE_CONNECTOR help Choose this option to enable support for Rockchip LVDS controllers. Rockchip rk3288 SoC has LVDS TX Controller can be used, and it @@ -96,6 +98,8 @@ config ROCKCHIP_RGB bool "Rockchip RGB support" depends on DRM_ROCKCHIP depends on PINCTRL + select DRM_DISPLAY_HELPER + select DRM_BRIDGE_CONNECTOR help Choose this option to enable support for Rockchip RGB output. Some Rockchip CRTCs, like rv1108, can directly output parallel diff --git a/drivers/gpu/drm/tegra/Kconfig b/drivers/gpu/drm/tegra/Kconfig index 782f51d3044a..e688d8104652 100644 --- a/drivers/gpu/drm/tegra/Kconfig +++ b/drivers/gpu/drm/tegra/Kconfig @@ -8,6 +8,7 @@ config DRM_TEGRA select DRM_DISPLAY_DP_HELPER select DRM_DISPLAY_HDMI_HELPER select DRM_DISPLAY_HELPER + select DRM_BRIDGE_CONNECTOR select DRM_DISPLAY_DP_AUX_BUS select DRM_KMS_HELPER select DRM_MIPI_DSI diff --git a/drivers/gpu/drm/tidss/Kconfig b/drivers/gpu/drm/tidss/Kconfig index 378600806167..2385c56493b9 100644 --- a/drivers/gpu/drm/tidss/Kconfig +++ b/drivers/gpu/drm/tidss/Kconfig @@ -3,6 +3,8 @@ config DRM_TIDSS depends on DRM && OF depends on ARM || ARM64 || COMPILE_TEST select DRM_KMS_HELPER + select DRM_DISPLAY_HELPER + select DRM_BRIDGE_CONNECTOR select DRM_GEM_DMA_HELPER help The TI Keystone family SoCs introduced a new generation of diff --git a/drivers/gpu/drm/xlnx/Kconfig b/drivers/gpu/drm/xlnx/Kconfig index 68ee897de9d7..626e5ac4c33d 100644 --- a/drivers/gpu/drm/xlnx/Kconfig +++ b/drivers/gpu/drm/xlnx/Kconfig @@ -8,6 +8,7 @@ config DRM_ZYNQMP_DPSUB select DMA_ENGINE select DRM_DISPLAY_DP_HELPER select DRM_DISPLAY_HELPER + select DRM_BRIDGE_CONNECTOR select DRM_GEM_DMA_HELPER select DRM_KMS_HELPER select GENERIC_PHY From 9a71cf8b6fa433a8f243626ba9930a3870584e38 Mon Sep 17 00:00:00 2001 From: Dmitry Baryshkov Date: Tue, 3 Sep 2024 05:01:58 +0300 Subject: [PATCH 06/11] drm/bridge-connector: reset the HDMI connector state On HDMI connectors which use drm_bridge_connector and DRM_BRIDGE_OP_HDMI IGT chokes on the max_bpc property in several kms_properties tests due to the drm_bridge_connector failing to reset HDMI-related properties. Call __drm_atomic_helper_connector_hdmi_reset() if the drm_bridge_connector has bridge_hdmi. It is impossible to call this function from HDMI bridges, none of the bridge callbacks correspond to the drm_connector_funcs::reset(). Fixes: 6b4468b0c6ba ("drm/bridge-connector: implement glue code for HDMI connector") Reviewed-by: Maxime Ripard Acked-by: Maxime Ripard Reviewed-by: Abhinav Kumar Signed-off-by: Dmitry Baryshkov Link: https://patchwork.freedesktop.org/patch/msgid/20240903-drm-bridge-connector-fix-hdmi-reset-v5-3-daebde6d9857@linaro.org Signed-off-by: Maxime Ripard --- drivers/gpu/drm/display/Kconfig | 1 + drivers/gpu/drm/display/drm_bridge_connector.c | 13 ++++++++++++- 2 files changed, 13 insertions(+), 1 deletion(-) diff --git a/drivers/gpu/drm/display/Kconfig b/drivers/gpu/drm/display/Kconfig index 1d73fdef2a33..3b824e01c9b5 100644 --- a/drivers/gpu/drm/display/Kconfig +++ b/drivers/gpu/drm/display/Kconfig @@ -15,6 +15,7 @@ if DRM_DISPLAY_HELPER config DRM_BRIDGE_CONNECTOR bool + select DRM_DISPLAY_HDMI_STATE_HELPER help DRM connector implementation terminating DRM bridge chains. diff --git a/drivers/gpu/drm/display/drm_bridge_connector.c b/drivers/gpu/drm/display/drm_bridge_connector.c index a4fbf1eb7ac5..3da5b8bf8259 100644 --- a/drivers/gpu/drm/display/drm_bridge_connector.c +++ b/drivers/gpu/drm/display/drm_bridge_connector.c @@ -216,8 +216,19 @@ static void drm_bridge_connector_debugfs_init(struct drm_connector *connector, } } +static void drm_bridge_connector_reset(struct drm_connector *connector) +{ + struct drm_bridge_connector *bridge_connector = + to_drm_bridge_connector(connector); + + drm_atomic_helper_connector_reset(connector); + if (bridge_connector->bridge_hdmi) + __drm_atomic_helper_connector_hdmi_reset(connector, + connector->state); +} + static const struct drm_connector_funcs drm_bridge_connector_funcs = { - .reset = drm_atomic_helper_connector_reset, + .reset = drm_bridge_connector_reset, .detect = drm_bridge_connector_detect, .fill_modes = drm_helper_probe_single_connector_modes, .atomic_duplicate_state = drm_atomic_helper_connector_duplicate_state, From 5f7762042f8a5377bd8a32844db353c0311a7369 Mon Sep 17 00:00:00 2001 From: Mary Guillemard Date: Tue, 3 Sep 2024 16:49:55 +0200 Subject: [PATCH 07/11] drm/panthor: Restrict high priorities on group_create We were allowing any users to create a high priority group without any permission checks. As a result, this was allowing possible denial of service. We now only allow the DRM master or users with the CAP_SYS_NICE capability to set higher priorities than PANTHOR_GROUP_PRIORITY_MEDIUM. As the sole user of that uAPI lives in Mesa and hardcode a value of MEDIUM [1], this should be safe to do. Additionally, as those checks are performed at the ioctl level, panthor_group_create now only check for priority level validity. [1]https://gitlab.freedesktop.org/mesa/mesa/-/blob/f390835074bdf162a63deb0311d1a6de527f9f89/src/gallium/drivers/panfrost/pan_csf.c#L1038 Signed-off-by: Mary Guillemard Fixes: de8548813824 ("drm/panthor: Add the scheduler logical block") Cc: stable@vger.kernel.org Reviewed-by: Boris Brezillon Signed-off-by: Boris Brezillon Link: https://patchwork.freedesktop.org/patch/msgid/20240903144955.144278-2-mary.guillemard@collabora.com --- drivers/gpu/drm/panthor/panthor_drv.c | 23 +++++++++++++++++++++++ drivers/gpu/drm/panthor/panthor_sched.c | 2 +- include/uapi/drm/panthor_drm.h | 6 +++++- 3 files changed, 29 insertions(+), 2 deletions(-) diff --git a/drivers/gpu/drm/panthor/panthor_drv.c b/drivers/gpu/drm/panthor/panthor_drv.c index b5e7b919f241..34182f67136c 100644 --- a/drivers/gpu/drm/panthor/panthor_drv.c +++ b/drivers/gpu/drm/panthor/panthor_drv.c @@ -10,6 +10,7 @@ #include #include +#include #include #include #include @@ -996,6 +997,24 @@ static int panthor_ioctl_group_destroy(struct drm_device *ddev, void *data, return panthor_group_destroy(pfile, args->group_handle); } +static int group_priority_permit(struct drm_file *file, + u8 priority) +{ + /* Ensure that priority is valid */ + if (priority > PANTHOR_GROUP_PRIORITY_HIGH) + return -EINVAL; + + /* Medium priority and below are always allowed */ + if (priority <= PANTHOR_GROUP_PRIORITY_MEDIUM) + return 0; + + /* Higher priorities require CAP_SYS_NICE or DRM_MASTER */ + if (capable(CAP_SYS_NICE) || drm_is_current_master(file)) + return 0; + + return -EACCES; +} + static int panthor_ioctl_group_create(struct drm_device *ddev, void *data, struct drm_file *file) { @@ -1011,6 +1030,10 @@ static int panthor_ioctl_group_create(struct drm_device *ddev, void *data, if (ret) return ret; + ret = group_priority_permit(file, args->priority); + if (ret) + return ret; + ret = panthor_group_create(pfile, args, queue_args); if (ret >= 0) { args->group_handle = ret; diff --git a/drivers/gpu/drm/panthor/panthor_sched.c b/drivers/gpu/drm/panthor/panthor_sched.c index 463bcd3cf00f..12b272a912f8 100644 --- a/drivers/gpu/drm/panthor/panthor_sched.c +++ b/drivers/gpu/drm/panthor/panthor_sched.c @@ -3092,7 +3092,7 @@ int panthor_group_create(struct panthor_file *pfile, if (group_args->pad) return -EINVAL; - if (group_args->priority > PANTHOR_CSG_PRIORITY_HIGH) + if (group_args->priority >= PANTHOR_CSG_PRIORITY_COUNT) return -EINVAL; if ((group_args->compute_core_mask & ~ptdev->gpu_info.shader_present) || diff --git a/include/uapi/drm/panthor_drm.h b/include/uapi/drm/panthor_drm.h index 926b1deb1116..e23a7f9b0eac 100644 --- a/include/uapi/drm/panthor_drm.h +++ b/include/uapi/drm/panthor_drm.h @@ -692,7 +692,11 @@ enum drm_panthor_group_priority { /** @PANTHOR_GROUP_PRIORITY_MEDIUM: Medium priority group. */ PANTHOR_GROUP_PRIORITY_MEDIUM, - /** @PANTHOR_GROUP_PRIORITY_HIGH: High priority group. */ + /** + * @PANTHOR_GROUP_PRIORITY_HIGH: High priority group. + * + * Requires CAP_SYS_NICE or DRM_MASTER. + */ PANTHOR_GROUP_PRIORITY_HIGH, }; From d682eef93ebfbcd107c1a339ef24a0dcc4681fbc Mon Sep 17 00:00:00 2001 From: Ryan Walklin Date: Wed, 4 Sep 2024 13:23:21 +1200 Subject: [PATCH 08/11] dt-bindings: display: panel: Rename WL-355608-A8 panel to rg35xx-*-panel The WL-355608-A8 is a 3.5" 640x480@60Hz RGB LCD display from an unknown OEM used in a number of handheld gaming devices made by Anbernic. Previously committed using the OEM serial without a vendor prefix, however following subsequent discussion the preference is to use the integrating device vendor and name where the OEM is unknown. There are 4 RG35XX series devices from Anbernic based on an Allwinner H700 SoC using this panel, with the -Plus variant introduced first. Therefore the -Plus is used as the fallback for the subsequent -H, -2024, and -SP devices. Alter the filename and compatible string to reflect the convention. Fixes: 45b888a8980a ("dt-bindings: display: panel: Add WL-355608-A8 panel") Signed-off-by: Ryan Walklin Acked-by: Rob Herring (Arm) Signed-off-by: Maxime Ripard Link: https://patchwork.freedesktop.org/patch/msgid/20240904012456.35429-2-ryan@testtoast.com --- ...08-a8.yaml => anbernic,rg35xx-plus-panel.yaml} | 15 +++++++++++---- 1 file changed, 11 insertions(+), 4 deletions(-) rename Documentation/devicetree/bindings/display/panel/{wl-355608-a8.yaml => anbernic,rg35xx-plus-panel.yaml} (67%) diff --git a/Documentation/devicetree/bindings/display/panel/wl-355608-a8.yaml b/Documentation/devicetree/bindings/display/panel/anbernic,rg35xx-plus-panel.yaml similarity index 67% rename from Documentation/devicetree/bindings/display/panel/wl-355608-a8.yaml rename to Documentation/devicetree/bindings/display/panel/anbernic,rg35xx-plus-panel.yaml index e552d01b52b9..1d67492ebd3b 100644 --- a/Documentation/devicetree/bindings/display/panel/wl-355608-a8.yaml +++ b/Documentation/devicetree/bindings/display/panel/anbernic,rg35xx-plus-panel.yaml @@ -1,10 +1,10 @@ # SPDX-License-Identifier: (GPL-2.0-only OR BSD-2-Clause) %YAML 1.2 --- -$id: http://devicetree.org/schemas/display/panel/wl-355608-a8.yaml# +$id: http://devicetree.org/schemas/display/panel/anbernic,rg35xx-plus-panel.yaml# $schema: http://devicetree.org/meta-schemas/core.yaml# -title: WL-355608-A8 3.5" (640x480 pixels) 24-bit IPS LCD panel +title: Anbernic RG35XX series (WL-355608-A8) 3.5" 640x480 24-bit IPS LCD panel maintainers: - Ryan Walklin @@ -15,7 +15,14 @@ allOf: properties: compatible: - const: wl-355608-a8 + oneOf: + - const: anbernic,rg35xx-plus-panel + - items: + - enum: + - anbernic,rg35xx-2024-panel + - anbernic,rg35xx-h-panel + - anbernic,rg35xx-sp-panel + - const: anbernic,rg35xx-plus-panel reg: maxItems: 1 @@ -40,7 +47,7 @@ examples: #size-cells = <0>; panel@0 { - compatible = "wl-355608-a8"; + compatible = "anbernic,rg35xx-plus-panel"; reg = <0>; spi-3wire; From 76dce2a96c0f48295e92acf7a8f3fa46ea0ee524 Mon Sep 17 00:00:00 2001 From: Ryan Walklin Date: Wed, 4 Sep 2024 13:23:22 +1200 Subject: [PATCH 09/11] drm: panel: nv3052c: Correct WL-355608-A8 panel compatible As per the previous dt-binding commit, update the WL-355608-A8 panel compatible to reflect the the integrating device vendor and name as the panel OEM is unknown. Fixes: 62ea2eeba7bf ("drm: panel: nv3052c: Add WL-355608-A8 panel") Signed-off-by: Ryan Walklin Signed-off-by: Maxime Ripard Link: https://patchwork.freedesktop.org/patch/msgid/20240904012456.35429-3-ryan@testtoast.com --- drivers/gpu/drm/panel/panel-newvision-nv3052c.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/gpu/drm/panel/panel-newvision-nv3052c.c b/drivers/gpu/drm/panel/panel-newvision-nv3052c.c index c5d3ead38555..d3baccfe6286 100644 --- a/drivers/gpu/drm/panel/panel-newvision-nv3052c.c +++ b/drivers/gpu/drm/panel/panel-newvision-nv3052c.c @@ -925,7 +925,7 @@ MODULE_DEVICE_TABLE(spi, nv3052c_ids); static const struct of_device_id nv3052c_of_match[] = { { .compatible = "leadtek,ltk035c5444t", .data = <k035c5444t_panel_info }, { .compatible = "fascontek,fs035vg158", .data = &fs035vg158_panel_info }, - { .compatible = "wl-355608-a8", .data = &wl_355608_a8_panel_info }, + { .compatible = "anbernic,rg35xx-plus-panel", .data = &wl_355608_a8_panel_info }, { /* sentinel */ } }; MODULE_DEVICE_TABLE(of, nv3052c_of_match); From 7de295d1a1a1b84e57b348e8bfd0fab5aab3ce69 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Adri=C3=A1n=20Larumbe?= Date: Mon, 2 Sep 2024 14:02:35 +0100 Subject: [PATCH 10/11] drm/panthor: flush FW AS caches in slow reset path MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit In the off-chance that waiting for the firmware to signal its booted status timed out in the fast reset path, one must flush the cache lines for the entire FW VM address space before reloading the regions, otherwise stale values eventually lead to a scheduler job timeout. Fixes: 647810ec2476 ("drm/panthor: Add the MMU/VM logical block") Cc: stable@vger.kernel.org Signed-off-by: Adrián Larumbe Acked-by: Liviu Dudau Reviewed-by: Steven Price Reviewed-by: Boris Brezillon Signed-off-by: Boris Brezillon Link: https://patchwork.freedesktop.org/patch/msgid/20240902130237.3440720-1-adrian.larumbe@collabora.com --- drivers/gpu/drm/panthor/panthor_fw.c | 8 +++++++- drivers/gpu/drm/panthor/panthor_mmu.c | 21 ++++++++++++++++++--- drivers/gpu/drm/panthor/panthor_mmu.h | 1 + 3 files changed, 26 insertions(+), 4 deletions(-) diff --git a/drivers/gpu/drm/panthor/panthor_fw.c b/drivers/gpu/drm/panthor/panthor_fw.c index 857f3f11258a..ef232c0c2049 100644 --- a/drivers/gpu/drm/panthor/panthor_fw.c +++ b/drivers/gpu/drm/panthor/panthor_fw.c @@ -1089,6 +1089,12 @@ int panthor_fw_post_reset(struct panthor_device *ptdev) panthor_fw_stop(ptdev); ptdev->fw->fast_reset = false; drm_err(&ptdev->base, "FW fast reset failed, trying a slow reset"); + + ret = panthor_vm_flush_all(ptdev->fw->vm); + if (ret) { + drm_err(&ptdev->base, "FW slow reset failed (couldn't flush FW's AS l2cache)"); + return ret; + } } /* Reload all sections, including RO ones. We're not supposed @@ -1099,7 +1105,7 @@ int panthor_fw_post_reset(struct panthor_device *ptdev) ret = panthor_fw_start(ptdev); if (ret) { - drm_err(&ptdev->base, "FW slow reset failed"); + drm_err(&ptdev->base, "FW slow reset failed (couldn't start the FW )"); return ret; } diff --git a/drivers/gpu/drm/panthor/panthor_mmu.c b/drivers/gpu/drm/panthor/panthor_mmu.c index fa0a002b1016..cc6e13a97783 100644 --- a/drivers/gpu/drm/panthor/panthor_mmu.c +++ b/drivers/gpu/drm/panthor/panthor_mmu.c @@ -576,6 +576,12 @@ static int mmu_hw_do_operation_locked(struct panthor_device *ptdev, int as_nr, if (as_nr < 0) return 0; + /* + * If the AS number is greater than zero, then we can be sure + * the device is up and running, so we don't need to explicitly + * power it up + */ + if (op != AS_COMMAND_UNLOCK) lock_region(ptdev, as_nr, iova, size); @@ -874,14 +880,23 @@ static int panthor_vm_flush_range(struct panthor_vm *vm, u64 iova, u64 size) if (!drm_dev_enter(&ptdev->base, &cookie)) return 0; - /* Flush the PTs only if we're already awake */ - if (pm_runtime_active(ptdev->base.dev)) - ret = mmu_hw_do_operation(vm, iova, size, AS_COMMAND_FLUSH_PT); + ret = mmu_hw_do_operation(vm, iova, size, AS_COMMAND_FLUSH_PT); drm_dev_exit(cookie); return ret; } +/** + * panthor_vm_flush_all() - Flush L2 caches for the entirety of a VM's AS + * @vm: VM whose cache to flush + * + * Return: 0 on success, a negative error code if flush failed. + */ +int panthor_vm_flush_all(struct panthor_vm *vm) +{ + return panthor_vm_flush_range(vm, vm->base.mm_start, vm->base.mm_range); +} + static int panthor_vm_unmap_pages(struct panthor_vm *vm, u64 iova, u64 size) { struct panthor_device *ptdev = vm->ptdev; diff --git a/drivers/gpu/drm/panthor/panthor_mmu.h b/drivers/gpu/drm/panthor/panthor_mmu.h index f3c1ed19f973..6788771071e3 100644 --- a/drivers/gpu/drm/panthor/panthor_mmu.h +++ b/drivers/gpu/drm/panthor/panthor_mmu.h @@ -31,6 +31,7 @@ panthor_vm_get_bo_for_va(struct panthor_vm *vm, u64 va, u64 *bo_offset); int panthor_vm_active(struct panthor_vm *vm); void panthor_vm_idle(struct panthor_vm *vm); int panthor_vm_as(struct panthor_vm *vm); +int panthor_vm_flush_all(struct panthor_vm *vm); struct panthor_heap_pool * panthor_vm_get_heap_pool(struct panthor_vm *vm, bool create); From 5a498d4d06d6d9bad76d8a50a7f8fe01670ad46f Mon Sep 17 00:00:00 2001 From: Thomas Zimmermann Date: Wed, 4 Sep 2024 14:36:54 +0200 Subject: [PATCH 11/11] drm/fbdev-dma: Only install deferred I/O if necessary Deferred I/O requires struct page for framebuffer memory, which is not guaranteed for all DMA ranges. We thus only install deferred I/O if we have a framebuffer that requires it. A reported bug affected the ipu-v3 and pl111 drivers, which have video memory in either Normal or HighMem zones [ 0.000000] Zone ranges: [ 0.000000] Normal [mem 0x0000000010000000-0x000000003fffffff] [ 0.000000] HighMem [mem 0x0000000040000000-0x000000004fffffff] where deferred I/O only works correctly with HighMem. See the Closes tags for bug reports. v2: - test if screen_buffer supports deferred I/O (Sima) Signed-off-by: Thomas Zimmermann Fixes: 808a40b69468 ("drm/fbdev-dma: Implement damage handling and deferred I/O") Reported-by: Alexander Stein Closes: https://lore.kernel.org/all/23636953.6Emhk5qWAg@steina-w/ Reported-by: Linus Walleij Closes: https://lore.kernel.org/dri-devel/CACRpkdb+hb9AGavbWpY-=uQQ0apY9en_tWJioPKf_fAbXMP4Hg@mail.gmail.com/ Tested-by: Alexander Stein Tested-by: Linus Walleij Cc: Thomas Zimmermann Cc: Javier Martinez Canillas Cc: Maarten Lankhorst Cc: Maxime Ripard Reviewed-by: Simona Vetter Reviewed-by: Linus Walleij Link: https://patchwork.freedesktop.org/patch/msgid/20240904123750.31206-1-tzimmermann@suse.de --- drivers/gpu/drm/drm_fbdev_dma.c | 83 +++++++++++++++++++++++++-------- 1 file changed, 64 insertions(+), 19 deletions(-) diff --git a/drivers/gpu/drm/drm_fbdev_dma.c b/drivers/gpu/drm/drm_fbdev_dma.c index 7ef5a48c8029..b0602c4f3628 100644 --- a/drivers/gpu/drm/drm_fbdev_dma.c +++ b/drivers/gpu/drm/drm_fbdev_dma.c @@ -36,20 +36,11 @@ static int drm_fbdev_dma_fb_release(struct fb_info *info, int user) return 0; } -FB_GEN_DEFAULT_DEFERRED_DMAMEM_OPS(drm_fbdev_dma, - drm_fb_helper_damage_range, - drm_fb_helper_damage_area); - static int drm_fbdev_dma_fb_mmap(struct fb_info *info, struct vm_area_struct *vma) { struct drm_fb_helper *fb_helper = info->par; - struct drm_framebuffer *fb = fb_helper->fb; - struct drm_gem_dma_object *dma = drm_fb_dma_get_gem_obj(fb, 0); - if (!dma->map_noncoherent) - vma->vm_page_prot = pgprot_writecombine(vma->vm_page_prot); - - return fb_deferred_io_mmap(info, vma); + return drm_gem_prime_mmap(fb_helper->buffer->gem, vma); } static void drm_fbdev_dma_fb_destroy(struct fb_info *info) @@ -70,13 +61,40 @@ static void drm_fbdev_dma_fb_destroy(struct fb_info *info) } static const struct fb_ops drm_fbdev_dma_fb_ops = { + .owner = THIS_MODULE, + .fb_open = drm_fbdev_dma_fb_open, + .fb_release = drm_fbdev_dma_fb_release, + __FB_DEFAULT_DMAMEM_OPS_RDWR, + DRM_FB_HELPER_DEFAULT_OPS, + __FB_DEFAULT_DMAMEM_OPS_DRAW, + .fb_mmap = drm_fbdev_dma_fb_mmap, + .fb_destroy = drm_fbdev_dma_fb_destroy, +}; + +FB_GEN_DEFAULT_DEFERRED_DMAMEM_OPS(drm_fbdev_dma, + drm_fb_helper_damage_range, + drm_fb_helper_damage_area); + +static int drm_fbdev_dma_deferred_fb_mmap(struct fb_info *info, struct vm_area_struct *vma) +{ + struct drm_fb_helper *fb_helper = info->par; + struct drm_framebuffer *fb = fb_helper->fb; + struct drm_gem_dma_object *dma = drm_fb_dma_get_gem_obj(fb, 0); + + if (!dma->map_noncoherent) + vma->vm_page_prot = pgprot_writecombine(vma->vm_page_prot); + + return fb_deferred_io_mmap(info, vma); +} + +static const struct fb_ops drm_fbdev_dma_deferred_fb_ops = { .owner = THIS_MODULE, .fb_open = drm_fbdev_dma_fb_open, .fb_release = drm_fbdev_dma_fb_release, __FB_DEFAULT_DEFERRED_OPS_RDWR(drm_fbdev_dma), DRM_FB_HELPER_DEFAULT_OPS, __FB_DEFAULT_DEFERRED_OPS_DRAW(drm_fbdev_dma), - .fb_mmap = drm_fbdev_dma_fb_mmap, + .fb_mmap = drm_fbdev_dma_deferred_fb_mmap, .fb_destroy = drm_fbdev_dma_fb_destroy, }; @@ -89,6 +107,7 @@ static int drm_fbdev_dma_helper_fb_probe(struct drm_fb_helper *fb_helper, { struct drm_client_dev *client = &fb_helper->client; struct drm_device *dev = fb_helper->dev; + bool use_deferred_io = false; struct drm_client_buffer *buffer; struct drm_gem_dma_object *dma_obj; struct drm_framebuffer *fb; @@ -111,6 +130,15 @@ static int drm_fbdev_dma_helper_fb_probe(struct drm_fb_helper *fb_helper, fb = buffer->fb; + /* + * Deferred I/O requires struct page for framebuffer memory, + * which is not guaranteed for all DMA ranges. We thus only + * install deferred I/O if we have a framebuffer that requires + * it. + */ + if (fb->funcs->dirty) + use_deferred_io = true; + ret = drm_client_buffer_vmap(buffer, &map); if (ret) { goto err_drm_client_buffer_delete; @@ -130,7 +158,10 @@ static int drm_fbdev_dma_helper_fb_probe(struct drm_fb_helper *fb_helper, drm_fb_helper_fill_info(info, fb_helper, sizes); - info->fbops = &drm_fbdev_dma_fb_ops; + if (use_deferred_io) + info->fbops = &drm_fbdev_dma_deferred_fb_ops; + else + info->fbops = &drm_fbdev_dma_fb_ops; /* screen */ info->flags |= FBINFO_VIRTFB; /* system memory */ @@ -144,14 +175,28 @@ static int drm_fbdev_dma_helper_fb_probe(struct drm_fb_helper *fb_helper, } info->fix.smem_len = info->screen_size; - /* deferred I/O */ - fb_helper->fbdefio.delay = HZ / 20; - fb_helper->fbdefio.deferred_io = drm_fb_helper_deferred_io; + /* + * Only set up deferred I/O if the screen buffer supports + * it. If this disagrees with the previous test for ->dirty, + * mmap on the /dev/fb file might not work correctly. + */ + if (!is_vmalloc_addr(info->screen_buffer) && info->fix.smem_start) { + unsigned long pfn = info->fix.smem_start >> PAGE_SHIFT; - info->fbdefio = &fb_helper->fbdefio; - ret = fb_deferred_io_init(info); - if (ret) - goto err_drm_fb_helper_release_info; + if (drm_WARN_ON(dev, !pfn_to_page(pfn))) + use_deferred_io = false; + } + + /* deferred I/O */ + if (use_deferred_io) { + fb_helper->fbdefio.delay = HZ / 20; + fb_helper->fbdefio.deferred_io = drm_fb_helper_deferred_io; + + info->fbdefio = &fb_helper->fbdefio; + ret = fb_deferred_io_init(info); + if (ret) + goto err_drm_fb_helper_release_info; + } return 0;