drm: add _DRM_DRIVER flag, and re-order unload.

Allow drivers to addmaps that won't be removed by lastclose or unload.
The unload needs to be re-ordered to avoid removing the hashs before
the driver has removed the final maps.

Signed-off-by: Dave Airlie <airlied@linux.ie>
diff --git a/drivers/char/drm/drm.h b/drivers/char/drm/drm.h
index 82fb3d0..3a05c6d 100644
--- a/drivers/char/drm/drm.h
+++ b/drivers/char/drm/drm.h
@@ -202,7 +202,8 @@
 	_DRM_KERNEL = 0x08,	     /**< kernel requires access */
 	_DRM_WRITE_COMBINING = 0x10, /**< use write-combining if available */
 	_DRM_CONTAINS_LOCK = 0x20,   /**< SHM page that contains lock */
-	_DRM_REMOVABLE = 0x40	     /**< Removable mapping */
+	_DRM_REMOVABLE = 0x40,	     /**< Removable mapping */
+	_DRM_DRIVER = 0x80	     /**< Managed by driver */
 };
 
 struct drm_ctx_priv_map {
diff --git a/drivers/char/drm/drm_drv.c b/drivers/char/drm/drm_drv.c
index d29d7ed..77e2fb7 100644
--- a/drivers/char/drm/drm_drv.c
+++ b/drivers/char/drm/drm_drv.c
@@ -200,8 +200,10 @@
 	}
 
 	list_for_each_entry_safe(r_list, list_t, &dev->maplist, head) {
-		drm_rmmap_locked(dev, r_list->map);
-		r_list = NULL;
+		if (!(r_list->map->flags & _DRM_DRIVER)) {
+			drm_rmmap_locked(dev, r_list->map);
+			r_list = NULL;
+		}
 	}
 
 	if (drm_core_check_feature(dev, DRIVER_DMA_QUEUE) && dev->queuelist) {
@@ -291,10 +293,6 @@
 
 	drm_lastclose(dev);
 
-	drm_ht_remove(&dev->map_hash);
-
-	drm_ctxbitmap_cleanup(dev);
-
 	if (drm_core_has_MTRR(dev) && drm_core_has_AGP(dev) &&
 	    dev->agp && dev->agp->agp_mtrr >= 0) {
 		int retval;
@@ -312,6 +310,9 @@
 	if (dev->driver->unload)
 		dev->driver->unload(dev);
 
+	drm_ht_remove(&dev->map_hash);
+	drm_ctxbitmap_cleanup(dev);
+
 	drm_put_head(&dev->primary);
 	if (drm_put_dev(dev))
 		DRM_ERROR("Cannot unload module\n");
diff --git a/drivers/char/drm/i915_dma.c b/drivers/char/drm/i915_dma.c
index b8db965..24f86e0 100644
--- a/drivers/char/drm/i915_dma.c
+++ b/drivers/char/drm/i915_dma.c
@@ -778,7 +778,8 @@
 	base = drm_get_resource_start(dev, mmio_bar);
 	size = drm_get_resource_len(dev, mmio_bar);
 
-	ret = drm_addmap(dev, base, size, _DRM_REGISTERS, _DRM_KERNEL,
+	ret = drm_addmap(dev, base, size, _DRM_REGISTERS,
+			 _DRM_KERNEL | _DRM_DRIVER,
 			 &dev_priv->mmio_map);
 	return ret;
 }