1 // SPDX-License-Identifier: GPL-2.0 OR Linux-OpenIB
2 /* Copyright (c) 2019 Mellanox Technologies. */
3 
4 #include "dr_types.h"
5 
mlx5dr_cmd_query_esw_vport_context(struct mlx5_core_dev * mdev,bool other_vport,u16 vport_number,u64 * icm_address_rx,u64 * icm_address_tx)6 int mlx5dr_cmd_query_esw_vport_context(struct mlx5_core_dev *mdev,
7 				       bool other_vport,
8 				       u16 vport_number,
9 				       u64 *icm_address_rx,
10 				       u64 *icm_address_tx)
11 {
12 	u32 out[MLX5_ST_SZ_DW(query_esw_vport_context_out)] = {};
13 	u32 in[MLX5_ST_SZ_DW(query_esw_vport_context_in)] = {};
14 	int err;
15 
16 	MLX5_SET(query_esw_vport_context_in, in, opcode,
17 		 MLX5_CMD_OP_QUERY_ESW_VPORT_CONTEXT);
18 	MLX5_SET(query_esw_vport_context_in, in, other_vport, other_vport);
19 	MLX5_SET(query_esw_vport_context_in, in, vport_number, vport_number);
20 
21 	err = mlx5_cmd_exec(mdev, in, sizeof(in), out, sizeof(out));
22 	if (err)
23 		return err;
24 
25 	*icm_address_rx =
26 		MLX5_GET64(query_esw_vport_context_out, out,
27 			   esw_vport_context.sw_steering_vport_icm_address_rx);
28 	*icm_address_tx =
29 		MLX5_GET64(query_esw_vport_context_out, out,
30 			   esw_vport_context.sw_steering_vport_icm_address_tx);
31 	return 0;
32 }
33 
mlx5dr_cmd_query_gvmi(struct mlx5_core_dev * mdev,bool other_vport,u16 vport_number,u16 * gvmi)34 int mlx5dr_cmd_query_gvmi(struct mlx5_core_dev *mdev, bool other_vport,
35 			  u16 vport_number, u16 *gvmi)
36 {
37 	u32 in[MLX5_ST_SZ_DW(query_hca_cap_in)] = {};
38 	int out_size;
39 	void *out;
40 	int err;
41 
42 	out_size = MLX5_ST_SZ_BYTES(query_hca_cap_out);
43 	out = kzalloc(out_size, GFP_KERNEL);
44 	if (!out)
45 		return -ENOMEM;
46 
47 	MLX5_SET(query_hca_cap_in, in, opcode, MLX5_CMD_OP_QUERY_HCA_CAP);
48 	MLX5_SET(query_hca_cap_in, in, other_function, other_vport);
49 	MLX5_SET(query_hca_cap_in, in, function_id, vport_number);
50 	MLX5_SET(query_hca_cap_in, in, op_mod,
51 		 MLX5_SET_HCA_CAP_OP_MOD_GENERAL_DEVICE << 1 |
52 		 HCA_CAP_OPMOD_GET_CUR);
53 
54 	err = mlx5_cmd_exec(mdev, in, sizeof(in), out, out_size);
55 	if (err) {
56 		kfree(out);
57 		return err;
58 	}
59 
60 	*gvmi = MLX5_GET(query_hca_cap_out, out, capability.cmd_hca_cap.vhca_id);
61 
62 	kfree(out);
63 	return 0;
64 }
65 
mlx5dr_cmd_query_esw_caps(struct mlx5_core_dev * mdev,struct mlx5dr_esw_caps * caps)66 int mlx5dr_cmd_query_esw_caps(struct mlx5_core_dev *mdev,
67 			      struct mlx5dr_esw_caps *caps)
68 {
69 	caps->drop_icm_address_rx =
70 		MLX5_CAP64_ESW_FLOWTABLE(mdev,
71 					 sw_steering_fdb_action_drop_icm_address_rx);
72 	caps->drop_icm_address_tx =
73 		MLX5_CAP64_ESW_FLOWTABLE(mdev,
74 					 sw_steering_fdb_action_drop_icm_address_tx);
75 	caps->uplink_icm_address_rx =
76 		MLX5_CAP64_ESW_FLOWTABLE(mdev,
77 					 sw_steering_uplink_icm_address_rx);
78 	caps->uplink_icm_address_tx =
79 		MLX5_CAP64_ESW_FLOWTABLE(mdev,
80 					 sw_steering_uplink_icm_address_tx);
81 	caps->sw_owner =
82 		MLX5_CAP_ESW_FLOWTABLE_FDB(mdev,
83 					   sw_owner);
84 
85 	return 0;
86 }
87 
mlx5dr_cmd_query_device(struct mlx5_core_dev * mdev,struct mlx5dr_cmd_caps * caps)88 int mlx5dr_cmd_query_device(struct mlx5_core_dev *mdev,
89 			    struct mlx5dr_cmd_caps *caps)
90 {
91 	caps->prio_tag_required	= MLX5_CAP_GEN(mdev, prio_tag_required);
92 	caps->eswitch_manager	= MLX5_CAP_GEN(mdev, eswitch_manager);
93 	caps->gvmi		= MLX5_CAP_GEN(mdev, vhca_id);
94 	caps->flex_protocols	= MLX5_CAP_GEN(mdev, flex_parser_protocols);
95 
96 	if (mlx5dr_matcher_supp_flex_parser_icmp_v4(caps)) {
97 		caps->flex_parser_id_icmp_dw0 = MLX5_CAP_GEN(mdev, flex_parser_id_icmp_dw0);
98 		caps->flex_parser_id_icmp_dw1 = MLX5_CAP_GEN(mdev, flex_parser_id_icmp_dw1);
99 	}
100 
101 	if (mlx5dr_matcher_supp_flex_parser_icmp_v6(caps)) {
102 		caps->flex_parser_id_icmpv6_dw0 =
103 			MLX5_CAP_GEN(mdev, flex_parser_id_icmpv6_dw0);
104 		caps->flex_parser_id_icmpv6_dw1 =
105 			MLX5_CAP_GEN(mdev, flex_parser_id_icmpv6_dw1);
106 	}
107 
108 	caps->nic_rx_drop_address =
109 		MLX5_CAP64_FLOWTABLE(mdev, sw_steering_nic_rx_action_drop_icm_address);
110 	caps->nic_tx_drop_address =
111 		MLX5_CAP64_FLOWTABLE(mdev, sw_steering_nic_tx_action_drop_icm_address);
112 	caps->nic_tx_allow_address =
113 		MLX5_CAP64_FLOWTABLE(mdev, sw_steering_nic_tx_action_allow_icm_address);
114 
115 	caps->rx_sw_owner = MLX5_CAP_FLOWTABLE_NIC_RX(mdev, sw_owner);
116 	caps->max_ft_level = MLX5_CAP_FLOWTABLE_NIC_RX(mdev, max_ft_level);
117 
118 	caps->tx_sw_owner = MLX5_CAP_FLOWTABLE_NIC_TX(mdev, sw_owner);
119 
120 	caps->log_icm_size = MLX5_CAP_DEV_MEM(mdev, log_steering_sw_icm_size);
121 	caps->hdr_modify_icm_addr =
122 		MLX5_CAP64_DEV_MEM(mdev, header_modify_sw_icm_start_address);
123 
124 	caps->roce_min_src_udp = MLX5_CAP_ROCE(mdev, r_roce_min_src_udp_port);
125 
126 	return 0;
127 }
128 
mlx5dr_cmd_query_flow_table(struct mlx5_core_dev * dev,enum fs_flow_table_type type,u32 table_id,struct mlx5dr_cmd_query_flow_table_details * output)129 int mlx5dr_cmd_query_flow_table(struct mlx5_core_dev *dev,
130 				enum fs_flow_table_type type,
131 				u32 table_id,
132 				struct mlx5dr_cmd_query_flow_table_details *output)
133 {
134 	u32 out[MLX5_ST_SZ_DW(query_flow_table_out)] = {};
135 	u32 in[MLX5_ST_SZ_DW(query_flow_table_in)] = {};
136 	int err;
137 
138 	MLX5_SET(query_flow_table_in, in, opcode,
139 		 MLX5_CMD_OP_QUERY_FLOW_TABLE);
140 
141 	MLX5_SET(query_flow_table_in, in, table_type, type);
142 	MLX5_SET(query_flow_table_in, in, table_id, table_id);
143 
144 	err = mlx5_cmd_exec(dev, in, sizeof(in), out, sizeof(out));
145 	if (err)
146 		return err;
147 
148 	output->status = MLX5_GET(query_flow_table_out, out, status);
149 	output->level = MLX5_GET(query_flow_table_out, out, flow_table_context.level);
150 
151 	output->sw_owner_icm_root_1 = MLX5_GET64(query_flow_table_out, out,
152 						 flow_table_context.sw_owner_icm_root_1);
153 	output->sw_owner_icm_root_0 = MLX5_GET64(query_flow_table_out, out,
154 						 flow_table_context.sw_owner_icm_root_0);
155 
156 	return 0;
157 }
158 
mlx5dr_cmd_sync_steering(struct mlx5_core_dev * mdev)159 int mlx5dr_cmd_sync_steering(struct mlx5_core_dev *mdev)
160 {
161 	u32 out[MLX5_ST_SZ_DW(sync_steering_out)] = {};
162 	u32 in[MLX5_ST_SZ_DW(sync_steering_in)] = {};
163 
164 	MLX5_SET(sync_steering_in, in, opcode, MLX5_CMD_OP_SYNC_STEERING);
165 
166 	return mlx5_cmd_exec(mdev, in, sizeof(in), out, sizeof(out));
167 }
168 
mlx5dr_cmd_set_fte_modify_and_vport(struct mlx5_core_dev * mdev,u32 table_type,u32 table_id,u32 group_id,u32 modify_header_id,u32 vport_id)169 int mlx5dr_cmd_set_fte_modify_and_vport(struct mlx5_core_dev *mdev,
170 					u32 table_type,
171 					u32 table_id,
172 					u32 group_id,
173 					u32 modify_header_id,
174 					u32 vport_id)
175 {
176 	u32 out[MLX5_ST_SZ_DW(set_fte_out)] = {};
177 	void *in_flow_context;
178 	unsigned int inlen;
179 	void *in_dests;
180 	u32 *in;
181 	int err;
182 
183 	inlen = MLX5_ST_SZ_BYTES(set_fte_in) +
184 		1 * MLX5_ST_SZ_BYTES(dest_format_struct); /* One destination only */
185 
186 	in = kvzalloc(inlen, GFP_KERNEL);
187 	if (!in)
188 		return -ENOMEM;
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, modify_header_id, modify_header_id);
197 	MLX5_SET(flow_context, in_flow_context, destination_list_size, 1);
198 	MLX5_SET(flow_context, in_flow_context, action,
199 		 MLX5_FLOW_CONTEXT_ACTION_FWD_DEST |
200 		 MLX5_FLOW_CONTEXT_ACTION_MOD_HDR);
201 
202 	in_dests = MLX5_ADDR_OF(flow_context, in_flow_context, destination);
203 	MLX5_SET(dest_format_struct, in_dests, destination_type,
204 		 MLX5_FLOW_DESTINATION_TYPE_VPORT);
205 	MLX5_SET(dest_format_struct, in_dests, destination_id, vport_id);
206 
207 	err = mlx5_cmd_exec(mdev, in, inlen, out, sizeof(out));
208 	kvfree(in);
209 
210 	return err;
211 }
212 
mlx5dr_cmd_del_flow_table_entry(struct mlx5_core_dev * mdev,u32 table_type,u32 table_id)213 int mlx5dr_cmd_del_flow_table_entry(struct mlx5_core_dev *mdev,
214 				    u32 table_type,
215 				    u32 table_id)
216 {
217 	u32 out[MLX5_ST_SZ_DW(delete_fte_out)] = {};
218 	u32 in[MLX5_ST_SZ_DW(delete_fte_in)] = {};
219 
220 	MLX5_SET(delete_fte_in, in, opcode, MLX5_CMD_OP_DELETE_FLOW_TABLE_ENTRY);
221 	MLX5_SET(delete_fte_in, in, table_type, table_type);
222 	MLX5_SET(delete_fte_in, in, table_id, table_id);
223 
224 	return mlx5_cmd_exec(mdev, in, sizeof(in), out, sizeof(out));
225 }
226 
mlx5dr_cmd_alloc_modify_header(struct mlx5_core_dev * mdev,u32 table_type,u8 num_of_actions,u64 * actions,u32 * modify_header_id)227 int mlx5dr_cmd_alloc_modify_header(struct mlx5_core_dev *mdev,
228 				   u32 table_type,
229 				   u8 num_of_actions,
230 				   u64 *actions,
231 				   u32 *modify_header_id)
232 {
233 	u32 out[MLX5_ST_SZ_DW(alloc_modify_header_context_out)] = {};
234 	void *p_actions;
235 	u32 inlen;
236 	u32 *in;
237 	int err;
238 
239 	inlen = MLX5_ST_SZ_BYTES(alloc_modify_header_context_in) +
240 		 num_of_actions * sizeof(u64);
241 	in = kvzalloc(inlen, GFP_KERNEL);
242 	if (!in)
243 		return -ENOMEM;
244 
245 	MLX5_SET(alloc_modify_header_context_in, in, opcode,
246 		 MLX5_CMD_OP_ALLOC_MODIFY_HEADER_CONTEXT);
247 	MLX5_SET(alloc_modify_header_context_in, in, table_type, table_type);
248 	MLX5_SET(alloc_modify_header_context_in, in, num_of_actions, num_of_actions);
249 	p_actions = MLX5_ADDR_OF(alloc_modify_header_context_in, in, actions);
250 	memcpy(p_actions, actions, num_of_actions * sizeof(u64));
251 
252 	err = mlx5_cmd_exec(mdev, in, inlen, out, sizeof(out));
253 	if (err)
254 		goto out;
255 
256 	*modify_header_id = MLX5_GET(alloc_modify_header_context_out, out,
257 				     modify_header_id);
258 out:
259 	kvfree(in);
260 	return err;
261 }
262 
mlx5dr_cmd_dealloc_modify_header(struct mlx5_core_dev * mdev,u32 modify_header_id)263 int mlx5dr_cmd_dealloc_modify_header(struct mlx5_core_dev *mdev,
264 				     u32 modify_header_id)
265 {
266 	u32 out[MLX5_ST_SZ_DW(dealloc_modify_header_context_out)] = {};
267 	u32 in[MLX5_ST_SZ_DW(dealloc_modify_header_context_in)] = {};
268 
269 	MLX5_SET(dealloc_modify_header_context_in, in, opcode,
270 		 MLX5_CMD_OP_DEALLOC_MODIFY_HEADER_CONTEXT);
271 	MLX5_SET(dealloc_modify_header_context_in, in, modify_header_id,
272 		 modify_header_id);
273 
274 	return mlx5_cmd_exec(mdev, in, sizeof(in), out, sizeof(out));
275 }
276 
mlx5dr_cmd_create_empty_flow_group(struct mlx5_core_dev * mdev,u32 table_type,u32 table_id,u32 * group_id)277 int mlx5dr_cmd_create_empty_flow_group(struct mlx5_core_dev *mdev,
278 				       u32 table_type,
279 				       u32 table_id,
280 				       u32 *group_id)
281 {
282 	u32 out[MLX5_ST_SZ_DW(create_flow_group_out)] = {};
283 	int inlen = MLX5_ST_SZ_BYTES(create_flow_group_in);
284 	u32 *in;
285 	int err;
286 
287 	in = kzalloc(inlen, GFP_KERNEL);
288 	if (!in)
289 		return -ENOMEM;
290 
291 	MLX5_SET(create_flow_group_in, in, opcode, MLX5_CMD_OP_CREATE_FLOW_GROUP);
292 	MLX5_SET(create_flow_group_in, in, table_type, table_type);
293 	MLX5_SET(create_flow_group_in, in, table_id, table_id);
294 
295 	err = mlx5_cmd_exec(mdev, in, inlen, out, sizeof(out));
296 	if (err)
297 		goto out;
298 
299 	*group_id = MLX5_GET(create_flow_group_out, out, group_id);
300 
301 out:
302 	kfree(in);
303 	return err;
304 }
305 
mlx5dr_cmd_destroy_flow_group(struct mlx5_core_dev * mdev,u32 table_type,u32 table_id,u32 group_id)306 int mlx5dr_cmd_destroy_flow_group(struct mlx5_core_dev *mdev,
307 				  u32 table_type,
308 				  u32 table_id,
309 				  u32 group_id)
310 {
311 	u32 in[MLX5_ST_SZ_DW(destroy_flow_group_in)] = {};
312 	u32 out[MLX5_ST_SZ_DW(destroy_flow_group_out)] = {};
313 
314 	MLX5_SET(create_flow_group_in, in, opcode, MLX5_CMD_OP_DESTROY_FLOW_GROUP);
315 	MLX5_SET(destroy_flow_group_in, in, table_type, table_type);
316 	MLX5_SET(destroy_flow_group_in, in, table_id, table_id);
317 	MLX5_SET(destroy_flow_group_in, in, group_id, group_id);
318 
319 	return mlx5_cmd_exec(mdev, in, sizeof(in), out, sizeof(out));
320 }
321 
mlx5dr_cmd_create_flow_table(struct mlx5_core_dev * mdev,u32 table_type,u64 icm_addr_rx,u64 icm_addr_tx,u8 level,bool sw_owner,bool term_tbl,u64 * fdb_rx_icm_addr,u32 * table_id)322 int mlx5dr_cmd_create_flow_table(struct mlx5_core_dev *mdev,
323 				 u32 table_type,
324 				 u64 icm_addr_rx,
325 				 u64 icm_addr_tx,
326 				 u8 level,
327 				 bool sw_owner,
328 				 bool term_tbl,
329 				 u64 *fdb_rx_icm_addr,
330 				 u32 *table_id)
331 {
332 	u32 out[MLX5_ST_SZ_DW(create_flow_table_out)] = {};
333 	u32 in[MLX5_ST_SZ_DW(create_flow_table_in)] = {};
334 	void *ft_mdev;
335 	int err;
336 
337 	MLX5_SET(create_flow_table_in, in, opcode, MLX5_CMD_OP_CREATE_FLOW_TABLE);
338 	MLX5_SET(create_flow_table_in, in, table_type, table_type);
339 
340 	ft_mdev = MLX5_ADDR_OF(create_flow_table_in, in, flow_table_context);
341 	MLX5_SET(flow_table_context, ft_mdev, termination_table, term_tbl);
342 	MLX5_SET(flow_table_context, ft_mdev, sw_owner, sw_owner);
343 	MLX5_SET(flow_table_context, ft_mdev, level, level);
344 
345 	if (sw_owner) {
346 		/* icm_addr_0 used for FDB RX / NIC TX / NIC_RX
347 		 * icm_addr_1 used for FDB TX
348 		 */
349 		if (table_type == MLX5_FLOW_TABLE_TYPE_NIC_RX) {
350 			MLX5_SET64(flow_table_context, ft_mdev,
351 				   sw_owner_icm_root_0, icm_addr_rx);
352 		} else if (table_type == MLX5_FLOW_TABLE_TYPE_NIC_TX) {
353 			MLX5_SET64(flow_table_context, ft_mdev,
354 				   sw_owner_icm_root_0, icm_addr_tx);
355 		} else if (table_type == MLX5_FLOW_TABLE_TYPE_FDB) {
356 			MLX5_SET64(flow_table_context, ft_mdev,
357 				   sw_owner_icm_root_0, icm_addr_rx);
358 			MLX5_SET64(flow_table_context, ft_mdev,
359 				   sw_owner_icm_root_1, icm_addr_tx);
360 		}
361 	}
362 
363 	err = mlx5_cmd_exec(mdev, in, sizeof(in), out, sizeof(out));
364 	if (err)
365 		return err;
366 
367 	*table_id = MLX5_GET(create_flow_table_out, out, table_id);
368 	if (!sw_owner && table_type == MLX5_FLOW_TABLE_TYPE_FDB)
369 		*fdb_rx_icm_addr =
370 		(u64)MLX5_GET(create_flow_table_out, out, icm_address_31_0) |
371 		(u64)MLX5_GET(create_flow_table_out, out, icm_address_39_32) << 32 |
372 		(u64)MLX5_GET(create_flow_table_out, out, icm_address_63_40) << 40;
373 
374 	return 0;
375 }
376 
mlx5dr_cmd_destroy_flow_table(struct mlx5_core_dev * mdev,u32 table_id,u32 table_type)377 int mlx5dr_cmd_destroy_flow_table(struct mlx5_core_dev *mdev,
378 				  u32 table_id,
379 				  u32 table_type)
380 {
381 	u32 out[MLX5_ST_SZ_DW(destroy_flow_table_out)] = {};
382 	u32 in[MLX5_ST_SZ_DW(destroy_flow_table_in)] = {};
383 
384 	MLX5_SET(destroy_flow_table_in, in, opcode,
385 		 MLX5_CMD_OP_DESTROY_FLOW_TABLE);
386 	MLX5_SET(destroy_flow_table_in, in, table_type, table_type);
387 	MLX5_SET(destroy_flow_table_in, in, table_id, table_id);
388 
389 	return mlx5_cmd_exec(mdev, in, sizeof(in), out, sizeof(out));
390 }
391 
mlx5dr_cmd_create_reformat_ctx(struct mlx5_core_dev * mdev,enum mlx5_reformat_ctx_type rt,size_t reformat_size,void * reformat_data,u32 * reformat_id)392 int mlx5dr_cmd_create_reformat_ctx(struct mlx5_core_dev *mdev,
393 				   enum mlx5_reformat_ctx_type rt,
394 				   size_t reformat_size,
395 				   void *reformat_data,
396 				   u32 *reformat_id)
397 {
398 	u32 out[MLX5_ST_SZ_DW(alloc_packet_reformat_context_out)] = {};
399 	size_t inlen, cmd_data_sz, cmd_total_sz;
400 	void *prctx;
401 	void *pdata;
402 	void *in;
403 	int err;
404 
405 	cmd_total_sz = MLX5_ST_SZ_BYTES(alloc_packet_reformat_context_in);
406 	cmd_data_sz = MLX5_FLD_SZ_BYTES(alloc_packet_reformat_context_in,
407 					packet_reformat_context.reformat_data);
408 	inlen = ALIGN(cmd_total_sz + reformat_size - cmd_data_sz, 4);
409 	in = kvzalloc(inlen, GFP_KERNEL);
410 	if (!in)
411 		return -ENOMEM;
412 
413 	MLX5_SET(alloc_packet_reformat_context_in, in, opcode,
414 		 MLX5_CMD_OP_ALLOC_PACKET_REFORMAT_CONTEXT);
415 
416 	prctx = MLX5_ADDR_OF(alloc_packet_reformat_context_in, in, packet_reformat_context);
417 	pdata = MLX5_ADDR_OF(packet_reformat_context_in, prctx, reformat_data);
418 
419 	MLX5_SET(packet_reformat_context_in, prctx, reformat_type, rt);
420 	MLX5_SET(packet_reformat_context_in, prctx, reformat_data_size, reformat_size);
421 	memcpy(pdata, reformat_data, reformat_size);
422 
423 	err = mlx5_cmd_exec(mdev, in, inlen, out, sizeof(out));
424 	if (err)
425 		return err;
426 
427 	*reformat_id = MLX5_GET(alloc_packet_reformat_context_out, out, packet_reformat_id);
428 	kvfree(in);
429 
430 	return err;
431 }
432 
mlx5dr_cmd_destroy_reformat_ctx(struct mlx5_core_dev * mdev,u32 reformat_id)433 void mlx5dr_cmd_destroy_reformat_ctx(struct mlx5_core_dev *mdev,
434 				     u32 reformat_id)
435 {
436 	u32 out[MLX5_ST_SZ_DW(dealloc_packet_reformat_context_out)] = {};
437 	u32 in[MLX5_ST_SZ_DW(dealloc_packet_reformat_context_in)] = {};
438 
439 	MLX5_SET(dealloc_packet_reformat_context_in, in, opcode,
440 		 MLX5_CMD_OP_DEALLOC_PACKET_REFORMAT_CONTEXT);
441 	MLX5_SET(dealloc_packet_reformat_context_in, in, packet_reformat_id,
442 		 reformat_id);
443 
444 	mlx5_cmd_exec(mdev, in, sizeof(in), out, sizeof(out));
445 }
446 
mlx5dr_cmd_query_gid(struct mlx5_core_dev * mdev,u8 vhca_port_num,u16 index,struct mlx5dr_cmd_gid_attr * attr)447 int mlx5dr_cmd_query_gid(struct mlx5_core_dev *mdev, u8 vhca_port_num,
448 			 u16 index, struct mlx5dr_cmd_gid_attr *attr)
449 {
450 	u32 out[MLX5_ST_SZ_DW(query_roce_address_out)] = {};
451 	u32 in[MLX5_ST_SZ_DW(query_roce_address_in)] = {};
452 	int err;
453 
454 	MLX5_SET(query_roce_address_in, in, opcode,
455 		 MLX5_CMD_OP_QUERY_ROCE_ADDRESS);
456 
457 	MLX5_SET(query_roce_address_in, in, roce_address_index, index);
458 	MLX5_SET(query_roce_address_in, in, vhca_port_num, vhca_port_num);
459 
460 	err = mlx5_cmd_exec(mdev, in, sizeof(in), out, sizeof(out));
461 	if (err)
462 		return err;
463 
464 	memcpy(&attr->gid,
465 	       MLX5_ADDR_OF(query_roce_address_out,
466 			    out, roce_address.source_l3_address),
467 	       sizeof(attr->gid));
468 	memcpy(attr->mac,
469 	       MLX5_ADDR_OF(query_roce_address_out, out,
470 			    roce_address.source_mac_47_32),
471 	       sizeof(attr->mac));
472 
473 	if (MLX5_GET(query_roce_address_out, out,
474 		     roce_address.roce_version) == MLX5_ROCE_VERSION_2)
475 		attr->roce_ver = MLX5_ROCE_VERSION_2;
476 	else
477 		attr->roce_ver = MLX5_ROCE_VERSION_1;
478 
479 	return 0;
480 }
481