linux/drivers/net/ethernet/mellanox/mlx5/core/steering/dr_cmd.c
<<
>>
Prefs
   1// SPDX-License-Identifier: GPL-2.0 OR Linux-OpenIB
   2/* Copyright (c) 2019 Mellanox Technologies. */
   3
   4#include "dr_types.h"
   5
   6int mlx5dr_cmd_query_esw_vport_context(struct mlx5_core_dev *mdev,
   7                                       bool other_vport,
   8                                       u16 vport_number,
   9                                       u64 *icm_address_rx,
  10                                       u64 *icm_address_tx)
  11{
  12        u32 out[MLX5_ST_SZ_DW(query_esw_vport_context_out)] = {};
  13        u32 in[MLX5_ST_SZ_DW(query_esw_vport_context_in)] = {};
  14        int err;
  15
  16        MLX5_SET(query_esw_vport_context_in, in, opcode,
  17                 MLX5_CMD_OP_QUERY_ESW_VPORT_CONTEXT);
  18        MLX5_SET(query_esw_vport_context_in, in, other_vport, other_vport);
  19        MLX5_SET(query_esw_vport_context_in, in, vport_number, vport_number);
  20
  21        err = mlx5_cmd_exec(mdev, in, sizeof(in), out, sizeof(out));
  22        if (err)
  23                return err;
  24
  25        *icm_address_rx =
  26                MLX5_GET64(query_esw_vport_context_out, out,
  27                           esw_vport_context.sw_steering_vport_icm_address_rx);
  28        *icm_address_tx =
  29                MLX5_GET64(query_esw_vport_context_out, out,
  30                           esw_vport_context.sw_steering_vport_icm_address_tx);
  31        return 0;
  32}
  33
  34int mlx5dr_cmd_query_gvmi(struct mlx5_core_dev *mdev, bool other_vport,
  35                          u16 vport_number, u16 *gvmi)
  36{
  37        u32 in[MLX5_ST_SZ_DW(query_hca_cap_in)] = {};
  38        int out_size;
  39        void *out;
  40        int err;
  41
  42        out_size = MLX5_ST_SZ_BYTES(query_hca_cap_out);
  43        out = kzalloc(out_size, GFP_KERNEL);
  44        if (!out)
  45                return -ENOMEM;
  46
  47        MLX5_SET(query_hca_cap_in, in, opcode, MLX5_CMD_OP_QUERY_HCA_CAP);
  48        MLX5_SET(query_hca_cap_in, in, other_function, other_vport);
  49        MLX5_SET(query_hca_cap_in, in, function_id, vport_number);
  50        MLX5_SET(query_hca_cap_in, in, op_mod,
  51                 MLX5_SET_HCA_CAP_OP_MOD_GENERAL_DEVICE << 1 |
  52                 HCA_CAP_OPMOD_GET_CUR);
  53
  54        err = mlx5_cmd_exec(mdev, in, sizeof(in), out, out_size);
  55        if (err) {
  56                kfree(out);
  57                return err;
  58        }
  59
  60        *gvmi = MLX5_GET(query_hca_cap_out, out, capability.cmd_hca_cap.vhca_id);
  61
  62        kfree(out);
  63        return 0;
  64}
  65
  66int mlx5dr_cmd_query_esw_caps(struct mlx5_core_dev *mdev,
  67                              struct mlx5dr_esw_caps *caps)
  68{
  69        caps->drop_icm_address_rx =
  70                MLX5_CAP64_ESW_FLOWTABLE(mdev,
  71                                         sw_steering_fdb_action_drop_icm_address_rx);
  72        caps->drop_icm_address_tx =
  73                MLX5_CAP64_ESW_FLOWTABLE(mdev,
  74                                         sw_steering_fdb_action_drop_icm_address_tx);
  75        caps->uplink_icm_address_rx =
  76                MLX5_CAP64_ESW_FLOWTABLE(mdev,
  77                                         sw_steering_uplink_icm_address_rx);
  78        caps->uplink_icm_address_tx =
  79                MLX5_CAP64_ESW_FLOWTABLE(mdev,
  80                                         sw_steering_uplink_icm_address_tx);
  81        caps->sw_owner =
  82                MLX5_CAP_ESW_FLOWTABLE_FDB(mdev,
  83                                           sw_owner);
  84
  85        return 0;
  86}
  87
  88int mlx5dr_cmd_query_device(struct mlx5_core_dev *mdev,
  89                            struct mlx5dr_cmd_caps *caps)
  90{
  91        caps->prio_tag_required = MLX5_CAP_GEN(mdev, prio_tag_required);
  92        caps->eswitch_manager   = MLX5_CAP_GEN(mdev, eswitch_manager);
  93        caps->gvmi              = MLX5_CAP_GEN(mdev, vhca_id);
  94        caps->flex_protocols    = MLX5_CAP_GEN(mdev, flex_parser_protocols);
  95
  96        if (mlx5dr_matcher_supp_flex_parser_icmp_v4(caps)) {
  97                caps->flex_parser_id_icmp_dw0 = MLX5_CAP_GEN(mdev, flex_parser_id_icmp_dw0);
  98                caps->flex_parser_id_icmp_dw1 = MLX5_CAP_GEN(mdev, flex_parser_id_icmp_dw1);
  99        }
 100
 101        if (mlx5dr_matcher_supp_flex_parser_icmp_v6(caps)) {
 102                caps->flex_parser_id_icmpv6_dw0 =
 103                        MLX5_CAP_GEN(mdev, flex_parser_id_icmpv6_dw0);
 104                caps->flex_parser_id_icmpv6_dw1 =
 105                        MLX5_CAP_GEN(mdev, flex_parser_id_icmpv6_dw1);
 106        }
 107
 108        caps->nic_rx_drop_address =
 109                MLX5_CAP64_FLOWTABLE(mdev, sw_steering_nic_rx_action_drop_icm_address);
 110        caps->nic_tx_drop_address =
 111                MLX5_CAP64_FLOWTABLE(mdev, sw_steering_nic_tx_action_drop_icm_address);
 112        caps->nic_tx_allow_address =
 113                MLX5_CAP64_FLOWTABLE(mdev, sw_steering_nic_tx_action_allow_icm_address);
 114
 115        caps->rx_sw_owner = MLX5_CAP_FLOWTABLE_NIC_RX(mdev, sw_owner);
 116        caps->max_ft_level = MLX5_CAP_FLOWTABLE_NIC_RX(mdev, max_ft_level);
 117
 118        caps->tx_sw_owner = MLX5_CAP_FLOWTABLE_NIC_TX(mdev, sw_owner);
 119
 120        caps->log_icm_size = MLX5_CAP_DEV_MEM(mdev, log_steering_sw_icm_size);
 121        caps->hdr_modify_icm_addr =
 122                MLX5_CAP64_DEV_MEM(mdev, header_modify_sw_icm_start_address);
 123
 124        caps->roce_min_src_udp = MLX5_CAP_ROCE(mdev, r_roce_min_src_udp_port);
 125
 126        return 0;
 127}
 128
 129int mlx5dr_cmd_query_flow_table(struct mlx5_core_dev *dev,
 130                                enum fs_flow_table_type type,
 131                                u32 table_id,
 132                                struct mlx5dr_cmd_query_flow_table_details *output)
 133{
 134        u32 out[MLX5_ST_SZ_DW(query_flow_table_out)] = {};
 135        u32 in[MLX5_ST_SZ_DW(query_flow_table_in)] = {};
 136        int err;
 137
 138        MLX5_SET(query_flow_table_in, in, opcode,
 139                 MLX5_CMD_OP_QUERY_FLOW_TABLE);
 140
 141        MLX5_SET(query_flow_table_in, in, table_type, type);
 142        MLX5_SET(query_flow_table_in, in, table_id, table_id);
 143
 144        err = mlx5_cmd_exec(dev, in, sizeof(in), out, sizeof(out));
 145        if (err)
 146                return err;
 147
 148        output->status = MLX5_GET(query_flow_table_out, out, status);
 149        output->level = MLX5_GET(query_flow_table_out, out, flow_table_context.level);
 150
 151        output->sw_owner_icm_root_1 = MLX5_GET64(query_flow_table_out, out,
 152                                                 flow_table_context.sw_owner_icm_root_1);
 153        output->sw_owner_icm_root_0 = MLX5_GET64(query_flow_table_out, out,
 154                                                 flow_table_context.sw_owner_icm_root_0);
 155
 156        return 0;
 157}
 158
 159int mlx5dr_cmd_sync_steering(struct mlx5_core_dev *mdev)
 160{
 161        u32 out[MLX5_ST_SZ_DW(sync_steering_out)] = {};
 162        u32 in[MLX5_ST_SZ_DW(sync_steering_in)] = {};
 163
 164        MLX5_SET(sync_steering_in, in, opcode, MLX5_CMD_OP_SYNC_STEERING);
 165
 166        return mlx5_cmd_exec(mdev, in, sizeof(in), out, sizeof(out));
 167}
 168
 169int mlx5dr_cmd_set_fte_modify_and_vport(struct mlx5_core_dev *mdev,
 170                                        u32 table_type,
 171                                        u32 table_id,
 172                                        u32 group_id,
 173                                        u32 modify_header_id,
 174                                        u32 vport_id)
 175{
 176        u32 out[MLX5_ST_SZ_DW(set_fte_out)] = {};
 177        void *in_flow_context;
 178        unsigned int inlen;
 179        void *in_dests;
 180        u32 *in;
 181        int err;
 182
 183        inlen = MLX5_ST_SZ_BYTES(set_fte_in) +
 184                1 * MLX5_ST_SZ_BYTES(dest_format_struct); /* One destination only */
 185
 186        in = kvzalloc(inlen, GFP_KERNEL);
 187        if (!in)
 188                return -ENOMEM;
 189
 190        MLX5_SET(set_fte_in, in, opcode, MLX5_CMD_OP_SET_FLOW_TABLE_ENTRY);
 191        MLX5_SET(set_fte_in, in, table_type, table_type);
 192        MLX5_SET(set_fte_in, in, table_id, table_id);
 193
 194        in_flow_context = MLX5_ADDR_OF(set_fte_in, in, flow_context);
 195        MLX5_SET(flow_context, in_flow_context, group_id, group_id);
 196        MLX5_SET(flow_context, in_flow_context, modify_header_id, modify_header_id);
 197        MLX5_SET(flow_context, in_flow_context, destination_list_size, 1);
 198        MLX5_SET(flow_context, in_flow_context, action,
 199                 MLX5_FLOW_CONTEXT_ACTION_FWD_DEST |
 200                 MLX5_FLOW_CONTEXT_ACTION_MOD_HDR);
 201
 202        in_dests = MLX5_ADDR_OF(flow_context, in_flow_context, destination);
 203        MLX5_SET(dest_format_struct, in_dests, destination_type,
 204                 MLX5_FLOW_DESTINATION_TYPE_VPORT);
 205        MLX5_SET(dest_format_struct, in_dests, destination_id, vport_id);
 206
 207        err = mlx5_cmd_exec(mdev, in, inlen, out, sizeof(out));
 208        kvfree(in);
 209
 210        return err;
 211}
 212
 213int mlx5dr_cmd_del_flow_table_entry(struct mlx5_core_dev *mdev,
 214                                    u32 table_type,
 215                                    u32 table_id)
 216{
 217        u32 out[MLX5_ST_SZ_DW(delete_fte_out)] = {};
 218        u32 in[MLX5_ST_SZ_DW(delete_fte_in)] = {};
 219
 220        MLX5_SET(delete_fte_in, in, opcode, MLX5_CMD_OP_DELETE_FLOW_TABLE_ENTRY);
 221        MLX5_SET(delete_fte_in, in, table_type, table_type);
 222        MLX5_SET(delete_fte_in, in, table_id, table_id);
 223
 224        return mlx5_cmd_exec(mdev, in, sizeof(in), out, sizeof(out));
 225}
 226
 227int mlx5dr_cmd_alloc_modify_header(struct mlx5_core_dev *mdev,
 228                                   u32 table_type,
 229                                   u8 num_of_actions,
 230                                   u64 *actions,
 231                                   u32 *modify_header_id)
 232{
 233        u32 out[MLX5_ST_SZ_DW(alloc_modify_header_context_out)] = {};
 234        void *p_actions;
 235        u32 inlen;
 236        u32 *in;
 237        int err;
 238
 239        inlen = MLX5_ST_SZ_BYTES(alloc_modify_header_context_in) +
 240                 num_of_actions * sizeof(u64);
 241        in = kvzalloc(inlen, GFP_KERNEL);
 242        if (!in)
 243                return -ENOMEM;
 244
 245        MLX5_SET(alloc_modify_header_context_in, in, opcode,
 246                 MLX5_CMD_OP_ALLOC_MODIFY_HEADER_CONTEXT);
 247        MLX5_SET(alloc_modify_header_context_in, in, table_type, table_type);
 248        MLX5_SET(alloc_modify_header_context_in, in, num_of_actions, num_of_actions);
 249        p_actions = MLX5_ADDR_OF(alloc_modify_header_context_in, in, actions);
 250        memcpy(p_actions, actions, num_of_actions * sizeof(u64));
 251
 252        err = mlx5_cmd_exec(mdev, in, inlen, out, sizeof(out));
 253        if (err)
 254                goto out;
 255
 256        *modify_header_id = MLX5_GET(alloc_modify_header_context_out, out,
 257                                     modify_header_id);
 258out:
 259        kvfree(in);
 260        return err;
 261}
 262
 263int mlx5dr_cmd_dealloc_modify_header(struct mlx5_core_dev *mdev,
 264                                     u32 modify_header_id)
 265{
 266        u32 out[MLX5_ST_SZ_DW(dealloc_modify_header_context_out)] = {};
 267        u32 in[MLX5_ST_SZ_DW(dealloc_modify_header_context_in)] = {};
 268
 269        MLX5_SET(dealloc_modify_header_context_in, in, opcode,
 270                 MLX5_CMD_OP_DEALLOC_MODIFY_HEADER_CONTEXT);
 271        MLX5_SET(dealloc_modify_header_context_in, in, modify_header_id,
 272                 modify_header_id);
 273
 274        return mlx5_cmd_exec(mdev, in, sizeof(in), out, sizeof(out));
 275}
 276
 277int mlx5dr_cmd_create_empty_flow_group(struct mlx5_core_dev *mdev,
 278                                       u32 table_type,
 279                                       u32 table_id,
 280                                       u32 *group_id)
 281{
 282        u32 out[MLX5_ST_SZ_DW(create_flow_group_out)] = {};
 283        int inlen = MLX5_ST_SZ_BYTES(create_flow_group_in);
 284        u32 *in;
 285        int err;
 286
 287        in = kzalloc(inlen, GFP_KERNEL);
 288        if (!in)
 289                return -ENOMEM;
 290
 291        MLX5_SET(create_flow_group_in, in, opcode, MLX5_CMD_OP_CREATE_FLOW_GROUP);
 292        MLX5_SET(create_flow_group_in, in, table_type, table_type);
 293        MLX5_SET(create_flow_group_in, in, table_id, table_id);
 294
 295        err = mlx5_cmd_exec(mdev, in, inlen, out, sizeof(out));
 296        if (err)
 297                goto out;
 298
 299        *group_id = MLX5_GET(create_flow_group_out, out, group_id);
 300
 301out:
 302        kfree(in);
 303        return err;
 304}
 305
 306int mlx5dr_cmd_destroy_flow_group(struct mlx5_core_dev *mdev,
 307                                  u32 table_type,
 308                                  u32 table_id,
 309                                  u32 group_id)
 310{
 311        u32 in[MLX5_ST_SZ_DW(destroy_flow_group_in)] = {};
 312        u32 out[MLX5_ST_SZ_DW(destroy_flow_group_out)] = {};
 313
 314        MLX5_SET(create_flow_group_in, in, opcode, MLX5_CMD_OP_DESTROY_FLOW_GROUP);
 315        MLX5_SET(destroy_flow_group_in, in, table_type, table_type);
 316        MLX5_SET(destroy_flow_group_in, in, table_id, table_id);
 317        MLX5_SET(destroy_flow_group_in, in, group_id, group_id);
 318
 319        return mlx5_cmd_exec(mdev, in, sizeof(in), out, sizeof(out));
 320}
 321
 322int mlx5dr_cmd_create_flow_table(struct mlx5_core_dev *mdev,
 323                                 u32 table_type,
 324                                 u64 icm_addr_rx,
 325                                 u64 icm_addr_tx,
 326                                 u8 level,
 327                                 bool sw_owner,
 328                                 bool term_tbl,
 329                                 u64 *fdb_rx_icm_addr,
 330                                 u32 *table_id)
 331{
 332        u32 out[MLX5_ST_SZ_DW(create_flow_table_out)] = {};
 333        u32 in[MLX5_ST_SZ_DW(create_flow_table_in)] = {};
 334        void *ft_mdev;
 335        int err;
 336
 337        MLX5_SET(create_flow_table_in, in, opcode, MLX5_CMD_OP_CREATE_FLOW_TABLE);
 338        MLX5_SET(create_flow_table_in, in, table_type, table_type);
 339
 340        ft_mdev = MLX5_ADDR_OF(create_flow_table_in, in, flow_table_context);
 341        MLX5_SET(flow_table_context, ft_mdev, termination_table, term_tbl);
 342        MLX5_SET(flow_table_context, ft_mdev, sw_owner, sw_owner);
 343        MLX5_SET(flow_table_context, ft_mdev, level, level);
 344
 345        if (sw_owner) {
 346                /* icm_addr_0 used for FDB RX / NIC TX / NIC_RX
 347                 * icm_addr_1 used for FDB TX
 348                 */
 349                if (table_type == MLX5_FLOW_TABLE_TYPE_NIC_RX) {
 350                        MLX5_SET64(flow_table_context, ft_mdev,
 351                                   sw_owner_icm_root_0, icm_addr_rx);
 352                } else if (table_type == MLX5_FLOW_TABLE_TYPE_NIC_TX) {
 353                        MLX5_SET64(flow_table_context, ft_mdev,
 354                                   sw_owner_icm_root_0, icm_addr_tx);
 355                } else if (table_type == MLX5_FLOW_TABLE_TYPE_FDB) {
 356                        MLX5_SET64(flow_table_context, ft_mdev,
 357                                   sw_owner_icm_root_0, icm_addr_rx);
 358                        MLX5_SET64(flow_table_context, ft_mdev,
 359                                   sw_owner_icm_root_1, icm_addr_tx);
 360                }
 361        }
 362
 363        err = mlx5_cmd_exec(mdev, in, sizeof(in), out, sizeof(out));
 364        if (err)
 365                return err;
 366
 367        *table_id = MLX5_GET(create_flow_table_out, out, table_id);
 368        if (!sw_owner && table_type == MLX5_FLOW_TABLE_TYPE_FDB)
 369                *fdb_rx_icm_addr =
 370                (u64)MLX5_GET(create_flow_table_out, out, icm_address_31_0) |
 371                (u64)MLX5_GET(create_flow_table_out, out, icm_address_39_32) << 32 |
 372                (u64)MLX5_GET(create_flow_table_out, out, icm_address_63_40) << 40;
 373
 374        return 0;
 375}
 376
 377int mlx5dr_cmd_destroy_flow_table(struct mlx5_core_dev *mdev,
 378                                  u32 table_id,
 379                                  u32 table_type)
 380{
 381        u32 out[MLX5_ST_SZ_DW(destroy_flow_table_out)] = {};
 382        u32 in[MLX5_ST_SZ_DW(destroy_flow_table_in)] = {};
 383
 384        MLX5_SET(destroy_flow_table_in, in, opcode,
 385                 MLX5_CMD_OP_DESTROY_FLOW_TABLE);
 386        MLX5_SET(destroy_flow_table_in, in, table_type, table_type);
 387        MLX5_SET(destroy_flow_table_in, in, table_id, table_id);
 388
 389        return mlx5_cmd_exec(mdev, in, sizeof(in), out, sizeof(out));
 390}
 391
 392int mlx5dr_cmd_create_reformat_ctx(struct mlx5_core_dev *mdev,
 393                                   enum mlx5_reformat_ctx_type rt,
 394                                   size_t reformat_size,
 395                                   void *reformat_data,
 396                                   u32 *reformat_id)
 397{
 398        u32 out[MLX5_ST_SZ_DW(alloc_packet_reformat_context_out)] = {};
 399        size_t inlen, cmd_data_sz, cmd_total_sz;
 400        void *prctx;
 401        void *pdata;
 402        void *in;
 403        int err;
 404
 405        cmd_total_sz = MLX5_ST_SZ_BYTES(alloc_packet_reformat_context_in);
 406        cmd_data_sz = MLX5_FLD_SZ_BYTES(alloc_packet_reformat_context_in,
 407                                        packet_reformat_context.reformat_data);
 408        inlen = ALIGN(cmd_total_sz + reformat_size - cmd_data_sz, 4);
 409        in = kvzalloc(inlen, GFP_KERNEL);
 410        if (!in)
 411                return -ENOMEM;
 412
 413        MLX5_SET(alloc_packet_reformat_context_in, in, opcode,
 414                 MLX5_CMD_OP_ALLOC_PACKET_REFORMAT_CONTEXT);
 415
 416        prctx = MLX5_ADDR_OF(alloc_packet_reformat_context_in, in, packet_reformat_context);
 417        pdata = MLX5_ADDR_OF(packet_reformat_context_in, prctx, reformat_data);
 418
 419        MLX5_SET(packet_reformat_context_in, prctx, reformat_type, rt);
 420        MLX5_SET(packet_reformat_context_in, prctx, reformat_data_size, reformat_size);
 421        memcpy(pdata, reformat_data, reformat_size);
 422
 423        err = mlx5_cmd_exec(mdev, in, inlen, out, sizeof(out));
 424        if (err)
 425                return err;
 426
 427        *reformat_id = MLX5_GET(alloc_packet_reformat_context_out, out, packet_reformat_id);
 428        kvfree(in);
 429
 430        return err;
 431}
 432
 433void mlx5dr_cmd_destroy_reformat_ctx(struct mlx5_core_dev *mdev,
 434                                     u32 reformat_id)
 435{
 436        u32 out[MLX5_ST_SZ_DW(dealloc_packet_reformat_context_out)] = {};
 437        u32 in[MLX5_ST_SZ_DW(dealloc_packet_reformat_context_in)] = {};
 438
 439        MLX5_SET(dealloc_packet_reformat_context_in, in, opcode,
 440                 MLX5_CMD_OP_DEALLOC_PACKET_REFORMAT_CONTEXT);
 441        MLX5_SET(dealloc_packet_reformat_context_in, in, packet_reformat_id,
 442                 reformat_id);
 443
 444        mlx5_cmd_exec(mdev, in, sizeof(in), out, sizeof(out));
 445}
 446
 447int mlx5dr_cmd_query_gid(struct mlx5_core_dev *mdev, u8 vhca_port_num,
 448                         u16 index, struct mlx5dr_cmd_gid_attr *attr)
 449{
 450        u32 out[MLX5_ST_SZ_DW(query_roce_address_out)] = {};
 451        u32 in[MLX5_ST_SZ_DW(query_roce_address_in)] = {};
 452        int err;
 453
 454        MLX5_SET(query_roce_address_in, in, opcode,
 455                 MLX5_CMD_OP_QUERY_ROCE_ADDRESS);
 456
 457        MLX5_SET(query_roce_address_in, in, roce_address_index, index);
 458        MLX5_SET(query_roce_address_in, in, vhca_port_num, vhca_port_num);
 459
 460        err = mlx5_cmd_exec(mdev, in, sizeof(in), out, sizeof(out));
 461        if (err)
 462                return err;
 463
 464        memcpy(&attr->gid,
 465               MLX5_ADDR_OF(query_roce_address_out,
 466                            out, roce_address.source_l3_address),
 467               sizeof(attr->gid));
 468        memcpy(attr->mac,
 469               MLX5_ADDR_OF(query_roce_address_out, out,
 470                            roce_address.source_mac_47_32),
 471               sizeof(attr->mac));
 472
 473        if (MLX5_GET(query_roce_address_out, out,
 474                     roce_address.roce_version) == MLX5_ROCE_VERSION_2)
 475                attr->roce_ver = MLX5_ROCE_VERSION_2;
 476        else
 477                attr->roce_ver = MLX5_ROCE_VERSION_1;
 478
 479        return 0;
 480}
 481