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 }