broadcom-wl: fixup mac addresses.
authorHauke Mehrtens <hauke@hauke-m.de>
Sat, 5 Jul 2014 19:23:40 +0000 (19:23 +0000)
committerHauke Mehrtens <hauke@hauke-m.de>
Sat, 5 Jul 2014 19:23:40 +0000 (19:23 +0000)
Some series of devices are using the same mac address, which causes
conflicts for these devices we generate a new mac address based on the
base address. This patch adds this functionality to braodcom-wl.

Signed-off-by: Hauke Mehrtens <hauke@hauke-m.de>
SVN-Revision: 41514

package/kernel/broadcom-wl/patches/120-fixup-mac-addresses.patch [new file with mode: 0644]

diff --git a/package/kernel/broadcom-wl/patches/120-fixup-mac-addresses.patch b/package/kernel/broadcom-wl/patches/120-fixup-mac-addresses.patch
new file mode 100644 (file)
index 0000000..f3d7c24
--- /dev/null
@@ -0,0 +1,92 @@
+--- a/driver/nvram_stub.c
++++ b/driver/nvram_stub.c
+@@ -5,6 +5,7 @@
+ #include <siutils.h>
+ #include <bcmendian.h>
+ #include <bcmnvram.h>
++#include <proto/ethernet.h>
+ #ifdef BCMDBG_ERR
+ #define NVR_MSG(x) printf x
+@@ -24,6 +25,7 @@ typedef struct _vars {
+ static vars_t *vars = NULL;
+ static int nvram_init_done = 0;
+ extern char *nvram_buf[];
++static void fixup_mac_addr(vars_t *new);
+ int
+ BCMATTACHFN(nvram_init)(void *si)
+@@ -55,6 +57,7 @@ BCMATTACHFN(nvram_init)(void *si)
+       vars = new;
+       bcopy((char *)(&nvh[1]), new->vars, nvs);
++      fixup_mac_addr(new);
+       return 0;
+ }
+@@ -164,3 +167,65 @@ nvram_getall(char *buf, int count)
+       *buf = '\0';
+       return 0;
+ }
++
++static bool nvram_is_valid_mac(struct ether_addr *mac)
++{
++      return mac && !(mac->octet[0] == 0x00 && mac->octet[1] == 0x90 && mac->octet[2] == 0x4c);
++}
++
++static int nvram_increase_mac_addr(struct ether_addr *mac, u8 num)
++{
++      u8 *oui = mac->octet + ETHER_ADDR_LEN/2 - 1;
++      u8 *p = mac->octet + ETHER_ADDR_LEN - 1;
++
++      do {
++              (*p) += num;
++              if (*p > num)
++                      break;
++              p--;
++              num = 1;
++      } while (p != oui);
++
++      if (p == oui) {
++              pr_err("unable to fetch mac address\n");
++              return -ENOENT;
++      }
++      return 0;
++}
++
++static void nvram_change_mac_addr(vars_t *new, struct ether_addr *valid, const char *name)
++{
++      char *macaddr_c;
++      struct ether_addr macaddr;
++
++      macaddr_c = findvar(new->vars, new->vars + new->size, name);
++      if (!macaddr_c)
++              return;
++
++      bcm_ether_atoe(macaddr_c, &macaddr);
++      if (nvram_is_valid_mac(&macaddr))
++              return;
++      nvram_increase_mac_addr(valid, 1);
++      bcm_ether_ntoa(valid, macaddr_c);
++}
++
++static void fixup_mac_addr(vars_t *new)
++{
++      char *macaddr_base_c;
++      struct ether_addr macaddr_base;
++
++      macaddr_base_c = findvar(new->vars, new->vars + new->size, "et0macaddr");
++      if (!macaddr_base_c)
++              return;
++
++      bcm_ether_atoe(macaddr_base_c, &macaddr_base);
++      if (!nvram_is_valid_mac(&macaddr_base))
++              return;
++
++      /* jump over the first free address so it can be used for wan */
++      nvram_increase_mac_addr(&macaddr_base, 1);
++      nvram_change_mac_addr(new, &macaddr_base, "pci/1/1/macaddr");
++      nvram_change_mac_addr(new, &macaddr_base, "pci/1/2/macaddr");
++      nvram_change_mac_addr(new, &macaddr_base, "pci/2/1/macaddr");
++      nvram_change_mac_addr(new, &macaddr_base, "sb/1/macaddr");
++}