From d9f1a5aa8ed48a7b829430535811a23f126981c8 Mon Sep 17 00:00:00 2001 From: Jack F Vogel Date: Tue, 7 Sep 2010 20:13:08 +0000 Subject: [PATCH] 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. --- sys/dev/e1000/if_em.c | 112 +++++++++++++++++++++++------------------- sys/dev/e1000/if_em.h | 4 +- 2 files changed, 65 insertions(+), 51 deletions(-) diff --git a/sys/dev/e1000/if_em.c b/sys/dev/e1000/if_em.c index e5dfa36416af..9c5a609b883e 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 @@ em_setup_msix(struct adapter *adapter) 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 @@ em_rxeof(struct rx_ring *rxr, int count, int *done) } } 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 @@ em_rxeof(struct rx_ring *rxr, int count, int *done) 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 d164edb18592..229cc0cc392c 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;