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