int nouveau_perflvl_wr;
 module_param_named(perflvl_wr, nouveau_perflvl_wr, int, 0400);
 
+MODULE_PARM_DESC(msi, "Enable MSI (default: off)\n");
+int nouveau_msi;
+module_param_named(msi, nouveau_msi, int, 0400);
+
 int nouveau_fbpercrtc;
 #if 0
 module_param_named(fbpercrtc, nouveau_fbpercrtc, int, 0400);
 
 
        struct nouveau_bo *vga_ram;
 
+       /* interrupt handling */
+       bool msi_enabled;
        struct workqueue_struct *wq;
        struct work_struct irq_work;
        struct work_struct hpd_work;
 extern int nouveau_override_conntype;
 extern char *nouveau_perflvl;
 extern int nouveau_perflvl_wr;
+extern int nouveau_msi;
 
 extern int nouveau_pci_suspend(struct pci_dev *pdev, pm_message_t pm_state);
 extern int nouveau_pci_resume(struct pci_dev *pdev);
                                     struct drm_file *);
 
 /* nouveau_irq.c */
+extern int         nouveau_irq_init(struct drm_device *);
+extern void        nouveau_irq_fini(struct drm_device *);
 extern irqreturn_t nouveau_irq_handler(DRM_IRQ_ARGS);
 extern void        nouveau_irq_preinstall(struct drm_device *);
 extern int         nouveau_irq_postinstall(struct drm_device *);
 
 int
 nouveau_irq_postinstall(struct drm_device *dev)
 {
+       struct drm_nouveau_private *dev_priv = dev->dev_private;
+
        /* Master enable */
        nv_wr32(dev, NV03_PMC_INTR_EN_0, NV_PMC_INTR_EN_0_MASTER_ENABLE);
+       if (dev_priv->msi_enabled)
+               nv_wr08(dev, 0x00088068, 0xff);
+
        return 0;
 }
 
 
        spin_unlock_irqrestore(&dev_priv->context_switch_lock, flags);
 
+       if (dev_priv->msi_enabled)
+               nv_wr08(dev, 0x00088068, 0xff);
+
        return IRQ_HANDLED;
 }
+
+int
+nouveau_irq_init(struct drm_device *dev)
+{
+       struct drm_nouveau_private *dev_priv = dev->dev_private;
+       int ret;
+
+       if (nouveau_msi != 0 && dev_priv->card_type >= NV_50) {
+               ret = pci_enable_msi(dev->pdev);
+               if (ret == 0) {
+                       NV_INFO(dev, "enabled MSI\n");
+                       dev_priv->msi_enabled = true;
+               }
+       }
+
+       return drm_irq_install(dev);
+}
+
+void
+nouveau_irq_fini(struct drm_device *dev)
+{
+       struct drm_nouveau_private *dev_priv = dev->dev_private;
+
+       drm_irq_uninstall(dev);
+       if (dev_priv->msi_enabled)
+               pci_disable_msi(dev->pdev);
+}
 
        if (ret)
                goto out_fifo;
 
-       /* this call irq_preinstall, register irq handler and
-        * call irq_postinstall
-        */
-       ret = drm_irq_install(dev);
+       ret = nouveau_irq_init(dev);
        if (ret)
                goto out_display;
 
 out_fence:
        nouveau_fence_fini(dev);
 out_irq:
-       drm_irq_uninstall(dev);
+       nouveau_irq_fini(dev);
 out_display:
        engine->display.destroy(dev);
 out_fifo:
        nouveau_gpuobj_takedown(dev);
        nouveau_mem_vram_fini(dev);
 
-       drm_irq_uninstall(dev);
+       nouveau_irq_fini(dev);
 
        nouveau_pm_fini(dev);
        nouveau_bios_takedown(dev);