245c5f3bd6c21c1d99f866628a7cb0ca3fa52799
[openwrt/staging/981213.git] /
1 From f10843e04a075202dbb39dfcee047e3a2fdf5a8d Mon Sep 17 00:00:00 2001
2 From: Michael Walle <michael@walle.cc>
3 Date: Mon, 12 Apr 2021 19:47:18 +0200
4 Subject: of: net: fix of_get_mac_addr_nvmem() for non-platform devices
5
6 of_get_mac_address() already supports fetching the MAC address by an
7 nvmem provider. But until now, it was just working for platform devices.
8 Esp. it was not working for DSA ports and PCI devices. It gets more
9 common that PCI devices have a device tree binding since SoCs contain
10 integrated root complexes.
11
12 Use the nvmem of_* binding to fetch the nvmem cells by a struct
13 device_node. We still have to try to read the cell by device first
14 because there might be a nvmem_cell_lookup associated with that device.
15
16 Signed-off-by: Michael Walle <michael@walle.cc>
17 Reviewed-by: Andrew Lunn <andrew@lunn.ch>
18 Signed-off-by: David S. Miller <davem@davemloft.net>
19 ---
20 drivers/of/of_net.c | 35 ++++++++++++++++++++++++++++++-----
21 1 file changed, 30 insertions(+), 5 deletions(-)
22
23 --- a/drivers/of/of_net.c
24 +++ b/drivers/of/of_net.c
25 @@ -11,6 +11,7 @@
26 #include <linux/phy.h>
27 #include <linux/export.h>
28 #include <linux/device.h>
29 +#include <linux/nvmem-consumer.h>
30
31 /**
32 * of_get_phy_mode - Get phy mode for given device_node
33 @@ -59,15 +60,39 @@ static int of_get_mac_addr(struct device
34 static int of_get_mac_addr_nvmem(struct device_node *np, u8 *addr)
35 {
36 struct platform_device *pdev = of_find_device_by_node(np);
37 + struct nvmem_cell *cell;
38 + const void *mac;
39 + size_t len;
40 int ret;
41
42 - if (!pdev)
43 - return -ENODEV;
44 + /* Try lookup by device first, there might be a nvmem_cell_lookup
45 + * associated with a given device.
46 + */
47 + if (pdev) {
48 + ret = nvmem_get_mac_address(&pdev->dev, addr);
49 + put_device(&pdev->dev);
50 + return ret;
51 + }
52 +
53 + cell = of_nvmem_cell_get(np, "mac-address");
54 + if (IS_ERR(cell))
55 + return PTR_ERR(cell);
56 +
57 + mac = nvmem_cell_read(cell, &len);
58 + nvmem_cell_put(cell);
59 +
60 + if (IS_ERR(mac))
61 + return PTR_ERR(mac);
62 +
63 + if (len != ETH_ALEN || !is_valid_ether_addr(mac)) {
64 + kfree(mac);
65 + return -EINVAL;
66 + }
67
68 - ret = nvmem_get_mac_address(&pdev->dev, addr);
69 - put_device(&pdev->dev);
70 + memcpy(addr, mac, ETH_ALEN);
71 + kfree(mac);
72
73 - return ret;
74 + return 0;
75 }
76
77 /**