mlx5_port.c revision 329207
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 329207 2018-02-13 15:09:03Z 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_query_dropless_mode(struct mlx5_core_dev *dev, u16 *timeout) 463{ 464 u32 in[MLX5_ST_SZ_DW(query_delay_drop_params_in)]; 465 u32 out[MLX5_ST_SZ_DW(query_delay_drop_params_out)]; 466 int err = 0; 467 468 memset(in, 0, sizeof(in)); 469 memset(out, 0, sizeof(out)); 470 471 MLX5_SET(query_delay_drop_params_in, in, opcode, 472 MLX5_CMD_OP_QUERY_DELAY_DROP_PARAMS); 473 474 err = mlx5_cmd_exec_check_status(dev, in, sizeof(in), out, sizeof(out)); 475 if (err) 476 return err; 477 478 *timeout = MLX5_GET(query_delay_drop_params_out, out, 479 delay_drop_timeout); 480 481 return 0; 482} 483EXPORT_SYMBOL_GPL(mlx5_query_dropless_mode); 484 485int mlx5_set_dropless_mode(struct mlx5_core_dev *dev, u16 timeout) 486{ 487 u32 in[MLX5_ST_SZ_DW(set_delay_drop_params_in)]; 488 u32 out[MLX5_ST_SZ_DW(set_delay_drop_params_out)]; 489 490 memset(in, 0, sizeof(in)); 491 memset(out, 0, sizeof(out)); 492 493 MLX5_SET(set_delay_drop_params_in, in, opcode, 494 MLX5_CMD_OP_SET_DELAY_DROP_PARAMS); 495 MLX5_SET(set_delay_drop_params_in, in, delay_drop_timeout, timeout); 496 497 return mlx5_cmd_exec_check_status(dev, in, sizeof(in), 498 out, sizeof(out)); 499} 500EXPORT_SYMBOL_GPL(mlx5_set_dropless_mode); 501 502int mlx5_core_access_pvlc(struct mlx5_core_dev *dev, 503 struct mlx5_pvlc_reg *pvlc, int write) 504{ 505 int sz = MLX5_ST_SZ_BYTES(pvlc_reg); 506 u8 in[MLX5_ST_SZ_BYTES(pvlc_reg)]; 507 u8 out[MLX5_ST_SZ_BYTES(pvlc_reg)]; 508 int err; 509 510 memset(out, 0, sizeof(out)); 511 memset(in, 0, sizeof(in)); 512 513 MLX5_SET(pvlc_reg, in, local_port, pvlc->local_port); 514 if (write) 515 MLX5_SET(pvlc_reg, in, vl_admin, pvlc->vl_admin); 516 517 err = mlx5_core_access_reg(dev, in, sz, out, sz, MLX5_REG_PVLC, 0, 518 !!write); 519 if (err) 520 return err; 521 522 if (!write) { 523 pvlc->local_port = MLX5_GET(pvlc_reg, out, local_port); 524 pvlc->vl_hw_cap = MLX5_GET(pvlc_reg, out, vl_hw_cap); 525 pvlc->vl_admin = MLX5_GET(pvlc_reg, out, vl_admin); 526 pvlc->vl_operational = MLX5_GET(pvlc_reg, out, vl_operational); 527 } 528 529 return 0; 530} 531EXPORT_SYMBOL_GPL(mlx5_core_access_pvlc); 532 533int mlx5_core_access_ptys(struct mlx5_core_dev *dev, 534 struct mlx5_ptys_reg *ptys, int write) 535{ 536 int sz = MLX5_ST_SZ_BYTES(ptys_reg); 537 void *out = NULL; 538 void *in = NULL; 539 int err; 540 541 in = mlx5_vzalloc(sz); 542 if (!in) 543 return -ENOMEM; 544 545 out = mlx5_vzalloc(sz); 546 if (!out) { 547 kfree(in); 548 return -ENOMEM; 549 } 550 551 MLX5_SET(ptys_reg, in, local_port, ptys->local_port); 552 MLX5_SET(ptys_reg, in, proto_mask, ptys->proto_mask); 553 if (write) { 554 MLX5_SET(ptys_reg, in, eth_proto_capability, 555 ptys->eth_proto_cap); 556 MLX5_SET(ptys_reg, in, ib_link_width_capability, 557 ptys->ib_link_width_cap); 558 MLX5_SET(ptys_reg, in, ib_proto_capability, 559 ptys->ib_proto_cap); 560 MLX5_SET(ptys_reg, in, eth_proto_admin, ptys->eth_proto_admin); 561 MLX5_SET(ptys_reg, in, ib_link_width_admin, 562 ptys->ib_link_width_admin); 563 MLX5_SET(ptys_reg, in, ib_proto_admin, ptys->ib_proto_admin); 564 MLX5_SET(ptys_reg, in, eth_proto_oper, ptys->eth_proto_oper); 565 MLX5_SET(ptys_reg, in, ib_link_width_oper, 566 ptys->ib_link_width_oper); 567 MLX5_SET(ptys_reg, in, ib_proto_oper, ptys->ib_proto_oper); 568 MLX5_SET(ptys_reg, in, eth_proto_lp_advertise, 569 ptys->eth_proto_lp_advertise); 570 } 571 572 err = mlx5_core_access_reg(dev, in, sz, out, sz, MLX5_REG_PTYS, 0, 573 !!write); 574 if (err) 575 goto out; 576 577 if (!write) { 578 ptys->local_port = MLX5_GET(ptys_reg, out, local_port); 579 ptys->proto_mask = MLX5_GET(ptys_reg, out, proto_mask); 580 ptys->eth_proto_cap = MLX5_GET(ptys_reg, out, 581 eth_proto_capability); 582 ptys->ib_link_width_cap = MLX5_GET(ptys_reg, out, 583 ib_link_width_capability); 584 ptys->ib_proto_cap = MLX5_GET(ptys_reg, out, 585 ib_proto_capability); 586 ptys->eth_proto_admin = MLX5_GET(ptys_reg, out, 587 eth_proto_admin); 588 ptys->ib_link_width_admin = MLX5_GET(ptys_reg, out, 589 ib_link_width_admin); 590 ptys->ib_proto_admin = MLX5_GET(ptys_reg, out, ib_proto_admin); 591 ptys->eth_proto_oper = MLX5_GET(ptys_reg, out, eth_proto_oper); 592 ptys->ib_link_width_oper = MLX5_GET(ptys_reg, out, 593 ib_link_width_oper); 594 ptys->ib_proto_oper = MLX5_GET(ptys_reg, out, ib_proto_oper); 595 ptys->eth_proto_lp_advertise = MLX5_GET(ptys_reg, out, 596 eth_proto_lp_advertise); 597 } 598 599out: 600 kvfree(in); 601 kvfree(out); 602 return err; 603} 604EXPORT_SYMBOL_GPL(mlx5_core_access_ptys); 605 606static int mtu_to_ib_mtu(int mtu) 607{ 608 switch (mtu) { 609 case 256: return 1; 610 case 512: return 2; 611 case 1024: return 3; 612 case 2048: return 4; 613 case 4096: return 5; 614 default: 615 printf("mlx5_core: WARN: ""invalid mtu\n"); 616 return -1; 617 } 618} 619 620int mlx5_core_access_pmtu(struct mlx5_core_dev *dev, 621 struct mlx5_pmtu_reg *pmtu, int write) 622{ 623 int sz = MLX5_ST_SZ_BYTES(pmtu_reg); 624 void *out = NULL; 625 void *in = NULL; 626 int err; 627 628 in = mlx5_vzalloc(sz); 629 if (!in) 630 return -ENOMEM; 631 632 out = mlx5_vzalloc(sz); 633 if (!out) { 634 kfree(in); 635 return -ENOMEM; 636 } 637 638 MLX5_SET(pmtu_reg, in, local_port, pmtu->local_port); 639 if (write) 640 MLX5_SET(pmtu_reg, in, admin_mtu, pmtu->admin_mtu); 641 642 err = mlx5_core_access_reg(dev, in, sz, out, sz, MLX5_REG_PMTU, 0, 643 !!write); 644 if (err) 645 goto out; 646 647 if (!write) { 648 pmtu->local_port = MLX5_GET(pmtu_reg, out, local_port); 649 pmtu->max_mtu = mtu_to_ib_mtu(MLX5_GET(pmtu_reg, out, 650 max_mtu)); 651 pmtu->admin_mtu = mtu_to_ib_mtu(MLX5_GET(pmtu_reg, out, 652 admin_mtu)); 653 pmtu->oper_mtu = mtu_to_ib_mtu(MLX5_GET(pmtu_reg, out, 654 oper_mtu)); 655 } 656 657out: 658 kvfree(in); 659 kvfree(out); 660 return err; 661} 662EXPORT_SYMBOL_GPL(mlx5_core_access_pmtu); 663 664int mlx5_query_module_num(struct mlx5_core_dev *dev, int *module_num) 665{ 666 u32 in[MLX5_ST_SZ_DW(pmlp_reg)]; 667 u32 out[MLX5_ST_SZ_DW(pmlp_reg)]; 668 int lane = 0; 669 int err; 670 671 memset(in, 0, sizeof(in)); 672 673 MLX5_SET(pmlp_reg, in, local_port, 1); 674 675 err = mlx5_core_access_reg(dev, in, sizeof(in), out, 676 sizeof(out), MLX5_REG_PMLP, 0, 0); 677 if (err) 678 return err; 679 680 lane = MLX5_GET(pmlp_reg, out, lane0_module_mapping); 681 *module_num = lane & MLX5_EEPROM_IDENTIFIER_BYTE_MASK; 682 683 return 0; 684} 685EXPORT_SYMBOL_GPL(mlx5_query_module_num); 686 687int mlx5_query_eeprom(struct mlx5_core_dev *dev, 688 int i2c_addr, int page_num, int device_addr, 689 int size, int module_num, u32 *data, int *size_read) 690{ 691 u32 in[MLX5_ST_SZ_DW(mcia_reg)]; 692 u32 out[MLX5_ST_SZ_DW(mcia_reg)]; 693 u32 *ptr = (u32 *)MLX5_ADDR_OF(mcia_reg, out, dword_0); 694 int status; 695 int err; 696 697 memset(in, 0, sizeof(in)); 698 size = min_t(int, size, MLX5_EEPROM_MAX_BYTES); 699 700 MLX5_SET(mcia_reg, in, l, 0); 701 MLX5_SET(mcia_reg, in, module, module_num); 702 MLX5_SET(mcia_reg, in, i2c_device_address, i2c_addr); 703 MLX5_SET(mcia_reg, in, page_number, page_num); 704 MLX5_SET(mcia_reg, in, device_address, device_addr); 705 MLX5_SET(mcia_reg, in, size, size); 706 707 err = mlx5_core_access_reg(dev, in, sizeof(in), out, 708 sizeof(out), MLX5_REG_MCIA, 0, 0); 709 if (err) 710 return err; 711 712 status = MLX5_GET(mcia_reg, out, status); 713 if (status) 714 return status; 715 716 memcpy(data, ptr, size); 717 *size_read = size; 718 return 0; 719} 720EXPORT_SYMBOL_GPL(mlx5_query_eeprom); 721 722int mlx5_vxlan_udp_port_add(struct mlx5_core_dev *dev, u16 port) 723{ 724 u32 in[MLX5_ST_SZ_DW(add_vxlan_udp_dport_in)]; 725 u32 out[MLX5_ST_SZ_DW(add_vxlan_udp_dport_out)]; 726 int err; 727 728 memset(in, 0, sizeof(in)); 729 memset(out, 0, sizeof(out)); 730 731 MLX5_SET(add_vxlan_udp_dport_in, in, opcode, 732 MLX5_CMD_OP_ADD_VXLAN_UDP_DPORT); 733 MLX5_SET(add_vxlan_udp_dport_in, in, vxlan_udp_port, port); 734 735 err = mlx5_cmd_exec_check_status(dev, in, sizeof(in), out, sizeof(out)); 736 if (err) { 737 mlx5_core_err(dev, "Failed %s, port %u, err - %d", 738 mlx5_command_str(MLX5_CMD_OP_ADD_VXLAN_UDP_DPORT), 739 port, err); 740 } 741 742 return err; 743} 744 745int mlx5_vxlan_udp_port_delete(struct mlx5_core_dev *dev, u16 port) 746{ 747 u32 in[MLX5_ST_SZ_DW(delete_vxlan_udp_dport_in)]; 748 u32 out[MLX5_ST_SZ_DW(delete_vxlan_udp_dport_out)]; 749 int err; 750 751 memset(in, 0, sizeof(in)); 752 memset(out, 0, sizeof(out)); 753 754 MLX5_SET(delete_vxlan_udp_dport_in, in, opcode, 755 MLX5_CMD_OP_DELETE_VXLAN_UDP_DPORT); 756 MLX5_SET(delete_vxlan_udp_dport_in, in, vxlan_udp_port, port); 757 758 err = mlx5_cmd_exec_check_status(dev, in, sizeof(in), out, sizeof(out)); 759 if (err) { 760 mlx5_core_err(dev, "Failed %s, port %u, err - %d", 761 mlx5_command_str(MLX5_CMD_OP_DELETE_VXLAN_UDP_DPORT), 762 port, err); 763 } 764 765 return err; 766} 767 768int mlx5_query_wol(struct mlx5_core_dev *dev, u8 *wol_mode) 769{ 770 u32 in[MLX5_ST_SZ_DW(query_wol_rol_in)]; 771 u32 out[MLX5_ST_SZ_DW(query_wol_rol_out)]; 772 int err; 773 774 memset(in, 0, sizeof(in)); 775 memset(out, 0, sizeof(out)); 776 777 MLX5_SET(query_wol_rol_in, in, opcode, MLX5_CMD_OP_QUERY_WOL_ROL); 778 779 err = mlx5_cmd_exec_check_status(dev, in, sizeof(in), out, sizeof(out)); 780 781 if (!err) 782 *wol_mode = MLX5_GET(query_wol_rol_out, out, wol_mode); 783 784 return err; 785} 786EXPORT_SYMBOL_GPL(mlx5_query_wol); 787 788int mlx5_query_port_cong_status(struct mlx5_core_dev *mdev, int protocol, 789 int priority, int *is_enable) 790{ 791 u32 in[MLX5_ST_SZ_DW(query_cong_status_in)]; 792 u32 out[MLX5_ST_SZ_DW(query_cong_status_out)]; 793 int err; 794 795 memset(in, 0, sizeof(in)); 796 memset(out, 0, sizeof(out)); 797 798 *is_enable = 0; 799 800 MLX5_SET(query_cong_status_in, in, opcode, 801 MLX5_CMD_OP_QUERY_CONG_STATUS); 802 MLX5_SET(query_cong_status_in, in, cong_protocol, protocol); 803 MLX5_SET(query_cong_status_in, in, priority, priority); 804 805 err = mlx5_cmd_exec_check_status(mdev, in, sizeof(in), 806 out, sizeof(out)); 807 if (!err) 808 *is_enable = MLX5_GET(query_cong_status_out, out, enable); 809 return err; 810} 811 812int mlx5_modify_port_cong_status(struct mlx5_core_dev *mdev, int protocol, 813 int priority, int enable) 814{ 815 u32 in[MLX5_ST_SZ_DW(modify_cong_status_in)]; 816 u32 out[MLX5_ST_SZ_DW(modify_cong_status_out)]; 817 818 memset(in, 0, sizeof(in)); 819 memset(out, 0, sizeof(out)); 820 821 MLX5_SET(modify_cong_status_in, in, opcode, 822 MLX5_CMD_OP_MODIFY_CONG_STATUS); 823 MLX5_SET(modify_cong_status_in, in, cong_protocol, protocol); 824 MLX5_SET(modify_cong_status_in, in, priority, priority); 825 MLX5_SET(modify_cong_status_in, in, enable, enable); 826 827 return mlx5_cmd_exec_check_status(mdev, in, sizeof(in), 828 out, sizeof(out)); 829} 830 831int mlx5_query_port_cong_params(struct mlx5_core_dev *mdev, int protocol, 832 void *out, int out_size) 833{ 834 u32 in[MLX5_ST_SZ_DW(query_cong_params_in)]; 835 836 memset(in, 0, sizeof(in)); 837 838 MLX5_SET(query_cong_params_in, in, opcode, 839 MLX5_CMD_OP_QUERY_CONG_PARAMS); 840 MLX5_SET(query_cong_params_in, in, cong_protocol, protocol); 841 842 return mlx5_cmd_exec_check_status(mdev, in, sizeof(in), 843 out, out_size); 844} 845 846int mlx5_modify_port_cong_params(struct mlx5_core_dev *mdev, 847 void *in, int in_size) 848{ 849 u32 out[MLX5_ST_SZ_DW(modify_cong_params_out)]; 850 851 memset(out, 0, sizeof(out)); 852 853 MLX5_SET(modify_cong_params_in, in, opcode, 854 MLX5_CMD_OP_MODIFY_CONG_PARAMS); 855 856 return mlx5_cmd_exec_check_status(mdev, in, in_size, out, sizeof(out)); 857} 858 859int mlx5_query_port_cong_statistics(struct mlx5_core_dev *mdev, int clear, 860 void *out, int out_size) 861{ 862 u32 in[MLX5_ST_SZ_DW(query_cong_statistics_in)]; 863 864 memset(in, 0, sizeof(in)); 865 866 MLX5_SET(query_cong_statistics_in, in, opcode, 867 MLX5_CMD_OP_QUERY_CONG_STATISTICS); 868 MLX5_SET(query_cong_statistics_in, in, clear, clear); 869 870 return mlx5_cmd_exec_check_status(mdev, in, sizeof(in), 871 out, out_size); 872} 873 874int mlx5_set_diagnostic_params(struct mlx5_core_dev *mdev, void *in, 875 int in_size) 876{ 877 u32 out[MLX5_ST_SZ_DW(set_diagnostic_params_out)]; 878 879 memset(out, 0, sizeof(out)); 880 881 MLX5_SET(set_diagnostic_params_in, in, opcode, 882 MLX5_CMD_OP_SET_DIAGNOSTICS); 883 884 return mlx5_cmd_exec_check_status(mdev, in, in_size, out, sizeof(out)); 885} 886 887int mlx5_query_diagnostic_counters(struct mlx5_core_dev *mdev, 888 u8 num_of_samples, u16 sample_index, 889 void *out, int out_size) 890{ 891 u32 in[MLX5_ST_SZ_DW(query_diagnostic_counters_in)]; 892 893 memset(in, 0, sizeof(in)); 894 895 MLX5_SET(query_diagnostic_counters_in, in, opcode, 896 MLX5_CMD_OP_QUERY_DIAGNOSTICS); 897 MLX5_SET(query_diagnostic_counters_in, in, num_of_samples, 898 num_of_samples); 899 MLX5_SET(query_diagnostic_counters_in, in, sample_index, sample_index); 900 901 return mlx5_cmd_exec_check_status(mdev, in, sizeof(in), out, out_size); 902} 903