mirror of
https://github.com/hardkernel/linux.git
synced 2026-06-08 11:50:43 +09:00
r8169: Rx FIFO overflow fixes.
commit811fd3010cupstream. 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 sinceb5ba6d12bd("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> Reviewed-by: Jonathan Nieder <jrnieder@gmail.com> Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
This commit is contained in:
committed by
Greg Kroah-Hartman
parent
c43209e915
commit
85ce02207e
@@ -1088,17 +1088,21 @@ static u8 rtl8168d_efuse_read(void __iomem *ioaddr, int reg_addr)
|
||||
return value;
|
||||
}
|
||||
|
||||
static void rtl8169_irq_mask_and_ack(void __iomem *ioaddr)
|
||||
static void rtl8169_irq_mask_and_ack(struct rtl8169_private *tp)
|
||||
{
|
||||
RTL_W16(IntrMask, 0x0000);
|
||||
void __iomem *ioaddr = tp->mmio_addr;
|
||||
|
||||
RTL_W16(IntrStatus, 0xffff);
|
||||
RTL_W16(IntrMask, 0x0000);
|
||||
RTL_W16(IntrStatus, tp->intr_event);
|
||||
RTL_R8(ChipCmd);
|
||||
}
|
||||
|
||||
static void rtl8169_asic_down(void __iomem *ioaddr)
|
||||
static void rtl8169_asic_down(struct rtl8169_private *tp)
|
||||
{
|
||||
void __iomem *ioaddr = tp->mmio_addr;
|
||||
|
||||
RTL_W8(ChipCmd, 0x00);
|
||||
rtl8169_irq_mask_and_ack(ioaddr);
|
||||
rtl8169_irq_mask_and_ack(tp);
|
||||
RTL_R16(CPlusCmd);
|
||||
}
|
||||
|
||||
@@ -3817,7 +3821,7 @@ static void rtl8169_hw_reset(struct rtl8169_private *tp)
|
||||
void __iomem *ioaddr = tp->mmio_addr;
|
||||
|
||||
/* Disable interrupts */
|
||||
rtl8169_irq_mask_and_ack(ioaddr);
|
||||
rtl8169_irq_mask_and_ack(tp);
|
||||
|
||||
if (tp->mac_version == RTL_GIGA_MAC_VER_27 ||
|
||||
tp->mac_version == RTL_GIGA_MAC_VER_28 ||
|
||||
@@ -4284,8 +4288,7 @@ static void rtl_hw_start_8168(struct net_device *dev)
|
||||
RTL_W16(IntrMitigate, 0x5151);
|
||||
|
||||
/* Work around for RxFIFO overflow. */
|
||||
if (tp->mac_version == RTL_GIGA_MAC_VER_11 ||
|
||||
tp->mac_version == RTL_GIGA_MAC_VER_22) {
|
||||
if (tp->mac_version == RTL_GIGA_MAC_VER_11) {
|
||||
tp->intr_event |= RxFIFOOver | PCSTimeout;
|
||||
tp->intr_event &= ~RxOverflow;
|
||||
}
|
||||
@@ -4467,6 +4470,11 @@ static void rtl_hw_start_8101(struct net_device *dev)
|
||||
void __iomem *ioaddr = tp->mmio_addr;
|
||||
struct pci_dev *pdev = tp->pci_dev;
|
||||
|
||||
if (tp->mac_version >= RTL_GIGA_MAC_VER_30) {
|
||||
tp->intr_event &= ~RxFIFOOver;
|
||||
tp->napi_event &= ~RxFIFOOver;
|
||||
}
|
||||
|
||||
if (tp->mac_version == RTL_GIGA_MAC_VER_13 ||
|
||||
tp->mac_version == RTL_GIGA_MAC_VER_16) {
|
||||
int cap = tp->pcie_cap;
|
||||
@@ -4738,7 +4746,7 @@ static void rtl8169_wait_for_quiescence(struct net_device *dev)
|
||||
/* Wait for any pending NAPI task to complete */
|
||||
napi_disable(&tp->napi);
|
||||
|
||||
rtl8169_irq_mask_and_ack(ioaddr);
|
||||
rtl8169_irq_mask_and_ack(tp);
|
||||
|
||||
tp->intr_mask = 0xffff;
|
||||
RTL_W16(IntrMask, tp->intr_event);
|
||||
@@ -5200,13 +5208,17 @@ static irqreturn_t rtl8169_interrupt(int irq, void *dev_instance)
|
||||
*/
|
||||
status = RTL_R16(IntrStatus);
|
||||
while (status && status != 0xffff) {
|
||||
status &= tp->intr_event;
|
||||
if (!status)
|
||||
break;
|
||||
|
||||
handled = 1;
|
||||
|
||||
/* Handle all of the error cases first. These will reset
|
||||
* the chip, so just exit the loop.
|
||||
*/
|
||||
if (unlikely(!netif_running(dev))) {
|
||||
rtl8169_asic_down(ioaddr);
|
||||
rtl8169_asic_down(tp);
|
||||
break;
|
||||
}
|
||||
|
||||
@@ -5214,27 +5226,9 @@ static irqreturn_t rtl8169_interrupt(int irq, void *dev_instance)
|
||||
switch (tp->mac_version) {
|
||||
/* Work around for rx fifo overflow */
|
||||
case RTL_GIGA_MAC_VER_11:
|
||||
case RTL_GIGA_MAC_VER_22:
|
||||
case RTL_GIGA_MAC_VER_26:
|
||||
netif_stop_queue(dev);
|
||||
rtl8169_tx_timeout(dev);
|
||||
goto done;
|
||||
/* Testers needed. */
|
||||
case RTL_GIGA_MAC_VER_17:
|
||||
case RTL_GIGA_MAC_VER_19:
|
||||
case RTL_GIGA_MAC_VER_20:
|
||||
case RTL_GIGA_MAC_VER_21:
|
||||
case RTL_GIGA_MAC_VER_23:
|
||||
case RTL_GIGA_MAC_VER_24:
|
||||
case RTL_GIGA_MAC_VER_27:
|
||||
case RTL_GIGA_MAC_VER_28:
|
||||
case RTL_GIGA_MAC_VER_31:
|
||||
/* Experimental science. Pktgen proof. */
|
||||
case RTL_GIGA_MAC_VER_12:
|
||||
case RTL_GIGA_MAC_VER_25:
|
||||
if (status == RxFIFOOver)
|
||||
goto done;
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
@@ -5329,7 +5323,7 @@ static void rtl8169_down(struct net_device *dev)
|
||||
|
||||
spin_lock_irq(&tp->lock);
|
||||
|
||||
rtl8169_asic_down(ioaddr);
|
||||
rtl8169_asic_down(tp);
|
||||
/*
|
||||
* At this point device interrupts can not be enabled in any function,
|
||||
* as netif_running is not true (rtl8169_interrupt, rtl8169_reset_task,
|
||||
@@ -5583,7 +5577,7 @@ static void rtl_shutdown(struct pci_dev *pdev)
|
||||
|
||||
spin_lock_irq(&tp->lock);
|
||||
|
||||
rtl8169_asic_down(ioaddr);
|
||||
rtl8169_asic_down(tp);
|
||||
|
||||
spin_unlock_irq(&tp->lock);
|
||||
|
||||
|
||||
Reference in New Issue
Block a user