Program net device MAC addresses after initializing
authorBen Warren <biggerbadderben@gmail.com>
Mon, 26 Apr 2010 18:11:46 +0000 (11:11 -0700)
committerBen Warren <biggerbadderben@gmail.com>
Mon, 3 May 2010 21:52:49 +0000 (14:52 -0700)
Add a new function to the eth_device struct for programming a network
controller's hardware address.

After all network devices have been initialized and the proper MAC address
for each has been determined, make a device driver call to program the
address into the device.  Only device instances with valid unicast addresses
will be programmed.

Signed-off-by: Ben Warren <biggerbadderben@gmail.com>
Acked-by: Detlev Zundel <dzu@denx.de>
Tested-by: Prafulla Wadaskar <prafulla@marvell.com>
Tested-by: Heiko Schocher <hs@denx.de>
Tested-by: Thomas Chou <thomas@wytron.com.tw>
README
doc/README.drivers.eth
doc/README.enetaddr
include/net.h
net/eth.c

diff --git a/README b/README
index cdd81d4efe3efafd8e8e3653303eec1af2e599f5..81692c0a49fedd8444663ec331383916591582f2 100644 (file)
--- a/README
+++ b/README
@@ -3303,6 +3303,11 @@ o If both the SROM and the environment contain a MAC address, and the
 o If neither SROM nor the environment contain a MAC address, an error
   is raised.
 
+If Ethernet drivers implement the 'write_hwaddr' function, valid MAC addresses
+will be programmed into hardware as part of the initialization process.  This
+may be skipped by setting the appropriate 'ethmacskip' environment variable.
+The naming convention is as follows:
+"ethmacskip" (=>eth0), "eth1macskip" (=>eth1) etc.
 
 Image Formats:
 ==============
index d0c3571165bcbc63fd54721345066542a35e25e9..eb83038b5dbd1880edc1e9f0cfa34f3ed6eb6a24 100644 (file)
@@ -70,6 +70,7 @@ int ape_register(bd_t *bis, int iobase)
        dev->halt = ape_halt;
        dev->send = ape_send;
        dev->recv = ape_recv;
+       dev->write_hwaddr = ape_write_hwaddr;
 
        eth_register(dev);
 
@@ -102,11 +103,12 @@ not checking its state or doing random probing.
  -----------
 
 Now that we've registered with the ethernet layer, we can start getting some
-real work done.  You will need four functions:
+real work done.  You will need five functions:
        int ape_init(struct eth_device *dev, bd_t *bis);
        int ape_send(struct eth_device *dev, volatile void *packet, int length);
        int ape_recv(struct eth_device *dev);
        int ape_halt(struct eth_device *dev);
+       int ape_write_hwaddr(struct eth_device *dev);
 
 The init function checks the hardware (probing/identifying) and gets it ready
 for send/recv operations.  You often do things here such as resetting the MAC
@@ -150,6 +152,9 @@ The halt function should turn off / disable the hardware and place it back in
 its reset state.  It can be called at any time (before any call to the related
 init function), so make sure it can handle this sort of thing.
 
+The write_hwaddr function should program the MAC address stored in dev->enetaddr
+into the Ethernet controller.
+
 So the call graph at this stage would look something like:
 some net operation (ping / tftp / whatever...)
        eth_init()
index 94d800a02ae0ff437746030587fbc65a75d49276..2d8e24f5cb4df128dcf5fdba00ed244614791f25 100644 (file)
@@ -33,11 +33,13 @@ Correct flow of setting up the MAC address (summarized):
 1. Read from hardware in initialize() function
 2. Read from environment in net/eth.c after initialize()
 3. Give priority to the value in the environment if a conflict
-4. Program hardware in the device's init() function.
+4. Program the address into hardware if the following conditions are met:
+       a) The relevant driver has a 'write_addr' function
+       b) The user hasn't set an 'ethmacskip' environment variable
+       c) The address is valid (unicast, not all-zeros)
 
-If somebody wants to subvert the design philosophy, this can be done
-in the board-specific board_eth_init() function by calling eth_init()
-after all the NICs have been registered.
+Previous behavior had the MAC address always being programmed into hardware
+in the device's init() function.
 
 -------
  Usage
index 3f6a5d1497fe439abe7d6a3e19cd070ba8515e57..a180881dc73d498a2fd283e460bd08c8480d245c 100644 (file)
@@ -105,6 +105,7 @@ struct eth_device {
 #ifdef CONFIG_MCAST_TFTP
        int (*mcast) (struct eth_device*, u32 ip, u8 set);
 #endif
+       int  (*write_hwaddr) (struct eth_device*);
        struct eth_device *next;
        void *priv;
 };
index aff698724d993f6af03b6ec939ef002a98926018..45e4a26d6fc36f4d080e3e6589cb11d7d40bd7d0 100644 (file)
--- a/net/eth.c
+++ b/net/eth.c
@@ -60,6 +60,14 @@ int eth_getenv_enetaddr_by_index(int index, uchar *enetaddr)
        return eth_getenv_enetaddr(enetvar, enetaddr);
 }
 
+static int eth_mac_skip(int index)
+{
+       char enetvar[15];
+       char *skip_state;
+       sprintf(enetvar, index ? "eth%dmacskip" : "ethmacskip", index);
+       return ((skip_state = getenv(enetvar)) != NULL);
+}
+
 #ifdef CONFIG_NET_MULTI
 
 /*
@@ -242,6 +250,11 @@ int eth_initialize(bd_t *bis)
 
                                memcpy(dev->enetaddr, env_enetaddr, 6);
                        }
+                       if (dev->write_hwaddr &&
+                               !eth_mac_skip(eth_number) &&
+                               is_valid_ether_addr(dev->enetaddr)) {
+                               dev->write_hwaddr(dev);
+                       }
 
                        eth_number++;
                        dev = dev->next;