From 3b19bfc2e85646f9573785f1754d10d127cdc492 Mon Sep 17 00:00:00 2001 From: Ben Hutchings Date: Mon, 24 Jan 2011 01:34:50 +0000 Subject: [PATCH] r8169: Keep firmware in memory (Closes: #609538) svn path=/dists/trunk/linux-2.6/; revision=16846 --- debian/changelog | 1 + .../all/r8169-keep-firmware-in-memory.patch | 130 ++++++++++++++++++ debian/patches/series/1~experimental.2 | 1 + 3 files changed, 132 insertions(+) create mode 100644 debian/patches/bugfix/all/r8169-keep-firmware-in-memory.patch diff --git a/debian/changelog b/debian/changelog index 002fb3c8b..a31e1e910 100644 --- a/debian/changelog +++ b/debian/changelog @@ -3,6 +3,7 @@ linux-2.6 (2.6.37-1~experimental.2) UNRELEASED; urgency=low [ Ben Hutchings ] * [arm] ixp4xx: Revert build fix, now applied upstream which resulted in another build failure + * r8169: Keep firmware in memory (Closes: #609538) [ Aurelien Jarno ] * [sh4] Export cpu_core_map to fix build failure with CONFIG_SFC=m. diff --git a/debian/patches/bugfix/all/r8169-keep-firmware-in-memory.patch b/debian/patches/bugfix/all/r8169-keep-firmware-in-memory.patch new file mode 100644 index 000000000..e0f5f95d1 --- /dev/null +++ b/debian/patches/bugfix/all/r8169-keep-firmware-in-memory.patch @@ -0,0 +1,130 @@ +From 73a575b628e2ae8e0393399387445eaf1dac3fb7 Mon Sep 17 00:00:00 2001 +From: =?UTF-8?q?fran=C3=A7ois=20romieu?= +Date: Thu, 13 Jan 2011 13:07:53 +0000 +Subject: [PATCH] r8169: keep firmware in memory. +MIME-Version: 1.0 +Content-Type: text/plain; charset=UTF-8 +Content-Transfer-Encoding: 8bit + +commit f1e02ed109df5f99abf942b8ccc99960cb09dd38 upstream. + +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 +Tested-by: Jarek KamiƄski +Cc: Hayes +Cc: Ben Hutchings +Signed-off-by: David S. Miller +--- + 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 49a6db6..a5b0271 100644 +--- a/drivers/net/r8169.c ++++ b/drivers/net/r8169.c +@@ -508,6 +508,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 "); +@@ -1458,6 +1460,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(void __iomem *ioaddr) + { + static const struct phy_reg phy_reg_init[] = { +@@ -1833,7 +1858,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_phy_write(ioaddr, phy_reg_init_0, ARRAY_SIZE(phy_reg_init_0)); + +@@ -1897,11 +1921,8 @@ static void rtl8168d_1_hw_phy_config(struct rtl8169_private *tp) + + mdio_write(ioaddr, 0x1f, 0x0005); + mdio_write(ioaddr, 0x05, 0x001b); +- if (mdio_read(ioaddr, 0x06) == 0xbf00 && +- request_firmware(&fw, FIRMWARE_8168D_1, &tp->pci_dev->dev) == 0) { +- rtl_phy_write_fw(tp, fw); +- release_firmware(fw); +- } else { ++ if ((mdio_read(ioaddr, 0x06) != 0xbf00) || ++ (rtl_apply_firmware(tp, FIRMWARE_8168D_1) < 0)) { + netif_warn(tp, probe, tp->dev, "unable to apply firmware patch\n"); + } + +@@ -1951,7 +1972,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_phy_write(ioaddr, phy_reg_init_0, ARRAY_SIZE(phy_reg_init_0)); + +@@ -2006,11 +2026,8 @@ static void rtl8168d_2_hw_phy_config(struct rtl8169_private *tp) + + mdio_write(ioaddr, 0x1f, 0x0005); + mdio_write(ioaddr, 0x05, 0x001b); +- if (mdio_read(ioaddr, 0x06) == 0xb300 && +- request_firmware(&fw, FIRMWARE_8168D_2, &tp->pci_dev->dev) == 0) { +- rtl_phy_write_fw(tp, fw); +- release_firmware(fw); +- } else { ++ if ((mdio_read(ioaddr, 0x06) != 0xb300) || ++ (rtl_apply_firmware(tp, FIRMWARE_8168D_2) < 0)) { + netif_warn(tp, probe, tp->dev, "unable to apply firmware patch\n"); + } + +@@ -2706,6 +2723,8 @@ static void __devexit rtl8169_remove_one(struct pci_dev *pdev) + + flush_scheduled_work(); + ++ rtl_release_firmware(tp); ++ + unregister_netdev(dev); + + if (pci_dev_run_wake(pdev)) +-- +1.7.2.3 + diff --git a/debian/patches/series/1~experimental.2 b/debian/patches/series/1~experimental.2 index 1164c86f9..b868ea5d0 100644 --- a/debian/patches/series/1~experimental.2 +++ b/debian/patches/series/1~experimental.2 @@ -1,2 +1,3 @@ - bugfix/arm/ixp4xx-add-missing-export.patch + bugfix/sh4/sh-export-topology-core-cpumask.patch ++ bugfix/all/r8169-keep-firmware-in-memory.patch