diff options
Diffstat (limited to 'package/kernel/mac80211/patches/332-ath10k-implement-NAPI-support.patch')
-rw-r--r-- | package/kernel/mac80211/patches/332-ath10k-implement-NAPI-support.patch | 642 |
1 files changed, 0 insertions, 642 deletions
diff --git a/package/kernel/mac80211/patches/332-ath10k-implement-NAPI-support.patch b/package/kernel/mac80211/patches/332-ath10k-implement-NAPI-support.patch deleted file mode 100644 index c6cc145957..0000000000 --- a/package/kernel/mac80211/patches/332-ath10k-implement-NAPI-support.patch +++ /dev/null @@ -1,642 +0,0 @@ -From: Rajkumar Manoharan <rmanohar@qti.qualcomm.com> -Date: Thu, 21 Jul 2016 11:50:00 +0530 -Subject: [PATCH] ath10k: implement NAPI support - -Add NAPI support for rx and tx completion. NAPI poll is scheduled -from interrupt handler. The design is as below - - - on interrupt - - schedule napi and mask interrupts - - on poll - - process all pipes (no actual Tx/Rx) - - process Rx within budget - - if quota exceeds budget reschedule napi poll by returning budget - - process Tx completions and update budget if necessary - - process Tx fetch indications (pull-push) - - push any other pending Tx (if possible) - - before resched or napi completion replenish htt rx ring buffer - - if work done < budget, complete napi poll and unmask interrupts - -This change also get rid of two tasklets (intr_tq and txrx_compl_task). - -Measured peak throughput with NAPI on IPQ4019 platform in controlled -environment. No noticeable reduction in throughput is seen and also -observed improvements in CPU usage. Approx. 15% CPU usage got reduced -in UDP uplink case. - -DL: AP DUT Tx -UL: AP DUT Rx - -IPQ4019 (avg. cpu usage %) -======== - TOT +NAPI - =========== ============= -TCP DL 644 Mbps (42%) 645 Mbps (36%) -TCP UL 673 Mbps (30%) 675 Mbps (26%) -UDP DL 682 Mbps (49%) 680 Mbps (49%) -UDP UL 720 Mbps (28%) 717 Mbps (11%) - -Signed-off-by: Rajkumar Manoharan <rmanohar@qti.qualcomm.com> ---- - ---- a/drivers/net/wireless/ath/ath10k/ahb.c -+++ b/drivers/net/wireless/ath/ath10k/ahb.c -@@ -462,13 +462,13 @@ static void ath10k_ahb_halt_chip(struct - static irqreturn_t ath10k_ahb_interrupt_handler(int irq, void *arg) - { - struct ath10k *ar = arg; -- struct ath10k_pci *ar_pci = ath10k_pci_priv(ar); - - if (!ath10k_pci_irq_pending(ar)) - return IRQ_NONE; - - ath10k_pci_disable_and_clear_legacy_irq(ar); -- tasklet_schedule(&ar_pci->intr_tq); -+ ath10k_pci_irq_msi_fw_mask(ar); -+ napi_schedule(&ar->napi); - - return IRQ_HANDLED; - } -@@ -831,7 +831,7 @@ static int ath10k_ahb_probe(struct platf - goto err_resource_deinit; - } - -- ath10k_pci_init_irq_tasklets(ar); -+ ath10k_pci_init_napi(ar); - - ret = ath10k_ahb_request_irq_legacy(ar); - if (ret) ---- a/drivers/net/wireless/ath/ath10k/core.c -+++ b/drivers/net/wireless/ath/ath10k/core.c -@@ -2226,6 +2226,8 @@ struct ath10k *ath10k_core_create(size_t - INIT_WORK(&ar->register_work, ath10k_core_register_work); - INIT_WORK(&ar->restart_work, ath10k_core_restart); - -+ init_dummy_netdev(&ar->napi_dev); -+ - ret = ath10k_debug_create(ar); - if (ret) - goto err_free_aux_wq; ---- a/drivers/net/wireless/ath/ath10k/core.h -+++ b/drivers/net/wireless/ath/ath10k/core.h -@@ -65,6 +65,10 @@ - #define ATH10K_KEEPALIVE_MAX_IDLE 3895 - #define ATH10K_KEEPALIVE_MAX_UNRESPONSIVE 3900 - -+/* NAPI poll budget */ -+#define ATH10K_NAPI_BUDGET 64 -+#define ATH10K_NAPI_QUOTA_LIMIT 60 -+ - struct ath10k; - - enum ath10k_bus { -@@ -933,6 +937,10 @@ struct ath10k { - struct ath10k_thermal thermal; - struct ath10k_wow wow; - -+ /* NAPI */ -+ struct net_device napi_dev; -+ struct napi_struct napi; -+ - /* must be last */ - u8 drv_priv[0] __aligned(sizeof(void *)); - }; ---- a/drivers/net/wireless/ath/ath10k/htt.h -+++ b/drivers/net/wireless/ath/ath10k/htt.h -@@ -1666,7 +1666,6 @@ struct ath10k_htt { - - /* This is used to group tx/rx completions separately and process them - * in batches to reduce cache stalls */ -- struct tasklet_struct txrx_compl_task; - struct sk_buff_head rx_compl_q; - struct sk_buff_head rx_in_ord_compl_q; - struct sk_buff_head tx_fetch_ind_q; -@@ -1799,5 +1798,6 @@ int ath10k_htt_tx(struct ath10k_htt *htt - struct sk_buff *msdu); - void ath10k_htt_rx_pktlog_completion_handler(struct ath10k *ar, - struct sk_buff *skb); -+int ath10k_htt_txrx_compl_task(struct ath10k *ar, int budget); - - #endif ---- a/drivers/net/wireless/ath/ath10k/htt_rx.c -+++ b/drivers/net/wireless/ath/ath10k/htt_rx.c -@@ -34,7 +34,6 @@ - #define HTT_RX_RING_REFILL_RESCHED_MS 5 - - static int ath10k_htt_rx_get_csum_state(struct sk_buff *skb); --static void ath10k_htt_txrx_compl_task(unsigned long ptr); - - static struct sk_buff * - ath10k_htt_rx_find_skb_paddr(struct ath10k *ar, u32 paddr) -@@ -226,7 +225,6 @@ int ath10k_htt_rx_ring_refill(struct ath - void ath10k_htt_rx_free(struct ath10k_htt *htt) - { - del_timer_sync(&htt->rx_ring.refill_retry_timer); -- tasklet_kill(&htt->txrx_compl_task); - - skb_queue_purge(&htt->rx_compl_q); - skb_queue_purge(&htt->rx_in_ord_compl_q); -@@ -520,9 +518,6 @@ int ath10k_htt_rx_alloc(struct ath10k_ht - skb_queue_head_init(&htt->tx_fetch_ind_q); - atomic_set(&htt->num_mpdus_ready, 0); - -- tasklet_init(&htt->txrx_compl_task, ath10k_htt_txrx_compl_task, -- (unsigned long)htt); -- - ath10k_dbg(ar, ATH10K_DBG_BOOT, "htt rx ring size %d fill_level %d\n", - htt->rx_ring.size, htt->rx_ring.fill_level); - return 0; -@@ -958,7 +953,7 @@ static void ath10k_process_rx(struct ath - trace_ath10k_rx_hdr(ar, skb->data, skb->len); - trace_ath10k_rx_payload(ar, skb->data, skb->len); - -- ieee80211_rx(ar->hw, skb); -+ ieee80211_rx_napi(ar->hw, NULL, skb, &ar->napi); - } - - static int ath10k_htt_rx_nwifi_hdrlen(struct ath10k *ar, -@@ -1527,7 +1522,7 @@ static int ath10k_htt_rx_handle_amsdu(st - struct ath10k *ar = htt->ar; - struct ieee80211_rx_status *rx_status = &htt->rx_status; - struct sk_buff_head amsdu; -- int ret; -+ int ret, num_msdus; - - __skb_queue_head_init(&amsdu); - -@@ -1549,13 +1544,14 @@ static int ath10k_htt_rx_handle_amsdu(st - return ret; - } - -+ num_msdus = skb_queue_len(&amsdu); - ath10k_htt_rx_h_ppdu(ar, &amsdu, rx_status, 0xffff); - ath10k_htt_rx_h_unchain(ar, &amsdu, ret > 0); - ath10k_htt_rx_h_filter(ar, &amsdu, rx_status); - ath10k_htt_rx_h_mpdu(ar, &amsdu, rx_status); - ath10k_htt_rx_h_deliver(ar, &amsdu, rx_status); - -- return 0; -+ return num_msdus; - } - - static void ath10k_htt_rx_proc_rx_ind(struct ath10k_htt *htt, -@@ -1579,15 +1575,6 @@ static void ath10k_htt_rx_proc_rx_ind(st - mpdu_count += mpdu_ranges[i].mpdu_count; - - atomic_add(mpdu_count, &htt->num_mpdus_ready); -- -- tasklet_schedule(&htt->txrx_compl_task); --} -- --static void ath10k_htt_rx_frag_handler(struct ath10k_htt *htt) --{ -- atomic_inc(&htt->num_mpdus_ready); -- -- tasklet_schedule(&htt->txrx_compl_task); - } - - static void ath10k_htt_rx_tx_compl_ind(struct ath10k *ar, -@@ -1772,14 +1759,15 @@ static void ath10k_htt_rx_h_rx_offload_p - RX_FLAG_MMIC_STRIPPED; - } - --static void ath10k_htt_rx_h_rx_offload(struct ath10k *ar, -- struct sk_buff_head *list) -+static int ath10k_htt_rx_h_rx_offload(struct ath10k *ar, -+ struct sk_buff_head *list) - { - struct ath10k_htt *htt = &ar->htt; - struct ieee80211_rx_status *status = &htt->rx_status; - struct htt_rx_offload_msdu *rx; - struct sk_buff *msdu; - size_t offset; -+ int num_msdu = 0; - - while ((msdu = __skb_dequeue(list))) { - /* Offloaded frames don't have Rx descriptor. Instead they have -@@ -1819,10 +1807,12 @@ static void ath10k_htt_rx_h_rx_offload(s - ath10k_htt_rx_h_rx_offload_prot(status, msdu); - ath10k_htt_rx_h_channel(ar, status, NULL, rx->vdev_id); - ath10k_process_rx(ar, status, msdu); -+ num_msdu++; - } -+ return num_msdu; - } - --static void ath10k_htt_rx_in_ord_ind(struct ath10k *ar, struct sk_buff *skb) -+static int ath10k_htt_rx_in_ord_ind(struct ath10k *ar, struct sk_buff *skb) - { - struct ath10k_htt *htt = &ar->htt; - struct htt_resp *resp = (void *)skb->data; -@@ -1835,12 +1825,12 @@ static void ath10k_htt_rx_in_ord_ind(str - u8 tid; - bool offload; - bool frag; -- int ret; -+ int ret, num_msdus = 0; - - lockdep_assert_held(&htt->rx_ring.lock); - - if (htt->rx_confused) -- return; -+ return -EIO; - - skb_pull(skb, sizeof(resp->hdr)); - skb_pull(skb, sizeof(resp->rx_in_ord_ind)); -@@ -1859,7 +1849,7 @@ static void ath10k_htt_rx_in_ord_ind(str - - if (skb->len < msdu_count * sizeof(*resp->rx_in_ord_ind.msdu_descs)) { - ath10k_warn(ar, "dropping invalid in order rx indication\n"); -- return; -+ return -EINVAL; - } - - /* The event can deliver more than 1 A-MSDU. Each A-MSDU is later -@@ -1870,14 +1860,14 @@ static void ath10k_htt_rx_in_ord_ind(str - if (ret < 0) { - ath10k_warn(ar, "failed to pop paddr list: %d\n", ret); - htt->rx_confused = true; -- return; -+ return -EIO; - } - - /* Offloaded frames are very different and need to be handled - * separately. - */ - if (offload) -- ath10k_htt_rx_h_rx_offload(ar, &list); -+ num_msdus = ath10k_htt_rx_h_rx_offload(ar, &list); - - while (!skb_queue_empty(&list)) { - __skb_queue_head_init(&amsdu); -@@ -1890,6 +1880,7 @@ static void ath10k_htt_rx_in_ord_ind(str - * better to report something than nothing though. This - * should still give an idea about rx rate to the user. - */ -+ num_msdus += skb_queue_len(&amsdu); - ath10k_htt_rx_h_ppdu(ar, &amsdu, status, vdev_id); - ath10k_htt_rx_h_filter(ar, &amsdu, status); - ath10k_htt_rx_h_mpdu(ar, &amsdu, status); -@@ -1902,9 +1893,10 @@ static void ath10k_htt_rx_in_ord_ind(str - ath10k_warn(ar, "failed to extract amsdu: %d\n", ret); - htt->rx_confused = true; - __skb_queue_purge(&list); -- return; -+ return -EIO; - } - } -+ return num_msdus; - } - - static void ath10k_htt_rx_tx_fetch_resp_id_confirm(struct ath10k *ar, -@@ -2267,7 +2259,6 @@ bool ath10k_htt_t2h_msg_handler(struct a - } - case HTT_T2H_MSG_TYPE_TX_COMPL_IND: - ath10k_htt_rx_tx_compl_ind(htt->ar, skb); -- tasklet_schedule(&htt->txrx_compl_task); - break; - case HTT_T2H_MSG_TYPE_SEC_IND: { - struct ath10k *ar = htt->ar; -@@ -2284,7 +2275,7 @@ bool ath10k_htt_t2h_msg_handler(struct a - case HTT_T2H_MSG_TYPE_RX_FRAG_IND: { - ath10k_dbg_dump(ar, ATH10K_DBG_HTT_DUMP, NULL, "htt event: ", - skb->data, skb->len); -- ath10k_htt_rx_frag_handler(htt); -+ atomic_inc(&htt->num_mpdus_ready); - break; - } - case HTT_T2H_MSG_TYPE_TEST: -@@ -2322,8 +2313,7 @@ bool ath10k_htt_t2h_msg_handler(struct a - break; - } - case HTT_T2H_MSG_TYPE_RX_IN_ORD_PADDR_IND: { -- skb_queue_tail(&htt->rx_in_ord_compl_q, skb); -- tasklet_schedule(&htt->txrx_compl_task); -+ __skb_queue_tail(&htt->rx_in_ord_compl_q, skb); - return false; - } - case HTT_T2H_MSG_TYPE_TX_CREDIT_UPDATE_IND: -@@ -2349,7 +2339,6 @@ bool ath10k_htt_t2h_msg_handler(struct a - break; - } - skb_queue_tail(&htt->tx_fetch_ind_q, tx_fetch_ind); -- tasklet_schedule(&htt->txrx_compl_task); - break; - } - case HTT_T2H_MSG_TYPE_TX_FETCH_CONFIRM: -@@ -2378,27 +2367,77 @@ void ath10k_htt_rx_pktlog_completion_han - } - EXPORT_SYMBOL(ath10k_htt_rx_pktlog_completion_handler); - --static void ath10k_htt_txrx_compl_task(unsigned long ptr) -+int ath10k_htt_txrx_compl_task(struct ath10k *ar, int budget) - { -- struct ath10k_htt *htt = (struct ath10k_htt *)ptr; -- struct ath10k *ar = htt->ar; -+ struct ath10k_htt *htt = &ar->htt; - struct htt_tx_done tx_done = {}; -- struct sk_buff_head rx_ind_q; - struct sk_buff_head tx_ind_q; - struct sk_buff *skb; - unsigned long flags; -- int num_mpdus; -+ int quota = 0, done, num_rx_msdus; -+ bool resched_napi = false; - -- __skb_queue_head_init(&rx_ind_q); - __skb_queue_head_init(&tx_ind_q); - -- spin_lock_irqsave(&htt->rx_in_ord_compl_q.lock, flags); -- skb_queue_splice_init(&htt->rx_in_ord_compl_q, &rx_ind_q); -- spin_unlock_irqrestore(&htt->rx_in_ord_compl_q.lock, flags); -+ /* Since in-ord-ind can deliver more than 1 A-MSDU in single event, -+ * process it first to utilize full available quota. -+ */ -+ while (quota < budget) { -+ if (skb_queue_empty(&htt->rx_in_ord_compl_q)) -+ break; - -- spin_lock_irqsave(&htt->tx_fetch_ind_q.lock, flags); -- skb_queue_splice_init(&htt->tx_fetch_ind_q, &tx_ind_q); -- spin_unlock_irqrestore(&htt->tx_fetch_ind_q.lock, flags); -+ skb = __skb_dequeue(&htt->rx_in_ord_compl_q); -+ if (!skb) { -+ resched_napi = true; -+ goto exit; -+ } -+ -+ spin_lock_bh(&htt->rx_ring.lock); -+ num_rx_msdus = ath10k_htt_rx_in_ord_ind(ar, skb); -+ spin_unlock_bh(&htt->rx_ring.lock); -+ if (num_rx_msdus < 0) { -+ resched_napi = true; -+ goto exit; -+ } -+ -+ dev_kfree_skb_any(skb); -+ if (num_rx_msdus > 0) -+ quota += num_rx_msdus; -+ -+ if ((quota > ATH10K_NAPI_QUOTA_LIMIT) && -+ !skb_queue_empty(&htt->rx_in_ord_compl_q)) { -+ resched_napi = true; -+ goto exit; -+ } -+ } -+ -+ while (quota < budget) { -+ /* no more data to receive */ -+ if (!atomic_read(&htt->num_mpdus_ready)) -+ break; -+ -+ num_rx_msdus = ath10k_htt_rx_handle_amsdu(htt); -+ if (num_rx_msdus < 0) { -+ resched_napi = true; -+ goto exit; -+ } -+ -+ quota += num_rx_msdus; -+ atomic_dec(&htt->num_mpdus_ready); -+ if ((quota > ATH10K_NAPI_QUOTA_LIMIT) && -+ atomic_read(&htt->num_mpdus_ready)) { -+ resched_napi = true; -+ goto exit; -+ } -+ } -+ -+ /* From NAPI documentation: -+ * The napi poll() function may also process TX completions, in which -+ * case if it processes the entire TX ring then it should count that -+ * work as the rest of the budget. -+ */ -+ if ((quota < budget) && !kfifo_is_empty(&htt->txdone_fifo)) -+ quota = budget; - - /* kfifo_get: called only within txrx_tasklet so it's neatly serialized. - * From kfifo_get() documentation: -@@ -2408,27 +2447,22 @@ static void ath10k_htt_txrx_compl_task(u - while (kfifo_get(&htt->txdone_fifo, &tx_done)) - ath10k_txrx_tx_unref(htt, &tx_done); - -+ spin_lock_irqsave(&htt->tx_fetch_ind_q.lock, flags); -+ skb_queue_splice_init(&htt->tx_fetch_ind_q, &tx_ind_q); -+ spin_unlock_irqrestore(&htt->tx_fetch_ind_q.lock, flags); -+ - while ((skb = __skb_dequeue(&tx_ind_q))) { - ath10k_htt_rx_tx_fetch_ind(ar, skb); - dev_kfree_skb_any(skb); - } - -- num_mpdus = atomic_read(&htt->num_mpdus_ready); -- -- while (num_mpdus) { -- if (ath10k_htt_rx_handle_amsdu(htt)) -- break; -- -- num_mpdus--; -- atomic_dec(&htt->num_mpdus_ready); -- } -- -- while ((skb = __skb_dequeue(&rx_ind_q))) { -- spin_lock_bh(&htt->rx_ring.lock); -- ath10k_htt_rx_in_ord_ind(ar, skb); -- spin_unlock_bh(&htt->rx_ring.lock); -- dev_kfree_skb_any(skb); -- } -- -+exit: - ath10k_htt_rx_msdu_buff_replenish(htt); -+ /* In case of rx failure or more data to read, report budget -+ * to reschedule NAPI poll -+ */ -+ done = resched_napi ? budget : quota; -+ -+ return done; - } -+EXPORT_SYMBOL(ath10k_htt_txrx_compl_task); ---- a/drivers/net/wireless/ath/ath10k/htt_tx.c -+++ b/drivers/net/wireless/ath/ath10k/htt_tx.c -@@ -388,8 +388,6 @@ void ath10k_htt_tx_free(struct ath10k_ht - { - int size; - -- tasklet_kill(&htt->txrx_compl_task); -- - idr_for_each(&htt->pending_tx, ath10k_htt_tx_clean_up_pending, htt->ar); - idr_destroy(&htt->pending_tx); - ---- a/drivers/net/wireless/ath/ath10k/pci.c -+++ b/drivers/net/wireless/ath/ath10k/pci.c -@@ -1502,12 +1502,10 @@ void ath10k_pci_hif_send_complete_check( - ath10k_ce_per_engine_service(ar, pipe); - } - --void ath10k_pci_kill_tasklet(struct ath10k *ar) -+static void ath10k_pci_rx_retry_sync(struct ath10k *ar) - { - struct ath10k_pci *ar_pci = ath10k_pci_priv(ar); - -- tasklet_kill(&ar_pci->intr_tq); -- - del_timer_sync(&ar_pci->rx_post_retry); - } - -@@ -1566,7 +1564,7 @@ void ath10k_pci_hif_get_default_pipe(str - ul_pipe, dl_pipe); - } - --static void ath10k_pci_irq_msi_fw_mask(struct ath10k *ar) -+void ath10k_pci_irq_msi_fw_mask(struct ath10k *ar) - { - u32 val; - -@@ -1747,7 +1745,7 @@ void ath10k_pci_ce_deinit(struct ath10k - - void ath10k_pci_flush(struct ath10k *ar) - { -- ath10k_pci_kill_tasklet(ar); -+ ath10k_pci_rx_retry_sync(ar); - ath10k_pci_buffer_cleanup(ar); - } - -@@ -2754,35 +2752,53 @@ static irqreturn_t ath10k_pci_interrupt_ - return IRQ_NONE; - } - -- if (ar_pci->oper_irq_mode == ATH10K_PCI_IRQ_LEGACY) { -- if (!ath10k_pci_irq_pending(ar)) -- return IRQ_NONE; -- -- ath10k_pci_disable_and_clear_legacy_irq(ar); -- } -+ if ((ar_pci->oper_irq_mode == ATH10K_PCI_IRQ_LEGACY) && -+ !ath10k_pci_irq_pending(ar)) -+ return IRQ_NONE; - -- tasklet_schedule(&ar_pci->intr_tq); -+ ath10k_pci_disable_and_clear_legacy_irq(ar); -+ ath10k_pci_irq_msi_fw_mask(ar); -+ napi_schedule(&ar->napi); - - return IRQ_HANDLED; - } - --static void ath10k_pci_tasklet(unsigned long data) -+static int ath10k_pci_napi_poll(struct napi_struct *ctx, int budget) - { -- struct ath10k *ar = (struct ath10k *)data; -- struct ath10k_pci *ar_pci = ath10k_pci_priv(ar); -+ struct ath10k *ar = container_of(ctx, struct ath10k, napi); -+ int done = 0; - - if (ath10k_pci_has_fw_crashed(ar)) { -- ath10k_pci_irq_disable(ar); - ath10k_pci_fw_crashed_clear(ar); - ath10k_pci_fw_crashed_dump(ar); -- return; -+ napi_complete(ctx); -+ return done; - } - - ath10k_ce_per_engine_service_any(ar); - -- /* Re-enable legacy irq that was disabled in the irq handler */ -- if (ar_pci->oper_irq_mode == ATH10K_PCI_IRQ_LEGACY) -+ done = ath10k_htt_txrx_compl_task(ar, budget); -+ -+ if (done < budget) { -+ napi_complete(ctx); -+ /* In case of MSI, it is possible that interrupts are received -+ * while NAPI poll is inprogress. So pending interrupts that are -+ * received after processing all copy engine pipes by NAPI poll -+ * will not be handled again. This is causing failure to -+ * complete boot sequence in x86 platform. So before enabling -+ * interrupts safer to check for pending interrupts for -+ * immediate servicing. -+ */ -+ if (CE_INTERRUPT_SUMMARY(ar)) { -+ napi_reschedule(&ar->napi); -+ goto out; -+ } - ath10k_pci_enable_legacy_irq(ar); -+ ath10k_pci_irq_msi_fw_unmask(ar); -+ } -+ -+out: -+ return done; - } - - static int ath10k_pci_request_irq_msi(struct ath10k *ar) -@@ -2840,11 +2856,11 @@ static void ath10k_pci_free_irq(struct a - free_irq(ar_pci->pdev->irq, ar); - } - --void ath10k_pci_init_irq_tasklets(struct ath10k *ar) -+void ath10k_pci_init_napi(struct ath10k *ar) - { -- struct ath10k_pci *ar_pci = ath10k_pci_priv(ar); -- -- tasklet_init(&ar_pci->intr_tq, ath10k_pci_tasklet, (unsigned long)ar); -+ netif_napi_add(&ar->napi_dev, &ar->napi, ath10k_pci_napi_poll, -+ ATH10K_NAPI_BUDGET); -+ napi_enable(&ar->napi); - } - - static int ath10k_pci_init_irq(struct ath10k *ar) -@@ -2852,7 +2868,7 @@ static int ath10k_pci_init_irq(struct at - struct ath10k_pci *ar_pci = ath10k_pci_priv(ar); - int ret; - -- ath10k_pci_init_irq_tasklets(ar); -+ ath10k_pci_init_napi(ar); - - if (ath10k_pci_irq_mode != ATH10K_PCI_IRQ_AUTO) - ath10k_info(ar, "limiting irq mode to: %d\n", -@@ -3113,7 +3129,8 @@ int ath10k_pci_setup_resource(struct ath - - void ath10k_pci_release_resource(struct ath10k *ar) - { -- ath10k_pci_kill_tasklet(ar); -+ ath10k_pci_rx_retry_sync(ar); -+ netif_napi_del(&ar->napi); - ath10k_pci_ce_deinit(ar); - ath10k_pci_free_pipes(ar); - } -@@ -3274,7 +3291,7 @@ static int ath10k_pci_probe(struct pci_d - - err_free_irq: - ath10k_pci_free_irq(ar); -- ath10k_pci_kill_tasklet(ar); -+ ath10k_pci_rx_retry_sync(ar); - - err_deinit_irq: - ath10k_pci_deinit_irq(ar); ---- a/drivers/net/wireless/ath/ath10k/pci.h -+++ b/drivers/net/wireless/ath/ath10k/pci.h -@@ -177,8 +177,6 @@ struct ath10k_pci { - /* Operating interrupt mode */ - enum ath10k_pci_irq_mode oper_irq_mode; - -- struct tasklet_struct intr_tq; -- - struct ath10k_pci_pipe pipe_info[CE_COUNT_MAX]; - - /* Copy Engine used for Diagnostic Accesses */ -@@ -294,8 +292,7 @@ void ath10k_pci_free_pipes(struct ath10k - void ath10k_pci_free_pipes(struct ath10k *ar); - void ath10k_pci_rx_replenish_retry(unsigned long ptr); - void ath10k_pci_ce_deinit(struct ath10k *ar); --void ath10k_pci_init_irq_tasklets(struct ath10k *ar); --void ath10k_pci_kill_tasklet(struct ath10k *ar); -+void ath10k_pci_init_napi(struct ath10k *ar); - int ath10k_pci_init_pipes(struct ath10k *ar); - int ath10k_pci_init_config(struct ath10k *ar); - void ath10k_pci_rx_post(struct ath10k *ar); -@@ -303,6 +300,7 @@ void ath10k_pci_flush(struct ath10k *ar) - void ath10k_pci_enable_legacy_irq(struct ath10k *ar); - bool ath10k_pci_irq_pending(struct ath10k *ar); - void ath10k_pci_disable_and_clear_legacy_irq(struct ath10k *ar); -+void ath10k_pci_irq_msi_fw_mask(struct ath10k *ar); - int ath10k_pci_wait_for_target_init(struct ath10k *ar); - int ath10k_pci_setup_resource(struct ath10k *ar); - void ath10k_pci_release_resource(struct ath10k *ar); |