diff options
author | Wei Yang <weiyang@linux.vnet.ibm.com> | 2014-04-13 21:51:19 -0400 |
---|---|---|
committer | David S. Miller <davem@davemloft.net> | 2014-04-13 23:12:15 -0400 |
commit | befdf8978accecac2e0739e6b5075afc62db37fe (patch) | |
tree | 58591373f00b298409be793cecfdaa9c9e60a5c1 | |
parent | b04c46190219a4f845e46a459e3102137b7f6cac (diff) |
net/mlx4_core: Preserve pci_dev_data after __mlx4_remove_one()
pci_match_id() just match the static pci_device_id, which may return NULL if
someone binds the driver to a device manually using
/sys/bus/pci/drivers/.../new_id.
This patch wrap up a helper function __mlx4_remove_one() which does the tear
down function but preserve the drv_data. Functions like
mlx4_pci_err_detected() and mlx4_restart_one() will call this one with out
releasing drvdata.
Fixes: 97a5221 "net/mlx4_core: pass pci_device_id.driver_data to __mlx4_init_one during reset".
CC: Bjorn Helgaas <bhelgaas@google.com>
CC: Amir Vadai <amirv@mellanox.com>
CC: Jack Morgenstein <jackm@dev.mellanox.co.il>
CC: Or Gerlitz <ogerlitz@mellanox.com>
Signed-off-by: Wei Yang <weiyang@linux.vnet.ibm.com>
Acked-by: Jack Morgenstein <jackm@dev.mellanox.co.il>
Signed-off-by: David S. Miller <davem@davemloft.net>
-rw-r--r-- | drivers/net/ethernet/mellanox/mlx4/main.c | 172 | ||||
-rw-r--r-- | drivers/net/ethernet/mellanox/mlx4/mlx4.h | 1 |
2 files changed, 96 insertions, 77 deletions
diff --git a/drivers/net/ethernet/mellanox/mlx4/main.c b/drivers/net/ethernet/mellanox/mlx4/main.c index f0ae95f66ceb..4b86c7af2a7a 100644 --- a/drivers/net/ethernet/mellanox/mlx4/main.c +++ b/drivers/net/ethernet/mellanox/mlx4/main.c | |||
@@ -2301,13 +2301,8 @@ static int __mlx4_init_one(struct pci_dev *pdev, int pci_dev_data) | |||
2301 | /* Allow large DMA segments, up to the firmware limit of 1 GB */ | 2301 | /* Allow large DMA segments, up to the firmware limit of 1 GB */ |
2302 | dma_set_max_seg_size(&pdev->dev, 1024 * 1024 * 1024); | 2302 | dma_set_max_seg_size(&pdev->dev, 1024 * 1024 * 1024); |
2303 | 2303 | ||
2304 | priv = kzalloc(sizeof(*priv), GFP_KERNEL); | 2304 | dev = pci_get_drvdata(pdev); |
2305 | if (!priv) { | 2305 | priv = mlx4_priv(dev); |
2306 | err = -ENOMEM; | ||
2307 | goto err_release_regions; | ||
2308 | } | ||
2309 | |||
2310 | dev = &priv->dev; | ||
2311 | dev->pdev = pdev; | 2306 | dev->pdev = pdev; |
2312 | INIT_LIST_HEAD(&priv->ctx_list); | 2307 | INIT_LIST_HEAD(&priv->ctx_list); |
2313 | spin_lock_init(&priv->ctx_lock); | 2308 | spin_lock_init(&priv->ctx_lock); |
@@ -2535,8 +2530,7 @@ slave_start: | |||
2535 | mlx4_sense_init(dev); | 2530 | mlx4_sense_init(dev); |
2536 | mlx4_start_sense(dev); | 2531 | mlx4_start_sense(dev); |
2537 | 2532 | ||
2538 | priv->pci_dev_data = pci_dev_data; | 2533 | priv->removed = 0; |
2539 | pci_set_drvdata(pdev, dev); | ||
2540 | 2534 | ||
2541 | return 0; | 2535 | return 0; |
2542 | 2536 | ||
@@ -2604,85 +2598,109 @@ err_disable_pdev: | |||
2604 | 2598 | ||
2605 | static int mlx4_init_one(struct pci_dev *pdev, const struct pci_device_id *id) | 2599 | static int mlx4_init_one(struct pci_dev *pdev, const struct pci_device_id *id) |
2606 | { | 2600 | { |
2601 | struct mlx4_priv *priv; | ||
2602 | struct mlx4_dev *dev; | ||
2603 | |||
2607 | printk_once(KERN_INFO "%s", mlx4_version); | 2604 | printk_once(KERN_INFO "%s", mlx4_version); |
2608 | 2605 | ||
2606 | priv = kzalloc(sizeof(*priv), GFP_KERNEL); | ||
2607 | if (!priv) | ||
2608 | return -ENOMEM; | ||
2609 | |||
2610 | dev = &priv->dev; | ||
2611 | pci_set_drvdata(pdev, dev); | ||
2612 | priv->pci_dev_data = id->driver_data; | ||
2613 | |||
2609 | return __mlx4_init_one(pdev, id->driver_data); | 2614 | return __mlx4_init_one(pdev, id->driver_data); |
2610 | } | 2615 | } |
2611 | 2616 | ||
2612 | static void mlx4_remove_one(struct pci_dev *pdev) | 2617 | static void __mlx4_remove_one(struct pci_dev *pdev) |
2613 | { | 2618 | { |
2614 | struct mlx4_dev *dev = pci_get_drvdata(pdev); | 2619 | struct mlx4_dev *dev = pci_get_drvdata(pdev); |
2615 | struct mlx4_priv *priv = mlx4_priv(dev); | 2620 | struct mlx4_priv *priv = mlx4_priv(dev); |
2621 | int pci_dev_data; | ||
2616 | int p; | 2622 | int p; |
2617 | 2623 | ||
2618 | if (dev) { | 2624 | if (priv->removed) |
2619 | /* in SRIOV it is not allowed to unload the pf's | 2625 | return; |
2620 | * driver while there are alive vf's */ | ||
2621 | if (mlx4_is_master(dev)) { | ||
2622 | if (mlx4_how_many_lives_vf(dev)) | ||
2623 | printk(KERN_ERR "Removing PF when there are assigned VF's !!!\n"); | ||
2624 | } | ||
2625 | mlx4_stop_sense(dev); | ||
2626 | mlx4_unregister_device(dev); | ||
2627 | 2626 | ||
2628 | for (p = 1; p <= dev->caps.num_ports; p++) { | 2627 | pci_dev_data = priv->pci_dev_data; |
2629 | mlx4_cleanup_port_info(&priv->port[p]); | ||
2630 | mlx4_CLOSE_PORT(dev, p); | ||
2631 | } | ||
2632 | 2628 | ||
2633 | if (mlx4_is_master(dev)) | 2629 | /* in SRIOV it is not allowed to unload the pf's |
2634 | mlx4_free_resource_tracker(dev, | 2630 | * driver while there are alive vf's */ |
2635 | RES_TR_FREE_SLAVES_ONLY); | 2631 | if (mlx4_is_master(dev) && mlx4_how_many_lives_vf(dev)) |
2636 | 2632 | printk(KERN_ERR "Removing PF when there are assigned VF's !!!\n"); | |
2637 | mlx4_cleanup_counters_table(dev); | 2633 | mlx4_stop_sense(dev); |
2638 | mlx4_cleanup_qp_table(dev); | 2634 | mlx4_unregister_device(dev); |
2639 | mlx4_cleanup_srq_table(dev); | ||
2640 | mlx4_cleanup_cq_table(dev); | ||
2641 | mlx4_cmd_use_polling(dev); | ||
2642 | mlx4_cleanup_eq_table(dev); | ||
2643 | mlx4_cleanup_mcg_table(dev); | ||
2644 | mlx4_cleanup_mr_table(dev); | ||
2645 | mlx4_cleanup_xrcd_table(dev); | ||
2646 | mlx4_cleanup_pd_table(dev); | ||
2647 | 2635 | ||
2648 | if (mlx4_is_master(dev)) | 2636 | for (p = 1; p <= dev->caps.num_ports; p++) { |
2649 | mlx4_free_resource_tracker(dev, | 2637 | mlx4_cleanup_port_info(&priv->port[p]); |
2650 | RES_TR_FREE_STRUCTS_ONLY); | 2638 | mlx4_CLOSE_PORT(dev, p); |
2651 | 2639 | } | |
2652 | iounmap(priv->kar); | ||
2653 | mlx4_uar_free(dev, &priv->driver_uar); | ||
2654 | mlx4_cleanup_uar_table(dev); | ||
2655 | if (!mlx4_is_slave(dev)) | ||
2656 | mlx4_clear_steering(dev); | ||
2657 | mlx4_free_eq_table(dev); | ||
2658 | if (mlx4_is_master(dev)) | ||
2659 | mlx4_multi_func_cleanup(dev); | ||
2660 | mlx4_close_hca(dev); | ||
2661 | if (mlx4_is_slave(dev)) | ||
2662 | mlx4_multi_func_cleanup(dev); | ||
2663 | mlx4_cmd_cleanup(dev); | ||
2664 | |||
2665 | if (dev->flags & MLX4_FLAG_MSI_X) | ||
2666 | pci_disable_msix(pdev); | ||
2667 | if (dev->flags & MLX4_FLAG_SRIOV) { | ||
2668 | mlx4_warn(dev, "Disabling SR-IOV\n"); | ||
2669 | pci_disable_sriov(pdev); | ||
2670 | } | ||
2671 | 2640 | ||
2672 | if (!mlx4_is_slave(dev)) | 2641 | if (mlx4_is_master(dev)) |
2673 | mlx4_free_ownership(dev); | 2642 | mlx4_free_resource_tracker(dev, |
2643 | RES_TR_FREE_SLAVES_ONLY); | ||
2644 | |||
2645 | mlx4_cleanup_counters_table(dev); | ||
2646 | mlx4_cleanup_qp_table(dev); | ||
2647 | mlx4_cleanup_srq_table(dev); | ||
2648 | mlx4_cleanup_cq_table(dev); | ||
2649 | mlx4_cmd_use_polling(dev); | ||
2650 | mlx4_cleanup_eq_table(dev); | ||
2651 | mlx4_cleanup_mcg_table(dev); | ||
2652 | mlx4_cleanup_mr_table(dev); | ||
2653 | mlx4_cleanup_xrcd_table(dev); | ||
2654 | mlx4_cleanup_pd_table(dev); | ||
2674 | 2655 | ||
2675 | kfree(dev->caps.qp0_tunnel); | 2656 | if (mlx4_is_master(dev)) |
2676 | kfree(dev->caps.qp0_proxy); | 2657 | mlx4_free_resource_tracker(dev, |
2677 | kfree(dev->caps.qp1_tunnel); | 2658 | RES_TR_FREE_STRUCTS_ONLY); |
2678 | kfree(dev->caps.qp1_proxy); | ||
2679 | kfree(dev->dev_vfs); | ||
2680 | 2659 | ||
2681 | kfree(priv); | 2660 | iounmap(priv->kar); |
2682 | pci_release_regions(pdev); | 2661 | mlx4_uar_free(dev, &priv->driver_uar); |
2683 | pci_disable_device(pdev); | 2662 | mlx4_cleanup_uar_table(dev); |
2684 | pci_set_drvdata(pdev, NULL); | 2663 | if (!mlx4_is_slave(dev)) |
2664 | mlx4_clear_steering(dev); | ||
2665 | mlx4_free_eq_table(dev); | ||
2666 | if (mlx4_is_master(dev)) | ||
2667 | mlx4_multi_func_cleanup(dev); | ||
2668 | mlx4_close_hca(dev); | ||
2669 | if (mlx4_is_slave(dev)) | ||
2670 | mlx4_multi_func_cleanup(dev); | ||
2671 | mlx4_cmd_cleanup(dev); | ||
2672 | |||
2673 | if (dev->flags & MLX4_FLAG_MSI_X) | ||
2674 | pci_disable_msix(pdev); | ||
2675 | if (dev->flags & MLX4_FLAG_SRIOV) { | ||
2676 | mlx4_warn(dev, "Disabling SR-IOV\n"); | ||
2677 | pci_disable_sriov(pdev); | ||
2685 | } | 2678 | } |
2679 | |||
2680 | if (!mlx4_is_slave(dev)) | ||
2681 | mlx4_free_ownership(dev); | ||
2682 | |||
2683 | kfree(dev->caps.qp0_tunnel); | ||
2684 | kfree(dev->caps.qp0_proxy); | ||
2685 | kfree(dev->caps.qp1_tunnel); | ||
2686 | kfree(dev->caps.qp1_proxy); | ||
2687 | kfree(dev->dev_vfs); | ||
2688 | |||
2689 | pci_release_regions(pdev); | ||
2690 | pci_disable_device(pdev); | ||
2691 | memset(priv, 0, sizeof(*priv)); | ||
2692 | priv->pci_dev_data = pci_dev_data; | ||
2693 | priv->removed = 1; | ||
2694 | } | ||
2695 | |||
2696 | static void mlx4_remove_one(struct pci_dev *pdev) | ||
2697 | { | ||
2698 | struct mlx4_dev *dev = pci_get_drvdata(pdev); | ||
2699 | struct mlx4_priv *priv = mlx4_priv(dev); | ||
2700 | |||
2701 | __mlx4_remove_one(pdev); | ||
2702 | kfree(priv); | ||
2703 | pci_set_drvdata(pdev, NULL); | ||
2686 | } | 2704 | } |
2687 | 2705 | ||
2688 | int mlx4_restart_one(struct pci_dev *pdev) | 2706 | int mlx4_restart_one(struct pci_dev *pdev) |
@@ -2692,7 +2710,7 @@ int mlx4_restart_one(struct pci_dev *pdev) | |||
2692 | int pci_dev_data; | 2710 | int pci_dev_data; |
2693 | 2711 | ||
2694 | pci_dev_data = priv->pci_dev_data; | 2712 | pci_dev_data = priv->pci_dev_data; |
2695 | mlx4_remove_one(pdev); | 2713 | __mlx4_remove_one(pdev); |
2696 | return __mlx4_init_one(pdev, pci_dev_data); | 2714 | return __mlx4_init_one(pdev, pci_dev_data); |
2697 | } | 2715 | } |
2698 | 2716 | ||
@@ -2747,7 +2765,7 @@ MODULE_DEVICE_TABLE(pci, mlx4_pci_table); | |||
2747 | static pci_ers_result_t mlx4_pci_err_detected(struct pci_dev *pdev, | 2765 | static pci_ers_result_t mlx4_pci_err_detected(struct pci_dev *pdev, |
2748 | pci_channel_state_t state) | 2766 | pci_channel_state_t state) |
2749 | { | 2767 | { |
2750 | mlx4_remove_one(pdev); | 2768 | __mlx4_remove_one(pdev); |
2751 | 2769 | ||
2752 | return state == pci_channel_io_perm_failure ? | 2770 | return state == pci_channel_io_perm_failure ? |
2753 | PCI_ERS_RESULT_DISCONNECT : PCI_ERS_RESULT_NEED_RESET; | 2771 | PCI_ERS_RESULT_DISCONNECT : PCI_ERS_RESULT_NEED_RESET; |
@@ -2755,11 +2773,11 @@ static pci_ers_result_t mlx4_pci_err_detected(struct pci_dev *pdev, | |||
2755 | 2773 | ||
2756 | static pci_ers_result_t mlx4_pci_slot_reset(struct pci_dev *pdev) | 2774 | static pci_ers_result_t mlx4_pci_slot_reset(struct pci_dev *pdev) |
2757 | { | 2775 | { |
2758 | const struct pci_device_id *id; | 2776 | struct mlx4_dev *dev = pci_get_drvdata(pdev); |
2759 | int ret; | 2777 | struct mlx4_priv *priv = mlx4_priv(dev); |
2778 | int ret; | ||
2760 | 2779 | ||
2761 | id = pci_match_id(mlx4_pci_table, pdev); | 2780 | ret = __mlx4_init_one(pdev, priv->pci_dev_data); |
2762 | ret = __mlx4_init_one(pdev, id->driver_data); | ||
2763 | 2781 | ||
2764 | return ret ? PCI_ERS_RESULT_DISCONNECT : PCI_ERS_RESULT_RECOVERED; | 2782 | return ret ? PCI_ERS_RESULT_DISCONNECT : PCI_ERS_RESULT_RECOVERED; |
2765 | } | 2783 | } |
diff --git a/drivers/net/ethernet/mellanox/mlx4/mlx4.h b/drivers/net/ethernet/mellanox/mlx4/mlx4.h index cf8be41abb36..f9c465101963 100644 --- a/drivers/net/ethernet/mellanox/mlx4/mlx4.h +++ b/drivers/net/ethernet/mellanox/mlx4/mlx4.h | |||
@@ -800,6 +800,7 @@ struct mlx4_priv { | |||
800 | spinlock_t ctx_lock; | 800 | spinlock_t ctx_lock; |
801 | 801 | ||
802 | int pci_dev_data; | 802 | int pci_dev_data; |
803 | int removed; | ||
803 | 804 | ||
804 | struct list_head pgdir_list; | 805 | struct list_head pgdir_list; |
805 | struct mutex pgdir_mutex; | 806 | struct mutex pgdir_mutex; |