2 * Copyright (c) 2007-2015 Solarflare Communications Inc.
5 * Redistribution and use in source and binary forms, with or without
6 * modification, are permitted provided that the following conditions are met:
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.
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.
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.
31 #include <sys/cdefs.h>
32 __FBSDID("$FreeBSD$");
38 #if EFSYS_OPT_FALCON || EFSYS_OPT_SIENA
40 static __checkReturn efx_rc_t
41 falconsiena_intr_init(
43 __in efx_intr_type_t type,
44 __in efsys_mem_t *esmp);
47 falconsiena_intr_enable(
51 falconsiena_intr_disable(
55 falconsiena_intr_disable_unlocked(
58 static __checkReturn efx_rc_t
59 falconsiena_intr_trigger(
61 __in unsigned int level);
64 falconsiena_intr_fini(
68 falconsiena_intr_status_line(
70 __out boolean_t *fatalp,
71 __out uint32_t *qmaskp);
74 falconsiena_intr_status_message(
76 __in unsigned int message,
77 __out boolean_t *fatalp);
80 falconsiena_intr_fatal(
83 static __checkReturn boolean_t
84 falconsiena_intr_check_fatal(
88 #endif /* EFSYS_OPT_FALCON || EFSYS_OPT_SIENA */
92 static efx_intr_ops_t __efx_intr_falcon_ops = {
93 falconsiena_intr_init, /* eio_init */
94 falconsiena_intr_enable, /* eio_enable */
95 falconsiena_intr_disable, /* eio_disable */
96 falconsiena_intr_disable_unlocked, /* eio_disable_unlocked */
97 falconsiena_intr_trigger, /* eio_trigger */
98 falconsiena_intr_status_line, /* eio_status_line */
99 falconsiena_intr_status_message, /* eio_status_message */
100 falconsiena_intr_fatal, /* eio_fatal */
101 falconsiena_intr_fini, /* eio_fini */
103 #endif /* EFSYS_OPT_FALCON */
106 static efx_intr_ops_t __efx_intr_siena_ops = {
107 falconsiena_intr_init, /* eio_init */
108 falconsiena_intr_enable, /* eio_enable */
109 falconsiena_intr_disable, /* eio_disable */
110 falconsiena_intr_disable_unlocked, /* eio_disable_unlocked */
111 falconsiena_intr_trigger, /* eio_trigger */
112 falconsiena_intr_status_line, /* eio_status_line */
113 falconsiena_intr_status_message, /* eio_status_message */
114 falconsiena_intr_fatal, /* eio_fatal */
115 falconsiena_intr_fini, /* eio_fini */
117 #endif /* EFSYS_OPT_SIENA */
119 #if EFSYS_OPT_HUNTINGTON || EFSYS_OPT_MEDFORD
120 static efx_intr_ops_t __efx_intr_ef10_ops = {
121 ef10_intr_init, /* eio_init */
122 ef10_intr_enable, /* eio_enable */
123 ef10_intr_disable, /* eio_disable */
124 ef10_intr_disable_unlocked, /* eio_disable_unlocked */
125 ef10_intr_trigger, /* eio_trigger */
126 ef10_intr_status_line, /* eio_status_line */
127 ef10_intr_status_message, /* eio_status_message */
128 ef10_intr_fatal, /* eio_fatal */
129 ef10_intr_fini, /* eio_fini */
131 #endif /* EFSYS_OPT_HUNTINGTON || EFSYS_OPT_MEDFORD */
133 __checkReturn efx_rc_t
136 __in efx_intr_type_t type,
137 __in efsys_mem_t *esmp)
139 efx_intr_t *eip = &(enp->en_intr);
140 efx_intr_ops_t *eiop;
143 EFSYS_ASSERT3U(enp->en_magic, ==, EFX_NIC_MAGIC);
144 EFSYS_ASSERT3U(enp->en_mod_flags, &, EFX_MOD_NIC);
146 if (enp->en_mod_flags & EFX_MOD_INTR) {
155 enp->en_mod_flags |= EFX_MOD_INTR;
157 switch (enp->en_family) {
159 case EFX_FAMILY_FALCON:
160 eiop = (efx_intr_ops_t *)&__efx_intr_falcon_ops;
162 #endif /* EFSYS_OPT_FALCON */
165 case EFX_FAMILY_SIENA:
166 eiop = (efx_intr_ops_t *)&__efx_intr_siena_ops;
168 #endif /* EFSYS_OPT_SIENA */
170 #if EFSYS_OPT_HUNTINGTON
171 case EFX_FAMILY_HUNTINGTON:
172 eiop = (efx_intr_ops_t *)&__efx_intr_ef10_ops;
174 #endif /* EFSYS_OPT_HUNTINGTON */
176 #if EFSYS_OPT_MEDFORD
177 case EFX_FAMILY_MEDFORD:
178 eiop = (efx_intr_ops_t *)&__efx_intr_ef10_ops;
180 #endif /* EFSYS_OPT_MEDFORD */
183 EFSYS_ASSERT(B_FALSE);
188 if ((rc = eiop->eio_init(enp, type, esmp)) != 0)
200 EFSYS_PROBE1(fail1, efx_rc_t, rc);
209 efx_intr_t *eip = &(enp->en_intr);
210 efx_intr_ops_t *eiop = eip->ei_eiop;
212 EFSYS_ASSERT3U(enp->en_magic, ==, EFX_NIC_MAGIC);
213 EFSYS_ASSERT3U(enp->en_mod_flags, &, EFX_MOD_NIC);
214 EFSYS_ASSERT3U(enp->en_mod_flags, &, EFX_MOD_INTR);
218 enp->en_mod_flags &= ~EFX_MOD_INTR;
225 efx_intr_t *eip = &(enp->en_intr);
226 efx_intr_ops_t *eiop = eip->ei_eiop;
228 EFSYS_ASSERT3U(enp->en_magic, ==, EFX_NIC_MAGIC);
229 EFSYS_ASSERT3U(enp->en_mod_flags, &, EFX_MOD_INTR);
231 eiop->eio_enable(enp);
238 efx_intr_t *eip = &(enp->en_intr);
239 efx_intr_ops_t *eiop = eip->ei_eiop;
241 EFSYS_ASSERT3U(enp->en_magic, ==, EFX_NIC_MAGIC);
242 EFSYS_ASSERT3U(enp->en_mod_flags, &, EFX_MOD_INTR);
244 eiop->eio_disable(enp);
248 efx_intr_disable_unlocked(
251 efx_intr_t *eip = &(enp->en_intr);
252 efx_intr_ops_t *eiop = eip->ei_eiop;
254 EFSYS_ASSERT3U(enp->en_magic, ==, EFX_NIC_MAGIC);
255 EFSYS_ASSERT3U(enp->en_mod_flags, &, EFX_MOD_INTR);
257 eiop->eio_disable_unlocked(enp);
261 __checkReturn efx_rc_t
264 __in unsigned int level)
266 efx_intr_t *eip = &(enp->en_intr);
267 efx_intr_ops_t *eiop = eip->ei_eiop;
269 EFSYS_ASSERT3U(enp->en_magic, ==, EFX_NIC_MAGIC);
270 EFSYS_ASSERT3U(enp->en_mod_flags, &, EFX_MOD_INTR);
272 return (eiop->eio_trigger(enp, level));
276 efx_intr_status_line(
278 __out boolean_t *fatalp,
279 __out uint32_t *qmaskp)
281 efx_intr_t *eip = &(enp->en_intr);
282 efx_intr_ops_t *eiop = eip->ei_eiop;
284 EFSYS_ASSERT3U(enp->en_magic, ==, EFX_NIC_MAGIC);
285 EFSYS_ASSERT3U(enp->en_mod_flags, &, EFX_MOD_INTR);
287 eiop->eio_status_line(enp, fatalp, qmaskp);
291 efx_intr_status_message(
293 __in unsigned int message,
294 __out boolean_t *fatalp)
296 efx_intr_t *eip = &(enp->en_intr);
297 efx_intr_ops_t *eiop = eip->ei_eiop;
299 EFSYS_ASSERT3U(enp->en_magic, ==, EFX_NIC_MAGIC);
300 EFSYS_ASSERT3U(enp->en_mod_flags, &, EFX_MOD_INTR);
302 eiop->eio_status_message(enp, message, fatalp);
309 efx_intr_t *eip = &(enp->en_intr);
310 efx_intr_ops_t *eiop = eip->ei_eiop;
312 EFSYS_ASSERT3U(enp->en_magic, ==, EFX_NIC_MAGIC);
313 EFSYS_ASSERT3U(enp->en_mod_flags, &, EFX_MOD_INTR);
315 eiop->eio_fatal(enp);
319 /* ************************************************************************* */
320 /* ************************************************************************* */
321 /* ************************************************************************* */
323 #if EFSYS_OPT_FALCON || EFSYS_OPT_SIENA
325 static __checkReturn efx_rc_t
326 falconsiena_intr_init(
328 __in efx_intr_type_t type,
329 __in efsys_mem_t *esmp)
331 efx_intr_t *eip = &(enp->en_intr);
335 * bug17213 workaround.
337 * Under legacy interrupts, don't share a level between fatal
338 * interrupts and event queue interrupts. Under MSI-X, they
339 * must share, or we won't get an interrupt.
341 if (enp->en_family == EFX_FAMILY_SIENA &&
342 eip->ei_type == EFX_INTR_LINE)
343 eip->ei_level = 0x1f;
347 /* Enable all the genuinely fatal interrupts */
348 EFX_SET_OWORD(oword);
349 EFX_SET_OWORD_FIELD(oword, FRF_AZ_ILL_ADR_INT_KER_EN, 0);
350 EFX_SET_OWORD_FIELD(oword, FRF_AZ_RBUF_OWN_INT_KER_EN, 0);
351 EFX_SET_OWORD_FIELD(oword, FRF_AZ_TBUF_OWN_INT_KER_EN, 0);
352 if (enp->en_family >= EFX_FAMILY_SIENA)
353 EFX_SET_OWORD_FIELD(oword, FRF_CZ_SRAM_PERR_INT_P_KER_EN, 0);
354 EFX_BAR_WRITEO(enp, FR_AZ_FATAL_INTR_REG_KER, &oword);
356 /* Set up the interrupt address register */
357 EFX_POPULATE_OWORD_3(oword,
358 FRF_AZ_NORM_INT_VEC_DIS_KER, (type == EFX_INTR_MESSAGE) ? 1 : 0,
359 FRF_AZ_INT_ADR_KER_DW0, EFSYS_MEM_ADDR(esmp) & 0xffffffff,
360 FRF_AZ_INT_ADR_KER_DW1, EFSYS_MEM_ADDR(esmp) >> 32);
361 EFX_BAR_WRITEO(enp, FR_AZ_INT_ADR_REG_KER, &oword);
367 falconsiena_intr_enable(
370 efx_intr_t *eip = &(enp->en_intr);
373 EFX_BAR_READO(enp, FR_AZ_INT_EN_REG_KER, &oword);
375 EFX_SET_OWORD_FIELD(oword, FRF_AZ_KER_INT_LEVE_SEL, eip->ei_level);
376 EFX_SET_OWORD_FIELD(oword, FRF_AZ_DRV_INT_EN_KER, 1);
377 EFX_BAR_WRITEO(enp, FR_AZ_INT_EN_REG_KER, &oword);
381 falconsiena_intr_disable(
386 EFX_BAR_READO(enp, FR_AZ_INT_EN_REG_KER, &oword);
387 EFX_SET_OWORD_FIELD(oword, FRF_AZ_DRV_INT_EN_KER, 0);
388 EFX_BAR_WRITEO(enp, FR_AZ_INT_EN_REG_KER, &oword);
394 falconsiena_intr_disable_unlocked(
399 EFSYS_BAR_READO(enp->en_esbp, FR_AZ_INT_EN_REG_KER_OFST,
401 EFX_SET_OWORD_FIELD(oword, FRF_AZ_DRV_INT_EN_KER, 0);
402 EFSYS_BAR_WRITEO(enp->en_esbp, FR_AZ_INT_EN_REG_KER_OFST,
406 static __checkReturn efx_rc_t
407 falconsiena_intr_trigger(
409 __in unsigned int level)
411 efx_intr_t *eip = &(enp->en_intr);
417 /* bug16757: No event queues can be initialized */
418 EFSYS_ASSERT(!(enp->en_mod_flags & EFX_MOD_EV));
420 switch (enp->en_family) {
421 case EFX_FAMILY_FALCON:
422 if (level >= EFX_NINTR_FALCON) {
428 case EFX_FAMILY_SIENA:
429 if (level >= EFX_NINTR_SIENA) {
436 EFSYS_ASSERT(B_FALSE);
440 if (level > EFX_MASK32(FRF_AZ_KER_INT_LEVE_SEL))
441 return (ENOTSUP); /* avoid EFSYS_PROBE() */
445 /* Trigger a test interrupt */
446 EFX_BAR_READO(enp, FR_AZ_INT_EN_REG_KER, &oword);
447 EFX_SET_OWORD_FIELD(oword, FRF_AZ_KER_INT_LEVE_SEL, sel);
448 EFX_SET_OWORD_FIELD(oword, FRF_AZ_KER_INT_KER, 1);
449 EFX_BAR_WRITEO(enp, FR_AZ_INT_EN_REG_KER, &oword);
452 * Wait up to 100ms for the interrupt to be raised before restoring
453 * KER_INT_LEVE_SEL. Ignore a failure to raise (the caller will
454 * observe this soon enough anyway), but always reset KER_INT_LEVE_SEL
458 EFSYS_SPIN(100); /* 100us */
460 EFX_BAR_READO(enp, FR_AZ_INT_EN_REG_KER, &oword);
461 } while (EFX_OWORD_FIELD(oword, FRF_AZ_KER_INT_KER) && ++count < 1000);
463 EFX_SET_OWORD_FIELD(oword, FRF_AZ_KER_INT_LEVE_SEL, eip->ei_level);
464 EFX_BAR_WRITEO(enp, FR_AZ_INT_EN_REG_KER, &oword);
469 EFSYS_PROBE1(fail1, efx_rc_t, rc);
474 static __checkReturn boolean_t
475 falconsiena_intr_check_fatal(
478 efx_intr_t *eip = &(enp->en_intr);
479 efsys_mem_t *esmp = eip->ei_esmp;
482 /* Read the syndrome */
483 EFSYS_MEM_READO(esmp, 0, &oword);
485 if (EFX_OWORD_FIELD(oword, FSF_AZ_NET_IVEC_FATAL_INT) != 0) {
488 /* Clear the fatal interrupt condition */
489 EFX_SET_OWORD_FIELD(oword, FSF_AZ_NET_IVEC_FATAL_INT, 0);
490 EFSYS_MEM_WRITEO(esmp, 0, &oword);
499 falconsiena_intr_status_line(
501 __out boolean_t *fatalp,
502 __out uint32_t *qmaskp)
504 efx_intr_t *eip = &(enp->en_intr);
507 EFSYS_ASSERT3U(enp->en_magic, ==, EFX_NIC_MAGIC);
508 EFSYS_ASSERT3U(enp->en_mod_flags, &, EFX_MOD_INTR);
511 * Read the queue mask and implicitly acknowledge the
514 EFX_BAR_READD(enp, FR_BZ_INT_ISR0_REG, &dword, B_FALSE);
515 *qmaskp = EFX_DWORD_FIELD(dword, EFX_DWORD_0);
517 EFSYS_PROBE1(qmask, uint32_t, *qmaskp);
519 if (*qmaskp & (1U << eip->ei_level))
520 *fatalp = falconsiena_intr_check_fatal(enp);
526 falconsiena_intr_status_message(
528 __in unsigned int message,
529 __out boolean_t *fatalp)
531 efx_intr_t *eip = &(enp->en_intr);
533 EFSYS_ASSERT3U(enp->en_magic, ==, EFX_NIC_MAGIC);
534 EFSYS_ASSERT3U(enp->en_mod_flags, &, EFX_MOD_INTR);
536 if (message == eip->ei_level)
537 *fatalp = falconsiena_intr_check_fatal(enp);
544 falconsiena_intr_fatal(
547 #if EFSYS_OPT_DECODE_INTR_FATAL
551 EFX_BAR_READO(enp, FR_AZ_FATAL_INTR_REG_KER, &fatal);
552 EFX_ZERO_OWORD(mem_per);
554 if (EFX_OWORD_FIELD(fatal, FRF_AZ_SRM_PERR_INT_KER) != 0 ||
555 EFX_OWORD_FIELD(fatal, FRF_AZ_MEM_PERR_INT_KER) != 0)
556 EFX_BAR_READO(enp, FR_AZ_MEM_STAT_REG, &mem_per);
558 if (EFX_OWORD_FIELD(fatal, FRF_AZ_SRAM_OOB_INT_KER) != 0)
559 EFSYS_ERR(enp->en_esip, EFX_ERR_SRAM_OOB, 0, 0);
561 if (EFX_OWORD_FIELD(fatal, FRF_AZ_BUFID_DC_OOB_INT_KER) != 0)
562 EFSYS_ERR(enp->en_esip, EFX_ERR_BUFID_DC_OOB, 0, 0);
564 if (EFX_OWORD_FIELD(fatal, FRF_AZ_MEM_PERR_INT_KER) != 0)
565 EFSYS_ERR(enp->en_esip, EFX_ERR_MEM_PERR,
566 EFX_OWORD_FIELD(mem_per, EFX_DWORD_0),
567 EFX_OWORD_FIELD(mem_per, EFX_DWORD_1));
569 if (EFX_OWORD_FIELD(fatal, FRF_AZ_RBUF_OWN_INT_KER) != 0)
570 EFSYS_ERR(enp->en_esip, EFX_ERR_RBUF_OWN, 0, 0);
572 if (EFX_OWORD_FIELD(fatal, FRF_AZ_TBUF_OWN_INT_KER) != 0)
573 EFSYS_ERR(enp->en_esip, EFX_ERR_TBUF_OWN, 0, 0);
575 if (EFX_OWORD_FIELD(fatal, FRF_AZ_RDESCQ_OWN_INT_KER) != 0)
576 EFSYS_ERR(enp->en_esip, EFX_ERR_RDESQ_OWN, 0, 0);
578 if (EFX_OWORD_FIELD(fatal, FRF_AZ_TDESCQ_OWN_INT_KER) != 0)
579 EFSYS_ERR(enp->en_esip, EFX_ERR_TDESQ_OWN, 0, 0);
581 if (EFX_OWORD_FIELD(fatal, FRF_AZ_EVQ_OWN_INT_KER) != 0)
582 EFSYS_ERR(enp->en_esip, EFX_ERR_EVQ_OWN, 0, 0);
584 if (EFX_OWORD_FIELD(fatal, FRF_AZ_EVF_OFLO_INT_KER) != 0)
585 EFSYS_ERR(enp->en_esip, EFX_ERR_EVFF_OFLO, 0, 0);
587 if (EFX_OWORD_FIELD(fatal, FRF_AZ_ILL_ADR_INT_KER) != 0)
588 EFSYS_ERR(enp->en_esip, EFX_ERR_ILL_ADDR, 0, 0);
590 if (EFX_OWORD_FIELD(fatal, FRF_AZ_SRM_PERR_INT_KER) != 0)
591 EFSYS_ERR(enp->en_esip, EFX_ERR_SRAM_PERR,
592 EFX_OWORD_FIELD(mem_per, EFX_DWORD_0),
593 EFX_OWORD_FIELD(mem_per, EFX_DWORD_1));
600 falconsiena_intr_fini(
605 /* Clear the interrupt address register */
606 EFX_ZERO_OWORD(oword);
607 EFX_BAR_WRITEO(enp, FR_AZ_INT_ADR_REG_KER, &oword);
610 #endif /* EFSYS_OPT_FALCON || EFSYS_OPT_SIENA */