On Mon, Nov 15, 2021 at 06:01:33PM +0100, Greg Kroah-Hartman wrote: > From: Vladimir Oltean <vladimir.oltean@xxxxxxx> > > [ Upstream commit 49753a75b9a32de4c0393bb8d1e51ea223fda8e4 ] > > Looking at the code, the GSWIP switch appears to hold bridging service > structures (VLANs, FDBs, forwarding rules) in PCE table entries. > Hardware access to the PCE table is non-atomic, and is comprised of > several register reads and writes. > > These accesses are currently serialized by the rtnl_lock, but DSA is > changing its driver API and that lock will no longer be held when > calling ->port_fdb_add() and ->port_fdb_del(). > > So this driver needs to serialize the access to the PCE table using its > own locking scheme. This patch adds that. > > Signed-off-by: Vladimir Oltean <vladimir.oltean@xxxxxxx> > Reviewed-by: Florian Fainelli <f.fainelli@xxxxxxxxx> > Acked-by: Hauke Mehrtens <hauke@xxxxxxxxxx> > Signed-off-by: David S. Miller <davem@xxxxxxxxxxxxx> > Signed-off-by: Sasha Levin <sashal@xxxxxxxxxx> > --- > drivers/net/dsa/lantiq_gswip.c | 28 +++++++++++++++++++++++----- > 1 file changed, 23 insertions(+), 5 deletions(-) > > diff --git a/drivers/net/dsa/lantiq_gswip.c b/drivers/net/dsa/lantiq_gswip.c > index 60e36f46f8abe..d612ef8648baa 100644 > --- a/drivers/net/dsa/lantiq_gswip.c > +++ b/drivers/net/dsa/lantiq_gswip.c > @@ -274,6 +274,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 { > @@ -521,10 +522,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 | > @@ -534,8 +539,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)); > @@ -551,6 +558,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; > } > > @@ -563,10 +572,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 | > @@ -598,8 +611,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, > - GSWIP_PCE_TBL_CTRL_BAS); > + 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 > @@ -2020,6 +2037,7 @@ static int gswip_probe(struct platform_device *pdev) > priv->ds->priv = priv; > priv->ds->ops = &gswip_switch_ops; > priv->dev = dev; > + mutex_init(&priv->pce_table_lock); > version = gswip_switch_r(priv, GSWIP_VERSION); > > /* bring up the mdio bus */ > -- > 2.33.0 > > > As discussed on the v5.14 backport, this patch can be dropped. Same thing for the 5.10 version of the backport.