Re: [PATCH v5 2/3] drivers: crypto: Add the Virtual Function driver for CPT
Hi Sasha, Thanks for the reveiw. On Friday 03 February 2017 12:24 AM, Sasha Levin wrote: On Mon, Jan 30, 2017 at 7:30 AM, George Cherianwrote: diff --git a/drivers/crypto/cavium/cpt/cptvf_main.c b/drivers/crypto/cavium/cpt/cptvf_main.c new file mode 100644 index 000..4cf466d --- /dev/null +++ b/drivers/crypto/cavium/cpt/cptvf_main.c @@ -0,0 +1,948 @@ +/* + * Copyright (C) 2016 Cavium, Inc. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of version 2 of the GNU General Public License + * as published by the Free Software Foundation. + */ + +#include +#include + +#include "cptvf.h" + +#define DRV_NAME "thunder-cptvf" +#define DRV_VERSION"1.0" + +struct cptvf_wqe { + struct tasklet_struct twork; + void *cptvf; + u32 qno; +}; + +struct cptvf_wqe_info { + struct cptvf_wqe vq_wqe[CPT_NUM_QS_PER_VF]; +}; + +static void vq_work_handler(unsigned long data) +{ + struct cptvf_wqe_info *cwqe_info = (struct cptvf_wqe_info *)data; + struct cptvf_wqe *cwqe = _info->vq_wqe[0]; + + vq_post_process(cwqe->cptvf, cwqe->qno); +} + +static int init_worker_threads(struct cpt_vf *cptvf) +{ + struct pci_dev *pdev = cptvf->pdev; + struct cptvf_wqe_info *cwqe_info; + int i; + + cwqe_info = kzalloc(sizeof(*cwqe_info), GFP_KERNEL); + if (!cwqe_info) + return -ENOMEM; + + if (cptvf->nr_queues) { + dev_info(>dev, "Creating VQ worker threads (%d)\n", +cptvf->nr_queues); + } + + for (i = 0; i < cptvf->nr_queues; i++) { + tasklet_init(_info->vq_wqe[i].twork, vq_work_handler, +(u64)cwqe_info); + cwqe_info->vq_wqe[i].qno = i; + cwqe_info->vq_wqe[i].cptvf = cptvf; + } + + cptvf->wqe_info = cwqe_info; + + return 0; +} + +static void cleanup_worker_threads(struct cpt_vf *cptvf) +{ + struct cptvf_wqe_info *cwqe_info; + struct pci_dev *pdev = cptvf->pdev; + int i; + + cwqe_info = (struct cptvf_wqe_info *)cptvf->wqe_info; + if (!cwqe_info) + return; + + if (cptvf->nr_queues) { + dev_info(>dev, "Cleaning VQ worker threads (%u)\n", +cptvf->nr_queues); + } + + for (i = 0; i < cptvf->nr_queues; i++) + tasklet_kill(_info->vq_wqe[i].twork); + + kzfree(cwqe_info); + cptvf->wqe_info = NULL; +} + +static void free_pending_queues(struct pending_qinfo *pqinfo) +{ + int i; + struct pending_queue *queue; + + for_each_pending_queue(pqinfo, queue, i) { + if (!queue->head) + continue; + + /* free single queue */ + kzfree((queue->head)); + + queue->front = 0; + queue->rear = 0; + + return; + } + + pqinfo->qlen = 0; + pqinfo->nr_queues = 0; +} + +static int alloc_pending_queues(struct pending_qinfo *pqinfo, u32 qlen, + u32 nr_queues) +{ + u32 i; + size_t size; + int ret; + struct pending_queue *queue = NULL; + + pqinfo->nr_queues = nr_queues; + pqinfo->qlen = qlen; + + size = (qlen * sizeof(struct pending_entry)); + + for_each_pending_queue(pqinfo, queue, i) { + queue->head = kzalloc((size), GFP_KERNEL); + if (!queue->head) { + ret = -ENOMEM; + goto pending_qfail; + } + + queue->front = 0; + queue->rear = 0; + atomic64_set((>pending_count), (0)); + + /* init queue spin lock */ + spin_lock_init(>lock); + } + + return 0; + +pending_qfail: + free_pending_queues(pqinfo); + + return ret; +} + +static int init_pending_queues(struct cpt_vf *cptvf, u32 qlen, u32 nr_queues) +{ + struct pci_dev *pdev = cptvf->pdev; + int ret; + + if (!nr_queues) + return 0; + + ret = alloc_pending_queues(>pqinfo, qlen, nr_queues); + if (ret) { + dev_err(>dev, "failed to setup pending queues (%u)\n", + nr_queues); + return ret; + } + + return 0; +} + +static void cleanup_pending_queues(struct cpt_vf *cptvf) +{ + struct pci_dev *pdev = cptvf->pdev; + + if (!cptvf->nr_queues) + return; + + dev_info(>dev, "Cleaning VQ pending queue (%u)\n", +cptvf->nr_queues); + free_pending_queues(>pqinfo); +} + +static void free_command_queues(struct cpt_vf *cptvf, + struct command_qinfo *cqinfo) +{ + int i, j; + struct command_queue *queue = NULL; + struct command_chunk *chunk = NULL, *next = NULL; + struct pci_dev *pdev = cptvf->pdev; + struct
Re: [PATCH v5 2/3] drivers: crypto: Add the Virtual Function driver for CPT
On Mon, Jan 30, 2017 at 7:30 AM, George Cherianwrote: > diff --git a/drivers/crypto/cavium/cpt/cptvf_main.c > b/drivers/crypto/cavium/cpt/cptvf_main.c > new file mode 100644 > index 000..4cf466d > --- /dev/null > +++ b/drivers/crypto/cavium/cpt/cptvf_main.c > @@ -0,0 +1,948 @@ > +/* > + * Copyright (C) 2016 Cavium, Inc. > + * > + * This program is free software; you can redistribute it and/or modify > + * it under the terms of version 2 of the GNU General Public License > + * as published by the Free Software Foundation. > + */ > + > +#include > +#include > + > +#include "cptvf.h" > + > +#define DRV_NAME "thunder-cptvf" > +#define DRV_VERSION"1.0" > + > +struct cptvf_wqe { > + struct tasklet_struct twork; > + void *cptvf; > + u32 qno; > +}; > + > +struct cptvf_wqe_info { > + struct cptvf_wqe vq_wqe[CPT_NUM_QS_PER_VF]; > +}; > + > +static void vq_work_handler(unsigned long data) > +{ > + struct cptvf_wqe_info *cwqe_info = (struct cptvf_wqe_info *)data; > + struct cptvf_wqe *cwqe = _info->vq_wqe[0]; > + > + vq_post_process(cwqe->cptvf, cwqe->qno); > +} > + > +static int init_worker_threads(struct cpt_vf *cptvf) > +{ > + struct pci_dev *pdev = cptvf->pdev; > + struct cptvf_wqe_info *cwqe_info; > + int i; > + > + cwqe_info = kzalloc(sizeof(*cwqe_info), GFP_KERNEL); > + if (!cwqe_info) > + return -ENOMEM; > + > + if (cptvf->nr_queues) { > + dev_info(>dev, "Creating VQ worker threads (%d)\n", > +cptvf->nr_queues); > + } > + > + for (i = 0; i < cptvf->nr_queues; i++) { > + tasklet_init(_info->vq_wqe[i].twork, vq_work_handler, > +(u64)cwqe_info); > + cwqe_info->vq_wqe[i].qno = i; > + cwqe_info->vq_wqe[i].cptvf = cptvf; > + } > + > + cptvf->wqe_info = cwqe_info; > + > + return 0; > +} > + > +static void cleanup_worker_threads(struct cpt_vf *cptvf) > +{ > + struct cptvf_wqe_info *cwqe_info; > + struct pci_dev *pdev = cptvf->pdev; > + int i; > + > + cwqe_info = (struct cptvf_wqe_info *)cptvf->wqe_info; > + if (!cwqe_info) > + return; > + > + if (cptvf->nr_queues) { > + dev_info(>dev, "Cleaning VQ worker threads (%u)\n", > +cptvf->nr_queues); > + } > + > + for (i = 0; i < cptvf->nr_queues; i++) > + tasklet_kill(_info->vq_wqe[i].twork); > + > + kzfree(cwqe_info); > + cptvf->wqe_info = NULL; > +} > + > +static void free_pending_queues(struct pending_qinfo *pqinfo) > +{ > + int i; > + struct pending_queue *queue; > + > + for_each_pending_queue(pqinfo, queue, i) { > + if (!queue->head) > + continue; > + > + /* free single queue */ > + kzfree((queue->head)); > + > + queue->front = 0; > + queue->rear = 0; > + > + return; > + } > + > + pqinfo->qlen = 0; > + pqinfo->nr_queues = 0; > +} > + > +static int alloc_pending_queues(struct pending_qinfo *pqinfo, u32 qlen, > + u32 nr_queues) > +{ > + u32 i; > + size_t size; > + int ret; > + struct pending_queue *queue = NULL; > + > + pqinfo->nr_queues = nr_queues; > + pqinfo->qlen = qlen; > + > + size = (qlen * sizeof(struct pending_entry)); > + > + for_each_pending_queue(pqinfo, queue, i) { > + queue->head = kzalloc((size), GFP_KERNEL); > + if (!queue->head) { > + ret = -ENOMEM; > + goto pending_qfail; > + } > + > + queue->front = 0; > + queue->rear = 0; > + atomic64_set((>pending_count), (0)); > + > + /* init queue spin lock */ > + spin_lock_init(>lock); > + } > + > + return 0; > + > +pending_qfail: > + free_pending_queues(pqinfo); > + > + return ret; > +} > + > +static int init_pending_queues(struct cpt_vf *cptvf, u32 qlen, u32 nr_queues) > +{ > + struct pci_dev *pdev = cptvf->pdev; > + int ret; > + > + if (!nr_queues) > + return 0; > + > + ret = alloc_pending_queues(>pqinfo, qlen, nr_queues); > + if (ret) { > + dev_err(>dev, "failed to setup pending queues (%u)\n", > + nr_queues); > + return ret; > + } > + > + return 0; > +} > + > +static void cleanup_pending_queues(struct cpt_vf *cptvf) > +{ > + struct pci_dev *pdev = cptvf->pdev; > + > + if (!cptvf->nr_queues) > + return; > + > + dev_info(>dev, "Cleaning VQ pending queue (%u)\n", > +cptvf->nr_queues); > + free_pending_queues(>pqinfo); > +} > + > +static void free_command_queues(struct
[PATCH v5 2/3] drivers: crypto: Add the Virtual Function driver for CPT
Enable the CPT VF driver. CPT is the cryptographic Acceleration Unit in Octeon-tx series of processors. Signed-off-by: George CherianReviewed-by: David Daney --- drivers/crypto/cavium/cpt/Makefile | 3 +- drivers/crypto/cavium/cpt/cptvf.h| 135 drivers/crypto/cavium/cpt/cptvf_algs.c | 444 + drivers/crypto/cavium/cpt/cptvf_algs.h | 113 drivers/crypto/cavium/cpt/cptvf_main.c | 948 +++ drivers/crypto/cavium/cpt/cptvf_mbox.c | 211 ++ drivers/crypto/cavium/cpt/cptvf_reqmanager.c | 593 + drivers/crypto/cavium/cpt/request_manager.h | 147 + 8 files changed, 2593 insertions(+), 1 deletion(-) create mode 100644 drivers/crypto/cavium/cpt/cptvf.h create mode 100644 drivers/crypto/cavium/cpt/cptvf_algs.c create mode 100644 drivers/crypto/cavium/cpt/cptvf_algs.h create mode 100644 drivers/crypto/cavium/cpt/cptvf_main.c create mode 100644 drivers/crypto/cavium/cpt/cptvf_mbox.c create mode 100644 drivers/crypto/cavium/cpt/cptvf_reqmanager.c create mode 100644 drivers/crypto/cavium/cpt/request_manager.h diff --git a/drivers/crypto/cavium/cpt/Makefile b/drivers/crypto/cavium/cpt/Makefile index fe3d454..dbf055e 100644 --- a/drivers/crypto/cavium/cpt/Makefile +++ b/drivers/crypto/cavium/cpt/Makefile @@ -1,2 +1,3 @@ -obj-$(CONFIG_CAVIUM_CPT) += cptpf.o +obj-$(CONFIG_CAVIUM_CPT) += cptpf.o cptvf.o cptpf-objs := cptpf_main.o cptpf_mbox.o +cptvf-objs := cptvf_main.o cptvf_reqmanager.o cptvf_mbox.o cptvf_algs.o diff --git a/drivers/crypto/cavium/cpt/cptvf.h b/drivers/crypto/cavium/cpt/cptvf.h new file mode 100644 index 000..1cc04aa --- /dev/null +++ b/drivers/crypto/cavium/cpt/cptvf.h @@ -0,0 +1,135 @@ +/* + * Copyright (C) 2016 Cavium, Inc. + * + * This program is free software; you can redistribute it and/or modify it + * under the terms of version 2 of the GNU General Public License + * as published by the Free Software Foundation. + */ + +#ifndef __CPTVF_H +#define __CPTVF_H + +#include +#include "cpt_common.h" + +/* Default command queue length */ +#define CPT_CMD_QLEN 2046 +#define CPT_CMD_QCHUNK_SIZE 1023 + +/* Default command timeout in seconds */ +#define CPT_COMMAND_TIMEOUT 4 +#define CPT_TIMER_THOLD0x +#define CPT_NUM_QS_PER_VF 1 +#define CPT_INST_SIZE 64 +#define CPT_NEXT_CHUNK_PTR_SIZE 8 + +#defineCPT_VF_MSIX_VECTORS 2 +#define CPT_VF_INTR_MBOX_MASK BIT(0) +#define CPT_VF_INTR_DOVF_MASK BIT(1) +#define CPT_VF_INTR_IRDE_MASK BIT(2) +#define CPT_VF_INTR_NWRP_MASK BIT(3) +#define CPT_VF_INTR_SERR_MASK BIT(4) +#define DMA_DIRECT_DIRECT 0 /* Input DIRECT, Output DIRECT */ +#define DMA_GATHER_SCATTER 1 +#define FROM_DPTR 1 + +/** + * Enumeration cpt_vf_int_vec_e + * + * CPT VF MSI-X Vector Enumeration + * Enumerates the MSI-X interrupt vectors. + */ +enum cpt_vf_int_vec_e { + CPT_VF_INT_VEC_E_MISC = 0x00, + CPT_VF_INT_VEC_E_DONE = 0x01 +}; + +struct command_chunk { + u8 *head; + dma_addr_t dma_addr; + u32 size; /* Chunk size, max CPT_INST_CHUNK_MAX_SIZE */ + struct hlist_node nextchunk; +}; + +struct command_queue { + spinlock_t lock; /* command queue lock */ + u32 idx; /* Command queue host write idx */ + u32 nchunks; /* Number of command chunks */ + struct command_chunk *qhead;/* Command queue head, instructions +* are inserted here +*/ + struct hlist_head chead; +}; + +struct command_qinfo { + u32 cmd_size; + u32 qchunksize; /* Command queue chunk size */ + struct command_queue queue[CPT_NUM_QS_PER_VF]; +}; + +struct pending_entry { + u8 busy; /* Entry status (free/busy) */ + + volatile u64 *completion_addr; /* Completion address */ + void *post_arg; + void (*callback)(int, void *); /* Kernel ASYNC request callabck */ + void *callback_arg; /* Kernel ASYNC request callabck arg */ +}; + +struct pending_queue { + struct pending_entry *head; /* head of the queue */ + u32 front; /* Process work from here */ + u32 rear; /* Append new work here */ + atomic64_t pending_count; + spinlock_t lock; /* Queue lock */ +}; + +struct pending_qinfo { + u32 nr_queues; /* Number of queues supported */ + u32 qlen; /* Queue length */ + struct pending_queue queue[CPT_NUM_QS_PER_VF]; +}; + +#define for_each_pending_queue(qinfo, q, i)\ + for (i = 0, q = >queue[i]; i < qinfo->nr_queues; i++, \ +q = >queue[i]) + +struct cpt_vf { + u16 flags; /* Flags to hold device status bits */ + u8 vfid; /* Device Index 0...CPT_MAX_VF_NUM */ + u8 vftype; /* VF type of SE_TYPE(1) or AE_TYPE(1) */ + u8 vfgrp; /* VF group (0 - 8) */ + u8 node; /* Operating node: Bits (46:44) in BAR0 address */ + u8 priority; /* VF priority ring: 1-High proirity