11d918647SAlex Vesker // SPDX-License-Identifier: GPL-2.0 OR Linux-OpenIB 21d918647SAlex Vesker /* Copyright (c) 2019 Mellanox Technologies. */ 31d918647SAlex Vesker 41d918647SAlex Vesker #include "dr_types.h" 51d918647SAlex Vesker 61d918647SAlex Vesker int mlx5dr_cmd_query_esw_vport_context(struct mlx5_core_dev *mdev, 71d918647SAlex Vesker bool other_vport, 81d918647SAlex Vesker u16 vport_number, 91d918647SAlex Vesker u64 *icm_address_rx, 101d918647SAlex Vesker u64 *icm_address_tx) 111d918647SAlex Vesker { 121d918647SAlex Vesker u32 out[MLX5_ST_SZ_DW(query_esw_vport_context_out)] = {}; 131d918647SAlex Vesker u32 in[MLX5_ST_SZ_DW(query_esw_vport_context_in)] = {}; 141d918647SAlex Vesker int err; 151d918647SAlex Vesker 161d918647SAlex Vesker MLX5_SET(query_esw_vport_context_in, in, opcode, 171d918647SAlex Vesker MLX5_CMD_OP_QUERY_ESW_VPORT_CONTEXT); 181d918647SAlex Vesker MLX5_SET(query_esw_vport_context_in, in, other_vport, other_vport); 191d918647SAlex Vesker MLX5_SET(query_esw_vport_context_in, in, vport_number, vport_number); 201d918647SAlex Vesker 217ba294e4SLeon Romanovsky err = mlx5_cmd_exec_inout(mdev, query_esw_vport_context, in, out); 221d918647SAlex Vesker if (err) 231d918647SAlex Vesker return err; 241d918647SAlex Vesker 251d918647SAlex Vesker *icm_address_rx = 261d918647SAlex Vesker MLX5_GET64(query_esw_vport_context_out, out, 271d918647SAlex Vesker esw_vport_context.sw_steering_vport_icm_address_rx); 281d918647SAlex Vesker *icm_address_tx = 291d918647SAlex Vesker MLX5_GET64(query_esw_vport_context_out, out, 301d918647SAlex Vesker esw_vport_context.sw_steering_vport_icm_address_tx); 311d918647SAlex Vesker return 0; 321d918647SAlex Vesker } 331d918647SAlex Vesker 341d918647SAlex Vesker int mlx5dr_cmd_query_gvmi(struct mlx5_core_dev *mdev, bool other_vport, 351d918647SAlex Vesker u16 vport_number, u16 *gvmi) 361d918647SAlex Vesker { 371d918647SAlex Vesker u32 in[MLX5_ST_SZ_DW(query_hca_cap_in)] = {}; 381d918647SAlex Vesker int out_size; 391d918647SAlex Vesker void *out; 401d918647SAlex Vesker int err; 411d918647SAlex Vesker 421d918647SAlex Vesker out_size = MLX5_ST_SZ_BYTES(query_hca_cap_out); 431d918647SAlex Vesker out = kzalloc(out_size, GFP_KERNEL); 441d918647SAlex Vesker if (!out) 451d918647SAlex Vesker return -ENOMEM; 461d918647SAlex Vesker 471d918647SAlex Vesker MLX5_SET(query_hca_cap_in, in, opcode, MLX5_CMD_OP_QUERY_HCA_CAP); 481d918647SAlex Vesker MLX5_SET(query_hca_cap_in, in, other_function, other_vport); 491d918647SAlex Vesker MLX5_SET(query_hca_cap_in, in, function_id, vport_number); 501d918647SAlex Vesker MLX5_SET(query_hca_cap_in, in, op_mod, 511d918647SAlex Vesker MLX5_SET_HCA_CAP_OP_MOD_GENERAL_DEVICE << 1 | 521d918647SAlex Vesker HCA_CAP_OPMOD_GET_CUR); 531d918647SAlex Vesker 547ba294e4SLeon Romanovsky err = mlx5_cmd_exec_inout(mdev, query_hca_cap, in, out); 551d918647SAlex Vesker if (err) { 561d918647SAlex Vesker kfree(out); 571d918647SAlex Vesker return err; 581d918647SAlex Vesker } 591d918647SAlex Vesker 601d918647SAlex Vesker *gvmi = MLX5_GET(query_hca_cap_out, out, capability.cmd_hca_cap.vhca_id); 611d918647SAlex Vesker 621d918647SAlex Vesker kfree(out); 631d918647SAlex Vesker return 0; 641d918647SAlex Vesker } 651d918647SAlex Vesker 661d918647SAlex Vesker int mlx5dr_cmd_query_esw_caps(struct mlx5_core_dev *mdev, 671d918647SAlex Vesker struct mlx5dr_esw_caps *caps) 681d918647SAlex Vesker { 691d918647SAlex Vesker caps->drop_icm_address_rx = 701d918647SAlex Vesker MLX5_CAP64_ESW_FLOWTABLE(mdev, 711d918647SAlex Vesker sw_steering_fdb_action_drop_icm_address_rx); 721d918647SAlex Vesker caps->drop_icm_address_tx = 731d918647SAlex Vesker MLX5_CAP64_ESW_FLOWTABLE(mdev, 741d918647SAlex Vesker sw_steering_fdb_action_drop_icm_address_tx); 751d918647SAlex Vesker caps->uplink_icm_address_rx = 761d918647SAlex Vesker MLX5_CAP64_ESW_FLOWTABLE(mdev, 771d918647SAlex Vesker sw_steering_uplink_icm_address_rx); 781d918647SAlex Vesker caps->uplink_icm_address_tx = 791d918647SAlex Vesker MLX5_CAP64_ESW_FLOWTABLE(mdev, 801d918647SAlex Vesker sw_steering_uplink_icm_address_tx); 81*64f45c0fSYevgeny Kliteynik caps->sw_owner_v2 = MLX5_CAP_ESW_FLOWTABLE_FDB(mdev, sw_owner_v2); 82*64f45c0fSYevgeny Kliteynik if (!caps->sw_owner_v2) 83*64f45c0fSYevgeny Kliteynik caps->sw_owner = MLX5_CAP_ESW_FLOWTABLE_FDB(mdev, sw_owner); 841d918647SAlex Vesker 851d918647SAlex Vesker return 0; 861d918647SAlex Vesker } 871d918647SAlex Vesker 881d918647SAlex Vesker int mlx5dr_cmd_query_device(struct mlx5_core_dev *mdev, 891d918647SAlex Vesker struct mlx5dr_cmd_caps *caps) 901d918647SAlex Vesker { 911d918647SAlex Vesker caps->prio_tag_required = MLX5_CAP_GEN(mdev, prio_tag_required); 921d918647SAlex Vesker caps->eswitch_manager = MLX5_CAP_GEN(mdev, eswitch_manager); 931d918647SAlex Vesker caps->gvmi = MLX5_CAP_GEN(mdev, vhca_id); 941d918647SAlex Vesker caps->flex_protocols = MLX5_CAP_GEN(mdev, flex_parser_protocols); 95d421e466SYevgeny Kliteynik caps->sw_format_ver = MLX5_CAP_GEN(mdev, steering_format_version); 961d918647SAlex Vesker 978a8a1023SYevgeny Kliteynik if (caps->flex_protocols & MLX5_FLEX_PARSER_ICMP_V4_ENABLED) { 981d918647SAlex Vesker caps->flex_parser_id_icmp_dw0 = MLX5_CAP_GEN(mdev, flex_parser_id_icmp_dw0); 991d918647SAlex Vesker caps->flex_parser_id_icmp_dw1 = MLX5_CAP_GEN(mdev, flex_parser_id_icmp_dw1); 1001d918647SAlex Vesker } 1011d918647SAlex Vesker 1028a8a1023SYevgeny Kliteynik if (caps->flex_protocols & MLX5_FLEX_PARSER_ICMP_V6_ENABLED) { 1031d918647SAlex Vesker caps->flex_parser_id_icmpv6_dw0 = 1041d918647SAlex Vesker MLX5_CAP_GEN(mdev, flex_parser_id_icmpv6_dw0); 1051d918647SAlex Vesker caps->flex_parser_id_icmpv6_dw1 = 1061d918647SAlex Vesker MLX5_CAP_GEN(mdev, flex_parser_id_icmpv6_dw1); 1071d918647SAlex Vesker } 1081d918647SAlex Vesker 1091d918647SAlex Vesker caps->nic_rx_drop_address = 1101d918647SAlex Vesker MLX5_CAP64_FLOWTABLE(mdev, sw_steering_nic_rx_action_drop_icm_address); 1111d918647SAlex Vesker caps->nic_tx_drop_address = 1121d918647SAlex Vesker MLX5_CAP64_FLOWTABLE(mdev, sw_steering_nic_tx_action_drop_icm_address); 1131d918647SAlex Vesker caps->nic_tx_allow_address = 1141d918647SAlex Vesker MLX5_CAP64_FLOWTABLE(mdev, sw_steering_nic_tx_action_allow_icm_address); 1151d918647SAlex Vesker 116*64f45c0fSYevgeny Kliteynik caps->rx_sw_owner_v2 = MLX5_CAP_FLOWTABLE_NIC_RX(mdev, sw_owner_v2); 117*64f45c0fSYevgeny Kliteynik caps->tx_sw_owner_v2 = MLX5_CAP_FLOWTABLE_NIC_TX(mdev, sw_owner_v2); 1181d918647SAlex Vesker 119*64f45c0fSYevgeny Kliteynik if (!caps->rx_sw_owner_v2) 120*64f45c0fSYevgeny Kliteynik caps->rx_sw_owner = MLX5_CAP_FLOWTABLE_NIC_RX(mdev, sw_owner); 121*64f45c0fSYevgeny Kliteynik if (!caps->tx_sw_owner_v2) 1221d918647SAlex Vesker caps->tx_sw_owner = MLX5_CAP_FLOWTABLE_NIC_TX(mdev, sw_owner); 1231d918647SAlex Vesker 124*64f45c0fSYevgeny Kliteynik caps->max_ft_level = MLX5_CAP_FLOWTABLE_NIC_RX(mdev, max_ft_level); 125*64f45c0fSYevgeny Kliteynik 1261d918647SAlex Vesker caps->log_icm_size = MLX5_CAP_DEV_MEM(mdev, log_steering_sw_icm_size); 1271d918647SAlex Vesker caps->hdr_modify_icm_addr = 1281d918647SAlex Vesker MLX5_CAP64_DEV_MEM(mdev, header_modify_sw_icm_start_address); 1291d918647SAlex Vesker 1301d918647SAlex Vesker caps->roce_min_src_udp = MLX5_CAP_ROCE(mdev, r_roce_min_src_udp_port); 1311d918647SAlex Vesker 1321d918647SAlex Vesker return 0; 1331d918647SAlex Vesker } 1341d918647SAlex Vesker 1351d918647SAlex Vesker int mlx5dr_cmd_query_flow_table(struct mlx5_core_dev *dev, 1361d918647SAlex Vesker enum fs_flow_table_type type, 1371d918647SAlex Vesker u32 table_id, 1381d918647SAlex Vesker struct mlx5dr_cmd_query_flow_table_details *output) 1391d918647SAlex Vesker { 1401d918647SAlex Vesker u32 out[MLX5_ST_SZ_DW(query_flow_table_out)] = {}; 1411d918647SAlex Vesker u32 in[MLX5_ST_SZ_DW(query_flow_table_in)] = {}; 1421d918647SAlex Vesker int err; 1431d918647SAlex Vesker 1441d918647SAlex Vesker MLX5_SET(query_flow_table_in, in, opcode, 1451d918647SAlex Vesker MLX5_CMD_OP_QUERY_FLOW_TABLE); 1461d918647SAlex Vesker 1471d918647SAlex Vesker MLX5_SET(query_flow_table_in, in, table_type, type); 1481d918647SAlex Vesker MLX5_SET(query_flow_table_in, in, table_id, table_id); 1491d918647SAlex Vesker 1507ba294e4SLeon Romanovsky err = mlx5_cmd_exec_inout(dev, query_flow_table, in, out); 1511d918647SAlex Vesker if (err) 1521d918647SAlex Vesker return err; 1531d918647SAlex Vesker 1541d918647SAlex Vesker output->status = MLX5_GET(query_flow_table_out, out, status); 1551d918647SAlex Vesker output->level = MLX5_GET(query_flow_table_out, out, flow_table_context.level); 1561d918647SAlex Vesker 1571d918647SAlex Vesker output->sw_owner_icm_root_1 = MLX5_GET64(query_flow_table_out, out, 1581d918647SAlex Vesker flow_table_context.sw_owner_icm_root_1); 1591d918647SAlex Vesker output->sw_owner_icm_root_0 = MLX5_GET64(query_flow_table_out, out, 1601d918647SAlex Vesker flow_table_context.sw_owner_icm_root_0); 1611d918647SAlex Vesker 1621d918647SAlex Vesker return 0; 1631d918647SAlex Vesker } 1641d918647SAlex Vesker 1651d918647SAlex Vesker int mlx5dr_cmd_sync_steering(struct mlx5_core_dev *mdev) 1661d918647SAlex Vesker { 1671d918647SAlex Vesker u32 in[MLX5_ST_SZ_DW(sync_steering_in)] = {}; 1681d918647SAlex Vesker 1691d918647SAlex Vesker MLX5_SET(sync_steering_in, in, opcode, MLX5_CMD_OP_SYNC_STEERING); 1701d918647SAlex Vesker 1717ba294e4SLeon Romanovsky return mlx5_cmd_exec_in(mdev, sync_steering, in); 1721d918647SAlex Vesker } 1731d918647SAlex Vesker 1741d918647SAlex Vesker int mlx5dr_cmd_set_fte_modify_and_vport(struct mlx5_core_dev *mdev, 1751d918647SAlex Vesker u32 table_type, 1761d918647SAlex Vesker u32 table_id, 1771d918647SAlex Vesker u32 group_id, 1781d918647SAlex Vesker u32 modify_header_id, 1791d918647SAlex Vesker u32 vport_id) 1801d918647SAlex Vesker { 1811d918647SAlex Vesker u32 out[MLX5_ST_SZ_DW(set_fte_out)] = {}; 1821d918647SAlex Vesker void *in_flow_context; 1831d918647SAlex Vesker unsigned int inlen; 1841d918647SAlex Vesker void *in_dests; 1851d918647SAlex Vesker u32 *in; 1861d918647SAlex Vesker int err; 1871d918647SAlex Vesker 1881d918647SAlex Vesker inlen = MLX5_ST_SZ_BYTES(set_fte_in) + 1891d918647SAlex Vesker 1 * MLX5_ST_SZ_BYTES(dest_format_struct); /* One destination only */ 1901d918647SAlex Vesker 1911d918647SAlex Vesker in = kvzalloc(inlen, GFP_KERNEL); 1921d918647SAlex Vesker if (!in) 1931d918647SAlex Vesker return -ENOMEM; 1941d918647SAlex Vesker 1951d918647SAlex Vesker MLX5_SET(set_fte_in, in, opcode, MLX5_CMD_OP_SET_FLOW_TABLE_ENTRY); 1961d918647SAlex Vesker MLX5_SET(set_fte_in, in, table_type, table_type); 1971d918647SAlex Vesker MLX5_SET(set_fte_in, in, table_id, table_id); 1981d918647SAlex Vesker 1991d918647SAlex Vesker in_flow_context = MLX5_ADDR_OF(set_fte_in, in, flow_context); 2001d918647SAlex Vesker MLX5_SET(flow_context, in_flow_context, group_id, group_id); 2011d918647SAlex Vesker MLX5_SET(flow_context, in_flow_context, modify_header_id, modify_header_id); 2021d918647SAlex Vesker MLX5_SET(flow_context, in_flow_context, destination_list_size, 1); 2031d918647SAlex Vesker MLX5_SET(flow_context, in_flow_context, action, 2041d918647SAlex Vesker MLX5_FLOW_CONTEXT_ACTION_FWD_DEST | 2051d918647SAlex Vesker MLX5_FLOW_CONTEXT_ACTION_MOD_HDR); 2061d918647SAlex Vesker 2071d918647SAlex Vesker in_dests = MLX5_ADDR_OF(flow_context, in_flow_context, destination); 2081d918647SAlex Vesker MLX5_SET(dest_format_struct, in_dests, destination_type, 2091d918647SAlex Vesker MLX5_FLOW_DESTINATION_TYPE_VPORT); 2101d918647SAlex Vesker MLX5_SET(dest_format_struct, in_dests, destination_id, vport_id); 2111d918647SAlex Vesker 2121d918647SAlex Vesker err = mlx5_cmd_exec(mdev, in, inlen, out, sizeof(out)); 2131d918647SAlex Vesker kvfree(in); 2141d918647SAlex Vesker 2151d918647SAlex Vesker return err; 2161d918647SAlex Vesker } 2171d918647SAlex Vesker 2181d918647SAlex Vesker int mlx5dr_cmd_del_flow_table_entry(struct mlx5_core_dev *mdev, 2191d918647SAlex Vesker u32 table_type, 2201d918647SAlex Vesker u32 table_id) 2211d918647SAlex Vesker { 2221d918647SAlex Vesker u32 in[MLX5_ST_SZ_DW(delete_fte_in)] = {}; 2231d918647SAlex Vesker 2241d918647SAlex Vesker MLX5_SET(delete_fte_in, in, opcode, MLX5_CMD_OP_DELETE_FLOW_TABLE_ENTRY); 2251d918647SAlex Vesker MLX5_SET(delete_fte_in, in, table_type, table_type); 2261d918647SAlex Vesker MLX5_SET(delete_fte_in, in, table_id, table_id); 2271d918647SAlex Vesker 2287ba294e4SLeon Romanovsky return mlx5_cmd_exec_in(mdev, delete_fte, in); 2291d918647SAlex Vesker } 2301d918647SAlex Vesker 2311d918647SAlex Vesker int mlx5dr_cmd_alloc_modify_header(struct mlx5_core_dev *mdev, 2321d918647SAlex Vesker u32 table_type, 2331d918647SAlex Vesker u8 num_of_actions, 2341d918647SAlex Vesker u64 *actions, 2351d918647SAlex Vesker u32 *modify_header_id) 2361d918647SAlex Vesker { 2371d918647SAlex Vesker u32 out[MLX5_ST_SZ_DW(alloc_modify_header_context_out)] = {}; 2381d918647SAlex Vesker void *p_actions; 2391d918647SAlex Vesker u32 inlen; 2401d918647SAlex Vesker u32 *in; 2411d918647SAlex Vesker int err; 2421d918647SAlex Vesker 2431d918647SAlex Vesker inlen = MLX5_ST_SZ_BYTES(alloc_modify_header_context_in) + 2441d918647SAlex Vesker num_of_actions * sizeof(u64); 2451d918647SAlex Vesker in = kvzalloc(inlen, GFP_KERNEL); 2461d918647SAlex Vesker if (!in) 2471d918647SAlex Vesker return -ENOMEM; 2481d918647SAlex Vesker 2491d918647SAlex Vesker MLX5_SET(alloc_modify_header_context_in, in, opcode, 2501d918647SAlex Vesker MLX5_CMD_OP_ALLOC_MODIFY_HEADER_CONTEXT); 2511d918647SAlex Vesker MLX5_SET(alloc_modify_header_context_in, in, table_type, table_type); 2521d918647SAlex Vesker MLX5_SET(alloc_modify_header_context_in, in, num_of_actions, num_of_actions); 2531d918647SAlex Vesker p_actions = MLX5_ADDR_OF(alloc_modify_header_context_in, in, actions); 2541d918647SAlex Vesker memcpy(p_actions, actions, num_of_actions * sizeof(u64)); 2551d918647SAlex Vesker 2561d918647SAlex Vesker err = mlx5_cmd_exec(mdev, in, inlen, out, sizeof(out)); 2571d918647SAlex Vesker if (err) 2581d918647SAlex Vesker goto out; 2591d918647SAlex Vesker 2601d918647SAlex Vesker *modify_header_id = MLX5_GET(alloc_modify_header_context_out, out, 2611d918647SAlex Vesker modify_header_id); 2621d918647SAlex Vesker out: 2631d918647SAlex Vesker kvfree(in); 2641d918647SAlex Vesker return err; 2651d918647SAlex Vesker } 2661d918647SAlex Vesker 2671d918647SAlex Vesker int mlx5dr_cmd_dealloc_modify_header(struct mlx5_core_dev *mdev, 2681d918647SAlex Vesker u32 modify_header_id) 2691d918647SAlex Vesker { 2701d918647SAlex Vesker u32 in[MLX5_ST_SZ_DW(dealloc_modify_header_context_in)] = {}; 2711d918647SAlex Vesker 2721d918647SAlex Vesker MLX5_SET(dealloc_modify_header_context_in, in, opcode, 2731d918647SAlex Vesker MLX5_CMD_OP_DEALLOC_MODIFY_HEADER_CONTEXT); 2741d918647SAlex Vesker MLX5_SET(dealloc_modify_header_context_in, in, modify_header_id, 2751d918647SAlex Vesker modify_header_id); 2761d918647SAlex Vesker 2777ba294e4SLeon Romanovsky return mlx5_cmd_exec_in(mdev, dealloc_modify_header_context, in); 2781d918647SAlex Vesker } 2791d918647SAlex Vesker 2801d918647SAlex Vesker int mlx5dr_cmd_create_empty_flow_group(struct mlx5_core_dev *mdev, 2811d918647SAlex Vesker u32 table_type, 2821d918647SAlex Vesker u32 table_id, 2831d918647SAlex Vesker u32 *group_id) 2841d918647SAlex Vesker { 2851d918647SAlex Vesker u32 out[MLX5_ST_SZ_DW(create_flow_group_out)] = {}; 2861d918647SAlex Vesker int inlen = MLX5_ST_SZ_BYTES(create_flow_group_in); 2871d918647SAlex Vesker u32 *in; 2881d918647SAlex Vesker int err; 2891d918647SAlex Vesker 2901d918647SAlex Vesker in = kzalloc(inlen, GFP_KERNEL); 2911d918647SAlex Vesker if (!in) 2921d918647SAlex Vesker return -ENOMEM; 2931d918647SAlex Vesker 2941d918647SAlex Vesker MLX5_SET(create_flow_group_in, in, opcode, MLX5_CMD_OP_CREATE_FLOW_GROUP); 2951d918647SAlex Vesker MLX5_SET(create_flow_group_in, in, table_type, table_type); 2961d918647SAlex Vesker MLX5_SET(create_flow_group_in, in, table_id, table_id); 2971d918647SAlex Vesker 2987ba294e4SLeon Romanovsky err = mlx5_cmd_exec_inout(mdev, create_flow_group, in, out); 2991d918647SAlex Vesker if (err) 3001d918647SAlex Vesker goto out; 3011d918647SAlex Vesker 3021d918647SAlex Vesker *group_id = MLX5_GET(create_flow_group_out, out, group_id); 3031d918647SAlex Vesker 3041d918647SAlex Vesker out: 3051d918647SAlex Vesker kfree(in); 3061d918647SAlex Vesker return err; 3071d918647SAlex Vesker } 3081d918647SAlex Vesker 3091d918647SAlex Vesker int mlx5dr_cmd_destroy_flow_group(struct mlx5_core_dev *mdev, 3101d918647SAlex Vesker u32 table_type, 3111d918647SAlex Vesker u32 table_id, 3121d918647SAlex Vesker u32 group_id) 3131d918647SAlex Vesker { 3141d918647SAlex Vesker u32 in[MLX5_ST_SZ_DW(destroy_flow_group_in)] = {}; 3151d918647SAlex Vesker 3167ba294e4SLeon Romanovsky MLX5_SET(destroy_flow_group_in, in, opcode, 3177ba294e4SLeon Romanovsky MLX5_CMD_OP_DESTROY_FLOW_GROUP); 3181d918647SAlex Vesker MLX5_SET(destroy_flow_group_in, in, table_type, table_type); 3191d918647SAlex Vesker MLX5_SET(destroy_flow_group_in, in, table_id, table_id); 3201d918647SAlex Vesker MLX5_SET(destroy_flow_group_in, in, group_id, group_id); 3211d918647SAlex Vesker 3227ba294e4SLeon Romanovsky return mlx5_cmd_exec_in(mdev, destroy_flow_group, in); 3231d918647SAlex Vesker } 3241d918647SAlex Vesker 3251d918647SAlex Vesker int mlx5dr_cmd_create_flow_table(struct mlx5_core_dev *mdev, 326cc78dbd7SAlex Vesker struct mlx5dr_cmd_create_flow_table_attr *attr, 3271d918647SAlex Vesker u64 *fdb_rx_icm_addr, 3281d918647SAlex Vesker u32 *table_id) 3291d918647SAlex Vesker { 3301d918647SAlex Vesker u32 out[MLX5_ST_SZ_DW(create_flow_table_out)] = {}; 3311d918647SAlex Vesker u32 in[MLX5_ST_SZ_DW(create_flow_table_in)] = {}; 3321d918647SAlex Vesker void *ft_mdev; 3331d918647SAlex Vesker int err; 3341d918647SAlex Vesker 3351d918647SAlex Vesker MLX5_SET(create_flow_table_in, in, opcode, MLX5_CMD_OP_CREATE_FLOW_TABLE); 336cc78dbd7SAlex Vesker MLX5_SET(create_flow_table_in, in, table_type, attr->table_type); 3371d918647SAlex Vesker 3381d918647SAlex Vesker ft_mdev = MLX5_ADDR_OF(create_flow_table_in, in, flow_table_context); 339cc78dbd7SAlex Vesker MLX5_SET(flow_table_context, ft_mdev, termination_table, attr->term_tbl); 340cc78dbd7SAlex Vesker MLX5_SET(flow_table_context, ft_mdev, sw_owner, attr->sw_owner); 341cc78dbd7SAlex Vesker MLX5_SET(flow_table_context, ft_mdev, level, attr->level); 3421d918647SAlex Vesker 343cc78dbd7SAlex Vesker if (attr->sw_owner) { 3441d918647SAlex Vesker /* icm_addr_0 used for FDB RX / NIC TX / NIC_RX 3451d918647SAlex Vesker * icm_addr_1 used for FDB TX 3461d918647SAlex Vesker */ 347cc78dbd7SAlex Vesker if (attr->table_type == MLX5_FLOW_TABLE_TYPE_NIC_RX) { 3481d918647SAlex Vesker MLX5_SET64(flow_table_context, ft_mdev, 349cc78dbd7SAlex Vesker sw_owner_icm_root_0, attr->icm_addr_rx); 350cc78dbd7SAlex Vesker } else if (attr->table_type == MLX5_FLOW_TABLE_TYPE_NIC_TX) { 3511d918647SAlex Vesker MLX5_SET64(flow_table_context, ft_mdev, 352cc78dbd7SAlex Vesker sw_owner_icm_root_0, attr->icm_addr_tx); 353cc78dbd7SAlex Vesker } else if (attr->table_type == MLX5_FLOW_TABLE_TYPE_FDB) { 3541d918647SAlex Vesker MLX5_SET64(flow_table_context, ft_mdev, 355cc78dbd7SAlex Vesker sw_owner_icm_root_0, attr->icm_addr_rx); 3561d918647SAlex Vesker MLX5_SET64(flow_table_context, ft_mdev, 357cc78dbd7SAlex Vesker sw_owner_icm_root_1, attr->icm_addr_tx); 3581d918647SAlex Vesker } 3591d918647SAlex Vesker } 3601d918647SAlex Vesker 361cc78dbd7SAlex Vesker MLX5_SET(create_flow_table_in, in, flow_table_context.decap_en, 362cc78dbd7SAlex Vesker attr->decap_en); 363cc78dbd7SAlex Vesker MLX5_SET(create_flow_table_in, in, flow_table_context.reformat_en, 364cc78dbd7SAlex Vesker attr->reformat_en); 365cc78dbd7SAlex Vesker 3667ba294e4SLeon Romanovsky err = mlx5_cmd_exec_inout(mdev, create_flow_table, in, out); 3671d918647SAlex Vesker if (err) 3681d918647SAlex Vesker return err; 3691d918647SAlex Vesker 3701d918647SAlex Vesker *table_id = MLX5_GET(create_flow_table_out, out, table_id); 371cc78dbd7SAlex Vesker if (!attr->sw_owner && attr->table_type == MLX5_FLOW_TABLE_TYPE_FDB && 372cc78dbd7SAlex Vesker fdb_rx_icm_addr) 3731d918647SAlex Vesker *fdb_rx_icm_addr = 3741d918647SAlex Vesker (u64)MLX5_GET(create_flow_table_out, out, icm_address_31_0) | 3751d918647SAlex Vesker (u64)MLX5_GET(create_flow_table_out, out, icm_address_39_32) << 32 | 3761d918647SAlex Vesker (u64)MLX5_GET(create_flow_table_out, out, icm_address_63_40) << 40; 3771d918647SAlex Vesker 3781d918647SAlex Vesker return 0; 3791d918647SAlex Vesker } 3801d918647SAlex Vesker 3811d918647SAlex Vesker int mlx5dr_cmd_destroy_flow_table(struct mlx5_core_dev *mdev, 3821d918647SAlex Vesker u32 table_id, 3831d918647SAlex Vesker u32 table_type) 3841d918647SAlex Vesker { 3851d918647SAlex Vesker u32 in[MLX5_ST_SZ_DW(destroy_flow_table_in)] = {}; 3861d918647SAlex Vesker 3871d918647SAlex Vesker MLX5_SET(destroy_flow_table_in, in, opcode, 3881d918647SAlex Vesker MLX5_CMD_OP_DESTROY_FLOW_TABLE); 3891d918647SAlex Vesker MLX5_SET(destroy_flow_table_in, in, table_type, table_type); 3901d918647SAlex Vesker MLX5_SET(destroy_flow_table_in, in, table_id, table_id); 3911d918647SAlex Vesker 3927ba294e4SLeon Romanovsky return mlx5_cmd_exec_in(mdev, destroy_flow_table, in); 3931d918647SAlex Vesker } 3941d918647SAlex Vesker 3951d918647SAlex Vesker int mlx5dr_cmd_create_reformat_ctx(struct mlx5_core_dev *mdev, 3961d918647SAlex Vesker enum mlx5_reformat_ctx_type rt, 3971d918647SAlex Vesker size_t reformat_size, 3981d918647SAlex Vesker void *reformat_data, 3991d918647SAlex Vesker u32 *reformat_id) 4001d918647SAlex Vesker { 4011d918647SAlex Vesker u32 out[MLX5_ST_SZ_DW(alloc_packet_reformat_context_out)] = {}; 4021d918647SAlex Vesker size_t inlen, cmd_data_sz, cmd_total_sz; 4031d918647SAlex Vesker void *prctx; 4041d918647SAlex Vesker void *pdata; 4051d918647SAlex Vesker void *in; 4061d918647SAlex Vesker int err; 4071d918647SAlex Vesker 4081d918647SAlex Vesker cmd_total_sz = MLX5_ST_SZ_BYTES(alloc_packet_reformat_context_in); 4091d918647SAlex Vesker cmd_data_sz = MLX5_FLD_SZ_BYTES(alloc_packet_reformat_context_in, 4101d918647SAlex Vesker packet_reformat_context.reformat_data); 4111d918647SAlex Vesker inlen = ALIGN(cmd_total_sz + reformat_size - cmd_data_sz, 4); 4121d918647SAlex Vesker in = kvzalloc(inlen, GFP_KERNEL); 4131d918647SAlex Vesker if (!in) 4141d918647SAlex Vesker return -ENOMEM; 4151d918647SAlex Vesker 4161d918647SAlex Vesker MLX5_SET(alloc_packet_reformat_context_in, in, opcode, 4171d918647SAlex Vesker MLX5_CMD_OP_ALLOC_PACKET_REFORMAT_CONTEXT); 4181d918647SAlex Vesker 4191d918647SAlex Vesker prctx = MLX5_ADDR_OF(alloc_packet_reformat_context_in, in, packet_reformat_context); 4201d918647SAlex Vesker pdata = MLX5_ADDR_OF(packet_reformat_context_in, prctx, reformat_data); 4211d918647SAlex Vesker 4221d918647SAlex Vesker MLX5_SET(packet_reformat_context_in, prctx, reformat_type, rt); 4231d918647SAlex Vesker MLX5_SET(packet_reformat_context_in, prctx, reformat_data_size, reformat_size); 4241d918647SAlex Vesker memcpy(pdata, reformat_data, reformat_size); 4251d918647SAlex Vesker 4261d918647SAlex Vesker err = mlx5_cmd_exec(mdev, in, inlen, out, sizeof(out)); 4271d918647SAlex Vesker if (err) 4281d918647SAlex Vesker return err; 4291d918647SAlex Vesker 4301d918647SAlex Vesker *reformat_id = MLX5_GET(alloc_packet_reformat_context_out, out, packet_reformat_id); 4311d918647SAlex Vesker kvfree(in); 4321d918647SAlex Vesker 4331d918647SAlex Vesker return err; 4341d918647SAlex Vesker } 4351d918647SAlex Vesker 4361d918647SAlex Vesker void mlx5dr_cmd_destroy_reformat_ctx(struct mlx5_core_dev *mdev, 4371d918647SAlex Vesker u32 reformat_id) 4381d918647SAlex Vesker { 4391d918647SAlex Vesker u32 in[MLX5_ST_SZ_DW(dealloc_packet_reformat_context_in)] = {}; 4401d918647SAlex Vesker 4411d918647SAlex Vesker MLX5_SET(dealloc_packet_reformat_context_in, in, opcode, 4421d918647SAlex Vesker MLX5_CMD_OP_DEALLOC_PACKET_REFORMAT_CONTEXT); 4431d918647SAlex Vesker MLX5_SET(dealloc_packet_reformat_context_in, in, packet_reformat_id, 4441d918647SAlex Vesker reformat_id); 4451d918647SAlex Vesker 4467ba294e4SLeon Romanovsky mlx5_cmd_exec_in(mdev, dealloc_packet_reformat_context, in); 4471d918647SAlex Vesker } 4481d918647SAlex Vesker 4491d918647SAlex Vesker int mlx5dr_cmd_query_gid(struct mlx5_core_dev *mdev, u8 vhca_port_num, 4501d918647SAlex Vesker u16 index, struct mlx5dr_cmd_gid_attr *attr) 4511d918647SAlex Vesker { 4521d918647SAlex Vesker u32 out[MLX5_ST_SZ_DW(query_roce_address_out)] = {}; 4531d918647SAlex Vesker u32 in[MLX5_ST_SZ_DW(query_roce_address_in)] = {}; 4541d918647SAlex Vesker int err; 4551d918647SAlex Vesker 4561d918647SAlex Vesker MLX5_SET(query_roce_address_in, in, opcode, 4571d918647SAlex Vesker MLX5_CMD_OP_QUERY_ROCE_ADDRESS); 4581d918647SAlex Vesker 4591d918647SAlex Vesker MLX5_SET(query_roce_address_in, in, roce_address_index, index); 4601d918647SAlex Vesker MLX5_SET(query_roce_address_in, in, vhca_port_num, vhca_port_num); 4611d918647SAlex Vesker 4627ba294e4SLeon Romanovsky err = mlx5_cmd_exec_inout(mdev, query_roce_address, in, out); 4631d918647SAlex Vesker if (err) 4641d918647SAlex Vesker return err; 4651d918647SAlex Vesker 4661d918647SAlex Vesker memcpy(&attr->gid, 4671d918647SAlex Vesker MLX5_ADDR_OF(query_roce_address_out, 4681d918647SAlex Vesker out, roce_address.source_l3_address), 4691d918647SAlex Vesker sizeof(attr->gid)); 4701d918647SAlex Vesker memcpy(attr->mac, 4711d918647SAlex Vesker MLX5_ADDR_OF(query_roce_address_out, out, 4721d918647SAlex Vesker roce_address.source_mac_47_32), 4731d918647SAlex Vesker sizeof(attr->mac)); 4741d918647SAlex Vesker 4751d918647SAlex Vesker if (MLX5_GET(query_roce_address_out, out, 4761d918647SAlex Vesker roce_address.roce_version) == MLX5_ROCE_VERSION_2) 4771d918647SAlex Vesker attr->roce_ver = MLX5_ROCE_VERSION_2; 4781d918647SAlex Vesker else 4791d918647SAlex Vesker attr->roce_ver = MLX5_ROCE_VERSION_1; 4801d918647SAlex Vesker 4811d918647SAlex Vesker return 0; 4821d918647SAlex Vesker } 4836de03d2dSErez Shitrit 4846de03d2dSErez Shitrit static int mlx5dr_cmd_set_extended_dest(struct mlx5_core_dev *dev, 4856de03d2dSErez Shitrit struct mlx5dr_cmd_fte_info *fte, 4866de03d2dSErez Shitrit bool *extended_dest) 4876de03d2dSErez Shitrit { 4886de03d2dSErez Shitrit int fw_log_max_fdb_encap_uplink = MLX5_CAP_ESW(dev, log_max_fdb_encap_uplink); 4896de03d2dSErez Shitrit int num_fwd_destinations = 0; 4906de03d2dSErez Shitrit int num_encap = 0; 4916de03d2dSErez Shitrit int i; 4926de03d2dSErez Shitrit 4936de03d2dSErez Shitrit *extended_dest = false; 4946de03d2dSErez Shitrit if (!(fte->action.action & MLX5_FLOW_CONTEXT_ACTION_FWD_DEST)) 4956de03d2dSErez Shitrit return 0; 4966de03d2dSErez Shitrit for (i = 0; i < fte->dests_size; i++) { 4976de03d2dSErez Shitrit if (fte->dest_arr[i].type == MLX5_FLOW_DESTINATION_TYPE_COUNTER) 4986de03d2dSErez Shitrit continue; 4996de03d2dSErez Shitrit if (fte->dest_arr[i].type == MLX5_FLOW_DESTINATION_TYPE_VPORT && 5006de03d2dSErez Shitrit fte->dest_arr[i].vport.flags & MLX5_FLOW_DEST_VPORT_REFORMAT_ID) 5016de03d2dSErez Shitrit num_encap++; 5026de03d2dSErez Shitrit num_fwd_destinations++; 5036de03d2dSErez Shitrit } 5046de03d2dSErez Shitrit 5056de03d2dSErez Shitrit if (num_fwd_destinations > 1 && num_encap > 0) 5066de03d2dSErez Shitrit *extended_dest = true; 5076de03d2dSErez Shitrit 5086de03d2dSErez Shitrit if (*extended_dest && !fw_log_max_fdb_encap_uplink) { 5096de03d2dSErez Shitrit mlx5_core_warn(dev, "FW does not support extended destination"); 5106de03d2dSErez Shitrit return -EOPNOTSUPP; 5116de03d2dSErez Shitrit } 5126de03d2dSErez Shitrit if (num_encap > (1 << fw_log_max_fdb_encap_uplink)) { 5136de03d2dSErez Shitrit mlx5_core_warn(dev, "FW does not support more than %d encaps", 5146de03d2dSErez Shitrit 1 << fw_log_max_fdb_encap_uplink); 5156de03d2dSErez Shitrit return -EOPNOTSUPP; 5166de03d2dSErez Shitrit } 5176de03d2dSErez Shitrit 5186de03d2dSErez Shitrit return 0; 5196de03d2dSErez Shitrit } 5206de03d2dSErez Shitrit 5216de03d2dSErez Shitrit int mlx5dr_cmd_set_fte(struct mlx5_core_dev *dev, 5226de03d2dSErez Shitrit int opmod, int modify_mask, 5236de03d2dSErez Shitrit struct mlx5dr_cmd_ft_info *ft, 5246de03d2dSErez Shitrit u32 group_id, 5256de03d2dSErez Shitrit struct mlx5dr_cmd_fte_info *fte) 5266de03d2dSErez Shitrit { 5276de03d2dSErez Shitrit u32 out[MLX5_ST_SZ_DW(set_fte_out)] = {}; 5286de03d2dSErez Shitrit void *in_flow_context, *vlan; 5296de03d2dSErez Shitrit bool extended_dest = false; 5306de03d2dSErez Shitrit void *in_match_value; 5316de03d2dSErez Shitrit unsigned int inlen; 5326de03d2dSErez Shitrit int dst_cnt_size; 5336de03d2dSErez Shitrit void *in_dests; 5346de03d2dSErez Shitrit u32 *in; 5356de03d2dSErez Shitrit int err; 5366de03d2dSErez Shitrit int i; 5376de03d2dSErez Shitrit 5386de03d2dSErez Shitrit if (mlx5dr_cmd_set_extended_dest(dev, fte, &extended_dest)) 5396de03d2dSErez Shitrit return -EOPNOTSUPP; 5406de03d2dSErez Shitrit 5416de03d2dSErez Shitrit if (!extended_dest) 5426de03d2dSErez Shitrit dst_cnt_size = MLX5_ST_SZ_BYTES(dest_format_struct); 5436de03d2dSErez Shitrit else 5446de03d2dSErez Shitrit dst_cnt_size = MLX5_ST_SZ_BYTES(extended_dest_format); 5456de03d2dSErez Shitrit 5466de03d2dSErez Shitrit inlen = MLX5_ST_SZ_BYTES(set_fte_in) + fte->dests_size * dst_cnt_size; 5476de03d2dSErez Shitrit in = kvzalloc(inlen, GFP_KERNEL); 5486de03d2dSErez Shitrit if (!in) 5496de03d2dSErez Shitrit return -ENOMEM; 5506de03d2dSErez Shitrit 5516de03d2dSErez Shitrit MLX5_SET(set_fte_in, in, opcode, MLX5_CMD_OP_SET_FLOW_TABLE_ENTRY); 5526de03d2dSErez Shitrit MLX5_SET(set_fte_in, in, op_mod, opmod); 5536de03d2dSErez Shitrit MLX5_SET(set_fte_in, in, modify_enable_mask, modify_mask); 5546de03d2dSErez Shitrit MLX5_SET(set_fte_in, in, table_type, ft->type); 5556de03d2dSErez Shitrit MLX5_SET(set_fte_in, in, table_id, ft->id); 5566de03d2dSErez Shitrit MLX5_SET(set_fte_in, in, flow_index, fte->index); 5576de03d2dSErez Shitrit if (ft->vport) { 5586de03d2dSErez Shitrit MLX5_SET(set_fte_in, in, vport_number, ft->vport); 5596de03d2dSErez Shitrit MLX5_SET(set_fte_in, in, other_vport, 1); 5606de03d2dSErez Shitrit } 5616de03d2dSErez Shitrit 5626de03d2dSErez Shitrit in_flow_context = MLX5_ADDR_OF(set_fte_in, in, flow_context); 5636de03d2dSErez Shitrit MLX5_SET(flow_context, in_flow_context, group_id, group_id); 5646de03d2dSErez Shitrit 5656de03d2dSErez Shitrit MLX5_SET(flow_context, in_flow_context, flow_tag, 5666de03d2dSErez Shitrit fte->flow_context.flow_tag); 5676de03d2dSErez Shitrit MLX5_SET(flow_context, in_flow_context, flow_source, 5686de03d2dSErez Shitrit fte->flow_context.flow_source); 5696de03d2dSErez Shitrit 5706de03d2dSErez Shitrit MLX5_SET(flow_context, in_flow_context, extended_destination, 5716de03d2dSErez Shitrit extended_dest); 5726de03d2dSErez Shitrit if (extended_dest) { 5736de03d2dSErez Shitrit u32 action; 5746de03d2dSErez Shitrit 5756de03d2dSErez Shitrit action = fte->action.action & 5766de03d2dSErez Shitrit ~MLX5_FLOW_CONTEXT_ACTION_PACKET_REFORMAT; 5776de03d2dSErez Shitrit MLX5_SET(flow_context, in_flow_context, action, action); 5786de03d2dSErez Shitrit } else { 5796de03d2dSErez Shitrit MLX5_SET(flow_context, in_flow_context, action, 5806de03d2dSErez Shitrit fte->action.action); 5816de03d2dSErez Shitrit if (fte->action.pkt_reformat) 5826de03d2dSErez Shitrit MLX5_SET(flow_context, in_flow_context, packet_reformat_id, 5836de03d2dSErez Shitrit fte->action.pkt_reformat->id); 5846de03d2dSErez Shitrit } 5856de03d2dSErez Shitrit if (fte->action.modify_hdr) 5866de03d2dSErez Shitrit MLX5_SET(flow_context, in_flow_context, modify_header_id, 5876de03d2dSErez Shitrit fte->action.modify_hdr->id); 5886de03d2dSErez Shitrit 5896de03d2dSErez Shitrit vlan = MLX5_ADDR_OF(flow_context, in_flow_context, push_vlan); 5906de03d2dSErez Shitrit 5916de03d2dSErez Shitrit MLX5_SET(vlan, vlan, ethtype, fte->action.vlan[0].ethtype); 5926de03d2dSErez Shitrit MLX5_SET(vlan, vlan, vid, fte->action.vlan[0].vid); 5936de03d2dSErez Shitrit MLX5_SET(vlan, vlan, prio, fte->action.vlan[0].prio); 5946de03d2dSErez Shitrit 5956de03d2dSErez Shitrit vlan = MLX5_ADDR_OF(flow_context, in_flow_context, push_vlan_2); 5966de03d2dSErez Shitrit 5976de03d2dSErez Shitrit MLX5_SET(vlan, vlan, ethtype, fte->action.vlan[1].ethtype); 5986de03d2dSErez Shitrit MLX5_SET(vlan, vlan, vid, fte->action.vlan[1].vid); 5996de03d2dSErez Shitrit MLX5_SET(vlan, vlan, prio, fte->action.vlan[1].prio); 6006de03d2dSErez Shitrit 6016de03d2dSErez Shitrit in_match_value = MLX5_ADDR_OF(flow_context, in_flow_context, 6026de03d2dSErez Shitrit match_value); 6036de03d2dSErez Shitrit memcpy(in_match_value, fte->val, sizeof(u32) * MLX5_ST_SZ_DW_MATCH_PARAM); 6046de03d2dSErez Shitrit 6056de03d2dSErez Shitrit in_dests = MLX5_ADDR_OF(flow_context, in_flow_context, destination); 6066de03d2dSErez Shitrit if (fte->action.action & MLX5_FLOW_CONTEXT_ACTION_FWD_DEST) { 6076de03d2dSErez Shitrit int list_size = 0; 6086de03d2dSErez Shitrit 6096de03d2dSErez Shitrit for (i = 0; i < fte->dests_size; i++) { 6106de03d2dSErez Shitrit unsigned int id, type = fte->dest_arr[i].type; 6116de03d2dSErez Shitrit 6126de03d2dSErez Shitrit if (type == MLX5_FLOW_DESTINATION_TYPE_COUNTER) 6136de03d2dSErez Shitrit continue; 6146de03d2dSErez Shitrit 6156de03d2dSErez Shitrit switch (type) { 6166de03d2dSErez Shitrit case MLX5_FLOW_DESTINATION_TYPE_FLOW_TABLE_NUM: 6176de03d2dSErez Shitrit id = fte->dest_arr[i].ft_num; 6186de03d2dSErez Shitrit type = MLX5_FLOW_DESTINATION_TYPE_FLOW_TABLE; 6196de03d2dSErez Shitrit break; 6206de03d2dSErez Shitrit case MLX5_FLOW_DESTINATION_TYPE_FLOW_TABLE: 6216de03d2dSErez Shitrit id = fte->dest_arr[i].ft_id; 6226de03d2dSErez Shitrit break; 6236de03d2dSErez Shitrit case MLX5_FLOW_DESTINATION_TYPE_VPORT: 6246de03d2dSErez Shitrit id = fte->dest_arr[i].vport.num; 6256de03d2dSErez Shitrit MLX5_SET(dest_format_struct, in_dests, 6266de03d2dSErez Shitrit destination_eswitch_owner_vhca_id_valid, 6276de03d2dSErez Shitrit !!(fte->dest_arr[i].vport.flags & 6286de03d2dSErez Shitrit MLX5_FLOW_DEST_VPORT_VHCA_ID)); 6296de03d2dSErez Shitrit MLX5_SET(dest_format_struct, in_dests, 6306de03d2dSErez Shitrit destination_eswitch_owner_vhca_id, 6316de03d2dSErez Shitrit fte->dest_arr[i].vport.vhca_id); 6326de03d2dSErez Shitrit if (extended_dest && (fte->dest_arr[i].vport.flags & 6336de03d2dSErez Shitrit MLX5_FLOW_DEST_VPORT_REFORMAT_ID)) { 6346de03d2dSErez Shitrit MLX5_SET(dest_format_struct, in_dests, 6356de03d2dSErez Shitrit packet_reformat, 6366de03d2dSErez Shitrit !!(fte->dest_arr[i].vport.flags & 6376de03d2dSErez Shitrit MLX5_FLOW_DEST_VPORT_REFORMAT_ID)); 6386de03d2dSErez Shitrit MLX5_SET(extended_dest_format, in_dests, 6396de03d2dSErez Shitrit packet_reformat_id, 6406de03d2dSErez Shitrit fte->dest_arr[i].vport.reformat_id); 6416de03d2dSErez Shitrit } 6426de03d2dSErez Shitrit break; 6436de03d2dSErez Shitrit default: 6446de03d2dSErez Shitrit id = fte->dest_arr[i].tir_num; 6456de03d2dSErez Shitrit } 6466de03d2dSErez Shitrit 6476de03d2dSErez Shitrit MLX5_SET(dest_format_struct, in_dests, destination_type, 6486de03d2dSErez Shitrit type); 6496de03d2dSErez Shitrit MLX5_SET(dest_format_struct, in_dests, destination_id, id); 6506de03d2dSErez Shitrit in_dests += dst_cnt_size; 6516de03d2dSErez Shitrit list_size++; 6526de03d2dSErez Shitrit } 6536de03d2dSErez Shitrit 6546de03d2dSErez Shitrit MLX5_SET(flow_context, in_flow_context, destination_list_size, 6556de03d2dSErez Shitrit list_size); 6566de03d2dSErez Shitrit } 6576de03d2dSErez Shitrit 6586de03d2dSErez Shitrit if (fte->action.action & MLX5_FLOW_CONTEXT_ACTION_COUNT) { 6596de03d2dSErez Shitrit int max_list_size = BIT(MLX5_CAP_FLOWTABLE_TYPE(dev, 6606de03d2dSErez Shitrit log_max_flow_counter, 6616de03d2dSErez Shitrit ft->type)); 6626de03d2dSErez Shitrit int list_size = 0; 6636de03d2dSErez Shitrit 6646de03d2dSErez Shitrit for (i = 0; i < fte->dests_size; i++) { 6656de03d2dSErez Shitrit if (fte->dest_arr[i].type != 6666de03d2dSErez Shitrit MLX5_FLOW_DESTINATION_TYPE_COUNTER) 6676de03d2dSErez Shitrit continue; 6686de03d2dSErez Shitrit 6696de03d2dSErez Shitrit MLX5_SET(flow_counter_list, in_dests, flow_counter_id, 6706de03d2dSErez Shitrit fte->dest_arr[i].counter_id); 6716de03d2dSErez Shitrit in_dests += dst_cnt_size; 6726de03d2dSErez Shitrit list_size++; 6736de03d2dSErez Shitrit } 6746de03d2dSErez Shitrit if (list_size > max_list_size) { 6756de03d2dSErez Shitrit err = -EINVAL; 6766de03d2dSErez Shitrit goto err_out; 6776de03d2dSErez Shitrit } 6786de03d2dSErez Shitrit 6796de03d2dSErez Shitrit MLX5_SET(flow_context, in_flow_context, flow_counter_list_size, 6806de03d2dSErez Shitrit list_size); 6816de03d2dSErez Shitrit } 6826de03d2dSErez Shitrit 6836de03d2dSErez Shitrit err = mlx5_cmd_exec(dev, in, inlen, out, sizeof(out)); 6846de03d2dSErez Shitrit err_out: 6856de03d2dSErez Shitrit kvfree(in); 6866de03d2dSErez Shitrit return err; 6876de03d2dSErez Shitrit } 688