lists.openwall.net   lists  /  announce  owl-users  owl-dev  john-users  john-dev  passwdqc-users  yescrypt  popa3d-users  /  oss-security  kernel-hardening  musl  sabotage  tlsify  passwords  /  crypt-dev  xvendor  /  Bugtraq  Full-Disclosure  linux-kernel  linux-netdev  linux-ext4  linux-hardening  linux-cve-announce  PHC 
Open Source and information security mailing list archives
 
Hash Suite: Windows password security audit tool. GUI, reports in PDF.
[<prev] [next>] [<thread-prev] [thread-next>] [day] [month] [year] [list]
Message-ID: <20061213145818.6223ffbb@dxpl.pdx.osdl.net>
Date:	Wed, 13 Dec 2006 14:58:18 -0800
From:	Stephen Hemminger <shemminger@...l.org>
To:	Tino Keitel <tino.keitel@...ei.de>
Cc:	netdev@...r.kernel.org
Subject: Re: wake on LAN with sky2

On Tue, 12 Dec 2006 21:27:20 +0100
Tino Keitel <tino.keitel@...ei.de> wrote:

> Hi folks,
> 
> I just tried the sk98lin driver version 8.41.2.3 and was happy that it
> seems to support wake on LAN with the Marvell 88E8053 PCIe chip.
> However, after resume from suspend to RAM, the machine hangs. As it
> doesn't hang with sky2, it looks like this particular driver breaks
> suspend to RAM. ($%&?#!!!)



> A quick look into sk98lin_suspend() shows that there is not much stuff
> in there. Am I right that I just have to port that stuff to sky2? The
> affected file skge.c is licenced under the GPL v2 or later.
> 
> Regards,
> Tino
> -


I was working on Wol for sky2, and got part way, but discovered that on my
test machine there were worse problems. The current code in the power management
resume runs the ACPI finish routine after the device resume. The ACPI finish
routine calls the BIOS, the BIOS then breaks MSI support.

The fix for that will be to reorder the PM resume code, but doing it right
means making the process thaw code SMP safe....  There are some patches
slowly working through the PM tree to fix this..

Anyway, this is as far as I got.

---
 drivers/net/sky2.c |   92 +++++++++++++++++++++++++++++++++++++++++++++++++++--
 drivers/net/sky2.h |   19 ++++------
 2 files changed, 96 insertions(+), 15 deletions(-)

--- sky2.orig/drivers/net/sky2.c	2006-11-09 14:47:59.000000000 -0800
+++ sky2/drivers/net/sky2.c	2006-11-09 14:51:21.000000000 -0800
@@ -539,16 +539,21 @@
 
 static void sky2_phy_power(struct sky2_hw *hw, unsigned port, int onoff)
 {
+	struct sky2_port *sky2 = netdev_priv(hw->dev[port]);
 	u32 reg1;
 	static const u32 phy_power[]
 		= { PCI_Y2_PHY1_POWD, PCI_Y2_PHY2_POWD };
 
+	reg1 = sky2_pci_read32(hw, PCI_DEV_REG1);
+	if (sky2->wol)
+		reg1 |= PCI_Y2_PIG_ENA;
+	else
+		reg1 &= ~PCI_Y2_PIG_ENA;
+
 	/* looks like this XL is back asswards .. */
 	if (hw->chip_id == CHIP_ID_YUKON_XL && hw->chip_rev > 1)
 		onoff = !onoff;
 
-	reg1 = sky2_pci_read32(hw, PCI_DEV_REG1);
-
 	if (onoff)
 		/* Turn off phy power saving */
 		reg1 &= ~phy_power[port];
@@ -568,6 +573,50 @@
 	spin_unlock_bh(&sky2->phy_lock);
 }
 
+/* Put device in state to listen for Wake On Lan */
+static void sky2_wol_init(struct sky2_port *sky2)
+{
+	struct sky2_hw *hw = sky2->hw;
+	unsigned port = sky2->port;
+	enum flow_control save_mode;
+	u16 ctrl;
+
+	sky2_phy_power(hw, port, 1);
+
+	sky2_write16(hw, B0_CTST, CS_RST_CLR);
+	sky2_write16(hw, SK_REG(port, GMAC_LINK_CTRL), GMLC_RST_CLR);
+	sky2_write8(hw, SK_REG(port, GPHY_CTRL), GPC_RST_CLR);
+	sky2_write8(hw, SK_REG(port, GMAC_CTRL), GMC_RST_CLR);
+
+	/* Force no F/C when for WOL, re-enable when link comes up */
+	save_mode = sky2->flow_mode;
+	sky2->flow_mode = FC_NONE;
+	sky2_phy_reinit(sky2);
+	sky2->flow_mode = save_mode;
+
+	gma_write16(hw, port, GM_GP_CTRL,
+		    GM_GPCR_FC_TX_DIS|GM_GPCR_TX_ENA|
+		    GM_GPCR_RX_ENA|GM_GPCR_FC_RX_DIS|
+		    GM_GPCR_DUP_FULL|GM_GPCR_AU_FCT_DIS);
+
+	sky2_write8(hw, SK_REG(port, RX_GMF_CTRL_T), GMF_RST_CLR);
+
+	sky2_write16(hw, WOL_REGS(port, WOL_CTRL_STAT), WOL_CTL_CLEAR_RESULT);
+	ctrl = 0;
+	if (sky2->wol & WAKE_PHY)
+		ctrl |= WOL_CTL_ENA_PME_ON_LINK_CHG|WOL_CTL_ENA_LINK_CHG_UNIT;
+	else
+		ctrl |= WOL_CTL_DIS_PME_ON_LINK_CHG|WOL_CTL_DIS_LINK_CHG_UNIT;
+
+	if (sky2->wol & WAKE_MAGIC)
+		ctrl |= WOL_CTL_ENA_PME_ON_MAGIC_PKT|WOL_CTL_ENA_MAGIC_PKT_UNIT;
+	else
+		ctrl |= WOL_CTL_DIS_PME_ON_MAGIC_PKT|WOL_CTL_DIS_MAGIC_PKT_UNIT;;
+
+	ctrl |= WOL_CTL_DIS_PME_ON_PATTERN|WOL_CTL_DIS_PATTERN_UNIT;
+	sky2_write16(hw, WOL_REGS(port, WOL_CTRL_STAT), ctrl);
+}
+
 static void sky2_mac_init(struct sky2_hw *hw, unsigned port)
 {
 	struct sky2_port *sky2 = netdev_priv(hw->dev[port]);
@@ -1551,6 +1600,8 @@
 	sky2->rx_ring = NULL;
 	sky2->tx_ring = NULL;
 
+	if (sky2->wol)
+		sky2_wol_init(sky2);
 	return 0;
 }
 
@@ -2525,6 +2576,35 @@
 	return 0;
 }
 
+static const u8 wol_supported = WAKE_PHY | WAKE_MAGIC;
+
+static void sky2_get_wol(struct net_device *dev, struct ethtool_wolinfo *wol)
+{
+	const struct sky2_port *sky2 = netdev_priv(dev);
+
+	wol->supported = wol_supported;
+	wol->wolopts = sky2->wol;
+}
+
+static int sky2_set_wol(struct net_device *dev, struct ethtool_wolinfo *wol)
+{
+	struct sky2_port *sky2 = netdev_priv(dev);
+	struct sky2_hw *hw = sky2->hw;
+
+	if (wol->wolopts & ~wol_supported)
+		return -EOPNOTSUPP;
+
+	sky2->wol = wol->wolopts;
+
+	if (hw->chip_id == CHIP_ID_YUKON_EC_U)
+		sky2_write32(hw, B0_CTST, sky2->wol
+			     ? Y2_HW_WOL_ON : Y2_HW_WOL_OFF);
+
+	if (!netif_running(dev))
+		sky2_wol_init(sky2);
+	return 0;
+}
+
 static u32 sky2_supported_modes(const struct sky2_hw *hw)
 {
 	if (sky2_is_copper(hw)) {
@@ -2809,6 +2889,8 @@
 		    dev->dev_addr, ETH_ALEN);
 	memcpy_toio(hw->regs + B2_MAC_2 + port * 8,
 		    dev->dev_addr, ETH_ALEN);
+	memcpy_toio(hw->regs + WOL_REGS(port, WOL_MAC_ADDR),
+		    dev->dev_addr, ETH_ALEN);
 
 	/* virtual address for data */
 	gma_set_addr(hw, port, GM_SRC_ADDR_2L, dev->dev_addr);
@@ -3162,7 +3244,9 @@
 static const struct ethtool_ops sky2_ethtool_ops = {
 	.get_settings = sky2_get_settings,
 	.set_settings = sky2_set_settings,
-	.get_drvinfo = sky2_get_drvinfo,
+	.get_drvinfo  = sky2_get_drvinfo,
+	.get_wol      = sky2_get_wol,
+	.set_wol      = sky2_set_wol,
 	.get_msglevel = sky2_get_msglevel,
 	.set_msglevel = sky2_set_msglevel,
 	.nway_reset   = sky2_nway_reset,
@@ -3264,6 +3348,8 @@
 	/* read the mac address */
 	memcpy_fromio(dev->dev_addr, hw->regs + B2_MAC_1 + port * 8, ETH_ALEN);
 	memcpy(dev->perm_addr, dev->dev_addr, dev->addr_len);
+	memcpy_toio(hw->regs + WOL_REGS(port, WOL_MAC_ADDR),
+		    dev->dev_addr, ETH_ALEN);
 
 	/* device is off until link detection */
 	netif_carrier_off(dev);
--- sky2.orig/drivers/net/sky2.h	2006-11-09 14:46:08.000000000 -0800
+++ sky2/drivers/net/sky2.h	2006-11-09 14:51:21.000000000 -0800
@@ -831,9 +831,6 @@
 	GMAC_LINK_CTRL	= 0x0f10,/* 16 bit	Link Control Reg */
 
 /* Wake-up Frame Pattern Match Control Registers (YUKON only) */
-
-	WOL_REG_OFFS	= 0x20,/* HW-Bug: Address is + 0x20 against spec. */
-
 	WOL_CTRL_STAT	= 0x0f20,/* 16 bit	WOL Control/Status Reg */
 	WOL_MATCH_CTL	= 0x0f22,/*  8 bit	WOL Match Control Reg */
 	WOL_MATCH_RES	= 0x0f23,/*  8 bit	WOL Match Result Reg */
@@ -853,11 +850,13 @@
 	WOL_PATT_CNT_0	= 0x0f38,/* 32 bit	WOL Pattern Counter 3..0 */
 	WOL_PATT_CNT_4	= 0x0f3c,/* 24 bit	WOL Pattern Counter 6..4 */
 };
+#define WOL_REGS(port, x)	(x + (port)*0x80)
 
 enum {
 	WOL_PATT_RAM_1	= 0x1000,/*  WOL Pattern RAM Link 1 */
 	WOL_PATT_RAM_2	= 0x1400,/*  WOL Pattern RAM Link 2 */
 };
+#define WOL_PATT_RAM_BASE(port)	(WOL_PATT_RAM_1 + (port)*0x400)
 
 enum {
 	BASE_GMAC_1	= 0x2800,/* GMAC 1 registers */
@@ -1712,14 +1711,17 @@
 	GM_IS_RX_COMPL	= 1<<0,	/* Frame Reception Complete */
 
 #define GMAC_DEF_MSK     GM_IS_TX_FF_UR
+};
 
 /*	GMAC_LINK_CTRL	16 bit	GMAC Link Control Reg (YUKON only) */
-						/* Bits 15.. 2:	reserved */
+enum {						/* Bits 15.. 2:	reserved */
 	GMLC_RST_CLR	= 1<<1,	/* Clear GMAC Link Reset */
 	GMLC_RST_SET	= 1<<0,	/* Set   GMAC Link Reset */
+};
 
 
 /*	WOL_CTRL_STAT	16 bit	WOL Control/Status Reg */
+enum {
 	WOL_CTL_LINK_CHG_OCC		= 1<<15,
 	WOL_CTL_MAGIC_PKT_OCC		= 1<<14,
 	WOL_CTL_PATTERN_OCC		= 1<<13,
@@ -1738,14 +1740,6 @@
 	WOL_CTL_DIS_PATTERN_UNIT	= 1<<0,
 };
 
-#define WOL_CTL_DEFAULT				\
-	(WOL_CTL_DIS_PME_ON_LINK_CHG |	\
-	WOL_CTL_DIS_PME_ON_PATTERN |	\
-	WOL_CTL_DIS_PME_ON_MAGIC_PKT |	\
-	WOL_CTL_DIS_LINK_CHG_UNIT |		\
-	WOL_CTL_DIS_PATTERN_UNIT |		\
-	WOL_CTL_DIS_MAGIC_PKT_UNIT)
-
 /*	WOL_MATCH_CTL	 8 bit	WOL Match Control Reg */
 #define WOL_CTL_PATT_ENA(x)	(1 << (x))
 
@@ -1872,6 +1866,7 @@
 	u8		     autoneg;	/* AUTONEG_ENABLE, AUTONEG_DISABLE */
 	u8		     duplex;	/* DUPLEX_HALF, DUPLEX_FULL */
 	u8		     rx_csum;
+	u8		     wol;
  	enum flow_control    flow_mode;
  	enum flow_control    flow_status;
 

-
To unsubscribe from this list: send the line "unsubscribe netdev" in
the body of a message to majordomo@...r.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html

Powered by blists - more mailing lists

Powered by Openwall GNU/*/Linux Powered by OpenVZ