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