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