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 }