The DRM design includes ioctls to allow a userland driver to tell the kernel 
driver when to register its interrupt handler and on what IRQ.  This is a 
really bad idea for several reasons, and fortunately I don't think any DDX 
drivers take advantage of the "no, use this IRQ" aspect of the API (and even 
if they did the kernel driver would have to ignore it).

This patch removes the DRM support for those ioctls, making drivers just 
register their interrupt handlers at load time.  The patch is fairly 
straightforward but there are still caveats, so each driver will need careful 
review to make sure that userland drivers don't set up additional state 
required for proper interrupt handling/enabling.  It also means drivers have 
to map registers at load time; the r128 bits in particular looked funky in 
that regard so extra eyes there would be appreciated.

I've only tested this patch so far on i915, where it's still slightly broken; 
I was planning on fixing it once I've sync'd some more linux-core changes 
into drm-next (namely the rest of the vblank-rework code).

 drivers/gpu/drm/drm_ioctl.c         |    2                                
 drivers/gpu/drm/drm_irq.c           |   82 +++++++----------
 drivers/gpu/drm/i810/i810_dma.c     |    7 -
 drivers/gpu/drm/i830/i830_dma.c     |    7 -
 drivers/gpu/drm/i915/i915_dma.c     |   48 ++++++++-
 drivers/gpu/drm/i915/i915_drv.c     |    3
 drivers/gpu/drm/i915/i915_drv.h     |    7 +
 drivers/gpu/drm/i915/i915_irq.c     |   62 ------------
 drivers/gpu/drm/mga/mga_dma.c       |   37 ++++++-
 drivers/gpu/drm/mga/mga_drv.c       |    3
 drivers/gpu/drm/mga/mga_irq.c       |   32 ------
 drivers/gpu/drm/r128/r128_cce.c     |  115 ++++++++++++++---------
 drivers/gpu/drm/r128/r128_drv.c     |    8 +
 drivers/gpu/drm/r128/r128_irq.c     |   28 -----
 drivers/gpu/drm/radeon/radeon_cp.c  |   43 +++++---
 drivers/gpu/drm/radeon/radeon_drv.c |    3
 drivers/gpu/drm/radeon/radeon_drv.h |    9 +
 drivers/gpu/drm/radeon/radeon_irq.c |   50 ----------
 drivers/gpu/drm/via/via_drv.c       |    3
 drivers/gpu/drm/via/via_drv.h       |   46 +++++++++
 drivers/gpu/drm/via/via_irq.c       |  135 +---------------------------
 drivers/gpu/drm/via/via_map.c       |   67 +++++++++++++
 drivers/gpu/drm/via/via_mm.c        |    2
 include/drm/drmP.h                  |   13 +-
 24 files changed, 355 insertions(+), 457 deletions(-)

Thanks,
-- 
Jesse Barnes, Intel Open Source Technology Center


diff --git a/drivers/gpu/drm/drm_ioctl.c b/drivers/gpu/drm/drm_ioctl.c
index 16829fb..3daefef 100644
--- a/drivers/gpu/drm/drm_ioctl.c
+++ b/drivers/gpu/drm/drm_ioctl.c
@@ -125,7 +125,7 @@ int drm_setunique(struct drm_device *dev, void *data,
 	return 0;
 }
 
-static int drm_set_busid(struct drm_device * dev)
+int drm_set_busid(struct drm_device * dev)
 {
 	int len;
 
diff --git a/drivers/gpu/drm/drm_irq.c b/drivers/gpu/drm/drm_irq.c
index d6d6be4..25feb48 100644
--- a/drivers/gpu/drm/drm_irq.c
+++ b/drivers/gpu/drm/drm_irq.c
@@ -72,38 +72,35 @@ int drm_irq_by_busid(struct drm_device *dev, void *data,
 }
 
 /**
- * Install IRQ handler.
+ * drm_irq_install - ioctl to set up IRQ
+ * @dev: DRM device
  *
- * \param dev DRM device.
- * \param irq IRQ number.
+ * Back in the bad old days, userspace drivers would tell the DRM when
+ * to call request_irq().  This is a bad idea on several levels, so now
+ * we just stub out the old ioctl and let the kernel driver set things
+ * up at load time.
+ */
+int drm_irq_install(struct drm_device * dev)
+{
+	return 0;
+}
+
+/**
+ * drm_irq_init - setup core DRM irq structures
+ * @dev: DRM device
  *
- * Initializes the IRQ related data, and setups drm_device::vbl_queue. Installs the handler, calling the driver
- * \c drm_driver_irq_preinstall() and \c drm_driver_irq_postinstall() functions
- * before and after the installation.
+ * Drivers that support IRQs should call this at load time to initialize
+ * the core DRM IRQ handling structures and register their IRQ with the
+ * kernel.
  */
-static int drm_irq_install(struct drm_device * dev)
+int drm_irq_init(struct drm_device *dev)
 {
-	int ret;
 	unsigned long sh_flags = 0;
+	int ret;
 
-	if (!drm_core_check_feature(dev, DRIVER_HAVE_IRQ))
-		return -EINVAL;
-
-	if (dev->pdev->irq == 0)
-		return -EINVAL;
+	drm_set_busid(dev);
 
 	mutex_lock(&dev->struct_mutex);
-
-	/* Driver must have been initialized */
-	if (!dev->dev_private) {
-		mutex_unlock(&dev->struct_mutex);
-		return -EINVAL;
-	}
-
-	if (dev->irq_enabled) {
-		mutex_unlock(&dev->struct_mutex);
-		return -EBUSY;
-	}
 	dev->irq_enabled = 1;
 	mutex_unlock(&dev->struct_mutex);
 
@@ -120,9 +117,6 @@ static int drm_irq_install(struct drm_device * dev)
 		dev->vbl_pending = 0;
 	}
 
-	/* Before installing handler */
-	dev->driver->irq_preinstall(dev);
-
 	/* Install handler */
 	if (drm_core_check_feature(dev, DRIVER_IRQ_SHARED))
 		sh_flags = IRQF_SHARED;
@@ -139,46 +133,46 @@ static int drm_irq_install(struct drm_device * dev)
 		return ret;
 	}
 
-	/* After installing handler */
-	dev->driver->irq_postinstall(dev);
-
 	return 0;
 }
+EXPORT_SYMBOL(drm_irq_init);
 
 /**
- * Uninstall the IRQ handler.
+ * drm_irq_uninstall - ioctl to free IRQ
+ * @dev: DRM device
  *
- * \param dev DRM device.
- *
- * Calls the driver's \c drm_driver_irq_uninstall() function, and stops the irq.
+ * See description for drm_irq_install()--we don't actually let userspace
+ * control the IRQ anymore.
  */
 int drm_irq_uninstall(struct drm_device * dev)
 {
-	int irq_enabled;
+	return 0;
+}
 
-	if (!drm_core_check_feature(dev, DRIVER_HAVE_IRQ))
+/**
+ * drm_irq_teardown - clean up core DRM IRQ handling
+ * @dev: DRM device
+ *
+ * Clean up and free IRQ.  Call should be symmetric with drm_irq_init().
+ */
+int drm_irq_teardown(struct drm_device *dev)
+{
+	if (!dev->irq_enabled)
 		return -EINVAL;
 
 	mutex_lock(&dev->struct_mutex);
-	irq_enabled = dev->irq_enabled;
 	dev->irq_enabled = 0;
 	mutex_unlock(&dev->struct_mutex);
 
-	if (!irq_enabled)
-		return -EINVAL;
-
 	DRM_DEBUG("irq=%d\n", dev->pdev->irq);
 
-	dev->driver->irq_uninstall(dev);
-
 	free_irq(dev->pdev->irq, dev);
 
 	dev->locked_tasklet_func = NULL;
 
 	return 0;
 }
-
-EXPORT_SYMBOL(drm_irq_uninstall);
+EXPORT_SYMBOL(drm_irq_teardown);
 
 /**
  * IRQ control ioctl.
diff --git a/drivers/gpu/drm/i810/i810_dma.c b/drivers/gpu/drm/i810/i810_dma.c
index e5de8ea..d24309f 100644
--- a/drivers/gpu/drm/i810/i810_dma.c
+++ b/drivers/gpu/drm/i810/i810_dma.c
@@ -205,13 +205,6 @@ static int i810_dma_cleanup(struct drm_device * dev)
 {
 	struct drm_device_dma *dma = dev->dma;
 
-	/* Make sure interrupts are disabled here because the uninstall ioctl
-	 * may not have been called from userspace and after dev_private
-	 * is freed, it's too late.
-	 */
-	if (drm_core_check_feature(dev, DRIVER_HAVE_IRQ) && dev->irq_enabled)
-		drm_irq_uninstall(dev);
-
 	if (dev->dev_private) {
 		int i;
 		drm_i810_private_t *dev_priv =
diff --git a/drivers/gpu/drm/i830/i830_dma.c b/drivers/gpu/drm/i830/i830_dma.c
index a86ab30..34d7e93 100644
--- a/drivers/gpu/drm/i830/i830_dma.c
+++ b/drivers/gpu/drm/i830/i830_dma.c
@@ -209,13 +209,6 @@ static int i830_dma_cleanup(struct drm_device * dev)
 {
 	struct drm_device_dma *dma = dev->dma;
 
-	/* Make sure interrupts are disabled here because the uninstall ioctl
-	 * may not have been called from userspace and after dev_private
-	 * is freed, it's too late.
-	 */
-	if (dev->irq_enabled)
-		drm_irq_uninstall(dev);
-
 	if (dev->dev_private) {
 		int i;
 		drm_i830_private_t *dev_priv =
diff --git a/drivers/gpu/drm/i915/i915_dma.c b/drivers/gpu/drm/i915/i915_dma.c
index cead62f..4daefa8 100644
--- a/drivers/gpu/drm/i915/i915_dma.c
+++ b/drivers/gpu/drm/i915/i915_dma.c
@@ -135,12 +135,6 @@ void i915_kernel_lost_context(struct drm_device * dev)
 static int i915_dma_cleanup(struct drm_device * dev)
 {
 	drm_i915_private_t *dev_priv = dev->dev_private;
-	/* Make sure interrupts are disabled here because the uninstall ioctl
-	 * may not have been called from userspace and after dev_private
-	 * is freed, it's too late.
-	 */
-	if (dev->irq_enabled)
-		drm_irq_uninstall(dev);
 
 	if (dev_priv->ring.virtual_start) {
 		drm_core_ioremapfree(&dev_priv->ring.map, dev);
@@ -814,12 +808,54 @@ int i915_driver_load(struct drm_device *dev, unsigned long flags)
 
 	spin_lock_init(&dev_priv->user_irq_lock);
 
+	/* Disable IRQs before setting them up */
+	I915_WRITE(HWSTAM, 0xfffe);
+	I915_WRITE(IER, 0x0);
+	I915_WRITE(IMR, 0xffffffff);
+
+	drm_irq_init(dev);
+
+	spin_lock_init(&dev_priv->swaps_lock);
+	INIT_LIST_HEAD(&dev_priv->vbl_swaps.head);
+	dev_priv->swaps_pending = 0;
+
+	if (!dev_priv->vblank_pipe)
+		dev_priv->vblank_pipe = DRM_I915_VBLANK_PIPE_A;
+
+	/* Set initial unmasked IRQs to just the selected vblank pipes. */
+	dev_priv->irq_mask_reg = ~0;
+	if (dev_priv->vblank_pipe & DRM_I915_VBLANK_PIPE_A)
+		dev_priv->irq_mask_reg &= ~I915_DISPLAY_PIPE_A_VBLANK_INTERRUPT;
+	if (dev_priv->vblank_pipe & DRM_I915_VBLANK_PIPE_B)
+		dev_priv->irq_mask_reg &= ~I915_DISPLAY_PIPE_B_VBLANK_INTERRUPT;
+
+	dev_priv->irq_mask_reg &= I915_INTERRUPT_ENABLE_MASK;
+
+	I915_WRITE(IMR, dev_priv->irq_mask_reg);
+	I915_WRITE(IER, I915_INTERRUPT_ENABLE_MASK);
+	(void) I915_READ(IER);
+
+	opregion_enable_asle(dev);
+
+	DRM_INIT_WAITQUEUE(&dev_priv->irq_queue);
+
 	return ret;
 }
 
 int i915_driver_unload(struct drm_device *dev)
 {
 	struct drm_i915_private *dev_priv = dev->dev_private;
+	unsigned long temp;
+
+	/* Clear & disable IRQs */
+	I915_WRITE(HWSTAM, 0xffff);
+	I915_WRITE(IMR, 0xffff);
+	I915_WRITE(IER, 0x0);
+
+	temp = I915_READ(IIR);
+	I915_WRITE(IIR, temp);
+
+	drm_irq_teardown(dev);
 
 	if (dev->pdev->msi_enabled)
 		pci_disable_msi(dev->pdev);
diff --git a/drivers/gpu/drm/i915/i915_drv.c b/drivers/gpu/drm/i915/i915_drv.c
index d95eca2..b8546d2 100644
--- a/drivers/gpu/drm/i915/i915_drv.c
+++ b/drivers/gpu/drm/i915/i915_drv.c
@@ -556,9 +556,6 @@ static struct drm_driver driver = {
 	.device_is_agp = i915_driver_device_is_agp,
 	.vblank_wait = i915_driver_vblank_wait,
 	.vblank_wait2 = i915_driver_vblank_wait2,
-	.irq_preinstall = i915_driver_irq_preinstall,
-	.irq_postinstall = i915_driver_irq_postinstall,
-	.irq_uninstall = i915_driver_irq_uninstall,
 	.irq_handler = i915_driver_irq_handler,
 	.reclaim_buffers = drm_core_reclaim_buffers,
 	.get_map_ofs = drm_core_get_map_ofs,
diff --git a/drivers/gpu/drm/i915/i915_drv.h b/drivers/gpu/drm/i915/i915_drv.h
index e4bd01c..f107195 100644
--- a/drivers/gpu/drm/i915/i915_drv.h
+++ b/drivers/gpu/drm/i915/i915_drv.h
@@ -275,6 +275,13 @@ extern void intel_opregion_free(struct drm_device *dev);
 extern void opregion_asle_intr(struct drm_device *dev);
 extern void opregion_enable_asle(struct drm_device *dev);
 
+/** These are the interrupts used by the driver */
+#define I915_INTERRUPT_ENABLE_MASK (I915_USER_INTERRUPT |		\
+				    I915_DISPLAY_PIPE_A_VBLANK_INTERRUPT | \
+				    I915_DISPLAY_PIPE_B_VBLANK_INTERRUPT | \
+				    I915_ASLE_INTERRUPT |		\
+				    I915_DISPLAY_PIPE_B_EVENT_INTERRUPT)
+
 #define I915_READ(reg)          DRM_READ32(dev_priv->mmio_map, (reg))
 #define I915_WRITE(reg,val)     DRM_WRITE32(dev_priv->mmio_map, (reg), (val))
 #define I915_READ16(reg)	DRM_READ16(dev_priv->mmio_map, (reg))
diff --git a/drivers/gpu/drm/i915/i915_irq.c b/drivers/gpu/drm/i915/i915_irq.c
index ae7d3a8..fbb13a8 100644
--- a/drivers/gpu/drm/i915/i915_irq.c
+++ b/drivers/gpu/drm/i915/i915_irq.c
@@ -33,13 +33,6 @@
 
 #define MAX_NOPID ((u32)~0)
 
-/** These are the interrupts used by the driver */
-#define I915_INTERRUPT_ENABLE_MASK (I915_USER_INTERRUPT |		\
-				    I915_DISPLAY_PIPE_A_VBLANK_INTERRUPT | \
-				    I915_DISPLAY_PIPE_B_VBLANK_INTERRUPT | \
-				    I915_ASLE_INTERRUPT |		\
-				    I915_DISPLAY_PIPE_B_EVENT_INTERRUPT)
-
 void
 i915_enable_irq(drm_i915_private_t *dev_priv, u32 mask)
 {
@@ -637,58 +630,3 @@ int i915_vblank_swap(struct drm_device *dev, void *data,
 	return 0;
 }
 
-/* drm_dma.h hooks
-*/
-void i915_driver_irq_preinstall(struct drm_device * dev)
-{
-	drm_i915_private_t *dev_priv = (drm_i915_private_t *) dev->dev_private;
-
-	I915_WRITE(HWSTAM, 0xfffe);
-	I915_WRITE(IMR, 0x0);
-	I915_WRITE(IER, 0x0);
-}
-
-void i915_driver_irq_postinstall(struct drm_device * dev)
-{
-	drm_i915_private_t *dev_priv = (drm_i915_private_t *) dev->dev_private;
-
-	spin_lock_init(&dev_priv->swaps_lock);
-	INIT_LIST_HEAD(&dev_priv->vbl_swaps.head);
-	dev_priv->swaps_pending = 0;
-
-	if (!dev_priv->vblank_pipe)
-		dev_priv->vblank_pipe = DRM_I915_VBLANK_PIPE_A;
-
-	/* Set initial unmasked IRQs to just the selected vblank pipes. */
-	dev_priv->irq_mask_reg = ~0;
-	if (dev_priv->vblank_pipe & DRM_I915_VBLANK_PIPE_A)
-		dev_priv->irq_mask_reg &= ~I915_DISPLAY_PIPE_A_VBLANK_INTERRUPT;
-	if (dev_priv->vblank_pipe & DRM_I915_VBLANK_PIPE_B)
-		dev_priv->irq_mask_reg &= ~I915_DISPLAY_PIPE_B_VBLANK_INTERRUPT;
-
-	dev_priv->irq_mask_reg &= I915_INTERRUPT_ENABLE_MASK;
-
-	I915_WRITE(IMR, dev_priv->irq_mask_reg);
-	I915_WRITE(IER, I915_INTERRUPT_ENABLE_MASK);
-	(void) I915_READ(IER);
-
-	opregion_enable_asle(dev);
-
-	DRM_INIT_WAITQUEUE(&dev_priv->irq_queue);
-}
-
-void i915_driver_irq_uninstall(struct drm_device * dev)
-{
-	drm_i915_private_t *dev_priv = (drm_i915_private_t *) dev->dev_private;
-	u16 temp;
-
-	if (!dev_priv)
-		return;
-
-	I915_WRITE(HWSTAM, 0xffff);
-	I915_WRITE(IMR, 0xffff);
-	I915_WRITE(IER, 0x0);
-
-	temp = I915_READ(IIR);
-	I915_WRITE(IIR, temp);
-}
diff --git a/drivers/gpu/drm/mga/mga_dma.c b/drivers/gpu/drm/mga/mga_dma.c
index c1d12db..75f224b 100644
--- a/drivers/gpu/drm/mga/mga_dma.c
+++ b/drivers/gpu/drm/mga/mga_dma.c
@@ -396,6 +396,7 @@ int mga_freelist_put(struct drm_device * dev, struct drm_buf * buf)
 int mga_driver_load(struct drm_device * dev, unsigned long flags)
 {
 	drm_mga_private_t *dev_priv;
+	int ret = 0;
 
 	dev_priv = drm_alloc(sizeof(drm_mga_private_t), DRM_MEM_DRIVER);
 	if (!dev_priv)
@@ -410,11 +411,31 @@ int mga_driver_load(struct drm_device * dev, unsigned long flags)
 	dev_priv->mmio_base = drm_get_resource_start(dev, 1);
 	dev_priv->mmio_size = drm_get_resource_len(dev, 1);
 
+	ret = drm_addmap(dev, dev_priv->mmio_base, dev_priv->mmio_size,
+			 _DRM_REGISTERS, _DRM_KERNEL | _DRM_DRIVER,
+			 &dev_priv->mmio);
+	if (ret) {
+		DRM_ERROR("failed to map registers: %d\n", ret);
+		return ret;
+	}
+
 	dev->counters += 3;
 	dev->types[6] = _DRM_STAT_IRQ;
 	dev->types[7] = _DRM_STAT_PRIMARY;
 	dev->types[8] = _DRM_STAT_SECONDARY;
 
+	/* Disable *all* interrupts */
+	MGA_WRITE(MGA_IEN, 0);
+	/* Clear bits if they're already high */
+	MGA_WRITE(MGA_ICLEAR, ~0);
+
+	drm_irq_init(dev);
+
+	DRM_INIT_WAITQUEUE(&dev_priv->fence_queue);
+
+	/* Turn on vertical blank interrupt and soft trap interrupt. */
+	MGA_WRITE(MGA_IEN, MGA_VLINEIEN | MGA_SOFTRAPEN);
+
 	return 0;
 }
 
@@ -932,13 +953,6 @@ static int mga_do_cleanup_dma(struct drm_device *dev, int full_cleanup)
 	int err = 0;
 	DRM_DEBUG("\n");
 
-	/* Make sure interrupts are disabled here because the uninstall ioctl
-	 * may not have been called from userspace and after dev_private
-	 * is freed, it's too late.
-	 */
-	if (dev->irq_enabled)
-		drm_irq_uninstall(dev);
-
 	if (dev->dev_private) {
 		drm_mga_private_t *dev_priv = dev->dev_private;
 
@@ -1141,6 +1155,15 @@ int mga_dma_buffers(struct drm_device *dev, void *data,
  */
 int mga_driver_unload(struct drm_device * dev)
 {
+	drm_mga_private_t *dev_priv = (drm_mga_private_t *) dev->dev_private;
+
+	/* Disable *all* interrupts */
+	MGA_WRITE(MGA_IEN, 0);
+
+	drm_rmmap(dev, dev_priv->mmio);
+
+	drm_irq_teardown(dev);
+
 	drm_free(dev->dev_private, sizeof(drm_mga_private_t), DRM_MEM_DRIVER);
 	dev->dev_private = NULL;
 
diff --git a/drivers/gpu/drm/mga/mga_drv.c b/drivers/gpu/drm/mga/mga_drv.c
index 5572939..6aa8673 100644
--- a/drivers/gpu/drm/mga/mga_drv.c
+++ b/drivers/gpu/drm/mga/mga_drv.c
@@ -54,9 +54,6 @@ static struct drm_driver driver = {
 	.dma_quiescent = mga_driver_dma_quiescent,
 	.device_is_agp = mga_driver_device_is_agp,
 	.vblank_wait = mga_driver_vblank_wait,
-	.irq_preinstall = mga_driver_irq_preinstall,
-	.irq_postinstall = mga_driver_irq_postinstall,
-	.irq_uninstall = mga_driver_irq_uninstall,
 	.irq_handler = mga_driver_irq_handler,
 	.reclaim_buffers = drm_core_reclaim_buffers,
 	.get_map_ofs = drm_core_get_map_ofs,
diff --git a/drivers/gpu/drm/mga/mga_irq.c b/drivers/gpu/drm/mga/mga_irq.c
index 9302cb8..f643dc0 100644
--- a/drivers/gpu/drm/mga/mga_irq.c
+++ b/drivers/gpu/drm/mga/mga_irq.c
@@ -114,35 +114,3 @@ int mga_driver_fence_wait(struct drm_device * dev, unsigned int *sequence)
 
 	return ret;
 }
-
-void mga_driver_irq_preinstall(struct drm_device * dev)
-{
-	drm_mga_private_t *dev_priv = (drm_mga_private_t *) dev->dev_private;
-
-	/* Disable *all* interrupts */
-	MGA_WRITE(MGA_IEN, 0);
-	/* Clear bits if they're already high */
-	MGA_WRITE(MGA_ICLEAR, ~0);
-}
-
-void mga_driver_irq_postinstall(struct drm_device * dev)
-{
-	drm_mga_private_t *dev_priv = (drm_mga_private_t *) dev->dev_private;
-
-	DRM_INIT_WAITQUEUE(&dev_priv->fence_queue);
-
-	/* Turn on vertical blank interrupt and soft trap interrupt. */
-	MGA_WRITE(MGA_IEN, MGA_VLINEIEN | MGA_SOFTRAPEN);
-}
-
-void mga_driver_irq_uninstall(struct drm_device * dev)
-{
-	drm_mga_private_t *dev_priv = (drm_mga_private_t *) dev->dev_private;
-	if (!dev_priv)
-		return;
-
-	/* Disable *all* interrupts */
-	MGA_WRITE(MGA_IEN, 0);
-
-	dev->irq_enabled = 0;
-}
diff --git a/drivers/gpu/drm/r128/r128_cce.c b/drivers/gpu/drm/r128/r128_cce.c
index c31afbd..a5d8584 100644
--- a/drivers/gpu/drm/r128/r128_cce.c
+++ b/drivers/gpu/drm/r128/r128_cce.c
@@ -349,21 +349,14 @@ static void r128_cce_init_ring_buffer(struct drm_device * dev,
 
 static int r128_do_init_cce(struct drm_device * dev, drm_r128_init_t * init)
 {
-	drm_r128_private_t *dev_priv;
+	drm_r128_private_t *dev_priv = dev->dev_private;
 
 	DRM_DEBUG("\n");
 
-	dev_priv = drm_alloc(sizeof(drm_r128_private_t), DRM_MEM_DRIVER);
-	if (dev_priv == NULL)
-		return -ENOMEM;
-
-	memset(dev_priv, 0, sizeof(drm_r128_private_t));
-
 	dev_priv->is_pci = init->is_pci;
 
 	if (dev_priv->is_pci && !dev->sg) {
 		DRM_ERROR("PCI GART memory not allocated!\n");
-		dev->dev_private = (void *)dev_priv;
 		r128_do_cleanup_cce(dev);
 		return -EINVAL;
 	}
@@ -587,42 +580,6 @@ static int r128_do_init_cce(struct drm_device * dev, drm_r128_init_t * init)
 
 int r128_do_cleanup_cce(struct drm_device * dev)
 {
-
-	/* Make sure interrupts are disabled here because the uninstall ioctl
-	 * may not have been called from userspace and after dev_private
-	 * is freed, it's too late.
-	 */
-	if (dev->irq_enabled)
-		drm_irq_uninstall(dev);
-
-	if (dev->dev_private) {
-		drm_r128_private_t *dev_priv = dev->dev_private;
-
-#if __OS_HAS_AGP
-		if (!dev_priv->is_pci) {
-			if (dev_priv->cce_ring != NULL)
-				drm_core_ioremapfree(dev_priv->cce_ring, dev);
-			if (dev_priv->ring_rptr != NULL)
-				drm_core_ioremapfree(dev_priv->ring_rptr, dev);
-			if (dev->agp_buffer_map != NULL) {
-				drm_core_ioremapfree(dev->agp_buffer_map, dev);
-				dev->agp_buffer_map = NULL;
-			}
-		} else
-#endif
-		{
-			if (dev_priv->gart_info.bus_addr)
-				if (!drm_ati_pcigart_cleanup(dev,
-							&dev_priv->gart_info))
-					DRM_ERROR
-					    ("failed to cleanup PCI GART!\n");
-		}
-
-		drm_free(dev->dev_private, sizeof(drm_r128_private_t),
-			 DRM_MEM_DRIVER);
-		dev->dev_private = NULL;
-	}
-
 	return 0;
 }
 
@@ -644,6 +601,76 @@ int r128_cce_init(struct drm_device *dev, void *data, struct drm_file *file_priv
 	return -EINVAL;
 }
 
+int r128_driver_load(struct drm_device *dev, unsigned long flags)
+{
+	drm_r128_private_t *dev_priv;
+	int ret = 0;
+
+	dev_priv = drm_alloc(sizeof(drm_r128_private_t), DRM_MEM_DRIVER);
+	if (dev_priv == NULL)
+		return -ENOMEM;
+
+	memset(dev_priv, 0, sizeof(drm_r128_private_t));
+
+	dev->dev_private = (void *)dev_priv;
+
+	ret = drm_addmap(dev, drm_get_resource_start(dev, 2),
+			 drm_get_resource_len(dev, 2), _DRM_REGISTERS,
+			 _DRM_KERNEL | _DRM_DRIVER, &dev_priv->mmio);
+	if (ret != 0)
+		return ret;
+
+	/* Disable *all* interrupts */
+	R128_WRITE(R128_GEN_INT_CNTL, 0);
+	/* Clear vblank bit if it's already high */
+	R128_WRITE(R128_GEN_INT_STATUS, R128_CRTC_VBLANK_INT_AK);
+
+	R128_WRITE(R128_GEN_INT_CNTL, R128_CRTC_VBLANK_INT_EN);
+
+	return ret;
+}
+
+int r128_driver_unload(struct drm_device *dev)
+{
+	drm_r128_private_t *dev_priv = dev->dev_private;
+	/* Make sure interrupts are disabled here because the uninstall ioctl
+	 * may not have been called from userspace and after dev_private
+	 * is freed, it's too late.
+	 */
+	/* Disable *all* interrupts */
+	R128_WRITE(R128_GEN_INT_CNTL, 0);
+
+	drm_irq_teardown(dev);
+
+	drm_rmmap(dev, dev_priv->mmio);
+
+#if __OS_HAS_AGP
+	if (!dev_priv->is_pci) {
+		if (dev_priv->cce_ring != NULL)
+			drm_core_ioremapfree(dev_priv->cce_ring, dev);
+		if (dev_priv->ring_rptr != NULL)
+			drm_core_ioremapfree(dev_priv->ring_rptr, dev);
+		if (dev->agp_buffer_map != NULL) {
+			drm_core_ioremapfree(dev->agp_buffer_map, dev);
+			dev->agp_buffer_map = NULL;
+		}
+	} else
+#endif
+	{
+		if (dev_priv->gart_info.bus_addr)
+			if (!drm_ati_pcigart_cleanup(dev,
+						     &dev_priv->gart_info))
+				DRM_ERROR
+					("failed to cleanup PCI GART!\n");
+	}
+
+	drm_free(dev->dev_private, sizeof(drm_r128_private_t),
+		 DRM_MEM_DRIVER);
+	dev->dev_private = NULL;
+
+	return 0;
+}
+
 int r128_cce_start(struct drm_device *dev, void *data, struct drm_file *file_priv)
 {
 	drm_r128_private_t *dev_priv = dev->dev_private;
diff --git a/drivers/gpu/drm/r128/r128_drv.c b/drivers/gpu/drm/r128/r128_drv.c
index 6108e75..9699f25 100644
--- a/drivers/gpu/drm/r128/r128_drv.c
+++ b/drivers/gpu/drm/r128/r128_drv.c
@@ -40,18 +40,20 @@ static struct pci_device_id pciidlist[] = {
 	r128_PCI_IDS
 };
 
+extern int r128_driver_load(struct drm_device *dev, unsigned long flags);
+extern int r128_driver_unload(struct drm_device *dev);
+
 static struct drm_driver driver = {
 	.driver_features =
 	    DRIVER_USE_AGP | DRIVER_USE_MTRR | DRIVER_PCI_DMA | DRIVER_SG |
 	    DRIVER_HAVE_DMA | DRIVER_HAVE_IRQ | DRIVER_IRQ_SHARED |
 	    DRIVER_IRQ_VBL,
+	.load = r128_driver_load,
+	.unload = r128_driver_unload,
 	.dev_priv_size = sizeof(drm_r128_buf_priv_t),
 	.preclose = r128_driver_preclose,
 	.lastclose = r128_driver_lastclose,
 	.vblank_wait = r128_driver_vblank_wait,
-	.irq_preinstall = r128_driver_irq_preinstall,
-	.irq_postinstall = r128_driver_irq_postinstall,
-	.irq_uninstall = r128_driver_irq_uninstall,
 	.irq_handler = r128_driver_irq_handler,
 	.reclaim_buffers = drm_core_reclaim_buffers,
 	.get_map_ofs = drm_core_get_map_ofs,
diff --git a/drivers/gpu/drm/r128/r128_irq.c b/drivers/gpu/drm/r128/r128_irq.c
index c76fdca..027d4b1 100644
--- a/drivers/gpu/drm/r128/r128_irq.c
+++ b/drivers/gpu/drm/r128/r128_irq.c
@@ -71,31 +71,3 @@ int r128_driver_vblank_wait(struct drm_device * dev, unsigned int *sequence)
 
 	return ret;
 }
-
-void r128_driver_irq_preinstall(struct drm_device * dev)
-{
-	drm_r128_private_t *dev_priv = (drm_r128_private_t *) dev->dev_private;
-
-	/* Disable *all* interrupts */
-	R128_WRITE(R128_GEN_INT_CNTL, 0);
-	/* Clear vblank bit if it's already high */
-	R128_WRITE(R128_GEN_INT_STATUS, R128_CRTC_VBLANK_INT_AK);
-}
-
-void r128_driver_irq_postinstall(struct drm_device * dev)
-{
-	drm_r128_private_t *dev_priv = (drm_r128_private_t *) dev->dev_private;
-
-	/* Turn on VBL interrupt */
-	R128_WRITE(R128_GEN_INT_CNTL, R128_CRTC_VBLANK_INT_EN);
-}
-
-void r128_driver_irq_uninstall(struct drm_device * dev)
-{
-	drm_r128_private_t *dev_priv = (drm_r128_private_t *) dev->dev_private;
-	if (!dev_priv)
-		return;
-
-	/* Disable *all* interrupts */
-	R128_WRITE(R128_GEN_INT_CNTL, 0);
-}
diff --git a/drivers/gpu/drm/radeon/radeon_cp.c b/drivers/gpu/drm/radeon/radeon_cp.c
index 3331f88..0994ca8 100644
--- a/drivers/gpu/drm/radeon/radeon_cp.c
+++ b/drivers/gpu/drm/radeon/radeon_cp.c
@@ -1209,13 +1209,6 @@ static int radeon_do_cleanup_cp(struct drm_device * dev)
 	drm_radeon_private_t *dev_priv = dev->dev_private;
 	DRM_DEBUG("\n");
 
-	/* Make sure interrupts are disabled here because the uninstall ioctl
-	 * may not have been called from userspace and after dev_private
-	 * is freed, it's too late.
-	 */
-	if (dev->irq_enabled)
-		drm_irq_uninstall(dev);
-
 #if __OS_HAS_AGP
 	if (dev_priv->flags & RADEON_IS_AGP) {
 		if (dev_priv->cp_ring != NULL) {
@@ -1727,6 +1720,29 @@ int radeon_driver_load(struct drm_device *dev, unsigned long flags)
 	else
 		dev_priv->flags |= RADEON_IS_PCI;
 
+	dev_priv->gart_info.table_size = RADEON_PCIGART_TABLE_SIZE;
+
+	ret = drm_addmap(dev, drm_get_resource_start(dev, 2),
+			 drm_get_resource_len(dev, 2), _DRM_REGISTERS,
+			 _DRM_KERNEL | _DRM_DRIVER, &dev_priv->mmio);
+	if (ret != 0)
+		return ret;
+
+	/* Disable *all* interrupts */
+	RADEON_WRITE(RADEON_GEN_INT_CNTL, 0);
+
+	/* Clear bits if they're already high */
+	radeon_acknowledge_irqs(dev_priv, (RADEON_SW_INT_TEST_ACK |
+					   RADEON_CRTC_VBLANK_STAT |
+					   RADEON_CRTC2_VBLANK_STAT));
+
+	drm_irq_init(dev);
+
+	atomic_set(&dev_priv->swi_emitted, 0);
+	DRM_INIT_WAITQUEUE(&dev_priv->swi_queue);
+
+	radeon_enable_interrupt(dev);
+
 	DRM_DEBUG("%s card detected\n",
 		  ((dev_priv->flags & RADEON_IS_AGP) ? "AGP" : (((dev_priv->flags & RADEON_IS_PCIE) ? "PCIE" : "PCI"))));
 	return ret;
@@ -1741,18 +1757,11 @@ int radeon_driver_firstopen(struct drm_device *dev)
 	drm_local_map_t *map;
 	drm_radeon_private_t *dev_priv = dev->dev_private;
 
-	dev_priv->gart_info.table_size = RADEON_PCIGART_TABLE_SIZE;
-
-	ret = drm_addmap(dev, drm_get_resource_start(dev, 2),
-			 drm_get_resource_len(dev, 2), _DRM_REGISTERS,
-			 _DRM_READ_ONLY, &dev_priv->mmio);
-	if (ret != 0)
-		return ret;
-
 	dev_priv->fb_aper_offset = drm_get_resource_start(dev, 0);
 	ret = drm_addmap(dev, dev_priv->fb_aper_offset,
 			 drm_get_resource_len(dev, 0), _DRM_FRAME_BUFFER,
-			 _DRM_WRITE_COMBINING, &map);
+			 _DRM_WRITE_COMBINING | _DRM_KERNEL | _DRM_DRIVER,
+			 &map);
 	if (ret != 0)
 		return ret;
 
@@ -1764,6 +1773,8 @@ int radeon_driver_unload(struct drm_device *dev)
 	drm_radeon_private_t *dev_priv = dev->dev_private;
 
 	DRM_DEBUG("\n");
+	RADEON_WRITE(RADEON_GEN_INT_CNTL, 0);
+	drm_rmmap(dev, dev_priv->mmio);
 	drm_free(dev_priv, sizeof(*dev_priv), DRM_MEM_DRIVER);
 
 	dev->dev_private = NULL;
diff --git a/drivers/gpu/drm/radeon/radeon_drv.c b/drivers/gpu/drm/radeon/radeon_drv.c
index 349ac3d..7942a30 100644
--- a/drivers/gpu/drm/radeon/radeon_drv.c
+++ b/drivers/gpu/drm/radeon/radeon_drv.c
@@ -72,9 +72,6 @@ static struct drm_driver driver = {
 	.vblank_wait = radeon_driver_vblank_wait,
 	.vblank_wait2 = radeon_driver_vblank_wait2,
 	.dri_library_name = dri_library_name,
-	.irq_preinstall = radeon_driver_irq_preinstall,
-	.irq_postinstall = radeon_driver_irq_postinstall,
-	.irq_uninstall = radeon_driver_irq_uninstall,
 	.irq_handler = radeon_driver_irq_handler,
 	.reclaim_buffers = drm_core_reclaim_buffers,
 	.get_map_ofs = drm_core_get_map_ofs,
diff --git a/drivers/gpu/drm/radeon/radeon_drv.h b/drivers/gpu/drm/radeon/radeon_drv.h
index 0993816..9866c7a 100644
--- a/drivers/gpu/drm/radeon/radeon_drv.h
+++ b/drivers/gpu/drm/radeon/radeon_drv.h
@@ -1408,4 +1408,13 @@ do {									\
 	write &= mask;						\
 } while (0)
 
+static __inline__ u32 radeon_acknowledge_irqs(drm_radeon_private_t * dev_priv,
+					      u32 mask)
+{
+	u32 irqs = RADEON_READ(RADEON_GEN_INT_STATUS) & mask;
+	if (irqs)
+		RADEON_WRITE(RADEON_GEN_INT_STATUS, irqs);
+	return irqs;
+}
+
 #endif				/* __RADEON_DRV_H__ */
diff --git a/drivers/gpu/drm/radeon/radeon_irq.c b/drivers/gpu/drm/radeon/radeon_irq.c
index ee40d19..38a838f 100644
--- a/drivers/gpu/drm/radeon/radeon_irq.c
+++ b/drivers/gpu/drm/radeon/radeon_irq.c
@@ -35,15 +35,6 @@
 #include "radeon_drm.h"
 #include "radeon_drv.h"
 
-static __inline__ u32 radeon_acknowledge_irqs(drm_radeon_private_t * dev_priv,
-					      u32 mask)
-{
-	u32 irqs = RADEON_READ(RADEON_GEN_INT_STATUS) & mask;
-	if (irqs)
-		RADEON_WRITE(RADEON_GEN_INT_STATUS, irqs);
-	return irqs;
-}
-
 /* Interrupts - Used for device synchronization and flushing in the
  * following circumstances:
  *
@@ -249,47 +240,6 @@ void radeon_enable_interrupt(struct drm_device *dev)
 	dev_priv->irq_enabled = 1;
 }
 
-/* drm_dma.h hooks
-*/
-void radeon_driver_irq_preinstall(struct drm_device * dev)
-{
-	drm_radeon_private_t *dev_priv =
-	    (drm_radeon_private_t *) dev->dev_private;
-
-	/* Disable *all* interrupts */
-	RADEON_WRITE(RADEON_GEN_INT_CNTL, 0);
-
-	/* Clear bits if they're already high */
-	radeon_acknowledge_irqs(dev_priv, (RADEON_SW_INT_TEST_ACK |
-					   RADEON_CRTC_VBLANK_STAT |
-					   RADEON_CRTC2_VBLANK_STAT));
-}
-
-void radeon_driver_irq_postinstall(struct drm_device * dev)
-{
-	drm_radeon_private_t *dev_priv =
-	    (drm_radeon_private_t *) dev->dev_private;
-
-	atomic_set(&dev_priv->swi_emitted, 0);
-	DRM_INIT_WAITQUEUE(&dev_priv->swi_queue);
-
-	radeon_enable_interrupt(dev);
-}
-
-void radeon_driver_irq_uninstall(struct drm_device * dev)
-{
-	drm_radeon_private_t *dev_priv =
-	    (drm_radeon_private_t *) dev->dev_private;
-	if (!dev_priv)
-		return;
-
-	dev_priv->irq_enabled = 0;
-
-	/* Disable *all* interrupts */
-	RADEON_WRITE(RADEON_GEN_INT_CNTL, 0);
-}
-
-
 int radeon_vblank_crtc_get(struct drm_device *dev)
 {
 	drm_radeon_private_t *dev_priv = (drm_radeon_private_t *) dev->dev_private;
diff --git a/drivers/gpu/drm/via/via_drv.c b/drivers/gpu/drm/via/via_drv.c
index 80c01cd..1ffa9f4 100644
--- a/drivers/gpu/drm/via/via_drv.c
+++ b/drivers/gpu/drm/via/via_drv.c
@@ -45,9 +45,6 @@ static struct drm_driver driver = {
 	.unload = via_driver_unload,
 	.context_dtor = via_final_context,
 	.vblank_wait = via_driver_vblank_wait,
-	.irq_preinstall = via_driver_irq_preinstall,
-	.irq_postinstall = via_driver_irq_postinstall,
-	.irq_uninstall = via_driver_irq_uninstall,
 	.irq_handler = via_driver_irq_handler,
 	.dma_quiescent = via_driver_dma_quiescent,
 	.dri_library_name = dri_library_name,
diff --git a/drivers/gpu/drm/via/via_drv.h b/drivers/gpu/drm/via/via_drv.h
index 2daae81..06e19ef 100644
--- a/drivers/gpu/drm/via/via_drv.h
+++ b/drivers/gpu/drm/via/via_drv.h
@@ -150,4 +150,50 @@ extern void via_lastclose(struct drm_device *dev);
 extern void via_dmablit_handler(struct drm_device *dev, int engine, int from_irq);
 extern void via_init_dmablit(struct drm_device *dev);
 
+#define VIA_REG_INTERRUPT       0x200
+
+/* VIA_REG_INTERRUPT */
+#define VIA_IRQ_GLOBAL          (1 << 31)
+#define VIA_IRQ_VBLANK_ENABLE   (1 << 19)
+#define VIA_IRQ_VBLANK_PENDING  (1 << 3)
+#define VIA_IRQ_HQV0_ENABLE     (1 << 11)
+#define VIA_IRQ_HQV1_ENABLE     (1 << 25)
+#define VIA_IRQ_HQV0_PENDING    (1 << 9)
+#define VIA_IRQ_HQV1_PENDING    (1 << 10)
+#define VIA_IRQ_DMA0_DD_ENABLE  (1 << 20)
+#define VIA_IRQ_DMA0_TD_ENABLE  (1 << 21)
+#define VIA_IRQ_DMA1_DD_ENABLE  (1 << 22)
+#define VIA_IRQ_DMA1_TD_ENABLE  (1 << 23)
+#define VIA_IRQ_DMA0_DD_PENDING (1 << 4)
+#define VIA_IRQ_DMA0_TD_PENDING (1 << 5)
+#define VIA_IRQ_DMA1_DD_PENDING (1 << 6)
+#define VIA_IRQ_DMA1_TD_PENDING (1 << 7)
+
+
+/*
+ * Device-specific IRQs go here. This type might need to be extended with
+ * the register if there are multiple IRQ control registers.
+ * Currently we activate the HQV interrupts of  Unichrome Pro group A.
+ */
+
+extern maskarray_t via_pro_group_a_irqs[];
+extern int via_num_pro_group_a;
+extern int via_irqmap_pro_group_a[];
+
+extern maskarray_t via_unichrome_irqs[];
+extern int via_num_unichrome;
+extern int via_irqmap_unichrome[];
+
+static __inline__ void viadrv_acknowledge_irqs(drm_via_private_t * dev_priv)
+{
+	u32 status;
+
+	if (dev_priv) {
+		/* Acknowlege interrupts */
+		status = VIA_READ(VIA_REG_INTERRUPT);
+		VIA_WRITE(VIA_REG_INTERRUPT, status |
+			  dev_priv->irq_pending_mask);
+	}
+}
+
 #endif
diff --git a/drivers/gpu/drm/via/via_irq.c b/drivers/gpu/drm/via/via_irq.c
index 3d926f8..831c04d 100644
--- a/drivers/gpu/drm/via/via_irq.c
+++ b/drivers/gpu/drm/via/via_irq.c
@@ -40,33 +40,13 @@
 #include "via_drm.h"
 #include "via_drv.h"
 
-#define VIA_REG_INTERRUPT       0x200
-
-/* VIA_REG_INTERRUPT */
-#define VIA_IRQ_GLOBAL          (1 << 31)
-#define VIA_IRQ_VBLANK_ENABLE   (1 << 19)
-#define VIA_IRQ_VBLANK_PENDING  (1 << 3)
-#define VIA_IRQ_HQV0_ENABLE     (1 << 11)
-#define VIA_IRQ_HQV1_ENABLE     (1 << 25)
-#define VIA_IRQ_HQV0_PENDING    (1 << 9)
-#define VIA_IRQ_HQV1_PENDING    (1 << 10)
-#define VIA_IRQ_DMA0_DD_ENABLE  (1 << 20)
-#define VIA_IRQ_DMA0_TD_ENABLE  (1 << 21)
-#define VIA_IRQ_DMA1_DD_ENABLE  (1 << 22)
-#define VIA_IRQ_DMA1_TD_ENABLE  (1 << 23)
-#define VIA_IRQ_DMA0_DD_PENDING (1 << 4)
-#define VIA_IRQ_DMA0_TD_PENDING (1 << 5)
-#define VIA_IRQ_DMA1_DD_PENDING (1 << 6)
-#define VIA_IRQ_DMA1_TD_PENDING (1 << 7)
-
-
 /*
  * Device-specific IRQs go here. This type might need to be extended with
  * the register if there are multiple IRQ control registers.
  * Currently we activate the HQV interrupts of  Unichrome Pro group A.
  */
 
-static maskarray_t via_pro_group_a_irqs[] = {
+maskarray_t via_pro_group_a_irqs[] = {
 	{VIA_IRQ_HQV0_ENABLE, VIA_IRQ_HQV0_PENDING, 0x000003D0, 0x00008010,
 	 0x00000000},
 	{VIA_IRQ_HQV1_ENABLE, VIA_IRQ_HQV1_PENDING, 0x000013D0, 0x00008010,
@@ -76,18 +56,18 @@ static maskarray_t via_pro_group_a_irqs[] = {
 	{VIA_IRQ_DMA1_TD_ENABLE, VIA_IRQ_DMA1_TD_PENDING, VIA_PCI_DMA_CSR1,
 	 VIA_DMA_CSR_TA | VIA_DMA_CSR_TD, 0x00000008},
 };
-static int via_num_pro_group_a =
+int via_num_pro_group_a =
     sizeof(via_pro_group_a_irqs) / sizeof(maskarray_t);
-static int via_irqmap_pro_group_a[] = {0, 1, -1, 2, -1, 3};
+int via_irqmap_pro_group_a[] = {0, 1, -1, 2, -1, 3};
 
-static maskarray_t via_unichrome_irqs[] = {
+maskarray_t via_unichrome_irqs[] = {
 	{VIA_IRQ_DMA0_TD_ENABLE, VIA_IRQ_DMA0_TD_PENDING, VIA_PCI_DMA_CSR0,
 	 VIA_DMA_CSR_TA | VIA_DMA_CSR_TD, 0x00000008},
 	{VIA_IRQ_DMA1_TD_ENABLE, VIA_IRQ_DMA1_TD_PENDING, VIA_PCI_DMA_CSR1,
 	 VIA_DMA_CSR_TA | VIA_DMA_CSR_TD, 0x00000008}
 };
-static int via_num_unichrome = sizeof(via_unichrome_irqs) / sizeof(maskarray_t);
-static int via_irqmap_unichrome[] = {-1, -1, -1, 0, -1, 1};
+int via_num_unichrome = sizeof(via_unichrome_irqs) / sizeof(maskarray_t);
+int via_irqmap_unichrome[] = {-1, -1, -1, 0, -1, 1};
 
 static unsigned time_diff(struct timeval *now, struct timeval *then)
 {
@@ -151,18 +131,6 @@ irqreturn_t via_driver_irq_handler(DRM_IRQ_ARGS)
 		return IRQ_NONE;
 }
 
-static __inline__ void viadrv_acknowledge_irqs(drm_via_private_t * dev_priv)
-{
-	u32 status;
-
-	if (dev_priv) {
-		/* Acknowlege interrupts */
-		status = VIA_READ(VIA_REG_INTERRUPT);
-		VIA_WRITE(VIA_REG_INTERRUPT, status |
-			  dev_priv->irq_pending_mask);
-	}
-}
-
 int via_driver_vblank_wait(struct drm_device * dev, unsigned int *sequence)
 {
 	drm_via_private_t *dev_priv = (drm_via_private_t *) dev->dev_private;
@@ -239,97 +207,6 @@ via_driver_irq_wait(struct drm_device * dev, unsigned int irq, int force_sequenc
 	return ret;
 }
 
-/*
- * drm_dma.h hooks
- */
-
-void via_driver_irq_preinstall(struct drm_device * dev)
-{
-	drm_via_private_t *dev_priv = (drm_via_private_t *) dev->dev_private;
-	u32 status;
-	drm_via_irq_t *cur_irq;
-	int i;
-
-	DRM_DEBUG("dev_priv: %p\n", dev_priv);
-	if (dev_priv) {
-		cur_irq = dev_priv->via_irqs;
-
-		dev_priv->irq_enable_mask = VIA_IRQ_VBLANK_ENABLE;
-		dev_priv->irq_pending_mask = VIA_IRQ_VBLANK_PENDING;
-
-		if (dev_priv->chipset == VIA_PRO_GROUP_A ||
-		    dev_priv->chipset == VIA_DX9_0) {
-			dev_priv->irq_masks = via_pro_group_a_irqs;
-			dev_priv->num_irqs = via_num_pro_group_a;
-			dev_priv->irq_map = via_irqmap_pro_group_a;
-		} else {
-			dev_priv->irq_masks = via_unichrome_irqs;
-			dev_priv->num_irqs = via_num_unichrome;
-			dev_priv->irq_map = via_irqmap_unichrome;
-		}
-
-		for (i = 0; i < dev_priv->num_irqs; ++i) {
-			atomic_set(&cur_irq->irq_received, 0);
-			cur_irq->enable_mask = dev_priv->irq_masks[i][0];
-			cur_irq->pending_mask = dev_priv->irq_masks[i][1];
-			DRM_INIT_WAITQUEUE(&cur_irq->irq_queue);
-			dev_priv->irq_enable_mask |= cur_irq->enable_mask;
-			dev_priv->irq_pending_mask |= cur_irq->pending_mask;
-			cur_irq++;
-
-			DRM_DEBUG("Initializing IRQ %d\n", i);
-		}
-
-		dev_priv->last_vblank_valid = 0;
-
-		/* Clear VSync interrupt regs */
-		status = VIA_READ(VIA_REG_INTERRUPT);
-		VIA_WRITE(VIA_REG_INTERRUPT, status &
-			  ~(dev_priv->irq_enable_mask));
-
-		/* Clear bits if they're already high */
-		viadrv_acknowledge_irqs(dev_priv);
-	}
-}
-
-void via_driver_irq_postinstall(struct drm_device * dev)
-{
-	drm_via_private_t *dev_priv = (drm_via_private_t *) dev->dev_private;
-	u32 status;
-
-	DRM_DEBUG("\n");
-	if (dev_priv) {
-		status = VIA_READ(VIA_REG_INTERRUPT);
-		VIA_WRITE(VIA_REG_INTERRUPT, status | VIA_IRQ_GLOBAL
-			  | dev_priv->irq_enable_mask);
-
-		/* Some magic, oh for some data sheets ! */
-
-		VIA_WRITE8(0x83d4, 0x11);
-		VIA_WRITE8(0x83d5, VIA_READ8(0x83d5) | 0x30);
-
-	}
-}
-
-void via_driver_irq_uninstall(struct drm_device * dev)
-{
-	drm_via_private_t *dev_priv = (drm_via_private_t *) dev->dev_private;
-	u32 status;
-
-	DRM_DEBUG("\n");
-	if (dev_priv) {
-
-		/* Some more magic, oh for some data sheets ! */
-
-		VIA_WRITE8(0x83d4, 0x11);
-		VIA_WRITE8(0x83d5, VIA_READ8(0x83d5) & ~0x30);
-
-		status = VIA_READ(VIA_REG_INTERRUPT);
-		VIA_WRITE(VIA_REG_INTERRUPT, status &
-			  ~(VIA_IRQ_VBLANK_ENABLE | dev_priv->irq_enable_mask));
-	}
-}
-
 int via_wait_irq(struct drm_device *dev, void *data, struct drm_file *file_priv)
 {
 	drm_via_irqwait_t *irqwait = data;
diff --git a/drivers/gpu/drm/via/via_map.c b/drivers/gpu/drm/via/via_map.c
index a967556..a5e1d14 100644
--- a/drivers/gpu/drm/via/via_map.c
+++ b/drivers/gpu/drm/via/via_map.c
@@ -94,6 +94,9 @@ int via_map_init(struct drm_device *dev, void *data, struct drm_file *file_priv)
 int via_driver_load(struct drm_device *dev, unsigned long chipset)
 {
 	drm_via_private_t *dev_priv;
+	u32 status;
+	drm_via_irq_t *cur_irq;
+	int i;
 	int ret = 0;
 
 	dev_priv = drm_calloc(1, sizeof(drm_via_private_t), DRM_MEM_DRIVER);
@@ -108,12 +111,76 @@ int via_driver_load(struct drm_device *dev, unsigned long chipset)
 	if (ret) {
 		drm_free(dev_priv, sizeof(*dev_priv), DRM_MEM_DRIVER);
 	}
+
+	ret = drm_addmap(dev, drm_get_resource_start(dev, 1),
+			 drm_get_resource_len(dev, 1), _DRM_REGISTERS,
+			 _DRM_KERNEL | _DRM_DRIVER, &dev_priv->mmio);
+	if (ret != 0)
+		return ret;
+
+	cur_irq = dev_priv->via_irqs;
+
+	dev_priv->irq_enable_mask = VIA_IRQ_VBLANK_ENABLE;
+	dev_priv->irq_pending_mask = VIA_IRQ_VBLANK_PENDING;
+
+	if (dev_priv->chipset == VIA_PRO_GROUP_A ||
+	    dev_priv->chipset == VIA_DX9_0) {
+		dev_priv->irq_masks = via_pro_group_a_irqs;
+		dev_priv->num_irqs = via_num_pro_group_a;
+		dev_priv->irq_map = via_irqmap_pro_group_a;
+	} else {
+		dev_priv->irq_masks = via_unichrome_irqs;
+		dev_priv->num_irqs = via_num_unichrome;
+		dev_priv->irq_map = via_irqmap_unichrome;
+	}
+
+	for (i = 0; i < dev_priv->num_irqs; ++i) {
+		atomic_set(&cur_irq->irq_received, 0);
+		cur_irq->enable_mask = dev_priv->irq_masks[i][0];
+		cur_irq->pending_mask = dev_priv->irq_masks[i][1];
+		DRM_INIT_WAITQUEUE(&cur_irq->irq_queue);
+		dev_priv->irq_enable_mask |= cur_irq->enable_mask;
+		dev_priv->irq_pending_mask |= cur_irq->pending_mask;
+		cur_irq++;
+
+		DRM_DEBUG("Initializing IRQ %d\n", i);
+	}
+
+	dev_priv->last_vblank_valid = 0;
+
+	/* Clear VSync interrupt regs */
+	status = VIA_READ(VIA_REG_INTERRUPT);
+	VIA_WRITE(VIA_REG_INTERRUPT, status &
+		  ~(dev_priv->irq_enable_mask));
+
+	/* Clear bits if they're already high */
+	viadrv_acknowledge_irqs(dev_priv);
+
+	drm_irq_init(dev);
+
+	status = VIA_READ(VIA_REG_INTERRUPT);
+	VIA_WRITE(VIA_REG_INTERRUPT, status | VIA_IRQ_GLOBAL
+		  | dev_priv->irq_enable_mask);
+
+	/* Some magic, oh for some data sheets ! */
+
+	VIA_WRITE8(0x83d4, 0x11);
+	VIA_WRITE8(0x83d5, VIA_READ8(0x83d5) | 0x30);
+
 	return ret;
 }
 
 int via_driver_unload(struct drm_device *dev)
 {
 	drm_via_private_t *dev_priv = dev->dev_private;
+	u32 status;
+
+	VIA_WRITE8(0x83d4, 0x11);
+	VIA_WRITE8(0x83d5, VIA_READ8(0x83d5) & ~0x30);
+
+	status = VIA_READ(VIA_REG_INTERRUPT);
+	VIA_WRITE(VIA_REG_INTERRUPT, status &
+		  ~(VIA_IRQ_VBLANK_ENABLE | dev_priv->irq_enable_mask));
 
 	drm_sman_takedown(&dev_priv->sman);
 
diff --git a/drivers/gpu/drm/via/via_mm.c b/drivers/gpu/drm/via/via_mm.c
index 45e1861..703863c 100644
--- a/drivers/gpu/drm/via/via_mm.c
+++ b/drivers/gpu/drm/via/via_mm.c
@@ -93,8 +93,6 @@ int via_final_context(struct drm_device *dev, int context)
 	/* Last context, perform cleanup */
 	if (dev->ctx_count == 1 && dev->dev_private) {
 		DRM_DEBUG("Last Context\n");
-		if (dev->pdev->irq)
-			drm_irq_uninstall(dev);
 		via_cleanup_futex(dev_priv);
 		via_do_cleanup_map(dev);
 	}
diff --git a/include/drm/drmP.h b/include/drm/drmP.h
index 50d8b77..2fd2266 100644
--- a/include/drm/drmP.h
+++ b/include/drm/drmP.h
@@ -600,9 +600,6 @@ struct drm_driver {
 	/* these have to be filled in */
 
 	irqreturn_t(*irq_handler) (DRM_IRQ_ARGS);
-	void (*irq_preinstall) (struct drm_device *dev);
-	void (*irq_postinstall) (struct drm_device *dev);
-	void (*irq_uninstall) (struct drm_device *dev);
 	void (*reclaim_buffers) (struct drm_device *dev,
 				 struct drm_file * file_priv);
 	void (*reclaim_buffers_locked) (struct drm_device *dev,
@@ -885,6 +882,7 @@ extern int drm_setversion(struct drm_device *dev, void *data,
 			  struct drm_file *file_priv);
 extern int drm_noop(struct drm_device *dev, void *data,
 		    struct drm_file *file_priv);
+extern int drm_set_busid(struct drm_device * dev);
 
 				/* Context IOCTL support (drm_context.h) */
 extern int drm_resctx(struct drm_device *dev, void *data,
@@ -984,11 +982,12 @@ extern void drm_core_reclaim_buffers(struct drm_device *dev,
 extern int drm_control(struct drm_device *dev, void *data,
 		       struct drm_file *file_priv);
 extern irqreturn_t drm_irq_handler(DRM_IRQ_ARGS);
-extern int drm_irq_uninstall(struct drm_device *dev);
-extern void drm_driver_irq_preinstall(struct drm_device *dev);
-extern void drm_driver_irq_postinstall(struct drm_device *dev);
-extern void drm_driver_irq_uninstall(struct drm_device *dev);
 
+extern int drm_irq_install(struct drm_device * dev);
+extern int drm_irq_uninstall(struct drm_device * dev);
+
+extern int drm_irq_init(struct drm_device *dev);
+extern int drm_irq_teardown(struct drm_device *dev);
 extern int drm_wait_vblank(struct drm_device *dev, void *data,
 			   struct drm_file *file_priv);
 extern int drm_vblank_wait(struct drm_device *dev, unsigned int *vbl_seq);
-------------------------------------------------------------------------
This SF.Net email is sponsored by the Moblin Your Move Developer's challenge
Build the coolest Linux based applications with Moblin SDK & win great prizes
Grand prize is a trip for two to an Open Source event anywhere in the world
http://moblin-contest.org/redirect.php?banner_id=100&url=/
--
_______________________________________________
Dri-devel mailing list
Dri-devel@lists.sourceforge.net
https://lists.sourceforge.net/lists/listinfo/dri-devel

Reply via email to