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