diff options
author | françois romieu <romieu@fr.zoreil.com> | 2011-12-04 15:30:45 -0500 |
---|---|---|
committer | David S. Miller <davem@davemloft.net> | 2011-12-05 18:31:42 -0500 |
commit | 811fd3010cf512f2e23e6c4c912aad54516dc706 (patch) | |
tree | 2b03937f3ccac46b09fa1030108f57b259769143 /drivers/net/ethernet/realtek | |
parent | 321f3b8708e853695a4ff4a1a95b6fa0965b06e5 (diff) |
r8169: Rx FIFO overflow fixes.
Realtek has specified that the post 8168c gigabit chips and the post
8105e fast ethernet chips recover automatically from a Rx FIFO overflow.
The driver does not need to clear the RxFIFOOver bit of IntrStatus and
it should rather avoid messing it.
The implementation deserves some explanation:
1. events outside of the intr_event bit mask are now ignored. It enforces
a no-processing policy for the events that either should not be there
or should be ignored.
2. RxFIFOOver was already ignored in rtl_cfg_infos[RTL_CFG_1] for the
whole 8168 line of chips with two exceptions:
- RTL_GIGA_MAC_VER_22 since b5ba6d12bdac21bc0620a5089e0f24e362645efd
("use RxFIFO overflow workaround for 8168c chipset.").
This one should now be correctly handled.
- RTL_GIGA_MAC_VER_11 (8168b) which requires a different Rx FIFO
overflow processing.
Though it does not conform to Realtek suggestion above, the updated
driver includes no change for RTL_GIGA_MAC_VER_12 and RTL_GIGA_MAC_VER_17.
Both are 8168b. RTL_GIGA_MAC_VER_12 is common and a bit old so I'd rather
wait for experimental evidence that the change suggested by Realtek really
helps or does not hurt in unexpected ways.
Removed case statements in rtl8169_interrupt are only 8168 relevant.
3. RxFIFOOver is masked for post 8105e 810x chips, namely the sole 8105e
(RTL_GIGA_MAC_VER_30) itself.
Signed-off-by: Francois Romieu <romieu@fr.zoreil.com>
Cc: hayeswang <hayeswang@realtek.com>
Signed-off-by: David S. Miller <davem@davemloft.net>
Diffstat (limited to 'drivers/net/ethernet/realtek')
-rw-r--r-- | drivers/net/ethernet/realtek/r8169.c | 42 |
1 files changed, 17 insertions, 25 deletions
diff --git a/drivers/net/ethernet/realtek/r8169.c b/drivers/net/ethernet/realtek/r8169.c index 6f06aa10f0d7..7a1e3a69f193 100644 --- a/drivers/net/ethernet/realtek/r8169.c +++ b/drivers/net/ethernet/realtek/r8169.c | |||
@@ -1183,11 +1183,13 @@ static u8 rtl8168d_efuse_read(void __iomem *ioaddr, int reg_addr) | |||
1183 | return value; | 1183 | return value; |
1184 | } | 1184 | } |
1185 | 1185 | ||
1186 | static void rtl8169_irq_mask_and_ack(void __iomem *ioaddr) | 1186 | static void rtl8169_irq_mask_and_ack(struct rtl8169_private *tp) |
1187 | { | 1187 | { |
1188 | RTL_W16(IntrMask, 0x0000); | 1188 | void __iomem *ioaddr = tp->mmio_addr; |
1189 | 1189 | ||
1190 | RTL_W16(IntrStatus, 0xffff); | 1190 | RTL_W16(IntrMask, 0x0000); |
1191 | RTL_W16(IntrStatus, tp->intr_event); | ||
1192 | RTL_R8(ChipCmd); | ||
1191 | } | 1193 | } |
1192 | 1194 | ||
1193 | static unsigned int rtl8169_tbi_reset_pending(struct rtl8169_private *tp) | 1195 | static unsigned int rtl8169_tbi_reset_pending(struct rtl8169_private *tp) |
@@ -4339,7 +4341,7 @@ static void rtl8169_hw_reset(struct rtl8169_private *tp) | |||
4339 | void __iomem *ioaddr = tp->mmio_addr; | 4341 | void __iomem *ioaddr = tp->mmio_addr; |
4340 | 4342 | ||
4341 | /* Disable interrupts */ | 4343 | /* Disable interrupts */ |
4342 | rtl8169_irq_mask_and_ack(ioaddr); | 4344 | rtl8169_irq_mask_and_ack(tp); |
4343 | 4345 | ||
4344 | rtl_rx_close(tp); | 4346 | rtl_rx_close(tp); |
4345 | 4347 | ||
@@ -4885,8 +4887,7 @@ static void rtl_hw_start_8168(struct net_device *dev) | |||
4885 | RTL_W16(IntrMitigate, 0x5151); | 4887 | RTL_W16(IntrMitigate, 0x5151); |
4886 | 4888 | ||
4887 | /* Work around for RxFIFO overflow. */ | 4889 | /* Work around for RxFIFO overflow. */ |
4888 | if (tp->mac_version == RTL_GIGA_MAC_VER_11 || | 4890 | if (tp->mac_version == RTL_GIGA_MAC_VER_11) { |
4889 | tp->mac_version == RTL_GIGA_MAC_VER_22) { | ||
4890 | tp->intr_event |= RxFIFOOver | PCSTimeout; | 4891 | tp->intr_event |= RxFIFOOver | PCSTimeout; |
4891 | tp->intr_event &= ~RxOverflow; | 4892 | tp->intr_event &= ~RxOverflow; |
4892 | } | 4893 | } |
@@ -5076,6 +5077,11 @@ static void rtl_hw_start_8101(struct net_device *dev) | |||
5076 | void __iomem *ioaddr = tp->mmio_addr; | 5077 | void __iomem *ioaddr = tp->mmio_addr; |
5077 | struct pci_dev *pdev = tp->pci_dev; | 5078 | struct pci_dev *pdev = tp->pci_dev; |
5078 | 5079 | ||
5080 | if (tp->mac_version >= RTL_GIGA_MAC_VER_30) { | ||
5081 | tp->intr_event &= ~RxFIFOOver; | ||
5082 | tp->napi_event &= ~RxFIFOOver; | ||
5083 | } | ||
5084 | |||
5079 | if (tp->mac_version == RTL_GIGA_MAC_VER_13 || | 5085 | if (tp->mac_version == RTL_GIGA_MAC_VER_13 || |
5080 | tp->mac_version == RTL_GIGA_MAC_VER_16) { | 5086 | tp->mac_version == RTL_GIGA_MAC_VER_16) { |
5081 | int cap = pci_pcie_cap(pdev); | 5087 | int cap = pci_pcie_cap(pdev); |
@@ -5342,7 +5348,7 @@ static void rtl8169_wait_for_quiescence(struct net_device *dev) | |||
5342 | /* Wait for any pending NAPI task to complete */ | 5348 | /* Wait for any pending NAPI task to complete */ |
5343 | napi_disable(&tp->napi); | 5349 | napi_disable(&tp->napi); |
5344 | 5350 | ||
5345 | rtl8169_irq_mask_and_ack(ioaddr); | 5351 | rtl8169_irq_mask_and_ack(tp); |
5346 | 5352 | ||
5347 | tp->intr_mask = 0xffff; | 5353 | tp->intr_mask = 0xffff; |
5348 | RTL_W16(IntrMask, tp->intr_event); | 5354 | RTL_W16(IntrMask, tp->intr_event); |
@@ -5804,6 +5810,10 @@ static irqreturn_t rtl8169_interrupt(int irq, void *dev_instance) | |||
5804 | */ | 5810 | */ |
5805 | status = RTL_R16(IntrStatus); | 5811 | status = RTL_R16(IntrStatus); |
5806 | while (status && status != 0xffff) { | 5812 | while (status && status != 0xffff) { |
5813 | status &= tp->intr_event; | ||
5814 | if (!status) | ||
5815 | break; | ||
5816 | |||
5807 | handled = 1; | 5817 | handled = 1; |
5808 | 5818 | ||
5809 | /* Handle all of the error cases first. These will reset | 5819 | /* Handle all of the error cases first. These will reset |
@@ -5818,27 +5828,9 @@ static irqreturn_t rtl8169_interrupt(int irq, void *dev_instance) | |||
5818 | switch (tp->mac_version) { | 5828 | switch (tp->mac_version) { |
5819 | /* Work around for rx fifo overflow */ | 5829 | /* Work around for rx fifo overflow */ |
5820 | case RTL_GIGA_MAC_VER_11: | 5830 | case RTL_GIGA_MAC_VER_11: |
5821 | case RTL_GIGA_MAC_VER_22: | ||
5822 | case RTL_GIGA_MAC_VER_26: | ||
5823 | netif_stop_queue(dev); | 5831 | netif_stop_queue(dev); |
5824 | rtl8169_tx_timeout(dev); | 5832 | rtl8169_tx_timeout(dev); |
5825 | goto done; | 5833 | goto done; |
5826 | /* Testers needed. */ | ||
5827 | case RTL_GIGA_MAC_VER_17: | ||
5828 | case RTL_GIGA_MAC_VER_19: | ||
5829 | case RTL_GIGA_MAC_VER_20: | ||
5830 | case RTL_GIGA_MAC_VER_21: | ||
5831 | case RTL_GIGA_MAC_VER_23: | ||
5832 | case RTL_GIGA_MAC_VER_24: | ||
5833 | case RTL_GIGA_MAC_VER_27: | ||
5834 | case RTL_GIGA_MAC_VER_28: | ||
5835 | case RTL_GIGA_MAC_VER_31: | ||
5836 | /* Experimental science. Pktgen proof. */ | ||
5837 | case RTL_GIGA_MAC_VER_12: | ||
5838 | case RTL_GIGA_MAC_VER_25: | ||
5839 | if (status == RxFIFOOver) | ||
5840 | goto done; | ||
5841 | break; | ||
5842 | default: | 5834 | default: |
5843 | break; | 5835 | break; |
5844 | } | 5836 | } |