mlx5_port.c revision 341968
1/*-
2 * Copyright (c) 2013-2018, 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: stable/11/sys/dev/mlx5/mlx5_core/mlx5_port.c 341968 2018-12-12 12:55:53Z hselasky $
26 */
27
28#include <linux/module.h>
29#include <dev/mlx5/port.h>
30#include "mlx5_core.h"
31
32int 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
62out:
63	kvfree(out);
64	kvfree(in);
65	return err;
66}
67EXPORT_SYMBOL_GPL(mlx5_core_access_reg);
68
69int 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}
80EXPORT_SYMBOL_GPL(mlx5_query_qcam_reg);
81
82struct 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 */
93void 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}
102EXPORT_SYMBOL_GPL(mlx5_toggle_port_link);
103
104int 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}
119EXPORT_SYMBOL_GPL(mlx5_set_port_caps);
120
121int 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}
136EXPORT_SYMBOL_GPL(mlx5_query_port_ptys);
137
138int 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}
155EXPORT_SYMBOL_GPL(mlx5_query_port_proto_cap);
156
157int 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}
172EXPORT_SYMBOL_GPL(mlx5_query_port_autoneg);
173
174int 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}
200EXPORT_SYMBOL_GPL(mlx5_set_port_autoneg);
201
202int 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}
219EXPORT_SYMBOL_GPL(mlx5_query_port_proto_admin);
220
221int 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}
236EXPORT_SYMBOL(mlx5_query_port_eth_proto_oper);
237
238int 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}
256EXPORT_SYMBOL_GPL(mlx5_set_port_proto);
257
258int 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
275int 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
292int 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}
307EXPORT_SYMBOL_GPL(mlx5_query_port_admin_status);
308
309static 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
333int 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}
344EXPORT_SYMBOL_GPL(mlx5_set_port_mtu);
345
346int 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}
350EXPORT_SYMBOL_GPL(mlx5_query_port_max_mtu);
351
352int 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
377int 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
397int 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}
415EXPORT_SYMBOL_GPL(mlx5_query_port_pfc);
416
417int 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}
421EXPORT_SYMBOL_GPL(mlx5_query_port_oper_mtu);
422
423u8 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}
444EXPORT_SYMBOL_GPL(mlx5_is_wol_supported);
445
446int 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}
457EXPORT_SYMBOL_GPL(mlx5_set_wol);
458
459int 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}
477EXPORT_SYMBOL_GPL(mlx5_query_dropless_mode);
478
479int 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}
490EXPORT_SYMBOL_GPL(mlx5_set_dropless_mode);
491
492int 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}
518EXPORT_SYMBOL_GPL(mlx5_core_access_pvlc);
519
520int 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
586out:
587	kvfree(in);
588	kvfree(out);
589	return err;
590}
591EXPORT_SYMBOL_GPL(mlx5_core_access_ptys);
592
593static 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
607int 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
644out:
645	kvfree(in);
646	kvfree(out);
647	return err;
648}
649EXPORT_SYMBOL_GPL(mlx5_core_access_pmtu);
650
651int 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}
670EXPORT_SYMBOL_GPL(mlx5_query_module_num);
671
672int 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}
704EXPORT_SYMBOL_GPL(mlx5_query_eeprom);
705
706int 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
726int 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
746int 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}
761EXPORT_SYMBOL_GPL(mlx5_query_wol);
762
763int 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
783int 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
798int 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
810static int mlx5_query_port_qetcr_reg(struct mlx5_core_dev *mdev, u32 *out,
811				     int outlen)
812{
813	u32 in[MLX5_ST_SZ_DW(qetc_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
823int 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}
829EXPORT_SYMBOL_GPL(mlx5_max_tc);
830
831static int mlx5_set_port_qetcr_reg(struct mlx5_core_dev *mdev, u32 *in,
832				   int inlen)
833{
834	u32 out[MLX5_ST_SZ_DW(qetc_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
843int 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}
867EXPORT_SYMBOL_GPL(mlx5_query_port_tc_rate_limit);
868
869int 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}
891EXPORT_SYMBOL_GPL(mlx5_modify_port_tc_rate_limit);
892
893int 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}
913EXPORT_SYMBOL_GPL(mlx5_query_port_prio_tc);
914
915int 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}
933EXPORT_SYMBOL_GPL(mlx5_set_port_prio_tc);
934
935int mlx5_set_port_tc_group(struct mlx5_core_dev *mdev, const u8 *tc_group)
936{
937	u32 in[MLX5_ST_SZ_DW(qetc_reg)] = {};
938	int i;
939
940	for (i = 0; i <= mlx5_max_tc(mdev); i++) {
941		MLX5_SET(qetc_reg, in, tc_configuration[i].g, 1);
942		MLX5_SET(qetc_reg, in, tc_configuration[i].group, tc_group[i]);
943	}
944
945	return mlx5_set_port_qetcr_reg(mdev, in, sizeof(in));
946}
947EXPORT_SYMBOL_GPL(mlx5_set_port_tc_group);
948
949int mlx5_query_port_tc_group(struct mlx5_core_dev *mdev,
950			     u8 tc, u8 *tc_group)
951{
952	u32 out[MLX5_ST_SZ_DW(qetc_reg)];
953	void *ets_tcn_conf;
954	int err;
955
956	err = mlx5_query_port_qetcr_reg(mdev, out, sizeof(out));
957	if (err)
958		return err;
959
960	ets_tcn_conf = MLX5_ADDR_OF(qetc_reg, out,
961				    tc_configuration[tc]);
962
963	*tc_group = MLX5_GET(ets_tcn_config_reg, ets_tcn_conf,
964			     group);
965
966	return 0;
967}
968EXPORT_SYMBOL_GPL(mlx5_query_port_tc_group);
969
970int mlx5_set_port_tc_bw_alloc(struct mlx5_core_dev *mdev, const u8 *tc_bw)
971{
972	u32 in[MLX5_ST_SZ_DW(qetc_reg)] = {};
973	int i;
974
975	for (i = 0; i <= mlx5_max_tc(mdev); i++) {
976		MLX5_SET(qetc_reg, in, tc_configuration[i].b, 1);
977		MLX5_SET(qetc_reg, in, tc_configuration[i].bw_allocation, tc_bw[i]);
978	}
979
980	return mlx5_set_port_qetcr_reg(mdev, in, sizeof(in));
981}
982EXPORT_SYMBOL_GPL(mlx5_set_port_tc_bw_alloc);
983
984int mlx5_query_port_tc_bw_alloc(struct mlx5_core_dev *mdev, u8 *bw_pct)
985{
986	u32 out[MLX5_ST_SZ_DW(qetc_reg)];
987	void *ets_tcn_conf;
988	int err;
989	int i;
990
991	err = mlx5_query_port_qetcr_reg(mdev, out, sizeof(out));
992	if (err)
993		return err;
994
995	for (i = 0; i <= mlx5_max_tc(mdev); i++) {
996		ets_tcn_conf = MLX5_ADDR_OF(qetc_reg, out, tc_configuration[i]);
997		bw_pct[i] = MLX5_GET(ets_tcn_config_reg, ets_tcn_conf, bw_allocation);
998	}
999	return 0;
1000}
1001EXPORT_SYMBOL_GPL(mlx5_query_port_tc_bw_alloc);
1002
1003int mlx5_modify_port_cong_params(struct mlx5_core_dev *mdev,
1004				 void *in, int in_size)
1005{
1006	u32 out[MLX5_ST_SZ_DW(modify_cong_params_out)] = {0};
1007
1008	MLX5_SET(modify_cong_params_in, in, opcode,
1009		 MLX5_CMD_OP_MODIFY_CONG_PARAMS);
1010
1011	return mlx5_cmd_exec(mdev, in, in_size, out, sizeof(out));
1012}
1013
1014int mlx5_query_port_cong_statistics(struct mlx5_core_dev *mdev, int clear,
1015				    void *out, int out_size)
1016{
1017	u32 in[MLX5_ST_SZ_DW(query_cong_statistics_in)] = {0};
1018
1019	MLX5_SET(query_cong_statistics_in, in, opcode,
1020		 MLX5_CMD_OP_QUERY_CONG_STATISTICS);
1021	MLX5_SET(query_cong_statistics_in, in, clear, clear);
1022
1023	return mlx5_cmd_exec(mdev, in, sizeof(in), out, out_size);
1024}
1025
1026int mlx5_set_diagnostic_params(struct mlx5_core_dev *mdev, void *in,
1027			       int in_size)
1028{
1029	u32 out[MLX5_ST_SZ_DW(set_diagnostic_params_out)] = {0};
1030
1031	MLX5_SET(set_diagnostic_params_in, in, opcode,
1032		 MLX5_CMD_OP_SET_DIAGNOSTICS);
1033
1034	return mlx5_cmd_exec(mdev, in, in_size, out, sizeof(out));
1035}
1036
1037int mlx5_query_diagnostic_counters(struct mlx5_core_dev *mdev,
1038				   u8 num_of_samples, u16 sample_index,
1039				   void *out, int out_size)
1040{
1041	u32 in[MLX5_ST_SZ_DW(query_diagnostic_counters_in)] = {0};
1042
1043	MLX5_SET(query_diagnostic_counters_in, in, opcode,
1044		 MLX5_CMD_OP_QUERY_DIAGNOSTICS);
1045	MLX5_SET(query_diagnostic_counters_in, in, num_of_samples,
1046		 num_of_samples);
1047	MLX5_SET(query_diagnostic_counters_in, in, sample_index, sample_index);
1048
1049	return mlx5_cmd_exec(mdev, in, sizeof(in), out, out_size);
1050}
1051
1052int mlx5_set_trust_state(struct mlx5_core_dev *mdev, u8 trust_state)
1053{
1054	u32 out[MLX5_ST_SZ_DW(qpts_reg)] = {};
1055	u32 in[MLX5_ST_SZ_DW(qpts_reg)] = {};
1056	int err;
1057
1058	MLX5_SET(qpts_reg, in, local_port, 1);
1059	MLX5_SET(qpts_reg, in, trust_state, trust_state);
1060
1061	err = mlx5_core_access_reg(mdev, in, sizeof(in), out,
1062				   sizeof(out), MLX5_REG_QPTS, 0, 1);
1063	return err;
1064}
1065
1066int mlx5_query_trust_state(struct mlx5_core_dev *mdev, u8 *trust_state)
1067{
1068	u32 out[MLX5_ST_SZ_DW(qpts_reg)] = {};
1069	u32 in[MLX5_ST_SZ_DW(qpts_reg)] = {};
1070	int err;
1071
1072	MLX5_SET(qpts_reg, in, local_port, 1);
1073
1074	err = mlx5_core_access_reg(mdev, in, sizeof(in), out,
1075				   sizeof(out), MLX5_REG_QPTS, 0, 0);
1076	if (!err)
1077		*trust_state = MLX5_GET(qpts_reg, out, trust_state);
1078
1079	return err;
1080}
1081
1082int mlx5_set_dscp2prio(struct mlx5_core_dev *mdev, const u8 *dscp2prio)
1083{
1084	int sz = MLX5_ST_SZ_BYTES(qpdpm_reg);
1085	void *qpdpm_dscp;
1086	void *out;
1087	void *in;
1088	int err;
1089	int i;
1090
1091	in = kzalloc(sz, GFP_KERNEL);
1092	out = kzalloc(sz, GFP_KERNEL);
1093	if (!in || !out) {
1094		err = -ENOMEM;
1095		goto out;
1096	}
1097
1098	MLX5_SET(qpdpm_reg, in, local_port, 1);
1099	err = mlx5_core_access_reg(mdev, in, sz, out, sz, MLX5_REG_QPDPM, 0, 0);
1100	if (err)
1101		goto out;
1102
1103	memcpy(in, out, sz);
1104	MLX5_SET(qpdpm_reg, in, local_port, 1);
1105
1106	/* Update the corresponding dscp entry */
1107	for (i = 0; i < MLX5_MAX_SUPPORTED_DSCP; i++) {
1108		qpdpm_dscp = MLX5_ADDR_OF(qpdpm_reg, in, dscp[i]);
1109		MLX5_SET16(qpdpm_dscp_reg, qpdpm_dscp, prio, dscp2prio[i]);
1110		MLX5_SET16(qpdpm_dscp_reg, qpdpm_dscp, e, 1);
1111	}
1112	err = mlx5_core_access_reg(mdev, in, sz, out, sz, MLX5_REG_QPDPM, 0, 1);
1113out:
1114	kfree(in);
1115	kfree(out);
1116	return err;
1117}
1118
1119int mlx5_query_dscp2prio(struct mlx5_core_dev *mdev, u8 *dscp2prio)
1120{
1121	int sz = MLX5_ST_SZ_BYTES(qpdpm_reg);
1122	void *qpdpm_dscp;
1123	void *out;
1124	void *in;
1125	int err;
1126	int i;
1127
1128	in = kzalloc(sz, GFP_KERNEL);
1129	out = kzalloc(sz, GFP_KERNEL);
1130	if (!in || !out) {
1131		err = -ENOMEM;
1132		goto out;
1133	}
1134
1135	MLX5_SET(qpdpm_reg, in, local_port, 1);
1136	err = mlx5_core_access_reg(mdev, in, sz, out, sz, MLX5_REG_QPDPM, 0, 0);
1137	if (err)
1138		goto out;
1139
1140	for (i = 0; i < MLX5_MAX_SUPPORTED_DSCP; i++) {
1141		qpdpm_dscp = MLX5_ADDR_OF(qpdpm_reg, out, dscp[i]);
1142		dscp2prio[i] = MLX5_GET16(qpdpm_dscp_reg, qpdpm_dscp, prio);
1143	}
1144out:
1145	kfree(in);
1146	kfree(out);
1147	return err;
1148}
1149