Factor out the common NVMEM EUI-48 retrieval logic from of_get_mac_address_nvmem() into a new of_get_nvmem_eui48() helper that accepts the NVMEM cell name as a parameter. This allows other subsystems (e.g. Bluetooth) to reuse the same lookup-validate-copy pattern with a different cell name, without duplicating code. of_get_mac_address_nvmem() is updated to call of_get_nvmem_eui48() with "mac-address", preserving its existing behavior. Reviewed-by: Bartosz Golaszewski Signed-off-by: Loic Poulain --- include/linux/of_net.h | 7 +++++++ net/core/of_net.c | 49 +++++++++++++++++++++++++++++++++++++------------ 2 files changed, 44 insertions(+), 12 deletions(-) diff --git a/include/linux/of_net.h b/include/linux/of_net.h index d88715a0b3a52f87af23d47791bea3baf5be5200..7854ba555d9a55f3d020a37fe00a27ae52e0e5dc 100644 --- a/include/linux/of_net.h +++ b/include/linux/of_net.h @@ -15,6 +15,7 @@ struct net_device; extern int of_get_phy_mode(struct device_node *np, phy_interface_t *interface); extern int of_get_mac_address(struct device_node *np, u8 *mac); extern int of_get_mac_address_nvmem(struct device_node *np, u8 *mac); +int of_get_nvmem_eui48(struct device_node *np, const char *cell_name, u8 *addr); int of_get_ethdev_address(struct device_node *np, struct net_device *dev); extern struct net_device *of_find_net_device_by_node(struct device_node *np); #else @@ -34,6 +35,12 @@ static inline int of_get_mac_address_nvmem(struct device_node *np, u8 *mac) return -ENODEV; } +static inline int of_get_nvmem_eui48(struct device_node *np, + const char *cell_name, u8 *addr) +{ + return -ENODEV; +} + static inline int of_get_ethdev_address(struct device_node *np, struct net_device *dev) { return -ENODEV; diff --git a/net/core/of_net.c b/net/core/of_net.c index 93ea425b9248a23f4f95a336e9cdbf0053248e32..75341c186123e949fbe21f1e51fce3ac74d4f56b 100644 --- a/net/core/of_net.c +++ b/net/core/of_net.c @@ -61,9 +61,7 @@ static int of_get_mac_addr(struct device_node *np, const char *name, u8 *addr) int of_get_mac_address_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; + u8 mac[ETH_ALEN]; int ret; /* Try lookup by device first, there might be a nvmem_cell_lookup @@ -75,27 +73,54 @@ int of_get_mac_address_nvmem(struct device_node *np, u8 *addr) return ret; } - cell = of_nvmem_cell_get(np, "mac-address"); + ret = of_get_nvmem_eui48(np, "mac-address", mac); + if (ret) + return ret; + + if (!is_valid_ether_addr(mac)) + return -EINVAL; + + ether_addr_copy(addr, mac); + return 0; +} +EXPORT_SYMBOL(of_get_mac_address_nvmem); + +/** + * of_get_nvmem_eui48 - Read a 6-byte EUI-48 address from a named NVMEM cell. + * @np: Device node to look up the NVMEM cell from. + * @cell_name: Name of the NVMEM cell (e.g. "mac-address", "local-bd-address"). + * @addr: Output buffer for the 6-byte address. + * + * Reads the named NVMEM cell and validates that it contains a non-zero 6-byte + * address. Returns 0 on success, negative errno on failure. + */ +int of_get_nvmem_eui48(struct device_node *np, const char *cell_name, u8 *addr) +{ + struct nvmem_cell *cell; + const void *eui48; + size_t len; + + cell = of_nvmem_cell_get(np, cell_name); if (IS_ERR(cell)) return PTR_ERR(cell); - mac = nvmem_cell_read(cell, &len); + eui48 = nvmem_cell_read(cell, &len); nvmem_cell_put(cell); - if (IS_ERR(mac)) - return PTR_ERR(mac); + if (IS_ERR(eui48)) + return PTR_ERR(eui48); - if (len != ETH_ALEN || !is_valid_ether_addr(mac)) { - kfree(mac); + if (len != ETH_ALEN || !memchr_inv(eui48, 0, ETH_ALEN)) { + kfree(eui48); return -EINVAL; } - memcpy(addr, mac, ETH_ALEN); - kfree(mac); + memcpy(addr, eui48, ETH_ALEN); + kfree(eui48); return 0; } -EXPORT_SYMBOL(of_get_mac_address_nvmem); +EXPORT_SYMBOL_GPL(of_get_nvmem_eui48); /** * of_get_mac_address() -- 2.34.1