diff options
Diffstat (limited to 'drivers/net/ethernet/mellanox/mlx4/main.c')
| -rw-r--r-- | drivers/net/ethernet/mellanox/mlx4/main.c | 164 | 
1 files changed, 103 insertions, 61 deletions
diff --git a/drivers/net/ethernet/mellanox/mlx4/main.c b/drivers/net/ethernet/mellanox/mlx4/main.c index b2acbe7706a..d180bc46826 100644 --- a/drivers/net/ethernet/mellanox/mlx4/main.c +++ b/drivers/net/ethernet/mellanox/mlx4/main.c @@ -85,15 +85,15 @@ static int probe_vf;  module_param(probe_vf, int, 0644);  MODULE_PARM_DESC(probe_vf, "number of vfs to probe by pf driver (num_vfs > 0)"); -int mlx4_log_num_mgm_entry_size = 10; +int mlx4_log_num_mgm_entry_size = MLX4_DEFAULT_MGM_LOG_ENTRY_SIZE;  module_param_named(log_num_mgm_entry_size,  			mlx4_log_num_mgm_entry_size, int, 0444);  MODULE_PARM_DESC(log_num_mgm_entry_size, "log mgm size, that defines the num"  					 " of qp per mcg, for example:" -					 " 10 gives 248.range: 9<=" +					 " 10 gives 248.range: 7 <="  					 " log_num_mgm_entry_size <= 12." -					 " Not in use with device managed" -					 " flow steering"); +					 " To activate device managed" +					 " flow steering when available, set to -1");  static bool enable_64b_cqe_eqe;  module_param(enable_64b_cqe_eqe, bool, 0444); @@ -281,28 +281,6 @@ static int mlx4_dev_cap(struct mlx4_dev *dev, struct mlx4_dev_cap *dev_cap)  	dev->caps.max_gso_sz	     = dev_cap->max_gso_sz;  	dev->caps.max_rss_tbl_sz     = dev_cap->max_rss_tbl_sz; -	if (dev_cap->flags2 & MLX4_DEV_CAP_FLAG2_FS_EN) { -		dev->caps.steering_mode = MLX4_STEERING_MODE_DEVICE_MANAGED; -		dev->caps.num_qp_per_mgm = dev_cap->fs_max_num_qp_per_entry; -		dev->caps.fs_log_max_ucast_qp_range_size = -			dev_cap->fs_log_max_ucast_qp_range_size; -	} else { -		if (dev->caps.flags & MLX4_DEV_CAP_FLAG_VEP_UC_STEER && -		    dev->caps.flags & MLX4_DEV_CAP_FLAG_VEP_MC_STEER) { -			dev->caps.steering_mode = MLX4_STEERING_MODE_B0; -		} else { -			dev->caps.steering_mode = MLX4_STEERING_MODE_A0; - -			if (dev->caps.flags & MLX4_DEV_CAP_FLAG_VEP_UC_STEER || -			    dev->caps.flags & MLX4_DEV_CAP_FLAG_VEP_MC_STEER) -				mlx4_warn(dev, "Must have UC_STEER and MC_STEER flags " -						"set to use B0 steering. Falling back to A0 steering mode.\n"); -		} -		dev->caps.num_qp_per_mgm = mlx4_get_qp_per_mgm(dev); -	} -	mlx4_dbg(dev, "Steering mode is: %s\n", -		 mlx4_steering_mode_str(dev->caps.steering_mode)); -  	/* Sense port always allowed on supported devices for ConnectX-1 and -2 */  	if (mlx4_priv(dev)->pci_dev_data & MLX4_PCI_DEV_FORCE_SENSE_PORT)  		dev->caps.flags |= MLX4_DEV_CAP_FLAG_SENSE_SUPPORT; @@ -402,7 +380,7 @@ static int mlx4_dev_cap(struct mlx4_dev *dev, struct mlx4_dev_cap *dev_cap)  		}  	} -	if ((dev_cap->flags & +	if ((dev->caps.flags &  	    (MLX4_DEV_CAP_FLAG_64B_CQE | MLX4_DEV_CAP_FLAG_64B_EQE)) &&  	    mlx4_is_master(dev))  		dev->caps.function_caps |= MLX4_FUNC_CAP_64B_EQE_CQE; @@ -493,6 +471,23 @@ int mlx4_is_slave_active(struct mlx4_dev *dev, int slave)  }  EXPORT_SYMBOL(mlx4_is_slave_active); +static void slave_adjust_steering_mode(struct mlx4_dev *dev, +				       struct mlx4_dev_cap *dev_cap, +				       struct mlx4_init_hca_param *hca_param) +{ +	dev->caps.steering_mode = hca_param->steering_mode; +	if (dev->caps.steering_mode == MLX4_STEERING_MODE_DEVICE_MANAGED) { +		dev->caps.num_qp_per_mgm = dev_cap->fs_max_num_qp_per_entry; +		dev->caps.fs_log_max_ucast_qp_range_size = +			dev_cap->fs_log_max_ucast_qp_range_size; +	} else +		dev->caps.num_qp_per_mgm = +			4 * ((1 << hca_param->log_mc_entry_sz)/16 - 2); + +	mlx4_dbg(dev, "Steering mode is: %s\n", +		 mlx4_steering_mode_str(dev->caps.steering_mode)); +} +  static int mlx4_slave_cap(struct mlx4_dev *dev)  {  	int			   err; @@ -635,6 +630,8 @@ static int mlx4_slave_cap(struct mlx4_dev *dev)  		dev->caps.cqe_size   = 32;  	} +	slave_adjust_steering_mode(dev, &dev_cap, &hca_param); +  	return 0;  err_mem: @@ -1321,6 +1318,59 @@ static void mlx4_parav_master_pf_caps(struct mlx4_dev *dev)  	}  } +static int choose_log_fs_mgm_entry_size(int qp_per_entry) +{ +	int i = MLX4_MIN_MGM_LOG_ENTRY_SIZE; + +	for (i = MLX4_MIN_MGM_LOG_ENTRY_SIZE; i <= MLX4_MAX_MGM_LOG_ENTRY_SIZE; +	      i++) { +		if (qp_per_entry <= 4 * ((1 << i) / 16 - 2)) +			break; +	} + +	return (i <= MLX4_MAX_MGM_LOG_ENTRY_SIZE) ? i : -1; +} + +static void choose_steering_mode(struct mlx4_dev *dev, +				 struct mlx4_dev_cap *dev_cap) +{ +	if (mlx4_log_num_mgm_entry_size == -1 && +	    dev_cap->flags2 & MLX4_DEV_CAP_FLAG2_FS_EN && +	    (!mlx4_is_mfunc(dev) || +	     (dev_cap->fs_max_num_qp_per_entry >= (num_vfs + 1))) && +	    choose_log_fs_mgm_entry_size(dev_cap->fs_max_num_qp_per_entry) >= +		MLX4_MIN_MGM_LOG_ENTRY_SIZE) { +		dev->oper_log_mgm_entry_size = +			choose_log_fs_mgm_entry_size(dev_cap->fs_max_num_qp_per_entry); +		dev->caps.steering_mode = MLX4_STEERING_MODE_DEVICE_MANAGED; +		dev->caps.num_qp_per_mgm = dev_cap->fs_max_num_qp_per_entry; +		dev->caps.fs_log_max_ucast_qp_range_size = +			dev_cap->fs_log_max_ucast_qp_range_size; +	} else { +		if (dev->caps.flags & MLX4_DEV_CAP_FLAG_VEP_UC_STEER && +		    dev->caps.flags & MLX4_DEV_CAP_FLAG_VEP_MC_STEER) +			dev->caps.steering_mode = MLX4_STEERING_MODE_B0; +		else { +			dev->caps.steering_mode = MLX4_STEERING_MODE_A0; + +			if (dev->caps.flags & MLX4_DEV_CAP_FLAG_VEP_UC_STEER || +			    dev->caps.flags & MLX4_DEV_CAP_FLAG_VEP_MC_STEER) +				mlx4_warn(dev, "Must have both UC_STEER and MC_STEER flags " +					  "set to use B0 steering. Falling back to A0 steering mode.\n"); +		} +		dev->oper_log_mgm_entry_size = +			mlx4_log_num_mgm_entry_size > 0 ? +			mlx4_log_num_mgm_entry_size : +			MLX4_DEFAULT_MGM_LOG_ENTRY_SIZE; +		dev->caps.num_qp_per_mgm = mlx4_get_qp_per_mgm(dev); +	} +	mlx4_dbg(dev, "Steering mode is: %s, oper_log_mgm_entry_size = %d, " +		 "modparam log_num_mgm_entry_size = %d\n", +		 mlx4_steering_mode_str(dev->caps.steering_mode), +		 dev->oper_log_mgm_entry_size, +		 mlx4_log_num_mgm_entry_size); +} +  static int mlx4_init_hca(struct mlx4_dev *dev)  {  	struct mlx4_priv	  *priv = mlx4_priv(dev); @@ -1360,25 +1410,11 @@ static int mlx4_init_hca(struct mlx4_dev *dev)  			goto err_stop_fw;  		} +		choose_steering_mode(dev, &dev_cap); +  		if (mlx4_is_master(dev))  			mlx4_parav_master_pf_caps(dev); -		priv->fs_hash_mode = MLX4_FS_L2_HASH; - -		switch (priv->fs_hash_mode) { -		case MLX4_FS_L2_HASH: -			init_hca.fs_hash_enable_bits = 0; -			break; - -		case MLX4_FS_L2_L3_L4_HASH: -			/* Enable flow steering with -			 * udp unicast and tcp unicast -			 */ -			init_hca.fs_hash_enable_bits = -				MLX4_FS_UDP_UC_EN | MLX4_FS_TCP_UC_EN; -			break; -		} -  		profile = default_profile;  		if (dev->caps.steering_mode ==  		    MLX4_STEERING_MODE_DEVICE_MANAGED) @@ -1395,6 +1431,10 @@ static int mlx4_init_hca(struct mlx4_dev *dev)  		init_hca.log_uar_sz = ilog2(dev->caps.num_uars);  		init_hca.uar_page_sz = PAGE_SHIFT - 12; +		init_hca.mw_enabled = 0; +		if (dev->caps.flags & MLX4_DEV_CAP_FLAG_MEM_WINDOW || +		    dev->caps.bmme_flags & MLX4_BMME_FLAG_TYPE_2_WIN) +			init_hca.mw_enabled = INIT_HCA_TPT_MW_ENABLE;  		err = mlx4_init_icm(dev, &dev_cap, &init_hca, icm_size);  		if (err) @@ -1738,15 +1778,8 @@ static void mlx4_enable_msi_x(struct mlx4_dev *dev)  	int i;  	if (msi_x) { -		/* In multifunction mode each function gets 2 msi-X vectors -		 * one for data path completions anf the other for asynch events -		 * or command completions */ -		if (mlx4_is_mfunc(dev)) { -			nreq = 2; -		} else { -			nreq = min_t(int, dev->caps.num_eqs - -				     dev->caps.reserved_eqs, nreq); -		} +		nreq = min_t(int, dev->caps.num_eqs - dev->caps.reserved_eqs, +			     nreq);  		entries = kcalloc(nreq, sizeof *entries, GFP_KERNEL);  		if (!entries) @@ -1804,12 +1837,9 @@ static int mlx4_init_port_info(struct mlx4_dev *dev, int port)  	info->dev = dev;  	info->port = port;  	if (!mlx4_is_slave(dev)) { -		INIT_RADIX_TREE(&info->mac_tree, GFP_KERNEL);  		mlx4_init_mac_table(dev, &info->mac_table);  		mlx4_init_vlan_table(dev, &info->vlan_table); -		info->base_qpn = -			dev->caps.reserved_qps_base[MLX4_QP_REGION_ETH_ADDR] + -			(port - 1) * (1 << log_num_mac); +		info->base_qpn = mlx4_get_base_qpn(dev, port);  	}  	sprintf(info->dev_name, "mlx4_port%d", port); @@ -2025,10 +2055,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); +	priv = kzalloc(sizeof(*priv), GFP_KERNEL);  	if (!priv) { -		dev_err(&pdev->dev, "Device struct alloc failed, " -			"aborting.\n");  		err = -ENOMEM;  		goto err_release_regions;  	} @@ -2117,7 +2145,8 @@ slave_start:  			dev->num_slaves = MLX4_MAX_NUM_SLAVES;  		else {  			dev->num_slaves = 0; -			if (mlx4_multi_func_init(dev)) { +			err = mlx4_multi_func_init(dev); +			if (err) {  				mlx4_err(dev, "Failed to init slave mfunc"  					 " interface, aborting.\n");  				goto err_cmd; @@ -2141,7 +2170,8 @@ slave_start:  	/* In master functions, the communication channel must be initialized  	 * after obtaining its address from fw */  	if (mlx4_is_master(dev)) { -		if (mlx4_multi_func_init(dev)) { +		err = mlx4_multi_func_init(dev); +		if (err) {  			mlx4_err(dev, "Failed to init master mfunc"  				 "interface, aborting.\n");  			goto err_close; @@ -2158,6 +2188,7 @@ slave_start:  	mlx4_enable_msi_x(dev);  	if ((mlx4_is_mfunc(dev)) &&  	    !(dev->flags & MLX4_FLAG_MSI_X)) { +		err = -ENOSYS;  		mlx4_err(dev, "INTx is not supported in multi-function mode."  			 " aborting.\n");  		goto err_free_eq; @@ -2452,6 +2483,17 @@ static int __init mlx4_verify_params(void)  		port_type_array[0] = true;  	} +	if (mlx4_log_num_mgm_entry_size != -1 && +	    (mlx4_log_num_mgm_entry_size < MLX4_MIN_MGM_LOG_ENTRY_SIZE || +	     mlx4_log_num_mgm_entry_size > MLX4_MAX_MGM_LOG_ENTRY_SIZE)) { +		pr_warning("mlx4_core: mlx4_log_num_mgm_entry_size (%d) not " +			   "in legal range (-1 or %d..%d)\n", +			   mlx4_log_num_mgm_entry_size, +			   MLX4_MIN_MGM_LOG_ENTRY_SIZE, +			   MLX4_MAX_MGM_LOG_ENTRY_SIZE); +		return -1; +	} +  	return 0;  }  |