[fdt] Add one more heuristic to determine MAC address of the SMSC device

- If check for net,ethernet/usb,device compatible node fails, try to find
    .../usb/hub/ethernet, where ... is bus path that can depend on actual HW.
    net,ethernet/usb,device compatibity strings are FreeBSD custom invention
    that is used only in RPi DTBs and since there is no other way to tie USB
    device to FDT node we just do our best effort here to work with upstream
    device tree

- Use -1 value to indicate invalid phandle_t, 0 is valid phandle value and
    shouldn't be used as error signal
This commit is contained in:
Oleksandr Tymoshenko 2016-10-12 19:53:10 +00:00
parent 68bd7ed102
commit 968d859d09

View File

@ -1556,6 +1556,9 @@ smsc_ioctl(struct ifnet *ifp, u_long cmd, caddr_t data)
}
#ifdef FDT
/*
* This is FreeBSD-specific compatibility strings for RPi/RPi2
*/
static phandle_t
smsc_fdt_find_eth_node(phandle_t start)
{
@ -1567,11 +1570,68 @@ smsc_fdt_find_eth_node(phandle_t start)
fdt_is_compatible(node, "usb,device"))
return (node);
child = smsc_fdt_find_eth_node(node);
if (child != 0)
if (child != -1)
return (child);
}
return (0);
return (-1);
}
/*
* Check if node's path is <*>/usb/hub/ethernet
*/
static int
smsc_fdt_is_usb_eth(phandle_t node)
{
char name[16];
int len;
memset(name, 0, sizeof(name));
len = OF_getprop(node, "name", name, sizeof(name));
if (len <= 0)
return (0);
if (strcmp(name, "ethernet"))
return (0);
node = OF_parent(node);
if (node == -1)
return (0);
len = OF_getprop(node, "name", name, sizeof(name));
if (len <= 0)
return (0);
if (strcmp(name, "hub"))
return (0);
node = OF_parent(node);
if (node == -1)
return (0);
len = OF_getprop(node, "name", name, sizeof(name));
if (len <= 0)
return (0);
if (strcmp(name, "usb"))
return (0);
return (1);
}
static phandle_t
smsc_fdt_find_eth_node_by_path(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 (smsc_fdt_is_usb_eth(node))
return (node);
child = smsc_fdt_find_eth_node_by_path(node);
if (child != -1)
return (child);
}
return (-1);
}
/**
@ -1587,8 +1647,14 @@ smsc_fdt_find_mac(unsigned char *mac)
root = OF_finddevice("/");
node = smsc_fdt_find_eth_node(root);
if (node != 0) {
/*
* If it's not FreeBSD FDT blob for RPi, try more
* generic .../usb/hub/ethernet
*/
if (node == -1)
node = smsc_fdt_find_eth_node_by_path(root);
if (node != -1) {
/* Check if there is property */
if ((len = OF_getproplen(node, "local-mac-address")) > 0) {
if (len != ETHER_ADDR_LEN)