Skip to content

Commit

Permalink
r8169: keep firmware in memory.
Browse files Browse the repository at this point in the history
The firmware agent is not available during resume. Loading the firmware
during open() (see eee3a96) 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>
Signed-off-by: David S. Miller <davem@davemloft.net>
  • Loading branch information
françois romieu authored and David S. Miller committed Jan 14, 2011
1 parent d0f4915 commit f1e02ed
Showing 1 changed file with 31 additions and 12 deletions.
43 changes: 31 additions & 12 deletions drivers/net/r8169.c
Original file line number Diff line number Diff line change
Expand Up @@ -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>");
Expand Down Expand Up @@ -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[] = {
Expand Down Expand Up @@ -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));

Expand Down Expand Up @@ -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");
}

Expand Down Expand Up @@ -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));

Expand Down Expand Up @@ -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");
}

Expand Down Expand Up @@ -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))
Expand Down

0 comments on commit f1e02ed

Please sign in to comment.