treewide: backport support for nvmem on non platform devices

This commit is contained in:
Ansuel Smith 2021-07-23 20:19:43 +02:00 committed by AmadeusGhost
parent 5ac4c8546c
commit 7a7f9d647d
10 changed files with 4171 additions and 280 deletions

View File

@ -1519,7 +1519,6 @@ static int ag71xx_probe(struct platform_device *pdev)
struct net_device *dev;
struct resource *res;
struct ag71xx *ag;
const void *mac_addr;
u32 max_frame_len;
int tx_size, err;
@ -1668,12 +1667,10 @@ static int ag71xx_probe(struct platform_device *pdev)
ag->stop_desc->ctrl = 0;
ag->stop_desc->next = (u32) ag->stop_desc_dma;
mac_addr = of_get_mac_address(np);
if (IS_ERR_OR_NULL(mac_addr) || !is_valid_ether_addr(mac_addr)) {
of_get_mac_address(np, dev->dev_addr);
if (!is_valid_ether_addr(dev->dev_addr)) {
dev_err(&pdev->dev, "invalid MAC address, using random address\n");
eth_random_addr(dev->dev_addr);
} else {
memcpy(dev->dev_addr, mac_addr, ETH_ALEN);
}
#if LINUX_VERSION_CODE >= KERNEL_VERSION(5,10,0)

View File

@ -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;
}
/**

View File

@ -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;
}
/**

View File

@ -0,0 +1,102 @@
From 6f8e5369ae054ec6c9265581d5a7e39738a5cd84 Mon Sep 17 00:00:00 2001
From: Ansuel Smith <ansuelsmth@gmail.com>
Date: Tue, 30 Mar 2021 13:16:38 +0200
Subject: [PATCH 1/2] NET: add mtd-mac-address support to of_get_mac_address()
Many embedded devices have information such as mac addresses stored inside mtd
devices. This patch allows us to add a property inside a node describing a
network interface. The new property points at a mtd partition with an offset
where the mac address can be found.
Signed-off-by: John Crispin <blogic@openwrt.org>
Signed-off-by: Felix Fietkau <nbd@nbd.name>
Signed-off-by: Ansuel Smith <ansuelsmth@gmail.com>
---
drivers/of/of_net.c | 75 ++++++++++++++++++++++++++++++++++++++++++++-
1 file changed, 74 insertions(+), 1 deletion(-)
--- a/drivers/of/of_net.c
+++ b/drivers/of/of_net.c
@@ -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
@@ -95,6 +96,52 @@ static int of_get_mac_addr_nvmem(struct
return 0;
}
+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);
+ struct device_node *mtd_np = NULL;
+ size_t retlen;
+ int size, ret;
+ struct mtd_info *mtd;
+ const char *part;
+ const __be32 *list;
+ phandle phandle;
+ u8 mac[ETH_ALEN];
+
+ list = of_get_property(np, "mtd-mac-address", &size);
+ if (!list || (size != (2 * sizeof(*list))))
+ return -ENODEV;
+
+ phandle = be32_to_cpup(list++);
+ if (phandle)
+ mtd_np = of_find_node_by_phandle(phandle);
+
+ if (!mtd_np)
+ return -ENODEV;
+
+ part = of_get_property(mtd_np, "label", NULL);
+ if (!part)
+ part = mtd_np->name;
+
+ mtd = get_mtd_device_nm(part);
+ if (IS_ERR(mtd))
+ return -ENODEV;
+
+ ret = mtd_read(mtd, be32_to_cpup(list), 6, &retlen, mac);
+ put_mtd_device(mtd);
+
+ if (!is_valid_ether_addr(mac))
+ return -EINVAL;
+
+ memcpy(addr, mac, ETH_ALEN);
+
+ return 0;
+#endif
+ 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
@@ -115,6 +162,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.
*
+ *
+ * If a mtd-mac-address property exists, try to fetch the MAC address from the
+ * specified mtd device.
+ *
* Return: 0 on success and errno in case of error.
*/
int of_get_mac_address(struct device_node *np, u8 *addr)
@@ -136,6 +187,10 @@ int of_get_mac_address(struct device_nod
if (!ret)
return 0;
+ ret = of_get_mac_address_mtd(np, addr);
+ if (!ret)
+ return 0;
+
return of_get_mac_addr_nvmem(np, addr);
}
EXPORT_SYMBOL(of_get_mac_address);

View File

@ -1,135 +0,0 @@
From: John Crispin <blogic@openwrt.org>
Subject: NET: add mtd-mac-address support to of_get_mac_address()
Many embedded devices have information such as mac addresses stored inside mtd
devices. This patch allows us to add a property inside a node describing a
network interface. The new property points at a mtd partition with an offset
where the mac address can be found.
Signed-off-by: John Crispin <blogic@openwrt.org>
Signed-off-by: Felix Fietkau <nbd@nbd.name>
---
drivers/of/of_net.c | 37 +++++++++++++++++++++++++++++++++++++
include/linux/of_net.h | 1 +
2 files changed, 38 insertions(+)
--- 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/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,79 @@ static const void *of_get_mac_addr_nvmem
return mac;
}
+static const void *of_get_mac_address_mtd(struct device_node *np)
+{
+#ifdef CONFIG_MTD
+ struct device_node *mtd_np = NULL;
+ struct property *prop;
+ size_t retlen;
+ int size, ret;
+ struct mtd_info *mtd;
+ const char *part;
+ const __be32 *list;
+ phandle phandle;
+ u32 mac_inc = 0;
+ u8 mac[ETH_ALEN];
+ void *addr;
+ u32 inc_idx;
+
+ list = of_get_property(np, "mtd-mac-address", &size);
+ if (!list || (size != (2 * sizeof(*list))))
+ return NULL;
+
+ phandle = be32_to_cpup(list++);
+ if (phandle)
+ mtd_np = of_find_node_by_phandle(phandle);
+
+ if (!mtd_np)
+ return NULL;
+
+ part = of_get_property(mtd_np, "label", NULL);
+ if (!part)
+ part = mtd_np->name;
+
+ mtd = get_mtd_device_nm(part);
+ if (IS_ERR(mtd))
+ return NULL;
+
+ ret = mtd_read(mtd, be32_to_cpup(list), 6, &retlen, mac);
+ put_mtd_device(mtd);
+
+ if (of_property_read_u32(np, "mtd-mac-address-increment-byte", &inc_idx))
+ inc_idx = 5;
+ if (inc_idx > 5)
+ return NULL;
+
+ if (!of_property_read_u32(np, "mtd-mac-address-increment", &mac_inc))
+ mac[inc_idx] += mac_inc;
+
+ if (!is_valid_ether_addr(mac))
+ return NULL;
+
+ addr = of_get_mac_addr(np, "mac-address");
+ if (addr) {
+ memcpy(addr, mac, ETH_ALEN);
+ return addr;
+ }
+
+ prop = kzalloc(sizeof(*prop), GFP_KERNEL);
+ if (!prop)
+ return NULL;
+
+ prop->name = "mac-address";
+ prop->length = ETH_ALEN;
+ prop->value = kmemdup(mac, ETH_ALEN, GFP_KERNEL);
+ if (!prop->value || of_add_property(np, prop))
+ goto free;
+
+ return prop->value;
+free:
+ kfree(prop->value);
+ kfree(prop);
+#endif
+ return NULL;
+}
+
/**
* 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,12 +172,20 @@ static const void *of_get_mac_addr_nvmem
* this case, the real MAC is in 'local-mac-address', and 'mac-address' exists
* but is all zeros.
*
+ *
+ * If a mtd-mac-address property exists, try to fetch the MAC address from the
+ * specified mtd device, and store it as a 'mac-address' property
+ *
* Return: Will be a valid pointer on success and ERR_PTR in case of error.
*/
const void *of_get_mac_address(struct device_node *np)
{
const void *addr;
+ addr = of_get_mac_address_mtd(np);
+ if (addr)
+ return addr;
+
addr = of_get_mac_addr(np, "mac-address");
if (addr)
return addr;

View File

@ -0,0 +1,102 @@
From 6f8e5369ae054ec6c9265581d5a7e39738a5cd84 Mon Sep 17 00:00:00 2001
From: Ansuel Smith <ansuelsmth@gmail.com>
Date: Tue, 30 Mar 2021 13:16:38 +0200
Subject: [PATCH 1/2] NET: add mtd-mac-address support to of_get_mac_address()
Many embedded devices have information such as mac addresses stored inside mtd
devices. This patch allows us to add a property inside a node describing a
network interface. The new property points at a mtd partition with an offset
where the mac address can be found.
Signed-off-by: John Crispin <blogic@openwrt.org>
Signed-off-by: Felix Fietkau <nbd@nbd.name>
Signed-off-by: Ansuel Smith <ansuelsmth@gmail.com>
---
drivers/of/of_net.c | 75 ++++++++++++++++++++++++++++++++++++++++++++-
1 file changed, 74 insertions(+), 1 deletion(-)
--- a/drivers/of/of_net.c
+++ b/drivers/of/of_net.c
@@ -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
@@ -89,6 +90,52 @@ static int of_get_mac_addr_nvmem(struct
return 0;
}
+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);
+ struct device_node *mtd_np = NULL;
+ size_t retlen;
+ int size, ret;
+ struct mtd_info *mtd;
+ const char *part;
+ const __be32 *list;
+ phandle phandle;
+ u8 mac[ETH_ALEN];
+
+ list = of_get_property(np, "mtd-mac-address", &size);
+ if (!list || (size != (2 * sizeof(*list))))
+ return -ENODEV;
+
+ phandle = be32_to_cpup(list++);
+ if (phandle)
+ mtd_np = of_find_node_by_phandle(phandle);
+
+ if (!mtd_np)
+ return -ENODEV;
+
+ part = of_get_property(mtd_np, "label", NULL);
+ if (!part)
+ part = mtd_np->name;
+
+ mtd = get_mtd_device_nm(part);
+ if (IS_ERR(mtd))
+ return -ENODEV;
+
+ ret = mtd_read(mtd, be32_to_cpup(list), 6, &retlen, mac);
+ put_mtd_device(mtd);
+
+ if (!is_valid_ether_addr(mac))
+ return -EINVAL;
+
+ memcpy(addr, mac, ETH_ALEN);
+
+ return 0;
+#endif
+ 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
@@ -109,6 +156,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.
*
+ *
+ * If a mtd-mac-address property exists, try to fetch the MAC address from the
+ * specified mtd device.
+ *
* Return: 0 on success and errno in case of error.
*/
int of_get_mac_address(struct device_node *np, u8 *addr)
@@ -130,6 +181,10 @@ int of_get_mac_address(struct device_nod
if (!ret)
return 0;
+ ret = of_get_mac_address_mtd(np, addr);
+ if (!ret)
+ return 0;
+
return of_get_mac_addr_nvmem(np, addr);
}
EXPORT_SYMBOL(of_get_mac_address);

View File

@ -1,135 +0,0 @@
From: John Crispin <blogic@openwrt.org>
Subject: NET: add mtd-mac-address support to of_get_mac_address()
Many embedded devices have information such as mac addresses stored inside mtd
devices. This patch allows us to add a property inside a node describing a
network interface. The new property points at a mtd partition with an offset
where the mac address can be found.
Signed-off-by: John Crispin <blogic@openwrt.org>
Signed-off-by: Felix Fietkau <nbd@nbd.name>
---
drivers/of/of_net.c | 37 +++++++++++++++++++++++++++++++++++++
include/linux/of_net.h | 1 +
2 files changed, 38 insertions(+)
--- 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/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,79 @@ static const void *of_get_mac_addr_nvmem
return mac;
}
+static const void *of_get_mac_address_mtd(struct device_node *np)
+{
+#ifdef CONFIG_MTD
+ struct device_node *mtd_np = NULL;
+ struct property *prop;
+ size_t retlen;
+ int size, ret;
+ struct mtd_info *mtd;
+ const char *part;
+ const __be32 *list;
+ phandle phandle;
+ u32 mac_inc = 0;
+ u8 mac[ETH_ALEN];
+ void *addr;
+ u32 inc_idx;
+
+ list = of_get_property(np, "mtd-mac-address", &size);
+ if (!list || (size != (2 * sizeof(*list))))
+ return NULL;
+
+ phandle = be32_to_cpup(list++);
+ if (phandle)
+ mtd_np = of_find_node_by_phandle(phandle);
+
+ if (!mtd_np)
+ return NULL;
+
+ part = of_get_property(mtd_np, "label", NULL);
+ if (!part)
+ part = mtd_np->name;
+
+ mtd = get_mtd_device_nm(part);
+ if (IS_ERR(mtd))
+ return NULL;
+
+ ret = mtd_read(mtd, be32_to_cpup(list), 6, &retlen, mac);
+ put_mtd_device(mtd);
+
+ if (of_property_read_u32(np, "mtd-mac-address-increment-byte", &inc_idx))
+ inc_idx = 5;
+ if (inc_idx > 5)
+ return NULL;
+
+ if (!of_property_read_u32(np, "mtd-mac-address-increment", &mac_inc))
+ mac[inc_idx] += mac_inc;
+
+ if (!is_valid_ether_addr(mac))
+ return NULL;
+
+ addr = of_get_mac_addr(np, "mac-address");
+ if (addr) {
+ memcpy(addr, mac, ETH_ALEN);
+ return addr;
+ }
+
+ prop = kzalloc(sizeof(*prop), GFP_KERNEL);
+ if (!prop)
+ return NULL;
+
+ prop->name = "mac-address";
+ prop->length = ETH_ALEN;
+ prop->value = kmemdup(mac, ETH_ALEN, GFP_KERNEL);
+ if (!prop->value || of_add_property(np, prop))
+ goto free;
+
+ return prop->value;
+free:
+ kfree(prop->value);
+ kfree(prop);
+#endif
+ return NULL;
+}
+
/**
* 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,12 +166,20 @@ static const void *of_get_mac_addr_nvmem
* this case, the real MAC is in 'local-mac-address', and 'mac-address' exists
* but is all zeros.
*
+ *
+ * If a mtd-mac-address property exists, try to fetch the MAC address from the
+ * specified mtd device, and store it as a 'mac-address' property
+ *
* Return: Will be a valid pointer on success and ERR_PTR in case of error.
*/
const void *of_get_mac_address(struct device_node *np)
{
const void *addr;
+ addr = of_get_mac_address_mtd(np);
+ if (addr)
+ return addr;
+
addr = of_get_mac_addr(np, "mac-address");
if (addr)
return addr;

View File

@ -904,8 +904,6 @@ static int edma_axi_probe(struct platform_device *pdev)
}
for_each_available_child_of_node(np, pnp) {
const char *mac_addr;
/* this check is needed if parent and daughter dts have
* different number of gmac nodes
*/
@ -914,9 +912,7 @@ static int edma_axi_probe(struct platform_device *pdev)
break;
}
mac_addr = of_get_mac_address(pnp);
if (!IS_ERR(mac_addr))
memcpy(edma_netdev[idx_mac]->dev_addr, mac_addr, ETH_ALEN);
of_get_mac_address(pnp, edma_netdev[idx_mac]->dev_addr);
idx_mac++;
}