Subject: kern/36576: Fix if_nfe to correctly read in MAC address for MCP6x adapters
To: None <kern-bug-people@netbsd.org, gnats-admin@netbsd.org,>
From: None <richy@fatkid.org>
List: netbsd-bugs
Date: 06/29/2007 08:15:05
>Number: 36576
>Category: kern
>Synopsis: Fix if_nfe to correctly read in MAC address for MCP6x adapters
>Confidential: no
>Severity: non-critical
>Priority: medium
>Responsible: kern-bug-people
>State: open
>Class: sw-bug
>Submitter-Id: net
>Arrival-Date: Fri Jun 29 08:15:05 +0000 2007
>Originator: Richy Kim
>Release: NetBSD 4.99.21 -current at 2007-06-28
>Organization:
>Environment:
>Description:
Not all NVIDIA nForce network adapters, in particular MCP6x, read in the MAC address backwards from non-volatile storage.
The -current if_nfe driver always restores the MAC address backwards -- generally resulting in a bad/invalid tuple. So in turn you get a cycling of random MAC addresses on reboot.
>How-To-Repeat:
The ECS GeForce6100SM-M motherboard was my reference platform.
Observe MAC address cycling between reboots.
>Fix:
Read NFE_MAC_ADDR_INORDER (0x8000) flag in NFE_TX_UNK register and reverse (or not) accordingly as confirmed by nVidia staff on FreeBSD's if_nfe port and Linux's forcedepth driver.
Fix/patch attached inline below:
http://fatkid.org/netbsd/netbsd.nfe_mac.diff
Index: if_nfe.c
===================================================================
RCS file: /cvsroot/src/sys/dev/pci/if_nfe.c,v
retrieving revision 1.15
diff -u -r1.15 if_nfe.c
--- if_nfe.c 4 Mar 2007 06:02:22 -0000 1.15
+++ if_nfe.c 29 Jun 2007 03:48:18 -0000
@@ -241,6 +241,10 @@
sc->sc_dmat = pa->pa_dmat;
+ /* Check for reversed ethernet address */
+ if ((NFE_READ(sc, NFE_TX_UNK) & NFE_MAC_ADDR_INORDER) != 0)
+ sc->sc_flags |= NFE_CORRECT_MACADDR;
+
nfe_get_macaddr(sc, sc->sc_enaddr);
printf("%s: Ethernet address %s\n",
sc->sc_dev.dv_xname, ether_sprintf(sc->sc_enaddr));
@@ -1844,15 +1848,27 @@
{
uint32_t tmp;
- tmp = NFE_READ(sc, NFE_MACADDR_LO);
- addr[0] = (tmp >> 8) & 0xff;
- addr[1] = (tmp & 0xff);
-
- tmp = NFE_READ(sc, NFE_MACADDR_HI);
- addr[2] = (tmp >> 24) & 0xff;
- addr[3] = (tmp >> 16) & 0xff;
- addr[4] = (tmp >> 8) & 0xff;
- addr[5] = (tmp & 0xff);
+ if ((sc->sc_flags & NFE_CORRECT_MACADDR) == 0) {
+ tmp = NFE_READ(sc, NFE_MACADDR_LO);
+ addr[0] = (tmp >> 8) & 0xff;
+ addr[1] = (tmp & 0xff);
+
+ tmp = NFE_READ(sc, NFE_MACADDR_HI);
+ addr[2] = (tmp >> 24) & 0xff;
+ addr[3] = (tmp >> 16) & 0xff;
+ addr[4] = (tmp >> 8) & 0xff;
+ addr[5] = (tmp & 0xff);
+ } else {
+ tmp = NFE_READ(sc, NFE_MACADDR_LO);
+ addr[5] = (tmp >> 8) & 0xff;
+ addr[4] = (tmp & 0xff);
+
+ tmp = NFE_READ(sc, NFE_MACADDR_HI);
+ addr[3] = (tmp >> 24) & 0xff;
+ addr[2] = (tmp >> 16) & 0xff;
+ addr[1] = (tmp >> 8) & 0xff;
+ addr[0] = (tmp & 0xff);
+ }
}
void
Index: if_nfereg.h
===================================================================
RCS file: /cvsroot/src/sys/dev/pci/if_nfereg.h,v
retrieving revision 1.4
diff -u -r1.4 if_nfereg.h
--- if_nfereg.h 28 Feb 2007 17:40:11 -0000 1.4
+++ if_nfereg.h 29 Jun 2007 03:48:18 -0000
@@ -84,6 +84,8 @@
#define NFE_STATUS_MAGIC 0x140000
+#define NFE_MAC_ADDR_INORDER 0x8000
+
#define NFE_R1_MAGIC 0x16070f
#define NFE_R2_MAGIC 0x16
#define NFE_R4_MAGIC 0x08
Index: if_nfevar.h
===================================================================
RCS file: /cvsroot/src/sys/dev/pci/if_nfevar.h,v
retrieving revision 1.2
diff -u -r1.2 if_nfevar.h
--- if_nfevar.h 4 Mar 2007 06:02:22 -0000 1.2
+++ if_nfevar.h 29 Jun 2007 03:48:18 -0000
@@ -79,11 +79,12 @@
int sc_if_flags;
u_int sc_flags;
-#define NFE_JUMBO_SUP 0x01
-#define NFE_40BIT_ADDR 0x02
-#define NFE_HW_CSUM 0x04
-#define NFE_HW_VLAN 0x08
-#define NFE_USE_JUMBO 0x10
+#define NFE_JUMBO_SUP 0x01
+#define NFE_40BIT_ADDR 0x02
+#define NFE_HW_CSUM 0x04
+#define NFE_HW_VLAN 0x08
+#define NFE_USE_JUMBO 0x10
+#define NFE_CORRECT_MACADDR 0x20
uint32_t rxtxctl;
uint8_t mii_phyaddr;