Commit ecee9324d73555e744593f3e0d387bec4c566f55

Authored by Ben Warren
1 parent c960b13ed2

Program net device MAC addresses after initializing

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>

Showing 5 changed files with 31 additions and 5 deletions Side-by-side Diff

... ... @@ -3303,6 +3303,11 @@
3303 3303 o If neither SROM nor the environment contain a MAC address, an error
3304 3304 is raised.
3305 3305  
  3306 +If Ethernet drivers implement the 'write_hwaddr' function, valid MAC addresses
  3307 +will be programmed into hardware as part of the initialization process. This
  3308 +may be skipped by setting the appropriate 'ethmacskip' environment variable.
  3309 +The naming convention is as follows:
  3310 +"ethmacskip" (=>eth0), "eth1macskip" (=>eth1) etc.
3306 3311  
3307 3312 Image Formats:
3308 3313 ==============
doc/README.drivers.eth
... ... @@ -70,6 +70,7 @@
70 70 dev->halt = ape_halt;
71 71 dev->send = ape_send;
72 72 dev->recv = ape_recv;
  73 + dev->write_hwaddr = ape_write_hwaddr;
73 74  
74 75 eth_register(dev);
75 76  
76 77  
... ... @@ -102,11 +103,12 @@
102 103 -----------
103 104  
104 105 Now that we've registered with the ethernet layer, we can start getting some
105   -real work done. You will need four functions:
  106 +real work done. You will need five functions:
106 107 int ape_init(struct eth_device *dev, bd_t *bis);
107 108 int ape_send(struct eth_device *dev, volatile void *packet, int length);
108 109 int ape_recv(struct eth_device *dev);
109 110 int ape_halt(struct eth_device *dev);
  111 + int ape_write_hwaddr(struct eth_device *dev);
110 112  
111 113 The init function checks the hardware (probing/identifying) and gets it ready
112 114 for send/recv operations. You often do things here such as resetting the MAC
... ... @@ -149,6 +151,9 @@
149 151 The halt function should turn off / disable the hardware and place it back in
150 152 its reset state. It can be called at any time (before any call to the related
151 153 init function), so make sure it can handle this sort of thing.
  154 +
  155 +The write_hwaddr function should program the MAC address stored in dev->enetaddr
  156 +into the Ethernet controller.
152 157  
153 158 So the call graph at this stage would look something like:
154 159 some net operation (ping / tftp / whatever...)
... ... @@ -33,11 +33,13 @@
33 33 1. Read from hardware in initialize() function
34 34 2. Read from environment in net/eth.c after initialize()
35 35 3. Give priority to the value in the environment if a conflict
36   -4. Program hardware in the device's init() function.
  36 +4. Program the address into hardware if the following conditions are met:
  37 + a) The relevant driver has a 'write_addr' function
  38 + b) The user hasn't set an 'ethmacskip' environment variable
  39 + c) The address is valid (unicast, not all-zeros)
37 40  
38   -If somebody wants to subvert the design philosophy, this can be done
39   -in the board-specific board_eth_init() function by calling eth_init()
40   -after all the NICs have been registered.
  41 +Previous behavior had the MAC address always being programmed into hardware
  42 +in the device's init() function.
41 43  
42 44 -------
43 45 Usage
... ... @@ -105,6 +105,7 @@
105 105 #ifdef CONFIG_MCAST_TFTP
106 106 int (*mcast) (struct eth_device*, u32 ip, u8 set);
107 107 #endif
  108 + int (*write_hwaddr) (struct eth_device*);
108 109 struct eth_device *next;
109 110 void *priv;
110 111 };
... ... @@ -60,6 +60,14 @@
60 60 return eth_getenv_enetaddr(enetvar, enetaddr);
61 61 }
62 62  
  63 +static int eth_mac_skip(int index)
  64 +{
  65 + char enetvar[15];
  66 + char *skip_state;
  67 + sprintf(enetvar, index ? "eth%dmacskip" : "ethmacskip", index);
  68 + return ((skip_state = getenv(enetvar)) != NULL);
  69 +}
  70 +
63 71 #ifdef CONFIG_NET_MULTI
64 72  
65 73 /*
... ... @@ -241,6 +249,11 @@
241 249 }
242 250  
243 251 memcpy(dev->enetaddr, env_enetaddr, 6);
  252 + }
  253 + if (dev->write_hwaddr &&
  254 + !eth_mac_skip(eth_number) &&
  255 + is_valid_ether_addr(dev->enetaddr)) {
  256 + dev->write_hwaddr(dev);
244 257 }
245 258  
246 259 eth_number++;