i915: Add support for MSI and interrupt mitigation.

Previous attempts at interrupt mitigation had been foiled by i915_wait_irq's
failure to update the sarea seqno value when the status page indicated that
the seqno had already been passed.  MSI support has been seen to cut CPU
costs by up to 40% in some workloads by avoiding other expensive interrupt
handlers for frequent graphics interrupts.

Signed-off-by: Eric Anholt <eric@anholt.net>
Signed-off-by: Dave Airlie <airlied@redhat.com>
diff --git a/drivers/gpu/drm/drm_irq.c b/drivers/gpu/drm/drm_irq.c
index 53f0e5a..61ed515 100644
--- a/drivers/gpu/drm/drm_irq.c
+++ b/drivers/gpu/drm/drm_irq.c
@@ -63,7 +63,7 @@
 	    p->devnum != PCI_SLOT(dev->pdev->devfn) || p->funcnum != PCI_FUNC(dev->pdev->devfn))
 		return -EINVAL;
 
-	p->irq = dev->irq;
+	p->irq = dev->pdev->irq;
 
 	DRM_DEBUG("%d:%d:%d => IRQ %d\n", p->busnum, p->devnum, p->funcnum,
 		  p->irq);
@@ -89,7 +89,7 @@
 	if (!drm_core_check_feature(dev, DRIVER_HAVE_IRQ))
 		return -EINVAL;
 
-	if (dev->irq == 0)
+	if (dev->pdev->irq == 0)
 		return -EINVAL;
 
 	mutex_lock(&dev->struct_mutex);
@@ -107,7 +107,7 @@
 	dev->irq_enabled = 1;
 	mutex_unlock(&dev->struct_mutex);
 
-	DRM_DEBUG("irq=%d\n", dev->irq);
+	DRM_DEBUG("irq=%d\n", dev->pdev->irq);
 
 	if (drm_core_check_feature(dev, DRIVER_IRQ_VBL)) {
 		init_waitqueue_head(&dev->vbl_queue);
@@ -127,8 +127,12 @@
 	if (drm_core_check_feature(dev, DRIVER_IRQ_SHARED))
 		sh_flags = IRQF_SHARED;
 
-	ret = request_irq(dev->irq, dev->driver->irq_handler,
+	ret = request_irq(dev->pdev->irq, dev->driver->irq_handler,
 			  sh_flags, dev->devname, dev);
+	/* Expose the device irq number to drivers that want to export it for
+	 * whatever reason.
+	 */
+	dev->irq = dev->pdev->irq;
 	if (ret < 0) {
 		mutex_lock(&dev->struct_mutex);
 		dev->irq_enabled = 0;
@@ -164,11 +168,11 @@
 	if (!irq_enabled)
 		return -EINVAL;
 
-	DRM_DEBUG("irq=%d\n", dev->irq);
+	DRM_DEBUG("irq=%d\n", dev->pdev->irq);
 
 	dev->driver->irq_uninstall(dev);
 
-	free_irq(dev->irq, dev);
+	free_irq(dev->pdev->irq, dev);
 
 	dev->locked_tasklet_func = NULL;
 
@@ -201,7 +205,7 @@
 		if (!drm_core_check_feature(dev, DRIVER_HAVE_IRQ))
 			return 0;
 		if (dev->if_version < DRM_IF_VERSION(1, 2) &&
-		    ctl->irq != dev->irq)
+		    ctl->irq != dev->pdev->irq)
 			return -EINVAL;
 		return drm_irq_install(dev);
 	case DRM_UNINST_HANDLER:
@@ -239,7 +243,7 @@
 	int ret = 0;
 	unsigned int flags, seq;
 
-	if ((!dev->irq) || (!dev->irq_enabled))
+	if ((!dev->pdev->irq) || (!dev->irq_enabled))
 		return -EINVAL;
 
 	if (vblwait->request.type &