diff options
author | françois romieu <romieu@fr.zoreil.com> | 2011-01-13 08:07:53 -0500 |
---|---|---|
committer | David S. Miller <davem@davemloft.net> | 2011-01-14 00:49:57 -0500 |
commit | f1e02ed109df5f99abf942b8ccc99960cb09dd38 (patch) | |
tree | b47e1934d70c990cb7731407b4b0af1953bf5071 /drivers | |
parent | d0f49157d1ce02671a450b566a12ff19baed6c19 (diff) |
r8169: keep firmware in memory.
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 <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>
Diffstat (limited to 'drivers')
-rw-r--r-- | 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 bb8645ab247c..bde7d61f1930 100644 --- a/drivers/net/r8169.c +++ b/drivers/net/r8169.c | |||
@@ -554,6 +554,8 @@ struct rtl8169_private { | |||
554 | struct mii_if_info mii; | 554 | struct mii_if_info mii; |
555 | struct rtl8169_counters counters; | 555 | struct rtl8169_counters counters; |
556 | u32 saved_wolopts; | 556 | u32 saved_wolopts; |
557 | |||
558 | const struct firmware *fw; | ||
557 | }; | 559 | }; |
558 | 560 | ||
559 | MODULE_AUTHOR("Realtek and the Linux r8169 crew <netdev@vger.kernel.org>"); | 561 | 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 | } | 1768 | } |
1767 | } | 1769 | } |
1768 | 1770 | ||
1771 | static void rtl_release_firmware(struct rtl8169_private *tp) | ||
1772 | { | ||
1773 | release_firmware(tp->fw); | ||
1774 | tp->fw = NULL; | ||
1775 | } | ||
1776 | |||
1777 | static int rtl_apply_firmware(struct rtl8169_private *tp, const char *fw_name) | ||
1778 | { | ||
1779 | const struct firmware **fw = &tp->fw; | ||
1780 | int rc = !*fw; | ||
1781 | |||
1782 | if (rc) { | ||
1783 | rc = request_firmware(fw, fw_name, &tp->pci_dev->dev); | ||
1784 | if (rc < 0) | ||
1785 | goto out; | ||
1786 | } | ||
1787 | |||
1788 | /* TODO: release firmware once rtl_phy_write_fw signals failures. */ | ||
1789 | rtl_phy_write_fw(tp, *fw); | ||
1790 | out: | ||
1791 | return rc; | ||
1792 | } | ||
1793 | |||
1769 | static void rtl8169s_hw_phy_config(struct rtl8169_private *tp) | 1794 | static void rtl8169s_hw_phy_config(struct rtl8169_private *tp) |
1770 | { | 1795 | { |
1771 | static const struct phy_reg phy_reg_init[] = { | 1796 | static const struct phy_reg phy_reg_init[] = { |
@@ -2139,7 +2164,6 @@ static void rtl8168d_1_hw_phy_config(struct rtl8169_private *tp) | |||
2139 | { 0x0d, 0xf880 } | 2164 | { 0x0d, 0xf880 } |
2140 | }; | 2165 | }; |
2141 | void __iomem *ioaddr = tp->mmio_addr; | 2166 | void __iomem *ioaddr = tp->mmio_addr; |
2142 | const struct firmware *fw; | ||
2143 | 2167 | ||
2144 | rtl_writephy_batch(tp, phy_reg_init_0, ARRAY_SIZE(phy_reg_init_0)); | 2168 | rtl_writephy_batch(tp, phy_reg_init_0, ARRAY_SIZE(phy_reg_init_0)); |
2145 | 2169 | ||
@@ -2203,11 +2227,8 @@ static void rtl8168d_1_hw_phy_config(struct rtl8169_private *tp) | |||
2203 | 2227 | ||
2204 | rtl_writephy(tp, 0x1f, 0x0005); | 2228 | rtl_writephy(tp, 0x1f, 0x0005); |
2205 | rtl_writephy(tp, 0x05, 0x001b); | 2229 | rtl_writephy(tp, 0x05, 0x001b); |
2206 | if (rtl_readphy(tp, 0x06) == 0xbf00 && | 2230 | if ((rtl_readphy(tp, 0x06) != 0xbf00) || |
2207 | request_firmware(&fw, FIRMWARE_8168D_1, &tp->pci_dev->dev) == 0) { | 2231 | (rtl_apply_firmware(tp, FIRMWARE_8168D_1) < 0)) { |
2208 | rtl_phy_write_fw(tp, fw); | ||
2209 | release_firmware(fw); | ||
2210 | } else { | ||
2211 | netif_warn(tp, probe, tp->dev, "unable to apply firmware patch\n"); | 2232 | netif_warn(tp, probe, tp->dev, "unable to apply firmware patch\n"); |
2212 | } | 2233 | } |
2213 | 2234 | ||
@@ -2257,7 +2278,6 @@ static void rtl8168d_2_hw_phy_config(struct rtl8169_private *tp) | |||
2257 | { 0x0d, 0xf880 } | 2278 | { 0x0d, 0xf880 } |
2258 | }; | 2279 | }; |
2259 | void __iomem *ioaddr = tp->mmio_addr; | 2280 | void __iomem *ioaddr = tp->mmio_addr; |
2260 | const struct firmware *fw; | ||
2261 | 2281 | ||
2262 | rtl_writephy_batch(tp, phy_reg_init_0, ARRAY_SIZE(phy_reg_init_0)); | 2282 | rtl_writephy_batch(tp, phy_reg_init_0, ARRAY_SIZE(phy_reg_init_0)); |
2263 | 2283 | ||
@@ -2312,11 +2332,8 @@ static void rtl8168d_2_hw_phy_config(struct rtl8169_private *tp) | |||
2312 | 2332 | ||
2313 | rtl_writephy(tp, 0x1f, 0x0005); | 2333 | rtl_writephy(tp, 0x1f, 0x0005); |
2314 | rtl_writephy(tp, 0x05, 0x001b); | 2334 | rtl_writephy(tp, 0x05, 0x001b); |
2315 | if (rtl_readphy(tp, 0x06) == 0xb300 && | 2335 | if ((rtl_readphy(tp, 0x06) != 0xb300) || |
2316 | request_firmware(&fw, FIRMWARE_8168D_2, &tp->pci_dev->dev) == 0) { | 2336 | (rtl_apply_firmware(tp, FIRMWARE_8168D_2) < 0)) { |
2317 | rtl_phy_write_fw(tp, fw); | ||
2318 | release_firmware(fw); | ||
2319 | } else { | ||
2320 | netif_warn(tp, probe, tp->dev, "unable to apply firmware patch\n"); | 2337 | netif_warn(tp, probe, tp->dev, "unable to apply firmware patch\n"); |
2321 | } | 2338 | } |
2322 | 2339 | ||
@@ -3200,6 +3217,8 @@ static void __devexit rtl8169_remove_one(struct pci_dev *pdev) | |||
3200 | 3217 | ||
3201 | cancel_delayed_work_sync(&tp->task); | 3218 | cancel_delayed_work_sync(&tp->task); |
3202 | 3219 | ||
3220 | rtl_release_firmware(tp); | ||
3221 | |||
3203 | unregister_netdev(dev); | 3222 | unregister_netdev(dev); |
3204 | 3223 | ||
3205 | if (pci_dev_run_wake(pdev)) | 3224 | if (pci_dev_run_wake(pdev)) |