generic: update nvmem cell mac-address-ascii support
[openwrt/staging/dedeckeh.git] / target / linux / generic / hack-5.15 / 601-of_net-add-mac-address-ascii-support.patch
1 From: Yousong Zhou <yszhou4tech@gmail.com>
2 Subject: [PATCH] of: net: add nvmem cell mac-address-ascii support
3
4 This is needed for devices with mac address stored in ascii format,
5 e.g. HiWiFi HC6361 to be ported in the following patch.
6
7 Submitted-by: Yousong Zhou <yszhou4tech@gmail.com>
8 ---
9 net/core/of_net.c | 83 ++++++++++++------
10 1 files changed, 72 insertions(+), 11 deletions(-)
11
12 --- a/net/core/of_net.c
13 +++ b/net/core/of_net.c
14 @@ -57,13 +57,70 @@ static int of_get_mac_addr(struct device
15 return -ENODEV;
16 }
17
18 +static void *nvmem_cell_get_mac_address(struct nvmem_cell *cell)
19 +{
20 + size_t len;
21 + void *mac;
22 +
23 + mac = nvmem_cell_read(cell, &len);
24 + if (IS_ERR(mac))
25 + return mac;
26 + if (len != ETH_ALEN) {
27 + kfree(mac);
28 + return ERR_PTR(-EINVAL);
29 + }
30 + return mac;
31 +}
32 +
33 +static void *nvmem_cell_get_mac_address_ascii(struct nvmem_cell *cell)
34 +{
35 + size_t len;
36 + int ret;
37 + void *mac_ascii;
38 + u8 *mac;
39 +
40 + mac_ascii = nvmem_cell_read(cell, &len);
41 + if (IS_ERR(mac_ascii))
42 + return mac_ascii;
43 + if (len != ETH_ALEN*2+5) {
44 + kfree(mac_ascii);
45 + return ERR_PTR(-EINVAL);
46 + }
47 + mac = kmalloc(ETH_ALEN, GFP_KERNEL);
48 + if (!mac) {
49 + kfree(mac_ascii);
50 + return ERR_PTR(-ENOMEM);
51 + }
52 + ret = sscanf(mac_ascii, "%2hhx:%2hhx:%2hhx:%2hhx:%2hhx:%2hhx",
53 + &mac[0], &mac[1], &mac[2],
54 + &mac[3], &mac[4], &mac[5]);
55 + kfree(mac_ascii);
56 + if (ret == ETH_ALEN)
57 + return mac;
58 + kfree(mac);
59 + return ERR_PTR(-EINVAL);
60 +}
61 +
62 +static struct nvmem_cell_mac_address_property {
63 + char *name;
64 + void *(*read)(struct nvmem_cell *);
65 +} nvmem_cell_mac_address_properties[] = {
66 + {
67 + .name = "mac-address",
68 + .read = nvmem_cell_get_mac_address,
69 + }, {
70 + .name = "mac-address-ascii",
71 + .read = nvmem_cell_get_mac_address_ascii,
72 + },
73 +};
74 +
75 static int of_get_mac_addr_nvmem(struct device_node *np, u8 *addr)
76 {
77 struct platform_device *pdev = of_find_device_by_node(np);
78 + struct nvmem_cell_mac_address_property *property;
79 struct nvmem_cell *cell;
80 const void *mac;
81 - size_t len;
82 - int ret;
83 + int ret, i;
84
85 /* Try lookup by device first, there might be a nvmem_cell_lookup
86 * associated with a given device.
87 @@ -74,17 +131,26 @@ static int of_get_mac_addr_nvmem(struct
88 return ret;
89 }
90
91 - cell = of_nvmem_cell_get(np, "mac-address");
92 + for (i = 0; i < ARRAY_SIZE(nvmem_cell_mac_address_properties); i++) {
93 + property = &nvmem_cell_mac_address_properties[i];
94 + cell = of_nvmem_cell_get(np, property->name);
95 + /* For -EPROBE_DEFER don't try other properties.
96 + * We'll get back to this one.
97 + */
98 + if (!IS_ERR(cell) || PTR_ERR(cell) == -EPROBE_DEFER)
99 + break;
100 + }
101 +
102 if (IS_ERR(cell))
103 return PTR_ERR(cell);
104
105 - mac = nvmem_cell_read(cell, &len);
106 + mac = property->read(cell);
107 nvmem_cell_put(cell);
108
109 if (IS_ERR(mac))
110 return PTR_ERR(mac);
111
112 - if (len != ETH_ALEN || !is_valid_ether_addr(mac)) {
113 + if (!is_valid_ether_addr(mac)) {
114 kfree(mac);
115 return -EINVAL;
116 }