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