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