Skip site navigation (1)Skip section navigation (2)
Date:      Sun, 27 Aug 2017 21:36:44 +0000 (UTC)
From:      Marius Strobl <marius@FreeBSD.org>
To:        src-committers@freebsd.org, svn-src-all@freebsd.org, svn-src-stable@freebsd.org, svn-src-stable-11@freebsd.org
Subject:   svn commit: r322956 - stable/11/sys/dev/e1000
Message-ID:  <201708272136.v7RLai0I067004@repo.freebsd.org>

next in thread | raw e-mail | index | archive | help
Author: marius
Date: Sun Aug 27 21:36:44 2017
New Revision: 322956
URL: https://svnweb.freebsd.org/changeset/base/322956

Log:
  MFC: r312641
  
  Enable WOL features also for igb(4) class of devices.
  
  PR:		208343
  Submitted by:	Kaho Tashikazu <kaho@elam.kais.kyoto-u.ac.jp>

Modified:
  stable/11/sys/dev/e1000/if_igb.c
Directory Properties:
  stable/11/   (props changed)

Modified: stable/11/sys/dev/e1000/if_igb.c
==============================================================================
--- stable/11/sys/dev/e1000/if_igb.c	Sun Aug 27 18:18:01 2017	(r322955)
+++ stable/11/sys/dev/e1000/if_igb.c	Sun Aug 27 21:36:44 2017	(r322956)
@@ -719,12 +719,6 @@ igb_detach(device_t dev)
 	igb_release_manageability(adapter);
 	igb_release_hw_control(adapter);
 
-	if (adapter->wol) {
-		E1000_WRITE_REG(&adapter->hw, E1000_WUC, E1000_WUC_PME_EN);
-		E1000_WRITE_REG(&adapter->hw, E1000_WUFC, adapter->wol);
-		igb_enable_wakeup(dev);
-	}
-
 	/* Unregister VLAN events */
 	if (adapter->vlan_attach != NULL)
 		EVENTHANDLER_DEREGISTER(vlan_config, adapter->vlan_attach);
@@ -776,13 +770,8 @@ igb_suspend(device_t dev)
 
         igb_release_manageability(adapter);
 	igb_release_hw_control(adapter);
+	igb_enable_wakeup(dev);
 
-        if (adapter->wol) {
-                E1000_WRITE_REG(&adapter->hw, E1000_WUC, E1000_WUC_PME_EN);
-                E1000_WRITE_REG(&adapter->hw, E1000_WUFC, adapter->wol);
-                igb_enable_wakeup(dev);
-        }
-
 	IGB_CORE_UNLOCK(adapter);
 
 	return bus_generic_suspend(dev);
@@ -1231,6 +1220,14 @@ igb_ioctl(struct ifnet *ifp, u_long command, caddr_t d
 			ifp->if_capenable ^= IFCAP_LRO;
 			reinit = 1;
 		}
+		if (mask & IFCAP_WOL) {
+			if (mask & IFCAP_WOL_MAGIC)
+				ifp->if_capenable ^= IFCAP_WOL_MAGIC;
+			if (mask & IFCAP_WOL_MCAST)
+				ifp->if_capenable ^= IFCAP_WOL_MCAST;
+			if (mask & IFCAP_WOL_UCAST)
+				ifp->if_capenable ^= IFCAP_WOL_UCAST;
+		}
 		if (reinit && (ifp->if_drv_flags & IFF_DRV_RUNNING))
 			igb_init(adapter);
 		VLAN_CAPABILITIES(ifp);
@@ -2290,7 +2287,7 @@ igb_stop(void *arg)
 	}
 
 	e1000_reset_hw(&adapter->hw);
-	E1000_WRITE_REG(&adapter->hw, E1000_WUC, 0);
+	E1000_WRITE_REG(&adapter->hw, E1000_WUFC, 0);
 
 	e1000_led_off(&adapter->hw);
 	e1000_cleanup_led(&adapter->hw);
@@ -3126,7 +3123,7 @@ igb_reset(struct adapter *adapter)
 
 	/* Issue a global reset */
 	e1000_reset_hw(hw);
-	E1000_WRITE_REG(hw, E1000_WUC, 0);
+	E1000_WRITE_REG(hw, E1000_WUFC, 0);
 
 	/* Reset for AutoMediaDetect */
 	if (adapter->flags & IGB_MEDIA_RESET) {
@@ -3218,6 +3215,13 @@ igb_setup_interface(device_t dev, struct adapter *adap
 			  |  IFCAP_VLAN_MTU;
 
 	/*
+	 * Enable only WOL MAGIC by default if WOL is enabled in EEPROM.
+	 */
+	ifp->if_capabilities |= IFCAP_WOL;
+	if (adapter->wol)
+		ifp->if_capenable |= IFCAP_WOL_MAGIC;
+
+	/*
 	** 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
@@ -5498,22 +5502,61 @@ igb_is_valid_ether_addr(uint8_t *addr)
 static void
 igb_enable_wakeup(device_t dev)
 {
-	u16     cap, status;
-	u8      id;
+	struct adapter	*adapter = device_get_softc(dev);
+	struct ifnet	*ifp = adapter->ifp;
+	u32		pmc, ctrl, ctrl_ext, rctl, wuc;
+	u16		status;
 
-	/* First find the capabilities pointer*/
-	cap = pci_read_config(dev, PCIR_CAP_PTR, 2);
-	/* Read the PM Capabilities */
-	id = pci_read_config(dev, cap, 1);
-	if (id != PCIY_PMG)     /* Something wrong */
+	if (pci_find_cap(dev, PCIY_PMG, &pmc) != 0)
 		return;
-	/* OK, we have the power capabilities, so
-	   now get the status register */
-	cap += PCIR_POWER_STATUS;
-	status = pci_read_config(dev, cap, 2);
-	status |= PCIM_PSTAT_PME | PCIM_PSTAT_PMEENABLE;
-	pci_write_config(dev, cap, status, 2);
-	return;
+
+	adapter->wol = E1000_READ_REG(&adapter->hw, E1000_WUFC);
+	if (ifp->if_capenable & IFCAP_WOL_MAGIC)
+		adapter->wol |=  E1000_WUFC_MAG;
+	else
+		adapter->wol &= ~E1000_WUFC_MAG;
+
+	if (ifp->if_capenable & IFCAP_WOL_MCAST) {
+		adapter->wol |=  E1000_WUFC_MC;
+		rctl = E1000_READ_REG(&adapter->hw, E1000_RCTL);
+		rctl |= E1000_RCTL_MPE;
+		E1000_WRITE_REG(&adapter->hw, E1000_RCTL, rctl);
+	} else
+		adapter->wol &= ~E1000_WUFC_MC;
+
+	if (ifp->if_capenable & IFCAP_WOL_UCAST)
+		adapter->wol |=  E1000_WUFC_EX;
+	else
+		adapter->wol &= ~E1000_WUFC_EX;
+
+	if (!(adapter->wol & (E1000_WUFC_EX | E1000_WUFC_MAG | E1000_WUFC_MC)))
+		goto pme;
+
+	/* Advertise the wakeup capability */
+	ctrl = E1000_READ_REG(&adapter->hw, E1000_CTRL);
+	ctrl |= (E1000_CTRL_SWDPIN2 | E1000_CTRL_SWDPIN3);
+	E1000_WRITE_REG(&adapter->hw, E1000_CTRL, ctrl);
+
+	/* Keep the laser running on Fiber adapters */
+	if (adapter->hw.phy.media_type == e1000_media_type_fiber ||
+	    adapter->hw.phy.media_type == e1000_media_type_internal_serdes) {
+		ctrl_ext = E1000_READ_REG(&adapter->hw, E1000_CTRL_EXT);
+		ctrl_ext |= E1000_CTRL_EXT_SDP3_DATA;
+		E1000_WRITE_REG(&adapter->hw, E1000_CTRL_EXT, ctrl_ext);
+	}
+
+	/* Enable wakeup by the MAC */
+	wuc = E1000_READ_REG(&adapter->hw, E1000_WUC);
+	wuc |= E1000_WUC_PME_EN | E1000_WUC_APME;
+	E1000_WRITE_REG(&adapter->hw, E1000_WUC, wuc);
+	E1000_WRITE_REG(&adapter->hw, E1000_WUFC, adapter->wol);
+
+pme:
+	status = pci_read_config(dev, pmc + PCIR_POWER_STATUS, 2);
+	status &= ~(PCIM_PSTAT_PME | PCIM_PSTAT_PMEENABLE);
+	if (ifp->if_capenable & IFCAP_WOL)
+		status |= PCIM_PSTAT_PME | PCIM_PSTAT_PMEENABLE;
+	pci_write_config(dev, pmc + PCIR_POWER_STATUS, status, 2);
 }
 
 static void



Want to link to this message? Use this URL: <https://mail-archive.FreeBSD.org/cgi/mid.cgi?201708272136.v7RLai0I067004>