Skip to content

Commit

Permalink
Merge branch 'eth-fix-calling-napi_enable-in-atomic-context'
Browse files Browse the repository at this point in the history
Jakub Kicinski says:

====================
eth: fix calling napi_enable() in atomic context

Dan has reported that I missed a lot of drivers which call napi_enable()
in atomic with the naive coccinelle search for spin locks:
https://lore.kernel.org/dcfd56bc-de32-4b11-9e19-d8bd1543745d@stanley.mountain

Fix them. Most of the fixes involve taking the netdev_lock()
before the spin lock. mt76 is special because we can just
move napi_enable() from the BH section.

All patches compile tested only.

v2: https://lore.kernel.org/20250123004520.806855-1-kuba@kernel.org
v1: https://lore.kernel.org/20250121221519.392014-1-kuba@kernel.org
====================

Link: https://patch.msgid.link/20250124031841.1179756-1-kuba@kernel.org
Signed-off-by: Jakub Kicinski <kuba@kernel.org>
  • Loading branch information
Jakub Kicinski committed Jan 27, 2025
2 parents 964417a + a605586 commit f17b15d
Show file tree
Hide file tree
Showing 17 changed files with 132 additions and 65 deletions.
35 changes: 31 additions & 4 deletions drivers/net/ethernet/broadcom/tg3.c
Original file line number Diff line number Diff line change
Expand Up @@ -7424,7 +7424,7 @@ static void tg3_napi_enable(struct tg3 *tp)

for (i = 0; i < tp->irq_cnt; i++) {
tnapi = &tp->napi[i];
napi_enable(&tnapi->napi);
napi_enable_locked(&tnapi->napi);
if (tnapi->tx_buffers) {
netif_queue_set_napi(tp->dev, txq_idx,
NETDEV_QUEUE_TYPE_TX,
Expand All @@ -7445,9 +7445,10 @@ static void tg3_napi_init(struct tg3 *tp)
int i;

for (i = 0; i < tp->irq_cnt; i++) {
netif_napi_add(tp->dev, &tp->napi[i].napi,
i ? tg3_poll_msix : tg3_poll);
netif_napi_set_irq(&tp->napi[i].napi, tp->napi[i].irq_vec);
netif_napi_add_locked(tp->dev, &tp->napi[i].napi,
i ? tg3_poll_msix : tg3_poll);
netif_napi_set_irq_locked(&tp->napi[i].napi,
tp->napi[i].irq_vec);
}
}

Expand Down Expand Up @@ -11259,6 +11260,8 @@ static void tg3_timer_stop(struct tg3 *tp)
static int tg3_restart_hw(struct tg3 *tp, bool reset_phy)
__releases(tp->lock)
__acquires(tp->lock)
__releases(tp->dev->lock)
__acquires(tp->dev->lock)
{
int err;

Expand All @@ -11271,7 +11274,9 @@ static int tg3_restart_hw(struct tg3 *tp, bool reset_phy)
tg3_timer_stop(tp);
tp->irq_sync = 0;
tg3_napi_enable(tp);
netdev_unlock(tp->dev);
dev_close(tp->dev);
netdev_lock(tp->dev);
tg3_full_lock(tp, 0);
}
return err;
Expand Down Expand Up @@ -11299,6 +11304,7 @@ static void tg3_reset_task(struct work_struct *work)

tg3_netif_stop(tp);

netdev_lock(tp->dev);
tg3_full_lock(tp, 1);

if (tg3_flag(tp, TX_RECOVERY_PENDING)) {
Expand All @@ -11318,12 +11324,14 @@ static void tg3_reset_task(struct work_struct *work)
* call cancel_work_sync() and wait forever.
*/
tg3_flag_clear(tp, RESET_TASK_PENDING);
netdev_unlock(tp->dev);
dev_close(tp->dev);
goto out;
}

tg3_netif_start(tp);
tg3_full_unlock(tp);
netdev_unlock(tp->dev);
tg3_phy_start(tp);
tg3_flag_clear(tp, RESET_TASK_PENDING);
out:
Expand Down Expand Up @@ -11683,9 +11691,11 @@ static int tg3_start(struct tg3 *tp, bool reset_phy, bool test_irq,
if (err)
goto out_ints_fini;

netdev_lock(dev);
tg3_napi_init(tp);

tg3_napi_enable(tp);
netdev_unlock(dev);

for (i = 0; i < tp->irq_cnt; i++) {
err = tg3_request_irq(tp, i);
Expand Down Expand Up @@ -12569,6 +12579,7 @@ static int tg3_set_ringparam(struct net_device *dev,
irq_sync = 1;
}

netdev_lock(dev);
tg3_full_lock(tp, irq_sync);

tp->rx_pending = ering->rx_pending;
Expand Down Expand Up @@ -12597,6 +12608,7 @@ static int tg3_set_ringparam(struct net_device *dev,
}

tg3_full_unlock(tp);
netdev_unlock(dev);

if (irq_sync && !err)
tg3_phy_start(tp);
Expand Down Expand Up @@ -12678,6 +12690,7 @@ static int tg3_set_pauseparam(struct net_device *dev, struct ethtool_pauseparam
irq_sync = 1;
}

netdev_lock(dev);
tg3_full_lock(tp, irq_sync);

if (epause->autoneg)
Expand Down Expand Up @@ -12707,6 +12720,7 @@ static int tg3_set_pauseparam(struct net_device *dev, struct ethtool_pauseparam
}

tg3_full_unlock(tp);
netdev_unlock(dev);
}

tp->phy_flags |= TG3_PHYFLG_USER_CONFIGURED;
Expand Down Expand Up @@ -13911,6 +13925,7 @@ static void tg3_self_test(struct net_device *dev, struct ethtool_test *etest,
data[TG3_INTERRUPT_TEST] = 1;
}

netdev_lock(dev);
tg3_full_lock(tp, 0);

tg3_halt(tp, RESET_KIND_SHUTDOWN, 1);
Expand All @@ -13922,6 +13937,7 @@ static void tg3_self_test(struct net_device *dev, struct ethtool_test *etest,
}

tg3_full_unlock(tp);
netdev_unlock(dev);

if (irq_sync && !err2)
tg3_phy_start(tp);
Expand Down Expand Up @@ -14365,6 +14381,7 @@ static int tg3_change_mtu(struct net_device *dev, int new_mtu)

tg3_set_mtu(dev, tp, new_mtu);

netdev_lock(dev);
tg3_full_lock(tp, 1);

tg3_halt(tp, RESET_KIND_SHUTDOWN, 1);
Expand All @@ -14384,6 +14401,7 @@ static int tg3_change_mtu(struct net_device *dev, int new_mtu)
tg3_netif_start(tp);

tg3_full_unlock(tp);
netdev_unlock(dev);

if (!err)
tg3_phy_start(tp);
Expand Down Expand Up @@ -18164,6 +18182,7 @@ static int tg3_resume(struct device *device)

netif_device_attach(dev);

netdev_lock(dev);
tg3_full_lock(tp, 0);

tg3_ape_driver_state_change(tp, RESET_KIND_INIT);
Expand All @@ -18180,6 +18199,7 @@ static int tg3_resume(struct device *device)

out:
tg3_full_unlock(tp);
netdev_unlock(dev);

if (!err)
tg3_phy_start(tp);
Expand Down Expand Up @@ -18260,7 +18280,9 @@ static pci_ers_result_t tg3_io_error_detected(struct pci_dev *pdev,
done:
if (state == pci_channel_io_perm_failure) {
if (netdev) {
netdev_lock(netdev);
tg3_napi_enable(tp);
netdev_unlock(netdev);
dev_close(netdev);
}
err = PCI_ERS_RESULT_DISCONNECT;
Expand Down Expand Up @@ -18314,7 +18336,9 @@ static pci_ers_result_t tg3_io_slot_reset(struct pci_dev *pdev)

done:
if (rc != PCI_ERS_RESULT_RECOVERED && netdev && netif_running(netdev)) {
netdev_lock(netdev);
tg3_napi_enable(tp);
netdev_unlock(netdev);
dev_close(netdev);
}
rtnl_unlock();
Expand All @@ -18340,12 +18364,14 @@ static void tg3_io_resume(struct pci_dev *pdev)
if (!netdev || !netif_running(netdev))
goto done;

netdev_lock(netdev);
tg3_full_lock(tp, 0);
tg3_ape_driver_state_change(tp, RESET_KIND_INIT);
tg3_flag_set(tp, INIT_COMPLETE);
err = tg3_restart_hw(tp, true);
if (err) {
tg3_full_unlock(tp);
netdev_unlock(netdev);
netdev_err(netdev, "Cannot restart hardware after reset.\n");
goto done;
}
Expand All @@ -18357,6 +18383,7 @@ static void tg3_io_resume(struct pci_dev *pdev)
tg3_netif_start(tp);

tg3_full_unlock(tp);
netdev_unlock(netdev);

tg3_phy_start(tp);

Expand Down
32 changes: 10 additions & 22 deletions drivers/net/ethernet/nvidia/forcedeth.c
Original file line number Diff line number Diff line change
Expand Up @@ -1120,20 +1120,6 @@ static void nv_disable_hw_interrupts(struct net_device *dev, u32 mask)
}
}

static void nv_napi_enable(struct net_device *dev)
{
struct fe_priv *np = get_nvpriv(dev);

napi_enable(&np->napi);
}

static void nv_napi_disable(struct net_device *dev)
{
struct fe_priv *np = get_nvpriv(dev);

napi_disable(&np->napi);
}

#define MII_READ (-1)
/* mii_rw: read/write a register on the PHY.
*
Expand Down Expand Up @@ -3114,7 +3100,7 @@ static int nv_change_mtu(struct net_device *dev, int new_mtu)
* Changing the MTU is a rare event, it shouldn't matter.
*/
nv_disable_irq(dev);
nv_napi_disable(dev);
napi_disable(&np->napi);
netif_tx_lock_bh(dev);
netif_addr_lock(dev);
spin_lock(&np->lock);
Expand Down Expand Up @@ -3143,7 +3129,7 @@ static int nv_change_mtu(struct net_device *dev, int new_mtu)
spin_unlock(&np->lock);
netif_addr_unlock(dev);
netif_tx_unlock_bh(dev);
nv_napi_enable(dev);
napi_enable(&np->napi);
nv_enable_irq(dev);
}
return 0;
Expand Down Expand Up @@ -4731,7 +4717,7 @@ static int nv_set_ringparam(struct net_device *dev,

if (netif_running(dev)) {
nv_disable_irq(dev);
nv_napi_disable(dev);
napi_disable(&np->napi);
netif_tx_lock_bh(dev);
netif_addr_lock(dev);
spin_lock(&np->lock);
Expand Down Expand Up @@ -4784,7 +4770,7 @@ static int nv_set_ringparam(struct net_device *dev,
spin_unlock(&np->lock);
netif_addr_unlock(dev);
netif_tx_unlock_bh(dev);
nv_napi_enable(dev);
napi_enable(&np->napi);
nv_enable_irq(dev);
}
return 0;
Expand Down Expand Up @@ -5277,7 +5263,7 @@ static void nv_self_test(struct net_device *dev, struct ethtool_test *test, u64
if (test->flags & ETH_TEST_FL_OFFLINE) {
if (netif_running(dev)) {
netif_stop_queue(dev);
nv_napi_disable(dev);
napi_disable(&np->napi);
netif_tx_lock_bh(dev);
netif_addr_lock(dev);
spin_lock_irq(&np->lock);
Expand Down Expand Up @@ -5334,7 +5320,7 @@ static void nv_self_test(struct net_device *dev, struct ethtool_test *test, u64
/* restart rx engine */
nv_start_rxtx(dev);
netif_start_queue(dev);
nv_napi_enable(dev);
napi_enable(&np->napi);
nv_enable_hw_interrupts(dev, np->irqmask);
}
}
Expand Down Expand Up @@ -5576,6 +5562,7 @@ static int nv_open(struct net_device *dev)
/* ask for interrupts */
nv_enable_hw_interrupts(dev, np->irqmask);

netdev_lock(dev);
spin_lock_irq(&np->lock);
writel(NVREG_MCASTADDRA_FORCE, base + NvRegMulticastAddrA);
writel(0, base + NvRegMulticastAddrB);
Expand All @@ -5594,7 +5581,7 @@ static int nv_open(struct net_device *dev)
ret = nv_update_linkspeed(dev);
nv_start_rxtx(dev);
netif_start_queue(dev);
nv_napi_enable(dev);
napi_enable_locked(&np->napi);

if (ret) {
netif_carrier_on(dev);
Expand All @@ -5611,6 +5598,7 @@ static int nv_open(struct net_device *dev)
round_jiffies(jiffies + STATS_INTERVAL));

spin_unlock_irq(&np->lock);
netdev_unlock(dev);

/* If the loopback feature was set while the device was down, make sure
* that it's set correctly now.
Expand All @@ -5632,7 +5620,7 @@ static int nv_close(struct net_device *dev)
spin_lock_irq(&np->lock);
np->in_shutdown = 1;
spin_unlock_irq(&np->lock);
nv_napi_disable(dev);
napi_disable(&np->napi);
synchronize_irq(np->pci_dev->irq);

del_timer_sync(&np->oom_kick);
Expand Down
4 changes: 3 additions & 1 deletion drivers/net/ethernet/realtek/8139too.c
Original file line number Diff line number Diff line change
Expand Up @@ -1684,6 +1684,7 @@ static void rtl8139_tx_timeout_task (struct work_struct *work)
if (tmp8 & CmdTxEnb)
RTL_W8 (ChipCmd, CmdRxEnb);

netdev_lock(dev);
spin_lock_bh(&tp->rx_lock);
/* Disable interrupts by clearing the interrupt mask. */
RTL_W16 (IntrMask, 0x0000);
Expand All @@ -1694,11 +1695,12 @@ static void rtl8139_tx_timeout_task (struct work_struct *work)
spin_unlock_irq(&tp->lock);

/* ...and finally, reset everything */
napi_enable(&tp->napi);
napi_enable_locked(&tp->napi);
rtl8139_hw_start(dev);
netif_wake_queue(dev);

spin_unlock_bh(&tp->rx_lock);
netdev_unlock(dev);
}

static void rtl8139_tx_timeout(struct net_device *dev, unsigned int txqueue)
Expand Down
10 changes: 9 additions & 1 deletion drivers/net/ethernet/sun/niu.c
Original file line number Diff line number Diff line change
Expand Up @@ -6086,7 +6086,7 @@ static void niu_enable_napi(struct niu *np)
int i;

for (i = 0; i < np->num_ldg; i++)
napi_enable(&np->ldg[i].napi);
napi_enable_locked(&np->ldg[i].napi);
}

static void niu_disable_napi(struct niu *np)
Expand Down Expand Up @@ -6116,7 +6116,9 @@ static int niu_open(struct net_device *dev)
if (err)
goto out_free_channels;

netdev_lock(dev);
niu_enable_napi(np);
netdev_unlock(dev);

spin_lock_irq(&np->lock);

Expand Down Expand Up @@ -6521,6 +6523,7 @@ static void niu_reset_task(struct work_struct *work)

niu_reset_buffers(np);

netdev_lock(np->dev);
spin_lock_irqsave(&np->lock, flags);

err = niu_init_hw(np);
Expand All @@ -6531,6 +6534,7 @@ static void niu_reset_task(struct work_struct *work)
}

spin_unlock_irqrestore(&np->lock, flags);
netdev_unlock(np->dev);
}

static void niu_tx_timeout(struct net_device *dev, unsigned int txqueue)
Expand Down Expand Up @@ -6761,7 +6765,9 @@ static int niu_change_mtu(struct net_device *dev, int new_mtu)

niu_free_channels(np);

netdev_lock(dev);
niu_enable_napi(np);
netdev_unlock(dev);

err = niu_alloc_channels(np);
if (err)
Expand Down Expand Up @@ -9937,6 +9943,7 @@ static int __maybe_unused niu_resume(struct device *dev_d)

spin_lock_irqsave(&np->lock, flags);

netdev_lock(dev);
err = niu_init_hw(np);
if (!err) {
np->timer.expires = jiffies + HZ;
Expand All @@ -9945,6 +9952,7 @@ static int __maybe_unused niu_resume(struct device *dev_d)
}

spin_unlock_irqrestore(&np->lock, flags);
netdev_unlock(dev);

return err;
}
Expand Down
Loading

0 comments on commit f17b15d

Please sign in to comment.