diff options
Diffstat (limited to 'drivers/staging/fsl-dpaa2/ethsw/ethsw.c')
-rw-r--r-- | drivers/staging/fsl-dpaa2/ethsw/ethsw.c | 59 |
1 files changed, 58 insertions, 1 deletions
diff --git a/drivers/staging/fsl-dpaa2/ethsw/ethsw.c b/drivers/staging/fsl-dpaa2/ethsw/ethsw.c index a8fc9bcf3b8a..2fb75a7c9314 100644 --- a/drivers/staging/fsl-dpaa2/ethsw/ethsw.c +++ b/drivers/staging/fsl-dpaa2/ethsw/ethsw.c @@ -468,6 +468,7 @@ static int port_carrier_state_sync(struct net_device *netdev) netif_carrier_off(netdev); port_priv->link_state = state.up; } + return 0; } @@ -690,6 +691,46 @@ err_map: return err; } +static int ethsw_port_set_mac_addr(struct ethsw_port_priv *port_priv) +{ + struct ethsw_core *ethsw = port_priv->ethsw_data; + struct net_device *net_dev = port_priv->netdev; + struct device *dev = net_dev->dev.parent; + u8 mac_addr[ETH_ALEN]; + int err; + + if (!(ethsw->features & ETHSW_FEATURE_MAC_ADDR)) + return 0; + + /* Get firmware address, if any */ + err = dpsw_if_get_port_mac_addr(ethsw->mc_io, 0, ethsw->dpsw_handle, + port_priv->idx, mac_addr); + if (err) { + dev_err(dev, "dpsw_if_get_port_mac_addr() failed\n"); + return err; + } + + /* First check if firmware has any address configured by bootloader */ + if (!is_zero_ether_addr(mac_addr)) { + memcpy(net_dev->dev_addr, mac_addr, net_dev->addr_len); + } else { + /* No MAC address configured, fill in net_dev->dev_addr + * with a random one + */ + eth_hw_addr_random(net_dev); + dev_dbg_once(dev, "device(s) have all-zero hwaddr, replaced with random\n"); + + /* Override NET_ADDR_RANDOM set by eth_hw_addr_random(); for all + * practical purposes, this will be our "permanent" mac address, + * at least until the next reboot. This move will also permit + * register_netdevice() to properly fill up net_dev->perm_addr. + */ + net_dev->addr_assign_type = NET_ADDR_PERM; + } + + return 0; +} + static const struct net_device_ops ethsw_port_ops = { .ndo_open = port_open, .ndo_stop = port_stop, @@ -712,8 +753,10 @@ static void ethsw_links_state_update(struct ethsw_core *ethsw) { int i; - for (i = 0; i < ethsw->sw_attr.num_ifs; i++) + for (i = 0; i < ethsw->sw_attr.num_ifs; i++) { port_carrier_state_sync(ethsw->ports[i]->netdev); + ethsw_port_set_mac_addr(ethsw->ports[i]); + } } static irqreturn_t ethsw_irq0_handler_thread(int irq_num, void *arg) @@ -1364,6 +1407,14 @@ err_switchdev_nb: return err; } +static void ethsw_detect_features(struct ethsw_core *ethsw) +{ + ethsw->features = 0; + + if (ethsw->major > 8 || (ethsw->major == 8 && ethsw->minor >= 6)) + ethsw->features |= ETHSW_FEATURE_MAC_ADDR; +} + static int ethsw_init(struct fsl_mc_device *sw_dev) { struct device *dev = &sw_dev->dev; @@ -1407,6 +1458,8 @@ static int ethsw_init(struct fsl_mc_device *sw_dev) goto err_close; } + ethsw_detect_features(ethsw); + err = dpsw_reset(ethsw->mc_io, 0, ethsw->dpsw_handle); if (err) { dev_err(dev, "dpsw_reset err %d\n", err); @@ -1602,6 +1655,10 @@ static int ethsw_probe_port(struct ethsw_core *ethsw, u16 port_idx) if (err) goto err_port_probe; + err = ethsw_port_set_mac_addr(port_priv); + if (err) + goto err_port_probe; + err = register_netdev(port_netdev); if (err < 0) { dev_err(dev, "register_netdev error %d\n", err); |