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