From patchwork Sat Dec 19 07:54:51 2020 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Jingjing Wu X-Patchwork-Id: 85502 Return-Path: X-Original-To: patchwork@inbox.dpdk.org Delivered-To: patchwork@inbox.dpdk.org Received: from dpdk.org (dpdk.org [92.243.14.124]) by inbox.dpdk.org (Postfix) with ESMTP id 7F238A04B5; Sat, 19 Dec 2020 09:06:45 +0100 (CET) Received: from [92.243.14.124] (localhost [127.0.0.1]) by dpdk.org (Postfix) with ESMTP id 4C93ECB3E; Sat, 19 Dec 2020 09:06:11 +0100 (CET) Received: from mga17.intel.com (mga17.intel.com [192.55.52.151]) by dpdk.org (Postfix) with ESMTP id 57D73CB19 for ; Sat, 19 Dec 2020 09:06:08 +0100 (CET) IronPort-SDR: KKBUSjDTsp8vCdDCkezPzGR0SkiMcBdI3sjrmhRoGWfjYQ0GfNDYpLPltLjXzD83eVVP5oVi5W wYF62yeZ4Rrw== X-IronPort-AV: E=McAfee;i="6000,8403,9839"; a="155353438" X-IronPort-AV: E=Sophos;i="5.78,432,1599548400"; d="scan'208";a="155353438" Received: from fmsmga001.fm.intel.com ([10.253.24.23]) by fmsmga107.fm.intel.com with ESMTP/TLS/ECDHE-RSA-AES256-GCM-SHA384; 19 Dec 2020 00:06:06 -0800 IronPort-SDR: Y0/HH4367AhMXgASByv9V5Y97O+kKmN2o90ezZ6jGN601xxnhKx0bNKmk7ncRZCiQbOEeIe8t8 vUfthc/u3kvg== X-ExtLoop1: 1 X-IronPort-AV: E=Sophos;i="5.78,432,1599548400"; d="scan'208";a="454532214" Received: from dpdk-wujingji.sh.intel.com ([10.67.119.101]) by fmsmga001.fm.intel.com with ESMTP; 19 Dec 2020 00:06:04 -0800 From: Jingjing Wu To: dev@dpdk.org Cc: jingjing.wu@intel.com, beilei.xing@intel.com, chenbo.xia@intel.com, xiuchun.lu@intel.com Date: Sat, 19 Dec 2020 15:54:51 +0800 Message-Id: <20201219075454.40266-3-jingjing.wu@intel.com> X-Mailer: git-send-email 2.21.1 In-Reply-To: <20201219075454.40266-1-jingjing.wu@intel.com> References: <20201219075454.40266-1-jingjing.wu@intel.com> MIME-Version: 1.0 Subject: [dpdk-dev] [PATCH v1 2/5] net/iavf_be: control queue enabling X-BeenThere: dev@dpdk.org X-Mailman-Version: 2.1.15 Precedence: list List-Id: DPDK patches and discussions List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Errors-To: dev-bounces@dpdk.org Sender: "dev" 1. Set up control rx/tx queues. 2. Emu device callback functions implemention. 3. Enabling recv/send msg through control queue. Signed-off-by: Jingjing Wu Signed-off-by: Chenbo Xia Signed-off-by: Xiuchun Lu --- drivers/net/iavf_be/iavf_be.h | 39 ++++ drivers/net/iavf_be/iavf_be_ethdev.c | 321 ++++++++++++++++++++++++++- drivers/net/iavf_be/iavf_be_vchnl.c | 273 +++++++++++++++++++++++ drivers/net/iavf_be/meson.build | 1 + 4 files changed, 632 insertions(+), 2 deletions(-) create mode 100644 drivers/net/iavf_be/iavf_be_vchnl.c diff --git a/drivers/net/iavf_be/iavf_be.h b/drivers/net/iavf_be/iavf_be.h index 55f218afcd..aff7bb9c56 100644 --- a/drivers/net/iavf_be/iavf_be.h +++ b/drivers/net/iavf_be/iavf_be.h @@ -5,13 +5,49 @@ #ifndef _IAVF_BE_H_ #define _IAVF_BE_H_ +#define IAVF_BE_AQ_LEN 32 +#define IAVF_BE_AQ_BUF_SZ 4096 +#define IAVF_BE_32_TO_64(hi, lo) ((((uint64_t)(hi)) << 32) + (lo)) + +#define IAVFBE_READ_32(addr) \ + rte_le_to_cpu_32(*(volatile uint32_t *)(addr)) +#define IAVFBE_WRITE_32(addr, val) \ + *(volatile uint32_t *)(addr) = rte_cpu_to_le_32(val); + +struct iavfbe_control_q { + rte_spinlock_t access_lock; + struct rte_emudev_q_info q_info; + struct iavf_aq_desc *ring; + uint64_t p_ring_addr; /* Guest physical address of the ring */ + uint16_t len; + volatile uint8_t *tail; + volatile uint8_t *head; + + uint16_t next_to_use; + uint16_t next_to_clean; + + uint32_t cmd_retval; /* return value of the cmd response from PF */ + uint8_t *aq_req; /* buffer to store the adminq request from VF, NULL if arq */ +}; + +/* Control queue structure of iavf */ +struct iavfbe_controlq_info { + struct iavfbe_control_q asq; + struct iavfbe_control_q arq; +}; + /* Structure to store private data for backend instance*/ struct iavfbe_adapter { struct rte_eth_dev *eth_dev; struct rte_emudev *emu_dev; uint16_t edev_id; /* Emulated Device ID */ struct rte_emudev_info dev_info; + struct rte_iavf_emu_mem *mem_table; + struct iavfbe_controlq_info cq_info; /* Control/Admin Queue info*/ + /* Adminq handle thread info */ + volatile int thread_status; + pthread_t thread_id; uint16_t nb_qps; bool link_up; int cq_irqfd; @@ -32,6 +68,9 @@ struct iavfbe_adapter { ((struct iavfbe_adapter *)adapter) int iavfbe_dev_link_update(struct rte_eth_dev *dev, int wait_to_complete); +void iavfbe_handle_virtchnl_msg(void *arg); +void iavfbe_reset_asq(struct iavfbe_adapter *adapter, bool lock); +void iavfbe_reset_arq(struct iavfbe_adapter *adapter, bool lock); extern int iavfbe_logtype; #define IAVF_BE_LOG(level, fmt, args...) \ diff --git a/drivers/net/iavf_be/iavf_be_ethdev.c b/drivers/net/iavf_be/iavf_be_ethdev.c index 3d5ca34ec0..2ab66f889d 100644 --- a/drivers/net/iavf_be/iavf_be_ethdev.c +++ b/drivers/net/iavf_be/iavf_be_ethdev.c @@ -14,6 +14,7 @@ #include #include +#include #include "iavf_be.h" #define AVFBE_EDEV_ID_ARG "emu" @@ -33,6 +34,12 @@ static struct rte_eth_link iavfbe_link = { .link_status = ETH_LINK_DOWN }; +static int iavfbe_new_device(struct rte_emudev *dev); +static void iavfbe_destroy_device(struct rte_emudev *dev); +static int iavfbe_update_device(struct rte_emudev *dev); +static int iavfbe_lock_dp(struct rte_emudev *dev, int lock); +static int iavfbe_reset_device(struct rte_emudev *dev); + static int iavfbe_dev_configure(struct rte_eth_dev *dev); static int iavfbe_dev_close(struct rte_eth_dev *dev); static int iavfbe_dev_start(struct rte_eth_dev *dev); @@ -41,6 +48,16 @@ static int iavfbe_dev_info_get(struct rte_eth_dev *dev, struct rte_eth_dev_info *dev_info); static void iavfbe_destroy_adapter(struct rte_eth_dev *dev); +struct rte_iavf_emu_notify_ops iavfbe_notify_ops = { + .device_ready = iavfbe_new_device, + .device_destroy = iavfbe_destroy_device, + .update_status = iavfbe_update_device, + .device_start = NULL, + .device_stop = NULL, + .lock_dp = iavfbe_lock_dp, + .reset_device = iavfbe_reset_device, +}; + static const struct eth_dev_ops iavfbe_eth_dev_ops = { .dev_configure = iavfbe_dev_configure, .dev_close = iavfbe_dev_close, @@ -51,7 +68,8 @@ static const struct eth_dev_ops iavfbe_eth_dev_ops = { }; static int -iavfbe_dev_info_get(struct rte_eth_dev *dev __rte_unused, struct rte_eth_dev_info *dev_info) +iavfbe_dev_info_get(struct rte_eth_dev *dev __rte_unused, + struct rte_eth_dev_info *dev_info) { dev_info->max_rx_queues = 0; dev_info->max_tx_queues = 0; @@ -61,7 +79,6 @@ iavfbe_dev_info_get(struct rte_eth_dev *dev __rte_unused, struct rte_eth_dev_i return 0; } - static int iavfbe_dev_configure(struct rte_eth_dev *dev __rte_unused) { @@ -122,6 +139,241 @@ iavfbe_dev_close(struct rte_eth_dev *dev) return 0; } +/* Called when emulation device is ready */ +static int +iavfbe_new_device(struct rte_emudev *dev) +{ + struct iavfbe_adapter *adapter = + (struct iavfbe_adapter *)dev->backend_priv; + struct rte_iavf_emu_mem **mem = &(adapter->mem_table); + struct rte_emudev_irq_info irq_info; + struct rte_emudev_q_info q_info; + struct rte_emudev_db_info db_info; + uint64_t addr; + uint16_t i; + + if (rte_emudev_get_mem_table(dev->dev_id, (void **)mem)) { + IAVF_BE_LOG(ERR, "Can not get mem table\n"); + return -1; + } + + for (i = 0; i < RTE_IAVF_EMU_ADMINQ_NUM; i++) { + if (rte_emudev_get_queue_info(dev->dev_id, i, &q_info)) { + IAVF_BE_LOG(ERR, + "Can not get queue info of qid %d\n", i); + return -1; + } + /* + * Only doorbell of LANQ is viable when device ready. + * Other info of LANQ is acquired through virtchnl. + * + * AdminQ's irq and doorbell will both be ready in this stage. + */ + if (rte_emudev_get_db_info(dev->dev_id, q_info.doorbell_id, + &db_info)) { + IAVF_BE_LOG(ERR, + "Can not get doorbell info of qid %d\n", i); + return -1; + } + + /* Only support memory based doorbell for now */ + if (db_info.flag & RTE_EMUDEV_DB_FD || + db_info.data.mem.size != 4) + return -1; + + if (i == RTE_IAVF_EMU_ADMINQ_TXQ) { + adapter->cq_info.asq.tail = + (uint8_t *)db_info.data.mem.base; + } else { + adapter->cq_info.arq.tail = + (uint8_t *)db_info.data.mem.base; + + if (rte_emudev_get_irq_info(dev->dev_id, + q_info.irq_vector, &irq_info)) { + IAVF_BE_LOG(ERR, + "Can not get irq info of qid %d\n", i); + return -1; + } + + adapter->cq_irqfd = irq_info.eventfd; + } + } + + /* Lan queue info would be set when queue setup */ + + if (rte_emudev_get_attr(dev->dev_id, RTE_IAVF_EMU_ATTR_ASQ_HEAD, + (rte_emudev_attr_t)&addr)) { + IAVF_BE_LOG(ERR, "Can not get asq head\n"); + return -1; + } + adapter->cq_info.asq.head = (uint8_t *)(uintptr_t)addr; + + if (rte_emudev_get_attr(dev->dev_id, RTE_IAVF_EMU_ATTR_ARQ_HEAD, + (rte_emudev_attr_t)&addr)) { + IAVF_BE_LOG(ERR, "Can not get arq head\n"); + return -1; + } + adapter->cq_info.arq.head = (uint8_t *)(uintptr_t)addr; + + iavfbe_reset_asq(adapter, false); + iavfbe_reset_arq(adapter, false); + + if (rte_emudev_get_attr(dev->dev_id, RTE_IAVF_EMU_ATTR_RESET, + (rte_emudev_attr_t)&addr)) { + IAVF_BE_LOG(ERR, "Can not get arq head\n"); + return -1; + } + adapter->reset = (uint8_t *)(uintptr_t)addr; + IAVFBE_WRITE_32(adapter->reset, RTE_IAVF_EMU_RESET_COMPLETED); + adapter->started = 1; + printf("NEW DEVICE: memtable, %p\n", adapter->mem_table); + + return 0; +} + +static void +iavfbe_destroy_device(struct rte_emudev *dev) +{ + struct iavfbe_adapter *adapter = + (struct iavfbe_adapter *)dev->backend_priv; + + /* TODO: Disable all lan queues */ + + /* update link status */ + adapter->link_up = false; + iavfbe_dev_link_update(adapter->eth_dev, 0); +} + +static int +iavfbe_update_device(struct rte_emudev *dev) +{ + struct iavfbe_adapter *adapter = + (struct iavfbe_adapter *)dev->backend_priv; + struct rte_iavf_emu_mem **mem = &(adapter->mem_table); + struct rte_emudev_q_info q_info; + struct rte_emudev_irq_info irq_info; + + if (rte_emudev_get_mem_table(dev->dev_id, (void **)mem)) { + IAVF_BE_LOG(ERR, "Can not get mem table\n"); + return -1; + } + + if (rte_emudev_get_queue_info(dev->dev_id, + RTE_IAVF_EMU_ADMINQ_RXQ, &q_info)) { + IAVF_BE_LOG(ERR, "Can not get queue info of qid %d\n", + RTE_IAVF_EMU_ADMINQ_RXQ); + return -1; + } + + if (rte_emudev_get_irq_info(dev->dev_id, q_info.irq_vector, &irq_info)) { + IAVF_BE_LOG(ERR, "Can not get irq info of qid %d\n", + RTE_IAVF_EMU_ADMINQ_RXQ); + return -1; + } + + /* TODO: Lan queue info update */ + adapter->cq_irqfd = irq_info.eventfd; + rte_atomic32_set(&adapter->irq_enable, irq_info.enable); + + return 0; +} + +static int +iavfbe_lock_dp(struct rte_emudev *dev, int lock) +{ + struct iavfbe_adapter *adapter = + (struct iavfbe_adapter *)dev->backend_priv; + + /* Acquire/Release lock of control queue and lan queue */ + + if (lock) { + /* TODO: Lan queue lock */ + rte_spinlock_lock(&adapter->cq_info.asq.access_lock); + rte_spinlock_lock(&adapter->cq_info.arq.access_lock); + } else { + /* TODO: Lan queue unlock */ + rte_spinlock_unlock(&adapter->cq_info.asq.access_lock); + rte_spinlock_unlock(&adapter->cq_info.arq.access_lock); + } + + return 0; +} + +void +iavfbe_reset_asq(struct iavfbe_adapter *adapter, bool lock) +{ + struct iavfbe_control_q *q; + + q = &adapter->cq_info.asq; + + if (lock) + rte_spinlock_lock(&q->access_lock); + + if (q->aq_req) + memset(q->aq_req, 0, IAVF_BE_AQ_BUF_SZ); + memset(&q->q_info, 0, sizeof(q->q_info)); + q->ring = NULL; + q->p_ring_addr = 0; + q->len = 0; + q->next_to_clean = 0; + q->cmd_retval = 0; + if (q->head) + IAVFBE_WRITE_32(q->head, 0); + + /* Do not reset tail as it init by FE */ + + if (lock) + rte_spinlock_unlock(&q->access_lock); + +} + +void +iavfbe_reset_arq(struct iavfbe_adapter *adapter, bool lock) +{ + struct iavfbe_control_q *q; + + q = &adapter->cq_info.arq; + + if (lock) + rte_spinlock_lock(&q->access_lock); + + memset(&q->q_info, 0, sizeof(q->q_info)); + q->ring = NULL; + q->p_ring_addr = 0; + q->len = 0; + q->next_to_use = 0; + if (q->head) + IAVFBE_WRITE_32(q->head, 0); + + /* Do not reset tail as it init by FE */ + + if (lock) + rte_spinlock_unlock(&q->access_lock); + +} + +static int +iavfbe_reset_device(struct rte_emudev *dev) +{ + struct iavfbe_adapter *adapter = + (struct iavfbe_adapter *)dev->backend_priv; + + /* Lock has been acquired by lock_dp */ + /* TODO: reset all queues */ + iavfbe_reset_asq(adapter, false); + iavfbe_reset_arq(adapter, false); + + adapter->link_up = 0; + adapter->unicast_promisc = true; + adapter->multicast_promisc = true; + adapter->vlan_filter = false; + adapter->vlan_strip = false; + adapter->cq_irqfd = -1; + adapter->adapter_stopped = 1; + + return 0; +} + static inline int save_str(const char *key __rte_unused, const char *value, void *extra_args) @@ -146,6 +398,34 @@ set_mac(const char *key __rte_unused, const char *value, void *extra_args) return 0; } +static int +iavfbe_driver_admq_session_start(struct rte_eth_dev *eth_dev) +{ + struct iavfbe_adapter *adapter = + IAVFBE_DEV_PRIVATE_TO_ADAPTER(eth_dev->data->dev_private); + int ret; + + adapter->thread_status = 1; + ret = pthread_create(&adapter->thread_id, NULL, + (void *)iavfbe_handle_virtchnl_msg, + eth_dev); + if (ret) { + IAVF_BE_LOG(ERR, "Can't create a thread\n"); + adapter->thread_status = 0; + } + return ret; +} + +static void +iavfbe_driver_admq_session_stop(struct rte_eth_dev *eth_dev) +{ + struct iavfbe_adapter *adapter = + IAVFBE_DEV_PRIVATE_TO_ADAPTER(eth_dev->data->dev_private); + + adapter->thread_status = 0; + pthread_join(adapter->thread_id, NULL); +} + static int iavfbe_init_adapter(struct rte_eth_dev *eth_dev, struct rte_emudev *emu_dev, @@ -177,8 +457,44 @@ iavfbe_init_adapter(struct rte_eth_dev *eth_dev, goto err_info; adapter->nb_qps = conf->qp_num; + + adapter->cq_info.asq.aq_req = + rte_zmalloc_socket("iavfbe", IAVF_BE_AQ_BUF_SZ, 0, + eth_dev->device->numa_node); + if (!adapter->cq_info.asq.aq_req) { + IAVF_BE_LOG(ERR, "Fail to allocate buffer for" + " control queue request"); + ret = -ENOMEM; + goto err_aq; + } + + /* Init lock */ + rte_spinlock_init(&adapter->cq_info.asq.access_lock); + rte_spinlock_init(&adapter->cq_info.arq.access_lock); + + adapter->unicast_promisc = true; + adapter->multicast_promisc = true; + adapter->vlan_filter = false; + adapter->vlan_strip = false; + + /* No need to map region or init admin queue here now. They would be + * done when emu device is ready.*/ + + /* Currently RSS is not necessary for device emulator */ + + /* Subscribe event from emulated avf device */ + rte_emudev_subscribe_event(emu_dev->dev_id, &iavfbe_notify_ops); + + /* Create a thread for virtchnnl command process */ + if (iavfbe_driver_admq_session_start(eth_dev)) { + IAVF_BE_LOG(ERR, "iavfbe driver adminq session start failed"); + goto err_thread; + } + return 0; +err_thread: +err_aq: err_info: rte_free(conf); return ret; @@ -190,6 +506,7 @@ iavfbe_destroy_adapter(struct rte_eth_dev *dev) struct iavfbe_adapter *adapter = IAVFBE_DEV_PRIVATE_TO_ADAPTER(dev->data->dev_private); + iavfbe_driver_admq_session_stop(dev); if (adapter->emu_dev) { adapter->emu_dev->backend_priv = NULL; rte_wmb(); diff --git a/drivers/net/iavf_be/iavf_be_vchnl.c b/drivers/net/iavf_be/iavf_be_vchnl.c new file mode 100644 index 0000000000..646c967252 --- /dev/null +++ b/drivers/net/iavf_be/iavf_be_vchnl.c @@ -0,0 +1,273 @@ +/* SPDX-License-Identifier: BSD-3-Clause + * Copyright(c) 2020 Intel Corporation + */ + +#include +#include +#include +#include + +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include + +#include "iavf_be.h" + +__rte_unused static int +iavfbe_send_msg_to_vf(struct iavfbe_adapter *adapter, + uint32_t opcode, + uint32_t retval, + uint8_t *msg, + uint16_t msglen) +{ + struct iavfbe_control_q *arq = &adapter->cq_info.arq; + struct iavf_aq_desc *desc; + enum iavf_status status = IAVF_SUCCESS; + uint32_t dma_buff_low, dma_buff_high; + uint16_t ntu; + + if (msglen > IAVF_BE_AQ_BUF_SZ) { + IAVF_BE_LOG(ERR, "ARQ: msg is tool long: %u\n", msglen); + status = IAVF_ERR_INVALID_SIZE; + goto arq_send_error; + } + + rte_spinlock_lock(&arq->access_lock); + + ntu = arq->next_to_use; + if (ntu == IAVFBE_READ_32(arq->tail)) { + IAVF_BE_LOG(ERR, "ARQ: No free desc\n"); + status = IAVF_ERR_QUEUE_EMPTY; + goto arq_send_error; + } + desc = &arq->ring[ntu]; + dma_buff_low = LE32_TO_CPU(desc->params.external.addr_low); + dma_buff_high = LE32_TO_CPU(desc->params.external.addr_high); + + /* Prepare descriptor */ + memset((void *)desc, 0, sizeof(struct iavf_aq_desc)); + desc->opcode = CPU_TO_LE16(iavf_aqc_opc_send_msg_to_vf); + + desc->flags = CPU_TO_LE16(IAVF_AQ_FLAG_SI); + desc->cookie_high = CPU_TO_LE32(opcode); + desc->cookie_low = CPU_TO_LE32(retval); + + if (msg && msglen) { + void *buf_va; + uint64_t buf_sz = msglen; + + desc->flags |= CPU_TO_LE16((uint16_t)(IAVF_AQ_FLAG_BUF + | IAVF_AQ_FLAG_RD)); + if (msglen > IAVF_AQ_LARGE_BUF) + desc->flags |= CPU_TO_LE16((uint16_t)IAVF_AQ_FLAG_LB); + desc->datalen = CPU_TO_LE16(msglen); + + buf_va = (void *)(uintptr_t)rte_iavf_emu_get_dma_vaddr( + adapter->mem_table, + IAVF_BE_32_TO_64(dma_buff_high, dma_buff_low), + &buf_sz); + if (buf_sz != msglen) + goto arq_send_error; + + rte_memcpy(buf_va, msg, msglen); + } + rte_wmb(); + + ntu++; + if (ntu == arq->len) + ntu = 0; + arq->next_to_use = ntu; + IAVFBE_WRITE_32(arq->head, arq->next_to_use); + +arq_send_error: + rte_spinlock_unlock(&arq->access_lock); + return status; +} + +/* Read data in admin queue to get msg from vf driver */ +static enum iavf_status +iavfbe_read_msg_from_vf(struct iavfbe_adapter *adapter, + struct iavf_arq_event_info *event) +{ + struct iavfbe_control_q *asq = &adapter->cq_info.asq; + struct iavf_aq_desc *desc; + enum virtchnl_ops opcode; + uint16_t ntc; + uint16_t datalen; + uint16_t flags; + int ret = IAVF_SUCCESS; + + rte_spinlock_lock(&asq->access_lock); + + ntc = asq->next_to_clean; + + /* pre-clean the event info */ + memset(&event->desc, 0, sizeof(event->desc)); + event->msg_len = 0; + + if (ntc == IAVFBE_READ_32(asq->tail)) { + /* nothing to do */ + ret = IAVF_ERR_ADMIN_QUEUE_NO_WORK; + goto end; + } + /* now get the next descriptor */ + desc = &asq->ring[ntc]; + rte_memcpy(&event->desc, desc, sizeof(struct iavf_aq_desc)); + flags = LE16_TO_CPU(desc->flags); + datalen = LE16_TO_CPU(desc->datalen); + if (flags & IAVF_AQ_FLAG_RD) { + if (datalen > event->buf_len) { + ret = IAVF_ERR_BUF_TOO_SHORT; + goto end; + } else { + uint32_t reg1 = 0; + uint32_t reg2 = 0; + void *buf_va; + uint64_t buf_sz = datalen; + + event->msg_len = datalen; + reg1 = LE32_TO_CPU(desc->params.external.addr_low); + reg2 = LE32_TO_CPU(desc->params.external.addr_high); + buf_va = (void *)(uintptr_t)rte_iavf_emu_get_dma_vaddr( + adapter->mem_table, + IAVF_BE_32_TO_64(reg2, reg1), &buf_sz); + rte_memcpy(event->msg_buf, buf_va, event->msg_len); + } + } + + ntc++; + if (ntc == asq->len) + ntc = 0; + asq->next_to_clean = ntc; + + /* Write back to head and Desc with Flags.DD and Flags.CMP */ + desc->flags |= IAVF_AQ_FLAG_DD | IAVF_AQ_FLAG_CMP; + rte_wmb(); + + IAVFBE_WRITE_32(asq->head, asq->next_to_clean); + opcode = (enum virtchnl_ops)rte_le_to_cpu_32(event->desc.cookie_high); + asq->cmd_retval = (enum virtchnl_status_code) + rte_le_to_cpu_32(event->desc.cookie_low); + + IAVF_BE_LOG(DEBUG, "AQ from pf carries opcode %u,virtchnl_op %u retval %d", + event->desc.opcode, opcode, asq->cmd_retval); +end: + rte_spinlock_unlock(&asq->access_lock); + + return ret; +} + +static inline int +iavfbe_control_queue_remap(struct iavfbe_adapter *adapter, + struct iavfbe_control_q *asq, + struct iavfbe_control_q *arq) +{ + struct rte_emudev_q_info *asq_info; + struct rte_emudev_q_info *arq_info; + uint64_t len; + int ret; + + asq_info = &adapter->cq_info.asq.q_info; + arq_info = &adapter->cq_info.arq.q_info; + + ret = rte_emudev_get_queue_info(adapter->edev_id, + RTE_IAVF_EMU_ADMINQ_TXQ, + asq_info); + if (ret) + return IAVF_ERR_NOT_READY; + + ret = rte_emudev_get_queue_info(adapter->edev_id, + RTE_IAVF_EMU_ADMINQ_RXQ, + arq_info); + if (ret) + return IAVF_ERR_NOT_READY; + + rte_spinlock_lock(&asq->access_lock); + + asq->p_ring_addr = asq_info->base; + asq->len = asq_info->size; + len = asq->len * sizeof(struct iavf_aq_desc); + asq->ring = (void *)(uintptr_t)rte_iavf_emu_get_dma_vaddr( + adapter->mem_table, + asq->p_ring_addr, &len); + rte_spinlock_unlock(&asq->access_lock); + + rte_spinlock_lock(&arq->access_lock); + arq->p_ring_addr = arq_info->base; + arq->len = arq_info->size; + len = arq->len * sizeof(struct iavf_aq_desc); + arq->ring = (void *)(uintptr_t)rte_iavf_emu_get_dma_vaddr( + adapter->mem_table, + arq->p_ring_addr, &len); + rte_spinlock_unlock(&arq->access_lock); + + return 0; +} + +void +iavfbe_handle_virtchnl_msg(void *arg) +{ + struct rte_eth_dev *dev = (struct rte_eth_dev *)arg; + struct iavfbe_adapter *adapter = + IAVFBE_DEV_PRIVATE_TO_ADAPTER(dev->data->dev_private); + struct iavfbe_control_q *arq = &adapter->cq_info.arq; + struct iavfbe_control_q *asq = &adapter->cq_info.asq; + struct iavf_arq_event_info info; + uint16_t aq_opc; + int ret; + + info.buf_len = IAVF_BE_AQ_BUF_SZ; + info.msg_buf = adapter->cq_info.asq.aq_req; + + while (adapter->thread_status) { + rte_delay_us_sleep(3000); /* sleep for 3 ms*/ + /* Check if control queue is initilized */ + if (adapter->started == 0) + continue; + + /* remap every time */ + ret = iavfbe_control_queue_remap(adapter, asq, arq); + if (ret || + !(asq->p_ring_addr && asq->len && asq->ring) || + !(arq->p_ring_addr && arq->len && arq->ring)) + continue; + + if (asq->next_to_clean == IAVFBE_READ_32(asq->tail)) + /* nothing to do */ + continue; + + ret = iavfbe_read_msg_from_vf(adapter, &info); + if (ret != IAVF_SUCCESS) { + IAVF_BE_LOG(DEBUG, "Failed to read msg" + "from AdminQ"); + break; + } + aq_opc = rte_le_to_cpu_16(info.desc.opcode); + + switch (aq_opc) { + case iavf_aqc_opc_send_msg_to_pf: + /* Process msg from VF BE*/ + break; + case iavf_aqc_opc_queue_shutdown: + iavfbe_reset_arq(adapter, true); + break; + case 0: + IAVF_BE_LOG(DEBUG, "NULL Request ignored"); + break; + default: + IAVF_BE_LOG(ERR, "Unexpected Request 0x%04x ignored ", + aq_opc); + break; + } + } + pthread_exit(0); +} diff --git a/drivers/net/iavf_be/meson.build b/drivers/net/iavf_be/meson.build index 24c625fa18..be13a2e492 100644 --- a/drivers/net/iavf_be/meson.build +++ b/drivers/net/iavf_be/meson.build @@ -9,4 +9,5 @@ deps += ['bus_vdev', 'common_iavf', 'vfio_user', 'emu_iavf'] sources = files( 'iavf_be_ethdev.c', + 'iavf_be_vchnl.c', )