mlx5_port.c revision 306233
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 306233 2016-09-23 08:17:51Z hselasky $ 26 */ 27 28#include <linux/module.h> 29#include <dev/mlx5/driver.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) 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, 1); 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); 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); 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); 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_set_port_proto(struct mlx5_core_dev *dev, u32 proto_admin, 215 int proto_mask) 216{ 217 u32 in[MLX5_ST_SZ_DW(ptys_reg)]; 218 u32 out[MLX5_ST_SZ_DW(ptys_reg)]; 219 int err; 220 221 memset(in, 0, sizeof(in)); 222 223 MLX5_SET(ptys_reg, in, local_port, 1); 224 MLX5_SET(ptys_reg, in, proto_mask, proto_mask); 225 if (proto_mask == MLX5_PTYS_EN) 226 MLX5_SET(ptys_reg, in, eth_proto_admin, proto_admin); 227 else 228 MLX5_SET(ptys_reg, in, ib_proto_admin, proto_admin); 229 230 err = mlx5_core_access_reg(dev, in, sizeof(in), out, 231 sizeof(out), MLX5_REG_PTYS, 0, 1); 232 return err; 233} 234EXPORT_SYMBOL_GPL(mlx5_set_port_proto); 235 236int mlx5_set_port_status(struct mlx5_core_dev *dev, 237 enum mlx5_port_status status) 238{ 239 u32 in[MLX5_ST_SZ_DW(paos_reg)]; 240 u32 out[MLX5_ST_SZ_DW(paos_reg)]; 241 int err; 242 243 memset(in, 0, sizeof(in)); 244 245 MLX5_SET(paos_reg, in, local_port, 1); 246 247 MLX5_SET(paos_reg, in, admin_status, status); 248 MLX5_SET(paos_reg, in, ase, 1); 249 250 err = mlx5_core_access_reg(dev, in, sizeof(in), out, 251 sizeof(out), MLX5_REG_PAOS, 0, 1); 252 return err; 253} 254 255int mlx5_query_port_status(struct mlx5_core_dev *dev, u8 *status) 256{ 257 u32 in[MLX5_ST_SZ_DW(paos_reg)]; 258 u32 out[MLX5_ST_SZ_DW(paos_reg)]; 259 int err; 260 261 memset(in, 0, sizeof(in)); 262 263 MLX5_SET(paos_reg, in, local_port, 1); 264 265 err = mlx5_core_access_reg(dev, in, sizeof(in), out, 266 sizeof(out), MLX5_REG_PAOS, 0, 0); 267 if (err) 268 return err; 269 270 *status = MLX5_GET(paos_reg, out, oper_status); 271 return err; 272} 273 274int mlx5_query_port_admin_status(struct mlx5_core_dev *dev, 275 enum mlx5_port_status *status) 276{ 277 u32 in[MLX5_ST_SZ_DW(paos_reg)] = {0}; 278 u32 out[MLX5_ST_SZ_DW(paos_reg)]; 279 int err; 280 281 MLX5_SET(paos_reg, in, local_port, 1); 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 *status = MLX5_GET(paos_reg, out, admin_status); 287 return 0; 288} 289EXPORT_SYMBOL_GPL(mlx5_query_port_admin_status); 290 291static int mlx5_query_port_mtu(struct mlx5_core_dev *dev, 292 int *admin_mtu, int *max_mtu, int *oper_mtu) 293{ 294 u32 in[MLX5_ST_SZ_DW(pmtu_reg)]; 295 u32 out[MLX5_ST_SZ_DW(pmtu_reg)]; 296 int err; 297 298 memset(in, 0, sizeof(in)); 299 300 MLX5_SET(pmtu_reg, in, local_port, 1); 301 302 err = mlx5_core_access_reg(dev, in, sizeof(in), out, 303 sizeof(out), MLX5_REG_PMTU, 0, 0); 304 if (err) 305 return err; 306 307 if (max_mtu) 308 *max_mtu = MLX5_GET(pmtu_reg, out, max_mtu); 309 if (oper_mtu) 310 *oper_mtu = MLX5_GET(pmtu_reg, out, oper_mtu); 311 if (admin_mtu) 312 *admin_mtu = MLX5_GET(pmtu_reg, out, admin_mtu); 313 314 return err; 315} 316 317int mlx5_set_port_mtu(struct mlx5_core_dev *dev, int mtu) 318{ 319 u32 in[MLX5_ST_SZ_DW(pmtu_reg)]; 320 u32 out[MLX5_ST_SZ_DW(pmtu_reg)]; 321 322 memset(in, 0, sizeof(in)); 323 324 MLX5_SET(pmtu_reg, in, admin_mtu, mtu); 325 MLX5_SET(pmtu_reg, in, local_port, 1); 326 327 return mlx5_core_access_reg(dev, in, sizeof(in), out, 328 sizeof(out), MLX5_REG_PMTU, 0, 1); 329} 330EXPORT_SYMBOL_GPL(mlx5_set_port_mtu); 331 332int mlx5_query_port_max_mtu(struct mlx5_core_dev *dev, int *max_mtu) 333{ 334 return mlx5_query_port_mtu(dev, NULL, max_mtu, NULL); 335} 336EXPORT_SYMBOL_GPL(mlx5_query_port_max_mtu); 337 338int mlx5_set_port_pause(struct mlx5_core_dev *dev, u32 port, 339 u32 rx_pause, u32 tx_pause) 340{ 341 u32 in[MLX5_ST_SZ_DW(pfcc_reg)]; 342 u32 out[MLX5_ST_SZ_DW(pfcc_reg)]; 343 344 memset(in, 0, sizeof(in)); 345 memset(out, 0, sizeof(out)); 346 347 MLX5_SET(pfcc_reg, in, local_port, port); 348 MLX5_SET(pfcc_reg, in, pptx, tx_pause); 349 MLX5_SET(pfcc_reg, in, pprx, rx_pause); 350 351 return mlx5_core_access_reg(dev, in, sizeof(in), out, 352 sizeof(out), MLX5_REG_PFCC, 0, 1); 353} 354 355int mlx5_query_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 int err; 361 362 memset(in, 0, sizeof(in)); 363 memset(out, 0, sizeof(out)); 364 365 MLX5_SET(pfcc_reg, in, local_port, port); 366 367 err = mlx5_core_access_reg(dev, in, sizeof(in), out, 368 sizeof(out), MLX5_REG_PFCC, 0, 0); 369 if (err) 370 return err; 371 372 *rx_pause = MLX5_GET(pfcc_reg, out, pprx); 373 *tx_pause = MLX5_GET(pfcc_reg, out, pptx); 374 375 return 0; 376} 377 378int mlx5_set_port_pfc(struct mlx5_core_dev *dev, u8 pfc_en_tx, u8 pfc_en_rx) 379{ 380 u32 in[MLX5_ST_SZ_DW(pfcc_reg)] = {0}; 381 u32 out[MLX5_ST_SZ_DW(pfcc_reg)]; 382 383 MLX5_SET(pfcc_reg, in, local_port, 1); 384 MLX5_SET(pfcc_reg, in, pfctx, pfc_en_tx); 385 MLX5_SET(pfcc_reg, in, pfcrx, pfc_en_rx); 386 MLX5_SET_TO_ONES(pfcc_reg, in, prio_mask_tx); 387 MLX5_SET_TO_ONES(pfcc_reg, in, prio_mask_rx); 388 389 return mlx5_core_access_reg(dev, in, sizeof(in), out, 390 sizeof(out), MLX5_REG_PFCC, 0, 1); 391} 392EXPORT_SYMBOL_GPL(mlx5_set_port_pfc); 393 394int mlx5_query_port_pfc(struct mlx5_core_dev *dev, u8 *pfc_en_tx, u8 *pfc_en_rx) 395{ 396 u32 in[MLX5_ST_SZ_DW(pfcc_reg)] = {0}; 397 u32 out[MLX5_ST_SZ_DW(pfcc_reg)]; 398 int err; 399 400 MLX5_SET(pfcc_reg, in, local_port, 1); 401 err = mlx5_core_access_reg(dev, in, sizeof(in), out, 402 sizeof(out), MLX5_REG_PFCC, 0, 0); 403 if (err) 404 return err; 405 406 if (pfc_en_tx) 407 *pfc_en_tx = MLX5_GET(pfcc_reg, out, pfctx); 408 409 if (pfc_en_rx) 410 *pfc_en_rx = MLX5_GET(pfcc_reg, out, pfcrx); 411 412 return 0; 413} 414EXPORT_SYMBOL_GPL(mlx5_query_port_pfc); 415 416int mlx5_query_port_oper_mtu(struct mlx5_core_dev *dev, int *oper_mtu) 417{ 418 return mlx5_query_port_mtu(dev, NULL, NULL, oper_mtu); 419} 420EXPORT_SYMBOL_GPL(mlx5_query_port_oper_mtu); 421 422u8 mlx5_is_wol_supported(struct mlx5_core_dev *dev) 423{ 424 u8 wol_supported = 0; 425 426 if (MLX5_CAP_GEN(dev, wol_s)) 427 wol_supported |= MLX5_WOL_SECURED_MAGIC; 428 if (MLX5_CAP_GEN(dev, wol_g)) 429 wol_supported |= MLX5_WOL_MAGIC; 430 if (MLX5_CAP_GEN(dev, wol_a)) 431 wol_supported |= MLX5_WOL_ARP; 432 if (MLX5_CAP_GEN(dev, wol_b)) 433 wol_supported |= MLX5_WOL_BROADCAST; 434 if (MLX5_CAP_GEN(dev, wol_m)) 435 wol_supported |= MLX5_WOL_MULTICAST; 436 if (MLX5_CAP_GEN(dev, wol_u)) 437 wol_supported |= MLX5_WOL_UNICAST; 438 if (MLX5_CAP_GEN(dev, wol_p)) 439 wol_supported |= MLX5_WOL_PHY_ACTIVITY; 440 441 return wol_supported; 442} 443EXPORT_SYMBOL_GPL(mlx5_is_wol_supported); 444 445int mlx5_set_wol(struct mlx5_core_dev *dev, u8 wol_mode) 446{ 447 u32 in[MLX5_ST_SZ_DW(set_wol_rol_in)]; 448 u32 out[MLX5_ST_SZ_DW(set_wol_rol_out)]; 449 450 memset(in, 0, sizeof(in)); 451 memset(out, 0, sizeof(out)); 452 453 MLX5_SET(set_wol_rol_in, in, opcode, MLX5_CMD_OP_SET_WOL_ROL); 454 MLX5_SET(set_wol_rol_in, in, wol_mode_valid, 1); 455 MLX5_SET(set_wol_rol_in, in, wol_mode, wol_mode); 456 457 return mlx5_cmd_exec_check_status(dev, in, sizeof(in), 458 out, sizeof(out)); 459} 460EXPORT_SYMBOL_GPL(mlx5_set_wol); 461 462int mlx5_core_access_pvlc(struct mlx5_core_dev *dev, 463 struct mlx5_pvlc_reg *pvlc, int write) 464{ 465 int sz = MLX5_ST_SZ_BYTES(pvlc_reg); 466 u8 in[MLX5_ST_SZ_BYTES(pvlc_reg)]; 467 u8 out[MLX5_ST_SZ_BYTES(pvlc_reg)]; 468 int err; 469 470 memset(out, 0, sizeof(out)); 471 memset(in, 0, sizeof(in)); 472 473 MLX5_SET(pvlc_reg, in, local_port, pvlc->local_port); 474 if (write) 475 MLX5_SET(pvlc_reg, in, vl_admin, pvlc->vl_admin); 476 477 err = mlx5_core_access_reg(dev, in, sz, out, sz, MLX5_REG_PVLC, 0, 478 !!write); 479 if (err) 480 return err; 481 482 if (!write) { 483 pvlc->local_port = MLX5_GET(pvlc_reg, out, local_port); 484 pvlc->vl_hw_cap = MLX5_GET(pvlc_reg, out, vl_hw_cap); 485 pvlc->vl_admin = MLX5_GET(pvlc_reg, out, vl_admin); 486 pvlc->vl_operational = MLX5_GET(pvlc_reg, out, vl_operational); 487 } 488 489 return 0; 490} 491EXPORT_SYMBOL_GPL(mlx5_core_access_pvlc); 492 493int mlx5_core_access_ptys(struct mlx5_core_dev *dev, 494 struct mlx5_ptys_reg *ptys, int write) 495{ 496 int sz = MLX5_ST_SZ_BYTES(ptys_reg); 497 void *out = NULL; 498 void *in = NULL; 499 int err; 500 501 in = mlx5_vzalloc(sz); 502 if (!in) 503 return -ENOMEM; 504 505 out = mlx5_vzalloc(sz); 506 if (!out) { 507 kfree(in); 508 return -ENOMEM; 509 } 510 511 MLX5_SET(ptys_reg, in, local_port, ptys->local_port); 512 MLX5_SET(ptys_reg, in, proto_mask, ptys->proto_mask); 513 if (write) { 514 MLX5_SET(ptys_reg, in, eth_proto_capability, 515 ptys->eth_proto_cap); 516 MLX5_SET(ptys_reg, in, ib_link_width_capability, 517 ptys->ib_link_width_cap); 518 MLX5_SET(ptys_reg, in, ib_proto_capability, 519 ptys->ib_proto_cap); 520 MLX5_SET(ptys_reg, in, eth_proto_admin, ptys->eth_proto_admin); 521 MLX5_SET(ptys_reg, in, ib_link_width_admin, 522 ptys->ib_link_width_admin); 523 MLX5_SET(ptys_reg, in, ib_proto_admin, ptys->ib_proto_admin); 524 MLX5_SET(ptys_reg, in, eth_proto_oper, ptys->eth_proto_oper); 525 MLX5_SET(ptys_reg, in, ib_link_width_oper, 526 ptys->ib_link_width_oper); 527 MLX5_SET(ptys_reg, in, ib_proto_oper, ptys->ib_proto_oper); 528 MLX5_SET(ptys_reg, in, eth_proto_lp_advertise, 529 ptys->eth_proto_lp_advertise); 530 } 531 532 err = mlx5_core_access_reg(dev, in, sz, out, sz, MLX5_REG_PTYS, 0, 533 !!write); 534 if (err) 535 goto out; 536 537 if (!write) { 538 ptys->local_port = MLX5_GET(ptys_reg, out, local_port); 539 ptys->proto_mask = MLX5_GET(ptys_reg, out, proto_mask); 540 ptys->eth_proto_cap = MLX5_GET(ptys_reg, out, 541 eth_proto_capability); 542 ptys->ib_link_width_cap = MLX5_GET(ptys_reg, out, 543 ib_link_width_capability); 544 ptys->ib_proto_cap = MLX5_GET(ptys_reg, out, 545 ib_proto_capability); 546 ptys->eth_proto_admin = MLX5_GET(ptys_reg, out, 547 eth_proto_admin); 548 ptys->ib_link_width_admin = MLX5_GET(ptys_reg, out, 549 ib_link_width_admin); 550 ptys->ib_proto_admin = MLX5_GET(ptys_reg, out, ib_proto_admin); 551 ptys->eth_proto_oper = MLX5_GET(ptys_reg, out, eth_proto_oper); 552 ptys->ib_link_width_oper = MLX5_GET(ptys_reg, out, 553 ib_link_width_oper); 554 ptys->ib_proto_oper = MLX5_GET(ptys_reg, out, ib_proto_oper); 555 ptys->eth_proto_lp_advertise = MLX5_GET(ptys_reg, out, 556 eth_proto_lp_advertise); 557 } 558 559out: 560 kvfree(in); 561 kvfree(out); 562 return err; 563} 564EXPORT_SYMBOL_GPL(mlx5_core_access_ptys); 565 566static int mtu_to_ib_mtu(int mtu) 567{ 568 switch (mtu) { 569 case 256: return 1; 570 case 512: return 2; 571 case 1024: return 3; 572 case 2048: return 4; 573 case 4096: return 5; 574 default: 575 printf("mlx5_core: WARN: ""invalid mtu\n"); 576 return -1; 577 } 578} 579 580int mlx5_core_access_pmtu(struct mlx5_core_dev *dev, 581 struct mlx5_pmtu_reg *pmtu, int write) 582{ 583 int sz = MLX5_ST_SZ_BYTES(pmtu_reg); 584 void *out = NULL; 585 void *in = NULL; 586 int err; 587 588 in = mlx5_vzalloc(sz); 589 if (!in) 590 return -ENOMEM; 591 592 out = mlx5_vzalloc(sz); 593 if (!out) { 594 kfree(in); 595 return -ENOMEM; 596 } 597 598 MLX5_SET(pmtu_reg, in, local_port, pmtu->local_port); 599 if (write) 600 MLX5_SET(pmtu_reg, in, admin_mtu, pmtu->admin_mtu); 601 602 err = mlx5_core_access_reg(dev, in, sz, out, sz, MLX5_REG_PMTU, 0, 603 !!write); 604 if (err) 605 goto out; 606 607 if (!write) { 608 pmtu->local_port = MLX5_GET(pmtu_reg, out, local_port); 609 pmtu->max_mtu = mtu_to_ib_mtu(MLX5_GET(pmtu_reg, out, 610 max_mtu)); 611 pmtu->admin_mtu = mtu_to_ib_mtu(MLX5_GET(pmtu_reg, out, 612 admin_mtu)); 613 pmtu->oper_mtu = mtu_to_ib_mtu(MLX5_GET(pmtu_reg, out, 614 oper_mtu)); 615 } 616 617out: 618 kvfree(in); 619 kvfree(out); 620 return err; 621} 622EXPORT_SYMBOL_GPL(mlx5_core_access_pmtu); 623 624int mlx5_query_module_num(struct mlx5_core_dev *dev, int *module_num) 625{ 626 u32 in[MLX5_ST_SZ_DW(pmlp_reg)]; 627 u32 out[MLX5_ST_SZ_DW(pmlp_reg)]; 628 int lane = 0; 629 int err; 630 631 memset(in, 0, sizeof(in)); 632 633 MLX5_SET(pmlp_reg, in, local_port, 1); 634 635 err = mlx5_core_access_reg(dev, in, sizeof(in), out, 636 sizeof(out), MLX5_REG_PMLP, 0, 0); 637 if (err) 638 return err; 639 640 lane = MLX5_GET(pmlp_reg, out, lane0_module_mapping); 641 *module_num = lane & MLX5_EEPROM_IDENTIFIER_BYTE_MASK; 642 643 return 0; 644} 645EXPORT_SYMBOL_GPL(mlx5_query_module_num); 646 647int mlx5_query_eeprom(struct mlx5_core_dev *dev, 648 int i2c_addr, int page_num, int device_addr, 649 int size, int module_num, u32 *data, int *size_read) 650{ 651 u32 in[MLX5_ST_SZ_DW(mcia_reg)]; 652 u32 out[MLX5_ST_SZ_DW(mcia_reg)]; 653 u32 *ptr = (u32 *)MLX5_ADDR_OF(mcia_reg, out, dword_0); 654 int status; 655 int err; 656 657 memset(in, 0, sizeof(in)); 658 size = min_t(int, size, MLX5_EEPROM_MAX_BYTES); 659 660 MLX5_SET(mcia_reg, in, l, 0); 661 MLX5_SET(mcia_reg, in, module, module_num); 662 MLX5_SET(mcia_reg, in, i2c_device_address, i2c_addr); 663 MLX5_SET(mcia_reg, in, page_number, page_num); 664 MLX5_SET(mcia_reg, in, device_address, device_addr); 665 MLX5_SET(mcia_reg, in, size, size); 666 667 err = mlx5_core_access_reg(dev, in, sizeof(in), out, 668 sizeof(out), MLX5_REG_MCIA, 0, 0); 669 if (err) 670 return err; 671 672 status = MLX5_GET(mcia_reg, out, status); 673 if (status) 674 return status; 675 676 memcpy(data, ptr, size); 677 *size_read = size; 678 return 0; 679} 680EXPORT_SYMBOL_GPL(mlx5_query_eeprom); 681 682int mlx5_vxlan_udp_port_add(struct mlx5_core_dev *dev, u16 port) 683{ 684 u32 in[MLX5_ST_SZ_DW(add_vxlan_udp_dport_in)]; 685 u32 out[MLX5_ST_SZ_DW(add_vxlan_udp_dport_out)]; 686 int err; 687 688 memset(in, 0, sizeof(in)); 689 memset(out, 0, sizeof(out)); 690 691 MLX5_SET(add_vxlan_udp_dport_in, in, opcode, 692 MLX5_CMD_OP_ADD_VXLAN_UDP_DPORT); 693 MLX5_SET(add_vxlan_udp_dport_in, in, vxlan_udp_port, port); 694 695 err = mlx5_cmd_exec_check_status(dev, in, sizeof(in), out, sizeof(out)); 696 if (err) { 697 mlx5_core_err(dev, "Failed %s, port %u, err - %d", 698 mlx5_command_str(MLX5_CMD_OP_ADD_VXLAN_UDP_DPORT), 699 port, err); 700 } 701 702 return err; 703} 704 705int mlx5_vxlan_udp_port_delete(struct mlx5_core_dev *dev, u16 port) 706{ 707 u32 in[MLX5_ST_SZ_DW(delete_vxlan_udp_dport_in)]; 708 u32 out[MLX5_ST_SZ_DW(delete_vxlan_udp_dport_out)]; 709 int err; 710 711 memset(in, 0, sizeof(in)); 712 memset(out, 0, sizeof(out)); 713 714 MLX5_SET(delete_vxlan_udp_dport_in, in, opcode, 715 MLX5_CMD_OP_DELETE_VXLAN_UDP_DPORT); 716 MLX5_SET(delete_vxlan_udp_dport_in, in, vxlan_udp_port, port); 717 718 err = mlx5_cmd_exec_check_status(dev, in, sizeof(in), out, sizeof(out)); 719 if (err) { 720 mlx5_core_err(dev, "Failed %s, port %u, err - %d", 721 mlx5_command_str(MLX5_CMD_OP_DELETE_VXLAN_UDP_DPORT), 722 port, err); 723 } 724 725 return err; 726} 727 728int mlx5_query_wol(struct mlx5_core_dev *dev, u8 *wol_mode) 729{ 730 u32 in[MLX5_ST_SZ_DW(query_wol_rol_in)]; 731 u32 out[MLX5_ST_SZ_DW(query_wol_rol_out)]; 732 int err; 733 734 memset(in, 0, sizeof(in)); 735 memset(out, 0, sizeof(out)); 736 737 MLX5_SET(query_wol_rol_in, in, opcode, MLX5_CMD_OP_QUERY_WOL_ROL); 738 739 err = mlx5_cmd_exec_check_status(dev, in, sizeof(in), out, sizeof(out)); 740 741 if (!err) 742 *wol_mode = MLX5_GET(query_wol_rol_out, out, wol_mode); 743 744 return err; 745} 746EXPORT_SYMBOL_GPL(mlx5_query_wol); 747 748int mlx5_query_port_cong_status(struct mlx5_core_dev *mdev, int protocol, 749 int priority, int *is_enable) 750{ 751 u32 in[MLX5_ST_SZ_DW(query_cong_status_in)]; 752 u32 out[MLX5_ST_SZ_DW(query_cong_status_out)]; 753 int err; 754 755 memset(in, 0, sizeof(in)); 756 memset(out, 0, sizeof(out)); 757 758 *is_enable = 0; 759 760 MLX5_SET(query_cong_status_in, in, opcode, 761 MLX5_CMD_OP_QUERY_CONG_STATUS); 762 MLX5_SET(query_cong_status_in, in, cong_protocol, protocol); 763 MLX5_SET(query_cong_status_in, in, priority, priority); 764 765 err = mlx5_cmd_exec_check_status(mdev, in, sizeof(in), 766 out, sizeof(out)); 767 if (!err) 768 *is_enable = MLX5_GET(query_cong_status_out, out, enable); 769 return err; 770} 771 772int mlx5_modify_port_cong_status(struct mlx5_core_dev *mdev, int protocol, 773 int priority, int enable) 774{ 775 u32 in[MLX5_ST_SZ_DW(modify_cong_status_in)]; 776 u32 out[MLX5_ST_SZ_DW(modify_cong_status_out)]; 777 778 memset(in, 0, sizeof(in)); 779 memset(out, 0, sizeof(out)); 780 781 MLX5_SET(modify_cong_status_in, in, opcode, 782 MLX5_CMD_OP_MODIFY_CONG_STATUS); 783 MLX5_SET(modify_cong_status_in, in, cong_protocol, protocol); 784 MLX5_SET(modify_cong_status_in, in, priority, priority); 785 MLX5_SET(modify_cong_status_in, in, enable, enable); 786 787 return mlx5_cmd_exec_check_status(mdev, in, sizeof(in), 788 out, sizeof(out)); 789} 790 791int mlx5_query_port_cong_params(struct mlx5_core_dev *mdev, int protocol, 792 void *out, int out_size) 793{ 794 u32 in[MLX5_ST_SZ_DW(query_cong_params_in)]; 795 796 memset(in, 0, sizeof(in)); 797 798 MLX5_SET(query_cong_params_in, in, opcode, 799 MLX5_CMD_OP_QUERY_CONG_PARAMS); 800 MLX5_SET(query_cong_params_in, in, cong_protocol, protocol); 801 802 return mlx5_cmd_exec_check_status(mdev, in, sizeof(in), 803 out, out_size); 804} 805 806int mlx5_modify_port_cong_params(struct mlx5_core_dev *mdev, 807 void *in, int in_size) 808{ 809 u32 out[MLX5_ST_SZ_DW(modify_cong_params_out)]; 810 811 memset(out, 0, sizeof(out)); 812 813 MLX5_SET(modify_cong_params_in, in, opcode, 814 MLX5_CMD_OP_MODIFY_CONG_PARAMS); 815 816 return mlx5_cmd_exec_check_status(mdev, in, in_size, out, sizeof(out)); 817} 818 819int mlx5_query_port_cong_statistics(struct mlx5_core_dev *mdev, int clear, 820 void *out, int out_size) 821{ 822 u32 in[MLX5_ST_SZ_DW(query_cong_statistics_in)]; 823 824 memset(in, 0, sizeof(in)); 825 826 MLX5_SET(query_cong_statistics_in, in, opcode, 827 MLX5_CMD_OP_QUERY_CONG_STATISTICS); 828 MLX5_SET(query_cong_statistics_in, in, clear, clear); 829 830 return mlx5_cmd_exec_check_status(mdev, in, sizeof(in), 831 out, out_size); 832} 833 834int mlx5_set_diagnostics(struct mlx5_core_dev *mdev, void *in, int in_size) 835{ 836 u32 out[MLX5_ST_SZ_DW(set_diagnostics_out)]; 837 838 memset(out, 0, sizeof(out)); 839 840 MLX5_SET(set_diagnostics_in, in, opcode, MLX5_CMD_OP_SET_DIAGNOSTICS); 841 842 return mlx5_cmd_exec_check_status(mdev, in, in_size, out, sizeof(out)); 843} 844 845int mlx5_query_diagnostics(struct mlx5_core_dev *mdev, u8 num_of_samples, 846 u16 sample_index, void *out, int out_size) 847{ 848 u32 in[MLX5_ST_SZ_DW(query_diagnostics_in)]; 849 850 memset(in, 0, sizeof(in)); 851 852 MLX5_SET(query_diagnostics_in, in, opcode, 853 MLX5_CMD_OP_QUERY_DIAGNOSTICS); 854 MLX5_SET(query_diagnostics_in, in, num_of_samples, num_of_samples); 855 MLX5_SET(query_diagnostics_in, in, sample_index, sample_index); 856 857 return mlx5_cmd_exec_check_status(mdev, in, sizeof(in), out, out_size); 858} 859