diff options
Diffstat (limited to 'arch')
-rw-r--r-- | arch/mips/bcm47xx/sprom.c | 48 |
1 files changed, 48 insertions, 0 deletions
diff --git a/arch/mips/bcm47xx/sprom.c b/arch/mips/bcm47xx/sprom.c index da4cdb16844e..41226b68de3d 100644 --- a/arch/mips/bcm47xx/sprom.c +++ b/arch/mips/bcm47xx/sprom.c | |||
@@ -28,6 +28,8 @@ | |||
28 | 28 | ||
29 | #include <bcm47xx.h> | 29 | #include <bcm47xx.h> |
30 | #include <bcm47xx_nvram.h> | 30 | #include <bcm47xx_nvram.h> |
31 | #include <linux/if_ether.h> | ||
32 | #include <linux/etherdevice.h> | ||
31 | 33 | ||
32 | static void create_key(const char *prefix, const char *postfix, | 34 | static void create_key(const char *prefix, const char *postfix, |
33 | const char *name, char *buf, int len) | 35 | const char *name, char *buf, int len) |
@@ -631,6 +633,33 @@ static void bcm47xx_fill_sprom_path_r45(struct ssb_sprom *sprom, | |||
631 | } | 633 | } |
632 | } | 634 | } |
633 | 635 | ||
636 | static bool bcm47xx_is_valid_mac(u8 *mac) | ||
637 | { | ||
638 | return mac && !(mac[0] == 0x00 && mac[1] == 0x90 && mac[2] == 0x4c); | ||
639 | } | ||
640 | |||
641 | static int bcm47xx_increase_mac_addr(u8 *mac, u8 num) | ||
642 | { | ||
643 | u8 *oui = mac + ETH_ALEN/2 - 1; | ||
644 | u8 *p = mac + ETH_ALEN - 1; | ||
645 | |||
646 | do { | ||
647 | (*p) += num; | ||
648 | if (*p > num) | ||
649 | break; | ||
650 | p--; | ||
651 | num = 1; | ||
652 | } while (p != oui); | ||
653 | |||
654 | if (p == oui) { | ||
655 | pr_err("unable to fetch mac address\n"); | ||
656 | return -ENOENT; | ||
657 | } | ||
658 | return 0; | ||
659 | } | ||
660 | |||
661 | static int mac_addr_used = 2; | ||
662 | |||
634 | static void bcm47xx_fill_sprom_ethernet(struct ssb_sprom *sprom, | 663 | static void bcm47xx_fill_sprom_ethernet(struct ssb_sprom *sprom, |
635 | const char *prefix, bool fallback) | 664 | const char *prefix, bool fallback) |
636 | { | 665 | { |
@@ -648,6 +677,25 @@ static void bcm47xx_fill_sprom_ethernet(struct ssb_sprom *sprom, | |||
648 | 677 | ||
649 | nvram_read_macaddr(prefix, "macaddr", sprom->il0mac, fallback); | 678 | nvram_read_macaddr(prefix, "macaddr", sprom->il0mac, fallback); |
650 | nvram_read_macaddr(prefix, "il0macaddr", sprom->il0mac, fallback); | 679 | nvram_read_macaddr(prefix, "il0macaddr", sprom->il0mac, fallback); |
680 | |||
681 | /* The address prefix 00:90:4C is used by Broadcom in their initial | ||
682 | configuration. When a mac address with the prefix 00:90:4C is used | ||
683 | all devices from the same series are sharing the same mac address. | ||
684 | To prevent mac address collisions we replace them with a mac address | ||
685 | based on the base address. */ | ||
686 | if (!bcm47xx_is_valid_mac(sprom->il0mac)) { | ||
687 | u8 mac[6]; | ||
688 | |||
689 | nvram_read_macaddr(NULL, "et0macaddr", mac, false); | ||
690 | if (bcm47xx_is_valid_mac(mac)) { | ||
691 | int err = bcm47xx_increase_mac_addr(mac, mac_addr_used); | ||
692 | |||
693 | if (!err) { | ||
694 | ether_addr_copy(sprom->il0mac, mac); | ||
695 | mac_addr_used++; | ||
696 | } | ||
697 | } | ||
698 | } | ||
651 | } | 699 | } |
652 | 700 | ||
653 | static void bcm47xx_fill_board_data(struct ssb_sprom *sprom, const char *prefix, | 701 | static void bcm47xx_fill_board_data(struct ssb_sprom *sprom, const char *prefix, |