treewide: fix replace nbd@openwrt.org with nbd@nbd.name
[openwrt.org/openwrt.git] / target / linux / generic / patches-4.4 / 681-NET-add-of_get_mac_address_mtd.patch
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
From: John Crispin <blogic@openwrt.org>
Date: Sun, 27 Jul 2014 09:40:01 +0100
Subject: NET: add mtd-mac-address support to of_get_mac_address()
 
Many embedded devices have information such as mac addresses stored inside mtd
devices. This patch allows us to add a property inside a node describing a
network interface. The new property points at a mtd partition with an offset
where the mac address can be found.
 
Signed-off-by: John Crispin <blogic@openwrt.org>
Signed-off-by: Felix Fietkau <nbd@nbd.name>
---
 drivers/of/of_net.c    |   37 +++++++++++++++++++++++++++++++++++++
 include/linux/of_net.h |    1 +
 2 files changed, 38 insertions(+)
 
--- a/drivers/of/of_net.c
+++ b/drivers/of/of_net.c
@@ -10,6 +10,7 @@
 #include <linux/of_net.h>
 #include <linux/phy.h>
 #include <linux/export.h>
+#include <linux/mtd/mtd.h>
 
 /**
  * of_get_phy_mode - Get phy mode for given device_node
@@ -38,7 +39,7 @@ int of_get_phy_mode(struct device_node *
 }
 EXPORT_SYMBOL_GPL(of_get_phy_mode);
 
-static const void *of_get_mac_addr(struct device_node *np, const char *name)
+static void *of_get_mac_addr(struct device_node *np, const char *name)
 {
        struct property *pp = of_find_property(np, name, NULL);
 
@@ -47,6 +48,73 @@ static const void *of_get_mac_addr(struc
        return NULL;
 }
 
+static const void *of_get_mac_address_mtd(struct device_node *np)
+{
+#ifdef CONFIG_MTD
+       struct device_node *mtd_np = NULL;
+       struct property *prop;
+       size_t retlen;
+       int size, ret;
+       struct mtd_info *mtd;
+       const char *part;
+       const __be32 *list;
+       phandle phandle;
+       u32 mac_inc = 0;
+       u8 mac[ETH_ALEN];
+       void *addr;
+
+       list = of_get_property(np, "mtd-mac-address", &size);
+       if (!list || (size != (2 * sizeof(*list))))
+               return NULL;
+
+       phandle = be32_to_cpup(list++);
+       if (phandle)
+               mtd_np = of_find_node_by_phandle(phandle);
+
+       if (!mtd_np)
+               return NULL;
+
+       part = of_get_property(mtd_np, "label", NULL);
+       if (!part)
+               part = mtd_np->name;
+
+       mtd = get_mtd_device_nm(part);
+       if (IS_ERR(mtd))
+               return NULL;
+
+       ret = mtd_read(mtd, be32_to_cpup(list), 6, &retlen, mac);
+       put_mtd_device(mtd);
+
+       if (!of_property_read_u32(np, "mtd-mac-address-increment", &mac_inc))
+               mac[5] += mac_inc;
+
+       if (!is_valid_ether_addr(mac))
+               return NULL;
+
+       addr = of_get_mac_addr(np, "mac-address");
+       if (addr) {
+               memcpy(addr, mac, ETH_ALEN);
+               return addr;
+       }
+
+       prop = kzalloc(sizeof(*prop), GFP_KERNEL);
+       if (!prop)
+               return NULL;
+
+       prop->name = "mac-address";
+       prop->length = ETH_ALEN;
+       prop->value = kmemdup(mac, ETH_ALEN, GFP_KERNEL);
+       if (!prop->value || of_add_property(np, prop))
+               goto free;
+
+       return prop->value;
+free:
+       kfree(prop->value);
+       kfree(prop);
+#endif
+       return NULL;
+}
+
 /**
  * Search the device tree for the best MAC address to use.  'mac-address' is
  * checked first, because that is supposed to contain to "most recent" MAC
@@ -64,11 +132,18 @@ static const void *of_get_mac_addr(struc
  * addresses.  Some older U-Boots only initialized 'local-mac-address'.  In
  * this case, the real MAC is in 'local-mac-address', and 'mac-address' exists
  * but is all zeros.
+ *
+ * If a mtd-mac-address property exists, try to fetch the MAC address from the
+ * specified mtd device, and store it as a 'mac-address' property
 */
 const void *of_get_mac_address(struct device_node *np)
 {
        const void *addr;
 
+       addr = of_get_mac_address_mtd(np);
+       if (addr)
+               return addr;
+
        addr = of_get_mac_addr(np, "mac-address");
        if (addr)
                return addr;
 
comments