summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorjfv <jfv@FreeBSD.org>2010-06-11 20:54:27 +0000
committerjfv <jfv@FreeBSD.org>2010-06-11 20:54:27 +0000
commit9858f3bc4c35be50f67da27521c73f26b6b6bd3a (patch)
tree1f5b9c0ff65e16c23a17572d1c94cf963e1e15e1
parent4ea1959e0155c8f372d3949e1e5b200c50ca7a4c (diff)
downloadFreeBSD-src-9858f3bc4c35be50f67da27521c73f26b6b6bd3a.zip
FreeBSD-src-9858f3bc4c35be50f67da27521c73f26b6b6bd3a.tar.gz
Add a couple fixes from Michael Tuexen.
Remove unneeded rxtx handler, make que handler generic. Do not allocate header mbufs in rx ring if not doing hdr split. Release the lock in rxeof call to stack. MFC for 8.1 asap
-rw-r--r--sys/dev/e1000/if_igb.c120
1 files changed, 49 insertions, 71 deletions
diff --git a/sys/dev/e1000/if_igb.c b/sys/dev/e1000/if_igb.c
index 85d9a8b..d5fe47b 100644
--- a/sys/dev/e1000/if_igb.c
+++ b/sys/dev/e1000/if_igb.c
@@ -99,7 +99,7 @@ int igb_display_debug_stats = 0;
/*********************************************************************
* Driver version:
*********************************************************************/
-char igb_driver_version[] = "version - 1.9.5";
+char igb_driver_version[] = "version - 1.9.6";
/*********************************************************************
@@ -240,7 +240,6 @@ static void igb_led_func(void *, int);
static int igb_irq_fast(void *);
static void igb_add_rx_process_limit(struct adapter *, const char *,
const char *, int *, int);
-static void igb_handle_rxtx(void *context, int pending);
static void igb_handle_que(void *context, int pending);
static void igb_handle_link(void *context, int pending);
@@ -818,21 +817,25 @@ igb_start(struct ifnet *ifp)
static int
igb_mq_start(struct ifnet *ifp, struct mbuf *m)
{
- struct adapter *adapter = ifp->if_softc;
- struct tx_ring *txr;
- int i = 0, err = 0;
+ struct adapter *adapter = ifp->if_softc;
+ struct igb_queue *que;
+ struct tx_ring *txr;
+ int i = 0, err = 0;
/* Which queue to use */
if ((m->m_flags & M_FLOWID) != 0)
i = m->m_pkthdr.flowid % adapter->num_queues;
txr = &adapter->tx_rings[i];
+ que = &adapter->queues[i];
if (IGB_TX_TRYLOCK(txr)) {
err = igb_mq_start_locked(ifp, txr, m);
IGB_TX_UNLOCK(txr);
- } else
+ } else {
err = drbr_enqueue(ifp, txr->br, m);
+ taskqueue_enqueue(que->tq, &que->que_task);
+ }
return (err);
}
@@ -1225,35 +1228,6 @@ igb_init(void *arg)
static void
-igb_handle_rxtx(void *context, int pending)
-{
- struct igb_queue *que = context;
- struct adapter *adapter = que->adapter;
- struct tx_ring *txr = adapter->tx_rings;
- struct ifnet *ifp;
-
- ifp = adapter->ifp;
-
- if (ifp->if_drv_flags & IFF_DRV_RUNNING) {
- if (igb_rxeof(que, adapter->rx_process_limit))
- taskqueue_enqueue(adapter->tq, &adapter->rxtx_task);
- IGB_TX_LOCK(txr);
- igb_txeof(txr);
-
-#if __FreeBSD_version >= 800000
- if (!drbr_empty(ifp, txr->br))
- igb_mq_start_locked(ifp, txr, NULL);
-#else
- if (!IFQ_DRV_IS_EMPTY(&ifp->if_snd))
- igb_start_locked(txr, ifp);
-#endif
- IGB_TX_UNLOCK(txr);
- }
-
- igb_enable_intr(adapter);
-}
-
-static void
igb_handle_que(void *context, int pending)
{
struct igb_queue *que = context;
@@ -1268,7 +1242,8 @@ igb_handle_que(void *context, int pending)
IGB_TX_LOCK(txr);
igb_txeof(txr);
#if __FreeBSD_version >= 800000
- igb_mq_start_locked(ifp, txr, NULL);
+ if (!drbr_empty(ifp, txr->br))
+ igb_mq_start_locked(ifp, txr, NULL);
#else
if (!IFQ_DRV_IS_EMPTY(&ifp->if_snd))
igb_start_locked(txr, ifp);
@@ -1280,11 +1255,15 @@ igb_handle_que(void *context, int pending)
}
}
- /* Reenable this interrupt */
#ifdef DEVICE_POLLING
- if (!(ifp->if_capenable & IFCAP_POLLING))
+ if (ifp->if_capenable & IFCAP_POLLING)
+ return;
#endif
- E1000_WRITE_REG(&adapter->hw, E1000_EIMS, que->eims);
+ /* Reenable this interrupt */
+ if (que->eims)
+ E1000_WRITE_REG(&adapter->hw, E1000_EIMS, que->eims);
+ else
+ igb_enable_intr(adapter);
}
/* Deal with link in a sleepable context */
@@ -1923,11 +1902,6 @@ igb_local_timer(void *arg)
goto timeout;
}
- /* Trigger an RX interrupt on all queues */
-#ifdef DEVICE_POLLING
- if (!(ifp->if_capenable & IFCAP_POLLING))
-#endif
- E1000_WRITE_REG(&adapter->hw, E1000_EICS, adapter->rx_mask);
callout_reset(&adapter->timer, hz, igb_local_timer, adapter);
return;
@@ -2142,7 +2116,7 @@ igb_allocate_legacy(struct adapter *adapter)
* Try allocating a fast interrupt and the associated deferred
* processing contexts.
*/
- TASK_INIT(&adapter->rxtx_task, 0, igb_handle_rxtx, que);
+ TASK_INIT(&adapter->rxtx_task, 0, igb_handle_que, que);
/* Make tasklet for deferred link handling */
TASK_INIT(&adapter->link_task, 0, igb_handle_link, adapter);
adapter->tq = taskqueue_create_fast("igb_taskq", M_NOWAIT,
@@ -2194,7 +2168,6 @@ igb_allocate_msix(struct adapter *adapter)
device_printf(dev, "Failed to register Queue handler");
return (error);
}
- bus_describe_intr(dev, que->res, que->tag, "que %d", i);
que->msix = vector;
if (adapter->hw.mac.type == e1000_82575)
que->eims = E1000_EICR_TX_QUEUE0 << i;
@@ -2230,7 +2203,6 @@ igb_allocate_msix(struct adapter *adapter)
device_printf(dev, "Failed to register Link handler");
return (error);
}
- bus_describe_intr(dev, adapter->res, adapter->tag, "link");
adapter->linkvec = vector;
/* Make tasklet for deferred handling */
@@ -3572,7 +3544,7 @@ igb_refresh_mbufs(struct rx_ring *rxr, int limit)
cleaned = -1; /* Signify no completions */
while (i != limit) {
rxbuf = &rxr->rx_buffers[i];
- if (rxbuf->m_head == NULL) {
+ if ((rxbuf->m_head == NULL) && (rxr->hdr_split)) {
mh = m_gethdr(M_DONTWAIT, MT_DATA);
if (mh == NULL)
goto update;
@@ -3778,16 +3750,24 @@ igb_setup_receive_ring(struct rx_ring *rxr)
*/
igb_free_receive_ring(rxr);
+ /* Configure for header split? */
+ if (igb_header_split)
+ rxr->hdr_split = TRUE;
+
/* Now replenish the ring mbufs */
for (int j = 0; j != adapter->num_rx_desc; ++j) {
struct mbuf *mh, *mp;
rxbuf = &rxr->rx_buffers[j];
+ if (rxr->hdr_split == FALSE)
+ goto skip_head;
/* First the header */
rxbuf->m_head = m_gethdr(M_DONTWAIT, MT_DATA);
- if (rxbuf->m_head == NULL)
+ if (rxbuf->m_head == NULL) {
+ error = ENOBUFS;
goto fail;
+ }
m_adj(rxbuf->m_head, ETHER_ALIGN);
mh = rxbuf->m_head;
mh->m_len = mh->m_pkthdr.len = MHLEN;
@@ -3803,11 +3783,14 @@ igb_setup_receive_ring(struct rx_ring *rxr)
/* Update descriptor */
rxr->rx_base[j].read.hdr_addr = htole64(hseg[0].ds_addr);
+skip_head:
/* Now the payload cluster */
rxbuf->m_pack = m_getjcl(M_DONTWAIT, MT_DATA,
M_PKTHDR, adapter->rx_mbuf_sz);
- if (rxbuf->m_pack == NULL)
+ if (rxbuf->m_pack == NULL) {
+ error = ENOBUFS;
goto fail;
+ }
mp = rxbuf->m_pack;
mp->m_pkthdr.len = mp->m_len = adapter->rx_mbuf_sz;
/* Get the memory mapping */
@@ -3826,11 +3809,8 @@ igb_setup_receive_ring(struct rx_ring *rxr)
rxr->next_to_check = 0;
rxr->next_to_refresh = 0;
rxr->lro_enabled = FALSE;
-
- if (igb_header_split)
- rxr->hdr_split = TRUE;
- else
- ifp->if_capabilities &= ~IFCAP_LRO;
+ rxr->rx_split_packets = 0;
+ rxr->rx_bytes = 0;
rxr->fmp = NULL;
rxr->lmp = NULL;
@@ -3874,7 +3854,7 @@ static int
igb_setup_receive_structures(struct adapter *adapter)
{
struct rx_ring *rxr = adapter->rx_rings;
- int i, j;
+ int i;
for (i = 0; i < adapter->num_queues; i++, rxr++)
if (igb_setup_receive_ring(rxr))
@@ -3885,13 +3865,11 @@ fail:
/*
* Free RX buffers allocated so far, we will only handle
* the rings that completed, the failing case will have
- * cleaned up for itself. The value of 'i' will be the
- * failed ring so we must pre-decrement it.
+ * cleaned up for itself. 'i' is the endpoint.
*/
- rxr = adapter->rx_rings;
- for (--i; i > 0; i--, rxr++) {
- for (j = 0; j < adapter->num_rx_desc; j++)
- igb_free_receive_ring(rxr);
+ for (int j = 0; j > i; ++j) {
+ rxr = &adapter->rx_rings[i];
+ igb_free_receive_ring(rxr);
}
return (ENOBUFS);
@@ -4197,7 +4175,9 @@ igb_rx_input(struct rx_ring *rxr, struct ifnet *ifp, struct mbuf *m, u32 ptype)
if (tcp_lro_rx(&rxr->lro, m, 0) == 0)
return;
}
+ IGB_RX_UNLOCK(rxr);
(*ifp->if_input)(ifp, m);
+ IGB_RX_LOCK(rxr);
}
/*********************************************************************
@@ -4368,8 +4348,11 @@ next_desc:
/*
** Send to the stack or LRO
*/
- if (sendmp != NULL)
+ if (sendmp != NULL) {
+ rxr->next_to_check = i;
igb_rx_input(rxr, ifp, sendmp, ptype);
+ i = rxr->next_to_check;
+ }
/* Every 8 descriptors we go to refresh mbufs */
if (processed == 8) {
@@ -4838,19 +4821,14 @@ igb_print_debug_info(struct adapter *adapter)
adapter->hw.fc.high_water,
adapter->hw.fc.low_water);
- for (int i = 0; i < adapter->num_queues; i++, rxr++, txr++) {
+ for (int i = 0; i < adapter->num_queues; i++, txr++) {
device_printf(dev, "Queue(%d) tdh = %d, tdt = %d ", i,
E1000_READ_REG(&adapter->hw, E1000_TDH(i)),
E1000_READ_REG(&adapter->hw, E1000_TDT(i)));
- device_printf(dev, "rdh = %d, rdt = %d\n",
- E1000_READ_REG(&adapter->hw, E1000_RDH(i)),
- E1000_READ_REG(&adapter->hw, E1000_RDT(i)));
- device_printf(dev, "TX(%d) no descriptors avail event = %lld\n",
+ device_printf(dev, "TX(%d) no descriptors = %lld\n",
txr->me, (long long)txr->no_desc_avail);
device_printf(dev, "TX(%d) Packets sent = %lld\n",
txr->me, (long long)txr->tx_packets);
- device_printf(dev, "RX(%d) Packets received = %lld ",
- rxr->me, (long long)rxr->rx_packets);
}
for (int i = 0; i < adapter->num_queues; i++, rxr++) {
@@ -4870,7 +4848,7 @@ igb_print_debug_info(struct adapter *adapter)
}
for (int i = 0; i < adapter->num_queues; i++, que++)
- device_printf(dev,"QUE(%d) IRQs = %llx\n",
+ device_printf(dev,"QUE(%d) IRQs = %lld\n",
i, (long long)que->irqs);
device_printf(dev, "LINK MSIX IRQ Handled = %u\n", adapter->link_irq);
OpenPOWER on IntegriCloud