]> www.pilppa.org Git - linux-2.6-omap-h63xx.git/blobdiff - drivers/net/r8169.c
r8169: workaround against ignored TxPoll writes (8168)
[linux-2.6-omap-h63xx.git] / drivers / net / r8169.c
index 49e599bc3f48958169e4db2e971fab6ca329e0bc..c921ec32c232cb265323f9075a2daf27275e188b 100644 (file)
@@ -1,53 +1,11 @@
 /*
-=========================================================================
- r8169.c: A RealTek RTL-8169 Gigabit Ethernet driver for Linux kernel 2.4.x.
- --------------------------------------------------------------------
-
- History:
- Feb  4 2002   - created initially by ShuChen <shuchen@realtek.com.tw>.
- May 20 2002   - Add link status force-mode and TBI mode support.
-       2004    - Massive updates. See kernel SCM system for details.
-=========================================================================
-  1. [DEPRECATED: use ethtool instead] The media can be forced in 5 modes.
-        Command: 'insmod r8169 media = SET_MEDIA'
-        Ex:      'insmod r8169 media = 0x04' will force PHY to operate in 100Mpbs Half-duplex.
-
-        SET_MEDIA can be:
-               _10_Half        = 0x01
-               _10_Full        = 0x02
-               _100_Half       = 0x04
-               _100_Full       = 0x08
-               _1000_Full      = 0x10
-
-  2. Support TBI mode.
-=========================================================================
-VERSION 1.1    <2002/10/4>
-
-       The bit4:0 of MII register 4 is called "selector field", and have to be
-       00001b to indicate support of IEEE std 802.3 during NWay process of
-       exchanging Link Code Word (FLP).
-
-VERSION 1.2    <2002/11/30>
-
-       - Large style cleanup
-       - Use ether_crc in stock kernel (linux/crc32.h)
-       - Copy mc_filter setup code from 8139cp
-         (includes an optimization, and avoids set_bit use)
-
-VERSION 1.6LK  <2004/04/14>
-
-       - Merge of Realtek's version 1.6
-       - Conversion to DMA API
-       - Suspend/resume
-       - Endianness
-       - Misc Rx/Tx bugs
-
-VERSION 2.2LK  <2005/01/25>
-
-       - RX csum, TX csum/SG, TSO
-       - VLAN
-       - baby (< 7200) Jumbo frames support
-       - Merge of Realtek's version 2.2 (new phy)
+ * r8169.c: RealTek 8169/8168/8101 ethernet driver.
+ *
+ * Copyright (c) 2002 ShuChen <shuchen@realtek.com.tw>
+ * Copyright (c) 2003 - 2007 Francois Romieu <romieu@fr.zoreil.com>
+ * Copyright (c) a lot of people too. Please respect their work.
+ *
+ * See MAINTAINERS file for support contact information.
  */
 
 #include <linux/module.h>
@@ -108,11 +66,6 @@ VERSION 2.2LK       <2005/01/25>
 #define rtl8169_rx_quota(count, quota) count
 #endif
 
-/* media options */
-#define MAX_UNITS 8
-static int media[MAX_UNITS] = { -1, -1, -1, -1, -1, -1, -1, -1 };
-static int num_media = 0;
-
 /* Maximum events (Rx packets, etc.) to handle at each interrupt. */
 static const int max_interrupt_work = 20;
 
@@ -126,7 +79,7 @@ static const int multicast_filter_limit = 32;
 #define RX_FIFO_THRESH 7       /* 7 means NO threshold, Rx buffer level before first PCI xfer. */
 #define RX_DMA_BURST   6       /* Maximum PCI burst, '6' is 1024 */
 #define TX_DMA_BURST   6       /* Maximum PCI burst, '6' is 1024 */
-#define EarlyTxThld    0x3F    /* 0x3F means NO early transmit */
+#define EarlyTxThld    0x3F    /* 0x3F means NO early transmit */
 #define RxPacketMaxSize        0x3FE8  /* 16K - 1 - ETH_HLEN - VLAN - CRC... */
 #define SafeMtu                0x1c20  /* ... actually life sucks beyond ~7k */
 #define InterFrameGap  0x03    /* 3 means InterFrameGap = the shortest one */
@@ -227,62 +180,63 @@ static struct {
        u32 msg_enable;
 } debug = { -1 };
 
-enum RTL8169_registers {
-       MAC0 = 0,               /* Ethernet hardware address. */
-       MAR0 = 8,               /* Multicast filter. */
-       CounterAddrLow = 0x10,
-       CounterAddrHigh = 0x14,
-       TxDescStartAddrLow = 0x20,
-       TxDescStartAddrHigh = 0x24,
-       TxHDescStartAddrLow = 0x28,
-       TxHDescStartAddrHigh = 0x2c,
-       FLASH = 0x30,
-       ERSR = 0x36,
-       ChipCmd = 0x37,
-       TxPoll = 0x38,
-       IntrMask = 0x3C,
-       IntrStatus = 0x3E,
-       TxConfig = 0x40,
-       RxConfig = 0x44,
-       RxMissed = 0x4C,
-       Cfg9346 = 0x50,
-       Config0 = 0x51,
-       Config1 = 0x52,
-       Config2 = 0x53,
-       Config3 = 0x54,
-       Config4 = 0x55,
-       Config5 = 0x56,
-       MultiIntr = 0x5C,
-       PHYAR = 0x60,
-       TBICSR = 0x64,
-       TBI_ANAR = 0x68,
-       TBI_LPAR = 0x6A,
-       PHYstatus = 0x6C,
-       RxMaxSize = 0xDA,
-       CPlusCmd = 0xE0,
-       IntrMitigate = 0xE2,
-       RxDescAddrLow = 0xE4,
-       RxDescAddrHigh = 0xE8,
-       EarlyTxThres = 0xEC,
-       FuncEvent = 0xF0,
-       FuncEventMask = 0xF4,
-       FuncPresetState = 0xF8,
-       FuncForceEvent = 0xFC,
+enum rtl_registers {
+       MAC0            = 0,    /* Ethernet hardware address. */
+       MAC4            = 4,
+       MAR0            = 8,    /* Multicast filter. */
+       CounterAddrLow          = 0x10,
+       CounterAddrHigh         = 0x14,
+       TxDescStartAddrLow      = 0x20,
+       TxDescStartAddrHigh     = 0x24,
+       TxHDescStartAddrLow     = 0x28,
+       TxHDescStartAddrHigh    = 0x2c,
+       FLASH           = 0x30,
+       ERSR            = 0x36,
+       ChipCmd         = 0x37,
+       TxPoll          = 0x38,
+       IntrMask        = 0x3c,
+       IntrStatus      = 0x3e,
+       TxConfig        = 0x40,
+       RxConfig        = 0x44,
+       RxMissed        = 0x4c,
+       Cfg9346         = 0x50,
+       Config0         = 0x51,
+       Config1         = 0x52,
+       Config2         = 0x53,
+       Config3         = 0x54,
+       Config4         = 0x55,
+       Config5         = 0x56,
+       MultiIntr       = 0x5c,
+       PHYAR           = 0x60,
+       TBICSR          = 0x64,
+       TBI_ANAR        = 0x68,
+       TBI_LPAR        = 0x6a,
+       PHYstatus       = 0x6c,
+       RxMaxSize       = 0xda,
+       CPlusCmd        = 0xe0,
+       IntrMitigate    = 0xe2,
+       RxDescAddrLow   = 0xe4,
+       RxDescAddrHigh  = 0xe8,
+       EarlyTxThres    = 0xec,
+       FuncEvent       = 0xf0,
+       FuncEventMask   = 0xf4,
+       FuncPresetState = 0xf8,
+       FuncForceEvent  = 0xfc,
 };
 
-enum RTL8169_register_content {
+enum rtl_register_content {
        /* InterruptStatusBits */
-       SYSErr = 0x8000,
-       PCSTimeout = 0x4000,
-       SWInt = 0x0100,
-       TxDescUnavail = 0x80,
-       RxFIFOOver = 0x40,
-       LinkChg = 0x20,
-       RxOverflow = 0x10,
-       TxErr = 0x08,
-       TxOK = 0x04,
-       RxErr = 0x02,
-       RxOK = 0x01,
+       SYSErr          = 0x8000,
+       PCSTimeout      = 0x4000,
+       SWInt           = 0x0100,
+       TxDescUnavail   = 0x0080,
+       RxFIFOOver      = 0x0040,
+       LinkChg         = 0x0020,
+       RxOverflow      = 0x0010,
+       TxErr           = 0x0008,
+       TxOK            = 0x0004,
+       RxErr           = 0x0002,
+       RxOK            = 0x0001,
 
        /* RxStatusDesc */
        RxFOVF  = (1 << 23),
@@ -292,26 +246,31 @@ enum RTL8169_register_content {
        RxCRC   = (1 << 19),
 
        /* ChipCmdBits */
-       CmdReset = 0x10,
-       CmdRxEnb = 0x08,
-       CmdTxEnb = 0x04,
-       RxBufEmpty = 0x01,
+       CmdReset        = 0x10,
+       CmdRxEnb        = 0x08,
+       CmdTxEnb        = 0x04,
+       RxBufEmpty      = 0x01,
+
+       /* TXPoll register p.5 */
+       HPQ             = 0x80,         /* Poll cmd on the high prio queue */
+       NPQ             = 0x40,         /* Poll cmd on the low prio queue */
+       FSWInt          = 0x01,         /* Forced software interrupt */
 
        /* Cfg9346Bits */
-       Cfg9346_Lock = 0x00,
-       Cfg9346_Unlock = 0xC0,
+       Cfg9346_Lock    = 0x00,
+       Cfg9346_Unlock  = 0xc0,
 
        /* rx_mode_bits */
-       AcceptErr = 0x20,
-       AcceptRunt = 0x10,
-       AcceptBroadcast = 0x08,
-       AcceptMulticast = 0x04,
-       AcceptMyPhys = 0x02,
-       AcceptAllPhys = 0x01,
+       AcceptErr       = 0x20,
+       AcceptRunt      = 0x10,
+       AcceptBroadcast = 0x08,
+       AcceptMulticast = 0x04,
+       AcceptMyPhys    = 0x02,
+       AcceptAllPhys   = 0x01,
 
        /* RxConfigBits */
-       RxCfgFIFOShift = 13,
-       RxCfgDMAShift = 8,
+       RxCfgFIFOShift  = 13,
+       RxCfgDMAShift   =  8,
 
        /* TxConfigBits */
        TxInterFrameGapShift = 24,
@@ -355,30 +314,23 @@ enum RTL8169_register_content {
        INTT_3          = 0x0003,       // 8168
 
        /* rtl8169_PHYstatus */
-       TBI_Enable = 0x80,
-       TxFlowCtrl = 0x40,
-       RxFlowCtrl = 0x20,
-       _1000bpsF = 0x10,
-       _100bps = 0x08,
-       _10bps = 0x04,
-       LinkStatus = 0x02,
-       FullDup = 0x01,
-
-       /* _MediaType */
-       _10_Half = 0x01,
-       _10_Full = 0x02,
-       _100_Half = 0x04,
-       _100_Full = 0x08,
-       _1000_Full = 0x10,
+       TBI_Enable      = 0x80,
+       TxFlowCtrl      = 0x40,
+       RxFlowCtrl      = 0x20,
+       _1000bpsF       = 0x10,
+       _100bps         = 0x08,
+       _10bps          = 0x04,
+       LinkStatus      = 0x02,
+       FullDup         = 0x01,
 
        /* _TBICSRBit */
-       TBILinkOK = 0x02000000,
+       TBILinkOK       = 0x02000000,
 
        /* DumpCounterCommand */
-       CounterDump = 0x8,
+       CounterDump     = 0x8,
 };
 
-enum _DescStatusBit {
+enum desc_status_bit {
        DescOwn         = (1 << 31), /* Descriptor is owned by NIC */
        RingEnd         = (1 << 30), /* End of descriptor ring */
        FirstFrag       = (1 << 29), /* First segment of a packet */
@@ -411,15 +363,15 @@ enum _DescStatusBit {
 #define RsvdMask       0x3fffc000
 
 struct TxDesc {
-       u32 opts1;
-       u32 opts2;
-       u64 addr;
+       __le32 opts1;
+       __le32 opts2;
+       __le64 addr;
 };
 
 struct RxDesc {
-       u32 opts1;
-       u32 opts2;
-       u64 addr;
+       __le32 opts1;
+       __le32 opts2;
+       __le64 addr;
 };
 
 struct ring_info {
@@ -472,8 +424,6 @@ struct rtl8169_private {
 
 MODULE_AUTHOR("Realtek and the Linux r8169 crew <netdev@vger.kernel.org>");
 MODULE_DESCRIPTION("RealTek RTL-8169 Gigabit Ethernet driver");
-module_param_array(media, int, &num_media, 0);
-MODULE_PARM_DESC(media, "force phy operation. Deprecated by ethtool (8).");
 module_param(rx_copybreak, int, 0);
 MODULE_PARM_DESC(rx_copybreak, "Copy breakpoint for copy-only-tiny-frames");
 module_param(use_dac, int, 0);
@@ -505,28 +455,34 @@ static int rtl8169_poll(struct net_device *dev, int *budget);
 static const unsigned int rtl8169_rx_config =
        (RX_FIFO_THRESH << RxCfgFIFOShift) | (RX_DMA_BURST << RxCfgDMAShift);
 
-static void mdio_write(void __iomem *ioaddr, int RegAddr, int value)
+static void mdio_write(void __iomem *ioaddr, int reg_addr, int value)
 {
        int i;
 
-       RTL_W32(PHYAR, 0x80000000 | (RegAddr & 0xFF) << 16 | value);
+       RTL_W32(PHYAR, 0x80000000 | (reg_addr & 0xFF) << 16 | value);
 
        for (i = 20; i > 0; i--) {
-               /* Check if the RTL8169 has completed writing to the specified MII register */
+               /*
+                * Check if the RTL8169 has completed writing to the specified
+                * MII register.
+                */
                if (!(RTL_R32(PHYAR) & 0x80000000))
                        break;
                udelay(25);
        }
 }
 
-static int mdio_read(void __iomem *ioaddr, int RegAddr)
+static int mdio_read(void __iomem *ioaddr, int reg_addr)
 {
        int i, value = -1;
 
-       RTL_W32(PHYAR, 0x0 | (RegAddr & 0xFF) << 16);
+       RTL_W32(PHYAR, 0x0 | (reg_addr & 0xFF) << 16);
 
        for (i = 20; i > 0; i--) {
-               /* Check if the RTL8169 has completed retrieving data from the specified MII register */
+               /*
+                * Check if the RTL8169 has completed retrieving data from
+                * the specified MII register.
+                */
                if (RTL_R32(PHYAR) & 0x80000000) {
                        value = (int) (RTL_R32(PHYAR) & 0xFFFF);
                        break;
@@ -584,7 +540,8 @@ static void rtl8169_xmii_reset_enable(void __iomem *ioaddr)
 }
 
 static void rtl8169_check_link_status(struct net_device *dev,
-                                     struct rtl8169_private *tp, void __iomem *ioaddr)
+                                     struct rtl8169_private *tp,
+                                     void __iomem *ioaddr)
 {
        unsigned long flags;
 
@@ -601,38 +558,6 @@ static void rtl8169_check_link_status(struct net_device *dev,
        spin_unlock_irqrestore(&tp->lock, flags);
 }
 
-static void rtl8169_link_option(int idx, u8 *autoneg, u16 *speed, u8 *duplex)
-{
-       struct {
-               u16 speed;
-               u8 duplex;
-               u8 autoneg;
-               u8 media;
-       } link_settings[] = {
-               { SPEED_10,     DUPLEX_HALF, AUTONEG_DISABLE,   _10_Half },
-               { SPEED_10,     DUPLEX_FULL, AUTONEG_DISABLE,   _10_Full },
-               { SPEED_100,    DUPLEX_HALF, AUTONEG_DISABLE,   _100_Half },
-               { SPEED_100,    DUPLEX_FULL, AUTONEG_DISABLE,   _100_Full },
-               { SPEED_1000,   DUPLEX_FULL, AUTONEG_DISABLE,   _1000_Full },
-               /* Make TBI happy */
-               { SPEED_1000,   DUPLEX_FULL, AUTONEG_ENABLE,    0xff }
-       }, *p;
-       unsigned char option;
-
-       option = ((idx < MAX_UNITS) && (idx >= 0)) ? media[idx] : 0xff;
-
-       if ((option != 0xff) && !idx && netif_msg_drv(&debug))
-               printk(KERN_WARNING PFX "media option is deprecated.\n");
-
-       for (p = link_settings; p->media != 0xff; p++) {
-               if (p->media == option)
-                       break;
-       }
-       *autoneg = p->autoneg;
-       *speed = p->speed;
-       *duplex = p->duplex;
-}
-
 static void rtl8169_get_wol(struct net_device *dev, struct ethtool_wolinfo *wol)
 {
        struct rtl8169_private *tp = netdev_priv(dev);
@@ -672,7 +597,7 @@ static int rtl8169_set_wol(struct net_device *dev, struct ethtool_wolinfo *wol)
 {
        struct rtl8169_private *tp = netdev_priv(dev);
        void __iomem *ioaddr = tp->mmio_addr;
-       int i;
+       unsigned int i;
        static struct {
                u32 opt;
                u16 reg;
@@ -800,6 +725,12 @@ static int rtl8169_set_speed_xmii(struct net_device *dev,
 
        auto_nego |= ADVERTISE_PAUSE_CAP | ADVERTISE_PAUSE_ASYM;
 
+       if (tp->mac_version == RTL_GIGA_MAC_VER_12) {
+               /* Vendor specific (0x1f) and reserved (0x0e) MII registers. */
+               mdio_write(ioaddr, 0x1f, 0x0000);
+               mdio_write(ioaddr, 0x0e, 0x0000);
+       }
+
        tp->phy_auto_nego_reg = auto_nego;
        tp->phy_1000_ctrl_reg = giga_ctrl;
 
@@ -898,8 +829,7 @@ static int rtl8169_rx_vlan_skb(struct rtl8169_private *tp, struct RxDesc *desc,
        int ret;
 
        if (tp->vlgrp && (opts2 & RxVlanTag)) {
-               rtl8169_rx_hwaccel_skb(skb, tp->vlgrp,
-                                      swab16(opts2 & 0xffff));
+               rtl8169_rx_hwaccel_skb(skb, tp->vlgrp, swab16(opts2 & 0xffff));
                ret = 0;
        } else
                ret = -1;
@@ -1120,7 +1050,6 @@ static void rtl8169_get_strings(struct net_device *dev, u32 stringset, u8 *data)
        }
 }
 
-
 static const struct ethtool_ops rtl8169_ethtool_ops = {
        .get_drvinfo            = rtl8169_get_drvinfo,
        .get_regs_len           = rtl8169_get_regs_len,
@@ -1143,11 +1072,10 @@ static const struct ethtool_ops rtl8169_ethtool_ops = {
        .get_strings            = rtl8169_get_strings,
        .get_stats_count        = rtl8169_get_stats_count,
        .get_ethtool_stats      = rtl8169_get_ethtool_stats,
-       .get_perm_addr          = ethtool_op_get_perm_addr,
 };
 
-static void rtl8169_write_gmii_reg_bit(void __iomem *ioaddr, int reg, int bitnum,
-                                      int bitval)
+static void rtl8169_write_gmii_reg_bit(void __iomem *ioaddr, int reg,
+                                      int bitnum, int bitval)
 {
        int val;
 
@@ -1157,7 +1085,8 @@ static void rtl8169_write_gmii_reg_bit(void __iomem *ioaddr, int reg, int bitnum
        mdio_write(ioaddr, reg, val & 0xffff);
 }
 
-static void rtl8169_get_mac_version(struct rtl8169_private *tp, void __iomem *ioaddr)
+static void rtl8169_get_mac_version(struct rtl8169_private *tp,
+                                   void __iomem *ioaddr)
 {
        /*
         * The driver currently handles the 8168Bf and the 8168Be identically
@@ -1199,7 +1128,8 @@ static void rtl8169_print_mac_version(struct rtl8169_private *tp)
        dprintk("mac_version = 0x%02x\n", tp->mac_version);
 }
 
-static void rtl8169_get_phy_version(struct rtl8169_private *tp, void __iomem *ioaddr)
+static void rtl8169_get_phy_version(struct rtl8169_private *tp,
+                                   void __iomem *ioaddr)
 {
        const struct {
                u16 mask;
@@ -1276,7 +1206,7 @@ static void rtl8169_hw_phy_config(struct net_device *dev)
                  0xbf00 }      //w 0 15 0 bf00
                }
        }, *p = phy_magic;
-       int i;
+       unsigned int i;
 
        rtl8169_print_mac_version(tp);
        rtl8169_print_phy_version(tp);
@@ -1298,7 +1228,10 @@ static void rtl8169_hw_phy_config(struct net_device *dev)
                return;
        }
 
-       /* phy config for RTL8169s mac_version C chip */
+       if ((tp->mac_version != RTL_GIGA_MAC_VER_02) &&
+           (tp->mac_version != RTL_GIGA_MAC_VER_03))
+               return;
+
        mdio_write(ioaddr, 31, 0x0001);                 //w 31 2 0 1
        mdio_write(ioaddr, 21, 0x1000);                 //w 21 15 0 1000
        mdio_write(ioaddr, 24, 0x65c7);                 //w 24 15 0 65c7
@@ -1410,7 +1343,7 @@ static void rtl8169_phy_reset(struct net_device *dev,
                              struct rtl8169_private *tp)
 {
        void __iomem *ioaddr = tp->mmio_addr;
-       int i;
+       unsigned int i;
 
        tp->phy_reset_enable(ioaddr);
        for (i = 0; i < 100; i++) {
@@ -1425,11 +1358,6 @@ static void rtl8169_phy_reset(struct net_device *dev,
 static void rtl8169_init_phy(struct net_device *dev, struct rtl8169_private *tp)
 {
        void __iomem *ioaddr = tp->mmio_addr;
-       static int board_idx = -1;
-       u8 autoneg, duplex;
-       u16 speed;
-
-       board_idx++;
 
        rtl8169_hw_phy_config(dev);
 
@@ -1448,16 +1376,52 @@ static void rtl8169_init_phy(struct net_device *dev, struct rtl8169_private *tp)
                mdio_write(ioaddr, 0x0b, 0x0000); //w 0x0b 15 0 0
        }
 
-       rtl8169_link_option(board_idx, &autoneg, &speed, &duplex);
-
        rtl8169_phy_reset(dev, tp);
 
-       rtl8169_set_speed(dev, autoneg, speed, duplex);
+       /*
+        * rtl8169_set_speed_xmii takes good care of the Fast Ethernet
+        * only 8101. Don't panic.
+        */
+       rtl8169_set_speed(dev, AUTONEG_ENABLE, SPEED_1000, DUPLEX_FULL);
 
        if ((RTL_R8(PHYstatus) & TBI_Enable) && netif_msg_link(tp))
                printk(KERN_INFO PFX "%s: TBI auto-negotiating\n", dev->name);
 }
 
+static void rtl_rar_set(struct rtl8169_private *tp, u8 *addr)
+{
+       void __iomem *ioaddr = tp->mmio_addr;
+       u32 high;
+       u32 low;
+
+       low  = addr[0] | (addr[1] << 8) | (addr[2] << 16) | (addr[3] << 24);
+       high = addr[4] | (addr[5] << 8);
+
+       spin_lock_irq(&tp->lock);
+
+       RTL_W8(Cfg9346, Cfg9346_Unlock);
+       RTL_W32(MAC0, low);
+       RTL_W32(MAC4, high);
+       RTL_W8(Cfg9346, Cfg9346_Lock);
+
+       spin_unlock_irq(&tp->lock);
+}
+
+static int rtl_set_mac_address(struct net_device *dev, void *p)
+{
+       struct rtl8169_private *tp = netdev_priv(dev);
+       struct sockaddr *addr = p;
+
+       if (!is_valid_ether_addr(addr->sa_data))
+               return -EADDRNOTAVAIL;
+
+       memcpy(dev->dev_addr, addr->sa_data, dev->addr_len);
+
+       rtl_rar_set(tp, dev->dev_addr);
+
+       return 0;
+}
+
 static int rtl8169_ioctl(struct net_device *dev, struct ifreq *ifr, int cmd)
 {
        struct rtl8169_private *tp = netdev_priv(dev);
@@ -1494,7 +1458,7 @@ static const struct rtl_cfg_info {
        [RTL_CFG_0] = {
                .hw_start       = rtl_hw_start_8169,
                .region         = 1,
-               .align          = 2,
+               .align          = 0,
                .intr_event     = SYSErr | LinkChg | RxOverflow |
                                  RxFIFOOver | TxErr | TxOK | RxOK | RxErr,
                .napi_event     = RxFIFOOver | TxErr | TxOK | RxOK | RxOverflow
@@ -1525,8 +1489,8 @@ rtl8169_init_one(struct pci_dev *pdev, const struct pci_device_id *ent)
        struct rtl8169_private *tp;
        struct net_device *dev;
        void __iomem *ioaddr;
-       unsigned int pm_cap;
-       int i, rc;
+       unsigned int i;
+       int rc;
 
        if (netif_msg_drv(&debug)) {
                printk(KERN_INFO "%s Gigabit Ethernet driver %s loaded\n",
@@ -1559,20 +1523,6 @@ rtl8169_init_one(struct pci_dev *pdev, const struct pci_device_id *ent)
        if (rc < 0)
                goto err_out_disable_2;
 
-       /* save power state before pci_enable_device overwrites it */
-       pm_cap = pci_find_capability(pdev, PCI_CAP_ID_PM);
-       if (pm_cap) {
-               u16 pwr_command, acpi_idle_state;
-
-               pci_read_config_word(pdev, pm_cap + PCI_PM_CTRL, &pwr_command);
-               acpi_idle_state = pwr_command & PCI_PM_CTRL_STATE_MASK;
-       } else {
-               if (netif_msg_probe(tp)) {
-                       dev_err(&pdev->dev,
-                               "PowerManagement capability not found.\n");
-               }
-       }
-
        /* make sure PCI base addr 1 is MMIO */
        if (!(pci_resource_flags(pdev, region) & IORESOURCE_MEM)) {
                if (netif_msg_probe(tp)) {
@@ -1636,7 +1586,7 @@ rtl8169_init_one(struct pci_dev *pdev, const struct pci_device_id *ent)
        RTL_W8(ChipCmd, CmdReset);
 
        /* Check that the chip has finished the reset. */
-       for (i = 100; i > 0; i--) {
+       for (i = 0; i < 100; i++) {
                if ((RTL_R8(ChipCmd) & CmdReset) == 0)
                        break;
                msleep_interruptible(1);
@@ -1703,6 +1653,7 @@ rtl8169_init_one(struct pci_dev *pdev, const struct pci_device_id *ent)
        dev->irq = pdev->irq;
        dev->base_addr = (unsigned long) ioaddr;
        dev->change_mtu = rtl8169_change_mtu;
+       dev->set_mac_address = rtl_set_mac_address;
 
 #ifdef CONFIG_R8169_NAPI
        dev->poll = rtl8169_poll;
@@ -1739,15 +1690,17 @@ rtl8169_init_one(struct pci_dev *pdev, const struct pci_device_id *ent)
        pci_set_drvdata(pdev, dev);
 
        if (netif_msg_probe(tp)) {
+               u32 xid = RTL_R32(TxConfig) & 0x7cf0f8ff;
+
                printk(KERN_INFO "%s: %s at 0x%lx, "
                       "%2.2x:%2.2x:%2.2x:%2.2x:%2.2x:%2.2x, "
-                      "IRQ %d\n",
+                      "XID %08x IRQ %d\n",
                       dev->name,
                       rtl_chip_info[tp->chipset].name,
                       dev->base_addr,
                       dev->dev_addr[0], dev->dev_addr[1],
                       dev->dev_addr[2], dev->dev_addr[3],
-                      dev->dev_addr[4], dev->dev_addr[5], dev->irq);
+                      dev->dev_addr[4], dev->dev_addr[5], xid, dev->irq);
        }
 
        rtl8169_init_phy(dev, tp);
@@ -1768,15 +1721,11 @@ err_out_free_dev_1:
        goto out;
 }
 
-static void __devexit
-rtl8169_remove_one(struct pci_dev *pdev)
+static void __devexit rtl8169_remove_one(struct pci_dev *pdev)
 {
        struct net_device *dev = pci_get_drvdata(pdev);
        struct rtl8169_private *tp = netdev_priv(dev);
 
-       assert(dev != NULL);
-       assert(tp != NULL);
-
        flush_scheduled_work();
 
        unregister_netdev(dev);
@@ -1876,13 +1825,13 @@ static void rtl_hw_start(struct net_device *dev)
 {
        struct rtl8169_private *tp = netdev_priv(dev);
        void __iomem *ioaddr = tp->mmio_addr;
-       u32 i;
+       unsigned int i;
 
        /* Soft reset the chip. */
        RTL_W8(ChipCmd, CmdReset);
 
        /* Check that the chip has finished the reset. */
-       for (i = 100; i > 0; i--) {
+       for (i = 0; i < 100; i++) {
                if ((RTL_R8(ChipCmd) & CmdReset) == 0)
                        break;
                msleep_interruptible(1);
@@ -2173,12 +2122,15 @@ static struct sk_buff *rtl8169_alloc_rx_skb(struct pci_dev *pdev,
 {
        struct sk_buff *skb;
        dma_addr_t mapping;
+       unsigned int pad;
+
+       pad = align ? align : NET_IP_ALIGN;
 
-       skb = netdev_alloc_skb(dev, rx_buf_sz + align);
+       skb = netdev_alloc_skb(dev, rx_buf_sz + pad);
        if (!skb)
                goto err_out;
 
-       skb_reserve(skb, (align - 1) & (unsigned long)skb->data);
+       skb_reserve(skb, align ? ((pad - 1) & (unsigned long)skb->data) : pad);
 
        mapping = pci_map_single(pdev, skb->data, rx_buf_sz,
                                 PCI_DMA_FROMDEVICE);
@@ -2194,7 +2146,7 @@ err_out:
 
 static void rtl8169_rx_clear(struct rtl8169_private *tp)
 {
-       int i;
+       unsigned int i;
 
        for (i = 0; i < NUM_RX_DESC; i++) {
                if (tp->Rx_skbuff[i]) {
@@ -2336,14 +2288,9 @@ static void rtl8169_reinit_task(struct work_struct *work)
 
        ret = rtl8169_open(dev);
        if (unlikely(ret < 0)) {
-               if (net_ratelimit()) {
-                       struct rtl8169_private *tp = netdev_priv(dev);
-
-                       if (netif_msg_drv(tp)) {
-                               printk(PFX KERN_ERR
-                                      "%s: reinit failure (status = %d)."
-                                      " Rescheduling.\n", dev->name, ret);
-                       }
+               if (net_ratelimit() && netif_msg_drv(tp)) {
+                       printk(PFX KERN_ERR "%s: reinit failure (status = %d)."
+                              " Rescheduling.\n", dev->name, ret);
                }
                rtl8169_schedule_work(dev, rtl8169_reinit_task);
        }
@@ -2373,13 +2320,9 @@ static void rtl8169_reset_task(struct work_struct *work)
                rtl_hw_start(dev);
                netif_wake_queue(dev);
        } else {
-               if (net_ratelimit()) {
-                       struct rtl8169_private *tp = netdev_priv(dev);
-
-                       if (netif_msg_intr(tp)) {
-                               printk(PFX KERN_EMERG
-                                      "%s: Rx buffers shortage\n", dev->name);
-                       }
+               if (net_ratelimit() && netif_msg_intr(tp)) {
+                       printk(PFX KERN_EMERG "%s: Rx buffers shortage\n",
+                              dev->name);
                }
                rtl8169_schedule_work(dev, rtl8169_reset_task);
        }
@@ -2403,7 +2346,7 @@ static int rtl8169_xmit_frags(struct rtl8169_private *tp, struct sk_buff *skb,
 {
        struct skb_shared_info *info = skb_shinfo(skb);
        unsigned int cur_frag, entry;
-       struct TxDesc *txd;
+       struct TxDesc * uninitialized_var(txd);
 
        entry = tp->cur_tx;
        for (cur_frag = 0; cur_frag < info->nr_frags; cur_frag++) {
@@ -2516,7 +2459,7 @@ static int rtl8169_start_xmit(struct sk_buff *skb, struct net_device *dev)
 
        smp_wmb();
 
-       RTL_W8(TxPoll, 0x40);   /* set polling bit */
+       RTL_W8(TxPoll, NPQ);    /* set polling bit */
 
        if (TX_BUFFS_AVAIL(tp) < MAX_SKB_FRAGS) {
                netif_stop_queue(dev);
@@ -2586,16 +2529,12 @@ static void rtl8169_pcierr_interrupt(struct net_device *dev)
        rtl8169_schedule_work(dev, rtl8169_reinit_task);
 }
 
-static void
-rtl8169_tx_interrupt(struct net_device *dev, struct rtl8169_private *tp,
-                    void __iomem *ioaddr)
+static void rtl8169_tx_interrupt(struct net_device *dev,
+                                struct rtl8169_private *tp,
+                                void __iomem *ioaddr)
 {
        unsigned int dirty_tx, tx_left;
 
-       assert(dev != NULL);
-       assert(tp != NULL);
-       assert(ioaddr != NULL);
-
        dirty_tx = tp->dirty_tx;
        smp_rmb();
        tx_left = tp->cur_tx - dirty_tx;
@@ -2631,6 +2570,15 @@ rtl8169_tx_interrupt(struct net_device *dev, struct rtl8169_private *tp,
                    (TX_BUFFS_AVAIL(tp) >= MAX_SKB_FRAGS)) {
                        netif_wake_queue(dev);
                }
+               /*
+                * 8168 hack: TxPoll requests are lost when the Tx packets are
+                * too close. Let's kick an extra TxPoll request when a burst
+                * of start_xmit activity is detected (if it is not detected,
+                * it is slow enough). -- FR
+                */
+               smp_rmb();
+               if (tp->cur_tx != dirty_tx)
+                       RTL_W8(TxPoll, NPQ);
        }
 }
 
@@ -2652,8 +2600,9 @@ static inline void rtl8169_rx_csum(struct sk_buff *skb, struct RxDesc *desc)
                skb->ip_summed = CHECKSUM_NONE;
 }
 
-static inline bool rtl8169_try_rx_copy(struct sk_buff **sk_buff, int pkt_size,
-                                      struct pci_dev *pdev, dma_addr_t addr)
+static inline bool rtl8169_try_rx_copy(struct sk_buff **sk_buff,
+                                      struct rtl8169_private *tp, int pkt_size,
+                                      dma_addr_t addr)
 {
        struct sk_buff *skb;
        bool done = false;
@@ -2661,11 +2610,12 @@ static inline bool rtl8169_try_rx_copy(struct sk_buff **sk_buff, int pkt_size,
        if (pkt_size >= rx_copybreak)
                goto out;
 
-       skb = dev_alloc_skb(pkt_size + NET_IP_ALIGN);
+       skb = netdev_alloc_skb(tp->dev, pkt_size + NET_IP_ALIGN);
        if (!skb)
                goto out;
 
-       pci_dma_sync_single_for_cpu(pdev, addr, pkt_size, PCI_DMA_FROMDEVICE);
+       pci_dma_sync_single_for_cpu(tp->pci_dev, addr, pkt_size,
+                                   PCI_DMA_FROMDEVICE);
        skb_reserve(skb, NET_IP_ALIGN);
        skb_copy_from_linear_data(*sk_buff, skb->data, pkt_size);
        *sk_buff = skb;
@@ -2674,17 +2624,13 @@ out:
        return done;
 }
 
-static int
-rtl8169_rx_interrupt(struct net_device *dev, struct rtl8169_private *tp,
-                    void __iomem *ioaddr)
+static int rtl8169_rx_interrupt(struct net_device *dev,
+                               struct rtl8169_private *tp,
+                               void __iomem *ioaddr)
 {
        unsigned int cur_rx, rx_left;
        unsigned int delta, count;
 
-       assert(dev != NULL);
-       assert(tp != NULL);
-       assert(ioaddr != NULL);
-
        cur_rx = tp->cur_rx;
        rx_left = NUM_RX_DESC + tp->dirty_rx - cur_rx;
        rx_left = rtl8169_rx_quota(rx_left, (u32) dev->quota);
@@ -2735,7 +2681,7 @@ rtl8169_rx_interrupt(struct net_device *dev, struct rtl8169_private *tp,
 
                        rtl8169_rx_csum(skb, desc);
 
-                       if (rtl8169_try_rx_copy(&skb, pkt_size, pdev, addr)) {
+                       if (rtl8169_try_rx_copy(&skb, tp, pkt_size, addr)) {
                                pci_dma_sync_single_for_device(pdev, addr,
                                        pkt_size, PCI_DMA_FROMDEVICE);
                                rtl8169_mark_to_asic(desc, tp->rx_buf_sz);
@@ -2785,11 +2731,9 @@ rtl8169_rx_interrupt(struct net_device *dev, struct rtl8169_private *tp,
        return count;
 }
 
-/* The interrupt handler does all of the Rx thread work and cleans up after the Tx thread. */
-static irqreturn_t
-rtl8169_interrupt(int irq, void *dev_instance)
+static irqreturn_t rtl8169_interrupt(int irq, void *dev_instance)
 {
-       struct net_device *dev = (struct net_device *) dev_instance;
+       struct net_device *dev = dev_instance;
        struct rtl8169_private *tp = netdev_priv(dev);
        int boguscnt = max_interrupt_work;
        void __iomem *ioaddr = tp->mmio_addr;
@@ -2834,21 +2778,23 @@ rtl8169_interrupt(int irq, void *dev_instance)
                        rtl8169_check_link_status(dev, tp, ioaddr);
 
 #ifdef CONFIG_R8169_NAPI
-               RTL_W16(IntrMask, tp->intr_event & ~tp->napi_event);
-               tp->intr_mask = ~tp->napi_event;
-
-               if (likely(netif_rx_schedule_prep(dev)))
-                       __netif_rx_schedule(dev);
-               else if (netif_msg_intr(tp)) {
-                       printk(KERN_INFO "%s: interrupt %04x taken in poll\n",
-                              dev->name, status);
+               if (status & tp->napi_event) {
+                       RTL_W16(IntrMask, tp->intr_event & ~tp->napi_event);
+                       tp->intr_mask = ~tp->napi_event;
+
+                       if (likely(netif_rx_schedule_prep(dev)))
+                               __netif_rx_schedule(dev);
+                       else if (netif_msg_intr(tp)) {
+                               printk(KERN_INFO "%s: interrupt %04x in poll\n",
+                                      dev->name, status);
+                       }
                }
                break;
 #else
                /* Rx interrupt */
-               if (status & (RxOK | RxOverflow | RxFIFOOver)) {
+               if (status & (RxOK | RxOverflow | RxFIFOOver))
                        rtl8169_rx_interrupt(dev, tp, ioaddr);
-               }
+
                /* Tx interrupt */
                if (status & (TxOK | TxErr))
                        rtl8169_tx_interrupt(dev, tp, ioaddr);
@@ -2980,7 +2926,7 @@ static void rtl_set_rx_mode(struct net_device *dev)
        void __iomem *ioaddr = tp->mmio_addr;
        unsigned long flags;
        u32 mc_filter[2];       /* Multicast hash filter */
-       int i, rx_mode;
+       int rx_mode;
        u32 tmp = 0;
 
        if (dev->flags & IFF_PROMISC) {
@@ -3000,6 +2946,8 @@ static void rtl_set_rx_mode(struct net_device *dev)
                mc_filter[1] = mc_filter[0] = 0xffffffff;
        } else {
                struct dev_mc_list *mclist;
+               unsigned int i;
+
                rx_mode = AcceptBroadcast | AcceptMyPhys;
                mc_filter[1] = mc_filter[0] = 0;
                for (i = 0, mclist = dev->mc_list; mclist && i < dev->mc_count;
@@ -3024,10 +2972,11 @@ static void rtl_set_rx_mode(struct net_device *dev)
                mc_filter[1] = 0xffffffff;
        }
 
-       RTL_W32(RxConfig, tmp);
        RTL_W32(MAR0 + 0, mc_filter[0]);
        RTL_W32(MAR0 + 4, mc_filter[1]);
 
+       RTL_W32(RxConfig, tmp);
+
        spin_unlock_irqrestore(&tp->lock, flags);
 }
 
@@ -3115,14 +3064,12 @@ static struct pci_driver rtl8169_pci_driver = {
 #endif
 };
 
-static int __init
-rtl8169_init_module(void)
+static int __init rtl8169_init_module(void)
 {
        return pci_register_driver(&rtl8169_pci_driver);
 }
 
-static void __exit
-rtl8169_cleanup_module(void)
+static void __exit rtl8169_cleanup_module(void)
 {
        pci_unregister_driver(&rtl8169_pci_driver);
 }