svn commit: r321257 - head/sys/dev/e1000

Sean Bruno sbruno at FreeBSD.org
Wed Jul 19 22:41:24 UTC 2017


Author: sbruno
Date: Wed Jul 19 22:41:22 2017
New Revision: 321257
URL: https://svnweb.freebsd.org/changeset/base/321257

Log:
  Restore igb(4) code dropped during iflib conversion
   - restore newer code for vf, i350, i210, i211
   - restore dmac init code for i354 and i350
   - restore WUC/WUFC update
   - check for igb mac type before attempting trying to assert
     a media changed event.
   - handle link events for igb(4) and em(4) devices differently
     and appropriately for their respective model types.
  
  Submitted by:	Matt Macy <mmacy at mattmacy.io>
  Sponsored by:	Limelight Networks

Modified:
  head/sys/dev/e1000/if_em.c
  head/sys/dev/e1000/if_em.h

Modified: head/sys/dev/e1000/if_em.c
==============================================================================
--- head/sys/dev/e1000/if_em.c	Wed Jul 19 22:06:35 2017	(r321256)
+++ head/sys/dev/e1000/if_em.c	Wed Jul 19 22:41:22 2017	(r321257)
@@ -1025,7 +1025,7 @@ em_if_attach_post(if_ctx_t ctx)
 	/* Non-AMT based hardware can now take control from firmware */
 	if (adapter->has_manage && !adapter->has_amt)
 		em_get_hw_control(adapter);
-	
+
 	INIT_DEBUGOUT("em_if_attach_post: end");
 
 	return (error);
@@ -1691,8 +1691,9 @@ em_if_update_admin_status(if_ctx_t ctx)
 	struct e1000_hw *hw = &adapter->hw;
 	struct ifnet *ifp = iflib_get_ifp(ctx);
 	device_t dev = iflib_get_dev(ctx);
-	u32 link_check = 0;
+	u32 link_check, thstat, ctrl;
 
+	link_check = thstat = ctrl = 0;
 	/* Get the cached link value or read phy for real */
 	switch (hw->phy.media_type) {
 	case e1000_media_type_copper:
@@ -1717,11 +1718,21 @@ em_if_update_admin_status(if_ctx_t ctx)
 		e1000_check_for_link(hw);
 		link_check = adapter->hw.mac.serdes_has_link;
 		break;
-	default:
+	/* VF device is type_unknown */
 	case e1000_media_type_unknown:
+                e1000_check_for_link(hw);
+		link_check = !hw->mac.get_link_status;
+		/* Fall thru */
+	default:
 		break;
 	}
 
+	/* Check for thermal downshift or shutdown */
+	if (hw->mac.type == e1000_i350) {
+		thstat = E1000_READ_REG(hw, E1000_THSTAT);
+		ctrl = E1000_READ_REG(hw, E1000_CTRL_EXT);
+	}
+
 	/* Now check for a transition */
 	if (link_check && (adapter->link_active == 0)) {
 		e1000_get_speed_and_duplex(hw, &adapter->link_speed,
@@ -1743,6 +1754,21 @@ em_if_update_admin_status(if_ctx_t ctx)
 		adapter->link_active = 1;
 		adapter->smartspeed = 0;
 		if_setbaudrate(ifp, adapter->link_speed * 1000000);
+		if ((ctrl & E1000_CTRL_EXT_LINK_MODE_GMII) &&
+		    (thstat & E1000_THSTAT_LINK_THROTTLE))
+			device_printf(dev, "Link: thermal downshift\n");
+		/* Delay Link Up for Phy update */
+		if (((hw->mac.type == e1000_i210) ||
+		    (hw->mac.type == e1000_i211)) &&
+		    (hw->phy.id == I210_I_PHY_ID))
+			msec_delay(I210_LINK_DELAY);
+		/* Reset if the media type changed. */
+		if ((hw->dev_spec._82575.media_changed) &&
+			(adapter->hw.mac.type >= igb_mac_min)) {
+			hw->dev_spec._82575.media_changed = false;
+			adapter->flags |= IGB_MEDIA_RESET;
+			em_reset(ctx);
+		}
 		iflib_link_state_change(ctx, LINK_STATE_UP, ifp->if_baudrate);
 		printf("Link state changed to up\n");
 	} else if (!link_check && (adapter->link_active == 1)) {
@@ -2210,7 +2236,115 @@ lem_smartspeed(struct adapter *adapter)
 		adapter->smartspeed = 0;
 }
 
+/*********************************************************************
+ *
+ *  Initialize the DMA Coalescing feature
+ *
+ **********************************************************************/
+static void
+igb_init_dmac(struct adapter *adapter, u32 pba)
+{
+	device_t	dev = adapter->dev;
+	struct e1000_hw *hw = &adapter->hw;
+	u32 		dmac, reg = ~E1000_DMACR_DMAC_EN;
+	u16		hwm;
+	u16		max_frame_size;
 
+	if (hw->mac.type == e1000_i211)
+		return;
+
+	max_frame_size = adapter->shared->isc_max_frame_size;
+	if (hw->mac.type > e1000_82580) {
+
+		if (adapter->dmac == 0) { /* Disabling it */
+			E1000_WRITE_REG(hw, E1000_DMACR, reg);
+			return;
+		} else
+			device_printf(dev, "DMA Coalescing enabled\n");
+
+		/* Set starting threshold */
+		E1000_WRITE_REG(hw, E1000_DMCTXTH, 0);
+
+		hwm = 64 * pba - max_frame_size / 16;
+		if (hwm < 64 * (pba - 6))
+			hwm = 64 * (pba - 6);
+		reg = E1000_READ_REG(hw, E1000_FCRTC);
+		reg &= ~E1000_FCRTC_RTH_COAL_MASK;
+		reg |= ((hwm << E1000_FCRTC_RTH_COAL_SHIFT)
+		    & E1000_FCRTC_RTH_COAL_MASK);
+		E1000_WRITE_REG(hw, E1000_FCRTC, reg);
+
+
+		dmac = pba - max_frame_size / 512;
+		if (dmac < pba - 10)
+			dmac = pba - 10;
+		reg = E1000_READ_REG(hw, E1000_DMACR);
+		reg &= ~E1000_DMACR_DMACTHR_MASK;
+		reg = ((dmac << E1000_DMACR_DMACTHR_SHIFT)
+		    & E1000_DMACR_DMACTHR_MASK);
+
+		/* transition to L0x or L1 if available..*/
+		reg |= (E1000_DMACR_DMAC_EN | E1000_DMACR_DMAC_LX_MASK);
+
+		/* Check if status is 2.5Gb backplane connection
+		* before configuration of watchdog timer, which is
+		* in msec values in 12.8usec intervals
+		* watchdog timer= msec values in 32usec intervals
+		* for non 2.5Gb connection
+		*/
+		if (hw->mac.type == e1000_i354) {
+			int status = E1000_READ_REG(hw, E1000_STATUS);
+			if ((status & E1000_STATUS_2P5_SKU) &&
+			    (!(status & E1000_STATUS_2P5_SKU_OVER)))
+				reg |= ((adapter->dmac * 5) >> 6);
+			else
+				reg |= (adapter->dmac >> 5);
+		} else {
+			reg |= (adapter->dmac >> 5);
+		}
+
+		E1000_WRITE_REG(hw, E1000_DMACR, reg);
+
+		E1000_WRITE_REG(hw, E1000_DMCRTRH, 0);
+
+		/* Set the interval before transition */
+		reg = E1000_READ_REG(hw, E1000_DMCTLX);
+		if (hw->mac.type == e1000_i350)
+			reg |= IGB_DMCTLX_DCFLUSH_DIS;
+		/*
+		** in 2.5Gb connection, TTLX unit is 0.4 usec
+		** which is 0x4*2 = 0xA. But delay is still 4 usec
+		*/
+		if (hw->mac.type == e1000_i354) {
+			int status = E1000_READ_REG(hw, E1000_STATUS);
+			if ((status & E1000_STATUS_2P5_SKU) &&
+			    (!(status & E1000_STATUS_2P5_SKU_OVER)))
+				reg |= 0xA;
+			else
+				reg |= 0x4;
+		} else {
+			reg |= 0x4;
+		}
+
+		E1000_WRITE_REG(hw, E1000_DMCTLX, reg);
+
+		/* free space in tx packet buffer to wake from DMA coal */
+		E1000_WRITE_REG(hw, E1000_DMCTXTH, (IGB_TXPBSIZE -
+		    (2 * max_frame_size)) >> 6);
+
+		/* make low power state decision controlled by DMA coal */
+		reg = E1000_READ_REG(hw, E1000_PCIEMISC);
+		reg &= ~E1000_PCIEMISC_LX_DECISION;
+		E1000_WRITE_REG(hw, E1000_PCIEMISC, reg);
+
+	} else if (hw->mac.type == e1000_82580) {
+		u32 reg = E1000_READ_REG(hw, E1000_PCIEMISC);
+		E1000_WRITE_REG(hw, E1000_PCIEMISC,
+		    reg & ~E1000_PCIEMISC_LX_DECISION);
+		E1000_WRITE_REG(hw, E1000_DMACR, 0);
+	}
+}
+
 static void
 em_reset(if_ctx_t ctx)
 {
@@ -2222,6 +2356,8 @@ em_reset(if_ctx_t ctx)
 	u32 pba;
 
 	INIT_DEBUGOUT("em_reset: begin");
+	/* Let the firmware know the OS is in control */
+	em_get_hw_control(adapter);
 
 	/* Set up smart power down as default off on newer adapters. */
 	if (!em_smart_pwr_down && (hw->mac.type == e1000_82571 ||
@@ -2417,13 +2553,24 @@ em_reset(if_ctx_t ctx)
 
 	/* Issue a global reset */
 	e1000_reset_hw(hw);
-	E1000_WRITE_REG(hw, E1000_WUFC, 0);
-	em_disable_aspm(adapter);
+	if (adapter->hw.mac.type >= igb_mac_min) {
+		E1000_WRITE_REG(hw, E1000_WUC, 0);
+	} else {
+		E1000_WRITE_REG(hw, E1000_WUFC, 0);
+		em_disable_aspm(adapter);
+	}
+	if (adapter->flags & IGB_MEDIA_RESET) {
+		e1000_setup_init_funcs(hw, TRUE);
+		e1000_get_bus_info(hw);
+		adapter->flags &= ~IGB_MEDIA_RESET;
+	}
 	/* and a re-init */
 	if (e1000_init_hw(hw) < 0) {
 		device_printf(dev, "Hardware Initialization Failed\n");
 		return;
 	}
+	if (adapter->hw.mac.type >= igb_mac_min)
+		igb_init_dmac(adapter, pba);
 
 	E1000_WRITE_REG(hw, E1000_VET, ETHERTYPE_VLAN);
 	e1000_get_phy_info(hw);
@@ -3307,6 +3454,9 @@ em_get_hw_control(struct adapter *adapter)
 {
 	u32 ctrl_ext, swsm;
 
+	if (adapter->vf_ifp)
+		return;
+
 	if (adapter->hw.mac.type == e1000_82573) {
 		swsm = E1000_READ_REG(&adapter->hw, E1000_SWSM);
 		E1000_WRITE_REG(&adapter->hw, E1000_SWSM,
@@ -3317,7 +3467,6 @@ em_get_hw_control(struct adapter *adapter)
 	ctrl_ext = E1000_READ_REG(&adapter->hw, E1000_CTRL_EXT);
 	E1000_WRITE_REG(&adapter->hw, E1000_CTRL_EXT,
 	    ctrl_ext | E1000_CTRL_EXT_DRV_LOAD);
-	return;
 }
 
 /*

Modified: head/sys/dev/e1000/if_em.h
==============================================================================
--- head/sys/dev/e1000/if_em.h	Wed Jul 19 22:06:35 2017	(r321256)
+++ head/sys/dev/e1000/if_em.h	Wed Jul 19 22:41:22 2017	(r321257)
@@ -235,6 +235,27 @@
 #define EM_EEPROM_APME			0x400;
 #define EM_82544_APME			0x0004;
 
+
+/* Support AutoMediaDetect for Marvell M88 PHY in i354 */
+#define IGB_MEDIA_RESET			(1 << 0)
+
+/* Define the starting Interrupt rate per Queue */
+#define IGB_INTS_PER_SEC        8000
+#define IGB_DEFAULT_ITR         ((1000000/IGB_INTS_PER_SEC) << 2)
+
+#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
+#define IGB_DMCTLX_DCFLUSH_DIS	0x80000000  /* Disable DMA Coalesce Flush */
+
 /*
  * Driver state logic for the detection of a hung state
  * in hardware.  Set TX_HUNG whenever a TX packet is used
@@ -455,11 +476,11 @@ struct adapter {
 	struct ifmedia	*media;
 	int		msix;
 	int		if_flags;
-	int		min_frame_size;
 	int		em_insert_vlan_header;
 	u32		ims;
 	bool		in_detach;
 
+	u32		flags;
 	/* Task for FAST handling */
 	struct grouptask link_task;
 
@@ -514,6 +535,7 @@ struct adapter {
 	unsigned long	watchdog_events;
 
 	struct e1000_hw_stats stats;
+	u16		vf_ifp;
 };
 
 /********************************************************************************


More information about the svn-src-all mailing list