xref: /freebsd/sys/dev/sfxge/common/efx_intr.c (revision 9a14aa017b21c292740c00ee098195cd46642730)
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