Re: [PATCH v5 2/3] drivers: crypto: Add the Virtual Function driver for CPT

2017-02-03 Thread George Cherian

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 Cherian
 wrote:

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

2017-02-02 Thread Sasha Levin
On Mon, Jan 30, 2017 at 7:30 AM, George Cherian
 wrote:
> 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

2017-01-30 Thread George Cherian
Enable the CPT VF driver. CPT is the cryptographic Acceleration Unit
in Octeon-tx series of processors.

Signed-off-by: George Cherian 
Reviewed-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