treewide: backport support for nvmem on non platform devices
In the current state, nvmem cells are only detected on platform device. To quickly fix the problem, we register the affected problematic driver with the of_platform but that is more an hack than a real solution. Backport from net-next the required patch so that nvmem can work also with non-platform devices and rework our current patch. Drop the mediatek and dsa workaround and rework the ath10k patches. Rework every driver that use the of_get_mac_address api. Signed-off-by: Ansuel Smith <ansuelsmth@gmail.com>
This commit is contained in:
committed by
David Bauer
parent
edb6bc1990
commit
91a52f22a1
File diff suppressed because it is too large
Load Diff
@@ -0,0 +1,77 @@
|
||||
From f10843e04a075202dbb39dfcee047e3a2fdf5a8d Mon Sep 17 00:00:00 2001
|
||||
From: Michael Walle <michael@walle.cc>
|
||||
Date: Mon, 12 Apr 2021 19:47:18 +0200
|
||||
Subject: of: net: fix of_get_mac_addr_nvmem() for non-platform devices
|
||||
|
||||
of_get_mac_address() already supports fetching the MAC address by an
|
||||
nvmem provider. But until now, it was just working for platform devices.
|
||||
Esp. it was not working for DSA ports and PCI devices. It gets more
|
||||
common that PCI devices have a device tree binding since SoCs contain
|
||||
integrated root complexes.
|
||||
|
||||
Use the nvmem of_* binding to fetch the nvmem cells by a struct
|
||||
device_node. We still have to try to read the cell by device first
|
||||
because there might be a nvmem_cell_lookup associated with that device.
|
||||
|
||||
Signed-off-by: Michael Walle <michael@walle.cc>
|
||||
Reviewed-by: Andrew Lunn <andrew@lunn.ch>
|
||||
Signed-off-by: David S. Miller <davem@davemloft.net>
|
||||
---
|
||||
drivers/of/of_net.c | 35 ++++++++++++++++++++++++++++++-----
|
||||
1 file changed, 30 insertions(+), 5 deletions(-)
|
||||
|
||||
--- a/drivers/of/of_net.c
|
||||
+++ b/drivers/of/of_net.c
|
||||
@@ -11,6 +11,7 @@
|
||||
#include <linux/phy.h>
|
||||
#include <linux/export.h>
|
||||
#include <linux/device.h>
|
||||
+#include <linux/nvmem-consumer.h>
|
||||
|
||||
/**
|
||||
* of_get_phy_mode - Get phy mode for given device_node
|
||||
@@ -59,15 +60,39 @@ static int of_get_mac_addr(struct device
|
||||
static int of_get_mac_addr_nvmem(struct device_node *np, u8 *addr)
|
||||
{
|
||||
struct platform_device *pdev = of_find_device_by_node(np);
|
||||
+ struct nvmem_cell *cell;
|
||||
+ const void *mac;
|
||||
+ size_t len;
|
||||
int ret;
|
||||
|
||||
- if (!pdev)
|
||||
- return -ENODEV;
|
||||
+ /* Try lookup by device first, there might be a nvmem_cell_lookup
|
||||
+ * associated with a given device.
|
||||
+ */
|
||||
+ if (pdev) {
|
||||
+ ret = nvmem_get_mac_address(&pdev->dev, addr);
|
||||
+ put_device(&pdev->dev);
|
||||
+ return ret;
|
||||
+ }
|
||||
+
|
||||
+ cell = of_nvmem_cell_get(np, "mac-address");
|
||||
+ if (IS_ERR(cell))
|
||||
+ return PTR_ERR(cell);
|
||||
+
|
||||
+ mac = nvmem_cell_read(cell, &len);
|
||||
+ nvmem_cell_put(cell);
|
||||
+
|
||||
+ if (IS_ERR(mac))
|
||||
+ return PTR_ERR(mac);
|
||||
+
|
||||
+ if (len != ETH_ALEN || !is_valid_ether_addr(mac)) {
|
||||
+ kfree(mac);
|
||||
+ return -EINVAL;
|
||||
+ }
|
||||
|
||||
- ret = nvmem_get_mac_address(&pdev->dev, addr);
|
||||
- put_device(&pdev->dev);
|
||||
+ memcpy(addr, mac, ETH_ALEN);
|
||||
+ kfree(mac);
|
||||
|
||||
- return ret;
|
||||
+ return 0;
|
||||
}
|
||||
|
||||
/**
|
||||
File diff suppressed because it is too large
Load Diff
@@ -0,0 +1,77 @@
|
||||
From f10843e04a075202dbb39dfcee047e3a2fdf5a8d Mon Sep 17 00:00:00 2001
|
||||
From: Michael Walle <michael@walle.cc>
|
||||
Date: Mon, 12 Apr 2021 19:47:18 +0200
|
||||
Subject: of: net: fix of_get_mac_addr_nvmem() for non-platform devices
|
||||
|
||||
of_get_mac_address() already supports fetching the MAC address by an
|
||||
nvmem provider. But until now, it was just working for platform devices.
|
||||
Esp. it was not working for DSA ports and PCI devices. It gets more
|
||||
common that PCI devices have a device tree binding since SoCs contain
|
||||
integrated root complexes.
|
||||
|
||||
Use the nvmem of_* binding to fetch the nvmem cells by a struct
|
||||
device_node. We still have to try to read the cell by device first
|
||||
because there might be a nvmem_cell_lookup associated with that device.
|
||||
|
||||
Signed-off-by: Michael Walle <michael@walle.cc>
|
||||
Reviewed-by: Andrew Lunn <andrew@lunn.ch>
|
||||
Signed-off-by: David S. Miller <davem@davemloft.net>
|
||||
---
|
||||
drivers/of/of_net.c | 35 ++++++++++++++++++++++++++++++-----
|
||||
1 file changed, 30 insertions(+), 5 deletions(-)
|
||||
|
||||
--- a/drivers/of/of_net.c
|
||||
+++ b/drivers/of/of_net.c
|
||||
@@ -11,6 +11,7 @@
|
||||
#include <linux/phy.h>
|
||||
#include <linux/export.h>
|
||||
#include <linux/device.h>
|
||||
+#include <linux/nvmem-consumer.h>
|
||||
|
||||
/**
|
||||
* of_get_phy_mode - Get phy mode for given device_node
|
||||
@@ -53,15 +54,39 @@ static int of_get_mac_addr(struct device
|
||||
static int of_get_mac_addr_nvmem(struct device_node *np, u8 *addr)
|
||||
{
|
||||
struct platform_device *pdev = of_find_device_by_node(np);
|
||||
+ struct nvmem_cell *cell;
|
||||
+ const void *mac;
|
||||
+ size_t len;
|
||||
int ret;
|
||||
|
||||
- if (!pdev)
|
||||
- return -ENODEV;
|
||||
+ /* Try lookup by device first, there might be a nvmem_cell_lookup
|
||||
+ * associated with a given device.
|
||||
+ */
|
||||
+ if (pdev) {
|
||||
+ ret = nvmem_get_mac_address(&pdev->dev, addr);
|
||||
+ put_device(&pdev->dev);
|
||||
+ return ret;
|
||||
+ }
|
||||
+
|
||||
+ cell = of_nvmem_cell_get(np, "mac-address");
|
||||
+ if (IS_ERR(cell))
|
||||
+ return PTR_ERR(cell);
|
||||
+
|
||||
+ mac = nvmem_cell_read(cell, &len);
|
||||
+ nvmem_cell_put(cell);
|
||||
+
|
||||
+ if (IS_ERR(mac))
|
||||
+ return PTR_ERR(mac);
|
||||
+
|
||||
+ if (len != ETH_ALEN || !is_valid_ether_addr(mac)) {
|
||||
+ kfree(mac);
|
||||
+ return -EINVAL;
|
||||
+ }
|
||||
|
||||
- ret = nvmem_get_mac_address(&pdev->dev, addr);
|
||||
- put_device(&pdev->dev);
|
||||
+ memcpy(addr, mac, ETH_ALEN);
|
||||
+ kfree(mac);
|
||||
|
||||
- return ret;
|
||||
+ return 0;
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -1,27 +0,0 @@
|
||||
From c94b2cfd25c282e2974accc1b07da98ae7139b47 Mon Sep 17 00:00:00 2001
|
||||
From: Ansuel Smith <ansuelsmth@gmail.com>
|
||||
Date: Fri, 23 Jul 2021 12:14:33 +0200
|
||||
Subject: [PATCH 1/2] drivers: net: mediatek: register of_platform for every
|
||||
port
|
||||
|
||||
Currently the nvmem framework require the devicenode to be registred on
|
||||
the of_platform or of_get_mac_address fail to get the macaddress if
|
||||
defined using an nvmem cell. Fix this by registrering these special node
|
||||
so they can be found by of_find_device_by_node.
|
||||
|
||||
Signed-off-by: Ansuel Smith <ansuelsmth@gmail.com>
|
||||
---
|
||||
drivers/net/ethernet/mediatek/mtk_eth_soc.c | 2 ++
|
||||
1 file changed, 2 insertions(+)
|
||||
|
||||
--- a/drivers/net/ethernet/mediatek/mtk_eth_soc.c
|
||||
+++ b/drivers/net/ethernet/mediatek/mtk_eth_soc.c
|
||||
@@ -3005,6 +3005,8 @@ static int mtk_add_mac(struct mtk_eth *e
|
||||
eth->netdev[id]->dev.of_node = np;
|
||||
|
||||
eth->netdev[id]->max_mtu = MTK_MAX_RX_LENGTH - MTK_RX_ETH_HLEN;
|
||||
+
|
||||
+ of_platform_device_create(np, NULL, NULL);
|
||||
|
||||
return 0;
|
||||
|
||||
@@ -1,35 +0,0 @@
|
||||
From 8bab551f44204fc5d43977063cd704112c17c750 Mon Sep 17 00:00:00 2001
|
||||
From: Ansuel Smith <ansuelsmth@gmail.com>
|
||||
Date: Fri, 23 Jul 2021 12:17:27 +0200
|
||||
Subject: [PATCH 2/2] dsa: register every port with of_platform
|
||||
|
||||
The declaration of a different mac-addr using the nvmem framework is
|
||||
currently broken. The dsa code use the generic of_get_mac_address where
|
||||
the nvmem function require the device node to be registred in the
|
||||
of_platform to be found by of_find_device_by_node. Register every port
|
||||
in the of_platform so they can corrently found and a custom mac-addr can
|
||||
correctly be declared using a nvmem-cell declared in the dts.
|
||||
|
||||
Signed-off-by: Ansuel Smith <ansuelsmth@gmail.com>
|
||||
---
|
||||
net/dsa/dsa2.c | 2 +
|
||||
1 file changed, 2 insertion(+)
|
||||
|
||||
--- a/net/dsa/dsa2.c
|
||||
+++ b/net/dsa/dsa2.c
|
||||
@@ -14,6 +14,7 @@
|
||||
#include <linux/rtnetlink.h>
|
||||
#include <linux/of.h>
|
||||
#include <linux/of_net.h>
|
||||
+#include <linux/of_platform.h>
|
||||
#include <net/devlink.h>
|
||||
|
||||
#include "dsa_priv.h"
|
||||
@@ -288,6 +289,7 @@ static int dsa_port_setup(struct dsa_por
|
||||
|
||||
break;
|
||||
case DSA_PORT_TYPE_USER:
|
||||
+ of_platform_device_create(dp->dn, NULL, NULL);
|
||||
dp->mac = of_get_mac_address(dp->dn);
|
||||
err = dsa_slave_create(dp);
|
||||
if (err)
|
||||
@@ -1,27 +0,0 @@
|
||||
From c94b2cfd25c282e2974accc1b07da98ae7139b47 Mon Sep 17 00:00:00 2001
|
||||
From: Ansuel Smith <ansuelsmth@gmail.com>
|
||||
Date: Fri, 23 Jul 2021 12:14:33 +0200
|
||||
Subject: [PATCH 1/2] drivers: net: mediatek: register of_platform for every
|
||||
port
|
||||
|
||||
Currently the nvmem framework require the devicenode to be registred on
|
||||
the of_platform or of_get_mac_address fail to get the macaddress if
|
||||
defined using an nvmem cell. Fix this by registrering these special node
|
||||
so they can be found by of_find_device_by_node.
|
||||
|
||||
Signed-off-by: Ansuel Smith <ansuelsmth@gmail.com>
|
||||
---
|
||||
drivers/net/ethernet/mediatek/mtk_eth_soc.c | 2 ++
|
||||
1 file changed, 2 insertions(+)
|
||||
|
||||
--- a/drivers/net/ethernet/mediatek/mtk_eth_soc.c
|
||||
+++ b/drivers/net/ethernet/mediatek/mtk_eth_soc.c
|
||||
@@ -3034,6 +3034,8 @@ static int mtk_add_mac(struct mtk_eth *e
|
||||
eth->netdev[id]->dev.of_node = np;
|
||||
|
||||
eth->netdev[id]->max_mtu = MTK_MAX_RX_LENGTH - MTK_RX_ETH_HLEN;
|
||||
+
|
||||
+ of_platform_device_create(np, NULL, NULL);
|
||||
|
||||
return 0;
|
||||
|
||||
@@ -1,35 +0,0 @@
|
||||
From 8bab551f44204fc5d43977063cd704112c17c750 Mon Sep 17 00:00:00 2001
|
||||
From: Ansuel Smith <ansuelsmth@gmail.com>
|
||||
Date: Fri, 23 Jul 2021 12:17:27 +0200
|
||||
Subject: [PATCH 2/2] dsa: register every port with of_platform
|
||||
|
||||
The declaration of a different mac-addr using the nvmem framework is
|
||||
currently broken. The dsa code use the generic of_get_mac_address where
|
||||
the nvmem function require the device node to be registred in the
|
||||
of_platform to be found by of_find_device_by_node. Register every port
|
||||
in the of_platform so they can corrently found and a custom mac-addr can
|
||||
correctly be declared using a nvmem-cell declared in the dts.
|
||||
|
||||
Signed-off-by: Ansuel Smith <ansuelsmth@gmail.com>
|
||||
---
|
||||
net/dsa/dsa2.c | 2 +
|
||||
1 file changed, 2 insertion(+)
|
||||
|
||||
--- a/net/dsa/dsa2.c
|
||||
+++ b/net/dsa/dsa2.c
|
||||
@@ -14,6 +14,7 @@
|
||||
#include <linux/rtnetlink.h>
|
||||
#include <linux/of.h>
|
||||
#include <linux/of_net.h>
|
||||
+#include <linux/of_platform.h>
|
||||
#include <net/devlink.h>
|
||||
|
||||
#include "dsa_priv.h"
|
||||
@@ -318,6 +319,7 @@ static int dsa_port_setup(struct dsa_por
|
||||
break;
|
||||
devlink_port_registered = true;
|
||||
|
||||
+ of_platform_device_create(dp->dn, NULL, NULL);
|
||||
dp->mac = of_get_mac_address(dp->dn);
|
||||
err = dsa_slave_create(dp);
|
||||
if (err)
|
||||
@@ -17,28 +17,19 @@ Signed-off-by: Ansuel Smith <ansuelsmth@gmail.com>
|
||||
|
||||
--- a/drivers/of/of_net.c
|
||||
+++ b/drivers/of/of_net.c
|
||||
@@ -11,6 +11,7 @@
|
||||
#include <linux/phy.h>
|
||||
@@ -12,6 +12,7 @@
|
||||
#include <linux/export.h>
|
||||
#include <linux/device.h>
|
||||
#include <linux/nvmem-consumer.h>
|
||||
+#include <linux/mtd/mtd.h>
|
||||
|
||||
/**
|
||||
* of_get_phy_mode - Get phy mode for given device_node
|
||||
@@ -45,7 +46,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);
|
||||
|
||||
@@ -78,6 +79,55 @@ static const void *of_get_mac_addr_nvmem
|
||||
return mac;
|
||||
@@ -95,6 +96,52 @@ static int of_get_mac_addr_nvmem(struct
|
||||
return 0;
|
||||
}
|
||||
|
||||
+static const void *of_get_mac_address_mtd(struct device_node *np)
|
||||
+static int of_get_mac_address_mtd(struct device_node *np, u8 *addr)
|
||||
+{
|
||||
+#ifdef CONFIG_MTD
|
||||
+ struct platform_device *pdev = of_find_device_by_node(np);
|
||||
@@ -50,18 +41,17 @@ Signed-off-by: Ansuel Smith <ansuelsmth@gmail.com>
|
||||
+ const __be32 *list;
|
||||
+ phandle phandle;
|
||||
+ u8 mac[ETH_ALEN];
|
||||
+ void *addr;
|
||||
+
|
||||
+ list = of_get_property(np, "mtd-mac-address", &size);
|
||||
+ if (!list || (size != (2 * sizeof(*list))))
|
||||
+ return NULL;
|
||||
+ return -ENODEV;
|
||||
+
|
||||
+ phandle = be32_to_cpup(list++);
|
||||
+ if (phandle)
|
||||
+ mtd_np = of_find_node_by_phandle(phandle);
|
||||
+
|
||||
+ if (!mtd_np)
|
||||
+ return NULL;
|
||||
+ return -ENODEV;
|
||||
+
|
||||
+ part = of_get_property(mtd_np, "label", NULL);
|
||||
+ if (!part)
|
||||
@@ -69,28 +59,26 @@ Signed-off-by: Ansuel Smith <ansuelsmth@gmail.com>
|
||||
+
|
||||
+ mtd = get_mtd_device_nm(part);
|
||||
+ if (IS_ERR(mtd))
|
||||
+ return NULL;
|
||||
+ return -ENODEV;
|
||||
+
|
||||
+ ret = mtd_read(mtd, be32_to_cpup(list), 6, &retlen, mac);
|
||||
+ put_mtd_device(mtd);
|
||||
+
|
||||
+ if (!is_valid_ether_addr(mac))
|
||||
+ return NULL;
|
||||
+ return -EINVAL;
|
||||
+
|
||||
+ addr = devm_kmemdup(&pdev->dev, mac, ETH_ALEN, GFP_KERNEL);
|
||||
+ if (!addr)
|
||||
+ return ERR_PTR(-ENOMEM);
|
||||
+ memcpy(addr, mac, ETH_ALEN);
|
||||
+
|
||||
+ return addr;
|
||||
+ return 0;
|
||||
+#endif
|
||||
+ return NULL;
|
||||
+ return -EINVAL;
|
||||
+}
|
||||
+
|
||||
+
|
||||
/**
|
||||
* 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
|
||||
@@ -98,6 +148,10 @@ static const void *of_get_mac_addr_nvmem
|
||||
@@ -115,6 +161,10 @@ static int of_get_mac_addr_nvmem(struct
|
||||
* this case, the real MAC is in 'local-mac-address', and 'mac-address' exists
|
||||
* but is all zeros.
|
||||
*
|
||||
@@ -98,17 +86,17 @@ Signed-off-by: Ansuel Smith <ansuelsmth@gmail.com>
|
||||
+ * If a mtd-mac-address property exists, try to fetch the MAC address from the
|
||||
+ * specified mtd device.
|
||||
+ *
|
||||
* Return: Will be a valid pointer on success and ERR_PTR in case of error.
|
||||
* Return: 0 on success and errno in case of error.
|
||||
*/
|
||||
const void *of_get_mac_address(struct device_node *np)
|
||||
@@ -116,6 +170,10 @@ const void *of_get_mac_address(struct de
|
||||
if (addr)
|
||||
return addr;
|
||||
int of_get_mac_address(struct device_node *np, u8 *addr)
|
||||
@@ -136,6 +186,10 @@ int of_get_mac_address(struct device_nod
|
||||
if (!ret)
|
||||
return 0;
|
||||
|
||||
+ addr = of_get_mac_address_mtd(np);
|
||||
+ if (addr)
|
||||
+ return addr;
|
||||
+ ret = of_get_mac_address_mtd(np, addr);
|
||||
+ if (!ret)
|
||||
+ return 0;
|
||||
+
|
||||
return of_get_mac_addr_nvmem(np);
|
||||
return of_get_mac_addr_nvmem(np, addr);
|
||||
}
|
||||
EXPORT_SYMBOL(of_get_mac_address);
|
||||
|
||||
@@ -20,52 +20,7 @@ Signed-off-by: Ansuel Smith <ansuelsmth@gmail.com>
|
||||
|
||||
--- a/drivers/of/of_net.c
|
||||
+++ b/drivers/of/of_net.c
|
||||
@@ -55,31 +55,36 @@ static void *of_get_mac_addr(struct devi
|
||||
return NULL;
|
||||
}
|
||||
|
||||
-static const void *of_get_mac_addr_nvmem(struct device_node *np)
|
||||
+static void *of_get_mac_addr_nvmem(struct device_node *np, int *err)
|
||||
{
|
||||
int ret;
|
||||
- const void *mac;
|
||||
+ void *mac;
|
||||
u8 nvmem_mac[ETH_ALEN];
|
||||
struct platform_device *pdev = of_find_device_by_node(np);
|
||||
|
||||
- if (!pdev)
|
||||
- return ERR_PTR(-ENODEV);
|
||||
+ if (!pdev) {
|
||||
+ *err = -ENODEV;
|
||||
+ return NULL;
|
||||
+ }
|
||||
|
||||
ret = nvmem_get_mac_address(&pdev->dev, &nvmem_mac);
|
||||
if (ret) {
|
||||
put_device(&pdev->dev);
|
||||
- return ERR_PTR(ret);
|
||||
+ *err = ret;
|
||||
+ return NULL;
|
||||
}
|
||||
|
||||
mac = devm_kmemdup(&pdev->dev, nvmem_mac, ETH_ALEN, GFP_KERNEL);
|
||||
put_device(&pdev->dev);
|
||||
- if (!mac)
|
||||
- return ERR_PTR(-ENOMEM);
|
||||
+ if (!mac) {
|
||||
+ *err = -ENOMEM;
|
||||
+ return NULL;
|
||||
+ }
|
||||
|
||||
return mac;
|
||||
}
|
||||
|
||||
-static const void *of_get_mac_address_mtd(struct device_node *np)
|
||||
+static void *of_get_mac_address_mtd(struct device_node *np)
|
||||
{
|
||||
#ifdef CONFIG_MTD
|
||||
struct platform_device *pdev = of_find_device_by_node(np);
|
||||
@@ -152,28 +157,54 @@ static const void *of_get_mac_address_mt
|
||||
@@ -165,31 +165,56 @@ static int of_get_mac_address_mtd(struct
|
||||
* If a mtd-mac-address property exists, try to fetch the MAC address from the
|
||||
* specified mtd device.
|
||||
*
|
||||
@@ -77,52 +32,53 @@ Signed-off-by: Ansuel Smith <ansuelsmth@gmail.com>
|
||||
+ * not overflow to other bytes if the increment is over 255.
|
||||
+ * (example 00:01:02:03:04:ff + 1 == 00:01:02:03:04:00)
|
||||
+ *
|
||||
* Return: Will be a valid pointer on success and ERR_PTR in case of error.
|
||||
* Return: 0 on success and errno in case of error.
|
||||
*/
|
||||
const void *of_get_mac_address(struct device_node *np)
|
||||
int of_get_mac_address(struct device_node *np, u8 *addr)
|
||||
{
|
||||
- const void *addr;
|
||||
+ u32 inc_idx, mac_inc;
|
||||
+ int ret = 0;
|
||||
+ u8 *addr;
|
||||
+
|
||||
int ret;
|
||||
|
||||
+ /* Check first if the increment byte is present and valid.
|
||||
+ * If not set assume to increment the last byte if found.
|
||||
+ */
|
||||
+ if (of_property_read_u32(np, "mac-address-increment-byte", &inc_idx))
|
||||
+ inc_idx = 5;
|
||||
+ if (inc_idx < 3 || inc_idx > 5)
|
||||
+ return ERR_PTR(-EINVAL);
|
||||
+ return -EINVAL;
|
||||
+
|
||||
if (!np)
|
||||
return -ENODEV;
|
||||
|
||||
addr = of_get_mac_addr(np, "mac-address");
|
||||
if (addr)
|
||||
- return addr;
|
||||
ret = of_get_mac_addr(np, "mac-address", addr);
|
||||
if (!ret)
|
||||
- return 0;
|
||||
+ goto found;
|
||||
|
||||
addr = of_get_mac_addr(np, "local-mac-address");
|
||||
if (addr)
|
||||
- return addr;
|
||||
ret = of_get_mac_addr(np, "local-mac-address", addr);
|
||||
if (!ret)
|
||||
- return 0;
|
||||
+ goto found;
|
||||
|
||||
addr = of_get_mac_addr(np, "address");
|
||||
if (addr)
|
||||
- return addr;
|
||||
ret = of_get_mac_addr(np, "address", addr);
|
||||
if (!ret)
|
||||
- return 0;
|
||||
+ goto found;
|
||||
|
||||
addr = of_get_mac_address_mtd(np);
|
||||
if (addr)
|
||||
- return addr;
|
||||
ret = of_get_mac_address_mtd(np, addr);
|
||||
if (!ret)
|
||||
- return 0;
|
||||
+ goto found;
|
||||
+
|
||||
+ addr = of_get_mac_addr_nvmem(np, &ret);
|
||||
+ ret = of_get_mac_addr_nvmem(np, addr);
|
||||
+ if (ret)
|
||||
+ return ERR_PTR(ret);
|
||||
+ return ret;
|
||||
+
|
||||
+found:
|
||||
+ if (!of_property_read_u32(np, "mac-address-increment", &mac_inc))
|
||||
+ addr[inc_idx] += mac_inc;
|
||||
|
||||
- return of_get_mac_addr_nvmem(np);
|
||||
+ return addr;
|
||||
- return of_get_mac_addr_nvmem(np, addr);
|
||||
+ return ret;
|
||||
}
|
||||
EXPORT_SYMBOL(of_get_mac_address);
|
||||
|
||||
@@ -1,19 +1,16 @@
|
||||
--- a/drivers/of/of_net.c
|
||||
+++ b/drivers/of/of_net.c
|
||||
@@ -132,6 +132,33 @@ static void *of_get_mac_address_mtd(stru
|
||||
return NULL;
|
||||
@@ -132,6 +132,30 @@ static void *of_get_mac_address_mtd(stru
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
+static int of_add_mac_address(struct device_node *np, u8* addr)
|
||||
+{
|
||||
+ struct property *prop;
|
||||
+ u8 *np_addr;
|
||||
+
|
||||
+ np_addr = of_get_mac_addr(np, "mac-address");
|
||||
+ if (np_addr) {
|
||||
+ memcpy(np_addr, addr, ETH_ALEN);
|
||||
+ return 0;
|
||||
+ }
|
||||
+ prop = of_find_property(np, "mac-address", NULL);
|
||||
+ if (prop)
|
||||
+ kfree(prop);
|
||||
+
|
||||
+ prop = kzalloc(sizeof(*prop), GFP_KERNEL);
|
||||
+ if (!prop)
|
||||
@@ -39,6 +36,6 @@
|
||||
addr[inc_idx] += mac_inc;
|
||||
|
||||
+ of_add_mac_address(np, addr);
|
||||
return addr;
|
||||
return ret;
|
||||
}
|
||||
EXPORT_SYMBOL(of_get_mac_address);
|
||||
|
||||
@@ -17,28 +17,19 @@ Signed-off-by: Ansuel Smith <ansuelsmth@gmail.com>
|
||||
|
||||
--- a/drivers/of/of_net.c
|
||||
+++ b/drivers/of/of_net.c
|
||||
@@ -11,6 +11,7 @@
|
||||
#include <linux/phy.h>
|
||||
@@ -12,6 +12,7 @@
|
||||
#include <linux/export.h>
|
||||
#include <linux/device.h>
|
||||
#include <linux/nvmem-consumer.h>
|
||||
+#include <linux/mtd/mtd.h>
|
||||
|
||||
/**
|
||||
* of_get_phy_mode - Get phy mode for given device_node
|
||||
@@ -39,7 +40,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);
|
||||
|
||||
@@ -72,6 +73,55 @@ static const void *of_get_mac_addr_nvmem
|
||||
return mac;
|
||||
@@ -95,6 +96,52 @@ static int of_get_mac_addr_nvmem(struct
|
||||
return 0;
|
||||
}
|
||||
|
||||
+static const void *of_get_mac_address_mtd(struct device_node *np)
|
||||
+static int of_get_mac_address_mtd(struct device_node *np, u8 *addr)
|
||||
+{
|
||||
+#ifdef CONFIG_MTD
|
||||
+ struct platform_device *pdev = of_find_device_by_node(np);
|
||||
@@ -50,18 +41,17 @@ Signed-off-by: Ansuel Smith <ansuelsmth@gmail.com>
|
||||
+ const __be32 *list;
|
||||
+ phandle phandle;
|
||||
+ u8 mac[ETH_ALEN];
|
||||
+ void *addr;
|
||||
+
|
||||
+ list = of_get_property(np, "mtd-mac-address", &size);
|
||||
+ if (!list || (size != (2 * sizeof(*list))))
|
||||
+ return NULL;
|
||||
+ return -ENODEV;
|
||||
+
|
||||
+ phandle = be32_to_cpup(list++);
|
||||
+ if (phandle)
|
||||
+ mtd_np = of_find_node_by_phandle(phandle);
|
||||
+
|
||||
+ if (!mtd_np)
|
||||
+ return NULL;
|
||||
+ return -ENODEV;
|
||||
+
|
||||
+ part = of_get_property(mtd_np, "label", NULL);
|
||||
+ if (!part)
|
||||
@@ -69,28 +59,26 @@ Signed-off-by: Ansuel Smith <ansuelsmth@gmail.com>
|
||||
+
|
||||
+ mtd = get_mtd_device_nm(part);
|
||||
+ if (IS_ERR(mtd))
|
||||
+ return NULL;
|
||||
+ return -ENODEV;
|
||||
+
|
||||
+ ret = mtd_read(mtd, be32_to_cpup(list), 6, &retlen, mac);
|
||||
+ put_mtd_device(mtd);
|
||||
+
|
||||
+ if (!is_valid_ether_addr(mac))
|
||||
+ return NULL;
|
||||
+ return -EINVAL;
|
||||
+
|
||||
+ addr = devm_kmemdup(&pdev->dev, mac, ETH_ALEN, GFP_KERNEL);
|
||||
+ if (!addr)
|
||||
+ return ERR_PTR(-ENOMEM);
|
||||
+ memcpy(addr, mac, ETH_ALEN);
|
||||
+
|
||||
+ return addr;
|
||||
+ return 0;
|
||||
+#endif
|
||||
+ return NULL;
|
||||
+ return -EINVAL;
|
||||
+}
|
||||
+
|
||||
+
|
||||
/**
|
||||
* 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
|
||||
@@ -92,6 +142,10 @@ static const void *of_get_mac_addr_nvmem
|
||||
@@ -115,6 +161,10 @@ static int of_get_mac_addr_nvmem(struct
|
||||
* this case, the real MAC is in 'local-mac-address', and 'mac-address' exists
|
||||
* but is all zeros.
|
||||
*
|
||||
@@ -98,17 +86,17 @@ Signed-off-by: Ansuel Smith <ansuelsmth@gmail.com>
|
||||
+ * If a mtd-mac-address property exists, try to fetch the MAC address from the
|
||||
+ * specified mtd device.
|
||||
+ *
|
||||
* Return: Will be a valid pointer on success and ERR_PTR in case of error.
|
||||
* Return: 0 on success and errno in case of error.
|
||||
*/
|
||||
const void *of_get_mac_address(struct device_node *np)
|
||||
@@ -110,6 +164,10 @@ const void *of_get_mac_address(struct de
|
||||
if (addr)
|
||||
return addr;
|
||||
int of_get_mac_address(struct device_node *np, u8 *addr)
|
||||
@@ -136,6 +186,10 @@ int of_get_mac_address(struct device_nod
|
||||
if (!ret)
|
||||
return 0;
|
||||
|
||||
+ addr = of_get_mac_address_mtd(np);
|
||||
+ if (addr)
|
||||
+ return addr;
|
||||
+ ret = of_get_mac_address_mtd(np, addr);
|
||||
+ if (!ret)
|
||||
+ return 0;
|
||||
+
|
||||
return of_get_mac_addr_nvmem(np);
|
||||
return of_get_mac_addr_nvmem(np, addr);
|
||||
}
|
||||
EXPORT_SYMBOL(of_get_mac_address);
|
||||
|
||||
@@ -20,52 +20,7 @@ Signed-off-by: Ansuel Smith <ansuelsmth@gmail.com>
|
||||
|
||||
--- a/drivers/of/of_net.c
|
||||
+++ b/drivers/of/of_net.c
|
||||
@@ -49,31 +49,36 @@ static void *of_get_mac_addr(struct devi
|
||||
return NULL;
|
||||
}
|
||||
|
||||
-static const void *of_get_mac_addr_nvmem(struct device_node *np)
|
||||
+static void *of_get_mac_addr_nvmem(struct device_node *np, int *err)
|
||||
{
|
||||
int ret;
|
||||
- const void *mac;
|
||||
+ void *mac;
|
||||
u8 nvmem_mac[ETH_ALEN];
|
||||
struct platform_device *pdev = of_find_device_by_node(np);
|
||||
|
||||
- if (!pdev)
|
||||
- return ERR_PTR(-ENODEV);
|
||||
+ if (!pdev) {
|
||||
+ *err = -ENODEV;
|
||||
+ return NULL;
|
||||
+ }
|
||||
|
||||
ret = nvmem_get_mac_address(&pdev->dev, &nvmem_mac);
|
||||
if (ret) {
|
||||
put_device(&pdev->dev);
|
||||
- return ERR_PTR(ret);
|
||||
+ *err = ret;
|
||||
+ return NULL;
|
||||
}
|
||||
|
||||
mac = devm_kmemdup(&pdev->dev, nvmem_mac, ETH_ALEN, GFP_KERNEL);
|
||||
put_device(&pdev->dev);
|
||||
- if (!mac)
|
||||
- return ERR_PTR(-ENOMEM);
|
||||
+ if (!mac) {
|
||||
+ *err = -ENOMEM;
|
||||
+ return NULL;
|
||||
+ }
|
||||
|
||||
return mac;
|
||||
}
|
||||
|
||||
-static const void *of_get_mac_address_mtd(struct device_node *np)
|
||||
+static void *of_get_mac_address_mtd(struct device_node *np)
|
||||
{
|
||||
#ifdef CONFIG_MTD
|
||||
struct platform_device *pdev = of_find_device_by_node(np);
|
||||
@@ -146,28 +151,54 @@ static const void *of_get_mac_address_mt
|
||||
@@ -165,31 +165,56 @@ static int of_get_mac_address_mtd(struct
|
||||
* If a mtd-mac-address property exists, try to fetch the MAC address from the
|
||||
* specified mtd device.
|
||||
*
|
||||
@@ -77,52 +32,53 @@ Signed-off-by: Ansuel Smith <ansuelsmth@gmail.com>
|
||||
+ * not overflow to other bytes if the increment is over 255.
|
||||
+ * (example 00:01:02:03:04:ff + 1 == 00:01:02:03:04:00)
|
||||
+ *
|
||||
* Return: Will be a valid pointer on success and ERR_PTR in case of error.
|
||||
* Return: 0 on success and errno in case of error.
|
||||
*/
|
||||
const void *of_get_mac_address(struct device_node *np)
|
||||
int of_get_mac_address(struct device_node *np, u8 *addr)
|
||||
{
|
||||
- const void *addr;
|
||||
+ u32 inc_idx, mac_inc;
|
||||
+ int ret = 0;
|
||||
+ u8 *addr;
|
||||
+
|
||||
int ret;
|
||||
|
||||
+ /* Check first if the increment byte is present and valid.
|
||||
+ * If not set assume to increment the last byte if found.
|
||||
+ */
|
||||
+ if (of_property_read_u32(np, "mac-address-increment-byte", &inc_idx))
|
||||
+ inc_idx = 5;
|
||||
+ if (inc_idx < 3 || inc_idx > 5)
|
||||
+ return ERR_PTR(-EINVAL);
|
||||
+ return -EINVAL;
|
||||
+
|
||||
if (!np)
|
||||
return -ENODEV;
|
||||
|
||||
addr = of_get_mac_addr(np, "mac-address");
|
||||
if (addr)
|
||||
- return addr;
|
||||
ret = of_get_mac_addr(np, "mac-address", addr);
|
||||
if (!ret)
|
||||
- return 0;
|
||||
+ goto found;
|
||||
|
||||
addr = of_get_mac_addr(np, "local-mac-address");
|
||||
if (addr)
|
||||
- return addr;
|
||||
ret = of_get_mac_addr(np, "local-mac-address", addr);
|
||||
if (!ret)
|
||||
- return 0;
|
||||
+ goto found;
|
||||
|
||||
addr = of_get_mac_addr(np, "address");
|
||||
if (addr)
|
||||
- return addr;
|
||||
ret = of_get_mac_addr(np, "address", addr);
|
||||
if (!ret)
|
||||
- return 0;
|
||||
+ goto found;
|
||||
|
||||
addr = of_get_mac_address_mtd(np);
|
||||
if (addr)
|
||||
- return addr;
|
||||
ret = of_get_mac_address_mtd(np, addr);
|
||||
if (!ret)
|
||||
- return 0;
|
||||
+ goto found;
|
||||
+
|
||||
+ addr = of_get_mac_addr_nvmem(np, &ret);
|
||||
+ ret = of_get_mac_addr_nvmem(np, addr);
|
||||
+ if (ret)
|
||||
+ return ERR_PTR(ret);
|
||||
+ return ret;
|
||||
+
|
||||
+found:
|
||||
+ if (!of_property_read_u32(np, "mac-address-increment", &mac_inc))
|
||||
+ addr[inc_idx] += mac_inc;
|
||||
|
||||
- return of_get_mac_addr_nvmem(np);
|
||||
+ return addr;
|
||||
- return of_get_mac_addr_nvmem(np, addr);
|
||||
+ return ret;
|
||||
}
|
||||
EXPORT_SYMBOL(of_get_mac_address);
|
||||
|
||||
@@ -1,19 +1,16 @@
|
||||
--- a/drivers/of/of_net.c
|
||||
+++ b/drivers/of/of_net.c
|
||||
@@ -126,6 +126,33 @@ static void *of_get_mac_address_mtd(stru
|
||||
return NULL;
|
||||
@@ -132,6 +132,30 @@ static void *of_get_mac_address_mtd(stru
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
+static int of_add_mac_address(struct device_node *np, u8* addr)
|
||||
+{
|
||||
+ struct property *prop;
|
||||
+ u8 *np_addr;
|
||||
+
|
||||
+ np_addr = of_get_mac_addr(np, "mac-address");
|
||||
+ if (np_addr) {
|
||||
+ memcpy(np_addr, addr, ETH_ALEN);
|
||||
+ return 0;
|
||||
+ }
|
||||
+ prop = of_find_property(np, "mac-address", NULL);
|
||||
+ if (prop)
|
||||
+ kfree(prop);
|
||||
+
|
||||
+ prop = kzalloc(sizeof(*prop), GFP_KERNEL);
|
||||
+ if (!prop)
|
||||
@@ -34,11 +31,11 @@
|
||||
|
||||
/**
|
||||
* Search the device tree for the best MAC address to use. 'mac-address' is
|
||||
@@ -199,6 +226,7 @@ found:
|
||||
@@ -205,6 +232,7 @@ found:
|
||||
if (!of_property_read_u32(np, "mac-address-increment", &mac_inc))
|
||||
addr[inc_idx] += mac_inc;
|
||||
|
||||
+ of_add_mac_address(np, addr);
|
||||
return addr;
|
||||
return ret;
|
||||
}
|
||||
EXPORT_SYMBOL(of_get_mac_address);
|
||||
|
||||
Reference in New Issue
Block a user