1 /*
   2  * Copyright 2007-2013 Solarflare Communications Inc.  All rights reserved.
   3  *
   4  * Redistribution and use in source and binary forms, with or without
   5  * modification, are permitted provided that the following conditions
   6  * are met:
   7  * 1. Redistributions of source code must retain the above copyright
   8  *    notice, this list of conditions and the following disclaimer.
   9  * 2. Redistributions in binary form must reproduce the above copyright
  10  *    notice, this list of conditions and the following disclaimer in the
  11  *    documentation and/or other materials provided with the distribution.
  12  *
  13  * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS AND
  14  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
  15  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
  16  * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
  17  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
  18  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
  19  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
  20  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
  21  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
  22  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
  23  * SUCH DAMAGE.
  24  */
  25 
  26 #include "efsys.h"
  27 #include "efx.h"
  28 #include "efx_types.h"
  29 #include "efx_regs.h"
  30 #include "efx_impl.h"
  31 
  32         __checkReturn   int
  33 efx_intr_init(
  34         __in            efx_nic_t *enp,
  35         __in            efx_intr_type_t type,
  36         __in            efsys_mem_t *esmp)
  37 {
  38         efx_intr_t *eip = &(enp->en_intr);
  39         efx_oword_t oword;
  40         int rc;
  41 
  42         EFSYS_ASSERT3U(enp->en_magic, ==, EFX_NIC_MAGIC);
  43         EFSYS_ASSERT3U(enp->en_mod_flags, &, EFX_MOD_NIC);
  44 
  45         if (enp->en_mod_flags & EFX_MOD_INTR) {
  46                 rc = EINVAL;
  47                 goto fail1;
  48         }
  49 
  50         enp->en_mod_flags |= EFX_MOD_INTR;
  51 
  52         eip->ei_type = type;
  53         eip->ei_esmp = esmp;
  54 
  55         /*
  56          * bug17213 workaround.
  57          *
  58          * Under legacy interrupts, don't share a level between fatal
  59          * interrupts and event queue interrupts. Under MSI-X, they
  60          * must share, or we won't get an interrupt.
  61          */
  62         if (enp->en_family == EFX_FAMILY_SIENA &&
  63             eip->ei_type == EFX_INTR_LINE)
  64                 eip->ei_level = 0x1f;
  65         else
  66                 eip->ei_level = 0;
  67 
  68         /* Enable all the genuinely fatal interrupts */
  69         EFX_SET_OWORD(oword);
  70         EFX_SET_OWORD_FIELD(oword, FRF_AZ_ILL_ADR_INT_KER_EN, 0);
  71         EFX_SET_OWORD_FIELD(oword, FRF_AZ_RBUF_OWN_INT_KER_EN, 0);
  72         EFX_SET_OWORD_FIELD(oword, FRF_AZ_TBUF_OWN_INT_KER_EN, 0);
  73         if (enp->en_family >= EFX_FAMILY_SIENA)
  74                 EFX_SET_OWORD_FIELD(oword, FRF_CZ_SRAM_PERR_INT_P_KER_EN, 0);
  75         EFX_BAR_WRITEO(enp, FR_AZ_FATAL_INTR_REG_KER, &oword);
  76 
  77         /* Set up the interrupt address register */
  78         EFX_POPULATE_OWORD_3(oword,
  79             FRF_AZ_NORM_INT_VEC_DIS_KER, (type == EFX_INTR_MESSAGE) ? 1 : 0,
  80             FRF_AZ_INT_ADR_KER_DW0, EFSYS_MEM_ADDR(esmp) & 0xffffffff,
  81             FRF_AZ_INT_ADR_KER_DW1, EFSYS_MEM_ADDR(esmp) >> 32);
  82         EFX_BAR_WRITEO(enp, FR_AZ_INT_ADR_REG_KER, &oword);
  83 
  84         return (0);
  85 
  86 fail1:
  87         EFSYS_PROBE1(fail1, int, rc);
  88 
  89         return (rc);
  90 }
  91 
  92                         void
  93 efx_intr_enable(
  94         __in            efx_nic_t *enp)
  95 {
  96         efx_intr_t *eip = &(enp->en_intr);
  97         efx_oword_t oword;
  98 
  99         EFSYS_ASSERT3U(enp->en_magic, ==, EFX_NIC_MAGIC);
 100         EFSYS_ASSERT3U(enp->en_mod_flags, &, EFX_MOD_INTR);
 101 
 102         EFX_BAR_READO(enp, FR_AZ_INT_EN_REG_KER, &oword);
 103 
 104         EFX_SET_OWORD_FIELD(oword, FRF_AZ_KER_INT_LEVE_SEL, eip->ei_level);
 105         EFX_SET_OWORD_FIELD(oword, FRF_AZ_DRV_INT_EN_KER, 1);
 106         EFX_BAR_WRITEO(enp, FR_AZ_INT_EN_REG_KER, &oword);
 107 }
 108 
 109                         void
 110 efx_intr_disable(
 111         __in            efx_nic_t *enp)
 112 {
 113         efx_oword_t oword;
 114 
 115         EFSYS_ASSERT3U(enp->en_magic, ==, EFX_NIC_MAGIC);
 116         EFSYS_ASSERT3U(enp->en_mod_flags, &, EFX_MOD_INTR);
 117 
 118         EFX_BAR_READO(enp, FR_AZ_INT_EN_REG_KER, &oword);
 119         EFX_SET_OWORD_FIELD(oword, FRF_AZ_DRV_INT_EN_KER, 0);
 120         EFX_BAR_WRITEO(enp, FR_AZ_INT_EN_REG_KER, &oword);
 121 
 122         EFSYS_SPIN(10);
 123 }
 124 
 125                         void
 126 efx_intr_disable_unlocked(
 127         __in            efx_nic_t *enp)
 128 {
 129         efx_oword_t oword;
 130 
 131         EFSYS_ASSERT3U(enp->en_magic, ==, EFX_NIC_MAGIC);
 132         EFSYS_ASSERT3U(enp->en_mod_flags, &, EFX_MOD_INTR);
 133 
 134         EFSYS_BAR_READO(enp->en_esbp, FR_AZ_INT_EN_REG_KER_OFST,
 135                         &oword, B_FALSE);
 136         EFX_SET_OWORD_FIELD(oword, FRF_AZ_DRV_INT_EN_KER, 0);
 137         EFSYS_BAR_WRITEO(enp->en_esbp, FR_AZ_INT_EN_REG_KER_OFST,
 138             &oword, B_FALSE);
 139 }
 140 
 141         __checkReturn   int
 142 efx_intr_trigger(
 143         __in            efx_nic_t *enp,
 144         __in            unsigned int level)
 145 {
 146         efx_intr_t *eip = &(enp->en_intr);
 147         efx_oword_t oword;
 148         unsigned int count;
 149         uint32_t sel;
 150         int rc;
 151 
 152         EFSYS_ASSERT3U(enp->en_magic, ==, EFX_NIC_MAGIC);
 153         EFSYS_ASSERT3U(enp->en_mod_flags, &, EFX_MOD_INTR);
 154 
 155         /* bug16757: No event queues can be initialized */
 156         EFSYS_ASSERT(!(enp->en_mod_flags & EFX_MOD_EV));
 157 
 158         switch (enp->en_family) {
 159         case EFX_FAMILY_FALCON:
 160                 if (level > EFX_NINTR_FALCON) {
 161                         rc = EINVAL;
 162                         goto fail1;
 163                 }
 164                 break;
 165 
 166         case EFX_FAMILY_SIENA:
 167                 if (level > EFX_NINTR_SIENA) {
 168                         rc = EINVAL;
 169                         goto fail1;
 170                 }
 171                 break;
 172 
 173         default:
 174                 EFSYS_ASSERT(B_FALSE);
 175                 break;
 176         }
 177 
 178         if (level > EFX_MASK32(FRF_AZ_KER_INT_LEVE_SEL))
 179                 return (ENOTSUP); /* avoid EFSYS_PROBE() */
 180 
 181         sel = level;
 182 
 183         /* Trigger a test interrupt */
 184         EFX_BAR_READO(enp, FR_AZ_INT_EN_REG_KER, &oword);
 185         EFX_SET_OWORD_FIELD(oword, FRF_AZ_KER_INT_LEVE_SEL, sel);
 186         EFX_SET_OWORD_FIELD(oword, FRF_AZ_KER_INT_KER, 1);
 187         EFX_BAR_WRITEO(enp, FR_AZ_INT_EN_REG_KER, &oword);
 188 
 189         /*
 190          * Wait up to 100ms for the interrupt to be raised before restoring
 191          * KER_INT_LEVE_SEL. Ignore a failure to raise (the caller will
 192          * observe this soon enough anyway), but always reset KER_INT_LEVE_SEL
 193          */
 194         count = 0;
 195         do {
 196                 EFSYS_SPIN(100);        /* 100us */
 197 
 198                 EFX_BAR_READO(enp, FR_AZ_INT_EN_REG_KER, &oword);
 199         } while (EFX_OWORD_FIELD(oword, FRF_AZ_KER_INT_KER) && ++count < 1000);
 200 
 201         EFX_SET_OWORD_FIELD(oword, FRF_AZ_KER_INT_LEVE_SEL, eip->ei_level);
 202         EFX_BAR_WRITEO(enp, FR_AZ_INT_EN_REG_KER, &oword);
 203 
 204         return (0);
 205 
 206 fail1:
 207         EFSYS_PROBE1(fail1, int, rc);
 208 
 209         return (rc);
 210 }
 211 
 212 static  __checkReturn   boolean_t
 213 efx_intr_check_fatal(
 214         __in            efx_nic_t *enp)
 215 {
 216         efx_intr_t *eip = &(enp->en_intr);
 217         efsys_mem_t *esmp = eip->ei_esmp;
 218         efx_oword_t oword;
 219 
 220         /* Read the syndrome */
 221         EFSYS_MEM_READO(esmp, 0, &oword);
 222 
 223         if (EFX_OWORD_FIELD(oword, FSF_AZ_NET_IVEC_FATAL_INT) != 0) {
 224                 EFSYS_PROBE(fatal);
 225 
 226                 /* Clear the fatal interrupt condition */
 227                 EFX_SET_OWORD_FIELD(oword, FSF_AZ_NET_IVEC_FATAL_INT, 0);
 228                 EFSYS_MEM_WRITEO(esmp, 0, &oword);
 229 
 230                 return (B_TRUE);
 231         }
 232 
 233         return (B_FALSE);
 234 }
 235 
 236                         void
 237 efx_intr_status_line(
 238         __in            efx_nic_t *enp,
 239         __out           boolean_t *fatalp,
 240         __out           uint32_t *qmaskp)
 241 {
 242         efx_intr_t *eip = &(enp->en_intr);
 243         efx_dword_t dword;
 244 
 245         EFSYS_ASSERT3U(enp->en_magic, ==, EFX_NIC_MAGIC);
 246         EFSYS_ASSERT3U(enp->en_mod_flags, &, EFX_MOD_INTR);
 247 
 248         /*
 249          * Read the queue mask and implicitly acknowledge the
 250          * interrupt.
 251          */
 252         EFX_BAR_READD(enp, FR_BZ_INT_ISR0_REG, &dword, B_FALSE);
 253         *qmaskp = EFX_DWORD_FIELD(dword, EFX_DWORD_0);
 254 
 255         EFSYS_PROBE1(qmask, uint32_t, *qmaskp);
 256 
 257         if (*qmaskp & (1U << eip->ei_level))
 258                 *fatalp = efx_intr_check_fatal(enp);
 259         else
 260                 *fatalp = B_FALSE;
 261 }
 262 
 263                         void
 264 efx_intr_status_message(
 265         __in            efx_nic_t *enp,
 266         __in            unsigned int message,
 267         __out           boolean_t *fatalp)
 268 {
 269         efx_intr_t *eip = &(enp->en_intr);
 270 
 271         EFSYS_ASSERT3U(enp->en_magic, ==, EFX_NIC_MAGIC);
 272         EFSYS_ASSERT3U(enp->en_mod_flags, &, EFX_MOD_INTR);
 273 
 274         if (message == eip->ei_level)
 275                 *fatalp = efx_intr_check_fatal(enp);
 276         else
 277                 *fatalp = B_FALSE;
 278 }
 279 
 280                 void
 281 efx_intr_fatal(
 282         __in    efx_nic_t *enp)
 283 {
 284 #if EFSYS_OPT_DECODE_INTR_FATAL
 285         efx_oword_t fatal;
 286         efx_oword_t mem_per;
 287 
 288         EFSYS_ASSERT3U(enp->en_magic, ==, EFX_NIC_MAGIC);
 289         EFSYS_ASSERT3U(enp->en_mod_flags, &, EFX_MOD_INTR);
 290 
 291         EFX_BAR_READO(enp, FR_AZ_FATAL_INTR_REG_KER, &fatal);
 292         EFX_ZERO_OWORD(mem_per);
 293 
 294         if (EFX_OWORD_FIELD(fatal, FRF_AZ_SRM_PERR_INT_KER) != 0 ||
 295             EFX_OWORD_FIELD(fatal, FRF_AZ_MEM_PERR_INT_KER) != 0)
 296                 EFX_BAR_READO(enp, FR_AZ_MEM_STAT_REG, &mem_per);
 297 
 298         if (EFX_OWORD_FIELD(fatal, FRF_AZ_SRAM_OOB_INT_KER) != 0)
 299                 EFSYS_ERR(enp->en_esip, EFX_ERR_SRAM_OOB, 0, 0);
 300 
 301         if (EFX_OWORD_FIELD(fatal, FRF_AZ_BUFID_DC_OOB_INT_KER) != 0)
 302                 EFSYS_ERR(enp->en_esip, EFX_ERR_BUFID_DC_OOB, 0, 0);
 303 
 304         if (EFX_OWORD_FIELD(fatal, FRF_AZ_MEM_PERR_INT_KER) != 0)
 305                 EFSYS_ERR(enp->en_esip, EFX_ERR_MEM_PERR,
 306                     EFX_OWORD_FIELD(mem_per, EFX_DWORD_0),
 307                     EFX_OWORD_FIELD(mem_per, EFX_DWORD_1));
 308 
 309         if (EFX_OWORD_FIELD(fatal, FRF_AZ_RBUF_OWN_INT_KER) != 0)
 310                 EFSYS_ERR(enp->en_esip, EFX_ERR_RBUF_OWN, 0, 0);
 311 
 312         if (EFX_OWORD_FIELD(fatal, FRF_AZ_TBUF_OWN_INT_KER) != 0)
 313                 EFSYS_ERR(enp->en_esip, EFX_ERR_TBUF_OWN, 0, 0);
 314 
 315         if (EFX_OWORD_FIELD(fatal, FRF_AZ_RDESCQ_OWN_INT_KER) != 0)
 316                 EFSYS_ERR(enp->en_esip, EFX_ERR_RDESQ_OWN, 0, 0);
 317 
 318         if (EFX_OWORD_FIELD(fatal, FRF_AZ_TDESCQ_OWN_INT_KER) != 0)
 319                 EFSYS_ERR(enp->en_esip, EFX_ERR_TDESQ_OWN, 0, 0);
 320 
 321         if (EFX_OWORD_FIELD(fatal, FRF_AZ_EVQ_OWN_INT_KER) != 0)
 322                 EFSYS_ERR(enp->en_esip, EFX_ERR_EVQ_OWN, 0, 0);
 323 
 324         if (EFX_OWORD_FIELD(fatal, FRF_AZ_EVF_OFLO_INT_KER) != 0)
 325                 EFSYS_ERR(enp->en_esip, EFX_ERR_EVFF_OFLO, 0, 0);
 326 
 327         if (EFX_OWORD_FIELD(fatal, FRF_AZ_ILL_ADR_INT_KER) != 0)
 328                 EFSYS_ERR(enp->en_esip, EFX_ERR_ILL_ADDR, 0, 0);
 329 
 330         if (EFX_OWORD_FIELD(fatal, FRF_AZ_SRM_PERR_INT_KER) != 0)
 331                 EFSYS_ERR(enp->en_esip, EFX_ERR_SRAM_PERR,
 332                     EFX_OWORD_FIELD(mem_per, EFX_DWORD_0),
 333                     EFX_OWORD_FIELD(mem_per, EFX_DWORD_1));
 334 #else
 335         EFSYS_ASSERT(0);
 336 #endif
 337 }
 338 
 339                 void
 340 efx_intr_fini(
 341         __in    efx_nic_t *enp)
 342 {
 343         efx_oword_t oword;
 344 
 345         EFSYS_ASSERT3U(enp->en_magic, ==, EFX_NIC_MAGIC);
 346         EFSYS_ASSERT3U(enp->en_mod_flags, &, EFX_MOD_NIC);
 347         EFSYS_ASSERT3U(enp->en_mod_flags, &, EFX_MOD_INTR);
 348 
 349         /* Clear the interrupt address register */
 350         EFX_ZERO_OWORD(oword);
 351         EFX_BAR_WRITEO(enp, FR_AZ_INT_ADR_REG_KER, &oword);
 352 
 353         enp->en_mod_flags &= ~EFX_MOD_INTR;
 354 }