File Index
Files and directories
Sign in
FILE

dr_cmd.c

File preview with syntax highlighting.

linux-6.19.14/drivers/net/ethernet/mellanox/mlx5/core/steering/sws/dr_cmd.c C
  1// SPDX-License-Identifier: GPL-2.0 OR Linux-OpenIB
  2/* Copyright (c) 2019 Mellanox Technologies. */
  3
  4#include "dr_types.h"
  5#include "eswitch.h"
  6
  7int mlx5dr_cmd_query_esw_vport_context(struct mlx5_core_dev *mdev,
  8				       bool other_vport,
  9				       u16 vport_number,
 10				       u64 *icm_address_rx,
 11				       u64 *icm_address_tx)
 12{
 13	u32 out[MLX5_ST_SZ_DW(query_esw_vport_context_out)] = {};
 14	u32 in[MLX5_ST_SZ_DW(query_esw_vport_context_in)] = {};
 15	int err;
 16
 17	MLX5_SET(query_esw_vport_context_in, in, opcode,
 18		 MLX5_CMD_OP_QUERY_ESW_VPORT_CONTEXT);
 19	MLX5_SET(query_esw_vport_context_in, in, other_vport, other_vport);
 20	MLX5_SET(query_esw_vport_context_in, in, vport_number, vport_number);
 21
 22	err = mlx5_cmd_exec_inout(mdev, query_esw_vport_context, in, out);
 23	if (err)
 24		return err;
 25
 26	*icm_address_rx =
 27		MLX5_GET64(query_esw_vport_context_out, out,
 28			   esw_vport_context.sw_steering_vport_icm_address_rx);
 29	*icm_address_tx =
 30		MLX5_GET64(query_esw_vport_context_out, out,
 31			   esw_vport_context.sw_steering_vport_icm_address_tx);
 32	return 0;
 33}
 34
 35int mlx5dr_cmd_query_gvmi(struct mlx5_core_dev *mdev, bool other_vport,
 36			  u16 vport_number, u16 *gvmi)
 37{
 38	int err;
 39
 40	if (!other_vport) {
 41		/* self vhca_id */
 42		*gvmi = MLX5_CAP_GEN(mdev, vhca_id);
 43		return 0;
 44	}
 45
 46	err = mlx5_vport_get_vhca_id(mdev, vport_number, gvmi);
 47	if (err) {
 48		mlx5_core_err(mdev, "Failed to get vport vhca id for vport %d\n",
 49			      vport_number);
 50		return err;
 51	}
 52
 53	return 0;
 54}
 55
 56int mlx5dr_cmd_query_esw_caps(struct mlx5_core_dev *mdev,
 57			      struct mlx5dr_esw_caps *caps)
 58{
 59	caps->drop_icm_address_rx =
 60		MLX5_CAP64_ESW_FLOWTABLE(mdev,
 61					 sw_steering_fdb_action_drop_icm_address_rx);
 62	caps->drop_icm_address_tx =
 63		MLX5_CAP64_ESW_FLOWTABLE(mdev,
 64					 sw_steering_fdb_action_drop_icm_address_tx);
 65	caps->uplink_icm_address_rx =
 66		MLX5_CAP64_ESW_FLOWTABLE(mdev,
 67					 sw_steering_uplink_icm_address_rx);
 68	caps->uplink_icm_address_tx =
 69		MLX5_CAP64_ESW_FLOWTABLE(mdev,
 70					 sw_steering_uplink_icm_address_tx);
 71	caps->sw_owner_v2 = MLX5_CAP_ESW_FLOWTABLE_FDB(mdev, sw_owner_v2);
 72	if (!caps->sw_owner_v2)
 73		caps->sw_owner = MLX5_CAP_ESW_FLOWTABLE_FDB(mdev, sw_owner);
 74
 75	return 0;
 76}
 77
 78static int dr_cmd_query_nic_vport_roce_en(struct mlx5_core_dev *mdev,
 79					  u16 vport, bool *roce_en)
 80{
 81	u32 out[MLX5_ST_SZ_DW(query_nic_vport_context_out)] = {};
 82	u32 in[MLX5_ST_SZ_DW(query_nic_vport_context_in)] = {};
 83	int err;
 84
 85	MLX5_SET(query_nic_vport_context_in, in, opcode,
 86		 MLX5_CMD_OP_QUERY_NIC_VPORT_CONTEXT);
 87	MLX5_SET(query_nic_vport_context_in, in, vport_number, vport);
 88	MLX5_SET(query_nic_vport_context_in, in, other_vport, !!vport);
 89
 90	err = mlx5_cmd_exec(mdev, in, sizeof(in), out, sizeof(out));
 91	if (err)
 92		return err;
 93
 94	*roce_en = MLX5_GET(query_nic_vport_context_out, out,
 95			    nic_vport_context.roce_en);
 96	return 0;
 97}
 98
 99int mlx5dr_cmd_query_device(struct mlx5_core_dev *mdev,
100			    struct mlx5dr_cmd_caps *caps)
101{
102	bool roce_en;
103	int err;
104
105	caps->prio_tag_required	= MLX5_CAP_GEN(mdev, prio_tag_required);
106	caps->eswitch_manager	= MLX5_CAP_GEN(mdev, eswitch_manager);
107	caps->gvmi		= MLX5_CAP_GEN(mdev, vhca_id);
108	caps->flex_protocols	= MLX5_CAP_GEN(mdev, flex_parser_protocols);
109	caps->sw_format_ver	= MLX5_CAP_GEN(mdev, steering_format_version);
110	caps->roce_caps.fl_rc_qp_when_roce_disabled =
111		MLX5_CAP_GEN(mdev, fl_rc_qp_when_roce_disabled);
112
113	if (MLX5_CAP_GEN(mdev, roce)) {
114		err = dr_cmd_query_nic_vport_roce_en(mdev, 0, &roce_en);
115		if (err)
116			return err;
117
118		caps->roce_caps.roce_en = roce_en;
119		caps->roce_caps.fl_rc_qp_when_roce_disabled |=
120			MLX5_CAP_ROCE(mdev, fl_rc_qp_when_roce_disabled);
121		caps->roce_caps.fl_rc_qp_when_roce_enabled =
122			MLX5_CAP_ROCE(mdev, fl_rc_qp_when_roce_enabled);
123	}
124
125	caps->isolate_vl_tc = MLX5_CAP_GEN(mdev, isolate_vl_tc_new);
126
127	caps->support_modify_argument =
128		MLX5_CAP_GEN_64(mdev, general_obj_types) &
129		MLX5_GENERAL_OBJ_TYPES_CAP_HEADER_MODIFY_ARGUMENT;
130
131	if (caps->support_modify_argument) {
132		caps->log_header_modify_argument_granularity =
133			MLX5_CAP_GEN(mdev, log_header_modify_argument_granularity);
134		caps->log_header_modify_argument_max_alloc =
135			MLX5_CAP_GEN(mdev, log_header_modify_argument_max_alloc);
136	}
137
138	/* geneve_tlv_option_0_exist is the indication of
139	 * STE support for lookup type flex_parser_ok
140	 */
141	caps->flex_parser_ok_bits_supp =
142		MLX5_CAP_FLOWTABLE(mdev,
143				   flow_table_properties_nic_receive.ft_field_support.geneve_tlv_option_0_exist);
144
145	if (caps->flex_protocols & MLX5_FLEX_PARSER_ICMP_V4_ENABLED) {
146		caps->flex_parser_id_icmp_dw0 = MLX5_CAP_GEN(mdev, flex_parser_id_icmp_dw0);
147		caps->flex_parser_id_icmp_dw1 = MLX5_CAP_GEN(mdev, flex_parser_id_icmp_dw1);
148	}
149
150	if (caps->flex_protocols & MLX5_FLEX_PARSER_ICMP_V6_ENABLED) {
151		caps->flex_parser_id_icmpv6_dw0 =
152			MLX5_CAP_GEN(mdev, flex_parser_id_icmpv6_dw0);
153		caps->flex_parser_id_icmpv6_dw1 =
154			MLX5_CAP_GEN(mdev, flex_parser_id_icmpv6_dw1);
155	}
156
157	if (caps->flex_protocols & MLX5_FLEX_PARSER_GENEVE_TLV_OPTION_0_ENABLED)
158		caps->flex_parser_id_geneve_tlv_option_0 =
159			MLX5_CAP_GEN(mdev, flex_parser_id_geneve_tlv_option_0);
160
161	if (caps->flex_protocols & MLX5_FLEX_PARSER_MPLS_OVER_GRE_ENABLED)
162		caps->flex_parser_id_mpls_over_gre =
163			MLX5_CAP_GEN(mdev, flex_parser_id_outer_first_mpls_over_gre);
164
165	if (caps->flex_protocols & MLX5_FLEX_PARSER_MPLS_OVER_UDP_ENABLED)
166		caps->flex_parser_id_mpls_over_udp =
167			MLX5_CAP_GEN(mdev, flex_parser_id_outer_first_mpls_over_udp_label);
168
169	if (caps->flex_protocols & MLX5_FLEX_PARSER_GTPU_DW_0_ENABLED)
170		caps->flex_parser_id_gtpu_dw_0 =
171			MLX5_CAP_GEN(mdev, flex_parser_id_gtpu_dw_0);
172
173	if (caps->flex_protocols & MLX5_FLEX_PARSER_GTPU_TEID_ENABLED)
174		caps->flex_parser_id_gtpu_teid =
175			MLX5_CAP_GEN(mdev, flex_parser_id_gtpu_teid);
176
177	if (caps->flex_protocols & MLX5_FLEX_PARSER_GTPU_DW_2_ENABLED)
178		caps->flex_parser_id_gtpu_dw_2 =
179			MLX5_CAP_GEN(mdev, flex_parser_id_gtpu_dw_2);
180
181	if (caps->flex_protocols & MLX5_FLEX_PARSER_GTPU_FIRST_EXT_DW_0_ENABLED)
182		caps->flex_parser_id_gtpu_first_ext_dw_0 =
183			MLX5_CAP_GEN(mdev, flex_parser_id_gtpu_first_ext_dw_0);
184
185	caps->nic_rx_drop_address =
186		MLX5_CAP64_FLOWTABLE(mdev, sw_steering_nic_rx_action_drop_icm_address);
187	caps->nic_tx_drop_address =
188		MLX5_CAP64_FLOWTABLE(mdev, sw_steering_nic_tx_action_drop_icm_address);
189	caps->nic_tx_allow_address =
190		MLX5_CAP64_FLOWTABLE(mdev, sw_steering_nic_tx_action_allow_icm_address);
191
192	caps->rx_sw_owner_v2 = MLX5_CAP_FLOWTABLE_NIC_RX(mdev, sw_owner_v2);
193	caps->tx_sw_owner_v2 = MLX5_CAP_FLOWTABLE_NIC_TX(mdev, sw_owner_v2);
194
195	if (!caps->rx_sw_owner_v2)
196		caps->rx_sw_owner = MLX5_CAP_FLOWTABLE_NIC_RX(mdev, sw_owner);
197	if (!caps->tx_sw_owner_v2)
198		caps->tx_sw_owner = MLX5_CAP_FLOWTABLE_NIC_TX(mdev, sw_owner);
199
200	caps->max_ft_level = MLX5_CAP_FLOWTABLE_NIC_RX(mdev, max_ft_level);
201
202	caps->log_icm_size = MLX5_CAP_DEV_MEM(mdev, log_steering_sw_icm_size);
203	caps->hdr_modify_icm_addr =
204		MLX5_CAP64_DEV_MEM(mdev, header_modify_sw_icm_start_address);
205
206	caps->log_modify_pattern_icm_size =
207		MLX5_CAP_DEV_MEM(mdev, log_header_modify_pattern_sw_icm_size);
208
209	caps->hdr_modify_pattern_icm_addr =
210		MLX5_CAP64_DEV_MEM(mdev, header_modify_pattern_sw_icm_start_address);
211
212	caps->roce_min_src_udp = MLX5_CAP_ROCE(mdev, r_roce_min_src_udp_port);
213
214	caps->is_ecpf = mlx5_core_is_ecpf_esw_manager(mdev);
215
216	return 0;
217}
218
219int mlx5dr_cmd_query_flow_table(struct mlx5_core_dev *dev,
220				enum fs_flow_table_type type,
221				u32 table_id,
222				struct mlx5dr_cmd_query_flow_table_details *output)
223{
224	u32 out[MLX5_ST_SZ_DW(query_flow_table_out)] = {};
225	u32 in[MLX5_ST_SZ_DW(query_flow_table_in)] = {};
226	int err;
227
228	MLX5_SET(query_flow_table_in, in, opcode,
229		 MLX5_CMD_OP_QUERY_FLOW_TABLE);
230
231	MLX5_SET(query_flow_table_in, in, table_type, type);
232	MLX5_SET(query_flow_table_in, in, table_id, table_id);
233
234	err = mlx5_cmd_exec_inout(dev, query_flow_table, in, out);
235	if (err)
236		return err;
237
238	output->status = MLX5_GET(query_flow_table_out, out, status);
239	output->level = MLX5_GET(query_flow_table_out, out, flow_table_context.level);
240
241	output->sw_owner_icm_root_1 = MLX5_GET64(query_flow_table_out, out,
242						 flow_table_context.sws.sw_owner_icm_root_1);
243	output->sw_owner_icm_root_0 = MLX5_GET64(query_flow_table_out, out,
244						 flow_table_context.sws.sw_owner_icm_root_0);
245
246	return 0;
247}
248
249int mlx5dr_cmd_query_flow_sampler(struct mlx5_core_dev *dev,
250				  u32 sampler_id,
251				  u64 *rx_icm_addr,
252				  u64 *tx_icm_addr)
253{
254	u32 out[MLX5_ST_SZ_DW(query_sampler_obj_out)] = {};
255	u32 in[MLX5_ST_SZ_DW(general_obj_in_cmd_hdr)] = {};
256	void *attr;
257	int ret;
258
259	MLX5_SET(general_obj_in_cmd_hdr, in, opcode,
260		 MLX5_CMD_OP_QUERY_GENERAL_OBJECT);
261	MLX5_SET(general_obj_in_cmd_hdr, in, obj_type,
262		 MLX5_GENERAL_OBJECT_TYPES_SAMPLER);
263	MLX5_SET(general_obj_in_cmd_hdr, in, obj_id, sampler_id);
264
265	ret = mlx5_cmd_exec(dev, in, sizeof(in), out, sizeof(out));
266	if (ret)
267		return ret;
268
269	attr = MLX5_ADDR_OF(query_sampler_obj_out, out, sampler_object);
270
271	*rx_icm_addr = MLX5_GET64(sampler_obj, attr,
272				  sw_steering_icm_address_rx);
273	*tx_icm_addr = MLX5_GET64(sampler_obj, attr,
274				  sw_steering_icm_address_tx);
275
276	return 0;
277}
278
279int mlx5dr_cmd_sync_steering(struct mlx5_core_dev *mdev)
280{
281	u32 in[MLX5_ST_SZ_DW(sync_steering_in)] = {};
282
283	/* Skip SYNC in case the device is internal error state.
284	 * Besides a device error, this also happens when we're
285	 * in fast teardown
286	 */
287	if (mdev->state == MLX5_DEVICE_STATE_INTERNAL_ERROR)
288		return 0;
289
290	MLX5_SET(sync_steering_in, in, opcode, MLX5_CMD_OP_SYNC_STEERING);
291
292	return mlx5_cmd_exec_in(mdev, sync_steering, in);
293}
294
295int mlx5dr_cmd_set_fte_modify_and_vport(struct mlx5_core_dev *mdev,
296					u32 table_type,
297					u32 table_id,
298					u32 group_id,
299					u32 modify_header_id,
300					u16 vport)
301{
302	u32 out[MLX5_ST_SZ_DW(set_fte_out)] = {};
303	void *in_flow_context;
304	unsigned int inlen;
305	void *in_dests;
306	u32 *in;
307	int err;
308
309	inlen = MLX5_ST_SZ_BYTES(set_fte_in) +
310		1 * MLX5_ST_SZ_BYTES(dest_format_struct); /* One destination only */
311
312	in = kvzalloc(inlen, GFP_KERNEL);
313	if (!in)
314		return -ENOMEM;
315
316	MLX5_SET(set_fte_in, in, opcode, MLX5_CMD_OP_SET_FLOW_TABLE_ENTRY);
317	MLX5_SET(set_fte_in, in, table_type, table_type);
318	MLX5_SET(set_fte_in, in, table_id, table_id);
319
320	in_flow_context = MLX5_ADDR_OF(set_fte_in, in, flow_context);
321	MLX5_SET(flow_context, in_flow_context, group_id, group_id);
322	MLX5_SET(flow_context, in_flow_context, modify_header_id, modify_header_id);
323	MLX5_SET(flow_context, in_flow_context, destination_list_size, 1);
324	MLX5_SET(flow_context, in_flow_context, action,
325		 MLX5_FLOW_CONTEXT_ACTION_FWD_DEST |
326		 MLX5_FLOW_CONTEXT_ACTION_MOD_HDR);
327
328	in_dests = MLX5_ADDR_OF(flow_context, in_flow_context, destination);
329	MLX5_SET(dest_format_struct, in_dests, destination_type,
330		 MLX5_IFC_FLOW_DESTINATION_TYPE_VPORT);
331	MLX5_SET(dest_format_struct, in_dests, destination_id, vport);
332
333	err = mlx5_cmd_exec(mdev, in, inlen, out, sizeof(out));
334	kvfree(in);
335
336	return err;
337}
338
339int mlx5dr_cmd_del_flow_table_entry(struct mlx5_core_dev *mdev,
340				    u32 table_type,
341				    u32 table_id)
342{
343	u32 in[MLX5_ST_SZ_DW(delete_fte_in)] = {};
344
345	MLX5_SET(delete_fte_in, in, opcode, MLX5_CMD_OP_DELETE_FLOW_TABLE_ENTRY);
346	MLX5_SET(delete_fte_in, in, table_type, table_type);
347	MLX5_SET(delete_fte_in, in, table_id, table_id);
348
349	return mlx5_cmd_exec_in(mdev, delete_fte, in);
350}
351
352int mlx5dr_cmd_alloc_modify_header(struct mlx5_core_dev *mdev,
353				   u32 table_type,
354				   u8 num_of_actions,
355				   u64 *actions,
356				   u32 *modify_header_id)
357{
358	u32 out[MLX5_ST_SZ_DW(alloc_modify_header_context_out)] = {};
359	void *p_actions;
360	u32 inlen;
361	u32 *in;
362	int err;
363
364	inlen = MLX5_ST_SZ_BYTES(alloc_modify_header_context_in) +
365		 num_of_actions * sizeof(u64);
366	in = kvzalloc(inlen, GFP_KERNEL);
367	if (!in)
368		return -ENOMEM;
369
370	MLX5_SET(alloc_modify_header_context_in, in, opcode,
371		 MLX5_CMD_OP_ALLOC_MODIFY_HEADER_CONTEXT);
372	MLX5_SET(alloc_modify_header_context_in, in, table_type, table_type);
373	MLX5_SET(alloc_modify_header_context_in, in, num_of_actions, num_of_actions);
374	p_actions = MLX5_ADDR_OF(alloc_modify_header_context_in, in, actions);
375	memcpy(p_actions, actions, num_of_actions * sizeof(u64));
376
377	err = mlx5_cmd_exec(mdev, in, inlen, out, sizeof(out));
378	if (err)
379		goto out;
380
381	*modify_header_id = MLX5_GET(alloc_modify_header_context_out, out,
382				     modify_header_id);
383out:
384	kvfree(in);
385	return err;
386}
387
388int mlx5dr_cmd_dealloc_modify_header(struct mlx5_core_dev *mdev,
389				     u32 modify_header_id)
390{
391	u32 in[MLX5_ST_SZ_DW(dealloc_modify_header_context_in)] = {};
392
393	MLX5_SET(dealloc_modify_header_context_in, in, opcode,
394		 MLX5_CMD_OP_DEALLOC_MODIFY_HEADER_CONTEXT);
395	MLX5_SET(dealloc_modify_header_context_in, in, modify_header_id,
396		 modify_header_id);
397
398	return mlx5_cmd_exec_in(mdev, dealloc_modify_header_context, in);
399}
400
401int mlx5dr_cmd_create_empty_flow_group(struct mlx5_core_dev *mdev,
402				       u32 table_type,
403				       u32 table_id,
404				       u32 *group_id)
405{
406	u32 out[MLX5_ST_SZ_DW(create_flow_group_out)] = {};
407	int inlen = MLX5_ST_SZ_BYTES(create_flow_group_in);
408	u32 *in;
409	int err;
410
411	in = kvzalloc(inlen, GFP_KERNEL);
412	if (!in)
413		return -ENOMEM;
414
415	MLX5_SET(create_flow_group_in, in, opcode, MLX5_CMD_OP_CREATE_FLOW_GROUP);
416	MLX5_SET(create_flow_group_in, in, table_type, table_type);
417	MLX5_SET(create_flow_group_in, in, table_id, table_id);
418
419	err = mlx5_cmd_exec_inout(mdev, create_flow_group, in, out);
420	if (err)
421		goto out;
422
423	*group_id = MLX5_GET(create_flow_group_out, out, group_id);
424
425out:
426	kvfree(in);
427	return err;
428}
429
430int mlx5dr_cmd_destroy_flow_group(struct mlx5_core_dev *mdev,
431				  u32 table_type,
432				  u32 table_id,
433				  u32 group_id)
434{
435	u32 in[MLX5_ST_SZ_DW(destroy_flow_group_in)] = {};
436
437	MLX5_SET(destroy_flow_group_in, in, opcode,
438		 MLX5_CMD_OP_DESTROY_FLOW_GROUP);
439	MLX5_SET(destroy_flow_group_in, in, table_type, table_type);
440	MLX5_SET(destroy_flow_group_in, in, table_id, table_id);
441	MLX5_SET(destroy_flow_group_in, in, group_id, group_id);
442
443	return mlx5_cmd_exec_in(mdev, destroy_flow_group, in);
444}
445
446int mlx5dr_cmd_create_flow_table(struct mlx5_core_dev *mdev,
447				 struct mlx5dr_cmd_create_flow_table_attr *attr,
448				 u64 *fdb_rx_icm_addr,
449				 u32 *table_id)
450{
451	u32 out[MLX5_ST_SZ_DW(create_flow_table_out)] = {};
452	u32 in[MLX5_ST_SZ_DW(create_flow_table_in)] = {};
453	void *ft_mdev;
454	int err;
455
456	MLX5_SET(create_flow_table_in, in, opcode, MLX5_CMD_OP_CREATE_FLOW_TABLE);
457	MLX5_SET(create_flow_table_in, in, table_type, attr->table_type);
458	MLX5_SET(create_flow_table_in, in, uid, attr->uid);
459
460	ft_mdev = MLX5_ADDR_OF(create_flow_table_in, in, flow_table_context);
461	MLX5_SET(flow_table_context, ft_mdev, termination_table, attr->term_tbl);
462	MLX5_SET(flow_table_context, ft_mdev, sw_owner, attr->sw_owner);
463	MLX5_SET(flow_table_context, ft_mdev, level, attr->level);
464
465	if (attr->sw_owner) {
466		/* icm_addr_0 used for FDB RX / NIC TX / NIC_RX
467		 * icm_addr_1 used for FDB TX
468		 */
469		if (attr->table_type == MLX5_FLOW_TABLE_TYPE_NIC_RX) {
470			MLX5_SET64(flow_table_context, ft_mdev,
471				   sws.sw_owner_icm_root_0, attr->icm_addr_rx);
472		} else if (attr->table_type == MLX5_FLOW_TABLE_TYPE_NIC_TX) {
473			MLX5_SET64(flow_table_context, ft_mdev,
474				   sws.sw_owner_icm_root_0, attr->icm_addr_tx);
475		} else if (attr->table_type == MLX5_FLOW_TABLE_TYPE_FDB) {
476			MLX5_SET64(flow_table_context, ft_mdev,
477				   sws.sw_owner_icm_root_0, attr->icm_addr_rx);
478			MLX5_SET64(flow_table_context, ft_mdev,
479				   sws.sw_owner_icm_root_1, attr->icm_addr_tx);
480		}
481	}
482
483	MLX5_SET(create_flow_table_in, in, flow_table_context.decap_en,
484		 attr->decap_en);
485	MLX5_SET(create_flow_table_in, in, flow_table_context.reformat_en,
486		 attr->reformat_en);
487
488	err = mlx5_cmd_exec_inout(mdev, create_flow_table, in, out);
489	if (err)
490		return err;
491
492	*table_id = MLX5_GET(create_flow_table_out, out, table_id);
493	if (!attr->sw_owner && attr->table_type == MLX5_FLOW_TABLE_TYPE_FDB &&
494	    fdb_rx_icm_addr)
495		*fdb_rx_icm_addr =
496		(u64)MLX5_GET(create_flow_table_out, out, icm_address_31_0) |
497		(u64)MLX5_GET(create_flow_table_out, out, icm_address_39_32) << 32 |
498		(u64)MLX5_GET(create_flow_table_out, out, icm_address_63_40) << 40;
499
500	return 0;
501}
502
503int mlx5dr_cmd_destroy_flow_table(struct mlx5_core_dev *mdev,
504				  u32 table_id,
505				  u32 table_type)
506{
507	u32 in[MLX5_ST_SZ_DW(destroy_flow_table_in)] = {};
508
509	MLX5_SET(destroy_flow_table_in, in, opcode,
510		 MLX5_CMD_OP_DESTROY_FLOW_TABLE);
511	MLX5_SET(destroy_flow_table_in, in, table_type, table_type);
512	MLX5_SET(destroy_flow_table_in, in, table_id, table_id);
513
514	return mlx5_cmd_exec_in(mdev, destroy_flow_table, in);
515}
516
517int mlx5dr_cmd_create_reformat_ctx(struct mlx5_core_dev *mdev,
518				   enum mlx5_reformat_ctx_type rt,
519				   u8 reformat_param_0,
520				   u8 reformat_param_1,
521				   size_t reformat_size,
522				   void *reformat_data,
523				   u32 *reformat_id)
524{
525	u32 out[MLX5_ST_SZ_DW(alloc_packet_reformat_context_out)] = {};
526	size_t inlen, cmd_data_sz, cmd_total_sz;
527	void *prctx;
528	void *pdata;
529	void *in;
530	int err;
531
532	cmd_total_sz = MLX5_ST_SZ_BYTES(alloc_packet_reformat_context_in);
533	cmd_data_sz = MLX5_FLD_SZ_BYTES(alloc_packet_reformat_context_in,
534					packet_reformat_context.reformat_data);
535	inlen = ALIGN(cmd_total_sz + reformat_size - cmd_data_sz, 4);
536	in = kvzalloc(inlen, GFP_KERNEL);
537	if (!in)
538		return -ENOMEM;
539
540	MLX5_SET(alloc_packet_reformat_context_in, in, opcode,
541		 MLX5_CMD_OP_ALLOC_PACKET_REFORMAT_CONTEXT);
542
543	prctx = MLX5_ADDR_OF(alloc_packet_reformat_context_in, in, packet_reformat_context);
544	pdata = MLX5_ADDR_OF(packet_reformat_context_in, prctx, reformat_data);
545
546	MLX5_SET(packet_reformat_context_in, prctx, reformat_type, rt);
547	MLX5_SET(packet_reformat_context_in, prctx, reformat_param_0, reformat_param_0);
548	MLX5_SET(packet_reformat_context_in, prctx, reformat_param_1, reformat_param_1);
549	MLX5_SET(packet_reformat_context_in, prctx, reformat_data_size, reformat_size);
550	if (reformat_data && reformat_size)
551		memcpy(pdata, reformat_data, reformat_size);
552
553	err = mlx5_cmd_exec(mdev, in, inlen, out, sizeof(out));
554	if (err)
555		goto err_free_in;
556
557	*reformat_id = MLX5_GET(alloc_packet_reformat_context_out, out, packet_reformat_id);
558
559err_free_in:
560	kvfree(in);
561	return err;
562}
563
564void mlx5dr_cmd_destroy_reformat_ctx(struct mlx5_core_dev *mdev,
565				     u32 reformat_id)
566{
567	u32 in[MLX5_ST_SZ_DW(dealloc_packet_reformat_context_in)] = {};
568
569	MLX5_SET(dealloc_packet_reformat_context_in, in, opcode,
570		 MLX5_CMD_OP_DEALLOC_PACKET_REFORMAT_CONTEXT);
571	MLX5_SET(dealloc_packet_reformat_context_in, in, packet_reformat_id,
572		 reformat_id);
573
574	mlx5_cmd_exec_in(mdev, dealloc_packet_reformat_context, in);
575}
576
577static void dr_cmd_set_definer_format(void *ptr, u16 format_id,
578				      u8 *dw_selectors,
579				      u8 *byte_selectors)
580{
581	if (format_id != MLX5_IFC_DEFINER_FORMAT_ID_SELECT)
582		return;
583
584	MLX5_SET(match_definer, ptr, format_select_dw0, dw_selectors[0]);
585	MLX5_SET(match_definer, ptr, format_select_dw1, dw_selectors[1]);
586	MLX5_SET(match_definer, ptr, format_select_dw2, dw_selectors[2]);
587	MLX5_SET(match_definer, ptr, format_select_dw3, dw_selectors[3]);
588	MLX5_SET(match_definer, ptr, format_select_dw4, dw_selectors[4]);
589	MLX5_SET(match_definer, ptr, format_select_dw5, dw_selectors[5]);
590	MLX5_SET(match_definer, ptr, format_select_dw6, dw_selectors[6]);
591	MLX5_SET(match_definer, ptr, format_select_dw7, dw_selectors[7]);
592	MLX5_SET(match_definer, ptr, format_select_dw8, dw_selectors[8]);
593
594	MLX5_SET(match_definer, ptr, format_select_byte0, byte_selectors[0]);
595	MLX5_SET(match_definer, ptr, format_select_byte1, byte_selectors[1]);
596	MLX5_SET(match_definer, ptr, format_select_byte2, byte_selectors[2]);
597	MLX5_SET(match_definer, ptr, format_select_byte3, byte_selectors[3]);
598	MLX5_SET(match_definer, ptr, format_select_byte4, byte_selectors[4]);
599	MLX5_SET(match_definer, ptr, format_select_byte5, byte_selectors[5]);
600	MLX5_SET(match_definer, ptr, format_select_byte6, byte_selectors[6]);
601	MLX5_SET(match_definer, ptr, format_select_byte7, byte_selectors[7]);
602}
603
604int mlx5dr_cmd_create_definer(struct mlx5_core_dev *mdev,
605			      u16 format_id,
606			      u8 *dw_selectors,
607			      u8 *byte_selectors,
608			      u8 *match_mask,
609			      u32 *definer_id)
610{
611	u32 out[MLX5_ST_SZ_DW(general_obj_out_cmd_hdr)] = {};
612	u32 in[MLX5_ST_SZ_DW(create_match_definer_in)] = {};
613	void *ptr;
614	int err;
615
616	ptr = MLX5_ADDR_OF(create_match_definer_in, in,
617			   general_obj_in_cmd_hdr);
618	MLX5_SET(general_obj_in_cmd_hdr, ptr, opcode,
619		 MLX5_CMD_OP_CREATE_GENERAL_OBJECT);
620	MLX5_SET(general_obj_in_cmd_hdr, ptr, obj_type,
621		 MLX5_OBJ_TYPE_MATCH_DEFINER);
622
623	ptr = MLX5_ADDR_OF(create_match_definer_in, in, obj_context);
624	MLX5_SET(match_definer, ptr, format_id, format_id);
625
626	dr_cmd_set_definer_format(ptr, format_id,
627				  dw_selectors, byte_selectors);
628
629	ptr = MLX5_ADDR_OF(match_definer, ptr, match_mask);
630	memcpy(ptr, match_mask, MLX5_FLD_SZ_BYTES(match_definer, match_mask));
631
632	err = mlx5_cmd_exec(mdev, in, sizeof(in), out, sizeof(out));
633	if (err)
634		return err;
635
636	*definer_id = MLX5_GET(general_obj_out_cmd_hdr, out, obj_id);
637
638	return 0;
639}
640
641void
642mlx5dr_cmd_destroy_definer(struct mlx5_core_dev *mdev, u32 definer_id)
643{
644	u32 in[MLX5_ST_SZ_DW(general_obj_in_cmd_hdr)] = {};
645	u32 out[MLX5_ST_SZ_DW(general_obj_out_cmd_hdr)];
646
647	MLX5_SET(general_obj_in_cmd_hdr, in, opcode, MLX5_CMD_OP_DESTROY_GENERAL_OBJECT);
648	MLX5_SET(general_obj_in_cmd_hdr, in, obj_type, MLX5_OBJ_TYPE_MATCH_DEFINER);
649	MLX5_SET(general_obj_in_cmd_hdr, in, obj_id, definer_id);
650
651	mlx5_cmd_exec(mdev, in, sizeof(in), out, sizeof(out));
652}
653
654int mlx5dr_cmd_query_gid(struct mlx5_core_dev *mdev, u8 vhca_port_num,
655			 u16 index, struct mlx5dr_cmd_gid_attr *attr)
656{
657	u32 out[MLX5_ST_SZ_DW(query_roce_address_out)] = {};
658	u32 in[MLX5_ST_SZ_DW(query_roce_address_in)] = {};
659	int err;
660
661	MLX5_SET(query_roce_address_in, in, opcode,
662		 MLX5_CMD_OP_QUERY_ROCE_ADDRESS);
663
664	MLX5_SET(query_roce_address_in, in, roce_address_index, index);
665	MLX5_SET(query_roce_address_in, in, vhca_port_num, vhca_port_num);
666
667	err = mlx5_cmd_exec_inout(mdev, query_roce_address, in, out);
668	if (err)
669		return err;
670
671	memcpy(&attr->gid,
672	       MLX5_ADDR_OF(query_roce_address_out,
673			    out, roce_address.source_l3_address),
674	       sizeof(attr->gid));
675	memcpy(attr->mac,
676	       MLX5_ADDR_OF(query_roce_address_out, out,
677			    roce_address.source_mac_47_32),
678	       sizeof(attr->mac));
679
680	if (MLX5_GET(query_roce_address_out, out,
681		     roce_address.roce_version) == MLX5_ROCE_VERSION_2)
682		attr->roce_ver = MLX5_ROCE_VERSION_2;
683	else
684		attr->roce_ver = MLX5_ROCE_VERSION_1;
685
686	return 0;
687}
688
689int mlx5dr_cmd_create_modify_header_arg(struct mlx5_core_dev *dev,
690					u16 log_obj_range, u32 pd,
691					u32 *obj_id)
692{
693	u32 in[MLX5_ST_SZ_DW(create_modify_header_arg_in)] = {};
694	u32 out[MLX5_ST_SZ_DW(general_obj_out_cmd_hdr)] = {};
695	void *attr;
696	int ret;
697
698	attr = MLX5_ADDR_OF(create_modify_header_arg_in, in, hdr);
699	MLX5_SET(general_obj_in_cmd_hdr, attr, opcode,
700		 MLX5_CMD_OP_CREATE_GENERAL_OBJECT);
701	MLX5_SET(general_obj_in_cmd_hdr, attr, obj_type,
702		 MLX5_OBJ_TYPE_HEADER_MODIFY_ARGUMENT);
703	MLX5_SET(general_obj_in_cmd_hdr, attr,
704		 op_param.create.log_obj_range, log_obj_range);
705
706	attr = MLX5_ADDR_OF(create_modify_header_arg_in, in, arg);
707	MLX5_SET(modify_header_arg, attr, access_pd, pd);
708
709	ret = mlx5_cmd_exec(dev, in, sizeof(in), out, sizeof(out));
710	if (ret)
711		return ret;
712
713	*obj_id = MLX5_GET(general_obj_out_cmd_hdr, out, obj_id);
714	return 0;
715}
716
717void mlx5dr_cmd_destroy_modify_header_arg(struct mlx5_core_dev *dev,
718					  u32 obj_id)
719{
720	u32 out[MLX5_ST_SZ_DW(general_obj_out_cmd_hdr)] = {};
721	u32 in[MLX5_ST_SZ_DW(general_obj_in_cmd_hdr)] = {};
722
723	MLX5_SET(general_obj_in_cmd_hdr, in, opcode,
724		 MLX5_CMD_OP_DESTROY_GENERAL_OBJECT);
725	MLX5_SET(general_obj_in_cmd_hdr, in, obj_type,
726		 MLX5_OBJ_TYPE_HEADER_MODIFY_ARGUMENT);
727	MLX5_SET(general_obj_in_cmd_hdr, in, obj_id, obj_id);
728
729	mlx5_cmd_exec(dev, in, sizeof(in), out, sizeof(out));
730}
731
732static int mlx5dr_cmd_set_extended_dest(struct mlx5_core_dev *dev,
733					struct mlx5dr_cmd_fte_info *fte,
734					bool *extended_dest)
735{
736	int fw_log_max_fdb_encap_uplink = MLX5_CAP_ESW(dev, log_max_fdb_encap_uplink);
737	int num_fwd_destinations = 0;
738	int num_encap = 0;
739	int i;
740
741	*extended_dest = false;
742	if (!(fte->action.action & MLX5_FLOW_CONTEXT_ACTION_FWD_DEST))
743		return 0;
744	for (i = 0; i < fte->dests_size; i++) {
745		if (fte->dest_arr[i].type == MLX5_FLOW_DESTINATION_TYPE_COUNTER ||
746		    fte->dest_arr[i].type == MLX5_FLOW_DESTINATION_TYPE_NONE)
747			continue;
748		if ((fte->dest_arr[i].type == MLX5_FLOW_DESTINATION_TYPE_VPORT ||
749		     fte->dest_arr[i].type == MLX5_FLOW_DESTINATION_TYPE_UPLINK) &&
750		    fte->dest_arr[i].vport.flags & MLX5_FLOW_DEST_VPORT_REFORMAT_ID)
751			num_encap++;
752		num_fwd_destinations++;
753	}
754
755	if (num_fwd_destinations > 1 && num_encap > 0)
756		*extended_dest = true;
757
758	if (*extended_dest && !fw_log_max_fdb_encap_uplink) {
759		mlx5_core_warn(dev, "FW does not support extended destination");
760		return -EOPNOTSUPP;
761	}
762	if (num_encap > (1 << fw_log_max_fdb_encap_uplink)) {
763		mlx5_core_warn(dev, "FW does not support more than %d encaps",
764			       1 << fw_log_max_fdb_encap_uplink);
765		return -EOPNOTSUPP;
766	}
767
768	return 0;
769}
770
771int mlx5dr_cmd_set_fte(struct mlx5_core_dev *dev,
772		       int opmod, int modify_mask,
773		       struct mlx5dr_cmd_ft_info *ft,
774		       u32 group_id,
775		       struct mlx5dr_cmd_fte_info *fte)
776{
777	u32 out[MLX5_ST_SZ_DW(set_fte_out)] = {};
778	void *in_flow_context, *vlan;
779	bool extended_dest = false;
780	void *in_match_value;
781	unsigned int inlen;
782	int dst_cnt_size;
783	void *in_dests;
784	u32 *in;
785	int err;
786	int i;
787
788	if (mlx5dr_cmd_set_extended_dest(dev, fte, &extended_dest))
789		return -EOPNOTSUPP;
790
791	if (!extended_dest)
792		dst_cnt_size = MLX5_ST_SZ_BYTES(dest_format_struct);
793	else
794		dst_cnt_size = MLX5_ST_SZ_BYTES(extended_dest_format);
795
796	inlen = MLX5_ST_SZ_BYTES(set_fte_in) + fte->dests_size * dst_cnt_size;
797	in = kvzalloc(inlen, GFP_KERNEL);
798	if (!in)
799		return -ENOMEM;
800
801	MLX5_SET(set_fte_in, in, opcode, MLX5_CMD_OP_SET_FLOW_TABLE_ENTRY);
802	MLX5_SET(set_fte_in, in, op_mod, opmod);
803	MLX5_SET(set_fte_in, in, modify_enable_mask, modify_mask);
804	MLX5_SET(set_fte_in, in, table_type, ft->type);
805	MLX5_SET(set_fte_in, in, table_id, ft->id);
806	MLX5_SET(set_fte_in, in, flow_index, fte->index);
807	MLX5_SET(set_fte_in, in, ignore_flow_level, fte->ignore_flow_level);
808	if (ft->vport) {
809		MLX5_SET(set_fte_in, in, vport_number, ft->vport);
810		MLX5_SET(set_fte_in, in, other_vport, 1);
811	}
812
813	in_flow_context = MLX5_ADDR_OF(set_fte_in, in, flow_context);
814	MLX5_SET(flow_context, in_flow_context, group_id, group_id);
815
816	MLX5_SET(flow_context, in_flow_context, flow_tag,
817		 fte->flow_context.flow_tag);
818	MLX5_SET(flow_context, in_flow_context, flow_source,
819		 fte->flow_context.flow_source);
820
821	MLX5_SET(flow_context, in_flow_context, extended_destination,
822		 extended_dest);
823	if (extended_dest) {
824		u32 action;
825
826		action = fte->action.action &
827			~MLX5_FLOW_CONTEXT_ACTION_PACKET_REFORMAT;
828		MLX5_SET(flow_context, in_flow_context, action, action);
829	} else {
830		MLX5_SET(flow_context, in_flow_context, action,
831			 fte->action.action);
832		if (fte->action.pkt_reformat)
833			MLX5_SET(flow_context, in_flow_context, packet_reformat_id,
834				 fte->action.pkt_reformat->id);
835	}
836	if (fte->action.modify_hdr)
837		MLX5_SET(flow_context, in_flow_context, modify_header_id,
838			 fte->action.modify_hdr->id);
839
840	vlan = MLX5_ADDR_OF(flow_context, in_flow_context, push_vlan);
841
842	MLX5_SET(vlan, vlan, ethtype, fte->action.vlan[0].ethtype);
843	MLX5_SET(vlan, vlan, vid, fte->action.vlan[0].vid);
844	MLX5_SET(vlan, vlan, prio, fte->action.vlan[0].prio);
845
846	vlan = MLX5_ADDR_OF(flow_context, in_flow_context, push_vlan_2);
847
848	MLX5_SET(vlan, vlan, ethtype, fte->action.vlan[1].ethtype);
849	MLX5_SET(vlan, vlan, vid, fte->action.vlan[1].vid);
850	MLX5_SET(vlan, vlan, prio, fte->action.vlan[1].prio);
851
852	in_match_value = MLX5_ADDR_OF(flow_context, in_flow_context,
853				      match_value);
854	memcpy(in_match_value, fte->val, sizeof(u32) * MLX5_ST_SZ_DW_MATCH_PARAM);
855
856	in_dests = MLX5_ADDR_OF(flow_context, in_flow_context, destination);
857	if (fte->action.action & MLX5_FLOW_CONTEXT_ACTION_FWD_DEST) {
858		int list_size = 0;
859
860		for (i = 0; i < fte->dests_size; i++) {
861			enum mlx5_flow_destination_type type = fte->dest_arr[i].type;
862			enum mlx5_ifc_flow_destination_type ifc_type;
863			unsigned int id;
864
865			if (type == MLX5_FLOW_DESTINATION_TYPE_COUNTER)
866				continue;
867
868			switch (type) {
869			case MLX5_FLOW_DESTINATION_TYPE_NONE:
870				continue;
871			case MLX5_FLOW_DESTINATION_TYPE_FLOW_TABLE_NUM:
872				id = fte->dest_arr[i].ft_num;
873				ifc_type = MLX5_IFC_FLOW_DESTINATION_TYPE_FLOW_TABLE;
874				break;
875			case MLX5_FLOW_DESTINATION_TYPE_FLOW_TABLE:
876				id = fte->dest_arr[i].ft_id;
877				ifc_type = MLX5_IFC_FLOW_DESTINATION_TYPE_FLOW_TABLE;
878
879				break;
880			case MLX5_FLOW_DESTINATION_TYPE_UPLINK:
881			case MLX5_FLOW_DESTINATION_TYPE_VPORT:
882				if (type == MLX5_FLOW_DESTINATION_TYPE_VPORT) {
883					id = fte->dest_arr[i].vport.num;
884					MLX5_SET(dest_format_struct, in_dests,
885						 destination_eswitch_owner_vhca_id_valid,
886						 !!(fte->dest_arr[i].vport.flags &
887						    MLX5_FLOW_DEST_VPORT_VHCA_ID));
888					ifc_type = MLX5_IFC_FLOW_DESTINATION_TYPE_VPORT;
889				} else {
890					id = 0;
891					ifc_type = MLX5_IFC_FLOW_DESTINATION_TYPE_UPLINK;
892					MLX5_SET(dest_format_struct, in_dests,
893						 destination_eswitch_owner_vhca_id_valid, 1);
894				}
895				MLX5_SET(dest_format_struct, in_dests,
896					 destination_eswitch_owner_vhca_id,
897					 fte->dest_arr[i].vport.vhca_id);
898				if (extended_dest && (fte->dest_arr[i].vport.flags &
899						    MLX5_FLOW_DEST_VPORT_REFORMAT_ID)) {
900					MLX5_SET(dest_format_struct, in_dests,
901						 packet_reformat,
902						 !!(fte->dest_arr[i].vport.flags &
903						    MLX5_FLOW_DEST_VPORT_REFORMAT_ID));
904					MLX5_SET(extended_dest_format, in_dests,
905						 packet_reformat_id,
906						 fte->dest_arr[i].vport.reformat_id);
907				}
908				break;
909			case MLX5_FLOW_DESTINATION_TYPE_FLOW_SAMPLER:
910				id = fte->dest_arr[i].sampler_id;
911				ifc_type = MLX5_IFC_FLOW_DESTINATION_TYPE_FLOW_SAMPLER;
912				break;
913			default:
914				id = fte->dest_arr[i].tir_num;
915				ifc_type = MLX5_IFC_FLOW_DESTINATION_TYPE_TIR;
916			}
917
918			MLX5_SET(dest_format_struct, in_dests, destination_type,
919				 ifc_type);
920			MLX5_SET(dest_format_struct, in_dests, destination_id, id);
921			in_dests += dst_cnt_size;
922			list_size++;
923		}
924
925		MLX5_SET(flow_context, in_flow_context, destination_list_size,
926			 list_size);
927	}
928
929	if (fte->action.action & MLX5_FLOW_CONTEXT_ACTION_COUNT) {
930		int max_list_size = BIT(MLX5_CAP_FLOWTABLE_TYPE(dev,
931					log_max_flow_counter,
932					ft->type));
933		int list_size = 0;
934
935		for (i = 0; i < fte->dests_size; i++) {
936			if (fte->dest_arr[i].type !=
937			    MLX5_FLOW_DESTINATION_TYPE_COUNTER)
938				continue;
939
940			MLX5_SET(flow_counter_list, in_dests, flow_counter_id,
941				 fte->dest_arr[i].counter_id);
942			in_dests += dst_cnt_size;
943			list_size++;
944		}
945		if (list_size > max_list_size) {
946			err = -EINVAL;
947			goto err_out;
948		}
949
950		MLX5_SET(flow_context, in_flow_context, flow_counter_list_size,
951			 list_size);
952	}
953
954	err = mlx5_cmd_exec(dev, in, inlen, out, sizeof(out));
955err_out:
956	kvfree(in);
957	return err;
958}
~/ Read-only file preview.