mirror of
https://github.com/edk2-porting/linux-next.git
synced 2024-11-19 16:14:13 +08:00
r8169: keep firmware in memory.
The firmware agent is not available during resume. Loading the firmware
during open() (see eee3a96c63
) 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>
This commit is contained in:
parent
d0f49157d1
commit
f1e02ed109
@ -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))
|
||||
|
Loading…
Reference in New Issue
Block a user