xref: /freebsd/sys/dev/mlx5/mlx5_core/mlx5_port.c (revision 190cef3d)
1 /*-
2  * Copyright (c) 2013-2017, Mellanox Technologies, Ltd.  All rights reserved.
3  *
4  * Redistribution and use in source and binary forms, with or without
5  * modification, are permitted provided that the following conditions
6  * are met:
7  * 1. Redistributions of source code must retain the above copyright
8  *    notice, this list of conditions and the following disclaimer.
9  * 2. Redistributions in binary form must reproduce the above copyright
10  *    notice, this list of conditions and the following disclaimer in the
11  *    documentation and/or other materials provided with the distribution.
12  *
13  * THIS SOFTWARE IS PROVIDED BY AUTHOR AND CONTRIBUTORS `AS IS' AND
14  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
15  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
16  * ARE DISCLAIMED.  IN NO EVENT SHALL AUTHOR OR CONTRIBUTORS BE LIABLE
17  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
18  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
19  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
20  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
21  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
22  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
23  * SUCH DAMAGE.
24  *
25  * $FreeBSD$
26  */
27 
28 #include <linux/module.h>
29 #include <dev/mlx5/port.h>
30 #include "mlx5_core.h"
31 
32 int mlx5_core_access_reg(struct mlx5_core_dev *dev, void *data_in,
33 			 int size_in, void *data_out, int size_out,
34 			 u16 reg_num, int arg, int write)
35 {
36 	int outlen = MLX5_ST_SZ_BYTES(access_register_out) + size_out;
37 	int inlen = MLX5_ST_SZ_BYTES(access_register_in) + size_in;
38 	int err = -ENOMEM;
39 	u32 *out = NULL;
40 	u32 *in = NULL;
41 	void *data;
42 
43 	in = mlx5_vzalloc(inlen);
44 	out = mlx5_vzalloc(outlen);
45 	if (!in || !out)
46 		goto out;
47 
48 	data = MLX5_ADDR_OF(access_register_in, in, register_data);
49 	memcpy(data, data_in, size_in);
50 
51 	MLX5_SET(access_register_in, in, opcode, MLX5_CMD_OP_ACCESS_REG);
52 	MLX5_SET(access_register_in, in, op_mod, !write);
53 	MLX5_SET(access_register_in, in, argument, arg);
54 	MLX5_SET(access_register_in, in, register_id, reg_num);
55 
56 	err = mlx5_cmd_exec(dev, in, inlen, out, outlen);
57 	if (err)
58 		goto out;
59 	data = MLX5_ADDR_OF(access_register_out, out, register_data);
60 	memcpy(data_out, data, size_out);
61 
62 out:
63 	kvfree(out);
64 	kvfree(in);
65 	return err;
66 }
67 EXPORT_SYMBOL_GPL(mlx5_core_access_reg);
68 
69 int mlx5_query_qcam_reg(struct mlx5_core_dev *mdev, u32 *qcam,
70 			u8 feature_group, u8 access_reg_group)
71 {
72 	u32 in[MLX5_ST_SZ_DW(qcam_reg)] = {};
73 	int sz = MLX5_ST_SZ_BYTES(qcam_reg);
74 
75 	MLX5_SET(qcam_reg, in, feature_group, feature_group);
76 	MLX5_SET(qcam_reg, in, access_reg_group, access_reg_group);
77 
78 	return mlx5_core_access_reg(mdev, in, sz, qcam, sz, MLX5_REG_QCAM, 0, 0);
79 }
80 EXPORT_SYMBOL_GPL(mlx5_query_qcam_reg);
81 
82 struct mlx5_reg_pcap {
83 	u8			rsvd0;
84 	u8			port_num;
85 	u8			rsvd1[2];
86 	__be32			caps_127_96;
87 	__be32			caps_95_64;
88 	__be32			caps_63_32;
89 	__be32			caps_31_0;
90 };
91 
92 /* This function should be used after setting a port register only */
93 void mlx5_toggle_port_link(struct mlx5_core_dev *dev)
94 {
95 	enum mlx5_port_status ps;
96 
97 	mlx5_query_port_admin_status(dev, &ps);
98 	mlx5_set_port_status(dev, MLX5_PORT_DOWN);
99 	if (ps == MLX5_PORT_UP)
100 		mlx5_set_port_status(dev, MLX5_PORT_UP);
101 }
102 EXPORT_SYMBOL_GPL(mlx5_toggle_port_link);
103 
104 int mlx5_set_port_caps(struct mlx5_core_dev *dev, u8 port_num, u32 caps)
105 {
106 	struct mlx5_reg_pcap in;
107 	struct mlx5_reg_pcap out;
108 	int err;
109 
110 	memset(&in, 0, sizeof(in));
111 	in.caps_127_96 = cpu_to_be32(caps);
112 	in.port_num = port_num;
113 
114 	err = mlx5_core_access_reg(dev, &in, sizeof(in), &out,
115 				   sizeof(out), MLX5_REG_PCAP, 0, 1);
116 
117 	return err;
118 }
119 EXPORT_SYMBOL_GPL(mlx5_set_port_caps);
120 
121 int mlx5_query_port_ptys(struct mlx5_core_dev *dev, u32 *ptys,
122 			 int ptys_size, int proto_mask, u8 local_port)
123 {
124 	u32 in[MLX5_ST_SZ_DW(ptys_reg)];
125 	int err;
126 
127 	memset(in, 0, sizeof(in));
128 	MLX5_SET(ptys_reg, in, local_port, local_port);
129 	MLX5_SET(ptys_reg, in, proto_mask, proto_mask);
130 
131 	err = mlx5_core_access_reg(dev, in, sizeof(in), ptys,
132 				   ptys_size, MLX5_REG_PTYS, 0, 0);
133 
134 	return err;
135 }
136 EXPORT_SYMBOL_GPL(mlx5_query_port_ptys);
137 
138 int mlx5_query_port_proto_cap(struct mlx5_core_dev *dev,
139 			      u32 *proto_cap, int proto_mask)
140 {
141 	u32 out[MLX5_ST_SZ_DW(ptys_reg)];
142 	int err;
143 
144 	err = mlx5_query_port_ptys(dev, out, sizeof(out), proto_mask, 1);
145 	if (err)
146 		return err;
147 
148 	if (proto_mask == MLX5_PTYS_EN)
149 		*proto_cap = MLX5_GET(ptys_reg, out, eth_proto_capability);
150 	else
151 		*proto_cap = MLX5_GET(ptys_reg, out, ib_proto_capability);
152 
153 	return 0;
154 }
155 EXPORT_SYMBOL_GPL(mlx5_query_port_proto_cap);
156 
157 int mlx5_query_port_autoneg(struct mlx5_core_dev *dev, int proto_mask,
158 			    u8 *an_disable_cap, u8 *an_disable_status)
159 {
160 	u32 out[MLX5_ST_SZ_DW(ptys_reg)];
161 	int err;
162 
163 	err = mlx5_query_port_ptys(dev, out, sizeof(out), proto_mask, 1);
164 	if (err)
165 		return err;
166 
167 	*an_disable_status = MLX5_GET(ptys_reg, out, an_disable_admin);
168 	*an_disable_cap = MLX5_GET(ptys_reg, out, an_disable_cap);
169 
170 	return 0;
171 }
172 EXPORT_SYMBOL_GPL(mlx5_query_port_autoneg);
173 
174 int mlx5_set_port_autoneg(struct mlx5_core_dev *dev, bool disable,
175 			  u32 eth_proto_admin, int proto_mask)
176 {
177 	u32 in[MLX5_ST_SZ_DW(ptys_reg)] = {0};
178 	u32 out[MLX5_ST_SZ_DW(ptys_reg)] = {0};
179 	u8 an_disable_cap;
180 	u8 an_disable_status;
181 	int err;
182 
183 	err = mlx5_query_port_autoneg(dev, proto_mask, &an_disable_cap,
184 				      &an_disable_status);
185 	if (err)
186 		return err;
187 	if (!an_disable_cap)
188 		return -EPERM;
189 
190 	MLX5_SET(ptys_reg, in, local_port, 1);
191 	MLX5_SET(ptys_reg, in, an_disable_admin, disable);
192 	MLX5_SET(ptys_reg, in, proto_mask, proto_mask);
193 	if (proto_mask == MLX5_PTYS_EN)
194 		MLX5_SET(ptys_reg, in, eth_proto_admin, eth_proto_admin);
195 
196 	err = mlx5_core_access_reg(dev, in, sizeof(in), out,
197 				   sizeof(out), MLX5_REG_PTYS, 0, 1);
198 	return err;
199 }
200 EXPORT_SYMBOL_GPL(mlx5_set_port_autoneg);
201 
202 int mlx5_query_port_proto_admin(struct mlx5_core_dev *dev,
203 				u32 *proto_admin, int proto_mask)
204 {
205 	u32 out[MLX5_ST_SZ_DW(ptys_reg)];
206 	int err;
207 
208 	err = mlx5_query_port_ptys(dev, out, sizeof(out), proto_mask, 1);
209 	if (err)
210 		return err;
211 
212 	if (proto_mask == MLX5_PTYS_EN)
213 		*proto_admin = MLX5_GET(ptys_reg, out, eth_proto_admin);
214 	else
215 		*proto_admin = MLX5_GET(ptys_reg, out, ib_proto_admin);
216 
217 	return 0;
218 }
219 EXPORT_SYMBOL_GPL(mlx5_query_port_proto_admin);
220 
221 int mlx5_query_port_eth_proto_oper(struct mlx5_core_dev *dev,
222 				   u32 *proto_oper, u8 local_port)
223 {
224 	u32 out[MLX5_ST_SZ_DW(ptys_reg)];
225 	int err;
226 
227 	err = mlx5_query_port_ptys(dev, out, sizeof(out), MLX5_PTYS_EN,
228 				   local_port);
229 	if (err)
230 		return err;
231 
232 	*proto_oper = MLX5_GET(ptys_reg, out, eth_proto_oper);
233 
234 	return 0;
235 }
236 EXPORT_SYMBOL(mlx5_query_port_eth_proto_oper);
237 
238 int mlx5_set_port_proto(struct mlx5_core_dev *dev, u32 proto_admin,
239 			int proto_mask)
240 {
241 	u32 in[MLX5_ST_SZ_DW(ptys_reg)] = {0};
242 	u32 out[MLX5_ST_SZ_DW(ptys_reg)] = {0};
243 	int err;
244 
245 	MLX5_SET(ptys_reg, in, local_port, 1);
246 	MLX5_SET(ptys_reg, in, proto_mask, proto_mask);
247 	if (proto_mask == MLX5_PTYS_EN)
248 		MLX5_SET(ptys_reg, in, eth_proto_admin, proto_admin);
249 	else
250 		MLX5_SET(ptys_reg, in, ib_proto_admin, proto_admin);
251 
252 	err = mlx5_core_access_reg(dev, in, sizeof(in), out,
253 				   sizeof(out), MLX5_REG_PTYS, 0, 1);
254 	return err;
255 }
256 EXPORT_SYMBOL_GPL(mlx5_set_port_proto);
257 
258 int mlx5_set_port_status(struct mlx5_core_dev *dev,
259 			 enum mlx5_port_status status)
260 {
261 	u32 in[MLX5_ST_SZ_DW(paos_reg)] = {0};
262 	u32 out[MLX5_ST_SZ_DW(paos_reg)] = {0};
263 	int err;
264 
265 	MLX5_SET(paos_reg, in, local_port, 1);
266 
267 	MLX5_SET(paos_reg, in, admin_status, status);
268 	MLX5_SET(paos_reg, in, ase, 1);
269 
270 	err = mlx5_core_access_reg(dev, in, sizeof(in), out,
271 				   sizeof(out), MLX5_REG_PAOS, 0, 1);
272 	return err;
273 }
274 
275 int mlx5_query_port_status(struct mlx5_core_dev *dev, u8 *status)
276 {
277 	u32 in[MLX5_ST_SZ_DW(paos_reg)] = {0};
278 	u32 out[MLX5_ST_SZ_DW(paos_reg)] = {0};
279 	int err;
280 
281 	MLX5_SET(paos_reg, in, local_port, 1);
282 
283 	err = mlx5_core_access_reg(dev, in, sizeof(in), out,
284 				   sizeof(out), MLX5_REG_PAOS, 0, 0);
285 	if (err)
286 		return err;
287 
288 	*status = MLX5_GET(paos_reg, out, oper_status);
289 	return err;
290 }
291 
292 int mlx5_query_port_admin_status(struct mlx5_core_dev *dev,
293 				 enum mlx5_port_status *status)
294 {
295 	u32 in[MLX5_ST_SZ_DW(paos_reg)] = {0};
296 	u32 out[MLX5_ST_SZ_DW(paos_reg)];
297 	int err;
298 
299 	MLX5_SET(paos_reg, in, local_port, 1);
300 	err = mlx5_core_access_reg(dev, in, sizeof(in), out,
301 				   sizeof(out), MLX5_REG_PAOS, 0, 0);
302 	if (err)
303 		return err;
304 	*status = MLX5_GET(paos_reg, out, admin_status);
305 	return 0;
306 }
307 EXPORT_SYMBOL_GPL(mlx5_query_port_admin_status);
308 
309 static int mlx5_query_port_mtu(struct mlx5_core_dev *dev,
310 			       int *admin_mtu, int *max_mtu, int *oper_mtu)
311 {
312 	u32 in[MLX5_ST_SZ_DW(pmtu_reg)] = {0};
313 	u32 out[MLX5_ST_SZ_DW(pmtu_reg)] = {0};
314 	int err;
315 
316 	MLX5_SET(pmtu_reg, in, local_port, 1);
317 
318 	err = mlx5_core_access_reg(dev, in, sizeof(in), out,
319 				   sizeof(out), MLX5_REG_PMTU, 0, 0);
320 	if (err)
321 		return err;
322 
323 	if (max_mtu)
324 		*max_mtu  = MLX5_GET(pmtu_reg, out, max_mtu);
325 	if (oper_mtu)
326 		*oper_mtu = MLX5_GET(pmtu_reg, out, oper_mtu);
327 	if (admin_mtu)
328 		*admin_mtu = MLX5_GET(pmtu_reg, out, admin_mtu);
329 
330 	return err;
331 }
332 
333 int mlx5_set_port_mtu(struct mlx5_core_dev *dev, int mtu)
334 {
335 	u32 in[MLX5_ST_SZ_DW(pmtu_reg)] = {0};
336 	u32 out[MLX5_ST_SZ_DW(pmtu_reg)] = {0};
337 
338 	MLX5_SET(pmtu_reg, in, admin_mtu, mtu);
339 	MLX5_SET(pmtu_reg, in, local_port, 1);
340 
341 	return mlx5_core_access_reg(dev, in, sizeof(in), out,
342 				   sizeof(out), MLX5_REG_PMTU, 0, 1);
343 }
344 EXPORT_SYMBOL_GPL(mlx5_set_port_mtu);
345 
346 int mlx5_query_port_max_mtu(struct mlx5_core_dev *dev, int *max_mtu)
347 {
348 	return mlx5_query_port_mtu(dev, NULL, max_mtu, NULL);
349 }
350 EXPORT_SYMBOL_GPL(mlx5_query_port_max_mtu);
351 
352 int mlx5_set_port_pause_and_pfc(struct mlx5_core_dev *dev, u32 port,
353 				u8 rx_pause, u8 tx_pause,
354 				u8 pfc_en_rx, u8 pfc_en_tx)
355 {
356 	u32 in[MLX5_ST_SZ_DW(pfcc_reg)] = {0};
357 	u32 out[MLX5_ST_SZ_DW(pfcc_reg)] = {0};
358 
359 	if (pfc_en_rx || pfc_en_tx) {
360 		/* PFC and global pauseframes are incompatible features */
361 		if (tx_pause || rx_pause)
362 			return -EINVAL;
363 	}
364 
365 	MLX5_SET(pfcc_reg, in, local_port, port);
366 	MLX5_SET(pfcc_reg, in, pptx, tx_pause);
367 	MLX5_SET(pfcc_reg, in, pprx, rx_pause);
368 	MLX5_SET(pfcc_reg, in, pfctx, pfc_en_tx);
369 	MLX5_SET(pfcc_reg, in, pfcrx, pfc_en_rx);
370 	MLX5_SET(pfcc_reg, in, prio_mask_tx, pfc_en_tx);
371 	MLX5_SET(pfcc_reg, in, prio_mask_rx, pfc_en_rx);
372 
373 	return mlx5_core_access_reg(dev, in, sizeof(in), out,
374 				   sizeof(out), MLX5_REG_PFCC, 0, 1);
375 }
376 
377 int mlx5_query_port_pause(struct mlx5_core_dev *dev, u32 port,
378 			  u32 *rx_pause, u32 *tx_pause)
379 {
380 	u32 in[MLX5_ST_SZ_DW(pfcc_reg)] = {0};
381 	u32 out[MLX5_ST_SZ_DW(pfcc_reg)] = {0};
382 	int err;
383 
384 	MLX5_SET(pfcc_reg, in, local_port, port);
385 
386 	err = mlx5_core_access_reg(dev, in, sizeof(in), out,
387 				   sizeof(out), MLX5_REG_PFCC, 0, 0);
388 	if (err)
389 		return err;
390 
391 	*rx_pause = MLX5_GET(pfcc_reg, out, pprx);
392 	*tx_pause = MLX5_GET(pfcc_reg, out, pptx);
393 
394 	return 0;
395 }
396 
397 int mlx5_query_port_pfc(struct mlx5_core_dev *dev, u8 *pfc_en_tx, u8 *pfc_en_rx)
398 {
399 	u32 in[MLX5_ST_SZ_DW(pfcc_reg)] = {};
400 	u32 out[MLX5_ST_SZ_DW(pfcc_reg)];
401 	int err;
402 
403 	MLX5_SET(pfcc_reg, in, local_port, 1);
404 	err = mlx5_core_access_reg(dev, in, sizeof(in), out,
405 				   sizeof(out), MLX5_REG_PFCC, 0, 0);
406 	if (err)
407 		return err;
408 
409 	if (pfc_en_tx != NULL)
410 		*pfc_en_tx = MLX5_GET(pfcc_reg, out, pfctx);
411 	if (pfc_en_rx != NULL)
412 		*pfc_en_rx = MLX5_GET(pfcc_reg, out, pfcrx);
413 	return 0;
414 }
415 EXPORT_SYMBOL_GPL(mlx5_query_port_pfc);
416 
417 int mlx5_query_port_oper_mtu(struct mlx5_core_dev *dev, int *oper_mtu)
418 {
419 	return mlx5_query_port_mtu(dev, NULL, NULL, oper_mtu);
420 }
421 EXPORT_SYMBOL_GPL(mlx5_query_port_oper_mtu);
422 
423 u8 mlx5_is_wol_supported(struct mlx5_core_dev *dev)
424 {
425 	u8 wol_supported = 0;
426 
427 	if (MLX5_CAP_GEN(dev, wol_s))
428 		wol_supported |= MLX5_WOL_SECURED_MAGIC;
429 	if (MLX5_CAP_GEN(dev, wol_g))
430 		wol_supported |= MLX5_WOL_MAGIC;
431 	if (MLX5_CAP_GEN(dev, wol_a))
432 		wol_supported |= MLX5_WOL_ARP;
433 	if (MLX5_CAP_GEN(dev, wol_b))
434 		wol_supported |= MLX5_WOL_BROADCAST;
435 	if (MLX5_CAP_GEN(dev, wol_m))
436 		wol_supported |= MLX5_WOL_MULTICAST;
437 	if (MLX5_CAP_GEN(dev, wol_u))
438 		wol_supported |= MLX5_WOL_UNICAST;
439 	if (MLX5_CAP_GEN(dev, wol_p))
440 		wol_supported |= MLX5_WOL_PHY_ACTIVITY;
441 
442 	return wol_supported;
443 }
444 EXPORT_SYMBOL_GPL(mlx5_is_wol_supported);
445 
446 int mlx5_set_wol(struct mlx5_core_dev *dev, u8 wol_mode)
447 {
448 	u32 in[MLX5_ST_SZ_DW(set_wol_rol_in)] = {0};
449 	u32 out[MLX5_ST_SZ_DW(set_wol_rol_out)] = {0};
450 
451 	MLX5_SET(set_wol_rol_in, in, opcode, MLX5_CMD_OP_SET_WOL_ROL);
452 	MLX5_SET(set_wol_rol_in, in, wol_mode_valid, 1);
453 	MLX5_SET(set_wol_rol_in, in, wol_mode, wol_mode);
454 
455 	return mlx5_cmd_exec(dev, in, sizeof(in), out, sizeof(out));
456 }
457 EXPORT_SYMBOL_GPL(mlx5_set_wol);
458 
459 int mlx5_query_dropless_mode(struct mlx5_core_dev *dev, u16 *timeout)
460 {
461 	u32 in[MLX5_ST_SZ_DW(query_delay_drop_params_in)] = {0};
462 	u32 out[MLX5_ST_SZ_DW(query_delay_drop_params_out)] = {0};
463 	int err = 0;
464 
465 	MLX5_SET(query_delay_drop_params_in, in, opcode,
466 		 MLX5_CMD_OP_QUERY_DELAY_DROP_PARAMS);
467 
468 	err = mlx5_cmd_exec(dev, in, sizeof(in), out, sizeof(out));
469 	if (err)
470 		return err;
471 
472 	*timeout = MLX5_GET(query_delay_drop_params_out, out,
473 			    delay_drop_timeout);
474 
475 	return 0;
476 }
477 EXPORT_SYMBOL_GPL(mlx5_query_dropless_mode);
478 
479 int mlx5_set_dropless_mode(struct mlx5_core_dev *dev, u16 timeout)
480 {
481 	u32 in[MLX5_ST_SZ_DW(set_delay_drop_params_in)] = {0};
482 	u32 out[MLX5_ST_SZ_DW(set_delay_drop_params_out)] = {0};
483 
484 	MLX5_SET(set_delay_drop_params_in, in, opcode,
485 		 MLX5_CMD_OP_SET_DELAY_DROP_PARAMS);
486 	MLX5_SET(set_delay_drop_params_in, in, delay_drop_timeout, timeout);
487 
488 	return mlx5_cmd_exec(dev, in, sizeof(in), out, sizeof(out));
489 }
490 EXPORT_SYMBOL_GPL(mlx5_set_dropless_mode);
491 
492 int mlx5_core_access_pvlc(struct mlx5_core_dev *dev,
493 			  struct mlx5_pvlc_reg *pvlc, int write)
494 {
495 	int sz = MLX5_ST_SZ_BYTES(pvlc_reg);
496 	u8 in[MLX5_ST_SZ_BYTES(pvlc_reg)] = {0};
497 	u8 out[MLX5_ST_SZ_BYTES(pvlc_reg)] = {0};
498 	int err;
499 
500 	MLX5_SET(pvlc_reg, in, local_port, pvlc->local_port);
501 	if (write)
502 		MLX5_SET(pvlc_reg, in, vl_admin, pvlc->vl_admin);
503 
504 	err = mlx5_core_access_reg(dev, in, sz, out, sz, MLX5_REG_PVLC, 0,
505 				   !!write);
506 	if (err)
507 		return err;
508 
509 	if (!write) {
510 		pvlc->local_port = MLX5_GET(pvlc_reg, out, local_port);
511 		pvlc->vl_hw_cap = MLX5_GET(pvlc_reg, out, vl_hw_cap);
512 		pvlc->vl_admin = MLX5_GET(pvlc_reg, out, vl_admin);
513 		pvlc->vl_operational = MLX5_GET(pvlc_reg, out, vl_operational);
514 	}
515 
516 	return 0;
517 }
518 EXPORT_SYMBOL_GPL(mlx5_core_access_pvlc);
519 
520 int mlx5_core_access_ptys(struct mlx5_core_dev *dev,
521 			  struct mlx5_ptys_reg *ptys, int write)
522 {
523 	int sz = MLX5_ST_SZ_BYTES(ptys_reg);
524 	void *out = NULL;
525 	void *in = NULL;
526 	int err;
527 
528 	in = mlx5_vzalloc(sz);
529 	if (!in)
530 		return -ENOMEM;
531 
532 	out = mlx5_vzalloc(sz);
533 	if (!out) {
534 		kfree(in);
535 		return -ENOMEM;
536 	}
537 
538 	MLX5_SET(ptys_reg, in, local_port, ptys->local_port);
539 	MLX5_SET(ptys_reg, in, proto_mask, ptys->proto_mask);
540 	if (write) {
541 		MLX5_SET(ptys_reg, in, eth_proto_capability,
542 			 ptys->eth_proto_cap);
543 		MLX5_SET(ptys_reg, in, ib_link_width_capability,
544 			 ptys->ib_link_width_cap);
545 		MLX5_SET(ptys_reg, in, ib_proto_capability,
546 			 ptys->ib_proto_cap);
547 		MLX5_SET(ptys_reg, in, eth_proto_admin, ptys->eth_proto_admin);
548 		MLX5_SET(ptys_reg, in, ib_link_width_admin,
549 			 ptys->ib_link_width_admin);
550 		MLX5_SET(ptys_reg, in, ib_proto_admin, ptys->ib_proto_admin);
551 		MLX5_SET(ptys_reg, in, eth_proto_oper, ptys->eth_proto_oper);
552 		MLX5_SET(ptys_reg, in, ib_link_width_oper,
553 			 ptys->ib_link_width_oper);
554 		MLX5_SET(ptys_reg, in, ib_proto_oper, ptys->ib_proto_oper);
555 		MLX5_SET(ptys_reg, in, eth_proto_lp_advertise,
556 			 ptys->eth_proto_lp_advertise);
557 	}
558 
559 	err = mlx5_core_access_reg(dev, in, sz, out, sz, MLX5_REG_PTYS, 0,
560 				   !!write);
561 	if (err)
562 		goto out;
563 
564 	if (!write) {
565 		ptys->local_port = MLX5_GET(ptys_reg, out, local_port);
566 		ptys->proto_mask = MLX5_GET(ptys_reg, out, proto_mask);
567 		ptys->eth_proto_cap = MLX5_GET(ptys_reg, out,
568 					       eth_proto_capability);
569 		ptys->ib_link_width_cap = MLX5_GET(ptys_reg, out,
570 					   ib_link_width_capability);
571 		ptys->ib_proto_cap = MLX5_GET(ptys_reg, out,
572 					      ib_proto_capability);
573 		ptys->eth_proto_admin = MLX5_GET(ptys_reg, out,
574 						 eth_proto_admin);
575 		ptys->ib_link_width_admin = MLX5_GET(ptys_reg, out,
576 						     ib_link_width_admin);
577 		ptys->ib_proto_admin = MLX5_GET(ptys_reg, out, ib_proto_admin);
578 		ptys->eth_proto_oper = MLX5_GET(ptys_reg, out, eth_proto_oper);
579 		ptys->ib_link_width_oper = MLX5_GET(ptys_reg, out,
580 						    ib_link_width_oper);
581 		ptys->ib_proto_oper = MLX5_GET(ptys_reg, out, ib_proto_oper);
582 		ptys->eth_proto_lp_advertise = MLX5_GET(ptys_reg, out,
583 							eth_proto_lp_advertise);
584 	}
585 
586 out:
587 	kvfree(in);
588 	kvfree(out);
589 	return err;
590 }
591 EXPORT_SYMBOL_GPL(mlx5_core_access_ptys);
592 
593 static int mtu_to_ib_mtu(int mtu)
594 {
595 	switch (mtu) {
596 	case 256: return 1;
597 	case 512: return 2;
598 	case 1024: return 3;
599 	case 2048: return 4;
600 	case 4096: return 5;
601 	default:
602 		printf("mlx5_core: WARN: ""invalid mtu\n");
603 		return -1;
604 	}
605 }
606 
607 int mlx5_core_access_pmtu(struct mlx5_core_dev *dev,
608 			  struct mlx5_pmtu_reg *pmtu, int write)
609 {
610 	int sz = MLX5_ST_SZ_BYTES(pmtu_reg);
611 	void *out = NULL;
612 	void *in = NULL;
613 	int err;
614 
615 	in = mlx5_vzalloc(sz);
616 	if (!in)
617 		return -ENOMEM;
618 
619 	out = mlx5_vzalloc(sz);
620 	if (!out) {
621 		kfree(in);
622 		return -ENOMEM;
623 	}
624 
625 	MLX5_SET(pmtu_reg, in, local_port, pmtu->local_port);
626 	if (write)
627 		MLX5_SET(pmtu_reg, in, admin_mtu, pmtu->admin_mtu);
628 
629 	err = mlx5_core_access_reg(dev, in, sz, out, sz, MLX5_REG_PMTU, 0,
630 				   !!write);
631 	if (err)
632 		goto out;
633 
634 	if (!write) {
635 		pmtu->local_port = MLX5_GET(pmtu_reg, out, local_port);
636 		pmtu->max_mtu = mtu_to_ib_mtu(MLX5_GET(pmtu_reg, out,
637 						       max_mtu));
638 		pmtu->admin_mtu = mtu_to_ib_mtu(MLX5_GET(pmtu_reg, out,
639 							 admin_mtu));
640 		pmtu->oper_mtu = mtu_to_ib_mtu(MLX5_GET(pmtu_reg, out,
641 							oper_mtu));
642 	}
643 
644 out:
645 	kvfree(in);
646 	kvfree(out);
647 	return err;
648 }
649 EXPORT_SYMBOL_GPL(mlx5_core_access_pmtu);
650 
651 int mlx5_query_module_num(struct mlx5_core_dev *dev, int *module_num)
652 {
653 	u32 in[MLX5_ST_SZ_DW(pmlp_reg)] = {0};
654 	u32 out[MLX5_ST_SZ_DW(pmlp_reg)] = {0};
655 	int lane = 0;
656 	int err;
657 
658 	MLX5_SET(pmlp_reg, in, local_port, 1);
659 
660 	err = mlx5_core_access_reg(dev, in, sizeof(in), out,
661 				   sizeof(out), MLX5_REG_PMLP, 0, 0);
662 	if (err)
663 		return err;
664 
665 	lane = MLX5_GET(pmlp_reg, out, lane0_module_mapping);
666 	*module_num = lane & MLX5_EEPROM_IDENTIFIER_BYTE_MASK;
667 
668 	return 0;
669 }
670 EXPORT_SYMBOL_GPL(mlx5_query_module_num);
671 
672 int mlx5_query_eeprom(struct mlx5_core_dev *dev,
673 		      int i2c_addr, int page_num, int device_addr,
674 		      int size, int module_num, u32 *data, int *size_read)
675 {
676 	u32 in[MLX5_ST_SZ_DW(mcia_reg)] = {0};
677 	u32 out[MLX5_ST_SZ_DW(mcia_reg)] = {0};
678 	u32 *ptr = (u32 *)MLX5_ADDR_OF(mcia_reg, out, dword_0);
679 	int status;
680 	int err;
681 
682 	size = min_t(int, size, MLX5_EEPROM_MAX_BYTES);
683 
684 	MLX5_SET(mcia_reg, in, l, 0);
685 	MLX5_SET(mcia_reg, in, module, module_num);
686 	MLX5_SET(mcia_reg, in, i2c_device_address, i2c_addr);
687 	MLX5_SET(mcia_reg, in, page_number, page_num);
688 	MLX5_SET(mcia_reg, in, device_address, device_addr);
689 	MLX5_SET(mcia_reg, in, size, size);
690 
691 	err = mlx5_core_access_reg(dev, in, sizeof(in), out,
692 				   sizeof(out), MLX5_REG_MCIA, 0, 0);
693 	if (err)
694 		return err;
695 
696 	status = MLX5_GET(mcia_reg, out, status);
697 	if (status)
698 		return status;
699 
700 	memcpy(data, ptr, size);
701 	*size_read = size;
702 	return 0;
703 }
704 EXPORT_SYMBOL_GPL(mlx5_query_eeprom);
705 
706 int mlx5_vxlan_udp_port_add(struct mlx5_core_dev *dev, u16 port)
707 {
708 	u32 in[MLX5_ST_SZ_DW(add_vxlan_udp_dport_in)] = {0};
709 	u32 out[MLX5_ST_SZ_DW(add_vxlan_udp_dport_out)] = {0};
710 	int err;
711 
712 	MLX5_SET(add_vxlan_udp_dport_in, in, opcode,
713 		 MLX5_CMD_OP_ADD_VXLAN_UDP_DPORT);
714 	MLX5_SET(add_vxlan_udp_dport_in, in, vxlan_udp_port, port);
715 
716 	err = mlx5_cmd_exec(dev, in, sizeof(in), out, sizeof(out));
717 	if (err) {
718 		mlx5_core_err(dev, "Failed %s, port %u, err - %d",
719 			      mlx5_command_str(MLX5_CMD_OP_ADD_VXLAN_UDP_DPORT),
720 			      port, err);
721 	}
722 
723 	return err;
724 }
725 
726 int mlx5_vxlan_udp_port_delete(struct mlx5_core_dev *dev, u16 port)
727 {
728 	u32 in[MLX5_ST_SZ_DW(delete_vxlan_udp_dport_in)] = {0};
729 	u32 out[MLX5_ST_SZ_DW(delete_vxlan_udp_dport_out)] = {0};
730 	int err;
731 
732 	MLX5_SET(delete_vxlan_udp_dport_in, in, opcode,
733 		 MLX5_CMD_OP_DELETE_VXLAN_UDP_DPORT);
734 	MLX5_SET(delete_vxlan_udp_dport_in, in, vxlan_udp_port, port);
735 
736 	err = mlx5_cmd_exec(dev, in, sizeof(in), out, sizeof(out));
737 	if (err) {
738 		mlx5_core_err(dev, "Failed %s, port %u, err - %d",
739 			      mlx5_command_str(MLX5_CMD_OP_DELETE_VXLAN_UDP_DPORT),
740 			      port, err);
741 	}
742 
743 	return err;
744 }
745 
746 int mlx5_query_wol(struct mlx5_core_dev *dev, u8 *wol_mode)
747 {
748 	u32 in[MLX5_ST_SZ_DW(query_wol_rol_in)] = {0};
749 	u32 out[MLX5_ST_SZ_DW(query_wol_rol_out)] = {0};
750 	int err;
751 
752 	MLX5_SET(query_wol_rol_in, in, opcode, MLX5_CMD_OP_QUERY_WOL_ROL);
753 
754 	err = mlx5_cmd_exec(dev, in, sizeof(in), out, sizeof(out));
755 
756 	if (!err)
757 		*wol_mode = MLX5_GET(query_wol_rol_out, out, wol_mode);
758 
759 	return err;
760 }
761 EXPORT_SYMBOL_GPL(mlx5_query_wol);
762 
763 int mlx5_query_port_cong_status(struct mlx5_core_dev *mdev, int protocol,
764 				int priority, int *is_enable)
765 {
766 	u32 in[MLX5_ST_SZ_DW(query_cong_status_in)] = {0};
767 	u32 out[MLX5_ST_SZ_DW(query_cong_status_out)] = {0};
768 	int err;
769 
770 	*is_enable = 0;
771 
772 	MLX5_SET(query_cong_status_in, in, opcode,
773 		 MLX5_CMD_OP_QUERY_CONG_STATUS);
774 	MLX5_SET(query_cong_status_in, in, cong_protocol, protocol);
775 	MLX5_SET(query_cong_status_in, in, priority, priority);
776 
777 	err = mlx5_cmd_exec(mdev, in, sizeof(in), out, sizeof(out));
778 	if (!err)
779 		*is_enable = MLX5_GET(query_cong_status_out, out, enable);
780 	return err;
781 }
782 
783 int mlx5_modify_port_cong_status(struct mlx5_core_dev *mdev, int protocol,
784 				 int priority, int enable)
785 {
786 	u32 in[MLX5_ST_SZ_DW(modify_cong_status_in)] = {0};
787 	u32 out[MLX5_ST_SZ_DW(modify_cong_status_out)] = {0};
788 
789 	MLX5_SET(modify_cong_status_in, in, opcode,
790 		 MLX5_CMD_OP_MODIFY_CONG_STATUS);
791 	MLX5_SET(modify_cong_status_in, in, cong_protocol, protocol);
792 	MLX5_SET(modify_cong_status_in, in, priority, priority);
793 	MLX5_SET(modify_cong_status_in, in, enable, enable);
794 
795 	return mlx5_cmd_exec(mdev, in, sizeof(in), out, sizeof(out));
796 }
797 
798 int mlx5_query_port_cong_params(struct mlx5_core_dev *mdev, int protocol,
799 				void *out, int out_size)
800 {
801 	u32 in[MLX5_ST_SZ_DW(query_cong_params_in)] = {0};
802 
803 	MLX5_SET(query_cong_params_in, in, opcode,
804 		 MLX5_CMD_OP_QUERY_CONG_PARAMS);
805 	MLX5_SET(query_cong_params_in, in, cong_protocol, protocol);
806 
807 	return mlx5_cmd_exec(mdev, in, sizeof(in), out, out_size);
808 }
809 
810 static int mlx5_query_port_qetcr_reg(struct mlx5_core_dev *mdev, u32 *out,
811 				     int outlen)
812 {
813 	u32 in[MLX5_ST_SZ_DW(qtct_reg)];
814 
815 	if (!MLX5_CAP_GEN(mdev, ets))
816 		return -ENOTSUPP;
817 
818 	memset(in, 0, sizeof(in));
819 	return mlx5_core_access_reg(mdev, in, sizeof(in), out, outlen,
820 				    MLX5_REG_QETCR, 0, 0);
821 }
822 
823 int mlx5_max_tc(struct mlx5_core_dev *mdev)
824 {
825 	u8 num_tc = MLX5_CAP_GEN(mdev, max_tc) ? : 8;
826 
827 	return num_tc - 1;
828 }
829 EXPORT_SYMBOL_GPL(mlx5_max_tc);
830 
831 static int mlx5_set_port_qetcr_reg(struct mlx5_core_dev *mdev, u32 *in,
832 				   int inlen)
833 {
834 	u32 out[MLX5_ST_SZ_DW(qtct_reg)];
835 
836 	if (!MLX5_CAP_GEN(mdev, ets))
837 		return -ENOTSUPP;
838 
839 	return mlx5_core_access_reg(mdev, in, inlen, out, sizeof(out),
840 				    MLX5_REG_QETCR, 0, 1);
841 }
842 
843 int mlx5_query_port_tc_rate_limit(struct mlx5_core_dev *mdev,
844 				   u8 *max_bw_value,
845 				   u8 *max_bw_units)
846 {
847 	u32 out[MLX5_ST_SZ_DW(qetc_reg)];
848 	void *ets_tcn_conf;
849 	int err;
850 	int i;
851 
852 	err = mlx5_query_port_qetcr_reg(mdev, out, sizeof(out));
853 	if (err)
854 		return err;
855 
856 	for (i = 0; i <= mlx5_max_tc(mdev); i++) {
857 		ets_tcn_conf = MLX5_ADDR_OF(qetc_reg, out, tc_configuration[i]);
858 
859 		max_bw_value[i] = MLX5_GET(ets_tcn_config_reg, ets_tcn_conf,
860 					   max_bw_value);
861 		max_bw_units[i] = MLX5_GET(ets_tcn_config_reg, ets_tcn_conf,
862 					   max_bw_units);
863 	}
864 
865 	return 0;
866 }
867 EXPORT_SYMBOL_GPL(mlx5_query_port_tc_rate_limit);
868 
869 int mlx5_modify_port_tc_rate_limit(struct mlx5_core_dev *mdev,
870 				   const u8 *max_bw_value,
871 				   const u8 *max_bw_units)
872 {
873 	u32 in[MLX5_ST_SZ_DW(qetc_reg)] = {};
874 	void *ets_tcn_conf;
875 	int i;
876 
877 	MLX5_SET(qetc_reg, in, port_number, 1);
878 
879 	for (i = 0; i <= mlx5_max_tc(mdev); i++) {
880 		ets_tcn_conf = MLX5_ADDR_OF(qetc_reg, in, tc_configuration[i]);
881 
882 		MLX5_SET(ets_tcn_config_reg, ets_tcn_conf, r, 1);
883 		MLX5_SET(ets_tcn_config_reg, ets_tcn_conf, max_bw_units,
884 			 max_bw_units[i]);
885 		MLX5_SET(ets_tcn_config_reg, ets_tcn_conf, max_bw_value,
886 			 max_bw_value[i]);
887 	}
888 
889 	return mlx5_set_port_qetcr_reg(mdev, in, sizeof(in));
890 }
891 EXPORT_SYMBOL_GPL(mlx5_modify_port_tc_rate_limit);
892 
893 int mlx5_query_port_prio_tc(struct mlx5_core_dev *mdev,
894 			    u8 prio, u8 *tc)
895 {
896 	u32 in[MLX5_ST_SZ_DW(qtct_reg)];
897 	u32 out[MLX5_ST_SZ_DW(qtct_reg)];
898 	int err;
899 
900 	memset(in, 0, sizeof(in));
901 	memset(out, 0, sizeof(out));
902 
903 	MLX5_SET(qtct_reg, in, port_number, 1);
904 	MLX5_SET(qtct_reg, in, prio, prio);
905 
906 	err = mlx5_core_access_reg(mdev, in, sizeof(in), out,
907 				   sizeof(out), MLX5_REG_QTCT, 0, 0);
908 	if (!err)
909 		*tc = MLX5_GET(qtct_reg, out, tclass);
910 
911 	return err;
912 }
913 EXPORT_SYMBOL_GPL(mlx5_query_port_prio_tc);
914 
915 int mlx5_set_port_prio_tc(struct mlx5_core_dev *mdev, int prio_index,
916 			  const u8 prio_tc)
917 {
918 	u32 in[MLX5_ST_SZ_DW(qtct_reg)] = {};
919 	u32 out[MLX5_ST_SZ_DW(qtct_reg)];
920 	int err;
921 
922 	if (prio_tc > mlx5_max_tc(mdev))
923 		return -EINVAL;
924 
925 	MLX5_SET(qtct_reg, in, prio, prio_index);
926 	MLX5_SET(qtct_reg, in, tclass, prio_tc);
927 
928 	err = mlx5_core_access_reg(mdev, in, sizeof(in), out,
929 				   sizeof(out), MLX5_REG_QTCT, 0, 1);
930 
931 	return (err);
932 }
933 EXPORT_SYMBOL_GPL(mlx5_set_port_prio_tc);
934 
935 int mlx5_modify_port_cong_params(struct mlx5_core_dev *mdev,
936 				 void *in, int in_size)
937 {
938 	u32 out[MLX5_ST_SZ_DW(modify_cong_params_out)] = {0};
939 
940 	MLX5_SET(modify_cong_params_in, in, opcode,
941 		 MLX5_CMD_OP_MODIFY_CONG_PARAMS);
942 
943 	return mlx5_cmd_exec(mdev, in, in_size, out, sizeof(out));
944 }
945 
946 int mlx5_query_port_cong_statistics(struct mlx5_core_dev *mdev, int clear,
947 				    void *out, int out_size)
948 {
949 	u32 in[MLX5_ST_SZ_DW(query_cong_statistics_in)] = {0};
950 
951 	MLX5_SET(query_cong_statistics_in, in, opcode,
952 		 MLX5_CMD_OP_QUERY_CONG_STATISTICS);
953 	MLX5_SET(query_cong_statistics_in, in, clear, clear);
954 
955 	return mlx5_cmd_exec(mdev, in, sizeof(in), out, out_size);
956 }
957 
958 int mlx5_set_diagnostic_params(struct mlx5_core_dev *mdev, void *in,
959 			       int in_size)
960 {
961 	u32 out[MLX5_ST_SZ_DW(set_diagnostic_params_out)] = {0};
962 
963 	MLX5_SET(set_diagnostic_params_in, in, opcode,
964 		 MLX5_CMD_OP_SET_DIAGNOSTICS);
965 
966 	return mlx5_cmd_exec(mdev, in, in_size, out, sizeof(out));
967 }
968 
969 int mlx5_query_diagnostic_counters(struct mlx5_core_dev *mdev,
970 				   u8 num_of_samples, u16 sample_index,
971 				   void *out, int out_size)
972 {
973 	u32 in[MLX5_ST_SZ_DW(query_diagnostic_counters_in)] = {0};
974 
975 	MLX5_SET(query_diagnostic_counters_in, in, opcode,
976 		 MLX5_CMD_OP_QUERY_DIAGNOSTICS);
977 	MLX5_SET(query_diagnostic_counters_in, in, num_of_samples,
978 		 num_of_samples);
979 	MLX5_SET(query_diagnostic_counters_in, in, sample_index, sample_index);
980 
981 	return mlx5_cmd_exec(mdev, in, sizeof(in), out, out_size);
982 }
983 
984 int mlx5_set_trust_state(struct mlx5_core_dev *mdev, u8 trust_state)
985 {
986 	u32 out[MLX5_ST_SZ_DW(qpts_reg)] = {};
987 	u32 in[MLX5_ST_SZ_DW(qpts_reg)] = {};
988 	int err;
989 
990 	MLX5_SET(qpts_reg, in, local_port, 1);
991 	MLX5_SET(qpts_reg, in, trust_state, trust_state);
992 
993 	err = mlx5_core_access_reg(mdev, in, sizeof(in), out,
994 				   sizeof(out), MLX5_REG_QPTS, 0, 1);
995 	return err;
996 }
997 
998 int mlx5_query_trust_state(struct mlx5_core_dev *mdev, u8 *trust_state)
999 {
1000 	u32 out[MLX5_ST_SZ_DW(qpts_reg)] = {};
1001 	u32 in[MLX5_ST_SZ_DW(qpts_reg)] = {};
1002 	int err;
1003 
1004 	MLX5_SET(qpts_reg, in, local_port, 1);
1005 
1006 	err = mlx5_core_access_reg(mdev, in, sizeof(in), out,
1007 				   sizeof(out), MLX5_REG_QPTS, 0, 0);
1008 	if (!err)
1009 		*trust_state = MLX5_GET(qpts_reg, out, trust_state);
1010 
1011 	return err;
1012 }
1013 
1014 int mlx5_set_dscp2prio(struct mlx5_core_dev *mdev, const u8 *dscp2prio)
1015 {
1016 	int sz = MLX5_ST_SZ_BYTES(qpdpm_reg);
1017 	void *qpdpm_dscp;
1018 	void *out;
1019 	void *in;
1020 	int err;
1021 	int i;
1022 
1023 	in = kzalloc(sz, GFP_KERNEL);
1024 	out = kzalloc(sz, GFP_KERNEL);
1025 	if (!in || !out) {
1026 		err = -ENOMEM;
1027 		goto out;
1028 	}
1029 
1030 	MLX5_SET(qpdpm_reg, in, local_port, 1);
1031 	err = mlx5_core_access_reg(mdev, in, sz, out, sz, MLX5_REG_QPDPM, 0, 0);
1032 	if (err)
1033 		goto out;
1034 
1035 	memcpy(in, out, sz);
1036 	MLX5_SET(qpdpm_reg, in, local_port, 1);
1037 
1038 	/* Update the corresponding dscp entry */
1039 	for (i = 0; i < MLX5_MAX_SUPPORTED_DSCP; i++) {
1040 		qpdpm_dscp = MLX5_ADDR_OF(qpdpm_reg, in, dscp[i]);
1041 		MLX5_SET16(qpdpm_dscp_reg, qpdpm_dscp, prio, dscp2prio[i]);
1042 		MLX5_SET16(qpdpm_dscp_reg, qpdpm_dscp, e, 1);
1043 	}
1044 	err = mlx5_core_access_reg(mdev, in, sz, out, sz, MLX5_REG_QPDPM, 0, 1);
1045 out:
1046 	kfree(in);
1047 	kfree(out);
1048 	return err;
1049 }
1050 
1051 int mlx5_query_dscp2prio(struct mlx5_core_dev *mdev, u8 *dscp2prio)
1052 {
1053 	int sz = MLX5_ST_SZ_BYTES(qpdpm_reg);
1054 	void *qpdpm_dscp;
1055 	void *out;
1056 	void *in;
1057 	int err;
1058 	int i;
1059 
1060 	in = kzalloc(sz, GFP_KERNEL);
1061 	out = kzalloc(sz, GFP_KERNEL);
1062 	if (!in || !out) {
1063 		err = -ENOMEM;
1064 		goto out;
1065 	}
1066 
1067 	MLX5_SET(qpdpm_reg, in, local_port, 1);
1068 	err = mlx5_core_access_reg(mdev, in, sz, out, sz, MLX5_REG_QPDPM, 0, 0);
1069 	if (err)
1070 		goto out;
1071 
1072 	for (i = 0; i < MLX5_MAX_SUPPORTED_DSCP; i++) {
1073 		qpdpm_dscp = MLX5_ADDR_OF(qpdpm_reg, out, dscp[i]);
1074 		dscp2prio[i] = MLX5_GET16(qpdpm_dscp_reg, qpdpm_dscp, prio);
1075 	}
1076 out:
1077 	kfree(in);
1078 	kfree(out);
1079 	return err;
1080 }
1081