diff options
| -rw-r--r-- | drivers/net/myri10ge/myri10ge.c | 54 |
1 files changed, 41 insertions, 13 deletions
diff --git a/drivers/net/myri10ge/myri10ge.c b/drivers/net/myri10ge/myri10ge.c index d771d1650d60..fb2c0927d3cc 100644 --- a/drivers/net/myri10ge/myri10ge.c +++ b/drivers/net/myri10ge/myri10ge.c | |||
| @@ -239,6 +239,7 @@ struct myri10ge_priv { | |||
| 239 | int watchdog_resets; | 239 | int watchdog_resets; |
| 240 | int watchdog_pause; | 240 | int watchdog_pause; |
| 241 | int pause; | 241 | int pause; |
| 242 | bool fw_name_allocated; | ||
| 242 | char *fw_name; | 243 | char *fw_name; |
| 243 | char eeprom_strings[MYRI10GE_EEPROM_STRINGS_SIZE]; | 244 | char eeprom_strings[MYRI10GE_EEPROM_STRINGS_SIZE]; |
| 244 | char *product_code_string; | 245 | char *product_code_string; |
| @@ -271,6 +272,7 @@ MODULE_FIRMWARE("myri10ge_eth_z8e.dat"); | |||
| 271 | MODULE_FIRMWARE("myri10ge_rss_ethp_z8e.dat"); | 272 | MODULE_FIRMWARE("myri10ge_rss_ethp_z8e.dat"); |
| 272 | MODULE_FIRMWARE("myri10ge_rss_eth_z8e.dat"); | 273 | MODULE_FIRMWARE("myri10ge_rss_eth_z8e.dat"); |
| 273 | 274 | ||
| 275 | /* Careful: must be accessed under kparam_block_sysfs_write */ | ||
| 274 | static char *myri10ge_fw_name = NULL; | 276 | static char *myri10ge_fw_name = NULL; |
| 275 | module_param(myri10ge_fw_name, charp, S_IRUGO | S_IWUSR); | 277 | module_param(myri10ge_fw_name, charp, S_IRUGO | S_IWUSR); |
| 276 | MODULE_PARM_DESC(myri10ge_fw_name, "Firmware image name"); | 278 | MODULE_PARM_DESC(myri10ge_fw_name, "Firmware image name"); |
| @@ -376,6 +378,14 @@ static inline void put_be32(__be32 val, __be32 __iomem * p) | |||
| 376 | 378 | ||
| 377 | static struct net_device_stats *myri10ge_get_stats(struct net_device *dev); | 379 | static struct net_device_stats *myri10ge_get_stats(struct net_device *dev); |
| 378 | 380 | ||
| 381 | static void set_fw_name(struct myri10ge_priv *mgp, char *name, bool allocated) | ||
| 382 | { | ||
| 383 | if (mgp->fw_name_allocated) | ||
| 384 | kfree(mgp->fw_name); | ||
| 385 | mgp->fw_name = name; | ||
| 386 | mgp->fw_name_allocated = allocated; | ||
| 387 | } | ||
| 388 | |||
| 379 | static int | 389 | static int |
| 380 | myri10ge_send_cmd(struct myri10ge_priv *mgp, u32 cmd, | 390 | myri10ge_send_cmd(struct myri10ge_priv *mgp, u32 cmd, |
| 381 | struct myri10ge_cmd *data, int atomic) | 391 | struct myri10ge_cmd *data, int atomic) |
| @@ -747,7 +757,7 @@ static int myri10ge_load_firmware(struct myri10ge_priv *mgp, int adopt) | |||
| 747 | dev_warn(&mgp->pdev->dev, "via hotplug\n"); | 757 | dev_warn(&mgp->pdev->dev, "via hotplug\n"); |
| 748 | } | 758 | } |
| 749 | 759 | ||
| 750 | mgp->fw_name = "adopted"; | 760 | set_fw_name(mgp, "adopted", false); |
| 751 | mgp->tx_boundary = 2048; | 761 | mgp->tx_boundary = 2048; |
| 752 | myri10ge_dummy_rdma(mgp, 1); | 762 | myri10ge_dummy_rdma(mgp, 1); |
| 753 | status = myri10ge_get_firmware_capabilities(mgp); | 763 | status = myri10ge_get_firmware_capabilities(mgp); |
| @@ -3233,7 +3243,7 @@ static void myri10ge_firmware_probe(struct myri10ge_priv *mgp) | |||
| 3233 | * load the optimized firmware (which assumes aligned PCIe | 3243 | * load the optimized firmware (which assumes aligned PCIe |
| 3234 | * completions) in order to see if it works on this host. | 3244 | * completions) in order to see if it works on this host. |
| 3235 | */ | 3245 | */ |
| 3236 | mgp->fw_name = myri10ge_fw_aligned; | 3246 | set_fw_name(mgp, myri10ge_fw_aligned, false); |
| 3237 | status = myri10ge_load_firmware(mgp, 1); | 3247 | status = myri10ge_load_firmware(mgp, 1); |
| 3238 | if (status != 0) { | 3248 | if (status != 0) { |
| 3239 | goto abort; | 3249 | goto abort; |
| @@ -3261,7 +3271,7 @@ static void myri10ge_firmware_probe(struct myri10ge_priv *mgp) | |||
| 3261 | abort: | 3271 | abort: |
| 3262 | /* fall back to using the unaligned firmware */ | 3272 | /* fall back to using the unaligned firmware */ |
| 3263 | mgp->tx_boundary = 2048; | 3273 | mgp->tx_boundary = 2048; |
| 3264 | mgp->fw_name = myri10ge_fw_unaligned; | 3274 | set_fw_name(mgp, myri10ge_fw_unaligned, false); |
| 3265 | 3275 | ||
| 3266 | } | 3276 | } |
| 3267 | 3277 | ||
| @@ -3284,7 +3294,7 @@ static void myri10ge_select_firmware(struct myri10ge_priv *mgp) | |||
| 3284 | dev_info(&mgp->pdev->dev, "PCIE x%d Link\n", | 3294 | dev_info(&mgp->pdev->dev, "PCIE x%d Link\n", |
| 3285 | link_width); | 3295 | link_width); |
| 3286 | mgp->tx_boundary = 4096; | 3296 | mgp->tx_boundary = 4096; |
| 3287 | mgp->fw_name = myri10ge_fw_aligned; | 3297 | set_fw_name(mgp, myri10ge_fw_aligned, false); |
| 3288 | } else { | 3298 | } else { |
| 3289 | myri10ge_firmware_probe(mgp); | 3299 | myri10ge_firmware_probe(mgp); |
| 3290 | } | 3300 | } |
| @@ -3293,22 +3303,29 @@ static void myri10ge_select_firmware(struct myri10ge_priv *mgp) | |||
| 3293 | dev_info(&mgp->pdev->dev, | 3303 | dev_info(&mgp->pdev->dev, |
| 3294 | "Assuming aligned completions (forced)\n"); | 3304 | "Assuming aligned completions (forced)\n"); |
| 3295 | mgp->tx_boundary = 4096; | 3305 | mgp->tx_boundary = 4096; |
| 3296 | mgp->fw_name = myri10ge_fw_aligned; | 3306 | set_fw_name(mgp, myri10ge_fw_aligned, false); |
| 3297 | } else { | 3307 | } else { |
| 3298 | dev_info(&mgp->pdev->dev, | 3308 | dev_info(&mgp->pdev->dev, |
| 3299 | "Assuming unaligned completions (forced)\n"); | 3309 | "Assuming unaligned completions (forced)\n"); |
| 3300 | mgp->tx_boundary = 2048; | 3310 | mgp->tx_boundary = 2048; |
| 3301 | mgp->fw_name = myri10ge_fw_unaligned; | 3311 | set_fw_name(mgp, myri10ge_fw_unaligned, false); |
| 3302 | } | 3312 | } |
| 3303 | } | 3313 | } |
| 3314 | |||
| 3315 | kparam_block_sysfs_write(myri10ge_fw_name); | ||
| 3304 | if (myri10ge_fw_name != NULL) { | 3316 | if (myri10ge_fw_name != NULL) { |
| 3305 | overridden = 1; | 3317 | char *fw_name = kstrdup(myri10ge_fw_name, GFP_KERNEL); |
| 3306 | mgp->fw_name = myri10ge_fw_name; | 3318 | if (fw_name) { |
| 3319 | overridden = 1; | ||
| 3320 | set_fw_name(mgp, fw_name, true); | ||
| 3321 | } | ||
| 3307 | } | 3322 | } |
| 3323 | kparam_unblock_sysfs_write(myri10ge_fw_name); | ||
| 3324 | |||
| 3308 | if (mgp->board_number < MYRI10GE_MAX_BOARDS && | 3325 | if (mgp->board_number < MYRI10GE_MAX_BOARDS && |
| 3309 | myri10ge_fw_names[mgp->board_number] != NULL && | 3326 | myri10ge_fw_names[mgp->board_number] != NULL && |
| 3310 | strlen(myri10ge_fw_names[mgp->board_number])) { | 3327 | strlen(myri10ge_fw_names[mgp->board_number])) { |
| 3311 | mgp->fw_name = myri10ge_fw_names[mgp->board_number]; | 3328 | set_fw_name(mgp, myri10ge_fw_names[mgp->board_number], false); |
| 3312 | overridden = 1; | 3329 | overridden = 1; |
| 3313 | } | 3330 | } |
| 3314 | if (overridden) | 3331 | if (overridden) |
| @@ -3660,6 +3677,7 @@ static void myri10ge_probe_slices(struct myri10ge_priv *mgp) | |||
| 3660 | struct myri10ge_cmd cmd; | 3677 | struct myri10ge_cmd cmd; |
| 3661 | struct pci_dev *pdev = mgp->pdev; | 3678 | struct pci_dev *pdev = mgp->pdev; |
| 3662 | char *old_fw; | 3679 | char *old_fw; |
| 3680 | bool old_allocated; | ||
| 3663 | int i, status, ncpus, msix_cap; | 3681 | int i, status, ncpus, msix_cap; |
| 3664 | 3682 | ||
| 3665 | mgp->num_slices = 1; | 3683 | mgp->num_slices = 1; |
| @@ -3672,17 +3690,23 @@ static void myri10ge_probe_slices(struct myri10ge_priv *mgp) | |||
| 3672 | 3690 | ||
| 3673 | /* try to load the slice aware rss firmware */ | 3691 | /* try to load the slice aware rss firmware */ |
| 3674 | old_fw = mgp->fw_name; | 3692 | old_fw = mgp->fw_name; |
| 3693 | old_allocated = mgp->fw_name_allocated; | ||
| 3694 | /* don't free old_fw if we override it. */ | ||
| 3695 | mgp->fw_name_allocated = false; | ||
| 3696 | |||
| 3675 | if (myri10ge_fw_name != NULL) { | 3697 | if (myri10ge_fw_name != NULL) { |
| 3676 | dev_info(&mgp->pdev->dev, "overriding rss firmware to %s\n", | 3698 | dev_info(&mgp->pdev->dev, "overriding rss firmware to %s\n", |
| 3677 | myri10ge_fw_name); | 3699 | myri10ge_fw_name); |
| 3678 | mgp->fw_name = myri10ge_fw_name; | 3700 | set_fw_name(mgp, myri10ge_fw_name, false); |
| 3679 | } else if (old_fw == myri10ge_fw_aligned) | 3701 | } else if (old_fw == myri10ge_fw_aligned) |
| 3680 | mgp->fw_name = myri10ge_fw_rss_aligned; | 3702 | set_fw_name(mgp, myri10ge_fw_rss_aligned, false); |
| 3681 | else | 3703 | else |
| 3682 | mgp->fw_name = myri10ge_fw_rss_unaligned; | 3704 | set_fw_name(mgp, myri10ge_fw_rss_unaligned, false); |
| 3683 | status = myri10ge_load_firmware(mgp, 0); | 3705 | status = myri10ge_load_firmware(mgp, 0); |
| 3684 | if (status != 0) { | 3706 | if (status != 0) { |
| 3685 | dev_info(&pdev->dev, "Rss firmware not found\n"); | 3707 | dev_info(&pdev->dev, "Rss firmware not found\n"); |
| 3708 | if (old_allocated) | ||
| 3709 | kfree(old_fw); | ||
| 3686 | return; | 3710 | return; |
| 3687 | } | 3711 | } |
| 3688 | 3712 | ||
| @@ -3747,6 +3771,8 @@ static void myri10ge_probe_slices(struct myri10ge_priv *mgp) | |||
| 3747 | mgp->num_slices); | 3771 | mgp->num_slices); |
| 3748 | if (status == 0) { | 3772 | if (status == 0) { |
| 3749 | pci_disable_msix(pdev); | 3773 | pci_disable_msix(pdev); |
| 3774 | if (old_allocated) | ||
| 3775 | kfree(old_fw); | ||
| 3750 | return; | 3776 | return; |
| 3751 | } | 3777 | } |
| 3752 | if (status > 0) | 3778 | if (status > 0) |
| @@ -3763,7 +3789,7 @@ disable_msix: | |||
| 3763 | 3789 | ||
| 3764 | abort_with_fw: | 3790 | abort_with_fw: |
| 3765 | mgp->num_slices = 1; | 3791 | mgp->num_slices = 1; |
| 3766 | mgp->fw_name = old_fw; | 3792 | set_fw_name(mgp, old_fw, old_allocated); |
| 3767 | myri10ge_load_firmware(mgp, 0); | 3793 | myri10ge_load_firmware(mgp, 0); |
| 3768 | } | 3794 | } |
| 3769 | 3795 | ||
| @@ -3993,6 +4019,7 @@ abort_with_enabled: | |||
| 3993 | pci_disable_device(pdev); | 4019 | pci_disable_device(pdev); |
| 3994 | 4020 | ||
| 3995 | abort_with_netdev: | 4021 | abort_with_netdev: |
| 4022 | set_fw_name(mgp, NULL, false); | ||
| 3996 | free_netdev(netdev); | 4023 | free_netdev(netdev); |
| 3997 | return status; | 4024 | return status; |
| 3998 | } | 4025 | } |
| @@ -4037,6 +4064,7 @@ static void myri10ge_remove(struct pci_dev *pdev) | |||
| 4037 | dma_free_coherent(&pdev->dev, sizeof(*mgp->cmd), | 4064 | dma_free_coherent(&pdev->dev, sizeof(*mgp->cmd), |
| 4038 | mgp->cmd, mgp->cmd_bus); | 4065 | mgp->cmd, mgp->cmd_bus); |
| 4039 | 4066 | ||
| 4067 | set_fw_name(mgp, NULL, false); | ||
| 4040 | free_netdev(netdev); | 4068 | free_netdev(netdev); |
| 4041 | pci_disable_device(pdev); | 4069 | pci_disable_device(pdev); |
| 4042 | pci_set_drvdata(pdev, NULL); | 4070 | pci_set_drvdata(pdev, NULL); |
