[<prev] [next>] [<thread-prev] [thread-next>] [day] [month] [year] [list]
Message-ID: <dcfd56bc-de32-4b11-9e19-d8bd1543745d@stanley.mountain>
Date: Tue, 21 Jan 2025 11:32:24 +0300
From: Dan Carpenter <dan.carpenter@...aro.org>
To: Jakub Kicinski <kuba@...nel.org>
Cc: davem@...emloft.net, netdev@...r.kernel.org, edumazet@...gle.com,
pabeni@...hat.com, andrew+netdev@...n.ch, horms@...nel.org,
jdamato@...tly.com, Francois Romieu <romieu@...zoreil.com>,
pcnet32@...ntier.com, anthony.l.nguyen@...el.com,
przemyslaw.kitszel@...el.com, marcin.s.wojtas@...il.com
Subject: Re: [PATCH net-next v2 06/11] net: protect NAPI enablement with
netdev_lock()
On Tue, Jan 14, 2025 at 07:53:14PM -0800, Jakub Kicinski wrote:
> Wrap napi_enable() / napi_disable() with netdev_lock().
> Provide the "already locked" flavor of the API.
>
> iavf needs the usual adjustment. A number of drivers call
> napi_enable() under a spin lock, so they have to be modified
> to take netdev_lock() first, then spin lock then call
> napi_enable_locked().
You missed some.
drivers/net/ethernet/broadcom/tg3.c:7427 tg3_napi_enable() warn: sleeping in atomic context
drivers/net/ethernet/nvidia/forcedeth.c:5597 nv_open() warn: sleeping in atomic context
drivers/net/ethernet/realtek/8139too.c:1697 rtl8139_tx_timeout_task() warn: sleeping in atomic context
drivers/net/ethernet/sun/niu.c:6530 niu_reset_task() warn: sleeping in atomic context
drivers/net/ethernet/sun/niu.c:9944 niu_resume() warn: sleeping in atomic context
drivers/net/ethernet/via/via-rhine.c:1740 rhine_reset_task() warn: sleeping in atomic context
drivers/net/ethernet/via/via-rhine.c:2545 rhine_resume() warn: sleeping in atomic context
drivers/net/wireless/mediatek/mt76/mt7603/mac.c:1483 mt7603_mac_watchdog_reset() warn: sleeping in atomic context
drivers/net/wireless/mediatek/mt76/mt7615/pci.c:169 mt7615_pci_resume() warn: sleeping in atomic context
drivers/net/wireless/mediatek/mt76/mt7615/pci_mac.c:266 mt7615_mac_reset_work() warn: sleeping in atomic context
drivers/net/wireless/mediatek/mt76/mt76x02_mmio.c:508 mt76x02_watchdog_reset() warn: sleeping in atomic context
drivers/net/wireless/mediatek/mt76/mt76x0/pci.c:288 mt76x0e_resume() warn: sleeping in atomic context
drivers/net/wireless/mediatek/mt76/mt76x2/pci.c:156 mt76x2e_resume() warn: sleeping in atomic context
drivers/net/wireless/mediatek/mt76/mt7915/mac.c:1362 mt7915_mac_restart() warn: sleeping in atomic context
drivers/net/wireless/mediatek/mt76/mt7915/mac.c:1575 mt7915_mac_reset_work() warn: sleeping in atomic context
drivers/net/wireless/mediatek/mt76/mt7921/pci.c:528 mt7921_pci_resume() warn: sleeping in atomic context
drivers/net/wireless/mediatek/mt76/mt7921/pci_mac.c:86 mt7921e_mac_reset() warn: sleeping in atomic context
drivers/net/wireless/mediatek/mt76/mt7925/pci.c:561 mt7925_pci_resume() warn: sleeping in atomic context
drivers/net/wireless/mediatek/mt76/mt7925/pci_mac.c:106 mt7925e_mac_reset() warn: sleeping in atomic context
drivers/net/wireless/mediatek/mt76/mt7996/mac.c:1705 mt7996_mac_restart() warn: sleeping in atomic context
drivers/net/wireless/mediatek/mt76/mt7996/mac.c:1967 mt7996_mac_reset_work() warn: sleeping in atomic context
The big one is the local_bh_disable() the mediatek driver. Let me break
it down a bit more below.
regards,
dan carpenter
=========================================================
drivers/net/ethernet/broadcom/tg3.c:7427 tg3_napi_enable() warn: sleeping in atomic context
static void tg3_napi_enable(struct tg3 *tp)
{
int txq_idx = 0, rxq_idx = 0;
struct tg3_napi *tnapi;
int i;
for (i = 0; i < tp->irq_cnt; i++) {
tnapi = &tp->napi[i];
---> napi_enable(&tnapi->napi);
if (tnapi->tx_buffers) {
netif_queue_set_napi(tp->dev, txq_idx,
NETDEV_QUEUE_TYPE_TX,
&tnapi->napi);
txq_idx++;
}
if (tnapi->rx_rcb) {
netif_queue_set_napi(tp->dev, rxq_idx,
NETDEV_QUEUE_TYPE_RX,
&tnapi->napi);
rxq_idx++;
}
}
}
This is the trickiest one. The spinlock is two steps away in
the tg3_full_lock().
tg3_reset_task() <- disables preempt
tg3_set_ringparam() <- disables preempt
tg3_set_pauseparam() <- disables preempt
tg3_self_test() <- disables preempt
tg3_change_mtu() <- disables preempt
tg3_resume() <- disables preempt
tg3_io_resume() <- disables preempt
-> tg3_netif_start()
-> tg3_napi_enable()
=========================================================
drivers/net/ethernet/nvidia/forcedeth.c:5597 nv_open() warn: sleeping in atomic context
spin_lock_irq(&np->lock);
^^^^^^^^^^^^^^^^^^^^^^^^
writel(NVREG_MCASTADDRA_FORCE, base + NvRegMulticastAddrA);
writel(0, base + NvRegMulticastAddrB);
writel(NVREG_MCASTMASKA_NONE, base + NvRegMulticastMaskA);
writel(NVREG_MCASTMASKB_NONE, base + NvRegMulticastMaskB);
writel(NVREG_PFF_ALWAYS|NVREG_PFF_MYADDR, base + NvRegPacketFilterFlags);
/* One manual link speed update: Interrupts are enabled, future link
* speed changes cause interrupts and are handled by nv_link_irq().
*/
readl(base + NvRegMIIStatus);
writel(NVREG_MIISTAT_MASK_ALL, base + NvRegMIIStatus);
/* set linkspeed to invalid value, thus force nv_update_linkspeed
* to init hw */
np->linkspeed = 0;
ret = nv_update_linkspeed(dev);
nv_start_rxtx(dev);
netif_start_queue(dev);
---> nv_napi_enable(dev);
if (ret) {
netif_carrier_on(dev);
} else {
netdev_info(dev, "no link during initialization\n");
netif_carrier_off(dev);
}
if (oom)
mod_timer(&np->oom_kick, jiffies + OOM_REFILL);
/* start statistics timer */
if (np->driver_data & (DEV_HAS_STATISTICS_V1|DEV_HAS_STATISTICS_V2|DEV_HAS_STATISTICS_V3))
mod_timer(&np->stats_poll,
round_jiffies(jiffies + STATS_INTERVAL));
spin_unlock_irq(&np->lock);
/* If the loopback feature was set while the device was down, make sure
* that it's set correctly now.
=========================================================
drivers/net/ethernet/realtek/8139too.c:1697 rtl8139_tx_timeout_task() warn: sleeping in atomic context
spin_lock_bh(&tp->rx_lock);
^^^^^^^^^^^^^^^^^^^^^^^^^^^
/* Disable interrupts by clearing the interrupt mask. */
RTL_W16 (IntrMask, 0x0000);
/* Stop a shared interrupt from scavenging while we are. */
spin_lock_irq(&tp->lock);
rtl8139_tx_clear (tp);
spin_unlock_irq(&tp->lock);
/* ...and finally, reset everything */
---> napi_enable(&tp->napi);
rtl8139_hw_start(dev);
netif_wake_queue(dev);
spin_unlock_bh(&tp->rx_lock);
}
=========================================================
drivers/net/ethernet/sun/niu.c:6530 niu_reset_task() warn: sleeping in atomic context
spin_lock_irqsave(&np->lock, flags);
^^^^^^^^^^^^^^^^^^
err = niu_init_hw(np);
if (!err) {
np->timer.expires = jiffies + HZ;
add_timer(&np->timer);
---> niu_netif_start(np);
}
spin_unlock_irqrestore(&np->lock, flags);
=========================================================
drivers/net/ethernet/sun/niu.c:9944 niu_resume() warn: sleeping in atomic context
spin_lock_irqsave(&np->lock, flags);
^^^^^^^^^^^^^^^^^^^^^^^^^^^
err = niu_init_hw(np);
if (!err) {
np->timer.expires = jiffies + HZ;
add_timer(&np->timer);
---> niu_netif_start(np);
}
spin_unlock_irqrestore(&np->lock, flags);
return err;
}
=========================================================
drivers/net/ethernet/via/via-rhine.c:1740 rhine_reset_task() warn: sleeping in atomic context
spin_lock_bh(&rp->lock);
^^^^^^^^^^^^^^^^^^^^^^^
/* clear all descriptors */
free_tbufs(dev);
alloc_tbufs(dev);
rhine_reset_rbufs(rp);
/* Reinitialize the hardware. */
rhine_chip_reset(dev);
---> init_registers(dev);
spin_unlock_bh(&rp->lock);
netif_trans_update(dev); /* prevent tx timeout */
dev->stats.tx_errors++;
netif_wake_queue(dev);
out_unlock:
mutex_unlock(&rp->task_lock);
}
=========================================================
drivers/net/ethernet/via/via-rhine.c:2545 rhine_resume() warn: sleeping in atomic context
static int rhine_resume(struct device *device)
{
struct net_device *dev = dev_get_drvdata(device);
struct rhine_private *rp = netdev_priv(dev);
if (!netif_running(dev))
return 0;
enable_mmio(rp->pioaddr, rp->quirks);
rhine_power_init(dev);
free_tbufs(dev);
alloc_tbufs(dev);
rhine_reset_rbufs(rp);
rhine_task_enable(rp);
spin_lock_bh(&rp->lock);
^^^^^^^^^^^^^^^^^^^^^^
---> init_registers(dev);
spin_unlock_bh(&rp->lock);
netif_device_attach(dev);
return 0;
}
=========================================================
drivers/net/wireless/mediatek/mt76/mt7603/mac.c:1483 mt7603_mac_watchdog_reset() warn: sleeping in atomic context
tasklet_enable(&dev->mt76.pre_tbtt_tasklet);
mt7603_beacon_set_timer(dev, -1, beacon_int);
local_bh_disable();
^^^^^^^^^^^^^^^^^^
---> napi_enable(&dev->mt76.tx_napi);
napi_schedule(&dev->mt76.tx_napi);
napi_enable(&dev->mt76.napi[0]);
napi_schedule(&dev->mt76.napi[0]);
napi_enable(&dev->mt76.napi[1]);
napi_schedule(&dev->mt76.napi[1]);
local_bh_enable();
ieee80211_wake_queues(dev->mt76.hw);
mt76_txq_schedule_all(&dev->mphy);
}
=========================================================
drivers/net/wireless/mediatek/mt76/mt7615/pci.c:169 mt7615_pci_resume() warn: sleeping in atomic context
if (pdma_reset)
dev_err(mdev->dev, "PDMA engine must be reinitialized\n");
mt76_worker_enable(&mdev->tx_worker);
local_bh_disable();
^^^^^^^^^^^^^^^^^^^
mt76_for_each_q_rx(mdev, i) {
---> napi_enable(&mdev->napi[i]);
napi_schedule(&mdev->napi[i]);
}
napi_enable(&mdev->tx_napi);
napi_schedule(&mdev->tx_napi);
local_bh_enable();
if (!test_bit(MT76_STATE_SUSPEND, &dev->mphy.state) &&
mt7615_firmware_offload(dev))
err = mt76_connac_mcu_set_hif_suspend(mdev, false, true);
return err;
}
=========================================================
drivers/net/wireless/mediatek/mt76/mt7615/pci_mac.c:266 mt7615_mac_reset_work() warn: sleeping in atomic context
clear_bit(MT76_MCU_RESET, &dev->mphy.state);
clear_bit(MT76_RESET, &dev->mphy.state);
if (phy2)
clear_bit(MT76_RESET, &phy2->mt76->state);
mt76_worker_enable(&dev->mt76.tx_worker);
local_bh_disable();
^^^^^^^^^^^^^^^^^^^
---> napi_enable(&dev->mt76.tx_napi);
napi_schedule(&dev->mt76.tx_napi);
mt76_for_each_q_rx(&dev->mt76, i) {
napi_enable(&dev->mt76.napi[i]);
napi_schedule(&dev->mt76.napi[i]);
}
local_bh_enable();
ieee80211_wake_queues(mt76_hw(dev));
if (ext_phy)
ieee80211_wake_queues(ext_phy->hw);
mt7615_hif_int_event_trigger(dev, MT_MCU_INT_EVENT_RESET_DONE);
mt7615_wait_reset_state(dev, MT_MCU_CMD_NORMAL_STATE);
mt7615_update_beacons(dev);
mt7615_mutex_release(dev);
=========================================================
drivers/net/wireless/mediatek/mt76/mt76x02_mmio.c:508 mt76x02_watchdog_reset() warn: sleeping in atomic context
mutex_unlock(&dev->mt76.mutex);
clear_bit(MT76_RESET, &dev->mphy.state);
mt76_worker_enable(&dev->mt76.tx_worker);
tasklet_enable(&dev->mt76.pre_tbtt_tasklet);
local_bh_disable();
^^^^^^^^^^^^^^^^
---> napi_enable(&dev->mt76.tx_napi);
napi_schedule(&dev->mt76.tx_napi);
mt76_for_each_q_rx(&dev->mt76, i) {
napi_enable(&dev->mt76.napi[i]);
napi_schedule(&dev->mt76.napi[i]);
}
local_bh_enable();
if (restart) {
set_bit(MT76_RESTART, &dev->mphy.state);
mt76x02_mcu_function_select(dev, Q_SELECT, 1);
ieee80211_restart_hw(dev->mt76.hw);
} else {
ieee80211_wake_queues(dev->mt76.hw);
mt76_txq_schedule_all(&dev->mphy);
}
}
=========================================================
drivers/net/wireless/mediatek/mt76/mt76x0/pci.c:288 mt76x0e_resume() warn: sleeping in atomic context
err = pci_set_power_state(pdev, PCI_D0);
if (err)
return err;
pci_restore_state(pdev);
mt76_worker_enable(&mdev->tx_worker);
local_bh_disable();
^^^^^^^^^^^^^^^^^^
mt76_for_each_q_rx(mdev, i) {
mt76_queue_rx_reset(dev, i);
---> napi_enable(&mdev->napi[i]);
napi_schedule(&mdev->napi[i]);
}
napi_enable(&mdev->tx_napi);
napi_schedule(&mdev->tx_napi);
local_bh_enable();
return mt76x0e_init_hardware(dev, true);
}
=========================================================
drivers/net/wireless/mediatek/mt76/mt76x2/pci.c:156 mt76x2e_resume() warn: sleeping in atomic context
static int __maybe_unused
mt76x2e_resume(struct pci_dev *pdev)
{
struct mt76_dev *mdev = pci_get_drvdata(pdev);
struct mt76x02_dev *dev = container_of(mdev, struct mt76x02_dev, mt76);
int i, err;
err = pci_set_power_state(pdev, PCI_D0);
if (err)
return err;
pci_restore_state(pdev);
mt76_worker_enable(&mdev->tx_worker);
local_bh_disable();
^^^^^^^^^^^^^^^^^^
mt76_for_each_q_rx(mdev, i) {
---> napi_enable(&mdev->napi[i]);
napi_schedule(&mdev->napi[i]);
}
napi_enable(&mdev->tx_napi);
napi_schedule(&mdev->tx_napi);
local_bh_enable();
return mt76x2_resume_device(dev);
}
=========================================================
drivers/net/wireless/mediatek/mt76/mt7915/mac.c:1362 mt7915_mac_restart() warn: sleeping in atomic context
/* token reinit */
mt76_connac2_tx_token_put(&dev->mt76);
idr_init(&dev->mt76.token);
mt7915_dma_reset(dev, true);
local_bh_disable();
^^^^^^^^^^^^^^^^^^
mt76_for_each_q_rx(mdev, i) {
if (mdev->q_rx[i].ndesc) {
---> napi_enable(&dev->mt76.napi[i]);
napi_schedule(&dev->mt76.napi[i]);
}
}
local_bh_enable();
clear_bit(MT76_MCU_RESET, &dev->mphy.state);
clear_bit(MT76_STATE_MCU_RUNNING, &dev->mphy.state);
mt76_wr(dev, MT_INT_MASK_CSR, dev->mt76.mmio.irqmask);
mt76_wr(dev, MT_INT_SOURCE_CSR, ~0);
if (dev->hif2) {
mt76_wr(dev, MT_INT1_MASK_CSR, dev->mt76.mmio.irqmask);
mt76_wr(dev, MT_INT1_SOURCE_CSR, ~0);
}
if (dev_is_pci(mdev->dev)) {
mt76_wr(dev, MT_PCIE_MAC_INT_ENABLE, 0xff);
if (dev->hif2) {
mt76_wr(dev, MT_PCIE_RECOG_ID,
dev->hif2->index | MT_PCIE_RECOG_ID_SEM);
=========================================================
drivers/net/wireless/mediatek/mt76/mt7915/mac.c:1575 mt7915_mac_reset_work() warn: sleeping in atomic context
/* enable DMA Tx/Rx and interrupt */
mt7915_dma_start(dev, false, false);
clear_bit(MT76_MCU_RESET, &dev->mphy.state);
clear_bit(MT76_RESET, &dev->mphy.state);
if (phy2)
clear_bit(MT76_RESET, &phy2->mt76->state);
local_bh_disable();
^^^^^^^^^^^^^^^^^^
mt76_for_each_q_rx(&dev->mt76, i) {
---> napi_enable(&dev->mt76.napi[i]);
napi_schedule(&dev->mt76.napi[i]);
}
local_bh_enable();
tasklet_schedule(&dev->mt76.irq_tasklet);
mt76_worker_enable(&dev->mt76.tx_worker);
local_bh_disable();
napi_enable(&dev->mt76.tx_napi);
napi_schedule(&dev->mt76.tx_napi);
local_bh_enable();
ieee80211_wake_queues(mt76_hw(dev));
if (ext_phy)
ieee80211_wake_queues(ext_phy->hw);
mutex_unlock(&dev->mt76.mutex);
=========================================================
drivers/net/wireless/mediatek/mt76/mt7921/pci.c:528 mt7921_pci_resume() warn: sleeping in atomic context
mt76_set(dev, MT_MCU2HOST_SW_INT_ENA, MT_MCU_CMD_WAKE_RX_PCIE);
/* put dma enabled */
mt76_set(dev, MT_WFDMA0_GLO_CFG,
MT_WFDMA0_GLO_CFG_TX_DMA_EN | MT_WFDMA0_GLO_CFG_RX_DMA_EN);
mt76_worker_enable(&mdev->tx_worker);
local_bh_disable();
^^^^^^^^^^^^^^^^^^
mt76_for_each_q_rx(mdev, i) {
---> napi_enable(&mdev->napi[i]);
napi_schedule(&mdev->napi[i]);
}
napi_enable(&mdev->tx_napi);
napi_schedule(&mdev->tx_napi);
local_bh_enable();
/* restore previous ds setting */
if (!pm->ds_enable)
mt76_connac_mcu_set_deep_sleep(&dev->mt76, false);
err = mt76_connac_mcu_set_hif_suspend(mdev, false, true);
if (err < 0)
goto failed;
mt7921_regd_update(dev);
err = mt7921_mcu_radio_led_ctrl(dev, EXT_CMD_RADIO_ON_LED);
failed:
pm->suspended = false;
=========================================================
drivers/net/wireless/mediatek/mt76/mt7921/pci_mac.c:86 mt7921e_mac_reset() warn: sleeping in atomic context
napi_disable(&dev->mt76.napi[MT_RXQ_MCU_WA]);
napi_disable(&dev->mt76.tx_napi);
mt76_connac2_tx_token_put(&dev->mt76);
idr_init(&dev->mt76.token);
mt792x_wpdma_reset(dev, true);
local_bh_disable();
^^^^^^^^^^^^^^^^^^
mt76_for_each_q_rx(&dev->mt76, i) {
---> napi_enable(&dev->mt76.napi[i]);
napi_schedule(&dev->mt76.napi[i]);
}
local_bh_enable();
dev->fw_assert = false;
clear_bit(MT76_MCU_RESET, &dev->mphy.state);
mt76_wr(dev, dev->irq_map->host_irq_enable,
dev->irq_map->tx.all_complete_mask |
MT_INT_RX_DONE_ALL | MT_INT_MCU_CMD);
mt76_wr(dev, MT_PCIE_MAC_INT_ENABLE, 0xff);
err = mt7921e_driver_own(dev);
if (err)
goto out;
err = mt7921_run_firmware(dev);
if (err)
goto out;
=========================================================
drivers/net/wireless/mediatek/mt76/mt7925/pci.c:561 mt7925_pci_resume() warn: sleeping in atomic context
mt76_set(dev, MT_MCU2HOST_SW_INT_ENA, MT_MCU_CMD_WAKE_RX_PCIE);
/* put dma enabled */
mt76_set(dev, MT_WFDMA0_GLO_CFG,
MT_WFDMA0_GLO_CFG_TX_DMA_EN | MT_WFDMA0_GLO_CFG_RX_DMA_EN);
mt76_worker_enable(&mdev->tx_worker);
local_bh_disable();
^^^^^^^^^^^^^^^^^^
mt76_for_each_q_rx(mdev, i) {
---> napi_enable(&mdev->napi[i]);
napi_schedule(&mdev->napi[i]);
}
napi_enable(&mdev->tx_napi);
napi_schedule(&mdev->tx_napi);
local_bh_enable();
mt76_connac_mcu_set_hif_suspend(mdev, false, false);
ret = wait_event_timeout(dev->wait,
dev->hif_resumed, 3 * HZ);
if (!ret) {
err = -ETIMEDOUT;
goto failed;
}
/* restore previous ds setting */
=========================================================
drivers/net/wireless/mediatek/mt76/mt7925/pci_mac.c:106 mt7925e_mac_reset() warn: sleeping in atomic context
mt7925_tx_token_put(dev);
idr_init(&dev->mt76.token);
mt792x_wpdma_reset(dev, true);
local_bh_disable();
^^^^^^^^^^^^^^^^
mt76_for_each_q_rx(&dev->mt76, i) {
---> napi_enable(&dev->mt76.napi[i]);
napi_schedule(&dev->mt76.napi[i]);
}
napi_enable(&dev->mt76.tx_napi);
napi_schedule(&dev->mt76.tx_napi);
local_bh_enable();
dev->fw_assert = false;
clear_bit(MT76_MCU_RESET, &dev->mphy.state);
mt76_wr(dev, dev->irq_map->host_irq_enable,
dev->irq_map->tx.all_complete_mask |
MT_INT_RX_DONE_ALL | MT_INT_MCU_CMD);
mt76_wr(dev, MT_PCIE_MAC_INT_ENABLE, 0xff);
err = mt792xe_mcu_fw_pmctrl(dev);
=========================================================
drivers/net/wireless/mediatek/mt76/mt7996/mac.c:1705 mt7996_mac_restart() warn: sleeping in atomic context
napi_disable(&dev->mt76.tx_napi);
/* token reinit */
mt7996_tx_token_put(dev);
idr_init(&dev->mt76.token);
mt7996_dma_reset(dev, true);
local_bh_disable();
^^^^^^^^^^^^^^^^^^
mt76_for_each_q_rx(mdev, i) {
if (mtk_wed_device_active(&dev->mt76.mmio.wed) &&
mt76_queue_is_wed_rro(&mdev->q_rx[i]))
continue;
if (mdev->q_rx[i].ndesc) {
---> napi_enable(&dev->mt76.napi[i]);
napi_schedule(&dev->mt76.napi[i]);
}
}
local_bh_enable();
clear_bit(MT76_MCU_RESET, &dev->mphy.state);
clear_bit(MT76_STATE_MCU_RUNNING, &dev->mphy.state);
mt76_wr(dev, MT_INT_MASK_CSR, dev->mt76.mmio.irqmask);
mt76_wr(dev, MT_INT_SOURCE_CSR, ~0);
if (dev->hif2) {
mt76_wr(dev, MT_INT1_MASK_CSR, dev->mt76.mmio.irqmask);
mt76_wr(dev, MT_INT1_SOURCE_CSR, ~0);
}
=========================================================
drivers/net/wireless/mediatek/mt76/mt7996/mac.c:1967 mt7996_mac_reset_work() warn: sleeping in atomic context
clear_bit(MT76_MCU_RESET, &dev->mphy.state);
clear_bit(MT76_RESET, &dev->mphy.state);
if (phy2)
clear_bit(MT76_RESET, &phy2->mt76->state);
if (phy3)
clear_bit(MT76_RESET, &phy3->mt76->state);
local_bh_disable();
^^^^^^^^^^^^^^^^^^^
mt76_for_each_q_rx(&dev->mt76, i) {
if (mtk_wed_device_active(&dev->mt76.mmio.wed) &&
mt76_queue_is_wed_rro(&dev->mt76.q_rx[i]))
continue;
---> napi_enable(&dev->mt76.napi[i]);
napi_schedule(&dev->mt76.napi[i]);
}
local_bh_enable();
tasklet_schedule(&dev->mt76.irq_tasklet);
mt76_worker_enable(&dev->mt76.tx_worker);
local_bh_disable();
napi_enable(&dev->mt76.tx_napi);
napi_schedule(&dev->mt76.tx_napi);
local_bh_enable();
ieee80211_wake_queues(mt76_hw(dev));
if (phy2)
ieee80211_wake_queues(phy2->mt76->hw);
if (phy3)
ieee80211_wake_queues(phy3->mt76->hw);
Powered by blists - more mailing lists