Skip to content

Commit 8125528

Browse files
linuswkuba-moo
authored andcommitted
net: ethernet: cortina: Locking fixes
This fixes a probably long standing problem in the Cortina Gemini ethernet driver: there are some paths in the code where the IRQ registers are written without taking the proper locks. Fixes: 4d5ae32 ("net: ethernet: Add a driver for Gemini gigabit ethernet") Signed-off-by: Linus Walleij <[email protected]> Reviewed-by: Simon Horman <[email protected]> Link: https://lore.kernel.org/r/[email protected] Signed-off-by: Jakub Kicinski <[email protected]>
1 parent 6d51d44 commit 8125528

File tree

1 file changed

+10
-2
lines changed

1 file changed

+10
-2
lines changed

drivers/net/ethernet/cortina/gemini.c

Lines changed: 10 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1107,10 +1107,13 @@ static void gmac_tx_irq_enable(struct net_device *netdev,
11071107
{
11081108
struct gemini_ethernet_port *port = netdev_priv(netdev);
11091109
struct gemini_ethernet *geth = port->geth;
1110+
unsigned long flags;
11101111
u32 val, mask;
11111112

11121113
netdev_dbg(netdev, "%s device %d\n", __func__, netdev->dev_id);
11131114

1115+
spin_lock_irqsave(&geth->irq_lock, flags);
1116+
11141117
mask = GMAC0_IRQ0_TXQ0_INTS << (6 * netdev->dev_id + txq);
11151118

11161119
if (en)
@@ -1119,6 +1122,8 @@ static void gmac_tx_irq_enable(struct net_device *netdev,
11191122
val = readl(geth->base + GLOBAL_INTERRUPT_ENABLE_0_REG);
11201123
val = en ? val | mask : val & ~mask;
11211124
writel(val, geth->base + GLOBAL_INTERRUPT_ENABLE_0_REG);
1125+
1126+
spin_unlock_irqrestore(&geth->irq_lock, flags);
11221127
}
11231128

11241129
static void gmac_tx_irq(struct net_device *netdev, unsigned int txq_num)
@@ -1415,15 +1420,19 @@ static unsigned int gmac_rx(struct net_device *netdev, unsigned int budget)
14151420
union gmac_rxdesc_3 word3;
14161421
struct page *page = NULL;
14171422
unsigned int page_offs;
1423+
unsigned long flags;
14181424
unsigned short r, w;
14191425
union dma_rwptr rw;
14201426
dma_addr_t mapping;
14211427
int frag_nr = 0;
14221428

1429+
spin_lock_irqsave(&geth->irq_lock, flags);
14231430
rw.bits32 = readl(ptr_reg);
14241431
/* Reset interrupt as all packages until here are taken into account */
14251432
writel(DEFAULT_Q0_INT_BIT << netdev->dev_id,
14261433
geth->base + GLOBAL_INTERRUPT_STATUS_1_REG);
1434+
spin_unlock_irqrestore(&geth->irq_lock, flags);
1435+
14271436
r = rw.bits.rptr;
14281437
w = rw.bits.wptr;
14291438

@@ -1726,10 +1735,9 @@ static irqreturn_t gmac_irq(int irq, void *data)
17261735
gmac_update_hw_stats(netdev);
17271736

17281737
if (val & (GMAC0_RX_OVERRUN_INT_BIT << (netdev->dev_id * 8))) {
1738+
spin_lock(&geth->irq_lock);
17291739
writel(GMAC0_RXDERR_INT_BIT << (netdev->dev_id * 8),
17301740
geth->base + GLOBAL_INTERRUPT_STATUS_4_REG);
1731-
1732-
spin_lock(&geth->irq_lock);
17331741
u64_stats_update_begin(&port->ir_stats_syncp);
17341742
++port->stats.rx_fifo_errors;
17351743
u64_stats_update_end(&port->ir_stats_syncp);

0 commit comments

Comments
 (0)