diff options
Diffstat (limited to 'freebsd/sys/dev/e1000/if_em.c')
-rw-r--r-- | freebsd/sys/dev/e1000/if_em.c | 134 |
1 files changed, 58 insertions, 76 deletions
diff --git a/freebsd/sys/dev/e1000/if_em.c b/freebsd/sys/dev/e1000/if_em.c index 72711a6e..4fe66dfc 100644 --- a/freebsd/sys/dev/e1000/if_em.c +++ b/freebsd/sys/dev/e1000/if_em.c @@ -412,7 +412,6 @@ static driver_t em_if_driver = { #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)) @@ -422,8 +421,6 @@ static driver_t em_if_driver = { #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; @@ -486,8 +483,10 @@ extern struct if_txrx lem_txrx; 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, @@ -510,12 +509,13 @@ static struct if_shared_ctx em_sctx_init = { if_shared_ctx_t em_sctx = &em_sctx_init; - static struct if_shared_ctx igb_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, @@ -699,16 +699,19 @@ em_set_num_queues(if_ctx_t ctx) 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 @@ -775,18 +778,11 @@ em_if_attach_pre(if_ctx_t ctx) /* 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; @@ -795,9 +791,12 @@ em_if_attach_pre(if_ctx_t ctx) 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_csum_flags = CSUM_TCP | CSUM_UDP | CSUM_TSO | CSUM_IP6_TCP \ - | CSUM_IP6_UDP | CSUM_IP6_TCP; + 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; if (adapter->hw.mac.type != e1000_82575) scctx->isc_tx_csum_flags |= CSUM_SCTP | CSUM_IP6_SCTP; @@ -809,26 +808,44 @@ em_if_attach_pre(if_ctx_t ctx) 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; } @@ -1009,6 +1026,11 @@ em_if_attach_pre(if_ctx_t ctx) */ 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); @@ -1702,7 +1724,6 @@ em_if_update_admin_status(if_ctx_t ctx) { struct adapter *adapter = iflib_get_softc(ctx); struct e1000_hw *hw = &adapter->hw; - struct ifnet *ifp = iflib_get_ifp(ctx); device_t dev = iflib_get_dev(ctx); u32 link_check, thstat, ctrl; @@ -1766,8 +1787,8 @@ em_if_update_admin_status(if_ctx_t ctx) "Full Duplex" : "Half Duplex")); adapter->link_active = 1; adapter->smartspeed = 0; - if_setbaudrate(ifp, adapter->link_speed * 1000000); - if ((ctrl & E1000_CTRL_EXT_LINK_MODE_GMII) && + if ((ctrl & E1000_CTRL_EXT_LINK_MODE_MASK) == + E1000_CTRL_EXT_LINK_MODE_GMII && (thstat & E1000_THSTAT_LINK_THROTTLE)) device_printf(dev, "Link: thermal downshift\n"); /* Delay Link Up for Phy update */ @@ -1782,17 +1803,15 @@ em_if_update_admin_status(if_ctx_t ctx) adapter->flags |= IGB_MEDIA_RESET; em_reset(ctx); } - iflib_link_state_change(ctx, LINK_STATE_UP, ifp->if_baudrate); + iflib_link_state_change(ctx, LINK_STATE_UP, + IF_Mbps(adapter->link_speed)); printf("Link state changed to up\n"); } else if (!link_check && (adapter->link_active == 1)) { - if_setbaudrate(ifp, 0); adapter->link_speed = 0; adapter->link_duplex = 0; - if (bootverbose) - device_printf(dev, "Link is Down\n"); adapter->link_active = 0; - iflib_link_state_change(ctx, LINK_STATE_DOWN, ifp->if_baudrate); - printf("link state changed to down\n"); + iflib_link_state_change(ctx, LINK_STATE_DOWN, 0); + printf("Link state changed to down\n"); } em_update_stats_counters(adapter); @@ -1965,7 +1984,6 @@ em_if_msix_intr_assign(if_ctx_t ctx, int msix) vector = 0; for (i = 0; i < adapter->tx_num_queues; i++, tx_que++, vector++) { - rid = vector + 1; snprintf(buf, sizeof(buf), "txq%d", i); tx_que = &adapter->tx_queues[i]; iflib_softirq_alloc_generic(ctx, @@ -2304,7 +2322,7 @@ igb_init_dmac(struct adapter *adapter, u32 pba) dmac = pba - 10; reg = E1000_READ_REG(hw, E1000_DMACR); reg &= ~E1000_DMACR_DMACTHR_MASK; - reg = ((dmac << E1000_DMACR_DMACTHR_SHIFT) + reg |= ((dmac << E1000_DMACR_DMACTHR_SHIFT) & E1000_DMACR_DMACTHR_MASK); /* transition to L0x or L1 if available..*/ @@ -2752,51 +2770,15 @@ em_setup_interface(if_ctx_t ctx) 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); - } - /* * Specify the media types supported by this adapter and register * callbacks to update media and link information |