diff options
Diffstat (limited to 'drivers/net/ethernet/mellanox/mlx4/main.c')
| -rw-r--r-- | drivers/net/ethernet/mellanox/mlx4/main.c | 181 |
1 files changed, 103 insertions, 78 deletions
diff --git a/drivers/net/ethernet/mellanox/mlx4/main.c b/drivers/net/ethernet/mellanox/mlx4/main.c index f0ae95f66ceb..cef267e24f9c 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); |
| @@ -2374,10 +2369,10 @@ static int __mlx4_init_one(struct pci_dev *pdev, int pci_dev_data) | |||
| 2374 | } else { | 2369 | } else { |
| 2375 | atomic_inc(&pf_loading); | 2370 | atomic_inc(&pf_loading); |
| 2376 | err = pci_enable_sriov(pdev, total_vfs); | 2371 | err = pci_enable_sriov(pdev, total_vfs); |
| 2377 | atomic_dec(&pf_loading); | ||
| 2378 | if (err) { | 2372 | if (err) { |
| 2379 | mlx4_err(dev, "Failed to enable SR-IOV, continuing without SR-IOV (err = %d).\n", | 2373 | mlx4_err(dev, "Failed to enable SR-IOV, continuing without SR-IOV (err = %d).\n", |
| 2380 | err); | 2374 | err); |
| 2375 | atomic_dec(&pf_loading); | ||
| 2381 | err = 0; | 2376 | err = 0; |
| 2382 | } else { | 2377 | } else { |
| 2383 | mlx4_warn(dev, "Running in master mode\n"); | 2378 | mlx4_warn(dev, "Running in master mode\n"); |
| @@ -2535,8 +2530,10 @@ 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); | 2534 | |
| 2535 | if (mlx4_is_master(dev) && dev->num_vfs) | ||
| 2536 | atomic_dec(&pf_loading); | ||
| 2540 | 2537 | ||
| 2541 | return 0; | 2538 | return 0; |
| 2542 | 2539 | ||
| @@ -2588,6 +2585,9 @@ err_rel_own: | |||
| 2588 | if (!mlx4_is_slave(dev)) | 2585 | if (!mlx4_is_slave(dev)) |
| 2589 | mlx4_free_ownership(dev); | 2586 | mlx4_free_ownership(dev); |
| 2590 | 2587 | ||
| 2588 | if (mlx4_is_master(dev) && dev->num_vfs) | ||
| 2589 | atomic_dec(&pf_loading); | ||
| 2590 | |||
| 2591 | kfree(priv->dev.dev_vfs); | 2591 | kfree(priv->dev.dev_vfs); |
| 2592 | 2592 | ||
| 2593 | err_free_dev: | 2593 | err_free_dev: |
| @@ -2604,85 +2604,110 @@ err_disable_pdev: | |||
| 2604 | 2604 | ||
| 2605 | static int mlx4_init_one(struct pci_dev *pdev, const struct pci_device_id *id) | 2605 | static int mlx4_init_one(struct pci_dev *pdev, const struct pci_device_id *id) |
| 2606 | { | 2606 | { |
| 2607 | struct mlx4_priv *priv; | ||
| 2608 | struct mlx4_dev *dev; | ||
| 2609 | |||
| 2607 | printk_once(KERN_INFO "%s", mlx4_version); | 2610 | printk_once(KERN_INFO "%s", mlx4_version); |
| 2608 | 2611 | ||
| 2612 | priv = kzalloc(sizeof(*priv), GFP_KERNEL); | ||
| 2613 | if (!priv) | ||
| 2614 | return -ENOMEM; | ||
| 2615 | |||
| 2616 | dev = &priv->dev; | ||
| 2617 | pci_set_drvdata(pdev, dev); | ||
| 2618 | priv->pci_dev_data = id->driver_data; | ||
| 2619 | |||
| 2609 | return __mlx4_init_one(pdev, id->driver_data); | 2620 | return __mlx4_init_one(pdev, id->driver_data); |
| 2610 | } | 2621 | } |
| 2611 | 2622 | ||
| 2612 | static void mlx4_remove_one(struct pci_dev *pdev) | 2623 | static void __mlx4_remove_one(struct pci_dev *pdev) |
| 2613 | { | 2624 | { |
| 2614 | struct mlx4_dev *dev = pci_get_drvdata(pdev); | 2625 | struct mlx4_dev *dev = pci_get_drvdata(pdev); |
| 2615 | struct mlx4_priv *priv = mlx4_priv(dev); | 2626 | struct mlx4_priv *priv = mlx4_priv(dev); |
| 2627 | int pci_dev_data; | ||
| 2616 | int p; | 2628 | int p; |
| 2617 | 2629 | ||
| 2618 | if (dev) { | 2630 | if (priv->removed) |
| 2619 | /* in SRIOV it is not allowed to unload the pf's | 2631 | 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 | 2632 | ||
| 2628 | for (p = 1; p <= dev->caps.num_ports; p++) { | 2633 | pci_dev_data = priv->pci_dev_data; |
| 2629 | mlx4_cleanup_port_info(&priv->port[p]); | ||
| 2630 | mlx4_CLOSE_PORT(dev, p); | ||
| 2631 | } | ||
| 2632 | 2634 | ||
| 2633 | if (mlx4_is_master(dev)) | 2635 | /* in SRIOV it is not allowed to unload the pf's |
| 2634 | mlx4_free_resource_tracker(dev, | 2636 | * driver while there are alive vf's */ |
| 2635 | RES_TR_FREE_SLAVES_ONLY); | 2637 | if (mlx4_is_master(dev) && mlx4_how_many_lives_vf(dev)) |
| 2636 | 2638 | printk(KERN_ERR "Removing PF when there are assigned VF's !!!\n"); | |
| 2637 | mlx4_cleanup_counters_table(dev); | 2639 | mlx4_stop_sense(dev); |
| 2638 | mlx4_cleanup_qp_table(dev); | 2640 | 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 | 2641 | ||
| 2648 | if (mlx4_is_master(dev)) | 2642 | for (p = 1; p <= dev->caps.num_ports; p++) { |
| 2649 | mlx4_free_resource_tracker(dev, | 2643 | mlx4_cleanup_port_info(&priv->port[p]); |
| 2650 | RES_TR_FREE_STRUCTS_ONLY); | 2644 | mlx4_CLOSE_PORT(dev, p); |
| 2651 | 2645 | } | |
| 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 | 2646 | ||
| 2672 | if (!mlx4_is_slave(dev)) | 2647 | if (mlx4_is_master(dev)) |
| 2673 | mlx4_free_ownership(dev); | 2648 | mlx4_free_resource_tracker(dev, |
| 2649 | RES_TR_FREE_SLAVES_ONLY); | ||
| 2674 | 2650 | ||
| 2675 | kfree(dev->caps.qp0_tunnel); | 2651 | mlx4_cleanup_counters_table(dev); |
| 2676 | kfree(dev->caps.qp0_proxy); | 2652 | mlx4_cleanup_qp_table(dev); |
| 2677 | kfree(dev->caps.qp1_tunnel); | 2653 | mlx4_cleanup_srq_table(dev); |
| 2678 | kfree(dev->caps.qp1_proxy); | 2654 | mlx4_cleanup_cq_table(dev); |
| 2679 | kfree(dev->dev_vfs); | 2655 | mlx4_cmd_use_polling(dev); |
| 2656 | mlx4_cleanup_eq_table(dev); | ||
| 2657 | mlx4_cleanup_mcg_table(dev); | ||
| 2658 | mlx4_cleanup_mr_table(dev); | ||
| 2659 | mlx4_cleanup_xrcd_table(dev); | ||
| 2660 | mlx4_cleanup_pd_table(dev); | ||
| 2680 | 2661 | ||
| 2681 | kfree(priv); | 2662 | if (mlx4_is_master(dev)) |
| 2682 | pci_release_regions(pdev); | 2663 | mlx4_free_resource_tracker(dev, |
| 2683 | pci_disable_device(pdev); | 2664 | RES_TR_FREE_STRUCTS_ONLY); |
| 2684 | pci_set_drvdata(pdev, NULL); | 2665 | |
| 2666 | iounmap(priv->kar); | ||
| 2667 | mlx4_uar_free(dev, &priv->driver_uar); | ||
| 2668 | mlx4_cleanup_uar_table(dev); | ||
| 2669 | if (!mlx4_is_slave(dev)) | ||
| 2670 | mlx4_clear_steering(dev); | ||
| 2671 | mlx4_free_eq_table(dev); | ||
| 2672 | if (mlx4_is_master(dev)) | ||
| 2673 | mlx4_multi_func_cleanup(dev); | ||
| 2674 | mlx4_close_hca(dev); | ||
| 2675 | if (mlx4_is_slave(dev)) | ||
| 2676 | mlx4_multi_func_cleanup(dev); | ||
| 2677 | mlx4_cmd_cleanup(dev); | ||
| 2678 | |||
| 2679 | if (dev->flags & MLX4_FLAG_MSI_X) | ||
| 2680 | pci_disable_msix(pdev); | ||
| 2681 | if (dev->flags & MLX4_FLAG_SRIOV) { | ||
| 2682 | mlx4_warn(dev, "Disabling SR-IOV\n"); | ||
| 2683 | pci_disable_sriov(pdev); | ||
| 2684 | dev->num_vfs = 0; | ||
| 2685 | } | 2685 | } |
| 2686 | |||
| 2687 | if (!mlx4_is_slave(dev)) | ||
| 2688 | mlx4_free_ownership(dev); | ||
| 2689 | |||
| 2690 | kfree(dev->caps.qp0_tunnel); | ||
| 2691 | kfree(dev->caps.qp0_proxy); | ||
| 2692 | kfree(dev->caps.qp1_tunnel); | ||
| 2693 | kfree(dev->caps.qp1_proxy); | ||
| 2694 | kfree(dev->dev_vfs); | ||
| 2695 | |||
| 2696 | pci_release_regions(pdev); | ||
| 2697 | pci_disable_device(pdev); | ||
| 2698 | memset(priv, 0, sizeof(*priv)); | ||
| 2699 | priv->pci_dev_data = pci_dev_data; | ||
| 2700 | priv->removed = 1; | ||
| 2701 | } | ||
| 2702 | |||
| 2703 | static void mlx4_remove_one(struct pci_dev *pdev) | ||
| 2704 | { | ||
| 2705 | struct mlx4_dev *dev = pci_get_drvdata(pdev); | ||
| 2706 | struct mlx4_priv *priv = mlx4_priv(dev); | ||
| 2707 | |||
| 2708 | __mlx4_remove_one(pdev); | ||
| 2709 | kfree(priv); | ||
| 2710 | pci_set_drvdata(pdev, NULL); | ||
| 2686 | } | 2711 | } |
| 2687 | 2712 | ||
| 2688 | int mlx4_restart_one(struct pci_dev *pdev) | 2713 | int mlx4_restart_one(struct pci_dev *pdev) |
| @@ -2692,7 +2717,7 @@ int mlx4_restart_one(struct pci_dev *pdev) | |||
| 2692 | int pci_dev_data; | 2717 | int pci_dev_data; |
| 2693 | 2718 | ||
| 2694 | pci_dev_data = priv->pci_dev_data; | 2719 | pci_dev_data = priv->pci_dev_data; |
| 2695 | mlx4_remove_one(pdev); | 2720 | __mlx4_remove_one(pdev); |
| 2696 | return __mlx4_init_one(pdev, pci_dev_data); | 2721 | return __mlx4_init_one(pdev, pci_dev_data); |
| 2697 | } | 2722 | } |
| 2698 | 2723 | ||
| @@ -2747,7 +2772,7 @@ MODULE_DEVICE_TABLE(pci, mlx4_pci_table); | |||
| 2747 | static pci_ers_result_t mlx4_pci_err_detected(struct pci_dev *pdev, | 2772 | static pci_ers_result_t mlx4_pci_err_detected(struct pci_dev *pdev, |
| 2748 | pci_channel_state_t state) | 2773 | pci_channel_state_t state) |
| 2749 | { | 2774 | { |
| 2750 | mlx4_remove_one(pdev); | 2775 | __mlx4_remove_one(pdev); |
| 2751 | 2776 | ||
| 2752 | return state == pci_channel_io_perm_failure ? | 2777 | return state == pci_channel_io_perm_failure ? |
| 2753 | PCI_ERS_RESULT_DISCONNECT : PCI_ERS_RESULT_NEED_RESET; | 2778 | PCI_ERS_RESULT_DISCONNECT : PCI_ERS_RESULT_NEED_RESET; |
| @@ -2755,11 +2780,11 @@ static pci_ers_result_t mlx4_pci_err_detected(struct pci_dev *pdev, | |||
| 2755 | 2780 | ||
| 2756 | static pci_ers_result_t mlx4_pci_slot_reset(struct pci_dev *pdev) | 2781 | static pci_ers_result_t mlx4_pci_slot_reset(struct pci_dev *pdev) |
| 2757 | { | 2782 | { |
| 2758 | const struct pci_device_id *id; | 2783 | struct mlx4_dev *dev = pci_get_drvdata(pdev); |
| 2759 | int ret; | 2784 | struct mlx4_priv *priv = mlx4_priv(dev); |
| 2785 | int ret; | ||
| 2760 | 2786 | ||
| 2761 | id = pci_match_id(mlx4_pci_table, pdev); | 2787 | ret = __mlx4_init_one(pdev, priv->pci_dev_data); |
| 2762 | ret = __mlx4_init_one(pdev, id->driver_data); | ||
| 2763 | 2788 | ||
| 2764 | return ret ? PCI_ERS_RESULT_DISCONNECT : PCI_ERS_RESULT_RECOVERED; | 2789 | return ret ? PCI_ERS_RESULT_DISCONNECT : PCI_ERS_RESULT_RECOVERED; |
| 2765 | } | 2790 | } |
