summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorDave Airlie <airlied@redhat.com>2009-01-19 17:17:58 +1000
committerDave Airlie <airlied@redhat.com>2009-01-19 17:17:58 +1000
commitc1ff85d97708550e634fb6fa099c463db90fc40d (patch)
tree58d06ba7fb375232ec614bc78db39faceb7898c6
parent1de9e8e70f5acc441550ca75433563d91b269bbe (diff)
drm: fix leak of device mappings since multi-master changes.
Device maps now contain a link to the master that created them, so when cleaning up the master, remove any maps that are connected to it. Also delete any remaining maps at driver unload time. Signed-off-by: Dave Airlie <airlied@redhat.com>
-rw-r--r--drivers/gpu/drm/drm_drv.c4
-rw-r--r--drivers/gpu/drm/drm_stub.c8
2 files changed, 12 insertions, 0 deletions
diff --git a/drivers/gpu/drm/drm_drv.c b/drivers/gpu/drm/drm_drv.c
index 5ff88d95222..14c7a23dc15 100644
--- a/drivers/gpu/drm/drm_drv.c
+++ b/drivers/gpu/drm/drm_drv.c
@@ -294,6 +294,7 @@ EXPORT_SYMBOL(drm_init);
*/
static void drm_cleanup(struct drm_device * dev)
{
+ struct drm_map_list *r_list, *list_temp;
DRM_DEBUG("\n");
if (!dev) {
@@ -325,6 +326,9 @@ static void drm_cleanup(struct drm_device * dev)
drm_ht_remove(&dev->map_hash);
drm_ctxbitmap_cleanup(dev);
+ list_for_each_entry_safe(r_list, list_temp, &dev->maplist, head)
+ drm_rmmap(dev, r_list->map);
+
if (drm_core_check_feature(dev, DRIVER_MODESET))
drm_put_minor(&dev->control);
diff --git a/drivers/gpu/drm/drm_stub.c b/drivers/gpu/drm/drm_stub.c
index 5ca132afa4f..46bb923b097 100644
--- a/drivers/gpu/drm/drm_stub.c
+++ b/drivers/gpu/drm/drm_stub.c
@@ -118,12 +118,20 @@ static void drm_master_destroy(struct kref *kref)
struct drm_master *master = container_of(kref, struct drm_master, refcount);
struct drm_magic_entry *pt, *next;
struct drm_device *dev = master->minor->dev;
+ struct drm_map_list *r_list, *list_temp;
list_del(&master->head);
if (dev->driver->master_destroy)
dev->driver->master_destroy(dev, master);
+ list_for_each_entry_safe(r_list, list_temp, &dev->maplist, head) {
+ if (r_list->master == master) {
+ drm_rmmap_locked(dev, r_list->map);
+ r_list = NULL;
+ }
+ }
+
if (master->unique) {
drm_free(master->unique, master->unique_size, DRM_MEM_DRIVER);
master->unique = NULL;