Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

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

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
Loading
Loading
Loading
Loading
+31 −12
Original line number Diff line number Diff line
@@ -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))