diff options
author | Dave Airlie <airlied@redhat.com> | 2008-11-28 04:43:47 +0100 |
---|---|---|
committer | Dave Airlie <airlied@linux.ie> | 2008-12-29 08:47:21 +0100 |
commit | e7f7ab45ebcb54fd5f814ea15ea079e079662f67 (patch) | |
tree | 53e8206501c0b7a00831ea084b52664f7899d1c0 | |
parent | Linux 2.6.28 (diff) | |
download | linux-e7f7ab45ebcb54fd5f814ea15ea079e079662f67.tar.xz linux-e7f7ab45ebcb54fd5f814ea15ea079e079662f67.zip |
drm: cleanup exit path for module unload
The current sub-module unload exit path is a mess, it tries
to abuse the idr. Just keep a list of devices per driver struct
and free them in-order on rmmod.
Signed-off-by: Dave Airlie <airlied@redhat.com>
-rw-r--r-- | drivers/gpu/drm/drm_drv.c | 25 | ||||
-rw-r--r-- | drivers/gpu/drm/drm_stub.c | 2 | ||||
-rw-r--r-- | include/drm/drmP.h | 3 |
3 files changed, 10 insertions, 20 deletions
diff --git a/drivers/gpu/drm/drm_drv.c b/drivers/gpu/drm/drm_drv.c index 996097acb5e7..3cb87a932b33 100644 --- a/drivers/gpu/drm/drm_drv.c +++ b/drivers/gpu/drm/drm_drv.c @@ -263,6 +263,8 @@ int drm_init(struct drm_driver *driver) DRM_DEBUG("\n"); + INIT_LIST_HEAD(&driver->device_list); + for (i = 0; driver->pci_driver.id_table[i].vendor != 0; i++) { pid = (struct pci_device_id *)&driver->pci_driver.id_table[i]; @@ -334,30 +336,13 @@ static void drm_cleanup(struct drm_device * dev) DRM_ERROR("Cannot unload module\n"); } -static int drm_minors_cleanup(int id, void *ptr, void *data) -{ - struct drm_minor *minor = ptr; - struct drm_device *dev; - struct drm_driver *driver = data; - - dev = minor->dev; - if (minor->dev->driver != driver) - return 0; - - if (minor->type != DRM_MINOR_LEGACY) - return 0; - - if (dev) - pci_dev_put(dev->pdev); - drm_cleanup(dev); - return 1; -} - void drm_exit(struct drm_driver *driver) { + struct drm_device *dev, *tmp; DRM_DEBUG("\n"); - idr_for_each(&drm_minors_idr, &drm_minors_cleanup, driver); + list_for_each_entry_safe(dev, tmp, &driver->device_list, driver_item) + drm_cleanup(dev); DRM_INFO("Module unloaded\n"); } diff --git a/drivers/gpu/drm/drm_stub.c b/drivers/gpu/drm/drm_stub.c index 66c96ec66672..849c0a9fe7fd 100644 --- a/drivers/gpu/drm/drm_stub.c +++ b/drivers/gpu/drm/drm_stub.c @@ -270,6 +270,8 @@ int drm_get_dev(struct pci_dev *pdev, const struct pci_device_id *ent, if ((ret = drm_get_minor(dev, &dev->primary, DRM_MINOR_LEGACY))) goto err_g2; + list_add_tail(&dev->driver_item, &driver->device_list); + DRM_INFO("Initialized %s %d.%d.%d %s on minor %d\n", driver->name, driver->major, driver->minor, driver->patchlevel, driver->date, dev->primary->index); diff --git a/include/drm/drmP.h b/include/drm/drmP.h index d5e8e5c89548..08b8539e7b3c 100644 --- a/include/drm/drmP.h +++ b/include/drm/drmP.h @@ -737,6 +737,8 @@ struct drm_driver { int num_ioctls; struct file_operations fops; struct pci_driver pci_driver; + /* List of devices hanging off this driver */ + struct list_head device_list; }; #define DRM_MINOR_UNASSIGNED 0 @@ -759,6 +761,7 @@ struct drm_minor { * may contain multiple heads. */ struct drm_device { + struct list_head driver_item; /**< list of devices per driver */ char *unique; /**< Unique identifier: e.g., busid */ int unique_len; /**< Length of unique field */ char *devname; /**< For /proc/interrupts */ |