Skip site navigation (1)Skip section navigation (2)
Date:      Tue, 22 Jan 2008 14:16:04 +0900
From:      Pyun YongHyeon <pyunyh@gmail.com>
To:        freebsd-current@FreeBSD.org
Subject:   CFT: re(4) WOL support
Message-ID:  <20080122051604.GC10560@cdnetworks.co.kr>

next in thread | raw e-mail | index | archive | help

--cmJC7u66zC7hs+87
Content-Type: text/plain; charset=us-ascii
Content-Disposition: inline


Dear all,

Attached patch enables WOL capability on re(4). Since there are too
many variants of hardwares that uses re(4), I'd like to hear
success/failure report of the patch prior to commit. You can wake
the system in suspend state as well as power down state. Because
suspend/resume does not work on my box I don't know whether waking
up from suspend work. WOL packets can be greated with tools like
ports/net/wol.
Patch was generated against HEAD and you should have latest CURRENT
to get WOL infrasture before running the patch.

-- 
Regards,
Pyun YongHyeon

--cmJC7u66zC7hs+87
Content-Type: text/plain; charset=us-ascii
Content-Disposition: attachment; filename="re.WOL.diff"

--- sys/dev/re/if_re.c.orig	2008-01-18 10:50:49.000000000 +0900
+++ sys/dev/re/if_re.c	2008-01-22 13:49:26.000000000 +0900
@@ -280,6 +280,8 @@
 
 static void re_setmulti		(struct rl_softc *);
 static void re_reset		(struct rl_softc *);
+static void re_setwol		(struct rl_softc *);
+static void re_clrwol		(struct rl_softc *);
 
 #ifdef RE_DIAG
 static int re_diag		(struct rl_softc *);
@@ -1334,6 +1336,9 @@
 	ifp->if_capabilities |= IFCAP_VLAN_MTU | IFCAP_VLAN_HWTAGGING;
 	if (ifp->if_capabilities & IFCAP_HWCSUM)
 		ifp->if_capabilities |= IFCAP_VLAN_HWCSUM;
+	/* Enable WOL if PM is supported. */
+	if (pci_find_extcap(sc->rl_dev, PCIY_PMG, &reg) == 0)
+		ifp->if_capabilities |= IFCAP_WOL;
 	ifp->if_capenable = ifp->if_capabilities;
 #ifdef DEVICE_POLLING
 	ifp->if_capabilities |= IFCAP_POLLING;
@@ -2715,6 +2720,15 @@
 			else
 				ifp->if_hwassist &= ~CSUM_TSO;
 		}
+		if ((mask & IFCAP_WOL) != 0 &&
+		    (ifp->if_capabilities & IFCAP_WOL) != 0) {
+			if ((mask & IFCAP_WOL_UCAST) != 0)
+				ifp->if_capenable ^= IFCAP_WOL_UCAST;
+			if ((mask & IFCAP_WOL_MCAST) != 0)
+				ifp->if_capenable ^= IFCAP_WOL_MCAST;
+			if ((mask & IFCAP_WOL_MAGIC) != 0)
+				ifp->if_capenable ^= IFCAP_WOL_MAGIC;
+		}
 		if (reinit && ifp->if_drv_flags & IFF_DRV_RUNNING)
 			re_init(sc);
 		VLAN_CAPABILITIES(ifp);
@@ -2820,6 +2834,7 @@
 
 	RL_LOCK(sc);
 	re_stop(sc);
+	re_setwol(sc);
 	sc->suspended = 1;
 	RL_UNLOCK(sc);
 
@@ -2848,6 +2863,11 @@
 	if (ifp->if_flags & IFF_UP)
 		re_init_locked(sc);
 
+	/*
+	 * Clear WOL matching such that normal Rx filtering
+	 * wouldn't interfere with WOL patterns.
+	 */
+	re_clrwol(sc);
 	sc->suspended = 0;
 	RL_UNLOCK(sc);
 
@@ -2874,7 +2894,95 @@
 	 * cases.
 	 */
 	sc->rl_ifp->if_flags &= ~IFF_UP;
+	re_setwol(sc);
 	RL_UNLOCK(sc);
 
 	return (0);
 }
+
+static void
+re_setwol(sc)
+	struct rl_softc		*sc;
+{
+	struct ifnet		*ifp;
+	int			pmc;
+	uint16_t		pmstat;
+	uint8_t			v;
+
+	RL_LOCK_ASSERT(sc);
+
+	if (pci_find_extcap(sc->rl_dev, PCIY_PMG, &pmc) != 0)
+		return;
+
+	ifp = sc->rl_ifp;
+	/* Enable config register write. */
+	CSR_WRITE_1(sc, RL_EECMD, RL_EE_MODE);
+
+	/* Enable PME. */
+	v = CSR_READ_1(sc, RL_CFG1);
+	v &= ~RL_CFG1_PME;
+	if ((ifp->if_capenable & IFCAP_WOL) != 0)
+		v |= RL_CFG1_PME;
+	CSR_WRITE_1(sc, RL_CFG1, v);
+
+	v = CSR_READ_1(sc, RL_CFG3);
+	v &= ~(RL_CFG3_WOL_LINK | RL_CFG3_WOL_MAGIC);
+	if ((ifp->if_capenable & IFCAP_WOL_MAGIC) != 0)
+		v |= RL_CFG3_WOL_MAGIC;
+	CSR_WRITE_1(sc, RL_CFG3, v);
+
+	/* Config register write done. */
+	CSR_WRITE_1(sc, RL_EECMD, 0);
+
+	v = CSR_READ_1(sc, RL_CFG5);
+	v &= ~(RL_CFG5_WOL_BCAST | RL_CFG5_WOL_MCAST | RL_CFG5_WOL_UCAST);
+	v &= ~RL_CFG5_WOL_LANWAKE;
+	if ((ifp->if_capenable & IFCAP_WOL_UCAST) != 0)
+		v |= RL_CFG5_WOL_UCAST;
+	if ((ifp->if_capenable & IFCAP_WOL_MCAST) != 0)
+		v |= RL_CFG5_WOL_MCAST | RL_CFG5_WOL_BCAST;
+	if ((ifp->if_capenable & IFCAP_WOL) != 0)
+		v |= RL_CFG5_WOL_LANWAKE;
+	CSR_WRITE_1(sc, RL_CFG5, v);
+
+	/*
+	 * It seems that hardware resets its link speed to 100Mbps in
+	 * power down mode so switching to 100Mbps in driver is not
+	 * needed.
+	 */
+
+	/* Request PME if WOL is requested. */
+	pmstat = pci_read_config(sc->rl_dev, pmc + PCIR_POWER_STATUS, 2);
+	pmstat &= ~(PCIM_PSTAT_PME | PCIM_PSTAT_PMEENABLE);
+	if ((ifp->if_capenable & IFCAP_WOL) != 0)
+		pmstat |= PCIM_PSTAT_PME | PCIM_PSTAT_PMEENABLE;
+	pci_write_config(sc->rl_dev, pmc + PCIR_POWER_STATUS, pmstat, 2);
+}
+
+static void
+re_clrwol(sc)
+	struct rl_softc		*sc;
+{
+	int			pmc;
+	uint8_t			v;
+
+	RL_LOCK_ASSERT(sc);
+
+	if (pci_find_extcap(sc->rl_dev, PCIY_PMG, &pmc) != 0)
+		return;
+
+	/* Enable config register write. */
+	CSR_WRITE_1(sc, RL_EECMD, RL_EE_MODE);
+
+	v = CSR_READ_1(sc, RL_CFG3);
+	v &= ~(RL_CFG3_WOL_LINK | RL_CFG3_WOL_MAGIC);
+	CSR_WRITE_1(sc, RL_CFG3, v);
+
+	/* Config register write done. */
+	CSR_WRITE_1(sc, RL_EECMD, 0);
+
+	v = CSR_READ_1(sc, RL_CFG5);
+	v &= ~(RL_CFG5_WOL_BCAST | RL_CFG5_WOL_MCAST | RL_CFG5_WOL_UCAST);
+	v &= ~RL_CFG5_WOL_LANWAKE;
+	CSR_WRITE_1(sc, RL_CFG5, v);
+}
--- sys/pci/if_rlreg.h.orig	2008-01-15 10:10:31.000000000 +0900
+++ sys/pci/if_rlreg.h	2008-01-22 13:42:39.000000000 +0900
@@ -76,7 +76,11 @@
 #define RL_EECMD	0x0050		/* EEPROM command register */
 #define RL_CFG0		0x0051		/* config register #0 */
 #define RL_CFG1		0x0052		/* config register #1 */
-                                        /* 0053-0057 reserved */   
+#define	RL_CFG2		0x0053		/* config register #2 */
+#define	RL_CFG3		0x0054		/* config register #3 */
+#define	RL_CFG4		0x0055		/* config register #4 */
+#define	RL_CFG5		0x0056		/* config register #5 */
+					/* 0057 reserved */
 #define RL_MEDIASTAT	0x0058		/* media status register (8139) */
 					/* 0059-005A reserved */
 #define RL_MII		0x005A		/* 8129 chip only */
@@ -359,16 +363,50 @@
  * Config 1 register
  */
 #define RL_CFG1_PWRDWN		0x01
+#define RL_CFG1_PME		0x01	
 #define RL_CFG1_SLEEP		0x02
+#define RL_CFG1_VPDEN		0x02
 #define RL_CFG1_IOMAP		0x04
 #define RL_CFG1_MEMMAP		0x08
 #define RL_CFG1_RSVD		0x10
+#define	RL_CFG1_LWACT		0x10
 #define RL_CFG1_DRVLOAD		0x20
 #define RL_CFG1_LED0		0x40
 #define RL_CFG1_FULLDUPLEX	0x40	/* 8129 only */
 #define RL_CFG1_LED1		0x80
 
 /*
+ * Config 2 register
+ */
+#define	RL_CFG2_PCI33MHZ	0x00
+#define	RL_CFG2_PCI66MHZ	0x01
+#define	RL_CFG2_PCI64BIT	0x08
+#define	RL_CFG2_AUXPWR		0x10
+
+/*
+ * Config 3 register
+ */
+#define	RL_CFG3_GRANTSEL	0x80
+#define	RL_CFG3_WOL_MAGIC	0x20
+#define	RL_CFG3_WOL_LINK	0x10
+#define	RL_CFG3_FAST_B2B	0x01
+
+/*
+ * Config 4 register
+ */
+#define	RL_CFG4_LWPTN		0x04
+#define	RL_CFG4_LWPME		0x10
+
+/*
+ * Config 5 register
+ */
+#define	RL_CFG5_WOL_BCAST	0x40
+#define	RL_CFG5_WOL_MCAST	0x20
+#define	RL_CFG5_WOL_UCAST	0x10
+#define	RL_CFG5_WOL_LANWAKE	0x02
+#define	RL_CFG5_PME_STS		0x01
+
+/*
  * 8139C+ register definitions
  */
 

--cmJC7u66zC7hs+87--



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