Patchwork Bug#609538: r8169: long delay during resume

login
register
mail settings
Submitter françois romieu
Date Jan. 11, 2011, 1:25 p.m.
Message ID <20110111132524.GA2479@electric-eye.fr.zoreil.com>
Download mbox | patch
Permalink /patch/78383/
State Superseded
Delegated to: David Miller
Headers show

Comments

françois romieu - Jan. 11, 2011, 1:25 p.m.
Jarek Kamiński <jarek@vilo.eu.org> :
[...]
> The last 2.6.36 I've tried was 2.6.36-1~experimental.1, I've then
> passsed and returned to 2.6.32 for unrelated problems. I think it wasn't
> affected, but I can re-check it and/or test later 2.6.36 versions if it
> may help.

The patch below against 2.6.37-git + davem's pending fixes (see
http://marc.info/?l=linux-netdev&m=129448910825754) should help.

Can you give it a try ?

r8169: keep firmware in memory.

The firmware agent is not available during resume.

It will help with http://bugs.debian.org/609538 but it will not avoid
the 60 seconds delay when there is no firmware.

Signed-off-by: Francois Romieu <romieu@fr.zoreil.com>
Cc: Hayes <hayeswang@realtek.com>
Cc: Ben Hutchings <benh@debian.org>
---
 drivers/net/r8169.c |   43 +++++++++++++++++++++++++++++++------------
 1 files changed, 31 insertions(+), 12 deletions(-)
Jarek Kamiński - Jan. 11, 2011, 6:21 p.m.
W dniu 11.01.2011 14:25, Francois Romieu pisze:
> Jarek Kamiński <jarek@vilo.eu.org> :
> [...]
>> The last 2.6.36 I've tried was 2.6.36-1~experimental.1, I've then
>> passsed and returned to 2.6.32 for unrelated problems. I think it wasn't
>> affected, but I can re-check it and/or test later 2.6.36 versions if it
>> may help.
> 
> The patch below against 2.6.37-git + davem's pending fixes (see
> http://marc.info/?l=linux-netdev&m=129448910825754) should help.
> 
> Can you give it a try ?
> 
> r8169: keep firmware in memory.

This patch applied against current git tree fixes problem (with firmware
installed). However, cherry-picking
eee3a96c6368f47df8df5bd4ed1843600652b337 (r8169: delay phy init until
device opens.) from net-2.6.git and applying "r8169: keep firmware in
memory." still results with
#v+
Jan 11 19:05:18 rocket kernel: [  673.176439] ata1.00: configured for
UDMA/100
Jan 11 19:05:18 rocket kernel: [  731.639054] r8169 0000:13:00.0: eth0:
unable to apply firmware patch
Jan 11 19:05:18 rocket kernel: [  731.640486] PM: resume of devices
complete after 60228.033 msecs
#v-
(I don't fully understand why)

"r8169: delay phy init until device opens." alone also doesn't do the trick.

Patch

diff --git a/drivers/net/r8169.c b/drivers/net/r8169.c
index dd758cd..7e2f01c 100644
--- a/drivers/net/r8169.c
+++ b/drivers/net/r8169.c
@@ -554,6 +554,8 @@  struct rtl8169_private {
 	struct mii_if_info mii;
 	struct rtl8169_counters counters;
 	u32 saved_wolopts;
+
+	const struct firmware *fw;
 };
 
 MODULE_AUTHOR("Realtek and the Linux r8169 crew <netdev@vger.kernel.org>");
@@ -1668,6 +1670,29 @@  rtl_phy_write_fw(struct rtl8169_private *tp, const struct firmware *fw)
 	}
 }
 
+static void rtl_release_firmware(struct rtl8169_private *tp)
+{
+	release_firmware(tp->fw);
+	tp->fw = NULL;
+}
+
+static int rtl_apply_firmware(struct rtl8169_private *tp, const char *fw_name)
+{
+	const struct firmware **fw = &tp->fw;
+	int rc = !*fw;
+
+	if (rc) {
+		rc = request_firmware(fw, fw_name, &tp->pci_dev->dev);
+		if (rc < 0)
+			goto out;
+	}
+
+	/* TODO: release firmware once rtl_phy_write_fw signals failures. */
+	rtl_phy_write_fw(tp, *fw);
+out:
+	return rc;
+}
+
 static void rtl8169s_hw_phy_config(struct rtl8169_private *tp)
 {
 	static const struct phy_reg phy_reg_init[] = {
@@ -2041,7 +2066,6 @@  static void rtl8168d_1_hw_phy_config(struct rtl8169_private *tp)
 		{ 0x0d, 0xf880 }
 	};
 	void __iomem *ioaddr = tp->mmio_addr;
-	const struct firmware *fw;
 
 	rtl_writephy_batch(tp, phy_reg_init_0, ARRAY_SIZE(phy_reg_init_0));
 
@@ -2105,11 +2129,8 @@  static void rtl8168d_1_hw_phy_config(struct rtl8169_private *tp)
 
 	rtl_writephy(tp, 0x1f, 0x0005);
 	rtl_writephy(tp, 0x05, 0x001b);
-	if (rtl_readphy(tp, 0x06) == 0xbf00 &&
-	    request_firmware(&fw, FIRMWARE_8168D_1, &tp->pci_dev->dev) == 0) {
-		rtl_phy_write_fw(tp, fw);
-		release_firmware(fw);
-	} else {
+	if ((rtl_readphy(tp, 0x06) != 0xbf00) ||
+	    (rtl_apply_firmware(tp, FIRMWARE_8168D_1) < 0)) {
 		netif_warn(tp, probe, tp->dev, "unable to apply firmware patch\n");
 	}
 
@@ -2159,7 +2180,6 @@  static void rtl8168d_2_hw_phy_config(struct rtl8169_private *tp)
 		{ 0x0d, 0xf880 }
 	};
 	void __iomem *ioaddr = tp->mmio_addr;
-	const struct firmware *fw;
 
 	rtl_writephy_batch(tp, phy_reg_init_0, ARRAY_SIZE(phy_reg_init_0));
 
@@ -2214,11 +2234,8 @@  static void rtl8168d_2_hw_phy_config(struct rtl8169_private *tp)
 
 	rtl_writephy(tp, 0x1f, 0x0005);
 	rtl_writephy(tp, 0x05, 0x001b);
-	if (rtl_readphy(tp, 0x06) == 0xb300 &&
-	    request_firmware(&fw, FIRMWARE_8168D_2, &tp->pci_dev->dev) == 0) {
-		rtl_phy_write_fw(tp, fw);
-		release_firmware(fw);
-	} else {
+	if ((rtl_readphy(tp, 0x06) != 0xb300) ||
+	    (rtl_apply_firmware(tp, FIRMWARE_8168D_2) < 0)) {
 		netif_warn(tp, probe, tp->dev, "unable to apply firmware patch\n");
 	}
 
@@ -4662,6 +4679,8 @@  static int rtl8169_close(struct net_device *dev)
 	tp->TxDescArray = NULL;
 	tp->RxDescArray = NULL;
 
+	rtl_release_firmware(tp);
+
 	pm_runtime_put_sync(&pdev->dev);
 
 	return 0;