Loading drivers/net/r8169.c +71 −28 Original line number Diff line number Diff line Loading @@ -170,6 +170,16 @@ static const struct { }; #undef _R static const struct rtl_firmware_info { int mac_version; const char *fw_name; } rtl_firmware_infos[] = { { .mac_version = RTL_GIGA_MAC_VER_25, .fw_name = FIRMWARE_8168D_1 }, { .mac_version = RTL_GIGA_MAC_VER_26, .fw_name = FIRMWARE_8168D_2 }, { .mac_version = RTL_GIGA_MAC_VER_29, .fw_name = FIRMWARE_8105E_1 }, { .mac_version = RTL_GIGA_MAC_VER_30, .fw_name = FIRMWARE_8105E_1 } }; enum cfg_version { RTL_CFG_0 = 0x00, RTL_CFG_1, Loading Loading @@ -565,6 +575,7 @@ struct rtl8169_private { u32 saved_wolopts; const struct firmware *fw; #define RTL_FIRMWARE_UNKNOWN ERR_PTR(-EAGAIN); }; MODULE_AUTHOR("Realtek and the Linux r8169 crew <netdev@vger.kernel.org>"); Loading Loading @@ -1789,25 +1800,26 @@ rtl_phy_write_fw(struct rtl8169_private *tp, const struct firmware *fw) static void rtl_release_firmware(struct rtl8169_private *tp) { if (!IS_ERR_OR_NULL(tp->fw)) release_firmware(tp->fw); tp->fw = NULL; tp->fw = RTL_FIRMWARE_UNKNOWN; } static int rtl_apply_firmware(struct rtl8169_private *tp, const char *fw_name) static void rtl_apply_firmware(struct rtl8169_private *tp) { const struct firmware **fw = &tp->fw; int rc = !*fw; const struct firmware *fw = tp->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. */ if (!IS_ERR_OR_NULL(fw)) rtl_phy_write_fw(tp, fw); } /* TODO: release firmware once rtl_phy_write_fw signals failures. */ rtl_phy_write_fw(tp, *fw); out: return rc; static void rtl_apply_firmware_cond(struct rtl8169_private *tp, u8 reg, u16 val) { if (rtl_readphy(tp, reg) != val) netif_warn(tp, hw, tp->dev, "chipset not ready for firmware\n"); else rtl_apply_firmware(tp); } static void rtl8169s_hw_phy_config(struct rtl8169_private *tp) Loading Loading @@ -2246,10 +2258,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) || (rtl_apply_firmware(tp, FIRMWARE_8168D_1) < 0)) { netif_warn(tp, probe, tp->dev, "unable to apply firmware patch\n"); } rtl_apply_firmware_cond(tp, MII_EXPANSION, 0xbf00); rtl_writephy(tp, 0x1f, 0x0000); } Loading Loading @@ -2351,10 +2361,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) || (rtl_apply_firmware(tp, FIRMWARE_8168D_2) < 0)) { netif_warn(tp, probe, tp->dev, "unable to apply firmware patch\n"); } rtl_apply_firmware_cond(tp, MII_EXPANSION, 0xb300); rtl_writephy(tp, 0x1f, 0x0000); } Loading Loading @@ -2474,8 +2482,7 @@ static void rtl8105e_hw_phy_config(struct rtl8169_private *tp) rtl_writephy(tp, 0x18, 0x0310); msleep(100); if (rtl_apply_firmware(tp, FIRMWARE_8105E_1) < 0) netif_warn(tp, probe, tp->dev, "unable to apply firmware patch\n"); rtl_apply_firmware(tp); rtl_writephy_batch(tp, phy_reg_init, ARRAY_SIZE(phy_reg_init)); } Loading Loading @@ -3237,6 +3244,8 @@ rtl8169_init_one(struct pci_dev *pdev, const struct pci_device_id *ent) tp->timer.data = (unsigned long) dev; tp->timer.function = rtl8169_phy_timer; tp->fw = RTL_FIRMWARE_UNKNOWN; rc = register_netdev(dev); if (rc < 0) goto err_out_msi_4; Loading Loading @@ -3288,10 +3297,10 @@ static void __devexit rtl8169_remove_one(struct pci_dev *pdev) cancel_delayed_work_sync(&tp->task); rtl_release_firmware(tp); unregister_netdev(dev); rtl_release_firmware(tp); if (pci_dev_run_wake(pdev)) pm_runtime_get_noresume(&pdev->dev); Loading @@ -3303,6 +3312,37 @@ static void __devexit rtl8169_remove_one(struct pci_dev *pdev) pci_set_drvdata(pdev, NULL); } static void rtl_request_firmware(struct rtl8169_private *tp) { int i; /* Return early if the firmware is already loaded / cached. */ if (!IS_ERR(tp->fw)) goto out; for (i = 0; i < ARRAY_SIZE(rtl_firmware_infos); i++) { const struct rtl_firmware_info *info = rtl_firmware_infos + i; if (info->mac_version == tp->mac_version) { const char *name = info->fw_name; int rc; rc = request_firmware(&tp->fw, name, &tp->pci_dev->dev); if (rc < 0) { netif_warn(tp, ifup, tp->dev, "unable to load " "firmware patch %s (%d)\n", name, rc); goto out_disable_request_firmware; } goto out; } } out_disable_request_firmware: tp->fw = NULL; out: return; } static int rtl8169_open(struct net_device *dev) { struct rtl8169_private *tp = netdev_priv(dev); Loading Loading @@ -3334,11 +3374,13 @@ static int rtl8169_open(struct net_device *dev) smp_mb(); rtl_request_firmware(tp); retval = request_irq(dev->irq, rtl8169_interrupt, (tp->features & RTL_FEATURE_MSI) ? 0 : IRQF_SHARED, dev->name, dev); if (retval < 0) goto err_release_ring_2; goto err_release_fw_2; napi_enable(&tp->napi); Loading @@ -3359,7 +3401,8 @@ static int rtl8169_open(struct net_device *dev) out: return retval; err_release_ring_2: err_release_fw_2: rtl_release_firmware(tp); rtl8169_rx_clear(tp); err_free_rx_1: dma_free_coherent(&pdev->dev, R8169_RX_RING_BYTES, tp->RxDescArray, Loading Loading
drivers/net/r8169.c +71 −28 Original line number Diff line number Diff line Loading @@ -170,6 +170,16 @@ static const struct { }; #undef _R static const struct rtl_firmware_info { int mac_version; const char *fw_name; } rtl_firmware_infos[] = { { .mac_version = RTL_GIGA_MAC_VER_25, .fw_name = FIRMWARE_8168D_1 }, { .mac_version = RTL_GIGA_MAC_VER_26, .fw_name = FIRMWARE_8168D_2 }, { .mac_version = RTL_GIGA_MAC_VER_29, .fw_name = FIRMWARE_8105E_1 }, { .mac_version = RTL_GIGA_MAC_VER_30, .fw_name = FIRMWARE_8105E_1 } }; enum cfg_version { RTL_CFG_0 = 0x00, RTL_CFG_1, Loading Loading @@ -565,6 +575,7 @@ struct rtl8169_private { u32 saved_wolopts; const struct firmware *fw; #define RTL_FIRMWARE_UNKNOWN ERR_PTR(-EAGAIN); }; MODULE_AUTHOR("Realtek and the Linux r8169 crew <netdev@vger.kernel.org>"); Loading Loading @@ -1789,25 +1800,26 @@ rtl_phy_write_fw(struct rtl8169_private *tp, const struct firmware *fw) static void rtl_release_firmware(struct rtl8169_private *tp) { if (!IS_ERR_OR_NULL(tp->fw)) release_firmware(tp->fw); tp->fw = NULL; tp->fw = RTL_FIRMWARE_UNKNOWN; } static int rtl_apply_firmware(struct rtl8169_private *tp, const char *fw_name) static void rtl_apply_firmware(struct rtl8169_private *tp) { const struct firmware **fw = &tp->fw; int rc = !*fw; const struct firmware *fw = tp->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. */ if (!IS_ERR_OR_NULL(fw)) rtl_phy_write_fw(tp, fw); } /* TODO: release firmware once rtl_phy_write_fw signals failures. */ rtl_phy_write_fw(tp, *fw); out: return rc; static void rtl_apply_firmware_cond(struct rtl8169_private *tp, u8 reg, u16 val) { if (rtl_readphy(tp, reg) != val) netif_warn(tp, hw, tp->dev, "chipset not ready for firmware\n"); else rtl_apply_firmware(tp); } static void rtl8169s_hw_phy_config(struct rtl8169_private *tp) Loading Loading @@ -2246,10 +2258,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) || (rtl_apply_firmware(tp, FIRMWARE_8168D_1) < 0)) { netif_warn(tp, probe, tp->dev, "unable to apply firmware patch\n"); } rtl_apply_firmware_cond(tp, MII_EXPANSION, 0xbf00); rtl_writephy(tp, 0x1f, 0x0000); } Loading Loading @@ -2351,10 +2361,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) || (rtl_apply_firmware(tp, FIRMWARE_8168D_2) < 0)) { netif_warn(tp, probe, tp->dev, "unable to apply firmware patch\n"); } rtl_apply_firmware_cond(tp, MII_EXPANSION, 0xb300); rtl_writephy(tp, 0x1f, 0x0000); } Loading Loading @@ -2474,8 +2482,7 @@ static void rtl8105e_hw_phy_config(struct rtl8169_private *tp) rtl_writephy(tp, 0x18, 0x0310); msleep(100); if (rtl_apply_firmware(tp, FIRMWARE_8105E_1) < 0) netif_warn(tp, probe, tp->dev, "unable to apply firmware patch\n"); rtl_apply_firmware(tp); rtl_writephy_batch(tp, phy_reg_init, ARRAY_SIZE(phy_reg_init)); } Loading Loading @@ -3237,6 +3244,8 @@ rtl8169_init_one(struct pci_dev *pdev, const struct pci_device_id *ent) tp->timer.data = (unsigned long) dev; tp->timer.function = rtl8169_phy_timer; tp->fw = RTL_FIRMWARE_UNKNOWN; rc = register_netdev(dev); if (rc < 0) goto err_out_msi_4; Loading Loading @@ -3288,10 +3297,10 @@ static void __devexit rtl8169_remove_one(struct pci_dev *pdev) cancel_delayed_work_sync(&tp->task); rtl_release_firmware(tp); unregister_netdev(dev); rtl_release_firmware(tp); if (pci_dev_run_wake(pdev)) pm_runtime_get_noresume(&pdev->dev); Loading @@ -3303,6 +3312,37 @@ static void __devexit rtl8169_remove_one(struct pci_dev *pdev) pci_set_drvdata(pdev, NULL); } static void rtl_request_firmware(struct rtl8169_private *tp) { int i; /* Return early if the firmware is already loaded / cached. */ if (!IS_ERR(tp->fw)) goto out; for (i = 0; i < ARRAY_SIZE(rtl_firmware_infos); i++) { const struct rtl_firmware_info *info = rtl_firmware_infos + i; if (info->mac_version == tp->mac_version) { const char *name = info->fw_name; int rc; rc = request_firmware(&tp->fw, name, &tp->pci_dev->dev); if (rc < 0) { netif_warn(tp, ifup, tp->dev, "unable to load " "firmware patch %s (%d)\n", name, rc); goto out_disable_request_firmware; } goto out; } } out_disable_request_firmware: tp->fw = NULL; out: return; } static int rtl8169_open(struct net_device *dev) { struct rtl8169_private *tp = netdev_priv(dev); Loading Loading @@ -3334,11 +3374,13 @@ static int rtl8169_open(struct net_device *dev) smp_mb(); rtl_request_firmware(tp); retval = request_irq(dev->irq, rtl8169_interrupt, (tp->features & RTL_FEATURE_MSI) ? 0 : IRQF_SHARED, dev->name, dev); if (retval < 0) goto err_release_ring_2; goto err_release_fw_2; napi_enable(&tp->napi); Loading @@ -3359,7 +3401,8 @@ static int rtl8169_open(struct net_device *dev) out: return retval; err_release_ring_2: err_release_fw_2: rtl_release_firmware(tp); rtl8169_rx_clear(tp); err_free_rx_1: dma_free_coherent(&pdev->dev, R8169_RX_RING_BYTES, tp->RxDescArray, Loading