drm: cleanup exit path for module unload
authorDave Airlie <airlied@redhat.com>
Fri, 28 Nov 2008 03:43:47 +0000 (13:43 +1000)
committerDave Airlie <airlied@linux.ie>
Mon, 29 Dec 2008 07:47:21 +0000 (17:47 +1000)
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>
drivers/gpu/drm/drm_drv.c
drivers/gpu/drm/drm_stub.c
include/drm/drmP.h

index 996097acb5e76b3c3d7698c0885f563ad9248522..3cb87a932b33f2dd4505197bb93b29070fa6b58c 100644 (file)
@@ -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");
 }
index 66c96ec66672ca2746dc70709772d8c780aea426..849c0a9fe7fde0823d81580b98a1528157235635 100644 (file)
@@ -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);
index d5e8e5c8954825baaf69564e07716dd041ed0593..08b8539e7b3c44e039363aa78b55ff1c8eb27be3 100644 (file)
@@ -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 */