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 131*aacc5f13SAndrew Boyer static void 132*aacc5f13SAndrew Boyer iocpt_get_abs_stats(const struct iocpt_dev *dev, 133*aacc5f13SAndrew Boyer struct rte_cryptodev_stats *stats) 134*aacc5f13SAndrew Boyer { 135*aacc5f13SAndrew Boyer uint32_t i; 136*aacc5f13SAndrew Boyer 137*aacc5f13SAndrew Boyer memset(stats, 0, sizeof(*stats)); 138*aacc5f13SAndrew Boyer 139*aacc5f13SAndrew Boyer /* Sum up the per-queue stats counters */ 140*aacc5f13SAndrew Boyer for (i = 0; i < dev->crypto_dev->data->nb_queue_pairs; i++) { 141*aacc5f13SAndrew Boyer struct rte_cryptodev_stats *q_stats = &dev->cryptoqs[i]->stats; 142*aacc5f13SAndrew Boyer 143*aacc5f13SAndrew Boyer stats->enqueued_count += q_stats->enqueued_count; 144*aacc5f13SAndrew Boyer stats->dequeued_count += q_stats->dequeued_count; 145*aacc5f13SAndrew Boyer stats->enqueue_err_count += q_stats->enqueue_err_count; 146*aacc5f13SAndrew Boyer stats->dequeue_err_count += q_stats->dequeue_err_count; 147*aacc5f13SAndrew Boyer } 148*aacc5f13SAndrew Boyer } 149*aacc5f13SAndrew Boyer 150*aacc5f13SAndrew Boyer void 151*aacc5f13SAndrew Boyer iocpt_get_stats(const struct iocpt_dev *dev, struct rte_cryptodev_stats *stats) 152*aacc5f13SAndrew Boyer { 153*aacc5f13SAndrew Boyer /* Retrieve the new absolute stats values */ 154*aacc5f13SAndrew Boyer iocpt_get_abs_stats(dev, stats); 155*aacc5f13SAndrew Boyer 156*aacc5f13SAndrew Boyer /* Subtract the base stats values to get relative values */ 157*aacc5f13SAndrew Boyer stats->enqueued_count -= dev->stats_base.enqueued_count; 158*aacc5f13SAndrew Boyer stats->dequeued_count -= dev->stats_base.dequeued_count; 159*aacc5f13SAndrew Boyer stats->enqueue_err_count -= dev->stats_base.enqueue_err_count; 160*aacc5f13SAndrew Boyer stats->dequeue_err_count -= dev->stats_base.dequeue_err_count; 161*aacc5f13SAndrew Boyer } 162*aacc5f13SAndrew Boyer 163*aacc5f13SAndrew Boyer void 164*aacc5f13SAndrew Boyer iocpt_reset_stats(struct iocpt_dev *dev) 165*aacc5f13SAndrew Boyer { 166*aacc5f13SAndrew Boyer uint32_t i; 167*aacc5f13SAndrew Boyer 168*aacc5f13SAndrew Boyer /* Erase the per-queue stats counters */ 169*aacc5f13SAndrew Boyer for (i = 0; i < dev->crypto_dev->data->nb_queue_pairs; i++) 170*aacc5f13SAndrew Boyer memset(&dev->cryptoqs[i]->stats, 0, 171*aacc5f13SAndrew Boyer sizeof(dev->cryptoqs[i]->stats)); 172*aacc5f13SAndrew Boyer 173*aacc5f13SAndrew Boyer /* Update the base stats values */ 174*aacc5f13SAndrew Boyer iocpt_get_abs_stats(dev, &dev->stats_base); 175*aacc5f13SAndrew Boyer } 176*aacc5f13SAndrew 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; 1966bc7f2cfSAndrew Boyer uint8_t key_segs, seg; 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; 2056bc7f2cfSAndrew Boyer memcpy(cmd->key, &priv->key[key_offset], 2066bc7f2cfSAndrew Boyer IOCPT_SESS_KEY_SEG_LEN); 2076bc7f2cfSAndrew Boyer cmd->key_seg_idx = seg; 2086bc7f2cfSAndrew Boyer 2096bc7f2cfSAndrew Boyer /* Mark final segment */ 2106bc7f2cfSAndrew Boyer if (seg + 1 == key_segs) 2116bc7f2cfSAndrew Boyer cmd->flags |= rte_cpu_to_le_16(IOCPT_SCTL_F_END); 2126bc7f2cfSAndrew Boyer 2136bc7f2cfSAndrew Boyer err = iocpt_adminq_post_wait(dev, &ctx); 2146bc7f2cfSAndrew Boyer if (err != 0) 2156bc7f2cfSAndrew Boyer return err; 2166bc7f2cfSAndrew Boyer } 2176bc7f2cfSAndrew Boyer 2186bc7f2cfSAndrew Boyer return 0; 2196bc7f2cfSAndrew Boyer } 2206bc7f2cfSAndrew Boyer 22154d56abaSAndrew Boyer static int 22254d56abaSAndrew Boyer iocpt_session_wdog(struct iocpt_dev *dev) 22354d56abaSAndrew Boyer { 22454d56abaSAndrew Boyer struct iocpt_session_priv priv = { 22554d56abaSAndrew Boyer .dev = dev, 22654d56abaSAndrew Boyer .index = IOCPT_Q_WDOG_SESS_IDX, 22754d56abaSAndrew Boyer .type = IOCPT_SESS_AEAD_AES_GCM, 22854d56abaSAndrew Boyer .key_len = IOCPT_Q_WDOG_KEY_LEN, 22954d56abaSAndrew Boyer }; 23054d56abaSAndrew Boyer 23154d56abaSAndrew Boyer /* Reserve session 0 for queue watchdog */ 23254d56abaSAndrew Boyer rte_bitmap_clear(dev->sess_bm, IOCPT_Q_WDOG_SESS_IDX); 23354d56abaSAndrew Boyer 23454d56abaSAndrew Boyer return iocpt_session_write(&priv, IOCPT_SESS_INIT); 23554d56abaSAndrew Boyer } 23654d56abaSAndrew Boyer 2376bc7f2cfSAndrew Boyer int 2386bc7f2cfSAndrew Boyer iocpt_session_init(struct iocpt_session_priv *priv) 2396bc7f2cfSAndrew Boyer { 2406bc7f2cfSAndrew Boyer struct iocpt_dev *dev = priv->dev; 2416bc7f2cfSAndrew Boyer uint64_t bm_slab = 0; 2426bc7f2cfSAndrew Boyer uint32_t bm_pos = 0; 2436bc7f2cfSAndrew Boyer int err = 0; 2446bc7f2cfSAndrew Boyer 2456bc7f2cfSAndrew Boyer rte_spinlock_lock(&dev->adminq_lock); 2466bc7f2cfSAndrew Boyer 2476bc7f2cfSAndrew Boyer if (rte_bitmap_scan(dev->sess_bm, &bm_pos, &bm_slab) > 0) { 2486bc7f2cfSAndrew Boyer priv->index = bm_pos + rte_ctz64(bm_slab); 2496bc7f2cfSAndrew Boyer rte_bitmap_clear(dev->sess_bm, priv->index); 2506bc7f2cfSAndrew Boyer } else 2516bc7f2cfSAndrew Boyer err = -ENOSPC; 2526bc7f2cfSAndrew Boyer 2536bc7f2cfSAndrew Boyer rte_spinlock_unlock(&dev->adminq_lock); 2546bc7f2cfSAndrew Boyer 2556bc7f2cfSAndrew Boyer if (err != 0) { 2566bc7f2cfSAndrew Boyer IOCPT_PRINT(ERR, "session index space exhausted"); 2576bc7f2cfSAndrew Boyer return err; 2586bc7f2cfSAndrew Boyer } 2596bc7f2cfSAndrew Boyer 2606bc7f2cfSAndrew Boyer err = iocpt_session_write(priv, IOCPT_SESS_INIT); 2616bc7f2cfSAndrew Boyer if (err != 0) { 2626bc7f2cfSAndrew Boyer rte_spinlock_lock(&dev->adminq_lock); 2636bc7f2cfSAndrew Boyer rte_bitmap_set(dev->sess_bm, priv->index); 2646bc7f2cfSAndrew Boyer rte_spinlock_unlock(&dev->adminq_lock); 2656bc7f2cfSAndrew Boyer return err; 2666bc7f2cfSAndrew Boyer } 2676bc7f2cfSAndrew Boyer 2686bc7f2cfSAndrew Boyer priv->flags |= IOCPT_S_F_INITED; 2696bc7f2cfSAndrew Boyer 2706bc7f2cfSAndrew Boyer return 0; 2716bc7f2cfSAndrew Boyer } 2726bc7f2cfSAndrew Boyer 2736bc7f2cfSAndrew Boyer int 2746bc7f2cfSAndrew Boyer iocpt_session_update(struct iocpt_session_priv *priv) 2756bc7f2cfSAndrew Boyer { 2766bc7f2cfSAndrew Boyer return iocpt_session_write(priv, IOCPT_SESS_UPDATE_KEY); 2776bc7f2cfSAndrew Boyer } 2786bc7f2cfSAndrew Boyer 2796bc7f2cfSAndrew Boyer void 2806bc7f2cfSAndrew Boyer iocpt_session_deinit(struct iocpt_session_priv *priv) 2816bc7f2cfSAndrew Boyer { 2826bc7f2cfSAndrew Boyer struct iocpt_dev *dev = priv->dev; 2836bc7f2cfSAndrew Boyer struct iocpt_admin_ctx ctx = { 2846bc7f2cfSAndrew Boyer .pending_work = true, 2856bc7f2cfSAndrew Boyer .cmd.sess_control = { 2866bc7f2cfSAndrew Boyer .opcode = IOCPT_CMD_SESS_CONTROL, 2876bc7f2cfSAndrew Boyer .type = priv->type, 2886bc7f2cfSAndrew Boyer .oper = IOCPT_SESS_DISABLE, 2896bc7f2cfSAndrew Boyer .index = rte_cpu_to_le_32(priv->index), 2906bc7f2cfSAndrew Boyer .key_len = rte_cpu_to_le_16(priv->key_len), 2916bc7f2cfSAndrew Boyer }, 2926bc7f2cfSAndrew Boyer }; 2936bc7f2cfSAndrew Boyer 2946bc7f2cfSAndrew Boyer (void)iocpt_adminq_post_wait(dev, &ctx); 2956bc7f2cfSAndrew Boyer 2966bc7f2cfSAndrew Boyer rte_spinlock_lock(&dev->adminq_lock); 2976bc7f2cfSAndrew Boyer rte_bitmap_set(dev->sess_bm, priv->index); 2986bc7f2cfSAndrew Boyer rte_spinlock_unlock(&dev->adminq_lock); 2996bc7f2cfSAndrew Boyer 3006bc7f2cfSAndrew Boyer priv->flags &= ~IOCPT_S_F_INITED; 3016bc7f2cfSAndrew Boyer } 3026bc7f2cfSAndrew Boyer 303a677112dSAndrew Boyer static const struct rte_memzone * 304a677112dSAndrew Boyer iocpt_dma_zone_reserve(const char *type_name, uint16_t qid, size_t size, 305a677112dSAndrew Boyer unsigned int align, int socket_id) 306a677112dSAndrew Boyer { 307a677112dSAndrew Boyer char zone_name[RTE_MEMZONE_NAMESIZE]; 308a677112dSAndrew Boyer const struct rte_memzone *mz; 309a677112dSAndrew Boyer int err; 310a677112dSAndrew Boyer 311a677112dSAndrew Boyer err = snprintf(zone_name, sizeof(zone_name), 312a677112dSAndrew Boyer "iocpt_%s_%u", type_name, qid); 313a677112dSAndrew Boyer if (err >= RTE_MEMZONE_NAMESIZE) { 314a677112dSAndrew Boyer IOCPT_PRINT(ERR, "Name %s too long", type_name); 315a677112dSAndrew Boyer return NULL; 316a677112dSAndrew Boyer } 317a677112dSAndrew Boyer 318a677112dSAndrew Boyer mz = rte_memzone_lookup(zone_name); 319a677112dSAndrew Boyer if (mz != NULL) 320a677112dSAndrew Boyer return mz; 321a677112dSAndrew Boyer 322a677112dSAndrew Boyer return rte_memzone_reserve_aligned(zone_name, size, socket_id, 323a677112dSAndrew Boyer RTE_MEMZONE_IOVA_CONTIG, align); 324a677112dSAndrew Boyer } 325a677112dSAndrew Boyer 326a677112dSAndrew Boyer static int 3272c1662bbSAndrew Boyer iocpt_commonq_alloc(struct iocpt_dev *dev, 3282c1662bbSAndrew Boyer uint8_t type, 3292c1662bbSAndrew Boyer size_t struct_size, 3302c1662bbSAndrew Boyer uint32_t socket_id, 3312c1662bbSAndrew Boyer uint32_t index, 3322c1662bbSAndrew Boyer const char *type_name, 3332c1662bbSAndrew Boyer uint16_t flags, 3342c1662bbSAndrew Boyer uint16_t num_descs, 3352c1662bbSAndrew Boyer uint16_t num_segs, 3362c1662bbSAndrew Boyer uint16_t desc_size, 3372c1662bbSAndrew Boyer uint16_t cq_desc_size, 3382c1662bbSAndrew Boyer uint16_t sg_desc_size, 3392c1662bbSAndrew Boyer struct iocpt_common_q **comq) 3402c1662bbSAndrew Boyer { 3412c1662bbSAndrew Boyer struct iocpt_common_q *new; 3422c1662bbSAndrew Boyer uint32_t q_size, cq_size, sg_size, total_size; 3432c1662bbSAndrew Boyer void *q_base, *cq_base, *sg_base; 3442c1662bbSAndrew Boyer rte_iova_t q_base_pa = 0; 3452c1662bbSAndrew Boyer rte_iova_t cq_base_pa = 0; 3462c1662bbSAndrew Boyer rte_iova_t sg_base_pa = 0; 3472c1662bbSAndrew Boyer size_t page_size = rte_mem_page_size(); 3482c1662bbSAndrew Boyer int err; 3492c1662bbSAndrew Boyer 3502c1662bbSAndrew Boyer *comq = NULL; 3512c1662bbSAndrew Boyer 3522c1662bbSAndrew Boyer q_size = num_descs * desc_size; 3532c1662bbSAndrew Boyer cq_size = num_descs * cq_desc_size; 3542c1662bbSAndrew Boyer sg_size = num_descs * sg_desc_size; 3552c1662bbSAndrew Boyer 3562c1662bbSAndrew Boyer /* 3572c1662bbSAndrew Boyer * Note: aligning q_size/cq_size is not enough due to cq_base address 3582c1662bbSAndrew Boyer * aligning as q_base could be not aligned to the page. 3592c1662bbSAndrew Boyer * Adding page_size. 3602c1662bbSAndrew Boyer */ 3612c1662bbSAndrew Boyer total_size = RTE_ALIGN(q_size, page_size) + 3622c1662bbSAndrew Boyer RTE_ALIGN(cq_size, page_size) + page_size; 3632c1662bbSAndrew Boyer if (flags & IOCPT_Q_F_SG) 3642c1662bbSAndrew Boyer total_size += RTE_ALIGN(sg_size, page_size) + page_size; 3652c1662bbSAndrew Boyer 3662c1662bbSAndrew Boyer new = rte_zmalloc_socket("iocpt", struct_size, 3672c1662bbSAndrew Boyer RTE_CACHE_LINE_SIZE, socket_id); 3682c1662bbSAndrew Boyer if (new == NULL) { 3692c1662bbSAndrew Boyer IOCPT_PRINT(ERR, "Cannot allocate queue structure"); 3702c1662bbSAndrew Boyer return -ENOMEM; 3712c1662bbSAndrew Boyer } 3722c1662bbSAndrew Boyer 3732c1662bbSAndrew Boyer new->dev = dev; 3742c1662bbSAndrew Boyer 3752c1662bbSAndrew Boyer err = iocpt_q_init(&new->q, type, index, num_descs, num_segs, 3762c1662bbSAndrew Boyer socket_id); 3772c1662bbSAndrew Boyer if (err != 0) { 3782c1662bbSAndrew Boyer IOCPT_PRINT(ERR, "Queue initialization failed"); 3792c1662bbSAndrew Boyer goto err_free_q; 3802c1662bbSAndrew Boyer } 3812c1662bbSAndrew Boyer 3822c1662bbSAndrew Boyer err = iocpt_cq_init(&new->cq, num_descs); 3832c1662bbSAndrew Boyer if (err != 0) { 3842c1662bbSAndrew Boyer IOCPT_PRINT(ERR, "Completion queue initialization failed"); 3852c1662bbSAndrew Boyer goto err_deinit_q; 3862c1662bbSAndrew Boyer } 3872c1662bbSAndrew Boyer 3882c1662bbSAndrew Boyer new->base_z = iocpt_dma_zone_reserve(type_name, index, total_size, 3892c1662bbSAndrew Boyer IONIC_ALIGN, socket_id); 3902c1662bbSAndrew Boyer if (new->base_z == NULL) { 3912c1662bbSAndrew Boyer IOCPT_PRINT(ERR, "Cannot reserve queue DMA memory"); 3922c1662bbSAndrew Boyer err = -ENOMEM; 3932c1662bbSAndrew Boyer goto err_deinit_cq; 3942c1662bbSAndrew Boyer } 3952c1662bbSAndrew Boyer 3962c1662bbSAndrew Boyer new->base = new->base_z->addr; 3972c1662bbSAndrew Boyer new->base_pa = new->base_z->iova; 3982c1662bbSAndrew Boyer 3992c1662bbSAndrew Boyer q_base = new->base; 4002c1662bbSAndrew Boyer q_base_pa = new->base_pa; 4012c1662bbSAndrew Boyer iocpt_q_map(&new->q, q_base, q_base_pa); 4022c1662bbSAndrew Boyer 4032c1662bbSAndrew Boyer cq_base = (void *)RTE_ALIGN((uintptr_t)q_base + q_size, page_size); 4042c1662bbSAndrew Boyer cq_base_pa = RTE_ALIGN(q_base_pa + q_size, page_size); 4052c1662bbSAndrew Boyer iocpt_cq_map(&new->cq, cq_base, cq_base_pa); 4062c1662bbSAndrew Boyer 4072c1662bbSAndrew Boyer if (flags & IOCPT_Q_F_SG) { 4082c1662bbSAndrew Boyer sg_base = (void *)RTE_ALIGN((uintptr_t)cq_base + cq_size, 4092c1662bbSAndrew Boyer page_size); 4102c1662bbSAndrew Boyer sg_base_pa = RTE_ALIGN(cq_base_pa + cq_size, page_size); 4112c1662bbSAndrew Boyer iocpt_q_sg_map(&new->q, sg_base, sg_base_pa); 4122c1662bbSAndrew Boyer } 4132c1662bbSAndrew Boyer 4142c1662bbSAndrew Boyer IOCPT_PRINT(DEBUG, "q_base_pa %#jx cq_base_pa %#jx sg_base_pa %#jx", 4152c1662bbSAndrew Boyer q_base_pa, cq_base_pa, sg_base_pa); 4162c1662bbSAndrew Boyer 4172c1662bbSAndrew Boyer *comq = new; 4182c1662bbSAndrew Boyer 4192c1662bbSAndrew Boyer return 0; 4202c1662bbSAndrew Boyer 4212c1662bbSAndrew Boyer err_deinit_cq: 4222c1662bbSAndrew Boyer err_deinit_q: 4232c1662bbSAndrew Boyer iocpt_q_free(&new->q); 4242c1662bbSAndrew Boyer err_free_q: 4252c1662bbSAndrew Boyer rte_free(new); 4262c1662bbSAndrew Boyer return err; 4272c1662bbSAndrew Boyer } 4282c1662bbSAndrew Boyer 42980518852SAndrew Boyer int 43080518852SAndrew Boyer iocpt_cryptoq_alloc(struct iocpt_dev *dev, uint32_t socket_id, uint32_t index, 43180518852SAndrew Boyer uint16_t num_descs) 43280518852SAndrew Boyer { 43380518852SAndrew Boyer struct iocpt_crypto_q *cptq; 43480518852SAndrew Boyer uint16_t flags = 0; 43580518852SAndrew Boyer int err; 43680518852SAndrew Boyer 43780518852SAndrew Boyer /* CryptoQ always supports scatter-gather */ 43880518852SAndrew Boyer flags |= IOCPT_Q_F_SG; 43980518852SAndrew Boyer 44080518852SAndrew Boyer IOCPT_PRINT(DEBUG, "cptq %u num_descs %u num_segs %u", 44180518852SAndrew Boyer index, num_descs, 1); 44280518852SAndrew Boyer 44380518852SAndrew Boyer err = iocpt_commonq_alloc(dev, 44480518852SAndrew Boyer IOCPT_QTYPE_CRYPTOQ, 44580518852SAndrew Boyer sizeof(struct iocpt_crypto_q), 44680518852SAndrew Boyer socket_id, 44780518852SAndrew Boyer index, 44880518852SAndrew Boyer "crypto", 44980518852SAndrew Boyer flags, 45080518852SAndrew Boyer num_descs, 45180518852SAndrew Boyer 1, 45280518852SAndrew Boyer sizeof(struct iocpt_crypto_desc), 45380518852SAndrew Boyer sizeof(struct iocpt_crypto_comp), 45480518852SAndrew Boyer sizeof(struct iocpt_crypto_sg_desc), 45580518852SAndrew Boyer (struct iocpt_common_q **)&cptq); 45680518852SAndrew Boyer if (err != 0) 45780518852SAndrew Boyer return err; 45880518852SAndrew Boyer 45980518852SAndrew Boyer cptq->flags = flags; 46080518852SAndrew Boyer 46180518852SAndrew Boyer dev->cryptoqs[index] = cptq; 46280518852SAndrew Boyer 46380518852SAndrew Boyer return 0; 46480518852SAndrew Boyer } 46580518852SAndrew Boyer 4662c1662bbSAndrew Boyer struct ionic_doorbell * 4672c1662bbSAndrew Boyer iocpt_db_map(struct iocpt_dev *dev, struct iocpt_queue *q) 4682c1662bbSAndrew Boyer { 4692c1662bbSAndrew Boyer return dev->db_pages + q->hw_type; 4702c1662bbSAndrew Boyer } 4712c1662bbSAndrew Boyer 4722c1662bbSAndrew Boyer static int 47380518852SAndrew Boyer iocpt_cryptoq_init(struct iocpt_crypto_q *cptq) 47480518852SAndrew Boyer { 47580518852SAndrew Boyer struct iocpt_queue *q = &cptq->q; 47680518852SAndrew Boyer struct iocpt_dev *dev = cptq->dev; 47780518852SAndrew Boyer struct iocpt_cq *cq = &cptq->cq; 47880518852SAndrew Boyer struct iocpt_admin_ctx ctx = { 47980518852SAndrew Boyer .pending_work = true, 48080518852SAndrew Boyer .cmd.q_init = { 48180518852SAndrew Boyer .opcode = IOCPT_CMD_Q_INIT, 48280518852SAndrew Boyer .type = IOCPT_QTYPE_CRYPTOQ, 48380518852SAndrew Boyer .ver = dev->qtype_info[IOCPT_QTYPE_CRYPTOQ].version, 48480518852SAndrew Boyer .index = rte_cpu_to_le_32(q->index), 48580518852SAndrew Boyer .flags = rte_cpu_to_le_16(IOCPT_QINIT_F_ENA | 48680518852SAndrew Boyer IOCPT_QINIT_F_SG), 48780518852SAndrew Boyer .intr_index = rte_cpu_to_le_16(IONIC_INTR_NONE), 48880518852SAndrew Boyer .ring_size = rte_log2_u32(q->num_descs), 48980518852SAndrew Boyer .ring_base = rte_cpu_to_le_64(q->base_pa), 49080518852SAndrew Boyer .cq_ring_base = rte_cpu_to_le_64(cq->base_pa), 49180518852SAndrew Boyer .sg_ring_base = rte_cpu_to_le_64(q->sg_base_pa), 49280518852SAndrew Boyer }, 49380518852SAndrew Boyer }; 49480518852SAndrew Boyer int err; 49580518852SAndrew Boyer 49680518852SAndrew Boyer IOCPT_PRINT(DEBUG, "cptq_init.index %d", q->index); 49780518852SAndrew Boyer IOCPT_PRINT(DEBUG, "cptq_init.ring_base %#jx", q->base_pa); 49880518852SAndrew Boyer IOCPT_PRINT(DEBUG, "cptq_init.ring_size %d", 49980518852SAndrew Boyer ctx.cmd.q_init.ring_size); 50080518852SAndrew Boyer IOCPT_PRINT(DEBUG, "cptq_init.ver %u", ctx.cmd.q_init.ver); 50180518852SAndrew Boyer 50280518852SAndrew Boyer iocpt_q_reset(q); 50380518852SAndrew Boyer iocpt_cq_reset(cq); 50480518852SAndrew Boyer 50580518852SAndrew Boyer err = iocpt_adminq_post_wait(dev, &ctx); 50680518852SAndrew Boyer if (err != 0) 50780518852SAndrew Boyer return err; 50880518852SAndrew Boyer 50980518852SAndrew Boyer q->hw_type = ctx.comp.q_init.hw_type; 51080518852SAndrew Boyer q->hw_index = rte_le_to_cpu_32(ctx.comp.q_init.hw_index); 51180518852SAndrew Boyer q->db = iocpt_db_map(dev, q); 51280518852SAndrew Boyer 51380518852SAndrew Boyer IOCPT_PRINT(DEBUG, "cptq->hw_type %d", q->hw_type); 51480518852SAndrew Boyer IOCPT_PRINT(DEBUG, "cptq->hw_index %d", q->hw_index); 51580518852SAndrew Boyer IOCPT_PRINT(DEBUG, "cptq->db %p", q->db); 51680518852SAndrew Boyer 51780518852SAndrew Boyer cptq->flags |= IOCPT_Q_F_INITED; 51880518852SAndrew Boyer 51980518852SAndrew Boyer return 0; 52080518852SAndrew Boyer } 52180518852SAndrew Boyer 52280518852SAndrew Boyer static void 52380518852SAndrew Boyer iocpt_cryptoq_deinit(struct iocpt_crypto_q *cptq) 52480518852SAndrew Boyer { 52580518852SAndrew Boyer struct iocpt_dev *dev = cptq->dev; 52680518852SAndrew Boyer struct iocpt_admin_ctx ctx = { 52780518852SAndrew Boyer .pending_work = true, 52880518852SAndrew Boyer .cmd.q_control = { 52980518852SAndrew Boyer .opcode = IOCPT_CMD_Q_CONTROL, 53080518852SAndrew Boyer .type = IOCPT_QTYPE_CRYPTOQ, 53180518852SAndrew Boyer .index = rte_cpu_to_le_32(cptq->q.index), 53280518852SAndrew Boyer .oper = IOCPT_Q_DISABLE, 53380518852SAndrew Boyer }, 53480518852SAndrew Boyer }; 53580518852SAndrew Boyer unsigned long sleep_usec = 100UL * 1000; 53680518852SAndrew Boyer uint32_t sleep_cnt, sleep_max = IOCPT_CRYPTOQ_WAIT; 53780518852SAndrew Boyer int err; 53880518852SAndrew Boyer 53980518852SAndrew Boyer for (sleep_cnt = 0; sleep_cnt < sleep_max; sleep_cnt++) { 54080518852SAndrew Boyer ctx.pending_work = true; 54180518852SAndrew Boyer 54280518852SAndrew Boyer err = iocpt_adminq_post_wait(dev, &ctx); 54380518852SAndrew Boyer if (err != -EAGAIN) 54480518852SAndrew Boyer break; 54580518852SAndrew Boyer 54680518852SAndrew Boyer rte_delay_us_block(sleep_usec); 54780518852SAndrew Boyer } 54880518852SAndrew Boyer 54980518852SAndrew Boyer if (err != 0) 55080518852SAndrew Boyer IOCPT_PRINT(ERR, "Deinit queue %u returned %d after %u ms", 55180518852SAndrew Boyer cptq->q.index, err, sleep_cnt * 100); 55280518852SAndrew Boyer else 55380518852SAndrew Boyer IOCPT_PRINT(DEBUG, "Deinit queue %u returned %d after %u ms", 55480518852SAndrew Boyer cptq->q.index, err, sleep_cnt * 100); 55580518852SAndrew Boyer 55654d56abaSAndrew Boyer IOCPT_PRINT(DEBUG, "Queue %u watchdog: enq %"PRIu64" deq %"PRIu64, 55754d56abaSAndrew Boyer cptq->q.index, cptq->enqueued_wdogs, cptq->dequeued_wdogs); 55854d56abaSAndrew Boyer 55980518852SAndrew Boyer cptq->flags &= ~IOCPT_Q_F_INITED; 56080518852SAndrew Boyer } 56180518852SAndrew Boyer 56280518852SAndrew Boyer void 56380518852SAndrew Boyer iocpt_cryptoq_free(struct iocpt_crypto_q *cptq) 56480518852SAndrew Boyer { 56580518852SAndrew Boyer if (cptq == NULL) 56680518852SAndrew Boyer return; 56780518852SAndrew Boyer 56880518852SAndrew Boyer if (cptq->base_z != NULL) { 56980518852SAndrew Boyer rte_memzone_free(cptq->base_z); 57080518852SAndrew Boyer cptq->base_z = NULL; 57180518852SAndrew Boyer cptq->base = NULL; 57280518852SAndrew Boyer cptq->base_pa = 0; 57380518852SAndrew Boyer } 57480518852SAndrew Boyer 57580518852SAndrew Boyer iocpt_q_free(&cptq->q); 57680518852SAndrew Boyer 57780518852SAndrew Boyer rte_free(cptq); 57880518852SAndrew Boyer } 57980518852SAndrew Boyer 58080518852SAndrew Boyer static int 5812c1662bbSAndrew Boyer iocpt_adminq_alloc(struct iocpt_dev *dev) 5822c1662bbSAndrew Boyer { 5832c1662bbSAndrew Boyer struct iocpt_admin_q *aq; 5842c1662bbSAndrew Boyer uint16_t num_descs = IOCPT_ADMINQ_LENGTH; 5852c1662bbSAndrew Boyer uint16_t flags = 0; 5862c1662bbSAndrew Boyer int err; 5872c1662bbSAndrew Boyer 5882c1662bbSAndrew Boyer err = iocpt_commonq_alloc(dev, 5892c1662bbSAndrew Boyer IOCPT_QTYPE_ADMINQ, 5902c1662bbSAndrew Boyer sizeof(struct iocpt_admin_q), 5912c1662bbSAndrew Boyer rte_socket_id(), 5922c1662bbSAndrew Boyer 0, 5932c1662bbSAndrew Boyer "admin", 5942c1662bbSAndrew Boyer flags, 5952c1662bbSAndrew Boyer num_descs, 5962c1662bbSAndrew Boyer 1, 5972c1662bbSAndrew Boyer sizeof(struct iocpt_admin_cmd), 5982c1662bbSAndrew Boyer sizeof(struct iocpt_admin_comp), 5992c1662bbSAndrew Boyer 0, 6002c1662bbSAndrew Boyer (struct iocpt_common_q **)&aq); 6012c1662bbSAndrew Boyer if (err != 0) 6022c1662bbSAndrew Boyer return err; 6032c1662bbSAndrew Boyer 6042c1662bbSAndrew Boyer aq->flags = flags; 6052c1662bbSAndrew Boyer 6062c1662bbSAndrew Boyer dev->adminq = aq; 6072c1662bbSAndrew Boyer 6082c1662bbSAndrew Boyer return 0; 6092c1662bbSAndrew Boyer } 6102c1662bbSAndrew Boyer 6112c1662bbSAndrew Boyer static int 6122c1662bbSAndrew Boyer iocpt_adminq_init(struct iocpt_dev *dev) 6132c1662bbSAndrew Boyer { 6142c1662bbSAndrew Boyer return iocpt_dev_adminq_init(dev); 6152c1662bbSAndrew Boyer } 6162c1662bbSAndrew Boyer 6172c1662bbSAndrew Boyer static void 6182c1662bbSAndrew Boyer iocpt_adminq_deinit(struct iocpt_dev *dev) 6192c1662bbSAndrew Boyer { 6202c1662bbSAndrew Boyer dev->adminq->flags &= ~IOCPT_Q_F_INITED; 6212c1662bbSAndrew Boyer } 6222c1662bbSAndrew Boyer 6232c1662bbSAndrew Boyer static void 6242c1662bbSAndrew Boyer iocpt_adminq_free(struct iocpt_admin_q *aq) 6252c1662bbSAndrew Boyer { 6262c1662bbSAndrew Boyer if (aq->base_z != NULL) { 6272c1662bbSAndrew Boyer rte_memzone_free(aq->base_z); 6282c1662bbSAndrew Boyer aq->base_z = NULL; 6292c1662bbSAndrew Boyer aq->base = NULL; 6302c1662bbSAndrew Boyer aq->base_pa = 0; 6312c1662bbSAndrew Boyer } 6322c1662bbSAndrew Boyer 6332c1662bbSAndrew Boyer iocpt_q_free(&aq->q); 6342c1662bbSAndrew Boyer 6352c1662bbSAndrew Boyer rte_free(aq); 6362c1662bbSAndrew Boyer } 6372c1662bbSAndrew Boyer 6382c1662bbSAndrew Boyer static int 639a677112dSAndrew Boyer iocpt_alloc_objs(struct iocpt_dev *dev) 640a677112dSAndrew Boyer { 6416bc7f2cfSAndrew Boyer uint32_t bmsize, i; 6426bc7f2cfSAndrew Boyer uint8_t *bm; 643a677112dSAndrew Boyer int err; 644a677112dSAndrew Boyer 645a677112dSAndrew Boyer IOCPT_PRINT(DEBUG, "Crypto: %s", dev->name); 646a677112dSAndrew Boyer 64780518852SAndrew Boyer dev->cryptoqs = rte_calloc_socket("iocpt", 64880518852SAndrew Boyer dev->max_qps, sizeof(*dev->cryptoqs), 64980518852SAndrew Boyer RTE_CACHE_LINE_SIZE, dev->socket_id); 65080518852SAndrew Boyer if (dev->cryptoqs == NULL) { 65180518852SAndrew Boyer IOCPT_PRINT(ERR, "Cannot allocate tx queues array"); 65280518852SAndrew Boyer return -ENOMEM; 65380518852SAndrew Boyer } 65480518852SAndrew Boyer 6552c1662bbSAndrew Boyer rte_spinlock_init(&dev->adminq_lock); 6562c1662bbSAndrew Boyer rte_spinlock_init(&dev->adminq_service_lock); 6572c1662bbSAndrew Boyer 6582c1662bbSAndrew Boyer err = iocpt_adminq_alloc(dev); 6592c1662bbSAndrew Boyer if (err != 0) { 6602c1662bbSAndrew Boyer IOCPT_PRINT(ERR, "Cannot allocate admin queue"); 6612c1662bbSAndrew Boyer err = -ENOMEM; 66280518852SAndrew Boyer goto err_free_cryptoqs; 6632c1662bbSAndrew Boyer } 6642c1662bbSAndrew Boyer 665a677112dSAndrew Boyer dev->info_sz = RTE_ALIGN(sizeof(*dev->info), rte_mem_page_size()); 666a677112dSAndrew Boyer dev->info_z = iocpt_dma_zone_reserve("info", 0, dev->info_sz, 667a677112dSAndrew Boyer IONIC_ALIGN, dev->socket_id); 668a677112dSAndrew Boyer if (dev->info_z == NULL) { 669a677112dSAndrew Boyer IOCPT_PRINT(ERR, "Cannot allocate dev info memory"); 670a677112dSAndrew Boyer err = -ENOMEM; 6712c1662bbSAndrew Boyer goto err_free_adminq; 672a677112dSAndrew Boyer } 673a677112dSAndrew Boyer 674a677112dSAndrew Boyer dev->info = dev->info_z->addr; 675a677112dSAndrew Boyer dev->info_pa = dev->info_z->iova; 676a677112dSAndrew Boyer 6776bc7f2cfSAndrew Boyer bmsize = rte_bitmap_get_memory_footprint(dev->max_sessions); 6786bc7f2cfSAndrew Boyer bm = rte_malloc_socket("iocpt", bmsize, 6796bc7f2cfSAndrew Boyer RTE_CACHE_LINE_SIZE, dev->socket_id); 6806bc7f2cfSAndrew Boyer if (bm == NULL) { 6816bc7f2cfSAndrew Boyer IOCPT_PRINT(ERR, "Cannot allocate %uB bitmap memory", bmsize); 6826bc7f2cfSAndrew Boyer err = -ENOMEM; 6836bc7f2cfSAndrew Boyer goto err_free_dmazone; 6846bc7f2cfSAndrew Boyer } 6856bc7f2cfSAndrew Boyer 6866bc7f2cfSAndrew Boyer dev->sess_bm = rte_bitmap_init(dev->max_sessions, bm, bmsize); 6876bc7f2cfSAndrew Boyer if (dev->sess_bm == NULL) { 6886bc7f2cfSAndrew Boyer IOCPT_PRINT(ERR, "Cannot initialize bitmap"); 6896bc7f2cfSAndrew Boyer err = -EFAULT; 6906bc7f2cfSAndrew Boyer goto err_free_bm; 6916bc7f2cfSAndrew Boyer } 6926bc7f2cfSAndrew Boyer for (i = 0; i < dev->max_sessions; i++) 6936bc7f2cfSAndrew Boyer rte_bitmap_set(dev->sess_bm, i); 6946bc7f2cfSAndrew Boyer 695a677112dSAndrew Boyer return 0; 696a677112dSAndrew Boyer 6976bc7f2cfSAndrew Boyer err_free_bm: 6986bc7f2cfSAndrew Boyer rte_free(bm); 6996bc7f2cfSAndrew Boyer err_free_dmazone: 7006bc7f2cfSAndrew Boyer rte_memzone_free(dev->info_z); 7016bc7f2cfSAndrew Boyer dev->info_z = NULL; 7026bc7f2cfSAndrew Boyer dev->info = NULL; 7036bc7f2cfSAndrew Boyer dev->info_pa = 0; 7042c1662bbSAndrew Boyer err_free_adminq: 7052c1662bbSAndrew Boyer iocpt_adminq_free(dev->adminq); 7062c1662bbSAndrew Boyer dev->adminq = NULL; 70780518852SAndrew Boyer err_free_cryptoqs: 70880518852SAndrew Boyer rte_free(dev->cryptoqs); 70980518852SAndrew Boyer dev->cryptoqs = NULL; 710a677112dSAndrew Boyer return err; 711a677112dSAndrew Boyer } 712a677112dSAndrew Boyer 7134610ac93SAndrew Boyer static int 7144610ac93SAndrew Boyer iocpt_init(struct iocpt_dev *dev) 7154610ac93SAndrew Boyer { 716a677112dSAndrew Boyer int err; 717a677112dSAndrew Boyer 718*aacc5f13SAndrew Boyer memset(&dev->stats_base, 0, sizeof(dev->stats_base)); 719*aacc5f13SAndrew Boyer 720a677112dSAndrew Boyer /* Uses dev_cmds */ 721a677112dSAndrew Boyer err = iocpt_dev_init(dev, dev->info_pa); 722a677112dSAndrew Boyer if (err != 0) 723a677112dSAndrew Boyer return err; 724a677112dSAndrew Boyer 7252c1662bbSAndrew Boyer err = iocpt_adminq_init(dev); 7262c1662bbSAndrew Boyer if (err != 0) 7272c1662bbSAndrew Boyer return err; 7282c1662bbSAndrew Boyer 72954d56abaSAndrew Boyer /* Write the queue watchdog key */ 73054d56abaSAndrew Boyer err = iocpt_session_wdog(dev); 73154d56abaSAndrew Boyer if (err != 0) { 73254d56abaSAndrew Boyer IOCPT_PRINT(ERR, "Cannot setup watchdog session"); 73354d56abaSAndrew Boyer goto err_out_adminq_deinit; 73454d56abaSAndrew Boyer } 73554d56abaSAndrew Boyer 7364610ac93SAndrew Boyer dev->state |= IOCPT_DEV_F_INITED; 7374610ac93SAndrew Boyer 7384610ac93SAndrew Boyer return 0; 73954d56abaSAndrew Boyer 74054d56abaSAndrew Boyer err_out_adminq_deinit: 74154d56abaSAndrew Boyer iocpt_adminq_deinit(dev); 74254d56abaSAndrew Boyer 74354d56abaSAndrew Boyer return err; 7444610ac93SAndrew Boyer } 7454610ac93SAndrew Boyer 7464610ac93SAndrew Boyer void 7474610ac93SAndrew Boyer iocpt_configure(struct iocpt_dev *dev) 7484610ac93SAndrew Boyer { 7494610ac93SAndrew Boyer RTE_SET_USED(dev); 7504610ac93SAndrew Boyer } 7514610ac93SAndrew Boyer 75280518852SAndrew Boyer int 75380518852SAndrew Boyer iocpt_start(struct iocpt_dev *dev) 75480518852SAndrew Boyer { 75580518852SAndrew Boyer uint32_t i; 75680518852SAndrew Boyer int err; 75780518852SAndrew Boyer 75880518852SAndrew Boyer IOCPT_PRINT(DEBUG, "Starting %u queues", 75980518852SAndrew Boyer dev->crypto_dev->data->nb_queue_pairs); 76080518852SAndrew Boyer 76180518852SAndrew Boyer for (i = 0; i < dev->crypto_dev->data->nb_queue_pairs; i++) { 76280518852SAndrew Boyer err = iocpt_cryptoq_init(dev->cryptoqs[i]); 76380518852SAndrew Boyer if (err != 0) 76480518852SAndrew Boyer return err; 76580518852SAndrew Boyer } 76680518852SAndrew Boyer 76780518852SAndrew Boyer dev->state |= IOCPT_DEV_F_UP; 76880518852SAndrew Boyer 76980518852SAndrew Boyer return 0; 77080518852SAndrew Boyer } 77180518852SAndrew Boyer 77280518852SAndrew Boyer void 77380518852SAndrew Boyer iocpt_stop(struct iocpt_dev *dev) 77480518852SAndrew Boyer { 77580518852SAndrew Boyer uint32_t i; 77680518852SAndrew Boyer 77780518852SAndrew Boyer IOCPT_PRINT_CALL(); 77880518852SAndrew Boyer 77980518852SAndrew Boyer dev->state &= ~IOCPT_DEV_F_UP; 78080518852SAndrew Boyer 78180518852SAndrew Boyer for (i = 0; i < dev->crypto_dev->data->nb_queue_pairs; i++) { 78280518852SAndrew Boyer struct iocpt_crypto_q *cptq = dev->cryptoqs[i]; 78380518852SAndrew Boyer 78480518852SAndrew Boyer if (cptq->flags & IOCPT_Q_F_INITED) 78580518852SAndrew Boyer (void)iocpt_cryptoq_deinit(cptq); 78680518852SAndrew Boyer } 78780518852SAndrew Boyer } 78880518852SAndrew Boyer 7894610ac93SAndrew Boyer void 7904610ac93SAndrew Boyer iocpt_deinit(struct iocpt_dev *dev) 7914610ac93SAndrew Boyer { 7924610ac93SAndrew Boyer IOCPT_PRINT_CALL(); 7934610ac93SAndrew Boyer 7944610ac93SAndrew Boyer if (!(dev->state & IOCPT_DEV_F_INITED)) 7954610ac93SAndrew Boyer return; 7964610ac93SAndrew Boyer 7972c1662bbSAndrew Boyer iocpt_adminq_deinit(dev); 7982c1662bbSAndrew Boyer 7994610ac93SAndrew Boyer dev->state &= ~IOCPT_DEV_F_INITED; 8004610ac93SAndrew Boyer } 8014610ac93SAndrew Boyer 802a677112dSAndrew Boyer static void 803a677112dSAndrew Boyer iocpt_free_objs(struct iocpt_dev *dev) 804a677112dSAndrew Boyer { 80580518852SAndrew Boyer void **queue_pairs = dev->crypto_dev->data->queue_pairs; 80680518852SAndrew Boyer uint32_t i; 80780518852SAndrew Boyer 808a677112dSAndrew Boyer IOCPT_PRINT_CALL(); 809a677112dSAndrew Boyer 81080518852SAndrew Boyer for (i = 0; i < dev->crypto_dev->data->nb_queue_pairs; i++) { 81180518852SAndrew Boyer iocpt_cryptoq_free(queue_pairs[i]); 81280518852SAndrew Boyer queue_pairs[i] = NULL; 81380518852SAndrew Boyer } 81480518852SAndrew Boyer 8156bc7f2cfSAndrew Boyer if (dev->sess_bm != NULL) { 8166bc7f2cfSAndrew Boyer rte_bitmap_free(dev->sess_bm); 8176bc7f2cfSAndrew Boyer rte_free(dev->sess_bm); 8186bc7f2cfSAndrew Boyer dev->sess_bm = NULL; 8196bc7f2cfSAndrew Boyer } 8206bc7f2cfSAndrew Boyer 8212c1662bbSAndrew Boyer if (dev->adminq != NULL) { 8222c1662bbSAndrew Boyer iocpt_adminq_free(dev->adminq); 8232c1662bbSAndrew Boyer dev->adminq = NULL; 8242c1662bbSAndrew Boyer } 8252c1662bbSAndrew Boyer 82680518852SAndrew Boyer if (dev->cryptoqs != NULL) { 82780518852SAndrew Boyer rte_free(dev->cryptoqs); 82880518852SAndrew Boyer dev->cryptoqs = NULL; 82980518852SAndrew Boyer } 83080518852SAndrew Boyer 831a677112dSAndrew Boyer if (dev->info != NULL) { 832a677112dSAndrew Boyer rte_memzone_free(dev->info_z); 833a677112dSAndrew Boyer dev->info_z = NULL; 834a677112dSAndrew Boyer dev->info = NULL; 835a677112dSAndrew Boyer dev->info_pa = 0; 836a677112dSAndrew Boyer } 837a677112dSAndrew Boyer } 838a677112dSAndrew Boyer 8394610ac93SAndrew Boyer static int 8404610ac93SAndrew Boyer iocpt_devargs(struct rte_devargs *devargs, struct iocpt_dev *dev) 8414610ac93SAndrew Boyer { 8424610ac93SAndrew Boyer RTE_SET_USED(devargs); 8434610ac93SAndrew Boyer RTE_SET_USED(dev); 8444610ac93SAndrew Boyer 8454610ac93SAndrew Boyer return 0; 8464610ac93SAndrew Boyer } 8474610ac93SAndrew Boyer 8484610ac93SAndrew Boyer int 8494610ac93SAndrew Boyer iocpt_probe(void *bus_dev, struct rte_device *rte_dev, 8504610ac93SAndrew Boyer struct iocpt_dev_bars *bars, const struct iocpt_dev_intf *intf, 8514610ac93SAndrew Boyer uint8_t driver_id, uint8_t socket_id) 8524610ac93SAndrew Boyer { 8534610ac93SAndrew Boyer struct rte_cryptodev_pmd_init_params init_params = { 8544610ac93SAndrew Boyer "iocpt", 8554610ac93SAndrew Boyer sizeof(struct iocpt_dev), 8564610ac93SAndrew Boyer socket_id, 8574610ac93SAndrew Boyer RTE_CRYPTODEV_PMD_DEFAULT_MAX_NB_QUEUE_PAIRS 8584610ac93SAndrew Boyer }; 8594610ac93SAndrew Boyer struct rte_cryptodev *cdev; 8604610ac93SAndrew Boyer struct iocpt_dev *dev; 86125c896eaSAndrew Boyer uint32_t i, sig; 8624610ac93SAndrew Boyer int err; 8634610ac93SAndrew Boyer 86425c896eaSAndrew Boyer /* Check structs (trigger error at compilation time) */ 86525c896eaSAndrew Boyer iocpt_struct_size_checks(); 86625c896eaSAndrew Boyer 8674610ac93SAndrew Boyer if (rte_eal_process_type() != RTE_PROC_PRIMARY) { 8684610ac93SAndrew Boyer IOCPT_PRINT(ERR, "Multi-process not supported"); 8694610ac93SAndrew Boyer err = -EPERM; 8704610ac93SAndrew Boyer goto err; 8714610ac93SAndrew Boyer } 8724610ac93SAndrew Boyer 8734610ac93SAndrew Boyer cdev = rte_cryptodev_pmd_create(rte_dev->name, rte_dev, &init_params); 8744610ac93SAndrew Boyer if (cdev == NULL) { 8754610ac93SAndrew Boyer IOCPT_PRINT(ERR, "Out of memory"); 8764610ac93SAndrew Boyer err = -ENOMEM; 8774610ac93SAndrew Boyer goto err; 8784610ac93SAndrew Boyer } 8794610ac93SAndrew Boyer 8804610ac93SAndrew Boyer dev = cdev->data->dev_private; 8814610ac93SAndrew Boyer dev->crypto_dev = cdev; 8824610ac93SAndrew Boyer dev->bus_dev = bus_dev; 8834610ac93SAndrew Boyer dev->intf = intf; 8844610ac93SAndrew Boyer dev->driver_id = driver_id; 8854610ac93SAndrew Boyer dev->socket_id = socket_id; 8864610ac93SAndrew Boyer 8874610ac93SAndrew Boyer for (i = 0; i < bars->num_bars; i++) { 8884610ac93SAndrew Boyer struct ionic_dev_bar *bar = &bars->bar[i]; 8894610ac93SAndrew Boyer 8904610ac93SAndrew Boyer IOCPT_PRINT(DEBUG, 8914610ac93SAndrew Boyer "bar[%u] = { .va = %p, .pa = %#jx, .len = %lu }", 8924610ac93SAndrew Boyer i, bar->vaddr, bar->bus_addr, bar->len); 8934610ac93SAndrew Boyer if (bar->vaddr == NULL) { 8944610ac93SAndrew Boyer IOCPT_PRINT(ERR, "Null bar found, aborting"); 8954610ac93SAndrew Boyer err = -EFAULT; 8964610ac93SAndrew Boyer goto err_destroy_crypto_dev; 8974610ac93SAndrew Boyer } 8984610ac93SAndrew Boyer 8994610ac93SAndrew Boyer dev->bars.bar[i].vaddr = bar->vaddr; 9004610ac93SAndrew Boyer dev->bars.bar[i].bus_addr = bar->bus_addr; 9014610ac93SAndrew Boyer dev->bars.bar[i].len = bar->len; 9024610ac93SAndrew Boyer } 9034610ac93SAndrew Boyer dev->bars.num_bars = bars->num_bars; 9044610ac93SAndrew Boyer 9054610ac93SAndrew Boyer err = iocpt_devargs(rte_dev->devargs, dev); 9064610ac93SAndrew Boyer if (err != 0) { 9074610ac93SAndrew Boyer IOCPT_PRINT(ERR, "Cannot parse device arguments"); 9084610ac93SAndrew Boyer goto err_destroy_crypto_dev; 9094610ac93SAndrew Boyer } 9104610ac93SAndrew Boyer 9114610ac93SAndrew Boyer err = iocpt_setup_bars(dev); 9124610ac93SAndrew Boyer if (err != 0) { 9134610ac93SAndrew Boyer IOCPT_PRINT(ERR, "Cannot setup BARs: %d, aborting", err); 9144610ac93SAndrew Boyer goto err_destroy_crypto_dev; 9154610ac93SAndrew Boyer } 9164610ac93SAndrew Boyer 91725c896eaSAndrew Boyer sig = ioread32(&dev->dev_info->signature); 91825c896eaSAndrew Boyer if (sig != IOCPT_DEV_INFO_SIGNATURE) { 91925c896eaSAndrew Boyer IOCPT_PRINT(ERR, "Incompatible firmware signature %#x", sig); 92025c896eaSAndrew Boyer err = -EFAULT; 92125c896eaSAndrew Boyer goto err_destroy_crypto_dev; 92225c896eaSAndrew Boyer } 92325c896eaSAndrew Boyer 92425c896eaSAndrew Boyer for (i = 0; i < IOCPT_FWVERS_BUFLEN; i++) 92525c896eaSAndrew Boyer dev->fw_version[i] = ioread8(&dev->dev_info->fw_version[i]); 92625c896eaSAndrew Boyer dev->fw_version[IOCPT_FWVERS_BUFLEN - 1] = '\0'; 92725c896eaSAndrew Boyer IOCPT_PRINT(DEBUG, "%s firmware: %s", dev->name, dev->fw_version); 92825c896eaSAndrew Boyer 929a677112dSAndrew Boyer err = iocpt_dev_identify(dev); 930a677112dSAndrew Boyer if (err != 0) { 931a677112dSAndrew Boyer IOCPT_PRINT(ERR, "Cannot identify device: %d, aborting", 932a677112dSAndrew Boyer err); 933a677112dSAndrew Boyer goto err_destroy_crypto_dev; 934a677112dSAndrew Boyer } 935a677112dSAndrew Boyer 936a677112dSAndrew Boyer err = iocpt_alloc_objs(dev); 937a677112dSAndrew Boyer if (err != 0) { 938a677112dSAndrew Boyer IOCPT_PRINT(ERR, "Cannot alloc device objects: %d", err); 939a677112dSAndrew Boyer goto err_destroy_crypto_dev; 940a677112dSAndrew Boyer } 941a677112dSAndrew Boyer 9424610ac93SAndrew Boyer err = iocpt_init(dev); 9434610ac93SAndrew Boyer if (err != 0) { 9444610ac93SAndrew Boyer IOCPT_PRINT(ERR, "Cannot init device: %d, aborting", err); 945a677112dSAndrew Boyer goto err_free_objs; 9464610ac93SAndrew Boyer } 9474610ac93SAndrew Boyer 948dddfb0d9SAndrew Boyer err = iocpt_assign_ops(cdev); 949dddfb0d9SAndrew Boyer if (err != 0) { 950dddfb0d9SAndrew Boyer IOCPT_PRINT(ERR, "Failed to configure opts"); 951dddfb0d9SAndrew Boyer goto err_deinit_dev; 952dddfb0d9SAndrew Boyer } 953dddfb0d9SAndrew Boyer 9544610ac93SAndrew Boyer return 0; 9554610ac93SAndrew Boyer 956dddfb0d9SAndrew Boyer err_deinit_dev: 957dddfb0d9SAndrew Boyer iocpt_deinit(dev); 958a677112dSAndrew Boyer err_free_objs: 959a677112dSAndrew Boyer iocpt_free_objs(dev); 9604610ac93SAndrew Boyer err_destroy_crypto_dev: 9614610ac93SAndrew Boyer rte_cryptodev_pmd_destroy(cdev); 9624610ac93SAndrew Boyer err: 9634610ac93SAndrew Boyer return err; 9644610ac93SAndrew Boyer } 9654610ac93SAndrew Boyer 9664610ac93SAndrew Boyer int 9674610ac93SAndrew Boyer iocpt_remove(struct rte_device *rte_dev) 9684610ac93SAndrew Boyer { 9694610ac93SAndrew Boyer struct rte_cryptodev *cdev; 9704610ac93SAndrew Boyer struct iocpt_dev *dev; 9714610ac93SAndrew Boyer 9724610ac93SAndrew Boyer cdev = rte_cryptodev_pmd_get_named_dev(rte_dev->name); 9734610ac93SAndrew Boyer if (cdev == NULL) { 9744610ac93SAndrew Boyer IOCPT_PRINT(DEBUG, "Cannot find device %s", rte_dev->name); 9754610ac93SAndrew Boyer return -ENODEV; 9764610ac93SAndrew Boyer } 9774610ac93SAndrew Boyer 9784610ac93SAndrew Boyer dev = cdev->data->dev_private; 9794610ac93SAndrew Boyer 9804610ac93SAndrew Boyer iocpt_deinit(dev); 9814610ac93SAndrew Boyer 982a677112dSAndrew Boyer iocpt_dev_reset(dev); 983a677112dSAndrew Boyer 984a677112dSAndrew Boyer iocpt_free_objs(dev); 985a677112dSAndrew Boyer 9864610ac93SAndrew Boyer rte_cryptodev_pmd_destroy(cdev); 9874610ac93SAndrew Boyer 9884610ac93SAndrew Boyer return 0; 9894610ac93SAndrew Boyer } 9904610ac93SAndrew Boyer 9914610ac93SAndrew Boyer RTE_LOG_REGISTER_DEFAULT(iocpt_logtype, NOTICE); 992