1 // SPDX-License-Identifier: GPL-2.0 OR Linux-OpenIB 2 /* Copyright (c) 2023, NVIDIA CORPORATION & AFFILIATES. */ 3 4 #include "reporter_vnic.h" 5 #include "en_stats.h" 6 #include "devlink.h" 7 8 #define VNIC_ENV_GET64(vnic_env_stats, c) \ 9 MLX5_GET64(query_vnic_env_out, (vnic_env_stats)->query_vnic_env_out, \ 10 vport_env.c) 11 12 struct mlx5_vnic_diag_stats { 13 __be64 query_vnic_env_out[MLX5_ST_SZ_QW(query_vnic_env_out)]; 14 }; 15 16 int mlx5_reporter_vnic_diagnose_counters(struct mlx5_core_dev *dev, 17 struct devlink_fmsg *fmsg, 18 u16 vport_num, bool other_vport) 19 { 20 u32 in[MLX5_ST_SZ_DW(query_vnic_env_in)] = {}; 21 struct mlx5_vnic_diag_stats vnic; 22 int err; 23 24 MLX5_SET(query_vnic_env_in, in, opcode, MLX5_CMD_OP_QUERY_VNIC_ENV); 25 MLX5_SET(query_vnic_env_in, in, vport_number, vport_num); 26 MLX5_SET(query_vnic_env_in, in, other_vport, !!other_vport); 27 28 err = mlx5_cmd_exec_inout(dev, query_vnic_env, in, &vnic.query_vnic_env_out); 29 if (err) 30 return err; 31 32 err = devlink_fmsg_pair_nest_start(fmsg, "vNIC env counters"); 33 if (err) 34 return err; 35 36 err = devlink_fmsg_obj_nest_start(fmsg); 37 if (err) 38 return err; 39 40 if (MLX5_CAP_GEN(dev, vnic_env_queue_counters)) { 41 err = devlink_fmsg_u32_pair_put(fmsg, "total_error_queues", 42 VNIC_ENV_GET(&vnic, total_error_queues)); 43 if (err) 44 return err; 45 46 err = devlink_fmsg_u32_pair_put(fmsg, "send_queue_priority_update_flow", 47 VNIC_ENV_GET(&vnic, 48 send_queue_priority_update_flow)); 49 if (err) 50 return err; 51 } 52 53 if (MLX5_CAP_GEN(dev, eq_overrun_count)) { 54 err = devlink_fmsg_u32_pair_put(fmsg, "comp_eq_overrun", 55 VNIC_ENV_GET(&vnic, comp_eq_overrun)); 56 if (err) 57 return err; 58 59 err = devlink_fmsg_u32_pair_put(fmsg, "async_eq_overrun", 60 VNIC_ENV_GET(&vnic, async_eq_overrun)); 61 if (err) 62 return err; 63 } 64 65 if (MLX5_CAP_GEN(dev, vnic_env_cq_overrun)) { 66 err = devlink_fmsg_u32_pair_put(fmsg, "cq_overrun", 67 VNIC_ENV_GET(&vnic, cq_overrun)); 68 if (err) 69 return err; 70 } 71 72 if (MLX5_CAP_GEN(dev, invalid_command_count)) { 73 err = devlink_fmsg_u32_pair_put(fmsg, "invalid_command", 74 VNIC_ENV_GET(&vnic, invalid_command)); 75 if (err) 76 return err; 77 } 78 79 if (MLX5_CAP_GEN(dev, quota_exceeded_count)) { 80 err = devlink_fmsg_u32_pair_put(fmsg, "quota_exceeded_command", 81 VNIC_ENV_GET(&vnic, quota_exceeded_command)); 82 if (err) 83 return err; 84 } 85 86 if (MLX5_CAP_GEN(dev, nic_receive_steering_discard)) { 87 err = devlink_fmsg_u64_pair_put(fmsg, "nic_receive_steering_discard", 88 VNIC_ENV_GET64(&vnic, 89 nic_receive_steering_discard)); 90 if (err) 91 return err; 92 } 93 94 if (MLX5_CAP_GEN(dev, vnic_env_cnt_steering_fail)) { 95 err = devlink_fmsg_u64_pair_put(fmsg, "generated_pkt_steering_fail", 96 VNIC_ENV_GET64(&vnic, 97 generated_pkt_steering_fail)); 98 if (err) 99 return err; 100 101 err = devlink_fmsg_u64_pair_put(fmsg, "handled_pkt_steering_fail", 102 VNIC_ENV_GET64(&vnic, handled_pkt_steering_fail)); 103 if (err) 104 return err; 105 } 106 107 err = devlink_fmsg_obj_nest_end(fmsg); 108 if (err) 109 return err; 110 111 err = devlink_fmsg_pair_nest_end(fmsg); 112 if (err) 113 return err; 114 115 return 0; 116 } 117 118 static int mlx5_reporter_vnic_diagnose(struct devlink_health_reporter *reporter, 119 struct devlink_fmsg *fmsg, 120 struct netlink_ext_ack *extack) 121 { 122 struct mlx5_core_dev *dev = devlink_health_reporter_priv(reporter); 123 124 return mlx5_reporter_vnic_diagnose_counters(dev, fmsg, 0, false); 125 } 126 127 static const struct devlink_health_reporter_ops mlx5_reporter_vnic_ops = { 128 .name = "vnic", 129 .diagnose = mlx5_reporter_vnic_diagnose, 130 }; 131 132 void mlx5_reporter_vnic_create(struct mlx5_core_dev *dev) 133 { 134 struct mlx5_core_health *health = &dev->priv.health; 135 struct devlink *devlink = priv_to_devlink(dev); 136 137 health->vnic_reporter = 138 devlink_health_reporter_create(devlink, 139 &mlx5_reporter_vnic_ops, 140 0, dev); 141 if (IS_ERR(health->vnic_reporter)) 142 mlx5_core_warn(dev, 143 "Failed to create vnic reporter, err = %ld\n", 144 PTR_ERR(health->vnic_reporter)); 145 } 146 147 void mlx5_reporter_vnic_destroy(struct mlx5_core_dev *dev) 148 { 149 struct mlx5_core_health *health = &dev->priv.health; 150 151 if (!IS_ERR_OR_NULL(health->vnic_reporter)) 152 devlink_health_reporter_destroy(health->vnic_reporter); 153 } 154