1 /*- 2 * Copyright 2007-2009 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 <sys/cdefs.h> 27 __FBSDID("$FreeBSD$"); 28 29 #include "efsys.h" 30 #include "efx.h" 31 #include "efx_types.h" 32 #include "efx_regs.h" 33 #include "efx_impl.h" 34 35 __checkReturn int 36 efx_intr_init( 37 __in efx_nic_t *enp, 38 __in efx_intr_type_t type, 39 __in efsys_mem_t *esmp) 40 { 41 efx_intr_t *eip = &(enp->en_intr); 42 efx_oword_t oword; 43 int rc; 44 45 EFSYS_ASSERT3U(enp->en_magic, ==, EFX_NIC_MAGIC); 46 EFSYS_ASSERT3U(enp->en_mod_flags, &, EFX_MOD_NIC); 47 48 if (enp->en_mod_flags & EFX_MOD_INTR) { 49 rc = EINVAL; 50 goto fail1; 51 } 52 53 enp->en_mod_flags |= EFX_MOD_INTR; 54 55 eip->ei_type = type; 56 eip->ei_esmp = esmp; 57 58 /* 59 * bug17213 workaround. 60 * 61 * Under legacy interrupts, don't share a level between fatal 62 * interrupts and event queue interrupts. Under MSI-X, they 63 * must share, or we won't get an interrupt. 64 */ 65 if (enp->en_family == EFX_FAMILY_SIENA && 66 eip->ei_type == EFX_INTR_LINE) 67 eip->ei_level = 0x1f; 68 else 69 eip->ei_level = 0; 70 71 /* Enable all the genuinely fatal interrupts */ 72 EFX_SET_OWORD(oword); 73 EFX_SET_OWORD_FIELD(oword, FRF_AZ_ILL_ADR_INT_KER_EN, 0); 74 EFX_SET_OWORD_FIELD(oword, FRF_AZ_RBUF_OWN_INT_KER_EN, 0); 75 EFX_SET_OWORD_FIELD(oword, FRF_AZ_TBUF_OWN_INT_KER_EN, 0); 76 if (enp->en_family >= EFX_FAMILY_SIENA) 77 EFX_SET_OWORD_FIELD(oword, FRF_CZ_SRAM_PERR_INT_P_KER_EN, 0); 78 EFX_BAR_WRITEO(enp, FR_AZ_FATAL_INTR_REG_KER, &oword); 79 80 /* Set up the interrupt address register */ 81 EFX_POPULATE_OWORD_3(oword, 82 FRF_AZ_NORM_INT_VEC_DIS_KER, (type == EFX_INTR_MESSAGE) ? 1 : 0, 83 FRF_AZ_INT_ADR_KER_DW0, EFSYS_MEM_ADDR(esmp) & 0xffffffff, 84 FRF_AZ_INT_ADR_KER_DW1, EFSYS_MEM_ADDR(esmp) >> 32); 85 EFX_BAR_WRITEO(enp, FR_AZ_INT_ADR_REG_KER, &oword); 86 87 return (0); 88 89 fail1: 90 EFSYS_PROBE1(fail1, int, rc); 91 92 return (rc); 93 } 94 95 void 96 efx_intr_enable( 97 __in efx_nic_t *enp) 98 { 99 efx_intr_t *eip = &(enp->en_intr); 100 efx_oword_t oword; 101 102 EFSYS_ASSERT3U(enp->en_magic, ==, EFX_NIC_MAGIC); 103 EFSYS_ASSERT3U(enp->en_mod_flags, &, EFX_MOD_INTR); 104 105 EFX_BAR_READO(enp, FR_AZ_INT_EN_REG_KER, &oword); 106 107 EFX_SET_OWORD_FIELD(oword, FRF_AZ_KER_INT_LEVE_SEL, eip->ei_level); 108 EFX_SET_OWORD_FIELD(oword, FRF_AZ_DRV_INT_EN_KER, 1); 109 EFX_BAR_WRITEO(enp, FR_AZ_INT_EN_REG_KER, &oword); 110 } 111 112 void 113 efx_intr_disable( 114 __in efx_nic_t *enp) 115 { 116 efx_oword_t oword; 117 118 EFSYS_ASSERT3U(enp->en_magic, ==, EFX_NIC_MAGIC); 119 EFSYS_ASSERT3U(enp->en_mod_flags, &, EFX_MOD_INTR); 120 121 EFX_BAR_READO(enp, FR_AZ_INT_EN_REG_KER, &oword); 122 EFX_SET_OWORD_FIELD(oword, FRF_AZ_DRV_INT_EN_KER, 0); 123 EFX_BAR_WRITEO(enp, FR_AZ_INT_EN_REG_KER, &oword); 124 125 EFSYS_SPIN(10); 126 } 127 128 void 129 efx_intr_disable_unlocked( 130 __in efx_nic_t *enp) 131 { 132 efx_oword_t oword; 133 134 EFSYS_ASSERT3U(enp->en_magic, ==, EFX_NIC_MAGIC); 135 EFSYS_ASSERT3U(enp->en_mod_flags, &, EFX_MOD_INTR); 136 137 EFSYS_BAR_READO(enp->en_esbp, FR_AZ_INT_EN_REG_KER_OFST, 138 &oword, B_FALSE); 139 EFX_SET_OWORD_FIELD(oword, FRF_AZ_DRV_INT_EN_KER, 0); 140 EFSYS_BAR_WRITEO(enp->en_esbp, FR_AZ_INT_EN_REG_KER_OFST, 141 &oword, B_FALSE); 142 } 143 144 __checkReturn int 145 efx_intr_trigger( 146 __in efx_nic_t *enp, 147 __in unsigned int level) 148 { 149 efx_intr_t *eip = &(enp->en_intr); 150 efx_oword_t oword; 151 unsigned int count; 152 uint32_t sel; 153 int rc; 154 155 EFSYS_ASSERT3U(enp->en_magic, ==, EFX_NIC_MAGIC); 156 EFSYS_ASSERT3U(enp->en_mod_flags, &, EFX_MOD_INTR); 157 158 /* bug16757: No event queues can be initialized */ 159 EFSYS_ASSERT(!(enp->en_mod_flags & EFX_MOD_EV)); 160 161 switch (enp->en_family) { 162 case EFX_FAMILY_FALCON: 163 if (level > EFX_NINTR_FALCON) { 164 rc = EINVAL; 165 goto fail1; 166 } 167 break; 168 169 case EFX_FAMILY_SIENA: 170 if (level > EFX_NINTR_SIENA) { 171 rc = EINVAL; 172 goto fail1; 173 } 174 break; 175 176 default: 177 EFSYS_ASSERT(B_FALSE); 178 break; 179 } 180 181 if (level > EFX_MASK32(FRF_AZ_KER_INT_LEVE_SEL)) 182 return (ENOTSUP); /* avoid EFSYS_PROBE() */ 183 184 sel = level; 185 186 /* Trigger a test interrupt */ 187 EFX_BAR_READO(enp, FR_AZ_INT_EN_REG_KER, &oword); 188 EFX_SET_OWORD_FIELD(oword, FRF_AZ_KER_INT_LEVE_SEL, sel); 189 EFX_SET_OWORD_FIELD(oword, FRF_AZ_KER_INT_KER, 1); 190 EFX_BAR_WRITEO(enp, FR_AZ_INT_EN_REG_KER, &oword); 191 192 /* 193 * Wait up to 100ms for the interrupt to be raised before restoring 194 * KER_INT_LEVE_SEL. Ignore a failure to raise (the caller will 195 * observe this soon enough anyway), but always reset KER_INT_LEVE_SEL 196 */ 197 count = 0; 198 do { 199 EFSYS_SPIN(100); /* 100us */ 200 201 EFX_BAR_READO(enp, FR_AZ_INT_EN_REG_KER, &oword); 202 } while (EFX_OWORD_FIELD(oword, FRF_AZ_KER_INT_KER) && ++count < 1000); 203 204 EFX_SET_OWORD_FIELD(oword, FRF_AZ_KER_INT_LEVE_SEL, eip->ei_level); 205 EFX_BAR_WRITEO(enp, FR_AZ_INT_EN_REG_KER, &oword); 206 207 return (0); 208 209 fail1: 210 EFSYS_PROBE1(fail1, int, rc); 211 212 return (rc); 213 } 214 215 static __checkReturn boolean_t 216 efx_intr_check_fatal( 217 __in efx_nic_t *enp) 218 { 219 efx_intr_t *eip = &(enp->en_intr); 220 efsys_mem_t *esmp = eip->ei_esmp; 221 efx_oword_t oword; 222 223 /* Read the syndrome */ 224 EFSYS_MEM_READO(esmp, 0, &oword); 225 226 if (EFX_OWORD_FIELD(oword, FSF_AZ_NET_IVEC_FATAL_INT) != 0) { 227 EFSYS_PROBE(fatal); 228 229 /* Clear the fatal interrupt condition */ 230 EFX_SET_OWORD_FIELD(oword, FSF_AZ_NET_IVEC_FATAL_INT, 0); 231 EFSYS_MEM_WRITEO(esmp, 0, &oword); 232 233 return (B_TRUE); 234 } 235 236 return (B_FALSE); 237 } 238 239 void 240 efx_intr_status_line( 241 __in efx_nic_t *enp, 242 __out boolean_t *fatalp, 243 __out uint32_t *qmaskp) 244 { 245 efx_intr_t *eip = &(enp->en_intr); 246 efx_dword_t dword; 247 248 EFSYS_ASSERT3U(enp->en_magic, ==, EFX_NIC_MAGIC); 249 EFSYS_ASSERT3U(enp->en_mod_flags, &, EFX_MOD_INTR); 250 251 /* 252 * Read the queue mask and implicitly acknowledge the 253 * interrupt. 254 */ 255 EFX_BAR_READD(enp, FR_BZ_INT_ISR0_REG, &dword, B_FALSE); 256 *qmaskp = EFX_DWORD_FIELD(dword, EFX_DWORD_0); 257 258 EFSYS_PROBE1(qmask, uint32_t, *qmaskp); 259 260 if (*qmaskp & (1U << eip->ei_level)) 261 *fatalp = efx_intr_check_fatal(enp); 262 else 263 *fatalp = B_FALSE; 264 } 265 266 void 267 efx_intr_status_message( 268 __in efx_nic_t *enp, 269 __in unsigned int message, 270 __out boolean_t *fatalp) 271 { 272 efx_intr_t *eip = &(enp->en_intr); 273 274 EFSYS_ASSERT3U(enp->en_magic, ==, EFX_NIC_MAGIC); 275 EFSYS_ASSERT3U(enp->en_mod_flags, &, EFX_MOD_INTR); 276 277 if (message == eip->ei_level) 278 *fatalp = efx_intr_check_fatal(enp); 279 else 280 *fatalp = B_FALSE; 281 } 282 283 void 284 efx_intr_fatal( 285 __in efx_nic_t *enp) 286 { 287 #if EFSYS_OPT_DECODE_INTR_FATAL 288 efx_oword_t fatal; 289 efx_oword_t mem_per; 290 291 EFSYS_ASSERT3U(enp->en_magic, ==, EFX_NIC_MAGIC); 292 EFSYS_ASSERT3U(enp->en_mod_flags, &, EFX_MOD_INTR); 293 294 EFX_BAR_READO(enp, FR_AZ_FATAL_INTR_REG_KER, &fatal); 295 EFX_ZERO_OWORD(mem_per); 296 297 if (EFX_OWORD_FIELD(fatal, FRF_AZ_SRM_PERR_INT_KER) != 0 || 298 EFX_OWORD_FIELD(fatal, FRF_AZ_MEM_PERR_INT_KER) != 0) 299 EFX_BAR_READO(enp, FR_AZ_MEM_STAT_REG, &mem_per); 300 301 if (EFX_OWORD_FIELD(fatal, FRF_AZ_SRAM_OOB_INT_KER) != 0) 302 EFSYS_ERR(enp->en_esip, EFX_ERR_SRAM_OOB, 0, 0); 303 304 if (EFX_OWORD_FIELD(fatal, FRF_AZ_BUFID_DC_OOB_INT_KER) != 0) 305 EFSYS_ERR(enp->en_esip, EFX_ERR_BUFID_DC_OOB, 0, 0); 306 307 if (EFX_OWORD_FIELD(fatal, FRF_AZ_MEM_PERR_INT_KER) != 0) 308 EFSYS_ERR(enp->en_esip, EFX_ERR_MEM_PERR, 309 EFX_OWORD_FIELD(mem_per, EFX_DWORD_0), 310 EFX_OWORD_FIELD(mem_per, EFX_DWORD_1)); 311 312 if (EFX_OWORD_FIELD(fatal, FRF_AZ_RBUF_OWN_INT_KER) != 0) 313 EFSYS_ERR(enp->en_esip, EFX_ERR_RBUF_OWN, 0, 0); 314 315 if (EFX_OWORD_FIELD(fatal, FRF_AZ_TBUF_OWN_INT_KER) != 0) 316 EFSYS_ERR(enp->en_esip, EFX_ERR_TBUF_OWN, 0, 0); 317 318 if (EFX_OWORD_FIELD(fatal, FRF_AZ_RDESCQ_OWN_INT_KER) != 0) 319 EFSYS_ERR(enp->en_esip, EFX_ERR_RDESQ_OWN, 0, 0); 320 321 if (EFX_OWORD_FIELD(fatal, FRF_AZ_TDESCQ_OWN_INT_KER) != 0) 322 EFSYS_ERR(enp->en_esip, EFX_ERR_TDESQ_OWN, 0, 0); 323 324 if (EFX_OWORD_FIELD(fatal, FRF_AZ_EVQ_OWN_INT_KER) != 0) 325 EFSYS_ERR(enp->en_esip, EFX_ERR_EVQ_OWN, 0, 0); 326 327 if (EFX_OWORD_FIELD(fatal, FRF_AZ_EVF_OFLO_INT_KER) != 0) 328 EFSYS_ERR(enp->en_esip, EFX_ERR_EVFF_OFLO, 0, 0); 329 330 if (EFX_OWORD_FIELD(fatal, FRF_AZ_ILL_ADR_INT_KER) != 0) 331 EFSYS_ERR(enp->en_esip, EFX_ERR_ILL_ADDR, 0, 0); 332 333 if (EFX_OWORD_FIELD(fatal, FRF_AZ_SRM_PERR_INT_KER) != 0) 334 EFSYS_ERR(enp->en_esip, EFX_ERR_SRAM_PERR, 335 EFX_OWORD_FIELD(mem_per, EFX_DWORD_0), 336 EFX_OWORD_FIELD(mem_per, EFX_DWORD_1)); 337 #else 338 EFSYS_ASSERT(0); 339 #endif 340 } 341 342 void 343 efx_intr_fini( 344 __in efx_nic_t *enp) 345 { 346 efx_oword_t oword; 347 348 EFSYS_ASSERT3U(enp->en_magic, ==, EFX_NIC_MAGIC); 349 EFSYS_ASSERT3U(enp->en_mod_flags, &, EFX_MOD_NIC); 350 EFSYS_ASSERT3U(enp->en_mod_flags, &, EFX_MOD_INTR); 351 352 /* Clear the interrupt address register */ 353 EFX_ZERO_OWORD(oword); 354 EFX_BAR_WRITEO(enp, FR_AZ_INT_ADR_REG_KER, &oword); 355 356 enp->en_mod_flags &= ~EFX_MOD_INTR; 357 } 358