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