Skip to content

Commit

Permalink
r8169: Rx FIFO overflow fixes.
Browse files Browse the repository at this point in the history
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 b5ba6d1
     ("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>
  • Loading branch information
françois romieu authored and David S. Miller committed Dec 5, 2011
1 parent 321f3b8 commit 811fd30
Showing 1 changed file with 17 additions and 25 deletions.
42 changes: 17 additions & 25 deletions drivers/net/ethernet/realtek/r8169.c
Original file line number Diff line number Diff line change
Expand Up @@ -1183,11 +1183,13 @@ 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 unsigned int rtl8169_tbi_reset_pending(struct rtl8169_private *tp)
Expand Down Expand Up @@ -4339,7 +4341,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);

rtl_rx_close(tp);

Expand Down Expand Up @@ -4885,8 +4887,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;
}
Expand Down Expand Up @@ -5076,6 +5077,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 = pci_pcie_cap(pdev);
Expand Down Expand Up @@ -5342,7 +5348,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);
Expand Down Expand Up @@ -5804,6 +5810,10 @@ 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
Expand All @@ -5818,27 +5828,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;
}
Expand Down

0 comments on commit 811fd30

Please sign in to comment.