mlx5_port.c revision 331583
1/*- 2 * Copyright (c) 2013-2015, Mellanox Technologies, Ltd. All rights reserved. 3 * 4 * Redistribution and use in source and binary forms, with or without 5 * modification, are permitted provided that the following conditions 6 * are met: 7 * 1. Redistributions of source code must retain the above copyright 8 * notice, this list of conditions and the following disclaimer. 9 * 2. Redistributions in binary form must reproduce the above copyright 10 * notice, this list of conditions and the following disclaimer in the 11 * documentation and/or other materials provided with the distribution. 12 * 13 * THIS SOFTWARE IS PROVIDED BY AUTHOR AND CONTRIBUTORS `AS IS' AND 14 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 15 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 16 * ARE DISCLAIMED. IN NO EVENT SHALL AUTHOR OR CONTRIBUTORS BE LIABLE 17 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 18 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 19 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 20 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 21 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 22 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 23 * SUCH DAMAGE. 24 * 25 * $FreeBSD: stable/11/sys/dev/mlx5/mlx5_core/mlx5_port.c 331583 2018-03-26 20:50:28Z hselasky $ 26 */ 27 28#include <linux/module.h> 29#include <dev/mlx5/port.h> 30#include "mlx5_core.h" 31 32int mlx5_core_access_reg(struct mlx5_core_dev *dev, void *data_in, 33 int size_in, void *data_out, int size_out, 34 u16 reg_num, int arg, int write) 35{ 36 struct mlx5_access_reg_mbox_in *in = NULL; 37 struct mlx5_access_reg_mbox_out *out = NULL; 38 int err = -ENOMEM; 39 40 in = mlx5_vzalloc(sizeof(*in) + size_in); 41 if (!in) 42 return -ENOMEM; 43 44 out = mlx5_vzalloc(sizeof(*out) + size_out); 45 if (!out) 46 goto ex1; 47 48 memcpy(in->data, data_in, size_in); 49 in->hdr.opcode = cpu_to_be16(MLX5_CMD_OP_ACCESS_REG); 50 in->hdr.opmod = cpu_to_be16(!write); 51 in->arg = cpu_to_be32(arg); 52 in->register_id = cpu_to_be16(reg_num); 53 err = mlx5_cmd_exec(dev, in, sizeof(*in) + size_in, out, 54 sizeof(*out) + size_out); 55 if (err) 56 goto ex2; 57 58 if (out->hdr.status) 59 err = mlx5_cmd_status_to_err(&out->hdr); 60 61 if (!err) 62 memcpy(data_out, out->data, size_out); 63 64ex2: 65 kvfree(out); 66ex1: 67 kvfree(in); 68 return err; 69} 70EXPORT_SYMBOL_GPL(mlx5_core_access_reg); 71 72 73struct mlx5_reg_pcap { 74 u8 rsvd0; 75 u8 port_num; 76 u8 rsvd1[2]; 77 __be32 caps_127_96; 78 __be32 caps_95_64; 79 __be32 caps_63_32; 80 __be32 caps_31_0; 81}; 82 83/* This function should be used after setting a port register only */ 84void mlx5_toggle_port_link(struct mlx5_core_dev *dev) 85{ 86 enum mlx5_port_status ps; 87 88 mlx5_query_port_admin_status(dev, &ps); 89 mlx5_set_port_status(dev, MLX5_PORT_DOWN); 90 if (ps == MLX5_PORT_UP) 91 mlx5_set_port_status(dev, MLX5_PORT_UP); 92} 93EXPORT_SYMBOL_GPL(mlx5_toggle_port_link); 94 95int mlx5_set_port_caps(struct mlx5_core_dev *dev, u8 port_num, u32 caps) 96{ 97 struct mlx5_reg_pcap in; 98 struct mlx5_reg_pcap out; 99 int err; 100 101 memset(&in, 0, sizeof(in)); 102 in.caps_127_96 = cpu_to_be32(caps); 103 in.port_num = port_num; 104 105 err = mlx5_core_access_reg(dev, &in, sizeof(in), &out, 106 sizeof(out), MLX5_REG_PCAP, 0, 1); 107 108 return err; 109} 110EXPORT_SYMBOL_GPL(mlx5_set_port_caps); 111 112int mlx5_query_port_ptys(struct mlx5_core_dev *dev, u32 *ptys, 113 int ptys_size, int proto_mask, u8 local_port) 114{ 115 u32 in[MLX5_ST_SZ_DW(ptys_reg)]; 116 int err; 117 118 memset(in, 0, sizeof(in)); 119 MLX5_SET(ptys_reg, in, local_port, local_port); 120 MLX5_SET(ptys_reg, in, proto_mask, proto_mask); 121 122 err = mlx5_core_access_reg(dev, in, sizeof(in), ptys, 123 ptys_size, MLX5_REG_PTYS, 0, 0); 124 125 return err; 126} 127EXPORT_SYMBOL_GPL(mlx5_query_port_ptys); 128 129int mlx5_query_port_proto_cap(struct mlx5_core_dev *dev, 130 u32 *proto_cap, int proto_mask) 131{ 132 u32 out[MLX5_ST_SZ_DW(ptys_reg)]; 133 int err; 134 135 err = mlx5_query_port_ptys(dev, out, sizeof(out), proto_mask, 1); 136 if (err) 137 return err; 138 139 if (proto_mask == MLX5_PTYS_EN) 140 *proto_cap = MLX5_GET(ptys_reg, out, eth_proto_capability); 141 else 142 *proto_cap = MLX5_GET(ptys_reg, out, ib_proto_capability); 143 144 return 0; 145} 146EXPORT_SYMBOL_GPL(mlx5_query_port_proto_cap); 147 148int mlx5_query_port_autoneg(struct mlx5_core_dev *dev, int proto_mask, 149 u8 *an_disable_cap, u8 *an_disable_status) 150{ 151 u32 out[MLX5_ST_SZ_DW(ptys_reg)]; 152 int err; 153 154 err = mlx5_query_port_ptys(dev, out, sizeof(out), proto_mask, 1); 155 if (err) 156 return err; 157 158 *an_disable_status = MLX5_GET(ptys_reg, out, an_disable_admin); 159 *an_disable_cap = MLX5_GET(ptys_reg, out, an_disable_cap); 160 161 return 0; 162} 163EXPORT_SYMBOL_GPL(mlx5_query_port_autoneg); 164 165int mlx5_set_port_autoneg(struct mlx5_core_dev *dev, bool disable, 166 u32 eth_proto_admin, int proto_mask) 167{ 168 u32 in[MLX5_ST_SZ_DW(ptys_reg)]; 169 u32 out[MLX5_ST_SZ_DW(ptys_reg)]; 170 u8 an_disable_cap; 171 u8 an_disable_status; 172 int err; 173 174 err = mlx5_query_port_autoneg(dev, proto_mask, &an_disable_cap, 175 &an_disable_status); 176 if (err) 177 return err; 178 if (!an_disable_cap) 179 return -EPERM; 180 181 memset(in, 0, sizeof(in)); 182 183 MLX5_SET(ptys_reg, in, local_port, 1); 184 MLX5_SET(ptys_reg, in, an_disable_admin, disable); 185 MLX5_SET(ptys_reg, in, proto_mask, proto_mask); 186 if (proto_mask == MLX5_PTYS_EN) 187 MLX5_SET(ptys_reg, in, eth_proto_admin, eth_proto_admin); 188 189 err = mlx5_core_access_reg(dev, in, sizeof(in), out, 190 sizeof(out), MLX5_REG_PTYS, 0, 1); 191 return err; 192} 193EXPORT_SYMBOL_GPL(mlx5_set_port_autoneg); 194 195int mlx5_query_port_proto_admin(struct mlx5_core_dev *dev, 196 u32 *proto_admin, int proto_mask) 197{ 198 u32 out[MLX5_ST_SZ_DW(ptys_reg)]; 199 int err; 200 201 err = mlx5_query_port_ptys(dev, out, sizeof(out), proto_mask, 1); 202 if (err) 203 return err; 204 205 if (proto_mask == MLX5_PTYS_EN) 206 *proto_admin = MLX5_GET(ptys_reg, out, eth_proto_admin); 207 else 208 *proto_admin = MLX5_GET(ptys_reg, out, ib_proto_admin); 209 210 return 0; 211} 212EXPORT_SYMBOL_GPL(mlx5_query_port_proto_admin); 213 214int mlx5_query_port_eth_proto_oper(struct mlx5_core_dev *dev, 215 u32 *proto_oper, u8 local_port) 216{ 217 u32 out[MLX5_ST_SZ_DW(ptys_reg)]; 218 int err; 219 220 err = mlx5_query_port_ptys(dev, out, sizeof(out), MLX5_PTYS_EN, 221 local_port); 222 if (err) 223 return err; 224 225 *proto_oper = MLX5_GET(ptys_reg, out, eth_proto_oper); 226 227 return 0; 228} 229EXPORT_SYMBOL(mlx5_query_port_eth_proto_oper); 230 231int mlx5_set_port_proto(struct mlx5_core_dev *dev, u32 proto_admin, 232 int proto_mask) 233{ 234 u32 in[MLX5_ST_SZ_DW(ptys_reg)]; 235 u32 out[MLX5_ST_SZ_DW(ptys_reg)]; 236 int err; 237 238 memset(in, 0, sizeof(in)); 239 240 MLX5_SET(ptys_reg, in, local_port, 1); 241 MLX5_SET(ptys_reg, in, proto_mask, proto_mask); 242 if (proto_mask == MLX5_PTYS_EN) 243 MLX5_SET(ptys_reg, in, eth_proto_admin, proto_admin); 244 else 245 MLX5_SET(ptys_reg, in, ib_proto_admin, proto_admin); 246 247 err = mlx5_core_access_reg(dev, in, sizeof(in), out, 248 sizeof(out), MLX5_REG_PTYS, 0, 1); 249 return err; 250} 251EXPORT_SYMBOL_GPL(mlx5_set_port_proto); 252 253int mlx5_set_port_status(struct mlx5_core_dev *dev, 254 enum mlx5_port_status status) 255{ 256 u32 in[MLX5_ST_SZ_DW(paos_reg)]; 257 u32 out[MLX5_ST_SZ_DW(paos_reg)]; 258 int err; 259 260 memset(in, 0, sizeof(in)); 261 262 MLX5_SET(paos_reg, in, local_port, 1); 263 264 MLX5_SET(paos_reg, in, admin_status, status); 265 MLX5_SET(paos_reg, in, ase, 1); 266 267 err = mlx5_core_access_reg(dev, in, sizeof(in), out, 268 sizeof(out), MLX5_REG_PAOS, 0, 1); 269 return err; 270} 271 272int mlx5_query_port_status(struct mlx5_core_dev *dev, u8 *status) 273{ 274 u32 in[MLX5_ST_SZ_DW(paos_reg)]; 275 u32 out[MLX5_ST_SZ_DW(paos_reg)]; 276 int err; 277 278 memset(in, 0, sizeof(in)); 279 280 MLX5_SET(paos_reg, in, local_port, 1); 281 282 err = mlx5_core_access_reg(dev, in, sizeof(in), out, 283 sizeof(out), MLX5_REG_PAOS, 0, 0); 284 if (err) 285 return err; 286 287 *status = MLX5_GET(paos_reg, out, oper_status); 288 return err; 289} 290 291int mlx5_query_port_admin_status(struct mlx5_core_dev *dev, 292 enum mlx5_port_status *status) 293{ 294 u32 in[MLX5_ST_SZ_DW(paos_reg)] = {0}; 295 u32 out[MLX5_ST_SZ_DW(paos_reg)]; 296 int err; 297 298 MLX5_SET(paos_reg, in, local_port, 1); 299 err = mlx5_core_access_reg(dev, in, sizeof(in), out, 300 sizeof(out), MLX5_REG_PAOS, 0, 0); 301 if (err) 302 return err; 303 *status = MLX5_GET(paos_reg, out, admin_status); 304 return 0; 305} 306EXPORT_SYMBOL_GPL(mlx5_query_port_admin_status); 307 308static int mlx5_query_port_mtu(struct mlx5_core_dev *dev, 309 int *admin_mtu, int *max_mtu, int *oper_mtu) 310{ 311 u32 in[MLX5_ST_SZ_DW(pmtu_reg)]; 312 u32 out[MLX5_ST_SZ_DW(pmtu_reg)]; 313 int err; 314 315 memset(in, 0, sizeof(in)); 316 317 MLX5_SET(pmtu_reg, in, local_port, 1); 318 319 err = mlx5_core_access_reg(dev, in, sizeof(in), out, 320 sizeof(out), MLX5_REG_PMTU, 0, 0); 321 if (err) 322 return err; 323 324 if (max_mtu) 325 *max_mtu = MLX5_GET(pmtu_reg, out, max_mtu); 326 if (oper_mtu) 327 *oper_mtu = MLX5_GET(pmtu_reg, out, oper_mtu); 328 if (admin_mtu) 329 *admin_mtu = MLX5_GET(pmtu_reg, out, admin_mtu); 330 331 return err; 332} 333 334int mlx5_set_port_mtu(struct mlx5_core_dev *dev, int mtu) 335{ 336 u32 in[MLX5_ST_SZ_DW(pmtu_reg)]; 337 u32 out[MLX5_ST_SZ_DW(pmtu_reg)]; 338 339 memset(in, 0, sizeof(in)); 340 341 MLX5_SET(pmtu_reg, in, admin_mtu, mtu); 342 MLX5_SET(pmtu_reg, in, local_port, 1); 343 344 return mlx5_core_access_reg(dev, in, sizeof(in), out, 345 sizeof(out), MLX5_REG_PMTU, 0, 1); 346} 347EXPORT_SYMBOL_GPL(mlx5_set_port_mtu); 348 349int mlx5_query_port_max_mtu(struct mlx5_core_dev *dev, int *max_mtu) 350{ 351 return mlx5_query_port_mtu(dev, NULL, max_mtu, NULL); 352} 353EXPORT_SYMBOL_GPL(mlx5_query_port_max_mtu); 354 355int mlx5_set_port_pause_and_pfc(struct mlx5_core_dev *dev, u32 port, 356 u8 rx_pause, u8 tx_pause, 357 u8 pfc_en_rx, u8 pfc_en_tx) 358{ 359 u32 in[MLX5_ST_SZ_DW(pfcc_reg)] = {0}; 360 u32 out[MLX5_ST_SZ_DW(pfcc_reg)] = {0}; 361 362 if (pfc_en_rx || pfc_en_tx) { 363 /* PFC and global pauseframes are incompatible features */ 364 if (tx_pause || rx_pause) 365 return -EINVAL; 366 } 367 368 MLX5_SET(pfcc_reg, in, local_port, port); 369 MLX5_SET(pfcc_reg, in, pptx, tx_pause); 370 MLX5_SET(pfcc_reg, in, pprx, rx_pause); 371 MLX5_SET(pfcc_reg, in, pfctx, pfc_en_tx); 372 MLX5_SET(pfcc_reg, in, pfcrx, pfc_en_rx); 373 MLX5_SET(pfcc_reg, in, prio_mask_tx, pfc_en_tx); 374 MLX5_SET(pfcc_reg, in, prio_mask_rx, pfc_en_rx); 375 376 return mlx5_core_access_reg(dev, in, sizeof(in), out, 377 sizeof(out), MLX5_REG_PFCC, 0, 1); 378} 379 380int mlx5_query_port_pause(struct mlx5_core_dev *dev, u32 port, 381 u32 *rx_pause, u32 *tx_pause) 382{ 383 u32 in[MLX5_ST_SZ_DW(pfcc_reg)]; 384 u32 out[MLX5_ST_SZ_DW(pfcc_reg)]; 385 int err; 386 387 memset(in, 0, sizeof(in)); 388 memset(out, 0, sizeof(out)); 389 390 MLX5_SET(pfcc_reg, in, local_port, port); 391 392 err = mlx5_core_access_reg(dev, in, sizeof(in), out, 393 sizeof(out), MLX5_REG_PFCC, 0, 0); 394 if (err) 395 return err; 396 397 *rx_pause = MLX5_GET(pfcc_reg, out, pprx); 398 *tx_pause = MLX5_GET(pfcc_reg, out, pptx); 399 400 return 0; 401} 402 403int mlx5_query_port_pfc(struct mlx5_core_dev *dev, u8 *pfc_en_tx, u8 *pfc_en_rx) 404{ 405 u32 in[MLX5_ST_SZ_DW(pfcc_reg)] = {}; 406 u32 out[MLX5_ST_SZ_DW(pfcc_reg)]; 407 int err; 408 409 MLX5_SET(pfcc_reg, in, local_port, 1); 410 err = mlx5_core_access_reg(dev, in, sizeof(in), out, 411 sizeof(out), MLX5_REG_PFCC, 0, 0); 412 if (err) 413 return err; 414 415 if (pfc_en_tx != NULL) 416 *pfc_en_tx = MLX5_GET(pfcc_reg, out, pfctx); 417 if (pfc_en_rx != NULL) 418 *pfc_en_rx = MLX5_GET(pfcc_reg, out, pfcrx); 419 return 0; 420} 421EXPORT_SYMBOL_GPL(mlx5_query_port_pfc); 422 423int mlx5_query_port_oper_mtu(struct mlx5_core_dev *dev, int *oper_mtu) 424{ 425 return mlx5_query_port_mtu(dev, NULL, NULL, oper_mtu); 426} 427EXPORT_SYMBOL_GPL(mlx5_query_port_oper_mtu); 428 429u8 mlx5_is_wol_supported(struct mlx5_core_dev *dev) 430{ 431 u8 wol_supported = 0; 432 433 if (MLX5_CAP_GEN(dev, wol_s)) 434 wol_supported |= MLX5_WOL_SECURED_MAGIC; 435 if (MLX5_CAP_GEN(dev, wol_g)) 436 wol_supported |= MLX5_WOL_MAGIC; 437 if (MLX5_CAP_GEN(dev, wol_a)) 438 wol_supported |= MLX5_WOL_ARP; 439 if (MLX5_CAP_GEN(dev, wol_b)) 440 wol_supported |= MLX5_WOL_BROADCAST; 441 if (MLX5_CAP_GEN(dev, wol_m)) 442 wol_supported |= MLX5_WOL_MULTICAST; 443 if (MLX5_CAP_GEN(dev, wol_u)) 444 wol_supported |= MLX5_WOL_UNICAST; 445 if (MLX5_CAP_GEN(dev, wol_p)) 446 wol_supported |= MLX5_WOL_PHY_ACTIVITY; 447 448 return wol_supported; 449} 450EXPORT_SYMBOL_GPL(mlx5_is_wol_supported); 451 452int mlx5_set_wol(struct mlx5_core_dev *dev, u8 wol_mode) 453{ 454 u32 in[MLX5_ST_SZ_DW(set_wol_rol_in)]; 455 u32 out[MLX5_ST_SZ_DW(set_wol_rol_out)]; 456 457 memset(in, 0, sizeof(in)); 458 memset(out, 0, sizeof(out)); 459 460 MLX5_SET(set_wol_rol_in, in, opcode, MLX5_CMD_OP_SET_WOL_ROL); 461 MLX5_SET(set_wol_rol_in, in, wol_mode_valid, 1); 462 MLX5_SET(set_wol_rol_in, in, wol_mode, wol_mode); 463 464 return mlx5_cmd_exec_check_status(dev, in, sizeof(in), 465 out, sizeof(out)); 466} 467EXPORT_SYMBOL_GPL(mlx5_set_wol); 468 469int mlx5_query_dropless_mode(struct mlx5_core_dev *dev, u16 *timeout) 470{ 471 u32 in[MLX5_ST_SZ_DW(query_delay_drop_params_in)]; 472 u32 out[MLX5_ST_SZ_DW(query_delay_drop_params_out)]; 473 int err = 0; 474 475 memset(in, 0, sizeof(in)); 476 memset(out, 0, sizeof(out)); 477 478 MLX5_SET(query_delay_drop_params_in, in, opcode, 479 MLX5_CMD_OP_QUERY_DELAY_DROP_PARAMS); 480 481 err = mlx5_cmd_exec_check_status(dev, in, sizeof(in), out, sizeof(out)); 482 if (err) 483 return err; 484 485 *timeout = MLX5_GET(query_delay_drop_params_out, out, 486 delay_drop_timeout); 487 488 return 0; 489} 490EXPORT_SYMBOL_GPL(mlx5_query_dropless_mode); 491 492int mlx5_set_dropless_mode(struct mlx5_core_dev *dev, u16 timeout) 493{ 494 u32 in[MLX5_ST_SZ_DW(set_delay_drop_params_in)]; 495 u32 out[MLX5_ST_SZ_DW(set_delay_drop_params_out)]; 496 497 memset(in, 0, sizeof(in)); 498 memset(out, 0, sizeof(out)); 499 500 MLX5_SET(set_delay_drop_params_in, in, opcode, 501 MLX5_CMD_OP_SET_DELAY_DROP_PARAMS); 502 MLX5_SET(set_delay_drop_params_in, in, delay_drop_timeout, timeout); 503 504 return mlx5_cmd_exec_check_status(dev, in, sizeof(in), 505 out, sizeof(out)); 506} 507EXPORT_SYMBOL_GPL(mlx5_set_dropless_mode); 508 509int mlx5_core_access_pvlc(struct mlx5_core_dev *dev, 510 struct mlx5_pvlc_reg *pvlc, int write) 511{ 512 int sz = MLX5_ST_SZ_BYTES(pvlc_reg); 513 u8 in[MLX5_ST_SZ_BYTES(pvlc_reg)]; 514 u8 out[MLX5_ST_SZ_BYTES(pvlc_reg)]; 515 int err; 516 517 memset(out, 0, sizeof(out)); 518 memset(in, 0, sizeof(in)); 519 520 MLX5_SET(pvlc_reg, in, local_port, pvlc->local_port); 521 if (write) 522 MLX5_SET(pvlc_reg, in, vl_admin, pvlc->vl_admin); 523 524 err = mlx5_core_access_reg(dev, in, sz, out, sz, MLX5_REG_PVLC, 0, 525 !!write); 526 if (err) 527 return err; 528 529 if (!write) { 530 pvlc->local_port = MLX5_GET(pvlc_reg, out, local_port); 531 pvlc->vl_hw_cap = MLX5_GET(pvlc_reg, out, vl_hw_cap); 532 pvlc->vl_admin = MLX5_GET(pvlc_reg, out, vl_admin); 533 pvlc->vl_operational = MLX5_GET(pvlc_reg, out, vl_operational); 534 } 535 536 return 0; 537} 538EXPORT_SYMBOL_GPL(mlx5_core_access_pvlc); 539 540int mlx5_core_access_ptys(struct mlx5_core_dev *dev, 541 struct mlx5_ptys_reg *ptys, int write) 542{ 543 int sz = MLX5_ST_SZ_BYTES(ptys_reg); 544 void *out = NULL; 545 void *in = NULL; 546 int err; 547 548 in = mlx5_vzalloc(sz); 549 if (!in) 550 return -ENOMEM; 551 552 out = mlx5_vzalloc(sz); 553 if (!out) { 554 kfree(in); 555 return -ENOMEM; 556 } 557 558 MLX5_SET(ptys_reg, in, local_port, ptys->local_port); 559 MLX5_SET(ptys_reg, in, proto_mask, ptys->proto_mask); 560 if (write) { 561 MLX5_SET(ptys_reg, in, eth_proto_capability, 562 ptys->eth_proto_cap); 563 MLX5_SET(ptys_reg, in, ib_link_width_capability, 564 ptys->ib_link_width_cap); 565 MLX5_SET(ptys_reg, in, ib_proto_capability, 566 ptys->ib_proto_cap); 567 MLX5_SET(ptys_reg, in, eth_proto_admin, ptys->eth_proto_admin); 568 MLX5_SET(ptys_reg, in, ib_link_width_admin, 569 ptys->ib_link_width_admin); 570 MLX5_SET(ptys_reg, in, ib_proto_admin, ptys->ib_proto_admin); 571 MLX5_SET(ptys_reg, in, eth_proto_oper, ptys->eth_proto_oper); 572 MLX5_SET(ptys_reg, in, ib_link_width_oper, 573 ptys->ib_link_width_oper); 574 MLX5_SET(ptys_reg, in, ib_proto_oper, ptys->ib_proto_oper); 575 MLX5_SET(ptys_reg, in, eth_proto_lp_advertise, 576 ptys->eth_proto_lp_advertise); 577 } 578 579 err = mlx5_core_access_reg(dev, in, sz, out, sz, MLX5_REG_PTYS, 0, 580 !!write); 581 if (err) 582 goto out; 583 584 if (!write) { 585 ptys->local_port = MLX5_GET(ptys_reg, out, local_port); 586 ptys->proto_mask = MLX5_GET(ptys_reg, out, proto_mask); 587 ptys->eth_proto_cap = MLX5_GET(ptys_reg, out, 588 eth_proto_capability); 589 ptys->ib_link_width_cap = MLX5_GET(ptys_reg, out, 590 ib_link_width_capability); 591 ptys->ib_proto_cap = MLX5_GET(ptys_reg, out, 592 ib_proto_capability); 593 ptys->eth_proto_admin = MLX5_GET(ptys_reg, out, 594 eth_proto_admin); 595 ptys->ib_link_width_admin = MLX5_GET(ptys_reg, out, 596 ib_link_width_admin); 597 ptys->ib_proto_admin = MLX5_GET(ptys_reg, out, ib_proto_admin); 598 ptys->eth_proto_oper = MLX5_GET(ptys_reg, out, eth_proto_oper); 599 ptys->ib_link_width_oper = MLX5_GET(ptys_reg, out, 600 ib_link_width_oper); 601 ptys->ib_proto_oper = MLX5_GET(ptys_reg, out, ib_proto_oper); 602 ptys->eth_proto_lp_advertise = MLX5_GET(ptys_reg, out, 603 eth_proto_lp_advertise); 604 } 605 606out: 607 kvfree(in); 608 kvfree(out); 609 return err; 610} 611EXPORT_SYMBOL_GPL(mlx5_core_access_ptys); 612 613static int mtu_to_ib_mtu(int mtu) 614{ 615 switch (mtu) { 616 case 256: return 1; 617 case 512: return 2; 618 case 1024: return 3; 619 case 2048: return 4; 620 case 4096: return 5; 621 default: 622 printf("mlx5_core: WARN: ""invalid mtu\n"); 623 return -1; 624 } 625} 626 627int mlx5_core_access_pmtu(struct mlx5_core_dev *dev, 628 struct mlx5_pmtu_reg *pmtu, int write) 629{ 630 int sz = MLX5_ST_SZ_BYTES(pmtu_reg); 631 void *out = NULL; 632 void *in = NULL; 633 int err; 634 635 in = mlx5_vzalloc(sz); 636 if (!in) 637 return -ENOMEM; 638 639 out = mlx5_vzalloc(sz); 640 if (!out) { 641 kfree(in); 642 return -ENOMEM; 643 } 644 645 MLX5_SET(pmtu_reg, in, local_port, pmtu->local_port); 646 if (write) 647 MLX5_SET(pmtu_reg, in, admin_mtu, pmtu->admin_mtu); 648 649 err = mlx5_core_access_reg(dev, in, sz, out, sz, MLX5_REG_PMTU, 0, 650 !!write); 651 if (err) 652 goto out; 653 654 if (!write) { 655 pmtu->local_port = MLX5_GET(pmtu_reg, out, local_port); 656 pmtu->max_mtu = mtu_to_ib_mtu(MLX5_GET(pmtu_reg, out, 657 max_mtu)); 658 pmtu->admin_mtu = mtu_to_ib_mtu(MLX5_GET(pmtu_reg, out, 659 admin_mtu)); 660 pmtu->oper_mtu = mtu_to_ib_mtu(MLX5_GET(pmtu_reg, out, 661 oper_mtu)); 662 } 663 664out: 665 kvfree(in); 666 kvfree(out); 667 return err; 668} 669EXPORT_SYMBOL_GPL(mlx5_core_access_pmtu); 670 671int mlx5_query_module_num(struct mlx5_core_dev *dev, int *module_num) 672{ 673 u32 in[MLX5_ST_SZ_DW(pmlp_reg)]; 674 u32 out[MLX5_ST_SZ_DW(pmlp_reg)]; 675 int lane = 0; 676 int err; 677 678 memset(in, 0, sizeof(in)); 679 680 MLX5_SET(pmlp_reg, in, local_port, 1); 681 682 err = mlx5_core_access_reg(dev, in, sizeof(in), out, 683 sizeof(out), MLX5_REG_PMLP, 0, 0); 684 if (err) 685 return err; 686 687 lane = MLX5_GET(pmlp_reg, out, lane0_module_mapping); 688 *module_num = lane & MLX5_EEPROM_IDENTIFIER_BYTE_MASK; 689 690 return 0; 691} 692EXPORT_SYMBOL_GPL(mlx5_query_module_num); 693 694int mlx5_query_eeprom(struct mlx5_core_dev *dev, 695 int i2c_addr, int page_num, int device_addr, 696 int size, int module_num, u32 *data, int *size_read) 697{ 698 u32 in[MLX5_ST_SZ_DW(mcia_reg)]; 699 u32 out[MLX5_ST_SZ_DW(mcia_reg)]; 700 u32 *ptr = (u32 *)MLX5_ADDR_OF(mcia_reg, out, dword_0); 701 int status; 702 int err; 703 704 memset(in, 0, sizeof(in)); 705 size = min_t(int, size, MLX5_EEPROM_MAX_BYTES); 706 707 MLX5_SET(mcia_reg, in, l, 0); 708 MLX5_SET(mcia_reg, in, module, module_num); 709 MLX5_SET(mcia_reg, in, i2c_device_address, i2c_addr); 710 MLX5_SET(mcia_reg, in, page_number, page_num); 711 MLX5_SET(mcia_reg, in, device_address, device_addr); 712 MLX5_SET(mcia_reg, in, size, size); 713 714 err = mlx5_core_access_reg(dev, in, sizeof(in), out, 715 sizeof(out), MLX5_REG_MCIA, 0, 0); 716 if (err) 717 return err; 718 719 status = MLX5_GET(mcia_reg, out, status); 720 if (status) 721 return status; 722 723 memcpy(data, ptr, size); 724 *size_read = size; 725 return 0; 726} 727EXPORT_SYMBOL_GPL(mlx5_query_eeprom); 728 729int mlx5_vxlan_udp_port_add(struct mlx5_core_dev *dev, u16 port) 730{ 731 u32 in[MLX5_ST_SZ_DW(add_vxlan_udp_dport_in)]; 732 u32 out[MLX5_ST_SZ_DW(add_vxlan_udp_dport_out)]; 733 int err; 734 735 memset(in, 0, sizeof(in)); 736 memset(out, 0, sizeof(out)); 737 738 MLX5_SET(add_vxlan_udp_dport_in, in, opcode, 739 MLX5_CMD_OP_ADD_VXLAN_UDP_DPORT); 740 MLX5_SET(add_vxlan_udp_dport_in, in, vxlan_udp_port, port); 741 742 err = mlx5_cmd_exec_check_status(dev, in, sizeof(in), out, sizeof(out)); 743 if (err) { 744 mlx5_core_err(dev, "Failed %s, port %u, err - %d", 745 mlx5_command_str(MLX5_CMD_OP_ADD_VXLAN_UDP_DPORT), 746 port, err); 747 } 748 749 return err; 750} 751 752int mlx5_vxlan_udp_port_delete(struct mlx5_core_dev *dev, u16 port) 753{ 754 u32 in[MLX5_ST_SZ_DW(delete_vxlan_udp_dport_in)]; 755 u32 out[MLX5_ST_SZ_DW(delete_vxlan_udp_dport_out)]; 756 int err; 757 758 memset(in, 0, sizeof(in)); 759 memset(out, 0, sizeof(out)); 760 761 MLX5_SET(delete_vxlan_udp_dport_in, in, opcode, 762 MLX5_CMD_OP_DELETE_VXLAN_UDP_DPORT); 763 MLX5_SET(delete_vxlan_udp_dport_in, in, vxlan_udp_port, port); 764 765 err = mlx5_cmd_exec_check_status(dev, in, sizeof(in), out, sizeof(out)); 766 if (err) { 767 mlx5_core_err(dev, "Failed %s, port %u, err - %d", 768 mlx5_command_str(MLX5_CMD_OP_DELETE_VXLAN_UDP_DPORT), 769 port, err); 770 } 771 772 return err; 773} 774 775int mlx5_query_wol(struct mlx5_core_dev *dev, u8 *wol_mode) 776{ 777 u32 in[MLX5_ST_SZ_DW(query_wol_rol_in)]; 778 u32 out[MLX5_ST_SZ_DW(query_wol_rol_out)]; 779 int err; 780 781 memset(in, 0, sizeof(in)); 782 memset(out, 0, sizeof(out)); 783 784 MLX5_SET(query_wol_rol_in, in, opcode, MLX5_CMD_OP_QUERY_WOL_ROL); 785 786 err = mlx5_cmd_exec_check_status(dev, in, sizeof(in), out, sizeof(out)); 787 788 if (!err) 789 *wol_mode = MLX5_GET(query_wol_rol_out, out, wol_mode); 790 791 return err; 792} 793EXPORT_SYMBOL_GPL(mlx5_query_wol); 794 795int mlx5_query_port_cong_status(struct mlx5_core_dev *mdev, int protocol, 796 int priority, int *is_enable) 797{ 798 u32 in[MLX5_ST_SZ_DW(query_cong_status_in)]; 799 u32 out[MLX5_ST_SZ_DW(query_cong_status_out)]; 800 int err; 801 802 memset(in, 0, sizeof(in)); 803 memset(out, 0, sizeof(out)); 804 805 *is_enable = 0; 806 807 MLX5_SET(query_cong_status_in, in, opcode, 808 MLX5_CMD_OP_QUERY_CONG_STATUS); 809 MLX5_SET(query_cong_status_in, in, cong_protocol, protocol); 810 MLX5_SET(query_cong_status_in, in, priority, priority); 811 812 err = mlx5_cmd_exec_check_status(mdev, in, sizeof(in), 813 out, sizeof(out)); 814 if (!err) 815 *is_enable = MLX5_GET(query_cong_status_out, out, enable); 816 return err; 817} 818 819int mlx5_modify_port_cong_status(struct mlx5_core_dev *mdev, int protocol, 820 int priority, int enable) 821{ 822 u32 in[MLX5_ST_SZ_DW(modify_cong_status_in)]; 823 u32 out[MLX5_ST_SZ_DW(modify_cong_status_out)]; 824 825 memset(in, 0, sizeof(in)); 826 memset(out, 0, sizeof(out)); 827 828 MLX5_SET(modify_cong_status_in, in, opcode, 829 MLX5_CMD_OP_MODIFY_CONG_STATUS); 830 MLX5_SET(modify_cong_status_in, in, cong_protocol, protocol); 831 MLX5_SET(modify_cong_status_in, in, priority, priority); 832 MLX5_SET(modify_cong_status_in, in, enable, enable); 833 834 return mlx5_cmd_exec_check_status(mdev, in, sizeof(in), 835 out, sizeof(out)); 836} 837 838int mlx5_query_port_cong_params(struct mlx5_core_dev *mdev, int protocol, 839 void *out, int out_size) 840{ 841 u32 in[MLX5_ST_SZ_DW(query_cong_params_in)]; 842 843 memset(in, 0, sizeof(in)); 844 845 MLX5_SET(query_cong_params_in, in, opcode, 846 MLX5_CMD_OP_QUERY_CONG_PARAMS); 847 MLX5_SET(query_cong_params_in, in, cong_protocol, protocol); 848 849 return mlx5_cmd_exec_check_status(mdev, in, sizeof(in), 850 out, out_size); 851} 852 853static int mlx5_query_port_qetcr_reg(struct mlx5_core_dev *mdev, u32 *out, 854 int outlen) 855{ 856 u32 in[MLX5_ST_SZ_DW(qtct_reg)]; 857 858 if (!MLX5_CAP_GEN(mdev, ets)) 859 return -ENOTSUPP; 860 861 memset(in, 0, sizeof(in)); 862 return mlx5_core_access_reg(mdev, in, sizeof(in), out, outlen, 863 MLX5_REG_QETCR, 0, 0); 864} 865 866int mlx5_max_tc(struct mlx5_core_dev *mdev) 867{ 868 u8 num_tc = MLX5_CAP_GEN(mdev, max_tc) ? : 8; 869 870 return num_tc - 1; 871} 872EXPORT_SYMBOL_GPL(mlx5_max_tc); 873 874static int mlx5_set_port_qetcr_reg(struct mlx5_core_dev *mdev, u32 *in, 875 int inlen) 876{ 877 u32 out[MLX5_ST_SZ_DW(qtct_reg)]; 878 879 if (!MLX5_CAP_GEN(mdev, ets)) 880 return -ENOTSUPP; 881 882 return mlx5_core_access_reg(mdev, in, inlen, out, sizeof(out), 883 MLX5_REG_QETCR, 0, 1); 884} 885 886int mlx5_query_port_tc_rate_limit(struct mlx5_core_dev *mdev, 887 u8 *max_bw_value, 888 u8 *max_bw_units) 889{ 890 u32 out[MLX5_ST_SZ_DW(qetc_reg)]; 891 void *ets_tcn_conf; 892 int err; 893 int i; 894 895 err = mlx5_query_port_qetcr_reg(mdev, out, sizeof(out)); 896 if (err) 897 return err; 898 899 for (i = 0; i <= mlx5_max_tc(mdev); i++) { 900 ets_tcn_conf = MLX5_ADDR_OF(qetc_reg, out, tc_configuration[i]); 901 902 max_bw_value[i] = MLX5_GET(ets_tcn_config_reg, ets_tcn_conf, 903 max_bw_value); 904 max_bw_units[i] = MLX5_GET(ets_tcn_config_reg, ets_tcn_conf, 905 max_bw_units); 906 } 907 908 return 0; 909} 910EXPORT_SYMBOL_GPL(mlx5_query_port_tc_rate_limit); 911 912int mlx5_modify_port_tc_rate_limit(struct mlx5_core_dev *mdev, 913 const u8 *max_bw_value, 914 const u8 *max_bw_units) 915{ 916 u32 in[MLX5_ST_SZ_DW(qetc_reg)] = {}; 917 void *ets_tcn_conf; 918 int i; 919 920 MLX5_SET(qetc_reg, in, port_number, 1); 921 922 for (i = 0; i <= mlx5_max_tc(mdev); i++) { 923 ets_tcn_conf = MLX5_ADDR_OF(qetc_reg, in, tc_configuration[i]); 924 925 MLX5_SET(ets_tcn_config_reg, ets_tcn_conf, r, 1); 926 MLX5_SET(ets_tcn_config_reg, ets_tcn_conf, max_bw_units, 927 max_bw_units[i]); 928 MLX5_SET(ets_tcn_config_reg, ets_tcn_conf, max_bw_value, 929 max_bw_value[i]); 930 } 931 932 return mlx5_set_port_qetcr_reg(mdev, in, sizeof(in)); 933} 934EXPORT_SYMBOL_GPL(mlx5_modify_port_tc_rate_limit); 935 936int mlx5_query_port_prio_tc(struct mlx5_core_dev *mdev, 937 u8 prio, u8 *tc) 938{ 939 u32 in[MLX5_ST_SZ_DW(qtct_reg)]; 940 u32 out[MLX5_ST_SZ_DW(qtct_reg)]; 941 int err; 942 943 memset(in, 0, sizeof(in)); 944 memset(out, 0, sizeof(out)); 945 946 MLX5_SET(qtct_reg, in, port_number, 1); 947 MLX5_SET(qtct_reg, in, prio, prio); 948 949 err = mlx5_core_access_reg(mdev, in, sizeof(in), out, 950 sizeof(out), MLX5_REG_QTCT, 0, 0); 951 if (!err) 952 *tc = MLX5_GET(qtct_reg, out, tclass); 953 954 return err; 955} 956EXPORT_SYMBOL_GPL(mlx5_query_port_prio_tc); 957 958int mlx5_set_port_prio_tc(struct mlx5_core_dev *mdev, int prio_index, 959 const u8 prio_tc) 960{ 961 u32 in[MLX5_ST_SZ_DW(qtct_reg)] = {}; 962 u32 out[MLX5_ST_SZ_DW(qtct_reg)]; 963 int err; 964 965 if (prio_tc > mlx5_max_tc(mdev)) 966 return -EINVAL; 967 968 MLX5_SET(qtct_reg, in, prio, prio_index); 969 MLX5_SET(qtct_reg, in, tclass, prio_tc); 970 971 err = mlx5_core_access_reg(mdev, in, sizeof(in), out, 972 sizeof(out), MLX5_REG_QTCT, 0, 1); 973 974 return (err); 975} 976EXPORT_SYMBOL_GPL(mlx5_set_port_prio_tc); 977 978int mlx5_modify_port_cong_params(struct mlx5_core_dev *mdev, 979 void *in, int in_size) 980{ 981 u32 out[MLX5_ST_SZ_DW(modify_cong_params_out)]; 982 983 memset(out, 0, sizeof(out)); 984 985 MLX5_SET(modify_cong_params_in, in, opcode, 986 MLX5_CMD_OP_MODIFY_CONG_PARAMS); 987 988 return mlx5_cmd_exec_check_status(mdev, in, in_size, out, sizeof(out)); 989} 990 991int mlx5_query_port_cong_statistics(struct mlx5_core_dev *mdev, int clear, 992 void *out, int out_size) 993{ 994 u32 in[MLX5_ST_SZ_DW(query_cong_statistics_in)]; 995 996 memset(in, 0, sizeof(in)); 997 998 MLX5_SET(query_cong_statistics_in, in, opcode, 999 MLX5_CMD_OP_QUERY_CONG_STATISTICS); 1000 MLX5_SET(query_cong_statistics_in, in, clear, clear); 1001 1002 return mlx5_cmd_exec_check_status(mdev, in, sizeof(in), 1003 out, out_size); 1004} 1005 1006int mlx5_set_diagnostic_params(struct mlx5_core_dev *mdev, void *in, 1007 int in_size) 1008{ 1009 u32 out[MLX5_ST_SZ_DW(set_diagnostic_params_out)]; 1010 1011 memset(out, 0, sizeof(out)); 1012 1013 MLX5_SET(set_diagnostic_params_in, in, opcode, 1014 MLX5_CMD_OP_SET_DIAGNOSTICS); 1015 1016 return mlx5_cmd_exec_check_status(mdev, in, in_size, out, sizeof(out)); 1017} 1018 1019int mlx5_query_diagnostic_counters(struct mlx5_core_dev *mdev, 1020 u8 num_of_samples, u16 sample_index, 1021 void *out, int out_size) 1022{ 1023 u32 in[MLX5_ST_SZ_DW(query_diagnostic_counters_in)]; 1024 1025 memset(in, 0, sizeof(in)); 1026 1027 MLX5_SET(query_diagnostic_counters_in, in, opcode, 1028 MLX5_CMD_OP_QUERY_DIAGNOSTICS); 1029 MLX5_SET(query_diagnostic_counters_in, in, num_of_samples, 1030 num_of_samples); 1031 MLX5_SET(query_diagnostic_counters_in, in, sample_index, sample_index); 1032 1033 return mlx5_cmd_exec_check_status(mdev, in, sizeof(in), out, out_size); 1034} 1035