Index: share/man/man4/em.4 =================================================================== --- share/man/man4/em.4 +++ share/man/man4/em.4 @@ -258,6 +258,11 @@ Defaults to 1. Only valid with kernel configuration .Cd "options EM_MULTIQUEUE". +.It Va hw.em.max_dma +Non-zero value that controls how many mbufs are DMA'd to and from the +hardware and what the tso size advertized up the stack will be. Defaults +to EM_MAX_SCATTER or 64 and is adjusted as a quirk for other boards to a +value of EM_MAX_LEGACY_SCATTER or 40. .El .Sh FILES .Bl -tag -width /dev/led/em* Index: sys/dev/e1000/if_em.h =================================================================== --- sys/dev/e1000/if_em.h +++ sys/dev/e1000/if_em.h @@ -267,6 +267,7 @@ #define HW_DEBUGOUT2(S, A, B) if (DEBUG_HW) printf(S "\n", A, B) #define EM_MAX_SCATTER 64 +#define EM_MAX_LEGACY_SCATTER 40 #define EM_VFTA_SIZE 128 #define EM_TSO_SIZE (65535 + sizeof(struct ether_vlan_header)) #define EM_TSO_SEG_SIZE 4096 /* Max dma segment size */ Index: sys/dev/e1000/if_em.c =================================================================== --- sys/dev/e1000/if_em.c +++ sys/dev/e1000/if_em.c @@ -397,6 +397,10 @@ SYSCTL_INT(_hw_em, OID_AUTO, txd, CTLFLAG_RDTUN, &em_txd, 0, "Number of transmit descriptors per queue"); +static int em_max_dma = EM_MAX_SCATTER; +SYSCTL_INT(_hw_em, OID_AUTO, rxd, CTLFLAG_RDTUN, &em_max_dma 0, + "Maximum number of descriptors we allow to be pushed to the card"); + static int em_smart_pwr_down = FALSE; SYSCTL_INT(_hw_em, OID_AUTO, smart_pwr_down, CTLFLAG_RDTUN, &em_smart_pwr_down, 0, "Set to true to leave smart power down enabled on newer adapters"); @@ -665,6 +669,15 @@ */ hw->mac.report_tx_early = 1; + /* + * If there is a known quirk for an Intel board + * where it cannot handle a DMA of >40 mbufs, note + * it here. sbruno 04FEB2016 + */ + if (hw->mac.type == e1000_82573) { + if (em_max_dma > EM_MAX_LEGACY_SCATTER) + em_max_dma = EM_MAX_LEGACY_SCATTER; + } /* ** Get queue/ring memory */ @@ -954,7 +967,7 @@ /* Call cleanup if number of TX descriptors low */ if (txr->tx_avail <= EM_TX_CLEANUP_THRESHOLD) em_txeof(txr); - if (txr->tx_avail < EM_MAX_SCATTER) { + if (txr->tx_avail < em_max_dma) { if_setdrvflagbits(ifp,IFF_DRV_OACTIVE, 0); break; } @@ -1080,9 +1093,9 @@ if ((enq > 0) && (txr->busy == EM_TX_IDLE)) txr->busy = EM_TX_BUSY; - if (txr->tx_avail < EM_MAX_SCATTER) + if (txr->tx_avail < em_max_dma) em_txeof(txr); - if (txr->tx_avail < EM_MAX_SCATTER) { + if (txr->tx_avail < em_max_dma) { if_setdrvflagbits(ifp, IFF_DRV_OACTIVE,0); } return (err); @@ -1879,7 +1892,7 @@ em_xmit(struct tx_ring *txr, struct mbuf **m_headp) { struct adapter *adapter = txr->adapter; - bus_dma_segment_t segs[EM_MAX_SCATTER]; + bus_dma_segment_t segs[em_max_dma]; bus_dmamap_t map; struct em_txbuffer *tx_buffer, *tx_buffer_mapped; struct e1000_tx_desc *ctxd = NULL; @@ -2042,7 +2055,7 @@ if (error == EFBIG && remap) { struct mbuf *m; - m = m_collapse(*m_headp, M_NOWAIT, EM_MAX_SCATTER); + m = m_collapse(*m_headp, M_NOWAIT, em_max_dma); if (m == NULL) { adapter->mbuf_defrag_failed++; m_freem(*m_headp); @@ -2073,7 +2086,7 @@ txr->tx_tso = FALSE; } - if (nsegs > (txr->tx_avail - EM_MAX_SCATTER)) { + if (nsegs > (txr->tx_avail - em_max_dma)) { txr->no_desc_avail++; bus_dmamap_unload(txr->txtag, map); return (ENOBUFS); @@ -2325,7 +2338,7 @@ if (txr->busy >= EM_TX_MAXTRIES) txr->busy = EM_TX_HUNG; /* Schedule a TX tasklet if needed */ - if (txr->tx_avail <= EM_MAX_SCATTER) + if (txr->tx_avail <= em_max_dma) taskqueue_enqueue(txr->tq, &txr->tx_task); } @@ -3054,7 +3067,7 @@ if_setgetcounterfn(ifp, em_get_counter); /* TSO parameters */ ifp->if_hw_tsomax = IP_MAXPACKET; - ifp->if_hw_tsomaxsegcount = EM_MAX_SCATTER; + ifp->if_hw_tsomaxsegcount = em_max_dma; ifp->if_hw_tsomaxsegsize = EM_TSO_SEG_SIZE; #ifdef EM_MULTIQUEUE @@ -3378,7 +3391,7 @@ BUS_SPACE_MAXADDR, /* highaddr */ NULL, NULL, /* filter, filterarg */ EM_TSO_SIZE, /* maxsize */ - EM_MAX_SCATTER, /* nsegments */ + em_max_dma, /* nsegments */ PAGE_SIZE, /* maxsegsize */ 0, /* flags */ NULL, /* lockfunc */ @@ -4038,7 +4051,7 @@ * TX lock which, with a single queue, guarantees * sanity. */ - if (txr->tx_avail >= EM_MAX_SCATTER) { + if (txr->tx_avail >= em_max_dma) { if_setdrvflagbits(ifp, 0, IFF_DRV_OACTIVE); }