Merge similar fixes from 223198 from igb to ixgbe:
- Use a dedicated task to handle deferred transmits from the if_transmit method instead of reusing the existing per-queue interrupt task. Reusing the per-queue interrupt task could result in both an interrupt thread and the taskqueue thread trying to handle received packets on a single queue resulting in out-of-order packet processing and lock contention. - Don't define ixgbe_start() at all where if_transmit is used. Tested by: Vijay Singh Reviewed by: jfv MFC after: 2 weeks
This commit is contained in:
parent
c87363c006
commit
aceb040376
@ -299,9 +299,9 @@ struct tx_ring {
|
||||
struct igb_tx_buffer *tx_buffers;
|
||||
#if __FreeBSD_version >= 800000
|
||||
struct buf_ring *br;
|
||||
struct task txq_task;
|
||||
#endif
|
||||
bus_dma_tag_t txtag;
|
||||
struct task txq_task;
|
||||
|
||||
u32 bytes;
|
||||
u32 packets;
|
||||
|
@ -104,13 +104,15 @@ static int ixgbe_probe(device_t);
|
||||
static int ixgbe_attach(device_t);
|
||||
static int ixgbe_detach(device_t);
|
||||
static int ixgbe_shutdown(device_t);
|
||||
static void ixgbe_start(struct ifnet *);
|
||||
static void ixgbe_start_locked(struct tx_ring *, struct ifnet *);
|
||||
#if __FreeBSD_version >= 800000
|
||||
static int ixgbe_mq_start(struct ifnet *, struct mbuf *);
|
||||
static int ixgbe_mq_start_locked(struct ifnet *,
|
||||
struct tx_ring *, struct mbuf *);
|
||||
static void ixgbe_qflush(struct ifnet *);
|
||||
static void ixgbe_deferred_mq_start(void *, int);
|
||||
#else
|
||||
static void ixgbe_start(struct ifnet *);
|
||||
static void ixgbe_start_locked(struct tx_ring *, struct ifnet *);
|
||||
#endif
|
||||
static int ixgbe_ioctl(struct ifnet *, u_long, caddr_t);
|
||||
static void ixgbe_init(void *);
|
||||
@ -631,6 +633,7 @@ ixgbe_detach(device_t dev)
|
||||
{
|
||||
struct adapter *adapter = device_get_softc(dev);
|
||||
struct ix_queue *que = adapter->queues;
|
||||
struct tx_ring *txr = adapter->tx_rings;
|
||||
u32 ctrl_ext;
|
||||
|
||||
INIT_DEBUGOUT("ixgbe_detach: begin");
|
||||
@ -645,8 +648,11 @@ ixgbe_detach(device_t dev)
|
||||
ixgbe_stop(adapter);
|
||||
IXGBE_CORE_UNLOCK(adapter);
|
||||
|
||||
for (int i = 0; i < adapter->num_queues; i++, que++) {
|
||||
for (int i = 0; i < adapter->num_queues; i++, que++, txr++) {
|
||||
if (que->tq) {
|
||||
#if __FreeBSD_version >= 800000
|
||||
taskqueue_drain(que->tq, &txr->txq_task);
|
||||
#endif
|
||||
taskqueue_drain(que->tq, &que->que_task);
|
||||
taskqueue_free(que->tq);
|
||||
}
|
||||
@ -708,6 +714,7 @@ ixgbe_shutdown(device_t dev)
|
||||
}
|
||||
|
||||
|
||||
#if __FreeBSD_version < 800000
|
||||
/*********************************************************************
|
||||
* Transmit entry point
|
||||
*
|
||||
@ -779,7 +786,7 @@ ixgbe_start(struct ifnet *ifp)
|
||||
return;
|
||||
}
|
||||
|
||||
#if __FreeBSD_version >= 800000
|
||||
#else
|
||||
/*
|
||||
** Multiqueue Transmit driver
|
||||
**
|
||||
@ -807,7 +814,7 @@ ixgbe_mq_start(struct ifnet *ifp, struct mbuf *m)
|
||||
IXGBE_TX_UNLOCK(txr);
|
||||
} else {
|
||||
err = drbr_enqueue(ifp, txr->br, m);
|
||||
taskqueue_enqueue(que->tq, &que->que_task);
|
||||
taskqueue_enqueue(que->tq, &txr->txq_task);
|
||||
}
|
||||
|
||||
return (err);
|
||||
@ -872,6 +879,22 @@ ixgbe_mq_start_locked(struct ifnet *ifp, struct tx_ring *txr, struct mbuf *m)
|
||||
return (err);
|
||||
}
|
||||
|
||||
/*
|
||||
* Called from a taskqueue to drain queued transmit packets.
|
||||
*/
|
||||
static void
|
||||
ixgbe_deferred_mq_start(void *arg, int pending)
|
||||
{
|
||||
struct tx_ring *txr = arg;
|
||||
struct adapter *adapter = txr->adapter;
|
||||
struct ifnet *ifp = adapter->ifp;
|
||||
|
||||
IXGBE_TX_LOCK(txr);
|
||||
if (!drbr_empty(ifp, txr->br))
|
||||
ixgbe_mq_start_locked(ifp, txr, NULL);
|
||||
IXGBE_TX_UNLOCK(txr);
|
||||
}
|
||||
|
||||
/*
|
||||
** Flush all ring buffers
|
||||
*/
|
||||
@ -2230,6 +2253,9 @@ ixgbe_allocate_legacy(struct adapter *adapter)
|
||||
{
|
||||
device_t dev = adapter->dev;
|
||||
struct ix_queue *que = adapter->queues;
|
||||
#if __FreeBSD_version >= 800000
|
||||
struct tx_ring *txr = adapter->tx_rings;
|
||||
#endif
|
||||
int error, rid = 0;
|
||||
|
||||
/* MSI RID at 1 */
|
||||
@ -2249,6 +2275,9 @@ ixgbe_allocate_legacy(struct adapter *adapter)
|
||||
* Try allocating a fast interrupt and the associated deferred
|
||||
* processing contexts.
|
||||
*/
|
||||
#if __FreeBSD_version >= 800000
|
||||
TASK_INIT(&txr->txq_task, 0, ixgbe_deferred_mq_start, txr);
|
||||
#endif
|
||||
TASK_INIT(&que->que_task, 0, ixgbe_handle_que, que);
|
||||
que->tq = taskqueue_create_fast("ixgbe_que", M_NOWAIT,
|
||||
taskqueue_thread_enqueue, &que->tq);
|
||||
@ -2295,9 +2324,10 @@ ixgbe_allocate_msix(struct adapter *adapter)
|
||||
{
|
||||
device_t dev = adapter->dev;
|
||||
struct ix_queue *que = adapter->queues;
|
||||
struct tx_ring *txr = adapter->tx_rings;
|
||||
int error, rid, vector = 0;
|
||||
|
||||
for (int i = 0; i < adapter->num_queues; i++, vector++, que++) {
|
||||
for (int i = 0; i < adapter->num_queues; i++, vector++, que++, txr++) {
|
||||
rid = vector + 1;
|
||||
que->res = bus_alloc_resource_any(dev, SYS_RES_IRQ, &rid,
|
||||
RF_SHAREABLE | RF_ACTIVE);
|
||||
@ -2327,6 +2357,9 @@ ixgbe_allocate_msix(struct adapter *adapter)
|
||||
if (adapter->num_queues > 1)
|
||||
bus_bind_intr(dev, que->res, i);
|
||||
|
||||
#if __FreeBSD_version >= 800000
|
||||
TASK_INIT(&txr->txq_task, 0, ixgbe_deferred_mq_start, txr);
|
||||
#endif
|
||||
TASK_INIT(&que->que_task, 0, ixgbe_handle_que, que);
|
||||
que->tq = taskqueue_create_fast("ixgbe_que", M_NOWAIT,
|
||||
taskqueue_thread_enqueue, &que->tq);
|
||||
@ -2570,12 +2603,13 @@ ixgbe_setup_interface(device_t dev, struct adapter *adapter)
|
||||
ifp->if_softc = adapter;
|
||||
ifp->if_flags = IFF_BROADCAST | IFF_SIMPLEX | IFF_MULTICAST;
|
||||
ifp->if_ioctl = ixgbe_ioctl;
|
||||
ifp->if_start = ixgbe_start;
|
||||
#if __FreeBSD_version >= 800000
|
||||
ifp->if_transmit = ixgbe_mq_start;
|
||||
ifp->if_qflush = ixgbe_qflush;
|
||||
#else
|
||||
ifp->if_start = ixgbe_start;
|
||||
IFQ_SET_MAXLEN(&ifp->if_snd, adapter->num_tx_desc - 2);
|
||||
#endif
|
||||
ifp->if_snd.ifq_maxlen = adapter->num_tx_desc - 2;
|
||||
|
||||
ether_ifattach(ifp, adapter->hw.mac.addr);
|
||||
|
||||
|
@ -314,6 +314,7 @@ struct tx_ring {
|
||||
char mtx_name[16];
|
||||
#if __FreeBSD_version >= 800000
|
||||
struct buf_ring *br;
|
||||
struct task txq_task;
|
||||
#endif
|
||||
#ifdef IXGBE_FDIR
|
||||
u16 atr_sample;
|
||||
|
Loading…
Reference in New Issue
Block a user