mlx5_port.c revision 331577
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 331577 2018-03-26 20:27:08Z 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(struct mlx5_core_dev *dev, u32 port, 356 u32 rx_pause, u32 tx_pause) 357{ 358 u32 in[MLX5_ST_SZ_DW(pfcc_reg)]; 359 u32 out[MLX5_ST_SZ_DW(pfcc_reg)]; 360 361 memset(in, 0, sizeof(in)); 362 memset(out, 0, sizeof(out)); 363 364 MLX5_SET(pfcc_reg, in, local_port, port); 365 MLX5_SET(pfcc_reg, in, pptx, tx_pause); 366 MLX5_SET(pfcc_reg, in, pprx, rx_pause); 367 368 return mlx5_core_access_reg(dev, in, sizeof(in), out, 369 sizeof(out), MLX5_REG_PFCC, 0, 1); 370} 371 372int mlx5_query_port_pause(struct mlx5_core_dev *dev, u32 port, 373 u32 *rx_pause, u32 *tx_pause) 374{ 375 u32 in[MLX5_ST_SZ_DW(pfcc_reg)]; 376 u32 out[MLX5_ST_SZ_DW(pfcc_reg)]; 377 int err; 378 379 memset(in, 0, sizeof(in)); 380 memset(out, 0, sizeof(out)); 381 382 MLX5_SET(pfcc_reg, in, local_port, port); 383 384 err = mlx5_core_access_reg(dev, in, sizeof(in), out, 385 sizeof(out), MLX5_REG_PFCC, 0, 0); 386 if (err) 387 return err; 388 389 *rx_pause = MLX5_GET(pfcc_reg, out, pprx); 390 *tx_pause = MLX5_GET(pfcc_reg, out, pptx); 391 392 return 0; 393} 394 395int mlx5_set_port_pfc(struct mlx5_core_dev *dev, u8 pfc_en_tx, u8 pfc_en_rx) 396{ 397 u32 in[MLX5_ST_SZ_DW(pfcc_reg)] = {0}; 398 u32 out[MLX5_ST_SZ_DW(pfcc_reg)]; 399 400 MLX5_SET(pfcc_reg, in, local_port, 1); 401 MLX5_SET(pfcc_reg, in, pfctx, pfc_en_tx); 402 MLX5_SET(pfcc_reg, in, pfcrx, pfc_en_rx); 403 MLX5_SET_TO_ONES(pfcc_reg, in, prio_mask_tx); 404 MLX5_SET_TO_ONES(pfcc_reg, in, prio_mask_rx); 405 406 return mlx5_core_access_reg(dev, in, sizeof(in), out, 407 sizeof(out), MLX5_REG_PFCC, 0, 1); 408} 409EXPORT_SYMBOL_GPL(mlx5_set_port_pfc); 410 411int mlx5_query_port_pfc(struct mlx5_core_dev *dev, u8 *pfc_en_tx, u8 *pfc_en_rx) 412{ 413 u32 in[MLX5_ST_SZ_DW(pfcc_reg)] = {0}; 414 u32 out[MLX5_ST_SZ_DW(pfcc_reg)]; 415 int err; 416 417 MLX5_SET(pfcc_reg, in, local_port, 1); 418 err = mlx5_core_access_reg(dev, in, sizeof(in), out, 419 sizeof(out), MLX5_REG_PFCC, 0, 0); 420 if (err) 421 return err; 422 423 if (pfc_en_tx) 424 *pfc_en_tx = MLX5_GET(pfcc_reg, out, pfctx); 425 426 if (pfc_en_rx) 427 *pfc_en_rx = MLX5_GET(pfcc_reg, out, pfcrx); 428 429 return 0; 430} 431EXPORT_SYMBOL_GPL(mlx5_query_port_pfc); 432 433int mlx5_query_port_oper_mtu(struct mlx5_core_dev *dev, int *oper_mtu) 434{ 435 return mlx5_query_port_mtu(dev, NULL, NULL, oper_mtu); 436} 437EXPORT_SYMBOL_GPL(mlx5_query_port_oper_mtu); 438 439u8 mlx5_is_wol_supported(struct mlx5_core_dev *dev) 440{ 441 u8 wol_supported = 0; 442 443 if (MLX5_CAP_GEN(dev, wol_s)) 444 wol_supported |= MLX5_WOL_SECURED_MAGIC; 445 if (MLX5_CAP_GEN(dev, wol_g)) 446 wol_supported |= MLX5_WOL_MAGIC; 447 if (MLX5_CAP_GEN(dev, wol_a)) 448 wol_supported |= MLX5_WOL_ARP; 449 if (MLX5_CAP_GEN(dev, wol_b)) 450 wol_supported |= MLX5_WOL_BROADCAST; 451 if (MLX5_CAP_GEN(dev, wol_m)) 452 wol_supported |= MLX5_WOL_MULTICAST; 453 if (MLX5_CAP_GEN(dev, wol_u)) 454 wol_supported |= MLX5_WOL_UNICAST; 455 if (MLX5_CAP_GEN(dev, wol_p)) 456 wol_supported |= MLX5_WOL_PHY_ACTIVITY; 457 458 return wol_supported; 459} 460EXPORT_SYMBOL_GPL(mlx5_is_wol_supported); 461 462int mlx5_set_wol(struct mlx5_core_dev *dev, u8 wol_mode) 463{ 464 u32 in[MLX5_ST_SZ_DW(set_wol_rol_in)]; 465 u32 out[MLX5_ST_SZ_DW(set_wol_rol_out)]; 466 467 memset(in, 0, sizeof(in)); 468 memset(out, 0, sizeof(out)); 469 470 MLX5_SET(set_wol_rol_in, in, opcode, MLX5_CMD_OP_SET_WOL_ROL); 471 MLX5_SET(set_wol_rol_in, in, wol_mode_valid, 1); 472 MLX5_SET(set_wol_rol_in, in, wol_mode, wol_mode); 473 474 return mlx5_cmd_exec_check_status(dev, in, sizeof(in), 475 out, sizeof(out)); 476} 477EXPORT_SYMBOL_GPL(mlx5_set_wol); 478 479int mlx5_query_dropless_mode(struct mlx5_core_dev *dev, u16 *timeout) 480{ 481 u32 in[MLX5_ST_SZ_DW(query_delay_drop_params_in)]; 482 u32 out[MLX5_ST_SZ_DW(query_delay_drop_params_out)]; 483 int err = 0; 484 485 memset(in, 0, sizeof(in)); 486 memset(out, 0, sizeof(out)); 487 488 MLX5_SET(query_delay_drop_params_in, in, opcode, 489 MLX5_CMD_OP_QUERY_DELAY_DROP_PARAMS); 490 491 err = mlx5_cmd_exec_check_status(dev, in, sizeof(in), out, sizeof(out)); 492 if (err) 493 return err; 494 495 *timeout = MLX5_GET(query_delay_drop_params_out, out, 496 delay_drop_timeout); 497 498 return 0; 499} 500EXPORT_SYMBOL_GPL(mlx5_query_dropless_mode); 501 502int mlx5_set_dropless_mode(struct mlx5_core_dev *dev, u16 timeout) 503{ 504 u32 in[MLX5_ST_SZ_DW(set_delay_drop_params_in)]; 505 u32 out[MLX5_ST_SZ_DW(set_delay_drop_params_out)]; 506 507 memset(in, 0, sizeof(in)); 508 memset(out, 0, sizeof(out)); 509 510 MLX5_SET(set_delay_drop_params_in, in, opcode, 511 MLX5_CMD_OP_SET_DELAY_DROP_PARAMS); 512 MLX5_SET(set_delay_drop_params_in, in, delay_drop_timeout, timeout); 513 514 return mlx5_cmd_exec_check_status(dev, in, sizeof(in), 515 out, sizeof(out)); 516} 517EXPORT_SYMBOL_GPL(mlx5_set_dropless_mode); 518 519int mlx5_core_access_pvlc(struct mlx5_core_dev *dev, 520 struct mlx5_pvlc_reg *pvlc, int write) 521{ 522 int sz = MLX5_ST_SZ_BYTES(pvlc_reg); 523 u8 in[MLX5_ST_SZ_BYTES(pvlc_reg)]; 524 u8 out[MLX5_ST_SZ_BYTES(pvlc_reg)]; 525 int err; 526 527 memset(out, 0, sizeof(out)); 528 memset(in, 0, sizeof(in)); 529 530 MLX5_SET(pvlc_reg, in, local_port, pvlc->local_port); 531 if (write) 532 MLX5_SET(pvlc_reg, in, vl_admin, pvlc->vl_admin); 533 534 err = mlx5_core_access_reg(dev, in, sz, out, sz, MLX5_REG_PVLC, 0, 535 !!write); 536 if (err) 537 return err; 538 539 if (!write) { 540 pvlc->local_port = MLX5_GET(pvlc_reg, out, local_port); 541 pvlc->vl_hw_cap = MLX5_GET(pvlc_reg, out, vl_hw_cap); 542 pvlc->vl_admin = MLX5_GET(pvlc_reg, out, vl_admin); 543 pvlc->vl_operational = MLX5_GET(pvlc_reg, out, vl_operational); 544 } 545 546 return 0; 547} 548EXPORT_SYMBOL_GPL(mlx5_core_access_pvlc); 549 550int mlx5_core_access_ptys(struct mlx5_core_dev *dev, 551 struct mlx5_ptys_reg *ptys, int write) 552{ 553 int sz = MLX5_ST_SZ_BYTES(ptys_reg); 554 void *out = NULL; 555 void *in = NULL; 556 int err; 557 558 in = mlx5_vzalloc(sz); 559 if (!in) 560 return -ENOMEM; 561 562 out = mlx5_vzalloc(sz); 563 if (!out) { 564 kfree(in); 565 return -ENOMEM; 566 } 567 568 MLX5_SET(ptys_reg, in, local_port, ptys->local_port); 569 MLX5_SET(ptys_reg, in, proto_mask, ptys->proto_mask); 570 if (write) { 571 MLX5_SET(ptys_reg, in, eth_proto_capability, 572 ptys->eth_proto_cap); 573 MLX5_SET(ptys_reg, in, ib_link_width_capability, 574 ptys->ib_link_width_cap); 575 MLX5_SET(ptys_reg, in, ib_proto_capability, 576 ptys->ib_proto_cap); 577 MLX5_SET(ptys_reg, in, eth_proto_admin, ptys->eth_proto_admin); 578 MLX5_SET(ptys_reg, in, ib_link_width_admin, 579 ptys->ib_link_width_admin); 580 MLX5_SET(ptys_reg, in, ib_proto_admin, ptys->ib_proto_admin); 581 MLX5_SET(ptys_reg, in, eth_proto_oper, ptys->eth_proto_oper); 582 MLX5_SET(ptys_reg, in, ib_link_width_oper, 583 ptys->ib_link_width_oper); 584 MLX5_SET(ptys_reg, in, ib_proto_oper, ptys->ib_proto_oper); 585 MLX5_SET(ptys_reg, in, eth_proto_lp_advertise, 586 ptys->eth_proto_lp_advertise); 587 } 588 589 err = mlx5_core_access_reg(dev, in, sz, out, sz, MLX5_REG_PTYS, 0, 590 !!write); 591 if (err) 592 goto out; 593 594 if (!write) { 595 ptys->local_port = MLX5_GET(ptys_reg, out, local_port); 596 ptys->proto_mask = MLX5_GET(ptys_reg, out, proto_mask); 597 ptys->eth_proto_cap = MLX5_GET(ptys_reg, out, 598 eth_proto_capability); 599 ptys->ib_link_width_cap = MLX5_GET(ptys_reg, out, 600 ib_link_width_capability); 601 ptys->ib_proto_cap = MLX5_GET(ptys_reg, out, 602 ib_proto_capability); 603 ptys->eth_proto_admin = MLX5_GET(ptys_reg, out, 604 eth_proto_admin); 605 ptys->ib_link_width_admin = MLX5_GET(ptys_reg, out, 606 ib_link_width_admin); 607 ptys->ib_proto_admin = MLX5_GET(ptys_reg, out, ib_proto_admin); 608 ptys->eth_proto_oper = MLX5_GET(ptys_reg, out, eth_proto_oper); 609 ptys->ib_link_width_oper = MLX5_GET(ptys_reg, out, 610 ib_link_width_oper); 611 ptys->ib_proto_oper = MLX5_GET(ptys_reg, out, ib_proto_oper); 612 ptys->eth_proto_lp_advertise = MLX5_GET(ptys_reg, out, 613 eth_proto_lp_advertise); 614 } 615 616out: 617 kvfree(in); 618 kvfree(out); 619 return err; 620} 621EXPORT_SYMBOL_GPL(mlx5_core_access_ptys); 622 623static int mtu_to_ib_mtu(int mtu) 624{ 625 switch (mtu) { 626 case 256: return 1; 627 case 512: return 2; 628 case 1024: return 3; 629 case 2048: return 4; 630 case 4096: return 5; 631 default: 632 printf("mlx5_core: WARN: ""invalid mtu\n"); 633 return -1; 634 } 635} 636 637int mlx5_core_access_pmtu(struct mlx5_core_dev *dev, 638 struct mlx5_pmtu_reg *pmtu, int write) 639{ 640 int sz = MLX5_ST_SZ_BYTES(pmtu_reg); 641 void *out = NULL; 642 void *in = NULL; 643 int err; 644 645 in = mlx5_vzalloc(sz); 646 if (!in) 647 return -ENOMEM; 648 649 out = mlx5_vzalloc(sz); 650 if (!out) { 651 kfree(in); 652 return -ENOMEM; 653 } 654 655 MLX5_SET(pmtu_reg, in, local_port, pmtu->local_port); 656 if (write) 657 MLX5_SET(pmtu_reg, in, admin_mtu, pmtu->admin_mtu); 658 659 err = mlx5_core_access_reg(dev, in, sz, out, sz, MLX5_REG_PMTU, 0, 660 !!write); 661 if (err) 662 goto out; 663 664 if (!write) { 665 pmtu->local_port = MLX5_GET(pmtu_reg, out, local_port); 666 pmtu->max_mtu = mtu_to_ib_mtu(MLX5_GET(pmtu_reg, out, 667 max_mtu)); 668 pmtu->admin_mtu = mtu_to_ib_mtu(MLX5_GET(pmtu_reg, out, 669 admin_mtu)); 670 pmtu->oper_mtu = mtu_to_ib_mtu(MLX5_GET(pmtu_reg, out, 671 oper_mtu)); 672 } 673 674out: 675 kvfree(in); 676 kvfree(out); 677 return err; 678} 679EXPORT_SYMBOL_GPL(mlx5_core_access_pmtu); 680 681int mlx5_query_module_num(struct mlx5_core_dev *dev, int *module_num) 682{ 683 u32 in[MLX5_ST_SZ_DW(pmlp_reg)]; 684 u32 out[MLX5_ST_SZ_DW(pmlp_reg)]; 685 int lane = 0; 686 int err; 687 688 memset(in, 0, sizeof(in)); 689 690 MLX5_SET(pmlp_reg, in, local_port, 1); 691 692 err = mlx5_core_access_reg(dev, in, sizeof(in), out, 693 sizeof(out), MLX5_REG_PMLP, 0, 0); 694 if (err) 695 return err; 696 697 lane = MLX5_GET(pmlp_reg, out, lane0_module_mapping); 698 *module_num = lane & MLX5_EEPROM_IDENTIFIER_BYTE_MASK; 699 700 return 0; 701} 702EXPORT_SYMBOL_GPL(mlx5_query_module_num); 703 704int mlx5_query_eeprom(struct mlx5_core_dev *dev, 705 int i2c_addr, int page_num, int device_addr, 706 int size, int module_num, u32 *data, int *size_read) 707{ 708 u32 in[MLX5_ST_SZ_DW(mcia_reg)]; 709 u32 out[MLX5_ST_SZ_DW(mcia_reg)]; 710 u32 *ptr = (u32 *)MLX5_ADDR_OF(mcia_reg, out, dword_0); 711 int status; 712 int err; 713 714 memset(in, 0, sizeof(in)); 715 size = min_t(int, size, MLX5_EEPROM_MAX_BYTES); 716 717 MLX5_SET(mcia_reg, in, l, 0); 718 MLX5_SET(mcia_reg, in, module, module_num); 719 MLX5_SET(mcia_reg, in, i2c_device_address, i2c_addr); 720 MLX5_SET(mcia_reg, in, page_number, page_num); 721 MLX5_SET(mcia_reg, in, device_address, device_addr); 722 MLX5_SET(mcia_reg, in, size, size); 723 724 err = mlx5_core_access_reg(dev, in, sizeof(in), out, 725 sizeof(out), MLX5_REG_MCIA, 0, 0); 726 if (err) 727 return err; 728 729 status = MLX5_GET(mcia_reg, out, status); 730 if (status) 731 return status; 732 733 memcpy(data, ptr, size); 734 *size_read = size; 735 return 0; 736} 737EXPORT_SYMBOL_GPL(mlx5_query_eeprom); 738 739int mlx5_vxlan_udp_port_add(struct mlx5_core_dev *dev, u16 port) 740{ 741 u32 in[MLX5_ST_SZ_DW(add_vxlan_udp_dport_in)]; 742 u32 out[MLX5_ST_SZ_DW(add_vxlan_udp_dport_out)]; 743 int err; 744 745 memset(in, 0, sizeof(in)); 746 memset(out, 0, sizeof(out)); 747 748 MLX5_SET(add_vxlan_udp_dport_in, in, opcode, 749 MLX5_CMD_OP_ADD_VXLAN_UDP_DPORT); 750 MLX5_SET(add_vxlan_udp_dport_in, in, vxlan_udp_port, port); 751 752 err = mlx5_cmd_exec_check_status(dev, in, sizeof(in), out, sizeof(out)); 753 if (err) { 754 mlx5_core_err(dev, "Failed %s, port %u, err - %d", 755 mlx5_command_str(MLX5_CMD_OP_ADD_VXLAN_UDP_DPORT), 756 port, err); 757 } 758 759 return err; 760} 761 762int mlx5_vxlan_udp_port_delete(struct mlx5_core_dev *dev, u16 port) 763{ 764 u32 in[MLX5_ST_SZ_DW(delete_vxlan_udp_dport_in)]; 765 u32 out[MLX5_ST_SZ_DW(delete_vxlan_udp_dport_out)]; 766 int err; 767 768 memset(in, 0, sizeof(in)); 769 memset(out, 0, sizeof(out)); 770 771 MLX5_SET(delete_vxlan_udp_dport_in, in, opcode, 772 MLX5_CMD_OP_DELETE_VXLAN_UDP_DPORT); 773 MLX5_SET(delete_vxlan_udp_dport_in, in, vxlan_udp_port, port); 774 775 err = mlx5_cmd_exec_check_status(dev, in, sizeof(in), out, sizeof(out)); 776 if (err) { 777 mlx5_core_err(dev, "Failed %s, port %u, err - %d", 778 mlx5_command_str(MLX5_CMD_OP_DELETE_VXLAN_UDP_DPORT), 779 port, err); 780 } 781 782 return err; 783} 784 785int mlx5_query_wol(struct mlx5_core_dev *dev, u8 *wol_mode) 786{ 787 u32 in[MLX5_ST_SZ_DW(query_wol_rol_in)]; 788 u32 out[MLX5_ST_SZ_DW(query_wol_rol_out)]; 789 int err; 790 791 memset(in, 0, sizeof(in)); 792 memset(out, 0, sizeof(out)); 793 794 MLX5_SET(query_wol_rol_in, in, opcode, MLX5_CMD_OP_QUERY_WOL_ROL); 795 796 err = mlx5_cmd_exec_check_status(dev, in, sizeof(in), out, sizeof(out)); 797 798 if (!err) 799 *wol_mode = MLX5_GET(query_wol_rol_out, out, wol_mode); 800 801 return err; 802} 803EXPORT_SYMBOL_GPL(mlx5_query_wol); 804 805int mlx5_query_port_cong_status(struct mlx5_core_dev *mdev, int protocol, 806 int priority, int *is_enable) 807{ 808 u32 in[MLX5_ST_SZ_DW(query_cong_status_in)]; 809 u32 out[MLX5_ST_SZ_DW(query_cong_status_out)]; 810 int err; 811 812 memset(in, 0, sizeof(in)); 813 memset(out, 0, sizeof(out)); 814 815 *is_enable = 0; 816 817 MLX5_SET(query_cong_status_in, in, opcode, 818 MLX5_CMD_OP_QUERY_CONG_STATUS); 819 MLX5_SET(query_cong_status_in, in, cong_protocol, protocol); 820 MLX5_SET(query_cong_status_in, in, priority, priority); 821 822 err = mlx5_cmd_exec_check_status(mdev, in, sizeof(in), 823 out, sizeof(out)); 824 if (!err) 825 *is_enable = MLX5_GET(query_cong_status_out, out, enable); 826 return err; 827} 828 829int mlx5_modify_port_cong_status(struct mlx5_core_dev *mdev, int protocol, 830 int priority, int enable) 831{ 832 u32 in[MLX5_ST_SZ_DW(modify_cong_status_in)]; 833 u32 out[MLX5_ST_SZ_DW(modify_cong_status_out)]; 834 835 memset(in, 0, sizeof(in)); 836 memset(out, 0, sizeof(out)); 837 838 MLX5_SET(modify_cong_status_in, in, opcode, 839 MLX5_CMD_OP_MODIFY_CONG_STATUS); 840 MLX5_SET(modify_cong_status_in, in, cong_protocol, protocol); 841 MLX5_SET(modify_cong_status_in, in, priority, priority); 842 MLX5_SET(modify_cong_status_in, in, enable, enable); 843 844 return mlx5_cmd_exec_check_status(mdev, in, sizeof(in), 845 out, sizeof(out)); 846} 847 848int mlx5_query_port_cong_params(struct mlx5_core_dev *mdev, int protocol, 849 void *out, int out_size) 850{ 851 u32 in[MLX5_ST_SZ_DW(query_cong_params_in)]; 852 853 memset(in, 0, sizeof(in)); 854 855 MLX5_SET(query_cong_params_in, in, opcode, 856 MLX5_CMD_OP_QUERY_CONG_PARAMS); 857 MLX5_SET(query_cong_params_in, in, cong_protocol, protocol); 858 859 return mlx5_cmd_exec_check_status(mdev, in, sizeof(in), 860 out, out_size); 861} 862 863static int mlx5_query_port_qetcr_reg(struct mlx5_core_dev *mdev, u32 *out, 864 int outlen) 865{ 866 u32 in[MLX5_ST_SZ_DW(qtct_reg)]; 867 868 if (!MLX5_CAP_GEN(mdev, ets)) 869 return -ENOTSUPP; 870 871 memset(in, 0, sizeof(in)); 872 return mlx5_core_access_reg(mdev, in, sizeof(in), out, outlen, 873 MLX5_REG_QETCR, 0, 0); 874} 875 876int mlx5_max_tc(struct mlx5_core_dev *mdev) 877{ 878 u8 num_tc = MLX5_CAP_GEN(mdev, max_tc) ? : 8; 879 880 return num_tc - 1; 881} 882EXPORT_SYMBOL_GPL(mlx5_max_tc); 883 884static int mlx5_set_port_qetcr_reg(struct mlx5_core_dev *mdev, u32 *in, 885 int inlen) 886{ 887 u32 out[MLX5_ST_SZ_DW(qtct_reg)]; 888 889 if (!MLX5_CAP_GEN(mdev, ets)) 890 return -ENOTSUPP; 891 892 return mlx5_core_access_reg(mdev, in, inlen, out, sizeof(out), 893 MLX5_REG_QETCR, 0, 1); 894} 895 896int mlx5_query_port_tc_rate_limit(struct mlx5_core_dev *mdev, 897 u8 *max_bw_value, 898 u8 *max_bw_units) 899{ 900 u32 out[MLX5_ST_SZ_DW(qetc_reg)]; 901 void *ets_tcn_conf; 902 int err; 903 int i; 904 905 err = mlx5_query_port_qetcr_reg(mdev, out, sizeof(out)); 906 if (err) 907 return err; 908 909 for (i = 0; i <= mlx5_max_tc(mdev); i++) { 910 ets_tcn_conf = MLX5_ADDR_OF(qetc_reg, out, tc_configuration[i]); 911 912 max_bw_value[i] = MLX5_GET(ets_tcn_config_reg, ets_tcn_conf, 913 max_bw_value); 914 max_bw_units[i] = MLX5_GET(ets_tcn_config_reg, ets_tcn_conf, 915 max_bw_units); 916 } 917 918 return 0; 919} 920EXPORT_SYMBOL_GPL(mlx5_query_port_tc_rate_limit); 921 922int mlx5_modify_port_tc_rate_limit(struct mlx5_core_dev *mdev, 923 const u8 *max_bw_value, 924 const u8 *max_bw_units) 925{ 926 u32 in[MLX5_ST_SZ_DW(qetc_reg)] = {}; 927 void *ets_tcn_conf; 928 int i; 929 930 MLX5_SET(qetc_reg, in, port_number, 1); 931 932 for (i = 0; i <= mlx5_max_tc(mdev); i++) { 933 ets_tcn_conf = MLX5_ADDR_OF(qetc_reg, in, tc_configuration[i]); 934 935 MLX5_SET(ets_tcn_config_reg, ets_tcn_conf, r, 1); 936 MLX5_SET(ets_tcn_config_reg, ets_tcn_conf, max_bw_units, 937 max_bw_units[i]); 938 MLX5_SET(ets_tcn_config_reg, ets_tcn_conf, max_bw_value, 939 max_bw_value[i]); 940 } 941 942 return mlx5_set_port_qetcr_reg(mdev, in, sizeof(in)); 943} 944EXPORT_SYMBOL_GPL(mlx5_modify_port_tc_rate_limit); 945 946int mlx5_modify_port_cong_params(struct mlx5_core_dev *mdev, 947 void *in, int in_size) 948{ 949 u32 out[MLX5_ST_SZ_DW(modify_cong_params_out)]; 950 951 memset(out, 0, sizeof(out)); 952 953 MLX5_SET(modify_cong_params_in, in, opcode, 954 MLX5_CMD_OP_MODIFY_CONG_PARAMS); 955 956 return mlx5_cmd_exec_check_status(mdev, in, in_size, out, sizeof(out)); 957} 958 959int mlx5_query_port_cong_statistics(struct mlx5_core_dev *mdev, int clear, 960 void *out, int out_size) 961{ 962 u32 in[MLX5_ST_SZ_DW(query_cong_statistics_in)]; 963 964 memset(in, 0, sizeof(in)); 965 966 MLX5_SET(query_cong_statistics_in, in, opcode, 967 MLX5_CMD_OP_QUERY_CONG_STATISTICS); 968 MLX5_SET(query_cong_statistics_in, in, clear, clear); 969 970 return mlx5_cmd_exec_check_status(mdev, in, sizeof(in), 971 out, out_size); 972} 973 974int mlx5_set_diagnostic_params(struct mlx5_core_dev *mdev, void *in, 975 int in_size) 976{ 977 u32 out[MLX5_ST_SZ_DW(set_diagnostic_params_out)]; 978 979 memset(out, 0, sizeof(out)); 980 981 MLX5_SET(set_diagnostic_params_in, in, opcode, 982 MLX5_CMD_OP_SET_DIAGNOSTICS); 983 984 return mlx5_cmd_exec_check_status(mdev, in, in_size, out, sizeof(out)); 985} 986 987int mlx5_query_diagnostic_counters(struct mlx5_core_dev *mdev, 988 u8 num_of_samples, u16 sample_index, 989 void *out, int out_size) 990{ 991 u32 in[MLX5_ST_SZ_DW(query_diagnostic_counters_in)]; 992 993 memset(in, 0, sizeof(in)); 994 995 MLX5_SET(query_diagnostic_counters_in, in, opcode, 996 MLX5_CMD_OP_QUERY_DIAGNOSTICS); 997 MLX5_SET(query_diagnostic_counters_in, in, num_of_samples, 998 num_of_samples); 999 MLX5_SET(query_diagnostic_counters_in, in, sample_index, sample_index); 1000 1001 return mlx5_cmd_exec_check_status(mdev, in, sizeof(in), out, out_size); 1002} 1003