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