1/*- 2 * Copyright (c) 2007-2016 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 40static __checkReturn efx_rc_t 41siena_intr_init( 42 __in efx_nic_t *enp, 43 __in efx_intr_type_t type, 44 __in efsys_mem_t *esmp); 45 46static void 47siena_intr_enable( 48 __in efx_nic_t *enp); 49 50static void 51siena_intr_disable( 52 __in efx_nic_t *enp); 53 54static void 55siena_intr_disable_unlocked( 56 __in efx_nic_t *enp); 57 58static __checkReturn efx_rc_t 59siena_intr_trigger( 60 __in efx_nic_t *enp, 61 __in unsigned int level); 62 63static void 64siena_intr_fini( 65 __in efx_nic_t *enp); 66 67static void 68siena_intr_status_line( 69 __in efx_nic_t *enp, 70 __out boolean_t *fatalp, 71 __out uint32_t *qmaskp); 72 73static void 74siena_intr_status_message( 75 __in efx_nic_t *enp, 76 __in unsigned int message, 77 __out boolean_t *fatalp); 78 79static void 80siena_intr_fatal( 81 __in efx_nic_t *enp); 82 83static __checkReturn boolean_t 84siena_intr_check_fatal( 85 __in efx_nic_t *enp); 86 87 88#endif /* EFSYS_OPT_SIENA */ 89 90 91#if EFSYS_OPT_SIENA 92static const efx_intr_ops_t __efx_intr_siena_ops = { 93 siena_intr_init, /* eio_init */ 94 siena_intr_enable, /* eio_enable */ 95 siena_intr_disable, /* eio_disable */ 96 siena_intr_disable_unlocked, /* eio_disable_unlocked */ 97 siena_intr_trigger, /* eio_trigger */ 98 siena_intr_status_line, /* eio_status_line */ 99 siena_intr_status_message, /* eio_status_message */ 100 siena_intr_fatal, /* eio_fatal */ 101 siena_intr_fini, /* eio_fini */ 102}; 103#endif /* EFSYS_OPT_SIENA */ 104 105#if EFSYS_OPT_HUNTINGTON || EFSYS_OPT_MEDFORD 106static 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 120efx_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 175fail3: 176 EFSYS_PROBE(fail3); 177fail2: 178 EFSYS_PROBE(fail2); 179fail1: 180 EFSYS_PROBE1(fail1, efx_rc_t, rc); 181 182 return (rc); 183} 184 185 void 186efx_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 202efx_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 215efx_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 228efx_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 242efx_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 256efx_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 271efx_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 286efx_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 305static __checkReturn efx_rc_t 306siena_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 346static void 347siena_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 360static void 361siena_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 373static void 374siena_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 386static __checkReturn efx_rc_t 387siena_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 433fail1: 434 EFSYS_PROBE1(fail1, efx_rc_t, rc); 435 436 return (rc); 437} 438 439static __checkReturn boolean_t 440siena_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 463static void 464siena_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 = siena_intr_check_fatal(enp); 486 else 487 *fatalp = B_FALSE; 488} 489 490static void 491siena_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 = siena_intr_check_fatal(enp); 503 else 504 *fatalp = B_FALSE; 505} 506 507 508static void 509siena_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 564static void 565siena_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