| From 621dba32010600142345476db96c8fa0d1534b99 Mon Sep 17 00:00:00 2001 |
| From: Brandon Pollack <brpol@chromium.org> |
| Date: Fri, 23 Jun 2023 18:23:43 -0400 |
| Subject: [PATCH] FROMLIST: drm/vkms: Back VKMS with DRM memory management |
| instead of static objects |
| MIME-Version: 1.0 |
| Content-Type: text/plain; charset=UTF-8 |
| Content-Transfer-Encoding: 8bit |
| |
| This is a small refactor to make ConfigFS support easier. Once we |
| support ConfigFS, there can be multiple devices instantiated by the |
| driver, and so moving everything into managed memory makes things much |
| easier. |
| |
| This should be a no-op refactor. |
| |
| Signed-off-by: Jim Shargo <jshargo@chromium.org> |
| Signed-off-by: Brandon Pollack <brpol@chromium.org> |
| (am from https://patchwork.kernel.org/project/dri-devel/patch/20230829053201.423261-2-brpol@chromium.org/) |
| |
| The change is in the final stages of review (fifth iteration), All that |
| remains is some (potential) igt tests and final signoff. |
| |
| Some reasons we'd like to submit in chromeOS are: |
| |
| This will allow our virtual multi display tests to run in presubmit. |
| This real world case will be compelling evidence if/when upstream |
| requests some data that this ran for real in production (and avoiding |
| the chicken egg problem of we need this in the kernel to run the tests |
| but without running the tests we can't submit upstream). |
| |
| Signed-off-by: Brandon Pollack <brpol@chromium.org> |
| BUG=241800059 |
| BUG=283357160 |
| TEST=new tests defined here passing https://chromium-review.googlesource.com/c/chromiumos/platform/tast-tests/+/4666669 |
| |
| Change-Id: I05cf40405f6ea413984e136d6d32030c45285b55 |
| Signed-off-by: Brandon Pollack <brpol@google.com> |
| Reviewed-on: https://chromium-review.googlesource.com/c/chromiumos/third_party/kernel/+/4810098 |
| Reviewed-by: Sean Paul <sean@poorly.run> |
| Reviewed-by: Stéphane Marchesin <marcheu@chromium.org> |
| --- |
| drivers/gpu/drm/vkms/vkms_drv.c | 128 +++++++++++++++-------------- |
| drivers/gpu/drm/vkms/vkms_drv.h | 4 +- |
| drivers/gpu/drm/vkms/vkms_output.c | 6 +- |
| 3 files changed, 70 insertions(+), 68 deletions(-) |
| |
| diff --git a/drivers/gpu/drm/vkms/vkms_drv.c b/drivers/gpu/drm/vkms/vkms_drv.c |
| index 0c1a713b7b7b3bc61f7a23ae4f240f0233d937a5..b5ca99011a23bf8f4df2c905910cfc94f88fb1c4 100644 |
| --- a/drivers/gpu/drm/vkms/vkms_drv.c |
| +++ b/drivers/gpu/drm/vkms/vkms_drv.c |
| @@ -9,10 +9,12 @@ |
| * the GPU in DRM API tests. |
| */ |
| |
| +#include <linux/device.h> |
| #include <linux/module.h> |
| #include <linux/platform_device.h> |
| #include <linux/dma-mapping.h> |
| |
| +#include <drm/drm_device.h> |
| #include <drm/drm_gem.h> |
| #include <drm/drm_atomic.h> |
| #include <drm/drm_atomic_helper.h> |
| @@ -37,8 +39,6 @@ |
| #define DRIVER_MAJOR 1 |
| #define DRIVER_MINOR 0 |
| |
| -static struct vkms_config *default_config; |
| - |
| static bool enable_cursor = true; |
| module_param_named(enable_cursor, enable_cursor, bool, 0444); |
| MODULE_PARM_DESC(enable_cursor, "Enable/Disable cursor support"); |
| @@ -96,9 +96,9 @@ static int vkms_config_show(struct seq_file *m, void *data) |
| struct drm_device *dev = entry->dev; |
| struct vkms_device *vkmsdev = drm_device_to_vkms_device(dev); |
| |
| - seq_printf(m, "writeback=%d\n", vkmsdev->config->writeback); |
| - seq_printf(m, "cursor=%d\n", vkmsdev->config->cursor); |
| - seq_printf(m, "overlay=%d\n", vkmsdev->config->overlay); |
| + seq_printf(m, "writeback=%d\n", vkmsdev->config.writeback); |
| + seq_printf(m, "cursor=%d\n", vkmsdev->config.cursor); |
| + seq_printf(m, "overlay=%d\n", vkmsdev->config.overlay); |
| |
| return 0; |
| } |
| @@ -164,10 +164,9 @@ static int vkms_modeset_init(struct vkms_device *vkmsdev) |
| dev->mode_config.max_height = YRES_MAX; |
| dev->mode_config.cursor_width = 512; |
| dev->mode_config.cursor_height = 512; |
| - /* |
| - * FIXME: There's a confusion between bpp and depth between this and |
| + /* FIXME: There's a confusion between bpp and depth between this and |
| * fbdev helpers. We have to go with 0, meaning "pick the default", |
| - * which is XRGB8888 in all cases. |
| + * which ix XRGB8888 in all cases. |
| */ |
| dev->mode_config.preferred_depth = 0; |
| dev->mode_config.helper_private = &vkms_mode_config_helpers; |
| @@ -175,114 +174,119 @@ static int vkms_modeset_init(struct vkms_device *vkmsdev) |
| return vkms_output_init(vkmsdev, 0); |
| } |
| |
| -static int vkms_create(struct vkms_config *config) |
| +static int vkms_platform_probe(struct platform_device *pdev) |
| { |
| int ret; |
| - struct platform_device *pdev; |
| struct vkms_device *vkms_device; |
| + void *grp; |
| |
| - pdev = platform_device_register_simple(DRIVER_NAME, -1, NULL, 0); |
| - if (IS_ERR(pdev)) |
| - return PTR_ERR(pdev); |
| - |
| - if (!devres_open_group(&pdev->dev, NULL, GFP_KERNEL)) { |
| - ret = -ENOMEM; |
| - goto out_unregister; |
| - } |
| + grp = devres_open_group(&pdev->dev, NULL, GFP_KERNEL); |
| + if (!grp) |
| + return -ENOMEM; |
| |
| 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; |
| + goto out_release_group; |
| } |
| vkms_device->platform = pdev; |
| - vkms_device->config = config; |
| - config->dev = vkms_device; |
| + vkms_device->config.cursor = enable_cursor; |
| + vkms_device->config.writeback = enable_writeback; |
| + vkms_device->config.overlay = enable_overlay; |
| |
| 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_devres; |
| + goto out_release_group; |
| } |
| |
| ret = drm_vblank_init(&vkms_device->drm, 1); |
| if (ret) { |
| DRM_ERROR("Failed to vblank\n"); |
| - goto out_devres; |
| + goto out_release_group; |
| } |
| |
| ret = vkms_modeset_init(vkms_device); |
| - if (ret) |
| - goto out_devres; |
| + if (ret) { |
| + DRM_ERROR("Unable to initialize modesetting\n"); |
| + goto out_release_group; |
| + } |
| |
| drm_debugfs_add_files(&vkms_device->drm, vkms_config_debugfs_list, |
| ARRAY_SIZE(vkms_config_debugfs_list)); |
| |
| ret = drm_dev_register(&vkms_device->drm, 0); |
| - if (ret) |
| - goto out_devres; |
| + if (ret) { |
| + DRM_ERROR("Unable to register device with id %d\n", pdev->id); |
| + goto out_release_group; |
| + } |
| |
| drm_fbdev_shmem_setup(&vkms_device->drm, 0); |
| + platform_set_drvdata(pdev, vkms_device); |
| + devres_close_group(&pdev->dev, grp); |
| |
| return 0; |
| |
| -out_devres: |
| - devres_release_group(&pdev->dev, NULL); |
| -out_unregister: |
| - platform_device_unregister(pdev); |
| +out_release_group: |
| + devres_release_group(&pdev->dev, grp); |
| return ret; |
| } |
| |
| -static int __init vkms_init(void) |
| +static int vkms_platform_remove(struct platform_device *pdev) |
| { |
| - int ret; |
| - struct vkms_config *config; |
| - |
| - config = kmalloc(sizeof(*config), GFP_KERNEL); |
| - if (!config) |
| - return -ENOMEM; |
| - |
| - default_config = config; |
| - |
| - config->cursor = enable_cursor; |
| - config->writeback = enable_writeback; |
| - config->overlay = enable_overlay; |
| + struct vkms_device *vkms_device; |
| |
| - ret = vkms_create(config); |
| - if (ret) |
| - kfree(config); |
| + vkms_device = platform_get_drvdata(pdev); |
| + if (!vkms_device) |
| + return 0; |
| |
| - return ret; |
| + drm_dev_unregister(&vkms_device->drm); |
| + drm_atomic_helper_shutdown(&vkms_device->drm); |
| + return 0; |
| } |
| |
| -static void vkms_destroy(struct vkms_config *config) |
| +static struct platform_driver vkms_platform_driver = { |
| + .probe = vkms_platform_probe, |
| + .remove = vkms_platform_remove, |
| + .driver.name = DRIVER_NAME, |
| +}; |
| + |
| +static int __init vkms_init(void) |
| { |
| + int ret; |
| struct platform_device *pdev; |
| |
| - if (!config->dev) { |
| - DRM_INFO("vkms_device is NULL.\n"); |
| - return; |
| + ret = platform_driver_register(&vkms_platform_driver); |
| + if (ret) { |
| + DRM_ERROR("Unable to register platform driver\n"); |
| + return ret; |
| } |
| |
| - pdev = config->dev->platform; |
| - |
| - drm_dev_unregister(&config->dev->drm); |
| - drm_atomic_helper_shutdown(&config->dev->drm); |
| - devres_release_group(&pdev->dev, NULL); |
| - platform_device_unregister(pdev); |
| + pdev = platform_device_register_simple(DRIVER_NAME, -1, NULL, 0); |
| + if (IS_ERR(pdev)) { |
| + platform_driver_unregister(&vkms_platform_driver); |
| + return PTR_ERR(pdev); |
| + } |
| |
| - config->dev = NULL; |
| + return 0; |
| } |
| |
| static void __exit vkms_exit(void) |
| { |
| - if (default_config->dev) |
| - vkms_destroy(default_config); |
| + struct device *dev; |
| + |
| + while ((dev = platform_find_device_by_driver( |
| + NULL, &vkms_platform_driver.driver))) { |
| + // platform_find_device_by_driver increments the refcount. Drop |
| + // it so we don't leak memory. |
| + put_device(dev); |
| + platform_device_unregister(to_platform_device(dev)); |
| + } |
| |
| - kfree(default_config); |
| + platform_driver_unregister(&vkms_platform_driver); |
| } |
| |
| module_init(vkms_init); |
| diff --git a/drivers/gpu/drm/vkms/vkms_drv.h b/drivers/gpu/drm/vkms/vkms_drv.h |
| index 5e46ea5b96dcc4412d4d78d5fb99287cdf33a293..74658ad2a8d85bf1fe74a70de450bd78a9731a31 100644 |
| --- a/drivers/gpu/drm/vkms/vkms_drv.h |
| +++ b/drivers/gpu/drm/vkms/vkms_drv.h |
| @@ -121,15 +121,13 @@ struct vkms_config { |
| bool writeback; |
| bool cursor; |
| bool overlay; |
| - /* only set when instantiated */ |
| - struct vkms_device *dev; |
| }; |
| |
| struct vkms_device { |
| struct drm_device drm; |
| struct platform_device *platform; |
| struct vkms_output output; |
| - const struct vkms_config *config; |
| + struct vkms_config config; |
| }; |
| |
| #define drm_crtc_to_vkms_output(target) \ |
| diff --git a/drivers/gpu/drm/vkms/vkms_output.c b/drivers/gpu/drm/vkms/vkms_output.c |
| index 5ce70dd946aa631d156589202d10d779018844ff..963a64cf068bbfbdeb89b03bafb843bf7fb895b7 100644 |
| --- a/drivers/gpu/drm/vkms/vkms_output.c |
| +++ b/drivers/gpu/drm/vkms/vkms_output.c |
| @@ -62,7 +62,7 @@ int vkms_output_init(struct vkms_device *vkmsdev, int index) |
| if (IS_ERR(primary)) |
| return PTR_ERR(primary); |
| |
| - if (vkmsdev->config->overlay) { |
| + if (vkmsdev->config.overlay) { |
| for (n = 0; n < NUM_OVERLAY_PLANES; n++) { |
| ret = vkms_add_overlay_plane(vkmsdev, index, crtc); |
| if (ret) |
| @@ -70,7 +70,7 @@ int vkms_output_init(struct vkms_device *vkmsdev, int index) |
| } |
| } |
| |
| - if (vkmsdev->config->cursor) { |
| + if (vkmsdev->config.cursor) { |
| cursor = vkms_plane_init(vkmsdev, DRM_PLANE_TYPE_CURSOR, index); |
| if (IS_ERR(cursor)) |
| return PTR_ERR(cursor); |
| @@ -103,7 +103,7 @@ int vkms_output_init(struct vkms_device *vkmsdev, int index) |
| goto err_attach; |
| } |
| |
| - if (vkmsdev->config->writeback) { |
| + if (vkmsdev->config.writeback) { |
| writeback = vkms_enable_writeback_connector(vkmsdev); |
| if (writeback) |
| DRM_ERROR("Failed to init writeback connector\n"); |
| -- |
| 2.47.0.338.g60cca15819-goog |
| |