TxDMAShift = 8, /* DMA burst value (0-7) is shift this many bits */
 
        /* Config1 register p.24 */
+       MSIEnable       = (1 << 5),     /* Enable Message Signaled Interrupt */
        PMEnable        = (1 << 0),     /* Power Management Enable */
 
        /* Config2 register p. 25 */
 
 enum features {
        RTL_FEATURE_WOL = (1 << 0),
+       RTL_FEATURE_MSI = (1 << 1),
 };
 
 struct rtl8169_private {
        unsigned int align;
        u16 intr_event;
        u16 napi_event;
+       unsigned msi;
 } rtl_cfg_infos [] = {
        [RTL_CFG_0] = {
                .hw_start       = rtl_hw_start_8169,
                .align          = 0,
                .intr_event     = SYSErr | LinkChg | RxOverflow |
                                  RxFIFOOver | TxErr | TxOK | RxOK | RxErr,
-               .napi_event     = RxFIFOOver | TxErr | TxOK | RxOK | RxOverflow
+               .napi_event     = RxFIFOOver | TxErr | TxOK | RxOK | RxOverflow,
+               .msi            = 0
        },
        [RTL_CFG_1] = {
                .hw_start       = rtl_hw_start_8168,
                .align          = 8,
                .intr_event     = SYSErr | LinkChg | RxOverflow |
                                  TxErr | TxOK | RxOK | RxErr,
-               .napi_event     = TxErr | TxOK | RxOK | RxOverflow
+               .napi_event     = TxErr | TxOK | RxOK | RxOverflow,
+               .msi            = RTL_FEATURE_MSI
        },
        [RTL_CFG_2] = {
                .hw_start       = rtl_hw_start_8101,
                .align          = 8,
                .intr_event     = SYSErr | LinkChg | RxOverflow | PCSTimeout |
                                  RxFIFOOver | TxErr | TxOK | RxOK | RxErr,
-               .napi_event     = RxFIFOOver | TxErr | TxOK | RxOK | RxOverflow
+               .napi_event     = RxFIFOOver | TxErr | TxOK | RxOK | RxOverflow,
+               .msi            = RTL_FEATURE_MSI
        }
 };
 
+/* Cfg9346_Unlock assumed. */
+static unsigned rtl_try_msi(struct pci_dev *pdev, void __iomem *ioaddr,
+                           const struct rtl_cfg_info *cfg)
+{
+       unsigned msi = 0;
+       u8 cfg2;
+
+       cfg2 = RTL_R8(Config2) & ~MSIEnable;
+       if (cfg->msi) {
+               if (pci_enable_msi(pdev)) {
+                       dev_info(&pdev->dev, "no MSI. Back to INTx.\n");
+               } else {
+                       cfg2 |= MSIEnable;
+                       msi = RTL_FEATURE_MSI;
+               }
+       }
+       RTL_W8(Config2, cfg2);
+       return msi;
+}
+
+static void rtl_disable_msi(struct pci_dev *pdev, struct rtl8169_private *tp)
+{
+       if (tp->features & RTL_FEATURE_MSI) {
+               pci_disable_msi(pdev);
+               tp->features &= ~RTL_FEATURE_MSI;
+       }
+}
+
 static int __devinit
 rtl8169_init_one(struct pci_dev *pdev, const struct pci_device_id *ent)
 {
        RTL_W8(Cfg9346, Cfg9346_Unlock);
        RTL_W8(Config1, RTL_R8(Config1) | PMEnable);
        RTL_W8(Config5, RTL_R8(Config5) & PMEStatus);
+       tp->features |= rtl_try_msi(pdev, ioaddr, cfg);
        RTL_W8(Cfg9346, Cfg9346_Lock);
 
        if (RTL_R8(PHYstatus) & TBI_Enable) {
 
        rc = register_netdev(dev);
        if (rc < 0)
-               goto err_out_unmap_5;
+               goto err_out_msi_5;
 
        pci_set_drvdata(pdev, dev);
 
 out:
        return rc;
 
-err_out_unmap_5:
+err_out_msi_5:
+       rtl_disable_msi(pdev, tp);
        iounmap(ioaddr);
 err_out_free_res_4:
        pci_release_regions(pdev);
        flush_scheduled_work();
 
        unregister_netdev(dev);
+       rtl_disable_msi(pdev, tp);
        rtl8169_release_board(pdev, dev, tp->mmio_addr);
        pci_set_drvdata(pdev, NULL);
 }
 
        smp_mb();
 
-       retval = request_irq(dev->irq, rtl8169_interrupt, IRQF_SHARED,
+       retval = request_irq(dev->irq, rtl8169_interrupt,
+                            (tp->features & RTL_FEATURE_MSI) ? 0 : IRQF_SHARED,
                             dev->name, dev);
        if (retval < 0)
                goto err_release_ring_2;