kernel: fix bugs added with mac-address-ascii support
[openwrt/openwrt.git] / target / linux / generic / hack-5.10 / 601-of_net-add-mac-address-ascii-support.patch
1 From: Yousong Zhou <yszhou4tech@gmail.com>
2 Subject: [PATCH] ath79: add nvmem cell mac-address-ascii support
3
4 This is needed for devices with mac address stored in ascii format, e.g.
5 HiWiFi HC6361 to be ported in the following patch.
6
7 Submitted-by: Yousong Zhou <yszhou4tech@gmail.com>
8 ---
9 net/ethernet/eth.c | 83 ++++++++++++------
10 1 files changed, 72 insertions(+), 11 deletions(-)
11
12 --- a/net/ethernet/eth.c
13 +++ b/net/ethernet/eth.c
14 @@ -539,6 +539,63 @@ int eth_platform_get_mac_address(struct
15 }
16 EXPORT_SYMBOL(eth_platform_get_mac_address);
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 /**
76 * Obtain the MAC address from an nvmem cell named 'mac-address' associated
77 * with given device.
78 @@ -550,21 +607,28 @@ EXPORT_SYMBOL(eth_platform_get_mac_addre
79 */
80 int nvmem_get_mac_address(struct device *dev, void *addrbuf)
81 {
82 + struct nvmem_cell_mac_address_property *property;
83 struct nvmem_cell *cell;
84 const void *mac;
85 - size_t len;
86 + int i;
87 +
88 + for (i = 0; i < ARRAY_SIZE(nvmem_cell_mac_address_properties); i++) {
89 + property = &nvmem_cell_mac_address_properties[i];
90 + cell = nvmem_cell_get(dev, property->name);
91 + /* For -EPROBE_DEFER don't try other properties. We'll get back to this one. */
92 + if (!IS_ERR(cell) || PTR_ERR(cell) == -EPROBE_DEFER)
93 + break;
94 + }
95
96 - cell = nvmem_cell_get(dev, "mac-address");
97 if (IS_ERR(cell))
98 return PTR_ERR(cell);
99
100 - mac = nvmem_cell_read(cell, &len);
101 + mac = property->read(cell);
102 nvmem_cell_put(cell);
103 -
104 if (IS_ERR(mac))
105 return PTR_ERR(mac);
106
107 - if (len != ETH_ALEN || !is_valid_ether_addr(mac)) {
108 + if (!is_valid_ether_addr(mac)) {
109 kfree(mac);
110 return -EINVAL;
111 }