File Index
Files and directories
Sign in
FILE

vport.c

File preview with syntax highlighting.

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