diff options
Diffstat (limited to 'drivers/net/ethernet/mellanox/mlx4/main.c')
| -rw-r--r-- | drivers/net/ethernet/mellanox/mlx4/main.c | 184 | 
1 files changed, 105 insertions, 79 deletions
diff --git a/drivers/net/ethernet/mellanox/mlx4/main.c b/drivers/net/ethernet/mellanox/mlx4/main.c index f0ae95f66ceb..7cf9dadcb471 100644 --- a/drivers/net/ethernet/mellanox/mlx4/main.c +++ b/drivers/net/ethernet/mellanox/mlx4/main.c @@ -754,10 +754,10 @@ static void mlx4_request_modules(struct mlx4_dev *dev)  			has_eth_port = true;  	} -	if (has_ib_port || (dev->caps.flags & MLX4_DEV_CAP_FLAG_IBOE)) -		request_module_nowait(IB_DRV_NAME);  	if (has_eth_port)  		request_module_nowait(EN_DRV_NAME); +	if (has_ib_port || (dev->caps.flags & MLX4_DEV_CAP_FLAG_IBOE)) +		request_module_nowait(IB_DRV_NAME);  }  /* @@ -2301,13 +2301,8 @@ static int __mlx4_init_one(struct pci_dev *pdev, int pci_dev_data)  	/* Allow large DMA segments, up to the firmware limit of 1 GB */  	dma_set_max_seg_size(&pdev->dev, 1024 * 1024 * 1024); -	priv = kzalloc(sizeof(*priv), GFP_KERNEL); -	if (!priv) { -		err = -ENOMEM; -		goto err_release_regions; -	} - -	dev       = &priv->dev; +	dev       = pci_get_drvdata(pdev); +	priv      = mlx4_priv(dev);  	dev->pdev = pdev;  	INIT_LIST_HEAD(&priv->ctx_list);  	spin_lock_init(&priv->ctx_lock); @@ -2374,10 +2369,10 @@ static int __mlx4_init_one(struct pci_dev *pdev, int pci_dev_data)  			} else {  				atomic_inc(&pf_loading);  				err = pci_enable_sriov(pdev, total_vfs); -				atomic_dec(&pf_loading);  				if (err) {  					mlx4_err(dev, "Failed to enable SR-IOV, continuing without SR-IOV (err = %d).\n",  						 err); +					atomic_dec(&pf_loading);  					err = 0;  				} else {  					mlx4_warn(dev, "Running in master mode\n"); @@ -2445,7 +2440,8 @@ slave_start:  	 * No return code for this call, just warn the user in case of PCI  	 * express device capabilities are under-satisfied by the bus.  	 */ -	mlx4_check_pcie_caps(dev); +	if (!mlx4_is_slave(dev)) +		mlx4_check_pcie_caps(dev);  	/* In master functions, the communication channel must be initialized  	 * after obtaining its address from fw */ @@ -2535,8 +2531,10 @@ slave_start:  	mlx4_sense_init(dev);  	mlx4_start_sense(dev); -	priv->pci_dev_data = pci_dev_data; -	pci_set_drvdata(pdev, dev); +	priv->removed = 0; + +	if (mlx4_is_master(dev) && dev->num_vfs) +		atomic_dec(&pf_loading);  	return 0; @@ -2588,6 +2586,9 @@ err_rel_own:  	if (!mlx4_is_slave(dev))  		mlx4_free_ownership(dev); +	if (mlx4_is_master(dev) && dev->num_vfs) +		atomic_dec(&pf_loading); +  	kfree(priv->dev.dev_vfs);  err_free_dev: @@ -2604,85 +2605,110 @@ err_disable_pdev:  static int mlx4_init_one(struct pci_dev *pdev, const struct pci_device_id *id)  { +	struct mlx4_priv *priv; +	struct mlx4_dev *dev; +  	printk_once(KERN_INFO "%s", mlx4_version); +	priv = kzalloc(sizeof(*priv), GFP_KERNEL); +	if (!priv) +		return -ENOMEM; + +	dev       = &priv->dev; +	pci_set_drvdata(pdev, dev); +	priv->pci_dev_data = id->driver_data; +  	return __mlx4_init_one(pdev, id->driver_data);  } -static void mlx4_remove_one(struct pci_dev *pdev) +static void __mlx4_remove_one(struct pci_dev *pdev)  {  	struct mlx4_dev  *dev  = pci_get_drvdata(pdev);  	struct mlx4_priv *priv = mlx4_priv(dev); +	int               pci_dev_data;  	int p; -	if (dev) { -		/* in SRIOV it is not allowed to unload the pf's -		 * driver while there are alive vf's */ -		if (mlx4_is_master(dev)) { -			if (mlx4_how_many_lives_vf(dev)) -				printk(KERN_ERR "Removing PF when there are assigned VF's !!!\n"); -		} -		mlx4_stop_sense(dev); -		mlx4_unregister_device(dev); - -		for (p = 1; p <= dev->caps.num_ports; p++) { -			mlx4_cleanup_port_info(&priv->port[p]); -			mlx4_CLOSE_PORT(dev, p); -		} +	if (priv->removed) +		return; -		if (mlx4_is_master(dev)) -			mlx4_free_resource_tracker(dev, -						   RES_TR_FREE_SLAVES_ONLY); +	pci_dev_data = priv->pci_dev_data; -		mlx4_cleanup_counters_table(dev); -		mlx4_cleanup_qp_table(dev); -		mlx4_cleanup_srq_table(dev); -		mlx4_cleanup_cq_table(dev); -		mlx4_cmd_use_polling(dev); -		mlx4_cleanup_eq_table(dev); -		mlx4_cleanup_mcg_table(dev); -		mlx4_cleanup_mr_table(dev); -		mlx4_cleanup_xrcd_table(dev); -		mlx4_cleanup_pd_table(dev); +	/* in SRIOV it is not allowed to unload the pf's +	 * driver while there are alive vf's */ +	if (mlx4_is_master(dev) && mlx4_how_many_lives_vf(dev)) +		printk(KERN_ERR "Removing PF when there are assigned VF's !!!\n"); +	mlx4_stop_sense(dev); +	mlx4_unregister_device(dev); -		if (mlx4_is_master(dev)) -			mlx4_free_resource_tracker(dev, -						   RES_TR_FREE_STRUCTS_ONLY); +	for (p = 1; p <= dev->caps.num_ports; p++) { +		mlx4_cleanup_port_info(&priv->port[p]); +		mlx4_CLOSE_PORT(dev, p); +	} -		iounmap(priv->kar); -		mlx4_uar_free(dev, &priv->driver_uar); -		mlx4_cleanup_uar_table(dev); -		if (!mlx4_is_slave(dev)) -			mlx4_clear_steering(dev); -		mlx4_free_eq_table(dev); -		if (mlx4_is_master(dev)) -			mlx4_multi_func_cleanup(dev); -		mlx4_close_hca(dev); -		if (mlx4_is_slave(dev)) -			mlx4_multi_func_cleanup(dev); -		mlx4_cmd_cleanup(dev); +	if (mlx4_is_master(dev)) +		mlx4_free_resource_tracker(dev, +					   RES_TR_FREE_SLAVES_ONLY); -		if (dev->flags & MLX4_FLAG_MSI_X) -			pci_disable_msix(pdev); -		if (dev->flags & MLX4_FLAG_SRIOV) { -			mlx4_warn(dev, "Disabling SR-IOV\n"); -			pci_disable_sriov(pdev); -		} +	mlx4_cleanup_counters_table(dev); +	mlx4_cleanup_qp_table(dev); +	mlx4_cleanup_srq_table(dev); +	mlx4_cleanup_cq_table(dev); +	mlx4_cmd_use_polling(dev); +	mlx4_cleanup_eq_table(dev); +	mlx4_cleanup_mcg_table(dev); +	mlx4_cleanup_mr_table(dev); +	mlx4_cleanup_xrcd_table(dev); +	mlx4_cleanup_pd_table(dev); -		if (!mlx4_is_slave(dev)) -			mlx4_free_ownership(dev); +	if (mlx4_is_master(dev)) +		mlx4_free_resource_tracker(dev, +					   RES_TR_FREE_STRUCTS_ONLY); -		kfree(dev->caps.qp0_tunnel); -		kfree(dev->caps.qp0_proxy); -		kfree(dev->caps.qp1_tunnel); -		kfree(dev->caps.qp1_proxy); -		kfree(dev->dev_vfs); +	iounmap(priv->kar); +	mlx4_uar_free(dev, &priv->driver_uar); +	mlx4_cleanup_uar_table(dev); +	if (!mlx4_is_slave(dev)) +		mlx4_clear_steering(dev); +	mlx4_free_eq_table(dev); +	if (mlx4_is_master(dev)) +		mlx4_multi_func_cleanup(dev); +	mlx4_close_hca(dev); +	if (mlx4_is_slave(dev)) +		mlx4_multi_func_cleanup(dev); +	mlx4_cmd_cleanup(dev); -		kfree(priv); -		pci_release_regions(pdev); -		pci_disable_device(pdev); -		pci_set_drvdata(pdev, NULL); +	if (dev->flags & MLX4_FLAG_MSI_X) +		pci_disable_msix(pdev); +	if (dev->flags & MLX4_FLAG_SRIOV) { +		mlx4_warn(dev, "Disabling SR-IOV\n"); +		pci_disable_sriov(pdev); +		dev->num_vfs = 0;  	} + +	if (!mlx4_is_slave(dev)) +		mlx4_free_ownership(dev); + +	kfree(dev->caps.qp0_tunnel); +	kfree(dev->caps.qp0_proxy); +	kfree(dev->caps.qp1_tunnel); +	kfree(dev->caps.qp1_proxy); +	kfree(dev->dev_vfs); + +	pci_release_regions(pdev); +	pci_disable_device(pdev); +	memset(priv, 0, sizeof(*priv)); +	priv->pci_dev_data = pci_dev_data; +	priv->removed = 1; +} + +static void mlx4_remove_one(struct pci_dev *pdev) +{ +	struct mlx4_dev  *dev  = pci_get_drvdata(pdev); +	struct mlx4_priv *priv = mlx4_priv(dev); + +	__mlx4_remove_one(pdev); +	kfree(priv); +	pci_set_drvdata(pdev, NULL);  }  int mlx4_restart_one(struct pci_dev *pdev) @@ -2692,7 +2718,7 @@ int mlx4_restart_one(struct pci_dev *pdev)  	int		  pci_dev_data;  	pci_dev_data = priv->pci_dev_data; -	mlx4_remove_one(pdev); +	__mlx4_remove_one(pdev);  	return __mlx4_init_one(pdev, pci_dev_data);  } @@ -2747,7 +2773,7 @@ MODULE_DEVICE_TABLE(pci, mlx4_pci_table);  static pci_ers_result_t mlx4_pci_err_detected(struct pci_dev *pdev,  					      pci_channel_state_t state)  { -	mlx4_remove_one(pdev); +	__mlx4_remove_one(pdev);  	return state == pci_channel_io_perm_failure ?  		PCI_ERS_RESULT_DISCONNECT : PCI_ERS_RESULT_NEED_RESET; @@ -2755,11 +2781,11 @@ static pci_ers_result_t mlx4_pci_err_detected(struct pci_dev *pdev,  static pci_ers_result_t mlx4_pci_slot_reset(struct pci_dev *pdev)  { -	const struct pci_device_id *id; -	int ret; +	struct mlx4_dev	 *dev  = pci_get_drvdata(pdev); +	struct mlx4_priv *priv = mlx4_priv(dev); +	int               ret; -	id = pci_match_id(mlx4_pci_table, pdev); -	ret = __mlx4_init_one(pdev, id->driver_data); +	ret = __mlx4_init_one(pdev, priv->pci_dev_data);  	return ret ? PCI_ERS_RESULT_DISCONNECT : PCI_ERS_RESULT_RECOVERED;  }  | 
