FILE
vport.c
File preview with syntax highlighting.
linux-6.19.14/drivers/net/ethernet/mellanox/mlx5/core/vport.c
1/* 2 * Copyright (c) 2013-2015, Mellanox Technologies, Ltd. All rights reserved. 3 * 4 * This software is available to you under a choice of one of two 5 * licenses. You may choose to be licensed under the terms of the GNU 6 * General Public License (GPL) Version 2, available from the file 7 * COPYING in the main directory of this source tree, or the 8 * OpenIB.org BSD license below: 9 * 10 * Redistribution and use in source and binary forms, with or 11 * without modification, are permitted provided that the following 12 * conditions are met: 13 * 14 * - Redistributions of source code must retain the above 15 * copyright notice, this list of conditions and the following 16 * disclaimer. 17 * 18 * - Redistributions in binary form must reproduce the above 19 * copyright notice, this list of conditions and the following 20 * disclaimer in the documentation and/or other materials 21 * provided with the distribution. 22 * 23 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, 24 * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF 25 * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND 26 * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS 27 * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN 28 * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN 29 * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 30 * SOFTWARE. 31 */ 32 33#include <linux/export.h> 34#include <linux/etherdevice.h> 35#include <linux/mlx5/driver.h> 36#include <linux/mlx5/vport.h> 37#include <linux/mlx5/eswitch.h> 38#include "mlx5_core.h" 39#include "eswitch.h" 40#include "sf/sf.h" 41 42/* Mutex to hold while enabling or disabling RoCE */ 43static DEFINE_MUTEX(mlx5_roce_en_lock); 44 45u8 mlx5_query_vport_state(struct mlx5_core_dev *mdev, u8 opmod, u16 vport) 46{ 47 u32 out[MLX5_ST_SZ_DW(query_vport_state_out)] = {}; 48 u32 in[MLX5_ST_SZ_DW(query_vport_state_in)] = {}; 49 int err; 50 51 MLX5_SET(query_vport_state_in, in, opcode, 52 MLX5_CMD_OP_QUERY_VPORT_STATE); 53 MLX5_SET(query_vport_state_in, in, op_mod, opmod); 54 MLX5_SET(query_vport_state_in, in, vport_number, vport); 55 if (vport) 56 MLX5_SET(query_vport_state_in, in, other_vport, 1); 57 58 err = mlx5_cmd_exec_inout(mdev, query_vport_state, in, out); 59 if (err) 60 return 0; 61 62 return MLX5_GET(query_vport_state_out, out, state); 63} 64 65int mlx5_modify_vport_admin_state(struct mlx5_core_dev *mdev, u8 opmod, 66 u16 vport, u8 other_vport, u8 state) 67{ 68 u32 in[MLX5_ST_SZ_DW(modify_vport_state_in)] = {}; 69 70 MLX5_SET(modify_vport_state_in, in, opcode, 71 MLX5_CMD_OP_MODIFY_VPORT_STATE); 72 MLX5_SET(modify_vport_state_in, in, op_mod, opmod); 73 MLX5_SET(modify_vport_state_in, in, vport_number, vport); 74 MLX5_SET(modify_vport_state_in, in, other_vport, other_vport); 75 MLX5_SET(modify_vport_state_in, in, admin_state, state); 76 77 return mlx5_cmd_exec_in(mdev, modify_vport_state, in); 78} 79 80static int mlx5_query_nic_vport_context(struct mlx5_core_dev *mdev, u16 vport, 81 bool other_vport, u32 *out) 82{ 83 u32 in[MLX5_ST_SZ_DW(query_nic_vport_context_in)] = {}; 84 85 MLX5_SET(query_nic_vport_context_in, in, opcode, 86 MLX5_CMD_OP_QUERY_NIC_VPORT_CONTEXT); 87 MLX5_SET(query_nic_vport_context_in, in, vport_number, vport); 88 MLX5_SET(query_nic_vport_context_in, in, other_vport, other_vport); 89 90 return mlx5_cmd_exec_inout(mdev, query_nic_vport_context, in, out); 91} 92 93int mlx5_query_nic_vport_min_inline(struct mlx5_core_dev *mdev, 94 u16 vport, u8 *min_inline) 95{ 96 u32 out[MLX5_ST_SZ_DW(query_nic_vport_context_out)] = {}; 97 int err; 98 99 err = mlx5_query_nic_vport_context(mdev, vport, vport > 0, out); 100 if (!err) 101 *min_inline = MLX5_GET(query_nic_vport_context_out, out, 102 nic_vport_context.min_wqe_inline_mode); 103 return err; 104} 105EXPORT_SYMBOL_GPL(mlx5_query_nic_vport_min_inline); 106 107void mlx5_query_min_inline(struct mlx5_core_dev *mdev, 108 u8 *min_inline_mode) 109{ 110 switch (MLX5_CAP_ETH(mdev, wqe_inline_mode)) { 111 case MLX5_CAP_INLINE_MODE_VPORT_CONTEXT: 112 if (!mlx5_query_nic_vport_min_inline(mdev, 0, min_inline_mode)) 113 break; 114 fallthrough; 115 case MLX5_CAP_INLINE_MODE_L2: 116 *min_inline_mode = MLX5_INLINE_MODE_L2; 117 break; 118 case MLX5_CAP_INLINE_MODE_NOT_REQUIRED: 119 *min_inline_mode = MLX5_INLINE_MODE_NONE; 120 break; 121 } 122} 123EXPORT_SYMBOL_GPL(mlx5_query_min_inline); 124 125int mlx5_modify_nic_vport_min_inline(struct mlx5_core_dev *mdev, 126 u16 vport, u8 min_inline) 127{ 128 u32 in[MLX5_ST_SZ_DW(modify_nic_vport_context_in)] = {}; 129 void *nic_vport_ctx; 130 131 MLX5_SET(modify_nic_vport_context_in, in, 132 field_select.min_inline, 1); 133 MLX5_SET(modify_nic_vport_context_in, in, vport_number, vport); 134 MLX5_SET(modify_nic_vport_context_in, in, other_vport, 1); 135 136 nic_vport_ctx = MLX5_ADDR_OF(modify_nic_vport_context_in, 137 in, nic_vport_context); 138 MLX5_SET(nic_vport_context, nic_vport_ctx, 139 min_wqe_inline_mode, min_inline); 140 MLX5_SET(modify_nic_vport_context_in, in, opcode, 141 MLX5_CMD_OP_MODIFY_NIC_VPORT_CONTEXT); 142 143 return mlx5_cmd_exec_in(mdev, modify_nic_vport_context, in); 144} 145 146int mlx5_query_nic_vport_mac_address(struct mlx5_core_dev *mdev, 147 u16 vport, bool other, u8 *addr) 148{ 149 u32 out[MLX5_ST_SZ_DW(query_nic_vport_context_out)] = {}; 150 u32 in[MLX5_ST_SZ_DW(query_nic_vport_context_in)] = {}; 151 u8 *out_addr; 152 int err; 153 154 out_addr = MLX5_ADDR_OF(query_nic_vport_context_out, out, 155 nic_vport_context.permanent_address); 156 157 MLX5_SET(query_nic_vport_context_in, in, opcode, 158 MLX5_CMD_OP_QUERY_NIC_VPORT_CONTEXT); 159 MLX5_SET(query_nic_vport_context_in, in, vport_number, vport); 160 MLX5_SET(query_nic_vport_context_in, in, other_vport, other); 161 162 err = mlx5_cmd_exec_inout(mdev, query_nic_vport_context, in, out); 163 if (!err) 164 ether_addr_copy(addr, &out_addr[2]); 165 166 return err; 167} 168EXPORT_SYMBOL_GPL(mlx5_query_nic_vport_mac_address); 169 170int mlx5_query_mac_address(struct mlx5_core_dev *mdev, u8 *addr) 171{ 172 return mlx5_query_nic_vport_mac_address(mdev, 0, false, addr); 173} 174EXPORT_SYMBOL_GPL(mlx5_query_mac_address); 175 176int mlx5_modify_nic_vport_mac_address(struct mlx5_core_dev *mdev, 177 u16 vport, const u8 *addr) 178{ 179 void *in; 180 int inlen = MLX5_ST_SZ_BYTES(modify_nic_vport_context_in); 181 int err; 182 void *nic_vport_ctx; 183 u8 *perm_mac; 184 185 in = kvzalloc(inlen, GFP_KERNEL); 186 if (!in) 187 return -ENOMEM; 188 189 MLX5_SET(modify_nic_vport_context_in, in, 190 field_select.permanent_address, 1); 191 MLX5_SET(modify_nic_vport_context_in, in, vport_number, vport); 192 MLX5_SET(modify_nic_vport_context_in, in, other_vport, 1); 193 194 nic_vport_ctx = MLX5_ADDR_OF(modify_nic_vport_context_in, 195 in, nic_vport_context); 196 perm_mac = MLX5_ADDR_OF(nic_vport_context, nic_vport_ctx, 197 permanent_address); 198 199 ether_addr_copy(&perm_mac[2], addr); 200 MLX5_SET(modify_nic_vport_context_in, in, opcode, 201 MLX5_CMD_OP_MODIFY_NIC_VPORT_CONTEXT); 202 203 err = mlx5_cmd_exec_in(mdev, modify_nic_vport_context, in); 204 205 kvfree(in); 206 207 return err; 208} 209EXPORT_SYMBOL_GPL(mlx5_modify_nic_vport_mac_address); 210 211int mlx5_query_nic_vport_mtu(struct mlx5_core_dev *mdev, u16 *mtu) 212{ 213 int outlen = MLX5_ST_SZ_BYTES(query_nic_vport_context_out); 214 u32 *out; 215 int err; 216 217 out = kvzalloc(outlen, GFP_KERNEL); 218 if (!out) 219 return -ENOMEM; 220 221 err = mlx5_query_nic_vport_context(mdev, 0, false, out); 222 if (!err) 223 *mtu = MLX5_GET(query_nic_vport_context_out, out, 224 nic_vport_context.mtu); 225 226 kvfree(out); 227 return err; 228} 229EXPORT_SYMBOL_GPL(mlx5_query_nic_vport_mtu); 230 231int mlx5_modify_nic_vport_mtu(struct mlx5_core_dev *mdev, u16 mtu) 232{ 233 int inlen = MLX5_ST_SZ_BYTES(modify_nic_vport_context_in); 234 void *in; 235 int err; 236 237 in = kvzalloc(inlen, GFP_KERNEL); 238 if (!in) 239 return -ENOMEM; 240 241 MLX5_SET(modify_nic_vport_context_in, in, field_select.mtu, 1); 242 MLX5_SET(modify_nic_vport_context_in, in, nic_vport_context.mtu, mtu); 243 MLX5_SET(modify_nic_vport_context_in, in, opcode, 244 MLX5_CMD_OP_MODIFY_NIC_VPORT_CONTEXT); 245 246 err = mlx5_cmd_exec_in(mdev, modify_nic_vport_context, in); 247 248 kvfree(in); 249 return err; 250} 251EXPORT_SYMBOL_GPL(mlx5_modify_nic_vport_mtu); 252 253int mlx5_query_nic_vport_mac_list(struct mlx5_core_dev *dev, 254 u16 vport, 255 enum mlx5_list_type list_type, 256 u8 addr_list[][ETH_ALEN], 257 int *list_size) 258{ 259 u32 in[MLX5_ST_SZ_DW(query_nic_vport_context_in)] = {0}; 260 void *nic_vport_ctx; 261 int max_list_size; 262 int req_list_size; 263 int out_sz; 264 void *out; 265 int err; 266 int i; 267 268 req_list_size = *list_size; 269 270 max_list_size = list_type == MLX5_NVPRT_LIST_TYPE_UC ? 271 1 << MLX5_CAP_GEN(dev, log_max_current_uc_list) : 272 1 << MLX5_CAP_GEN(dev, log_max_current_mc_list); 273 274 if (req_list_size > max_list_size) { 275 mlx5_core_warn(dev, "Requested list size (%d) > (%d) max_list_size\n", 276 req_list_size, max_list_size); 277 req_list_size = max_list_size; 278 } 279 280 out_sz = MLX5_ST_SZ_BYTES(query_nic_vport_context_out) + 281 req_list_size * MLX5_ST_SZ_BYTES(mac_address_layout); 282 283 out = kvzalloc(out_sz, GFP_KERNEL); 284 if (!out) 285 return -ENOMEM; 286 287 MLX5_SET(query_nic_vport_context_in, in, opcode, 288 MLX5_CMD_OP_QUERY_NIC_VPORT_CONTEXT); 289 MLX5_SET(query_nic_vport_context_in, in, allowed_list_type, list_type); 290 MLX5_SET(query_nic_vport_context_in, in, vport_number, vport); 291 if (vport || mlx5_core_is_ecpf(dev)) 292 MLX5_SET(query_nic_vport_context_in, in, other_vport, 1); 293 294 err = mlx5_cmd_exec(dev, in, sizeof(in), out, out_sz); 295 if (err) 296 goto out; 297 298 nic_vport_ctx = MLX5_ADDR_OF(query_nic_vport_context_out, out, 299 nic_vport_context); 300 req_list_size = MLX5_GET(nic_vport_context, nic_vport_ctx, 301 allowed_list_size); 302 303 *list_size = req_list_size; 304 for (i = 0; i < req_list_size; i++) { 305 u8 *mac_addr = MLX5_ADDR_OF(nic_vport_context, 306 nic_vport_ctx, 307 current_uc_mac_address[i]) + 2; 308 ether_addr_copy(addr_list[i], mac_addr); 309 } 310out: 311 kvfree(out); 312 return err; 313} 314EXPORT_SYMBOL_GPL(mlx5_query_nic_vport_mac_list); 315 316int mlx5_modify_nic_vport_mac_list(struct mlx5_core_dev *dev, 317 enum mlx5_list_type list_type, 318 u8 addr_list[][ETH_ALEN], 319 int list_size) 320{ 321 u32 out[MLX5_ST_SZ_DW(modify_nic_vport_context_out)] = {}; 322 void *nic_vport_ctx; 323 int max_list_size; 324 int in_sz; 325 void *in; 326 int err; 327 int i; 328 329 max_list_size = list_type == MLX5_NVPRT_LIST_TYPE_UC ? 330 1 << MLX5_CAP_GEN(dev, log_max_current_uc_list) : 331 1 << MLX5_CAP_GEN(dev, log_max_current_mc_list); 332 333 if (list_size > max_list_size) 334 return -ENOSPC; 335 336 in_sz = MLX5_ST_SZ_BYTES(modify_nic_vport_context_in) + 337 list_size * MLX5_ST_SZ_BYTES(mac_address_layout); 338 339 in = kvzalloc(in_sz, GFP_KERNEL); 340 if (!in) 341 return -ENOMEM; 342 343 MLX5_SET(modify_nic_vport_context_in, in, opcode, 344 MLX5_CMD_OP_MODIFY_NIC_VPORT_CONTEXT); 345 MLX5_SET(modify_nic_vport_context_in, in, 346 field_select.addresses_list, 1); 347 348 nic_vport_ctx = MLX5_ADDR_OF(modify_nic_vport_context_in, in, 349 nic_vport_context); 350 351 MLX5_SET(nic_vport_context, nic_vport_ctx, 352 allowed_list_type, list_type); 353 MLX5_SET(nic_vport_context, nic_vport_ctx, 354 allowed_list_size, list_size); 355 356 for (i = 0; i < list_size; i++) { 357 u8 *curr_mac = MLX5_ADDR_OF(nic_vport_context, 358 nic_vport_ctx, 359 current_uc_mac_address[i]) + 2; 360 ether_addr_copy(curr_mac, addr_list[i]); 361 } 362 363 err = mlx5_cmd_exec(dev, in, in_sz, out, sizeof(out)); 364 kvfree(in); 365 return err; 366} 367EXPORT_SYMBOL_GPL(mlx5_modify_nic_vport_mac_list); 368 369int mlx5_modify_nic_vport_vlans(struct mlx5_core_dev *dev, 370 u16 vlans[], 371 int list_size) 372{ 373 u32 out[MLX5_ST_SZ_DW(modify_nic_vport_context_out)]; 374 void *nic_vport_ctx; 375 int max_list_size; 376 int in_sz; 377 void *in; 378 int err; 379 int i; 380 381 max_list_size = 1 << MLX5_CAP_GEN(dev, log_max_vlan_list); 382 383 if (list_size > max_list_size) 384 return -ENOSPC; 385 386 in_sz = MLX5_ST_SZ_BYTES(modify_nic_vport_context_in) + 387 list_size * MLX5_ST_SZ_BYTES(vlan_layout); 388 389 memset(out, 0, sizeof(out)); 390 in = kvzalloc(in_sz, GFP_KERNEL); 391 if (!in) 392 return -ENOMEM; 393 394 MLX5_SET(modify_nic_vport_context_in, in, opcode, 395 MLX5_CMD_OP_MODIFY_NIC_VPORT_CONTEXT); 396 MLX5_SET(modify_nic_vport_context_in, in, 397 field_select.addresses_list, 1); 398 399 nic_vport_ctx = MLX5_ADDR_OF(modify_nic_vport_context_in, in, 400 nic_vport_context); 401 402 MLX5_SET(nic_vport_context, nic_vport_ctx, 403 allowed_list_type, MLX5_NVPRT_LIST_TYPE_VLAN); 404 MLX5_SET(nic_vport_context, nic_vport_ctx, 405 allowed_list_size, list_size); 406 407 for (i = 0; i < list_size; i++) { 408 void *vlan_addr = MLX5_ADDR_OF(nic_vport_context, 409 nic_vport_ctx, 410 current_uc_mac_address[i]); 411 MLX5_SET(vlan_layout, vlan_addr, vlan, vlans[i]); 412 } 413 414 err = mlx5_cmd_exec(dev, in, in_sz, out, sizeof(out)); 415 kvfree(in); 416 return err; 417} 418EXPORT_SYMBOL_GPL(mlx5_modify_nic_vport_vlans); 419 420int mlx5_query_nic_vport_system_image_guid(struct mlx5_core_dev *mdev, 421 u64 *system_image_guid) 422{ 423 u32 *out; 424 int outlen = MLX5_ST_SZ_BYTES(query_nic_vport_context_out); 425 int err; 426 427 out = kvzalloc(outlen, GFP_KERNEL); 428 if (!out) 429 return -ENOMEM; 430 431 err = mlx5_query_nic_vport_context(mdev, 0, false, out); 432 if (err) 433 goto out; 434 435 *system_image_guid = MLX5_GET64(query_nic_vport_context_out, out, 436 nic_vport_context.system_image_guid); 437out: 438 kvfree(out); 439 return err; 440} 441EXPORT_SYMBOL_GPL(mlx5_query_nic_vport_system_image_guid); 442 443int mlx5_query_nic_vport_sd_group(struct mlx5_core_dev *mdev, u8 *sd_group) 444{ 445 int outlen = MLX5_ST_SZ_BYTES(query_nic_vport_context_out); 446 u32 *out; 447 int err; 448 449 out = kvzalloc(outlen, GFP_KERNEL); 450 if (!out) 451 return -ENOMEM; 452 453 err = mlx5_query_nic_vport_context(mdev, 0, false, out); 454 if (err) 455 goto out; 456 457 *sd_group = MLX5_GET(query_nic_vport_context_out, out, 458 nic_vport_context.sd_group); 459out: 460 kvfree(out); 461 return err; 462} 463 464int mlx5_query_nic_vport_node_guid(struct mlx5_core_dev *mdev, 465 u16 vport, bool other_vport, u64 *node_guid) 466{ 467 u32 *out; 468 int outlen = MLX5_ST_SZ_BYTES(query_nic_vport_context_out); 469 int err; 470 471 out = kvzalloc(outlen, GFP_KERNEL); 472 if (!out) 473 return -ENOMEM; 474 475 err = mlx5_query_nic_vport_context(mdev, vport, other_vport, out); 476 if (err) 477 goto out; 478 479 *node_guid = MLX5_GET64(query_nic_vport_context_out, out, 480 nic_vport_context.node_guid); 481out: 482 kvfree(out); 483 484 return err; 485} 486EXPORT_SYMBOL_GPL(mlx5_query_nic_vport_node_guid); 487 488int mlx5_modify_nic_vport_node_guid(struct mlx5_core_dev *mdev, 489 u16 vport, u64 node_guid) 490{ 491 int inlen = MLX5_ST_SZ_BYTES(modify_nic_vport_context_in); 492 void *nic_vport_context; 493 void *in; 494 int err; 495 496 if (!MLX5_CAP_GEN(mdev, vport_group_manager)) 497 return -EACCES; 498 499 in = kvzalloc(inlen, GFP_KERNEL); 500 if (!in) 501 return -ENOMEM; 502 503 MLX5_SET(modify_nic_vport_context_in, in, 504 field_select.node_guid, 1); 505 MLX5_SET(modify_nic_vport_context_in, in, vport_number, vport); 506 MLX5_SET(modify_nic_vport_context_in, in, other_vport, 1); 507 508 nic_vport_context = MLX5_ADDR_OF(modify_nic_vport_context_in, 509 in, nic_vport_context); 510 MLX5_SET64(nic_vport_context, nic_vport_context, node_guid, node_guid); 511 MLX5_SET(modify_nic_vport_context_in, in, opcode, 512 MLX5_CMD_OP_MODIFY_NIC_VPORT_CONTEXT); 513 514 err = mlx5_cmd_exec_in(mdev, modify_nic_vport_context, in); 515 516 kvfree(in); 517 518 return err; 519} 520 521int mlx5_query_nic_vport_qkey_viol_cntr(struct mlx5_core_dev *mdev, 522 u16 *qkey_viol_cntr) 523{ 524 u32 *out; 525 int outlen = MLX5_ST_SZ_BYTES(query_nic_vport_context_out); 526 int err; 527 528 out = kvzalloc(outlen, GFP_KERNEL); 529 if (!out) 530 return -ENOMEM; 531 532 err = mlx5_query_nic_vport_context(mdev, 0, false, out); 533 if (err) 534 goto out; 535 536 *qkey_viol_cntr = MLX5_GET(query_nic_vport_context_out, out, 537 nic_vport_context.qkey_violation_counter); 538out: 539 kvfree(out); 540 541 return err; 542} 543EXPORT_SYMBOL_GPL(mlx5_query_nic_vport_qkey_viol_cntr); 544 545int mlx5_query_hca_vport_gid(struct mlx5_core_dev *dev, u8 other_vport, 546 u8 port_num, u16 vf_num, u16 gid_index, 547 union ib_gid *gid) 548{ 549 int in_sz = MLX5_ST_SZ_BYTES(query_hca_vport_gid_in); 550 int out_sz = MLX5_ST_SZ_BYTES(query_hca_vport_gid_out); 551 int is_group_manager; 552 void *out = NULL; 553 void *in = NULL; 554 union ib_gid *tmp; 555 int tbsz; 556 int nout; 557 int err; 558 559 is_group_manager = MLX5_CAP_GEN(dev, vport_group_manager); 560 tbsz = mlx5_get_gid_table_len(MLX5_CAP_GEN(dev, gid_table_size)); 561 mlx5_core_dbg(dev, "vf_num %d, index %d, gid_table_size %d\n", 562 vf_num, gid_index, tbsz); 563 564 if (gid_index > tbsz && gid_index != 0xffff) 565 return -EINVAL; 566 567 if (gid_index == 0xffff) 568 nout = tbsz; 569 else 570 nout = 1; 571 572 out_sz += nout * sizeof(*gid); 573 574 in = kvzalloc(in_sz, GFP_KERNEL); 575 out = kvzalloc(out_sz, GFP_KERNEL); 576 if (!in || !out) { 577 err = -ENOMEM; 578 goto out; 579 } 580 581 MLX5_SET(query_hca_vport_gid_in, in, opcode, MLX5_CMD_OP_QUERY_HCA_VPORT_GID); 582 if (other_vport) { 583 if (is_group_manager) { 584 MLX5_SET(query_hca_vport_gid_in, in, vport_number, vf_num); 585 MLX5_SET(query_hca_vport_gid_in, in, other_vport, 1); 586 } else { 587 err = -EPERM; 588 goto out; 589 } 590 } 591 MLX5_SET(query_hca_vport_gid_in, in, gid_index, gid_index); 592 593 if (MLX5_CAP_GEN(dev, num_ports) == 2) 594 MLX5_SET(query_hca_vport_gid_in, in, port_num, port_num); 595 596 err = mlx5_cmd_exec(dev, in, in_sz, out, out_sz); 597 if (err) 598 goto out; 599 600 tmp = out + MLX5_ST_SZ_BYTES(query_hca_vport_gid_out); 601 gid->global.subnet_prefix = tmp->global.subnet_prefix; 602 gid->global.interface_id = tmp->global.interface_id; 603 604out: 605 kvfree(in); 606 kvfree(out); 607 return err; 608} 609EXPORT_SYMBOL_GPL(mlx5_query_hca_vport_gid); 610 611int mlx5_query_hca_vport_pkey(struct mlx5_core_dev *dev, u8 other_vport, 612 u8 port_num, u16 vf_num, u16 pkey_index, 613 u16 *pkey) 614{ 615 int in_sz = MLX5_ST_SZ_BYTES(query_hca_vport_pkey_in); 616 int out_sz = MLX5_ST_SZ_BYTES(query_hca_vport_pkey_out); 617 int is_group_manager; 618 void *out = NULL; 619 void *in = NULL; 620 void *pkarr; 621 int nout; 622 int tbsz; 623 int err; 624 int i; 625 626 is_group_manager = MLX5_CAP_GEN(dev, vport_group_manager); 627 628 tbsz = mlx5_to_sw_pkey_sz(MLX5_CAP_GEN(dev, pkey_table_size)); 629 if (pkey_index > tbsz && pkey_index != 0xffff) 630 return -EINVAL; 631 632 if (pkey_index == 0xffff) 633 nout = tbsz; 634 else 635 nout = 1; 636 637 out_sz += nout * MLX5_ST_SZ_BYTES(pkey); 638 639 in = kvzalloc(in_sz, GFP_KERNEL); 640 out = kvzalloc(out_sz, GFP_KERNEL); 641 if (!in || !out) { 642 err = -ENOMEM; 643 goto out; 644 } 645 646 MLX5_SET(query_hca_vport_pkey_in, in, opcode, MLX5_CMD_OP_QUERY_HCA_VPORT_PKEY); 647 if (other_vport) { 648 if (is_group_manager) { 649 MLX5_SET(query_hca_vport_pkey_in, in, vport_number, vf_num); 650 MLX5_SET(query_hca_vport_pkey_in, in, other_vport, 1); 651 } else { 652 err = -EPERM; 653 goto out; 654 } 655 } 656 MLX5_SET(query_hca_vport_pkey_in, in, pkey_index, pkey_index); 657 658 if (MLX5_CAP_GEN(dev, num_ports) == 2) 659 MLX5_SET(query_hca_vport_pkey_in, in, port_num, port_num); 660 661 err = mlx5_cmd_exec(dev, in, in_sz, out, out_sz); 662 if (err) 663 goto out; 664 665 pkarr = MLX5_ADDR_OF(query_hca_vport_pkey_out, out, pkey); 666 for (i = 0; i < nout; i++, pkey++, pkarr += MLX5_ST_SZ_BYTES(pkey)) 667 *pkey = MLX5_GET_PR(pkey, pkarr, pkey); 668 669out: 670 kvfree(in); 671 kvfree(out); 672 return err; 673} 674EXPORT_SYMBOL_GPL(mlx5_query_hca_vport_pkey); 675 676int mlx5_query_hca_vport_context(struct mlx5_core_dev *dev, 677 u8 other_vport, u8 port_num, 678 u16 vf_num, 679 struct mlx5_hca_vport_context *rep) 680{ 681 int out_sz = MLX5_ST_SZ_BYTES(query_hca_vport_context_out); 682 int in[MLX5_ST_SZ_DW(query_hca_vport_context_in)] = {}; 683 int is_group_manager; 684 void *out; 685 void *ctx; 686 int err; 687 688 is_group_manager = MLX5_CAP_GEN(dev, vport_group_manager); 689 690 out = kvzalloc(out_sz, GFP_KERNEL); 691 if (!out) 692 return -ENOMEM; 693 694 MLX5_SET(query_hca_vport_context_in, in, opcode, MLX5_CMD_OP_QUERY_HCA_VPORT_CONTEXT); 695 696 if (other_vport) { 697 if (is_group_manager) { 698 MLX5_SET(query_hca_vport_context_in, in, other_vport, 1); 699 MLX5_SET(query_hca_vport_context_in, in, vport_number, vf_num); 700 } else { 701 err = -EPERM; 702 goto ex; 703 } 704 } 705 706 if (MLX5_CAP_GEN(dev, num_ports) == 2) 707 MLX5_SET(query_hca_vport_context_in, in, port_num, port_num); 708 709 err = mlx5_cmd_exec_inout(dev, query_hca_vport_context, in, out); 710 if (err) 711 goto ex; 712 713 ctx = MLX5_ADDR_OF(query_hca_vport_context_out, out, hca_vport_context); 714 rep->field_select = MLX5_GET_PR(hca_vport_context, ctx, field_select); 715 rep->sm_virt_aware = MLX5_GET_PR(hca_vport_context, ctx, sm_virt_aware); 716 rep->has_smi = MLX5_GET_PR(hca_vport_context, ctx, has_smi); 717 rep->has_raw = MLX5_GET_PR(hca_vport_context, ctx, has_raw); 718 rep->policy = MLX5_GET_PR(hca_vport_context, ctx, vport_state_policy); 719 rep->phys_state = MLX5_GET_PR(hca_vport_context, ctx, 720 port_physical_state); 721 rep->vport_state = MLX5_GET_PR(hca_vport_context, ctx, vport_state); 722 rep->port_physical_state = MLX5_GET_PR(hca_vport_context, ctx, 723 port_physical_state); 724 rep->port_guid = MLX5_GET64_PR(hca_vport_context, ctx, port_guid); 725 rep->node_guid = MLX5_GET64_PR(hca_vport_context, ctx, node_guid); 726 rep->cap_mask1 = MLX5_GET_PR(hca_vport_context, ctx, cap_mask1); 727 rep->cap_mask1_perm = MLX5_GET_PR(hca_vport_context, ctx, 728 cap_mask1_field_select); 729 rep->cap_mask2 = MLX5_GET_PR(hca_vport_context, ctx, cap_mask2); 730 rep->cap_mask2_perm = MLX5_GET_PR(hca_vport_context, ctx, 731 cap_mask2_field_select); 732 rep->lid = MLX5_GET_PR(hca_vport_context, ctx, lid); 733 rep->init_type_reply = MLX5_GET_PR(hca_vport_context, ctx, 734 init_type_reply); 735 rep->lmc = MLX5_GET_PR(hca_vport_context, ctx, lmc); 736 rep->subnet_timeout = MLX5_GET_PR(hca_vport_context, ctx, 737 subnet_timeout); 738 rep->sm_lid = MLX5_GET_PR(hca_vport_context, ctx, sm_lid); 739 rep->sm_sl = MLX5_GET_PR(hca_vport_context, ctx, sm_sl); 740 rep->qkey_violation_counter = MLX5_GET_PR(hca_vport_context, ctx, 741 qkey_violation_counter); 742 rep->pkey_violation_counter = MLX5_GET_PR(hca_vport_context, ctx, 743 pkey_violation_counter); 744 rep->grh_required = MLX5_GET_PR(hca_vport_context, ctx, grh_required); 745 rep->sys_image_guid = MLX5_GET64_PR(hca_vport_context, ctx, 746 system_image_guid); 747 rep->num_plane = MLX5_GET_PR(hca_vport_context, ctx, num_port_plane); 748 749ex: 750 kvfree(out); 751 return err; 752} 753EXPORT_SYMBOL_GPL(mlx5_query_hca_vport_context); 754 755int mlx5_query_hca_vport_system_image_guid(struct mlx5_core_dev *dev, 756 u64 *sys_image_guid) 757{ 758 struct mlx5_hca_vport_context *rep; 759 int err; 760 761 rep = kvzalloc(sizeof(*rep), GFP_KERNEL); 762 if (!rep) 763 return -ENOMEM; 764 765 err = mlx5_query_hca_vport_context(dev, 0, 1, 0, rep); 766 if (!err) 767 *sys_image_guid = rep->sys_image_guid; 768 769 kvfree(rep); 770 return err; 771} 772EXPORT_SYMBOL_GPL(mlx5_query_hca_vport_system_image_guid); 773 774int mlx5_query_hca_vport_node_guid(struct mlx5_core_dev *dev, 775 u64 *node_guid) 776{ 777 struct mlx5_hca_vport_context *rep; 778 int err; 779 780 rep = kvzalloc(sizeof(*rep), GFP_KERNEL); 781 if (!rep) 782 return -ENOMEM; 783 784 err = mlx5_query_hca_vport_context(dev, 0, 1, 0, rep); 785 if (!err) 786 *node_guid = rep->node_guid; 787 788 kvfree(rep); 789 return err; 790} 791EXPORT_SYMBOL_GPL(mlx5_query_hca_vport_node_guid); 792 793int mlx5_query_nic_vport_promisc(struct mlx5_core_dev *mdev, 794 u16 vport, 795 int *promisc_uc, 796 int *promisc_mc, 797 int *promisc_all) 798{ 799 u32 *out; 800 int outlen = MLX5_ST_SZ_BYTES(query_nic_vport_context_out); 801 int err; 802 803 out = kvzalloc(outlen, GFP_KERNEL); 804 if (!out) 805 return -ENOMEM; 806 807 err = mlx5_query_nic_vport_context(mdev, vport, vport > 0, out); 808 if (err) 809 goto out; 810 811 *promisc_uc = MLX5_GET(query_nic_vport_context_out, out, 812 nic_vport_context.promisc_uc); 813 *promisc_mc = MLX5_GET(query_nic_vport_context_out, out, 814 nic_vport_context.promisc_mc); 815 *promisc_all = MLX5_GET(query_nic_vport_context_out, out, 816 nic_vport_context.promisc_all); 817 818out: 819 kvfree(out); 820 return err; 821} 822EXPORT_SYMBOL_GPL(mlx5_query_nic_vport_promisc); 823 824int mlx5_modify_nic_vport_promisc(struct mlx5_core_dev *mdev, 825 int promisc_uc, 826 int promisc_mc, 827 int promisc_all) 828{ 829 void *in; 830 int inlen = MLX5_ST_SZ_BYTES(modify_nic_vport_context_in); 831 int err; 832 833 in = kvzalloc(inlen, GFP_KERNEL); 834 if (!in) 835 return -ENOMEM; 836 837 MLX5_SET(modify_nic_vport_context_in, in, field_select.promisc, 1); 838 MLX5_SET(modify_nic_vport_context_in, in, 839 nic_vport_context.promisc_uc, promisc_uc); 840 MLX5_SET(modify_nic_vport_context_in, in, 841 nic_vport_context.promisc_mc, promisc_mc); 842 MLX5_SET(modify_nic_vport_context_in, in, 843 nic_vport_context.promisc_all, promisc_all); 844 MLX5_SET(modify_nic_vport_context_in, in, opcode, 845 MLX5_CMD_OP_MODIFY_NIC_VPORT_CONTEXT); 846 847 err = mlx5_cmd_exec_in(mdev, modify_nic_vport_context, in); 848 849 kvfree(in); 850 851 return err; 852} 853EXPORT_SYMBOL_GPL(mlx5_modify_nic_vport_promisc); 854 855enum { 856 UC_LOCAL_LB, 857 MC_LOCAL_LB 858}; 859 860int mlx5_nic_vport_update_local_lb(struct mlx5_core_dev *mdev, bool enable) 861{ 862 int inlen = MLX5_ST_SZ_BYTES(modify_nic_vport_context_in); 863 void *in; 864 int err; 865 866 if (!MLX5_CAP_GEN(mdev, disable_local_lb_mc) && 867 !MLX5_CAP_GEN(mdev, disable_local_lb_uc)) 868 return 0; 869 870 in = kvzalloc(inlen, GFP_KERNEL); 871 if (!in) 872 return -ENOMEM; 873 874 MLX5_SET(modify_nic_vport_context_in, in, 875 nic_vport_context.disable_mc_local_lb, !enable); 876 MLX5_SET(modify_nic_vport_context_in, in, 877 nic_vport_context.disable_uc_local_lb, !enable); 878 879 if (MLX5_CAP_GEN(mdev, disable_local_lb_mc)) 880 MLX5_SET(modify_nic_vport_context_in, in, 881 field_select.disable_mc_local_lb, 1); 882 883 if (MLX5_CAP_GEN(mdev, disable_local_lb_uc)) 884 MLX5_SET(modify_nic_vport_context_in, in, 885 field_select.disable_uc_local_lb, 1); 886 MLX5_SET(modify_nic_vport_context_in, in, opcode, 887 MLX5_CMD_OP_MODIFY_NIC_VPORT_CONTEXT); 888 889 err = mlx5_cmd_exec_in(mdev, modify_nic_vport_context, in); 890 891 if (!err) 892 mlx5_core_dbg(mdev, "%s local_lb\n", 893 enable ? "enable" : "disable"); 894 895 kvfree(in); 896 return err; 897} 898EXPORT_SYMBOL_GPL(mlx5_nic_vport_update_local_lb); 899 900int mlx5_nic_vport_query_local_lb(struct mlx5_core_dev *mdev, bool *status) 901{ 902 int outlen = MLX5_ST_SZ_BYTES(query_nic_vport_context_out); 903 u32 *out; 904 int value; 905 int err; 906 907 out = kvzalloc(outlen, GFP_KERNEL); 908 if (!out) 909 return -ENOMEM; 910 911 err = mlx5_query_nic_vport_context(mdev, 0, false, out); 912 if (err) 913 goto out; 914 915 value = MLX5_GET(query_nic_vport_context_out, out, 916 nic_vport_context.disable_mc_local_lb) << MC_LOCAL_LB; 917 918 value |= MLX5_GET(query_nic_vport_context_out, out, 919 nic_vport_context.disable_uc_local_lb) << UC_LOCAL_LB; 920 921 *status = !value; 922 923out: 924 kvfree(out); 925 return err; 926} 927EXPORT_SYMBOL_GPL(mlx5_nic_vport_query_local_lb); 928 929enum mlx5_vport_roce_state { 930 MLX5_VPORT_ROCE_DISABLED = 0, 931 MLX5_VPORT_ROCE_ENABLED = 1, 932}; 933 934static int mlx5_nic_vport_update_roce_state(struct mlx5_core_dev *mdev, 935 enum mlx5_vport_roce_state state) 936{ 937 void *in; 938 int inlen = MLX5_ST_SZ_BYTES(modify_nic_vport_context_in); 939 int err; 940 941 in = kvzalloc(inlen, GFP_KERNEL); 942 if (!in) 943 return -ENOMEM; 944 945 MLX5_SET(modify_nic_vport_context_in, in, field_select.roce_en, 1); 946 MLX5_SET(modify_nic_vport_context_in, in, nic_vport_context.roce_en, 947 state); 948 MLX5_SET(modify_nic_vport_context_in, in, opcode, 949 MLX5_CMD_OP_MODIFY_NIC_VPORT_CONTEXT); 950 951 err = mlx5_cmd_exec_in(mdev, modify_nic_vport_context, in); 952 953 kvfree(in); 954 955 return err; 956} 957 958int mlx5_nic_vport_enable_roce(struct mlx5_core_dev *mdev) 959{ 960 int err = 0; 961 962 mutex_lock(&mlx5_roce_en_lock); 963 if (!mdev->roce.roce_en) 964 err = mlx5_nic_vport_update_roce_state(mdev, MLX5_VPORT_ROCE_ENABLED); 965 966 if (!err) 967 mdev->roce.roce_en++; 968 mutex_unlock(&mlx5_roce_en_lock); 969 970 return err; 971} 972EXPORT_SYMBOL_GPL(mlx5_nic_vport_enable_roce); 973 974int mlx5_nic_vport_disable_roce(struct mlx5_core_dev *mdev) 975{ 976 int err = 0; 977 978 mutex_lock(&mlx5_roce_en_lock); 979 if (mdev->roce.roce_en) { 980 mdev->roce.roce_en--; 981 if (mdev->roce.roce_en == 0) 982 err = mlx5_nic_vport_update_roce_state(mdev, MLX5_VPORT_ROCE_DISABLED); 983 984 if (err) 985 mdev->roce.roce_en++; 986 } 987 mutex_unlock(&mlx5_roce_en_lock); 988 return err; 989} 990EXPORT_SYMBOL(mlx5_nic_vport_disable_roce); 991 992int mlx5_core_query_vport_counter(struct mlx5_core_dev *dev, u8 other_vport, 993 int vf, u8 port_num, void *out) 994{ 995 int in_sz = MLX5_ST_SZ_BYTES(query_vport_counter_in); 996 int is_group_manager; 997 void *in; 998 int err; 999 1000 is_group_manager = MLX5_CAP_GEN(dev, vport_group_manager); 1001 in = kvzalloc(in_sz, GFP_KERNEL); 1002 if (!in) { 1003 err = -ENOMEM; 1004 return err; 1005 } 1006 1007 MLX5_SET(query_vport_counter_in, in, opcode, 1008 MLX5_CMD_OP_QUERY_VPORT_COUNTER); 1009 if (other_vport) { 1010 if (is_group_manager) { 1011 MLX5_SET(query_vport_counter_in, in, other_vport, 1); 1012 MLX5_SET(query_vport_counter_in, in, vport_number, vf + 1); 1013 } else { 1014 err = -EPERM; 1015 goto free; 1016 } 1017 } 1018 if (MLX5_CAP_GEN(dev, num_ports) == 2) 1019 MLX5_SET(query_vport_counter_in, in, port_num, port_num); 1020 1021 err = mlx5_cmd_exec_inout(dev, query_vport_counter, in, out); 1022free: 1023 kvfree(in); 1024 return err; 1025} 1026EXPORT_SYMBOL_GPL(mlx5_core_query_vport_counter); 1027 1028int mlx5_query_vport_down_stats(struct mlx5_core_dev *mdev, u16 vport, 1029 u8 other_vport, u64 *rx_discard_vport_down, 1030 u64 *tx_discard_vport_down) 1031{ 1032 u32 out[MLX5_ST_SZ_DW(query_vnic_env_out)] = {}; 1033 u32 in[MLX5_ST_SZ_DW(query_vnic_env_in)] = {}; 1034 int err; 1035 1036 MLX5_SET(query_vnic_env_in, in, opcode, 1037 MLX5_CMD_OP_QUERY_VNIC_ENV); 1038 MLX5_SET(query_vnic_env_in, in, op_mod, 0); 1039 MLX5_SET(query_vnic_env_in, in, vport_number, vport); 1040 MLX5_SET(query_vnic_env_in, in, other_vport, other_vport); 1041 1042 err = mlx5_cmd_exec_inout(mdev, query_vnic_env, in, out); 1043 if (err) 1044 return err; 1045 1046 *rx_discard_vport_down = MLX5_GET64(query_vnic_env_out, out, 1047 vport_env.receive_discard_vport_down); 1048 *tx_discard_vport_down = MLX5_GET64(query_vnic_env_out, out, 1049 vport_env.transmit_discard_vport_down); 1050 return 0; 1051} 1052 1053int mlx5_core_modify_hca_vport_context(struct mlx5_core_dev *dev, 1054 u8 other_vport, u8 port_num, 1055 int vf, 1056 struct mlx5_hca_vport_context *req) 1057{ 1058 int in_sz = MLX5_ST_SZ_BYTES(modify_hca_vport_context_in); 1059 int is_group_manager; 1060 void *ctx; 1061 void *in; 1062 int err; 1063 1064 mlx5_core_dbg(dev, "vf %d\n", vf); 1065 is_group_manager = MLX5_CAP_GEN(dev, vport_group_manager); 1066 in = kvzalloc(in_sz, GFP_KERNEL); 1067 if (!in) 1068 return -ENOMEM; 1069 1070 MLX5_SET(modify_hca_vport_context_in, in, opcode, MLX5_CMD_OP_MODIFY_HCA_VPORT_CONTEXT); 1071 if (other_vport) { 1072 if (is_group_manager) { 1073 MLX5_SET(modify_hca_vport_context_in, in, other_vport, 1); 1074 MLX5_SET(modify_hca_vport_context_in, in, vport_number, vf); 1075 } else { 1076 err = -EPERM; 1077 goto ex; 1078 } 1079 } 1080 1081 if (MLX5_CAP_GEN(dev, num_ports) > 1) 1082 MLX5_SET(modify_hca_vport_context_in, in, port_num, port_num); 1083 1084 ctx = MLX5_ADDR_OF(modify_hca_vport_context_in, in, hca_vport_context); 1085 MLX5_SET(hca_vport_context, ctx, field_select, req->field_select); 1086 if (req->field_select & MLX5_HCA_VPORT_SEL_STATE_POLICY) 1087 MLX5_SET(hca_vport_context, ctx, vport_state_policy, 1088 req->policy); 1089 if (req->field_select & MLX5_HCA_VPORT_SEL_PORT_GUID) 1090 MLX5_SET64(hca_vport_context, ctx, port_guid, req->port_guid); 1091 if (req->field_select & MLX5_HCA_VPORT_SEL_NODE_GUID) 1092 MLX5_SET64(hca_vport_context, ctx, node_guid, req->node_guid); 1093 MLX5_SET(hca_vport_context, ctx, cap_mask1, req->cap_mask1); 1094 MLX5_SET(hca_vport_context, ctx, cap_mask1_field_select, 1095 req->cap_mask1_perm); 1096 err = mlx5_cmd_exec_in(dev, modify_hca_vport_context, in); 1097ex: 1098 kvfree(in); 1099 return err; 1100} 1101EXPORT_SYMBOL_GPL(mlx5_core_modify_hca_vport_context); 1102 1103int mlx5_nic_vport_affiliate_multiport(struct mlx5_core_dev *master_mdev, 1104 struct mlx5_core_dev *port_mdev) 1105{ 1106 int inlen = MLX5_ST_SZ_BYTES(modify_nic_vport_context_in); 1107 void *in; 1108 int err; 1109 1110 in = kvzalloc(inlen, GFP_KERNEL); 1111 if (!in) 1112 return -ENOMEM; 1113 1114 err = mlx5_nic_vport_enable_roce(port_mdev); 1115 if (err) 1116 goto free; 1117 1118 MLX5_SET(modify_nic_vport_context_in, in, field_select.affiliation, 1); 1119 if (MLX5_CAP_GEN_2(master_mdev, sw_vhca_id_valid)) { 1120 MLX5_SET(modify_nic_vport_context_in, in, 1121 nic_vport_context.vhca_id_type, VHCA_ID_TYPE_SW); 1122 MLX5_SET(modify_nic_vport_context_in, in, 1123 nic_vport_context.affiliated_vhca_id, 1124 MLX5_CAP_GEN_2(master_mdev, sw_vhca_id)); 1125 } else { 1126 MLX5_SET(modify_nic_vport_context_in, in, 1127 nic_vport_context.affiliated_vhca_id, 1128 MLX5_CAP_GEN(master_mdev, vhca_id)); 1129 } 1130 MLX5_SET(modify_nic_vport_context_in, in, 1131 nic_vport_context.affiliation_criteria, 1132 MLX5_CAP_GEN(port_mdev, affiliate_nic_vport_criteria)); 1133 MLX5_SET(modify_nic_vport_context_in, in, opcode, 1134 MLX5_CMD_OP_MODIFY_NIC_VPORT_CONTEXT); 1135 1136 err = mlx5_cmd_exec_in(port_mdev, modify_nic_vport_context, in); 1137 if (err) 1138 mlx5_nic_vport_disable_roce(port_mdev); 1139 1140free: 1141 kvfree(in); 1142 return err; 1143} 1144EXPORT_SYMBOL_GPL(mlx5_nic_vport_affiliate_multiport); 1145 1146int mlx5_nic_vport_unaffiliate_multiport(struct mlx5_core_dev *port_mdev) 1147{ 1148 int inlen = MLX5_ST_SZ_BYTES(modify_nic_vport_context_in); 1149 void *in; 1150 int err; 1151 1152 in = kvzalloc(inlen, GFP_KERNEL); 1153 if (!in) 1154 return -ENOMEM; 1155 1156 MLX5_SET(modify_nic_vport_context_in, in, field_select.affiliation, 1); 1157 MLX5_SET(modify_nic_vport_context_in, in, 1158 nic_vport_context.affiliated_vhca_id, 0); 1159 MLX5_SET(modify_nic_vport_context_in, in, 1160 nic_vport_context.affiliation_criteria, 0); 1161 MLX5_SET(modify_nic_vport_context_in, in, opcode, 1162 MLX5_CMD_OP_MODIFY_NIC_VPORT_CONTEXT); 1163 1164 err = mlx5_cmd_exec_in(port_mdev, modify_nic_vport_context, in); 1165 if (!err) 1166 mlx5_nic_vport_disable_roce(port_mdev); 1167 1168 kvfree(in); 1169 return err; 1170} 1171EXPORT_SYMBOL_GPL(mlx5_nic_vport_unaffiliate_multiport); 1172 1173u64 mlx5_query_nic_system_image_guid(struct mlx5_core_dev *mdev) 1174{ 1175 int port_type_cap = MLX5_CAP_GEN(mdev, port_type); 1176 u64 tmp; 1177 int err; 1178 1179 if (mdev->sys_image_guid) 1180 return mdev->sys_image_guid; 1181 1182 if (port_type_cap == MLX5_CAP_PORT_TYPE_ETH) 1183 err = mlx5_query_nic_vport_system_image_guid(mdev, &tmp); 1184 else 1185 err = mlx5_query_hca_vport_system_image_guid(mdev, &tmp); 1186 1187 mdev->sys_image_guid = err ? 0 : tmp; 1188 1189 return mdev->sys_image_guid; 1190} 1191EXPORT_SYMBOL_GPL(mlx5_query_nic_system_image_guid); 1192 1193void mlx5_query_nic_sw_system_image_guid(struct mlx5_core_dev *mdev, u8 *buf, 1194 u8 *len) 1195{ 1196 u64 fw_system_image_guid; 1197 1198 *len = 0; 1199 1200 fw_system_image_guid = mlx5_query_nic_system_image_guid(mdev); 1201 if (!fw_system_image_guid) 1202 return; 1203 1204 memcpy(buf, &fw_system_image_guid, sizeof(fw_system_image_guid)); 1205 *len += sizeof(fw_system_image_guid); 1206 1207 if (MLX5_CAP_GEN_2(mdev, load_balance_id) && 1208 MLX5_CAP_GEN_2(mdev, lag_per_mp_group)) 1209 buf[(*len)++] = MLX5_CAP_GEN_2(mdev, load_balance_id); 1210} 1211 1212static bool mlx5_vport_use_vhca_id_as_func_id(struct mlx5_core_dev *dev, 1213 u16 vport_num, u16 *vhca_id) 1214{ 1215 if (!MLX5_CAP_GEN_2(dev, function_id_type_vhca_id)) 1216 return false; 1217 1218 return mlx5_esw_vport_vhca_id(dev->priv.eswitch, vport_num, vhca_id); 1219} 1220 1221int mlx5_vport_get_other_func_cap(struct mlx5_core_dev *dev, u16 vport, void *out, 1222 u16 opmod) 1223{ 1224 u8 in[MLX5_ST_SZ_BYTES(query_hca_cap_in)] = {}; 1225 u16 vhca_id = 0, function_id = 0; 1226 bool ec_vf_func = false; 1227 1228 /* if this vport is referring to a vport on the ec PF (embedded cpu ) 1229 * let the FW know which domain we are querying since vport numbers or 1230 * function_ids are not unique across the different PF domains, 1231 * unless we use vhca_id as the function_id below. 1232 */ 1233 ec_vf_func = mlx5_core_is_ec_vf_vport(dev, vport); 1234 function_id = mlx5_vport_to_func_id(dev, vport, ec_vf_func); 1235 1236 if (mlx5_vport_use_vhca_id_as_func_id(dev, vport, &vhca_id)) { 1237 MLX5_SET(query_hca_cap_in, in, function_id_type, 1); 1238 function_id = vhca_id; 1239 ec_vf_func = false; 1240 mlx5_core_dbg(dev, "%s using vhca_id as function_id for vport %d vhca_id 0x%x\n", 1241 __func__, vport, vhca_id); 1242 } 1243 1244 opmod = (opmod << 1) | (HCA_CAP_OPMOD_GET_MAX & 0x01); 1245 MLX5_SET(query_hca_cap_in, in, opcode, MLX5_CMD_OP_QUERY_HCA_CAP); 1246 MLX5_SET(query_hca_cap_in, in, op_mod, opmod); 1247 MLX5_SET(query_hca_cap_in, in, other_function, true); 1248 MLX5_SET(query_hca_cap_in, in, ec_vf_function, ec_vf_func); 1249 MLX5_SET(query_hca_cap_in, in, function_id, function_id); 1250 return mlx5_cmd_exec_inout(dev, query_hca_cap, in, out); 1251} 1252EXPORT_SYMBOL_GPL(mlx5_vport_get_other_func_cap); 1253 1254int mlx5_vport_get_vhca_id(struct mlx5_core_dev *dev, u16 vport, u16 *vhca_id) 1255{ 1256 int query_out_sz = MLX5_ST_SZ_BYTES(query_hca_cap_out); 1257 void *query_ctx; 1258 void *hca_caps; 1259 int err; 1260 1261 /* try get vhca_id via eswitch */ 1262 if (mlx5_esw_vport_vhca_id(dev->priv.eswitch, vport, vhca_id)) 1263 return 0; 1264 1265 query_ctx = kzalloc(query_out_sz, GFP_KERNEL); 1266 if (!query_ctx) 1267 return -ENOMEM; 1268 1269 err = mlx5_vport_get_other_func_general_cap(dev, vport, query_ctx); 1270 if (err) 1271 goto out_free; 1272 1273 hca_caps = MLX5_ADDR_OF(query_hca_cap_out, query_ctx, capability); 1274 *vhca_id = MLX5_GET(cmd_hca_cap, hca_caps, vhca_id); 1275 1276out_free: 1277 kfree(query_ctx); 1278 return err; 1279} 1280EXPORT_SYMBOL_GPL(mlx5_vport_get_vhca_id); 1281 1282int mlx5_vport_set_other_func_cap(struct mlx5_core_dev *dev, const void *hca_cap, 1283 u16 vport, u16 opmod) 1284{ 1285 int set_sz = MLX5_ST_SZ_BYTES(set_hca_cap_in); 1286 u16 vhca_id = 0, function_id = 0; 1287 bool ec_vf_func = false; 1288 void *set_hca_cap; 1289 void *set_ctx; 1290 int ret; 1291 1292 set_ctx = kzalloc(set_sz, GFP_KERNEL); 1293 if (!set_ctx) 1294 return -ENOMEM; 1295 1296 /* if this vport is referring to a vport on the ec PF (embedded cpu ) 1297 * let the FW know which domain we are querying since vport numbers or 1298 * function_ids are not unique across the different PF domains, 1299 * unless we use vhca_id as the function_id below. 1300 */ 1301 ec_vf_func = mlx5_core_is_ec_vf_vport(dev, vport); 1302 function_id = mlx5_vport_to_func_id(dev, vport, ec_vf_func); 1303 1304 if (mlx5_vport_use_vhca_id_as_func_id(dev, vport, &vhca_id)) { 1305 MLX5_SET(set_hca_cap_in, set_ctx, function_id_type, 1); 1306 function_id = vhca_id; 1307 ec_vf_func = false; 1308 mlx5_core_dbg(dev, "%s using vhca_id as function_id for vport %d vhca_id 0x%x\n", 1309 __func__, vport, vhca_id); 1310 } 1311 1312 MLX5_SET(set_hca_cap_in, set_ctx, opcode, MLX5_CMD_OP_SET_HCA_CAP); 1313 MLX5_SET(set_hca_cap_in, set_ctx, op_mod, opmod << 1); 1314 set_hca_cap = MLX5_ADDR_OF(set_hca_cap_in, set_ctx, capability); 1315 memcpy(set_hca_cap, hca_cap, MLX5_ST_SZ_BYTES(cmd_hca_cap)); 1316 MLX5_SET(set_hca_cap_in, set_ctx, other_function, true); 1317 MLX5_SET(set_hca_cap_in, set_ctx, ec_vf_function, ec_vf_func); 1318 MLX5_SET(set_hca_cap_in, set_ctx, function_id, function_id); 1319 ret = mlx5_cmd_exec_in(dev, set_hca_cap, set_ctx); 1320 1321 kfree(set_ctx); 1322 return ret; 1323}
~/
Read-only file preview.