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

net/mlx5: Expose ICM consumption per function

ICM is a portion of the host's memory assigned to a function by the OS
through requests made by the NIC's firmware.

PF ICM consumption can be accessed directly, while VF/SF ICM consumption
can be accessed through their representors in switchdev mode.

The value is exposed to the user in granularity of 4KB through the vnic
health reporter as follows:

$ devlink health diagnose pci/0000:08:00.0 reporter vnic
vNIC env counters:
total_error_queues: 0 send_queue_priority_update_flow: 0
comp_eq_overrun: 0 async_eq_overrun: 0 cq_overrun: 0
invalid_command: 0 quota_exceeded_command: 0
nic_receive_steering_discard: 0 icm_consumption: 1032

Signed-off-by: Akiva Goldberger <agoldberger@nvidia.com>
Reviewed-by: Moshe Shemesh <moshe@nvidia.com>
Signed-off-by: Tariq Toukan <tariqt@nvidia.com>
Link: https://patch.msgid.link/20250209101716.112774-11-tariqt@nvidia.com
Signed-off-by: Jakub Kicinski <kuba@kernel.org>

authored by

Akiva Goldberger and committed by
Jakub Kicinski
b8208643 38b3d42e

+50
+4
Documentation/networking/devlink/mlx5.rst
··· 280 280 number of packets handled by the VNIC experiencing unexpected steering 281 281 failure (at any point in steering flow owned by the VNIC, including the FDB 282 282 for the eswitch owner). 283 + - icm_consumption 284 + amount of Interconnect Host Memory (ICM) consumed by the vnic in 285 + granularity of 4KB. ICM is host memory allocated by SW upon HCA request 286 + and is used for storing data structures that control HCA operation. 283 287 284 288 User commands examples: 285 289
+46
drivers/net/ethernet/mellanox/mlx5/core/diag/reporter_vnic.c
··· 13 13 __be64 query_vnic_env_out[MLX5_ST_SZ_QW(query_vnic_env_out)]; 14 14 }; 15 15 16 + static void mlx5_reporter_vnic_diagnose_counter_icm(struct mlx5_core_dev *dev, 17 + struct devlink_fmsg *fmsg, 18 + u16 vport_num, bool other_vport) 19 + { 20 + u32 out_icm_reg[MLX5_ST_SZ_DW(vhca_icm_ctrl_reg)] = {}; 21 + u32 in_icm_reg[MLX5_ST_SZ_DW(vhca_icm_ctrl_reg)] = {}; 22 + u32 out_reg[MLX5_ST_SZ_DW(nic_cap_reg)] = {}; 23 + u32 in_reg[MLX5_ST_SZ_DW(nic_cap_reg)] = {}; 24 + u32 cur_alloc_icm; 25 + int vhca_icm_ctrl; 26 + u16 vhca_id; 27 + int err; 28 + 29 + err = mlx5_core_access_reg(dev, in_reg, sizeof(in_reg), out_reg, 30 + sizeof(out_reg), MLX5_REG_NIC_CAP, 0, 0); 31 + if (err) { 32 + mlx5_core_warn(dev, "Reading nic_cap_reg failed. err = %d\n", err); 33 + return; 34 + } 35 + vhca_icm_ctrl = MLX5_GET(nic_cap_reg, out_reg, vhca_icm_ctrl); 36 + if (!vhca_icm_ctrl) 37 + return; 38 + 39 + MLX5_SET(vhca_icm_ctrl_reg, in_icm_reg, vhca_id_valid, other_vport); 40 + if (other_vport) { 41 + err = mlx5_vport_get_vhca_id(dev, vport_num, &vhca_id); 42 + if (err) { 43 + mlx5_core_warn(dev, "vport to vhca_id failed. vport_num = %d, err = %d\n", 44 + vport_num, err); 45 + return; 46 + } 47 + MLX5_SET(vhca_icm_ctrl_reg, in_icm_reg, vhca_id, vhca_id); 48 + } 49 + err = mlx5_core_access_reg(dev, in_icm_reg, sizeof(in_icm_reg), 50 + out_icm_reg, sizeof(out_icm_reg), 51 + MLX5_REG_VHCA_ICM_CTRL, 0, 0); 52 + if (err) { 53 + mlx5_core_warn(dev, "Reading vhca_icm_ctrl failed. err = %d\n", err); 54 + return; 55 + } 56 + cur_alloc_icm = MLX5_GET(vhca_icm_ctrl_reg, out_icm_reg, cur_alloc_icm); 57 + devlink_fmsg_u32_pair_put(fmsg, "icm_consumption", cur_alloc_icm); 58 + } 59 + 16 60 void mlx5_reporter_vnic_diagnose_counters(struct mlx5_core_dev *dev, 17 61 struct devlink_fmsg *fmsg, 18 62 u16 vport_num, bool other_vport) ··· 103 59 devlink_fmsg_u64_pair_put(fmsg, "handled_pkt_steering_fail", 104 60 VNIC_ENV_GET64(&vnic, handled_pkt_steering_fail)); 105 61 } 62 + if (MLX5_CAP_GEN(dev, nic_cap_reg)) 63 + mlx5_reporter_vnic_diagnose_counter_icm(dev, fmsg, vport_num, other_vport); 106 64 107 65 devlink_fmsg_obj_nest_end(fmsg); 108 66 devlink_fmsg_pair_nest_end(fmsg);