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 13*2c1662bbSAndrew Boyer static int 14*2c1662bbSAndrew Boyer iocpt_cq_init(struct iocpt_cq *cq, uint16_t num_descs) 15*2c1662bbSAndrew Boyer { 16*2c1662bbSAndrew Boyer if (!rte_is_power_of_2(num_descs) || 17*2c1662bbSAndrew Boyer num_descs < IOCPT_MIN_RING_DESC || 18*2c1662bbSAndrew Boyer num_descs > IOCPT_MAX_RING_DESC) { 19*2c1662bbSAndrew Boyer IOCPT_PRINT(ERR, "%u descriptors (min: %u max: %u)", 20*2c1662bbSAndrew Boyer num_descs, IOCPT_MIN_RING_DESC, IOCPT_MAX_RING_DESC); 21*2c1662bbSAndrew Boyer return -EINVAL; 22*2c1662bbSAndrew Boyer } 23*2c1662bbSAndrew Boyer 24*2c1662bbSAndrew Boyer cq->num_descs = num_descs; 25*2c1662bbSAndrew Boyer cq->size_mask = num_descs - 1; 26*2c1662bbSAndrew Boyer cq->tail_idx = 0; 27*2c1662bbSAndrew Boyer cq->done_color = 1; 28*2c1662bbSAndrew Boyer 29*2c1662bbSAndrew Boyer return 0; 30*2c1662bbSAndrew Boyer } 31*2c1662bbSAndrew Boyer 32*2c1662bbSAndrew Boyer static void 33*2c1662bbSAndrew Boyer iocpt_cq_map(struct iocpt_cq *cq, void *base, rte_iova_t base_pa) 34*2c1662bbSAndrew Boyer { 35*2c1662bbSAndrew Boyer cq->base = base; 36*2c1662bbSAndrew Boyer cq->base_pa = base_pa; 37*2c1662bbSAndrew Boyer } 38*2c1662bbSAndrew Boyer 39*2c1662bbSAndrew Boyer uint32_t 40*2c1662bbSAndrew Boyer iocpt_cq_service(struct iocpt_cq *cq, uint32_t work_to_do, 41*2c1662bbSAndrew Boyer iocpt_cq_cb cb, void *cb_arg) 42*2c1662bbSAndrew Boyer { 43*2c1662bbSAndrew Boyer uint32_t work_done = 0; 44*2c1662bbSAndrew Boyer 45*2c1662bbSAndrew Boyer if (work_to_do == 0) 46*2c1662bbSAndrew Boyer return 0; 47*2c1662bbSAndrew Boyer 48*2c1662bbSAndrew Boyer while (cb(cq, cq->tail_idx, cb_arg)) { 49*2c1662bbSAndrew Boyer cq->tail_idx = Q_NEXT_TO_SRVC(cq, 1); 50*2c1662bbSAndrew Boyer if (cq->tail_idx == 0) 51*2c1662bbSAndrew Boyer cq->done_color = !cq->done_color; 52*2c1662bbSAndrew Boyer 53*2c1662bbSAndrew Boyer if (++work_done == work_to_do) 54*2c1662bbSAndrew Boyer break; 55*2c1662bbSAndrew Boyer } 56*2c1662bbSAndrew Boyer 57*2c1662bbSAndrew Boyer return work_done; 58*2c1662bbSAndrew Boyer } 59*2c1662bbSAndrew Boyer 60*2c1662bbSAndrew Boyer static int 61*2c1662bbSAndrew Boyer iocpt_q_init(struct iocpt_queue *q, uint8_t type, uint32_t index, 62*2c1662bbSAndrew Boyer uint16_t num_descs, uint16_t num_segs, uint32_t socket_id) 63*2c1662bbSAndrew Boyer { 64*2c1662bbSAndrew Boyer uint32_t ring_size; 65*2c1662bbSAndrew Boyer 66*2c1662bbSAndrew Boyer if (!rte_is_power_of_2(num_descs)) 67*2c1662bbSAndrew Boyer return -EINVAL; 68*2c1662bbSAndrew Boyer 69*2c1662bbSAndrew Boyer ring_size = rte_log2_u32(num_descs); 70*2c1662bbSAndrew Boyer if (ring_size < 2 || ring_size > 16) 71*2c1662bbSAndrew Boyer return -EINVAL; 72*2c1662bbSAndrew Boyer 73*2c1662bbSAndrew Boyer q->type = type; 74*2c1662bbSAndrew Boyer q->index = index; 75*2c1662bbSAndrew Boyer q->num_descs = num_descs; 76*2c1662bbSAndrew Boyer q->num_segs = num_segs; 77*2c1662bbSAndrew Boyer q->size_mask = num_descs - 1; 78*2c1662bbSAndrew Boyer q->head_idx = 0; 79*2c1662bbSAndrew Boyer q->tail_idx = 0; 80*2c1662bbSAndrew Boyer 81*2c1662bbSAndrew Boyer q->info = rte_calloc_socket("iocpt", 82*2c1662bbSAndrew Boyer num_descs * num_segs, sizeof(void *), 83*2c1662bbSAndrew Boyer rte_mem_page_size(), socket_id); 84*2c1662bbSAndrew Boyer if (q->info == NULL) { 85*2c1662bbSAndrew Boyer IOCPT_PRINT(ERR, "Cannot allocate queue info"); 86*2c1662bbSAndrew Boyer return -ENOMEM; 87*2c1662bbSAndrew Boyer } 88*2c1662bbSAndrew Boyer 89*2c1662bbSAndrew Boyer return 0; 90*2c1662bbSAndrew Boyer } 91*2c1662bbSAndrew Boyer 92*2c1662bbSAndrew Boyer static void 93*2c1662bbSAndrew Boyer iocpt_q_map(struct iocpt_queue *q, void *base, rte_iova_t base_pa) 94*2c1662bbSAndrew Boyer { 95*2c1662bbSAndrew Boyer q->base = base; 96*2c1662bbSAndrew Boyer q->base_pa = base_pa; 97*2c1662bbSAndrew Boyer } 98*2c1662bbSAndrew Boyer 99*2c1662bbSAndrew Boyer static void 100*2c1662bbSAndrew Boyer iocpt_q_sg_map(struct iocpt_queue *q, void *base, rte_iova_t base_pa) 101*2c1662bbSAndrew Boyer { 102*2c1662bbSAndrew Boyer q->sg_base = base; 103*2c1662bbSAndrew Boyer q->sg_base_pa = base_pa; 104*2c1662bbSAndrew Boyer } 105*2c1662bbSAndrew Boyer 106*2c1662bbSAndrew Boyer static void 107*2c1662bbSAndrew Boyer iocpt_q_free(struct iocpt_queue *q) 108*2c1662bbSAndrew Boyer { 109*2c1662bbSAndrew Boyer if (q->info != NULL) { 110*2c1662bbSAndrew Boyer rte_free(q->info); 111*2c1662bbSAndrew Boyer q->info = NULL; 112*2c1662bbSAndrew Boyer } 113*2c1662bbSAndrew Boyer } 114*2c1662bbSAndrew Boyer 115a677112dSAndrew Boyer static const struct rte_memzone * 116a677112dSAndrew Boyer iocpt_dma_zone_reserve(const char *type_name, uint16_t qid, size_t size, 117a677112dSAndrew Boyer unsigned int align, int socket_id) 118a677112dSAndrew Boyer { 119a677112dSAndrew Boyer char zone_name[RTE_MEMZONE_NAMESIZE]; 120a677112dSAndrew Boyer const struct rte_memzone *mz; 121a677112dSAndrew Boyer int err; 122a677112dSAndrew Boyer 123a677112dSAndrew Boyer err = snprintf(zone_name, sizeof(zone_name), 124a677112dSAndrew Boyer "iocpt_%s_%u", type_name, qid); 125a677112dSAndrew Boyer if (err >= RTE_MEMZONE_NAMESIZE) { 126a677112dSAndrew Boyer IOCPT_PRINT(ERR, "Name %s too long", type_name); 127a677112dSAndrew Boyer return NULL; 128a677112dSAndrew Boyer } 129a677112dSAndrew Boyer 130a677112dSAndrew Boyer mz = rte_memzone_lookup(zone_name); 131a677112dSAndrew Boyer if (mz != NULL) 132a677112dSAndrew Boyer return mz; 133a677112dSAndrew Boyer 134a677112dSAndrew Boyer return rte_memzone_reserve_aligned(zone_name, size, socket_id, 135a677112dSAndrew Boyer RTE_MEMZONE_IOVA_CONTIG, align); 136a677112dSAndrew Boyer } 137a677112dSAndrew Boyer 138a677112dSAndrew Boyer static int 139*2c1662bbSAndrew Boyer iocpt_commonq_alloc(struct iocpt_dev *dev, 140*2c1662bbSAndrew Boyer uint8_t type, 141*2c1662bbSAndrew Boyer size_t struct_size, 142*2c1662bbSAndrew Boyer uint32_t socket_id, 143*2c1662bbSAndrew Boyer uint32_t index, 144*2c1662bbSAndrew Boyer const char *type_name, 145*2c1662bbSAndrew Boyer uint16_t flags, 146*2c1662bbSAndrew Boyer uint16_t num_descs, 147*2c1662bbSAndrew Boyer uint16_t num_segs, 148*2c1662bbSAndrew Boyer uint16_t desc_size, 149*2c1662bbSAndrew Boyer uint16_t cq_desc_size, 150*2c1662bbSAndrew Boyer uint16_t sg_desc_size, 151*2c1662bbSAndrew Boyer struct iocpt_common_q **comq) 152*2c1662bbSAndrew Boyer { 153*2c1662bbSAndrew Boyer struct iocpt_common_q *new; 154*2c1662bbSAndrew Boyer uint32_t q_size, cq_size, sg_size, total_size; 155*2c1662bbSAndrew Boyer void *q_base, *cq_base, *sg_base; 156*2c1662bbSAndrew Boyer rte_iova_t q_base_pa = 0; 157*2c1662bbSAndrew Boyer rte_iova_t cq_base_pa = 0; 158*2c1662bbSAndrew Boyer rte_iova_t sg_base_pa = 0; 159*2c1662bbSAndrew Boyer size_t page_size = rte_mem_page_size(); 160*2c1662bbSAndrew Boyer int err; 161*2c1662bbSAndrew Boyer 162*2c1662bbSAndrew Boyer *comq = NULL; 163*2c1662bbSAndrew Boyer 164*2c1662bbSAndrew Boyer q_size = num_descs * desc_size; 165*2c1662bbSAndrew Boyer cq_size = num_descs * cq_desc_size; 166*2c1662bbSAndrew Boyer sg_size = num_descs * sg_desc_size; 167*2c1662bbSAndrew Boyer 168*2c1662bbSAndrew Boyer /* 169*2c1662bbSAndrew Boyer * Note: aligning q_size/cq_size is not enough due to cq_base address 170*2c1662bbSAndrew Boyer * aligning as q_base could be not aligned to the page. 171*2c1662bbSAndrew Boyer * Adding page_size. 172*2c1662bbSAndrew Boyer */ 173*2c1662bbSAndrew Boyer total_size = RTE_ALIGN(q_size, page_size) + 174*2c1662bbSAndrew Boyer RTE_ALIGN(cq_size, page_size) + page_size; 175*2c1662bbSAndrew Boyer if (flags & IOCPT_Q_F_SG) 176*2c1662bbSAndrew Boyer total_size += RTE_ALIGN(sg_size, page_size) + page_size; 177*2c1662bbSAndrew Boyer 178*2c1662bbSAndrew Boyer new = rte_zmalloc_socket("iocpt", struct_size, 179*2c1662bbSAndrew Boyer RTE_CACHE_LINE_SIZE, socket_id); 180*2c1662bbSAndrew Boyer if (new == NULL) { 181*2c1662bbSAndrew Boyer IOCPT_PRINT(ERR, "Cannot allocate queue structure"); 182*2c1662bbSAndrew Boyer return -ENOMEM; 183*2c1662bbSAndrew Boyer } 184*2c1662bbSAndrew Boyer 185*2c1662bbSAndrew Boyer new->dev = dev; 186*2c1662bbSAndrew Boyer 187*2c1662bbSAndrew Boyer err = iocpt_q_init(&new->q, type, index, num_descs, num_segs, 188*2c1662bbSAndrew Boyer socket_id); 189*2c1662bbSAndrew Boyer if (err != 0) { 190*2c1662bbSAndrew Boyer IOCPT_PRINT(ERR, "Queue initialization failed"); 191*2c1662bbSAndrew Boyer goto err_free_q; 192*2c1662bbSAndrew Boyer } 193*2c1662bbSAndrew Boyer 194*2c1662bbSAndrew Boyer err = iocpt_cq_init(&new->cq, num_descs); 195*2c1662bbSAndrew Boyer if (err != 0) { 196*2c1662bbSAndrew Boyer IOCPT_PRINT(ERR, "Completion queue initialization failed"); 197*2c1662bbSAndrew Boyer goto err_deinit_q; 198*2c1662bbSAndrew Boyer } 199*2c1662bbSAndrew Boyer 200*2c1662bbSAndrew Boyer new->base_z = iocpt_dma_zone_reserve(type_name, index, total_size, 201*2c1662bbSAndrew Boyer IONIC_ALIGN, socket_id); 202*2c1662bbSAndrew Boyer if (new->base_z == NULL) { 203*2c1662bbSAndrew Boyer IOCPT_PRINT(ERR, "Cannot reserve queue DMA memory"); 204*2c1662bbSAndrew Boyer err = -ENOMEM; 205*2c1662bbSAndrew Boyer goto err_deinit_cq; 206*2c1662bbSAndrew Boyer } 207*2c1662bbSAndrew Boyer 208*2c1662bbSAndrew Boyer new->base = new->base_z->addr; 209*2c1662bbSAndrew Boyer new->base_pa = new->base_z->iova; 210*2c1662bbSAndrew Boyer 211*2c1662bbSAndrew Boyer q_base = new->base; 212*2c1662bbSAndrew Boyer q_base_pa = new->base_pa; 213*2c1662bbSAndrew Boyer iocpt_q_map(&new->q, q_base, q_base_pa); 214*2c1662bbSAndrew Boyer 215*2c1662bbSAndrew Boyer cq_base = (void *)RTE_ALIGN((uintptr_t)q_base + q_size, page_size); 216*2c1662bbSAndrew Boyer cq_base_pa = RTE_ALIGN(q_base_pa + q_size, page_size); 217*2c1662bbSAndrew Boyer iocpt_cq_map(&new->cq, cq_base, cq_base_pa); 218*2c1662bbSAndrew Boyer 219*2c1662bbSAndrew Boyer if (flags & IOCPT_Q_F_SG) { 220*2c1662bbSAndrew Boyer sg_base = (void *)RTE_ALIGN((uintptr_t)cq_base + cq_size, 221*2c1662bbSAndrew Boyer page_size); 222*2c1662bbSAndrew Boyer sg_base_pa = RTE_ALIGN(cq_base_pa + cq_size, page_size); 223*2c1662bbSAndrew Boyer iocpt_q_sg_map(&new->q, sg_base, sg_base_pa); 224*2c1662bbSAndrew Boyer } 225*2c1662bbSAndrew Boyer 226*2c1662bbSAndrew Boyer IOCPT_PRINT(DEBUG, "q_base_pa %#jx cq_base_pa %#jx sg_base_pa %#jx", 227*2c1662bbSAndrew Boyer q_base_pa, cq_base_pa, sg_base_pa); 228*2c1662bbSAndrew Boyer 229*2c1662bbSAndrew Boyer *comq = new; 230*2c1662bbSAndrew Boyer 231*2c1662bbSAndrew Boyer return 0; 232*2c1662bbSAndrew Boyer 233*2c1662bbSAndrew Boyer err_deinit_cq: 234*2c1662bbSAndrew Boyer err_deinit_q: 235*2c1662bbSAndrew Boyer iocpt_q_free(&new->q); 236*2c1662bbSAndrew Boyer err_free_q: 237*2c1662bbSAndrew Boyer rte_free(new); 238*2c1662bbSAndrew Boyer return err; 239*2c1662bbSAndrew Boyer } 240*2c1662bbSAndrew Boyer 241*2c1662bbSAndrew Boyer struct ionic_doorbell * 242*2c1662bbSAndrew Boyer iocpt_db_map(struct iocpt_dev *dev, struct iocpt_queue *q) 243*2c1662bbSAndrew Boyer { 244*2c1662bbSAndrew Boyer return dev->db_pages + q->hw_type; 245*2c1662bbSAndrew Boyer } 246*2c1662bbSAndrew Boyer 247*2c1662bbSAndrew Boyer static int 248*2c1662bbSAndrew Boyer iocpt_adminq_alloc(struct iocpt_dev *dev) 249*2c1662bbSAndrew Boyer { 250*2c1662bbSAndrew Boyer struct iocpt_admin_q *aq; 251*2c1662bbSAndrew Boyer uint16_t num_descs = IOCPT_ADMINQ_LENGTH; 252*2c1662bbSAndrew Boyer uint16_t flags = 0; 253*2c1662bbSAndrew Boyer int err; 254*2c1662bbSAndrew Boyer 255*2c1662bbSAndrew Boyer err = iocpt_commonq_alloc(dev, 256*2c1662bbSAndrew Boyer IOCPT_QTYPE_ADMINQ, 257*2c1662bbSAndrew Boyer sizeof(struct iocpt_admin_q), 258*2c1662bbSAndrew Boyer rte_socket_id(), 259*2c1662bbSAndrew Boyer 0, 260*2c1662bbSAndrew Boyer "admin", 261*2c1662bbSAndrew Boyer flags, 262*2c1662bbSAndrew Boyer num_descs, 263*2c1662bbSAndrew Boyer 1, 264*2c1662bbSAndrew Boyer sizeof(struct iocpt_admin_cmd), 265*2c1662bbSAndrew Boyer sizeof(struct iocpt_admin_comp), 266*2c1662bbSAndrew Boyer 0, 267*2c1662bbSAndrew Boyer (struct iocpt_common_q **)&aq); 268*2c1662bbSAndrew Boyer if (err != 0) 269*2c1662bbSAndrew Boyer return err; 270*2c1662bbSAndrew Boyer 271*2c1662bbSAndrew Boyer aq->flags = flags; 272*2c1662bbSAndrew Boyer 273*2c1662bbSAndrew Boyer dev->adminq = aq; 274*2c1662bbSAndrew Boyer 275*2c1662bbSAndrew Boyer return 0; 276*2c1662bbSAndrew Boyer } 277*2c1662bbSAndrew Boyer 278*2c1662bbSAndrew Boyer static int 279*2c1662bbSAndrew Boyer iocpt_adminq_init(struct iocpt_dev *dev) 280*2c1662bbSAndrew Boyer { 281*2c1662bbSAndrew Boyer return iocpt_dev_adminq_init(dev); 282*2c1662bbSAndrew Boyer } 283*2c1662bbSAndrew Boyer 284*2c1662bbSAndrew Boyer static void 285*2c1662bbSAndrew Boyer iocpt_adminq_deinit(struct iocpt_dev *dev) 286*2c1662bbSAndrew Boyer { 287*2c1662bbSAndrew Boyer dev->adminq->flags &= ~IOCPT_Q_F_INITED; 288*2c1662bbSAndrew Boyer } 289*2c1662bbSAndrew Boyer 290*2c1662bbSAndrew Boyer static void 291*2c1662bbSAndrew Boyer iocpt_adminq_free(struct iocpt_admin_q *aq) 292*2c1662bbSAndrew Boyer { 293*2c1662bbSAndrew Boyer if (aq->base_z != NULL) { 294*2c1662bbSAndrew Boyer rte_memzone_free(aq->base_z); 295*2c1662bbSAndrew Boyer aq->base_z = NULL; 296*2c1662bbSAndrew Boyer aq->base = NULL; 297*2c1662bbSAndrew Boyer aq->base_pa = 0; 298*2c1662bbSAndrew Boyer } 299*2c1662bbSAndrew Boyer 300*2c1662bbSAndrew Boyer iocpt_q_free(&aq->q); 301*2c1662bbSAndrew Boyer 302*2c1662bbSAndrew Boyer rte_free(aq); 303*2c1662bbSAndrew Boyer } 304*2c1662bbSAndrew Boyer 305*2c1662bbSAndrew Boyer static int 306a677112dSAndrew Boyer iocpt_alloc_objs(struct iocpt_dev *dev) 307a677112dSAndrew Boyer { 308a677112dSAndrew Boyer int err; 309a677112dSAndrew Boyer 310a677112dSAndrew Boyer IOCPT_PRINT(DEBUG, "Crypto: %s", dev->name); 311a677112dSAndrew Boyer 312*2c1662bbSAndrew Boyer rte_spinlock_init(&dev->adminq_lock); 313*2c1662bbSAndrew Boyer rte_spinlock_init(&dev->adminq_service_lock); 314*2c1662bbSAndrew Boyer 315*2c1662bbSAndrew Boyer err = iocpt_adminq_alloc(dev); 316*2c1662bbSAndrew Boyer if (err != 0) { 317*2c1662bbSAndrew Boyer IOCPT_PRINT(ERR, "Cannot allocate admin queue"); 318*2c1662bbSAndrew Boyer err = -ENOMEM; 319*2c1662bbSAndrew Boyer goto err_out; 320*2c1662bbSAndrew Boyer } 321*2c1662bbSAndrew Boyer 322a677112dSAndrew Boyer dev->info_sz = RTE_ALIGN(sizeof(*dev->info), rte_mem_page_size()); 323a677112dSAndrew Boyer dev->info_z = iocpt_dma_zone_reserve("info", 0, dev->info_sz, 324a677112dSAndrew Boyer IONIC_ALIGN, dev->socket_id); 325a677112dSAndrew Boyer if (dev->info_z == NULL) { 326a677112dSAndrew Boyer IOCPT_PRINT(ERR, "Cannot allocate dev info memory"); 327a677112dSAndrew Boyer err = -ENOMEM; 328*2c1662bbSAndrew Boyer goto err_free_adminq; 329a677112dSAndrew Boyer } 330a677112dSAndrew Boyer 331a677112dSAndrew Boyer dev->info = dev->info_z->addr; 332a677112dSAndrew Boyer dev->info_pa = dev->info_z->iova; 333a677112dSAndrew Boyer 334a677112dSAndrew Boyer return 0; 335a677112dSAndrew Boyer 336*2c1662bbSAndrew Boyer err_free_adminq: 337*2c1662bbSAndrew Boyer iocpt_adminq_free(dev->adminq); 338*2c1662bbSAndrew Boyer dev->adminq = NULL; 339a677112dSAndrew Boyer err_out: 340a677112dSAndrew Boyer return err; 341a677112dSAndrew Boyer } 342a677112dSAndrew Boyer 3434610ac93SAndrew Boyer static int 3444610ac93SAndrew Boyer iocpt_init(struct iocpt_dev *dev) 3454610ac93SAndrew Boyer { 346a677112dSAndrew Boyer int err; 347a677112dSAndrew Boyer 348a677112dSAndrew Boyer /* Uses dev_cmds */ 349a677112dSAndrew Boyer err = iocpt_dev_init(dev, dev->info_pa); 350a677112dSAndrew Boyer if (err != 0) 351a677112dSAndrew Boyer return err; 352a677112dSAndrew Boyer 353*2c1662bbSAndrew Boyer err = iocpt_adminq_init(dev); 354*2c1662bbSAndrew Boyer if (err != 0) 355*2c1662bbSAndrew Boyer return err; 356*2c1662bbSAndrew Boyer 3574610ac93SAndrew Boyer dev->state |= IOCPT_DEV_F_INITED; 3584610ac93SAndrew Boyer 3594610ac93SAndrew Boyer return 0; 3604610ac93SAndrew Boyer } 3614610ac93SAndrew Boyer 3624610ac93SAndrew Boyer void 3634610ac93SAndrew Boyer iocpt_configure(struct iocpt_dev *dev) 3644610ac93SAndrew Boyer { 3654610ac93SAndrew Boyer RTE_SET_USED(dev); 3664610ac93SAndrew Boyer } 3674610ac93SAndrew Boyer 3684610ac93SAndrew Boyer void 3694610ac93SAndrew Boyer iocpt_deinit(struct iocpt_dev *dev) 3704610ac93SAndrew Boyer { 3714610ac93SAndrew Boyer IOCPT_PRINT_CALL(); 3724610ac93SAndrew Boyer 3734610ac93SAndrew Boyer if (!(dev->state & IOCPT_DEV_F_INITED)) 3744610ac93SAndrew Boyer return; 3754610ac93SAndrew Boyer 376*2c1662bbSAndrew Boyer iocpt_adminq_deinit(dev); 377*2c1662bbSAndrew Boyer 3784610ac93SAndrew Boyer dev->state &= ~IOCPT_DEV_F_INITED; 3794610ac93SAndrew Boyer } 3804610ac93SAndrew Boyer 381a677112dSAndrew Boyer static void 382a677112dSAndrew Boyer iocpt_free_objs(struct iocpt_dev *dev) 383a677112dSAndrew Boyer { 384a677112dSAndrew Boyer IOCPT_PRINT_CALL(); 385a677112dSAndrew Boyer 386*2c1662bbSAndrew Boyer if (dev->adminq != NULL) { 387*2c1662bbSAndrew Boyer iocpt_adminq_free(dev->adminq); 388*2c1662bbSAndrew Boyer dev->adminq = NULL; 389*2c1662bbSAndrew Boyer } 390*2c1662bbSAndrew Boyer 391a677112dSAndrew Boyer if (dev->info != NULL) { 392a677112dSAndrew Boyer rte_memzone_free(dev->info_z); 393a677112dSAndrew Boyer dev->info_z = NULL; 394a677112dSAndrew Boyer dev->info = NULL; 395a677112dSAndrew Boyer dev->info_pa = 0; 396a677112dSAndrew Boyer } 397a677112dSAndrew Boyer } 398a677112dSAndrew Boyer 3994610ac93SAndrew Boyer static int 4004610ac93SAndrew Boyer iocpt_devargs(struct rte_devargs *devargs, struct iocpt_dev *dev) 4014610ac93SAndrew Boyer { 4024610ac93SAndrew Boyer RTE_SET_USED(devargs); 4034610ac93SAndrew Boyer RTE_SET_USED(dev); 4044610ac93SAndrew Boyer 4054610ac93SAndrew Boyer return 0; 4064610ac93SAndrew Boyer } 4074610ac93SAndrew Boyer 4084610ac93SAndrew Boyer int 4094610ac93SAndrew Boyer iocpt_probe(void *bus_dev, struct rte_device *rte_dev, 4104610ac93SAndrew Boyer struct iocpt_dev_bars *bars, const struct iocpt_dev_intf *intf, 4114610ac93SAndrew Boyer uint8_t driver_id, uint8_t socket_id) 4124610ac93SAndrew Boyer { 4134610ac93SAndrew Boyer struct rte_cryptodev_pmd_init_params init_params = { 4144610ac93SAndrew Boyer "iocpt", 4154610ac93SAndrew Boyer sizeof(struct iocpt_dev), 4164610ac93SAndrew Boyer socket_id, 4174610ac93SAndrew Boyer RTE_CRYPTODEV_PMD_DEFAULT_MAX_NB_QUEUE_PAIRS 4184610ac93SAndrew Boyer }; 4194610ac93SAndrew Boyer struct rte_cryptodev *cdev; 4204610ac93SAndrew Boyer struct iocpt_dev *dev; 42125c896eaSAndrew Boyer uint32_t i, sig; 4224610ac93SAndrew Boyer int err; 4234610ac93SAndrew Boyer 42425c896eaSAndrew Boyer /* Check structs (trigger error at compilation time) */ 42525c896eaSAndrew Boyer iocpt_struct_size_checks(); 42625c896eaSAndrew Boyer 4274610ac93SAndrew Boyer if (rte_eal_process_type() != RTE_PROC_PRIMARY) { 4284610ac93SAndrew Boyer IOCPT_PRINT(ERR, "Multi-process not supported"); 4294610ac93SAndrew Boyer err = -EPERM; 4304610ac93SAndrew Boyer goto err; 4314610ac93SAndrew Boyer } 4324610ac93SAndrew Boyer 4334610ac93SAndrew Boyer cdev = rte_cryptodev_pmd_create(rte_dev->name, rte_dev, &init_params); 4344610ac93SAndrew Boyer if (cdev == NULL) { 4354610ac93SAndrew Boyer IOCPT_PRINT(ERR, "Out of memory"); 4364610ac93SAndrew Boyer err = -ENOMEM; 4374610ac93SAndrew Boyer goto err; 4384610ac93SAndrew Boyer } 4394610ac93SAndrew Boyer 4404610ac93SAndrew Boyer dev = cdev->data->dev_private; 4414610ac93SAndrew Boyer dev->crypto_dev = cdev; 4424610ac93SAndrew Boyer dev->bus_dev = bus_dev; 4434610ac93SAndrew Boyer dev->intf = intf; 4444610ac93SAndrew Boyer dev->driver_id = driver_id; 4454610ac93SAndrew Boyer dev->socket_id = socket_id; 4464610ac93SAndrew Boyer 4474610ac93SAndrew Boyer for (i = 0; i < bars->num_bars; i++) { 4484610ac93SAndrew Boyer struct ionic_dev_bar *bar = &bars->bar[i]; 4494610ac93SAndrew Boyer 4504610ac93SAndrew Boyer IOCPT_PRINT(DEBUG, 4514610ac93SAndrew Boyer "bar[%u] = { .va = %p, .pa = %#jx, .len = %lu }", 4524610ac93SAndrew Boyer i, bar->vaddr, bar->bus_addr, bar->len); 4534610ac93SAndrew Boyer if (bar->vaddr == NULL) { 4544610ac93SAndrew Boyer IOCPT_PRINT(ERR, "Null bar found, aborting"); 4554610ac93SAndrew Boyer err = -EFAULT; 4564610ac93SAndrew Boyer goto err_destroy_crypto_dev; 4574610ac93SAndrew Boyer } 4584610ac93SAndrew Boyer 4594610ac93SAndrew Boyer dev->bars.bar[i].vaddr = bar->vaddr; 4604610ac93SAndrew Boyer dev->bars.bar[i].bus_addr = bar->bus_addr; 4614610ac93SAndrew Boyer dev->bars.bar[i].len = bar->len; 4624610ac93SAndrew Boyer } 4634610ac93SAndrew Boyer dev->bars.num_bars = bars->num_bars; 4644610ac93SAndrew Boyer 4654610ac93SAndrew Boyer err = iocpt_devargs(rte_dev->devargs, dev); 4664610ac93SAndrew Boyer if (err != 0) { 4674610ac93SAndrew Boyer IOCPT_PRINT(ERR, "Cannot parse device arguments"); 4684610ac93SAndrew Boyer goto err_destroy_crypto_dev; 4694610ac93SAndrew Boyer } 4704610ac93SAndrew Boyer 4714610ac93SAndrew Boyer err = iocpt_setup_bars(dev); 4724610ac93SAndrew Boyer if (err != 0) { 4734610ac93SAndrew Boyer IOCPT_PRINT(ERR, "Cannot setup BARs: %d, aborting", err); 4744610ac93SAndrew Boyer goto err_destroy_crypto_dev; 4754610ac93SAndrew Boyer } 4764610ac93SAndrew Boyer 47725c896eaSAndrew Boyer sig = ioread32(&dev->dev_info->signature); 47825c896eaSAndrew Boyer if (sig != IOCPT_DEV_INFO_SIGNATURE) { 47925c896eaSAndrew Boyer IOCPT_PRINT(ERR, "Incompatible firmware signature %#x", sig); 48025c896eaSAndrew Boyer err = -EFAULT; 48125c896eaSAndrew Boyer goto err_destroy_crypto_dev; 48225c896eaSAndrew Boyer } 48325c896eaSAndrew Boyer 48425c896eaSAndrew Boyer for (i = 0; i < IOCPT_FWVERS_BUFLEN; i++) 48525c896eaSAndrew Boyer dev->fw_version[i] = ioread8(&dev->dev_info->fw_version[i]); 48625c896eaSAndrew Boyer dev->fw_version[IOCPT_FWVERS_BUFLEN - 1] = '\0'; 48725c896eaSAndrew Boyer IOCPT_PRINT(DEBUG, "%s firmware: %s", dev->name, dev->fw_version); 48825c896eaSAndrew Boyer 489a677112dSAndrew Boyer err = iocpt_dev_identify(dev); 490a677112dSAndrew Boyer if (err != 0) { 491a677112dSAndrew Boyer IOCPT_PRINT(ERR, "Cannot identify device: %d, aborting", 492a677112dSAndrew Boyer err); 493a677112dSAndrew Boyer goto err_destroy_crypto_dev; 494a677112dSAndrew Boyer } 495a677112dSAndrew Boyer 496a677112dSAndrew Boyer err = iocpt_alloc_objs(dev); 497a677112dSAndrew Boyer if (err != 0) { 498a677112dSAndrew Boyer IOCPT_PRINT(ERR, "Cannot alloc device objects: %d", err); 499a677112dSAndrew Boyer goto err_destroy_crypto_dev; 500a677112dSAndrew Boyer } 501a677112dSAndrew Boyer 5024610ac93SAndrew Boyer err = iocpt_init(dev); 5034610ac93SAndrew Boyer if (err != 0) { 5044610ac93SAndrew Boyer IOCPT_PRINT(ERR, "Cannot init device: %d, aborting", err); 505a677112dSAndrew Boyer goto err_free_objs; 5064610ac93SAndrew Boyer } 5074610ac93SAndrew Boyer 5084610ac93SAndrew Boyer return 0; 5094610ac93SAndrew Boyer 510a677112dSAndrew Boyer err_free_objs: 511a677112dSAndrew Boyer iocpt_free_objs(dev); 5124610ac93SAndrew Boyer err_destroy_crypto_dev: 5134610ac93SAndrew Boyer rte_cryptodev_pmd_destroy(cdev); 5144610ac93SAndrew Boyer err: 5154610ac93SAndrew Boyer return err; 5164610ac93SAndrew Boyer } 5174610ac93SAndrew Boyer 5184610ac93SAndrew Boyer int 5194610ac93SAndrew Boyer iocpt_remove(struct rte_device *rte_dev) 5204610ac93SAndrew Boyer { 5214610ac93SAndrew Boyer struct rte_cryptodev *cdev; 5224610ac93SAndrew Boyer struct iocpt_dev *dev; 5234610ac93SAndrew Boyer 5244610ac93SAndrew Boyer cdev = rte_cryptodev_pmd_get_named_dev(rte_dev->name); 5254610ac93SAndrew Boyer if (cdev == NULL) { 5264610ac93SAndrew Boyer IOCPT_PRINT(DEBUG, "Cannot find device %s", rte_dev->name); 5274610ac93SAndrew Boyer return -ENODEV; 5284610ac93SAndrew Boyer } 5294610ac93SAndrew Boyer 5304610ac93SAndrew Boyer dev = cdev->data->dev_private; 5314610ac93SAndrew Boyer 5324610ac93SAndrew Boyer iocpt_deinit(dev); 5334610ac93SAndrew Boyer 534a677112dSAndrew Boyer iocpt_dev_reset(dev); 535a677112dSAndrew Boyer 536a677112dSAndrew Boyer iocpt_free_objs(dev); 537a677112dSAndrew Boyer 5384610ac93SAndrew Boyer rte_cryptodev_pmd_destroy(cdev); 5394610ac93SAndrew Boyer 5404610ac93SAndrew Boyer return 0; 5414610ac93SAndrew Boyer } 5424610ac93SAndrew Boyer 5434610ac93SAndrew Boyer RTE_LOG_REGISTER_DEFAULT(iocpt_logtype, NOTICE); 544