summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorRavi Gunasekaran <r-gunasekaran@ti.com>2024-03-12 15:57:00 +0530
committerPraneeth Bajjuri <praneeth@ti.com>2024-03-12 15:51:03 -0500
commit902a51e8a5c8bf2f9efbd76a750665878dae063b (patch)
tree4eaa5e95ca663b1bec351856e278110fc43c209b
parenta082ce3b5578703fd9379919a1a9aab7c64e8c96 (diff)
net: ethernet: ti: icssg_prueth: Fix race condition for VLAN table access
The VLAN table is a shared memory between the two ports/slices in a ICSSG cluster and this may lead to race condition when the common code paths for both ports are executed in different CPUs. Fix the race condition access by locking the shared memory access. Signed-off-by: Ravi Gunasekaran <r-gunasekaran@ti.com>
-rw-r--r--drivers/net/ethernet/ti/icssg_config.c11
-rw-r--r--drivers/net/ethernet/ti/icssg_prueth.c1
-rw-r--r--drivers/net/ethernet/ti/icssg_prueth.h1
3 files changed, 11 insertions, 2 deletions
diff --git a/drivers/net/ethernet/ti/icssg_config.c b/drivers/net/ethernet/ti/icssg_config.c
index 9d34ec0cb682..88dc611f0fc6 100644
--- a/drivers/net/ethernet/ti/icssg_config.c
+++ b/drivers/net/ethernet/ti/icssg_config.c
@@ -771,7 +771,10 @@ void icssg_vtbl_modify(struct prueth_emac *emac, u8 vid, u8 port_mask,
{
struct prueth *prueth = emac->prueth;
struct prueth_vlan_tbl *tbl = prueth->vlan_tbl;
- u8 fid_c1 = tbl[vid].fid_c1;
+ u8 fid_c1;
+
+ spin_lock(&prueth->vtbl_lock);
+ fid_c1 = tbl[vid].fid_c1;
/* FID_C1: bit0..2 port membership mask,
* bit3..5 tagging mask for each port
@@ -786,6 +789,7 @@ void icssg_vtbl_modify(struct prueth_emac *emac, u8 vid, u8 port_mask,
}
tbl[vid].fid_c1 = fid_c1;
+ spin_unlock(&prueth->vtbl_lock);
}
u16 icssg_get_pvid(struct prueth_emac *emac)
@@ -848,15 +852,18 @@ int emac_fdb_erase_all(struct prueth_emac *emac)
int emac_fdb_flush_multicast(struct prueth_emac *emac)
{
struct prueth *prueth = emac->prueth;
+ u8 port_mask = BIT(emac->port_id);
int ret = 0;
int i;
ret = emac_fdb_erase_all(emac);
+ spin_lock(&prueth->vtbl_lock);
for (i = 0; i < SZ_4K - 1; i++) {
prueth->vlan_tbl[i].fid = i;
- prueth->vlan_tbl[i].fid_c1 = 0;
+ prueth->vlan_tbl[i].fid_c1 &= ~(port_mask | port_mask << 3);
}
+ spin_unlock(&prueth->vtbl_lock);
return ret;
}
diff --git a/drivers/net/ethernet/ti/icssg_prueth.c b/drivers/net/ethernet/ti/icssg_prueth.c
index 56a2f6c622b3..f3d033723857 100644
--- a/drivers/net/ethernet/ti/icssg_prueth.c
+++ b/drivers/net/ethernet/ti/icssg_prueth.c
@@ -3298,6 +3298,7 @@ static int prueth_probe(struct platform_device *pdev)
icss_iep_init_fw(prueth->iep1);
}
+ spin_lock_init(&prueth->vtbl_lock);
/* setup netdev interfaces */
if (eth0_node) {
ret = prueth_netdev_init(prueth, eth0_node);
diff --git a/drivers/net/ethernet/ti/icssg_prueth.h b/drivers/net/ethernet/ti/icssg_prueth.h
index 03ec5b8438c2..0534c3b256ea 100644
--- a/drivers/net/ethernet/ti/icssg_prueth.h
+++ b/drivers/net/ethernet/ti/icssg_prueth.h
@@ -330,6 +330,7 @@ struct prueth {
unsigned char switch_id[MAX_PHYS_ITEM_ID_LEN];
int default_vlan;
struct devlink *devlink;
+ spinlock_t vtbl_lock; /* Lock for vtbl in shared memory */
};
struct emac_tx_ts_response {