Lines 98-108
static unsigned int next_index = 0;
Link Here
|
98 |
#define EPAIR_LOCK() mtx_lock(&epair_n_index_mtx) |
98 |
#define EPAIR_LOCK() mtx_lock(&epair_n_index_mtx) |
99 |
#define EPAIR_UNLOCK() mtx_unlock(&epair_n_index_mtx) |
99 |
#define EPAIR_UNLOCK() mtx_unlock(&epair_n_index_mtx) |
100 |
|
100 |
|
|
|
101 |
#define BIT_QUEUE_TASK 0 |
102 |
#define BIT_MBUF_QUEUED 1 |
103 |
|
101 |
struct epair_softc; |
104 |
struct epair_softc; |
102 |
struct epair_queue { |
105 |
struct epair_queue { |
103 |
int id; |
106 |
int id; |
104 |
struct buf_ring *rxring[2]; |
107 |
struct buf_ring *rxring[2]; |
105 |
volatile int ridx; /* 0 || 1 */ |
108 |
volatile int ridx; /* 0 || 1 */ |
|
|
109 |
volatile int state; /* queue state */ |
106 |
struct task tx_task; |
110 |
struct task tx_task; |
107 |
struct epair_softc *sc; |
111 |
struct epair_softc *sc; |
108 |
}; |
112 |
}; |
Lines 171-177
epair_tx_start_deferred(void *arg, int pending)
Link Here
|
171 |
} while (!atomic_fcmpset_int(&q->ridx, &ridx, nidx)); |
175 |
} while (!atomic_fcmpset_int(&q->ridx, &ridx, nidx)); |
172 |
epair_if_input(sc, q, ridx); |
176 |
epair_if_input(sc, q, ridx); |
173 |
|
177 |
|
174 |
if (! buf_ring_empty(q->rxring[nidx])) |
178 |
atomic_clear_int(&q->state, (1 << BIT_QUEUE_TASK)); |
|
|
179 |
if (atomic_testandclear_int(&q->state, BIT_MBUF_QUEUED)) |
175 |
taskqueue_enqueue(epair_tasks.tq[q->id], &q->tx_task); |
180 |
taskqueue_enqueue(epair_tasks.tq[q->id], &q->tx_task); |
176 |
|
181 |
|
177 |
if_rele(sc->ifp); |
182 |
if_rele(sc->ifp); |
Lines 186-192
epair_menq(struct mbuf *m, struct epair_softc *osc)
Link Here
|
186 |
short mflags; |
191 |
short mflags; |
187 |
struct epair_queue *q = NULL; |
192 |
struct epair_queue *q = NULL; |
188 |
uint32_t bucket; |
193 |
uint32_t bucket; |
189 |
bool was_empty; |
|
|
190 |
#ifdef RSS |
194 |
#ifdef RSS |
191 |
struct ether_header *eh; |
195 |
struct ether_header *eh; |
192 |
#endif |
196 |
#endif |
Lines 234-241
epair_menq(struct mbuf *m, struct epair_softc *osc)
Link Here
|
234 |
#endif |
238 |
#endif |
235 |
q = &osc->queues[bucket]; |
239 |
q = &osc->queues[bucket]; |
236 |
|
240 |
|
|
|
241 |
atomic_set_int(&q->state, (1 << BIT_MBUF_QUEUED)); |
237 |
ridx = atomic_load_int(&q->ridx); |
242 |
ridx = atomic_load_int(&q->ridx); |
238 |
was_empty = buf_ring_empty(q->rxring[ridx]); |
|
|
239 |
ret = buf_ring_enqueue(q->rxring[ridx], m); |
243 |
ret = buf_ring_enqueue(q->rxring[ridx], m); |
240 |
if (ret != 0) { |
244 |
if (ret != 0) { |
241 |
/* Ring is full. */ |
245 |
/* Ring is full. */ |
Lines 256-265
epair_menq(struct mbuf *m, struct epair_softc *osc)
Link Here
|
256 |
/* Someone else received the packet. */ |
260 |
/* Someone else received the packet. */ |
257 |
if_inc_counter(oifp, IFCOUNTER_IPACKETS, 1); |
261 |
if_inc_counter(oifp, IFCOUNTER_IPACKETS, 1); |
258 |
|
262 |
|
259 |
done: |
263 |
if (!atomic_testandset_int(&q->state, BIT_QUEUE_TASK)) { |
260 |
if (was_empty) |
|
|
261 |
taskqueue_enqueue(epair_tasks.tq[bucket], &q->tx_task); |
264 |
taskqueue_enqueue(epair_tasks.tq[bucket], &q->tx_task); |
|
|
265 |
} |
262 |
|
266 |
|
|
|
267 |
done: |
263 |
return (0); |
268 |
return (0); |
264 |
} |
269 |
} |
265 |
|
270 |
|
Lines 304-312
epair_transmit(struct ifnet *ifp, struct mbuf *m)
Link Here
|
304 |
{ |
309 |
{ |
305 |
struct epair_softc *sc; |
310 |
struct epair_softc *sc; |
306 |
struct ifnet *oifp; |
311 |
struct ifnet *oifp; |
307 |
int error, len; |
312 |
int error; |
|
|
313 |
#ifdef ALTQ |
314 |
int len; |
308 |
short mflags; |
315 |
short mflags; |
309 |
|
316 |
#endif |
310 |
if (m == NULL) |
317 |
if (m == NULL) |
311 |
return (0); |
318 |
return (0); |
312 |
M_ASSERTPKTHDR(m); |
319 |
M_ASSERTPKTHDR(m); |
Lines 342-351
epair_transmit(struct ifnet *ifp, struct mbuf *m)
Link Here
|
342 |
m_freem(m); |
349 |
m_freem(m); |
343 |
return (0); |
350 |
return (0); |
344 |
} |
351 |
} |
|
|
352 |
|
353 |
#ifdef ALTQ |
345 |
len = m->m_pkthdr.len; |
354 |
len = m->m_pkthdr.len; |
346 |
mflags = m->m_flags; |
355 |
mflags = m->m_flags; |
347 |
|
356 |
|
348 |
#ifdef ALTQ |
|
|
349 |
/* Support ALTQ via the classic if_start() path. */ |
357 |
/* Support ALTQ via the classic if_start() path. */ |
350 |
IF_LOCK(&ifp->if_snd); |
358 |
IF_LOCK(&ifp->if_snd); |
351 |
if (ALTQ_IS_ENABLED(&ifp->if_snd)) { |
359 |
if (ALTQ_IS_ENABLED(&ifp->if_snd)) { |
Lines 538-543
epair_clone_create(struct if_clone *ifc, char *name, size_t len, caddr_t params)
Link Here
|
538 |
q->rxring[0] = buf_ring_alloc(RXRSIZE, M_EPAIR, M_WAITOK, NULL); |
546 |
q->rxring[0] = buf_ring_alloc(RXRSIZE, M_EPAIR, M_WAITOK, NULL); |
539 |
q->rxring[1] = buf_ring_alloc(RXRSIZE, M_EPAIR, M_WAITOK, NULL); |
547 |
q->rxring[1] = buf_ring_alloc(RXRSIZE, M_EPAIR, M_WAITOK, NULL); |
540 |
q->ridx = 0; |
548 |
q->ridx = 0; |
|
|
549 |
q->state = 0; |
541 |
q->sc = sca; |
550 |
q->sc = sca; |
542 |
NET_TASK_INIT(&q->tx_task, 0, epair_tx_start_deferred, q); |
551 |
NET_TASK_INIT(&q->tx_task, 0, epair_tx_start_deferred, q); |
543 |
} |
552 |
} |
Lines 560-565
epair_clone_create(struct if_clone *ifc, char *name, size_t len, caddr_t params)
Link Here
|
560 |
q->rxring[0] = buf_ring_alloc(RXRSIZE, M_EPAIR, M_WAITOK, NULL); |
569 |
q->rxring[0] = buf_ring_alloc(RXRSIZE, M_EPAIR, M_WAITOK, NULL); |
561 |
q->rxring[1] = buf_ring_alloc(RXRSIZE, M_EPAIR, M_WAITOK, NULL); |
570 |
q->rxring[1] = buf_ring_alloc(RXRSIZE, M_EPAIR, M_WAITOK, NULL); |
562 |
q->ridx = 0; |
571 |
q->ridx = 0; |
|
|
572 |
q->state = 0; |
563 |
q->sc = scb; |
573 |
q->sc = scb; |
564 |
NET_TASK_INIT(&q->tx_task, 0, epair_tx_start_deferred, q); |
574 |
NET_TASK_INIT(&q->tx_task, 0, epair_tx_start_deferred, q); |
565 |
} |
575 |
} |