1 /*
2  * Copyright (c) 2012-2014 Qualcomm Atheros, Inc.
3  *
4  * Permission to use, copy, modify, and/or distribute this software for any
5  * purpose with or without fee is hereby granted, provided that the above
6  * copyright notice and this permission notice appear in all copies.
7  *
8  * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
9  * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
10  * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
11  * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
12  * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
13  * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
14  * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
15  */
16 
17 #include <linux/interrupt.h>
18 
19 #include "wil6210.h"
20 #include "trace.h"
21 
22 /**
23  * Theory of operation:
24  *
25  * There is ISR pseudo-cause register,
26  * dma_rgf->DMA_RGF.PSEUDO_CAUSE.PSEUDO_CAUSE
27  * Its bits represents OR'ed bits from 3 real ISR registers:
28  * TX, RX, and MISC.
29  *
30  * Registers may be configured to either "write 1 to clear" or
31  * "clear on read" mode
32  *
33  * When handling interrupt, one have to mask/unmask interrupts for the
34  * real ISR registers, or hardware may malfunction.
35  *
36  */
37 
38 #define WIL6210_IRQ_DISABLE	(0xFFFFFFFFUL)
39 #define WIL6210_IMC_RX		(BIT_DMA_EP_RX_ICR_RX_DONE | \
40 				 BIT_DMA_EP_RX_ICR_RX_HTRSH)
41 #define WIL6210_IMC_TX		(BIT_DMA_EP_TX_ICR_TX_DONE | \
42 				BIT_DMA_EP_TX_ICR_TX_DONE_N(0))
43 #define WIL6210_IMC_MISC	(ISR_MISC_FW_READY | \
44 				 ISR_MISC_MBOX_EVT | \
45 				 ISR_MISC_FW_ERROR)
46 
47 #define WIL6210_IRQ_PSEUDO_MASK (u32)(~(BIT_DMA_PSEUDO_CAUSE_RX | \
48 					BIT_DMA_PSEUDO_CAUSE_TX | \
49 					BIT_DMA_PSEUDO_CAUSE_MISC))
50 
51 #if defined(CONFIG_WIL6210_ISR_COR)
52 /* configure to Clear-On-Read mode */
53 #define WIL_ICR_ICC_VALUE	(0xFFFFFFFFUL)
54 
55 static inline void wil_icr_clear(u32 x, void __iomem *addr)
56 {
57 }
58 #else /* defined(CONFIG_WIL6210_ISR_COR) */
59 /* configure to Write-1-to-Clear mode */
60 #define WIL_ICR_ICC_VALUE	(0UL)
61 
62 static inline void wil_icr_clear(u32 x, void __iomem *addr)
63 {
64 	iowrite32(x, addr);
65 }
66 #endif /* defined(CONFIG_WIL6210_ISR_COR) */
67 
68 static inline u32 wil_ioread32_and_clear(void __iomem *addr)
69 {
70 	u32 x = ioread32(addr);
71 
72 	wil_icr_clear(x, addr);
73 
74 	return x;
75 }
76 
77 static void wil6210_mask_irq_tx(struct wil6210_priv *wil)
78 {
79 	iowrite32(WIL6210_IRQ_DISABLE, wil->csr +
80 		  HOSTADDR(RGF_DMA_EP_TX_ICR) +
81 		  offsetof(struct RGF_ICR, IMS));
82 }
83 
84 static void wil6210_mask_irq_rx(struct wil6210_priv *wil)
85 {
86 	iowrite32(WIL6210_IRQ_DISABLE, wil->csr +
87 		  HOSTADDR(RGF_DMA_EP_RX_ICR) +
88 		  offsetof(struct RGF_ICR, IMS));
89 }
90 
91 static void wil6210_mask_irq_misc(struct wil6210_priv *wil)
92 {
93 	iowrite32(WIL6210_IRQ_DISABLE, wil->csr +
94 		  HOSTADDR(RGF_DMA_EP_MISC_ICR) +
95 		  offsetof(struct RGF_ICR, IMS));
96 }
97 
98 static void wil6210_mask_irq_pseudo(struct wil6210_priv *wil)
99 {
100 	wil_dbg_irq(wil, "%s()\n", __func__);
101 
102 	iowrite32(WIL6210_IRQ_DISABLE, wil->csr +
103 		  HOSTADDR(RGF_DMA_PSEUDO_CAUSE_MASK_SW));
104 
105 	clear_bit(wil_status_irqen, &wil->status);
106 }
107 
108 void wil6210_unmask_irq_tx(struct wil6210_priv *wil)
109 {
110 	iowrite32(WIL6210_IMC_TX, wil->csr +
111 		  HOSTADDR(RGF_DMA_EP_TX_ICR) +
112 		  offsetof(struct RGF_ICR, IMC));
113 }
114 
115 void wil6210_unmask_irq_rx(struct wil6210_priv *wil)
116 {
117 	iowrite32(WIL6210_IMC_RX, wil->csr +
118 		  HOSTADDR(RGF_DMA_EP_RX_ICR) +
119 		  offsetof(struct RGF_ICR, IMC));
120 }
121 
122 static void wil6210_unmask_irq_misc(struct wil6210_priv *wil)
123 {
124 	iowrite32(WIL6210_IMC_MISC, wil->csr +
125 		  HOSTADDR(RGF_DMA_EP_MISC_ICR) +
126 		  offsetof(struct RGF_ICR, IMC));
127 }
128 
129 static void wil6210_unmask_irq_pseudo(struct wil6210_priv *wil)
130 {
131 	wil_dbg_irq(wil, "%s()\n", __func__);
132 
133 	set_bit(wil_status_irqen, &wil->status);
134 
135 	iowrite32(WIL6210_IRQ_PSEUDO_MASK, wil->csr +
136 		  HOSTADDR(RGF_DMA_PSEUDO_CAUSE_MASK_SW));
137 }
138 
139 void wil_mask_irq(struct wil6210_priv *wil)
140 {
141 	wil_dbg_irq(wil, "%s()\n", __func__);
142 
143 	wil6210_mask_irq_tx(wil);
144 	wil6210_mask_irq_rx(wil);
145 	wil6210_mask_irq_misc(wil);
146 	wil6210_mask_irq_pseudo(wil);
147 }
148 
149 void wil_unmask_irq(struct wil6210_priv *wil)
150 {
151 	wil_dbg_irq(wil, "%s()\n", __func__);
152 
153 	iowrite32(WIL_ICR_ICC_VALUE, wil->csr + HOSTADDR(RGF_DMA_EP_RX_ICR) +
154 		  offsetof(struct RGF_ICR, ICC));
155 	iowrite32(WIL_ICR_ICC_VALUE, wil->csr + HOSTADDR(RGF_DMA_EP_TX_ICR) +
156 		  offsetof(struct RGF_ICR, ICC));
157 	iowrite32(WIL_ICR_ICC_VALUE, wil->csr + HOSTADDR(RGF_DMA_EP_MISC_ICR) +
158 		  offsetof(struct RGF_ICR, ICC));
159 
160 	/* interrupt moderation parameters */
161 	wil_set_itr_trsh(wil);
162 
163 	wil6210_unmask_irq_pseudo(wil);
164 	wil6210_unmask_irq_tx(wil);
165 	wil6210_unmask_irq_rx(wil);
166 	wil6210_unmask_irq_misc(wil);
167 }
168 
169 static irqreturn_t wil6210_irq_rx(int irq, void *cookie)
170 {
171 	struct wil6210_priv *wil = cookie;
172 	u32 isr = wil_ioread32_and_clear(wil->csr +
173 					 HOSTADDR(RGF_DMA_EP_RX_ICR) +
174 					 offsetof(struct RGF_ICR, ICR));
175 	bool need_unmask = true;
176 
177 	trace_wil6210_irq_rx(isr);
178 	wil_dbg_irq(wil, "ISR RX 0x%08x\n", isr);
179 
180 	if (!isr) {
181 		wil_err(wil, "spurious IRQ: RX\n");
182 		return IRQ_NONE;
183 	}
184 
185 	wil6210_mask_irq_rx(wil);
186 
187 	/* RX_DONE and RX_HTRSH interrupts are the same if interrupt
188 	 * moderation is not used. Interrupt moderation may cause RX
189 	 * buffer overflow while RX_DONE is delayed. The required
190 	 * action is always the same - should empty the accumulated
191 	 * packets from the RX ring.
192 	 */
193 	if (isr & (BIT_DMA_EP_RX_ICR_RX_DONE | BIT_DMA_EP_RX_ICR_RX_HTRSH)) {
194 		wil_dbg_irq(wil, "RX done\n");
195 
196 		if (isr & BIT_DMA_EP_RX_ICR_RX_HTRSH)
197 			wil_err_ratelimited(wil, "Received \"Rx buffer is in risk "
198 				"of overflow\" interrupt\n");
199 
200 		isr &= ~(BIT_DMA_EP_RX_ICR_RX_DONE | BIT_DMA_EP_RX_ICR_RX_HTRSH);
201 		if (test_bit(wil_status_reset_done, &wil->status)) {
202 			if (test_bit(wil_status_napi_en, &wil->status)) {
203 				wil_dbg_txrx(wil, "NAPI(Rx) schedule\n");
204 				need_unmask = false;
205 				napi_schedule(&wil->napi_rx);
206 			} else {
207 				wil_err(wil, "Got Rx interrupt while "
208 					"stopping interface\n");
209 			}
210 		} else {
211 			wil_err(wil, "Got Rx interrupt while in reset\n");
212 		}
213 	}
214 
215 	if (isr)
216 		wil_err(wil, "un-handled RX ISR bits 0x%08x\n", isr);
217 
218 	/* Rx IRQ will be enabled when NAPI processing finished */
219 
220 	atomic_inc(&wil->isr_count_rx);
221 
222 	if (unlikely(need_unmask))
223 		wil6210_unmask_irq_rx(wil);
224 
225 	return IRQ_HANDLED;
226 }
227 
228 static irqreturn_t wil6210_irq_tx(int irq, void *cookie)
229 {
230 	struct wil6210_priv *wil = cookie;
231 	u32 isr = wil_ioread32_and_clear(wil->csr +
232 					 HOSTADDR(RGF_DMA_EP_TX_ICR) +
233 					 offsetof(struct RGF_ICR, ICR));
234 	bool need_unmask = true;
235 
236 	trace_wil6210_irq_tx(isr);
237 	wil_dbg_irq(wil, "ISR TX 0x%08x\n", isr);
238 
239 	if (!isr) {
240 		wil_err(wil, "spurious IRQ: TX\n");
241 		return IRQ_NONE;
242 	}
243 
244 	wil6210_mask_irq_tx(wil);
245 
246 	if (isr & BIT_DMA_EP_TX_ICR_TX_DONE) {
247 		wil_dbg_irq(wil, "TX done\n");
248 		isr &= ~BIT_DMA_EP_TX_ICR_TX_DONE;
249 		/* clear also all VRING interrupts */
250 		isr &= ~(BIT(25) - 1UL);
251 		if (test_bit(wil_status_reset_done, &wil->status)) {
252 			wil_dbg_txrx(wil, "NAPI(Tx) schedule\n");
253 			need_unmask = false;
254 			napi_schedule(&wil->napi_tx);
255 		} else {
256 			wil_err(wil, "Got Tx interrupt while in reset\n");
257 		}
258 	}
259 
260 	if (isr)
261 		wil_err(wil, "un-handled TX ISR bits 0x%08x\n", isr);
262 
263 	/* Tx IRQ will be enabled when NAPI processing finished */
264 
265 	atomic_inc(&wil->isr_count_tx);
266 
267 	if (unlikely(need_unmask))
268 		wil6210_unmask_irq_tx(wil);
269 
270 	return IRQ_HANDLED;
271 }
272 
273 static void wil_notify_fw_error(struct wil6210_priv *wil)
274 {
275 	struct device *dev = &wil_to_ndev(wil)->dev;
276 	char *envp[3] = {
277 		[0] = "SOURCE=wil6210",
278 		[1] = "EVENT=FW_ERROR",
279 		[2] = NULL,
280 	};
281 	wil_err(wil, "Notify about firmware error\n");
282 	kobject_uevent_env(&dev->kobj, KOBJ_CHANGE, envp);
283 }
284 
285 static void wil_cache_mbox_regs(struct wil6210_priv *wil)
286 {
287 	/* make shadow copy of registers that should not change on run time */
288 	wil_memcpy_fromio_32(&wil->mbox_ctl, wil->csr + HOST_MBOX,
289 			     sizeof(struct wil6210_mbox_ctl));
290 	wil_mbox_ring_le2cpus(&wil->mbox_ctl.rx);
291 	wil_mbox_ring_le2cpus(&wil->mbox_ctl.tx);
292 }
293 
294 static irqreturn_t wil6210_irq_misc(int irq, void *cookie)
295 {
296 	struct wil6210_priv *wil = cookie;
297 	u32 isr = wil_ioread32_and_clear(wil->csr +
298 					 HOSTADDR(RGF_DMA_EP_MISC_ICR) +
299 					 offsetof(struct RGF_ICR, ICR));
300 
301 	trace_wil6210_irq_misc(isr);
302 	wil_dbg_irq(wil, "ISR MISC 0x%08x\n", isr);
303 
304 	if (!isr) {
305 		wil_err(wil, "spurious IRQ: MISC\n");
306 		return IRQ_NONE;
307 	}
308 
309 	wil6210_mask_irq_misc(wil);
310 
311 	if (isr & ISR_MISC_FW_ERROR) {
312 		wil_err(wil, "Firmware error detected\n");
313 		clear_bit(wil_status_fwready, &wil->status);
314 		/*
315 		 * do not clear @isr here - we do 2-nd part in thread
316 		 * there, user space get notified, and it should be done
317 		 * in non-atomic context
318 		 */
319 	}
320 
321 	if (isr & ISR_MISC_FW_READY) {
322 		wil_dbg_irq(wil, "IRQ: FW ready\n");
323 		wil_cache_mbox_regs(wil);
324 		set_bit(wil_status_reset_done, &wil->status);
325 		/**
326 		 * Actual FW ready indicated by the
327 		 * WMI_FW_READY_EVENTID
328 		 */
329 		isr &= ~ISR_MISC_FW_READY;
330 	}
331 
332 	wil->isr_misc = isr;
333 
334 	if (isr) {
335 		return IRQ_WAKE_THREAD;
336 	} else {
337 		wil6210_unmask_irq_misc(wil);
338 		return IRQ_HANDLED;
339 	}
340 }
341 
342 static irqreturn_t wil6210_irq_misc_thread(int irq, void *cookie)
343 {
344 	struct wil6210_priv *wil = cookie;
345 	u32 isr = wil->isr_misc;
346 
347 	trace_wil6210_irq_misc_thread(isr);
348 	wil_dbg_irq(wil, "Thread ISR MISC 0x%08x\n", isr);
349 
350 	if (isr & ISR_MISC_FW_ERROR) {
351 		wil_notify_fw_error(wil);
352 		isr &= ~ISR_MISC_FW_ERROR;
353 		wil_fw_error_recovery(wil);
354 	}
355 
356 	if (isr & ISR_MISC_MBOX_EVT) {
357 		wil_dbg_irq(wil, "MBOX event\n");
358 		wmi_recv_cmd(wil);
359 		isr &= ~ISR_MISC_MBOX_EVT;
360 	}
361 
362 	if (isr)
363 		wil_dbg_irq(wil, "un-handled MISC ISR bits 0x%08x\n", isr);
364 
365 	wil->isr_misc = 0;
366 
367 	wil6210_unmask_irq_misc(wil);
368 
369 	return IRQ_HANDLED;
370 }
371 
372 /**
373  * thread IRQ handler
374  */
375 static irqreturn_t wil6210_thread_irq(int irq, void *cookie)
376 {
377 	struct wil6210_priv *wil = cookie;
378 
379 	wil_dbg_irq(wil, "Thread IRQ\n");
380 	/* Discover real IRQ cause */
381 	if (wil->isr_misc)
382 		wil6210_irq_misc_thread(irq, cookie);
383 
384 	wil6210_unmask_irq_pseudo(wil);
385 
386 	return IRQ_HANDLED;
387 }
388 
389 /* DEBUG
390  * There is subtle bug in hardware that causes IRQ to raise when it should be
391  * masked. It is quite rare and hard to debug.
392  *
393  * Catch irq issue if it happens and print all I can.
394  */
395 static int wil6210_debug_irq_mask(struct wil6210_priv *wil, u32 pseudo_cause)
396 {
397 	if (!test_bit(wil_status_irqen, &wil->status)) {
398 		u32 icm_rx = wil_ioread32_and_clear(wil->csr +
399 				HOSTADDR(RGF_DMA_EP_RX_ICR) +
400 				offsetof(struct RGF_ICR, ICM));
401 		u32 icr_rx = wil_ioread32_and_clear(wil->csr +
402 				HOSTADDR(RGF_DMA_EP_RX_ICR) +
403 				offsetof(struct RGF_ICR, ICR));
404 		u32 imv_rx = ioread32(wil->csr +
405 				HOSTADDR(RGF_DMA_EP_RX_ICR) +
406 				offsetof(struct RGF_ICR, IMV));
407 		u32 icm_tx = wil_ioread32_and_clear(wil->csr +
408 				HOSTADDR(RGF_DMA_EP_TX_ICR) +
409 				offsetof(struct RGF_ICR, ICM));
410 		u32 icr_tx = wil_ioread32_and_clear(wil->csr +
411 				HOSTADDR(RGF_DMA_EP_TX_ICR) +
412 				offsetof(struct RGF_ICR, ICR));
413 		u32 imv_tx = ioread32(wil->csr +
414 				HOSTADDR(RGF_DMA_EP_TX_ICR) +
415 				offsetof(struct RGF_ICR, IMV));
416 		u32 icm_misc = wil_ioread32_and_clear(wil->csr +
417 				HOSTADDR(RGF_DMA_EP_MISC_ICR) +
418 				offsetof(struct RGF_ICR, ICM));
419 		u32 icr_misc = wil_ioread32_and_clear(wil->csr +
420 				HOSTADDR(RGF_DMA_EP_MISC_ICR) +
421 				offsetof(struct RGF_ICR, ICR));
422 		u32 imv_misc = ioread32(wil->csr +
423 				HOSTADDR(RGF_DMA_EP_MISC_ICR) +
424 				offsetof(struct RGF_ICR, IMV));
425 		wil_err(wil, "IRQ when it should be masked: pseudo 0x%08x\n"
426 				"Rx   icm:icr:imv 0x%08x 0x%08x 0x%08x\n"
427 				"Tx   icm:icr:imv 0x%08x 0x%08x 0x%08x\n"
428 				"Misc icm:icr:imv 0x%08x 0x%08x 0x%08x\n",
429 				pseudo_cause,
430 				icm_rx, icr_rx, imv_rx,
431 				icm_tx, icr_tx, imv_tx,
432 				icm_misc, icr_misc, imv_misc);
433 
434 		return -EINVAL;
435 	}
436 
437 	return 0;
438 }
439 
440 static irqreturn_t wil6210_hardirq(int irq, void *cookie)
441 {
442 	irqreturn_t rc = IRQ_HANDLED;
443 	struct wil6210_priv *wil = cookie;
444 	u32 pseudo_cause = ioread32(wil->csr + HOSTADDR(RGF_DMA_PSEUDO_CAUSE));
445 
446 	/**
447 	 * pseudo_cause is Clear-On-Read, no need to ACK
448 	 */
449 	if ((pseudo_cause == 0) || ((pseudo_cause & 0xff) == 0xff))
450 		return IRQ_NONE;
451 
452 	/* FIXME: IRQ mask debug */
453 	if (wil6210_debug_irq_mask(wil, pseudo_cause))
454 		return IRQ_NONE;
455 
456 	trace_wil6210_irq_pseudo(pseudo_cause);
457 	wil_dbg_irq(wil, "Pseudo IRQ 0x%08x\n", pseudo_cause);
458 
459 	wil6210_mask_irq_pseudo(wil);
460 
461 	/* Discover real IRQ cause
462 	 * There are 2 possible phases for every IRQ:
463 	 * - hard IRQ handler called right here
464 	 * - threaded handler called later
465 	 *
466 	 * Hard IRQ handler reads and clears ISR.
467 	 *
468 	 * If threaded handler requested, hard IRQ handler
469 	 * returns IRQ_WAKE_THREAD and saves ISR register value
470 	 * for the threaded handler use.
471 	 *
472 	 * voting for wake thread - need at least 1 vote
473 	 */
474 	if ((pseudo_cause & BIT_DMA_PSEUDO_CAUSE_RX) &&
475 	    (wil6210_irq_rx(irq, cookie) == IRQ_WAKE_THREAD))
476 		rc = IRQ_WAKE_THREAD;
477 
478 	if ((pseudo_cause & BIT_DMA_PSEUDO_CAUSE_TX) &&
479 	    (wil6210_irq_tx(irq, cookie) == IRQ_WAKE_THREAD))
480 		rc = IRQ_WAKE_THREAD;
481 
482 	if ((pseudo_cause & BIT_DMA_PSEUDO_CAUSE_MISC) &&
483 	    (wil6210_irq_misc(irq, cookie) == IRQ_WAKE_THREAD))
484 		rc = IRQ_WAKE_THREAD;
485 
486 	/* if thread is requested, it will unmask IRQ */
487 	if (rc != IRQ_WAKE_THREAD)
488 		wil6210_unmask_irq_pseudo(wil);
489 
490 	return rc;
491 }
492 
493 static int wil6210_request_3msi(struct wil6210_priv *wil, int irq)
494 {
495 	int rc;
496 	/*
497 	 * IRQ's are in the following order:
498 	 * - Tx
499 	 * - Rx
500 	 * - Misc
501 	 */
502 
503 	rc = request_irq(irq, wil6210_irq_tx, IRQF_SHARED,
504 			 WIL_NAME"_tx", wil);
505 	if (rc)
506 		return rc;
507 
508 	rc = request_irq(irq + 1, wil6210_irq_rx, IRQF_SHARED,
509 			 WIL_NAME"_rx", wil);
510 	if (rc)
511 		goto free0;
512 
513 	rc = request_threaded_irq(irq + 2, wil6210_irq_misc,
514 				  wil6210_irq_misc_thread,
515 				  IRQF_SHARED, WIL_NAME"_misc", wil);
516 	if (rc)
517 		goto free1;
518 
519 	return 0;
520 	/* error branch */
521 free1:
522 	free_irq(irq + 1, wil);
523 free0:
524 	free_irq(irq, wil);
525 
526 	return rc;
527 }
528 
529 /* can't use wil_ioread32_and_clear because ICC value is not set yet */
530 static inline void wil_clear32(void __iomem *addr)
531 {
532 	u32 x = ioread32(addr);
533 
534 	iowrite32(x, addr);
535 }
536 
537 void wil6210_clear_irq(struct wil6210_priv *wil)
538 {
539 	wil_clear32(wil->csr + HOSTADDR(RGF_DMA_EP_RX_ICR) +
540 		    offsetof(struct RGF_ICR, ICR));
541 	wil_clear32(wil->csr + HOSTADDR(RGF_DMA_EP_TX_ICR) +
542 		    offsetof(struct RGF_ICR, ICR));
543 	wil_clear32(wil->csr + HOSTADDR(RGF_DMA_EP_MISC_ICR) +
544 		    offsetof(struct RGF_ICR, ICR));
545 	wmb(); /* make sure write completed */
546 }
547 
548 int wil6210_init_irq(struct wil6210_priv *wil, int irq)
549 {
550 	int rc;
551 
552 	wil_dbg_misc(wil, "%s() n_msi=%d\n", __func__, wil->n_msi);
553 
554 	if (wil->n_msi == 3)
555 		rc = wil6210_request_3msi(wil, irq);
556 	else
557 		rc = request_threaded_irq(irq, wil6210_hardirq,
558 					  wil6210_thread_irq,
559 					  wil->n_msi ? 0 : IRQF_SHARED,
560 					  WIL_NAME, wil);
561 	return rc;
562 }
563 
564 void wil6210_fini_irq(struct wil6210_priv *wil, int irq)
565 {
566 	wil_dbg_misc(wil, "%s()\n", __func__);
567 
568 	wil_mask_irq(wil);
569 	free_irq(irq, wil);
570 	if (wil->n_msi == 3) {
571 		free_irq(irq + 1, wil);
572 		free_irq(irq + 2, wil);
573 	}
574 }
575