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