提交 fbac58fc 编写于 作者: F Francois Romieu

r8169: MSI support

It is currently limited to the tested 0x8136 and 0x8168. 8169sb/8110sb ought
to handle it as well where they support MSI.
Signed-off-by: NFrancois Romieu <romieu@fr.zoreil.com>
Cc: Edward Hsu <edward_hsu@realtek.com.tw>
Tester-Cc: Rolf Eike Beer <eike-kernel@sf-tec.de>
上级 f23e7fda
...@@ -278,6 +278,7 @@ enum rtl_register_content { ...@@ -278,6 +278,7 @@ enum rtl_register_content {
TxDMAShift = 8, /* DMA burst value (0-7) is shift this many bits */ TxDMAShift = 8, /* DMA burst value (0-7) is shift this many bits */
/* Config1 register p.24 */ /* Config1 register p.24 */
MSIEnable = (1 << 5), /* Enable Message Signaled Interrupt */
PMEnable = (1 << 0), /* Power Management Enable */ PMEnable = (1 << 0), /* Power Management Enable */
/* Config2 register p. 25 */ /* Config2 register p. 25 */
...@@ -383,6 +384,7 @@ struct ring_info { ...@@ -383,6 +384,7 @@ struct ring_info {
enum features { enum features {
RTL_FEATURE_WOL = (1 << 0), RTL_FEATURE_WOL = (1 << 0),
RTL_FEATURE_MSI = (1 << 1),
}; };
struct rtl8169_private { struct rtl8169_private {
...@@ -1465,6 +1467,7 @@ static const struct rtl_cfg_info { ...@@ -1465,6 +1467,7 @@ static const struct rtl_cfg_info {
unsigned int align; unsigned int align;
u16 intr_event; u16 intr_event;
u16 napi_event; u16 napi_event;
unsigned msi;
} rtl_cfg_infos [] = { } rtl_cfg_infos [] = {
[RTL_CFG_0] = { [RTL_CFG_0] = {
.hw_start = rtl_hw_start_8169, .hw_start = rtl_hw_start_8169,
...@@ -1472,7 +1475,8 @@ static const struct rtl_cfg_info { ...@@ -1472,7 +1475,8 @@ static const struct rtl_cfg_info {
.align = 0, .align = 0,
.intr_event = SYSErr | LinkChg | RxOverflow | .intr_event = SYSErr | LinkChg | RxOverflow |
RxFIFOOver | TxErr | TxOK | RxOK | RxErr, RxFIFOOver | TxErr | TxOK | RxOK | RxErr,
.napi_event = RxFIFOOver | TxErr | TxOK | RxOK | RxOverflow .napi_event = RxFIFOOver | TxErr | TxOK | RxOK | RxOverflow,
.msi = 0
}, },
[RTL_CFG_1] = { [RTL_CFG_1] = {
.hw_start = rtl_hw_start_8168, .hw_start = rtl_hw_start_8168,
...@@ -1480,7 +1484,8 @@ static const struct rtl_cfg_info { ...@@ -1480,7 +1484,8 @@ static const struct rtl_cfg_info {
.align = 8, .align = 8,
.intr_event = SYSErr | LinkChg | RxOverflow | .intr_event = SYSErr | LinkChg | RxOverflow |
TxErr | TxOK | RxOK | RxErr, TxErr | TxOK | RxOK | RxErr,
.napi_event = TxErr | TxOK | RxOK | RxOverflow .napi_event = TxErr | TxOK | RxOK | RxOverflow,
.msi = RTL_FEATURE_MSI
}, },
[RTL_CFG_2] = { [RTL_CFG_2] = {
.hw_start = rtl_hw_start_8101, .hw_start = rtl_hw_start_8101,
...@@ -1488,10 +1493,39 @@ static const struct rtl_cfg_info { ...@@ -1488,10 +1493,39 @@ static const struct rtl_cfg_info {
.align = 8, .align = 8,
.intr_event = SYSErr | LinkChg | RxOverflow | PCSTimeout | .intr_event = SYSErr | LinkChg | RxOverflow | PCSTimeout |
RxFIFOOver | TxErr | TxOK | RxOK | RxErr, 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 static int __devinit
rtl8169_init_one(struct pci_dev *pdev, const struct pci_device_id *ent) rtl8169_init_one(struct pci_dev *pdev, const struct pci_device_id *ent)
{ {
...@@ -1627,6 +1661,7 @@ rtl8169_init_one(struct pci_dev *pdev, const struct pci_device_id *ent) ...@@ -1627,6 +1661,7 @@ rtl8169_init_one(struct pci_dev *pdev, const struct pci_device_id *ent)
RTL_W8(Cfg9346, Cfg9346_Unlock); RTL_W8(Cfg9346, Cfg9346_Unlock);
RTL_W8(Config1, RTL_R8(Config1) | PMEnable); RTL_W8(Config1, RTL_R8(Config1) | PMEnable);
RTL_W8(Config5, RTL_R8(Config5) & PMEStatus); RTL_W8(Config5, RTL_R8(Config5) & PMEStatus);
tp->features |= rtl_try_msi(pdev, ioaddr, cfg);
RTL_W8(Cfg9346, Cfg9346_Lock); RTL_W8(Cfg9346, Cfg9346_Lock);
if (RTL_R8(PHYstatus) & TBI_Enable) { if (RTL_R8(PHYstatus) & TBI_Enable) {
...@@ -1694,7 +1729,7 @@ rtl8169_init_one(struct pci_dev *pdev, const struct pci_device_id *ent) ...@@ -1694,7 +1729,7 @@ rtl8169_init_one(struct pci_dev *pdev, const struct pci_device_id *ent)
rc = register_netdev(dev); rc = register_netdev(dev);
if (rc < 0) if (rc < 0)
goto err_out_unmap_5; goto err_out_msi_5;
pci_set_drvdata(pdev, dev); pci_set_drvdata(pdev, dev);
...@@ -1717,7 +1752,8 @@ rtl8169_init_one(struct pci_dev *pdev, const struct pci_device_id *ent) ...@@ -1717,7 +1752,8 @@ rtl8169_init_one(struct pci_dev *pdev, const struct pci_device_id *ent)
out: out:
return rc; return rc;
err_out_unmap_5: err_out_msi_5:
rtl_disable_msi(pdev, tp);
iounmap(ioaddr); iounmap(ioaddr);
err_out_free_res_4: err_out_free_res_4:
pci_release_regions(pdev); pci_release_regions(pdev);
...@@ -1738,6 +1774,7 @@ static void __devexit rtl8169_remove_one(struct pci_dev *pdev) ...@@ -1738,6 +1774,7 @@ static void __devexit rtl8169_remove_one(struct pci_dev *pdev)
flush_scheduled_work(); flush_scheduled_work();
unregister_netdev(dev); unregister_netdev(dev);
rtl_disable_msi(pdev, tp);
rtl8169_release_board(pdev, dev, tp->mmio_addr); rtl8169_release_board(pdev, dev, tp->mmio_addr);
pci_set_drvdata(pdev, NULL); pci_set_drvdata(pdev, NULL);
} }
...@@ -1781,7 +1818,8 @@ static int rtl8169_open(struct net_device *dev) ...@@ -1781,7 +1818,8 @@ static int rtl8169_open(struct net_device *dev)
smp_mb(); 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); dev->name, dev);
if (retval < 0) if (retval < 0)
goto err_release_ring_2; goto err_release_ring_2;
......
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册