1227569Sphilip/*- 2300607Sarybchik * Copyright (c) 2007-2016 Solarflare Communications Inc. 3283514Sarybchik * All rights reserved. 4227569Sphilip * 5227569Sphilip * Redistribution and use in source and binary forms, with or without 6283514Sarybchik * modification, are permitted provided that the following conditions are met: 7227569Sphilip * 8283514Sarybchik * 1. Redistributions of source code must retain the above copyright notice, 9283514Sarybchik * this list of conditions and the following disclaimer. 10283514Sarybchik * 2. Redistributions in binary form must reproduce the above copyright notice, 11283514Sarybchik * this list of conditions and the following disclaimer in the documentation 12283514Sarybchik * and/or other materials provided with the distribution. 13283514Sarybchik * 14283514Sarybchik * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" 15283514Sarybchik * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, 16283514Sarybchik * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR 17283514Sarybchik * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR 18283514Sarybchik * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, 19283514Sarybchik * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, 20283514Sarybchik * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; 21283514Sarybchik * OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, 22283514Sarybchik * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR 23283514Sarybchik * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, 24283514Sarybchik * EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 25283514Sarybchik * 26283514Sarybchik * The views and conclusions contained in the software and documentation are 27283514Sarybchik * those of the authors and should not be interpreted as representing official 28283514Sarybchik * policies, either expressed or implied, of the FreeBSD Project. 29227569Sphilip */ 30227569Sphilip 31228078Sphilip#include <sys/cdefs.h> 32228078Sphilip__FBSDID("$FreeBSD$"); 33228078Sphilip 34227569Sphilip#include "efx.h" 35227569Sphilip#include "efx_impl.h" 36227569Sphilip 37283514Sarybchik 38299320Sarybchik#if EFSYS_OPT_SIENA 39283514Sarybchik 40291436Sarybchikstatic __checkReturn efx_rc_t 41299608Sarybchiksiena_intr_init( 42283514Sarybchik __in efx_nic_t *enp, 43283514Sarybchik __in efx_intr_type_t type, 44283514Sarybchik __in efsys_mem_t *esmp); 45283514Sarybchik 46283514Sarybchikstatic void 47299608Sarybchiksiena_intr_enable( 48283514Sarybchik __in efx_nic_t *enp); 49283514Sarybchik 50283514Sarybchikstatic void 51299608Sarybchiksiena_intr_disable( 52283514Sarybchik __in efx_nic_t *enp); 53283514Sarybchik 54283514Sarybchikstatic void 55299608Sarybchiksiena_intr_disable_unlocked( 56283514Sarybchik __in efx_nic_t *enp); 57283514Sarybchik 58291436Sarybchikstatic __checkReturn efx_rc_t 59299608Sarybchiksiena_intr_trigger( 60283514Sarybchik __in efx_nic_t *enp, 61283514Sarybchik __in unsigned int level); 62283514Sarybchik 63283514Sarybchikstatic void 64299608Sarybchiksiena_intr_fini( 65283514Sarybchik __in efx_nic_t *enp); 66283514Sarybchik 67293769Sarybchikstatic void 68299608Sarybchiksiena_intr_status_line( 69293769Sarybchik __in efx_nic_t *enp, 70293769Sarybchik __out boolean_t *fatalp, 71293769Sarybchik __out uint32_t *qmaskp); 72283514Sarybchik 73293769Sarybchikstatic void 74299608Sarybchiksiena_intr_status_message( 75293769Sarybchik __in efx_nic_t *enp, 76293769Sarybchik __in unsigned int message, 77293769Sarybchik __out boolean_t *fatalp); 78283514Sarybchik 79283514Sarybchikstatic void 80299608Sarybchiksiena_intr_fatal( 81283514Sarybchik __in efx_nic_t *enp); 82283514Sarybchik 83293769Sarybchikstatic __checkReturn boolean_t 84299608Sarybchiksiena_intr_check_fatal( 85293769Sarybchik __in efx_nic_t *enp); 86293769Sarybchik 87293769Sarybchik 88299320Sarybchik#endif /* EFSYS_OPT_SIENA */ 89283514Sarybchik 90283514Sarybchik 91283514Sarybchik#if EFSYS_OPT_SIENA 92299517Sarybchikstatic const efx_intr_ops_t __efx_intr_siena_ops = { 93299608Sarybchik siena_intr_init, /* eio_init */ 94299608Sarybchik siena_intr_enable, /* eio_enable */ 95299608Sarybchik siena_intr_disable, /* eio_disable */ 96299608Sarybchik siena_intr_disable_unlocked, /* eio_disable_unlocked */ 97299608Sarybchik siena_intr_trigger, /* eio_trigger */ 98299608Sarybchik siena_intr_status_line, /* eio_status_line */ 99299608Sarybchik siena_intr_status_message, /* eio_status_message */ 100299608Sarybchik siena_intr_fatal, /* eio_fatal */ 101299608Sarybchik siena_intr_fini, /* eio_fini */ 102283514Sarybchik}; 103283514Sarybchik#endif /* EFSYS_OPT_SIENA */ 104283514Sarybchik 105293751Sarybchik#if EFSYS_OPT_HUNTINGTON || EFSYS_OPT_MEDFORD 106299517Sarybchikstatic const efx_intr_ops_t __efx_intr_ef10_ops = { 107293751Sarybchik ef10_intr_init, /* eio_init */ 108293751Sarybchik ef10_intr_enable, /* eio_enable */ 109293751Sarybchik ef10_intr_disable, /* eio_disable */ 110293751Sarybchik ef10_intr_disable_unlocked, /* eio_disable_unlocked */ 111293751Sarybchik ef10_intr_trigger, /* eio_trigger */ 112293769Sarybchik ef10_intr_status_line, /* eio_status_line */ 113293769Sarybchik ef10_intr_status_message, /* eio_status_message */ 114293769Sarybchik ef10_intr_fatal, /* eio_fatal */ 115293751Sarybchik ef10_intr_fini, /* eio_fini */ 116283514Sarybchik}; 117293751Sarybchik#endif /* EFSYS_OPT_HUNTINGTON || EFSYS_OPT_MEDFORD */ 118283514Sarybchik 119291436Sarybchik __checkReturn efx_rc_t 120227569Sphilipefx_intr_init( 121227569Sphilip __in efx_nic_t *enp, 122227569Sphilip __in efx_intr_type_t type, 123227569Sphilip __in efsys_mem_t *esmp) 124227569Sphilip{ 125227569Sphilip efx_intr_t *eip = &(enp->en_intr); 126299517Sarybchik const efx_intr_ops_t *eiop; 127291436Sarybchik efx_rc_t rc; 128227569Sphilip 129227569Sphilip EFSYS_ASSERT3U(enp->en_magic, ==, EFX_NIC_MAGIC); 130227569Sphilip EFSYS_ASSERT3U(enp->en_mod_flags, &, EFX_MOD_NIC); 131227569Sphilip 132227569Sphilip if (enp->en_mod_flags & EFX_MOD_INTR) { 133227569Sphilip rc = EINVAL; 134227569Sphilip goto fail1; 135227569Sphilip } 136227569Sphilip 137283514Sarybchik eip->ei_esmp = esmp; 138283514Sarybchik eip->ei_type = type; 139283514Sarybchik eip->ei_level = 0; 140283514Sarybchik 141227569Sphilip enp->en_mod_flags |= EFX_MOD_INTR; 142227569Sphilip 143283514Sarybchik switch (enp->en_family) { 144283514Sarybchik#if EFSYS_OPT_SIENA 145283514Sarybchik case EFX_FAMILY_SIENA: 146299517Sarybchik eiop = &__efx_intr_siena_ops; 147283514Sarybchik break; 148283514Sarybchik#endif /* EFSYS_OPT_SIENA */ 149283514Sarybchik 150283514Sarybchik#if EFSYS_OPT_HUNTINGTON 151283514Sarybchik case EFX_FAMILY_HUNTINGTON: 152299517Sarybchik eiop = &__efx_intr_ef10_ops; 153283514Sarybchik break; 154283514Sarybchik#endif /* EFSYS_OPT_HUNTINGTON */ 155283514Sarybchik 156293751Sarybchik#if EFSYS_OPT_MEDFORD 157293751Sarybchik case EFX_FAMILY_MEDFORD: 158299517Sarybchik eiop = &__efx_intr_ef10_ops; 159293751Sarybchik break; 160293751Sarybchik#endif /* EFSYS_OPT_MEDFORD */ 161293751Sarybchik 162283514Sarybchik default: 163283514Sarybchik EFSYS_ASSERT(B_FALSE); 164283514Sarybchik rc = ENOTSUP; 165283514Sarybchik goto fail2; 166283514Sarybchik } 167283514Sarybchik 168283514Sarybchik if ((rc = eiop->eio_init(enp, type, esmp)) != 0) 169283514Sarybchik goto fail3; 170283514Sarybchik 171283514Sarybchik eip->ei_eiop = eiop; 172283514Sarybchik 173283514Sarybchik return (0); 174283514Sarybchik 175283514Sarybchikfail3: 176283514Sarybchik EFSYS_PROBE(fail3); 177283514Sarybchikfail2: 178283514Sarybchik EFSYS_PROBE(fail2); 179283514Sarybchikfail1: 180291436Sarybchik EFSYS_PROBE1(fail1, efx_rc_t, rc); 181283514Sarybchik 182283514Sarybchik return (rc); 183283514Sarybchik} 184283514Sarybchik 185283514Sarybchik void 186283514Sarybchikefx_intr_fini( 187283514Sarybchik __in efx_nic_t *enp) 188283514Sarybchik{ 189283514Sarybchik efx_intr_t *eip = &(enp->en_intr); 190299517Sarybchik const efx_intr_ops_t *eiop = eip->ei_eiop; 191283514Sarybchik 192283514Sarybchik EFSYS_ASSERT3U(enp->en_magic, ==, EFX_NIC_MAGIC); 193283514Sarybchik EFSYS_ASSERT3U(enp->en_mod_flags, &, EFX_MOD_NIC); 194283514Sarybchik EFSYS_ASSERT3U(enp->en_mod_flags, &, EFX_MOD_INTR); 195283514Sarybchik 196283514Sarybchik eiop->eio_fini(enp); 197283514Sarybchik 198283514Sarybchik enp->en_mod_flags &= ~EFX_MOD_INTR; 199283514Sarybchik} 200283514Sarybchik 201283514Sarybchik void 202283514Sarybchikefx_intr_enable( 203283514Sarybchik __in efx_nic_t *enp) 204283514Sarybchik{ 205283514Sarybchik efx_intr_t *eip = &(enp->en_intr); 206299517Sarybchik const efx_intr_ops_t *eiop = eip->ei_eiop; 207283514Sarybchik 208283514Sarybchik EFSYS_ASSERT3U(enp->en_magic, ==, EFX_NIC_MAGIC); 209283514Sarybchik EFSYS_ASSERT3U(enp->en_mod_flags, &, EFX_MOD_INTR); 210283514Sarybchik 211283514Sarybchik eiop->eio_enable(enp); 212283514Sarybchik} 213283514Sarybchik 214283514Sarybchik void 215283514Sarybchikefx_intr_disable( 216283514Sarybchik __in efx_nic_t *enp) 217283514Sarybchik{ 218283514Sarybchik efx_intr_t *eip = &(enp->en_intr); 219299517Sarybchik const efx_intr_ops_t *eiop = eip->ei_eiop; 220283514Sarybchik 221283514Sarybchik EFSYS_ASSERT3U(enp->en_magic, ==, EFX_NIC_MAGIC); 222283514Sarybchik EFSYS_ASSERT3U(enp->en_mod_flags, &, EFX_MOD_INTR); 223283514Sarybchik 224283514Sarybchik eiop->eio_disable(enp); 225283514Sarybchik} 226283514Sarybchik 227283514Sarybchik void 228283514Sarybchikefx_intr_disable_unlocked( 229283514Sarybchik __in efx_nic_t *enp) 230283514Sarybchik{ 231283514Sarybchik efx_intr_t *eip = &(enp->en_intr); 232299517Sarybchik const efx_intr_ops_t *eiop = eip->ei_eiop; 233283514Sarybchik 234283514Sarybchik EFSYS_ASSERT3U(enp->en_magic, ==, EFX_NIC_MAGIC); 235283514Sarybchik EFSYS_ASSERT3U(enp->en_mod_flags, &, EFX_MOD_INTR); 236283514Sarybchik 237283514Sarybchik eiop->eio_disable_unlocked(enp); 238283514Sarybchik} 239283514Sarybchik 240283514Sarybchik 241291436Sarybchik __checkReturn efx_rc_t 242283514Sarybchikefx_intr_trigger( 243283514Sarybchik __in efx_nic_t *enp, 244283514Sarybchik __in unsigned int level) 245283514Sarybchik{ 246283514Sarybchik efx_intr_t *eip = &(enp->en_intr); 247299517Sarybchik const efx_intr_ops_t *eiop = eip->ei_eiop; 248283514Sarybchik 249283514Sarybchik EFSYS_ASSERT3U(enp->en_magic, ==, EFX_NIC_MAGIC); 250283514Sarybchik EFSYS_ASSERT3U(enp->en_mod_flags, &, EFX_MOD_INTR); 251283514Sarybchik 252283514Sarybchik return (eiop->eio_trigger(enp, level)); 253283514Sarybchik} 254283514Sarybchik 255283514Sarybchik void 256283514Sarybchikefx_intr_status_line( 257283514Sarybchik __in efx_nic_t *enp, 258283514Sarybchik __out boolean_t *fatalp, 259283514Sarybchik __out uint32_t *qmaskp) 260283514Sarybchik{ 261283514Sarybchik efx_intr_t *eip = &(enp->en_intr); 262299517Sarybchik const efx_intr_ops_t *eiop = eip->ei_eiop; 263283514Sarybchik 264283514Sarybchik EFSYS_ASSERT3U(enp->en_magic, ==, EFX_NIC_MAGIC); 265283514Sarybchik EFSYS_ASSERT3U(enp->en_mod_flags, &, EFX_MOD_INTR); 266283514Sarybchik 267293769Sarybchik eiop->eio_status_line(enp, fatalp, qmaskp); 268283514Sarybchik} 269283514Sarybchik 270283514Sarybchik void 271283514Sarybchikefx_intr_status_message( 272283514Sarybchik __in efx_nic_t *enp, 273283514Sarybchik __in unsigned int message, 274283514Sarybchik __out boolean_t *fatalp) 275283514Sarybchik{ 276283514Sarybchik efx_intr_t *eip = &(enp->en_intr); 277299517Sarybchik const efx_intr_ops_t *eiop = eip->ei_eiop; 278283514Sarybchik 279283514Sarybchik EFSYS_ASSERT3U(enp->en_magic, ==, EFX_NIC_MAGIC); 280283514Sarybchik EFSYS_ASSERT3U(enp->en_mod_flags, &, EFX_MOD_INTR); 281283514Sarybchik 282293769Sarybchik eiop->eio_status_message(enp, message, fatalp); 283283514Sarybchik} 284283514Sarybchik 285283514Sarybchik void 286283514Sarybchikefx_intr_fatal( 287283514Sarybchik __in efx_nic_t *enp) 288283514Sarybchik{ 289293769Sarybchik efx_intr_t *eip = &(enp->en_intr); 290299517Sarybchik const efx_intr_ops_t *eiop = eip->ei_eiop; 291293769Sarybchik 292283514Sarybchik EFSYS_ASSERT3U(enp->en_magic, ==, EFX_NIC_MAGIC); 293283514Sarybchik EFSYS_ASSERT3U(enp->en_mod_flags, &, EFX_MOD_INTR); 294283514Sarybchik 295293769Sarybchik eiop->eio_fatal(enp); 296283514Sarybchik} 297283514Sarybchik 298283514Sarybchik 299283514Sarybchik/* ************************************************************************* */ 300283514Sarybchik/* ************************************************************************* */ 301283514Sarybchik/* ************************************************************************* */ 302283514Sarybchik 303299320Sarybchik#if EFSYS_OPT_SIENA 304283514Sarybchik 305291436Sarybchikstatic __checkReturn efx_rc_t 306299608Sarybchiksiena_intr_init( 307283514Sarybchik __in efx_nic_t *enp, 308283514Sarybchik __in efx_intr_type_t type, 309283514Sarybchik __in efsys_mem_t *esmp) 310283514Sarybchik{ 311283514Sarybchik efx_intr_t *eip = &(enp->en_intr); 312283514Sarybchik efx_oword_t oword; 313283514Sarybchik 314283514Sarybchik /* 315227569Sphilip * bug17213 workaround. 316227569Sphilip * 317227569Sphilip * Under legacy interrupts, don't share a level between fatal 318227569Sphilip * interrupts and event queue interrupts. Under MSI-X, they 319227569Sphilip * must share, or we won't get an interrupt. 320227569Sphilip */ 321227569Sphilip if (enp->en_family == EFX_FAMILY_SIENA && 322227569Sphilip eip->ei_type == EFX_INTR_LINE) 323227569Sphilip eip->ei_level = 0x1f; 324227569Sphilip else 325227569Sphilip eip->ei_level = 0; 326227569Sphilip 327227569Sphilip /* Enable all the genuinely fatal interrupts */ 328227569Sphilip EFX_SET_OWORD(oword); 329227569Sphilip EFX_SET_OWORD_FIELD(oword, FRF_AZ_ILL_ADR_INT_KER_EN, 0); 330227569Sphilip EFX_SET_OWORD_FIELD(oword, FRF_AZ_RBUF_OWN_INT_KER_EN, 0); 331227569Sphilip EFX_SET_OWORD_FIELD(oword, FRF_AZ_TBUF_OWN_INT_KER_EN, 0); 332227569Sphilip if (enp->en_family >= EFX_FAMILY_SIENA) 333227569Sphilip EFX_SET_OWORD_FIELD(oword, FRF_CZ_SRAM_PERR_INT_P_KER_EN, 0); 334227569Sphilip EFX_BAR_WRITEO(enp, FR_AZ_FATAL_INTR_REG_KER, &oword); 335227569Sphilip 336227569Sphilip /* Set up the interrupt address register */ 337227569Sphilip EFX_POPULATE_OWORD_3(oword, 338227569Sphilip FRF_AZ_NORM_INT_VEC_DIS_KER, (type == EFX_INTR_MESSAGE) ? 1 : 0, 339227569Sphilip FRF_AZ_INT_ADR_KER_DW0, EFSYS_MEM_ADDR(esmp) & 0xffffffff, 340227569Sphilip FRF_AZ_INT_ADR_KER_DW1, EFSYS_MEM_ADDR(esmp) >> 32); 341227569Sphilip EFX_BAR_WRITEO(enp, FR_AZ_INT_ADR_REG_KER, &oword); 342227569Sphilip 343227569Sphilip return (0); 344227569Sphilip} 345227569Sphilip 346283514Sarybchikstatic void 347299608Sarybchiksiena_intr_enable( 348227569Sphilip __in efx_nic_t *enp) 349227569Sphilip{ 350227569Sphilip efx_intr_t *eip = &(enp->en_intr); 351227569Sphilip efx_oword_t oword; 352227569Sphilip 353227569Sphilip EFX_BAR_READO(enp, FR_AZ_INT_EN_REG_KER, &oword); 354227569Sphilip 355227569Sphilip EFX_SET_OWORD_FIELD(oword, FRF_AZ_KER_INT_LEVE_SEL, eip->ei_level); 356227569Sphilip EFX_SET_OWORD_FIELD(oword, FRF_AZ_DRV_INT_EN_KER, 1); 357227569Sphilip EFX_BAR_WRITEO(enp, FR_AZ_INT_EN_REG_KER, &oword); 358227569Sphilip} 359227569Sphilip 360283514Sarybchikstatic void 361299608Sarybchiksiena_intr_disable( 362227569Sphilip __in efx_nic_t *enp) 363227569Sphilip{ 364227569Sphilip efx_oword_t oword; 365227569Sphilip 366227569Sphilip EFX_BAR_READO(enp, FR_AZ_INT_EN_REG_KER, &oword); 367227569Sphilip EFX_SET_OWORD_FIELD(oword, FRF_AZ_DRV_INT_EN_KER, 0); 368227569Sphilip EFX_BAR_WRITEO(enp, FR_AZ_INT_EN_REG_KER, &oword); 369227569Sphilip 370227569Sphilip EFSYS_SPIN(10); 371227569Sphilip} 372227569Sphilip 373283514Sarybchikstatic void 374299608Sarybchiksiena_intr_disable_unlocked( 375227569Sphilip __in efx_nic_t *enp) 376227569Sphilip{ 377227569Sphilip efx_oword_t oword; 378227569Sphilip 379227569Sphilip EFSYS_BAR_READO(enp->en_esbp, FR_AZ_INT_EN_REG_KER_OFST, 380227569Sphilip &oword, B_FALSE); 381227569Sphilip EFX_SET_OWORD_FIELD(oword, FRF_AZ_DRV_INT_EN_KER, 0); 382227569Sphilip EFSYS_BAR_WRITEO(enp->en_esbp, FR_AZ_INT_EN_REG_KER_OFST, 383227569Sphilip &oword, B_FALSE); 384227569Sphilip} 385227569Sphilip 386291436Sarybchikstatic __checkReturn efx_rc_t 387299608Sarybchiksiena_intr_trigger( 388227569Sphilip __in efx_nic_t *enp, 389227569Sphilip __in unsigned int level) 390227569Sphilip{ 391227569Sphilip efx_intr_t *eip = &(enp->en_intr); 392227569Sphilip efx_oword_t oword; 393227569Sphilip unsigned int count; 394227569Sphilip uint32_t sel; 395291436Sarybchik efx_rc_t rc; 396227569Sphilip 397227569Sphilip /* bug16757: No event queues can be initialized */ 398227569Sphilip EFSYS_ASSERT(!(enp->en_mod_flags & EFX_MOD_EV)); 399227569Sphilip 400299403Sarybchik if (level >= EFX_NINTR_SIENA) { 401299403Sarybchik rc = EINVAL; 402299403Sarybchik goto fail1; 403227569Sphilip } 404227569Sphilip 405227569Sphilip if (level > EFX_MASK32(FRF_AZ_KER_INT_LEVE_SEL)) 406227569Sphilip return (ENOTSUP); /* avoid EFSYS_PROBE() */ 407227569Sphilip 408227569Sphilip sel = level; 409227569Sphilip 410227569Sphilip /* Trigger a test interrupt */ 411227569Sphilip EFX_BAR_READO(enp, FR_AZ_INT_EN_REG_KER, &oword); 412227569Sphilip EFX_SET_OWORD_FIELD(oword, FRF_AZ_KER_INT_LEVE_SEL, sel); 413227569Sphilip EFX_SET_OWORD_FIELD(oword, FRF_AZ_KER_INT_KER, 1); 414227569Sphilip EFX_BAR_WRITEO(enp, FR_AZ_INT_EN_REG_KER, &oword); 415227569Sphilip 416227569Sphilip /* 417227569Sphilip * Wait up to 100ms for the interrupt to be raised before restoring 418227569Sphilip * KER_INT_LEVE_SEL. Ignore a failure to raise (the caller will 419227569Sphilip * observe this soon enough anyway), but always reset KER_INT_LEVE_SEL 420227569Sphilip */ 421227569Sphilip count = 0; 422227569Sphilip do { 423227569Sphilip EFSYS_SPIN(100); /* 100us */ 424227569Sphilip 425227569Sphilip EFX_BAR_READO(enp, FR_AZ_INT_EN_REG_KER, &oword); 426227569Sphilip } while (EFX_OWORD_FIELD(oword, FRF_AZ_KER_INT_KER) && ++count < 1000); 427227569Sphilip 428227569Sphilip EFX_SET_OWORD_FIELD(oword, FRF_AZ_KER_INT_LEVE_SEL, eip->ei_level); 429227569Sphilip EFX_BAR_WRITEO(enp, FR_AZ_INT_EN_REG_KER, &oword); 430227569Sphilip 431227569Sphilip return (0); 432227569Sphilip 433227569Sphilipfail1: 434291436Sarybchik EFSYS_PROBE1(fail1, efx_rc_t, rc); 435227569Sphilip 436227569Sphilip return (rc); 437227569Sphilip} 438227569Sphilip 439227569Sphilipstatic __checkReturn boolean_t 440299608Sarybchiksiena_intr_check_fatal( 441227569Sphilip __in efx_nic_t *enp) 442227569Sphilip{ 443227569Sphilip efx_intr_t *eip = &(enp->en_intr); 444227569Sphilip efsys_mem_t *esmp = eip->ei_esmp; 445227569Sphilip efx_oword_t oword; 446227569Sphilip 447227569Sphilip /* Read the syndrome */ 448227569Sphilip EFSYS_MEM_READO(esmp, 0, &oword); 449227569Sphilip 450227569Sphilip if (EFX_OWORD_FIELD(oword, FSF_AZ_NET_IVEC_FATAL_INT) != 0) { 451227569Sphilip EFSYS_PROBE(fatal); 452227569Sphilip 453227569Sphilip /* Clear the fatal interrupt condition */ 454227569Sphilip EFX_SET_OWORD_FIELD(oword, FSF_AZ_NET_IVEC_FATAL_INT, 0); 455227569Sphilip EFSYS_MEM_WRITEO(esmp, 0, &oword); 456227569Sphilip 457227569Sphilip return (B_TRUE); 458227569Sphilip } 459227569Sphilip 460227569Sphilip return (B_FALSE); 461227569Sphilip} 462227569Sphilip 463293769Sarybchikstatic void 464299608Sarybchiksiena_intr_status_line( 465293769Sarybchik __in efx_nic_t *enp, 466293769Sarybchik __out boolean_t *fatalp, 467293769Sarybchik __out uint32_t *qmaskp) 468293769Sarybchik{ 469293769Sarybchik efx_intr_t *eip = &(enp->en_intr); 470293769Sarybchik efx_dword_t dword; 471293769Sarybchik 472293769Sarybchik EFSYS_ASSERT3U(enp->en_magic, ==, EFX_NIC_MAGIC); 473293769Sarybchik EFSYS_ASSERT3U(enp->en_mod_flags, &, EFX_MOD_INTR); 474293769Sarybchik 475293769Sarybchik /* 476293769Sarybchik * Read the queue mask and implicitly acknowledge the 477293769Sarybchik * interrupt. 478293769Sarybchik */ 479293769Sarybchik EFX_BAR_READD(enp, FR_BZ_INT_ISR0_REG, &dword, B_FALSE); 480293769Sarybchik *qmaskp = EFX_DWORD_FIELD(dword, EFX_DWORD_0); 481293769Sarybchik 482293769Sarybchik EFSYS_PROBE1(qmask, uint32_t, *qmaskp); 483293769Sarybchik 484293769Sarybchik if (*qmaskp & (1U << eip->ei_level)) 485299608Sarybchik *fatalp = siena_intr_check_fatal(enp); 486293769Sarybchik else 487293769Sarybchik *fatalp = B_FALSE; 488293769Sarybchik} 489293769Sarybchik 490293769Sarybchikstatic void 491299608Sarybchiksiena_intr_status_message( 492293769Sarybchik __in efx_nic_t *enp, 493293769Sarybchik __in unsigned int message, 494293769Sarybchik __out boolean_t *fatalp) 495293769Sarybchik{ 496293769Sarybchik efx_intr_t *eip = &(enp->en_intr); 497293769Sarybchik 498293769Sarybchik EFSYS_ASSERT3U(enp->en_magic, ==, EFX_NIC_MAGIC); 499293769Sarybchik EFSYS_ASSERT3U(enp->en_mod_flags, &, EFX_MOD_INTR); 500293769Sarybchik 501293769Sarybchik if (message == eip->ei_level) 502299608Sarybchik *fatalp = siena_intr_check_fatal(enp); 503293769Sarybchik else 504293769Sarybchik *fatalp = B_FALSE; 505293769Sarybchik} 506293769Sarybchik 507293769Sarybchik 508283514Sarybchikstatic void 509299608Sarybchiksiena_intr_fatal( 510227569Sphilip __in efx_nic_t *enp) 511227569Sphilip{ 512227569Sphilip#if EFSYS_OPT_DECODE_INTR_FATAL 513227569Sphilip efx_oword_t fatal; 514227569Sphilip efx_oword_t mem_per; 515227569Sphilip 516227569Sphilip EFX_BAR_READO(enp, FR_AZ_FATAL_INTR_REG_KER, &fatal); 517227569Sphilip EFX_ZERO_OWORD(mem_per); 518227569Sphilip 519227569Sphilip if (EFX_OWORD_FIELD(fatal, FRF_AZ_SRM_PERR_INT_KER) != 0 || 520227569Sphilip EFX_OWORD_FIELD(fatal, FRF_AZ_MEM_PERR_INT_KER) != 0) 521227569Sphilip EFX_BAR_READO(enp, FR_AZ_MEM_STAT_REG, &mem_per); 522227569Sphilip 523227569Sphilip if (EFX_OWORD_FIELD(fatal, FRF_AZ_SRAM_OOB_INT_KER) != 0) 524227569Sphilip EFSYS_ERR(enp->en_esip, EFX_ERR_SRAM_OOB, 0, 0); 525227569Sphilip 526227569Sphilip if (EFX_OWORD_FIELD(fatal, FRF_AZ_BUFID_DC_OOB_INT_KER) != 0) 527227569Sphilip EFSYS_ERR(enp->en_esip, EFX_ERR_BUFID_DC_OOB, 0, 0); 528227569Sphilip 529227569Sphilip if (EFX_OWORD_FIELD(fatal, FRF_AZ_MEM_PERR_INT_KER) != 0) 530227569Sphilip EFSYS_ERR(enp->en_esip, EFX_ERR_MEM_PERR, 531227569Sphilip EFX_OWORD_FIELD(mem_per, EFX_DWORD_0), 532227569Sphilip EFX_OWORD_FIELD(mem_per, EFX_DWORD_1)); 533227569Sphilip 534227569Sphilip if (EFX_OWORD_FIELD(fatal, FRF_AZ_RBUF_OWN_INT_KER) != 0) 535227569Sphilip EFSYS_ERR(enp->en_esip, EFX_ERR_RBUF_OWN, 0, 0); 536227569Sphilip 537227569Sphilip if (EFX_OWORD_FIELD(fatal, FRF_AZ_TBUF_OWN_INT_KER) != 0) 538227569Sphilip EFSYS_ERR(enp->en_esip, EFX_ERR_TBUF_OWN, 0, 0); 539227569Sphilip 540227569Sphilip if (EFX_OWORD_FIELD(fatal, FRF_AZ_RDESCQ_OWN_INT_KER) != 0) 541227569Sphilip EFSYS_ERR(enp->en_esip, EFX_ERR_RDESQ_OWN, 0, 0); 542227569Sphilip 543227569Sphilip if (EFX_OWORD_FIELD(fatal, FRF_AZ_TDESCQ_OWN_INT_KER) != 0) 544227569Sphilip EFSYS_ERR(enp->en_esip, EFX_ERR_TDESQ_OWN, 0, 0); 545227569Sphilip 546227569Sphilip if (EFX_OWORD_FIELD(fatal, FRF_AZ_EVQ_OWN_INT_KER) != 0) 547227569Sphilip EFSYS_ERR(enp->en_esip, EFX_ERR_EVQ_OWN, 0, 0); 548227569Sphilip 549227569Sphilip if (EFX_OWORD_FIELD(fatal, FRF_AZ_EVF_OFLO_INT_KER) != 0) 550227569Sphilip EFSYS_ERR(enp->en_esip, EFX_ERR_EVFF_OFLO, 0, 0); 551227569Sphilip 552227569Sphilip if (EFX_OWORD_FIELD(fatal, FRF_AZ_ILL_ADR_INT_KER) != 0) 553227569Sphilip EFSYS_ERR(enp->en_esip, EFX_ERR_ILL_ADDR, 0, 0); 554227569Sphilip 555227569Sphilip if (EFX_OWORD_FIELD(fatal, FRF_AZ_SRM_PERR_INT_KER) != 0) 556227569Sphilip EFSYS_ERR(enp->en_esip, EFX_ERR_SRAM_PERR, 557227569Sphilip EFX_OWORD_FIELD(mem_per, EFX_DWORD_0), 558227569Sphilip EFX_OWORD_FIELD(mem_per, EFX_DWORD_1)); 559227569Sphilip#else 560227569Sphilip EFSYS_ASSERT(0); 561227569Sphilip#endif 562227569Sphilip} 563227569Sphilip 564283514Sarybchikstatic void 565299608Sarybchiksiena_intr_fini( 566227569Sphilip __in efx_nic_t *enp) 567227569Sphilip{ 568227569Sphilip efx_oword_t oword; 569227569Sphilip 570227569Sphilip /* Clear the interrupt address register */ 571227569Sphilip EFX_ZERO_OWORD(oword); 572227569Sphilip EFX_BAR_WRITEO(enp, FR_AZ_INT_ADR_REG_KER, &oword); 573283514Sarybchik} 574227569Sphilip 575299320Sarybchik#endif /* EFSYS_OPT_SIENA */ 576