File Index
Files and directories
Sign in
FILE

cmd.c

File preview with syntax highlighting.

linux-6.19.14/drivers/net/ethernet/mellanox/mlx5/core/steering/hws/cmd.c C
   1// SPDX-License-Identifier: GPL-2.0 OR Linux-OpenIB
   2/* Copyright (c) 2024 NVIDIA Corporation & Affiliates */
   3
   4#include "internal.h"
   5
   6static enum mlx5_ifc_flow_destination_type
   7hws_cmd_dest_type_to_ifc_dest_type(enum mlx5_flow_destination_type type)
   8{
   9	switch (type) {
  10	case MLX5_FLOW_DESTINATION_TYPE_VPORT:
  11		return MLX5_IFC_FLOW_DESTINATION_TYPE_VPORT;
  12	case MLX5_FLOW_DESTINATION_TYPE_FLOW_TABLE:
  13		return MLX5_IFC_FLOW_DESTINATION_TYPE_FLOW_TABLE;
  14	case MLX5_FLOW_DESTINATION_TYPE_TIR:
  15		return MLX5_IFC_FLOW_DESTINATION_TYPE_TIR;
  16	case MLX5_FLOW_DESTINATION_TYPE_FLOW_SAMPLER:
  17		return MLX5_IFC_FLOW_DESTINATION_TYPE_FLOW_SAMPLER;
  18	case MLX5_FLOW_DESTINATION_TYPE_UPLINK:
  19		return MLX5_IFC_FLOW_DESTINATION_TYPE_UPLINK;
  20	case MLX5_FLOW_DESTINATION_TYPE_TABLE_TYPE:
  21		return MLX5_IFC_FLOW_DESTINATION_TYPE_TABLE_TYPE;
  22	case MLX5_FLOW_DESTINATION_TYPE_NONE:
  23	case MLX5_FLOW_DESTINATION_TYPE_PORT:
  24	case MLX5_FLOW_DESTINATION_TYPE_COUNTER:
  25	case MLX5_FLOW_DESTINATION_TYPE_FLOW_TABLE_NUM:
  26	case MLX5_FLOW_DESTINATION_TYPE_RANGE:
  27	default:
  28		pr_warn("HWS: unknown flow dest type %d\n", type);
  29		return 0;
  30	}
  31};
  32
  33static int hws_cmd_general_obj_destroy(struct mlx5_core_dev *mdev,
  34				       u32 object_type,
  35				       u32 object_id)
  36{
  37	u32 in[MLX5_ST_SZ_DW(general_obj_in_cmd_hdr)] = {};
  38	u32 out[MLX5_ST_SZ_DW(general_obj_out_cmd_hdr)];
  39
  40	MLX5_SET(general_obj_in_cmd_hdr, in, opcode, MLX5_CMD_OP_DESTROY_GENERAL_OBJECT);
  41	MLX5_SET(general_obj_in_cmd_hdr, in, obj_type, object_type);
  42	MLX5_SET(general_obj_in_cmd_hdr, in, obj_id, object_id);
  43
  44	return mlx5_cmd_exec(mdev, in, sizeof(in), out, sizeof(out));
  45}
  46
  47int mlx5hws_cmd_flow_table_create(struct mlx5_core_dev *mdev,
  48				  struct mlx5hws_cmd_ft_create_attr *ft_attr,
  49				  u32 *table_id)
  50{
  51	u32 out[MLX5_ST_SZ_DW(create_flow_table_out)] = {0};
  52	u32 in[MLX5_ST_SZ_DW(create_flow_table_in)] = {0};
  53	void *ft_ctx;
  54	int ret;
  55
  56	MLX5_SET(create_flow_table_in, in, opcode, MLX5_CMD_OP_CREATE_FLOW_TABLE);
  57	MLX5_SET(create_flow_table_in, in, table_type, ft_attr->type);
  58	MLX5_SET(create_flow_table_in, in, uid, ft_attr->uid);
  59
  60	ft_ctx = MLX5_ADDR_OF(create_flow_table_in, in, flow_table_context);
  61	MLX5_SET(flow_table_context, ft_ctx, level, ft_attr->level);
  62	MLX5_SET(flow_table_context, ft_ctx, rtc_valid, ft_attr->rtc_valid);
  63	MLX5_SET(flow_table_context, ft_ctx, reformat_en, ft_attr->reformat_en);
  64	MLX5_SET(flow_table_context, ft_ctx, decap_en, ft_attr->decap_en);
  65
  66	ret = mlx5_cmd_exec_inout(mdev, create_flow_table, in, out);
  67	if (ret)
  68		return ret;
  69
  70	*table_id = MLX5_GET(create_flow_table_out, out, table_id);
  71
  72	return 0;
  73}
  74
  75int mlx5hws_cmd_flow_table_modify(struct mlx5_core_dev *mdev,
  76				  struct mlx5hws_cmd_ft_modify_attr *ft_attr,
  77				  u32 table_id)
  78{
  79	u32 in[MLX5_ST_SZ_DW(modify_flow_table_in)] = {0};
  80	void *ft_ctx;
  81
  82	MLX5_SET(modify_flow_table_in, in, opcode, MLX5_CMD_OP_MODIFY_FLOW_TABLE);
  83	MLX5_SET(modify_flow_table_in, in, table_type, ft_attr->type);
  84	MLX5_SET(modify_flow_table_in, in, modify_field_select, ft_attr->modify_fs);
  85	MLX5_SET(modify_flow_table_in, in, table_id, table_id);
  86
  87	ft_ctx = MLX5_ADDR_OF(modify_flow_table_in, in, flow_table_context);
  88
  89	MLX5_SET(flow_table_context, ft_ctx, table_miss_action, ft_attr->table_miss_action);
  90	MLX5_SET(flow_table_context, ft_ctx, table_miss_id, ft_attr->table_miss_id);
  91	MLX5_SET(flow_table_context, ft_ctx, hws.rtc_id_0, ft_attr->rtc_id_0);
  92	MLX5_SET(flow_table_context, ft_ctx, hws.rtc_id_1, ft_attr->rtc_id_1);
  93
  94	return mlx5_cmd_exec_in(mdev, modify_flow_table, in);
  95}
  96
  97int mlx5hws_cmd_flow_table_query(struct mlx5_core_dev *mdev,
  98				 u32 table_id,
  99				 struct mlx5hws_cmd_ft_query_attr *ft_attr,
 100				 u64 *icm_addr_0, u64 *icm_addr_1)
 101{
 102	u32 out[MLX5_ST_SZ_DW(query_flow_table_out)] = {0};
 103	u32 in[MLX5_ST_SZ_DW(query_flow_table_in)] = {0};
 104	void *ft_ctx;
 105	int ret;
 106
 107	MLX5_SET(query_flow_table_in, in, opcode, MLX5_CMD_OP_QUERY_FLOW_TABLE);
 108	MLX5_SET(query_flow_table_in, in, table_type, ft_attr->type);
 109	MLX5_SET(query_flow_table_in, in, table_id, table_id);
 110
 111	ret = mlx5_cmd_exec_inout(mdev, query_flow_table, in, out);
 112	if (ret)
 113		return ret;
 114
 115	ft_ctx = MLX5_ADDR_OF(query_flow_table_out, out, flow_table_context);
 116	*icm_addr_0 = MLX5_GET64(flow_table_context, ft_ctx, sws.sw_owner_icm_root_0);
 117	*icm_addr_1 = MLX5_GET64(flow_table_context, ft_ctx, sws.sw_owner_icm_root_1);
 118
 119	return ret;
 120}
 121
 122int mlx5hws_cmd_flow_table_destroy(struct mlx5_core_dev *mdev,
 123				   u8 fw_ft_type, u32 table_id)
 124{
 125	u32 in[MLX5_ST_SZ_DW(destroy_flow_table_in)] = {0};
 126
 127	MLX5_SET(destroy_flow_table_in, in, opcode, MLX5_CMD_OP_DESTROY_FLOW_TABLE);
 128	MLX5_SET(destroy_flow_table_in, in, table_type, fw_ft_type);
 129	MLX5_SET(destroy_flow_table_in, in, table_id, table_id);
 130
 131	return mlx5_cmd_exec_in(mdev, destroy_flow_table, in);
 132}
 133
 134static int hws_cmd_flow_group_create(struct mlx5_core_dev *mdev,
 135				     struct mlx5hws_cmd_fg_attr *fg_attr,
 136				     u32 *group_id)
 137{
 138	u32 out[MLX5_ST_SZ_DW(create_flow_group_out)] = {0};
 139	int inlen = MLX5_ST_SZ_BYTES(create_flow_group_in);
 140	u32 *in;
 141	int ret;
 142
 143	in = kvzalloc(inlen, GFP_KERNEL);
 144	if (!in)
 145		return -ENOMEM;
 146
 147	MLX5_SET(create_flow_group_in, in, opcode, MLX5_CMD_OP_CREATE_FLOW_GROUP);
 148	MLX5_SET(create_flow_group_in, in, table_type, fg_attr->table_type);
 149	MLX5_SET(create_flow_group_in, in, table_id, fg_attr->table_id);
 150
 151	ret = mlx5_cmd_exec_inout(mdev, create_flow_group, in, out);
 152	if (ret)
 153		goto out;
 154
 155	*group_id = MLX5_GET(create_flow_group_out, out, group_id);
 156
 157out:
 158	kvfree(in);
 159	return ret;
 160}
 161
 162static int hws_cmd_flow_group_destroy(struct mlx5_core_dev *mdev,
 163				      u32 ft_id, u32 fg_id, u8 ft_type)
 164{
 165	u32 in[MLX5_ST_SZ_DW(destroy_flow_group_in)] = {};
 166
 167	MLX5_SET(destroy_flow_group_in, in, opcode, MLX5_CMD_OP_DESTROY_FLOW_GROUP);
 168	MLX5_SET(destroy_flow_group_in, in, table_type, ft_type);
 169	MLX5_SET(destroy_flow_group_in, in, table_id, ft_id);
 170	MLX5_SET(destroy_flow_group_in, in, group_id, fg_id);
 171
 172	return mlx5_cmd_exec_in(mdev, destroy_flow_group, in);
 173}
 174
 175int mlx5hws_cmd_set_fte(struct mlx5_core_dev *mdev,
 176			u32 table_type,
 177			u32 table_id,
 178			u32 group_id,
 179			struct mlx5hws_cmd_set_fte_attr *fte_attr)
 180{
 181	u32 out[MLX5_ST_SZ_DW(set_fte_out)] = {0};
 182	void *in_flow_context;
 183	u32 dest_entry_sz;
 184	u32 total_dest_sz;
 185	u32 action_flags;
 186	u8 *in_dests;
 187	u32 inlen;
 188	u32 *in;
 189	int ret;
 190	u32 i;
 191
 192	dest_entry_sz = fte_attr->extended_dest ?
 193			MLX5_ST_SZ_BYTES(extended_dest_format) :
 194			MLX5_ST_SZ_BYTES(dest_format);
 195	total_dest_sz = dest_entry_sz * fte_attr->dests_num;
 196	inlen = align((MLX5_ST_SZ_BYTES(set_fte_in) + total_dest_sz), DW_SIZE);
 197	in = kzalloc(inlen, GFP_KERNEL);
 198	if (!in)
 199		return -ENOMEM;
 200
 201	MLX5_SET(set_fte_in, in, opcode, MLX5_CMD_OP_SET_FLOW_TABLE_ENTRY);
 202	MLX5_SET(set_fte_in, in, table_type, table_type);
 203	MLX5_SET(set_fte_in, in, table_id, table_id);
 204
 205	in_flow_context = MLX5_ADDR_OF(set_fte_in, in, flow_context);
 206	MLX5_SET(flow_context, in_flow_context, group_id, group_id);
 207	MLX5_SET(flow_context, in_flow_context, flow_source, fte_attr->flow_source);
 208	MLX5_SET(flow_context, in_flow_context, extended_destination, fte_attr->extended_dest);
 209	MLX5_SET(set_fte_in, in, ignore_flow_level, fte_attr->ignore_flow_level);
 210
 211	action_flags = fte_attr->action_flags;
 212	MLX5_SET(flow_context, in_flow_context, action, action_flags);
 213
 214	if (action_flags & MLX5_FLOW_CONTEXT_ACTION_PACKET_REFORMAT) {
 215		MLX5_SET(flow_context, in_flow_context,
 216			 packet_reformat_id, fte_attr->packet_reformat_id);
 217	}
 218
 219	if (action_flags & (MLX5_FLOW_CONTEXT_ACTION_DECRYPT | MLX5_FLOW_CONTEXT_ACTION_ENCRYPT)) {
 220		MLX5_SET(flow_context, in_flow_context,
 221			 encrypt_decrypt_type, fte_attr->encrypt_decrypt_type);
 222		MLX5_SET(flow_context, in_flow_context,
 223			 encrypt_decrypt_obj_id, fte_attr->encrypt_decrypt_obj_id);
 224	}
 225
 226	if (action_flags & MLX5_FLOW_CONTEXT_ACTION_FWD_DEST) {
 227		in_dests = (u8 *)MLX5_ADDR_OF(flow_context, in_flow_context, destination);
 228
 229		for (i = 0; i < fte_attr->dests_num; i++) {
 230			struct mlx5hws_cmd_set_fte_dest *dest = &fte_attr->dests[i];
 231			enum mlx5_ifc_flow_destination_type ifc_dest_type =
 232				hws_cmd_dest_type_to_ifc_dest_type(dest->destination_type);
 233
 234			switch (dest->destination_type) {
 235			case MLX5_FLOW_DESTINATION_TYPE_VPORT:
 236				if (dest->ext_flags & MLX5HWS_CMD_EXT_DEST_ESW_OWNER_VHCA_ID) {
 237					MLX5_SET(dest_format, in_dests,
 238						 destination_eswitch_owner_vhca_id_valid, 1);
 239					MLX5_SET(dest_format, in_dests,
 240						 destination_eswitch_owner_vhca_id,
 241						 dest->esw_owner_vhca_id);
 242				}
 243				fallthrough;
 244			case MLX5_FLOW_DESTINATION_TYPE_TIR:
 245			case MLX5_FLOW_DESTINATION_TYPE_FLOW_TABLE:
 246				MLX5_SET(dest_format, in_dests, destination_type, ifc_dest_type);
 247				MLX5_SET(dest_format, in_dests, destination_id,
 248					 dest->destination_id);
 249				if (dest->ext_flags & MLX5HWS_CMD_EXT_DEST_REFORMAT) {
 250					MLX5_SET(dest_format, in_dests, packet_reformat, 1);
 251					MLX5_SET(extended_dest_format, in_dests, packet_reformat_id,
 252						 dest->ext_reformat_id);
 253				}
 254				break;
 255			case MLX5_FLOW_DESTINATION_TYPE_FLOW_SAMPLER:
 256				MLX5_SET(dest_format, in_dests,
 257					 destination_type, ifc_dest_type);
 258				MLX5_SET(dest_format, in_dests, destination_id,
 259					 dest->destination_id);
 260				break;
 261			default:
 262				ret = -EOPNOTSUPP;
 263				goto out;
 264			}
 265
 266			in_dests = in_dests + dest_entry_sz;
 267		}
 268		MLX5_SET(flow_context, in_flow_context, destination_list_size, fte_attr->dests_num);
 269	}
 270
 271	ret = mlx5_cmd_exec(mdev, in, inlen, out, sizeof(out));
 272	if (ret)
 273		mlx5_core_err(mdev, "Failed creating FLOW_TABLE_ENTRY\n");
 274
 275out:
 276	kfree(in);
 277	return ret;
 278}
 279
 280int mlx5hws_cmd_delete_fte(struct mlx5_core_dev *mdev,
 281			   u32 table_type,
 282			   u32 table_id)
 283{
 284	u32 in[MLX5_ST_SZ_DW(delete_fte_in)] = {};
 285
 286	MLX5_SET(delete_fte_in, in, opcode, MLX5_CMD_OP_DELETE_FLOW_TABLE_ENTRY);
 287	MLX5_SET(delete_fte_in, in, table_type, table_type);
 288	MLX5_SET(delete_fte_in, in, table_id, table_id);
 289
 290	return mlx5_cmd_exec_in(mdev, delete_fte, in);
 291}
 292
 293struct mlx5hws_cmd_forward_tbl *
 294mlx5hws_cmd_forward_tbl_create(struct mlx5_core_dev *mdev,
 295			       struct mlx5hws_cmd_ft_create_attr *ft_attr,
 296			       struct mlx5hws_cmd_set_fte_attr *fte_attr)
 297{
 298	struct mlx5hws_cmd_fg_attr fg_attr = {0};
 299	struct mlx5hws_cmd_forward_tbl *tbl;
 300	int ret;
 301
 302	tbl = kzalloc(sizeof(*tbl), GFP_KERNEL);
 303	if (!tbl)
 304		return NULL;
 305
 306	ret = mlx5hws_cmd_flow_table_create(mdev, ft_attr, &tbl->ft_id);
 307	if (ret) {
 308		mlx5_core_err(mdev, "Failed to create FT\n");
 309		goto free_tbl;
 310	}
 311
 312	fg_attr.table_id = tbl->ft_id;
 313	fg_attr.table_type = ft_attr->type;
 314
 315	ret = hws_cmd_flow_group_create(mdev, &fg_attr, &tbl->fg_id);
 316	if (ret) {
 317		mlx5_core_err(mdev, "Failed to create FG\n");
 318		goto free_ft;
 319	}
 320
 321	ret = mlx5hws_cmd_set_fte(mdev, ft_attr->type,
 322				  tbl->ft_id, tbl->fg_id, fte_attr);
 323	if (ret) {
 324		mlx5_core_err(mdev, "Failed to create FTE\n");
 325		goto free_fg;
 326	}
 327
 328	tbl->type = ft_attr->type;
 329	return tbl;
 330
 331free_fg:
 332	hws_cmd_flow_group_destroy(mdev, tbl->ft_id, tbl->fg_id, ft_attr->type);
 333free_ft:
 334	mlx5hws_cmd_flow_table_destroy(mdev, ft_attr->type, tbl->ft_id);
 335free_tbl:
 336	kfree(tbl);
 337	return NULL;
 338}
 339
 340void mlx5hws_cmd_forward_tbl_destroy(struct mlx5_core_dev *mdev,
 341				     struct mlx5hws_cmd_forward_tbl *tbl)
 342{
 343	mlx5hws_cmd_delete_fte(mdev, tbl->type, tbl->ft_id);
 344	hws_cmd_flow_group_destroy(mdev, tbl->ft_id, tbl->fg_id, tbl->type);
 345	mlx5hws_cmd_flow_table_destroy(mdev, tbl->type, tbl->ft_id);
 346	kfree(tbl);
 347}
 348
 349void mlx5hws_cmd_set_attr_connect_miss_tbl(struct mlx5hws_context *ctx,
 350					   u32 fw_ft_type,
 351					   enum mlx5hws_table_type type,
 352					   struct mlx5hws_cmd_ft_modify_attr *ft_attr)
 353{
 354	u32 default_miss_tbl;
 355
 356	if (type != MLX5HWS_TABLE_TYPE_FDB)
 357		return;
 358
 359	ft_attr->modify_fs = MLX5_IFC_MODIFY_FLOW_TABLE_MISS_ACTION;
 360	ft_attr->type = fw_ft_type;
 361	ft_attr->table_miss_action = MLX5_IFC_MODIFY_FLOW_TABLE_MISS_ACTION_GOTO_TBL;
 362
 363	default_miss_tbl = ctx->common_res.default_miss->ft_id;
 364	if (!default_miss_tbl) {
 365		pr_warn("HWS: no flow table ID for default miss\n");
 366		return;
 367	}
 368
 369	ft_attr->table_miss_id = default_miss_tbl;
 370}
 371
 372int mlx5hws_cmd_rtc_create(struct mlx5_core_dev *mdev,
 373			   struct mlx5hws_cmd_rtc_create_attr *rtc_attr,
 374			   u32 *rtc_id)
 375{
 376	u32 out[MLX5_ST_SZ_DW(general_obj_out_cmd_hdr)] = {0};
 377	u32 in[MLX5_ST_SZ_DW(create_rtc_in)] = {0};
 378	void *attr;
 379	int ret;
 380
 381	attr = MLX5_ADDR_OF(create_rtc_in, in, hdr);
 382	MLX5_SET(general_obj_in_cmd_hdr,
 383		 attr, opcode, MLX5_CMD_OP_CREATE_GENERAL_OBJECT);
 384	MLX5_SET(general_obj_in_cmd_hdr,
 385		 attr, obj_type, MLX5_OBJ_TYPE_RTC);
 386
 387	attr = MLX5_ADDR_OF(create_rtc_in, in, rtc);
 388	MLX5_SET(rtc, attr, ste_format_0, rtc_attr->is_frst_jumbo ?
 389		 MLX5_IFC_RTC_STE_FORMAT_11DW :
 390		 MLX5_IFC_RTC_STE_FORMAT_8DW);
 391
 392	if (rtc_attr->is_scnd_range) {
 393		MLX5_SET(rtc, attr, ste_format_1, MLX5_IFC_RTC_STE_FORMAT_RANGE);
 394		MLX5_SET(rtc, attr, num_match_ste, 2);
 395	}
 396
 397	MLX5_SET(rtc, attr, pd, rtc_attr->pd);
 398	MLX5_SET(rtc, attr, update_method, rtc_attr->fw_gen_wqe);
 399	MLX5_SET(rtc, attr, update_index_mode, rtc_attr->update_index_mode);
 400	MLX5_SET(rtc, attr, access_index_mode, rtc_attr->access_index_mode);
 401	MLX5_SET(rtc, attr, num_hash_definer, rtc_attr->num_hash_definer);
 402	MLX5_SET(rtc, attr, log_depth, rtc_attr->log_depth);
 403	MLX5_SET(rtc, attr, log_hash_size, rtc_attr->log_size);
 404	MLX5_SET(rtc, attr, table_type, rtc_attr->table_type);
 405	MLX5_SET(rtc, attr, num_hash_definer, rtc_attr->num_hash_definer);
 406	MLX5_SET(rtc, attr, match_definer_0, rtc_attr->match_definer_0);
 407	MLX5_SET(rtc, attr, match_definer_1, rtc_attr->match_definer_1);
 408	MLX5_SET(rtc, attr, stc_id, rtc_attr->stc_base);
 409	MLX5_SET(rtc, attr, ste_table_base_id, rtc_attr->ste_base);
 410	MLX5_SET(rtc, attr, miss_flow_table_id, rtc_attr->miss_ft_id);
 411	MLX5_SET(rtc, attr, reparse_mode, rtc_attr->reparse_mode);
 412
 413	ret = mlx5_cmd_exec(mdev, in, sizeof(in), out, sizeof(out));
 414	if (ret) {
 415		mlx5_core_err(mdev, "Failed to create RTC\n");
 416		goto out;
 417	}
 418
 419	*rtc_id = MLX5_GET(general_obj_out_cmd_hdr, out, obj_id);
 420out:
 421	return ret;
 422}
 423
 424void mlx5hws_cmd_rtc_destroy(struct mlx5_core_dev *mdev, u32 rtc_id)
 425{
 426	hws_cmd_general_obj_destroy(mdev, MLX5_OBJ_TYPE_RTC, rtc_id);
 427}
 428
 429int mlx5hws_cmd_stc_create(struct mlx5_core_dev *mdev,
 430			   struct mlx5hws_cmd_stc_create_attr *stc_attr,
 431			   u32 *stc_id)
 432{
 433	u32 out[MLX5_ST_SZ_DW(general_obj_out_cmd_hdr)] = {0};
 434	u32 in[MLX5_ST_SZ_DW(create_stc_in)] = {0};
 435	void *attr;
 436	int ret;
 437
 438	attr = MLX5_ADDR_OF(create_stc_in, in, hdr);
 439	MLX5_SET(general_obj_in_cmd_hdr,
 440		 attr, opcode, MLX5_CMD_OP_CREATE_GENERAL_OBJECT);
 441	MLX5_SET(general_obj_in_cmd_hdr,
 442		 attr, obj_type, MLX5_OBJ_TYPE_STC);
 443	MLX5_SET(general_obj_in_cmd_hdr,
 444		 attr, op_param.create.log_obj_range, stc_attr->log_obj_range);
 445
 446	attr = MLX5_ADDR_OF(create_stc_in, in, stc);
 447	MLX5_SET(stc, attr, table_type, stc_attr->table_type);
 448
 449	ret = mlx5_cmd_exec(mdev, in, sizeof(in), out, sizeof(out));
 450	if (ret) {
 451		mlx5_core_err(mdev, "Failed to create STC\n");
 452		goto out;
 453	}
 454
 455	*stc_id = MLX5_GET(general_obj_out_cmd_hdr, out, obj_id);
 456out:
 457	return ret;
 458}
 459
 460void mlx5hws_cmd_stc_destroy(struct mlx5_core_dev *mdev, u32 stc_id)
 461{
 462	hws_cmd_general_obj_destroy(mdev, MLX5_OBJ_TYPE_STC, stc_id);
 463}
 464
 465static int
 466hws_cmd_stc_modify_set_stc_param(struct mlx5_core_dev *mdev,
 467				 struct mlx5hws_cmd_stc_modify_attr *stc_attr,
 468				 void *stc_param)
 469{
 470	switch (stc_attr->action_type) {
 471	case MLX5_IFC_STC_ACTION_TYPE_COUNTER:
 472		MLX5_SET(stc_ste_param_flow_counter, stc_param, flow_counter_id, stc_attr->id);
 473		break;
 474	case MLX5_IFC_STC_ACTION_TYPE_JUMP_TO_TIR:
 475		MLX5_SET(stc_ste_param_tir, stc_param, tirn, stc_attr->dest_tir_num);
 476		break;
 477	case MLX5_IFC_STC_ACTION_TYPE_JUMP_TO_FT:
 478		MLX5_SET(stc_ste_param_table, stc_param, table_id, stc_attr->dest_table_id);
 479		break;
 480	case MLX5_IFC_STC_ACTION_TYPE_ACC_MODIFY_LIST:
 481		MLX5_SET(stc_ste_param_header_modify_list, stc_param,
 482			 header_modify_pattern_id, stc_attr->modify_header.pattern_id);
 483		MLX5_SET(stc_ste_param_header_modify_list, stc_param,
 484			 header_modify_argument_id, stc_attr->modify_header.arg_id);
 485		break;
 486	case MLX5_IFC_STC_ACTION_TYPE_HEADER_REMOVE:
 487		MLX5_SET(stc_ste_param_remove, stc_param, action_type,
 488			 MLX5_MODIFICATION_TYPE_REMOVE);
 489		MLX5_SET(stc_ste_param_remove, stc_param, decap,
 490			 stc_attr->remove_header.decap);
 491		MLX5_SET(stc_ste_param_remove, stc_param, remove_start_anchor,
 492			 stc_attr->remove_header.start_anchor);
 493		MLX5_SET(stc_ste_param_remove, stc_param, remove_end_anchor,
 494			 stc_attr->remove_header.end_anchor);
 495		break;
 496	case MLX5_IFC_STC_ACTION_TYPE_HEADER_INSERT:
 497		MLX5_SET(stc_ste_param_insert, stc_param, action_type,
 498			 MLX5_MODIFICATION_TYPE_INSERT);
 499		MLX5_SET(stc_ste_param_insert, stc_param, encap,
 500			 stc_attr->insert_header.encap);
 501		MLX5_SET(stc_ste_param_insert, stc_param, inline_data,
 502			 stc_attr->insert_header.is_inline);
 503		MLX5_SET(stc_ste_param_insert, stc_param, insert_anchor,
 504			 stc_attr->insert_header.insert_anchor);
 505		/* HW gets the next 2 sizes in words */
 506		MLX5_SET(stc_ste_param_insert, stc_param, insert_size,
 507			 stc_attr->insert_header.header_size / W_SIZE);
 508		MLX5_SET(stc_ste_param_insert, stc_param, insert_offset,
 509			 stc_attr->insert_header.insert_offset / W_SIZE);
 510		MLX5_SET(stc_ste_param_insert, stc_param, insert_argument,
 511			 stc_attr->insert_header.arg_id);
 512		break;
 513	case MLX5_IFC_STC_ACTION_TYPE_COPY:
 514	case MLX5_IFC_STC_ACTION_TYPE_SET:
 515	case MLX5_IFC_STC_ACTION_TYPE_ADD:
 516	case MLX5_IFC_STC_ACTION_TYPE_ADD_FIELD:
 517		*(__be64 *)stc_param = stc_attr->modify_action.data;
 518		break;
 519	case MLX5_IFC_STC_ACTION_TYPE_JUMP_TO_VPORT:
 520	case MLX5_IFC_STC_ACTION_TYPE_JUMP_TO_UPLINK:
 521		MLX5_SET(stc_ste_param_vport, stc_param, vport_number,
 522			 stc_attr->vport.vport_num);
 523		MLX5_SET(stc_ste_param_vport, stc_param, eswitch_owner_vhca_id,
 524			 stc_attr->vport.esw_owner_vhca_id);
 525		MLX5_SET(stc_ste_param_vport, stc_param, eswitch_owner_vhca_id_valid,
 526			 stc_attr->vport.eswitch_owner_vhca_id_valid);
 527		break;
 528	case MLX5_IFC_STC_ACTION_TYPE_DROP:
 529	case MLX5_IFC_STC_ACTION_TYPE_NOP:
 530	case MLX5_IFC_STC_ACTION_TYPE_TAG:
 531	case MLX5_IFC_STC_ACTION_TYPE_ALLOW:
 532		break;
 533	case MLX5_IFC_STC_ACTION_TYPE_ASO:
 534		MLX5_SET(stc_ste_param_execute_aso, stc_param, aso_object_id,
 535			 stc_attr->aso.devx_obj_id);
 536		MLX5_SET(stc_ste_param_execute_aso, stc_param, return_reg_id,
 537			 stc_attr->aso.return_reg_id);
 538		MLX5_SET(stc_ste_param_execute_aso, stc_param, aso_type,
 539			 stc_attr->aso.aso_type);
 540		break;
 541	case MLX5_IFC_STC_ACTION_TYPE_JUMP_TO_STE_TABLE:
 542		MLX5_SET(stc_ste_param_ste_table, stc_param, ste_obj_id,
 543			 stc_attr->ste_table.ste_obj_id);
 544		MLX5_SET(stc_ste_param_ste_table, stc_param, match_definer_id,
 545			 stc_attr->ste_table.match_definer_id);
 546		MLX5_SET(stc_ste_param_ste_table, stc_param, log_hash_size,
 547			 stc_attr->ste_table.log_hash_size);
 548		break;
 549	case MLX5_IFC_STC_ACTION_TYPE_REMOVE_WORDS:
 550		MLX5_SET(stc_ste_param_remove_words, stc_param, action_type,
 551			 MLX5_MODIFICATION_TYPE_REMOVE_WORDS);
 552		MLX5_SET(stc_ste_param_remove_words, stc_param, remove_start_anchor,
 553			 stc_attr->remove_words.start_anchor);
 554		MLX5_SET(stc_ste_param_remove_words, stc_param,
 555			 remove_size, stc_attr->remove_words.num_of_words);
 556		break;
 557	case MLX5_IFC_STC_ACTION_TYPE_CRYPTO_IPSEC_ENCRYPTION:
 558		MLX5_SET(stc_ste_param_ipsec_encrypt, stc_param, ipsec_object_id,
 559			 stc_attr->id);
 560		break;
 561	case MLX5_IFC_STC_ACTION_TYPE_CRYPTO_IPSEC_DECRYPTION:
 562		MLX5_SET(stc_ste_param_ipsec_decrypt, stc_param, ipsec_object_id,
 563			 stc_attr->id);
 564		break;
 565	case MLX5_IFC_STC_ACTION_TYPE_TRAILER:
 566		MLX5_SET(stc_ste_param_trailer, stc_param, command,
 567			 stc_attr->reformat_trailer.op);
 568		MLX5_SET(stc_ste_param_trailer, stc_param, type,
 569			 stc_attr->reformat_trailer.type);
 570		MLX5_SET(stc_ste_param_trailer, stc_param, length,
 571			 stc_attr->reformat_trailer.size);
 572		break;
 573	default:
 574		mlx5_core_err(mdev, "Not supported type %d\n", stc_attr->action_type);
 575		return -EINVAL;
 576	}
 577	return 0;
 578}
 579
 580int mlx5hws_cmd_stc_modify(struct mlx5_core_dev *mdev,
 581			   u32 stc_id,
 582			   struct mlx5hws_cmd_stc_modify_attr *stc_attr)
 583{
 584	u32 out[MLX5_ST_SZ_DW(general_obj_out_cmd_hdr)] = {0};
 585	u32 in[MLX5_ST_SZ_DW(create_stc_in)] = {0};
 586	void *stc_param;
 587	void *attr;
 588	int ret;
 589
 590	attr = MLX5_ADDR_OF(create_stc_in, in, hdr);
 591	MLX5_SET(general_obj_in_cmd_hdr,
 592		 attr, opcode, MLX5_CMD_OP_MODIFY_GENERAL_OBJECT);
 593	MLX5_SET(general_obj_in_cmd_hdr,
 594		 attr, obj_type, MLX5_OBJ_TYPE_STC);
 595	MLX5_SET(general_obj_in_cmd_hdr, in, obj_id, stc_id);
 596	MLX5_SET(general_obj_in_cmd_hdr, in,
 597		 op_param.query.obj_offset, stc_attr->stc_offset);
 598
 599	attr = MLX5_ADDR_OF(create_stc_in, in, stc);
 600	MLX5_SET(stc, attr, ste_action_offset, stc_attr->action_offset);
 601	MLX5_SET(stc, attr, action_type, stc_attr->action_type);
 602	MLX5_SET(stc, attr, reparse_mode, stc_attr->reparse_mode);
 603	MLX5_SET64(stc, attr, modify_field_select,
 604		   MLX5_IFC_MODIFY_STC_FIELD_SELECT_NEW_STC);
 605
 606	/* Set destination TIRN, TAG, FT ID, STE ID */
 607	stc_param = MLX5_ADDR_OF(stc, attr, stc_param);
 608	ret = hws_cmd_stc_modify_set_stc_param(mdev, stc_attr, stc_param);
 609	if (ret)
 610		return ret;
 611
 612	ret = mlx5_cmd_exec(mdev, in, sizeof(in), out, sizeof(out));
 613	if (ret)
 614		mlx5_core_err(mdev, "Failed to modify STC FW action_type %d\n",
 615			      stc_attr->action_type);
 616
 617	return ret;
 618}
 619
 620int mlx5hws_cmd_arg_create(struct mlx5_core_dev *mdev,
 621			   u16 log_obj_range,
 622			   u32 pd,
 623			   u32 *arg_id)
 624{
 625	u32 in[MLX5_ST_SZ_DW(create_modify_header_arg_in)] = {0};
 626	u32 out[MLX5_ST_SZ_DW(general_obj_out_cmd_hdr)] = {0};
 627	void *attr;
 628	int ret;
 629
 630	attr = MLX5_ADDR_OF(create_modify_header_arg_in, in, hdr);
 631	MLX5_SET(general_obj_in_cmd_hdr,
 632		 attr, opcode, MLX5_CMD_OP_CREATE_GENERAL_OBJECT);
 633	MLX5_SET(general_obj_in_cmd_hdr,
 634		 attr, obj_type, MLX5_OBJ_TYPE_HEADER_MODIFY_ARGUMENT);
 635	MLX5_SET(general_obj_in_cmd_hdr,
 636		 attr, op_param.create.log_obj_range, log_obj_range);
 637
 638	attr = MLX5_ADDR_OF(create_modify_header_arg_in, in, arg);
 639	MLX5_SET(modify_header_arg, attr, access_pd, pd);
 640
 641	ret = mlx5_cmd_exec(mdev, in, sizeof(in), out, sizeof(out));
 642	if (ret) {
 643		mlx5_core_err(mdev, "Failed to create ARG\n");
 644		goto out;
 645	}
 646
 647	*arg_id = MLX5_GET(general_obj_out_cmd_hdr, out, obj_id);
 648out:
 649	return ret;
 650}
 651
 652void mlx5hws_cmd_arg_destroy(struct mlx5_core_dev *mdev,
 653			     u32 arg_id)
 654{
 655	hws_cmd_general_obj_destroy(mdev, MLX5_OBJ_TYPE_HEADER_MODIFY_ARGUMENT, arg_id);
 656}
 657
 658int mlx5hws_cmd_header_modify_pattern_create(struct mlx5_core_dev *mdev,
 659					     u32 pattern_length,
 660					     u8 *actions,
 661					     u32 *ptrn_id)
 662{
 663	u32 in[MLX5_ST_SZ_DW(create_header_modify_pattern_in)] = {0};
 664	u32 out[MLX5_ST_SZ_DW(general_obj_out_cmd_hdr)] = {0};
 665	int num_of_actions;
 666	u64 *pattern_data;
 667	void *pattern;
 668	void *attr;
 669	int ret;
 670	int i;
 671
 672	if (pattern_length > MLX5_MAX_ACTIONS_DATA_IN_HEADER_MODIFY) {
 673		mlx5_core_err(mdev, "Pattern length %d exceeds limit %d\n",
 674			      pattern_length, MLX5_MAX_ACTIONS_DATA_IN_HEADER_MODIFY);
 675		return -EINVAL;
 676	}
 677
 678	attr = MLX5_ADDR_OF(create_header_modify_pattern_in, in, hdr);
 679	MLX5_SET(general_obj_in_cmd_hdr,
 680		 attr, opcode, MLX5_CMD_OP_CREATE_GENERAL_OBJECT);
 681	MLX5_SET(general_obj_in_cmd_hdr,
 682		 attr, obj_type, MLX5_OBJ_TYPE_MODIFY_HDR_PATTERN);
 683
 684	pattern = MLX5_ADDR_OF(create_header_modify_pattern_in, in, pattern);
 685	/* Pattern_length is in ddwords */
 686	MLX5_SET(header_modify_pattern_in, pattern, pattern_length, pattern_length / (2 * DW_SIZE));
 687
 688	pattern_data = (u64 *)MLX5_ADDR_OF(header_modify_pattern_in, pattern, pattern_data);
 689	memcpy(pattern_data, actions, pattern_length);
 690
 691	num_of_actions = pattern_length / MLX5HWS_MODIFY_ACTION_SIZE;
 692	for (i = 0; i < num_of_actions; i++) {
 693		int type;
 694
 695		type = MLX5_GET(set_action_in, &pattern_data[i], action_type);
 696		if (type != MLX5_MODIFICATION_TYPE_COPY &&
 697		    type != MLX5_MODIFICATION_TYPE_ADD_FIELD)
 698			/* Action typ-copy use all bytes for control */
 699			MLX5_SET(set_action_in, &pattern_data[i], data, 0);
 700	}
 701
 702	ret = mlx5_cmd_exec(mdev, in, sizeof(in), out, sizeof(out));
 703	if (ret) {
 704		mlx5_core_err(mdev, "Failed to create header_modify_pattern\n");
 705		goto out;
 706	}
 707
 708	*ptrn_id = MLX5_GET(general_obj_out_cmd_hdr, out, obj_id);
 709out:
 710	return ret;
 711}
 712
 713void mlx5hws_cmd_header_modify_pattern_destroy(struct mlx5_core_dev *mdev,
 714					       u32 ptrn_id)
 715{
 716	hws_cmd_general_obj_destroy(mdev, MLX5_OBJ_TYPE_MODIFY_HDR_PATTERN, ptrn_id);
 717}
 718
 719int mlx5hws_cmd_ste_create(struct mlx5_core_dev *mdev,
 720			   struct mlx5hws_cmd_ste_create_attr *ste_attr,
 721			   u32 *ste_id)
 722{
 723	u32 out[MLX5_ST_SZ_DW(general_obj_out_cmd_hdr)] = {0};
 724	u32 in[MLX5_ST_SZ_DW(create_ste_in)] = {0};
 725	void *attr;
 726	int ret;
 727
 728	attr = MLX5_ADDR_OF(create_ste_in, in, hdr);
 729	MLX5_SET(general_obj_in_cmd_hdr,
 730		 attr, opcode, MLX5_CMD_OP_CREATE_GENERAL_OBJECT);
 731	MLX5_SET(general_obj_in_cmd_hdr,
 732		 attr, obj_type, MLX5_OBJ_TYPE_STE);
 733	MLX5_SET(general_obj_in_cmd_hdr,
 734		 attr, op_param.create.log_obj_range, ste_attr->log_obj_range);
 735
 736	attr = MLX5_ADDR_OF(create_ste_in, in, ste);
 737	MLX5_SET(ste, attr, table_type, ste_attr->table_type);
 738
 739	ret = mlx5_cmd_exec(mdev, in, sizeof(in), out, sizeof(out));
 740	if (ret) {
 741		mlx5_core_err(mdev, "Failed to create STE\n");
 742		goto out;
 743	}
 744
 745	*ste_id = MLX5_GET(general_obj_out_cmd_hdr, out, obj_id);
 746out:
 747	return ret;
 748}
 749
 750void mlx5hws_cmd_ste_destroy(struct mlx5_core_dev *mdev, u32 ste_id)
 751{
 752	hws_cmd_general_obj_destroy(mdev, MLX5_OBJ_TYPE_STE, ste_id);
 753}
 754
 755int mlx5hws_cmd_definer_create(struct mlx5_core_dev *mdev,
 756			       struct mlx5hws_cmd_definer_create_attr *def_attr,
 757			       u32 *definer_id)
 758{
 759	u32 out[MLX5_ST_SZ_DW(general_obj_out_cmd_hdr)] = {0};
 760	u32 in[MLX5_ST_SZ_DW(create_definer_in)] = {0};
 761	void *ptr;
 762	int ret;
 763
 764	MLX5_SET(general_obj_in_cmd_hdr,
 765		 in, opcode, MLX5_CMD_OP_CREATE_GENERAL_OBJECT);
 766	MLX5_SET(general_obj_in_cmd_hdr,
 767		 in, obj_type, MLX5_OBJ_TYPE_MATCH_DEFINER);
 768
 769	ptr = MLX5_ADDR_OF(create_definer_in, in, definer);
 770	MLX5_SET(definer, ptr, format_id, MLX5_IFC_DEFINER_FORMAT_ID_SELECT);
 771
 772	MLX5_SET(definer, ptr, format_select_dw0, def_attr->dw_selector[0]);
 773	MLX5_SET(definer, ptr, format_select_dw1, def_attr->dw_selector[1]);
 774	MLX5_SET(definer, ptr, format_select_dw2, def_attr->dw_selector[2]);
 775	MLX5_SET(definer, ptr, format_select_dw3, def_attr->dw_selector[3]);
 776	MLX5_SET(definer, ptr, format_select_dw4, def_attr->dw_selector[4]);
 777	MLX5_SET(definer, ptr, format_select_dw5, def_attr->dw_selector[5]);
 778	MLX5_SET(definer, ptr, format_select_dw6, def_attr->dw_selector[6]);
 779	MLX5_SET(definer, ptr, format_select_dw7, def_attr->dw_selector[7]);
 780	MLX5_SET(definer, ptr, format_select_dw8, def_attr->dw_selector[8]);
 781
 782	MLX5_SET(definer, ptr, format_select_byte0, def_attr->byte_selector[0]);
 783	MLX5_SET(definer, ptr, format_select_byte1, def_attr->byte_selector[1]);
 784	MLX5_SET(definer, ptr, format_select_byte2, def_attr->byte_selector[2]);
 785	MLX5_SET(definer, ptr, format_select_byte3, def_attr->byte_selector[3]);
 786	MLX5_SET(definer, ptr, format_select_byte4, def_attr->byte_selector[4]);
 787	MLX5_SET(definer, ptr, format_select_byte5, def_attr->byte_selector[5]);
 788	MLX5_SET(definer, ptr, format_select_byte6, def_attr->byte_selector[6]);
 789	MLX5_SET(definer, ptr, format_select_byte7, def_attr->byte_selector[7]);
 790
 791	ptr = MLX5_ADDR_OF(definer, ptr, match_mask);
 792	memcpy(ptr, def_attr->match_mask, MLX5_FLD_SZ_BYTES(definer, match_mask));
 793
 794	ret = mlx5_cmd_exec(mdev, in, sizeof(in), out, sizeof(out));
 795	if (ret) {
 796		mlx5_core_err(mdev, "Failed to create Definer\n");
 797		goto out;
 798	}
 799
 800	*definer_id = MLX5_GET(general_obj_out_cmd_hdr, out, obj_id);
 801out:
 802	return ret;
 803}
 804
 805void mlx5hws_cmd_definer_destroy(struct mlx5_core_dev *mdev,
 806				 u32 definer_id)
 807{
 808	hws_cmd_general_obj_destroy(mdev, MLX5_OBJ_TYPE_MATCH_DEFINER, definer_id);
 809}
 810
 811int mlx5hws_cmd_packet_reformat_create(struct mlx5_core_dev *mdev,
 812				       struct mlx5hws_cmd_packet_reformat_create_attr *attr,
 813				       u32 *reformat_id)
 814{
 815	u32 out[MLX5_ST_SZ_DW(alloc_packet_reformat_context_out)] = {0};
 816	size_t insz, cmd_data_sz, cmd_total_sz;
 817	void *prctx;
 818	void *pdata;
 819	void *in;
 820	int ret;
 821
 822	cmd_total_sz = MLX5_ST_SZ_BYTES(alloc_packet_reformat_context_in);
 823	cmd_total_sz += MLX5_ST_SZ_BYTES(packet_reformat_context_in);
 824	cmd_data_sz = MLX5_FLD_SZ_BYTES(packet_reformat_context_in, reformat_data);
 825	insz = align(cmd_total_sz + attr->data_sz - cmd_data_sz, DW_SIZE);
 826	in = kzalloc(insz, GFP_KERNEL);
 827	if (!in)
 828		return -ENOMEM;
 829
 830	MLX5_SET(alloc_packet_reformat_context_in, in, opcode,
 831		 MLX5_CMD_OP_ALLOC_PACKET_REFORMAT_CONTEXT);
 832
 833	prctx = MLX5_ADDR_OF(alloc_packet_reformat_context_in, in,
 834			     packet_reformat_context);
 835	pdata = MLX5_ADDR_OF(packet_reformat_context_in, prctx, reformat_data);
 836
 837	MLX5_SET(packet_reformat_context_in, prctx, reformat_type, attr->type);
 838	MLX5_SET(packet_reformat_context_in, prctx, reformat_param_0, attr->reformat_param_0);
 839	MLX5_SET(packet_reformat_context_in, prctx, reformat_data_size, attr->data_sz);
 840	memcpy(pdata, attr->data, attr->data_sz);
 841
 842	ret = mlx5_cmd_exec(mdev, in, insz, out, sizeof(out));
 843	if (ret) {
 844		mlx5_core_err(mdev, "Failed to create packet reformat\n");
 845		goto out;
 846	}
 847
 848	*reformat_id = MLX5_GET(alloc_packet_reformat_context_out, out, packet_reformat_id);
 849out:
 850	kfree(in);
 851	return ret;
 852}
 853
 854int mlx5hws_cmd_packet_reformat_destroy(struct mlx5_core_dev *mdev,
 855					u32 reformat_id)
 856{
 857	u32 out[MLX5_ST_SZ_DW(dealloc_packet_reformat_context_out)] = {0};
 858	u32 in[MLX5_ST_SZ_DW(dealloc_packet_reformat_context_in)] = {0};
 859	int ret;
 860
 861	MLX5_SET(dealloc_packet_reformat_context_in, in, opcode,
 862		 MLX5_CMD_OP_DEALLOC_PACKET_REFORMAT_CONTEXT);
 863	MLX5_SET(dealloc_packet_reformat_context_in, in,
 864		 packet_reformat_id, reformat_id);
 865
 866	ret = mlx5_cmd_exec(mdev, in, sizeof(in), out, sizeof(out));
 867	if (ret)
 868		mlx5_core_err(mdev, "Failed to destroy packet_reformat\n");
 869
 870	return ret;
 871}
 872
 873int mlx5hws_cmd_sq_modify_rdy(struct mlx5_core_dev *mdev, u32 sqn)
 874{
 875	u32 out[MLX5_ST_SZ_DW(modify_sq_out)] = {0};
 876	u32 in[MLX5_ST_SZ_DW(modify_sq_in)] = {0};
 877	void *sqc = MLX5_ADDR_OF(modify_sq_in, in, ctx);
 878	int ret;
 879
 880	MLX5_SET(modify_sq_in, in, opcode, MLX5_CMD_OP_MODIFY_SQ);
 881	MLX5_SET(modify_sq_in, in, sqn, sqn);
 882	MLX5_SET(modify_sq_in, in, sq_state, MLX5_SQC_STATE_RST);
 883	MLX5_SET(sqc, sqc, state, MLX5_SQC_STATE_RDY);
 884
 885	ret = mlx5_cmd_exec(mdev, in, sizeof(in), out, sizeof(out));
 886	if (ret)
 887		mlx5_core_err(mdev, "Failed to modify SQ\n");
 888
 889	return ret;
 890}
 891
 892int mlx5hws_cmd_generate_wqe(struct mlx5_core_dev *mdev,
 893			     struct mlx5hws_cmd_generate_wqe_attr *attr,
 894			     struct mlx5_cqe64 *ret_cqe)
 895{
 896	u32 out[MLX5_ST_SZ_DW(generate_wqe_out)] = {0};
 897	u32 in[MLX5_ST_SZ_DW(generate_wqe_in)] = {0};
 898	u8 status;
 899	void *ptr;
 900	int ret;
 901
 902	MLX5_SET(generate_wqe_in, in, opcode, MLX5_CMD_OP_GENERATE_WQE);
 903	MLX5_SET(generate_wqe_in, in, pdn, attr->pdn);
 904
 905	ptr = MLX5_ADDR_OF(generate_wqe_in, in, wqe_ctrl);
 906	memcpy(ptr, attr->wqe_ctrl, MLX5_FLD_SZ_BYTES(generate_wqe_in, wqe_ctrl));
 907
 908	ptr = MLX5_ADDR_OF(generate_wqe_in, in, wqe_gta_ctrl);
 909	memcpy(ptr, attr->gta_ctrl, MLX5_FLD_SZ_BYTES(generate_wqe_in, wqe_gta_ctrl));
 910
 911	ptr = MLX5_ADDR_OF(generate_wqe_in, in, wqe_gta_data_0);
 912	memcpy(ptr, attr->gta_data_0, MLX5_FLD_SZ_BYTES(generate_wqe_in, wqe_gta_data_0));
 913
 914	if (attr->gta_data_1) {
 915		ptr = MLX5_ADDR_OF(generate_wqe_in, in, wqe_gta_data_1);
 916		memcpy(ptr, attr->gta_data_1, MLX5_FLD_SZ_BYTES(generate_wqe_in, wqe_gta_data_1));
 917	}
 918
 919	ret = mlx5_cmd_exec(mdev, in, sizeof(in), out, sizeof(out));
 920	if (ret) {
 921		mlx5_core_err(mdev, "Failed to write GTA WQE using FW\n");
 922		return ret;
 923	}
 924
 925	status = MLX5_GET(generate_wqe_out, out, status);
 926	if (status) {
 927		mlx5_core_err(mdev, "Invalid FW CQE status %d\n", status);
 928		return -EINVAL;
 929	}
 930
 931	ptr = MLX5_ADDR_OF(generate_wqe_out, out, cqe_data);
 932	memcpy(ret_cqe, ptr, sizeof(*ret_cqe));
 933
 934	return ret;
 935}
 936
 937int mlx5hws_cmd_query_caps(struct mlx5_core_dev *mdev,
 938			   struct mlx5hws_cmd_query_caps *caps)
 939{
 940	u32 in[MLX5_ST_SZ_DW(query_hca_cap_in)] = {0};
 941	u32 out_size;
 942	u32 *out;
 943	int ret;
 944
 945	out_size = MLX5_ST_SZ_BYTES(query_hca_cap_out);
 946	out = kzalloc(out_size, GFP_KERNEL);
 947	if (!out)
 948		return -ENOMEM;
 949
 950	MLX5_SET(query_hca_cap_in, in, opcode, MLX5_CMD_OP_QUERY_HCA_CAP);
 951	MLX5_SET(query_hca_cap_in, in, op_mod,
 952		 MLX5_SET_HCA_CAP_OP_MOD_GENERAL_DEVICE | HCA_CAP_OPMOD_GET_CUR);
 953
 954	ret = mlx5_cmd_exec(mdev, in, sizeof(in), out, out_size);
 955	if (ret) {
 956		mlx5_core_err(mdev, "Failed to query device caps\n");
 957		goto out;
 958	}
 959
 960	caps->wqe_based_update =
 961		MLX5_GET(query_hca_cap_out, out,
 962			 capability.cmd_hca_cap.wqe_based_flow_table_update_cap);
 963
 964	caps->eswitch_manager = MLX5_GET(query_hca_cap_out, out,
 965					 capability.cmd_hca_cap.eswitch_manager);
 966
 967	caps->flex_protocols = MLX5_GET(query_hca_cap_out, out,
 968					capability.cmd_hca_cap.flex_parser_protocols);
 969
 970	if (caps->flex_protocols & MLX5_FLEX_PARSER_GENEVE_TLV_OPTION_0_ENABLED)
 971		caps->flex_parser_id_geneve_tlv_option_0 =
 972			MLX5_GET(query_hca_cap_out, out,
 973				 capability.cmd_hca_cap.flex_parser_id_geneve_tlv_option_0);
 974
 975	if (caps->flex_protocols & MLX5_FLEX_PARSER_MPLS_OVER_GRE_ENABLED)
 976		caps->flex_parser_id_mpls_over_gre =
 977			MLX5_GET(query_hca_cap_out, out,
 978				 capability.cmd_hca_cap.flex_parser_id_outer_first_mpls_over_gre);
 979
 980	if (caps->flex_protocols & MLX5_FLEX_PARSER_MPLS_OVER_UDP_ENABLED)
 981		caps->flex_parser_id_mpls_over_udp =
 982			MLX5_GET(query_hca_cap_out, out,
 983				 capability.cmd_hca_cap.flex_parser_id_outer_first_mpls_over_udp_label);
 984
 985	caps->log_header_modify_argument_granularity =
 986		MLX5_GET(query_hca_cap_out, out,
 987			 capability.cmd_hca_cap.log_header_modify_argument_granularity);
 988
 989	caps->log_header_modify_argument_granularity -=
 990		MLX5_GET(query_hca_cap_out, out,
 991			 capability.cmd_hca_cap.log_header_modify_argument_granularity_offset);
 992
 993	caps->log_header_modify_argument_max_alloc =
 994		MLX5_GET(query_hca_cap_out, out,
 995			 capability.cmd_hca_cap.log_header_modify_argument_max_alloc);
 996
 997	caps->definer_format_sup =
 998		MLX5_GET64(query_hca_cap_out, out,
 999			   capability.cmd_hca_cap.match_definer_format_supported);
1000
1001	caps->vhca_id = MLX5_GET(query_hca_cap_out, out,
1002				 capability.cmd_hca_cap.vhca_id);
1003
1004	caps->sq_ts_format = MLX5_GET(query_hca_cap_out, out,
1005				      capability.cmd_hca_cap.sq_ts_format);
1006
1007	caps->ipsec_offload = MLX5_GET(query_hca_cap_out, out,
1008				       capability.cmd_hca_cap.ipsec_offload);
1009
1010	MLX5_SET(query_hca_cap_in, in, op_mod,
1011		 MLX5_GET_HCA_CAP_OP_MOD_GENERAL_DEVICE_2 | HCA_CAP_OPMOD_GET_CUR);
1012
1013	ret = mlx5_cmd_exec(mdev, in, sizeof(in), out, out_size);
1014	if (ret) {
1015		mlx5_core_err(mdev, "Failed to query device caps 2\n");
1016		goto out;
1017	}
1018
1019	caps->full_dw_jumbo_support =
1020		MLX5_GET(query_hca_cap_out, out,
1021			 capability.cmd_hca_cap_2.format_select_dw_8_6_ext);
1022
1023	caps->format_select_gtpu_dw_0 =
1024		MLX5_GET(query_hca_cap_out, out,
1025			 capability.cmd_hca_cap_2.format_select_dw_gtpu_dw_0);
1026
1027	caps->format_select_gtpu_dw_1 =
1028		MLX5_GET(query_hca_cap_out, out,
1029			 capability.cmd_hca_cap_2.format_select_dw_gtpu_dw_1);
1030
1031	caps->format_select_gtpu_dw_2 =
1032		MLX5_GET(query_hca_cap_out, out,
1033			 capability.cmd_hca_cap_2.format_select_dw_gtpu_dw_2);
1034
1035	caps->format_select_gtpu_ext_dw_0 =
1036		MLX5_GET(query_hca_cap_out, out,
1037			 capability.cmd_hca_cap_2.format_select_dw_gtpu_first_ext_dw_0);
1038
1039	caps->supp_type_gen_wqe =
1040		MLX5_GET(query_hca_cap_out, out,
1041			 capability.cmd_hca_cap_2.generate_wqe_type);
1042
1043	caps->flow_table_hash_type =
1044		MLX5_GET(query_hca_cap_out, out,
1045			 capability.cmd_hca_cap_2.flow_table_hash_type);
1046
1047	MLX5_SET(query_hca_cap_in, in, op_mod,
1048		 MLX5_GET_HCA_CAP_OP_MOD_NIC_FLOW_TABLE | HCA_CAP_OPMOD_GET_CUR);
1049
1050	ret = mlx5_cmd_exec(mdev, in, sizeof(in), out, out_size);
1051	if (ret) {
1052		mlx5_core_err(mdev, "Failed to query flow table caps\n");
1053		goto out;
1054	}
1055
1056	caps->nic_ft.max_level =
1057		MLX5_GET(query_hca_cap_out, out,
1058			 capability.flow_table_nic_cap.flow_table_properties_nic_receive.max_ft_level);
1059
1060	caps->nic_ft.reparse =
1061		MLX5_GET(query_hca_cap_out, out,
1062			 capability.flow_table_nic_cap.flow_table_properties_nic_receive.reparse);
1063
1064	caps->nic_ft.ignore_flow_level_rtc_valid =
1065		MLX5_GET(query_hca_cap_out, out,
1066			 capability.flow_table_nic_cap.flow_table_properties_nic_receive.ignore_flow_level_rtc_valid);
1067
1068	caps->flex_parser_ok_bits_supp =
1069		MLX5_GET(query_hca_cap_out, out,
1070			 capability.flow_table_nic_cap.flow_table_properties_nic_receive.ft_field_support.geneve_tlv_option_0_exist);
1071
1072	if (caps->wqe_based_update) {
1073		MLX5_SET(query_hca_cap_in, in, op_mod,
1074			 MLX5_GET_HCA_CAP_OP_MOD_WQE_BASED_FLOW_TABLE | HCA_CAP_OPMOD_GET_CUR);
1075
1076		ret = mlx5_cmd_exec(mdev, in, sizeof(in), out, out_size);
1077		if (ret) {
1078			mlx5_core_err(mdev, "Failed to query WQE based FT caps\n");
1079			goto out;
1080		}
1081
1082		caps->rtc_reparse_mode =
1083			MLX5_GET(query_hca_cap_out, out,
1084				 capability.wqe_based_flow_table_cap.rtc_reparse_mode);
1085
1086		caps->ste_format =
1087			MLX5_GET(query_hca_cap_out, out,
1088				 capability.wqe_based_flow_table_cap.ste_format);
1089
1090		caps->rtc_index_mode =
1091			MLX5_GET(query_hca_cap_out, out,
1092				 capability.wqe_based_flow_table_cap.rtc_index_mode);
1093
1094		caps->rtc_log_depth_max =
1095			MLX5_GET(query_hca_cap_out, out,
1096				 capability.wqe_based_flow_table_cap.rtc_log_depth_max);
1097
1098		caps->ste_alloc_log_max =
1099			MLX5_GET(query_hca_cap_out, out,
1100				 capability.wqe_based_flow_table_cap.ste_alloc_log_max);
1101
1102		caps->ste_alloc_log_gran =
1103			MLX5_GET(query_hca_cap_out, out,
1104				 capability.wqe_based_flow_table_cap.ste_alloc_log_granularity);
1105
1106		caps->trivial_match_definer =
1107			MLX5_GET(query_hca_cap_out, out,
1108				 capability.wqe_based_flow_table_cap.trivial_match_definer);
1109
1110		caps->stc_alloc_log_max =
1111			MLX5_GET(query_hca_cap_out, out,
1112				 capability.wqe_based_flow_table_cap.stc_alloc_log_max);
1113
1114		caps->stc_alloc_log_gran =
1115			MLX5_GET(query_hca_cap_out, out,
1116				 capability.wqe_based_flow_table_cap.stc_alloc_log_granularity);
1117
1118		caps->rtc_hash_split_table =
1119			MLX5_GET(query_hca_cap_out, out,
1120				 capability.wqe_based_flow_table_cap.rtc_hash_split_table);
1121
1122		caps->rtc_linear_lookup_table =
1123			MLX5_GET(query_hca_cap_out, out,
1124				 capability.wqe_based_flow_table_cap.rtc_linear_lookup_table);
1125
1126		caps->access_index_mode =
1127			MLX5_GET(query_hca_cap_out, out,
1128				 capability.wqe_based_flow_table_cap.access_index_mode);
1129
1130		caps->linear_match_definer =
1131			MLX5_GET(query_hca_cap_out, out,
1132				 capability.wqe_based_flow_table_cap.linear_match_definer_reg_c3);
1133
1134		caps->rtc_max_hash_def_gen_wqe =
1135			MLX5_GET(query_hca_cap_out, out,
1136				 capability.wqe_based_flow_table_cap.rtc_max_num_hash_definer_gen_wqe);
1137
1138		caps->supp_ste_format_gen_wqe =
1139			MLX5_GET(query_hca_cap_out, out,
1140				 capability.wqe_based_flow_table_cap.ste_format_gen_wqe);
1141
1142		caps->fdb_tir_stc =
1143			MLX5_GET(query_hca_cap_out, out,
1144				 capability.wqe_based_flow_table_cap.fdb_jump_to_tir_stc);
1145	}
1146
1147	if (caps->eswitch_manager) {
1148		MLX5_SET(query_hca_cap_in, in, op_mod,
1149			 MLX5_GET_HCA_CAP_OP_MOD_ESW_FLOW_TABLE | HCA_CAP_OPMOD_GET_CUR);
1150
1151		ret = mlx5_cmd_exec(mdev, in, sizeof(in), out, out_size);
1152		if (ret) {
1153			mlx5_core_err(mdev, "Failed to query flow table esw caps\n");
1154			goto out;
1155		}
1156
1157		caps->fdb_ft.max_level =
1158			MLX5_GET(query_hca_cap_out, out,
1159				 capability.flow_table_nic_cap.flow_table_properties_nic_receive.max_ft_level);
1160
1161		caps->fdb_ft.reparse =
1162			MLX5_GET(query_hca_cap_out, out,
1163				 capability.flow_table_nic_cap.flow_table_properties_nic_receive.reparse);
1164
1165		MLX5_SET(query_hca_cap_in, in, op_mod,
1166			 MLX5_SET_HCA_CAP_OP_MOD_ESW | HCA_CAP_OPMOD_GET_CUR);
1167
1168		ret = mlx5_cmd_exec(mdev, in, sizeof(in), out, out_size);
1169		if (ret) {
1170			mlx5_core_err(mdev, "Failed to query eswitch capabilities\n");
1171			goto out;
1172		}
1173
1174		if (MLX5_GET(query_hca_cap_out, out,
1175			     capability.esw_cap.esw_manager_vport_number_valid))
1176			caps->eswitch_manager_vport_number =
1177				MLX5_GET(query_hca_cap_out, out,
1178					 capability.esw_cap.esw_manager_vport_number);
1179
1180		caps->merged_eswitch = MLX5_GET(query_hca_cap_out, out,
1181						capability.esw_cap.merged_eswitch);
1182	}
1183
1184	ret = mlx5_cmd_exec(mdev, in, sizeof(in), out, out_size);
1185	if (ret) {
1186		mlx5_core_err(mdev, "Failed to query device attributes\n");
1187		goto out;
1188	}
1189
1190	snprintf(caps->fw_ver, sizeof(caps->fw_ver), "%d.%d.%d",
1191		 fw_rev_maj(mdev), fw_rev_min(mdev), fw_rev_sub(mdev));
1192
1193	caps->is_ecpf = mlx5_core_is_ecpf_esw_manager(mdev);
1194
1195out:
1196	kfree(out);
1197	return ret;
1198}
1199
1200int mlx5hws_cmd_query_gvmi(struct mlx5_core_dev *mdev, bool other_function,
1201			   u16 vport_number, u16 *gvmi)
1202{
1203	int err;
1204
1205	if (!other_function) {
1206		/* self vhca_id */
1207		*gvmi = MLX5_CAP_GEN(mdev, vhca_id);
1208		return 0;
1209	}
1210
1211	err = mlx5_vport_get_vhca_id(mdev, vport_number, gvmi);
1212	if (err) {
1213		mlx5_core_err(mdev, "Failed to get vport vhca id for vport %d\n",
1214			      vport_number);
1215		return err;
1216	}
1217
1218	return 0;
1219}
~/ Read-only file preview.