From: Andy Green <[email protected]>

This exposes a new API in devices.c that lets a board register
a list of device paths representing network devices that have
no arrangements for their MAC address to be set by the board.

It watches network device registrations via a notifier and
gives the devices requiring them a synthetic - but constant for
a given board - MAC address immediately.

This approach is compatible with devices with asynchronous
probe such as the USB-based Etherent PHY and SDIO-based
wlan module found on PandaBoard / ES.

It has also been tested on PandaBoard 5 successfully but that
support is not part of this series.

Signed-off-by: Andy Green <[email protected]>
---
 arch/arm/mach-omap2/common.h  |    2 +
 arch/arm/mach-omap2/devices.c |   89 +++++++++++++++++++++++++++++++++++++++++
 2 files changed, 91 insertions(+)

diff --git a/arch/arm/mach-omap2/common.h b/arch/arm/mach-omap2/common.h
index 5d99c1b..ae4d8a9 100644
--- a/arch/arm/mach-omap2/common.h
+++ b/arch/arm/mach-omap2/common.h
@@ -116,6 +116,8 @@ static inline int omap_mux_late_init(void)
 #endif
 
 extern void omap2_init_common_infrastructure(void);
+extern int omap_register_mac_device_fixup_paths(const char * const *paths,
+                                                                   int count);
 
 extern struct sys_timer omap2_timer;
 extern struct sys_timer omap3_timer;
diff --git a/arch/arm/mach-omap2/devices.c b/arch/arm/mach-omap2/devices.c
index 91ef6699..d0a3d2d 100644
--- a/arch/arm/mach-omap2/devices.c
+++ b/arch/arm/mach-omap2/devices.c
@@ -18,12 +18,15 @@
 #include <linux/slab.h>
 #include <linux/of.h>
 #include <linux/platform_data/omap4-keypad.h>
+#include <linux/netdevice.h>
+#include <linux/if_ether.h>
 
 #include <mach/hardware.h>
 #include <mach/irqs.h>
 #include <asm/mach-types.h>
 #include <asm/mach/map.h>
 #include <asm/pmu.h>
+#include <mach/id.h>
 
 #include "iomap.h"
 #include <plat/board.h>
@@ -39,6 +42,9 @@
 #define L3_MODULES_MAX_LEN 12
 #define L3_MODULES 3
 
+static const char * const *mac_device_fixup_paths;
+int count_mac_device_fixup_paths;
+
 static int __init omap3_l3_init(void)
 {
        struct omap_hwmod *oh;
@@ -627,6 +633,89 @@ static void omap_init_vout(void)
 static inline void omap_init_vout(void) {}
 #endif
 
+static int omap_device_path_need_mac(struct device *dev)
+{
+       const char **try = (const char **)mac_device_fixup_paths;
+       const char *path;
+       int count = count_mac_device_fixup_paths;
+       const char *p;
+       int len;
+       struct device *devn;
+
+       while (count--) {
+
+               p = *try + strlen(*try);
+               devn = dev;
+
+               while (devn) {
+
+                       path = dev_name(devn);
+                       len = strlen(path);
+
+                       if ((p - *try) < len) {
+                               devn = NULL;
+                               continue;
+                       }
+
+                       p -= len;
+
+                       if (strncmp(path, p, len)) {
+                               devn = NULL;
+                               continue;
+                       }
+
+                       devn = devn->parent;
+                       if (p == *try)
+                               return count;
+
+                       if (devn != NULL && (p - *try) < 2)
+                               devn = NULL;
+
+                       p--;
+                       if (devn != NULL && *p != '/')
+                               devn = NULL;
+               }
+
+               try++;
+       }
+
+       return -ENOENT;
+}
+
+static int omap_panda_netdev_event(struct notifier_block *this,
+                                               unsigned long event, void *ptr)
+{
+       struct net_device *dev = ptr;
+       struct sockaddr sa;
+       int n;
+
+       if (event != NETDEV_REGISTER)
+               return NOTIFY_DONE;
+
+       n = omap_device_path_need_mac(dev->dev.parent);
+       if (n < 0)
+               return NOTIFY_DONE;
+
+       sa.sa_family = dev->type;
+       omap2_die_id_to_ethernet_mac(sa.sa_data, n);
+       dev->netdev_ops->ndo_set_mac_address(dev, &sa);
+
+       return NOTIFY_DONE;
+}
+
+static struct notifier_block omap_panda_netdev_notifier = {
+       .notifier_call = omap_panda_netdev_event,
+       .priority = 1,
+};
+
+int omap_register_mac_device_fixup_paths(const char * const *paths, int count)
+{
+       mac_device_fixup_paths = paths;
+       count_mac_device_fixup_paths = count;
+
+       return register_netdevice_notifier(&omap_panda_netdev_notifier);
+}
+
 /*-------------------------------------------------------------------------*/
 
 static int __init omap2_init_devices(void)

--
To unsubscribe from this list: send the line "unsubscribe linux-omap" in
the body of a message to [email protected]
More majordomo info at  http://vger.kernel.org/majordomo-info.html

Reply via email to