Patchwork 3rd attempt to initialize MAC address on r8169

login
register
mail settings
Submitter Ivan Vecera
Date June 19, 2009, 7:21 a.m.
Message ID <4A3B3C75.5090200@redhat.com>
Download mbox | patch
Permalink /patch/28901/
State Rejected
Delegated to: David Miller
Headers show

Comments

Ivan Vecera - June 19, 2009, 7:21 a.m.
Francois Romieu napsal(a):
> Mikael Pettersson <mikpe@it.uu.se> :
> [...]
>> May I suggest that 6709fe9a27e43a4931938fe0d7f2cc5edef31386 is reverted
>> until this regression is debugged and fixed?
> 
> Yes.
> 
Hello guys,
I made 3rd attempt to enable the ability to initialize r8169's MAC address
on initialization. The proposed patch below works for all my Realtek devices,
but you had some issues with the previous one. Could you please test it on your
devices? I would like to close finally this long term issue.

Thanks,
Ivan

---
 drivers/net/r8169.c |   94 +++++++++++++++++++++++++++++++++++++++++++++++++-
 1 files changed, 92 insertions(+), 2 deletions(-)
Mikael Pettersson - June 19, 2009, 11:30 a.m.
Ivan Vecera writes:
 > Francois Romieu napsal(a):
 > > Mikael Pettersson <mikpe@it.uu.se> :
 > > [...]
 > >> May I suggest that 6709fe9a27e43a4931938fe0d7f2cc5edef31386 is reverted
 > >> until this regression is debugged and fixed?
 > > 
 > > Yes.
 > > 
 > Hello guys,
 > I made 3rd attempt to enable the ability to initialize r8169's MAC address
 > on initialization. The proposed patch below works for all my Realtek devices,
 > but you had some issues with the previous one. Could you please test it on your
 > devices? I would like to close finally this long term issue.

Sorry, this one breaks my Thecus n2100 NAS box just like before.
Here's a dmesg diff from 2.6.30 vanilla and 2.6.30 + this patch:

@@ -158,11 +158,13 @@
 r8169 Gigabit Ethernet driver 2.3LK-NAPI loaded
 r8169 0000:00:01.0: enabling Mem-Wr-Inval
 r8169 0000:00:01.0: no PCI Express capability
-eth0: RTL8169sb/8110sb at 0xe0810200, 00:14:fd:30:11:78, XID 10000000 IRQ 27
+r8169 0000:00:01.0: MAC address found in EEPROM: 00:14:fd:10:00:00
+eth0: RTL8169sb/8110sb at 0xe0810200, 00:00:00:00:00:00, XID 10000000 IRQ 27
 r8169 Gigabit Ethernet driver 2.3LK-NAPI loaded
 r8169 0000:00:02.0: enabling Mem-Wr-Inval
 r8169 0000:00:02.0: no PCI Express capability
-eth1: RTL8169sb/8110sb at 0xe0814300, 00:14:fd:30:11:79, XID 10000000 IRQ 30
+r8169 0000:00:02.0: MAC address found in EEPROM: 00:14:fd:10:00:00
+eth1: RTL8169sb/8110sb at 0xe0814300, 00:00:00:00:00:00, XID 10000000 IRQ 30
 physmap platform flash device: 01000000 at f0000000
 physmap-flash.0: Found 1 x16 devices at 0x0 in 16-bit bank
  Intel/Sharp Extended Query Table at 0x0031
@@ -250,6 +246,4 @@
 EXT3 FS on sda5, internal journal
 EXT3-fs: mounted filesystem with ordered data mode.
 Adding 2008116k swap on /dev/sda3.  Priority:-1 extents:1 across:2008116k 
-r8169: eth0: link up
-r8169: eth0: link up
 warning: `dbus-daemon' uses 32-bit capabilities (legacy support in use)

/Mikael
--
To unsubscribe from this list: send the line "unsubscribe netdev" in
the body of a message to majordomo@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html

Patch

diff --git a/drivers/net/r8169.c b/drivers/net/r8169.c
index 3b19e0c..60c8811 100644
--- a/drivers/net/r8169.c
+++ b/drivers/net/r8169.c
@@ -80,9 +80,9 @@  static const int multicast_filter_limit = 32;
 #define RTL8169_TX_TIMEOUT	(6*HZ)
 #define RTL8169_PHY_TIMEOUT	(10*HZ)
 
-#define RTL_EEPROM_SIG		cpu_to_le32(0x8129)
-#define RTL_EEPROM_SIG_MASK	cpu_to_le32(0xffff)
+#define RTL_EEPROM_SIG		0x8129
 #define RTL_EEPROM_SIG_ADDR	0x0000
+#define RTL_EEPROM_MAC_ADDR	0x0007
 
 /* write/read MMIO register */
 #define RTL_W8(reg, val8)	writeb ((val8), ioaddr + (reg))
@@ -292,6 +292,11 @@  enum rtl_register_content {
 	/* Cfg9346Bits */
 	Cfg9346_Lock	= 0x00,
 	Cfg9346_Unlock	= 0xc0,
+	Cfg9346_Program	= 0x88,		/* Programming mode */
+	Cfg9346_EECS	= 0x08,		/* Chip select */
+	Cfg9346_EESK	= 0x04,		/* Serial data clock */
+	Cfg9346_EEDI	= 0x02,		/* Data input */
+	Cfg9346_EEDO	= 0x01,		/* Data output */
 
 	/* rx_mode_bits */
 	AcceptErr	= 0x20,
@@ -304,6 +309,7 @@  enum rtl_register_content {
 	/* RxConfigBits */
 	RxCfgFIFOShift	= 13,
 	RxCfgDMAShift	=  8,
+	RxCfg9356SEL	=  6, 		/* EEPROM type: 0 = 9346, 1 = 9356 */
 
 	/* TxConfigBits */
 	TxInterFrameGapShift = 24,
@@ -1962,6 +1968,88 @@  static const struct net_device_ops rtl8169_netdev_ops = {
 
 };
 
+/* delay between EEPROM clock transitions - force out buffered PCI writes. */
+#define RTL_EEPROM_DELAY()	(void)RTL_R8(Cfg9346)
+#define RTL_EEPROM_READ_CMD	6
+
+/* read 16bit word stored in EEPROM. EEPROM is addressed by words. */
+static u16 rtl_eeprom_read(void __iomem *ioaddr, int addr)
+{
+	int read_cmd, addr_len, i;
+	u16 result = 0;
+
+	/* check for EEPROM address size (in bits) */
+	addr_len = (RTL_R32(RxConfig) & (1 << RxCfg9356SEL)) ? 8 : 6;
+	read_cmd = addr | (RTL_EEPROM_READ_CMD << addr_len);
+
+	/* enter programming mode */
+	RTL_W8(Cfg9346, Cfg9346_Program & ~Cfg9346_EECS);
+	RTL_W8(Cfg9346, Cfg9346_Program);
+	RTL_EEPROM_DELAY();
+
+	/* shift out read command and requested address */
+	for (i = 4 + addr_len; i >= 0; i--) {
+		int val = (read_cmd & (1 << i)) ? Cfg9346_EEDI : 0;
+		RTL_W8(Cfg9346, Cfg9346_Program | val);
+		RTL_EEPROM_DELAY();
+		RTL_W8(Cfg9346, Cfg9346_Program | val | Cfg9346_EESK);
+		RTL_EEPROM_DELAY();
+	}
+	RTL_W8(Cfg9346, Cfg9346_Program);
+	RTL_EEPROM_DELAY();
+
+	/* read back 16bit value */
+	for (i = 16; i > 0; i--) {
+		RTL_W8(Cfg9346, Cfg9346_Program | Cfg9346_EESK);
+		RTL_EEPROM_DELAY();
+
+		result <<= 1;
+		result |= (RTL_R8 (Cfg9346) & Cfg9346_EEDO) ? 1 : 0;
+
+		RTL_W8(Cfg9346, Cfg9346_Program);
+		RTL_EEPROM_DELAY();
+	}
+
+	/* leave programming mode - lock configuration */
+	RTL_W8(Cfg9346, Cfg9346_Lock);
+	RTL_EEPROM_DELAY();
+
+	return result;
+}
+
+static void rtl_init_mac_address(struct rtl8169_private *tp,
+				 void __iomem *ioaddr)
+{
+	struct pci_dev *pdev = tp->pci_dev;
+	int i;
+	u16 x;
+	u8 mac[8];
+
+	/* read EEPROM signature */
+	x = rtl_eeprom_read(ioaddr, RTL_EEPROM_SIG_ADDR);
+	if (x != RTL_EEPROM_SIG) {
+		dev_info(&pdev->dev, "Missing EEPROM signature: %04x\n", x);
+		return;
+	}
+
+	/* read MAC address */
+	for (i = 0; i < 3; i++) {
+		x = rtl_eeprom_read(ioaddr, RTL_EEPROM_MAC_ADDR + i);
+		mac[i*2] = x & 0xff;
+		mac[i*2+1] = x >> 8;
+	}
+
+	if (netif_msg_probe(tp)) {
+		DECLARE_MAC_BUF(buf);
+
+		dev_info(&pdev->dev, "MAC address found in EEPROM: %s\n",
+			 print_mac(buf, mac));
+	}
+
+	if (is_valid_ether_addr(mac))
+		rtl_rar_set(tp, mac);
+}
+
 static int __devinit
 rtl8169_init_one(struct pci_dev *pdev, const struct pci_device_id *ent)
 {
@@ -2141,6 +2229,8 @@  rtl8169_init_one(struct pci_dev *pdev, const struct pci_device_id *ent)
 
 	tp->mmio_addr = ioaddr;
 
+	rtl_init_mac_address(tp, ioaddr);
+
 	/* Get MAC address */
 	for (i = 0; i < MAC_ADDR_LEN; i++)
 		dev->dev_addr[i] = RTL_R8(MAC0 + i);