]> Git Repo - J-linux.git/blob - drivers/net/wireless/ath/wil6210/interrupt.c
Merge tag 'kbuild-v6.9' of git://git.kernel.org/pub/scm/linux/kernel/git/masahiroy...
[J-linux.git] / drivers / net / wireless / ath / wil6210 / interrupt.c
1 // SPDX-License-Identifier: ISC
2 /*
3  * Copyright (c) 2012-2017 Qualcomm Atheros, Inc.
4  * Copyright (c) 2018-2019, The Linux Foundation. All rights reserved.
5  */
6
7 #include <linux/interrupt.h>
8
9 #include "wil6210.h"
10 #include "trace.h"
11
12 /*
13  * Theory of operation:
14  *
15  * There is ISR pseudo-cause register,
16  * dma_rgf->DMA_RGF.PSEUDO_CAUSE.PSEUDO_CAUSE
17  * Its bits represents OR'ed bits from 3 real ISR registers:
18  * TX, RX, and MISC.
19  *
20  * Registers may be configured to either "write 1 to clear" or
21  * "clear on read" mode
22  *
23  * When handling interrupt, one have to mask/unmask interrupts for the
24  * real ISR registers, or hardware may malfunction.
25  *
26  */
27
28 #define WIL6210_IRQ_DISABLE             (0xFFFFFFFFUL)
29 #define WIL6210_IRQ_DISABLE_NO_HALP     (0xF7FFFFFFUL)
30 #define WIL6210_IMC_RX          (BIT_DMA_EP_RX_ICR_RX_DONE | \
31                                  BIT_DMA_EP_RX_ICR_RX_HTRSH)
32 #define WIL6210_IMC_RX_NO_RX_HTRSH (WIL6210_IMC_RX & \
33                                     (~(BIT_DMA_EP_RX_ICR_RX_HTRSH)))
34 #define WIL6210_IMC_TX          (BIT_DMA_EP_TX_ICR_TX_DONE | \
35                                 BIT_DMA_EP_TX_ICR_TX_DONE_N(0))
36 #define WIL6210_IMC_TX_EDMA             BIT_TX_STATUS_IRQ
37 #define WIL6210_IMC_RX_EDMA             BIT_RX_STATUS_IRQ
38 #define WIL6210_IMC_MISC_NO_HALP        (ISR_MISC_FW_READY | \
39                                          ISR_MISC_MBOX_EVT | \
40                                          ISR_MISC_FW_ERROR)
41 #define WIL6210_IMC_MISC                (WIL6210_IMC_MISC_NO_HALP | \
42                                          BIT_DMA_EP_MISC_ICR_HALP)
43 #define WIL6210_IRQ_PSEUDO_MASK (u32)(~(BIT_DMA_PSEUDO_CAUSE_RX | \
44                                         BIT_DMA_PSEUDO_CAUSE_TX | \
45                                         BIT_DMA_PSEUDO_CAUSE_MISC))
46
47 #if defined(CONFIG_WIL6210_ISR_COR)
48 /* configure to Clear-On-Read mode */
49 #define WIL_ICR_ICC_VALUE       (0xFFFFFFFFUL)
50 #define WIL_ICR_ICC_MISC_VALUE  (0xF7FFFFFFUL)
51
52 static inline void wil_icr_clear(u32 x, void __iomem *addr)
53 {
54 }
55 #else /* defined(CONFIG_WIL6210_ISR_COR) */
56 /* configure to Write-1-to-Clear mode */
57 #define WIL_ICR_ICC_VALUE       (0UL)
58 #define WIL_ICR_ICC_MISC_VALUE  (0UL)
59
60 static inline void wil_icr_clear(u32 x, void __iomem *addr)
61 {
62         writel(x, addr);
63 }
64 #endif /* defined(CONFIG_WIL6210_ISR_COR) */
65
66 static inline u32 wil_ioread32_and_clear(void __iomem *addr)
67 {
68         u32 x = readl(addr);
69
70         wil_icr_clear(x, addr);
71
72         return x;
73 }
74
75 static void wil6210_mask_irq_tx(struct wil6210_priv *wil)
76 {
77         wil_w(wil, RGF_DMA_EP_TX_ICR + offsetof(struct RGF_ICR, IMS),
78               WIL6210_IRQ_DISABLE);
79 }
80
81 static void wil6210_mask_irq_tx_edma(struct wil6210_priv *wil)
82 {
83         wil_w(wil, RGF_INT_GEN_TX_ICR + offsetof(struct RGF_ICR, IMS),
84               WIL6210_IRQ_DISABLE);
85 }
86
87 static void wil6210_mask_irq_rx(struct wil6210_priv *wil)
88 {
89         wil_w(wil, RGF_DMA_EP_RX_ICR + offsetof(struct RGF_ICR, IMS),
90               WIL6210_IRQ_DISABLE);
91 }
92
93 static void wil6210_mask_irq_rx_edma(struct wil6210_priv *wil)
94 {
95         wil_w(wil, RGF_INT_GEN_RX_ICR + offsetof(struct RGF_ICR, IMS),
96               WIL6210_IRQ_DISABLE);
97 }
98
99 static void wil6210_mask_irq_misc(struct wil6210_priv *wil, bool mask_halp)
100 {
101         wil_dbg_irq(wil, "mask_irq_misc: mask_halp(%s)\n",
102                     mask_halp ? "true" : "false");
103
104         wil_w(wil, RGF_DMA_EP_MISC_ICR + offsetof(struct RGF_ICR, IMS),
105               mask_halp ? WIL6210_IRQ_DISABLE : WIL6210_IRQ_DISABLE_NO_HALP);
106 }
107
108 void wil6210_mask_halp(struct wil6210_priv *wil)
109 {
110         wil_dbg_irq(wil, "mask_halp\n");
111
112         wil_w(wil, RGF_DMA_EP_MISC_ICR + offsetof(struct RGF_ICR, IMS),
113               BIT_DMA_EP_MISC_ICR_HALP);
114 }
115
116 static void wil6210_mask_irq_pseudo(struct wil6210_priv *wil)
117 {
118         wil_dbg_irq(wil, "mask_irq_pseudo\n");
119
120         wil_w(wil, RGF_DMA_PSEUDO_CAUSE_MASK_SW, WIL6210_IRQ_DISABLE);
121
122         clear_bit(wil_status_irqen, wil->status);
123 }
124
125 void wil6210_unmask_irq_tx(struct wil6210_priv *wil)
126 {
127         wil_w(wil, RGF_DMA_EP_TX_ICR + offsetof(struct RGF_ICR, IMC),
128               WIL6210_IMC_TX);
129 }
130
131 void wil6210_unmask_irq_tx_edma(struct wil6210_priv *wil)
132 {
133         wil_w(wil, RGF_INT_GEN_TX_ICR + offsetof(struct RGF_ICR, IMC),
134               WIL6210_IMC_TX_EDMA);
135 }
136
137 void wil6210_unmask_irq_rx(struct wil6210_priv *wil)
138 {
139         bool unmask_rx_htrsh = atomic_read(&wil->connected_vifs) > 0;
140
141         wil_w(wil, RGF_DMA_EP_RX_ICR + offsetof(struct RGF_ICR, IMC),
142               unmask_rx_htrsh ? WIL6210_IMC_RX : WIL6210_IMC_RX_NO_RX_HTRSH);
143 }
144
145 void wil6210_unmask_irq_rx_edma(struct wil6210_priv *wil)
146 {
147         wil_w(wil, RGF_INT_GEN_RX_ICR + offsetof(struct RGF_ICR, IMC),
148               WIL6210_IMC_RX_EDMA);
149 }
150
151 static void wil6210_unmask_irq_misc(struct wil6210_priv *wil, bool unmask_halp)
152 {
153         wil_dbg_irq(wil, "unmask_irq_misc: unmask_halp(%s)\n",
154                     unmask_halp ? "true" : "false");
155
156         wil_w(wil, RGF_DMA_EP_MISC_ICR + offsetof(struct RGF_ICR, IMC),
157               unmask_halp ? WIL6210_IMC_MISC : WIL6210_IMC_MISC_NO_HALP);
158 }
159
160 static void wil6210_unmask_halp(struct wil6210_priv *wil)
161 {
162         wil_dbg_irq(wil, "unmask_halp\n");
163
164         wil_w(wil, RGF_DMA_EP_MISC_ICR + offsetof(struct RGF_ICR, IMC),
165               BIT_DMA_EP_MISC_ICR_HALP);
166 }
167
168 static void wil6210_unmask_irq_pseudo(struct wil6210_priv *wil)
169 {
170         wil_dbg_irq(wil, "unmask_irq_pseudo\n");
171
172         set_bit(wil_status_irqen, wil->status);
173
174         wil_w(wil, RGF_DMA_PSEUDO_CAUSE_MASK_SW, WIL6210_IRQ_PSEUDO_MASK);
175 }
176
177 void wil_mask_irq(struct wil6210_priv *wil)
178 {
179         wil_dbg_irq(wil, "mask_irq\n");
180
181         wil6210_mask_irq_tx(wil);
182         wil6210_mask_irq_tx_edma(wil);
183         wil6210_mask_irq_rx(wil);
184         wil6210_mask_irq_rx_edma(wil);
185         wil6210_mask_irq_misc(wil, true);
186         wil6210_mask_irq_pseudo(wil);
187 }
188
189 void wil_unmask_irq(struct wil6210_priv *wil)
190 {
191         wil_dbg_irq(wil, "unmask_irq\n");
192
193         wil_w(wil, RGF_DMA_EP_RX_ICR + offsetof(struct RGF_ICR, ICC),
194               WIL_ICR_ICC_VALUE);
195         wil_w(wil, RGF_DMA_EP_TX_ICR + offsetof(struct RGF_ICR, ICC),
196               WIL_ICR_ICC_VALUE);
197         wil_w(wil, RGF_DMA_EP_MISC_ICR + offsetof(struct RGF_ICR, ICC),
198               WIL_ICR_ICC_MISC_VALUE);
199         wil_w(wil, RGF_INT_GEN_TX_ICR + offsetof(struct RGF_ICR, ICC),
200               WIL_ICR_ICC_VALUE);
201         wil_w(wil, RGF_INT_GEN_RX_ICR + offsetof(struct RGF_ICR, ICC),
202               WIL_ICR_ICC_VALUE);
203
204         wil6210_unmask_irq_pseudo(wil);
205         if (wil->use_enhanced_dma_hw) {
206                 wil6210_unmask_irq_tx_edma(wil);
207                 wil6210_unmask_irq_rx_edma(wil);
208         } else {
209                 wil6210_unmask_irq_tx(wil);
210                 wil6210_unmask_irq_rx(wil);
211         }
212         wil6210_unmask_irq_misc(wil, true);
213 }
214
215 void wil_configure_interrupt_moderation_edma(struct wil6210_priv *wil)
216 {
217         u32 moderation;
218
219         wil_s(wil, RGF_INT_GEN_IDLE_TIME_LIMIT, WIL_EDMA_IDLE_TIME_LIMIT_USEC);
220
221         wil_s(wil, RGF_INT_GEN_TIME_UNIT_LIMIT, WIL_EDMA_TIME_UNIT_CLK_CYCLES);
222
223         /* Update RX and TX moderation */
224         moderation = wil->rx_max_burst_duration |
225                 (WIL_EDMA_AGG_WATERMARK << WIL_EDMA_AGG_WATERMARK_POS);
226         wil_w(wil, RGF_INT_CTRL_INT_GEN_CFG_0, moderation);
227         wil_w(wil, RGF_INT_CTRL_INT_GEN_CFG_1, moderation);
228
229         /* Treat special events as regular
230          * (set bit 0 to 0x1 and clear bits 1-8)
231          */
232         wil_c(wil, RGF_INT_COUNT_ON_SPECIAL_EVT, 0x1FE);
233         wil_s(wil, RGF_INT_COUNT_ON_SPECIAL_EVT, 0x1);
234 }
235
236 void wil_configure_interrupt_moderation(struct wil6210_priv *wil)
237 {
238         struct wireless_dev *wdev = wil->main_ndev->ieee80211_ptr;
239
240         wil_dbg_irq(wil, "configure_interrupt_moderation\n");
241
242         /* disable interrupt moderation for monitor
243          * to get better timestamp precision
244          */
245         if (wdev->iftype == NL80211_IFTYPE_MONITOR)
246                 return;
247
248         /* Disable and clear tx counter before (re)configuration */
249         wil_w(wil, RGF_DMA_ITR_TX_CNT_CTL, BIT_DMA_ITR_TX_CNT_CTL_CLR);
250         wil_w(wil, RGF_DMA_ITR_TX_CNT_TRSH, wil->tx_max_burst_duration);
251         wil_info(wil, "set ITR_TX_CNT_TRSH = %d usec\n",
252                  wil->tx_max_burst_duration);
253         /* Configure TX max burst duration timer to use usec units */
254         wil_w(wil, RGF_DMA_ITR_TX_CNT_CTL,
255               BIT_DMA_ITR_TX_CNT_CTL_EN | BIT_DMA_ITR_TX_CNT_CTL_EXT_TIC_SEL);
256
257         /* Disable and clear tx idle counter before (re)configuration */
258         wil_w(wil, RGF_DMA_ITR_TX_IDL_CNT_CTL, BIT_DMA_ITR_TX_IDL_CNT_CTL_CLR);
259         wil_w(wil, RGF_DMA_ITR_TX_IDL_CNT_TRSH, wil->tx_interframe_timeout);
260         wil_info(wil, "set ITR_TX_IDL_CNT_TRSH = %d usec\n",
261                  wil->tx_interframe_timeout);
262         /* Configure TX max burst duration timer to use usec units */
263         wil_w(wil, RGF_DMA_ITR_TX_IDL_CNT_CTL, BIT_DMA_ITR_TX_IDL_CNT_CTL_EN |
264               BIT_DMA_ITR_TX_IDL_CNT_CTL_EXT_TIC_SEL);
265
266         /* Disable and clear rx counter before (re)configuration */
267         wil_w(wil, RGF_DMA_ITR_RX_CNT_CTL, BIT_DMA_ITR_RX_CNT_CTL_CLR);
268         wil_w(wil, RGF_DMA_ITR_RX_CNT_TRSH, wil->rx_max_burst_duration);
269         wil_info(wil, "set ITR_RX_CNT_TRSH = %d usec\n",
270                  wil->rx_max_burst_duration);
271         /* Configure TX max burst duration timer to use usec units */
272         wil_w(wil, RGF_DMA_ITR_RX_CNT_CTL,
273               BIT_DMA_ITR_RX_CNT_CTL_EN | BIT_DMA_ITR_RX_CNT_CTL_EXT_TIC_SEL);
274
275         /* Disable and clear rx idle counter before (re)configuration */
276         wil_w(wil, RGF_DMA_ITR_RX_IDL_CNT_CTL, BIT_DMA_ITR_RX_IDL_CNT_CTL_CLR);
277         wil_w(wil, RGF_DMA_ITR_RX_IDL_CNT_TRSH, wil->rx_interframe_timeout);
278         wil_info(wil, "set ITR_RX_IDL_CNT_TRSH = %d usec\n",
279                  wil->rx_interframe_timeout);
280         /* Configure TX max burst duration timer to use usec units */
281         wil_w(wil, RGF_DMA_ITR_RX_IDL_CNT_CTL, BIT_DMA_ITR_RX_IDL_CNT_CTL_EN |
282               BIT_DMA_ITR_RX_IDL_CNT_CTL_EXT_TIC_SEL);
283 }
284
285 static irqreturn_t wil6210_irq_rx(int irq, void *cookie)
286 {
287         struct wil6210_priv *wil = cookie;
288         u32 isr;
289         bool need_unmask = true;
290
291         wil6210_mask_irq_rx(wil);
292
293         isr = wil_ioread32_and_clear(wil->csr +
294                                      HOSTADDR(RGF_DMA_EP_RX_ICR) +
295                                      offsetof(struct RGF_ICR, ICR));
296
297         trace_wil6210_irq_rx(isr);
298         wil_dbg_irq(wil, "ISR RX 0x%08x\n", isr);
299
300         if (unlikely(!isr)) {
301                 wil_err_ratelimited(wil, "spurious IRQ: RX\n");
302                 wil6210_unmask_irq_rx(wil);
303                 return IRQ_NONE;
304         }
305
306         /* RX_DONE and RX_HTRSH interrupts are the same if interrupt
307          * moderation is not used. Interrupt moderation may cause RX
308          * buffer overflow while RX_DONE is delayed. The required
309          * action is always the same - should empty the accumulated
310          * packets from the RX ring.
311          */
312         if (likely(isr & (BIT_DMA_EP_RX_ICR_RX_DONE |
313                           BIT_DMA_EP_RX_ICR_RX_HTRSH))) {
314                 wil_dbg_irq(wil, "RX done / RX_HTRSH received, ISR (0x%x)\n",
315                             isr);
316
317                 isr &= ~(BIT_DMA_EP_RX_ICR_RX_DONE |
318                          BIT_DMA_EP_RX_ICR_RX_HTRSH);
319                 if (likely(test_bit(wil_status_fwready, wil->status))) {
320                         if (likely(test_bit(wil_status_napi_en, wil->status))) {
321                                 wil_dbg_txrx(wil, "NAPI(Rx) schedule\n");
322                                 need_unmask = false;
323                                 napi_schedule(&wil->napi_rx);
324                         } else {
325                                 wil_err_ratelimited(
326                                         wil,
327                                         "Got Rx interrupt while stopping interface\n");
328                         }
329                 } else {
330                         wil_err_ratelimited(wil, "Got Rx interrupt while in reset\n");
331                 }
332         }
333
334         if (unlikely(isr))
335                 wil_err(wil, "un-handled RX ISR bits 0x%08x\n", isr);
336
337         /* Rx IRQ will be enabled when NAPI processing finished */
338
339         atomic_inc(&wil->isr_count_rx);
340
341         if (unlikely(need_unmask))
342                 wil6210_unmask_irq_rx(wil);
343
344         return IRQ_HANDLED;
345 }
346
347 static irqreturn_t wil6210_irq_rx_edma(int irq, void *cookie)
348 {
349         struct wil6210_priv *wil = cookie;
350         u32 isr;
351         bool need_unmask = true;
352
353         wil6210_mask_irq_rx_edma(wil);
354
355         isr = wil_ioread32_and_clear(wil->csr +
356                                      HOSTADDR(RGF_INT_GEN_RX_ICR) +
357                                      offsetof(struct RGF_ICR, ICR));
358
359         trace_wil6210_irq_rx(isr);
360         wil_dbg_irq(wil, "ISR RX 0x%08x\n", isr);
361
362         if (unlikely(!isr)) {
363                 wil_err(wil, "spurious IRQ: RX\n");
364                 wil6210_unmask_irq_rx_edma(wil);
365                 return IRQ_NONE;
366         }
367
368         if (likely(isr & BIT_RX_STATUS_IRQ)) {
369                 wil_dbg_irq(wil, "RX status ring\n");
370                 isr &= ~BIT_RX_STATUS_IRQ;
371                 if (likely(test_bit(wil_status_fwready, wil->status))) {
372                         if (likely(test_bit(wil_status_napi_en, wil->status))) {
373                                 wil_dbg_txrx(wil, "NAPI(Rx) schedule\n");
374                                 need_unmask = false;
375                                 napi_schedule(&wil->napi_rx);
376                         } else {
377                                 wil_err(wil,
378                                         "Got Rx interrupt while stopping interface\n");
379                         }
380                 } else {
381                         wil_err(wil, "Got Rx interrupt while in reset\n");
382                 }
383         }
384
385         if (unlikely(isr))
386                 wil_err(wil, "un-handled RX ISR bits 0x%08x\n", isr);
387
388         /* Rx IRQ will be enabled when NAPI processing finished */
389
390         atomic_inc(&wil->isr_count_rx);
391
392         if (unlikely(need_unmask))
393                 wil6210_unmask_irq_rx_edma(wil);
394
395         return IRQ_HANDLED;
396 }
397
398 static irqreturn_t wil6210_irq_tx_edma(int irq, void *cookie)
399 {
400         struct wil6210_priv *wil = cookie;
401         u32 isr;
402         bool need_unmask = true;
403
404         wil6210_mask_irq_tx_edma(wil);
405
406         isr = wil_ioread32_and_clear(wil->csr +
407                                      HOSTADDR(RGF_INT_GEN_TX_ICR) +
408                                      offsetof(struct RGF_ICR, ICR));
409
410         trace_wil6210_irq_tx(isr);
411         wil_dbg_irq(wil, "ISR TX 0x%08x\n", isr);
412
413         if (unlikely(!isr)) {
414                 wil_err(wil, "spurious IRQ: TX\n");
415                 wil6210_unmask_irq_tx_edma(wil);
416                 return IRQ_NONE;
417         }
418
419         if (likely(isr & BIT_TX_STATUS_IRQ)) {
420                 wil_dbg_irq(wil, "TX status ring\n");
421                 isr &= ~BIT_TX_STATUS_IRQ;
422                 if (likely(test_bit(wil_status_fwready, wil->status))) {
423                         wil_dbg_txrx(wil, "NAPI(Tx) schedule\n");
424                         need_unmask = false;
425                         napi_schedule(&wil->napi_tx);
426                 } else {
427                         wil_err(wil, "Got Tx status ring IRQ while in reset\n");
428                 }
429         }
430
431         if (unlikely(isr))
432                 wil_err(wil, "un-handled TX ISR bits 0x%08x\n", isr);
433
434         /* Tx IRQ will be enabled when NAPI processing finished */
435
436         atomic_inc(&wil->isr_count_tx);
437
438         if (unlikely(need_unmask))
439                 wil6210_unmask_irq_tx_edma(wil);
440
441         return IRQ_HANDLED;
442 }
443
444 static irqreturn_t wil6210_irq_tx(int irq, void *cookie)
445 {
446         struct wil6210_priv *wil = cookie;
447         u32 isr;
448         bool need_unmask = true;
449
450         wil6210_mask_irq_tx(wil);
451
452         isr = wil_ioread32_and_clear(wil->csr +
453                                      HOSTADDR(RGF_DMA_EP_TX_ICR) +
454                                      offsetof(struct RGF_ICR, ICR));
455
456         trace_wil6210_irq_tx(isr);
457         wil_dbg_irq(wil, "ISR TX 0x%08x\n", isr);
458
459         if (unlikely(!isr)) {
460                 wil_err_ratelimited(wil, "spurious IRQ: TX\n");
461                 wil6210_unmask_irq_tx(wil);
462                 return IRQ_NONE;
463         }
464
465         if (likely(isr & BIT_DMA_EP_TX_ICR_TX_DONE)) {
466                 wil_dbg_irq(wil, "TX done\n");
467                 isr &= ~BIT_DMA_EP_TX_ICR_TX_DONE;
468                 /* clear also all VRING interrupts */
469                 isr &= ~(BIT(25) - 1UL);
470                 if (likely(test_bit(wil_status_fwready, wil->status))) {
471                         wil_dbg_txrx(wil, "NAPI(Tx) schedule\n");
472                         need_unmask = false;
473                         napi_schedule(&wil->napi_tx);
474                 } else {
475                         wil_err_ratelimited(wil, "Got Tx interrupt while in reset\n");
476                 }
477         }
478
479         if (unlikely(isr))
480                 wil_err_ratelimited(wil, "un-handled TX ISR bits 0x%08x\n",
481                                     isr);
482
483         /* Tx IRQ will be enabled when NAPI processing finished */
484
485         atomic_inc(&wil->isr_count_tx);
486
487         if (unlikely(need_unmask))
488                 wil6210_unmask_irq_tx(wil);
489
490         return IRQ_HANDLED;
491 }
492
493 static void wil_notify_fw_error(struct wil6210_priv *wil)
494 {
495         struct device *dev = &wil->main_ndev->dev;
496         char *envp[3] = {
497                 [0] = "SOURCE=wil6210",
498                 [1] = "EVENT=FW_ERROR",
499                 [2] = NULL,
500         };
501         wil_err(wil, "Notify about firmware error\n");
502         kobject_uevent_env(&dev->kobj, KOBJ_CHANGE, envp);
503 }
504
505 static void wil_cache_mbox_regs(struct wil6210_priv *wil)
506 {
507         /* make shadow copy of registers that should not change on run time */
508         wil_memcpy_fromio_32(&wil->mbox_ctl, wil->csr + HOST_MBOX,
509                              sizeof(struct wil6210_mbox_ctl));
510         wil_mbox_ring_le2cpus(&wil->mbox_ctl.rx);
511         wil_mbox_ring_le2cpus(&wil->mbox_ctl.tx);
512 }
513
514 static bool wil_validate_mbox_regs(struct wil6210_priv *wil)
515 {
516         size_t min_size = sizeof(struct wil6210_mbox_hdr) +
517                 sizeof(struct wmi_cmd_hdr);
518
519         if (wil->mbox_ctl.rx.entry_size < min_size) {
520                 wil_err(wil, "rx mbox entry too small (%d)\n",
521                         wil->mbox_ctl.rx.entry_size);
522                 return false;
523         }
524         if (wil->mbox_ctl.tx.entry_size < min_size) {
525                 wil_err(wil, "tx mbox entry too small (%d)\n",
526                         wil->mbox_ctl.tx.entry_size);
527                 return false;
528         }
529
530         return true;
531 }
532
533 static irqreturn_t wil6210_irq_misc(int irq, void *cookie)
534 {
535         struct wil6210_priv *wil = cookie;
536         u32 isr;
537
538         wil6210_mask_irq_misc(wil, false);
539
540         isr = wil_ioread32_and_clear(wil->csr +
541                                      HOSTADDR(RGF_DMA_EP_MISC_ICR) +
542                                      offsetof(struct RGF_ICR, ICR));
543
544         trace_wil6210_irq_misc(isr);
545         wil_dbg_irq(wil, "ISR MISC 0x%08x\n", isr);
546
547         if (!isr) {
548                 wil_err(wil, "spurious IRQ: MISC\n");
549                 wil6210_unmask_irq_misc(wil, false);
550                 return IRQ_NONE;
551         }
552
553         if (isr & ISR_MISC_FW_ERROR) {
554                 u32 fw_assert_code = wil_r(wil, wil->rgf_fw_assert_code_addr);
555                 u32 ucode_assert_code =
556                         wil_r(wil, wil->rgf_ucode_assert_code_addr);
557
558                 wil_err(wil,
559                         "Firmware error detected, assert codes FW 0x%08x, UCODE 0x%08x\n",
560                         fw_assert_code, ucode_assert_code);
561                 clear_bit(wil_status_fwready, wil->status);
562                 /*
563                  * do not clear @isr here - we do 2-nd part in thread
564                  * there, user space get notified, and it should be done
565                  * in non-atomic context
566                  */
567         }
568
569         if (isr & ISR_MISC_FW_READY) {
570                 wil_dbg_irq(wil, "IRQ: FW ready\n");
571                 wil_cache_mbox_regs(wil);
572                 if (wil_validate_mbox_regs(wil))
573                         set_bit(wil_status_mbox_ready, wil->status);
574                 /**
575                  * Actual FW ready indicated by the
576                  * WMI_FW_READY_EVENTID
577                  */
578                 isr &= ~ISR_MISC_FW_READY;
579         }
580
581         if (isr & BIT_DMA_EP_MISC_ICR_HALP) {
582                 isr &= ~BIT_DMA_EP_MISC_ICR_HALP;
583                 if (wil->halp.handle_icr) {
584                         /* no need to handle HALP ICRs until next vote */
585                         wil->halp.handle_icr = false;
586                         wil_dbg_irq(wil, "irq_misc: HALP IRQ invoked\n");
587                         wil6210_mask_irq_misc(wil, true);
588                         complete(&wil->halp.comp);
589                 }
590         }
591
592         wil->isr_misc = isr;
593
594         if (isr) {
595                 return IRQ_WAKE_THREAD;
596         } else {
597                 wil6210_unmask_irq_misc(wil, false);
598                 return IRQ_HANDLED;
599         }
600 }
601
602 static irqreturn_t wil6210_irq_misc_thread(int irq, void *cookie)
603 {
604         struct wil6210_priv *wil = cookie;
605         u32 isr = wil->isr_misc;
606
607         trace_wil6210_irq_misc_thread(isr);
608         wil_dbg_irq(wil, "Thread ISR MISC 0x%08x\n", isr);
609
610         if (isr & ISR_MISC_FW_ERROR) {
611                 wil->recovery_state = fw_recovery_pending;
612                 wil_fw_core_dump(wil);
613                 wil_notify_fw_error(wil);
614                 isr &= ~ISR_MISC_FW_ERROR;
615                 if (wil->platform_ops.notify) {
616                         wil_err(wil, "notify platform driver about FW crash");
617                         wil->platform_ops.notify(wil->platform_handle,
618                                                  WIL_PLATFORM_EVT_FW_CRASH);
619                 } else {
620                         wil_fw_error_recovery(wil);
621                 }
622         }
623         if (isr & ISR_MISC_MBOX_EVT) {
624                 wil_dbg_irq(wil, "MBOX event\n");
625                 wmi_recv_cmd(wil);
626                 isr &= ~ISR_MISC_MBOX_EVT;
627         }
628
629         if (isr)
630                 wil_dbg_irq(wil, "un-handled MISC ISR bits 0x%08x\n", isr);
631
632         wil->isr_misc = 0;
633
634         wil6210_unmask_irq_misc(wil, false);
635
636         /* in non-triple MSI case, this is done inside wil6210_thread_irq
637          * because it has to be done after unmasking the pseudo.
638          */
639         if (wil->n_msi == 3 && wil->suspend_resp_rcvd) {
640                 wil_dbg_irq(wil, "set suspend_resp_comp to true\n");
641                 wil->suspend_resp_comp = true;
642                 wake_up_interruptible(&wil->wq);
643         }
644
645         return IRQ_HANDLED;
646 }
647
648 /* thread IRQ handler */
649 static irqreturn_t wil6210_thread_irq(int irq, void *cookie)
650 {
651         struct wil6210_priv *wil = cookie;
652
653         wil_dbg_irq(wil, "Thread IRQ\n");
654         /* Discover real IRQ cause */
655         if (wil->isr_misc)
656                 wil6210_irq_misc_thread(irq, cookie);
657
658         wil6210_unmask_irq_pseudo(wil);
659
660         if (wil->suspend_resp_rcvd) {
661                 wil_dbg_irq(wil, "set suspend_resp_comp to true\n");
662                 wil->suspend_resp_comp = true;
663                 wake_up_interruptible(&wil->wq);
664         }
665
666         return IRQ_HANDLED;
667 }
668
669 /* DEBUG
670  * There is subtle bug in hardware that causes IRQ to raise when it should be
671  * masked. It is quite rare and hard to debug.
672  *
673  * Catch irq issue if it happens and print all I can.
674  */
675 static int wil6210_debug_irq_mask(struct wil6210_priv *wil, u32 pseudo_cause)
676 {
677         u32 icm_rx, icr_rx, imv_rx;
678         u32 icm_tx, icr_tx, imv_tx;
679         u32 icm_misc, icr_misc, imv_misc;
680
681         if (!test_bit(wil_status_irqen, wil->status)) {
682                 if (wil->use_enhanced_dma_hw) {
683                         icm_rx = wil_ioread32_and_clear(wil->csr +
684                                         HOSTADDR(RGF_INT_GEN_RX_ICR) +
685                                         offsetof(struct RGF_ICR, ICM));
686                         icr_rx = wil_ioread32_and_clear(wil->csr +
687                                         HOSTADDR(RGF_INT_GEN_RX_ICR) +
688                                         offsetof(struct RGF_ICR, ICR));
689                         imv_rx = wil_r(wil, RGF_INT_GEN_RX_ICR +
690                                    offsetof(struct RGF_ICR, IMV));
691                         icm_tx = wil_ioread32_and_clear(wil->csr +
692                                         HOSTADDR(RGF_INT_GEN_TX_ICR) +
693                                         offsetof(struct RGF_ICR, ICM));
694                         icr_tx = wil_ioread32_and_clear(wil->csr +
695                                         HOSTADDR(RGF_INT_GEN_TX_ICR) +
696                                         offsetof(struct RGF_ICR, ICR));
697                         imv_tx = wil_r(wil, RGF_INT_GEN_TX_ICR +
698                                            offsetof(struct RGF_ICR, IMV));
699                 } else {
700                         icm_rx = wil_ioread32_and_clear(wil->csr +
701                                         HOSTADDR(RGF_DMA_EP_RX_ICR) +
702                                         offsetof(struct RGF_ICR, ICM));
703                         icr_rx = wil_ioread32_and_clear(wil->csr +
704                                         HOSTADDR(RGF_DMA_EP_RX_ICR) +
705                                         offsetof(struct RGF_ICR, ICR));
706                         imv_rx = wil_r(wil, RGF_DMA_EP_RX_ICR +
707                                    offsetof(struct RGF_ICR, IMV));
708                         icm_tx = wil_ioread32_and_clear(wil->csr +
709                                         HOSTADDR(RGF_DMA_EP_TX_ICR) +
710                                         offsetof(struct RGF_ICR, ICM));
711                         icr_tx = wil_ioread32_and_clear(wil->csr +
712                                         HOSTADDR(RGF_DMA_EP_TX_ICR) +
713                                         offsetof(struct RGF_ICR, ICR));
714                         imv_tx = wil_r(wil, RGF_DMA_EP_TX_ICR +
715                                            offsetof(struct RGF_ICR, IMV));
716                 }
717                 icm_misc = wil_ioread32_and_clear(wil->csr +
718                                 HOSTADDR(RGF_DMA_EP_MISC_ICR) +
719                                 offsetof(struct RGF_ICR, ICM));
720                 icr_misc = wil_ioread32_and_clear(wil->csr +
721                                 HOSTADDR(RGF_DMA_EP_MISC_ICR) +
722                                 offsetof(struct RGF_ICR, ICR));
723                 imv_misc = wil_r(wil, RGF_DMA_EP_MISC_ICR +
724                                      offsetof(struct RGF_ICR, IMV));
725
726                 /* HALP interrupt can be unmasked when misc interrupts are
727                  * masked
728                  */
729                 if (icr_misc & BIT_DMA_EP_MISC_ICR_HALP)
730                         return 0;
731
732                 wil_err(wil, "IRQ when it should be masked: pseudo 0x%08x\n"
733                                 "Rx   icm:icr:imv 0x%08x 0x%08x 0x%08x\n"
734                                 "Tx   icm:icr:imv 0x%08x 0x%08x 0x%08x\n"
735                                 "Misc icm:icr:imv 0x%08x 0x%08x 0x%08x\n",
736                                 pseudo_cause,
737                                 icm_rx, icr_rx, imv_rx,
738                                 icm_tx, icr_tx, imv_tx,
739                                 icm_misc, icr_misc, imv_misc);
740
741                 return -EINVAL;
742         }
743
744         return 0;
745 }
746
747 static irqreturn_t wil6210_hardirq(int irq, void *cookie)
748 {
749         irqreturn_t rc = IRQ_HANDLED;
750         struct wil6210_priv *wil = cookie;
751         u32 pseudo_cause = wil_r(wil, RGF_DMA_PSEUDO_CAUSE);
752
753         /**
754          * pseudo_cause is Clear-On-Read, no need to ACK
755          */
756         if (unlikely((pseudo_cause == 0) || ((pseudo_cause & 0xff) == 0xff)))
757                 return IRQ_NONE;
758
759         /* IRQ mask debug */
760         if (unlikely(wil6210_debug_irq_mask(wil, pseudo_cause)))
761                 return IRQ_NONE;
762
763         trace_wil6210_irq_pseudo(pseudo_cause);
764         wil_dbg_irq(wil, "Pseudo IRQ 0x%08x\n", pseudo_cause);
765
766         wil6210_mask_irq_pseudo(wil);
767
768         /* Discover real IRQ cause
769          * There are 2 possible phases for every IRQ:
770          * - hard IRQ handler called right here
771          * - threaded handler called later
772          *
773          * Hard IRQ handler reads and clears ISR.
774          *
775          * If threaded handler requested, hard IRQ handler
776          * returns IRQ_WAKE_THREAD and saves ISR register value
777          * for the threaded handler use.
778          *
779          * voting for wake thread - need at least 1 vote
780          */
781         if ((pseudo_cause & BIT_DMA_PSEUDO_CAUSE_RX) &&
782             (wil->txrx_ops.irq_rx(irq, cookie) == IRQ_WAKE_THREAD))
783                 rc = IRQ_WAKE_THREAD;
784
785         if ((pseudo_cause & BIT_DMA_PSEUDO_CAUSE_TX) &&
786             (wil->txrx_ops.irq_tx(irq, cookie) == IRQ_WAKE_THREAD))
787                 rc = IRQ_WAKE_THREAD;
788
789         if ((pseudo_cause & BIT_DMA_PSEUDO_CAUSE_MISC) &&
790             (wil6210_irq_misc(irq, cookie) == IRQ_WAKE_THREAD))
791                 rc = IRQ_WAKE_THREAD;
792
793         /* if thread is requested, it will unmask IRQ */
794         if (rc != IRQ_WAKE_THREAD)
795                 wil6210_unmask_irq_pseudo(wil);
796
797         return rc;
798 }
799
800 static int wil6210_request_3msi(struct wil6210_priv *wil, int irq)
801 {
802         int rc;
803
804         /* IRQ's are in the following order:
805          * - Tx
806          * - Rx
807          * - Misc
808          */
809         rc = request_irq(irq, wil->txrx_ops.irq_tx, IRQF_SHARED,
810                          WIL_NAME "_tx", wil);
811         if (rc)
812                 return rc;
813
814         rc = request_irq(irq + 1, wil->txrx_ops.irq_rx, IRQF_SHARED,
815                          WIL_NAME "_rx", wil);
816         if (rc)
817                 goto free0;
818
819         rc = request_threaded_irq(irq + 2, wil6210_irq_misc,
820                                   wil6210_irq_misc_thread,
821                                   IRQF_SHARED, WIL_NAME "_misc", wil);
822         if (rc)
823                 goto free1;
824
825         return 0;
826 free1:
827         free_irq(irq + 1, wil);
828 free0:
829         free_irq(irq, wil);
830
831         return rc;
832 }
833
834 /* can't use wil_ioread32_and_clear because ICC value is not set yet */
835 static inline void wil_clear32(void __iomem *addr)
836 {
837         u32 x = readl(addr);
838
839         writel(x, addr);
840 }
841
842 void wil6210_clear_irq(struct wil6210_priv *wil)
843 {
844         wil_clear32(wil->csr + HOSTADDR(RGF_DMA_EP_RX_ICR) +
845                     offsetof(struct RGF_ICR, ICR));
846         wil_clear32(wil->csr + HOSTADDR(RGF_DMA_EP_TX_ICR) +
847                     offsetof(struct RGF_ICR, ICR));
848         wil_clear32(wil->csr + HOSTADDR(RGF_INT_GEN_RX_ICR) +
849                     offsetof(struct RGF_ICR, ICR));
850         wil_clear32(wil->csr + HOSTADDR(RGF_INT_GEN_TX_ICR) +
851                     offsetof(struct RGF_ICR, ICR));
852         wil_clear32(wil->csr + HOSTADDR(RGF_DMA_EP_MISC_ICR) +
853                     offsetof(struct RGF_ICR, ICR));
854         wmb(); /* make sure write completed */
855 }
856
857 void wil6210_set_halp(struct wil6210_priv *wil)
858 {
859         wil_dbg_irq(wil, "set_halp\n");
860
861         wil_w(wil, RGF_DMA_EP_MISC_ICR + offsetof(struct RGF_ICR, ICS),
862               BIT_DMA_EP_MISC_ICR_HALP);
863 }
864
865 void wil6210_clear_halp(struct wil6210_priv *wil)
866 {
867         wil_dbg_irq(wil, "clear_halp\n");
868
869         wil_w(wil, RGF_DMA_EP_MISC_ICR + offsetof(struct RGF_ICR, ICR),
870               BIT_DMA_EP_MISC_ICR_HALP);
871         wil6210_unmask_halp(wil);
872 }
873
874 int wil6210_init_irq(struct wil6210_priv *wil, int irq)
875 {
876         int rc;
877
878         wil_dbg_misc(wil, "init_irq: %s, n_msi=%d\n",
879                      wil->n_msi ? "MSI" : "INTx", wil->n_msi);
880
881         if (wil->use_enhanced_dma_hw) {
882                 wil->txrx_ops.irq_tx = wil6210_irq_tx_edma;
883                 wil->txrx_ops.irq_rx = wil6210_irq_rx_edma;
884         } else {
885                 wil->txrx_ops.irq_tx = wil6210_irq_tx;
886                 wil->txrx_ops.irq_rx = wil6210_irq_rx;
887         }
888
889         if (wil->n_msi == 3)
890                 rc = wil6210_request_3msi(wil, irq);
891         else
892                 rc = request_threaded_irq(irq, wil6210_hardirq,
893                                           wil6210_thread_irq,
894                                           wil->n_msi ? 0 : IRQF_SHARED,
895                                           WIL_NAME, wil);
896         return rc;
897 }
898
899 void wil6210_fini_irq(struct wil6210_priv *wil, int irq)
900 {
901         wil_dbg_misc(wil, "fini_irq:\n");
902
903         wil_mask_irq(wil);
904         free_irq(irq, wil);
905         if (wil->n_msi == 3) {
906                 free_irq(irq + 1, wil);
907                 free_irq(irq + 2, wil);
908         }
909 }
This page took 0.096391 seconds and 4 git commands to generate.