[Bug 96239] [radeonsi tessellation] Random "texture flickering" (Shadow of Mordor, Tomb Raider, Unigine Heaven 4.0)
https://bugs.freedesktop.org/show_bug.cgi?id=96239 --- Comment #5 from Rafael Castillo --- i can confirm this patches generates 0 issues on TAHITI R9-280 and CAPE VERDE HD7700, so it seems it is specific to hawaii/grenada pro -- You are receiving this mail because: You are the assignee for the bug. -- next part -- An HTML attachment was scrubbed... URL: <https://lists.freedesktop.org/archives/dri-devel/attachments/20160529/c9904553/attachment-0001.html>
[PATCH] drm/amdkfd: print once about mem_banks truncation
This print can really spam the kernel log in case we are truncating mem_banks, so just print this info once. It should also not be classified as warning. Signed-off-by: Oded Gabbay --- drivers/gpu/drm/amd/amdkfd/kfd_topology.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/gpu/drm/amd/amdkfd/kfd_topology.c b/drivers/gpu/drm/amd/amdkfd/kfd_topology.c index 74909e7..884c96f 100644 --- a/drivers/gpu/drm/amd/amdkfd/kfd_topology.c +++ b/drivers/gpu/drm/amd/amdkfd/kfd_topology.c @@ -666,7 +666,7 @@ static ssize_t node_show(struct kobject *kobj, struct attribute *attr, dev->node_props.simd_count); if (dev->mem_bank_count < dev->node_props.mem_banks_count) { - pr_warn("kfd: mem_banks_count truncated from %d to %d\n", + pr_info_once("kfd: mem_banks_count truncated from %d to %d\n", dev->node_props.mem_banks_count, dev->mem_bank_count); sysfs_show_32bit_prop(buffer, "mem_banks_count", -- 2.5.5
[Bug 80004] Serious Sam 3 BFE - incorrect weapon rendering
https://bugs.freedesktop.org/show_bug.cgi?id=80004 Vitaliy Filippov changed: What|Removed |Added Resolution|--- |FIXED Status|NEW |RESOLVED --- Comment #11 from Vitaliy Filippov --- The bug does not reproduce anymore with current mesa 11.3 -- You are receiving this mail because: You are the assignee for the bug. -- next part -- An HTML attachment was scrubbed... URL: <https://lists.freedesktop.org/archives/dri-devel/attachments/20160529/2b719567/attachment.html>
[Bug 96239] [radeonsi tessellation] Random "texture flickering" (Shadow of Mordor, Tomb Raider, Unigine Heaven 4.0)
https://bugs.freedesktop.org/show_bug.cgi?id=96239 --- Comment #6 from Jan Ziak <0xe2.0x9a.0x9b at gmail.com> --- (In reply to Bas Nieuwenhuizen from comment #4) > Created attachment 124151 [details] [review] > ci-64-tess-blocks.patch > > Does the attached patch help? If not I would appreciate it if someone could > find the first commit that fails (using e.g. bisect). > > Also, I noticed all reporters use hawaii/grenada pro chips. If anyone with a > different chip also has this issue, please let me know. Unfortunately, ci-64-tess-blocks.patch is making the issue more severe. The frequency of "black triangles on screen" in Tomb Raider is higher. -- You are receiving this mail because: You are the assignee for the bug. -- next part -- An HTML attachment was scrubbed... URL: <https://lists.freedesktop.org/archives/dri-devel/attachments/20160529/a0c797fe/attachment.html>
[Bug 96239] [radeonsi tessellation] Random "texture flickering" (Shadow of Mordor, Tomb Raider, Unigine Heaven 4.0)
https://bugs.freedesktop.org/show_bug.cgi?id=96239 --- Comment #7 from Jan Ziak <0xe2.0x9a.0x9b at gmail.com> --- Created attachment 124154 --> https://bugs.freedesktop.org/attachment.cgi?id=124154&action=edit Tomb Raider ci-64-tess-blocks screenshot -- You are receiving this mail because: You are the assignee for the bug. -- next part -- An HTML attachment was scrubbed... URL: <https://lists.freedesktop.org/archives/dri-devel/attachments/20160529/14a3d356/attachment.html>
[Bug 96239] [radeonsi tessellation] [R9 290/390] Random "texture flickering" (Shadow of Mordor, Tomb Raider, Unigine Heaven 4.0)
https://bugs.freedesktop.org/show_bug.cgi?id=96239 Jan Ziak <0xe2.0x9a.0x9b at gmail.com> changed: What|Removed |Added Summary|[radeonsi tessellation] |[radeonsi tessellation] [R9 |Random "texture flickering" |290/390] Random "texture |(Shadow of Mordor, Tomb |flickering" (Shadow of |Raider, Unigine Heaven 4.0) |Mordor, Tomb Raider, ||Unigine Heaven 4.0) -- You are receiving this mail because: You are the assignee for the bug. -- next part -- An HTML attachment was scrubbed... URL: <https://lists.freedesktop.org/archives/dri-devel/attachments/20160529/39c9d116/attachment.html>
[Bug 96239] [radeonsi tessellation] [R9 290/390] Random "texture flickering" (Shadow of Mordor, Tomb Raider, Unigine Heaven 4.0)
https://bugs.freedesktop.org/show_bug.cgi?id=96239 --- Comment #8 from Jan Ziak <0xe2.0x9a.0x9b at gmail.com> --- (In reply to Bas Nieuwenhuizen from comment #4) > Does the attached patch help? If not I would appreciate it if someone could > find the first commit that fails (using e.g. bisect). Checking out for example f91c85b29b8261ab3f44d292ed2130d4f577d976 and starting Tomb Raider restarts the X server on my machine. -- You are receiving this mail because: You are the assignee for the bug. -- next part -- An HTML attachment was scrubbed... URL: <https://lists.freedesktop.org/archives/dri-devel/attachments/20160529/ecfc2378/attachment.html>
[Bug 96239] [radeonsi tessellation] [R9 290/390] Random "texture flickering" (Shadow of Mordor, Tomb Raider, Unigine Heaven 4.0)
https://bugs.freedesktop.org/show_bug.cgi?id=96239 --- Comment #9 from Jan Ziak <0xe2.0x9a.0x9b at gmail.com> --- Created attachment 124155 --> https://bugs.freedesktop.org/attachment.cgi?id=124155&action=edit S_03093C_OFFCHIP_BUFFERING(offchip_blocks) if >= CIK This patch fixes the issue on my R9 390. The code is just a guesswork. Maybe it should be (2*offchip_blocks-1) instead? -- You are receiving this mail because: You are the assignee for the bug. -- next part -- An HTML attachment was scrubbed... URL: <https://lists.freedesktop.org/archives/dri-devel/attachments/20160529/fb62b862/attachment.html>
[Bug 96239] [radeonsi tessellation] [R9 290/390] Random "texture flickering" (Shadow of Mordor, Tomb Raider, Unigine Heaven 4.0)
https://bugs.freedesktop.org/show_bug.cgi?id=96239 --- Comment #10 from Jan Ziak <0xe2.0x9a.0x9b at gmail.com> --- Passing +1 to S_03093C_OFFCHIP_BUFFERING() explains why changing offchip_blocks from 256 to 64 increases the severity of the issue. -- You are receiving this mail because: You are the assignee for the bug. -- next part -- An HTML attachment was scrubbed... URL: <https://lists.freedesktop.org/archives/dri-devel/attachments/20160529/da6b935c/attachment.html>
[path v2 4/7] drm/hisilicon/hibmc: Add encoder for VDAC
Add encoder funcs and helpers for VDAC. Signed-off-by: Rongrong Zou Signed-off-by: Jianhua Li --- drivers/gpu/drm/hisilicon/hibmc/Makefile | 2 +- drivers/gpu/drm/hisilicon/hibmc/hibmc_drm_drv.c | 6 ++ drivers/gpu/drm/hisilicon/hibmc/hibmc_drm_drv.h | 2 + drivers/gpu/drm/hisilicon/hibmc/hibmc_drm_vdac.c | 85 4 files changed, 94 insertions(+), 1 deletion(-) create mode 100644 drivers/gpu/drm/hisilicon/hibmc/hibmc_drm_vdac.c diff --git a/drivers/gpu/drm/hisilicon/hibmc/Makefile b/drivers/gpu/drm/hisilicon/hibmc/Makefile index faa7e64..4e7797a 100644 --- a/drivers/gpu/drm/hisilicon/hibmc/Makefile +++ b/drivers/gpu/drm/hisilicon/hibmc/Makefile @@ -1,4 +1,4 @@ -hibmc-drm-y := hibmc_drm_drv.o hibmc_drm_de.o hibmc_drm_power.o +hibmc-drm-y := hibmc_drm_drv.o hibmc_drm_de.o hibmc_drm_vdac.o hibmc_drm_power.o obj-$(CONFIG_DRM_HISI_HIBMC) +=hibmc-drm.o #obj-y += hibmc-drm.o diff --git a/drivers/gpu/drm/hisilicon/hibmc/hibmc_drm_drv.c b/drivers/gpu/drm/hisilicon/hibmc/hibmc_drm_drv.c index f7837cc..962072f 100644 --- a/drivers/gpu/drm/hisilicon/hibmc/hibmc_drm_drv.c +++ b/drivers/gpu/drm/hisilicon/hibmc/hibmc_drm_drv.c @@ -129,6 +129,12 @@ static int hibmc_kms_init(struct hibmc_drm_device *hidev) return ret; } + ret = hibmc_encoder_init(hidev); + if (ret) { + DRM_ERROR("failed to init encoder\n"); + return ret; + } + return 0; } diff --git a/drivers/gpu/drm/hisilicon/hibmc/hibmc_drm_drv.h b/drivers/gpu/drm/hisilicon/hibmc/hibmc_drm_drv.h index e64ec8d..d0c5982 100644 --- a/drivers/gpu/drm/hisilicon/hibmc/hibmc_drm_drv.h +++ b/drivers/gpu/drm/hisilicon/hibmc/hibmc_drm_drv.h @@ -34,11 +34,13 @@ struct hibmc_drm_device { struct drm_device *dev; struct drm_plane plane; struct drm_crtc crtc; + struct drm_encoder encoder; bool mode_config_initialized; }; int hibmc_plane_init(struct hibmc_drm_device *hidev); int hibmc_crtc_init(struct hibmc_drm_device *hidev); +int hibmc_encoder_init(struct hibmc_drm_device *hidev); #endif diff --git a/drivers/gpu/drm/hisilicon/hibmc/hibmc_drm_vdac.c b/drivers/gpu/drm/hisilicon/hibmc/hibmc_drm_vdac.c new file mode 100644 index 000..cb9a130 --- /dev/null +++ b/drivers/gpu/drm/hisilicon/hibmc/hibmc_drm_vdac.c @@ -0,0 +1,85 @@ +/* Hisilicon Hibmc SoC drm driver + * + * Based on the bochs drm driver. + * + * Copyright (c) 2016 Huawei Limited. + * + * Author: + * Rongrong Zou + * Rongrong Zou + * Jianhua Li + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + */ + +#include +#include +#include +#include + +#include "hibmc_drm_drv.h" +#include "hibmc_drm_regs.h" + + +static void hibmc_encoder_disable(struct drm_encoder *encoder) +{ +} + +static void hibmc_encoder_enable(struct drm_encoder *encoder) +{ +} + +static void hibmc_encoder_mode_set(struct drm_encoder *encoder, + struct drm_display_mode *mode, + struct drm_display_mode *adj_mode) +{ + u32 reg; + struct drm_device *dev = encoder->dev; + struct hibmc_drm_device *hidev = dev->dev_private; + + /* just open DISPLAY_CONTROL_HISILE register bit 3:0*/ + reg = readl(hidev->mmio + DISPLAY_CONTROL_HISILE); + reg |= 0xf; + writel(reg, hidev->mmio + DISPLAY_CONTROL_HISILE); +} + +static int hibmc_encoder_atomic_check(struct drm_encoder *encoder, + struct drm_crtc_state *crtc_state, + struct drm_connector_state *conn_state) +{ + return 0; +} + +static const struct drm_encoder_helper_funcs hibmc_encoder_helper_funcs = { + .mode_set = hibmc_encoder_mode_set, + .disable = hibmc_encoder_disable, + .enable = hibmc_encoder_enable, + .atomic_check = hibmc_encoder_atomic_check, +}; + +static const struct drm_encoder_funcs hibmc_encoder_encoder_funcs = { + .destroy = drm_encoder_cleanup, +}; + +int hibmc_encoder_init(struct hibmc_drm_device *hidev) +{ + struct drm_device *dev = hidev->dev; + struct drm_encoder *encoder = &hidev->encoder; + int ret; + + encoder->possible_crtcs = 0x1; + ret = drm_encoder_init(dev, encoder, &hibmc_encoder_encoder_funcs, + DRM_MODE_ENCODER_DAC, NULL); + if (ret) { + DRM_ERROR("failed to init encoder\n"); + return ret; + } + + drm_encoder_helper_add(encoder, &hibmc_encoder_helper_funcs); + return 0; +} + -- 1.9.1
[path v2 5/7] drm/hisilicon/hibmc: Add connector for VDAC
Add connector funcs and helper funcs for VDAC. Signed-off-by: Rongrong Zou Signed-off-by: Jianhua Li --- drivers/gpu/drm/hisilicon/hibmc/hibmc_drm_drv.c | 21 ++ drivers/gpu/drm/hisilicon/hibmc/hibmc_drm_drv.h | 3 +- drivers/gpu/drm/hisilicon/hibmc/hibmc_drm_vdac.c | 89 3 files changed, 112 insertions(+), 1 deletion(-) diff --git a/drivers/gpu/drm/hisilicon/hibmc/hibmc_drm_drv.c b/drivers/gpu/drm/hisilicon/hibmc/hibmc_drm_drv.c index 962072f..70d79d2 100644 --- a/drivers/gpu/drm/hisilicon/hibmc/hibmc_drm_drv.c +++ b/drivers/gpu/drm/hisilicon/hibmc/hibmc_drm_drv.c @@ -135,6 +135,14 @@ static int hibmc_kms_init(struct hibmc_drm_device *hidev) return ret; } + ret = hibmc_connector_init(hidev); + if (ret) { + DRM_ERROR("failed to init connector\n"); + return ret; + } + + drm_mode_connector_attach_encoder(&hidev->connector, + &hidev->encoder); return 0; } @@ -278,6 +286,12 @@ err: return ret; } +static void hibmc_connector_unplug_all(struct drm_device *dev) +{ + mutex_lock(&dev->mode_config.mutex); + drm_connector_unregister_all(dev); + mutex_unlock(&dev->mode_config.mutex); +} static int hibmc_pci_probe(struct pci_dev *pdev, const struct pci_device_id *ent) @@ -304,8 +318,14 @@ static int hibmc_pci_probe(struct pci_dev *pdev, if (ret) goto err_unload; + ret = drm_connector_register_all(dev); + if (ret) + goto err_unregister; + return 0; +err_unregister: + drm_dev_unregister(dev); err_unload: hibmc_unload(dev); err_disable: @@ -320,6 +340,7 @@ static void hibmc_pci_remove(struct pci_dev *pdev) { struct drm_device *dev = pci_get_drvdata(pdev); + hibmc_connector_unplug_all(dev); drm_dev_unregister(dev); hibmc_unload(dev); drm_dev_unref(dev); diff --git a/drivers/gpu/drm/hisilicon/hibmc/hibmc_drm_drv.h b/drivers/gpu/drm/hisilicon/hibmc/hibmc_drm_drv.h index d0c5982..eb5a892 100644 --- a/drivers/gpu/drm/hisilicon/hibmc/hibmc_drm_drv.h +++ b/drivers/gpu/drm/hisilicon/hibmc/hibmc_drm_drv.h @@ -35,12 +35,13 @@ struct hibmc_drm_device { struct drm_plane plane; struct drm_crtc crtc; struct drm_encoder encoder; + struct drm_connector connector; bool mode_config_initialized; }; int hibmc_plane_init(struct hibmc_drm_device *hidev); int hibmc_crtc_init(struct hibmc_drm_device *hidev); int hibmc_encoder_init(struct hibmc_drm_device *hidev); - +int hibmc_connector_init(struct hibmc_drm_device *hidev); #endif diff --git a/drivers/gpu/drm/hisilicon/hibmc/hibmc_drm_vdac.c b/drivers/gpu/drm/hisilicon/hibmc/hibmc_drm_vdac.c index cb9a130..b39ec65 100644 --- a/drivers/gpu/drm/hisilicon/hibmc/hibmc_drm_vdac.c +++ b/drivers/gpu/drm/hisilicon/hibmc/hibmc_drm_vdac.c @@ -24,6 +24,13 @@ #include "hibmc_drm_drv.h" #include "hibmc_drm_regs.h" +static int defx = 800; +static int defy = 600; + +module_param(defx, int, 0444); +module_param(defy, int, 0444); +MODULE_PARM_DESC(defx, "default x resolution"); +MODULE_PARM_DESC(defy, "default y resolution"); static void hibmc_encoder_disable(struct drm_encoder *encoder) { @@ -83,3 +90,85 @@ int hibmc_encoder_init(struct hibmc_drm_device *hidev) return 0; } +static int hibmc_connector_get_modes(struct drm_connector *connector) +{ + int count; + + count = drm_add_modes_noedid(connector, 800, 600); + drm_set_preferred_mode(connector, defx, defy); + return count; +} + +static int hibmc_connector_mode_valid(struct drm_connector *connector, + struct drm_display_mode *mode) +{ + struct hibmc_drm_device *hiprivate = +container_of(connector, struct hibmc_drm_device, connector); + unsigned long size = mode->hdisplay * mode->vdisplay * 4; + + /* + * Make sure we can fit two framebuffers into video memory. + * This allows up to 1600x1200 with 16 MB (default size). + * If you want more try this: + * 'qemu -vga std -global VGA.vgamem_mb=32 $otherargs' + */ + if (size * 2 > hiprivate->fb_size) + return MODE_BAD; + + return MODE_OK; +} + +static struct drm_encoder * +hibmc_connector_best_encoder(struct drm_connector *connector) +{ + int enc_id = connector->encoder_ids[0]; + + /* pick the encoder ids */ + if (enc_id) + return drm_encoder_find(connector->dev, enc_id); + + return NULL; +} + +static enum drm_connector_status hibmc_connector_detect(struct drm_connector +*connector, bool force) +{ + return connector_status_connected; +} + +static const struct drm_connector_helper_funcs + hibmc_connector_connector_helper_funcs = { + .get_modes = hibmc_connector_get_modes, + .mo
[Intel-gfx] 4.7-rc0: redshift stopped working on intel display
Could you try to apply the following patch [1], hopefully this fixes the issue for you. [1] https://patchwork.freedesktop.org/patch/89111/
[path v2 0/7] Add DRM driver for Hisilicon Hibmc
This patch set adds a new drm driver for Hisilicon Hibmc. Hibmc is a base board management controller, usually it is used on server for Out-of-band management purpose. In this patch set, we just support basic function for Hibmc display subsystem. Hibmc display subsystem is connected to host CPU by PCIe as blow: +--+ +--+ | | PCIe | Hibmc | |host CPU( |<->| display | |arm64,x86)| |subsystem | +--+ +--+ Hardware Detail for Hibmc display subsystem --- The display subsystem of Hibmc is show as bellow: ++ ++ ++ ++ || || || || | FB |->| DE |->|VDAC|>|external| || || || | VGA| ++ ++ ++ ++ -DE(Display Engine) is the display controller. -VDAC(Video Digital-to-Analog converter) converts the RGB diaital data stream from DE to VGA analog signals. Change History Changes in v2: -Remove self-defined macros for bit operations. -Remove unused register. -Replace those deprecated functions with new version of them. -use drm_connector_register_all() to register connector after drm_dev_register(). The patch v1 is at https://lists.freedesktop.org/archives/dri-devel/2016-February/101921.html Sorry for too late sending. Rongrong Zou (7): idrm/hisilicon/hibmc: Add hisilicon hibmc drm master driver drm/hisilicon/hibmc: Add plane for DE drm/hisilicon/hibmc: Add crtc for DE drm/hisilicon/hibmc: Add encoder for VDAC drm/hisilicon/hibmc: Add connector for VDAC drm/hisilicon/hibmc: Add support for frame buffer drm/hisilicon/hibmc: Add maintainer for Hibmc DRM MAINTAINERS | 7 + drivers/gpu/drm/hisilicon/Kconfig | 1 + drivers/gpu/drm/hisilicon/Makefile| 3 +- drivers/gpu/drm/hisilicon/hibmc/Kconfig | 13 + drivers/gpu/drm/hisilicon/hibmc/Makefile | 4 + drivers/gpu/drm/hisilicon/hibmc/hibmc_drm_de.c| 477 ++ drivers/gpu/drm/hisilicon/hibmc/hibmc_drm_de.h| 29 ++ drivers/gpu/drm/hisilicon/hibmc/hibmc_drm_drv.c | 399 ++ drivers/gpu/drm/hisilicon/hibmc/hibmc_drm_drv.h | 64 +++ drivers/gpu/drm/hisilicon/hibmc/hibmc_drm_fbdev.c | 286 + drivers/gpu/drm/hisilicon/hibmc/hibmc_drm_power.c | 91 + drivers/gpu/drm/hisilicon/hibmc/hibmc_drm_power.h | 28 ++ drivers/gpu/drm/hisilicon/hibmc/hibmc_drm_regs.h | 214 ++ drivers/gpu/drm/hisilicon/hibmc/hibmc_drm_vdac.c | 174 14 files changed, 1789 insertions(+), 1 deletion(-) create mode 100644 drivers/gpu/drm/hisilicon/hibmc/Kconfig create mode 100644 drivers/gpu/drm/hisilicon/hibmc/Makefile create mode 100644 drivers/gpu/drm/hisilicon/hibmc/hibmc_drm_de.c create mode 100644 drivers/gpu/drm/hisilicon/hibmc/hibmc_drm_de.h create mode 100644 drivers/gpu/drm/hisilicon/hibmc/hibmc_drm_drv.c create mode 100644 drivers/gpu/drm/hisilicon/hibmc/hibmc_drm_drv.h create mode 100644 drivers/gpu/drm/hisilicon/hibmc/hibmc_drm_fbdev.c create mode 100644 drivers/gpu/drm/hisilicon/hibmc/hibmc_drm_power.c create mode 100644 drivers/gpu/drm/hisilicon/hibmc/hibmc_drm_power.h create mode 100644 drivers/gpu/drm/hisilicon/hibmc/hibmc_drm_regs.h create mode 100644 drivers/gpu/drm/hisilicon/hibmc/hibmc_drm_vdac.c -- 1.9.1
[path v2 1/7] drm/hisilicon/hibmc: Add hisilicon hibmc drm master driver
Add DRM master driver for Hisilicon Hibmc SoC which used for Out-of-band management. Blow is the general hardware connection, both the Hibmc and the host CPU are on the same mother board. +--+ +--+ | | PCIe | Hibmc | |host CPU( |<->| display | |arm64,x86)| |subsystem | +--+ +--+ Signed-off-by: Rongrong Zou Signed-off-by: Jianhua Li --- drivers/gpu/drm/hisilicon/Kconfig | 1 + drivers/gpu/drm/hisilicon/Makefile| 3 +- drivers/gpu/drm/hisilicon/hibmc/Kconfig | 13 + drivers/gpu/drm/hisilicon/hibmc/Makefile | 4 + drivers/gpu/drm/hisilicon/hibmc/hibmc_drm_drv.c | 307 ++ drivers/gpu/drm/hisilicon/hibmc/hibmc_drm_drv.h | 39 +++ drivers/gpu/drm/hisilicon/hibmc/hibmc_drm_power.c | 91 +++ drivers/gpu/drm/hisilicon/hibmc/hibmc_drm_power.h | 28 ++ drivers/gpu/drm/hisilicon/hibmc/hibmc_drm_regs.h | 214 +++ 9 files changed, 699 insertions(+), 1 deletion(-) create mode 100644 drivers/gpu/drm/hisilicon/hibmc/Kconfig create mode 100644 drivers/gpu/drm/hisilicon/hibmc/Makefile create mode 100644 drivers/gpu/drm/hisilicon/hibmc/hibmc_drm_drv.c create mode 100644 drivers/gpu/drm/hisilicon/hibmc/hibmc_drm_drv.h create mode 100644 drivers/gpu/drm/hisilicon/hibmc/hibmc_drm_power.c create mode 100644 drivers/gpu/drm/hisilicon/hibmc/hibmc_drm_power.h create mode 100644 drivers/gpu/drm/hisilicon/hibmc/hibmc_drm_regs.h diff --git a/drivers/gpu/drm/hisilicon/Kconfig b/drivers/gpu/drm/hisilicon/Kconfig index 558c61b..2fd2724 100644 --- a/drivers/gpu/drm/hisilicon/Kconfig +++ b/drivers/gpu/drm/hisilicon/Kconfig @@ -2,4 +2,5 @@ # hisilicon drm device configuration. # Please keep this list sorted alphabetically +source "drivers/gpu/drm/hisilicon/hibmc/Kconfig" source "drivers/gpu/drm/hisilicon/kirin/Kconfig" diff --git a/drivers/gpu/drm/hisilicon/Makefile b/drivers/gpu/drm/hisilicon/Makefile index e3f6d49..4d7185c 100644 --- a/drivers/gpu/drm/hisilicon/Makefile +++ b/drivers/gpu/drm/hisilicon/Makefile @@ -2,4 +2,5 @@ # Makefile for hisilicon drm drivers. # Please keep this list sorted alphabetically -obj-$(CONFIG_DRM_HISI_KIRIN) += kirin/ +obj-$(CONFIG_DRM_HISI_HIBMC) += hibmc/ +obj-$(CONFIG_DRM_HISI_KIRIN) += kirin/ \ No newline at end of file diff --git a/drivers/gpu/drm/hisilicon/hibmc/Kconfig b/drivers/gpu/drm/hisilicon/hibmc/Kconfig new file mode 100644 index 000..1e7810d --- /dev/null +++ b/drivers/gpu/drm/hisilicon/hibmc/Kconfig @@ -0,0 +1,13 @@ +config DRM_HISI_HIBMC + tristate "DRM Support for Hisilicon Hibmc" + depends on DRM && PCI + select DRM_KMS_HELPER + select DRM_KMS_FB_HELPER + select DRM_GEM_CMA_HELPER + select DRM_KMS_CMA_HELPER + select FB_SYS_FILLRECT + select FB_SYS_COPYAREA + select FB_SYS_IMAGEBLIT + help + Choose this option if you have a Hisilicon Hibmc soc chipset. + If M is selected the module will be called hibmc-drm. diff --git a/drivers/gpu/drm/hisilicon/hibmc/Makefile b/drivers/gpu/drm/hisilicon/hibmc/Makefile new file mode 100644 index 000..533f9ed --- /dev/null +++ b/drivers/gpu/drm/hisilicon/hibmc/Makefile @@ -0,0 +1,4 @@ +hibmc-drm-y := hibmc_drm_drv.o hibmc_drm_power.o + +obj-$(CONFIG_DRM_HISI_HIBMC) +=hibmc-drm.o +#obj-y += hibmc-drm.o diff --git a/drivers/gpu/drm/hisilicon/hibmc/hibmc_drm_drv.c b/drivers/gpu/drm/hisilicon/hibmc/hibmc_drm_drv.c new file mode 100644 index 000..7eaacd8 --- /dev/null +++ b/drivers/gpu/drm/hisilicon/hibmc/hibmc_drm_drv.c @@ -0,0 +1,307 @@ +/* Hisilicon Hibmc SoC drm driver + * + * Based on the bochs drm driver. + * + * Copyright (c) 2016 Huawei Limited. + * + * Author: + * Rongrong Zou + * Rongrong Zou + * Jianhua Li + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + */ + +#include +#include +#include +#include +#include +#include +#include + +#include "hibmc_drm_drv.h" +#include "hibmc_drm_regs.h" +#include "hibmc_drm_power.h" + +static const struct file_operations hibmc_fops = { + .owner = THIS_MODULE, + .open = drm_open, + .release= drm_release, + .unlocked_ioctl = drm_ioctl, +#ifdef CONFIG_COMPAT + .compat_ioctl = drm_compat_ioctl, +#endif + .poll = drm_poll, + .read = drm_read, + .llseek = no_llseek, +}; + +static int hibmc_enable_vblank(struct drm_device *dev, unsigned int pipe) +{ + return 0; +} + +static void hibmc_disable_vblank(struct drm_device *dev, unsigned int pipe) +{ +} + +static struct drm_driver hibmc_driver = { + .driver_features= DRIVER_GEM | DRIVER_MODESET, + .fops = &hibmc_fops, +
[path v2 2/7] drm/hisilicon/hibmc: Add plane for DE
Add plane funcs and helper funcs for DE. Signed-off-by: Rongrong Zou Signed-off-by: Jianhua Li --- drivers/gpu/drm/hisilicon/hibmc/Makefile| 2 +- drivers/gpu/drm/hisilicon/hibmc/hibmc_drm_de.c | 170 drivers/gpu/drm/hisilicon/hibmc/hibmc_drm_drv.c | 41 +- drivers/gpu/drm/hisilicon/hibmc/hibmc_drm_drv.h | 3 + 4 files changed, 214 insertions(+), 2 deletions(-) create mode 100644 drivers/gpu/drm/hisilicon/hibmc/hibmc_drm_de.c diff --git a/drivers/gpu/drm/hisilicon/hibmc/Makefile b/drivers/gpu/drm/hisilicon/hibmc/Makefile index 533f9ed..faa7e64 100644 --- a/drivers/gpu/drm/hisilicon/hibmc/Makefile +++ b/drivers/gpu/drm/hisilicon/hibmc/Makefile @@ -1,4 +1,4 @@ -hibmc-drm-y := hibmc_drm_drv.o hibmc_drm_power.o +hibmc-drm-y := hibmc_drm_drv.o hibmc_drm_de.o hibmc_drm_power.o obj-$(CONFIG_DRM_HISI_HIBMC) +=hibmc-drm.o #obj-y += hibmc-drm.o diff --git a/drivers/gpu/drm/hisilicon/hibmc/hibmc_drm_de.c b/drivers/gpu/drm/hisilicon/hibmc/hibmc_drm_de.c new file mode 100644 index 000..e8e5853 --- /dev/null +++ b/drivers/gpu/drm/hisilicon/hibmc/hibmc_drm_de.c @@ -0,0 +1,170 @@ +/* Hisilicon Hibmc SoC drm driver + * + * Based on the bochs drm driver. + * + * Copyright (c) 2016 Huawei Limited. + * + * Author: + * Rongrong Zou + * Rongrong Zou + * Jianhua Li + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + */ + +#include +#include +#include +#include +#include +#include +#include + +#include "hibmc_drm_drv.h" +#include "hibmc_drm_regs.h" +#include "hibmc_drm_power.h" + +/* -- */ + +static int hibmc_plane_prepare_fb(struct drm_plane *plane, + const struct drm_plane_state *new_state) +{ + /* do nothing */ + return 0; +} + +static void hibmc_plane_cleanup_fb(struct drm_plane *plane, + const struct drm_plane_state *old_state) +{ + /* do nothing */ +} + +static int hibmc_plane_atomic_check(struct drm_plane *plane, + struct drm_plane_state *state) +{ + struct drm_framebuffer *fb = state->fb; + struct drm_crtc *crtc = state->crtc; + struct drm_crtc_state *crtc_state; + u32 src_x = state->src_x >> 16; + u32 src_y = state->src_y >> 16; + u32 src_w = state->src_w >> 16; + u32 src_h = state->src_h >> 16; + int crtc_x = state->crtc_x; + int crtc_y = state->crtc_y; + u32 crtc_w = state->crtc_w; + u32 crtc_h = state->crtc_h; + + if (!crtc || !fb) + return 0; + + crtc_state = drm_atomic_get_crtc_state(state->state, crtc); + if (IS_ERR(crtc_state)) + return PTR_ERR(crtc_state); + + if (src_w != crtc_w || src_h != crtc_h) { + DRM_ERROR("Scale not support!!!\n"); + return -EINVAL; + } + + if (src_x + src_w > fb->width || + src_y + src_h > fb->height) + return -EINVAL; + + if (crtc_x < 0 || crtc_y < 0) + return -EINVAL; + + if (crtc_x + crtc_w > crtc_state->adjusted_mode.hdisplay || + crtc_y + crtc_h > crtc_state->adjusted_mode.vdisplay) + return -EINVAL; + + return 0; +} + +static void hibmc_plane_atomic_update(struct drm_plane *plane, + struct drm_plane_state *old_state) +{ + struct drm_plane_state *state = plane->state; + u32 reg; + unsigned int line_l; + struct hibmc_drm_device *hidev = + (struct hibmc_drm_device *)plane->dev->dev_private; + + /* now just support one plane */ + writel(0, hidev->mmio + HIBMC_CRT_FB_ADDRESS); + reg = state->fb->width * (state->fb->bits_per_pixel >> 3); + /* now line_pad is 16 */ + reg = PADDING(16, reg); + + line_l = state->fb->width * state->fb->bits_per_pixel / 8; + line_l = PADDING(16, line_l); + writel((HIBMC_CRT_FB_WIDTH_WIDTH(reg) & HIBMC_CRT_FB_WIDTH_WIDTH_MASK) | + (HIBMC_CRT_FB_WIDTH_OFFS(line_l) & HIBMC_CRT_FB_WIDTH_OFFS_MASK), + hidev->mmio + HIBMC_CRT_FB_WIDTH); + + /* SET PIXEL FORMAT */ + reg = readl(hidev->mmio + HIBMC_CRT_DISP_CTL); + reg = reg & ~HIBMC_CRT_DISP_CTL_FORMAT_MASK; + reg = reg | (HIBMC_CRT_DISP_CTL_FORMAT(state->fb->bits_per_pixel >> 4) & +HIBMC_CRT_DISP_CTL_FORMAT_MASK); + writel(reg, hidev->mmio + HIBMC_CRT_DISP_CTL); +} + +static void hibmc_plane_atomic_disable(struct drm_plane *plane, + struct drm_plane_state *old_state) +{ +} + +static const u32 channel_formats1[] = { + DRM_FORMAT_RGB565, DRM_FORMAT_BGR565, DRM_FORMAT_RGB888, + D
[path v2 3/7] drm/hisilicon/hibmc: Add crtc for DE
Add crtc funcs and helper funcs for DE. Signed-off-by: Rongrong Zou Signed-off-by: Jianhua Li --- drivers/gpu/drm/hisilicon/hibmc/hibmc_drm_de.c | 307 drivers/gpu/drm/hisilicon/hibmc/hibmc_drm_de.h | 29 +++ drivers/gpu/drm/hisilicon/hibmc/hibmc_drm_drv.c | 6 + drivers/gpu/drm/hisilicon/hibmc/hibmc_drm_drv.h | 2 + 4 files changed, 344 insertions(+) create mode 100644 drivers/gpu/drm/hisilicon/hibmc/hibmc_drm_de.h diff --git a/drivers/gpu/drm/hisilicon/hibmc/hibmc_drm_de.c b/drivers/gpu/drm/hisilicon/hibmc/hibmc_drm_de.c index e8e5853..87a7e52 100644 --- a/drivers/gpu/drm/hisilicon/hibmc/hibmc_drm_de.c +++ b/drivers/gpu/drm/hisilicon/hibmc/hibmc_drm_de.c @@ -26,6 +26,7 @@ #include "hibmc_drm_drv.h" #include "hibmc_drm_regs.h" +#include "hibmc_drm_de.h" #include "hibmc_drm_power.h" /* -- */ @@ -168,3 +169,309 @@ int hibmc_plane_init(struct hibmc_drm_device *hidev) return 0; } +static void hibmc_crtc_enable(struct drm_crtc *crtc) +{ + unsigned int reg; + /* power mode 0 is default. */ + struct hibmc_drm_device *hidev = crtc->dev->dev_private; + + hibmc_set_power_mode(hidev, HIBMC_PW_MODE_CTL_MODE_MODE0); + + /* Enable display power gate & LOCALMEM power gate*/ + reg = readl(hidev->mmio + HIBMC_CURRENT_GATE); + reg &= ~HIBMC_CURR_GATE_LOCALMEM_MASK; + reg &= ~HIBMC_CURR_GATE_DISPLAY_MASK; + reg |= HIBMC_CURR_GATE_LOCALMEM(ON); + reg |= HIBMC_CURR_GATE_DISPLAY(ON); + hibmc_set_current_gate(hidev, reg); +} + +static void hibmc_crtc_disable(struct drm_crtc *crtc) +{ + unsigned int reg; + struct hibmc_drm_device *hidev = crtc->dev->dev_private; + + hibmc_set_power_mode(hidev, HIBMC_PW_MODE_CTL_MODE_SLEEP); + + /* Enable display power gate & LOCALMEM power gate*/ + reg = readl(hidev->mmio + HIBMC_CURRENT_GATE); + reg &= ~HIBMC_CURR_GATE_LOCALMEM_MASK; + reg &= ~HIBMC_CURR_GATE_DISPLAY_MASK; + reg |= HIBMC_CURR_GATE_LOCALMEM(OFF); + reg |= HIBMC_CURR_GATE_DISPLAY(OFF); + hibmc_set_current_gate(hidev, reg); +} + +static int hibmc_crtc_atomic_check(struct drm_crtc *crtc, + struct drm_crtc_state *state) +{ + return 0; +} + +static unsigned int format_pll_reg(void) +{ + unsigned int pllreg = 0; + struct panel_pll pll = {0}; + + /* Note that all PLL's have the same format. Here, + * we just use Panel PLL parameter to work out the bit + * fields in the register.On returning a 32 bit number, the value can + * be applied to any PLL in the calling function. + */ + pllreg |= HIBMC_PLL_CTRL_BYPASS(OFF) & HIBMC_PLL_CTRL_BYPASS_MASK; + pllreg |= HIBMC_PLL_CTRL_POWER(ON) & HIBMC_PLL_CTRL_POWER_MASK; + pllreg |= HIBMC_PLL_CTRL_INPUT(OSC) & HIBMC_PLL_CTRL_INPUT_MASK; + pllreg |= HIBMC_PLL_CTRL_POD(pll.POD) & HIBMC_PLL_CTRL_POD_MASK; + pllreg |= HIBMC_PLL_CTRL_OD(pll.OD) & HIBMC_PLL_CTRL_OD_MASK; + pllreg |= HIBMC_PLL_CTRL_N(pll.N) & HIBMC_PLL_CTRL_N_MASK; + pllreg |= HIBMC_PLL_CTRL_M(pll.M) & HIBMC_PLL_CTRL_M_MASK; + + return pllreg; +} + +static void set_vclock_hisilicon(struct drm_device *dev, unsigned long pll) +{ + unsigned long tmp0, tmp1; + struct hibmc_drm_device *hidev = dev->dev_private; + +/* 1. outer_bypass_n=0 */ + tmp0 = readl(hidev->mmio + CRT_PLL1_HS); + tmp0 &= 0xBFFF; + writel(tmp0, hidev->mmio + CRT_PLL1_HS); + + /* 2. pll_pd=1?inter_bypass=1 */ + writel(0x2100, hidev->mmio + CRT_PLL1_HS); + + /* 3. config pll */ + writel(pll, hidev->mmio + CRT_PLL1_HS); + + /* 4. delay */ + mdelay(1); + + /* 5. pll_pd =0 */ + tmp1 = pll & ~0x0100; + writel(tmp1, hidev->mmio + CRT_PLL1_HS); + + /* 6. delay */ + mdelay(1); + + /* 7. inter_bypass=0 */ + tmp1 &= ~0x2000; + writel(tmp1, hidev->mmio + CRT_PLL1_HS); + + /* 8. delay */ + mdelay(1); + + /* 9. outer_bypass_n=1 */ + tmp1 |= 0x4000; + writel(tmp1, hidev->mmio + CRT_PLL1_HS); +} + +/* This function takes care the extra registers and bit fields required to +*setup a mode in board. +*Explanation about Display Control register: +*FPGA only supports 7 predefined pixel clocks, and clock select is +*in bit 4:0 of new register 0x802a8. +*/ +static unsigned int display_ctrl_adjust(struct drm_device *dev, + struct drm_display_mode *mode, + unsigned int ctrl) +{ + unsigned long x, y; + unsigned long pll1; /* bit[31:0] of PLL */ + unsigned long pll2; /* bit[63:32] of PLL */ + struct hibmc_drm_device *hidev = dev->dev_private; + + x = mode->hdisplay; + y = mode->vdisplay; + + /* Hisilicon has to set up a new register for PLL control +*(CRT_PLL1_
[path v2 6/7] drm/hisilicon/hibmc: Add support for frame buffer
Add support for fbdev. Signed-off-by: Rongrong Zou Signed-off-by: Jianhua Li --- drivers/gpu/drm/hisilicon/hibmc/Makefile | 2 +- drivers/gpu/drm/hisilicon/hibmc/hibmc_drm_drv.c | 20 ++ drivers/gpu/drm/hisilicon/hibmc/hibmc_drm_drv.h | 17 ++ drivers/gpu/drm/hisilicon/hibmc/hibmc_drm_fbdev.c | 286 ++ 4 files changed, 324 insertions(+), 1 deletion(-) create mode 100644 drivers/gpu/drm/hisilicon/hibmc/hibmc_drm_fbdev.c diff --git a/drivers/gpu/drm/hisilicon/hibmc/Makefile b/drivers/gpu/drm/hisilicon/hibmc/Makefile index 4e7797a..92e7b33 100644 --- a/drivers/gpu/drm/hisilicon/hibmc/Makefile +++ b/drivers/gpu/drm/hisilicon/hibmc/Makefile @@ -1,4 +1,4 @@ -hibmc-drm-y := hibmc_drm_drv.o hibmc_drm_de.o hibmc_drm_vdac.o hibmc_drm_power.o +hibmc-drm-y := hibmc_drm_drv.o hibmc_drm_de.o hibmc_drm_vdac.o hibmc_drm_fbdev.o hibmc_drm_power.o obj-$(CONFIG_DRM_HISI_HIBMC) +=hibmc-drm.o #obj-y += hibmc-drm.o diff --git a/drivers/gpu/drm/hisilicon/hibmc/hibmc_drm_drv.c b/drivers/gpu/drm/hisilicon/hibmc/hibmc_drm_drv.c index 70d79d2..e36a7ec 100644 --- a/drivers/gpu/drm/hisilicon/hibmc/hibmc_drm_drv.c +++ b/drivers/gpu/drm/hisilicon/hibmc/hibmc_drm_drv.c @@ -72,9 +72,16 @@ static int hibmc_pm_suspend(struct device *dev) { struct pci_dev *pdev = to_pci_dev(dev); struct drm_device *drm_dev = pci_get_drvdata(pdev); + struct hibmc_drm_device *hidev = drm_dev->dev_private; drm_kms_helper_poll_disable(drm_dev); + if (hidev->fbdev.initialized) { + console_lock(); + drm_fb_helper_set_suspend(&hidev->fbdev.helper, 1); + console_unlock(); + } + return 0; } @@ -82,8 +89,16 @@ static int hibmc_pm_resume(struct device *dev) { struct pci_dev *pdev = to_pci_dev(dev); struct drm_device *drm_dev = pci_get_drvdata(pdev); + struct hibmc_drm_device *hidev = drm_dev->dev_private; drm_helper_resume_force_mode(drm_dev); + + if (hidev->fbdev.initialized) { + console_lock(); + drm_fb_helper_set_suspend(&hidev->fbdev.helper, 0); + console_unlock(); + } + drm_kms_helper_poll_enable(drm_dev); return 0; @@ -245,6 +260,7 @@ static int hibmc_unload(struct drm_device *dev) { struct hibmc_drm_device *hidev = dev->dev_private; + hibmc_fbdev_fini(hidev); hibmc_kms_fini(hidev); hibmc_hw_fini(hidev); dev->dev_private = NULL; @@ -278,6 +294,10 @@ static int hibmc_load(struct drm_device *dev, unsigned long flags) /* reset all the states of crtc/plane/encoder/connector */ drm_mode_config_reset(dev); + ret = hibmc_fbdev_init(hidev); + if (ret) + goto err; + return 0; err: diff --git a/drivers/gpu/drm/hisilicon/hibmc/hibmc_drm_drv.h b/drivers/gpu/drm/hisilicon/hibmc/hibmc_drm_drv.h index eb5a892..1f32f2e 100644 --- a/drivers/gpu/drm/hisilicon/hibmc/hibmc_drm_drv.h +++ b/drivers/gpu/drm/hisilicon/hibmc/hibmc_drm_drv.h @@ -23,6 +23,18 @@ #include #include +struct hibmc_framebuffer { + struct drm_framebuffer fb; + struct drm_gem_cma_object *obj; + bool is_fbdev_fb; +}; + +struct hibmc_fbdev { + struct hibmc_framebuffer fb; + struct drm_fb_helper helper; + bool initialized; +}; + struct hibmc_drm_device { /* hw */ void __iomem *mmio; @@ -37,11 +49,16 @@ struct hibmc_drm_device { struct drm_encoder encoder; struct drm_connector connector; bool mode_config_initialized; + + /* fbdev */ + struct hibmc_fbdev fbdev; }; int hibmc_plane_init(struct hibmc_drm_device *hidev); int hibmc_crtc_init(struct hibmc_drm_device *hidev); int hibmc_encoder_init(struct hibmc_drm_device *hidev); int hibmc_connector_init(struct hibmc_drm_device *hidev); +int hibmc_fbdev_init(struct hibmc_drm_device *hidev); +void hibmc_fbdev_fini(struct hibmc_drm_device *hidev); #endif diff --git a/drivers/gpu/drm/hisilicon/hibmc/hibmc_drm_fbdev.c b/drivers/gpu/drm/hisilicon/hibmc/hibmc_drm_fbdev.c new file mode 100644 index 000..774bfb0 --- /dev/null +++ b/drivers/gpu/drm/hisilicon/hibmc/hibmc_drm_fbdev.c @@ -0,0 +1,286 @@ +/* Hisilicon Hibmc SoC drm driver + * + * Based on the bochs drm driver. + * + * Copyright (c) 2016 Huawei Limited. + * + * Author: + * Rongrong Zou + * Rongrong Zou + * Jianhua Li + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + */ + +#include +#include +#include +#include + +#include "hibmc_drm_drv.h" + +/* -- */ + +static void hibmc_drm_fb_destroy(struct drm_framebuffer *fb) +{ + struct hibmc_drm_device *hidev = + conta
[path v2 7/7] drm/hisilicon/hibmc: Add maintainer for Hibmc DRM
Signed-off-by: Rongrong Zou Signed-off-by: Jianhua Li --- MAINTAINERS | 7 +++ 1 file changed, 7 insertions(+) diff --git a/MAINTAINERS b/MAINTAINERS index f466673..a8a62e0 100644 --- a/MAINTAINERS +++ b/MAINTAINERS @@ -3957,6 +3957,13 @@ T: git git://github.com/patjak/drm-gma500 S: Maintained F: drivers/gpu/drm/gma500/ +DRM DRIVERS FOR HIBMC +M: lijianhua +M: Rongrong Zou +L: dri-devel at lists.freedesktop.org +S: Maintained +F: drivers/gpu/drm/hisilicon/hibmc + DRM DRIVERS FOR HISILICON M: Xinliang Liu R: Xinwei Kong -- 1.9.1
[RFT v3] drm: use late_initcall() for amdkfd and radeon
On Fri, May 27, 2016 at 4:18 AM, Luis R. Rodriguez wrote: > To get KFD support in radeon we need the following > initialization to happen in this order, their > respective driver file that has its init routine > listed next to it: > > 0. AMD IOMMUv1:arch/x86/kernel/pci-dma.c > 1. AMD IOMMUv2:drivers/iommu/amd_iommu_v2.c > 2. AMD KFD:drivers/gpu/drm/amd/amdkfd/kfd_module.c > 3. AMD Radeon: drivers/gpu/drm/radeon/radeon_drv.c Also AMD amdgpu (for VI+ APUs) > > Order is rather implicit, but these drivers can currently > only do so much given the amount of leg room available. > Below are the respective init routines and how they are > initialized: > > arch/x86/kernel/pci-dma.c rootfs_initcall(pci_iommu_init); > drivers/iommu/amd_iommu_v2.cmodule_init(amd_iommu_v2_init); > drivers/gpu/drm/amd/amdkfd/kfd_module.c module_init(kfd_module_init); > drivers/gpu/drm/radeon/radeon_drv.c module_init(radeon_init); > > When a driver is built-in module_init() folds to use > device_initcall(), and we have the following possible > orders: > > #define pure_initcall(fn)__define_initcall(fn, 0) > #define core_initcall(fn)__define_initcall(fn, 1) > #define postcore_initcall(fn)__define_initcall(fn, 2) > #define arch_initcall(fn)__define_initcall(fn, 3) > #define subsys_initcall(fn) __define_initcall(fn, 4) > #define fs_initcall(fn) __define_initcall(fn, 5) > - > #define rootfs_initcall(fn) __define_initcall(fn, rootfs) > #define device_initcall(fn) __define_initcall(fn, 6) > #define late_initcall(fn)__define_initcall(fn, 7) > > Since we start off from rootfs_initcall(), it gives us 3 more > levels of leg room to play with for order semantics, this isn't > enough to address all required levels of dependencies, this > is specially true given that AMD-KFD needs to be loaded before > the radeon driver -- -but this it not enforced by symbols. > If the AMD-KFD driver is not loaded prior to the radeon driver > because otherwise the radeon driver will not initialize the > AMD-KFD driver and you get no KFD functionality in userspace. > > Commit 1bacc894c227fad8a7 ("drivers: Move iommu/ before gpu/ in > Makefile") works around some of the possibe races between > the AMD IOMMU v2 and GPU drivers by changing the link order. > This is fragile, however its the bets we can do, given that > making the GPU drivers use late_initcall() would also implicate > a similar race between them. That possible race is fortunatley > addressed given that the drm Makefile currently has amdkfd > linked prior to radeon: > > drivers/gpu/drm/Makefile > ... > obj-$(CONFIG_HSA_AMD) += amd/amdkfd/ > obj-$(CONFIG_DRM_RADEON)+= radeon/ > ... > > Changing amdkfd and radeon to late_initcall() however is > still the right call in orde to annotate explicitly a > delayed dependency requirement between the GPU drivers > and the IOMMUs. > > We can't address the fragile nature of the link order > right now, but in the future that might be possible. > > Signed-off-by: Luis R. Rodriguez > --- > > Please note, the changes to drivers/Makefile are just > for the sake of forcing the possible race to occur, > if this works well the actual [PATCH] submission will > skip those changes as its pointless to remove those > work arounds as it stands, due to the limited nature > of the levels available for addressing requirements. > > Also, if you are aware of further dependency hell > things like these -- please do let me know as I am > interested in looking at addressing them. > > drivers/Makefile| 6 ++ > drivers/gpu/drm/amd/amdkfd/kfd_module.c | 2 +- > drivers/gpu/drm/radeon/radeon_drv.c | 2 +- > 3 files changed, 4 insertions(+), 6 deletions(-) > > diff --git a/drivers/Makefile b/drivers/Makefile > index 0b6f3d60193d..0fbe3982041f 100644 > --- a/drivers/Makefile > +++ b/drivers/Makefile > @@ -50,10 +50,7 @@ obj-$(CONFIG_RESET_CONTROLLER) += reset/ > obj-y += tty/ > obj-y += char/ > > -# iommu/ comes before gpu as gpu are using iommu controllers > -obj-$(CONFIG_IOMMU_SUPPORT)+= iommu/ > - > -# gpu/ comes after char for AGP vs DRM startup and after iommu > +# gpu/ comes after char for AGP vs DRM startup > obj-y += gpu/ > > obj-$(CONFIG_CONNECTOR)+= connector/ > @@ -147,6 +144,7 @@ obj-y += clk/ > > obj-$(CONFIG_MAILBOX) += mailbox/ > obj-$(CONFIG_HWSPINLOCK) += hwspinlock/ > +obj-$(CONFIG_IOMMU_SUPPORT)+= iommu/ > obj-$(CONFIG_REMOTEPROC) += remoteproc/ > obj-$(CONFIG_RPMSG)+= rpmsg/ > > diff --git a/drivers/gpu/drm/amd/amdkfd/kfd_module.c > b/drivers/gpu/drm/amd/amdkfd/kfd_module.c > index 850a5623661f..3d1dab8a31c7 100644 > --- a/drivers/gpu/drm/amd/amdkfd/kfd_module.c >
[PATCH v2] gpu: drm: amd: amdkfd: Remove create_workqueue()
On Thu, May 26, 2016 at 10:37 PM, Bhaktipriya Shridhar wrote: > alloc_workqueue replaces deprecated create_workqueue(). > > create_workqueue has been replaced with alloc_workqueue with max_active > as 0 since there is no need for throttling the number of active work items. > > WQ_MEM_RECLAIM has not been set to because kfd_process_wq will not be used in > memory reclaim path. > > kfd_process_wq is used for delay destruction. A work item embedded in > kfd_process gets queued to kfd_process_wq and when it executes it > destroys and frees the containing kfd_process and thus itself. > > This requires a dedicated workqueue because a work item once queued, may > get freed at any point of time and any external entity cannot > flush the work item. So, in order to wait for such a work item, > it needs to be put on a dedicated workqueue. > > kfd_module_exit() calls kfd_process_destroy_wq which ensures that all > pending work items are finished before the module is removed. > > flush_workqueue is unnecessary since destroy_workqueue() itself calls > drain_workqueue() which flushes repeatedly till the workqueue becomes empty. > > Hence flush_workqueue has been removed. > > Signed-off-by: Bhaktipriya Shridhar > --- > Changes in v2: > - added explanation for setting concurrency value to > WQ_DFL_ACTIVE > - added explanation for dropping WQ_MEM_RECLAIM > > drivers/gpu/drm/amd/amdkfd/kfd_process.c | 3 +-- > 1 file changed, 1 insertion(+), 2 deletions(-) > > diff --git a/drivers/gpu/drm/amd/amdkfd/kfd_process.c > b/drivers/gpu/drm/amd/amdkfd/kfd_process.c > index ac00579..b21d3fc8 100644 > --- a/drivers/gpu/drm/amd/amdkfd/kfd_process.c > +++ b/drivers/gpu/drm/amd/amdkfd/kfd_process.c > @@ -63,13 +63,12 @@ static struct kfd_process *create_process(const struct > task_struct *thread); > void kfd_process_create_wq(void) > { > if (!kfd_process_wq) > - kfd_process_wq = create_workqueue("kfd_process_wq"); > + kfd_process_wq = alloc_workqueue("kfd_process_wq",0,0); You are missing a space between the arguments. Seem you forgot to run checkpatch.pl ;) Send a new patch and I'll add it to amdkfd's tree. Thanks, Oded > } > > void kfd_process_destroy_wq(void) > { > if (kfd_process_wq) { > - flush_workqueue(kfd_process_wq); > destroy_workqueue(kfd_process_wq); > kfd_process_wq = NULL; > } > -- > 2.1.4 >
[PATCH v4 3/3] drm: Add helper for simple display pipeline
Den 12.05.2016 20:25, skrev Noralf Trønnes: > Provides helper functions for drivers that have a simple display > pipeline. Plane, crtc and encoder are collapsed into one entity. > > Cc: jsarha at ti.com > Signed-off-by: Noralf Trønnes > --- [...] > diff --git a/drivers/gpu/drm/drm_simple_kms_helper.c > b/drivers/gpu/drm/drm_simple_kms_helper.c > new file mode 100644 > index 000..d45417a > --- /dev/null > +++ b/drivers/gpu/drm/drm_simple_kms_helper.c > @@ -0,0 +1,208 @@ > +/* > + * Copyright (C) 2016 Noralf Trønnes > + * > + * This program is free software; you can redistribute it and/or modify > + * it under the terms of the GNU General Public License as published by > + * the Free Software Foundation; either version 2 of the License, or > + * (at your option) any later version. > + */ > + > +#include > +#include > +#include > +#include > +#include > +#include > +#include > + > +/** > + * DOC: overview > + * > + * This helper library provides helpers for drivers for simple display > + * hardware. > + * > + * drm_simple_display_pipe_init() initializes a simple display pipeline > + * which has only one full-screen scanout buffer feeding one output. The > + * pipeline is represented by struct &drm_simple_display_pipe and binds > + * together &drm_plane, &drm_crtc and &drm_encoder structures into one fixed > + * entity. Some flexibility for code reuse is provided through a separately > + * allocated &drm_connector object and supporting optional &drm_bridge > + * encoder drivers. > + */ > + > +static const struct drm_encoder_funcs drm_simple_kms_encoder_funcs = { > + .destroy = drm_encoder_cleanup, > +}; > + > +static void drm_simple_kms_crtc_enable(struct drm_crtc *crtc) > +{ > + struct drm_simple_display_pipe *pipe; > + > + pipe = container_of(crtc, struct drm_simple_display_pipe, crtc); > + if (!pipe->funcs || !pipe->funcs->enable) > + return; > + > + pipe->funcs->enable(pipe, crtc->state); > +} > + > +static void drm_simple_kms_crtc_disable(struct drm_crtc *crtc) > +{ > + struct drm_simple_display_pipe *pipe; > + > + pipe = container_of(crtc, struct drm_simple_display_pipe, crtc); > + if (!pipe->funcs || !pipe->funcs->disable) > + return; > + > + pipe->funcs->disable(pipe); > +} > + > +static const struct drm_crtc_helper_funcs drm_simple_kms_crtc_helper_funcs = > { > + .disable = drm_simple_kms_crtc_disable, > + .enable = drm_simple_kms_crtc_enable, > +}; > + > +static const struct drm_crtc_funcs drm_simple_kms_crtc_funcs = { > + .reset = drm_atomic_helper_crtc_reset, > + .destroy = drm_crtc_cleanup, > + .set_config = drm_atomic_helper_set_config, > + .page_flip = drm_atomic_helper_page_flip, > + .atomic_duplicate_state = drm_atomic_helper_crtc_duplicate_state, > + .atomic_destroy_state = drm_atomic_helper_crtc_destroy_state, > +}; > + > +static int drm_simple_kms_plane_atomic_check(struct drm_plane *plane, > + struct drm_plane_state *plane_state) > +{ > + struct drm_rect src = { > + .x1 = plane_state->src_x, > + .y1 = plane_state->src_y, > + .x2 = plane_state->src_x + plane_state->src_w, > + .y2 = plane_state->src_y + plane_state->src_h, > + }; > + struct drm_rect dest = { > + .x1 = plane_state->crtc_x, > + .y1 = plane_state->crtc_y, > + .x2 = plane_state->crtc_x + plane_state->crtc_w, > + .y2 = plane_state->crtc_y + plane_state->crtc_h, > + }; > + struct drm_rect clip = { 0 }; > + struct drm_simple_display_pipe *pipe; > + struct drm_crtc_state *crtc_state; > + bool visible; > + int ret; > + > + pipe = container_of(plane, struct drm_simple_display_pipe, plane); > + crtc_state = drm_atomic_get_existing_crtc_state(plane_state->state, > + &pipe->crtc); > + if (crtc_state->enable != !!plane_state->crtc) > + return -EINVAL; /* plane must match crtc enable state */ > + > + if (!crtc_state->enable) > + return 0; /* nothing to check when disabling or disabled */ > + > + clip.x2 = crtc_state->adjusted_mode.hdisplay; > + clip.y2 = crtc_state->adjusted_mode.vdisplay; > + ret = drm_plane_helper_check_update(plane, &pipe->crtc, > + plane_state->fb, > + &src, &dest, &clip, > + DRM_PLANE_HELPER_NO_SCALING, > + DRM_PLANE_HELPER_NO_SCALING, > + false, true, &visible); > + if (ret) > + return ret; > + > + if (!visible) > + return -EINVAL; > + > + if (!pipe->funcs || !pipe->funcs->check) > + return 0; > + > + return pipe->funcs->check(pipe, plane_state, crtc_state); > +} > + > +static void drm_simple_
[Nouveau] [PATCH 1/9] drm/nouveau: Don't leak runtime pm ref on driver unload
Hi Peter, On Fri, May 27, 2016 at 03:07:33AM +0200, Peter Wu wrote: > On Tue, May 24, 2016 at 06:03:27PM +0200, Lukas Wunner wrote: > > nouveau_drm_load() calls pm_runtime_put() if nouveau_runtime_pm != 0, > > but nouveau_drm_unload() calls pm_runtime_get_sync() unconditionally. > > We therefore leak a runtime pm ref whenever nouveau is loaded with > > runpm=0 and then unloaded. The GPU will subsequently never runtime > > suspend even if nouveau is loaded again with runpm=1. > > > > Fix by taking the runtime pm ref under the same condition that it was > > released on driver load. > > > > Fixes: 5addcf0a5f0f ("nouveau: add runtime PM support (v0.9)") > > Cc: Dave Airlie > > Reported-by: Karol Herbst > > Tested-by: Karol Herbst > > Signed-off-by: Lukas Wunner > > Looks good, I tested this scenario: > > ru(){ cat /sys/bus/pci/devices/\:01:00.0/power/runtime_usage;} > ru # reports 1 > modprobe nouveau runpm=0 > ru # reports 2 > rmmod nouveau > ru # reports 1 > > Without runpm=0 the count drops to 0 in the second step and stays 0 in > the third step. After applying patch 2/9, this correctly reports 1 as > expected (this is the same as manually setting power/control to on). How exactly did you reach the situation where the root port didn't wake up when you tried to load nouveau again? (IRC conversation this week.) What's happening is, the PCI core will keep unbound devices (i.e., without driver) in D0 but the runtime status is allowed to change to "suspended". So it'll appear to the kernel as if it was suspended but in reality it stays in D0. Once runtime pm for PCIe ports gets merged, the root port above the GPU will indeed go to D3 in such a situation because the check pm_children_suspended() (called from rpm_check_suspend_allowed()) returns true. I'm not sure if this is desirable or not. If we keep unbound devices in D0, should we allow ports above them to go to D3? In any case, when nouveau is loaded again, local_pci_probe() will call pm_runtime_get_sync(), which will implicitly set the runtime status to "active" and which should also wake parents. So how did you ever reach a point where you loaded nouveau and the root port stayed asleep? Clearly we have a bug there, question is where. This shouldn't work only if pm_runtime_forbid() was called on driver unload. Thanks for the extensive testing! Lukas > > Peter > > > --- > > drivers/gpu/drm/nouveau/nouveau_drm.c | 5 - > > 1 file changed, 4 insertions(+), 1 deletion(-) > > > > diff --git a/drivers/gpu/drm/nouveau/nouveau_drm.c > > b/drivers/gpu/drm/nouveau/nouveau_drm.c > > index 11f8dd9..faf7438 100644 > > --- a/drivers/gpu/drm/nouveau/nouveau_drm.c > > +++ b/drivers/gpu/drm/nouveau/nouveau_drm.c > > @@ -498,7 +498,10 @@ nouveau_drm_unload(struct drm_device *dev) > > { > > struct nouveau_drm *drm = nouveau_drm(dev); > > > > - pm_runtime_get_sync(dev->dev); > > + if (nouveau_runtime_pm != 0) { > > + pm_runtime_get_sync(dev->dev); > > + } > > + > > nouveau_fbcon_fini(dev); > > nouveau_accel_fini(drm); > > nouveau_hwmon_fini(dev); > > -- > > 2.8.1 > > > > ___ > > Nouveau mailing list > > Nouveau at lists.freedesktop.org > > https://lists.freedesktop.org/mailman/listinfo/nouveau > > -- > Kind regards, > Peter Wu > https://lekensteyn.nl
[Bug 119181] New: Hang in amdgpu_vm_bo_update_mapping with powerplay enabled
https://bugzilla.kernel.org/show_bug.cgi?id=119181 Bug ID: 119181 Summary: Hang in amdgpu_vm_bo_update_mapping with powerplay enabled Product: Drivers Version: 2.5 Kernel Version: 4.5.4 Hardware: All OS: Linux Tree: Mainline Status: NEW Severity: normal Priority: P1 Component: Video(DRI - non Intel) Assignee: drivers_video-dri at kernel-bugs.osdl.org Reporter: mustrumr97 at gmail.com Regression: No Created attachment 218111 --> https://bugzilla.kernel.org/attachment.cgi?id=218111&action=edit Stack trace (sysrq-w) This happens after a few minutes in a 3D-intensive workload (e.g. Kerbal Space Program). The game hangs, but the mouse is moving. A few seconds later the mouse stops moving. 1. The game is waiting on an ioctl (libdrm: amdgpu_fence_wait/amdgpu_cs_query_fence_status) 2. Xorg is in D state (see attached stack trace). 3. CPU load at ~0%. 4. Nothing interesting in kernel log. The kernel has voluntary preemption enabled, the GPU is 1002:6938 (AMD Radeon 380X). It is at 56°C, quickly drops down to 51 when forced to low performance state, goes up to 56 when at auto. -- You are receiving this mail because: You are watching the assignee of the bug.
[RFT v3] drm: use late_initcall() for amdkfd and radeon
On Fri, May 27, 2016 at 3:18 AM, Luis R. Rodriguez wrote: > To get KFD support in radeon we need the following > initialization to happen in this order, their > respective driver file that has its init routine > listed next to it: > > 0. AMD IOMMUv1:arch/x86/kernel/pci-dma.c > 1. AMD IOMMUv2:drivers/iommu/amd_iommu_v2.c > 2. AMD KFD:drivers/gpu/drm/amd/amdkfd/kfd_module.c > 3. AMD Radeon: drivers/gpu/drm/radeon/radeon_drv.c > > Order is rather implicit, but these drivers can currently > only do so much given the amount of leg room available. > Below are the respective init routines and how they are > initialized: > > arch/x86/kernel/pci-dma.c rootfs_initcall(pci_iommu_init); > drivers/iommu/amd_iommu_v2.cmodule_init(amd_iommu_v2_init); > drivers/gpu/drm/amd/amdkfd/kfd_module.c module_init(kfd_module_init); > drivers/gpu/drm/radeon/radeon_drv.c module_init(radeon_init); > > When a driver is built-in module_init() folds to use > device_initcall(), and we have the following possible > orders: > > #define pure_initcall(fn)__define_initcall(fn, 0) > #define core_initcall(fn)__define_initcall(fn, 1) > #define postcore_initcall(fn)__define_initcall(fn, 2) > #define arch_initcall(fn)__define_initcall(fn, 3) > #define subsys_initcall(fn) __define_initcall(fn, 4) > #define fs_initcall(fn) __define_initcall(fn, 5) > - > #define rootfs_initcall(fn) __define_initcall(fn, rootfs) > #define device_initcall(fn) __define_initcall(fn, 6) > #define late_initcall(fn)__define_initcall(fn, 7) > > Since we start off from rootfs_initcall(), it gives us 3 more > levels of leg room to play with for order semantics, this isn't > enough to address all required levels of dependencies, this > is specially true given that AMD-KFD needs to be loaded before > the radeon driver -- -but this it not enforced by symbols. > If the AMD-KFD driver is not loaded prior to the radeon driver > because otherwise the radeon driver will not initialize the > AMD-KFD driver and you get no KFD functionality in userspace. > > Commit 1bacc894c227fad8a7 ("drivers: Move iommu/ before gpu/ in > Makefile") works around some of the possibe races between > the AMD IOMMU v2 and GPU drivers by changing the link order. > This is fragile, however its the bets we can do, given that > making the GPU drivers use late_initcall() would also implicate > a similar race between them. That possible race is fortunatley > addressed given that the drm Makefile currently has amdkfd > linked prior to radeon: > > drivers/gpu/drm/Makefile > ... > obj-$(CONFIG_HSA_AMD) += amd/amdkfd/ > obj-$(CONFIG_DRM_RADEON)+= radeon/ > ... > > Changing amdkfd and radeon to late_initcall() however is > still the right call in orde to annotate explicitly a > delayed dependency requirement between the GPU drivers > and the IOMMUs. > > We can't address the fragile nature of the link order > right now, but in the future that might be possible. > > Signed-off-by: Luis R. Rodriguez > --- > > Please note, the changes to drivers/Makefile are just > for the sake of forcing the possible race to occur, > if this works well the actual [PATCH] submission will > skip those changes as its pointless to remove those > work arounds as it stands, due to the limited nature > of the levels available for addressing requirements. > > Also, if you are aware of further dependency hell > things like these -- please do let me know as I am > interested in looking at addressing them. This should be fixed with -EDEFER_PROBE instead. Frobbing initcall levels should then just be done as an optimization to avoid too much reprobing. Thanks, Daniel -- Daniel Vetter Software Engineer, Intel Corporation +41 (0) 79 365 57 48 - http://blog.ffwll.ch
[PATCH 00/26] RFC: generic nonblocking support in the atomic helpers
Hi all, So I finally unlazied and implemented generic nonblocking atomic commit support in the atomic helpers. Still an early draft, but stopped being a fireworks show on i915 at least. Rockchip still oopses somewhere, virtio conversion is entirely untested. Same for arc/hdlcd/fsl-du/sun4i. All these untested drivers must be converted since they've been a bit too lazy in their atomic implementations and simply didn't bother implementing nonblocking. The main patch adding the helpers explains the design, I just want to highlight one key aspect: This code fully relies on correct handling of crtc_state->event, drivers which don't get this right will fall over. To avoid too much trouble the helpers all have a 10s timeout, in case of broken drivers. This is both good - hopefully no more atomic drivers that just outright forget to implement drm event handling. And also a bit annoying for getting this series in since the above mentioned 5 atomic drivers all look like they haven't been properly tested with events. Stuff left to do: - Debug at least rockchip&virtio I'd say to make sure it works there flawlessly. Would be good to also convert some other drivers. - Get as much debugging on the other 4 drivers which have to be converted. Otoh they already have a broken atomic implementation in-tree, so me. - Kerneldoc for a bunch of functions is still missing, plus the updated overview section for nonblocking commits. - Bugfixing, but I hope that the helpers themselves are solid now. Cheers, Daniel Daniel Vetter (25): drm/atomic-helper: use for_each_*_in_state more drm/i915: Use drm_atomic_get_existing_plane_state drm/msm: Use for_each_*_in_state drm/rcar-du: Use for_each_*_in_state drm/vc4: Use for_each_plane_in_state drm/atomic: Add __drm_atomic_get_current_plane_state drm/exynos: Use for_each_crtc_in_state drm: Consolidate connector arrays in drm_atomic_state drm: Consolidate plane arrays in drm_atomic_state drm: Consolidate crtc arrays in drm_atomic_state drm/atomic-helper: Massage swap_state signature somewhat drm/arc: Nuke event_list drm/arc: Actually bother with handling atomic events. drm/arc: Implement nonblocking commit correctly drm/hdlcd: Use helper support for nonblocking commits drm/fsl-du: Implement some semblance of vblank event handling drm/hisilicon: Implement some semblance of vblank event handling drm/sun4i: Implement some semblance of vblank event handling drm/atomic: kerneldoc for drm_atomic_crtc_needs_modeset drm/atomic-helper: nonblocking commit support drm/i915: Signal drm events for atomic drm/i915: Roll out the helper nonblock tracking drm/rockchip: convert to helper nonblocking atomic commit drm/rockchip: Nuke pending event handling in preclose drm/virtio: Don't reinvent a flipping wheel Gustavo Padovan (1): drm/fence: add fence to drm_pending_event drivers/gpu/drm/arc/arcpgu.h| 1 - drivers/gpu/drm/arc/arcpgu_crtc.c | 19 +- drivers/gpu/drm/arc/arcpgu_drv.c| 27 +- drivers/gpu/drm/arm/hdlcd_drv.c | 8 +- drivers/gpu/drm/atmel-hlcdc/atmel_hlcdc_dc.c| 2 +- drivers/gpu/drm/drm_atomic.c| 102 +++--- drivers/gpu/drm/drm_atomic_helper.c | 421 drivers/gpu/drm/drm_crtc.c | 3 + drivers/gpu/drm/drm_fops.c | 22 +- drivers/gpu/drm/exynos/exynos_drm_drv.c | 10 +- drivers/gpu/drm/fsl-dcu/fsl_dcu_drm_crtc.c | 23 +- drivers/gpu/drm/hisilicon/kirin/kirin_drm_ade.c | 20 +- drivers/gpu/drm/i915/intel_atomic.c | 6 +- drivers/gpu/drm/i915/intel_display.c| 25 +- drivers/gpu/drm/i915/intel_sprite.c | 14 + drivers/gpu/drm/mediatek/mtk_drm_drv.c | 2 +- drivers/gpu/drm/msm/mdp/mdp4/mdp4_kms.c | 20 +- drivers/gpu/drm/msm/mdp/mdp5/mdp5_crtc.c| 10 +- drivers/gpu/drm/msm/mdp/mdp5/mdp5_kms.c | 12 +- drivers/gpu/drm/msm/msm_atomic.c| 37 +-- drivers/gpu/drm/nouveau/nouveau_usif.c | 1 - drivers/gpu/drm/omapdrm/omap_drv.c | 2 +- drivers/gpu/drm/rcar-du/rcar_du_kms.c | 10 +- drivers/gpu/drm/rcar-du/rcar_du_plane.c | 20 +- drivers/gpu/drm/rockchip/rockchip_drm_drv.c | 25 -- drivers/gpu/drm/rockchip/rockchip_drm_drv.h | 11 - drivers/gpu/drm/rockchip/rockchip_drm_fb.c | 73 +--- drivers/gpu/drm/rockchip/rockchip_drm_vop.c | 35 +- drivers/gpu/drm/sti/sti_drv.c | 2 +- drivers/gpu/drm/sun4i/sun4i_crtc.c | 12 + drivers/gpu/drm/tegra/drm.c | 2 +- drivers/gpu/drm/vc4/vc4_crtc.c | 11 +- drivers/gpu/drm/vc4/vc4_drv.h | 2 +- drivers/gpu/drm/vc4/vc4_kms.c | 12 +- drivers/gpu/drm/vc4/vc4_plane.c | 5 +- drivers/gpu/drm/virtio/virtgpu_display.c| 48 +-- inclu
[PATCH 01/26] drm/atomic-helper: use for_each_*_in_state more
This avois leaking drm_atomic_state internals into the helpers. The only place where this still happens after this patch is drm_atomic_helper_swap_state(). It's unavoidable there, and maybe a good indicator we should actually move that function into drm_atomic.c. Signed-off-by: Daniel Vetter --- drivers/gpu/drm/drm_atomic_helper.c | 47 + 1 file changed, 16 insertions(+), 31 deletions(-) diff --git a/drivers/gpu/drm/drm_atomic_helper.c b/drivers/gpu/drm/drm_atomic_helper.c index ddfa0d120e39..464541c87c40 100644 --- a/drivers/gpu/drm/drm_atomic_helper.c +++ b/drivers/gpu/drm/drm_atomic_helper.c @@ -611,7 +611,7 @@ drm_atomic_helper_check_planes(struct drm_device *dev, if (!funcs || !funcs->atomic_check) continue; - ret = funcs->atomic_check(crtc, state->crtc_states[i]); + ret = funcs->atomic_check(crtc, crtc_state); if (ret) { DRM_DEBUG_ATOMIC("[CRTC:%d:%s] atomic driver check failed\n", crtc->base.id, crtc->name); @@ -1249,16 +1249,12 @@ EXPORT_SYMBOL(drm_atomic_helper_commit); int drm_atomic_helper_prepare_planes(struct drm_device *dev, struct drm_atomic_state *state) { - int nplanes = dev->mode_config.num_total_plane; - int ret, i; + struct drm_plane *plane; + struct drm_plane_state *plane_state; + int ret, i, j; - for (i = 0; i < nplanes; i++) { + for_each_plane_in_state(state, plane, plane_state, i) { const struct drm_plane_helper_funcs *funcs; - struct drm_plane *plane = state->planes[i]; - struct drm_plane_state *plane_state = state->plane_states[i]; - - if (!plane) - continue; funcs = plane->helper_private; @@ -1272,12 +1268,10 @@ int drm_atomic_helper_prepare_planes(struct drm_device *dev, return 0; fail: - for (i--; i >= 0; i--) { + for_each_plane_in_state(state, plane, plane_state, j) { const struct drm_plane_helper_funcs *funcs; - struct drm_plane *plane = state->planes[i]; - struct drm_plane_state *plane_state = state->plane_states[i]; - if (!plane) + if (j >= i) continue; funcs = plane->helper_private; @@ -1564,35 +1558,26 @@ void drm_atomic_helper_swap_state(struct drm_device *dev, struct drm_atomic_state *state) { int i; + struct drm_connector *connector; + struct drm_connector_state *conn_state; + struct drm_crtc *crtc; + struct drm_crtc_state *crtc_state; + struct drm_plane *plane; + struct drm_plane_state *plane_state; - for (i = 0; i < state->num_connector; i++) { - struct drm_connector *connector = state->connectors[i]; - - if (!connector) - continue; - + for_each_connector_in_state(state, connector, conn_state, i) { connector->state->state = state; swap(state->connector_states[i], connector->state); connector->state->state = NULL; } - for (i = 0; i < dev->mode_config.num_crtc; i++) { - struct drm_crtc *crtc = state->crtcs[i]; - - if (!crtc) - continue; - + for_each_crtc_in_state(state, crtc, crtc_state, i) { crtc->state->state = state; swap(state->crtc_states[i], crtc->state); crtc->state->state = NULL; } - for (i = 0; i < dev->mode_config.num_total_plane; i++) { - struct drm_plane *plane = state->planes[i]; - - if (!plane) - continue; - + for_each_plane_in_state(state, plane, plane_state, i) { plane->state->state = state; swap(state->plane_states[i], plane->state); plane->state->state = NULL; -- 2.8.1
[PATCH 02/26] drm/i915: Use drm_atomic_get_existing_plane_state
We want to encapsulate the drm_atomic_state internals. Signed-off-by: Daniel Vetter --- drivers/gpu/drm/i915/intel_atomic.c | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/drivers/gpu/drm/i915/intel_atomic.c b/drivers/gpu/drm/i915/intel_atomic.c index 50ff90aea721..3e6d9ff8840a 100644 --- a/drivers/gpu/drm/i915/intel_atomic.c +++ b/drivers/gpu/drm/i915/intel_atomic.c @@ -223,7 +223,9 @@ int intel_atomic_setup_scalers(struct drm_device *dev, continue; } - plane_state = to_intel_plane_state(drm_state->plane_states[i]); + plane_state = to_intel_plane_state( + drm_atomic_get_existing_plane_state(drm_state, + plane)); scaler_id = &plane_state->scaler_id; } -- 2.8.1
[PATCH 03/26] drm/msm: Use for_each_*_in_state
We want to hide drm_atomic_state internals Cc: Rob Clark Signed-off-by: Daniel Vetter --- drivers/gpu/drm/msm/mdp/mdp4/mdp4_kms.c| 20 +++-- drivers/gpu/drm/msm/mdp/mdp5/mdp5_kms.c| 12 +++--- drivers/gpu/drm/msm/msm_atomic.c | 35 ++ drivers/gpu/drm/rockchip/rockchip_drm_fb.c | 1 + 4 files changed, 23 insertions(+), 45 deletions(-) diff --git a/drivers/gpu/drm/msm/mdp/mdp4/mdp4_kms.c b/drivers/gpu/drm/msm/mdp/mdp4/mdp4_kms.c index 67442d50a6c2..f145d256e332 100644 --- a/drivers/gpu/drm/msm/mdp/mdp4/mdp4_kms.c +++ b/drivers/gpu/drm/msm/mdp/mdp4/mdp4_kms.c @@ -106,31 +106,27 @@ out: static void mdp4_prepare_commit(struct msm_kms *kms, struct drm_atomic_state *state) { struct mdp4_kms *mdp4_kms = to_mdp4_kms(to_mdp_kms(kms)); - int i, ncrtcs = state->dev->mode_config.num_crtc; + int i; + struct drm_crtc *crtc; + struct drm_crtc_state *crtc_state; mdp4_enable(mdp4_kms); /* see 119ecb7fd */ - for (i = 0; i < ncrtcs; i++) { - struct drm_crtc *crtc = state->crtcs[i]; - if (!crtc) - continue; + for_each_crtc_in_state(state, crtc, crtc_state, i) drm_crtc_vblank_get(crtc); - } } static void mdp4_complete_commit(struct msm_kms *kms, struct drm_atomic_state *state) { struct mdp4_kms *mdp4_kms = to_mdp4_kms(to_mdp_kms(kms)); - int i, ncrtcs = state->dev->mode_config.num_crtc; + int i; + struct drm_crtc *crtc; + struct drm_crtc_state *crtc_state; /* see 119ecb7fd */ - for (i = 0; i < ncrtcs; i++) { - struct drm_crtc *crtc = state->crtcs[i]; - if (!crtc) - continue; + for_each_crtc_in_state(state, crtc, crtc_state, i) drm_crtc_vblank_put(crtc); - } mdp4_disable(mdp4_kms); } diff --git a/drivers/gpu/drm/msm/mdp/mdp5/mdp5_kms.c b/drivers/gpu/drm/msm/mdp/mdp5/mdp5_kms.c index 484b4d15e71d..f0c285b1c027 100644 --- a/drivers/gpu/drm/msm/mdp/mdp5/mdp5_kms.c +++ b/drivers/gpu/drm/msm/mdp/mdp5/mdp5_kms.c @@ -78,17 +78,11 @@ static void mdp5_complete_commit(struct msm_kms *kms, struct drm_atomic_state *s { int i; struct mdp5_kms *mdp5_kms = to_mdp5_kms(to_mdp_kms(kms)); - int nplanes = mdp5_kms->dev->mode_config.num_total_plane; - - for (i = 0; i < nplanes; i++) { - struct drm_plane *plane = state->planes[i]; - struct drm_plane_state *plane_state = state->plane_states[i]; - - if (!plane) - continue; + struct drm_plane *plane; + struct drm_plane_state *plane_state; + for_each_plane_in_state(state, plane, plane_state, i) mdp5_plane_complete_commit(plane, plane_state); - } mdp5_disable(mdp5_kms); } diff --git a/drivers/gpu/drm/msm/msm_atomic.c b/drivers/gpu/drm/msm/msm_atomic.c index e3892c263f27..9c0e4261dbba 100644 --- a/drivers/gpu/drm/msm/msm_atomic.c +++ b/drivers/gpu/drm/msm/msm_atomic.c @@ -84,17 +84,12 @@ static void msm_atomic_wait_for_commit_done(struct drm_device *dev, struct drm_atomic_state *old_state) { struct drm_crtc *crtc; + struct drm_crtc_state *crtc_state; struct msm_drm_private *priv = old_state->dev->dev_private; struct msm_kms *kms = priv->kms; - int ncrtcs = old_state->dev->mode_config.num_crtc; int i; - for (i = 0; i < ncrtcs; i++) { - crtc = old_state->crtcs[i]; - - if (!crtc) - continue; - + for_each_crtc_in_state(old_state, crtc, crtc_state, i) { if (!crtc->state->enable) continue; @@ -192,9 +187,11 @@ int msm_atomic_commit(struct drm_device *dev, struct drm_atomic_state *state, bool nonblock) { struct msm_drm_private *priv = dev->dev_private; - int nplanes = dev->mode_config.num_total_plane; - int ncrtcs = dev->mode_config.num_crtc; struct msm_commit *c; + struct drm_crtc *crtc; + struct drm_crtc_state *crtc_state; + struct drm_plane *plane; + struct drm_plane_state *plane_state; int i, ret; ret = drm_atomic_helper_prepare_planes(dev, state); @@ -210,28 +207,18 @@ int msm_atomic_commit(struct drm_device *dev, /* * Figure out what crtcs we have: */ - for (i = 0; i < ncrtcs; i++) { - struct drm_crtc *crtc = state->crtcs[i]; - if (!crtc) - continue; + for_each_crtc_in_state(state, crtc, crtc_state, i) c->crtc_mask |= (1 << drm_crtc_index(crtc)); - } /* * Figure out what fence to wait for: */ - for (i = 0; i < nplanes; i++) { - struct drm_plane *plane = state->planes[i]; - struct drm_plane_state *new_state =
[PATCH 04/26] drm/rcar-du: Use for_each_*_in_state
We want to hide drm_atomic_state internals better. Cc: Laurent Pinchart Signed-off-by: Daniel Vetter --- drivers/gpu/drm/rcar-du/rcar_du_kms.c | 8 drivers/gpu/drm/rcar-du/rcar_du_plane.c | 20 2 files changed, 12 insertions(+), 16 deletions(-) diff --git a/drivers/gpu/drm/rcar-du/rcar_du_kms.c b/drivers/gpu/drm/rcar-du/rcar_du_kms.c index e70a4f33d970..f315c55c1f65 100644 --- a/drivers/gpu/drm/rcar-du/rcar_du_kms.c +++ b/drivers/gpu/drm/rcar-du/rcar_du_kms.c @@ -288,6 +288,8 @@ static int rcar_du_atomic_commit(struct drm_device *dev, { struct rcar_du_device *rcdu = dev->dev_private; struct rcar_du_commit *commit; + struct drm_crtc *crtc; + struct drm_crtc_state *crtc_state; unsigned int i; int ret; @@ -309,10 +311,8 @@ static int rcar_du_atomic_commit(struct drm_device *dev, /* Wait until all affected CRTCs have completed previous commits and * mark them as pending. */ - for (i = 0; i < dev->mode_config.num_crtc; ++i) { - if (state->crtcs[i]) - commit->crtcs |= 1 << drm_crtc_index(state->crtcs[i]); - } + for_each_crtc_in_state(state, crtc, crtc_state, i) + commit->crtcs |= 1 << drm_crtc_index(crtc); spin_lock(&rcdu->commit.wait.lock); ret = wait_event_interruptible_locked(rcdu->commit.wait, diff --git a/drivers/gpu/drm/rcar-du/rcar_du_plane.c b/drivers/gpu/drm/rcar-du/rcar_du_plane.c index d445e67f78e1..bfe31ca870cc 100644 --- a/drivers/gpu/drm/rcar-du/rcar_du_plane.c +++ b/drivers/gpu/drm/rcar-du/rcar_du_plane.c @@ -140,18 +140,17 @@ int rcar_du_atomic_check_planes(struct drm_device *dev, bool needs_realloc = false; unsigned int groups = 0; unsigned int i; + struct drm_plane *drm_plane; + struct drm_plane_state *drm_plane_state; /* Check if hardware planes need to be reallocated. */ - for (i = 0; i < dev->mode_config.num_total_plane; ++i) { + for_each_plane_in_state(state, drm_plane, drm_plane_state, i) { struct rcar_du_plane_state *plane_state; struct rcar_du_plane *plane; unsigned int index; - if (!state->planes[i]) - continue; - - plane = to_rcar_plane(state->planes[i]); - plane_state = to_rcar_plane_state(state->plane_states[i]); + plane = to_rcar_plane(drm_plane); + plane_state = to_rcar_plane_state(drm_plane_state); dev_dbg(rcdu->dev, "%s: checking plane (%u,%tu)\n", __func__, plane->group->index, plane - plane->group->planes); @@ -247,18 +246,15 @@ int rcar_du_atomic_check_planes(struct drm_device *dev, } /* Reallocate hardware planes for each plane that needs it. */ - for (i = 0; i < dev->mode_config.num_total_plane; ++i) { + for_each_plane_in_state(state, drm_plane, drm_plane_state, i) { struct rcar_du_plane_state *plane_state; struct rcar_du_plane *plane; unsigned int crtc_planes; unsigned int free; int idx; - if (!state->planes[i]) - continue; - - plane = to_rcar_plane(state->planes[i]); - plane_state = to_rcar_plane_state(state->plane_states[i]); + plane = to_rcar_plane(drm_plane); + plane_state = to_rcar_plane_state(drm_plane_state); dev_dbg(rcdu->dev, "%s: allocating plane (%u,%tu)\n", __func__, plane->group->index, plane - plane->group->planes); -- 2.8.1
[PATCH 05/26] drm/vc4: Use for_each_plane_in_state
We want to hide drm_atomic_stat internals a bit better. Cc: Eric Anholt Signed-off-by: Daniel Vetter --- drivers/gpu/drm/vc4/vc4_kms.c | 10 +++--- 1 file changed, 3 insertions(+), 7 deletions(-) diff --git a/drivers/gpu/drm/vc4/vc4_kms.c b/drivers/gpu/drm/vc4/vc4_kms.c index cb37751bc99f..39c0b2048bfd 100644 --- a/drivers/gpu/drm/vc4/vc4_kms.c +++ b/drivers/gpu/drm/vc4/vc4_kms.c @@ -111,6 +111,8 @@ static int vc4_atomic_commit(struct drm_device *dev, int i; uint64_t wait_seqno = 0; struct vc4_commit *c; + struct drm_plane *plane; + struct drm_plane_state *new_state; c = commit_init(state); if (!c) @@ -130,13 +132,7 @@ static int vc4_atomic_commit(struct drm_device *dev, return ret; } - for (i = 0; i < dev->mode_config.num_total_plane; i++) { - struct drm_plane *plane = state->planes[i]; - struct drm_plane_state *new_state = state->plane_states[i]; - - if (!plane) - continue; - + for_each_plane_in_state(state, plane, new_state, i) { if ((plane->state->fb != new_state->fb) && new_state->fb) { struct drm_gem_cma_object *cma_bo = drm_fb_cma_get_gem_obj(new_state->fb, 0); -- 2.8.1
[PATCH 06/26] drm/atomic: Add __drm_atomic_get_current_plane_state
... and use it in msm&vc4. Again just want to encapsulate drm_atomic_state internals a bit. The const threading is a bit awkward in vc4 since C sucks, but I still think it's worth to enforce this. Eventually I want to make all the obj->state pointers const too, but that's a lot more work ... Cc: Eric Anholt Cc: Rob Clark Signed-off-by: Daniel Vetter --- drivers/gpu/drm/msm/mdp/mdp5/mdp5_crtc.c | 10 +++-- drivers/gpu/drm/vc4/vc4_crtc.c | 11 +++--- drivers/gpu/drm/vc4/vc4_drv.h| 2 +- drivers/gpu/drm/vc4/vc4_plane.c | 5 +++-- include/drm/drm_atomic.h | 36 5 files changed, 46 insertions(+), 18 deletions(-) diff --git a/drivers/gpu/drm/msm/mdp/mdp5/mdp5_crtc.c b/drivers/gpu/drm/msm/mdp/mdp5/mdp5_crtc.c index 88fe256c1931..6d4086ee0503 100644 --- a/drivers/gpu/drm/msm/mdp/mdp5/mdp5_crtc.c +++ b/drivers/gpu/drm/msm/mdp/mdp5/mdp5_crtc.c @@ -383,19 +383,15 @@ static int mdp5_crtc_atomic_check(struct drm_crtc *crtc, */ hw_cfg = mdp5_cfg_get_hw_config(mdp5_kms->cfg); drm_atomic_crtc_state_for_each_plane(plane, state) { - struct drm_plane_state *pstate; + const struct drm_plane_state *pstate; if (cnt >= (hw_cfg->lm.nb_stages)) { dev_err(dev->dev, "too many planes!\n"); return -EINVAL; } - pstate = state->state->plane_states[drm_plane_index(plane)]; + pstate = __drm_atomic_get_current_plane_state(state->state, + plane); - /* plane might not have changed, in which case take -* current state: -*/ - if (!pstate) - pstate = plane->state; pstates[cnt].plane = plane; pstates[cnt].state = to_mdp5_plane_state(pstate); diff --git a/drivers/gpu/drm/vc4/vc4_crtc.c b/drivers/gpu/drm/vc4/vc4_crtc.c index 904d0754ad78..703bda170105 100644 --- a/drivers/gpu/drm/vc4/vc4_crtc.c +++ b/drivers/gpu/drm/vc4/vc4_crtc.c @@ -405,14 +405,9 @@ static int vc4_crtc_atomic_check(struct drm_crtc *crtc, return -EINVAL; drm_atomic_crtc_state_for_each_plane(plane, state) { - struct drm_plane_state *plane_state = - state->state->plane_states[drm_plane_index(plane)]; - - /* plane might not have changed, in which case take -* current state: -*/ - if (!plane_state) - plane_state = plane->state; + const struct drm_plane_state *plane_state = + __drm_atomic_get_current_plane_state(state->state, +plane); dlist_count += vc4_plane_dlist_size(plane_state); } diff --git a/drivers/gpu/drm/vc4/vc4_drv.h b/drivers/gpu/drm/vc4/vc4_drv.h index 37cac59401d7..c799baabc008 100644 --- a/drivers/gpu/drm/vc4/vc4_drv.h +++ b/drivers/gpu/drm/vc4/vc4_drv.h @@ -469,7 +469,7 @@ int vc4_kms_load(struct drm_device *dev); struct drm_plane *vc4_plane_init(struct drm_device *dev, enum drm_plane_type type); u32 vc4_plane_write_dlist(struct drm_plane *plane, u32 __iomem *dlist); -u32 vc4_plane_dlist_size(struct drm_plane_state *state); +u32 vc4_plane_dlist_size(const struct drm_plane_state *state); void vc4_plane_async_set_fb(struct drm_plane *plane, struct drm_framebuffer *fb); diff --git a/drivers/gpu/drm/vc4/vc4_plane.c b/drivers/gpu/drm/vc4/vc4_plane.c index 4037b52fde31..5d2c3d9fd17a 100644 --- a/drivers/gpu/drm/vc4/vc4_plane.c +++ b/drivers/gpu/drm/vc4/vc4_plane.c @@ -690,9 +690,10 @@ u32 vc4_plane_write_dlist(struct drm_plane *plane, u32 __iomem *dlist) return vc4_state->dlist_count; } -u32 vc4_plane_dlist_size(struct drm_plane_state *state) +u32 vc4_plane_dlist_size(const struct drm_plane_state *state) { - struct vc4_plane_state *vc4_state = to_vc4_plane_state(state); + const struct vc4_plane_state *vc4_state = + container_of(state, typeof(*vc4_state), base); return vc4_state->dlist_count; } diff --git a/include/drm/drm_atomic.h b/include/drm/drm_atomic.h index 92c84e9ab09a..4e97186293be 100644 --- a/include/drm/drm_atomic.h +++ b/include/drm/drm_atomic.h @@ -109,6 +109,42 @@ drm_atomic_get_existing_connector_state(struct drm_atomic_state *state, return state->connector_states[index]; } +/** + * __drm_atomic_get_current_plane_state - get current plane state + * @state: global atomic state object + * @plane: plane to grab + * + * This function returns the plane state for the given plane, either from + * @state, or if the plane isn't part of the atomic state update, from @plane. + * This is useful in atomic check callbacks, when drivers need to peek at, but + * not c
[PATCH 07/26] drm/exynos: Use for_each_crtc_in_state
We want to hide drm_atomic_state internals better. Cc: Inki Dae Signed-off-by: Daniel Vetter --- drivers/gpu/drm/exynos/exynos_drm_drv.c | 8 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/drivers/gpu/drm/exynos/exynos_drm_drv.c b/drivers/gpu/drm/exynos/exynos_drm_drv.c index 2dd820e23b0c..cabc5fd0246d 100644 --- a/drivers/gpu/drm/exynos/exynos_drm_drv.c +++ b/drivers/gpu/drm/exynos/exynos_drm_drv.c @@ -267,6 +267,8 @@ int exynos_atomic_commit(struct drm_device *dev, struct drm_atomic_state *state, { struct exynos_drm_private *priv = dev->dev_private; struct exynos_atomic_commit *commit; + struct drm_crtc *crtc; + struct drm_crtc_state *crtc_state; int i, ret; commit = kzalloc(sizeof(*commit), GFP_KERNEL); @@ -288,10 +290,8 @@ int exynos_atomic_commit(struct drm_device *dev, struct drm_atomic_state *state, /* Wait until all affected CRTCs have completed previous commits and * mark them as pending. */ - for (i = 0; i < dev->mode_config.num_crtc; ++i) { - if (state->crtcs[i]) - commit->crtcs |= 1 << drm_crtc_index(state->crtcs[i]); - } + for_each_crtc_in_state(state, crtc, crtc_state, i) + commit->crtcs |= 1 << drm_crtc_index(crtc); wait_event(priv->wait, !commit_is_pending(priv, commit->crtcs)); -- 2.8.1
[PATCH 08/26] drm: Consolidate connector arrays in drm_atomic_state
It's kinda pointless to have 2 separate mallocs for these. And when we add more per-connector state in the future it's even more pointless. Right now there's no such thing planned, but both Gustavo's per-crtc fence patches, and some nonblocking commit helpers I'm playing around with will add more per-crtc stuff. It makes sense to also consolidate connectors, just for consistency. In the future we can use this to store a pointer to the preceeding state, making an atomic update entirely free-standing. This will be needed to be able to queue them up with a depth > 1. Cc: Gustavo Padovan Signed-off-by: Daniel Vetter --- drivers/gpu/drm/drm_atomic.c| 27 +-- drivers/gpu/drm/drm_atomic_helper.c | 2 +- include/drm/drm_atomic.h| 10 +- include/drm/drm_crtc.h | 11 +++ 4 files changed, 22 insertions(+), 28 deletions(-) diff --git a/drivers/gpu/drm/drm_atomic.c b/drivers/gpu/drm/drm_atomic.c index 3ff1ed7b33db..a6395e9654af 100644 --- a/drivers/gpu/drm/drm_atomic.c +++ b/drivers/gpu/drm/drm_atomic.c @@ -44,7 +44,6 @@ void drm_atomic_state_default_release(struct drm_atomic_state *state) { kfree(state->connectors); - kfree(state->connector_states); kfree(state->crtcs); kfree(state->crtc_states); kfree(state->planes); @@ -139,15 +138,15 @@ void drm_atomic_state_default_clear(struct drm_atomic_state *state) DRM_DEBUG_ATOMIC("Clearing atomic state %p\n", state); for (i = 0; i < state->num_connector; i++) { - struct drm_connector *connector = state->connectors[i]; + struct drm_connector *connector = state->connectors[i].ptr; if (!connector) continue; connector->funcs->atomic_destroy_state(connector, - state->connector_states[i]); - state->connectors[i] = NULL; - state->connector_states[i] = NULL; + state->connectors[i].state); + state->connectors[i].ptr = NULL; + state->connectors[i].state = NULL; drm_connector_unreference(connector); } @@ -896,8 +895,7 @@ drm_atomic_get_connector_state(struct drm_atomic_state *state, index = drm_connector_index(connector); if (index >= state->num_connector) { - struct drm_connector **c; - struct drm_connector_state **cs; + struct __drm_connnectors_state *c; int alloc = max(index + 1, config->num_connector); c = krealloc(state->connectors, alloc * sizeof(*state->connectors), GFP_KERNEL); @@ -908,26 +906,19 @@ drm_atomic_get_connector_state(struct drm_atomic_state *state, memset(&state->connectors[state->num_connector], 0, sizeof(*state->connectors) * (alloc - state->num_connector)); - cs = krealloc(state->connector_states, alloc * sizeof(*state->connector_states), GFP_KERNEL); - if (!cs) - return ERR_PTR(-ENOMEM); - - state->connector_states = cs; - memset(&state->connector_states[state->num_connector], 0, - sizeof(*state->connector_states) * (alloc - state->num_connector)); state->num_connector = alloc; } - if (state->connector_states[index]) - return state->connector_states[index]; + if (state->connectors[index].state) + return state->connectors[index].state; connector_state = connector->funcs->atomic_duplicate_state(connector); if (!connector_state) return ERR_PTR(-ENOMEM); drm_connector_reference(connector); - state->connector_states[index] = connector_state; - state->connectors[index] = connector; + state->connectors[index].state = connector_state; + state->connectors[index].ptr = connector; connector_state->state = state; DRM_DEBUG_ATOMIC("Added [CONNECTOR:%d] %p state to %p\n", diff --git a/drivers/gpu/drm/drm_atomic_helper.c b/drivers/gpu/drm/drm_atomic_helper.c index 464541c87c40..0fb4868fdad6 100644 --- a/drivers/gpu/drm/drm_atomic_helper.c +++ b/drivers/gpu/drm/drm_atomic_helper.c @@ -1567,7 +1567,7 @@ void drm_atomic_helper_swap_state(struct drm_device *dev, for_each_connector_in_state(state, connector, conn_state, i) { connector->state->state = state; - swap(state->connector_states[i], connector->state); + swap(state->connectors[i].state, connector->state); connector->state->state = NULL; } diff --git a/include/drm/drm_atomic.h b/include/drm/drm_atomic.h index 4e97186293be..37478adb6a16 100644 --- a/include/drm/drm_atomic.h +++ b/include/drm/drm_atomic.h @@ -106,7 +106,7 @@ drm_atomic_get_existing_connector_state(
[PATCH 09/26] drm: Consolidate plane arrays in drm_atomic_state
It's kinda pointless to have 2 separate mallocs for these. And when we add more per-plane state in the future it's even more pointless. Right now there's no such thing planned, but both Gustavo's per-crtc fence patches, and some nonblocking commit helpers I'm playing around with will add more per-crtc stuff. It makes sense to also consolidate planes, just for consistency. In the future we can use this to store a pointer to the preceeding state, making an atomic update entirely free-standing. This will be needed to be able to queue them up with a depth > 1. Cc: Gustavo Padovan Signed-off-by: Daniel Vetter --- drivers/gpu/drm/drm_atomic.c| 17 ++--- drivers/gpu/drm/drm_atomic_helper.c | 2 +- drivers/gpu/drm/i915/intel_atomic.c | 2 +- include/drm/drm_atomic.h| 14 +++--- include/drm/drm_crtc.h | 11 +++ 5 files changed, 22 insertions(+), 24 deletions(-) diff --git a/drivers/gpu/drm/drm_atomic.c b/drivers/gpu/drm/drm_atomic.c index a6395e9654af..68fd99d2fd01 100644 --- a/drivers/gpu/drm/drm_atomic.c +++ b/drivers/gpu/drm/drm_atomic.c @@ -47,7 +47,6 @@ void drm_atomic_state_default_release(struct drm_atomic_state *state) kfree(state->crtcs); kfree(state->crtc_states); kfree(state->planes); - kfree(state->plane_states); } EXPORT_SYMBOL(drm_atomic_state_default_release); @@ -79,10 +78,6 @@ drm_atomic_state_init(struct drm_device *dev, struct drm_atomic_state *state) sizeof(*state->planes), GFP_KERNEL); if (!state->planes) goto fail; - state->plane_states = kcalloc(dev->mode_config.num_total_plane, - sizeof(*state->plane_states), GFP_KERNEL); - if (!state->plane_states) - goto fail; state->dev = dev; @@ -163,15 +158,15 @@ void drm_atomic_state_default_clear(struct drm_atomic_state *state) } for (i = 0; i < config->num_total_plane; i++) { - struct drm_plane *plane = state->planes[i]; + struct drm_plane *plane = state->planes[i].ptr; if (!plane) continue; plane->funcs->atomic_destroy_state(plane, - state->plane_states[i]); - state->planes[i] = NULL; - state->plane_states[i] = NULL; + state->planes[i].state); + state->planes[i].ptr = NULL; + state->planes[i].state = NULL; } } EXPORT_SYMBOL(drm_atomic_state_default_clear); @@ -630,8 +625,8 @@ drm_atomic_get_plane_state(struct drm_atomic_state *state, if (!plane_state) return ERR_PTR(-ENOMEM); - state->plane_states[index] = plane_state; - state->planes[index] = plane; + state->planes[index].state = plane_state; + state->planes[index].ptr = plane; plane_state->state = state; DRM_DEBUG_ATOMIC("Added [PLANE:%d:%s] %p state to %p\n", diff --git a/drivers/gpu/drm/drm_atomic_helper.c b/drivers/gpu/drm/drm_atomic_helper.c index 0fb4868fdad6..f70d576f745e 100644 --- a/drivers/gpu/drm/drm_atomic_helper.c +++ b/drivers/gpu/drm/drm_atomic_helper.c @@ -1579,7 +1579,7 @@ void drm_atomic_helper_swap_state(struct drm_device *dev, for_each_plane_in_state(state, plane, plane_state, i) { plane->state->state = state; - swap(state->plane_states[i], plane->state); + swap(state->planes[i].state, plane->state); plane->state->state = NULL; } } diff --git a/drivers/gpu/drm/i915/intel_atomic.c b/drivers/gpu/drm/i915/intel_atomic.c index 3e6d9ff8840a..7542f5f5db1d 100644 --- a/drivers/gpu/drm/i915/intel_atomic.c +++ b/drivers/gpu/drm/i915/intel_atomic.c @@ -191,7 +191,7 @@ int intel_atomic_setup_scalers(struct drm_device *dev, /* plane scaler case: assign as a plane scaler */ /* find the plane that set the bit as scaler_user */ - plane = drm_state->planes[i]; + plane = drm_state->planes[i].ptr; /* * to enable/disable hq mode, add planes that are using scaler diff --git a/include/drm/drm_atomic.h b/include/drm/drm_atomic.h index 37478adb6a16..8e616d39353b 100644 --- a/include/drm/drm_atomic.h +++ b/include/drm/drm_atomic.h @@ -86,7 +86,7 @@ static inline struct drm_plane_state * drm_atomic_get_existing_plane_state(struct drm_atomic_state *state, struct drm_plane *plane) { - return state->plane_states[drm_plane_index(plane)]; + return state->planes[drm_plane_index(plane)].state; } /** @@ -139,8 +139,8 @@ static inline const struct drm_plane_state * __drm_atomic_get_current_plane_state(struct drm_atomic_state *state, struct drm_pla
[PATCH 10/26] drm: Consolidate crtc arrays in drm_atomic_state
It's silly to have 2 mallocs when we could tie these two together. Also, Gustavo adds another one in his per-crtc out-fence patches. And I want to add more stuff here for nonblocking commit helpers. In the future we can use this to store a pointer to the preceeding state, making an atomic update entirely free-standing. This will be needed to be able to queue them up with a depth > 1. Cc: Gustavo Padovan Signed-off-by: Daniel Vetter --- drivers/gpu/drm/drm_atomic.c| 17 ++--- drivers/gpu/drm/drm_atomic_helper.c | 2 +- include/drm/drm_atomic.h| 10 +- include/drm/drm_crtc.h | 8 ++-- 4 files changed, 18 insertions(+), 19 deletions(-) diff --git a/drivers/gpu/drm/drm_atomic.c b/drivers/gpu/drm/drm_atomic.c index 68fd99d2fd01..674b2e490aa9 100644 --- a/drivers/gpu/drm/drm_atomic.c +++ b/drivers/gpu/drm/drm_atomic.c @@ -45,7 +45,6 @@ void drm_atomic_state_default_release(struct drm_atomic_state *state) { kfree(state->connectors); kfree(state->crtcs); - kfree(state->crtc_states); kfree(state->planes); } EXPORT_SYMBOL(drm_atomic_state_default_release); @@ -70,10 +69,6 @@ drm_atomic_state_init(struct drm_device *dev, struct drm_atomic_state *state) sizeof(*state->crtcs), GFP_KERNEL); if (!state->crtcs) goto fail; - state->crtc_states = kcalloc(dev->mode_config.num_crtc, -sizeof(*state->crtc_states), GFP_KERNEL); - if (!state->crtc_states) - goto fail; state->planes = kcalloc(dev->mode_config.num_total_plane, sizeof(*state->planes), GFP_KERNEL); if (!state->planes) @@ -146,15 +141,15 @@ void drm_atomic_state_default_clear(struct drm_atomic_state *state) } for (i = 0; i < config->num_crtc; i++) { - struct drm_crtc *crtc = state->crtcs[i]; + struct drm_crtc *crtc = state->crtcs[i].ptr; if (!crtc) continue; crtc->funcs->atomic_destroy_state(crtc, - state->crtc_states[i]); - state->crtcs[i] = NULL; - state->crtc_states[i] = NULL; + state->crtcs[i].state); + state->crtcs[i].ptr = NULL; + state->crtcs[i].state = NULL; } for (i = 0; i < config->num_total_plane; i++) { @@ -264,8 +259,8 @@ drm_atomic_get_crtc_state(struct drm_atomic_state *state, if (!crtc_state) return ERR_PTR(-ENOMEM); - state->crtc_states[index] = crtc_state; - state->crtcs[index] = crtc; + state->crtcs[index].state = crtc_state; + state->crtcs[index].ptr = crtc; crtc_state->state = state; DRM_DEBUG_ATOMIC("Added [CRTC:%d:%s] %p state to %p\n", diff --git a/drivers/gpu/drm/drm_atomic_helper.c b/drivers/gpu/drm/drm_atomic_helper.c index f70d576f745e..5298eb668ca7 100644 --- a/drivers/gpu/drm/drm_atomic_helper.c +++ b/drivers/gpu/drm/drm_atomic_helper.c @@ -1573,7 +1573,7 @@ void drm_atomic_helper_swap_state(struct drm_device *dev, for_each_crtc_in_state(state, crtc, crtc_state, i) { crtc->state->state = state; - swap(state->crtc_states[i], crtc->state); + swap(state->crtcs[i].state, crtc->state); crtc->state->state = NULL; } diff --git a/include/drm/drm_atomic.h b/include/drm/drm_atomic.h index 8e616d39353b..d9504dfcd1cc 100644 --- a/include/drm/drm_atomic.h +++ b/include/drm/drm_atomic.h @@ -71,7 +71,7 @@ static inline struct drm_crtc_state * drm_atomic_get_existing_crtc_state(struct drm_atomic_state *state, struct drm_crtc *crtc) { - return state->crtc_states[drm_crtc_index(crtc)]; + return state->crtcs[drm_crtc_index(crtc)].state; } /** @@ -183,11 +183,11 @@ int __must_check drm_atomic_nonblocking_commit(struct drm_atomic_state *state); (__i)++) \ for_each_if (connector) -#define for_each_crtc_in_state(state, crtc, crtc_state, __i) \ +#define for_each_crtc_in_state(__state, crtc, crtc_state, __i) \ for ((__i) = 0; \ -(__i) < (state)->dev->mode_config.num_crtc && \ -((crtc) = (state)->crtcs[__i], \ -(crtc_state) = (state)->crtc_states[__i], 1); \ +(__i) < (__state)->dev->mode_config.num_crtc &&\ +((crtc) = (__state)->crtcs[__i].ptr, \ +(crtc_state) = (__state)->crtcs[__i].state, 1);\ (__i)++) \ for_each_if (crtc_state) diff --git a/include/drm/drm_crtc.h b/include/drm/drm_crtc.h index c7c2b3fa7179..d5d
[PATCH 11/26] drm/fence: add fence to drm_pending_event
From: Gustavo Padovan Now a drm_pending_event can either send a real drm_event or signal a fence, or both. It allow us to signal via fences when the buffer is displayed on the screen. Which in turn means that the previous buffer is not in use anymore and can be freed or sent back to another driver for processing. v2: Comments from Daniel Vetter - call fence_signal in drm_send_event_locked() - remove unneeded !e->event check v3: Remove drm_pending_event->destroy to fix a leak when e->file_priv is not set. Signed-off-by: Gustavo Padovan (v2) Signed-off-by: Daniel Vetter --- drivers/gpu/drm/drm_atomic.c| 19 +-- drivers/gpu/drm/drm_fops.c | 16 +--- drivers/gpu/drm/nouveau/nouveau_usif.c | 1 - drivers/gpu/drm/rockchip/rockchip_drm_vop.c | 2 +- include/drm/drmP.h | 3 ++- 5 files changed, 25 insertions(+), 16 deletions(-) diff --git a/drivers/gpu/drm/drm_atomic.c b/drivers/gpu/drm/drm_atomic.c index 674b2e490aa9..1db198df3014 100644 --- a/drivers/gpu/drm/drm_atomic.c +++ b/drivers/gpu/drm/drm_atomic.c @@ -1412,7 +1412,8 @@ EXPORT_SYMBOL(drm_atomic_nonblocking_commit); */ static struct drm_pending_vblank_event *create_vblank_event( - struct drm_device *dev, struct drm_file *file_priv, uint64_t user_data) + struct drm_device *dev, struct drm_file *file_priv, + struct fence *fence, uint64_t user_data) { struct drm_pending_vblank_event *e = NULL; int ret; @@ -1425,12 +1426,17 @@ static struct drm_pending_vblank_event *create_vblank_event( e->event.base.length = sizeof(e->event); e->event.user_data = user_data; - ret = drm_event_reserve_init(dev, file_priv, &e->base, &e->event.base); - if (ret) { - kfree(e); - return NULL; + if (file_priv) { + ret = drm_event_reserve_init(dev, file_priv, &e->base, +&e->event.base); + if (ret) { + kfree(e); + return NULL; + } } + e->base.fence = fence; + return e; } @@ -1670,7 +1676,8 @@ retry: for_each_crtc_in_state(state, crtc, crtc_state, i) { struct drm_pending_vblank_event *e; - e = create_vblank_event(dev, file_priv, arg->user_data); + e = create_vblank_event(dev, file_priv, NULL, + arg->user_data); if (!e) { ret = -ENOMEM; goto out; diff --git a/drivers/gpu/drm/drm_fops.c b/drivers/gpu/drm/drm_fops.c index 868871068956..4c4b30f7a9f2 100644 --- a/drivers/gpu/drm/drm_fops.c +++ b/drivers/gpu/drm/drm_fops.c @@ -294,7 +294,7 @@ static void drm_events_release(struct drm_file *file_priv) /* Remove unconsumed events */ list_for_each_entry_safe(e, et, &file_priv->event_list, link) { list_del(&e->link); - e->destroy(e); + kfree(e); } spin_unlock_irqrestore(&dev->event_lock, flags); @@ -525,7 +525,7 @@ put_back_event: } ret += length; - e->destroy(e); + kfree(e); } } mutex_unlock(&file_priv->event_read_lock); @@ -602,9 +602,6 @@ int drm_event_reserve_init_locked(struct drm_device *dev, list_add(&p->pending_link, &file_priv->pending_event_list); p->file_priv = file_priv; - /* we *could* pass this in as arg, but everyone uses kfree: */ - p->destroy = (void (*) (struct drm_pending_event *)) kfree; - return 0; } EXPORT_SYMBOL(drm_event_reserve_init_locked); @@ -667,7 +664,7 @@ void drm_event_cancel_free(struct drm_device *dev, list_del(&p->pending_link); } spin_unlock_irqrestore(&dev->event_lock, flags); - p->destroy(p); + kfree(p); } EXPORT_SYMBOL(drm_event_cancel_free); @@ -689,8 +686,13 @@ void drm_send_event_locked(struct drm_device *dev, struct drm_pending_event *e) { assert_spin_locked(&dev->event_lock); + if (e->fence) { + fence_signal(e->fence); + fence_put(e->fence); + } + if (!e->file_priv) { - e->destroy(e); + kfree(e); return; } diff --git a/drivers/gpu/drm/nouveau/nouveau_usif.c b/drivers/gpu/drm/nouveau/nouveau_usif.c index 675e9e077a95..08f9c6fa0f7f 100644 --- a/drivers/gpu/drm/nouveau/nouveau_usif.c +++ b/drivers/gpu/drm/nouveau/nouveau_usif.c @@ -212,7 +212,6 @@ usif_notify_get(struct drm_file *f, void *data, u32 size, void *argv, u32 argc) ntfy->p->base.event = &ntfy->p->e.base; ntfy->p->base.file_priv = f; ntfy->p->base.pid = current->pid; -
[PATCH 13/26] drm/arc: Nuke event_list
This is just used for cleanup in preclose, and with the reworked event handling code this is now done properly by the core. Nuke it! But it also shows that arc totally fails at sending out drm events for flips. Next patch will hack that up. Cc: Carlos Palminha Cc: Alexey Brodkin Cc: linux-snps-arc at lists.infradead.org Signed-off-by: Daniel Vetter --- drivers/gpu/drm/arc/arcpgu.h | 1 - drivers/gpu/drm/arc/arcpgu_crtc.c | 4 drivers/gpu/drm/arc/arcpgu_drv.c | 19 --- 3 files changed, 24 deletions(-) diff --git a/drivers/gpu/drm/arc/arcpgu.h b/drivers/gpu/drm/arc/arcpgu.h index 86574b698a78..8c01a25d279a 100644 --- a/drivers/gpu/drm/arc/arcpgu.h +++ b/drivers/gpu/drm/arc/arcpgu.h @@ -22,7 +22,6 @@ struct arcpgu_drm_private { struct clk *clk; struct drm_fbdev_cma*fbdev; struct drm_framebuffer *fb; - struct list_headevent_list; struct drm_crtc crtc; struct drm_plane*plane; }; diff --git a/drivers/gpu/drm/arc/arcpgu_crtc.c b/drivers/gpu/drm/arc/arcpgu_crtc.c index 92f8beff8e60..d5ca0c280e68 100644 --- a/drivers/gpu/drm/arc/arcpgu_crtc.c +++ b/drivers/gpu/drm/arc/arcpgu_crtc.c @@ -155,10 +155,6 @@ static void arc_pgu_crtc_atomic_begin(struct drm_crtc *crtc, event->pipe = drm_crtc_index(crtc); WARN_ON(drm_crtc_vblank_get(crtc) != 0); - - spin_lock_irqsave(&crtc->dev->event_lock, flags); - list_add_tail(&event->base.link, &arcpgu->event_list); - spin_unlock_irqrestore(&crtc->dev->event_lock, flags); } } diff --git a/drivers/gpu/drm/arc/arcpgu_drv.c b/drivers/gpu/drm/arc/arcpgu_drv.c index bc53ebb83f75..d407fd79a400 100644 --- a/drivers/gpu/drm/arc/arcpgu_drv.c +++ b/drivers/gpu/drm/arc/arcpgu_drv.c @@ -81,22 +81,6 @@ static const struct file_operations arcpgu_drm_ops = { .mmap = arcpgu_gem_mmap, }; -static void arcpgu_preclose(struct drm_device *drm, struct drm_file *file) -{ - struct arcpgu_drm_private *arcpgu = drm->dev_private; - struct drm_pending_vblank_event *e, *t; - unsigned long flags; - - spin_lock_irqsave(&drm->event_lock, flags); - list_for_each_entry_safe(e, t, &arcpgu->event_list, base.link) { - if (e->base.file_priv != file) - continue; - list_del(&e->base.link); - e->base.destroy(&e->base); - } - spin_unlock_irqrestore(&drm->event_lock, flags); -} - static void arcpgu_lastclose(struct drm_device *drm) { struct arcpgu_drm_private *arcpgu = drm->dev_private; @@ -122,8 +106,6 @@ static int arcpgu_load(struct drm_device *drm) if (IS_ERR(arcpgu->clk)) return PTR_ERR(arcpgu->clk); - INIT_LIST_HEAD(&arcpgu->event_list); - arcpgu_setup_mode_config(drm); res = platform_get_resource(pdev, IORESOURCE_MEM, 0); @@ -192,7 +174,6 @@ int arcpgu_unload(struct drm_device *drm) static struct drm_driver arcpgu_drm_driver = { .driver_features = DRIVER_MODESET | DRIVER_GEM | DRIVER_PRIME | DRIVER_ATOMIC, - .preclose = arcpgu_preclose, .lastclose = arcpgu_lastclose, .name = "drm-arcpgu", .desc = "ARC PGU Controller", -- 2.8.1
[PATCH 12/26] drm/atomic-helper: Massage swap_state signature somewhat
- dev is redundant, we have state->atomic - add stall parameter, which must be set when swapping needs to stall for preceeding commits to stop looking at ->state pointers. Currently all drivers need this to be, just prep work for a glorious future. Signed-off-by: Daniel Vetter --- drivers/gpu/drm/atmel-hlcdc/atmel_hlcdc_dc.c | 2 +- drivers/gpu/drm/drm_atomic_helper.c | 8 drivers/gpu/drm/exynos/exynos_drm_drv.c | 2 +- drivers/gpu/drm/i915/intel_display.c | 2 +- drivers/gpu/drm/mediatek/mtk_drm_drv.c | 2 +- drivers/gpu/drm/msm/msm_atomic.c | 2 +- drivers/gpu/drm/omapdrm/omap_drv.c | 2 +- drivers/gpu/drm/rcar-du/rcar_du_kms.c| 2 +- drivers/gpu/drm/rockchip/rockchip_drm_fb.c | 2 +- drivers/gpu/drm/sti/sti_drv.c| 2 +- drivers/gpu/drm/tegra/drm.c | 2 +- drivers/gpu/drm/vc4/vc4_kms.c| 2 +- include/drm/drm_atomic_helper.h | 4 ++-- 13 files changed, 17 insertions(+), 17 deletions(-) diff --git a/drivers/gpu/drm/atmel-hlcdc/atmel_hlcdc_dc.c b/drivers/gpu/drm/atmel-hlcdc/atmel_hlcdc_dc.c index 6485fa5bee8b..9ecf16c7911d 100644 --- a/drivers/gpu/drm/atmel-hlcdc/atmel_hlcdc_dc.c +++ b/drivers/gpu/drm/atmel-hlcdc/atmel_hlcdc_dc.c @@ -519,7 +519,7 @@ static int atmel_hlcdc_dc_atomic_commit(struct drm_device *dev, } /* Swap the state, this is the point of no return. */ - drm_atomic_helper_swap_state(dev, state); + drm_atomic_helper_swap_state(state, true); if (async) queue_work(dc->wq, &commit->work); diff --git a/drivers/gpu/drm/drm_atomic_helper.c b/drivers/gpu/drm/drm_atomic_helper.c index 5298eb668ca7..fecbb52cbb85 100644 --- a/drivers/gpu/drm/drm_atomic_helper.c +++ b/drivers/gpu/drm/drm_atomic_helper.c @@ -1160,7 +1160,7 @@ int drm_atomic_helper_commit(struct drm_device *dev, * the software side now. */ - drm_atomic_helper_swap_state(dev, state); + drm_atomic_helper_swap_state(state, true); /* * Everything below can be run asynchronously without the need to grab @@ -1531,8 +1531,8 @@ EXPORT_SYMBOL(drm_atomic_helper_cleanup_planes); /** * drm_atomic_helper_swap_state - store atomic state into current sw state - * @dev: DRM device * @state: atomic state + * @stall: stall for proceeding commits * * This function stores the atomic state into the current state pointers in all * driver objects. It should be called after all failing steps have been done @@ -1554,8 +1554,8 @@ EXPORT_SYMBOL(drm_atomic_helper_cleanup_planes); * 5. Call drm_atomic_helper_cleanup_planes() with @state, which since step 3 * contains the old state. Also do any other cleanup required with that state. */ -void drm_atomic_helper_swap_state(struct drm_device *dev, - struct drm_atomic_state *state) +void drm_atomic_helper_swap_state(struct drm_atomic_state *state, + bool stall) { int i; struct drm_connector *connector; diff --git a/drivers/gpu/drm/exynos/exynos_drm_drv.c b/drivers/gpu/drm/exynos/exynos_drm_drv.c index cabc5fd0246d..deba76982358 100644 --- a/drivers/gpu/drm/exynos/exynos_drm_drv.c +++ b/drivers/gpu/drm/exynos/exynos_drm_drv.c @@ -299,7 +299,7 @@ int exynos_atomic_commit(struct drm_device *dev, struct drm_atomic_state *state, priv->pending |= commit->crtcs; spin_unlock(&priv->lock); - drm_atomic_helper_swap_state(dev, state); + drm_atomic_helper_swap_state(state, true); if (nonblock) schedule_work(&commit->work); diff --git a/drivers/gpu/drm/i915/intel_display.c b/drivers/gpu/drm/i915/intel_display.c index 9ccd76699f48..d32274071393 100644 --- a/drivers/gpu/drm/i915/intel_display.c +++ b/drivers/gpu/drm/i915/intel_display.c @@ -13660,7 +13660,7 @@ static int intel_atomic_commit(struct drm_device *dev, return ret; } - drm_atomic_helper_swap_state(dev, state); + drm_atomic_helper_swap_state(state, true); dev_priv->wm.distrust_bios_wm = false; dev_priv->wm.skl_results = intel_state->wm_results; intel_shared_dpll_commit(state); diff --git a/drivers/gpu/drm/mediatek/mtk_drm_drv.c b/drivers/gpu/drm/mediatek/mtk_drm_drv.c index 06a417b2f91e..c33bf98c5d5e 100644 --- a/drivers/gpu/drm/mediatek/mtk_drm_drv.c +++ b/drivers/gpu/drm/mediatek/mtk_drm_drv.c @@ -91,7 +91,7 @@ static int mtk_atomic_commit(struct drm_device *drm, mutex_lock(&private->commit.lock); flush_work(&private->commit.work); - drm_atomic_helper_swap_state(drm, state); + drm_atomic_helper_swap_state(state, true); if (async) mtk_atomic_schedule(private, state); diff --git a/drivers/gpu/drm/msm/msm_atomic.c b/drivers/gpu/drm/msm/msm_atomic.c index 9c0e4261dbba..d02bd6a50e90 100644 --- a/drivers/gpu/drm/msm/msm_atomic.c +++ b/drivers/gpu/drm/msm/msm_atomic.c @@ -238
[PATCH 14/26] drm/arc: Actually bother with handling atomic events.
The drm core has a nice ready-made helper for exactly the simple case where it should fire on the next vblank. Note that arming the vblank event in _begin is probably too early, and might easily result in the vblank firing too early, before the new set of planes are actually disabled. But that's kinda a minor issue compared to just outright hanging userspace. v2: Be more robust and either arm, when the CRTC is on, or just send the event out right away. Cc: Carlos Palminha Cc: Alexey Brodkin Cc: linux-snps-arc at lists.infradead.org Signed-off-by: Daniel Vetter --- drivers/gpu/drm/arc/arcpgu_crtc.c | 15 --- 1 file changed, 8 insertions(+), 7 deletions(-) diff --git a/drivers/gpu/drm/arc/arcpgu_crtc.c b/drivers/gpu/drm/arc/arcpgu_crtc.c index d5ca0c280e68..c9f183b11df9 100644 --- a/drivers/gpu/drm/arc/arcpgu_crtc.c +++ b/drivers/gpu/drm/arc/arcpgu_crtc.c @@ -145,16 +145,17 @@ static int arc_pgu_crtc_atomic_check(struct drm_crtc *crtc, static void arc_pgu_crtc_atomic_begin(struct drm_crtc *crtc, struct drm_crtc_state *state) { - struct arcpgu_drm_private *arcpgu = crtc_to_arcpgu_priv(crtc); - unsigned long flags; - - if (crtc->state->event) { - struct drm_pending_vblank_event *event = crtc->state->event; + struct drm_pending_vblank_event *event = crtc->state->event; + if (event) { crtc->state->event = NULL; - event->pipe = drm_crtc_index(crtc); - WARN_ON(drm_crtc_vblank_get(crtc) != 0); + spin_lock_irq(&crtc->dev->event_lock); + if (drm_crtc_vblank_get(crtc) == 0) + drm_crtc_arm_vblank_event(crtc, event); + else + drm_crtc_send_vblank_event(crtc, event); + spin_unlock_irq(&crtc->dev->event_lock); } } -- 2.8.1
[PATCH 17/26] drm/fsl-du: Implement some semblance of vblank event handling
No idea how exactly fsl-du commits hw state changes, but here in flush is probably the safest place. While at it nuke the dummy functions. v2: Be more robust and either arm, when the CRTC is on, or just send the event out right away. Cc: Stefan Agner Signed-off-by: Daniel Vetter --- drivers/gpu/drm/fsl-dcu/fsl_dcu_drm_crtc.c | 23 +++ 1 file changed, 11 insertions(+), 12 deletions(-) diff --git a/drivers/gpu/drm/fsl-dcu/fsl_dcu_drm_crtc.c b/drivers/gpu/drm/fsl-dcu/fsl_dcu_drm_crtc.c index 89c0084c2814..706de3278f1c 100644 --- a/drivers/gpu/drm/fsl-dcu/fsl_dcu_drm_crtc.c +++ b/drivers/gpu/drm/fsl-dcu/fsl_dcu_drm_crtc.c @@ -22,20 +22,21 @@ #include "fsl_dcu_drm_drv.h" #include "fsl_dcu_drm_plane.h" -static void fsl_dcu_drm_crtc_atomic_begin(struct drm_crtc *crtc, +static void fsl_dcu_drm_crtc_atomic_flush(struct drm_crtc *crtc, struct drm_crtc_state *old_crtc_state) { -} + struct drm_pending_vblank_event *event = crtc->state->event; -static int fsl_dcu_drm_crtc_atomic_check(struct drm_crtc *crtc, -struct drm_crtc_state *state) -{ - return 0; -} + if (event) { + crtc->state->event = NULL; -static void fsl_dcu_drm_crtc_atomic_flush(struct drm_crtc *crtc, - struct drm_crtc_state *old_crtc_state) -{ + spin_lock_irq(&crtc->dev->event_lock); + if (drm_crtc_vblank_get(crtc) == 0) + drm_crtc_arm_vblank_event(crtc, event); + else + drm_crtc_send_vblank_event(crtc, event); + spin_unlock_irq(&crtc->dev->event_lock); + } } static void fsl_dcu_drm_disable_crtc(struct drm_crtc *crtc) @@ -117,8 +118,6 @@ static void fsl_dcu_drm_crtc_mode_set_nofb(struct drm_crtc *crtc) } static const struct drm_crtc_helper_funcs fsl_dcu_drm_crtc_helper_funcs = { - .atomic_begin = fsl_dcu_drm_crtc_atomic_begin, - .atomic_check = fsl_dcu_drm_crtc_atomic_check, .atomic_flush = fsl_dcu_drm_crtc_atomic_flush, .disable = fsl_dcu_drm_disable_crtc, .enable = fsl_dcu_drm_crtc_enable, -- 2.8.1
[PATCH 15/26] drm/arc: Implement nonblocking commit correctly
Committing with block it is not. Thanks to the fixed up vblank event handling we can just use the helper support for nonblocking commits now. Cc: Carlos Palminha Cc: Alexey Brodkin Cc: linux-snps-arc at lists.infradead.org Signed-off-by: Daniel Vetter --- drivers/gpu/drm/arc/arcpgu_drv.c | 8 +--- 1 file changed, 1 insertion(+), 7 deletions(-) diff --git a/drivers/gpu/drm/arc/arcpgu_drv.c b/drivers/gpu/drm/arc/arcpgu_drv.c index d407fd79a400..a92e533531c3 100644 --- a/drivers/gpu/drm/arc/arcpgu_drv.c +++ b/drivers/gpu/drm/arc/arcpgu_drv.c @@ -32,17 +32,11 @@ static void arcpgu_fb_output_poll_changed(struct drm_device *dev) drm_fbdev_cma_hotplug_event(arcpgu->fbdev); } -static int arcpgu_atomic_commit(struct drm_device *dev, - struct drm_atomic_state *state, bool async) -{ - return drm_atomic_helper_commit(dev, state, false); -} - static struct drm_mode_config_funcs arcpgu_drm_modecfg_funcs = { .fb_create = drm_fb_cma_create, .output_poll_changed = arcpgu_fb_output_poll_changed, .atomic_check = drm_atomic_helper_check, - .atomic_commit = arcpgu_atomic_commit, + .atomic_commit = drm_atomic_helper_commit, }; static void arcpgu_setup_mode_config(struct drm_device *drm) -- 2.8.1
[PATCH 16/26] drm/hdlcd: Use helper support for nonblocking commits
Again, just doing them as blocking commits isn't cool. >From a cursory check hdlcd does seem to at least try to handle drm_pending_vblank_event, so hopefully this works. Cc: Liviu Dudau Signed-off-by: Daniel Vetter --- drivers/gpu/drm/arm/hdlcd_drv.c | 8 +--- 1 file changed, 1 insertion(+), 7 deletions(-) diff --git a/drivers/gpu/drm/arm/hdlcd_drv.c b/drivers/gpu/drm/arm/hdlcd_drv.c index 4f909378d581..6d1877238cf0 100644 --- a/drivers/gpu/drm/arm/hdlcd_drv.c +++ b/drivers/gpu/drm/arm/hdlcd_drv.c @@ -112,17 +112,11 @@ static void hdlcd_fb_output_poll_changed(struct drm_device *drm) drm_fbdev_cma_hotplug_event(hdlcd->fbdev); } -static int hdlcd_atomic_commit(struct drm_device *dev, - struct drm_atomic_state *state, bool nonblock) -{ - return drm_atomic_helper_commit(dev, state, false); -} - static const struct drm_mode_config_funcs hdlcd_mode_config_funcs = { .fb_create = drm_fb_cma_create, .output_poll_changed = hdlcd_fb_output_poll_changed, .atomic_check = drm_atomic_helper_check, - .atomic_commit = hdlcd_atomic_commit, + .atomic_commit = drm_atomic_helper_commit, }; static void hdlcd_setup_mode_config(struct drm_device *drm) -- 2.8.1
[PATCH 18/26] drm/hisilicon: Implement some semblance of vblank event handling
atomic_flush seems to be the right place, but I'm not entirely sure whether this will catch them all. It could be that when disabling the crtc we'll miss the vblank. While at it nuke the dummy functions. v2: Be more robust and either arm, when the CRTC is on, or just send the event out right away. Cc: Xinliang Liu Cc: Xinwei Kong Cc: Archit Taneja Signed-off-by: Daniel Vetter --- drivers/gpu/drm/hisilicon/kirin/kirin_drm_ade.c | 20 1 file changed, 12 insertions(+), 8 deletions(-) diff --git a/drivers/gpu/drm/hisilicon/kirin/kirin_drm_ade.c b/drivers/gpu/drm/hisilicon/kirin/kirin_drm_ade.c index fba6372d060e..ed76baad525f 100644 --- a/drivers/gpu/drm/hisilicon/kirin/kirin_drm_ade.c +++ b/drivers/gpu/drm/hisilicon/kirin/kirin_drm_ade.c @@ -502,13 +502,6 @@ static void ade_crtc_disable(struct drm_crtc *crtc) acrtc->enable = false; } -static int ade_crtc_atomic_check(struct drm_crtc *crtc, -struct drm_crtc_state *state) -{ - /* do nothing */ - return 0; -} - static void ade_crtc_mode_set_nofb(struct drm_crtc *crtc) { struct ade_crtc *acrtc = to_ade_crtc(crtc); @@ -537,6 +530,7 @@ static void ade_crtc_atomic_flush(struct drm_crtc *crtc, { struct ade_crtc *acrtc = to_ade_crtc(crtc); struct ade_hw_ctx *ctx = acrtc->ctx; + struct drm_pending_vblank_event *event = crtc->state->event; void __iomem *base = ctx->base; /* only crtc is enabled regs take effect */ @@ -545,12 +539,22 @@ static void ade_crtc_atomic_flush(struct drm_crtc *crtc, /* flush ade registers */ writel(ADE_ENABLE, base + ADE_EN); } + + if (event) { + crtc->state->event = NULL; + + spin_lock_irq(&crtc->dev->event_lock); + if (drm_crtc_vblank_get(crtc) == 0) + drm_crtc_arm_vblank_event(crtc, event); + else + drm_crtc_send_vblank_event(crtc, event); + spin_unlock_irq(&crtc->dev->event_lock); + } } static const struct drm_crtc_helper_funcs ade_crtc_helper_funcs = { .enable = ade_crtc_enable, .disable= ade_crtc_disable, - .atomic_check = ade_crtc_atomic_check, .mode_set_nofb = ade_crtc_mode_set_nofb, .atomic_begin = ade_crtc_atomic_begin, .atomic_flush = ade_crtc_atomic_flush, -- 2.8.1
[PATCH 19/26] drm/sun4i: Implement some semblance of vblank event handling
atomic_flush seems to be the right place, right after we commit the plane updates. Again use the fullproof version, since the pipe might be off. Cc: Boris Brezillon Cc: Maxime Ripard Signed-off-by: Daniel Vetter --- drivers/gpu/drm/sun4i/sun4i_crtc.c | 12 1 file changed, 12 insertions(+) diff --git a/drivers/gpu/drm/sun4i/sun4i_crtc.c b/drivers/gpu/drm/sun4i/sun4i_crtc.c index 4182a21f5923..f628b6d8f23f 100644 --- a/drivers/gpu/drm/sun4i/sun4i_crtc.c +++ b/drivers/gpu/drm/sun4i/sun4i_crtc.c @@ -51,10 +51,22 @@ static void sun4i_crtc_atomic_flush(struct drm_crtc *crtc, { struct sun4i_crtc *scrtc = drm_crtc_to_sun4i_crtc(crtc); struct sun4i_drv *drv = scrtc->drv; + struct drm_pending_vblank_event *event = crtc->state->event; DRM_DEBUG_DRIVER("Committing plane changes\n"); sun4i_backend_commit(drv->backend); + + if (event) { + crtc->state->event = NULL; + + spin_lock_irq(&crtc->dev->event_lock); + if (drm_crtc_vblank_get(crtc) == 0) + drm_crtc_arm_vblank_event(crtc, event); + else + drm_crtc_send_vblank_event(crtc, event); + spin_unlock_irq(&crtc->dev->event_lock); + } } static void sun4i_crtc_disable(struct drm_crtc *crtc) -- 2.8.1
[PATCH 20/26] drm/atomic: kerneldoc for drm_atomic_crtc_needs_modeset
Just a bit of drive-by ocd. Signed-off-by: Daniel Vetter --- include/drm/drm_atomic.h | 7 +++ 1 file changed, 7 insertions(+) diff --git a/include/drm/drm_atomic.h b/include/drm/drm_atomic.h index d9504dfcd1cc..465a1212f4f0 100644 --- a/include/drm/drm_atomic.h +++ b/include/drm/drm_atomic.h @@ -198,6 +198,13 @@ int __must_check drm_atomic_nonblocking_commit(struct drm_atomic_state *state); (plane_state) = (__state)->planes[__i].state, 1); \ (__i)++) \ for_each_if (plane_state) + +/** + * drm_atomic_crtc_needs_modeset - compute combined modeset need + * @state: &drm_crtc_state for the CRTC + * + * This computes the combined need for a modeset for @state. + */ static inline bool drm_atomic_crtc_needs_modeset(struct drm_crtc_state *state) { -- 2.8.1
[PATCH 22/26] drm/i915: Signal drm events for atomic
This is part of what atomic must implement. And it's also required to be able to use the helper nonblocking support. v2: Always send out the drm event, remove the planes_changed check. Signed-off-by: Daniel Vetter --- drivers/gpu/drm/i915/intel_display.c | 13 ++--- drivers/gpu/drm/i915/intel_sprite.c | 14 ++ 2 files changed, 24 insertions(+), 3 deletions(-) diff --git a/drivers/gpu/drm/i915/intel_display.c b/drivers/gpu/drm/i915/intel_display.c index d32274071393..66a254fa2a96 100644 --- a/drivers/gpu/drm/i915/intel_display.c +++ b/drivers/gpu/drm/i915/intel_display.c @@ -13731,13 +13731,21 @@ static int intel_atomic_commit(struct drm_device *dev, bool modeset = needs_modeset(crtc->state); struct intel_crtc_state *pipe_config = to_intel_crtc_state(crtc->state); - bool update_pipe = !modeset && pipe_config->update_pipe; if (modeset && crtc->state->active) { update_scanline_offset(to_intel_crtc(crtc)); dev_priv->display.crtc_enable(crtc); } + /* Complete events for now disable pipes here. */ + if (modeset && !crtc->state->active && crtc->state->event) { + spin_lock_irq(&dev->event_lock); + drm_crtc_send_vblank_event(crtc, crtc->state->event); + spin_unlock_irq(&dev->event_lock); + + crtc->state->event = NULL; + } + if (!modeset) intel_pre_plane_update(to_intel_crtc_state(old_crtc_state)); @@ -13745,8 +13753,7 @@ static int intel_atomic_commit(struct drm_device *dev, drm_atomic_get_existing_plane_state(state, crtc->primary)) intel_fbc_enable(intel_crtc); - if (crtc->state->active && - (crtc->state->planes_changed || update_pipe)) + if (crtc->state->active) drm_atomic_helper_commit_planes_on_crtc(old_crtc_state); if (pipe_config->base.active && needs_vblank_wait(pipe_config)) diff --git a/drivers/gpu/drm/i915/intel_sprite.c b/drivers/gpu/drm/i915/intel_sprite.c index 97b1a54eb09f..8864cc983ea2 100644 --- a/drivers/gpu/drm/i915/intel_sprite.c +++ b/drivers/gpu/drm/i915/intel_sprite.c @@ -166,6 +166,20 @@ void intel_pipe_update_end(struct intel_crtc *crtc, struct intel_flip_work *work trace_i915_pipe_update_end(crtc, end_vbl_count, scanline_end); + /* We're still in the vblank-evade critical section, this can't race. +* Would be slightly nice to just grab the vblank count and arm the +* event outside of the critical section - the spinlock might spin for a +* while ... */ + if (crtc->base.state->event) { + WARN_ON(drm_crtc_vblank_get(&crtc->base) != 0); + + spin_lock(&crtc->base.dev->event_lock); + drm_crtc_arm_vblank_event(&crtc->base, crtc->base.state->event); + spin_unlock(&crtc->base.dev->event_lock); + + crtc->base.state->event = NULL; + } + local_irq_enable(); if (crtc->debug.start_vbl_count && -- 2.8.1
[PATCH 21/26] drm/atomic-helper: nonblocking commit support
Design ideas: - split up the actual commit into different phases, and have completions for each of them. This will be useful for the future when we want to interleave phases much more aggressively, for e.g. queue depth > 1. For not it's just a minimal optimization compared to current common nonblocking implementation patterns from drivers, which all stall for the entire commit to complete, including vblank waits and cleanups. - Extract a separate atomic_commit_hw hook since that's the part most drivers will need to overwrite, hopefully allowing even more shared code. - Enforce EBUSY seamntics by attaching one of the completions to the flip_done vblank event. Side benefit of forcing atomic drivers using these helpers to implement event handlign at least semi-correct. I'm evil that way ;-) - Ridiculously modular, as usual. - The main tracking unit for a commit stays struct drm_atomic_state, and the ownership rules for that are unchanged. Ownership still gets transferred to the driver (and subsequently to the worker) on successful commits. What is added is a small, per-crtc, refcounted structure to track pending commits called struct drm_crtc_commit. No actual state is attached to that though, it's purely for ordering and waiting. - Dependencies are implicitly handled by assuming that any CRTC part of &drm_atomic_state is a dependency, and that the current commit must wait for any commits to complete on those CRTC. This way drivers can easily add more depencies using drm_atomic_get_crtc_state(), which is very natural since in most case a dependency exists iff there's some bit of state that needs to be cross checked. Removing depencies is not possible, drivers simply need to be careful to not include every CRTC in a commit if that's not necessary. Which is a good idea anyway, since that also avoids ww_mutex lock contention. - Queue depth > 1 sees some prep work in this patch by adding a stall paramater to drm_atomic_helper_swap_states(). To be able to push commits entirely free-standing and in a deeper queue through the back-end the driver must not access any obj->state pointers. This means we need to track the old state in drm_atomic_state (much easier with the consolidated arrays), and pass them all explicitly to driver backends (this will be serious amounts of churn). Once that's done stall can be set to false in swap_states. Features: Contains bugs because totally untested. v2: Dont ask for flip_done signalling when the CRTC is off and stays off: Drivers don't handle events in that case. Instead complete right away. This way future commits don't need to have special-case logic, but can keep blocking for the flip_done completion. v3: Tons of fixes: - Stall for preceeding commit for real, not the current one by accident. - Add WARN_ON in case drivers don't fire the drm event. - Don't double-free drm events. v4: Make legacy cursor not stall. v5: Extend the helper hook to cover the entire commit tail. Some drivers need special code for cleanup and vblank waiting, this makes it a bit more useful. Inspired by the rockchip driver. v6: Add WARN_ON to catch drivers who forget to send out the drm event. Cc: Tomeu Vizoso Cc: Daniel Stone Signed-off-by: Daniel Vetter --- drivers/gpu/drm/drm_atomic.c | 22 ++ drivers/gpu/drm/drm_atomic_helper.c | 366 --- drivers/gpu/drm/drm_crtc.c | 3 + drivers/gpu/drm/drm_fops.c | 6 + include/drm/drmP.h | 1 + include/drm/drm_atomic.h | 6 + include/drm/drm_atomic_helper.h | 8 + include/drm/drm_crtc.h | 119 +- include/drm/drm_modeset_helper_vtables.h | 36 +++ 9 files changed, 534 insertions(+), 33 deletions(-) diff --git a/drivers/gpu/drm/drm_atomic.c b/drivers/gpu/drm/drm_atomic.c index 1db198df3014..50aa341ca9ff 100644 --- a/drivers/gpu/drm/drm_atomic.c +++ b/drivers/gpu/drm/drm_atomic.c @@ -33,6 +33,20 @@ #include "drm_crtc_internal.h" +static void crtc_commit_free(struct kref *kref) +{ + struct drm_crtc_commit *commit = + container_of(kref, struct drm_crtc_commit, ref); + + kfree(commit); +} + +void drm_crtc_commit_put(struct drm_crtc_commit *commit) +{ + kref_put(&commit->ref, crtc_commit_free); +} +EXPORT_SYMBOL(drm_crtc_commit_put); + /** * drm_atomic_state_default_release - * release memory initialized by drm_atomic_state_init @@ -148,6 +162,14 @@ void drm_atomic_state_default_clear(struct drm_atomic_state *state) crtc->funcs->atomic_destroy_state(crtc, state->crtcs[i].state); + + if (state->crtcs[i].commit) { + kfree(state->crtcs[i].commit->event); + state->crtcs[i].commit->event = NULL; + drm_crtc_commit_put(state->crtcs[i].commit); +
[PATCH 23/26] drm/i915: Roll out the helper nonblock tracking
Right now still all blocking, no worker anywhere to be seen. Signed-off-by: Daniel Vetter --- drivers/gpu/drm/i915/intel_display.c | 10 +- 1 file changed, 9 insertions(+), 1 deletion(-) diff --git a/drivers/gpu/drm/i915/intel_display.c b/drivers/gpu/drm/i915/intel_display.c index 66a254fa2a96..4b81cffef24e 100644 --- a/drivers/gpu/drm/i915/intel_display.c +++ b/drivers/gpu/drm/i915/intel_display.c @@ -13654,6 +13654,10 @@ static int intel_atomic_commit(struct drm_device *dev, unsigned long put_domains[I915_MAX_PIPES] = {}; unsigned crtc_vblank_mask = 0; + ret = drm_atomic_helper_setup_commit(state, nonblock); + if (ret) + return ret; + ret = intel_atomic_prepare_commit(dev, state, nonblock); if (ret) { DRM_DEBUG_ATOMIC("Preparing state failed with %i\n", ret); @@ -13665,6 +13669,8 @@ static int intel_atomic_commit(struct drm_device *dev, dev_priv->wm.skl_results = intel_state->wm_results; intel_shared_dpll_commit(state); + drm_atomic_helper_wait_for_dependencies(state); + if (intel_state->modeset) { memcpy(dev_priv->min_pixclk, intel_state->min_pixclk, sizeof(intel_state->min_pixclk)); @@ -13760,7 +13766,7 @@ static int intel_atomic_commit(struct drm_device *dev, crtc_vblank_mask |= 1 << i; } - /* FIXME: add subpixel order */ + drm_atomic_helper_commit_hw_done(state); if (!state->legacy_cursor_update) intel_atomic_wait_for_vblanks(dev, dev_priv, crtc_vblank_mask); @@ -13795,6 +13801,8 @@ static int intel_atomic_commit(struct drm_device *dev, drm_atomic_helper_cleanup_planes(dev, state); mutex_unlock(&dev->struct_mutex); + drm_atomic_helper_commit_cleanup_done(state); + drm_atomic_state_free(state); /* As one of the primary mmio accessors, KMS has a high likelihood -- 2.8.1
[PATCH 24/26] drm/rockchip: convert to helper nonblocking atomic commit
So totally untested ... v2: Fixes from Tomeu. v3: Send out vblank events correctly when shutting down a crtc for good. This is part of the atomic interface contract. v4: Properly protect vop->event. Cc: Tomeu Vizoso Cc: Mark yao Signed-off-by: Daniel Vetter --- drivers/gpu/drm/rockchip/rockchip_drm_drv.c | 3 -- drivers/gpu/drm/rockchip/rockchip_drm_drv.h | 10 drivers/gpu/drm/rockchip/rockchip_drm_fb.c | 72 - drivers/gpu/drm/rockchip/rockchip_drm_vop.c | 15 +- 4 files changed, 22 insertions(+), 78 deletions(-) diff --git a/drivers/gpu/drm/rockchip/rockchip_drm_drv.c b/drivers/gpu/drm/rockchip/rockchip_drm_drv.c index 09a4d429c0f0..2fac6799ceb2 100644 --- a/drivers/gpu/drm/rockchip/rockchip_drm_drv.c +++ b/drivers/gpu/drm/rockchip/rockchip_drm_drv.c @@ -145,9 +145,6 @@ static int rockchip_drm_load(struct drm_device *drm_dev, unsigned long flags) if (!private) return -ENOMEM; - mutex_init(&private->commit.lock); - INIT_WORK(&private->commit.work, rockchip_drm_atomic_work); - drm_dev->dev_private = private; drm_mode_config_init(drm_dev); diff --git a/drivers/gpu/drm/rockchip/rockchip_drm_drv.h b/drivers/gpu/drm/rockchip/rockchip_drm_drv.h index 56f43a364c7f..7684503ff765 100644 --- a/drivers/gpu/drm/rockchip/rockchip_drm_drv.h +++ b/drivers/gpu/drm/rockchip/rockchip_drm_drv.h @@ -43,13 +43,6 @@ struct rockchip_crtc_funcs { void (*cancel_pending_vblank)(struct drm_crtc *crtc, struct drm_file *file_priv); }; -struct rockchip_atomic_commit { - struct work_struct work; - struct drm_atomic_state *state; - struct drm_device *dev; - struct mutex lock; -}; - struct rockchip_crtc_state { struct drm_crtc_state base; int output_type; @@ -68,11 +61,8 @@ struct rockchip_drm_private { struct drm_fb_helper fbdev_helper; struct drm_gem_object *fbdev_bo; const struct rockchip_crtc_funcs *crtc_funcs[ROCKCHIP_MAX_CRTC]; - - struct rockchip_atomic_commit commit; }; -void rockchip_drm_atomic_work(struct work_struct *work); int rockchip_register_crtc_funcs(struct drm_crtc *crtc, const struct rockchip_crtc_funcs *crtc_funcs); void rockchip_unregister_crtc_funcs(struct drm_crtc *crtc); diff --git a/drivers/gpu/drm/rockchip/rockchip_drm_fb.c b/drivers/gpu/drm/rockchip/rockchip_drm_fb.c index 5ea141dfae5b..9198ee1ddc87 100644 --- a/drivers/gpu/drm/rockchip/rockchip_drm_fb.c +++ b/drivers/gpu/drm/rockchip/rockchip_drm_fb.c @@ -229,87 +229,32 @@ rockchip_atomic_wait_for_complete(struct drm_device *dev, struct drm_atomic_stat } static void -rockchip_atomic_commit_complete(struct rockchip_atomic_commit *commit) +rockchip_atomic_commit_tail(struct drm_atomic_state *state) { - struct drm_atomic_state *state = commit->state; - struct drm_device *dev = commit->dev; + struct drm_device *dev = state->dev; - /* -* TODO: do fence wait here. -*/ - - /* -* Rockchip crtc support runtime PM, can't update display planes -* when crtc is disabled. -* -* drm_atomic_helper_commit comments detail that: -* For drivers supporting runtime PM the recommended sequence is -* -* drm_atomic_helper_commit_modeset_disables(dev, state); -* -* drm_atomic_helper_commit_modeset_enables(dev, state); -* -* drm_atomic_helper_commit_planes(dev, state, true); -* -* See the kerneldoc entries for these three functions for more details. -*/ drm_atomic_helper_commit_modeset_disables(dev, state); drm_atomic_helper_commit_modeset_enables(dev, state); drm_atomic_helper_commit_planes(dev, state, true); + drm_atomic_helper_commit_hw_done(state); + rockchip_atomic_wait_for_complete(dev, state); drm_atomic_helper_cleanup_planes(dev, state); - - drm_atomic_state_free(state); -} - -void rockchip_drm_atomic_work(struct work_struct *work) -{ - struct rockchip_atomic_commit *commit = container_of(work, - struct rockchip_atomic_commit, work); - - rockchip_atomic_commit_complete(commit); } -int rockchip_drm_atomic_commit(struct drm_device *dev, - struct drm_atomic_state *state, - bool nonblock) -{ - struct rockchip_drm_private *private = dev->dev_private; - struct rockchip_atomic_commit *commit = &private->commit; - int ret; - - ret = drm_atomic_helper_prepare_planes(dev, state); - if (ret) - return ret; - - /* serialize outstanding nonblocking commits */ - mutex_lock(&commit->lock); - flush_work(&commit->work); - - drm_atomic_helper_swap_state(state, true); - - commit->dev = dev; - commit->state = state; - - if (nonblock) - s
[PATCH 25/26] drm/rockchip: Nuke pending event handling in preclose
This is now handled by the core, drivers can totally ignore lifetime issues of drm events. Cc: Tomeu Vizoso Cc: Mark yao Signed-off-by: Daniel Vetter --- drivers/gpu/drm/rockchip/rockchip_drm_drv.c | 22 -- drivers/gpu/drm/rockchip/rockchip_drm_drv.h | 1 - drivers/gpu/drm/rockchip/rockchip_drm_vop.c | 20 3 files changed, 43 deletions(-) diff --git a/drivers/gpu/drm/rockchip/rockchip_drm_drv.c b/drivers/gpu/drm/rockchip/rockchip_drm_drv.c index 2fac6799ceb2..2251121343e6 100644 --- a/drivers/gpu/drm/rockchip/rockchip_drm_drv.c +++ b/drivers/gpu/drm/rockchip/rockchip_drm_drv.c @@ -257,27 +257,6 @@ static int rockchip_drm_unload(struct drm_device *drm_dev) return 0; } -static void rockchip_drm_crtc_cancel_pending_vblank(struct drm_crtc *crtc, - struct drm_file *file_priv) -{ - struct rockchip_drm_private *priv = crtc->dev->dev_private; - int pipe = drm_crtc_index(crtc); - - if (pipe < ROCKCHIP_MAX_CRTC && - priv->crtc_funcs[pipe] && - priv->crtc_funcs[pipe]->cancel_pending_vblank) - priv->crtc_funcs[pipe]->cancel_pending_vblank(crtc, file_priv); -} - -static void rockchip_drm_preclose(struct drm_device *dev, - struct drm_file *file_priv) -{ - struct drm_crtc *crtc; - - list_for_each_entry(crtc, &dev->mode_config.crtc_list, head) - rockchip_drm_crtc_cancel_pending_vblank(crtc, file_priv); -} - void rockchip_drm_lastclose(struct drm_device *dev) { struct rockchip_drm_private *priv = dev->dev_private; @@ -303,7 +282,6 @@ static struct drm_driver rockchip_drm_driver = { DRIVER_PRIME | DRIVER_ATOMIC, .load = rockchip_drm_load, .unload = rockchip_drm_unload, - .preclose = rockchip_drm_preclose, .lastclose = rockchip_drm_lastclose, .get_vblank_counter = drm_vblank_no_hw_counter, .enable_vblank = rockchip_drm_crtc_enable_vblank, diff --git a/drivers/gpu/drm/rockchip/rockchip_drm_drv.h b/drivers/gpu/drm/rockchip/rockchip_drm_drv.h index 7684503ff765..005634484441 100644 --- a/drivers/gpu/drm/rockchip/rockchip_drm_drv.h +++ b/drivers/gpu/drm/rockchip/rockchip_drm_drv.h @@ -40,7 +40,6 @@ struct rockchip_crtc_funcs { int (*enable_vblank)(struct drm_crtc *crtc); void (*disable_vblank)(struct drm_crtc *crtc); void (*wait_for_update)(struct drm_crtc *crtc); - void (*cancel_pending_vblank)(struct drm_crtc *crtc, struct drm_file *file_priv); }; struct rockchip_crtc_state { diff --git a/drivers/gpu/drm/rockchip/rockchip_drm_vop.c b/drivers/gpu/drm/rockchip/rockchip_drm_vop.c index 8cde1ea62978..37a1339c30ae 100644 --- a/drivers/gpu/drm/rockchip/rockchip_drm_vop.c +++ b/drivers/gpu/drm/rockchip/rockchip_drm_vop.c @@ -884,30 +884,10 @@ static void vop_crtc_wait_for_update(struct drm_crtc *crtc) WARN_ON(!wait_for_completion_timeout(&vop->wait_update_complete, 100)); } -static void vop_crtc_cancel_pending_vblank(struct drm_crtc *crtc, - struct drm_file *file_priv) -{ - struct drm_device *drm = crtc->dev; - struct vop *vop = to_vop(crtc); - struct drm_pending_vblank_event *e; - unsigned long flags; - - spin_lock_irqsave(&drm->event_lock, flags); - e = vop->event; - if (e && e->base.file_priv == file_priv) { - vop->event = NULL; - - kfree(&e->base); - file_priv->event_space += sizeof(e->event); - } - spin_unlock_irqrestore(&drm->event_lock, flags); -} - static const struct rockchip_crtc_funcs private_crtc_funcs = { .enable_vblank = vop_crtc_enable_vblank, .disable_vblank = vop_crtc_disable_vblank, .wait_for_update = vop_crtc_wait_for_update, - .cancel_pending_vblank = vop_crtc_cancel_pending_vblank, }; static bool vop_crtc_mode_fixup(struct drm_crtc *crtc, -- 2.8.1
[PATCH 26/26] drm/virtio: Don't reinvent a flipping wheel
Now that the core helpers support nonblocking atomic commits there's no need to invent that wheel separately (instead of fixing the bug in the atomic implementation of virtio, as it should have been done!). Cc: Gerd Hoffmann Signed-off-by: Daniel Vetter --- drivers/gpu/drm/virtio/virtgpu_display.c | 48 ++-- 1 file changed, 2 insertions(+), 46 deletions(-) diff --git a/drivers/gpu/drm/virtio/virtgpu_display.c b/drivers/gpu/drm/virtio/virtgpu_display.c index d4305da88f44..325c6f73814b 100644 --- a/drivers/gpu/drm/virtio/virtgpu_display.c +++ b/drivers/gpu/drm/virtio/virtgpu_display.c @@ -118,58 +118,13 @@ static int virtio_gpu_crtc_cursor_move(struct drm_crtc *crtc, return 0; } -static int virtio_gpu_page_flip(struct drm_crtc *crtc, - struct drm_framebuffer *fb, - struct drm_pending_vblank_event *event, - uint32_t flags) -{ - struct virtio_gpu_device *vgdev = crtc->dev->dev_private; - struct virtio_gpu_output *output = - container_of(crtc, struct virtio_gpu_output, crtc); - struct drm_plane *plane = crtc->primary; - struct virtio_gpu_framebuffer *vgfb; - struct virtio_gpu_object *bo; - unsigned long irqflags; - uint32_t handle; - - plane->fb = fb; - vgfb = to_virtio_gpu_framebuffer(plane->fb); - bo = gem_to_virtio_gpu_obj(vgfb->obj); - handle = bo->hw_res_handle; - - DRM_DEBUG("handle 0x%x%s, crtc %dx%d\n", handle, - bo->dumb ? ", dumb" : "", - crtc->mode.hdisplay, crtc->mode.vdisplay); - if (bo->dumb) { - virtio_gpu_cmd_transfer_to_host_2d - (vgdev, handle, 0, -cpu_to_le32(crtc->mode.hdisplay), -cpu_to_le32(crtc->mode.vdisplay), -0, 0, NULL); - } - virtio_gpu_cmd_set_scanout(vgdev, output->index, handle, - crtc->mode.hdisplay, - crtc->mode.vdisplay, 0, 0); - virtio_gpu_cmd_resource_flush(vgdev, handle, 0, 0, - crtc->mode.hdisplay, - crtc->mode.vdisplay); - - if (event) { - spin_lock_irqsave(&crtc->dev->event_lock, irqflags); - drm_send_vblank_event(crtc->dev, -1, event); - spin_unlock_irqrestore(&crtc->dev->event_lock, irqflags); - } - - return 0; -} - static const struct drm_crtc_funcs virtio_gpu_crtc_funcs = { .cursor_set2= virtio_gpu_crtc_cursor_set, .cursor_move= virtio_gpu_crtc_cursor_move, .set_config = drm_atomic_helper_set_config, .destroy= drm_crtc_cleanup, - .page_flip = virtio_gpu_page_flip, + .page_flip = drm_atomic_helper_page_flip, .reset = drm_atomic_helper_crtc_reset, .atomic_duplicate_state = drm_atomic_helper_crtc_duplicate_state, .atomic_destroy_state = drm_atomic_helper_crtc_destroy_state, @@ -267,6 +222,7 @@ static void virtio_gpu_crtc_atomic_flush(struct drm_crtc *crtc, spin_lock_irqsave(&crtc->dev->event_lock, flags); if (crtc->state->event) drm_crtc_send_vblank_event(crtc, crtc->state->event); + crtc->state->event = NULL; spin_unlock_irqrestore(&crtc->dev->event_lock, flags); } -- 2.8.1
[Bug 119181] Hang in amdgpu_vm_bo_update_mapping with powerplay enabled
https://bugzilla.kernel.org/show_bug.cgi?id=119181 --- Comment #1 from Hristo Venev --- The hang does not occur when the power state is set to low. There are also no rendering glitches (otherwise some frames seem to have random triangles on them). -- You are receiving this mail because: You are watching the assignee of the bug.
[Nouveau] Should I expect nouveau on 4.6 to work on a GM206?
On Sun, May 29, 2016 at 3:07 PM, Andy Lutomirski wrote: > On Sat, May 28, 2016 at 5:48 PM, Ilia Mirkin wrote: >> Do you have mesa 11.2 or later? GM20x support was only added in mesa 11.2. >> > > I just upgraded to 11.2. I'm getting errors like this in the log: > > [ 5383.723240] nouveau :09:00.0: fifo: read fault at 011000 > engine 07 [PBDMA0] client 06 [HOST] reason 00 [PDE] on channel -1 > [007f9ed000 unknown] > [ 5398.722676] nouveau :09:00.0: systemd-logind[30778]: failed to > idle channel 2 [systemd-logind[30778]] > [ 5413.722853] nouveau :09:00.0: systemd-logind[30778]: failed to > idle channel 2 [systemd-logind[30778]] > > and the display output in general is unreliable enough that I'm having > trouble telling whether the performance is remotely reasonable. If you're having trouble telling, that means it's not :) The error you pasted is quite odd. Was there anything in the log before those messages? If there's no channel associated, that means that it's the background copying between vram and sysmem? Not sure. Note that with maxwell we have yet to add EXA support to xf86-video-nouveau, so you're ending up with GLAMOR (and Ben and I disagree on whether EXA support should be added in the first place). There was also an issue that glamor was hitting with nouveau which appears to have dissipated, either due to a change in nouveau or a change in glamor. So you might consider upgrading to Xorg 1.18.3 (as glamor is part of X). FWIW a few other people have been using GM20x without incident, but this can all be very sensitive to your desktop/etc. Lots of things like to use GL nowadays - I stick to a more classic desktop - no compositor, simple window manager, etc. -ilia
[Bug 96271] TF2: GPU lockup on HD 7950
https://bugs.freedesktop.org/show_bug.cgi?id=96271 Bug ID: 96271 Summary: TF2: GPU lockup on HD 7950 Product: Mesa Version: git Hardware: x86-64 (AMD64) OS: Linux (All) Status: NEW Severity: normal Priority: medium Component: Drivers/Gallium/radeonsi Assignee: dri-devel at lists.freedesktop.org Reporter: hi+freedesktop at stephenliang.pw QA Contact: dri-devel at lists.freedesktop.org Created attachment 124165 --> https://bugs.freedesktop.org/attachment.cgi?id=124165&action=edit dmesg on kernel 4.7 I'm getting a GPU lockup on Team Fortress 2 which seems to be related to bug #80419 since my dmesg is the same as comment #44 but this is occurring on Team Fortress 2 rather than XCOM. If I run native TF2 with GALLIUM_DDEBUG=800, I cannot reproduce the bug but the frame rate drops significantly. With GALLIUM_DDEBUG="800 noflush", I was able to reproduce the hang. This leads me to believe that the issue is related how high the FPS is running. My kernel is: Linux localhost.localdomain 4.4.9-300.fc23.x86_64 I've also tried 4.6 and 4.7, all of which hangs. My ATI driver is: 7.7.99-3.20160524git040a7b8.fc23 (latest commit in git for radeon) I've also tried 7.6.1-3.20160215gitd41fccc.fc23 (the latest stable from fedora 23), all of which hangs. My mesa version is: 11.3.0-0.37.git357495b.fc23 I've also tried 11.1.0-2.20151218.fc23 (the latest stable from fedora 23), all of which hangs. I've attached the GALLIUM_DDEBUG output and dmesg. One curious thing is that on kernel 4.7, the kernel detects a hang and is able to reset the GPU resulting in a temporary freeze that eventually resumes. However, the freeze will come again after a short while (and resumes). As a data point, I don't get any lockups while playing Skyrim on Wine. -- You are receiving this mail because: You are the assignee for the bug. -- next part -- An HTML attachment was scrubbed... URL: <https://lists.freedesktop.org/archives/dri-devel/attachments/20160529/9758336b/attachment.html>
[Bug 96271] TF2: GPU lockup on HD 7950
https://bugs.freedesktop.org/show_bug.cgi?id=96271 --- Comment #1 from Stephen Liang --- Created attachment 124166 --> https://bugs.freedesktop.org/attachment.cgi?id=124166&action=edit output from GALLIUM_DDEBUG="800 noflush" steam steam://rungameid/440 -- You are receiving this mail because: You are the assignee for the bug. -- next part -- An HTML attachment was scrubbed... URL: <https://lists.freedesktop.org/archives/dri-devel/attachments/20160529/6e116a2b/attachment.html>
[Bug 96271] TF2: GPU lockup on HD 7950
https://bugs.freedesktop.org/show_bug.cgi?id=96271 --- Comment #2 from Stephen Liang --- One more thing, I did run an apitrace and replayed the apitrace to see if that reproduces the hang. The replay didn't hang my machine initially but after running it a 2-3 times, it was able to hang the machine. I would attach the apitrace but it is 2-3 GB and the hang is several hundreds of thousands of frames in (and it's not reproducible every time during replay, just sometimes). -- You are receiving this mail because: You are the assignee for the bug. -- next part -- An HTML attachment was scrubbed... URL: <https://lists.freedesktop.org/archives/dri-devel/attachments/20160529/3ea313f6/attachment.html>
[Bug 119211] New: amdgpu disables fan by default
https://bugzilla.kernel.org/show_bug.cgi?id=119211 Bug ID: 119211 Summary: amdgpu disables fan by default Product: Drivers Version: 2.5 Kernel Version: 4.5.5 Hardware: All OS: Linux Tree: Fedora Status: NEW Severity: normal Priority: P1 Component: Video(DRI - non Intel) Assignee: drivers_video-dri at kernel-bugs.osdl.org Reporter: stsp at list.ru Regression: No I have radeon R9 380. After the KMS driver activates, the fans on the GPU stops. They can be activated again by properly setting up fancontrol, but this wasn't configured on my PC. As the result, for the last few years I have replaced many motherboards, all starting to have bad capacitors around the video card. But only now I have noticed that the fans are not rotating... :( The driver should activate fans by default, or don't touch the initial settings (fans are rotating before linux have started), but not stop them by default. -- You are receiving this mail because: You are watching the assignee of the bug.
[Bug 119211] amdgpu disables fan by default
https://bugzilla.kernel.org/show_bug.cgi?id=119211 --- Comment #1 from Vedran MiletiÄ --- You should produce some GPU load before the fan activates. -- You are receiving this mail because: You are watching the assignee of the bug.
[Bug 119211] amdgpu disables fan by default
https://bugzilla.kernel.org/show_bug.cgi?id=119211 --- Comment #2 from Stas Sergeev --- Even besides the fact that GPU was so hot I couldn't even touch it? -- You are receiving this mail because: You are watching the assignee of the bug.
[Bug 119211] amdgpu disables fan by default
https://bugzilla.kernel.org/show_bug.cgi?id=119211 --- Comment #3 from Stas Sergeev --- Essentially, when driver initializes, it puts 0 to /sys/class/hwmon/hwmon0/pwm1. And unless you set up fancontrol (which is a major pita), this 0 remain there, no matter how you load you GPU. It should put some other value there, like 50 or more. On my system 50 is a minimum value needed to get the GPU fan rotating. -- You are receiving this mail because: You are watching the assignee of the bug.
[Nouveau] Should I expect nouveau on 4.6 to work on a GM206?
On Sun, May 29, 2016 at 12:22 PM, Ilia Mirkin wrote: > On Sun, May 29, 2016 at 3:07 PM, Andy Lutomirski wrote: >> On Sat, May 28, 2016 at 5:48 PM, Ilia Mirkin wrote: >>> Do you have mesa 11.2 or later? GM20x support was only added in mesa 11.2. >>> >> >> I just upgraded to 11.2. I'm getting errors like this in the log: >> >> [ 5383.723240] nouveau :09:00.0: fifo: read fault at 011000 >> engine 07 [PBDMA0] client 06 [HOST] reason 00 [PDE] on channel -1 >> [007f9ed000 unknown] >> [ 5398.722676] nouveau :09:00.0: systemd-logind[30778]: failed to >> idle channel 2 [systemd-logind[30778]] >> [ 5413.722853] nouveau :09:00.0: systemd-logind[30778]: failed to >> idle channel 2 [systemd-logind[30778]] >> >> and the display output in general is unreliable enough that I'm having >> trouble telling whether the performance is remotely reasonable. > > If you're having trouble telling, that means it's not :) The error you > pasted is quite odd. Was there anything in the log before those > messages? If there's no channel associated, that means that it's the > background copying between vram and sysmem? Not sure. Don't get too excited yet. In the process of upgrading mesa, I managed to boot 4.5 without noticing. I'll post back later today with actual valid test results. > > Note that with maxwell we have yet to add EXA support to > xf86-video-nouveau, so you're ending up with GLAMOR (and Ben and I > disagree on whether EXA support should be added in the first place). > There was also an issue that glamor was hitting with nouveau which > appears to have dissipated, either due to a change in nouveau or a > change in glamor. So you might consider upgrading to Xorg 1.18.3 (as > glamor is part of X). > > FWIW a few other people have been using GM20x without incident, but > this can all be very sensitive to your desktop/etc. Lots of things > like to use GL nowadays - I stick to a more classic desktop - no > compositor, simple window manager, etc. This is GNOME 3 on Fedora 24 Beta. --Andy
[PATCH v3] gpu: drm: amd: amdkfd: Remove create_workqueue()
alloc_workqueue replaces deprecated create_workqueue(). create_workqueue has been replaced with alloc_workqueue with max_active as 0 since there is no need for throttling the number of active work items. WQ_MEM_RECLAIM has not been set to because kfd_process_wq will not be used in memory reclaim path. kfd_process_wq is used for delay destruction. A work item embedded in kfd_process gets queued to kfd_process_wq and when it executes it destroys and frees the containing kfd_process and thus itself. This requires a dedicated workqueue because a work item once queued, may get freed at any point of time and any external entity cannot flush the work item. So, in order to wait for such a work item, it needs to be put on a dedicated workqueue. kfd_module_exit() calls kfd_process_destroy_wq which ensures that all pending work items are finished before the module is removed. flush_workqueue is unnecessary since destroy_workqueue() itself calls drain_workqueue() which flushes repeatedly till the workqueue becomes empty. Hence flush_workqueue has been removed. Signed-off-by: Bhaktipriya Shridhar --- Changes in v3: - Corrected space between arguments. drivers/gpu/drm/amd/amdkfd/kfd_process.c | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/drivers/gpu/drm/amd/amdkfd/kfd_process.c b/drivers/gpu/drm/amd/amdkfd/kfd_process.c index ac00579..6482fee 100644 --- a/drivers/gpu/drm/amd/amdkfd/kfd_process.c +++ b/drivers/gpu/drm/amd/amdkfd/kfd_process.c @@ -63,13 +63,12 @@ static struct kfd_process *create_process(const struct task_struct *thread); void kfd_process_create_wq(void) { if (!kfd_process_wq) - kfd_process_wq = create_workqueue("kfd_process_wq"); + kfd_process_wq = alloc_workqueue("kfd_process_wq", 0, 0); } void kfd_process_destroy_wq(void) { if (kfd_process_wq) { - flush_workqueue(kfd_process_wq); destroy_workqueue(kfd_process_wq); kfd_process_wq = NULL; } -- 2.1.4
[PATCH v2] gpu: drm: amd: amdkfd: Remove create_workqueue()
Thanks Oded. Sending v3 right away :) On Sun, May 29, 2016 at 8:31 PM, Oded Gabbay wrote: > On Thu, May 26, 2016 at 10:37 PM, Bhaktipriya Shridhar > wrote: >> alloc_workqueue replaces deprecated create_workqueue(). >> >> create_workqueue has been replaced with alloc_workqueue with max_active >> as 0 since there is no need for throttling the number of active work items. >> >> WQ_MEM_RECLAIM has not been set to because kfd_process_wq will not be used in >> memory reclaim path. >> >> kfd_process_wq is used for delay destruction. A work item embedded in >> kfd_process gets queued to kfd_process_wq and when it executes it >> destroys and frees the containing kfd_process and thus itself. >> >> This requires a dedicated workqueue because a work item once queued, may >> get freed at any point of time and any external entity cannot >> flush the work item. So, in order to wait for such a work item, >> it needs to be put on a dedicated workqueue. >> >> kfd_module_exit() calls kfd_process_destroy_wq which ensures that all >> pending work items are finished before the module is removed. >> >> flush_workqueue is unnecessary since destroy_workqueue() itself calls >> drain_workqueue() which flushes repeatedly till the workqueue becomes empty. >> >> Hence flush_workqueue has been removed. >> >> Signed-off-by: Bhaktipriya Shridhar >> --- >> Changes in v2: >> - added explanation for setting concurrency value to >> WQ_DFL_ACTIVE >> - added explanation for dropping WQ_MEM_RECLAIM >> >> drivers/gpu/drm/amd/amdkfd/kfd_process.c | 3 +-- >> 1 file changed, 1 insertion(+), 2 deletions(-) >> >> diff --git a/drivers/gpu/drm/amd/amdkfd/kfd_process.c >> b/drivers/gpu/drm/amd/amdkfd/kfd_process.c >> index ac00579..b21d3fc8 100644 >> --- a/drivers/gpu/drm/amd/amdkfd/kfd_process.c >> +++ b/drivers/gpu/drm/amd/amdkfd/kfd_process.c >> @@ -63,13 +63,12 @@ static struct kfd_process *create_process(const struct >> task_struct *thread); >> void kfd_process_create_wq(void) >> { >> if (!kfd_process_wq) >> - kfd_process_wq = create_workqueue("kfd_process_wq"); >> + kfd_process_wq = alloc_workqueue("kfd_process_wq",0,0); > > You are missing a space between the arguments. Seem you forgot to run > checkpatch.pl ;) > > Send a new patch and I'll add it to amdkfd's tree. > > Thanks, > >Oded > >> } >> >> void kfd_process_destroy_wq(void) >> { >> if (kfd_process_wq) { >> - flush_workqueue(kfd_process_wq); >> destroy_workqueue(kfd_process_wq); >> kfd_process_wq = NULL; >> } >> -- >> 2.1.4 >>
[Nouveau] Should I expect nouveau on 4.6 to work on a GM206?
On Sat, May 28, 2016 at 5:48 PM, Ilia Mirkin wrote: > Do you have mesa 11.2 or later? GM20x support was only added in mesa 11.2. > I just upgraded to 11.2. I'm getting errors like this in the log: [ 5383.723240] nouveau :09:00.0: fifo: read fault at 011000 engine 07 [PBDMA0] client 06 [HOST] reason 00 [PDE] on channel -1 [007f9ed000 unknown] [ 5398.722676] nouveau :09:00.0: systemd-logind[30778]: failed to idle channel 2 [systemd-logind[30778]] [ 5413.722853] nouveau :09:00.0: systemd-logind[30778]: failed to idle channel 2 [systemd-logind[30778]] and the display output in general is unreliable enough that I'm having trouble telling whether the performance is remotely reasonable. --Andy > Cheers, > > -ilia > > On Sat, May 28, 2016 at 4:51 PM, Andy Lutomirski wrote: >> I have the signed firmware (I think) and I'm running a fresh 4.6 >> kernel. I got an image to show up briefly, rendering the Fedora >> sign-in screen at something like one frame per ten seconds. But then >> I got all kinds of garbage, and I see: >> >> [ 719.300820] nouveau :09:00.0: disp: outp 04:0006:0f44: link >> training failed >> >> dmesg |grep nouveau says: >> >> [ 10.053162] fb: switching to nouveaufb from EFI VGA >> [ 10.053349] nouveau :09:00.0: NVIDIA GM206 (126010a1) >> [ 10.174033] nouveau :09:00.0: bios: version 84.06.0d.00.01 >> [ 10.174854] nouveau :09:00.0: disp: dcb 15 type 8 unknown >> [ 10.178375] nouveau :09:00.0: fb: 2048 MiB GDDR5 >> [ 10.202108] nouveau :09:00.0: DRM: VRAM: 2048 MiB >> [ 10.202109] nouveau :09:00.0: DRM: GART: 1048576 MiB >> [ 10.202113] nouveau :09:00.0: DRM: TMDS table version 2.0 >> [ 10.202114] nouveau :09:00.0: DRM: DCB version 4.1 >> [ 10.202116] nouveau :09:00.0: DRM: DCB outp 00: 01000f02 00020030 >> [ 10.202117] nouveau :09:00.0: DRM: DCB outp 01: 02000f00 >> [ 10.202118] nouveau :09:00.0: DRM: DCB outp 02: 02811f76 04400020 >> [ 10.202120] nouveau :09:00.0: DRM: DCB outp 03: 02011f72 00020020 >> [ 10.202121] nouveau :09:00.0: DRM: DCB outp 04: 04822f86 04400010 >> [ 10.202122] nouveau :09:00.0: DRM: DCB outp 05: 04022f82 00020010 >> [ 10.202123] nouveau :09:00.0: DRM: DCB outp 06: 04833f96 04400020 >> [ 10.202124] nouveau :09:00.0: DRM: DCB outp 07: 04033f92 00020020 >> [ 10.202125] nouveau :09:00.0: DRM: DCB outp 08: 02044f62 00020010 >> [ 10.202126] nouveau :09:00.0: DRM: DCB outp 15: 01df5ff8 >> [ 10.202127] nouveau :09:00.0: DRM: DCB conn 00: 1030 >> [ 10.202128] nouveau :09:00.0: DRM: DCB conn 01: 00020146 >> [ 10.202129] nouveau :09:00.0: DRM: DCB conn 02: 01000246 >> [ 10.202130] nouveau :09:00.0: DRM: DCB conn 03: 02000346 >> [ 10.202131] nouveau :09:00.0: DRM: DCB conn 04: 00010461 >> [ 10.202132] nouveau :09:00.0: DRM: DCB conn 05: 0570 >> [ 10.202134] nouveau :09:00.0: DRM: Pointer to flat panel table invalid >> [ 10.214683] nouveau :09:00.0: DRM: unknown connector type 70 >> [ 10.214728] nouveau :09:00.0: DRM: failed to create encoder 1/8/0: -19 >> [ 10.214730] nouveau :09:00.0: DRM: Unknown-1 has no encoders, removing >> [ 10.369691] nouveau :09:00.0: DRM: MM: using COPY for buffer copies >> [ 10.478561] nouveau :09:00.0: priv: GPC0: 419df4 (1e40820e) >> [ 10.478578] nouveau :09:00.0: priv: GPC1: 419df4 (1e40820e) >> [ 10.607100] nouveau :09:00.0: DRM: allocated 3840x2160 fb: >> 0x6, bo 88044aad7400 >> [ 10.607276] fbcon: nouveaufb (fb0) is primary device >> [ 10.607576] nouveau :09:00.0: fb0: nouveaufb frame buffer device >> [ 10.617064] [drm] Initialized nouveau 1.3.1 20120801 for >> :09:00.0 on minor 0 >> [ 719.282184] nouveau :09:00.0: disp: outp 04:0006:0f44: link >> training failed >> [ 719.300820] nouveau :09:00.0: disp: outp 04:0006:0f44: link >> training failed >> >> >> >> Thanks, >> Andy >> ___ >> Nouveau mailing list >> Nouveau at lists.freedesktop.org >> https://lists.freedesktop.org/mailman/listinfo/nouveau