Commit d1c8b6a3 authored by Jakub Kicinski's avatar Jakub Kicinski
Browse files

Merge branch 'get-rid-of-the-switchdev-transactional-model'

Vladimir Oltean says:

====================
Get rid of the switchdev transactional model

Changes in v4:
- Fixed build error in dsa_loop and build warning in hellcreek driver.
- Scheduling the mlxsw SPAN work item regardless of the VLAN add return
  code, as per Ido's and Petr's request.

Changes in v3:
- Resolved a build warning in mv88e6xxx and tested that it actually
  works properly, which resulted in an extra patch (02/11).
- Addressed Ido's minor feedback in commit 10/11 relating to a comment.

Changes in v2:
- Got rid of the vid_begin -> vid_end range too from the switchdev API.
- Actually propagating errors from DSA MDB and VLAN notifiers.

This series comes after the late realization that the prepare/commit
separation imposed by switchdev does not help literally anybody:
https://patchwork.kernel.org/project/netdevbpf/patch/20201212203901.351331-1-vladimir.oltean@nxp.com/

We should kill it before it inflicts even more damage to the error
handling logic in drivers.

Also remove the unused VLAN ranges feature from the switchdev VLAN
objects, which simplifies all drivers by quite a bit.
====================

Link: https://lore.kernel.org/r/20210109000156.1246735-1-olteanv@gmail.com


Signed-off-by: default avatarJakub Kicinski <kuba@kernel.org>
parents beb401ec 8f73cc50
Loading
Loading
Loading
Loading
+39 −57
Original line number Diff line number Diff line
@@ -1374,26 +1374,22 @@ void b53_phylink_mac_link_up(struct dsa_switch *ds, int port,
}
EXPORT_SYMBOL(b53_phylink_mac_link_up);

int b53_vlan_filtering(struct dsa_switch *ds, int port, bool vlan_filtering,
		       struct switchdev_trans *trans)
int b53_vlan_filtering(struct dsa_switch *ds, int port, bool vlan_filtering)
{
	struct b53_device *dev = ds->priv;

	if (switchdev_trans_ph_prepare(trans))
		return 0;

	b53_enable_vlan(dev, dev->vlan_enabled, vlan_filtering);

	return 0;
}
EXPORT_SYMBOL(b53_vlan_filtering);

int b53_vlan_prepare(struct dsa_switch *ds, int port,
static int b53_vlan_prepare(struct dsa_switch *ds, int port,
			    const struct switchdev_obj_port_vlan *vlan)
{
	struct b53_device *dev = ds->priv;

	if ((is5325(dev) || is5365(dev)) && vlan->vid_begin == 0)
	if ((is5325(dev) || is5365(dev)) && vlan->vid == 0)
		return -EOPNOTSUPP;

	/* Port 7 on 7278 connects to the ASP's UniMAC which is not capable of
@@ -1404,30 +1400,32 @@ int b53_vlan_prepare(struct dsa_switch *ds, int port,
	    !(vlan->flags & BRIDGE_VLAN_INFO_UNTAGGED))
		return -EINVAL;

	if (vlan->vid_end > dev->num_vlans)
	if (vlan->vid > dev->num_vlans)
		return -ERANGE;

	b53_enable_vlan(dev, true, ds->vlan_filtering);

	return 0;
}
EXPORT_SYMBOL(b53_vlan_prepare);

void b53_vlan_add(struct dsa_switch *ds, int port,
int b53_vlan_add(struct dsa_switch *ds, int port,
		 const struct switchdev_obj_port_vlan *vlan)
{
	struct b53_device *dev = ds->priv;
	bool untagged = vlan->flags & BRIDGE_VLAN_INFO_UNTAGGED;
	bool pvid = vlan->flags & BRIDGE_VLAN_INFO_PVID;
	struct b53_vlan *vl;
	u16 vid;
	int err;

	err = b53_vlan_prepare(ds, port, vlan);
	if (err)
		return err;

	for (vid = vlan->vid_begin; vid <= vlan->vid_end; ++vid) {
		vl = &dev->vlans[vid];
	vl = &dev->vlans[vlan->vid];

		b53_get_vlan_entry(dev, vid, vl);
	b53_get_vlan_entry(dev, vlan->vid, vl);

		if (vid == 0 && vid == b53_default_pvid(dev))
	if (vlan->vid == 0 && vlan->vid == b53_default_pvid(dev))
		untagged = true;

	vl->members |= BIT(port);
@@ -1436,15 +1434,16 @@ void b53_vlan_add(struct dsa_switch *ds, int port,
	else
		vl->untag &= ~BIT(port);

		b53_set_vlan_entry(dev, vid, vl);
		b53_fast_age_vlan(dev, vid);
	}
	b53_set_vlan_entry(dev, vlan->vid, vl);
	b53_fast_age_vlan(dev, vlan->vid);

	if (pvid && !dsa_is_cpu_port(ds, port)) {
		b53_write16(dev, B53_VLAN_PAGE, B53_VLAN_PORT_DEF_TAG(port),
			    vlan->vid_end);
		b53_fast_age_vlan(dev, vid);
			    vlan->vid);
		b53_fast_age_vlan(dev, vlan->vid);
	}

	return 0;
}
EXPORT_SYMBOL(b53_vlan_add);

@@ -1454,27 +1453,24 @@ int b53_vlan_del(struct dsa_switch *ds, int port,
	struct b53_device *dev = ds->priv;
	bool untagged = vlan->flags & BRIDGE_VLAN_INFO_UNTAGGED;
	struct b53_vlan *vl;
	u16 vid;
	u16 pvid;

	b53_read16(dev, B53_VLAN_PAGE, B53_VLAN_PORT_DEF_TAG(port), &pvid);

	for (vid = vlan->vid_begin; vid <= vlan->vid_end; ++vid) {
		vl = &dev->vlans[vid];
	vl = &dev->vlans[vlan->vid];

		b53_get_vlan_entry(dev, vid, vl);
	b53_get_vlan_entry(dev, vlan->vid, vl);

	vl->members &= ~BIT(port);

		if (pvid == vid)
	if (pvid == vlan->vid)
		pvid = b53_default_pvid(dev);

	if (untagged && !dsa_is_cpu_port(ds, port))
		vl->untag &= ~(BIT(port));

		b53_set_vlan_entry(dev, vid, vl);
		b53_fast_age_vlan(dev, vid);
	}
	b53_set_vlan_entry(dev, vlan->vid, vl);
	b53_fast_age_vlan(dev, vlan->vid);

	b53_write16(dev, B53_VLAN_PAGE, B53_VLAN_PORT_DEF_TAG(port), pvid);
	b53_fast_age_vlan(dev, pvid);
@@ -1751,7 +1747,7 @@ int b53_fdb_dump(struct dsa_switch *ds, int port,
}
EXPORT_SYMBOL(b53_fdb_dump);

int b53_mdb_prepare(struct dsa_switch *ds, int port,
int b53_mdb_add(struct dsa_switch *ds, int port,
		const struct switchdev_obj_port_mdb *mdb)
{
	struct b53_device *priv = ds->priv;
@@ -1762,19 +1758,7 @@ int b53_mdb_prepare(struct dsa_switch *ds, int port,
	if (is5325(priv) || is5365(priv))
		return -EOPNOTSUPP;

	return 0;
}
EXPORT_SYMBOL(b53_mdb_prepare);

void b53_mdb_add(struct dsa_switch *ds, int port,
		 const struct switchdev_obj_port_mdb *mdb)
{
	struct b53_device *priv = ds->priv;
	int ret;

	ret = b53_arl_op(priv, 0, port, mdb->addr, mdb->vid, true);
	if (ret)
		dev_err(ds->dev, "failed to add MDB entry\n");
	return b53_arl_op(priv, 0, port, mdb->addr, mdb->vid, true);
}
EXPORT_SYMBOL(b53_mdb_add);

@@ -2207,7 +2191,6 @@ static const struct dsa_switch_ops b53_switch_ops = {
	.port_fast_age		= b53_br_fast_age,
	.port_egress_floods	= b53_br_egress_floods,
	.port_vlan_filtering	= b53_vlan_filtering,
	.port_vlan_prepare	= b53_vlan_prepare,
	.port_vlan_add		= b53_vlan_add,
	.port_vlan_del		= b53_vlan_del,
	.port_fdb_dump		= b53_fdb_dump,
@@ -2215,7 +2198,6 @@ static const struct dsa_switch_ops b53_switch_ops = {
	.port_fdb_del		= b53_fdb_del,
	.port_mirror_add	= b53_mirror_add,
	.port_mirror_del	= b53_mirror_del,
	.port_mdb_prepare	= b53_mdb_prepare,
	.port_mdb_add		= b53_mdb_add,
	.port_mdb_del		= b53_mdb_del,
	.port_max_mtu		= b53_get_max_mtu,
+5 −10
Original line number Diff line number Diff line
@@ -348,11 +348,8 @@ void b53_phylink_mac_link_up(struct dsa_switch *ds, int port,
			     struct phy_device *phydev,
			     int speed, int duplex,
			     bool tx_pause, bool rx_pause);
int b53_vlan_filtering(struct dsa_switch *ds, int port, bool vlan_filtering,
		       struct switchdev_trans *trans);
int b53_vlan_prepare(struct dsa_switch *ds, int port,
		     const struct switchdev_obj_port_vlan *vlan);
void b53_vlan_add(struct dsa_switch *ds, int port,
int b53_vlan_filtering(struct dsa_switch *ds, int port, bool vlan_filtering);
int b53_vlan_add(struct dsa_switch *ds, int port,
		 const struct switchdev_obj_port_vlan *vlan);
int b53_vlan_del(struct dsa_switch *ds, int port,
		 const struct switchdev_obj_port_vlan *vlan);
@@ -362,9 +359,7 @@ int b53_fdb_del(struct dsa_switch *ds, int port,
		const unsigned char *addr, u16 vid);
int b53_fdb_dump(struct dsa_switch *ds, int port,
		 dsa_fdb_dump_cb_t *cb, void *data);
int b53_mdb_prepare(struct dsa_switch *ds, int port,
		    const struct switchdev_obj_port_mdb *mdb);
void b53_mdb_add(struct dsa_switch *ds, int port,
int b53_mdb_add(struct dsa_switch *ds, int port,
		const struct switchdev_obj_port_mdb *mdb);
int b53_mdb_del(struct dsa_switch *ds, int port,
		const struct switchdev_obj_port_mdb *mdb);
+0 −2
Original line number Diff line number Diff line
@@ -1116,7 +1116,6 @@ static const struct dsa_switch_ops bcm_sf2_ops = {
	.port_stp_state_set	= b53_br_set_stp_state,
	.port_fast_age		= b53_br_fast_age,
	.port_vlan_filtering	= b53_vlan_filtering,
	.port_vlan_prepare	= b53_vlan_prepare,
	.port_vlan_add		= b53_vlan_add,
	.port_vlan_del		= b53_vlan_del,
	.port_fdb_dump		= b53_fdb_dump,
@@ -1126,7 +1125,6 @@ static const struct dsa_switch_ops bcm_sf2_ops = {
	.set_rxnfc		= bcm_sf2_set_rxnfc,
	.port_mirror_add	= b53_mirror_add,
	.port_mirror_del	= b53_mirror_del,
	.port_mdb_prepare	= b53_mdb_prepare,
	.port_mdb_add		= b53_mdb_add,
	.port_mdb_del		= b53_mdb_del,
};
+3 −7
Original line number Diff line number Diff line
@@ -885,18 +885,15 @@ static int bcm_sf2_cfp_rule_insert(struct dsa_switch *ds, int port,
			return -EINVAL;

		vid = be16_to_cpu(fs->h_ext.vlan_tci) & VLAN_VID_MASK;
		vlan.vid_begin = vid;
		vlan.vid_end = vid;
		vlan.vid = vid;
		if (cpu_to_be32(fs->h_ext.data[1]) & 1)
			vlan.flags = BRIDGE_VLAN_INFO_UNTAGGED;
		else
			vlan.flags = 0;

		ret = ds->ops->port_vlan_prepare(ds, port_num, &vlan);
		ret = ds->ops->port_vlan_add(ds, port_num, &vlan);
		if (ret)
			return ret;

		ds->ops->port_vlan_add(ds, port_num, &vlan);
	}

	/*
@@ -942,8 +939,7 @@ static int bcm_sf2_cfp_rule_set(struct dsa_switch *ds, int port,
		return -EINVAL;

	if ((fs->flow_type & FLOW_EXT) &&
	    !(ds->ops->port_vlan_prepare || ds->ops->port_vlan_add ||
	      ds->ops->port_vlan_del))
	    !(ds->ops->port_vlan_add || ds->ops->port_vlan_del))
		return -EOPNOTSUPP;

	if (fs->location != RX_CLS_LOC_ANY &&
+26 −47
Original line number Diff line number Diff line
@@ -190,8 +190,7 @@ static void dsa_loop_port_stp_state_set(struct dsa_switch *ds, int port,
}

static int dsa_loop_port_vlan_filtering(struct dsa_switch *ds, int port,
					bool vlan_filtering,
					struct switchdev_trans *trans)
					bool vlan_filtering)
{
	dev_dbg(ds->dev, "%s: port: %d, vlan_filtering: %d\n",
		__func__, port, vlan_filtering);
@@ -199,26 +198,7 @@ static int dsa_loop_port_vlan_filtering(struct dsa_switch *ds, int port,
	return 0;
}

static int
dsa_loop_port_vlan_prepare(struct dsa_switch *ds, int port,
			   const struct switchdev_obj_port_vlan *vlan)
{
	struct dsa_loop_priv *ps = ds->priv;
	struct mii_bus *bus = ps->bus;

	dev_dbg(ds->dev, "%s: port: %d, vlan: %d-%d",
		__func__, port, vlan->vid_begin, vlan->vid_end);

	/* Just do a sleeping operation to make lockdep checks effective */
	mdiobus_read(bus, ps->port_base + port, MII_BMSR);

	if (vlan->vid_end > ARRAY_SIZE(ps->vlans))
		return -ERANGE;

	return 0;
}

static void dsa_loop_port_vlan_add(struct dsa_switch *ds, int port,
static int dsa_loop_port_vlan_add(struct dsa_switch *ds, int port,
				  const struct switchdev_obj_port_vlan *vlan)
{
	bool untagged = vlan->flags & BRIDGE_VLAN_INFO_UNTAGGED;
@@ -226,13 +206,14 @@ static void dsa_loop_port_vlan_add(struct dsa_switch *ds, int port,
	struct dsa_loop_priv *ps = ds->priv;
	struct mii_bus *bus = ps->bus;
	struct dsa_loop_vlan *vl;
	u16 vid;

	if (vlan->vid > ARRAY_SIZE(ps->vlans))
		return -ERANGE;

	/* Just do a sleeping operation to make lockdep checks effective */
	mdiobus_read(bus, ps->port_base + port, MII_BMSR);

	for (vid = vlan->vid_begin; vid <= vlan->vid_end; ++vid) {
		vl = &ps->vlans[vid];
	vl = &ps->vlans[vlan->vid];

	vl->members |= BIT(port);
	if (untagged)
@@ -241,11 +222,12 @@ static void dsa_loop_port_vlan_add(struct dsa_switch *ds, int port,
		vl->untagged &= ~BIT(port);

	dev_dbg(ds->dev, "%s: port: %d vlan: %d, %stagged, pvid: %d\n",
			__func__, port, vid, untagged ? "un" : "", pvid);
	}
		__func__, port, vlan->vid, untagged ? "un" : "", pvid);

	if (pvid)
		ps->ports[port].pvid = vid;
		ps->ports[port].pvid = vlan->vid;

	return 0;
}

static int dsa_loop_port_vlan_del(struct dsa_switch *ds, int port,
@@ -253,26 +235,24 @@ static int dsa_loop_port_vlan_del(struct dsa_switch *ds, int port,
{
	bool untagged = vlan->flags & BRIDGE_VLAN_INFO_UNTAGGED;
	struct dsa_loop_priv *ps = ds->priv;
	u16 pvid = ps->ports[port].pvid;
	struct mii_bus *bus = ps->bus;
	struct dsa_loop_vlan *vl;
	u16 vid, pvid = ps->ports[port].pvid;

	/* Just do a sleeping operation to make lockdep checks effective */
	mdiobus_read(bus, ps->port_base + port, MII_BMSR);

	for (vid = vlan->vid_begin; vid <= vlan->vid_end; ++vid) {
		vl = &ps->vlans[vid];
	vl = &ps->vlans[vlan->vid];

	vl->members &= ~BIT(port);
	if (untagged)
		vl->untagged &= ~BIT(port);

		if (pvid == vid)
	if (pvid == vlan->vid)
		pvid = 1;

	dev_dbg(ds->dev, "%s: port: %d vlan: %d, %stagged, pvid: %d\n",
			__func__, port, vid, untagged ? "un" : "", pvid);
	}
		__func__, port, vlan->vid, untagged ? "un" : "", pvid);
	ps->ports[port].pvid = pvid;

	return 0;
@@ -307,7 +287,6 @@ static const struct dsa_switch_ops dsa_loop_driver = {
	.port_bridge_leave	= dsa_loop_port_bridge_leave,
	.port_stp_state_set	= dsa_loop_port_stp_state_set,
	.port_vlan_filtering	= dsa_loop_port_vlan_filtering,
	.port_vlan_prepare	= dsa_loop_port_vlan_prepare,
	.port_vlan_add		= dsa_loop_port_vlan_add,
	.port_vlan_del		= dsa_loop_port_vlan_del,
	.port_change_mtu	= dsa_loop_port_change_mtu,
Loading