Commit 2d7e73f0 authored by David S. Miller's avatar David S. Miller

Revert "Merge branch 'dsa-rtnl'"

This reverts commit 965e6b26, reversing
changes made to 4d98bb0d.
parent 12f241f2
...@@ -13056,7 +13056,6 @@ F: include/linux/dsa/ ...@@ -13056,7 +13056,6 @@ F: include/linux/dsa/
F: include/linux/platform_data/dsa.h F: include/linux/platform_data/dsa.h
F: include/net/dsa.h F: include/net/dsa.h
F: net/dsa/ F: net/dsa/
F: tools/testing/selftests/drivers/net/dsa/
NETWORKING [GENERAL] NETWORKING [GENERAL]
M: "David S. Miller" <davem@davemloft.net> M: "David S. Miller" <davem@davemloft.net>
......
...@@ -1544,7 +1544,6 @@ EXPORT_SYMBOL(b53_vlan_del); ...@@ -1544,7 +1544,6 @@ EXPORT_SYMBOL(b53_vlan_del);
/* Address Resolution Logic routines */ /* Address Resolution Logic routines */
static int b53_arl_op_wait(struct b53_device *dev) static int b53_arl_op_wait(struct b53_device *dev)
__must_hold(&dev->arl_mutex)
{ {
unsigned int timeout = 10; unsigned int timeout = 10;
u8 reg; u8 reg;
...@@ -1563,7 +1562,6 @@ static int b53_arl_op_wait(struct b53_device *dev) ...@@ -1563,7 +1562,6 @@ static int b53_arl_op_wait(struct b53_device *dev)
} }
static int b53_arl_rw_op(struct b53_device *dev, unsigned int op) static int b53_arl_rw_op(struct b53_device *dev, unsigned int op)
__must_hold(&dev->arl_mutex)
{ {
u8 reg; u8 reg;
...@@ -1587,7 +1585,6 @@ static int b53_arl_rw_op(struct b53_device *dev, unsigned int op) ...@@ -1587,7 +1585,6 @@ static int b53_arl_rw_op(struct b53_device *dev, unsigned int op)
static int b53_arl_read(struct b53_device *dev, u64 mac, static int b53_arl_read(struct b53_device *dev, u64 mac,
u16 vid, struct b53_arl_entry *ent, u8 *idx) u16 vid, struct b53_arl_entry *ent, u8 *idx)
__must_hold(&dev->arl_mutex)
{ {
DECLARE_BITMAP(free_bins, B53_ARLTBL_MAX_BIN_ENTRIES); DECLARE_BITMAP(free_bins, B53_ARLTBL_MAX_BIN_ENTRIES);
unsigned int i; unsigned int i;
...@@ -1633,7 +1630,6 @@ static int b53_arl_read(struct b53_device *dev, u64 mac, ...@@ -1633,7 +1630,6 @@ static int b53_arl_read(struct b53_device *dev, u64 mac,
static int b53_arl_op(struct b53_device *dev, int op, int port, static int b53_arl_op(struct b53_device *dev, int op, int port,
const unsigned char *addr, u16 vid, bool is_valid) const unsigned char *addr, u16 vid, bool is_valid)
__must_hold(&dev->arl_mutex)
{ {
struct b53_arl_entry ent; struct b53_arl_entry ent;
u32 fwd_entry; u32 fwd_entry;
...@@ -1711,7 +1707,6 @@ int b53_fdb_add(struct dsa_switch *ds, int port, ...@@ -1711,7 +1707,6 @@ int b53_fdb_add(struct dsa_switch *ds, int port,
const unsigned char *addr, u16 vid) const unsigned char *addr, u16 vid)
{ {
struct b53_device *priv = ds->priv; struct b53_device *priv = ds->priv;
int ret;
/* 5325 and 5365 require some more massaging, but could /* 5325 and 5365 require some more massaging, but could
* be supported eventually * be supported eventually
...@@ -1719,11 +1714,7 @@ int b53_fdb_add(struct dsa_switch *ds, int port, ...@@ -1719,11 +1714,7 @@ int b53_fdb_add(struct dsa_switch *ds, int port,
if (is5325(priv) || is5365(priv)) if (is5325(priv) || is5365(priv))
return -EOPNOTSUPP; return -EOPNOTSUPP;
mutex_lock(&priv->arl_mutex); return b53_arl_op(priv, 0, port, addr, vid, true);
ret = b53_arl_op(priv, 0, port, addr, vid, true);
mutex_unlock(&priv->arl_mutex);
return ret;
} }
EXPORT_SYMBOL(b53_fdb_add); EXPORT_SYMBOL(b53_fdb_add);
...@@ -1731,18 +1722,12 @@ int b53_fdb_del(struct dsa_switch *ds, int port, ...@@ -1731,18 +1722,12 @@ int b53_fdb_del(struct dsa_switch *ds, int port,
const unsigned char *addr, u16 vid) const unsigned char *addr, u16 vid)
{ {
struct b53_device *priv = ds->priv; 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 ret; return b53_arl_op(priv, 0, port, addr, vid, false);
} }
EXPORT_SYMBOL(b53_fdb_del); EXPORT_SYMBOL(b53_fdb_del);
static int b53_arl_search_wait(struct b53_device *dev) static int b53_arl_search_wait(struct b53_device *dev)
__must_hold(&dev->arl_mutex)
{ {
unsigned int timeout = 1000; unsigned int timeout = 1000;
u8 reg; u8 reg;
...@@ -1763,7 +1748,6 @@ static int b53_arl_search_wait(struct b53_device *dev) ...@@ -1763,7 +1748,6 @@ static int b53_arl_search_wait(struct b53_device *dev)
static void b53_arl_search_rd(struct b53_device *dev, u8 idx, static void b53_arl_search_rd(struct b53_device *dev, u8 idx,
struct b53_arl_entry *ent) struct b53_arl_entry *ent)
__must_hold(&dev->arl_mutex)
{ {
u64 mac_vid; u64 mac_vid;
u32 fwd_entry; u32 fwd_entry;
...@@ -1796,8 +1780,6 @@ int b53_fdb_dump(struct dsa_switch *ds, int port, ...@@ -1796,8 +1780,6 @@ int b53_fdb_dump(struct dsa_switch *ds, int port,
int ret; int ret;
u8 reg; u8 reg;
mutex_lock(&priv->arl_mutex);
/* Start search operation */ /* Start search operation */
reg = ARL_SRCH_STDN; reg = ARL_SRCH_STDN;
b53_write8(priv, B53_ARLIO_PAGE, B53_ARL_SRCH_CTL, reg); b53_write8(priv, B53_ARLIO_PAGE, B53_ARL_SRCH_CTL, reg);
...@@ -1805,18 +1787,18 @@ int b53_fdb_dump(struct dsa_switch *ds, int port, ...@@ -1805,18 +1787,18 @@ int b53_fdb_dump(struct dsa_switch *ds, int port,
do { do {
ret = b53_arl_search_wait(priv); ret = b53_arl_search_wait(priv);
if (ret) if (ret)
break; return ret;
b53_arl_search_rd(priv, 0, &results[0]); b53_arl_search_rd(priv, 0, &results[0]);
ret = b53_fdb_copy(port, &results[0], cb, data); ret = b53_fdb_copy(port, &results[0], cb, data);
if (ret) if (ret)
break; return ret;
if (priv->num_arl_bins > 2) { if (priv->num_arl_bins > 2) {
b53_arl_search_rd(priv, 1, &results[1]); b53_arl_search_rd(priv, 1, &results[1]);
ret = b53_fdb_copy(port, &results[1], cb, data); ret = b53_fdb_copy(port, &results[1], cb, data);
if (ret) if (ret)
break; return ret;
if (!results[0].is_valid && !results[1].is_valid) if (!results[0].is_valid && !results[1].is_valid)
break; break;
...@@ -1824,8 +1806,6 @@ int b53_fdb_dump(struct dsa_switch *ds, int port, ...@@ -1824,8 +1806,6 @@ int b53_fdb_dump(struct dsa_switch *ds, int port,
} while (count++ < b53_max_arl_entries(priv) / 2); } while (count++ < b53_max_arl_entries(priv) / 2);
mutex_unlock(&priv->arl_mutex);
return 0; return 0;
} }
EXPORT_SYMBOL(b53_fdb_dump); EXPORT_SYMBOL(b53_fdb_dump);
...@@ -1834,7 +1814,6 @@ int b53_mdb_add(struct dsa_switch *ds, int port, ...@@ -1834,7 +1814,6 @@ int b53_mdb_add(struct dsa_switch *ds, int port,
const struct switchdev_obj_port_mdb *mdb) const struct switchdev_obj_port_mdb *mdb)
{ {
struct b53_device *priv = ds->priv; struct b53_device *priv = ds->priv;
int ret;
/* 5325 and 5365 require some more massaging, but could /* 5325 and 5365 require some more massaging, but could
* be supported eventually * be supported eventually
...@@ -1842,11 +1821,7 @@ int b53_mdb_add(struct dsa_switch *ds, int port, ...@@ -1842,11 +1821,7 @@ int b53_mdb_add(struct dsa_switch *ds, int port,
if (is5325(priv) || is5365(priv)) if (is5325(priv) || is5365(priv))
return -EOPNOTSUPP; return -EOPNOTSUPP;
mutex_lock(&priv->arl_mutex); return b53_arl_op(priv, 0, port, mdb->addr, mdb->vid, true);
ret = b53_arl_op(priv, 0, port, mdb->addr, mdb->vid, true);
mutex_unlock(&priv->arl_mutex);
return ret;
} }
EXPORT_SYMBOL(b53_mdb_add); EXPORT_SYMBOL(b53_mdb_add);
...@@ -1856,9 +1831,7 @@ int b53_mdb_del(struct dsa_switch *ds, int port, ...@@ -1856,9 +1831,7 @@ int b53_mdb_del(struct dsa_switch *ds, int port,
struct b53_device *priv = ds->priv; struct b53_device *priv = ds->priv;
int ret; int ret;
mutex_lock(&priv->arl_mutex);
ret = b53_arl_op(priv, 0, port, mdb->addr, mdb->vid, false); ret = b53_arl_op(priv, 0, port, mdb->addr, mdb->vid, false);
mutex_unlock(&priv->arl_mutex);
if (ret) if (ret)
dev_err(ds->dev, "failed to delete MDB entry\n"); dev_err(ds->dev, "failed to delete MDB entry\n");
...@@ -2695,7 +2668,6 @@ struct b53_device *b53_switch_alloc(struct device *base, ...@@ -2695,7 +2668,6 @@ struct b53_device *b53_switch_alloc(struct device *base,
mutex_init(&dev->reg_mutex); mutex_init(&dev->reg_mutex);
mutex_init(&dev->stats_mutex); mutex_init(&dev->stats_mutex);
mutex_init(&dev->arl_mutex);
return dev; return dev;
} }
......
...@@ -107,7 +107,6 @@ struct b53_device { ...@@ -107,7 +107,6 @@ struct b53_device {
struct mutex reg_mutex; struct mutex reg_mutex;
struct mutex stats_mutex; struct mutex stats_mutex;
struct mutex arl_mutex;
const struct b53_io_ops *ops; const struct b53_io_ops *ops;
/* chip specific data */ /* chip specific data */
......
...@@ -276,7 +276,6 @@ struct gswip_priv { ...@@ -276,7 +276,6 @@ struct gswip_priv {
int num_gphy_fw; int num_gphy_fw;
struct gswip_gphy_fw *gphy_fw; struct gswip_gphy_fw *gphy_fw;
u32 port_vlan_filter; u32 port_vlan_filter;
struct mutex pce_table_lock;
}; };
struct gswip_pce_table_entry { struct gswip_pce_table_entry {
...@@ -524,14 +523,10 @@ static int gswip_pce_table_entry_read(struct gswip_priv *priv, ...@@ -524,14 +523,10 @@ static int gswip_pce_table_entry_read(struct gswip_priv *priv,
u16 addr_mode = tbl->key_mode ? GSWIP_PCE_TBL_CTRL_OPMOD_KSRD : u16 addr_mode = tbl->key_mode ? GSWIP_PCE_TBL_CTRL_OPMOD_KSRD :
GSWIP_PCE_TBL_CTRL_OPMOD_ADRD; GSWIP_PCE_TBL_CTRL_OPMOD_ADRD;
mutex_lock(&priv->pce_table_lock);
err = gswip_switch_r_timeout(priv, GSWIP_PCE_TBL_CTRL, err = gswip_switch_r_timeout(priv, GSWIP_PCE_TBL_CTRL,
GSWIP_PCE_TBL_CTRL_BAS); GSWIP_PCE_TBL_CTRL_BAS);
if (err) { if (err)
mutex_unlock(&priv->pce_table_lock);
return err; return err;
}
gswip_switch_w(priv, tbl->index, GSWIP_PCE_TBL_ADDR); gswip_switch_w(priv, tbl->index, GSWIP_PCE_TBL_ADDR);
gswip_switch_mask(priv, GSWIP_PCE_TBL_CTRL_ADDR_MASK | gswip_switch_mask(priv, GSWIP_PCE_TBL_CTRL_ADDR_MASK |
...@@ -541,10 +536,8 @@ static int gswip_pce_table_entry_read(struct gswip_priv *priv, ...@@ -541,10 +536,8 @@ static int gswip_pce_table_entry_read(struct gswip_priv *priv,
err = gswip_switch_r_timeout(priv, GSWIP_PCE_TBL_CTRL, err = gswip_switch_r_timeout(priv, GSWIP_PCE_TBL_CTRL,
GSWIP_PCE_TBL_CTRL_BAS); GSWIP_PCE_TBL_CTRL_BAS);
if (err) { if (err)
mutex_unlock(&priv->pce_table_lock);
return err; return err;
}
for (i = 0; i < ARRAY_SIZE(tbl->key); i++) for (i = 0; i < ARRAY_SIZE(tbl->key); i++)
tbl->key[i] = gswip_switch_r(priv, GSWIP_PCE_TBL_KEY(i)); tbl->key[i] = gswip_switch_r(priv, GSWIP_PCE_TBL_KEY(i));
...@@ -560,8 +553,6 @@ static int gswip_pce_table_entry_read(struct gswip_priv *priv, ...@@ -560,8 +553,6 @@ static int gswip_pce_table_entry_read(struct gswip_priv *priv,
tbl->valid = !!(crtl & GSWIP_PCE_TBL_CTRL_VLD); tbl->valid = !!(crtl & GSWIP_PCE_TBL_CTRL_VLD);
tbl->gmap = (crtl & GSWIP_PCE_TBL_CTRL_GMAP_MASK) >> 7; tbl->gmap = (crtl & GSWIP_PCE_TBL_CTRL_GMAP_MASK) >> 7;
mutex_unlock(&priv->pce_table_lock);
return 0; return 0;
} }
...@@ -574,14 +565,10 @@ static int gswip_pce_table_entry_write(struct gswip_priv *priv, ...@@ -574,14 +565,10 @@ static int gswip_pce_table_entry_write(struct gswip_priv *priv,
u16 addr_mode = tbl->key_mode ? GSWIP_PCE_TBL_CTRL_OPMOD_KSWR : u16 addr_mode = tbl->key_mode ? GSWIP_PCE_TBL_CTRL_OPMOD_KSWR :
GSWIP_PCE_TBL_CTRL_OPMOD_ADWR; GSWIP_PCE_TBL_CTRL_OPMOD_ADWR;
mutex_lock(&priv->pce_table_lock);
err = gswip_switch_r_timeout(priv, GSWIP_PCE_TBL_CTRL, err = gswip_switch_r_timeout(priv, GSWIP_PCE_TBL_CTRL,
GSWIP_PCE_TBL_CTRL_BAS); GSWIP_PCE_TBL_CTRL_BAS);
if (err) { if (err)
mutex_unlock(&priv->pce_table_lock);
return err; return err;
}
gswip_switch_w(priv, tbl->index, GSWIP_PCE_TBL_ADDR); gswip_switch_w(priv, tbl->index, GSWIP_PCE_TBL_ADDR);
gswip_switch_mask(priv, GSWIP_PCE_TBL_CTRL_ADDR_MASK | gswip_switch_mask(priv, GSWIP_PCE_TBL_CTRL_ADDR_MASK |
...@@ -613,12 +600,8 @@ static int gswip_pce_table_entry_write(struct gswip_priv *priv, ...@@ -613,12 +600,8 @@ static int gswip_pce_table_entry_write(struct gswip_priv *priv,
crtl |= GSWIP_PCE_TBL_CTRL_BAS; crtl |= GSWIP_PCE_TBL_CTRL_BAS;
gswip_switch_w(priv, crtl, GSWIP_PCE_TBL_CTRL); gswip_switch_w(priv, crtl, GSWIP_PCE_TBL_CTRL);
err = gswip_switch_r_timeout(priv, GSWIP_PCE_TBL_CTRL, return gswip_switch_r_timeout(priv, GSWIP_PCE_TBL_CTRL,
GSWIP_PCE_TBL_CTRL_BAS); 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 /* Add the LAN port into a bridge with the CPU port by
...@@ -2121,7 +2104,6 @@ static int gswip_probe(struct platform_device *pdev) ...@@ -2121,7 +2104,6 @@ static int gswip_probe(struct platform_device *pdev)
priv->ds->priv = priv; priv->ds->priv = priv;
priv->ds->ops = priv->hw_info->ops; priv->ds->ops = priv->hw_info->ops;
priv->dev = dev; priv->dev = dev;
mutex_init(&priv->pce_table_lock);
version = gswip_switch_r(priv, GSWIP_VERSION); version = gswip_switch_r(priv, GSWIP_VERSION);
np = dev->of_node; np = dev->of_node;
......
...@@ -261,8 +261,6 @@ struct sja1105_private { ...@@ -261,8 +261,6 @@ struct sja1105_private {
* the switch doesn't confuse them with one another. * the switch doesn't confuse them with one another.
*/ */
struct mutex mgmt_lock; struct mutex mgmt_lock;
/* Serializes access to the dynamic config interface */
struct mutex dynamic_config_lock;
struct devlink_region **regions; struct devlink_region **regions;
struct sja1105_cbs_entry *cbs; struct sja1105_cbs_entry *cbs;
struct mii_bus *mdio_base_t1; struct mii_bus *mdio_base_t1;
......
...@@ -1170,56 +1170,6 @@ const struct sja1105_dynamic_table_ops sja1110_dyn_ops[BLK_IDX_MAX_DYN] = { ...@@ -1170,56 +1170,6 @@ const struct sja1105_dynamic_table_ops sja1110_dyn_ops[BLK_IDX_MAX_DYN] = {
}, },
}; };
#define SJA1105_DYNAMIC_CONFIG_SLEEP_US 10
#define SJA1105_DYNAMIC_CONFIG_TIMEOUT_US 100000
static int
sja1105_dynamic_config_poll_valid(struct sja1105_private *priv,
struct sja1105_dyn_cmd *cmd,
const struct sja1105_dynamic_table_ops *ops)
{
u8 packed_buf[SJA1105_MAX_DYN_CMD_SIZE] = {};
int rc;
/* We don't _need_ to read the full entry, just the command area which
* is a fixed SJA1105_SIZE_DYN_CMD. But our cmd_packing() API expects a
* buffer that contains the full entry too. Additionally, our API
* doesn't really know how many bytes into the buffer does the command
* area really begin. So just read back the whole entry.
*/
rc = sja1105_xfer_buf(priv, SPI_READ, ops->addr, packed_buf,
ops->packed_size);
if (rc)
return rc;
/* Unpack the command structure, and return it to the caller in case it
* needs to perform further checks on it (VALIDENT).
*/
memset(cmd, 0, sizeof(*cmd));
ops->cmd_packing(packed_buf, cmd, UNPACK);
/* Hardware hasn't cleared VALID => still working on it */
return cmd->valid ? -EAGAIN : 0;
}
/* Poll the dynamic config entry's control area until the hardware has
* cleared the VALID bit, which means we have confirmation that it has
* finished processing the command.
*/
static int
sja1105_dynamic_config_wait_complete(struct sja1105_private *priv,
struct sja1105_dyn_cmd *cmd,
const struct sja1105_dynamic_table_ops *ops)
{
int rc;
return read_poll_timeout(sja1105_dynamic_config_poll_valid,
rc, rc != -EAGAIN,
SJA1105_DYNAMIC_CONFIG_SLEEP_US,
SJA1105_DYNAMIC_CONFIG_TIMEOUT_US,
false, priv, cmd, ops);
}
/* Provides read access to the settings through the dynamic interface /* Provides read access to the settings through the dynamic interface
* of the switch. * of the switch.
* @blk_idx is used as key to select from the sja1105_dynamic_table_ops. * @blk_idx is used as key to select from the sja1105_dynamic_table_ops.
...@@ -1246,6 +1196,7 @@ int sja1105_dynamic_config_read(struct sja1105_private *priv, ...@@ -1246,6 +1196,7 @@ int sja1105_dynamic_config_read(struct sja1105_private *priv,
struct sja1105_dyn_cmd cmd = {0}; struct sja1105_dyn_cmd cmd = {0};
/* SPI payload buffer */ /* SPI payload buffer */
u8 packed_buf[SJA1105_MAX_DYN_CMD_SIZE] = {0}; u8 packed_buf[SJA1105_MAX_DYN_CMD_SIZE] = {0};
int retries = 3;
int rc; int rc;
if (blk_idx >= BLK_IDX_MAX_DYN) if (blk_idx >= BLK_IDX_MAX_DYN)
...@@ -1283,21 +1234,33 @@ int sja1105_dynamic_config_read(struct sja1105_private *priv, ...@@ -1283,21 +1234,33 @@ int sja1105_dynamic_config_read(struct sja1105_private *priv,
ops->entry_packing(packed_buf, entry, PACK); ops->entry_packing(packed_buf, entry, PACK);
/* Send SPI write operation: read config table entry */ /* Send SPI write operation: read config table entry */
mutex_lock(&priv->dynamic_config_lock);
rc = sja1105_xfer_buf(priv, SPI_WRITE, ops->addr, packed_buf, rc = sja1105_xfer_buf(priv, SPI_WRITE, ops->addr, packed_buf,
ops->packed_size); ops->packed_size);
if (rc < 0) { if (rc < 0)
mutex_unlock(&priv->dynamic_config_lock);
return rc; return rc;
}
rc = sja1105_dynamic_config_wait_complete(priv, &cmd, ops); /* Loop until we have confirmation that hardware has finished
mutex_unlock(&priv->dynamic_config_lock); * processing the command and has cleared the VALID field
*/
do {
memset(packed_buf, 0, ops->packed_size);
/* Retrieve the read operation's result */
rc = sja1105_xfer_buf(priv, SPI_READ, ops->addr, packed_buf,
ops->packed_size);
if (rc < 0) if (rc < 0)
return rc; return rc;
cmd = (struct sja1105_dyn_cmd) {0};
ops->cmd_packing(packed_buf, &cmd, UNPACK);
if (!cmd.valident && !(ops->access & OP_VALID_ANYWAY)) if (!cmd.valident && !(ops->access & OP_VALID_ANYWAY))
return -ENOENT; return -ENOENT;
cpu_relax();
} while (cmd.valid && --retries);
if (cmd.valid)
return -ETIMEDOUT;
/* Don't dereference possibly NULL pointer - maybe caller /* Don't dereference possibly NULL pointer - maybe caller
* only wanted to see whether the entry existed or not. * only wanted to see whether the entry existed or not.
...@@ -1353,16 +1316,8 @@ int sja1105_dynamic_config_write(struct sja1105_private *priv, ...@@ -1353,16 +1316,8 @@ int sja1105_dynamic_config_write(struct sja1105_private *priv,
ops->entry_packing(packed_buf, entry, PACK); ops->entry_packing(packed_buf, entry, PACK);
/* Send SPI write operation: read config table entry */ /* Send SPI write operation: read config table entry */
mutex_lock(&priv->dynamic_config_lock);
rc = sja1105_xfer_buf(priv, SPI_WRITE, ops->addr, packed_buf, rc = sja1105_xfer_buf(priv, SPI_WRITE, ops->addr, packed_buf,
ops->packed_size); ops->packed_size);
if (rc < 0) {
mutex_unlock(&priv->dynamic_config_lock);
return rc;
}
rc = sja1105_dynamic_config_wait_complete(priv, &cmd, ops);
mutex_unlock(&priv->dynamic_config_lock);
if (rc < 0) if (rc < 0)
return rc; return rc;
......
...@@ -3365,7 +3365,6 @@ static int sja1105_probe(struct spi_device *spi) ...@@ -3365,7 +3365,6 @@ static int sja1105_probe(struct spi_device *spi)
priv->ds = ds; priv->ds = ds;
mutex_init(&priv->ptp_data.lock); mutex_init(&priv->ptp_data.lock);
mutex_init(&priv->dynamic_config_lock);
mutex_init(&priv->mgmt_lock); mutex_init(&priv->mgmt_lock);
rc = sja1105_parse_dt(priv); rc = sja1105_parse_dt(priv);
......
...@@ -21,13 +21,11 @@ struct ocelot_mact_entry { ...@@ -21,13 +21,11 @@ struct ocelot_mact_entry {
}; };
static inline u32 ocelot_mact_read_macaccess(struct ocelot *ocelot) static inline u32 ocelot_mact_read_macaccess(struct ocelot *ocelot)
__must_hold(&ocelot->mact_lock)
{ {
return ocelot_read(ocelot, ANA_TABLES_MACACCESS); return ocelot_read(ocelot, ANA_TABLES_MACACCESS);
} }
static inline int ocelot_mact_wait_for_completion(struct ocelot *ocelot) static inline int ocelot_mact_wait_for_completion(struct ocelot *ocelot)
__must_hold(&ocelot->mact_lock)
{ {
u32 val; u32 val;
...@@ -41,7 +39,6 @@ static inline int ocelot_mact_wait_for_completion(struct ocelot *ocelot) ...@@ -41,7 +39,6 @@ static inline int ocelot_mact_wait_for_completion(struct ocelot *ocelot)
static void ocelot_mact_select(struct ocelot *ocelot, static void ocelot_mact_select(struct ocelot *ocelot,
const unsigned char mac[ETH_ALEN], const unsigned char mac[ETH_ALEN],
unsigned int vid) unsigned int vid)
__must_hold(&ocelot->mact_lock)
{ {
u32 macl = 0, mach = 0; u32 macl = 0, mach = 0;
...@@ -70,7 +67,6 @@ int ocelot_mact_learn(struct ocelot *ocelot, int port, ...@@ -70,7 +67,6 @@ int ocelot_mact_learn(struct ocelot *ocelot, int port,
ANA_TABLES_MACACCESS_ENTRYTYPE(type) | ANA_TABLES_MACACCESS_ENTRYTYPE(type) |
ANA_TABLES_MACACCESS_MAC_TABLE_CMD(MACACCESS_CMD_LEARN); ANA_TABLES_MACACCESS_MAC_TABLE_CMD(MACACCESS_CMD_LEARN);
unsigned int mc_ports; unsigned int mc_ports;
int err;
/* Set MAC_CPU_COPY if the CPU port is used by a multicast entry */ /* Set MAC_CPU_COPY if the CPU port is used by a multicast entry */
if (type == ENTRYTYPE_MACv4) if (type == ENTRYTYPE_MACv4)
...@@ -83,28 +79,18 @@ int ocelot_mact_learn(struct ocelot *ocelot, int port, ...@@ -83,28 +79,18 @@ int ocelot_mact_learn(struct ocelot *ocelot, int port,
if (mc_ports & BIT(ocelot->num_phys_ports)) if (mc_ports & BIT(ocelot->num_phys_ports))
cmd |= ANA_TABLES_MACACCESS_MAC_CPU_COPY; cmd |= ANA_TABLES_MACACCESS_MAC_CPU_COPY;
mutex_lock(&ocelot->mact_lock);
ocelot_mact_select(ocelot, mac, vid); ocelot_mact_select(ocelot, mac, vid);
/* Issue a write command */ /* Issue a write command */
ocelot_write(ocelot, cmd, ANA_TABLES_MACACCESS); ocelot_write(ocelot, cmd, ANA_TABLES_MACACCESS);
err = ocelot_mact_wait_for_completion(ocelot); return ocelot_mact_wait_for_completion(ocelot);
mutex_unlock(&ocelot->mact_lock);
return err;
} }
EXPORT_SYMBOL(ocelot_mact_learn); EXPORT_SYMBOL(ocelot_mact_learn);
int ocelot_mact_forget(struct ocelot *ocelot, int ocelot_mact_forget(struct ocelot *ocelot,
const unsigned char mac[ETH_ALEN], unsigned int vid) const unsigned char mac[ETH_ALEN], unsigned int vid)
{ {
int err;
mutex_lock(&ocelot->mact_lock);
ocelot_mact_select(ocelot, mac, vid); ocelot_mact_select(ocelot, mac, vid);
/* Issue a forget command */ /* Issue a forget command */
...@@ -112,11 +98,7 @@ int ocelot_mact_forget(struct ocelot *ocelot, ...@@ -112,11 +98,7 @@ int ocelot_mact_forget(struct ocelot *ocelot,
ANA_TABLES_MACACCESS_MAC_TABLE_CMD(MACACCESS_CMD_FORGET), ANA_TABLES_MACACCESS_MAC_TABLE_CMD(MACACCESS_CMD_FORGET),
ANA_TABLES_MACACCESS); ANA_TABLES_MACACCESS);
err = ocelot_mact_wait_for_completion(ocelot); return ocelot_mact_wait_for_completion(ocelot);
mutex_unlock(&ocelot->mact_lock);
return err;
} }
EXPORT_SYMBOL(ocelot_mact_forget); EXPORT_SYMBOL(ocelot_mact_forget);
...@@ -132,9 +114,7 @@ static void ocelot_mact_init(struct ocelot *ocelot) ...@@ -132,9 +114,7 @@ static void ocelot_mact_init(struct ocelot *ocelot)
| ANA_AGENCTRL_LEARN_IGNORE_VLAN, | ANA_AGENCTRL_LEARN_IGNORE_VLAN,
ANA_AGENCTRL); ANA_AGENCTRL);
/* Clear the MAC table. We are not concurrent with anyone, so /* Clear the MAC table */
* holding &ocelot->mact_lock is pointless.
*/
ocelot_write(ocelot, MACACCESS_CMD_INIT, ANA_TABLES_MACACCESS); ocelot_write(ocelot, MACACCESS_CMD_INIT, ANA_TABLES_MACACCESS);
} }
...@@ -1192,7 +1172,6 @@ EXPORT_SYMBOL(ocelot_port_fdb_do_dump); ...@@ -1192,7 +1172,6 @@ EXPORT_SYMBOL(ocelot_port_fdb_do_dump);
static int ocelot_mact_read(struct ocelot *ocelot, int port, int row, int col, static int ocelot_mact_read(struct ocelot *ocelot, int port, int row, int col,
struct ocelot_mact_entry *entry) struct ocelot_mact_entry *entry)
__must_hold(&ocelot->mact_lock)
{ {
u32 val, dst, macl, mach; u32 val, dst, macl, mach;
char mac[ETH_ALEN]; char mac[ETH_ALEN];
...@@ -1241,40 +1220,33 @@ static int ocelot_mact_read(struct ocelot *ocelot, int port, int row, int col, ...@@ -1241,40 +1220,33 @@ static int ocelot_mact_read(struct ocelot *ocelot, int port, int row, int col,
int ocelot_fdb_dump(struct ocelot *ocelot, int port, int ocelot_fdb_dump(struct ocelot *ocelot, int port,
dsa_fdb_dump_cb_t *cb, void *data) dsa_fdb_dump_cb_t *cb, void *data)
{ {
int err = 0;
int i, j; int i, j;
/* We could take the lock just around ocelot_mact_read, but doing so
* thousands of times in a row seems rather pointless and inefficient.
*/
mutex_lock(&ocelot->mact_lock);
/* Loop through all the mac tables entries. */ /* Loop through all the mac tables entries. */
for (i = 0; i < ocelot->num_mact_rows; i++) { for (i = 0; i < ocelot->num_mact_rows; i++) {
for (j = 0; j < 4; j++) { for (j = 0; j < 4; j++) {
struct ocelot_mact_entry entry; struct ocelot_mact_entry entry;
bool is_static; bool is_static;
int ret;
err = ocelot_mact_read(ocelot, port, i, j, &entry); ret = ocelot_mact_read(ocelot, port, i, j, &entry);
/* If the entry is invalid (wrong port, invalid...), /* If the entry is invalid (wrong port, invalid...),
* skip it. * skip it.
*/ */
if (err == -EINVAL) if (ret == -EINVAL)
continue; continue;
else if (err) else if (ret)
break; return ret;
is_static = (entry.type == ENTRYTYPE_LOCKED); is_static = (entry.type == ENTRYTYPE_LOCKED);
err = cb(entry.mac, entry.vid, is_static, data); ret = cb(entry.mac, entry.vid, is_static, data);
if (err) if (ret)
break; return ret;
} }
} }
mutex_unlock(&ocelot->mact_lock); return 0;
return err;
} }
EXPORT_SYMBOL(ocelot_fdb_dump); EXPORT_SYMBOL(ocelot_fdb_dump);
...@@ -2259,7 +2231,6 @@ int ocelot_init(struct ocelot *ocelot) ...@@ -2259,7 +2231,6 @@ int ocelot_init(struct ocelot *ocelot)
mutex_init(&ocelot->stats_lock); mutex_init(&ocelot->stats_lock);
mutex_init(&ocelot->ptp_lock); mutex_init(&ocelot->ptp_lock);
mutex_init(&ocelot->mact_lock);
spin_lock_init(&ocelot->ptp_clock_lock); spin_lock_init(&ocelot->ptp_clock_lock);
spin_lock_init(&ocelot->ts_id_lock); spin_lock_init(&ocelot->ts_id_lock);
snprintf(queue_name, sizeof(queue_name), "%s-stats", snprintf(queue_name, sizeof(queue_name), "%s-stats",
......
...@@ -287,7 +287,6 @@ struct dsa_port { ...@@ -287,7 +287,6 @@ struct dsa_port {
/* List of MAC addresses that must be forwarded on this port. /* List of MAC addresses that must be forwarded on this port.
* These are only valid on CPU ports and DSA links. * These are only valid on CPU ports and DSA links.
*/ */
struct mutex addr_lists_lock;
struct list_head fdbs; struct list_head fdbs;
struct list_head mdbs; struct list_head mdbs;
......
...@@ -675,9 +675,6 @@ struct ocelot { ...@@ -675,9 +675,6 @@ struct ocelot {
struct delayed_work stats_work; struct delayed_work stats_work;
struct workqueue_struct *stats_queue; struct workqueue_struct *stats_queue;
/* Lock for serializing access to the MAC table */
struct mutex mact_lock;
struct workqueue_struct *owq; struct workqueue_struct *owq;
u8 ptp:1; u8 ptp:1;
......
...@@ -433,7 +433,6 @@ static int dsa_port_setup(struct dsa_port *dp) ...@@ -433,7 +433,6 @@ static int dsa_port_setup(struct dsa_port *dp)
if (dp->setup) if (dp->setup)
return 0; return 0;
mutex_init(&dp->addr_lists_lock);
INIT_LIST_HEAD(&dp->fdbs); INIT_LIST_HEAD(&dp->fdbs);
INIT_LIST_HEAD(&dp->mdbs); INIT_LIST_HEAD(&dp->mdbs);
......
...@@ -2413,6 +2413,7 @@ static void dsa_slave_switchdev_event_work(struct work_struct *work) ...@@ -2413,6 +2413,7 @@ static void dsa_slave_switchdev_event_work(struct work_struct *work)
dp = dsa_to_port(ds, switchdev_work->port); dp = dsa_to_port(ds, switchdev_work->port);
rtnl_lock();
switch (switchdev_work->event) { switch (switchdev_work->event) {
case SWITCHDEV_FDB_ADD_TO_DEVICE: case SWITCHDEV_FDB_ADD_TO_DEVICE:
if (switchdev_work->host_addr) if (switchdev_work->host_addr)
...@@ -2447,6 +2448,7 @@ static void dsa_slave_switchdev_event_work(struct work_struct *work) ...@@ -2447,6 +2448,7 @@ static void dsa_slave_switchdev_event_work(struct work_struct *work)
break; break;
} }
rtnl_unlock();
dev_put(switchdev_work->dev); dev_put(switchdev_work->dev);
kfree(switchdev_work); kfree(switchdev_work);
......
...@@ -215,30 +215,26 @@ static int dsa_port_do_mdb_add(struct dsa_port *dp, ...@@ -215,30 +215,26 @@ static int dsa_port_do_mdb_add(struct dsa_port *dp,
struct dsa_switch *ds = dp->ds; struct dsa_switch *ds = dp->ds;
struct dsa_mac_addr *a; struct dsa_mac_addr *a;
int port = dp->index; int port = dp->index;
int err = 0; int err;
/* No need to bother with refcounting for user ports */ /* No need to bother with refcounting for user ports */
if (!(dsa_port_is_cpu(dp) || dsa_port_is_dsa(dp))) if (!(dsa_port_is_cpu(dp) || dsa_port_is_dsa(dp)))
return ds->ops->port_mdb_add(ds, port, mdb); return ds->ops->port_mdb_add(ds, port, mdb);
mutex_lock(&dp->addr_lists_lock);
a = dsa_mac_addr_find(&dp->mdbs, mdb->addr, mdb->vid); a = dsa_mac_addr_find(&dp->mdbs, mdb->addr, mdb->vid);
if (a) { if (a) {
refcount_inc(&a->refcount); refcount_inc(&a->refcount);
goto out; return 0;
} }
a = kzalloc(sizeof(*a), GFP_KERNEL); a = kzalloc(sizeof(*a), GFP_KERNEL);
if (!a) { if (!a)
err = -ENOMEM; return -ENOMEM;
goto out;
}
err = ds->ops->port_mdb_add(ds, port, mdb); err = ds->ops->port_mdb_add(ds, port, mdb);
if (err) { if (err) {
kfree(a); kfree(a);
goto out; return err;
} }
ether_addr_copy(a->addr, mdb->addr); ether_addr_copy(a->addr, mdb->addr);
...@@ -246,10 +242,7 @@ static int dsa_port_do_mdb_add(struct dsa_port *dp, ...@@ -246,10 +242,7 @@ static int dsa_port_do_mdb_add(struct dsa_port *dp,
refcount_set(&a->refcount, 1); refcount_set(&a->refcount, 1);
list_add_tail(&a->list, &dp->mdbs); list_add_tail(&a->list, &dp->mdbs);
out: return 0;
mutex_unlock(&dp->addr_lists_lock);
return err;
} }
static int dsa_port_do_mdb_del(struct dsa_port *dp, static int dsa_port_do_mdb_del(struct dsa_port *dp,
...@@ -258,36 +251,29 @@ static int dsa_port_do_mdb_del(struct dsa_port *dp, ...@@ -258,36 +251,29 @@ static int dsa_port_do_mdb_del(struct dsa_port *dp,
struct dsa_switch *ds = dp->ds; struct dsa_switch *ds = dp->ds;
struct dsa_mac_addr *a; struct dsa_mac_addr *a;
int port = dp->index; int port = dp->index;
int err = 0; int err;
/* No need to bother with refcounting for user ports */ /* No need to bother with refcounting for user ports */
if (!(dsa_port_is_cpu(dp) || dsa_port_is_dsa(dp))) if (!(dsa_port_is_cpu(dp) || dsa_port_is_dsa(dp)))
return ds->ops->port_mdb_del(ds, port, mdb); return ds->ops->port_mdb_del(ds, port, mdb);
mutex_lock(&dp->addr_lists_lock);
a = dsa_mac_addr_find(&dp->mdbs, mdb->addr, mdb->vid); a = dsa_mac_addr_find(&dp->mdbs, mdb->addr, mdb->vid);
if (!a) { if (!a)
err = -ENOENT; return -ENOENT;
goto out;
}
if (!refcount_dec_and_test(&a->refcount)) if (!refcount_dec_and_test(&a->refcount))
goto out; return 0;
err = ds->ops->port_mdb_del(ds, port, mdb); err = ds->ops->port_mdb_del(ds, port, mdb);
if (err) { if (err) {
refcount_inc(&a->refcount); refcount_inc(&a->refcount);
goto out; return err;
} }
list_del(&a->list); list_del(&a->list);
kfree(a); kfree(a);
out: return 0;
mutex_unlock(&dp->addr_lists_lock);
return err;
} }
static int dsa_port_do_fdb_add(struct dsa_port *dp, const unsigned char *addr, static int dsa_port_do_fdb_add(struct dsa_port *dp, const unsigned char *addr,
...@@ -296,30 +282,26 @@ static int dsa_port_do_fdb_add(struct dsa_port *dp, const unsigned char *addr, ...@@ -296,30 +282,26 @@ static int dsa_port_do_fdb_add(struct dsa_port *dp, const unsigned char *addr,
struct dsa_switch *ds = dp->ds; struct dsa_switch *ds = dp->ds;
struct dsa_mac_addr *a; struct dsa_mac_addr *a;
int port = dp->index; int port = dp->index;
int err = 0; int err;
/* No need to bother with refcounting for user ports */ /* No need to bother with refcounting for user ports */
if (!(dsa_port_is_cpu(dp) || dsa_port_is_dsa(dp))) if (!(dsa_port_is_cpu(dp) || dsa_port_is_dsa(dp)))
return ds->ops->port_fdb_add(ds, port, addr, vid); return ds->ops->port_fdb_add(ds, port, addr, vid);
mutex_lock(&dp->addr_lists_lock);
a = dsa_mac_addr_find(&dp->fdbs, addr, vid); a = dsa_mac_addr_find(&dp->fdbs, addr, vid);
if (a) { if (a) {
refcount_inc(&a->refcount); refcount_inc(&a->refcount);
goto out; return 0;
} }
a = kzalloc(sizeof(*a), GFP_KERNEL); a = kzalloc(sizeof(*a), GFP_KERNEL);
if (!a) { if (!a)
err = -ENOMEM; return -ENOMEM;
goto out;
}
err = ds->ops->port_fdb_add(ds, port, addr, vid); err = ds->ops->port_fdb_add(ds, port, addr, vid);
if (err) { if (err) {
kfree(a); kfree(a);
goto out; return err;
} }
ether_addr_copy(a->addr, addr); ether_addr_copy(a->addr, addr);
...@@ -327,10 +309,7 @@ static int dsa_port_do_fdb_add(struct dsa_port *dp, const unsigned char *addr, ...@@ -327,10 +309,7 @@ static int dsa_port_do_fdb_add(struct dsa_port *dp, const unsigned char *addr,
refcount_set(&a->refcount, 1); refcount_set(&a->refcount, 1);
list_add_tail(&a->list, &dp->fdbs); list_add_tail(&a->list, &dp->fdbs);
out: return 0;
mutex_unlock(&dp->addr_lists_lock);
return err;
} }
static int dsa_port_do_fdb_del(struct dsa_port *dp, const unsigned char *addr, static int dsa_port_do_fdb_del(struct dsa_port *dp, const unsigned char *addr,
...@@ -339,36 +318,29 @@ static int dsa_port_do_fdb_del(struct dsa_port *dp, const unsigned char *addr, ...@@ -339,36 +318,29 @@ static int dsa_port_do_fdb_del(struct dsa_port *dp, const unsigned char *addr,
struct dsa_switch *ds = dp->ds; struct dsa_switch *ds = dp->ds;
struct dsa_mac_addr *a; struct dsa_mac_addr *a;
int port = dp->index; int port = dp->index;
int err = 0; int err;
/* No need to bother with refcounting for user ports */ /* No need to bother with refcounting for user ports */
if (!(dsa_port_is_cpu(dp) || dsa_port_is_dsa(dp))) if (!(dsa_port_is_cpu(dp) || dsa_port_is_dsa(dp)))
return ds->ops->port_fdb_del(ds, port, addr, vid); return ds->ops->port_fdb_del(ds, port, addr, vid);
mutex_lock(&dp->addr_lists_lock);
a = dsa_mac_addr_find(&dp->fdbs, addr, vid); a = dsa_mac_addr_find(&dp->fdbs, addr, vid);
if (!a) { if (!a)
err = -ENOENT; return -ENOENT;
goto out;
}
if (!refcount_dec_and_test(&a->refcount)) if (!refcount_dec_and_test(&a->refcount))
goto out; return 0;
err = ds->ops->port_fdb_del(ds, port, addr, vid); err = ds->ops->port_fdb_del(ds, port, addr, vid);
if (err) { if (err) {
refcount_inc(&a->refcount); refcount_inc(&a->refcount);
goto out; return err;
} }
list_del(&a->list); list_del(&a->list);
kfree(a); kfree(a);
out: return 0;
mutex_unlock(&dp->addr_lists_lock);
return err;
} }
static int dsa_switch_host_fdb_add(struct dsa_switch *ds, static int dsa_switch_host_fdb_add(struct dsa_switch *ds,
......
#!/bin/bash
# SPDX-License-Identifier: GPL-2.0
# Bridge FDB entries can be offloaded to DSA switches without holding the
# rtnl_mutex. Traditionally this mutex has conferred drivers implicit
# serialization, which means their code paths are not well tested in the
# presence of concurrency.
# This test creates a background task that stresses the FDB by adding and
# deleting an entry many times in a row without the rtnl_mutex held.
# It then tests the driver resistance to concurrency by calling .ndo_fdb_dump
# (with rtnl_mutex held) from a foreground task.
# Since either the FDB dump or the additions/removals can fail, but the
# additions and removals are performed in deferred as opposed to process
# context, we cannot simply check for user space error codes.
WAIT_TIME=1
NUM_NETIFS=1
REQUIRE_JQ="no"
REQUIRE_MZ="no"
NETIF_CREATE="no"
lib_dir=$(dirname $0)/../../../net/forwarding
source $lib_dir/lib.sh
cleanup() {
echo "Cleaning up"
kill $pid && wait $pid &> /dev/null
ip link del br0
echo "Please check kernel log for errors"
}
trap 'cleanup' EXIT
eth=${NETIFS[p1]}
ip link del br0 2&>1 >/dev/null || :
ip link add br0 type bridge && ip link set $eth master br0
(while :; do
bridge fdb add 00:01:02:03:04:05 dev $eth master static
bridge fdb del 00:01:02:03:04:05 dev $eth master static
done) &
pid=$!
for i in $(seq 1 50); do
bridge fdb show > /dev/null
sleep 3
echo "$((${i} * 2))% complete..."
done
...@@ -23,8 +23,6 @@ MC_CLI=${MC_CLI:=smcroutectl} ...@@ -23,8 +23,6 @@ MC_CLI=${MC_CLI:=smcroutectl}
PING_TIMEOUT=${PING_TIMEOUT:=5} PING_TIMEOUT=${PING_TIMEOUT:=5}
WAIT_TIMEOUT=${WAIT_TIMEOUT:=20} WAIT_TIMEOUT=${WAIT_TIMEOUT:=20}
INTERFACE_TIMEOUT=${INTERFACE_TIMEOUT:=600} INTERFACE_TIMEOUT=${INTERFACE_TIMEOUT:=600}
REQUIRE_JQ=${REQUIRE_JQ:=yes}
REQUIRE_MZ=${REQUIRE_MZ:=yes}
relative_path="${BASH_SOURCE%/*}" relative_path="${BASH_SOURCE%/*}"
if [[ "$relative_path" == "${BASH_SOURCE}" ]]; then if [[ "$relative_path" == "${BASH_SOURCE}" ]]; then
...@@ -143,12 +141,8 @@ require_command() ...@@ -143,12 +141,8 @@ require_command()
fi fi
} }
if [[ "$REQUIRE_JQ" = "yes" ]]; then require_command jq
require_command jq require_command $MZ
fi
if [[ "$REQUIRE_MZ" = "yes" ]]; then
require_command $MZ
fi
if [[ ! -v NUM_NETIFS ]]; then if [[ ! -v NUM_NETIFS ]]; then
echo "SKIP: importer does not define \"NUM_NETIFS\"" echo "SKIP: importer does not define \"NUM_NETIFS\""
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment