14a2da0b8SParav Pandit /* 24a2da0b8SParav Pandit * Copyright (c) 2013-2017, Mellanox Technologies. All rights reserved. 34a2da0b8SParav Pandit * 44a2da0b8SParav Pandit * This software is available to you under a choice of one of two 54a2da0b8SParav Pandit * licenses. You may choose to be licensed under the terms of the GNU 64a2da0b8SParav Pandit * General Public License (GPL) Version 2, available from the file 74a2da0b8SParav Pandit * COPYING in the main directory of this source tree, or the 84a2da0b8SParav Pandit * OpenIB.org BSD license below: 94a2da0b8SParav Pandit * 104a2da0b8SParav Pandit * Redistribution and use in source and binary forms, with or 114a2da0b8SParav Pandit * without modification, are permitted provided that the following 124a2da0b8SParav Pandit * conditions are met: 134a2da0b8SParav Pandit * 144a2da0b8SParav Pandit * - Redistributions of source code must retain the above 154a2da0b8SParav Pandit * copyright notice, this list of conditions and the following 164a2da0b8SParav Pandit * disclaimer. 174a2da0b8SParav Pandit * 184a2da0b8SParav Pandit * - Redistributions in binary form must reproduce the above 194a2da0b8SParav Pandit * copyright notice, this list of conditions and the following 204a2da0b8SParav Pandit * disclaimer in the documentation and/or other materials 214a2da0b8SParav Pandit * provided with the distribution. 224a2da0b8SParav Pandit * 234a2da0b8SParav Pandit * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, 244a2da0b8SParav Pandit * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF 254a2da0b8SParav Pandit * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND 264a2da0b8SParav Pandit * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS 274a2da0b8SParav Pandit * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN 284a2da0b8SParav Pandit * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN 294a2da0b8SParav Pandit * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 304a2da0b8SParav Pandit * SOFTWARE. 314a2da0b8SParav Pandit */ 324a2da0b8SParav Pandit 334a2da0b8SParav Pandit #include <linux/debugfs.h> 344a2da0b8SParav Pandit 354a2da0b8SParav Pandit #include "mlx5_ib.h" 364a2da0b8SParav Pandit #include "cmd.h" 374a2da0b8SParav Pandit 384a2da0b8SParav Pandit enum mlx5_ib_cong_node_type { 394a2da0b8SParav Pandit MLX5_IB_RROCE_ECN_RP = 1, 404a2da0b8SParav Pandit MLX5_IB_RROCE_ECN_NP = 2, 414a2da0b8SParav Pandit }; 424a2da0b8SParav Pandit 434a2da0b8SParav Pandit static const char * const mlx5_ib_dbg_cc_name[] = { 444a2da0b8SParav Pandit "rp_clamp_tgt_rate", 454a2da0b8SParav Pandit "rp_clamp_tgt_rate_ati", 464a2da0b8SParav Pandit "rp_time_reset", 474a2da0b8SParav Pandit "rp_byte_reset", 484a2da0b8SParav Pandit "rp_threshold", 494a2da0b8SParav Pandit "rp_ai_rate", 504a2da0b8SParav Pandit "rp_hai_rate", 514a2da0b8SParav Pandit "rp_min_dec_fac", 524a2da0b8SParav Pandit "rp_min_rate", 534a2da0b8SParav Pandit "rp_rate_to_set_on_first_cnp", 544a2da0b8SParav Pandit "rp_dce_tcp_g", 554a2da0b8SParav Pandit "rp_dce_tcp_rtt", 564a2da0b8SParav Pandit "rp_rate_reduce_monitor_period", 574a2da0b8SParav Pandit "rp_initial_alpha_value", 584a2da0b8SParav Pandit "rp_gd", 594a2da0b8SParav Pandit "np_cnp_dscp", 604a2da0b8SParav Pandit "np_cnp_prio_mode", 614a2da0b8SParav Pandit "np_cnp_prio", 624a2da0b8SParav Pandit }; 634a2da0b8SParav Pandit 644a2da0b8SParav Pandit #define MLX5_IB_RP_CLAMP_TGT_RATE_ATTR BIT(1) 654a2da0b8SParav Pandit #define MLX5_IB_RP_CLAMP_TGT_RATE_ATI_ATTR BIT(2) 664a2da0b8SParav Pandit #define MLX5_IB_RP_TIME_RESET_ATTR BIT(3) 674a2da0b8SParav Pandit #define MLX5_IB_RP_BYTE_RESET_ATTR BIT(4) 684a2da0b8SParav Pandit #define MLX5_IB_RP_THRESHOLD_ATTR BIT(5) 694a2da0b8SParav Pandit #define MLX5_IB_RP_AI_RATE_ATTR BIT(7) 704a2da0b8SParav Pandit #define MLX5_IB_RP_HAI_RATE_ATTR BIT(8) 714a2da0b8SParav Pandit #define MLX5_IB_RP_MIN_DEC_FAC_ATTR BIT(9) 724a2da0b8SParav Pandit #define MLX5_IB_RP_MIN_RATE_ATTR BIT(10) 734a2da0b8SParav Pandit #define MLX5_IB_RP_RATE_TO_SET_ON_FIRST_CNP_ATTR BIT(11) 744a2da0b8SParav Pandit #define MLX5_IB_RP_DCE_TCP_G_ATTR BIT(12) 754a2da0b8SParav Pandit #define MLX5_IB_RP_DCE_TCP_RTT_ATTR BIT(13) 764a2da0b8SParav Pandit #define MLX5_IB_RP_RATE_REDUCE_MONITOR_PERIOD_ATTR BIT(14) 774a2da0b8SParav Pandit #define MLX5_IB_RP_INITIAL_ALPHA_VALUE_ATTR BIT(15) 784a2da0b8SParav Pandit #define MLX5_IB_RP_GD_ATTR BIT(16) 794a2da0b8SParav Pandit 804a2da0b8SParav Pandit #define MLX5_IB_NP_CNP_DSCP_ATTR BIT(3) 814a2da0b8SParav Pandit #define MLX5_IB_NP_CNP_PRIO_MODE_ATTR BIT(4) 824a2da0b8SParav Pandit 834a2da0b8SParav Pandit static enum mlx5_ib_cong_node_type 844a2da0b8SParav Pandit mlx5_ib_param_to_node(enum mlx5_ib_dbg_cc_types param_offset) 854a2da0b8SParav Pandit { 864a2da0b8SParav Pandit if (param_offset >= MLX5_IB_DBG_CC_RP_CLAMP_TGT_RATE && 874a2da0b8SParav Pandit param_offset <= MLX5_IB_DBG_CC_RP_GD) 884a2da0b8SParav Pandit return MLX5_IB_RROCE_ECN_RP; 894a2da0b8SParav Pandit else 904a2da0b8SParav Pandit return MLX5_IB_RROCE_ECN_NP; 914a2da0b8SParav Pandit } 924a2da0b8SParav Pandit 934a2da0b8SParav Pandit static u32 mlx5_get_cc_param_val(void *field, int offset) 944a2da0b8SParav Pandit { 954a2da0b8SParav Pandit switch (offset) { 964a2da0b8SParav Pandit case MLX5_IB_DBG_CC_RP_CLAMP_TGT_RATE: 974a2da0b8SParav Pandit return MLX5_GET(cong_control_r_roce_ecn_rp, field, 984a2da0b8SParav Pandit clamp_tgt_rate); 994a2da0b8SParav Pandit case MLX5_IB_DBG_CC_RP_CLAMP_TGT_RATE_ATI: 1004a2da0b8SParav Pandit return MLX5_GET(cong_control_r_roce_ecn_rp, field, 1014a2da0b8SParav Pandit clamp_tgt_rate_after_time_inc); 1024a2da0b8SParav Pandit case MLX5_IB_DBG_CC_RP_TIME_RESET: 1034a2da0b8SParav Pandit return MLX5_GET(cong_control_r_roce_ecn_rp, field, 1044a2da0b8SParav Pandit rpg_time_reset); 1054a2da0b8SParav Pandit case MLX5_IB_DBG_CC_RP_BYTE_RESET: 1064a2da0b8SParav Pandit return MLX5_GET(cong_control_r_roce_ecn_rp, field, 1074a2da0b8SParav Pandit rpg_byte_reset); 1084a2da0b8SParav Pandit case MLX5_IB_DBG_CC_RP_THRESHOLD: 1094a2da0b8SParav Pandit return MLX5_GET(cong_control_r_roce_ecn_rp, field, 1104a2da0b8SParav Pandit rpg_threshold); 1114a2da0b8SParav Pandit case MLX5_IB_DBG_CC_RP_AI_RATE: 1124a2da0b8SParav Pandit return MLX5_GET(cong_control_r_roce_ecn_rp, field, 1134a2da0b8SParav Pandit rpg_ai_rate); 1144a2da0b8SParav Pandit case MLX5_IB_DBG_CC_RP_HAI_RATE: 1154a2da0b8SParav Pandit return MLX5_GET(cong_control_r_roce_ecn_rp, field, 1164a2da0b8SParav Pandit rpg_hai_rate); 1174a2da0b8SParav Pandit case MLX5_IB_DBG_CC_RP_MIN_DEC_FAC: 1184a2da0b8SParav Pandit return MLX5_GET(cong_control_r_roce_ecn_rp, field, 1194a2da0b8SParav Pandit rpg_min_dec_fac); 1204a2da0b8SParav Pandit case MLX5_IB_DBG_CC_RP_MIN_RATE: 1214a2da0b8SParav Pandit return MLX5_GET(cong_control_r_roce_ecn_rp, field, 1224a2da0b8SParav Pandit rpg_min_rate); 1234a2da0b8SParav Pandit case MLX5_IB_DBG_CC_RP_RATE_TO_SET_ON_FIRST_CNP: 1244a2da0b8SParav Pandit return MLX5_GET(cong_control_r_roce_ecn_rp, field, 1254a2da0b8SParav Pandit rate_to_set_on_first_cnp); 1264a2da0b8SParav Pandit case MLX5_IB_DBG_CC_RP_DCE_TCP_G: 1274a2da0b8SParav Pandit return MLX5_GET(cong_control_r_roce_ecn_rp, field, 1284a2da0b8SParav Pandit dce_tcp_g); 1294a2da0b8SParav Pandit case MLX5_IB_DBG_CC_RP_DCE_TCP_RTT: 1304a2da0b8SParav Pandit return MLX5_GET(cong_control_r_roce_ecn_rp, field, 1314a2da0b8SParav Pandit dce_tcp_rtt); 1324a2da0b8SParav Pandit case MLX5_IB_DBG_CC_RP_RATE_REDUCE_MONITOR_PERIOD: 1334a2da0b8SParav Pandit return MLX5_GET(cong_control_r_roce_ecn_rp, field, 1344a2da0b8SParav Pandit rate_reduce_monitor_period); 1354a2da0b8SParav Pandit case MLX5_IB_DBG_CC_RP_INITIAL_ALPHA_VALUE: 1364a2da0b8SParav Pandit return MLX5_GET(cong_control_r_roce_ecn_rp, field, 1374a2da0b8SParav Pandit initial_alpha_value); 1384a2da0b8SParav Pandit case MLX5_IB_DBG_CC_RP_GD: 1394a2da0b8SParav Pandit return MLX5_GET(cong_control_r_roce_ecn_rp, field, 1404a2da0b8SParav Pandit rpg_gd); 1414a2da0b8SParav Pandit case MLX5_IB_DBG_CC_NP_CNP_DSCP: 1424a2da0b8SParav Pandit return MLX5_GET(cong_control_r_roce_ecn_np, field, 1434a2da0b8SParav Pandit cnp_dscp); 1444a2da0b8SParav Pandit case MLX5_IB_DBG_CC_NP_CNP_PRIO_MODE: 1454a2da0b8SParav Pandit return MLX5_GET(cong_control_r_roce_ecn_np, field, 1464a2da0b8SParav Pandit cnp_prio_mode); 1474a2da0b8SParav Pandit case MLX5_IB_DBG_CC_NP_CNP_PRIO: 1484a2da0b8SParav Pandit return MLX5_GET(cong_control_r_roce_ecn_np, field, 1494a2da0b8SParav Pandit cnp_802p_prio); 1504a2da0b8SParav Pandit default: 1514a2da0b8SParav Pandit return 0; 1524a2da0b8SParav Pandit } 1534a2da0b8SParav Pandit } 1544a2da0b8SParav Pandit 1554a2da0b8SParav Pandit static void mlx5_ib_set_cc_param_mask_val(void *field, int offset, 1564a2da0b8SParav Pandit u32 var, u32 *attr_mask) 1574a2da0b8SParav Pandit { 1584a2da0b8SParav Pandit switch (offset) { 1594a2da0b8SParav Pandit case MLX5_IB_DBG_CC_RP_CLAMP_TGT_RATE: 1604a2da0b8SParav Pandit *attr_mask |= MLX5_IB_RP_CLAMP_TGT_RATE_ATTR; 1614a2da0b8SParav Pandit MLX5_SET(cong_control_r_roce_ecn_rp, field, 1624a2da0b8SParav Pandit clamp_tgt_rate, var); 1634a2da0b8SParav Pandit break; 1644a2da0b8SParav Pandit case MLX5_IB_DBG_CC_RP_CLAMP_TGT_RATE_ATI: 1654a2da0b8SParav Pandit *attr_mask |= MLX5_IB_RP_CLAMP_TGT_RATE_ATI_ATTR; 1664a2da0b8SParav Pandit MLX5_SET(cong_control_r_roce_ecn_rp, field, 1674a2da0b8SParav Pandit clamp_tgt_rate_after_time_inc, var); 1684a2da0b8SParav Pandit break; 1694a2da0b8SParav Pandit case MLX5_IB_DBG_CC_RP_TIME_RESET: 1704a2da0b8SParav Pandit *attr_mask |= MLX5_IB_RP_TIME_RESET_ATTR; 1714a2da0b8SParav Pandit MLX5_SET(cong_control_r_roce_ecn_rp, field, 1724a2da0b8SParav Pandit rpg_time_reset, var); 1734a2da0b8SParav Pandit break; 1744a2da0b8SParav Pandit case MLX5_IB_DBG_CC_RP_BYTE_RESET: 1754a2da0b8SParav Pandit *attr_mask |= MLX5_IB_RP_BYTE_RESET_ATTR; 1764a2da0b8SParav Pandit MLX5_SET(cong_control_r_roce_ecn_rp, field, 1774a2da0b8SParav Pandit rpg_byte_reset, var); 1784a2da0b8SParav Pandit break; 1794a2da0b8SParav Pandit case MLX5_IB_DBG_CC_RP_THRESHOLD: 1804a2da0b8SParav Pandit *attr_mask |= MLX5_IB_RP_THRESHOLD_ATTR; 1814a2da0b8SParav Pandit MLX5_SET(cong_control_r_roce_ecn_rp, field, 1824a2da0b8SParav Pandit rpg_threshold, var); 1834a2da0b8SParav Pandit break; 1844a2da0b8SParav Pandit case MLX5_IB_DBG_CC_RP_AI_RATE: 1854a2da0b8SParav Pandit *attr_mask |= MLX5_IB_RP_AI_RATE_ATTR; 1864a2da0b8SParav Pandit MLX5_SET(cong_control_r_roce_ecn_rp, field, 1874a2da0b8SParav Pandit rpg_ai_rate, var); 1884a2da0b8SParav Pandit break; 1894a2da0b8SParav Pandit case MLX5_IB_DBG_CC_RP_HAI_RATE: 1904a2da0b8SParav Pandit *attr_mask |= MLX5_IB_RP_HAI_RATE_ATTR; 1914a2da0b8SParav Pandit MLX5_SET(cong_control_r_roce_ecn_rp, field, 1924a2da0b8SParav Pandit rpg_hai_rate, var); 1934a2da0b8SParav Pandit break; 1944a2da0b8SParav Pandit case MLX5_IB_DBG_CC_RP_MIN_DEC_FAC: 1954a2da0b8SParav Pandit *attr_mask |= MLX5_IB_RP_MIN_DEC_FAC_ATTR; 1964a2da0b8SParav Pandit MLX5_SET(cong_control_r_roce_ecn_rp, field, 1974a2da0b8SParav Pandit rpg_min_dec_fac, var); 1984a2da0b8SParav Pandit break; 1994a2da0b8SParav Pandit case MLX5_IB_DBG_CC_RP_MIN_RATE: 2004a2da0b8SParav Pandit *attr_mask |= MLX5_IB_RP_MIN_RATE_ATTR; 2014a2da0b8SParav Pandit MLX5_SET(cong_control_r_roce_ecn_rp, field, 2024a2da0b8SParav Pandit rpg_min_rate, var); 2034a2da0b8SParav Pandit break; 2044a2da0b8SParav Pandit case MLX5_IB_DBG_CC_RP_RATE_TO_SET_ON_FIRST_CNP: 2054a2da0b8SParav Pandit *attr_mask |= MLX5_IB_RP_RATE_TO_SET_ON_FIRST_CNP_ATTR; 2064a2da0b8SParav Pandit MLX5_SET(cong_control_r_roce_ecn_rp, field, 2074a2da0b8SParav Pandit rate_to_set_on_first_cnp, var); 2084a2da0b8SParav Pandit break; 2094a2da0b8SParav Pandit case MLX5_IB_DBG_CC_RP_DCE_TCP_G: 2104a2da0b8SParav Pandit *attr_mask |= MLX5_IB_RP_DCE_TCP_G_ATTR; 2114a2da0b8SParav Pandit MLX5_SET(cong_control_r_roce_ecn_rp, field, 2124a2da0b8SParav Pandit dce_tcp_g, var); 2134a2da0b8SParav Pandit break; 2144a2da0b8SParav Pandit case MLX5_IB_DBG_CC_RP_DCE_TCP_RTT: 2154a2da0b8SParav Pandit *attr_mask |= MLX5_IB_RP_DCE_TCP_RTT_ATTR; 2164a2da0b8SParav Pandit MLX5_SET(cong_control_r_roce_ecn_rp, field, 2174a2da0b8SParav Pandit dce_tcp_rtt, var); 2184a2da0b8SParav Pandit break; 2194a2da0b8SParav Pandit case MLX5_IB_DBG_CC_RP_RATE_REDUCE_MONITOR_PERIOD: 2204a2da0b8SParav Pandit *attr_mask |= MLX5_IB_RP_RATE_REDUCE_MONITOR_PERIOD_ATTR; 2214a2da0b8SParav Pandit MLX5_SET(cong_control_r_roce_ecn_rp, field, 2224a2da0b8SParav Pandit rate_reduce_monitor_period, var); 2234a2da0b8SParav Pandit break; 2244a2da0b8SParav Pandit case MLX5_IB_DBG_CC_RP_INITIAL_ALPHA_VALUE: 2254a2da0b8SParav Pandit *attr_mask |= MLX5_IB_RP_INITIAL_ALPHA_VALUE_ATTR; 2264a2da0b8SParav Pandit MLX5_SET(cong_control_r_roce_ecn_rp, field, 2274a2da0b8SParav Pandit initial_alpha_value, var); 2284a2da0b8SParav Pandit break; 2294a2da0b8SParav Pandit case MLX5_IB_DBG_CC_RP_GD: 2304a2da0b8SParav Pandit *attr_mask |= MLX5_IB_RP_GD_ATTR; 2314a2da0b8SParav Pandit MLX5_SET(cong_control_r_roce_ecn_rp, field, 2324a2da0b8SParav Pandit rpg_gd, var); 2334a2da0b8SParav Pandit break; 2344a2da0b8SParav Pandit case MLX5_IB_DBG_CC_NP_CNP_DSCP: 2354a2da0b8SParav Pandit *attr_mask |= MLX5_IB_NP_CNP_DSCP_ATTR; 2364a2da0b8SParav Pandit MLX5_SET(cong_control_r_roce_ecn_np, field, cnp_dscp, var); 2374a2da0b8SParav Pandit break; 2384a2da0b8SParav Pandit case MLX5_IB_DBG_CC_NP_CNP_PRIO_MODE: 2394a2da0b8SParav Pandit *attr_mask |= MLX5_IB_NP_CNP_PRIO_MODE_ATTR; 2404a2da0b8SParav Pandit MLX5_SET(cong_control_r_roce_ecn_np, field, cnp_prio_mode, var); 2414a2da0b8SParav Pandit break; 2424a2da0b8SParav Pandit case MLX5_IB_DBG_CC_NP_CNP_PRIO: 2434a2da0b8SParav Pandit *attr_mask |= MLX5_IB_NP_CNP_PRIO_MODE_ATTR; 2444a2da0b8SParav Pandit MLX5_SET(cong_control_r_roce_ecn_np, field, cnp_prio_mode, 0); 2454a2da0b8SParav Pandit MLX5_SET(cong_control_r_roce_ecn_np, field, cnp_802p_prio, var); 2464a2da0b8SParav Pandit break; 2474a2da0b8SParav Pandit } 2484a2da0b8SParav Pandit } 2494a2da0b8SParav Pandit 250a9e546e7SParav Pandit static int mlx5_ib_get_cc_params(struct mlx5_ib_dev *dev, u8 port_num, 251a9e546e7SParav Pandit int offset, u32 *var) 2524a2da0b8SParav Pandit { 2534a2da0b8SParav Pandit int outlen = MLX5_ST_SZ_BYTES(query_cong_params_out); 2544a2da0b8SParav Pandit void *out; 2554a2da0b8SParav Pandit void *field; 2564a2da0b8SParav Pandit int err; 2574a2da0b8SParav Pandit enum mlx5_ib_cong_node_type node; 258a9e546e7SParav Pandit struct mlx5_core_dev *mdev; 259a9e546e7SParav Pandit 260a9e546e7SParav Pandit /* Takes a 1-based port number */ 261a9e546e7SParav Pandit mdev = mlx5_ib_get_native_port_mdev(dev, port_num + 1, NULL); 262a9e546e7SParav Pandit if (!mdev) 263a9e546e7SParav Pandit return -ENODEV; 2644a2da0b8SParav Pandit 2654a2da0b8SParav Pandit out = kvzalloc(outlen, GFP_KERNEL); 266a9e546e7SParav Pandit if (!out) { 267a9e546e7SParav Pandit err = -ENOMEM; 268a9e546e7SParav Pandit goto alloc_err; 269a9e546e7SParav Pandit } 2704a2da0b8SParav Pandit 2714a2da0b8SParav Pandit node = mlx5_ib_param_to_node(offset); 2724a2da0b8SParav Pandit 273a9e546e7SParav Pandit err = mlx5_cmd_query_cong_params(mdev, node, out, outlen); 2744a2da0b8SParav Pandit if (err) 2754a2da0b8SParav Pandit goto free; 2764a2da0b8SParav Pandit 2774a2da0b8SParav Pandit field = MLX5_ADDR_OF(query_cong_params_out, out, congestion_parameters); 2784a2da0b8SParav Pandit *var = mlx5_get_cc_param_val(field, offset); 2794a2da0b8SParav Pandit 2804a2da0b8SParav Pandit free: 2814a2da0b8SParav Pandit kvfree(out); 282a9e546e7SParav Pandit alloc_err: 283a9e546e7SParav Pandit mlx5_ib_put_native_port_mdev(dev, port_num + 1); 2844a2da0b8SParav Pandit return err; 2854a2da0b8SParav Pandit } 2864a2da0b8SParav Pandit 287a9e546e7SParav Pandit static int mlx5_ib_set_cc_params(struct mlx5_ib_dev *dev, u8 port_num, 288a9e546e7SParav Pandit int offset, u32 var) 2894a2da0b8SParav Pandit { 2904a2da0b8SParav Pandit int inlen = MLX5_ST_SZ_BYTES(modify_cong_params_in); 2914a2da0b8SParav Pandit void *in; 2924a2da0b8SParav Pandit void *field; 2934a2da0b8SParav Pandit enum mlx5_ib_cong_node_type node; 294a9e546e7SParav Pandit struct mlx5_core_dev *mdev; 2954a2da0b8SParav Pandit u32 attr_mask = 0; 2964a2da0b8SParav Pandit int err; 2974a2da0b8SParav Pandit 298a9e546e7SParav Pandit /* Takes a 1-based port number */ 299a9e546e7SParav Pandit mdev = mlx5_ib_get_native_port_mdev(dev, port_num + 1, NULL); 300a9e546e7SParav Pandit if (!mdev) 301a9e546e7SParav Pandit return -ENODEV; 302a9e546e7SParav Pandit 3034a2da0b8SParav Pandit in = kvzalloc(inlen, GFP_KERNEL); 304a9e546e7SParav Pandit if (!in) { 305a9e546e7SParav Pandit err = -ENOMEM; 306a9e546e7SParav Pandit goto alloc_err; 307a9e546e7SParav Pandit } 3084a2da0b8SParav Pandit 3094a2da0b8SParav Pandit MLX5_SET(modify_cong_params_in, in, opcode, 3104a2da0b8SParav Pandit MLX5_CMD_OP_MODIFY_CONG_PARAMS); 3114a2da0b8SParav Pandit 3124a2da0b8SParav Pandit node = mlx5_ib_param_to_node(offset); 3134a2da0b8SParav Pandit MLX5_SET(modify_cong_params_in, in, cong_protocol, node); 3144a2da0b8SParav Pandit 3154a2da0b8SParav Pandit field = MLX5_ADDR_OF(modify_cong_params_in, in, congestion_parameters); 3164a2da0b8SParav Pandit mlx5_ib_set_cc_param_mask_val(field, offset, var, &attr_mask); 3174a2da0b8SParav Pandit 3184a2da0b8SParav Pandit field = MLX5_ADDR_OF(modify_cong_params_in, in, field_select); 3194a2da0b8SParav Pandit MLX5_SET(field_select_r_roce_rp, field, field_select_r_roce_rp, 3204a2da0b8SParav Pandit attr_mask); 3214a2da0b8SParav Pandit 322a9e546e7SParav Pandit err = mlx5_cmd_modify_cong_params(mdev, in, inlen); 3234a2da0b8SParav Pandit kvfree(in); 324a9e546e7SParav Pandit alloc_err: 325a9e546e7SParav Pandit mlx5_ib_put_native_port_mdev(dev, port_num + 1); 3264a2da0b8SParav Pandit return err; 3274a2da0b8SParav Pandit } 3284a2da0b8SParav Pandit 3294a2da0b8SParav Pandit static ssize_t set_param(struct file *filp, const char __user *buf, 3304a2da0b8SParav Pandit size_t count, loff_t *pos) 3314a2da0b8SParav Pandit { 3324a2da0b8SParav Pandit struct mlx5_ib_dbg_param *param = filp->private_data; 3334a2da0b8SParav Pandit int offset = param->offset; 3344a2da0b8SParav Pandit char lbuf[11] = { }; 3354a2da0b8SParav Pandit u32 var; 3364a2da0b8SParav Pandit int ret; 3374a2da0b8SParav Pandit 3384a2da0b8SParav Pandit if (count > sizeof(lbuf)) 3394a2da0b8SParav Pandit return -EINVAL; 3404a2da0b8SParav Pandit 3414a2da0b8SParav Pandit if (copy_from_user(lbuf, buf, count)) 3424a2da0b8SParav Pandit return -EFAULT; 3434a2da0b8SParav Pandit 3444a2da0b8SParav Pandit lbuf[sizeof(lbuf) - 1] = '\0'; 3454a2da0b8SParav Pandit 3464a2da0b8SParav Pandit if (kstrtou32(lbuf, 0, &var)) 3474a2da0b8SParav Pandit return -EINVAL; 3484a2da0b8SParav Pandit 349a9e546e7SParav Pandit ret = mlx5_ib_set_cc_params(param->dev, param->port_num, offset, var); 3504a2da0b8SParav Pandit return ret ? ret : count; 3514a2da0b8SParav Pandit } 3524a2da0b8SParav Pandit 3534a2da0b8SParav Pandit static ssize_t get_param(struct file *filp, char __user *buf, size_t count, 3544a2da0b8SParav Pandit loff_t *pos) 3554a2da0b8SParav Pandit { 3564a2da0b8SParav Pandit struct mlx5_ib_dbg_param *param = filp->private_data; 3574a2da0b8SParav Pandit int offset = param->offset; 3584a2da0b8SParav Pandit u32 var = 0; 3594a2da0b8SParav Pandit int ret; 3604a2da0b8SParav Pandit char lbuf[11]; 3614a2da0b8SParav Pandit 362a9e546e7SParav Pandit ret = mlx5_ib_get_cc_params(param->dev, param->port_num, offset, &var); 3634a2da0b8SParav Pandit if (ret) 3644a2da0b8SParav Pandit return ret; 3654a2da0b8SParav Pandit 3664a2da0b8SParav Pandit ret = snprintf(lbuf, sizeof(lbuf), "%d\n", var); 3674a2da0b8SParav Pandit if (ret < 0) 3684a2da0b8SParav Pandit return ret; 3694a2da0b8SParav Pandit 370*60e6627fSJann Horn return simple_read_from_buffer(buf, count, pos, lbuf, ret); 3714a2da0b8SParav Pandit } 3724a2da0b8SParav Pandit 3734a2da0b8SParav Pandit static const struct file_operations dbg_cc_fops = { 3744a2da0b8SParav Pandit .owner = THIS_MODULE, 3754a2da0b8SParav Pandit .open = simple_open, 3764a2da0b8SParav Pandit .write = set_param, 3774a2da0b8SParav Pandit .read = get_param, 3784a2da0b8SParav Pandit }; 3794a2da0b8SParav Pandit 380a9e546e7SParav Pandit void mlx5_ib_cleanup_cong_debugfs(struct mlx5_ib_dev *dev, u8 port_num) 3814a2da0b8SParav Pandit { 3824a2da0b8SParav Pandit if (!mlx5_debugfs_root || 383a9e546e7SParav Pandit !dev->port[port_num].dbg_cc_params || 384a9e546e7SParav Pandit !dev->port[port_num].dbg_cc_params->root) 3854a2da0b8SParav Pandit return; 3864a2da0b8SParav Pandit 387a9e546e7SParav Pandit debugfs_remove_recursive(dev->port[port_num].dbg_cc_params->root); 388a9e546e7SParav Pandit kfree(dev->port[port_num].dbg_cc_params); 389a9e546e7SParav Pandit dev->port[port_num].dbg_cc_params = NULL; 3904a2da0b8SParav Pandit } 3914a2da0b8SParav Pandit 392a9e546e7SParav Pandit int mlx5_ib_init_cong_debugfs(struct mlx5_ib_dev *dev, u8 port_num) 3934a2da0b8SParav Pandit { 3944a2da0b8SParav Pandit struct mlx5_ib_dbg_cc_params *dbg_cc_params; 395a9e546e7SParav Pandit struct mlx5_core_dev *mdev; 3964a2da0b8SParav Pandit int i; 3974a2da0b8SParav Pandit 3984a2da0b8SParav Pandit if (!mlx5_debugfs_root) 3994a2da0b8SParav Pandit goto out; 4004a2da0b8SParav Pandit 401a9e546e7SParav Pandit /* Takes a 1-based port number */ 402a9e546e7SParav Pandit mdev = mlx5_ib_get_native_port_mdev(dev, port_num + 1, NULL); 403a9e546e7SParav Pandit if (!mdev) 4044a2da0b8SParav Pandit goto out; 4054a2da0b8SParav Pandit 406a9e546e7SParav Pandit if (!MLX5_CAP_GEN(mdev, cc_query_allowed) || 407a9e546e7SParav Pandit !MLX5_CAP_GEN(mdev, cc_modify_allowed)) 408a9e546e7SParav Pandit goto put_mdev; 409a9e546e7SParav Pandit 4104a2da0b8SParav Pandit dbg_cc_params = kzalloc(sizeof(*dbg_cc_params), GFP_KERNEL); 4114a2da0b8SParav Pandit if (!dbg_cc_params) 412a9e546e7SParav Pandit goto err; 4134a2da0b8SParav Pandit 414a9e546e7SParav Pandit dev->port[port_num].dbg_cc_params = dbg_cc_params; 4154a2da0b8SParav Pandit 4164a2da0b8SParav Pandit dbg_cc_params->root = debugfs_create_dir("cc_params", 417a9e546e7SParav Pandit mdev->priv.dbg_root); 4184a2da0b8SParav Pandit if (!dbg_cc_params->root) 4194a2da0b8SParav Pandit goto err; 4204a2da0b8SParav Pandit 4214a2da0b8SParav Pandit for (i = 0; i < MLX5_IB_DBG_CC_MAX; i++) { 4224a2da0b8SParav Pandit dbg_cc_params->params[i].offset = i; 4234a2da0b8SParav Pandit dbg_cc_params->params[i].dev = dev; 424a9e546e7SParav Pandit dbg_cc_params->params[i].port_num = port_num; 4254a2da0b8SParav Pandit dbg_cc_params->params[i].dentry = 4264a2da0b8SParav Pandit debugfs_create_file(mlx5_ib_dbg_cc_name[i], 4274a2da0b8SParav Pandit 0600, dbg_cc_params->root, 4284a2da0b8SParav Pandit &dbg_cc_params->params[i], 4294a2da0b8SParav Pandit &dbg_cc_fops); 4304a2da0b8SParav Pandit if (!dbg_cc_params->params[i].dentry) 4314a2da0b8SParav Pandit goto err; 4324a2da0b8SParav Pandit } 433a9e546e7SParav Pandit 434a9e546e7SParav Pandit put_mdev: 435a9e546e7SParav Pandit mlx5_ib_put_native_port_mdev(dev, port_num + 1); 436a9e546e7SParav Pandit out: 437a9e546e7SParav Pandit return 0; 4384a2da0b8SParav Pandit 4394a2da0b8SParav Pandit err: 4404a2da0b8SParav Pandit mlx5_ib_warn(dev, "cong debugfs failure\n"); 441a9e546e7SParav Pandit mlx5_ib_cleanup_cong_debugfs(dev, port_num); 442a9e546e7SParav Pandit mlx5_ib_put_native_port_mdev(dev, port_num + 1); 443a9e546e7SParav Pandit 4444a2da0b8SParav Pandit /* 4454a2da0b8SParav Pandit * We don't want to fail driver if debugfs failed to initialize, 4464a2da0b8SParav Pandit * so we are not forwarding error to the user. 4474a2da0b8SParav Pandit */ 4484a2da0b8SParav Pandit return 0; 4494a2da0b8SParav Pandit } 450