[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