]> git.baikalelectronics.ru Git - kernel.git/commitdiff
drm/tegra: Do not use ->load() and ->unload() callbacks
authorThierry Reding <treding@nvidia.com>
Mon, 28 Oct 2019 12:16:10 +0000 (13:16 +0100)
committerThierry Reding <treding@nvidia.com>
Tue, 29 Oct 2019 14:04:29 +0000 (15:04 +0100)
The ->load() and ->unload() drivers are midlayers and should be avoided
in modern drivers. Fix this by moving the code into the driver ->probe()
and ->remove() implementations, respectively.

v2: kick out conflicting framebuffers before initializing fbdev
v3: rebase onto drm/tegra/for-next

Tested-by: Dmitry Osipenko <digetx@gmail.com>
Signed-off-by: Thierry Reding <treding@nvidia.com>
drivers/gpu/drm/tegra/drm.c

index b74362cb63ebdd174ea4feedf2b408fa445443e6..7480f575188ddbac059138221475fffe64727221 100644 (file)
@@ -86,168 +86,6 @@ tegra_drm_mode_config_helpers = {
        .atomic_commit_tail = tegra_atomic_commit_tail,
 };
 
-static int tegra_drm_load(struct drm_device *drm, unsigned long flags)
-{
-       struct host1x_device *device = to_host1x_device(drm->dev);
-       struct tegra_drm *tegra;
-       int err;
-
-       tegra = kzalloc(sizeof(*tegra), GFP_KERNEL);
-       if (!tegra)
-               return -ENOMEM;
-
-       if (iommu_present(&platform_bus_type)) {
-               tegra->domain = iommu_domain_alloc(&platform_bus_type);
-               if (!tegra->domain) {
-                       err = -ENOMEM;
-                       goto free;
-               }
-
-               err = iova_cache_get();
-               if (err < 0)
-                       goto domain;
-       }
-
-       mutex_init(&tegra->clients_lock);
-       INIT_LIST_HEAD(&tegra->clients);
-
-       drm->dev_private = tegra;
-       tegra->drm = drm;
-
-       drm_mode_config_init(drm);
-
-       drm->mode_config.min_width = 0;
-       drm->mode_config.min_height = 0;
-
-       drm->mode_config.max_width = 4096;
-       drm->mode_config.max_height = 4096;
-
-       drm->mode_config.allow_fb_modifiers = true;
-
-       drm->mode_config.normalize_zpos = true;
-
-       drm->mode_config.funcs = &tegra_drm_mode_config_funcs;
-       drm->mode_config.helper_private = &tegra_drm_mode_config_helpers;
-
-       err = tegra_drm_fb_prepare(drm);
-       if (err < 0)
-               goto config;
-
-       drm_kms_helper_poll_init(drm);
-
-       err = host1x_device_init(device);
-       if (err < 0)
-               goto fbdev;
-
-       if (tegra->domain) {
-               u64 carveout_start, carveout_end, gem_start, gem_end;
-               u64 dma_mask = dma_get_mask(&device->dev);
-               dma_addr_t start, end;
-               unsigned long order;
-
-               start = tegra->domain->geometry.aperture_start & dma_mask;
-               end = tegra->domain->geometry.aperture_end & dma_mask;
-
-               gem_start = start;
-               gem_end = end - CARVEOUT_SZ;
-               carveout_start = gem_end + 1;
-               carveout_end = end;
-
-               order = __ffs(tegra->domain->pgsize_bitmap);
-               init_iova_domain(&tegra->carveout.domain, 1UL << order,
-                                carveout_start >> order);
-
-               tegra->carveout.shift = iova_shift(&tegra->carveout.domain);
-               tegra->carveout.limit = carveout_end >> tegra->carveout.shift;
-
-               drm_mm_init(&tegra->mm, gem_start, gem_end - gem_start + 1);
-               mutex_init(&tegra->mm_lock);
-
-               DRM_DEBUG_DRIVER("IOMMU apertures:\n");
-               DRM_DEBUG_DRIVER("  GEM: %#llx-%#llx\n", gem_start, gem_end);
-               DRM_DEBUG_DRIVER("  Carveout: %#llx-%#llx\n", carveout_start,
-                                carveout_end);
-       }
-
-       if (tegra->hub) {
-               err = tegra_display_hub_prepare(tegra->hub);
-               if (err < 0)
-                       goto device;
-       }
-
-       /*
-        * We don't use the drm_irq_install() helpers provided by the DRM
-        * core, so we need to set this manually in order to allow the
-        * DRM_IOCTL_WAIT_VBLANK to operate correctly.
-        */
-       drm->irq_enabled = true;
-
-       /* syncpoints are used for full 32-bit hardware VBLANK counters */
-       drm->max_vblank_count = 0xffffffff;
-
-       err = drm_vblank_init(drm, drm->mode_config.num_crtc);
-       if (err < 0)
-               goto hub;
-
-       drm_mode_config_reset(drm);
-
-       err = tegra_drm_fb_init(drm);
-       if (err < 0)
-               goto hub;
-
-       return 0;
-
-hub:
-       if (tegra->hub)
-               tegra_display_hub_cleanup(tegra->hub);
-device:
-       if (tegra->domain) {
-               mutex_destroy(&tegra->mm_lock);
-               drm_mm_takedown(&tegra->mm);
-               put_iova_domain(&tegra->carveout.domain);
-               iova_cache_put();
-       }
-
-       host1x_device_exit(device);
-fbdev:
-       drm_kms_helper_poll_fini(drm);
-       tegra_drm_fb_free(drm);
-config:
-       drm_mode_config_cleanup(drm);
-domain:
-       if (tegra->domain)
-               iommu_domain_free(tegra->domain);
-free:
-       kfree(tegra);
-       return err;
-}
-
-static void tegra_drm_unload(struct drm_device *drm)
-{
-       struct host1x_device *device = to_host1x_device(drm->dev);
-       struct tegra_drm *tegra = drm->dev_private;
-       int err;
-
-       drm_kms_helper_poll_fini(drm);
-       tegra_drm_fb_exit(drm);
-       drm_atomic_helper_shutdown(drm);
-       drm_mode_config_cleanup(drm);
-
-       err = host1x_device_exit(device);
-       if (err < 0)
-               return;
-
-       if (tegra->domain) {
-               mutex_destroy(&tegra->mm_lock);
-               drm_mm_takedown(&tegra->mm);
-               put_iova_domain(&tegra->carveout.domain);
-               iova_cache_put();
-               iommu_domain_free(tegra->domain);
-       }
-
-       kfree(tegra);
-}
-
 static int tegra_drm_open(struct drm_device *drm, struct drm_file *filp)
 {
        struct tegra_drm_file *fpriv;
@@ -1014,8 +852,6 @@ static int tegra_debugfs_init(struct drm_minor *minor)
 static struct drm_driver tegra_drm_driver = {
        .driver_features = DRIVER_MODESET | DRIVER_GEM |
                           DRIVER_ATOMIC | DRIVER_RENDER,
-       .load = tegra_drm_load,
-       .unload = tegra_drm_unload,
        .open = tegra_drm_open,
        .postclose = tegra_drm_postclose,
        .lastclose = drm_fb_helper_lastclose,
@@ -1202,6 +1038,7 @@ void tegra_drm_free(struct tegra_drm *tegra, size_t size, void *virt,
 static int host1x_drm_probe(struct host1x_device *dev)
 {
        struct drm_driver *driver = &tegra_drm_driver;
+       struct tegra_drm *tegra;
        struct drm_device *drm;
        int err;
 
@@ -1209,18 +1046,147 @@ static int host1x_drm_probe(struct host1x_device *dev)
        if (IS_ERR(drm))
                return PTR_ERR(drm);
 
+       tegra = kzalloc(sizeof(*tegra), GFP_KERNEL);
+       if (!tegra) {
+               err = -ENOMEM;
+               goto put;
+       }
+
+       if (iommu_present(&platform_bus_type)) {
+               tegra->domain = iommu_domain_alloc(&platform_bus_type);
+               if (!tegra->domain) {
+                       err = -ENOMEM;
+                       goto free;
+               }
+
+               err = iova_cache_get();
+               if (err < 0)
+                       goto domain;
+       }
+
+       mutex_init(&tegra->clients_lock);
+       INIT_LIST_HEAD(&tegra->clients);
+
        dev_set_drvdata(&dev->dev, drm);
+       drm->dev_private = tegra;
+       tegra->drm = drm;
+
+       drm_mode_config_init(drm);
+
+       drm->mode_config.min_width = 0;
+       drm->mode_config.min_height = 0;
+
+       drm->mode_config.max_width = 4096;
+       drm->mode_config.max_height = 4096;
+
+       drm->mode_config.allow_fb_modifiers = true;
+
+       drm->mode_config.normalize_zpos = true;
 
-       err = drm_fb_helper_remove_conflicting_framebuffers(NULL, "tegradrmfb", false);
+       drm->mode_config.funcs = &tegra_drm_mode_config_funcs;
+       drm->mode_config.helper_private = &tegra_drm_mode_config_helpers;
+
+       err = tegra_drm_fb_prepare(drm);
        if (err < 0)
-               goto put;
+               goto config;
+
+       drm_kms_helper_poll_init(drm);
+
+       err = host1x_device_init(dev);
+       if (err < 0)
+               goto fbdev;
+
+       if (tegra->domain) {
+               u64 carveout_start, carveout_end, gem_start, gem_end;
+               u64 dma_mask = dma_get_mask(&dev->dev);
+               dma_addr_t start, end;
+               unsigned long order;
+
+               start = tegra->domain->geometry.aperture_start & dma_mask;
+               end = tegra->domain->geometry.aperture_end & dma_mask;
+
+               gem_start = start;
+               gem_end = end - CARVEOUT_SZ;
+               carveout_start = gem_end + 1;
+               carveout_end = end;
+
+               order = __ffs(tegra->domain->pgsize_bitmap);
+               init_iova_domain(&tegra->carveout.domain, 1UL << order,
+                                carveout_start >> order);
+
+               tegra->carveout.shift = iova_shift(&tegra->carveout.domain);
+               tegra->carveout.limit = carveout_end >> tegra->carveout.shift;
+
+               drm_mm_init(&tegra->mm, gem_start, gem_end - gem_start + 1);
+               mutex_init(&tegra->mm_lock);
+
+               DRM_DEBUG_DRIVER("IOMMU apertures:\n");
+               DRM_DEBUG_DRIVER("  GEM: %#llx-%#llx\n", gem_start, gem_end);
+               DRM_DEBUG_DRIVER("  Carveout: %#llx-%#llx\n", carveout_start,
+                                carveout_end);
+       }
+
+       if (tegra->hub) {
+               err = tegra_display_hub_prepare(tegra->hub);
+               if (err < 0)
+                       goto device;
+       }
+
+       /*
+        * We don't use the drm_irq_install() helpers provided by the DRM
+        * core, so we need to set this manually in order to allow the
+        * DRM_IOCTL_WAIT_VBLANK to operate correctly.
+        */
+       drm->irq_enabled = true;
+
+       /* syncpoints are used for full 32-bit hardware VBLANK counters */
+       drm->max_vblank_count = 0xffffffff;
+
+       err = drm_vblank_init(drm, drm->mode_config.num_crtc);
+       if (err < 0)
+               goto hub;
+
+       drm_mode_config_reset(drm);
+
+       err = drm_fb_helper_remove_conflicting_framebuffers(NULL, "tegradrmfb",
+                                                           false);
+       if (err < 0)
+               goto hub;
+
+       err = tegra_drm_fb_init(drm);
+       if (err < 0)
+               goto hub;
 
        err = drm_dev_register(drm, 0);
        if (err < 0)
-               goto put;
+               goto fb;
 
        return 0;
 
+fb:
+       tegra_drm_fb_exit(drm);
+hub:
+       if (tegra->hub)
+               tegra_display_hub_cleanup(tegra->hub);
+device:
+       if (tegra->domain) {
+               mutex_destroy(&tegra->mm_lock);
+               drm_mm_takedown(&tegra->mm);
+               put_iova_domain(&tegra->carveout.domain);
+               iova_cache_put();
+       }
+
+       host1x_device_exit(dev);
+fbdev:
+       drm_kms_helper_poll_fini(drm);
+       tegra_drm_fb_free(drm);
+config:
+       drm_mode_config_cleanup(drm);
+domain:
+       if (tegra->domain)
+               iommu_domain_free(tegra->domain);
+free:
+       kfree(tegra);
 put:
        drm_dev_put(drm);
        return err;
@@ -1229,8 +1195,29 @@ put:
 static int host1x_drm_remove(struct host1x_device *dev)
 {
        struct drm_device *drm = dev_get_drvdata(&dev->dev);
+       struct tegra_drm *tegra = drm->dev_private;
+       int err;
 
        drm_dev_unregister(drm);
+
+       drm_kms_helper_poll_fini(drm);
+       tegra_drm_fb_exit(drm);
+       drm_atomic_helper_shutdown(drm);
+       drm_mode_config_cleanup(drm);
+
+       err = host1x_device_exit(dev);
+       if (err < 0)
+               dev_err(&dev->dev, "host1x device cleanup failed: %d\n", err);
+
+       if (tegra->domain) {
+               mutex_destroy(&tegra->mm_lock);
+               drm_mm_takedown(&tegra->mm);
+               put_iova_domain(&tegra->carveout.domain);
+               iova_cache_put();
+               iommu_domain_free(tegra->domain);
+       }
+
+       kfree(tegra);
        drm_dev_put(drm);
 
        return 0;