summaryrefslogtreecommitdiffstats
path: root/drivers/staging/fsl-dpaa2/ethsw/ethsw.c
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/staging/fsl-dpaa2/ethsw/ethsw.c')
-rw-r--r--drivers/staging/fsl-dpaa2/ethsw/ethsw.c59
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);