Commit f1e02ed1 authored by françois romieu's avatar françois romieu Committed by David S. Miller

r8169: keep firmware in memory.

The firmware agent is not available during resume. Loading the firmware
during open() (see eee3a96c) 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: default avatarFrancois Romieu <romieu@fr.zoreil.com>
Tested-by: default avatarJarek Kamiński <jarek@vilo.eu.org>
Cc: Hayes <hayeswang@realtek.com>
Cc: Ben Hutchings <benh@debian.org>
Signed-off-by: default avatarDavid S. Miller <davem@davemloft.net>
parent d0f49157
...@@ -554,6 +554,8 @@ struct rtl8169_private { ...@@ -554,6 +554,8 @@ struct rtl8169_private {
struct mii_if_info mii; struct mii_if_info mii;
struct rtl8169_counters counters; struct rtl8169_counters counters;
u32 saved_wolopts; u32 saved_wolopts;
const struct firmware *fw;
}; };
MODULE_AUTHOR("Realtek and the Linux r8169 crew <netdev@vger.kernel.org>"); 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) ...@@ -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 void rtl8169s_hw_phy_config(struct rtl8169_private *tp)
{ {
static const struct phy_reg phy_reg_init[] = { static const struct phy_reg phy_reg_init[] = {
...@@ -2139,7 +2164,6 @@ static void rtl8168d_1_hw_phy_config(struct rtl8169_private *tp) ...@@ -2139,7 +2164,6 @@ static void rtl8168d_1_hw_phy_config(struct rtl8169_private *tp)
{ 0x0d, 0xf880 } { 0x0d, 0xf880 }
}; };
void __iomem *ioaddr = tp->mmio_addr; void __iomem *ioaddr = tp->mmio_addr;
const struct firmware *fw;
rtl_writephy_batch(tp, phy_reg_init_0, ARRAY_SIZE(phy_reg_init_0)); 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) ...@@ -2203,11 +2227,8 @@ static void rtl8168d_1_hw_phy_config(struct rtl8169_private *tp)
rtl_writephy(tp, 0x1f, 0x0005); rtl_writephy(tp, 0x1f, 0x0005);
rtl_writephy(tp, 0x05, 0x001b); rtl_writephy(tp, 0x05, 0x001b);
if (rtl_readphy(tp, 0x06) == 0xbf00 && if ((rtl_readphy(tp, 0x06) != 0xbf00) ||
request_firmware(&fw, FIRMWARE_8168D_1, &tp->pci_dev->dev) == 0) { (rtl_apply_firmware(tp, FIRMWARE_8168D_1) < 0)) {
rtl_phy_write_fw(tp, fw);
release_firmware(fw);
} else {
netif_warn(tp, probe, tp->dev, "unable to apply firmware patch\n"); 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) ...@@ -2257,7 +2278,6 @@ static void rtl8168d_2_hw_phy_config(struct rtl8169_private *tp)
{ 0x0d, 0xf880 } { 0x0d, 0xf880 }
}; };
void __iomem *ioaddr = tp->mmio_addr; void __iomem *ioaddr = tp->mmio_addr;
const struct firmware *fw;
rtl_writephy_batch(tp, phy_reg_init_0, ARRAY_SIZE(phy_reg_init_0)); 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) ...@@ -2312,11 +2332,8 @@ static void rtl8168d_2_hw_phy_config(struct rtl8169_private *tp)
rtl_writephy(tp, 0x1f, 0x0005); rtl_writephy(tp, 0x1f, 0x0005);
rtl_writephy(tp, 0x05, 0x001b); rtl_writephy(tp, 0x05, 0x001b);
if (rtl_readphy(tp, 0x06) == 0xb300 && if ((rtl_readphy(tp, 0x06) != 0xb300) ||
request_firmware(&fw, FIRMWARE_8168D_2, &tp->pci_dev->dev) == 0) { (rtl_apply_firmware(tp, FIRMWARE_8168D_2) < 0)) {
rtl_phy_write_fw(tp, fw);
release_firmware(fw);
} else {
netif_warn(tp, probe, tp->dev, "unable to apply firmware patch\n"); 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) ...@@ -3200,6 +3217,8 @@ static void __devexit rtl8169_remove_one(struct pci_dev *pdev)
cancel_delayed_work_sync(&tp->task); cancel_delayed_work_sync(&tp->task);
rtl_release_firmware(tp);
unregister_netdev(dev); unregister_netdev(dev);
if (pci_dev_run_wake(pdev)) if (pci_dev_run_wake(pdev))
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment