From: Ivan Vecera <ivecera@redhat.com> Date: Wed, 22 Apr 2009 16:52:58 +0200 Subject: [net] r8169: fix RxMissed register access Message-id: 1240411978-5467-1-git-send-email-ivecera@redhat.com O-Subject: [RHEL5.4 PATCH] r8169: fix RxMissed register access Bugzilla: 474334 RH-Acked-by: Michal Schmidt <mschmidt@redhat.com> RH-Acked-by: Prarit Bhargava <prarit@redhat.com> RH-Acked-by: Stanislaw Gruszka <sgruszka@redhat.com> RH-Acked-by: David Miller <davem@redhat.com> BZs: #474334 - r8169 reports incredible number of RX dropped packets Description: Some NIC chipsets handled by r8169 returns incredible (random) number of RX dropped packets (in ifconfig ethX). The reason is that RxMissed register is valid only for 8169 chipset (MACs below RTL_GIGA_MAC_VER_06) and this register is only 24-bit and not 32-bit. For other chipsets this register is not defined and should not be used. Test status: Tested successfully by myself. Upstream status: http://git.kernel.org/?p=linux/kernel/git/torvalds/linux-2.6.git;a=commitdiff;h=523a609496dbc3897e530db2a2f27650d125ea00 Signed-off-by: Ivan Vecera <ivecera@redhat.com> diff --git a/drivers/net/r8169.c b/drivers/net/r8169.c index 41f99d1..913959b 100644 --- a/drivers/net/r8169.c +++ b/drivers/net/r8169.c @@ -2656,8 +2656,6 @@ static void rtl_hw_start_8168(struct net_device *dev) RTL_W32(TxConfig, (TX_DMA_BURST << TxDMAShift) | (InterFrameGap << TxInterFrameGapShift)); - RTL_W32(RxMissed, 0); - RTL_R8(IntrMask); switch (tp->mac_version) { @@ -2832,8 +2830,6 @@ static void rtl_hw_start_8101(struct net_device *dev) RTL_R8(IntrMask); - RTL_W32(RxMissed, 0); - rtl_set_rx_mode(dev); RTL_W8(ChipCmd, CmdTxEnb | CmdRxEnb); @@ -3612,6 +3608,17 @@ static int rtl8169_poll(struct net_device *dev, int *budget) return (work_done >= work_to_do); } +static void rtl8169_rx_missed(struct net_device *dev, void __iomem *ioaddr) +{ + struct rtl8169_private *tp = netdev_priv(dev); + + if (tp->mac_version > RTL_GIGA_MAC_VER_06) + return; + + tp->stats.rx_missed_errors += (RTL_R32(RxMissed) & 0xffffff); + RTL_W32(RxMissed, 0); +} + static void rtl8169_down(struct net_device *dev) { struct rtl8169_private *tp = netdev_priv(dev); @@ -3629,9 +3636,7 @@ core_down: rtl8169_asic_down(ioaddr); - /* Update the error counts. */ - tp->stats.rx_missed_errors += RTL_R32(RxMissed); - RTL_W32(RxMissed, 0); + rtl8169_rx_missed(dev, ioaddr); spin_unlock_irq(&tp->lock); @@ -3753,8 +3758,7 @@ static struct net_device_stats *rtl8169_get_stats(struct net_device *dev) if (netif_running(dev)) { spin_lock_irqsave(&tp->lock, flags); - tp->stats.rx_missed_errors += RTL_R32(RxMissed); - RTL_W32(RxMissed, 0); + rtl8169_rx_missed(dev, ioaddr); spin_unlock_irqrestore(&tp->lock, flags); } @@ -3779,8 +3783,7 @@ static int rtl8169_suspend(struct pci_dev *pdev, pm_message_t state) rtl8169_asic_down(ioaddr); - tp->stats.rx_missed_errors += RTL_R32(RxMissed); - RTL_W32(RxMissed, 0); + rtl8169_rx_missed(dev, ioaddr); spin_unlock_irq(&tp->lock);