1 /* SPDX-License-Identifier: BSD-3-Clause 2 * Copyright (c) 2022 NVIDIA Corporation & Affiliates 3 */ 4 5 #include "mlx5dr_internal.h" 6 7 static uint32_t mlx5dr_cmd_get_syndrome(uint32_t *out) 8 { 9 /* Assumption: syndrome is always the second u32 */ 10 return be32toh(out[1]); 11 } 12 13 int mlx5dr_cmd_destroy_obj(struct mlx5dr_devx_obj *devx_obj) 14 { 15 int ret; 16 17 ret = mlx5_glue->devx_obj_destroy(devx_obj->obj); 18 simple_free(devx_obj); 19 20 return ret; 21 } 22 23 struct mlx5dr_devx_obj * 24 mlx5dr_cmd_flow_table_create(struct ibv_context *ctx, 25 struct mlx5dr_cmd_ft_create_attr *ft_attr) 26 { 27 uint32_t out[MLX5_ST_SZ_DW(create_flow_table_out)] = {0}; 28 uint32_t in[MLX5_ST_SZ_DW(create_flow_table_in)] = {0}; 29 struct mlx5dr_devx_obj *devx_obj; 30 void *ft_ctx; 31 32 devx_obj = simple_malloc(sizeof(*devx_obj)); 33 if (!devx_obj) { 34 DR_LOG(ERR, "Failed to allocate memory for flow table object"); 35 rte_errno = ENOMEM; 36 return NULL; 37 } 38 39 MLX5_SET(create_flow_table_in, in, opcode, MLX5_CMD_OP_CREATE_FLOW_TABLE); 40 MLX5_SET(create_flow_table_in, in, table_type, ft_attr->type); 41 42 ft_ctx = MLX5_ADDR_OF(create_flow_table_in, in, flow_table_context); 43 MLX5_SET(flow_table_context, ft_ctx, level, ft_attr->level); 44 MLX5_SET(flow_table_context, ft_ctx, rtc_valid, ft_attr->rtc_valid); 45 MLX5_SET(flow_table_context, ft_ctx, reformat_en, ft_attr->reformat_en); 46 47 devx_obj->obj = mlx5_glue->devx_obj_create(ctx, in, sizeof(in), out, sizeof(out)); 48 if (!devx_obj->obj) { 49 DR_LOG(ERR, "Failed to create FT (syndrome: %#x)", 50 mlx5dr_cmd_get_syndrome(out)); 51 simple_free(devx_obj); 52 rte_errno = errno; 53 return NULL; 54 } 55 56 devx_obj->id = MLX5_GET(create_flow_table_out, out, table_id); 57 58 return devx_obj; 59 } 60 61 int 62 mlx5dr_cmd_flow_table_modify(struct mlx5dr_devx_obj *devx_obj, 63 struct mlx5dr_cmd_ft_modify_attr *ft_attr) 64 { 65 uint32_t out[MLX5_ST_SZ_DW(modify_flow_table_out)] = {0}; 66 uint32_t in[MLX5_ST_SZ_DW(modify_flow_table_in)] = {0}; 67 void *ft_ctx; 68 int ret; 69 70 MLX5_SET(modify_flow_table_in, in, opcode, MLX5_CMD_OP_MODIFY_FLOW_TABLE); 71 MLX5_SET(modify_flow_table_in, in, table_type, ft_attr->type); 72 MLX5_SET(modify_flow_table_in, in, modify_field_select, ft_attr->modify_fs); 73 MLX5_SET(modify_flow_table_in, in, table_id, devx_obj->id); 74 75 ft_ctx = MLX5_ADDR_OF(modify_flow_table_in, in, flow_table_context); 76 77 MLX5_SET(flow_table_context, ft_ctx, table_miss_action, ft_attr->table_miss_action); 78 MLX5_SET(flow_table_context, ft_ctx, table_miss_id, ft_attr->table_miss_id); 79 MLX5_SET(flow_table_context, ft_ctx, rtc_id_0, ft_attr->rtc_id_0); 80 MLX5_SET(flow_table_context, ft_ctx, rtc_id_1, ft_attr->rtc_id_1); 81 82 ret = mlx5_glue->devx_obj_modify(devx_obj->obj, in, sizeof(in), out, sizeof(out)); 83 if (ret) { 84 DR_LOG(ERR, "Failed to modify FT (syndrome: %#x)", 85 mlx5dr_cmd_get_syndrome(out)); 86 rte_errno = errno; 87 } 88 89 return ret; 90 } 91 92 int 93 mlx5dr_cmd_flow_table_query(struct mlx5dr_devx_obj *devx_obj, 94 struct mlx5dr_cmd_ft_query_attr *ft_attr, 95 uint64_t *icm_addr_0, uint64_t *icm_addr_1) 96 { 97 uint32_t out[MLX5_ST_SZ_DW(query_flow_table_out)] = {0}; 98 uint32_t in[MLX5_ST_SZ_DW(query_flow_table_in)] = {0}; 99 void *ft_ctx; 100 int ret; 101 102 MLX5_SET(query_flow_table_in, in, opcode, MLX5_CMD_OP_QUERY_FLOW_TABLE); 103 MLX5_SET(query_flow_table_in, in, table_type, ft_attr->type); 104 MLX5_SET(query_flow_table_in, in, table_id, devx_obj->id); 105 106 ret = mlx5_glue->devx_obj_query(devx_obj->obj, in, sizeof(in), out, sizeof(out)); 107 if (ret) { 108 DR_LOG(ERR, "Failed to query FT (syndrome: %#x)", 109 mlx5dr_cmd_get_syndrome(out)); 110 rte_errno = errno; 111 return ret; 112 } 113 114 ft_ctx = MLX5_ADDR_OF(query_flow_table_out, out, flow_table_context); 115 *icm_addr_0 = MLX5_GET64(flow_table_context, ft_ctx, sw_owner_icm_root_0); 116 *icm_addr_1 = MLX5_GET64(flow_table_context, ft_ctx, sw_owner_icm_root_1); 117 118 return ret; 119 } 120 121 static struct mlx5dr_devx_obj * 122 mlx5dr_cmd_flow_group_create(struct ibv_context *ctx, 123 struct mlx5dr_cmd_fg_attr *fg_attr) 124 { 125 uint32_t out[MLX5_ST_SZ_DW(create_flow_group_out)] = {0}; 126 uint32_t in[MLX5_ST_SZ_DW(create_flow_group_in)] = {0}; 127 struct mlx5dr_devx_obj *devx_obj; 128 129 devx_obj = simple_malloc(sizeof(*devx_obj)); 130 if (!devx_obj) { 131 DR_LOG(ERR, "Failed to allocate memory for flow group object"); 132 rte_errno = ENOMEM; 133 return NULL; 134 } 135 136 MLX5_SET(create_flow_group_in, in, opcode, MLX5_CMD_OP_CREATE_FLOW_GROUP); 137 MLX5_SET(create_flow_group_in, in, table_type, fg_attr->table_type); 138 MLX5_SET(create_flow_group_in, in, table_id, fg_attr->table_id); 139 140 devx_obj->obj = mlx5_glue->devx_obj_create(ctx, in, sizeof(in), out, sizeof(out)); 141 if (!devx_obj->obj) { 142 DR_LOG(ERR, "Failed to create Flow group(syndrome: %#x)", 143 mlx5dr_cmd_get_syndrome(out)); 144 simple_free(devx_obj); 145 rte_errno = errno; 146 return NULL; 147 } 148 149 devx_obj->id = MLX5_GET(create_flow_group_out, out, group_id); 150 151 return devx_obj; 152 } 153 154 struct mlx5dr_devx_obj * 155 mlx5dr_cmd_set_fte(struct ibv_context *ctx, 156 uint32_t table_type, 157 uint32_t table_id, 158 uint32_t group_id, 159 struct mlx5dr_cmd_set_fte_attr *fte_attr) 160 { 161 uint32_t out[MLX5_ST_SZ_DW(set_fte_out)] = {0}; 162 struct mlx5dr_devx_obj *devx_obj; 163 uint32_t dest_entry_sz; 164 uint32_t total_dest_sz; 165 void *in_flow_context; 166 uint32_t action_flags; 167 uint8_t *in_dests; 168 uint32_t inlen; 169 uint32_t *in; 170 uint32_t i; 171 172 dest_entry_sz = fte_attr->extended_dest ? 173 MLX5_ST_SZ_BYTES(extended_dest_format) : 174 MLX5_ST_SZ_BYTES(dest_format); 175 total_dest_sz = dest_entry_sz * fte_attr->dests_num; 176 inlen = align((MLX5_ST_SZ_BYTES(set_fte_in) + total_dest_sz), DW_SIZE); 177 in = simple_calloc(1, inlen); 178 if (!in) { 179 rte_errno = ENOMEM; 180 return NULL; 181 } 182 183 devx_obj = simple_malloc(sizeof(*devx_obj)); 184 if (!devx_obj) { 185 DR_LOG(ERR, "Failed to allocate memory for fte object"); 186 rte_errno = ENOMEM; 187 goto free_in; 188 } 189 190 MLX5_SET(set_fte_in, in, opcode, MLX5_CMD_OP_SET_FLOW_TABLE_ENTRY); 191 MLX5_SET(set_fte_in, in, table_type, table_type); 192 MLX5_SET(set_fte_in, in, table_id, table_id); 193 194 in_flow_context = MLX5_ADDR_OF(set_fte_in, in, flow_context); 195 MLX5_SET(flow_context, in_flow_context, group_id, group_id); 196 MLX5_SET(flow_context, in_flow_context, flow_source, fte_attr->flow_source); 197 MLX5_SET(flow_context, in_flow_context, extended_destination, fte_attr->extended_dest); 198 MLX5_SET(set_fte_in, in, ignore_flow_level, fte_attr->ignore_flow_level); 199 200 action_flags = fte_attr->action_flags; 201 MLX5_SET(flow_context, in_flow_context, action, action_flags); 202 203 if (action_flags & MLX5_FLOW_CONTEXT_ACTION_REFORMAT) 204 MLX5_SET(flow_context, in_flow_context, 205 packet_reformat_id, fte_attr->packet_reformat_id); 206 207 if (action_flags & (MLX5_FLOW_CONTEXT_ACTION_DECRYPT | MLX5_FLOW_CONTEXT_ACTION_ENCRYPT)) { 208 MLX5_SET(flow_context, in_flow_context, 209 encrypt_decrypt_type, fte_attr->encrypt_decrypt_type); 210 MLX5_SET(flow_context, in_flow_context, 211 encrypt_decrypt_obj_id, fte_attr->encrypt_decrypt_obj_id); 212 } 213 214 if (action_flags & MLX5_FLOW_CONTEXT_ACTION_FWD_DEST) { 215 in_dests = (uint8_t *)MLX5_ADDR_OF(flow_context, in_flow_context, destination); 216 217 for (i = 0; i < fte_attr->dests_num; i++) { 218 struct mlx5dr_cmd_set_fte_dest *dest = &fte_attr->dests[i]; 219 220 switch (dest->destination_type) { 221 case MLX5_FLOW_DESTINATION_TYPE_VPORT: 222 if (dest->ext_flags & MLX5DR_CMD_EXT_DEST_ESW_OWNER_VHCA_ID) { 223 MLX5_SET(dest_format, in_dests, 224 destination_eswitch_owner_vhca_id_valid, 1); 225 MLX5_SET(dest_format, in_dests, 226 destination_eswitch_owner_vhca_id, 227 dest->esw_owner_vhca_id); 228 } 229 /* Fall through */ 230 case MLX5_FLOW_DESTINATION_TYPE_TIR: 231 case MLX5_FLOW_DESTINATION_TYPE_FLOW_TABLE: 232 MLX5_SET(dest_format, in_dests, destination_type, 233 dest->destination_type); 234 MLX5_SET(dest_format, in_dests, destination_id, 235 dest->destination_id); 236 if (dest->ext_flags & MLX5DR_CMD_EXT_DEST_REFORMAT) { 237 MLX5_SET(dest_format, in_dests, packet_reformat, 1); 238 MLX5_SET(extended_dest_format, in_dests, packet_reformat_id, 239 dest->ext_reformat->id); 240 } 241 break; 242 default: 243 rte_errno = EOPNOTSUPP; 244 goto free_devx; 245 } 246 247 in_dests = in_dests + dest_entry_sz; 248 } 249 MLX5_SET(flow_context, in_flow_context, destination_list_size, fte_attr->dests_num); 250 } 251 252 devx_obj->obj = mlx5_glue->devx_obj_create(ctx, in, inlen, out, sizeof(out)); 253 if (!devx_obj->obj) { 254 DR_LOG(ERR, "Failed to create FTE (syndrome: %#x)", 255 mlx5dr_cmd_get_syndrome(out)); 256 rte_errno = errno; 257 goto free_devx; 258 } 259 260 simple_free(in); 261 return devx_obj; 262 263 free_devx: 264 simple_free(devx_obj); 265 free_in: 266 simple_free(in); 267 return NULL; 268 } 269 270 struct mlx5dr_cmd_forward_tbl * 271 mlx5dr_cmd_forward_tbl_create(struct ibv_context *ctx, 272 struct mlx5dr_cmd_ft_create_attr *ft_attr, 273 struct mlx5dr_cmd_set_fte_attr *fte_attr) 274 { 275 struct mlx5dr_cmd_fg_attr fg_attr = {0}; 276 struct mlx5dr_cmd_forward_tbl *tbl; 277 278 tbl = simple_calloc(1, sizeof(*tbl)); 279 if (!tbl) { 280 DR_LOG(ERR, "Failed to allocate memory"); 281 rte_errno = ENOMEM; 282 return NULL; 283 } 284 285 tbl->ft = mlx5dr_cmd_flow_table_create(ctx, ft_attr); 286 if (!tbl->ft) { 287 DR_LOG(ERR, "Failed to create FT"); 288 goto free_tbl; 289 } 290 291 fg_attr.table_id = tbl->ft->id; 292 fg_attr.table_type = ft_attr->type; 293 294 tbl->fg = mlx5dr_cmd_flow_group_create(ctx, &fg_attr); 295 if (!tbl->fg) { 296 DR_LOG(ERR, "Failed to create FG"); 297 goto free_ft; 298 } 299 300 tbl->fte = mlx5dr_cmd_set_fte(ctx, ft_attr->type, tbl->ft->id, tbl->fg->id, fte_attr); 301 if (!tbl->fte) { 302 DR_LOG(ERR, "Failed to create FTE"); 303 goto free_fg; 304 } 305 return tbl; 306 307 free_fg: 308 mlx5dr_cmd_destroy_obj(tbl->fg); 309 free_ft: 310 mlx5dr_cmd_destroy_obj(tbl->ft); 311 free_tbl: 312 simple_free(tbl); 313 return NULL; 314 } 315 316 void mlx5dr_cmd_forward_tbl_destroy(struct mlx5dr_cmd_forward_tbl *tbl) 317 { 318 mlx5dr_cmd_destroy_obj(tbl->fte); 319 mlx5dr_cmd_destroy_obj(tbl->fg); 320 mlx5dr_cmd_destroy_obj(tbl->ft); 321 simple_free(tbl); 322 } 323 324 void mlx5dr_cmd_set_attr_connect_miss_tbl(struct mlx5dr_context *ctx, 325 uint32_t fw_ft_type, 326 enum mlx5dr_table_type type, 327 struct mlx5dr_cmd_ft_modify_attr *ft_attr) 328 { 329 struct mlx5dr_devx_obj *default_miss_tbl; 330 331 if (type != MLX5DR_TABLE_TYPE_FDB && !mlx5dr_context_shared_gvmi_used(ctx)) 332 return; 333 334 ft_attr->modify_fs = MLX5_IFC_MODIFY_FLOW_TABLE_MISS_ACTION; 335 ft_attr->type = fw_ft_type; 336 ft_attr->table_miss_action = MLX5_IFC_MODIFY_FLOW_TABLE_MISS_ACTION_GOTO_TBL; 337 338 if (type == MLX5DR_TABLE_TYPE_FDB) { 339 default_miss_tbl = ctx->common_res[type].default_miss->ft; 340 if (!default_miss_tbl) { 341 assert(false); 342 return; 343 } 344 ft_attr->table_miss_id = default_miss_tbl->id; 345 } else { 346 ft_attr->table_miss_id = ctx->gvmi_res[type].aliased_end_ft->id; 347 } 348 } 349 350 struct mlx5dr_devx_obj * 351 mlx5dr_cmd_rtc_create(struct ibv_context *ctx, 352 struct mlx5dr_cmd_rtc_create_attr *rtc_attr) 353 { 354 uint32_t out[MLX5_ST_SZ_DW(general_obj_out_cmd_hdr)] = {0}; 355 uint32_t in[MLX5_ST_SZ_DW(create_rtc_in)] = {0}; 356 struct mlx5dr_devx_obj *devx_obj; 357 void *attr; 358 359 devx_obj = simple_malloc(sizeof(*devx_obj)); 360 if (!devx_obj) { 361 DR_LOG(ERR, "Failed to allocate memory for RTC object"); 362 rte_errno = ENOMEM; 363 return NULL; 364 } 365 366 attr = MLX5_ADDR_OF(create_rtc_in, in, hdr); 367 MLX5_SET(general_obj_in_cmd_hdr, 368 attr, opcode, MLX5_CMD_OP_CREATE_GENERAL_OBJECT); 369 MLX5_SET(general_obj_in_cmd_hdr, 370 attr, obj_type, MLX5_GENERAL_OBJ_TYPE_RTC); 371 372 attr = MLX5_ADDR_OF(create_rtc_in, in, rtc); 373 MLX5_SET(rtc, attr, ste_format_0, rtc_attr->is_frst_jumbo ? 374 MLX5_IFC_RTC_STE_FORMAT_11DW : 375 MLX5_IFC_RTC_STE_FORMAT_8DW); 376 377 if (rtc_attr->is_scnd_range) { 378 MLX5_SET(rtc, attr, ste_format_1, MLX5_IFC_RTC_STE_FORMAT_RANGE); 379 MLX5_SET(rtc, attr, num_match_ste, 2); 380 } 381 382 MLX5_SET(rtc, attr, pd, rtc_attr->pd); 383 MLX5_SET(rtc, attr, update_method, rtc_attr->fw_gen_wqe); 384 MLX5_SET(rtc, attr, update_index_mode, rtc_attr->update_index_mode); 385 MLX5_SET(rtc, attr, access_index_mode, rtc_attr->access_index_mode); 386 MLX5_SET(rtc, attr, num_hash_definer, rtc_attr->num_hash_definer); 387 MLX5_SET(rtc, attr, log_depth, rtc_attr->log_depth); 388 MLX5_SET(rtc, attr, log_hash_size, rtc_attr->log_size); 389 MLX5_SET(rtc, attr, table_type, rtc_attr->table_type); 390 MLX5_SET(rtc, attr, num_hash_definer, rtc_attr->num_hash_definer); 391 MLX5_SET(rtc, attr, match_definer_0, rtc_attr->match_definer_0); 392 MLX5_SET(rtc, attr, match_definer_1, rtc_attr->match_definer_1); 393 MLX5_SET(rtc, attr, stc_id, rtc_attr->stc_base); 394 MLX5_SET(rtc, attr, ste_table_base_id, rtc_attr->ste_base); 395 MLX5_SET(rtc, attr, ste_table_offset, rtc_attr->ste_offset); 396 MLX5_SET(rtc, attr, miss_flow_table_id, rtc_attr->miss_ft_id); 397 MLX5_SET(rtc, attr, reparse_mode, rtc_attr->reparse_mode); 398 399 devx_obj->obj = mlx5_glue->devx_obj_create(ctx, in, sizeof(in), out, sizeof(out)); 400 if (!devx_obj->obj) { 401 DR_LOG(ERR, "Failed to create RTC (syndrome: %#x)", 402 mlx5dr_cmd_get_syndrome(out)); 403 simple_free(devx_obj); 404 rte_errno = errno; 405 return NULL; 406 } 407 408 devx_obj->id = MLX5_GET(general_obj_out_cmd_hdr, out, obj_id); 409 410 return devx_obj; 411 } 412 413 struct mlx5dr_devx_obj * 414 mlx5dr_cmd_stc_create(struct ibv_context *ctx, 415 struct mlx5dr_cmd_stc_create_attr *stc_attr) 416 { 417 uint32_t out[MLX5_ST_SZ_DW(general_obj_out_cmd_hdr)] = {0}; 418 uint32_t in[MLX5_ST_SZ_DW(create_stc_in)] = {0}; 419 struct mlx5dr_devx_obj *devx_obj; 420 void *attr; 421 422 devx_obj = simple_malloc(sizeof(*devx_obj)); 423 if (!devx_obj) { 424 DR_LOG(ERR, "Failed to allocate memory for STC object"); 425 rte_errno = ENOMEM; 426 return NULL; 427 } 428 429 attr = MLX5_ADDR_OF(create_stc_in, in, hdr); 430 MLX5_SET(general_obj_in_cmd_hdr, 431 attr, opcode, MLX5_CMD_OP_CREATE_GENERAL_OBJECT); 432 MLX5_SET(general_obj_in_cmd_hdr, 433 attr, obj_type, MLX5_GENERAL_OBJ_TYPE_STC); 434 MLX5_SET(general_obj_in_cmd_hdr, 435 attr, log_obj_range, stc_attr->log_obj_range); 436 437 attr = MLX5_ADDR_OF(create_stc_in, in, stc); 438 MLX5_SET(stc, attr, table_type, stc_attr->table_type); 439 440 devx_obj->obj = mlx5_glue->devx_obj_create(ctx, in, sizeof(in), out, sizeof(out)); 441 if (!devx_obj->obj) { 442 DR_LOG(ERR, "Failed to create STC (syndrome: %#x)", 443 mlx5dr_cmd_get_syndrome(out)); 444 simple_free(devx_obj); 445 rte_errno = errno; 446 return NULL; 447 } 448 449 devx_obj->id = MLX5_GET(general_obj_out_cmd_hdr, out, obj_id); 450 451 return devx_obj; 452 } 453 454 static int 455 mlx5dr_cmd_stc_modify_set_stc_param(struct mlx5dr_cmd_stc_modify_attr *stc_attr, 456 void *stc_parm) 457 { 458 switch (stc_attr->action_type) { 459 case MLX5_IFC_STC_ACTION_TYPE_COUNTER: 460 MLX5_SET(stc_ste_param_flow_counter, stc_parm, flow_counter_id, stc_attr->id); 461 break; 462 case MLX5_IFC_STC_ACTION_TYPE_JUMP_TO_TIR: 463 MLX5_SET(stc_ste_param_tir, stc_parm, tirn, stc_attr->dest_tir_num); 464 break; 465 case MLX5_IFC_STC_ACTION_TYPE_JUMP_TO_FT: 466 MLX5_SET(stc_ste_param_table, stc_parm, table_id, stc_attr->dest_table_id); 467 break; 468 case MLX5_IFC_STC_ACTION_TYPE_ACC_MODIFY_LIST: 469 MLX5_SET(stc_ste_param_header_modify_list, stc_parm, 470 header_modify_pattern_id, stc_attr->modify_header.pattern_id); 471 MLX5_SET(stc_ste_param_header_modify_list, stc_parm, 472 header_modify_argument_id, stc_attr->modify_header.arg_id); 473 break; 474 case MLX5_IFC_STC_ACTION_TYPE_HEADER_REMOVE: 475 MLX5_SET(stc_ste_param_remove, stc_parm, action_type, 476 MLX5_MODIFICATION_TYPE_REMOVE); 477 MLX5_SET(stc_ste_param_remove, stc_parm, decap, 478 stc_attr->remove_header.decap); 479 MLX5_SET(stc_ste_param_remove, stc_parm, remove_start_anchor, 480 stc_attr->remove_header.start_anchor); 481 MLX5_SET(stc_ste_param_remove, stc_parm, remove_end_anchor, 482 stc_attr->remove_header.end_anchor); 483 break; 484 case MLX5_IFC_STC_ACTION_TYPE_HEADER_INSERT: 485 MLX5_SET(stc_ste_param_insert, stc_parm, action_type, 486 MLX5_MODIFICATION_TYPE_INSERT); 487 MLX5_SET(stc_ste_param_insert, stc_parm, encap, 488 stc_attr->insert_header.encap); 489 MLX5_SET(stc_ste_param_insert, stc_parm, inline_data, 490 stc_attr->insert_header.is_inline); 491 MLX5_SET(stc_ste_param_insert, stc_parm, insert_anchor, 492 stc_attr->insert_header.insert_anchor); 493 /* HW gets the next 2 sizes in words */ 494 MLX5_SET(stc_ste_param_insert, stc_parm, insert_size, 495 stc_attr->insert_header.header_size / W_SIZE); 496 MLX5_SET(stc_ste_param_insert, stc_parm, insert_offset, 497 stc_attr->insert_header.insert_offset / W_SIZE); 498 MLX5_SET(stc_ste_param_insert, stc_parm, insert_argument, 499 stc_attr->insert_header.arg_id); 500 break; 501 case MLX5_IFC_STC_ACTION_TYPE_COPY: 502 case MLX5_IFC_STC_ACTION_TYPE_SET: 503 case MLX5_IFC_STC_ACTION_TYPE_ADD: 504 case MLX5_IFC_STC_ACTION_TYPE_ADD_FIELD: 505 *(__be64 *)stc_parm = stc_attr->modify_action.data; 506 break; 507 case MLX5_IFC_STC_ACTION_TYPE_JUMP_TO_VPORT: 508 case MLX5_IFC_STC_ACTION_TYPE_JUMP_TO_UPLINK: 509 MLX5_SET(stc_ste_param_vport, stc_parm, vport_number, 510 stc_attr->vport.vport_num); 511 MLX5_SET(stc_ste_param_vport, stc_parm, eswitch_owner_vhca_id, 512 stc_attr->vport.esw_owner_vhca_id); 513 MLX5_SET(stc_ste_param_vport, stc_parm, eswitch_owner_vhca_id_valid, 1); 514 break; 515 case MLX5_IFC_STC_ACTION_TYPE_DROP: 516 case MLX5_IFC_STC_ACTION_TYPE_NOP: 517 case MLX5_IFC_STC_ACTION_TYPE_TAG: 518 case MLX5_IFC_STC_ACTION_TYPE_ALLOW: 519 break; 520 case MLX5_IFC_STC_ACTION_TYPE_ASO: 521 MLX5_SET(stc_ste_param_execute_aso, stc_parm, aso_object_id, 522 stc_attr->aso.devx_obj_id); 523 MLX5_SET(stc_ste_param_execute_aso, stc_parm, return_reg_id, 524 stc_attr->aso.return_reg_id); 525 MLX5_SET(stc_ste_param_execute_aso, stc_parm, aso_type, 526 stc_attr->aso.aso_type); 527 break; 528 case MLX5_IFC_STC_ACTION_TYPE_JUMP_TO_STE_TABLE: 529 MLX5_SET(stc_ste_param_ste_table, stc_parm, ste_obj_id, 530 stc_attr->ste_table.ste_obj_id); 531 MLX5_SET(stc_ste_param_ste_table, stc_parm, match_definer_id, 532 stc_attr->ste_table.match_definer_id); 533 MLX5_SET(stc_ste_param_ste_table, stc_parm, log_hash_size, 534 stc_attr->ste_table.log_hash_size); 535 break; 536 case MLX5_IFC_STC_ACTION_TYPE_REMOVE_WORDS: 537 MLX5_SET(stc_ste_param_remove_words, stc_parm, action_type, 538 MLX5_MODIFICATION_TYPE_REMOVE_WORDS); 539 MLX5_SET(stc_ste_param_remove_words, stc_parm, remove_start_anchor, 540 stc_attr->remove_words.start_anchor); 541 MLX5_SET(stc_ste_param_remove_words, stc_parm, 542 remove_size, stc_attr->remove_words.num_of_words); 543 break; 544 default: 545 DR_LOG(ERR, "Not supported type %d", stc_attr->action_type); 546 rte_errno = EINVAL; 547 return rte_errno; 548 } 549 return 0; 550 } 551 552 int 553 mlx5dr_cmd_stc_modify(struct mlx5dr_devx_obj *devx_obj, 554 struct mlx5dr_cmd_stc_modify_attr *stc_attr) 555 { 556 uint32_t out[MLX5_ST_SZ_DW(general_obj_out_cmd_hdr)] = {0}; 557 uint32_t in[MLX5_ST_SZ_DW(create_stc_in)] = {0}; 558 void *stc_parm; 559 void *attr; 560 int ret; 561 562 attr = MLX5_ADDR_OF(create_stc_in, in, hdr); 563 MLX5_SET(general_obj_in_cmd_hdr, 564 attr, opcode, MLX5_CMD_OP_MODIFY_GENERAL_OBJECT); 565 MLX5_SET(general_obj_in_cmd_hdr, 566 attr, obj_type, MLX5_GENERAL_OBJ_TYPE_STC); 567 MLX5_SET(general_obj_in_cmd_hdr, in, obj_id, devx_obj->id); 568 MLX5_SET(general_obj_in_cmd_hdr, in, obj_offset, stc_attr->stc_offset); 569 570 attr = MLX5_ADDR_OF(create_stc_in, in, stc); 571 MLX5_SET(stc, attr, ste_action_offset, stc_attr->action_offset); 572 MLX5_SET(stc, attr, action_type, stc_attr->action_type); 573 MLX5_SET(stc, attr, reparse_mode, stc_attr->reparse_mode); 574 MLX5_SET64(stc, attr, modify_field_select, 575 MLX5_IFC_MODIFY_STC_FIELD_SELECT_NEW_STC); 576 577 /* Set destination TIRN, TAG, FT ID, STE ID */ 578 stc_parm = MLX5_ADDR_OF(stc, attr, stc_param); 579 ret = mlx5dr_cmd_stc_modify_set_stc_param(stc_attr, stc_parm); 580 if (ret) 581 return ret; 582 583 ret = mlx5_glue->devx_obj_modify(devx_obj->obj, in, sizeof(in), out, sizeof(out)); 584 if (ret) { 585 DR_LOG(ERR, "Failed to modify STC FW action_type %d (syndrome: %#x)", 586 stc_attr->action_type, mlx5dr_cmd_get_syndrome(out)); 587 rte_errno = errno; 588 } 589 590 return ret; 591 } 592 593 struct mlx5dr_devx_obj * 594 mlx5dr_cmd_arg_create(struct ibv_context *ctx, 595 uint16_t log_obj_range, 596 uint32_t pd) 597 { 598 uint32_t out[MLX5_ST_SZ_DW(general_obj_out_cmd_hdr)] = {0}; 599 uint32_t in[MLX5_ST_SZ_DW(create_arg_in)] = {0}; 600 struct mlx5dr_devx_obj *devx_obj; 601 void *attr; 602 603 devx_obj = simple_malloc(sizeof(*devx_obj)); 604 if (!devx_obj) { 605 DR_LOG(ERR, "Failed to allocate memory for ARG object"); 606 rte_errno = ENOMEM; 607 return NULL; 608 } 609 610 attr = MLX5_ADDR_OF(create_arg_in, in, hdr); 611 MLX5_SET(general_obj_in_cmd_hdr, 612 attr, opcode, MLX5_CMD_OP_CREATE_GENERAL_OBJECT); 613 MLX5_SET(general_obj_in_cmd_hdr, 614 attr, obj_type, MLX5_GENERAL_OBJ_TYPE_ARG); 615 MLX5_SET(general_obj_in_cmd_hdr, 616 attr, log_obj_range, log_obj_range); 617 618 attr = MLX5_ADDR_OF(create_arg_in, in, arg); 619 MLX5_SET(arg, attr, access_pd, pd); 620 621 devx_obj->obj = mlx5_glue->devx_obj_create(ctx, in, sizeof(in), out, sizeof(out)); 622 if (!devx_obj->obj) { 623 DR_LOG(ERR, "Failed to create ARG (syndrome: %#x)", 624 mlx5dr_cmd_get_syndrome(out)); 625 simple_free(devx_obj); 626 rte_errno = errno; 627 return NULL; 628 } 629 630 devx_obj->id = MLX5_GET(general_obj_out_cmd_hdr, out, obj_id); 631 632 return devx_obj; 633 } 634 635 struct mlx5dr_devx_obj * 636 mlx5dr_cmd_header_modify_pattern_create(struct ibv_context *ctx, 637 uint32_t pattern_length, 638 uint8_t *actions) 639 { 640 uint32_t in[MLX5_ST_SZ_DW(create_header_modify_pattern_in)] = {0}; 641 uint32_t out[MLX5_ST_SZ_DW(general_obj_out_cmd_hdr)] = {0}; 642 struct mlx5dr_devx_obj *devx_obj; 643 uint64_t *pattern_data; 644 int num_of_actions; 645 void *pattern; 646 void *attr; 647 int i; 648 649 if (pattern_length > MAX_ACTIONS_DATA_IN_HEADER_MODIFY) { 650 DR_LOG(ERR, "Pattern length %d exceeds limit %d", 651 pattern_length, MAX_ACTIONS_DATA_IN_HEADER_MODIFY); 652 rte_errno = EINVAL; 653 return NULL; 654 } 655 656 devx_obj = simple_malloc(sizeof(*devx_obj)); 657 if (!devx_obj) { 658 DR_LOG(ERR, "Failed to allocate memory for header_modify_pattern object"); 659 rte_errno = ENOMEM; 660 return NULL; 661 } 662 attr = MLX5_ADDR_OF(create_header_modify_pattern_in, in, hdr); 663 MLX5_SET(general_obj_in_cmd_hdr, 664 attr, opcode, MLX5_CMD_OP_CREATE_GENERAL_OBJECT); 665 MLX5_SET(general_obj_in_cmd_hdr, 666 attr, obj_type, MLX5_GENERAL_OBJ_TYPE_MODIFY_HEADER_PATTERN); 667 668 pattern = MLX5_ADDR_OF(create_header_modify_pattern_in, in, pattern); 669 /* Pattern_length is in ddwords */ 670 MLX5_SET(header_modify_pattern_in, pattern, pattern_length, pattern_length / (2 * DW_SIZE)); 671 672 pattern_data = (uint64_t *)MLX5_ADDR_OF(header_modify_pattern_in, pattern, pattern_data); 673 memcpy(pattern_data, actions, pattern_length); 674 675 num_of_actions = pattern_length / MLX5DR_MODIFY_ACTION_SIZE; 676 for (i = 0; i < num_of_actions; i++) { 677 int type; 678 679 type = MLX5_GET(set_action_in, &pattern_data[i], action_type); 680 if (type != MLX5_MODIFICATION_TYPE_COPY && 681 type != MLX5_MODIFICATION_TYPE_ADD_FIELD) 682 /* Action typ-copy use all bytes for control */ 683 MLX5_SET(set_action_in, &pattern_data[i], data, 0); 684 } 685 686 devx_obj->obj = mlx5_glue->devx_obj_create(ctx, in, sizeof(in), out, sizeof(out)); 687 if (!devx_obj->obj) { 688 DR_LOG(ERR, "Failed to create header_modify_pattern (syndrome: %#x)", 689 mlx5dr_cmd_get_syndrome(out)); 690 rte_errno = errno; 691 goto free_obj; 692 } 693 694 devx_obj->id = MLX5_GET(general_obj_out_cmd_hdr, out, obj_id); 695 696 return devx_obj; 697 698 free_obj: 699 simple_free(devx_obj); 700 return NULL; 701 } 702 703 struct mlx5dr_devx_obj * 704 mlx5dr_cmd_ste_create(struct ibv_context *ctx, 705 struct mlx5dr_cmd_ste_create_attr *ste_attr) 706 { 707 uint32_t out[MLX5_ST_SZ_DW(general_obj_out_cmd_hdr)] = {0}; 708 uint32_t in[MLX5_ST_SZ_DW(create_ste_in)] = {0}; 709 struct mlx5dr_devx_obj *devx_obj; 710 void *attr; 711 712 devx_obj = simple_malloc(sizeof(*devx_obj)); 713 if (!devx_obj) { 714 DR_LOG(ERR, "Failed to allocate memory for STE object"); 715 rte_errno = ENOMEM; 716 return NULL; 717 } 718 719 attr = MLX5_ADDR_OF(create_ste_in, in, hdr); 720 MLX5_SET(general_obj_in_cmd_hdr, 721 attr, opcode, MLX5_CMD_OP_CREATE_GENERAL_OBJECT); 722 MLX5_SET(general_obj_in_cmd_hdr, 723 attr, obj_type, MLX5_GENERAL_OBJ_TYPE_STE); 724 MLX5_SET(general_obj_in_cmd_hdr, 725 attr, log_obj_range, ste_attr->log_obj_range); 726 727 attr = MLX5_ADDR_OF(create_ste_in, in, ste); 728 MLX5_SET(ste, attr, table_type, ste_attr->table_type); 729 730 devx_obj->obj = mlx5_glue->devx_obj_create(ctx, in, sizeof(in), out, sizeof(out)); 731 if (!devx_obj->obj) { 732 DR_LOG(ERR, "Failed to create STE (syndrome: %#x)", 733 mlx5dr_cmd_get_syndrome(out)); 734 simple_free(devx_obj); 735 rte_errno = errno; 736 return NULL; 737 } 738 739 devx_obj->id = MLX5_GET(general_obj_out_cmd_hdr, out, obj_id); 740 741 return devx_obj; 742 } 743 744 struct mlx5dr_devx_obj * 745 mlx5dr_cmd_definer_create(struct ibv_context *ctx, 746 struct mlx5dr_cmd_definer_create_attr *def_attr) 747 { 748 uint32_t out[MLX5_ST_SZ_DW(general_obj_out_cmd_hdr)] = {0}; 749 uint32_t in[MLX5_ST_SZ_DW(create_definer_in)] = {0}; 750 struct mlx5dr_devx_obj *devx_obj; 751 void *ptr; 752 753 devx_obj = simple_malloc(sizeof(*devx_obj)); 754 if (!devx_obj) { 755 DR_LOG(ERR, "Failed to allocate memory for definer object"); 756 rte_errno = ENOMEM; 757 return NULL; 758 } 759 760 MLX5_SET(general_obj_in_cmd_hdr, 761 in, opcode, MLX5_CMD_OP_CREATE_GENERAL_OBJECT); 762 MLX5_SET(general_obj_in_cmd_hdr, 763 in, obj_type, MLX5_GENERAL_OBJ_TYPE_DEFINER); 764 765 ptr = MLX5_ADDR_OF(create_definer_in, in, definer); 766 MLX5_SET(definer, ptr, format_id, MLX5_IFC_DEFINER_FORMAT_ID_SELECT); 767 768 MLX5_SET(definer, ptr, format_select_dw0, def_attr->dw_selector[0]); 769 MLX5_SET(definer, ptr, format_select_dw1, def_attr->dw_selector[1]); 770 MLX5_SET(definer, ptr, format_select_dw2, def_attr->dw_selector[2]); 771 MLX5_SET(definer, ptr, format_select_dw3, def_attr->dw_selector[3]); 772 MLX5_SET(definer, ptr, format_select_dw4, def_attr->dw_selector[4]); 773 MLX5_SET(definer, ptr, format_select_dw5, def_attr->dw_selector[5]); 774 MLX5_SET(definer, ptr, format_select_dw6, def_attr->dw_selector[6]); 775 MLX5_SET(definer, ptr, format_select_dw7, def_attr->dw_selector[7]); 776 MLX5_SET(definer, ptr, format_select_dw8, def_attr->dw_selector[8]); 777 778 MLX5_SET(definer, ptr, format_select_byte0, def_attr->byte_selector[0]); 779 MLX5_SET(definer, ptr, format_select_byte1, def_attr->byte_selector[1]); 780 MLX5_SET(definer, ptr, format_select_byte2, def_attr->byte_selector[2]); 781 MLX5_SET(definer, ptr, format_select_byte3, def_attr->byte_selector[3]); 782 MLX5_SET(definer, ptr, format_select_byte4, def_attr->byte_selector[4]); 783 MLX5_SET(definer, ptr, format_select_byte5, def_attr->byte_selector[5]); 784 MLX5_SET(definer, ptr, format_select_byte6, def_attr->byte_selector[6]); 785 MLX5_SET(definer, ptr, format_select_byte7, def_attr->byte_selector[7]); 786 787 ptr = MLX5_ADDR_OF(definer, ptr, match_mask); 788 memcpy(ptr, def_attr->match_mask, MLX5_FLD_SZ_BYTES(definer, match_mask)); 789 790 devx_obj->obj = mlx5_glue->devx_obj_create(ctx, in, sizeof(in), out, sizeof(out)); 791 if (!devx_obj->obj) { 792 DR_LOG(ERR, "Failed to create Definer (syndrome: %#x)", 793 mlx5dr_cmd_get_syndrome(out)); 794 simple_free(devx_obj); 795 rte_errno = errno; 796 return NULL; 797 } 798 799 devx_obj->id = MLX5_GET(general_obj_out_cmd_hdr, out, obj_id); 800 801 return devx_obj; 802 } 803 804 struct mlx5dr_devx_obj * 805 mlx5dr_cmd_sq_create(struct ibv_context *ctx, 806 struct mlx5dr_cmd_sq_create_attr *attr) 807 { 808 uint32_t out[MLX5_ST_SZ_DW(create_sq_out)] = {0}; 809 uint32_t in[MLX5_ST_SZ_DW(create_sq_in)] = {0}; 810 void *sqc = MLX5_ADDR_OF(create_sq_in, in, ctx); 811 void *wqc = MLX5_ADDR_OF(sqc, sqc, wq); 812 struct mlx5dr_devx_obj *devx_obj; 813 814 devx_obj = simple_malloc(sizeof(*devx_obj)); 815 if (!devx_obj) { 816 DR_LOG(ERR, "Failed to create SQ"); 817 rte_errno = ENOMEM; 818 return NULL; 819 } 820 821 MLX5_SET(create_sq_in, in, opcode, MLX5_CMD_OP_CREATE_SQ); 822 MLX5_SET(sqc, sqc, cqn, attr->cqn); 823 MLX5_SET(sqc, sqc, flush_in_error_en, 1); 824 MLX5_SET(sqc, sqc, non_wire, 1); 825 MLX5_SET(sqc, sqc, ts_format, attr->ts_format); 826 MLX5_SET(wq, wqc, wq_type, MLX5_WQ_TYPE_CYCLIC); 827 MLX5_SET(wq, wqc, pd, attr->pdn); 828 MLX5_SET(wq, wqc, uar_page, attr->page_id); 829 MLX5_SET(wq, wqc, log_wq_stride, log2above(MLX5_SEND_WQE_BB)); 830 MLX5_SET(wq, wqc, log_wq_sz, attr->log_wq_sz); 831 MLX5_SET(wq, wqc, dbr_umem_id, attr->dbr_id); 832 MLX5_SET(wq, wqc, wq_umem_id, attr->wq_id); 833 834 devx_obj->obj = mlx5_glue->devx_obj_create(ctx, in, sizeof(in), out, sizeof(out)); 835 if (!devx_obj->obj) { 836 simple_free(devx_obj); 837 rte_errno = errno; 838 return NULL; 839 } 840 841 devx_obj->id = MLX5_GET(create_sq_out, out, sqn); 842 843 return devx_obj; 844 } 845 846 struct mlx5dr_devx_obj * 847 mlx5dr_cmd_packet_reformat_create(struct ibv_context *ctx, 848 struct mlx5dr_cmd_packet_reformat_create_attr *attr) 849 { 850 uint32_t out[MLX5_ST_SZ_DW(alloc_packet_reformat_out)] = {0}; 851 size_t insz, cmd_data_sz, cmd_total_sz; 852 struct mlx5dr_devx_obj *devx_obj; 853 void *prctx; 854 void *pdata; 855 void *in; 856 857 cmd_total_sz = MLX5_ST_SZ_BYTES(alloc_packet_reformat_context_in); 858 cmd_total_sz += MLX5_ST_SZ_BYTES(packet_reformat_context_in); 859 cmd_data_sz = MLX5_FLD_SZ_BYTES(packet_reformat_context_in, reformat_data); 860 insz = align(cmd_total_sz + attr->data_sz - cmd_data_sz, DW_SIZE); 861 in = simple_calloc(1, insz); 862 if (!in) { 863 rte_errno = ENOMEM; 864 return NULL; 865 } 866 867 MLX5_SET(alloc_packet_reformat_context_in, in, opcode, 868 MLX5_CMD_OP_ALLOC_PACKET_REFORMAT_CONTEXT); 869 870 prctx = MLX5_ADDR_OF(alloc_packet_reformat_context_in, in, 871 packet_reformat_context); 872 pdata = MLX5_ADDR_OF(packet_reformat_context_in, prctx, reformat_data); 873 874 MLX5_SET(packet_reformat_context_in, prctx, reformat_type, attr->type); 875 MLX5_SET(packet_reformat_context_in, prctx, reformat_param_0, attr->reformat_param_0); 876 MLX5_SET(packet_reformat_context_in, prctx, reformat_data_size, attr->data_sz); 877 memcpy(pdata, attr->data, attr->data_sz); 878 879 devx_obj = simple_malloc(sizeof(*devx_obj)); 880 if (!devx_obj) { 881 DR_LOG(ERR, "Failed to allocate memory for packet reformat object"); 882 rte_errno = ENOMEM; 883 goto out_free_in; 884 } 885 886 devx_obj->obj = mlx5_glue->devx_obj_create(ctx, in, insz, out, sizeof(out)); 887 if (!devx_obj->obj) { 888 DR_LOG(ERR, "Failed to create packet reformat"); 889 rte_errno = errno; 890 goto out_free_devx; 891 } 892 893 devx_obj->id = MLX5_GET(alloc_packet_reformat_out, out, packet_reformat_id); 894 895 simple_free(in); 896 897 return devx_obj; 898 899 out_free_devx: 900 simple_free(devx_obj); 901 out_free_in: 902 simple_free(in); 903 return NULL; 904 } 905 906 int mlx5dr_cmd_sq_modify_rdy(struct mlx5dr_devx_obj *devx_obj) 907 { 908 uint32_t out[MLX5_ST_SZ_DW(modify_sq_out)] = {0}; 909 uint32_t in[MLX5_ST_SZ_DW(modify_sq_in)] = {0}; 910 void *sqc = MLX5_ADDR_OF(modify_sq_in, in, ctx); 911 int ret; 912 913 MLX5_SET(modify_sq_in, in, opcode, MLX5_CMD_OP_MODIFY_SQ); 914 MLX5_SET(modify_sq_in, in, sqn, devx_obj->id); 915 MLX5_SET(modify_sq_in, in, sq_state, MLX5_SQC_STATE_RST); 916 MLX5_SET(sqc, sqc, state, MLX5_SQC_STATE_RDY); 917 918 ret = mlx5_glue->devx_obj_modify(devx_obj->obj, in, sizeof(in), out, sizeof(out)); 919 if (ret) { 920 DR_LOG(ERR, "Failed to modify SQ (syndrome: %#x)", 921 mlx5dr_cmd_get_syndrome(out)); 922 rte_errno = errno; 923 } 924 925 return ret; 926 } 927 928 int mlx5dr_cmd_allow_other_vhca_access(struct ibv_context *ctx, 929 struct mlx5dr_cmd_allow_other_vhca_access_attr *attr) 930 { 931 uint32_t out[MLX5_ST_SZ_DW(allow_other_vhca_access_out)] = {0}; 932 uint32_t in[MLX5_ST_SZ_DW(allow_other_vhca_access_in)] = {0}; 933 void *key; 934 int ret; 935 936 MLX5_SET(allow_other_vhca_access_in, 937 in, opcode, MLX5_CMD_OP_ALLOW_OTHER_VHCA_ACCESS); 938 MLX5_SET(allow_other_vhca_access_in, 939 in, object_type_to_be_accessed, attr->obj_type); 940 MLX5_SET(allow_other_vhca_access_in, 941 in, object_id_to_be_accessed, attr->obj_id); 942 943 key = MLX5_ADDR_OF(allow_other_vhca_access_in, in, access_key); 944 memcpy(key, attr->access_key, sizeof(attr->access_key)); 945 946 ret = mlx5_glue->devx_general_cmd(ctx, in, sizeof(in), out, sizeof(out)); 947 if (ret) { 948 DR_LOG(ERR, "Failed to execute ALLOW_OTHER_VHCA_ACCESS command"); 949 rte_errno = errno; 950 return rte_errno; 951 } 952 953 return 0; 954 } 955 956 struct mlx5dr_devx_obj * 957 mlx5dr_cmd_alias_obj_create(struct ibv_context *ctx, 958 struct mlx5dr_cmd_alias_obj_create_attr *alias_attr) 959 { 960 uint32_t out[MLX5_ST_SZ_DW(general_obj_out_cmd_hdr)] = {0}; 961 uint32_t in[MLX5_ST_SZ_DW(create_alias_obj_in)] = {0}; 962 struct mlx5dr_devx_obj *devx_obj; 963 void *attr; 964 void *key; 965 966 devx_obj = simple_malloc(sizeof(*devx_obj)); 967 if (!devx_obj) { 968 DR_LOG(ERR, "Failed to allocate memory for ALIAS general object"); 969 rte_errno = ENOMEM; 970 return NULL; 971 } 972 973 attr = MLX5_ADDR_OF(create_alias_obj_in, in, hdr); 974 MLX5_SET(general_obj_in_cmd_hdr, 975 attr, opcode, MLX5_CMD_OP_CREATE_GENERAL_OBJECT); 976 MLX5_SET(general_obj_in_cmd_hdr, 977 attr, obj_type, alias_attr->obj_type); 978 MLX5_SET(general_obj_in_cmd_hdr, attr, alias_object, 1); 979 980 attr = MLX5_ADDR_OF(create_alias_obj_in, in, alias_ctx); 981 MLX5_SET(alias_context, attr, vhca_id_to_be_accessed, alias_attr->vhca_id); 982 MLX5_SET(alias_context, attr, object_id_to_be_accessed, alias_attr->obj_id); 983 984 key = MLX5_ADDR_OF(alias_context, attr, access_key); 985 memcpy(key, alias_attr->access_key, sizeof(alias_attr->access_key)); 986 987 devx_obj->obj = mlx5_glue->devx_obj_create(ctx, in, sizeof(in), out, sizeof(out)); 988 if (!devx_obj->obj) { 989 DR_LOG(ERR, "Failed to create ALIAS OBJ (syndrome: %#x)", 990 mlx5dr_cmd_get_syndrome(out)); 991 simple_free(devx_obj); 992 rte_errno = errno; 993 return NULL; 994 } 995 996 devx_obj->id = MLX5_GET(general_obj_out_cmd_hdr, out, obj_id); 997 998 return devx_obj; 999 } 1000 1001 int mlx5dr_cmd_generate_wqe(struct ibv_context *ctx, 1002 struct mlx5dr_cmd_generate_wqe_attr *attr, 1003 struct mlx5_cqe64 *ret_cqe) 1004 { 1005 uint32_t out[MLX5_ST_SZ_DW(generate_wqe_out)] = {0}; 1006 uint32_t in[MLX5_ST_SZ_DW(generate_wqe_in)] = {0}; 1007 uint8_t status; 1008 void *ptr; 1009 int ret; 1010 1011 MLX5_SET(generate_wqe_in, in, opcode, MLX5_CMD_OP_GENERATE_WQE); 1012 MLX5_SET(generate_wqe_in, in, pdn, attr->pdn); 1013 1014 ptr = MLX5_ADDR_OF(generate_wqe_in, in, wqe_ctrl); 1015 memcpy(ptr, attr->wqe_ctrl, MLX5_FLD_SZ_BYTES(generate_wqe_in, wqe_ctrl)); 1016 1017 ptr = MLX5_ADDR_OF(generate_wqe_in, in, wqe_gta_ctrl); 1018 memcpy(ptr, attr->gta_ctrl, MLX5_FLD_SZ_BYTES(generate_wqe_in, wqe_gta_ctrl)); 1019 1020 ptr = MLX5_ADDR_OF(generate_wqe_in, in, wqe_gta_data_0); 1021 memcpy(ptr, attr->gta_data_0, MLX5_FLD_SZ_BYTES(generate_wqe_in, wqe_gta_data_0)); 1022 1023 if (attr->gta_data_1) { 1024 ptr = MLX5_ADDR_OF(generate_wqe_in, in, wqe_gta_data_1); 1025 memcpy(ptr, attr->gta_data_1, MLX5_FLD_SZ_BYTES(generate_wqe_in, wqe_gta_data_1)); 1026 } 1027 1028 ret = mlx5_glue->devx_general_cmd(ctx, in, sizeof(in), out, sizeof(out)); 1029 if (ret) { 1030 DR_LOG(ERR, "Failed to write GTA WQE using FW"); 1031 rte_errno = errno; 1032 return rte_errno; 1033 } 1034 1035 status = MLX5_GET(generate_wqe_out, out, status); 1036 if (status) { 1037 DR_LOG(ERR, "Invalid FW CQE status %d", status); 1038 rte_errno = EINVAL; 1039 return rte_errno; 1040 } 1041 1042 ptr = MLX5_ADDR_OF(generate_wqe_out, out, cqe_data); 1043 memcpy(ret_cqe, ptr, sizeof(*ret_cqe)); 1044 1045 return 0; 1046 } 1047 1048 int mlx5dr_cmd_query_caps(struct ibv_context *ctx, 1049 struct mlx5dr_cmd_query_caps *caps) 1050 { 1051 uint32_t out[MLX5_ST_SZ_DW(query_hca_cap_out)] = {0}; 1052 uint32_t in[MLX5_ST_SZ_DW(query_hca_cap_in)] = {0}; 1053 const struct flow_hw_port_info *port_info; 1054 struct ibv_device_attr_ex attr_ex; 1055 u32 res; 1056 int ret; 1057 1058 MLX5_SET(query_hca_cap_in, in, opcode, MLX5_CMD_OP_QUERY_HCA_CAP); 1059 MLX5_SET(query_hca_cap_in, in, op_mod, 1060 MLX5_GET_HCA_CAP_OP_MOD_GENERAL_DEVICE | 1061 MLX5_HCA_CAP_OPMOD_GET_CUR); 1062 1063 ret = mlx5_glue->devx_general_cmd(ctx, in, sizeof(in), out, sizeof(out)); 1064 if (ret) { 1065 DR_LOG(ERR, "Failed to query device caps"); 1066 rte_errno = errno; 1067 return rte_errno; 1068 } 1069 1070 caps->wqe_based_update = 1071 MLX5_GET(query_hca_cap_out, out, 1072 capability.cmd_hca_cap.wqe_based_flow_table_update_cap); 1073 1074 caps->eswitch_manager = MLX5_GET(query_hca_cap_out, out, 1075 capability.cmd_hca_cap.eswitch_manager); 1076 1077 caps->flex_protocols = MLX5_GET(query_hca_cap_out, out, 1078 capability.cmd_hca_cap.flex_parser_protocols); 1079 1080 caps->log_header_modify_argument_granularity = 1081 MLX5_GET(query_hca_cap_out, out, 1082 capability.cmd_hca_cap.log_header_modify_argument_granularity); 1083 1084 caps->log_header_modify_argument_granularity -= 1085 MLX5_GET(query_hca_cap_out, out, 1086 capability.cmd_hca_cap. 1087 log_header_modify_argument_granularity_offset); 1088 1089 caps->log_header_modify_argument_max_alloc = 1090 MLX5_GET(query_hca_cap_out, out, 1091 capability.cmd_hca_cap.log_header_modify_argument_max_alloc); 1092 1093 caps->definer_format_sup = 1094 MLX5_GET64(query_hca_cap_out, out, 1095 capability.cmd_hca_cap.match_definer_format_supported); 1096 1097 caps->vhca_id = MLX5_GET(query_hca_cap_out, out, 1098 capability.cmd_hca_cap.vhca_id); 1099 1100 caps->sq_ts_format = MLX5_GET(query_hca_cap_out, out, 1101 capability.cmd_hca_cap.sq_ts_format); 1102 1103 caps->ipsec_offload = MLX5_GET(query_hca_cap_out, out, 1104 capability.cmd_hca_cap.ipsec_offload); 1105 1106 caps->roce = MLX5_GET(query_hca_cap_out, out, capability.cmd_hca_cap.roce); 1107 1108 MLX5_SET(query_hca_cap_in, in, op_mod, 1109 MLX5_GET_HCA_CAP_OP_MOD_GENERAL_DEVICE_2 | 1110 MLX5_HCA_CAP_OPMOD_GET_CUR); 1111 1112 ret = mlx5_glue->devx_general_cmd(ctx, in, sizeof(in), out, sizeof(out)); 1113 if (ret) { 1114 DR_LOG(ERR, "Failed to query device caps"); 1115 rte_errno = errno; 1116 return rte_errno; 1117 } 1118 1119 caps->full_dw_jumbo_support = MLX5_GET(query_hca_cap_out, out, 1120 capability.cmd_hca_cap_2. 1121 format_select_dw_8_6_ext); 1122 1123 caps->format_select_gtpu_dw_0 = MLX5_GET(query_hca_cap_out, out, 1124 capability.cmd_hca_cap_2. 1125 format_select_dw_gtpu_dw_0); 1126 1127 caps->format_select_gtpu_dw_1 = MLX5_GET(query_hca_cap_out, out, 1128 capability.cmd_hca_cap_2. 1129 format_select_dw_gtpu_dw_1); 1130 1131 caps->format_select_gtpu_dw_2 = MLX5_GET(query_hca_cap_out, out, 1132 capability.cmd_hca_cap_2. 1133 format_select_dw_gtpu_dw_2); 1134 1135 caps->format_select_gtpu_ext_dw_0 = MLX5_GET(query_hca_cap_out, out, 1136 capability.cmd_hca_cap_2. 1137 format_select_dw_gtpu_first_ext_dw_0); 1138 1139 caps->supp_type_gen_wqe = MLX5_GET(query_hca_cap_out, out, 1140 capability.cmd_hca_cap_2. 1141 generate_wqe_type); 1142 1143 /* check cross-VHCA support in cap2 */ 1144 res = 1145 MLX5_GET(query_hca_cap_out, out, 1146 capability.cmd_hca_cap_2.cross_vhca_object_to_object_supported); 1147 1148 caps->cross_vhca_resources = (res & MLX5_CROSS_VHCA_OBJ_TO_OBJ_TYPE_STC_TO_TIR) && 1149 (res & MLX5_CROSS_VHCA_OBJ_TO_OBJ_TYPE_STC_TO_FT) && 1150 (res & MLX5_CROSS_VHCA_OBJ_TO_OBJ_TYPE_FT_TO_RTC); 1151 1152 res = 1153 MLX5_GET(query_hca_cap_out, out, 1154 capability.cmd_hca_cap_2.allowed_object_for_other_vhca_access); 1155 1156 caps->cross_vhca_resources &= (res & MLX5_CROSS_VHCA_ALLOWED_OBJS_TIR) && 1157 (res & MLX5_CROSS_VHCA_ALLOWED_OBJS_FT) && 1158 (res & MLX5_CROSS_VHCA_ALLOWED_OBJS_RTC); 1159 1160 caps->flow_table_hash_type = MLX5_GET(query_hca_cap_out, out, 1161 capability.cmd_hca_cap_2.flow_table_hash_type); 1162 1163 caps->encap_entropy_hash_type = MLX5_GET(query_hca_cap_out, out, 1164 capability.cmd_hca_cap_2.encap_entropy_hash_type); 1165 1166 MLX5_SET(query_hca_cap_in, in, op_mod, 1167 MLX5_GET_HCA_CAP_OP_MOD_NIC_FLOW_TABLE | 1168 MLX5_HCA_CAP_OPMOD_GET_CUR); 1169 1170 ret = mlx5_glue->devx_general_cmd(ctx, in, sizeof(in), out, sizeof(out)); 1171 if (ret) { 1172 DR_LOG(ERR, "Failed to query flow table caps"); 1173 rte_errno = errno; 1174 return rte_errno; 1175 } 1176 1177 caps->nic_ft.max_level = MLX5_GET(query_hca_cap_out, out, 1178 capability.flow_table_nic_cap. 1179 flow_table_properties_nic_receive.max_ft_level); 1180 1181 caps->nic_ft.reparse = MLX5_GET(query_hca_cap_out, out, 1182 capability.flow_table_nic_cap. 1183 flow_table_properties_nic_receive.reparse); 1184 1185 caps->nic_ft.ignore_flow_level_rtc_valid = 1186 MLX5_GET(query_hca_cap_out, 1187 out, 1188 capability.flow_table_nic_cap. 1189 flow_table_properties_nic_receive.ignore_flow_level_rtc_valid); 1190 1191 /* check cross-VHCA support in flow table properties */ 1192 res = 1193 MLX5_GET(query_hca_cap_out, out, 1194 capability.flow_table_nic_cap.flow_table_properties_nic_receive.cross_vhca_object); 1195 caps->cross_vhca_resources &= res; 1196 1197 if (caps->wqe_based_update) { 1198 MLX5_SET(query_hca_cap_in, in, op_mod, 1199 MLX5_GET_HCA_CAP_OP_MOD_WQE_BASED_FLOW_TABLE | 1200 MLX5_HCA_CAP_OPMOD_GET_CUR); 1201 1202 ret = mlx5_glue->devx_general_cmd(ctx, in, sizeof(in), out, sizeof(out)); 1203 if (ret) { 1204 DR_LOG(ERR, "Failed to query WQE based FT caps"); 1205 rte_errno = errno; 1206 return rte_errno; 1207 } 1208 1209 caps->rtc_reparse_mode = MLX5_GET(query_hca_cap_out, out, 1210 capability.wqe_based_flow_table_cap. 1211 rtc_reparse_mode); 1212 1213 caps->ste_format = MLX5_GET(query_hca_cap_out, out, 1214 capability.wqe_based_flow_table_cap. 1215 ste_format); 1216 1217 caps->rtc_index_mode = MLX5_GET(query_hca_cap_out, out, 1218 capability.wqe_based_flow_table_cap. 1219 rtc_index_mode); 1220 1221 caps->rtc_log_depth_max = MLX5_GET(query_hca_cap_out, out, 1222 capability.wqe_based_flow_table_cap. 1223 rtc_log_depth_max); 1224 1225 caps->ste_alloc_log_max = MLX5_GET(query_hca_cap_out, out, 1226 capability.wqe_based_flow_table_cap. 1227 ste_alloc_log_max); 1228 1229 caps->ste_alloc_log_gran = MLX5_GET(query_hca_cap_out, out, 1230 capability.wqe_based_flow_table_cap. 1231 ste_alloc_log_granularity); 1232 1233 caps->trivial_match_definer = MLX5_GET(query_hca_cap_out, out, 1234 capability.wqe_based_flow_table_cap. 1235 trivial_match_definer); 1236 1237 caps->stc_alloc_log_max = MLX5_GET(query_hca_cap_out, out, 1238 capability.wqe_based_flow_table_cap. 1239 stc_alloc_log_max); 1240 1241 caps->stc_alloc_log_gran = MLX5_GET(query_hca_cap_out, out, 1242 capability.wqe_based_flow_table_cap. 1243 stc_alloc_log_granularity); 1244 1245 caps->rtc_hash_split_table = MLX5_GET(query_hca_cap_out, out, 1246 capability.wqe_based_flow_table_cap. 1247 rtc_hash_split_table); 1248 1249 caps->rtc_linear_lookup_table = MLX5_GET(query_hca_cap_out, out, 1250 capability.wqe_based_flow_table_cap. 1251 rtc_linear_lookup_table); 1252 1253 caps->access_index_mode = MLX5_GET(query_hca_cap_out, out, 1254 capability.wqe_based_flow_table_cap. 1255 access_index_mode); 1256 1257 caps->linear_match_definer = MLX5_GET(query_hca_cap_out, out, 1258 capability.wqe_based_flow_table_cap. 1259 linear_match_definer_reg_c3); 1260 1261 caps->rtc_max_hash_def_gen_wqe = MLX5_GET(query_hca_cap_out, out, 1262 capability.wqe_based_flow_table_cap. 1263 rtc_max_num_hash_definer_gen_wqe); 1264 1265 caps->supp_ste_format_gen_wqe = MLX5_GET(query_hca_cap_out, out, 1266 capability.wqe_based_flow_table_cap. 1267 ste_format_gen_wqe); 1268 1269 caps->fdb_tir_stc = MLX5_GET(query_hca_cap_out, out, 1270 capability.wqe_based_flow_table_cap. 1271 fdb_jump_to_tir_stc); 1272 } 1273 1274 if (caps->eswitch_manager) { 1275 MLX5_SET(query_hca_cap_in, in, op_mod, 1276 MLX5_GET_HCA_CAP_OP_MOD_ESW_FLOW_TABLE | 1277 MLX5_HCA_CAP_OPMOD_GET_CUR); 1278 1279 ret = mlx5_glue->devx_general_cmd(ctx, in, sizeof(in), out, sizeof(out)); 1280 if (ret) { 1281 DR_LOG(ERR, "Failed to query flow table esw caps"); 1282 rte_errno = errno; 1283 return rte_errno; 1284 } 1285 1286 caps->fdb_ft.max_level = MLX5_GET(query_hca_cap_out, out, 1287 capability.flow_table_nic_cap. 1288 flow_table_properties_nic_receive.max_ft_level); 1289 1290 caps->fdb_ft.reparse = MLX5_GET(query_hca_cap_out, out, 1291 capability.flow_table_nic_cap. 1292 flow_table_properties_nic_receive.reparse); 1293 1294 MLX5_SET(query_hca_cap_in, in, op_mod, 1295 MLX5_SET_HCA_CAP_OP_MOD_ESW | MLX5_HCA_CAP_OPMOD_GET_CUR); 1296 1297 ret = mlx5_glue->devx_general_cmd(ctx, in, sizeof(in), out, sizeof(out)); 1298 if (ret) { 1299 DR_LOG(ERR, "Query eswitch capabilities failed %d", ret); 1300 rte_errno = errno; 1301 return rte_errno; 1302 } 1303 1304 if (MLX5_GET(query_hca_cap_out, out, 1305 capability.esw_cap.esw_manager_vport_number_valid)) 1306 caps->eswitch_manager_vport_number = 1307 MLX5_GET(query_hca_cap_out, out, 1308 capability.esw_cap.esw_manager_vport_number); 1309 1310 caps->merged_eswitch = MLX5_GET(query_hca_cap_out, out, 1311 capability.esw_cap.merged_eswitch); 1312 } 1313 1314 if (caps->roce) { 1315 MLX5_SET(query_hca_cap_in, in, op_mod, 1316 MLX5_GET_HCA_CAP_OP_MOD_ROCE | 1317 MLX5_HCA_CAP_OPMOD_GET_CUR); 1318 1319 ret = mlx5_glue->devx_general_cmd(ctx, in, sizeof(in), out, sizeof(out)); 1320 if (ret) { 1321 DR_LOG(ERR, "Failed to query roce caps"); 1322 rte_errno = errno; 1323 return rte_errno; 1324 } 1325 1326 caps->roce_max_src_udp_port = MLX5_GET(query_hca_cap_out, out, 1327 capability.roce_caps.r_roce_max_src_udp_port); 1328 caps->roce_min_src_udp_port = MLX5_GET(query_hca_cap_out, out, 1329 capability.roce_caps.r_roce_min_src_udp_port); 1330 } 1331 1332 ret = mlx5_glue->query_device_ex(ctx, NULL, &attr_ex); 1333 if (ret) { 1334 DR_LOG(ERR, "Failed to query device attributes"); 1335 rte_errno = ret; 1336 return rte_errno; 1337 } 1338 1339 strlcpy(caps->fw_ver, attr_ex.orig_attr.fw_ver, sizeof(caps->fw_ver)); 1340 1341 port_info = flow_hw_get_wire_port(ctx); 1342 if (port_info) { 1343 caps->wire_regc = port_info->regc_value; 1344 caps->wire_regc_mask = port_info->regc_mask; 1345 } else { 1346 DR_LOG(INFO, "Failed to query wire port regc value"); 1347 } 1348 1349 return ret; 1350 } 1351 1352 int mlx5dr_cmd_query_ib_port(struct ibv_context *ctx, 1353 struct mlx5dr_cmd_query_vport_caps *vport_caps, 1354 uint32_t port_num) 1355 { 1356 struct mlx5_port_info port_info = {0}; 1357 uint32_t flags; 1358 int ret; 1359 1360 flags = MLX5_PORT_QUERY_VPORT | MLX5_PORT_QUERY_ESW_OWNER_VHCA_ID; 1361 1362 ret = mlx5_glue->devx_port_query(ctx, port_num, &port_info); 1363 /* Check if query succeed and vport is enabled */ 1364 if (ret || (port_info.query_flags & flags) != flags) { 1365 rte_errno = ENOTSUP; 1366 return rte_errno; 1367 } 1368 1369 vport_caps->vport_num = port_info.vport_id; 1370 vport_caps->esw_owner_vhca_id = port_info.esw_owner_vhca_id; 1371 1372 if (port_info.query_flags & MLX5_PORT_QUERY_REG_C0) { 1373 vport_caps->metadata_c = port_info.vport_meta_tag; 1374 vport_caps->metadata_c_mask = port_info.vport_meta_mask; 1375 } 1376 1377 return 0; 1378 } 1379