1*49ef7e06SGarrett D'Amore /*
2*49ef7e06SGarrett D'Amore * Copyright (c) 2007-2015 Solarflare Communications Inc.
3*49ef7e06SGarrett D'Amore * All rights reserved.
4*49ef7e06SGarrett D'Amore *
5*49ef7e06SGarrett D'Amore * Redistribution and use in source and binary forms, with or without
6*49ef7e06SGarrett D'Amore * modification, are permitted provided that the following conditions are met:
7*49ef7e06SGarrett D'Amore *
8*49ef7e06SGarrett D'Amore * 1. Redistributions of source code must retain the above copyright notice,
9*49ef7e06SGarrett D'Amore * this list of conditions and the following disclaimer.
10*49ef7e06SGarrett D'Amore * 2. Redistributions in binary form must reproduce the above copyright notice,
11*49ef7e06SGarrett D'Amore * this list of conditions and the following disclaimer in the documentation
12*49ef7e06SGarrett D'Amore * and/or other materials provided with the distribution.
13*49ef7e06SGarrett D'Amore *
14*49ef7e06SGarrett D'Amore * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
15*49ef7e06SGarrett D'Amore * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
16*49ef7e06SGarrett D'Amore * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
17*49ef7e06SGarrett D'Amore * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
18*49ef7e06SGarrett D'Amore * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
19*49ef7e06SGarrett D'Amore * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
20*49ef7e06SGarrett D'Amore * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS;
21*49ef7e06SGarrett D'Amore * OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
22*49ef7e06SGarrett D'Amore * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
23*49ef7e06SGarrett D'Amore * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE,
24*49ef7e06SGarrett D'Amore * EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
25*49ef7e06SGarrett D'Amore *
26*49ef7e06SGarrett D'Amore * The views and conclusions contained in the software and documentation are
27*49ef7e06SGarrett D'Amore * those of the authors and should not be interpreted as representing official
28*49ef7e06SGarrett D'Amore * policies, either expressed or implied, of the FreeBSD Project.
29*49ef7e06SGarrett D'Amore */
30*49ef7e06SGarrett D'Amore
31*49ef7e06SGarrett D'Amore #include "efx.h"
32*49ef7e06SGarrett D'Amore #include "efx_impl.h"
33*49ef7e06SGarrett D'Amore
34*49ef7e06SGarrett D'Amore
35*49ef7e06SGarrett D'Amore #if EFSYS_OPT_SIENA
36*49ef7e06SGarrett D'Amore
37*49ef7e06SGarrett D'Amore static __checkReturn efx_rc_t
38*49ef7e06SGarrett D'Amore siena_intr_init(
39*49ef7e06SGarrett D'Amore __in efx_nic_t *enp,
40*49ef7e06SGarrett D'Amore __in efx_intr_type_t type,
41*49ef7e06SGarrett D'Amore __in efsys_mem_t *esmp);
42*49ef7e06SGarrett D'Amore
43*49ef7e06SGarrett D'Amore static void
44*49ef7e06SGarrett D'Amore siena_intr_enable(
45*49ef7e06SGarrett D'Amore __in efx_nic_t *enp);
46*49ef7e06SGarrett D'Amore
47*49ef7e06SGarrett D'Amore static void
48*49ef7e06SGarrett D'Amore siena_intr_disable(
49*49ef7e06SGarrett D'Amore __in efx_nic_t *enp);
50*49ef7e06SGarrett D'Amore
51*49ef7e06SGarrett D'Amore static void
52*49ef7e06SGarrett D'Amore siena_intr_disable_unlocked(
53*49ef7e06SGarrett D'Amore __in efx_nic_t *enp);
54*49ef7e06SGarrett D'Amore
55*49ef7e06SGarrett D'Amore static __checkReturn efx_rc_t
56*49ef7e06SGarrett D'Amore siena_intr_trigger(
57*49ef7e06SGarrett D'Amore __in efx_nic_t *enp,
58*49ef7e06SGarrett D'Amore __in unsigned int level);
59*49ef7e06SGarrett D'Amore
60*49ef7e06SGarrett D'Amore static void
61*49ef7e06SGarrett D'Amore siena_intr_fini(
62*49ef7e06SGarrett D'Amore __in efx_nic_t *enp);
63*49ef7e06SGarrett D'Amore
64*49ef7e06SGarrett D'Amore static void
65*49ef7e06SGarrett D'Amore siena_intr_status_line(
66*49ef7e06SGarrett D'Amore __in efx_nic_t *enp,
67*49ef7e06SGarrett D'Amore __out boolean_t *fatalp,
68*49ef7e06SGarrett D'Amore __out uint32_t *qmaskp);
69*49ef7e06SGarrett D'Amore
70*49ef7e06SGarrett D'Amore static void
71*49ef7e06SGarrett D'Amore siena_intr_status_message(
72*49ef7e06SGarrett D'Amore __in efx_nic_t *enp,
73*49ef7e06SGarrett D'Amore __in unsigned int message,
74*49ef7e06SGarrett D'Amore __out boolean_t *fatalp);
75*49ef7e06SGarrett D'Amore
76*49ef7e06SGarrett D'Amore static void
77*49ef7e06SGarrett D'Amore siena_intr_fatal(
78*49ef7e06SGarrett D'Amore __in efx_nic_t *enp);
79*49ef7e06SGarrett D'Amore
80*49ef7e06SGarrett D'Amore static __checkReturn boolean_t
81*49ef7e06SGarrett D'Amore siena_intr_check_fatal(
82*49ef7e06SGarrett D'Amore __in efx_nic_t *enp);
83*49ef7e06SGarrett D'Amore
84*49ef7e06SGarrett D'Amore
85*49ef7e06SGarrett D'Amore #endif /* EFSYS_OPT_SIENA */
86*49ef7e06SGarrett D'Amore
87*49ef7e06SGarrett D'Amore
88*49ef7e06SGarrett D'Amore #if EFSYS_OPT_SIENA
89*49ef7e06SGarrett D'Amore static const efx_intr_ops_t __efx_intr_siena_ops = {
90*49ef7e06SGarrett D'Amore siena_intr_init, /* eio_init */
91*49ef7e06SGarrett D'Amore siena_intr_enable, /* eio_enable */
92*49ef7e06SGarrett D'Amore siena_intr_disable, /* eio_disable */
93*49ef7e06SGarrett D'Amore siena_intr_disable_unlocked, /* eio_disable_unlocked */
94*49ef7e06SGarrett D'Amore siena_intr_trigger, /* eio_trigger */
95*49ef7e06SGarrett D'Amore siena_intr_status_line, /* eio_status_line */
96*49ef7e06SGarrett D'Amore siena_intr_status_message, /* eio_status_message */
97*49ef7e06SGarrett D'Amore siena_intr_fatal, /* eio_fatal */
98*49ef7e06SGarrett D'Amore siena_intr_fini, /* eio_fini */
99*49ef7e06SGarrett D'Amore };
100*49ef7e06SGarrett D'Amore #endif /* EFSYS_OPT_SIENA */
101*49ef7e06SGarrett D'Amore
102*49ef7e06SGarrett D'Amore #if EFSYS_OPT_HUNTINGTON || EFSYS_OPT_MEDFORD
103*49ef7e06SGarrett D'Amore static const efx_intr_ops_t __efx_intr_ef10_ops = {
104*49ef7e06SGarrett D'Amore ef10_intr_init, /* eio_init */
105*49ef7e06SGarrett D'Amore ef10_intr_enable, /* eio_enable */
106*49ef7e06SGarrett D'Amore ef10_intr_disable, /* eio_disable */
107*49ef7e06SGarrett D'Amore ef10_intr_disable_unlocked, /* eio_disable_unlocked */
108*49ef7e06SGarrett D'Amore ef10_intr_trigger, /* eio_trigger */
109*49ef7e06SGarrett D'Amore ef10_intr_status_line, /* eio_status_line */
110*49ef7e06SGarrett D'Amore ef10_intr_status_message, /* eio_status_message */
111*49ef7e06SGarrett D'Amore ef10_intr_fatal, /* eio_fatal */
112*49ef7e06SGarrett D'Amore ef10_intr_fini, /* eio_fini */
113*49ef7e06SGarrett D'Amore };
114*49ef7e06SGarrett D'Amore #endif /* EFSYS_OPT_HUNTINGTON || EFSYS_OPT_MEDFORD */
115*49ef7e06SGarrett D'Amore
116*49ef7e06SGarrett D'Amore __checkReturn efx_rc_t
efx_intr_init(__in efx_nic_t * enp,__in efx_intr_type_t type,__in efsys_mem_t * esmp)117*49ef7e06SGarrett D'Amore efx_intr_init(
118*49ef7e06SGarrett D'Amore __in efx_nic_t *enp,
119*49ef7e06SGarrett D'Amore __in efx_intr_type_t type,
120*49ef7e06SGarrett D'Amore __in efsys_mem_t *esmp)
121*49ef7e06SGarrett D'Amore {
122*49ef7e06SGarrett D'Amore efx_intr_t *eip = &(enp->en_intr);
123*49ef7e06SGarrett D'Amore const efx_intr_ops_t *eiop;
124*49ef7e06SGarrett D'Amore efx_rc_t rc;
125*49ef7e06SGarrett D'Amore
126*49ef7e06SGarrett D'Amore EFSYS_ASSERT3U(enp->en_magic, ==, EFX_NIC_MAGIC);
127*49ef7e06SGarrett D'Amore EFSYS_ASSERT3U(enp->en_mod_flags, &, EFX_MOD_NIC);
128*49ef7e06SGarrett D'Amore
129*49ef7e06SGarrett D'Amore if (enp->en_mod_flags & EFX_MOD_INTR) {
130*49ef7e06SGarrett D'Amore rc = EINVAL;
131*49ef7e06SGarrett D'Amore goto fail1;
132*49ef7e06SGarrett D'Amore }
133*49ef7e06SGarrett D'Amore
134*49ef7e06SGarrett D'Amore eip->ei_esmp = esmp;
135*49ef7e06SGarrett D'Amore eip->ei_type = type;
136*49ef7e06SGarrett D'Amore eip->ei_level = 0;
137*49ef7e06SGarrett D'Amore
138*49ef7e06SGarrett D'Amore enp->en_mod_flags |= EFX_MOD_INTR;
139*49ef7e06SGarrett D'Amore
140*49ef7e06SGarrett D'Amore switch (enp->en_family) {
141*49ef7e06SGarrett D'Amore #if EFSYS_OPT_SIENA
142*49ef7e06SGarrett D'Amore case EFX_FAMILY_SIENA:
143*49ef7e06SGarrett D'Amore eiop = &__efx_intr_siena_ops;
144*49ef7e06SGarrett D'Amore break;
145*49ef7e06SGarrett D'Amore #endif /* EFSYS_OPT_SIENA */
146*49ef7e06SGarrett D'Amore
147*49ef7e06SGarrett D'Amore #if EFSYS_OPT_HUNTINGTON
148*49ef7e06SGarrett D'Amore case EFX_FAMILY_HUNTINGTON:
149*49ef7e06SGarrett D'Amore eiop = &__efx_intr_ef10_ops;
150*49ef7e06SGarrett D'Amore break;
151*49ef7e06SGarrett D'Amore #endif /* EFSYS_OPT_HUNTINGTON */
152*49ef7e06SGarrett D'Amore
153*49ef7e06SGarrett D'Amore #if EFSYS_OPT_MEDFORD
154*49ef7e06SGarrett D'Amore case EFX_FAMILY_MEDFORD:
155*49ef7e06SGarrett D'Amore eiop = &__efx_intr_ef10_ops;
156*49ef7e06SGarrett D'Amore break;
157*49ef7e06SGarrett D'Amore #endif /* EFSYS_OPT_MEDFORD */
158*49ef7e06SGarrett D'Amore
159*49ef7e06SGarrett D'Amore default:
160*49ef7e06SGarrett D'Amore EFSYS_ASSERT(B_FALSE);
161*49ef7e06SGarrett D'Amore rc = ENOTSUP;
162*49ef7e06SGarrett D'Amore goto fail2;
163*49ef7e06SGarrett D'Amore }
164*49ef7e06SGarrett D'Amore
165*49ef7e06SGarrett D'Amore if ((rc = eiop->eio_init(enp, type, esmp)) != 0)
166*49ef7e06SGarrett D'Amore goto fail3;
167*49ef7e06SGarrett D'Amore
168*49ef7e06SGarrett D'Amore eip->ei_eiop = eiop;
169*49ef7e06SGarrett D'Amore
170*49ef7e06SGarrett D'Amore return (0);
171*49ef7e06SGarrett D'Amore
172*49ef7e06SGarrett D'Amore fail3:
173*49ef7e06SGarrett D'Amore EFSYS_PROBE(fail3);
174*49ef7e06SGarrett D'Amore fail2:
175*49ef7e06SGarrett D'Amore EFSYS_PROBE(fail2);
176*49ef7e06SGarrett D'Amore fail1:
177*49ef7e06SGarrett D'Amore EFSYS_PROBE1(fail1, efx_rc_t, rc);
178*49ef7e06SGarrett D'Amore
179*49ef7e06SGarrett D'Amore return (rc);
180*49ef7e06SGarrett D'Amore }
181*49ef7e06SGarrett D'Amore
182*49ef7e06SGarrett D'Amore void
efx_intr_fini(__in efx_nic_t * enp)183*49ef7e06SGarrett D'Amore efx_intr_fini(
184*49ef7e06SGarrett D'Amore __in efx_nic_t *enp)
185*49ef7e06SGarrett D'Amore {
186*49ef7e06SGarrett D'Amore efx_intr_t *eip = &(enp->en_intr);
187*49ef7e06SGarrett D'Amore const efx_intr_ops_t *eiop = eip->ei_eiop;
188*49ef7e06SGarrett D'Amore
189*49ef7e06SGarrett D'Amore EFSYS_ASSERT3U(enp->en_magic, ==, EFX_NIC_MAGIC);
190*49ef7e06SGarrett D'Amore EFSYS_ASSERT3U(enp->en_mod_flags, &, EFX_MOD_NIC);
191*49ef7e06SGarrett D'Amore EFSYS_ASSERT3U(enp->en_mod_flags, &, EFX_MOD_INTR);
192*49ef7e06SGarrett D'Amore
193*49ef7e06SGarrett D'Amore eiop->eio_fini(enp);
194*49ef7e06SGarrett D'Amore
195*49ef7e06SGarrett D'Amore enp->en_mod_flags &= ~EFX_MOD_INTR;
196*49ef7e06SGarrett D'Amore }
197*49ef7e06SGarrett D'Amore
198*49ef7e06SGarrett D'Amore void
efx_intr_enable(__in efx_nic_t * enp)199*49ef7e06SGarrett D'Amore efx_intr_enable(
200*49ef7e06SGarrett D'Amore __in efx_nic_t *enp)
201*49ef7e06SGarrett D'Amore {
202*49ef7e06SGarrett D'Amore efx_intr_t *eip = &(enp->en_intr);
203*49ef7e06SGarrett D'Amore const efx_intr_ops_t *eiop = eip->ei_eiop;
204*49ef7e06SGarrett D'Amore
205*49ef7e06SGarrett D'Amore EFSYS_ASSERT3U(enp->en_magic, ==, EFX_NIC_MAGIC);
206*49ef7e06SGarrett D'Amore EFSYS_ASSERT3U(enp->en_mod_flags, &, EFX_MOD_INTR);
207*49ef7e06SGarrett D'Amore
208*49ef7e06SGarrett D'Amore eiop->eio_enable(enp);
209*49ef7e06SGarrett D'Amore }
210*49ef7e06SGarrett D'Amore
211*49ef7e06SGarrett D'Amore void
efx_intr_disable(__in efx_nic_t * enp)212*49ef7e06SGarrett D'Amore efx_intr_disable(
213*49ef7e06SGarrett D'Amore __in efx_nic_t *enp)
214*49ef7e06SGarrett D'Amore {
215*49ef7e06SGarrett D'Amore efx_intr_t *eip = &(enp->en_intr);
216*49ef7e06SGarrett D'Amore const efx_intr_ops_t *eiop = eip->ei_eiop;
217*49ef7e06SGarrett D'Amore
218*49ef7e06SGarrett D'Amore EFSYS_ASSERT3U(enp->en_magic, ==, EFX_NIC_MAGIC);
219*49ef7e06SGarrett D'Amore EFSYS_ASSERT3U(enp->en_mod_flags, &, EFX_MOD_INTR);
220*49ef7e06SGarrett D'Amore
221*49ef7e06SGarrett D'Amore eiop->eio_disable(enp);
222*49ef7e06SGarrett D'Amore }
223*49ef7e06SGarrett D'Amore
224*49ef7e06SGarrett D'Amore void
efx_intr_disable_unlocked(__in efx_nic_t * enp)225*49ef7e06SGarrett D'Amore efx_intr_disable_unlocked(
226*49ef7e06SGarrett D'Amore __in efx_nic_t *enp)
227*49ef7e06SGarrett D'Amore {
228*49ef7e06SGarrett D'Amore efx_intr_t *eip = &(enp->en_intr);
229*49ef7e06SGarrett D'Amore const efx_intr_ops_t *eiop = eip->ei_eiop;
230*49ef7e06SGarrett D'Amore
231*49ef7e06SGarrett D'Amore EFSYS_ASSERT3U(enp->en_magic, ==, EFX_NIC_MAGIC);
232*49ef7e06SGarrett D'Amore EFSYS_ASSERT3U(enp->en_mod_flags, &, EFX_MOD_INTR);
233*49ef7e06SGarrett D'Amore
234*49ef7e06SGarrett D'Amore eiop->eio_disable_unlocked(enp);
235*49ef7e06SGarrett D'Amore }
236*49ef7e06SGarrett D'Amore
237*49ef7e06SGarrett D'Amore
238*49ef7e06SGarrett D'Amore __checkReturn efx_rc_t
efx_intr_trigger(__in efx_nic_t * enp,__in unsigned int level)239*49ef7e06SGarrett D'Amore efx_intr_trigger(
240*49ef7e06SGarrett D'Amore __in efx_nic_t *enp,
241*49ef7e06SGarrett D'Amore __in unsigned int level)
242*49ef7e06SGarrett D'Amore {
243*49ef7e06SGarrett D'Amore efx_intr_t *eip = &(enp->en_intr);
244*49ef7e06SGarrett D'Amore const efx_intr_ops_t *eiop = eip->ei_eiop;
245*49ef7e06SGarrett D'Amore
246*49ef7e06SGarrett D'Amore EFSYS_ASSERT3U(enp->en_magic, ==, EFX_NIC_MAGIC);
247*49ef7e06SGarrett D'Amore EFSYS_ASSERT3U(enp->en_mod_flags, &, EFX_MOD_INTR);
248*49ef7e06SGarrett D'Amore
249*49ef7e06SGarrett D'Amore return (eiop->eio_trigger(enp, level));
250*49ef7e06SGarrett D'Amore }
251*49ef7e06SGarrett D'Amore
252*49ef7e06SGarrett D'Amore void
efx_intr_status_line(__in efx_nic_t * enp,__out boolean_t * fatalp,__out uint32_t * qmaskp)253*49ef7e06SGarrett D'Amore efx_intr_status_line(
254*49ef7e06SGarrett D'Amore __in efx_nic_t *enp,
255*49ef7e06SGarrett D'Amore __out boolean_t *fatalp,
256*49ef7e06SGarrett D'Amore __out uint32_t *qmaskp)
257*49ef7e06SGarrett D'Amore {
258*49ef7e06SGarrett D'Amore efx_intr_t *eip = &(enp->en_intr);
259*49ef7e06SGarrett D'Amore const efx_intr_ops_t *eiop = eip->ei_eiop;
260*49ef7e06SGarrett D'Amore
261*49ef7e06SGarrett D'Amore EFSYS_ASSERT3U(enp->en_magic, ==, EFX_NIC_MAGIC);
262*49ef7e06SGarrett D'Amore EFSYS_ASSERT3U(enp->en_mod_flags, &, EFX_MOD_INTR);
263*49ef7e06SGarrett D'Amore
264*49ef7e06SGarrett D'Amore eiop->eio_status_line(enp, fatalp, qmaskp);
265*49ef7e06SGarrett D'Amore }
266*49ef7e06SGarrett D'Amore
267*49ef7e06SGarrett D'Amore void
efx_intr_status_message(__in efx_nic_t * enp,__in unsigned int message,__out boolean_t * fatalp)268*49ef7e06SGarrett D'Amore efx_intr_status_message(
269*49ef7e06SGarrett D'Amore __in efx_nic_t *enp,
270*49ef7e06SGarrett D'Amore __in unsigned int message,
271*49ef7e06SGarrett D'Amore __out boolean_t *fatalp)
272*49ef7e06SGarrett D'Amore {
273*49ef7e06SGarrett D'Amore efx_intr_t *eip = &(enp->en_intr);
274*49ef7e06SGarrett D'Amore const efx_intr_ops_t *eiop = eip->ei_eiop;
275*49ef7e06SGarrett D'Amore
276*49ef7e06SGarrett D'Amore EFSYS_ASSERT3U(enp->en_magic, ==, EFX_NIC_MAGIC);
277*49ef7e06SGarrett D'Amore EFSYS_ASSERT3U(enp->en_mod_flags, &, EFX_MOD_INTR);
278*49ef7e06SGarrett D'Amore
279*49ef7e06SGarrett D'Amore eiop->eio_status_message(enp, message, fatalp);
280*49ef7e06SGarrett D'Amore }
281*49ef7e06SGarrett D'Amore
282*49ef7e06SGarrett D'Amore void
efx_intr_fatal(__in efx_nic_t * enp)283*49ef7e06SGarrett D'Amore efx_intr_fatal(
284*49ef7e06SGarrett D'Amore __in efx_nic_t *enp)
285*49ef7e06SGarrett D'Amore {
286*49ef7e06SGarrett D'Amore efx_intr_t *eip = &(enp->en_intr);
287*49ef7e06SGarrett D'Amore const efx_intr_ops_t *eiop = eip->ei_eiop;
288*49ef7e06SGarrett D'Amore
289*49ef7e06SGarrett D'Amore EFSYS_ASSERT3U(enp->en_magic, ==, EFX_NIC_MAGIC);
290*49ef7e06SGarrett D'Amore EFSYS_ASSERT3U(enp->en_mod_flags, &, EFX_MOD_INTR);
291*49ef7e06SGarrett D'Amore
292*49ef7e06SGarrett D'Amore eiop->eio_fatal(enp);
293*49ef7e06SGarrett D'Amore }
294*49ef7e06SGarrett D'Amore
295*49ef7e06SGarrett D'Amore
296*49ef7e06SGarrett D'Amore /* ************************************************************************* */
297*49ef7e06SGarrett D'Amore /* ************************************************************************* */
298*49ef7e06SGarrett D'Amore /* ************************************************************************* */
299*49ef7e06SGarrett D'Amore
300*49ef7e06SGarrett D'Amore #if EFSYS_OPT_SIENA
301*49ef7e06SGarrett D'Amore
302*49ef7e06SGarrett D'Amore static __checkReturn efx_rc_t
siena_intr_init(__in efx_nic_t * enp,__in efx_intr_type_t type,__in efsys_mem_t * esmp)303*49ef7e06SGarrett D'Amore siena_intr_init(
304*49ef7e06SGarrett D'Amore __in efx_nic_t *enp,
305*49ef7e06SGarrett D'Amore __in efx_intr_type_t type,
306*49ef7e06SGarrett D'Amore __in efsys_mem_t *esmp)
307*49ef7e06SGarrett D'Amore {
308*49ef7e06SGarrett D'Amore efx_intr_t *eip = &(enp->en_intr);
309*49ef7e06SGarrett D'Amore efx_oword_t oword;
310*49ef7e06SGarrett D'Amore
311*49ef7e06SGarrett D'Amore /*
312*49ef7e06SGarrett D'Amore * bug17213 workaround.
313*49ef7e06SGarrett D'Amore *
314*49ef7e06SGarrett D'Amore * Under legacy interrupts, don't share a level between fatal
315*49ef7e06SGarrett D'Amore * interrupts and event queue interrupts. Under MSI-X, they
316*49ef7e06SGarrett D'Amore * must share, or we won't get an interrupt.
317*49ef7e06SGarrett D'Amore */
318*49ef7e06SGarrett D'Amore if (enp->en_family == EFX_FAMILY_SIENA &&
319*49ef7e06SGarrett D'Amore eip->ei_type == EFX_INTR_LINE)
320*49ef7e06SGarrett D'Amore eip->ei_level = 0x1f;
321*49ef7e06SGarrett D'Amore else
322*49ef7e06SGarrett D'Amore eip->ei_level = 0;
323*49ef7e06SGarrett D'Amore
324*49ef7e06SGarrett D'Amore /* Enable all the genuinely fatal interrupts */
325*49ef7e06SGarrett D'Amore EFX_SET_OWORD(oword);
326*49ef7e06SGarrett D'Amore EFX_SET_OWORD_FIELD(oword, FRF_AZ_ILL_ADR_INT_KER_EN, 0);
327*49ef7e06SGarrett D'Amore EFX_SET_OWORD_FIELD(oword, FRF_AZ_RBUF_OWN_INT_KER_EN, 0);
328*49ef7e06SGarrett D'Amore EFX_SET_OWORD_FIELD(oword, FRF_AZ_TBUF_OWN_INT_KER_EN, 0);
329*49ef7e06SGarrett D'Amore if (enp->en_family >= EFX_FAMILY_SIENA)
330*49ef7e06SGarrett D'Amore EFX_SET_OWORD_FIELD(oword, FRF_CZ_SRAM_PERR_INT_P_KER_EN, 0);
331*49ef7e06SGarrett D'Amore EFX_BAR_WRITEO(enp, FR_AZ_FATAL_INTR_REG_KER, &oword);
332*49ef7e06SGarrett D'Amore
333*49ef7e06SGarrett D'Amore /* Set up the interrupt address register */
334*49ef7e06SGarrett D'Amore EFX_POPULATE_OWORD_3(oword,
335*49ef7e06SGarrett D'Amore FRF_AZ_NORM_INT_VEC_DIS_KER, (type == EFX_INTR_MESSAGE) ? 1 : 0,
336*49ef7e06SGarrett D'Amore FRF_AZ_INT_ADR_KER_DW0, EFSYS_MEM_ADDR(esmp) & 0xffffffff,
337*49ef7e06SGarrett D'Amore FRF_AZ_INT_ADR_KER_DW1, EFSYS_MEM_ADDR(esmp) >> 32);
338*49ef7e06SGarrett D'Amore EFX_BAR_WRITEO(enp, FR_AZ_INT_ADR_REG_KER, &oword);
339*49ef7e06SGarrett D'Amore
340*49ef7e06SGarrett D'Amore return (0);
341*49ef7e06SGarrett D'Amore }
342*49ef7e06SGarrett D'Amore
343*49ef7e06SGarrett D'Amore static void
siena_intr_enable(__in efx_nic_t * enp)344*49ef7e06SGarrett D'Amore siena_intr_enable(
345*49ef7e06SGarrett D'Amore __in efx_nic_t *enp)
346*49ef7e06SGarrett D'Amore {
347*49ef7e06SGarrett D'Amore efx_intr_t *eip = &(enp->en_intr);
348*49ef7e06SGarrett D'Amore efx_oword_t oword;
349*49ef7e06SGarrett D'Amore
350*49ef7e06SGarrett D'Amore EFX_BAR_READO(enp, FR_AZ_INT_EN_REG_KER, &oword);
351*49ef7e06SGarrett D'Amore
352*49ef7e06SGarrett D'Amore EFX_SET_OWORD_FIELD(oword, FRF_AZ_KER_INT_LEVE_SEL, eip->ei_level);
353*49ef7e06SGarrett D'Amore EFX_SET_OWORD_FIELD(oword, FRF_AZ_DRV_INT_EN_KER, 1);
354*49ef7e06SGarrett D'Amore EFX_BAR_WRITEO(enp, FR_AZ_INT_EN_REG_KER, &oword);
355*49ef7e06SGarrett D'Amore }
356*49ef7e06SGarrett D'Amore
357*49ef7e06SGarrett D'Amore static void
siena_intr_disable(__in efx_nic_t * enp)358*49ef7e06SGarrett D'Amore siena_intr_disable(
359*49ef7e06SGarrett D'Amore __in efx_nic_t *enp)
360*49ef7e06SGarrett D'Amore {
361*49ef7e06SGarrett D'Amore efx_oword_t oword;
362*49ef7e06SGarrett D'Amore
363*49ef7e06SGarrett D'Amore EFX_BAR_READO(enp, FR_AZ_INT_EN_REG_KER, &oword);
364*49ef7e06SGarrett D'Amore EFX_SET_OWORD_FIELD(oword, FRF_AZ_DRV_INT_EN_KER, 0);
365*49ef7e06SGarrett D'Amore EFX_BAR_WRITEO(enp, FR_AZ_INT_EN_REG_KER, &oword);
366*49ef7e06SGarrett D'Amore
367*49ef7e06SGarrett D'Amore EFSYS_SPIN(10);
368*49ef7e06SGarrett D'Amore }
369*49ef7e06SGarrett D'Amore
370*49ef7e06SGarrett D'Amore static void
siena_intr_disable_unlocked(__in efx_nic_t * enp)371*49ef7e06SGarrett D'Amore siena_intr_disable_unlocked(
372*49ef7e06SGarrett D'Amore __in efx_nic_t *enp)
373*49ef7e06SGarrett D'Amore {
374*49ef7e06SGarrett D'Amore efx_oword_t oword;
375*49ef7e06SGarrett D'Amore
376*49ef7e06SGarrett D'Amore EFSYS_BAR_READO(enp->en_esbp, FR_AZ_INT_EN_REG_KER_OFST,
377*49ef7e06SGarrett D'Amore &oword, B_FALSE);
378*49ef7e06SGarrett D'Amore EFX_SET_OWORD_FIELD(oword, FRF_AZ_DRV_INT_EN_KER, 0);
379*49ef7e06SGarrett D'Amore EFSYS_BAR_WRITEO(enp->en_esbp, FR_AZ_INT_EN_REG_KER_OFST,
380*49ef7e06SGarrett D'Amore &oword, B_FALSE);
381*49ef7e06SGarrett D'Amore }
382*49ef7e06SGarrett D'Amore
383*49ef7e06SGarrett D'Amore static __checkReturn efx_rc_t
siena_intr_trigger(__in efx_nic_t * enp,__in unsigned int level)384*49ef7e06SGarrett D'Amore siena_intr_trigger(
385*49ef7e06SGarrett D'Amore __in efx_nic_t *enp,
386*49ef7e06SGarrett D'Amore __in unsigned int level)
387*49ef7e06SGarrett D'Amore {
388*49ef7e06SGarrett D'Amore efx_intr_t *eip = &(enp->en_intr);
389*49ef7e06SGarrett D'Amore efx_oword_t oword;
390*49ef7e06SGarrett D'Amore unsigned int count;
391*49ef7e06SGarrett D'Amore uint32_t sel;
392*49ef7e06SGarrett D'Amore efx_rc_t rc;
393*49ef7e06SGarrett D'Amore
394*49ef7e06SGarrett D'Amore /* bug16757: No event queues can be initialized */
395*49ef7e06SGarrett D'Amore EFSYS_ASSERT(!(enp->en_mod_flags & EFX_MOD_EV));
396*49ef7e06SGarrett D'Amore
397*49ef7e06SGarrett D'Amore if (level >= EFX_NINTR_SIENA) {
398*49ef7e06SGarrett D'Amore rc = EINVAL;
399*49ef7e06SGarrett D'Amore goto fail1;
400*49ef7e06SGarrett D'Amore }
401*49ef7e06SGarrett D'Amore
402*49ef7e06SGarrett D'Amore if (level > EFX_MASK32(FRF_AZ_KER_INT_LEVE_SEL))
403*49ef7e06SGarrett D'Amore return (ENOTSUP); /* avoid EFSYS_PROBE() */
404*49ef7e06SGarrett D'Amore
405*49ef7e06SGarrett D'Amore sel = level;
406*49ef7e06SGarrett D'Amore
407*49ef7e06SGarrett D'Amore /* Trigger a test interrupt */
408*49ef7e06SGarrett D'Amore EFX_BAR_READO(enp, FR_AZ_INT_EN_REG_KER, &oword);
409*49ef7e06SGarrett D'Amore EFX_SET_OWORD_FIELD(oword, FRF_AZ_KER_INT_LEVE_SEL, sel);
410*49ef7e06SGarrett D'Amore EFX_SET_OWORD_FIELD(oword, FRF_AZ_KER_INT_KER, 1);
411*49ef7e06SGarrett D'Amore EFX_BAR_WRITEO(enp, FR_AZ_INT_EN_REG_KER, &oword);
412*49ef7e06SGarrett D'Amore
413*49ef7e06SGarrett D'Amore /*
414*49ef7e06SGarrett D'Amore * Wait up to 100ms for the interrupt to be raised before restoring
415*49ef7e06SGarrett D'Amore * KER_INT_LEVE_SEL. Ignore a failure to raise (the caller will
416*49ef7e06SGarrett D'Amore * observe this soon enough anyway), but always reset KER_INT_LEVE_SEL
417*49ef7e06SGarrett D'Amore */
418*49ef7e06SGarrett D'Amore count = 0;
419*49ef7e06SGarrett D'Amore do {
420*49ef7e06SGarrett D'Amore EFSYS_SPIN(100); /* 100us */
421*49ef7e06SGarrett D'Amore
422*49ef7e06SGarrett D'Amore EFX_BAR_READO(enp, FR_AZ_INT_EN_REG_KER, &oword);
423*49ef7e06SGarrett D'Amore } while (EFX_OWORD_FIELD(oword, FRF_AZ_KER_INT_KER) && ++count < 1000);
424*49ef7e06SGarrett D'Amore
425*49ef7e06SGarrett D'Amore EFX_SET_OWORD_FIELD(oword, FRF_AZ_KER_INT_LEVE_SEL, eip->ei_level);
426*49ef7e06SGarrett D'Amore EFX_BAR_WRITEO(enp, FR_AZ_INT_EN_REG_KER, &oword);
427*49ef7e06SGarrett D'Amore
428*49ef7e06SGarrett D'Amore return (0);
429*49ef7e06SGarrett D'Amore
430*49ef7e06SGarrett D'Amore fail1:
431*49ef7e06SGarrett D'Amore EFSYS_PROBE1(fail1, efx_rc_t, rc);
432*49ef7e06SGarrett D'Amore
433*49ef7e06SGarrett D'Amore return (rc);
434*49ef7e06SGarrett D'Amore }
435*49ef7e06SGarrett D'Amore
436*49ef7e06SGarrett D'Amore static __checkReturn boolean_t
siena_intr_check_fatal(__in efx_nic_t * enp)437*49ef7e06SGarrett D'Amore siena_intr_check_fatal(
438*49ef7e06SGarrett D'Amore __in efx_nic_t *enp)
439*49ef7e06SGarrett D'Amore {
440*49ef7e06SGarrett D'Amore efx_intr_t *eip = &(enp->en_intr);
441*49ef7e06SGarrett D'Amore efsys_mem_t *esmp = eip->ei_esmp;
442*49ef7e06SGarrett D'Amore efx_oword_t oword;
443*49ef7e06SGarrett D'Amore
444*49ef7e06SGarrett D'Amore /* Read the syndrome */
445*49ef7e06SGarrett D'Amore EFSYS_MEM_READO(esmp, 0, &oword);
446*49ef7e06SGarrett D'Amore
447*49ef7e06SGarrett D'Amore if (EFX_OWORD_FIELD(oword, FSF_AZ_NET_IVEC_FATAL_INT) != 0) {
448*49ef7e06SGarrett D'Amore EFSYS_PROBE(fatal);
449*49ef7e06SGarrett D'Amore
450*49ef7e06SGarrett D'Amore /* Clear the fatal interrupt condition */
451*49ef7e06SGarrett D'Amore EFX_SET_OWORD_FIELD(oword, FSF_AZ_NET_IVEC_FATAL_INT, 0);
452*49ef7e06SGarrett D'Amore EFSYS_MEM_WRITEO(esmp, 0, &oword);
453*49ef7e06SGarrett D'Amore
454*49ef7e06SGarrett D'Amore return (B_TRUE);
455*49ef7e06SGarrett D'Amore }
456*49ef7e06SGarrett D'Amore
457*49ef7e06SGarrett D'Amore return (B_FALSE);
458*49ef7e06SGarrett D'Amore }
459*49ef7e06SGarrett D'Amore
460*49ef7e06SGarrett D'Amore static void
siena_intr_status_line(__in efx_nic_t * enp,__out boolean_t * fatalp,__out uint32_t * qmaskp)461*49ef7e06SGarrett D'Amore siena_intr_status_line(
462*49ef7e06SGarrett D'Amore __in efx_nic_t *enp,
463*49ef7e06SGarrett D'Amore __out boolean_t *fatalp,
464*49ef7e06SGarrett D'Amore __out uint32_t *qmaskp)
465*49ef7e06SGarrett D'Amore {
466*49ef7e06SGarrett D'Amore efx_intr_t *eip = &(enp->en_intr);
467*49ef7e06SGarrett D'Amore efx_dword_t dword;
468*49ef7e06SGarrett D'Amore
469*49ef7e06SGarrett D'Amore EFSYS_ASSERT3U(enp->en_magic, ==, EFX_NIC_MAGIC);
470*49ef7e06SGarrett D'Amore EFSYS_ASSERT3U(enp->en_mod_flags, &, EFX_MOD_INTR);
471*49ef7e06SGarrett D'Amore
472*49ef7e06SGarrett D'Amore /*
473*49ef7e06SGarrett D'Amore * Read the queue mask and implicitly acknowledge the
474*49ef7e06SGarrett D'Amore * interrupt.
475*49ef7e06SGarrett D'Amore */
476*49ef7e06SGarrett D'Amore EFX_BAR_READD(enp, FR_BZ_INT_ISR0_REG, &dword, B_FALSE);
477*49ef7e06SGarrett D'Amore *qmaskp = EFX_DWORD_FIELD(dword, EFX_DWORD_0);
478*49ef7e06SGarrett D'Amore
479*49ef7e06SGarrett D'Amore EFSYS_PROBE1(qmask, uint32_t, *qmaskp);
480*49ef7e06SGarrett D'Amore
481*49ef7e06SGarrett D'Amore if (*qmaskp & (1U << eip->ei_level))
482*49ef7e06SGarrett D'Amore *fatalp = siena_intr_check_fatal(enp);
483*49ef7e06SGarrett D'Amore else
484*49ef7e06SGarrett D'Amore *fatalp = B_FALSE;
485*49ef7e06SGarrett D'Amore }
486*49ef7e06SGarrett D'Amore
487*49ef7e06SGarrett D'Amore static void
siena_intr_status_message(__in efx_nic_t * enp,__in unsigned int message,__out boolean_t * fatalp)488*49ef7e06SGarrett D'Amore siena_intr_status_message(
489*49ef7e06SGarrett D'Amore __in efx_nic_t *enp,
490*49ef7e06SGarrett D'Amore __in unsigned int message,
491*49ef7e06SGarrett D'Amore __out boolean_t *fatalp)
492*49ef7e06SGarrett D'Amore {
493*49ef7e06SGarrett D'Amore efx_intr_t *eip = &(enp->en_intr);
494*49ef7e06SGarrett D'Amore
495*49ef7e06SGarrett D'Amore EFSYS_ASSERT3U(enp->en_magic, ==, EFX_NIC_MAGIC);
496*49ef7e06SGarrett D'Amore EFSYS_ASSERT3U(enp->en_mod_flags, &, EFX_MOD_INTR);
497*49ef7e06SGarrett D'Amore
498*49ef7e06SGarrett D'Amore if (message == eip->ei_level)
499*49ef7e06SGarrett D'Amore *fatalp = siena_intr_check_fatal(enp);
500*49ef7e06SGarrett D'Amore else
501*49ef7e06SGarrett D'Amore *fatalp = B_FALSE;
502*49ef7e06SGarrett D'Amore }
503*49ef7e06SGarrett D'Amore
504*49ef7e06SGarrett D'Amore
505*49ef7e06SGarrett D'Amore static void
siena_intr_fatal(__in efx_nic_t * enp)506*49ef7e06SGarrett D'Amore siena_intr_fatal(
507*49ef7e06SGarrett D'Amore __in efx_nic_t *enp)
508*49ef7e06SGarrett D'Amore {
509*49ef7e06SGarrett D'Amore #if EFSYS_OPT_DECODE_INTR_FATAL
510*49ef7e06SGarrett D'Amore efx_oword_t fatal;
511*49ef7e06SGarrett D'Amore efx_oword_t mem_per;
512*49ef7e06SGarrett D'Amore
513*49ef7e06SGarrett D'Amore EFX_BAR_READO(enp, FR_AZ_FATAL_INTR_REG_KER, &fatal);
514*49ef7e06SGarrett D'Amore EFX_ZERO_OWORD(mem_per);
515*49ef7e06SGarrett D'Amore
516*49ef7e06SGarrett D'Amore if (EFX_OWORD_FIELD(fatal, FRF_AZ_SRM_PERR_INT_KER) != 0 ||
517*49ef7e06SGarrett D'Amore EFX_OWORD_FIELD(fatal, FRF_AZ_MEM_PERR_INT_KER) != 0)
518*49ef7e06SGarrett D'Amore EFX_BAR_READO(enp, FR_AZ_MEM_STAT_REG, &mem_per);
519*49ef7e06SGarrett D'Amore
520*49ef7e06SGarrett D'Amore if (EFX_OWORD_FIELD(fatal, FRF_AZ_SRAM_OOB_INT_KER) != 0)
521*49ef7e06SGarrett D'Amore EFSYS_ERR(enp->en_esip, EFX_ERR_SRAM_OOB, 0, 0);
522*49ef7e06SGarrett D'Amore
523*49ef7e06SGarrett D'Amore if (EFX_OWORD_FIELD(fatal, FRF_AZ_BUFID_DC_OOB_INT_KER) != 0)
524*49ef7e06SGarrett D'Amore EFSYS_ERR(enp->en_esip, EFX_ERR_BUFID_DC_OOB, 0, 0);
525*49ef7e06SGarrett D'Amore
526*49ef7e06SGarrett D'Amore if (EFX_OWORD_FIELD(fatal, FRF_AZ_MEM_PERR_INT_KER) != 0)
527*49ef7e06SGarrett D'Amore EFSYS_ERR(enp->en_esip, EFX_ERR_MEM_PERR,
528*49ef7e06SGarrett D'Amore EFX_OWORD_FIELD(mem_per, EFX_DWORD_0),
529*49ef7e06SGarrett D'Amore EFX_OWORD_FIELD(mem_per, EFX_DWORD_1));
530*49ef7e06SGarrett D'Amore
531*49ef7e06SGarrett D'Amore if (EFX_OWORD_FIELD(fatal, FRF_AZ_RBUF_OWN_INT_KER) != 0)
532*49ef7e06SGarrett D'Amore EFSYS_ERR(enp->en_esip, EFX_ERR_RBUF_OWN, 0, 0);
533*49ef7e06SGarrett D'Amore
534*49ef7e06SGarrett D'Amore if (EFX_OWORD_FIELD(fatal, FRF_AZ_TBUF_OWN_INT_KER) != 0)
535*49ef7e06SGarrett D'Amore EFSYS_ERR(enp->en_esip, EFX_ERR_TBUF_OWN, 0, 0);
536*49ef7e06SGarrett D'Amore
537*49ef7e06SGarrett D'Amore if (EFX_OWORD_FIELD(fatal, FRF_AZ_RDESCQ_OWN_INT_KER) != 0)
538*49ef7e06SGarrett D'Amore EFSYS_ERR(enp->en_esip, EFX_ERR_RDESQ_OWN, 0, 0);
539*49ef7e06SGarrett D'Amore
540*49ef7e06SGarrett D'Amore if (EFX_OWORD_FIELD(fatal, FRF_AZ_TDESCQ_OWN_INT_KER) != 0)
541*49ef7e06SGarrett D'Amore EFSYS_ERR(enp->en_esip, EFX_ERR_TDESQ_OWN, 0, 0);
542*49ef7e06SGarrett D'Amore
543*49ef7e06SGarrett D'Amore if (EFX_OWORD_FIELD(fatal, FRF_AZ_EVQ_OWN_INT_KER) != 0)
544*49ef7e06SGarrett D'Amore EFSYS_ERR(enp->en_esip, EFX_ERR_EVQ_OWN, 0, 0);
545*49ef7e06SGarrett D'Amore
546*49ef7e06SGarrett D'Amore if (EFX_OWORD_FIELD(fatal, FRF_AZ_EVF_OFLO_INT_KER) != 0)
547*49ef7e06SGarrett D'Amore EFSYS_ERR(enp->en_esip, EFX_ERR_EVFF_OFLO, 0, 0);
548*49ef7e06SGarrett D'Amore
549*49ef7e06SGarrett D'Amore if (EFX_OWORD_FIELD(fatal, FRF_AZ_ILL_ADR_INT_KER) != 0)
550*49ef7e06SGarrett D'Amore EFSYS_ERR(enp->en_esip, EFX_ERR_ILL_ADDR, 0, 0);
551*49ef7e06SGarrett D'Amore
552*49ef7e06SGarrett D'Amore if (EFX_OWORD_FIELD(fatal, FRF_AZ_SRM_PERR_INT_KER) != 0)
553*49ef7e06SGarrett D'Amore EFSYS_ERR(enp->en_esip, EFX_ERR_SRAM_PERR,
554*49ef7e06SGarrett D'Amore EFX_OWORD_FIELD(mem_per, EFX_DWORD_0),
555*49ef7e06SGarrett D'Amore EFX_OWORD_FIELD(mem_per, EFX_DWORD_1));
556*49ef7e06SGarrett D'Amore #else
557*49ef7e06SGarrett D'Amore EFSYS_ASSERT(0);
558*49ef7e06SGarrett D'Amore #endif
559*49ef7e06SGarrett D'Amore }
560*49ef7e06SGarrett D'Amore
561*49ef7e06SGarrett D'Amore static void
siena_intr_fini(__in efx_nic_t * enp)562*49ef7e06SGarrett D'Amore siena_intr_fini(
563*49ef7e06SGarrett D'Amore __in efx_nic_t *enp)
564*49ef7e06SGarrett D'Amore {
565*49ef7e06SGarrett D'Amore efx_oword_t oword;
566*49ef7e06SGarrett D'Amore
567*49ef7e06SGarrett D'Amore /* Clear the interrupt address register */
568*49ef7e06SGarrett D'Amore EFX_ZERO_OWORD(oword);
569*49ef7e06SGarrett D'Amore EFX_BAR_WRITEO(enp, FR_AZ_INT_ADR_REG_KER, &oword);
570*49ef7e06SGarrett D'Amore }
571*49ef7e06SGarrett D'Amore
572*49ef7e06SGarrett D'Amore #endif /* EFSYS_OPT_SIENA */
573