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 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 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 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 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 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", 912c1662bbSAndrew Boyer 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 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 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 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 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 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 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 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 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; 196*c09a6e7aSAndrew 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; 205*c09a6e7aSAndrew Boyer seg_len = (uint8_t)RTE_MIN(priv->key_len - key_offset, 2066bc7f2cfSAndrew Boyer IOCPT_SESS_KEY_SEG_LEN); 207*c09a6e7aSAndrew 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 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 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 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 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 * 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 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 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 * 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 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 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 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 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 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 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 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 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 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 7484610ac93SAndrew Boyer iocpt_configure(struct iocpt_dev *dev) 7494610ac93SAndrew Boyer { 7504610ac93SAndrew Boyer RTE_SET_USED(dev); 7514610ac93SAndrew Boyer } 7524610ac93SAndrew Boyer 75380518852SAndrew Boyer int 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 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 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 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 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 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 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