ath10k: add NAPI support
[openwrt/openwrt.git] / package / kernel / mac80211 / patches / 332-ath10k-implement-NAPI-support.patch
1 From: Rajkumar Manoharan <rmanohar@qti.qualcomm.com>
2 Date: Thu, 21 Jul 2016 11:50:00 +0530
3 Subject: [PATCH] ath10k: implement NAPI support
4
5 Add NAPI support for rx and tx completion. NAPI poll is scheduled
6 from interrupt handler. The design is as below
7
8 - on interrupt
9 - schedule napi and mask interrupts
10 - on poll
11 - process all pipes (no actual Tx/Rx)
12 - process Rx within budget
13 - if quota exceeds budget reschedule napi poll by returning budget
14 - process Tx completions and update budget if necessary
15 - process Tx fetch indications (pull-push)
16 - push any other pending Tx (if possible)
17 - before resched or napi completion replenish htt rx ring buffer
18 - if work done < budget, complete napi poll and unmask interrupts
19
20 This change also get rid of two tasklets (intr_tq and txrx_compl_task).
21
22 Measured peak throughput with NAPI on IPQ4019 platform in controlled
23 environment. No noticeable reduction in throughput is seen and also
24 observed improvements in CPU usage. Approx. 15% CPU usage got reduced
25 in UDP uplink case.
26
27 DL: AP DUT Tx
28 UL: AP DUT Rx
29
30 IPQ4019 (avg. cpu usage %)
31 ========
32 TOT +NAPI
33 =========== =============
34 TCP DL 644 Mbps (42%) 645 Mbps (36%)
35 TCP UL 673 Mbps (30%) 675 Mbps (26%)
36 UDP DL 682 Mbps (49%) 680 Mbps (49%)
37 UDP UL 720 Mbps (28%) 717 Mbps (11%)
38
39 Signed-off-by: Rajkumar Manoharan <rmanohar@qti.qualcomm.com>
40 ---
41
42 --- a/drivers/net/wireless/ath/ath10k/ahb.c
43 +++ b/drivers/net/wireless/ath/ath10k/ahb.c
44 @@ -462,13 +462,13 @@ static void ath10k_ahb_halt_chip(struct
45 static irqreturn_t ath10k_ahb_interrupt_handler(int irq, void *arg)
46 {
47 struct ath10k *ar = arg;
48 - struct ath10k_pci *ar_pci = ath10k_pci_priv(ar);
49
50 if (!ath10k_pci_irq_pending(ar))
51 return IRQ_NONE;
52
53 ath10k_pci_disable_and_clear_legacy_irq(ar);
54 - tasklet_schedule(&ar_pci->intr_tq);
55 + ath10k_pci_irq_msi_fw_mask(ar);
56 + napi_schedule(&ar->napi);
57
58 return IRQ_HANDLED;
59 }
60 @@ -831,7 +831,7 @@ static int ath10k_ahb_probe(struct platf
61 goto err_resource_deinit;
62 }
63
64 - ath10k_pci_init_irq_tasklets(ar);
65 + ath10k_pci_init_napi(ar);
66
67 ret = ath10k_ahb_request_irq_legacy(ar);
68 if (ret)
69 --- a/drivers/net/wireless/ath/ath10k/core.c
70 +++ b/drivers/net/wireless/ath/ath10k/core.c
71 @@ -2226,6 +2226,8 @@ struct ath10k *ath10k_core_create(size_t
72 INIT_WORK(&ar->register_work, ath10k_core_register_work);
73 INIT_WORK(&ar->restart_work, ath10k_core_restart);
74
75 + init_dummy_netdev(&ar->napi_dev);
76 +
77 ret = ath10k_debug_create(ar);
78 if (ret)
79 goto err_free_aux_wq;
80 --- a/drivers/net/wireless/ath/ath10k/core.h
81 +++ b/drivers/net/wireless/ath/ath10k/core.h
82 @@ -65,6 +65,10 @@
83 #define ATH10K_KEEPALIVE_MAX_IDLE 3895
84 #define ATH10K_KEEPALIVE_MAX_UNRESPONSIVE 3900
85
86 +/* NAPI poll budget */
87 +#define ATH10K_NAPI_BUDGET 64
88 +#define ATH10K_NAPI_QUOTA_LIMIT 60
89 +
90 struct ath10k;
91
92 enum ath10k_bus {
93 @@ -933,6 +937,10 @@ struct ath10k {
94 struct ath10k_thermal thermal;
95 struct ath10k_wow wow;
96
97 + /* NAPI */
98 + struct net_device napi_dev;
99 + struct napi_struct napi;
100 +
101 /* must be last */
102 u8 drv_priv[0] __aligned(sizeof(void *));
103 };
104 --- a/drivers/net/wireless/ath/ath10k/htt.h
105 +++ b/drivers/net/wireless/ath/ath10k/htt.h
106 @@ -1666,7 +1666,6 @@ struct ath10k_htt {
107
108 /* This is used to group tx/rx completions separately and process them
109 * in batches to reduce cache stalls */
110 - struct tasklet_struct txrx_compl_task;
111 struct sk_buff_head rx_compl_q;
112 struct sk_buff_head rx_in_ord_compl_q;
113 struct sk_buff_head tx_fetch_ind_q;
114 @@ -1799,5 +1798,6 @@ int ath10k_htt_tx(struct ath10k_htt *htt
115 struct sk_buff *msdu);
116 void ath10k_htt_rx_pktlog_completion_handler(struct ath10k *ar,
117 struct sk_buff *skb);
118 +int ath10k_htt_txrx_compl_task(struct ath10k *ar, int budget);
119
120 #endif
121 --- a/drivers/net/wireless/ath/ath10k/htt_rx.c
122 +++ b/drivers/net/wireless/ath/ath10k/htt_rx.c
123 @@ -34,7 +34,6 @@
124 #define HTT_RX_RING_REFILL_RESCHED_MS 5
125
126 static int ath10k_htt_rx_get_csum_state(struct sk_buff *skb);
127 -static void ath10k_htt_txrx_compl_task(unsigned long ptr);
128
129 static struct sk_buff *
130 ath10k_htt_rx_find_skb_paddr(struct ath10k *ar, u32 paddr)
131 @@ -226,7 +225,6 @@ int ath10k_htt_rx_ring_refill(struct ath
132 void ath10k_htt_rx_free(struct ath10k_htt *htt)
133 {
134 del_timer_sync(&htt->rx_ring.refill_retry_timer);
135 - tasklet_kill(&htt->txrx_compl_task);
136
137 skb_queue_purge(&htt->rx_compl_q);
138 skb_queue_purge(&htt->rx_in_ord_compl_q);
139 @@ -520,9 +518,6 @@ int ath10k_htt_rx_alloc(struct ath10k_ht
140 skb_queue_head_init(&htt->tx_fetch_ind_q);
141 atomic_set(&htt->num_mpdus_ready, 0);
142
143 - tasklet_init(&htt->txrx_compl_task, ath10k_htt_txrx_compl_task,
144 - (unsigned long)htt);
145 -
146 ath10k_dbg(ar, ATH10K_DBG_BOOT, "htt rx ring size %d fill_level %d\n",
147 htt->rx_ring.size, htt->rx_ring.fill_level);
148 return 0;
149 @@ -958,7 +953,7 @@ static void ath10k_process_rx(struct ath
150 trace_ath10k_rx_hdr(ar, skb->data, skb->len);
151 trace_ath10k_rx_payload(ar, skb->data, skb->len);
152
153 - ieee80211_rx(ar->hw, skb);
154 + ieee80211_rx_napi(ar->hw, NULL, skb, &ar->napi);
155 }
156
157 static int ath10k_htt_rx_nwifi_hdrlen(struct ath10k *ar,
158 @@ -1527,7 +1522,7 @@ static int ath10k_htt_rx_handle_amsdu(st
159 struct ath10k *ar = htt->ar;
160 struct ieee80211_rx_status *rx_status = &htt->rx_status;
161 struct sk_buff_head amsdu;
162 - int ret;
163 + int ret, num_msdus;
164
165 __skb_queue_head_init(&amsdu);
166
167 @@ -1549,13 +1544,14 @@ static int ath10k_htt_rx_handle_amsdu(st
168 return ret;
169 }
170
171 + num_msdus = skb_queue_len(&amsdu);
172 ath10k_htt_rx_h_ppdu(ar, &amsdu, rx_status, 0xffff);
173 ath10k_htt_rx_h_unchain(ar, &amsdu, ret > 0);
174 ath10k_htt_rx_h_filter(ar, &amsdu, rx_status);
175 ath10k_htt_rx_h_mpdu(ar, &amsdu, rx_status);
176 ath10k_htt_rx_h_deliver(ar, &amsdu, rx_status);
177
178 - return 0;
179 + return num_msdus;
180 }
181
182 static void ath10k_htt_rx_proc_rx_ind(struct ath10k_htt *htt,
183 @@ -1579,15 +1575,6 @@ static void ath10k_htt_rx_proc_rx_ind(st
184 mpdu_count += mpdu_ranges[i].mpdu_count;
185
186 atomic_add(mpdu_count, &htt->num_mpdus_ready);
187 -
188 - tasklet_schedule(&htt->txrx_compl_task);
189 -}
190 -
191 -static void ath10k_htt_rx_frag_handler(struct ath10k_htt *htt)
192 -{
193 - atomic_inc(&htt->num_mpdus_ready);
194 -
195 - tasklet_schedule(&htt->txrx_compl_task);
196 }
197
198 static void ath10k_htt_rx_tx_compl_ind(struct ath10k *ar,
199 @@ -1772,14 +1759,15 @@ static void ath10k_htt_rx_h_rx_offload_p
200 RX_FLAG_MMIC_STRIPPED;
201 }
202
203 -static void ath10k_htt_rx_h_rx_offload(struct ath10k *ar,
204 - struct sk_buff_head *list)
205 +static int ath10k_htt_rx_h_rx_offload(struct ath10k *ar,
206 + struct sk_buff_head *list)
207 {
208 struct ath10k_htt *htt = &ar->htt;
209 struct ieee80211_rx_status *status = &htt->rx_status;
210 struct htt_rx_offload_msdu *rx;
211 struct sk_buff *msdu;
212 size_t offset;
213 + int num_msdu = 0;
214
215 while ((msdu = __skb_dequeue(list))) {
216 /* Offloaded frames don't have Rx descriptor. Instead they have
217 @@ -1819,10 +1807,12 @@ static void ath10k_htt_rx_h_rx_offload(s
218 ath10k_htt_rx_h_rx_offload_prot(status, msdu);
219 ath10k_htt_rx_h_channel(ar, status, NULL, rx->vdev_id);
220 ath10k_process_rx(ar, status, msdu);
221 + num_msdu++;
222 }
223 + return num_msdu;
224 }
225
226 -static void ath10k_htt_rx_in_ord_ind(struct ath10k *ar, struct sk_buff *skb)
227 +static int ath10k_htt_rx_in_ord_ind(struct ath10k *ar, struct sk_buff *skb)
228 {
229 struct ath10k_htt *htt = &ar->htt;
230 struct htt_resp *resp = (void *)skb->data;
231 @@ -1835,12 +1825,12 @@ static void ath10k_htt_rx_in_ord_ind(str
232 u8 tid;
233 bool offload;
234 bool frag;
235 - int ret;
236 + int ret, num_msdus = 0;
237
238 lockdep_assert_held(&htt->rx_ring.lock);
239
240 if (htt->rx_confused)
241 - return;
242 + return -EIO;
243
244 skb_pull(skb, sizeof(resp->hdr));
245 skb_pull(skb, sizeof(resp->rx_in_ord_ind));
246 @@ -1859,7 +1849,7 @@ static void ath10k_htt_rx_in_ord_ind(str
247
248 if (skb->len < msdu_count * sizeof(*resp->rx_in_ord_ind.msdu_descs)) {
249 ath10k_warn(ar, "dropping invalid in order rx indication\n");
250 - return;
251 + return -EINVAL;
252 }
253
254 /* The event can deliver more than 1 A-MSDU. Each A-MSDU is later
255 @@ -1870,14 +1860,14 @@ static void ath10k_htt_rx_in_ord_ind(str
256 if (ret < 0) {
257 ath10k_warn(ar, "failed to pop paddr list: %d\n", ret);
258 htt->rx_confused = true;
259 - return;
260 + return -EIO;
261 }
262
263 /* Offloaded frames are very different and need to be handled
264 * separately.
265 */
266 if (offload)
267 - ath10k_htt_rx_h_rx_offload(ar, &list);
268 + num_msdus = ath10k_htt_rx_h_rx_offload(ar, &list);
269
270 while (!skb_queue_empty(&list)) {
271 __skb_queue_head_init(&amsdu);
272 @@ -1890,6 +1880,7 @@ static void ath10k_htt_rx_in_ord_ind(str
273 * better to report something than nothing though. This
274 * should still give an idea about rx rate to the user.
275 */
276 + num_msdus += skb_queue_len(&amsdu);
277 ath10k_htt_rx_h_ppdu(ar, &amsdu, status, vdev_id);
278 ath10k_htt_rx_h_filter(ar, &amsdu, status);
279 ath10k_htt_rx_h_mpdu(ar, &amsdu, status);
280 @@ -1902,9 +1893,10 @@ static void ath10k_htt_rx_in_ord_ind(str
281 ath10k_warn(ar, "failed to extract amsdu: %d\n", ret);
282 htt->rx_confused = true;
283 __skb_queue_purge(&list);
284 - return;
285 + return -EIO;
286 }
287 }
288 + return num_msdus;
289 }
290
291 static void ath10k_htt_rx_tx_fetch_resp_id_confirm(struct ath10k *ar,
292 @@ -2267,7 +2259,6 @@ bool ath10k_htt_t2h_msg_handler(struct a
293 }
294 case HTT_T2H_MSG_TYPE_TX_COMPL_IND:
295 ath10k_htt_rx_tx_compl_ind(htt->ar, skb);
296 - tasklet_schedule(&htt->txrx_compl_task);
297 break;
298 case HTT_T2H_MSG_TYPE_SEC_IND: {
299 struct ath10k *ar = htt->ar;
300 @@ -2284,7 +2275,7 @@ bool ath10k_htt_t2h_msg_handler(struct a
301 case HTT_T2H_MSG_TYPE_RX_FRAG_IND: {
302 ath10k_dbg_dump(ar, ATH10K_DBG_HTT_DUMP, NULL, "htt event: ",
303 skb->data, skb->len);
304 - ath10k_htt_rx_frag_handler(htt);
305 + atomic_inc(&htt->num_mpdus_ready);
306 break;
307 }
308 case HTT_T2H_MSG_TYPE_TEST:
309 @@ -2322,8 +2313,7 @@ bool ath10k_htt_t2h_msg_handler(struct a
310 break;
311 }
312 case HTT_T2H_MSG_TYPE_RX_IN_ORD_PADDR_IND: {
313 - skb_queue_tail(&htt->rx_in_ord_compl_q, skb);
314 - tasklet_schedule(&htt->txrx_compl_task);
315 + __skb_queue_tail(&htt->rx_in_ord_compl_q, skb);
316 return false;
317 }
318 case HTT_T2H_MSG_TYPE_TX_CREDIT_UPDATE_IND:
319 @@ -2349,7 +2339,6 @@ bool ath10k_htt_t2h_msg_handler(struct a
320 break;
321 }
322 skb_queue_tail(&htt->tx_fetch_ind_q, tx_fetch_ind);
323 - tasklet_schedule(&htt->txrx_compl_task);
324 break;
325 }
326 case HTT_T2H_MSG_TYPE_TX_FETCH_CONFIRM:
327 @@ -2378,27 +2367,77 @@ void ath10k_htt_rx_pktlog_completion_han
328 }
329 EXPORT_SYMBOL(ath10k_htt_rx_pktlog_completion_handler);
330
331 -static void ath10k_htt_txrx_compl_task(unsigned long ptr)
332 +int ath10k_htt_txrx_compl_task(struct ath10k *ar, int budget)
333 {
334 - struct ath10k_htt *htt = (struct ath10k_htt *)ptr;
335 - struct ath10k *ar = htt->ar;
336 + struct ath10k_htt *htt = &ar->htt;
337 struct htt_tx_done tx_done = {};
338 - struct sk_buff_head rx_ind_q;
339 struct sk_buff_head tx_ind_q;
340 struct sk_buff *skb;
341 unsigned long flags;
342 - int num_mpdus;
343 + int quota = 0, done, num_rx_msdus;
344 + bool resched_napi = false;
345
346 - __skb_queue_head_init(&rx_ind_q);
347 __skb_queue_head_init(&tx_ind_q);
348
349 - spin_lock_irqsave(&htt->rx_in_ord_compl_q.lock, flags);
350 - skb_queue_splice_init(&htt->rx_in_ord_compl_q, &rx_ind_q);
351 - spin_unlock_irqrestore(&htt->rx_in_ord_compl_q.lock, flags);
352 + /* Since in-ord-ind can deliver more than 1 A-MSDU in single event,
353 + * process it first to utilize full available quota.
354 + */
355 + while (quota < budget) {
356 + if (skb_queue_empty(&htt->rx_in_ord_compl_q))
357 + break;
358
359 - spin_lock_irqsave(&htt->tx_fetch_ind_q.lock, flags);
360 - skb_queue_splice_init(&htt->tx_fetch_ind_q, &tx_ind_q);
361 - spin_unlock_irqrestore(&htt->tx_fetch_ind_q.lock, flags);
362 + skb = __skb_dequeue(&htt->rx_in_ord_compl_q);
363 + if (!skb) {
364 + resched_napi = true;
365 + goto exit;
366 + }
367 +
368 + spin_lock_bh(&htt->rx_ring.lock);
369 + num_rx_msdus = ath10k_htt_rx_in_ord_ind(ar, skb);
370 + spin_unlock_bh(&htt->rx_ring.lock);
371 + if (num_rx_msdus < 0) {
372 + resched_napi = true;
373 + goto exit;
374 + }
375 +
376 + dev_kfree_skb_any(skb);
377 + if (num_rx_msdus > 0)
378 + quota += num_rx_msdus;
379 +
380 + if ((quota > ATH10K_NAPI_QUOTA_LIMIT) &&
381 + !skb_queue_empty(&htt->rx_in_ord_compl_q)) {
382 + resched_napi = true;
383 + goto exit;
384 + }
385 + }
386 +
387 + while (quota < budget) {
388 + /* no more data to receive */
389 + if (!atomic_read(&htt->num_mpdus_ready))
390 + break;
391 +
392 + num_rx_msdus = ath10k_htt_rx_handle_amsdu(htt);
393 + if (num_rx_msdus < 0) {
394 + resched_napi = true;
395 + goto exit;
396 + }
397 +
398 + quota += num_rx_msdus;
399 + atomic_dec(&htt->num_mpdus_ready);
400 + if ((quota > ATH10K_NAPI_QUOTA_LIMIT) &&
401 + atomic_read(&htt->num_mpdus_ready)) {
402 + resched_napi = true;
403 + goto exit;
404 + }
405 + }
406 +
407 + /* From NAPI documentation:
408 + * The napi poll() function may also process TX completions, in which
409 + * case if it processes the entire TX ring then it should count that
410 + * work as the rest of the budget.
411 + */
412 + if ((quota < budget) && !kfifo_is_empty(&htt->txdone_fifo))
413 + quota = budget;
414
415 /* kfifo_get: called only within txrx_tasklet so it's neatly serialized.
416 * From kfifo_get() documentation:
417 @@ -2408,27 +2447,22 @@ static void ath10k_htt_txrx_compl_task(u
418 while (kfifo_get(&htt->txdone_fifo, &tx_done))
419 ath10k_txrx_tx_unref(htt, &tx_done);
420
421 + spin_lock_irqsave(&htt->tx_fetch_ind_q.lock, flags);
422 + skb_queue_splice_init(&htt->tx_fetch_ind_q, &tx_ind_q);
423 + spin_unlock_irqrestore(&htt->tx_fetch_ind_q.lock, flags);
424 +
425 while ((skb = __skb_dequeue(&tx_ind_q))) {
426 ath10k_htt_rx_tx_fetch_ind(ar, skb);
427 dev_kfree_skb_any(skb);
428 }
429
430 - num_mpdus = atomic_read(&htt->num_mpdus_ready);
431 -
432 - while (num_mpdus) {
433 - if (ath10k_htt_rx_handle_amsdu(htt))
434 - break;
435 -
436 - num_mpdus--;
437 - atomic_dec(&htt->num_mpdus_ready);
438 - }
439 -
440 - while ((skb = __skb_dequeue(&rx_ind_q))) {
441 - spin_lock_bh(&htt->rx_ring.lock);
442 - ath10k_htt_rx_in_ord_ind(ar, skb);
443 - spin_unlock_bh(&htt->rx_ring.lock);
444 - dev_kfree_skb_any(skb);
445 - }
446 -
447 +exit:
448 ath10k_htt_rx_msdu_buff_replenish(htt);
449 + /* In case of rx failure or more data to read, report budget
450 + * to reschedule NAPI poll
451 + */
452 + done = resched_napi ? budget : quota;
453 +
454 + return done;
455 }
456 +EXPORT_SYMBOL(ath10k_htt_txrx_compl_task);
457 --- a/drivers/net/wireless/ath/ath10k/htt_tx.c
458 +++ b/drivers/net/wireless/ath/ath10k/htt_tx.c
459 @@ -388,8 +388,6 @@ void ath10k_htt_tx_free(struct ath10k_ht
460 {
461 int size;
462
463 - tasklet_kill(&htt->txrx_compl_task);
464 -
465 idr_for_each(&htt->pending_tx, ath10k_htt_tx_clean_up_pending, htt->ar);
466 idr_destroy(&htt->pending_tx);
467
468 --- a/drivers/net/wireless/ath/ath10k/pci.c
469 +++ b/drivers/net/wireless/ath/ath10k/pci.c
470 @@ -1502,12 +1502,10 @@ void ath10k_pci_hif_send_complete_check(
471 ath10k_ce_per_engine_service(ar, pipe);
472 }
473
474 -void ath10k_pci_kill_tasklet(struct ath10k *ar)
475 +static void ath10k_pci_rx_retry_sync(struct ath10k *ar)
476 {
477 struct ath10k_pci *ar_pci = ath10k_pci_priv(ar);
478
479 - tasklet_kill(&ar_pci->intr_tq);
480 -
481 del_timer_sync(&ar_pci->rx_post_retry);
482 }
483
484 @@ -1566,7 +1564,7 @@ void ath10k_pci_hif_get_default_pipe(str
485 ul_pipe, dl_pipe);
486 }
487
488 -static void ath10k_pci_irq_msi_fw_mask(struct ath10k *ar)
489 +void ath10k_pci_irq_msi_fw_mask(struct ath10k *ar)
490 {
491 u32 val;
492
493 @@ -1747,7 +1745,7 @@ void ath10k_pci_ce_deinit(struct ath10k
494
495 void ath10k_pci_flush(struct ath10k *ar)
496 {
497 - ath10k_pci_kill_tasklet(ar);
498 + ath10k_pci_rx_retry_sync(ar);
499 ath10k_pci_buffer_cleanup(ar);
500 }
501
502 @@ -2754,35 +2752,53 @@ static irqreturn_t ath10k_pci_interrupt_
503 return IRQ_NONE;
504 }
505
506 - if (ar_pci->oper_irq_mode == ATH10K_PCI_IRQ_LEGACY) {
507 - if (!ath10k_pci_irq_pending(ar))
508 - return IRQ_NONE;
509 -
510 - ath10k_pci_disable_and_clear_legacy_irq(ar);
511 - }
512 + if ((ar_pci->oper_irq_mode == ATH10K_PCI_IRQ_LEGACY) &&
513 + !ath10k_pci_irq_pending(ar))
514 + return IRQ_NONE;
515
516 - tasklet_schedule(&ar_pci->intr_tq);
517 + ath10k_pci_disable_and_clear_legacy_irq(ar);
518 + ath10k_pci_irq_msi_fw_mask(ar);
519 + napi_schedule(&ar->napi);
520
521 return IRQ_HANDLED;
522 }
523
524 -static void ath10k_pci_tasklet(unsigned long data)
525 +static int ath10k_pci_napi_poll(struct napi_struct *ctx, int budget)
526 {
527 - struct ath10k *ar = (struct ath10k *)data;
528 - struct ath10k_pci *ar_pci = ath10k_pci_priv(ar);
529 + struct ath10k *ar = container_of(ctx, struct ath10k, napi);
530 + int done = 0;
531
532 if (ath10k_pci_has_fw_crashed(ar)) {
533 - ath10k_pci_irq_disable(ar);
534 ath10k_pci_fw_crashed_clear(ar);
535 ath10k_pci_fw_crashed_dump(ar);
536 - return;
537 + napi_complete(ctx);
538 + return done;
539 }
540
541 ath10k_ce_per_engine_service_any(ar);
542
543 - /* Re-enable legacy irq that was disabled in the irq handler */
544 - if (ar_pci->oper_irq_mode == ATH10K_PCI_IRQ_LEGACY)
545 + done = ath10k_htt_txrx_compl_task(ar, budget);
546 +
547 + if (done < budget) {
548 + napi_complete(ctx);
549 + /* In case of MSI, it is possible that interrupts are received
550 + * while NAPI poll is inprogress. So pending interrupts that are
551 + * received after processing all copy engine pipes by NAPI poll
552 + * will not be handled again. This is causing failure to
553 + * complete boot sequence in x86 platform. So before enabling
554 + * interrupts safer to check for pending interrupts for
555 + * immediate servicing.
556 + */
557 + if (CE_INTERRUPT_SUMMARY(ar)) {
558 + napi_reschedule(&ar->napi);
559 + goto out;
560 + }
561 ath10k_pci_enable_legacy_irq(ar);
562 + ath10k_pci_irq_msi_fw_unmask(ar);
563 + }
564 +
565 +out:
566 + return done;
567 }
568
569 static int ath10k_pci_request_irq_msi(struct ath10k *ar)
570 @@ -2840,11 +2856,11 @@ static void ath10k_pci_free_irq(struct a
571 free_irq(ar_pci->pdev->irq, ar);
572 }
573
574 -void ath10k_pci_init_irq_tasklets(struct ath10k *ar)
575 +void ath10k_pci_init_napi(struct ath10k *ar)
576 {
577 - struct ath10k_pci *ar_pci = ath10k_pci_priv(ar);
578 -
579 - tasklet_init(&ar_pci->intr_tq, ath10k_pci_tasklet, (unsigned long)ar);
580 + netif_napi_add(&ar->napi_dev, &ar->napi, ath10k_pci_napi_poll,
581 + ATH10K_NAPI_BUDGET);
582 + napi_enable(&ar->napi);
583 }
584
585 static int ath10k_pci_init_irq(struct ath10k *ar)
586 @@ -2852,7 +2868,7 @@ static int ath10k_pci_init_irq(struct at
587 struct ath10k_pci *ar_pci = ath10k_pci_priv(ar);
588 int ret;
589
590 - ath10k_pci_init_irq_tasklets(ar);
591 + ath10k_pci_init_napi(ar);
592
593 if (ath10k_pci_irq_mode != ATH10K_PCI_IRQ_AUTO)
594 ath10k_info(ar, "limiting irq mode to: %d\n",
595 @@ -3113,7 +3129,8 @@ int ath10k_pci_setup_resource(struct ath
596
597 void ath10k_pci_release_resource(struct ath10k *ar)
598 {
599 - ath10k_pci_kill_tasklet(ar);
600 + ath10k_pci_rx_retry_sync(ar);
601 + netif_napi_del(&ar->napi);
602 ath10k_pci_ce_deinit(ar);
603 ath10k_pci_free_pipes(ar);
604 }
605 @@ -3274,7 +3291,7 @@ static int ath10k_pci_probe(struct pci_d
606
607 err_free_irq:
608 ath10k_pci_free_irq(ar);
609 - ath10k_pci_kill_tasklet(ar);
610 + ath10k_pci_rx_retry_sync(ar);
611
612 err_deinit_irq:
613 ath10k_pci_deinit_irq(ar);
614 --- a/drivers/net/wireless/ath/ath10k/pci.h
615 +++ b/drivers/net/wireless/ath/ath10k/pci.h
616 @@ -177,8 +177,6 @@ struct ath10k_pci {
617 /* Operating interrupt mode */
618 enum ath10k_pci_irq_mode oper_irq_mode;
619
620 - struct tasklet_struct intr_tq;
621 -
622 struct ath10k_pci_pipe pipe_info[CE_COUNT_MAX];
623
624 /* Copy Engine used for Diagnostic Accesses */
625 @@ -294,8 +292,7 @@ void ath10k_pci_free_pipes(struct ath10k
626 void ath10k_pci_free_pipes(struct ath10k *ar);
627 void ath10k_pci_rx_replenish_retry(unsigned long ptr);
628 void ath10k_pci_ce_deinit(struct ath10k *ar);
629 -void ath10k_pci_init_irq_tasklets(struct ath10k *ar);
630 -void ath10k_pci_kill_tasklet(struct ath10k *ar);
631 +void ath10k_pci_init_napi(struct ath10k *ar);
632 int ath10k_pci_init_pipes(struct ath10k *ar);
633 int ath10k_pci_init_config(struct ath10k *ar);
634 void ath10k_pci_rx_post(struct ath10k *ar);
635 @@ -303,6 +300,7 @@ void ath10k_pci_flush(struct ath10k *ar)
636 void ath10k_pci_enable_legacy_irq(struct ath10k *ar);
637 bool ath10k_pci_irq_pending(struct ath10k *ar);
638 void ath10k_pci_disable_and_clear_legacy_irq(struct ath10k *ar);
639 +void ath10k_pci_irq_msi_fw_mask(struct ath10k *ar);
640 int ath10k_pci_wait_for_target_init(struct ath10k *ar);
641 int ath10k_pci_setup_resource(struct ath10k *ar);
642 void ath10k_pci_release_resource(struct ath10k *ar);