public inbox for netdev@vger.kernel.org
 help / color / mirror / Atom feed
* [PATCH] r8169: keep firmware in memory.
@ 2011-01-13 23:07 Francois Romieu
  2011-01-14  5:50 ` David Miller
  2011-01-14  6:52 ` Michael Tokarev
  0 siblings, 2 replies; 7+ messages in thread
From: Francois Romieu @ 2011-01-13 23:07 UTC (permalink / raw)
  To: David Miller
  Cc: netdev, Jarek Kamiński, Hayes, Ben Hutchings, Linus Torvalds

The firmware agent is not available during resume. Loading the firmware
during open() (see eee3a96c6368f47df8df5bd4ed1843600652b337) is not
enough.

close() is run during resume through rtl8169_reset_task(), whence the
mildly natural release of firmware in the driver removal method instead.

It will help with http://bugs.debian.org/609538. It will not avoid
the 60 seconds delay when:
- there is no firmware
- the driver is loaded and the device is not up before a suspend/resume

Signed-off-by: Francois Romieu <romieu@fr.zoreil.com>
Tested-by: Jarek Kamiński <jarek@vilo.eu.org>
Cc: Hayes <hayeswang@realtek.com>
Cc: Ben Hutchings <benh@debian.org>
---
 drivers/net/r8169.c |   43 +++++++++++++++++++++++++++++++------------
 1 files changed, 31 insertions(+), 12 deletions(-)

diff --git a/drivers/net/r8169.c b/drivers/net/r8169.c
index bb8645a..bde7d61 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>");
@@ -1766,6 +1768,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[] = {
@@ -2139,7 +2164,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));
 
@@ -2203,11 +2227,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");
 	}
 
@@ -2257,7 +2278,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));
 
@@ -2312,11 +2332,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");
 	}
 
@@ -3200,6 +3217,8 @@ static void __devexit rtl8169_remove_one(struct pci_dev *pdev)
 
 	cancel_delayed_work_sync(&tp->task);
 
+	rtl_release_firmware(tp);
+
 	unregister_netdev(dev);
 
 	if (pci_dev_run_wake(pdev))
-- 
1.7.3.4


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

* Re: [PATCH] r8169: keep firmware in memory.
  2011-01-13 23:07 [PATCH] r8169: keep firmware in memory Francois Romieu
@ 2011-01-14  5:50 ` David Miller
  2011-01-14  6:52 ` Michael Tokarev
  1 sibling, 0 replies; 7+ messages in thread
From: David Miller @ 2011-01-14  5:50 UTC (permalink / raw)
  To: romieu; +Cc: netdev, jarek, hayeswang, benh, torvalds

From: Francois Romieu <romieu@fr.zoreil.com>
Date: Fri, 14 Jan 2011 00:07:53 +0100

> The firmware agent is not available during resume. Loading the firmware
> during open() (see eee3a96c6368f47df8df5bd4ed1843600652b337) is not
> enough.
> 
> close() is run during resume through rtl8169_reset_task(), whence the
> mildly natural release of firmware in the driver removal method instead.
> 
> It will help with http://bugs.debian.org/609538. It will not avoid
> the 60 seconds delay when:
> - there is no firmware
> - the driver is loaded and the device is not up before a suspend/resume
> 
> Signed-off-by: Francois Romieu <romieu@fr.zoreil.com>
> Tested-by: Jarek Kamiński <jarek@vilo.eu.org>
> Cc: Hayes <hayeswang@realtek.com>
> Cc: Ben Hutchings <benh@debian.org>

Applied.

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

* Re: [PATCH] r8169: keep firmware in memory.
  2011-01-13 23:07 [PATCH] r8169: keep firmware in memory Francois Romieu
  2011-01-14  5:50 ` David Miller
@ 2011-01-14  6:52 ` Michael Tokarev
  2011-01-14 16:05   ` Linus Torvalds
  1 sibling, 1 reply; 7+ messages in thread
From: Michael Tokarev @ 2011-01-14  6:52 UTC (permalink / raw)
  To: Francois Romieu
  Cc: David Miller, netdev, Jarek Kamiński, Hayes, Ben Hutchings,
	Linus Torvalds

14.01.2011 02:07, Francois Romieu wrote:
> The firmware agent is not available during resume. Loading the firmware
> during open() (see eee3a96c6368f47df8df5bd4ed1843600652b337) is not
> enough.
> 
> close() is run during resume through rtl8169_reset_task(), whence the
> mildly natural release of firmware in the driver removal method instead.
> 
> It will help with http://bugs.debian.org/609538. It will not avoid
> the 60 seconds delay when:
> - there is no firmware
> - the driver is loaded and the device is not up before a suspend/resume

Given all this I think this is somewhat clumsy still.  How
does other NIC drivers handles this situation - e.g. tg3?
Maybe this needs to be a generic solution instead of per-driver?

/mjt

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

* Re: [PATCH] r8169: keep firmware in memory.
  2011-01-14  6:52 ` Michael Tokarev
@ 2011-01-14 16:05   ` Linus Torvalds
  2011-01-14 16:30     ` Ben Hutchings
  0 siblings, 1 reply; 7+ messages in thread
From: Linus Torvalds @ 2011-01-14 16:05 UTC (permalink / raw)
  To: Michael Tokarev, David Woodhouse, Johannes Berg,
	Greg Kroah-Hartman, Rafael J. Wysocki
  Cc: Francois Romieu, David Miller, netdev, Jarek Kamiński, Hayes,
	Ben Hutchings

[ background for new people in discussion: once more, a driver resume
didn't get a working firmware load. ]

On Thu, Jan 13, 2011 at 10:52 PM, Michael Tokarev <mjt@tls.msk.ru> wrote:
>
> Given all this I think this is somewhat clumsy still.  How
> does other NIC drivers handles this situation - e.g. tg3?
> Maybe this needs to be a generic solution instead of per-driver?

We've had this bug several times - and not just for network drivers
either. It's almost universal that drivers just load their firmware at
initialization, and then don't realize that they need to do it at
resume too and have no filesystems accessible. I think the firmware
access interface is partly to blame, because I suspect both the
documentation and the code (and probably any examples: as mentioned,
this is very common) tends to be about that initial one-shot "bring
the device up" rather than thinking about "oh, resume is a bootup too,
and unlike initial boot, it needs to come up in a configured state".

Maybe the firmware loader could be made more useful to automatically
handle the caching (it already knows about built-in firmware) for the
case where CONFIG_PM is enabled. So that drivers _could_ just
basically do "request_firmware()" in their resume functions, and it
would get satisfied from RAM for the re-request case.

Or maybe we could have some honking big comments, at least ;)

Added some device core/fw-class people to the discussion for comments.
Clearly the fw loading _works_, but it does end up being a common bug
that it's messed up at resume. This time it was the "oh, I moved the
firmware loading around so now it's done at a different stage", but
quite often it's literally just "oh, it never worked, I had just
forgotten about resume".

                       Linus

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

* Re: [PATCH] r8169: keep firmware in memory.
  2011-01-14 16:05   ` Linus Torvalds
@ 2011-01-14 16:30     ` Ben Hutchings
  2011-01-14 17:21       ` Linus Torvalds
  0 siblings, 1 reply; 7+ messages in thread
From: Ben Hutchings @ 2011-01-14 16:30 UTC (permalink / raw)
  To: Linus Torvalds
  Cc: Michael Tokarev, David Woodhouse, Johannes Berg,
	Greg Kroah-Hartman, Rafael J. Wysocki, Francois Romieu,
	David Miller, netdev, Jarek Kamiński, Hayes

On Fri, Jan 14, 2011 at 08:05:22AM -0800, Linus Torvalds wrote:
> [ background for new people in discussion: once more, a driver resume
> didn't get a working firmware load. ]
> 
> On Thu, Jan 13, 2011 at 10:52 PM, Michael Tokarev <mjt@tls.msk.ru> wrote:
> >
> > Given all this I think this is somewhat clumsy still.  How
> > does other NIC drivers handles this situation - e.g. tg3?
> > Maybe this needs to be a generic solution instead of per-driver?
> 
> We've had this bug several times - and not just for network drivers
> either.
[...]
> Maybe the firmware loader could be made more useful to automatically
> handle the caching (it already knows about built-in firmware) for the
> case where CONFIG_PM is enabled. So that drivers _could_ just
> basically do "request_firmware()" in their resume functions, and it
> would get satisfied from RAM for the re-request case.
[...]
 
This is something I started to implement, but never got finished.  I
don't think it can be done without an API change, though, as we need
to know when to drop firmware from the cache.  But perhaps this could
be done with a hook in the device-driver binding code.

Ben.

-- 
Ben Hutchings
We get into the habit of living before acquiring the habit of thinking.
                                                              - Albert Camus

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

* Re: [PATCH] r8169: keep firmware in memory.
  2011-01-14 16:30     ` Ben Hutchings
@ 2011-01-14 17:21       ` Linus Torvalds
  2011-01-14 21:44         ` Rafael J. Wysocki
  0 siblings, 1 reply; 7+ messages in thread
From: Linus Torvalds @ 2011-01-14 17:21 UTC (permalink / raw)
  To: Ben Hutchings
  Cc: Michael Tokarev, David Woodhouse, Johannes Berg,
	Greg Kroah-Hartman, Rafael J. Wysocki, Francois Romieu,
	David Miller, netdev, Jarek Kamiński, Hayes

On Fri, Jan 14, 2011 at 8:30 AM, Ben Hutchings <benh@debian.org> wrote:
>
> This is something I started to implement, but never got finished.  I
> don't think it can be done without an API change, though, as we need
> to know when to drop firmware from the cache.  But perhaps this could
> be done with a hook in the device-driver binding code.

Or just associate the firmware with a module?

So if the firmware gets loaded, it stays in memory until the module is unloaded?

And this all would only be the case if CONFIG_PM is set, so you'd not
waste memory unnecessarily.

                Linus

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

* Re: [PATCH] r8169: keep firmware in memory.
  2011-01-14 17:21       ` Linus Torvalds
@ 2011-01-14 21:44         ` Rafael J. Wysocki
  0 siblings, 0 replies; 7+ messages in thread
From: Rafael J. Wysocki @ 2011-01-14 21:44 UTC (permalink / raw)
  To: Linus Torvalds
  Cc: Ben Hutchings, Michael Tokarev, David Woodhouse, Johannes Berg,
	Greg Kroah-Hartman, Francois Romieu, David Miller, netdev,
	Jarek Kamiński, Hayes

On Friday, January 14, 2011, Linus Torvalds wrote:
> On Fri, Jan 14, 2011 at 8:30 AM, Ben Hutchings <benh@debian.org> wrote:
> >
> > This is something I started to implement, but never got finished.  I
> > don't think it can be done without an API change, though, as we need
> > to know when to drop firmware from the cache.  But perhaps this could
> > be done with a hook in the device-driver binding code.
> 
> Or just associate the firmware with a module?
> 
> So if the firmware gets loaded, it stays in memory until the module is unloaded?
> 
> And this all would only be the case if CONFIG_PM is set, so you'd not
> waste memory unnecessarily.

Alternatively, a suspend/hibernate notifier can be used for that I think.

They are called before the freezing and after the thawing of user space, so the
the PM_POST_SUSPEND or PM_POST_RESTORE notification can easily cause the
firmare(s) to be dropped from memory.

Thanks,
Rafael

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

end of thread, other threads:[~2011-01-14 21:44 UTC | newest]

Thread overview: 7+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2011-01-13 23:07 [PATCH] r8169: keep firmware in memory Francois Romieu
2011-01-14  5:50 ` David Miller
2011-01-14  6:52 ` Michael Tokarev
2011-01-14 16:05   ` Linus Torvalds
2011-01-14 16:30     ` Ben Hutchings
2011-01-14 17:21       ` Linus Torvalds
2011-01-14 21:44         ` Rafael J. Wysocki

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox