]> git.ipfire.org Git - people/teissler/ipfire-2.x.git/blame - src/patches/linux-2.x-smsc95xx-add_mac_addr_param.patch
Merge remote-tracking branch 'ummeegge/iptraf-ng' into next
[people/teissler/ipfire-2.x.git] / src / patches / linux-2.x-smsc95xx-add_mac_addr_param.patch
CommitLineData
080ce045
AF
1Added smsc95xx.macaddr module parameter to allow the user to
2change the MAC address on boot if there was no MAC on the EEPROM.
3
4The parameter take the MAC address in 01:23:45:67:89:ab format and
5needs to be locally assigned. The MAC get assigned to the first
6smsc95xx device with no MAC on EEPROM (which resulted in a random
7MAC before). If there is more than one device without MAC on
8EEPROM and the user needs set the MAC to a specific device, it
9can be done by attaching the netdev name (e.g. eth0) to the
10smsc95xx.macaddr parameter seperated by a ';' as e.g. in
11'01:23:45:67:89:ab;eth0'
12
13This allows e.g. u-boot to pass on PandaBoard or BeagleBoard
14the by u-boot generated static MAC address to the kernel device
15to ensure the MAC stays the same during the whole boot process.
16
17Signed-off-by: Danny Kukawka <danny.kukawka@...>
18---
19 drivers/net/usb/smsc95xx.c | 85 ++++++++++++++++++++++++++++++++++++++++++--
20 1 files changed, 82 insertions(+), 3 deletions(-)
21
22diff --git a/drivers/net/usb/smsc95xx.c b/drivers/net/usb/smsc95xx.c
23index 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