Skip to content

Commit 604774a

Browse files
committed
net/mlx5: Dynamically assign MSI-X vectors count
The number of MSI-X vectors is a PCI property visible through lspci. The field is read-only and configured by the device. The mlx5 devices work in a static or dynamic assignment mode. Static assignment means that all newly created VFs have a preset number of MSI-X vectors determined by device configuration parameters. This can result in some VFs having too many or too few MSI-X vectors. Till now this has been the only means of fine-tuning the MSI-X vector count and it was acceptable for small numbers of VFs. With dynamic assignment the inefficiency of having a fixed number of MSI-X vectors can be avoided with each VF having exactly the required vectors. Userspace will provide this information while provisioning the VF for use, based on the intended use. For instance if being used with a VM, the MSI-X vector count might be matched to the CPU count of the VM. For compatibility mlx5 continues to start up with MSI-X vector assignment, but the kernel can now access a larger dynamic vector pool and assign more vectors to created VFs. Link: https://lore.kernel.org/linux-pci/[email protected] Acked-by: Bjorn Helgaas <[email protected]> Signed-off-by: Leon Romanovsky <[email protected]>
1 parent 0b989c1 commit 604774a

File tree

4 files changed

+93
-2
lines changed

4 files changed

+93
-2
lines changed

drivers/net/ethernet/mellanox/mlx5/core/main.c

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -571,6 +571,10 @@ static int handle_hca_cap(struct mlx5_core_dev *dev, void *set_ctx)
571571

572572
mlx5_vhca_state_cap_handle(dev, set_hca_cap);
573573

574+
if (MLX5_CAP_GEN_MAX(dev, num_total_dynamic_vf_msix))
575+
MLX5_SET(cmd_hca_cap, set_hca_cap, num_total_dynamic_vf_msix,
576+
MLX5_CAP_GEN_MAX(dev, num_total_dynamic_vf_msix));
577+
574578
return set_caps(dev, set_ctx, MLX5_SET_HCA_CAP_OP_MOD_GENERAL_DEVICE);
575579
}
576580

drivers/net/ethernet/mellanox/mlx5/core/mlx5_core.h

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -174,6 +174,11 @@ int mlx5_irq_attach_nb(struct mlx5_irq_table *irq_table, int vecidx,
174174
struct notifier_block *nb);
175175
int mlx5_irq_detach_nb(struct mlx5_irq_table *irq_table, int vecidx,
176176
struct notifier_block *nb);
177+
178+
int mlx5_set_msix_vec_count(struct mlx5_core_dev *dev, int devfn,
179+
int msix_vec_count);
180+
int mlx5_get_default_msix_vec_count(struct mlx5_core_dev *dev, int num_vfs);
181+
177182
struct cpumask *
178183
mlx5_irq_get_affinity_mask(struct mlx5_irq_table *irq_table, int vecidx);
179184
struct cpu_rmap *mlx5_irq_get_rmap(struct mlx5_irq_table *table);

drivers/net/ethernet/mellanox/mlx5/core/pci_irq.c

Lines changed: 73 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -61,6 +61,79 @@ static struct mlx5_irq *mlx5_irq_get(struct mlx5_core_dev *dev, int vecidx)
6161
return &irq_table->irq[vecidx];
6262
}
6363

64+
/**
65+
* mlx5_get_default_msix_vec_count - Get the default number of MSI-X vectors
66+
* to be ssigned to each VF.
67+
* @dev: PF to work on
68+
* @num_vfs: Number of enabled VFs
69+
*/
70+
int mlx5_get_default_msix_vec_count(struct mlx5_core_dev *dev, int num_vfs)
71+
{
72+
int num_vf_msix, min_msix, max_msix;
73+
74+
num_vf_msix = MLX5_CAP_GEN_MAX(dev, num_total_dynamic_vf_msix);
75+
if (!num_vf_msix)
76+
return 0;
77+
78+
min_msix = MLX5_CAP_GEN(dev, min_dynamic_vf_msix_table_size);
79+
max_msix = MLX5_CAP_GEN(dev, max_dynamic_vf_msix_table_size);
80+
81+
/* Limit maximum number of MSI-X vectors so the default configuration
82+
* has some available in the pool. This will allow the user to increase
83+
* the number of vectors in a VF without having to first size-down other
84+
* VFs.
85+
*/
86+
return max(min(num_vf_msix / num_vfs, max_msix / 2), min_msix);
87+
}
88+
89+
/**
90+
* mlx5_set_msix_vec_count - Set dynamically allocated MSI-X on the VF
91+
* @dev: PF to work on
92+
* @function_id: Internal PCI VF function IDd
93+
* @msix_vec_count: Number of MSI-X vectors to set
94+
*/
95+
int mlx5_set_msix_vec_count(struct mlx5_core_dev *dev, int function_id,
96+
int msix_vec_count)
97+
{
98+
int sz = MLX5_ST_SZ_BYTES(set_hca_cap_in);
99+
int num_vf_msix, min_msix, max_msix;
100+
void *hca_cap, *cap;
101+
int ret;
102+
103+
num_vf_msix = MLX5_CAP_GEN_MAX(dev, num_total_dynamic_vf_msix);
104+
if (!num_vf_msix)
105+
return 0;
106+
107+
if (!MLX5_CAP_GEN(dev, vport_group_manager) || !mlx5_core_is_pf(dev))
108+
return -EOPNOTSUPP;
109+
110+
min_msix = MLX5_CAP_GEN(dev, min_dynamic_vf_msix_table_size);
111+
max_msix = MLX5_CAP_GEN(dev, max_dynamic_vf_msix_table_size);
112+
113+
if (msix_vec_count < min_msix)
114+
return -EINVAL;
115+
116+
if (msix_vec_count > max_msix)
117+
return -EOVERFLOW;
118+
119+
hca_cap = kzalloc(sz, GFP_KERNEL);
120+
if (!hca_cap)
121+
return -ENOMEM;
122+
123+
cap = MLX5_ADDR_OF(set_hca_cap_in, hca_cap, capability);
124+
MLX5_SET(cmd_hca_cap, cap, dynamic_msix_table_size, msix_vec_count);
125+
126+
MLX5_SET(set_hca_cap_in, hca_cap, opcode, MLX5_CMD_OP_SET_HCA_CAP);
127+
MLX5_SET(set_hca_cap_in, hca_cap, other_function, 1);
128+
MLX5_SET(set_hca_cap_in, hca_cap, function_id, function_id);
129+
130+
MLX5_SET(set_hca_cap_in, hca_cap, op_mod,
131+
MLX5_SET_HCA_CAP_OP_MOD_GENERAL_DEVICE << 1);
132+
ret = mlx5_cmd_exec_in(dev, set_hca_cap, hca_cap);
133+
kfree(hca_cap);
134+
return ret;
135+
}
136+
64137
int mlx5_irq_attach_nb(struct mlx5_irq_table *irq_table, int vecidx,
65138
struct notifier_block *nb)
66139
{

drivers/net/ethernet/mellanox/mlx5/core/sriov.c

Lines changed: 11 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -71,8 +71,7 @@ static int sriov_restore_guids(struct mlx5_core_dev *dev, int vf)
7171
static int mlx5_device_enable_sriov(struct mlx5_core_dev *dev, int num_vfs)
7272
{
7373
struct mlx5_core_sriov *sriov = &dev->priv.sriov;
74-
int err;
75-
int vf;
74+
int err, vf, num_msix_count;
7675

7776
if (!MLX5_ESWITCH_MANAGER(dev))
7877
goto enable_vfs_hca;
@@ -85,12 +84,22 @@ static int mlx5_device_enable_sriov(struct mlx5_core_dev *dev, int num_vfs)
8584
}
8685

8786
enable_vfs_hca:
87+
num_msix_count = mlx5_get_default_msix_vec_count(dev, num_vfs);
8888
for (vf = 0; vf < num_vfs; vf++) {
8989
err = mlx5_core_enable_hca(dev, vf + 1);
9090
if (err) {
9191
mlx5_core_warn(dev, "failed to enable VF %d (%d)\n", vf, err);
9292
continue;
9393
}
94+
95+
err = mlx5_set_msix_vec_count(dev, vf + 1, num_msix_count);
96+
if (err) {
97+
mlx5_core_warn(dev,
98+
"failed to set MSI-X vector counts VF %d, err %d\n",
99+
vf, err);
100+
continue;
101+
}
102+
94103
sriov->vfs_ctx[vf].enabled = 1;
95104
if (MLX5_CAP_GEN(dev, port_type) == MLX5_CAP_PORT_TYPE_IB) {
96105
err = sriov_restore_guids(dev, vf);

0 commit comments

Comments
 (0)