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