1/*-
2 * Copyright (c) 2007-2015 Solarflare Communications Inc.
3 * All rights reserved.
4 *
5 * Redistribution and use in source and binary forms, with or without
6 * modification, are permitted provided that the following conditions are met:
7 *
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.
13 *
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.
25 *
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.
29 */
30
31#include <sys/cdefs.h>
32__FBSDID("$FreeBSD: head/sys/dev/sfxge/common/efx_intr.c 293814 2016-01-13 07:25:51Z arybchik $");
33
34#include "efx.h"
35#include "efx_impl.h"
36
37
38#if EFSYS_OPT_FALCON || EFSYS_OPT_SIENA
39
40static __checkReturn efx_rc_t
41falconsiena_intr_init(
42 __in efx_nic_t *enp,
43 __in efx_intr_type_t type,
44 __in efsys_mem_t *esmp);
45
46static void
47falconsiena_intr_enable(
48 __in efx_nic_t *enp);
49
50static void
51falconsiena_intr_disable(
52 __in efx_nic_t *enp);
53
54static void
55falconsiena_intr_disable_unlocked(
56 __in efx_nic_t *enp);
57
58static __checkReturn efx_rc_t
59falconsiena_intr_trigger(
60 __in efx_nic_t *enp,
61 __in unsigned int level);
62
63static void
64falconsiena_intr_fini(
65 __in efx_nic_t *enp);
66
67static void
68falconsiena_intr_status_line(
69 __in efx_nic_t *enp,
70 __out boolean_t *fatalp,
71 __out uint32_t *qmaskp);
72
73static void
74falconsiena_intr_status_message(
75 __in efx_nic_t *enp,
76 __in unsigned int message,
77 __out boolean_t *fatalp);
78
79static void
80falconsiena_intr_fatal(
81 __in efx_nic_t *enp);
82
83static __checkReturn boolean_t
84falconsiena_intr_check_fatal(
85 __in efx_nic_t *enp);
86
87
88#endif /* EFSYS_OPT_FALCON || EFSYS_OPT_SIENA */
89
90
91#if EFSYS_OPT_FALCON
92static 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 */
102};
103#endif /* EFSYS_OPT_FALCON */
104
105#if EFSYS_OPT_SIENA
106static 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 */
116};
117#endif /* EFSYS_OPT_SIENA */
118
119#if EFSYS_OPT_HUNTINGTON || EFSYS_OPT_MEDFORD
120static 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 */
130};
131#endif /* EFSYS_OPT_HUNTINGTON || EFSYS_OPT_MEDFORD */
132
133 __checkReturn efx_rc_t
134efx_intr_init(
135 __in efx_nic_t *enp,
136 __in efx_intr_type_t type,
137 __in efsys_mem_t *esmp)
138{
139 efx_intr_t *eip = &(enp->en_intr);
140 efx_intr_ops_t *eiop;
141 efx_rc_t rc;
142
143 EFSYS_ASSERT3U(enp->en_magic, ==, EFX_NIC_MAGIC);
144 EFSYS_ASSERT3U(enp->en_mod_flags, &, EFX_MOD_NIC);
145
146 if (enp->en_mod_flags & EFX_MOD_INTR) {
147 rc = EINVAL;
148 goto fail1;
149 }
150
151 eip->ei_esmp = esmp;
152 eip->ei_type = type;
153 eip->ei_level = 0;
154
155 enp->en_mod_flags |= EFX_MOD_INTR;
156
157 switch (enp->en_family) {
158#if EFSYS_OPT_FALCON
159 case EFX_FAMILY_FALCON:
160 eiop = (efx_intr_ops_t *)&__efx_intr_falcon_ops;
161 break;
162#endif /* EFSYS_OPT_FALCON */
163
164#if EFSYS_OPT_SIENA
165 case EFX_FAMILY_SIENA:
166 eiop = (efx_intr_ops_t *)&__efx_intr_siena_ops;
167 break;
168#endif /* EFSYS_OPT_SIENA */
169
170#if EFSYS_OPT_HUNTINGTON
171 case EFX_FAMILY_HUNTINGTON:
172 eiop = (efx_intr_ops_t *)&__efx_intr_ef10_ops;
173 break;
174#endif /* EFSYS_OPT_HUNTINGTON */
175
176#if EFSYS_OPT_MEDFORD
177 case EFX_FAMILY_MEDFORD:
178 eiop = (efx_intr_ops_t *)&__efx_intr_ef10_ops;
179 break;
180#endif /* EFSYS_OPT_MEDFORD */
181
182 default:
183 EFSYS_ASSERT(B_FALSE);
184 rc = ENOTSUP;
185 goto fail2;
186 }
187
188 if ((rc = eiop->eio_init(enp, type, esmp)) != 0)
189 goto fail3;
190
191 eip->ei_eiop = eiop;
192
193 return (0);
194
195fail3:
196 EFSYS_PROBE(fail3);
197fail2:
198 EFSYS_PROBE(fail2);
199fail1:
200 EFSYS_PROBE1(fail1, efx_rc_t, rc);
201
202 return (rc);
203}
204
205 void
206efx_intr_fini(
207 __in efx_nic_t *enp)
208{
209 efx_intr_t *eip = &(enp->en_intr);
210 efx_intr_ops_t *eiop = eip->ei_eiop;
211
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);
215
216 eiop->eio_fini(enp);
217
218 enp->en_mod_flags &= ~EFX_MOD_INTR;
219}
220
221 void
222efx_intr_enable(
223 __in efx_nic_t *enp)
224{
225 efx_intr_t *eip = &(enp->en_intr);
226 efx_intr_ops_t *eiop = eip->ei_eiop;
227
228 EFSYS_ASSERT3U(enp->en_magic, ==, EFX_NIC_MAGIC);
229 EFSYS_ASSERT3U(enp->en_mod_flags, &, EFX_MOD_INTR);
230
231 eiop->eio_enable(enp);
232}
233
234 void
235efx_intr_disable(
236 __in efx_nic_t *enp)
237{
238 efx_intr_t *eip = &(enp->en_intr);
239 efx_intr_ops_t *eiop = eip->ei_eiop;
240
241 EFSYS_ASSERT3U(enp->en_magic, ==, EFX_NIC_MAGIC);
242 EFSYS_ASSERT3U(enp->en_mod_flags, &, EFX_MOD_INTR);
243
244 eiop->eio_disable(enp);
245}
246
247 void
248efx_intr_disable_unlocked(
249 __in efx_nic_t *enp)
250{
251 efx_intr_t *eip = &(enp->en_intr);
252 efx_intr_ops_t *eiop = eip->ei_eiop;
253
254 EFSYS_ASSERT3U(enp->en_magic, ==, EFX_NIC_MAGIC);
255 EFSYS_ASSERT3U(enp->en_mod_flags, &, EFX_MOD_INTR);
256
257 eiop->eio_disable_unlocked(enp);
258}
259
260
261 __checkReturn efx_rc_t
262efx_intr_trigger(
263 __in efx_nic_t *enp,
264 __in unsigned int level)
265{
266 efx_intr_t *eip = &(enp->en_intr);
267 efx_intr_ops_t *eiop = eip->ei_eiop;
268
269 EFSYS_ASSERT3U(enp->en_magic, ==, EFX_NIC_MAGIC);
270 EFSYS_ASSERT3U(enp->en_mod_flags, &, EFX_MOD_INTR);
271
272 return (eiop->eio_trigger(enp, level));
273}
274
275 void
276efx_intr_status_line(
277 __in efx_nic_t *enp,
278 __out boolean_t *fatalp,
279 __out uint32_t *qmaskp)
280{
281 efx_intr_t *eip = &(enp->en_intr);
282 efx_intr_ops_t *eiop = eip->ei_eiop;
283
284 EFSYS_ASSERT3U(enp->en_magic, ==, EFX_NIC_MAGIC);
285 EFSYS_ASSERT3U(enp->en_mod_flags, &, EFX_MOD_INTR);
286
287 eiop->eio_status_line(enp, fatalp, qmaskp);
288}
289
290 void
291efx_intr_status_message(
292 __in efx_nic_t *enp,
293 __in unsigned int message,
294 __out boolean_t *fatalp)
295{
296 efx_intr_t *eip = &(enp->en_intr);
297 efx_intr_ops_t *eiop = eip->ei_eiop;
298
299 EFSYS_ASSERT3U(enp->en_magic, ==, EFX_NIC_MAGIC);
300 EFSYS_ASSERT3U(enp->en_mod_flags, &, EFX_MOD_INTR);
301
302 eiop->eio_status_message(enp, message, fatalp);
303}
304
305 void
306efx_intr_fatal(
307 __in efx_nic_t *enp)
308{
309 efx_intr_t *eip = &(enp->en_intr);
310 efx_intr_ops_t *eiop = eip->ei_eiop;
311
312 EFSYS_ASSERT3U(enp->en_magic, ==, EFX_NIC_MAGIC);
313 EFSYS_ASSERT3U(enp->en_mod_flags, &, EFX_MOD_INTR);
314
315 eiop->eio_fatal(enp);
316}
317
318
319/* ************************************************************************* */
320/* ************************************************************************* */
321/* ************************************************************************* */
322
323#if EFSYS_OPT_FALCON || EFSYS_OPT_SIENA
324
325static __checkReturn efx_rc_t
326falconsiena_intr_init(
327 __in efx_nic_t *enp,
328 __in efx_intr_type_t type,
329 __in efsys_mem_t *esmp)
330{
331 efx_intr_t *eip = &(enp->en_intr);
332 efx_oword_t oword;
333
334 /*
335 * bug17213 workaround.
336 *
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.
340 */
341 if (enp->en_family == EFX_FAMILY_SIENA &&
342 eip->ei_type == EFX_INTR_LINE)
343 eip->ei_level = 0x1f;
344 else
345 eip->ei_level = 0;
346
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);
355
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);
362
363 return (0);
364}
365
366static void
367falconsiena_intr_enable(
368 __in efx_nic_t *enp)
369{
370 efx_intr_t *eip = &(enp->en_intr);
371 efx_oword_t oword;
372
373 EFX_BAR_READO(enp, FR_AZ_INT_EN_REG_KER, &oword);
374
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);
378}
379
380static void
381falconsiena_intr_disable(
382 __in efx_nic_t *enp)
383{
384 efx_oword_t oword;
385
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);
389
390 EFSYS_SPIN(10);
391}
392
393static void
394falconsiena_intr_disable_unlocked(
395 __in efx_nic_t *enp)
396{
397 efx_oword_t oword;
398
399 EFSYS_BAR_READO(enp->en_esbp, FR_AZ_INT_EN_REG_KER_OFST,
400 &oword, B_FALSE);
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,
403 &oword, B_FALSE);
404}
405
406static __checkReturn efx_rc_t
407falconsiena_intr_trigger(
408 __in efx_nic_t *enp,
409 __in unsigned int level)
410{
411 efx_intr_t *eip = &(enp->en_intr);
412 efx_oword_t oword;
413 unsigned int count;
414 uint32_t sel;
415 efx_rc_t rc;
416
417 /* bug16757: No event queues can be initialized */
418 EFSYS_ASSERT(!(enp->en_mod_flags & EFX_MOD_EV));
419
420 switch (enp->en_family) {
421 case EFX_FAMILY_FALCON:
422 if (level >= EFX_NINTR_FALCON) {
423 rc = EINVAL;
424 goto fail1;
425 }
426 break;
427
428 case EFX_FAMILY_SIENA:
429 if (level >= EFX_NINTR_SIENA) {
430 rc = EINVAL;
431 goto fail1;
432 }
433 break;
434
435 default:
436 EFSYS_ASSERT(B_FALSE);
437 break;
438 }
439
440 if (level > EFX_MASK32(FRF_AZ_KER_INT_LEVE_SEL))
441 return (ENOTSUP); /* avoid EFSYS_PROBE() */
442
443 sel = level;
444
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);
450
451 /*
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
455 */
456 count = 0;
457 do {
458 EFSYS_SPIN(100); /* 100us */
459
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);
462
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);
465
466 return (0);
467
468fail1:
469 EFSYS_PROBE1(fail1, efx_rc_t, rc);
470
471 return (rc);
472}
473
474static __checkReturn boolean_t
475falconsiena_intr_check_fatal(
476 __in efx_nic_t *enp)
477{
478 efx_intr_t *eip = &(enp->en_intr);
479 efsys_mem_t *esmp = eip->ei_esmp;
480 efx_oword_t oword;
481
482 /* Read the syndrome */
483 EFSYS_MEM_READO(esmp, 0, &oword);
484
485 if (EFX_OWORD_FIELD(oword, FSF_AZ_NET_IVEC_FATAL_INT) != 0) {
486 EFSYS_PROBE(fatal);
487
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);
491
492 return (B_TRUE);
493 }
494
495 return (B_FALSE);
496}
497
498static void
499falconsiena_intr_status_line(
500 __in efx_nic_t *enp,
501 __out boolean_t *fatalp,
502 __out uint32_t *qmaskp)
503{
504 efx_intr_t *eip = &(enp->en_intr);
505 efx_dword_t dword;
506
507 EFSYS_ASSERT3U(enp->en_magic, ==, EFX_NIC_MAGIC);
508 EFSYS_ASSERT3U(enp->en_mod_flags, &, EFX_MOD_INTR);
509
510 /*
511 * Read the queue mask and implicitly acknowledge the
512 * interrupt.
513 */
514 EFX_BAR_READD(enp, FR_BZ_INT_ISR0_REG, &dword, B_FALSE);
515 *qmaskp = EFX_DWORD_FIELD(dword, EFX_DWORD_0);
516
517 EFSYS_PROBE1(qmask, uint32_t, *qmaskp);
518
519 if (*qmaskp & (1U << eip->ei_level))
520 *fatalp = falconsiena_intr_check_fatal(enp);
521 else
522 *fatalp = B_FALSE;
523}
524
525static void
526falconsiena_intr_status_message(
527 __in efx_nic_t *enp,
528 __in unsigned int message,
529 __out boolean_t *fatalp)
530{
531 efx_intr_t *eip = &(enp->en_intr);
532
533 EFSYS_ASSERT3U(enp->en_magic, ==, EFX_NIC_MAGIC);
534 EFSYS_ASSERT3U(enp->en_mod_flags, &, EFX_MOD_INTR);
535
536 if (message == eip->ei_level)
537 *fatalp = falconsiena_intr_check_fatal(enp);
538 else
539 *fatalp = B_FALSE;
540}
541
542
543static void
544falconsiena_intr_fatal(
545 __in efx_nic_t *enp)
546{
547#if EFSYS_OPT_DECODE_INTR_FATAL
548 efx_oword_t fatal;
549 efx_oword_t mem_per;
550
551 EFX_BAR_READO(enp, FR_AZ_FATAL_INTR_REG_KER, &fatal);
552 EFX_ZERO_OWORD(mem_per);
553
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);
557
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);
560
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);
563
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));
568
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);
571
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);
574
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);
577
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);
580
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);
583
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);
586
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);
589
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));
594#else
595 EFSYS_ASSERT(0);
596#endif
597}
598
599static void
600falconsiena_intr_fini(
601 __in efx_nic_t *enp)
602{
603 efx_oword_t oword;
604
605 /* Clear the interrupt address register */
606 EFX_ZERO_OWORD(oword);
607 EFX_BAR_WRITEO(enp, FR_AZ_INT_ADR_REG_KER, &oword);
608}
609
610#endif /* EFSYS_OPT_FALCON || EFSYS_OPT_SIENA */
2 * Copyright (c) 2007-2015 Solarflare Communications Inc.
3 * All rights reserved.
4 *
5 * Redistribution and use in source and binary forms, with or without
6 * modification, are permitted provided that the following conditions are met:
7 *
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.
13 *
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.
25 *
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.
29 */
30
31#include <sys/cdefs.h>
32__FBSDID("$FreeBSD: head/sys/dev/sfxge/common/efx_intr.c 293814 2016-01-13 07:25:51Z arybchik $");
33
34#include "efx.h"
35#include "efx_impl.h"
36
37
38#if EFSYS_OPT_FALCON || EFSYS_OPT_SIENA
39
40static __checkReturn efx_rc_t
41falconsiena_intr_init(
42 __in efx_nic_t *enp,
43 __in efx_intr_type_t type,
44 __in efsys_mem_t *esmp);
45
46static void
47falconsiena_intr_enable(
48 __in efx_nic_t *enp);
49
50static void
51falconsiena_intr_disable(
52 __in efx_nic_t *enp);
53
54static void
55falconsiena_intr_disable_unlocked(
56 __in efx_nic_t *enp);
57
58static __checkReturn efx_rc_t
59falconsiena_intr_trigger(
60 __in efx_nic_t *enp,
61 __in unsigned int level);
62
63static void
64falconsiena_intr_fini(
65 __in efx_nic_t *enp);
66
67static void
68falconsiena_intr_status_line(
69 __in efx_nic_t *enp,
70 __out boolean_t *fatalp,
71 __out uint32_t *qmaskp);
72
73static void
74falconsiena_intr_status_message(
75 __in efx_nic_t *enp,
76 __in unsigned int message,
77 __out boolean_t *fatalp);
78
79static void
80falconsiena_intr_fatal(
81 __in efx_nic_t *enp);
82
83static __checkReturn boolean_t
84falconsiena_intr_check_fatal(
85 __in efx_nic_t *enp);
86
87
88#endif /* EFSYS_OPT_FALCON || EFSYS_OPT_SIENA */
89
90
91#if EFSYS_OPT_FALCON
92static 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 */
102};
103#endif /* EFSYS_OPT_FALCON */
104
105#if EFSYS_OPT_SIENA
106static 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 */
116};
117#endif /* EFSYS_OPT_SIENA */
118
119#if EFSYS_OPT_HUNTINGTON || EFSYS_OPT_MEDFORD
120static 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 */
130};
131#endif /* EFSYS_OPT_HUNTINGTON || EFSYS_OPT_MEDFORD */
132
133 __checkReturn efx_rc_t
134efx_intr_init(
135 __in efx_nic_t *enp,
136 __in efx_intr_type_t type,
137 __in efsys_mem_t *esmp)
138{
139 efx_intr_t *eip = &(enp->en_intr);
140 efx_intr_ops_t *eiop;
141 efx_rc_t rc;
142
143 EFSYS_ASSERT3U(enp->en_magic, ==, EFX_NIC_MAGIC);
144 EFSYS_ASSERT3U(enp->en_mod_flags, &, EFX_MOD_NIC);
145
146 if (enp->en_mod_flags & EFX_MOD_INTR) {
147 rc = EINVAL;
148 goto fail1;
149 }
150
151 eip->ei_esmp = esmp;
152 eip->ei_type = type;
153 eip->ei_level = 0;
154
155 enp->en_mod_flags |= EFX_MOD_INTR;
156
157 switch (enp->en_family) {
158#if EFSYS_OPT_FALCON
159 case EFX_FAMILY_FALCON:
160 eiop = (efx_intr_ops_t *)&__efx_intr_falcon_ops;
161 break;
162#endif /* EFSYS_OPT_FALCON */
163
164#if EFSYS_OPT_SIENA
165 case EFX_FAMILY_SIENA:
166 eiop = (efx_intr_ops_t *)&__efx_intr_siena_ops;
167 break;
168#endif /* EFSYS_OPT_SIENA */
169
170#if EFSYS_OPT_HUNTINGTON
171 case EFX_FAMILY_HUNTINGTON:
172 eiop = (efx_intr_ops_t *)&__efx_intr_ef10_ops;
173 break;
174#endif /* EFSYS_OPT_HUNTINGTON */
175
176#if EFSYS_OPT_MEDFORD
177 case EFX_FAMILY_MEDFORD:
178 eiop = (efx_intr_ops_t *)&__efx_intr_ef10_ops;
179 break;
180#endif /* EFSYS_OPT_MEDFORD */
181
182 default:
183 EFSYS_ASSERT(B_FALSE);
184 rc = ENOTSUP;
185 goto fail2;
186 }
187
188 if ((rc = eiop->eio_init(enp, type, esmp)) != 0)
189 goto fail3;
190
191 eip->ei_eiop = eiop;
192
193 return (0);
194
195fail3:
196 EFSYS_PROBE(fail3);
197fail2:
198 EFSYS_PROBE(fail2);
199fail1:
200 EFSYS_PROBE1(fail1, efx_rc_t, rc);
201
202 return (rc);
203}
204
205 void
206efx_intr_fini(
207 __in efx_nic_t *enp)
208{
209 efx_intr_t *eip = &(enp->en_intr);
210 efx_intr_ops_t *eiop = eip->ei_eiop;
211
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);
215
216 eiop->eio_fini(enp);
217
218 enp->en_mod_flags &= ~EFX_MOD_INTR;
219}
220
221 void
222efx_intr_enable(
223 __in efx_nic_t *enp)
224{
225 efx_intr_t *eip = &(enp->en_intr);
226 efx_intr_ops_t *eiop = eip->ei_eiop;
227
228 EFSYS_ASSERT3U(enp->en_magic, ==, EFX_NIC_MAGIC);
229 EFSYS_ASSERT3U(enp->en_mod_flags, &, EFX_MOD_INTR);
230
231 eiop->eio_enable(enp);
232}
233
234 void
235efx_intr_disable(
236 __in efx_nic_t *enp)
237{
238 efx_intr_t *eip = &(enp->en_intr);
239 efx_intr_ops_t *eiop = eip->ei_eiop;
240
241 EFSYS_ASSERT3U(enp->en_magic, ==, EFX_NIC_MAGIC);
242 EFSYS_ASSERT3U(enp->en_mod_flags, &, EFX_MOD_INTR);
243
244 eiop->eio_disable(enp);
245}
246
247 void
248efx_intr_disable_unlocked(
249 __in efx_nic_t *enp)
250{
251 efx_intr_t *eip = &(enp->en_intr);
252 efx_intr_ops_t *eiop = eip->ei_eiop;
253
254 EFSYS_ASSERT3U(enp->en_magic, ==, EFX_NIC_MAGIC);
255 EFSYS_ASSERT3U(enp->en_mod_flags, &, EFX_MOD_INTR);
256
257 eiop->eio_disable_unlocked(enp);
258}
259
260
261 __checkReturn efx_rc_t
262efx_intr_trigger(
263 __in efx_nic_t *enp,
264 __in unsigned int level)
265{
266 efx_intr_t *eip = &(enp->en_intr);
267 efx_intr_ops_t *eiop = eip->ei_eiop;
268
269 EFSYS_ASSERT3U(enp->en_magic, ==, EFX_NIC_MAGIC);
270 EFSYS_ASSERT3U(enp->en_mod_flags, &, EFX_MOD_INTR);
271
272 return (eiop->eio_trigger(enp, level));
273}
274
275 void
276efx_intr_status_line(
277 __in efx_nic_t *enp,
278 __out boolean_t *fatalp,
279 __out uint32_t *qmaskp)
280{
281 efx_intr_t *eip = &(enp->en_intr);
282 efx_intr_ops_t *eiop = eip->ei_eiop;
283
284 EFSYS_ASSERT3U(enp->en_magic, ==, EFX_NIC_MAGIC);
285 EFSYS_ASSERT3U(enp->en_mod_flags, &, EFX_MOD_INTR);
286
287 eiop->eio_status_line(enp, fatalp, qmaskp);
288}
289
290 void
291efx_intr_status_message(
292 __in efx_nic_t *enp,
293 __in unsigned int message,
294 __out boolean_t *fatalp)
295{
296 efx_intr_t *eip = &(enp->en_intr);
297 efx_intr_ops_t *eiop = eip->ei_eiop;
298
299 EFSYS_ASSERT3U(enp->en_magic, ==, EFX_NIC_MAGIC);
300 EFSYS_ASSERT3U(enp->en_mod_flags, &, EFX_MOD_INTR);
301
302 eiop->eio_status_message(enp, message, fatalp);
303}
304
305 void
306efx_intr_fatal(
307 __in efx_nic_t *enp)
308{
309 efx_intr_t *eip = &(enp->en_intr);
310 efx_intr_ops_t *eiop = eip->ei_eiop;
311
312 EFSYS_ASSERT3U(enp->en_magic, ==, EFX_NIC_MAGIC);
313 EFSYS_ASSERT3U(enp->en_mod_flags, &, EFX_MOD_INTR);
314
315 eiop->eio_fatal(enp);
316}
317
318
319/* ************************************************************************* */
320/* ************************************************************************* */
321/* ************************************************************************* */
322
323#if EFSYS_OPT_FALCON || EFSYS_OPT_SIENA
324
325static __checkReturn efx_rc_t
326falconsiena_intr_init(
327 __in efx_nic_t *enp,
328 __in efx_intr_type_t type,
329 __in efsys_mem_t *esmp)
330{
331 efx_intr_t *eip = &(enp->en_intr);
332 efx_oword_t oword;
333
334 /*
335 * bug17213 workaround.
336 *
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.
340 */
341 if (enp->en_family == EFX_FAMILY_SIENA &&
342 eip->ei_type == EFX_INTR_LINE)
343 eip->ei_level = 0x1f;
344 else
345 eip->ei_level = 0;
346
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);
355
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);
362
363 return (0);
364}
365
366static void
367falconsiena_intr_enable(
368 __in efx_nic_t *enp)
369{
370 efx_intr_t *eip = &(enp->en_intr);
371 efx_oword_t oword;
372
373 EFX_BAR_READO(enp, FR_AZ_INT_EN_REG_KER, &oword);
374
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);
378}
379
380static void
381falconsiena_intr_disable(
382 __in efx_nic_t *enp)
383{
384 efx_oword_t oword;
385
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);
389
390 EFSYS_SPIN(10);
391}
392
393static void
394falconsiena_intr_disable_unlocked(
395 __in efx_nic_t *enp)
396{
397 efx_oword_t oword;
398
399 EFSYS_BAR_READO(enp->en_esbp, FR_AZ_INT_EN_REG_KER_OFST,
400 &oword, B_FALSE);
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,
403 &oword, B_FALSE);
404}
405
406static __checkReturn efx_rc_t
407falconsiena_intr_trigger(
408 __in efx_nic_t *enp,
409 __in unsigned int level)
410{
411 efx_intr_t *eip = &(enp->en_intr);
412 efx_oword_t oword;
413 unsigned int count;
414 uint32_t sel;
415 efx_rc_t rc;
416
417 /* bug16757: No event queues can be initialized */
418 EFSYS_ASSERT(!(enp->en_mod_flags & EFX_MOD_EV));
419
420 switch (enp->en_family) {
421 case EFX_FAMILY_FALCON:
422 if (level >= EFX_NINTR_FALCON) {
423 rc = EINVAL;
424 goto fail1;
425 }
426 break;
427
428 case EFX_FAMILY_SIENA:
429 if (level >= EFX_NINTR_SIENA) {
430 rc = EINVAL;
431 goto fail1;
432 }
433 break;
434
435 default:
436 EFSYS_ASSERT(B_FALSE);
437 break;
438 }
439
440 if (level > EFX_MASK32(FRF_AZ_KER_INT_LEVE_SEL))
441 return (ENOTSUP); /* avoid EFSYS_PROBE() */
442
443 sel = level;
444
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);
450
451 /*
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
455 */
456 count = 0;
457 do {
458 EFSYS_SPIN(100); /* 100us */
459
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);
462
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);
465
466 return (0);
467
468fail1:
469 EFSYS_PROBE1(fail1, efx_rc_t, rc);
470
471 return (rc);
472}
473
474static __checkReturn boolean_t
475falconsiena_intr_check_fatal(
476 __in efx_nic_t *enp)
477{
478 efx_intr_t *eip = &(enp->en_intr);
479 efsys_mem_t *esmp = eip->ei_esmp;
480 efx_oword_t oword;
481
482 /* Read the syndrome */
483 EFSYS_MEM_READO(esmp, 0, &oword);
484
485 if (EFX_OWORD_FIELD(oword, FSF_AZ_NET_IVEC_FATAL_INT) != 0) {
486 EFSYS_PROBE(fatal);
487
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);
491
492 return (B_TRUE);
493 }
494
495 return (B_FALSE);
496}
497
498static void
499falconsiena_intr_status_line(
500 __in efx_nic_t *enp,
501 __out boolean_t *fatalp,
502 __out uint32_t *qmaskp)
503{
504 efx_intr_t *eip = &(enp->en_intr);
505 efx_dword_t dword;
506
507 EFSYS_ASSERT3U(enp->en_magic, ==, EFX_NIC_MAGIC);
508 EFSYS_ASSERT3U(enp->en_mod_flags, &, EFX_MOD_INTR);
509
510 /*
511 * Read the queue mask and implicitly acknowledge the
512 * interrupt.
513 */
514 EFX_BAR_READD(enp, FR_BZ_INT_ISR0_REG, &dword, B_FALSE);
515 *qmaskp = EFX_DWORD_FIELD(dword, EFX_DWORD_0);
516
517 EFSYS_PROBE1(qmask, uint32_t, *qmaskp);
518
519 if (*qmaskp & (1U << eip->ei_level))
520 *fatalp = falconsiena_intr_check_fatal(enp);
521 else
522 *fatalp = B_FALSE;
523}
524
525static void
526falconsiena_intr_status_message(
527 __in efx_nic_t *enp,
528 __in unsigned int message,
529 __out boolean_t *fatalp)
530{
531 efx_intr_t *eip = &(enp->en_intr);
532
533 EFSYS_ASSERT3U(enp->en_magic, ==, EFX_NIC_MAGIC);
534 EFSYS_ASSERT3U(enp->en_mod_flags, &, EFX_MOD_INTR);
535
536 if (message == eip->ei_level)
537 *fatalp = falconsiena_intr_check_fatal(enp);
538 else
539 *fatalp = B_FALSE;
540}
541
542
543static void
544falconsiena_intr_fatal(
545 __in efx_nic_t *enp)
546{
547#if EFSYS_OPT_DECODE_INTR_FATAL
548 efx_oword_t fatal;
549 efx_oword_t mem_per;
550
551 EFX_BAR_READO(enp, FR_AZ_FATAL_INTR_REG_KER, &fatal);
552 EFX_ZERO_OWORD(mem_per);
553
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);
557
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);
560
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);
563
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));
568
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);
571
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);
574
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);
577
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);
580
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);
583
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);
586
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);
589
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));
594#else
595 EFSYS_ASSERT(0);
596#endif
597}
598
599static void
600falconsiena_intr_fini(
601 __in efx_nic_t *enp)
602{
603 efx_oword_t oword;
604
605 /* Clear the interrupt address register */
606 EFX_ZERO_OWORD(oword);
607 EFX_BAR_WRITEO(enp, FR_AZ_INT_ADR_REG_KER, &oword);
608}
609
610#endif /* EFSYS_OPT_FALCON || EFSYS_OPT_SIENA */