Deleted Added
full compact
sfxge_ev.c (280510) sfxge_ev.c (280513)
1/*-
2 * Copyright (c) 2010-2011 Solarflare Communications, Inc.
3 * All rights reserved.
4 *
5 * This software was developed in part by Philip Paeps under contract for
6 * Solarflare Communications, Inc.
7 *
8 * Redistribution and use in source and binary forms, with or without
9 * modification, are permitted provided that the following conditions
10 * are met:
11 * 1. Redistributions of source code must retain the above copyright
12 * notice, this list of conditions and the following disclaimer.
13 * 2. Redistributions in binary form must reproduce the above copyright
14 * notice, this list of conditions and the following disclaimer in the
15 * documentation and/or other materials provided with the distribution.
16 *
17 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
18 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
19 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
20 * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
21 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
22 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
23 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
24 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
25 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
26 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
27 * SUCH DAMAGE.
28 */
29
30#include <sys/cdefs.h>
1/*-
2 * Copyright (c) 2010-2011 Solarflare Communications, Inc.
3 * All rights reserved.
4 *
5 * This software was developed in part by Philip Paeps under contract for
6 * Solarflare Communications, Inc.
7 *
8 * Redistribution and use in source and binary forms, with or without
9 * modification, are permitted provided that the following conditions
10 * are met:
11 * 1. Redistributions of source code must retain the above copyright
12 * notice, this list of conditions and the following disclaimer.
13 * 2. Redistributions in binary form must reproduce the above copyright
14 * notice, this list of conditions and the following disclaimer in the
15 * documentation and/or other materials provided with the distribution.
16 *
17 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
18 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
19 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
20 * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
21 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
22 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
23 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
24 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
25 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
26 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
27 * SUCH DAMAGE.
28 */
29
30#include <sys/cdefs.h>
31__FBSDID("$FreeBSD: stable/10/sys/dev/sfxge/sfxge_ev.c 280510 2015-03-25 10:13:19Z arybchik $");
31__FBSDID("$FreeBSD: stable/10/sys/dev/sfxge/sfxge_ev.c 280513 2015-03-25 10:17:24Z arybchik $");
32
33#include <sys/param.h>
34#include <sys/systm.h>
35
36#include "common/efx.h"
37
38#include "sfxge.h"
39
40static void
41sfxge_ev_qcomplete(struct sfxge_evq *evq, boolean_t eop)
42{
43 struct sfxge_softc *sc;
44 unsigned int index;
45 struct sfxge_rxq *rxq;
46 struct sfxge_txq *txq;
47
48 sc = evq->sc;
49 index = evq->index;
50 rxq = sc->rxq[index];
51
52 if ((txq = evq->txq) != NULL) {
53 evq->txq = NULL;
54 evq->txqs = &(evq->txq);
55
56 do {
57 struct sfxge_txq *next;
58
59 next = txq->next;
60 txq->next = NULL;
61
62 KASSERT(txq->evq_index == index,
63 ("txq->evq_index != index"));
64
65 if (txq->pending != txq->completed)
32
33#include <sys/param.h>
34#include <sys/systm.h>
35
36#include "common/efx.h"
37
38#include "sfxge.h"
39
40static void
41sfxge_ev_qcomplete(struct sfxge_evq *evq, boolean_t eop)
42{
43 struct sfxge_softc *sc;
44 unsigned int index;
45 struct sfxge_rxq *rxq;
46 struct sfxge_txq *txq;
47
48 sc = evq->sc;
49 index = evq->index;
50 rxq = sc->rxq[index];
51
52 if ((txq = evq->txq) != NULL) {
53 evq->txq = NULL;
54 evq->txqs = &(evq->txq);
55
56 do {
57 struct sfxge_txq *next;
58
59 next = txq->next;
60 txq->next = NULL;
61
62 KASSERT(txq->evq_index == index,
63 ("txq->evq_index != index"));
64
65 if (txq->pending != txq->completed)
66 sfxge_tx_qcomplete(txq);
66 sfxge_tx_qcomplete(txq, evq);
67
68 txq = next;
69 } while (txq != NULL);
70 }
71
72 if (rxq->pending != rxq->completed)
73 sfxge_rx_qcomplete(rxq, eop);
74}
75
76static boolean_t
77sfxge_ev_rx(void *arg, uint32_t label, uint32_t id, uint32_t size,
78 uint16_t flags)
79{
80 struct sfxge_evq *evq;
81 struct sfxge_softc *sc;
82 struct sfxge_rxq *rxq;
83 unsigned int expected;
84 struct sfxge_rx_sw_desc *rx_desc;
85
86 evq = arg;
87 sc = evq->sc;
88
89 if (evq->exception)
90 goto done;
91
92 rxq = sc->rxq[label];
93 KASSERT(rxq != NULL, ("rxq == NULL"));
94 KASSERT(evq->index == rxq->index,
95 ("evq->index != rxq->index"));
96
97 if (rxq->init_state != SFXGE_RXQ_STARTED)
98 goto done;
99
100 expected = rxq->pending++ & rxq->ptr_mask;
101 if (id != expected) {
102 evq->exception = B_TRUE;
103
104 device_printf(sc->dev, "RX completion out of order"
105 " (id=%#x expected=%#x flags=%#x); resetting\n",
106 id, expected, flags);
107 sfxge_schedule_reset(sc);
108
109 goto done;
110 }
111
112 rx_desc = &rxq->queue[id];
113
114 KASSERT(rx_desc->flags == EFX_DISCARD,
115 ("rx_desc->flags != EFX_DISCARD"));
116 rx_desc->flags = flags;
117
118 KASSERT(size < (1 << 16), ("size > (1 << 16)"));
119 rx_desc->size = (uint16_t)size;
120 prefetch_read_many(rx_desc->mbuf);
121
122 evq->rx_done++;
123
124 if (rxq->pending - rxq->completed >= SFXGE_RX_BATCH)
125 sfxge_ev_qcomplete(evq, B_FALSE);
126
127done:
128 return (evq->rx_done >= SFXGE_EV_BATCH);
129}
130
131static boolean_t
132sfxge_ev_exception(void *arg, uint32_t code, uint32_t data)
133{
134 struct sfxge_evq *evq;
135 struct sfxge_softc *sc;
136
137 evq = (struct sfxge_evq *)arg;
138 sc = evq->sc;
139
140 evq->exception = B_TRUE;
141
142 if (code != EFX_EXCEPTION_UNKNOWN_SENSOREVT) {
143 device_printf(sc->dev,
144 "hardware exception (code=%u); resetting\n",
145 code);
146 sfxge_schedule_reset(sc);
147 }
148
149 return (B_FALSE);
150}
151
152static boolean_t
153sfxge_ev_rxq_flush_done(void *arg, uint32_t rxq_index)
154{
155 struct sfxge_evq *evq;
156 struct sfxge_softc *sc;
157 struct sfxge_rxq *rxq;
158 unsigned int index;
159 unsigned int label;
160 uint16_t magic;
161
162 evq = (struct sfxge_evq *)arg;
163 sc = evq->sc;
164 rxq = sc->rxq[rxq_index];
165
166 KASSERT(rxq != NULL, ("rxq == NULL"));
167
168 /* Resend a software event on the correct queue */
169 index = rxq->index;
170 evq = sc->evq[index];
171
172 label = rxq_index;
173 KASSERT((label & SFXGE_MAGIC_DMAQ_LABEL_MASK) == label,
174 ("(label & SFXGE_MAGIC_DMAQ_LABEL_MASK) != level"));
175 magic = SFXGE_MAGIC_RX_QFLUSH_DONE | label;
176
177 KASSERT(evq->init_state == SFXGE_EVQ_STARTED,
178 ("evq not started"));
179 efx_ev_qpost(evq->common, magic);
180
181 return (B_FALSE);
182}
183
184static boolean_t
185sfxge_ev_rxq_flush_failed(void *arg, uint32_t rxq_index)
186{
187 struct sfxge_evq *evq;
188 struct sfxge_softc *sc;
189 struct sfxge_rxq *rxq;
190 unsigned int index;
191 unsigned int label;
192 uint16_t magic;
193
194 evq = (struct sfxge_evq *)arg;
195 sc = evq->sc;
196 rxq = sc->rxq[rxq_index];
197
198 KASSERT(rxq != NULL, ("rxq == NULL"));
199
200 /* Resend a software event on the correct queue */
201 index = rxq->index;
202 evq = sc->evq[index];
203
204 label = rxq_index;
205 KASSERT((label & SFXGE_MAGIC_DMAQ_LABEL_MASK) == label,
206 ("(label & SFXGE_MAGIC_DMAQ_LABEL_MASK) != label"));
207 magic = SFXGE_MAGIC_RX_QFLUSH_FAILED | label;
208
209 KASSERT(evq->init_state == SFXGE_EVQ_STARTED,
210 ("evq not started"));
211 efx_ev_qpost(evq->common, magic);
212
213 return (B_FALSE);
214}
215
216static struct sfxge_txq *
217sfxge_get_txq_by_label(struct sfxge_evq *evq, enum sfxge_txq_type label)
218{
219 unsigned int index;
220
221 KASSERT((evq->index == 0 && label < SFXGE_TXQ_NTYPES) ||
222 (label == SFXGE_TXQ_IP_TCP_UDP_CKSUM), ("unexpected txq label"));
223 index = (evq->index == 0) ? label : (evq->index - 1 + SFXGE_TXQ_NTYPES);
224 return (evq->sc->txq[index]);
225}
226
227static boolean_t
228sfxge_ev_tx(void *arg, uint32_t label, uint32_t id)
229{
230 struct sfxge_evq *evq;
231 struct sfxge_txq *txq;
232 unsigned int stop;
233 unsigned int delta;
234
235 evq = (struct sfxge_evq *)arg;
236 txq = sfxge_get_txq_by_label(evq, label);
237
238 KASSERT(txq != NULL, ("txq == NULL"));
239 KASSERT(evq->index == txq->evq_index,
240 ("evq->index != txq->evq_index"));
241
242 if (txq->init_state != SFXGE_TXQ_STARTED)
243 goto done;
244
245 stop = (id + 1) & txq->ptr_mask;
246 id = txq->pending & txq->ptr_mask;
247
248 delta = (stop >= id) ? (stop - id) : (txq->entries - id + stop);
249 txq->pending += delta;
250
251 evq->tx_done++;
252
253 if (txq->next == NULL &&
254 evq->txqs != &(txq->next)) {
255 *(evq->txqs) = txq;
256 evq->txqs = &(txq->next);
257 }
258
259 if (txq->pending - txq->completed >= SFXGE_TX_BATCH)
67
68 txq = next;
69 } while (txq != NULL);
70 }
71
72 if (rxq->pending != rxq->completed)
73 sfxge_rx_qcomplete(rxq, eop);
74}
75
76static boolean_t
77sfxge_ev_rx(void *arg, uint32_t label, uint32_t id, uint32_t size,
78 uint16_t flags)
79{
80 struct sfxge_evq *evq;
81 struct sfxge_softc *sc;
82 struct sfxge_rxq *rxq;
83 unsigned int expected;
84 struct sfxge_rx_sw_desc *rx_desc;
85
86 evq = arg;
87 sc = evq->sc;
88
89 if (evq->exception)
90 goto done;
91
92 rxq = sc->rxq[label];
93 KASSERT(rxq != NULL, ("rxq == NULL"));
94 KASSERT(evq->index == rxq->index,
95 ("evq->index != rxq->index"));
96
97 if (rxq->init_state != SFXGE_RXQ_STARTED)
98 goto done;
99
100 expected = rxq->pending++ & rxq->ptr_mask;
101 if (id != expected) {
102 evq->exception = B_TRUE;
103
104 device_printf(sc->dev, "RX completion out of order"
105 " (id=%#x expected=%#x flags=%#x); resetting\n",
106 id, expected, flags);
107 sfxge_schedule_reset(sc);
108
109 goto done;
110 }
111
112 rx_desc = &rxq->queue[id];
113
114 KASSERT(rx_desc->flags == EFX_DISCARD,
115 ("rx_desc->flags != EFX_DISCARD"));
116 rx_desc->flags = flags;
117
118 KASSERT(size < (1 << 16), ("size > (1 << 16)"));
119 rx_desc->size = (uint16_t)size;
120 prefetch_read_many(rx_desc->mbuf);
121
122 evq->rx_done++;
123
124 if (rxq->pending - rxq->completed >= SFXGE_RX_BATCH)
125 sfxge_ev_qcomplete(evq, B_FALSE);
126
127done:
128 return (evq->rx_done >= SFXGE_EV_BATCH);
129}
130
131static boolean_t
132sfxge_ev_exception(void *arg, uint32_t code, uint32_t data)
133{
134 struct sfxge_evq *evq;
135 struct sfxge_softc *sc;
136
137 evq = (struct sfxge_evq *)arg;
138 sc = evq->sc;
139
140 evq->exception = B_TRUE;
141
142 if (code != EFX_EXCEPTION_UNKNOWN_SENSOREVT) {
143 device_printf(sc->dev,
144 "hardware exception (code=%u); resetting\n",
145 code);
146 sfxge_schedule_reset(sc);
147 }
148
149 return (B_FALSE);
150}
151
152static boolean_t
153sfxge_ev_rxq_flush_done(void *arg, uint32_t rxq_index)
154{
155 struct sfxge_evq *evq;
156 struct sfxge_softc *sc;
157 struct sfxge_rxq *rxq;
158 unsigned int index;
159 unsigned int label;
160 uint16_t magic;
161
162 evq = (struct sfxge_evq *)arg;
163 sc = evq->sc;
164 rxq = sc->rxq[rxq_index];
165
166 KASSERT(rxq != NULL, ("rxq == NULL"));
167
168 /* Resend a software event on the correct queue */
169 index = rxq->index;
170 evq = sc->evq[index];
171
172 label = rxq_index;
173 KASSERT((label & SFXGE_MAGIC_DMAQ_LABEL_MASK) == label,
174 ("(label & SFXGE_MAGIC_DMAQ_LABEL_MASK) != level"));
175 magic = SFXGE_MAGIC_RX_QFLUSH_DONE | label;
176
177 KASSERT(evq->init_state == SFXGE_EVQ_STARTED,
178 ("evq not started"));
179 efx_ev_qpost(evq->common, magic);
180
181 return (B_FALSE);
182}
183
184static boolean_t
185sfxge_ev_rxq_flush_failed(void *arg, uint32_t rxq_index)
186{
187 struct sfxge_evq *evq;
188 struct sfxge_softc *sc;
189 struct sfxge_rxq *rxq;
190 unsigned int index;
191 unsigned int label;
192 uint16_t magic;
193
194 evq = (struct sfxge_evq *)arg;
195 sc = evq->sc;
196 rxq = sc->rxq[rxq_index];
197
198 KASSERT(rxq != NULL, ("rxq == NULL"));
199
200 /* Resend a software event on the correct queue */
201 index = rxq->index;
202 evq = sc->evq[index];
203
204 label = rxq_index;
205 KASSERT((label & SFXGE_MAGIC_DMAQ_LABEL_MASK) == label,
206 ("(label & SFXGE_MAGIC_DMAQ_LABEL_MASK) != label"));
207 magic = SFXGE_MAGIC_RX_QFLUSH_FAILED | label;
208
209 KASSERT(evq->init_state == SFXGE_EVQ_STARTED,
210 ("evq not started"));
211 efx_ev_qpost(evq->common, magic);
212
213 return (B_FALSE);
214}
215
216static struct sfxge_txq *
217sfxge_get_txq_by_label(struct sfxge_evq *evq, enum sfxge_txq_type label)
218{
219 unsigned int index;
220
221 KASSERT((evq->index == 0 && label < SFXGE_TXQ_NTYPES) ||
222 (label == SFXGE_TXQ_IP_TCP_UDP_CKSUM), ("unexpected txq label"));
223 index = (evq->index == 0) ? label : (evq->index - 1 + SFXGE_TXQ_NTYPES);
224 return (evq->sc->txq[index]);
225}
226
227static boolean_t
228sfxge_ev_tx(void *arg, uint32_t label, uint32_t id)
229{
230 struct sfxge_evq *evq;
231 struct sfxge_txq *txq;
232 unsigned int stop;
233 unsigned int delta;
234
235 evq = (struct sfxge_evq *)arg;
236 txq = sfxge_get_txq_by_label(evq, label);
237
238 KASSERT(txq != NULL, ("txq == NULL"));
239 KASSERT(evq->index == txq->evq_index,
240 ("evq->index != txq->evq_index"));
241
242 if (txq->init_state != SFXGE_TXQ_STARTED)
243 goto done;
244
245 stop = (id + 1) & txq->ptr_mask;
246 id = txq->pending & txq->ptr_mask;
247
248 delta = (stop >= id) ? (stop - id) : (txq->entries - id + stop);
249 txq->pending += delta;
250
251 evq->tx_done++;
252
253 if (txq->next == NULL &&
254 evq->txqs != &(txq->next)) {
255 *(evq->txqs) = txq;
256 evq->txqs = &(txq->next);
257 }
258
259 if (txq->pending - txq->completed >= SFXGE_TX_BATCH)
260 sfxge_tx_qcomplete(txq);
260 sfxge_tx_qcomplete(txq, evq);
261
262done:
263 return (evq->tx_done >= SFXGE_EV_BATCH);
264}
265
266static boolean_t
267sfxge_ev_txq_flush_done(void *arg, uint32_t txq_index)
268{
269 struct sfxge_evq *evq;
270 struct sfxge_softc *sc;
271 struct sfxge_txq *txq;
272 unsigned int label;
273 uint16_t magic;
274
275 evq = (struct sfxge_evq *)arg;
276 sc = evq->sc;
277 txq = sc->txq[txq_index];
278
279 KASSERT(txq != NULL, ("txq == NULL"));
280 KASSERT(txq->init_state == SFXGE_TXQ_INITIALIZED,
281 ("txq not initialized"));
282
283 /* Resend a software event on the correct queue */
284 evq = sc->evq[txq->evq_index];
285
286 label = txq->type;
287 KASSERT((label & SFXGE_MAGIC_DMAQ_LABEL_MASK) == label,
288 ("(label & SFXGE_MAGIC_DMAQ_LABEL_MASK) != label"));
289 magic = SFXGE_MAGIC_TX_QFLUSH_DONE | label;
290
291 KASSERT(evq->init_state == SFXGE_EVQ_STARTED,
292 ("evq not started"));
293 efx_ev_qpost(evq->common, magic);
294
295 return (B_FALSE);
296}
297
298static boolean_t
299sfxge_ev_software(void *arg, uint16_t magic)
300{
301 struct sfxge_evq *evq;
302 struct sfxge_softc *sc;
303 unsigned int label;
304
305 evq = (struct sfxge_evq *)arg;
306 sc = evq->sc;
307
308 label = magic & SFXGE_MAGIC_DMAQ_LABEL_MASK;
309 magic &= ~SFXGE_MAGIC_DMAQ_LABEL_MASK;
310
311 switch (magic) {
312 case SFXGE_MAGIC_RX_QFLUSH_DONE: {
313 struct sfxge_rxq *rxq = sc->rxq[label];
314
315 KASSERT(rxq != NULL, ("rxq == NULL"));
316 KASSERT(evq->index == rxq->index,
317 ("evq->index != rxq->index"));
318
319 sfxge_rx_qflush_done(rxq);
320 break;
321 }
322 case SFXGE_MAGIC_RX_QFLUSH_FAILED: {
323 struct sfxge_rxq *rxq = sc->rxq[label];
324
325 KASSERT(rxq != NULL, ("rxq == NULL"));
326 KASSERT(evq->index == rxq->index,
327 ("evq->index != rxq->index"));
328
329 sfxge_rx_qflush_failed(rxq);
330 break;
331 }
332 case SFXGE_MAGIC_RX_QREFILL: {
333 struct sfxge_rxq *rxq = sc->rxq[label];
334
335 KASSERT(rxq != NULL, ("rxq == NULL"));
336 KASSERT(evq->index == rxq->index,
337 ("evq->index != rxq->index"));
338
339 sfxge_rx_qrefill(rxq);
340 break;
341 }
342 case SFXGE_MAGIC_TX_QFLUSH_DONE: {
343 struct sfxge_txq *txq = sfxge_get_txq_by_label(evq, label);
344
345 KASSERT(txq != NULL, ("txq == NULL"));
346 KASSERT(evq->index == txq->evq_index,
347 ("evq->index != txq->evq_index"));
348
349 sfxge_tx_qflush_done(txq);
350 break;
351 }
352 default:
353 break;
354 }
355
356 return (B_FALSE);
357}
358
359static boolean_t
360sfxge_ev_sram(void *arg, uint32_t code)
361{
362 (void)arg;
363 (void)code;
364
365 switch (code) {
366 case EFX_SRAM_UPDATE:
367 EFSYS_PROBE(sram_update);
368 break;
369
370 case EFX_SRAM_CLEAR:
371 EFSYS_PROBE(sram_clear);
372 break;
373
374 case EFX_SRAM_ILLEGAL_CLEAR:
375 EFSYS_PROBE(sram_illegal_clear);
376 break;
377
378 default:
379 KASSERT(B_FALSE, ("Impossible SRAM event"));
380 break;
381 }
382
383 return (B_FALSE);
384}
385
386static boolean_t
387sfxge_ev_timer(void *arg, uint32_t index)
388{
389 (void)arg;
390 (void)index;
391
392 return (B_FALSE);
393}
394
395static boolean_t
396sfxge_ev_wake_up(void *arg, uint32_t index)
397{
398 (void)arg;
399 (void)index;
400
401 return (B_FALSE);
402}
403
404#if EFSYS_OPT_QSTATS
405
406static void
407sfxge_ev_stat_update(struct sfxge_softc *sc)
408{
409 struct sfxge_evq *evq;
410 unsigned int index;
411 clock_t now;
412
413 sx_xlock(&sc->softc_lock);
414
415 if (sc->evq[0]->init_state != SFXGE_EVQ_STARTED)
416 goto out;
417
418 now = ticks;
419 if (now - sc->ev_stats_update_time < hz)
420 goto out;
421
422 sc->ev_stats_update_time = now;
423
424 /* Add event counts from each event queue in turn */
425 for (index = 0; index < sc->intr.n_alloc; index++) {
426 evq = sc->evq[index];
427 mtx_lock(&evq->lock);
428 efx_ev_qstats_update(evq->common, sc->ev_stats);
429 mtx_unlock(&evq->lock);
430 }
431out:
432 sx_xunlock(&sc->softc_lock);
433}
434
435static int
436sfxge_ev_stat_handler(SYSCTL_HANDLER_ARGS)
437{
438 struct sfxge_softc *sc = arg1;
439 unsigned int id = arg2;
440
441 sfxge_ev_stat_update(sc);
442
443 return (SYSCTL_OUT(req, &sc->ev_stats[id], sizeof(sc->ev_stats[id])));
444}
445
446static void
447sfxge_ev_stat_init(struct sfxge_softc *sc)
448{
449 struct sysctl_ctx_list *ctx = device_get_sysctl_ctx(sc->dev);
450 struct sysctl_oid_list *stat_list;
451 unsigned int id;
452 char name[40];
453
454 stat_list = SYSCTL_CHILDREN(sc->stats_node);
455
456 for (id = 0; id < EV_NQSTATS; id++) {
457 snprintf(name, sizeof(name), "ev_%s",
458 efx_ev_qstat_name(sc->enp, id));
459 SYSCTL_ADD_PROC(
460 ctx, stat_list,
461 OID_AUTO, name, CTLTYPE_U64|CTLFLAG_RD,
462 sc, id, sfxge_ev_stat_handler, "Q",
463 "");
464 }
465}
466
467#endif /* EFSYS_OPT_QSTATS */
468
469static void
470sfxge_ev_qmoderate(struct sfxge_softc *sc, unsigned int idx, unsigned int us)
471{
472 struct sfxge_evq *evq;
473 efx_evq_t *eep;
474
475 evq = sc->evq[idx];
476 eep = evq->common;
477
478 KASSERT(evq->init_state == SFXGE_EVQ_STARTED,
479 ("evq->init_state != SFXGE_EVQ_STARTED"));
480
481 (void)efx_ev_qmoderate(eep, us);
482}
483
484static int
485sfxge_int_mod_handler(SYSCTL_HANDLER_ARGS)
486{
487 struct sfxge_softc *sc = arg1;
488 struct sfxge_intr *intr = &sc->intr;
489 unsigned int moderation;
490 int error;
491 int index;
492
493 sx_xlock(&sc->softc_lock);
494
495 if (req->newptr != NULL) {
496 if ((error = SYSCTL_IN(req, &moderation, sizeof(moderation)))
497 != 0)
498 goto out;
499
500 /* We may not be calling efx_ev_qmoderate() now,
501 * so we have to range-check the value ourselves.
502 */
503 if (moderation >
504 efx_nic_cfg_get(sc->enp)->enc_evq_moderation_max) {
505 error = EINVAL;
506 goto out;
507 }
508
509 sc->ev_moderation = moderation;
510 if (intr->state == SFXGE_INTR_STARTED) {
511 for (index = 0; index < intr->n_alloc; index++)
512 sfxge_ev_qmoderate(sc, index, moderation);
513 }
514 } else {
515 error = SYSCTL_OUT(req, &sc->ev_moderation,
516 sizeof(sc->ev_moderation));
517 }
518
519out:
520 sx_xunlock(&sc->softc_lock);
521
522 return (error);
523}
524
525static boolean_t
526sfxge_ev_initialized(void *arg)
527{
528 struct sfxge_evq *evq;
529
530 evq = (struct sfxge_evq *)arg;
531
532 KASSERT(evq->init_state == SFXGE_EVQ_STARTING,
533 ("evq not starting"));
534
535 evq->init_state = SFXGE_EVQ_STARTED;
536
537 return (0);
538}
539
540static boolean_t
541sfxge_ev_link_change(void *arg, efx_link_mode_t link_mode)
542{
543 struct sfxge_evq *evq;
544 struct sfxge_softc *sc;
545
546 evq = (struct sfxge_evq *)arg;
547 sc = evq->sc;
548
549 sfxge_mac_link_update(sc, link_mode);
550
551 return (0);
552}
553
554static const efx_ev_callbacks_t sfxge_ev_callbacks = {
555 .eec_initialized = sfxge_ev_initialized,
556 .eec_rx = sfxge_ev_rx,
557 .eec_tx = sfxge_ev_tx,
558 .eec_exception = sfxge_ev_exception,
559 .eec_rxq_flush_done = sfxge_ev_rxq_flush_done,
560 .eec_rxq_flush_failed = sfxge_ev_rxq_flush_failed,
561 .eec_txq_flush_done = sfxge_ev_txq_flush_done,
562 .eec_software = sfxge_ev_software,
563 .eec_sram = sfxge_ev_sram,
564 .eec_wake_up = sfxge_ev_wake_up,
565 .eec_timer = sfxge_ev_timer,
566 .eec_link_change = sfxge_ev_link_change,
567};
568
569
570int
571sfxge_ev_qpoll(struct sfxge_evq *evq)
572{
573 int rc;
574
575 mtx_lock(&evq->lock);
576
577 if (evq->init_state != SFXGE_EVQ_STARTING &&
578 evq->init_state != SFXGE_EVQ_STARTED) {
579 rc = EINVAL;
580 goto fail;
581 }
582
583 /* Synchronize the DMA memory for reading */
584 bus_dmamap_sync(evq->mem.esm_tag, evq->mem.esm_map,
585 BUS_DMASYNC_POSTREAD);
586
587 KASSERT(evq->rx_done == 0, ("evq->rx_done != 0"));
588 KASSERT(evq->tx_done == 0, ("evq->tx_done != 0"));
589 KASSERT(evq->txq == NULL, ("evq->txq != NULL"));
590 KASSERT(evq->txqs == &evq->txq, ("evq->txqs != &evq->txq"));
591
592 /* Poll the queue */
593 efx_ev_qpoll(evq->common, &evq->read_ptr, &sfxge_ev_callbacks, evq);
594
595 evq->rx_done = 0;
596 evq->tx_done = 0;
597
598 /* Perform any pending completion processing */
599 sfxge_ev_qcomplete(evq, B_TRUE);
600
601 /* Re-prime the event queue for interrupts */
602 if ((rc = efx_ev_qprime(evq->common, evq->read_ptr)) != 0)
603 goto fail;
604
605 mtx_unlock(&evq->lock);
606
607 return (0);
608
609fail:
610 mtx_unlock(&(evq->lock));
611 return (rc);
612}
613
614static void
615sfxge_ev_qstop(struct sfxge_softc *sc, unsigned int index)
616{
617 struct sfxge_evq *evq;
618
619 evq = sc->evq[index];
620
621 KASSERT(evq->init_state == SFXGE_EVQ_STARTED,
622 ("evq->init_state != SFXGE_EVQ_STARTED"));
623
624 mtx_lock(&evq->lock);
625 evq->init_state = SFXGE_EVQ_INITIALIZED;
626 evq->read_ptr = 0;
627 evq->exception = B_FALSE;
628
629#if EFSYS_OPT_QSTATS
630 /* Add event counts before discarding the common evq state */
631 efx_ev_qstats_update(evq->common, sc->ev_stats);
632#endif
633
634 efx_ev_qdestroy(evq->common);
635 efx_sram_buf_tbl_clear(sc->enp, evq->buf_base_id,
636 EFX_EVQ_NBUFS(evq->entries));
637 mtx_unlock(&evq->lock);
638}
639
640static int
641sfxge_ev_qstart(struct sfxge_softc *sc, unsigned int index)
642{
643 struct sfxge_evq *evq;
644 efsys_mem_t *esmp;
645 int count;
646 int rc;
647
648 evq = sc->evq[index];
649 esmp = &evq->mem;
650
651 KASSERT(evq->init_state == SFXGE_EVQ_INITIALIZED,
652 ("evq->init_state != SFXGE_EVQ_INITIALIZED"));
653
654 /* Clear all events. */
655 (void)memset(esmp->esm_base, 0xff, EFX_EVQ_SIZE(evq->entries));
656
657 /* Program the buffer table. */
658 if ((rc = efx_sram_buf_tbl_set(sc->enp, evq->buf_base_id, esmp,
659 EFX_EVQ_NBUFS(evq->entries))) != 0)
660 return (rc);
661
662 /* Create the common code event queue. */
663 if ((rc = efx_ev_qcreate(sc->enp, index, esmp, evq->entries,
664 evq->buf_base_id, &evq->common)) != 0)
665 goto fail;
666
667 mtx_lock(&evq->lock);
668
669 /* Set the default moderation */
670 (void)efx_ev_qmoderate(evq->common, sc->ev_moderation);
671
672 /* Prime the event queue for interrupts */
673 if ((rc = efx_ev_qprime(evq->common, evq->read_ptr)) != 0)
674 goto fail2;
675
676 evq->init_state = SFXGE_EVQ_STARTING;
677
678 mtx_unlock(&evq->lock);
679
680 /* Wait for the initialization event */
681 count = 0;
682 do {
683 /* Pause for 100 ms */
684 pause("sfxge evq init", hz / 10);
685
686 /* Check to see if the test event has been processed */
687 if (evq->init_state == SFXGE_EVQ_STARTED)
688 goto done;
689
690 } while (++count < 20);
691
692 rc = ETIMEDOUT;
693 goto fail3;
694
695done:
696 return (0);
697
698fail3:
699 mtx_lock(&evq->lock);
700 evq->init_state = SFXGE_EVQ_INITIALIZED;
701fail2:
702 mtx_unlock(&evq->lock);
703 efx_ev_qdestroy(evq->common);
704fail:
705 efx_sram_buf_tbl_clear(sc->enp, evq->buf_base_id,
706 EFX_EVQ_NBUFS(evq->entries));
707
708 return (rc);
709}
710
711void
712sfxge_ev_stop(struct sfxge_softc *sc)
713{
714 struct sfxge_intr *intr;
715 efx_nic_t *enp;
716 int index;
717
718 intr = &sc->intr;
719 enp = sc->enp;
720
721 KASSERT(intr->state == SFXGE_INTR_STARTED,
722 ("Interrupts not started"));
723
724 /* Stop the event queue(s) */
725 index = intr->n_alloc;
726 while (--index >= 0)
727 sfxge_ev_qstop(sc, index);
728
729 /* Tear down the event module */
730 efx_ev_fini(enp);
731}
732
733int
734sfxge_ev_start(struct sfxge_softc *sc)
735{
736 struct sfxge_intr *intr;
737 int index;
738 int rc;
739
740 intr = &sc->intr;
741
742 KASSERT(intr->state == SFXGE_INTR_STARTED,
743 ("intr->state != SFXGE_INTR_STARTED"));
744
745 /* Initialize the event module */
746 if ((rc = efx_ev_init(sc->enp)) != 0)
747 return (rc);
748
749 /* Start the event queues */
750 for (index = 0; index < intr->n_alloc; index++) {
751 if ((rc = sfxge_ev_qstart(sc, index)) != 0)
752 goto fail;
753 }
754
755 return (0);
756
757fail:
758 /* Stop the event queue(s) */
759 while (--index >= 0)
760 sfxge_ev_qstop(sc, index);
761
762 /* Tear down the event module */
763 efx_ev_fini(sc->enp);
764
765 return (rc);
766}
767
768static void
769sfxge_ev_qfini(struct sfxge_softc *sc, unsigned int index)
770{
771 struct sfxge_evq *evq;
772
773 evq = sc->evq[index];
774
775 KASSERT(evq->init_state == SFXGE_EVQ_INITIALIZED,
776 ("evq->init_state != SFXGE_EVQ_INITIALIZED"));
777 KASSERT(evq->txqs == &evq->txq, ("evq->txqs != &evq->txq"));
778
779 sfxge_dma_free(&evq->mem);
780
781 sc->evq[index] = NULL;
782
783 mtx_destroy(&evq->lock);
784
785 free(evq, M_SFXGE);
786}
787
788static int
789sfxge_ev_qinit(struct sfxge_softc *sc, unsigned int index)
790{
791 struct sfxge_evq *evq;
792 efsys_mem_t *esmp;
793 int rc;
794
795 KASSERT(index < SFXGE_RX_SCALE_MAX, ("index >= SFXGE_RX_SCALE_MAX"));
796
797 evq = malloc(sizeof(struct sfxge_evq), M_SFXGE, M_ZERO | M_WAITOK);
798 evq->sc = sc;
799 evq->index = index;
800 sc->evq[index] = evq;
801 esmp = &evq->mem;
802
803 /* Build an event queue with room for one event per tx and rx buffer,
804 * plus some extra for link state events and MCDI completions.
805 * There are three tx queues in the first event queue and one in
806 * other.
807 */
808 if (index == 0)
809 evq->entries =
810 ROUNDUP_POW_OF_TWO(sc->rxq_entries +
811 3 * sc->txq_entries +
812 128);
813 else
814 evq->entries =
815 ROUNDUP_POW_OF_TWO(sc->rxq_entries +
816 sc->txq_entries +
817 128);
818
819 /* Initialise TX completion list */
820 evq->txqs = &evq->txq;
821
822 /* Allocate DMA space. */
823 if ((rc = sfxge_dma_alloc(sc, EFX_EVQ_SIZE(evq->entries), esmp)) != 0)
824 return (rc);
825
826 /* Allocate buffer table entries. */
827 sfxge_sram_buf_tbl_alloc(sc, EFX_EVQ_NBUFS(evq->entries),
828 &evq->buf_base_id);
829
830 mtx_init(&evq->lock, "evq", NULL, MTX_DEF);
831
832 evq->init_state = SFXGE_EVQ_INITIALIZED;
833
834 return (0);
835}
836
837void
838sfxge_ev_fini(struct sfxge_softc *sc)
839{
840 struct sfxge_intr *intr;
841 int index;
842
843 intr = &sc->intr;
844
845 KASSERT(intr->state == SFXGE_INTR_INITIALIZED,
846 ("intr->state != SFXGE_INTR_INITIALIZED"));
847
848 sc->ev_moderation = 0;
849
850 /* Tear down the event queue(s). */
851 index = intr->n_alloc;
852 while (--index >= 0)
853 sfxge_ev_qfini(sc, index);
854}
855
856int
857sfxge_ev_init(struct sfxge_softc *sc)
858{
859 struct sysctl_ctx_list *sysctl_ctx = device_get_sysctl_ctx(sc->dev);
860 struct sysctl_oid *sysctl_tree = device_get_sysctl_tree(sc->dev);
861 struct sfxge_intr *intr;
862 int index;
863 int rc;
864
865 intr = &sc->intr;
866
867 KASSERT(intr->state == SFXGE_INTR_INITIALIZED,
868 ("intr->state != SFXGE_INTR_INITIALIZED"));
869
870 /* Set default interrupt moderation; add a sysctl to
871 * read and change it.
872 */
873 sc->ev_moderation = 30;
874 SYSCTL_ADD_PROC(sysctl_ctx, SYSCTL_CHILDREN(sysctl_tree),
875 OID_AUTO, "int_mod", CTLTYPE_UINT|CTLFLAG_RW,
876 sc, 0, sfxge_int_mod_handler, "IU",
877 "sfxge interrupt moderation (us)");
878
879 /*
880 * Initialize the event queue(s) - one per interrupt.
881 */
882 for (index = 0; index < intr->n_alloc; index++) {
883 if ((rc = sfxge_ev_qinit(sc, index)) != 0)
884 goto fail;
885 }
886
887#if EFSYS_OPT_QSTATS
888 sfxge_ev_stat_init(sc);
889#endif
890
891 return (0);
892
893fail:
894 while (--index >= 0)
895 sfxge_ev_qfini(sc, index);
896
897 return (rc);
898}
261
262done:
263 return (evq->tx_done >= SFXGE_EV_BATCH);
264}
265
266static boolean_t
267sfxge_ev_txq_flush_done(void *arg, uint32_t txq_index)
268{
269 struct sfxge_evq *evq;
270 struct sfxge_softc *sc;
271 struct sfxge_txq *txq;
272 unsigned int label;
273 uint16_t magic;
274
275 evq = (struct sfxge_evq *)arg;
276 sc = evq->sc;
277 txq = sc->txq[txq_index];
278
279 KASSERT(txq != NULL, ("txq == NULL"));
280 KASSERT(txq->init_state == SFXGE_TXQ_INITIALIZED,
281 ("txq not initialized"));
282
283 /* Resend a software event on the correct queue */
284 evq = sc->evq[txq->evq_index];
285
286 label = txq->type;
287 KASSERT((label & SFXGE_MAGIC_DMAQ_LABEL_MASK) == label,
288 ("(label & SFXGE_MAGIC_DMAQ_LABEL_MASK) != label"));
289 magic = SFXGE_MAGIC_TX_QFLUSH_DONE | label;
290
291 KASSERT(evq->init_state == SFXGE_EVQ_STARTED,
292 ("evq not started"));
293 efx_ev_qpost(evq->common, magic);
294
295 return (B_FALSE);
296}
297
298static boolean_t
299sfxge_ev_software(void *arg, uint16_t magic)
300{
301 struct sfxge_evq *evq;
302 struct sfxge_softc *sc;
303 unsigned int label;
304
305 evq = (struct sfxge_evq *)arg;
306 sc = evq->sc;
307
308 label = magic & SFXGE_MAGIC_DMAQ_LABEL_MASK;
309 magic &= ~SFXGE_MAGIC_DMAQ_LABEL_MASK;
310
311 switch (magic) {
312 case SFXGE_MAGIC_RX_QFLUSH_DONE: {
313 struct sfxge_rxq *rxq = sc->rxq[label];
314
315 KASSERT(rxq != NULL, ("rxq == NULL"));
316 KASSERT(evq->index == rxq->index,
317 ("evq->index != rxq->index"));
318
319 sfxge_rx_qflush_done(rxq);
320 break;
321 }
322 case SFXGE_MAGIC_RX_QFLUSH_FAILED: {
323 struct sfxge_rxq *rxq = sc->rxq[label];
324
325 KASSERT(rxq != NULL, ("rxq == NULL"));
326 KASSERT(evq->index == rxq->index,
327 ("evq->index != rxq->index"));
328
329 sfxge_rx_qflush_failed(rxq);
330 break;
331 }
332 case SFXGE_MAGIC_RX_QREFILL: {
333 struct sfxge_rxq *rxq = sc->rxq[label];
334
335 KASSERT(rxq != NULL, ("rxq == NULL"));
336 KASSERT(evq->index == rxq->index,
337 ("evq->index != rxq->index"));
338
339 sfxge_rx_qrefill(rxq);
340 break;
341 }
342 case SFXGE_MAGIC_TX_QFLUSH_DONE: {
343 struct sfxge_txq *txq = sfxge_get_txq_by_label(evq, label);
344
345 KASSERT(txq != NULL, ("txq == NULL"));
346 KASSERT(evq->index == txq->evq_index,
347 ("evq->index != txq->evq_index"));
348
349 sfxge_tx_qflush_done(txq);
350 break;
351 }
352 default:
353 break;
354 }
355
356 return (B_FALSE);
357}
358
359static boolean_t
360sfxge_ev_sram(void *arg, uint32_t code)
361{
362 (void)arg;
363 (void)code;
364
365 switch (code) {
366 case EFX_SRAM_UPDATE:
367 EFSYS_PROBE(sram_update);
368 break;
369
370 case EFX_SRAM_CLEAR:
371 EFSYS_PROBE(sram_clear);
372 break;
373
374 case EFX_SRAM_ILLEGAL_CLEAR:
375 EFSYS_PROBE(sram_illegal_clear);
376 break;
377
378 default:
379 KASSERT(B_FALSE, ("Impossible SRAM event"));
380 break;
381 }
382
383 return (B_FALSE);
384}
385
386static boolean_t
387sfxge_ev_timer(void *arg, uint32_t index)
388{
389 (void)arg;
390 (void)index;
391
392 return (B_FALSE);
393}
394
395static boolean_t
396sfxge_ev_wake_up(void *arg, uint32_t index)
397{
398 (void)arg;
399 (void)index;
400
401 return (B_FALSE);
402}
403
404#if EFSYS_OPT_QSTATS
405
406static void
407sfxge_ev_stat_update(struct sfxge_softc *sc)
408{
409 struct sfxge_evq *evq;
410 unsigned int index;
411 clock_t now;
412
413 sx_xlock(&sc->softc_lock);
414
415 if (sc->evq[0]->init_state != SFXGE_EVQ_STARTED)
416 goto out;
417
418 now = ticks;
419 if (now - sc->ev_stats_update_time < hz)
420 goto out;
421
422 sc->ev_stats_update_time = now;
423
424 /* Add event counts from each event queue in turn */
425 for (index = 0; index < sc->intr.n_alloc; index++) {
426 evq = sc->evq[index];
427 mtx_lock(&evq->lock);
428 efx_ev_qstats_update(evq->common, sc->ev_stats);
429 mtx_unlock(&evq->lock);
430 }
431out:
432 sx_xunlock(&sc->softc_lock);
433}
434
435static int
436sfxge_ev_stat_handler(SYSCTL_HANDLER_ARGS)
437{
438 struct sfxge_softc *sc = arg1;
439 unsigned int id = arg2;
440
441 sfxge_ev_stat_update(sc);
442
443 return (SYSCTL_OUT(req, &sc->ev_stats[id], sizeof(sc->ev_stats[id])));
444}
445
446static void
447sfxge_ev_stat_init(struct sfxge_softc *sc)
448{
449 struct sysctl_ctx_list *ctx = device_get_sysctl_ctx(sc->dev);
450 struct sysctl_oid_list *stat_list;
451 unsigned int id;
452 char name[40];
453
454 stat_list = SYSCTL_CHILDREN(sc->stats_node);
455
456 for (id = 0; id < EV_NQSTATS; id++) {
457 snprintf(name, sizeof(name), "ev_%s",
458 efx_ev_qstat_name(sc->enp, id));
459 SYSCTL_ADD_PROC(
460 ctx, stat_list,
461 OID_AUTO, name, CTLTYPE_U64|CTLFLAG_RD,
462 sc, id, sfxge_ev_stat_handler, "Q",
463 "");
464 }
465}
466
467#endif /* EFSYS_OPT_QSTATS */
468
469static void
470sfxge_ev_qmoderate(struct sfxge_softc *sc, unsigned int idx, unsigned int us)
471{
472 struct sfxge_evq *evq;
473 efx_evq_t *eep;
474
475 evq = sc->evq[idx];
476 eep = evq->common;
477
478 KASSERT(evq->init_state == SFXGE_EVQ_STARTED,
479 ("evq->init_state != SFXGE_EVQ_STARTED"));
480
481 (void)efx_ev_qmoderate(eep, us);
482}
483
484static int
485sfxge_int_mod_handler(SYSCTL_HANDLER_ARGS)
486{
487 struct sfxge_softc *sc = arg1;
488 struct sfxge_intr *intr = &sc->intr;
489 unsigned int moderation;
490 int error;
491 int index;
492
493 sx_xlock(&sc->softc_lock);
494
495 if (req->newptr != NULL) {
496 if ((error = SYSCTL_IN(req, &moderation, sizeof(moderation)))
497 != 0)
498 goto out;
499
500 /* We may not be calling efx_ev_qmoderate() now,
501 * so we have to range-check the value ourselves.
502 */
503 if (moderation >
504 efx_nic_cfg_get(sc->enp)->enc_evq_moderation_max) {
505 error = EINVAL;
506 goto out;
507 }
508
509 sc->ev_moderation = moderation;
510 if (intr->state == SFXGE_INTR_STARTED) {
511 for (index = 0; index < intr->n_alloc; index++)
512 sfxge_ev_qmoderate(sc, index, moderation);
513 }
514 } else {
515 error = SYSCTL_OUT(req, &sc->ev_moderation,
516 sizeof(sc->ev_moderation));
517 }
518
519out:
520 sx_xunlock(&sc->softc_lock);
521
522 return (error);
523}
524
525static boolean_t
526sfxge_ev_initialized(void *arg)
527{
528 struct sfxge_evq *evq;
529
530 evq = (struct sfxge_evq *)arg;
531
532 KASSERT(evq->init_state == SFXGE_EVQ_STARTING,
533 ("evq not starting"));
534
535 evq->init_state = SFXGE_EVQ_STARTED;
536
537 return (0);
538}
539
540static boolean_t
541sfxge_ev_link_change(void *arg, efx_link_mode_t link_mode)
542{
543 struct sfxge_evq *evq;
544 struct sfxge_softc *sc;
545
546 evq = (struct sfxge_evq *)arg;
547 sc = evq->sc;
548
549 sfxge_mac_link_update(sc, link_mode);
550
551 return (0);
552}
553
554static const efx_ev_callbacks_t sfxge_ev_callbacks = {
555 .eec_initialized = sfxge_ev_initialized,
556 .eec_rx = sfxge_ev_rx,
557 .eec_tx = sfxge_ev_tx,
558 .eec_exception = sfxge_ev_exception,
559 .eec_rxq_flush_done = sfxge_ev_rxq_flush_done,
560 .eec_rxq_flush_failed = sfxge_ev_rxq_flush_failed,
561 .eec_txq_flush_done = sfxge_ev_txq_flush_done,
562 .eec_software = sfxge_ev_software,
563 .eec_sram = sfxge_ev_sram,
564 .eec_wake_up = sfxge_ev_wake_up,
565 .eec_timer = sfxge_ev_timer,
566 .eec_link_change = sfxge_ev_link_change,
567};
568
569
570int
571sfxge_ev_qpoll(struct sfxge_evq *evq)
572{
573 int rc;
574
575 mtx_lock(&evq->lock);
576
577 if (evq->init_state != SFXGE_EVQ_STARTING &&
578 evq->init_state != SFXGE_EVQ_STARTED) {
579 rc = EINVAL;
580 goto fail;
581 }
582
583 /* Synchronize the DMA memory for reading */
584 bus_dmamap_sync(evq->mem.esm_tag, evq->mem.esm_map,
585 BUS_DMASYNC_POSTREAD);
586
587 KASSERT(evq->rx_done == 0, ("evq->rx_done != 0"));
588 KASSERT(evq->tx_done == 0, ("evq->tx_done != 0"));
589 KASSERT(evq->txq == NULL, ("evq->txq != NULL"));
590 KASSERT(evq->txqs == &evq->txq, ("evq->txqs != &evq->txq"));
591
592 /* Poll the queue */
593 efx_ev_qpoll(evq->common, &evq->read_ptr, &sfxge_ev_callbacks, evq);
594
595 evq->rx_done = 0;
596 evq->tx_done = 0;
597
598 /* Perform any pending completion processing */
599 sfxge_ev_qcomplete(evq, B_TRUE);
600
601 /* Re-prime the event queue for interrupts */
602 if ((rc = efx_ev_qprime(evq->common, evq->read_ptr)) != 0)
603 goto fail;
604
605 mtx_unlock(&evq->lock);
606
607 return (0);
608
609fail:
610 mtx_unlock(&(evq->lock));
611 return (rc);
612}
613
614static void
615sfxge_ev_qstop(struct sfxge_softc *sc, unsigned int index)
616{
617 struct sfxge_evq *evq;
618
619 evq = sc->evq[index];
620
621 KASSERT(evq->init_state == SFXGE_EVQ_STARTED,
622 ("evq->init_state != SFXGE_EVQ_STARTED"));
623
624 mtx_lock(&evq->lock);
625 evq->init_state = SFXGE_EVQ_INITIALIZED;
626 evq->read_ptr = 0;
627 evq->exception = B_FALSE;
628
629#if EFSYS_OPT_QSTATS
630 /* Add event counts before discarding the common evq state */
631 efx_ev_qstats_update(evq->common, sc->ev_stats);
632#endif
633
634 efx_ev_qdestroy(evq->common);
635 efx_sram_buf_tbl_clear(sc->enp, evq->buf_base_id,
636 EFX_EVQ_NBUFS(evq->entries));
637 mtx_unlock(&evq->lock);
638}
639
640static int
641sfxge_ev_qstart(struct sfxge_softc *sc, unsigned int index)
642{
643 struct sfxge_evq *evq;
644 efsys_mem_t *esmp;
645 int count;
646 int rc;
647
648 evq = sc->evq[index];
649 esmp = &evq->mem;
650
651 KASSERT(evq->init_state == SFXGE_EVQ_INITIALIZED,
652 ("evq->init_state != SFXGE_EVQ_INITIALIZED"));
653
654 /* Clear all events. */
655 (void)memset(esmp->esm_base, 0xff, EFX_EVQ_SIZE(evq->entries));
656
657 /* Program the buffer table. */
658 if ((rc = efx_sram_buf_tbl_set(sc->enp, evq->buf_base_id, esmp,
659 EFX_EVQ_NBUFS(evq->entries))) != 0)
660 return (rc);
661
662 /* Create the common code event queue. */
663 if ((rc = efx_ev_qcreate(sc->enp, index, esmp, evq->entries,
664 evq->buf_base_id, &evq->common)) != 0)
665 goto fail;
666
667 mtx_lock(&evq->lock);
668
669 /* Set the default moderation */
670 (void)efx_ev_qmoderate(evq->common, sc->ev_moderation);
671
672 /* Prime the event queue for interrupts */
673 if ((rc = efx_ev_qprime(evq->common, evq->read_ptr)) != 0)
674 goto fail2;
675
676 evq->init_state = SFXGE_EVQ_STARTING;
677
678 mtx_unlock(&evq->lock);
679
680 /* Wait for the initialization event */
681 count = 0;
682 do {
683 /* Pause for 100 ms */
684 pause("sfxge evq init", hz / 10);
685
686 /* Check to see if the test event has been processed */
687 if (evq->init_state == SFXGE_EVQ_STARTED)
688 goto done;
689
690 } while (++count < 20);
691
692 rc = ETIMEDOUT;
693 goto fail3;
694
695done:
696 return (0);
697
698fail3:
699 mtx_lock(&evq->lock);
700 evq->init_state = SFXGE_EVQ_INITIALIZED;
701fail2:
702 mtx_unlock(&evq->lock);
703 efx_ev_qdestroy(evq->common);
704fail:
705 efx_sram_buf_tbl_clear(sc->enp, evq->buf_base_id,
706 EFX_EVQ_NBUFS(evq->entries));
707
708 return (rc);
709}
710
711void
712sfxge_ev_stop(struct sfxge_softc *sc)
713{
714 struct sfxge_intr *intr;
715 efx_nic_t *enp;
716 int index;
717
718 intr = &sc->intr;
719 enp = sc->enp;
720
721 KASSERT(intr->state == SFXGE_INTR_STARTED,
722 ("Interrupts not started"));
723
724 /* Stop the event queue(s) */
725 index = intr->n_alloc;
726 while (--index >= 0)
727 sfxge_ev_qstop(sc, index);
728
729 /* Tear down the event module */
730 efx_ev_fini(enp);
731}
732
733int
734sfxge_ev_start(struct sfxge_softc *sc)
735{
736 struct sfxge_intr *intr;
737 int index;
738 int rc;
739
740 intr = &sc->intr;
741
742 KASSERT(intr->state == SFXGE_INTR_STARTED,
743 ("intr->state != SFXGE_INTR_STARTED"));
744
745 /* Initialize the event module */
746 if ((rc = efx_ev_init(sc->enp)) != 0)
747 return (rc);
748
749 /* Start the event queues */
750 for (index = 0; index < intr->n_alloc; index++) {
751 if ((rc = sfxge_ev_qstart(sc, index)) != 0)
752 goto fail;
753 }
754
755 return (0);
756
757fail:
758 /* Stop the event queue(s) */
759 while (--index >= 0)
760 sfxge_ev_qstop(sc, index);
761
762 /* Tear down the event module */
763 efx_ev_fini(sc->enp);
764
765 return (rc);
766}
767
768static void
769sfxge_ev_qfini(struct sfxge_softc *sc, unsigned int index)
770{
771 struct sfxge_evq *evq;
772
773 evq = sc->evq[index];
774
775 KASSERT(evq->init_state == SFXGE_EVQ_INITIALIZED,
776 ("evq->init_state != SFXGE_EVQ_INITIALIZED"));
777 KASSERT(evq->txqs == &evq->txq, ("evq->txqs != &evq->txq"));
778
779 sfxge_dma_free(&evq->mem);
780
781 sc->evq[index] = NULL;
782
783 mtx_destroy(&evq->lock);
784
785 free(evq, M_SFXGE);
786}
787
788static int
789sfxge_ev_qinit(struct sfxge_softc *sc, unsigned int index)
790{
791 struct sfxge_evq *evq;
792 efsys_mem_t *esmp;
793 int rc;
794
795 KASSERT(index < SFXGE_RX_SCALE_MAX, ("index >= SFXGE_RX_SCALE_MAX"));
796
797 evq = malloc(sizeof(struct sfxge_evq), M_SFXGE, M_ZERO | M_WAITOK);
798 evq->sc = sc;
799 evq->index = index;
800 sc->evq[index] = evq;
801 esmp = &evq->mem;
802
803 /* Build an event queue with room for one event per tx and rx buffer,
804 * plus some extra for link state events and MCDI completions.
805 * There are three tx queues in the first event queue and one in
806 * other.
807 */
808 if (index == 0)
809 evq->entries =
810 ROUNDUP_POW_OF_TWO(sc->rxq_entries +
811 3 * sc->txq_entries +
812 128);
813 else
814 evq->entries =
815 ROUNDUP_POW_OF_TWO(sc->rxq_entries +
816 sc->txq_entries +
817 128);
818
819 /* Initialise TX completion list */
820 evq->txqs = &evq->txq;
821
822 /* Allocate DMA space. */
823 if ((rc = sfxge_dma_alloc(sc, EFX_EVQ_SIZE(evq->entries), esmp)) != 0)
824 return (rc);
825
826 /* Allocate buffer table entries. */
827 sfxge_sram_buf_tbl_alloc(sc, EFX_EVQ_NBUFS(evq->entries),
828 &evq->buf_base_id);
829
830 mtx_init(&evq->lock, "evq", NULL, MTX_DEF);
831
832 evq->init_state = SFXGE_EVQ_INITIALIZED;
833
834 return (0);
835}
836
837void
838sfxge_ev_fini(struct sfxge_softc *sc)
839{
840 struct sfxge_intr *intr;
841 int index;
842
843 intr = &sc->intr;
844
845 KASSERT(intr->state == SFXGE_INTR_INITIALIZED,
846 ("intr->state != SFXGE_INTR_INITIALIZED"));
847
848 sc->ev_moderation = 0;
849
850 /* Tear down the event queue(s). */
851 index = intr->n_alloc;
852 while (--index >= 0)
853 sfxge_ev_qfini(sc, index);
854}
855
856int
857sfxge_ev_init(struct sfxge_softc *sc)
858{
859 struct sysctl_ctx_list *sysctl_ctx = device_get_sysctl_ctx(sc->dev);
860 struct sysctl_oid *sysctl_tree = device_get_sysctl_tree(sc->dev);
861 struct sfxge_intr *intr;
862 int index;
863 int rc;
864
865 intr = &sc->intr;
866
867 KASSERT(intr->state == SFXGE_INTR_INITIALIZED,
868 ("intr->state != SFXGE_INTR_INITIALIZED"));
869
870 /* Set default interrupt moderation; add a sysctl to
871 * read and change it.
872 */
873 sc->ev_moderation = 30;
874 SYSCTL_ADD_PROC(sysctl_ctx, SYSCTL_CHILDREN(sysctl_tree),
875 OID_AUTO, "int_mod", CTLTYPE_UINT|CTLFLAG_RW,
876 sc, 0, sfxge_int_mod_handler, "IU",
877 "sfxge interrupt moderation (us)");
878
879 /*
880 * Initialize the event queue(s) - one per interrupt.
881 */
882 for (index = 0; index < intr->n_alloc; index++) {
883 if ((rc = sfxge_ev_qinit(sc, index)) != 0)
884 goto fail;
885 }
886
887#if EFSYS_OPT_QSTATS
888 sfxge_ev_stat_init(sc);
889#endif
890
891 return (0);
892
893fail:
894 while (--index >= 0)
895 sfxge_ev_qfini(sc, index);
896
897 return (rc);
898}