diff options
author | Ravi Gunasekaran <r-gunasekaran@ti.com> | 2024-03-12 15:57:00 +0530 |
---|---|---|
committer | Praneeth Bajjuri <praneeth@ti.com> | 2024-03-12 15:51:03 -0500 |
commit | 902a51e8a5c8bf2f9efbd76a750665878dae063b (patch) | |
tree | 4eaa5e95ca663b1bec351856e278110fc43c209b | |
parent | a082ce3b5578703fd9379919a1a9aab7c64e8c96 (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.c | 11 | ||||
-rw-r--r-- | drivers/net/ethernet/ti/icssg_prueth.c | 1 | ||||
-rw-r--r-- | drivers/net/ethernet/ti/icssg_prueth.h | 1 |
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 { |