1 /*- 2 * Copyright (c) 2007-2015 Solarflare Communications Inc. 3 * All rights reserved. 4 * 5 * Redistribution and use in source and binary forms, with or without 6 * modification, are permitted provided that the following conditions are met: 7 * 8 * 1. Redistributions of source code must retain the above copyright notice, 9 * this list of conditions and the following disclaimer. 10 * 2. Redistributions in binary form must reproduce the above copyright notice, 11 * this list of conditions and the following disclaimer in the documentation 12 * and/or other materials provided with the distribution. 13 * 14 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" 15 * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, 16 * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR 17 * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR 18 * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, 19 * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, 20 * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; 21 * OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, 22 * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR 23 * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, 24 * EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 25 * 26 * The views and conclusions contained in the software and documentation are 27 * those of the authors and should not be interpreted as representing official 28 * policies, either expressed or implied, of the FreeBSD Project. 29 */ 30 31 #include <sys/cdefs.h> 32 __FBSDID("$FreeBSD$"); 33 34 #include "efx.h" 35 #include "efx_impl.h" 36 37 38 #if EFSYS_OPT_SIENA 39 40 static __checkReturn efx_rc_t 41 falconsiena_intr_init( 42 __in efx_nic_t *enp, 43 __in efx_intr_type_t type, 44 __in efsys_mem_t *esmp); 45 46 static void 47 falconsiena_intr_enable( 48 __in efx_nic_t *enp); 49 50 static void 51 falconsiena_intr_disable( 52 __in efx_nic_t *enp); 53 54 static void 55 falconsiena_intr_disable_unlocked( 56 __in efx_nic_t *enp); 57 58 static __checkReturn efx_rc_t 59 falconsiena_intr_trigger( 60 __in efx_nic_t *enp, 61 __in unsigned int level); 62 63 static void 64 falconsiena_intr_fini( 65 __in efx_nic_t *enp); 66 67 static void 68 falconsiena_intr_status_line( 69 __in efx_nic_t *enp, 70 __out boolean_t *fatalp, 71 __out uint32_t *qmaskp); 72 73 static void 74 falconsiena_intr_status_message( 75 __in efx_nic_t *enp, 76 __in unsigned int message, 77 __out boolean_t *fatalp); 78 79 static void 80 falconsiena_intr_fatal( 81 __in efx_nic_t *enp); 82 83 static __checkReturn boolean_t 84 falconsiena_intr_check_fatal( 85 __in efx_nic_t *enp); 86 87 88 #endif /* EFSYS_OPT_SIENA */ 89 90 91 #if EFSYS_OPT_SIENA 92 static const efx_intr_ops_t __efx_intr_siena_ops = { 93 falconsiena_intr_init, /* eio_init */ 94 falconsiena_intr_enable, /* eio_enable */ 95 falconsiena_intr_disable, /* eio_disable */ 96 falconsiena_intr_disable_unlocked, /* eio_disable_unlocked */ 97 falconsiena_intr_trigger, /* eio_trigger */ 98 falconsiena_intr_status_line, /* eio_status_line */ 99 falconsiena_intr_status_message, /* eio_status_message */ 100 falconsiena_intr_fatal, /* eio_fatal */ 101 falconsiena_intr_fini, /* eio_fini */ 102 }; 103 #endif /* EFSYS_OPT_SIENA */ 104 105 #if EFSYS_OPT_HUNTINGTON || EFSYS_OPT_MEDFORD 106 static const efx_intr_ops_t __efx_intr_ef10_ops = { 107 ef10_intr_init, /* eio_init */ 108 ef10_intr_enable, /* eio_enable */ 109 ef10_intr_disable, /* eio_disable */ 110 ef10_intr_disable_unlocked, /* eio_disable_unlocked */ 111 ef10_intr_trigger, /* eio_trigger */ 112 ef10_intr_status_line, /* eio_status_line */ 113 ef10_intr_status_message, /* eio_status_message */ 114 ef10_intr_fatal, /* eio_fatal */ 115 ef10_intr_fini, /* eio_fini */ 116 }; 117 #endif /* EFSYS_OPT_HUNTINGTON || EFSYS_OPT_MEDFORD */ 118 119 __checkReturn efx_rc_t 120 efx_intr_init( 121 __in efx_nic_t *enp, 122 __in efx_intr_type_t type, 123 __in efsys_mem_t *esmp) 124 { 125 efx_intr_t *eip = &(enp->en_intr); 126 const efx_intr_ops_t *eiop; 127 efx_rc_t rc; 128 129 EFSYS_ASSERT3U(enp->en_magic, ==, EFX_NIC_MAGIC); 130 EFSYS_ASSERT3U(enp->en_mod_flags, &, EFX_MOD_NIC); 131 132 if (enp->en_mod_flags & EFX_MOD_INTR) { 133 rc = EINVAL; 134 goto fail1; 135 } 136 137 eip->ei_esmp = esmp; 138 eip->ei_type = type; 139 eip->ei_level = 0; 140 141 enp->en_mod_flags |= EFX_MOD_INTR; 142 143 switch (enp->en_family) { 144 #if EFSYS_OPT_SIENA 145 case EFX_FAMILY_SIENA: 146 eiop = &__efx_intr_siena_ops; 147 break; 148 #endif /* EFSYS_OPT_SIENA */ 149 150 #if EFSYS_OPT_HUNTINGTON 151 case EFX_FAMILY_HUNTINGTON: 152 eiop = &__efx_intr_ef10_ops; 153 break; 154 #endif /* EFSYS_OPT_HUNTINGTON */ 155 156 #if EFSYS_OPT_MEDFORD 157 case EFX_FAMILY_MEDFORD: 158 eiop = &__efx_intr_ef10_ops; 159 break; 160 #endif /* EFSYS_OPT_MEDFORD */ 161 162 default: 163 EFSYS_ASSERT(B_FALSE); 164 rc = ENOTSUP; 165 goto fail2; 166 } 167 168 if ((rc = eiop->eio_init(enp, type, esmp)) != 0) 169 goto fail3; 170 171 eip->ei_eiop = eiop; 172 173 return (0); 174 175 fail3: 176 EFSYS_PROBE(fail3); 177 fail2: 178 EFSYS_PROBE(fail2); 179 fail1: 180 EFSYS_PROBE1(fail1, efx_rc_t, rc); 181 182 return (rc); 183 } 184 185 void 186 efx_intr_fini( 187 __in efx_nic_t *enp) 188 { 189 efx_intr_t *eip = &(enp->en_intr); 190 const efx_intr_ops_t *eiop = eip->ei_eiop; 191 192 EFSYS_ASSERT3U(enp->en_magic, ==, EFX_NIC_MAGIC); 193 EFSYS_ASSERT3U(enp->en_mod_flags, &, EFX_MOD_NIC); 194 EFSYS_ASSERT3U(enp->en_mod_flags, &, EFX_MOD_INTR); 195 196 eiop->eio_fini(enp); 197 198 enp->en_mod_flags &= ~EFX_MOD_INTR; 199 } 200 201 void 202 efx_intr_enable( 203 __in efx_nic_t *enp) 204 { 205 efx_intr_t *eip = &(enp->en_intr); 206 const efx_intr_ops_t *eiop = eip->ei_eiop; 207 208 EFSYS_ASSERT3U(enp->en_magic, ==, EFX_NIC_MAGIC); 209 EFSYS_ASSERT3U(enp->en_mod_flags, &, EFX_MOD_INTR); 210 211 eiop->eio_enable(enp); 212 } 213 214 void 215 efx_intr_disable( 216 __in efx_nic_t *enp) 217 { 218 efx_intr_t *eip = &(enp->en_intr); 219 const efx_intr_ops_t *eiop = eip->ei_eiop; 220 221 EFSYS_ASSERT3U(enp->en_magic, ==, EFX_NIC_MAGIC); 222 EFSYS_ASSERT3U(enp->en_mod_flags, &, EFX_MOD_INTR); 223 224 eiop->eio_disable(enp); 225 } 226 227 void 228 efx_intr_disable_unlocked( 229 __in efx_nic_t *enp) 230 { 231 efx_intr_t *eip = &(enp->en_intr); 232 const efx_intr_ops_t *eiop = eip->ei_eiop; 233 234 EFSYS_ASSERT3U(enp->en_magic, ==, EFX_NIC_MAGIC); 235 EFSYS_ASSERT3U(enp->en_mod_flags, &, EFX_MOD_INTR); 236 237 eiop->eio_disable_unlocked(enp); 238 } 239 240 241 __checkReturn efx_rc_t 242 efx_intr_trigger( 243 __in efx_nic_t *enp, 244 __in unsigned int level) 245 { 246 efx_intr_t *eip = &(enp->en_intr); 247 const efx_intr_ops_t *eiop = eip->ei_eiop; 248 249 EFSYS_ASSERT3U(enp->en_magic, ==, EFX_NIC_MAGIC); 250 EFSYS_ASSERT3U(enp->en_mod_flags, &, EFX_MOD_INTR); 251 252 return (eiop->eio_trigger(enp, level)); 253 } 254 255 void 256 efx_intr_status_line( 257 __in efx_nic_t *enp, 258 __out boolean_t *fatalp, 259 __out uint32_t *qmaskp) 260 { 261 efx_intr_t *eip = &(enp->en_intr); 262 const efx_intr_ops_t *eiop = eip->ei_eiop; 263 264 EFSYS_ASSERT3U(enp->en_magic, ==, EFX_NIC_MAGIC); 265 EFSYS_ASSERT3U(enp->en_mod_flags, &, EFX_MOD_INTR); 266 267 eiop->eio_status_line(enp, fatalp, qmaskp); 268 } 269 270 void 271 efx_intr_status_message( 272 __in efx_nic_t *enp, 273 __in unsigned int message, 274 __out boolean_t *fatalp) 275 { 276 efx_intr_t *eip = &(enp->en_intr); 277 const efx_intr_ops_t *eiop = eip->ei_eiop; 278 279 EFSYS_ASSERT3U(enp->en_magic, ==, EFX_NIC_MAGIC); 280 EFSYS_ASSERT3U(enp->en_mod_flags, &, EFX_MOD_INTR); 281 282 eiop->eio_status_message(enp, message, fatalp); 283 } 284 285 void 286 efx_intr_fatal( 287 __in efx_nic_t *enp) 288 { 289 efx_intr_t *eip = &(enp->en_intr); 290 const efx_intr_ops_t *eiop = eip->ei_eiop; 291 292 EFSYS_ASSERT3U(enp->en_magic, ==, EFX_NIC_MAGIC); 293 EFSYS_ASSERT3U(enp->en_mod_flags, &, EFX_MOD_INTR); 294 295 eiop->eio_fatal(enp); 296 } 297 298 299 /* ************************************************************************* */ 300 /* ************************************************************************* */ 301 /* ************************************************************************* */ 302 303 #if EFSYS_OPT_SIENA 304 305 static __checkReturn efx_rc_t 306 falconsiena_intr_init( 307 __in efx_nic_t *enp, 308 __in efx_intr_type_t type, 309 __in efsys_mem_t *esmp) 310 { 311 efx_intr_t *eip = &(enp->en_intr); 312 efx_oword_t oword; 313 314 /* 315 * bug17213 workaround. 316 * 317 * Under legacy interrupts, don't share a level between fatal 318 * interrupts and event queue interrupts. Under MSI-X, they 319 * must share, or we won't get an interrupt. 320 */ 321 if (enp->en_family == EFX_FAMILY_SIENA && 322 eip->ei_type == EFX_INTR_LINE) 323 eip->ei_level = 0x1f; 324 else 325 eip->ei_level = 0; 326 327 /* Enable all the genuinely fatal interrupts */ 328 EFX_SET_OWORD(oword); 329 EFX_SET_OWORD_FIELD(oword, FRF_AZ_ILL_ADR_INT_KER_EN, 0); 330 EFX_SET_OWORD_FIELD(oword, FRF_AZ_RBUF_OWN_INT_KER_EN, 0); 331 EFX_SET_OWORD_FIELD(oword, FRF_AZ_TBUF_OWN_INT_KER_EN, 0); 332 if (enp->en_family >= EFX_FAMILY_SIENA) 333 EFX_SET_OWORD_FIELD(oword, FRF_CZ_SRAM_PERR_INT_P_KER_EN, 0); 334 EFX_BAR_WRITEO(enp, FR_AZ_FATAL_INTR_REG_KER, &oword); 335 336 /* Set up the interrupt address register */ 337 EFX_POPULATE_OWORD_3(oword, 338 FRF_AZ_NORM_INT_VEC_DIS_KER, (type == EFX_INTR_MESSAGE) ? 1 : 0, 339 FRF_AZ_INT_ADR_KER_DW0, EFSYS_MEM_ADDR(esmp) & 0xffffffff, 340 FRF_AZ_INT_ADR_KER_DW1, EFSYS_MEM_ADDR(esmp) >> 32); 341 EFX_BAR_WRITEO(enp, FR_AZ_INT_ADR_REG_KER, &oword); 342 343 return (0); 344 } 345 346 static void 347 falconsiena_intr_enable( 348 __in efx_nic_t *enp) 349 { 350 efx_intr_t *eip = &(enp->en_intr); 351 efx_oword_t oword; 352 353 EFX_BAR_READO(enp, FR_AZ_INT_EN_REG_KER, &oword); 354 355 EFX_SET_OWORD_FIELD(oword, FRF_AZ_KER_INT_LEVE_SEL, eip->ei_level); 356 EFX_SET_OWORD_FIELD(oword, FRF_AZ_DRV_INT_EN_KER, 1); 357 EFX_BAR_WRITEO(enp, FR_AZ_INT_EN_REG_KER, &oword); 358 } 359 360 static void 361 falconsiena_intr_disable( 362 __in efx_nic_t *enp) 363 { 364 efx_oword_t oword; 365 366 EFX_BAR_READO(enp, FR_AZ_INT_EN_REG_KER, &oword); 367 EFX_SET_OWORD_FIELD(oword, FRF_AZ_DRV_INT_EN_KER, 0); 368 EFX_BAR_WRITEO(enp, FR_AZ_INT_EN_REG_KER, &oword); 369 370 EFSYS_SPIN(10); 371 } 372 373 static void 374 falconsiena_intr_disable_unlocked( 375 __in efx_nic_t *enp) 376 { 377 efx_oword_t oword; 378 379 EFSYS_BAR_READO(enp->en_esbp, FR_AZ_INT_EN_REG_KER_OFST, 380 &oword, B_FALSE); 381 EFX_SET_OWORD_FIELD(oword, FRF_AZ_DRV_INT_EN_KER, 0); 382 EFSYS_BAR_WRITEO(enp->en_esbp, FR_AZ_INT_EN_REG_KER_OFST, 383 &oword, B_FALSE); 384 } 385 386 static __checkReturn efx_rc_t 387 falconsiena_intr_trigger( 388 __in efx_nic_t *enp, 389 __in unsigned int level) 390 { 391 efx_intr_t *eip = &(enp->en_intr); 392 efx_oword_t oword; 393 unsigned int count; 394 uint32_t sel; 395 efx_rc_t rc; 396 397 /* bug16757: No event queues can be initialized */ 398 EFSYS_ASSERT(!(enp->en_mod_flags & EFX_MOD_EV)); 399 400 if (level >= EFX_NINTR_SIENA) { 401 rc = EINVAL; 402 goto fail1; 403 } 404 405 if (level > EFX_MASK32(FRF_AZ_KER_INT_LEVE_SEL)) 406 return (ENOTSUP); /* avoid EFSYS_PROBE() */ 407 408 sel = level; 409 410 /* Trigger a test interrupt */ 411 EFX_BAR_READO(enp, FR_AZ_INT_EN_REG_KER, &oword); 412 EFX_SET_OWORD_FIELD(oword, FRF_AZ_KER_INT_LEVE_SEL, sel); 413 EFX_SET_OWORD_FIELD(oword, FRF_AZ_KER_INT_KER, 1); 414 EFX_BAR_WRITEO(enp, FR_AZ_INT_EN_REG_KER, &oword); 415 416 /* 417 * Wait up to 100ms for the interrupt to be raised before restoring 418 * KER_INT_LEVE_SEL. Ignore a failure to raise (the caller will 419 * observe this soon enough anyway), but always reset KER_INT_LEVE_SEL 420 */ 421 count = 0; 422 do { 423 EFSYS_SPIN(100); /* 100us */ 424 425 EFX_BAR_READO(enp, FR_AZ_INT_EN_REG_KER, &oword); 426 } while (EFX_OWORD_FIELD(oword, FRF_AZ_KER_INT_KER) && ++count < 1000); 427 428 EFX_SET_OWORD_FIELD(oword, FRF_AZ_KER_INT_LEVE_SEL, eip->ei_level); 429 EFX_BAR_WRITEO(enp, FR_AZ_INT_EN_REG_KER, &oword); 430 431 return (0); 432 433 fail1: 434 EFSYS_PROBE1(fail1, efx_rc_t, rc); 435 436 return (rc); 437 } 438 439 static __checkReturn boolean_t 440 falconsiena_intr_check_fatal( 441 __in efx_nic_t *enp) 442 { 443 efx_intr_t *eip = &(enp->en_intr); 444 efsys_mem_t *esmp = eip->ei_esmp; 445 efx_oword_t oword; 446 447 /* Read the syndrome */ 448 EFSYS_MEM_READO(esmp, 0, &oword); 449 450 if (EFX_OWORD_FIELD(oword, FSF_AZ_NET_IVEC_FATAL_INT) != 0) { 451 EFSYS_PROBE(fatal); 452 453 /* Clear the fatal interrupt condition */ 454 EFX_SET_OWORD_FIELD(oword, FSF_AZ_NET_IVEC_FATAL_INT, 0); 455 EFSYS_MEM_WRITEO(esmp, 0, &oword); 456 457 return (B_TRUE); 458 } 459 460 return (B_FALSE); 461 } 462 463 static void 464 falconsiena_intr_status_line( 465 __in efx_nic_t *enp, 466 __out boolean_t *fatalp, 467 __out uint32_t *qmaskp) 468 { 469 efx_intr_t *eip = &(enp->en_intr); 470 efx_dword_t dword; 471 472 EFSYS_ASSERT3U(enp->en_magic, ==, EFX_NIC_MAGIC); 473 EFSYS_ASSERT3U(enp->en_mod_flags, &, EFX_MOD_INTR); 474 475 /* 476 * Read the queue mask and implicitly acknowledge the 477 * interrupt. 478 */ 479 EFX_BAR_READD(enp, FR_BZ_INT_ISR0_REG, &dword, B_FALSE); 480 *qmaskp = EFX_DWORD_FIELD(dword, EFX_DWORD_0); 481 482 EFSYS_PROBE1(qmask, uint32_t, *qmaskp); 483 484 if (*qmaskp & (1U << eip->ei_level)) 485 *fatalp = falconsiena_intr_check_fatal(enp); 486 else 487 *fatalp = B_FALSE; 488 } 489 490 static void 491 falconsiena_intr_status_message( 492 __in efx_nic_t *enp, 493 __in unsigned int message, 494 __out boolean_t *fatalp) 495 { 496 efx_intr_t *eip = &(enp->en_intr); 497 498 EFSYS_ASSERT3U(enp->en_magic, ==, EFX_NIC_MAGIC); 499 EFSYS_ASSERT3U(enp->en_mod_flags, &, EFX_MOD_INTR); 500 501 if (message == eip->ei_level) 502 *fatalp = falconsiena_intr_check_fatal(enp); 503 else 504 *fatalp = B_FALSE; 505 } 506 507 508 static void 509 falconsiena_intr_fatal( 510 __in efx_nic_t *enp) 511 { 512 #if EFSYS_OPT_DECODE_INTR_FATAL 513 efx_oword_t fatal; 514 efx_oword_t mem_per; 515 516 EFX_BAR_READO(enp, FR_AZ_FATAL_INTR_REG_KER, &fatal); 517 EFX_ZERO_OWORD(mem_per); 518 519 if (EFX_OWORD_FIELD(fatal, FRF_AZ_SRM_PERR_INT_KER) != 0 || 520 EFX_OWORD_FIELD(fatal, FRF_AZ_MEM_PERR_INT_KER) != 0) 521 EFX_BAR_READO(enp, FR_AZ_MEM_STAT_REG, &mem_per); 522 523 if (EFX_OWORD_FIELD(fatal, FRF_AZ_SRAM_OOB_INT_KER) != 0) 524 EFSYS_ERR(enp->en_esip, EFX_ERR_SRAM_OOB, 0, 0); 525 526 if (EFX_OWORD_FIELD(fatal, FRF_AZ_BUFID_DC_OOB_INT_KER) != 0) 527 EFSYS_ERR(enp->en_esip, EFX_ERR_BUFID_DC_OOB, 0, 0); 528 529 if (EFX_OWORD_FIELD(fatal, FRF_AZ_MEM_PERR_INT_KER) != 0) 530 EFSYS_ERR(enp->en_esip, EFX_ERR_MEM_PERR, 531 EFX_OWORD_FIELD(mem_per, EFX_DWORD_0), 532 EFX_OWORD_FIELD(mem_per, EFX_DWORD_1)); 533 534 if (EFX_OWORD_FIELD(fatal, FRF_AZ_RBUF_OWN_INT_KER) != 0) 535 EFSYS_ERR(enp->en_esip, EFX_ERR_RBUF_OWN, 0, 0); 536 537 if (EFX_OWORD_FIELD(fatal, FRF_AZ_TBUF_OWN_INT_KER) != 0) 538 EFSYS_ERR(enp->en_esip, EFX_ERR_TBUF_OWN, 0, 0); 539 540 if (EFX_OWORD_FIELD(fatal, FRF_AZ_RDESCQ_OWN_INT_KER) != 0) 541 EFSYS_ERR(enp->en_esip, EFX_ERR_RDESQ_OWN, 0, 0); 542 543 if (EFX_OWORD_FIELD(fatal, FRF_AZ_TDESCQ_OWN_INT_KER) != 0) 544 EFSYS_ERR(enp->en_esip, EFX_ERR_TDESQ_OWN, 0, 0); 545 546 if (EFX_OWORD_FIELD(fatal, FRF_AZ_EVQ_OWN_INT_KER) != 0) 547 EFSYS_ERR(enp->en_esip, EFX_ERR_EVQ_OWN, 0, 0); 548 549 if (EFX_OWORD_FIELD(fatal, FRF_AZ_EVF_OFLO_INT_KER) != 0) 550 EFSYS_ERR(enp->en_esip, EFX_ERR_EVFF_OFLO, 0, 0); 551 552 if (EFX_OWORD_FIELD(fatal, FRF_AZ_ILL_ADR_INT_KER) != 0) 553 EFSYS_ERR(enp->en_esip, EFX_ERR_ILL_ADDR, 0, 0); 554 555 if (EFX_OWORD_FIELD(fatal, FRF_AZ_SRM_PERR_INT_KER) != 0) 556 EFSYS_ERR(enp->en_esip, EFX_ERR_SRAM_PERR, 557 EFX_OWORD_FIELD(mem_per, EFX_DWORD_0), 558 EFX_OWORD_FIELD(mem_per, EFX_DWORD_1)); 559 #else 560 EFSYS_ASSERT(0); 561 #endif 562 } 563 564 static void 565 falconsiena_intr_fini( 566 __in efx_nic_t *enp) 567 { 568 efx_oword_t oword; 569 570 /* Clear the interrupt address register */ 571 EFX_ZERO_OWORD(oword); 572 EFX_BAR_WRITEO(enp, FR_AZ_INT_ADR_REG_KER, &oword); 573 } 574 575 #endif /* EFSYS_OPT_SIENA */ 576