Skip to content

Commit

Permalink
staging: dpaa2-switch: fix up initial forwarding configuration done b…
Browse files Browse the repository at this point in the history
…y firmware

By default, the DPSW object is configured with VLAN ID 1 in the VLAN
table, which all ports are member of. This entry in the VLAN table
selects the same FDB ID for all ports, meaning that forwarding between
ports is permitted. This is unlike the switchdev model, where each port
should operate as standalone by default.

To make the switch operate in standalone ports mode, we need the VLAN
table to select a unique FDB ID for each port. In order to do that, we
need to simply delete the VLAN 1 created automatically by firmware, and
let dpaa2_switch_port_init take over, by readding VLAN ID 1, but
pointing towards a unique FDB ID.

Signed-off-by: Ioana Ciornei <ioana.ciornei@nxp.com>
Signed-off-by: David S. Miller <davem@davemloft.net>
  • Loading branch information
Ioana Ciornei authored and David S. Miller committed Mar 10, 2021
1 parent 93a4d0a commit 282d47d
Showing 1 changed file with 51 additions and 29 deletions.
80 changes: 51 additions & 29 deletions drivers/staging/fsl-dpaa2/ethsw/ethsw.c
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@
* DPAA2 Ethernet Switch driver
*
* Copyright 2014-2016 Freescale Semiconductor Inc.
* Copyright 2017-2018 NXP
* Copyright 2017-2021 NXP
*
*/

Expand Down Expand Up @@ -1365,6 +1365,8 @@ static int dpaa2_switch_init(struct fsl_mc_device *sw_dev)
{
struct device *dev = &sw_dev->dev;
struct ethsw_core *ethsw = dev_get_drvdata(dev);
struct dpsw_vlan_if_cfg vcfg = {0};
struct dpsw_tci_cfg tci_cfg = {0};
struct dpsw_stp_cfg stp_cfg;
int err;
u16 i;
Expand Down Expand Up @@ -1416,13 +1418,52 @@ static int dpaa2_switch_init(struct fsl_mc_device *sw_dev)
stp_cfg.state = DPSW_STP_STATE_FORWARDING;

for (i = 0; i < ethsw->sw_attr.num_ifs; i++) {
err = dpsw_if_disable(ethsw->mc_io, 0, ethsw->dpsw_handle, i);
if (err) {
dev_err(dev, "dpsw_if_disable err %d\n", err);
goto err_close;
}

err = dpsw_if_set_stp(ethsw->mc_io, 0, ethsw->dpsw_handle, i,
&stp_cfg);
if (err) {
dev_err(dev, "dpsw_if_set_stp err %d for port %d\n",
err, i);
goto err_close;
}

/* Switch starts with all ports configured to VLAN 1. Need to
* remove this setting to allow configuration at bridge join
*/
vcfg.num_ifs = 1;
vcfg.if_id[0] = i;
err = dpsw_vlan_remove_if_untagged(ethsw->mc_io, 0, ethsw->dpsw_handle,
DEFAULT_VLAN_ID, &vcfg);
if (err) {
dev_err(dev, "dpsw_vlan_remove_if_untagged err %d\n",
err);
goto err_close;
}

tci_cfg.vlan_id = 4095;
err = dpsw_if_set_tci(ethsw->mc_io, 0, ethsw->dpsw_handle, i, &tci_cfg);
if (err) {
dev_err(dev, "dpsw_if_set_tci err %d\n", err);
goto err_close;
}

err = dpsw_vlan_remove_if(ethsw->mc_io, 0, ethsw->dpsw_handle,
DEFAULT_VLAN_ID, &vcfg);
if (err) {
dev_err(dev, "dpsw_vlan_remove_if err %d\n", err);
goto err_close;
}
}

err = dpsw_vlan_remove(ethsw->mc_io, 0, ethsw->dpsw_handle, DEFAULT_VLAN_ID);
if (err) {
dev_err(dev, "dpsw_vlan_remove err %d\n", err);
goto err_close;
}

ethsw->workqueue = alloc_ordered_workqueue("%s_%d_ordered",
Expand All @@ -1449,34 +1490,22 @@ static int dpaa2_switch_init(struct fsl_mc_device *sw_dev)

static int dpaa2_switch_port_init(struct ethsw_port_priv *port_priv, u16 port)
{
struct switchdev_obj_port_vlan vlan = {
.obj.id = SWITCHDEV_OBJ_ID_PORT_VLAN,
.vid = DEFAULT_VLAN_ID,
.flags = BRIDGE_VLAN_INFO_UNTAGGED | BRIDGE_VLAN_INFO_PVID,
};
struct net_device *netdev = port_priv->netdev;
struct ethsw_core *ethsw = port_priv->ethsw_data;
struct dpsw_vlan_if_cfg vcfg;
int err;

/* Switch starts with all ports configured to VLAN 1. Need to
* remove this setting to allow configuration at bridge join
/* We need to add VLAN 1 as the PVID on this port until it is under a
* bridge since the DPAA2 switch is not able to handle the traffic in a
* VLAN unaware fashion
*/
vcfg.num_ifs = 1;
vcfg.if_id[0] = port_priv->idx;

err = dpsw_vlan_remove_if_untagged(ethsw->mc_io, 0, ethsw->dpsw_handle,
DEFAULT_VLAN_ID, &vcfg);
if (err) {
netdev_err(netdev, "dpsw_vlan_remove_if_untagged err %d\n",
err);
return err;
}

err = dpaa2_switch_port_set_pvid(port_priv, 0);
err = dpaa2_switch_port_vlans_add(netdev, &vlan);
if (err)
return err;

err = dpsw_vlan_remove_if(ethsw->mc_io, 0, ethsw->dpsw_handle,
DEFAULT_VLAN_ID, &vcfg);
if (err)
netdev_err(netdev, "dpsw_vlan_remove_if err %d\n", err);

return err;
}

Expand Down Expand Up @@ -1633,9 +1662,6 @@ static int dpaa2_switch_probe(struct fsl_mc_device *sw_dev)
if (err)
goto err_free_cmdport;

/* DEFAULT_VLAN_ID is implicitly configured on the switch */
ethsw->vlans[DEFAULT_VLAN_ID] = ETHSW_VLAN_MEMBER;

ethsw->ports = kcalloc(ethsw->sw_attr.num_ifs, sizeof(*ethsw->ports),
GFP_KERNEL);
if (!(ethsw->ports)) {
Expand All @@ -1655,10 +1681,6 @@ static int dpaa2_switch_probe(struct fsl_mc_device *sw_dev)
goto err_free_ports;
}

/* Make sure the switch ports are disabled at probe time */
for (i = 0; i < ethsw->sw_attr.num_ifs; i++)
dpsw_if_disable(ethsw->mc_io, 0, ethsw->dpsw_handle, i);

/* Setup IRQs */
err = dpaa2_switch_setup_irqs(sw_dev);
if (err)
Expand Down

0 comments on commit 282d47d

Please sign in to comment.