summaryrefslogtreecommitdiffstats
path: root/sys/dev
diff options
context:
space:
mode:
authorloos <loos@FreeBSD.org>2015-01-09 02:43:17 +0000
committerloos <loos@FreeBSD.org>2015-01-09 02:43:17 +0000
commit544e0536f8812fa76e463d665fcc4fa9f25680df (patch)
tree195d754f894daeb9769c64e436f8f59bc5f93323 /sys/dev
parenteee196bd333d987dc3ec8b06d507e89d58690f5a (diff)
downloadFreeBSD-src-544e0536f8812fa76e463d665fcc4fa9f25680df.zip
FreeBSD-src-544e0536f8812fa76e463d665fcc4fa9f25680df.tar.gz
MFC: r273546
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')
-rw-r--r--sys/dev/usb/net/if_smsc.c75
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 f040a25..f009183 100644
--- a/sys/dev/usb/net/if_smsc.c
+++ b/sys/dev/usb/net/if_smsc.c
@@ -1535,57 +1535,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);
}
}
OpenPOWER on IntegriCloud