Commit 57bb1132 authored by David S. Miller's avatar David S. Miller
Browse files

Merge branch 'dsa-rtnl'

Vladimir Oltean says:

====================
Drop rtnl_lock from DSA .port_fdb_{add,del}

As mentioned in the RFC posted 2 months ago:
https://patchwork.kernel.org/project/netdevbpf/cover/20210824114049.3814660-1-vladimir.oltean@nxp.com/



DSA is transitioning to a driver API where the rtnl_lock is not held
when calling ds->ops->port_fdb_add() and ds->ops->port_fdb_del().
Drivers cannot take that lock privately from those callbacks either.

This change is required so that DSA can wait for switchdev FDB work
items to finish before leaving the bridge. That change will be made in a
future patch series.

A small selftest is provided with the patch set in the hope that
concurrency issues uncovered by this series, but not spotted by me by
code inspection, will be caught.

A status of the existing drivers:

- mv88e6xxx_port_fdb_add() and mv88e6xxx_port_fdb_del() take
  mv88e6xxx_reg_lock() so they should be safe.

- qca8k_fdb_add() and qca8k_fdb_del() take mutex_lock(&priv->reg_mutex)
  so they should be safe.

- hellcreek_fdb_add() and hellcreek_fdb_add() take mutex_lock(&hellcreek->reg_lock)
  so they should be safe.

- ksz9477_port_fdb_add() and ksz9477_port_fdb_del() take mutex_lock(&dev->alu_mutex)
  so they should be safe.

- b53_fdb_add() and b53_fdb_del() did not have locking, so I've added a
  scheme based on my own judgement there (not tested).

- felix_fdb_add() and felix_fdb_del() did not have locking, I've added
  and tested a locking scheme there.

- mt7530_port_fdb_add() and mt7530_port_fdb_del() take
  mutex_lock(&priv->reg_mutex), so they should be safe.

- gswip_port_fdb() did not have locking, so I've added a non-expert
  locking scheme based on my own judgement (not tested).

- lan9303_alr_add_port() and lan9303_alr_del_port() take
  mutex_lock(&chip->alr_mutex) so they should be safe.

- sja1105_fdb_add() and sja1105_fdb_del() did not have locking, I've
  added and tested a locking scheme.

Changes in v3:
Unlock arl_mutex only once in b53_fdb_dump().

Changes in v4:
- Use __must_hold in ocelot and b53
- Add missing mutex_init in lantiq_gswip
- Clean up the selftest a bit.

Changes in v5:
- Replace __must_hold with a comment.
- Add a new patch (01/10).
====================

Signed-off-by: default avatarDavid S. Miller <davem@davemloft.net>
parents 2d7e73f0 eccd0a80
Loading
Loading
Loading
Loading
+1 −0
Original line number Diff line number Diff line
@@ -13056,6 +13056,7 @@ F: include/linux/dsa/
F:	include/linux/platform_data/dsa.h
F:	include/net/dsa.h
F:	net/dsa/
F:	tools/testing/selftests/drivers/net/dsa/
NETWORKING [GENERAL]
M:	"David S. Miller" <davem@davemloft.net>
+29 −7
Original line number Diff line number Diff line
@@ -1542,7 +1542,7 @@ int b53_vlan_del(struct dsa_switch *ds, int port,
}
EXPORT_SYMBOL(b53_vlan_del);

/* Address Resolution Logic routines */
/* Address Resolution Logic routines. Caller must hold &dev->arl_mutex. */
static int b53_arl_op_wait(struct b53_device *dev)
{
	unsigned int timeout = 10;
@@ -1707,6 +1707,7 @@ int b53_fdb_add(struct dsa_switch *ds, int port,
		const unsigned char *addr, u16 vid)
{
	struct b53_device *priv = ds->priv;
	int ret;

	/* 5325 and 5365 require some more massaging, but could
	 * be supported eventually
@@ -1714,7 +1715,11 @@ int b53_fdb_add(struct dsa_switch *ds, int port,
	if (is5325(priv) || is5365(priv))
		return -EOPNOTSUPP;

	return b53_arl_op(priv, 0, port, addr, vid, true);
	mutex_lock(&priv->arl_mutex);
	ret = b53_arl_op(priv, 0, port, addr, vid, true);
	mutex_unlock(&priv->arl_mutex);

	return ret;
}
EXPORT_SYMBOL(b53_fdb_add);

@@ -1722,8 +1727,13 @@ int b53_fdb_del(struct dsa_switch *ds, int port,
		const unsigned char *addr, u16 vid)
{
	struct b53_device *priv = ds->priv;
	int ret;

	mutex_lock(&priv->arl_mutex);
	ret = b53_arl_op(priv, 0, port, addr, vid, false);
	mutex_unlock(&priv->arl_mutex);

	return b53_arl_op(priv, 0, port, addr, vid, false);
	return ret;
}
EXPORT_SYMBOL(b53_fdb_del);

@@ -1780,6 +1790,8 @@ int b53_fdb_dump(struct dsa_switch *ds, int port,
	int ret;
	u8 reg;

	mutex_lock(&priv->arl_mutex);

	/* Start search operation */
	reg = ARL_SRCH_STDN;
	b53_write8(priv, B53_ARLIO_PAGE, B53_ARL_SRCH_CTL, reg);
@@ -1787,18 +1799,18 @@ int b53_fdb_dump(struct dsa_switch *ds, int port,
	do {
		ret = b53_arl_search_wait(priv);
		if (ret)
			return ret;
			break;

		b53_arl_search_rd(priv, 0, &results[0]);
		ret = b53_fdb_copy(port, &results[0], cb, data);
		if (ret)
			return ret;
			break;

		if (priv->num_arl_bins > 2) {
			b53_arl_search_rd(priv, 1, &results[1]);
			ret = b53_fdb_copy(port, &results[1], cb, data);
			if (ret)
				return ret;
				break;

			if (!results[0].is_valid && !results[1].is_valid)
				break;
@@ -1806,6 +1818,8 @@ int b53_fdb_dump(struct dsa_switch *ds, int port,

	} while (count++ < b53_max_arl_entries(priv) / 2);

	mutex_unlock(&priv->arl_mutex);

	return 0;
}
EXPORT_SYMBOL(b53_fdb_dump);
@@ -1814,6 +1828,7 @@ int b53_mdb_add(struct dsa_switch *ds, int port,
		const struct switchdev_obj_port_mdb *mdb)
{
	struct b53_device *priv = ds->priv;
	int ret;

	/* 5325 and 5365 require some more massaging, but could
	 * be supported eventually
@@ -1821,7 +1836,11 @@ int b53_mdb_add(struct dsa_switch *ds, int port,
	if (is5325(priv) || is5365(priv))
		return -EOPNOTSUPP;

	return b53_arl_op(priv, 0, port, mdb->addr, mdb->vid, true);
	mutex_lock(&priv->arl_mutex);
	ret = b53_arl_op(priv, 0, port, mdb->addr, mdb->vid, true);
	mutex_unlock(&priv->arl_mutex);

	return ret;
}
EXPORT_SYMBOL(b53_mdb_add);

@@ -1831,7 +1850,9 @@ int b53_mdb_del(struct dsa_switch *ds, int port,
	struct b53_device *priv = ds->priv;
	int ret;

	mutex_lock(&priv->arl_mutex);
	ret = b53_arl_op(priv, 0, port, mdb->addr, mdb->vid, false);
	mutex_unlock(&priv->arl_mutex);
	if (ret)
		dev_err(ds->dev, "failed to delete MDB entry\n");

@@ -2668,6 +2689,7 @@ struct b53_device *b53_switch_alloc(struct device *base,

	mutex_init(&dev->reg_mutex);
	mutex_init(&dev->stats_mutex);
	mutex_init(&dev->arl_mutex);

	return dev;
}
+1 −0
Original line number Diff line number Diff line
@@ -107,6 +107,7 @@ struct b53_device {

	struct mutex reg_mutex;
	struct mutex stats_mutex;
	struct mutex arl_mutex;
	const struct b53_io_ops *ops;

	/* chip specific data */
+23 −5
Original line number Diff line number Diff line
@@ -276,6 +276,7 @@ struct gswip_priv {
	int num_gphy_fw;
	struct gswip_gphy_fw *gphy_fw;
	u32 port_vlan_filter;
	struct mutex pce_table_lock;
};

struct gswip_pce_table_entry {
@@ -523,10 +524,14 @@ static int gswip_pce_table_entry_read(struct gswip_priv *priv,
	u16 addr_mode = tbl->key_mode ? GSWIP_PCE_TBL_CTRL_OPMOD_KSRD :
					GSWIP_PCE_TBL_CTRL_OPMOD_ADRD;

	mutex_lock(&priv->pce_table_lock);

	err = gswip_switch_r_timeout(priv, GSWIP_PCE_TBL_CTRL,
				     GSWIP_PCE_TBL_CTRL_BAS);
	if (err)
	if (err) {
		mutex_unlock(&priv->pce_table_lock);
		return err;
	}

	gswip_switch_w(priv, tbl->index, GSWIP_PCE_TBL_ADDR);
	gswip_switch_mask(priv, GSWIP_PCE_TBL_CTRL_ADDR_MASK |
@@ -536,8 +541,10 @@ static int gswip_pce_table_entry_read(struct gswip_priv *priv,

	err = gswip_switch_r_timeout(priv, GSWIP_PCE_TBL_CTRL,
				     GSWIP_PCE_TBL_CTRL_BAS);
	if (err)
	if (err) {
		mutex_unlock(&priv->pce_table_lock);
		return err;
	}

	for (i = 0; i < ARRAY_SIZE(tbl->key); i++)
		tbl->key[i] = gswip_switch_r(priv, GSWIP_PCE_TBL_KEY(i));
@@ -553,6 +560,8 @@ static int gswip_pce_table_entry_read(struct gswip_priv *priv,
	tbl->valid = !!(crtl & GSWIP_PCE_TBL_CTRL_VLD);
	tbl->gmap = (crtl & GSWIP_PCE_TBL_CTRL_GMAP_MASK) >> 7;

	mutex_unlock(&priv->pce_table_lock);

	return 0;
}

@@ -565,10 +574,14 @@ static int gswip_pce_table_entry_write(struct gswip_priv *priv,
	u16 addr_mode = tbl->key_mode ? GSWIP_PCE_TBL_CTRL_OPMOD_KSWR :
					GSWIP_PCE_TBL_CTRL_OPMOD_ADWR;

	mutex_lock(&priv->pce_table_lock);

	err = gswip_switch_r_timeout(priv, GSWIP_PCE_TBL_CTRL,
				     GSWIP_PCE_TBL_CTRL_BAS);
	if (err)
	if (err) {
		mutex_unlock(&priv->pce_table_lock);
		return err;
	}

	gswip_switch_w(priv, tbl->index, GSWIP_PCE_TBL_ADDR);
	gswip_switch_mask(priv, GSWIP_PCE_TBL_CTRL_ADDR_MASK |
@@ -600,8 +613,12 @@ static int gswip_pce_table_entry_write(struct gswip_priv *priv,
	crtl |= GSWIP_PCE_TBL_CTRL_BAS;
	gswip_switch_w(priv, crtl, GSWIP_PCE_TBL_CTRL);

	return gswip_switch_r_timeout(priv, GSWIP_PCE_TBL_CTRL,
	err = gswip_switch_r_timeout(priv, GSWIP_PCE_TBL_CTRL,
				     GSWIP_PCE_TBL_CTRL_BAS);

	mutex_unlock(&priv->pce_table_lock);

	return err;
}

/* Add the LAN port into a bridge with the CPU port by
@@ -2104,6 +2121,7 @@ static int gswip_probe(struct platform_device *pdev)
	priv->ds->priv = priv;
	priv->ds->ops = priv->hw_info->ops;
	priv->dev = dev;
	mutex_init(&priv->pce_table_lock);
	version = gswip_switch_r(priv, GSWIP_VERSION);

	np = dev->of_node;
+2 −0
Original line number Diff line number Diff line
@@ -261,6 +261,8 @@ struct sja1105_private {
	 * the switch doesn't confuse them with one another.
	 */
	struct mutex mgmt_lock;
	/* Serializes access to the dynamic config interface */
	struct mutex dynamic_config_lock;
	struct devlink_region **regions;
	struct sja1105_cbs_entry *cbs;
	struct mii_bus *mdio_base_t1;
Loading