Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux

net/mlx4_core: Fix number of EQs used in ICM initialisation

In SRIOV mode, the number of EQs used when computing the total ICM size
was incorrect.

To fix this, we do the following:
1. We add a new structure to mlx4_dev, mlx4_phys_caps, to contain physical HCA
capabilities. The PPF uses the phys capabilities when it computes things
like ICM size.

The dev_caps structure will then contain the paravirtualized values, making
bookkeeping much easier in SRIOV mode. We add a structure rather than a
single parameter because there will be other fields in the phys_caps.

The first field we add to the mlx4_phys_caps structure is num_phys_eqs.

2. In INIT_HCA, when running in SRIOV mode, the "log_num_eqs" parameter
passed to the FW is the number of EQs per VF/PF; each function (PF or VF)
has this number of EQs available.

However, the total number of EQs which must be allowed for in the ICM is
(1 << log_num_eqs) * (#VFs + #PFs). Rather than compute this quantity,
we allocate ICM space for 1024 EQs (which is the device maximum
number of EQs, and which is the value we place in the mlx4_phys_caps structure).

For INIT_HCA, however, we use the per-function number of EQs as described
above.

Signed-off-by: Marcel Apfelbaum <marcela@dev.mellanox.co.il>
Signed-off-by: Jack Morgenstein <jackm@dev.mellanox.co.il>
Reviewed-by: Or Gerlitz <ogerlitz@mellanox.com>
Signed-off-by: David S. Miller <davem@davemloft.net>

authored by

Marcel Apfelbaum and committed by
David S. Miller
3fc929e2 30f7c73b

+17 -15
+5 -12
drivers/net/ethernet/mellanox/mlx4/main.c
··· 142 142 struct pci_dev *pdev; 143 143 }; 144 144 145 - static inline int mlx4_master_get_num_eqs(struct mlx4_dev *dev) 146 - { 147 - return dev->caps.reserved_eqs + 148 - MLX4_MFUNC_EQ_NUM * (dev->num_slaves + 1); 149 - } 150 - 151 145 int mlx4_check_port_params(struct mlx4_dev *dev, 152 146 enum mlx4_port_type *port_type) 153 147 { ··· 211 217 } 212 218 213 219 dev->caps.num_ports = dev_cap->num_ports; 220 + dev->phys_caps.num_phys_eqs = MLX4_MAX_EQ_NUM; 214 221 for (i = 1; i <= dev->caps.num_ports; ++i) { 215 222 dev->caps.vl_cap[i] = dev_cap->max_vl[i]; 216 223 dev->caps.ib_mtu_cap[i] = dev_cap->ib_mtu[i]; ··· 805 810 if (err) 806 811 goto err_srq; 807 812 808 - num_eqs = (mlx4_is_master(dev)) ? 809 - roundup_pow_of_two(mlx4_master_get_num_eqs(dev)) : 810 - dev->caps.num_eqs; 813 + num_eqs = (mlx4_is_master(dev)) ? dev->phys_caps.num_phys_eqs : 814 + dev->caps.num_eqs; 811 815 err = mlx4_init_icm_table(dev, &priv->eq_table.cmpt_table, 812 816 cmpt_base + 813 817 ((u64) (MLX4_CMPT_TYPE_EQ * ··· 868 874 } 869 875 870 876 871 - num_eqs = (mlx4_is_master(dev)) ? 872 - roundup_pow_of_two(mlx4_master_get_num_eqs(dev)) : 873 - dev->caps.num_eqs; 877 + num_eqs = (mlx4_is_master(dev)) ? dev->phys_caps.num_phys_eqs : 878 + dev->caps.num_eqs; 874 879 err = mlx4_init_icm_table(dev, &priv->eq_table.table, 875 880 init_hca->eqc_base, dev_cap->eqc_entry_sz, 876 881 num_eqs, num_eqs, 0, 0);
+6 -3
drivers/net/ethernet/mellanox/mlx4/profile.c
··· 126 126 profile[MLX4_RES_AUXC].num = request->num_qp; 127 127 profile[MLX4_RES_SRQ].num = request->num_srq; 128 128 profile[MLX4_RES_CQ].num = request->num_cq; 129 - profile[MLX4_RES_EQ].num = min_t(unsigned, dev_cap->max_eqs, MAX_MSIX); 129 + profile[MLX4_RES_EQ].num = mlx4_is_mfunc(dev) ? 130 + dev->phys_caps.num_phys_eqs : 131 + min_t(unsigned, dev_cap->max_eqs, MAX_MSIX); 130 132 profile[MLX4_RES_DMPT].num = request->num_mpt; 131 133 profile[MLX4_RES_CMPT].num = MLX4_NUM_CMPTS; 132 134 profile[MLX4_RES_MTT].num = request->num_mtt * (1 << log_mtts_per_seg); ··· 217 215 init_hca->log_num_cqs = profile[i].log_num; 218 216 break; 219 217 case MLX4_RES_EQ: 220 - dev->caps.num_eqs = profile[i].num; 218 + dev->caps.num_eqs = roundup_pow_of_two(min_t(unsigned, dev_cap->max_eqs, 219 + MAX_MSIX)); 221 220 init_hca->eqc_base = profile[i].start; 222 - init_hca->log_num_eqs = profile[i].log_num; 221 + init_hca->log_num_eqs = ilog2(dev->caps.num_eqs); 223 222 break; 224 223 case MLX4_RES_DMPT: 225 224 dev->caps.num_mpts = profile[i].num;
+6
include/linux/mlx4/device.h
··· 64 64 MLX4_MAX_NUM_PF = 16, 65 65 MLX4_MAX_NUM_VF = 64, 66 66 MLX4_MFUNC_MAX = 80, 67 + MLX4_MAX_EQ_NUM = 1024, 67 68 MLX4_MFUNC_EQ_NUM = 4, 68 69 MLX4_MFUNC_MAX_EQES = 8, 69 70 MLX4_MFUNC_EQE_MASK = (MLX4_MFUNC_MAX_EQES - 1) ··· 239 238 { 240 239 return (major << 32) | (minor << 16) | subminor; 241 240 } 241 + 242 + struct mlx4_phys_caps { 243 + u32 num_phys_eqs; 244 + }; 242 245 243 246 struct mlx4_caps { 244 247 u64 fw_ver; ··· 504 499 unsigned long flags; 505 500 unsigned long num_slaves; 506 501 struct mlx4_caps caps; 502 + struct mlx4_phys_caps phys_caps; 507 503 struct radix_tree_root qp_table_tree; 508 504 u8 rev_id; 509 505 char board_id[MLX4_BOARD_ID_LEN];