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 @@ -270,6 +270,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 @@ -400,6 +400,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, max_dma, 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"); @@ -683,6 +687,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 */ @@ -972,7 +985,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; } @@ -1098,9 +1111,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); @@ -2061,7 +2074,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); @@ -2092,7 +2105,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); @@ -2344,7 +2357,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); } @@ -3195,7 +3208,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 @@ -3519,7 +3532,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 */ @@ -4188,7 +4201,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); }