These definitions are shared between the PMD and firmware.
Teach the device to read the FW version and check for liveness.

Signed-off-by: Andrew Boyer <andrew.bo...@amd.com>
---
 drivers/crypto/ionic/ionic_crypto.h      |   53 ++
 drivers/crypto/ionic/ionic_crypto_if.h   | 1021 ++++++++++++++++++++++
 drivers/crypto/ionic/ionic_crypto_main.c |   17 +-
 drivers/crypto/ionic/ionic_crypto_vdev.c |   37 +
 4 files changed, 1127 insertions(+), 1 deletion(-)
 create mode 100644 drivers/crypto/ionic/ionic_crypto_if.h

diff --git a/drivers/crypto/ionic/ionic_crypto.h 
b/drivers/crypto/ionic/ionic_crypto.h
index 86750f0cbd..7f456b5154 100644
--- a/drivers/crypto/ionic/ionic_crypto.h
+++ b/drivers/crypto/ionic/ionic_crypto.h
@@ -16,6 +16,7 @@
 #include <rte_log.h>
 
 #include "ionic_common.h"
+#include "ionic_crypto_if.h"
 #include "ionic_regs.h"
 
 /* Devargs */
@@ -29,6 +30,51 @@ 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;
@@ -41,12 +87,19 @@ struct iocpt_dev_bars {
 /* Combined dev / LIF object */
 struct iocpt_dev {
        const char *name;
+       char fw_version[IOCPT_FWVERS_BUFLEN];
        struct iocpt_dev_bars bars;
 
        const struct iocpt_dev_intf *intf;
        void *bus_dev;
        struct rte_cryptodev *crypto_dev;
 
+       union iocpt_dev_info_regs __iomem *dev_info;
+       union iocpt_dev_cmd_regs __iomem *dev_cmd;
+
+       struct ionic_doorbell __iomem *db_pages;
+       struct ionic_intr __iomem *intr_ctrl;
+
        uint32_t max_qps;
        uint32_t max_sessions;
        uint16_t state;
diff --git a/drivers/crypto/ionic/ionic_crypto_if.h 
b/drivers/crypto/ionic/ionic_crypto_if.h
new file mode 100644
index 0000000000..ea418f3d4b
--- /dev/null
+++ b/drivers/crypto/ionic/ionic_crypto_if.h
@@ -0,0 +1,1021 @@
+/* SPDX-License-Identifier: BSD-3-Clause
+ * Copyright 2021-2024 Advanced Micro Devices, Inc.
+ */
+
+#ifndef _IONIC_CRYPTO_IF_H_
+#define _IONIC_CRYPTO_IF_H_
+
+#define IOCPT_DEV_INFO_SIGNATURE               0x43585660      /* 'CRPT' */
+#define IOCPT_DEV_INFO_VERSION                 1
+#define IOCPT_IFNAMSIZ                         16
+
+/**
+ * enum iocpt_cmd_opcode - Device commands
+ */
+enum iocpt_cmd_opcode {
+       IOCPT_CMD_NOP                           = 0,    /* D, A */
+
+       /* Device commands */
+       IOCPT_CMD_IDENTIFY                      = 1,    /* D */
+       IOCPT_CMD_RESET                         = 3,    /* D */
+
+       /* LIF commands */
+       IOCPT_CMD_LIF_IDENTIFY                  = 20,   /* D */
+       IOCPT_CMD_LIF_INIT                      = 21,   /* D */
+       IOCPT_CMD_LIF_RESET                     = 22,   /* D */
+       IOCPT_CMD_LIF_GETATTR                   = 23,   /* D, A */
+       IOCPT_CMD_LIF_SETATTR                   = 24,   /* D, A */
+
+       /* Queue commands */
+       IOCPT_CMD_Q_IDENTIFY                    = 39,   /* D, A */
+       IOCPT_CMD_Q_INIT                        = 40,   /* D, A */
+       IOCPT_CMD_Q_CONTROL                     = 41,   /* D, A */
+
+       /* Session commands */
+       IOCPT_CMD_SESS_CONTROL                  = 45,   /* D, A */
+};
+
+/**
+ * enum iocpt_status_code - Device command return codes
+ */
+enum iocpt_status_code {
+       IOCPT_RC_SUCCESS        = 0,    /* Success */
+       IOCPT_RC_EVERSION       = 1,    /* Incorrect version for request */
+       IOCPT_RC_EOPCODE        = 2,    /* Invalid cmd opcode */
+       IOCPT_RC_EIO            = 3,    /* I/O error */
+       IOCPT_RC_EPERM          = 4,    /* Permission denied */
+       IOCPT_RC_EQID           = 5,    /* Bad qid */
+       IOCPT_RC_EQTYPE         = 6,    /* Bad qtype */
+       IOCPT_RC_ENOENT         = 7,    /* No such element */
+       IOCPT_RC_EINTR          = 8,    /* Operation interrupted */
+       IOCPT_RC_EAGAIN         = 9,    /* Try again */
+       IOCPT_RC_ENOMEM         = 10,   /* Out of memory */
+       IOCPT_RC_EFAULT         = 11,   /* Bad address */
+       IOCPT_RC_EBUSY          = 12,   /* Device or resource busy */
+       IOCPT_RC_EEXIST         = 13,   /* Object already exists */
+       IOCPT_RC_EINVAL         = 14,   /* Invalid argument */
+       IOCPT_RC_ENOSPC         = 15,   /* No space left or alloc failure */
+       IOCPT_RC_ERANGE         = 16,   /* Parameter out of range */
+       IOCPT_RC_BAD_ADDR       = 17,   /* Descriptor contains a bad ptr */
+       IOCPT_RC_DEV_CMD        = 18,   /* Device cmd attempted on AdminQ */
+       IOCPT_RC_ENOSUPP        = 19,   /* Operation not supported */
+       IOCPT_RC_ERROR          = 29,   /* Generic error */
+};
+
+enum iocpt_notifyq_opcode {
+       IOCPT_EVENT_RESET               = 1,
+       IOCPT_EVENT_HEARTBEAT           = 2,
+       IOCPT_EVENT_LOG                 = 3,
+};
+
+enum iocpt_lif_type {
+       IOCPT_LIF_TYPE_DEFAULT = 0,
+};
+
+/**
+ * struct iocpt_admin_cmd - General admin command format
+ * @opcode:    Opcode for the command
+ * @lif_index: LIF index
+ * @cmd_data:  Opcode-specific command bytes
+ */
+struct iocpt_admin_cmd {
+       u8     opcode;
+       u8     rsvd;
+       __le16 lif_index;
+       u8     cmd_data[60];
+};
+
+/**
+ * struct iocpt_admin_comp - General admin command completion format
+ * @status:     Status of the command (enum iocpt_status_code)
+ * @comp_index: Index in the descriptor ring for which this is the completion
+ * @cmd_data:   Command-specific bytes
+ * @color:      Color bit (Always 0 for commands issued to the
+ *              Device Cmd Registers)
+ */
+struct iocpt_admin_comp {
+       u8     status;
+       u8     rsvd;
+       __le16 comp_index;
+       u8     cmd_data[11];
+       u8     color;
+#define IOCPT_COMP_COLOR_MASK  0x80
+};
+
+static inline u8 iocpt_color_match(u8 color, u8 done_color)
+{
+       return (!!(color & IOCPT_COMP_COLOR_MASK)) == done_color;
+}
+
+/**
+ * struct iocpt_nop_cmd - NOP command
+ * @opcode:    Opcode
+ */
+struct iocpt_nop_cmd {
+       u8     opcode;
+       u8     rsvd[63];
+};
+
+/**
+ * struct iocpt_nop_comp - NOP command completion
+ * @status:    Status of the command (enum iocpt_status_code)
+ */
+struct iocpt_nop_comp {
+       u8     status;
+       u8     rsvd[15];
+};
+
+#define IOCPT_IDENTITY_VERSION_1       1
+
+/**
+ * struct iocpt_dev_identify_cmd - Driver/device identify command
+ * @opcode:    Opcode
+ * @ver:       Highest version of identify supported by driver
+ */
+struct iocpt_dev_identify_cmd {
+       u8     opcode;
+       u8     ver;
+       u8     rsvd[62];
+};
+
+/**
+ * struct iocpt_dev_identify_comp - Device identify command completion
+ * @status:    Status of the command (enum iocpt_status_code)
+ * @ver:       Version of identify returned by device
+ */
+struct iocpt_dev_identify_comp {
+       u8     status;
+       u8     ver;
+       u8     rsvd[14];
+};
+
+/**
+ * struct iocpt_dev_reset_cmd - Device reset command
+ * Will reset all LIFs on the device.
+ * @opcode:    Opcode
+ */
+struct iocpt_dev_reset_cmd {
+       u8     opcode;
+       u8     rsvd[63];
+};
+
+/**
+ * struct iocpt_dev_reset_comp - Reset command completion
+ * @status:    Status of the command (enum iocpt_status_code)
+ */
+struct iocpt_dev_reset_comp {
+       u8     status;
+       u8     rsvd[15];
+};
+
+/**
+ * struct iocpt_lif_identify_cmd - LIF identify command
+ * @opcode:    Opcode
+ * @type:      LIF type (enum iocpt_lif_type)
+ * @lif_index: LIF index
+ * @ver:       Version of identify returned by device
+ */
+struct iocpt_lif_identify_cmd {
+       u8     opcode;
+       u8     type;
+       __le16 lif_index;
+       u8     ver;
+       u8     rsvd[59];
+};
+
+/**
+ * struct iocpt_lif_identify_comp - LIF identify command completion
+ * @status:  Status of the command (enum iocpt_status_code)
+ * @ver:     Version of identify returned by device
+ */
+struct iocpt_lif_identify_comp {
+       u8     status;
+       u8     ver;
+       u8     rsvd2[14];
+};
+
+/**
+ * struct iocpt_lif_init_cmd - LIF init command
+ * @opcode:    Opcode
+ * @type:      LIF type (enum iocpt_lif_type)
+ * @lif_index: LIF index
+ * @info_pa:   Destination address for LIF info (struct iocpt_lif_info)
+ */
+struct iocpt_lif_init_cmd {
+       u8     opcode;
+       u8     type;
+       __le16 lif_index;
+       __le32 rsvd;
+       __le64 info_pa;
+       u8     rsvd2[48];
+};
+
+/**
+ * struct iocpt_lif_init_comp - LIF init command completion
+ * @status:    Status of the command (enum iocpt_status_code)
+ * @hw_index:  Hardware index of the initialized LIF
+ */
+struct iocpt_lif_init_comp {
+       u8     status;
+       u8     rsvd;
+       __le16 hw_index;
+       u8     rsvd2[12];
+};
+
+/**
+ * struct iocpt_lif_reset_cmd - LIF reset command
+ * Will reset only the specified LIF.
+ * @opcode:    Opcode
+ * @lif_index: LIF index
+ */
+struct iocpt_lif_reset_cmd {
+       u8     opcode;
+       u8     rsvd;
+       __le16 lif_index;
+       __le32 rsvd2[15];
+};
+
+/**
+ * enum iocpt_lif_attr - List of LIF attributes
+ * @IOCPT_LIF_ATTR_STATE:      LIF state attribute
+ * @IOCPT_LIF_ATTR_NAME:       LIF name attribute
+ * @IOCPT_LIF_ATTR_FEATURES:   LIF features attribute
+ * @IOCPT_LIF_ATTR_STATS_CTRL: LIF statistics control attribute
+ */
+enum iocpt_lif_attr {
+       IOCPT_LIF_ATTR_STATE        = 0,
+       IOCPT_LIF_ATTR_NAME         = 1,
+       IOCPT_LIF_ATTR_FEATURES     = 4,
+       IOCPT_LIF_ATTR_STATS_CTRL   = 6,
+};
+
+/**
+ * struct iocpt_lif_setattr_cmd - Set LIF attributes on the NIC
+ * @opcode:    Opcode
+ * @attr:      Attribute type (enum iocpt_lif_attr)
+ * @lif_index: LIF index
+ * @state:     LIF state (enum iocpt_lif_state)
+ * @name:      The name string, 0 terminated
+ * @features:  Features (enum iocpt_hw_features)
+ * @stats_ctl: Stats control commands (enum iocpt_stats_ctl_cmd)
+ */
+struct iocpt_lif_setattr_cmd {
+       u8     opcode;
+       u8     attr;
+       __le16 lif_index;
+       union {
+               u8      state;
+               char    name[IOCPT_IFNAMSIZ];
+               __le64  features;
+               u8      stats_ctl;
+               u8      rsvd[60];
+       } __rte_packed;
+};
+
+/**
+ * struct iocpt_lif_setattr_comp - LIF set attr command completion
+ * @status:    Status of the command (enum iocpt_status_code)
+ * @comp_index: Index in the descriptor ring for which this is the completion
+ * @features:  Features (enum iocpt_hw_features)
+ * @color:     Color bit
+ */
+struct iocpt_lif_setattr_comp {
+       u8     status;
+       u8     rsvd;
+       __le16 comp_index;
+       union {
+               __le64  features;
+               u8      rsvd2[11];
+       } __rte_packed;
+       u8     color;
+};
+
+/**
+ * struct iocpt_lif_getattr_cmd - Get LIF attributes from the NIC
+ * @opcode:    Opcode
+ * @attr:      Attribute type (enum iocpt_lif_attr)
+ * @lif_index: LIF index
+ */
+struct iocpt_lif_getattr_cmd {
+       u8     opcode;
+       u8     attr;
+       __le16 lif_index;
+       u8     rsvd[60];
+};
+
+/**
+ * struct iocpt_lif_getattr_comp - LIF get attr command completion
+ * @status:    Status of the command (enum iocpt_status_code)
+ * @comp_index: Index in the descriptor ring for which this is the completion
+ * @state:     LIF state (enum iocpt_lif_state)
+ * @name:      LIF name string, 0 terminated
+ * @features:  Features (enum iocpt_hw_features)
+ * @color:     Color bit
+ */
+struct iocpt_lif_getattr_comp {
+       u8     status;
+       u8     rsvd;
+       __le16 comp_index;
+       union {
+               u8      state;
+               __le64  features;
+               u8      rsvd2[11];
+       } __rte_packed;
+       u8     color;
+};
+
+/**
+ * enum iocpt_logical_qtype - Logical Queue Types
+ * @IOCPT_QTYPE_ADMINQ:    Administrative Queue
+ * @IOCPT_QTYPE_NOTIFYQ:   Notify Queue
+ * @IOCPT_QTYPE_CRYPTOQ:   Cryptographic Queue
+ * @IOCPT_QTYPE_MAX:       Max queue type supported
+ */
+enum iocpt_logical_qtype {
+       IOCPT_QTYPE_ADMINQ  = 0,
+       IOCPT_QTYPE_NOTIFYQ = 1,
+       IOCPT_QTYPE_CRYPTOQ = 2,
+       IOCPT_QTYPE_MAX     = 8,
+};
+
+/**
+ * struct iocpt_q_identify_cmd - queue identify command
+ * @opcode:     Opcode
+ * @type:       Logical queue type (enum iocpt_logical_qtype)
+ * @lif_index:  LIF index
+ * @ver:        Highest queue type version that the driver supports
+ */
+struct iocpt_q_identify_cmd {
+       u8     opcode;
+       u8     type;
+       __le16 lif_index;
+       u8     ver;
+       u8     rsvd2[59];
+};
+
+/**
+ * struct iocpt_q_identify_comp - queue identify command completion
+ * @status:     Status of the command (enum iocpt_status_code)
+ * @comp_index: Index in the descriptor ring for which this is the completion
+ * @ver:        Queue type version that can be used with FW
+ */
+struct iocpt_q_identify_comp {
+       u8     status;
+       u8     rsvd;
+       __le16 comp_index;
+       u8     ver;
+       u8     rsvd2[11];
+};
+
+/**
+ * struct iocpt_q_init_cmd - Queue init command
+ * @opcode:       Opcode
+ * @type:         Logical queue type
+ * @lif_index:    LIF index
+ * @ver:          Queue type version
+ * @index:        (LIF, qtype) relative admin queue index
+ * @intr_index:   Interrupt control register index, or Event queue index
+ * @pid:          Process ID
+ * @flags:
+ *    IRQ:        Interrupt requested on completion
+ *    ENA:        Enable the queue.  If ENA=0 the queue is initialized
+ *                but remains disabled, to be later enabled with the
+ *                Queue Enable command.  If ENA=1, then queue is
+ *                initialized and then enabled.
+ *    SG:         Enable Scatter-Gather on the queue.
+ * @cos:          Class of service for this queue
+ * @ring_size:    Queue ring size, encoded as a log2(size), in
+ *                number of descriptors.  The actual ring size is
+ *                (1 << ring_size).  For example, to select a ring size
+ *                of 64 descriptors write ring_size = 6. The minimum
+ *                ring_size value is 2 for a ring of 4 descriptors.
+ *                The maximum ring_size value is 12 for a ring of 4k
+ *                descriptors.  Values of ring_size <2 and >12 are
+ *                reserved.
+ * @ring_base:    Queue ring base address
+ * @cq_ring_base: Completion queue ring base address
+ * @sg_ring_base: Scatter/Gather ring base address
+ */
+struct iocpt_q_init_cmd {
+       u8     opcode;
+       u8     type;
+       __le16 lif_index;
+       u8     ver;
+       u8     rsvd[3];
+       __le32 index;
+       __le16 pid;
+       __le16 intr_index;
+       __le16 flags;
+#define IOCPT_QINIT_F_IRQ      0x01    /* Request interrupt on completion */
+#define IOCPT_QINIT_F_ENA      0x02    /* Enable the queue */
+#define IOCPT_QINIT_F_SG       0x04    /* Enable scatter/gather on queue */
+       u8     cos;
+#define IOCPT_QSIZE_MIN_LG2    2
+#define IOCPT_QSIZE_MAX_LG2    12
+       u8     ring_size;
+       __le64 ring_base;
+       __le64 cq_ring_base;
+       __le64 sg_ring_base;
+       u8     rsvd2[20];
+} __rte_packed;
+
+/**
+ * struct iocpt_q_init_comp - Queue init command completion
+ * @status:     Status of the command (enum iocpt_status_code)
+ * @comp_index: Index in the descriptor ring for which this is the completion
+ * @hw_index:   Hardware Queue ID
+ * @hw_type:    Hardware Queue type
+ * @color:      Color
+ */
+struct iocpt_q_init_comp {
+       u8     status;
+       u8     rsvd;
+       __le16 comp_index;
+       __le32 hw_index;
+       u8     hw_type;
+       u8     rsvd2[6];
+       u8     color;
+};
+
+enum iocpt_desc_opcode {
+       IOCPT_DESC_OPCODE_GCM_AEAD_ENCRYPT = 0,
+       IOCPT_DESC_OPCODE_GCM_AEAD_DECRYPT = 1,
+       IOCPT_DESC_OPCODE_XTS_ENCRYPT = 2,
+       IOCPT_DESC_OPCODE_XTS_DECRYPT = 3,
+};
+
+#define IOCPT_DESC_F_AAD_VALID         0x1
+
+/**
+ * struct iocpt_desc - Crypto queue descriptor format
+ * @opcode:
+ *         IOCPT_DESC_OPCODE_GCM_AEAD_ENCRYPT:
+ *                   Perform a GCM-AES encrypt operation
+ *
+ *         IOCPT_DESC_OPCODE_GCM_AEAD_DECRYPT:
+ *                   Perform a GCM-AES decrypt operation
+ *
+ *         IOCPT_DESC_OPCODE_XTS_ENCRYPT:
+ *                   Perform an XTS encrypt operation
+ *
+ *         IOCPT_DESC_OPCODE_XTS_DECRYPT:
+ *                   Perform an XTS decrypt operation
+ * @flags:
+ *         IOCPT_DESC_F_AAD_VALID:
+ *                   Source SGL contains an AAD addr and length
+ * @num_src_dst_sgs: Number of scatter-gather elements in SG
+ *                   descriptor (4 bits for source, 4 bits for destination)
+ * @session_tag:     Session tag (key index)
+ * @intr_ctx_addr:   Completion interrupt context address
+ * @intr_ctx_data:   Completion interrupt context data
+ */
+struct iocpt_crypto_desc {
+       uint8_t  opcode;
+       uint8_t  flags;
+       uint8_t  num_src_dst_sgs;
+#define IOCPT_DESC_NSGE_SRC_MASK       0xf
+#define IOCPT_DESC_NSGE_SRC_SHIFT      0
+#define IOCPT_DESC_NSGE_DST_MASK       0xf
+#define IOCPT_DESC_NSGE_DST_SHIFT      4
+       uint8_t  rsvd[9];
+       __le32   session_tag;
+       __le64   intr_ctx_addr;
+       __le64   intr_ctx_data;
+} __rte_packed;
+
+static inline uint8_t iocpt_encode_nsge_src_dst(uint8_t src, uint8_t dst)
+{
+       uint8_t nsge_src_dst;
+
+       nsge_src_dst = (src & IOCPT_DESC_NSGE_SRC_MASK) <<
+               IOCPT_DESC_NSGE_SRC_SHIFT;
+       nsge_src_dst |= (dst & IOCPT_DESC_NSGE_DST_MASK) <<
+               IOCPT_DESC_NSGE_DST_SHIFT;
+
+       return nsge_src_dst;
+};
+
+static inline void iocpt_decode_nsge_src_dst(uint8_t nsge_src_dst,
+                                            uint8_t *src, uint8_t *dst)
+{
+       *src = (nsge_src_dst >> IOCPT_DESC_NSGE_SRC_SHIFT) &
+               IOCPT_DESC_NSGE_SRC_MASK;
+       *dst = (nsge_src_dst >> IOCPT_DESC_NSGE_DST_SHIFT) &
+               IOCPT_DESC_NSGE_DST_MASK;
+};
+
+/**
+ * struct iocpt_crypto_sg_elem - Crypto scatter-gather (SG) descriptor element
+ * @addr:      DMA address of SG element data buffer
+ * @len:       Length of SG element data buffer, in bytes
+ */
+struct iocpt_crypto_sg_elem {
+       __le64  addr;
+       __le16  len;
+       uint8_t rsvd[6];
+};
+
+/**
+ * struct iocpt_crypto_sg_desc - Crypto scatter-gather (SG) list
+ * @src_elems: Source SG elements; also destination in IP case
+ *     AES_GCM:
+ *         SGE0: Nonce
+ *         SGE1: AAD (see IOCPT_DESC_F_AAD_VALID)
+ *         SGE2 to SGE(N): Payload
+ *         SGE(N+1): Auth tag
+ * @dst_elems: Destination SG elements for OOP case; unused in IP case
+ */
+struct iocpt_crypto_sg_desc {
+#define IOCPT_CRYPTO_MAX_SG_ELEMS      8
+#define IOCPT_CRYPTO_NONCE_ELEM                0
+#define IOCPT_CRYPTO_AAD_ELEM          1
+       struct iocpt_crypto_sg_elem src_elems[IOCPT_CRYPTO_MAX_SG_ELEMS];
+       struct iocpt_crypto_sg_elem dst_elems[IOCPT_CRYPTO_MAX_SG_ELEMS];
+};
+
+/**
+ * struct iocpt_crypto_comp - Crypto queue completion descriptor
+ * @status:    Status of the command (enum iocpt_status_code)
+ * @comp_index:        Index in the descriptor ring for which this is the 
completion
+ * @color:     Color bit
+ */
+struct iocpt_crypto_comp {
+#define IOCPT_COMP_SUCCESS                     0
+#define IOCPT_COMP_INVAL_OPCODE_ERROR          1
+#define IOCPT_COMP_UNSUPP_OPCODE_ERROR         2
+#define IOCPT_COMP_SYMM_SRC_SG_ERROR           3
+#define IOCPT_COMP_SYMM_DST_SG_ERROR           4
+#define IOCPT_COMP_SYMM_SRC_DST_LEN_MISMATCH   5
+#define IOCPT_COMP_SYMM_HW_QAVAIL_ERROR                6
+#define IOCPT_COMP_SYMM_AUTH_VERIFY_ERROR      7
+#define IOCPT_COMP_SYMM_OTHER_VERIFY_ERROR     8
+#define IOCPT_COMP_SYMM_PI_MODE_CHKSUM_ERROR   9
+#define IOCPT_COMP_SYMM_HARDWARE_ERROR         10
+#define IOCPT_COMP_SYMM_KEY_IDX_ERROR          11
+       u8     status;
+       u8     rsvd;
+       __le16 comp_index;
+       u8     rsvd2[11];
+       u8     color;
+};
+
+/**
+ * enum iocpt_hw_features - Feature flags supported by hardware
+ * @IOCPT_HW_SYM:   Symmetric crypto operations
+ * @IOCPT_HW_ASYM:  Asymmetric crypto operations
+ * @IOCPT_HW_CHAIN: Chained crypto operations
+ * @IOCPT_HW_IP:    In-Place (destination same as source)
+ * @IOCPT_HW_OOP:   Out-Of-Place (destination differs from source)
+ */
+enum iocpt_hw_features {
+       IOCPT_HW_SYM             = BIT(0),
+       IOCPT_HW_ASYM            = BIT(1),
+       IOCPT_HW_CHAIN           = BIT(2),
+       IOCPT_HW_IP              = BIT(3),
+       IOCPT_HW_OOP             = BIT(4),
+};
+
+/**
+ * struct iocpt_q_control_cmd - Queue control command
+ * @opcode:    Opcode
+ * @type:      Queue type
+ * @lif_index: LIF index
+ * @index:     Queue index
+ * @oper:      Operation (enum iocpt_q_control_oper)
+ */
+struct iocpt_q_control_cmd {
+       u8     opcode;
+       u8     type;
+       __le16 lif_index;
+       __le32 index;
+       u8     oper;
+       u8     rsvd2[55];
+};
+
+enum iocpt_q_control_oper {
+       IOCPT_Q_DISABLE         = 0,
+       IOCPT_Q_ENABLE          = 1,
+};
+
+/* NB: It will take 64 transfers to update a 2048B key */
+#define IOCPT_SESS_KEY_LEN_MIN         16
+#define IOCPT_SESS_KEY_LEN_MAX_SYMM    32
+#define IOCPT_SESS_KEY_LEN_MAX_ASYM    2048
+#define IOCPT_SESS_KEY_SEG_LEN         32
+#define IOCPT_SESS_KEY_SEG_SHFT                5
+#define IOCPT_SESS_KEY_SEG_CNT         \
+       (IOCPT_SESS_KEY_LEN_MAX_SYMM >> IOCPT_SESS_KEY_SEG_SHFT)
+
+enum iocpt_sess_type {
+       IOCPT_SESS_NONE                 = 0,
+       IOCPT_SESS_AEAD_AES_GCM         = 1,
+};
+
+enum iocpt_sess_control_oper {
+       IOCPT_SESS_INIT                 = 0,
+       IOCPT_SESS_UPDATE_KEY           = 2,
+       IOCPT_SESS_DISABLE              = 3,
+};
+
+/**
+ * struct iocpt_sess_control_cmd - Session control command
+ * @opcode:      Opcode
+ * @type:        Session type (enum iocpt_sess_type)
+ * @lif_index:   LIF index
+ * @oper:        Operation (enum iocpt_sess_control_oper)
+ * @flags:
+ *    END:       Indicates that this is the final segment of the key.
+ *               When this flag is set, a write will be triggered from the
+ *               controller's memory into the dedicated key-storage area.
+ * @key_len:     Crypto key length in bytes
+ * @index:       Session index, as allocated by PMD
+ * @key_seg_len: Crypto key segment length in bytes
+ * @key_seg_idx: Crypto key segment index
+ * @key:         Crypto key
+ */
+struct iocpt_sess_control_cmd {
+       u8     opcode;
+       u8     type;
+       __le16 lif_index;
+       u8     oper;
+       u8     flags;
+#define IOCPT_SCTL_F_END       0x01    /* Final segment of key */
+       __le16 key_len;
+       __le32 index;
+       u8     key_seg_len;
+       u8     key_seg_idx;
+       u8     rsvd[18];
+       u8     key[IOCPT_SESS_KEY_SEG_LEN];
+};
+
+/**
+ * struct iocpt_sess_control_comp - Session control command completion
+ * @status:     Status of the command (enum iocpt_status_code)
+ * @comp_index: Index in the descriptor ring for which this is the completion
+ * @index:      Session index
+ * @hw_type:    Hardware Session type
+ * @color:      Color
+ */
+struct iocpt_sess_control_comp {
+       u8     status;
+       u8     rsvd;
+       __le16 comp_index;
+       __le32 index;
+       u8     hw_type;
+       u8     rsvd2[6];
+       u8     color;
+};
+
+/**
+ * enum iocpt_stats_ctl_cmd - List of commands for stats control
+ * @IOCPT_STATS_CTL_RESET:      Reset statistics
+ */
+enum iocpt_stats_ctl_cmd {
+       IOCPT_STATS_CTL_RESET           = 0,
+};
+
+/**
+ * struct iocpt_dev_status - Device status register
+ * @eid:             most recent NotifyQ event id
+ */
+struct iocpt_dev_status {
+       __le64 eid;
+       u8     rsvd2[56];
+};
+
+enum iocpt_dev_state {
+       IOCPT_DEV_DISABLE       = 0,
+       IOCPT_DEV_ENABLE        = 1,
+       IOCPT_DEV_HANG_RESET    = 2,
+};
+
+/**
+ * enum iocpt_dev_attr - List of device attributes
+ * @IOCPT_DEV_ATTR_STATE:     Device state attribute
+ * @IOCPT_DEV_ATTR_NAME:      Device name attribute
+ * @IOCPT_DEV_ATTR_FEATURES:  Device feature attributes
+ */
+enum iocpt_dev_attr {
+       IOCPT_DEV_ATTR_STATE    = 0,
+       IOCPT_DEV_ATTR_NAME     = 1,
+       IOCPT_DEV_ATTR_FEATURES = 2,
+};
+
+/**
+ * struct iocpt_notify_event - Generic event reporting structure
+ * @eid:   event number
+ * @ecode: event code
+ * @data:  unspecified data about the event
+ *
+ * This is the generic event report struct from which the other
+ * actual events will be formed.
+ */
+struct iocpt_notify_event {
+       __le64 eid;
+       __le16 ecode;
+       u8     data[54];
+};
+
+/**
+ * struct iocpt_reset_event - Reset event notification
+ * @eid:               event number
+ * @ecode:             event code = IOCPT_EVENT_RESET
+ * @reset_code:                reset type
+ * @state:             0=pending, 1=complete, 2=error
+ *
+ * Sent when the NIC or some subsystem is going to be or
+ * has been reset.
+ */
+struct iocpt_reset_event {
+       __le64 eid;
+       __le16 ecode;
+       u8     reset_code;
+       u8     state;
+       u8     rsvd[52];
+};
+
+/**
+ * struct iocpt_heartbeat_event - Sent periodically by NIC to indicate health
+ * @eid:       event number
+ * @ecode:     event code = IOCPT_EVENT_HEARTBEAT
+ */
+struct iocpt_heartbeat_event {
+       __le64 eid;
+       __le16 ecode;
+       u8     rsvd[54];
+};
+
+/**
+ * struct iocpt_log_event - Sent to notify the driver of an internal error
+ * @eid:       event number
+ * @ecode:     event code = IOCPT_EVENT_LOG
+ * @data:      log data
+ */
+struct iocpt_log_event {
+       __le64 eid;
+       __le16 ecode;
+       u8     data[54];
+};
+
+/**
+ * union iocpt_lif_config - LIF configuration
+ * @state:         LIF state (enum iocpt_lif_state)
+ * @name:          LIF name
+ * @features:      LIF features active (enum iocpt_hw_features)
+ * @queue_count:    Queue counts per queue-type
+ */
+union iocpt_lif_config {
+       struct {
+               u8     state;
+               u8     rsvd[3];
+               char   name[IOCPT_IFNAMSIZ];
+               u8     rsvd2[12];
+               __le64 features;
+               __le32 queue_count[IOCPT_QTYPE_MAX];
+       } __rte_packed;
+       __le32 words[56];
+};
+
+/**
+ * struct iocpt_lif_status - LIF status register
+ * @eid:            most recent NotifyQ event id
+ */
+struct iocpt_lif_status {
+       __le64 eid;
+       u8     rsvd[56];
+};
+
+/**
+ * struct iocpt_lif_info - LIF info structure
+ * @config:    LIF configuration structure
+ * @status:    LIF status structure
+ * @stats:     LIF statistics structure
+ */
+struct iocpt_lif_info {
+       union iocpt_lif_config config;
+       struct iocpt_lif_status status;
+};
+
+union iocpt_dev_cmd {
+       u32    words[16];
+       struct iocpt_admin_cmd cmd;
+       struct iocpt_nop_cmd nop;
+
+       struct iocpt_dev_identify_cmd identify;
+       struct iocpt_dev_reset_cmd reset;
+
+       struct iocpt_lif_identify_cmd lif_identify;
+       struct iocpt_lif_init_cmd lif_init;
+       struct iocpt_lif_reset_cmd lif_reset;
+       struct iocpt_lif_getattr_cmd lif_getattr;
+       struct iocpt_lif_setattr_cmd lif_setattr;
+
+       struct iocpt_q_identify_cmd q_identify;
+       struct iocpt_q_init_cmd q_init;
+       struct iocpt_q_control_cmd q_control;
+
+       struct iocpt_sess_control_cmd sess_control;
+};
+
+union iocpt_dev_cmd_comp {
+       u32    words[4];
+       u8     status;
+       struct iocpt_admin_comp comp;
+       struct iocpt_nop_comp nop;
+
+       struct iocpt_dev_identify_comp identify;
+       struct iocpt_dev_reset_comp reset;
+
+       struct iocpt_lif_identify_comp lif_identify;
+       struct iocpt_lif_init_comp lif_init;
+       struct iocpt_lif_getattr_comp lif_getattr;
+       struct iocpt_lif_setattr_comp lif_setattr;
+
+       struct iocpt_q_identify_comp q_identify;
+       struct iocpt_q_init_comp q_init;
+
+       struct iocpt_sess_control_comp sess_control;
+};
+
+/**
+ * union iocpt_dev_info_regs - Device info register format (read-only)
+ * @signature:       Signature value of 0x43585660 ('CRPT')
+ * @version:         Current version of info
+ * @asic_type:       Asic type
+ * @asic_rev:        Asic revision
+ * @fw_status:       Firmware status
+ * @fw_heartbeat:    Firmware heartbeat counter
+ * @serial_num:      Serial number
+ * @fw_version:      Firmware version
+ */
+union iocpt_dev_info_regs {
+#define IOCPT_FWVERS_BUFLEN 32
+#define IOCPT_SERIAL_BUFLEN 32
+       struct {
+               u32    signature;
+               u8     version;
+               u8     asic_type;
+               u8     asic_rev;
+#define IOCPT_FW_STS_F_RUNNING 0x1
+               u8     fw_status;
+               u32    fw_heartbeat;
+               char   fw_version[IOCPT_FWVERS_BUFLEN];
+               char   serial_num[IOCPT_SERIAL_BUFLEN];
+       };
+       u32    words[512];
+};
+
+/**
+ * union iocpt_dev_cmd_regs - Device command register format (read-write)
+ * @doorbell:        Device Cmd Doorbell, write-only
+ *                   Write a 1 to signal device to process cmd,
+ *                   poll done for completion.
+ * @done:            Done indicator, bit 0 == 1 when command is complete
+ * @cmd:             Opcode-specific command bytes
+ * @comp:            Opcode-specific response bytes
+ * @data:            Opcode-specific side-data
+ */
+union iocpt_dev_cmd_regs {
+       struct {
+               u32    doorbell;
+               u32    done;
+               union iocpt_dev_cmd         cmd;
+               union iocpt_dev_cmd_comp    comp;
+               u8     rsvd[48];
+               u32    data[478];
+       } __rte_packed;
+       u32    words[512];
+};
+
+/**
+ * union iocpt_dev_regs - Device register format for bar 0 page 0
+ * @info:            Device info registers
+ * @devcmd:          Device command registers
+ */
+union iocpt_dev_regs {
+       struct {
+               union iocpt_dev_info_regs info;
+               union iocpt_dev_cmd_regs  devcmd;
+       } __rte_packed;
+       __le32 words[1024];
+};
+
+union iocpt_adminq_cmd {
+       struct iocpt_admin_cmd cmd;
+       struct iocpt_nop_cmd nop;
+       struct iocpt_q_identify_cmd q_identify;
+       struct iocpt_q_init_cmd q_init;
+       struct iocpt_q_control_cmd q_control;
+       struct iocpt_lif_setattr_cmd lif_setattr;
+       struct iocpt_lif_getattr_cmd lif_getattr;
+       struct iocpt_sess_control_cmd sess_control;
+};
+
+union iocpt_adminq_comp {
+       struct iocpt_admin_comp comp;
+       struct iocpt_nop_comp nop;
+       struct iocpt_q_identify_comp q_identify;
+       struct iocpt_q_init_comp q_init;
+       struct iocpt_lif_setattr_comp lif_setattr;
+       struct iocpt_lif_getattr_comp lif_getattr;
+       struct iocpt_sess_control_comp sess_control;
+};
+
+union iocpt_notify_comp {
+       struct iocpt_notify_event event;
+       struct iocpt_reset_event reset;
+       struct iocpt_heartbeat_event heartbeat;
+       struct iocpt_log_event log;
+};
+
+/**
+ * union iocpt_dev_identity - device identity information
+ * @version:          Version of device identify
+ * @type:             Identify type (0 for now)
+ * @state:            Device state
+ * @nlifs:            Number of LIFs provisioned
+ * @nintrs:           Number of interrupts provisioned
+ * @ndbpgs_per_lif:   Number of doorbell pages per LIF
+ * @intr_coal_mult:   Interrupt coalescing multiplication factor
+ *                    Scale user-supplied interrupt coalescing
+ *                    value in usecs to device units using:
+ *                    device units = usecs * mult / div
+ * @intr_coal_div:    Interrupt coalescing division factor
+ *                    Scale user-supplied interrupt coalescing
+ *                    value in usecs to device units using:
+ *                    device units = usecs * mult / div
+ */
+union iocpt_dev_identity {
+       struct {
+               u8     version;
+               u8     type;
+               u8     state;
+               u8     rsvd;
+               __le32 nlifs;
+               __le32 nintrs;
+               __le32 ndbpgs_per_lif;
+               __le32 intr_coal_mult;
+               __le32 intr_coal_div;
+               u8     rsvd2[8];
+       };
+       __le32 words[8];
+};
+
+/**
+ * union iocpt_lif_identity - LIF identity information (type-specific)
+ *
+ * @features:           LIF features (see enum iocpt_hw_features)
+ * @version:            Identify structure version
+ * @hw_index:           LIF hardware index
+ * @max_nb_sessions:    Maximum number of sessions supported
+ * @config:             LIF config struct with features, q counts
+ */
+union iocpt_lif_identity {
+       struct {
+               __le64 features;
+
+               u8 version;
+               u8 hw_index;
+               u8 rsvd[2];
+               __le32 max_nb_sessions;
+               u8 rsvd2[120];
+               union iocpt_lif_config config;
+       } __rte_packed;
+       __le32 words[90];
+};
+
+/**
+ * union iocpt_q_identity - queue identity information
+ *     @version:        Queue type version that can be used with FW
+ *     @supported:      Bitfield of queue versions, first bit = ver 0
+ *     @features:       Queue features
+ *     @desc_sz:        Descriptor size
+ *     @comp_sz:        Completion descriptor size
+ *     @sg_desc_sz:     Scatter/Gather descriptor size
+ *     @max_sg_elems:   Maximum number of Scatter/Gather elements
+ *     @sg_desc_stride: Number of Scatter/Gather elements per descriptor
+ */
+union iocpt_q_identity {
+       struct {
+               u8      version;
+               u8      supported;
+               u8      rsvd[6];
+#define IOCPT_QIDENT_F_CQ      0x01    /* queue has completion ring */
+#define IOCPT_QIDENT_F_SG      0x02    /* queue has scatter/gather ring */
+               __le64  features;
+               __le16  desc_sz;
+               __le16  comp_sz;
+               __le16  sg_desc_sz;
+               __le16  max_sg_elems;
+               __le16  sg_desc_stride;
+       };
+       __le32 words[20];
+};
+
+struct iocpt_identity {
+       union iocpt_dev_identity dev;
+       union iocpt_lif_identity lif;
+       union iocpt_q_identity q;
+};
+
+#endif /* _IONIC_CRYPTO_IF_H_ */
diff --git a/drivers/crypto/ionic/ionic_crypto_main.c 
b/drivers/crypto/ionic/ionic_crypto_main.c
index 7c1cf5c20e..2aec52bc34 100644
--- a/drivers/crypto/ionic/ionic_crypto_main.c
+++ b/drivers/crypto/ionic/ionic_crypto_main.c
@@ -57,9 +57,12 @@ iocpt_probe(void *bus_dev, struct rte_device *rte_dev,
        };
        struct rte_cryptodev *cdev;
        struct iocpt_dev *dev;
-       uint32_t i;
+       uint32_t i, sig;
        int err;
 
+       /* Check structs (trigger error at compilation time) */
+       iocpt_struct_size_checks();
+
        if (rte_eal_process_type() != RTE_PROC_PRIMARY) {
                IOCPT_PRINT(ERR, "Multi-process not supported");
                err = -EPERM;
@@ -110,6 +113,18 @@ iocpt_probe(void *bus_dev, struct rte_device *rte_dev,
                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_init(dev);
        if (err != 0) {
                IOCPT_PRINT(ERR, "Cannot init device: %d, aborting", err);
diff --git a/drivers/crypto/ionic/ionic_crypto_vdev.c 
b/drivers/crypto/ionic/ionic_crypto_vdev.c
index a915aa06aa..d15acf660a 100644
--- a/drivers/crypto/ionic/ionic_crypto_vdev.c
+++ b/drivers/crypto/ionic/ionic_crypto_vdev.c
@@ -24,11 +24,48 @@
 #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;
-- 
2.17.1

Reply via email to