Message ID | 20210405164643.21130-3-michael@walle.cc (mailing list archive) |
---|---|
State | New, archived |
Headers | show |
Series | of: net: support non-platform devices in of_get_mac_address() | expand |
On Mon, Apr 5, 2021 at 11:47 AM Michael Walle <michael@walle.cc> wrote: > > 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> > --- > Please note, that I've kept the nvmem_get_mac_address() which operates > on a device. The new of_get_mac_addr_nvmem() is almost identical and > there are no users of the former function right now, but it seems to be > the "newer" version to get the MAC address for a "struct device". Thus > I've kept it. Please advise, if I should kill it though. It seems kind of backwards from how we normally design this type of API where the API with a struct device will call a firmware specific version if there's a firmware handle. But certainly, I don't think we should be operating on platform device if we can help it. > drivers/of/of_net.c | 37 +++++++++++++++++++++++++++++++------ > 1 file changed, 31 insertions(+), 6 deletions(-) > > diff --git a/drivers/of/of_net.c b/drivers/of/of_net.c > index 2344ad7fff5e..2323c6063eaf 100644 > --- 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 > @@ -56,18 +57,42 @@ static int of_get_mac_addr(struct device_node *np, const char *name, u8 *addr) > return -ENODEV; > } > > -static int of_get_mac_addr_nvmem(struct device_node *np, u8 addr) > +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); > + ether_addr_copy(addr, mac); > + kfree(mac); > > - return ret; > + return 0; > } > > /** > -- > 2.20.1 >
diff --git a/drivers/of/of_net.c b/drivers/of/of_net.c index 2344ad7fff5e..2323c6063eaf 100644 --- 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 @@ -56,18 +57,42 @@ static int of_get_mac_addr(struct device_node *np, const char *name, u8 *addr) return -ENODEV; } -static int of_get_mac_addr_nvmem(struct device_node *np, u8 addr) +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); + ether_addr_copy(addr, mac); + kfree(mac); - return ret; + return 0; } /**
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> --- Please note, that I've kept the nvmem_get_mac_address() which operates on a device. The new of_get_mac_addr_nvmem() is almost identical and there are no users of the former function right now, but it seems to be the "newer" version to get the MAC address for a "struct device". Thus I've kept it. Please advise, if I should kill it though. drivers/of/of_net.c | 37 +++++++++++++++++++++++++++++++------ 1 file changed, 31 insertions(+), 6 deletions(-)