diff options
author | loos <loos@FreeBSD.org> | 2014-10-23 13:47:19 +0000 |
---|---|---|
committer | loos <loos@FreeBSD.org> | 2014-10-23 13:47:19 +0000 |
commit | 85f9a84b9481f2d78800f7d04d5d5f381a2cda13 (patch) | |
tree | 8eaa643505c83215ad00cc3694a9a39969d4043e /sys/dev/usb | |
parent | 525706da8781a6b6adae75c89cb21fff56447cfe (diff) | |
download | FreeBSD-src-85f9a84b9481f2d78800f7d04d5d5f381a2cda13.zip FreeBSD-src-85f9a84b9481f2d78800f7d04d5d5f381a2cda13.tar.gz |
Fix a bug where some DTS layouts could cause the premature ending of the
search (i.e. without returning any result) and you would end up with a
random MAC address.
Change the search algorithm to a recursive one to ensure that all the nodes
on DTS will be verified.
The previous algorithm could not keep up if the DTS has too many sub-nodes.
While here, fix the punctuation on comments.
Diffstat (limited to 'sys/dev/usb')
-rw-r--r-- | sys/dev/usb/net/if_smsc.c | 75 |
1 files changed, 37 insertions, 38 deletions
diff --git a/sys/dev/usb/net/if_smsc.c b/sys/dev/usb/net/if_smsc.c index bd2e751..8f5e0ab 100644 --- a/sys/dev/usb/net/if_smsc.c +++ b/sys/dev/usb/net/if_smsc.c @@ -1556,57 +1556,56 @@ smsc_ioctl(struct ifnet *ifp, u_long cmd, caddr_t data) } #ifdef FDT +static phandle_t +smsc_fdt_find_eth_node(phandle_t start) +{ + phandle_t child, node; + + /* Traverse through entire tree to find usb ethernet nodes. */ + for (node = OF_child(start); node != 0; node = OF_peer(node)) { + if (fdt_is_compatible(node, "net,ethernet") && + fdt_is_compatible(node, "usb,device")) + return (node); + child = smsc_fdt_find_eth_node(node); + if (child != 0) + return (child); + } + + return (0); +} + /** - * Get MAC address from FDT blob. Firmware or loader should fill - * mac-address or local-mac-address property Returns 0 if MAC address - * obtained, error code otherwise + * Get MAC address from FDT blob. Firmware or loader should fill + * mac-address or local-mac-address property. Returns 0 if MAC address + * obtained, error code otherwise. */ static int smsc_fdt_find_mac(unsigned char *mac) { - phandle_t child, parent, root; + phandle_t node, root; int len; root = OF_finddevice("/"); - len = 0; - parent = root; + node = smsc_fdt_find_eth_node(root); + if (node != 0) { - /* Traverse through entire tree to find nodes usb ethernet nodes */ - for (child = OF_child(parent); child != 0; child = OF_peer(child)) { + /* Check if there is property */ + if ((len = OF_getproplen(node, "local-mac-address")) > 0) { + if (len != ETHER_ADDR_LEN) + return (EINVAL); - /* Find a 'leaf'. Start the search from this node. */ - while (OF_child(child)) { - parent = child; - child = OF_child(child); + OF_getprop(node, "local-mac-address", mac, + ETHER_ADDR_LEN); + return (0); } - if (fdt_is_compatible(child, "net,ethernet") && - fdt_is_compatible(child, "usb,device")) { - - /* Check if there is property */ - if ((len = OF_getproplen(child, "local-mac-address")) > 0) { - if (len != ETHER_ADDR_LEN) - return (EINVAL); + if ((len = OF_getproplen(node, "mac-address")) > 0) { + if (len != ETHER_ADDR_LEN) + return (EINVAL); - OF_getprop(child, "local-mac-address", mac, - ETHER_ADDR_LEN); - return (0); - } - - if ((len = OF_getproplen(child, "mac-address")) > 0) { - if (len != ETHER_ADDR_LEN) - return (EINVAL); - - OF_getprop(child, "mac-address", mac, - ETHER_ADDR_LEN); - return (0); - } - } - - if (OF_peer(child) == 0) { - /* No more siblings. */ - child = parent; - parent = OF_parent(child); + OF_getprop(node, "mac-address", mac, + ETHER_ADDR_LEN); + return (0); } } |