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 if (rtc_attr->is_compare) { 374 MLX5_SET(rtc, attr, ste_format_0, MLX5_IFC_RTC_STE_FORMAT_4DW_RANGE); 375 } else { 376 MLX5_SET(rtc, attr, ste_format_0, rtc_attr->is_frst_jumbo ? 377 MLX5_IFC_RTC_STE_FORMAT_11DW : MLX5_IFC_RTC_STE_FORMAT_8DW); 378 } 379 380 if (rtc_attr->is_scnd_range) { 381 MLX5_SET(rtc, attr, ste_format_1, MLX5_IFC_RTC_STE_FORMAT_RANGE); 382 MLX5_SET(rtc, attr, num_match_ste, 2); 383 } 384 385 MLX5_SET(rtc, attr, pd, rtc_attr->pd); 386 MLX5_SET(rtc, attr, update_method, rtc_attr->fw_gen_wqe); 387 MLX5_SET(rtc, attr, update_index_mode, rtc_attr->update_index_mode); 388 MLX5_SET(rtc, attr, access_index_mode, rtc_attr->access_index_mode); 389 MLX5_SET(rtc, attr, num_hash_definer, rtc_attr->num_hash_definer); 390 MLX5_SET(rtc, attr, log_depth, rtc_attr->log_depth); 391 MLX5_SET(rtc, attr, log_hash_size, rtc_attr->log_size); 392 MLX5_SET(rtc, attr, table_type, rtc_attr->table_type); 393 MLX5_SET(rtc, attr, num_hash_definer, rtc_attr->num_hash_definer); 394 MLX5_SET(rtc, attr, match_definer_0, rtc_attr->match_definer_0); 395 MLX5_SET(rtc, attr, match_definer_1, rtc_attr->match_definer_1); 396 MLX5_SET(rtc, attr, stc_id, rtc_attr->stc_base); 397 MLX5_SET(rtc, attr, ste_table_base_id, rtc_attr->ste_base); 398 MLX5_SET(rtc, attr, ste_table_offset, rtc_attr->ste_offset); 399 MLX5_SET(rtc, attr, miss_flow_table_id, rtc_attr->miss_ft_id); 400 MLX5_SET(rtc, attr, reparse_mode, rtc_attr->reparse_mode); 401 402 devx_obj->obj = mlx5_glue->devx_obj_create(ctx, in, sizeof(in), out, sizeof(out)); 403 if (!devx_obj->obj) { 404 DR_LOG(ERR, "Failed to create RTC (syndrome: %#x)", 405 mlx5dr_cmd_get_syndrome(out)); 406 simple_free(devx_obj); 407 rte_errno = errno; 408 return NULL; 409 } 410 411 devx_obj->id = MLX5_GET(general_obj_out_cmd_hdr, out, obj_id); 412 413 return devx_obj; 414 } 415 416 struct mlx5dr_devx_obj * 417 mlx5dr_cmd_stc_create(struct ibv_context *ctx, 418 struct mlx5dr_cmd_stc_create_attr *stc_attr) 419 { 420 uint32_t out[MLX5_ST_SZ_DW(general_obj_out_cmd_hdr)] = {0}; 421 uint32_t in[MLX5_ST_SZ_DW(create_stc_in)] = {0}; 422 struct mlx5dr_devx_obj *devx_obj; 423 void *attr; 424 425 devx_obj = simple_malloc(sizeof(*devx_obj)); 426 if (!devx_obj) { 427 DR_LOG(ERR, "Failed to allocate memory for STC object"); 428 rte_errno = ENOMEM; 429 return NULL; 430 } 431 432 attr = MLX5_ADDR_OF(create_stc_in, in, hdr); 433 MLX5_SET(general_obj_in_cmd_hdr, 434 attr, opcode, MLX5_CMD_OP_CREATE_GENERAL_OBJECT); 435 MLX5_SET(general_obj_in_cmd_hdr, 436 attr, obj_type, MLX5_GENERAL_OBJ_TYPE_STC); 437 MLX5_SET(general_obj_in_cmd_hdr, 438 attr, log_obj_range, stc_attr->log_obj_range); 439 440 attr = MLX5_ADDR_OF(create_stc_in, in, stc); 441 MLX5_SET(stc, attr, table_type, stc_attr->table_type); 442 443 devx_obj->obj = mlx5_glue->devx_obj_create(ctx, in, sizeof(in), out, sizeof(out)); 444 if (!devx_obj->obj) { 445 DR_LOG(ERR, "Failed to create STC (syndrome: %#x)", 446 mlx5dr_cmd_get_syndrome(out)); 447 simple_free(devx_obj); 448 rte_errno = errno; 449 return NULL; 450 } 451 452 devx_obj->id = MLX5_GET(general_obj_out_cmd_hdr, out, obj_id); 453 454 return devx_obj; 455 } 456 457 static int 458 mlx5dr_cmd_stc_modify_set_stc_param(struct mlx5dr_cmd_stc_modify_attr *stc_attr, 459 void *stc_param) 460 { 461 switch (stc_attr->action_type) { 462 case MLX5_IFC_STC_ACTION_TYPE_COUNTER: 463 MLX5_SET(stc_ste_param_flow_counter, stc_param, flow_counter_id, stc_attr->id); 464 break; 465 case MLX5_IFC_STC_ACTION_TYPE_JUMP_TO_TIR: 466 MLX5_SET(stc_ste_param_tir, stc_param, tirn, stc_attr->dest_tir_num); 467 break; 468 case MLX5_IFC_STC_ACTION_TYPE_JUMP_TO_FT: 469 MLX5_SET(stc_ste_param_table, stc_param, table_id, stc_attr->dest_table_id); 470 break; 471 case MLX5_IFC_STC_ACTION_TYPE_ACC_MODIFY_LIST: 472 MLX5_SET(stc_ste_param_header_modify_list, stc_param, 473 header_modify_pattern_id, stc_attr->modify_header.pattern_id); 474 MLX5_SET(stc_ste_param_header_modify_list, stc_param, 475 header_modify_argument_id, stc_attr->modify_header.arg_id); 476 break; 477 case MLX5_IFC_STC_ACTION_TYPE_HEADER_REMOVE: 478 MLX5_SET(stc_ste_param_remove, stc_param, action_type, 479 MLX5_MODIFICATION_TYPE_REMOVE); 480 MLX5_SET(stc_ste_param_remove, stc_param, decap, 481 stc_attr->remove_header.decap); 482 MLX5_SET(stc_ste_param_remove, stc_param, remove_start_anchor, 483 stc_attr->remove_header.start_anchor); 484 MLX5_SET(stc_ste_param_remove, stc_param, remove_end_anchor, 485 stc_attr->remove_header.end_anchor); 486 break; 487 case MLX5_IFC_STC_ACTION_TYPE_HEADER_INSERT: 488 MLX5_SET(stc_ste_param_insert, stc_param, action_type, 489 MLX5_MODIFICATION_TYPE_INSERT); 490 MLX5_SET(stc_ste_param_insert, stc_param, encap, 491 stc_attr->insert_header.encap); 492 MLX5_SET(stc_ste_param_insert, stc_param, push_esp, 493 stc_attr->insert_header.push_esp); 494 MLX5_SET(stc_ste_param_insert, stc_param, inline_data, 495 stc_attr->insert_header.is_inline); 496 MLX5_SET(stc_ste_param_insert, stc_param, insert_anchor, 497 stc_attr->insert_header.insert_anchor); 498 /* HW gets the next 2 sizes in words */ 499 MLX5_SET(stc_ste_param_insert, stc_param, insert_size, 500 stc_attr->insert_header.header_size / W_SIZE); 501 MLX5_SET(stc_ste_param_insert, stc_param, insert_offset, 502 stc_attr->insert_header.insert_offset / W_SIZE); 503 MLX5_SET(stc_ste_param_insert, stc_param, insert_argument, 504 stc_attr->insert_header.arg_id); 505 break; 506 case MLX5_IFC_STC_ACTION_TYPE_COPY: 507 case MLX5_IFC_STC_ACTION_TYPE_SET: 508 case MLX5_IFC_STC_ACTION_TYPE_ADD: 509 case MLX5_IFC_STC_ACTION_TYPE_ADD_FIELD: 510 *(__be64 *)stc_param = stc_attr->modify_action.data; 511 break; 512 case MLX5_IFC_STC_ACTION_TYPE_JUMP_TO_VPORT: 513 case MLX5_IFC_STC_ACTION_TYPE_JUMP_TO_UPLINK: 514 MLX5_SET(stc_ste_param_vport, stc_param, vport_number, 515 stc_attr->vport.vport_num); 516 MLX5_SET(stc_ste_param_vport, stc_param, eswitch_owner_vhca_id, 517 stc_attr->vport.esw_owner_vhca_id); 518 MLX5_SET(stc_ste_param_vport, stc_param, eswitch_owner_vhca_id_valid, 519 stc_attr->vport.eswitch_owner_vhca_id_valid); 520 break; 521 case MLX5_IFC_STC_ACTION_TYPE_DROP: 522 case MLX5_IFC_STC_ACTION_TYPE_NOP: 523 case MLX5_IFC_STC_ACTION_TYPE_TAG: 524 case MLX5_IFC_STC_ACTION_TYPE_ALLOW: 525 break; 526 case MLX5_IFC_STC_ACTION_TYPE_ASO: 527 MLX5_SET(stc_ste_param_execute_aso, stc_param, aso_object_id, 528 stc_attr->aso.devx_obj_id); 529 MLX5_SET(stc_ste_param_execute_aso, stc_param, return_reg_id, 530 stc_attr->aso.return_reg_id); 531 MLX5_SET(stc_ste_param_execute_aso, stc_param, aso_type, 532 stc_attr->aso.aso_type); 533 break; 534 case MLX5_IFC_STC_ACTION_TYPE_JUMP_TO_STE_TABLE: 535 MLX5_SET(stc_ste_param_ste_table, stc_param, ste_obj_id, 536 stc_attr->ste_table.ste_obj_id); 537 MLX5_SET(stc_ste_param_ste_table, stc_param, match_definer_id, 538 stc_attr->ste_table.match_definer_id); 539 MLX5_SET(stc_ste_param_ste_table, stc_param, log_hash_size, 540 stc_attr->ste_table.log_hash_size); 541 break; 542 case MLX5_IFC_STC_ACTION_TYPE_REMOVE_WORDS: 543 MLX5_SET(stc_ste_param_remove_words, stc_param, action_type, 544 MLX5_MODIFICATION_TYPE_REMOVE_WORDS); 545 MLX5_SET(stc_ste_param_remove_words, stc_param, remove_start_anchor, 546 stc_attr->remove_words.start_anchor); 547 MLX5_SET(stc_ste_param_remove_words, stc_param, 548 remove_size, stc_attr->remove_words.num_of_words); 549 break; 550 default: 551 DR_LOG(ERR, "Not supported type %d", stc_attr->action_type); 552 rte_errno = EINVAL; 553 return rte_errno; 554 } 555 return 0; 556 } 557 558 int 559 mlx5dr_cmd_stc_modify(struct mlx5dr_devx_obj *devx_obj, 560 struct mlx5dr_cmd_stc_modify_attr *stc_attr) 561 { 562 uint32_t out[MLX5_ST_SZ_DW(general_obj_out_cmd_hdr)] = {0}; 563 uint32_t in[MLX5_ST_SZ_DW(create_stc_in)] = {0}; 564 void *stc_param; 565 void *attr; 566 int ret; 567 568 attr = MLX5_ADDR_OF(create_stc_in, in, hdr); 569 MLX5_SET(general_obj_in_cmd_hdr, 570 attr, opcode, MLX5_CMD_OP_MODIFY_GENERAL_OBJECT); 571 MLX5_SET(general_obj_in_cmd_hdr, 572 attr, obj_type, MLX5_GENERAL_OBJ_TYPE_STC); 573 MLX5_SET(general_obj_in_cmd_hdr, in, obj_id, devx_obj->id); 574 MLX5_SET(general_obj_in_cmd_hdr, in, obj_offset, stc_attr->stc_offset); 575 576 attr = MLX5_ADDR_OF(create_stc_in, in, stc); 577 MLX5_SET(stc, attr, ste_action_offset, stc_attr->action_offset); 578 MLX5_SET(stc, attr, action_type, stc_attr->action_type); 579 MLX5_SET(stc, attr, reparse_mode, stc_attr->reparse_mode); 580 MLX5_SET64(stc, attr, modify_field_select, 581 MLX5_IFC_MODIFY_STC_FIELD_SELECT_NEW_STC); 582 583 /* Set destination TIRN, TAG, FT ID, STE ID */ 584 stc_param = MLX5_ADDR_OF(stc, attr, stc_param); 585 ret = mlx5dr_cmd_stc_modify_set_stc_param(stc_attr, stc_param); 586 if (ret) 587 return ret; 588 589 ret = mlx5_glue->devx_obj_modify(devx_obj->obj, in, sizeof(in), out, sizeof(out)); 590 if (ret) { 591 DR_LOG(ERR, "Failed to modify STC FW action_type %d (syndrome: %#x)", 592 stc_attr->action_type, mlx5dr_cmd_get_syndrome(out)); 593 rte_errno = errno; 594 } 595 596 return ret; 597 } 598 599 struct mlx5dr_devx_obj * 600 mlx5dr_cmd_arg_create(struct ibv_context *ctx, 601 uint16_t log_obj_range, 602 uint32_t pd) 603 { 604 uint32_t out[MLX5_ST_SZ_DW(general_obj_out_cmd_hdr)] = {0}; 605 uint32_t in[MLX5_ST_SZ_DW(create_arg_in)] = {0}; 606 struct mlx5dr_devx_obj *devx_obj; 607 void *attr; 608 609 devx_obj = simple_malloc(sizeof(*devx_obj)); 610 if (!devx_obj) { 611 DR_LOG(ERR, "Failed to allocate memory for ARG object"); 612 rte_errno = ENOMEM; 613 return NULL; 614 } 615 616 attr = MLX5_ADDR_OF(create_arg_in, in, hdr); 617 MLX5_SET(general_obj_in_cmd_hdr, 618 attr, opcode, MLX5_CMD_OP_CREATE_GENERAL_OBJECT); 619 MLX5_SET(general_obj_in_cmd_hdr, 620 attr, obj_type, MLX5_GENERAL_OBJ_TYPE_ARG); 621 MLX5_SET(general_obj_in_cmd_hdr, 622 attr, log_obj_range, log_obj_range); 623 624 attr = MLX5_ADDR_OF(create_arg_in, in, arg); 625 MLX5_SET(arg, attr, access_pd, pd); 626 627 devx_obj->obj = mlx5_glue->devx_obj_create(ctx, in, sizeof(in), out, sizeof(out)); 628 if (!devx_obj->obj) { 629 DR_LOG(ERR, "Failed to create ARG (syndrome: %#x)", 630 mlx5dr_cmd_get_syndrome(out)); 631 simple_free(devx_obj); 632 rte_errno = errno; 633 return NULL; 634 } 635 636 devx_obj->id = MLX5_GET(general_obj_out_cmd_hdr, out, obj_id); 637 638 return devx_obj; 639 } 640 641 struct mlx5dr_devx_obj * 642 mlx5dr_cmd_header_modify_pattern_create(struct ibv_context *ctx, 643 uint32_t pattern_length, 644 uint8_t *actions) 645 { 646 uint32_t in[MLX5_ST_SZ_DW(create_header_modify_pattern_in)] = {0}; 647 uint32_t out[MLX5_ST_SZ_DW(general_obj_out_cmd_hdr)] = {0}; 648 struct mlx5dr_devx_obj *devx_obj; 649 uint64_t *pattern_data; 650 int num_of_actions; 651 void *pattern; 652 void *attr; 653 int i; 654 655 if (pattern_length > MAX_ACTIONS_DATA_IN_HEADER_MODIFY) { 656 DR_LOG(ERR, "Pattern length %d exceeds limit %d", 657 pattern_length, MAX_ACTIONS_DATA_IN_HEADER_MODIFY); 658 rte_errno = EINVAL; 659 return NULL; 660 } 661 662 devx_obj = simple_malloc(sizeof(*devx_obj)); 663 if (!devx_obj) { 664 DR_LOG(ERR, "Failed to allocate memory for header_modify_pattern object"); 665 rte_errno = ENOMEM; 666 return NULL; 667 } 668 attr = MLX5_ADDR_OF(create_header_modify_pattern_in, in, hdr); 669 MLX5_SET(general_obj_in_cmd_hdr, 670 attr, opcode, MLX5_CMD_OP_CREATE_GENERAL_OBJECT); 671 MLX5_SET(general_obj_in_cmd_hdr, 672 attr, obj_type, MLX5_GENERAL_OBJ_TYPE_MODIFY_HEADER_PATTERN); 673 674 pattern = MLX5_ADDR_OF(create_header_modify_pattern_in, in, pattern); 675 /* Pattern_length is in ddwords */ 676 MLX5_SET(header_modify_pattern_in, pattern, pattern_length, pattern_length / (2 * DW_SIZE)); 677 678 pattern_data = (uint64_t *)MLX5_ADDR_OF(header_modify_pattern_in, pattern, pattern_data); 679 memcpy(pattern_data, actions, pattern_length); 680 681 num_of_actions = pattern_length / MLX5DR_MODIFY_ACTION_SIZE; 682 for (i = 0; i < num_of_actions; i++) { 683 int type; 684 685 type = MLX5_GET(set_action_in, &pattern_data[i], action_type); 686 if (type != MLX5_MODIFICATION_TYPE_COPY && 687 type != MLX5_MODIFICATION_TYPE_ADD_FIELD) 688 /* Action typ-copy use all bytes for control */ 689 MLX5_SET(set_action_in, &pattern_data[i], data, 0); 690 } 691 692 devx_obj->obj = mlx5_glue->devx_obj_create(ctx, in, sizeof(in), out, sizeof(out)); 693 if (!devx_obj->obj) { 694 DR_LOG(ERR, "Failed to create header_modify_pattern (syndrome: %#x)", 695 mlx5dr_cmd_get_syndrome(out)); 696 rte_errno = errno; 697 goto free_obj; 698 } 699 700 devx_obj->id = MLX5_GET(general_obj_out_cmd_hdr, out, obj_id); 701 702 return devx_obj; 703 704 free_obj: 705 simple_free(devx_obj); 706 return NULL; 707 } 708 709 struct mlx5dr_devx_obj * 710 mlx5dr_cmd_ste_create(struct ibv_context *ctx, 711 struct mlx5dr_cmd_ste_create_attr *ste_attr) 712 { 713 uint32_t out[MLX5_ST_SZ_DW(general_obj_out_cmd_hdr)] = {0}; 714 uint32_t in[MLX5_ST_SZ_DW(create_ste_in)] = {0}; 715 struct mlx5dr_devx_obj *devx_obj; 716 void *attr; 717 718 devx_obj = simple_malloc(sizeof(*devx_obj)); 719 if (!devx_obj) { 720 DR_LOG(ERR, "Failed to allocate memory for STE object"); 721 rte_errno = ENOMEM; 722 return NULL; 723 } 724 725 attr = MLX5_ADDR_OF(create_ste_in, in, hdr); 726 MLX5_SET(general_obj_in_cmd_hdr, 727 attr, opcode, MLX5_CMD_OP_CREATE_GENERAL_OBJECT); 728 MLX5_SET(general_obj_in_cmd_hdr, 729 attr, obj_type, MLX5_GENERAL_OBJ_TYPE_STE); 730 MLX5_SET(general_obj_in_cmd_hdr, 731 attr, log_obj_range, ste_attr->log_obj_range); 732 733 attr = MLX5_ADDR_OF(create_ste_in, in, ste); 734 MLX5_SET(ste, attr, table_type, ste_attr->table_type); 735 736 devx_obj->obj = mlx5_glue->devx_obj_create(ctx, in, sizeof(in), out, sizeof(out)); 737 if (!devx_obj->obj) { 738 DR_LOG(ERR, "Failed to create STE (syndrome: %#x)", 739 mlx5dr_cmd_get_syndrome(out)); 740 simple_free(devx_obj); 741 rte_errno = errno; 742 return NULL; 743 } 744 745 devx_obj->id = MLX5_GET(general_obj_out_cmd_hdr, out, obj_id); 746 747 return devx_obj; 748 } 749 750 struct mlx5dr_devx_obj * 751 mlx5dr_cmd_definer_create(struct ibv_context *ctx, 752 struct mlx5dr_cmd_definer_create_attr *def_attr) 753 { 754 uint32_t out[MLX5_ST_SZ_DW(general_obj_out_cmd_hdr)] = {0}; 755 uint32_t in[MLX5_ST_SZ_DW(create_definer_in)] = {0}; 756 struct mlx5dr_devx_obj *devx_obj; 757 void *ptr; 758 759 devx_obj = simple_malloc(sizeof(*devx_obj)); 760 if (!devx_obj) { 761 DR_LOG(ERR, "Failed to allocate memory for definer object"); 762 rte_errno = ENOMEM; 763 return NULL; 764 } 765 766 MLX5_SET(general_obj_in_cmd_hdr, 767 in, opcode, MLX5_CMD_OP_CREATE_GENERAL_OBJECT); 768 MLX5_SET(general_obj_in_cmd_hdr, 769 in, obj_type, MLX5_GENERAL_OBJ_TYPE_DEFINER); 770 771 ptr = MLX5_ADDR_OF(create_definer_in, in, definer); 772 MLX5_SET(definer, ptr, format_id, MLX5_IFC_DEFINER_FORMAT_ID_SELECT); 773 774 MLX5_SET(definer, ptr, format_select_dw0, def_attr->dw_selector[0]); 775 MLX5_SET(definer, ptr, format_select_dw1, def_attr->dw_selector[1]); 776 MLX5_SET(definer, ptr, format_select_dw2, def_attr->dw_selector[2]); 777 MLX5_SET(definer, ptr, format_select_dw3, def_attr->dw_selector[3]); 778 MLX5_SET(definer, ptr, format_select_dw4, def_attr->dw_selector[4]); 779 MLX5_SET(definer, ptr, format_select_dw5, def_attr->dw_selector[5]); 780 MLX5_SET(definer, ptr, format_select_dw6, def_attr->dw_selector[6]); 781 MLX5_SET(definer, ptr, format_select_dw7, def_attr->dw_selector[7]); 782 MLX5_SET(definer, ptr, format_select_dw8, def_attr->dw_selector[8]); 783 784 MLX5_SET(definer, ptr, format_select_byte0, def_attr->byte_selector[0]); 785 MLX5_SET(definer, ptr, format_select_byte1, def_attr->byte_selector[1]); 786 MLX5_SET(definer, ptr, format_select_byte2, def_attr->byte_selector[2]); 787 MLX5_SET(definer, ptr, format_select_byte3, def_attr->byte_selector[3]); 788 MLX5_SET(definer, ptr, format_select_byte4, def_attr->byte_selector[4]); 789 MLX5_SET(definer, ptr, format_select_byte5, def_attr->byte_selector[5]); 790 MLX5_SET(definer, ptr, format_select_byte6, def_attr->byte_selector[6]); 791 MLX5_SET(definer, ptr, format_select_byte7, def_attr->byte_selector[7]); 792 793 ptr = MLX5_ADDR_OF(definer, ptr, match_mask); 794 memcpy(ptr, def_attr->match_mask, MLX5_FLD_SZ_BYTES(definer, match_mask)); 795 796 devx_obj->obj = mlx5_glue->devx_obj_create(ctx, in, sizeof(in), out, sizeof(out)); 797 if (!devx_obj->obj) { 798 DR_LOG(ERR, "Failed to create Definer (syndrome: %#x)", 799 mlx5dr_cmd_get_syndrome(out)); 800 simple_free(devx_obj); 801 rte_errno = errno; 802 return NULL; 803 } 804 805 devx_obj->id = MLX5_GET(general_obj_out_cmd_hdr, out, obj_id); 806 807 return devx_obj; 808 } 809 810 struct mlx5dr_devx_obj * 811 mlx5dr_cmd_sq_create(struct ibv_context *ctx, 812 struct mlx5dr_cmd_sq_create_attr *attr) 813 { 814 uint32_t out[MLX5_ST_SZ_DW(create_sq_out)] = {0}; 815 uint32_t in[MLX5_ST_SZ_DW(create_sq_in)] = {0}; 816 void *sqc = MLX5_ADDR_OF(create_sq_in, in, ctx); 817 void *wqc = MLX5_ADDR_OF(sqc, sqc, wq); 818 struct mlx5dr_devx_obj *devx_obj; 819 820 devx_obj = simple_malloc(sizeof(*devx_obj)); 821 if (!devx_obj) { 822 DR_LOG(ERR, "Failed to create SQ"); 823 rte_errno = ENOMEM; 824 return NULL; 825 } 826 827 MLX5_SET(create_sq_in, in, opcode, MLX5_CMD_OP_CREATE_SQ); 828 MLX5_SET(sqc, sqc, cqn, attr->cqn); 829 MLX5_SET(sqc, sqc, flush_in_error_en, 1); 830 MLX5_SET(sqc, sqc, non_wire, 1); 831 MLX5_SET(sqc, sqc, ts_format, attr->ts_format); 832 MLX5_SET(wq, wqc, wq_type, MLX5_WQ_TYPE_CYCLIC); 833 MLX5_SET(wq, wqc, pd, attr->pdn); 834 MLX5_SET(wq, wqc, uar_page, attr->page_id); 835 MLX5_SET(wq, wqc, log_wq_stride, log2above(MLX5_SEND_WQE_BB)); 836 MLX5_SET(wq, wqc, log_wq_sz, attr->log_wq_sz); 837 MLX5_SET(wq, wqc, dbr_umem_id, attr->dbr_id); 838 MLX5_SET(wq, wqc, wq_umem_id, attr->wq_id); 839 840 devx_obj->obj = mlx5_glue->devx_obj_create(ctx, in, sizeof(in), out, sizeof(out)); 841 if (!devx_obj->obj) { 842 simple_free(devx_obj); 843 rte_errno = errno; 844 return NULL; 845 } 846 847 devx_obj->id = MLX5_GET(create_sq_out, out, sqn); 848 849 return devx_obj; 850 } 851 852 struct mlx5dr_devx_obj * 853 mlx5dr_cmd_packet_reformat_create(struct ibv_context *ctx, 854 struct mlx5dr_cmd_packet_reformat_create_attr *attr) 855 { 856 uint32_t out[MLX5_ST_SZ_DW(alloc_packet_reformat_out)] = {0}; 857 size_t insz, cmd_data_sz, cmd_total_sz; 858 struct mlx5dr_devx_obj *devx_obj; 859 void *prctx; 860 void *pdata; 861 void *in; 862 863 cmd_total_sz = MLX5_ST_SZ_BYTES(alloc_packet_reformat_context_in); 864 cmd_total_sz += MLX5_ST_SZ_BYTES(packet_reformat_context_in); 865 cmd_data_sz = MLX5_FLD_SZ_BYTES(packet_reformat_context_in, reformat_data); 866 insz = align(cmd_total_sz + attr->data_sz - cmd_data_sz, DW_SIZE); 867 in = simple_calloc(1, insz); 868 if (!in) { 869 rte_errno = ENOMEM; 870 return NULL; 871 } 872 873 MLX5_SET(alloc_packet_reformat_context_in, in, opcode, 874 MLX5_CMD_OP_ALLOC_PACKET_REFORMAT_CONTEXT); 875 876 prctx = MLX5_ADDR_OF(alloc_packet_reformat_context_in, in, 877 packet_reformat_context); 878 pdata = MLX5_ADDR_OF(packet_reformat_context_in, prctx, reformat_data); 879 880 MLX5_SET(packet_reformat_context_in, prctx, reformat_type, attr->type); 881 MLX5_SET(packet_reformat_context_in, prctx, reformat_param_0, attr->reformat_param_0); 882 MLX5_SET(packet_reformat_context_in, prctx, reformat_data_size, attr->data_sz); 883 memcpy(pdata, attr->data, attr->data_sz); 884 885 devx_obj = simple_malloc(sizeof(*devx_obj)); 886 if (!devx_obj) { 887 DR_LOG(ERR, "Failed to allocate memory for packet reformat object"); 888 rte_errno = ENOMEM; 889 goto out_free_in; 890 } 891 892 devx_obj->obj = mlx5_glue->devx_obj_create(ctx, in, insz, out, sizeof(out)); 893 if (!devx_obj->obj) { 894 DR_LOG(ERR, "Failed to create packet reformat"); 895 rte_errno = errno; 896 goto out_free_devx; 897 } 898 899 devx_obj->id = MLX5_GET(alloc_packet_reformat_out, out, packet_reformat_id); 900 901 simple_free(in); 902 903 return devx_obj; 904 905 out_free_devx: 906 simple_free(devx_obj); 907 out_free_in: 908 simple_free(in); 909 return NULL; 910 } 911 912 int mlx5dr_cmd_sq_modify_rdy(struct mlx5dr_devx_obj *devx_obj) 913 { 914 uint32_t out[MLX5_ST_SZ_DW(modify_sq_out)] = {0}; 915 uint32_t in[MLX5_ST_SZ_DW(modify_sq_in)] = {0}; 916 void *sqc = MLX5_ADDR_OF(modify_sq_in, in, ctx); 917 int ret; 918 919 MLX5_SET(modify_sq_in, in, opcode, MLX5_CMD_OP_MODIFY_SQ); 920 MLX5_SET(modify_sq_in, in, sqn, devx_obj->id); 921 MLX5_SET(modify_sq_in, in, sq_state, MLX5_SQC_STATE_RST); 922 MLX5_SET(sqc, sqc, state, MLX5_SQC_STATE_RDY); 923 924 ret = mlx5_glue->devx_obj_modify(devx_obj->obj, in, sizeof(in), out, sizeof(out)); 925 if (ret) { 926 DR_LOG(ERR, "Failed to modify SQ (syndrome: %#x)", 927 mlx5dr_cmd_get_syndrome(out)); 928 rte_errno = errno; 929 } 930 931 return ret; 932 } 933 934 int mlx5dr_cmd_allow_other_vhca_access(struct ibv_context *ctx, 935 struct mlx5dr_cmd_allow_other_vhca_access_attr *attr) 936 { 937 uint32_t out[MLX5_ST_SZ_DW(allow_other_vhca_access_out)] = {0}; 938 uint32_t in[MLX5_ST_SZ_DW(allow_other_vhca_access_in)] = {0}; 939 void *key; 940 int ret; 941 942 MLX5_SET(allow_other_vhca_access_in, 943 in, opcode, MLX5_CMD_OP_ALLOW_OTHER_VHCA_ACCESS); 944 MLX5_SET(allow_other_vhca_access_in, 945 in, object_type_to_be_accessed, attr->obj_type); 946 MLX5_SET(allow_other_vhca_access_in, 947 in, object_id_to_be_accessed, attr->obj_id); 948 949 key = MLX5_ADDR_OF(allow_other_vhca_access_in, in, access_key); 950 memcpy(key, attr->access_key, sizeof(attr->access_key)); 951 952 ret = mlx5_glue->devx_general_cmd(ctx, in, sizeof(in), out, sizeof(out)); 953 if (ret) { 954 DR_LOG(ERR, "Failed to execute ALLOW_OTHER_VHCA_ACCESS command"); 955 rte_errno = errno; 956 return rte_errno; 957 } 958 959 return 0; 960 } 961 962 struct mlx5dr_devx_obj * 963 mlx5dr_cmd_alias_obj_create(struct ibv_context *ctx, 964 struct mlx5dr_cmd_alias_obj_create_attr *alias_attr) 965 { 966 uint32_t out[MLX5_ST_SZ_DW(general_obj_out_cmd_hdr)] = {0}; 967 uint32_t in[MLX5_ST_SZ_DW(create_alias_obj_in)] = {0}; 968 struct mlx5dr_devx_obj *devx_obj; 969 void *attr; 970 void *key; 971 972 devx_obj = simple_malloc(sizeof(*devx_obj)); 973 if (!devx_obj) { 974 DR_LOG(ERR, "Failed to allocate memory for ALIAS general object"); 975 rte_errno = ENOMEM; 976 return NULL; 977 } 978 979 attr = MLX5_ADDR_OF(create_alias_obj_in, in, hdr); 980 MLX5_SET(general_obj_in_cmd_hdr, 981 attr, opcode, MLX5_CMD_OP_CREATE_GENERAL_OBJECT); 982 MLX5_SET(general_obj_in_cmd_hdr, 983 attr, obj_type, alias_attr->obj_type); 984 MLX5_SET(general_obj_in_cmd_hdr, attr, alias_object, 1); 985 986 attr = MLX5_ADDR_OF(create_alias_obj_in, in, alias_ctx); 987 MLX5_SET(alias_context, attr, vhca_id_to_be_accessed, alias_attr->vhca_id); 988 MLX5_SET(alias_context, attr, object_id_to_be_accessed, alias_attr->obj_id); 989 990 key = MLX5_ADDR_OF(alias_context, attr, access_key); 991 memcpy(key, alias_attr->access_key, sizeof(alias_attr->access_key)); 992 993 devx_obj->obj = mlx5_glue->devx_obj_create(ctx, in, sizeof(in), out, sizeof(out)); 994 if (!devx_obj->obj) { 995 DR_LOG(ERR, "Failed to create ALIAS OBJ (syndrome: %#x)", 996 mlx5dr_cmd_get_syndrome(out)); 997 simple_free(devx_obj); 998 rte_errno = errno; 999 return NULL; 1000 } 1001 1002 devx_obj->id = MLX5_GET(general_obj_out_cmd_hdr, out, obj_id); 1003 1004 return devx_obj; 1005 } 1006 1007 int mlx5dr_cmd_generate_wqe(struct ibv_context *ctx, 1008 struct mlx5dr_cmd_generate_wqe_attr *attr, 1009 struct mlx5_cqe64 *ret_cqe) 1010 { 1011 uint32_t out[MLX5_ST_SZ_DW(generate_wqe_out)] = {0}; 1012 uint32_t in[MLX5_ST_SZ_DW(generate_wqe_in)] = {0}; 1013 uint8_t status; 1014 void *ptr; 1015 int ret; 1016 1017 MLX5_SET(generate_wqe_in, in, opcode, MLX5_CMD_OP_GENERATE_WQE); 1018 MLX5_SET(generate_wqe_in, in, pdn, attr->pdn); 1019 1020 ptr = MLX5_ADDR_OF(generate_wqe_in, in, wqe_ctrl); 1021 memcpy(ptr, attr->wqe_ctrl, MLX5_FLD_SZ_BYTES(generate_wqe_in, wqe_ctrl)); 1022 1023 ptr = MLX5_ADDR_OF(generate_wqe_in, in, wqe_gta_ctrl); 1024 memcpy(ptr, attr->gta_ctrl, MLX5_FLD_SZ_BYTES(generate_wqe_in, wqe_gta_ctrl)); 1025 1026 ptr = MLX5_ADDR_OF(generate_wqe_in, in, wqe_gta_data_0); 1027 memcpy(ptr, attr->gta_data_0, MLX5_FLD_SZ_BYTES(generate_wqe_in, wqe_gta_data_0)); 1028 1029 if (attr->gta_data_1) { 1030 ptr = MLX5_ADDR_OF(generate_wqe_in, in, wqe_gta_data_1); 1031 memcpy(ptr, attr->gta_data_1, MLX5_FLD_SZ_BYTES(generate_wqe_in, wqe_gta_data_1)); 1032 } 1033 1034 ret = mlx5_glue->devx_general_cmd(ctx, in, sizeof(in), out, sizeof(out)); 1035 if (ret) { 1036 DR_LOG(ERR, "Failed to write GTA WQE using FW (syndrome: %#x)", 1037 mlx5dr_cmd_get_syndrome(out)); 1038 rte_errno = errno; 1039 return rte_errno; 1040 } 1041 1042 status = MLX5_GET(generate_wqe_out, out, status); 1043 if (status) { 1044 DR_LOG(ERR, "Invalid FW CQE status %d", status); 1045 rte_errno = EINVAL; 1046 return rte_errno; 1047 } 1048 1049 ptr = MLX5_ADDR_OF(generate_wqe_out, out, cqe_data); 1050 memcpy(ret_cqe, ptr, sizeof(*ret_cqe)); 1051 1052 return 0; 1053 } 1054 1055 int mlx5dr_cmd_query_caps(struct ibv_context *ctx, 1056 struct mlx5dr_cmd_query_caps *caps) 1057 { 1058 uint32_t out[MLX5_ST_SZ_DW(query_hca_cap_out)] = {0}; 1059 uint32_t in[MLX5_ST_SZ_DW(query_hca_cap_in)] = {0}; 1060 const struct flow_hw_port_info *port_info; 1061 struct ibv_device_attr_ex attr_ex; 1062 u32 res; 1063 int ret; 1064 1065 MLX5_SET(query_hca_cap_in, in, opcode, MLX5_CMD_OP_QUERY_HCA_CAP); 1066 MLX5_SET(query_hca_cap_in, in, op_mod, 1067 MLX5_GET_HCA_CAP_OP_MOD_GENERAL_DEVICE | 1068 MLX5_HCA_CAP_OPMOD_GET_CUR); 1069 1070 ret = mlx5_glue->devx_general_cmd(ctx, in, sizeof(in), out, sizeof(out)); 1071 if (ret) { 1072 DR_LOG(ERR, "Failed to query device caps"); 1073 rte_errno = errno; 1074 return rte_errno; 1075 } 1076 1077 caps->wqe_based_update = 1078 MLX5_GET(query_hca_cap_out, out, 1079 capability.cmd_hca_cap.wqe_based_flow_table_update_cap); 1080 1081 caps->eswitch_manager = MLX5_GET(query_hca_cap_out, out, 1082 capability.cmd_hca_cap.eswitch_manager); 1083 1084 caps->flex_protocols = MLX5_GET(query_hca_cap_out, out, 1085 capability.cmd_hca_cap.flex_parser_protocols); 1086 1087 caps->log_header_modify_argument_granularity = 1088 MLX5_GET(query_hca_cap_out, out, 1089 capability.cmd_hca_cap.log_header_modify_argument_granularity); 1090 1091 caps->log_header_modify_argument_granularity -= 1092 MLX5_GET(query_hca_cap_out, out, 1093 capability.cmd_hca_cap. 1094 log_header_modify_argument_granularity_offset); 1095 1096 caps->log_header_modify_argument_max_alloc = 1097 MLX5_GET(query_hca_cap_out, out, 1098 capability.cmd_hca_cap.log_header_modify_argument_max_alloc); 1099 1100 caps->definer_format_sup = 1101 MLX5_GET64(query_hca_cap_out, out, 1102 capability.cmd_hca_cap.match_definer_format_supported); 1103 1104 caps->vhca_id = MLX5_GET(query_hca_cap_out, out, 1105 capability.cmd_hca_cap.vhca_id); 1106 1107 caps->sq_ts_format = MLX5_GET(query_hca_cap_out, out, 1108 capability.cmd_hca_cap.sq_ts_format); 1109 1110 caps->ipsec_offload = MLX5_GET(query_hca_cap_out, out, 1111 capability.cmd_hca_cap.ipsec_offload); 1112 1113 caps->roce = MLX5_GET(query_hca_cap_out, out, capability.cmd_hca_cap.roce); 1114 1115 MLX5_SET(query_hca_cap_in, in, op_mod, 1116 MLX5_GET_HCA_CAP_OP_MOD_GENERAL_DEVICE_2 | 1117 MLX5_HCA_CAP_OPMOD_GET_CUR); 1118 1119 ret = mlx5_glue->devx_general_cmd(ctx, in, sizeof(in), out, sizeof(out)); 1120 if (ret) { 1121 DR_LOG(ERR, "Failed to query device caps"); 1122 rte_errno = errno; 1123 return rte_errno; 1124 } 1125 1126 caps->full_dw_jumbo_support = MLX5_GET(query_hca_cap_out, out, 1127 capability.cmd_hca_cap_2. 1128 format_select_dw_8_6_ext); 1129 1130 caps->format_select_gtpu_dw_0 = MLX5_GET(query_hca_cap_out, out, 1131 capability.cmd_hca_cap_2. 1132 format_select_dw_gtpu_dw_0); 1133 1134 caps->format_select_gtpu_dw_1 = MLX5_GET(query_hca_cap_out, out, 1135 capability.cmd_hca_cap_2. 1136 format_select_dw_gtpu_dw_1); 1137 1138 caps->format_select_gtpu_dw_2 = MLX5_GET(query_hca_cap_out, out, 1139 capability.cmd_hca_cap_2. 1140 format_select_dw_gtpu_dw_2); 1141 1142 caps->format_select_gtpu_ext_dw_0 = MLX5_GET(query_hca_cap_out, out, 1143 capability.cmd_hca_cap_2. 1144 format_select_dw_gtpu_first_ext_dw_0); 1145 1146 caps->supp_type_gen_wqe = MLX5_GET(query_hca_cap_out, out, 1147 capability.cmd_hca_cap_2. 1148 generate_wqe_type); 1149 1150 /* check cross-VHCA support in cap2 */ 1151 res = 1152 MLX5_GET(query_hca_cap_out, out, 1153 capability.cmd_hca_cap_2.cross_vhca_object_to_object_supported); 1154 1155 caps->cross_vhca_resources = (res & MLX5_CROSS_VHCA_OBJ_TO_OBJ_TYPE_STC_TO_TIR) && 1156 (res & MLX5_CROSS_VHCA_OBJ_TO_OBJ_TYPE_STC_TO_FT) && 1157 (res & MLX5_CROSS_VHCA_OBJ_TO_OBJ_TYPE_FT_TO_RTC); 1158 1159 res = 1160 MLX5_GET(query_hca_cap_out, out, 1161 capability.cmd_hca_cap_2.allowed_object_for_other_vhca_access); 1162 1163 caps->cross_vhca_resources &= (res & MLX5_CROSS_VHCA_ALLOWED_OBJS_TIR) && 1164 (res & MLX5_CROSS_VHCA_ALLOWED_OBJS_FT) && 1165 (res & MLX5_CROSS_VHCA_ALLOWED_OBJS_RTC); 1166 1167 caps->flow_table_hash_type = MLX5_GET(query_hca_cap_out, out, 1168 capability.cmd_hca_cap_2.flow_table_hash_type); 1169 1170 caps->encap_entropy_hash_type = MLX5_GET(query_hca_cap_out, out, 1171 capability.cmd_hca_cap_2.encap_entropy_hash_type); 1172 1173 MLX5_SET(query_hca_cap_in, in, op_mod, 1174 MLX5_GET_HCA_CAP_OP_MOD_NIC_FLOW_TABLE | 1175 MLX5_HCA_CAP_OPMOD_GET_CUR); 1176 1177 ret = mlx5_glue->devx_general_cmd(ctx, in, sizeof(in), out, sizeof(out)); 1178 if (ret) { 1179 DR_LOG(ERR, "Failed to query flow table caps"); 1180 rte_errno = errno; 1181 return rte_errno; 1182 } 1183 1184 caps->nic_ft.max_level = MLX5_GET(query_hca_cap_out, out, 1185 capability.flow_table_nic_cap. 1186 flow_table_properties_nic_receive.max_ft_level); 1187 1188 caps->nic_ft.reparse = MLX5_GET(query_hca_cap_out, out, 1189 capability.flow_table_nic_cap. 1190 flow_table_properties_nic_receive.reparse); 1191 1192 caps->nic_ft.ignore_flow_level_rtc_valid = 1193 MLX5_GET(query_hca_cap_out, 1194 out, 1195 capability.flow_table_nic_cap. 1196 flow_table_properties_nic_receive.ignore_flow_level_rtc_valid); 1197 1198 /* check cross-VHCA support in flow table properties */ 1199 res = 1200 MLX5_GET(query_hca_cap_out, out, 1201 capability.flow_table_nic_cap.flow_table_properties_nic_receive.cross_vhca_object); 1202 caps->cross_vhca_resources &= res; 1203 1204 if (caps->wqe_based_update) { 1205 MLX5_SET(query_hca_cap_in, in, op_mod, 1206 MLX5_GET_HCA_CAP_OP_MOD_WQE_BASED_FLOW_TABLE | 1207 MLX5_HCA_CAP_OPMOD_GET_CUR); 1208 1209 ret = mlx5_glue->devx_general_cmd(ctx, in, sizeof(in), out, sizeof(out)); 1210 if (ret) { 1211 DR_LOG(ERR, "Failed to query WQE based FT caps"); 1212 rte_errno = errno; 1213 return rte_errno; 1214 } 1215 1216 caps->rtc_reparse_mode = MLX5_GET(query_hca_cap_out, out, 1217 capability.wqe_based_flow_table_cap. 1218 rtc_reparse_mode); 1219 1220 caps->ste_format = MLX5_GET(query_hca_cap_out, out, 1221 capability.wqe_based_flow_table_cap. 1222 ste_format); 1223 1224 caps->rtc_index_mode = MLX5_GET(query_hca_cap_out, out, 1225 capability.wqe_based_flow_table_cap. 1226 rtc_index_mode); 1227 1228 caps->rtc_log_depth_max = MLX5_GET(query_hca_cap_out, out, 1229 capability.wqe_based_flow_table_cap. 1230 rtc_log_depth_max); 1231 1232 caps->ste_alloc_log_max = MLX5_GET(query_hca_cap_out, out, 1233 capability.wqe_based_flow_table_cap. 1234 ste_alloc_log_max); 1235 1236 caps->ste_alloc_log_gran = MLX5_GET(query_hca_cap_out, out, 1237 capability.wqe_based_flow_table_cap. 1238 ste_alloc_log_granularity); 1239 1240 caps->trivial_match_definer = MLX5_GET(query_hca_cap_out, out, 1241 capability.wqe_based_flow_table_cap. 1242 trivial_match_definer); 1243 1244 caps->stc_alloc_log_max = MLX5_GET(query_hca_cap_out, out, 1245 capability.wqe_based_flow_table_cap. 1246 stc_alloc_log_max); 1247 1248 caps->stc_alloc_log_gran = MLX5_GET(query_hca_cap_out, out, 1249 capability.wqe_based_flow_table_cap. 1250 stc_alloc_log_granularity); 1251 1252 caps->rtc_hash_split_table = MLX5_GET(query_hca_cap_out, out, 1253 capability.wqe_based_flow_table_cap. 1254 rtc_hash_split_table); 1255 1256 caps->rtc_linear_lookup_table = MLX5_GET(query_hca_cap_out, out, 1257 capability.wqe_based_flow_table_cap. 1258 rtc_linear_lookup_table); 1259 1260 caps->access_index_mode = MLX5_GET(query_hca_cap_out, out, 1261 capability.wqe_based_flow_table_cap. 1262 access_index_mode); 1263 1264 caps->linear_match_definer = MLX5_GET(query_hca_cap_out, out, 1265 capability.wqe_based_flow_table_cap. 1266 linear_match_definer_reg_c3); 1267 1268 caps->rtc_max_hash_def_gen_wqe = MLX5_GET(query_hca_cap_out, out, 1269 capability.wqe_based_flow_table_cap. 1270 rtc_max_num_hash_definer_gen_wqe); 1271 1272 caps->supp_ste_format_gen_wqe = MLX5_GET(query_hca_cap_out, out, 1273 capability.wqe_based_flow_table_cap. 1274 ste_format_gen_wqe); 1275 1276 caps->fdb_tir_stc = MLX5_GET(query_hca_cap_out, out, 1277 capability.wqe_based_flow_table_cap. 1278 fdb_jump_to_tir_stc); 1279 } 1280 1281 if (caps->eswitch_manager) { 1282 MLX5_SET(query_hca_cap_in, in, op_mod, 1283 MLX5_GET_HCA_CAP_OP_MOD_ESW_FLOW_TABLE | 1284 MLX5_HCA_CAP_OPMOD_GET_CUR); 1285 1286 ret = mlx5_glue->devx_general_cmd(ctx, in, sizeof(in), out, sizeof(out)); 1287 if (ret) { 1288 DR_LOG(ERR, "Failed to query flow table esw caps"); 1289 rte_errno = errno; 1290 return rte_errno; 1291 } 1292 1293 caps->fdb_ft.max_level = MLX5_GET(query_hca_cap_out, out, 1294 capability.flow_table_nic_cap. 1295 flow_table_properties_nic_receive.max_ft_level); 1296 1297 caps->fdb_ft.reparse = MLX5_GET(query_hca_cap_out, out, 1298 capability.flow_table_nic_cap. 1299 flow_table_properties_nic_receive.reparse); 1300 1301 MLX5_SET(query_hca_cap_in, in, op_mod, 1302 MLX5_SET_HCA_CAP_OP_MOD_ESW | MLX5_HCA_CAP_OPMOD_GET_CUR); 1303 1304 ret = mlx5_glue->devx_general_cmd(ctx, in, sizeof(in), out, sizeof(out)); 1305 if (ret) { 1306 DR_LOG(ERR, "Query eswitch capabilities failed %d", ret); 1307 rte_errno = errno; 1308 return rte_errno; 1309 } 1310 1311 if (MLX5_GET(query_hca_cap_out, out, 1312 capability.esw_cap.esw_manager_vport_number_valid)) 1313 caps->eswitch_manager_vport_number = 1314 MLX5_GET(query_hca_cap_out, out, 1315 capability.esw_cap.esw_manager_vport_number); 1316 1317 caps->merged_eswitch = MLX5_GET(query_hca_cap_out, out, 1318 capability.esw_cap.merged_eswitch); 1319 } 1320 1321 if (caps->roce) { 1322 MLX5_SET(query_hca_cap_in, in, op_mod, 1323 MLX5_GET_HCA_CAP_OP_MOD_ROCE | 1324 MLX5_HCA_CAP_OPMOD_GET_CUR); 1325 1326 ret = mlx5_glue->devx_general_cmd(ctx, in, sizeof(in), out, sizeof(out)); 1327 if (ret) { 1328 DR_LOG(ERR, "Failed to query roce caps"); 1329 rte_errno = errno; 1330 return rte_errno; 1331 } 1332 1333 caps->roce_max_src_udp_port = MLX5_GET(query_hca_cap_out, out, 1334 capability.roce_caps.r_roce_max_src_udp_port); 1335 caps->roce_min_src_udp_port = MLX5_GET(query_hca_cap_out, out, 1336 capability.roce_caps.r_roce_min_src_udp_port); 1337 } 1338 1339 ret = mlx5_glue->query_device_ex(ctx, NULL, &attr_ex); 1340 if (ret) { 1341 DR_LOG(ERR, "Failed to query device attributes"); 1342 rte_errno = ret; 1343 return rte_errno; 1344 } 1345 1346 strlcpy(caps->fw_ver, attr_ex.orig_attr.fw_ver, sizeof(caps->fw_ver)); 1347 1348 port_info = flow_hw_get_wire_port(ctx); 1349 if (port_info) 1350 caps->wire_regc_mask = port_info->regc_mask; 1351 else 1352 DR_LOG(INFO, "Failed to query wire port regc value"); 1353 1354 return ret; 1355 } 1356 1357 int mlx5dr_cmd_query_ib_port(struct ibv_context *ctx, 1358 struct mlx5dr_cmd_query_vport_caps *vport_caps, 1359 uint32_t port_num) 1360 { 1361 struct mlx5_port_info port_info = {0}; 1362 uint32_t flags; 1363 int ret; 1364 1365 flags = MLX5_PORT_QUERY_VPORT | MLX5_PORT_QUERY_ESW_OWNER_VHCA_ID; 1366 1367 ret = mlx5_glue->devx_port_query(ctx, port_num, &port_info); 1368 /* Check if query succeed and vport is enabled */ 1369 if (ret || (port_info.query_flags & flags) != flags) { 1370 rte_errno = ENOTSUP; 1371 return rte_errno; 1372 } 1373 1374 vport_caps->vport_num = port_info.vport_id; 1375 vport_caps->esw_owner_vhca_id = port_info.esw_owner_vhca_id; 1376 1377 return 0; 1378 } 1379