Hi all,
After quite a long interruption with looking too much at dma-fence I've found some time (and motivation due to questions from people who got confused by the intermediate state) to polish this off. Changes:
- arc changes moved to the end, since they're not really critical. Iirc there's still a bug in there, but some are fixed in this version, so needs some testing. Also added some of the Acks from Sam, and applied the minor nits.
- virtual drivers (vkms, vgem & i915 selftests) changed to use devres_open/release_group, so that we don't need a hack in driver core or an entire fake bus.
I'd really like to get "drm/dev: Remove drm_dev_init" so that all the confusing intermediate functions are gone from drivers.
Review, testing, comments all very much welcome like usual.
Cheers, Daniel
Daniel Vetter (24): drm/armada: Use devm_drm_dev_alloc drm/armada: Don't use drm_device->dev_private drm/aspeed: Use managed drmm_mode_config_cleanup drm/vgem: Use devm_drm_dev_alloc drm/vkms: Use devm_drm_dev_alloc drm/xlnx: Use devm_drm_dev_alloc drm/i915/selftest: Create mock_destroy_device drm/i915/selftests: align more to real device lifetimes drm/dev: Remove drm_dev_init drm/arc: Switch to devm_drm_dev_alloc drm/arc: Stop using drm_device->dev_private drm/arc: Delete arcpgu_priv->fb drm/arc: Embedded a drm_simple_display_pipe drm/arc: Embedd a drm_connector for sim case drm/arc: Drop surplus connector registration drm/arc: Use drmm_mode_config_cleanup drm/arc: Align with simple pipe helpers drm/arc: Convert to drm_simple_kms_pipe_helper drm/arc: Drop crtc check in arc_pgu_update drm/arc: Inline arcpgu_crtc.c drm/arc: Inline arcpgu_drm_hdmi_init drm/arc: Inline remaining files drm/arc: Initialize sim connector before display pipe drm/arc: Move to drm/tiny
MAINTAINERS | 2 +- drivers/gpu/drm/Kconfig | 2 - drivers/gpu/drm/Makefile | 1 - drivers/gpu/drm/arc/Kconfig | 10 - drivers/gpu/drm/arc/Makefile | 3 - drivers/gpu/drm/arc/arcpgu.h | 37 -- drivers/gpu/drm/arc/arcpgu_crtc.c | 222 --------- drivers/gpu/drm/arc/arcpgu_drv.c | 224 --------- drivers/gpu/drm/arc/arcpgu_hdmi.c | 48 -- drivers/gpu/drm/arc/arcpgu_regs.h | 31 -- drivers/gpu/drm/arc/arcpgu_sim.c | 108 ----- drivers/gpu/drm/armada/armada_crtc.c | 4 +- drivers/gpu/drm/armada/armada_debugfs.c | 2 +- drivers/gpu/drm/armada/armada_drm.h | 2 + drivers/gpu/drm/armada/armada_drv.c | 30 +- drivers/gpu/drm/armada/armada_fbdev.c | 4 +- drivers/gpu/drm/armada/armada_gem.c | 4 +- drivers/gpu/drm/armada/armada_overlay.c | 8 +- drivers/gpu/drm/aspeed/aspeed_gfx_drv.c | 15 +- drivers/gpu/drm/drm_drv.c | 41 +- drivers/gpu/drm/drm_internal.h | 1 + drivers/gpu/drm/drm_managed.c | 13 - .../gpu/drm/i915/gem/selftests/huge_pages.c | 2 +- .../drm/i915/gem/selftests/i915_gem_context.c | 2 +- .../drm/i915/gem/selftests/i915_gem_dmabuf.c | 2 +- .../drm/i915/gem/selftests/i915_gem_object.c | 2 +- .../drm/i915/gem/selftests/i915_gem_phys.c | 2 +- drivers/gpu/drm/i915/gt/selftest_timeline.c | 2 +- .../gpu/drm/i915/selftests/i915_gem_evict.c | 2 +- drivers/gpu/drm/i915/selftests/i915_gem_gtt.c | 2 +- drivers/gpu/drm/i915/selftests/i915_request.c | 2 +- drivers/gpu/drm/i915/selftests/i915_vma.c | 2 +- .../drm/i915/selftests/intel_memory_region.c | 2 +- .../gpu/drm/i915/selftests/mock_gem_device.c | 47 +- .../gpu/drm/i915/selftests/mock_gem_device.h | 2 + drivers/gpu/drm/tiny/Kconfig | 10 + drivers/gpu/drm/tiny/Makefile | 1 + drivers/gpu/drm/tiny/arcpgu.c | 434 ++++++++++++++++++ drivers/gpu/drm/vgem/vgem_drv.c | 55 +-- drivers/gpu/drm/vkms/vkms_drv.c | 54 ++- drivers/gpu/drm/xlnx/zynqmp_dpsub.c | 21 +- include/drm/drm_drv.h | 4 - 42 files changed, 578 insertions(+), 884 deletions(-) delete mode 100644 drivers/gpu/drm/arc/Kconfig delete mode 100644 drivers/gpu/drm/arc/Makefile delete mode 100644 drivers/gpu/drm/arc/arcpgu.h delete mode 100644 drivers/gpu/drm/arc/arcpgu_crtc.c delete mode 100644 drivers/gpu/drm/arc/arcpgu_drv.c delete mode 100644 drivers/gpu/drm/arc/arcpgu_hdmi.c delete mode 100644 drivers/gpu/drm/arc/arcpgu_regs.h delete mode 100644 drivers/gpu/drm/arc/arcpgu_sim.c create mode 100644 drivers/gpu/drm/tiny/arcpgu.c
Also remove the now no longer needed build bug on since that's already not needed anymore with drmm_add_final_kfree. Conversion to managed drm_device cleanup is easy, the final drm_dev_put() is already the last thing in both the bind unbind as in the unbind flow.
Also, this relies on component.c correctly wrapping bind&unbind in separate devres groups, which it does.
Signed-off-by: Daniel Vetter daniel.vetter@intel.com Cc: Russell King linux@armlinux.org.uk --- drivers/gpu/drm/armada/armada_drv.c | 26 ++++++-------------------- 1 file changed, 6 insertions(+), 20 deletions(-)
diff --git a/drivers/gpu/drm/armada/armada_drv.c b/drivers/gpu/drm/armada/armada_drv.c index 5fc25c3f445c..a8d5908b3922 100644 --- a/drivers/gpu/drm/armada/armada_drv.c +++ b/drivers/gpu/drm/armada/armada_drv.c @@ -87,24 +87,13 @@ static int armada_drm_bind(struct device *dev) "armada-drm")) return -EBUSY;
- priv = kzalloc(sizeof(*priv), GFP_KERNEL); - if (!priv) - return -ENOMEM; - - /* - * The drm_device structure must be at the start of - * armada_private for drm_dev_put() to work correctly. - */ - BUILD_BUG_ON(offsetof(struct armada_private, drm) != 0); - - ret = drm_dev_init(&priv->drm, &armada_drm_driver, dev); - if (ret) { - dev_err(dev, "[" DRM_NAME ":%s] drm_dev_init failed: %d\n", - __func__, ret); - kfree(priv); - return ret; + priv = devm_drm_dev_alloc(dev, &armada_drm_driver, + struct armada_private, drm); + if (IS_ERR(priv)) { + dev_err(dev, "[" DRM_NAME ":%s] devm_drm_dev_alloc failed: %li\n", + __func__, PTR_ERR(priv)); + return PTR_ERR(priv); } - drmm_add_final_kfree(&priv->drm, priv);
/* Remove early framebuffers */ ret = drm_fb_helper_remove_conflicting_framebuffers(NULL, @@ -174,7 +163,6 @@ static int armada_drm_bind(struct device *dev) err_kms: drm_mode_config_cleanup(&priv->drm); drm_mm_takedown(&priv->linear); - drm_dev_put(&priv->drm); return ret; }
@@ -194,8 +182,6 @@ static void armada_drm_unbind(struct device *dev)
drm_mode_config_cleanup(&priv->drm); drm_mm_takedown(&priv->linear); - - drm_dev_put(&priv->drm); }
static int compare_of(struct device *dev, void *data)
For the two armada patches.
Reviewed-by: Dave Airlie airlied@redhat.com
On Sat, 5 Sep 2020 at 00:40, Daniel Vetter daniel.vetter@ffwll.ch wrote:
Upcasting using a container_of macro is more typesafe, faster and easier for the compiler to optimize.
Signed-off-by: Daniel Vetter daniel.vetter@intel.com Cc: Russell King linux@armlinux.org.uk --- drivers/gpu/drm/armada/armada_crtc.c | 4 ++-- drivers/gpu/drm/armada/armada_debugfs.c | 2 +- drivers/gpu/drm/armada/armada_drm.h | 2 ++ drivers/gpu/drm/armada/armada_drv.c | 4 +--- drivers/gpu/drm/armada/armada_fbdev.c | 4 ++-- drivers/gpu/drm/armada/armada_gem.c | 4 ++-- drivers/gpu/drm/armada/armada_overlay.c | 8 ++++---- 7 files changed, 14 insertions(+), 14 deletions(-)
diff --git a/drivers/gpu/drm/armada/armada_crtc.c b/drivers/gpu/drm/armada/armada_crtc.c index 38dfaa46d306..a887b6a5f8bd 100644 --- a/drivers/gpu/drm/armada/armada_crtc.c +++ b/drivers/gpu/drm/armada/armada_crtc.c @@ -757,7 +757,7 @@ static int armada_drm_crtc_cursor_move(struct drm_crtc *crtc, int x, int y) static void armada_drm_crtc_destroy(struct drm_crtc *crtc) { struct armada_crtc *dcrtc = drm_to_armada_crtc(crtc); - struct armada_private *priv = crtc->dev->dev_private; + struct armada_private *priv = drm_to_armada_dev(crtc->dev);
if (dcrtc->cursor_obj) drm_gem_object_put(&dcrtc->cursor_obj->obj); @@ -901,7 +901,7 @@ static int armada_drm_crtc_create(struct drm_device *drm, struct device *dev, struct resource *res, int irq, const struct armada_variant *variant, struct device_node *port) { - struct armada_private *priv = drm->dev_private; + struct armada_private *priv = drm_to_armada_dev(drm); struct armada_crtc *dcrtc; struct drm_plane *primary; void __iomem *base; diff --git a/drivers/gpu/drm/armada/armada_debugfs.c b/drivers/gpu/drm/armada/armada_debugfs.c index c6fc2f1d58e9..29f4b52e3c8d 100644 --- a/drivers/gpu/drm/armada/armada_debugfs.c +++ b/drivers/gpu/drm/armada/armada_debugfs.c @@ -19,7 +19,7 @@ static int armada_debugfs_gem_linear_show(struct seq_file *m, void *data) { struct drm_info_node *node = m->private; struct drm_device *dev = node->minor->dev; - struct armada_private *priv = dev->dev_private; + struct armada_private *priv = drm_to_armada_dev(dev); struct drm_printer p = drm_seq_file_printer(m);
mutex_lock(&priv->linear_lock); diff --git a/drivers/gpu/drm/armada/armada_drm.h b/drivers/gpu/drm/armada/armada_drm.h index a11bdaccbb33..6a5a87932576 100644 --- a/drivers/gpu/drm/armada/armada_drm.h +++ b/drivers/gpu/drm/armada/armada_drm.h @@ -73,6 +73,8 @@ struct armada_private { #endif };
+#define drm_to_armada_dev(dev) container_of(dev, struct armada_private, drm) + int armada_fbdev_init(struct drm_device *); void armada_fbdev_fini(struct drm_device *);
diff --git a/drivers/gpu/drm/armada/armada_drv.c b/drivers/gpu/drm/armada/armada_drv.c index a8d5908b3922..980d3f1f8f16 100644 --- a/drivers/gpu/drm/armada/armada_drv.c +++ b/drivers/gpu/drm/armada/armada_drv.c @@ -106,8 +106,6 @@ static int armada_drm_bind(struct device *dev) return ret; }
- priv->drm.dev_private = priv; - dev_set_drvdata(dev, &priv->drm);
/* Mode setting support */ @@ -169,7 +167,7 @@ static int armada_drm_bind(struct device *dev) static void armada_drm_unbind(struct device *dev) { struct drm_device *drm = dev_get_drvdata(dev); - struct armada_private *priv = drm->dev_private; + struct armada_private *priv = drm_to_armada_dev(drm);
drm_kms_helper_poll_fini(&priv->drm); armada_fbdev_fini(&priv->drm); diff --git a/drivers/gpu/drm/armada/armada_fbdev.c b/drivers/gpu/drm/armada/armada_fbdev.c index 0c4601275507..38f5170c0fea 100644 --- a/drivers/gpu/drm/armada/armada_fbdev.c +++ b/drivers/gpu/drm/armada/armada_fbdev.c @@ -117,7 +117,7 @@ static const struct drm_fb_helper_funcs armada_fb_helper_funcs = {
int armada_fbdev_init(struct drm_device *dev) { - struct armada_private *priv = dev->dev_private; + struct armada_private *priv = drm_to_armada_dev(dev); struct drm_fb_helper *fbh; int ret;
@@ -151,7 +151,7 @@ int armada_fbdev_init(struct drm_device *dev)
void armada_fbdev_fini(struct drm_device *dev) { - struct armada_private *priv = dev->dev_private; + struct armada_private *priv = drm_to_armada_dev(dev); struct drm_fb_helper *fbh = priv->fbdev;
if (fbh) { diff --git a/drivers/gpu/drm/armada/armada_gem.c b/drivers/gpu/drm/armada/armada_gem.c index 8005614d2e6b..ecf8a55e93d9 100644 --- a/drivers/gpu/drm/armada/armada_gem.c +++ b/drivers/gpu/drm/armada/armada_gem.c @@ -39,7 +39,7 @@ static size_t roundup_gem_size(size_t size) void armada_gem_free_object(struct drm_gem_object *obj) { struct armada_gem_object *dobj = drm_to_armada_gem(obj); - struct armada_private *priv = obj->dev->dev_private; + struct armada_private *priv = drm_to_armada_dev(obj->dev);
DRM_DEBUG_DRIVER("release obj %p\n", dobj);
@@ -77,7 +77,7 @@ void armada_gem_free_object(struct drm_gem_object *obj) int armada_gem_linear_back(struct drm_device *dev, struct armada_gem_object *obj) { - struct armada_private *priv = dev->dev_private; + struct armada_private *priv = drm_to_armada_dev(dev); size_t size = obj->obj.size;
if (obj->page || obj->linear) diff --git a/drivers/gpu/drm/armada/armada_overlay.c b/drivers/gpu/drm/armada/armada_overlay.c index 07f0da4d9ba1..30e01101f59e 100644 --- a/drivers/gpu/drm/armada/armada_overlay.c +++ b/drivers/gpu/drm/armada/armada_overlay.c @@ -344,7 +344,7 @@ static int armada_overlay_set_property(struct drm_plane *plane, struct drm_plane_state *state, struct drm_property *property, uint64_t val) { - struct armada_private *priv = plane->dev->dev_private; + struct armada_private *priv = drm_to_armada_dev(plane->dev);
#define K2R(val) (((val) >> 0) & 0xff) #define K2G(val) (((val) >> 8) & 0xff) @@ -412,7 +412,7 @@ static int armada_overlay_get_property(struct drm_plane *plane, const struct drm_plane_state *state, struct drm_property *property, uint64_t *val) { - struct armada_private *priv = plane->dev->dev_private; + struct armada_private *priv = drm_to_armada_dev(plane->dev);
#define C2K(c,s) (((c) >> (s)) & 0xff) #define R2BGR(r,g,b,s) (C2K(r,s) << 0 | C2K(g,s) << 8 | C2K(b,s) << 16) @@ -505,7 +505,7 @@ static const struct drm_prop_enum_list armada_drm_colorkey_enum_list[] = {
static int armada_overlay_create_properties(struct drm_device *dev) { - struct armada_private *priv = dev->dev_private; + struct armada_private *priv = drm_to_armada_dev(dev);
if (priv->colorkey_prop) return 0; @@ -539,7 +539,7 @@ static int armada_overlay_create_properties(struct drm_device *dev)
int armada_overlay_plane_create(struct drm_device *dev, unsigned long crtcs) { - struct armada_private *priv = dev->dev_private; + struct armada_private *priv = drm_to_armada_dev(dev); struct drm_mode_object *mobj; struct drm_plane *overlay; int ret;
Since aspeed doesn't use devm_kzalloc anymore we can use the managed mode config cleanup.
v2: Keep call order as suggested by Sam.
Acked-by: Sam Ravnborg sam@ravnborg.org Signed-off-by: Daniel Vetter daniel.vetter@intel.com Cc: Joel Stanley joel@jms.id.au Cc: Andrew Jeffery andrew@aj.id.au Cc: linux-aspeed@lists.ozlabs.org Cc: linux-arm-kernel@lists.infradead.org --- drivers/gpu/drm/aspeed/aspeed_gfx_drv.c | 15 +++++++++++---- 1 file changed, 11 insertions(+), 4 deletions(-)
diff --git a/drivers/gpu/drm/aspeed/aspeed_gfx_drv.c b/drivers/gpu/drm/aspeed/aspeed_gfx_drv.c index 903f4f304647..2b424b2b85cc 100644 --- a/drivers/gpu/drm/aspeed/aspeed_gfx_drv.c +++ b/drivers/gpu/drm/aspeed/aspeed_gfx_drv.c @@ -63,15 +63,21 @@ static const struct drm_mode_config_funcs aspeed_gfx_mode_config_funcs = { .atomic_commit = drm_atomic_helper_commit, };
-static void aspeed_gfx_setup_mode_config(struct drm_device *drm) +static int aspeed_gfx_setup_mode_config(struct drm_device *drm) { - drm_mode_config_init(drm); + int ret; + + ret = drmm_mode_config_init(drm); + if (ret) + return ret;
drm->mode_config.min_width = 0; drm->mode_config.min_height = 0; drm->mode_config.max_width = 800; drm->mode_config.max_height = 600; drm->mode_config.funcs = &aspeed_gfx_mode_config_funcs; + + return ret; }
static irqreturn_t aspeed_gfx_irq_handler(int irq, void *data) @@ -144,7 +150,9 @@ static int aspeed_gfx_load(struct drm_device *drm) writel(0, priv->base + CRT_CTRL1); writel(0, priv->base + CRT_CTRL2);
- aspeed_gfx_setup_mode_config(drm); + ret = aspeed_gfx_setup_mode_config(drm); + if (ret < 0) + return ret;
ret = drm_vblank_init(drm, 1); if (ret < 0) { @@ -179,7 +187,6 @@ static int aspeed_gfx_load(struct drm_device *drm) static void aspeed_gfx_unload(struct drm_device *drm) { drm_kms_helper_poll_fini(drm); - drm_mode_config_cleanup(drm); }
DEFINE_DRM_GEM_CMA_FOPS(fops);
This means we also need to slightly restructure the exit code, so that final cleanup of the drm_device is triggered by unregistering the platform device. Note that devres is both clean up when the driver is unbound (not the case for vgem, we don't bind), and also when unregistering the device (very much the case for vgem). Therefore we can rely on devres even though vgem isn't a proper platform device driver.
This also somewhat untangles the load code, since the drm and platform device setup are no longer interleaved, but two distinct steps.
v2: use devres_open/release_group so we can use devm without real hacks in the driver core or having to create an entire fake bus for testing drivers. Might want to extract this into helpers eventually, maybe as a mock_drm_dev_alloc or test_drm_dev_alloc.
Signed-off-by: Daniel Vetter daniel.vetter@ffwll.ch Cc: Daniel Vetter daniel.vetter@ffwll.ch Cc: Emil Velikov emil.velikov@collabora.com Cc: Sean Paul seanpaul@chromium.org Cc: Chris Wilson chris@chris-wilson.co.uk Cc: Sam Ravnborg sam@ravnborg.org Cc: Rob Clark robdclark@chromium.org --- drivers/gpu/drm/vgem/vgem_drv.c | 55 ++++++++++++++------------------- 1 file changed, 24 insertions(+), 31 deletions(-)
diff --git a/drivers/gpu/drm/vgem/vgem_drv.c b/drivers/gpu/drm/vgem/vgem_drv.c index 313339bbff90..f95537627463 100644 --- a/drivers/gpu/drm/vgem/vgem_drv.c +++ b/drivers/gpu/drm/vgem/vgem_drv.c @@ -401,16 +401,8 @@ static int vgem_prime_mmap(struct drm_gem_object *obj, return 0; }
-static void vgem_release(struct drm_device *dev) -{ - struct vgem_device *vgem = container_of(dev, typeof(*vgem), drm); - - platform_device_unregister(vgem->platform); -} - static struct drm_driver vgem_driver = { .driver_features = DRIVER_GEM | DRIVER_RENDER, - .release = vgem_release, .open = vgem_open, .postclose = vgem_postclose, .gem_free_object_unlocked = vgem_gem_free_object, @@ -442,48 +434,49 @@ static struct drm_driver vgem_driver = { static int __init vgem_init(void) { int ret; + struct platform_device *pdev;
- vgem_device = kzalloc(sizeof(*vgem_device), GFP_KERNEL); - if (!vgem_device) - return -ENOMEM; + pdev = platform_device_register_simple("vgem", -1, NULL, 0); + if (IS_ERR(pdev)) + return PTR_ERR(vgem_device->platform);
- vgem_device->platform = - platform_device_register_simple("vgem", -1, NULL, 0); - if (IS_ERR(vgem_device->platform)) { - ret = PTR_ERR(vgem_device->platform); - goto out_free; + if (!devres_open_group(&pdev->dev, NULL, GFP_KERNEL)) { + ret = -ENOMEM; + goto out_unregister; }
- dma_coerce_mask_and_coherent(&vgem_device->platform->dev, + dma_coerce_mask_and_coherent(&pdev->dev, DMA_BIT_MASK(64)); - ret = drm_dev_init(&vgem_device->drm, &vgem_driver, - &vgem_device->platform->dev); - if (ret) - goto out_unregister; - drmm_add_final_kfree(&vgem_device->drm, vgem_device); + + vgem_device = devm_drm_dev_alloc(&pdev->dev, &vgem_driver, + struct vgem_device, drm); + if (IS_ERR(vgem_device)) { + ret = PTR_ERR(vgem_device); + goto out_devres; + } + vgem_device->platform = pdev;
/* Final step: expose the device/driver to userspace */ ret = drm_dev_register(&vgem_device->drm, 0); if (ret) - goto out_put; + goto out_devres;
return 0;
-out_put: - drm_dev_put(&vgem_device->drm); - platform_device_unregister(vgem_device->platform); - return ret; +out_devres: + devres_release_group(&pdev->dev, NULL); out_unregister: - platform_device_unregister(vgem_device->platform); -out_free: - kfree(vgem_device); + platform_device_unregister(pdev); return ret; }
static void __exit vgem_exit(void) { + struct platform_device *pdev = vgem_device->platform; + drm_dev_unregister(&vgem_device->drm); - drm_dev_put(&vgem_device->drm); + devres_release_group(&pdev->dev, NULL); + platform_device_unregister(pdev); }
module_init(vgem_init);
Hi Daniel,
looks good to me, just a few things inline.
On 09/04, Daniel Vetter wrote:
I caught this line right above. It should be: return PTR_ERR (pdev), right?
Well, there has never been a check for a null vgem_device here before, as in vkms. Should?
Apart from these two points,
Reviewed-by: Melissa Wen melissa.srw@gmail.com
Thanks!
On Wed, Sep 9, 2020 at 1:01 PM Melissa Wen melissa.srw@gmail.com wrote:
Yes I will fix.
I think it should, but that's kinda a separate patch. Want to type it? -Daniel
This means we also need to slightly restructure the exit code, so that final cleanup of the drm_device is triggered by unregistering the platform device. Note that devres is both clean up when the driver is unbound (not the case for vgem, we don't bind), and also when unregistering the device (very much the case for vgem). Therefore we can rely on devres even though vgem isn't a proper platform device driver.
This also somewhat untangles the load code, since the drm and platform device setup are no longer interleaved, but two distinct steps.
v2: use devres_open/release_group so we can use devm without real hacks in the driver core or having to create an entire fake bus for testing drivers. Might want to extract this into helpers eventually, maybe as a mock_drm_dev_alloc or test_drm_dev_alloc.
v3: Fix error code handling (Melissa)
Cc: Melissa Wen melissa.srw@gmail.com Reviewed-by: Melissa Wen melissa.srw@gmail.com Signed-off-by: Daniel Vetter daniel.vetter@ffwll.ch Cc: Daniel Vetter daniel.vetter@ffwll.ch Cc: Emil Velikov emil.velikov@collabora.com Cc: Sean Paul seanpaul@chromium.org Cc: Chris Wilson chris@chris-wilson.co.uk Cc: Sam Ravnborg sam@ravnborg.org Cc: Rob Clark robdclark@chromium.org --- drivers/gpu/drm/vgem/vgem_drv.c | 55 ++++++++++++++------------------- 1 file changed, 24 insertions(+), 31 deletions(-)
diff --git a/drivers/gpu/drm/vgem/vgem_drv.c b/drivers/gpu/drm/vgem/vgem_drv.c index 15dd41e67de3..cb884c890065 100644 --- a/drivers/gpu/drm/vgem/vgem_drv.c +++ b/drivers/gpu/drm/vgem/vgem_drv.c @@ -401,16 +401,8 @@ static int vgem_prime_mmap(struct drm_gem_object *obj, return 0; }
-static void vgem_release(struct drm_device *dev) -{ - struct vgem_device *vgem = container_of(dev, typeof(*vgem), drm); - - platform_device_unregister(vgem->platform); -} - static struct drm_driver vgem_driver = { .driver_features = DRIVER_GEM | DRIVER_RENDER, - .release = vgem_release, .open = vgem_open, .postclose = vgem_postclose, .gem_free_object_unlocked = vgem_gem_free_object, @@ -442,48 +434,49 @@ static struct drm_driver vgem_driver = { static int __init vgem_init(void) { int ret; + struct platform_device *pdev;
- vgem_device = kzalloc(sizeof(*vgem_device), GFP_KERNEL); - if (!vgem_device) - return -ENOMEM; + pdev = platform_device_register_simple("vgem", -1, NULL, 0); + if (IS_ERR(pdev)) + return PTR_ERR(pdev);
- vgem_device->platform = - platform_device_register_simple("vgem", -1, NULL, 0); - if (IS_ERR(vgem_device->platform)) { - ret = PTR_ERR(vgem_device->platform); - goto out_free; + if (!devres_open_group(&pdev->dev, NULL, GFP_KERNEL)) { + ret = -ENOMEM; + goto out_unregister; }
- dma_coerce_mask_and_coherent(&vgem_device->platform->dev, + dma_coerce_mask_and_coherent(&pdev->dev, DMA_BIT_MASK(64)); - ret = drm_dev_init(&vgem_device->drm, &vgem_driver, - &vgem_device->platform->dev); - if (ret) - goto out_unregister; - drmm_add_final_kfree(&vgem_device->drm, vgem_device); + + vgem_device = devm_drm_dev_alloc(&pdev->dev, &vgem_driver, + struct vgem_device, drm); + if (IS_ERR(vgem_device)) { + ret = PTR_ERR(vgem_device); + goto out_devres; + } + vgem_device->platform = pdev;
/* Final step: expose the device/driver to userspace */ ret = drm_dev_register(&vgem_device->drm, 0); if (ret) - goto out_put; + goto out_devres;
return 0;
-out_put: - drm_dev_put(&vgem_device->drm); - platform_device_unregister(vgem_device->platform); - return ret; +out_devres: + devres_release_group(&pdev->dev, NULL); out_unregister: - platform_device_unregister(vgem_device->platform); -out_free: - kfree(vgem_device); + platform_device_unregister(pdev); return ret; }
static void __exit vgem_exit(void) { + struct platform_device *pdev = vgem_device->platform; + drm_dev_unregister(&vgem_device->drm); - drm_dev_put(&vgem_device->drm); + devres_release_group(&pdev->dev, NULL); + platform_device_unregister(pdev); }
module_init(vgem_init);
This means we also need to slightly restructure the exit code, so that final cleanup of the drm_device is triggered by unregistering the platform device. Note that devres is both clean up when the driver is unbound (not the case for vkms, we don't bind), and also when unregistering the device (very much the case for vkms). Therefore we can rely on devres even though vkms isn't a proper platform device driver.
This also somewhat untangles the load code, since the drm and platform device setup are no longer interleaved, but two distinct steps.
v2: use devres_open/release_group so we can use devm without real hacks in the driver core or having to create an entire fake bus for testing drivers. Might want to extract this into helpers eventually, maybe as a mock_drm_dev_alloc or test_drm_dev_alloc.
Signed-off-by: Daniel Vetter daniel.vetter@intel.com Cc: Rodrigo Siqueira rodrigosiqueiramelo@gmail.com Cc: Haneen Mohammed hamohammed.sa@gmail.com Cc: Daniel Vetter daniel@ffwll.ch --- drivers/gpu/drm/vkms/vkms_drv.c | 54 ++++++++++++++++----------------- 1 file changed, 26 insertions(+), 28 deletions(-)
diff --git a/drivers/gpu/drm/vkms/vkms_drv.c b/drivers/gpu/drm/vkms/vkms_drv.c index 83dd5567de8b..0d2c6dcf73c3 100644 --- a/drivers/gpu/drm/vkms/vkms_drv.c +++ b/drivers/gpu/drm/vkms/vkms_drv.c @@ -61,9 +61,6 @@ static void vkms_release(struct drm_device *dev) { struct vkms_device *vkms = container_of(dev, struct vkms_device, drm);
- platform_device_unregister(vkms->platform); - drm_atomic_helper_shutdown(&vkms->drm); - drm_mode_config_cleanup(&vkms->drm); destroy_workqueue(vkms->output.composer_workq); }
@@ -144,30 +141,31 @@ static int vkms_modeset_init(struct vkms_device *vkmsdev) static int __init vkms_init(void) { int ret; + struct platform_device *pdev;
- vkms_device = kzalloc(sizeof(*vkms_device), GFP_KERNEL); - if (!vkms_device) - return -ENOMEM; + pdev = platform_device_register_simple(DRIVER_NAME, -1, NULL, 0); + if (IS_ERR(pdev)) + return PTR_ERR(pdev);
- vkms_device->platform = - platform_device_register_simple(DRIVER_NAME, -1, NULL, 0); - if (IS_ERR(vkms_device->platform)) { - ret = PTR_ERR(vkms_device->platform); - goto out_free; + if (!devres_open_group(&pdev->dev, NULL, GFP_KERNEL)) { + ret = -ENOMEM; + goto out_unregister; }
- ret = drm_dev_init(&vkms_device->drm, &vkms_driver, - &vkms_device->platform->dev); - if (ret) - goto out_unregister; - drmm_add_final_kfree(&vkms_device->drm, vkms_device); + vkms_device = devm_drm_dev_alloc(&pdev->dev, &vkms_driver, + struct vkms_device, drm); + if (IS_ERR(vkms_device)) { + ret = PTR_ERR(vkms_device); + goto out_devres; + } + vkms_device->platform = pdev;
ret = dma_coerce_mask_and_coherent(vkms_device->drm.dev, DMA_BIT_MASK(64));
if (ret) { DRM_ERROR("Could not initialize DMA support\n"); - goto out_put; + goto out_devres; }
vkms_device->drm.irq_enabled = true; @@ -175,39 +173,39 @@ static int __init vkms_init(void) ret = drm_vblank_init(&vkms_device->drm, 1); if (ret) { DRM_ERROR("Failed to vblank\n"); - goto out_put; + goto out_devres; }
ret = vkms_modeset_init(vkms_device); if (ret) - goto out_put; + goto out_devres;
ret = drm_dev_register(&vkms_device->drm, 0); if (ret) - goto out_put; + goto out_devres;
return 0;
-out_put: - drm_dev_put(&vkms_device->drm); - platform_device_unregister(vkms_device->platform); - return ret; +out_devres: + devres_release_group(&pdev->dev, NULL); out_unregister: - platform_device_unregister(vkms_device->platform); -out_free: - kfree(vkms_device); + platform_device_unregister(pdev); return ret; }
static void __exit vkms_exit(void) { + struct platform_device *pdev = vkms_device->platform; + if (!vkms_device) { DRM_INFO("vkms_device is NULL.\n"); return; }
drm_dev_unregister(&vkms_device->drm); - drm_dev_put(&vkms_device->drm); + drm_atomic_helper_shutdown(&vkms_device->drm); + devres_release_group(&pdev->dev, NULL); + platform_device_unregister(pdev); }
module_init(vkms_init);
Hi Daniel,
Thanks for this work.
This change works smoothly to me. However, there is a check in the vkms_exit that doesn't look very good. Please, see inline comment.
On 09/04, Daniel Vetter wrote:
I think it would be better to check vkms_device before assigning vkms_device->platform to the pdev above. I don't know if the compiler handles this, but doing the validation first seems more clear.
This means we also need to slightly restructure the exit code, so that final cleanup of the drm_device is triggered by unregistering the platform device. Note that devres is both clean up when the driver is unbound (not the case for vkms, we don't bind), and also when unregistering the device (very much the case for vkms). Therefore we can rely on devres even though vkms isn't a proper platform device driver.
This also somewhat untangles the load code, since the drm and platform device setup are no longer interleaved, but two distinct steps.
v2: use devres_open/release_group so we can use devm without real hacks in the driver core or having to create an entire fake bus for testing drivers. Might want to extract this into helpers eventually, maybe as a mock_drm_dev_alloc or test_drm_dev_alloc.
v3: Only deref vkms_device after checking it (Melissa)
Cc: Melissa Wen melissa.srw@gmail.com Signed-off-by: Daniel Vetter daniel.vetter@intel.com Cc: Rodrigo Siqueira rodrigosiqueiramelo@gmail.com Cc: Haneen Mohammed hamohammed.sa@gmail.com Cc: Daniel Vetter daniel@ffwll.ch --- drivers/gpu/drm/vkms/vkms_drv.c | 56 ++++++++++++++++----------------- 1 file changed, 28 insertions(+), 28 deletions(-)
diff --git a/drivers/gpu/drm/vkms/vkms_drv.c b/drivers/gpu/drm/vkms/vkms_drv.c index 83dd5567de8b..cb0b6230c22c 100644 --- a/drivers/gpu/drm/vkms/vkms_drv.c +++ b/drivers/gpu/drm/vkms/vkms_drv.c @@ -61,9 +61,6 @@ static void vkms_release(struct drm_device *dev) { struct vkms_device *vkms = container_of(dev, struct vkms_device, drm);
- platform_device_unregister(vkms->platform); - drm_atomic_helper_shutdown(&vkms->drm); - drm_mode_config_cleanup(&vkms->drm); destroy_workqueue(vkms->output.composer_workq); }
@@ -144,30 +141,31 @@ static int vkms_modeset_init(struct vkms_device *vkmsdev) static int __init vkms_init(void) { int ret; + struct platform_device *pdev;
- vkms_device = kzalloc(sizeof(*vkms_device), GFP_KERNEL); - if (!vkms_device) - return -ENOMEM; + pdev = platform_device_register_simple(DRIVER_NAME, -1, NULL, 0); + if (IS_ERR(pdev)) + return PTR_ERR(pdev);
- vkms_device->platform = - platform_device_register_simple(DRIVER_NAME, -1, NULL, 0); - if (IS_ERR(vkms_device->platform)) { - ret = PTR_ERR(vkms_device->platform); - goto out_free; + if (!devres_open_group(&pdev->dev, NULL, GFP_KERNEL)) { + ret = -ENOMEM; + goto out_unregister; }
- ret = drm_dev_init(&vkms_device->drm, &vkms_driver, - &vkms_device->platform->dev); - if (ret) - goto out_unregister; - drmm_add_final_kfree(&vkms_device->drm, vkms_device); + vkms_device = devm_drm_dev_alloc(&pdev->dev, &vkms_driver, + struct vkms_device, drm); + if (IS_ERR(vkms_device)) { + ret = PTR_ERR(vkms_device); + goto out_devres; + } + vkms_device->platform = pdev;
ret = dma_coerce_mask_and_coherent(vkms_device->drm.dev, DMA_BIT_MASK(64));
if (ret) { DRM_ERROR("Could not initialize DMA support\n"); - goto out_put; + goto out_devres; }
vkms_device->drm.irq_enabled = true; @@ -175,39 +173,41 @@ static int __init vkms_init(void) ret = drm_vblank_init(&vkms_device->drm, 1); if (ret) { DRM_ERROR("Failed to vblank\n"); - goto out_put; + goto out_devres; }
ret = vkms_modeset_init(vkms_device); if (ret) - goto out_put; + goto out_devres;
ret = drm_dev_register(&vkms_device->drm, 0); if (ret) - goto out_put; + goto out_devres;
return 0;
-out_put: - drm_dev_put(&vkms_device->drm); - platform_device_unregister(vkms_device->platform); - return ret; +out_devres: + devres_release_group(&pdev->dev, NULL); out_unregister: - platform_device_unregister(vkms_device->platform); -out_free: - kfree(vkms_device); + platform_device_unregister(pdev); return ret; }
static void __exit vkms_exit(void) { + struct platform_device *pdev; + if (!vkms_device) { DRM_INFO("vkms_device is NULL.\n"); return; }
+ pdev = vkms_device->platform; + drm_dev_unregister(&vkms_device->drm); - drm_dev_put(&vkms_device->drm); + drm_atomic_helper_shutdown(&vkms_device->drm); + devres_release_group(&pdev->dev, NULL); + platform_device_unregister(pdev); }
module_init(vkms_init);
Gets rid of drmm_add_final_kfree, which I want to unexport so that it stops confusion people about this transitional state of rolling drm managed memory out.
This also fixes the missing drm_dev_put in the error path of the probe code.
Signed-off-by: Daniel Vetter daniel.vetter@intel.com Cc: Hyun Kwon hyun.kwon@xilinx.com Cc: Laurent Pinchart laurent.pinchart@ideasonboard.com Cc: Michal Simek michal.simek@xilinx.com Cc: linux-arm-kernel@lists.infradead.org --- drivers/gpu/drm/xlnx/zynqmp_dpsub.c | 21 ++++----------------- 1 file changed, 4 insertions(+), 17 deletions(-)
diff --git a/drivers/gpu/drm/xlnx/zynqmp_dpsub.c b/drivers/gpu/drm/xlnx/zynqmp_dpsub.c index 26328c76305b..80b8edd20442 100644 --- a/drivers/gpu/drm/xlnx/zynqmp_dpsub.c +++ b/drivers/gpu/drm/xlnx/zynqmp_dpsub.c @@ -208,27 +208,16 @@ static int zynqmp_dpsub_probe(struct platform_device *pdev) int ret;
/* Allocate private data. */ - dpsub = kzalloc(sizeof(*dpsub), GFP_KERNEL); - if (!dpsub) - return -ENOMEM; + dpsub = devm_drm_dev_alloc(&pdev->dev, &zynqmp_dpsub_drm_driver, + struct zynqmp_dpsub, drm); + if (IS_ERR(dpsub)) + return PTR_ERR(dpsub);
dpsub->dev = &pdev->dev; platform_set_drvdata(pdev, dpsub);
dma_set_mask(dpsub->dev, DMA_BIT_MASK(ZYNQMP_DISP_MAX_DMA_BIT));
- /* - * Initialize the DRM device early, as the DRM core mandates usage of - * the managed memory helpers tied to the DRM device. - */ - ret = drm_dev_init(&dpsub->drm, &zynqmp_dpsub_drm_driver, &pdev->dev); - if (ret < 0) { - kfree(dpsub); - return ret; - } - - drmm_add_final_kfree(&dpsub->drm, dpsub); - /* Try the reserved memory. Proceed if there's none. */ of_reserved_mem_device_init(&pdev->dev);
@@ -286,8 +275,6 @@ static int zynqmp_dpsub_remove(struct platform_device *pdev) clk_disable_unprepare(dpsub->apb_clk); of_reserved_mem_device_release(&pdev->dev);
- drm_dev_put(drm); - return 0; }
Gets rid of drmm_add_final_kfree, which I want to unexport so that it stops confusion people about this transitional state of rolling drm managed memory out.
This also fixes the missing drm_dev_put in the error path of the probe code.
v2: Drop the misplaced drm_dev_put from zynqmp_dpsub_drm_init (all other paths leaked on error, this should have been in zynqmp_dpsub_probe), now that subsumed by the auto-cleanup of devm_drm_dev_alloc.
Signed-off-by: Daniel Vetter daniel.vetter@intel.com Cc: Hyun Kwon hyun.kwon@xilinx.com Cc: Laurent Pinchart laurent.pinchart@ideasonboard.com Cc: Michal Simek michal.simek@xilinx.com Cc: linux-arm-kernel@lists.infradead.org --- drivers/gpu/drm/xlnx/zynqmp_dpsub.c | 27 ++++++--------------------- 1 file changed, 6 insertions(+), 21 deletions(-)
diff --git a/drivers/gpu/drm/xlnx/zynqmp_dpsub.c b/drivers/gpu/drm/xlnx/zynqmp_dpsub.c index 26328c76305b..8e69303aad3f 100644 --- a/drivers/gpu/drm/xlnx/zynqmp_dpsub.c +++ b/drivers/gpu/drm/xlnx/zynqmp_dpsub.c @@ -111,7 +111,7 @@ static int zynqmp_dpsub_drm_init(struct zynqmp_dpsub *dpsub) /* Initialize mode config, vblank and the KMS poll helper. */ ret = drmm_mode_config_init(drm); if (ret < 0) - goto err_dev_put; + return ret;
drm->mode_config.funcs = &zynqmp_dpsub_mode_config_funcs; drm->mode_config.min_width = 0; @@ -121,7 +121,7 @@ static int zynqmp_dpsub_drm_init(struct zynqmp_dpsub *dpsub)
ret = drm_vblank_init(drm, 1); if (ret) - goto err_dev_put; + return ret;
drm->irq_enabled = 1;
@@ -154,8 +154,6 @@ static int zynqmp_dpsub_drm_init(struct zynqmp_dpsub *dpsub)
err_poll_fini: drm_kms_helper_poll_fini(drm); -err_dev_put: - drm_dev_put(drm); return ret; }
@@ -208,27 +206,16 @@ static int zynqmp_dpsub_probe(struct platform_device *pdev) int ret;
/* Allocate private data. */ - dpsub = kzalloc(sizeof(*dpsub), GFP_KERNEL); - if (!dpsub) - return -ENOMEM; + dpsub = devm_drm_dev_alloc(&pdev->dev, &zynqmp_dpsub_drm_driver, + struct zynqmp_dpsub, drm); + if (IS_ERR(dpsub)) + return PTR_ERR(dpsub);
dpsub->dev = &pdev->dev; platform_set_drvdata(pdev, dpsub);
dma_set_mask(dpsub->dev, DMA_BIT_MASK(ZYNQMP_DISP_MAX_DMA_BIT));
- /* - * Initialize the DRM device early, as the DRM core mandates usage of - * the managed memory helpers tied to the DRM device. - */ - ret = drm_dev_init(&dpsub->drm, &zynqmp_dpsub_drm_driver, &pdev->dev); - if (ret < 0) { - kfree(dpsub); - return ret; - } - - drmm_add_final_kfree(&dpsub->drm, dpsub); - /* Try the reserved memory. Proceed if there's none. */ of_reserved_mem_device_init(&pdev->dev);
@@ -286,8 +273,6 @@ static int zynqmp_dpsub_remove(struct platform_device *pdev) clk_disable_unprepare(dpsub->apb_clk); of_reserved_mem_device_release(&pdev->dev);
- drm_dev_put(drm); - return 0; }
Hi Daniel,
On Mon, Sep 07, 2020 at 01:22:25AM -0700, Daniel Vetter wrote:
Looks correct to me.
Reviewed-by: Hyun Kwon hyun.kwon@xilinx.com
Thanks!
-hyun
On Tue, Sep 08, 2020 at 12:16:00PM -0700, Hyun Kwon wrote:
Merged all patches up to this one here to drm-misc-next. -Daniel
Just some prep work before we rework the lifetime handling, which requires replacing all the drm_dev_put in selftests by something else.
v2: Don't go with a static inline, upsets the header tests and separation.
Signed-off-by: Daniel Vetter daniel.vetter@intel.com --- drivers/gpu/drm/i915/gem/selftests/huge_pages.c | 2 +- drivers/gpu/drm/i915/gem/selftests/i915_gem_context.c | 2 +- drivers/gpu/drm/i915/gem/selftests/i915_gem_dmabuf.c | 2 +- drivers/gpu/drm/i915/gem/selftests/i915_gem_object.c | 2 +- drivers/gpu/drm/i915/gem/selftests/i915_gem_phys.c | 2 +- drivers/gpu/drm/i915/gt/selftest_timeline.c | 2 +- drivers/gpu/drm/i915/selftests/i915_gem_evict.c | 2 +- drivers/gpu/drm/i915/selftests/i915_gem_gtt.c | 2 +- drivers/gpu/drm/i915/selftests/i915_request.c | 2 +- drivers/gpu/drm/i915/selftests/i915_vma.c | 2 +- drivers/gpu/drm/i915/selftests/intel_memory_region.c | 2 +- drivers/gpu/drm/i915/selftests/mock_gem_device.c | 7 ++++++- drivers/gpu/drm/i915/selftests/mock_gem_device.h | 2 ++ 13 files changed, 19 insertions(+), 12 deletions(-)
diff --git a/drivers/gpu/drm/i915/gem/selftests/huge_pages.c b/drivers/gpu/drm/i915/gem/selftests/huge_pages.c index 5daf4a2be422..1f35e71429b4 100644 --- a/drivers/gpu/drm/i915/gem/selftests/huge_pages.c +++ b/drivers/gpu/drm/i915/gem/selftests/huge_pages.c @@ -1617,7 +1617,7 @@ int i915_gem_huge_page_mock_selftests(void) out_put: i915_vm_put(&ppgtt->vm); out_unlock: - drm_dev_put(&dev_priv->drm); + mock_destroy_device(dev_priv); return err; }
diff --git a/drivers/gpu/drm/i915/gem/selftests/i915_gem_context.c b/drivers/gpu/drm/i915/gem/selftests/i915_gem_context.c index 99becb86abd3..d3f87dc4eda3 100644 --- a/drivers/gpu/drm/i915/gem/selftests/i915_gem_context.c +++ b/drivers/gpu/drm/i915/gem/selftests/i915_gem_context.c @@ -1997,7 +1997,7 @@ int i915_gem_context_mock_selftests(void)
err = i915_subtests(tests, i915);
- drm_dev_put(&i915->drm); + mock_destroy_device(i915); return err; }
diff --git a/drivers/gpu/drm/i915/gem/selftests/i915_gem_dmabuf.c b/drivers/gpu/drm/i915/gem/selftests/i915_gem_dmabuf.c index 2a52b92586b9..0845ce1ae37c 100644 --- a/drivers/gpu/drm/i915/gem/selftests/i915_gem_dmabuf.c +++ b/drivers/gpu/drm/i915/gem/selftests/i915_gem_dmabuf.c @@ -272,7 +272,7 @@ int i915_gem_dmabuf_mock_selftests(void)
err = i915_subtests(tests, i915);
- drm_dev_put(&i915->drm); + mock_destroy_device(i915); return err; }
diff --git a/drivers/gpu/drm/i915/gem/selftests/i915_gem_object.c b/drivers/gpu/drm/i915/gem/selftests/i915_gem_object.c index faa5b6d91795..bf853c40ec65 100644 --- a/drivers/gpu/drm/i915/gem/selftests/i915_gem_object.c +++ b/drivers/gpu/drm/i915/gem/selftests/i915_gem_object.c @@ -85,7 +85,7 @@ int i915_gem_object_mock_selftests(void)
err = i915_subtests(tests, i915);
- drm_dev_put(&i915->drm); + mock_destroy_device(i915); return err; }
diff --git a/drivers/gpu/drm/i915/gem/selftests/i915_gem_phys.c b/drivers/gpu/drm/i915/gem/selftests/i915_gem_phys.c index a94243dc4c5c..8cee68c6a6dc 100644 --- a/drivers/gpu/drm/i915/gem/selftests/i915_gem_phys.c +++ b/drivers/gpu/drm/i915/gem/selftests/i915_gem_phys.c @@ -73,6 +73,6 @@ int i915_gem_phys_mock_selftests(void)
err = i915_subtests(tests, i915);
- drm_dev_put(&i915->drm); + mock_destroy_device(i915); return err; } diff --git a/drivers/gpu/drm/i915/gt/selftest_timeline.c b/drivers/gpu/drm/i915/gt/selftest_timeline.c index 96d164a3841d..19c2cb166e7c 100644 --- a/drivers/gpu/drm/i915/gt/selftest_timeline.c +++ b/drivers/gpu/drm/i915/gt/selftest_timeline.c @@ -158,7 +158,7 @@ static int mock_hwsp_freelist(void *arg) __mock_hwsp_record(&state, na, NULL); kfree(state.history); err_put: - drm_dev_put(&i915->drm); + mock_destroy_device(i915); return err; }
diff --git a/drivers/gpu/drm/i915/selftests/i915_gem_evict.c b/drivers/gpu/drm/i915/selftests/i915_gem_evict.c index 028baae9631f..f88473d396f4 100644 --- a/drivers/gpu/drm/i915/selftests/i915_gem_evict.c +++ b/drivers/gpu/drm/i915/selftests/i915_gem_evict.c @@ -536,7 +536,7 @@ int i915_gem_evict_mock_selftests(void) with_intel_runtime_pm(&i915->runtime_pm, wakeref) err = i915_subtests(tests, &i915->gt);
- drm_dev_put(&i915->drm); + mock_destroy_device(i915); return err; }
diff --git a/drivers/gpu/drm/i915/selftests/i915_gem_gtt.c b/drivers/gpu/drm/i915/selftests/i915_gem_gtt.c index af8205a2bd8f..c53a222e3dec 100644 --- a/drivers/gpu/drm/i915/selftests/i915_gem_gtt.c +++ b/drivers/gpu/drm/i915/selftests/i915_gem_gtt.c @@ -1727,7 +1727,7 @@ int i915_gem_gtt_mock_selftests(void) mock_fini_ggtt(ggtt); kfree(ggtt); out_put: - drm_dev_put(&i915->drm); + mock_destroy_device(i915); return err; }
diff --git a/drivers/gpu/drm/i915/selftests/i915_request.c b/drivers/gpu/drm/i915/selftests/i915_request.c index 3092ca763789..64bbb8288249 100644 --- a/drivers/gpu/drm/i915/selftests/i915_request.c +++ b/drivers/gpu/drm/i915/selftests/i915_request.c @@ -527,7 +527,7 @@ int i915_request_mock_selftests(void) with_intel_runtime_pm(&i915->runtime_pm, wakeref) err = i915_subtests(tests, i915);
- drm_dev_put(&i915->drm); + mock_destroy_device(i915);
return err; } diff --git a/drivers/gpu/drm/i915/selftests/i915_vma.c b/drivers/gpu/drm/i915/selftests/i915_vma.c index 88c5e9acb84c..1b6125e4c1ac 100644 --- a/drivers/gpu/drm/i915/selftests/i915_vma.c +++ b/drivers/gpu/drm/i915/selftests/i915_vma.c @@ -841,7 +841,7 @@ int i915_vma_mock_selftests(void) mock_fini_ggtt(ggtt); kfree(ggtt); out_put: - drm_dev_put(&i915->drm); + mock_destroy_device(i915); return err; }
diff --git a/drivers/gpu/drm/i915/selftests/intel_memory_region.c b/drivers/gpu/drm/i915/selftests/intel_memory_region.c index 93a38a323584..334b0648e253 100644 --- a/drivers/gpu/drm/i915/selftests/intel_memory_region.c +++ b/drivers/gpu/drm/i915/selftests/intel_memory_region.c @@ -791,7 +791,7 @@ int intel_memory_region_mock_selftests(void)
intel_memory_region_put(mem); out_unref: - drm_dev_put(&i915->drm); + mock_destroy_device(i915); return err; }
diff --git a/drivers/gpu/drm/i915/selftests/mock_gem_device.c b/drivers/gpu/drm/i915/selftests/mock_gem_device.c index f127e633f7ca..fbb403edb7a0 100644 --- a/drivers/gpu/drm/i915/selftests/mock_gem_device.c +++ b/drivers/gpu/drm/i915/selftests/mock_gem_device.c @@ -224,7 +224,12 @@ struct drm_i915_private *mock_gem_device(void) intel_gt_driver_late_release(&i915->gt); intel_memory_regions_driver_release(i915); drm_mode_config_cleanup(&i915->drm); - drm_dev_put(&i915->drm); + mock_destroy_device(i915);
return NULL; } + +void mock_destroy_device(struct drm_i915_private *i915) +{ + drm_dev_put(&i915->drm); +} diff --git a/drivers/gpu/drm/i915/selftests/mock_gem_device.h b/drivers/gpu/drm/i915/selftests/mock_gem_device.h index b5dc4e394555..953cfe4fab34 100644 --- a/drivers/gpu/drm/i915/selftests/mock_gem_device.h +++ b/drivers/gpu/drm/i915/selftests/mock_gem_device.h @@ -7,4 +7,6 @@ struct drm_i915_private; struct drm_i915_private *mock_gem_device(void); void mock_device_flush(struct drm_i915_private *i915);
+void mock_destroy_device(struct drm_i915_private *i915); + #endif /* !__MOCK_GEM_DEVICE_H__ */
The big change is device_add so that device_del can auto-cleanup devres resources. This allows us to use devm_drm_dev_alloc, which removes the last user of drm_dev_init.
v2: Rebased
v3: use devres_open/release_group so we can use devm without real hacks in the driver core or having to create an entire fake bus for testing drivers. Might want to extract this into helpers eventually, maybe as a mock_drm_dev_alloc or test_drm_dev_alloc.
Signed-off-by: Daniel Vetter daniel.vetter@intel.com --- .../gpu/drm/i915/selftests/mock_gem_device.c | 42 +++++++++++-------- 1 file changed, 25 insertions(+), 17 deletions(-)
diff --git a/drivers/gpu/drm/i915/selftests/mock_gem_device.c b/drivers/gpu/drm/i915/selftests/mock_gem_device.c index fbb403edb7a0..164ad1746da9 100644 --- a/drivers/gpu/drm/i915/selftests/mock_gem_device.c +++ b/drivers/gpu/drm/i915/selftests/mock_gem_device.c @@ -128,12 +128,6 @@ struct drm_i915_private *mock_gem_device(void) pdev = kzalloc(sizeof(*pdev), GFP_KERNEL); if (!pdev) return NULL; - i915 = kzalloc(sizeof(*i915), GFP_KERNEL); - if (!i915) { - kfree(pdev); - return NULL; - } - device_initialize(&pdev->dev); pdev->class = PCI_BASE_CLASS_DISPLAY << 16; pdev->dev.release = release_dev; @@ -146,8 +140,29 @@ struct drm_i915_private *mock_gem_device(void) iommu.priv = (void *)-1; pdev->dev.iommu = &iommu; #endif + err = device_add(&pdev->dev); + if (err) { + kfree(pdev); + return NULL; + } + + if (!devres_open_group(&pdev->dev, NULL, GFP_KERNEL)) { + device_del(&pdev->dev); + return NULL; + } + + i915 = devm_drm_dev_alloc(&pdev->dev, &mock_driver, + struct drm_i915_private, drm); + if (err) { + pr_err("Failed to allocate mock GEM device: err=%d\n", err); + devres_release_group(&pdev->dev, NULL); + device_del(&pdev->dev); + + return NULL; + }
pci_set_drvdata(pdev, i915); + i915->drm.pdev = pdev;
dev_pm_domain_set(&pdev->dev, &pm_domain); pm_runtime_enable(&pdev->dev); @@ -155,16 +170,6 @@ struct drm_i915_private *mock_gem_device(void) if (pm_runtime_enabled(&pdev->dev)) WARN_ON(pm_runtime_get_sync(&pdev->dev));
- err = drm_dev_init(&i915->drm, &mock_driver, &pdev->dev); - if (err) { - pr_err("Failed to initialise mock GEM device: err=%d\n", err); - put_device(&pdev->dev); - kfree(i915); - - return NULL; - } - i915->drm.pdev = pdev; - drmm_add_final_kfree(&i915->drm, i915);
i915_params_copy(&i915->params, &i915_modparams);
@@ -231,5 +236,8 @@ struct drm_i915_private *mock_gem_device(void)
void mock_destroy_device(struct drm_i915_private *i915) { - drm_dev_put(&i915->drm); + struct device *dev = i915->drm.dev; + + devres_release_group(dev, NULL); + device_del(dev); }
Op 04-09-2020 om 16:39 schreef Daniel Vetter:
Looks sane,
For patch 7 and 8:
Reviewed-by: Maarten Lankhorst maarten.lankhorst@linux.intel.com
We can now also delete drm_dev_init, now that vkms, vgem and i915 selftests are resolved.
Signed-off-by: Daniel Vetter daniel.vetter@ffwll.ch --- drivers/gpu/drm/drm_drv.c | 41 +++------------------------------- drivers/gpu/drm/drm_internal.h | 1 + drivers/gpu/drm/drm_managed.c | 13 ----------- include/drm/drm_drv.h | 4 ---- 4 files changed, 4 insertions(+), 55 deletions(-)
diff --git a/drivers/gpu/drm/drm_drv.c b/drivers/gpu/drm/drm_drv.c index 7c1689842ec0..457ac0f82be2 100644 --- a/drivers/gpu/drm/drm_drv.c +++ b/drivers/gpu/drm/drm_drv.c @@ -573,43 +573,9 @@ static void drm_dev_init_release(struct drm_device *dev, void *res) drm_legacy_destroy_members(dev); }
-/** - * drm_dev_init - Initialise new DRM device - * @dev: DRM device - * @driver: DRM driver - * @parent: Parent device object - * - * Initialize a new DRM device. No device registration is done. - * Call drm_dev_register() to advertice the device to user space and register it - * with other core subsystems. This should be done last in the device - * initialization sequence to make sure userspace can't access an inconsistent - * state. - * - * The initial ref-count of the object is 1. Use drm_dev_get() and - * drm_dev_put() to take and drop further ref-counts. - * - * It is recommended that drivers embed &struct drm_device into their own device - * structure. - * - * Drivers that do not want to allocate their own device struct - * embedding &struct drm_device can call drm_dev_alloc() instead. For drivers - * that do embed &struct drm_device it must be placed first in the overall - * structure, and the overall structure must be allocated using kmalloc(): The - * drm core's release function unconditionally calls kfree() on the @dev pointer - * when the final reference is released. To override this behaviour, and so - * allow embedding of the drm_device inside the driver's device struct at an - * arbitrary offset, you must supply a &drm_driver.release callback and control - * the finalization explicitly. - * - * Note that drivers must call drmm_add_final_kfree() after this function has - * completed successfully. - * - * RETURNS: - * 0 on success, or error code on failure. - */ -int drm_dev_init(struct drm_device *dev, - struct drm_driver *driver, - struct device *parent) +static int drm_dev_init(struct drm_device *dev, + struct drm_driver *driver, + struct device *parent) { int ret;
@@ -689,7 +655,6 @@ int drm_dev_init(struct drm_device *dev,
return ret; } -EXPORT_SYMBOL(drm_dev_init);
static void devm_drm_dev_init_release(void *data) { diff --git a/drivers/gpu/drm/drm_internal.h b/drivers/gpu/drm/drm_internal.h index 8e01caaf95cc..b65865c630b0 100644 --- a/drivers/gpu/drm/drm_internal.h +++ b/drivers/gpu/drm/drm_internal.h @@ -95,6 +95,7 @@ void drm_minor_release(struct drm_minor *minor);
/* drm_managed.c */ void drm_managed_release(struct drm_device *dev); +void drmm_add_final_kfree(struct drm_device *dev, void *container);
/* drm_vblank.c */ static inline bool drm_vblank_passed(u64 seq, u64 ref) diff --git a/drivers/gpu/drm/drm_managed.c b/drivers/gpu/drm/drm_managed.c index c36e3d98fd71..37d7db6223be 100644 --- a/drivers/gpu/drm/drm_managed.c +++ b/drivers/gpu/drm/drm_managed.c @@ -125,18 +125,6 @@ static void add_dr(struct drm_device *dev, struct drmres *dr) dr, dr->node.name, (unsigned long) dr->node.size); }
-/** - * drmm_add_final_kfree - add release action for the final kfree() - * @dev: DRM device - * @container: pointer to the kmalloc allocation containing @dev - * - * Since the allocation containing the struct &drm_device must be allocated - * before it can be initialized with drm_dev_init() there's no way to allocate - * that memory with drmm_kmalloc(). To side-step this chicken-egg problem the - * pointer for this final kfree() must be specified by calling this function. It - * will be released in the final drm_dev_put() for @dev, after all other release - * actions installed through drmm_add_action() have been processed. - */ void drmm_add_final_kfree(struct drm_device *dev, void *container) { WARN_ON(dev->managed.final_kfree); @@ -144,7 +132,6 @@ void drmm_add_final_kfree(struct drm_device *dev, void *container) WARN_ON(dev + 1 > (struct drm_device *) (container + ksize(container))); dev->managed.final_kfree = container; } -EXPORT_SYMBOL(drmm_add_final_kfree);
int __drmm_add_action(struct drm_device *dev, drmres_release_t action, diff --git a/include/drm/drm_drv.h b/include/drm/drm_drv.h index 533c6e1a5a95..b8ce9147c9a6 100644 --- a/include/drm/drm_drv.h +++ b/include/drm/drm_drv.h @@ -591,10 +591,6 @@ struct drm_driver { int dev_priv_size; };
-int drm_dev_init(struct drm_device *dev, - struct drm_driver *driver, - struct device *parent); - void *__devm_drm_dev_alloc(struct device *parent, struct drm_driver *driver, size_t size, size_t offset);
- Need to embedded the drm_device, but for now we keep the usual pointer chasing. - No more devm_kzalloc, which fixes a lifetime issues on driver remove. - No more drm_dev_put, that's done by devm_ now.
Acked-by: Sam Ravnborg sam@ravnborg.org Cc: Eugeniy Paltsev Eugeniy.Paltsev@synopsys.com Signed-off-by: Daniel Vetter daniel.vetter@intel.com Cc: Alexey Brodkin abrodkin@synopsys.com --- drivers/gpu/drm/arc/arcpgu.h | 1 + drivers/gpu/drm/arc/arcpgu_drv.c | 33 +++++++++++++------------------- 2 files changed, 14 insertions(+), 20 deletions(-)
diff --git a/drivers/gpu/drm/arc/arcpgu.h b/drivers/gpu/drm/arc/arcpgu.h index 6aac44b953ad..cd9e932f501e 100644 --- a/drivers/gpu/drm/arc/arcpgu.h +++ b/drivers/gpu/drm/arc/arcpgu.h @@ -9,6 +9,7 @@ #define _ARCPGU_H_
struct arcpgu_drm_private { + struct drm_device drm; void __iomem *regs; struct clk *clk; struct drm_framebuffer *fb; diff --git a/drivers/gpu/drm/arc/arcpgu_drv.c b/drivers/gpu/drm/arc/arcpgu_drv.c index f164818ec477..68eb4a31c54b 100644 --- a/drivers/gpu/drm/arc/arcpgu_drv.c +++ b/drivers/gpu/drm/arc/arcpgu_drv.c @@ -42,18 +42,14 @@ static void arcpgu_setup_mode_config(struct drm_device *drm)
DEFINE_DRM_GEM_CMA_FOPS(arcpgu_drm_ops);
-static int arcpgu_load(struct drm_device *drm) +static int arcpgu_load(struct arcpgu_drm_private *arcpgu) { - struct platform_device *pdev = to_platform_device(drm->dev); - struct arcpgu_drm_private *arcpgu; + struct platform_device *pdev = to_platform_device(arcpgu->drm.dev); struct device_node *encoder_node = NULL, *endpoint_node = NULL; + struct drm_device *drm = &arcpgu->drm; struct resource *res; int ret;
- arcpgu = devm_kzalloc(&pdev->dev, sizeof(*arcpgu), GFP_KERNEL); - if (arcpgu == NULL) - return -ENOMEM; - drm->dev_private = arcpgu;
arcpgu->clk = devm_clk_get(drm->dev, "pxlclk"); @@ -162,30 +158,28 @@ static struct drm_driver arcpgu_drm_driver = {
static int arcpgu_probe(struct platform_device *pdev) { - struct drm_device *drm; + struct arcpgu_drm_private *arcpgu; int ret;
- drm = drm_dev_alloc(&arcpgu_drm_driver, &pdev->dev); - if (IS_ERR(drm)) - return PTR_ERR(drm); + arcpgu = devm_drm_dev_alloc(&pdev->dev, &arcpgu_drm_driver, + struct arcpgu_drm_private, drm); + if (IS_ERR(arcpgu)) + return PTR_ERR(arcpgu);
- ret = arcpgu_load(drm); + ret = arcpgu_load(arcpgu); if (ret) - goto err_unref; + return ret;
- ret = drm_dev_register(drm, 0); + ret = drm_dev_register(&arcpgu->drm, 0); if (ret) goto err_unload;
- drm_fbdev_generic_setup(drm, 16); + drm_fbdev_generic_setup(&arcpgu->drm, 16);
return 0;
err_unload: - arcpgu_unload(drm); - -err_unref: - drm_dev_put(drm); + arcpgu_unload(&arcpgu->drm);
return ret; } @@ -196,7 +190,6 @@ static int arcpgu_remove(struct platform_device *pdev)
drm_dev_unregister(drm); arcpgu_unload(drm); - drm_dev_put(drm);
return 0; }
On Fri, Sep 04, 2020 at 04:39:27PM +0200, Daniel Vetter wrote:
Ping for some testing/feedback/review on the arcpgu series here. I can also resend that pile again.
Thanks, Daniel
Upcasting using a container_of macro is more typesafe, faster and easier for the compiler to optimize.
Cc: Eugeniy Paltsev Eugeniy.Paltsev@synopsys.com Signed-off-by: Daniel Vetter daniel.vetter@intel.com Cc: Alexey Brodkin abrodkin@synopsys.com --- drivers/gpu/drm/arc/arcpgu.h | 2 ++ drivers/gpu/drm/arc/arcpgu_crtc.c | 4 ++-- drivers/gpu/drm/arc/arcpgu_drv.c | 4 +--- 3 files changed, 5 insertions(+), 5 deletions(-)
diff --git a/drivers/gpu/drm/arc/arcpgu.h b/drivers/gpu/drm/arc/arcpgu.h index cd9e932f501e..87821c91a00c 100644 --- a/drivers/gpu/drm/arc/arcpgu.h +++ b/drivers/gpu/drm/arc/arcpgu.h @@ -17,6 +17,8 @@ struct arcpgu_drm_private { struct drm_plane *plane; };
+#define dev_to_arcpgu(x) container_of(x, struct arcpgu_drm_private, drm) + #define crtc_to_arcpgu_priv(x) container_of(x, struct arcpgu_drm_private, crtc)
static inline void arc_pgu_write(struct arcpgu_drm_private *arcpgu, diff --git a/drivers/gpu/drm/arc/arcpgu_crtc.c b/drivers/gpu/drm/arc/arcpgu_crtc.c index be7c29cec318..ba796a216244 100644 --- a/drivers/gpu/drm/arc/arcpgu_crtc.c +++ b/drivers/gpu/drm/arc/arcpgu_crtc.c @@ -178,7 +178,7 @@ static const struct drm_plane_funcs arc_pgu_plane_funcs = {
static struct drm_plane *arc_pgu_plane_init(struct drm_device *drm) { - struct arcpgu_drm_private *arcpgu = drm->dev_private; + struct arcpgu_drm_private *arcpgu = dev_to_arcpgu(drm); struct drm_plane *plane = NULL; int ret;
@@ -202,7 +202,7 @@ static struct drm_plane *arc_pgu_plane_init(struct drm_device *drm)
int arc_pgu_setup_crtc(struct drm_device *drm) { - struct arcpgu_drm_private *arcpgu = drm->dev_private; + struct arcpgu_drm_private *arcpgu = dev_to_arcpgu(drm); struct drm_plane *primary; int ret;
diff --git a/drivers/gpu/drm/arc/arcpgu_drv.c b/drivers/gpu/drm/arc/arcpgu_drv.c index 68eb4a31c54b..c6a8deb56b0f 100644 --- a/drivers/gpu/drm/arc/arcpgu_drv.c +++ b/drivers/gpu/drm/arc/arcpgu_drv.c @@ -50,8 +50,6 @@ static int arcpgu_load(struct arcpgu_drm_private *arcpgu) struct resource *res; int ret;
- drm->dev_private = arcpgu; - arcpgu->clk = devm_clk_get(drm->dev, "pxlclk"); if (IS_ERR(arcpgu->clk)) return PTR_ERR(arcpgu->clk); @@ -120,7 +118,7 @@ static int arcpgu_show_pxlclock(struct seq_file *m, void *arg) { struct drm_info_node *node = (struct drm_info_node *)m->private; struct drm_device *drm = node->minor->dev; - struct arcpgu_drm_private *arcpgu = drm->dev_private; + struct arcpgu_drm_private *arcpgu = dev_to_arcpgu(drm); unsigned long clkrate = clk_get_rate(arcpgu->clk); unsigned long mode_clock = arcpgu->crtc.mode.crtc_clock * 1000;
On Fri, Sep 4, 2020 at 4:40 PM Daniel Vetter daniel.vetter@ffwll.ch wrote:
From the old thread Sam just confirmed he's ok with dev_to_arcpgu:
Acked-by: Sam Ravnborg sam@ravnborg.org
Cheers, Daniel
Leftover from the conversion to the generic fbdev emulation.
Cc: Eugeniy Paltsev Eugeniy.Paltsev@synopsys.com Signed-off-by: Daniel Vetter daniel.vetter@ffwll.ch Cc: Alexey Brodkin abrodkin@synopsys.com --- drivers/gpu/drm/arc/arcpgu.h | 1 - 1 file changed, 1 deletion(-)
diff --git a/drivers/gpu/drm/arc/arcpgu.h b/drivers/gpu/drm/arc/arcpgu.h index 87821c91a00c..ed77dd5dd5cb 100644 --- a/drivers/gpu/drm/arc/arcpgu.h +++ b/drivers/gpu/drm/arc/arcpgu.h @@ -12,7 +12,6 @@ struct arcpgu_drm_private { struct drm_device drm; void __iomem *regs; struct clk *clk; - struct drm_framebuffer *fb; struct drm_crtc crtc; struct drm_plane *plane; };
This is a prep step to convert arc over to the simple kms helpers, for now we just use this as an embedding container to drop all the various allocations. Big change is the removal of the various devm_kzalloc, which have the wrong lifetimes anyway.
Acked-by: Sam Ravnborg sam@ravnborg.org Cc: Eugeniy Paltsev Eugeniy.Paltsev@synopsys.com Signed-off-by: Daniel Vetter daniel.vetter@intel.com Cc: Alexey Brodkin abrodkin@synopsys.com --- drivers/gpu/drm/arc/arcpgu.h | 7 ++++--- drivers/gpu/drm/arc/arcpgu_crtc.c | 9 +++------ drivers/gpu/drm/arc/arcpgu_drv.c | 2 +- drivers/gpu/drm/arc/arcpgu_hdmi.c | 5 ++--- drivers/gpu/drm/arc/arcpgu_sim.c | 5 ++--- 5 files changed, 12 insertions(+), 16 deletions(-)
diff --git a/drivers/gpu/drm/arc/arcpgu.h b/drivers/gpu/drm/arc/arcpgu.h index ed77dd5dd5cb..52afd638a4d2 100644 --- a/drivers/gpu/drm/arc/arcpgu.h +++ b/drivers/gpu/drm/arc/arcpgu.h @@ -8,17 +8,18 @@ #ifndef _ARCPGU_H_ #define _ARCPGU_H_
+#include <drm/drm_simple_kms_helper.h> + struct arcpgu_drm_private { struct drm_device drm; void __iomem *regs; struct clk *clk; - struct drm_crtc crtc; - struct drm_plane *plane; + struct drm_simple_display_pipe pipe; };
#define dev_to_arcpgu(x) container_of(x, struct arcpgu_drm_private, drm)
-#define crtc_to_arcpgu_priv(x) container_of(x, struct arcpgu_drm_private, crtc) +#define crtc_to_arcpgu_priv(x) container_of(x, struct arcpgu_drm_private, pipe.crtc)
static inline void arc_pgu_write(struct arcpgu_drm_private *arcpgu, unsigned int reg, u32 value) diff --git a/drivers/gpu/drm/arc/arcpgu_crtc.c b/drivers/gpu/drm/arc/arcpgu_crtc.c index ba796a216244..88ba2e284fc0 100644 --- a/drivers/gpu/drm/arc/arcpgu_crtc.c +++ b/drivers/gpu/drm/arc/arcpgu_crtc.c @@ -182,9 +182,7 @@ static struct drm_plane *arc_pgu_plane_init(struct drm_device *drm) struct drm_plane *plane = NULL; int ret;
- plane = devm_kzalloc(drm->dev, sizeof(*plane), GFP_KERNEL); - if (!plane) - return ERR_PTR(-ENOMEM); + plane = &arcpgu->pipe.plane;
ret = drm_universal_plane_init(drm, plane, 0xff, &arc_pgu_plane_funcs, arc_pgu_supported_formats, @@ -195,7 +193,6 @@ static struct drm_plane *arc_pgu_plane_init(struct drm_device *drm) return ERR_PTR(ret);
drm_plane_helper_add(plane, &arc_pgu_plane_helper_funcs); - arcpgu->plane = plane;
return plane; } @@ -210,13 +207,13 @@ int arc_pgu_setup_crtc(struct drm_device *drm) if (IS_ERR(primary)) return PTR_ERR(primary);
- ret = drm_crtc_init_with_planes(drm, &arcpgu->crtc, primary, NULL, + ret = drm_crtc_init_with_planes(drm, &arcpgu->pipe.crtc, primary, NULL, &arc_pgu_crtc_funcs, NULL); if (ret) { arc_pgu_plane_destroy(primary); return ret; }
- drm_crtc_helper_add(&arcpgu->crtc, &arc_pgu_crtc_helper_funcs); + drm_crtc_helper_add(&arcpgu->pipe.crtc, &arc_pgu_crtc_helper_funcs); return 0; } diff --git a/drivers/gpu/drm/arc/arcpgu_drv.c b/drivers/gpu/drm/arc/arcpgu_drv.c index c6a8deb56b0f..9020352816fa 100644 --- a/drivers/gpu/drm/arc/arcpgu_drv.c +++ b/drivers/gpu/drm/arc/arcpgu_drv.c @@ -120,7 +120,7 @@ static int arcpgu_show_pxlclock(struct seq_file *m, void *arg) struct drm_device *drm = node->minor->dev; struct arcpgu_drm_private *arcpgu = dev_to_arcpgu(drm); unsigned long clkrate = clk_get_rate(arcpgu->clk); - unsigned long mode_clock = arcpgu->crtc.mode.crtc_clock * 1000; + unsigned long mode_clock = arcpgu->pipe.crtc.mode.crtc_clock * 1000;
seq_printf(m, "hw : %lu\n", clkrate); seq_printf(m, "mode: %lu\n", mode_clock); diff --git a/drivers/gpu/drm/arc/arcpgu_hdmi.c b/drivers/gpu/drm/arc/arcpgu_hdmi.c index 52839934f2fb..dbad2c9237fe 100644 --- a/drivers/gpu/drm/arc/arcpgu_hdmi.c +++ b/drivers/gpu/drm/arc/arcpgu_hdmi.c @@ -18,14 +18,13 @@ static struct drm_encoder_funcs arcpgu_drm_encoder_funcs = {
int arcpgu_drm_hdmi_init(struct drm_device *drm, struct device_node *np) { + struct arcpgu_drm_private *arcpgu = dev_to_arcpgu(drm); struct drm_encoder *encoder; struct drm_bridge *bridge;
int ret = 0;
- encoder = devm_kzalloc(drm->dev, sizeof(*encoder), GFP_KERNEL); - if (encoder == NULL) - return -ENOMEM; + encoder = &arcpgu->pipe.encoder;
/* Locate drm bridge from the hdmi encoder DT node */ bridge = of_drm_find_bridge(np); diff --git a/drivers/gpu/drm/arc/arcpgu_sim.c b/drivers/gpu/drm/arc/arcpgu_sim.c index 37d961668dfe..134afb9fa625 100644 --- a/drivers/gpu/drm/arc/arcpgu_sim.c +++ b/drivers/gpu/drm/arc/arcpgu_sim.c @@ -56,14 +56,13 @@ static struct drm_encoder_funcs arcpgu_drm_encoder_funcs = {
int arcpgu_drm_sim_init(struct drm_device *drm, struct device_node *np) { + struct arcpgu_drm_private *arcpgu = dev_to_arcpgu(drm); struct arcpgu_drm_connector *arcpgu_connector; struct drm_encoder *encoder; struct drm_connector *connector; int ret;
- encoder = devm_kzalloc(drm->dev, sizeof(*encoder), GFP_KERNEL); - if (encoder == NULL) - return -ENOMEM; + encoder = &arcpgu->pipe.encoder;
encoder->possible_crtcs = 1; encoder->possible_clones = 0;
Removes the last devm_kzalloc, which means we're now prepared to use drmm_mode_config_cleanup!
Acked-by: Sam Ravnborg sam@ravnborg.org Cc: Eugeniy Paltsev Eugeniy.Paltsev@synopsys.com Signed-off-by: Daniel Vetter daniel.vetter@intel.com Cc: Alexey Brodkin abrodkin@synopsys.com --- drivers/gpu/drm/arc/arcpgu.h | 1 + drivers/gpu/drm/arc/arcpgu_sim.c | 14 +------------- 2 files changed, 2 insertions(+), 13 deletions(-)
diff --git a/drivers/gpu/drm/arc/arcpgu.h b/drivers/gpu/drm/arc/arcpgu.h index 52afd638a4d2..c52cdd2274e1 100644 --- a/drivers/gpu/drm/arc/arcpgu.h +++ b/drivers/gpu/drm/arc/arcpgu.h @@ -15,6 +15,7 @@ struct arcpgu_drm_private { void __iomem *regs; struct clk *clk; struct drm_simple_display_pipe pipe; + struct drm_connector sim_conn; };
#define dev_to_arcpgu(x) container_of(x, struct arcpgu_drm_private, drm) diff --git a/drivers/gpu/drm/arc/arcpgu_sim.c b/drivers/gpu/drm/arc/arcpgu_sim.c index 134afb9fa625..e42fe5d05a3d 100644 --- a/drivers/gpu/drm/arc/arcpgu_sim.c +++ b/drivers/gpu/drm/arc/arcpgu_sim.c @@ -18,10 +18,6 @@ #define YRES_MAX 8192
-struct arcpgu_drm_connector { - struct drm_connector connector; -}; - static int arcpgu_drm_connector_get_modes(struct drm_connector *connector) { int count; @@ -57,7 +53,6 @@ static struct drm_encoder_funcs arcpgu_drm_encoder_funcs = { int arcpgu_drm_sim_init(struct drm_device *drm, struct device_node *np) { struct arcpgu_drm_private *arcpgu = dev_to_arcpgu(drm); - struct arcpgu_drm_connector *arcpgu_connector; struct drm_encoder *encoder; struct drm_connector *connector; int ret; @@ -72,14 +67,7 @@ int arcpgu_drm_sim_init(struct drm_device *drm, struct device_node *np) if (ret) return ret;
- arcpgu_connector = devm_kzalloc(drm->dev, sizeof(*arcpgu_connector), - GFP_KERNEL); - if (!arcpgu_connector) { - ret = -ENOMEM; - goto error_encoder_cleanup; - } - - connector = &arcpgu_connector->connector; + connector = &arcpgu->sim_conn; drm_connector_helper_add(connector, &arcpgu_drm_connector_helper_funcs);
ret = drm_connector_init(drm, connector, &arcpgu_drm_connector_funcs,
drm_connector_register does nothing before drm_dev_register(), it is meant for hotpluggable connectors only. Same for the unregister side.
Acked-by: Sam Ravnborg sam@ravnborg.org Cc: Eugeniy Paltsev Eugeniy.Paltsev@synopsys.com Signed-off-by: Daniel Vetter daniel.vetter@ffwll.ch Cc: Alexey Brodkin abrodkin@synopsys.com --- drivers/gpu/drm/arc/arcpgu_sim.c | 2 -- 1 file changed, 2 deletions(-)
diff --git a/drivers/gpu/drm/arc/arcpgu_sim.c b/drivers/gpu/drm/arc/arcpgu_sim.c index e42fe5d05a3d..3772df1647aa 100644 --- a/drivers/gpu/drm/arc/arcpgu_sim.c +++ b/drivers/gpu/drm/arc/arcpgu_sim.c @@ -29,7 +29,6 @@ static int arcpgu_drm_connector_get_modes(struct drm_connector *connector)
static void arcpgu_drm_connector_destroy(struct drm_connector *connector) { - drm_connector_unregister(connector); drm_connector_cleanup(connector); }
@@ -80,7 +79,6 @@ int arcpgu_drm_sim_init(struct drm_device *drm, struct device_node *np) ret = drm_connector_attach_encoder(connector, encoder); if (ret < 0) { dev_err(drm->dev, "could not attach connector to encoder\n"); - drm_connector_unregister(connector); goto error_connector_cleanup; }
With autocleanup through drm_device management we can delete all the code. Possible now that there's no confusion against devm_kzalloc'ed structures anymore.
I inlined arcpgu_setup_mode_config because it's tiny and the newly needed return value handling would have been more ...
Acked-by: Sam Ravnborg sam@ravnborg.org Cc: Eugeniy Paltsev Eugeniy.Paltsev@synopsys.com Signed-off-by: Daniel Vetter daniel.vetter@intel.com Cc: Alexey Brodkin abrodkin@synopsys.com --- drivers/gpu/drm/arc/arcpgu_crtc.c | 4 +--- drivers/gpu/drm/arc/arcpgu_drv.c | 21 +++++++++------------ drivers/gpu/drm/arc/arcpgu_hdmi.c | 6 +----- drivers/gpu/drm/arc/arcpgu_sim.c | 11 ++--------- 4 files changed, 13 insertions(+), 29 deletions(-)
diff --git a/drivers/gpu/drm/arc/arcpgu_crtc.c b/drivers/gpu/drm/arc/arcpgu_crtc.c index 88ba2e284fc0..72719556debb 100644 --- a/drivers/gpu/drm/arc/arcpgu_crtc.c +++ b/drivers/gpu/drm/arc/arcpgu_crtc.c @@ -209,10 +209,8 @@ int arc_pgu_setup_crtc(struct drm_device *drm)
ret = drm_crtc_init_with_planes(drm, &arcpgu->pipe.crtc, primary, NULL, &arc_pgu_crtc_funcs, NULL); - if (ret) { - arc_pgu_plane_destroy(primary); + if (ret) return ret; - }
drm_crtc_helper_add(&arcpgu->pipe.crtc, &arc_pgu_crtc_helper_funcs); return 0; diff --git a/drivers/gpu/drm/arc/arcpgu_drv.c b/drivers/gpu/drm/arc/arcpgu_drv.c index 9020352816fa..6349e9dc770e 100644 --- a/drivers/gpu/drm/arc/arcpgu_drv.c +++ b/drivers/gpu/drm/arc/arcpgu_drv.c @@ -30,16 +30,6 @@ static const struct drm_mode_config_funcs arcpgu_drm_modecfg_funcs = { .atomic_commit = drm_atomic_helper_commit, };
-static void arcpgu_setup_mode_config(struct drm_device *drm) -{ - drm_mode_config_init(drm); - drm->mode_config.min_width = 0; - drm->mode_config.min_height = 0; - drm->mode_config.max_width = 1920; - drm->mode_config.max_height = 1080; - drm->mode_config.funcs = &arcpgu_drm_modecfg_funcs; -} - DEFINE_DRM_GEM_CMA_FOPS(arcpgu_drm_ops);
static int arcpgu_load(struct arcpgu_drm_private *arcpgu) @@ -54,7 +44,15 @@ static int arcpgu_load(struct arcpgu_drm_private *arcpgu) if (IS_ERR(arcpgu->clk)) return PTR_ERR(arcpgu->clk);
- arcpgu_setup_mode_config(drm); + ret = drmm_mode_config_init(drm); + if (ret) + return ret; + + drm->mode_config.min_width = 0; + drm->mode_config.min_height = 0; + drm->mode_config.max_width = 1920; + drm->mode_config.max_height = 1080; + drm->mode_config.funcs = &arcpgu_drm_modecfg_funcs;
res = platform_get_resource(pdev, IORESOURCE_MEM, 0); arcpgu->regs = devm_ioremap_resource(&pdev->dev, res); @@ -108,7 +106,6 @@ static int arcpgu_unload(struct drm_device *drm) { drm_kms_helper_poll_fini(drm); drm_atomic_helper_shutdown(drm); - drm_mode_config_cleanup(drm);
return 0; } diff --git a/drivers/gpu/drm/arc/arcpgu_hdmi.c b/drivers/gpu/drm/arc/arcpgu_hdmi.c index dbad2c9237fe..925d6d31bb78 100644 --- a/drivers/gpu/drm/arc/arcpgu_hdmi.c +++ b/drivers/gpu/drm/arc/arcpgu_hdmi.c @@ -39,9 +39,5 @@ int arcpgu_drm_hdmi_init(struct drm_device *drm, struct device_node *np) return ret;
/* Link drm_bridge to encoder */ - ret = drm_bridge_attach(encoder, bridge, NULL, 0); - if (ret) - drm_encoder_cleanup(encoder); - - return ret; + return drm_bridge_attach(encoder, bridge, NULL, 0); } diff --git a/drivers/gpu/drm/arc/arcpgu_sim.c b/drivers/gpu/drm/arc/arcpgu_sim.c index 3772df1647aa..afc34f8b4de0 100644 --- a/drivers/gpu/drm/arc/arcpgu_sim.c +++ b/drivers/gpu/drm/arc/arcpgu_sim.c @@ -73,21 +73,14 @@ int arcpgu_drm_sim_init(struct drm_device *drm, struct device_node *np) DRM_MODE_CONNECTOR_VIRTUAL); if (ret < 0) { dev_err(drm->dev, "failed to initialize drm connector\n"); - goto error_encoder_cleanup; + return ret; }
ret = drm_connector_attach_encoder(connector, encoder); if (ret < 0) { dev_err(drm->dev, "could not attach connector to encoder\n"); - goto error_connector_cleanup; + return ret; }
return 0; - -error_connector_cleanup: - drm_connector_cleanup(connector); - -error_encoder_cleanup: - drm_encoder_cleanup(encoder); - return ret; }
Simple pipe helpers only have an enable and disable hook, no more mode_set_nofb. Call it from our enable hook to align with that conversions.
Atomic helpers always call mode_set_nofb and enable together, so there's no functional change here.
Acked-by: Sam Ravnborg sam@ravnborg.org Cc: Eugeniy Paltsev Eugeniy.Paltsev@synopsys.com Signed-off-by: Daniel Vetter daniel.vetter@intel.com Cc: Alexey Brodkin abrodkin@synopsys.com --- drivers/gpu/drm/arc/arcpgu_crtc.c | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-)
diff --git a/drivers/gpu/drm/arc/arcpgu_crtc.c b/drivers/gpu/drm/arc/arcpgu_crtc.c index 72719556debb..c7769edeefdf 100644 --- a/drivers/gpu/drm/arc/arcpgu_crtc.c +++ b/drivers/gpu/drm/arc/arcpgu_crtc.c @@ -73,10 +73,9 @@ static enum drm_mode_status arc_pgu_crtc_mode_valid(struct drm_crtc *crtc, return MODE_NOCLOCK; }
-static void arc_pgu_crtc_mode_set_nofb(struct drm_crtc *crtc) +static void arc_pgu_mode_set(struct arcpgu_drm_private *arcpgu) { - struct arcpgu_drm_private *arcpgu = crtc_to_arcpgu_priv(crtc); - struct drm_display_mode *m = &crtc->state->adjusted_mode; + struct drm_display_mode *m = &arcpgu->pipe.crtc.state->adjusted_mode; u32 val;
arc_pgu_write(arcpgu, ARCPGU_REG_FMT, @@ -110,7 +109,7 @@ static void arc_pgu_crtc_mode_set_nofb(struct drm_crtc *crtc) arc_pgu_write(arcpgu, ARCPGU_REG_STRIDE, 0); arc_pgu_write(arcpgu, ARCPGU_REG_START_SET, 1);
- arc_pgu_set_pxl_fmt(crtc); + arc_pgu_set_pxl_fmt(&arcpgu->pipe.crtc);
clk_set_rate(arcpgu->clk, m->crtc_clock * 1000); } @@ -120,6 +119,8 @@ static void arc_pgu_crtc_atomic_enable(struct drm_crtc *crtc, { struct arcpgu_drm_private *arcpgu = crtc_to_arcpgu_priv(crtc);
+ arc_pgu_mode_set(arcpgu); + clk_prepare_enable(arcpgu->clk); arc_pgu_write(arcpgu, ARCPGU_REG_CTRL, arc_pgu_read(arcpgu, ARCPGU_REG_CTRL) | @@ -139,7 +140,6 @@ static void arc_pgu_crtc_atomic_disable(struct drm_crtc *crtc,
static const struct drm_crtc_helper_funcs arc_pgu_crtc_helper_funcs = { .mode_valid = arc_pgu_crtc_mode_valid, - .mode_set_nofb = arc_pgu_crtc_mode_set_nofb, .atomic_enable = arc_pgu_crtc_atomic_enable, .atomic_disable = arc_pgu_crtc_atomic_disable, };
Really straighforward, only slight issue is that the sim connector is created after the pipe is set up, so can't use the helpers perfectly yet. Subsequent patches will fix that.
Aside from lots of deleting code no functional changes in here.
v2: Delete now unused crtc funcs (0day)
v3: Move endcoder setup removal to right patch (Sam)
Cc: Sam Ravnborg sam@ravnborg.org Acked-by: Sam Ravnborg sam@ravnborg.org Cc: Eugeniy Paltsev Eugeniy.Paltsev@synopsys.com Signed-off-by: Daniel Vetter daniel.vetter@intel.com Cc: Alexey Brodkin abrodkin@synopsys.com --- drivers/gpu/drm/arc/arcpgu.h | 4 +- drivers/gpu/drm/arc/arcpgu_crtc.c | 111 ++++++++---------------------- drivers/gpu/drm/arc/arcpgu_drv.c | 2 +- drivers/gpu/drm/arc/arcpgu_hdmi.c | 18 +---- drivers/gpu/drm/arc/arcpgu_sim.c | 12 ---- 5 files changed, 31 insertions(+), 116 deletions(-)
diff --git a/drivers/gpu/drm/arc/arcpgu.h b/drivers/gpu/drm/arc/arcpgu.h index c52cdd2274e1..b5c699d14f27 100644 --- a/drivers/gpu/drm/arc/arcpgu.h +++ b/drivers/gpu/drm/arc/arcpgu.h @@ -20,7 +20,7 @@ struct arcpgu_drm_private {
#define dev_to_arcpgu(x) container_of(x, struct arcpgu_drm_private, drm)
-#define crtc_to_arcpgu_priv(x) container_of(x, struct arcpgu_drm_private, pipe.crtc) +#define pipe_to_arcpgu_priv(x) container_of(x, struct arcpgu_drm_private, pipe)
static inline void arc_pgu_write(struct arcpgu_drm_private *arcpgu, unsigned int reg, u32 value) @@ -34,7 +34,7 @@ static inline u32 arc_pgu_read(struct arcpgu_drm_private *arcpgu, return ioread32(arcpgu->regs + reg); }
-int arc_pgu_setup_crtc(struct drm_device *dev); +int arc_pgu_setup_pipe(struct drm_device *dev); int arcpgu_drm_hdmi_init(struct drm_device *drm, struct device_node *np); int arcpgu_drm_sim_init(struct drm_device *drm, struct device_node *np);
diff --git a/drivers/gpu/drm/arc/arcpgu_crtc.c b/drivers/gpu/drm/arc/arcpgu_crtc.c index c7769edeefdf..ef7dca789868 100644 --- a/drivers/gpu/drm/arc/arcpgu_crtc.c +++ b/drivers/gpu/drm/arc/arcpgu_crtc.c @@ -25,10 +25,9 @@ static const u32 arc_pgu_supported_formats[] = { DRM_FORMAT_ARGB8888, };
-static void arc_pgu_set_pxl_fmt(struct drm_crtc *crtc) +static void arc_pgu_set_pxl_fmt(struct arcpgu_drm_private *arcpgu) { - struct arcpgu_drm_private *arcpgu = crtc_to_arcpgu_priv(crtc); - const struct drm_framebuffer *fb = crtc->primary->state->fb; + const struct drm_framebuffer *fb = arcpgu->pipe.plane.state->fb; uint32_t pixel_format = fb->format->format; u32 format = DRM_FORMAT_INVALID; int i; @@ -50,19 +49,10 @@ static void arc_pgu_set_pxl_fmt(struct drm_crtc *crtc) arc_pgu_write(arcpgu, ARCPGU_REG_CTRL, reg_ctrl); }
-static const struct drm_crtc_funcs arc_pgu_crtc_funcs = { - .destroy = drm_crtc_cleanup, - .set_config = drm_atomic_helper_set_config, - .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, -}; - -static enum drm_mode_status arc_pgu_crtc_mode_valid(struct drm_crtc *crtc, - const struct drm_display_mode *mode) +static enum drm_mode_status arc_pgu_mode_valid(struct drm_simple_display_pipe *pipe, + const struct drm_display_mode *mode) { - struct arcpgu_drm_private *arcpgu = crtc_to_arcpgu_priv(crtc); + struct arcpgu_drm_private *arcpgu = pipe_to_arcpgu_priv(pipe); long rate, clk_rate = mode->clock * 1000; long diff = clk_rate / 200; /* +-0.5% allowed by HDMI spec */
@@ -109,15 +99,16 @@ static void arc_pgu_mode_set(struct arcpgu_drm_private *arcpgu) arc_pgu_write(arcpgu, ARCPGU_REG_STRIDE, 0); arc_pgu_write(arcpgu, ARCPGU_REG_START_SET, 1);
- arc_pgu_set_pxl_fmt(&arcpgu->pipe.crtc); + arc_pgu_set_pxl_fmt(arcpgu);
clk_set_rate(arcpgu->clk, m->crtc_clock * 1000); }
-static void arc_pgu_crtc_atomic_enable(struct drm_crtc *crtc, - struct drm_crtc_state *old_state) +static void arc_pgu_enable(struct drm_simple_display_pipe *pipe, + struct drm_crtc_state *crtc_state, + struct drm_plane_state *plane_state) { - struct arcpgu_drm_private *arcpgu = crtc_to_arcpgu_priv(crtc); + struct arcpgu_drm_private *arcpgu = pipe_to_arcpgu_priv(pipe);
arc_pgu_mode_set(arcpgu);
@@ -127,10 +118,9 @@ static void arc_pgu_crtc_atomic_enable(struct drm_crtc *crtc, ARCPGU_CTRL_ENABLE_MASK); }
-static void arc_pgu_crtc_atomic_disable(struct drm_crtc *crtc, - struct drm_crtc_state *old_state) +static void arc_pgu_disable(struct drm_simple_display_pipe *pipe) { - struct arcpgu_drm_private *arcpgu = crtc_to_arcpgu_priv(crtc); + struct arcpgu_drm_private *arcpgu = pipe_to_arcpgu_priv(pipe);
clk_disable_unprepare(arcpgu->clk); arc_pgu_write(arcpgu, ARCPGU_REG_CTRL, @@ -138,80 +128,33 @@ static void arc_pgu_crtc_atomic_disable(struct drm_crtc *crtc, ~ARCPGU_CTRL_ENABLE_MASK); }
-static const struct drm_crtc_helper_funcs arc_pgu_crtc_helper_funcs = { - .mode_valid = arc_pgu_crtc_mode_valid, - .atomic_enable = arc_pgu_crtc_atomic_enable, - .atomic_disable = arc_pgu_crtc_atomic_disable, -}; - -static void arc_pgu_plane_atomic_update(struct drm_plane *plane, - struct drm_plane_state *state) +static void arc_pgu_update(struct drm_simple_display_pipe *pipe, + struct drm_plane_state *state) { struct arcpgu_drm_private *arcpgu; struct drm_gem_cma_object *gem;
- if (!plane->state->crtc || !plane->state->fb) + if (!pipe->plane.state->crtc || !pipe->plane.state->fb) return;
- arcpgu = crtc_to_arcpgu_priv(plane->state->crtc); - gem = drm_fb_cma_get_gem_obj(plane->state->fb, 0); + arcpgu = pipe_to_arcpgu_priv(pipe); + gem = drm_fb_cma_get_gem_obj(pipe->plane.state->fb, 0); arc_pgu_write(arcpgu, ARCPGU_REG_BUF0_ADDR, gem->paddr); }
-static const struct drm_plane_helper_funcs arc_pgu_plane_helper_funcs = { - .atomic_update = arc_pgu_plane_atomic_update, -}; - -static void arc_pgu_plane_destroy(struct drm_plane *plane) -{ - drm_plane_cleanup(plane); -} - -static const struct drm_plane_funcs arc_pgu_plane_funcs = { - .update_plane = drm_atomic_helper_update_plane, - .disable_plane = drm_atomic_helper_disable_plane, - .destroy = arc_pgu_plane_destroy, - .reset = drm_atomic_helper_plane_reset, - .atomic_duplicate_state = drm_atomic_helper_plane_duplicate_state, - .atomic_destroy_state = drm_atomic_helper_plane_destroy_state, +static const struct drm_simple_display_pipe_funcs arc_pgu_pipe_funcs = { + .update = arc_pgu_update, + .mode_valid = arc_pgu_mode_valid, + .enable = arc_pgu_enable, + .disable = arc_pgu_disable, };
-static struct drm_plane *arc_pgu_plane_init(struct drm_device *drm) +int arc_pgu_setup_pipe(struct drm_device *drm) { struct arcpgu_drm_private *arcpgu = dev_to_arcpgu(drm); - struct drm_plane *plane = NULL; - int ret; - - plane = &arcpgu->pipe.plane; - - ret = drm_universal_plane_init(drm, plane, 0xff, &arc_pgu_plane_funcs, - arc_pgu_supported_formats, - ARRAY_SIZE(arc_pgu_supported_formats), - NULL, - DRM_PLANE_TYPE_PRIMARY, NULL); - if (ret) - return ERR_PTR(ret); - - drm_plane_helper_add(plane, &arc_pgu_plane_helper_funcs); - - return plane; -} - -int arc_pgu_setup_crtc(struct drm_device *drm) -{ - struct arcpgu_drm_private *arcpgu = dev_to_arcpgu(drm); - struct drm_plane *primary; - int ret; - - primary = arc_pgu_plane_init(drm); - if (IS_ERR(primary)) - return PTR_ERR(primary); - - ret = drm_crtc_init_with_planes(drm, &arcpgu->pipe.crtc, primary, NULL, - &arc_pgu_crtc_funcs, NULL); - if (ret) - return ret;
- drm_crtc_helper_add(&arcpgu->pipe.crtc, &arc_pgu_crtc_helper_funcs); - return 0; + return drm_simple_display_pipe_init(drm, &arcpgu->pipe, &arc_pgu_pipe_funcs, + arc_pgu_supported_formats, + ARRAY_SIZE(arc_pgu_supported_formats), + NULL, NULL); } diff --git a/drivers/gpu/drm/arc/arcpgu_drv.c b/drivers/gpu/drm/arc/arcpgu_drv.c index 6349e9dc770e..222ab28efbd0 100644 --- a/drivers/gpu/drm/arc/arcpgu_drv.c +++ b/drivers/gpu/drm/arc/arcpgu_drv.c @@ -70,7 +70,7 @@ static int arcpgu_load(struct arcpgu_drm_private *arcpgu) if (dma_set_mask_and_coherent(drm->dev, DMA_BIT_MASK(32))) return -ENODEV;
- if (arc_pgu_setup_crtc(drm) < 0) + if (arc_pgu_setup_pipe(drm) < 0) return -ENODEV;
/* diff --git a/drivers/gpu/drm/arc/arcpgu_hdmi.c b/drivers/gpu/drm/arc/arcpgu_hdmi.c index 925d6d31bb78..d430af686cbc 100644 --- a/drivers/gpu/drm/arc/arcpgu_hdmi.c +++ b/drivers/gpu/drm/arc/arcpgu_hdmi.c @@ -12,32 +12,16 @@
#include "arcpgu.h"
-static struct drm_encoder_funcs arcpgu_drm_encoder_funcs = { - .destroy = drm_encoder_cleanup, -}; - int arcpgu_drm_hdmi_init(struct drm_device *drm, struct device_node *np) { struct arcpgu_drm_private *arcpgu = dev_to_arcpgu(drm); - struct drm_encoder *encoder; struct drm_bridge *bridge;
- int ret = 0; - - encoder = &arcpgu->pipe.encoder; - /* Locate drm bridge from the hdmi encoder DT node */ bridge = of_drm_find_bridge(np); if (!bridge) return -EPROBE_DEFER;
- encoder->possible_crtcs = 1; - encoder->possible_clones = 0; - ret = drm_encoder_init(drm, encoder, &arcpgu_drm_encoder_funcs, - DRM_MODE_ENCODER_TMDS, NULL); - if (ret) - return ret; - /* Link drm_bridge to encoder */ - return drm_bridge_attach(encoder, bridge, NULL, 0); + return drm_simple_display_pipe_attach_bridge(&arcpgu->pipe, bridge); } diff --git a/drivers/gpu/drm/arc/arcpgu_sim.c b/drivers/gpu/drm/arc/arcpgu_sim.c index afc34f8b4de0..1a63f0868504 100644 --- a/drivers/gpu/drm/arc/arcpgu_sim.c +++ b/drivers/gpu/drm/arc/arcpgu_sim.c @@ -45,10 +45,6 @@ static const struct drm_connector_funcs arcpgu_drm_connector_funcs = { .atomic_destroy_state = drm_atomic_helper_connector_destroy_state, };
-static struct drm_encoder_funcs arcpgu_drm_encoder_funcs = { - .destroy = drm_encoder_cleanup, -}; - int arcpgu_drm_sim_init(struct drm_device *drm, struct device_node *np) { struct arcpgu_drm_private *arcpgu = dev_to_arcpgu(drm); @@ -58,14 +54,6 @@ int arcpgu_drm_sim_init(struct drm_device *drm, struct device_node *np)
encoder = &arcpgu->pipe.encoder;
- encoder->possible_crtcs = 1; - encoder->possible_clones = 0; - - ret = drm_encoder_init(drm, encoder, &arcpgu_drm_encoder_funcs, - DRM_MODE_ENCODER_VIRTUAL, NULL); - if (ret) - return ret; - connector = &arcpgu->sim_conn; drm_connector_helper_add(connector, &arcpgu_drm_connector_helper_funcs);
It's redundant, drm core guarantees that state->fb is set iff state->crtc is set.
v2: I had a misconception about simple helpers here and thought they filter this out. They don't. Issue reported by Eugeniy.
Cc: Eugeniy Paltsev Eugeniy.Paltsev@synopsys.com Signed-off-by: Daniel Vetter daniel.vetter@intel.com Cc: Alexey Brodkin abrodkin@synopsys.com --- drivers/gpu/drm/arc/arcpgu_crtc.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/drivers/gpu/drm/arc/arcpgu_crtc.c b/drivers/gpu/drm/arc/arcpgu_crtc.c index ef7dca789868..30fbb3052bc7 100644 --- a/drivers/gpu/drm/arc/arcpgu_crtc.c +++ b/drivers/gpu/drm/arc/arcpgu_crtc.c @@ -134,7 +134,7 @@ static void arc_pgu_update(struct drm_simple_display_pipe *pipe, struct arcpgu_drm_private *arcpgu; struct drm_gem_cma_object *gem;
- if (!pipe->plane.state->crtc || !pipe->plane.state->fb) + if (!pipe->plane.state->fb) return;
arcpgu = pipe_to_arcpgu_priv(pipe);
Really not big anymore.
Note that we no longer clamp all errors to ENODEV, highlighted by Sam.
v2: Fixup update function, bug reported by Eugeniy
v3: Delete now unused crtc funcs (0day)
v4: Move encoder removal to right patch (Sam).
Cc: Eugeniy Paltsev Eugeniy.Paltsev@synopsys.com Signed-off-by: Daniel Vetter daniel.vetter@intel.com Cc: Sam Ravnborg sam@ravnborg.org Cc: Alexey Brodkin abrodkin@synopsys.com --- drivers/gpu/drm/arc/Makefile | 2 +- drivers/gpu/drm/arc/arcpgu.h | 1 - drivers/gpu/drm/arc/arcpgu_crtc.c | 160 ------------------------------ drivers/gpu/drm/arc/arcpgu_drv.c | 141 +++++++++++++++++++++++++- 4 files changed, 140 insertions(+), 164 deletions(-) delete mode 100644 drivers/gpu/drm/arc/arcpgu_crtc.c
diff --git a/drivers/gpu/drm/arc/Makefile b/drivers/gpu/drm/arc/Makefile index c7028b7427b3..c686e0287a71 100644 --- a/drivers/gpu/drm/arc/Makefile +++ b/drivers/gpu/drm/arc/Makefile @@ -1,3 +1,3 @@ # SPDX-License-Identifier: GPL-2.0-only -arcpgu-y := arcpgu_crtc.o arcpgu_hdmi.o arcpgu_sim.o arcpgu_drv.o +arcpgu-y := arcpgu_hdmi.o arcpgu_sim.o arcpgu_drv.o obj-$(CONFIG_DRM_ARCPGU) += arcpgu.o diff --git a/drivers/gpu/drm/arc/arcpgu.h b/drivers/gpu/drm/arc/arcpgu.h index b5c699d14f27..cee2448a07d6 100644 --- a/drivers/gpu/drm/arc/arcpgu.h +++ b/drivers/gpu/drm/arc/arcpgu.h @@ -34,7 +34,6 @@ static inline u32 arc_pgu_read(struct arcpgu_drm_private *arcpgu, return ioread32(arcpgu->regs + reg); }
-int arc_pgu_setup_pipe(struct drm_device *dev); int arcpgu_drm_hdmi_init(struct drm_device *drm, struct device_node *np); int arcpgu_drm_sim_init(struct drm_device *drm, struct device_node *np);
diff --git a/drivers/gpu/drm/arc/arcpgu_crtc.c b/drivers/gpu/drm/arc/arcpgu_crtc.c deleted file mode 100644 index 30fbb3052bc7..000000000000 --- a/drivers/gpu/drm/arc/arcpgu_crtc.c +++ /dev/null @@ -1,160 +0,0 @@ -// SPDX-License-Identifier: GPL-2.0-only -/* - * ARC PGU DRM driver. - * - * Copyright (C) 2016 Synopsys, Inc. (www.synopsys.com) - */ - -#include <drm/drm_atomic_helper.h> -#include <drm/drm_device.h> -#include <drm/drm_fb_cma_helper.h> -#include <drm/drm_gem_cma_helper.h> -#include <drm/drm_plane_helper.h> -#include <drm/drm_probe_helper.h> -#include <linux/clk.h> -#include <linux/platform_data/simplefb.h> - -#include "arcpgu.h" -#include "arcpgu_regs.h" - -#define ENCODE_PGU_XY(x, y) ((((x) - 1) << 16) | ((y) - 1)) - -static const u32 arc_pgu_supported_formats[] = { - DRM_FORMAT_RGB565, - DRM_FORMAT_XRGB8888, - DRM_FORMAT_ARGB8888, -}; - -static void arc_pgu_set_pxl_fmt(struct arcpgu_drm_private *arcpgu) -{ - const struct drm_framebuffer *fb = arcpgu->pipe.plane.state->fb; - uint32_t pixel_format = fb->format->format; - u32 format = DRM_FORMAT_INVALID; - int i; - u32 reg_ctrl; - - for (i = 0; i < ARRAY_SIZE(arc_pgu_supported_formats); i++) { - if (arc_pgu_supported_formats[i] == pixel_format) - format = arc_pgu_supported_formats[i]; - } - - if (WARN_ON(format == DRM_FORMAT_INVALID)) - return; - - reg_ctrl = arc_pgu_read(arcpgu, ARCPGU_REG_CTRL); - if (format == DRM_FORMAT_RGB565) - reg_ctrl &= ~ARCPGU_MODE_XRGB8888; - else - reg_ctrl |= ARCPGU_MODE_XRGB8888; - arc_pgu_write(arcpgu, ARCPGU_REG_CTRL, reg_ctrl); -} - -static enum drm_mode_status arc_pgu_mode_valid(struct drm_simple_display_pipe *pipe, - const struct drm_display_mode *mode) -{ - struct arcpgu_drm_private *arcpgu = pipe_to_arcpgu_priv(pipe); - long rate, clk_rate = mode->clock * 1000; - long diff = clk_rate / 200; /* +-0.5% allowed by HDMI spec */ - - rate = clk_round_rate(arcpgu->clk, clk_rate); - if ((max(rate, clk_rate) - min(rate, clk_rate) < diff) && (rate > 0)) - return MODE_OK; - - return MODE_NOCLOCK; -} - -static void arc_pgu_mode_set(struct arcpgu_drm_private *arcpgu) -{ - struct drm_display_mode *m = &arcpgu->pipe.crtc.state->adjusted_mode; - u32 val; - - arc_pgu_write(arcpgu, ARCPGU_REG_FMT, - ENCODE_PGU_XY(m->crtc_htotal, m->crtc_vtotal)); - - arc_pgu_write(arcpgu, ARCPGU_REG_HSYNC, - ENCODE_PGU_XY(m->crtc_hsync_start - m->crtc_hdisplay, - m->crtc_hsync_end - m->crtc_hdisplay)); - - arc_pgu_write(arcpgu, ARCPGU_REG_VSYNC, - ENCODE_PGU_XY(m->crtc_vsync_start - m->crtc_vdisplay, - m->crtc_vsync_end - m->crtc_vdisplay)); - - arc_pgu_write(arcpgu, ARCPGU_REG_ACTIVE, - ENCODE_PGU_XY(m->crtc_hblank_end - m->crtc_hblank_start, - m->crtc_vblank_end - m->crtc_vblank_start)); - - val = arc_pgu_read(arcpgu, ARCPGU_REG_CTRL); - - if (m->flags & DRM_MODE_FLAG_PVSYNC) - val |= ARCPGU_CTRL_VS_POL_MASK << ARCPGU_CTRL_VS_POL_OFST; - else - val &= ~(ARCPGU_CTRL_VS_POL_MASK << ARCPGU_CTRL_VS_POL_OFST); - - if (m->flags & DRM_MODE_FLAG_PHSYNC) - val |= ARCPGU_CTRL_HS_POL_MASK << ARCPGU_CTRL_HS_POL_OFST; - else - val &= ~(ARCPGU_CTRL_HS_POL_MASK << ARCPGU_CTRL_HS_POL_OFST); - - arc_pgu_write(arcpgu, ARCPGU_REG_CTRL, val); - arc_pgu_write(arcpgu, ARCPGU_REG_STRIDE, 0); - arc_pgu_write(arcpgu, ARCPGU_REG_START_SET, 1); - - arc_pgu_set_pxl_fmt(arcpgu); - - clk_set_rate(arcpgu->clk, m->crtc_clock * 1000); -} - -static void arc_pgu_enable(struct drm_simple_display_pipe *pipe, - struct drm_crtc_state *crtc_state, - struct drm_plane_state *plane_state) -{ - struct arcpgu_drm_private *arcpgu = pipe_to_arcpgu_priv(pipe); - - arc_pgu_mode_set(arcpgu); - - clk_prepare_enable(arcpgu->clk); - arc_pgu_write(arcpgu, ARCPGU_REG_CTRL, - arc_pgu_read(arcpgu, ARCPGU_REG_CTRL) | - ARCPGU_CTRL_ENABLE_MASK); -} - -static void arc_pgu_disable(struct drm_simple_display_pipe *pipe) -{ - struct arcpgu_drm_private *arcpgu = pipe_to_arcpgu_priv(pipe); - - clk_disable_unprepare(arcpgu->clk); - arc_pgu_write(arcpgu, ARCPGU_REG_CTRL, - arc_pgu_read(arcpgu, ARCPGU_REG_CTRL) & - ~ARCPGU_CTRL_ENABLE_MASK); -} - -static void arc_pgu_update(struct drm_simple_display_pipe *pipe, - struct drm_plane_state *state) -{ - struct arcpgu_drm_private *arcpgu; - struct drm_gem_cma_object *gem; - - if (!pipe->plane.state->fb) - return; - - arcpgu = pipe_to_arcpgu_priv(pipe); - gem = drm_fb_cma_get_gem_obj(pipe->plane.state->fb, 0); - arc_pgu_write(arcpgu, ARCPGU_REG_BUF0_ADDR, gem->paddr); -} - -static const struct drm_simple_display_pipe_funcs arc_pgu_pipe_funcs = { - .update = arc_pgu_update, - .mode_valid = arc_pgu_mode_valid, - .enable = arc_pgu_enable, - .disable = arc_pgu_disable, -}; - -int arc_pgu_setup_pipe(struct drm_device *drm) -{ - struct arcpgu_drm_private *arcpgu = dev_to_arcpgu(drm); - - return drm_simple_display_pipe_init(drm, &arcpgu->pipe, &arc_pgu_pipe_funcs, - arc_pgu_supported_formats, - ARRAY_SIZE(arc_pgu_supported_formats), - NULL, NULL); -} diff --git a/drivers/gpu/drm/arc/arcpgu_drv.c b/drivers/gpu/drm/arc/arcpgu_drv.c index 222ab28efbd0..e49e80b8b089 100644 --- a/drivers/gpu/drm/arc/arcpgu_drv.c +++ b/drivers/gpu/drm/arc/arcpgu_drv.c @@ -12,6 +12,7 @@ #include <drm/drm_drv.h> #include <drm/drm_fb_cma_helper.h> #include <drm/drm_fb_helper.h> +#include <drm/drm_fourcc.h> #include <drm/drm_gem_cma_helper.h> #include <drm/drm_gem_framebuffer_helper.h> #include <drm/drm_of.h> @@ -24,6 +25,138 @@ #include "arcpgu.h" #include "arcpgu_regs.h"
+#define ENCODE_PGU_XY(x, y) ((((x) - 1) << 16) | ((y) - 1)) + +static const u32 arc_pgu_supported_formats[] = { + DRM_FORMAT_RGB565, + DRM_FORMAT_XRGB8888, + DRM_FORMAT_ARGB8888, +}; + +static void arc_pgu_set_pxl_fmt(struct arcpgu_drm_private *arcpgu) +{ + const struct drm_framebuffer *fb = arcpgu->pipe.plane.state->fb; + uint32_t pixel_format = fb->format->format; + u32 format = DRM_FORMAT_INVALID; + int i; + u32 reg_ctrl; + + for (i = 0; i < ARRAY_SIZE(arc_pgu_supported_formats); i++) { + if (arc_pgu_supported_formats[i] == pixel_format) + format = arc_pgu_supported_formats[i]; + } + + if (WARN_ON(format == DRM_FORMAT_INVALID)) + return; + + reg_ctrl = arc_pgu_read(arcpgu, ARCPGU_REG_CTRL); + if (format == DRM_FORMAT_RGB565) + reg_ctrl &= ~ARCPGU_MODE_XRGB8888; + else + reg_ctrl |= ARCPGU_MODE_XRGB8888; + arc_pgu_write(arcpgu, ARCPGU_REG_CTRL, reg_ctrl); +} + +static enum drm_mode_status arc_pgu_mode_valid(struct drm_simple_display_pipe *pipe, + const struct drm_display_mode *mode) +{ + struct arcpgu_drm_private *arcpgu = pipe_to_arcpgu_priv(pipe); + long rate, clk_rate = mode->clock * 1000; + long diff = clk_rate / 200; /* +-0.5% allowed by HDMI spec */ + + rate = clk_round_rate(arcpgu->clk, clk_rate); + if ((max(rate, clk_rate) - min(rate, clk_rate) < diff) && (rate > 0)) + return MODE_OK; + + return MODE_NOCLOCK; +} + +static void arc_pgu_mode_set(struct arcpgu_drm_private *arcpgu) +{ + struct drm_display_mode *m = &arcpgu->pipe.crtc.state->adjusted_mode; + u32 val; + + arc_pgu_write(arcpgu, ARCPGU_REG_FMT, + ENCODE_PGU_XY(m->crtc_htotal, m->crtc_vtotal)); + + arc_pgu_write(arcpgu, ARCPGU_REG_HSYNC, + ENCODE_PGU_XY(m->crtc_hsync_start - m->crtc_hdisplay, + m->crtc_hsync_end - m->crtc_hdisplay)); + + arc_pgu_write(arcpgu, ARCPGU_REG_VSYNC, + ENCODE_PGU_XY(m->crtc_vsync_start - m->crtc_vdisplay, + m->crtc_vsync_end - m->crtc_vdisplay)); + + arc_pgu_write(arcpgu, ARCPGU_REG_ACTIVE, + ENCODE_PGU_XY(m->crtc_hblank_end - m->crtc_hblank_start, + m->crtc_vblank_end - m->crtc_vblank_start)); + + val = arc_pgu_read(arcpgu, ARCPGU_REG_CTRL); + + if (m->flags & DRM_MODE_FLAG_PVSYNC) + val |= ARCPGU_CTRL_VS_POL_MASK << ARCPGU_CTRL_VS_POL_OFST; + else + val &= ~(ARCPGU_CTRL_VS_POL_MASK << ARCPGU_CTRL_VS_POL_OFST); + + if (m->flags & DRM_MODE_FLAG_PHSYNC) + val |= ARCPGU_CTRL_HS_POL_MASK << ARCPGU_CTRL_HS_POL_OFST; + else + val &= ~(ARCPGU_CTRL_HS_POL_MASK << ARCPGU_CTRL_HS_POL_OFST); + + arc_pgu_write(arcpgu, ARCPGU_REG_CTRL, val); + arc_pgu_write(arcpgu, ARCPGU_REG_STRIDE, 0); + arc_pgu_write(arcpgu, ARCPGU_REG_START_SET, 1); + + arc_pgu_set_pxl_fmt(arcpgu); + + clk_set_rate(arcpgu->clk, m->crtc_clock * 1000); +} + +static void arc_pgu_enable(struct drm_simple_display_pipe *pipe, + struct drm_crtc_state *crtc_state, + struct drm_plane_state *plane_state) +{ + struct arcpgu_drm_private *arcpgu = pipe_to_arcpgu_priv(pipe); + + arc_pgu_mode_set(arcpgu); + + clk_prepare_enable(arcpgu->clk); + arc_pgu_write(arcpgu, ARCPGU_REG_CTRL, + arc_pgu_read(arcpgu, ARCPGU_REG_CTRL) | + ARCPGU_CTRL_ENABLE_MASK); +} + +static void arc_pgu_disable(struct drm_simple_display_pipe *pipe) +{ + struct arcpgu_drm_private *arcpgu = pipe_to_arcpgu_priv(pipe); + + clk_disable_unprepare(arcpgu->clk); + arc_pgu_write(arcpgu, ARCPGU_REG_CTRL, + arc_pgu_read(arcpgu, ARCPGU_REG_CTRL) & + ~ARCPGU_CTRL_ENABLE_MASK); +} + +static void arc_pgu_update(struct drm_simple_display_pipe *pipe, + struct drm_plane_state *state) +{ + struct arcpgu_drm_private *arcpgu; + struct drm_gem_cma_object *gem; + + if (!pipe->plane.state->fb) + return; + + arcpgu = pipe_to_arcpgu_priv(pipe); + gem = drm_fb_cma_get_gem_obj(pipe->plane.state->fb, 0); + arc_pgu_write(arcpgu, ARCPGU_REG_BUF0_ADDR, gem->paddr); +} + +static const struct drm_simple_display_pipe_funcs arc_pgu_pipe_funcs = { + .update = arc_pgu_update, + .mode_valid = arc_pgu_mode_valid, + .enable = arc_pgu_enable, + .disable = arc_pgu_disable, +}; + static const struct drm_mode_config_funcs arcpgu_drm_modecfg_funcs = { .fb_create = drm_gem_fb_create, .atomic_check = drm_atomic_helper_check, @@ -70,8 +203,12 @@ static int arcpgu_load(struct arcpgu_drm_private *arcpgu) if (dma_set_mask_and_coherent(drm->dev, DMA_BIT_MASK(32))) return -ENODEV;
- if (arc_pgu_setup_pipe(drm) < 0) - return -ENODEV; + ret = drm_simple_display_pipe_init(drm, &arcpgu->pipe, &arc_pgu_pipe_funcs, + arc_pgu_supported_formats, + ARRAY_SIZE(arc_pgu_supported_formats), + NULL, NULL); + if (ret) + return ret;
/* * There is only one output port inside each device. It is linked with
Really not worth the function, much less the separate file now that almost all the code is gone.
Cc: Eugeniy Paltsev Eugeniy.Paltsev@synopsys.com Cc: Alexey Brodkin abrodkin@synopsys.com Signed-off-by: Daniel Vetter daniel.vetter@intel.com --- drivers/gpu/drm/arc/Makefile | 2 +- drivers/gpu/drm/arc/arcpgu.h | 1 - drivers/gpu/drm/arc/arcpgu_drv.c | 12 +++++++++--- drivers/gpu/drm/arc/arcpgu_hdmi.c | 27 --------------------------- 4 files changed, 10 insertions(+), 32 deletions(-) delete mode 100644 drivers/gpu/drm/arc/arcpgu_hdmi.c
diff --git a/drivers/gpu/drm/arc/Makefile b/drivers/gpu/drm/arc/Makefile index c686e0287a71..379a1145bc2f 100644 --- a/drivers/gpu/drm/arc/Makefile +++ b/drivers/gpu/drm/arc/Makefile @@ -1,3 +1,3 @@ # SPDX-License-Identifier: GPL-2.0-only -arcpgu-y := arcpgu_hdmi.o arcpgu_sim.o arcpgu_drv.o +arcpgu-y := arcpgu_sim.o arcpgu_drv.o obj-$(CONFIG_DRM_ARCPGU) += arcpgu.o diff --git a/drivers/gpu/drm/arc/arcpgu.h b/drivers/gpu/drm/arc/arcpgu.h index cee2448a07d6..7dce0c2313ba 100644 --- a/drivers/gpu/drm/arc/arcpgu.h +++ b/drivers/gpu/drm/arc/arcpgu.h @@ -34,7 +34,6 @@ static inline u32 arc_pgu_read(struct arcpgu_drm_private *arcpgu, return ioread32(arcpgu->regs + reg); }
-int arcpgu_drm_hdmi_init(struct drm_device *drm, struct device_node *np); int arcpgu_drm_sim_init(struct drm_device *drm, struct device_node *np);
#endif diff --git a/drivers/gpu/drm/arc/arcpgu_drv.c b/drivers/gpu/drm/arc/arcpgu_drv.c index e49e80b8b089..0e959e42893d 100644 --- a/drivers/gpu/drm/arc/arcpgu_drv.c +++ b/drivers/gpu/drm/arc/arcpgu_drv.c @@ -221,9 +221,15 @@ static int arcpgu_load(struct arcpgu_drm_private *arcpgu) }
if (encoder_node) { - ret = arcpgu_drm_hdmi_init(drm, encoder_node); - of_node_put(encoder_node); - if (ret < 0) + struct drm_bridge *bridge; + + /* Locate drm bridge from the hdmi encoder DT node */ + bridge = of_drm_find_bridge(encoder_node); + if (!bridge) + return -EPROBE_DEFER; + + ret = drm_simple_display_pipe_attach_bridge(&arcpgu->pipe, bridge); + if (ret) return ret; } else { dev_info(drm->dev, "no encoder found. Assumed virtual LCD on simulation platform\n"); diff --git a/drivers/gpu/drm/arc/arcpgu_hdmi.c b/drivers/gpu/drm/arc/arcpgu_hdmi.c deleted file mode 100644 index d430af686cbc..000000000000 --- a/drivers/gpu/drm/arc/arcpgu_hdmi.c +++ /dev/null @@ -1,27 +0,0 @@ -// SPDX-License-Identifier: GPL-2.0-only -/* - * ARC PGU DRM driver. - * - * Copyright (C) 2016 Synopsys, Inc. (www.synopsys.com) - */ - -#include <drm/drm_bridge.h> -#include <drm/drm_crtc.h> -#include <drm/drm_encoder.h> -#include <drm/drm_device.h> - -#include "arcpgu.h" - -int arcpgu_drm_hdmi_init(struct drm_device *drm, struct device_node *np) -{ - struct arcpgu_drm_private *arcpgu = dev_to_arcpgu(drm); - struct drm_bridge *bridge; - - /* Locate drm bridge from the hdmi encoder DT node */ - bridge = of_drm_find_bridge(np); - if (!bridge) - return -EPROBE_DEFER; - - /* Link drm_bridge to encoder */ - return drm_simple_display_pipe_attach_bridge(&arcpgu->pipe, bridge); -}
At less than 500 lines total feels like the right thing to do.
Also noticed that the simple wrapper around drm_connector_cleanup can be dropped.
Acked-by: Sam Ravnborg sam@ravnborg.org Cc: Eugeniy Paltsev Eugeniy.Paltsev@synopsys.com Cc: Alexey Brodkin abrodkin@synopsys.com Signed-off-by: Daniel Vetter daniel.vetter@intel.com --- drivers/gpu/drm/arc/Makefile | 2 +- drivers/gpu/drm/arc/arcpgu.h | 39 ------------ drivers/gpu/drm/arc/arcpgu_drv.c | 102 +++++++++++++++++++++++++++++- drivers/gpu/drm/arc/arcpgu_regs.h | 31 --------- drivers/gpu/drm/arc/arcpgu_sim.c | 74 ---------------------- 5 files changed, 101 insertions(+), 147 deletions(-) delete mode 100644 drivers/gpu/drm/arc/arcpgu.h delete mode 100644 drivers/gpu/drm/arc/arcpgu_regs.h delete mode 100644 drivers/gpu/drm/arc/arcpgu_sim.c
diff --git a/drivers/gpu/drm/arc/Makefile b/drivers/gpu/drm/arc/Makefile index 379a1145bc2f..b26f2495c532 100644 --- a/drivers/gpu/drm/arc/Makefile +++ b/drivers/gpu/drm/arc/Makefile @@ -1,3 +1,3 @@ # SPDX-License-Identifier: GPL-2.0-only -arcpgu-y := arcpgu_sim.o arcpgu_drv.o +arcpgu-y := arcpgu_drv.o obj-$(CONFIG_DRM_ARCPGU) += arcpgu.o diff --git a/drivers/gpu/drm/arc/arcpgu.h b/drivers/gpu/drm/arc/arcpgu.h deleted file mode 100644 index 7dce0c2313ba..000000000000 --- a/drivers/gpu/drm/arc/arcpgu.h +++ /dev/null @@ -1,39 +0,0 @@ -/* SPDX-License-Identifier: GPL-2.0-only */ -/* - * ARC PGU DRM driver. - * - * Copyright (C) 2016 Synopsys, Inc. (www.synopsys.com) - */ - -#ifndef _ARCPGU_H_ -#define _ARCPGU_H_ - -#include <drm/drm_simple_kms_helper.h> - -struct arcpgu_drm_private { - struct drm_device drm; - void __iomem *regs; - struct clk *clk; - struct drm_simple_display_pipe pipe; - struct drm_connector sim_conn; -}; - -#define dev_to_arcpgu(x) container_of(x, struct arcpgu_drm_private, drm) - -#define pipe_to_arcpgu_priv(x) container_of(x, struct arcpgu_drm_private, pipe) - -static inline void arc_pgu_write(struct arcpgu_drm_private *arcpgu, - unsigned int reg, u32 value) -{ - iowrite32(value, arcpgu->regs + reg); -} - -static inline u32 arc_pgu_read(struct arcpgu_drm_private *arcpgu, - unsigned int reg) -{ - return ioread32(arcpgu->regs + reg); -} - -int arcpgu_drm_sim_init(struct drm_device *drm, struct device_node *np); - -#endif diff --git a/drivers/gpu/drm/arc/arcpgu_drv.c b/drivers/gpu/drm/arc/arcpgu_drv.c index 0e959e42893d..0a0b54993773 100644 --- a/drivers/gpu/drm/arc/arcpgu_drv.c +++ b/drivers/gpu/drm/arc/arcpgu_drv.c @@ -17,13 +17,111 @@ #include <drm/drm_gem_framebuffer_helper.h> #include <drm/drm_of.h> #include <drm/drm_probe_helper.h> +#include <drm/drm_simple_kms_helper.h> #include <linux/dma-mapping.h> #include <linux/module.h> #include <linux/of_reserved_mem.h> #include <linux/platform_device.h>
-#include "arcpgu.h" -#include "arcpgu_regs.h" +#define ARCPGU_REG_CTRL 0x00 +#define ARCPGU_REG_STAT 0x04 +#define ARCPGU_REG_FMT 0x10 +#define ARCPGU_REG_HSYNC 0x14 +#define ARCPGU_REG_VSYNC 0x18 +#define ARCPGU_REG_ACTIVE 0x1c +#define ARCPGU_REG_BUF0_ADDR 0x40 +#define ARCPGU_REG_STRIDE 0x50 +#define ARCPGU_REG_START_SET 0x84 + +#define ARCPGU_REG_ID 0x3FC + +#define ARCPGU_CTRL_ENABLE_MASK 0x02 +#define ARCPGU_CTRL_VS_POL_MASK 0x1 +#define ARCPGU_CTRL_VS_POL_OFST 0x3 +#define ARCPGU_CTRL_HS_POL_MASK 0x1 +#define ARCPGU_CTRL_HS_POL_OFST 0x4 +#define ARCPGU_MODE_XRGB8888 BIT(2) +#define ARCPGU_STAT_BUSY_MASK 0x02 + +struct arcpgu_drm_private { + struct drm_device drm; + void __iomem *regs; + struct clk *clk; + struct drm_simple_display_pipe pipe; + struct drm_connector sim_conn; +}; + +#define dev_to_arcpgu(x) container_of(x, struct arcpgu_drm_private, drm) + +#define pipe_to_arcpgu_priv(x) container_of(x, struct arcpgu_drm_private, pipe) + +static inline void arc_pgu_write(struct arcpgu_drm_private *arcpgu, + unsigned int reg, u32 value) +{ + iowrite32(value, arcpgu->regs + reg); +} + +static inline u32 arc_pgu_read(struct arcpgu_drm_private *arcpgu, + unsigned int reg) +{ + return ioread32(arcpgu->regs + reg); +} + +#define XRES_DEF 640 +#define YRES_DEF 480 + +#define XRES_MAX 8192 +#define YRES_MAX 8192 + +static int arcpgu_drm_connector_get_modes(struct drm_connector *connector) +{ + int count; + + count = drm_add_modes_noedid(connector, XRES_MAX, YRES_MAX); + drm_set_preferred_mode(connector, XRES_DEF, YRES_DEF); + return count; +} + +static const struct drm_connector_helper_funcs +arcpgu_drm_connector_helper_funcs = { + .get_modes = arcpgu_drm_connector_get_modes, +}; + +static const struct drm_connector_funcs arcpgu_drm_connector_funcs = { + .reset = drm_atomic_helper_connector_reset, + .fill_modes = drm_helper_probe_single_connector_modes, + .destroy = drm_connector_cleanup, + .atomic_duplicate_state = drm_atomic_helper_connector_duplicate_state, + .atomic_destroy_state = drm_atomic_helper_connector_destroy_state, +}; + +static int arcpgu_drm_sim_init(struct drm_device *drm, struct device_node *np) +{ + struct arcpgu_drm_private *arcpgu = dev_to_arcpgu(drm); + struct drm_encoder *encoder; + struct drm_connector *connector; + int ret; + + encoder = &arcpgu->pipe.encoder; + + connector = &arcpgu->sim_conn; + drm_connector_helper_add(connector, &arcpgu_drm_connector_helper_funcs); + + ret = drm_connector_init(drm, connector, &arcpgu_drm_connector_funcs, + DRM_MODE_CONNECTOR_VIRTUAL); + if (ret < 0) { + dev_err(drm->dev, "failed to initialize drm connector\n"); + return ret; + } + + ret = drm_connector_attach_encoder(connector, encoder); + if (ret < 0) { + dev_err(drm->dev, "could not attach connector to encoder\n"); + return ret; + } + + return 0; +}
#define ENCODE_PGU_XY(x, y) ((((x) - 1) << 16) | ((y) - 1))
diff --git a/drivers/gpu/drm/arc/arcpgu_regs.h b/drivers/gpu/drm/arc/arcpgu_regs.h deleted file mode 100644 index b689a382d556..000000000000 --- a/drivers/gpu/drm/arc/arcpgu_regs.h +++ /dev/null @@ -1,31 +0,0 @@ -/* SPDX-License-Identifier: GPL-2.0-only */ -/* - * ARC PGU DRM driver. - * - * Copyright (C) 2016 Synopsys, Inc. (www.synopsys.com) - */ - -#ifndef _ARC_PGU_REGS_H_ -#define _ARC_PGU_REGS_H_ - -#define ARCPGU_REG_CTRL 0x00 -#define ARCPGU_REG_STAT 0x04 -#define ARCPGU_REG_FMT 0x10 -#define ARCPGU_REG_HSYNC 0x14 -#define ARCPGU_REG_VSYNC 0x18 -#define ARCPGU_REG_ACTIVE 0x1c -#define ARCPGU_REG_BUF0_ADDR 0x40 -#define ARCPGU_REG_STRIDE 0x50 -#define ARCPGU_REG_START_SET 0x84 - -#define ARCPGU_REG_ID 0x3FC - -#define ARCPGU_CTRL_ENABLE_MASK 0x02 -#define ARCPGU_CTRL_VS_POL_MASK 0x1 -#define ARCPGU_CTRL_VS_POL_OFST 0x3 -#define ARCPGU_CTRL_HS_POL_MASK 0x1 -#define ARCPGU_CTRL_HS_POL_OFST 0x4 -#define ARCPGU_MODE_XRGB8888 BIT(2) -#define ARCPGU_STAT_BUSY_MASK 0x02 - -#endif diff --git a/drivers/gpu/drm/arc/arcpgu_sim.c b/drivers/gpu/drm/arc/arcpgu_sim.c deleted file mode 100644 index 1a63f0868504..000000000000 --- a/drivers/gpu/drm/arc/arcpgu_sim.c +++ /dev/null @@ -1,74 +0,0 @@ -// SPDX-License-Identifier: GPL-2.0-only -/* - * ARC PGU DRM driver. - * - * Copyright (C) 2016 Synopsys, Inc. (www.synopsys.com) - */ - -#include <drm/drm_atomic_helper.h> -#include <drm/drm_device.h> -#include <drm/drm_probe_helper.h> - -#include "arcpgu.h" - -#define XRES_DEF 640 -#define YRES_DEF 480 - -#define XRES_MAX 8192 -#define YRES_MAX 8192 - - -static int arcpgu_drm_connector_get_modes(struct drm_connector *connector) -{ - int count; - - count = drm_add_modes_noedid(connector, XRES_MAX, YRES_MAX); - drm_set_preferred_mode(connector, XRES_DEF, YRES_DEF); - return count; -} - -static void arcpgu_drm_connector_destroy(struct drm_connector *connector) -{ - drm_connector_cleanup(connector); -} - -static const struct drm_connector_helper_funcs -arcpgu_drm_connector_helper_funcs = { - .get_modes = arcpgu_drm_connector_get_modes, -}; - -static const struct drm_connector_funcs arcpgu_drm_connector_funcs = { - .reset = drm_atomic_helper_connector_reset, - .fill_modes = drm_helper_probe_single_connector_modes, - .destroy = arcpgu_drm_connector_destroy, - .atomic_duplicate_state = drm_atomic_helper_connector_duplicate_state, - .atomic_destroy_state = drm_atomic_helper_connector_destroy_state, -}; - -int arcpgu_drm_sim_init(struct drm_device *drm, struct device_node *np) -{ - struct arcpgu_drm_private *arcpgu = dev_to_arcpgu(drm); - struct drm_encoder *encoder; - struct drm_connector *connector; - int ret; - - encoder = &arcpgu->pipe.encoder; - - connector = &arcpgu->sim_conn; - drm_connector_helper_add(connector, &arcpgu_drm_connector_helper_funcs); - - ret = drm_connector_init(drm, connector, &arcpgu_drm_connector_funcs, - DRM_MODE_CONNECTOR_VIRTUAL); - if (ret < 0) { - dev_err(drm->dev, "failed to initialize drm connector\n"); - return ret; - } - - ret = drm_connector_attach_encoder(connector, encoder); - if (ret < 0) { - dev_err(drm->dev, "could not attach connector to encoder\n"); - return ret; - } - - return 0; -}
That way we can get rid of this final piece of init code, and use the simple pipe helpers as intended.
v2: Fix indent (Sam)
Acked-by: Sam Ravnborg sam@ravnborg.org Cc: Eugeniy Paltsev Eugeniy.Paltsev@synopsys.com Signed-off-by: Daniel Vetter daniel.vetter@intel.com Cc: Alexey Brodkin abrodkin@synopsys.com --- drivers/gpu/drm/arc/arcpgu_drv.c | 53 ++++++++++---------------------- 1 file changed, 17 insertions(+), 36 deletions(-)
diff --git a/drivers/gpu/drm/arc/arcpgu_drv.c b/drivers/gpu/drm/arc/arcpgu_drv.c index 0a0b54993773..8edfe6601151 100644 --- a/drivers/gpu/drm/arc/arcpgu_drv.c +++ b/drivers/gpu/drm/arc/arcpgu_drv.c @@ -95,32 +95,11 @@ static const struct drm_connector_funcs arcpgu_drm_connector_funcs = { .atomic_destroy_state = drm_atomic_helper_connector_destroy_state, };
-static int arcpgu_drm_sim_init(struct drm_device *drm, struct device_node *np) +static int arcpgu_drm_sim_init(struct drm_device *drm, struct drm_connector *connector) { - struct arcpgu_drm_private *arcpgu = dev_to_arcpgu(drm); - struct drm_encoder *encoder; - struct drm_connector *connector; - int ret; - - encoder = &arcpgu->pipe.encoder; - - connector = &arcpgu->sim_conn; drm_connector_helper_add(connector, &arcpgu_drm_connector_helper_funcs); - - ret = drm_connector_init(drm, connector, &arcpgu_drm_connector_funcs, - DRM_MODE_CONNECTOR_VIRTUAL); - if (ret < 0) { - dev_err(drm->dev, "failed to initialize drm connector\n"); - return ret; - } - - ret = drm_connector_attach_encoder(connector, encoder); - if (ret < 0) { - dev_err(drm->dev, "could not attach connector to encoder\n"); - return ret; - } - - return 0; + return drm_connector_init(drm, connector, &arcpgu_drm_connector_funcs, + DRM_MODE_CONNECTOR_VIRTUAL); }
#define ENCODE_PGU_XY(x, y) ((((x) - 1) << 16) | ((y) - 1)) @@ -267,6 +246,7 @@ static int arcpgu_load(struct arcpgu_drm_private *arcpgu) { struct platform_device *pdev = to_platform_device(arcpgu->drm.dev); struct device_node *encoder_node = NULL, *endpoint_node = NULL; + struct drm_connector *connector = NULL; struct drm_device *drm = &arcpgu->drm; struct resource *res; int ret; @@ -301,13 +281,6 @@ static int arcpgu_load(struct arcpgu_drm_private *arcpgu) if (dma_set_mask_and_coherent(drm->dev, DMA_BIT_MASK(32))) return -ENODEV;
- ret = drm_simple_display_pipe_init(drm, &arcpgu->pipe, &arc_pgu_pipe_funcs, - arc_pgu_supported_formats, - ARRAY_SIZE(arc_pgu_supported_formats), - NULL, NULL); - if (ret) - return ret; - /* * There is only one output port inside each device. It is linked with * encoder endpoint. @@ -316,8 +289,21 @@ static int arcpgu_load(struct arcpgu_drm_private *arcpgu) if (endpoint_node) { encoder_node = of_graph_get_remote_port_parent(endpoint_node); of_node_put(endpoint_node); + } else { + connector = &arcpgu->sim_conn; + dev_info(drm->dev, "no encoder found. Assumed virtual LCD on simulation platform\n"); + ret = arcpgu_drm_sim_init(drm, connector); + if (ret < 0) + return ret; }
+ ret = drm_simple_display_pipe_init(drm, &arcpgu->pipe, &arc_pgu_pipe_funcs, + arc_pgu_supported_formats, + ARRAY_SIZE(arc_pgu_supported_formats), + NULL, connector); + if (ret) + return ret; + if (encoder_node) { struct drm_bridge *bridge;
@@ -329,11 +315,6 @@ static int arcpgu_load(struct arcpgu_drm_private *arcpgu) ret = drm_simple_display_pipe_attach_bridge(&arcpgu->pipe, bridge); if (ret) return ret; - } else { - dev_info(drm->dev, "no encoder found. Assumed virtual LCD on simulation platform\n"); - ret = arcpgu_drm_sim_init(drm, NULL); - if (ret < 0) - return ret; }
drm_mode_config_reset(drm);
Because it is.
v2: Delete now unused crtc funcs (0day)
Cc: Eugeniy Paltsev Eugeniy.Paltsev@synopsys.com Signed-off-by: Daniel Vetter daniel.vetter@intel.com Cc: Alexey Brodkin abrodkin@synopsys.com --- MAINTAINERS | 2 +- drivers/gpu/drm/Kconfig | 2 -- drivers/gpu/drm/Makefile | 1 - drivers/gpu/drm/arc/Kconfig | 10 ---------- drivers/gpu/drm/arc/Makefile | 3 --- drivers/gpu/drm/tiny/Kconfig | 10 ++++++++++ drivers/gpu/drm/tiny/Makefile | 1 + drivers/gpu/drm/{arc/arcpgu_drv.c => tiny/arcpgu.c} | 0 8 files changed, 12 insertions(+), 17 deletions(-) delete mode 100644 drivers/gpu/drm/arc/Kconfig delete mode 100644 drivers/gpu/drm/arc/Makefile rename drivers/gpu/drm/{arc/arcpgu_drv.c => tiny/arcpgu.c} (100%)
diff --git a/MAINTAINERS b/MAINTAINERS index f92035bfbbcd..b16e80c4d669 100644 --- a/MAINTAINERS +++ b/MAINTAINERS @@ -1334,7 +1334,7 @@ ARC PGU DRM DRIVER M: Alexey Brodkin abrodkin@synopsys.com S: Supported F: Documentation/devicetree/bindings/display/snps,arcpgu.txt -F: drivers/gpu/drm/arc/ +F: drivers/gpu/drm/tiny/arcpgu.c
ARCNET NETWORK LAYER M: Michael Grzeschik m.grzeschik@pengutronix.de diff --git a/drivers/gpu/drm/Kconfig b/drivers/gpu/drm/Kconfig index 147d61b9674e..9efb82caaa87 100644 --- a/drivers/gpu/drm/Kconfig +++ b/drivers/gpu/drm/Kconfig @@ -354,8 +354,6 @@ source "drivers/gpu/drm/vc4/Kconfig"
source "drivers/gpu/drm/etnaviv/Kconfig"
-source "drivers/gpu/drm/arc/Kconfig" - source "drivers/gpu/drm/hisilicon/Kconfig"
source "drivers/gpu/drm/mediatek/Kconfig" diff --git a/drivers/gpu/drm/Makefile b/drivers/gpu/drm/Makefile index 2f31579f91d4..6c15ef9b04d6 100644 --- a/drivers/gpu/drm/Makefile +++ b/drivers/gpu/drm/Makefile @@ -109,7 +109,6 @@ obj-y += panel/ obj-y += bridge/ obj-$(CONFIG_DRM_FSL_DCU) += fsl-dcu/ obj-$(CONFIG_DRM_ETNAVIV) += etnaviv/ -obj-$(CONFIG_DRM_ARCPGU)+= arc/ obj-y += hisilicon/ obj-$(CONFIG_DRM_ZTE) += zte/ obj-$(CONFIG_DRM_MXSFB) += mxsfb/ diff --git a/drivers/gpu/drm/arc/Kconfig b/drivers/gpu/drm/arc/Kconfig deleted file mode 100644 index e8f3d63e0b91..000000000000 --- a/drivers/gpu/drm/arc/Kconfig +++ /dev/null @@ -1,10 +0,0 @@ -# SPDX-License-Identifier: GPL-2.0-only -config DRM_ARCPGU - tristate "ARC PGU" - depends on DRM && OF - select DRM_KMS_CMA_HELPER - select DRM_KMS_HELPER - help - Choose this option if you have an ARC PGU controller. - - If M is selected the module will be called arcpgu. diff --git a/drivers/gpu/drm/arc/Makefile b/drivers/gpu/drm/arc/Makefile deleted file mode 100644 index b26f2495c532..000000000000 --- a/drivers/gpu/drm/arc/Makefile +++ /dev/null @@ -1,3 +0,0 @@ -# SPDX-License-Identifier: GPL-2.0-only -arcpgu-y := arcpgu_drv.o -obj-$(CONFIG_DRM_ARCPGU) += arcpgu.o diff --git a/drivers/gpu/drm/tiny/Kconfig b/drivers/gpu/drm/tiny/Kconfig index 2b6414f0fa75..9bbaa1a69050 100644 --- a/drivers/gpu/drm/tiny/Kconfig +++ b/drivers/gpu/drm/tiny/Kconfig @@ -1,5 +1,15 @@ # SPDX-License-Identifier: GPL-2.0-only
+config DRM_ARCPGU + tristate "ARC PGU" + depends on DRM && OF + select DRM_KMS_CMA_HELPER + select DRM_KMS_HELPER + help + Choose this option if you have an ARC PGU controller. + + If M is selected the module will be called arcpgu. + config DRM_CIRRUS_QEMU tristate "Cirrus driver for QEMU emulated device" depends on DRM && PCI && MMU diff --git a/drivers/gpu/drm/tiny/Makefile b/drivers/gpu/drm/tiny/Makefile index 6ae4e9e5a35f..bef6780bdd6f 100644 --- a/drivers/gpu/drm/tiny/Makefile +++ b/drivers/gpu/drm/tiny/Makefile @@ -1,5 +1,6 @@ # SPDX-License-Identifier: GPL-2.0-only
+obj-$(CONFIG_DRM_ARCPGU) += arcpgu.o obj-$(CONFIG_DRM_CIRRUS_QEMU) += cirrus.o obj-$(CONFIG_DRM_GM12U320) += gm12u320.o obj-$(CONFIG_TINYDRM_HX8357D) += hx8357d.o diff --git a/drivers/gpu/drm/arc/arcpgu_drv.c b/drivers/gpu/drm/tiny/arcpgu.c similarity index 100% rename from drivers/gpu/drm/arc/arcpgu_drv.c rename to drivers/gpu/drm/tiny/arcpgu.c
Am 04.09.20 um 16:39 schrieb Daniel Vetter:
Because it is.
Absolutely.
Acked-by: Thomas Zimmermann tzimmermann@suse.de
dri-devel@lists.freedesktop.org