Author: waldi
Date: Wed Sep 27 14:07:20 2006
New Revision: 7541

Added:
   dists/trunk/linux-2.6/debian/patches/features/all/drivers/net-r8169-1.patch  
 (contents, props changed)
Modified:
   dists/trunk/linux-2.6/debian/patches/series/2

Log:
* debian/patches/features/all/drivers/net-r8169-1.patch: Add.
* debian/patches/series/2: Add features/all/drivers/net-r8169-1.patch.


Added: 
dists/trunk/linux-2.6/debian/patches/features/all/drivers/net-r8169-1.patch
==============================================================================
--- (empty file)
+++ dists/trunk/linux-2.6/debian/patches/features/all/drivers/net-r8169-1.patch 
Wed Sep 27 14:07:20 2006
@@ -0,0 +1,1208 @@
+diff --git a/drivers/net/r8169.c b/drivers/net/r8169.c
+index 5722a56..ebb948b 100644
+--- a/drivers/net/r8169.c
++++ b/drivers/net/r8169.c
+@@ -6,26 +6,26 @@
+  History:
+  Feb  4 2002  - created initially by ShuChen <[EMAIL PROTECTED]>.
+  May 20 2002  - Add link status force-mode and TBI mode support.
+-        2004  - Massive updates. See kernel SCM system for details.
++      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). 
++      exchanging Link Code Word (FLP).
+ 
+ VERSION 1.2   <2002/11/30>
+ 
+@@ -81,10 +81,10 @@ #define PFX MODULENAME ": "
+ 
+ #ifdef RTL8169_DEBUG
+ #define assert(expr) \
+-        if(!(expr)) {                                 \
+-              printk( "Assertion failed! %s,%s,%s,line=%d\n", \
+-              #expr,__FILE__,__FUNCTION__,__LINE__);          \
+-        }
++      if (!(expr)) {                                  \
++              printk( "Assertion failed! %s,%s,%s,line=%d\n", \
++              #expr,__FILE__,__FUNCTION__,__LINE__);          \
++      }
+ #define dprintk(fmt, args...) do { printk(PFX fmt, ## args); } while (0)
+ #else
+ #define assert(expr) do {} while (0)
+@@ -150,11 +150,16 @@ #define RTL_R16(reg)             readw (ioaddr + (r
+ #define RTL_R32(reg)          ((unsigned long) readl (ioaddr + (reg)))
+ 
+ enum mac_version {
+-      RTL_GIGA_MAC_VER_B = 0x00,
+-      /* RTL_GIGA_MAC_VER_C = 0x03, */
+-      RTL_GIGA_MAC_VER_D = 0x01,
+-      RTL_GIGA_MAC_VER_E = 0x02,
+-      RTL_GIGA_MAC_VER_X = 0x04       /* Greater than RTL_GIGA_MAC_VER_E */
++      RTL_GIGA_MAC_VER_01 = 0x00,
++      RTL_GIGA_MAC_VER_02 = 0x01,
++      RTL_GIGA_MAC_VER_03 = 0x02,
++      RTL_GIGA_MAC_VER_04 = 0x03,
++      RTL_GIGA_MAC_VER_05 = 0x04,
++      RTL_GIGA_MAC_VER_11 = 0x0b,
++      RTL_GIGA_MAC_VER_12 = 0x0c,
++      RTL_GIGA_MAC_VER_13 = 0x0d,
++      RTL_GIGA_MAC_VER_14 = 0x0e,
++      RTL_GIGA_MAC_VER_15 = 0x0f
+ };
+ 
+ enum phy_version {
+@@ -166,7 +171,6 @@ enum phy_version {
+       RTL_GIGA_PHY_VER_H = 0x08, /* PHY Reg 0x03 bit0-3 == 0x0003 */
+ };
+ 
+-
+ #define _R(NAME,MAC,MASK) \
+       { .name = NAME, .mac_version = MAC, .RxConfigMask = MASK }
+ 
+@@ -175,19 +179,44 @@ static const struct {
+       u8 mac_version;
+       u32 RxConfigMask;       /* Clears the bits supported by this chip */
+ } rtl_chip_info[] = {
+-      _R("RTL8169",           RTL_GIGA_MAC_VER_B, 0xff7e1880),
+-      _R("RTL8169s/8110s",    RTL_GIGA_MAC_VER_D, 0xff7e1880),
+-      _R("RTL8169s/8110s",    RTL_GIGA_MAC_VER_E, 0xff7e1880),
+-      _R("RTL8169s/8110s",    RTL_GIGA_MAC_VER_X, 0xff7e1880),
++      _R("RTL8169",           RTL_GIGA_MAC_VER_01, 0xff7e1880),
++      _R("RTL8169s/8110s",    RTL_GIGA_MAC_VER_02, 0xff7e1880),
++      _R("RTL8169s/8110s",    RTL_GIGA_MAC_VER_03, 0xff7e1880),
++      _R("RTL8169sb/8110sb",  RTL_GIGA_MAC_VER_04, 0xff7e1880),
++      _R("RTL8169sc/8110sc",  RTL_GIGA_MAC_VER_05, 0xff7e1880),
++      _R("RTL8168b/8111b",    RTL_GIGA_MAC_VER_11, 0xff7e1880), // PCI-E
++      _R("RTL8168b/8111b",    RTL_GIGA_MAC_VER_12, 0xff7e1880), // PCI-E
++      _R("RTL8101e",          RTL_GIGA_MAC_VER_13, 0xff7e1880), // PCI-E 8139
++      _R("RTL8100e",          RTL_GIGA_MAC_VER_14, 0xff7e1880), // PCI-E 8139
++      _R("RTL8100e",          RTL_GIGA_MAC_VER_15, 0xff7e1880)  // PCI-E 8139
+ };
+ #undef _R
+ 
++enum cfg_version {
++      RTL_CFG_0 = 0x00,
++      RTL_CFG_1,
++      RTL_CFG_2
++};
++
++static const struct {
++      unsigned int region;
++      unsigned int align;
++} rtl_cfg_info[] = {
++      [RTL_CFG_0] = { 1, NET_IP_ALIGN },
++      [RTL_CFG_1] = { 2, NET_IP_ALIGN },
++      [RTL_CFG_2] = { 2, 8 }
++};
++
+ static struct pci_device_id rtl8169_pci_tbl[] = {
+-      { PCI_DEVICE(PCI_VENDOR_ID_REALTEK,     0x8169), },
+-      { PCI_DEVICE(PCI_VENDOR_ID_REALTEK,     0x8129), },
+-      { PCI_DEVICE(PCI_VENDOR_ID_DLINK,       0x4300), },
+-      { PCI_DEVICE(0x16ec,                    0x0116), },
+-      { PCI_VENDOR_ID_LINKSYS,                0x1032, PCI_ANY_ID, 0x0024, },
++      { PCI_DEVICE(PCI_VENDOR_ID_REALTEK,     0x8129), 0, 0, RTL_CFG_0 },
++      { PCI_DEVICE(PCI_VENDOR_ID_REALTEK,     0x8136), 0, 0, RTL_CFG_2 },
++      { PCI_DEVICE(PCI_VENDOR_ID_REALTEK,     0x8167), 0, 0, RTL_CFG_1 },
++      { PCI_DEVICE(PCI_VENDOR_ID_REALTEK,     0x8168), 0, 0, RTL_CFG_2 },
++      { PCI_DEVICE(PCI_VENDOR_ID_REALTEK,     0x8169), 0, 0, RTL_CFG_0 },
++      { PCI_DEVICE(PCI_VENDOR_ID_DLINK,       0x4300), 0, 0, RTL_CFG_0 },
++      { PCI_DEVICE(0x16ec,                    0x0116), 0, 0, RTL_CFG_0 },
++      { PCI_VENDOR_ID_LINKSYS,                0x1032,
++              PCI_ANY_ID, 0x0024, 0, 0, RTL_CFG_0 },
+       {0,},
+ };
+ 
+@@ -257,10 +286,11 @@ enum RTL8169_register_content {
+       RxOK = 0x01,
+ 
+       /* RxStatusDesc */
+-      RxRES = 0x00200000,
+-      RxCRC = 0x00080000,
+-      RxRUNT = 0x00100000,
+-      RxRWT = 0x00400000,
++      RxFOVF  = (1 << 23),
++      RxRWT   = (1 << 22),
++      RxRES   = (1 << 21),
++      RxRUNT  = (1 << 20),
++      RxCRC   = (1 << 19),
+ 
+       /* ChipCmdBits */
+       CmdReset = 0x10,
+@@ -326,30 +356,6 @@ enum RTL8169_register_content {
+       LinkStatus = 0x02,
+       FullDup = 0x01,
+ 
+-      /* GIGABIT_PHY_registers */
+-      PHY_CTRL_REG = 0,
+-      PHY_STAT_REG = 1,
+-      PHY_AUTO_NEGO_REG = 4,
+-      PHY_1000_CTRL_REG = 9,
+-
+-      /* GIGABIT_PHY_REG_BIT */
+-      PHY_Restart_Auto_Nego = 0x0200,
+-      PHY_Enable_Auto_Nego = 0x1000,
+-
+-      /* PHY_STAT_REG = 1 */
+-      PHY_Auto_Neco_Comp = 0x0020,
+-
+-      /* PHY_AUTO_NEGO_REG = 4 */
+-      PHY_Cap_10_Half = 0x0020,
+-      PHY_Cap_10_Full = 0x0040,
+-      PHY_Cap_100_Half = 0x0080,
+-      PHY_Cap_100_Full = 0x0100,
+-
+-      /* PHY_1000_CTRL_REG = 9 */
+-      PHY_Cap_1000_Full = 0x0200,
+-
+-      PHY_Cap_Null = 0x0,
+-
+       /* _MediaType */
+       _10_Half = 0x01,
+       _10_Full = 0x02,
+@@ -433,6 +439,7 @@ struct rtl8169_private {
+       dma_addr_t RxPhyAddr;
+       struct sk_buff *Rx_skbuff[NUM_RX_DESC]; /* Rx data buffers */
+       struct ring_info tx_skb[NUM_TX_DESC];   /* Tx data buffers */
++      unsigned align;
+       unsigned rx_buf_sz;
+       struct timer_list timer;
+       u16 cp_cmd;
+@@ -488,12 +495,7 @@ static const u16 rtl8169_intr_mask =
+ static const u16 rtl8169_napi_event =
+       RxOK | RxOverflow | RxFIFOOver | TxOK | TxErr;
+ static const unsigned int rtl8169_rx_config =
+-    (RX_FIFO_THRESH << RxCfgFIFOShift) | (RX_DMA_BURST << RxCfgDMAShift);
+-
+-#define PHY_Cap_10_Half_Or_Less PHY_Cap_10_Half
+-#define PHY_Cap_10_Full_Or_Less PHY_Cap_10_Full | PHY_Cap_10_Half_Or_Less
+-#define PHY_Cap_100_Half_Or_Less PHY_Cap_100_Half | PHY_Cap_10_Full_Or_Less
+-#define PHY_Cap_100_Full_Or_Less PHY_Cap_100_Full | PHY_Cap_100_Half_Or_Less
++      (RX_FIFO_THRESH << RxCfgFIFOShift) | (RX_DMA_BURST << RxCfgDMAShift);
+ 
+ static void mdio_write(void __iomem *ioaddr, int RegAddr, int value)
+ {
+@@ -503,7 +505,7 @@ static void mdio_write(void __iomem *ioa
+ 
+       for (i = 20; i > 0; i--) {
+               /* Check if the RTL8169 has completed writing to the specified 
MII register */
+-              if (!(RTL_R32(PHYAR) & 0x80000000)) 
++              if (!(RTL_R32(PHYAR) & 0x80000000))
+                       break;
+               udelay(25);
+       }
+@@ -547,7 +549,7 @@ static unsigned int rtl8169_tbi_reset_pe
+ 
+ static unsigned int rtl8169_xmii_reset_pending(void __iomem *ioaddr)
+ {
+-      return mdio_read(ioaddr, 0) & 0x8000;
++      return mdio_read(ioaddr, MII_BMCR) & BMCR_RESET;
+ }
+ 
+ static unsigned int rtl8169_tbi_link_ok(void __iomem *ioaddr)
+@@ -569,8 +571,8 @@ static void rtl8169_xmii_reset_enable(vo
+ {
+       unsigned int val;
+ 
+-      val = (mdio_read(ioaddr, PHY_CTRL_REG) | 0x8000) & 0xffff;
+-      mdio_write(ioaddr, PHY_CTRL_REG, val);
++      val = (mdio_read(ioaddr, MII_BMCR) | BMCR_RESET) & 0xffff;
++      mdio_write(ioaddr, MII_BMCR, val);
+ }
+ 
+ static void rtl8169_check_link_status(struct net_device *dev,
+@@ -608,7 +610,7 @@ static void rtl8169_link_option(int idx,
+               { 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))
+@@ -650,9 +652,9 @@ #define WAKE_ANY (WAKE_PHY | WAKE_MAGIC 
+       if (options & UWF)
+               wol->wolopts |= WAKE_UCAST;
+       if (options & BWF)
+-              wol->wolopts |= WAKE_BCAST;
++              wol->wolopts |= WAKE_BCAST;
+       if (options & MWF)
+-              wol->wolopts |= WAKE_MCAST;
++              wol->wolopts |= WAKE_MCAST;
+ 
+ out_unlock:
+       spin_unlock_irq(&tp->lock);
+@@ -745,38 +747,57 @@ static int rtl8169_set_speed_xmii(struct
+       void __iomem *ioaddr = tp->mmio_addr;
+       int auto_nego, giga_ctrl;
+ 
+-      auto_nego = mdio_read(ioaddr, PHY_AUTO_NEGO_REG);
+-      auto_nego &= ~(PHY_Cap_10_Half | PHY_Cap_10_Full |
+-                     PHY_Cap_100_Half | PHY_Cap_100_Full);
+-      giga_ctrl = mdio_read(ioaddr, PHY_1000_CTRL_REG);
+-      giga_ctrl &= ~(PHY_Cap_1000_Full | PHY_Cap_Null);
++      auto_nego = mdio_read(ioaddr, MII_ADVERTISE);
++      auto_nego &= ~(ADVERTISE_10HALF | ADVERTISE_10FULL |
++                     ADVERTISE_100HALF | ADVERTISE_100FULL);
++      giga_ctrl = mdio_read(ioaddr, MII_CTRL1000);
++      giga_ctrl &= ~(ADVERTISE_1000FULL | ADVERTISE_1000HALF);
+ 
+       if (autoneg == AUTONEG_ENABLE) {
+-              auto_nego |= (PHY_Cap_10_Half | PHY_Cap_10_Full |
+-                            PHY_Cap_100_Half | PHY_Cap_100_Full);
+-              giga_ctrl |= PHY_Cap_1000_Full;
++              auto_nego |= (ADVERTISE_10HALF | ADVERTISE_10FULL |
++                            ADVERTISE_100HALF | ADVERTISE_100FULL);
++              giga_ctrl |= ADVERTISE_1000FULL | ADVERTISE_1000HALF;
+       } else {
+               if (speed == SPEED_10)
+-                      auto_nego |= PHY_Cap_10_Half | PHY_Cap_10_Full;
++                      auto_nego |= ADVERTISE_10HALF | ADVERTISE_10FULL;
+               else if (speed == SPEED_100)
+-                      auto_nego |= PHY_Cap_100_Half | PHY_Cap_100_Full;
++                      auto_nego |= ADVERTISE_100HALF | ADVERTISE_100FULL;
+               else if (speed == SPEED_1000)
+-                      giga_ctrl |= PHY_Cap_1000_Full;
++                      giga_ctrl |= ADVERTISE_1000FULL | ADVERTISE_1000HALF;
+ 
+               if (duplex == DUPLEX_HALF)
+-                      auto_nego &= ~(PHY_Cap_10_Full | PHY_Cap_100_Full);
++                      auto_nego &= ~(ADVERTISE_10FULL | ADVERTISE_100FULL);
+ 
+               if (duplex == DUPLEX_FULL)
+-                      auto_nego &= ~(PHY_Cap_10_Half | PHY_Cap_100_Half);
++                      auto_nego &= ~(ADVERTISE_10HALF | ADVERTISE_100HALF);
++
++              /* This tweak comes straight from Realtek's driver. */
++              if ((speed == SPEED_100) && (duplex == DUPLEX_HALF) &&
++                  (tp->mac_version == RTL_GIGA_MAC_VER_13)) {
++                      auto_nego = ADVERTISE_100HALF | ADVERTISE_CSMA;
++              }
++      }
++
++      /* The 8100e/8101e do Fast Ethernet only. */
++      if ((tp->mac_version == RTL_GIGA_MAC_VER_13) ||
++          (tp->mac_version == RTL_GIGA_MAC_VER_14) ||
++          (tp->mac_version == RTL_GIGA_MAC_VER_15)) {
++              if ((giga_ctrl & (ADVERTISE_1000FULL | ADVERTISE_1000HALF)) &&
++                  netif_msg_link(tp)) {
++                      printk(KERN_INFO "%s: PHY does not support 1000Mbps.\n",
++                             dev->name);
++              }
++              giga_ctrl &= ~(ADVERTISE_1000FULL | ADVERTISE_1000HALF);
+       }
+ 
++      auto_nego |= ADVERTISE_PAUSE_CAP | ADVERTISE_PAUSE_ASYM;
++
+       tp->phy_auto_nego_reg = auto_nego;
+       tp->phy_1000_ctrl_reg = giga_ctrl;
+ 
+-      mdio_write(ioaddr, PHY_AUTO_NEGO_REG, auto_nego);
+-      mdio_write(ioaddr, PHY_1000_CTRL_REG, giga_ctrl);
+-      mdio_write(ioaddr, PHY_CTRL_REG, PHY_Enable_Auto_Nego |
+-                                       PHY_Restart_Auto_Nego);
++      mdio_write(ioaddr, MII_ADVERTISE, auto_nego);
++      mdio_write(ioaddr, MII_CTRL1000, giga_ctrl);
++      mdio_write(ioaddr, MII_BMCR, BMCR_ANENABLE | BMCR_ANRESTART);
+       return 0;
+ }
+ 
+@@ -788,7 +809,7 @@ static int rtl8169_set_speed(struct net_
+ 
+       ret = tp->set_speed(dev, autoneg, speed, duplex);
+ 
+-      if (netif_running(dev) && (tp->phy_1000_ctrl_reg & PHY_Cap_1000_Full))
++      if (netif_running(dev) && (tp->phy_1000_ctrl_reg & ADVERTISE_1000FULL))
+               mod_timer(&tp->timer, jiffies + RTL8169_PHY_TIMEOUT);
+ 
+       return ret;
+@@ -803,7 +824,7 @@ static int rtl8169_set_settings(struct n
+       spin_lock_irqsave(&tp->lock, flags);
+       ret = rtl8169_set_speed(dev, cmd->autoneg, cmd->speed, cmd->duplex);
+       spin_unlock_irqrestore(&tp->lock, flags);
+-      
++
+       return ret;
+ }
+ 
+@@ -936,20 +957,20 @@ static void rtl8169_gset_xmii(struct net
+                        SUPPORTED_100baseT_Full |
+                        SUPPORTED_1000baseT_Full |
+                        SUPPORTED_Autoneg |
+-                       SUPPORTED_TP;
++                       SUPPORTED_TP;
+ 
+       cmd->autoneg = 1;
+       cmd->advertising = ADVERTISED_TP | ADVERTISED_Autoneg;
+ 
+-      if (tp->phy_auto_nego_reg & PHY_Cap_10_Half)
++      if (tp->phy_auto_nego_reg & ADVERTISE_10HALF)
+               cmd->advertising |= ADVERTISED_10baseT_Half;
+-      if (tp->phy_auto_nego_reg & PHY_Cap_10_Full)
++      if (tp->phy_auto_nego_reg & ADVERTISE_10FULL)
+               cmd->advertising |= ADVERTISED_10baseT_Full;
+-      if (tp->phy_auto_nego_reg & PHY_Cap_100_Half)
++      if (tp->phy_auto_nego_reg & ADVERTISE_100HALF)
+               cmd->advertising |= ADVERTISED_100baseT_Half;
+-      if (tp->phy_auto_nego_reg & PHY_Cap_100_Full)
++      if (tp->phy_auto_nego_reg & ADVERTISE_100FULL)
+               cmd->advertising |= ADVERTISED_100baseT_Full;
+-      if (tp->phy_1000_ctrl_reg & PHY_Cap_1000_Full)
++      if (tp->phy_1000_ctrl_reg & ADVERTISE_1000FULL)
+               cmd->advertising |= ADVERTISED_1000baseT_Full;
+ 
+       status = RTL_R8(PHYstatus);
+@@ -961,6 +982,11 @@ static void rtl8169_gset_xmii(struct net
+       else if (status & _10bps)
+               cmd->speed = SPEED_10;
+ 
++      if (status & TxFlowCtrl)
++              cmd->advertising |= ADVERTISED_Asym_Pause;
++      if (status & RxFlowCtrl)
++              cmd->advertising |= ADVERTISED_Pause;
++
+       cmd->duplex = ((status & _1000bpsF) || (status & FullDup)) ?
+                     DUPLEX_FULL : DUPLEX_HALF;
+ }
+@@ -981,15 +1007,15 @@ static int rtl8169_get_settings(struct n
+ static void rtl8169_get_regs(struct net_device *dev, struct ethtool_regs 
*regs,
+                            void *p)
+ {
+-        struct rtl8169_private *tp = netdev_priv(dev);
+-        unsigned long flags;
++      struct rtl8169_private *tp = netdev_priv(dev);
++      unsigned long flags;
+ 
+-        if (regs->len > R8169_REGS_SIZE)
+-              regs->len = R8169_REGS_SIZE;
++      if (regs->len > R8169_REGS_SIZE)
++              regs->len = R8169_REGS_SIZE;
+ 
+-        spin_lock_irqsave(&tp->lock, flags);
+-        memcpy_fromio(p, tp->mmio_addr, regs->len);
+-        spin_unlock_irqrestore(&tp->lock, flags);
++      spin_lock_irqsave(&tp->lock, flags);
++      memcpy_fromio(p, tp->mmio_addr, regs->len);
++      spin_unlock_irqrestore(&tp->lock, flags);
+ }
+ 
+ static u32 rtl8169_get_msglevel(struct net_device *dev)
+@@ -1071,7 +1097,7 @@ static void rtl8169_get_ethtool_stats(st
+       RTL_W32(CounterAddrLow, 0);
+       RTL_W32(CounterAddrHigh, 0);
+ 
+-      data[0] = le64_to_cpu(counters->tx_packets);
++      data[0] = le64_to_cpu(counters->tx_packets);
+       data[1] = le64_to_cpu(counters->rx_packets);
+       data[2] = le64_to_cpu(counters->tx_errors);
+       data[3] = le32_to_cpu(counters->rx_errors);
+@@ -1131,7 +1157,7 @@ static void rtl8169_write_gmii_reg_bit(v
+       val = mdio_read(ioaddr, reg);
+       val = (bitval == 1) ?
+               val | (bitval << bitnum) :  val & ~(0x0001 << bitnum);
+-      mdio_write(ioaddr, reg, val & 0xffff); 
++      mdio_write(ioaddr, reg, val & 0xffff);
+ }
+ 
+ static void rtl8169_get_mac_version(struct rtl8169_private *tp, void __iomem 
*ioaddr)
+@@ -1140,10 +1166,16 @@ static void rtl8169_get_mac_version(stru
+               u32 mask;
+               int mac_version;
+       } mac_info[] = {
+-              { 0x1 << 28,    RTL_GIGA_MAC_VER_X },
+-              { 0x1 << 26,    RTL_GIGA_MAC_VER_E },
+-              { 0x1 << 23,    RTL_GIGA_MAC_VER_D }, 
+-              { 0x00000000,   RTL_GIGA_MAC_VER_B } /* Catch-all */
++              { 0x38800000,   RTL_GIGA_MAC_VER_15 },
++              { 0x38000000,   RTL_GIGA_MAC_VER_12 },
++              { 0x34000000,   RTL_GIGA_MAC_VER_13 },
++              { 0x30800000,   RTL_GIGA_MAC_VER_14 },
++              { 0x30000000,   RTL_GIGA_MAC_VER_11 },
++              { 0x18000000,   RTL_GIGA_MAC_VER_05 },
++              { 0x10000000,   RTL_GIGA_MAC_VER_04 },
++              { 0x04000000,   RTL_GIGA_MAC_VER_03 },
++              { 0x00800000,   RTL_GIGA_MAC_VER_02 },
++              { 0x00000000,   RTL_GIGA_MAC_VER_01 }   /* Catch-all */
+       }, *p = mac_info;
+       u32 reg;
+ 
+@@ -1155,24 +1187,7 @@ static void rtl8169_get_mac_version(stru
+ 
+ static void rtl8169_print_mac_version(struct rtl8169_private *tp)
+ {
+-      struct {
+-              int version;
+-              char *msg;
+-      } mac_print[] = {
+-              { RTL_GIGA_MAC_VER_E, "RTL_GIGA_MAC_VER_E" },
+-              { RTL_GIGA_MAC_VER_D, "RTL_GIGA_MAC_VER_D" },
+-              { RTL_GIGA_MAC_VER_B, "RTL_GIGA_MAC_VER_B" },
+-              { 0, NULL }
+-      }, *p;
+-
+-      for (p = mac_print; p->msg; p++) {
+-              if (tp->mac_version == p->version) {
+-                      dprintk("mac_version == %s (%04d)\n", p->msg,
+-                                p->version);
+-                      return;
+-              }
+-      }
+-      dprintk("mac_version == Unknown\n");
++      dprintk("mac_version = 0x%02x\n", tp->mac_version);
+ }
+ 
+ static void rtl8169_get_phy_version(struct rtl8169_private *tp, void __iomem 
*ioaddr)
+@@ -1189,7 +1204,7 @@ static void rtl8169_get_phy_version(stru
+       }, *p = phy_info;
+       u16 reg;
+ 
+-      reg = mdio_read(ioaddr, 3) & 0xffff;
++      reg = mdio_read(ioaddr, MII_PHYSID2) & 0xffff;
+       while ((reg & p->mask) != p->set)
+               p++;
+       tp->phy_version = p->phy_version;
+@@ -1257,7 +1272,7 @@ static void rtl8169_hw_phy_config(struct
+       rtl8169_print_mac_version(tp);
+       rtl8169_print_phy_version(tp);
+ 
+-      if (tp->mac_version <= RTL_GIGA_MAC_VER_B)
++      if (tp->mac_version <= RTL_GIGA_MAC_VER_01)
+               return;
+       if (tp->phy_version >= RTL_GIGA_PHY_VER_H)
+               return;
+@@ -1267,7 +1282,7 @@ static void rtl8169_hw_phy_config(struct
+ 
+       /* Shazam ! */
+ 
+-      if (tp->mac_version == RTL_GIGA_MAC_VER_X) {
++      if (tp->mac_version == RTL_GIGA_MAC_VER_04) {
+               mdio_write(ioaddr, 31, 0x0001);
+               mdio_write(ioaddr,  9, 0x273a);
+               mdio_write(ioaddr, 14, 0x7bfb);
+@@ -1306,16 +1321,16 @@ static void rtl8169_phy_timer(unsigned l
+       void __iomem *ioaddr = tp->mmio_addr;
+       unsigned long timeout = RTL8169_PHY_TIMEOUT;
+ 
+-      assert(tp->mac_version > RTL_GIGA_MAC_VER_B);
++      assert(tp->mac_version > RTL_GIGA_MAC_VER_01);
+       assert(tp->phy_version < RTL_GIGA_PHY_VER_H);
+ 
+-      if (!(tp->phy_1000_ctrl_reg & PHY_Cap_1000_Full))
++      if (!(tp->phy_1000_ctrl_reg & ADVERTISE_1000FULL))
+               return;
+ 
+       spin_lock_irq(&tp->lock);
+ 
+       if (tp->phy_reset_pending(ioaddr)) {
+-              /* 
++              /*
+                * A busy loop could burn quite a few cycles on nowadays CPU.
+                * Let's delay the execution of the timer for a few ticks.
+                */
+@@ -1342,7 +1357,7 @@ static inline void rtl8169_delete_timer(
+       struct rtl8169_private *tp = netdev_priv(dev);
+       struct timer_list *timer = &tp->timer;
+ 
+-      if ((tp->mac_version <= RTL_GIGA_MAC_VER_B) ||
++      if ((tp->mac_version <= RTL_GIGA_MAC_VER_01) ||
+           (tp->phy_version >= RTL_GIGA_PHY_VER_H))
+               return;
+ 
+@@ -1354,7 +1369,7 @@ static inline void rtl8169_request_timer
+       struct rtl8169_private *tp = netdev_priv(dev);
+       struct timer_list *timer = &tp->timer;
+ 
+-      if ((tp->mac_version <= RTL_GIGA_MAC_VER_B) ||
++      if ((tp->mac_version <= RTL_GIGA_MAC_VER_01) ||
+           (tp->phy_version >= RTL_GIGA_PHY_VER_H))
+               return;
+ 
+@@ -1382,6 +1397,41 @@ static void rtl8169_netpoll(struct net_d
+ }
+ #endif
+ 
++static void __rtl8169_set_mac_addr(struct net_device *dev, void __iomem 
*ioaddr)
++{
++      unsigned int i, j;
++
++      RTL_W8(Cfg9346, Cfg9346_Unlock);
++      for (i = 0; i < 2; i++) {
++              __le32 l = 0;
++
++              for (j = 0; j < 4; j++) {
++                      l <<= 8;
++                      l |= dev->dev_addr[4*i + j];
++              }
++              RTL_W32(MAC0 + 4*i, cpu_to_be32(l));
++      }
++      RTL_W8(Cfg9346, Cfg9346_Lock);
++}
++
++static int rtl8169_set_mac_addr(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 -EINVAL;
++
++      memcpy(dev->dev_addr, addr->sa_data, dev->addr_len);
++
++      if (netif_running(dev)) {
++              spin_lock_irq(&tp->lock);
++              __rtl8169_set_mac_addr(dev, tp->mmio_addr);
++              spin_unlock_irq(&tp->lock);
++      }
++      return 0;
++}
++
+ static void rtl8169_release_board(struct pci_dev *pdev, struct net_device 
*dev,
+                                 void __iomem *ioaddr)
+ {
+@@ -1391,23 +1441,87 @@ static void rtl8169_release_board(struct
+       free_netdev(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);
++
++      dprintk("Set MAC Reg C+CR Offset 0x82h = 0x01h\n");
++      RTL_W8(0x82, 0x01);
++
++      if (tp->mac_version < RTL_GIGA_MAC_VER_03) {
++              dprintk("Set PCI Latency=0x40\n");
++              pci_write_config_byte(tp->pci_dev, PCI_LATENCY_TIMER, 0x40);
++      }
++
++      if (tp->mac_version == RTL_GIGA_MAC_VER_02) {
++              dprintk("Set MAC Reg C+CR Offset 0x82h = 0x01h\n");
++              RTL_W8(0x82, 0x01);
++              dprintk("Set PHY Reg 0x0bh = 0x00h\n");
++              mdio_write(ioaddr, 0x0b, 0x0000); //w 0x0b 15 0 0
++      }
++
++      rtl8169_link_option(board_idx, &autoneg, &speed, &duplex);
++
++      rtl8169_set_speed(dev, autoneg, speed, duplex);
++
++      if ((RTL_R8(PHYstatus) & TBI_Enable) && netif_msg_link(tp))
++              printk(KERN_INFO PFX "%s: TBI auto-negotiating\n", dev->name);
++}
++
++static int rtl8169_ioctl(struct net_device *dev, struct ifreq *ifr, int cmd)
++{
++      struct rtl8169_private *tp = netdev_priv(dev);
++      struct mii_ioctl_data *data = if_mii(ifr);
++
++      if (!netif_running(dev))
++              return -ENODEV;
++
++      switch (cmd) {
++      case SIOCGMIIPHY:
++              data->phy_id = 32; /* Internal PHY */
++              return 0;
++
++      case SIOCGMIIREG:
++              data->val_out = mdio_read(tp->mmio_addr, data->reg_num & 0x1f);
++              return 0;
++
++      case SIOCSMIIREG:
++              if (!capable(CAP_NET_ADMIN))
++                      return -EPERM;
++              mdio_write(tp->mmio_addr, data->reg_num & 0x1f, data->val_in);
++              return 0;
++      }
++      return -EOPNOTSUPP;
++}
++
+ static int __devinit
+-rtl8169_init_board(struct pci_dev *pdev, struct net_device **dev_out,
+-                 void __iomem **ioaddr_out)
++rtl8169_init_one(struct pci_dev *pdev, const struct pci_device_id *ent)
+ {
+-      void __iomem *ioaddr;
+-      struct net_device *dev;
++      const unsigned int region = rtl_cfg_info[ent->driver_data].region;
+       struct rtl8169_private *tp;
+-      int rc = -ENOMEM, i, acpi_idle_state = 0, pm_cap;
++      struct net_device *dev;
++      void __iomem *ioaddr;
++      unsigned int i, pm_cap;
++      int rc;
+ 
+-      assert(ioaddr_out != NULL);
++      if (netif_msg_drv(&debug)) {
++              printk(KERN_INFO "%s Gigabit Ethernet driver %s loaded\n",
++                     MODULENAME, RTL8169_VERSION);
++      }
+ 
+-      /* dev zeroed in alloc_etherdev */
+       dev = alloc_etherdev(sizeof (*tp));
+-      if (dev == NULL) {
++      if (!dev) {
+               if (netif_msg_drv(&debug))
+                       dev_err(&pdev->dev, "unable to alloc new ethernet\n");
+-              goto err_out;
++              rc = -ENOMEM;
++              goto out;
+       }
+ 
+       SET_MODULE_OWNER(dev);
+@@ -1420,48 +1534,53 @@ rtl8169_init_board(struct pci_dev *pdev,
+       if (rc < 0) {
+               if (netif_msg_probe(tp))
+                       dev_err(&pdev->dev, "enable failure\n");
+-              goto err_out_free_dev;
++              goto err_out_free_dev_1;
+       }
+ 
+       rc = pci_set_mwi(pdev);
+       if (rc < 0)
+-              goto err_out_disable;
++              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;
++              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))
++              if (netif_msg_probe(tp)) {
+                       dev_err(&pdev->dev,
+-                             "PowerManagement capability not found.\n");
++                              "PowerManagement capability not found.\n");
++              }
+       }
+ 
+       /* make sure PCI base addr 1 is MMIO */
+-      if (!(pci_resource_flags(pdev, 1) & IORESOURCE_MEM)) {
+-              if (netif_msg_probe(tp))
++      if (!(pci_resource_flags(pdev, region) & IORESOURCE_MEM)) {
++              if (netif_msg_probe(tp)) {
+                       dev_err(&pdev->dev,
+-                             "region #1 not an MMIO resource, aborting\n");
++                              "region #%d not an MMIO resource, aborting\n",
++                              region);
++              }
+               rc = -ENODEV;
+-              goto err_out_mwi;
++              goto err_out_mwi_3;
+       }
++
+       /* check for weird/broken PCI region reporting */
+-      if (pci_resource_len(pdev, 1) < R8169_REGS_SIZE) {
+-              if (netif_msg_probe(tp))
++      if (pci_resource_len(pdev, region) < R8169_REGS_SIZE) {
++              if (netif_msg_probe(tp)) {
+                       dev_err(&pdev->dev,
+-                             "Invalid PCI region size(s), aborting\n");
++                              "Invalid PCI region size(s), aborting\n");
++              }
+               rc = -ENODEV;
+-              goto err_out_mwi;
++              goto err_out_mwi_3;
+       }
+ 
+       rc = pci_request_regions(pdev, MODULENAME);
+       if (rc < 0) {
+               if (netif_msg_probe(tp))
+                       dev_err(&pdev->dev, "could not request regions.\n");
+-              goto err_out_mwi;
++              goto err_out_mwi_3;
+       }
+ 
+       tp->cp_cmd = PCIMulRW | RxChkSum;
+@@ -1473,22 +1592,23 @@ rtl8169_init_board(struct pci_dev *pdev,
+       } else {
+               rc = pci_set_dma_mask(pdev, DMA_32BIT_MASK);
+               if (rc < 0) {
+-                      if (netif_msg_probe(tp))
++                      if (netif_msg_probe(tp)) {
+                               dev_err(&pdev->dev,
+-                                     "DMA configuration failed.\n");
+-                      goto err_out_free_res;
++                                      "DMA configuration failed.\n");
++                      }
++                      goto err_out_free_res_4;
+               }
+       }
+ 
+       pci_set_master(pdev);
+ 
+       /* ioremap MMIO region */
+-      ioaddr = ioremap(pci_resource_start(pdev, 1), R8169_REGS_SIZE);
+-      if (ioaddr == NULL) {
++      ioaddr = ioremap(pci_resource_start(pdev, region), R8169_REGS_SIZE);
++      if (!ioaddr) {
+               if (netif_msg_probe(tp))
+                       dev_err(&pdev->dev, "cannot remap MMIO, aborting\n");
+               rc = -EIO;
+-              goto err_out_free_res;
++              goto err_out_free_res_4;
+       }
+ 
+       /* Unneeded ? Don't mess with Mrs. Murphy. */
+@@ -1498,10 +1618,10 @@ rtl8169_init_board(struct pci_dev *pdev,
+       RTL_W8(ChipCmd, CmdReset);
+ 
+       /* Check that the chip has finished the reset. */
+-      for (i = 1000; i > 0; i--) {
++      for (i = 100; i > 0; i--) {
+               if ((RTL_R8(ChipCmd) & CmdReset) == 0)
+                       break;
+-              udelay(10);
++              msleep_interruptible(1);
+       }
+ 
+       /* Identify chip attached to board */
+@@ -1519,8 +1639,8 @@ rtl8169_init_board(struct pci_dev *pdev,
+               /* Unknown chip: assume array element #0, original RTL-8169 */
+               if (netif_msg_probe(tp)) {
+                       dev_printk(KERN_DEBUG, &pdev->dev,
+-                             "unknown chip version, assuming %s\n",
+-                             rtl_chip_info[0].name);
++                              "unknown chip version, assuming %s\n",
++                              rtl_chip_info[0].name);
+               }
+               i++;
+       }
+@@ -1531,56 +1651,6 @@ rtl8169_init_board(struct pci_dev *pdev,
+       RTL_W8(Config5, RTL_R8(Config5) & PMEStatus);
+       RTL_W8(Cfg9346, Cfg9346_Lock);
+ 
+-      *ioaddr_out = ioaddr;
+-      *dev_out = dev;
+-out:
+-      return rc;
+-
+-err_out_free_res:
+-      pci_release_regions(pdev);
+-
+-err_out_mwi:
+-      pci_clear_mwi(pdev);
+-
+-err_out_disable:
+-      pci_disable_device(pdev);
+-
+-err_out_free_dev:
+-      free_netdev(dev);
+-err_out:
+-      *ioaddr_out = NULL;
+-      *dev_out = NULL;
+-      goto out;
+-}
+-
+-static int __devinit
+-rtl8169_init_one(struct pci_dev *pdev, const struct pci_device_id *ent)
+-{
+-      struct net_device *dev = NULL;
+-      struct rtl8169_private *tp;
+-      void __iomem *ioaddr = NULL;
+-      static int board_idx = -1;
+-      u8 autoneg, duplex;
+-      u16 speed;
+-      int i, rc;
+-
+-      assert(pdev != NULL);
+-      assert(ent != NULL);
+-
+-      board_idx++;
+-
+-      if (netif_msg_drv(&debug)) {
+-              printk(KERN_INFO "%s Gigabit Ethernet driver %s loaded\n",
+-                     MODULENAME, RTL8169_VERSION);
+-      }
+-
+-      rc = rtl8169_init_board(pdev, &dev, &ioaddr);
+-      if (rc)
+-              return rc;
+-
+-      tp = netdev_priv(dev);
+-      assert(ioaddr != NULL);
+-
+       if (RTL_R8(PHYstatus) & TBI_Enable) {
+               tp->set_speed = rtl8169_set_speed_tbi;
+               tp->get_settings = rtl8169_gset_tbi;
+@@ -1588,13 +1658,15 @@ rtl8169_init_one(struct pci_dev *pdev, c
+               tp->phy_reset_pending = rtl8169_tbi_reset_pending;
+               tp->link_ok = rtl8169_tbi_link_ok;
+ 
+-              tp->phy_1000_ctrl_reg = PHY_Cap_1000_Full; /* Implied by TBI */
++              tp->phy_1000_ctrl_reg = ADVERTISE_1000FULL; /* Implied by TBI */
+       } else {
+               tp->set_speed = rtl8169_set_speed_xmii;
+               tp->get_settings = rtl8169_gset_xmii;
+               tp->phy_reset_enable = rtl8169_xmii_reset_enable;
+               tp->phy_reset_pending = rtl8169_xmii_reset_pending;
+               tp->link_ok = rtl8169_xmii_link_ok;
++
++              dev->do_ioctl = rtl8169_ioctl;
+       }
+ 
+       /* Get MAC address.  FIXME: read EEPROM */
+@@ -1609,6 +1681,7 @@ rtl8169_init_one(struct pci_dev *pdev, c
+       dev->stop = rtl8169_close;
+       dev->tx_timeout = rtl8169_tx_timeout;
+       dev->set_multicast_list = rtl8169_set_rx_mode;
++      dev->set_mac_address = rtl8169_set_mac_addr;
+       dev->watchdog_timeo = RTL8169_TX_TIMEOUT;
+       dev->irq = pdev->irq;
+       dev->base_addr = (unsigned long) ioaddr;
+@@ -1632,19 +1705,13 @@ #endif
+       tp->intr_mask = 0xffff;
+       tp->pci_dev = pdev;
+       tp->mmio_addr = ioaddr;
++      tp->align = rtl_cfg_info[ent->driver_data].align;
+ 
+       spin_lock_init(&tp->lock);
+ 
+       rc = register_netdev(dev);
+-      if (rc) {
+-              rtl8169_release_board(pdev, dev, ioaddr);
+-              return rc;
+-      }
+-
+-      if (netif_msg_probe(tp)) {
+-              printk(KERN_DEBUG "%s: Identified chip type is '%s'.\n",
+-                     dev->name, rtl_chip_info[tp->chipset].name);
+-      }
++      if (rc < 0)
++              goto err_out_unmap_5;
+ 
+       pci_set_drvdata(pdev, dev);
+ 
+@@ -1653,38 +1720,29 @@ #endif
+                      "%2.2x:%2.2x:%2.2x:%2.2x:%2.2x:%2.2x, "
+                      "IRQ %d\n",
+                      dev->name,
+-                     rtl_chip_info[ent->driver_data].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);
+       }
+ 
+-      rtl8169_hw_phy_config(dev);
+-
+-      dprintk("Set MAC Reg C+CR Offset 0x82h = 0x01h\n");
+-      RTL_W8(0x82, 0x01);
++      rtl8169_init_phy(dev, tp);
+ 
+-      if (tp->mac_version < RTL_GIGA_MAC_VER_E) {
+-              dprintk("Set PCI Latency=0x40\n");
+-              pci_write_config_byte(pdev, PCI_LATENCY_TIMER, 0x40);
+-      }
+-
+-      if (tp->mac_version == RTL_GIGA_MAC_VER_D) {
+-              dprintk("Set MAC Reg C+CR Offset 0x82h = 0x01h\n");
+-              RTL_W8(0x82, 0x01);
+-              dprintk("Set PHY Reg 0x0bh = 0x00h\n");
+-              mdio_write(ioaddr, 0x0b, 0x0000); //w 0x0b 15 0 0
+-      }
+-
+-      rtl8169_link_option(board_idx, &autoneg, &speed, &duplex);
+-
+-      rtl8169_set_speed(dev, autoneg, speed, duplex);
+-      
+-      if ((RTL_R8(PHYstatus) & TBI_Enable) && netif_msg_link(tp))
+-              printk(KERN_INFO PFX "%s: TBI auto-negotiating\n", dev->name);
++out:
++      return rc;
+ 
+-      return 0;
++err_out_unmap_5:
++      iounmap(ioaddr);
++err_out_free_res_4:
++      pci_release_regions(pdev);
++err_out_mwi_3:
++      pci_clear_mwi(pdev);
++err_out_disable_2:
++      pci_disable_device(pdev);
++err_out_free_dev_1:
++      free_netdev(dev);
++      goto out;
+ }
+ 
+ static void __devexit
+@@ -1780,20 +1838,41 @@ rtl8169_hw_start(struct net_device *dev)
+ {
+       struct rtl8169_private *tp = netdev_priv(dev);
+       void __iomem *ioaddr = tp->mmio_addr;
++      struct pci_dev *pdev = tp->pci_dev;
+       u32 i;
+ 
+       /* Soft reset the chip. */
+       RTL_W8(ChipCmd, CmdReset);
+ 
+       /* Check that the chip has finished the reset. */
+-      for (i = 1000; i > 0; i--) {
++      for (i = 100; i > 0; i--) {
+               if ((RTL_R8(ChipCmd) & CmdReset) == 0)
+                       break;
+-              udelay(10);
++              msleep_interruptible(1);
++      }
++
++      if (tp->mac_version == RTL_GIGA_MAC_VER_13) {
++              pci_write_config_word(pdev, 0x68, 0x00);
++              pci_write_config_word(pdev, 0x69, 0x08);
++      }
++
++      /* Undocumented stuff. */
++      if (tp->mac_version == RTL_GIGA_MAC_VER_05) {
++              u16 cmd;
++
++              /* Realtek's r1000_n.c driver uses '&& 0x01' here. Well... */
++              if ((RTL_R8(Config2) & 0x07) & 0x01)
++                      RTL_W32(0x7c, 0x0007ffff);
++
++              RTL_W32(0x7c, 0x0007ff00);
++
++              pci_read_config_word(pdev, PCI_COMMAND, &cmd);
++              cmd = cmd & 0xef;
++              pci_write_config_word(pdev, PCI_COMMAND, cmd);
+       }
+ 
++
+       RTL_W8(Cfg9346, Cfg9346_Unlock);
+-      RTL_W8(ChipCmd, CmdTxEnb | CmdRxEnb);
+       RTL_W8(EarlyTxThres, EarlyTxThld);
+ 
+       /* Low hurts. Let's disable the filtering. */
+@@ -1805,32 +1884,40 @@ rtl8169_hw_start(struct net_device *dev)
+       RTL_W32(RxConfig, i);
+ 
+       /* Set DMA burst size and Interframe Gap Time */
+-      RTL_W32(TxConfig,
+-              (TX_DMA_BURST << TxDMAShift) | (InterFrameGap <<
+-                                              TxInterFrameGapShift));
+-      tp->cp_cmd |= RTL_R16(CPlusCmd);
+-      RTL_W16(CPlusCmd, tp->cp_cmd);
++      RTL_W32(TxConfig, (TX_DMA_BURST << TxDMAShift) |
++              (InterFrameGap << TxInterFrameGapShift));
++
++      tp->cp_cmd |= RTL_R16(CPlusCmd) | PCIMulRW;
+ 
+-      if ((tp->mac_version == RTL_GIGA_MAC_VER_D) ||
+-          (tp->mac_version == RTL_GIGA_MAC_VER_E)) {
++      if ((tp->mac_version == RTL_GIGA_MAC_VER_02) ||
++          (tp->mac_version == RTL_GIGA_MAC_VER_03)) {
+               dprintk(KERN_INFO PFX "Set MAC Reg C+CR Offset 0xE0. "
+                       "Bit-3 and bit-14 MUST be 1\n");
+-              tp->cp_cmd |= (1 << 14) | PCIMulRW;
+-              RTL_W16(CPlusCmd, tp->cp_cmd);
++              tp->cp_cmd |= (1 << 14);
+       }
+ 
++      RTL_W16(CPlusCmd, tp->cp_cmd);
++
+       /*
+        * Undocumented corner. Supposedly:
+        * (TxTimer << 12) | (TxPackets << 8) | (RxTimer << 4) | RxPackets
+        */
+       RTL_W16(IntrMitigate, 0x0000);
+ 
+-      RTL_W32(TxDescStartAddrLow, ((u64) tp->TxPhyAddr & DMA_32BIT_MASK));
++      /*
++       * Magic spell: some iop3xx ARM board needs the TxDescAddrHigh
++       * register to be written before TxDescAddrLow to work.
++       * Switching from MMIO to I/O access fixes the issue as well.
++       */
+       RTL_W32(TxDescStartAddrHigh, ((u64) tp->TxPhyAddr >> 32));
+-      RTL_W32(RxDescAddrLow, ((u64) tp->RxPhyAddr & DMA_32BIT_MASK));
++      RTL_W32(TxDescStartAddrLow, ((u64) tp->TxPhyAddr & DMA_32BIT_MASK));
+       RTL_W32(RxDescAddrHigh, ((u64) tp->RxPhyAddr >> 32));
++      RTL_W32(RxDescAddrLow, ((u64) tp->RxPhyAddr & DMA_32BIT_MASK));
++      RTL_W8(ChipCmd, CmdTxEnb | CmdRxEnb);
+       RTL_W8(Cfg9346, Cfg9346_Lock);
+-      udelay(10);
++
++      /* Initially a 10 us delay. Turned it into a PCI commit. - FR */
++      RTL_R8(IntrMask);
+ 
+       RTL_W32(RxMissed, 0);
+ 
+@@ -1842,6 +1929,8 @@ rtl8169_hw_start(struct net_device *dev)
+       /* Enable all known interrupts by setting the interrupt mask. */
+       RTL_W16(IntrMask, rtl8169_intr_mask);
+ 
++      __rtl8169_set_mac_addr(dev, ioaddr);
++
+       netif_start_queue(dev);
+ }
+ 
+@@ -1910,17 +1999,18 @@ static inline void rtl8169_map_to_asic(s
+ }
+ 
+ static int rtl8169_alloc_rx_skb(struct pci_dev *pdev, struct sk_buff 
**sk_buff,
+-                              struct RxDesc *desc, int rx_buf_sz)
++                              struct RxDesc *desc, int rx_buf_sz,
++                              unsigned int align)
+ {
+       struct sk_buff *skb;
+       dma_addr_t mapping;
+       int ret = 0;
+ 
+-      skb = dev_alloc_skb(rx_buf_sz + NET_IP_ALIGN);
++      skb = dev_alloc_skb(rx_buf_sz + align);
+       if (!skb)
+               goto err_out;
+ 
+-      skb_reserve(skb, NET_IP_ALIGN);
++      skb_reserve(skb, align);
+       *sk_buff = skb;
+ 
+       mapping = pci_map_single(pdev, skb->data, rx_buf_sz,
+@@ -1953,15 +2043,15 @@ static u32 rtl8169_rx_fill(struct rtl816
+                          u32 start, u32 end)
+ {
+       u32 cur;
+-      
++
+       for (cur = start; end - cur > 0; cur++) {
+               int ret, i = cur % NUM_RX_DESC;
+ 
+               if (tp->Rx_skbuff[i])
+                       continue;
+-                      
++
+               ret = rtl8169_alloc_rx_skb(tp->pci_dev, tp->Rx_skbuff + i,
+-                                         tp->RxDescArray + i, tp->rx_buf_sz);
++                      tp->RxDescArray + i, tp->rx_buf_sz, tp->align);
+               if (ret < 0)
+                       break;
+       }
+@@ -2190,8 +2280,8 @@ static int rtl8169_start_xmit(struct sk_
+       dma_addr_t mapping;
+       u32 status, len;
+       u32 opts1;
+-      int ret = 0;
+-      
++      int ret = NETDEV_TX_OK;
++
+       if (unlikely(TX_BUFFS_AVAIL(tp) < skb_shinfo(skb)->nr_frags)) {
+               if (netif_msg_drv(tp)) {
+                       printk(KERN_ERR
+@@ -2255,7 +2345,7 @@ out:
+ 
+ err_stop:
+       netif_stop_queue(dev);
+-      ret = 1;
++      ret = NETDEV_TX_BUSY;
+ err_update_stats:
+       tp->stats.tx_dropped++;
+       goto out;
+@@ -2372,16 +2462,17 @@ static inline void rtl8169_rx_csum(struc
+ }
+ 
+ static inline int rtl8169_try_rx_copy(struct sk_buff **sk_buff, int pkt_size,
+-                                    struct RxDesc *desc, int rx_buf_sz)
++                                    struct RxDesc *desc, int rx_buf_sz,
++                                    unsigned int align)
+ {
+       int ret = -1;
+ 
+       if (pkt_size < rx_copybreak) {
+               struct sk_buff *skb;
+ 
+-              skb = dev_alloc_skb(pkt_size + NET_IP_ALIGN);
++              skb = dev_alloc_skb(pkt_size + align);
+               if (skb) {
+-                      skb_reserve(skb, NET_IP_ALIGN);
++                      skb_reserve(skb, align);
+                       eth_copy_and_sum(skb, sk_buff[0]->data, pkt_size, 0);
+                       *sk_buff = skb;
+                       rtl8169_mark_to_asic(desc, rx_buf_sz);
+@@ -2427,6 +2518,10 @@ rtl8169_rx_interrupt(struct net_device *
+                               tp->stats.rx_length_errors++;
+                       if (status & RxCRC)
+                               tp->stats.rx_crc_errors++;
++                      if (status & RxFOVF) {
++                              rtl8169_schedule_work(dev, rtl8169_reset_task);
++                              tp->stats.rx_fifo_errors++;
++                      }
+                       rtl8169_mark_to_asic(desc, tp->rx_buf_sz);
+               } else {
+                       struct sk_buff *skb = tp->Rx_skbuff[entry];
+@@ -2447,13 +2542,13 @@ rtl8169_rx_interrupt(struct net_device *
+                       }
+ 
+                       rtl8169_rx_csum(skb, desc);
+-                      
++
+                       pci_dma_sync_single_for_cpu(tp->pci_dev,
+                               le64_to_cpu(desc->addr), tp->rx_buf_sz,
+                               PCI_DMA_FROMDEVICE);
+ 
+                       if (rtl8169_try_rx_copy(&skb, pkt_size, desc,
+-                                              tp->rx_buf_sz)) {
++                                              tp->rx_buf_sz, tp->align)) {
+                               pci_action = pci_unmap_single;
+                               tp->Rx_skbuff[entry] = NULL;
+                       }
+@@ -2543,7 +2638,7 @@ #ifdef CONFIG_R8169_NAPI
+                       __netif_rx_schedule(dev);
+               else if (netif_msg_intr(tp)) {
+                       printk(KERN_INFO "%s: interrupt %04x taken in poll\n",
+-                             dev->name, status);      
++                             dev->name, status);
+               }
+               break;
+ #else
+@@ -2716,6 +2811,15 @@ rtl8169_set_rx_mode(struct net_device *d
+       tmp = rtl8169_rx_config | rx_mode |
+             (RTL_R32(RxConfig) & rtl_chip_info[tp->chipset].RxConfigMask);
+ 
++      if ((tp->mac_version == RTL_GIGA_MAC_VER_11) ||
++          (tp->mac_version == RTL_GIGA_MAC_VER_12) ||
++          (tp->mac_version == RTL_GIGA_MAC_VER_13) ||
++          (tp->mac_version == RTL_GIGA_MAC_VER_14) ||
++          (tp->mac_version == RTL_GIGA_MAC_VER_15)) {
++              mc_filter[0] = 0xffffffff;
++              mc_filter[1] = 0xffffffff;
++      }
++
+       RTL_W32(RxConfig, tmp);
+       RTL_W32(MAR0 + 0, mc_filter[0]);
+       RTL_W32(MAR0 + 4, mc_filter[1]);
+@@ -2741,7 +2845,7 @@ static struct net_device_stats *rtl8169_
+               RTL_W32(RxMissed, 0);
+               spin_unlock_irqrestore(&tp->lock, flags);
+       }
+-              
++
+       return &tp->stats;
+ }
+ 

Modified: dists/trunk/linux-2.6/debian/patches/series/2
==============================================================================
--- dists/trunk/linux-2.6/debian/patches/series/2       (original)
+++ dists/trunk/linux-2.6/debian/patches/series/2       Wed Sep 27 14:07:20 2006
@@ -1,3 +1,4 @@
 + features/all/drivers/scsi-arcmsr-1.patch
 + features/all/drivers/scsi-arcmsr-2.patch
 + features/all/drivers/scsi-arcmsr-3.patch
++ features/all/drivers/net-r8169-1.patch

_______________________________________________
Kernel-svn-changes mailing list
[email protected]
http://lists.alioth.debian.org/mailman/listinfo/kernel-svn-changes

Reply via email to