linux/drivers/crypto/cavium/nitrox/nitrox_lib.c
<<
>>
Prefs
   1// SPDX-License-Identifier: GPL-2.0
   2#include <linux/cpumask.h>
   3#include <linux/dma-mapping.h>
   4#include <linux/dmapool.h>
   5#include <linux/delay.h>
   6#include <linux/gfp.h>
   7#include <linux/kernel.h>
   8#include <linux/module.h>
   9#include <linux/pci_regs.h>
  10#include <linux/vmalloc.h>
  11#include <linux/pci.h>
  12
  13#include "nitrox_dev.h"
  14#include "nitrox_common.h"
  15#include "nitrox_req.h"
  16#include "nitrox_csr.h"
  17
  18#define CRYPTO_CTX_SIZE 256
  19
  20/* packet inuput ring alignments */
  21#define PKTIN_Q_ALIGN_BYTES 16
  22
  23static int nitrox_cmdq_init(struct nitrox_cmdq *cmdq, int align_bytes)
  24{
  25        struct nitrox_device *ndev = cmdq->ndev;
  26
  27        cmdq->qsize = (ndev->qlen * cmdq->instr_size) + align_bytes;
  28        cmdq->unalign_base = dma_alloc_coherent(DEV(ndev), cmdq->qsize,
  29                                                &cmdq->unalign_dma,
  30                                                GFP_KERNEL);
  31        if (!cmdq->unalign_base)
  32                return -ENOMEM;
  33
  34        cmdq->dma = PTR_ALIGN(cmdq->unalign_dma, align_bytes);
  35        cmdq->base = cmdq->unalign_base + (cmdq->dma - cmdq->unalign_dma);
  36        cmdq->write_idx = 0;
  37
  38        spin_lock_init(&cmdq->cmd_qlock);
  39        spin_lock_init(&cmdq->resp_qlock);
  40        spin_lock_init(&cmdq->backlog_qlock);
  41
  42        INIT_LIST_HEAD(&cmdq->response_head);
  43        INIT_LIST_HEAD(&cmdq->backlog_head);
  44        INIT_WORK(&cmdq->backlog_qflush, backlog_qflush_work);
  45
  46        atomic_set(&cmdq->pending_count, 0);
  47        atomic_set(&cmdq->backlog_count, 0);
  48        return 0;
  49}
  50
  51static void nitrox_cmdq_reset(struct nitrox_cmdq *cmdq)
  52{
  53        cmdq->write_idx = 0;
  54        atomic_set(&cmdq->pending_count, 0);
  55        atomic_set(&cmdq->backlog_count, 0);
  56}
  57
  58static void nitrox_cmdq_cleanup(struct nitrox_cmdq *cmdq)
  59{
  60        struct nitrox_device *ndev = cmdq->ndev;
  61
  62        if (!cmdq->unalign_base)
  63                return;
  64
  65        cancel_work_sync(&cmdq->backlog_qflush);
  66
  67        dma_free_coherent(DEV(ndev), cmdq->qsize,
  68                          cmdq->unalign_base, cmdq->unalign_dma);
  69        nitrox_cmdq_reset(cmdq);
  70
  71        cmdq->dbell_csr_addr = NULL;
  72        cmdq->compl_cnt_csr_addr = NULL;
  73        cmdq->unalign_base = NULL;
  74        cmdq->base = NULL;
  75        cmdq->unalign_dma = 0;
  76        cmdq->dma = 0;
  77        cmdq->qsize = 0;
  78        cmdq->instr_size = 0;
  79}
  80
  81static void nitrox_free_pktin_queues(struct nitrox_device *ndev)
  82{
  83        int i;
  84
  85        for (i = 0; i < ndev->nr_queues; i++) {
  86                struct nitrox_cmdq *cmdq = &ndev->pkt_inq[i];
  87
  88                nitrox_cmdq_cleanup(cmdq);
  89        }
  90        kfree(ndev->pkt_inq);
  91        ndev->pkt_inq = NULL;
  92}
  93
  94static int nitrox_alloc_pktin_queues(struct nitrox_device *ndev)
  95{
  96        int i, err;
  97
  98        ndev->pkt_inq = kcalloc_node(ndev->nr_queues,
  99                                     sizeof(struct nitrox_cmdq),
 100                                     GFP_KERNEL, ndev->node);
 101        if (!ndev->pkt_inq)
 102                return -ENOMEM;
 103
 104        for (i = 0; i < ndev->nr_queues; i++) {
 105                struct nitrox_cmdq *cmdq;
 106                u64 offset;
 107
 108                cmdq = &ndev->pkt_inq[i];
 109                cmdq->ndev = ndev;
 110                cmdq->qno = i;
 111                cmdq->instr_size = sizeof(struct nps_pkt_instr);
 112
 113                /* packet input ring doorbell address */
 114                offset = NPS_PKT_IN_INSTR_BAOFF_DBELLX(i);
 115                cmdq->dbell_csr_addr = NITROX_CSR_ADDR(ndev, offset);
 116                /* packet solicit port completion count address */
 117                offset = NPS_PKT_SLC_CNTSX(i);
 118                cmdq->compl_cnt_csr_addr = NITROX_CSR_ADDR(ndev, offset);
 119
 120                err = nitrox_cmdq_init(cmdq, PKTIN_Q_ALIGN_BYTES);
 121                if (err)
 122                        goto pktq_fail;
 123        }
 124        return 0;
 125
 126pktq_fail:
 127        nitrox_free_pktin_queues(ndev);
 128        return err;
 129}
 130
 131static int create_crypto_dma_pool(struct nitrox_device *ndev)
 132{
 133        size_t size;
 134
 135        /* Crypto context pool, 16 byte aligned */
 136        size = CRYPTO_CTX_SIZE + sizeof(struct ctx_hdr);
 137        ndev->ctx_pool = dma_pool_create("nitrox-context",
 138                                         DEV(ndev), size, 16, 0);
 139        if (!ndev->ctx_pool)
 140                return -ENOMEM;
 141
 142        return 0;
 143}
 144
 145static void destroy_crypto_dma_pool(struct nitrox_device *ndev)
 146{
 147        if (!ndev->ctx_pool)
 148                return;
 149
 150        dma_pool_destroy(ndev->ctx_pool);
 151        ndev->ctx_pool = NULL;
 152}
 153
 154/*
 155 * crypto_alloc_context - Allocate crypto context from pool
 156 * @ndev: NITROX Device
 157 */
 158void *crypto_alloc_context(struct nitrox_device *ndev)
 159{
 160        struct ctx_hdr *ctx;
 161        struct crypto_ctx_hdr *chdr;
 162        void *vaddr;
 163        dma_addr_t dma;
 164
 165        chdr = kmalloc(sizeof(*chdr), GFP_KERNEL);
 166        if (!chdr)
 167                return NULL;
 168
 169        vaddr = dma_pool_zalloc(ndev->ctx_pool, GFP_KERNEL, &dma);
 170        if (!vaddr) {
 171                kfree(chdr);
 172                return NULL;
 173        }
 174
 175        /* fill meta data */
 176        ctx = vaddr;
 177        ctx->pool = ndev->ctx_pool;
 178        ctx->dma = dma;
 179        ctx->ctx_dma = dma + sizeof(struct ctx_hdr);
 180
 181        chdr->pool = ndev->ctx_pool;
 182        chdr->dma = dma;
 183        chdr->vaddr = vaddr;
 184
 185        return chdr;
 186}
 187
 188/**
 189 * crypto_free_context - Free crypto context to pool
 190 * @ctx: context to free
 191 */
 192void crypto_free_context(void *ctx)
 193{
 194        struct crypto_ctx_hdr *ctxp;
 195
 196        if (!ctx)
 197                return;
 198
 199        ctxp = ctx;
 200        dma_pool_free(ctxp->pool, ctxp->vaddr, ctxp->dma);
 201        kfree(ctxp);
 202}
 203
 204/**
 205 * nitrox_common_sw_init - allocate software resources.
 206 * @ndev: NITROX device
 207 *
 208 * Allocates crypto context pools and command queues etc.
 209 *
 210 * Return: 0 on success, or a negative error code on error.
 211 */
 212int nitrox_common_sw_init(struct nitrox_device *ndev)
 213{
 214        int err = 0;
 215
 216        /* per device crypto context pool */
 217        err = create_crypto_dma_pool(ndev);
 218        if (err)
 219                return err;
 220
 221        err = nitrox_alloc_pktin_queues(ndev);
 222        if (err)
 223                destroy_crypto_dma_pool(ndev);
 224
 225        return err;
 226}
 227
 228/**
 229 * nitrox_common_sw_cleanup - free software resources.
 230 * @ndev: NITROX device
 231 */
 232void nitrox_common_sw_cleanup(struct nitrox_device *ndev)
 233{
 234        nitrox_free_pktin_queues(ndev);
 235        destroy_crypto_dma_pool(ndev);
 236}
 237