mlx5_port.c revision 329207
1/*-
2 * Copyright (c) 2013-2015, 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 329207 2018-02-13 15:09:03Z hselasky $
26 */
27
28#include <linux/module.h>
29#include <dev/mlx5/driver.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	struct mlx5_access_reg_mbox_in *in = NULL;
37	struct mlx5_access_reg_mbox_out *out = NULL;
38	int err = -ENOMEM;
39
40	in = mlx5_vzalloc(sizeof(*in) + size_in);
41	if (!in)
42		return -ENOMEM;
43
44	out = mlx5_vzalloc(sizeof(*out) + size_out);
45	if (!out)
46		goto ex1;
47
48	memcpy(in->data, data_in, size_in);
49	in->hdr.opcode = cpu_to_be16(MLX5_CMD_OP_ACCESS_REG);
50	in->hdr.opmod = cpu_to_be16(!write);
51	in->arg = cpu_to_be32(arg);
52	in->register_id = cpu_to_be16(reg_num);
53	err = mlx5_cmd_exec(dev, in, sizeof(*in) + size_in, out,
54			    sizeof(*out) + size_out);
55	if (err)
56		goto ex2;
57
58	if (out->hdr.status)
59		err = mlx5_cmd_status_to_err(&out->hdr);
60
61	if (!err)
62		memcpy(data_out, out->data, size_out);
63
64ex2:
65	kvfree(out);
66ex1:
67	kvfree(in);
68	return err;
69}
70EXPORT_SYMBOL_GPL(mlx5_core_access_reg);
71
72
73struct mlx5_reg_pcap {
74	u8			rsvd0;
75	u8			port_num;
76	u8			rsvd1[2];
77	__be32			caps_127_96;
78	__be32			caps_95_64;
79	__be32			caps_63_32;
80	__be32			caps_31_0;
81};
82
83/* This function should be used after setting a port register only */
84void mlx5_toggle_port_link(struct mlx5_core_dev *dev)
85{
86	enum mlx5_port_status ps;
87
88	mlx5_query_port_admin_status(dev, &ps);
89	mlx5_set_port_status(dev, MLX5_PORT_DOWN);
90	if (ps == MLX5_PORT_UP)
91		mlx5_set_port_status(dev, MLX5_PORT_UP);
92}
93EXPORT_SYMBOL_GPL(mlx5_toggle_port_link);
94
95int mlx5_set_port_caps(struct mlx5_core_dev *dev, u8 port_num, u32 caps)
96{
97	struct mlx5_reg_pcap in;
98	struct mlx5_reg_pcap out;
99	int err;
100
101	memset(&in, 0, sizeof(in));
102	in.caps_127_96 = cpu_to_be32(caps);
103	in.port_num = port_num;
104
105	err = mlx5_core_access_reg(dev, &in, sizeof(in), &out,
106				   sizeof(out), MLX5_REG_PCAP, 0, 1);
107
108	return err;
109}
110EXPORT_SYMBOL_GPL(mlx5_set_port_caps);
111
112int mlx5_query_port_ptys(struct mlx5_core_dev *dev, u32 *ptys,
113			 int ptys_size, int proto_mask)
114{
115	u32 in[MLX5_ST_SZ_DW(ptys_reg)];
116	int err;
117
118	memset(in, 0, sizeof(in));
119	MLX5_SET(ptys_reg, in, local_port, 1);
120	MLX5_SET(ptys_reg, in, proto_mask, proto_mask);
121
122	err = mlx5_core_access_reg(dev, in, sizeof(in), ptys,
123				   ptys_size, MLX5_REG_PTYS, 0, 0);
124
125	return err;
126}
127EXPORT_SYMBOL_GPL(mlx5_query_port_ptys);
128
129int mlx5_query_port_proto_cap(struct mlx5_core_dev *dev,
130			      u32 *proto_cap, int proto_mask)
131{
132	u32 out[MLX5_ST_SZ_DW(ptys_reg)];
133	int err;
134
135	err = mlx5_query_port_ptys(dev, out, sizeof(out), proto_mask);
136	if (err)
137		return err;
138
139	if (proto_mask == MLX5_PTYS_EN)
140		*proto_cap = MLX5_GET(ptys_reg, out, eth_proto_capability);
141	else
142		*proto_cap = MLX5_GET(ptys_reg, out, ib_proto_capability);
143
144	return 0;
145}
146EXPORT_SYMBOL_GPL(mlx5_query_port_proto_cap);
147
148int mlx5_query_port_autoneg(struct mlx5_core_dev *dev, int proto_mask,
149			    u8 *an_disable_cap, u8 *an_disable_status)
150{
151	u32 out[MLX5_ST_SZ_DW(ptys_reg)];
152	int err;
153
154	err = mlx5_query_port_ptys(dev, out, sizeof(out), proto_mask);
155	if (err)
156		return err;
157
158	*an_disable_status = MLX5_GET(ptys_reg, out, an_disable_admin);
159	*an_disable_cap = MLX5_GET(ptys_reg, out, an_disable_cap);
160
161	return 0;
162}
163EXPORT_SYMBOL_GPL(mlx5_query_port_autoneg);
164
165int mlx5_set_port_autoneg(struct mlx5_core_dev *dev, bool disable,
166			  u32 eth_proto_admin, int proto_mask)
167{
168	u32 in[MLX5_ST_SZ_DW(ptys_reg)];
169	u32 out[MLX5_ST_SZ_DW(ptys_reg)];
170	u8 an_disable_cap;
171	u8 an_disable_status;
172	int err;
173
174	err = mlx5_query_port_autoneg(dev, proto_mask, &an_disable_cap,
175				      &an_disable_status);
176	if (err)
177		return err;
178	if (!an_disable_cap)
179		return -EPERM;
180
181	memset(in, 0, sizeof(in));
182
183	MLX5_SET(ptys_reg, in, local_port, 1);
184	MLX5_SET(ptys_reg, in, an_disable_admin, disable);
185	MLX5_SET(ptys_reg, in, proto_mask, proto_mask);
186	if (proto_mask == MLX5_PTYS_EN)
187		MLX5_SET(ptys_reg, in, eth_proto_admin, eth_proto_admin);
188
189	err = mlx5_core_access_reg(dev, in, sizeof(in), out,
190				   sizeof(out), MLX5_REG_PTYS, 0, 1);
191	return err;
192}
193EXPORT_SYMBOL_GPL(mlx5_set_port_autoneg);
194
195int mlx5_query_port_proto_admin(struct mlx5_core_dev *dev,
196				u32 *proto_admin, int proto_mask)
197{
198	u32 out[MLX5_ST_SZ_DW(ptys_reg)];
199	int err;
200
201	err = mlx5_query_port_ptys(dev, out, sizeof(out), proto_mask);
202	if (err)
203		return err;
204
205	if (proto_mask == MLX5_PTYS_EN)
206		*proto_admin = MLX5_GET(ptys_reg, out, eth_proto_admin);
207	else
208		*proto_admin = MLX5_GET(ptys_reg, out, ib_proto_admin);
209
210	return 0;
211}
212EXPORT_SYMBOL_GPL(mlx5_query_port_proto_admin);
213
214int mlx5_set_port_proto(struct mlx5_core_dev *dev, u32 proto_admin,
215			int proto_mask)
216{
217	u32 in[MLX5_ST_SZ_DW(ptys_reg)];
218	u32 out[MLX5_ST_SZ_DW(ptys_reg)];
219	int err;
220
221	memset(in, 0, sizeof(in));
222
223	MLX5_SET(ptys_reg, in, local_port, 1);
224	MLX5_SET(ptys_reg, in, proto_mask, proto_mask);
225	if (proto_mask == MLX5_PTYS_EN)
226		MLX5_SET(ptys_reg, in, eth_proto_admin, proto_admin);
227	else
228		MLX5_SET(ptys_reg, in, ib_proto_admin, proto_admin);
229
230	err = mlx5_core_access_reg(dev, in, sizeof(in), out,
231				   sizeof(out), MLX5_REG_PTYS, 0, 1);
232	return err;
233}
234EXPORT_SYMBOL_GPL(mlx5_set_port_proto);
235
236int mlx5_set_port_status(struct mlx5_core_dev *dev,
237			 enum mlx5_port_status status)
238{
239	u32 in[MLX5_ST_SZ_DW(paos_reg)];
240	u32 out[MLX5_ST_SZ_DW(paos_reg)];
241	int err;
242
243	memset(in, 0, sizeof(in));
244
245	MLX5_SET(paos_reg, in, local_port, 1);
246
247	MLX5_SET(paos_reg, in, admin_status, status);
248	MLX5_SET(paos_reg, in, ase, 1);
249
250	err = mlx5_core_access_reg(dev, in, sizeof(in), out,
251				   sizeof(out), MLX5_REG_PAOS, 0, 1);
252	return err;
253}
254
255int mlx5_query_port_status(struct mlx5_core_dev *dev, u8 *status)
256{
257	u32 in[MLX5_ST_SZ_DW(paos_reg)];
258	u32 out[MLX5_ST_SZ_DW(paos_reg)];
259	int err;
260
261	memset(in, 0, sizeof(in));
262
263	MLX5_SET(paos_reg, in, local_port, 1);
264
265	err = mlx5_core_access_reg(dev, in, sizeof(in), out,
266				   sizeof(out), MLX5_REG_PAOS, 0, 0);
267	if (err)
268		return err;
269
270	*status = MLX5_GET(paos_reg, out, oper_status);
271	return err;
272}
273
274int mlx5_query_port_admin_status(struct mlx5_core_dev *dev,
275				 enum mlx5_port_status *status)
276{
277	u32 in[MLX5_ST_SZ_DW(paos_reg)] = {0};
278	u32 out[MLX5_ST_SZ_DW(paos_reg)];
279	int err;
280
281	MLX5_SET(paos_reg, in, local_port, 1);
282	err = mlx5_core_access_reg(dev, in, sizeof(in), out,
283				   sizeof(out), MLX5_REG_PAOS, 0, 0);
284	if (err)
285		return err;
286	*status = MLX5_GET(paos_reg, out, admin_status);
287	return 0;
288}
289EXPORT_SYMBOL_GPL(mlx5_query_port_admin_status);
290
291static int mlx5_query_port_mtu(struct mlx5_core_dev *dev,
292			       int *admin_mtu, int *max_mtu, int *oper_mtu)
293{
294	u32 in[MLX5_ST_SZ_DW(pmtu_reg)];
295	u32 out[MLX5_ST_SZ_DW(pmtu_reg)];
296	int err;
297
298	memset(in, 0, sizeof(in));
299
300	MLX5_SET(pmtu_reg, in, local_port, 1);
301
302	err = mlx5_core_access_reg(dev, in, sizeof(in), out,
303				   sizeof(out), MLX5_REG_PMTU, 0, 0);
304	if (err)
305		return err;
306
307	if (max_mtu)
308		*max_mtu  = MLX5_GET(pmtu_reg, out, max_mtu);
309	if (oper_mtu)
310		*oper_mtu = MLX5_GET(pmtu_reg, out, oper_mtu);
311	if (admin_mtu)
312		*admin_mtu = MLX5_GET(pmtu_reg, out, admin_mtu);
313
314	return err;
315}
316
317int mlx5_set_port_mtu(struct mlx5_core_dev *dev, int mtu)
318{
319	u32 in[MLX5_ST_SZ_DW(pmtu_reg)];
320	u32 out[MLX5_ST_SZ_DW(pmtu_reg)];
321
322	memset(in, 0, sizeof(in));
323
324	MLX5_SET(pmtu_reg, in, admin_mtu, mtu);
325	MLX5_SET(pmtu_reg, in, local_port, 1);
326
327	return mlx5_core_access_reg(dev, in, sizeof(in), out,
328				   sizeof(out), MLX5_REG_PMTU, 0, 1);
329}
330EXPORT_SYMBOL_GPL(mlx5_set_port_mtu);
331
332int mlx5_query_port_max_mtu(struct mlx5_core_dev *dev, int *max_mtu)
333{
334	return mlx5_query_port_mtu(dev, NULL, max_mtu, NULL);
335}
336EXPORT_SYMBOL_GPL(mlx5_query_port_max_mtu);
337
338int mlx5_set_port_pause(struct mlx5_core_dev *dev, u32 port,
339			u32 rx_pause, u32 tx_pause)
340{
341	u32 in[MLX5_ST_SZ_DW(pfcc_reg)];
342	u32 out[MLX5_ST_SZ_DW(pfcc_reg)];
343
344	memset(in, 0, sizeof(in));
345	memset(out, 0, sizeof(out));
346
347	MLX5_SET(pfcc_reg, in, local_port, port);
348	MLX5_SET(pfcc_reg, in, pptx, tx_pause);
349	MLX5_SET(pfcc_reg, in, pprx, rx_pause);
350
351	return mlx5_core_access_reg(dev, in, sizeof(in), out,
352				   sizeof(out), MLX5_REG_PFCC, 0, 1);
353}
354
355int mlx5_query_port_pause(struct mlx5_core_dev *dev, u32 port,
356			  u32 *rx_pause, u32 *tx_pause)
357{
358	u32 in[MLX5_ST_SZ_DW(pfcc_reg)];
359	u32 out[MLX5_ST_SZ_DW(pfcc_reg)];
360	int err;
361
362	memset(in, 0, sizeof(in));
363	memset(out, 0, sizeof(out));
364
365	MLX5_SET(pfcc_reg, in, local_port, port);
366
367	err = mlx5_core_access_reg(dev, in, sizeof(in), out,
368				   sizeof(out), MLX5_REG_PFCC, 0, 0);
369	if (err)
370		return err;
371
372	*rx_pause = MLX5_GET(pfcc_reg, out, pprx);
373	*tx_pause = MLX5_GET(pfcc_reg, out, pptx);
374
375	return 0;
376}
377
378int mlx5_set_port_pfc(struct mlx5_core_dev *dev, u8 pfc_en_tx, u8 pfc_en_rx)
379{
380	u32 in[MLX5_ST_SZ_DW(pfcc_reg)] = {0};
381	u32 out[MLX5_ST_SZ_DW(pfcc_reg)];
382
383	MLX5_SET(pfcc_reg, in, local_port, 1);
384	MLX5_SET(pfcc_reg, in, pfctx, pfc_en_tx);
385	MLX5_SET(pfcc_reg, in, pfcrx, pfc_en_rx);
386	MLX5_SET_TO_ONES(pfcc_reg, in, prio_mask_tx);
387	MLX5_SET_TO_ONES(pfcc_reg, in, prio_mask_rx);
388
389	return mlx5_core_access_reg(dev, in, sizeof(in), out,
390				    sizeof(out), MLX5_REG_PFCC, 0, 1);
391}
392EXPORT_SYMBOL_GPL(mlx5_set_port_pfc);
393
394int mlx5_query_port_pfc(struct mlx5_core_dev *dev, u8 *pfc_en_tx, u8 *pfc_en_rx)
395{
396	u32 in[MLX5_ST_SZ_DW(pfcc_reg)] = {0};
397	u32 out[MLX5_ST_SZ_DW(pfcc_reg)];
398	int err;
399
400	MLX5_SET(pfcc_reg, in, local_port, 1);
401	err = mlx5_core_access_reg(dev, in, sizeof(in), out,
402				   sizeof(out), MLX5_REG_PFCC, 0, 0);
403	if (err)
404		return err;
405
406	if (pfc_en_tx)
407		*pfc_en_tx = MLX5_GET(pfcc_reg, out, pfctx);
408
409	if (pfc_en_rx)
410		*pfc_en_rx = MLX5_GET(pfcc_reg, out, pfcrx);
411
412	return 0;
413}
414EXPORT_SYMBOL_GPL(mlx5_query_port_pfc);
415
416int mlx5_query_port_oper_mtu(struct mlx5_core_dev *dev, int *oper_mtu)
417{
418	return mlx5_query_port_mtu(dev, NULL, NULL, oper_mtu);
419}
420EXPORT_SYMBOL_GPL(mlx5_query_port_oper_mtu);
421
422u8 mlx5_is_wol_supported(struct mlx5_core_dev *dev)
423{
424	u8 wol_supported = 0;
425
426	if (MLX5_CAP_GEN(dev, wol_s))
427		wol_supported |= MLX5_WOL_SECURED_MAGIC;
428	if (MLX5_CAP_GEN(dev, wol_g))
429		wol_supported |= MLX5_WOL_MAGIC;
430	if (MLX5_CAP_GEN(dev, wol_a))
431		wol_supported |= MLX5_WOL_ARP;
432	if (MLX5_CAP_GEN(dev, wol_b))
433		wol_supported |= MLX5_WOL_BROADCAST;
434	if (MLX5_CAP_GEN(dev, wol_m))
435		wol_supported |= MLX5_WOL_MULTICAST;
436	if (MLX5_CAP_GEN(dev, wol_u))
437		wol_supported |= MLX5_WOL_UNICAST;
438	if (MLX5_CAP_GEN(dev, wol_p))
439		wol_supported |= MLX5_WOL_PHY_ACTIVITY;
440
441	return wol_supported;
442}
443EXPORT_SYMBOL_GPL(mlx5_is_wol_supported);
444
445int mlx5_set_wol(struct mlx5_core_dev *dev, u8 wol_mode)
446{
447	u32 in[MLX5_ST_SZ_DW(set_wol_rol_in)];
448	u32 out[MLX5_ST_SZ_DW(set_wol_rol_out)];
449
450	memset(in, 0, sizeof(in));
451	memset(out, 0, sizeof(out));
452
453	MLX5_SET(set_wol_rol_in, in, opcode, MLX5_CMD_OP_SET_WOL_ROL);
454	MLX5_SET(set_wol_rol_in, in, wol_mode_valid, 1);
455	MLX5_SET(set_wol_rol_in, in, wol_mode, wol_mode);
456
457	return mlx5_cmd_exec_check_status(dev, in, sizeof(in),
458					  out, sizeof(out));
459}
460EXPORT_SYMBOL_GPL(mlx5_set_wol);
461
462int mlx5_query_dropless_mode(struct mlx5_core_dev *dev, u16 *timeout)
463{
464	u32 in[MLX5_ST_SZ_DW(query_delay_drop_params_in)];
465	u32 out[MLX5_ST_SZ_DW(query_delay_drop_params_out)];
466	int err = 0;
467
468	memset(in, 0, sizeof(in));
469	memset(out, 0, sizeof(out));
470
471	MLX5_SET(query_delay_drop_params_in, in, opcode,
472		 MLX5_CMD_OP_QUERY_DELAY_DROP_PARAMS);
473
474	err = mlx5_cmd_exec_check_status(dev, in, sizeof(in), out, sizeof(out));
475	if (err)
476		return err;
477
478	*timeout = MLX5_GET(query_delay_drop_params_out, out,
479			    delay_drop_timeout);
480
481	return 0;
482}
483EXPORT_SYMBOL_GPL(mlx5_query_dropless_mode);
484
485int mlx5_set_dropless_mode(struct mlx5_core_dev *dev, u16 timeout)
486{
487	u32 in[MLX5_ST_SZ_DW(set_delay_drop_params_in)];
488	u32 out[MLX5_ST_SZ_DW(set_delay_drop_params_out)];
489
490	memset(in, 0, sizeof(in));
491	memset(out, 0, sizeof(out));
492
493	MLX5_SET(set_delay_drop_params_in, in, opcode,
494		 MLX5_CMD_OP_SET_DELAY_DROP_PARAMS);
495	MLX5_SET(set_delay_drop_params_in, in, delay_drop_timeout, timeout);
496
497	return mlx5_cmd_exec_check_status(dev, in, sizeof(in),
498					   out, sizeof(out));
499}
500EXPORT_SYMBOL_GPL(mlx5_set_dropless_mode);
501
502int mlx5_core_access_pvlc(struct mlx5_core_dev *dev,
503			  struct mlx5_pvlc_reg *pvlc, int write)
504{
505	int sz = MLX5_ST_SZ_BYTES(pvlc_reg);
506	u8 in[MLX5_ST_SZ_BYTES(pvlc_reg)];
507	u8 out[MLX5_ST_SZ_BYTES(pvlc_reg)];
508	int err;
509
510	memset(out, 0, sizeof(out));
511	memset(in, 0, sizeof(in));
512
513	MLX5_SET(pvlc_reg, in, local_port, pvlc->local_port);
514	if (write)
515		MLX5_SET(pvlc_reg, in, vl_admin, pvlc->vl_admin);
516
517	err = mlx5_core_access_reg(dev, in, sz, out, sz, MLX5_REG_PVLC, 0,
518				   !!write);
519	if (err)
520		return err;
521
522	if (!write) {
523		pvlc->local_port = MLX5_GET(pvlc_reg, out, local_port);
524		pvlc->vl_hw_cap = MLX5_GET(pvlc_reg, out, vl_hw_cap);
525		pvlc->vl_admin = MLX5_GET(pvlc_reg, out, vl_admin);
526		pvlc->vl_operational = MLX5_GET(pvlc_reg, out, vl_operational);
527	}
528
529	return 0;
530}
531EXPORT_SYMBOL_GPL(mlx5_core_access_pvlc);
532
533int mlx5_core_access_ptys(struct mlx5_core_dev *dev,
534			  struct mlx5_ptys_reg *ptys, int write)
535{
536	int sz = MLX5_ST_SZ_BYTES(ptys_reg);
537	void *out = NULL;
538	void *in = NULL;
539	int err;
540
541	in = mlx5_vzalloc(sz);
542	if (!in)
543		return -ENOMEM;
544
545	out = mlx5_vzalloc(sz);
546	if (!out) {
547		kfree(in);
548		return -ENOMEM;
549	}
550
551	MLX5_SET(ptys_reg, in, local_port, ptys->local_port);
552	MLX5_SET(ptys_reg, in, proto_mask, ptys->proto_mask);
553	if (write) {
554		MLX5_SET(ptys_reg, in, eth_proto_capability,
555			 ptys->eth_proto_cap);
556		MLX5_SET(ptys_reg, in, ib_link_width_capability,
557			 ptys->ib_link_width_cap);
558		MLX5_SET(ptys_reg, in, ib_proto_capability,
559			 ptys->ib_proto_cap);
560		MLX5_SET(ptys_reg, in, eth_proto_admin, ptys->eth_proto_admin);
561		MLX5_SET(ptys_reg, in, ib_link_width_admin,
562			 ptys->ib_link_width_admin);
563		MLX5_SET(ptys_reg, in, ib_proto_admin, ptys->ib_proto_admin);
564		MLX5_SET(ptys_reg, in, eth_proto_oper, ptys->eth_proto_oper);
565		MLX5_SET(ptys_reg, in, ib_link_width_oper,
566			 ptys->ib_link_width_oper);
567		MLX5_SET(ptys_reg, in, ib_proto_oper, ptys->ib_proto_oper);
568		MLX5_SET(ptys_reg, in, eth_proto_lp_advertise,
569			 ptys->eth_proto_lp_advertise);
570	}
571
572	err = mlx5_core_access_reg(dev, in, sz, out, sz, MLX5_REG_PTYS, 0,
573				   !!write);
574	if (err)
575		goto out;
576
577	if (!write) {
578		ptys->local_port = MLX5_GET(ptys_reg, out, local_port);
579		ptys->proto_mask = MLX5_GET(ptys_reg, out, proto_mask);
580		ptys->eth_proto_cap = MLX5_GET(ptys_reg, out,
581					       eth_proto_capability);
582		ptys->ib_link_width_cap = MLX5_GET(ptys_reg, out,
583					   ib_link_width_capability);
584		ptys->ib_proto_cap = MLX5_GET(ptys_reg, out,
585					      ib_proto_capability);
586		ptys->eth_proto_admin = MLX5_GET(ptys_reg, out,
587						 eth_proto_admin);
588		ptys->ib_link_width_admin = MLX5_GET(ptys_reg, out,
589						     ib_link_width_admin);
590		ptys->ib_proto_admin = MLX5_GET(ptys_reg, out, ib_proto_admin);
591		ptys->eth_proto_oper = MLX5_GET(ptys_reg, out, eth_proto_oper);
592		ptys->ib_link_width_oper = MLX5_GET(ptys_reg, out,
593						    ib_link_width_oper);
594		ptys->ib_proto_oper = MLX5_GET(ptys_reg, out, ib_proto_oper);
595		ptys->eth_proto_lp_advertise = MLX5_GET(ptys_reg, out,
596							eth_proto_lp_advertise);
597	}
598
599out:
600	kvfree(in);
601	kvfree(out);
602	return err;
603}
604EXPORT_SYMBOL_GPL(mlx5_core_access_ptys);
605
606static int mtu_to_ib_mtu(int mtu)
607{
608	switch (mtu) {
609	case 256: return 1;
610	case 512: return 2;
611	case 1024: return 3;
612	case 2048: return 4;
613	case 4096: return 5;
614	default:
615		printf("mlx5_core: WARN: ""invalid mtu\n");
616		return -1;
617	}
618}
619
620int mlx5_core_access_pmtu(struct mlx5_core_dev *dev,
621			  struct mlx5_pmtu_reg *pmtu, int write)
622{
623	int sz = MLX5_ST_SZ_BYTES(pmtu_reg);
624	void *out = NULL;
625	void *in = NULL;
626	int err;
627
628	in = mlx5_vzalloc(sz);
629	if (!in)
630		return -ENOMEM;
631
632	out = mlx5_vzalloc(sz);
633	if (!out) {
634		kfree(in);
635		return -ENOMEM;
636	}
637
638	MLX5_SET(pmtu_reg, in, local_port, pmtu->local_port);
639	if (write)
640		MLX5_SET(pmtu_reg, in, admin_mtu, pmtu->admin_mtu);
641
642	err = mlx5_core_access_reg(dev, in, sz, out, sz, MLX5_REG_PMTU, 0,
643				   !!write);
644	if (err)
645		goto out;
646
647	if (!write) {
648		pmtu->local_port = MLX5_GET(pmtu_reg, out, local_port);
649		pmtu->max_mtu = mtu_to_ib_mtu(MLX5_GET(pmtu_reg, out,
650						       max_mtu));
651		pmtu->admin_mtu = mtu_to_ib_mtu(MLX5_GET(pmtu_reg, out,
652							 admin_mtu));
653		pmtu->oper_mtu = mtu_to_ib_mtu(MLX5_GET(pmtu_reg, out,
654							oper_mtu));
655	}
656
657out:
658	kvfree(in);
659	kvfree(out);
660	return err;
661}
662EXPORT_SYMBOL_GPL(mlx5_core_access_pmtu);
663
664int mlx5_query_module_num(struct mlx5_core_dev *dev, int *module_num)
665{
666	u32 in[MLX5_ST_SZ_DW(pmlp_reg)];
667	u32 out[MLX5_ST_SZ_DW(pmlp_reg)];
668	int lane = 0;
669	int err;
670
671	memset(in, 0, sizeof(in));
672
673	MLX5_SET(pmlp_reg, in, local_port, 1);
674
675	err = mlx5_core_access_reg(dev, in, sizeof(in), out,
676				   sizeof(out), MLX5_REG_PMLP, 0, 0);
677	if (err)
678		return err;
679
680	lane = MLX5_GET(pmlp_reg, out, lane0_module_mapping);
681	*module_num = lane & MLX5_EEPROM_IDENTIFIER_BYTE_MASK;
682
683	return 0;
684}
685EXPORT_SYMBOL_GPL(mlx5_query_module_num);
686
687int mlx5_query_eeprom(struct mlx5_core_dev *dev,
688		      int i2c_addr, int page_num, int device_addr,
689		      int size, int module_num, u32 *data, int *size_read)
690{
691	u32 in[MLX5_ST_SZ_DW(mcia_reg)];
692	u32 out[MLX5_ST_SZ_DW(mcia_reg)];
693	u32 *ptr = (u32 *)MLX5_ADDR_OF(mcia_reg, out, dword_0);
694	int status;
695	int err;
696
697	memset(in, 0, sizeof(in));
698	size = min_t(int, size, MLX5_EEPROM_MAX_BYTES);
699
700	MLX5_SET(mcia_reg, in, l, 0);
701	MLX5_SET(mcia_reg, in, module, module_num);
702	MLX5_SET(mcia_reg, in, i2c_device_address, i2c_addr);
703	MLX5_SET(mcia_reg, in, page_number, page_num);
704	MLX5_SET(mcia_reg, in, device_address, device_addr);
705	MLX5_SET(mcia_reg, in, size, size);
706
707	err = mlx5_core_access_reg(dev, in, sizeof(in), out,
708				   sizeof(out), MLX5_REG_MCIA, 0, 0);
709	if (err)
710		return err;
711
712	status = MLX5_GET(mcia_reg, out, status);
713	if (status)
714		return status;
715
716	memcpy(data, ptr, size);
717	*size_read = size;
718	return 0;
719}
720EXPORT_SYMBOL_GPL(mlx5_query_eeprom);
721
722int mlx5_vxlan_udp_port_add(struct mlx5_core_dev *dev, u16 port)
723{
724	u32 in[MLX5_ST_SZ_DW(add_vxlan_udp_dport_in)];
725	u32 out[MLX5_ST_SZ_DW(add_vxlan_udp_dport_out)];
726	int err;
727
728	memset(in, 0, sizeof(in));
729	memset(out, 0, sizeof(out));
730
731	MLX5_SET(add_vxlan_udp_dport_in, in, opcode,
732		 MLX5_CMD_OP_ADD_VXLAN_UDP_DPORT);
733	MLX5_SET(add_vxlan_udp_dport_in, in, vxlan_udp_port, port);
734
735	err = mlx5_cmd_exec_check_status(dev, in, sizeof(in), out, sizeof(out));
736	if (err) {
737		mlx5_core_err(dev, "Failed %s, port %u, err - %d",
738			      mlx5_command_str(MLX5_CMD_OP_ADD_VXLAN_UDP_DPORT),
739			      port, err);
740	}
741
742	return err;
743}
744
745int mlx5_vxlan_udp_port_delete(struct mlx5_core_dev *dev, u16 port)
746{
747	u32 in[MLX5_ST_SZ_DW(delete_vxlan_udp_dport_in)];
748	u32 out[MLX5_ST_SZ_DW(delete_vxlan_udp_dport_out)];
749	int err;
750
751	memset(in, 0, sizeof(in));
752	memset(out, 0, sizeof(out));
753
754	MLX5_SET(delete_vxlan_udp_dport_in, in, opcode,
755		 MLX5_CMD_OP_DELETE_VXLAN_UDP_DPORT);
756	MLX5_SET(delete_vxlan_udp_dport_in, in, vxlan_udp_port, port);
757
758	err = mlx5_cmd_exec_check_status(dev, in, sizeof(in), out, sizeof(out));
759	if (err) {
760		mlx5_core_err(dev, "Failed %s, port %u, err - %d",
761			      mlx5_command_str(MLX5_CMD_OP_DELETE_VXLAN_UDP_DPORT),
762			      port, err);
763	}
764
765	return err;
766}
767
768int mlx5_query_wol(struct mlx5_core_dev *dev, u8 *wol_mode)
769{
770	u32 in[MLX5_ST_SZ_DW(query_wol_rol_in)];
771	u32 out[MLX5_ST_SZ_DW(query_wol_rol_out)];
772	int err;
773
774	memset(in, 0, sizeof(in));
775	memset(out, 0, sizeof(out));
776
777	MLX5_SET(query_wol_rol_in, in, opcode, MLX5_CMD_OP_QUERY_WOL_ROL);
778
779	err = mlx5_cmd_exec_check_status(dev, in, sizeof(in), out, sizeof(out));
780
781	if (!err)
782		*wol_mode = MLX5_GET(query_wol_rol_out, out, wol_mode);
783
784	return err;
785}
786EXPORT_SYMBOL_GPL(mlx5_query_wol);
787
788int mlx5_query_port_cong_status(struct mlx5_core_dev *mdev, int protocol,
789				int priority, int *is_enable)
790{
791	u32 in[MLX5_ST_SZ_DW(query_cong_status_in)];
792	u32 out[MLX5_ST_SZ_DW(query_cong_status_out)];
793	int err;
794
795	memset(in, 0, sizeof(in));
796	memset(out, 0, sizeof(out));
797
798	*is_enable = 0;
799
800	MLX5_SET(query_cong_status_in, in, opcode,
801		 MLX5_CMD_OP_QUERY_CONG_STATUS);
802	MLX5_SET(query_cong_status_in, in, cong_protocol, protocol);
803	MLX5_SET(query_cong_status_in, in, priority, priority);
804
805	err = mlx5_cmd_exec_check_status(mdev, in, sizeof(in),
806					 out, sizeof(out));
807	if (!err)
808		*is_enable = MLX5_GET(query_cong_status_out, out, enable);
809	return err;
810}
811
812int mlx5_modify_port_cong_status(struct mlx5_core_dev *mdev, int protocol,
813				 int priority, int enable)
814{
815	u32 in[MLX5_ST_SZ_DW(modify_cong_status_in)];
816	u32 out[MLX5_ST_SZ_DW(modify_cong_status_out)];
817
818	memset(in, 0, sizeof(in));
819	memset(out, 0, sizeof(out));
820
821	MLX5_SET(modify_cong_status_in, in, opcode,
822		 MLX5_CMD_OP_MODIFY_CONG_STATUS);
823	MLX5_SET(modify_cong_status_in, in, cong_protocol, protocol);
824	MLX5_SET(modify_cong_status_in, in, priority, priority);
825	MLX5_SET(modify_cong_status_in, in, enable, enable);
826
827	return mlx5_cmd_exec_check_status(mdev, in, sizeof(in),
828					  out, sizeof(out));
829}
830
831int mlx5_query_port_cong_params(struct mlx5_core_dev *mdev, int protocol,
832				void *out, int out_size)
833{
834	u32 in[MLX5_ST_SZ_DW(query_cong_params_in)];
835
836	memset(in, 0, sizeof(in));
837
838	MLX5_SET(query_cong_params_in, in, opcode,
839		 MLX5_CMD_OP_QUERY_CONG_PARAMS);
840	MLX5_SET(query_cong_params_in, in, cong_protocol, protocol);
841
842	return mlx5_cmd_exec_check_status(mdev, in, sizeof(in),
843					  out, out_size);
844}
845
846int mlx5_modify_port_cong_params(struct mlx5_core_dev *mdev,
847				 void *in, int in_size)
848{
849	u32 out[MLX5_ST_SZ_DW(modify_cong_params_out)];
850
851	memset(out, 0, sizeof(out));
852
853	MLX5_SET(modify_cong_params_in, in, opcode,
854		 MLX5_CMD_OP_MODIFY_CONG_PARAMS);
855
856	return mlx5_cmd_exec_check_status(mdev, in, in_size, out, sizeof(out));
857}
858
859int mlx5_query_port_cong_statistics(struct mlx5_core_dev *mdev, int clear,
860				    void *out, int out_size)
861{
862	u32 in[MLX5_ST_SZ_DW(query_cong_statistics_in)];
863
864	memset(in, 0, sizeof(in));
865
866	MLX5_SET(query_cong_statistics_in, in, opcode,
867		 MLX5_CMD_OP_QUERY_CONG_STATISTICS);
868	MLX5_SET(query_cong_statistics_in, in, clear, clear);
869
870	return mlx5_cmd_exec_check_status(mdev, in, sizeof(in),
871					  out, out_size);
872}
873
874int mlx5_set_diagnostic_params(struct mlx5_core_dev *mdev, void *in,
875			       int in_size)
876{
877	u32 out[MLX5_ST_SZ_DW(set_diagnostic_params_out)];
878
879	memset(out, 0, sizeof(out));
880
881	MLX5_SET(set_diagnostic_params_in, in, opcode,
882		 MLX5_CMD_OP_SET_DIAGNOSTICS);
883
884	return mlx5_cmd_exec_check_status(mdev, in, in_size, out, sizeof(out));
885}
886
887int mlx5_query_diagnostic_counters(struct mlx5_core_dev *mdev,
888				   u8 num_of_samples, u16 sample_index,
889				   void *out, int out_size)
890{
891	u32 in[MLX5_ST_SZ_DW(query_diagnostic_counters_in)];
892
893	memset(in, 0, sizeof(in));
894
895	MLX5_SET(query_diagnostic_counters_in, in, opcode,
896		 MLX5_CMD_OP_QUERY_DIAGNOSTICS);
897	MLX5_SET(query_diagnostic_counters_in, in, num_of_samples,
898		 num_of_samples);
899	MLX5_SET(query_diagnostic_counters_in, in, sample_index, sample_index);
900
901	return mlx5_cmd_exec_check_status(mdev, in, sizeof(in), out, out_size);
902}
903