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 33*80518852SAndrew Boyer iocpt_cq_reset(struct iocpt_cq *cq) 34*80518852SAndrew Boyer { 35*80518852SAndrew Boyer cq->tail_idx = 0; 36*80518852SAndrew Boyer cq->done_color = 1; 37*80518852SAndrew Boyer 38*80518852SAndrew Boyer memset(cq->base, 0, sizeof(struct iocpt_nop_comp) * cq->num_descs); 39*80518852SAndrew Boyer } 40*80518852SAndrew Boyer 41*80518852SAndrew 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 102*80518852SAndrew Boyer iocpt_q_reset(struct iocpt_queue *q) 103*80518852SAndrew Boyer { 104*80518852SAndrew Boyer q->head_idx = 0; 105*80518852SAndrew Boyer q->tail_idx = 0; 106*80518852SAndrew Boyer } 107*80518852SAndrew Boyer 108*80518852SAndrew 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 1316bc7f2cfSAndrew Boyer static int 1326bc7f2cfSAndrew Boyer iocpt_session_write(struct iocpt_session_priv *priv, 1336bc7f2cfSAndrew Boyer enum iocpt_sess_control_oper oper) 1346bc7f2cfSAndrew Boyer { 1356bc7f2cfSAndrew Boyer struct iocpt_dev *dev = priv->dev; 1366bc7f2cfSAndrew Boyer struct iocpt_admin_ctx ctx = { 1376bc7f2cfSAndrew Boyer .pending_work = true, 1386bc7f2cfSAndrew Boyer .cmd.sess_control = { 1396bc7f2cfSAndrew Boyer .opcode = IOCPT_CMD_SESS_CONTROL, 1406bc7f2cfSAndrew Boyer .type = priv->type, 1416bc7f2cfSAndrew Boyer .oper = oper, 1426bc7f2cfSAndrew Boyer .index = rte_cpu_to_le_32(priv->index), 1436bc7f2cfSAndrew Boyer .key_len = rte_cpu_to_le_16(priv->key_len), 1446bc7f2cfSAndrew Boyer .key_seg_len = (uint8_t)RTE_MIN(priv->key_len, 1456bc7f2cfSAndrew Boyer IOCPT_SESS_KEY_SEG_LEN), 1466bc7f2cfSAndrew Boyer }, 1476bc7f2cfSAndrew Boyer }; 1486bc7f2cfSAndrew Boyer struct iocpt_sess_control_cmd *cmd = &ctx.cmd.sess_control; 1496bc7f2cfSAndrew Boyer uint16_t key_offset; 1506bc7f2cfSAndrew Boyer uint8_t key_segs, seg; 1516bc7f2cfSAndrew Boyer int err; 1526bc7f2cfSAndrew Boyer 1536bc7f2cfSAndrew Boyer key_segs = ((priv->key_len - 1) >> IOCPT_SESS_KEY_SEG_SHFT) + 1; 1546bc7f2cfSAndrew Boyer 1556bc7f2cfSAndrew Boyer for (seg = 0; seg < key_segs; seg++) { 1566bc7f2cfSAndrew Boyer ctx.pending_work = true; 1576bc7f2cfSAndrew Boyer 1586bc7f2cfSAndrew Boyer key_offset = seg * cmd->key_seg_len; 1596bc7f2cfSAndrew Boyer memcpy(cmd->key, &priv->key[key_offset], 1606bc7f2cfSAndrew Boyer IOCPT_SESS_KEY_SEG_LEN); 1616bc7f2cfSAndrew Boyer cmd->key_seg_idx = seg; 1626bc7f2cfSAndrew Boyer 1636bc7f2cfSAndrew Boyer /* Mark final segment */ 1646bc7f2cfSAndrew Boyer if (seg + 1 == key_segs) 1656bc7f2cfSAndrew Boyer cmd->flags |= rte_cpu_to_le_16(IOCPT_SCTL_F_END); 1666bc7f2cfSAndrew Boyer 1676bc7f2cfSAndrew Boyer err = iocpt_adminq_post_wait(dev, &ctx); 1686bc7f2cfSAndrew Boyer if (err != 0) 1696bc7f2cfSAndrew Boyer return err; 1706bc7f2cfSAndrew Boyer } 1716bc7f2cfSAndrew Boyer 1726bc7f2cfSAndrew Boyer return 0; 1736bc7f2cfSAndrew Boyer } 1746bc7f2cfSAndrew Boyer 1756bc7f2cfSAndrew Boyer int 1766bc7f2cfSAndrew Boyer iocpt_session_init(struct iocpt_session_priv *priv) 1776bc7f2cfSAndrew Boyer { 1786bc7f2cfSAndrew Boyer struct iocpt_dev *dev = priv->dev; 1796bc7f2cfSAndrew Boyer uint64_t bm_slab = 0; 1806bc7f2cfSAndrew Boyer uint32_t bm_pos = 0; 1816bc7f2cfSAndrew Boyer int err = 0; 1826bc7f2cfSAndrew Boyer 1836bc7f2cfSAndrew Boyer rte_spinlock_lock(&dev->adminq_lock); 1846bc7f2cfSAndrew Boyer 1856bc7f2cfSAndrew Boyer if (rte_bitmap_scan(dev->sess_bm, &bm_pos, &bm_slab) > 0) { 1866bc7f2cfSAndrew Boyer priv->index = bm_pos + rte_ctz64(bm_slab); 1876bc7f2cfSAndrew Boyer rte_bitmap_clear(dev->sess_bm, priv->index); 1886bc7f2cfSAndrew Boyer } else 1896bc7f2cfSAndrew Boyer err = -ENOSPC; 1906bc7f2cfSAndrew Boyer 1916bc7f2cfSAndrew Boyer rte_spinlock_unlock(&dev->adminq_lock); 1926bc7f2cfSAndrew Boyer 1936bc7f2cfSAndrew Boyer if (err != 0) { 1946bc7f2cfSAndrew Boyer IOCPT_PRINT(ERR, "session index space exhausted"); 1956bc7f2cfSAndrew Boyer return err; 1966bc7f2cfSAndrew Boyer } 1976bc7f2cfSAndrew Boyer 1986bc7f2cfSAndrew Boyer err = iocpt_session_write(priv, IOCPT_SESS_INIT); 1996bc7f2cfSAndrew Boyer if (err != 0) { 2006bc7f2cfSAndrew Boyer rte_spinlock_lock(&dev->adminq_lock); 2016bc7f2cfSAndrew Boyer rte_bitmap_set(dev->sess_bm, priv->index); 2026bc7f2cfSAndrew Boyer rte_spinlock_unlock(&dev->adminq_lock); 2036bc7f2cfSAndrew Boyer return err; 2046bc7f2cfSAndrew Boyer } 2056bc7f2cfSAndrew Boyer 2066bc7f2cfSAndrew Boyer priv->flags |= IOCPT_S_F_INITED; 2076bc7f2cfSAndrew Boyer 2086bc7f2cfSAndrew Boyer return 0; 2096bc7f2cfSAndrew Boyer } 2106bc7f2cfSAndrew Boyer 2116bc7f2cfSAndrew Boyer int 2126bc7f2cfSAndrew Boyer iocpt_session_update(struct iocpt_session_priv *priv) 2136bc7f2cfSAndrew Boyer { 2146bc7f2cfSAndrew Boyer return iocpt_session_write(priv, IOCPT_SESS_UPDATE_KEY); 2156bc7f2cfSAndrew Boyer } 2166bc7f2cfSAndrew Boyer 2176bc7f2cfSAndrew Boyer void 2186bc7f2cfSAndrew Boyer iocpt_session_deinit(struct iocpt_session_priv *priv) 2196bc7f2cfSAndrew Boyer { 2206bc7f2cfSAndrew Boyer struct iocpt_dev *dev = priv->dev; 2216bc7f2cfSAndrew Boyer struct iocpt_admin_ctx ctx = { 2226bc7f2cfSAndrew Boyer .pending_work = true, 2236bc7f2cfSAndrew Boyer .cmd.sess_control = { 2246bc7f2cfSAndrew Boyer .opcode = IOCPT_CMD_SESS_CONTROL, 2256bc7f2cfSAndrew Boyer .type = priv->type, 2266bc7f2cfSAndrew Boyer .oper = IOCPT_SESS_DISABLE, 2276bc7f2cfSAndrew Boyer .index = rte_cpu_to_le_32(priv->index), 2286bc7f2cfSAndrew Boyer .key_len = rte_cpu_to_le_16(priv->key_len), 2296bc7f2cfSAndrew Boyer }, 2306bc7f2cfSAndrew Boyer }; 2316bc7f2cfSAndrew Boyer 2326bc7f2cfSAndrew Boyer (void)iocpt_adminq_post_wait(dev, &ctx); 2336bc7f2cfSAndrew Boyer 2346bc7f2cfSAndrew Boyer rte_spinlock_lock(&dev->adminq_lock); 2356bc7f2cfSAndrew Boyer rte_bitmap_set(dev->sess_bm, priv->index); 2366bc7f2cfSAndrew Boyer rte_spinlock_unlock(&dev->adminq_lock); 2376bc7f2cfSAndrew Boyer 2386bc7f2cfSAndrew Boyer priv->flags &= ~IOCPT_S_F_INITED; 2396bc7f2cfSAndrew Boyer } 2406bc7f2cfSAndrew Boyer 241a677112dSAndrew Boyer static const struct rte_memzone * 242a677112dSAndrew Boyer iocpt_dma_zone_reserve(const char *type_name, uint16_t qid, size_t size, 243a677112dSAndrew Boyer unsigned int align, int socket_id) 244a677112dSAndrew Boyer { 245a677112dSAndrew Boyer char zone_name[RTE_MEMZONE_NAMESIZE]; 246a677112dSAndrew Boyer const struct rte_memzone *mz; 247a677112dSAndrew Boyer int err; 248a677112dSAndrew Boyer 249a677112dSAndrew Boyer err = snprintf(zone_name, sizeof(zone_name), 250a677112dSAndrew Boyer "iocpt_%s_%u", type_name, qid); 251a677112dSAndrew Boyer if (err >= RTE_MEMZONE_NAMESIZE) { 252a677112dSAndrew Boyer IOCPT_PRINT(ERR, "Name %s too long", type_name); 253a677112dSAndrew Boyer return NULL; 254a677112dSAndrew Boyer } 255a677112dSAndrew Boyer 256a677112dSAndrew Boyer mz = rte_memzone_lookup(zone_name); 257a677112dSAndrew Boyer if (mz != NULL) 258a677112dSAndrew Boyer return mz; 259a677112dSAndrew Boyer 260a677112dSAndrew Boyer return rte_memzone_reserve_aligned(zone_name, size, socket_id, 261a677112dSAndrew Boyer RTE_MEMZONE_IOVA_CONTIG, align); 262a677112dSAndrew Boyer } 263a677112dSAndrew Boyer 264a677112dSAndrew Boyer static int 2652c1662bbSAndrew Boyer iocpt_commonq_alloc(struct iocpt_dev *dev, 2662c1662bbSAndrew Boyer uint8_t type, 2672c1662bbSAndrew Boyer size_t struct_size, 2682c1662bbSAndrew Boyer uint32_t socket_id, 2692c1662bbSAndrew Boyer uint32_t index, 2702c1662bbSAndrew Boyer const char *type_name, 2712c1662bbSAndrew Boyer uint16_t flags, 2722c1662bbSAndrew Boyer uint16_t num_descs, 2732c1662bbSAndrew Boyer uint16_t num_segs, 2742c1662bbSAndrew Boyer uint16_t desc_size, 2752c1662bbSAndrew Boyer uint16_t cq_desc_size, 2762c1662bbSAndrew Boyer uint16_t sg_desc_size, 2772c1662bbSAndrew Boyer struct iocpt_common_q **comq) 2782c1662bbSAndrew Boyer { 2792c1662bbSAndrew Boyer struct iocpt_common_q *new; 2802c1662bbSAndrew Boyer uint32_t q_size, cq_size, sg_size, total_size; 2812c1662bbSAndrew Boyer void *q_base, *cq_base, *sg_base; 2822c1662bbSAndrew Boyer rte_iova_t q_base_pa = 0; 2832c1662bbSAndrew Boyer rte_iova_t cq_base_pa = 0; 2842c1662bbSAndrew Boyer rte_iova_t sg_base_pa = 0; 2852c1662bbSAndrew Boyer size_t page_size = rte_mem_page_size(); 2862c1662bbSAndrew Boyer int err; 2872c1662bbSAndrew Boyer 2882c1662bbSAndrew Boyer *comq = NULL; 2892c1662bbSAndrew Boyer 2902c1662bbSAndrew Boyer q_size = num_descs * desc_size; 2912c1662bbSAndrew Boyer cq_size = num_descs * cq_desc_size; 2922c1662bbSAndrew Boyer sg_size = num_descs * sg_desc_size; 2932c1662bbSAndrew Boyer 2942c1662bbSAndrew Boyer /* 2952c1662bbSAndrew Boyer * Note: aligning q_size/cq_size is not enough due to cq_base address 2962c1662bbSAndrew Boyer * aligning as q_base could be not aligned to the page. 2972c1662bbSAndrew Boyer * Adding page_size. 2982c1662bbSAndrew Boyer */ 2992c1662bbSAndrew Boyer total_size = RTE_ALIGN(q_size, page_size) + 3002c1662bbSAndrew Boyer RTE_ALIGN(cq_size, page_size) + page_size; 3012c1662bbSAndrew Boyer if (flags & IOCPT_Q_F_SG) 3022c1662bbSAndrew Boyer total_size += RTE_ALIGN(sg_size, page_size) + page_size; 3032c1662bbSAndrew Boyer 3042c1662bbSAndrew Boyer new = rte_zmalloc_socket("iocpt", struct_size, 3052c1662bbSAndrew Boyer RTE_CACHE_LINE_SIZE, socket_id); 3062c1662bbSAndrew Boyer if (new == NULL) { 3072c1662bbSAndrew Boyer IOCPT_PRINT(ERR, "Cannot allocate queue structure"); 3082c1662bbSAndrew Boyer return -ENOMEM; 3092c1662bbSAndrew Boyer } 3102c1662bbSAndrew Boyer 3112c1662bbSAndrew Boyer new->dev = dev; 3122c1662bbSAndrew Boyer 3132c1662bbSAndrew Boyer err = iocpt_q_init(&new->q, type, index, num_descs, num_segs, 3142c1662bbSAndrew Boyer socket_id); 3152c1662bbSAndrew Boyer if (err != 0) { 3162c1662bbSAndrew Boyer IOCPT_PRINT(ERR, "Queue initialization failed"); 3172c1662bbSAndrew Boyer goto err_free_q; 3182c1662bbSAndrew Boyer } 3192c1662bbSAndrew Boyer 3202c1662bbSAndrew Boyer err = iocpt_cq_init(&new->cq, num_descs); 3212c1662bbSAndrew Boyer if (err != 0) { 3222c1662bbSAndrew Boyer IOCPT_PRINT(ERR, "Completion queue initialization failed"); 3232c1662bbSAndrew Boyer goto err_deinit_q; 3242c1662bbSAndrew Boyer } 3252c1662bbSAndrew Boyer 3262c1662bbSAndrew Boyer new->base_z = iocpt_dma_zone_reserve(type_name, index, total_size, 3272c1662bbSAndrew Boyer IONIC_ALIGN, socket_id); 3282c1662bbSAndrew Boyer if (new->base_z == NULL) { 3292c1662bbSAndrew Boyer IOCPT_PRINT(ERR, "Cannot reserve queue DMA memory"); 3302c1662bbSAndrew Boyer err = -ENOMEM; 3312c1662bbSAndrew Boyer goto err_deinit_cq; 3322c1662bbSAndrew Boyer } 3332c1662bbSAndrew Boyer 3342c1662bbSAndrew Boyer new->base = new->base_z->addr; 3352c1662bbSAndrew Boyer new->base_pa = new->base_z->iova; 3362c1662bbSAndrew Boyer 3372c1662bbSAndrew Boyer q_base = new->base; 3382c1662bbSAndrew Boyer q_base_pa = new->base_pa; 3392c1662bbSAndrew Boyer iocpt_q_map(&new->q, q_base, q_base_pa); 3402c1662bbSAndrew Boyer 3412c1662bbSAndrew Boyer cq_base = (void *)RTE_ALIGN((uintptr_t)q_base + q_size, page_size); 3422c1662bbSAndrew Boyer cq_base_pa = RTE_ALIGN(q_base_pa + q_size, page_size); 3432c1662bbSAndrew Boyer iocpt_cq_map(&new->cq, cq_base, cq_base_pa); 3442c1662bbSAndrew Boyer 3452c1662bbSAndrew Boyer if (flags & IOCPT_Q_F_SG) { 3462c1662bbSAndrew Boyer sg_base = (void *)RTE_ALIGN((uintptr_t)cq_base + cq_size, 3472c1662bbSAndrew Boyer page_size); 3482c1662bbSAndrew Boyer sg_base_pa = RTE_ALIGN(cq_base_pa + cq_size, page_size); 3492c1662bbSAndrew Boyer iocpt_q_sg_map(&new->q, sg_base, sg_base_pa); 3502c1662bbSAndrew Boyer } 3512c1662bbSAndrew Boyer 3522c1662bbSAndrew Boyer IOCPT_PRINT(DEBUG, "q_base_pa %#jx cq_base_pa %#jx sg_base_pa %#jx", 3532c1662bbSAndrew Boyer q_base_pa, cq_base_pa, sg_base_pa); 3542c1662bbSAndrew Boyer 3552c1662bbSAndrew Boyer *comq = new; 3562c1662bbSAndrew Boyer 3572c1662bbSAndrew Boyer return 0; 3582c1662bbSAndrew Boyer 3592c1662bbSAndrew Boyer err_deinit_cq: 3602c1662bbSAndrew Boyer err_deinit_q: 3612c1662bbSAndrew Boyer iocpt_q_free(&new->q); 3622c1662bbSAndrew Boyer err_free_q: 3632c1662bbSAndrew Boyer rte_free(new); 3642c1662bbSAndrew Boyer return err; 3652c1662bbSAndrew Boyer } 3662c1662bbSAndrew Boyer 367*80518852SAndrew Boyer int 368*80518852SAndrew Boyer iocpt_cryptoq_alloc(struct iocpt_dev *dev, uint32_t socket_id, uint32_t index, 369*80518852SAndrew Boyer uint16_t num_descs) 370*80518852SAndrew Boyer { 371*80518852SAndrew Boyer struct iocpt_crypto_q *cptq; 372*80518852SAndrew Boyer uint16_t flags = 0; 373*80518852SAndrew Boyer int err; 374*80518852SAndrew Boyer 375*80518852SAndrew Boyer /* CryptoQ always supports scatter-gather */ 376*80518852SAndrew Boyer flags |= IOCPT_Q_F_SG; 377*80518852SAndrew Boyer 378*80518852SAndrew Boyer IOCPT_PRINT(DEBUG, "cptq %u num_descs %u num_segs %u", 379*80518852SAndrew Boyer index, num_descs, 1); 380*80518852SAndrew Boyer 381*80518852SAndrew Boyer err = iocpt_commonq_alloc(dev, 382*80518852SAndrew Boyer IOCPT_QTYPE_CRYPTOQ, 383*80518852SAndrew Boyer sizeof(struct iocpt_crypto_q), 384*80518852SAndrew Boyer socket_id, 385*80518852SAndrew Boyer index, 386*80518852SAndrew Boyer "crypto", 387*80518852SAndrew Boyer flags, 388*80518852SAndrew Boyer num_descs, 389*80518852SAndrew Boyer 1, 390*80518852SAndrew Boyer sizeof(struct iocpt_crypto_desc), 391*80518852SAndrew Boyer sizeof(struct iocpt_crypto_comp), 392*80518852SAndrew Boyer sizeof(struct iocpt_crypto_sg_desc), 393*80518852SAndrew Boyer (struct iocpt_common_q **)&cptq); 394*80518852SAndrew Boyer if (err != 0) 395*80518852SAndrew Boyer return err; 396*80518852SAndrew Boyer 397*80518852SAndrew Boyer cptq->flags = flags; 398*80518852SAndrew Boyer 399*80518852SAndrew Boyer dev->cryptoqs[index] = cptq; 400*80518852SAndrew Boyer 401*80518852SAndrew Boyer return 0; 402*80518852SAndrew Boyer } 403*80518852SAndrew Boyer 4042c1662bbSAndrew Boyer struct ionic_doorbell * 4052c1662bbSAndrew Boyer iocpt_db_map(struct iocpt_dev *dev, struct iocpt_queue *q) 4062c1662bbSAndrew Boyer { 4072c1662bbSAndrew Boyer return dev->db_pages + q->hw_type; 4082c1662bbSAndrew Boyer } 4092c1662bbSAndrew Boyer 4102c1662bbSAndrew Boyer static int 411*80518852SAndrew Boyer iocpt_cryptoq_init(struct iocpt_crypto_q *cptq) 412*80518852SAndrew Boyer { 413*80518852SAndrew Boyer struct iocpt_queue *q = &cptq->q; 414*80518852SAndrew Boyer struct iocpt_dev *dev = cptq->dev; 415*80518852SAndrew Boyer struct iocpt_cq *cq = &cptq->cq; 416*80518852SAndrew Boyer struct iocpt_admin_ctx ctx = { 417*80518852SAndrew Boyer .pending_work = true, 418*80518852SAndrew Boyer .cmd.q_init = { 419*80518852SAndrew Boyer .opcode = IOCPT_CMD_Q_INIT, 420*80518852SAndrew Boyer .type = IOCPT_QTYPE_CRYPTOQ, 421*80518852SAndrew Boyer .ver = dev->qtype_info[IOCPT_QTYPE_CRYPTOQ].version, 422*80518852SAndrew Boyer .index = rte_cpu_to_le_32(q->index), 423*80518852SAndrew Boyer .flags = rte_cpu_to_le_16(IOCPT_QINIT_F_ENA | 424*80518852SAndrew Boyer IOCPT_QINIT_F_SG), 425*80518852SAndrew Boyer .intr_index = rte_cpu_to_le_16(IONIC_INTR_NONE), 426*80518852SAndrew Boyer .ring_size = rte_log2_u32(q->num_descs), 427*80518852SAndrew Boyer .ring_base = rte_cpu_to_le_64(q->base_pa), 428*80518852SAndrew Boyer .cq_ring_base = rte_cpu_to_le_64(cq->base_pa), 429*80518852SAndrew Boyer .sg_ring_base = rte_cpu_to_le_64(q->sg_base_pa), 430*80518852SAndrew Boyer }, 431*80518852SAndrew Boyer }; 432*80518852SAndrew Boyer int err; 433*80518852SAndrew Boyer 434*80518852SAndrew Boyer IOCPT_PRINT(DEBUG, "cptq_init.index %d", q->index); 435*80518852SAndrew Boyer IOCPT_PRINT(DEBUG, "cptq_init.ring_base %#jx", q->base_pa); 436*80518852SAndrew Boyer IOCPT_PRINT(DEBUG, "cptq_init.ring_size %d", 437*80518852SAndrew Boyer ctx.cmd.q_init.ring_size); 438*80518852SAndrew Boyer IOCPT_PRINT(DEBUG, "cptq_init.ver %u", ctx.cmd.q_init.ver); 439*80518852SAndrew Boyer 440*80518852SAndrew Boyer iocpt_q_reset(q); 441*80518852SAndrew Boyer iocpt_cq_reset(cq); 442*80518852SAndrew Boyer 443*80518852SAndrew Boyer err = iocpt_adminq_post_wait(dev, &ctx); 444*80518852SAndrew Boyer if (err != 0) 445*80518852SAndrew Boyer return err; 446*80518852SAndrew Boyer 447*80518852SAndrew Boyer q->hw_type = ctx.comp.q_init.hw_type; 448*80518852SAndrew Boyer q->hw_index = rte_le_to_cpu_32(ctx.comp.q_init.hw_index); 449*80518852SAndrew Boyer q->db = iocpt_db_map(dev, q); 450*80518852SAndrew Boyer 451*80518852SAndrew Boyer IOCPT_PRINT(DEBUG, "cptq->hw_type %d", q->hw_type); 452*80518852SAndrew Boyer IOCPT_PRINT(DEBUG, "cptq->hw_index %d", q->hw_index); 453*80518852SAndrew Boyer IOCPT_PRINT(DEBUG, "cptq->db %p", q->db); 454*80518852SAndrew Boyer 455*80518852SAndrew Boyer cptq->flags |= IOCPT_Q_F_INITED; 456*80518852SAndrew Boyer 457*80518852SAndrew Boyer return 0; 458*80518852SAndrew Boyer } 459*80518852SAndrew Boyer 460*80518852SAndrew Boyer static void 461*80518852SAndrew Boyer iocpt_cryptoq_deinit(struct iocpt_crypto_q *cptq) 462*80518852SAndrew Boyer { 463*80518852SAndrew Boyer struct iocpt_dev *dev = cptq->dev; 464*80518852SAndrew Boyer struct iocpt_admin_ctx ctx = { 465*80518852SAndrew Boyer .pending_work = true, 466*80518852SAndrew Boyer .cmd.q_control = { 467*80518852SAndrew Boyer .opcode = IOCPT_CMD_Q_CONTROL, 468*80518852SAndrew Boyer .type = IOCPT_QTYPE_CRYPTOQ, 469*80518852SAndrew Boyer .index = rte_cpu_to_le_32(cptq->q.index), 470*80518852SAndrew Boyer .oper = IOCPT_Q_DISABLE, 471*80518852SAndrew Boyer }, 472*80518852SAndrew Boyer }; 473*80518852SAndrew Boyer unsigned long sleep_usec = 100UL * 1000; 474*80518852SAndrew Boyer uint32_t sleep_cnt, sleep_max = IOCPT_CRYPTOQ_WAIT; 475*80518852SAndrew Boyer int err; 476*80518852SAndrew Boyer 477*80518852SAndrew Boyer for (sleep_cnt = 0; sleep_cnt < sleep_max; sleep_cnt++) { 478*80518852SAndrew Boyer ctx.pending_work = true; 479*80518852SAndrew Boyer 480*80518852SAndrew Boyer err = iocpt_adminq_post_wait(dev, &ctx); 481*80518852SAndrew Boyer if (err != -EAGAIN) 482*80518852SAndrew Boyer break; 483*80518852SAndrew Boyer 484*80518852SAndrew Boyer rte_delay_us_block(sleep_usec); 485*80518852SAndrew Boyer } 486*80518852SAndrew Boyer 487*80518852SAndrew Boyer if (err != 0) 488*80518852SAndrew Boyer IOCPT_PRINT(ERR, "Deinit queue %u returned %d after %u ms", 489*80518852SAndrew Boyer cptq->q.index, err, sleep_cnt * 100); 490*80518852SAndrew Boyer else 491*80518852SAndrew Boyer IOCPT_PRINT(DEBUG, "Deinit queue %u returned %d after %u ms", 492*80518852SAndrew Boyer cptq->q.index, err, sleep_cnt * 100); 493*80518852SAndrew Boyer 494*80518852SAndrew Boyer cptq->flags &= ~IOCPT_Q_F_INITED; 495*80518852SAndrew Boyer } 496*80518852SAndrew Boyer 497*80518852SAndrew Boyer void 498*80518852SAndrew Boyer iocpt_cryptoq_free(struct iocpt_crypto_q *cptq) 499*80518852SAndrew Boyer { 500*80518852SAndrew Boyer if (cptq == NULL) 501*80518852SAndrew Boyer return; 502*80518852SAndrew Boyer 503*80518852SAndrew Boyer if (cptq->base_z != NULL) { 504*80518852SAndrew Boyer rte_memzone_free(cptq->base_z); 505*80518852SAndrew Boyer cptq->base_z = NULL; 506*80518852SAndrew Boyer cptq->base = NULL; 507*80518852SAndrew Boyer cptq->base_pa = 0; 508*80518852SAndrew Boyer } 509*80518852SAndrew Boyer 510*80518852SAndrew Boyer iocpt_q_free(&cptq->q); 511*80518852SAndrew Boyer 512*80518852SAndrew Boyer rte_free(cptq); 513*80518852SAndrew Boyer } 514*80518852SAndrew Boyer 515*80518852SAndrew Boyer static int 5162c1662bbSAndrew Boyer iocpt_adminq_alloc(struct iocpt_dev *dev) 5172c1662bbSAndrew Boyer { 5182c1662bbSAndrew Boyer struct iocpt_admin_q *aq; 5192c1662bbSAndrew Boyer uint16_t num_descs = IOCPT_ADMINQ_LENGTH; 5202c1662bbSAndrew Boyer uint16_t flags = 0; 5212c1662bbSAndrew Boyer int err; 5222c1662bbSAndrew Boyer 5232c1662bbSAndrew Boyer err = iocpt_commonq_alloc(dev, 5242c1662bbSAndrew Boyer IOCPT_QTYPE_ADMINQ, 5252c1662bbSAndrew Boyer sizeof(struct iocpt_admin_q), 5262c1662bbSAndrew Boyer rte_socket_id(), 5272c1662bbSAndrew Boyer 0, 5282c1662bbSAndrew Boyer "admin", 5292c1662bbSAndrew Boyer flags, 5302c1662bbSAndrew Boyer num_descs, 5312c1662bbSAndrew Boyer 1, 5322c1662bbSAndrew Boyer sizeof(struct iocpt_admin_cmd), 5332c1662bbSAndrew Boyer sizeof(struct iocpt_admin_comp), 5342c1662bbSAndrew Boyer 0, 5352c1662bbSAndrew Boyer (struct iocpt_common_q **)&aq); 5362c1662bbSAndrew Boyer if (err != 0) 5372c1662bbSAndrew Boyer return err; 5382c1662bbSAndrew Boyer 5392c1662bbSAndrew Boyer aq->flags = flags; 5402c1662bbSAndrew Boyer 5412c1662bbSAndrew Boyer dev->adminq = aq; 5422c1662bbSAndrew Boyer 5432c1662bbSAndrew Boyer return 0; 5442c1662bbSAndrew Boyer } 5452c1662bbSAndrew Boyer 5462c1662bbSAndrew Boyer static int 5472c1662bbSAndrew Boyer iocpt_adminq_init(struct iocpt_dev *dev) 5482c1662bbSAndrew Boyer { 5492c1662bbSAndrew Boyer return iocpt_dev_adminq_init(dev); 5502c1662bbSAndrew Boyer } 5512c1662bbSAndrew Boyer 5522c1662bbSAndrew Boyer static void 5532c1662bbSAndrew Boyer iocpt_adminq_deinit(struct iocpt_dev *dev) 5542c1662bbSAndrew Boyer { 5552c1662bbSAndrew Boyer dev->adminq->flags &= ~IOCPT_Q_F_INITED; 5562c1662bbSAndrew Boyer } 5572c1662bbSAndrew Boyer 5582c1662bbSAndrew Boyer static void 5592c1662bbSAndrew Boyer iocpt_adminq_free(struct iocpt_admin_q *aq) 5602c1662bbSAndrew Boyer { 5612c1662bbSAndrew Boyer if (aq->base_z != NULL) { 5622c1662bbSAndrew Boyer rte_memzone_free(aq->base_z); 5632c1662bbSAndrew Boyer aq->base_z = NULL; 5642c1662bbSAndrew Boyer aq->base = NULL; 5652c1662bbSAndrew Boyer aq->base_pa = 0; 5662c1662bbSAndrew Boyer } 5672c1662bbSAndrew Boyer 5682c1662bbSAndrew Boyer iocpt_q_free(&aq->q); 5692c1662bbSAndrew Boyer 5702c1662bbSAndrew Boyer rte_free(aq); 5712c1662bbSAndrew Boyer } 5722c1662bbSAndrew Boyer 5732c1662bbSAndrew Boyer static int 574a677112dSAndrew Boyer iocpt_alloc_objs(struct iocpt_dev *dev) 575a677112dSAndrew Boyer { 5766bc7f2cfSAndrew Boyer uint32_t bmsize, i; 5776bc7f2cfSAndrew Boyer uint8_t *bm; 578a677112dSAndrew Boyer int err; 579a677112dSAndrew Boyer 580a677112dSAndrew Boyer IOCPT_PRINT(DEBUG, "Crypto: %s", dev->name); 581a677112dSAndrew Boyer 582*80518852SAndrew Boyer dev->cryptoqs = rte_calloc_socket("iocpt", 583*80518852SAndrew Boyer dev->max_qps, sizeof(*dev->cryptoqs), 584*80518852SAndrew Boyer RTE_CACHE_LINE_SIZE, dev->socket_id); 585*80518852SAndrew Boyer if (dev->cryptoqs == NULL) { 586*80518852SAndrew Boyer IOCPT_PRINT(ERR, "Cannot allocate tx queues array"); 587*80518852SAndrew Boyer return -ENOMEM; 588*80518852SAndrew Boyer } 589*80518852SAndrew Boyer 5902c1662bbSAndrew Boyer rte_spinlock_init(&dev->adminq_lock); 5912c1662bbSAndrew Boyer rte_spinlock_init(&dev->adminq_service_lock); 5922c1662bbSAndrew Boyer 5932c1662bbSAndrew Boyer err = iocpt_adminq_alloc(dev); 5942c1662bbSAndrew Boyer if (err != 0) { 5952c1662bbSAndrew Boyer IOCPT_PRINT(ERR, "Cannot allocate admin queue"); 5962c1662bbSAndrew Boyer err = -ENOMEM; 597*80518852SAndrew Boyer goto err_free_cryptoqs; 5982c1662bbSAndrew Boyer } 5992c1662bbSAndrew Boyer 600a677112dSAndrew Boyer dev->info_sz = RTE_ALIGN(sizeof(*dev->info), rte_mem_page_size()); 601a677112dSAndrew Boyer dev->info_z = iocpt_dma_zone_reserve("info", 0, dev->info_sz, 602a677112dSAndrew Boyer IONIC_ALIGN, dev->socket_id); 603a677112dSAndrew Boyer if (dev->info_z == NULL) { 604a677112dSAndrew Boyer IOCPT_PRINT(ERR, "Cannot allocate dev info memory"); 605a677112dSAndrew Boyer err = -ENOMEM; 6062c1662bbSAndrew Boyer goto err_free_adminq; 607a677112dSAndrew Boyer } 608a677112dSAndrew Boyer 609a677112dSAndrew Boyer dev->info = dev->info_z->addr; 610a677112dSAndrew Boyer dev->info_pa = dev->info_z->iova; 611a677112dSAndrew Boyer 6126bc7f2cfSAndrew Boyer bmsize = rte_bitmap_get_memory_footprint(dev->max_sessions); 6136bc7f2cfSAndrew Boyer bm = rte_malloc_socket("iocpt", bmsize, 6146bc7f2cfSAndrew Boyer RTE_CACHE_LINE_SIZE, dev->socket_id); 6156bc7f2cfSAndrew Boyer if (bm == NULL) { 6166bc7f2cfSAndrew Boyer IOCPT_PRINT(ERR, "Cannot allocate %uB bitmap memory", bmsize); 6176bc7f2cfSAndrew Boyer err = -ENOMEM; 6186bc7f2cfSAndrew Boyer goto err_free_dmazone; 6196bc7f2cfSAndrew Boyer } 6206bc7f2cfSAndrew Boyer 6216bc7f2cfSAndrew Boyer dev->sess_bm = rte_bitmap_init(dev->max_sessions, bm, bmsize); 6226bc7f2cfSAndrew Boyer if (dev->sess_bm == NULL) { 6236bc7f2cfSAndrew Boyer IOCPT_PRINT(ERR, "Cannot initialize bitmap"); 6246bc7f2cfSAndrew Boyer err = -EFAULT; 6256bc7f2cfSAndrew Boyer goto err_free_bm; 6266bc7f2cfSAndrew Boyer } 6276bc7f2cfSAndrew Boyer for (i = 0; i < dev->max_sessions; i++) 6286bc7f2cfSAndrew Boyer rte_bitmap_set(dev->sess_bm, i); 6296bc7f2cfSAndrew Boyer 630a677112dSAndrew Boyer return 0; 631a677112dSAndrew Boyer 6326bc7f2cfSAndrew Boyer err_free_bm: 6336bc7f2cfSAndrew Boyer rte_free(bm); 6346bc7f2cfSAndrew Boyer err_free_dmazone: 6356bc7f2cfSAndrew Boyer rte_memzone_free(dev->info_z); 6366bc7f2cfSAndrew Boyer dev->info_z = NULL; 6376bc7f2cfSAndrew Boyer dev->info = NULL; 6386bc7f2cfSAndrew Boyer dev->info_pa = 0; 6392c1662bbSAndrew Boyer err_free_adminq: 6402c1662bbSAndrew Boyer iocpt_adminq_free(dev->adminq); 6412c1662bbSAndrew Boyer dev->adminq = NULL; 642*80518852SAndrew Boyer err_free_cryptoqs: 643*80518852SAndrew Boyer rte_free(dev->cryptoqs); 644*80518852SAndrew Boyer dev->cryptoqs = NULL; 645a677112dSAndrew Boyer return err; 646a677112dSAndrew Boyer } 647a677112dSAndrew Boyer 6484610ac93SAndrew Boyer static int 6494610ac93SAndrew Boyer iocpt_init(struct iocpt_dev *dev) 6504610ac93SAndrew Boyer { 651a677112dSAndrew Boyer int err; 652a677112dSAndrew Boyer 653a677112dSAndrew Boyer /* Uses dev_cmds */ 654a677112dSAndrew Boyer err = iocpt_dev_init(dev, dev->info_pa); 655a677112dSAndrew Boyer if (err != 0) 656a677112dSAndrew Boyer return err; 657a677112dSAndrew Boyer 6582c1662bbSAndrew Boyer err = iocpt_adminq_init(dev); 6592c1662bbSAndrew Boyer if (err != 0) 6602c1662bbSAndrew Boyer return err; 6612c1662bbSAndrew Boyer 6624610ac93SAndrew Boyer dev->state |= IOCPT_DEV_F_INITED; 6634610ac93SAndrew Boyer 6644610ac93SAndrew Boyer return 0; 6654610ac93SAndrew Boyer } 6664610ac93SAndrew Boyer 6674610ac93SAndrew Boyer void 6684610ac93SAndrew Boyer iocpt_configure(struct iocpt_dev *dev) 6694610ac93SAndrew Boyer { 6704610ac93SAndrew Boyer RTE_SET_USED(dev); 6714610ac93SAndrew Boyer } 6724610ac93SAndrew Boyer 673*80518852SAndrew Boyer int 674*80518852SAndrew Boyer iocpt_start(struct iocpt_dev *dev) 675*80518852SAndrew Boyer { 676*80518852SAndrew Boyer uint32_t i; 677*80518852SAndrew Boyer int err; 678*80518852SAndrew Boyer 679*80518852SAndrew Boyer IOCPT_PRINT(DEBUG, "Starting %u queues", 680*80518852SAndrew Boyer dev->crypto_dev->data->nb_queue_pairs); 681*80518852SAndrew Boyer 682*80518852SAndrew Boyer for (i = 0; i < dev->crypto_dev->data->nb_queue_pairs; i++) { 683*80518852SAndrew Boyer err = iocpt_cryptoq_init(dev->cryptoqs[i]); 684*80518852SAndrew Boyer if (err != 0) 685*80518852SAndrew Boyer return err; 686*80518852SAndrew Boyer } 687*80518852SAndrew Boyer 688*80518852SAndrew Boyer dev->state |= IOCPT_DEV_F_UP; 689*80518852SAndrew Boyer 690*80518852SAndrew Boyer return 0; 691*80518852SAndrew Boyer } 692*80518852SAndrew Boyer 693*80518852SAndrew Boyer void 694*80518852SAndrew Boyer iocpt_stop(struct iocpt_dev *dev) 695*80518852SAndrew Boyer { 696*80518852SAndrew Boyer uint32_t i; 697*80518852SAndrew Boyer 698*80518852SAndrew Boyer IOCPT_PRINT_CALL(); 699*80518852SAndrew Boyer 700*80518852SAndrew Boyer dev->state &= ~IOCPT_DEV_F_UP; 701*80518852SAndrew Boyer 702*80518852SAndrew Boyer for (i = 0; i < dev->crypto_dev->data->nb_queue_pairs; i++) { 703*80518852SAndrew Boyer struct iocpt_crypto_q *cptq = dev->cryptoqs[i]; 704*80518852SAndrew Boyer 705*80518852SAndrew Boyer if (cptq->flags & IOCPT_Q_F_INITED) 706*80518852SAndrew Boyer (void)iocpt_cryptoq_deinit(cptq); 707*80518852SAndrew Boyer } 708*80518852SAndrew Boyer } 709*80518852SAndrew Boyer 7104610ac93SAndrew Boyer void 7114610ac93SAndrew Boyer iocpt_deinit(struct iocpt_dev *dev) 7124610ac93SAndrew Boyer { 7134610ac93SAndrew Boyer IOCPT_PRINT_CALL(); 7144610ac93SAndrew Boyer 7154610ac93SAndrew Boyer if (!(dev->state & IOCPT_DEV_F_INITED)) 7164610ac93SAndrew Boyer return; 7174610ac93SAndrew Boyer 7182c1662bbSAndrew Boyer iocpt_adminq_deinit(dev); 7192c1662bbSAndrew Boyer 7204610ac93SAndrew Boyer dev->state &= ~IOCPT_DEV_F_INITED; 7214610ac93SAndrew Boyer } 7224610ac93SAndrew Boyer 723a677112dSAndrew Boyer static void 724a677112dSAndrew Boyer iocpt_free_objs(struct iocpt_dev *dev) 725a677112dSAndrew Boyer { 726*80518852SAndrew Boyer void **queue_pairs = dev->crypto_dev->data->queue_pairs; 727*80518852SAndrew Boyer uint32_t i; 728*80518852SAndrew Boyer 729a677112dSAndrew Boyer IOCPT_PRINT_CALL(); 730a677112dSAndrew Boyer 731*80518852SAndrew Boyer for (i = 0; i < dev->crypto_dev->data->nb_queue_pairs; i++) { 732*80518852SAndrew Boyer iocpt_cryptoq_free(queue_pairs[i]); 733*80518852SAndrew Boyer queue_pairs[i] = NULL; 734*80518852SAndrew Boyer } 735*80518852SAndrew Boyer 7366bc7f2cfSAndrew Boyer if (dev->sess_bm != NULL) { 7376bc7f2cfSAndrew Boyer rte_bitmap_free(dev->sess_bm); 7386bc7f2cfSAndrew Boyer rte_free(dev->sess_bm); 7396bc7f2cfSAndrew Boyer dev->sess_bm = NULL; 7406bc7f2cfSAndrew Boyer } 7416bc7f2cfSAndrew Boyer 7422c1662bbSAndrew Boyer if (dev->adminq != NULL) { 7432c1662bbSAndrew Boyer iocpt_adminq_free(dev->adminq); 7442c1662bbSAndrew Boyer dev->adminq = NULL; 7452c1662bbSAndrew Boyer } 7462c1662bbSAndrew Boyer 747*80518852SAndrew Boyer if (dev->cryptoqs != NULL) { 748*80518852SAndrew Boyer rte_free(dev->cryptoqs); 749*80518852SAndrew Boyer dev->cryptoqs = NULL; 750*80518852SAndrew Boyer } 751*80518852SAndrew Boyer 752a677112dSAndrew Boyer if (dev->info != NULL) { 753a677112dSAndrew Boyer rte_memzone_free(dev->info_z); 754a677112dSAndrew Boyer dev->info_z = NULL; 755a677112dSAndrew Boyer dev->info = NULL; 756a677112dSAndrew Boyer dev->info_pa = 0; 757a677112dSAndrew Boyer } 758a677112dSAndrew Boyer } 759a677112dSAndrew Boyer 7604610ac93SAndrew Boyer static int 7614610ac93SAndrew Boyer iocpt_devargs(struct rte_devargs *devargs, struct iocpt_dev *dev) 7624610ac93SAndrew Boyer { 7634610ac93SAndrew Boyer RTE_SET_USED(devargs); 7644610ac93SAndrew Boyer RTE_SET_USED(dev); 7654610ac93SAndrew Boyer 7664610ac93SAndrew Boyer return 0; 7674610ac93SAndrew Boyer } 7684610ac93SAndrew Boyer 7694610ac93SAndrew Boyer int 7704610ac93SAndrew Boyer iocpt_probe(void *bus_dev, struct rte_device *rte_dev, 7714610ac93SAndrew Boyer struct iocpt_dev_bars *bars, const struct iocpt_dev_intf *intf, 7724610ac93SAndrew Boyer uint8_t driver_id, uint8_t socket_id) 7734610ac93SAndrew Boyer { 7744610ac93SAndrew Boyer struct rte_cryptodev_pmd_init_params init_params = { 7754610ac93SAndrew Boyer "iocpt", 7764610ac93SAndrew Boyer sizeof(struct iocpt_dev), 7774610ac93SAndrew Boyer socket_id, 7784610ac93SAndrew Boyer RTE_CRYPTODEV_PMD_DEFAULT_MAX_NB_QUEUE_PAIRS 7794610ac93SAndrew Boyer }; 7804610ac93SAndrew Boyer struct rte_cryptodev *cdev; 7814610ac93SAndrew Boyer struct iocpt_dev *dev; 78225c896eaSAndrew Boyer uint32_t i, sig; 7834610ac93SAndrew Boyer int err; 7844610ac93SAndrew Boyer 78525c896eaSAndrew Boyer /* Check structs (trigger error at compilation time) */ 78625c896eaSAndrew Boyer iocpt_struct_size_checks(); 78725c896eaSAndrew Boyer 7884610ac93SAndrew Boyer if (rte_eal_process_type() != RTE_PROC_PRIMARY) { 7894610ac93SAndrew Boyer IOCPT_PRINT(ERR, "Multi-process not supported"); 7904610ac93SAndrew Boyer err = -EPERM; 7914610ac93SAndrew Boyer goto err; 7924610ac93SAndrew Boyer } 7934610ac93SAndrew Boyer 7944610ac93SAndrew Boyer cdev = rte_cryptodev_pmd_create(rte_dev->name, rte_dev, &init_params); 7954610ac93SAndrew Boyer if (cdev == NULL) { 7964610ac93SAndrew Boyer IOCPT_PRINT(ERR, "Out of memory"); 7974610ac93SAndrew Boyer err = -ENOMEM; 7984610ac93SAndrew Boyer goto err; 7994610ac93SAndrew Boyer } 8004610ac93SAndrew Boyer 8014610ac93SAndrew Boyer dev = cdev->data->dev_private; 8024610ac93SAndrew Boyer dev->crypto_dev = cdev; 8034610ac93SAndrew Boyer dev->bus_dev = bus_dev; 8044610ac93SAndrew Boyer dev->intf = intf; 8054610ac93SAndrew Boyer dev->driver_id = driver_id; 8064610ac93SAndrew Boyer dev->socket_id = socket_id; 8074610ac93SAndrew Boyer 8084610ac93SAndrew Boyer for (i = 0; i < bars->num_bars; i++) { 8094610ac93SAndrew Boyer struct ionic_dev_bar *bar = &bars->bar[i]; 8104610ac93SAndrew Boyer 8114610ac93SAndrew Boyer IOCPT_PRINT(DEBUG, 8124610ac93SAndrew Boyer "bar[%u] = { .va = %p, .pa = %#jx, .len = %lu }", 8134610ac93SAndrew Boyer i, bar->vaddr, bar->bus_addr, bar->len); 8144610ac93SAndrew Boyer if (bar->vaddr == NULL) { 8154610ac93SAndrew Boyer IOCPT_PRINT(ERR, "Null bar found, aborting"); 8164610ac93SAndrew Boyer err = -EFAULT; 8174610ac93SAndrew Boyer goto err_destroy_crypto_dev; 8184610ac93SAndrew Boyer } 8194610ac93SAndrew Boyer 8204610ac93SAndrew Boyer dev->bars.bar[i].vaddr = bar->vaddr; 8214610ac93SAndrew Boyer dev->bars.bar[i].bus_addr = bar->bus_addr; 8224610ac93SAndrew Boyer dev->bars.bar[i].len = bar->len; 8234610ac93SAndrew Boyer } 8244610ac93SAndrew Boyer dev->bars.num_bars = bars->num_bars; 8254610ac93SAndrew Boyer 8264610ac93SAndrew Boyer err = iocpt_devargs(rte_dev->devargs, dev); 8274610ac93SAndrew Boyer if (err != 0) { 8284610ac93SAndrew Boyer IOCPT_PRINT(ERR, "Cannot parse device arguments"); 8294610ac93SAndrew Boyer goto err_destroy_crypto_dev; 8304610ac93SAndrew Boyer } 8314610ac93SAndrew Boyer 8324610ac93SAndrew Boyer err = iocpt_setup_bars(dev); 8334610ac93SAndrew Boyer if (err != 0) { 8344610ac93SAndrew Boyer IOCPT_PRINT(ERR, "Cannot setup BARs: %d, aborting", err); 8354610ac93SAndrew Boyer goto err_destroy_crypto_dev; 8364610ac93SAndrew Boyer } 8374610ac93SAndrew Boyer 83825c896eaSAndrew Boyer sig = ioread32(&dev->dev_info->signature); 83925c896eaSAndrew Boyer if (sig != IOCPT_DEV_INFO_SIGNATURE) { 84025c896eaSAndrew Boyer IOCPT_PRINT(ERR, "Incompatible firmware signature %#x", sig); 84125c896eaSAndrew Boyer err = -EFAULT; 84225c896eaSAndrew Boyer goto err_destroy_crypto_dev; 84325c896eaSAndrew Boyer } 84425c896eaSAndrew Boyer 84525c896eaSAndrew Boyer for (i = 0; i < IOCPT_FWVERS_BUFLEN; i++) 84625c896eaSAndrew Boyer dev->fw_version[i] = ioread8(&dev->dev_info->fw_version[i]); 84725c896eaSAndrew Boyer dev->fw_version[IOCPT_FWVERS_BUFLEN - 1] = '\0'; 84825c896eaSAndrew Boyer IOCPT_PRINT(DEBUG, "%s firmware: %s", dev->name, dev->fw_version); 84925c896eaSAndrew Boyer 850a677112dSAndrew Boyer err = iocpt_dev_identify(dev); 851a677112dSAndrew Boyer if (err != 0) { 852a677112dSAndrew Boyer IOCPT_PRINT(ERR, "Cannot identify device: %d, aborting", 853a677112dSAndrew Boyer err); 854a677112dSAndrew Boyer goto err_destroy_crypto_dev; 855a677112dSAndrew Boyer } 856a677112dSAndrew Boyer 857a677112dSAndrew Boyer err = iocpt_alloc_objs(dev); 858a677112dSAndrew Boyer if (err != 0) { 859a677112dSAndrew Boyer IOCPT_PRINT(ERR, "Cannot alloc device objects: %d", err); 860a677112dSAndrew Boyer goto err_destroy_crypto_dev; 861a677112dSAndrew Boyer } 862a677112dSAndrew Boyer 8634610ac93SAndrew Boyer err = iocpt_init(dev); 8644610ac93SAndrew Boyer if (err != 0) { 8654610ac93SAndrew Boyer IOCPT_PRINT(ERR, "Cannot init device: %d, aborting", err); 866a677112dSAndrew Boyer goto err_free_objs; 8674610ac93SAndrew Boyer } 8684610ac93SAndrew Boyer 869dddfb0d9SAndrew Boyer err = iocpt_assign_ops(cdev); 870dddfb0d9SAndrew Boyer if (err != 0) { 871dddfb0d9SAndrew Boyer IOCPT_PRINT(ERR, "Failed to configure opts"); 872dddfb0d9SAndrew Boyer goto err_deinit_dev; 873dddfb0d9SAndrew Boyer } 874dddfb0d9SAndrew Boyer 8754610ac93SAndrew Boyer return 0; 8764610ac93SAndrew Boyer 877dddfb0d9SAndrew Boyer err_deinit_dev: 878dddfb0d9SAndrew Boyer iocpt_deinit(dev); 879a677112dSAndrew Boyer err_free_objs: 880a677112dSAndrew Boyer iocpt_free_objs(dev); 8814610ac93SAndrew Boyer err_destroy_crypto_dev: 8824610ac93SAndrew Boyer rte_cryptodev_pmd_destroy(cdev); 8834610ac93SAndrew Boyer err: 8844610ac93SAndrew Boyer return err; 8854610ac93SAndrew Boyer } 8864610ac93SAndrew Boyer 8874610ac93SAndrew Boyer int 8884610ac93SAndrew Boyer iocpt_remove(struct rte_device *rte_dev) 8894610ac93SAndrew Boyer { 8904610ac93SAndrew Boyer struct rte_cryptodev *cdev; 8914610ac93SAndrew Boyer struct iocpt_dev *dev; 8924610ac93SAndrew Boyer 8934610ac93SAndrew Boyer cdev = rte_cryptodev_pmd_get_named_dev(rte_dev->name); 8944610ac93SAndrew Boyer if (cdev == NULL) { 8954610ac93SAndrew Boyer IOCPT_PRINT(DEBUG, "Cannot find device %s", rte_dev->name); 8964610ac93SAndrew Boyer return -ENODEV; 8974610ac93SAndrew Boyer } 8984610ac93SAndrew Boyer 8994610ac93SAndrew Boyer dev = cdev->data->dev_private; 9004610ac93SAndrew Boyer 9014610ac93SAndrew Boyer iocpt_deinit(dev); 9024610ac93SAndrew Boyer 903a677112dSAndrew Boyer iocpt_dev_reset(dev); 904a677112dSAndrew Boyer 905a677112dSAndrew Boyer iocpt_free_objs(dev); 906a677112dSAndrew Boyer 9074610ac93SAndrew Boyer rte_cryptodev_pmd_destroy(cdev); 9084610ac93SAndrew Boyer 9094610ac93SAndrew Boyer return 0; 9104610ac93SAndrew Boyer } 9114610ac93SAndrew Boyer 9124610ac93SAndrew Boyer RTE_LOG_REGISTER_DEFAULT(iocpt_logtype, NOTICE); 913