Merge ath-next from git://git.kernel.org/pub/scm/linux/kernel/git/kvalo/ath.git
[linux-block.git] / drivers / net / wireless / ath / ath11k / pcic.c
1 // SPDX-License-Identifier: BSD-3-Clause-Clear
2 /*
3  * Copyright (c) 2019-2021 The Linux Foundation. All rights reserved.
4  * Copyright (c) 2021-2022, Qualcomm Innovation Center, Inc. All rights reserved.
5  */
6
7 #include "core.h"
8 #include "pcic.h"
9 #include "debug.h"
10
11 static const char *irq_name[ATH11K_IRQ_NUM_MAX] = {
12         "bhi",
13         "mhi-er0",
14         "mhi-er1",
15         "ce0",
16         "ce1",
17         "ce2",
18         "ce3",
19         "ce4",
20         "ce5",
21         "ce6",
22         "ce7",
23         "ce8",
24         "ce9",
25         "ce10",
26         "ce11",
27         "host2wbm-desc-feed",
28         "host2reo-re-injection",
29         "host2reo-command",
30         "host2rxdma-monitor-ring3",
31         "host2rxdma-monitor-ring2",
32         "host2rxdma-monitor-ring1",
33         "reo2ost-exception",
34         "wbm2host-rx-release",
35         "reo2host-status",
36         "reo2host-destination-ring4",
37         "reo2host-destination-ring3",
38         "reo2host-destination-ring2",
39         "reo2host-destination-ring1",
40         "rxdma2host-monitor-destination-mac3",
41         "rxdma2host-monitor-destination-mac2",
42         "rxdma2host-monitor-destination-mac1",
43         "ppdu-end-interrupts-mac3",
44         "ppdu-end-interrupts-mac2",
45         "ppdu-end-interrupts-mac1",
46         "rxdma2host-monitor-status-ring-mac3",
47         "rxdma2host-monitor-status-ring-mac2",
48         "rxdma2host-monitor-status-ring-mac1",
49         "host2rxdma-host-buf-ring-mac3",
50         "host2rxdma-host-buf-ring-mac2",
51         "host2rxdma-host-buf-ring-mac1",
52         "rxdma2host-destination-ring-mac3",
53         "rxdma2host-destination-ring-mac2",
54         "rxdma2host-destination-ring-mac1",
55         "host2tcl-input-ring4",
56         "host2tcl-input-ring3",
57         "host2tcl-input-ring2",
58         "host2tcl-input-ring1",
59         "wbm2host-tx-completions-ring3",
60         "wbm2host-tx-completions-ring2",
61         "wbm2host-tx-completions-ring1",
62         "tcl2host-status-ring",
63 };
64
65 static const struct ath11k_msi_config ath11k_msi_config[] = {
66         {
67                 .total_vectors = 32,
68                 .total_users = 4,
69                 .users = (struct ath11k_msi_user[]) {
70                         { .name = "MHI", .num_vectors = 3, .base_vector = 0 },
71                         { .name = "CE", .num_vectors = 10, .base_vector = 3 },
72                         { .name = "WAKE", .num_vectors = 1, .base_vector = 13 },
73                         { .name = "DP", .num_vectors = 18, .base_vector = 14 },
74                 },
75                 .hw_rev = ATH11K_HW_QCA6390_HW20,
76         },
77         {
78                 .total_vectors = 16,
79                 .total_users = 3,
80                 .users = (struct ath11k_msi_user[]) {
81                         { .name = "MHI", .num_vectors = 3, .base_vector = 0 },
82                         { .name = "CE", .num_vectors = 5, .base_vector = 3 },
83                         { .name = "DP", .num_vectors = 8, .base_vector = 8 },
84                 },
85                 .hw_rev = ATH11K_HW_QCN9074_HW10,
86         },
87         {
88                 .total_vectors = 32,
89                 .total_users = 4,
90                 .users = (struct ath11k_msi_user[]) {
91                         { .name = "MHI", .num_vectors = 3, .base_vector = 0 },
92                         { .name = "CE", .num_vectors = 10, .base_vector = 3 },
93                         { .name = "WAKE", .num_vectors = 1, .base_vector = 13 },
94                         { .name = "DP", .num_vectors = 18, .base_vector = 14 },
95                 },
96                 .hw_rev = ATH11K_HW_WCN6855_HW20,
97         },
98         {
99                 .total_vectors = 32,
100                 .total_users = 4,
101                 .users = (struct ath11k_msi_user[]) {
102                         { .name = "MHI", .num_vectors = 3, .base_vector = 0 },
103                         { .name = "CE", .num_vectors = 10, .base_vector = 3 },
104                         { .name = "WAKE", .num_vectors = 1, .base_vector = 13 },
105                         { .name = "DP", .num_vectors = 18, .base_vector = 14 },
106                 },
107                 .hw_rev = ATH11K_HW_WCN6855_HW21,
108         },
109         {
110                 .total_vectors = 28,
111                 .total_users = 2,
112                 .users = (struct ath11k_msi_user[]) {
113                         { .name = "CE", .num_vectors = 10, .base_vector = 0 },
114                         { .name = "DP", .num_vectors = 18, .base_vector = 10 },
115                 },
116                 .hw_rev = ATH11K_HW_WCN6750_HW10,
117         },
118 };
119
120 int ath11k_pcic_init_msi_config(struct ath11k_base *ab)
121 {
122         const struct ath11k_msi_config *msi_config;
123         int i;
124
125         for (i = 0; i < ARRAY_SIZE(ath11k_msi_config); i++) {
126                 msi_config = &ath11k_msi_config[i];
127
128                 if (msi_config->hw_rev == ab->hw_rev)
129                         break;
130         }
131
132         if (i == ARRAY_SIZE(ath11k_msi_config)) {
133                 ath11k_err(ab, "failed to fetch msi config, unsupported hw version: 0x%x\n",
134                            ab->hw_rev);
135                 return -EINVAL;
136         }
137
138         ab->pci.msi.config = msi_config;
139         return 0;
140 }
141 EXPORT_SYMBOL(ath11k_pcic_init_msi_config);
142
143 static void __ath11k_pcic_write32(struct ath11k_base *ab, u32 offset, u32 value)
144 {
145         if (offset < ATH11K_PCI_WINDOW_START)
146                 iowrite32(value, ab->mem  + offset);
147         else
148                 ab->pci.ops->window_write32(ab, offset, value);
149 }
150
151 void ath11k_pcic_write32(struct ath11k_base *ab, u32 offset, u32 value)
152 {
153         int ret = 0;
154         bool wakeup_required;
155
156         /* for offset beyond BAR + 4K - 32, may
157          * need to wakeup the device to access.
158          */
159         wakeup_required = test_bit(ATH11K_FLAG_DEVICE_INIT_DONE, &ab->dev_flags) &&
160                           offset >= ATH11K_PCI_ACCESS_ALWAYS_OFF;
161         if (wakeup_required && ab->pci.ops->wakeup)
162                 ret = ab->pci.ops->wakeup(ab);
163
164         __ath11k_pcic_write32(ab, offset, value);
165
166         if (wakeup_required && !ret && ab->pci.ops->release)
167                 ab->pci.ops->release(ab);
168 }
169 EXPORT_SYMBOL(ath11k_pcic_write32);
170
171 static u32 __ath11k_pcic_read32(struct ath11k_base *ab, u32 offset)
172 {
173         u32 val;
174
175         if (offset < ATH11K_PCI_WINDOW_START)
176                 val = ioread32(ab->mem + offset);
177         else
178                 val = ab->pci.ops->window_read32(ab, offset);
179
180         return val;
181 }
182
183 u32 ath11k_pcic_read32(struct ath11k_base *ab, u32 offset)
184 {
185         int ret = 0;
186         u32 val;
187         bool wakeup_required;
188
189         /* for offset beyond BAR + 4K - 32, may
190          * need to wakeup the device to access.
191          */
192         wakeup_required = test_bit(ATH11K_FLAG_DEVICE_INIT_DONE, &ab->dev_flags) &&
193                           offset >= ATH11K_PCI_ACCESS_ALWAYS_OFF;
194         if (wakeup_required && ab->pci.ops->wakeup)
195                 ret = ab->pci.ops->wakeup(ab);
196
197         val = __ath11k_pcic_read32(ab, offset);
198
199         if (wakeup_required && !ret && ab->pci.ops->release)
200                 ab->pci.ops->release(ab);
201
202         return val;
203 }
204 EXPORT_SYMBOL(ath11k_pcic_read32);
205
206 int ath11k_pcic_read(struct ath11k_base *ab, void *buf, u32 start, u32 end)
207 {
208         int ret = 0;
209         bool wakeup_required;
210         u32 *data = buf;
211         u32 i;
212
213         /* for offset beyond BAR + 4K - 32, may
214          * need to wakeup the device to access.
215          */
216         wakeup_required = test_bit(ATH11K_FLAG_DEVICE_INIT_DONE, &ab->dev_flags) &&
217                           end >= ATH11K_PCI_ACCESS_ALWAYS_OFF;
218         if (wakeup_required && ab->pci.ops->wakeup) {
219                 ret = ab->pci.ops->wakeup(ab);
220                 if (ret) {
221                         ath11k_warn(ab,
222                                     "wakeup failed, data may be invalid: %d",
223                                     ret);
224                         /* Even though wakeup() failed, continue processing rather
225                          * than returning because some parts of the data may still
226                          * be valid and useful in some cases, e.g. could give us
227                          * some clues on firmware crash.
228                          * Mislead due to invalid data could be avoided because we
229                          * are aware of the wakeup failure.
230                          */
231                 }
232         }
233
234         for (i = start; i < end + 1; i += 4)
235                 *data++ = __ath11k_pcic_read32(ab, i);
236
237         if (wakeup_required && ab->pci.ops->release)
238                 ab->pci.ops->release(ab);
239
240         return 0;
241 }
242 EXPORT_SYMBOL(ath11k_pcic_read);
243
244 void ath11k_pcic_get_msi_address(struct ath11k_base *ab, u32 *msi_addr_lo,
245                                  u32 *msi_addr_hi)
246 {
247         *msi_addr_lo = ab->pci.msi.addr_lo;
248         *msi_addr_hi = ab->pci.msi.addr_hi;
249 }
250 EXPORT_SYMBOL(ath11k_pcic_get_msi_address);
251
252 int ath11k_pcic_get_user_msi_assignment(struct ath11k_base *ab, char *user_name,
253                                         int *num_vectors, u32 *user_base_data,
254                                         u32 *base_vector)
255 {
256         const struct ath11k_msi_config *msi_config = ab->pci.msi.config;
257         int idx;
258
259         for (idx = 0; idx < msi_config->total_users; idx++) {
260                 if (strcmp(user_name, msi_config->users[idx].name) == 0) {
261                         *num_vectors = msi_config->users[idx].num_vectors;
262                         *base_vector =  msi_config->users[idx].base_vector;
263                         *user_base_data = *base_vector + ab->pci.msi.ep_base_data;
264
265                         ath11k_dbg(ab, ATH11K_DBG_PCI,
266                                    "Assign MSI to user: %s, num_vectors: %d, user_base_data: %u, base_vector: %u\n",
267                                    user_name, *num_vectors, *user_base_data,
268                                    *base_vector);
269
270                         return 0;
271                 }
272         }
273
274         ath11k_err(ab, "Failed to find MSI assignment for %s!\n", user_name);
275
276         return -EINVAL;
277 }
278 EXPORT_SYMBOL(ath11k_pcic_get_user_msi_assignment);
279
280 void ath11k_pcic_get_ce_msi_idx(struct ath11k_base *ab, u32 ce_id, u32 *msi_idx)
281 {
282         u32 i, msi_data_idx;
283
284         for (i = 0, msi_data_idx = 0; i < ab->hw_params.ce_count; i++) {
285                 if (ath11k_ce_get_attr_flags(ab, i) & CE_ATTR_DIS_INTR)
286                         continue;
287
288                 if (ce_id == i)
289                         break;
290
291                 msi_data_idx++;
292         }
293         *msi_idx = msi_data_idx;
294 }
295 EXPORT_SYMBOL(ath11k_pcic_get_ce_msi_idx);
296
297 static void ath11k_pcic_free_ext_irq(struct ath11k_base *ab)
298 {
299         int i, j;
300
301         for (i = 0; i < ATH11K_EXT_IRQ_GRP_NUM_MAX; i++) {
302                 struct ath11k_ext_irq_grp *irq_grp = &ab->ext_irq_grp[i];
303
304                 for (j = 0; j < irq_grp->num_irq; j++)
305                         free_irq(ab->irq_num[irq_grp->irqs[j]], irq_grp);
306
307                 netif_napi_del(&irq_grp->napi);
308         }
309 }
310
311 void ath11k_pcic_free_irq(struct ath11k_base *ab)
312 {
313         int i, irq_idx;
314
315         for (i = 0; i < ab->hw_params.ce_count; i++) {
316                 if (ath11k_ce_get_attr_flags(ab, i) & CE_ATTR_DIS_INTR)
317                         continue;
318                 irq_idx = ATH11K_PCI_IRQ_CE0_OFFSET + i;
319                 free_irq(ab->irq_num[irq_idx], &ab->ce.ce_pipe[i]);
320         }
321
322         ath11k_pcic_free_ext_irq(ab);
323 }
324 EXPORT_SYMBOL(ath11k_pcic_free_irq);
325
326 static void ath11k_pcic_ce_irq_enable(struct ath11k_base *ab, u16 ce_id)
327 {
328         u32 irq_idx;
329
330         /* In case of one MSI vector, we handle irq enable/disable in a
331          * uniform way since we only have one irq
332          */
333         if (!test_bit(ATH11K_FLAG_MULTI_MSI_VECTORS, &ab->dev_flags))
334                 return;
335
336         irq_idx = ATH11K_PCI_IRQ_CE0_OFFSET + ce_id;
337         enable_irq(ab->irq_num[irq_idx]);
338 }
339
340 static void ath11k_pcic_ce_irq_disable(struct ath11k_base *ab, u16 ce_id)
341 {
342         u32 irq_idx;
343
344         /* In case of one MSI vector, we handle irq enable/disable in a
345          * uniform way since we only have one irq
346          */
347         if (!test_bit(ATH11K_FLAG_MULTI_MSI_VECTORS, &ab->dev_flags))
348                 return;
349
350         irq_idx = ATH11K_PCI_IRQ_CE0_OFFSET + ce_id;
351         disable_irq_nosync(ab->irq_num[irq_idx]);
352 }
353
354 static void ath11k_pcic_ce_irqs_disable(struct ath11k_base *ab)
355 {
356         int i;
357
358         clear_bit(ATH11K_FLAG_CE_IRQ_ENABLED, &ab->dev_flags);
359
360         for (i = 0; i < ab->hw_params.ce_count; i++) {
361                 if (ath11k_ce_get_attr_flags(ab, i) & CE_ATTR_DIS_INTR)
362                         continue;
363                 ath11k_pcic_ce_irq_disable(ab, i);
364         }
365 }
366
367 static void ath11k_pcic_sync_ce_irqs(struct ath11k_base *ab)
368 {
369         int i;
370         int irq_idx;
371
372         for (i = 0; i < ab->hw_params.ce_count; i++) {
373                 if (ath11k_ce_get_attr_flags(ab, i) & CE_ATTR_DIS_INTR)
374                         continue;
375
376                 irq_idx = ATH11K_PCI_IRQ_CE0_OFFSET + i;
377                 synchronize_irq(ab->irq_num[irq_idx]);
378         }
379 }
380
381 static void ath11k_pcic_ce_tasklet(struct tasklet_struct *t)
382 {
383         struct ath11k_ce_pipe *ce_pipe = from_tasklet(ce_pipe, t, intr_tq);
384         int irq_idx = ATH11K_PCI_IRQ_CE0_OFFSET + ce_pipe->pipe_num;
385
386         ath11k_ce_per_engine_service(ce_pipe->ab, ce_pipe->pipe_num);
387
388         enable_irq(ce_pipe->ab->irq_num[irq_idx]);
389 }
390
391 static irqreturn_t ath11k_pcic_ce_interrupt_handler(int irq, void *arg)
392 {
393         struct ath11k_ce_pipe *ce_pipe = arg;
394         struct ath11k_base *ab = ce_pipe->ab;
395         int irq_idx = ATH11K_PCI_IRQ_CE0_OFFSET + ce_pipe->pipe_num;
396
397         if (!test_bit(ATH11K_FLAG_CE_IRQ_ENABLED, &ab->dev_flags))
398                 return IRQ_HANDLED;
399
400         /* last interrupt received for this CE */
401         ce_pipe->timestamp = jiffies;
402
403         disable_irq_nosync(ab->irq_num[irq_idx]);
404
405         tasklet_schedule(&ce_pipe->intr_tq);
406
407         return IRQ_HANDLED;
408 }
409
410 static void ath11k_pcic_ext_grp_disable(struct ath11k_ext_irq_grp *irq_grp)
411 {
412         struct ath11k_base *ab = irq_grp->ab;
413         int i;
414
415         /* In case of one MSI vector, we handle irq enable/disable
416          * in a uniform way since we only have one irq
417          */
418         if (!test_bit(ATH11K_FLAG_MULTI_MSI_VECTORS, &ab->dev_flags))
419                 return;
420
421         for (i = 0; i < irq_grp->num_irq; i++)
422                 disable_irq_nosync(irq_grp->ab->irq_num[irq_grp->irqs[i]]);
423 }
424
425 static void __ath11k_pcic_ext_irq_disable(struct ath11k_base *sc)
426 {
427         int i;
428
429         clear_bit(ATH11K_FLAG_EXT_IRQ_ENABLED, &sc->dev_flags);
430
431         for (i = 0; i < ATH11K_EXT_IRQ_GRP_NUM_MAX; i++) {
432                 struct ath11k_ext_irq_grp *irq_grp = &sc->ext_irq_grp[i];
433
434                 ath11k_pcic_ext_grp_disable(irq_grp);
435
436                 if (irq_grp->napi_enabled) {
437                         napi_synchronize(&irq_grp->napi);
438                         napi_disable(&irq_grp->napi);
439                         irq_grp->napi_enabled = false;
440                 }
441         }
442 }
443
444 static void ath11k_pcic_ext_grp_enable(struct ath11k_ext_irq_grp *irq_grp)
445 {
446         struct ath11k_base *ab = irq_grp->ab;
447         int i;
448
449         /* In case of one MSI vector, we handle irq enable/disable in a
450          * uniform way since we only have one irq
451          */
452         if (!test_bit(ATH11K_FLAG_MULTI_MSI_VECTORS, &ab->dev_flags))
453                 return;
454
455         for (i = 0; i < irq_grp->num_irq; i++)
456                 enable_irq(irq_grp->ab->irq_num[irq_grp->irqs[i]]);
457 }
458
459 void ath11k_pcic_ext_irq_enable(struct ath11k_base *ab)
460 {
461         int i;
462
463         set_bit(ATH11K_FLAG_EXT_IRQ_ENABLED, &ab->dev_flags);
464
465         for (i = 0; i < ATH11K_EXT_IRQ_GRP_NUM_MAX; i++) {
466                 struct ath11k_ext_irq_grp *irq_grp = &ab->ext_irq_grp[i];
467
468                 if (!irq_grp->napi_enabled) {
469                         dev_set_threaded(&irq_grp->napi_ndev, true);
470                         napi_enable(&irq_grp->napi);
471                         irq_grp->napi_enabled = true;
472                 }
473                 ath11k_pcic_ext_grp_enable(irq_grp);
474         }
475 }
476 EXPORT_SYMBOL(ath11k_pcic_ext_irq_enable);
477
478 static void ath11k_pcic_sync_ext_irqs(struct ath11k_base *ab)
479 {
480         int i, j, irq_idx;
481
482         for (i = 0; i < ATH11K_EXT_IRQ_GRP_NUM_MAX; i++) {
483                 struct ath11k_ext_irq_grp *irq_grp = &ab->ext_irq_grp[i];
484
485                 for (j = 0; j < irq_grp->num_irq; j++) {
486                         irq_idx = irq_grp->irqs[j];
487                         synchronize_irq(ab->irq_num[irq_idx]);
488                 }
489         }
490 }
491
492 void ath11k_pcic_ext_irq_disable(struct ath11k_base *ab)
493 {
494         __ath11k_pcic_ext_irq_disable(ab);
495         ath11k_pcic_sync_ext_irqs(ab);
496 }
497 EXPORT_SYMBOL(ath11k_pcic_ext_irq_disable);
498
499 static int ath11k_pcic_ext_grp_napi_poll(struct napi_struct *napi, int budget)
500 {
501         struct ath11k_ext_irq_grp *irq_grp = container_of(napi,
502                                                 struct ath11k_ext_irq_grp,
503                                                 napi);
504         struct ath11k_base *ab = irq_grp->ab;
505         int work_done;
506         int i;
507
508         work_done = ath11k_dp_service_srng(ab, irq_grp, budget);
509         if (work_done < budget) {
510                 napi_complete_done(napi, work_done);
511                 for (i = 0; i < irq_grp->num_irq; i++)
512                         enable_irq(irq_grp->ab->irq_num[irq_grp->irqs[i]]);
513         }
514
515         if (work_done > budget)
516                 work_done = budget;
517
518         return work_done;
519 }
520
521 static irqreturn_t ath11k_pcic_ext_interrupt_handler(int irq, void *arg)
522 {
523         struct ath11k_ext_irq_grp *irq_grp = arg;
524         struct ath11k_base *ab = irq_grp->ab;
525         int i;
526
527         if (!test_bit(ATH11K_FLAG_EXT_IRQ_ENABLED, &ab->dev_flags))
528                 return IRQ_HANDLED;
529
530         ath11k_dbg(irq_grp->ab, ATH11K_DBG_PCI, "ext irq:%d\n", irq);
531
532         /* last interrupt received for this group */
533         irq_grp->timestamp = jiffies;
534
535         for (i = 0; i < irq_grp->num_irq; i++)
536                 disable_irq_nosync(irq_grp->ab->irq_num[irq_grp->irqs[i]]);
537
538         napi_schedule(&irq_grp->napi);
539
540         return IRQ_HANDLED;
541 }
542
543 static int
544 ath11k_pcic_get_msi_irq(struct ath11k_base *ab, unsigned int vector)
545 {
546         return ab->pci.ops->get_msi_irq(ab, vector);
547 }
548
549 static int ath11k_pcic_ext_irq_config(struct ath11k_base *ab)
550 {
551         int i, j, ret, num_vectors = 0;
552         u32 user_base_data = 0, base_vector = 0;
553         unsigned long irq_flags;
554
555         ret = ath11k_pcic_get_user_msi_assignment(ab, "DP", &num_vectors,
556                                                   &user_base_data,
557                                                   &base_vector);
558         if (ret < 0)
559                 return ret;
560
561         irq_flags = IRQF_SHARED;
562         if (!test_bit(ATH11K_FLAG_MULTI_MSI_VECTORS, &ab->dev_flags))
563                 irq_flags |= IRQF_NOBALANCING;
564
565         for (i = 0; i < ATH11K_EXT_IRQ_GRP_NUM_MAX; i++) {
566                 struct ath11k_ext_irq_grp *irq_grp = &ab->ext_irq_grp[i];
567                 u32 num_irq = 0;
568
569                 irq_grp->ab = ab;
570                 irq_grp->grp_id = i;
571                 init_dummy_netdev(&irq_grp->napi_ndev);
572                 netif_napi_add(&irq_grp->napi_ndev, &irq_grp->napi,
573                                ath11k_pcic_ext_grp_napi_poll);
574
575                 if (ab->hw_params.ring_mask->tx[i] ||
576                     ab->hw_params.ring_mask->rx[i] ||
577                     ab->hw_params.ring_mask->rx_err[i] ||
578                     ab->hw_params.ring_mask->rx_wbm_rel[i] ||
579                     ab->hw_params.ring_mask->reo_status[i] ||
580                     ab->hw_params.ring_mask->rxdma2host[i] ||
581                     ab->hw_params.ring_mask->host2rxdma[i] ||
582                     ab->hw_params.ring_mask->rx_mon_status[i]) {
583                         num_irq = 1;
584                 }
585
586                 irq_grp->num_irq = num_irq;
587                 irq_grp->irqs[0] = ATH11K_PCI_IRQ_DP_OFFSET + i;
588
589                 for (j = 0; j < irq_grp->num_irq; j++) {
590                         int irq_idx = irq_grp->irqs[j];
591                         int vector = (i % num_vectors) + base_vector;
592                         int irq = ath11k_pcic_get_msi_irq(ab, vector);
593
594                         if (irq < 0)
595                                 return irq;
596
597                         ab->irq_num[irq_idx] = irq;
598
599                         ath11k_dbg(ab, ATH11K_DBG_PCI,
600                                    "irq:%d group:%d\n", irq, i);
601
602                         irq_set_status_flags(irq, IRQ_DISABLE_UNLAZY);
603                         ret = request_irq(irq, ath11k_pcic_ext_interrupt_handler,
604                                           irq_flags, "DP_EXT_IRQ", irq_grp);
605                         if (ret) {
606                                 ath11k_err(ab, "failed request irq %d: %d\n",
607                                            vector, ret);
608                                 return ret;
609                         }
610                 }
611                 ath11k_pcic_ext_grp_disable(irq_grp);
612         }
613
614         return 0;
615 }
616
617 int ath11k_pcic_config_irq(struct ath11k_base *ab)
618 {
619         struct ath11k_ce_pipe *ce_pipe;
620         u32 msi_data_start;
621         u32 msi_data_count, msi_data_idx;
622         u32 msi_irq_start;
623         unsigned int msi_data;
624         int irq, i, ret, irq_idx;
625         unsigned long irq_flags;
626
627         ret = ath11k_pcic_get_user_msi_assignment(ab, "CE", &msi_data_count,
628                                                   &msi_data_start, &msi_irq_start);
629         if (ret)
630                 return ret;
631
632         irq_flags = IRQF_SHARED;
633         if (!test_bit(ATH11K_FLAG_MULTI_MSI_VECTORS, &ab->dev_flags))
634                 irq_flags |= IRQF_NOBALANCING;
635
636         /* Configure CE irqs */
637         for (i = 0, msi_data_idx = 0; i < ab->hw_params.ce_count; i++) {
638                 if (ath11k_ce_get_attr_flags(ab, i) & CE_ATTR_DIS_INTR)
639                         continue;
640
641                 msi_data = (msi_data_idx % msi_data_count) + msi_irq_start;
642                 irq = ath11k_pcic_get_msi_irq(ab, msi_data);
643                 if (irq < 0)
644                         return irq;
645
646                 ce_pipe = &ab->ce.ce_pipe[i];
647
648                 irq_idx = ATH11K_PCI_IRQ_CE0_OFFSET + i;
649
650                 tasklet_setup(&ce_pipe->intr_tq, ath11k_pcic_ce_tasklet);
651
652                 ret = request_irq(irq, ath11k_pcic_ce_interrupt_handler,
653                                   irq_flags, irq_name[irq_idx], ce_pipe);
654                 if (ret) {
655                         ath11k_err(ab, "failed to request irq %d: %d\n",
656                                    irq_idx, ret);
657                         return ret;
658                 }
659
660                 ab->irq_num[irq_idx] = irq;
661                 msi_data_idx++;
662
663                 ath11k_pcic_ce_irq_disable(ab, i);
664         }
665
666         ret = ath11k_pcic_ext_irq_config(ab);
667         if (ret)
668                 return ret;
669
670         return 0;
671 }
672 EXPORT_SYMBOL(ath11k_pcic_config_irq);
673
674 void ath11k_pcic_ce_irqs_enable(struct ath11k_base *ab)
675 {
676         int i;
677
678         set_bit(ATH11K_FLAG_CE_IRQ_ENABLED, &ab->dev_flags);
679
680         for (i = 0; i < ab->hw_params.ce_count; i++) {
681                 if (ath11k_ce_get_attr_flags(ab, i) & CE_ATTR_DIS_INTR)
682                         continue;
683                 ath11k_pcic_ce_irq_enable(ab, i);
684         }
685 }
686 EXPORT_SYMBOL(ath11k_pcic_ce_irqs_enable);
687
688 static void ath11k_pcic_kill_tasklets(struct ath11k_base *ab)
689 {
690         int i;
691
692         for (i = 0; i < ab->hw_params.ce_count; i++) {
693                 struct ath11k_ce_pipe *ce_pipe = &ab->ce.ce_pipe[i];
694
695                 if (ath11k_ce_get_attr_flags(ab, i) & CE_ATTR_DIS_INTR)
696                         continue;
697
698                 tasklet_kill(&ce_pipe->intr_tq);
699         }
700 }
701
702 void ath11k_pcic_ce_irq_disable_sync(struct ath11k_base *ab)
703 {
704         ath11k_pcic_ce_irqs_disable(ab);
705         ath11k_pcic_sync_ce_irqs(ab);
706         ath11k_pcic_kill_tasklets(ab);
707 }
708 EXPORT_SYMBOL(ath11k_pcic_ce_irq_disable_sync);
709
710 void ath11k_pcic_stop(struct ath11k_base *ab)
711 {
712         ath11k_pcic_ce_irq_disable_sync(ab);
713         ath11k_ce_cleanup_pipes(ab);
714 }
715 EXPORT_SYMBOL(ath11k_pcic_stop);
716
717 int ath11k_pcic_start(struct ath11k_base *ab)
718 {
719         set_bit(ATH11K_FLAG_DEVICE_INIT_DONE, &ab->dev_flags);
720
721         ath11k_pcic_ce_irqs_enable(ab);
722         ath11k_ce_rx_post_buf(ab);
723
724         return 0;
725 }
726 EXPORT_SYMBOL(ath11k_pcic_start);
727
728 int ath11k_pcic_map_service_to_pipe(struct ath11k_base *ab, u16 service_id,
729                                     u8 *ul_pipe, u8 *dl_pipe)
730 {
731         const struct service_to_pipe *entry;
732         bool ul_set = false, dl_set = false;
733         int i;
734
735         for (i = 0; i < ab->hw_params.svc_to_ce_map_len; i++) {
736                 entry = &ab->hw_params.svc_to_ce_map[i];
737
738                 if (__le32_to_cpu(entry->service_id) != service_id)
739                         continue;
740
741                 switch (__le32_to_cpu(entry->pipedir)) {
742                 case PIPEDIR_NONE:
743                         break;
744                 case PIPEDIR_IN:
745                         WARN_ON(dl_set);
746                         *dl_pipe = __le32_to_cpu(entry->pipenum);
747                         dl_set = true;
748                         break;
749                 case PIPEDIR_OUT:
750                         WARN_ON(ul_set);
751                         *ul_pipe = __le32_to_cpu(entry->pipenum);
752                         ul_set = true;
753                         break;
754                 case PIPEDIR_INOUT:
755                         WARN_ON(dl_set);
756                         WARN_ON(ul_set);
757                         *dl_pipe = __le32_to_cpu(entry->pipenum);
758                         *ul_pipe = __le32_to_cpu(entry->pipenum);
759                         dl_set = true;
760                         ul_set = true;
761                         break;
762                 }
763         }
764
765         if (WARN_ON(!ul_set || !dl_set))
766                 return -ENOENT;
767
768         return 0;
769 }
770 EXPORT_SYMBOL(ath11k_pcic_map_service_to_pipe);
771
772 int ath11k_pcic_register_pci_ops(struct ath11k_base *ab,
773                                  const struct ath11k_pci_ops *pci_ops)
774 {
775         if (!pci_ops)
776                 return 0;
777
778         /* Return error if mandatory pci_ops callbacks are missing */
779         if (!pci_ops->get_msi_irq || !pci_ops->window_write32 ||
780             !pci_ops->window_read32)
781                 return -EINVAL;
782
783         ab->pci.ops = pci_ops;
784         return 0;
785 }
786 EXPORT_SYMBOL(ath11k_pcic_register_pci_ops);
787
788 void ath11k_pci_enable_ce_irqs_except_wake_irq(struct ath11k_base *ab)
789 {
790         int i;
791
792         for (i = 0; i < ab->hw_params.ce_count; i++) {
793                 if (ath11k_ce_get_attr_flags(ab, i) & CE_ATTR_DIS_INTR ||
794                     i == ATH11K_PCI_CE_WAKE_IRQ)
795                         continue;
796                 ath11k_pcic_ce_irq_enable(ab, i);
797         }
798 }
799 EXPORT_SYMBOL(ath11k_pci_enable_ce_irqs_except_wake_irq);
800
801 void ath11k_pci_disable_ce_irqs_except_wake_irq(struct ath11k_base *ab)
802 {
803         int i;
804         int irq_idx;
805         struct ath11k_ce_pipe *ce_pipe;
806
807         for (i = 0; i < ab->hw_params.ce_count; i++) {
808                 ce_pipe = &ab->ce.ce_pipe[i];
809                 irq_idx = ATH11K_PCI_IRQ_CE0_OFFSET + i;
810
811                 if (ath11k_ce_get_attr_flags(ab, i) & CE_ATTR_DIS_INTR ||
812                     i == ATH11K_PCI_CE_WAKE_IRQ)
813                         continue;
814
815                 disable_irq_nosync(ab->irq_num[irq_idx]);
816                 synchronize_irq(ab->irq_num[irq_idx]);
817                 tasklet_kill(&ce_pipe->intr_tq);
818         }
819 }
820 EXPORT_SYMBOL(ath11k_pci_disable_ce_irqs_except_wake_irq);