Merge branch 'for-linus' of git://git.kernel.org/pub/scm/linux/kernel/git/ebiederm...
[sfrench/cifs-2.6.git] / drivers / crypto / cavium / nitrox / nitrox_lib.c
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
23 static 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
51 static 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
58 static 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
81 static 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
94 static 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
126 pktq_fail:
127         nitrox_free_pktin_queues(ndev);
128         return err;
129 }
130
131 static 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
145 static 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  */
158 void *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  */
192 void 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  */
212 int 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  */
232 void nitrox_common_sw_cleanup(struct nitrox_device *ndev)
233 {
234         nitrox_free_pktin_queues(ndev);
235         destroy_crypto_dma_pool(ndev);
236 }