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 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 } 310 out: 311 kvfree(out); 312 return err; 313 } 314 EXPORT_SYMBOL_GPL(mlx5_query_nic_vport_mac_list); 315 316 int 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 } 367 EXPORT_SYMBOL_GPL(mlx5_modify_nic_vport_mac_list); 368 369 int 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 } 418 EXPORT_SYMBOL_GPL(mlx5_modify_nic_vport_vlans); 419 420 int 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, 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); 437 out: 438 kvfree(out); 439 return err; 440 } 441 EXPORT_SYMBOL_GPL(mlx5_query_nic_vport_system_image_guid); 442 443 int mlx5_query_nic_vport_node_guid(struct mlx5_core_dev *mdev, u64 *node_guid) 444 { 445 u32 *out; 446 int outlen = MLX5_ST_SZ_BYTES(query_nic_vport_context_out); 447 448 out = kvzalloc(outlen, GFP_KERNEL); 449 if (!out) 450 return -ENOMEM; 451 452 mlx5_query_nic_vport_context(mdev, 0, out); 453 454 *node_guid = MLX5_GET64(query_nic_vport_context_out, out, 455 nic_vport_context.node_guid); 456 457 kvfree(out); 458 459 return 0; 460 } 461 EXPORT_SYMBOL_GPL(mlx5_query_nic_vport_node_guid); 462 463 int mlx5_modify_nic_vport_node_guid(struct mlx5_core_dev *mdev, 464 u16 vport, u64 node_guid) 465 { 466 int inlen = MLX5_ST_SZ_BYTES(modify_nic_vport_context_in); 467 void *nic_vport_context; 468 void *in; 469 int err; 470 471 if (!MLX5_CAP_GEN(mdev, vport_group_manager)) 472 return -EACCES; 473 474 in = kvzalloc(inlen, GFP_KERNEL); 475 if (!in) 476 return -ENOMEM; 477 478 MLX5_SET(modify_nic_vport_context_in, in, 479 field_select.node_guid, 1); 480 MLX5_SET(modify_nic_vport_context_in, in, vport_number, vport); 481 MLX5_SET(modify_nic_vport_context_in, in, other_vport, 1); 482 483 nic_vport_context = MLX5_ADDR_OF(modify_nic_vport_context_in, 484 in, nic_vport_context); 485 MLX5_SET64(nic_vport_context, nic_vport_context, node_guid, node_guid); 486 MLX5_SET(modify_nic_vport_context_in, in, opcode, 487 MLX5_CMD_OP_MODIFY_NIC_VPORT_CONTEXT); 488 489 err = mlx5_cmd_exec_in(mdev, modify_nic_vport_context, in); 490 491 kvfree(in); 492 493 return err; 494 } 495 496 int mlx5_query_nic_vport_qkey_viol_cntr(struct mlx5_core_dev *mdev, 497 u16 *qkey_viol_cntr) 498 { 499 u32 *out; 500 int outlen = MLX5_ST_SZ_BYTES(query_nic_vport_context_out); 501 502 out = kvzalloc(outlen, GFP_KERNEL); 503 if (!out) 504 return -ENOMEM; 505 506 mlx5_query_nic_vport_context(mdev, 0, out); 507 508 *qkey_viol_cntr = MLX5_GET(query_nic_vport_context_out, out, 509 nic_vport_context.qkey_violation_counter); 510 511 kvfree(out); 512 513 return 0; 514 } 515 EXPORT_SYMBOL_GPL(mlx5_query_nic_vport_qkey_viol_cntr); 516 517 int mlx5_query_hca_vport_gid(struct mlx5_core_dev *dev, u8 other_vport, 518 u8 port_num, u16 vf_num, u16 gid_index, 519 union ib_gid *gid) 520 { 521 int in_sz = MLX5_ST_SZ_BYTES(query_hca_vport_gid_in); 522 int out_sz = MLX5_ST_SZ_BYTES(query_hca_vport_gid_out); 523 int is_group_manager; 524 void *out = NULL; 525 void *in = NULL; 526 union ib_gid *tmp; 527 int tbsz; 528 int nout; 529 int err; 530 531 is_group_manager = MLX5_CAP_GEN(dev, vport_group_manager); 532 tbsz = mlx5_get_gid_table_len(MLX5_CAP_GEN(dev, gid_table_size)); 533 mlx5_core_dbg(dev, "vf_num %d, index %d, gid_table_size %d\n", 534 vf_num, gid_index, tbsz); 535 536 if (gid_index > tbsz && gid_index != 0xffff) 537 return -EINVAL; 538 539 if (gid_index == 0xffff) 540 nout = tbsz; 541 else 542 nout = 1; 543 544 out_sz += nout * sizeof(*gid); 545 546 in = kvzalloc(in_sz, GFP_KERNEL); 547 out = kvzalloc(out_sz, GFP_KERNEL); 548 if (!in || !out) { 549 err = -ENOMEM; 550 goto out; 551 } 552 553 MLX5_SET(query_hca_vport_gid_in, in, opcode, MLX5_CMD_OP_QUERY_HCA_VPORT_GID); 554 if (other_vport) { 555 if (is_group_manager) { 556 MLX5_SET(query_hca_vport_gid_in, in, vport_number, vf_num); 557 MLX5_SET(query_hca_vport_gid_in, in, other_vport, 1); 558 } else { 559 err = -EPERM; 560 goto out; 561 } 562 } 563 MLX5_SET(query_hca_vport_gid_in, in, gid_index, gid_index); 564 565 if (MLX5_CAP_GEN(dev, num_ports) == 2) 566 MLX5_SET(query_hca_vport_gid_in, in, port_num, port_num); 567 568 err = mlx5_cmd_exec(dev, in, in_sz, out, out_sz); 569 if (err) 570 goto out; 571 572 tmp = out + MLX5_ST_SZ_BYTES(query_hca_vport_gid_out); 573 gid->global.subnet_prefix = tmp->global.subnet_prefix; 574 gid->global.interface_id = tmp->global.interface_id; 575 576 out: 577 kvfree(in); 578 kvfree(out); 579 return err; 580 } 581 EXPORT_SYMBOL_GPL(mlx5_query_hca_vport_gid); 582 583 int mlx5_query_hca_vport_pkey(struct mlx5_core_dev *dev, u8 other_vport, 584 u8 port_num, u16 vf_num, u16 pkey_index, 585 u16 *pkey) 586 { 587 int in_sz = MLX5_ST_SZ_BYTES(query_hca_vport_pkey_in); 588 int out_sz = MLX5_ST_SZ_BYTES(query_hca_vport_pkey_out); 589 int is_group_manager; 590 void *out = NULL; 591 void *in = NULL; 592 void *pkarr; 593 int nout; 594 int tbsz; 595 int err; 596 int i; 597 598 is_group_manager = MLX5_CAP_GEN(dev, vport_group_manager); 599 600 tbsz = mlx5_to_sw_pkey_sz(MLX5_CAP_GEN(dev, pkey_table_size)); 601 if (pkey_index > tbsz && pkey_index != 0xffff) 602 return -EINVAL; 603 604 if (pkey_index == 0xffff) 605 nout = tbsz; 606 else 607 nout = 1; 608 609 out_sz += nout * MLX5_ST_SZ_BYTES(pkey); 610 611 in = kvzalloc(in_sz, GFP_KERNEL); 612 out = kvzalloc(out_sz, GFP_KERNEL); 613 if (!in || !out) { 614 err = -ENOMEM; 615 goto out; 616 } 617 618 MLX5_SET(query_hca_vport_pkey_in, in, opcode, MLX5_CMD_OP_QUERY_HCA_VPORT_PKEY); 619 if (other_vport) { 620 if (is_group_manager) { 621 MLX5_SET(query_hca_vport_pkey_in, in, vport_number, vf_num); 622 MLX5_SET(query_hca_vport_pkey_in, in, other_vport, 1); 623 } else { 624 err = -EPERM; 625 goto out; 626 } 627 } 628 MLX5_SET(query_hca_vport_pkey_in, in, pkey_index, pkey_index); 629 630 if (MLX5_CAP_GEN(dev, num_ports) == 2) 631 MLX5_SET(query_hca_vport_pkey_in, in, port_num, port_num); 632 633 err = mlx5_cmd_exec(dev, in, in_sz, out, out_sz); 634 if (err) 635 goto out; 636 637 pkarr = MLX5_ADDR_OF(query_hca_vport_pkey_out, out, pkey); 638 for (i = 0; i < nout; i++, pkey++, pkarr += MLX5_ST_SZ_BYTES(pkey)) 639 *pkey = MLX5_GET_PR(pkey, pkarr, pkey); 640 641 out: 642 kvfree(in); 643 kvfree(out); 644 return err; 645 } 646 EXPORT_SYMBOL_GPL(mlx5_query_hca_vport_pkey); 647 648 int mlx5_query_hca_vport_context(struct mlx5_core_dev *dev, 649 u8 other_vport, u8 port_num, 650 u16 vf_num, 651 struct mlx5_hca_vport_context *rep) 652 { 653 int out_sz = MLX5_ST_SZ_BYTES(query_hca_vport_context_out); 654 int in[MLX5_ST_SZ_DW(query_hca_vport_context_in)] = {}; 655 int is_group_manager; 656 void *out; 657 void *ctx; 658 int err; 659 660 is_group_manager = MLX5_CAP_GEN(dev, vport_group_manager); 661 662 out = kvzalloc(out_sz, GFP_KERNEL); 663 if (!out) 664 return -ENOMEM; 665 666 MLX5_SET(query_hca_vport_context_in, in, opcode, MLX5_CMD_OP_QUERY_HCA_VPORT_CONTEXT); 667 668 if (other_vport) { 669 if (is_group_manager) { 670 MLX5_SET(query_hca_vport_context_in, in, other_vport, 1); 671 MLX5_SET(query_hca_vport_context_in, in, vport_number, vf_num); 672 } else { 673 err = -EPERM; 674 goto ex; 675 } 676 } 677 678 if (MLX5_CAP_GEN(dev, num_ports) == 2) 679 MLX5_SET(query_hca_vport_context_in, in, port_num, port_num); 680 681 err = mlx5_cmd_exec_inout(dev, query_hca_vport_context, in, out); 682 if (err) 683 goto ex; 684 685 ctx = MLX5_ADDR_OF(query_hca_vport_context_out, out, hca_vport_context); 686 rep->field_select = MLX5_GET_PR(hca_vport_context, ctx, field_select); 687 rep->sm_virt_aware = MLX5_GET_PR(hca_vport_context, ctx, sm_virt_aware); 688 rep->has_smi = MLX5_GET_PR(hca_vport_context, ctx, has_smi); 689 rep->has_raw = MLX5_GET_PR(hca_vport_context, ctx, has_raw); 690 rep->policy = MLX5_GET_PR(hca_vport_context, ctx, vport_state_policy); 691 rep->phys_state = MLX5_GET_PR(hca_vport_context, ctx, 692 port_physical_state); 693 rep->vport_state = MLX5_GET_PR(hca_vport_context, ctx, vport_state); 694 rep->port_physical_state = MLX5_GET_PR(hca_vport_context, ctx, 695 port_physical_state); 696 rep->port_guid = MLX5_GET64_PR(hca_vport_context, ctx, port_guid); 697 rep->node_guid = MLX5_GET64_PR(hca_vport_context, ctx, node_guid); 698 rep->cap_mask1 = MLX5_GET_PR(hca_vport_context, ctx, cap_mask1); 699 rep->cap_mask1_perm = MLX5_GET_PR(hca_vport_context, ctx, 700 cap_mask1_field_select); 701 rep->cap_mask2 = MLX5_GET_PR(hca_vport_context, ctx, cap_mask2); 702 rep->cap_mask2_perm = MLX5_GET_PR(hca_vport_context, ctx, 703 cap_mask2_field_select); 704 rep->lid = MLX5_GET_PR(hca_vport_context, ctx, lid); 705 rep->init_type_reply = MLX5_GET_PR(hca_vport_context, ctx, 706 init_type_reply); 707 rep->lmc = MLX5_GET_PR(hca_vport_context, ctx, lmc); 708 rep->subnet_timeout = MLX5_GET_PR(hca_vport_context, ctx, 709 subnet_timeout); 710 rep->sm_lid = MLX5_GET_PR(hca_vport_context, ctx, sm_lid); 711 rep->sm_sl = MLX5_GET_PR(hca_vport_context, ctx, sm_sl); 712 rep->qkey_violation_counter = MLX5_GET_PR(hca_vport_context, ctx, 713 qkey_violation_counter); 714 rep->pkey_violation_counter = MLX5_GET_PR(hca_vport_context, ctx, 715 pkey_violation_counter); 716 rep->grh_required = MLX5_GET_PR(hca_vport_context, ctx, grh_required); 717 rep->sys_image_guid = MLX5_GET64_PR(hca_vport_context, ctx, 718 system_image_guid); 719 720 ex: 721 kvfree(out); 722 return err; 723 } 724 EXPORT_SYMBOL_GPL(mlx5_query_hca_vport_context); 725 726 int mlx5_query_hca_vport_system_image_guid(struct mlx5_core_dev *dev, 727 u64 *sys_image_guid) 728 { 729 struct mlx5_hca_vport_context *rep; 730 int err; 731 732 rep = kvzalloc(sizeof(*rep), GFP_KERNEL); 733 if (!rep) 734 return -ENOMEM; 735 736 err = mlx5_query_hca_vport_context(dev, 0, 1, 0, rep); 737 if (!err) 738 *sys_image_guid = rep->sys_image_guid; 739 740 kvfree(rep); 741 return err; 742 } 743 EXPORT_SYMBOL_GPL(mlx5_query_hca_vport_system_image_guid); 744 745 int mlx5_query_hca_vport_node_guid(struct mlx5_core_dev *dev, 746 u64 *node_guid) 747 { 748 struct mlx5_hca_vport_context *rep; 749 int err; 750 751 rep = kvzalloc(sizeof(*rep), GFP_KERNEL); 752 if (!rep) 753 return -ENOMEM; 754 755 err = mlx5_query_hca_vport_context(dev, 0, 1, 0, rep); 756 if (!err) 757 *node_guid = rep->node_guid; 758 759 kvfree(rep); 760 return err; 761 } 762 EXPORT_SYMBOL_GPL(mlx5_query_hca_vport_node_guid); 763 764 int mlx5_query_nic_vport_promisc(struct mlx5_core_dev *mdev, 765 u16 vport, 766 int *promisc_uc, 767 int *promisc_mc, 768 int *promisc_all) 769 { 770 u32 *out; 771 int outlen = MLX5_ST_SZ_BYTES(query_nic_vport_context_out); 772 int err; 773 774 out = kvzalloc(outlen, GFP_KERNEL); 775 if (!out) 776 return -ENOMEM; 777 778 err = mlx5_query_nic_vport_context(mdev, vport, out); 779 if (err) 780 goto out; 781 782 *promisc_uc = MLX5_GET(query_nic_vport_context_out, out, 783 nic_vport_context.promisc_uc); 784 *promisc_mc = MLX5_GET(query_nic_vport_context_out, out, 785 nic_vport_context.promisc_mc); 786 *promisc_all = MLX5_GET(query_nic_vport_context_out, out, 787 nic_vport_context.promisc_all); 788 789 out: 790 kvfree(out); 791 return err; 792 } 793 EXPORT_SYMBOL_GPL(mlx5_query_nic_vport_promisc); 794 795 int mlx5_modify_nic_vport_promisc(struct mlx5_core_dev *mdev, 796 int promisc_uc, 797 int promisc_mc, 798 int promisc_all) 799 { 800 void *in; 801 int inlen = MLX5_ST_SZ_BYTES(modify_nic_vport_context_in); 802 int err; 803 804 in = kvzalloc(inlen, GFP_KERNEL); 805 if (!in) 806 return -ENOMEM; 807 808 MLX5_SET(modify_nic_vport_context_in, in, field_select.promisc, 1); 809 MLX5_SET(modify_nic_vport_context_in, in, 810 nic_vport_context.promisc_uc, promisc_uc); 811 MLX5_SET(modify_nic_vport_context_in, in, 812 nic_vport_context.promisc_mc, promisc_mc); 813 MLX5_SET(modify_nic_vport_context_in, in, 814 nic_vport_context.promisc_all, promisc_all); 815 MLX5_SET(modify_nic_vport_context_in, in, opcode, 816 MLX5_CMD_OP_MODIFY_NIC_VPORT_CONTEXT); 817 818 err = mlx5_cmd_exec_in(mdev, modify_nic_vport_context, in); 819 820 kvfree(in); 821 822 return err; 823 } 824 EXPORT_SYMBOL_GPL(mlx5_modify_nic_vport_promisc); 825 826 enum { 827 UC_LOCAL_LB, 828 MC_LOCAL_LB 829 }; 830 831 int mlx5_nic_vport_update_local_lb(struct mlx5_core_dev *mdev, bool enable) 832 { 833 int inlen = MLX5_ST_SZ_BYTES(modify_nic_vport_context_in); 834 void *in; 835 int err; 836 837 if (!MLX5_CAP_GEN(mdev, disable_local_lb_mc) && 838 !MLX5_CAP_GEN(mdev, disable_local_lb_uc)) 839 return 0; 840 841 in = kvzalloc(inlen, GFP_KERNEL); 842 if (!in) 843 return -ENOMEM; 844 845 MLX5_SET(modify_nic_vport_context_in, in, 846 nic_vport_context.disable_mc_local_lb, !enable); 847 MLX5_SET(modify_nic_vport_context_in, in, 848 nic_vport_context.disable_uc_local_lb, !enable); 849 850 if (MLX5_CAP_GEN(mdev, disable_local_lb_mc)) 851 MLX5_SET(modify_nic_vport_context_in, in, 852 field_select.disable_mc_local_lb, 1); 853 854 if (MLX5_CAP_GEN(mdev, disable_local_lb_uc)) 855 MLX5_SET(modify_nic_vport_context_in, in, 856 field_select.disable_uc_local_lb, 1); 857 MLX5_SET(modify_nic_vport_context_in, in, opcode, 858 MLX5_CMD_OP_MODIFY_NIC_VPORT_CONTEXT); 859 860 err = mlx5_cmd_exec_in(mdev, modify_nic_vport_context, in); 861 862 if (!err) 863 mlx5_core_dbg(mdev, "%s local_lb\n", 864 enable ? "enable" : "disable"); 865 866 kvfree(in); 867 return err; 868 } 869 EXPORT_SYMBOL_GPL(mlx5_nic_vport_update_local_lb); 870 871 int mlx5_nic_vport_query_local_lb(struct mlx5_core_dev *mdev, bool *status) 872 { 873 int outlen = MLX5_ST_SZ_BYTES(query_nic_vport_context_out); 874 u32 *out; 875 int value; 876 int err; 877 878 out = kvzalloc(outlen, GFP_KERNEL); 879 if (!out) 880 return -ENOMEM; 881 882 err = mlx5_query_nic_vport_context(mdev, 0, out); 883 if (err) 884 goto out; 885 886 value = MLX5_GET(query_nic_vport_context_out, out, 887 nic_vport_context.disable_mc_local_lb) << MC_LOCAL_LB; 888 889 value |= MLX5_GET(query_nic_vport_context_out, out, 890 nic_vport_context.disable_uc_local_lb) << UC_LOCAL_LB; 891 892 *status = !value; 893 894 out: 895 kvfree(out); 896 return err; 897 } 898 EXPORT_SYMBOL_GPL(mlx5_nic_vport_query_local_lb); 899 900 enum mlx5_vport_roce_state { 901 MLX5_VPORT_ROCE_DISABLED = 0, 902 MLX5_VPORT_ROCE_ENABLED = 1, 903 }; 904 905 static int mlx5_nic_vport_update_roce_state(struct mlx5_core_dev *mdev, 906 enum mlx5_vport_roce_state state) 907 { 908 void *in; 909 int inlen = MLX5_ST_SZ_BYTES(modify_nic_vport_context_in); 910 int err; 911 912 in = kvzalloc(inlen, GFP_KERNEL); 913 if (!in) 914 return -ENOMEM; 915 916 MLX5_SET(modify_nic_vport_context_in, in, field_select.roce_en, 1); 917 MLX5_SET(modify_nic_vport_context_in, in, nic_vport_context.roce_en, 918 state); 919 MLX5_SET(modify_nic_vport_context_in, in, opcode, 920 MLX5_CMD_OP_MODIFY_NIC_VPORT_CONTEXT); 921 922 err = mlx5_cmd_exec_in(mdev, modify_nic_vport_context, in); 923 924 kvfree(in); 925 926 return err; 927 } 928 929 int mlx5_nic_vport_enable_roce(struct mlx5_core_dev *mdev) 930 { 931 int err = 0; 932 933 mutex_lock(&mlx5_roce_en_lock); 934 if (!mdev->roce.roce_en) 935 err = mlx5_nic_vport_update_roce_state(mdev, MLX5_VPORT_ROCE_ENABLED); 936 937 if (!err) 938 mdev->roce.roce_en++; 939 mutex_unlock(&mlx5_roce_en_lock); 940 941 return err; 942 } 943 EXPORT_SYMBOL_GPL(mlx5_nic_vport_enable_roce); 944 945 int mlx5_nic_vport_disable_roce(struct mlx5_core_dev *mdev) 946 { 947 int err = 0; 948 949 mutex_lock(&mlx5_roce_en_lock); 950 if (mdev->roce.roce_en) { 951 mdev->roce.roce_en--; 952 if (mdev->roce.roce_en == 0) 953 err = mlx5_nic_vport_update_roce_state(mdev, MLX5_VPORT_ROCE_DISABLED); 954 955 if (err) 956 mdev->roce.roce_en++; 957 } 958 mutex_unlock(&mlx5_roce_en_lock); 959 return err; 960 } 961 EXPORT_SYMBOL(mlx5_nic_vport_disable_roce); 962 963 int mlx5_core_query_vport_counter(struct mlx5_core_dev *dev, u8 other_vport, 964 int vf, u8 port_num, void *out) 965 { 966 int in_sz = MLX5_ST_SZ_BYTES(query_vport_counter_in); 967 int is_group_manager; 968 void *in; 969 int err; 970 971 is_group_manager = MLX5_CAP_GEN(dev, vport_group_manager); 972 in = kvzalloc(in_sz, GFP_KERNEL); 973 if (!in) { 974 err = -ENOMEM; 975 return err; 976 } 977 978 MLX5_SET(query_vport_counter_in, in, opcode, 979 MLX5_CMD_OP_QUERY_VPORT_COUNTER); 980 if (other_vport) { 981 if (is_group_manager) { 982 MLX5_SET(query_vport_counter_in, in, other_vport, 1); 983 MLX5_SET(query_vport_counter_in, in, vport_number, vf + 1); 984 } else { 985 err = -EPERM; 986 goto free; 987 } 988 } 989 if (MLX5_CAP_GEN(dev, num_ports) == 2) 990 MLX5_SET(query_vport_counter_in, in, port_num, port_num); 991 992 err = mlx5_cmd_exec_inout(dev, query_vport_counter, in, out); 993 free: 994 kvfree(in); 995 return err; 996 } 997 EXPORT_SYMBOL_GPL(mlx5_core_query_vport_counter); 998 999 int mlx5_query_vport_down_stats(struct mlx5_core_dev *mdev, u16 vport, 1000 u8 other_vport, u64 *rx_discard_vport_down, 1001 u64 *tx_discard_vport_down) 1002 { 1003 u32 out[MLX5_ST_SZ_DW(query_vnic_env_out)] = {}; 1004 u32 in[MLX5_ST_SZ_DW(query_vnic_env_in)] = {}; 1005 int err; 1006 1007 MLX5_SET(query_vnic_env_in, in, opcode, 1008 MLX5_CMD_OP_QUERY_VNIC_ENV); 1009 MLX5_SET(query_vnic_env_in, in, op_mod, 0); 1010 MLX5_SET(query_vnic_env_in, in, vport_number, vport); 1011 MLX5_SET(query_vnic_env_in, in, other_vport, other_vport); 1012 1013 err = mlx5_cmd_exec_inout(mdev, query_vnic_env, in, out); 1014 if (err) 1015 return err; 1016 1017 *rx_discard_vport_down = MLX5_GET64(query_vnic_env_out, out, 1018 vport_env.receive_discard_vport_down); 1019 *tx_discard_vport_down = MLX5_GET64(query_vnic_env_out, out, 1020 vport_env.transmit_discard_vport_down); 1021 return 0; 1022 } 1023 1024 int mlx5_core_modify_hca_vport_context(struct mlx5_core_dev *dev, 1025 u8 other_vport, u8 port_num, 1026 int vf, 1027 struct mlx5_hca_vport_context *req) 1028 { 1029 int in_sz = MLX5_ST_SZ_BYTES(modify_hca_vport_context_in); 1030 int is_group_manager; 1031 void *ctx; 1032 void *in; 1033 int err; 1034 1035 mlx5_core_dbg(dev, "vf %d\n", vf); 1036 is_group_manager = MLX5_CAP_GEN(dev, vport_group_manager); 1037 in = kvzalloc(in_sz, GFP_KERNEL); 1038 if (!in) 1039 return -ENOMEM; 1040 1041 MLX5_SET(modify_hca_vport_context_in, in, opcode, MLX5_CMD_OP_MODIFY_HCA_VPORT_CONTEXT); 1042 if (other_vport) { 1043 if (is_group_manager) { 1044 MLX5_SET(modify_hca_vport_context_in, in, other_vport, 1); 1045 MLX5_SET(modify_hca_vport_context_in, in, vport_number, vf); 1046 } else { 1047 err = -EPERM; 1048 goto ex; 1049 } 1050 } 1051 1052 if (MLX5_CAP_GEN(dev, num_ports) > 1) 1053 MLX5_SET(modify_hca_vport_context_in, in, port_num, port_num); 1054 1055 ctx = MLX5_ADDR_OF(modify_hca_vport_context_in, in, hca_vport_context); 1056 MLX5_SET(hca_vport_context, ctx, field_select, req->field_select); 1057 if (req->field_select & MLX5_HCA_VPORT_SEL_STATE_POLICY) 1058 MLX5_SET(hca_vport_context, ctx, vport_state_policy, 1059 req->policy); 1060 if (req->field_select & MLX5_HCA_VPORT_SEL_PORT_GUID) 1061 MLX5_SET64(hca_vport_context, ctx, port_guid, req->port_guid); 1062 if (req->field_select & MLX5_HCA_VPORT_SEL_NODE_GUID) 1063 MLX5_SET64(hca_vport_context, ctx, node_guid, req->node_guid); 1064 MLX5_SET(hca_vport_context, ctx, cap_mask1, req->cap_mask1); 1065 MLX5_SET(hca_vport_context, ctx, cap_mask1_field_select, 1066 req->cap_mask1_perm); 1067 err = mlx5_cmd_exec_in(dev, modify_hca_vport_context, in); 1068 ex: 1069 kvfree(in); 1070 return err; 1071 } 1072 EXPORT_SYMBOL_GPL(mlx5_core_modify_hca_vport_context); 1073 1074 int mlx5_nic_vport_affiliate_multiport(struct mlx5_core_dev *master_mdev, 1075 struct mlx5_core_dev *port_mdev) 1076 { 1077 int inlen = MLX5_ST_SZ_BYTES(modify_nic_vport_context_in); 1078 void *in; 1079 int err; 1080 1081 in = kvzalloc(inlen, GFP_KERNEL); 1082 if (!in) 1083 return -ENOMEM; 1084 1085 err = mlx5_nic_vport_enable_roce(port_mdev); 1086 if (err) 1087 goto free; 1088 1089 MLX5_SET(modify_nic_vport_context_in, in, field_select.affiliation, 1); 1090 if (MLX5_CAP_GEN_2(master_mdev, sw_vhca_id_valid)) { 1091 MLX5_SET(modify_nic_vport_context_in, in, 1092 nic_vport_context.vhca_id_type, VHCA_ID_TYPE_SW); 1093 MLX5_SET(modify_nic_vport_context_in, in, 1094 nic_vport_context.affiliated_vhca_id, 1095 MLX5_CAP_GEN_2(master_mdev, sw_vhca_id)); 1096 } else { 1097 MLX5_SET(modify_nic_vport_context_in, in, 1098 nic_vport_context.affiliated_vhca_id, 1099 MLX5_CAP_GEN(master_mdev, vhca_id)); 1100 } 1101 MLX5_SET(modify_nic_vport_context_in, in, 1102 nic_vport_context.affiliation_criteria, 1103 MLX5_CAP_GEN(port_mdev, affiliate_nic_vport_criteria)); 1104 MLX5_SET(modify_nic_vport_context_in, in, opcode, 1105 MLX5_CMD_OP_MODIFY_NIC_VPORT_CONTEXT); 1106 1107 err = mlx5_cmd_exec_in(port_mdev, modify_nic_vport_context, in); 1108 if (err) 1109 mlx5_nic_vport_disable_roce(port_mdev); 1110 1111 free: 1112 kvfree(in); 1113 return err; 1114 } 1115 EXPORT_SYMBOL_GPL(mlx5_nic_vport_affiliate_multiport); 1116 1117 int mlx5_nic_vport_unaffiliate_multiport(struct mlx5_core_dev *port_mdev) 1118 { 1119 int inlen = MLX5_ST_SZ_BYTES(modify_nic_vport_context_in); 1120 void *in; 1121 int err; 1122 1123 in = kvzalloc(inlen, GFP_KERNEL); 1124 if (!in) 1125 return -ENOMEM; 1126 1127 MLX5_SET(modify_nic_vport_context_in, in, field_select.affiliation, 1); 1128 MLX5_SET(modify_nic_vport_context_in, in, 1129 nic_vport_context.affiliated_vhca_id, 0); 1130 MLX5_SET(modify_nic_vport_context_in, in, 1131 nic_vport_context.affiliation_criteria, 0); 1132 MLX5_SET(modify_nic_vport_context_in, in, opcode, 1133 MLX5_CMD_OP_MODIFY_NIC_VPORT_CONTEXT); 1134 1135 err = mlx5_cmd_exec_in(port_mdev, modify_nic_vport_context, in); 1136 if (!err) 1137 mlx5_nic_vport_disable_roce(port_mdev); 1138 1139 kvfree(in); 1140 return err; 1141 } 1142 EXPORT_SYMBOL_GPL(mlx5_nic_vport_unaffiliate_multiport); 1143 1144 u64 mlx5_query_nic_system_image_guid(struct mlx5_core_dev *mdev) 1145 { 1146 int port_type_cap = MLX5_CAP_GEN(mdev, port_type); 1147 u64 tmp; 1148 int err; 1149 1150 if (mdev->sys_image_guid) 1151 return mdev->sys_image_guid; 1152 1153 if (port_type_cap == MLX5_CAP_PORT_TYPE_ETH) 1154 err = mlx5_query_nic_vport_system_image_guid(mdev, &tmp); 1155 else 1156 err = mlx5_query_hca_vport_system_image_guid(mdev, &tmp); 1157 1158 mdev->sys_image_guid = err ? 0 : tmp; 1159 1160 return mdev->sys_image_guid; 1161 } 1162 EXPORT_SYMBOL_GPL(mlx5_query_nic_system_image_guid); 1163 1164 int mlx5_vport_get_other_func_cap(struct mlx5_core_dev *dev, u16 vport, void *out, 1165 u16 opmod) 1166 { 1167 bool ec_vf_func = mlx5_core_is_ec_vf_vport(dev, vport); 1168 u8 in[MLX5_ST_SZ_BYTES(query_hca_cap_in)] = {}; 1169 1170 opmod = (opmod << 1) | (HCA_CAP_OPMOD_GET_MAX & 0x01); 1171 MLX5_SET(query_hca_cap_in, in, opcode, MLX5_CMD_OP_QUERY_HCA_CAP); 1172 MLX5_SET(query_hca_cap_in, in, op_mod, opmod); 1173 MLX5_SET(query_hca_cap_in, in, function_id, mlx5_vport_to_func_id(dev, vport, ec_vf_func)); 1174 MLX5_SET(query_hca_cap_in, in, other_function, true); 1175 MLX5_SET(query_hca_cap_in, in, ec_vf_function, ec_vf_func); 1176 return mlx5_cmd_exec_inout(dev, query_hca_cap, in, out); 1177 } 1178 EXPORT_SYMBOL_GPL(mlx5_vport_get_other_func_cap); 1179 1180 int mlx5_vport_set_other_func_cap(struct mlx5_core_dev *dev, const void *hca_cap, 1181 u16 vport, u16 opmod) 1182 { 1183 bool ec_vf_func = mlx5_core_is_ec_vf_vport(dev, vport); 1184 int set_sz = MLX5_ST_SZ_BYTES(set_hca_cap_in); 1185 void *set_hca_cap; 1186 void *set_ctx; 1187 int ret; 1188 1189 set_ctx = kzalloc(set_sz, GFP_KERNEL); 1190 if (!set_ctx) 1191 return -ENOMEM; 1192 1193 MLX5_SET(set_hca_cap_in, set_ctx, opcode, MLX5_CMD_OP_SET_HCA_CAP); 1194 MLX5_SET(set_hca_cap_in, set_ctx, op_mod, opmod << 1); 1195 set_hca_cap = MLX5_ADDR_OF(set_hca_cap_in, set_ctx, capability); 1196 memcpy(set_hca_cap, hca_cap, MLX5_ST_SZ_BYTES(cmd_hca_cap)); 1197 MLX5_SET(set_hca_cap_in, set_ctx, function_id, 1198 mlx5_vport_to_func_id(dev, vport, ec_vf_func)); 1199 MLX5_SET(set_hca_cap_in, set_ctx, other_function, true); 1200 MLX5_SET(set_hca_cap_in, set_ctx, ec_vf_function, ec_vf_func); 1201 ret = mlx5_cmd_exec_in(dev, set_hca_cap, set_ctx); 1202 1203 kfree(set_ctx); 1204 return ret; 1205 } 1206