xref: /freebsd/sys/dev/sfxge/sfxge_intr.c (revision 911f0260390e18cf85f3dbf2c719b593efdc1e3c)
1 /*-
2  * SPDX-License-Identifier: BSD-2-Clause
3  *
4  * Copyright (c) 2010-2016 Solarflare Communications Inc.
5  * All rights reserved.
6  *
7  * This software was developed in part by Philip Paeps under contract for
8  * Solarflare Communications, Inc.
9  *
10  * Redistribution and use in source and binary forms, with or without
11  * modification, are permitted provided that the following conditions are met:
12  *
13  * 1. Redistributions of source code must retain the above copyright notice,
14  *    this list of conditions and the following disclaimer.
15  * 2. Redistributions in binary form must reproduce the above copyright notice,
16  *    this list of conditions and the following disclaimer in the documentation
17  *    and/or other materials provided with the distribution.
18  *
19  * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
20  * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
21  * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
22  * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
23  * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
24  * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
25  * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS;
26  * OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
27  * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
28  * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE,
29  * EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
30  *
31  * The views and conclusions contained in the software and documentation are
32  * those of the authors and should not be interpreted as representing official
33  * policies, either expressed or implied, of the FreeBSD Project.
34  */
35 
36 #include <sys/cdefs.h>
37 __FBSDID("$FreeBSD$");
38 
39 #include "opt_rss.h"
40 
41 #include <sys/param.h>
42 #include <sys/bus.h>
43 #include <sys/kernel.h>
44 #include <sys/malloc.h>
45 #include <sys/queue.h>
46 #include <sys/rman.h>
47 #include <sys/syslog.h>
48 #include <sys/taskqueue.h>
49 
50 #include <machine/bus.h>
51 #include <machine/resource.h>
52 
53 #include <dev/pci/pcireg.h>
54 #include <dev/pci/pcivar.h>
55 
56 #ifdef RSS
57 #include <net/rss_config.h>
58 #endif
59 
60 #include "common/efx.h"
61 
62 #include "sfxge.h"
63 
64 static int
65 sfxge_intr_line_filter(void *arg)
66 {
67 	struct sfxge_evq *evq;
68 	struct sfxge_softc *sc;
69 	efx_nic_t *enp;
70 	struct sfxge_intr *intr;
71 	boolean_t fatal;
72 	uint32_t qmask;
73 
74 	evq = (struct sfxge_evq *)arg;
75 	sc = evq->sc;
76 	enp = sc->enp;
77 	intr = &sc->intr;
78 
79 	KASSERT(intr != NULL, ("intr == NULL"));
80 	KASSERT(intr->type == EFX_INTR_LINE,
81 	    ("intr->type != EFX_INTR_LINE"));
82 
83 	if (intr->state != SFXGE_INTR_STARTED)
84 		return (FILTER_STRAY);
85 
86 	(void)efx_intr_status_line(enp, &fatal, &qmask);
87 
88 	if (fatal) {
89 		(void) efx_intr_disable(enp);
90 		(void) efx_intr_fatal(enp);
91 		return (FILTER_HANDLED);
92 	}
93 
94 	if (qmask != 0) {
95 		intr->zero_count = 0;
96 		return (FILTER_SCHEDULE_THREAD);
97 	}
98 
99 	/* SF bug 15783: If the function is not asserting its IRQ and
100 	 * we read the queue mask on the cycle before a flag is added
101 	 * to the mask, this inhibits the function from asserting the
102 	 * IRQ even though we don't see the flag set.  To work around
103 	 * this, we must re-prime all event queues and report the IRQ
104 	 * as handled when we see a mask of zero.  To allow for shared
105 	 * IRQs, we don't repeat this if we see a mask of zero twice
106 	 * or more in a row.
107 	 */
108 	if (intr->zero_count++ == 0) {
109 		if (evq->init_state == SFXGE_EVQ_STARTED) {
110 			if (efx_ev_qpending(evq->common, evq->read_ptr))
111 				return (FILTER_SCHEDULE_THREAD);
112 			efx_ev_qprime(evq->common, evq->read_ptr);
113 			return (FILTER_HANDLED);
114 		}
115 	}
116 
117 	return (FILTER_STRAY);
118 }
119 
120 static void
121 sfxge_intr_line(void *arg)
122 {
123 	struct sfxge_evq *evq = arg;
124 
125 	(void)sfxge_ev_qpoll(evq);
126 }
127 
128 static void
129 sfxge_intr_message(void *arg)
130 {
131 	struct sfxge_evq *evq;
132 	struct sfxge_softc *sc;
133 	efx_nic_t *enp;
134 	struct sfxge_intr *intr;
135 	unsigned int index;
136 	boolean_t fatal;
137 
138 	evq = (struct sfxge_evq *)arg;
139 	sc = evq->sc;
140 	enp = sc->enp;
141 	intr = &sc->intr;
142 	index = evq->index;
143 
144 	KASSERT(intr != NULL, ("intr == NULL"));
145 	KASSERT(intr->type == EFX_INTR_MESSAGE,
146 	    ("intr->type != EFX_INTR_MESSAGE"));
147 
148 	if (__predict_false(intr->state != SFXGE_INTR_STARTED))
149 		return;
150 
151 	(void)efx_intr_status_message(enp, index, &fatal);
152 
153 	if (fatal) {
154 		(void)efx_intr_disable(enp);
155 		(void)efx_intr_fatal(enp);
156 		return;
157 	}
158 
159 	(void)sfxge_ev_qpoll(evq);
160 }
161 
162 static int
163 sfxge_intr_bus_enable(struct sfxge_softc *sc)
164 {
165 	struct sfxge_intr *intr;
166 	struct sfxge_intr_hdl *table;
167 	driver_filter_t *filter;
168 	driver_intr_t *handler;
169 	int index;
170 	int err;
171 
172 	intr = &sc->intr;
173 	table = intr->table;
174 
175 	switch (intr->type) {
176 	case EFX_INTR_MESSAGE:
177 		filter = NULL; /* not shared */
178 		handler = sfxge_intr_message;
179 		break;
180 
181 	case EFX_INTR_LINE:
182 		filter = sfxge_intr_line_filter;
183 		handler = sfxge_intr_line;
184 		break;
185 
186 	default:
187 		KASSERT(0, ("Invalid interrupt type"));
188 		return (EINVAL);
189 	}
190 
191 	/* Try to add the handlers */
192 	for (index = 0; index < intr->n_alloc; index++) {
193 		if ((err = bus_setup_intr(sc->dev, table[index].eih_res,
194 			    INTR_MPSAFE|INTR_TYPE_NET, filter, handler,
195 			    sc->evq[index], &table[index].eih_tag)) != 0) {
196 			goto fail;
197 		}
198 		if (intr->n_alloc > 1)
199 			bus_describe_intr(sc->dev, table[index].eih_res,
200 			    table[index].eih_tag, "%d", index);
201 #ifdef RSS
202 		bus_bind_intr(sc->dev, table[index].eih_res,
203 			      rss_getcpu(index));
204 #else
205 		bus_bind_intr(sc->dev, table[index].eih_res, index);
206 #endif
207 	}
208 
209 	return (0);
210 
211 fail:
212 	/* Remove remaining handlers */
213 	while (--index >= 0)
214 		bus_teardown_intr(sc->dev, table[index].eih_res,
215 		    table[index].eih_tag);
216 
217 	return (err);
218 }
219 
220 static void
221 sfxge_intr_bus_disable(struct sfxge_softc *sc)
222 {
223 	struct sfxge_intr *intr;
224 	struct sfxge_intr_hdl *table;
225 	int i;
226 
227 	intr = &sc->intr;
228 	table = intr->table;
229 
230 	/* Remove all handlers */
231 	for (i = 0; i < intr->n_alloc; i++)
232 		bus_teardown_intr(sc->dev, table[i].eih_res,
233 		    table[i].eih_tag);
234 }
235 
236 static int
237 sfxge_intr_alloc(struct sfxge_softc *sc, int count)
238 {
239 	device_t dev;
240 	struct sfxge_intr_hdl *table;
241 	struct sfxge_intr *intr;
242 	struct resource *res;
243 	int rid;
244 	int error;
245 	int i;
246 
247 	dev = sc->dev;
248 	intr = &sc->intr;
249 	error = 0;
250 
251 	table = malloc(count * sizeof(struct sfxge_intr_hdl),
252 	    M_SFXGE, M_WAITOK);
253 	intr->table = table;
254 
255 	for (i = 0; i < count; i++) {
256 		rid = i + 1;
257 		res = bus_alloc_resource_any(dev, SYS_RES_IRQ, &rid,
258 		    RF_SHAREABLE | RF_ACTIVE);
259 		if (res == NULL) {
260 			device_printf(dev, "Couldn't allocate interrupts for "
261 			    "message %d\n", rid);
262 			error = ENOMEM;
263 			break;
264 		}
265 		table[i].eih_rid = rid;
266 		table[i].eih_res = res;
267 	}
268 
269 	if (error != 0) {
270 		count = i - 1;
271 		for (i = 0; i < count; i++)
272 			bus_release_resource(dev, SYS_RES_IRQ,
273 			    table[i].eih_rid, table[i].eih_res);
274 	}
275 
276 	return (error);
277 }
278 
279 static void
280 sfxge_intr_teardown_msix(struct sfxge_softc *sc)
281 {
282 	device_t dev;
283 	struct resource *resp;
284 	int rid;
285 
286 	dev = sc->dev;
287 	resp = sc->intr.msix_res;
288 
289 	rid = rman_get_rid(resp);
290 	bus_release_resource(dev, SYS_RES_MEMORY, rid, resp);
291 }
292 
293 static int
294 sfxge_intr_setup_msix(struct sfxge_softc *sc)
295 {
296 	struct sfxge_intr *intr;
297 	struct resource *resp;
298 	device_t dev;
299 	int count;
300 	int rid;
301 
302 	dev = sc->dev;
303 	intr = &sc->intr;
304 
305 	/* Check if MSI-X is available. */
306 	count = pci_msix_count(dev);
307 	if (count == 0)
308 		return (EINVAL);
309 
310 	/* Do not try to allocate more than already estimated EVQ maximum */
311 	KASSERT(sc->evq_max > 0, ("evq_max is zero"));
312 	count = MIN(count, sc->evq_max);
313 
314 	rid = PCIR_BAR(4);
315 	resp = bus_alloc_resource_any(dev, SYS_RES_MEMORY, &rid, RF_ACTIVE);
316 	if (resp == NULL)
317 		return (ENOMEM);
318 
319 	if (pci_alloc_msix(dev, &count) != 0) {
320 		bus_release_resource(dev, SYS_RES_MEMORY, rid, resp);
321 		return (ENOMEM);
322 	}
323 
324 	/* Allocate interrupt handlers. */
325 	if (sfxge_intr_alloc(sc, count) != 0) {
326 		bus_release_resource(dev, SYS_RES_MEMORY, rid, resp);
327 		pci_release_msi(dev);
328 		return (ENOMEM);
329 	}
330 
331 	intr->type = EFX_INTR_MESSAGE;
332 	intr->n_alloc = count;
333 	intr->msix_res = resp;
334 
335 	return (0);
336 }
337 
338 static int
339 sfxge_intr_setup_msi(struct sfxge_softc *sc)
340 {
341 	struct sfxge_intr *intr;
342 	device_t dev;
343 	int count;
344 	int error;
345 
346 	dev = sc->dev;
347 	intr = &sc->intr;
348 
349 	/*
350 	 * Check if MSI is available.  All messages must be written to
351 	 * the same address and on x86 this means the IRQs have the
352 	 * same CPU affinity.  So we only ever allocate 1.
353 	 */
354 	count = pci_msi_count(dev) ? 1 : 0;
355 	if (count == 0)
356 		return (EINVAL);
357 
358 	if ((error = pci_alloc_msi(dev, &count)) != 0)
359 		return (ENOMEM);
360 
361 	/* Allocate interrupt handler. */
362 	if (sfxge_intr_alloc(sc, count) != 0) {
363 		pci_release_msi(dev);
364 		return (ENOMEM);
365 	}
366 
367 	intr->type = EFX_INTR_MESSAGE;
368 	intr->n_alloc = count;
369 
370 	return (0);
371 }
372 
373 static int
374 sfxge_intr_setup_fixed(struct sfxge_softc *sc)
375 {
376 	struct sfxge_intr_hdl *table;
377 	struct sfxge_intr *intr;
378 	struct resource *res;
379 	device_t dev;
380 	int rid;
381 
382 	dev = sc->dev;
383 	intr = &sc->intr;
384 
385 	rid = 0;
386 	res =  bus_alloc_resource_any(dev, SYS_RES_IRQ, &rid,
387 	    RF_SHAREABLE | RF_ACTIVE);
388 	if (res == NULL)
389 		return (ENOMEM);
390 
391 	table = malloc(sizeof(struct sfxge_intr_hdl), M_SFXGE, M_WAITOK);
392 	table[0].eih_rid = rid;
393 	table[0].eih_res = res;
394 
395 	intr->type = EFX_INTR_LINE;
396 	intr->n_alloc = 1;
397 	intr->table = table;
398 
399 	return (0);
400 }
401 
402 static const char *const __sfxge_err[] = {
403 	"",
404 	"SRAM out-of-bounds",
405 	"Buffer ID out-of-bounds",
406 	"Internal memory parity",
407 	"Receive buffer ownership",
408 	"Transmit buffer ownership",
409 	"Receive descriptor ownership",
410 	"Transmit descriptor ownership",
411 	"Event queue ownership",
412 	"Event queue FIFO overflow",
413 	"Illegal address",
414 	"SRAM parity"
415 };
416 
417 void
418 sfxge_err(efsys_identifier_t *arg, unsigned int code, uint32_t dword0,
419 	  uint32_t dword1)
420 {
421 	struct sfxge_softc *sc = (struct sfxge_softc *)arg;
422 	device_t dev = sc->dev;
423 
424 	log(LOG_WARNING, "[%s%d] FATAL ERROR: %s (0x%08x%08x)",
425 	    device_get_name(dev), device_get_unit(dev),
426 		__sfxge_err[code], dword1, dword0);
427 }
428 
429 void
430 sfxge_intr_stop(struct sfxge_softc *sc)
431 {
432 	struct sfxge_intr *intr;
433 
434 	intr = &sc->intr;
435 
436 	KASSERT(intr->state == SFXGE_INTR_STARTED,
437 	    ("Interrupts not started"));
438 
439 	intr->state = SFXGE_INTR_INITIALIZED;
440 
441 	/* Disable interrupts at the NIC */
442 	efx_intr_disable(sc->enp);
443 
444 	/* Disable interrupts at the bus */
445 	sfxge_intr_bus_disable(sc);
446 
447 	/* Tear down common code interrupt bits. */
448 	efx_intr_fini(sc->enp);
449 }
450 
451 int
452 sfxge_intr_start(struct sfxge_softc *sc)
453 {
454 	struct sfxge_intr *intr;
455 	efsys_mem_t *esmp;
456 	int rc;
457 
458 	intr = &sc->intr;
459 	esmp = &intr->status;
460 
461 	KASSERT(intr->state == SFXGE_INTR_INITIALIZED,
462 	    ("Interrupts not initialized"));
463 
464 	/* Zero the memory. */
465 	(void)memset(esmp->esm_base, 0, EFX_INTR_SIZE);
466 
467 	/* Initialize common code interrupt bits. */
468 	(void)efx_intr_init(sc->enp, intr->type, esmp);
469 
470 	/* Enable interrupts at the bus */
471 	if ((rc = sfxge_intr_bus_enable(sc)) != 0)
472 		goto fail;
473 
474 	intr->state = SFXGE_INTR_STARTED;
475 
476 	/* Enable interrupts at the NIC */
477 	efx_intr_enable(sc->enp);
478 
479 	return (0);
480 
481 fail:
482 	/* Tear down common code interrupt bits. */
483 	efx_intr_fini(sc->enp);
484 
485 	intr->state = SFXGE_INTR_INITIALIZED;
486 
487 	return (rc);
488 }
489 
490 void
491 sfxge_intr_fini(struct sfxge_softc *sc)
492 {
493 	struct sfxge_intr_hdl *table;
494 	struct sfxge_intr *intr;
495 	efsys_mem_t *esmp;
496 	device_t dev;
497 	int i;
498 
499 	dev = sc->dev;
500 	intr = &sc->intr;
501 	esmp = &intr->status;
502 	table = intr->table;
503 
504 	KASSERT(intr->state == SFXGE_INTR_INITIALIZED,
505 	    ("intr->state != SFXGE_INTR_INITIALIZED"));
506 
507 	/* Free DMA memory. */
508 	sfxge_dma_free(esmp);
509 
510 	/* Free interrupt handles. */
511 	for (i = 0; i < intr->n_alloc; i++)
512 		bus_release_resource(dev, SYS_RES_IRQ,
513 		    table[i].eih_rid, table[i].eih_res);
514 
515 	if (table[0].eih_rid != 0)
516 		pci_release_msi(dev);
517 
518 	if (intr->msix_res != NULL)
519 		sfxge_intr_teardown_msix(sc);
520 
521 	/* Free the handle table */
522 	free(table, M_SFXGE);
523 	intr->table = NULL;
524 	intr->n_alloc = 0;
525 
526 	/* Clear the interrupt type */
527 	intr->type = EFX_INTR_INVALID;
528 
529 	intr->state = SFXGE_INTR_UNINITIALIZED;
530 }
531 
532 int
533 sfxge_intr_init(struct sfxge_softc *sc)
534 {
535 	device_t dev;
536 	struct sfxge_intr *intr;
537 	efsys_mem_t *esmp;
538 	int rc;
539 
540 	dev = sc->dev;
541 	intr = &sc->intr;
542 	esmp = &intr->status;
543 
544 	KASSERT(intr->state == SFXGE_INTR_UNINITIALIZED,
545 	    ("Interrupts already initialized"));
546 
547 	/* Try to setup MSI-X or MSI interrupts if available. */
548 	if ((rc = sfxge_intr_setup_msix(sc)) == 0)
549 		device_printf(dev, "Using MSI-X interrupts\n");
550 	else if ((rc = sfxge_intr_setup_msi(sc)) == 0)
551 		device_printf(dev, "Using MSI interrupts\n");
552 	else if ((rc = sfxge_intr_setup_fixed(sc)) == 0) {
553 		device_printf(dev, "Using fixed interrupts\n");
554 	} else {
555 		device_printf(dev, "Couldn't setup interrupts\n");
556 		return (ENOMEM);
557 	}
558 
559 	/* Set up DMA for interrupts. */
560 	if ((rc = sfxge_dma_alloc(sc, EFX_INTR_SIZE, esmp)) != 0)
561 		return (ENOMEM);
562 
563 	intr->state = SFXGE_INTR_INITIALIZED;
564 
565 	return (0);
566 }
567