aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorDave Airlie <airlied@redhat.com>2008-11-27 22:43:47 -0500
committerDave Airlie <airlied@linux.ie>2008-12-29 02:47:21 -0500
commite7f7ab45ebcb54fd5f814ea15ea079e079662f67 (patch)
tree53e8206501c0b7a00831ea084b52664f7899d1c0
parent4a6908a3a050aacc9c3a2f36b276b46c0629ad91 (diff)
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.c25
-rw-r--r--drivers/gpu/drm/drm_stub.c2
-rw-r--r--include/drm/drmP.h3
3 files changed, 10 insertions, 20 deletions
diff --git a/drivers/gpu/drm/drm_drv.c b/drivers/gpu/drm/drm_drv.c
index 996097acb5e..3cb87a932b3 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)
263 263
264 DRM_DEBUG("\n"); 264 DRM_DEBUG("\n");
265 265
266 INIT_LIST_HEAD(&driver->device_list);
267
266 for (i = 0; driver->pci_driver.id_table[i].vendor != 0; i++) { 268 for (i = 0; driver->pci_driver.id_table[i].vendor != 0; i++) {
267 pid = (struct pci_device_id *)&driver->pci_driver.id_table[i]; 269 pid = (struct pci_device_id *)&driver->pci_driver.id_table[i];
268 270
@@ -334,30 +336,13 @@ static void drm_cleanup(struct drm_device * dev)
334 DRM_ERROR("Cannot unload module\n"); 336 DRM_ERROR("Cannot unload module\n");
335} 337}
336 338
337static int drm_minors_cleanup(int id, void *ptr, void *data)
338{
339 struct drm_minor *minor = ptr;
340 struct drm_device *dev;
341 struct drm_driver *driver = data;
342
343 dev = minor->dev;
344 if (minor->dev->driver != driver)
345 return 0;
346
347 if (minor->type != DRM_MINOR_LEGACY)
348 return 0;
349
350 if (dev)
351 pci_dev_put(dev->pdev);
352 drm_cleanup(dev);
353 return 1;
354}
355
356void drm_exit(struct drm_driver *driver) 339void drm_exit(struct drm_driver *driver)
357{ 340{
341 struct drm_device *dev, *tmp;
358 DRM_DEBUG("\n"); 342 DRM_DEBUG("\n");
359 343
360 idr_for_each(&drm_minors_idr, &drm_minors_cleanup, driver); 344 list_for_each_entry_safe(dev, tmp, &driver->device_list, driver_item)
345 drm_cleanup(dev);
361 346
362 DRM_INFO("Module unloaded\n"); 347 DRM_INFO("Module unloaded\n");
363} 348}
diff --git a/drivers/gpu/drm/drm_stub.c b/drivers/gpu/drm/drm_stub.c
index 66c96ec6667..849c0a9fe7f 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,
270 if ((ret = drm_get_minor(dev, &dev->primary, DRM_MINOR_LEGACY))) 270 if ((ret = drm_get_minor(dev, &dev->primary, DRM_MINOR_LEGACY)))
271 goto err_g2; 271 goto err_g2;
272 272
273 list_add_tail(&dev->driver_item, &driver->device_list);
274
273 DRM_INFO("Initialized %s %d.%d.%d %s on minor %d\n", 275 DRM_INFO("Initialized %s %d.%d.%d %s on minor %d\n",
274 driver->name, driver->major, driver->minor, driver->patchlevel, 276 driver->name, driver->major, driver->minor, driver->patchlevel,
275 driver->date, dev->primary->index); 277 driver->date, dev->primary->index);
diff --git a/include/drm/drmP.h b/include/drm/drmP.h
index d5e8e5c8954..08b8539e7b3 100644
--- a/include/drm/drmP.h
+++ b/include/drm/drmP.h
@@ -737,6 +737,8 @@ struct drm_driver {
737 int num_ioctls; 737 int num_ioctls;
738 struct file_operations fops; 738 struct file_operations fops;
739 struct pci_driver pci_driver; 739 struct pci_driver pci_driver;
740 /* List of devices hanging off this driver */
741 struct list_head device_list;
740}; 742};
741 743
742#define DRM_MINOR_UNASSIGNED 0 744#define DRM_MINOR_UNASSIGNED 0
@@ -759,6 +761,7 @@ struct drm_minor {
759 * may contain multiple heads. 761 * may contain multiple heads.
760 */ 762 */
761struct drm_device { 763struct drm_device {
764 struct list_head driver_item; /**< list of devices per driver */
762 char *unique; /**< Unique identifier: e.g., busid */ 765 char *unique; /**< Unique identifier: e.g., busid */
763 int unique_len; /**< Length of unique field */ 766 int unique_len; /**< Length of unique field */
764 char *devname; /**< For /proc/interrupts */ 767 char *devname; /**< For /proc/interrupts */