mlx5_vport.c revision 341972
1284345Ssjg/*- 2284345Ssjg * Copyright (c) 2013-2017, Mellanox Technologies, Ltd. All rights reserved. 3284345Ssjg * 4284345Ssjg * Redistribution and use in source and binary forms, with or without 5284345Ssjg * modification, are permitted provided that the following conditions 6284345Ssjg * are met: 7284345Ssjg * 1. Redistributions of source code must retain the above copyright 8284345Ssjg * notice, this list of conditions and the following disclaimer. 9284345Ssjg * 2. Redistributions in binary form must reproduce the above copyright 10284345Ssjg * notice, this list of conditions and the following disclaimer in the 11284345Ssjg * 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_vport.c 341972 2018-12-12 13:00:56Z hselasky $ 26 */ 27 28#include <linux/etherdevice.h> 29#include <dev/mlx5/driver.h> 30#include <dev/mlx5/vport.h> 31#include "mlx5_core.h" 32 33static int mlx5_modify_nic_vport_context(struct mlx5_core_dev *mdev, void *in, 34 int inlen); 35 36static int _mlx5_query_vport_state(struct mlx5_core_dev *mdev, u8 opmod, 37 u16 vport, u32 *out, int outlen) 38{ 39 int err; 40 u32 in[MLX5_ST_SZ_DW(query_vport_state_in)] = {0}; 41 42 MLX5_SET(query_vport_state_in, in, opcode, 43 MLX5_CMD_OP_QUERY_VPORT_STATE); 44 MLX5_SET(query_vport_state_in, in, op_mod, opmod); 45 MLX5_SET(query_vport_state_in, in, vport_number, vport); 46 if (vport) 47 MLX5_SET(query_vport_state_in, in, other_vport, 1); 48 49 err = mlx5_cmd_exec(mdev, in, sizeof(in), out, outlen); 50 if (err) 51 mlx5_core_warn(mdev, "MLX5_CMD_OP_QUERY_VPORT_STATE failed\n"); 52 53 return err; 54} 55 56u8 mlx5_query_vport_state(struct mlx5_core_dev *mdev, u8 opmod, u16 vport) 57{ 58 u32 out[MLX5_ST_SZ_DW(query_vport_state_out)] = {0}; 59 60 _mlx5_query_vport_state(mdev, opmod, vport, out, sizeof(out)); 61 62 return MLX5_GET(query_vport_state_out, out, state); 63} 64EXPORT_SYMBOL_GPL(mlx5_query_vport_state); 65 66u8 mlx5_query_vport_admin_state(struct mlx5_core_dev *mdev, u8 opmod, u16 vport) 67{ 68 u32 out[MLX5_ST_SZ_DW(query_vport_state_out)] = {0}; 69 70 _mlx5_query_vport_state(mdev, opmod, vport, out, sizeof(out)); 71 72 return MLX5_GET(query_vport_state_out, out, admin_state); 73} 74EXPORT_SYMBOL(mlx5_query_vport_admin_state); 75 76int mlx5_modify_vport_admin_state(struct mlx5_core_dev *mdev, u8 opmod, 77 u16 vport, u8 state) 78{ 79 u32 in[MLX5_ST_SZ_DW(modify_vport_state_in)] = {0}; 80 u32 out[MLX5_ST_SZ_DW(modify_vport_state_out)] = {0}; 81 int err; 82 83 MLX5_SET(modify_vport_state_in, in, opcode, 84 MLX5_CMD_OP_MODIFY_VPORT_STATE); 85 MLX5_SET(modify_vport_state_in, in, op_mod, opmod); 86 MLX5_SET(modify_vport_state_in, in, vport_number, vport); 87 88 if (vport) 89 MLX5_SET(modify_vport_state_in, in, other_vport, 1); 90 91 MLX5_SET(modify_vport_state_in, in, admin_state, state); 92 93 err = mlx5_cmd_exec(mdev, in, sizeof(in), out, sizeof(out)); 94 if (err) 95 mlx5_core_warn(mdev, "MLX5_CMD_OP_MODIFY_VPORT_STATE failed\n"); 96 97 return err; 98} 99EXPORT_SYMBOL(mlx5_modify_vport_admin_state); 100 101static int mlx5_query_nic_vport_context(struct mlx5_core_dev *mdev, u16 vport, 102 u32 *out, int outlen) 103{ 104 u32 in[MLX5_ST_SZ_DW(query_nic_vport_context_in)] = {0}; 105 106 MLX5_SET(query_nic_vport_context_in, in, opcode, 107 MLX5_CMD_OP_QUERY_NIC_VPORT_CONTEXT); 108 109 MLX5_SET(query_nic_vport_context_in, in, vport_number, vport); 110 if (vport) 111 MLX5_SET(query_nic_vport_context_in, in, other_vport, 1); 112 113 return mlx5_cmd_exec(mdev, in, sizeof(in), out, outlen); 114} 115 116static u32 mlx5_vport_max_q_counter_allocator(struct mlx5_core_dev *mdev, 117 int client_id) 118{ 119 switch (client_id) { 120 case MLX5_INTERFACE_PROTOCOL_IB: 121 return (MLX5_CAP_GEN(mdev, max_qp_cnt) - 122 MLX5_QCOUNTER_SETS_NETDEV); 123 case MLX5_INTERFACE_PROTOCOL_ETH: 124 return MLX5_QCOUNTER_SETS_NETDEV; 125 default: 126 mlx5_core_warn(mdev, "Unknown Client: %d\n", client_id); 127 return 0; 128 } 129} 130 131int mlx5_vport_alloc_q_counter(struct mlx5_core_dev *mdev, 132 int client_id, u16 *counter_set_id) 133{ 134 u32 in[MLX5_ST_SZ_DW(alloc_q_counter_in)] = {0}; 135 u32 out[MLX5_ST_SZ_DW(alloc_q_counter_out)] = {0}; 136 int err; 137 138 if (mdev->num_q_counter_allocated[client_id] > 139 mlx5_vport_max_q_counter_allocator(mdev, client_id)) 140 return -EINVAL; 141 142 MLX5_SET(alloc_q_counter_in, in, opcode, 143 MLX5_CMD_OP_ALLOC_Q_COUNTER); 144 145 err = mlx5_cmd_exec(mdev, in, sizeof(in), out, sizeof(out)); 146 147 if (!err) 148 *counter_set_id = MLX5_GET(alloc_q_counter_out, out, 149 counter_set_id); 150 151 mdev->num_q_counter_allocated[client_id]++; 152 153 return err; 154} 155 156int mlx5_vport_dealloc_q_counter(struct mlx5_core_dev *mdev, 157 int client_id, u16 counter_set_id) 158{ 159 u32 in[MLX5_ST_SZ_DW(dealloc_q_counter_in)] = {0}; 160 u32 out[MLX5_ST_SZ_DW(dealloc_q_counter_out)] = {0}; 161 int err; 162 163 if (mdev->num_q_counter_allocated[client_id] <= 0) 164 return -EINVAL; 165 166 MLX5_SET(dealloc_q_counter_in, in, opcode, 167 MLX5_CMD_OP_DEALLOC_Q_COUNTER); 168 MLX5_SET(dealloc_q_counter_in, in, counter_set_id, 169 counter_set_id); 170 171 err = mlx5_cmd_exec(mdev, in, sizeof(in), out, sizeof(out)); 172 173 mdev->num_q_counter_allocated[client_id]--; 174 175 return err; 176} 177 178int mlx5_vport_query_q_counter(struct mlx5_core_dev *mdev, 179 u16 counter_set_id, 180 int reset, 181 void *out, 182 int out_size) 183{ 184 u32 in[MLX5_ST_SZ_DW(query_q_counter_in)] = {0}; 185 186 MLX5_SET(query_q_counter_in, in, opcode, MLX5_CMD_OP_QUERY_Q_COUNTER); 187 MLX5_SET(query_q_counter_in, in, clear, reset); 188 MLX5_SET(query_q_counter_in, in, counter_set_id, counter_set_id); 189 190 return mlx5_cmd_exec(mdev, in, sizeof(in), out, out_size); 191} 192 193int mlx5_vport_query_out_of_rx_buffer(struct mlx5_core_dev *mdev, 194 u16 counter_set_id, 195 u32 *out_of_rx_buffer) 196{ 197 u32 out[MLX5_ST_SZ_DW(query_q_counter_out)] = {0}; 198 int err; 199 200 err = mlx5_vport_query_q_counter(mdev, counter_set_id, 0, out, 201 sizeof(out)); 202 203 if (err) 204 return err; 205 206 *out_of_rx_buffer = MLX5_GET(query_q_counter_out, out, 207 out_of_buffer); 208 return err; 209} 210 211int mlx5_query_nic_vport_min_inline(struct mlx5_core_dev *mdev, 212 u16 vport, u8 *min_inline) 213{ 214 u32 out[MLX5_ST_SZ_DW(query_nic_vport_context_out)] = {0}; 215 int err; 216 217 err = mlx5_query_nic_vport_context(mdev, vport, out, sizeof(out)); 218 if (!err) 219 *min_inline = MLX5_GET(query_nic_vport_context_out, out, 220 nic_vport_context.min_wqe_inline_mode); 221 return err; 222} 223EXPORT_SYMBOL_GPL(mlx5_query_nic_vport_min_inline); 224 225int mlx5_query_min_inline(struct mlx5_core_dev *mdev, 226 u8 *min_inline_mode) 227{ 228 int err; 229 230 switch (MLX5_CAP_ETH(mdev, wqe_inline_mode)) { 231 case MLX5_CAP_INLINE_MODE_L2: 232 *min_inline_mode = MLX5_INLINE_MODE_L2; 233 err = 0; 234 break; 235 case MLX5_CAP_INLINE_MODE_VPORT_CONTEXT: 236 err = mlx5_query_nic_vport_min_inline(mdev, 0, min_inline_mode); 237 break; 238 case MLX5_CAP_INLINE_MODE_NOT_REQUIRED: 239 *min_inline_mode = MLX5_INLINE_MODE_NONE; 240 err = 0; 241 break; 242 default: 243 err = -EINVAL; 244 break; 245 } 246 return err; 247} 248EXPORT_SYMBOL_GPL(mlx5_query_min_inline); 249 250int mlx5_modify_nic_vport_min_inline(struct mlx5_core_dev *mdev, 251 u16 vport, u8 min_inline) 252{ 253 u32 in[MLX5_ST_SZ_DW(modify_nic_vport_context_in)] = {0}; 254 int inlen = MLX5_ST_SZ_BYTES(modify_nic_vport_context_in); 255 void *nic_vport_ctx; 256 257 MLX5_SET(modify_nic_vport_context_in, in, 258 field_select.min_wqe_inline_mode, 1); 259 MLX5_SET(modify_nic_vport_context_in, in, vport_number, vport); 260 MLX5_SET(modify_nic_vport_context_in, in, other_vport, 1); 261 262 nic_vport_ctx = MLX5_ADDR_OF(modify_nic_vport_context_in, 263 in, nic_vport_context); 264 MLX5_SET(nic_vport_context, nic_vport_ctx, 265 min_wqe_inline_mode, min_inline); 266 267 return mlx5_modify_nic_vport_context(mdev, in, inlen); 268} 269EXPORT_SYMBOL_GPL(mlx5_modify_nic_vport_min_inline); 270 271int mlx5_query_nic_vport_mac_address(struct mlx5_core_dev *mdev, 272 u16 vport, u8 *addr) 273{ 274 u32 *out; 275 int outlen = MLX5_ST_SZ_BYTES(query_nic_vport_context_out); 276 u8 *out_addr; 277 int err; 278 279 out = mlx5_vzalloc(outlen); 280 if (!out) 281 return -ENOMEM; 282 283 out_addr = MLX5_ADDR_OF(query_nic_vport_context_out, out, 284 nic_vport_context.permanent_address); 285 286 err = mlx5_query_nic_vport_context(mdev, vport, out, outlen); 287 if (err) 288 goto out; 289 290 ether_addr_copy(addr, &out_addr[2]); 291 292out: 293 kvfree(out); 294 return err; 295} 296EXPORT_SYMBOL_GPL(mlx5_query_nic_vport_mac_address); 297 298int mlx5_modify_nic_vport_mac_address(struct mlx5_core_dev *mdev, 299 u16 vport, u8 *addr) 300{ 301 void *in; 302 int inlen = MLX5_ST_SZ_BYTES(modify_nic_vport_context_in); 303 int err; 304 void *nic_vport_ctx; 305 u8 *perm_mac; 306 307 in = mlx5_vzalloc(inlen); 308 if (!in) { 309 mlx5_core_warn(mdev, "failed to allocate inbox\n"); 310 return -ENOMEM; 311 } 312 313 MLX5_SET(modify_nic_vport_context_in, in, 314 field_select.permanent_address, 1); 315 MLX5_SET(modify_nic_vport_context_in, in, vport_number, vport); 316 317 if (vport) 318 MLX5_SET(modify_nic_vport_context_in, in, other_vport, 1); 319 320 nic_vport_ctx = MLX5_ADDR_OF(modify_nic_vport_context_in, 321 in, nic_vport_context); 322 perm_mac = MLX5_ADDR_OF(nic_vport_context, nic_vport_ctx, 323 permanent_address); 324 325 ether_addr_copy(&perm_mac[2], addr); 326 327 err = mlx5_modify_nic_vport_context(mdev, in, inlen); 328 329 kvfree(in); 330 331 return err; 332} 333EXPORT_SYMBOL(mlx5_modify_nic_vport_mac_address); 334 335int mlx5_query_nic_vport_system_image_guid(struct mlx5_core_dev *mdev, 336 u64 *system_image_guid) 337{ 338 u32 *out; 339 int outlen = MLX5_ST_SZ_BYTES(query_nic_vport_context_out); 340 int err; 341 342 out = mlx5_vzalloc(outlen); 343 if (!out) 344 return -ENOMEM; 345 346 err = mlx5_query_nic_vport_context(mdev, 0, out, outlen); 347 if (err) 348 goto out; 349 350 *system_image_guid = MLX5_GET64(query_nic_vport_context_out, out, 351 nic_vport_context.system_image_guid); 352out: 353 kvfree(out); 354 return err; 355} 356EXPORT_SYMBOL_GPL(mlx5_query_nic_vport_system_image_guid); 357 358int mlx5_query_nic_vport_node_guid(struct mlx5_core_dev *mdev, u64 *node_guid) 359{ 360 u32 *out; 361 int outlen = MLX5_ST_SZ_BYTES(query_nic_vport_context_out); 362 int err; 363 364 out = mlx5_vzalloc(outlen); 365 if (!out) 366 return -ENOMEM; 367 368 err = mlx5_query_nic_vport_context(mdev, 0, out, outlen); 369 if (err) 370 goto out; 371 372 *node_guid = MLX5_GET64(query_nic_vport_context_out, out, 373 nic_vport_context.node_guid); 374 375out: 376 kvfree(out); 377 return err; 378} 379EXPORT_SYMBOL_GPL(mlx5_query_nic_vport_node_guid); 380 381static int mlx5_query_nic_vport_port_guid(struct mlx5_core_dev *mdev, 382 u64 *port_guid) 383{ 384 u32 *out; 385 int outlen = MLX5_ST_SZ_BYTES(query_nic_vport_context_out); 386 int err; 387 388 out = mlx5_vzalloc(outlen); 389 if (!out) 390 return -ENOMEM; 391 392 err = mlx5_query_nic_vport_context(mdev, 0, out, outlen); 393 if (err) 394 goto out; 395 396 *port_guid = MLX5_GET64(query_nic_vport_context_out, out, 397 nic_vport_context.port_guid); 398 399out: 400 kvfree(out); 401 return err; 402} 403 404int mlx5_query_nic_vport_qkey_viol_cntr(struct mlx5_core_dev *mdev, 405 u16 *qkey_viol_cntr) 406{ 407 u32 *out; 408 int outlen = MLX5_ST_SZ_BYTES(query_nic_vport_context_out); 409 int err; 410 411 out = mlx5_vzalloc(outlen); 412 if (!out) 413 return -ENOMEM; 414 415 err = mlx5_query_nic_vport_context(mdev, 0, out, outlen); 416 if (err) 417 goto out; 418 419 *qkey_viol_cntr = MLX5_GET(query_nic_vport_context_out, out, 420 nic_vport_context.qkey_violation_counter); 421 422out: 423 kvfree(out); 424 return err; 425} 426EXPORT_SYMBOL_GPL(mlx5_query_nic_vport_qkey_viol_cntr); 427 428static int mlx5_modify_nic_vport_context(struct mlx5_core_dev *mdev, void *in, 429 int inlen) 430{ 431 u32 out[MLX5_ST_SZ_DW(modify_nic_vport_context_out)] = {0}; 432 433 MLX5_SET(modify_nic_vport_context_in, in, opcode, 434 MLX5_CMD_OP_MODIFY_NIC_VPORT_CONTEXT); 435 436 return mlx5_cmd_exec(mdev, in, inlen, out, sizeof(out)); 437} 438 439static int mlx5_nic_vport_enable_disable_roce(struct mlx5_core_dev *mdev, 440 int enable_disable) 441{ 442 void *in; 443 int inlen = MLX5_ST_SZ_BYTES(modify_nic_vport_context_in); 444 int err; 445 446 in = mlx5_vzalloc(inlen); 447 if (!in) { 448 mlx5_core_warn(mdev, "failed to allocate inbox\n"); 449 return -ENOMEM; 450 } 451 452 MLX5_SET(modify_nic_vport_context_in, in, field_select.roce_en, 1); 453 MLX5_SET(modify_nic_vport_context_in, in, nic_vport_context.roce_en, 454 enable_disable); 455 456 err = mlx5_modify_nic_vport_context(mdev, in, inlen); 457 458 kvfree(in); 459 460 return err; 461} 462 463int mlx5_set_nic_vport_current_mac(struct mlx5_core_dev *mdev, int vport, 464 bool other_vport, u8 *addr) 465{ 466 void *in; 467 int inlen = MLX5_ST_SZ_BYTES(modify_nic_vport_context_in) 468 + MLX5_ST_SZ_BYTES(mac_address_layout); 469 u8 *mac_layout; 470 u8 *mac_ptr; 471 int err; 472 473 in = mlx5_vzalloc(inlen); 474 if (!in) { 475 mlx5_core_warn(mdev, "failed to allocate inbox\n"); 476 return -ENOMEM; 477 } 478 479 MLX5_SET(modify_nic_vport_context_in, in, 480 opcode, MLX5_CMD_OP_MODIFY_NIC_VPORT_CONTEXT); 481 MLX5_SET(modify_nic_vport_context_in, in, 482 vport_number, vport); 483 MLX5_SET(modify_nic_vport_context_in, in, 484 other_vport, other_vport); 485 MLX5_SET(modify_nic_vport_context_in, in, 486 field_select.addresses_list, 1); 487 MLX5_SET(modify_nic_vport_context_in, in, 488 nic_vport_context.allowed_list_type, 489 MLX5_NIC_VPORT_LIST_TYPE_UC); 490 MLX5_SET(modify_nic_vport_context_in, in, 491 nic_vport_context.allowed_list_size, 1); 492 493 mac_layout = (u8 *)MLX5_ADDR_OF(modify_nic_vport_context_in, in, 494 nic_vport_context.current_uc_mac_address); 495 mac_ptr = (u8 *)MLX5_ADDR_OF(mac_address_layout, mac_layout, 496 mac_addr_47_32); 497 ether_addr_copy(mac_ptr, addr); 498 499 err = mlx5_modify_nic_vport_context(mdev, in, inlen); 500 501 kvfree(in); 502 503 return err; 504} 505EXPORT_SYMBOL_GPL(mlx5_set_nic_vport_current_mac); 506 507int mlx5_modify_nic_vport_node_guid(struct mlx5_core_dev *mdev, 508 u32 vport, u64 node_guid) 509{ 510 void *in; 511 int inlen = MLX5_ST_SZ_BYTES(modify_nic_vport_context_in); 512 int err; 513 void *nic_vport_context; 514 515 if (!vport) 516 return -EINVAL; 517 if (!MLX5_CAP_GEN(mdev, vport_group_manager)) 518 return -EPERM; 519 if (!MLX5_CAP_ESW(mdev, nic_vport_node_guid_modify)) 520 return -ENOTSUPP; 521 522 in = mlx5_vzalloc(inlen); 523 if (!in) { 524 mlx5_core_warn(mdev, "failed to allocate inbox\n"); 525 return -ENOMEM; 526 } 527 528 MLX5_SET(modify_nic_vport_context_in, in, 529 field_select.node_guid, 1); 530 MLX5_SET(modify_nic_vport_context_in, in, vport_number, vport); 531 532 MLX5_SET(modify_nic_vport_context_in, in, other_vport, 1); 533 534 nic_vport_context = MLX5_ADDR_OF(modify_nic_vport_context_in, 535 in, nic_vport_context); 536 MLX5_SET64(nic_vport_context, nic_vport_context, node_guid, node_guid); 537 538 err = mlx5_modify_nic_vport_context(mdev, in, inlen); 539 540 kvfree(in); 541 542 return err; 543} 544EXPORT_SYMBOL(mlx5_modify_nic_vport_node_guid); 545 546int mlx5_modify_nic_vport_port_guid(struct mlx5_core_dev *mdev, 547 u32 vport, u64 port_guid) 548{ 549 void *in; 550 int inlen = MLX5_ST_SZ_BYTES(modify_nic_vport_context_in); 551 int err; 552 void *nic_vport_context; 553 554 if (!vport) 555 return -EINVAL; 556 if (!MLX5_CAP_GEN(mdev, vport_group_manager)) 557 return -EPERM; 558 if (!MLX5_CAP_ESW(mdev, nic_vport_port_guid_modify)) 559 return -ENOTSUPP; 560 561 in = mlx5_vzalloc(inlen); 562 if (!in) { 563 mlx5_core_warn(mdev, "failed to allocate inbox\n"); 564 return -ENOMEM; 565 } 566 567 MLX5_SET(modify_nic_vport_context_in, in, 568 field_select.port_guid, 1); 569 MLX5_SET(modify_nic_vport_context_in, in, vport_number, vport); 570 571 MLX5_SET(modify_nic_vport_context_in, in, other_vport, 1); 572 573 nic_vport_context = MLX5_ADDR_OF(modify_nic_vport_context_in, 574 in, nic_vport_context); 575 MLX5_SET64(nic_vport_context, nic_vport_context, port_guid, port_guid); 576 577 err = mlx5_modify_nic_vport_context(mdev, in, inlen); 578 579 kvfree(in); 580 581 return err; 582} 583EXPORT_SYMBOL(mlx5_modify_nic_vport_port_guid); 584 585int mlx5_set_nic_vport_vlan_list(struct mlx5_core_dev *dev, u16 vport, 586 u16 *vlan_list, int list_len) 587{ 588 void *in, *ctx; 589 int i, err; 590 int inlen = MLX5_ST_SZ_BYTES(modify_nic_vport_context_in) 591 + MLX5_ST_SZ_BYTES(vlan_layout) * (int)list_len; 592 593 int max_list_size = 1 << MLX5_CAP_GEN_MAX(dev, log_max_vlan_list); 594 595 if (list_len > max_list_size) { 596 mlx5_core_warn(dev, "Requested list size (%d) > (%d) max_list_size\n", 597 list_len, max_list_size); 598 return -ENOSPC; 599 } 600 601 in = mlx5_vzalloc(inlen); 602 if (!in) { 603 mlx5_core_warn(dev, "failed to allocate inbox\n"); 604 return -ENOMEM; 605 } 606 607 MLX5_SET(modify_nic_vport_context_in, in, vport_number, vport); 608 if (vport) 609 MLX5_SET(modify_nic_vport_context_in, in, 610 other_vport, 1); 611 MLX5_SET(modify_nic_vport_context_in, in, 612 field_select.addresses_list, 1); 613 614 ctx = MLX5_ADDR_OF(modify_nic_vport_context_in, in, nic_vport_context); 615 616 MLX5_SET(nic_vport_context, ctx, allowed_list_type, 617 MLX5_NIC_VPORT_LIST_TYPE_VLAN); 618 MLX5_SET(nic_vport_context, ctx, allowed_list_size, list_len); 619 620 for (i = 0; i < list_len; i++) { 621 u8 *vlan_lout = MLX5_ADDR_OF(nic_vport_context, ctx, 622 current_uc_mac_address[i]); 623 MLX5_SET(vlan_layout, vlan_lout, vlan, vlan_list[i]); 624 } 625 626 err = mlx5_modify_nic_vport_context(dev, in, inlen); 627 628 kvfree(in); 629 return err; 630} 631EXPORT_SYMBOL_GPL(mlx5_set_nic_vport_vlan_list); 632 633int mlx5_set_nic_vport_mc_list(struct mlx5_core_dev *mdev, int vport, 634 u64 *addr_list, size_t addr_list_len) 635{ 636 void *in, *ctx; 637 int inlen = MLX5_ST_SZ_BYTES(modify_nic_vport_context_in) 638 + MLX5_ST_SZ_BYTES(mac_address_layout) * (int)addr_list_len; 639 int err; 640 size_t i; 641 int max_list_sz = 1 << MLX5_CAP_GEN_MAX(mdev, log_max_current_mc_list); 642 643 if ((int)addr_list_len > max_list_sz) { 644 mlx5_core_warn(mdev, "Requested list size (%d) > (%d) max_list_size\n", 645 (int)addr_list_len, max_list_sz); 646 return -ENOSPC; 647 } 648 649 in = mlx5_vzalloc(inlen); 650 if (!in) { 651 mlx5_core_warn(mdev, "failed to allocate inbox\n"); 652 return -ENOMEM; 653 } 654 655 MLX5_SET(modify_nic_vport_context_in, in, vport_number, vport); 656 if (vport) 657 MLX5_SET(modify_nic_vport_context_in, in, 658 other_vport, 1); 659 MLX5_SET(modify_nic_vport_context_in, in, 660 field_select.addresses_list, 1); 661 662 ctx = MLX5_ADDR_OF(modify_nic_vport_context_in, in, nic_vport_context); 663 664 MLX5_SET(nic_vport_context, ctx, allowed_list_type, 665 MLX5_NIC_VPORT_LIST_TYPE_MC); 666 MLX5_SET(nic_vport_context, ctx, allowed_list_size, addr_list_len); 667 668 for (i = 0; i < addr_list_len; i++) { 669 u8 *mac_lout = (u8 *)MLX5_ADDR_OF(nic_vport_context, ctx, 670 current_uc_mac_address[i]); 671 u8 *mac_ptr = (u8 *)MLX5_ADDR_OF(mac_address_layout, mac_lout, 672 mac_addr_47_32); 673 ether_addr_copy(mac_ptr, (u8 *)&addr_list[i]); 674 } 675 676 err = mlx5_modify_nic_vport_context(mdev, in, inlen); 677 678 kvfree(in); 679 680 return err; 681} 682EXPORT_SYMBOL_GPL(mlx5_set_nic_vport_mc_list); 683 684int mlx5_set_nic_vport_promisc(struct mlx5_core_dev *mdev, int vport, 685 bool promisc_mc, bool promisc_uc, 686 bool promisc_all) 687{ 688 u8 in[MLX5_ST_SZ_BYTES(modify_nic_vport_context_in)]; 689 u8 *ctx = MLX5_ADDR_OF(modify_nic_vport_context_in, in, 690 nic_vport_context); 691 692 memset(in, 0, MLX5_ST_SZ_BYTES(modify_nic_vport_context_in)); 693 694 MLX5_SET(modify_nic_vport_context_in, in, vport_number, vport); 695 if (vport) 696 MLX5_SET(modify_nic_vport_context_in, in, 697 other_vport, 1); 698 MLX5_SET(modify_nic_vport_context_in, in, field_select.promisc, 1); 699 if (promisc_mc) 700 MLX5_SET(nic_vport_context, ctx, promisc_mc, 1); 701 if (promisc_uc) 702 MLX5_SET(nic_vport_context, ctx, promisc_uc, 1); 703 if (promisc_all) 704 MLX5_SET(nic_vport_context, ctx, promisc_all, 1); 705 706 return mlx5_modify_nic_vport_context(mdev, in, sizeof(in)); 707} 708EXPORT_SYMBOL_GPL(mlx5_set_nic_vport_promisc); 709 710int mlx5_query_nic_vport_mac_list(struct mlx5_core_dev *dev, 711 u16 vport, 712 enum mlx5_list_type list_type, 713 u8 addr_list[][ETH_ALEN], 714 int *list_size) 715{ 716 u32 in[MLX5_ST_SZ_DW(query_nic_vport_context_in)] = {0}; 717 void *nic_vport_ctx; 718 int max_list_size; 719 int req_list_size; 720 int out_sz; 721 void *out; 722 int err; 723 int i; 724 725 req_list_size = *list_size; 726 727 max_list_size = (list_type == MLX5_NIC_VPORT_LIST_TYPE_UC) ? 728 1 << MLX5_CAP_GEN_MAX(dev, log_max_current_uc_list) : 729 1 << MLX5_CAP_GEN_MAX(dev, log_max_current_mc_list); 730 731 if (req_list_size > max_list_size) { 732 mlx5_core_warn(dev, "Requested list size (%d) > (%d) max_list_size\n", 733 req_list_size, max_list_size); 734 req_list_size = max_list_size; 735 } 736 737 out_sz = MLX5_ST_SZ_BYTES(modify_nic_vport_context_in) + 738 req_list_size * MLX5_ST_SZ_BYTES(mac_address_layout); 739 740 out = kzalloc(out_sz, GFP_KERNEL); 741 if (!out) 742 return -ENOMEM; 743 744 MLX5_SET(query_nic_vport_context_in, in, opcode, 745 MLX5_CMD_OP_QUERY_NIC_VPORT_CONTEXT); 746 MLX5_SET(query_nic_vport_context_in, in, allowed_list_type, list_type); 747 MLX5_SET(query_nic_vport_context_in, in, vport_number, vport); 748 749 if (vport) 750 MLX5_SET(query_nic_vport_context_in, in, other_vport, 1); 751 752 err = mlx5_cmd_exec(dev, in, sizeof(in), out, out_sz); 753 if (err) 754 goto out; 755 756 nic_vport_ctx = MLX5_ADDR_OF(query_nic_vport_context_out, out, 757 nic_vport_context); 758 req_list_size = MLX5_GET(nic_vport_context, nic_vport_ctx, 759 allowed_list_size); 760 761 *list_size = req_list_size; 762 for (i = 0; i < req_list_size; i++) { 763 u8 *mac_addr = MLX5_ADDR_OF(nic_vport_context, 764 nic_vport_ctx, 765 current_uc_mac_address[i]) + 2; 766 ether_addr_copy(addr_list[i], mac_addr); 767 } 768out: 769 kfree(out); 770 return err; 771} 772EXPORT_SYMBOL_GPL(mlx5_query_nic_vport_mac_list); 773 774int mlx5_modify_nic_vport_mac_list(struct mlx5_core_dev *dev, 775 enum mlx5_list_type list_type, 776 u8 addr_list[][ETH_ALEN], 777 int list_size) 778{ 779 u32 out[MLX5_ST_SZ_DW(modify_nic_vport_context_out)] = {0}; 780 void *nic_vport_ctx; 781 int max_list_size; 782 int in_sz; 783 void *in; 784 int err; 785 int i; 786 787 max_list_size = list_type == MLX5_NIC_VPORT_LIST_TYPE_UC ? 788 1 << MLX5_CAP_GEN(dev, log_max_current_uc_list) : 789 1 << MLX5_CAP_GEN(dev, log_max_current_mc_list); 790 791 if (list_size > max_list_size) 792 return -ENOSPC; 793 794 in_sz = MLX5_ST_SZ_BYTES(modify_nic_vport_context_in) + 795 list_size * MLX5_ST_SZ_BYTES(mac_address_layout); 796 797 in = kzalloc(in_sz, GFP_KERNEL); 798 if (!in) 799 return -ENOMEM; 800 801 MLX5_SET(modify_nic_vport_context_in, in, opcode, 802 MLX5_CMD_OP_MODIFY_NIC_VPORT_CONTEXT); 803 MLX5_SET(modify_nic_vport_context_in, in, 804 field_select.addresses_list, 1); 805 806 nic_vport_ctx = MLX5_ADDR_OF(modify_nic_vport_context_in, in, 807 nic_vport_context); 808 809 MLX5_SET(nic_vport_context, nic_vport_ctx, 810 allowed_list_type, list_type); 811 MLX5_SET(nic_vport_context, nic_vport_ctx, 812 allowed_list_size, list_size); 813 814 for (i = 0; i < list_size; i++) { 815 u8 *curr_mac = MLX5_ADDR_OF(nic_vport_context, 816 nic_vport_ctx, 817 current_uc_mac_address[i]) + 2; 818 ether_addr_copy(curr_mac, addr_list[i]); 819 } 820 821 err = mlx5_cmd_exec(dev, in, in_sz, out, sizeof(out)); 822 kfree(in); 823 return err; 824} 825EXPORT_SYMBOL_GPL(mlx5_modify_nic_vport_mac_list); 826 827int mlx5_query_nic_vport_vlans(struct mlx5_core_dev *dev, 828 u16 vport, 829 u16 vlans[], 830 int *size) 831{ 832 u32 in[MLX5_ST_SZ_DW(query_nic_vport_context_in)] = {0}; 833 void *nic_vport_ctx; 834 int req_list_size; 835 int max_list_size; 836 int out_sz; 837 void *out; 838 int err; 839 int i; 840 841 req_list_size = *size; 842 max_list_size = 1 << MLX5_CAP_GEN(dev, log_max_vlan_list); 843 if (req_list_size > max_list_size) { 844 mlx5_core_warn(dev, "Requested list size (%d) > (%d) max list size\n", 845 req_list_size, max_list_size); 846 req_list_size = max_list_size; 847 } 848 849 out_sz = MLX5_ST_SZ_BYTES(modify_nic_vport_context_in) + 850 req_list_size * MLX5_ST_SZ_BYTES(vlan_layout); 851 852 out = kzalloc(out_sz, GFP_KERNEL); 853 if (!out) 854 return -ENOMEM; 855 856 MLX5_SET(query_nic_vport_context_in, in, opcode, 857 MLX5_CMD_OP_QUERY_NIC_VPORT_CONTEXT); 858 MLX5_SET(query_nic_vport_context_in, in, allowed_list_type, 859 MLX5_NIC_VPORT_CONTEXT_ALLOWED_LIST_TYPE_VLAN_LIST); 860 MLX5_SET(query_nic_vport_context_in, in, vport_number, vport); 861 862 if (vport) 863 MLX5_SET(query_nic_vport_context_in, in, other_vport, 1); 864 865 err = mlx5_cmd_exec(dev, in, sizeof(in), out, out_sz); 866 if (err) 867 goto out; 868 869 nic_vport_ctx = MLX5_ADDR_OF(query_nic_vport_context_out, out, 870 nic_vport_context); 871 req_list_size = MLX5_GET(nic_vport_context, nic_vport_ctx, 872 allowed_list_size); 873 874 *size = req_list_size; 875 for (i = 0; i < req_list_size; i++) { 876 void *vlan_addr = MLX5_ADDR_OF(nic_vport_context, 877 nic_vport_ctx, 878 current_uc_mac_address[i]); 879 vlans[i] = MLX5_GET(vlan_layout, vlan_addr, vlan); 880 } 881out: 882 kfree(out); 883 return err; 884} 885EXPORT_SYMBOL_GPL(mlx5_query_nic_vport_vlans); 886 887int mlx5_modify_nic_vport_vlans(struct mlx5_core_dev *dev, 888 u16 vlans[], 889 int list_size) 890{ 891 u32 out[MLX5_ST_SZ_DW(modify_nic_vport_context_out)] = {0}; 892 void *nic_vport_ctx; 893 int max_list_size; 894 int in_sz; 895 void *in; 896 int err; 897 int i; 898 899 max_list_size = 1 << MLX5_CAP_GEN(dev, log_max_vlan_list); 900 901 if (list_size > max_list_size) 902 return -ENOSPC; 903 904 in_sz = MLX5_ST_SZ_BYTES(modify_nic_vport_context_in) + 905 list_size * MLX5_ST_SZ_BYTES(vlan_layout); 906 907 in = kzalloc(in_sz, GFP_KERNEL); 908 if (!in) 909 return -ENOMEM; 910 911 MLX5_SET(modify_nic_vport_context_in, in, opcode, 912 MLX5_CMD_OP_MODIFY_NIC_VPORT_CONTEXT); 913 MLX5_SET(modify_nic_vport_context_in, in, 914 field_select.addresses_list, 1); 915 916 nic_vport_ctx = MLX5_ADDR_OF(modify_nic_vport_context_in, in, 917 nic_vport_context); 918 919 MLX5_SET(nic_vport_context, nic_vport_ctx, 920 allowed_list_type, MLX5_NIC_VPORT_LIST_TYPE_VLAN); 921 MLX5_SET(nic_vport_context, nic_vport_ctx, 922 allowed_list_size, list_size); 923 924 for (i = 0; i < list_size; i++) { 925 void *vlan_addr = MLX5_ADDR_OF(nic_vport_context, 926 nic_vport_ctx, 927 current_uc_mac_address[i]); 928 MLX5_SET(vlan_layout, vlan_addr, vlan, vlans[i]); 929 } 930 931 err = mlx5_cmd_exec(dev, in, in_sz, out, sizeof(out)); 932 kfree(in); 933 return err; 934} 935EXPORT_SYMBOL_GPL(mlx5_modify_nic_vport_vlans); 936 937int mlx5_query_nic_vport_roce_en(struct mlx5_core_dev *mdev, u8 *enable) 938{ 939 u32 *out; 940 int outlen = MLX5_ST_SZ_BYTES(query_nic_vport_context_out); 941 int err; 942 943 out = kzalloc(outlen, GFP_KERNEL); 944 if (!out) 945 return -ENOMEM; 946 947 err = mlx5_query_nic_vport_context(mdev, 0, out, outlen); 948 if (err) 949 goto out; 950 951 *enable = MLX5_GET(query_nic_vport_context_out, out, 952 nic_vport_context.roce_en); 953 954out: 955 kfree(out); 956 return err; 957} 958EXPORT_SYMBOL_GPL(mlx5_query_nic_vport_roce_en); 959 960int mlx5_set_nic_vport_permanent_mac(struct mlx5_core_dev *mdev, int vport, 961 u8 *addr) 962{ 963 void *in; 964 int inlen = MLX5_ST_SZ_BYTES(modify_nic_vport_context_in); 965 u8 *mac_ptr; 966 int err; 967 968 in = mlx5_vzalloc(inlen); 969 if (!in) { 970 mlx5_core_warn(mdev, "failed to allocate inbox\n"); 971 return -ENOMEM; 972 } 973 974 MLX5_SET(modify_nic_vport_context_in, in, 975 opcode, MLX5_CMD_OP_MODIFY_NIC_VPORT_CONTEXT); 976 MLX5_SET(modify_nic_vport_context_in, in, vport_number, vport); 977 MLX5_SET(modify_nic_vport_context_in, in, other_vport, 1); 978 MLX5_SET(modify_nic_vport_context_in, in, 979 field_select.permanent_address, 1); 980 mac_ptr = (u8 *)MLX5_ADDR_OF(modify_nic_vport_context_in, in, 981 nic_vport_context.permanent_address.mac_addr_47_32); 982 ether_addr_copy(mac_ptr, addr); 983 984 err = mlx5_modify_nic_vport_context(mdev, in, inlen); 985 986 kvfree(in); 987 988 return err; 989} 990EXPORT_SYMBOL_GPL(mlx5_set_nic_vport_permanent_mac); 991 992int mlx5_nic_vport_enable_roce(struct mlx5_core_dev *mdev) 993{ 994 return mlx5_nic_vport_enable_disable_roce(mdev, 1); 995} 996EXPORT_SYMBOL_GPL(mlx5_nic_vport_enable_roce); 997 998int mlx5_nic_vport_disable_roce(struct mlx5_core_dev *mdev) 999{ 1000 return mlx5_nic_vport_enable_disable_roce(mdev, 0); 1001} 1002EXPORT_SYMBOL_GPL(mlx5_nic_vport_disable_roce); 1003 1004int mlx5_core_query_vport_counter(struct mlx5_core_dev *dev, u8 other_vport, 1005 int vf, u8 port_num, void *out, 1006 size_t out_sz) 1007{ 1008 int in_sz = MLX5_ST_SZ_BYTES(query_vport_counter_in); 1009 int is_group_manager; 1010 void *in; 1011 int err; 1012 1013 is_group_manager = MLX5_CAP_GEN(dev, vport_group_manager); 1014 in = mlx5_vzalloc(in_sz); 1015 if (!in) { 1016 err = -ENOMEM; 1017 return err; 1018 } 1019 1020 MLX5_SET(query_vport_counter_in, in, opcode, 1021 MLX5_CMD_OP_QUERY_VPORT_COUNTER); 1022 if (other_vport) { 1023 if (is_group_manager) { 1024 MLX5_SET(query_vport_counter_in, in, other_vport, 1); 1025 MLX5_SET(query_vport_counter_in, in, vport_number, vf + 1); 1026 } else { 1027 err = -EPERM; 1028 goto free; 1029 } 1030 } 1031 if (MLX5_CAP_GEN(dev, num_ports) == 2) 1032 MLX5_SET(query_vport_counter_in, in, port_num, port_num); 1033 1034 err = mlx5_cmd_exec(dev, in, in_sz, out, out_sz); 1035free: 1036 kvfree(in); 1037 return err; 1038} 1039EXPORT_SYMBOL_GPL(mlx5_core_query_vport_counter); 1040 1041int mlx5_query_hca_vport_context(struct mlx5_core_dev *mdev, 1042 u8 port_num, u8 vport_num, u32 *out, 1043 int outlen) 1044{ 1045 u32 in[MLX5_ST_SZ_DW(query_hca_vport_context_in)] = {0}; 1046 int is_group_manager; 1047 1048 is_group_manager = MLX5_CAP_GEN(mdev, vport_group_manager); 1049 1050 MLX5_SET(query_hca_vport_context_in, in, opcode, 1051 MLX5_CMD_OP_QUERY_HCA_VPORT_CONTEXT); 1052 1053 if (vport_num) { 1054 if (is_group_manager) { 1055 MLX5_SET(query_hca_vport_context_in, in, other_vport, 1056 1); 1057 MLX5_SET(query_hca_vport_context_in, in, vport_number, 1058 vport_num); 1059 } else { 1060 return -EPERM; 1061 } 1062 } 1063 1064 if (MLX5_CAP_GEN(mdev, num_ports) == 2) 1065 MLX5_SET(query_hca_vport_context_in, in, port_num, port_num); 1066 1067 return mlx5_cmd_exec(mdev, in, sizeof(in), out, outlen); 1068} 1069 1070int mlx5_query_hca_vport_system_image_guid(struct mlx5_core_dev *mdev, 1071 u64 *system_image_guid) 1072{ 1073 u32 *out; 1074 int outlen = MLX5_ST_SZ_BYTES(query_hca_vport_context_out); 1075 int err; 1076 1077 out = mlx5_vzalloc(outlen); 1078 if (!out) 1079 return -ENOMEM; 1080 1081 err = mlx5_query_hca_vport_context(mdev, 1, 0, out, outlen); 1082 if (err) 1083 goto out; 1084 1085 *system_image_guid = MLX5_GET64(query_hca_vport_context_out, out, 1086 hca_vport_context.system_image_guid); 1087 1088out: 1089 kvfree(out); 1090 return err; 1091} 1092EXPORT_SYMBOL_GPL(mlx5_query_hca_vport_system_image_guid); 1093 1094int mlx5_query_hca_vport_node_guid(struct mlx5_core_dev *mdev, u64 *node_guid) 1095{ 1096 u32 *out; 1097 int outlen = MLX5_ST_SZ_BYTES(query_hca_vport_context_out); 1098 int err; 1099 1100 out = mlx5_vzalloc(outlen); 1101 if (!out) 1102 return -ENOMEM; 1103 1104 err = mlx5_query_hca_vport_context(mdev, 1, 0, out, outlen); 1105 if (err) 1106 goto out; 1107 1108 *node_guid = MLX5_GET64(query_hca_vport_context_out, out, 1109 hca_vport_context.node_guid); 1110 1111out: 1112 kvfree(out); 1113 return err; 1114} 1115EXPORT_SYMBOL_GPL(mlx5_query_hca_vport_node_guid); 1116 1117static int mlx5_query_hca_vport_port_guid(struct mlx5_core_dev *mdev, 1118 u64 *port_guid) 1119{ 1120 u32 *out; 1121 int outlen = MLX5_ST_SZ_BYTES(query_hca_vport_context_out); 1122 int err; 1123 1124 out = mlx5_vzalloc(outlen); 1125 if (!out) 1126 return -ENOMEM; 1127 1128 err = mlx5_query_hca_vport_context(mdev, 1, 0, out, outlen); 1129 if (err) 1130 goto out; 1131 1132 *port_guid = MLX5_GET64(query_hca_vport_context_out, out, 1133 hca_vport_context.port_guid); 1134 1135out: 1136 kvfree(out); 1137 return err; 1138} 1139 1140int mlx5_query_hca_vport_gid(struct mlx5_core_dev *dev, u8 port_num, 1141 u16 vport_num, u16 gid_index, union ib_gid *gid) 1142{ 1143 int in_sz = MLX5_ST_SZ_BYTES(query_hca_vport_gid_in); 1144 int out_sz = MLX5_ST_SZ_BYTES(query_hca_vport_gid_out); 1145 int is_group_manager; 1146 void *out = NULL; 1147 void *in = NULL; 1148 union ib_gid *tmp; 1149 int tbsz; 1150 int nout; 1151 int err; 1152 1153 is_group_manager = MLX5_CAP_GEN(dev, vport_group_manager); 1154 tbsz = mlx5_get_gid_table_len(MLX5_CAP_GEN(dev, gid_table_size)); 1155 1156 if (gid_index > tbsz && gid_index != 0xffff) 1157 return -EINVAL; 1158 1159 if (gid_index == 0xffff) 1160 nout = tbsz; 1161 else 1162 nout = 1; 1163 1164 out_sz += nout * sizeof(*gid); 1165 1166 in = mlx5_vzalloc(in_sz); 1167 out = mlx5_vzalloc(out_sz); 1168 if (!in || !out) { 1169 err = -ENOMEM; 1170 goto out; 1171 } 1172 1173 MLX5_SET(query_hca_vport_gid_in, in, opcode, 1174 MLX5_CMD_OP_QUERY_HCA_VPORT_GID); 1175 if (vport_num) { 1176 if (is_group_manager) { 1177 MLX5_SET(query_hca_vport_gid_in, in, vport_number, 1178 vport_num); 1179 MLX5_SET(query_hca_vport_gid_in, in, other_vport, 1); 1180 } else { 1181 err = -EPERM; 1182 goto out; 1183 } 1184 } 1185 1186 MLX5_SET(query_hca_vport_gid_in, in, gid_index, gid_index); 1187 1188 if (MLX5_CAP_GEN(dev, num_ports) == 2) 1189 MLX5_SET(query_hca_vport_gid_in, in, port_num, port_num); 1190 1191 err = mlx5_cmd_exec(dev, in, in_sz, out, out_sz); 1192 if (err) 1193 goto out; 1194 1195 tmp = (union ib_gid *)MLX5_ADDR_OF(query_hca_vport_gid_out, out, gid); 1196 gid->global.subnet_prefix = tmp->global.subnet_prefix; 1197 gid->global.interface_id = tmp->global.interface_id; 1198 1199out: 1200 kvfree(in); 1201 kvfree(out); 1202 return err; 1203} 1204EXPORT_SYMBOL_GPL(mlx5_query_hca_vport_gid); 1205 1206int mlx5_query_hca_vport_pkey(struct mlx5_core_dev *dev, u8 other_vport, 1207 u8 port_num, u16 vf_num, u16 pkey_index, 1208 u16 *pkey) 1209{ 1210 int in_sz = MLX5_ST_SZ_BYTES(query_hca_vport_pkey_in); 1211 int out_sz = MLX5_ST_SZ_BYTES(query_hca_vport_pkey_out); 1212 int is_group_manager; 1213 void *out = NULL; 1214 void *in = NULL; 1215 void *pkarr; 1216 int nout; 1217 int tbsz; 1218 int err; 1219 int i; 1220 1221 is_group_manager = MLX5_CAP_GEN(dev, vport_group_manager); 1222 1223 tbsz = mlx5_to_sw_pkey_sz(MLX5_CAP_GEN(dev, pkey_table_size)); 1224 if (pkey_index > tbsz && pkey_index != 0xffff) 1225 return -EINVAL; 1226 1227 if (pkey_index == 0xffff) 1228 nout = tbsz; 1229 else 1230 nout = 1; 1231 1232 out_sz += nout * MLX5_ST_SZ_BYTES(pkey); 1233 1234 in = kzalloc(in_sz, GFP_KERNEL); 1235 out = kzalloc(out_sz, GFP_KERNEL); 1236 1237 MLX5_SET(query_hca_vport_pkey_in, in, opcode, 1238 MLX5_CMD_OP_QUERY_HCA_VPORT_PKEY); 1239 if (other_vport) { 1240 if (is_group_manager) { 1241 MLX5_SET(query_hca_vport_pkey_in, in, vport_number, 1242 vf_num); 1243 MLX5_SET(query_hca_vport_pkey_in, in, other_vport, 1); 1244 } else { 1245 err = -EPERM; 1246 goto out; 1247 } 1248 } 1249 MLX5_SET(query_hca_vport_pkey_in, in, pkey_index, pkey_index); 1250 1251 if (MLX5_CAP_GEN(dev, num_ports) == 2) 1252 MLX5_SET(query_hca_vport_pkey_in, in, port_num, port_num); 1253 1254 err = mlx5_cmd_exec(dev, in, in_sz, out, out_sz); 1255 if (err) 1256 goto out; 1257 1258 pkarr = MLX5_ADDR_OF(query_hca_vport_pkey_out, out, pkey); 1259 for (i = 0; i < nout; i++, pkey++, 1260 pkarr += MLX5_ST_SZ_BYTES(pkey)) 1261 *pkey = MLX5_GET_PR(pkey, pkarr, pkey); 1262 1263out: 1264 kfree(in); 1265 kfree(out); 1266 return err; 1267} 1268EXPORT_SYMBOL_GPL(mlx5_query_hca_vport_pkey); 1269 1270static int mlx5_query_hca_min_wqe_header(struct mlx5_core_dev *mdev, 1271 int *min_header) 1272{ 1273 u32 *out; 1274 u32 outlen = MLX5_ST_SZ_BYTES(query_hca_vport_context_out); 1275 int err; 1276 1277 out = mlx5_vzalloc(outlen); 1278 if (!out) 1279 return -ENOMEM; 1280 1281 err = mlx5_query_hca_vport_context(mdev, 1, 0, out, outlen); 1282 if (err) 1283 goto out; 1284 1285 *min_header = MLX5_GET(query_hca_vport_context_out, out, 1286 hca_vport_context.min_wqe_inline_mode); 1287 1288out: 1289 kvfree(out); 1290 return err; 1291} 1292 1293static int mlx5_modify_eswitch_vport_context(struct mlx5_core_dev *mdev, 1294 u16 vport, void *in, int inlen) 1295{ 1296 u32 out[MLX5_ST_SZ_DW(modify_esw_vport_context_out)] = {0}; 1297 int err; 1298 1299 MLX5_SET(modify_esw_vport_context_in, in, vport_number, vport); 1300 if (vport) 1301 MLX5_SET(modify_esw_vport_context_in, in, other_vport, 1); 1302 1303 MLX5_SET(modify_esw_vport_context_in, in, opcode, 1304 MLX5_CMD_OP_MODIFY_ESW_VPORT_CONTEXT); 1305 1306 err = mlx5_cmd_exec(mdev, in, inlen, out, sizeof(out)); 1307 if (err) 1308 mlx5_core_warn(mdev, "MLX5_CMD_OP_MODIFY_ESW_VPORT_CONTEXT failed\n"); 1309 1310 return err; 1311} 1312 1313int mlx5_set_eswitch_cvlan_info(struct mlx5_core_dev *mdev, u8 vport, 1314 u8 insert_mode, u8 strip_mode, 1315 u16 vlan, u8 cfi, u8 pcp) 1316{ 1317 u32 in[MLX5_ST_SZ_DW(modify_esw_vport_context_in)]; 1318 1319 memset(in, 0, sizeof(in)); 1320 1321 if (insert_mode != MLX5_MODIFY_ESW_VPORT_CONTEXT_CVLAN_INSERT_NONE) { 1322 MLX5_SET(modify_esw_vport_context_in, in, 1323 esw_vport_context.cvlan_cfi, cfi); 1324 MLX5_SET(modify_esw_vport_context_in, in, 1325 esw_vport_context.cvlan_pcp, pcp); 1326 MLX5_SET(modify_esw_vport_context_in, in, 1327 esw_vport_context.cvlan_id, vlan); 1328 } 1329 1330 MLX5_SET(modify_esw_vport_context_in, in, 1331 esw_vport_context.vport_cvlan_insert, insert_mode); 1332 1333 MLX5_SET(modify_esw_vport_context_in, in, 1334 esw_vport_context.vport_cvlan_strip, strip_mode); 1335 1336 MLX5_SET(modify_esw_vport_context_in, in, field_select, 1337 MLX5_MODIFY_ESW_VPORT_CONTEXT_FIELD_SELECT_CVLAN_STRIP | 1338 MLX5_MODIFY_ESW_VPORT_CONTEXT_FIELD_SELECT_CVLAN_INSERT); 1339 1340 return mlx5_modify_eswitch_vport_context(mdev, vport, in, sizeof(in)); 1341} 1342EXPORT_SYMBOL_GPL(mlx5_set_eswitch_cvlan_info); 1343 1344int mlx5_query_vport_mtu(struct mlx5_core_dev *mdev, int *mtu) 1345{ 1346 u32 *out; 1347 u32 outlen = MLX5_ST_SZ_BYTES(query_nic_vport_context_out); 1348 int err; 1349 1350 out = mlx5_vzalloc(outlen); 1351 if (!out) 1352 return -ENOMEM; 1353 1354 err = mlx5_query_nic_vport_context(mdev, 0, out, outlen); 1355 if (err) 1356 goto out; 1357 1358 *mtu = MLX5_GET(query_nic_vport_context_out, out, 1359 nic_vport_context.mtu); 1360 1361out: 1362 kvfree(out); 1363 return err; 1364} 1365EXPORT_SYMBOL_GPL(mlx5_query_vport_mtu); 1366 1367int mlx5_set_vport_mtu(struct mlx5_core_dev *mdev, int mtu) 1368{ 1369 u32 *in; 1370 u32 inlen = MLX5_ST_SZ_BYTES(modify_nic_vport_context_in); 1371 int err; 1372 1373 in = mlx5_vzalloc(inlen); 1374 if (!in) 1375 return -ENOMEM; 1376 1377 MLX5_SET(modify_nic_vport_context_in, in, field_select.mtu, 1); 1378 MLX5_SET(modify_nic_vport_context_in, in, nic_vport_context.mtu, mtu); 1379 1380 err = mlx5_modify_nic_vport_context(mdev, in, inlen); 1381 1382 kvfree(in); 1383 return err; 1384} 1385EXPORT_SYMBOL_GPL(mlx5_set_vport_mtu); 1386 1387static int mlx5_query_vport_min_wqe_header(struct mlx5_core_dev *mdev, 1388 int *min_header) 1389{ 1390 u32 *out; 1391 u32 outlen = MLX5_ST_SZ_BYTES(query_nic_vport_context_out); 1392 int err; 1393 1394 out = mlx5_vzalloc(outlen); 1395 if (!out) 1396 return -ENOMEM; 1397 1398 err = mlx5_query_nic_vport_context(mdev, 0, out, outlen); 1399 if (err) 1400 goto out; 1401 1402 *min_header = MLX5_GET(query_nic_vport_context_out, out, 1403 nic_vport_context.min_wqe_inline_mode); 1404 1405out: 1406 kvfree(out); 1407 return err; 1408} 1409 1410int mlx5_set_vport_min_wqe_header(struct mlx5_core_dev *mdev, 1411 u8 vport, int min_header) 1412{ 1413 u32 *in; 1414 u32 inlen = MLX5_ST_SZ_BYTES(modify_nic_vport_context_in); 1415 int err; 1416 1417 in = mlx5_vzalloc(inlen); 1418 if (!in) 1419 return -ENOMEM; 1420 1421 MLX5_SET(modify_nic_vport_context_in, in, 1422 field_select.min_wqe_inline_mode, 1); 1423 MLX5_SET(modify_nic_vport_context_in, in, 1424 nic_vport_context.min_wqe_inline_mode, min_header); 1425 MLX5_SET(modify_nic_vport_context_in, in, vport_number, vport); 1426 MLX5_SET(modify_nic_vport_context_in, in, other_vport, 1); 1427 1428 err = mlx5_modify_nic_vport_context(mdev, in, inlen); 1429 1430 kvfree(in); 1431 return err; 1432} 1433EXPORT_SYMBOL_GPL(mlx5_set_vport_min_wqe_header); 1434 1435int mlx5_query_min_wqe_header(struct mlx5_core_dev *dev, int *min_header) 1436{ 1437 switch (MLX5_CAP_GEN(dev, port_type)) { 1438 case MLX5_CMD_HCA_CAP_PORT_TYPE_IB: 1439 return mlx5_query_hca_min_wqe_header(dev, min_header); 1440 1441 case MLX5_CMD_HCA_CAP_PORT_TYPE_ETHERNET: 1442 return mlx5_query_vport_min_wqe_header(dev, min_header); 1443 1444 default: 1445 return -EINVAL; 1446 } 1447} 1448EXPORT_SYMBOL_GPL(mlx5_query_min_wqe_header); 1449 1450int mlx5_query_nic_vport_promisc(struct mlx5_core_dev *mdev, 1451 u16 vport, 1452 int *promisc_uc, 1453 int *promisc_mc, 1454 int *promisc_all) 1455{ 1456 u32 *out; 1457 int outlen = MLX5_ST_SZ_BYTES(query_nic_vport_context_out); 1458 int err; 1459 1460 out = kzalloc(outlen, GFP_KERNEL); 1461 if (!out) 1462 return -ENOMEM; 1463 1464 err = mlx5_query_nic_vport_context(mdev, vport, out, outlen); 1465 if (err) 1466 goto out; 1467 1468 *promisc_uc = MLX5_GET(query_nic_vport_context_out, out, 1469 nic_vport_context.promisc_uc); 1470 *promisc_mc = MLX5_GET(query_nic_vport_context_out, out, 1471 nic_vport_context.promisc_mc); 1472 *promisc_all = MLX5_GET(query_nic_vport_context_out, out, 1473 nic_vport_context.promisc_all); 1474 1475out: 1476 kfree(out); 1477 return err; 1478} 1479EXPORT_SYMBOL_GPL(mlx5_query_nic_vport_promisc); 1480 1481int mlx5_modify_nic_vport_promisc(struct mlx5_core_dev *mdev, 1482 int promisc_uc, 1483 int promisc_mc, 1484 int promisc_all) 1485{ 1486 void *in; 1487 int inlen = MLX5_ST_SZ_BYTES(modify_nic_vport_context_in); 1488 int err; 1489 1490 in = mlx5_vzalloc(inlen); 1491 if (!in) { 1492 mlx5_core_err(mdev, "failed to allocate inbox\n"); 1493 return -ENOMEM; 1494 } 1495 1496 MLX5_SET(modify_nic_vport_context_in, in, field_select.promisc, 1); 1497 MLX5_SET(modify_nic_vport_context_in, in, 1498 nic_vport_context.promisc_uc, promisc_uc); 1499 MLX5_SET(modify_nic_vport_context_in, in, 1500 nic_vport_context.promisc_mc, promisc_mc); 1501 MLX5_SET(modify_nic_vport_context_in, in, 1502 nic_vport_context.promisc_all, promisc_all); 1503 1504 err = mlx5_modify_nic_vport_context(mdev, in, inlen); 1505 kvfree(in); 1506 return err; 1507} 1508EXPORT_SYMBOL_GPL(mlx5_modify_nic_vport_promisc); 1509 1510int mlx5_nic_vport_modify_local_lb(struct mlx5_core_dev *mdev, 1511 enum mlx5_local_lb_selection selection, 1512 u8 value) 1513{ 1514 void *in; 1515 int inlen = MLX5_ST_SZ_BYTES(modify_nic_vport_context_in); 1516 int err; 1517 1518 in = mlx5_vzalloc(inlen); 1519 if (!in) { 1520 mlx5_core_warn(mdev, "failed to allocate inbox\n"); 1521 return -ENOMEM; 1522 } 1523 1524 MLX5_SET(modify_nic_vport_context_in, in, vport_number, 0); 1525 1526 if (selection == MLX5_LOCAL_MC_LB) { 1527 MLX5_SET(modify_nic_vport_context_in, in, 1528 field_select.disable_mc_local_lb, 1); 1529 MLX5_SET(modify_nic_vport_context_in, in, 1530 nic_vport_context.disable_mc_local_lb, 1531 value); 1532 } else { 1533 MLX5_SET(modify_nic_vport_context_in, in, 1534 field_select.disable_uc_local_lb, 1); 1535 MLX5_SET(modify_nic_vport_context_in, in, 1536 nic_vport_context.disable_uc_local_lb, 1537 value); 1538 } 1539 1540 err = mlx5_modify_nic_vport_context(mdev, in, inlen); 1541 1542 kvfree(in); 1543 return err; 1544} 1545EXPORT_SYMBOL_GPL(mlx5_nic_vport_modify_local_lb); 1546 1547int mlx5_nic_vport_query_local_lb(struct mlx5_core_dev *mdev, 1548 enum mlx5_local_lb_selection selection, 1549 u8 *value) 1550{ 1551 void *out; 1552 int outlen = MLX5_ST_SZ_BYTES(query_nic_vport_context_out); 1553 int err; 1554 1555 out = kzalloc(outlen, GFP_KERNEL); 1556 if (!out) 1557 return -ENOMEM; 1558 1559 err = mlx5_query_nic_vport_context(mdev, 0, out, outlen); 1560 if (err) 1561 goto done; 1562 1563 if (selection == MLX5_LOCAL_MC_LB) 1564 *value = MLX5_GET(query_nic_vport_context_out, out, 1565 nic_vport_context.disable_mc_local_lb); 1566 else 1567 *value = MLX5_GET(query_nic_vport_context_out, out, 1568 nic_vport_context.disable_uc_local_lb); 1569 1570done: 1571 kfree(out); 1572 return err; 1573} 1574EXPORT_SYMBOL_GPL(mlx5_nic_vport_query_local_lb); 1575 1576int mlx5_query_vport_counter(struct mlx5_core_dev *dev, 1577 u8 port_num, u16 vport_num, 1578 void *out, int out_size) 1579{ 1580 int in_sz = MLX5_ST_SZ_BYTES(query_vport_counter_in); 1581 int is_group_manager; 1582 void *in; 1583 int err; 1584 1585 is_group_manager = MLX5_CAP_GEN(dev, vport_group_manager); 1586 1587 in = mlx5_vzalloc(in_sz); 1588 if (!in) 1589 return -ENOMEM; 1590 1591 MLX5_SET(query_vport_counter_in, in, opcode, 1592 MLX5_CMD_OP_QUERY_VPORT_COUNTER); 1593 if (vport_num) { 1594 if (is_group_manager) { 1595 MLX5_SET(query_vport_counter_in, in, other_vport, 1); 1596 MLX5_SET(query_vport_counter_in, in, vport_number, 1597 vport_num); 1598 } else { 1599 err = -EPERM; 1600 goto ex; 1601 } 1602 } 1603 if (MLX5_CAP_GEN(dev, num_ports) == 2) 1604 MLX5_SET(query_vport_counter_in, in, port_num, port_num); 1605 1606 err = mlx5_cmd_exec(dev, in, in_sz, out, out_size); 1607 1608ex: 1609 kvfree(in); 1610 return err; 1611} 1612EXPORT_SYMBOL_GPL(mlx5_query_vport_counter); 1613 1614int mlx5_get_vport_counters(struct mlx5_core_dev *dev, u8 port_num, 1615 struct mlx5_vport_counters *vc) 1616{ 1617 int out_sz = MLX5_ST_SZ_BYTES(query_vport_counter_out); 1618 void *out; 1619 int err; 1620 1621 out = mlx5_vzalloc(out_sz); 1622 if (!out) 1623 return -ENOMEM; 1624 1625 err = mlx5_query_vport_counter(dev, port_num, 0, out, out_sz); 1626 if (err) 1627 goto ex; 1628 1629 vc->received_errors.packets = 1630 MLX5_GET64(query_vport_counter_out, 1631 out, received_errors.packets); 1632 vc->received_errors.octets = 1633 MLX5_GET64(query_vport_counter_out, 1634 out, received_errors.octets); 1635 vc->transmit_errors.packets = 1636 MLX5_GET64(query_vport_counter_out, 1637 out, transmit_errors.packets); 1638 vc->transmit_errors.octets = 1639 MLX5_GET64(query_vport_counter_out, 1640 out, transmit_errors.octets); 1641 vc->received_ib_unicast.packets = 1642 MLX5_GET64(query_vport_counter_out, 1643 out, received_ib_unicast.packets); 1644 vc->received_ib_unicast.octets = 1645 MLX5_GET64(query_vport_counter_out, 1646 out, received_ib_unicast.octets); 1647 vc->transmitted_ib_unicast.packets = 1648 MLX5_GET64(query_vport_counter_out, 1649 out, transmitted_ib_unicast.packets); 1650 vc->transmitted_ib_unicast.octets = 1651 MLX5_GET64(query_vport_counter_out, 1652 out, transmitted_ib_unicast.octets); 1653 vc->received_ib_multicast.packets = 1654 MLX5_GET64(query_vport_counter_out, 1655 out, received_ib_multicast.packets); 1656 vc->received_ib_multicast.octets = 1657 MLX5_GET64(query_vport_counter_out, 1658 out, received_ib_multicast.octets); 1659 vc->transmitted_ib_multicast.packets = 1660 MLX5_GET64(query_vport_counter_out, 1661 out, transmitted_ib_multicast.packets); 1662 vc->transmitted_ib_multicast.octets = 1663 MLX5_GET64(query_vport_counter_out, 1664 out, transmitted_ib_multicast.octets); 1665 vc->received_eth_broadcast.packets = 1666 MLX5_GET64(query_vport_counter_out, 1667 out, received_eth_broadcast.packets); 1668 vc->received_eth_broadcast.octets = 1669 MLX5_GET64(query_vport_counter_out, 1670 out, received_eth_broadcast.octets); 1671 vc->transmitted_eth_broadcast.packets = 1672 MLX5_GET64(query_vport_counter_out, 1673 out, transmitted_eth_broadcast.packets); 1674 vc->transmitted_eth_broadcast.octets = 1675 MLX5_GET64(query_vport_counter_out, 1676 out, transmitted_eth_broadcast.octets); 1677 vc->received_eth_unicast.octets = 1678 MLX5_GET64(query_vport_counter_out, 1679 out, received_eth_unicast.octets); 1680 vc->received_eth_unicast.packets = 1681 MLX5_GET64(query_vport_counter_out, 1682 out, received_eth_unicast.packets); 1683 vc->transmitted_eth_unicast.octets = 1684 MLX5_GET64(query_vport_counter_out, 1685 out, transmitted_eth_unicast.octets); 1686 vc->transmitted_eth_unicast.packets = 1687 MLX5_GET64(query_vport_counter_out, 1688 out, transmitted_eth_unicast.packets); 1689 vc->received_eth_multicast.octets = 1690 MLX5_GET64(query_vport_counter_out, 1691 out, received_eth_multicast.octets); 1692 vc->received_eth_multicast.packets = 1693 MLX5_GET64(query_vport_counter_out, 1694 out, received_eth_multicast.packets); 1695 vc->transmitted_eth_multicast.octets = 1696 MLX5_GET64(query_vport_counter_out, 1697 out, transmitted_eth_multicast.octets); 1698 vc->transmitted_eth_multicast.packets = 1699 MLX5_GET64(query_vport_counter_out, 1700 out, transmitted_eth_multicast.packets); 1701 1702ex: 1703 kvfree(out); 1704 return err; 1705} 1706 1707int mlx5_query_vport_system_image_guid(struct mlx5_core_dev *dev, 1708 u64 *sys_image_guid) 1709{ 1710 switch (MLX5_CAP_GEN(dev, port_type)) { 1711 case MLX5_CMD_HCA_CAP_PORT_TYPE_IB: 1712 return mlx5_query_hca_vport_system_image_guid(dev, 1713 sys_image_guid); 1714 1715 case MLX5_CMD_HCA_CAP_PORT_TYPE_ETHERNET: 1716 return mlx5_query_nic_vport_system_image_guid(dev, 1717 sys_image_guid); 1718 1719 default: 1720 return -EINVAL; 1721 } 1722} 1723EXPORT_SYMBOL_GPL(mlx5_query_vport_system_image_guid); 1724 1725int mlx5_query_vport_node_guid(struct mlx5_core_dev *dev, u64 *node_guid) 1726{ 1727 switch (MLX5_CAP_GEN(dev, port_type)) { 1728 case MLX5_CMD_HCA_CAP_PORT_TYPE_IB: 1729 return mlx5_query_hca_vport_node_guid(dev, node_guid); 1730 1731 case MLX5_CMD_HCA_CAP_PORT_TYPE_ETHERNET: 1732 return mlx5_query_nic_vport_node_guid(dev, node_guid); 1733 1734 default: 1735 return -EINVAL; 1736 } 1737} 1738EXPORT_SYMBOL_GPL(mlx5_query_vport_node_guid); 1739 1740int mlx5_query_vport_port_guid(struct mlx5_core_dev *dev, u64 *port_guid) 1741{ 1742 switch (MLX5_CAP_GEN(dev, port_type)) { 1743 case MLX5_CMD_HCA_CAP_PORT_TYPE_IB: 1744 return mlx5_query_hca_vport_port_guid(dev, port_guid); 1745 1746 case MLX5_CMD_HCA_CAP_PORT_TYPE_ETHERNET: 1747 return mlx5_query_nic_vport_port_guid(dev, port_guid); 1748 1749 default: 1750 return -EINVAL; 1751 } 1752} 1753EXPORT_SYMBOL_GPL(mlx5_query_vport_port_guid); 1754 1755int mlx5_query_hca_vport_state(struct mlx5_core_dev *dev, u8 *vport_state) 1756{ 1757 u32 *out; 1758 int outlen = MLX5_ST_SZ_BYTES(query_hca_vport_context_out); 1759 int err; 1760 1761 out = mlx5_vzalloc(outlen); 1762 if (!out) 1763 return -ENOMEM; 1764 1765 err = mlx5_query_hca_vport_context(dev, 1, 0, out, outlen); 1766 if (err) 1767 goto out; 1768 1769 *vport_state = MLX5_GET(query_hca_vport_context_out, out, 1770 hca_vport_context.vport_state); 1771 1772out: 1773 kvfree(out); 1774 return err; 1775} 1776EXPORT_SYMBOL_GPL(mlx5_query_hca_vport_state); 1777 1778int mlx5_core_query_ib_ppcnt(struct mlx5_core_dev *dev, 1779 u8 port_num, void *out, size_t sz) 1780{ 1781 u32 *in; 1782 int err; 1783 1784 in = mlx5_vzalloc(sz); 1785 if (!in) { 1786 err = -ENOMEM; 1787 return err; 1788 } 1789 1790 MLX5_SET(ppcnt_reg, in, local_port, port_num); 1791 1792 MLX5_SET(ppcnt_reg, in, grp, MLX5_INFINIBAND_PORT_COUNTERS_GROUP); 1793 err = mlx5_core_access_reg(dev, in, sz, out, 1794 sz, MLX5_REG_PPCNT, 0, 0); 1795 1796 kvfree(in); 1797 return err; 1798} 1799