xref: /freebsd/sys/dev/mlx5/mlx5_core/mlx5_port.c (revision 5d3e7166)
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$
26  */
27 
28 #include "opt_rss.h"
29 #include "opt_ratelimit.h"
30 
31 #include <linux/module.h>
32 #include <dev/mlx5/port.h>
33 #include <dev/mlx5/mlx5_core/mlx5_core.h>
34 
35 int mlx5_core_access_reg(struct mlx5_core_dev *dev, void *data_in,
36 			 int size_in, void *data_out, int size_out,
37 			 u16 reg_num, int arg, int write)
38 {
39 	int outlen = MLX5_ST_SZ_BYTES(access_register_out) + size_out;
40 	int inlen = MLX5_ST_SZ_BYTES(access_register_in) + size_in;
41 	int err = -ENOMEM;
42 	u32 *out = NULL;
43 	u32 *in = NULL;
44 	void *data;
45 
46 	in = mlx5_vzalloc(inlen);
47 	out = mlx5_vzalloc(outlen);
48 	if (!in || !out)
49 		goto out;
50 
51 	data = MLX5_ADDR_OF(access_register_in, in, register_data);
52 	memcpy(data, data_in, size_in);
53 
54 	MLX5_SET(access_register_in, in, opcode, MLX5_CMD_OP_ACCESS_REG);
55 	MLX5_SET(access_register_in, in, op_mod, !write);
56 	MLX5_SET(access_register_in, in, argument, arg);
57 	MLX5_SET(access_register_in, in, register_id, reg_num);
58 
59 	err = mlx5_cmd_exec(dev, in, inlen, out, outlen);
60 	if (err)
61 		goto out;
62 	data = MLX5_ADDR_OF(access_register_out, out, register_data);
63 	memcpy(data_out, data, size_out);
64 
65 out:
66 	kvfree(out);
67 	kvfree(in);
68 	return err;
69 }
70 EXPORT_SYMBOL_GPL(mlx5_core_access_reg);
71 
72 int mlx5_query_qcam_reg(struct mlx5_core_dev *mdev, u32 *qcam,
73 			u8 feature_group, u8 access_reg_group)
74 {
75 	u32 in[MLX5_ST_SZ_DW(qcam_reg)] = {};
76 	int sz = MLX5_ST_SZ_BYTES(qcam_reg);
77 
78 	MLX5_SET(qcam_reg, in, feature_group, feature_group);
79 	MLX5_SET(qcam_reg, in, access_reg_group, access_reg_group);
80 
81 	return mlx5_core_access_reg(mdev, in, sz, qcam, sz, MLX5_REG_QCAM, 0, 0);
82 }
83 EXPORT_SYMBOL_GPL(mlx5_query_qcam_reg);
84 
85 int mlx5_query_pcam_reg(struct mlx5_core_dev *dev, u32 *pcam, u8 feature_group,
86 			u8 access_reg_group)
87 {
88 	u32 in[MLX5_ST_SZ_DW(pcam_reg)] = {};
89 	int sz = MLX5_ST_SZ_BYTES(pcam_reg);
90 
91 	MLX5_SET(pcam_reg, in, feature_group, feature_group);
92 	MLX5_SET(pcam_reg, in, access_reg_group, access_reg_group);
93 
94 	return mlx5_core_access_reg(dev, in, sz, pcam, sz, MLX5_REG_PCAM, 0, 0);
95 }
96 
97 int mlx5_query_mcam_reg(struct mlx5_core_dev *dev, u32 *mcam, u8 feature_group,
98 			u8 access_reg_group)
99 {
100 	u32 in[MLX5_ST_SZ_DW(mcam_reg)] = {};
101 	int sz = MLX5_ST_SZ_BYTES(mcam_reg);
102 
103 	MLX5_SET(mcam_reg, in, feature_group, feature_group);
104 	MLX5_SET(mcam_reg, in, access_reg_group, access_reg_group);
105 
106 	return mlx5_core_access_reg(dev, in, sz, mcam, sz, MLX5_REG_MCAM, 0, 0);
107 }
108 
109 struct mlx5_reg_pcap {
110 	u8			rsvd0;
111 	u8			port_num;
112 	u8			rsvd1[2];
113 	__be32			caps_127_96;
114 	__be32			caps_95_64;
115 	__be32			caps_63_32;
116 	__be32			caps_31_0;
117 };
118 
119 /* This function should be used after setting a port register only */
120 void mlx5_toggle_port_link(struct mlx5_core_dev *dev)
121 {
122 	enum mlx5_port_status ps;
123 
124 	mlx5_query_port_admin_status(dev, &ps);
125 	mlx5_set_port_status(dev, MLX5_PORT_DOWN);
126 	if (ps == MLX5_PORT_UP)
127 		mlx5_set_port_status(dev, MLX5_PORT_UP);
128 }
129 EXPORT_SYMBOL_GPL(mlx5_toggle_port_link);
130 
131 int mlx5_set_port_caps(struct mlx5_core_dev *dev, u8 port_num, u32 caps)
132 {
133 	struct mlx5_reg_pcap in;
134 	struct mlx5_reg_pcap out;
135 	int err;
136 
137 	memset(&in, 0, sizeof(in));
138 	in.caps_127_96 = cpu_to_be32(caps);
139 	in.port_num = port_num;
140 
141 	err = mlx5_core_access_reg(dev, &in, sizeof(in), &out,
142 				   sizeof(out), MLX5_REG_PCAP, 0, 1);
143 
144 	return err;
145 }
146 EXPORT_SYMBOL_GPL(mlx5_set_port_caps);
147 
148 int mlx5_query_port_ptys(struct mlx5_core_dev *dev, u32 *ptys,
149 			 int ptys_size, int proto_mask, u8 local_port)
150 {
151 	u32 in[MLX5_ST_SZ_DW(ptys_reg)];
152 	int err;
153 
154 	memset(in, 0, sizeof(in));
155 	MLX5_SET(ptys_reg, in, local_port, local_port);
156 	MLX5_SET(ptys_reg, in, proto_mask, proto_mask);
157 
158 	err = mlx5_core_access_reg(dev, in, sizeof(in), ptys,
159 				   ptys_size, MLX5_REG_PTYS, 0, 0);
160 
161 	return err;
162 }
163 EXPORT_SYMBOL_GPL(mlx5_query_port_ptys);
164 
165 int mlx5_query_port_proto_cap(struct mlx5_core_dev *dev,
166 			      u32 *proto_cap, int proto_mask)
167 {
168 	u32 out[MLX5_ST_SZ_DW(ptys_reg)];
169 	int err;
170 
171 	err = mlx5_query_port_ptys(dev, out, sizeof(out), proto_mask, 1);
172 	if (err)
173 		return err;
174 
175 	if (proto_mask == MLX5_PTYS_EN)
176 		*proto_cap = MLX5_GET(ptys_reg, out, eth_proto_capability);
177 	else
178 		*proto_cap = MLX5_GET(ptys_reg, out, ib_proto_capability);
179 
180 	return 0;
181 }
182 EXPORT_SYMBOL_GPL(mlx5_query_port_proto_cap);
183 
184 int mlx5_query_port_autoneg(struct mlx5_core_dev *dev, int proto_mask,
185 			    u8 *an_disable_cap, u8 *an_disable_status)
186 {
187 	u32 out[MLX5_ST_SZ_DW(ptys_reg)];
188 	int err;
189 
190 	err = mlx5_query_port_ptys(dev, out, sizeof(out), proto_mask, 1);
191 	if (err)
192 		return err;
193 
194 	*an_disable_status = MLX5_GET(ptys_reg, out, an_disable_admin);
195 	*an_disable_cap = MLX5_GET(ptys_reg, out, an_disable_cap);
196 
197 	return 0;
198 }
199 EXPORT_SYMBOL_GPL(mlx5_query_port_autoneg);
200 
201 int mlx5_set_port_autoneg(struct mlx5_core_dev *dev, bool disable,
202 			  u32 eth_proto_admin, int proto_mask)
203 {
204 	u32 in[MLX5_ST_SZ_DW(ptys_reg)] = {0};
205 	u32 out[MLX5_ST_SZ_DW(ptys_reg)] = {0};
206 	u8 an_disable_cap;
207 	u8 an_disable_status;
208 	int err;
209 
210 	err = mlx5_query_port_autoneg(dev, proto_mask, &an_disable_cap,
211 				      &an_disable_status);
212 	if (err)
213 		return err;
214 	if (!an_disable_cap)
215 		return -EPERM;
216 
217 	MLX5_SET(ptys_reg, in, local_port, 1);
218 	MLX5_SET(ptys_reg, in, an_disable_admin, disable);
219 	MLX5_SET(ptys_reg, in, proto_mask, proto_mask);
220 	if (proto_mask == MLX5_PTYS_EN)
221 		MLX5_SET(ptys_reg, in, eth_proto_admin, eth_proto_admin);
222 
223 	err = mlx5_core_access_reg(dev, in, sizeof(in), out,
224 				   sizeof(out), MLX5_REG_PTYS, 0, 1);
225 	return err;
226 }
227 EXPORT_SYMBOL_GPL(mlx5_set_port_autoneg);
228 
229 int mlx5_query_port_proto_admin(struct mlx5_core_dev *dev,
230 				u32 *proto_admin, int proto_mask)
231 {
232 	u32 out[MLX5_ST_SZ_DW(ptys_reg)];
233 	int err;
234 
235 	err = mlx5_query_port_ptys(dev, out, sizeof(out), proto_mask, 1);
236 	if (err)
237 		return err;
238 
239 	if (proto_mask == MLX5_PTYS_EN)
240 		*proto_admin = MLX5_GET(ptys_reg, out, eth_proto_admin);
241 	else
242 		*proto_admin = MLX5_GET(ptys_reg, out, ib_proto_admin);
243 
244 	return 0;
245 }
246 EXPORT_SYMBOL_GPL(mlx5_query_port_proto_admin);
247 
248 int mlx5_query_port_eth_proto_oper(struct mlx5_core_dev *dev,
249 				   u32 *proto_oper, u8 local_port)
250 {
251 	u32 out[MLX5_ST_SZ_DW(ptys_reg)];
252 	int err;
253 
254 	err = mlx5_query_port_ptys(dev, out, sizeof(out), MLX5_PTYS_EN,
255 				   local_port);
256 	if (err)
257 		return err;
258 
259 	*proto_oper = MLX5_GET(ptys_reg, out, eth_proto_oper);
260 
261 	return 0;
262 }
263 EXPORT_SYMBOL(mlx5_query_port_eth_proto_oper);
264 
265 int mlx5_set_port_proto(struct mlx5_core_dev *dev, u32 proto_admin,
266 			int proto_mask, bool ext)
267 {
268 	u32 in[MLX5_ST_SZ_DW(ptys_reg)] = {0};
269 	u32 out[MLX5_ST_SZ_DW(ptys_reg)] = {0};
270 	int err;
271 
272 	MLX5_SET(ptys_reg, in, local_port, 1);
273 	MLX5_SET(ptys_reg, in, proto_mask, proto_mask);
274 	if (proto_mask == MLX5_PTYS_EN) {
275 		if (ext)
276 			MLX5_SET(ptys_reg, in, ext_eth_proto_admin, proto_admin);
277 		else
278 			MLX5_SET(ptys_reg, in, eth_proto_admin, proto_admin);
279 	} else {
280 		MLX5_SET(ptys_reg, in, ib_proto_admin, proto_admin);
281 	}
282 
283 	err = mlx5_core_access_reg(dev, in, sizeof(in), out,
284 				   sizeof(out), MLX5_REG_PTYS, 0, 1);
285 	return err;
286 }
287 EXPORT_SYMBOL_GPL(mlx5_set_port_proto);
288 
289 int mlx5_set_port_status(struct mlx5_core_dev *dev,
290 			 enum mlx5_port_status status)
291 {
292 	u32 in[MLX5_ST_SZ_DW(paos_reg)] = {0};
293 	u32 out[MLX5_ST_SZ_DW(paos_reg)] = {0};
294 	int err;
295 
296 	MLX5_SET(paos_reg, in, local_port, 1);
297 
298 	MLX5_SET(paos_reg, in, admin_status, status);
299 	MLX5_SET(paos_reg, in, ase, 1);
300 
301 	err = mlx5_core_access_reg(dev, in, sizeof(in), out,
302 				   sizeof(out), MLX5_REG_PAOS, 0, 1);
303 	return err;
304 }
305 
306 int mlx5_query_port_status(struct mlx5_core_dev *dev, u8 *status)
307 {
308 	u32 in[MLX5_ST_SZ_DW(paos_reg)] = {0};
309 	u32 out[MLX5_ST_SZ_DW(paos_reg)] = {0};
310 	int err;
311 
312 	MLX5_SET(paos_reg, in, local_port, 1);
313 
314 	err = mlx5_core_access_reg(dev, in, sizeof(in), out,
315 				   sizeof(out), MLX5_REG_PAOS, 0, 0);
316 	if (err)
317 		return err;
318 
319 	*status = MLX5_GET(paos_reg, out, oper_status);
320 	return err;
321 }
322 
323 int mlx5_query_port_admin_status(struct mlx5_core_dev *dev,
324 				 enum mlx5_port_status *status)
325 {
326 	u32 in[MLX5_ST_SZ_DW(paos_reg)] = {0};
327 	u32 out[MLX5_ST_SZ_DW(paos_reg)];
328 	int err;
329 
330 	MLX5_SET(paos_reg, in, local_port, 1);
331 	err = mlx5_core_access_reg(dev, in, sizeof(in), out,
332 				   sizeof(out), MLX5_REG_PAOS, 0, 0);
333 	if (err)
334 		return err;
335 	*status = MLX5_GET(paos_reg, out, admin_status);
336 	return 0;
337 }
338 EXPORT_SYMBOL_GPL(mlx5_query_port_admin_status);
339 
340 static int mlx5_query_port_mtu(struct mlx5_core_dev *dev,
341 			       int *admin_mtu, int *max_mtu, int *oper_mtu)
342 {
343 	u32 in[MLX5_ST_SZ_DW(pmtu_reg)] = {0};
344 	u32 out[MLX5_ST_SZ_DW(pmtu_reg)] = {0};
345 	int err;
346 
347 	MLX5_SET(pmtu_reg, in, local_port, 1);
348 
349 	err = mlx5_core_access_reg(dev, in, sizeof(in), out,
350 				   sizeof(out), MLX5_REG_PMTU, 0, 0);
351 	if (err)
352 		return err;
353 
354 	if (max_mtu)
355 		*max_mtu  = MLX5_GET(pmtu_reg, out, max_mtu);
356 	if (oper_mtu)
357 		*oper_mtu = MLX5_GET(pmtu_reg, out, oper_mtu);
358 	if (admin_mtu)
359 		*admin_mtu = MLX5_GET(pmtu_reg, out, admin_mtu);
360 
361 	return err;
362 }
363 
364 int mlx5_set_port_mtu(struct mlx5_core_dev *dev, int mtu)
365 {
366 	u32 in[MLX5_ST_SZ_DW(pmtu_reg)] = {0};
367 	u32 out[MLX5_ST_SZ_DW(pmtu_reg)] = {0};
368 
369 	MLX5_SET(pmtu_reg, in, admin_mtu, mtu);
370 	MLX5_SET(pmtu_reg, in, local_port, 1);
371 
372 	return mlx5_core_access_reg(dev, in, sizeof(in), out,
373 				   sizeof(out), MLX5_REG_PMTU, 0, 1);
374 }
375 EXPORT_SYMBOL_GPL(mlx5_set_port_mtu);
376 
377 int mlx5_query_port_max_mtu(struct mlx5_core_dev *dev, int *max_mtu)
378 {
379 	return mlx5_query_port_mtu(dev, NULL, max_mtu, NULL);
380 }
381 EXPORT_SYMBOL_GPL(mlx5_query_port_max_mtu);
382 
383 int mlx5_set_port_pause_and_pfc(struct mlx5_core_dev *dev, u32 port,
384 				u8 rx_pause, u8 tx_pause,
385 				u8 pfc_en_rx, u8 pfc_en_tx)
386 {
387 	u32 in[MLX5_ST_SZ_DW(pfcc_reg)] = {0};
388 	u32 out[MLX5_ST_SZ_DW(pfcc_reg)] = {0};
389 
390 	if (pfc_en_rx || pfc_en_tx) {
391 		/* PFC and global pauseframes are incompatible features */
392 		if (tx_pause || rx_pause)
393 			return -EINVAL;
394 	}
395 
396 	MLX5_SET(pfcc_reg, in, local_port, port);
397 	MLX5_SET(pfcc_reg, in, pptx, tx_pause);
398 	MLX5_SET(pfcc_reg, in, pprx, rx_pause);
399 	MLX5_SET(pfcc_reg, in, pfctx, pfc_en_tx);
400 	MLX5_SET(pfcc_reg, in, pfcrx, pfc_en_rx);
401 	MLX5_SET(pfcc_reg, in, prio_mask_tx, pfc_en_tx);
402 	MLX5_SET(pfcc_reg, in, prio_mask_rx, pfc_en_rx);
403 
404 	return mlx5_core_access_reg(dev, in, sizeof(in), out,
405 				   sizeof(out), MLX5_REG_PFCC, 0, 1);
406 }
407 
408 int mlx5_query_port_pause(struct mlx5_core_dev *dev, u32 port,
409 			  u32 *rx_pause, u32 *tx_pause)
410 {
411 	u32 in[MLX5_ST_SZ_DW(pfcc_reg)] = {0};
412 	u32 out[MLX5_ST_SZ_DW(pfcc_reg)] = {0};
413 	int err;
414 
415 	MLX5_SET(pfcc_reg, in, local_port, port);
416 
417 	err = mlx5_core_access_reg(dev, in, sizeof(in), out,
418 				   sizeof(out), MLX5_REG_PFCC, 0, 0);
419 	if (err)
420 		return err;
421 
422 	*rx_pause = MLX5_GET(pfcc_reg, out, pprx);
423 	*tx_pause = MLX5_GET(pfcc_reg, out, pptx);
424 
425 	return 0;
426 }
427 
428 int mlx5_query_port_pfc(struct mlx5_core_dev *dev, u8 *pfc_en_tx, u8 *pfc_en_rx)
429 {
430 	u32 in[MLX5_ST_SZ_DW(pfcc_reg)] = {};
431 	u32 out[MLX5_ST_SZ_DW(pfcc_reg)];
432 	int err;
433 
434 	MLX5_SET(pfcc_reg, in, local_port, 1);
435 	err = mlx5_core_access_reg(dev, in, sizeof(in), out,
436 				   sizeof(out), MLX5_REG_PFCC, 0, 0);
437 	if (err)
438 		return err;
439 
440 	if (pfc_en_tx != NULL)
441 		*pfc_en_tx = MLX5_GET(pfcc_reg, out, pfctx);
442 	if (pfc_en_rx != NULL)
443 		*pfc_en_rx = MLX5_GET(pfcc_reg, out, pfcrx);
444 	return 0;
445 }
446 EXPORT_SYMBOL_GPL(mlx5_query_port_pfc);
447 
448 int mlx5_query_port_oper_mtu(struct mlx5_core_dev *dev, int *oper_mtu)
449 {
450 	return mlx5_query_port_mtu(dev, NULL, NULL, oper_mtu);
451 }
452 EXPORT_SYMBOL_GPL(mlx5_query_port_oper_mtu);
453 
454 u8 mlx5_is_wol_supported(struct mlx5_core_dev *dev)
455 {
456 	u8 wol_supported = 0;
457 
458 	if (MLX5_CAP_GEN(dev, wol_s))
459 		wol_supported |= MLX5_WOL_SECURED_MAGIC;
460 	if (MLX5_CAP_GEN(dev, wol_g))
461 		wol_supported |= MLX5_WOL_MAGIC;
462 	if (MLX5_CAP_GEN(dev, wol_a))
463 		wol_supported |= MLX5_WOL_ARP;
464 	if (MLX5_CAP_GEN(dev, wol_b))
465 		wol_supported |= MLX5_WOL_BROADCAST;
466 	if (MLX5_CAP_GEN(dev, wol_m))
467 		wol_supported |= MLX5_WOL_MULTICAST;
468 	if (MLX5_CAP_GEN(dev, wol_u))
469 		wol_supported |= MLX5_WOL_UNICAST;
470 	if (MLX5_CAP_GEN(dev, wol_p))
471 		wol_supported |= MLX5_WOL_PHY_ACTIVITY;
472 
473 	return wol_supported;
474 }
475 EXPORT_SYMBOL_GPL(mlx5_is_wol_supported);
476 
477 int mlx5_set_wol(struct mlx5_core_dev *dev, u8 wol_mode)
478 {
479 	u32 in[MLX5_ST_SZ_DW(set_wol_rol_in)] = {0};
480 	u32 out[MLX5_ST_SZ_DW(set_wol_rol_out)] = {0};
481 
482 	MLX5_SET(set_wol_rol_in, in, opcode, MLX5_CMD_OP_SET_WOL_ROL);
483 	MLX5_SET(set_wol_rol_in, in, wol_mode_valid, 1);
484 	MLX5_SET(set_wol_rol_in, in, wol_mode, wol_mode);
485 
486 	return mlx5_cmd_exec(dev, in, sizeof(in), out, sizeof(out));
487 }
488 EXPORT_SYMBOL_GPL(mlx5_set_wol);
489 
490 int mlx5_query_dropless_mode(struct mlx5_core_dev *dev, u16 *timeout)
491 {
492 	u32 in[MLX5_ST_SZ_DW(query_delay_drop_params_in)] = {0};
493 	u32 out[MLX5_ST_SZ_DW(query_delay_drop_params_out)] = {0};
494 	int err = 0;
495 
496 	MLX5_SET(query_delay_drop_params_in, in, opcode,
497 		 MLX5_CMD_OP_QUERY_DELAY_DROP_PARAMS);
498 
499 	err = mlx5_cmd_exec(dev, in, sizeof(in), out, sizeof(out));
500 	if (err)
501 		return err;
502 
503 	*timeout = MLX5_GET(query_delay_drop_params_out, out,
504 			    delay_drop_timeout);
505 
506 	return 0;
507 }
508 EXPORT_SYMBOL_GPL(mlx5_query_dropless_mode);
509 
510 int mlx5_set_dropless_mode(struct mlx5_core_dev *dev, u16 timeout)
511 {
512 	u32 in[MLX5_ST_SZ_DW(set_delay_drop_params_in)] = {0};
513 	u32 out[MLX5_ST_SZ_DW(set_delay_drop_params_out)] = {0};
514 
515 	MLX5_SET(set_delay_drop_params_in, in, opcode,
516 		 MLX5_CMD_OP_SET_DELAY_DROP_PARAMS);
517 	MLX5_SET(set_delay_drop_params_in, in, delay_drop_timeout, timeout);
518 
519 	return mlx5_cmd_exec(dev, in, sizeof(in), out, sizeof(out));
520 }
521 EXPORT_SYMBOL_GPL(mlx5_set_dropless_mode);
522 
523 int mlx5_core_access_pvlc(struct mlx5_core_dev *dev,
524 			  struct mlx5_pvlc_reg *pvlc, int write)
525 {
526 	int sz = MLX5_ST_SZ_BYTES(pvlc_reg);
527 	u8 in[MLX5_ST_SZ_BYTES(pvlc_reg)] = {0};
528 	u8 out[MLX5_ST_SZ_BYTES(pvlc_reg)] = {0};
529 	int err;
530 
531 	MLX5_SET(pvlc_reg, in, local_port, pvlc->local_port);
532 	if (write)
533 		MLX5_SET(pvlc_reg, in, vl_admin, pvlc->vl_admin);
534 
535 	err = mlx5_core_access_reg(dev, in, sz, out, sz, MLX5_REG_PVLC, 0,
536 				   !!write);
537 	if (err)
538 		return err;
539 
540 	if (!write) {
541 		pvlc->local_port = MLX5_GET(pvlc_reg, out, local_port);
542 		pvlc->vl_hw_cap = MLX5_GET(pvlc_reg, out, vl_hw_cap);
543 		pvlc->vl_admin = MLX5_GET(pvlc_reg, out, vl_admin);
544 		pvlc->vl_operational = MLX5_GET(pvlc_reg, out, vl_operational);
545 	}
546 
547 	return 0;
548 }
549 EXPORT_SYMBOL_GPL(mlx5_core_access_pvlc);
550 
551 int mlx5_core_access_ptys(struct mlx5_core_dev *dev,
552 			  struct mlx5_ptys_reg *ptys, int write)
553 {
554 	int sz = MLX5_ST_SZ_BYTES(ptys_reg);
555 	void *out = NULL;
556 	void *in = NULL;
557 	int err;
558 
559 	in = mlx5_vzalloc(sz);
560 	if (!in)
561 		return -ENOMEM;
562 
563 	out = mlx5_vzalloc(sz);
564 	if (!out) {
565 		kfree(in);
566 		return -ENOMEM;
567 	}
568 
569 	MLX5_SET(ptys_reg, in, local_port, ptys->local_port);
570 	MLX5_SET(ptys_reg, in, proto_mask, ptys->proto_mask);
571 	if (write) {
572 		MLX5_SET(ptys_reg, in, eth_proto_capability,
573 			 ptys->eth_proto_cap);
574 		MLX5_SET(ptys_reg, in, ib_link_width_capability,
575 			 ptys->ib_link_width_cap);
576 		MLX5_SET(ptys_reg, in, ib_proto_capability,
577 			 ptys->ib_proto_cap);
578 		MLX5_SET(ptys_reg, in, eth_proto_admin, ptys->eth_proto_admin);
579 		MLX5_SET(ptys_reg, in, ib_link_width_admin,
580 			 ptys->ib_link_width_admin);
581 		MLX5_SET(ptys_reg, in, ib_proto_admin, ptys->ib_proto_admin);
582 		MLX5_SET(ptys_reg, in, eth_proto_oper, ptys->eth_proto_oper);
583 		MLX5_SET(ptys_reg, in, ib_link_width_oper,
584 			 ptys->ib_link_width_oper);
585 		MLX5_SET(ptys_reg, in, ib_proto_oper, ptys->ib_proto_oper);
586 		MLX5_SET(ptys_reg, in, eth_proto_lp_advertise,
587 			 ptys->eth_proto_lp_advertise);
588 	}
589 
590 	err = mlx5_core_access_reg(dev, in, sz, out, sz, MLX5_REG_PTYS, 0,
591 				   !!write);
592 	if (err)
593 		goto out;
594 
595 	if (!write) {
596 		ptys->local_port = MLX5_GET(ptys_reg, out, local_port);
597 		ptys->proto_mask = MLX5_GET(ptys_reg, out, proto_mask);
598 		ptys->eth_proto_cap = MLX5_GET(ptys_reg, out,
599 					       eth_proto_capability);
600 		ptys->ib_link_width_cap = MLX5_GET(ptys_reg, out,
601 					   ib_link_width_capability);
602 		ptys->ib_proto_cap = MLX5_GET(ptys_reg, out,
603 					      ib_proto_capability);
604 		ptys->eth_proto_admin = MLX5_GET(ptys_reg, out,
605 						 eth_proto_admin);
606 		ptys->ib_link_width_admin = MLX5_GET(ptys_reg, out,
607 						     ib_link_width_admin);
608 		ptys->ib_proto_admin = MLX5_GET(ptys_reg, out, ib_proto_admin);
609 		ptys->eth_proto_oper = MLX5_GET(ptys_reg, out, eth_proto_oper);
610 		ptys->ib_link_width_oper = MLX5_GET(ptys_reg, out,
611 						    ib_link_width_oper);
612 		ptys->ib_proto_oper = MLX5_GET(ptys_reg, out, ib_proto_oper);
613 		ptys->eth_proto_lp_advertise = MLX5_GET(ptys_reg, out,
614 							eth_proto_lp_advertise);
615 	}
616 
617 out:
618 	kvfree(in);
619 	kvfree(out);
620 	return err;
621 }
622 EXPORT_SYMBOL_GPL(mlx5_core_access_ptys);
623 
624 static int mtu_to_ib_mtu(struct mlx5_core_dev *dev, int mtu)
625 {
626 	switch (mtu) {
627 	case 256: return 1;
628 	case 512: return 2;
629 	case 1024: return 3;
630 	case 2048: return 4;
631 	case 4096: return 5;
632 	default:
633 		mlx5_core_warn(dev, "invalid mtu\n");
634 		return -1;
635 	}
636 }
637 
638 int mlx5_core_access_pmtu(struct mlx5_core_dev *dev,
639 			  struct mlx5_pmtu_reg *pmtu, int write)
640 {
641 	int sz = MLX5_ST_SZ_BYTES(pmtu_reg);
642 	void *out = NULL;
643 	void *in = NULL;
644 	int err;
645 
646 	in = mlx5_vzalloc(sz);
647 	if (!in)
648 		return -ENOMEM;
649 
650 	out = mlx5_vzalloc(sz);
651 	if (!out) {
652 		kfree(in);
653 		return -ENOMEM;
654 	}
655 
656 	MLX5_SET(pmtu_reg, in, local_port, pmtu->local_port);
657 	if (write)
658 		MLX5_SET(pmtu_reg, in, admin_mtu, pmtu->admin_mtu);
659 
660 	err = mlx5_core_access_reg(dev, in, sz, out, sz, MLX5_REG_PMTU, 0,
661 				   !!write);
662 	if (err)
663 		goto out;
664 
665 	if (!write) {
666 		pmtu->local_port = MLX5_GET(pmtu_reg, out, local_port);
667 		pmtu->max_mtu = mtu_to_ib_mtu(dev, MLX5_GET(pmtu_reg, out,
668 						       max_mtu));
669 		pmtu->admin_mtu = mtu_to_ib_mtu(dev, MLX5_GET(pmtu_reg, out,
670 							 admin_mtu));
671 		pmtu->oper_mtu = mtu_to_ib_mtu(dev, MLX5_GET(pmtu_reg, out,
672 							oper_mtu));
673 	}
674 
675 out:
676 	kvfree(in);
677 	kvfree(out);
678 	return err;
679 }
680 EXPORT_SYMBOL_GPL(mlx5_core_access_pmtu);
681 
682 int mlx5_query_module_num(struct mlx5_core_dev *dev, int *module_num)
683 {
684 	u32 in[MLX5_ST_SZ_DW(pmlp_reg)] = {0};
685 	u32 out[MLX5_ST_SZ_DW(pmlp_reg)] = {0};
686 	int lane = 0;
687 	int err;
688 
689 	MLX5_SET(pmlp_reg, in, local_port, 1);
690 
691 	err = mlx5_core_access_reg(dev, in, sizeof(in), out,
692 				   sizeof(out), MLX5_REG_PMLP, 0, 0);
693 	if (err)
694 		return err;
695 
696 	lane = MLX5_GET(pmlp_reg, out, lane0_module_mapping);
697 	*module_num = lane & MLX5_EEPROM_IDENTIFIER_BYTE_MASK;
698 
699 	return 0;
700 }
701 EXPORT_SYMBOL_GPL(mlx5_query_module_num);
702 
703 int mlx5_query_eeprom(struct mlx5_core_dev *dev,
704 		      int i2c_addr, int page_num, int device_addr,
705 		      int size, int module_num, u32 *data, int *size_read)
706 {
707 	u32 in[MLX5_ST_SZ_DW(mcia_reg)] = {0};
708 	u32 out[MLX5_ST_SZ_DW(mcia_reg)] = {0};
709 	u32 *ptr = (u32 *)MLX5_ADDR_OF(mcia_reg, out, dword_0);
710 	int status;
711 	int err;
712 
713 	size = min_t(int, size, MLX5_EEPROM_MAX_BYTES);
714 
715 	MLX5_SET(mcia_reg, in, l, 0);
716 	MLX5_SET(mcia_reg, in, module, module_num);
717 	MLX5_SET(mcia_reg, in, i2c_device_address, i2c_addr);
718 	MLX5_SET(mcia_reg, in, page_number, page_num);
719 	MLX5_SET(mcia_reg, in, device_address, device_addr);
720 	MLX5_SET(mcia_reg, in, size, size);
721 
722 	err = mlx5_core_access_reg(dev, in, sizeof(in), out,
723 				   sizeof(out), MLX5_REG_MCIA, 0, 0);
724 	if (err)
725 		return err;
726 
727 	status = MLX5_GET(mcia_reg, out, status);
728 	if (status)
729 		return status;
730 
731 	memcpy(data, ptr, size);
732 	*size_read = size;
733 	return 0;
734 }
735 EXPORT_SYMBOL_GPL(mlx5_query_eeprom);
736 
737 int mlx5_vxlan_udp_port_add(struct mlx5_core_dev *dev, u16 port)
738 {
739 	u32 in[MLX5_ST_SZ_DW(add_vxlan_udp_dport_in)] = {0};
740 	u32 out[MLX5_ST_SZ_DW(add_vxlan_udp_dport_out)] = {0};
741 	int err;
742 
743 	MLX5_SET(add_vxlan_udp_dport_in, in, opcode,
744 		 MLX5_CMD_OP_ADD_VXLAN_UDP_DPORT);
745 	MLX5_SET(add_vxlan_udp_dport_in, in, vxlan_udp_port, port);
746 
747 	err = mlx5_cmd_exec(dev, in, sizeof(in), out, sizeof(out));
748 	if (err) {
749 		mlx5_core_err(dev, "Failed %s, port %u, err - %d",
750 			      mlx5_command_str(MLX5_CMD_OP_ADD_VXLAN_UDP_DPORT),
751 			      port, err);
752 	}
753 
754 	return err;
755 }
756 
757 int mlx5_vxlan_udp_port_delete(struct mlx5_core_dev *dev, u16 port)
758 {
759 	u32 in[MLX5_ST_SZ_DW(delete_vxlan_udp_dport_in)] = {0};
760 	u32 out[MLX5_ST_SZ_DW(delete_vxlan_udp_dport_out)] = {0};
761 	int err;
762 
763 	MLX5_SET(delete_vxlan_udp_dport_in, in, opcode,
764 		 MLX5_CMD_OP_DELETE_VXLAN_UDP_DPORT);
765 	MLX5_SET(delete_vxlan_udp_dport_in, in, vxlan_udp_port, port);
766 
767 	err = mlx5_cmd_exec(dev, in, sizeof(in), out, sizeof(out));
768 	if (err) {
769 		mlx5_core_err(dev, "Failed %s, port %u, err - %d",
770 			      mlx5_command_str(MLX5_CMD_OP_DELETE_VXLAN_UDP_DPORT),
771 			      port, err);
772 	}
773 
774 	return err;
775 }
776 
777 int mlx5_query_wol(struct mlx5_core_dev *dev, u8 *wol_mode)
778 {
779 	u32 in[MLX5_ST_SZ_DW(query_wol_rol_in)] = {0};
780 	u32 out[MLX5_ST_SZ_DW(query_wol_rol_out)] = {0};
781 	int err;
782 
783 	MLX5_SET(query_wol_rol_in, in, opcode, MLX5_CMD_OP_QUERY_WOL_ROL);
784 
785 	err = mlx5_cmd_exec(dev, in, sizeof(in), out, sizeof(out));
786 
787 	if (!err)
788 		*wol_mode = MLX5_GET(query_wol_rol_out, out, wol_mode);
789 
790 	return err;
791 }
792 EXPORT_SYMBOL_GPL(mlx5_query_wol);
793 
794 int mlx5_query_port_cong_status(struct mlx5_core_dev *mdev, int protocol,
795 				int priority, int *is_enable)
796 {
797 	u32 in[MLX5_ST_SZ_DW(query_cong_status_in)] = {0};
798 	u32 out[MLX5_ST_SZ_DW(query_cong_status_out)] = {0};
799 	int err;
800 
801 	*is_enable = 0;
802 
803 	MLX5_SET(query_cong_status_in, in, opcode,
804 		 MLX5_CMD_OP_QUERY_CONG_STATUS);
805 	MLX5_SET(query_cong_status_in, in, cong_protocol, protocol);
806 	MLX5_SET(query_cong_status_in, in, priority, priority);
807 
808 	err = mlx5_cmd_exec(mdev, in, sizeof(in), out, sizeof(out));
809 	if (!err)
810 		*is_enable = MLX5_GET(query_cong_status_out, out, enable);
811 	return err;
812 }
813 
814 int mlx5_modify_port_cong_status(struct mlx5_core_dev *mdev, int protocol,
815 				 int priority, int enable)
816 {
817 	u32 in[MLX5_ST_SZ_DW(modify_cong_status_in)] = {0};
818 	u32 out[MLX5_ST_SZ_DW(modify_cong_status_out)] = {0};
819 
820 	MLX5_SET(modify_cong_status_in, in, opcode,
821 		 MLX5_CMD_OP_MODIFY_CONG_STATUS);
822 	MLX5_SET(modify_cong_status_in, in, cong_protocol, protocol);
823 	MLX5_SET(modify_cong_status_in, in, priority, priority);
824 	MLX5_SET(modify_cong_status_in, in, enable, enable);
825 
826 	return mlx5_cmd_exec(mdev, in, sizeof(in), out, sizeof(out));
827 }
828 
829 int mlx5_query_port_cong_params(struct mlx5_core_dev *mdev, int protocol,
830 				void *out, int out_size)
831 {
832 	u32 in[MLX5_ST_SZ_DW(query_cong_params_in)] = {0};
833 
834 	MLX5_SET(query_cong_params_in, in, opcode,
835 		 MLX5_CMD_OP_QUERY_CONG_PARAMS);
836 	MLX5_SET(query_cong_params_in, in, cong_protocol, protocol);
837 
838 	return mlx5_cmd_exec(mdev, in, sizeof(in), out, out_size);
839 }
840 
841 static int mlx5_query_port_qetcr_reg(struct mlx5_core_dev *mdev, u32 *out,
842 				     int outlen)
843 {
844 	u32 in[MLX5_ST_SZ_DW(qetc_reg)];
845 
846 	if (!MLX5_CAP_GEN(mdev, ets))
847 		return -ENOTSUPP;
848 
849 	memset(in, 0, sizeof(in));
850 	return mlx5_core_access_reg(mdev, in, sizeof(in), out, outlen,
851 				    MLX5_REG_QETCR, 0, 0);
852 }
853 
854 int mlx5_max_tc(struct mlx5_core_dev *mdev)
855 {
856 	u8 num_tc = MLX5_CAP_GEN(mdev, max_tc) ? : 8;
857 
858 	return num_tc - 1;
859 }
860 EXPORT_SYMBOL_GPL(mlx5_max_tc);
861 
862 static int mlx5_set_port_qetcr_reg(struct mlx5_core_dev *mdev, u32 *in,
863 				   int inlen)
864 {
865 	u32 out[MLX5_ST_SZ_DW(qetc_reg)];
866 
867 	if (!MLX5_CAP_GEN(mdev, ets))
868 		return -ENOTSUPP;
869 
870 	return mlx5_core_access_reg(mdev, in, inlen, out, sizeof(out),
871 				    MLX5_REG_QETCR, 0, 1);
872 }
873 
874 int mlx5_query_port_tc_rate_limit(struct mlx5_core_dev *mdev,
875 				   u8 *max_bw_value,
876 				   u8 *max_bw_units)
877 {
878 	u32 out[MLX5_ST_SZ_DW(qetc_reg)];
879 	void *ets_tcn_conf;
880 	int err;
881 	int i;
882 
883 	err = mlx5_query_port_qetcr_reg(mdev, out, sizeof(out));
884 	if (err)
885 		return err;
886 
887 	for (i = 0; i <= mlx5_max_tc(mdev); i++) {
888 		ets_tcn_conf = MLX5_ADDR_OF(qetc_reg, out, tc_configuration[i]);
889 
890 		max_bw_value[i] = MLX5_GET(ets_tcn_config_reg, ets_tcn_conf,
891 					   max_bw_value);
892 		max_bw_units[i] = MLX5_GET(ets_tcn_config_reg, ets_tcn_conf,
893 					   max_bw_units);
894 	}
895 
896 	return 0;
897 }
898 EXPORT_SYMBOL_GPL(mlx5_query_port_tc_rate_limit);
899 
900 int mlx5_modify_port_tc_rate_limit(struct mlx5_core_dev *mdev,
901 				   const u8 *max_bw_value,
902 				   const u8 *max_bw_units)
903 {
904 	u32 in[MLX5_ST_SZ_DW(qetc_reg)] = {};
905 	void *ets_tcn_conf;
906 	int i;
907 
908 	MLX5_SET(qetc_reg, in, port_number, 1);
909 
910 	for (i = 0; i <= mlx5_max_tc(mdev); i++) {
911 		ets_tcn_conf = MLX5_ADDR_OF(qetc_reg, in, tc_configuration[i]);
912 
913 		MLX5_SET(ets_tcn_config_reg, ets_tcn_conf, r, 1);
914 		MLX5_SET(ets_tcn_config_reg, ets_tcn_conf, max_bw_units,
915 			 max_bw_units[i]);
916 		MLX5_SET(ets_tcn_config_reg, ets_tcn_conf, max_bw_value,
917 			 max_bw_value[i]);
918 	}
919 
920 	return mlx5_set_port_qetcr_reg(mdev, in, sizeof(in));
921 }
922 EXPORT_SYMBOL_GPL(mlx5_modify_port_tc_rate_limit);
923 
924 int mlx5_query_port_prio_tc(struct mlx5_core_dev *mdev,
925 			    u8 prio, u8 *tc)
926 {
927 	u32 in[MLX5_ST_SZ_DW(qtct_reg)];
928 	u32 out[MLX5_ST_SZ_DW(qtct_reg)];
929 	int err;
930 
931 	memset(in, 0, sizeof(in));
932 	memset(out, 0, sizeof(out));
933 
934 	MLX5_SET(qtct_reg, in, port_number, 1);
935 	MLX5_SET(qtct_reg, in, prio, prio);
936 
937 	err = mlx5_core_access_reg(mdev, in, sizeof(in), out,
938 				   sizeof(out), MLX5_REG_QTCT, 0, 0);
939 	if (!err)
940 		*tc = MLX5_GET(qtct_reg, out, tclass);
941 
942 	return err;
943 }
944 EXPORT_SYMBOL_GPL(mlx5_query_port_prio_tc);
945 
946 int mlx5_set_port_prio_tc(struct mlx5_core_dev *mdev, int prio_index,
947 			  const u8 prio_tc)
948 {
949 	u32 in[MLX5_ST_SZ_DW(qtct_reg)] = {};
950 	u32 out[MLX5_ST_SZ_DW(qtct_reg)];
951 	int err;
952 
953 	if (prio_tc > mlx5_max_tc(mdev))
954 		return -EINVAL;
955 
956 	MLX5_SET(qtct_reg, in, prio, prio_index);
957 	MLX5_SET(qtct_reg, in, tclass, prio_tc);
958 
959 	err = mlx5_core_access_reg(mdev, in, sizeof(in), out,
960 				   sizeof(out), MLX5_REG_QTCT, 0, 1);
961 
962 	return (err);
963 }
964 EXPORT_SYMBOL_GPL(mlx5_set_port_prio_tc);
965 
966 int mlx5_set_port_tc_group(struct mlx5_core_dev *mdev, const u8 *tc_group)
967 {
968 	u32 in[MLX5_ST_SZ_DW(qetc_reg)] = {};
969 	int i;
970 
971 	for (i = 0; i <= mlx5_max_tc(mdev); i++) {
972 		MLX5_SET(qetc_reg, in, tc_configuration[i].g, 1);
973 		MLX5_SET(qetc_reg, in, tc_configuration[i].group, tc_group[i]);
974 	}
975 
976 	return mlx5_set_port_qetcr_reg(mdev, in, sizeof(in));
977 }
978 EXPORT_SYMBOL_GPL(mlx5_set_port_tc_group);
979 
980 int mlx5_query_port_tc_group(struct mlx5_core_dev *mdev,
981 			     u8 tc, u8 *tc_group)
982 {
983 	u32 out[MLX5_ST_SZ_DW(qetc_reg)];
984 	void *ets_tcn_conf;
985 	int err;
986 
987 	err = mlx5_query_port_qetcr_reg(mdev, out, sizeof(out));
988 	if (err)
989 		return err;
990 
991 	ets_tcn_conf = MLX5_ADDR_OF(qetc_reg, out,
992 				    tc_configuration[tc]);
993 
994 	*tc_group = MLX5_GET(ets_tcn_config_reg, ets_tcn_conf,
995 			     group);
996 
997 	return 0;
998 }
999 EXPORT_SYMBOL_GPL(mlx5_query_port_tc_group);
1000 
1001 int mlx5_set_port_tc_bw_alloc(struct mlx5_core_dev *mdev, const u8 *tc_bw)
1002 {
1003 	u32 in[MLX5_ST_SZ_DW(qetc_reg)] = {};
1004 	int i;
1005 
1006 	for (i = 0; i <= mlx5_max_tc(mdev); i++) {
1007 		MLX5_SET(qetc_reg, in, tc_configuration[i].b, 1);
1008 		MLX5_SET(qetc_reg, in, tc_configuration[i].bw_allocation, tc_bw[i]);
1009 	}
1010 
1011 	return mlx5_set_port_qetcr_reg(mdev, in, sizeof(in));
1012 }
1013 EXPORT_SYMBOL_GPL(mlx5_set_port_tc_bw_alloc);
1014 
1015 int mlx5_query_port_tc_bw_alloc(struct mlx5_core_dev *mdev, u8 *bw_pct)
1016 {
1017 	u32 out[MLX5_ST_SZ_DW(qetc_reg)];
1018 	void *ets_tcn_conf;
1019 	int err;
1020 	int i;
1021 
1022 	err = mlx5_query_port_qetcr_reg(mdev, out, sizeof(out));
1023 	if (err)
1024 		return err;
1025 
1026 	for (i = 0; i <= mlx5_max_tc(mdev); i++) {
1027 		ets_tcn_conf = MLX5_ADDR_OF(qetc_reg, out, tc_configuration[i]);
1028 		bw_pct[i] = MLX5_GET(ets_tcn_config_reg, ets_tcn_conf, bw_allocation);
1029 	}
1030 	return 0;
1031 }
1032 EXPORT_SYMBOL_GPL(mlx5_query_port_tc_bw_alloc);
1033 
1034 int mlx5_modify_port_cong_params(struct mlx5_core_dev *mdev,
1035 				 void *in, int in_size)
1036 {
1037 	u32 out[MLX5_ST_SZ_DW(modify_cong_params_out)] = {0};
1038 
1039 	MLX5_SET(modify_cong_params_in, in, opcode,
1040 		 MLX5_CMD_OP_MODIFY_CONG_PARAMS);
1041 
1042 	return mlx5_cmd_exec(mdev, in, in_size, out, sizeof(out));
1043 }
1044 
1045 int mlx5_query_port_cong_statistics(struct mlx5_core_dev *mdev, int clear,
1046 				    void *out, int out_size)
1047 {
1048 	u32 in[MLX5_ST_SZ_DW(query_cong_statistics_in)] = {0};
1049 
1050 	MLX5_SET(query_cong_statistics_in, in, opcode,
1051 		 MLX5_CMD_OP_QUERY_CONG_STATISTICS);
1052 	MLX5_SET(query_cong_statistics_in, in, clear, clear);
1053 
1054 	return mlx5_cmd_exec(mdev, in, sizeof(in), out, out_size);
1055 }
1056 
1057 int mlx5_set_diagnostic_params(struct mlx5_core_dev *mdev, void *in,
1058 			       int in_size)
1059 {
1060 	u32 out[MLX5_ST_SZ_DW(set_diagnostic_params_out)] = {0};
1061 
1062 	MLX5_SET(set_diagnostic_params_in, in, opcode,
1063 		 MLX5_CMD_OP_SET_DIAGNOSTICS);
1064 
1065 	return mlx5_cmd_exec(mdev, in, in_size, out, sizeof(out));
1066 }
1067 
1068 int mlx5_query_diagnostic_counters(struct mlx5_core_dev *mdev,
1069 				   u8 num_of_samples, u16 sample_index,
1070 				   void *out, int out_size)
1071 {
1072 	u32 in[MLX5_ST_SZ_DW(query_diagnostic_counters_in)] = {0};
1073 
1074 	MLX5_SET(query_diagnostic_counters_in, in, opcode,
1075 		 MLX5_CMD_OP_QUERY_DIAGNOSTICS);
1076 	MLX5_SET(query_diagnostic_counters_in, in, num_of_samples,
1077 		 num_of_samples);
1078 	MLX5_SET(query_diagnostic_counters_in, in, sample_index, sample_index);
1079 
1080 	return mlx5_cmd_exec(mdev, in, sizeof(in), out, out_size);
1081 }
1082 
1083 int mlx5_set_trust_state(struct mlx5_core_dev *mdev, u8 trust_state)
1084 {
1085 	u32 out[MLX5_ST_SZ_DW(qpts_reg)] = {};
1086 	u32 in[MLX5_ST_SZ_DW(qpts_reg)] = {};
1087 	int err;
1088 
1089 	MLX5_SET(qpts_reg, in, local_port, 1);
1090 	MLX5_SET(qpts_reg, in, trust_state, trust_state);
1091 
1092 	err = mlx5_core_access_reg(mdev, in, sizeof(in), out,
1093 				   sizeof(out), MLX5_REG_QPTS, 0, 1);
1094 	return err;
1095 }
1096 
1097 int mlx5_query_trust_state(struct mlx5_core_dev *mdev, u8 *trust_state)
1098 {
1099 	u32 out[MLX5_ST_SZ_DW(qpts_reg)] = {};
1100 	u32 in[MLX5_ST_SZ_DW(qpts_reg)] = {};
1101 	int err;
1102 
1103 	MLX5_SET(qpts_reg, in, local_port, 1);
1104 
1105 	err = mlx5_core_access_reg(mdev, in, sizeof(in), out,
1106 				   sizeof(out), MLX5_REG_QPTS, 0, 0);
1107 	if (!err)
1108 		*trust_state = MLX5_GET(qpts_reg, out, trust_state);
1109 
1110 	return err;
1111 }
1112 
1113 int mlx5_set_dscp2prio(struct mlx5_core_dev *mdev, const u8 *dscp2prio)
1114 {
1115 	int sz = MLX5_ST_SZ_BYTES(qpdpm_reg);
1116 	void *qpdpm_dscp;
1117 	void *out;
1118 	void *in;
1119 	int err;
1120 	int i;
1121 
1122 	in = kzalloc(sz, GFP_KERNEL);
1123 	out = kzalloc(sz, GFP_KERNEL);
1124 	if (!in || !out) {
1125 		err = -ENOMEM;
1126 		goto out;
1127 	}
1128 
1129 	MLX5_SET(qpdpm_reg, in, local_port, 1);
1130 	err = mlx5_core_access_reg(mdev, in, sz, out, sz, MLX5_REG_QPDPM, 0, 0);
1131 	if (err)
1132 		goto out;
1133 
1134 	memcpy(in, out, sz);
1135 	MLX5_SET(qpdpm_reg, in, local_port, 1);
1136 
1137 	/* Update the corresponding dscp entry */
1138 	for (i = 0; i < MLX5_MAX_SUPPORTED_DSCP; i++) {
1139 		qpdpm_dscp = MLX5_ADDR_OF(qpdpm_reg, in, dscp[i]);
1140 		MLX5_SET16(qpdpm_dscp_reg, qpdpm_dscp, prio, dscp2prio[i]);
1141 		MLX5_SET16(qpdpm_dscp_reg, qpdpm_dscp, e, 1);
1142 	}
1143 	err = mlx5_core_access_reg(mdev, in, sz, out, sz, MLX5_REG_QPDPM, 0, 1);
1144 out:
1145 	kfree(in);
1146 	kfree(out);
1147 	return err;
1148 }
1149 
1150 int mlx5_query_dscp2prio(struct mlx5_core_dev *mdev, u8 *dscp2prio)
1151 {
1152 	int sz = MLX5_ST_SZ_BYTES(qpdpm_reg);
1153 	void *qpdpm_dscp;
1154 	void *out;
1155 	void *in;
1156 	int err;
1157 	int i;
1158 
1159 	in = kzalloc(sz, GFP_KERNEL);
1160 	out = kzalloc(sz, GFP_KERNEL);
1161 	if (!in || !out) {
1162 		err = -ENOMEM;
1163 		goto out;
1164 	}
1165 
1166 	MLX5_SET(qpdpm_reg, in, local_port, 1);
1167 	err = mlx5_core_access_reg(mdev, in, sz, out, sz, MLX5_REG_QPDPM, 0, 0);
1168 	if (err)
1169 		goto out;
1170 
1171 	for (i = 0; i < MLX5_MAX_SUPPORTED_DSCP; i++) {
1172 		qpdpm_dscp = MLX5_ADDR_OF(qpdpm_reg, out, dscp[i]);
1173 		dscp2prio[i] = MLX5_GET16(qpdpm_dscp_reg, qpdpm_dscp, prio);
1174 	}
1175 out:
1176 	kfree(in);
1177 	kfree(out);
1178 	return err;
1179 }
1180 
1181 static int mlx5_query_pddr(struct mlx5_core_dev *mdev,
1182     u8 local_port, int page_select, u32 *out, int outlen)
1183 {
1184 	u32 in[MLX5_ST_SZ_DW(pddr_reg)] = {0};
1185 
1186 	if (!MLX5_CAP_PCAM_REG(mdev, pddr))
1187 		return -EOPNOTSUPP;
1188 
1189 	MLX5_SET(pddr_reg, in, local_port, local_port);
1190 	MLX5_SET(pddr_reg, in, page_select, page_select);
1191 
1192 	return mlx5_core_access_reg(mdev, in, sizeof(in), out, outlen, MLX5_REG_PDDR, 0, 0);
1193 }
1194 
1195 int mlx5_query_pddr_range_info(struct mlx5_core_dev *mdev, u8 local_port, u8 *is_er_type)
1196 {
1197 	u32 pddr_reg[MLX5_ST_SZ_DW(pddr_reg)] = {};
1198 	int error;
1199 	u8 ecc;
1200 	u8 ci;
1201 
1202 	error = mlx5_query_pddr(mdev, local_port, MLX5_PDDR_MODULE_INFO_PAGE,
1203 	    pddr_reg, sizeof(pddr_reg));
1204 	if (error != 0)
1205 		return (error);
1206 
1207 	ecc = MLX5_GET(pddr_reg, pddr_reg, page_data.pddr_module_info.ethernet_compliance_code);
1208 	ci = MLX5_GET(pddr_reg, pddr_reg, page_data.pddr_module_info.cable_identifier);
1209 
1210 	switch (ci) {
1211 	case 0:	/* QSFP28 */
1212 	case 1:	/* QSFP+ */
1213 		*is_er_type = 0;
1214 		break;
1215 	case 2:	/* SFP28/SFP+ */
1216 	case 3: /* QSA (QSFP->SFP) */
1217 		*is_er_type = ((ecc & (1 << 7)) != 0);
1218 		break;
1219 	default:
1220 		*is_er_type = 0;
1221 		break;
1222 	}
1223 	return (0);
1224 }
1225 EXPORT_SYMBOL_GPL(mlx5_query_pddr_range_info);
1226 
1227 int mlx5_query_pddr_cable_type(struct mlx5_core_dev *mdev, u8 local_port, u8 *cable_type)
1228 {
1229 	u32 pddr_reg[MLX5_ST_SZ_DW(pddr_reg)] = {};
1230 	int error;
1231 
1232 	error = mlx5_query_pddr(mdev, local_port, MLX5_PDDR_MODULE_INFO_PAGE,
1233 	    pddr_reg, sizeof(pddr_reg));
1234 	if (error != 0)
1235 		return (error);
1236 
1237 	*cable_type = MLX5_GET(pddr_reg, pddr_reg, page_data.pddr_module_info.cable_type);
1238 	return (0);
1239 }
1240 EXPORT_SYMBOL_GPL(mlx5_query_pddr_cable_type);
1241 
1242 int mlx5_query_pddr_troubleshooting_info(struct mlx5_core_dev *mdev,
1243     u16 *monitor_opcode, u8 *status_message, size_t sm_len)
1244 {
1245 	int outlen = MLX5_ST_SZ_BYTES(pddr_reg);
1246 	u32 out[MLX5_ST_SZ_DW(pddr_reg)] = {0};
1247 	int err;
1248 
1249 	err = mlx5_query_pddr(mdev, MLX5_PDDR_TROUBLESHOOTING_INFO_PAGE, 1,
1250 	    out, outlen);
1251 	if (err != 0)
1252 		return err;
1253 	if (monitor_opcode != NULL) {
1254 		*monitor_opcode = MLX5_GET(pddr_reg, out,
1255 		    page_data.troubleshooting_info_page.status_opcode.
1256 		    monitor_opcodes);
1257 	}
1258 	if (status_message != NULL) {
1259 		strlcpy(status_message,
1260 		    MLX5_ADDR_OF(pddr_reg, out,
1261 		    page_data.troubleshooting_info_page.status_message),
1262 		    sm_len);
1263 	}
1264 	return (0);
1265 }
1266 
1267 int
1268 mlx5_query_mfrl_reg(struct mlx5_core_dev *mdev, u8 *reset_level)
1269 {
1270 	u32 mfrl[MLX5_ST_SZ_DW(mfrl_reg)] = {};
1271 	int sz = MLX5_ST_SZ_BYTES(mfrl_reg);
1272 	int err;
1273 
1274 	err = mlx5_core_access_reg(mdev, mfrl, sz, mfrl, sz, MLX5_REG_MFRL,
1275 	    0, 0);
1276 	if (err == 0)
1277 		*reset_level = MLX5_GET(mfrl_reg, mfrl, reset_level);
1278 	return (err);
1279 }
1280 
1281 int
1282 mlx5_set_mfrl_reg(struct mlx5_core_dev *mdev, u8 reset_level)
1283 {
1284 	u32 mfrl[MLX5_ST_SZ_DW(mfrl_reg)] = {};
1285 	int sz = MLX5_ST_SZ_BYTES(mfrl_reg);
1286 
1287 	MLX5_SET(mfrl_reg, mfrl, reset_level, reset_level);
1288 
1289 	return (mlx5_core_access_reg(mdev, mfrl, sz, mfrl, sz, MLX5_REG_MFRL,
1290 	    0, 1));
1291 }
1292 
1293 /* speed in units of 1Mb */
1294 static const u32 mlx5e_link_speed[/*MLX5E_LINK_MODES_NUMBER*/] = {
1295 	[MLX5E_1000BASE_CX_SGMII] = 1000,
1296 	[MLX5E_1000BASE_KX]       = 1000,
1297 	[MLX5E_10GBASE_CX4]       = 10000,
1298 	[MLX5E_10GBASE_KX4]       = 10000,
1299 	[MLX5E_10GBASE_KR]        = 10000,
1300 	[MLX5E_20GBASE_KR2]       = 20000,
1301 	[MLX5E_40GBASE_CR4]       = 40000,
1302 	[MLX5E_40GBASE_KR4]       = 40000,
1303 	[MLX5E_56GBASE_R4]        = 56000,
1304 	[MLX5E_10GBASE_CR]        = 10000,
1305 	[MLX5E_10GBASE_SR]        = 10000,
1306 	[MLX5E_10GBASE_ER_LR]     = 10000,
1307 	[MLX5E_40GBASE_SR4]       = 40000,
1308 	[MLX5E_40GBASE_LR4_ER4]   = 40000,
1309 	[MLX5E_50GBASE_SR2]       = 50000,
1310 	[MLX5E_100GBASE_CR4]      = 100000,
1311 	[MLX5E_100GBASE_SR4]      = 100000,
1312 	[MLX5E_100GBASE_KR4]      = 100000,
1313 	[MLX5E_100GBASE_LR4]      = 100000,
1314 	[MLX5E_100BASE_TX]        = 100,
1315 	[MLX5E_1000BASE_T]        = 1000,
1316 	[MLX5E_10GBASE_T]         = 10000,
1317 	[MLX5E_25GBASE_CR]        = 25000,
1318 	[MLX5E_25GBASE_KR]        = 25000,
1319 	[MLX5E_25GBASE_SR]        = 25000,
1320 	[MLX5E_50GBASE_CR2]       = 50000,
1321 	[MLX5E_50GBASE_KR2]       = 50000,
1322 };
1323 
1324 static const u32 mlx5e_ext_link_speed[/*MLX5E_EXT_LINK_MODES_NUMBER*/] = {
1325 	[MLX5E_SGMII_100M]			= 100,
1326 	[MLX5E_1000BASE_X_SGMII]		= 1000,
1327 	[MLX5E_5GBASE_R]			= 5000,
1328 	[MLX5E_10GBASE_XFI_XAUI_1]		= 10000,
1329 	[MLX5E_40GBASE_XLAUI_4_XLPPI_4]		= 40000,
1330 	[MLX5E_25GAUI_1_25GBASE_CR_KR]		= 25000,
1331 	[MLX5E_50GAUI_2_LAUI_2_50GBASE_CR2_KR2]	= 50000,
1332 	[MLX5E_50GAUI_1_LAUI_1_50GBASE_CR_KR]	= 50000,
1333 	[MLX5E_CAUI_4_100GBASE_CR4_KR4]		= 100000,
1334 	[MLX5E_200GAUI_4_200GBASE_CR4_KR4]	= 200000,
1335 	[MLX5E_400GAUI_8]			= 400000,
1336 };
1337 
1338 static void mlx5e_port_get_speed_arr(struct mlx5_core_dev *mdev,
1339 				     const u32 **arr, u32 *size)
1340 {
1341 	bool ext = MLX5_CAP_PCAM_FEATURE(mdev, ptys_extended_ethernet);
1342 
1343 	*size = ext ? ARRAY_SIZE(mlx5e_ext_link_speed) :
1344 		      ARRAY_SIZE(mlx5e_link_speed);
1345 	*arr  = ext ? mlx5e_ext_link_speed : mlx5e_link_speed;
1346 }
1347 
1348 u32 mlx5e_port_ptys2speed(struct mlx5_core_dev *mdev, u32 eth_proto_oper)
1349 {
1350 	unsigned long temp = eth_proto_oper;
1351 	const u32 *table;
1352 	u32 speed = 0;
1353 	u32 max_size;
1354 	int i;
1355 
1356 	mlx5e_port_get_speed_arr(mdev, &table, &max_size);
1357 	i = find_first_bit(&temp, max_size);
1358 	if (i < max_size)
1359 		speed = table[i];
1360 	return speed;
1361 }
1362 
1363 int mlx5_port_query_eth_proto(struct mlx5_core_dev *dev, u8 port, bool ext,
1364 			      struct mlx5e_port_eth_proto *eproto)
1365 {
1366 	u32 out[MLX5_ST_SZ_DW(ptys_reg)];
1367 	int err;
1368 
1369 	if (!eproto)
1370 		return -EINVAL;
1371 
1372 	err = mlx5_query_port_ptys(dev, out, sizeof(out), MLX5_PTYS_EN, port);
1373 	if (err)
1374 		return err;
1375 
1376 	eproto->cap   = MLX5_GET_ETH_PROTO(ptys_reg, out, ext,
1377 					   eth_proto_capability);
1378 	eproto->admin = MLX5_GET_ETH_PROTO(ptys_reg, out, ext, eth_proto_admin);
1379 	eproto->oper  = MLX5_GET_ETH_PROTO(ptys_reg, out, ext, eth_proto_oper);
1380 	return 0;
1381 }
1382 
1383 int mlx5e_port_linkspeed(struct mlx5_core_dev *mdev, u32 *speed)
1384 {
1385 	struct mlx5e_port_eth_proto eproto;
1386 	bool ext;
1387 	int err;
1388 
1389 	ext = MLX5_CAP_PCAM_FEATURE(mdev, ptys_extended_ethernet);
1390 	err = mlx5_port_query_eth_proto(mdev, 1, ext, &eproto);
1391 	if (err)
1392 		goto out;
1393 
1394 	*speed = mlx5e_port_ptys2speed(mdev, eproto.oper);
1395 	if (!(*speed))
1396 		err = -EINVAL;
1397 
1398 out:
1399 	return err;
1400 }
1401 
1402 int mlx5e_port_query_pbmc(struct mlx5_core_dev *mdev, void *out)
1403 {
1404 	int sz = MLX5_ST_SZ_BYTES(pbmc_reg);
1405 	void *in;
1406 	int err;
1407 
1408 	in = kzalloc(sz, GFP_KERNEL);
1409 	if (!in)
1410 		return -ENOMEM;
1411 
1412 	MLX5_SET(pbmc_reg, in, local_port, 1);
1413 	err = mlx5_core_access_reg(mdev, in, sz, out, sz, MLX5_REG_PBMC, 0, 0);
1414 
1415 	kfree(in);
1416 	return err;
1417 }
1418 
1419 int mlx5e_port_set_pbmc(struct mlx5_core_dev *mdev, void *in)
1420 {
1421 	int sz = MLX5_ST_SZ_BYTES(pbmc_reg);
1422 	void *out;
1423 	int err;
1424 
1425 	out = kzalloc(sz, GFP_KERNEL);
1426 	if (!out)
1427 		return -ENOMEM;
1428 
1429 	MLX5_SET(pbmc_reg, in, local_port, 1);
1430 	err = mlx5_core_access_reg(mdev, in, sz, out, sz, MLX5_REG_PBMC, 0, 1);
1431 
1432 	kfree(out);
1433 	return err;
1434 }
1435 
1436 /* buffer[i]: buffer that priority i mapped to */
1437 int mlx5e_port_query_priority2buffer(struct mlx5_core_dev *mdev, u8 *buffer)
1438 {
1439 	int sz = MLX5_ST_SZ_BYTES(pptb_reg);
1440 	u32 prio_x_buff;
1441 	void *out;
1442 	void *in;
1443 	int prio;
1444 	int err;
1445 
1446 	in = kzalloc(sz, GFP_KERNEL);
1447 	out = kzalloc(sz, GFP_KERNEL);
1448 	if (!in || !out) {
1449 		err = -ENOMEM;
1450 		goto out;
1451 	}
1452 
1453 	MLX5_SET(pptb_reg, in, local_port, 1);
1454 	err = mlx5_core_access_reg(mdev, in, sz, out, sz, MLX5_REG_PPTB, 0, 0);
1455 	if (err)
1456 		goto out;
1457 
1458 	prio_x_buff = MLX5_GET(pptb_reg, out, prio_x_buff);
1459 	for (prio = 0; prio < 8; prio++) {
1460 		buffer[prio] = (u8)(prio_x_buff >> (4 * prio)) & 0xF;
1461 		mlx5_core_dbg(mdev, "prio %d, buffer %d\n", prio, buffer[prio]);
1462 	}
1463 out:
1464 	kfree(in);
1465 	kfree(out);
1466 	return err;
1467 }
1468 
1469 int mlx5e_port_set_priority2buffer(struct mlx5_core_dev *mdev, u8 *buffer)
1470 {
1471 	int sz = MLX5_ST_SZ_BYTES(pptb_reg);
1472 	u32 prio_x_buff;
1473 	void *out;
1474 	void *in;
1475 	int prio;
1476 	int err;
1477 
1478 	in = kzalloc(sz, GFP_KERNEL);
1479 	out = kzalloc(sz, GFP_KERNEL);
1480 	if (!in || !out) {
1481 		err = -ENOMEM;
1482 		goto out;
1483 	}
1484 
1485 	/* First query the pptb register */
1486 	MLX5_SET(pptb_reg, in, local_port, 1);
1487 	err = mlx5_core_access_reg(mdev, in, sz, out, sz, MLX5_REG_PPTB, 0, 0);
1488 	if (err)
1489 		goto out;
1490 
1491 	memcpy(in, out, sz);
1492 	MLX5_SET(pptb_reg, in, local_port, 1);
1493 
1494 	/* Update the pm and prio_x_buff */
1495 	MLX5_SET(pptb_reg, in, pm, 0xFF);
1496 
1497 	prio_x_buff = 0;
1498 	for (prio = 0; prio < 8; prio++)
1499 		prio_x_buff |= (buffer[prio] << (4 * prio));
1500 	MLX5_SET(pptb_reg, in, prio_x_buff, prio_x_buff);
1501 
1502 	err = mlx5_core_access_reg(mdev, in, sz, out, sz, MLX5_REG_PPTB, 0, 1);
1503 
1504 out:
1505 	kfree(in);
1506 	kfree(out);
1507 	return err;
1508 }
1509