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 "sf/sf.h" 40 41 /* Mutex to hold while enabling or disabling RoCE */ 42 static DEFINE_MUTEX(mlx5_roce_en_lock); 43 44 u8 mlx5_query_vport_state(struct mlx5_core_dev *mdev, u8 opmod, u16 vport) 45 { 46 u32 out[MLX5_ST_SZ_DW(query_vport_state_out)] = {}; 47 u32 in[MLX5_ST_SZ_DW(query_vport_state_in)] = {}; 48 int err; 49 50 MLX5_SET(query_vport_state_in, in, opcode, 51 MLX5_CMD_OP_QUERY_VPORT_STATE); 52 MLX5_SET(query_vport_state_in, in, op_mod, opmod); 53 MLX5_SET(query_vport_state_in, in, vport_number, vport); 54 if (vport) 55 MLX5_SET(query_vport_state_in, in, other_vport, 1); 56 57 err = mlx5_cmd_exec_inout(mdev, query_vport_state, in, out); 58 if (err) 59 return 0; 60 61 return MLX5_GET(query_vport_state_out, out, state); 62 } 63 64 int mlx5_modify_vport_admin_state(struct mlx5_core_dev *mdev, u8 opmod, 65 u16 vport, u8 other_vport, u8 state) 66 { 67 u32 in[MLX5_ST_SZ_DW(modify_vport_state_in)] = {}; 68 69 MLX5_SET(modify_vport_state_in, in, opcode, 70 MLX5_CMD_OP_MODIFY_VPORT_STATE); 71 MLX5_SET(modify_vport_state_in, in, op_mod, opmod); 72 MLX5_SET(modify_vport_state_in, in, vport_number, vport); 73 MLX5_SET(modify_vport_state_in, in, other_vport, other_vport); 74 MLX5_SET(modify_vport_state_in, in, admin_state, state); 75 76 return mlx5_cmd_exec_in(mdev, modify_vport_state, in); 77 } 78 79 static int mlx5_query_nic_vport_context(struct mlx5_core_dev *mdev, u16 vport, 80 u32 *out) 81 { 82 u32 in[MLX5_ST_SZ_DW(query_nic_vport_context_in)] = {}; 83 84 MLX5_SET(query_nic_vport_context_in, in, opcode, 85 MLX5_CMD_OP_QUERY_NIC_VPORT_CONTEXT); 86 MLX5_SET(query_nic_vport_context_in, in, vport_number, vport); 87 if (vport) 88 MLX5_SET(query_nic_vport_context_in, in, other_vport, 1); 89 90 return mlx5_cmd_exec_inout(mdev, query_nic_vport_context, in, out); 91 } 92 93 int 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, 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 } 105 EXPORT_SYMBOL_GPL(mlx5_query_nic_vport_min_inline); 106 107 void 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 } 123 EXPORT_SYMBOL_GPL(mlx5_query_min_inline); 124 125 int 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 146 int 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 } 168 EXPORT_SYMBOL_GPL(mlx5_query_nic_vport_mac_address); 169 170 int 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 } 174 EXPORT_SYMBOL_GPL(mlx5_query_mac_address); 175 176 int 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 } 209 EXPORT_SYMBOL_GPL(mlx5_modify_nic_vport_mac_address); 210 211 int 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, 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 } 229 EXPORT_SYMBOL_GPL(mlx5_query_nic_vport_mtu); 230 231 int 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 } 251 EXPORT_SYMBOL_GPL(mlx5_modify_nic_vport_mtu); 252 253 int 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_in) + 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 MLX5_SET(query_nic_vport_context_in, in, other_vport, 1); 292 293 err = mlx5_cmd_exec(dev, in, sizeof(in), out, out_sz); 294 if (err) 295 goto out; 296 297 nic_vport_ctx = MLX5_ADDR_OF(query_nic_vport_context_out, out, 298 nic_vport_context); 299 req_list_size = MLX5_GET(nic_vport_context, nic_vport_ctx, 300 allowed_list_size); 301 302 *list_size = req_list_size; 303 for (i = 0; i < req_list_size; i++) { 304 u8 *mac_addr = MLX5_ADDR_OF(nic_vport_context, 305 nic_vport_ctx, 306 current_uc_mac_address[i]) + 2; 307 ether_addr_copy(addr_list[i], mac_addr); 308 } 309 out: 310 kvfree(out); 311 return err; 312 } 313 EXPORT_SYMBOL_GPL(mlx5_query_nic_vport_mac_list); 314 315 int mlx5_modify_nic_vport_mac_list(struct mlx5_core_dev *dev, 316 enum mlx5_list_type list_type, 317 u8 addr_list[][ETH_ALEN], 318 int list_size) 319 { 320 u32 out[MLX5_ST_SZ_DW(modify_nic_vport_context_out)] = {}; 321 void *nic_vport_ctx; 322 int max_list_size; 323 int in_sz; 324 void *in; 325 int err; 326 int i; 327 328 max_list_size = list_type == MLX5_NVPRT_LIST_TYPE_UC ? 329 1 << MLX5_CAP_GEN(dev, log_max_current_uc_list) : 330 1 << MLX5_CAP_GEN(dev, log_max_current_mc_list); 331 332 if (list_size > max_list_size) 333 return -ENOSPC; 334 335 in_sz = MLX5_ST_SZ_BYTES(modify_nic_vport_context_in) + 336 list_size * MLX5_ST_SZ_BYTES(mac_address_layout); 337 338 in = kvzalloc(in_sz, GFP_KERNEL); 339 if (!in) 340 return -ENOMEM; 341 342 MLX5_SET(modify_nic_vport_context_in, in, opcode, 343 MLX5_CMD_OP_MODIFY_NIC_VPORT_CONTEXT); 344 MLX5_SET(modify_nic_vport_context_in, in, 345 field_select.addresses_list, 1); 346 347 nic_vport_ctx = MLX5_ADDR_OF(modify_nic_vport_context_in, in, 348 nic_vport_context); 349 350 MLX5_SET(nic_vport_context, nic_vport_ctx, 351 allowed_list_type, list_type); 352 MLX5_SET(nic_vport_context, nic_vport_ctx, 353 allowed_list_size, list_size); 354 355 for (i = 0; i < list_size; i++) { 356 u8 *curr_mac = MLX5_ADDR_OF(nic_vport_context, 357 nic_vport_ctx, 358 current_uc_mac_address[i]) + 2; 359 ether_addr_copy(curr_mac, addr_list[i]); 360 } 361 362 err = mlx5_cmd_exec(dev, in, in_sz, out, sizeof(out)); 363 kvfree(in); 364 return err; 365 } 366 EXPORT_SYMBOL_GPL(mlx5_modify_nic_vport_mac_list); 367 368 int mlx5_modify_nic_vport_vlans(struct mlx5_core_dev *dev, 369 u16 vlans[], 370 int list_size) 371 { 372 u32 out[MLX5_ST_SZ_DW(modify_nic_vport_context_out)]; 373 void *nic_vport_ctx; 374 int max_list_size; 375 int in_sz; 376 void *in; 377 int err; 378 int i; 379 380 max_list_size = 1 << MLX5_CAP_GEN(dev, log_max_vlan_list); 381 382 if (list_size > max_list_size) 383 return -ENOSPC; 384 385 in_sz = MLX5_ST_SZ_BYTES(modify_nic_vport_context_in) + 386 list_size * MLX5_ST_SZ_BYTES(vlan_layout); 387 388 memset(out, 0, sizeof(out)); 389 in = kvzalloc(in_sz, GFP_KERNEL); 390 if (!in) 391 return -ENOMEM; 392 393 MLX5_SET(modify_nic_vport_context_in, in, opcode, 394 MLX5_CMD_OP_MODIFY_NIC_VPORT_CONTEXT); 395 MLX5_SET(modify_nic_vport_context_in, in, 396 field_select.addresses_list, 1); 397 398 nic_vport_ctx = MLX5_ADDR_OF(modify_nic_vport_context_in, in, 399 nic_vport_context); 400 401 MLX5_SET(nic_vport_context, nic_vport_ctx, 402 allowed_list_type, MLX5_NVPRT_LIST_TYPE_VLAN); 403 MLX5_SET(nic_vport_context, nic_vport_ctx, 404 allowed_list_size, list_size); 405 406 for (i = 0; i < list_size; i++) { 407 void *vlan_addr = MLX5_ADDR_OF(nic_vport_context, 408 nic_vport_ctx, 409 current_uc_mac_address[i]); 410 MLX5_SET(vlan_layout, vlan_addr, vlan, vlans[i]); 411 } 412 413 err = mlx5_cmd_exec(dev, in, in_sz, out, sizeof(out)); 414 kvfree(in); 415 return err; 416 } 417 EXPORT_SYMBOL_GPL(mlx5_modify_nic_vport_vlans); 418 419 int mlx5_query_nic_vport_system_image_guid(struct mlx5_core_dev *mdev, 420 u64 *system_image_guid) 421 { 422 u32 *out; 423 int outlen = MLX5_ST_SZ_BYTES(query_nic_vport_context_out); 424 int err; 425 426 out = kvzalloc(outlen, GFP_KERNEL); 427 if (!out) 428 return -ENOMEM; 429 430 err = mlx5_query_nic_vport_context(mdev, 0, out); 431 if (err) 432 goto out; 433 434 *system_image_guid = MLX5_GET64(query_nic_vport_context_out, out, 435 nic_vport_context.system_image_guid); 436 out: 437 kvfree(out); 438 return err; 439 } 440 EXPORT_SYMBOL_GPL(mlx5_query_nic_vport_system_image_guid); 441 442 int mlx5_query_nic_vport_node_guid(struct mlx5_core_dev *mdev, u64 *node_guid) 443 { 444 u32 *out; 445 int outlen = MLX5_ST_SZ_BYTES(query_nic_vport_context_out); 446 447 out = kvzalloc(outlen, GFP_KERNEL); 448 if (!out) 449 return -ENOMEM; 450 451 mlx5_query_nic_vport_context(mdev, 0, out); 452 453 *node_guid = MLX5_GET64(query_nic_vport_context_out, out, 454 nic_vport_context.node_guid); 455 456 kvfree(out); 457 458 return 0; 459 } 460 EXPORT_SYMBOL_GPL(mlx5_query_nic_vport_node_guid); 461 462 int mlx5_modify_nic_vport_node_guid(struct mlx5_core_dev *mdev, 463 u16 vport, u64 node_guid) 464 { 465 int inlen = MLX5_ST_SZ_BYTES(modify_nic_vport_context_in); 466 void *nic_vport_context; 467 void *in; 468 int err; 469 470 if (!MLX5_CAP_GEN(mdev, vport_group_manager)) 471 return -EACCES; 472 473 in = kvzalloc(inlen, GFP_KERNEL); 474 if (!in) 475 return -ENOMEM; 476 477 MLX5_SET(modify_nic_vport_context_in, in, 478 field_select.node_guid, 1); 479 MLX5_SET(modify_nic_vport_context_in, in, vport_number, vport); 480 MLX5_SET(modify_nic_vport_context_in, in, other_vport, 1); 481 482 nic_vport_context = MLX5_ADDR_OF(modify_nic_vport_context_in, 483 in, nic_vport_context); 484 MLX5_SET64(nic_vport_context, nic_vport_context, node_guid, node_guid); 485 MLX5_SET(modify_nic_vport_context_in, in, opcode, 486 MLX5_CMD_OP_MODIFY_NIC_VPORT_CONTEXT); 487 488 err = mlx5_cmd_exec_in(mdev, modify_nic_vport_context, in); 489 490 kvfree(in); 491 492 return err; 493 } 494 495 int mlx5_query_nic_vport_qkey_viol_cntr(struct mlx5_core_dev *mdev, 496 u16 *qkey_viol_cntr) 497 { 498 u32 *out; 499 int outlen = MLX5_ST_SZ_BYTES(query_nic_vport_context_out); 500 501 out = kvzalloc(outlen, GFP_KERNEL); 502 if (!out) 503 return -ENOMEM; 504 505 mlx5_query_nic_vport_context(mdev, 0, out); 506 507 *qkey_viol_cntr = MLX5_GET(query_nic_vport_context_out, out, 508 nic_vport_context.qkey_violation_counter); 509 510 kvfree(out); 511 512 return 0; 513 } 514 EXPORT_SYMBOL_GPL(mlx5_query_nic_vport_qkey_viol_cntr); 515 516 int mlx5_query_hca_vport_gid(struct mlx5_core_dev *dev, u8 other_vport, 517 u8 port_num, u16 vf_num, u16 gid_index, 518 union ib_gid *gid) 519 { 520 int in_sz = MLX5_ST_SZ_BYTES(query_hca_vport_gid_in); 521 int out_sz = MLX5_ST_SZ_BYTES(query_hca_vport_gid_out); 522 int is_group_manager; 523 void *out = NULL; 524 void *in = NULL; 525 union ib_gid *tmp; 526 int tbsz; 527 int nout; 528 int err; 529 530 is_group_manager = MLX5_CAP_GEN(dev, vport_group_manager); 531 tbsz = mlx5_get_gid_table_len(MLX5_CAP_GEN(dev, gid_table_size)); 532 mlx5_core_dbg(dev, "vf_num %d, index %d, gid_table_size %d\n", 533 vf_num, gid_index, tbsz); 534 535 if (gid_index > tbsz && gid_index != 0xffff) 536 return -EINVAL; 537 538 if (gid_index == 0xffff) 539 nout = tbsz; 540 else 541 nout = 1; 542 543 out_sz += nout * sizeof(*gid); 544 545 in = kvzalloc(in_sz, GFP_KERNEL); 546 out = kvzalloc(out_sz, GFP_KERNEL); 547 if (!in || !out) { 548 err = -ENOMEM; 549 goto out; 550 } 551 552 MLX5_SET(query_hca_vport_gid_in, in, opcode, MLX5_CMD_OP_QUERY_HCA_VPORT_GID); 553 if (other_vport) { 554 if (is_group_manager) { 555 MLX5_SET(query_hca_vport_gid_in, in, vport_number, vf_num); 556 MLX5_SET(query_hca_vport_gid_in, in, other_vport, 1); 557 } else { 558 err = -EPERM; 559 goto out; 560 } 561 } 562 MLX5_SET(query_hca_vport_gid_in, in, gid_index, gid_index); 563 564 if (MLX5_CAP_GEN(dev, num_ports) == 2) 565 MLX5_SET(query_hca_vport_gid_in, in, port_num, port_num); 566 567 err = mlx5_cmd_exec(dev, in, in_sz, out, out_sz); 568 if (err) 569 goto out; 570 571 tmp = out + MLX5_ST_SZ_BYTES(query_hca_vport_gid_out); 572 gid->global.subnet_prefix = tmp->global.subnet_prefix; 573 gid->global.interface_id = tmp->global.interface_id; 574 575 out: 576 kvfree(in); 577 kvfree(out); 578 return err; 579 } 580 EXPORT_SYMBOL_GPL(mlx5_query_hca_vport_gid); 581 582 int mlx5_query_hca_vport_pkey(struct mlx5_core_dev *dev, u8 other_vport, 583 u8 port_num, u16 vf_num, u16 pkey_index, 584 u16 *pkey) 585 { 586 int in_sz = MLX5_ST_SZ_BYTES(query_hca_vport_pkey_in); 587 int out_sz = MLX5_ST_SZ_BYTES(query_hca_vport_pkey_out); 588 int is_group_manager; 589 void *out = NULL; 590 void *in = NULL; 591 void *pkarr; 592 int nout; 593 int tbsz; 594 int err; 595 int i; 596 597 is_group_manager = MLX5_CAP_GEN(dev, vport_group_manager); 598 599 tbsz = mlx5_to_sw_pkey_sz(MLX5_CAP_GEN(dev, pkey_table_size)); 600 if (pkey_index > tbsz && pkey_index != 0xffff) 601 return -EINVAL; 602 603 if (pkey_index == 0xffff) 604 nout = tbsz; 605 else 606 nout = 1; 607 608 out_sz += nout * MLX5_ST_SZ_BYTES(pkey); 609 610 in = kvzalloc(in_sz, GFP_KERNEL); 611 out = kvzalloc(out_sz, GFP_KERNEL); 612 if (!in || !out) { 613 err = -ENOMEM; 614 goto out; 615 } 616 617 MLX5_SET(query_hca_vport_pkey_in, in, opcode, MLX5_CMD_OP_QUERY_HCA_VPORT_PKEY); 618 if (other_vport) { 619 if (is_group_manager) { 620 MLX5_SET(query_hca_vport_pkey_in, in, vport_number, vf_num); 621 MLX5_SET(query_hca_vport_pkey_in, in, other_vport, 1); 622 } else { 623 err = -EPERM; 624 goto out; 625 } 626 } 627 MLX5_SET(query_hca_vport_pkey_in, in, pkey_index, pkey_index); 628 629 if (MLX5_CAP_GEN(dev, num_ports) == 2) 630 MLX5_SET(query_hca_vport_pkey_in, in, port_num, port_num); 631 632 err = mlx5_cmd_exec(dev, in, in_sz, out, out_sz); 633 if (err) 634 goto out; 635 636 pkarr = MLX5_ADDR_OF(query_hca_vport_pkey_out, out, pkey); 637 for (i = 0; i < nout; i++, pkey++, pkarr += MLX5_ST_SZ_BYTES(pkey)) 638 *pkey = MLX5_GET_PR(pkey, pkarr, pkey); 639 640 out: 641 kvfree(in); 642 kvfree(out); 643 return err; 644 } 645 EXPORT_SYMBOL_GPL(mlx5_query_hca_vport_pkey); 646 647 int mlx5_query_hca_vport_context(struct mlx5_core_dev *dev, 648 u8 other_vport, u8 port_num, 649 u16 vf_num, 650 struct mlx5_hca_vport_context *rep) 651 { 652 int out_sz = MLX5_ST_SZ_BYTES(query_hca_vport_context_out); 653 int in[MLX5_ST_SZ_DW(query_hca_vport_context_in)] = {}; 654 int is_group_manager; 655 void *out; 656 void *ctx; 657 int err; 658 659 is_group_manager = MLX5_CAP_GEN(dev, vport_group_manager); 660 661 out = kvzalloc(out_sz, GFP_KERNEL); 662 if (!out) 663 return -ENOMEM; 664 665 MLX5_SET(query_hca_vport_context_in, in, opcode, MLX5_CMD_OP_QUERY_HCA_VPORT_CONTEXT); 666 667 if (other_vport) { 668 if (is_group_manager) { 669 MLX5_SET(query_hca_vport_context_in, in, other_vport, 1); 670 MLX5_SET(query_hca_vport_context_in, in, vport_number, vf_num); 671 } else { 672 err = -EPERM; 673 goto ex; 674 } 675 } 676 677 if (MLX5_CAP_GEN(dev, num_ports) == 2) 678 MLX5_SET(query_hca_vport_context_in, in, port_num, port_num); 679 680 err = mlx5_cmd_exec_inout(dev, query_hca_vport_context, in, out); 681 if (err) 682 goto ex; 683 684 ctx = MLX5_ADDR_OF(query_hca_vport_context_out, out, hca_vport_context); 685 rep->field_select = MLX5_GET_PR(hca_vport_context, ctx, field_select); 686 rep->sm_virt_aware = MLX5_GET_PR(hca_vport_context, ctx, sm_virt_aware); 687 rep->has_smi = MLX5_GET_PR(hca_vport_context, ctx, has_smi); 688 rep->has_raw = MLX5_GET_PR(hca_vport_context, ctx, has_raw); 689 rep->policy = MLX5_GET_PR(hca_vport_context, ctx, vport_state_policy); 690 rep->phys_state = MLX5_GET_PR(hca_vport_context, ctx, 691 port_physical_state); 692 rep->vport_state = MLX5_GET_PR(hca_vport_context, ctx, vport_state); 693 rep->port_physical_state = MLX5_GET_PR(hca_vport_context, ctx, 694 port_physical_state); 695 rep->port_guid = MLX5_GET64_PR(hca_vport_context, ctx, port_guid); 696 rep->node_guid = MLX5_GET64_PR(hca_vport_context, ctx, node_guid); 697 rep->cap_mask1 = MLX5_GET_PR(hca_vport_context, ctx, cap_mask1); 698 rep->cap_mask1_perm = MLX5_GET_PR(hca_vport_context, ctx, 699 cap_mask1_field_select); 700 rep->cap_mask2 = MLX5_GET_PR(hca_vport_context, ctx, cap_mask2); 701 rep->cap_mask2_perm = MLX5_GET_PR(hca_vport_context, ctx, 702 cap_mask2_field_select); 703 rep->lid = MLX5_GET_PR(hca_vport_context, ctx, lid); 704 rep->init_type_reply = MLX5_GET_PR(hca_vport_context, ctx, 705 init_type_reply); 706 rep->lmc = MLX5_GET_PR(hca_vport_context, ctx, lmc); 707 rep->subnet_timeout = MLX5_GET_PR(hca_vport_context, ctx, 708 subnet_timeout); 709 rep->sm_lid = MLX5_GET_PR(hca_vport_context, ctx, sm_lid); 710 rep->sm_sl = MLX5_GET_PR(hca_vport_context, ctx, sm_sl); 711 rep->qkey_violation_counter = MLX5_GET_PR(hca_vport_context, ctx, 712 qkey_violation_counter); 713 rep->pkey_violation_counter = MLX5_GET_PR(hca_vport_context, ctx, 714 pkey_violation_counter); 715 rep->grh_required = MLX5_GET_PR(hca_vport_context, ctx, grh_required); 716 rep->sys_image_guid = MLX5_GET64_PR(hca_vport_context, ctx, 717 system_image_guid); 718 719 ex: 720 kvfree(out); 721 return err; 722 } 723 EXPORT_SYMBOL_GPL(mlx5_query_hca_vport_context); 724 725 int mlx5_query_hca_vport_system_image_guid(struct mlx5_core_dev *dev, 726 u64 *sys_image_guid) 727 { 728 struct mlx5_hca_vport_context *rep; 729 int err; 730 731 rep = kvzalloc(sizeof(*rep), GFP_KERNEL); 732 if (!rep) 733 return -ENOMEM; 734 735 err = mlx5_query_hca_vport_context(dev, 0, 1, 0, rep); 736 if (!err) 737 *sys_image_guid = rep->sys_image_guid; 738 739 kvfree(rep); 740 return err; 741 } 742 EXPORT_SYMBOL_GPL(mlx5_query_hca_vport_system_image_guid); 743 744 int mlx5_query_hca_vport_node_guid(struct mlx5_core_dev *dev, 745 u64 *node_guid) 746 { 747 struct mlx5_hca_vport_context *rep; 748 int err; 749 750 rep = kvzalloc(sizeof(*rep), GFP_KERNEL); 751 if (!rep) 752 return -ENOMEM; 753 754 err = mlx5_query_hca_vport_context(dev, 0, 1, 0, rep); 755 if (!err) 756 *node_guid = rep->node_guid; 757 758 kvfree(rep); 759 return err; 760 } 761 EXPORT_SYMBOL_GPL(mlx5_query_hca_vport_node_guid); 762 763 int mlx5_query_nic_vport_promisc(struct mlx5_core_dev *mdev, 764 u16 vport, 765 int *promisc_uc, 766 int *promisc_mc, 767 int *promisc_all) 768 { 769 u32 *out; 770 int outlen = MLX5_ST_SZ_BYTES(query_nic_vport_context_out); 771 int err; 772 773 out = kvzalloc(outlen, GFP_KERNEL); 774 if (!out) 775 return -ENOMEM; 776 777 err = mlx5_query_nic_vport_context(mdev, vport, out); 778 if (err) 779 goto out; 780 781 *promisc_uc = MLX5_GET(query_nic_vport_context_out, out, 782 nic_vport_context.promisc_uc); 783 *promisc_mc = MLX5_GET(query_nic_vport_context_out, out, 784 nic_vport_context.promisc_mc); 785 *promisc_all = MLX5_GET(query_nic_vport_context_out, out, 786 nic_vport_context.promisc_all); 787 788 out: 789 kvfree(out); 790 return err; 791 } 792 EXPORT_SYMBOL_GPL(mlx5_query_nic_vport_promisc); 793 794 int mlx5_modify_nic_vport_promisc(struct mlx5_core_dev *mdev, 795 int promisc_uc, 796 int promisc_mc, 797 int promisc_all) 798 { 799 void *in; 800 int inlen = MLX5_ST_SZ_BYTES(modify_nic_vport_context_in); 801 int err; 802 803 in = kvzalloc(inlen, GFP_KERNEL); 804 if (!in) 805 return -ENOMEM; 806 807 MLX5_SET(modify_nic_vport_context_in, in, field_select.promisc, 1); 808 MLX5_SET(modify_nic_vport_context_in, in, 809 nic_vport_context.promisc_uc, promisc_uc); 810 MLX5_SET(modify_nic_vport_context_in, in, 811 nic_vport_context.promisc_mc, promisc_mc); 812 MLX5_SET(modify_nic_vport_context_in, in, 813 nic_vport_context.promisc_all, promisc_all); 814 MLX5_SET(modify_nic_vport_context_in, in, opcode, 815 MLX5_CMD_OP_MODIFY_NIC_VPORT_CONTEXT); 816 817 err = mlx5_cmd_exec_in(mdev, modify_nic_vport_context, in); 818 819 kvfree(in); 820 821 return err; 822 } 823 EXPORT_SYMBOL_GPL(mlx5_modify_nic_vport_promisc); 824 825 enum { 826 UC_LOCAL_LB, 827 MC_LOCAL_LB 828 }; 829 830 int mlx5_nic_vport_update_local_lb(struct mlx5_core_dev *mdev, bool enable) 831 { 832 int inlen = MLX5_ST_SZ_BYTES(modify_nic_vport_context_in); 833 void *in; 834 int err; 835 836 if (!MLX5_CAP_GEN(mdev, disable_local_lb_mc) && 837 !MLX5_CAP_GEN(mdev, disable_local_lb_uc)) 838 return 0; 839 840 in = kvzalloc(inlen, GFP_KERNEL); 841 if (!in) 842 return -ENOMEM; 843 844 MLX5_SET(modify_nic_vport_context_in, in, 845 nic_vport_context.disable_mc_local_lb, !enable); 846 MLX5_SET(modify_nic_vport_context_in, in, 847 nic_vport_context.disable_uc_local_lb, !enable); 848 849 if (MLX5_CAP_GEN(mdev, disable_local_lb_mc)) 850 MLX5_SET(modify_nic_vport_context_in, in, 851 field_select.disable_mc_local_lb, 1); 852 853 if (MLX5_CAP_GEN(mdev, disable_local_lb_uc)) 854 MLX5_SET(modify_nic_vport_context_in, in, 855 field_select.disable_uc_local_lb, 1); 856 MLX5_SET(modify_nic_vport_context_in, in, opcode, 857 MLX5_CMD_OP_MODIFY_NIC_VPORT_CONTEXT); 858 859 err = mlx5_cmd_exec_in(mdev, modify_nic_vport_context, in); 860 861 if (!err) 862 mlx5_core_dbg(mdev, "%s local_lb\n", 863 enable ? "enable" : "disable"); 864 865 kvfree(in); 866 return err; 867 } 868 EXPORT_SYMBOL_GPL(mlx5_nic_vport_update_local_lb); 869 870 int mlx5_nic_vport_query_local_lb(struct mlx5_core_dev *mdev, bool *status) 871 { 872 int outlen = MLX5_ST_SZ_BYTES(query_nic_vport_context_out); 873 u32 *out; 874 int value; 875 int err; 876 877 out = kvzalloc(outlen, GFP_KERNEL); 878 if (!out) 879 return -ENOMEM; 880 881 err = mlx5_query_nic_vport_context(mdev, 0, out); 882 if (err) 883 goto out; 884 885 value = MLX5_GET(query_nic_vport_context_out, out, 886 nic_vport_context.disable_mc_local_lb) << MC_LOCAL_LB; 887 888 value |= MLX5_GET(query_nic_vport_context_out, out, 889 nic_vport_context.disable_uc_local_lb) << UC_LOCAL_LB; 890 891 *status = !value; 892 893 out: 894 kvfree(out); 895 return err; 896 } 897 EXPORT_SYMBOL_GPL(mlx5_nic_vport_query_local_lb); 898 899 enum mlx5_vport_roce_state { 900 MLX5_VPORT_ROCE_DISABLED = 0, 901 MLX5_VPORT_ROCE_ENABLED = 1, 902 }; 903 904 static int mlx5_nic_vport_update_roce_state(struct mlx5_core_dev *mdev, 905 enum mlx5_vport_roce_state state) 906 { 907 void *in; 908 int inlen = MLX5_ST_SZ_BYTES(modify_nic_vport_context_in); 909 int err; 910 911 in = kvzalloc(inlen, GFP_KERNEL); 912 if (!in) 913 return -ENOMEM; 914 915 MLX5_SET(modify_nic_vport_context_in, in, field_select.roce_en, 1); 916 MLX5_SET(modify_nic_vport_context_in, in, nic_vport_context.roce_en, 917 state); 918 MLX5_SET(modify_nic_vport_context_in, in, opcode, 919 MLX5_CMD_OP_MODIFY_NIC_VPORT_CONTEXT); 920 921 err = mlx5_cmd_exec_in(mdev, modify_nic_vport_context, in); 922 923 kvfree(in); 924 925 return err; 926 } 927 928 int mlx5_nic_vport_enable_roce(struct mlx5_core_dev *mdev) 929 { 930 int err = 0; 931 932 mutex_lock(&mlx5_roce_en_lock); 933 if (!mdev->roce.roce_en) 934 err = mlx5_nic_vport_update_roce_state(mdev, MLX5_VPORT_ROCE_ENABLED); 935 936 if (!err) 937 mdev->roce.roce_en++; 938 mutex_unlock(&mlx5_roce_en_lock); 939 940 return err; 941 } 942 EXPORT_SYMBOL_GPL(mlx5_nic_vport_enable_roce); 943 944 int mlx5_nic_vport_disable_roce(struct mlx5_core_dev *mdev) 945 { 946 int err = 0; 947 948 mutex_lock(&mlx5_roce_en_lock); 949 if (mdev->roce.roce_en) { 950 mdev->roce.roce_en--; 951 if (mdev->roce.roce_en == 0) 952 err = mlx5_nic_vport_update_roce_state(mdev, MLX5_VPORT_ROCE_DISABLED); 953 954 if (err) 955 mdev->roce.roce_en++; 956 } 957 mutex_unlock(&mlx5_roce_en_lock); 958 return err; 959 } 960 EXPORT_SYMBOL(mlx5_nic_vport_disable_roce); 961 962 int mlx5_core_query_vport_counter(struct mlx5_core_dev *dev, u8 other_vport, 963 int vf, u8 port_num, void *out) 964 { 965 int in_sz = MLX5_ST_SZ_BYTES(query_vport_counter_in); 966 int is_group_manager; 967 void *in; 968 int err; 969 970 is_group_manager = MLX5_CAP_GEN(dev, vport_group_manager); 971 in = kvzalloc(in_sz, GFP_KERNEL); 972 if (!in) { 973 err = -ENOMEM; 974 return err; 975 } 976 977 MLX5_SET(query_vport_counter_in, in, opcode, 978 MLX5_CMD_OP_QUERY_VPORT_COUNTER); 979 if (other_vport) { 980 if (is_group_manager) { 981 MLX5_SET(query_vport_counter_in, in, other_vport, 1); 982 MLX5_SET(query_vport_counter_in, in, vport_number, vf + 1); 983 } else { 984 err = -EPERM; 985 goto free; 986 } 987 } 988 if (MLX5_CAP_GEN(dev, num_ports) == 2) 989 MLX5_SET(query_vport_counter_in, in, port_num, port_num); 990 991 err = mlx5_cmd_exec_inout(dev, query_vport_counter, in, out); 992 free: 993 kvfree(in); 994 return err; 995 } 996 EXPORT_SYMBOL_GPL(mlx5_core_query_vport_counter); 997 998 int mlx5_query_vport_down_stats(struct mlx5_core_dev *mdev, u16 vport, 999 u8 other_vport, u64 *rx_discard_vport_down, 1000 u64 *tx_discard_vport_down) 1001 { 1002 u32 out[MLX5_ST_SZ_DW(query_vnic_env_out)] = {}; 1003 u32 in[MLX5_ST_SZ_DW(query_vnic_env_in)] = {}; 1004 int err; 1005 1006 MLX5_SET(query_vnic_env_in, in, opcode, 1007 MLX5_CMD_OP_QUERY_VNIC_ENV); 1008 MLX5_SET(query_vnic_env_in, in, op_mod, 0); 1009 MLX5_SET(query_vnic_env_in, in, vport_number, vport); 1010 MLX5_SET(query_vnic_env_in, in, other_vport, other_vport); 1011 1012 err = mlx5_cmd_exec_inout(mdev, query_vnic_env, in, out); 1013 if (err) 1014 return err; 1015 1016 *rx_discard_vport_down = MLX5_GET64(query_vnic_env_out, out, 1017 vport_env.receive_discard_vport_down); 1018 *tx_discard_vport_down = MLX5_GET64(query_vnic_env_out, out, 1019 vport_env.transmit_discard_vport_down); 1020 return 0; 1021 } 1022 1023 int mlx5_core_modify_hca_vport_context(struct mlx5_core_dev *dev, 1024 u8 other_vport, u8 port_num, 1025 int vf, 1026 struct mlx5_hca_vport_context *req) 1027 { 1028 int in_sz = MLX5_ST_SZ_BYTES(modify_hca_vport_context_in); 1029 int is_group_manager; 1030 void *ctx; 1031 void *in; 1032 int err; 1033 1034 mlx5_core_dbg(dev, "vf %d\n", vf); 1035 is_group_manager = MLX5_CAP_GEN(dev, vport_group_manager); 1036 in = kvzalloc(in_sz, GFP_KERNEL); 1037 if (!in) 1038 return -ENOMEM; 1039 1040 MLX5_SET(modify_hca_vport_context_in, in, opcode, MLX5_CMD_OP_MODIFY_HCA_VPORT_CONTEXT); 1041 if (other_vport) { 1042 if (is_group_manager) { 1043 MLX5_SET(modify_hca_vport_context_in, in, other_vport, 1); 1044 MLX5_SET(modify_hca_vport_context_in, in, vport_number, vf); 1045 } else { 1046 err = -EPERM; 1047 goto ex; 1048 } 1049 } 1050 1051 if (MLX5_CAP_GEN(dev, num_ports) > 1) 1052 MLX5_SET(modify_hca_vport_context_in, in, port_num, port_num); 1053 1054 ctx = MLX5_ADDR_OF(modify_hca_vport_context_in, in, hca_vport_context); 1055 MLX5_SET(hca_vport_context, ctx, field_select, req->field_select); 1056 if (req->field_select & MLX5_HCA_VPORT_SEL_STATE_POLICY) 1057 MLX5_SET(hca_vport_context, ctx, vport_state_policy, 1058 req->policy); 1059 if (req->field_select & MLX5_HCA_VPORT_SEL_PORT_GUID) 1060 MLX5_SET64(hca_vport_context, ctx, port_guid, req->port_guid); 1061 if (req->field_select & MLX5_HCA_VPORT_SEL_NODE_GUID) 1062 MLX5_SET64(hca_vport_context, ctx, node_guid, req->node_guid); 1063 MLX5_SET(hca_vport_context, ctx, cap_mask1, req->cap_mask1); 1064 MLX5_SET(hca_vport_context, ctx, cap_mask1_field_select, 1065 req->cap_mask1_perm); 1066 err = mlx5_cmd_exec_in(dev, modify_hca_vport_context, in); 1067 ex: 1068 kvfree(in); 1069 return err; 1070 } 1071 EXPORT_SYMBOL_GPL(mlx5_core_modify_hca_vport_context); 1072 1073 int mlx5_nic_vport_affiliate_multiport(struct mlx5_core_dev *master_mdev, 1074 struct mlx5_core_dev *port_mdev) 1075 { 1076 int inlen = MLX5_ST_SZ_BYTES(modify_nic_vport_context_in); 1077 void *in; 1078 int err; 1079 1080 in = kvzalloc(inlen, GFP_KERNEL); 1081 if (!in) 1082 return -ENOMEM; 1083 1084 err = mlx5_nic_vport_enable_roce(port_mdev); 1085 if (err) 1086 goto free; 1087 1088 MLX5_SET(modify_nic_vport_context_in, in, field_select.affiliation, 1); 1089 if (MLX5_CAP_GEN_2(master_mdev, sw_vhca_id_valid)) { 1090 MLX5_SET(modify_nic_vport_context_in, in, 1091 nic_vport_context.vhca_id_type, VHCA_ID_TYPE_SW); 1092 MLX5_SET(modify_nic_vport_context_in, in, 1093 nic_vport_context.affiliated_vhca_id, 1094 MLX5_CAP_GEN_2(master_mdev, sw_vhca_id)); 1095 } else { 1096 MLX5_SET(modify_nic_vport_context_in, in, 1097 nic_vport_context.affiliated_vhca_id, 1098 MLX5_CAP_GEN(master_mdev, vhca_id)); 1099 } 1100 MLX5_SET(modify_nic_vport_context_in, in, 1101 nic_vport_context.affiliation_criteria, 1102 MLX5_CAP_GEN(port_mdev, affiliate_nic_vport_criteria)); 1103 MLX5_SET(modify_nic_vport_context_in, in, opcode, 1104 MLX5_CMD_OP_MODIFY_NIC_VPORT_CONTEXT); 1105 1106 err = mlx5_cmd_exec_in(port_mdev, modify_nic_vport_context, in); 1107 if (err) 1108 mlx5_nic_vport_disable_roce(port_mdev); 1109 1110 free: 1111 kvfree(in); 1112 return err; 1113 } 1114 EXPORT_SYMBOL_GPL(mlx5_nic_vport_affiliate_multiport); 1115 1116 int mlx5_nic_vport_unaffiliate_multiport(struct mlx5_core_dev *port_mdev) 1117 { 1118 int inlen = MLX5_ST_SZ_BYTES(modify_nic_vport_context_in); 1119 void *in; 1120 int err; 1121 1122 in = kvzalloc(inlen, GFP_KERNEL); 1123 if (!in) 1124 return -ENOMEM; 1125 1126 MLX5_SET(modify_nic_vport_context_in, in, field_select.affiliation, 1); 1127 MLX5_SET(modify_nic_vport_context_in, in, 1128 nic_vport_context.affiliated_vhca_id, 0); 1129 MLX5_SET(modify_nic_vport_context_in, in, 1130 nic_vport_context.affiliation_criteria, 0); 1131 MLX5_SET(modify_nic_vport_context_in, in, opcode, 1132 MLX5_CMD_OP_MODIFY_NIC_VPORT_CONTEXT); 1133 1134 err = mlx5_cmd_exec_in(port_mdev, modify_nic_vport_context, in); 1135 if (!err) 1136 mlx5_nic_vport_disable_roce(port_mdev); 1137 1138 kvfree(in); 1139 return err; 1140 } 1141 EXPORT_SYMBOL_GPL(mlx5_nic_vport_unaffiliate_multiport); 1142 1143 u64 mlx5_query_nic_system_image_guid(struct mlx5_core_dev *mdev) 1144 { 1145 int port_type_cap = MLX5_CAP_GEN(mdev, port_type); 1146 u64 tmp; 1147 int err; 1148 1149 if (mdev->sys_image_guid) 1150 return mdev->sys_image_guid; 1151 1152 if (port_type_cap == MLX5_CAP_PORT_TYPE_ETH) 1153 err = mlx5_query_nic_vport_system_image_guid(mdev, &tmp); 1154 else 1155 err = mlx5_query_hca_vport_system_image_guid(mdev, &tmp); 1156 1157 mdev->sys_image_guid = err ? 0 : tmp; 1158 1159 return mdev->sys_image_guid; 1160 } 1161 EXPORT_SYMBOL_GPL(mlx5_query_nic_system_image_guid); 1162 1163 int mlx5_vport_get_other_func_cap(struct mlx5_core_dev *dev, u16 function_id, void *out) 1164 { 1165 u16 opmod = (MLX5_CAP_GENERAL << 1) | (HCA_CAP_OPMOD_GET_MAX & 0x01); 1166 u8 in[MLX5_ST_SZ_BYTES(query_hca_cap_in)] = {}; 1167 1168 MLX5_SET(query_hca_cap_in, in, opcode, MLX5_CMD_OP_QUERY_HCA_CAP); 1169 MLX5_SET(query_hca_cap_in, in, op_mod, opmod); 1170 MLX5_SET(query_hca_cap_in, in, function_id, function_id); 1171 MLX5_SET(query_hca_cap_in, in, other_function, true); 1172 return mlx5_cmd_exec_inout(dev, query_hca_cap, in, out); 1173 } 1174