dpdk/drivers/net/iavf/iavf_vchnl.c
<<
>>
Prefs
   1/* SPDX-License-Identifier: BSD-3-Clause
   2 * Copyright(c) 2017 Intel Corporation
   3 */
   4
   5#include <stdio.h>
   6#include <errno.h>
   7#include <stdint.h>
   8#include <string.h>
   9#include <unistd.h>
  10#include <stdarg.h>
  11#include <inttypes.h>
  12#include <rte_byteorder.h>
  13#include <rte_common.h>
  14
  15#include <rte_debug.h>
  16#include <rte_atomic.h>
  17#include <rte_eal.h>
  18#include <rte_ether.h>
  19#include <rte_ethdev_driver.h>
  20#include <rte_dev.h>
  21
  22#include "iavf.h"
  23#include "iavf_rxtx.h"
  24
  25#define MAX_TRY_TIMES 200
  26#define ASQ_DELAY_MS  10
  27
  28/* Read data in admin queue to get msg from pf driver */
  29static enum iavf_status
  30iavf_read_msg_from_pf(struct iavf_adapter *adapter, uint16_t buf_len,
  31                     uint8_t *buf)
  32{
  33        struct iavf_hw *hw = IAVF_DEV_PRIVATE_TO_HW(adapter);
  34        struct iavf_info *vf = IAVF_DEV_PRIVATE_TO_VF(adapter);
  35        struct iavf_arq_event_info event;
  36        enum virtchnl_ops opcode;
  37        int ret;
  38
  39        event.buf_len = buf_len;
  40        event.msg_buf = buf;
  41        ret = iavf_clean_arq_element(hw, &event, NULL);
  42        /* Can't read any msg from adminQ */
  43        if (ret) {
  44                PMD_DRV_LOG(DEBUG, "Can't read msg from AQ");
  45                return ret;
  46        }
  47
  48        opcode = (enum virtchnl_ops)rte_le_to_cpu_32(event.desc.cookie_high);
  49        vf->cmd_retval = (enum virtchnl_status_code)rte_le_to_cpu_32(
  50                        event.desc.cookie_low);
  51
  52        PMD_DRV_LOG(DEBUG, "AQ from pf carries opcode %u, retval %d",
  53                    opcode, vf->cmd_retval);
  54
  55        if (opcode != vf->pend_cmd) {
  56                PMD_DRV_LOG(WARNING, "command mismatch, expect %u, get %u",
  57                            vf->pend_cmd, opcode);
  58                return IAVF_ERR_OPCODE_MISMATCH;
  59        }
  60
  61        return IAVF_SUCCESS;
  62}
  63
  64static int
  65iavf_execute_vf_cmd(struct iavf_adapter *adapter, struct iavf_cmd_info *args)
  66{
  67        struct iavf_hw *hw = IAVF_DEV_PRIVATE_TO_HW(adapter);
  68        struct iavf_info *vf = IAVF_DEV_PRIVATE_TO_VF(adapter);
  69        enum iavf_status ret;
  70        int err = 0;
  71        int i = 0;
  72
  73        if (_atomic_set_cmd(vf, args->ops))
  74                return -1;
  75
  76        ret = iavf_aq_send_msg_to_pf(hw, args->ops, IAVF_SUCCESS,
  77                                    args->in_args, args->in_args_size, NULL);
  78        if (ret) {
  79                PMD_DRV_LOG(ERR, "fail to send cmd %d", args->ops);
  80                _clear_cmd(vf);
  81                return err;
  82        }
  83
  84        switch (args->ops) {
  85        case VIRTCHNL_OP_RESET_VF:
  86                /*no need to wait for response */
  87                _clear_cmd(vf);
  88                break;
  89        case VIRTCHNL_OP_VERSION:
  90        case VIRTCHNL_OP_GET_VF_RESOURCES:
  91        case VIRTCHNL_OP_GET_SUPPORTED_RXDIDS:
  92                /* for init virtchnl ops, need to poll the response */
  93                do {
  94                        ret = iavf_read_msg_from_pf(adapter, args->out_size,
  95                                                   args->out_buffer);
  96                        if (ret == IAVF_SUCCESS)
  97                                break;
  98                        rte_delay_ms(ASQ_DELAY_MS);
  99                } while (i++ < MAX_TRY_TIMES);
 100                if (i >= MAX_TRY_TIMES ||
 101                    vf->cmd_retval != VIRTCHNL_STATUS_SUCCESS) {
 102                        err = -1;
 103                        PMD_DRV_LOG(ERR, "No response or return failure (%d)"
 104                                    " for cmd %d", vf->cmd_retval, args->ops);
 105                }
 106                _clear_cmd(vf);
 107                break;
 108
 109        default:
 110                /* For other virtchnl ops in running time,
 111                 * wait for the cmd done flag.
 112                 */
 113                do {
 114                        if (vf->pend_cmd == VIRTCHNL_OP_UNKNOWN)
 115                                break;
 116                        rte_delay_ms(ASQ_DELAY_MS);
 117                        /* If don't read msg or read sys event, continue */
 118                } while (i++ < MAX_TRY_TIMES);
 119                /* If there's no response is received, clear command */
 120                if (i >= MAX_TRY_TIMES  ||
 121                    vf->cmd_retval != VIRTCHNL_STATUS_SUCCESS) {
 122                        err = -1;
 123                        PMD_DRV_LOG(ERR, "No response or return failure (%d)"
 124                                    " for cmd %d", vf->cmd_retval, args->ops);
 125                        _clear_cmd(vf);
 126                }
 127                break;
 128        }
 129
 130        return err;
 131}
 132
 133static uint32_t
 134iavf_convert_link_speed(enum virtchnl_link_speed virt_link_speed)
 135{
 136        uint32_t speed;
 137
 138        switch (virt_link_speed) {
 139        case VIRTCHNL_LINK_SPEED_100MB:
 140                speed = 100;
 141                break;
 142        case VIRTCHNL_LINK_SPEED_1GB:
 143                speed = 1000;
 144                break;
 145        case VIRTCHNL_LINK_SPEED_10GB:
 146                speed = 10000;
 147                break;
 148        case VIRTCHNL_LINK_SPEED_40GB:
 149                speed = 40000;
 150                break;
 151        case VIRTCHNL_LINK_SPEED_20GB:
 152                speed = 20000;
 153                break;
 154        case VIRTCHNL_LINK_SPEED_25GB:
 155                speed = 25000;
 156                break;
 157        case VIRTCHNL_LINK_SPEED_2_5GB:
 158                speed = 2500;
 159                break;
 160        case VIRTCHNL_LINK_SPEED_5GB:
 161                speed = 5000;
 162                break;
 163        default:
 164                speed = 0;
 165                break;
 166        }
 167
 168        return speed;
 169}
 170
 171static void
 172iavf_handle_pf_event_msg(struct rte_eth_dev *dev, uint8_t *msg,
 173                        uint16_t msglen)
 174{
 175        struct virtchnl_pf_event *pf_msg =
 176                        (struct virtchnl_pf_event *)msg;
 177        struct iavf_info *vf = IAVF_DEV_PRIVATE_TO_VF(dev->data->dev_private);
 178
 179        if (msglen < sizeof(struct virtchnl_pf_event)) {
 180                PMD_DRV_LOG(DEBUG, "Error event");
 181                return;
 182        }
 183        switch (pf_msg->event) {
 184        case VIRTCHNL_EVENT_RESET_IMPENDING:
 185                PMD_DRV_LOG(DEBUG, "VIRTCHNL_EVENT_RESET_IMPENDING event");
 186                _rte_eth_dev_callback_process(dev, RTE_ETH_EVENT_INTR_RESET,
 187                                              NULL);
 188                break;
 189        case VIRTCHNL_EVENT_LINK_CHANGE:
 190                PMD_DRV_LOG(DEBUG, "VIRTCHNL_EVENT_LINK_CHANGE event");
 191                vf->link_up = pf_msg->event_data.link_event.link_status;
 192                if (vf->vf_res->vf_cap_flags & VIRTCHNL_VF_CAP_ADV_LINK_SPEED) {
 193                        vf->link_speed =
 194                                pf_msg->event_data.link_event_adv.link_speed;
 195                } else {
 196                        enum virtchnl_link_speed speed;
 197                        speed = pf_msg->event_data.link_event.link_speed;
 198                        vf->link_speed = iavf_convert_link_speed(speed);
 199                }
 200                iavf_dev_link_update(dev, 0);
 201                _rte_eth_dev_callback_process(dev, RTE_ETH_EVENT_INTR_LSC,
 202                                              NULL);
 203                break;
 204        case VIRTCHNL_EVENT_PF_DRIVER_CLOSE:
 205                PMD_DRV_LOG(DEBUG, "VIRTCHNL_EVENT_PF_DRIVER_CLOSE event");
 206                break;
 207        default:
 208                PMD_DRV_LOG(ERR, " unknown event received %u", pf_msg->event);
 209                break;
 210        }
 211}
 212
 213void
 214iavf_handle_virtchnl_msg(struct rte_eth_dev *dev)
 215{
 216        struct iavf_hw *hw = IAVF_DEV_PRIVATE_TO_HW(dev->data->dev_private);
 217        struct iavf_info *vf = IAVF_DEV_PRIVATE_TO_VF(dev->data->dev_private);
 218        struct iavf_arq_event_info info;
 219        uint16_t pending, aq_opc;
 220        enum virtchnl_ops msg_opc;
 221        enum iavf_status msg_ret;
 222        int ret;
 223
 224        info.buf_len = IAVF_AQ_BUF_SZ;
 225        if (!vf->aq_resp) {
 226                PMD_DRV_LOG(ERR, "Buffer for adminq resp should not be NULL");
 227                return;
 228        }
 229        info.msg_buf = vf->aq_resp;
 230
 231        pending = 1;
 232        while (pending) {
 233                ret = iavf_clean_arq_element(hw, &info, &pending);
 234
 235                if (ret != IAVF_SUCCESS) {
 236                        PMD_DRV_LOG(INFO, "Failed to read msg from AdminQ,"
 237                                    "ret: %d", ret);
 238                        break;
 239                }
 240                aq_opc = rte_le_to_cpu_16(info.desc.opcode);
 241                /* For the message sent from pf to vf, opcode is stored in
 242                 * cookie_high of struct iavf_aq_desc, while return error code
 243                 * are stored in cookie_low, Which is done by PF driver.
 244                 */
 245                msg_opc = (enum virtchnl_ops)rte_le_to_cpu_32(
 246                                                  info.desc.cookie_high);
 247                msg_ret = (enum iavf_status)rte_le_to_cpu_32(
 248                                                  info.desc.cookie_low);
 249                switch (aq_opc) {
 250                case iavf_aqc_opc_send_msg_to_vf:
 251                        if (msg_opc == VIRTCHNL_OP_EVENT) {
 252                                iavf_handle_pf_event_msg(dev, info.msg_buf,
 253                                                        info.msg_len);
 254                        } else {
 255                                /* read message and it's expected one */
 256                                if (msg_opc == vf->pend_cmd)
 257                                        _notify_cmd(vf, msg_ret);
 258                                else
 259                                        PMD_DRV_LOG(ERR, "command mismatch,"
 260                                                    "expect %u, get %u",
 261                                                    vf->pend_cmd, msg_opc);
 262                                PMD_DRV_LOG(DEBUG,
 263                                            "adminq response is received,"
 264                                            " opcode = %d", msg_opc);
 265                        }
 266                        break;
 267                default:
 268                        PMD_DRV_LOG(ERR, "Request %u is not supported yet",
 269                                    aq_opc);
 270                        break;
 271                }
 272        }
 273}
 274
 275int
 276iavf_enable_vlan_strip(struct iavf_adapter *adapter)
 277{
 278        struct iavf_info *vf = IAVF_DEV_PRIVATE_TO_VF(adapter);
 279        struct iavf_cmd_info args;
 280        int ret;
 281
 282        memset(&args, 0, sizeof(args));
 283        args.ops = VIRTCHNL_OP_ENABLE_VLAN_STRIPPING;
 284        args.in_args = NULL;
 285        args.in_args_size = 0;
 286        args.out_buffer = vf->aq_resp;
 287        args.out_size = IAVF_AQ_BUF_SZ;
 288        ret = iavf_execute_vf_cmd(adapter, &args);
 289        if (ret)
 290                PMD_DRV_LOG(ERR, "Failed to execute command of"
 291                            " OP_ENABLE_VLAN_STRIPPING");
 292
 293        return ret;
 294}
 295
 296int
 297iavf_disable_vlan_strip(struct iavf_adapter *adapter)
 298{
 299        struct iavf_info *vf = IAVF_DEV_PRIVATE_TO_VF(adapter);
 300        struct iavf_cmd_info args;
 301        int ret;
 302
 303        memset(&args, 0, sizeof(args));
 304        args.ops = VIRTCHNL_OP_DISABLE_VLAN_STRIPPING;
 305        args.in_args = NULL;
 306        args.in_args_size = 0;
 307        args.out_buffer = vf->aq_resp;
 308        args.out_size = IAVF_AQ_BUF_SZ;
 309        ret = iavf_execute_vf_cmd(adapter, &args);
 310        if (ret)
 311                PMD_DRV_LOG(ERR, "Failed to execute command of"
 312                            " OP_DISABLE_VLAN_STRIPPING");
 313
 314        return ret;
 315}
 316
 317#define VIRTCHNL_VERSION_MAJOR_START 1
 318#define VIRTCHNL_VERSION_MINOR_START 1
 319
 320/* Check API version with sync wait until version read from admin queue */
 321int
 322iavf_check_api_version(struct iavf_adapter *adapter)
 323{
 324        struct iavf_info *vf = IAVF_DEV_PRIVATE_TO_VF(adapter);
 325        struct virtchnl_version_info version, *pver;
 326        struct iavf_cmd_info args;
 327        int err;
 328
 329        version.major = VIRTCHNL_VERSION_MAJOR;
 330        version.minor = VIRTCHNL_VERSION_MINOR;
 331
 332        args.ops = VIRTCHNL_OP_VERSION;
 333        args.in_args = (uint8_t *)&version;
 334        args.in_args_size = sizeof(version);
 335        args.out_buffer = vf->aq_resp;
 336        args.out_size = IAVF_AQ_BUF_SZ;
 337
 338        err = iavf_execute_vf_cmd(adapter, &args);
 339        if (err) {
 340                PMD_INIT_LOG(ERR, "Fail to execute command of OP_VERSION");
 341                return err;
 342        }
 343
 344        pver = (struct virtchnl_version_info *)args.out_buffer;
 345        vf->virtchnl_version = *pver;
 346
 347        if (vf->virtchnl_version.major < VIRTCHNL_VERSION_MAJOR_START ||
 348            (vf->virtchnl_version.major == VIRTCHNL_VERSION_MAJOR_START &&
 349             vf->virtchnl_version.minor < VIRTCHNL_VERSION_MINOR_START)) {
 350                PMD_INIT_LOG(ERR, "VIRTCHNL API version should not be lower"
 351                             " than (%u.%u) to support Adapative VF",
 352                             VIRTCHNL_VERSION_MAJOR_START,
 353                             VIRTCHNL_VERSION_MAJOR_START);
 354                return -1;
 355        } else if (vf->virtchnl_version.major > VIRTCHNL_VERSION_MAJOR ||
 356                   (vf->virtchnl_version.major == VIRTCHNL_VERSION_MAJOR &&
 357                    vf->virtchnl_version.minor > VIRTCHNL_VERSION_MINOR)) {
 358                PMD_INIT_LOG(ERR, "PF/VF API version mismatch:(%u.%u)-(%u.%u)",
 359                             vf->virtchnl_version.major,
 360                             vf->virtchnl_version.minor,
 361                             VIRTCHNL_VERSION_MAJOR,
 362                             VIRTCHNL_VERSION_MINOR);
 363                return -1;
 364        }
 365
 366        PMD_DRV_LOG(DEBUG, "Peer is supported PF host");
 367        return 0;
 368}
 369
 370int
 371iavf_get_vf_resource(struct iavf_adapter *adapter)
 372{
 373        struct iavf_hw *hw = IAVF_DEV_PRIVATE_TO_HW(adapter);
 374        struct iavf_info *vf = IAVF_DEV_PRIVATE_TO_VF(adapter);
 375        struct iavf_cmd_info args;
 376        uint32_t caps, len;
 377        int err, i;
 378
 379        args.ops = VIRTCHNL_OP_GET_VF_RESOURCES;
 380        args.out_buffer = vf->aq_resp;
 381        args.out_size = IAVF_AQ_BUF_SZ;
 382
 383        caps = IAVF_BASIC_OFFLOAD_CAPS | VIRTCHNL_VF_CAP_ADV_LINK_SPEED |
 384                VIRTCHNL_VF_OFFLOAD_RX_FLEX_DESC |
 385                VIRTCHNL_VF_OFFLOAD_FDIR_PF |
 386                VIRTCHNL_VF_OFFLOAD_ADV_RSS_PF;
 387
 388        args.in_args = (uint8_t *)&caps;
 389        args.in_args_size = sizeof(caps);
 390
 391        err = iavf_execute_vf_cmd(adapter, &args);
 392
 393        if (err) {
 394                PMD_DRV_LOG(ERR,
 395                            "Failed to execute command of OP_GET_VF_RESOURCE");
 396                return -1;
 397        }
 398
 399        len =  sizeof(struct virtchnl_vf_resource) +
 400                      IAVF_MAX_VF_VSI * sizeof(struct virtchnl_vsi_resource);
 401
 402        rte_memcpy(vf->vf_res, args.out_buffer,
 403                   RTE_MIN(args.out_size, len));
 404        /* parse  VF config message back from PF*/
 405        iavf_vf_parse_hw_config(hw, vf->vf_res);
 406        for (i = 0; i < vf->vf_res->num_vsis; i++) {
 407                if (vf->vf_res->vsi_res[i].vsi_type == VIRTCHNL_VSI_SRIOV)
 408                        vf->vsi_res = &vf->vf_res->vsi_res[i];
 409        }
 410
 411        if (!vf->vsi_res) {
 412                PMD_INIT_LOG(ERR, "no LAN VSI found");
 413                return -1;
 414        }
 415
 416        vf->vsi.vsi_id = vf->vsi_res->vsi_id;
 417        vf->vsi.nb_qps = vf->vsi_res->num_queue_pairs;
 418        vf->vsi.adapter = adapter;
 419
 420        return 0;
 421}
 422
 423int
 424iavf_get_supported_rxdid(struct iavf_adapter *adapter)
 425{
 426        struct iavf_info *vf = IAVF_DEV_PRIVATE_TO_VF(adapter);
 427        struct iavf_cmd_info args;
 428        int ret;
 429
 430        args.ops = VIRTCHNL_OP_GET_SUPPORTED_RXDIDS;
 431        args.in_args = NULL;
 432        args.in_args_size = 0;
 433        args.out_buffer = vf->aq_resp;
 434        args.out_size = IAVF_AQ_BUF_SZ;
 435
 436        ret = iavf_execute_vf_cmd(adapter, &args);
 437        if (ret) {
 438                PMD_DRV_LOG(ERR,
 439                            "Failed to execute command of OP_GET_SUPPORTED_RXDIDS");
 440                return ret;
 441        }
 442
 443        vf->supported_rxdid =
 444                ((struct virtchnl_supported_rxdids *)args.out_buffer)->supported_rxdids;
 445
 446        return 0;
 447}
 448
 449int
 450iavf_enable_queues(struct iavf_adapter *adapter)
 451{
 452        struct iavf_info *vf = IAVF_DEV_PRIVATE_TO_VF(adapter);
 453        struct virtchnl_queue_select queue_select;
 454        struct iavf_cmd_info args;
 455        int err;
 456
 457        memset(&queue_select, 0, sizeof(queue_select));
 458        queue_select.vsi_id = vf->vsi_res->vsi_id;
 459
 460        queue_select.rx_queues = BIT(adapter->eth_dev->data->nb_rx_queues) - 1;
 461        queue_select.tx_queues = BIT(adapter->eth_dev->data->nb_tx_queues) - 1;
 462
 463        args.ops = VIRTCHNL_OP_ENABLE_QUEUES;
 464        args.in_args = (u8 *)&queue_select;
 465        args.in_args_size = sizeof(queue_select);
 466        args.out_buffer = vf->aq_resp;
 467        args.out_size = IAVF_AQ_BUF_SZ;
 468        err = iavf_execute_vf_cmd(adapter, &args);
 469        if (err) {
 470                PMD_DRV_LOG(ERR,
 471                            "Failed to execute command of OP_ENABLE_QUEUES");
 472                return err;
 473        }
 474        return 0;
 475}
 476
 477int
 478iavf_disable_queues(struct iavf_adapter *adapter)
 479{
 480        struct iavf_info *vf = IAVF_DEV_PRIVATE_TO_VF(adapter);
 481        struct virtchnl_queue_select queue_select;
 482        struct iavf_cmd_info args;
 483        int err;
 484
 485        memset(&queue_select, 0, sizeof(queue_select));
 486        queue_select.vsi_id = vf->vsi_res->vsi_id;
 487
 488        queue_select.rx_queues = BIT(adapter->eth_dev->data->nb_rx_queues) - 1;
 489        queue_select.tx_queues = BIT(adapter->eth_dev->data->nb_tx_queues) - 1;
 490
 491        args.ops = VIRTCHNL_OP_DISABLE_QUEUES;
 492        args.in_args = (u8 *)&queue_select;
 493        args.in_args_size = sizeof(queue_select);
 494        args.out_buffer = vf->aq_resp;
 495        args.out_size = IAVF_AQ_BUF_SZ;
 496        err = iavf_execute_vf_cmd(adapter, &args);
 497        if (err) {
 498                PMD_DRV_LOG(ERR,
 499                            "Failed to execute command of OP_DISABLE_QUEUES");
 500                return err;
 501        }
 502        return 0;
 503}
 504
 505int
 506iavf_switch_queue(struct iavf_adapter *adapter, uint16_t qid,
 507                 bool rx, bool on)
 508{
 509        struct iavf_info *vf = IAVF_DEV_PRIVATE_TO_VF(adapter);
 510        struct virtchnl_queue_select queue_select;
 511        struct iavf_cmd_info args;
 512        int err;
 513
 514        memset(&queue_select, 0, sizeof(queue_select));
 515        queue_select.vsi_id = vf->vsi_res->vsi_id;
 516        if (rx)
 517                queue_select.rx_queues |= 1 << qid;
 518        else
 519                queue_select.tx_queues |= 1 << qid;
 520
 521        if (on)
 522                args.ops = VIRTCHNL_OP_ENABLE_QUEUES;
 523        else
 524                args.ops = VIRTCHNL_OP_DISABLE_QUEUES;
 525        args.in_args = (u8 *)&queue_select;
 526        args.in_args_size = sizeof(queue_select);
 527        args.out_buffer = vf->aq_resp;
 528        args.out_size = IAVF_AQ_BUF_SZ;
 529        err = iavf_execute_vf_cmd(adapter, &args);
 530        if (err)
 531                PMD_DRV_LOG(ERR, "Failed to execute command of %s",
 532                            on ? "OP_ENABLE_QUEUES" : "OP_DISABLE_QUEUES");
 533        return err;
 534}
 535
 536int
 537iavf_configure_rss_lut(struct iavf_adapter *adapter)
 538{
 539        struct iavf_info *vf = IAVF_DEV_PRIVATE_TO_VF(adapter);
 540        struct virtchnl_rss_lut *rss_lut;
 541        struct iavf_cmd_info args;
 542        int len, err = 0;
 543
 544        len = sizeof(*rss_lut) + vf->vf_res->rss_lut_size - 1;
 545        rss_lut = rte_zmalloc("rss_lut", len, 0);
 546        if (!rss_lut)
 547                return -ENOMEM;
 548
 549        rss_lut->vsi_id = vf->vsi_res->vsi_id;
 550        rss_lut->lut_entries = vf->vf_res->rss_lut_size;
 551        rte_memcpy(rss_lut->lut, vf->rss_lut, vf->vf_res->rss_lut_size);
 552
 553        args.ops = VIRTCHNL_OP_CONFIG_RSS_LUT;
 554        args.in_args = (u8 *)rss_lut;
 555        args.in_args_size = len;
 556        args.out_buffer = vf->aq_resp;
 557        args.out_size = IAVF_AQ_BUF_SZ;
 558
 559        err = iavf_execute_vf_cmd(adapter, &args);
 560        if (err)
 561                PMD_DRV_LOG(ERR,
 562                            "Failed to execute command of OP_CONFIG_RSS_LUT");
 563
 564        rte_free(rss_lut);
 565        return err;
 566}
 567
 568int
 569iavf_configure_rss_key(struct iavf_adapter *adapter)
 570{
 571        struct iavf_info *vf = IAVF_DEV_PRIVATE_TO_VF(adapter);
 572        struct virtchnl_rss_key *rss_key;
 573        struct iavf_cmd_info args;
 574        int len, err = 0;
 575
 576        len = sizeof(*rss_key) + vf->vf_res->rss_key_size - 1;
 577        rss_key = rte_zmalloc("rss_key", len, 0);
 578        if (!rss_key)
 579                return -ENOMEM;
 580
 581        rss_key->vsi_id = vf->vsi_res->vsi_id;
 582        rss_key->key_len = vf->vf_res->rss_key_size;
 583        rte_memcpy(rss_key->key, vf->rss_key, vf->vf_res->rss_key_size);
 584
 585        args.ops = VIRTCHNL_OP_CONFIG_RSS_KEY;
 586        args.in_args = (u8 *)rss_key;
 587        args.in_args_size = len;
 588        args.out_buffer = vf->aq_resp;
 589        args.out_size = IAVF_AQ_BUF_SZ;
 590
 591        err = iavf_execute_vf_cmd(adapter, &args);
 592        if (err)
 593                PMD_DRV_LOG(ERR,
 594                            "Failed to execute command of OP_CONFIG_RSS_KEY");
 595
 596        rte_free(rss_key);
 597        return err;
 598}
 599
 600int
 601iavf_configure_queues(struct iavf_adapter *adapter)
 602{
 603        struct iavf_rx_queue **rxq =
 604                (struct iavf_rx_queue **)adapter->eth_dev->data->rx_queues;
 605        struct iavf_tx_queue **txq =
 606                (struct iavf_tx_queue **)adapter->eth_dev->data->tx_queues;
 607        struct iavf_info *vf = IAVF_DEV_PRIVATE_TO_VF(adapter);
 608        struct virtchnl_vsi_queue_config_info *vc_config;
 609        struct virtchnl_queue_pair_info *vc_qp;
 610        struct iavf_cmd_info args;
 611        uint16_t i, size;
 612        int err;
 613
 614        size = sizeof(*vc_config) +
 615               sizeof(vc_config->qpair[0]) * vf->num_queue_pairs;
 616        vc_config = rte_zmalloc("cfg_queue", size, 0);
 617        if (!vc_config)
 618                return -ENOMEM;
 619
 620        vc_config->vsi_id = vf->vsi_res->vsi_id;
 621        vc_config->num_queue_pairs = vf->num_queue_pairs;
 622
 623        for (i = 0, vc_qp = vc_config->qpair;
 624             i < vf->num_queue_pairs;
 625             i++, vc_qp++) {
 626                vc_qp->txq.vsi_id = vf->vsi_res->vsi_id;
 627                vc_qp->txq.queue_id = i;
 628                /* Virtchnnl configure queues by pairs */
 629                if (i < adapter->eth_dev->data->nb_tx_queues) {
 630                        vc_qp->txq.ring_len = txq[i]->nb_tx_desc;
 631                        vc_qp->txq.dma_ring_addr = txq[i]->tx_ring_phys_addr;
 632                }
 633                vc_qp->rxq.vsi_id = vf->vsi_res->vsi_id;
 634                vc_qp->rxq.queue_id = i;
 635                vc_qp->rxq.max_pkt_size = vf->max_pkt_len;
 636                /* Virtchnnl configure queues by pairs */
 637                if (i < adapter->eth_dev->data->nb_rx_queues) {
 638                        vc_qp->rxq.ring_len = rxq[i]->nb_rx_desc;
 639                        vc_qp->rxq.dma_ring_addr = rxq[i]->rx_ring_phys_addr;
 640                        vc_qp->rxq.databuffer_size = rxq[i]->rx_buf_len;
 641                }
 642
 643#ifndef RTE_LIBRTE_IAVF_16BYTE_RX_DESC
 644                if (vf->vf_res->vf_cap_flags &
 645                        VIRTCHNL_VF_OFFLOAD_RX_FLEX_DESC &&
 646                        vf->supported_rxdid & BIT(IAVF_RXDID_COMMS_OVS_1)) {
 647                        vc_qp->rxq.rxdid = IAVF_RXDID_COMMS_OVS_1;
 648                        PMD_DRV_LOG(NOTICE, "request RXDID == %d in "
 649                                        "Queue[%d]", vc_qp->rxq.rxdid, i);
 650                } else {
 651                        vc_qp->rxq.rxdid = IAVF_RXDID_LEGACY_1;
 652                        PMD_DRV_LOG(NOTICE, "request RXDID == %d in "
 653                                        "Queue[%d]", vc_qp->rxq.rxdid, i);
 654                }
 655#else
 656                if (vf->vf_res->vf_cap_flags &
 657                        VIRTCHNL_VF_OFFLOAD_RX_FLEX_DESC &&
 658                        vf->supported_rxdid & BIT(IAVF_RXDID_LEGACY_0)) {
 659                        vc_qp->rxq.rxdid = IAVF_RXDID_LEGACY_0;
 660                        PMD_DRV_LOG(NOTICE, "request RXDID == %d in "
 661                                        "Queue[%d]", vc_qp->rxq.rxdid, i);
 662                } else {
 663                        PMD_DRV_LOG(ERR, "RXDID == 0 is not supported");
 664                        return -1;
 665                }
 666#endif
 667        }
 668
 669        memset(&args, 0, sizeof(args));
 670        args.ops = VIRTCHNL_OP_CONFIG_VSI_QUEUES;
 671        args.in_args = (uint8_t *)vc_config;
 672        args.in_args_size = size;
 673        args.out_buffer = vf->aq_resp;
 674        args.out_size = IAVF_AQ_BUF_SZ;
 675
 676        err = iavf_execute_vf_cmd(adapter, &args);
 677        if (err)
 678                PMD_DRV_LOG(ERR, "Failed to execute command of"
 679                            " VIRTCHNL_OP_CONFIG_VSI_QUEUES");
 680
 681        rte_free(vc_config);
 682        return err;
 683}
 684
 685int
 686iavf_config_irq_map(struct iavf_adapter *adapter)
 687{
 688        struct iavf_info *vf = IAVF_DEV_PRIVATE_TO_VF(adapter);
 689        struct virtchnl_irq_map_info *map_info;
 690        struct virtchnl_vector_map *vecmap;
 691        struct iavf_cmd_info args;
 692        int len, i, err;
 693
 694        len = sizeof(struct virtchnl_irq_map_info) +
 695              sizeof(struct virtchnl_vector_map) * vf->nb_msix;
 696
 697        map_info = rte_zmalloc("map_info", len, 0);
 698        if (!map_info)
 699                return -ENOMEM;
 700
 701        map_info->num_vectors = vf->nb_msix;
 702        for (i = 0; i < vf->nb_msix; i++) {
 703                vecmap = &map_info->vecmap[i];
 704                vecmap->vsi_id = vf->vsi_res->vsi_id;
 705                vecmap->rxitr_idx = IAVF_ITR_INDEX_DEFAULT;
 706                vecmap->vector_id = vf->msix_base + i;
 707                vecmap->txq_map = 0;
 708                vecmap->rxq_map = vf->rxq_map[vf->msix_base + i];
 709        }
 710
 711        args.ops = VIRTCHNL_OP_CONFIG_IRQ_MAP;
 712        args.in_args = (u8 *)map_info;
 713        args.in_args_size = len;
 714        args.out_buffer = vf->aq_resp;
 715        args.out_size = IAVF_AQ_BUF_SZ;
 716        err = iavf_execute_vf_cmd(adapter, &args);
 717        if (err)
 718                PMD_DRV_LOG(ERR, "fail to execute command OP_CONFIG_IRQ_MAP");
 719
 720        rte_free(map_info);
 721        return err;
 722}
 723
 724void
 725iavf_add_del_all_mac_addr(struct iavf_adapter *adapter, bool add)
 726{
 727        struct virtchnl_ether_addr_list *list;
 728        struct iavf_info *vf = IAVF_DEV_PRIVATE_TO_VF(adapter);
 729        struct rte_ether_addr *addr;
 730        struct iavf_cmd_info args;
 731        int len, err, i, j;
 732        int next_begin = 0;
 733        int begin = 0;
 734
 735        do {
 736                j = 0;
 737                len = sizeof(struct virtchnl_ether_addr_list);
 738                for (i = begin; i < IAVF_NUM_MACADDR_MAX; i++, next_begin++) {
 739                        addr = &adapter->eth_dev->data->mac_addrs[i];
 740                        if (rte_is_zero_ether_addr(addr))
 741                                continue;
 742                        len += sizeof(struct virtchnl_ether_addr);
 743                        if (len >= IAVF_AQ_BUF_SZ) {
 744                                next_begin = i + 1;
 745                                break;
 746                        }
 747                }
 748
 749                list = rte_zmalloc("iavf_del_mac_buffer", len, 0);
 750                if (!list) {
 751                        PMD_DRV_LOG(ERR, "fail to allocate memory");
 752                        return;
 753                }
 754
 755                for (i = begin; i < next_begin; i++) {
 756                        addr = &adapter->eth_dev->data->mac_addrs[i];
 757                        if (rte_is_zero_ether_addr(addr))
 758                                continue;
 759                        rte_memcpy(list->list[j].addr, addr->addr_bytes,
 760                                   sizeof(addr->addr_bytes));
 761                        PMD_DRV_LOG(DEBUG, "add/rm mac:%x:%x:%x:%x:%x:%x",
 762                                    addr->addr_bytes[0], addr->addr_bytes[1],
 763                                    addr->addr_bytes[2], addr->addr_bytes[3],
 764                                    addr->addr_bytes[4], addr->addr_bytes[5]);
 765                        j++;
 766                }
 767                list->vsi_id = vf->vsi_res->vsi_id;
 768                list->num_elements = j;
 769                args.ops = add ? VIRTCHNL_OP_ADD_ETH_ADDR :
 770                           VIRTCHNL_OP_DEL_ETH_ADDR;
 771                args.in_args = (uint8_t *)list;
 772                args.in_args_size = len;
 773                args.out_buffer = vf->aq_resp;
 774                args.out_size = IAVF_AQ_BUF_SZ;
 775                err = iavf_execute_vf_cmd(adapter, &args);
 776                if (err)
 777                        PMD_DRV_LOG(ERR, "fail to execute command %s",
 778                                    add ? "OP_ADD_ETHER_ADDRESS" :
 779                                    "OP_DEL_ETHER_ADDRESS");
 780                rte_free(list);
 781                begin = next_begin;
 782        } while (begin < IAVF_NUM_MACADDR_MAX);
 783}
 784
 785int
 786iavf_query_stats(struct iavf_adapter *adapter,
 787                struct virtchnl_eth_stats **pstats)
 788{
 789        struct iavf_info *vf = IAVF_DEV_PRIVATE_TO_VF(adapter);
 790        struct virtchnl_queue_select q_stats;
 791        struct iavf_cmd_info args;
 792        int err;
 793
 794        memset(&q_stats, 0, sizeof(q_stats));
 795        q_stats.vsi_id = vf->vsi_res->vsi_id;
 796        args.ops = VIRTCHNL_OP_GET_STATS;
 797        args.in_args = (uint8_t *)&q_stats;
 798        args.in_args_size = sizeof(q_stats);
 799        args.out_buffer = vf->aq_resp;
 800        args.out_size = IAVF_AQ_BUF_SZ;
 801
 802        err = iavf_execute_vf_cmd(adapter, &args);
 803        if (err) {
 804                PMD_DRV_LOG(ERR, "fail to execute command OP_GET_STATS");
 805                *pstats = NULL;
 806                return err;
 807        }
 808        *pstats = (struct virtchnl_eth_stats *)args.out_buffer;
 809        return 0;
 810}
 811
 812int
 813iavf_config_promisc(struct iavf_adapter *adapter,
 814                   bool enable_unicast,
 815                   bool enable_multicast)
 816{
 817        struct iavf_info *vf = IAVF_DEV_PRIVATE_TO_VF(adapter);
 818        struct virtchnl_promisc_info promisc;
 819        struct iavf_cmd_info args;
 820        int err;
 821
 822        promisc.flags = 0;
 823        promisc.vsi_id = vf->vsi_res->vsi_id;
 824
 825        if (enable_unicast)
 826                promisc.flags |= FLAG_VF_UNICAST_PROMISC;
 827
 828        if (enable_multicast)
 829                promisc.flags |= FLAG_VF_MULTICAST_PROMISC;
 830
 831        args.ops = VIRTCHNL_OP_CONFIG_PROMISCUOUS_MODE;
 832        args.in_args = (uint8_t *)&promisc;
 833        args.in_args_size = sizeof(promisc);
 834        args.out_buffer = vf->aq_resp;
 835        args.out_size = IAVF_AQ_BUF_SZ;
 836
 837        err = iavf_execute_vf_cmd(adapter, &args);
 838
 839        if (err)
 840                PMD_DRV_LOG(ERR,
 841                            "fail to execute command CONFIG_PROMISCUOUS_MODE");
 842        return err;
 843}
 844
 845int
 846iavf_add_del_eth_addr(struct iavf_adapter *adapter, struct rte_ether_addr *addr,
 847                     bool add)
 848{
 849        struct virtchnl_ether_addr_list *list;
 850        struct iavf_info *vf = IAVF_DEV_PRIVATE_TO_VF(adapter);
 851        uint8_t cmd_buffer[sizeof(struct virtchnl_ether_addr_list) +
 852                           sizeof(struct virtchnl_ether_addr)];
 853        struct iavf_cmd_info args;
 854        int err;
 855
 856        list = (struct virtchnl_ether_addr_list *)cmd_buffer;
 857        list->vsi_id = vf->vsi_res->vsi_id;
 858        list->num_elements = 1;
 859        rte_memcpy(list->list[0].addr, addr->addr_bytes,
 860                   sizeof(addr->addr_bytes));
 861
 862        args.ops = add ? VIRTCHNL_OP_ADD_ETH_ADDR : VIRTCHNL_OP_DEL_ETH_ADDR;
 863        args.in_args = cmd_buffer;
 864        args.in_args_size = sizeof(cmd_buffer);
 865        args.out_buffer = vf->aq_resp;
 866        args.out_size = IAVF_AQ_BUF_SZ;
 867        err = iavf_execute_vf_cmd(adapter, &args);
 868        if (err)
 869                PMD_DRV_LOG(ERR, "fail to execute command %s",
 870                            add ? "OP_ADD_ETH_ADDR" :  "OP_DEL_ETH_ADDR");
 871        return err;
 872}
 873
 874int
 875iavf_add_del_vlan(struct iavf_adapter *adapter, uint16_t vlanid, bool add)
 876{
 877        struct virtchnl_vlan_filter_list *vlan_list;
 878        struct iavf_info *vf = IAVF_DEV_PRIVATE_TO_VF(adapter);
 879        uint8_t cmd_buffer[sizeof(struct virtchnl_vlan_filter_list) +
 880                                                        sizeof(uint16_t)];
 881        struct iavf_cmd_info args;
 882        int err;
 883
 884        vlan_list = (struct virtchnl_vlan_filter_list *)cmd_buffer;
 885        vlan_list->vsi_id = vf->vsi_res->vsi_id;
 886        vlan_list->num_elements = 1;
 887        vlan_list->vlan_id[0] = vlanid;
 888
 889        args.ops = add ? VIRTCHNL_OP_ADD_VLAN : VIRTCHNL_OP_DEL_VLAN;
 890        args.in_args = cmd_buffer;
 891        args.in_args_size = sizeof(cmd_buffer);
 892        args.out_buffer = vf->aq_resp;
 893        args.out_size = IAVF_AQ_BUF_SZ;
 894        err = iavf_execute_vf_cmd(adapter, &args);
 895        if (err)
 896                PMD_DRV_LOG(ERR, "fail to execute command %s",
 897                            add ? "OP_ADD_VLAN" :  "OP_DEL_VLAN");
 898
 899        return err;
 900}
 901
 902int
 903iavf_fdir_add(struct iavf_adapter *adapter,
 904        struct iavf_fdir_conf *filter)
 905{
 906        struct iavf_info *vf = IAVF_DEV_PRIVATE_TO_VF(adapter);
 907        struct virtchnl_fdir_add *fdir_ret;
 908
 909        struct iavf_cmd_info args;
 910        int err;
 911
 912        filter->add_fltr.vsi_id = vf->vsi_res->vsi_id;
 913        filter->add_fltr.validate_only = 0;
 914
 915        args.ops = VIRTCHNL_OP_ADD_FDIR_FILTER;
 916        args.in_args = (uint8_t *)(&filter->add_fltr);
 917        args.in_args_size = sizeof(*(&filter->add_fltr));
 918        args.out_buffer = vf->aq_resp;
 919        args.out_size = IAVF_AQ_BUF_SZ;
 920
 921        err = iavf_execute_vf_cmd(adapter, &args);
 922        if (err) {
 923                PMD_DRV_LOG(ERR, "fail to execute command OP_ADD_FDIR_FILTER");
 924                return err;
 925        }
 926
 927        fdir_ret = (struct virtchnl_fdir_add *)args.out_buffer;
 928        filter->flow_id = fdir_ret->flow_id;
 929
 930        if (fdir_ret->status == VIRTCHNL_FDIR_SUCCESS) {
 931                PMD_DRV_LOG(INFO,
 932                        "Succeed in adding rule request by PF");
 933        } else if (fdir_ret->status == VIRTCHNL_FDIR_FAILURE_RULE_NORESOURCE) {
 934                PMD_DRV_LOG(ERR,
 935                        "Failed to add rule request due to no hw resource");
 936                return -1;
 937        } else if (fdir_ret->status == VIRTCHNL_FDIR_FAILURE_RULE_EXIST) {
 938                PMD_DRV_LOG(ERR,
 939                        "Failed to add rule request due to the rule is already existed");
 940                return -1;
 941        } else if (fdir_ret->status == VIRTCHNL_FDIR_FAILURE_RULE_CONFLICT) {
 942                PMD_DRV_LOG(ERR,
 943                        "Failed to add rule request due to the rule is conflict with existing rule");
 944                return -1;
 945        } else if (fdir_ret->status == VIRTCHNL_FDIR_FAILURE_RULE_INVALID) {
 946                PMD_DRV_LOG(ERR,
 947                        "Failed to add rule request due to the hw doesn't support");
 948                return -1;
 949        } else if (fdir_ret->status == VIRTCHNL_FDIR_FAILURE_RULE_TIMEOUT) {
 950                PMD_DRV_LOG(ERR,
 951                        "Failed to add rule request due to time out for programming");
 952                return -1;
 953        } else {
 954                PMD_DRV_LOG(ERR,
 955                        "Failed to add rule request due to other reasons");
 956                return -1;
 957        }
 958
 959        return 0;
 960};
 961
 962int
 963iavf_fdir_del(struct iavf_adapter *adapter,
 964        struct iavf_fdir_conf *filter)
 965{
 966        struct iavf_info *vf = IAVF_DEV_PRIVATE_TO_VF(adapter);
 967        struct virtchnl_fdir_del *fdir_ret;
 968
 969        struct iavf_cmd_info args;
 970        int err;
 971
 972        filter->del_fltr.vsi_id = vf->vsi_res->vsi_id;
 973        filter->del_fltr.flow_id = filter->flow_id;
 974
 975        args.ops = VIRTCHNL_OP_DEL_FDIR_FILTER;
 976        args.in_args = (uint8_t *)(&filter->del_fltr);
 977        args.in_args_size = sizeof(filter->del_fltr);
 978        args.out_buffer = vf->aq_resp;
 979        args.out_size = IAVF_AQ_BUF_SZ;
 980
 981        err = iavf_execute_vf_cmd(adapter, &args);
 982        if (err) {
 983                PMD_DRV_LOG(ERR, "fail to execute command OP_DEL_FDIR_FILTER");
 984                return err;
 985        }
 986
 987        fdir_ret = (struct virtchnl_fdir_del *)args.out_buffer;
 988
 989        if (fdir_ret->status == VIRTCHNL_FDIR_SUCCESS) {
 990                PMD_DRV_LOG(INFO,
 991                        "Succeed in deleting rule request by PF");
 992        } else if (fdir_ret->status == VIRTCHNL_FDIR_FAILURE_RULE_NONEXIST) {
 993                PMD_DRV_LOG(ERR,
 994                        "Failed to delete rule request due to this rule doesn't exist");
 995                return -1;
 996        } else if (fdir_ret->status == VIRTCHNL_FDIR_FAILURE_RULE_TIMEOUT) {
 997                PMD_DRV_LOG(ERR,
 998                        "Failed to delete rule request due to time out for programming");
 999                return -1;
1000        } else {
1001                PMD_DRV_LOG(ERR,
1002                        "Failed to delete rule request due to other reasons");
1003                return -1;
1004        }
1005
1006        return 0;
1007};
1008
1009int
1010iavf_fdir_check(struct iavf_adapter *adapter,
1011                struct iavf_fdir_conf *filter)
1012{
1013        struct iavf_info *vf = IAVF_DEV_PRIVATE_TO_VF(adapter);
1014        struct virtchnl_fdir_add *fdir_ret;
1015
1016        struct iavf_cmd_info args;
1017        int err;
1018
1019        filter->add_fltr.vsi_id = vf->vsi_res->vsi_id;
1020        filter->add_fltr.validate_only = 1;
1021
1022        args.ops = VIRTCHNL_OP_ADD_FDIR_FILTER;
1023        args.in_args = (uint8_t *)(&filter->add_fltr);
1024        args.in_args_size = sizeof(*(&filter->add_fltr));
1025        args.out_buffer = vf->aq_resp;
1026        args.out_size = IAVF_AQ_BUF_SZ;
1027
1028        err = iavf_execute_vf_cmd(adapter, &args);
1029        if (err) {
1030                PMD_DRV_LOG(ERR, "fail to check flow direcotor rule");
1031                return err;
1032        }
1033
1034        fdir_ret = (struct virtchnl_fdir_add *)args.out_buffer;
1035
1036        if (fdir_ret->status == VIRTCHNL_FDIR_SUCCESS) {
1037                PMD_DRV_LOG(INFO,
1038                        "Succeed in checking rule request by PF");
1039        } else if (fdir_ret->status == VIRTCHNL_FDIR_FAILURE_RULE_INVALID) {
1040                PMD_DRV_LOG(ERR,
1041                        "Failed to check rule request due to parameters validation"
1042                        " or HW doesn't support");
1043                return -1;
1044        } else {
1045                PMD_DRV_LOG(ERR,
1046                        "Failed to check rule request due to other reasons");
1047                return -1;
1048        }
1049
1050        return 0;
1051}
1052
1053int
1054iavf_add_del_rss_cfg(struct iavf_adapter *adapter,
1055                     struct virtchnl_rss_cfg *rss_cfg, bool add)
1056{
1057        struct iavf_info *vf = IAVF_DEV_PRIVATE_TO_VF(adapter);
1058        struct iavf_cmd_info args;
1059        int err;
1060
1061        memset(&args, 0, sizeof(args));
1062        args.ops = add ? VIRTCHNL_OP_ADD_RSS_CFG :
1063                VIRTCHNL_OP_DEL_RSS_CFG;
1064        args.in_args = (u8 *)rss_cfg;
1065        args.in_args_size = sizeof(*rss_cfg);
1066        args.out_buffer = vf->aq_resp;
1067        args.out_size = IAVF_AQ_BUF_SZ;
1068
1069        err = iavf_execute_vf_cmd(adapter, &args);
1070        if (err)
1071                PMD_DRV_LOG(ERR,
1072                            "Failed to execute command of %s",
1073                            add ? "OP_ADD_RSS_CFG" :
1074                            "OP_DEL_RSS_INPUT_CFG");
1075
1076        return err;
1077}
1078