1 Added smsc95xx.macaddr module parameter to allow the user to
2 change the MAC address on boot if there was no MAC on the EEPROM.
4 The parameter take the MAC address in 01:23:45:67:89:ab format and
5 needs to be locally assigned. The MAC get assigned to the first
6 smsc95xx device with no MAC on EEPROM (which resulted in a random
7 MAC before). If there is more than one device without MAC on
8 EEPROM and the user needs set the MAC to a specific device, it
9 can be done by attaching the netdev name (e.g. eth0) to the
10 smsc95xx.macaddr parameter seperated by a ';' as e.g. in
11 '01:23:45:67:89:ab;eth0'
13 This allows e.g. u-boot to pass on PandaBoard or BeagleBoard
14 the by u-boot generated static MAC address to the kernel device
15 to ensure the MAC stays the same during the whole boot process.
17 Signed-off-by: Danny Kukawka <danny.kukawka@...>
19 drivers/net/usb/smsc95xx.c | 85 ++++++++++++++++++++++++++++++++++++++++++--
20 1 files changed, 82 insertions(+), 3 deletions(-)
22 diff --git a/drivers/net/usb/smsc95xx.c b/drivers/net/usb/smsc95xx.c
23 index d45520e..3198c7d 100644
24 --- a/drivers/net/usb/smsc95xx.c
25 +++ b/drivers/net/usb/smsc95xx.c
26 @@ -52,6 +52,8 @@ struct smsc95xx_priv {
29 spinlock_t mac_cr_lock;
30 + bool mac_set_from_param;
35 @@ -63,6 +65,11 @@ static bool turbo_mode = true;
36 module_param(turbo_mode, bool, 0644);
37 MODULE_PARM_DESC(turbo_mode, "Enable multiple frames per Rx transaction");
39 +static char *macaddr = ":";
40 +static bool set_macaddr = false;
41 +module_param(macaddr, charp, 0);
42 +MODULE_PARM_DESC(macaddr, " macaddr=macaddr;[tgt-netdevname] (Set MAC only if there is a device without MAC on EEPROM)");
44 static int smsc95xx_read_reg(struct usbnet *dev, u32 index, u32 *data)
46 u32 *buf = kmalloc(4, GFP_KERNEL);
47 @@ -601,8 +608,71 @@ static int smsc95xx_ioctl(struct net_device *netdev, struct ifreq *rq, int cmd)
48 return generic_mii_ioctl(&dev->mii, if_mii(rq), cmd, NULL);
51 +/* set mac address from the macaddr module parameter */
52 +static int smsc95xx_init_mac_address_from_param(struct usbnet *dev)
54 + struct smsc95xx_priv *pdata = (struct smsc95xx_priv *)(dev->data[0]);
58 + char *config_param = NULL;
59 + char *netdev_name = NULL;
64 + input = kstrdup(macaddr, GFP_KERNEL);
69 + if (strlen(input) >= 17) {
70 + while ((config_param = strsep(&input, ";"))) {
72 + if (!mac_pton(config_param, mtbl)) {
77 + netdev_name = config_param;
82 + if (parsed && is_valid_ether_addr(mtbl)) {
83 + if (netdev_name && strlen(netdev_name)) {
84 + if (strcmp(netdev_name, dev->net->name) != 0) {
85 + netif_dbg(dev, ifup, dev->net, "requested devname (%s) didn't match (%s)\n", netdev_name, dev->net->name);
91 + for (i = 0; i < ETH_ALEN; i++) {
92 + dev->net->dev_addr[i] = mtbl[i];
95 + netif_dbg(dev, ifup, dev->net, "set valid MAC address from smsc95xx.macaddr\n");
97 + pdata->mac_set_from_param = true;
98 + pdata->mac_is_random = false;
104 + netif_dbg(dev, ifup, dev->net, "failed to parse (valid) MAC from smsc95xx.macaddr\n");
105 + set_macaddr = true;
112 static void smsc95xx_init_mac_address(struct usbnet *dev)
114 + struct smsc95xx_priv *pdata = (struct smsc95xx_priv *)(dev->data[0]);
116 /* try reading mac address from EEPROM */
117 if (smsc95xx_read_eeprom(dev, EEPROM_MAC_OFFSET, ETH_ALEN,
118 dev->net->dev_addr) == 0) {
119 @@ -615,16 +685,25 @@ static void smsc95xx_init_mac_address(struct usbnet *dev)
121 /* no eeprom, or eeprom values are invalid. generate random MAC */
122 random_ether_addr(dev->net->dev_addr);
123 + pdata->mac_is_random = true;
124 netif_dbg(dev, ifup, dev->net, "MAC address set to random_ether_addr\n");
127 static int smsc95xx_set_mac_address(struct usbnet *dev)
129 - u32 addr_lo = dev->net->dev_addr[0] | dev->net->dev_addr[1] << 8 |
130 - dev->net->dev_addr[2] << 16 | dev->net->dev_addr[3] << 24;
131 - u32 addr_hi = dev->net->dev_addr[4] | dev->net->dev_addr[5] << 8;
132 + struct smsc95xx_priv *pdata = (struct smsc95xx_priv *)(dev->data[0]);
133 + u32 addr_lo, addr_hi;
136 + if (pdata->mac_is_random && !pdata->mac_set_from_param && !set_macaddr) {
137 + netif_dbg(dev, ifup, dev->net, "random MAC address, not yet set from smsc95xx.macaddr, try to set it ...\n");
138 + smsc95xx_init_mac_address_from_param(dev);
141 + addr_lo = dev->net->dev_addr[0] | dev->net->dev_addr[1] << 8 |
142 + dev->net->dev_addr[2] << 16 | dev->net->dev_addr[3] << 24;
143 + addr_hi = dev->net->dev_addr[4] | dev->net->dev_addr[5] << 8;
145 ret = smsc95xx_write_reg(dev, ADDRL, addr_lo);
147 netdev_warn(dev->net, "Failed to write ADDRL: %d\n", ret);