xref: /NextBSD/sys/dev/mlx5/mlx5_core/mlx5_port.c (revision 4557fabb34e865d7f40be64b39c9e34fa41dbb60)
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$
26  */
27 
28 #include <linux/module.h>
29 #include <dev/mlx5/driver.h>
30 #include "mlx5_core.h"
31 
mlx5_core_access_reg(struct mlx5_core_dev * dev,void * data_in,int size_in,void * data_out,int size_out,u16 reg_num,int arg,int write)32 int mlx5_core_access_reg(struct mlx5_core_dev *dev, void *data_in,
33 			 int size_in, void *data_out, int size_out,
34 			 u16 reg_num, int arg, int write)
35 {
36 	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 
64 ex2:
65 	kvfree(out);
66 ex1:
67 	kvfree(in);
68 	return err;
69 }
70 EXPORT_SYMBOL_GPL(mlx5_core_access_reg);
71 
72 
73 struct 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 
mlx5_set_port_caps(struct mlx5_core_dev * dev,u8 port_num,u32 caps)83 int mlx5_set_port_caps(struct mlx5_core_dev *dev, u8 port_num, u32 caps)
84 {
85 	struct mlx5_reg_pcap in;
86 	struct mlx5_reg_pcap out;
87 	int err;
88 
89 	memset(&in, 0, sizeof(in));
90 	in.caps_127_96 = cpu_to_be32(caps);
91 	in.port_num = port_num;
92 
93 	err = mlx5_core_access_reg(dev, &in, sizeof(in), &out,
94 				   sizeof(out), MLX5_REG_PCAP, 0, 1);
95 
96 	return err;
97 }
98 EXPORT_SYMBOL_GPL(mlx5_set_port_caps);
99 
mlx5_query_port_ptys(struct mlx5_core_dev * dev,u32 * ptys,int ptys_size,int proto_mask)100 int mlx5_query_port_ptys(struct mlx5_core_dev *dev, u32 *ptys,
101 			 int ptys_size, int proto_mask)
102 {
103 	u32 in[MLX5_ST_SZ_DW(ptys_reg)];
104 	int err;
105 
106 	memset(in, 0, sizeof(in));
107 	MLX5_SET(ptys_reg, in, local_port, 1);
108 	MLX5_SET(ptys_reg, in, proto_mask, proto_mask);
109 
110 	err = mlx5_core_access_reg(dev, in, sizeof(in), ptys,
111 				   ptys_size, MLX5_REG_PTYS, 0, 0);
112 
113 	return err;
114 }
115 EXPORT_SYMBOL_GPL(mlx5_query_port_ptys);
116 
mlx5_query_port_proto_cap(struct mlx5_core_dev * dev,u32 * proto_cap,int proto_mask)117 int mlx5_query_port_proto_cap(struct mlx5_core_dev *dev,
118 			      u32 *proto_cap, int proto_mask)
119 {
120 	u32 out[MLX5_ST_SZ_DW(ptys_reg)];
121 	int err;
122 
123 	err = mlx5_query_port_ptys(dev, out, sizeof(out), proto_mask);
124 	if (err)
125 		return err;
126 
127 	if (proto_mask == MLX5_PTYS_EN)
128 		*proto_cap = MLX5_GET(ptys_reg, out, eth_proto_capability);
129 	else
130 		*proto_cap = MLX5_GET(ptys_reg, out, ib_proto_capability);
131 
132 	return 0;
133 }
134 EXPORT_SYMBOL_GPL(mlx5_query_port_proto_cap);
135 
mlx5_query_port_proto_admin(struct mlx5_core_dev * dev,u32 * proto_admin,int proto_mask)136 int mlx5_query_port_proto_admin(struct mlx5_core_dev *dev,
137 				u32 *proto_admin, int proto_mask)
138 {
139 	u32 out[MLX5_ST_SZ_DW(ptys_reg)];
140 	int err;
141 
142 	err = mlx5_query_port_ptys(dev, out, sizeof(out), proto_mask);
143 	if (err)
144 		return err;
145 
146 	if (proto_mask == MLX5_PTYS_EN)
147 		*proto_admin = MLX5_GET(ptys_reg, out, eth_proto_admin);
148 	else
149 		*proto_admin = MLX5_GET(ptys_reg, out, ib_proto_admin);
150 
151 	return 0;
152 }
153 EXPORT_SYMBOL_GPL(mlx5_query_port_proto_admin);
154 
mlx5_set_port_proto(struct mlx5_core_dev * dev,u32 proto_admin,int proto_mask)155 int mlx5_set_port_proto(struct mlx5_core_dev *dev, u32 proto_admin,
156 			int proto_mask)
157 {
158 	u32 in[MLX5_ST_SZ_DW(ptys_reg)];
159 	u32 out[MLX5_ST_SZ_DW(ptys_reg)];
160 	int err;
161 
162 	memset(in, 0, sizeof(in));
163 
164 	MLX5_SET(ptys_reg, in, local_port, 1);
165 	MLX5_SET(ptys_reg, in, proto_mask, proto_mask);
166 	if (proto_mask == MLX5_PTYS_EN)
167 		MLX5_SET(ptys_reg, in, eth_proto_admin, proto_admin);
168 	else
169 		MLX5_SET(ptys_reg, in, ib_proto_admin, proto_admin);
170 
171 	err = mlx5_core_access_reg(dev, in, sizeof(in), out,
172 				   sizeof(out), MLX5_REG_PTYS, 0, 1);
173 	return err;
174 }
175 EXPORT_SYMBOL_GPL(mlx5_set_port_proto);
176 
mlx5_set_port_status(struct mlx5_core_dev * dev,enum mlx5_port_status status)177 int mlx5_set_port_status(struct mlx5_core_dev *dev,
178 			 enum mlx5_port_status status)
179 {
180 	u32 in[MLX5_ST_SZ_DW(paos_reg)];
181 	u32 out[MLX5_ST_SZ_DW(paos_reg)];
182 	int err;
183 
184 	memset(in, 0, sizeof(in));
185 
186 	MLX5_SET(paos_reg, in, local_port, 1);
187 
188 	MLX5_SET(paos_reg, in, admin_status, status);
189 	MLX5_SET(paos_reg, in, ase, 1);
190 
191 	err = mlx5_core_access_reg(dev, in, sizeof(in), out,
192 				   sizeof(out), MLX5_REG_PAOS, 0, 1);
193 	return err;
194 }
195 
mlx5_query_port_status(struct mlx5_core_dev * dev,u8 * status)196 int mlx5_query_port_status(struct mlx5_core_dev *dev, u8 *status)
197 {
198 	u32 in[MLX5_ST_SZ_DW(paos_reg)];
199 	u32 out[MLX5_ST_SZ_DW(paos_reg)];
200 	int err;
201 
202 	memset(in, 0, sizeof(in));
203 
204 	MLX5_SET(paos_reg, in, local_port, 1);
205 
206 	err = mlx5_core_access_reg(dev, in, sizeof(in), out,
207 				   sizeof(out), MLX5_REG_PAOS, 0, 0);
208 	if (err)
209 		return err;
210 
211 	*status = MLX5_GET(paos_reg, out, oper_status);
212 	return err;
213 }
214 
mlx5_query_port_mtu(struct mlx5_core_dev * dev,int * admin_mtu,int * max_mtu,int * oper_mtu)215 static int mlx5_query_port_mtu(struct mlx5_core_dev *dev,
216 			       int *admin_mtu, int *max_mtu, int *oper_mtu)
217 {
218 	u32 in[MLX5_ST_SZ_DW(pmtu_reg)];
219 	u32 out[MLX5_ST_SZ_DW(pmtu_reg)];
220 	int err;
221 
222 	memset(in, 0, sizeof(in));
223 
224 	MLX5_SET(pmtu_reg, in, local_port, 1);
225 
226 	err = mlx5_core_access_reg(dev, in, sizeof(in), out,
227 				   sizeof(out), MLX5_REG_PMTU, 0, 0);
228 	if (err)
229 		return err;
230 
231 	if (max_mtu)
232 		*max_mtu  = MLX5_GET(pmtu_reg, out, max_mtu);
233 	if (oper_mtu)
234 		*oper_mtu = MLX5_GET(pmtu_reg, out, oper_mtu);
235 	if (admin_mtu)
236 		*admin_mtu = MLX5_GET(pmtu_reg, out, admin_mtu);
237 
238 	return err;
239 }
240 
mlx5_set_port_mtu(struct mlx5_core_dev * dev,int mtu)241 int mlx5_set_port_mtu(struct mlx5_core_dev *dev, int mtu)
242 {
243 	u32 in[MLX5_ST_SZ_DW(pmtu_reg)];
244 	u32 out[MLX5_ST_SZ_DW(pmtu_reg)];
245 
246 	memset(in, 0, sizeof(in));
247 
248 	MLX5_SET(pmtu_reg, in, admin_mtu, mtu);
249 	MLX5_SET(pmtu_reg, in, local_port, 1);
250 
251 	return mlx5_core_access_reg(dev, in, sizeof(in), out,
252 				   sizeof(out), MLX5_REG_PMTU, 0, 1);
253 }
254 EXPORT_SYMBOL_GPL(mlx5_set_port_mtu);
255 
mlx5_query_port_max_mtu(struct mlx5_core_dev * dev,int * max_mtu)256 int mlx5_query_port_max_mtu(struct mlx5_core_dev *dev, int *max_mtu)
257 {
258 	return mlx5_query_port_mtu(dev, NULL, max_mtu, NULL);
259 }
260 EXPORT_SYMBOL_GPL(mlx5_query_port_max_mtu);
261 
mlx5_set_port_pause(struct mlx5_core_dev * dev,u32 port,u32 rx_pause,u32 tx_pause)262 int mlx5_set_port_pause(struct mlx5_core_dev *dev, u32 port,
263 			u32 rx_pause, u32 tx_pause)
264 {
265 	u32 in[MLX5_ST_SZ_DW(pfcc_reg)];
266 	u32 out[MLX5_ST_SZ_DW(pfcc_reg)];
267 
268 	memset(in, 0, sizeof(in));
269 	memset(out, 0, sizeof(out));
270 
271 	MLX5_SET(pfcc_reg, in, local_port, port);
272 	MLX5_SET(pfcc_reg, in, pptx, tx_pause);
273 	MLX5_SET(pfcc_reg, in, pprx, rx_pause);
274 
275 	return mlx5_core_access_reg(dev, in, sizeof(in), out,
276 				   sizeof(out), MLX5_REG_PFCC, 0, 1);
277 }
278 
mlx5_query_port_pause(struct mlx5_core_dev * dev,u32 port,u32 * rx_pause,u32 * tx_pause)279 int mlx5_query_port_pause(struct mlx5_core_dev *dev, u32 port,
280 			  u32 *rx_pause, u32 *tx_pause)
281 {
282 	u32 in[MLX5_ST_SZ_DW(pfcc_reg)];
283 	u32 out[MLX5_ST_SZ_DW(pfcc_reg)];
284 	int err;
285 
286 	memset(in, 0, sizeof(in));
287 	memset(out, 0, sizeof(out));
288 
289 	MLX5_SET(pfcc_reg, in, local_port, port);
290 
291 	err = mlx5_core_access_reg(dev, in, sizeof(in), out,
292 				   sizeof(out), MLX5_REG_PFCC, 0, 0);
293 	if (err)
294 		return err;
295 
296 	*rx_pause = MLX5_GET(pfcc_reg, out, pprx);
297 	*tx_pause = MLX5_GET(pfcc_reg, out, pptx);
298 
299 	return 0;
300 }
301 
mlx5_query_port_oper_mtu(struct mlx5_core_dev * dev,int * oper_mtu)302 int mlx5_query_port_oper_mtu(struct mlx5_core_dev *dev, int *oper_mtu)
303 {
304 	return mlx5_query_port_mtu(dev, NULL, NULL, oper_mtu);
305 }
306 EXPORT_SYMBOL_GPL(mlx5_query_port_oper_mtu);
307 
mlx5_is_wol_supported(struct mlx5_core_dev * dev)308 u8 mlx5_is_wol_supported(struct mlx5_core_dev *dev)
309 {
310 	u8 wol_supported = 0;
311 
312 	if (MLX5_CAP_GEN(dev, wol_s))
313 		wol_supported |= MLX5_WOL_SECURED_MAGIC;
314 	if (MLX5_CAP_GEN(dev, wol_g))
315 		wol_supported |= MLX5_WOL_MAGIC;
316 	if (MLX5_CAP_GEN(dev, wol_a))
317 		wol_supported |= MLX5_WOL_ARP;
318 	if (MLX5_CAP_GEN(dev, wol_b))
319 		wol_supported |= MLX5_WOL_BROADCAST;
320 	if (MLX5_CAP_GEN(dev, wol_m))
321 		wol_supported |= MLX5_WOL_MULTICAST;
322 	if (MLX5_CAP_GEN(dev, wol_u))
323 		wol_supported |= MLX5_WOL_UNICAST;
324 	if (MLX5_CAP_GEN(dev, wol_p))
325 		wol_supported |= MLX5_WOL_PHY_ACTIVITY;
326 
327 	return wol_supported;
328 }
329 EXPORT_SYMBOL_GPL(mlx5_is_wol_supported);
330 
mlx5_set_wol(struct mlx5_core_dev * dev,u8 wol_mode)331 int mlx5_set_wol(struct mlx5_core_dev *dev, u8 wol_mode)
332 {
333 	u32 in[MLX5_ST_SZ_DW(set_wol_rol_in)];
334 	u32 out[MLX5_ST_SZ_DW(set_wol_rol_out)];
335 
336 	memset(in, 0, sizeof(in));
337 	memset(out, 0, sizeof(out));
338 
339 	MLX5_SET(set_wol_rol_in, in, opcode, MLX5_CMD_OP_SET_WOL_ROL);
340 	MLX5_SET(set_wol_rol_in, in, wol_mode_valid, 1);
341 	MLX5_SET(set_wol_rol_in, in, wol_mode, wol_mode);
342 
343 	return mlx5_cmd_exec_check_status(dev, in, sizeof(in),
344 					  out, sizeof(out));
345 }
346 EXPORT_SYMBOL_GPL(mlx5_set_wol);
347 
mlx5_core_access_pvlc(struct mlx5_core_dev * dev,struct mlx5_pvlc_reg * pvlc,int write)348 int mlx5_core_access_pvlc(struct mlx5_core_dev *dev,
349 			  struct mlx5_pvlc_reg *pvlc, int write)
350 {
351 	int sz = MLX5_ST_SZ_BYTES(pvlc_reg);
352 	u8 in[MLX5_ST_SZ_BYTES(pvlc_reg)];
353 	u8 out[MLX5_ST_SZ_BYTES(pvlc_reg)];
354 	int err;
355 
356 	memset(out, 0, sizeof(out));
357 	memset(in, 0, sizeof(in));
358 
359 	MLX5_SET(pvlc_reg, in, local_port, pvlc->local_port);
360 	if (write)
361 		MLX5_SET(pvlc_reg, in, vl_admin, pvlc->vl_admin);
362 
363 	err = mlx5_core_access_reg(dev, in, sz, out, sz, MLX5_REG_PVLC, 0,
364 				   !!write);
365 	if (err)
366 		return err;
367 
368 	if (!write) {
369 		pvlc->local_port = MLX5_GET(pvlc_reg, out, local_port);
370 		pvlc->vl_hw_cap = MLX5_GET(pvlc_reg, out, vl_hw_cap);
371 		pvlc->vl_admin = MLX5_GET(pvlc_reg, out, vl_admin);
372 		pvlc->vl_operational = MLX5_GET(pvlc_reg, out, vl_operational);
373 	}
374 
375 	return 0;
376 }
377 EXPORT_SYMBOL_GPL(mlx5_core_access_pvlc);
378 
mlx5_core_access_ptys(struct mlx5_core_dev * dev,struct mlx5_ptys_reg * ptys,int write)379 int mlx5_core_access_ptys(struct mlx5_core_dev *dev,
380 			  struct mlx5_ptys_reg *ptys, int write)
381 {
382 	int sz = MLX5_ST_SZ_BYTES(ptys_reg);
383 	void *out = NULL;
384 	void *in = NULL;
385 	int err;
386 
387 	in = mlx5_vzalloc(sz);
388 	if (!in)
389 		return -ENOMEM;
390 
391 	out = mlx5_vzalloc(sz);
392 	if (!out) {
393 		kfree(in);
394 		return -ENOMEM;
395 	}
396 
397 	MLX5_SET(ptys_reg, in, local_port, ptys->local_port);
398 	MLX5_SET(ptys_reg, in, proto_mask, ptys->proto_mask);
399 	if (write) {
400 		MLX5_SET(ptys_reg, in, eth_proto_capability,
401 			 ptys->eth_proto_cap);
402 		MLX5_SET(ptys_reg, in, ib_link_width_capability,
403 			 ptys->ib_link_width_cap);
404 		MLX5_SET(ptys_reg, in, ib_proto_capability,
405 			 ptys->ib_proto_cap);
406 		MLX5_SET(ptys_reg, in, eth_proto_admin, ptys->eth_proto_admin);
407 		MLX5_SET(ptys_reg, in, ib_link_width_admin,
408 			 ptys->ib_link_width_admin);
409 		MLX5_SET(ptys_reg, in, ib_proto_admin, ptys->ib_proto_admin);
410 		MLX5_SET(ptys_reg, in, eth_proto_oper, ptys->eth_proto_oper);
411 		MLX5_SET(ptys_reg, in, ib_link_width_oper,
412 			 ptys->ib_link_width_oper);
413 		MLX5_SET(ptys_reg, in, ib_proto_oper, ptys->ib_proto_oper);
414 		MLX5_SET(ptys_reg, in, eth_proto_lp_advertise,
415 			 ptys->eth_proto_lp_advertise);
416 	}
417 
418 	err = mlx5_core_access_reg(dev, in, sz, out, sz, MLX5_REG_PTYS, 0,
419 				   !!write);
420 	if (err)
421 		goto out;
422 
423 	if (!write) {
424 		ptys->local_port = MLX5_GET(ptys_reg, out, local_port);
425 		ptys->proto_mask = MLX5_GET(ptys_reg, out, proto_mask);
426 		ptys->eth_proto_cap = MLX5_GET(ptys_reg, out,
427 					       eth_proto_capability);
428 		ptys->ib_link_width_cap = MLX5_GET(ptys_reg, out,
429 					   ib_link_width_capability);
430 		ptys->ib_proto_cap = MLX5_GET(ptys_reg, out,
431 					      ib_proto_capability);
432 		ptys->eth_proto_admin = MLX5_GET(ptys_reg, out,
433 						 eth_proto_admin);
434 		ptys->ib_link_width_admin = MLX5_GET(ptys_reg, out,
435 						     ib_link_width_admin);
436 		ptys->ib_proto_admin = MLX5_GET(ptys_reg, out, ib_proto_admin);
437 		ptys->eth_proto_oper = MLX5_GET(ptys_reg, out, eth_proto_oper);
438 		ptys->ib_link_width_oper = MLX5_GET(ptys_reg, out,
439 						    ib_link_width_oper);
440 		ptys->ib_proto_oper = MLX5_GET(ptys_reg, out, ib_proto_oper);
441 		ptys->eth_proto_lp_advertise = MLX5_GET(ptys_reg, out,
442 							eth_proto_lp_advertise);
443 	}
444 
445 out:
446 	kvfree(in);
447 	kvfree(out);
448 	return err;
449 }
450 EXPORT_SYMBOL_GPL(mlx5_core_access_ptys);
451 
mtu_to_ib_mtu(int mtu)452 static int mtu_to_ib_mtu(int mtu)
453 {
454 	switch (mtu) {
455 	case 256: return 1;
456 	case 512: return 2;
457 	case 1024: return 3;
458 	case 2048: return 4;
459 	case 4096: return 5;
460 	default:
461 		printf("mlx5_core: WARN: ""invalid mtu\n");
462 		return -1;
463 	}
464 }
465 
mlx5_core_access_pmtu(struct mlx5_core_dev * dev,struct mlx5_pmtu_reg * pmtu,int write)466 int mlx5_core_access_pmtu(struct mlx5_core_dev *dev,
467 			  struct mlx5_pmtu_reg *pmtu, int write)
468 {
469 	int sz = MLX5_ST_SZ_BYTES(pmtu_reg);
470 	void *out = NULL;
471 	void *in = NULL;
472 	int err;
473 
474 	in = mlx5_vzalloc(sz);
475 	if (!in)
476 		return -ENOMEM;
477 
478 	out = mlx5_vzalloc(sz);
479 	if (!out) {
480 		kfree(in);
481 		return -ENOMEM;
482 	}
483 
484 	MLX5_SET(pmtu_reg, in, local_port, pmtu->local_port);
485 	if (write)
486 		MLX5_SET(pmtu_reg, in, admin_mtu, pmtu->admin_mtu);
487 
488 	err = mlx5_core_access_reg(dev, in, sz, out, sz, MLX5_REG_PMTU, 0,
489 				   !!write);
490 	if (err)
491 		goto out;
492 
493 	if (!write) {
494 		pmtu->local_port = MLX5_GET(pmtu_reg, out, local_port);
495 		pmtu->max_mtu = mtu_to_ib_mtu(MLX5_GET(pmtu_reg, out,
496 						       max_mtu));
497 		pmtu->admin_mtu = mtu_to_ib_mtu(MLX5_GET(pmtu_reg, out,
498 							 admin_mtu));
499 		pmtu->oper_mtu = mtu_to_ib_mtu(MLX5_GET(pmtu_reg, out,
500 							oper_mtu));
501 	}
502 
503 out:
504 	kvfree(in);
505 	kvfree(out);
506 	return err;
507 }
508 EXPORT_SYMBOL_GPL(mlx5_core_access_pmtu);
509 
mlx5_query_module_num(struct mlx5_core_dev * dev,int * module_num)510 int mlx5_query_module_num(struct mlx5_core_dev *dev, int *module_num)
511 {
512 	u32 in[MLX5_ST_SZ_DW(pmlp_reg)];
513 	u32 out[MLX5_ST_SZ_DW(pmlp_reg)];
514 	int lane = 0;
515 	int err;
516 
517 	memset(in, 0, sizeof(in));
518 
519 	MLX5_SET(pmlp_reg, in, local_port, 1);
520 
521 	err = mlx5_core_access_reg(dev, in, sizeof(in), out,
522 				   sizeof(out), MLX5_REG_PMLP, 0, 0);
523 	if (err)
524 		return err;
525 
526 	lane = MLX5_GET(pmlp_reg, out, lane0_module_mapping);
527 	*module_num = lane & MLX5_EEPROM_IDENTIFIER_BYTE_MASK;
528 
529 	return 0;
530 }
531 EXPORT_SYMBOL_GPL(mlx5_query_module_num);
532 
mlx5_query_eeprom(struct mlx5_core_dev * dev,int i2c_addr,int page_num,int device_addr,int size,int module_num,u32 * data,int * size_read)533 int mlx5_query_eeprom(struct mlx5_core_dev *dev,
534 		      int i2c_addr, int page_num, int device_addr,
535 		      int size, int module_num, u32 *data, int *size_read)
536 {
537 	u32 in[MLX5_ST_SZ_DW(mcia_reg)];
538 	u32 out[MLX5_ST_SZ_DW(mcia_reg)];
539 	u32 *ptr = (u32 *)MLX5_ADDR_OF(mcia_reg, out, dword_0);
540 	int status;
541 	int err;
542 
543 	memset(in, 0, sizeof(in));
544 	size = min_t(int, size, MLX5_EEPROM_MAX_BYTES);
545 
546 	MLX5_SET(mcia_reg, in, l, 0);
547 	MLX5_SET(mcia_reg, in, module, module_num);
548 	MLX5_SET(mcia_reg, in, i2c_device_address, i2c_addr);
549 	MLX5_SET(mcia_reg, in, page_number, page_num);
550 	MLX5_SET(mcia_reg, in, device_address, device_addr);
551 	MLX5_SET(mcia_reg, in, size, size);
552 
553 	err = mlx5_core_access_reg(dev, in, sizeof(in), out,
554 				   sizeof(out), MLX5_REG_MCIA, 0, 0);
555 	if (err)
556 		return err;
557 
558 	status = MLX5_GET(mcia_reg, out, status);
559 	if (status)
560 		return status;
561 
562 	memcpy(data, ptr, size);
563 	*size_read = size;
564 	return 0;
565 }
566 EXPORT_SYMBOL_GPL(mlx5_query_eeprom);
567 
mlx5_vxlan_udp_port_add(struct mlx5_core_dev * dev,u16 port)568 int mlx5_vxlan_udp_port_add(struct mlx5_core_dev *dev, u16 port)
569 {
570 	u32 in[MLX5_ST_SZ_DW(add_vxlan_udp_dport_in)];
571 	u32 out[MLX5_ST_SZ_DW(add_vxlan_udp_dport_out)];
572 	int err;
573 
574 	memset(in, 0, sizeof(in));
575 	memset(out, 0, sizeof(out));
576 
577 	MLX5_SET(add_vxlan_udp_dport_in, in, opcode,
578 		 MLX5_CMD_OP_ADD_VXLAN_UDP_DPORT);
579 	MLX5_SET(add_vxlan_udp_dport_in, in, vxlan_udp_port, port);
580 
581 	err = mlx5_cmd_exec_check_status(dev, in, sizeof(in), out, sizeof(out));
582 	if (err) {
583 		mlx5_core_err(dev, "Failed %s, port %u, err - %d",
584 			      mlx5_command_str(MLX5_CMD_OP_ADD_VXLAN_UDP_DPORT),
585 			      port, err);
586 	}
587 
588 	return err;
589 }
590 
mlx5_vxlan_udp_port_delete(struct mlx5_core_dev * dev,u16 port)591 int mlx5_vxlan_udp_port_delete(struct mlx5_core_dev *dev, u16 port)
592 {
593 	u32 in[MLX5_ST_SZ_DW(delete_vxlan_udp_dport_in)];
594 	u32 out[MLX5_ST_SZ_DW(delete_vxlan_udp_dport_out)];
595 	int err;
596 
597 	memset(in, 0, sizeof(in));
598 	memset(out, 0, sizeof(out));
599 
600 	MLX5_SET(delete_vxlan_udp_dport_in, in, opcode,
601 		 MLX5_CMD_OP_DELETE_VXLAN_UDP_DPORT);
602 	MLX5_SET(delete_vxlan_udp_dport_in, in, vxlan_udp_port, port);
603 
604 	err = mlx5_cmd_exec_check_status(dev, in, sizeof(in), out, sizeof(out));
605 	if (err) {
606 		mlx5_core_err(dev, "Failed %s, port %u, err - %d",
607 			      mlx5_command_str(MLX5_CMD_OP_DELETE_VXLAN_UDP_DPORT),
608 			      port, err);
609 	}
610 
611 	return err;
612 }
613 
mlx5_query_wol(struct mlx5_core_dev * dev,u8 * wol_mode)614 int mlx5_query_wol(struct mlx5_core_dev *dev, u8 *wol_mode)
615 {
616 	u32 in[MLX5_ST_SZ_DW(query_wol_rol_in)];
617 	u32 out[MLX5_ST_SZ_DW(query_wol_rol_out)];
618 	int err;
619 
620 	memset(in, 0, sizeof(in));
621 	memset(out, 0, sizeof(out));
622 
623 	MLX5_SET(query_wol_rol_in, in, opcode, MLX5_CMD_OP_QUERY_WOL_ROL);
624 
625 	err = mlx5_cmd_exec_check_status(dev, in, sizeof(in), out, sizeof(out));
626 
627 	if (!err)
628 		*wol_mode = MLX5_GET(query_wol_rol_out, out, wol_mode);
629 
630 	return err;
631 }
632 EXPORT_SYMBOL_GPL(mlx5_query_wol);
633 
mlx5_query_port_cong_status(struct mlx5_core_dev * mdev,int protocol,int priority,int * is_enable)634 int mlx5_query_port_cong_status(struct mlx5_core_dev *mdev, int protocol,
635 				int priority, int *is_enable)
636 {
637 	u32 in[MLX5_ST_SZ_DW(query_cong_status_in)];
638 	u32 out[MLX5_ST_SZ_DW(query_cong_status_out)];
639 	int err;
640 
641 	memset(in, 0, sizeof(in));
642 	memset(out, 0, sizeof(out));
643 
644 	*is_enable = 0;
645 
646 	MLX5_SET(query_cong_status_in, in, opcode,
647 		 MLX5_CMD_OP_QUERY_CONG_STATUS);
648 	MLX5_SET(query_cong_status_in, in, cong_protocol, protocol);
649 	MLX5_SET(query_cong_status_in, in, priority, priority);
650 
651 	err = mlx5_cmd_exec_check_status(mdev, in, sizeof(in),
652 					 out, sizeof(out));
653 	if (!err)
654 		*is_enable = MLX5_GET(query_cong_status_out, out, enable);
655 	return err;
656 }
657 
mlx5_modify_port_cong_status(struct mlx5_core_dev * mdev,int protocol,int priority,int enable)658 int mlx5_modify_port_cong_status(struct mlx5_core_dev *mdev, int protocol,
659 				 int priority, int enable)
660 {
661 	u32 in[MLX5_ST_SZ_DW(modify_cong_status_in)];
662 	u32 out[MLX5_ST_SZ_DW(modify_cong_status_out)];
663 
664 	memset(in, 0, sizeof(in));
665 	memset(out, 0, sizeof(out));
666 
667 	MLX5_SET(modify_cong_status_in, in, opcode,
668 		 MLX5_CMD_OP_MODIFY_CONG_STATUS);
669 	MLX5_SET(modify_cong_status_in, in, cong_protocol, protocol);
670 	MLX5_SET(modify_cong_status_in, in, priority, priority);
671 	MLX5_SET(modify_cong_status_in, in, enable, enable);
672 
673 	return mlx5_cmd_exec_check_status(mdev, in, sizeof(in),
674 					  out, sizeof(out));
675 }
676 
mlx5_query_port_cong_params(struct mlx5_core_dev * mdev,int protocol,void * out,int out_size)677 int mlx5_query_port_cong_params(struct mlx5_core_dev *mdev, int protocol,
678 				void *out, int out_size)
679 {
680 	u32 in[MLX5_ST_SZ_DW(query_cong_params_in)];
681 
682 	memset(in, 0, sizeof(in));
683 
684 	MLX5_SET(query_cong_params_in, in, opcode,
685 		 MLX5_CMD_OP_QUERY_CONG_PARAMS);
686 	MLX5_SET(query_cong_params_in, in, cong_protocol, protocol);
687 
688 	return mlx5_cmd_exec_check_status(mdev, in, sizeof(in),
689 					  out, out_size);
690 }
691 
mlx5_modify_port_cong_params(struct mlx5_core_dev * mdev,void * in,int in_size)692 int mlx5_modify_port_cong_params(struct mlx5_core_dev *mdev,
693 				 void *in, int in_size)
694 {
695 	u32 out[MLX5_ST_SZ_DW(modify_cong_params_out)];
696 
697 	memset(out, 0, sizeof(out));
698 
699 	MLX5_SET(modify_cong_params_in, in, opcode,
700 		 MLX5_CMD_OP_MODIFY_CONG_PARAMS);
701 
702 	return mlx5_cmd_exec_check_status(mdev, in, in_size, out, sizeof(out));
703 }
704 
mlx5_query_port_cong_statistics(struct mlx5_core_dev * mdev,int clear,void * out,int out_size)705 int mlx5_query_port_cong_statistics(struct mlx5_core_dev *mdev, int clear,
706 				    void *out, int out_size)
707 {
708 	u32 in[MLX5_ST_SZ_DW(query_cong_statistics_in)];
709 
710 	memset(in, 0, sizeof(in));
711 
712 	MLX5_SET(query_cong_statistics_in, in, opcode,
713 		 MLX5_CMD_OP_QUERY_CONG_STATISTICS);
714 	MLX5_SET(query_cong_statistics_in, in, clear, clear);
715 
716 	return mlx5_cmd_exec_check_status(mdev, in, sizeof(in),
717 					  out, out_size);
718 }
719