aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorWei Yang <weiyang@linux.vnet.ibm.com>2014-04-13 21:51:19 -0400
committerDavid S. Miller <davem@davemloft.net>2014-04-13 23:12:15 -0400
commitbefdf8978accecac2e0739e6b5075afc62db37fe (patch)
tree58591373f00b298409be793cecfdaa9c9e60a5c1
parentb04c46190219a4f845e46a459e3102137b7f6cac (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.c172
-rw-r--r--drivers/net/ethernet/mellanox/mlx4/mlx4.h1
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
2605static int mlx4_init_one(struct pci_dev *pdev, const struct pci_device_id *id) 2599static 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
2612static void mlx4_remove_one(struct pci_dev *pdev) 2617static 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
2696static 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
2688int mlx4_restart_one(struct pci_dev *pdev) 2706int 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);
2747static pci_ers_result_t mlx4_pci_err_detected(struct pci_dev *pdev, 2765static 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
2756static pci_ers_result_t mlx4_pci_slot_reset(struct pci_dev *pdev) 2774static 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;