static uint8_t probe_vf[3] = {0, 0, 0}; staticint probe_vfs_argc;
module_param_array(probe_vf, byte, &probe_vfs_argc, 0444);
MODULE_PARM_DESC(probe_vf, "number of vfs to probe by pf driver (num_vfs > 0)\n" "probe_vf=port1,port2,port1+2");
staticint 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: 7 <=" " log_num_mgm_entry_size <= 12." " To activate device managed" " flow steering when available, set to -1");
staticbool enable_64b_cqe_eqe = true;
module_param(enable_64b_cqe_eqe, bool, 0444);
MODULE_PARM_DESC(enable_64b_cqe_eqe, "Enable 64 byte CQEs/EQEs when the FW supports this (default: True)");
staticbool enable_4k_uar;
module_param(enable_4k_uar, bool, 0444);
MODULE_PARM_DESC(enable_4k_uar, "Enable using 4K UAR. Should not be enabled if have VFs which do not support 4K UARs (default: false)");
staticint log_num_mac = 7;
module_param_named(log_num_mac, log_num_mac, int, 0444);
MODULE_PARM_DESC(log_num_mac, "Log2 max number of MACs per ETH port (1-7)");
staticint log_num_vlan;
module_param_named(log_num_vlan, log_num_vlan, int, 0444);
MODULE_PARM_DESC(log_num_vlan, "Log2 max number of VLANs per ETH port (0-7)"); /* Log2 max number of VLANs per ETH port (0-7) */ #define MLX4_LOG_NUM_VLANS 7 #define MLX4_MIN_LOG_NUM_VLANS 0 #define MLX4_MIN_LOG_NUM_MAC 1
staticbool use_prio;
module_param_named(use_prio, use_prio, bool, 0444);
MODULE_PARM_DESC(use_prio, "Enable steering by VLAN priority on ETH ports (deprecated)");
int log_mtts_per_seg = ilog2(1);
module_param_named(log_mtts_per_seg, log_mtts_per_seg, int, 0444);
MODULE_PARM_DESC(log_mtts_per_seg, "Log2 number of MTT entries per segment " "(0-7) (default: 0)");
staticint port_type_array[2] = {MLX4_PORT_TYPE_NONE, MLX4_PORT_TYPE_NONE}; staticint arr_argc = 2;
module_param_array(port_type_array, int, &arr_argc, 0444);
MODULE_PARM_DESC(port_type_array, "Array of port types: HW_DEFAULT (0) is default " "1 for IB, 2 for Ethernet");
staticinlinevoid mlx4_set_num_reserved_uars(struct mlx4_dev *dev, struct mlx4_dev_cap *dev_cap)
{ /* The reserved_uars is calculated by system page size unit. *Therefore,adjustmentisaddedwhentheuarpagesizeisless *thanthesystempagesize
*/
dev->caps.reserved_uars =
max_t(int,
mlx4_get_num_reserved_uar(dev),
dev_cap->reserved_uars /
(1 << (PAGE_SHIFT - dev->uar_page_shift)));
}
int mlx4_check_port_params(struct mlx4_dev *dev, enum mlx4_port_type *port_type)
{ int i;
if (!(dev->caps.flags & MLX4_DEV_CAP_FLAG_DPDP)) { for (i = 0; i < dev->caps.num_ports - 1; i++) { if (port_type[i] != port_type[i + 1]) {
mlx4_err(dev, "Only same port types supported on this HCA, aborting\n"); return -EOPNOTSUPP;
}
}
}
for (i = 0; i < dev->caps.num_ports; i++) { if (!(port_type[i] & dev->caps.supported_type[i+1])) {
mlx4_err(dev, "Requested port type for port %d is not supported on this HCA\n",
i + 1); return -EOPNOTSUPP;
}
} return0;
}
staticvoid mlx4_set_port_mask(struct mlx4_dev *dev)
{ int i;
for (i = 1; i <= dev->caps.num_ports; ++i)
dev->caps.port_mask[i] = dev->caps.port_type[i];
}
/* FW not supporting or cancelled by user */ if (!(dev_cap->flags2 & MLX4_DEV_CAP_FLAG2_EQE_STRIDE) ||
!(dev_cap->flags2 & MLX4_DEV_CAP_FLAG2_CQE_STRIDE)) return;
/* Must have 64B CQE_EQE enabled by FW to use bigger stride *WhenFWhasNCSIitmaydecidenottoreport64BCQE/EQEs
*/ if (!(dev_cap->flags & MLX4_DEV_CAP_FLAG_64B_EQE) ||
!(dev_cap->flags & MLX4_DEV_CAP_FLAG_64B_CQE)) {
dev_cap->flags2 &= ~MLX4_DEV_CAP_FLAG2_CQE_STRIDE;
dev_cap->flags2 &= ~MLX4_DEV_CAP_FLAG2_EQE_STRIDE; return;
}
if (cache_line_size() == 128 || cache_line_size() == 256) {
mlx4_dbg(dev, "Enabling CQE stride cacheLine supported\n"); /* Changing the real data inside CQE size to 32B */
dev_cap->flags &= ~MLX4_DEV_CAP_FLAG_64B_CQE;
dev_cap->flags &= ~MLX4_DEV_CAP_FLAG_64B_EQE;
if (dev_cap->min_page_sz > PAGE_SIZE) {
mlx4_err(dev, "HCA minimum page size of %d bigger than kernel PAGE_SIZE of %ld, aborting\n",
dev_cap->min_page_sz, PAGE_SIZE); return -ENODEV;
} if (dev_cap->num_ports > MLX4_MAX_PORTS) {
mlx4_err(dev, "HCA has %d ports, but we only support %d, aborting\n",
dev_cap->num_ports, MLX4_MAX_PORTS); return -ENODEV;
}
if (dev_cap->uar_size > pci_resource_len(dev->persist->pdev, 2)) {
mlx4_err(dev, "HCA reported UAR size of 0x%x bigger than PCI resource 2 size of 0x%llx, aborting\n",
dev_cap->uar_size,
(unsignedlonglong)
pci_resource_len(dev->persist->pdev, 2)); return -ENODEV;
}
dev->caps.num_ports = dev_cap->num_ports;
dev->caps.num_sys_eqs = dev_cap->num_sys_eqs;
dev->phys_caps.num_phys_eqs = dev_cap->flags2 & MLX4_DEV_CAP_FLAG2_SYS_EQS ?
dev->caps.num_sys_eqs :
MLX4_MAX_EQ_NUM; for (i = 1; i <= dev->caps.num_ports; ++i) {
err = _mlx4_dev_port(dev, i, dev_cap->port_cap + i); if (err) {
mlx4_err(dev, "QUERY_PORT command failed, aborting\n"); return err;
}
}
/* Save uar page shift */ if (!mlx4_is_slave(dev)) { /* Virtual PCI function needs to determine UAR page size from *firmware.OnlymasterPCIfunctioncansettheuarpagesize
*/ if (enable_4k_uar || !dev->persist->num_vfs)
dev->uar_page_shift = DEFAULT_UAR_PAGE_SHIFT; else
dev->uar_page_shift = PAGE_SHIFT;
mlx4_set_num_reserved_uars(dev, dev_cap);
}
if (dev->caps.flags2 & MLX4_DEV_CAP_FLAG2_PHV_EN) { struct mlx4_init_hca_param hca_param;
memset(&hca_param, 0, sizeof(hca_param));
err = mlx4_QUERY_HCA(dev, &hca_param); /* Turn off PHV_EN flag in case phv_check_en is set. *phv_check_enisaHWcheckthatparsethepacketandverify *phvbitwasreportedcorrectlyinthewqe.ToallowQinQ *PHV_ENflagshouldbesetandphv_check_enmustbecleared *otherwiseQinQpacketswillbedropbytheHW.
*/ if (err || hca_param.phv_check_en)
dev->caps.flags2 &= ~MLX4_DEV_CAP_FLAG2_PHV_EN;
}
/* 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; /* Don't do sense port on multifunction devices (for now at least) */ if (mlx4_is_mfunc(dev))
dev->caps.flags &= ~MLX4_DEV_CAP_FLAG_SENSE_SUPPORT;
for (i = 1; i <= dev->caps.num_ports; ++i) {
dev->caps.port_type[i] = MLX4_PORT_TYPE_NONE; if (dev->caps.supported_type[i]) { /* if only ETH is supported - assign ETH */ if (dev->caps.supported_type[i] == MLX4_PORT_TYPE_ETH)
dev->caps.port_type[i] = MLX4_PORT_TYPE_ETH; /* if only IB is supported, assign IB */ elseif (dev->caps.supported_type[i] ==
MLX4_PORT_TYPE_IB)
dev->caps.port_type[i] = MLX4_PORT_TYPE_IB; else { /* if IB and ETH are supported, we set the port *typeaccordingtouserselectionofporttype;
* if user selected none, take the FW hint */ if (port_type_array[i - 1] == MLX4_PORT_TYPE_NONE)
dev->caps.port_type[i] = dev->caps.suggested_type[i] ?
MLX4_PORT_TYPE_ETH : MLX4_PORT_TYPE_IB; else
dev->caps.port_type[i] = port_type_array[i - 1];
}
} /* *Linksensingisallowedontheportif3conditionsaretrue: *1.Bothprotocolsaresupportedontheport. *2.Differenttypesaresupportedontheport *3.FWdeclaredthatitsupportslinksensing
*/
mlx4_priv(dev)->sense.sense_allowed[i] =
((dev->caps.supported_type[i] == MLX4_PORT_TYPE_AUTO) &&
(dev->caps.flags & MLX4_DEV_CAP_FLAG_DPDP) &&
(dev->caps.flags & MLX4_DEV_CAP_FLAG_SENSE_SUPPORT));
if (dev->caps.log_num_macs > dev_cap->port_cap[i].log_max_macs) {
dev->caps.log_num_macs = dev_cap->port_cap[i].log_max_macs;
mlx4_warn(dev, "Requested number of MACs is too much for port %d, reducing to %d\n",
i, 1 << dev->caps.log_num_macs);
} if (dev->caps.log_num_vlans > dev_cap->port_cap[i].log_max_vlans) {
dev->caps.log_num_vlans = dev_cap->port_cap[i].log_max_vlans;
mlx4_warn(dev, "Requested number of VLANs is too much for port %d, reducing to %d\n",
i, 1 << dev->caps.log_num_vlans);
}
}
if (mlx4_is_master(dev) && (dev->caps.num_ports == 2) &&
(port_type_array[0] == MLX4_PORT_TYPE_IB) &&
(port_type_array[1] == MLX4_PORT_TYPE_ETH)) {
mlx4_warn(dev, "Granular QoS per VF not supported with IB/Eth configuration\n");
dev->caps.flags2 &= ~MLX4_DEV_CAP_FLAG2_QOS_VPP;
}
if (!enable_64b_cqe_eqe && !mlx4_is_slave(dev)) { if (dev_cap->flags &
(MLX4_DEV_CAP_FLAG_64B_CQE | MLX4_DEV_CAP_FLAG_64B_EQE)) {
mlx4_warn(dev, "64B EQEs/CQEs supported by the device but not enabled\n");
dev->caps.flags &= ~MLX4_DEV_CAP_FLAG_64B_CQE;
dev->caps.flags &= ~MLX4_DEV_CAP_FLAG_64B_EQE;
}
if (dev_cap->flags2 &
(MLX4_DEV_CAP_FLAG2_CQE_STRIDE |
MLX4_DEV_CAP_FLAG2_EQE_STRIDE)) {
mlx4_warn(dev, "Disabling EQE/CQE stride per user request\n");
dev_cap->flags2 &= ~MLX4_DEV_CAP_FLAG2_CQE_STRIDE;
dev_cap->flags2 &= ~MLX4_DEV_CAP_FLAG2_EQE_STRIDE;
}
}
/*The function checks if there are live vf, return the num of them*/ staticint mlx4_how_many_lives_vf(struct mlx4_dev *dev)
{ struct mlx4_priv *priv = mlx4_priv(dev); struct mlx4_slave_state *s_state; int i; int ret = 0;
for (i = 1/*the ppf is 0*/; i < dev->num_slaves; ++i) {
s_state = &priv->mfunc.master.slave_state[i]; if (s_state->active && s_state->last_cmd !=
MLX4_COMM_CMD_RESET) {
mlx4_warn(dev, "%s: slave: %d is still active\n",
__func__, i);
ret++;
}
} return ret;
}
void mlx4_sync_pkey_table(struct mlx4_dev *dev, int slave, int port, int i, int val)
{ struct mlx4_priv *priv = container_of(dev, struct mlx4_priv, dev);
if (!func_cap || !caps->spec_qps) {
mlx4_err(dev, "Failed to allocate memory for special qps cap\n");
err = -ENOMEM; goto err_mem;
}
for (i = 1; i <= caps->num_ports; ++i) {
err = mlx4_QUERY_FUNC_CAP(dev, i, func_cap); if (err) {
mlx4_err(dev, "QUERY_FUNC_CAP port command failed for port %d, aborting (%d)\n",
i, err); goto err_mem;
}
caps->spec_qps[i - 1] = func_cap->spec_qps;
caps->port_mask[i] = caps->port_type[i];
caps->phys_port_id[i] = func_cap->phys_port_id;
err = mlx4_get_slave_pkey_gid_tbl_len(dev, i,
&caps->gid_table_len[i],
&caps->pkey_table_len[i]); if (err) {
mlx4_err(dev, "QUERY_PORT command failed for port %d, aborting (%d)\n",
i, err); goto err_mem;
}
}
err_mem: if (err)
mlx4_slave_destroy_special_qp_cap(dev);
kfree(func_cap); return err;
}
/* fail if the hca has an unknown global capability *atthistimeglobal_capsshouldbealwayszeroed
*/ if (hca_param->global_caps) {
mlx4_err(dev, "Unknown hca global capabilities\n");
err = -EINVAL; goto free_mem;
}
err = mlx4_QUERY_FW(dev); if (err)
mlx4_err(dev, "QUERY_FW command failed: could not get FW version\n");
page_size = ~dev->caps.page_size_cap + 1;
mlx4_warn(dev, "HCA minimum page size:%d\n", page_size); if (page_size > PAGE_SIZE) {
mlx4_err(dev, "HCA minimum page size of %d bigger than kernel PAGE_SIZE of %ld, aborting\n",
page_size, PAGE_SIZE);
err = -ENODEV; goto free_mem;
}
/* Set uar_page_shift for VF */
dev->uar_page_shift = hca_param->uar_page_sz + 12;
/* Make sure the master uar page size is valid */ if (dev->uar_page_shift > PAGE_SHIFT) {
mlx4_err(dev, "Invalid configuration: uar page size is larger than system page size\n");
err = -ENODEV; goto free_mem;
}
/* Set reserved_uars based on the uar_page_shift */
mlx4_set_num_reserved_uars(dev, dev_cap);
/* Although uar page size in FW differs from system page size, *uppersoftwarelayers(mlx4_ib,mlx4_enandpartofmlx4_core) *stillworkswithassumptionthatuarpagesize==systempagesize
*/
dev->caps.uar_page_size = PAGE_SIZE;
err = mlx4_QUERY_FUNC_CAP(dev, 0, func_cap); if (err) {
mlx4_err(dev, "QUERY_FUNC_CAP general command failed, aborting (%d)\n",
err); goto free_mem;
}
if (dev->caps.num_ports > MLX4_MAX_PORTS) {
mlx4_err(dev, "HCA has %d ports, but we only support %d, aborting\n",
dev->caps.num_ports, MLX4_MAX_PORTS);
err = -ENODEV; goto free_mem;
}
mlx4_replace_zero_macs(dev);
err = mlx4_slave_special_qp_cap(dev); if (err) {
mlx4_err(dev, "Set special QP caps failed. aborting\n"); goto free_mem;
}
if (dev->caps.uar_page_size * (dev->caps.num_uars -
dev->caps.reserved_uars) >
pci_resource_len(dev->persist->pdev, 2)) {
mlx4_err(dev, "HCA reported UAR region size of 0x%x bigger than PCI resource 2 size of 0x%llx, aborting\n",
dev->caps.uar_page_size * dev->caps.num_uars,
(unsignedlonglong)
pci_resource_len(dev->persist->pdev, 2));
err = -ENOMEM; goto err_mem;
}
if (hca_param->dev_cap_enabled & MLX4_DEV_CAP_CQE_STRIDE_ENABLED) {
dev->caps.cqe_size = hca_param->cqe_size; /* User still need to know when CQE > 32B */
dev->caps.userspace_caps |= MLX4_USER_DEV_CAP_LARGE_CQE;
}
dev->caps.flags2 &= ~MLX4_DEV_CAP_FLAG2_TS;
mlx4_warn(dev, "Timestamping is not supported in slave mode\n");
dev->caps.flags2 &= ~MLX4_DEV_CAP_FLAG2_USER_MAC_EN;
mlx4_dbg(dev, "User MAC FW update is not supported in slave mode\n");
slave_adjust_steering_mode(dev, dev_cap, hca_param);
mlx4_dbg(dev, "RSS support for IP fragments is %s\n",
hca_param->rss_ip_frags ? "on" : "off");
if (func_cap->extra_flags & MLX4_QUERY_FUNC_FLAGS_BF_RES_QP &&
dev->caps.bf_reg_size)
dev->caps.alloc_res_qp_mask |= MLX4_RESERVE_ETH_BF_QP;
if (func_cap->extra_flags & MLX4_QUERY_FUNC_FLAGS_A0_RES_QP)
dev->caps.alloc_res_qp_mask |= MLX4_RESERVE_A0_QP;
/* *Changetheportconfigurationofthedevice. *Everyuserofthisfunctionmustholdtheportmutex.
*/ int mlx4_change_port_types(struct mlx4_dev *dev, enum mlx4_port_type *port_types)
{ int err = 0; int change = 0; int port;
for (port = 0; port < dev->caps.num_ports; port++) { /* Change the port type only if the new type is different
* from the current, and not set to Auto */ if (port_types[port] != dev->caps.port_type[port + 1])
change = 1;
} if (change) {
mlx4_unregister_device(dev); for (port = 1; port <= dev->caps.num_ports; port++) {
mlx4_CLOSE_PORT(dev, port);
dev->caps.port_type[port] = port_types[port - 1];
err = mlx4_SET_PORT(dev, port, -1); if (err) {
mlx4_err(dev, "Failed to set port %d, aborting\n",
port); goto out;
}
}
mlx4_set_port_mask(dev);
err = mlx4_register_device(dev); if (err) {
mlx4_err(dev, "Failed to register device\n"); goto out;
}
}
if ((port_type & mdev->caps.supported_type[info->port]) != port_type) {
mlx4_err(mdev, "Requested port type for port %d is not supported on this HCA\n",
info->port); return -EOPNOTSUPP;
}
/* Possible type is always the one that was delivered */
mdev->caps.possible_type[info->port] = info->tmp_type;
for (i = 0; i < mdev->caps.num_ports; i++) {
types[i] = priv->port[i+1].tmp_type ? priv->port[i+1].tmp_type :
mdev->caps.possible_type[i+1]; if (types[i] == MLX4_PORT_TYPE_AUTO)
types[i] = mdev->caps.port_type[i+1];
}
if (!(mdev->caps.flags & MLX4_DEV_CAP_FLAG_DPDP) &&
!(mdev->caps.flags & MLX4_DEV_CAP_FLAG_SENSE_SUPPORT)) { for (i = 1; i <= mdev->caps.num_ports; i++) { if (mdev->caps.possible_type[i] == MLX4_PORT_TYPE_AUTO) {
mdev->caps.possible_type[i] = mdev->caps.port_type[i];
err = -EOPNOTSUPP;
}
}
} if (err) {
mlx4_err(mdev, "Auto sensing is not supported on this HCA. Set only 'eth' or 'ib' for both ports (should be the same)\n"); goto out;
}
mlx4_do_sense_ports(mdev, new_types, types);
err = mlx4_check_port_params(mdev, new_types); if (err) goto out;
/* We are about to apply the changes after the configuration *wasverified,noneedtorememberthetemporarytypes
* any more */ for (i = 0; i < mdev->caps.num_ports; i++)
priv->port[i + 1].tmp_type = 0;
/* only single port vfs are allowed */ if (bitmap_weight_and(slaves_port1.slaves, slaves_port2.slaves,
dev->persist->num_vfs + 1) > 1) {
mlx4_warn(dev, "HA mode unsupported for dual ported VFs\n"); return -EINVAL;
}
/* number of virtual functions is number of total functions minus one *physicalfunctionforeachport.
*/
nvfs = bitmap_weight(slaves_port1.slaves, dev->persist->num_vfs + 1) +
bitmap_weight(slaves_port2.slaves, dev->persist->num_vfs + 1) - 2;
/* limit on maximum allowed VFs */ if (nvfs > MAX_MF_BOND_ALLOWED_SLAVES) {
mlx4_warn(dev, "HA mode is not supported for %d VFs (max %d are allowed)\n",
nvfs, MAX_MF_BOND_ALLOWED_SLAVES); return -EINVAL;
}
if (dev->caps.steering_mode != MLX4_STEERING_MODE_DEVICE_MANAGED) {
mlx4_warn(dev, "HA mode unsupported for NON DMFS steering\n"); return -EINVAL;
}
err = mlx4_bond_mac_table(dev); if (err) return err;
err = mlx4_bond_vlan_table(dev); if (err) goto err1;
err = mlx4_bond_fs_rules(dev); if (err) goto err2;
staticint mlx4_mf_unbond(struct mlx4_dev *dev)
{ int ret, ret1;
ret = mlx4_unbond_fs_rules(dev); if (ret)
mlx4_warn(dev, "multifunction unbond for flow rules failed (%d)\n", ret);
ret1 = mlx4_unbond_mac_table(dev); if (ret1) {
mlx4_warn(dev, "multifunction unbond for MAC table failed (%d)\n", ret1);
ret = ret1;
}
ret1 = mlx4_unbond_vlan_table(dev); if (ret1) {
mlx4_warn(dev, "multifunction unbond for VLAN table failed (%d)\n", ret1);
ret = ret1;
} return ret;
}
staticint mlx4_bond(struct mlx4_dev *dev)
{ int ret = 0; struct mlx4_priv *priv = mlx4_priv(dev);
mutex_lock(&priv->bond_mutex);
if (!mlx4_is_bonded(dev)) {
ret = mlx4_do_bond(dev, true); if (ret)
mlx4_err(dev, "Failed to bond device: %d\n", ret); if (!ret && mlx4_is_master(dev)) {
ret = mlx4_mf_bond(dev); if (ret) {
mlx4_err(dev, "bond for multifunction failed\n");
mlx4_do_bond(dev, false);
}
}
}
mutex_unlock(&priv->bond_mutex); if (!ret)
mlx4_dbg(dev, "Device is bonded\n");
return ret;
}
staticint mlx4_unbond(struct mlx4_dev *dev)
{ int ret = 0; struct mlx4_priv *priv = mlx4_priv(dev);
mutex_lock(&priv->bond_mutex);
if (mlx4_is_bonded(dev)) { int ret2 = 0;
ret = mlx4_do_bond(dev, false); if (ret)
mlx4_err(dev, "Failed to unbond device: %d\n", ret); if (mlx4_is_master(dev))
ret2 = mlx4_mf_unbond(dev); if (ret2) {
mlx4_warn(dev, "Failed to unbond device for multifunction (%d)\n", ret2);
ret = ret2;
}
}
mutex_unlock(&priv->bond_mutex); if (!ret)
mlx4_dbg(dev, "Device is unbonded\n");
if (bond->is_bonded) { if (!mlx4_is_bonded(bond->dev)) {
err = mlx4_bond(bond->dev); if (err)
mlx4_err(bond->dev, "Fail to bond device\n");
} if (!err) {
err = mlx4_port_map_set(bond->dev, &bond->port_map); if (err)
mlx4_err(bond->dev, "Fail to set port map [%d][%d]: %d\n",
bond->port_map.port1,
bond->port_map.port2, err);
}
} elseif (mlx4_is_bonded(bond->dev)) {
err = mlx4_unbond(bond->dev); if (err)
mlx4_err(bond->dev, "Fail to unbond device\n");
}
put_device(&bond->dev->persist->pdev->dev);
kfree(bond);
}
int mlx4_queue_bond_work(struct mlx4_dev *dev, int is_bonded, u8 v2p_p1,
u8 v2p_p2)
{ struct mlx4_bond *bond;
bond = kzalloc(sizeof(*bond), GFP_ATOMIC); if (!bond) return -ENOMEM;
mutex_lock(&priv->cmd.slave_cmd_mutex); if (mlx4_comm_cmd(dev, MLX4_COMM_CMD_RESET, 0, MLX4_COMM_CMD_NA_OP,
MLX4_COMM_TIME))
mlx4_warn(dev, "Failed to close slave function\n");
mutex_unlock(&priv->cmd.slave_cmd_mutex);
}
end = msecs_to_jiffies(MLX4_COMM_OFFLINE_TIME_OUT) + jiffies; while (time_before(jiffies, end)) {
comm_flags = swab32(readl((__iomem char *)priv->mfunc.comm +
MLX4_COMM_CHAN_FLAGS));
offline_bit = (comm_flags &
(u32)(1 << COMM_CHAN_OFFLINE_OFFSET)); if (!offline_bit) return0;
/* If device removal has been requested, *donotcontinueretrying.
*/ if (dev->persist->interface_state &
MLX4_INTERFACE_STATE_NOWAIT) break;
/* There are cases as part of AER/Reset flow that PF needs *around100msectoload.Wethereforesleepfor100msec *toallowothertaskstomakeuseofthatCPUduringthis *timeinterval.
*/
msleep(100);
}
mlx4_err(dev, "Communication channel is offline.\n"); return -EIO;
}
if (atomic_read(&pf_loading)) {
mlx4_warn(dev, "PF is not ready - Deferring probe\n"); return -EPROBE_DEFER;
}
mutex_lock(&priv->cmd.slave_cmd_mutex);
priv->cmd.max_cmds = 1; if (mlx4_comm_check_offline(dev)) {
mlx4_err(dev, "PF is not responsive, skipping initialization\n"); goto err_offline;
}
mlx4_reset_vf_support(dev);
mlx4_warn(dev, "Sending reset\n");
ret_from_reset = mlx4_comm_cmd(dev, MLX4_COMM_CMD_RESET, 0,
MLX4_COMM_CMD_NA_OP, MLX4_COMM_TIME); /* if we are in the middle of flr the slave will try
* NUM_OF_RESET_RETRIES times before leaving.*/ if (ret_from_reset) { if (MLX4_DELAY_RESET_SLAVE == ret_from_reset) {
mlx4_warn(dev, "slave is currently in the middle of FLR - Deferring probe\n");
mutex_unlock(&priv->cmd.slave_cmd_mutex); return -EPROBE_DEFER;
} else goto err;
}
/* check the driver version - the slave I/F revision
* must match the master's */
slave_read = swab32(readl(&priv->mfunc.comm->slave_read));
cmd_channel_ver = mlx4_comm_get_version();
if (MLX4_COMM_GET_IF_REV(cmd_channel_ver) !=
MLX4_COMM_GET_IF_REV(slave_read)) {
mlx4_err(dev, "slave driver version is not supported by the master\n"); goto err;
}
/* In case we got HCA frequency 0 - disable timestamping *toavoiddividingbyzero
*/ if (!dev->caps.hca_core_clock) {
dev->caps.flags2 &= ~MLX4_DEV_CAP_FLAG2_TS;
mlx4_err(dev, "HCA frequency is 0 - timestamping is not supported\n");
} elseif (map_internal_clock(dev)) { /* *Mapinternalclock, *incaseoffailuredisabletimestamping
*/
dev->caps.flags2 &= ~MLX4_DEV_CAP_FLAG2_TS;
mlx4_err(dev, "Failed to map internal clock. Timestamping is not supported\n");
}
}
if (dev->caps.dmfs_high_steer_mode !=
MLX4_STEERING_DMFS_A0_NOT_SUPPORTED) { if (mlx4_validate_optimized_steering(dev))
mlx4_warn(dev, "Optimized steering validation failed\n");
err = mlx4_init_pd_table(dev); if (err) {
mlx4_err(dev, "Failed to initialize protection domain table, aborting\n"); goto err_kar_unmap;
}
err = mlx4_init_xrcd_table(dev); if (err) {
mlx4_err(dev, "Failed to initialize reliable connection domain table, aborting\n"); goto err_pd_table_free;
}
err = mlx4_init_mr_table(dev); if (err) {
mlx4_err(dev, "Failed to initialize memory region table, aborting\n"); goto err_xrcd_table_free;
}
if (!mlx4_is_slave(dev)) {
err = mlx4_init_mcg_table(dev); if (err) {
mlx4_err(dev, "Failed to initialize multicast group table, aborting\n"); goto err_mr_table_free;
}
err = mlx4_config_mad_demux(dev); if (err) {
mlx4_err(dev, "Failed in config_mad_demux, aborting\n"); goto err_mcg_table_free;
}
}
err = mlx4_init_eq_table(dev); if (err) {
mlx4_err(dev, "Failed to initialize event queue table, aborting\n"); goto err_mcg_table_free;
}
err = mlx4_cmd_use_events(dev); if (err) {
mlx4_err(dev, "Failed to switch to event-driven firmware commands, aborting\n"); goto err_eq_table_free;
}
err = mlx4_NOP(dev); if (err) { if (dev->flags & MLX4_FLAG_MSI_X) {
mlx4_warn(dev, "NOP command failed to generate MSI-X interrupt IRQ %d)\n",
priv->eq_table.eq[MLX4_EQ_ASYNC].irq);
mlx4_warn(dev, "Trying again without MSI-X\n");
} else {
mlx4_err(dev, "NOP command failed to generate interrupt (IRQ %d), aborting\n",
priv->eq_table.eq[MLX4_EQ_ASYNC].irq);
mlx4_err(dev, "BIOS or ACPI interrupt routing problem?\n");
}
goto err_cmd_poll;
}
mlx4_dbg(dev, "NOP command IRQ test passed\n");
err = mlx4_init_cq_table(dev); if (err) {
mlx4_err(dev, "Failed to initialize completion queue table, aborting\n"); goto err_cmd_poll;
}
err = mlx4_init_srq_table(dev); if (err) {
mlx4_err(dev, "Failed to initialize shared receive queue table, aborting\n"); goto err_cq_table_free;
}
err = mlx4_init_qp_table(dev); if (err) {
mlx4_err(dev, "Failed to initialize queue pair table, aborting\n"); goto err_srq_table_free;
}
if (!mlx4_is_slave(dev)) {
err = mlx4_init_counters_table(dev); if (err && err != -ENOENT) {
mlx4_err(dev, "Failed to initialize counters table, aborting\n"); goto err_qp_table_free;
}
}
err = mlx4_allocate_default_counters(dev); if (err) {
mlx4_err(dev, "Failed to allocate default counters, aborting\n"); goto err_counters_table_free;
}
if (!mlx4_is_slave(dev)) { for (port = 1; port <= dev->caps.num_ports; port++) {
ib_port_default_caps = 0;
err = mlx4_get_port_ib_caps(dev, port,
&ib_port_default_caps); if (err)
mlx4_warn(dev, "failed to get port %d default ib capabilities (%d). Continuing with caps = 0\n",
port, err);
dev->caps.ib_port_def_cap[port] = ib_port_default_caps;
/* initialize per-slave default ib port capabilities */ if (mlx4_is_master(dev)) { int i; for (i = 0; i < dev->num_slaves; i++) { if (i == mlx4_master_func_num(dev)) continue;
priv->mfunc.master.slave_state[i].ib_cap_mask[port] =
ib_port_default_caps;
}
}
if (mlx4_is_mfunc(dev))
dev->caps.port_ib_mtu[port] = IB_MTU_2048; else
dev->caps.port_ib_mtu[port] = IB_MTU_4096;
err = mlx4_SET_PORT(dev, port, mlx4_is_master(dev) ?
dev->caps.pkey_table_len[port] : -1); if (err) {
mlx4_err(dev, "Failed to set port %d, aborting\n",
port); goto err_default_countes_free;
}
}
}
staticint mlx4_init_affinity_hint(struct mlx4_dev *dev, int port, int eqn)
{ int requested_cpu = 0; struct mlx4_priv *priv = mlx4_priv(dev); struct mlx4_eq *eq; int off = 0; int i;
if (eqn > dev->caps.num_comp_vectors) return -EINVAL;
for (i = 1; i < port; i++)
off += mlx4_get_eqs_per_port(dev, i);
requested_cpu = eqn - off - !!(eqn > MLX4_EQ_ASYNC);
/* Meaning EQs are shared, and this call comes from the second port */ if (requested_cpu < 0) return0;
eq = &priv->eq_table.eq[eqn];
if (!zalloc_cpumask_var(&eq->affinity_mask, GFP_KERNEL)) return -ENOMEM;
if (MLX4_IS_LEGACY_EQ_MODE(dev->caps)) {
bitmap_fill(priv->eq_table.eq[i].actv_ports.ports,
dev->caps.num_ports); /* We don't set affinity hint when there *aren'tenoughEQs
*/
} else {
set_bit(port,
priv->eq_table.eq[i].actv_ports.ports); if (mlx4_init_affinity_hint(dev, port + 1, i))
mlx4_warn(dev, "Couldn't init hint cpumask for EQ %d\n",
i);
} /* We divide the Eqs evenly between the two ports. *(dev->caps.num_comp_vectors/dev->caps.num_ports) *referstothenumberofEqsperport *(i.eeqs_per_port).Theoretically,wewouldliketo *writesomethinglike(i+1)%eqs_per_port==0. *However,sincethere'sanasynchronousEq,wehave *toskipoveritbycomparingthisconditionto *!!((i+1)>MLX4_EQ_ASYNC).
*/ if ((dev->caps.num_comp_vectors > dev->caps.num_ports) &&
((i + 1) %
(dev->caps.num_comp_vectors / dev->caps.num_ports)) ==
!!((i + 1) > MLX4_EQ_ASYNC)) /* If dev->caps.num_comp_vectors < dev->caps.num_ports, *everythingissharedanyway.
*/
port++;
}
dev->flags |= MLX4_FLAG_MSI_X;
kfree(entries); return;
}
no_msi:
dev->caps.num_comp_vectors = 1;
BUG_ON(MLX4_EQ_ASYNC >= 2); for (i = 0; i < 2; ++i) {
priv->eq_table.eq[i].irq = dev->persist->pdev->irq; if (i != MLX4_EQ_ASYNC) {
bitmap_fill(priv->eq_table.eq[i].actv_ports.ports,
dev->caps.num_ports);
}
}
}
staticint mlx4_init_port_info(struct mlx4_dev *dev, int port)
{ struct devlink *devlink = priv_to_devlink(mlx4_priv(dev)); struct mlx4_port_info *info = &mlx4_priv(dev)->port[port]; int err;
err = devl_port_register_with_ops(devlink, &info->devlink_port, port,
&mlx4_devlink_port_ops); if (err) return err;
/* Ethernet and IB drivers will normally set the port type, *butiftheyarenotbuiltsetthetypenowtoprevent *devlink_port_type_warn()fromfiring.
*/ if (!IS_ENABLED(CONFIG_MLX4_EN) &&
dev->caps.port_type[port] == MLX4_PORT_TYPE_ETH)
devlink_port_type_eth_set(&info->devlink_port); elseif (!IS_ENABLED(CONFIG_MLX4_INFINIBAND) &&
dev->caps.port_type[port] == MLX4_PORT_TYPE_IB)
devlink_port_type_ib_set(&info->devlink_port, NULL);
static u64 mlx4_enable_sriov(struct mlx4_dev *dev, struct pci_dev *pdev,
u8 total_vfs, int existing_vfs, int reset_flow)
{
u64 dev_flags = dev->flags; int err = 0; int fw_enabled_sriov_vfs = min(pci_sriov_get_totalvfs(pdev),
MLX4_MAX_NUM_VF);
if (reset_flow) {
dev->dev_vfs = kcalloc(total_vfs, sizeof(*dev->dev_vfs),
GFP_KERNEL); if (!dev->dev_vfs) goto free_mem; return dev_flags;
}
atomic_inc(&pf_loading); if (dev->flags & MLX4_FLAG_SRIOV) { if (existing_vfs != total_vfs) {
mlx4_err(dev, "SR-IOV was already enabled, but with num_vfs (%d) different than requested (%d)\n",
existing_vfs, total_vfs);
total_vfs = existing_vfs;
}
}
dev->dev_vfs = kcalloc(total_vfs, sizeof(*dev->dev_vfs), GFP_KERNEL); if (NULL == dev->dev_vfs) {
mlx4_err(dev, "Failed to allocate memory for VFs\n"); goto disable_sriov;
}
if (!(dev->flags & MLX4_FLAG_SRIOV)) { if (total_vfs > fw_enabled_sriov_vfs) {
mlx4_err(dev, "requested vfs (%d) > available vfs (%d). Continuing without SR_IOV\n",
total_vfs, fw_enabled_sriov_vfs);
err = -ENOMEM; goto disable_sriov;
}
mlx4_warn(dev, "Enabling SR-IOV with %d VFs\n", total_vfs);
err = pci_enable_sriov(pdev, total_vfs);
} if (err) {
mlx4_err(dev, "Failed to enable SR-IOV, continuing without SR-IOV (err = %d)\n",
err); goto disable_sriov;
} else {
mlx4_warn(dev, "Running in master mode\n");
dev_flags |= MLX4_FLAG_SRIOV |
MLX4_FLAG_MASTER;
dev_flags &= ~MLX4_FLAG_SLAVE;
dev->persist->num_vfs = total_vfs;
} return dev_flags;
staticint mlx4_check_dev_cap(struct mlx4_dev *dev, struct mlx4_dev_cap *dev_cap, int *nvfs)
{ int requested_vfs = nvfs[0] + nvfs[1] + nvfs[2]; /* Checking for 64 VFs as a limitation of CX2 */ if (!(dev_cap->flags2 & MLX4_DEV_CAP_FLAG2_80_VFS) &&
requested_vfs >= 64) {
mlx4_err(dev, "Requested %d VFs, but FW does not support more than 64\n",
requested_vfs); return MLX4_DEV_CAP_CHECK_NUM_VFS_ABOVE_64;
} return0;
}
staticint mlx4_load_one(struct pci_dev *pdev, int pci_dev_data, int total_vfs, int *nvfs, struct mlx4_priv *priv, int reset_flow)
{ struct devlink *devlink = priv_to_devlink(priv); struct mlx4_dev *dev; unsigned sum = 0; int err; int port; int i; struct mlx4_dev_cap *dev_cap = NULL; int existing_vfs = 0;
/* Detect if this device is a virtual function */ if (pci_dev_data & MLX4_PCI_DEV_IS_VF) {
mlx4_warn(dev, "Detected virtual function - running in slave mode\n");
dev->flags |= MLX4_FLAG_SLAVE;
} else { /* We reset the device and enable SRIOV only for physical *devices.Trytoclaimownershiponthedevice;
* if already taken, skip -- do not allow multiple PFs */
err = mlx4_get_ownership(dev); if (err) { if (err < 0) goto err_adev; else {
mlx4_warn(dev, "Multiple PFs not yet supported - Skipping PF\n");
err = -EINVAL; goto err_adev;
}
}
/* *NowresettheHCAbeforewetouchthePCIcapabilitiesor *attemptafirmwarecommand,sinceabootROMmayhaveleft *theHCAinanundefinedstate.
*/
err = mlx4_reset(dev); if (err) {
mlx4_err(dev, "Failed to reset HCA, aborting\n"); goto err_sriov;
}
if (total_vfs) {
dev->flags = MLX4_FLAG_MASTER;
existing_vfs = pci_num_vf(pdev); if (existing_vfs)
dev->flags |= MLX4_FLAG_SRIOV;
dev->persist->num_vfs = total_vfs;
}
}
/* on load remove any previous indication of internal error, *deviceisup.
*/
dev->persist->state = MLX4_DEVICE_STATE_UP;
slave_start:
err = mlx4_cmd_init(dev); if (err) {
mlx4_err(dev, "Failed to init command interface, aborting\n"); goto err_sriov;
}
/* In slave functions, the communication channel must be initialized *beforepostingcommands.Also,initnum_slavesbeforecalling
* mlx4_init_hca */ if (mlx4_is_mfunc(dev)) { if (mlx4_is_master(dev)) {
dev->num_slaves = MLX4_MAX_NUM_SLAVES;
err = mlx4_init_fw(dev); if (err) {
mlx4_err(dev, "Failed to init fw, aborting.\n"); goto err_mfunc;
}
if (mlx4_is_master(dev)) { /* when we hit the goto slave_start below, dev_cap already initialized */ if (!dev_cap) {
dev_cap = kzalloc(sizeof(*dev_cap), GFP_KERNEL);
/* check if the device is functioning at its maximum possible speed. *Noreturncodeforthiscall,justwarntheuserincaseofPCI *expressdevicecapabilitiesareunder-satisfiedbythebus.
*/ if (!mlx4_is_slave(dev))
pcie_print_link_status(dev->persist->pdev);
/* In master functions, the communication channel must be initialized
* after obtaining its address from fw */ if (mlx4_is_master(dev)) { if (dev->caps.num_ports < 2 &&
num_vfs_argc > 1) {
err = -EINVAL;
mlx4_err(dev, "Error: Trying to configure VFs on port 2, but HCA has only %d physical ports\n",
dev->caps.num_ports); goto err_close;
}
memcpy(dev->persist->nvfs, nvfs, sizeof(dev->persist->nvfs));
for (i = 0;
i < sizeof(dev->persist->nvfs)/ sizeof(dev->persist->nvfs[0]); i++) { unsigned j;
for (j = 0; j < dev->persist->nvfs[i]; ++sum, ++j) {
dev->dev_vfs[sum].min_port = i < 2 ? i + 1 : 1;
dev->dev_vfs[sum].n_ports = i < 2 ? 1 :
dev->caps.num_ports;
}
}
/* In master functions, the communication channel *mustbeinitializedafterobtainingitsaddressfromfw
*/
err = mlx4_multi_func_init(dev); if (err) {
mlx4_err(dev, "Failed to init master mfunc interface, aborting.\n"); goto err_close;
}
}
err = mlx4_alloc_eq_table(dev); if (err) goto err_master_mfunc;
/* When PF resources are ready arm its comm channel to enable *gettingcommands
*/ if (mlx4_is_master(dev)) {
err = mlx4_ARM_COMM_CHANNEL(dev); if (err) {
mlx4_err(dev, " Failed to arm comm channel eq: %x\n",
err); goto err_steer;
}
}
for (port = 1; port <= dev->caps.num_ports; port++) {
err = mlx4_init_port_info(dev, port); if (err) goto err_port;
}
priv->v2p.port1 = 1;
priv->v2p.port2 = 2;
err = mlx4_register_device(dev); if (err) goto err_port;
mlx4_sense_init(dev);
mlx4_start_sense(dev);
priv->removed = 0;
if (mlx4_is_master(dev) && dev->persist->num_vfs && !reset_flow)
atomic_dec(&pf_loading);
kfree(dev_cap); return0;
err_port: for (--port; port >= 1; --port)
mlx4_cleanup_port_info(&priv->port[port]);
/* Due to requirement that all VFs and the PF are *guaranteed* 2 MACS *perport,wemustlimitthenumberofVFsto63(sincetheirare *128MACs)
*/ for (i = 0; i < ARRAY_SIZE(nvfs) && i < num_vfs_argc;
total_vfs += nvfs[param_map[num_vfs_argc - 1][i]], i++) {
nvfs[param_map[num_vfs_argc - 1][i]] = num_vfs[i]; if (nvfs[i] < 0) {
dev_err(&pdev->dev, "num_vfs module parameter cannot be negative\n");
err = -EINVAL; goto err_disable_pdev;
}
} for (i = 0; i < ARRAY_SIZE(prb_vf) && i < probe_vfs_argc;
i++) {
prb_vf[param_map[probe_vfs_argc - 1][i]] = probe_vf[i]; if (prb_vf[i] < 0 || prb_vf[i] > nvfs[i]) {
dev_err(&pdev->dev, "probe_vf module parameter cannot be negative or greater than num_vfs\n");
err = -EINVAL; goto err_disable_pdev;
}
} if (total_vfs > MLX4_MAX_NUM_VF) {
dev_err(&pdev->dev, "Requested more VF's (%d) than allowed by hw (%d)\n",
total_vfs, MLX4_MAX_NUM_VF);
err = -EINVAL; goto err_disable_pdev;
}
for (i = 0; i < MLX4_MAX_PORTS; i++) { if (nvfs[i] + nvfs[2] > MLX4_MAX_NUM_VF_P_PORT) {
dev_err(&pdev->dev, "Requested more VF's (%d) for port (%d) than allowed by driver (%d)\n",
nvfs[i] + nvfs[2], i + 1,
MLX4_MAX_NUM_VF_P_PORT);
err = -EINVAL; goto err_disable_pdev;
}
}
err = pci_request_regions(pdev, DRV_NAME); if (err) {
dev_err(&pdev->dev, "Couldn't get PCI resources, aborting\n"); goto err_disable_pdev;
}
pci_set_master(pdev);
err = dma_set_mask_and_coherent(&pdev->dev, DMA_BIT_MASK(64)); if (err) {
dev_warn(&pdev->dev, "Warning: couldn't set 64-bit PCI DMA mask\n");
err = dma_set_mask_and_coherent(&pdev->dev, DMA_BIT_MASK(32)); if (err) {
dev_err(&pdev->dev, "Can't set PCI DMA mask, aborting\n"); goto err_release_regions;
}
}
/* Allow large DMA segments, up to the firmware limit of 1 GB */
dma_set_max_seg_size(&pdev->dev, 1024 * 1024 * 1024); /* Detect if this device is a virtual function */ if (pci_dev_data & MLX4_PCI_DEV_IS_VF) { /* When acting as pf, we normally skip vfs unless explicitly *requestedtoprobethem.
*/ if (total_vfs) { unsigned vfs_offset = 0;
for (i = 0; i < ARRAY_SIZE(nvfs) &&
vfs_offset + nvfs[i] < extended_func_num(pdev);
vfs_offset += nvfs[i], i++)
; if (i == ARRAY_SIZE(nvfs)) {
err = -ENODEV; goto err_release_regions;
} if ((extended_func_num(pdev) - vfs_offset)
> prb_vf[i]) {
dev_warn(&pdev->dev, "Skipping virtual function:%d\n",
extended_func_num(pdev));
err = -ENODEV; goto err_release_regions;
}
}
}
err = mlx4_crdump_init(&priv->dev); if (err) goto err_release_regions;
err = mlx4_catas_init(&priv->dev); if (err) goto err_crdump;
if (netns_change) {
NL_SET_ERR_MSG_MOD(extack, "Namespace change is not supported"); return -EOPNOTSUPP;
} if (persist->num_vfs)
mlx4_warn(persist->dev, "Reload performed on PF, will cause reset on operating Virtual Functions\n");
mlx4_restart_one_down(persist->pdev); return0;
}
dev = &priv->dev;
dev->persist = kzalloc(sizeof(*dev->persist), GFP_KERNEL); if (!dev->persist) {
ret = -ENOMEM; goto err_devlink_free;
}
dev->persist->pdev = pdev;
dev->persist->dev = dev;
pci_set_drvdata(pdev, dev->persist);
priv->pci_dev_data = id->driver_data;
mutex_init(&dev->persist->device_state_mutex);
mutex_init(&dev->persist->interface_state_mutex);
mutex_init(&dev->persist->pci_status_mutex);
ret = devl_params_register(devlink, mlx4_devlink_params,
ARRAY_SIZE(mlx4_devlink_params)); if (ret) goto err_devlink_unregister;
mlx4_devlink_set_params_init_values(devlink);
ret = __mlx4_init_one(pdev, id->driver_data, priv); if (ret) goto err_params_unregister;
devlink = priv_to_devlink(priv);
devl_assert_locked(devlink); if (priv->removed) return;
/* saving current ports type for further use */ for (i = 0; i < dev->caps.num_ports; i++) {
dev->persist->curr_port_type[i] = dev->caps.port_type[i + 1];
dev->persist->curr_port_poss_type[i] = dev->caps.
possible_type[i + 1];
}
/* Disabling SR-IOV is not allowed while there are active vf's */ if (mlx4_is_master(dev) && dev->flags & MLX4_FLAG_SRIOV) {
active_vfs = mlx4_how_many_lives_vf(dev); if (active_vfs) {
pr_warn("Removing PF when there are active VF's !!\n");
pr_warn("Will not disable SR-IOV.\n");
}
}
/* device marked to be under deletion running now without the lock *lettingothertaskstobeterminated
*/ if (persist->interface_state & MLX4_INTERFACE_STATE_UP)
mlx4_unload_one(pdev); else
mlx4_info(dev, "%s: interface is down\n", __func__);
mlx4_catas_end(dev);
mlx4_crdump_end(dev); if (dev->flags & MLX4_FLAG_SRIOV && !active_vfs) {
mlx4_warn(dev, "Disabling SR-IOV\n");
pci_disable_sriov(pdev);
}
err = restore_current_port_types(dev, dev->persist->curr_port_type,
dev->persist->curr_port_poss_type); if (err)
mlx4_err(dev, "could not restore original port types (%d)\n",
err);
mlx4_err(dev, "resume was called\n");
total_vfs = dev->persist->num_vfs;
memcpy(nvfs, dev->persist->nvfs, sizeof(dev->persist->nvfs));
devlink = priv_to_devlink(priv);
devl_lock(devlink);
mutex_lock(&persist->interface_state_mutex); if (!(persist->interface_state & MLX4_INTERFACE_STATE_UP)) {
ret = mlx4_load_one(pdev, priv->pci_dev_data, total_vfs,
nvfs, priv, 1); if (!ret) {
ret = restore_current_port_types(dev,
dev->persist->curr_port_type,
dev->persist->curr_port_poss_type); if (ret)
mlx4_err(dev, "resume: could not restore original port types (%d)\n", ret);
}
}
mutex_unlock(&persist->interface_state_mutex);
devl_unlock(devlink);
if ((log_mtts_per_seg < 0) || (log_mtts_per_seg > 7)) {
pr_warn("mlx4_core: bad log_mtts_per_seg: %d\n",
log_mtts_per_seg); return -1;
}
/* Check if module param for ports type has legal combination */ if (port_type_array[0] == false && port_type_array[1] == true) {
pr_warn("Module parameter configuration ETH/IB is not supported. Switching to default configuration IB/IB\n");
port_type_array[0] = true;
}
if (mlx4_log_num_mgm_entry_size < -7 ||
(mlx4_log_num_mgm_entry_size > 0 &&
(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_warn("mlx4_core: mlx4_log_num_mgm_entry_size (%d) not in legal range (-7..0 or %d..%d)\n",
mlx4_log_num_mgm_entry_size,
MLX4_MIN_MGM_LOG_ENTRY_SIZE,
MLX4_MAX_MGM_LOG_ENTRY_SIZE); return -1;
}
return0;
}
staticint __init mlx4_init(void)
{ int ret;
WARN_ONCE(strcmp(MLX4_ADEV_NAME, KBUILD_MODNAME), "mlx4_core name not in sync with kernel module name");
if (mlx4_verify_params()) return -EINVAL;
mlx4_wq = create_singlethread_workqueue("mlx4"); if (!mlx4_wq) return -ENOMEM;
ret = pci_register_driver(&mlx4_driver); if (ret < 0)
destroy_workqueue(mlx4_wq); return ret < 0 ? ret : 0;
}
¤ Die Informationen auf dieser Webseite wurden
nach bestem Wissen sorgfältig zusammengestellt. Es wird jedoch weder Vollständigkeit, noch Richtigkeit,
noch Qualität der bereit gestellten Informationen zugesichert.0.142Angebot
(Wie Sie bei der Firma Beratungs- und Dienstleistungen beauftragen können 2026-10-12)
¤
Die Informationen auf dieser Webseite wurden
nach bestem Wissen sorgfältig zusammengestellt. Es wird jedoch weder Vollständigkeit, noch Richtigkeit,
noch Qualität der bereit gestellten Informationen zugesichert.
Bemerkung:
Die farbliche Syntaxdarstellung und die Messung sind noch experimentell.