netdev.vger.kernel.org archive mirror
 help / color / mirror / Atom feed
* [RESEND #3/patch 2.6.26-rc6] net/enc28j60: low power mode
@ 2008-06-13  4:38 David Brownell
  2008-06-13  9:40 ` Jeff Garzik
  2008-06-18  3:26 ` Jeff Garzik
  0 siblings, 2 replies; 4+ messages in thread
From: David Brownell @ 2008-06-13  4:38 UTC (permalink / raw)
  To: netdev; +Cc: Claudio Lanconelli, lkml

Keep enc28j60 chips in low-power mode when they're not in use.
At typically 120 mA, these chips run hot even when idle; this
low power mode cuts that power usage by a factor of around 100.

This version provides a generic routine to poll a register until
its masked value equals some value ... e.g. bit set or cleared.
It's basically what the previous wait_phy_ready() did, but this
version is generalized to support the handshaking needed to
enter and exit low power mode.

Signed-off-by: David Brownell <dbrownell@users.sourceforge.net>
Signed-off-by: Claudio Lanconelli <lanconelli.claudio@eptar.com>
---
Previously sent:  18-May, 19-February; there were several
previous iterations too ...

 drivers/net/enc28j60.c |   82 ++++++++++++++++++++++++++++++++++---------------
 1 file changed, 58 insertions(+), 24 deletions(-)

--- g26.orig/drivers/net/enc28j60.c	2008-02-22 19:48:14.000000000 -0800
+++ g26/drivers/net/enc28j60.c	2008-02-22 19:48:21.000000000 -0800
@@ -400,26 +400,31 @@ enc28j60_packet_write(struct enc28j60_ne
 	mutex_unlock(&priv->lock);
 }
 
-/*
- * Wait until the PHY operation is complete.
- */
-static int wait_phy_ready(struct enc28j60_net *priv)
+static unsigned long msec20_to_jiffies;
+
+static int poll_ready(struct enc28j60_net *priv, u8 reg, u8 mask, u8 val)
 {
-	unsigned long timeout = jiffies + 20 * HZ / 1000;
-	int ret = 1;
+	unsigned long timeout = jiffies + msec20_to_jiffies;
 
 	/* 20 msec timeout read */
-	while (nolock_regb_read(priv, MISTAT) & MISTAT_BUSY) {
+	while ((nolock_regb_read(priv, reg) & mask) != val) {
 		if (time_after(jiffies, timeout)) {
 			if (netif_msg_drv(priv))
-				printk(KERN_DEBUG DRV_NAME
-					": PHY ready timeout!\n");
-			ret = 0;
-			break;
+				dev_dbg(&priv->spi->dev,
+					"reg %02x ready timeout!\n", reg);
+			return -ETIMEDOUT;
 		}
 		cpu_relax();
 	}
-	return ret;
+	return 0;
+}
+
+/*
+ * Wait until the PHY operation is complete.
+ */
+static int wait_phy_ready(struct enc28j60_net *priv)
+{
+	return poll_ready(priv, MISTAT, MISTAT_BUSY, 0) ? 0 : 1;
 }
 
 /*
@@ -594,6 +599,32 @@ static void nolock_txfifo_init(struct en
 	nolock_regw_write(priv, ETXNDL, end);
 }
 
+/*
+ * Low power mode shrinks power consumption about 100x, so we'd like
+ * the chip to be in that mode whenever it's inactive.  (However, we
+ * can't stay in lowpower mode during suspend with WOL active.)
+ */
+static void enc28j60_lowpower(struct enc28j60_net *priv, bool is_low)
+{
+	if (netif_msg_drv(priv))
+		dev_dbg(&priv->spi->dev, "%s power...\n",
+				is_low ? "low" : "high");
+
+	mutex_lock(&priv->lock);
+	if (is_low) {
+		nolock_reg_bfclr(priv, ECON1, ECON1_RXEN);
+		poll_ready(priv, ESTAT, ESTAT_RXBUSY, 0);
+		poll_ready(priv, ECON1, ECON1_TXRTS, 0);
+		/* ECON2_VRPS was set during initialization */
+		nolock_reg_bfset(priv, ECON2, ECON2_PWRSV);
+	} else {
+		nolock_reg_bfclr(priv, ECON2, ECON2_PWRSV);
+		poll_ready(priv, ESTAT, ESTAT_CLKRDY, ESTAT_CLKRDY);
+		/* caller sets ECON1_RXEN */
+	}
+	mutex_unlock(&priv->lock);
+}
+
 static int enc28j60_hw_init(struct enc28j60_net *priv)
 {
 	u8 reg;
@@ -612,8 +643,8 @@ static int enc28j60_hw_init(struct enc28
 	priv->tx_retry_count = 0;
 	priv->max_pk_counter = 0;
 	priv->rxfilter = RXFILTER_NORMAL;
-	/* enable address auto increment */
-	nolock_regb_write(priv, ECON2, ECON2_AUTOINC);
+	/* enable address auto increment and voltage regulator powersave */
+	nolock_regb_write(priv, ECON2, ECON2_AUTOINC | ECON2_VRPS);
 
 	nolock_rxfifo_init(priv, RXSTART_INIT, RXEND_INIT);
 	nolock_txfifo_init(priv, TXSTART_INIT, TXEND_INIT);
@@ -690,7 +721,7 @@ static int enc28j60_hw_init(struct enc28
 
 static void enc28j60_hw_enable(struct enc28j60_net *priv)
 {
-	/* enable interrutps */
+	/* enable interrupts */
 	if (netif_msg_hw(priv))
 		printk(KERN_DEBUG DRV_NAME ": %s() enabling interrupts.\n",
 			__FUNCTION__);
@@ -726,15 +757,12 @@ enc28j60_setlink(struct net_device *ndev
 	int ret = 0;
 
 	if (!priv->hw_enable) {
-		if (autoneg == AUTONEG_DISABLE && speed == SPEED_10) {
+		/* link is in low power mode now; duplex setting
+		 * will take effect on next enc28j60_hw_init().
+		 */
+		if (autoneg == AUTONEG_DISABLE && speed == SPEED_10)
 			priv->full_duplex = (duplex == DUPLEX_FULL);
-			if (!enc28j60_hw_init(priv)) {
-				if (netif_msg_drv(priv))
-					dev_err(&ndev->dev,
-						"hw_reset() failed\n");
-				ret = -EINVAL;
-			}
-		} else {
+		else {
 			if (netif_msg_link(priv))
 				dev_warn(&ndev->dev,
 					"unsupported link setting\n");
@@ -1307,7 +1335,8 @@ static int enc28j60_net_open(struct net_
 		}
 		return -EADDRNOTAVAIL;
 	}
-	/* Reset the hardware here */
+	/* Reset the hardware here (and take it out of low power mode) */
+	enc28j60_lowpower(priv, false);
 	enc28j60_hw_disable(priv);
 	if (!enc28j60_hw_init(priv)) {
 		if (netif_msg_ifup(priv))
@@ -1337,6 +1366,7 @@ static int enc28j60_net_close(struct net
 		printk(KERN_DEBUG DRV_NAME ": %s() enter\n", __FUNCTION__);
 
 	enc28j60_hw_disable(priv);
+	enc28j60_lowpower(priv, true);
 	netif_stop_queue(dev);
 
 	return 0;
@@ -1537,6 +1567,8 @@ static int __devinit enc28j60_probe(stru
 	dev->watchdog_timeo = TX_TIMEOUT;
 	SET_ETHTOOL_OPS(dev, &enc28j60_ethtool_ops);
 
+	enc28j60_lowpower(priv, true);
+
 	ret = register_netdev(dev);
 	if (ret) {
 		if (netif_msg_probe(priv))
@@ -1581,6 +1613,8 @@ static struct spi_driver enc28j60_driver
 
 static int __init enc28j60_init(void)
 {
+	msec20_to_jiffies = msecs_to_jiffies(20);
+
 	return spi_register_driver(&enc28j60_driver);
 }
 

^ permalink raw reply	[flat|nested] 4+ messages in thread

* Re: [RESEND #3/patch 2.6.26-rc6] net/enc28j60: low power mode
  2008-06-13  4:38 [RESEND #3/patch 2.6.26-rc6] net/enc28j60: low power mode David Brownell
@ 2008-06-13  9:40 ` Jeff Garzik
  2008-06-13 18:21   ` David Brownell
  2008-06-18  3:26 ` Jeff Garzik
  1 sibling, 1 reply; 4+ messages in thread
From: Jeff Garzik @ 2008-06-13  9:40 UTC (permalink / raw)
  To: David Brownell; +Cc: netdev, Claudio Lanconelli, lkml, Andrew Morton

David Brownell wrote:
> Keep enc28j60 chips in low-power mode when they're not in use.
> At typically 120 mA, these chips run hot even when idle; this
> low power mode cuts that power usage by a factor of around 100.
> 
> This version provides a generic routine to poll a register until
> its masked value equals some value ... e.g. bit set or cleared.
> It's basically what the previous wait_phy_ready() did, but this
> version is generalized to support the handshaking needed to
> enter and exit low power mode.
> 
> Signed-off-by: David Brownell <dbrownell@users.sourceforge.net>
> Signed-off-by: Claudio Lanconelli <lanconelli.claudio@eptar.com>
> ---
> Previously sent:  18-May, 19-February; there were several
> previous iterations too ...
> 
>  drivers/net/enc28j60.c |   82 ++++++++++++++++++++++++++++++++++---------------
>  1 file changed, 58 insertions(+), 24 deletions(-)

I've put these two into my queue, so they are definitely in process now.

For netdev patches it helps to CC me, since not every patch sent solely 
to netdev@ is a to-be-applied patch, and might be missed -- or quite 
often, assumed to be a patch that warrants discussion.

	Jeff




^ permalink raw reply	[flat|nested] 4+ messages in thread

* Re: [RESEND #3/patch 2.6.26-rc6] net/enc28j60: low power mode
  2008-06-13  9:40 ` Jeff Garzik
@ 2008-06-13 18:21   ` David Brownell
  0 siblings, 0 replies; 4+ messages in thread
From: David Brownell @ 2008-06-13 18:21 UTC (permalink / raw)
  To: Jeff Garzik; +Cc: netdev, Claudio Lanconelli, lkml, Andrew Morton

On Friday 13 June 2008, Jeff Garzik wrote:
> I've put these two into my queue, so they are definitely in process now.

Thanks..


> For netdev patches it helps to CC me, since not every patch sent solely 
> to netdev@ is a to-be-applied patch, and might be missed -- or quite 
> often, assumed to be a patch that warrants discussion.

Ah.  I was more used to the convention that all patches should go to
the relevant mailing list (or LKML), and were assumed to be ready to
merge unless they were flagged as "RFC" or the relevant maintainer(s)
issued a NAK or other negative feedback.  When there was an ack or
signoff from the driver maintainer, it was ready to go.

- Dave


^ permalink raw reply	[flat|nested] 4+ messages in thread

* Re: [RESEND #3/patch 2.6.26-rc6] net/enc28j60: low power mode
  2008-06-13  4:38 [RESEND #3/patch 2.6.26-rc6] net/enc28j60: low power mode David Brownell
  2008-06-13  9:40 ` Jeff Garzik
@ 2008-06-18  3:26 ` Jeff Garzik
  1 sibling, 0 replies; 4+ messages in thread
From: Jeff Garzik @ 2008-06-18  3:26 UTC (permalink / raw)
  To: David Brownell; +Cc: netdev, Claudio Lanconelli, lkml

David Brownell wrote:
> Keep enc28j60 chips in low-power mode when they're not in use.
> At typically 120 mA, these chips run hot even when idle; this
> low power mode cuts that power usage by a factor of around 100.
> 
> This version provides a generic routine to poll a register until
> its masked value equals some value ... e.g. bit set or cleared.
> It's basically what the previous wait_phy_ready() did, but this
> version is generalized to support the handshaking needed to
> enter and exit low power mode.
> 
> Signed-off-by: David Brownell <dbrownell@users.sourceforge.net>
> Signed-off-by: Claudio Lanconelli <lanconelli.claudio@eptar.com>
> ---
> Previously sent:  18-May, 19-February; there were several
> previous iterations too ...
> 
>  drivers/net/enc28j60.c |   82 ++++++++++++++++++++++++++++++++++---------------
>  1 file changed, 58 insertions(+), 24 deletions(-)

applied



^ permalink raw reply	[flat|nested] 4+ messages in thread

end of thread, other threads:[~2008-06-18  3:26 UTC | newest]

Thread overview: 4+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2008-06-13  4:38 [RESEND #3/patch 2.6.26-rc6] net/enc28j60: low power mode David Brownell
2008-06-13  9:40 ` Jeff Garzik
2008-06-13 18:21   ` David Brownell
2008-06-18  3:26 ` Jeff Garzik

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).