diff options
author | Francois Romieu <romieu@fr.zoreil.com> | 2007-02-19 18:00:26 -0500 |
---|---|---|
committer | Jeff Garzik <jeff@garzik.org> | 2007-07-08 22:16:44 -0400 |
commit | 0e4851502f846b13b29b7f88f1250c980d57e944 (patch) | |
tree | 39f5b5d6ae5706f8f4884fbb7058d9ee7594abe0 /drivers/net/r8169.c | |
parent | 6dccd16b7c2703e8bbf8bca62b5cf248332afbe2 (diff) |
r8169: merge with version 8.001.00 of Realtek's r8168 driver
This one includes:
- more tweaks to rtl_hw_start_8168
- a work around for a Rx FiFO overflow issue on the 8168Bb
- rtl8169_{intr_mask/napi_event} are replaced with per-device fields,
namely tp->{intr/napi}_event
- rtl_cfg_info is converted to C99 for readability but the values are
not changed for the 8169/8110 and the 8101
Includes ChipCmd fix from Bernhard Walle <bwalle@suse.de> (2007/02/24).
Signed-off-by: Francois Romieu <romieu@fr.zoreil.com>
Cc: Edward Hsu <edward_hsu@realtek.com.tw>
Diffstat (limited to 'drivers/net/r8169.c')
-rw-r--r-- | drivers/net/r8169.c | 119 |
1 files changed, 89 insertions, 30 deletions
diff --git a/drivers/net/r8169.c b/drivers/net/r8169.c index 0d2aeb84510f..9c49d910c06d 100644 --- a/drivers/net/r8169.c +++ b/drivers/net/r8169.c | |||
@@ -205,16 +205,6 @@ static void rtl_hw_start_8169(struct net_device *); | |||
205 | static void rtl_hw_start_8168(struct net_device *); | 205 | static void rtl_hw_start_8168(struct net_device *); |
206 | static void rtl_hw_start_8101(struct net_device *); | 206 | static void rtl_hw_start_8101(struct net_device *); |
207 | 207 | ||
208 | static const struct { | ||
209 | void (*hw_start)(struct net_device *); | ||
210 | unsigned int region; | ||
211 | unsigned int align; | ||
212 | } rtl_cfg_info[] = { | ||
213 | [RTL_CFG_0] = { rtl_hw_start_8169, 1, NET_IP_ALIGN }, | ||
214 | [RTL_CFG_1] = { rtl_hw_start_8168, 2, 8 }, | ||
215 | [RTL_CFG_2] = { rtl_hw_start_8101, 2, 8 } | ||
216 | }; | ||
217 | |||
218 | static struct pci_device_id rtl8169_pci_tbl[] = { | 208 | static struct pci_device_id rtl8169_pci_tbl[] = { |
219 | { PCI_DEVICE(PCI_VENDOR_ID_REALTEK, 0x8129), 0, 0, RTL_CFG_0 }, | 209 | { PCI_DEVICE(PCI_VENDOR_ID_REALTEK, 0x8129), 0, 0, RTL_CFG_0 }, |
220 | { PCI_DEVICE(PCI_VENDOR_ID_REALTEK, 0x8136), 0, 0, RTL_CFG_2 }, | 210 | { PCI_DEVICE(PCI_VENDOR_ID_REALTEK, 0x8136), 0, 0, RTL_CFG_2 }, |
@@ -354,10 +344,15 @@ enum RTL8169_register_content { | |||
354 | TBINwComplete = 0x01000000, | 344 | TBINwComplete = 0x01000000, |
355 | 345 | ||
356 | /* CPlusCmd p.31 */ | 346 | /* CPlusCmd p.31 */ |
347 | PktCntrDisable = (1 << 7), // 8168 | ||
357 | RxVlan = (1 << 6), | 348 | RxVlan = (1 << 6), |
358 | RxChkSum = (1 << 5), | 349 | RxChkSum = (1 << 5), |
359 | PCIDAC = (1 << 4), | 350 | PCIDAC = (1 << 4), |
360 | PCIMulRW = (1 << 3), | 351 | PCIMulRW = (1 << 3), |
352 | INTT_0 = 0x0000, // 8168 | ||
353 | INTT_1 = 0x0001, // 8168 | ||
354 | INTT_2 = 0x0002, // 8168 | ||
355 | INTT_3 = 0x0003, // 8168 | ||
361 | 356 | ||
362 | /* rtl8169_PHYstatus */ | 357 | /* rtl8169_PHYstatus */ |
363 | TBI_Enable = 0x80, | 358 | TBI_Enable = 0x80, |
@@ -457,6 +452,8 @@ struct rtl8169_private { | |||
457 | unsigned rx_buf_sz; | 452 | unsigned rx_buf_sz; |
458 | struct timer_list timer; | 453 | struct timer_list timer; |
459 | u16 cp_cmd; | 454 | u16 cp_cmd; |
455 | u16 intr_event; | ||
456 | u16 napi_event; | ||
460 | u16 intr_mask; | 457 | u16 intr_mask; |
461 | int phy_auto_nego_reg; | 458 | int phy_auto_nego_reg; |
462 | int phy_1000_ctrl_reg; | 459 | int phy_1000_ctrl_reg; |
@@ -505,10 +502,6 @@ static void rtl8169_rx_clear(struct rtl8169_private *tp); | |||
505 | static int rtl8169_poll(struct net_device *dev, int *budget); | 502 | static int rtl8169_poll(struct net_device *dev, int *budget); |
506 | #endif | 503 | #endif |
507 | 504 | ||
508 | static const u16 rtl8169_intr_mask = | ||
509 | SYSErr | LinkChg | RxOverflow | RxFIFOOver | TxErr | TxOK | RxErr | RxOK; | ||
510 | static const u16 rtl8169_napi_event = | ||
511 | RxOK | RxOverflow | RxFIFOOver | TxOK | TxErr; | ||
512 | static const unsigned int rtl8169_rx_config = | 505 | static const unsigned int rtl8169_rx_config = |
513 | (RX_FIFO_THRESH << RxCfgFIFOShift) | (RX_DMA_BURST << RxCfgDMAShift); | 506 | (RX_FIFO_THRESH << RxCfgFIFOShift) | (RX_DMA_BURST << RxCfgDMAShift); |
514 | 507 | ||
@@ -1166,6 +1159,13 @@ static void rtl8169_write_gmii_reg_bit(void __iomem *ioaddr, int reg, int bitnum | |||
1166 | 1159 | ||
1167 | static void rtl8169_get_mac_version(struct rtl8169_private *tp, void __iomem *ioaddr) | 1160 | static void rtl8169_get_mac_version(struct rtl8169_private *tp, void __iomem *ioaddr) |
1168 | { | 1161 | { |
1162 | /* | ||
1163 | * The driver currently handles the 8168Bf and the 8168Be identically | ||
1164 | * but they can be identified more specifically through the test below | ||
1165 | * if needed: | ||
1166 | * | ||
1167 | * (RTL_R32(TxConfig) & 0x700000) == 0x500000 ? 8168Bf : 8168Be | ||
1168 | */ | ||
1169 | const struct { | 1169 | const struct { |
1170 | u32 mask; | 1170 | u32 mask; |
1171 | int mac_version; | 1171 | int mac_version; |
@@ -1480,10 +1480,44 @@ static int rtl8169_ioctl(struct net_device *dev, struct ifreq *ifr, int cmd) | |||
1480 | return -EOPNOTSUPP; | 1480 | return -EOPNOTSUPP; |
1481 | } | 1481 | } |
1482 | 1482 | ||
1483 | static const struct rtl_cfg_info { | ||
1484 | void (*hw_start)(struct net_device *); | ||
1485 | unsigned int region; | ||
1486 | unsigned int align; | ||
1487 | u16 intr_event; | ||
1488 | u16 napi_event; | ||
1489 | } rtl_cfg_infos [] = { | ||
1490 | [RTL_CFG_0] = { | ||
1491 | .hw_start = rtl_hw_start_8169, | ||
1492 | .region = 1, | ||
1493 | .align = NET_IP_ALIGN, | ||
1494 | .intr_event = SYSErr | LinkChg | RxOverflow | | ||
1495 | RxFIFOOver | TxErr | TxOK | RxOK | RxErr, | ||
1496 | .napi_event = RxFIFOOver | TxErr | TxOK | RxOK | RxOverflow | ||
1497 | }, | ||
1498 | [RTL_CFG_1] = { | ||
1499 | .hw_start = rtl_hw_start_8168, | ||
1500 | .region = 2, | ||
1501 | .align = 8, | ||
1502 | .intr_event = SYSErr | LinkChg | RxOverflow | | ||
1503 | TxErr | TxOK | RxOK | RxErr, | ||
1504 | .napi_event = TxErr | TxOK | RxOK | RxOverflow | ||
1505 | }, | ||
1506 | [RTL_CFG_2] = { | ||
1507 | .hw_start = rtl_hw_start_8101, | ||
1508 | .region = 2, | ||
1509 | .align = 8, | ||
1510 | .intr_event = SYSErr | LinkChg | RxOverflow | PCSTimeout | | ||
1511 | RxFIFOOver | TxErr | TxOK | RxOK | RxErr, | ||
1512 | .napi_event = RxFIFOOver | TxErr | TxOK | RxOK | RxOverflow | ||
1513 | } | ||
1514 | }; | ||
1515 | |||
1483 | static int __devinit | 1516 | static int __devinit |
1484 | rtl8169_init_one(struct pci_dev *pdev, const struct pci_device_id *ent) | 1517 | rtl8169_init_one(struct pci_dev *pdev, const struct pci_device_id *ent) |
1485 | { | 1518 | { |
1486 | const unsigned int region = rtl_cfg_info[ent->driver_data].region; | 1519 | const struct rtl_cfg_info *cfg = rtl_cfg_infos + ent->driver_data; |
1520 | const unsigned int region = cfg->region; | ||
1487 | struct rtl8169_private *tp; | 1521 | struct rtl8169_private *tp; |
1488 | struct net_device *dev; | 1522 | struct net_device *dev; |
1489 | void __iomem *ioaddr; | 1523 | void __iomem *ioaddr; |
@@ -1683,14 +1717,15 @@ rtl8169_init_one(struct pci_dev *pdev, const struct pci_device_id *ent) | |||
1683 | tp->intr_mask = 0xffff; | 1717 | tp->intr_mask = 0xffff; |
1684 | tp->pci_dev = pdev; | 1718 | tp->pci_dev = pdev; |
1685 | tp->mmio_addr = ioaddr; | 1719 | tp->mmio_addr = ioaddr; |
1686 | tp->align = rtl_cfg_info[ent->driver_data].align; | 1720 | tp->align = cfg->align; |
1721 | tp->hw_start = cfg->hw_start; | ||
1722 | tp->intr_event = cfg->intr_event; | ||
1723 | tp->napi_event = cfg->napi_event; | ||
1687 | 1724 | ||
1688 | init_timer(&tp->timer); | 1725 | init_timer(&tp->timer); |
1689 | tp->timer.data = (unsigned long) dev; | 1726 | tp->timer.data = (unsigned long) dev; |
1690 | tp->timer.function = rtl8169_phy_timer; | 1727 | tp->timer.function = rtl8169_phy_timer; |
1691 | 1728 | ||
1692 | tp->hw_start = rtl_cfg_info[ent->driver_data].hw_start; | ||
1693 | |||
1694 | spin_lock_init(&tp->lock); | 1729 | spin_lock_init(&tp->lock); |
1695 | 1730 | ||
1696 | rc = register_netdev(dev); | 1731 | rc = register_netdev(dev); |
@@ -1966,7 +2001,7 @@ static void rtl_hw_start_8169(struct net_device *dev) | |||
1966 | RTL_W16(MultiIntr, RTL_R16(MultiIntr) & 0xF000); | 2001 | RTL_W16(MultiIntr, RTL_R16(MultiIntr) & 0xF000); |
1967 | 2002 | ||
1968 | /* Enable all known interrupts by setting the interrupt mask. */ | 2003 | /* Enable all known interrupts by setting the interrupt mask. */ |
1969 | RTL_W16(IntrMask, rtl8169_intr_mask); | 2004 | RTL_W16(IntrMask, tp->intr_event); |
1970 | 2005 | ||
1971 | RTL_W8(ChipCmd, CmdTxEnb | CmdRxEnb); | 2006 | RTL_W8(ChipCmd, CmdTxEnb | CmdRxEnb); |
1972 | } | 2007 | } |
@@ -1975,6 +2010,8 @@ static void rtl_hw_start_8168(struct net_device *dev) | |||
1975 | { | 2010 | { |
1976 | struct rtl8169_private *tp = netdev_priv(dev); | 2011 | struct rtl8169_private *tp = netdev_priv(dev); |
1977 | void __iomem *ioaddr = tp->mmio_addr; | 2012 | void __iomem *ioaddr = tp->mmio_addr; |
2013 | struct pci_dev *pdev = tp->pci_dev; | ||
2014 | u8 ctl; | ||
1978 | 2015 | ||
1979 | RTL_W8(Cfg9346, Cfg9346_Unlock); | 2016 | RTL_W8(Cfg9346, Cfg9346_Unlock); |
1980 | 2017 | ||
@@ -1982,16 +2019,26 @@ static void rtl_hw_start_8168(struct net_device *dev) | |||
1982 | 2019 | ||
1983 | rtl_set_rx_max_size(ioaddr); | 2020 | rtl_set_rx_max_size(ioaddr); |
1984 | 2021 | ||
1985 | tp->cp_cmd |= rtl_rw_cpluscmd(ioaddr) | PCIMulRW; | 2022 | rtl_set_rx_tx_config_registers(tp); |
2023 | |||
2024 | tp->cp_cmd |= RTL_R16(CPlusCmd) | PktCntrDisable | INTT_1; | ||
1986 | 2025 | ||
1987 | RTL_W16(CPlusCmd, tp->cp_cmd); | 2026 | RTL_W16(CPlusCmd, tp->cp_cmd); |
1988 | 2027 | ||
1989 | RTL_W16(IntrMitigate, 0x0000); | 2028 | /* Tx performance tweak. */ |
2029 | pci_read_config_byte(pdev, 0x69, &ctl); | ||
2030 | ctl = (ctl & ~0x70) | 0x50; | ||
2031 | pci_write_config_byte(pdev, 0x69, ctl); | ||
1990 | 2032 | ||
1991 | rtl_set_rx_tx_desc_registers(tp, ioaddr); | 2033 | RTL_W16(IntrMitigate, 0x5151); |
1992 | 2034 | ||
1993 | RTL_W8(ChipCmd, CmdTxEnb | CmdRxEnb); | 2035 | /* Work around for RxFIFO overflow. */ |
1994 | rtl_set_rx_tx_config_registers(tp); | 2036 | if (tp->mac_version == RTL_GIGA_MAC_VER_11) { |
2037 | tp->intr_event |= RxFIFOOver | PCSTimeout; | ||
2038 | tp->intr_event &= ~RxOverflow; | ||
2039 | } | ||
2040 | |||
2041 | rtl_set_rx_tx_desc_registers(tp, ioaddr); | ||
1995 | 2042 | ||
1996 | RTL_W8(Cfg9346, Cfg9346_Lock); | 2043 | RTL_W8(Cfg9346, Cfg9346_Lock); |
1997 | 2044 | ||
@@ -2001,9 +2048,11 @@ static void rtl_hw_start_8168(struct net_device *dev) | |||
2001 | 2048 | ||
2002 | rtl_set_rx_mode(dev); | 2049 | rtl_set_rx_mode(dev); |
2003 | 2050 | ||
2051 | RTL_W8(ChipCmd, CmdTxEnb | CmdRxEnb); | ||
2052 | |||
2004 | RTL_W16(MultiIntr, RTL_R16(MultiIntr) & 0xF000); | 2053 | RTL_W16(MultiIntr, RTL_R16(MultiIntr) & 0xF000); |
2005 | 2054 | ||
2006 | RTL_W16(IntrMask, rtl8169_intr_mask); | 2055 | RTL_W16(IntrMask, tp->intr_event); |
2007 | } | 2056 | } |
2008 | 2057 | ||
2009 | static void rtl_hw_start_8101(struct net_device *dev) | 2058 | static void rtl_hw_start_8101(struct net_device *dev) |
@@ -2042,9 +2091,11 @@ static void rtl_hw_start_8101(struct net_device *dev) | |||
2042 | 2091 | ||
2043 | rtl_set_rx_mode(dev); | 2092 | rtl_set_rx_mode(dev); |
2044 | 2093 | ||
2094 | RTL_W8(ChipCmd, CmdTxEnb | CmdRxEnb); | ||
2095 | |||
2045 | RTL_W16(MultiIntr, RTL_R16(MultiIntr) & 0xf000); | 2096 | RTL_W16(MultiIntr, RTL_R16(MultiIntr) & 0xf000); |
2046 | 2097 | ||
2047 | RTL_W16(IntrMask, rtl8169_intr_mask); | 2098 | RTL_W16(IntrMask, tp->intr_event); |
2048 | } | 2099 | } |
2049 | 2100 | ||
2050 | static int rtl8169_change_mtu(struct net_device *dev, int new_mtu) | 2101 | static int rtl8169_change_mtu(struct net_device *dev, int new_mtu) |
@@ -2761,8 +2812,16 @@ rtl8169_interrupt(int irq, void *dev_instance) | |||
2761 | RTL_W16(IntrStatus, | 2812 | RTL_W16(IntrStatus, |
2762 | (status & RxFIFOOver) ? (status | RxOverflow) : status); | 2813 | (status & RxFIFOOver) ? (status | RxOverflow) : status); |
2763 | 2814 | ||
2764 | if (!(status & rtl8169_intr_mask)) | 2815 | if (!(status & tp->intr_event)) |
2816 | break; | ||
2817 | |||
2818 | /* Work around for rx fifo overflow */ | ||
2819 | if (unlikely(status & RxFIFOOver) && | ||
2820 | (tp->mac_version == RTL_GIGA_MAC_VER_11)) { | ||
2821 | netif_stop_queue(dev); | ||
2822 | rtl8169_tx_timeout(dev); | ||
2765 | break; | 2823 | break; |
2824 | } | ||
2766 | 2825 | ||
2767 | if (unlikely(status & SYSErr)) { | 2826 | if (unlikely(status & SYSErr)) { |
2768 | rtl8169_pcierr_interrupt(dev); | 2827 | rtl8169_pcierr_interrupt(dev); |
@@ -2773,8 +2832,8 @@ rtl8169_interrupt(int irq, void *dev_instance) | |||
2773 | rtl8169_check_link_status(dev, tp, ioaddr); | 2832 | rtl8169_check_link_status(dev, tp, ioaddr); |
2774 | 2833 | ||
2775 | #ifdef CONFIG_R8169_NAPI | 2834 | #ifdef CONFIG_R8169_NAPI |
2776 | RTL_W16(IntrMask, rtl8169_intr_mask & ~rtl8169_napi_event); | 2835 | RTL_W16(IntrMask, tp->intr_event & ~tp->napi_event); |
2777 | tp->intr_mask = ~rtl8169_napi_event; | 2836 | tp->intr_mask = ~tp->napi_event; |
2778 | 2837 | ||
2779 | if (likely(netif_rx_schedule_prep(dev))) | 2838 | if (likely(netif_rx_schedule_prep(dev))) |
2780 | __netif_rx_schedule(dev); | 2839 | __netif_rx_schedule(dev); |
@@ -2831,7 +2890,7 @@ static int rtl8169_poll(struct net_device *dev, int *budget) | |||
2831 | * write is safe - FR | 2890 | * write is safe - FR |
2832 | */ | 2891 | */ |
2833 | smp_wmb(); | 2892 | smp_wmb(); |
2834 | RTL_W16(IntrMask, rtl8169_intr_mask); | 2893 | RTL_W16(IntrMask, tp->intr_event); |
2835 | } | 2894 | } |
2836 | 2895 | ||
2837 | return (work_done >= work_to_do); | 2896 | return (work_done >= work_to_do); |