14610ac93SAndrew Boyer /* SPDX-License-Identifier: BSD-3-Clause
24610ac93SAndrew Boyer * Copyright 2021-2024 Advanced Micro Devices, Inc.
34610ac93SAndrew Boyer */
44610ac93SAndrew Boyer
54610ac93SAndrew Boyer #include <inttypes.h>
64610ac93SAndrew Boyer
74610ac93SAndrew Boyer #include <rte_common.h>
84610ac93SAndrew Boyer #include <rte_malloc.h>
94610ac93SAndrew Boyer #include <rte_bitops.h>
104610ac93SAndrew Boyer
114610ac93SAndrew Boyer #include "ionic_crypto.h"
124610ac93SAndrew Boyer
132c1662bbSAndrew Boyer static int
iocpt_cq_init(struct iocpt_cq * cq,uint16_t num_descs)142c1662bbSAndrew Boyer iocpt_cq_init(struct iocpt_cq *cq, uint16_t num_descs)
152c1662bbSAndrew Boyer {
162c1662bbSAndrew Boyer if (!rte_is_power_of_2(num_descs) ||
172c1662bbSAndrew Boyer num_descs < IOCPT_MIN_RING_DESC ||
182c1662bbSAndrew Boyer num_descs > IOCPT_MAX_RING_DESC) {
192c1662bbSAndrew Boyer IOCPT_PRINT(ERR, "%u descriptors (min: %u max: %u)",
202c1662bbSAndrew Boyer num_descs, IOCPT_MIN_RING_DESC, IOCPT_MAX_RING_DESC);
212c1662bbSAndrew Boyer return -EINVAL;
222c1662bbSAndrew Boyer }
232c1662bbSAndrew Boyer
242c1662bbSAndrew Boyer cq->num_descs = num_descs;
252c1662bbSAndrew Boyer cq->size_mask = num_descs - 1;
262c1662bbSAndrew Boyer cq->tail_idx = 0;
272c1662bbSAndrew Boyer cq->done_color = 1;
282c1662bbSAndrew Boyer
292c1662bbSAndrew Boyer return 0;
302c1662bbSAndrew Boyer }
312c1662bbSAndrew Boyer
322c1662bbSAndrew Boyer static void
iocpt_cq_reset(struct iocpt_cq * cq)3380518852SAndrew Boyer iocpt_cq_reset(struct iocpt_cq *cq)
3480518852SAndrew Boyer {
3580518852SAndrew Boyer cq->tail_idx = 0;
3680518852SAndrew Boyer cq->done_color = 1;
3780518852SAndrew Boyer
3880518852SAndrew Boyer memset(cq->base, 0, sizeof(struct iocpt_nop_comp) * cq->num_descs);
3980518852SAndrew Boyer }
4080518852SAndrew Boyer
4180518852SAndrew Boyer static void
iocpt_cq_map(struct iocpt_cq * cq,void * base,rte_iova_t base_pa)422c1662bbSAndrew Boyer iocpt_cq_map(struct iocpt_cq *cq, void *base, rte_iova_t base_pa)
432c1662bbSAndrew Boyer {
442c1662bbSAndrew Boyer cq->base = base;
452c1662bbSAndrew Boyer cq->base_pa = base_pa;
462c1662bbSAndrew Boyer }
472c1662bbSAndrew Boyer
482c1662bbSAndrew Boyer uint32_t
iocpt_cq_service(struct iocpt_cq * cq,uint32_t work_to_do,iocpt_cq_cb cb,void * cb_arg)492c1662bbSAndrew Boyer iocpt_cq_service(struct iocpt_cq *cq, uint32_t work_to_do,
502c1662bbSAndrew Boyer iocpt_cq_cb cb, void *cb_arg)
512c1662bbSAndrew Boyer {
522c1662bbSAndrew Boyer uint32_t work_done = 0;
532c1662bbSAndrew Boyer
542c1662bbSAndrew Boyer if (work_to_do == 0)
552c1662bbSAndrew Boyer return 0;
562c1662bbSAndrew Boyer
572c1662bbSAndrew Boyer while (cb(cq, cq->tail_idx, cb_arg)) {
582c1662bbSAndrew Boyer cq->tail_idx = Q_NEXT_TO_SRVC(cq, 1);
592c1662bbSAndrew Boyer if (cq->tail_idx == 0)
602c1662bbSAndrew Boyer cq->done_color = !cq->done_color;
612c1662bbSAndrew Boyer
622c1662bbSAndrew Boyer if (++work_done == work_to_do)
632c1662bbSAndrew Boyer break;
642c1662bbSAndrew Boyer }
652c1662bbSAndrew Boyer
662c1662bbSAndrew Boyer return work_done;
672c1662bbSAndrew Boyer }
682c1662bbSAndrew Boyer
692c1662bbSAndrew Boyer static int
iocpt_q_init(struct iocpt_queue * q,uint8_t type,uint32_t index,uint16_t num_descs,uint16_t num_segs,uint32_t socket_id)702c1662bbSAndrew Boyer iocpt_q_init(struct iocpt_queue *q, uint8_t type, uint32_t index,
712c1662bbSAndrew Boyer uint16_t num_descs, uint16_t num_segs, uint32_t socket_id)
722c1662bbSAndrew Boyer {
732c1662bbSAndrew Boyer uint32_t ring_size;
742c1662bbSAndrew Boyer
752c1662bbSAndrew Boyer if (!rte_is_power_of_2(num_descs))
762c1662bbSAndrew Boyer return -EINVAL;
772c1662bbSAndrew Boyer
782c1662bbSAndrew Boyer ring_size = rte_log2_u32(num_descs);
792c1662bbSAndrew Boyer if (ring_size < 2 || ring_size > 16)
802c1662bbSAndrew Boyer return -EINVAL;
812c1662bbSAndrew Boyer
822c1662bbSAndrew Boyer q->type = type;
832c1662bbSAndrew Boyer q->index = index;
842c1662bbSAndrew Boyer q->num_descs = num_descs;
852c1662bbSAndrew Boyer q->num_segs = num_segs;
862c1662bbSAndrew Boyer q->size_mask = num_descs - 1;
872c1662bbSAndrew Boyer q->head_idx = 0;
882c1662bbSAndrew Boyer q->tail_idx = 0;
892c1662bbSAndrew Boyer
902c1662bbSAndrew Boyer q->info = rte_calloc_socket("iocpt",
91*974cbdc3SAndrew Boyer (uint64_t)num_descs * num_segs, sizeof(void *),
922c1662bbSAndrew Boyer rte_mem_page_size(), socket_id);
932c1662bbSAndrew Boyer if (q->info == NULL) {
942c1662bbSAndrew Boyer IOCPT_PRINT(ERR, "Cannot allocate queue info");
952c1662bbSAndrew Boyer return -ENOMEM;
962c1662bbSAndrew Boyer }
972c1662bbSAndrew Boyer
982c1662bbSAndrew Boyer return 0;
992c1662bbSAndrew Boyer }
1002c1662bbSAndrew Boyer
1012c1662bbSAndrew Boyer static void
iocpt_q_reset(struct iocpt_queue * q)10280518852SAndrew Boyer iocpt_q_reset(struct iocpt_queue *q)
10380518852SAndrew Boyer {
10480518852SAndrew Boyer q->head_idx = 0;
10580518852SAndrew Boyer q->tail_idx = 0;
10680518852SAndrew Boyer }
10780518852SAndrew Boyer
10880518852SAndrew Boyer static void
iocpt_q_map(struct iocpt_queue * q,void * base,rte_iova_t base_pa)1092c1662bbSAndrew Boyer iocpt_q_map(struct iocpt_queue *q, void *base, rte_iova_t base_pa)
1102c1662bbSAndrew Boyer {
1112c1662bbSAndrew Boyer q->base = base;
1122c1662bbSAndrew Boyer q->base_pa = base_pa;
1132c1662bbSAndrew Boyer }
1142c1662bbSAndrew Boyer
1152c1662bbSAndrew Boyer static void
iocpt_q_sg_map(struct iocpt_queue * q,void * base,rte_iova_t base_pa)1162c1662bbSAndrew Boyer iocpt_q_sg_map(struct iocpt_queue *q, void *base, rte_iova_t base_pa)
1172c1662bbSAndrew Boyer {
1182c1662bbSAndrew Boyer q->sg_base = base;
1192c1662bbSAndrew Boyer q->sg_base_pa = base_pa;
1202c1662bbSAndrew Boyer }
1212c1662bbSAndrew Boyer
1222c1662bbSAndrew Boyer static void
iocpt_q_free(struct iocpt_queue * q)1232c1662bbSAndrew Boyer iocpt_q_free(struct iocpt_queue *q)
1242c1662bbSAndrew Boyer {
1252c1662bbSAndrew Boyer if (q->info != NULL) {
1262c1662bbSAndrew Boyer rte_free(q->info);
1272c1662bbSAndrew Boyer q->info = NULL;
1282c1662bbSAndrew Boyer }
1292c1662bbSAndrew Boyer }
1302c1662bbSAndrew Boyer
131aacc5f13SAndrew Boyer static void
iocpt_get_abs_stats(const struct iocpt_dev * dev,struct rte_cryptodev_stats * stats)132aacc5f13SAndrew Boyer iocpt_get_abs_stats(const struct iocpt_dev *dev,
133aacc5f13SAndrew Boyer struct rte_cryptodev_stats *stats)
134aacc5f13SAndrew Boyer {
135aacc5f13SAndrew Boyer uint32_t i;
136aacc5f13SAndrew Boyer
137aacc5f13SAndrew Boyer memset(stats, 0, sizeof(*stats));
138aacc5f13SAndrew Boyer
139aacc5f13SAndrew Boyer /* Sum up the per-queue stats counters */
140aacc5f13SAndrew Boyer for (i = 0; i < dev->crypto_dev->data->nb_queue_pairs; i++) {
141aacc5f13SAndrew Boyer struct rte_cryptodev_stats *q_stats = &dev->cryptoqs[i]->stats;
142aacc5f13SAndrew Boyer
143aacc5f13SAndrew Boyer stats->enqueued_count += q_stats->enqueued_count;
144aacc5f13SAndrew Boyer stats->dequeued_count += q_stats->dequeued_count;
145aacc5f13SAndrew Boyer stats->enqueue_err_count += q_stats->enqueue_err_count;
146aacc5f13SAndrew Boyer stats->dequeue_err_count += q_stats->dequeue_err_count;
147aacc5f13SAndrew Boyer }
148aacc5f13SAndrew Boyer }
149aacc5f13SAndrew Boyer
150aacc5f13SAndrew Boyer void
iocpt_get_stats(const struct iocpt_dev * dev,struct rte_cryptodev_stats * stats)151aacc5f13SAndrew Boyer iocpt_get_stats(const struct iocpt_dev *dev, struct rte_cryptodev_stats *stats)
152aacc5f13SAndrew Boyer {
153aacc5f13SAndrew Boyer /* Retrieve the new absolute stats values */
154aacc5f13SAndrew Boyer iocpt_get_abs_stats(dev, stats);
155aacc5f13SAndrew Boyer
156aacc5f13SAndrew Boyer /* Subtract the base stats values to get relative values */
157aacc5f13SAndrew Boyer stats->enqueued_count -= dev->stats_base.enqueued_count;
158aacc5f13SAndrew Boyer stats->dequeued_count -= dev->stats_base.dequeued_count;
159aacc5f13SAndrew Boyer stats->enqueue_err_count -= dev->stats_base.enqueue_err_count;
160aacc5f13SAndrew Boyer stats->dequeue_err_count -= dev->stats_base.dequeue_err_count;
161aacc5f13SAndrew Boyer }
162aacc5f13SAndrew Boyer
163aacc5f13SAndrew Boyer void
iocpt_reset_stats(struct iocpt_dev * dev)164aacc5f13SAndrew Boyer iocpt_reset_stats(struct iocpt_dev *dev)
165aacc5f13SAndrew Boyer {
166aacc5f13SAndrew Boyer uint32_t i;
167aacc5f13SAndrew Boyer
168aacc5f13SAndrew Boyer /* Erase the per-queue stats counters */
169aacc5f13SAndrew Boyer for (i = 0; i < dev->crypto_dev->data->nb_queue_pairs; i++)
170aacc5f13SAndrew Boyer memset(&dev->cryptoqs[i]->stats, 0,
171aacc5f13SAndrew Boyer sizeof(dev->cryptoqs[i]->stats));
172aacc5f13SAndrew Boyer
173aacc5f13SAndrew Boyer /* Update the base stats values */
174aacc5f13SAndrew Boyer iocpt_get_abs_stats(dev, &dev->stats_base);
175aacc5f13SAndrew Boyer }
176aacc5f13SAndrew Boyer
1776bc7f2cfSAndrew Boyer static int
iocpt_session_write(struct iocpt_session_priv * priv,enum iocpt_sess_control_oper oper)1786bc7f2cfSAndrew Boyer iocpt_session_write(struct iocpt_session_priv *priv,
1796bc7f2cfSAndrew Boyer enum iocpt_sess_control_oper oper)
1806bc7f2cfSAndrew Boyer {
1816bc7f2cfSAndrew Boyer struct iocpt_dev *dev = priv->dev;
1826bc7f2cfSAndrew Boyer struct iocpt_admin_ctx ctx = {
1836bc7f2cfSAndrew Boyer .pending_work = true,
1846bc7f2cfSAndrew Boyer .cmd.sess_control = {
1856bc7f2cfSAndrew Boyer .opcode = IOCPT_CMD_SESS_CONTROL,
1866bc7f2cfSAndrew Boyer .type = priv->type,
1876bc7f2cfSAndrew Boyer .oper = oper,
1886bc7f2cfSAndrew Boyer .index = rte_cpu_to_le_32(priv->index),
1896bc7f2cfSAndrew Boyer .key_len = rte_cpu_to_le_16(priv->key_len),
1906bc7f2cfSAndrew Boyer .key_seg_len = (uint8_t)RTE_MIN(priv->key_len,
1916bc7f2cfSAndrew Boyer IOCPT_SESS_KEY_SEG_LEN),
1926bc7f2cfSAndrew Boyer },
1936bc7f2cfSAndrew Boyer };
1946bc7f2cfSAndrew Boyer struct iocpt_sess_control_cmd *cmd = &ctx.cmd.sess_control;
1956bc7f2cfSAndrew Boyer uint16_t key_offset;
196c09a6e7aSAndrew Boyer uint8_t key_segs, seg, seg_len;
1976bc7f2cfSAndrew Boyer int err;
1986bc7f2cfSAndrew Boyer
1996bc7f2cfSAndrew Boyer key_segs = ((priv->key_len - 1) >> IOCPT_SESS_KEY_SEG_SHFT) + 1;
2006bc7f2cfSAndrew Boyer
2016bc7f2cfSAndrew Boyer for (seg = 0; seg < key_segs; seg++) {
2026bc7f2cfSAndrew Boyer ctx.pending_work = true;
2036bc7f2cfSAndrew Boyer
2046bc7f2cfSAndrew Boyer key_offset = seg * cmd->key_seg_len;
205c09a6e7aSAndrew Boyer seg_len = (uint8_t)RTE_MIN(priv->key_len - key_offset,
2066bc7f2cfSAndrew Boyer IOCPT_SESS_KEY_SEG_LEN);
207c09a6e7aSAndrew Boyer memcpy(cmd->key, &priv->key[key_offset], seg_len);
2086bc7f2cfSAndrew Boyer cmd->key_seg_idx = seg;
2096bc7f2cfSAndrew Boyer
2106bc7f2cfSAndrew Boyer /* Mark final segment */
2116bc7f2cfSAndrew Boyer if (seg + 1 == key_segs)
2126bc7f2cfSAndrew Boyer cmd->flags |= rte_cpu_to_le_16(IOCPT_SCTL_F_END);
2136bc7f2cfSAndrew Boyer
2146bc7f2cfSAndrew Boyer err = iocpt_adminq_post_wait(dev, &ctx);
2156bc7f2cfSAndrew Boyer if (err != 0)
2166bc7f2cfSAndrew Boyer return err;
2176bc7f2cfSAndrew Boyer }
2186bc7f2cfSAndrew Boyer
2196bc7f2cfSAndrew Boyer return 0;
2206bc7f2cfSAndrew Boyer }
2216bc7f2cfSAndrew Boyer
22254d56abaSAndrew Boyer static int
iocpt_session_wdog(struct iocpt_dev * dev)22354d56abaSAndrew Boyer iocpt_session_wdog(struct iocpt_dev *dev)
22454d56abaSAndrew Boyer {
22554d56abaSAndrew Boyer struct iocpt_session_priv priv = {
22654d56abaSAndrew Boyer .dev = dev,
22754d56abaSAndrew Boyer .index = IOCPT_Q_WDOG_SESS_IDX,
22854d56abaSAndrew Boyer .type = IOCPT_SESS_AEAD_AES_GCM,
22954d56abaSAndrew Boyer .key_len = IOCPT_Q_WDOG_KEY_LEN,
23054d56abaSAndrew Boyer };
23154d56abaSAndrew Boyer
23254d56abaSAndrew Boyer /* Reserve session 0 for queue watchdog */
23354d56abaSAndrew Boyer rte_bitmap_clear(dev->sess_bm, IOCPT_Q_WDOG_SESS_IDX);
23454d56abaSAndrew Boyer
23554d56abaSAndrew Boyer return iocpt_session_write(&priv, IOCPT_SESS_INIT);
23654d56abaSAndrew Boyer }
23754d56abaSAndrew Boyer
2386bc7f2cfSAndrew Boyer int
iocpt_session_init(struct iocpt_session_priv * priv)2396bc7f2cfSAndrew Boyer iocpt_session_init(struct iocpt_session_priv *priv)
2406bc7f2cfSAndrew Boyer {
2416bc7f2cfSAndrew Boyer struct iocpt_dev *dev = priv->dev;
2426bc7f2cfSAndrew Boyer uint64_t bm_slab = 0;
2436bc7f2cfSAndrew Boyer uint32_t bm_pos = 0;
2446bc7f2cfSAndrew Boyer int err = 0;
2456bc7f2cfSAndrew Boyer
2466bc7f2cfSAndrew Boyer rte_spinlock_lock(&dev->adminq_lock);
2476bc7f2cfSAndrew Boyer
2486bc7f2cfSAndrew Boyer if (rte_bitmap_scan(dev->sess_bm, &bm_pos, &bm_slab) > 0) {
2496bc7f2cfSAndrew Boyer priv->index = bm_pos + rte_ctz64(bm_slab);
2506bc7f2cfSAndrew Boyer rte_bitmap_clear(dev->sess_bm, priv->index);
2516bc7f2cfSAndrew Boyer } else
2526bc7f2cfSAndrew Boyer err = -ENOSPC;
2536bc7f2cfSAndrew Boyer
2546bc7f2cfSAndrew Boyer rte_spinlock_unlock(&dev->adminq_lock);
2556bc7f2cfSAndrew Boyer
2566bc7f2cfSAndrew Boyer if (err != 0) {
2576bc7f2cfSAndrew Boyer IOCPT_PRINT(ERR, "session index space exhausted");
2586bc7f2cfSAndrew Boyer return err;
2596bc7f2cfSAndrew Boyer }
2606bc7f2cfSAndrew Boyer
2616bc7f2cfSAndrew Boyer err = iocpt_session_write(priv, IOCPT_SESS_INIT);
2626bc7f2cfSAndrew Boyer if (err != 0) {
2636bc7f2cfSAndrew Boyer rte_spinlock_lock(&dev->adminq_lock);
2646bc7f2cfSAndrew Boyer rte_bitmap_set(dev->sess_bm, priv->index);
2656bc7f2cfSAndrew Boyer rte_spinlock_unlock(&dev->adminq_lock);
2666bc7f2cfSAndrew Boyer return err;
2676bc7f2cfSAndrew Boyer }
2686bc7f2cfSAndrew Boyer
2696bc7f2cfSAndrew Boyer priv->flags |= IOCPT_S_F_INITED;
2706bc7f2cfSAndrew Boyer
2716bc7f2cfSAndrew Boyer return 0;
2726bc7f2cfSAndrew Boyer }
2736bc7f2cfSAndrew Boyer
2746bc7f2cfSAndrew Boyer int
iocpt_session_update(struct iocpt_session_priv * priv)2756bc7f2cfSAndrew Boyer iocpt_session_update(struct iocpt_session_priv *priv)
2766bc7f2cfSAndrew Boyer {
2776bc7f2cfSAndrew Boyer return iocpt_session_write(priv, IOCPT_SESS_UPDATE_KEY);
2786bc7f2cfSAndrew Boyer }
2796bc7f2cfSAndrew Boyer
2806bc7f2cfSAndrew Boyer void
iocpt_session_deinit(struct iocpt_session_priv * priv)2816bc7f2cfSAndrew Boyer iocpt_session_deinit(struct iocpt_session_priv *priv)
2826bc7f2cfSAndrew Boyer {
2836bc7f2cfSAndrew Boyer struct iocpt_dev *dev = priv->dev;
2846bc7f2cfSAndrew Boyer struct iocpt_admin_ctx ctx = {
2856bc7f2cfSAndrew Boyer .pending_work = true,
2866bc7f2cfSAndrew Boyer .cmd.sess_control = {
2876bc7f2cfSAndrew Boyer .opcode = IOCPT_CMD_SESS_CONTROL,
2886bc7f2cfSAndrew Boyer .type = priv->type,
2896bc7f2cfSAndrew Boyer .oper = IOCPT_SESS_DISABLE,
2906bc7f2cfSAndrew Boyer .index = rte_cpu_to_le_32(priv->index),
2916bc7f2cfSAndrew Boyer .key_len = rte_cpu_to_le_16(priv->key_len),
2926bc7f2cfSAndrew Boyer },
2936bc7f2cfSAndrew Boyer };
2946bc7f2cfSAndrew Boyer
2956bc7f2cfSAndrew Boyer (void)iocpt_adminq_post_wait(dev, &ctx);
2966bc7f2cfSAndrew Boyer
2976bc7f2cfSAndrew Boyer rte_spinlock_lock(&dev->adminq_lock);
2986bc7f2cfSAndrew Boyer rte_bitmap_set(dev->sess_bm, priv->index);
2996bc7f2cfSAndrew Boyer rte_spinlock_unlock(&dev->adminq_lock);
3006bc7f2cfSAndrew Boyer
3016bc7f2cfSAndrew Boyer priv->flags &= ~IOCPT_S_F_INITED;
3026bc7f2cfSAndrew Boyer }
3036bc7f2cfSAndrew Boyer
304a677112dSAndrew Boyer static const struct rte_memzone *
iocpt_dma_zone_reserve(const char * type_name,uint16_t qid,size_t size,unsigned int align,int socket_id)305a677112dSAndrew Boyer iocpt_dma_zone_reserve(const char *type_name, uint16_t qid, size_t size,
306a677112dSAndrew Boyer unsigned int align, int socket_id)
307a677112dSAndrew Boyer {
308a677112dSAndrew Boyer char zone_name[RTE_MEMZONE_NAMESIZE];
309a677112dSAndrew Boyer const struct rte_memzone *mz;
310a677112dSAndrew Boyer int err;
311a677112dSAndrew Boyer
312a677112dSAndrew Boyer err = snprintf(zone_name, sizeof(zone_name),
313a677112dSAndrew Boyer "iocpt_%s_%u", type_name, qid);
314a677112dSAndrew Boyer if (err >= RTE_MEMZONE_NAMESIZE) {
315a677112dSAndrew Boyer IOCPT_PRINT(ERR, "Name %s too long", type_name);
316a677112dSAndrew Boyer return NULL;
317a677112dSAndrew Boyer }
318a677112dSAndrew Boyer
319a677112dSAndrew Boyer mz = rte_memzone_lookup(zone_name);
320a677112dSAndrew Boyer if (mz != NULL)
321a677112dSAndrew Boyer return mz;
322a677112dSAndrew Boyer
323a677112dSAndrew Boyer return rte_memzone_reserve_aligned(zone_name, size, socket_id,
324a677112dSAndrew Boyer RTE_MEMZONE_IOVA_CONTIG, align);
325a677112dSAndrew Boyer }
326a677112dSAndrew Boyer
327a677112dSAndrew Boyer static int
iocpt_commonq_alloc(struct iocpt_dev * dev,uint8_t type,size_t struct_size,uint32_t socket_id,uint32_t index,const char * type_name,uint16_t flags,uint16_t num_descs,uint16_t num_segs,uint16_t desc_size,uint16_t cq_desc_size,uint16_t sg_desc_size,struct iocpt_common_q ** comq)3282c1662bbSAndrew Boyer iocpt_commonq_alloc(struct iocpt_dev *dev,
3292c1662bbSAndrew Boyer uint8_t type,
3302c1662bbSAndrew Boyer size_t struct_size,
3312c1662bbSAndrew Boyer uint32_t socket_id,
3322c1662bbSAndrew Boyer uint32_t index,
3332c1662bbSAndrew Boyer const char *type_name,
3342c1662bbSAndrew Boyer uint16_t flags,
3352c1662bbSAndrew Boyer uint16_t num_descs,
3362c1662bbSAndrew Boyer uint16_t num_segs,
3372c1662bbSAndrew Boyer uint16_t desc_size,
3382c1662bbSAndrew Boyer uint16_t cq_desc_size,
3392c1662bbSAndrew Boyer uint16_t sg_desc_size,
3402c1662bbSAndrew Boyer struct iocpt_common_q **comq)
3412c1662bbSAndrew Boyer {
3422c1662bbSAndrew Boyer struct iocpt_common_q *new;
3432c1662bbSAndrew Boyer uint32_t q_size, cq_size, sg_size, total_size;
3442c1662bbSAndrew Boyer void *q_base, *cq_base, *sg_base;
3452c1662bbSAndrew Boyer rte_iova_t q_base_pa = 0;
3462c1662bbSAndrew Boyer rte_iova_t cq_base_pa = 0;
3472c1662bbSAndrew Boyer rte_iova_t sg_base_pa = 0;
3482c1662bbSAndrew Boyer size_t page_size = rte_mem_page_size();
3492c1662bbSAndrew Boyer int err;
3502c1662bbSAndrew Boyer
3512c1662bbSAndrew Boyer *comq = NULL;
3522c1662bbSAndrew Boyer
3532c1662bbSAndrew Boyer q_size = num_descs * desc_size;
3542c1662bbSAndrew Boyer cq_size = num_descs * cq_desc_size;
3552c1662bbSAndrew Boyer sg_size = num_descs * sg_desc_size;
3562c1662bbSAndrew Boyer
3572c1662bbSAndrew Boyer /*
3582c1662bbSAndrew Boyer * Note: aligning q_size/cq_size is not enough due to cq_base address
3592c1662bbSAndrew Boyer * aligning as q_base could be not aligned to the page.
3602c1662bbSAndrew Boyer * Adding page_size.
3612c1662bbSAndrew Boyer */
3622c1662bbSAndrew Boyer total_size = RTE_ALIGN(q_size, page_size) +
3632c1662bbSAndrew Boyer RTE_ALIGN(cq_size, page_size) + page_size;
3642c1662bbSAndrew Boyer if (flags & IOCPT_Q_F_SG)
3652c1662bbSAndrew Boyer total_size += RTE_ALIGN(sg_size, page_size) + page_size;
3662c1662bbSAndrew Boyer
3672c1662bbSAndrew Boyer new = rte_zmalloc_socket("iocpt", struct_size,
3682c1662bbSAndrew Boyer RTE_CACHE_LINE_SIZE, socket_id);
3692c1662bbSAndrew Boyer if (new == NULL) {
3702c1662bbSAndrew Boyer IOCPT_PRINT(ERR, "Cannot allocate queue structure");
3712c1662bbSAndrew Boyer return -ENOMEM;
3722c1662bbSAndrew Boyer }
3732c1662bbSAndrew Boyer
3742c1662bbSAndrew Boyer new->dev = dev;
3752c1662bbSAndrew Boyer
3762c1662bbSAndrew Boyer err = iocpt_q_init(&new->q, type, index, num_descs, num_segs,
3772c1662bbSAndrew Boyer socket_id);
3782c1662bbSAndrew Boyer if (err != 0) {
3792c1662bbSAndrew Boyer IOCPT_PRINT(ERR, "Queue initialization failed");
3802c1662bbSAndrew Boyer goto err_free_q;
3812c1662bbSAndrew Boyer }
3822c1662bbSAndrew Boyer
3832c1662bbSAndrew Boyer err = iocpt_cq_init(&new->cq, num_descs);
3842c1662bbSAndrew Boyer if (err != 0) {
3852c1662bbSAndrew Boyer IOCPT_PRINT(ERR, "Completion queue initialization failed");
3862c1662bbSAndrew Boyer goto err_deinit_q;
3872c1662bbSAndrew Boyer }
3882c1662bbSAndrew Boyer
3892c1662bbSAndrew Boyer new->base_z = iocpt_dma_zone_reserve(type_name, index, total_size,
3902c1662bbSAndrew Boyer IONIC_ALIGN, socket_id);
3912c1662bbSAndrew Boyer if (new->base_z == NULL) {
3922c1662bbSAndrew Boyer IOCPT_PRINT(ERR, "Cannot reserve queue DMA memory");
3932c1662bbSAndrew Boyer err = -ENOMEM;
3942c1662bbSAndrew Boyer goto err_deinit_cq;
3952c1662bbSAndrew Boyer }
3962c1662bbSAndrew Boyer
3972c1662bbSAndrew Boyer new->base = new->base_z->addr;
3982c1662bbSAndrew Boyer new->base_pa = new->base_z->iova;
3992c1662bbSAndrew Boyer
4002c1662bbSAndrew Boyer q_base = new->base;
4012c1662bbSAndrew Boyer q_base_pa = new->base_pa;
4022c1662bbSAndrew Boyer iocpt_q_map(&new->q, q_base, q_base_pa);
4032c1662bbSAndrew Boyer
4042c1662bbSAndrew Boyer cq_base = (void *)RTE_ALIGN((uintptr_t)q_base + q_size, page_size);
4052c1662bbSAndrew Boyer cq_base_pa = RTE_ALIGN(q_base_pa + q_size, page_size);
4062c1662bbSAndrew Boyer iocpt_cq_map(&new->cq, cq_base, cq_base_pa);
4072c1662bbSAndrew Boyer
4082c1662bbSAndrew Boyer if (flags & IOCPT_Q_F_SG) {
4092c1662bbSAndrew Boyer sg_base = (void *)RTE_ALIGN((uintptr_t)cq_base + cq_size,
4102c1662bbSAndrew Boyer page_size);
4112c1662bbSAndrew Boyer sg_base_pa = RTE_ALIGN(cq_base_pa + cq_size, page_size);
4122c1662bbSAndrew Boyer iocpt_q_sg_map(&new->q, sg_base, sg_base_pa);
4132c1662bbSAndrew Boyer }
4142c1662bbSAndrew Boyer
4152c1662bbSAndrew Boyer IOCPT_PRINT(DEBUG, "q_base_pa %#jx cq_base_pa %#jx sg_base_pa %#jx",
4162c1662bbSAndrew Boyer q_base_pa, cq_base_pa, sg_base_pa);
4172c1662bbSAndrew Boyer
4182c1662bbSAndrew Boyer *comq = new;
4192c1662bbSAndrew Boyer
4202c1662bbSAndrew Boyer return 0;
4212c1662bbSAndrew Boyer
4222c1662bbSAndrew Boyer err_deinit_cq:
4232c1662bbSAndrew Boyer err_deinit_q:
4242c1662bbSAndrew Boyer iocpt_q_free(&new->q);
4252c1662bbSAndrew Boyer err_free_q:
4262c1662bbSAndrew Boyer rte_free(new);
4272c1662bbSAndrew Boyer return err;
4282c1662bbSAndrew Boyer }
4292c1662bbSAndrew Boyer
43080518852SAndrew Boyer int
iocpt_cryptoq_alloc(struct iocpt_dev * dev,uint32_t socket_id,uint32_t index,uint16_t num_descs)43180518852SAndrew Boyer iocpt_cryptoq_alloc(struct iocpt_dev *dev, uint32_t socket_id, uint32_t index,
43280518852SAndrew Boyer uint16_t num_descs)
43380518852SAndrew Boyer {
43480518852SAndrew Boyer struct iocpt_crypto_q *cptq;
43580518852SAndrew Boyer uint16_t flags = 0;
43680518852SAndrew Boyer int err;
43780518852SAndrew Boyer
43880518852SAndrew Boyer /* CryptoQ always supports scatter-gather */
43980518852SAndrew Boyer flags |= IOCPT_Q_F_SG;
44080518852SAndrew Boyer
44180518852SAndrew Boyer IOCPT_PRINT(DEBUG, "cptq %u num_descs %u num_segs %u",
44280518852SAndrew Boyer index, num_descs, 1);
44380518852SAndrew Boyer
44480518852SAndrew Boyer err = iocpt_commonq_alloc(dev,
44580518852SAndrew Boyer IOCPT_QTYPE_CRYPTOQ,
44680518852SAndrew Boyer sizeof(struct iocpt_crypto_q),
44780518852SAndrew Boyer socket_id,
44880518852SAndrew Boyer index,
44980518852SAndrew Boyer "crypto",
45080518852SAndrew Boyer flags,
45180518852SAndrew Boyer num_descs,
45280518852SAndrew Boyer 1,
45380518852SAndrew Boyer sizeof(struct iocpt_crypto_desc),
45480518852SAndrew Boyer sizeof(struct iocpt_crypto_comp),
45580518852SAndrew Boyer sizeof(struct iocpt_crypto_sg_desc),
45680518852SAndrew Boyer (struct iocpt_common_q **)&cptq);
45780518852SAndrew Boyer if (err != 0)
45880518852SAndrew Boyer return err;
45980518852SAndrew Boyer
46080518852SAndrew Boyer cptq->flags = flags;
46180518852SAndrew Boyer
46280518852SAndrew Boyer dev->cryptoqs[index] = cptq;
46380518852SAndrew Boyer
46480518852SAndrew Boyer return 0;
46580518852SAndrew Boyer }
46680518852SAndrew Boyer
4672c1662bbSAndrew Boyer struct ionic_doorbell *
iocpt_db_map(struct iocpt_dev * dev,struct iocpt_queue * q)4682c1662bbSAndrew Boyer iocpt_db_map(struct iocpt_dev *dev, struct iocpt_queue *q)
4692c1662bbSAndrew Boyer {
4702c1662bbSAndrew Boyer return dev->db_pages + q->hw_type;
4712c1662bbSAndrew Boyer }
4722c1662bbSAndrew Boyer
4732c1662bbSAndrew Boyer static int
iocpt_cryptoq_init(struct iocpt_crypto_q * cptq)47480518852SAndrew Boyer iocpt_cryptoq_init(struct iocpt_crypto_q *cptq)
47580518852SAndrew Boyer {
47680518852SAndrew Boyer struct iocpt_queue *q = &cptq->q;
47780518852SAndrew Boyer struct iocpt_dev *dev = cptq->dev;
47880518852SAndrew Boyer struct iocpt_cq *cq = &cptq->cq;
47980518852SAndrew Boyer struct iocpt_admin_ctx ctx = {
48080518852SAndrew Boyer .pending_work = true,
48180518852SAndrew Boyer .cmd.q_init = {
48280518852SAndrew Boyer .opcode = IOCPT_CMD_Q_INIT,
48380518852SAndrew Boyer .type = IOCPT_QTYPE_CRYPTOQ,
48480518852SAndrew Boyer .ver = dev->qtype_info[IOCPT_QTYPE_CRYPTOQ].version,
48580518852SAndrew Boyer .index = rte_cpu_to_le_32(q->index),
48680518852SAndrew Boyer .flags = rte_cpu_to_le_16(IOCPT_QINIT_F_ENA |
48780518852SAndrew Boyer IOCPT_QINIT_F_SG),
48880518852SAndrew Boyer .intr_index = rte_cpu_to_le_16(IONIC_INTR_NONE),
48980518852SAndrew Boyer .ring_size = rte_log2_u32(q->num_descs),
49080518852SAndrew Boyer .ring_base = rte_cpu_to_le_64(q->base_pa),
49180518852SAndrew Boyer .cq_ring_base = rte_cpu_to_le_64(cq->base_pa),
49280518852SAndrew Boyer .sg_ring_base = rte_cpu_to_le_64(q->sg_base_pa),
49380518852SAndrew Boyer },
49480518852SAndrew Boyer };
49580518852SAndrew Boyer int err;
49680518852SAndrew Boyer
49780518852SAndrew Boyer IOCPT_PRINT(DEBUG, "cptq_init.index %d", q->index);
49880518852SAndrew Boyer IOCPT_PRINT(DEBUG, "cptq_init.ring_base %#jx", q->base_pa);
49980518852SAndrew Boyer IOCPT_PRINT(DEBUG, "cptq_init.ring_size %d",
50080518852SAndrew Boyer ctx.cmd.q_init.ring_size);
50180518852SAndrew Boyer IOCPT_PRINT(DEBUG, "cptq_init.ver %u", ctx.cmd.q_init.ver);
50280518852SAndrew Boyer
50380518852SAndrew Boyer iocpt_q_reset(q);
50480518852SAndrew Boyer iocpt_cq_reset(cq);
50580518852SAndrew Boyer
50680518852SAndrew Boyer err = iocpt_adminq_post_wait(dev, &ctx);
50780518852SAndrew Boyer if (err != 0)
50880518852SAndrew Boyer return err;
50980518852SAndrew Boyer
51080518852SAndrew Boyer q->hw_type = ctx.comp.q_init.hw_type;
51180518852SAndrew Boyer q->hw_index = rte_le_to_cpu_32(ctx.comp.q_init.hw_index);
51280518852SAndrew Boyer q->db = iocpt_db_map(dev, q);
51380518852SAndrew Boyer
51480518852SAndrew Boyer IOCPT_PRINT(DEBUG, "cptq->hw_type %d", q->hw_type);
51580518852SAndrew Boyer IOCPT_PRINT(DEBUG, "cptq->hw_index %d", q->hw_index);
51680518852SAndrew Boyer IOCPT_PRINT(DEBUG, "cptq->db %p", q->db);
51780518852SAndrew Boyer
51880518852SAndrew Boyer cptq->flags |= IOCPT_Q_F_INITED;
51980518852SAndrew Boyer
52080518852SAndrew Boyer return 0;
52180518852SAndrew Boyer }
52280518852SAndrew Boyer
52380518852SAndrew Boyer static void
iocpt_cryptoq_deinit(struct iocpt_crypto_q * cptq)52480518852SAndrew Boyer iocpt_cryptoq_deinit(struct iocpt_crypto_q *cptq)
52580518852SAndrew Boyer {
52680518852SAndrew Boyer struct iocpt_dev *dev = cptq->dev;
52780518852SAndrew Boyer struct iocpt_admin_ctx ctx = {
52880518852SAndrew Boyer .pending_work = true,
52980518852SAndrew Boyer .cmd.q_control = {
53080518852SAndrew Boyer .opcode = IOCPT_CMD_Q_CONTROL,
53180518852SAndrew Boyer .type = IOCPT_QTYPE_CRYPTOQ,
53280518852SAndrew Boyer .index = rte_cpu_to_le_32(cptq->q.index),
53380518852SAndrew Boyer .oper = IOCPT_Q_DISABLE,
53480518852SAndrew Boyer },
53580518852SAndrew Boyer };
53680518852SAndrew Boyer unsigned long sleep_usec = 100UL * 1000;
53780518852SAndrew Boyer uint32_t sleep_cnt, sleep_max = IOCPT_CRYPTOQ_WAIT;
53880518852SAndrew Boyer int err;
53980518852SAndrew Boyer
54080518852SAndrew Boyer for (sleep_cnt = 0; sleep_cnt < sleep_max; sleep_cnt++) {
54180518852SAndrew Boyer ctx.pending_work = true;
54280518852SAndrew Boyer
54380518852SAndrew Boyer err = iocpt_adminq_post_wait(dev, &ctx);
54480518852SAndrew Boyer if (err != -EAGAIN)
54580518852SAndrew Boyer break;
54680518852SAndrew Boyer
54780518852SAndrew Boyer rte_delay_us_block(sleep_usec);
54880518852SAndrew Boyer }
54980518852SAndrew Boyer
55080518852SAndrew Boyer if (err != 0)
55180518852SAndrew Boyer IOCPT_PRINT(ERR, "Deinit queue %u returned %d after %u ms",
55280518852SAndrew Boyer cptq->q.index, err, sleep_cnt * 100);
55380518852SAndrew Boyer else
55480518852SAndrew Boyer IOCPT_PRINT(DEBUG, "Deinit queue %u returned %d after %u ms",
55580518852SAndrew Boyer cptq->q.index, err, sleep_cnt * 100);
55680518852SAndrew Boyer
55754d56abaSAndrew Boyer IOCPT_PRINT(DEBUG, "Queue %u watchdog: enq %"PRIu64" deq %"PRIu64,
55854d56abaSAndrew Boyer cptq->q.index, cptq->enqueued_wdogs, cptq->dequeued_wdogs);
55954d56abaSAndrew Boyer
56080518852SAndrew Boyer cptq->flags &= ~IOCPT_Q_F_INITED;
56180518852SAndrew Boyer }
56280518852SAndrew Boyer
56380518852SAndrew Boyer void
iocpt_cryptoq_free(struct iocpt_crypto_q * cptq)56480518852SAndrew Boyer iocpt_cryptoq_free(struct iocpt_crypto_q *cptq)
56580518852SAndrew Boyer {
56680518852SAndrew Boyer if (cptq == NULL)
56780518852SAndrew Boyer return;
56880518852SAndrew Boyer
56980518852SAndrew Boyer if (cptq->base_z != NULL) {
57080518852SAndrew Boyer rte_memzone_free(cptq->base_z);
57180518852SAndrew Boyer cptq->base_z = NULL;
57280518852SAndrew Boyer cptq->base = NULL;
57380518852SAndrew Boyer cptq->base_pa = 0;
57480518852SAndrew Boyer }
57580518852SAndrew Boyer
57680518852SAndrew Boyer iocpt_q_free(&cptq->q);
57780518852SAndrew Boyer
57880518852SAndrew Boyer rte_free(cptq);
57980518852SAndrew Boyer }
58080518852SAndrew Boyer
58180518852SAndrew Boyer static int
iocpt_adminq_alloc(struct iocpt_dev * dev)5822c1662bbSAndrew Boyer iocpt_adminq_alloc(struct iocpt_dev *dev)
5832c1662bbSAndrew Boyer {
5842c1662bbSAndrew Boyer struct iocpt_admin_q *aq;
5852c1662bbSAndrew Boyer uint16_t num_descs = IOCPT_ADMINQ_LENGTH;
5862c1662bbSAndrew Boyer uint16_t flags = 0;
5872c1662bbSAndrew Boyer int err;
5882c1662bbSAndrew Boyer
5892c1662bbSAndrew Boyer err = iocpt_commonq_alloc(dev,
5902c1662bbSAndrew Boyer IOCPT_QTYPE_ADMINQ,
5912c1662bbSAndrew Boyer sizeof(struct iocpt_admin_q),
5922c1662bbSAndrew Boyer rte_socket_id(),
5932c1662bbSAndrew Boyer 0,
5942c1662bbSAndrew Boyer "admin",
5952c1662bbSAndrew Boyer flags,
5962c1662bbSAndrew Boyer num_descs,
5972c1662bbSAndrew Boyer 1,
5982c1662bbSAndrew Boyer sizeof(struct iocpt_admin_cmd),
5992c1662bbSAndrew Boyer sizeof(struct iocpt_admin_comp),
6002c1662bbSAndrew Boyer 0,
6012c1662bbSAndrew Boyer (struct iocpt_common_q **)&aq);
6022c1662bbSAndrew Boyer if (err != 0)
6032c1662bbSAndrew Boyer return err;
6042c1662bbSAndrew Boyer
6052c1662bbSAndrew Boyer aq->flags = flags;
6062c1662bbSAndrew Boyer
6072c1662bbSAndrew Boyer dev->adminq = aq;
6082c1662bbSAndrew Boyer
6092c1662bbSAndrew Boyer return 0;
6102c1662bbSAndrew Boyer }
6112c1662bbSAndrew Boyer
6122c1662bbSAndrew Boyer static int
iocpt_adminq_init(struct iocpt_dev * dev)6132c1662bbSAndrew Boyer iocpt_adminq_init(struct iocpt_dev *dev)
6142c1662bbSAndrew Boyer {
6152c1662bbSAndrew Boyer return iocpt_dev_adminq_init(dev);
6162c1662bbSAndrew Boyer }
6172c1662bbSAndrew Boyer
6182c1662bbSAndrew Boyer static void
iocpt_adminq_deinit(struct iocpt_dev * dev)6192c1662bbSAndrew Boyer iocpt_adminq_deinit(struct iocpt_dev *dev)
6202c1662bbSAndrew Boyer {
6212c1662bbSAndrew Boyer dev->adminq->flags &= ~IOCPT_Q_F_INITED;
6222c1662bbSAndrew Boyer }
6232c1662bbSAndrew Boyer
6242c1662bbSAndrew Boyer static void
iocpt_adminq_free(struct iocpt_admin_q * aq)6252c1662bbSAndrew Boyer iocpt_adminq_free(struct iocpt_admin_q *aq)
6262c1662bbSAndrew Boyer {
6272c1662bbSAndrew Boyer if (aq->base_z != NULL) {
6282c1662bbSAndrew Boyer rte_memzone_free(aq->base_z);
6292c1662bbSAndrew Boyer aq->base_z = NULL;
6302c1662bbSAndrew Boyer aq->base = NULL;
6312c1662bbSAndrew Boyer aq->base_pa = 0;
6322c1662bbSAndrew Boyer }
6332c1662bbSAndrew Boyer
6342c1662bbSAndrew Boyer iocpt_q_free(&aq->q);
6352c1662bbSAndrew Boyer
6362c1662bbSAndrew Boyer rte_free(aq);
6372c1662bbSAndrew Boyer }
6382c1662bbSAndrew Boyer
6392c1662bbSAndrew Boyer static int
iocpt_alloc_objs(struct iocpt_dev * dev)640a677112dSAndrew Boyer iocpt_alloc_objs(struct iocpt_dev *dev)
641a677112dSAndrew Boyer {
6426bc7f2cfSAndrew Boyer uint32_t bmsize, i;
6436bc7f2cfSAndrew Boyer uint8_t *bm;
644a677112dSAndrew Boyer int err;
645a677112dSAndrew Boyer
646a677112dSAndrew Boyer IOCPT_PRINT(DEBUG, "Crypto: %s", dev->name);
647a677112dSAndrew Boyer
64880518852SAndrew Boyer dev->cryptoqs = rte_calloc_socket("iocpt",
64980518852SAndrew Boyer dev->max_qps, sizeof(*dev->cryptoqs),
65080518852SAndrew Boyer RTE_CACHE_LINE_SIZE, dev->socket_id);
65180518852SAndrew Boyer if (dev->cryptoqs == NULL) {
65280518852SAndrew Boyer IOCPT_PRINT(ERR, "Cannot allocate tx queues array");
65380518852SAndrew Boyer return -ENOMEM;
65480518852SAndrew Boyer }
65580518852SAndrew Boyer
6562c1662bbSAndrew Boyer rte_spinlock_init(&dev->adminq_lock);
6572c1662bbSAndrew Boyer rte_spinlock_init(&dev->adminq_service_lock);
6582c1662bbSAndrew Boyer
6592c1662bbSAndrew Boyer err = iocpt_adminq_alloc(dev);
6602c1662bbSAndrew Boyer if (err != 0) {
6612c1662bbSAndrew Boyer IOCPT_PRINT(ERR, "Cannot allocate admin queue");
6622c1662bbSAndrew Boyer err = -ENOMEM;
66380518852SAndrew Boyer goto err_free_cryptoqs;
6642c1662bbSAndrew Boyer }
6652c1662bbSAndrew Boyer
666a677112dSAndrew Boyer dev->info_sz = RTE_ALIGN(sizeof(*dev->info), rte_mem_page_size());
667a677112dSAndrew Boyer dev->info_z = iocpt_dma_zone_reserve("info", 0, dev->info_sz,
668a677112dSAndrew Boyer IONIC_ALIGN, dev->socket_id);
669a677112dSAndrew Boyer if (dev->info_z == NULL) {
670a677112dSAndrew Boyer IOCPT_PRINT(ERR, "Cannot allocate dev info memory");
671a677112dSAndrew Boyer err = -ENOMEM;
6722c1662bbSAndrew Boyer goto err_free_adminq;
673a677112dSAndrew Boyer }
674a677112dSAndrew Boyer
675a677112dSAndrew Boyer dev->info = dev->info_z->addr;
676a677112dSAndrew Boyer dev->info_pa = dev->info_z->iova;
677a677112dSAndrew Boyer
6786bc7f2cfSAndrew Boyer bmsize = rte_bitmap_get_memory_footprint(dev->max_sessions);
6796bc7f2cfSAndrew Boyer bm = rte_malloc_socket("iocpt", bmsize,
6806bc7f2cfSAndrew Boyer RTE_CACHE_LINE_SIZE, dev->socket_id);
6816bc7f2cfSAndrew Boyer if (bm == NULL) {
6826bc7f2cfSAndrew Boyer IOCPT_PRINT(ERR, "Cannot allocate %uB bitmap memory", bmsize);
6836bc7f2cfSAndrew Boyer err = -ENOMEM;
6846bc7f2cfSAndrew Boyer goto err_free_dmazone;
6856bc7f2cfSAndrew Boyer }
6866bc7f2cfSAndrew Boyer
6876bc7f2cfSAndrew Boyer dev->sess_bm = rte_bitmap_init(dev->max_sessions, bm, bmsize);
6886bc7f2cfSAndrew Boyer if (dev->sess_bm == NULL) {
6896bc7f2cfSAndrew Boyer IOCPT_PRINT(ERR, "Cannot initialize bitmap");
6906bc7f2cfSAndrew Boyer err = -EFAULT;
6916bc7f2cfSAndrew Boyer goto err_free_bm;
6926bc7f2cfSAndrew Boyer }
6936bc7f2cfSAndrew Boyer for (i = 0; i < dev->max_sessions; i++)
6946bc7f2cfSAndrew Boyer rte_bitmap_set(dev->sess_bm, i);
6956bc7f2cfSAndrew Boyer
696a677112dSAndrew Boyer return 0;
697a677112dSAndrew Boyer
6986bc7f2cfSAndrew Boyer err_free_bm:
6996bc7f2cfSAndrew Boyer rte_free(bm);
7006bc7f2cfSAndrew Boyer err_free_dmazone:
7016bc7f2cfSAndrew Boyer rte_memzone_free(dev->info_z);
7026bc7f2cfSAndrew Boyer dev->info_z = NULL;
7036bc7f2cfSAndrew Boyer dev->info = NULL;
7046bc7f2cfSAndrew Boyer dev->info_pa = 0;
7052c1662bbSAndrew Boyer err_free_adminq:
7062c1662bbSAndrew Boyer iocpt_adminq_free(dev->adminq);
7072c1662bbSAndrew Boyer dev->adminq = NULL;
70880518852SAndrew Boyer err_free_cryptoqs:
70980518852SAndrew Boyer rte_free(dev->cryptoqs);
71080518852SAndrew Boyer dev->cryptoqs = NULL;
711a677112dSAndrew Boyer return err;
712a677112dSAndrew Boyer }
713a677112dSAndrew Boyer
7144610ac93SAndrew Boyer static int
iocpt_init(struct iocpt_dev * dev)7154610ac93SAndrew Boyer iocpt_init(struct iocpt_dev *dev)
7164610ac93SAndrew Boyer {
717a677112dSAndrew Boyer int err;
718a677112dSAndrew Boyer
719aacc5f13SAndrew Boyer memset(&dev->stats_base, 0, sizeof(dev->stats_base));
720aacc5f13SAndrew Boyer
721a677112dSAndrew Boyer /* Uses dev_cmds */
722a677112dSAndrew Boyer err = iocpt_dev_init(dev, dev->info_pa);
723a677112dSAndrew Boyer if (err != 0)
724a677112dSAndrew Boyer return err;
725a677112dSAndrew Boyer
7262c1662bbSAndrew Boyer err = iocpt_adminq_init(dev);
7272c1662bbSAndrew Boyer if (err != 0)
7282c1662bbSAndrew Boyer return err;
7292c1662bbSAndrew Boyer
73054d56abaSAndrew Boyer /* Write the queue watchdog key */
73154d56abaSAndrew Boyer err = iocpt_session_wdog(dev);
73254d56abaSAndrew Boyer if (err != 0) {
73354d56abaSAndrew Boyer IOCPT_PRINT(ERR, "Cannot setup watchdog session");
73454d56abaSAndrew Boyer goto err_out_adminq_deinit;
73554d56abaSAndrew Boyer }
73654d56abaSAndrew Boyer
7374610ac93SAndrew Boyer dev->state |= IOCPT_DEV_F_INITED;
7384610ac93SAndrew Boyer
7394610ac93SAndrew Boyer return 0;
74054d56abaSAndrew Boyer
74154d56abaSAndrew Boyer err_out_adminq_deinit:
74254d56abaSAndrew Boyer iocpt_adminq_deinit(dev);
74354d56abaSAndrew Boyer
74454d56abaSAndrew Boyer return err;
7454610ac93SAndrew Boyer }
7464610ac93SAndrew Boyer
7474610ac93SAndrew Boyer void
iocpt_configure(struct iocpt_dev * dev)7484610ac93SAndrew Boyer iocpt_configure(struct iocpt_dev *dev)
7494610ac93SAndrew Boyer {
7504610ac93SAndrew Boyer RTE_SET_USED(dev);
7514610ac93SAndrew Boyer }
7524610ac93SAndrew Boyer
75380518852SAndrew Boyer int
iocpt_start(struct iocpt_dev * dev)75480518852SAndrew Boyer iocpt_start(struct iocpt_dev *dev)
75580518852SAndrew Boyer {
75680518852SAndrew Boyer uint32_t i;
75780518852SAndrew Boyer int err;
75880518852SAndrew Boyer
75980518852SAndrew Boyer IOCPT_PRINT(DEBUG, "Starting %u queues",
76080518852SAndrew Boyer dev->crypto_dev->data->nb_queue_pairs);
76180518852SAndrew Boyer
76280518852SAndrew Boyer for (i = 0; i < dev->crypto_dev->data->nb_queue_pairs; i++) {
76380518852SAndrew Boyer err = iocpt_cryptoq_init(dev->cryptoqs[i]);
76480518852SAndrew Boyer if (err != 0)
76580518852SAndrew Boyer return err;
76680518852SAndrew Boyer }
76780518852SAndrew Boyer
76880518852SAndrew Boyer dev->state |= IOCPT_DEV_F_UP;
76980518852SAndrew Boyer
77080518852SAndrew Boyer return 0;
77180518852SAndrew Boyer }
77280518852SAndrew Boyer
77380518852SAndrew Boyer void
iocpt_stop(struct iocpt_dev * dev)77480518852SAndrew Boyer iocpt_stop(struct iocpt_dev *dev)
77580518852SAndrew Boyer {
77680518852SAndrew Boyer uint32_t i;
77780518852SAndrew Boyer
77880518852SAndrew Boyer IOCPT_PRINT_CALL();
77980518852SAndrew Boyer
78080518852SAndrew Boyer dev->state &= ~IOCPT_DEV_F_UP;
78180518852SAndrew Boyer
78280518852SAndrew Boyer for (i = 0; i < dev->crypto_dev->data->nb_queue_pairs; i++) {
78380518852SAndrew Boyer struct iocpt_crypto_q *cptq = dev->cryptoqs[i];
78480518852SAndrew Boyer
78580518852SAndrew Boyer if (cptq->flags & IOCPT_Q_F_INITED)
78680518852SAndrew Boyer (void)iocpt_cryptoq_deinit(cptq);
78780518852SAndrew Boyer }
78880518852SAndrew Boyer }
78980518852SAndrew Boyer
7904610ac93SAndrew Boyer void
iocpt_deinit(struct iocpt_dev * dev)7914610ac93SAndrew Boyer iocpt_deinit(struct iocpt_dev *dev)
7924610ac93SAndrew Boyer {
7934610ac93SAndrew Boyer IOCPT_PRINT_CALL();
7944610ac93SAndrew Boyer
7954610ac93SAndrew Boyer if (!(dev->state & IOCPT_DEV_F_INITED))
7964610ac93SAndrew Boyer return;
7974610ac93SAndrew Boyer
7982c1662bbSAndrew Boyer iocpt_adminq_deinit(dev);
7992c1662bbSAndrew Boyer
8004610ac93SAndrew Boyer dev->state &= ~IOCPT_DEV_F_INITED;
8014610ac93SAndrew Boyer }
8024610ac93SAndrew Boyer
803a677112dSAndrew Boyer static void
iocpt_free_objs(struct iocpt_dev * dev)804a677112dSAndrew Boyer iocpt_free_objs(struct iocpt_dev *dev)
805a677112dSAndrew Boyer {
80680518852SAndrew Boyer void **queue_pairs = dev->crypto_dev->data->queue_pairs;
80780518852SAndrew Boyer uint32_t i;
80880518852SAndrew Boyer
809a677112dSAndrew Boyer IOCPT_PRINT_CALL();
810a677112dSAndrew Boyer
81180518852SAndrew Boyer for (i = 0; i < dev->crypto_dev->data->nb_queue_pairs; i++) {
81280518852SAndrew Boyer iocpt_cryptoq_free(queue_pairs[i]);
81380518852SAndrew Boyer queue_pairs[i] = NULL;
81480518852SAndrew Boyer }
81580518852SAndrew Boyer
8166bc7f2cfSAndrew Boyer if (dev->sess_bm != NULL) {
8176bc7f2cfSAndrew Boyer rte_bitmap_free(dev->sess_bm);
8186bc7f2cfSAndrew Boyer rte_free(dev->sess_bm);
8196bc7f2cfSAndrew Boyer dev->sess_bm = NULL;
8206bc7f2cfSAndrew Boyer }
8216bc7f2cfSAndrew Boyer
8222c1662bbSAndrew Boyer if (dev->adminq != NULL) {
8232c1662bbSAndrew Boyer iocpt_adminq_free(dev->adminq);
8242c1662bbSAndrew Boyer dev->adminq = NULL;
8252c1662bbSAndrew Boyer }
8262c1662bbSAndrew Boyer
82780518852SAndrew Boyer if (dev->cryptoqs != NULL) {
82880518852SAndrew Boyer rte_free(dev->cryptoqs);
82980518852SAndrew Boyer dev->cryptoqs = NULL;
83080518852SAndrew Boyer }
83180518852SAndrew Boyer
832a677112dSAndrew Boyer if (dev->info != NULL) {
833a677112dSAndrew Boyer rte_memzone_free(dev->info_z);
834a677112dSAndrew Boyer dev->info_z = NULL;
835a677112dSAndrew Boyer dev->info = NULL;
836a677112dSAndrew Boyer dev->info_pa = 0;
837a677112dSAndrew Boyer }
838a677112dSAndrew Boyer }
839a677112dSAndrew Boyer
8404610ac93SAndrew Boyer static int
iocpt_devargs(struct rte_devargs * devargs,struct iocpt_dev * dev)8414610ac93SAndrew Boyer iocpt_devargs(struct rte_devargs *devargs, struct iocpt_dev *dev)
8424610ac93SAndrew Boyer {
8434610ac93SAndrew Boyer RTE_SET_USED(devargs);
8444610ac93SAndrew Boyer RTE_SET_USED(dev);
8454610ac93SAndrew Boyer
8464610ac93SAndrew Boyer return 0;
8474610ac93SAndrew Boyer }
8484610ac93SAndrew Boyer
8494610ac93SAndrew Boyer int
iocpt_probe(void * bus_dev,struct rte_device * rte_dev,struct iocpt_dev_bars * bars,const struct iocpt_dev_intf * intf,uint8_t driver_id,uint8_t socket_id)8504610ac93SAndrew Boyer iocpt_probe(void *bus_dev, struct rte_device *rte_dev,
8514610ac93SAndrew Boyer struct iocpt_dev_bars *bars, const struct iocpt_dev_intf *intf,
8524610ac93SAndrew Boyer uint8_t driver_id, uint8_t socket_id)
8534610ac93SAndrew Boyer {
8544610ac93SAndrew Boyer struct rte_cryptodev_pmd_init_params init_params = {
8554610ac93SAndrew Boyer "iocpt",
8564610ac93SAndrew Boyer sizeof(struct iocpt_dev),
8574610ac93SAndrew Boyer socket_id,
8584610ac93SAndrew Boyer RTE_CRYPTODEV_PMD_DEFAULT_MAX_NB_QUEUE_PAIRS
8594610ac93SAndrew Boyer };
8604610ac93SAndrew Boyer struct rte_cryptodev *cdev;
8614610ac93SAndrew Boyer struct iocpt_dev *dev;
86225c896eaSAndrew Boyer uint32_t i, sig;
8634610ac93SAndrew Boyer int err;
8644610ac93SAndrew Boyer
86525c896eaSAndrew Boyer /* Check structs (trigger error at compilation time) */
86625c896eaSAndrew Boyer iocpt_struct_size_checks();
86725c896eaSAndrew Boyer
8684610ac93SAndrew Boyer if (rte_eal_process_type() != RTE_PROC_PRIMARY) {
8694610ac93SAndrew Boyer IOCPT_PRINT(ERR, "Multi-process not supported");
8704610ac93SAndrew Boyer err = -EPERM;
8714610ac93SAndrew Boyer goto err;
8724610ac93SAndrew Boyer }
8734610ac93SAndrew Boyer
8744610ac93SAndrew Boyer cdev = rte_cryptodev_pmd_create(rte_dev->name, rte_dev, &init_params);
8754610ac93SAndrew Boyer if (cdev == NULL) {
8764610ac93SAndrew Boyer IOCPT_PRINT(ERR, "Out of memory");
8774610ac93SAndrew Boyer err = -ENOMEM;
8784610ac93SAndrew Boyer goto err;
8794610ac93SAndrew Boyer }
8804610ac93SAndrew Boyer
8814610ac93SAndrew Boyer dev = cdev->data->dev_private;
8824610ac93SAndrew Boyer dev->crypto_dev = cdev;
8834610ac93SAndrew Boyer dev->bus_dev = bus_dev;
8844610ac93SAndrew Boyer dev->intf = intf;
8854610ac93SAndrew Boyer dev->driver_id = driver_id;
8864610ac93SAndrew Boyer dev->socket_id = socket_id;
8874610ac93SAndrew Boyer
8884610ac93SAndrew Boyer for (i = 0; i < bars->num_bars; i++) {
8894610ac93SAndrew Boyer struct ionic_dev_bar *bar = &bars->bar[i];
8904610ac93SAndrew Boyer
8914610ac93SAndrew Boyer IOCPT_PRINT(DEBUG,
8924610ac93SAndrew Boyer "bar[%u] = { .va = %p, .pa = %#jx, .len = %lu }",
8934610ac93SAndrew Boyer i, bar->vaddr, bar->bus_addr, bar->len);
8944610ac93SAndrew Boyer if (bar->vaddr == NULL) {
8954610ac93SAndrew Boyer IOCPT_PRINT(ERR, "Null bar found, aborting");
8964610ac93SAndrew Boyer err = -EFAULT;
8974610ac93SAndrew Boyer goto err_destroy_crypto_dev;
8984610ac93SAndrew Boyer }
8994610ac93SAndrew Boyer
9004610ac93SAndrew Boyer dev->bars.bar[i].vaddr = bar->vaddr;
9014610ac93SAndrew Boyer dev->bars.bar[i].bus_addr = bar->bus_addr;
9024610ac93SAndrew Boyer dev->bars.bar[i].len = bar->len;
9034610ac93SAndrew Boyer }
9044610ac93SAndrew Boyer dev->bars.num_bars = bars->num_bars;
9054610ac93SAndrew Boyer
9064610ac93SAndrew Boyer err = iocpt_devargs(rte_dev->devargs, dev);
9074610ac93SAndrew Boyer if (err != 0) {
9084610ac93SAndrew Boyer IOCPT_PRINT(ERR, "Cannot parse device arguments");
9094610ac93SAndrew Boyer goto err_destroy_crypto_dev;
9104610ac93SAndrew Boyer }
9114610ac93SAndrew Boyer
9124610ac93SAndrew Boyer err = iocpt_setup_bars(dev);
9134610ac93SAndrew Boyer if (err != 0) {
9144610ac93SAndrew Boyer IOCPT_PRINT(ERR, "Cannot setup BARs: %d, aborting", err);
9154610ac93SAndrew Boyer goto err_destroy_crypto_dev;
9164610ac93SAndrew Boyer }
9174610ac93SAndrew Boyer
91825c896eaSAndrew Boyer sig = ioread32(&dev->dev_info->signature);
91925c896eaSAndrew Boyer if (sig != IOCPT_DEV_INFO_SIGNATURE) {
92025c896eaSAndrew Boyer IOCPT_PRINT(ERR, "Incompatible firmware signature %#x", sig);
92125c896eaSAndrew Boyer err = -EFAULT;
92225c896eaSAndrew Boyer goto err_destroy_crypto_dev;
92325c896eaSAndrew Boyer }
92425c896eaSAndrew Boyer
92525c896eaSAndrew Boyer for (i = 0; i < IOCPT_FWVERS_BUFLEN; i++)
92625c896eaSAndrew Boyer dev->fw_version[i] = ioread8(&dev->dev_info->fw_version[i]);
92725c896eaSAndrew Boyer dev->fw_version[IOCPT_FWVERS_BUFLEN - 1] = '\0';
92825c896eaSAndrew Boyer IOCPT_PRINT(DEBUG, "%s firmware: %s", dev->name, dev->fw_version);
92925c896eaSAndrew Boyer
930a677112dSAndrew Boyer err = iocpt_dev_identify(dev);
931a677112dSAndrew Boyer if (err != 0) {
932a677112dSAndrew Boyer IOCPT_PRINT(ERR, "Cannot identify device: %d, aborting",
933a677112dSAndrew Boyer err);
934a677112dSAndrew Boyer goto err_destroy_crypto_dev;
935a677112dSAndrew Boyer }
936a677112dSAndrew Boyer
937a677112dSAndrew Boyer err = iocpt_alloc_objs(dev);
938a677112dSAndrew Boyer if (err != 0) {
939a677112dSAndrew Boyer IOCPT_PRINT(ERR, "Cannot alloc device objects: %d", err);
940a677112dSAndrew Boyer goto err_destroy_crypto_dev;
941a677112dSAndrew Boyer }
942a677112dSAndrew Boyer
9434610ac93SAndrew Boyer err = iocpt_init(dev);
9444610ac93SAndrew Boyer if (err != 0) {
9454610ac93SAndrew Boyer IOCPT_PRINT(ERR, "Cannot init device: %d, aborting", err);
946a677112dSAndrew Boyer goto err_free_objs;
9474610ac93SAndrew Boyer }
9484610ac93SAndrew Boyer
949dddfb0d9SAndrew Boyer err = iocpt_assign_ops(cdev);
950dddfb0d9SAndrew Boyer if (err != 0) {
951dddfb0d9SAndrew Boyer IOCPT_PRINT(ERR, "Failed to configure opts");
952dddfb0d9SAndrew Boyer goto err_deinit_dev;
953dddfb0d9SAndrew Boyer }
954dddfb0d9SAndrew Boyer
9554610ac93SAndrew Boyer return 0;
9564610ac93SAndrew Boyer
957dddfb0d9SAndrew Boyer err_deinit_dev:
958dddfb0d9SAndrew Boyer iocpt_deinit(dev);
959a677112dSAndrew Boyer err_free_objs:
960a677112dSAndrew Boyer iocpt_free_objs(dev);
9614610ac93SAndrew Boyer err_destroy_crypto_dev:
9624610ac93SAndrew Boyer rte_cryptodev_pmd_destroy(cdev);
9634610ac93SAndrew Boyer err:
9644610ac93SAndrew Boyer return err;
9654610ac93SAndrew Boyer }
9664610ac93SAndrew Boyer
9674610ac93SAndrew Boyer int
iocpt_remove(struct rte_device * rte_dev)9684610ac93SAndrew Boyer iocpt_remove(struct rte_device *rte_dev)
9694610ac93SAndrew Boyer {
9704610ac93SAndrew Boyer struct rte_cryptodev *cdev;
9714610ac93SAndrew Boyer struct iocpt_dev *dev;
9724610ac93SAndrew Boyer
9734610ac93SAndrew Boyer cdev = rte_cryptodev_pmd_get_named_dev(rte_dev->name);
9744610ac93SAndrew Boyer if (cdev == NULL) {
9754610ac93SAndrew Boyer IOCPT_PRINT(DEBUG, "Cannot find device %s", rte_dev->name);
9764610ac93SAndrew Boyer return -ENODEV;
9774610ac93SAndrew Boyer }
9784610ac93SAndrew Boyer
9794610ac93SAndrew Boyer dev = cdev->data->dev_private;
9804610ac93SAndrew Boyer
9814610ac93SAndrew Boyer iocpt_deinit(dev);
9824610ac93SAndrew Boyer
983a677112dSAndrew Boyer iocpt_dev_reset(dev);
984a677112dSAndrew Boyer
985a677112dSAndrew Boyer iocpt_free_objs(dev);
986a677112dSAndrew Boyer
9874610ac93SAndrew Boyer rte_cryptodev_pmd_destroy(cdev);
9884610ac93SAndrew Boyer
9894610ac93SAndrew Boyer return 0;
9904610ac93SAndrew Boyer }
9914610ac93SAndrew Boyer
9924610ac93SAndrew Boyer RTE_LOG_REGISTER_DEFAULT(iocpt_logtype, NOTICE);
993