[kernel] r7541 - in dists/trunk/linux-2.6/debian/patches:
features/all/drivers series
Bastian Blank
waldi at costa.debian.org
Wed Sep 27 14:08:12 UTC 2006
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 <shuchen at realtek.com.tw>.
+ 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
More information about the Kernel-svn-changes
mailing list