This defines the main device object routines and the vdev support code. The vdev code uses the common library.
Signed-off-by: Andrew Boyer <andrew.bo...@amd.com> --- drivers/crypto/ionic/ionic_crypto.h | 89 ++++ drivers/crypto/ionic/ionic_crypto_main.c | 538 +++++++++++++++++++++++ drivers/crypto/ionic/ionic_crypto_vdev.c | 128 ++++++ drivers/crypto/ionic/meson.build | 2 + 4 files changed, 757 insertions(+) create mode 100644 drivers/crypto/ionic/ionic_crypto_vdev.c diff --git a/drivers/crypto/ionic/ionic_crypto.h b/drivers/crypto/ionic/ionic_crypto.h index 958e611337..d048f7aa51 100644 --- a/drivers/crypto/ionic/ionic_crypto.h +++ b/drivers/crypto/ionic/ionic_crypto.h @@ -20,6 +20,11 @@ #include "ionic_crypto_if.h" #include "ionic_regs.h" +/* Devargs */ +/* NONE */ + +#define IOCPT_MAX_RING_DESC 32768 +#define IOCPT_MIN_RING_DESC 16 #define IOCPT_ADMINQ_LENGTH 16 /* must be a power of two */ #define IOCPT_CRYPTOQ_WAIT 10 /* 1s */ @@ -32,6 +37,64 @@ extern int iocpt_logtype; #define IOCPT_PRINT_CALL() IOCPT_PRINT(DEBUG, " >>") +static inline void iocpt_struct_size_checks(void) +{ + RTE_BUILD_BUG_ON(sizeof(struct ionic_doorbell) != 8); + RTE_BUILD_BUG_ON(sizeof(struct ionic_intr) != 32); + RTE_BUILD_BUG_ON(sizeof(struct ionic_intr_status) != 8); + + RTE_BUILD_BUG_ON(sizeof(union iocpt_dev_regs) != 4096); + RTE_BUILD_BUG_ON(sizeof(union iocpt_dev_info_regs) != 2048); + RTE_BUILD_BUG_ON(sizeof(union iocpt_dev_cmd_regs) != 2048); + + RTE_BUILD_BUG_ON(sizeof(struct iocpt_admin_cmd) != 64); + RTE_BUILD_BUG_ON(sizeof(struct iocpt_admin_comp) != 16); + RTE_BUILD_BUG_ON(sizeof(struct iocpt_nop_cmd) != 64); + RTE_BUILD_BUG_ON(sizeof(struct iocpt_nop_comp) != 16); + + /* Device commands */ + RTE_BUILD_BUG_ON(sizeof(struct iocpt_dev_identify_cmd) != 64); + RTE_BUILD_BUG_ON(sizeof(struct iocpt_dev_identify_comp) != 16); + RTE_BUILD_BUG_ON(sizeof(struct iocpt_dev_reset_cmd) != 64); + RTE_BUILD_BUG_ON(sizeof(struct iocpt_dev_reset_comp) != 16); + + /* LIF commands */ + RTE_BUILD_BUG_ON(sizeof(struct iocpt_lif_identify_cmd) != 64); + RTE_BUILD_BUG_ON(sizeof(struct iocpt_lif_identify_comp) != 16); + RTE_BUILD_BUG_ON(sizeof(struct iocpt_lif_init_cmd) != 64); + RTE_BUILD_BUG_ON(sizeof(struct iocpt_lif_init_comp) != 16); + RTE_BUILD_BUG_ON(sizeof(struct iocpt_lif_reset_cmd) != 64); + RTE_BUILD_BUG_ON(sizeof(struct iocpt_lif_getattr_cmd) != 64); + RTE_BUILD_BUG_ON(sizeof(struct iocpt_lif_getattr_comp) != 16); + RTE_BUILD_BUG_ON(sizeof(struct iocpt_lif_setattr_cmd) != 64); + RTE_BUILD_BUG_ON(sizeof(struct iocpt_lif_setattr_comp) != 16); + + /* Queue commands */ + RTE_BUILD_BUG_ON(sizeof(struct iocpt_q_identify_cmd) != 64); + RTE_BUILD_BUG_ON(sizeof(struct iocpt_q_identify_comp) != 16); + RTE_BUILD_BUG_ON(sizeof(struct iocpt_q_init_cmd) != 64); + RTE_BUILD_BUG_ON(sizeof(struct iocpt_q_init_comp) != 16); + RTE_BUILD_BUG_ON(sizeof(struct iocpt_q_control_cmd) != 64); + + /* Crypto */ + RTE_BUILD_BUG_ON(sizeof(struct iocpt_crypto_desc) != 32); + RTE_BUILD_BUG_ON(sizeof(struct iocpt_crypto_sg_desc) != 256); + RTE_BUILD_BUG_ON(sizeof(struct iocpt_crypto_comp) != 16); +} + +struct iocpt_dev_bars { + struct ionic_dev_bar bar[IONIC_BARS_MAX]; + uint32_t num_bars; +}; + +/* Queue watchdog */ +#define IOCPT_Q_WDOG_SESS_IDX 0 +#define IOCPT_Q_WDOG_KEY_LEN 16 +#define IOCPT_Q_WDOG_IV_LEN 12 +#define IOCPT_Q_WDOG_PLD_LEN 4 +#define IOCPT_Q_WDOG_TAG_LEN 16 +#define IOCPT_Q_WDOG_OP_TYPE RTE_CRYPTO_OP_TYPE_UNDEFINED + struct iocpt_qtype_info { uint8_t version; uint8_t supported; @@ -108,8 +171,10 @@ struct iocpt_admin_q { struct iocpt_dev { const char *name; char fw_version[IOCPT_FWVERS_BUFLEN]; + struct iocpt_dev_bars bars; struct iocpt_identity ident; + const struct iocpt_dev_intf *intf; void *bus_dev; struct rte_cryptodev *crypto_dev; @@ -130,6 +195,8 @@ struct iocpt_dev { struct iocpt_admin_q *adminq; + struct rte_bitmap *sess_bm; /* SET bit indicates index is free */ + uint64_t features; uint32_t hw_features; @@ -144,6 +211,20 @@ struct iocpt_dev { struct rte_cryptodev_stats stats_base; }; +struct iocpt_dev_intf { + int (*setup_bars)(struct iocpt_dev *dev); + void (*unmap_bars)(struct iocpt_dev *dev); +}; + +static inline int +iocpt_setup_bars(struct iocpt_dev *dev) +{ + if (dev->intf->setup_bars == NULL) + return -EINVAL; + + return (*dev->intf->setup_bars)(dev); +} + /** iocpt_admin_ctx - Admin command context. * @pending_work: Flag that indicates a completion. * @cmd: Admin command (64B) to be copied to the queue. @@ -155,6 +236,14 @@ struct iocpt_admin_ctx { union iocpt_adminq_comp comp; }; +int iocpt_probe(void *bus_dev, struct rte_device *rte_dev, + struct iocpt_dev_bars *bars, const struct iocpt_dev_intf *intf, + uint8_t driver_id, uint8_t socket_id); +int iocpt_remove(struct rte_device *rte_dev); + +void iocpt_configure(struct iocpt_dev *dev); +void iocpt_deinit(struct iocpt_dev *dev); + int iocpt_dev_identify(struct iocpt_dev *dev); int iocpt_dev_init(struct iocpt_dev *dev, rte_iova_t info_pa); int iocpt_dev_adminq_init(struct iocpt_dev *dev); diff --git a/drivers/crypto/ionic/ionic_crypto_main.c b/drivers/crypto/ionic/ionic_crypto_main.c index 7b26080bd1..84aff65f22 100644 --- a/drivers/crypto/ionic/ionic_crypto_main.c +++ b/drivers/crypto/ionic/ionic_crypto_main.c @@ -12,6 +12,32 @@ int iocpt_logtype; +static int +iocpt_cq_init(struct iocpt_cq *cq, uint16_t num_descs) +{ + if (!rte_is_power_of_2(num_descs) || + num_descs < IOCPT_MIN_RING_DESC || + num_descs > IOCPT_MAX_RING_DESC) { + IOCPT_PRINT(ERR, "%u descriptors (min: %u max: %u)", + num_descs, IOCPT_MIN_RING_DESC, IOCPT_MAX_RING_DESC); + return -EINVAL; + } + + cq->num_descs = num_descs; + cq->size_mask = num_descs - 1; + cq->tail_idx = 0; + cq->done_color = 1; + + return 0; +} + +static void +iocpt_cq_map(struct iocpt_cq *cq, void *base, rte_iova_t base_pa) +{ + cq->base = base; + cq->base_pa = base_pa; +} + uint32_t iocpt_cq_service(struct iocpt_cq *cq, uint32_t work_to_do, iocpt_cq_cb cb, void *cb_arg) @@ -33,10 +59,522 @@ iocpt_cq_service(struct iocpt_cq *cq, uint32_t work_to_do, return work_done; } +static int +iocpt_q_init(struct iocpt_queue *q, uint8_t type, uint32_t index, + uint16_t num_descs, uint16_t num_segs, uint32_t socket_id) +{ + uint32_t ring_size; + + if (!rte_is_power_of_2(num_descs)) + return -EINVAL; + + ring_size = rte_log2_u32(num_descs); + if (ring_size < 2 || ring_size > 16) + return -EINVAL; + + q->type = type; + q->index = index; + q->num_descs = num_descs; + q->num_segs = num_segs; + q->size_mask = num_descs - 1; + q->head_idx = 0; + q->tail_idx = 0; + + q->info = rte_calloc_socket("iocpt", + num_descs * num_segs, sizeof(void *), + rte_mem_page_size(), socket_id); + if (q->info == NULL) { + IOCPT_PRINT(ERR, "Cannot allocate queue info"); + return -ENOMEM; + } + + return 0; +} + +static void +iocpt_q_map(struct iocpt_queue *q, void *base, rte_iova_t base_pa) +{ + q->base = base; + q->base_pa = base_pa; +} + +static void +iocpt_q_sg_map(struct iocpt_queue *q, void *base, rte_iova_t base_pa) +{ + q->sg_base = base; + q->sg_base_pa = base_pa; +} + +static void +iocpt_q_free(struct iocpt_queue *q) +{ + if (q->info != NULL) { + rte_free(q->info); + q->info = NULL; + } +} + +static const struct rte_memzone * +iocpt_dma_zone_reserve(const char *type_name, uint16_t qid, size_t size, + unsigned int align, int socket_id) +{ + char zone_name[RTE_MEMZONE_NAMESIZE]; + const struct rte_memzone *mz; + int err; + + err = snprintf(zone_name, sizeof(zone_name), + "iocpt_%s_%u", type_name, qid); + if (err >= RTE_MEMZONE_NAMESIZE) { + IOCPT_PRINT(ERR, "Name %s too long", type_name); + return NULL; + } + + mz = rte_memzone_lookup(zone_name); + if (mz != NULL) + return mz; + + return rte_memzone_reserve_aligned(zone_name, size, socket_id, + RTE_MEMZONE_IOVA_CONTIG, align); +} + +static int +iocpt_commonq_alloc(struct iocpt_dev *dev, + uint8_t type, + size_t struct_size, + uint32_t socket_id, + uint32_t index, + const char *type_name, + uint16_t flags, + uint16_t num_descs, + uint16_t num_segs, + uint16_t desc_size, + uint16_t cq_desc_size, + uint16_t sg_desc_size, + struct iocpt_common_q **comq) +{ + struct iocpt_common_q *new; + uint32_t q_size, cq_size, sg_size, total_size; + void *q_base, *cq_base, *sg_base; + rte_iova_t q_base_pa = 0; + rte_iova_t cq_base_pa = 0; + rte_iova_t sg_base_pa = 0; + size_t page_size = rte_mem_page_size(); + int err; + + *comq = NULL; + + q_size = num_descs * desc_size; + cq_size = num_descs * cq_desc_size; + sg_size = num_descs * sg_desc_size; + + /* + * Note: aligning q_size/cq_size is not enough due to cq_base address + * aligning as q_base could be not aligned to the page. + * Adding page_size. + */ + total_size = RTE_ALIGN(q_size, page_size) + + RTE_ALIGN(cq_size, page_size) + page_size; + if (flags & IOCPT_Q_F_SG) + total_size += RTE_ALIGN(sg_size, page_size) + page_size; + + new = rte_zmalloc_socket("iocpt", struct_size, + RTE_CACHE_LINE_SIZE, socket_id); + if (new == NULL) { + IOCPT_PRINT(ERR, "Cannot allocate queue structure"); + return -ENOMEM; + } + + new->dev = dev; + + err = iocpt_q_init(&new->q, type, index, num_descs, num_segs, + socket_id); + if (err != 0) { + IOCPT_PRINT(ERR, "Queue initialization failed"); + goto err_free_q; + } + + err = iocpt_cq_init(&new->cq, num_descs); + if (err != 0) { + IOCPT_PRINT(ERR, "Completion queue initialization failed"); + goto err_deinit_q; + } + + new->base_z = iocpt_dma_zone_reserve(type_name, index, total_size, + IONIC_ALIGN, socket_id); + if (new->base_z == NULL) { + IOCPT_PRINT(ERR, "Cannot reserve queue DMA memory"); + err = -ENOMEM; + goto err_deinit_cq; + } + + new->base = new->base_z->addr; + new->base_pa = new->base_z->iova; + + q_base = new->base; + q_base_pa = new->base_pa; + iocpt_q_map(&new->q, q_base, q_base_pa); + + cq_base = (void *)RTE_ALIGN((uintptr_t)q_base + q_size, page_size); + cq_base_pa = RTE_ALIGN(q_base_pa + q_size, page_size); + iocpt_cq_map(&new->cq, cq_base, cq_base_pa); + + if (flags & IOCPT_Q_F_SG) { + sg_base = (void *)RTE_ALIGN((uintptr_t)cq_base + cq_size, + page_size); + sg_base_pa = RTE_ALIGN(cq_base_pa + cq_size, page_size); + iocpt_q_sg_map(&new->q, sg_base, sg_base_pa); + } + + IOCPT_PRINT(DEBUG, "q_base_pa %#jx cq_base_pa %#jx sg_base_pa %#jx", + q_base_pa, cq_base_pa, sg_base_pa); + + *comq = new; + + return 0; + +err_deinit_cq: +err_deinit_q: + iocpt_q_free(&new->q); +err_free_q: + rte_free(new); + return err; +} + struct ionic_doorbell * iocpt_db_map(struct iocpt_dev *dev, struct iocpt_queue *q) { return dev->db_pages + q->hw_type; } +static int +iocpt_adminq_alloc(struct iocpt_dev *dev) +{ + struct iocpt_admin_q *aq; + uint16_t num_descs = IOCPT_ADMINQ_LENGTH; + uint16_t flags = 0; + int err; + + err = iocpt_commonq_alloc(dev, + IOCPT_QTYPE_ADMINQ, + sizeof(struct iocpt_admin_q), + rte_socket_id(), + 0, + "admin", + flags, + num_descs, + 1, + sizeof(struct iocpt_admin_cmd), + sizeof(struct iocpt_admin_comp), + 0, + (struct iocpt_common_q **)&aq); + if (err != 0) + return err; + + aq->flags = flags; + + dev->adminq = aq; + + return 0; +} + +static int +iocpt_adminq_init(struct iocpt_dev *dev) +{ + return iocpt_dev_adminq_init(dev); +} + +static void +iocpt_adminq_deinit(struct iocpt_dev *dev) +{ + dev->adminq->flags &= ~IOCPT_Q_F_INITED; +} + +static void +iocpt_adminq_free(struct iocpt_admin_q *aq) +{ + if (aq->base_z != NULL) { + rte_memzone_free(aq->base_z); + aq->base_z = NULL; + aq->base = NULL; + aq->base_pa = 0; + } + + iocpt_q_free(&aq->q); + + rte_free(aq); +} + +static int +iocpt_alloc_objs(struct iocpt_dev *dev) +{ + uint32_t bmsize, i; + uint8_t *bm; + int err; + + IOCPT_PRINT(DEBUG, "Crypto: %s", dev->name); + + rte_spinlock_init(&dev->adminq_lock); + rte_spinlock_init(&dev->adminq_service_lock); + + err = iocpt_adminq_alloc(dev); + if (err != 0) { + IOCPT_PRINT(ERR, "Cannot allocate admin queue"); + err = -ENOMEM; + goto err_out; + } + + dev->info_sz = RTE_ALIGN(sizeof(*dev->info), rte_mem_page_size()); + dev->info_z = iocpt_dma_zone_reserve("info", 0, dev->info_sz, + IONIC_ALIGN, dev->socket_id); + if (dev->info_z == NULL) { + IOCPT_PRINT(ERR, "Cannot allocate dev info memory"); + err = -ENOMEM; + goto err_free_adminq; + } + + dev->info = dev->info_z->addr; + dev->info_pa = dev->info_z->iova; + + bmsize = rte_bitmap_get_memory_footprint(dev->max_sessions); + bm = rte_malloc_socket("iocpt", bmsize, + RTE_CACHE_LINE_SIZE, dev->socket_id); + if (bm == NULL) { + IOCPT_PRINT(ERR, "Cannot allocate %uB bitmap memory", bmsize); + err = -ENOMEM; + goto err_free_dmazone; + } + + dev->sess_bm = rte_bitmap_init(dev->max_sessions, bm, bmsize); + if (dev->sess_bm == NULL) { + IOCPT_PRINT(ERR, "Cannot initialize bitmap"); + err = -EFAULT; + goto err_free_bm; + } + for (i = 0; i < dev->max_sessions; i++) + rte_bitmap_set(dev->sess_bm, i); + + return 0; + +err_free_bm: + rte_free(bm); +err_free_dmazone: + rte_memzone_free(dev->info_z); + dev->info_z = NULL; + dev->info = NULL; + dev->info_pa = 0; +err_free_adminq: + iocpt_adminq_free(dev->adminq); + dev->adminq = NULL; +err_out: + return err; +} + +static int +iocpt_init(struct iocpt_dev *dev) +{ + int err; + + memset(&dev->stats_base, 0, sizeof(dev->stats_base)); + + /* Uses dev_cmds */ + err = iocpt_dev_init(dev, dev->info_pa); + if (err != 0) + return err; + + err = iocpt_adminq_init(dev); + if (err != 0) + return err; + + dev->state |= IOCPT_DEV_F_INITED; + + return 0; +} + +void +iocpt_configure(struct iocpt_dev *dev) +{ + RTE_SET_USED(dev); +} + +void +iocpt_deinit(struct iocpt_dev *dev) +{ + IOCPT_PRINT_CALL(); + + if (!(dev->state & IOCPT_DEV_F_INITED)) + return; + + iocpt_adminq_deinit(dev); + + dev->state &= ~IOCPT_DEV_F_INITED; +} + +static void +iocpt_free_objs(struct iocpt_dev *dev) +{ + IOCPT_PRINT_CALL(); + + if (dev->sess_bm != NULL) { + rte_bitmap_free(dev->sess_bm); + rte_free(dev->sess_bm); + dev->sess_bm = NULL; + } + + if (dev->adminq != NULL) { + iocpt_adminq_free(dev->adminq); + dev->adminq = NULL; + } + + if (dev->info != NULL) { + rte_memzone_free(dev->info_z); + dev->info_z = NULL; + dev->info = NULL; + dev->info_pa = 0; + } +} + +static int +iocpt_devargs(struct rte_devargs *devargs, struct iocpt_dev *dev) +{ + RTE_SET_USED(devargs); + RTE_SET_USED(dev); + + return 0; +} + +int +iocpt_probe(void *bus_dev, struct rte_device *rte_dev, + struct iocpt_dev_bars *bars, const struct iocpt_dev_intf *intf, + uint8_t driver_id, uint8_t socket_id) +{ + struct rte_cryptodev_pmd_init_params init_params = { + "iocpt", + sizeof(struct iocpt_dev), + socket_id, + RTE_CRYPTODEV_PMD_DEFAULT_MAX_NB_QUEUE_PAIRS + }; + struct rte_cryptodev *cdev; + struct iocpt_dev *dev; + uint32_t i, sig; + int err; + + /* Check structs (trigger error at compilation time) */ + iocpt_struct_size_checks(); + + /* Multi-process not supported */ + if (rte_eal_process_type() != RTE_PROC_PRIMARY) { + err = -EPERM; + goto err; + } + + cdev = rte_cryptodev_pmd_create(rte_dev->name, rte_dev, &init_params); + if (cdev == NULL) { + IOCPT_PRINT(ERR, "OOM"); + err = -ENOMEM; + goto err; + } + + dev = cdev->data->dev_private; + dev->crypto_dev = cdev; + dev->bus_dev = bus_dev; + dev->intf = intf; + dev->driver_id = driver_id; + dev->socket_id = socket_id; + + for (i = 0; i < bars->num_bars; i++) { + struct ionic_dev_bar *bar = &bars->bar[i]; + + IOCPT_PRINT(DEBUG, + "bar[%u] = { .va = %p, .pa = %#jx, .len = %lu }", + i, bar->vaddr, bar->bus_addr, bar->len); + if (bar->vaddr == NULL) { + IOCPT_PRINT(ERR, "Null bar found, aborting"); + err = -EFAULT; + goto err_destroy_crypto_dev; + } + + dev->bars.bar[i].vaddr = bar->vaddr; + dev->bars.bar[i].bus_addr = bar->bus_addr; + dev->bars.bar[i].len = bar->len; + } + dev->bars.num_bars = bars->num_bars; + + err = iocpt_devargs(rte_dev->devargs, dev); + if (err != 0) { + IOCPT_PRINT(ERR, "Cannot parse device arguments"); + goto err_destroy_crypto_dev; + } + + err = iocpt_setup_bars(dev); + if (err != 0) { + IOCPT_PRINT(ERR, "Cannot setup BARs: %d, aborting", err); + goto err_destroy_crypto_dev; + } + + sig = ioread32(&dev->dev_info->signature); + if (sig != IOCPT_DEV_INFO_SIGNATURE) { + IOCPT_PRINT(ERR, "Incompatible firmware signature %#x", sig); + err = -EFAULT; + goto err_destroy_crypto_dev; + } + + for (i = 0; i < IOCPT_FWVERS_BUFLEN; i++) + dev->fw_version[i] = ioread8(&dev->dev_info->fw_version[i]); + dev->fw_version[IOCPT_FWVERS_BUFLEN - 1] = '\0'; + IOCPT_PRINT(DEBUG, "%s firmware: %s", dev->name, dev->fw_version); + + err = iocpt_dev_identify(dev); + if (err != 0) { + IOCPT_PRINT(ERR, "Cannot identify device: %d, aborting", + err); + goto err_destroy_crypto_dev; + } + + err = iocpt_alloc_objs(dev); + if (err != 0) { + IOCPT_PRINT(ERR, "Cannot alloc device objects: %d", err); + goto err_destroy_crypto_dev; + } + + err = iocpt_init(dev); + if (err != 0) { + IOCPT_PRINT(ERR, "Cannot init device: %d, aborting", err); + goto err_free_objs; + } + + return 0; + +err_free_objs: + iocpt_free_objs(dev); +err_destroy_crypto_dev: + rte_cryptodev_pmd_destroy(cdev); +err: + return err; +} + +int +iocpt_remove(struct rte_device *rte_dev) +{ + struct rte_cryptodev *cdev; + struct iocpt_dev *dev; + + cdev = rte_cryptodev_pmd_get_named_dev(rte_dev->name); + if (cdev == NULL) { + IOCPT_PRINT(DEBUG, "Cannot find device %s", rte_dev->name); + return -ENODEV; + } + + dev = cdev->data->dev_private; + + iocpt_deinit(dev); + + iocpt_dev_reset(dev); + + iocpt_free_objs(dev); + + rte_cryptodev_pmd_destroy(cdev); + + return 0; +} + RTE_LOG_REGISTER_DEFAULT(iocpt_logtype, NOTICE); diff --git a/drivers/crypto/ionic/ionic_crypto_vdev.c b/drivers/crypto/ionic/ionic_crypto_vdev.c new file mode 100644 index 0000000000..d15acf660a --- /dev/null +++ b/drivers/crypto/ionic/ionic_crypto_vdev.c @@ -0,0 +1,128 @@ +/* SPDX-License-Identifier: BSD-3-Clause + * Copyright 2021-2024 Advanced Micro Devices, Inc. + */ + +#include <stdint.h> +#include <errno.h> + +#include <rte_errno.h> +#include <rte_common.h> +#include <rte_log.h> +#include <rte_eal.h> +#include <bus_vdev_driver.h> +#include <rte_dev.h> +#include <rte_string_fns.h> + +#include "ionic_crypto.h" + +#define IOCPT_VDEV_DEV_BAR 0 +#define IOCPT_VDEV_INTR_CTL_BAR 1 +#define IOCPT_VDEV_INTR_CFG_BAR 2 +#define IOCPT_VDEV_DB_BAR 3 +#define IOCPT_VDEV_BARS_MAX 4 + +#define IOCPT_VDEV_DEV_INFO_REGS_OFFSET 0x0000 +#define IOCPT_VDEV_DEV_CMD_REGS_OFFSET 0x0800 + +#define IOCPT_VDEV_FW_WAIT_US 1000 /* 1ms */ +#define IOCPT_VDEV_FW_WAIT_MAX 5000 /* 5s */ + +static int +iocpt_vdev_setup_bars(struct iocpt_dev *dev) +{ + struct iocpt_dev_bars *bars = &dev->bars; + uint8_t *bar0_base; + uint32_t fw_waits = 0; + uint8_t fw; + + IOCPT_PRINT_CALL(); + + /* BAR0: dev_cmd */ + bar0_base = bars->bar[IOCPT_VDEV_DEV_BAR].vaddr; + dev->dev_info = (union iocpt_dev_info_regs *) + &bar0_base[IOCPT_VDEV_DEV_INFO_REGS_OFFSET]; + dev->dev_cmd = (union iocpt_dev_cmd_regs *) + &bar0_base[IOCPT_VDEV_DEV_CMD_REGS_OFFSET]; + + /* BAR1: interrupts */ + dev->intr_ctrl = (void *)bars->bar[IOCPT_VDEV_INTR_CTL_BAR].vaddr; + + /* BAR3: doorbells */ + dev->db_pages = (void *)bars->bar[IOCPT_VDEV_DB_BAR].vaddr; + + /* Wait for the FW to indicate readiness */ + while (1) { + fw = ioread8(&dev->dev_info->fw_status); + if ((fw & IOCPT_FW_STS_F_RUNNING) != 0) + break; + + if (fw_waits > IOCPT_VDEV_FW_WAIT_MAX) { + IOCPT_PRINT(ERR, "Firmware readiness bit not set"); + return -ETIMEDOUT; + } + + fw_waits++; + rte_delay_us_block(IOCPT_VDEV_FW_WAIT_US); + } + IOCPT_PRINT(DEBUG, "Firmware ready (%u waits)", fw_waits); + + dev->name = rte_vdev_device_name(dev->bus_dev); + + return 0; +} + +static void +iocpt_vdev_unmap_bars(struct iocpt_dev *dev) +{ + struct iocpt_dev_bars *bars = &dev->bars; + uint32_t i; + + for (i = 0; i < IOCPT_VDEV_BARS_MAX; i++) + ionic_uio_rel_rsrc(dev->name, i, &bars->bar[i]); +} + +static uint8_t iocpt_vdev_driver_id; +static const struct iocpt_dev_intf iocpt_vdev_intf = { + .setup_bars = iocpt_vdev_setup_bars, + .unmap_bars = iocpt_vdev_unmap_bars, +}; + +static int +iocpt_vdev_probe(struct rte_vdev_device *vdev) +{ + struct iocpt_dev_bars bars = {}; + const char *name = rte_vdev_device_name(vdev); + unsigned int i; + + IOCPT_PRINT(NOTICE, "Initializing device %s%s", name, + rte_eal_process_type() == RTE_PROC_SECONDARY ? + " [SECONDARY]" : ""); + + ionic_uio_scan_mcrypt_devices(); + + for (i = 0; i < IOCPT_VDEV_BARS_MAX; i++) + ionic_uio_get_rsrc(name, i, &bars.bar[i]); + + bars.num_bars = IOCPT_VDEV_BARS_MAX; + + return iocpt_probe((void *)vdev, &vdev->device, + &bars, &iocpt_vdev_intf, + iocpt_vdev_driver_id, rte_socket_id()); +} + +static int +iocpt_vdev_remove(struct rte_vdev_device *vdev) +{ + return iocpt_remove(&vdev->device); +} + +static struct rte_vdev_driver rte_vdev_iocpt_pmd = { + .probe = iocpt_vdev_probe, + .remove = iocpt_vdev_remove, +}; + +static struct cryptodev_driver rte_vdev_iocpt_drv; + +RTE_PMD_REGISTER_VDEV(crypto_ionic, rte_vdev_iocpt_pmd); +RTE_PMD_REGISTER_CRYPTO_DRIVER(rte_vdev_iocpt_drv, rte_vdev_iocpt_pmd.driver, + iocpt_vdev_driver_id); diff --git a/drivers/crypto/ionic/meson.build b/drivers/crypto/ionic/meson.build index 6eaef41196..a6e0a1d415 100644 --- a/drivers/crypto/ionic/meson.build +++ b/drivers/crypto/ionic/meson.build @@ -1,11 +1,13 @@ # SPDX-License-Identifier: BSD-3-Clause # Copyright 2021-2024 Advanced Micro Devices, Inc. +deps += ['bus_vdev'] deps += ['common_ionic'] sources = files( 'ionic_crypto_cmds.c', 'ionic_crypto_main.c', + 'ionic_crypto_vdev.c', ) name = 'ionic_crypto' -- 2.17.1