Index: head/sys/dev/bnxt/if_bnxt.c =================================================================== --- head/sys/dev/bnxt/if_bnxt.c +++ head/sys/dev/bnxt/if_bnxt.c @@ -300,10 +300,12 @@ .isc_nfl = 2, // Number of Free Lists .isc_flags = IFLIB_HAS_RXCQ | IFLIB_HAS_TXCQ | IFLIB_NEED_ETHER_PAD, .isc_q_align = PAGE_SIZE, - .isc_tx_maxsize = BNXT_TSO_SIZE, - .isc_tx_maxsegsize = BNXT_TSO_SIZE, - .isc_rx_maxsize = BNXT_TSO_SIZE, - .isc_rx_maxsegsize = BNXT_TSO_SIZE, + .isc_tx_maxsize = BNXT_TSO_SIZE + sizeof(struct ether_vlan_header), + .isc_tx_maxsegsize = BNXT_TSO_SIZE + sizeof(struct ether_vlan_header), + .isc_tso_maxsize = BNXT_TSO_SIZE + sizeof(struct ether_vlan_header), + .isc_tso_maxsegsize = BNXT_TSO_SIZE + sizeof(struct ether_vlan_header), + .isc_rx_maxsize = BNXT_TSO_SIZE + sizeof(struct ether_vlan_header), + .isc_rx_maxsegsize = BNXT_TSO_SIZE + sizeof(struct ether_vlan_header), // Only use a single segment to avoid page size constraints .isc_rx_nsegments = 1, @@ -784,7 +786,7 @@ scctx->isc_txrx = &bnxt_txrx; scctx->isc_tx_csum_flags = (CSUM_IP | CSUM_TCP | CSUM_UDP | CSUM_TCP_IPV6 | CSUM_UDP_IPV6 | CSUM_TSO); - scctx->isc_capenable = + scctx->isc_capabilities = scctx->isc_capenable = /* These are translated to hwassit bits */ IFCAP_TXCSUM | IFCAP_TXCSUM_IPV6 | IFCAP_TSO4 | IFCAP_TSO6 | /* These are checked by iflib */ Index: head/sys/dev/e1000/if_em.h =================================================================== --- head/sys/dev/e1000/if_em.h +++ head/sys/dev/e1000/if_em.h @@ -250,11 +250,6 @@ #define IGB_LINK_ITR 2000 #define I210_LINK_DELAY 1000 -#define IGB_MAX_SCATTER 40 -#define IGB_VFTA_SIZE 128 -#define IGB_BR_SIZE 4096 /* ring buf size */ -#define IGB_TSO_SIZE (65535 + sizeof(struct ether_vlan_header)) -#define IGB_TSO_SEG_SIZE 4096 /* Max dma segment size */ #define IGB_TXPBSIZE 20408 #define IGB_HDR_BUF 128 #define IGB_PKTTYPE_MASK 0x0000FFF0 @@ -340,7 +335,7 @@ #define EM_MAX_SCATTER 40 #define EM_VFTA_SIZE 128 -#define EM_TSO_SIZE (65535 + sizeof(struct ether_vlan_header)) +#define EM_TSO_SIZE 65535 #define EM_TSO_SEG_SIZE 4096 /* Max dma segment size */ #define EM_MSIX_MASK 0x01F00000 /* For 82574 use */ #define EM_MSIX_LINK 0x01000000 /* For 82574 use */ Index: head/sys/dev/e1000/if_em.c =================================================================== --- head/sys/dev/e1000/if_em.c +++ head/sys/dev/e1000/if_em.c @@ -410,7 +410,6 @@ #define EM_TICKS_TO_USECS(ticks) ((1024 * (ticks) + 500) / 1000) #define EM_USECS_TO_TICKS(usecs) ((1000 * (usecs) + 512) / 1024) -#define M_TSO_LEN 66 #define MAX_INTS_PER_SEC 8000 #define DEFAULT_ITR (1000000000/(MAX_INTS_PER_SEC * 256)) @@ -420,8 +419,6 @@ #define CSUM_TSO 0 #endif -#define TSO_WORKAROUND 4 - static SYSCTL_NODE(_hw, OID_AUTO, em, CTLFLAG_RD, 0, "EM driver parameters"); static int em_disable_crc_stripping = 0; @@ -484,8 +481,10 @@ static struct if_shared_ctx em_sctx_init = { .isc_magic = IFLIB_MAGIC, .isc_q_align = PAGE_SIZE, - .isc_tx_maxsize = EM_TSO_SIZE, + .isc_tx_maxsize = EM_TSO_SIZE + sizeof(struct ether_vlan_header), .isc_tx_maxsegsize = PAGE_SIZE, + .isc_tso_maxsize = EM_TSO_SIZE + sizeof(struct ether_vlan_header), + .isc_tso_maxsegsize = EM_TSO_SEG_SIZE, .isc_rx_maxsize = MJUM9BYTES, .isc_rx_nsegments = 1, .isc_rx_maxsegsize = MJUM9BYTES, @@ -697,16 +696,19 @@ return (maxqueues); } +#define LEM_CAPS \ + IFCAP_HWCSUM | IFCAP_VLAN_MTU | IFCAP_VLAN_HWTAGGING | \ + IFCAP_VLAN_HWCSUM | IFCAP_WOL | IFCAP_VLAN_HWFILTER -#define EM_CAPS \ - IFCAP_TSO4 | IFCAP_TXCSUM | IFCAP_LRO | IFCAP_RXCSUM | IFCAP_VLAN_HWFILTER | IFCAP_WOL_MAGIC | \ - IFCAP_WOL_MCAST | IFCAP_WOL | IFCAP_VLAN_HWTSO | IFCAP_HWCSUM | IFCAP_VLAN_HWTAGGING | \ - IFCAP_VLAN_HWCSUM | IFCAP_VLAN_HWTSO | IFCAP_VLAN_MTU; +#define EM_CAPS \ + IFCAP_HWCSUM | IFCAP_VLAN_MTU | IFCAP_VLAN_HWTAGGING | \ + IFCAP_VLAN_HWCSUM | IFCAP_WOL | IFCAP_VLAN_HWFILTER | IFCAP_TSO4 | \ + IFCAP_LRO | IFCAP_VLAN_HWTSO -#define IGB_CAPS \ - IFCAP_TSO4 | IFCAP_TXCSUM | IFCAP_LRO | IFCAP_RXCSUM | IFCAP_VLAN_HWFILTER | IFCAP_WOL_MAGIC | \ - IFCAP_WOL_MCAST | IFCAP_WOL | IFCAP_VLAN_HWTSO | IFCAP_HWCSUM | IFCAP_VLAN_HWTAGGING | IFCAP_VLAN_HWCSUM | \ - IFCAP_VLAN_HWTSO | IFCAP_VLAN_MTU | IFCAP_TXCSUM_IPV6 | IFCAP_HWCSUM_IPV6 | IFCAP_JUMBO_MTU; +#define IGB_CAPS \ + IFCAP_HWCSUM | IFCAP_VLAN_MTU | IFCAP_VLAN_HWTAGGING | \ + IFCAP_VLAN_HWCSUM | IFCAP_WOL | IFCAP_VLAN_HWFILTER | IFCAP_TSO4 | \ + IFCAP_LRO | IFCAP_VLAN_HWTSO | IFCAP_JUMBO_MTU | IFCAP_HWCSUM_IPV6; /********************************************************************* * Device initialization routine @@ -773,18 +775,11 @@ /* Determine hardware and mac info */ em_identify_hardware(ctx); - /* Set isc_msix_bar */ scctx->isc_msix_bar = PCIR_BAR(EM_MSIX_BAR); scctx->isc_tx_nsegments = EM_MAX_SCATTER; - scctx->isc_tx_tso_segments_max = scctx->isc_tx_nsegments; - scctx->isc_tx_tso_size_max = EM_TSO_SIZE; - scctx->isc_tx_tso_segsize_max = EM_TSO_SEG_SIZE; scctx->isc_nrxqsets_max = scctx->isc_ntxqsets_max = em_set_num_queues(ctx); device_printf(dev, "attach_pre capping queues at %d\n", scctx->isc_ntxqsets_max); - scctx->isc_tx_csum_flags = CSUM_TCP | CSUM_UDP | CSUM_IP_TSO; - - if (adapter->hw.mac.type >= igb_mac_min) { int try_second_bar; @@ -793,7 +788,10 @@ scctx->isc_txd_size[0] = sizeof(union e1000_adv_tx_desc); scctx->isc_rxd_size[0] = sizeof(union e1000_adv_rx_desc); scctx->isc_txrx = &igb_txrx; - scctx->isc_capenable = IGB_CAPS; + scctx->isc_tx_tso_segments_max = EM_MAX_SCATTER; + scctx->isc_tx_tso_size_max = EM_TSO_SIZE; + scctx->isc_tx_tso_segsize_max = EM_TSO_SEG_SIZE; + scctx->isc_capabilities = scctx->isc_capenable = IGB_CAPS; scctx->isc_tx_csum_flags = CSUM_TCP | CSUM_UDP | CSUM_TSO | CSUM_IP6_TCP \ | CSUM_IP6_UDP | CSUM_IP6_TCP; if (adapter->hw.mac.type != e1000_82575) @@ -807,26 +805,44 @@ try_second_bar = pci_read_config(dev, scctx->isc_msix_bar, 4); if (try_second_bar == 0) scctx->isc_msix_bar += 4; - } else if (adapter->hw.mac.type >= em_mac_min) { scctx->isc_txqsizes[0] = roundup2(scctx->isc_ntxd[0]* sizeof(struct e1000_tx_desc), EM_DBA_ALIGN); scctx->isc_rxqsizes[0] = roundup2(scctx->isc_nrxd[0] * sizeof(union e1000_rx_desc_extended), EM_DBA_ALIGN); scctx->isc_txd_size[0] = sizeof(struct e1000_tx_desc); scctx->isc_rxd_size[0] = sizeof(union e1000_rx_desc_extended); scctx->isc_txrx = &em_txrx; - scctx->isc_capenable = EM_CAPS; + scctx->isc_tx_tso_segments_max = EM_MAX_SCATTER; + scctx->isc_tx_tso_size_max = EM_TSO_SIZE; + scctx->isc_tx_tso_segsize_max = EM_TSO_SEG_SIZE; + scctx->isc_capabilities = scctx->isc_capenable = EM_CAPS; + /* + * For EM-class devices, don't enable IFCAP_{TSO4,VLAN_HWTSO} + * by default as we don't have workarounds for all associated + * silicon errata. E. g., with several MACs such as 82573E, + * TSO only works at Gigabit speed and otherwise can cause the + * hardware to hang (which also would be next to impossible to + * work around given that already queued TSO-using descriptors + * would need to be flushed and vlan(4) reconfigured at runtime + * in case of a link speed change). Moreover, MACs like 82579 + * still can hang at Gigabit even with all publicly documented + * TSO workarounds implemented. Generally, the penality of + * these workarounds is rather high and may involve copying + * mbuf data around so advantages of TSO lapse. Still, TSO may + * work for a few MACs of this class - at least when sticking + * with Gigabit - in which case users may enable TSO manually. + */ + scctx->isc_capenable &= ~(IFCAP_TSO4 | IFCAP_VLAN_HWTSO); scctx->isc_tx_csum_flags = CSUM_TCP | CSUM_UDP | CSUM_IP_TSO; } else { scctx->isc_txqsizes[0] = roundup2((scctx->isc_ntxd[0] + 1) * sizeof(struct e1000_tx_desc), EM_DBA_ALIGN); scctx->isc_rxqsizes[0] = roundup2((scctx->isc_nrxd[0] + 1) * sizeof(struct e1000_rx_desc), EM_DBA_ALIGN); scctx->isc_txd_size[0] = sizeof(struct e1000_tx_desc); scctx->isc_rxd_size[0] = sizeof(struct e1000_rx_desc); - scctx->isc_tx_csum_flags = CSUM_TCP | CSUM_UDP | CSUM_IP_TSO; + scctx->isc_tx_csum_flags = CSUM_TCP | CSUM_UDP; scctx->isc_txrx = &lem_txrx; - scctx->isc_capenable = EM_CAPS; + scctx->isc_capabilities = scctx->isc_capenable = LEM_CAPS; if (adapter->hw.mac.type < e1000_82543) scctx->isc_capenable &= ~(IFCAP_HWCSUM|IFCAP_VLAN_HWCSUM); - scctx->isc_tx_csum_flags = CSUM_TCP | CSUM_UDP | CSUM_IP_TSO; scctx->isc_msix_bar = 0; } @@ -1007,6 +1023,11 @@ */ em_get_wakeup(ctx); + /* Enable only WOL MAGIC by default */ + scctx->isc_capenable &= ~IFCAP_WOL; + if (adapter->wol != 0) + scctx->isc_capenable |= IFCAP_WOL_MAGIC; + iflib_set_mac(ctx, hw->mac.addr); return (0); @@ -2750,49 +2771,13 @@ struct ifnet *ifp = iflib_get_ifp(ctx); struct adapter *adapter = iflib_get_softc(ctx); if_softc_ctx_t scctx = adapter->shared; - uint64_t cap = 0; INIT_DEBUGOUT("em_setup_interface: begin"); - /* TSO parameters */ - if_sethwtsomax(ifp, IP_MAXPACKET); - /* Take m_pullup(9)'s in em_xmit() w/ TSO into acount. */ - if_sethwtsomaxsegcount(ifp, EM_MAX_SCATTER - 5); - if_sethwtsomaxsegsize(ifp, EM_TSO_SEG_SIZE); - /* Single Queue */ if (adapter->tx_num_queues == 1) { if_setsendqlen(ifp, scctx->isc_ntxd[0] - 1); if_setsendqready(ifp); - } - - cap = IFCAP_HWCSUM | IFCAP_VLAN_HWCSUM | IFCAP_TSO4; - cap |= IFCAP_VLAN_HWTAGGING | IFCAP_VLAN_HWTSO | IFCAP_VLAN_MTU; - - /* - * Tell the upper layer(s) we - * support full VLAN capability - */ - if_setifheaderlen(ifp, sizeof(struct ether_vlan_header)); - if_setcapabilitiesbit(ifp, cap, 0); - - /* - * Don't turn this on by default, if vlans are - * created on another pseudo device (eg. lagg) - * then vlan events are not passed thru, breaking - * operation, but with HW FILTER off it works. If - * using vlans directly on the em driver you can - * enable this and get full hardware tag filtering. - */ - if_setcapabilitiesbit(ifp, IFCAP_VLAN_HWFILTER,0); - - /* Enable only WOL MAGIC by default */ - if (adapter->wol) { - if_setcapenablebit(ifp, IFCAP_WOL_MAGIC, - IFCAP_WOL_MCAST| IFCAP_WOL_UCAST); - } else { - if_setcapenablebit(ifp, 0, IFCAP_WOL_MAGIC | - IFCAP_WOL_MCAST| IFCAP_WOL_UCAST); } /* Index: head/sys/dev/ixgbe/if_ix.c =================================================================== --- head/sys/dev/ixgbe/if_ix.c +++ head/sys/dev/ixgbe/if_ix.c @@ -364,10 +364,10 @@ static struct if_shared_ctx ixgbe_sctx_init = { .isc_magic = IFLIB_MAGIC, .isc_q_align = PAGE_SIZE,/* max(DBA_ALIGN, PAGE_SIZE) */ - .isc_tx_maxsize = IXGBE_TSO_SIZE, - + .isc_tx_maxsize = IXGBE_TSO_SIZE + sizeof(struct ether_vlan_header), .isc_tx_maxsegsize = PAGE_SIZE, - + .isc_tso_maxsize = IXGBE_TSO_SIZE + sizeof(struct ether_vlan_header), + .isc_tso_maxsegsize = PAGE_SIZE, .isc_rx_maxsize = PAGE_SIZE*4, .isc_rx_nsegments = 1, .isc_rx_maxsegsize = PAGE_SIZE*4, @@ -1034,7 +1034,7 @@ scctx->isc_txrx = &ixgbe_txrx; - scctx->isc_capenable = IXGBE_CAPS; + scctx->isc_capabilities = scctx->isc_capenable = IXGBE_CAPS; return (0); @@ -1175,7 +1175,6 @@ INIT_DEBUGOUT("ixgbe_setup_interface: begin"); - if_setifheaderlen(ifp, sizeof(struct ether_vlan_header)); if_setbaudrate(ifp, IF_Gbps(10)); adapter->max_frame_size = ifp->if_mtu + ETHER_HDR_LEN + ETHER_CRC_LEN; Index: head/sys/dev/ixgbe/if_ixv.c =================================================================== --- head/sys/dev/ixgbe/if_ixv.c +++ head/sys/dev/ixgbe/if_ixv.c @@ -209,10 +209,10 @@ static struct if_shared_ctx ixv_sctx_init = { .isc_magic = IFLIB_MAGIC, .isc_q_align = PAGE_SIZE,/* max(DBA_ALIGN, PAGE_SIZE) */ - .isc_tx_maxsize = IXGBE_TSO_SIZE, - + .isc_tx_maxsize = IXGBE_TSO_SIZE + sizeof(struct ether_vlan_header), .isc_tx_maxsegsize = PAGE_SIZE, - + .isc_tso_maxsize = IXGBE_TSO_SIZE + sizeof(struct ether_vlan_header), + .isc_tso_maxsegsize = PAGE_SIZE, .isc_rx_maxsize = MJUM16BYTES, .isc_rx_nsegments = 1, .isc_rx_maxsegsize = MJUM16BYTES, @@ -507,11 +507,11 @@ /* * Tell the upper layer(s) we support everything the PF * driver does except... - * hardware stats * Wake-on-LAN */ - scctx->isc_capenable = IXGBE_CAPS; - scctx->isc_capenable ^= IFCAP_HWSTATS | IFCAP_WOL; + scctx->isc_capabilities = IXGBE_CAPS; + scctx->isc_capabilities ^= IFCAP_WOL; + scctx->isc_capenable = scctx->isc_capabilities; INIT_DEBUGOUT("ixv_if_attach_pre: end"); @@ -1163,7 +1163,6 @@ INIT_DEBUGOUT("ixv_setup_interface: begin"); - if_setifheaderlen(ifp, sizeof(struct ether_vlan_header)); if_setbaudrate(ifp, IF_Gbps(10)); ifp->if_snd.ifq_maxlen = scctx->isc_ntxd[0] - 2; Index: head/sys/dev/ixgbe/ixgbe.h =================================================================== --- head/sys/dev/ixgbe/ixgbe.h +++ head/sys/dev/ixgbe/ixgbe.h @@ -215,7 +215,7 @@ #define IXGBE_CAPS (IFCAP_HWCSUM | IFCAP_HWCSUM_IPV6 | IFCAP_TSO | \ IFCAP_LRO | IFCAP_VLAN_HWTAGGING | IFCAP_VLAN_HWTSO | \ IFCAP_VLAN_HWCSUM | IFCAP_JUMBO_MTU | IFCAP_VLAN_MTU | \ - IFCAP_HWSTATS | IFCAP_VLAN_HWFILTER | IFCAP_WOL) + IFCAP_VLAN_HWFILTER | IFCAP_WOL) /* Backward compatibility items for very old versions */ #ifndef pci_find_cap Index: head/sys/dev/ixl/if_ixl.c =================================================================== --- head/sys/dev/ixl/if_ixl.c +++ head/sys/dev/ixl/if_ixl.c @@ -295,9 +295,10 @@ static struct if_shared_ctx ixl_sctx_init = { .isc_magic = IFLIB_MAGIC, .isc_q_align = PAGE_SIZE, - .isc_tx_maxsize = IXL_TSO_SIZE, + .isc_tx_maxsize = IXL_TSO_SIZE + sizeof(struct ether_vlan_header), .isc_tx_maxsegsize = IXL_MAX_DMA_SEG_SIZE, - + .isc_tso_maxsize = IXL_TSO_SIZE + sizeof(struct ether_vlan_header), + .isc_tso_maxsegsize = IXL_MAX_DMA_SEG_SIZE, .isc_rx_maxsize = 16384, .isc_rx_nsegments = IXL_MAX_RX_SEGS, .isc_rx_maxsegsize = IXL_MAX_DMA_SEG_SIZE, @@ -552,7 +553,7 @@ scctx->isc_tx_tso_segsize_max = IXL_MAX_DMA_SEG_SIZE; scctx->isc_rss_table_size = pf->hw.func_caps.rss_table_size; scctx->isc_tx_csum_flags = CSUM_OFFLOAD; - scctx->isc_capenable = IXL_CAPS; + scctx->isc_capabilities = scctx->isc_capenable = IXL_CAPS; INIT_DEBUGOUT("ixl_if_attach_pre: end"); return (0); Index: head/sys/dev/ixl/if_ixlv.c =================================================================== --- head/sys/dev/ixl/if_ixlv.c +++ head/sys/dev/ixl/if_ixlv.c @@ -256,10 +256,10 @@ static struct if_shared_ctx ixlv_sctx_init = { .isc_magic = IFLIB_MAGIC, .isc_q_align = PAGE_SIZE,/* max(DBA_ALIGN, PAGE_SIZE) */ - .isc_tx_maxsize = IXL_TSO_SIZE, - + .isc_tx_maxsize = IXL_TSO_SIZE + sizeof(struct ether_vlan_header), .isc_tx_maxsegsize = PAGE_SIZE, - + .isc_tso_maxsize = IXL_TSO_SIZE + sizeof(struct ether_vlan_header), + .isc_tso_maxsegsize = PAGE_SIZE, // TODO: Review the rx_maxsize and rx_maxsegsize params // Where are they used in iflib? .isc_rx_maxsize = 16384, @@ -446,7 +446,7 @@ // TODO: Probably needs changing vsi->shared->isc_rss_table_size = sc->hw.func_caps.rss_table_size; scctx->isc_tx_csum_flags = CSUM_OFFLOAD; - scctx->isc_capenable = IXL_CAPS; + scctx->isc_capabilities = scctx->isc_capenable = IXL_CAPS; INIT_DBG_DEV(dev, "end"); return (0); @@ -1841,11 +1841,6 @@ INIT_DBG_DEV(dev, "begin"); - /* initialize fast path functions */ - cap = IXL_CAPS; - if_setifheaderlen(ifp, sizeof(struct ether_vlan_header)); - if_setcapabilitiesbit(ifp, cap, 0); - if_setcapenable(ifp, if_getcapabilities(ifp)); /* TODO: Remove VLAN_ENCAP_LEN? */ vsi->shared->isc_max_frame_size = ifp->if_mtu + ETHER_HDR_LEN + ETHER_CRC_LEN @@ -1855,16 +1850,6 @@ #else if_initbaudrate(ifp, IF_Gbps(40)); #endif - - /* - ** Don't turn this on by default, if vlans are - ** created on another pseudo device (eg. lagg) - ** then vlan events are not passed thru, breaking - ** operation, but with HW FILTER off it works. If - ** using vlans directly on the ixl driver you can - ** enable this and get full hardware tag filtering. - */ - if_setcapabilitiesbit(ifp, IFCAP_VLAN_HWFILTER, 0); /* Media types based on reported link speed over AdminQ */ ifmedia_add(&sc->media, IFM_ETHER | IFM_100_TX, 0, NULL); Index: head/sys/dev/ixl/ixl_pf_main.c =================================================================== --- head/sys/dev/ixl/ixl_pf_main.c +++ head/sys/dev/ixl/ixl_pf_main.c @@ -1026,29 +1026,12 @@ struct i40e_aq_get_phy_abilities_resp abilities; enum i40e_status_code aq_error = 0; - uint64_t cap; - INIT_DBG_DEV(dev, "begin"); - /* initialize fast path functions */ - cap = IXL_CAPS; - if_setifheaderlen(ifp, sizeof(struct ether_vlan_header)); - if_setcapabilitiesbit(ifp, cap, 0); - if_setcapenable(ifp, if_getcapabilities(ifp)); /* TODO: Remove VLAN_ENCAP_LEN? */ vsi->shared->isc_max_frame_size = ifp->if_mtu + ETHER_HDR_LEN + ETHER_CRC_LEN + ETHER_VLAN_ENCAP_LEN; - - /* - ** Don't turn this on by default, if vlans are - ** created on another pseudo device (eg. lagg) - ** then vlan events are not passed thru, breaking - ** operation, but with HW FILTER off it works. If - ** using vlans directly on the ixl driver you can - ** enable this and get full hardware tag filtering. - */ - if_setcapabilitiesbit(ifp, IFCAP_VLAN_HWFILTER, 0); aq_error = i40e_aq_get_phy_capabilities(hw, FALSE, TRUE, &abilities, NULL); Index: head/sys/net/iflib.h =================================================================== --- head/sys/net/iflib.h +++ head/sys/net/iflib.h @@ -45,14 +45,7 @@ */ typedef uint16_t qidx_t; #define QIDX_INVALID 0xFFFF -/* - * Most cards can handle much larger TSO requests - * but the FreeBSD TCP stack will break on larger - * values - */ -#define FREEBSD_TSO_SIZE_MAX 65518 - struct iflib_ctx; typedef struct iflib_ctx *if_ctx_t; struct if_shared_ctx; @@ -216,6 +209,7 @@ int isc_tx_tso_size_max; int isc_tx_tso_segsize_max; int isc_tx_csum_flags; + int isc_capabilities; int isc_capenable; int isc_rss_table_size; int isc_rss_table_mask; @@ -242,6 +236,8 @@ bus_size_t isc_q_align; bus_size_t isc_tx_maxsize; bus_size_t isc_tx_maxsegsize; + bus_size_t isc_tso_maxsize; + bus_size_t isc_tso_maxsegsize; bus_size_t isc_rx_maxsize; bus_size_t isc_rx_maxsegsize; int isc_rx_nsegments; Index: head/sys/net/iflib.c =================================================================== --- head/sys/net/iflib.c +++ head/sys/net/iflib.c @@ -1574,14 +1574,22 @@ if_shared_ctx_t sctx = ctx->ifc_sctx; if_softc_ctx_t scctx = &ctx->ifc_softc_ctx; device_t dev = ctx->ifc_dev; + bus_size_t tsomaxsize; int err, nsegments, ntsosegments; nsegments = scctx->isc_tx_nsegments; ntsosegments = scctx->isc_tx_tso_segments_max; + tsomaxsize = scctx->isc_tx_tso_size_max; + if (if_getcapabilities(ctx->ifc_ifp) & IFCAP_VLAN_MTU) + tsomaxsize += sizeof(struct ether_vlan_header); MPASS(scctx->isc_ntxd[0] > 0); MPASS(scctx->isc_ntxd[txq->ift_br_offset] > 0); MPASS(nsegments > 0); - MPASS(ntsosegments > 0); + if (if_getcapabilities(ctx->ifc_ifp) & IFCAP_TSO) { + MPASS(ntsosegments > 0); + MPASS(sctx->isc_tso_maxsize >= tsomaxsize); + } + /* * Setup DMA descriptor areas. */ @@ -1602,14 +1610,15 @@ (uintmax_t)sctx->isc_tx_maxsize, nsegments, (uintmax_t)sctx->isc_tx_maxsegsize); goto fail; } - if ((err = bus_dma_tag_create(bus_get_dma_tag(dev), + if ((if_getcapabilities(ctx->ifc_ifp) & IFCAP_TSO) & + (err = bus_dma_tag_create(bus_get_dma_tag(dev), 1, 0, /* alignment, bounds */ BUS_SPACE_MAXADDR, /* lowaddr */ BUS_SPACE_MAXADDR, /* highaddr */ NULL, NULL, /* filter, filterarg */ - scctx->isc_tx_tso_size_max, /* maxsize */ + tsomaxsize, /* maxsize */ ntsosegments, /* nsegments */ - scctx->isc_tx_tso_segsize_max, /* maxsegsize */ + sctx->isc_tso_maxsegsize,/* maxsegsize */ 0, /* flags */ NULL, /* lockfunc */ NULL, /* lockfuncarg */ @@ -3279,6 +3288,8 @@ if (m_head->m_pkthdr.csum_flags & CSUM_TSO) { desc_tag = txq->ift_tso_desc_tag; max_segs = scctx->isc_tx_tso_segments_max; + MPASS(desc_tag != NULL); + MPASS(max_segs > 0); } else { desc_tag = txq->ift_desc_tag; max_segs = scctx->isc_tx_nsegments; @@ -4379,12 +4390,12 @@ ctx->ifc_txrx = *scctx->isc_txrx; #ifdef INVARIANTS - MPASS(scctx->isc_capenable); - if (scctx->isc_capenable & IFCAP_TXCSUM) + MPASS(scctx->isc_capabilities); + if (scctx->isc_capabilities & IFCAP_TXCSUM) MPASS(scctx->isc_tx_csum_flags); #endif - if_setcapabilities(ifp, scctx->isc_capenable | IFCAP_HWSTATS); + if_setcapabilities(ifp, scctx->isc_capabilities | IFCAP_HWSTATS); if_setcapenable(ifp, scctx->isc_capenable | IFCAP_HWSTATS); if (scctx->isc_ntxqsets == 0 || (scctx->isc_ntxqsets_max && scctx->isc_ntxqsets_max < scctx->isc_ntxqsets)) @@ -4432,16 +4443,25 @@ scctx->isc_tx_tso_segments_max = max(1, scctx->isc_ntxd[main_txq] / MAX_SINGLE_PACKET_FRACTION); - /* - * Protect the stack against modern hardware - */ - if (scctx->isc_tx_tso_size_max > FREEBSD_TSO_SIZE_MAX) - scctx->isc_tx_tso_size_max = FREEBSD_TSO_SIZE_MAX; - /* TSO parameters - dig these out of the data sheet - simply correspond to tag setup */ - ifp->if_hw_tsomaxsegcount = scctx->isc_tx_tso_segments_max; - ifp->if_hw_tsomax = scctx->isc_tx_tso_size_max; - ifp->if_hw_tsomaxsegsize = scctx->isc_tx_tso_segsize_max; + if (if_getcapabilities(ifp) & IFCAP_TSO) { + /* + * The stack can't handle a TSO size larger than IP_MAXPACKET, + * but some MACs do. + */ + if_sethwtsomax(ifp, min(scctx->isc_tx_tso_size_max, + IP_MAXPACKET)); + /* + * Take maximum number of m_pullup(9)'s in iflib_parse_header() + * into account. In the worst case, each of these calls will + * add another mbuf and, thus, the requirement for another DMA + * segment. So for best performance, it doesn't make sense to + * advertize a maximum of TSO segments that typically will + * require defragmentation in iflib_encap(). + */ + if_sethwtsomaxsegcount(ifp, scctx->isc_tx_tso_segments_max - 3); + if_sethwtsomaxsegsize(ifp, scctx->isc_tx_tso_segsize_max); + } if (scctx->isc_rss_table_size == 0) scctx->isc_rss_table_size = 64; scctx->isc_rss_table_mask = scctx->isc_rss_table_size-1; @@ -4512,11 +4532,22 @@ goto fail_intr_free; } } + ether_ifattach(ctx->ifc_ifp, ctx->ifc_mac); + if ((err = IFDI_ATTACH_POST(ctx)) != 0) { device_printf(dev, "IFDI_ATTACH_POST failed %d\n", err); goto fail_detach; } + + /* + * Tell the upper layer(s) if IFCAP_VLAN_MTU is supported. + * This must appear after the call to ether_ifattach() because + * ether_ifattach() sets if_hdrlen to the default value. + */ + if (if_getcapabilities(ifp) & IFCAP_VLAN_MTU) + if_setifheaderlen(ifp, sizeof(struct ether_vlan_header)); + if ((err = iflib_netmap_attach(ctx))) { device_printf(ctx->ifc_dev, "netmap attach failed: %d\n", err); goto fail_detach; @@ -4599,12 +4630,12 @@ ifmedia_set(&ctx->ifc_media, IFM_ETHER | IFM_AUTO); #ifdef INVARIANTS - MPASS(scctx->isc_capenable); - if (scctx->isc_capenable & IFCAP_TXCSUM) + MPASS(scctx->isc_capabilities); + if (scctx->isc_capabilities & IFCAP_TXCSUM) MPASS(scctx->isc_tx_csum_flags); #endif - if_setcapabilities(ifp, scctx->isc_capenable | IFCAP_HWSTATS | IFCAP_LINKSTATE); + if_setcapabilities(ifp, scctx->isc_capabilities | IFCAP_HWSTATS | IFCAP_LINKSTATE); if_setcapenable(ifp, scctx->isc_capenable | IFCAP_HWSTATS | IFCAP_LINKSTATE); ifp->if_flags |= IFF_NOGROUP; @@ -4617,6 +4648,15 @@ } *ctxp = ctx; + /* + * Tell the upper layer(s) if IFCAP_VLAN_MTU is supported. + * This must appear after the call to ether_ifattach() because + * ether_ifattach() sets if_hdrlen to the default value. + */ + if (if_getcapabilities(ifp) & IFCAP_VLAN_MTU) + if_setifheaderlen(ifp, + sizeof(struct ether_vlan_header)); + if_setgetcounterfn(ctx->ifc_ifp, iflib_if_get_counter); iflib_add_device_sysctl_post(ctx); ctx->ifc_flags |= IFC_INIT_DONE; @@ -4662,16 +4702,25 @@ scctx->isc_tx_tso_segments_max = max(1, scctx->isc_ntxd[main_txq] / MAX_SINGLE_PACKET_FRACTION); - /* - * Protect the stack against modern hardware - */ - if (scctx->isc_tx_tso_size_max > FREEBSD_TSO_SIZE_MAX) - scctx->isc_tx_tso_size_max = FREEBSD_TSO_SIZE_MAX; - /* TSO parameters - dig these out of the data sheet - simply correspond to tag setup */ - ifp->if_hw_tsomaxsegcount = scctx->isc_tx_tso_segments_max; - ifp->if_hw_tsomax = scctx->isc_tx_tso_size_max; - ifp->if_hw_tsomaxsegsize = scctx->isc_tx_tso_segsize_max; + if (if_getcapabilities(ifp) & IFCAP_TSO) { + /* + * The stack can't handle a TSO size larger than IP_MAXPACKET, + * but some MACs do. + */ + if_sethwtsomax(ifp, min(scctx->isc_tx_tso_size_max, + IP_MAXPACKET)); + /* + * Take maximum number of m_pullup(9)'s in iflib_parse_header() + * into account. In the worst case, each of these calls will + * add another mbuf and, thus, the requirement for another DMA + * segment. So for best performance, it doesn't make sense to + * advertize a maximum of TSO segments that typically will + * require defragmentation in iflib_encap(). + */ + if_sethwtsomaxsegcount(ifp, scctx->isc_tx_tso_segments_max - 3); + if_sethwtsomaxsegsize(ifp, scctx->isc_tx_tso_segsize_max); + } if (scctx->isc_rss_table_size == 0) scctx->isc_rss_table_size = 64; scctx->isc_rss_table_mask = scctx->isc_rss_table_size-1; @@ -4693,6 +4742,7 @@ device_printf(dev, "qset structure setup failed %d\n", err); goto fail_queues; } + /* * XXX What if anything do we want to do about interrupts? */ @@ -4701,6 +4751,15 @@ device_printf(dev, "IFDI_ATTACH_POST failed %d\n", err); goto fail_detach; } + + /* + * Tell the upper layer(s) if IFCAP_VLAN_MTU is supported. + * This must appear after the call to ether_ifattach() because + * ether_ifattach() sets if_hdrlen to the default value. + */ + if (if_getcapabilities(ifp) & IFCAP_VLAN_MTU) + if_setifheaderlen(ifp, sizeof(struct ether_vlan_header)); + /* XXX handle more than one queue */ for (i = 0; i < scctx->isc_nrxqsets; i++) IFDI_RX_CLSET(ctx, 0, i, ctx->ifc_rxqs[i].ifr_fl[0].ifl_sds.ifsd_cl); Index: head/sys/sys/param.h =================================================================== --- head/sys/sys/param.h +++ head/sys/sys/param.h @@ -60,7 +60,7 @@ * in the range 5 to 9. */ #undef __FreeBSD_version -#define __FreeBSD_version 1200072 /* Master, propagated to newvers */ +#define __FreeBSD_version 1200073 /* Master, propagated to newvers */ /* * __FreeBSD_kernel__ indicates that this system uses the kernel of FreeBSD,