mlx5_vport.c revision 306233
1156956Sume/*- 2156956Sume * Copyright (c) 2013-2015, Mellanox Technologies, Ltd. All rights reserved. 3156956Sume * 4156956Sume * Redistribution and use in source and binary forms, with or without 5156956Sume * modification, are permitted provided that the following conditions 6156956Sume * are met: 7156956Sume * 1. Redistributions of source code must retain the above copyright 8156956Sume * notice, this list of conditions and the following disclaimer. 9156956Sume * 2. Redistributions in binary form must reproduce the above copyright 10156956Sume * notice, this list of conditions and the following disclaimer in the 11156956Sume * documentation and/or other materials provided with the distribution. 12156956Sume * 13156956Sume * THIS SOFTWARE IS PROVIDED BY AUTHOR AND CONTRIBUTORS `AS IS' AND 14156956Sume * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 15156956Sume * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 16156956Sume * ARE DISCLAIMED. IN NO EVENT SHALL AUTHOR OR CONTRIBUTORS BE LIABLE 17156956Sume * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 18156956Sume * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 19156956Sume * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 20156956Sume * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 21156956Sume * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 22156956Sume * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 23156956Sume * SUCH DAMAGE. 24156956Sume * 25156956Sume * $FreeBSD: stable/11/sys/dev/mlx5/mlx5_core/mlx5_vport.c 306233 2016-09-23 08:17:51Z hselasky $ 26156956Sume */ 27156956Sume 28156956Sume#include <linux/etherdevice.h> 29156956Sume#include <dev/mlx5/driver.h> 30156956Sume#include <dev/mlx5/vport.h> 31156956Sume#include "mlx5_core.h" 32156956Sume 33156956Sumestatic int mlx5_modify_nic_vport_context(struct mlx5_core_dev *mdev, void *in, 34156956Sume int inlen); 35156956Sume 36156956Sumestatic int _mlx5_query_vport_state(struct mlx5_core_dev *mdev, u8 opmod, 37156956Sume u16 vport, u32 *out, int outlen) 38156956Sume{ 39156956Sume int err; 40156956Sume u32 in[MLX5_ST_SZ_DW(query_vport_state_in)]; 41156956Sume 42156956Sume memset(in, 0, sizeof(in)); 43156956Sume 44156956Sume MLX5_SET(query_vport_state_in, in, opcode, 45156956Sume MLX5_CMD_OP_QUERY_VPORT_STATE); 46156956Sume MLX5_SET(query_vport_state_in, in, op_mod, opmod); 47156956Sume MLX5_SET(query_vport_state_in, in, vport_number, vport); 48156956Sume if (vport) 49156956Sume MLX5_SET(query_vport_state_in, in, other_vport, 1); 50156956Sume 51157594Sume err = mlx5_cmd_exec_check_status(mdev, in, sizeof(in), out, outlen); 52156956Sume if (err) 53156956Sume mlx5_core_warn(mdev, "MLX5_CMD_OP_QUERY_VPORT_STATE failed\n"); 54156956Sume 55156956Sume return err; 56156956Sume} 57156956Sume 58156956Sumeu8 mlx5_query_vport_state(struct mlx5_core_dev *mdev, u8 opmod, u16 vport) 59156956Sume{ 60156956Sume u32 out[MLX5_ST_SZ_DW(query_vport_state_out)] = {0}; 61156956Sume 62156956Sume _mlx5_query_vport_state(mdev, opmod, vport, out, sizeof(out)); 63156956Sume 64156956Sume return MLX5_GET(query_vport_state_out, out, state); 65156956Sume} 66156956SumeEXPORT_SYMBOL_GPL(mlx5_query_vport_state); 67156956Sume 68156956Sumeu8 mlx5_query_vport_admin_state(struct mlx5_core_dev *mdev, u8 opmod, u16 vport) 69156956Sume{ 70156956Sume u32 out[MLX5_ST_SZ_DW(query_vport_state_out)] = {0}; 71156956Sume 72156956Sume _mlx5_query_vport_state(mdev, opmod, vport, out, sizeof(out)); 73156956Sume 74156956Sume return MLX5_GET(query_vport_state_out, out, admin_state); 75156956Sume} 76156956SumeEXPORT_SYMBOL(mlx5_query_vport_admin_state); 77156956Sume 78156956Sumeint mlx5_modify_vport_admin_state(struct mlx5_core_dev *mdev, u8 opmod, 79156956Sume u16 vport, u8 state) 80156956Sume{ 81156956Sume u32 in[MLX5_ST_SZ_DW(modify_vport_state_in)]; 82156956Sume u32 out[MLX5_ST_SZ_DW(modify_vport_state_out)]; 83156956Sume int err; 84156956Sume 85156956Sume memset(in, 0, sizeof(in)); 86156956Sume 87156956Sume MLX5_SET(modify_vport_state_in, in, opcode, 88 MLX5_CMD_OP_MODIFY_VPORT_STATE); 89 MLX5_SET(modify_vport_state_in, in, op_mod, opmod); 90 MLX5_SET(modify_vport_state_in, in, vport_number, vport); 91 92 if (vport) 93 MLX5_SET(modify_vport_state_in, in, other_vport, 1); 94 95 MLX5_SET(modify_vport_state_in, in, admin_state, state); 96 97 err = mlx5_cmd_exec_check_status(mdev, in, sizeof(in), out, 98 sizeof(out)); 99 if (err) 100 mlx5_core_warn(mdev, "MLX5_CMD_OP_MODIFY_VPORT_STATE failed\n"); 101 102 return err; 103} 104EXPORT_SYMBOL(mlx5_modify_vport_admin_state); 105 106static int mlx5_query_nic_vport_context(struct mlx5_core_dev *mdev, u16 vport, 107 u32 *out, int outlen) 108{ 109 u32 in[MLX5_ST_SZ_DW(query_nic_vport_context_in)]; 110 111 memset(in, 0, sizeof(in)); 112 113 MLX5_SET(query_nic_vport_context_in, in, opcode, 114 MLX5_CMD_OP_QUERY_NIC_VPORT_CONTEXT); 115 116 MLX5_SET(query_nic_vport_context_in, in, vport_number, vport); 117 if (vport) 118 MLX5_SET(query_nic_vport_context_in, in, other_vport, 1); 119 120 return mlx5_cmd_exec_check_status(mdev, in, sizeof(in), out, outlen); 121} 122 123static u32 mlx5_vport_max_q_counter_allocator(struct mlx5_core_dev *mdev, 124 int client_id) 125{ 126 switch (client_id) { 127 case MLX5_INTERFACE_PROTOCOL_IB: 128 return (MLX5_CAP_GEN(mdev, max_qp_cnt) - 129 MLX5_QCOUNTER_SETS_NETDEV); 130 case MLX5_INTERFACE_PROTOCOL_ETH: 131 return MLX5_QCOUNTER_SETS_NETDEV; 132 default: 133 mlx5_core_warn(mdev, "Unknown Client: %d\n", client_id); 134 return 0; 135 } 136} 137 138int mlx5_vport_alloc_q_counter(struct mlx5_core_dev *mdev, 139 int client_id, u16 *counter_set_id) 140{ 141 u32 in[MLX5_ST_SZ_DW(alloc_q_counter_in)]; 142 u32 out[MLX5_ST_SZ_DW(alloc_q_counter_out)]; 143 int err; 144 145 if (mdev->num_q_counter_allocated[client_id] > 146 mlx5_vport_max_q_counter_allocator(mdev, client_id)) 147 return -EINVAL; 148 149 memset(in, 0, sizeof(in)); 150 memset(out, 0, sizeof(out)); 151 152 MLX5_SET(alloc_q_counter_in, in, opcode, 153 MLX5_CMD_OP_ALLOC_Q_COUNTER); 154 155 err = mlx5_cmd_exec_check_status(mdev, in, sizeof(in), 156 out, sizeof(out)); 157 158 if (!err) 159 *counter_set_id = MLX5_GET(alloc_q_counter_out, out, 160 counter_set_id); 161 162 mdev->num_q_counter_allocated[client_id]++; 163 164 return err; 165} 166 167int mlx5_vport_dealloc_q_counter(struct mlx5_core_dev *mdev, 168 int client_id, u16 counter_set_id) 169{ 170 u32 in[MLX5_ST_SZ_DW(dealloc_q_counter_in)]; 171 u32 out[MLX5_ST_SZ_DW(dealloc_q_counter_out)]; 172 int err; 173 174 if (mdev->num_q_counter_allocated[client_id] <= 0) 175 return -EINVAL; 176 177 memset(in, 0, sizeof(in)); 178 memset(out, 0, sizeof(out)); 179 180 MLX5_SET(dealloc_q_counter_in, in, opcode, 181 MLX5_CMD_OP_DEALLOC_Q_COUNTER); 182 MLX5_SET(dealloc_q_counter_in, in, counter_set_id, 183 counter_set_id); 184 185 err = mlx5_cmd_exec_check_status(mdev, in, sizeof(in), 186 out, sizeof(out)); 187 188 mdev->num_q_counter_allocated[client_id]--; 189 190 return err; 191} 192 193int mlx5_vport_query_q_counter(struct mlx5_core_dev *mdev, 194 u16 counter_set_id, 195 int reset, 196 void *out, 197 int out_size) 198{ 199 u32 in[MLX5_ST_SZ_DW(query_q_counter_in)]; 200 201 memset(in, 0, sizeof(in)); 202 203 MLX5_SET(query_q_counter_in, in, opcode, MLX5_CMD_OP_QUERY_Q_COUNTER); 204 MLX5_SET(query_q_counter_in, in, clear, reset); 205 MLX5_SET(query_q_counter_in, in, counter_set_id, counter_set_id); 206 207 return mlx5_cmd_exec_check_status(mdev, in, sizeof(in), 208 out, out_size); 209} 210 211int mlx5_vport_query_out_of_rx_buffer(struct mlx5_core_dev *mdev, 212 u16 counter_set_id, 213 u32 *out_of_rx_buffer) 214{ 215 u32 out[MLX5_ST_SZ_DW(query_q_counter_out)]; 216 int err; 217 218 memset(out, 0, sizeof(out)); 219 220 err = mlx5_vport_query_q_counter(mdev, counter_set_id, 0, out, 221 sizeof(out)); 222 223 if (err) 224 return err; 225 226 *out_of_rx_buffer = MLX5_GET(query_q_counter_out, out, 227 out_of_buffer); 228 return err; 229} 230 231int mlx5_query_nic_vport_mac_address(struct mlx5_core_dev *mdev, 232 u16 vport, u8 *addr) 233{ 234 u32 *out; 235 int outlen = MLX5_ST_SZ_BYTES(query_nic_vport_context_out); 236 u8 *out_addr; 237 int err; 238 239 out = mlx5_vzalloc(outlen); 240 if (!out) 241 return -ENOMEM; 242 243 out_addr = MLX5_ADDR_OF(query_nic_vport_context_out, out, 244 nic_vport_context.permanent_address); 245 246 err = mlx5_query_nic_vport_context(mdev, vport, out, outlen); 247 if (err) 248 goto out; 249 250 ether_addr_copy(addr, &out_addr[2]); 251 252out: 253 kvfree(out); 254 return err; 255} 256EXPORT_SYMBOL_GPL(mlx5_query_nic_vport_mac_address); 257 258int mlx5_modify_nic_vport_mac_address(struct mlx5_core_dev *mdev, 259 u16 vport, u8 *addr) 260{ 261 void *in; 262 int inlen = MLX5_ST_SZ_BYTES(modify_nic_vport_context_in); 263 int err; 264 void *nic_vport_ctx; 265 u8 *perm_mac; 266 267 in = mlx5_vzalloc(inlen); 268 if (!in) { 269 mlx5_core_warn(mdev, "failed to allocate inbox\n"); 270 return -ENOMEM; 271 } 272 273 MLX5_SET(modify_nic_vport_context_in, in, 274 field_select.permanent_address, 1); 275 MLX5_SET(modify_nic_vport_context_in, in, vport_number, vport); 276 277 if (vport) 278 MLX5_SET(modify_nic_vport_context_in, in, other_vport, 1); 279 280 nic_vport_ctx = MLX5_ADDR_OF(modify_nic_vport_context_in, 281 in, nic_vport_context); 282 perm_mac = MLX5_ADDR_OF(nic_vport_context, nic_vport_ctx, 283 permanent_address); 284 285 ether_addr_copy(&perm_mac[2], addr); 286 287 err = mlx5_modify_nic_vport_context(mdev, in, inlen); 288 289 kvfree(in); 290 291 return err; 292} 293EXPORT_SYMBOL(mlx5_modify_nic_vport_mac_address); 294 295int mlx5_query_nic_vport_system_image_guid(struct mlx5_core_dev *mdev, 296 u64 *system_image_guid) 297{ 298 u32 *out; 299 int outlen = MLX5_ST_SZ_BYTES(query_nic_vport_context_out); 300 int err; 301 302 out = mlx5_vzalloc(outlen); 303 if (!out) 304 return -ENOMEM; 305 306 err = mlx5_query_nic_vport_context(mdev, 0, out, outlen); 307 if (err) 308 goto out; 309 310 *system_image_guid = MLX5_GET64(query_nic_vport_context_out, out, 311 nic_vport_context.system_image_guid); 312out: 313 kvfree(out); 314 return err; 315} 316EXPORT_SYMBOL_GPL(mlx5_query_nic_vport_system_image_guid); 317 318int mlx5_query_nic_vport_node_guid(struct mlx5_core_dev *mdev, u64 *node_guid) 319{ 320 u32 *out; 321 int outlen = MLX5_ST_SZ_BYTES(query_nic_vport_context_out); 322 int err; 323 324 out = mlx5_vzalloc(outlen); 325 if (!out) 326 return -ENOMEM; 327 328 err = mlx5_query_nic_vport_context(mdev, 0, out, outlen); 329 if (err) 330 goto out; 331 332 *node_guid = MLX5_GET64(query_nic_vport_context_out, out, 333 nic_vport_context.node_guid); 334 335out: 336 kvfree(out); 337 return err; 338} 339EXPORT_SYMBOL_GPL(mlx5_query_nic_vport_node_guid); 340 341static int mlx5_query_nic_vport_port_guid(struct mlx5_core_dev *mdev, 342 u64 *port_guid) 343{ 344 u32 *out; 345 int outlen = MLX5_ST_SZ_BYTES(query_nic_vport_context_out); 346 int err; 347 348 out = mlx5_vzalloc(outlen); 349 if (!out) 350 return -ENOMEM; 351 352 err = mlx5_query_nic_vport_context(mdev, 0, out, outlen); 353 if (err) 354 goto out; 355 356 *port_guid = MLX5_GET64(query_nic_vport_context_out, out, 357 nic_vport_context.port_guid); 358 359out: 360 kvfree(out); 361 return err; 362} 363 364int mlx5_query_nic_vport_qkey_viol_cntr(struct mlx5_core_dev *mdev, 365 u16 *qkey_viol_cntr) 366{ 367 u32 *out; 368 int outlen = MLX5_ST_SZ_BYTES(query_nic_vport_context_out); 369 int err; 370 371 out = mlx5_vzalloc(outlen); 372 if (!out) 373 return -ENOMEM; 374 375 err = mlx5_query_nic_vport_context(mdev, 0, out, outlen); 376 if (err) 377 goto out; 378 379 *qkey_viol_cntr = MLX5_GET(query_nic_vport_context_out, out, 380 nic_vport_context.qkey_violation_counter); 381 382out: 383 kvfree(out); 384 return err; 385} 386EXPORT_SYMBOL_GPL(mlx5_query_nic_vport_qkey_viol_cntr); 387 388static int mlx5_modify_nic_vport_context(struct mlx5_core_dev *mdev, void *in, 389 int inlen) 390{ 391 u32 out[MLX5_ST_SZ_DW(modify_nic_vport_context_out)]; 392 393 MLX5_SET(modify_nic_vport_context_in, in, opcode, 394 MLX5_CMD_OP_MODIFY_NIC_VPORT_CONTEXT); 395 396 memset(out, 0, sizeof(out)); 397 return mlx5_cmd_exec_check_status(mdev, in, inlen, out, sizeof(out)); 398} 399 400static int mlx5_nic_vport_enable_disable_roce(struct mlx5_core_dev *mdev, 401 int enable_disable) 402{ 403 void *in; 404 int inlen = MLX5_ST_SZ_BYTES(modify_nic_vport_context_in); 405 int err; 406 407 in = mlx5_vzalloc(inlen); 408 if (!in) { 409 mlx5_core_warn(mdev, "failed to allocate inbox\n"); 410 return -ENOMEM; 411 } 412 413 MLX5_SET(modify_nic_vport_context_in, in, field_select.roce_en, 1); 414 MLX5_SET(modify_nic_vport_context_in, in, nic_vport_context.roce_en, 415 enable_disable); 416 417 err = mlx5_modify_nic_vport_context(mdev, in, inlen); 418 419 kvfree(in); 420 421 return err; 422} 423 424int mlx5_set_nic_vport_current_mac(struct mlx5_core_dev *mdev, int vport, 425 bool other_vport, u8 *addr) 426{ 427 void *in; 428 int inlen = MLX5_ST_SZ_BYTES(modify_nic_vport_context_in) 429 + MLX5_ST_SZ_BYTES(mac_address_layout); 430 u8 *mac_layout; 431 u8 *mac_ptr; 432 int err; 433 434 in = mlx5_vzalloc(inlen); 435 if (!in) { 436 mlx5_core_warn(mdev, "failed to allocate inbox\n"); 437 return -ENOMEM; 438 } 439 440 MLX5_SET(modify_nic_vport_context_in, in, 441 opcode, MLX5_CMD_OP_MODIFY_NIC_VPORT_CONTEXT); 442 MLX5_SET(modify_nic_vport_context_in, in, 443 vport_number, vport); 444 MLX5_SET(modify_nic_vport_context_in, in, 445 other_vport, other_vport); 446 MLX5_SET(modify_nic_vport_context_in, in, 447 field_select.addresses_list, 1); 448 MLX5_SET(modify_nic_vport_context_in, in, 449 nic_vport_context.allowed_list_type, 450 MLX5_NIC_VPORT_LIST_TYPE_UC); 451 MLX5_SET(modify_nic_vport_context_in, in, 452 nic_vport_context.allowed_list_size, 1); 453 454 mac_layout = (u8 *)MLX5_ADDR_OF(modify_nic_vport_context_in, in, 455 nic_vport_context.current_uc_mac_address); 456 mac_ptr = (u8 *)MLX5_ADDR_OF(mac_address_layout, mac_layout, 457 mac_addr_47_32); 458 ether_addr_copy(mac_ptr, addr); 459 460 err = mlx5_modify_nic_vport_context(mdev, in, inlen); 461 462 kvfree(in); 463 464 return err; 465} 466EXPORT_SYMBOL_GPL(mlx5_set_nic_vport_current_mac); 467 468int mlx5_modify_nic_vport_node_guid(struct mlx5_core_dev *mdev, 469 u32 vport, u64 node_guid) 470{ 471 void *in; 472 int inlen = MLX5_ST_SZ_BYTES(modify_nic_vport_context_in); 473 int err; 474 void *nic_vport_context; 475 476 if (!vport) 477 return -EINVAL; 478 if (!MLX5_CAP_GEN(mdev, vport_group_manager)) 479 return -EPERM; 480 if (!MLX5_CAP_ESW(mdev, nic_vport_node_guid_modify)) 481 return -ENOTSUPP; 482 483 in = mlx5_vzalloc(inlen); 484 if (!in) { 485 mlx5_core_warn(mdev, "failed to allocate inbox\n"); 486 return -ENOMEM; 487 } 488 489 MLX5_SET(modify_nic_vport_context_in, in, 490 field_select.node_guid, 1); 491 MLX5_SET(modify_nic_vport_context_in, in, vport_number, vport); 492 493 MLX5_SET(modify_nic_vport_context_in, in, other_vport, 1); 494 495 nic_vport_context = MLX5_ADDR_OF(modify_nic_vport_context_in, 496 in, nic_vport_context); 497 MLX5_SET64(nic_vport_context, nic_vport_context, node_guid, node_guid); 498 499 err = mlx5_modify_nic_vport_context(mdev, in, inlen); 500 501 kvfree(in); 502 503 return err; 504} 505EXPORT_SYMBOL(mlx5_modify_nic_vport_node_guid); 506 507int mlx5_modify_nic_vport_port_guid(struct mlx5_core_dev *mdev, 508 u32 vport, u64 port_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_port_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.port_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, port_guid, port_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_port_guid); 545 546int mlx5_set_nic_vport_vlan_list(struct mlx5_core_dev *dev, u16 vport, 547 u16 *vlan_list, int list_len) 548{ 549 void *in, *ctx; 550 int i, err; 551 int inlen = MLX5_ST_SZ_BYTES(modify_nic_vport_context_in) 552 + MLX5_ST_SZ_BYTES(vlan_layout) * (int)list_len; 553 554 int max_list_size = 1 << MLX5_CAP_GEN_MAX(dev, log_max_vlan_list); 555 556 if (list_len > max_list_size) { 557 mlx5_core_warn(dev, "Requested list size (%d) > (%d) max_list_size\n", 558 list_len, max_list_size); 559 return -ENOSPC; 560 } 561 562 in = mlx5_vzalloc(inlen); 563 if (!in) { 564 mlx5_core_warn(dev, "failed to allocate inbox\n"); 565 return -ENOMEM; 566 } 567 568 MLX5_SET(modify_nic_vport_context_in, in, vport_number, vport); 569 if (vport) 570 MLX5_SET(modify_nic_vport_context_in, in, 571 other_vport, 1); 572 MLX5_SET(modify_nic_vport_context_in, in, 573 field_select.addresses_list, 1); 574 575 ctx = MLX5_ADDR_OF(modify_nic_vport_context_in, in, nic_vport_context); 576 577 MLX5_SET(nic_vport_context, ctx, allowed_list_type, 578 MLX5_NIC_VPORT_LIST_TYPE_VLAN); 579 MLX5_SET(nic_vport_context, ctx, allowed_list_size, list_len); 580 581 for (i = 0; i < list_len; i++) { 582 u8 *vlan_lout = MLX5_ADDR_OF(nic_vport_context, ctx, 583 current_uc_mac_address[i]); 584 MLX5_SET(vlan_layout, vlan_lout, vlan, vlan_list[i]); 585 } 586 587 err = mlx5_modify_nic_vport_context(dev, in, inlen); 588 589 kvfree(in); 590 return err; 591} 592EXPORT_SYMBOL_GPL(mlx5_set_nic_vport_vlan_list); 593 594int mlx5_set_nic_vport_mc_list(struct mlx5_core_dev *mdev, int vport, 595 u64 *addr_list, size_t addr_list_len) 596{ 597 void *in, *ctx; 598 int inlen = MLX5_ST_SZ_BYTES(modify_nic_vport_context_in) 599 + MLX5_ST_SZ_BYTES(mac_address_layout) * (int)addr_list_len; 600 int err; 601 size_t i; 602 int max_list_sz = 1 << MLX5_CAP_GEN_MAX(mdev, log_max_current_mc_list); 603 604 if ((int)addr_list_len > max_list_sz) { 605 mlx5_core_warn(mdev, "Requested list size (%d) > (%d) max_list_size\n", 606 (int)addr_list_len, max_list_sz); 607 return -ENOSPC; 608 } 609 610 in = mlx5_vzalloc(inlen); 611 if (!in) { 612 mlx5_core_warn(mdev, "failed to allocate inbox\n"); 613 return -ENOMEM; 614 } 615 616 MLX5_SET(modify_nic_vport_context_in, in, vport_number, vport); 617 if (vport) 618 MLX5_SET(modify_nic_vport_context_in, in, 619 other_vport, 1); 620 MLX5_SET(modify_nic_vport_context_in, in, 621 field_select.addresses_list, 1); 622 623 ctx = MLX5_ADDR_OF(modify_nic_vport_context_in, in, nic_vport_context); 624 625 MLX5_SET(nic_vport_context, ctx, allowed_list_type, 626 MLX5_NIC_VPORT_LIST_TYPE_MC); 627 MLX5_SET(nic_vport_context, ctx, allowed_list_size, addr_list_len); 628 629 for (i = 0; i < addr_list_len; i++) { 630 u8 *mac_lout = (u8 *)MLX5_ADDR_OF(nic_vport_context, ctx, 631 current_uc_mac_address[i]); 632 u8 *mac_ptr = (u8 *)MLX5_ADDR_OF(mac_address_layout, mac_lout, 633 mac_addr_47_32); 634 ether_addr_copy(mac_ptr, (u8 *)&addr_list[i]); 635 } 636 637 err = mlx5_modify_nic_vport_context(mdev, in, inlen); 638 639 kvfree(in); 640 641 return err; 642} 643EXPORT_SYMBOL_GPL(mlx5_set_nic_vport_mc_list); 644 645int mlx5_set_nic_vport_promisc(struct mlx5_core_dev *mdev, int vport, 646 bool promisc_mc, bool promisc_uc, 647 bool promisc_all) 648{ 649 u8 in[MLX5_ST_SZ_BYTES(modify_nic_vport_context_in)]; 650 u8 *ctx = MLX5_ADDR_OF(modify_nic_vport_context_in, in, 651 nic_vport_context); 652 653 memset(in, 0, MLX5_ST_SZ_BYTES(modify_nic_vport_context_in)); 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, field_select.promisc, 1); 660 if (promisc_mc) 661 MLX5_SET(nic_vport_context, ctx, promisc_mc, 1); 662 if (promisc_uc) 663 MLX5_SET(nic_vport_context, ctx, promisc_uc, 1); 664 if (promisc_all) 665 MLX5_SET(nic_vport_context, ctx, promisc_all, 1); 666 667 return mlx5_modify_nic_vport_context(mdev, in, sizeof(in)); 668} 669EXPORT_SYMBOL_GPL(mlx5_set_nic_vport_promisc); 670 671int mlx5_query_nic_vport_mac_list(struct mlx5_core_dev *dev, 672 u16 vport, 673 enum mlx5_list_type list_type, 674 u8 addr_list[][ETH_ALEN], 675 int *list_size) 676{ 677 u32 in[MLX5_ST_SZ_DW(query_nic_vport_context_in)]; 678 void *nic_vport_ctx; 679 int max_list_size; 680 int req_list_size; 681 int out_sz; 682 void *out; 683 int err; 684 int i; 685 686 req_list_size = *list_size; 687 688 max_list_size = (list_type == MLX5_NIC_VPORT_LIST_TYPE_UC) ? 689 1 << MLX5_CAP_GEN_MAX(dev, log_max_current_uc_list) : 690 1 << MLX5_CAP_GEN_MAX(dev, log_max_current_mc_list); 691 692 if (req_list_size > max_list_size) { 693 mlx5_core_warn(dev, "Requested list size (%d) > (%d) max_list_size\n", 694 req_list_size, max_list_size); 695 req_list_size = max_list_size; 696 } 697 698 out_sz = MLX5_ST_SZ_BYTES(modify_nic_vport_context_in) + 699 req_list_size * MLX5_ST_SZ_BYTES(mac_address_layout); 700 701 memset(in, 0, sizeof(in)); 702 out = kzalloc(out_sz, GFP_KERNEL); 703 if (!out) 704 return -ENOMEM; 705 706 MLX5_SET(query_nic_vport_context_in, in, opcode, 707 MLX5_CMD_OP_QUERY_NIC_VPORT_CONTEXT); 708 MLX5_SET(query_nic_vport_context_in, in, allowed_list_type, list_type); 709 MLX5_SET(query_nic_vport_context_in, in, vport_number, vport); 710 711 if (vport) 712 MLX5_SET(query_nic_vport_context_in, in, other_vport, 1); 713 714 err = mlx5_cmd_exec_check_status(dev, in, sizeof(in), out, out_sz); 715 if (err) 716 goto out; 717 718 nic_vport_ctx = MLX5_ADDR_OF(query_nic_vport_context_out, out, 719 nic_vport_context); 720 req_list_size = MLX5_GET(nic_vport_context, nic_vport_ctx, 721 allowed_list_size); 722 723 *list_size = req_list_size; 724 for (i = 0; i < req_list_size; i++) { 725 u8 *mac_addr = MLX5_ADDR_OF(nic_vport_context, 726 nic_vport_ctx, 727 current_uc_mac_address[i]) + 2; 728 ether_addr_copy(addr_list[i], mac_addr); 729 } 730out: 731 kfree(out); 732 return err; 733} 734EXPORT_SYMBOL_GPL(mlx5_query_nic_vport_mac_list); 735 736int mlx5_modify_nic_vport_mac_list(struct mlx5_core_dev *dev, 737 enum mlx5_list_type list_type, 738 u8 addr_list[][ETH_ALEN], 739 int list_size) 740{ 741 u32 out[MLX5_ST_SZ_DW(modify_nic_vport_context_out)]; 742 void *nic_vport_ctx; 743 int max_list_size; 744 int in_sz; 745 void *in; 746 int err; 747 int i; 748 749 max_list_size = list_type == MLX5_NIC_VPORT_LIST_TYPE_UC ? 750 1 << MLX5_CAP_GEN(dev, log_max_current_uc_list) : 751 1 << MLX5_CAP_GEN(dev, log_max_current_mc_list); 752 753 if (list_size > max_list_size) 754 return -ENOSPC; 755 756 in_sz = MLX5_ST_SZ_BYTES(modify_nic_vport_context_in) + 757 list_size * MLX5_ST_SZ_BYTES(mac_address_layout); 758 759 memset(out, 0, sizeof(out)); 760 in = kzalloc(in_sz, GFP_KERNEL); 761 if (!in) 762 return -ENOMEM; 763 764 MLX5_SET(modify_nic_vport_context_in, in, opcode, 765 MLX5_CMD_OP_MODIFY_NIC_VPORT_CONTEXT); 766 MLX5_SET(modify_nic_vport_context_in, in, 767 field_select.addresses_list, 1); 768 769 nic_vport_ctx = MLX5_ADDR_OF(modify_nic_vport_context_in, in, 770 nic_vport_context); 771 772 MLX5_SET(nic_vport_context, nic_vport_ctx, 773 allowed_list_type, list_type); 774 MLX5_SET(nic_vport_context, nic_vport_ctx, 775 allowed_list_size, list_size); 776 777 for (i = 0; i < list_size; i++) { 778 u8 *curr_mac = MLX5_ADDR_OF(nic_vport_context, 779 nic_vport_ctx, 780 current_uc_mac_address[i]) + 2; 781 ether_addr_copy(curr_mac, addr_list[i]); 782 } 783 784 err = mlx5_cmd_exec_check_status(dev, in, in_sz, out, sizeof(out)); 785 kfree(in); 786 return err; 787} 788EXPORT_SYMBOL_GPL(mlx5_modify_nic_vport_mac_list); 789 790int mlx5_query_nic_vport_vlans(struct mlx5_core_dev *dev, 791 u16 vport, 792 u16 vlans[], 793 int *size) 794{ 795 u32 in[MLX5_ST_SZ_DW(query_nic_vport_context_in)]; 796 void *nic_vport_ctx; 797 int req_list_size; 798 int max_list_size; 799 int out_sz; 800 void *out; 801 int err; 802 int i; 803 804 req_list_size = *size; 805 max_list_size = 1 << MLX5_CAP_GEN(dev, log_max_vlan_list); 806 if (req_list_size > max_list_size) { 807 mlx5_core_warn(dev, "Requested list size (%d) > (%d) max list size\n", 808 req_list_size, max_list_size); 809 req_list_size = max_list_size; 810 } 811 812 out_sz = MLX5_ST_SZ_BYTES(modify_nic_vport_context_in) + 813 req_list_size * MLX5_ST_SZ_BYTES(vlan_layout); 814 815 memset(in, 0, sizeof(in)); 816 out = kzalloc(out_sz, GFP_KERNEL); 817 if (!out) 818 return -ENOMEM; 819 820 MLX5_SET(query_nic_vport_context_in, in, opcode, 821 MLX5_CMD_OP_QUERY_NIC_VPORT_CONTEXT); 822 MLX5_SET(query_nic_vport_context_in, in, allowed_list_type, 823 MLX5_NIC_VPORT_CONTEXT_ALLOWED_LIST_TYPE_VLAN_LIST); 824 MLX5_SET(query_nic_vport_context_in, in, vport_number, vport); 825 826 if (vport) 827 MLX5_SET(query_nic_vport_context_in, in, other_vport, 1); 828 829 err = mlx5_cmd_exec_check_status(dev, in, sizeof(in), out, out_sz); 830 if (err) 831 goto out; 832 833 nic_vport_ctx = MLX5_ADDR_OF(query_nic_vport_context_out, out, 834 nic_vport_context); 835 req_list_size = MLX5_GET(nic_vport_context, nic_vport_ctx, 836 allowed_list_size); 837 838 *size = req_list_size; 839 for (i = 0; i < req_list_size; i++) { 840 void *vlan_addr = MLX5_ADDR_OF(nic_vport_context, 841 nic_vport_ctx, 842 current_uc_mac_address[i]); 843 vlans[i] = MLX5_GET(vlan_layout, vlan_addr, vlan); 844 } 845out: 846 kfree(out); 847 return err; 848} 849EXPORT_SYMBOL_GPL(mlx5_query_nic_vport_vlans); 850 851int mlx5_modify_nic_vport_vlans(struct mlx5_core_dev *dev, 852 u16 vlans[], 853 int list_size) 854{ 855 u32 out[MLX5_ST_SZ_DW(modify_nic_vport_context_out)]; 856 void *nic_vport_ctx; 857 int max_list_size; 858 int in_sz; 859 void *in; 860 int err; 861 int i; 862 863 max_list_size = 1 << MLX5_CAP_GEN(dev, log_max_vlan_list); 864 865 if (list_size > max_list_size) 866 return -ENOSPC; 867 868 in_sz = MLX5_ST_SZ_BYTES(modify_nic_vport_context_in) + 869 list_size * MLX5_ST_SZ_BYTES(vlan_layout); 870 871 memset(out, 0, sizeof(out)); 872 in = kzalloc(in_sz, GFP_KERNEL); 873 if (!in) 874 return -ENOMEM; 875 876 MLX5_SET(modify_nic_vport_context_in, in, opcode, 877 MLX5_CMD_OP_MODIFY_NIC_VPORT_CONTEXT); 878 MLX5_SET(modify_nic_vport_context_in, in, 879 field_select.addresses_list, 1); 880 881 nic_vport_ctx = MLX5_ADDR_OF(modify_nic_vport_context_in, in, 882 nic_vport_context); 883 884 MLX5_SET(nic_vport_context, nic_vport_ctx, 885 allowed_list_type, MLX5_NIC_VPORT_LIST_TYPE_VLAN); 886 MLX5_SET(nic_vport_context, nic_vport_ctx, 887 allowed_list_size, list_size); 888 889 for (i = 0; i < list_size; i++) { 890 void *vlan_addr = MLX5_ADDR_OF(nic_vport_context, 891 nic_vport_ctx, 892 current_uc_mac_address[i]); 893 MLX5_SET(vlan_layout, vlan_addr, vlan, vlans[i]); 894 } 895 896 err = mlx5_cmd_exec_check_status(dev, in, in_sz, out, sizeof(out)); 897 kfree(in); 898 return err; 899} 900EXPORT_SYMBOL_GPL(mlx5_modify_nic_vport_vlans); 901 902int mlx5_query_nic_vport_roce_en(struct mlx5_core_dev *mdev, u8 *enable) 903{ 904 u32 *out; 905 int outlen = MLX5_ST_SZ_BYTES(query_nic_vport_context_out); 906 int err; 907 908 out = kzalloc(outlen, GFP_KERNEL); 909 if (!out) 910 return -ENOMEM; 911 912 err = mlx5_query_nic_vport_context(mdev, 0, out, outlen); 913 if (err) 914 goto out; 915 916 *enable = MLX5_GET(query_nic_vport_context_out, out, 917 nic_vport_context.roce_en); 918 919out: 920 kfree(out); 921 return err; 922} 923EXPORT_SYMBOL_GPL(mlx5_query_nic_vport_roce_en); 924 925int mlx5_set_nic_vport_permanent_mac(struct mlx5_core_dev *mdev, int vport, 926 u8 *addr) 927{ 928 void *in; 929 int inlen = MLX5_ST_SZ_BYTES(modify_nic_vport_context_in); 930 u8 *mac_ptr; 931 int err; 932 933 in = mlx5_vzalloc(inlen); 934 if (!in) { 935 mlx5_core_warn(mdev, "failed to allocate inbox\n"); 936 return -ENOMEM; 937 } 938 939 MLX5_SET(modify_nic_vport_context_in, in, 940 opcode, MLX5_CMD_OP_MODIFY_NIC_VPORT_CONTEXT); 941 MLX5_SET(modify_nic_vport_context_in, in, vport_number, vport); 942 MLX5_SET(modify_nic_vport_context_in, in, other_vport, 1); 943 MLX5_SET(modify_nic_vport_context_in, in, 944 field_select.permanent_address, 1); 945 mac_ptr = (u8 *)MLX5_ADDR_OF(modify_nic_vport_context_in, in, 946 nic_vport_context.permanent_address.mac_addr_47_32); 947 ether_addr_copy(mac_ptr, addr); 948 949 err = mlx5_modify_nic_vport_context(mdev, in, inlen); 950 951 kvfree(in); 952 953 return err; 954} 955EXPORT_SYMBOL_GPL(mlx5_set_nic_vport_permanent_mac); 956 957int mlx5_nic_vport_enable_roce(struct mlx5_core_dev *mdev) 958{ 959 return mlx5_nic_vport_enable_disable_roce(mdev, 1); 960} 961EXPORT_SYMBOL_GPL(mlx5_nic_vport_enable_roce); 962 963int mlx5_nic_vport_disable_roce(struct mlx5_core_dev *mdev) 964{ 965 return mlx5_nic_vport_enable_disable_roce(mdev, 0); 966} 967EXPORT_SYMBOL_GPL(mlx5_nic_vport_disable_roce); 968 969int mlx5_query_hca_vport_context(struct mlx5_core_dev *mdev, 970 u8 port_num, u8 vport_num, u32 *out, 971 int outlen) 972{ 973 u32 in[MLX5_ST_SZ_DW(query_hca_vport_context_in)]; 974 int is_group_manager; 975 976 is_group_manager = MLX5_CAP_GEN(mdev, vport_group_manager); 977 978 memset(in, 0, sizeof(in)); 979 980 MLX5_SET(query_hca_vport_context_in, in, opcode, 981 MLX5_CMD_OP_QUERY_HCA_VPORT_CONTEXT); 982 983 if (vport_num) { 984 if (is_group_manager) { 985 MLX5_SET(query_hca_vport_context_in, in, other_vport, 986 1); 987 MLX5_SET(query_hca_vport_context_in, in, vport_number, 988 vport_num); 989 } else { 990 return -EPERM; 991 } 992 } 993 994 if (MLX5_CAP_GEN(mdev, num_ports) == 2) 995 MLX5_SET(query_hca_vport_context_in, in, port_num, port_num); 996 997 return mlx5_cmd_exec_check_status(mdev, in, sizeof(in), out, outlen); 998} 999 1000int mlx5_query_hca_vport_system_image_guid(struct mlx5_core_dev *mdev, 1001 u64 *system_image_guid) 1002{ 1003 u32 *out; 1004 int outlen = MLX5_ST_SZ_BYTES(query_hca_vport_context_out); 1005 int err; 1006 1007 out = mlx5_vzalloc(outlen); 1008 if (!out) 1009 return -ENOMEM; 1010 1011 err = mlx5_query_hca_vport_context(mdev, 1, 0, out, outlen); 1012 if (err) 1013 goto out; 1014 1015 *system_image_guid = MLX5_GET64(query_hca_vport_context_out, out, 1016 hca_vport_context.system_image_guid); 1017 1018out: 1019 kvfree(out); 1020 return err; 1021} 1022EXPORT_SYMBOL_GPL(mlx5_query_hca_vport_system_image_guid); 1023 1024int mlx5_query_hca_vport_node_guid(struct mlx5_core_dev *mdev, u64 *node_guid) 1025{ 1026 u32 *out; 1027 int outlen = MLX5_ST_SZ_BYTES(query_hca_vport_context_out); 1028 int err; 1029 1030 out = mlx5_vzalloc(outlen); 1031 if (!out) 1032 return -ENOMEM; 1033 1034 err = mlx5_query_hca_vport_context(mdev, 1, 0, out, outlen); 1035 if (err) 1036 goto out; 1037 1038 *node_guid = MLX5_GET64(query_hca_vport_context_out, out, 1039 hca_vport_context.node_guid); 1040 1041out: 1042 kvfree(out); 1043 return err; 1044} 1045EXPORT_SYMBOL_GPL(mlx5_query_hca_vport_node_guid); 1046 1047static int mlx5_query_hca_vport_port_guid(struct mlx5_core_dev *mdev, 1048 u64 *port_guid) 1049{ 1050 u32 *out; 1051 int outlen = MLX5_ST_SZ_BYTES(query_hca_vport_context_out); 1052 int err; 1053 1054 out = mlx5_vzalloc(outlen); 1055 if (!out) 1056 return -ENOMEM; 1057 1058 err = mlx5_query_hca_vport_context(mdev, 1, 0, out, outlen); 1059 if (err) 1060 goto out; 1061 1062 *port_guid = MLX5_GET64(query_hca_vport_context_out, out, 1063 hca_vport_context.port_guid); 1064 1065out: 1066 kvfree(out); 1067 return err; 1068} 1069 1070int mlx5_query_hca_vport_gid(struct mlx5_core_dev *dev, u8 port_num, 1071 u16 vport_num, u16 gid_index, union ib_gid *gid) 1072{ 1073 int in_sz = MLX5_ST_SZ_BYTES(query_hca_vport_gid_in); 1074 int out_sz = MLX5_ST_SZ_BYTES(query_hca_vport_gid_out); 1075 int is_group_manager; 1076 void *out = NULL; 1077 void *in = NULL; 1078 union ib_gid *tmp; 1079 int tbsz; 1080 int nout; 1081 int err; 1082 1083 is_group_manager = MLX5_CAP_GEN(dev, vport_group_manager); 1084 tbsz = mlx5_get_gid_table_len(MLX5_CAP_GEN(dev, gid_table_size)); 1085 1086 if (gid_index > tbsz && gid_index != 0xffff) 1087 return -EINVAL; 1088 1089 if (gid_index == 0xffff) 1090 nout = tbsz; 1091 else 1092 nout = 1; 1093 1094 out_sz += nout * sizeof(*gid); 1095 1096 in = mlx5_vzalloc(in_sz); 1097 out = mlx5_vzalloc(out_sz); 1098 if (!in || !out) { 1099 err = -ENOMEM; 1100 goto out; 1101 } 1102 1103 MLX5_SET(query_hca_vport_gid_in, in, opcode, 1104 MLX5_CMD_OP_QUERY_HCA_VPORT_GID); 1105 if (vport_num) { 1106 if (is_group_manager) { 1107 MLX5_SET(query_hca_vport_gid_in, in, vport_number, 1108 vport_num); 1109 MLX5_SET(query_hca_vport_gid_in, in, other_vport, 1); 1110 } else { 1111 err = -EPERM; 1112 goto out; 1113 } 1114 } 1115 1116 MLX5_SET(query_hca_vport_gid_in, in, gid_index, gid_index); 1117 1118 if (MLX5_CAP_GEN(dev, num_ports) == 2) 1119 MLX5_SET(query_hca_vport_gid_in, in, port_num, port_num); 1120 1121 err = mlx5_cmd_exec(dev, in, in_sz, out, out_sz); 1122 if (err) 1123 goto out; 1124 1125 err = mlx5_cmd_status_to_err_v2(out); 1126 if (err) 1127 goto out; 1128 1129 tmp = (union ib_gid *)MLX5_ADDR_OF(query_hca_vport_gid_out, out, gid); 1130 gid->global.subnet_prefix = tmp->global.subnet_prefix; 1131 gid->global.interface_id = tmp->global.interface_id; 1132 1133out: 1134 kvfree(in); 1135 kvfree(out); 1136 return err; 1137} 1138EXPORT_SYMBOL_GPL(mlx5_query_hca_vport_gid); 1139 1140int mlx5_query_hca_vport_pkey(struct mlx5_core_dev *dev, u8 other_vport, 1141 u8 port_num, u16 vf_num, u16 pkey_index, 1142 u16 *pkey) 1143{ 1144 int in_sz = MLX5_ST_SZ_BYTES(query_hca_vport_pkey_in); 1145 int out_sz = MLX5_ST_SZ_BYTES(query_hca_vport_pkey_out); 1146 int is_group_manager; 1147 void *out = NULL; 1148 void *in = NULL; 1149 void *pkarr; 1150 int nout; 1151 int tbsz; 1152 int err; 1153 int i; 1154 1155 is_group_manager = MLX5_CAP_GEN(dev, vport_group_manager); 1156 1157 tbsz = mlx5_to_sw_pkey_sz(MLX5_CAP_GEN(dev, pkey_table_size)); 1158 if (pkey_index > tbsz && pkey_index != 0xffff) 1159 return -EINVAL; 1160 1161 if (pkey_index == 0xffff) 1162 nout = tbsz; 1163 else 1164 nout = 1; 1165 1166 out_sz += nout * MLX5_ST_SZ_BYTES(pkey); 1167 1168 in = kzalloc(in_sz, GFP_KERNEL); 1169 out = kzalloc(out_sz, GFP_KERNEL); 1170 1171 MLX5_SET(query_hca_vport_pkey_in, in, opcode, 1172 MLX5_CMD_OP_QUERY_HCA_VPORT_PKEY); 1173 if (other_vport) { 1174 if (is_group_manager) { 1175 MLX5_SET(query_hca_vport_pkey_in, in, vport_number, 1176 vf_num); 1177 MLX5_SET(query_hca_vport_pkey_in, in, other_vport, 1); 1178 } else { 1179 err = -EPERM; 1180 goto out; 1181 } 1182 } 1183 MLX5_SET(query_hca_vport_pkey_in, in, pkey_index, pkey_index); 1184 1185 if (MLX5_CAP_GEN(dev, num_ports) == 2) 1186 MLX5_SET(query_hca_vport_pkey_in, in, port_num, port_num); 1187 1188 err = mlx5_cmd_exec(dev, in, in_sz, out, out_sz); 1189 if (err) 1190 goto out; 1191 1192 err = mlx5_cmd_status_to_err_v2(out); 1193 if (err) 1194 goto out; 1195 1196 pkarr = MLX5_ADDR_OF(query_hca_vport_pkey_out, out, pkey); 1197 for (i = 0; i < nout; i++, pkey++, 1198 pkarr += MLX5_ST_SZ_BYTES(pkey)) 1199 *pkey = MLX5_GET_PR(pkey, pkarr, pkey); 1200 1201out: 1202 kfree(in); 1203 kfree(out); 1204 return err; 1205} 1206EXPORT_SYMBOL_GPL(mlx5_query_hca_vport_pkey); 1207 1208static int mlx5_query_hca_min_wqe_header(struct mlx5_core_dev *mdev, 1209 int *min_header) 1210{ 1211 u32 *out; 1212 u32 outlen = MLX5_ST_SZ_BYTES(query_hca_vport_context_out); 1213 int err; 1214 1215 out = mlx5_vzalloc(outlen); 1216 if (!out) 1217 return -ENOMEM; 1218 1219 err = mlx5_query_hca_vport_context(mdev, 1, 0, out, outlen); 1220 if (err) 1221 goto out; 1222 1223 *min_header = MLX5_GET(query_hca_vport_context_out, out, 1224 hca_vport_context.min_wqe_inline_mode); 1225 1226out: 1227 kvfree(out); 1228 return err; 1229} 1230 1231static int mlx5_modify_eswitch_vport_context(struct mlx5_core_dev *mdev, 1232 u16 vport, void *in, int inlen) 1233{ 1234 u32 out[MLX5_ST_SZ_DW(modify_esw_vport_context_out)]; 1235 int err; 1236 1237 memset(out, 0, sizeof(out)); 1238 1239 MLX5_SET(modify_esw_vport_context_in, in, vport_number, vport); 1240 if (vport) 1241 MLX5_SET(modify_esw_vport_context_in, in, other_vport, 1); 1242 1243 MLX5_SET(modify_esw_vport_context_in, in, opcode, 1244 MLX5_CMD_OP_MODIFY_ESW_VPORT_CONTEXT); 1245 1246 err = mlx5_cmd_exec_check_status(mdev, in, inlen, 1247 out, sizeof(out)); 1248 if (err) 1249 mlx5_core_warn(mdev, "MLX5_CMD_OP_MODIFY_ESW_VPORT_CONTEXT failed\n"); 1250 1251 return err; 1252} 1253 1254int mlx5_set_eswitch_cvlan_info(struct mlx5_core_dev *mdev, u8 vport, 1255 u8 insert_mode, u8 strip_mode, 1256 u16 vlan, u8 cfi, u8 pcp) 1257{ 1258 u32 in[MLX5_ST_SZ_DW(modify_esw_vport_context_in)]; 1259 1260 memset(in, 0, sizeof(in)); 1261 1262 if (insert_mode != MLX5_MODIFY_ESW_VPORT_CONTEXT_CVLAN_INSERT_NONE) { 1263 MLX5_SET(modify_esw_vport_context_in, in, 1264 esw_vport_context.cvlan_cfi, cfi); 1265 MLX5_SET(modify_esw_vport_context_in, in, 1266 esw_vport_context.cvlan_pcp, pcp); 1267 MLX5_SET(modify_esw_vport_context_in, in, 1268 esw_vport_context.cvlan_id, vlan); 1269 } 1270 1271 MLX5_SET(modify_esw_vport_context_in, in, 1272 esw_vport_context.vport_cvlan_insert, insert_mode); 1273 1274 MLX5_SET(modify_esw_vport_context_in, in, 1275 esw_vport_context.vport_cvlan_strip, strip_mode); 1276 1277 MLX5_SET(modify_esw_vport_context_in, in, field_select, 1278 MLX5_MODIFY_ESW_VPORT_CONTEXT_FIELD_SELECT_CVLAN_STRIP | 1279 MLX5_MODIFY_ESW_VPORT_CONTEXT_FIELD_SELECT_CVLAN_INSERT); 1280 1281 return mlx5_modify_eswitch_vport_context(mdev, vport, in, sizeof(in)); 1282} 1283EXPORT_SYMBOL_GPL(mlx5_set_eswitch_cvlan_info); 1284 1285int mlx5_query_vport_mtu(struct mlx5_core_dev *mdev, int *mtu) 1286{ 1287 u32 *out; 1288 u32 outlen = MLX5_ST_SZ_BYTES(query_nic_vport_context_out); 1289 int err; 1290 1291 out = mlx5_vzalloc(outlen); 1292 if (!out) 1293 return -ENOMEM; 1294 1295 err = mlx5_query_nic_vport_context(mdev, 0, out, outlen); 1296 if (err) 1297 goto out; 1298 1299 *mtu = MLX5_GET(query_nic_vport_context_out, out, 1300 nic_vport_context.mtu); 1301 1302out: 1303 kvfree(out); 1304 return err; 1305} 1306EXPORT_SYMBOL_GPL(mlx5_query_vport_mtu); 1307 1308int mlx5_set_vport_mtu(struct mlx5_core_dev *mdev, int mtu) 1309{ 1310 u32 *in; 1311 u32 inlen = MLX5_ST_SZ_BYTES(modify_nic_vport_context_in); 1312 int err; 1313 1314 in = mlx5_vzalloc(inlen); 1315 if (!in) 1316 return -ENOMEM; 1317 1318 MLX5_SET(modify_nic_vport_context_in, in, field_select.mtu, 1); 1319 MLX5_SET(modify_nic_vport_context_in, in, nic_vport_context.mtu, mtu); 1320 1321 err = mlx5_modify_nic_vport_context(mdev, in, inlen); 1322 1323 kvfree(in); 1324 return err; 1325} 1326EXPORT_SYMBOL_GPL(mlx5_set_vport_mtu); 1327 1328static int mlx5_query_vport_min_wqe_header(struct mlx5_core_dev *mdev, 1329 int *min_header) 1330{ 1331 u32 *out; 1332 u32 outlen = MLX5_ST_SZ_BYTES(query_nic_vport_context_out); 1333 int err; 1334 1335 out = mlx5_vzalloc(outlen); 1336 if (!out) 1337 return -ENOMEM; 1338 1339 err = mlx5_query_nic_vport_context(mdev, 0, out, outlen); 1340 if (err) 1341 goto out; 1342 1343 *min_header = MLX5_GET(query_nic_vport_context_out, out, 1344 nic_vport_context.min_wqe_inline_mode); 1345 1346out: 1347 kvfree(out); 1348 return err; 1349} 1350 1351int mlx5_set_vport_min_wqe_header(struct mlx5_core_dev *mdev, 1352 u8 vport, int min_header) 1353{ 1354 u32 *in; 1355 u32 inlen = MLX5_ST_SZ_BYTES(modify_nic_vport_context_in); 1356 int err; 1357 1358 in = mlx5_vzalloc(inlen); 1359 if (!in) 1360 return -ENOMEM; 1361 1362 MLX5_SET(modify_nic_vport_context_in, in, 1363 field_select.min_wqe_inline_mode, 1); 1364 MLX5_SET(modify_nic_vport_context_in, in, 1365 nic_vport_context.min_wqe_inline_mode, min_header); 1366 MLX5_SET(modify_nic_vport_context_in, in, vport_number, vport); 1367 MLX5_SET(modify_nic_vport_context_in, in, other_vport, 1); 1368 1369 err = mlx5_modify_nic_vport_context(mdev, in, inlen); 1370 1371 kvfree(in); 1372 return err; 1373} 1374EXPORT_SYMBOL_GPL(mlx5_set_vport_min_wqe_header); 1375 1376int mlx5_query_min_wqe_header(struct mlx5_core_dev *dev, int *min_header) 1377{ 1378 switch (MLX5_CAP_GEN(dev, port_type)) { 1379 case MLX5_CMD_HCA_CAP_PORT_TYPE_IB: 1380 return mlx5_query_hca_min_wqe_header(dev, min_header); 1381 1382 case MLX5_CMD_HCA_CAP_PORT_TYPE_ETHERNET: 1383 return mlx5_query_vport_min_wqe_header(dev, min_header); 1384 1385 default: 1386 return -EINVAL; 1387 } 1388} 1389EXPORT_SYMBOL_GPL(mlx5_query_min_wqe_header); 1390 1391int mlx5_query_nic_vport_promisc(struct mlx5_core_dev *mdev, 1392 u16 vport, 1393 int *promisc_uc, 1394 int *promisc_mc, 1395 int *promisc_all) 1396{ 1397 u32 *out; 1398 int outlen = MLX5_ST_SZ_BYTES(query_nic_vport_context_out); 1399 int err; 1400 1401 out = kzalloc(outlen, GFP_KERNEL); 1402 if (!out) 1403 return -ENOMEM; 1404 1405 err = mlx5_query_nic_vport_context(mdev, vport, out, outlen); 1406 if (err) 1407 goto out; 1408 1409 *promisc_uc = MLX5_GET(query_nic_vport_context_out, out, 1410 nic_vport_context.promisc_uc); 1411 *promisc_mc = MLX5_GET(query_nic_vport_context_out, out, 1412 nic_vport_context.promisc_mc); 1413 *promisc_all = MLX5_GET(query_nic_vport_context_out, out, 1414 nic_vport_context.promisc_all); 1415 1416out: 1417 kfree(out); 1418 return err; 1419} 1420EXPORT_SYMBOL_GPL(mlx5_query_nic_vport_promisc); 1421 1422int mlx5_modify_nic_vport_promisc(struct mlx5_core_dev *mdev, 1423 int promisc_uc, 1424 int promisc_mc, 1425 int promisc_all) 1426{ 1427 void *in; 1428 int inlen = MLX5_ST_SZ_BYTES(modify_nic_vport_context_in); 1429 int err; 1430 1431 in = mlx5_vzalloc(inlen); 1432 if (!in) { 1433 mlx5_core_err(mdev, "failed to allocate inbox\n"); 1434 return -ENOMEM; 1435 } 1436 1437 MLX5_SET(modify_nic_vport_context_in, in, field_select.promisc, 1); 1438 MLX5_SET(modify_nic_vport_context_in, in, 1439 nic_vport_context.promisc_uc, promisc_uc); 1440 MLX5_SET(modify_nic_vport_context_in, in, 1441 nic_vport_context.promisc_mc, promisc_mc); 1442 MLX5_SET(modify_nic_vport_context_in, in, 1443 nic_vport_context.promisc_all, promisc_all); 1444 1445 err = mlx5_modify_nic_vport_context(mdev, in, inlen); 1446 kvfree(in); 1447 return err; 1448} 1449EXPORT_SYMBOL_GPL(mlx5_modify_nic_vport_promisc); 1450 1451int mlx5_query_vport_counter(struct mlx5_core_dev *dev, 1452 u8 port_num, u16 vport_num, 1453 void *out, int out_size) 1454{ 1455 int in_sz = MLX5_ST_SZ_BYTES(query_vport_counter_in); 1456 int is_group_manager; 1457 void *in; 1458 int err; 1459 1460 is_group_manager = MLX5_CAP_GEN(dev, vport_group_manager); 1461 1462 in = mlx5_vzalloc(in_sz); 1463 if (!in) 1464 return -ENOMEM; 1465 1466 MLX5_SET(query_vport_counter_in, in, opcode, 1467 MLX5_CMD_OP_QUERY_VPORT_COUNTER); 1468 if (vport_num) { 1469 if (is_group_manager) { 1470 MLX5_SET(query_vport_counter_in, in, other_vport, 1); 1471 MLX5_SET(query_vport_counter_in, in, vport_number, 1472 vport_num); 1473 } else { 1474 err = -EPERM; 1475 goto ex; 1476 } 1477 } 1478 if (MLX5_CAP_GEN(dev, num_ports) == 2) 1479 MLX5_SET(query_vport_counter_in, in, port_num, port_num); 1480 1481 err = mlx5_cmd_exec(dev, in, in_sz, out, out_size); 1482 if (err) 1483 goto ex; 1484 err = mlx5_cmd_status_to_err_v2(out); 1485 if (err) 1486 goto ex; 1487 1488ex: 1489 kvfree(in); 1490 return err; 1491} 1492EXPORT_SYMBOL_GPL(mlx5_query_vport_counter); 1493 1494int mlx5_get_vport_counters(struct mlx5_core_dev *dev, u8 port_num, 1495 struct mlx5_vport_counters *vc) 1496{ 1497 int out_sz = MLX5_ST_SZ_BYTES(query_vport_counter_out); 1498 void *out; 1499 int err; 1500 1501 out = mlx5_vzalloc(out_sz); 1502 if (!out) 1503 return -ENOMEM; 1504 1505 err = mlx5_query_vport_counter(dev, port_num, 0, out, out_sz); 1506 if (err) 1507 goto ex; 1508 1509 vc->received_errors.packets = 1510 MLX5_GET64(query_vport_counter_out, 1511 out, received_errors.packets); 1512 vc->received_errors.octets = 1513 MLX5_GET64(query_vport_counter_out, 1514 out, received_errors.octets); 1515 vc->transmit_errors.packets = 1516 MLX5_GET64(query_vport_counter_out, 1517 out, transmit_errors.packets); 1518 vc->transmit_errors.octets = 1519 MLX5_GET64(query_vport_counter_out, 1520 out, transmit_errors.octets); 1521 vc->received_ib_unicast.packets = 1522 MLX5_GET64(query_vport_counter_out, 1523 out, received_ib_unicast.packets); 1524 vc->received_ib_unicast.octets = 1525 MLX5_GET64(query_vport_counter_out, 1526 out, received_ib_unicast.octets); 1527 vc->transmitted_ib_unicast.packets = 1528 MLX5_GET64(query_vport_counter_out, 1529 out, transmitted_ib_unicast.packets); 1530 vc->transmitted_ib_unicast.octets = 1531 MLX5_GET64(query_vport_counter_out, 1532 out, transmitted_ib_unicast.octets); 1533 vc->received_ib_multicast.packets = 1534 MLX5_GET64(query_vport_counter_out, 1535 out, received_ib_multicast.packets); 1536 vc->received_ib_multicast.octets = 1537 MLX5_GET64(query_vport_counter_out, 1538 out, received_ib_multicast.octets); 1539 vc->transmitted_ib_multicast.packets = 1540 MLX5_GET64(query_vport_counter_out, 1541 out, transmitted_ib_multicast.packets); 1542 vc->transmitted_ib_multicast.octets = 1543 MLX5_GET64(query_vport_counter_out, 1544 out, transmitted_ib_multicast.octets); 1545 vc->received_eth_broadcast.packets = 1546 MLX5_GET64(query_vport_counter_out, 1547 out, received_eth_broadcast.packets); 1548 vc->received_eth_broadcast.octets = 1549 MLX5_GET64(query_vport_counter_out, 1550 out, received_eth_broadcast.octets); 1551 vc->transmitted_eth_broadcast.packets = 1552 MLX5_GET64(query_vport_counter_out, 1553 out, transmitted_eth_broadcast.packets); 1554 vc->transmitted_eth_broadcast.octets = 1555 MLX5_GET64(query_vport_counter_out, 1556 out, transmitted_eth_broadcast.octets); 1557 vc->received_eth_unicast.octets = 1558 MLX5_GET64(query_vport_counter_out, 1559 out, received_eth_unicast.octets); 1560 vc->received_eth_unicast.packets = 1561 MLX5_GET64(query_vport_counter_out, 1562 out, received_eth_unicast.packets); 1563 vc->transmitted_eth_unicast.octets = 1564 MLX5_GET64(query_vport_counter_out, 1565 out, transmitted_eth_unicast.octets); 1566 vc->transmitted_eth_unicast.packets = 1567 MLX5_GET64(query_vport_counter_out, 1568 out, transmitted_eth_unicast.packets); 1569 vc->received_eth_multicast.octets = 1570 MLX5_GET64(query_vport_counter_out, 1571 out, received_eth_multicast.octets); 1572 vc->received_eth_multicast.packets = 1573 MLX5_GET64(query_vport_counter_out, 1574 out, received_eth_multicast.packets); 1575 vc->transmitted_eth_multicast.octets = 1576 MLX5_GET64(query_vport_counter_out, 1577 out, transmitted_eth_multicast.octets); 1578 vc->transmitted_eth_multicast.packets = 1579 MLX5_GET64(query_vport_counter_out, 1580 out, transmitted_eth_multicast.packets); 1581 1582ex: 1583 kvfree(out); 1584 return err; 1585} 1586 1587int mlx5_query_vport_system_image_guid(struct mlx5_core_dev *dev, 1588 u64 *sys_image_guid) 1589{ 1590 switch (MLX5_CAP_GEN(dev, port_type)) { 1591 case MLX5_CMD_HCA_CAP_PORT_TYPE_IB: 1592 return mlx5_query_hca_vport_system_image_guid(dev, 1593 sys_image_guid); 1594 1595 case MLX5_CMD_HCA_CAP_PORT_TYPE_ETHERNET: 1596 return mlx5_query_nic_vport_system_image_guid(dev, 1597 sys_image_guid); 1598 1599 default: 1600 return -EINVAL; 1601 } 1602} 1603EXPORT_SYMBOL_GPL(mlx5_query_vport_system_image_guid); 1604 1605int mlx5_query_vport_node_guid(struct mlx5_core_dev *dev, u64 *node_guid) 1606{ 1607 switch (MLX5_CAP_GEN(dev, port_type)) { 1608 case MLX5_CMD_HCA_CAP_PORT_TYPE_IB: 1609 return mlx5_query_hca_vport_node_guid(dev, node_guid); 1610 1611 case MLX5_CMD_HCA_CAP_PORT_TYPE_ETHERNET: 1612 return mlx5_query_nic_vport_node_guid(dev, node_guid); 1613 1614 default: 1615 return -EINVAL; 1616 } 1617} 1618EXPORT_SYMBOL_GPL(mlx5_query_vport_node_guid); 1619 1620int mlx5_query_vport_port_guid(struct mlx5_core_dev *dev, u64 *port_guid) 1621{ 1622 switch (MLX5_CAP_GEN(dev, port_type)) { 1623 case MLX5_CMD_HCA_CAP_PORT_TYPE_IB: 1624 return mlx5_query_hca_vport_port_guid(dev, port_guid); 1625 1626 case MLX5_CMD_HCA_CAP_PORT_TYPE_ETHERNET: 1627 return mlx5_query_nic_vport_port_guid(dev, port_guid); 1628 1629 default: 1630 return -EINVAL; 1631 } 1632} 1633EXPORT_SYMBOL_GPL(mlx5_query_vport_port_guid); 1634 1635int mlx5_query_hca_vport_state(struct mlx5_core_dev *dev, u8 *vport_state) 1636{ 1637 u32 *out; 1638 int outlen = MLX5_ST_SZ_BYTES(query_hca_vport_context_out); 1639 int err; 1640 1641 out = mlx5_vzalloc(outlen); 1642 if (!out) 1643 return -ENOMEM; 1644 1645 err = mlx5_query_hca_vport_context(dev, 1, 0, out, outlen); 1646 if (err) 1647 goto out; 1648 1649 *vport_state = MLX5_GET(query_hca_vport_context_out, out, 1650 hca_vport_context.vport_state); 1651 1652out: 1653 kvfree(out); 1654 return err; 1655} 1656EXPORT_SYMBOL_GPL(mlx5_query_hca_vport_state); 1657