r8169: don't request firmware when there's no userspace.

The firmware is cached during the first successfull call to open() and
released once the network device is unregistered. The driver uses the
cached firmware between open() and unregister_netdev().

So far the firmware is optional : a failure to load the firmware does
not prevent open() to success. It is thus necessary to 1) unregister
all 816x / 810[23] devices and 2) force a driver probe to issue a new
firmware load.

Signed-off-by: Francois Romieu <romieu@fr.zoreil.com>
Fixed-by: Ciprian Docan <docan@eden.rutgers.edu>
Cc: Realtek linux nic maintainers <nic_swsd@realtek.com>

+71 -28
+71 -28
drivers/net/r8169.c
··· 170 170 }; 171 171 #undef _R 172 172 173 + static const struct rtl_firmware_info { 174 + int mac_version; 175 + const char *fw_name; 176 + } rtl_firmware_infos[] = { 177 + { .mac_version = RTL_GIGA_MAC_VER_25, .fw_name = FIRMWARE_8168D_1 }, 178 + { .mac_version = RTL_GIGA_MAC_VER_26, .fw_name = FIRMWARE_8168D_2 }, 179 + { .mac_version = RTL_GIGA_MAC_VER_29, .fw_name = FIRMWARE_8105E_1 }, 180 + { .mac_version = RTL_GIGA_MAC_VER_30, .fw_name = FIRMWARE_8105E_1 } 181 + }; 182 + 173 183 enum cfg_version { 174 184 RTL_CFG_0 = 0x00, 175 185 RTL_CFG_1, ··· 575 565 u32 saved_wolopts; 576 566 577 567 const struct firmware *fw; 568 + #define RTL_FIRMWARE_UNKNOWN ERR_PTR(-EAGAIN); 578 569 }; 579 570 580 571 MODULE_AUTHOR("Realtek and the Linux r8169 crew <netdev@vger.kernel.org>"); ··· 1800 1789 1801 1790 static void rtl_release_firmware(struct rtl8169_private *tp) 1802 1791 { 1803 - release_firmware(tp->fw); 1804 - tp->fw = NULL; 1792 + if (!IS_ERR_OR_NULL(tp->fw)) 1793 + release_firmware(tp->fw); 1794 + tp->fw = RTL_FIRMWARE_UNKNOWN; 1805 1795 } 1806 1796 1807 - static int rtl_apply_firmware(struct rtl8169_private *tp, const char *fw_name) 1797 + static void rtl_apply_firmware(struct rtl8169_private *tp) 1808 1798 { 1809 - const struct firmware **fw = &tp->fw; 1810 - int rc = !*fw; 1811 - 1812 - if (rc) { 1813 - rc = request_firmware(fw, fw_name, &tp->pci_dev->dev); 1814 - if (rc < 0) 1815 - goto out; 1816 - } 1799 + const struct firmware *fw = tp->fw; 1817 1800 1818 1801 /* TODO: release firmware once rtl_phy_write_fw signals failures. */ 1819 - rtl_phy_write_fw(tp, *fw); 1820 - out: 1821 - return rc; 1802 + if (!IS_ERR_OR_NULL(fw)) 1803 + rtl_phy_write_fw(tp, fw); 1804 + } 1805 + 1806 + static void rtl_apply_firmware_cond(struct rtl8169_private *tp, u8 reg, u16 val) 1807 + { 1808 + if (rtl_readphy(tp, reg) != val) 1809 + netif_warn(tp, hw, tp->dev, "chipset not ready for firmware\n"); 1810 + else 1811 + rtl_apply_firmware(tp); 1822 1812 } 1823 1813 1824 1814 static void rtl8169s_hw_phy_config(struct rtl8169_private *tp) ··· 2258 2246 2259 2247 rtl_writephy(tp, 0x1f, 0x0005); 2260 2248 rtl_writephy(tp, 0x05, 0x001b); 2261 - if ((rtl_readphy(tp, 0x06) != 0xbf00) || 2262 - (rtl_apply_firmware(tp, FIRMWARE_8168D_1) < 0)) { 2263 - netif_warn(tp, probe, tp->dev, "unable to apply firmware patch\n"); 2264 - } 2249 + 2250 + rtl_apply_firmware_cond(tp, MII_EXPANSION, 0xbf00); 2265 2251 2266 2252 rtl_writephy(tp, 0x1f, 0x0000); 2267 2253 } ··· 2361 2351 2362 2352 rtl_writephy(tp, 0x1f, 0x0005); 2363 2353 rtl_writephy(tp, 0x05, 0x001b); 2364 - if ((rtl_readphy(tp, 0x06) != 0xb300) || 2365 - (rtl_apply_firmware(tp, FIRMWARE_8168D_2) < 0)) { 2366 - netif_warn(tp, probe, tp->dev, "unable to apply firmware patch\n"); 2367 - } 2354 + 2355 + rtl_apply_firmware_cond(tp, MII_EXPANSION, 0xb300); 2368 2356 2369 2357 rtl_writephy(tp, 0x1f, 0x0000); 2370 2358 } ··· 2482 2474 rtl_writephy(tp, 0x18, 0x0310); 2483 2475 msleep(100); 2484 2476 2485 - if (rtl_apply_firmware(tp, FIRMWARE_8105E_1) < 0) 2486 - netif_warn(tp, probe, tp->dev, "unable to apply firmware patch\n"); 2477 + rtl_apply_firmware(tp); 2487 2478 2488 2479 rtl_writephy_batch(tp, phy_reg_init, ARRAY_SIZE(phy_reg_init)); 2489 2480 } ··· 3244 3237 tp->timer.data = (unsigned long) dev; 3245 3238 tp->timer.function = rtl8169_phy_timer; 3246 3239 3240 + tp->fw = RTL_FIRMWARE_UNKNOWN; 3241 + 3247 3242 rc = register_netdev(dev); 3248 3243 if (rc < 0) 3249 3244 goto err_out_msi_4; ··· 3297 3288 3298 3289 cancel_delayed_work_sync(&tp->task); 3299 3290 3300 - rtl_release_firmware(tp); 3301 - 3302 3291 unregister_netdev(dev); 3292 + 3293 + rtl_release_firmware(tp); 3303 3294 3304 3295 if (pci_dev_run_wake(pdev)) 3305 3296 pm_runtime_get_noresume(&pdev->dev); ··· 3310 3301 rtl_disable_msi(pdev, tp); 3311 3302 rtl8169_release_board(pdev, dev, tp->mmio_addr); 3312 3303 pci_set_drvdata(pdev, NULL); 3304 + } 3305 + 3306 + static void rtl_request_firmware(struct rtl8169_private *tp) 3307 + { 3308 + int i; 3309 + 3310 + /* Return early if the firmware is already loaded / cached. */ 3311 + if (!IS_ERR(tp->fw)) 3312 + goto out; 3313 + 3314 + for (i = 0; i < ARRAY_SIZE(rtl_firmware_infos); i++) { 3315 + const struct rtl_firmware_info *info = rtl_firmware_infos + i; 3316 + 3317 + if (info->mac_version == tp->mac_version) { 3318 + const char *name = info->fw_name; 3319 + int rc; 3320 + 3321 + rc = request_firmware(&tp->fw, name, &tp->pci_dev->dev); 3322 + if (rc < 0) { 3323 + netif_warn(tp, ifup, tp->dev, "unable to load " 3324 + "firmware patch %s (%d)\n", name, rc); 3325 + goto out_disable_request_firmware; 3326 + } 3327 + goto out; 3328 + } 3329 + } 3330 + 3331 + out_disable_request_firmware: 3332 + tp->fw = NULL; 3333 + out: 3334 + return; 3313 3335 } 3314 3336 3315 3337 static int rtl8169_open(struct net_device *dev) ··· 3374 3334 3375 3335 smp_mb(); 3376 3336 3337 + rtl_request_firmware(tp); 3338 + 3377 3339 retval = request_irq(dev->irq, rtl8169_interrupt, 3378 3340 (tp->features & RTL_FEATURE_MSI) ? 0 : IRQF_SHARED, 3379 3341 dev->name, dev); 3380 3342 if (retval < 0) 3381 - goto err_release_ring_2; 3343 + goto err_release_fw_2; 3382 3344 3383 3345 napi_enable(&tp->napi); 3384 3346 ··· 3401 3359 out: 3402 3360 return retval; 3403 3361 3404 - err_release_ring_2: 3362 + err_release_fw_2: 3363 + rtl_release_firmware(tp); 3405 3364 rtl8169_rx_clear(tp); 3406 3365 err_free_rx_1: 3407 3366 dma_free_coherent(&pdev->dev, R8169_RX_RING_BYTES, tp->RxDescArray,