summaryrefslogtreecommitdiffstats
path: root/freebsd/sys/dev/e1000/if_em.c
diff options
context:
space:
mode:
Diffstat (limited to 'freebsd/sys/dev/e1000/if_em.c')
-rw-r--r--freebsd/sys/dev/e1000/if_em.c134
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