drm/nouveau/disp/gm200-: enforce identity-mapped SOR assignment for LVDS/eDP panels
[linux-2.6-microblaze.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 /* command queue alignments */
21 #define PKT_IN_ALIGN    16
22
23 static int cmdq_common_init(struct nitrox_cmdq *cmdq)
24 {
25         struct nitrox_device *ndev = cmdq->ndev;
26         u32 qsize;
27
28         qsize = (ndev->qlen) * cmdq->instr_size;
29         cmdq->head_unaligned = dma_zalloc_coherent(DEV(ndev),
30                                                    (qsize + PKT_IN_ALIGN),
31                                                    &cmdq->dma_unaligned,
32                                                    GFP_KERNEL);
33         if (!cmdq->head_unaligned)
34                 return -ENOMEM;
35
36         cmdq->head = PTR_ALIGN(cmdq->head_unaligned, PKT_IN_ALIGN);
37         cmdq->dma = PTR_ALIGN(cmdq->dma_unaligned, PKT_IN_ALIGN);
38         cmdq->qsize = (qsize + PKT_IN_ALIGN);
39
40         spin_lock_init(&cmdq->response_lock);
41         spin_lock_init(&cmdq->cmdq_lock);
42         spin_lock_init(&cmdq->backlog_lock);
43
44         INIT_LIST_HEAD(&cmdq->response_head);
45         INIT_LIST_HEAD(&cmdq->backlog_head);
46         INIT_WORK(&cmdq->backlog_qflush, backlog_qflush_work);
47
48         atomic_set(&cmdq->pending_count, 0);
49         atomic_set(&cmdq->backlog_count, 0);
50         return 0;
51 }
52
53 static void cmdq_common_cleanup(struct nitrox_cmdq *cmdq)
54 {
55         struct nitrox_device *ndev = cmdq->ndev;
56
57         cancel_work_sync(&cmdq->backlog_qflush);
58
59         dma_free_coherent(DEV(ndev), cmdq->qsize,
60                           cmdq->head_unaligned, cmdq->dma_unaligned);
61
62         atomic_set(&cmdq->pending_count, 0);
63         atomic_set(&cmdq->backlog_count, 0);
64
65         cmdq->dbell_csr_addr = NULL;
66         cmdq->head = NULL;
67         cmdq->dma = 0;
68         cmdq->qsize = 0;
69         cmdq->instr_size = 0;
70 }
71
72 static void nitrox_cleanup_pkt_cmdqs(struct nitrox_device *ndev)
73 {
74         int i;
75
76         for (i = 0; i < ndev->nr_queues; i++) {
77                 struct nitrox_cmdq *cmdq = &ndev->pkt_cmdqs[i];
78
79                 cmdq_common_cleanup(cmdq);
80         }
81         kfree(ndev->pkt_cmdqs);
82         ndev->pkt_cmdqs = NULL;
83 }
84
85 static int nitrox_init_pkt_cmdqs(struct nitrox_device *ndev)
86 {
87         int i, err, size;
88
89         size = ndev->nr_queues * sizeof(struct nitrox_cmdq);
90         ndev->pkt_cmdqs = kzalloc(size, GFP_KERNEL);
91         if (!ndev->pkt_cmdqs)
92                 return -ENOMEM;
93
94         for (i = 0; i < ndev->nr_queues; i++) {
95                 struct nitrox_cmdq *cmdq;
96                 u64 offset;
97
98                 cmdq = &ndev->pkt_cmdqs[i];
99                 cmdq->ndev = ndev;
100                 cmdq->qno = i;
101                 cmdq->instr_size = sizeof(struct nps_pkt_instr);
102
103                 offset = NPS_PKT_IN_INSTR_BAOFF_DBELLX(i);
104                 /* SE ring doorbell address for this queue */
105                 cmdq->dbell_csr_addr = NITROX_CSR_ADDR(ndev, offset);
106
107                 err = cmdq_common_init(cmdq);
108                 if (err)
109                         goto pkt_cmdq_fail;
110         }
111         return 0;
112
113 pkt_cmdq_fail:
114         nitrox_cleanup_pkt_cmdqs(ndev);
115         return err;
116 }
117
118 static int create_crypto_dma_pool(struct nitrox_device *ndev)
119 {
120         size_t size;
121
122         /* Crypto context pool, 16 byte aligned */
123         size = CRYPTO_CTX_SIZE + sizeof(struct ctx_hdr);
124         ndev->ctx_pool = dma_pool_create("crypto-context",
125                                          DEV(ndev), size, 16, 0);
126         if (!ndev->ctx_pool)
127                 return -ENOMEM;
128
129         return 0;
130 }
131
132 static void destroy_crypto_dma_pool(struct nitrox_device *ndev)
133 {
134         if (!ndev->ctx_pool)
135                 return;
136
137         dma_pool_destroy(ndev->ctx_pool);
138         ndev->ctx_pool = NULL;
139 }
140
141 /*
142  * crypto_alloc_context - Allocate crypto context from pool
143  * @ndev: NITROX Device
144  */
145 void *crypto_alloc_context(struct nitrox_device *ndev)
146 {
147         struct ctx_hdr *ctx;
148         void *vaddr;
149         dma_addr_t dma;
150
151         vaddr = dma_pool_alloc(ndev->ctx_pool, (GFP_KERNEL | __GFP_ZERO), &dma);
152         if (!vaddr)
153                 return NULL;
154
155         /* fill meta data */
156         ctx = vaddr;
157         ctx->pool = ndev->ctx_pool;
158         ctx->dma = dma;
159         ctx->ctx_dma = dma + sizeof(struct ctx_hdr);
160
161         return ((u8 *)vaddr + sizeof(struct ctx_hdr));
162 }
163
164 /**
165  * crypto_free_context - Free crypto context to pool
166  * @ctx: context to free
167  */
168 void crypto_free_context(void *ctx)
169 {
170         struct ctx_hdr *ctxp;
171
172         if (!ctx)
173                 return;
174
175         ctxp = (struct ctx_hdr *)((u8 *)ctx - sizeof(struct ctx_hdr));
176         dma_pool_free(ctxp->pool, ctxp, ctxp->dma);
177 }
178
179 /**
180  * nitrox_common_sw_init - allocate software resources.
181  * @ndev: NITROX device
182  *
183  * Allocates crypto context pools and command queues etc.
184  *
185  * Return: 0 on success, or a negative error code on error.
186  */
187 int nitrox_common_sw_init(struct nitrox_device *ndev)
188 {
189         int err = 0;
190
191         /* per device crypto context pool */
192         err = create_crypto_dma_pool(ndev);
193         if (err)
194                 return err;
195
196         err = nitrox_init_pkt_cmdqs(ndev);
197         if (err)
198                 destroy_crypto_dma_pool(ndev);
199
200         return err;
201 }
202
203 /**
204  * nitrox_common_sw_cleanup - free software resources.
205  * @ndev: NITROX device
206  */
207 void nitrox_common_sw_cleanup(struct nitrox_device *ndev)
208 {
209         nitrox_cleanup_pkt_cmdqs(ndev);
210         destroy_crypto_dma_pool(ndev);
211 }