summaryrefslogtreecommitdiffstats
path: root/sys/dev/e1000
diff options
context:
space:
mode:
authorjfv <jfv@FreeBSD.org>2010-09-07 20:13:08 +0000
committerjfv <jfv@FreeBSD.org>2010-09-07 20:13:08 +0000
commit62814bf50cf8a8c9acaff4bb25428f2d32f1cf91 (patch)
treec4884ae35544f48c9262a2d078128ebf8a0f2e00 /sys/dev/e1000
parentbe2f46c2bbd64f0cdab557444c05f767ff97a55d (diff)
downloadFreeBSD-src-62814bf50cf8a8c9acaff4bb25428f2d32f1cf91.zip
FreeBSD-src-62814bf50cf8a8c9acaff4bb25428f2d32f1cf91.tar.gz
Tighten up the rx mbuf refresh code, there were some
discrepencies from the igb version which was the target. Change the message when neither MSI or MSIX are enabled and a fallback to Legacy interrupts happen, the existing message was confusing.
Diffstat (limited to 'sys/dev/e1000')
-rw-r--r--sys/dev/e1000/if_em.c112
-rw-r--r--sys/dev/e1000/if_em.h4
2 files changed, 65 insertions, 51 deletions
diff --git a/sys/dev/e1000/if_em.c b/sys/dev/e1000/if_em.c
index e5dfa36..9c5a609 100644
--- a/sys/dev/e1000/if_em.c
+++ b/sys/dev/e1000/if_em.c
@@ -93,7 +93,7 @@ int em_display_debug_stats = 0;
/*********************************************************************
* Driver version:
*********************************************************************/
-char em_driver_version[] = "7.0.5";
+char em_driver_version[] = "7.0.6";
/*********************************************************************
@@ -281,6 +281,8 @@ static void em_handle_link(void *context, int pending);
static void em_add_rx_process_limit(struct adapter *, const char *,
const char *, int *, int);
+static __inline void em_rx_discard(struct rx_ring *, int);
+
#ifdef DEVICE_POLLING
static poll_handler_t em_poll;
#endif /* POLLING */
@@ -2563,11 +2565,11 @@ msi:
val = pci_msi_count(dev);
if (val == 1 && pci_alloc_msi(dev, &val) == 0) {
adapter->msix = 1;
- device_printf(adapter->dev,"Using MSI interrupt\n");
+ device_printf(adapter->dev,"Using an MSI interrupt\n");
return (val);
}
- /* Should only happen due to manual invention */
- device_printf(adapter->dev,"Setup MSIX failure\n");
+ /* Should only happen due to manual configuration */
+ device_printf(adapter->dev,"No MSI/MSIX using a Legacy IRQ\n");
return (0);
}
@@ -3681,14 +3683,27 @@ em_refresh_mbufs(struct rx_ring *rxr, int limit)
struct adapter *adapter = rxr->adapter;
struct mbuf *m;
bus_dma_segment_t segs[1];
- bus_dmamap_t map;
struct em_buffer *rxbuf;
int i, error, nsegs, cleaned;
i = rxr->next_to_refresh;
cleaned = -1;
while (i != limit) {
+ rxbuf = &rxr->rx_buffers[i];
+ /*
+ ** Just skip entries with a buffer,
+ ** they can only be due to an error
+ ** and are to be reused.
+ */
+ if (rxbuf->m_head != NULL)
+ continue;
m = m_getcl(M_DONTWAIT, MT_DATA, M_PKTHDR);
+ /*
+ ** If we have a temporary resource shortage
+ ** that causes a failure, just abort refresh
+ ** for now, we will return to this point when
+ ** reinvoked from em_rxeof.
+ */
if (m == NULL)
goto update;
m->m_len = m->m_pkthdr.len = MCLBYTES;
@@ -3696,11 +3711,8 @@ em_refresh_mbufs(struct rx_ring *rxr, int limit)
if (adapter->max_frame_size <= (MCLBYTES - ETHER_ALIGN))
m_adj(m, ETHER_ALIGN);
- /*
- * Using memory from the mbuf cluster pool, invoke the
- * bus_dma machinery to arrange the memory mapping.
- */
- error = bus_dmamap_load_mbuf_sg(rxr->rxtag, rxr->rx_sparemap,
+ /* Use bus_dma machinery to setup the memory mapping */
+ error = bus_dmamap_load_mbuf_sg(rxr->rxtag, rxbuf->map,
m, segs, &nsegs, BUS_DMA_NOWAIT);
if (error != 0) {
m_free(m);
@@ -3710,13 +3722,6 @@ em_refresh_mbufs(struct rx_ring *rxr, int limit)
/* If nsegs is wrong then the stack is corrupt. */
KASSERT(nsegs == 1, ("Too many segments returned!"));
- rxbuf = &rxr->rx_buffers[i];
- if (rxbuf->m_head != NULL)
- bus_dmamap_unload(rxr->rxtag, rxbuf->map);
-
- map = rxbuf->map;
- rxbuf->map = rxr->rx_sparemap;
- rxr->rx_sparemap = map;
bus_dmamap_sync(rxr->rxtag,
rxbuf->map, BUS_DMASYNC_PREREAD);
rxbuf->m_head = m;
@@ -3730,8 +3735,10 @@ em_refresh_mbufs(struct rx_ring *rxr, int limit)
rxr->next_to_refresh = i;
}
update:
- bus_dmamap_sync(rxr->rxdma.dma_tag, rxr->rxdma.dma_map,
- BUS_DMASYNC_PREREAD | BUS_DMASYNC_PREWRITE);
+ /*
+ ** Update the tail pointer only if,
+ ** and as far as we have refreshed.
+ */
if (cleaned != -1) /* Update tail index */
E1000_WRITE_REG(&adapter->hw,
E1000_RDT(rxr->me), cleaned);
@@ -3781,15 +3788,6 @@ em_allocate_receive_buffers(struct rx_ring *rxr)
goto fail;
}
- /* Create the spare map (used by getbuf) */
- error = bus_dmamap_create(rxr->rxtag, BUS_DMA_NOWAIT,
- &rxr->rx_sparemap);
- if (error) {
- device_printf(dev, "%s: bus_dmamap_create failed: %d\n",
- __func__, error);
- goto fail;
- }
-
rxbuf = rxr->rx_buffers;
for (int i = 0; i < adapter->num_rx_desc; i++, rxbuf++) {
rxbuf = &rxr->rx_buffers[i];
@@ -3956,11 +3954,6 @@ em_free_receive_buffers(struct rx_ring *rxr)
INIT_DEBUGOUT("free_receive_buffers: begin");
- if (rxr->rx_sparemap) {
- bus_dmamap_destroy(rxr->rxtag, rxr->rx_sparemap);
- rxr->rx_sparemap = NULL;
- }
-
if (rxr->rx_buffers != NULL) {
for (int i = 0; i < adapter->num_rx_desc; i++) {
rxbuf = &rxr->rx_buffers[i];
@@ -4132,12 +4125,16 @@ em_rxeof(struct rx_ring *rxr, int count, int *done)
eop = (status & E1000_RXD_STAT_EOP) != 0;
count--;
- if ((cur->errors & E1000_RXD_ERR_FRAME_ERR_MASK) == 0) {
+ if (((cur->errors & E1000_RXD_ERR_FRAME_ERR_MASK) == 0) &&
+ (rxr->discard == FALSE)) {
/* Assign correct length to the current fragment */
mp = rxr->rx_buffers[i].m_head;
mp->m_len = len;
+ /* Trigger for refresh */
+ rxr->rx_buffers[i].m_head = NULL;
+
if (rxr->fmp == NULL) {
mp->m_pkthdr.len = len;
rxr->fmp = mp; /* Store the first mbuf */
@@ -4179,19 +4176,12 @@ skip:
}
} else {
ifp->if_ierrors++;
- /* Reuse loaded DMA map and just update mbuf chain */
- mp = rxr->rx_buffers[i].m_head;
- mp->m_len = mp->m_pkthdr.len = MCLBYTES;
- mp->m_data = mp->m_ext.ext_buf;
- mp->m_next = NULL;
- if (adapter->max_frame_size <=
- (MCLBYTES - ETHER_ALIGN))
- m_adj(mp, ETHER_ALIGN);
- if (rxr->fmp != NULL) {
- m_freem(rxr->fmp);
- rxr->fmp = NULL;
- rxr->lmp = NULL;
- }
+ ++rxr->rx_discarded;
+ if (!eop) /* Catch subsequent segs */
+ rxr->discard = TRUE;
+ else
+ rxr->discard = FALSE;
+ em_rx_discard(rxr, i);
sendmp = NULL;
}
@@ -4234,6 +4224,31 @@ skip:
return ((status & E1000_RXD_STAT_DD) ? TRUE : FALSE);
}
+static __inline void
+em_rx_discard(struct rx_ring *rxr, int i)
+{
+ struct em_buffer *rbuf;
+ struct mbuf *m;
+
+ rbuf = &rxr->rx_buffers[i];
+ /* Free any previous pieces */
+ if (rxr->fmp != NULL) {
+ rxr->fmp->m_flags |= M_PKTHDR;
+ m_freem(rxr->fmp);
+ rxr->fmp = NULL;
+ rxr->lmp = NULL;
+ }
+
+ /* Reset state, keep loaded DMA map and reuse */
+ m = rbuf->m_head;
+ m->m_len = m->m_pkthdr.len = MCLBYTES;
+ m->m_flags |= M_PKTHDR;
+ m->m_data = m->m_ext.ext_buf;
+ m->m_next = NULL;
+
+ return;
+}
+
#ifndef __NO_STRICT_ALIGNMENT
/*
* When jumbo frames are enabled we should realign entire payload on
@@ -5159,8 +5174,6 @@ em_add_hw_stats(struct adapter *adapter)
CTLFLAG_RD, &adapter->stats.hrmpc,
"Header Redirection Missed Packet Count");
-
-
}
/**********************************************************************
@@ -5170,7 +5183,6 @@ em_add_hw_stats(struct adapter *adapter)
* 32 words, stuff that matters is in that extent.
*
**********************************************************************/
-
static int
em_sysctl_nvm_info(SYSCTL_HANDLER_ARGS)
{
diff --git a/sys/dev/e1000/if_em.h b/sys/dev/e1000/if_em.h
index d164edb..229cc0c 100644
--- a/sys/dev/e1000/if_em.h
+++ b/sys/dev/e1000/if_em.h
@@ -320,10 +320,11 @@ struct rx_ring {
void *tag;
struct resource *res;
bus_dma_tag_t rxtag;
- bus_dmamap_t rx_sparemap;
+ bool discard;
/* Soft stats */
unsigned long rx_irq;
+ unsigned long rx_discarded;
unsigned long rx_packets;
unsigned long rx_bytes;
};
@@ -393,6 +394,7 @@ struct adapter {
/* Multicast array memory */
u8 *mta;
+
/* Info about the board itself */
uint8_t link_active;
uint16_t link_speed;
OpenPOWER on IntegriCloud