Skip to content

Commit c192468

Browse files
HoratiuVulturkuba-moo
authored andcommitted
net: lan966x: Fix usage of lan966x->mac_lock inside lan966x_mac_irq_handler
The problem with this spin lock is that it was just protecting the list of the MAC entries in SW and not also the access to the MAC entries in HW. Because the access to HW is indirect, then it could happen to have race conditions. For example when SW introduced an entry in MAC table and the irq mac is trying to read something from the MAC. Update such that also the access to MAC entries in HW is protected by this lock. Fixes: 5ccd66e ("net: lan966x: add support for interrupts from analyzer") Signed-off-by: Horatiu Vultur <horatiu.vultur@microchip.com> Reviewed-by: Vladimir Oltean <vladimir.oltean@nxp.com> Signed-off-by: Jakub Kicinski <kuba@kernel.org>
1 parent 99343cf commit c192468

1 file changed

Lines changed: 12 additions & 7 deletions

File tree

drivers/net/ethernet/microchip/lan966x/lan966x_mac.c

Lines changed: 12 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -183,7 +183,7 @@ static struct lan966x_mac_entry *lan966x_mac_alloc_entry(const unsigned char *ma
183183
{
184184
struct lan966x_mac_entry *mac_entry;
185185

186-
mac_entry = kzalloc(sizeof(*mac_entry), GFP_KERNEL);
186+
mac_entry = kzalloc(sizeof(*mac_entry), GFP_ATOMIC);
187187
if (!mac_entry)
188188
return NULL;
189189

@@ -310,8 +310,8 @@ void lan966x_mac_purge_entries(struct lan966x *lan966x)
310310
spin_lock(&lan966x->mac_lock);
311311
list_for_each_entry_safe(mac_entry, tmp, &lan966x->mac_entries,
312312
list) {
313-
lan966x_mac_forget(lan966x, mac_entry->mac, mac_entry->vid,
314-
ENTRYTYPE_LOCKED);
313+
lan966x_mac_forget_locked(lan966x, mac_entry->mac,
314+
mac_entry->vid, ENTRYTYPE_LOCKED);
315315

316316
list_del(&mac_entry->list);
317317
kfree(mac_entry);
@@ -427,13 +427,14 @@ static void lan966x_mac_irq_process(struct lan966x *lan966x, u32 row,
427427
if (WARN_ON(dest_idx >= lan966x->num_phys_ports))
428428
continue;
429429

430+
spin_lock(&lan966x->mac_lock);
430431
mac_entry = lan966x_mac_alloc_entry(mac, vid, dest_idx);
431-
if (!mac_entry)
432+
if (!mac_entry) {
433+
spin_unlock(&lan966x->mac_lock);
432434
return;
435+
}
433436

434437
mac_entry->row = row;
435-
436-
spin_lock(&lan966x->mac_lock);
437438
list_add_tail(&mac_entry->list, &lan966x->mac_entries);
438439
spin_unlock(&lan966x->mac_lock);
439440

@@ -455,6 +456,7 @@ irqreturn_t lan966x_mac_irq_handler(struct lan966x *lan966x)
455456
lan966x, ANA_MACTINDX);
456457

457458
while (1) {
459+
spin_lock(&lan966x->mac_lock);
458460
lan_rmw(ANA_MACACCESS_MAC_TABLE_CMD_SET(MACACCESS_CMD_SYNC_GET_NEXT),
459461
ANA_MACACCESS_MAC_TABLE_CMD,
460462
lan966x, ANA_MACACCESS);
@@ -478,12 +480,15 @@ irqreturn_t lan966x_mac_irq_handler(struct lan966x *lan966x)
478480
stop = false;
479481

480482
if (column == LAN966X_MAC_COLUMNS - 1 &&
481-
index == 0 && stop)
483+
index == 0 && stop) {
484+
spin_unlock(&lan966x->mac_lock);
482485
break;
486+
}
483487

484488
entry[column].mach = lan_rd(lan966x, ANA_MACHDATA);
485489
entry[column].macl = lan_rd(lan966x, ANA_MACLDATA);
486490
entry[column].maca = lan_rd(lan966x, ANA_MACACCESS);
491+
spin_unlock(&lan966x->mac_lock);
487492

488493
/* Once all the columns are read process them */
489494
if (column == LAN966X_MAC_COLUMNS - 1) {

0 commit comments

Comments
 (0)