From mboxrd@z Thu Jan 1 00:00:00 1970 Return-Path: Received: from dpdk.org (dpdk.org [92.243.14.124]) by inbox.dpdk.org (Postfix) with ESMTP id DBCF9A04BA; Thu, 1 Oct 2020 17:38:46 +0200 (CEST) Received: from [92.243.14.124] (localhost [127.0.0.1]) by dpdk.org (Postfix) with ESMTP id A78441D539; Thu, 1 Oct 2020 17:38:45 +0200 (CEST) Received: from us-smtp-delivery-124.mimecast.com (us-smtp-delivery-124.mimecast.com [216.205.24.124]) by dpdk.org (Postfix) with ESMTP id AF18F1C1C3 for ; Thu, 1 Oct 2020 17:38:43 +0200 (CEST) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=redhat.com; s=mimecast20190719; t=1601566722; h=from:from:reply-to:subject:subject:date:date:message-id:message-id: to:to:cc:cc:mime-version:mime-version:content-type:content-type: content-transfer-encoding:content-transfer-encoding: in-reply-to:in-reply-to:references:references:autocrypt:autocrypt; bh=IkLTtWhg3eYMuax18jaUJdDU7KjrnSqOK0ZlocZ0Xco=; b=NHguR3VOnVN/FaIhinp326J6DCE5VL0bSIxH7XDELkhaF34gY9Gd22zrwfJawwKAR38koS KpF6Eyrr9j6dDycye6v8LrzPcqWKVgcMohtLtxRoJxwJRmYmKDL6d36v3rI+av1IIe7hIk l0izq5NCiuL78WSDAaZRo++Wmo4XSbA= Received: from mimecast-mx01.redhat.com (mimecast-mx01.redhat.com [209.132.183.4]) (Using TLS) by relay.mimecast.com with ESMTP id us-mta-447-Glhf5FdkMsC6LuZ2kbQiWA-1; Thu, 01 Oct 2020 11:38:40 -0400 X-MC-Unique: Glhf5FdkMsC6LuZ2kbQiWA-1 Received: from smtp.corp.redhat.com (int-mx01.intmail.prod.int.phx2.redhat.com [10.5.11.11]) (using TLSv1.2 with cipher AECDH-AES256-SHA (256/256 bits)) (No client certificate requested) by mimecast-mx01.redhat.com (Postfix) with ESMTPS id A42901015ED6; Thu, 1 Oct 2020 15:38:38 +0000 (UTC) Received: from [10.36.110.36] (unknown [10.36.110.36]) by smtp.corp.redhat.com (Postfix) with ESMTPS id 124A77880A; Thu, 1 Oct 2020 15:38:35 +0000 (UTC) To: Nicolas Chautru , dev@dpdk.org, akhil.goyal@nxp.com Cc: bruce.richardson@intel.com, rosen.xu@intel.com, trix@redhat.com, ferruh.yigit@intel.com, tianjiao.liu@intel.com References: <1597796731-57841-12-git-send-email-nicolas.chautru@intel.com> <1601522084-151443-1-git-send-email-nicolas.chautru@intel.com> <1601522084-151443-5-git-send-email-nicolas.chautru@intel.com> From: Maxime Coquelin Autocrypt: addr=maxime.coquelin@redhat.com; keydata= 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 Mwqu3GQ= Message-ID: <761f5a8b-bade-87c6-cd42-e899e1df3913@redhat.com> Date: Thu, 1 Oct 2020 17:38:33 +0200 User-Agent: Mozilla/5.0 (X11; Linux x86_64; rv:68.0) Gecko/20100101 Thunderbird/68.10.0 MIME-Version: 1.0 In-Reply-To: <1601522084-151443-5-git-send-email-nicolas.chautru@intel.com> X-Scanned-By: MIMEDefang 2.79 on 10.5.11.11 Authentication-Results: relay.mimecast.com; auth=pass smtp.auth=CUSA124A263 smtp.mailfrom=maxime.coquelin@redhat.com X-Mimecast-Spam-Score: 0 X-Mimecast-Originator: redhat.com Content-Type: text/plain; charset=utf-8 Content-Language: en-US Content-Transfer-Encoding: 8bit Subject: Re: [dpdk-dev] [PATCH v10 04/10] baseband/acc100: add queue configuration 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" On 10/1/20 5:14 AM, Nicolas Chautru wrote: > Adding function to create and configure queues for > the device. Still no capability. > > Signed-off-by: Nicolas Chautru > Reviewed-by: Rosen Xu > Acked-by: Liu Tianjiao > --- > drivers/baseband/acc100/rte_acc100_pmd.c | 438 ++++++++++++++++++++++++++++++- > drivers/baseband/acc100/rte_acc100_pmd.h | 45 ++++ > 2 files changed, 482 insertions(+), 1 deletion(-) > > diff --git a/drivers/baseband/acc100/rte_acc100_pmd.c b/drivers/baseband/acc100/rte_acc100_pmd.c > index 98a17b3..709a7af 100644 > --- a/drivers/baseband/acc100/rte_acc100_pmd.c > +++ b/drivers/baseband/acc100/rte_acc100_pmd.c > @@ -26,6 +26,22 @@ > RTE_LOG_REGISTER(acc100_logtype, pmd.bb.acc100, NOTICE); > #endif > > +/* Write to MMIO register address */ > +static inline void > +mmio_write(void *addr, uint32_t value) > +{ > + *((volatile uint32_t *)(addr)) = rte_cpu_to_le_32(value); > +} > + > +/* Write a register of a ACC100 device */ > +static inline void > +acc100_reg_write(struct acc100_device *d, uint32_t offset, uint32_t payload) > +{ > + void *reg_addr = RTE_PTR_ADD(d->mmio_base, offset); > + mmio_write(reg_addr, payload); > + usleep(ACC100_LONG_WAIT); Is it really needed to sleep after the MMIO write access? > +} > + > /* Read a register of a ACC100 device */ > static inline uint32_t > acc100_reg_read(struct acc100_device *d, uint32_t offset) > @@ -36,6 +52,22 @@ > return rte_le_to_cpu_32(ret); > } > > +/* Basic Implementation of Log2 for exact 2^N */ > +static inline uint32_t > +log2_basic(uint32_t value) > +{ > + return (value == 0) ? 0 : rte_bsf32(value); > +} > + > +/* Calculate memory alignment offset assuming alignment is 2^N */ > +static inline uint32_t > +calc_mem_alignment_offset(void *unaligned_virt_mem, uint32_t alignment) > +{ > + rte_iova_t unaligned_phy_mem = rte_malloc_virt2iova(unaligned_virt_mem); > + return (uint32_t)(alignment - > + (unaligned_phy_mem & (alignment-1))); > +} > + > /* Calculate the offset of the enqueue register */ > static inline uint32_t > queue_offset(bool pf_device, uint8_t vf_id, uint8_t qgrp_id, uint16_t aq_id) > @@ -208,10 +240,411 @@ > acc100_conf->q_dl_5g.aq_depth_log2); > } > > +static void > +free_base_addresses(void **base_addrs, int size) > +{ > + int i; > + for (i = 0; i < size; i++) > + rte_free(base_addrs[i]); > +} > + > +static inline uint32_t > +get_desc_len(void) > +{ > + return sizeof(union acc100_dma_desc); > +} > + > +/* Allocate the 2 * 64MB block for the sw rings */ > +static int > +alloc_2x64mb_sw_rings_mem(struct rte_bbdev *dev, struct acc100_device *d, > + int socket) > +{ > + uint32_t sw_ring_size = ACC100_SIZE_64MBYTE; > + d->sw_rings_base = rte_zmalloc_socket(dev->device->driver->name, > + 2 * sw_ring_size, RTE_CACHE_LINE_SIZE, socket); > + if (d->sw_rings_base == NULL) { > + rte_bbdev_log(ERR, "Failed to allocate memory for %s:%u", > + dev->device->driver->name, > + dev->data->dev_id); > + return -ENOMEM; > + } > + memset(d->sw_rings_base, 0, ACC100_SIZE_64MBYTE); Having used zmalloc, the memset looks overkill. Also, it does not clear all the allocated are, don't know if this is expected. > + uint32_t next_64mb_align_offset = calc_mem_alignment_offset( > + d->sw_rings_base, ACC100_SIZE_64MBYTE); > + d->sw_rings = RTE_PTR_ADD(d->sw_rings_base, next_64mb_align_offset); > + d->sw_rings_phys = rte_malloc_virt2iova(d->sw_rings_base) + > + next_64mb_align_offset; sw_rings_phys should be renamed to sw_rings_iova, as it could be a VA if IOVA_AS_VA more is used. > + d->sw_ring_size = ACC100_MAX_QUEUE_DEPTH * get_desc_len(); > + d->sw_ring_max_depth = d->sw_ring_size / get_desc_len(); d->sw_ring_max_depth = ACC100_MAX_QUEUE_DEPTH; > + > + return 0; > +} > + > +/* Attempt to allocate minimised memory space for sw rings */ > +static void > +alloc_sw_rings_min_mem(struct rte_bbdev *dev, struct acc100_device *d, > + uint16_t num_queues, int socket) > +{ > + rte_iova_t sw_rings_base_phy, next_64mb_align_addr_phy; Same comment regarding phys vs. iova in this function. > + uint32_t next_64mb_align_offset; > + rte_iova_t sw_ring_phys_end_addr; > + void *base_addrs[ACC100_SW_RING_MEM_ALLOC_ATTEMPTS]; > + void *sw_rings_base; > + int i = 0; > + uint32_t q_sw_ring_size = ACC100_MAX_QUEUE_DEPTH * get_desc_len(); > + uint32_t dev_sw_ring_size = q_sw_ring_size * num_queues; > + > + /* Find an aligned block of memory to store sw rings */ > + while (i < ACC100_SW_RING_MEM_ALLOC_ATTEMPTS) { > + /* > + * sw_ring allocated memory is guaranteed to be aligned to > + * q_sw_ring_size at the condition that the requested size is > + * less than the page size > + */ > + sw_rings_base = rte_zmalloc_socket( > + dev->device->driver->name, > + dev_sw_ring_size, q_sw_ring_size, socket); > + > + if (sw_rings_base == NULL) { > + rte_bbdev_log(ERR, > + "Failed to allocate memory for %s:%u", > + dev->device->driver->name, > + dev->data->dev_id); > + break; > + } > + > + sw_rings_base_phy = rte_malloc_virt2iova(sw_rings_base); > + next_64mb_align_offset = calc_mem_alignment_offset( > + sw_rings_base, ACC100_SIZE_64MBYTE); > + next_64mb_align_addr_phy = sw_rings_base_phy + > + next_64mb_align_offset; > + sw_ring_phys_end_addr = sw_rings_base_phy + dev_sw_ring_size; > + > + /* Check if the end of the sw ring memory block is before the > + * start of next 64MB aligned mem address > + */ > + if (sw_ring_phys_end_addr < next_64mb_align_addr_phy) { > + d->sw_rings_phys = sw_rings_base_phy; > + d->sw_rings = sw_rings_base; > + d->sw_rings_base = sw_rings_base; > + d->sw_ring_size = q_sw_ring_size; > + d->sw_ring_max_depth = ACC100_MAX_QUEUE_DEPTH; > + break; > + } > + /* Store the address of the unaligned mem block */ > + base_addrs[i] = sw_rings_base; > + i++; > + } > + > + /* Free all unaligned blocks of mem allocated in the loop */ > + free_base_addresses(base_addrs, i); > +} > + > + > +/* Allocate 64MB memory used for all software rings */ > +static int > +acc100_setup_queues(struct rte_bbdev *dev, uint16_t num_queues, int socket_id) > +{ > + uint32_t phys_low, phys_high, payload; > + struct acc100_device *d = dev->data->dev_private; > + const struct acc100_registry_addr *reg_addr; > + > + if (d->pf_device && !d->acc100_conf.pf_mode_en) { > + rte_bbdev_log(NOTICE, > + "%s has PF mode disabled. This PF can't be used.", > + dev->data->name); > + return -ENODEV; > + } > + > + alloc_sw_rings_min_mem(dev, d, num_queues, socket_id); > + > + /* If minimal memory space approach failed, then allocate > + * the 2 * 64MB block for the sw rings > + */ > + if (d->sw_rings == NULL) > + alloc_2x64mb_sw_rings_mem(dev, d, socket_id); > + > + if (d->sw_rings == NULL) { > + rte_bbdev_log(NOTICE, > + "Failure allocating sw_rings memory"); > + return -ENODEV; > + } > + > + /* Configure ACC100 with the base address for DMA descriptor rings > + * Same descriptor rings used for UL and DL DMA Engines > + * Note : Assuming only VF0 bundle is used for PF mode > + */ > + phys_high = (uint32_t)(d->sw_rings_phys >> 32); > + phys_low = (uint32_t)(d->sw_rings_phys & ~(ACC100_SIZE_64MBYTE-1)); > + > + /* Choose correct registry addresses for the device type */ > + if (d->pf_device) > + reg_addr = &pf_reg_addr; > + else > + reg_addr = &vf_reg_addr; > + > + /* Read the populated cfg from ACC100 registers */ > + fetch_acc100_config(dev); > + > + /* Release AXI from PF */ > + if (d->pf_device) > + acc100_reg_write(d, HWPfDmaAxiControl, 1); > + > + acc100_reg_write(d, reg_addr->dma_ring_ul5g_hi, phys_high); > + acc100_reg_write(d, reg_addr->dma_ring_ul5g_lo, phys_low); > + acc100_reg_write(d, reg_addr->dma_ring_dl5g_hi, phys_high); > + acc100_reg_write(d, reg_addr->dma_ring_dl5g_lo, phys_low); > + acc100_reg_write(d, reg_addr->dma_ring_ul4g_hi, phys_high); > + acc100_reg_write(d, reg_addr->dma_ring_ul4g_lo, phys_low); > + acc100_reg_write(d, reg_addr->dma_ring_dl4g_hi, phys_high); > + acc100_reg_write(d, reg_addr->dma_ring_dl4g_lo, phys_low); > + > + /* > + * Configure Ring Size to the max queue ring size > + * (used for wrapping purpose) > + */ > + payload = log2_basic(d->sw_ring_size / 64); > + acc100_reg_write(d, reg_addr->ring_size, payload); > + > + /* Configure tail pointer for use when SDONE enabled */ > + d->tail_ptrs = rte_zmalloc_socket( > + dev->device->driver->name, > + ACC100_NUM_QGRPS * ACC100_NUM_AQS * sizeof(uint32_t), > + RTE_CACHE_LINE_SIZE, socket_id); > + if (d->tail_ptrs == NULL) { > + rte_bbdev_log(ERR, "Failed to allocate tail ptr for %s:%u", > + dev->device->driver->name, > + dev->data->dev_id); > + rte_free(d->sw_rings); > + return -ENOMEM; > + } > + d->tail_ptr_phys = rte_malloc_virt2iova(d->tail_ptrs); > + > + phys_high = (uint32_t)(d->tail_ptr_phys >> 32); > + phys_low = (uint32_t)(d->tail_ptr_phys); > + acc100_reg_write(d, reg_addr->tail_ptrs_ul5g_hi, phys_high); > + acc100_reg_write(d, reg_addr->tail_ptrs_ul5g_lo, phys_low); > + acc100_reg_write(d, reg_addr->tail_ptrs_dl5g_hi, phys_high); > + acc100_reg_write(d, reg_addr->tail_ptrs_dl5g_lo, phys_low); > + acc100_reg_write(d, reg_addr->tail_ptrs_ul4g_hi, phys_high); > + acc100_reg_write(d, reg_addr->tail_ptrs_ul4g_lo, phys_low); > + acc100_reg_write(d, reg_addr->tail_ptrs_dl4g_hi, phys_high); > + acc100_reg_write(d, reg_addr->tail_ptrs_dl4g_lo, phys_low); > + > + d->harq_layout = rte_zmalloc_socket("HARQ Layout", > + ACC100_HARQ_LAYOUT * sizeof(*d->harq_layout), > + RTE_CACHE_LINE_SIZE, dev->data->socket_id); > + if (d->harq_layout == NULL) { > + rte_bbdev_log(ERR, "Failed to allocate harq_layout for %s:%u", > + dev->device->driver->name, > + dev->data->dev_id); > + rte_free(d->sw_rings); > + return -ENOMEM; > + } > + > + /* Mark as configured properly */ > + d->configured = true; > + > + rte_bbdev_log_debug( > + "ACC100 (%s) configured sw_rings = %p, sw_rings_phys = %#" > + PRIx64, dev->data->name, d->sw_rings, d->sw_rings_phys); > + > + return 0; > +} > + > /* Free 64MB memory used for software rings */ Seems to be 2x64MB are allocated. > static int > -acc100_dev_close(struct rte_bbdev *dev __rte_unused) > +acc100_dev_close(struct rte_bbdev *dev) > { > + struct acc100_device *d = dev->data->dev_private; > + if (d->sw_rings_base != NULL) { > + rte_free(d->tail_ptrs); > + rte_free(d->sw_rings_base); > + d->sw_rings_base = NULL; > + } > + usleep(ACC100_LONG_WAIT); This sleep looks weird, it would need a comment if it is really needed. > + return 0; > +} > + > + > +/** > + * Report a ACC100 queue index which is free > + * Return 0 to 16k for a valid queue_idx or -1 when no queue is available > + * Note : Only supporting VF0 Bundle for PF mode > + */ > +static int > +acc100_find_free_queue_idx(struct rte_bbdev *dev, > + const struct rte_bbdev_queue_conf *conf) > +{ > + struct acc100_device *d = dev->data->dev_private; > + int op_2_acc[5] = {0, UL_4G, DL_4G, UL_5G, DL_5G}; > + int acc = op_2_acc[conf->op_type]; > + struct rte_q_topology_t *qtop = NULL; New line. > + qtopFromAcc(&qtop, acc, &(d->acc100_conf)); > + if (qtop == NULL) > + return -1; > + /* Identify matching QGroup Index which are sorted in priority order */ > + uint16_t group_idx = qtop->first_qgroup_index; > + group_idx += conf->priority; > + if (group_idx >= ACC100_NUM_QGRPS || > + conf->priority >= qtop->num_qgroups) { > + rte_bbdev_log(INFO, "Invalid Priority on %s, priority %u", > + dev->data->name, conf->priority); > + return -1; > + } > + /* Find a free AQ_idx */ > + uint16_t aq_idx; > + for (aq_idx = 0; aq_idx < qtop->num_aqs_per_groups; aq_idx++) { > + if (((d->q_assigned_bit_map[group_idx] >> aq_idx) & 0x1) == 0) { > + /* Mark the Queue as assigned */ > + d->q_assigned_bit_map[group_idx] |= (1 << aq_idx); > + /* Report the AQ Index */ > + return (group_idx << ACC100_GRP_ID_SHIFT) + aq_idx; > + } > + } > + rte_bbdev_log(INFO, "Failed to find free queue on %s, priority %u", > + dev->data->name, conf->priority); > + return -1; > +} > + > +/* Setup ACC100 queue */ > +static int > +acc100_queue_setup(struct rte_bbdev *dev, uint16_t queue_id, > + const struct rte_bbdev_queue_conf *conf) > +{ > + struct acc100_device *d = dev->data->dev_private; > + struct acc100_queue *q; > + int16_t q_idx; > + > + /* Allocate the queue data structure. */ > + q = rte_zmalloc_socket(dev->device->driver->name, sizeof(*q), > + RTE_CACHE_LINE_SIZE, conf->socket); > + if (q == NULL) { > + rte_bbdev_log(ERR, "Failed to allocate queue memory"); > + return -ENOMEM; > + } > + > + q->d = d; > + q->ring_addr = RTE_PTR_ADD(d->sw_rings, (d->sw_ring_size * queue_id)); You might want to ensure d is not NULL before dereferencing it. > + q->ring_addr_phys = d->sw_rings_phys + (d->sw_ring_size * queue_id); > + > + /* Prepare the Ring with default descriptor format */ > + union acc100_dma_desc *desc = NULL; > + unsigned int desc_idx, b_idx; > + int fcw_len = (conf->op_type == RTE_BBDEV_OP_LDPC_ENC ? > + ACC100_FCW_LE_BLEN : (conf->op_type == RTE_BBDEV_OP_TURBO_DEC ? > + ACC100_FCW_TD_BLEN : ACC100_FCW_LD_BLEN)); > + > + for (desc_idx = 0; desc_idx < d->sw_ring_max_depth; desc_idx++) { > + desc = q->ring_addr + desc_idx; > + desc->req.word0 = ACC100_DMA_DESC_TYPE; > + desc->req.word1 = 0; /**< Timestamp */ > + desc->req.word2 = 0; > + desc->req.word3 = 0; > + uint64_t fcw_offset = (desc_idx << 8) + ACC100_DESC_FCW_OFFSET; > + desc->req.data_ptrs[0].address = q->ring_addr_phys + fcw_offset; > + desc->req.data_ptrs[0].blen = fcw_len; > + desc->req.data_ptrs[0].blkid = ACC100_DMA_BLKID_FCW; > + desc->req.data_ptrs[0].last = 0; > + desc->req.data_ptrs[0].dma_ext = 0; > + for (b_idx = 1; b_idx < ACC100_DMA_MAX_NUM_POINTERS - 1; > + b_idx++) { > + desc->req.data_ptrs[b_idx].blkid = ACC100_DMA_BLKID_IN; > + desc->req.data_ptrs[b_idx].last = 1; > + desc->req.data_ptrs[b_idx].dma_ext = 0; > + b_idx++; > + desc->req.data_ptrs[b_idx].blkid = > + ACC100_DMA_BLKID_OUT_ENC; > + desc->req.data_ptrs[b_idx].last = 1; > + desc->req.data_ptrs[b_idx].dma_ext = 0; > + } > + /* Preset some fields of LDPC FCW */ > + desc->req.fcw_ld.FCWversion = ACC100_FCW_VER; > + desc->req.fcw_ld.gain_i = 1; > + desc->req.fcw_ld.gain_h = 1; > + } > + > + q->lb_in = rte_zmalloc_socket(dev->device->driver->name, > + RTE_CACHE_LINE_SIZE, > + RTE_CACHE_LINE_SIZE, conf->socket); > + if (q->lb_in == NULL) { > + rte_bbdev_log(ERR, "Failed to allocate lb_in memory"); > + rte_free(q); > + return -ENOMEM; > + } > + q->lb_in_addr_phys = rte_malloc_virt2iova(q->lb_in); > + q->lb_out = rte_zmalloc_socket(dev->device->driver->name, > + RTE_CACHE_LINE_SIZE, > + RTE_CACHE_LINE_SIZE, conf->socket); > + if (q->lb_out == NULL) { > + rte_bbdev_log(ERR, "Failed to allocate lb_out memory"); > + rte_free(q->lb_in); > + rte_free(q); > + return -ENOMEM; > + } > + q->lb_out_addr_phys = rte_malloc_virt2iova(q->lb_out); > + > + /* > + * Software queue ring wraps synchronously with the HW when it reaches > + * the boundary of the maximum allocated queue size, no matter what the > + * sw queue size is. This wrapping is guarded by setting the wrap_mask > + * to represent the maximum queue size as allocated at the time when > + * the device has been setup (in configure()). > + * > + * The queue depth is set to the queue size value (conf->queue_size). > + * This limits the occupancy of the queue at any point of time, so that > + * the queue does not get swamped with enqueue requests. > + */ > + q->sw_ring_depth = conf->queue_size; > + q->sw_ring_wrap_mask = d->sw_ring_max_depth - 1; > + > + q->op_type = conf->op_type; > + > + q_idx = acc100_find_free_queue_idx(dev, conf); > + if (q_idx == -1) { > + rte_free(q->lb_in); > + rte_free(q->lb_out); > + rte_free(q); > + return -1; > + } > + > + q->qgrp_id = (q_idx >> ACC100_GRP_ID_SHIFT) & 0xF; > + q->vf_id = (q_idx >> ACC100_VF_ID_SHIFT) & 0x3F; > + q->aq_id = q_idx & 0xF; > + q->aq_depth = (conf->op_type == RTE_BBDEV_OP_TURBO_DEC) ? > + (1 << d->acc100_conf.q_ul_4g.aq_depth_log2) : > + (1 << d->acc100_conf.q_dl_4g.aq_depth_log2); > + > + q->mmio_reg_enqueue = RTE_PTR_ADD(d->mmio_base, > + queue_offset(d->pf_device, > + q->vf_id, q->qgrp_id, q->aq_id)); > + > + rte_bbdev_log_debug( > + "Setup dev%u q%u: qgrp_id=%u, vf_id=%u, aq_id=%u, aq_depth=%u, mmio_reg_enqueue=%p", > + dev->data->dev_id, queue_id, q->qgrp_id, q->vf_id, > + q->aq_id, q->aq_depth, q->mmio_reg_enqueue); > + > + dev->data->queues[queue_id].queue_private = q; > + return 0; > +} > + > +/* Release ACC100 queue */ > +static int > +acc100_queue_release(struct rte_bbdev *dev, uint16_t q_id) > +{ > + struct acc100_device *d = dev->data->dev_private; > + struct acc100_queue *q = dev->data->queues[q_id].queue_private; > + > + if (q != NULL) { > + /* Mark the Queue as un-assigned */ > + d->q_assigned_bit_map[q->qgrp_id] &= (0xFFFFFFFF - > + (1 << q->aq_id)); > + rte_free(q->lb_in); > + rte_free(q->lb_out); > + rte_free(q); > + dev->data->queues[q_id].queue_private = NULL; > + } > + > return 0; > } > > @@ -262,8 +695,11 @@ > } > > static const struct rte_bbdev_ops acc100_bbdev_ops = { > + .setup_queues = acc100_setup_queues, > .close = acc100_dev_close, > .info_get = acc100_dev_info_get, > + .queue_setup = acc100_queue_setup, > + .queue_release = acc100_queue_release, > }; > > /* ACC100 PCI PF address map */ > diff --git a/drivers/baseband/acc100/rte_acc100_pmd.h b/drivers/baseband/acc100/rte_acc100_pmd.h > index de015ca..2508385 100644 > --- a/drivers/baseband/acc100/rte_acc100_pmd.h > +++ b/drivers/baseband/acc100/rte_acc100_pmd.h > @@ -522,11 +522,56 @@ struct acc100_registry_addr { > .ddr_range = HWVfDmaDdrBaseRangeRoVf, > }; > > +/* Structure associated with each queue. */ > +struct __rte_cache_aligned acc100_queue { > + union acc100_dma_desc *ring_addr; /* Virtual address of sw ring */ > + rte_iova_t ring_addr_phys; /* Physical address of software ring */ > + uint32_t sw_ring_head; /* software ring head */ > + uint32_t sw_ring_tail; /* software ring tail */ > + /* software ring size (descriptors, not bytes) */ > + uint32_t sw_ring_depth; > + /* mask used to wrap enqueued descriptors on the sw ring */ > + uint32_t sw_ring_wrap_mask; > + /* MMIO register used to enqueue descriptors */ > + void *mmio_reg_enqueue; > + uint8_t vf_id; /* VF ID (max = 63) */ > + uint8_t qgrp_id; /* Queue Group ID */ > + uint16_t aq_id; /* Atomic Queue ID */ > + uint16_t aq_depth; /* Depth of atomic queue */ > + uint32_t aq_enqueued; /* Count how many "batches" have been enqueued */ > + uint32_t aq_dequeued; /* Count how many "batches" have been dequeued */ > + uint32_t irq_enable; /* Enable ops dequeue interrupts if set to 1 */ > + struct rte_mempool *fcw_mempool; /* FCW mempool */ > + enum rte_bbdev_op_type op_type; /* Type of this Queue: TE or TD */ > + /* Internal Buffers for loopback input */ > + uint8_t *lb_in; > + uint8_t *lb_out; > + rte_iova_t lb_in_addr_phys; > + rte_iova_t lb_out_addr_phys; > + struct acc100_device *d; > +}; > + > /* Private data structure for each ACC100 device */ > struct acc100_device { > void *mmio_base; /**< Base address of MMIO registers (BAR0) */ > + void *sw_rings_base; /* Base addr of un-aligned memory for sw rings */ > + void *sw_rings; /* 64MBs of 64MB aligned memory for sw rings */ > + rte_iova_t sw_rings_phys; /* Physical address of sw_rings */ > + /* Virtual address of the info memory routed to the this function under > + * operation, whether it is PF or VF. > + */ > + union acc100_harq_layout_data *harq_layout; > + uint32_t sw_ring_size; > uint32_t ddr_size; /* Size in kB */ > + uint32_t *tail_ptrs; /* Base address of response tail pointer buffer */ > + rte_iova_t tail_ptr_phys; /* Physical address of tail pointers */ > + /* Max number of entries available for each queue in device, depending > + * on how many queues are enabled with configure() > + */ > + uint32_t sw_ring_max_depth; > struct acc100_conf acc100_conf; /* ACC100 Initial configuration */ > + /* Bitmap capturing which Queues have already been assigned */ > + uint16_t q_assigned_bit_map[ACC100_NUM_QGRPS]; > bool pf_device; /**< True if this is a PF ACC100 device */ > bool configured; /**< True if this ACC100 device is configured */ > }; >