]> git.ipfire.org Git - people/pmueller/ipfire-2.x.git/blob - src/patches/linux-2.x-smsc95xx-add_mac_addr_param.patch
Merge remote-tracking branch 'origin/next' into thirteen
[people/pmueller/ipfire-2.x.git] / src / patches / linux-2.x-smsc95xx-add_mac_addr_param.patch
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.
3
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'
12
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.
16
17 Signed-off-by: Danny Kukawka <danny.kukawka@...>
18 ---
19 drivers/net/usb/smsc95xx.c | 85 ++++++++++++++++++++++++++++++++++++++++++--
20 1 files changed, 82 insertions(+), 3 deletions(-)
21
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 {
27 u32 hash_hi;
28 u32 hash_lo;
29 spinlock_t mac_cr_lock;
30 + bool mac_set_from_param;
31 + bool mac_is_random;
32 };
33
34 struct usb_context {
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");
38
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)");
43 +
44 static int smsc95xx_read_reg(struct usbnet *dev, u32 index, u32 *data)
45 {
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);
49 }
50
51 +/* set mac address from the macaddr module parameter */
52 +static int smsc95xx_init_mac_address_from_param(struct usbnet *dev)
53 +{
54 + struct smsc95xx_priv *pdata = (struct smsc95xx_priv *)(dev->data[0]);
55 + int i, parsed, ret;
56 + u8 mtbl[ETH_ALEN];
57 + char *input = NULL;
58 + char *config_param = NULL;
59 + char *netdev_name = NULL;
60 +
61 + parsed = 0;
62 + ret = 0;
63 +
64 + input = kstrdup(macaddr, GFP_KERNEL);
65 +
66 + if (!input)
67 + return -ENOMEM;
68 +
69 + if (strlen(input) >= 17) {
70 + while ((config_param = strsep(&input, ";"))) {
71 + if (parsed == 0) {
72 + if (!mac_pton(config_param, mtbl)) {
73 + ret = 1;
74 + goto parse_err;
75 + }
76 + } else {
77 + netdev_name = config_param;
78 + }
79 + parsed ++;
80 + }
81 +
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);
86 + ret = 1;
87 + goto out;
88 + }
89 + }
90 +
91 + for (i = 0; i < ETH_ALEN; i++) {
92 + dev->net->dev_addr[i] = mtbl[i];
93 + }
94 +
95 + netif_dbg(dev, ifup, dev->net, "set valid MAC address from smsc95xx.macaddr\n");
96 + set_macaddr = true;
97 + pdata->mac_set_from_param = true;
98 + pdata->mac_is_random = false;
99 + goto out;
100 + }
101 + }
102 +
103 +parse_err:
104 + netif_dbg(dev, ifup, dev->net, "failed to parse (valid) MAC from smsc95xx.macaddr\n");
105 + set_macaddr = true;
106 +out:
107 + if (input)
108 + kfree(input);
109 + return ret;
110 +}
111 +
112 static void smsc95xx_init_mac_address(struct usbnet *dev)
113 {
114 + struct smsc95xx_priv *pdata = (struct smsc95xx_priv *)(dev->data[0]);
115 +
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)
120
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");
125 }
126
127 static int smsc95xx_set_mac_address(struct usbnet *dev)
128 {
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;
134 int ret;
135
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);
139 + }
140 +
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;
144 +
145 ret = smsc95xx_write_reg(dev, ADDRL, addr_lo);
146 if (ret < 0) {
147 netdev_warn(dev->net, "Failed to write ADDRL: %d\n", ret);
148 --
149