sleep in control plane thread
[dpdk.git] / drivers / crypto / caam_jr / caam_jr_hw.c
1 /* SPDX-License-Identifier: BSD-3-Clause
2  * Copyright 2017-2018 NXP
3  */
4
5 #include <fcntl.h>
6 #include <unistd.h>
7 #include <inttypes.h>
8 #include <rte_common.h>
9 #include <rte_memory.h>
10 #include <rte_malloc.h>
11 #include <rte_crypto.h>
12 #include <rte_security.h>
13
14 #include <caam_jr_config.h>
15 #include <caam_jr_hw_specific.h>
16 #include <caam_jr_pvt.h>
17 #include <caam_jr_log.h>
18
19 /* Used to retry resetting a job ring in SEC hardware. */
20 #define SEC_TIMEOUT 100000
21
22 /* @brief Process Jump Halt Condition related errors
23  *
24  * @param [in]  error_code        The error code in the descriptor status word
25  */
26 static inline void
27 hw_handle_jmp_halt_cond_err(union hw_error_code error_code)
28 {
29         CAAM_JR_DEBUG("JMP: %d, Descriptor Index: 0x%x, Condition: 0x%x",
30                         error_code.error_desc.jmp_halt_cond_src.jmp,
31                         error_code.error_desc.jmp_halt_cond_src.desc_idx,
32                         error_code.error_desc.jmp_halt_cond_src.cond);
33         (void)error_code;
34 }
35
36 /* @brief Process DECO related errors
37  *
38  * @param [in]  error_code        The error code in the descriptor status word
39  */
40 static inline void
41 hw_handle_deco_err(union hw_error_code error_code)
42 {
43         CAAM_JR_DEBUG("JMP: %d, Descriptor Index: 0x%x",
44                         error_code.error_desc.deco_src.jmp,
45                         error_code.error_desc.deco_src.desc_idx);
46
47         switch (error_code.error_desc.deco_src.desc_err) {
48         case SEC_HW_ERR_DECO_HFN_THRESHOLD:
49                 CAAM_JR_DEBUG(" Warning: Descriptor completed normally,"
50                         "but 3GPP HFN matches or exceeds the Threshold ");
51                 break;
52         default:
53                 CAAM_JR_DEBUG("Error 0x%04x not implemented",
54                                 error_code.error_desc.deco_src.desc_err);
55                 break;
56         }
57 }
58
59 /* @brief Process  Jump Halt User Status related errors
60  *
61  * @param [in]  error_code        The error code in the descriptor status word
62  */
63 static inline void
64 hw_handle_jmp_halt_user_err(union hw_error_code error_code __rte_unused)
65 {
66         CAAM_JR_DEBUG(" Not implemented");
67 }
68
69 /* @brief Process CCB related errors
70  *
71  * @param [in]  error_code        The error code in the descriptor status word
72  */
73 static inline void
74 hw_handle_ccb_err(union hw_error_code hw_error_code __rte_unused)
75 {
76         CAAM_JR_DEBUG(" Not implemented");
77 }
78
79 /* @brief Process Job Ring related errors
80  *
81  * @param [in]  error_code        The error code in the descriptor status word
82  */
83 static inline void
84 hw_handle_jr_err(union hw_error_code hw_error_code __rte_unused)
85 {
86         CAAM_JR_DEBUG(" Not implemented");
87 }
88
89 int
90 hw_reset_job_ring(struct sec_job_ring_t *job_ring)
91 {
92         int ret = 0;
93
94         ASSERT(job_ring->register_base_addr != NULL);
95
96         /* First reset the job ring in hw */
97         ret = hw_shutdown_job_ring(job_ring);
98         SEC_ASSERT(ret == 0, ret, "Failed resetting job ring in hardware");
99
100         /* In order to have the HW JR in a workable state
101          * after a reset, I need to re-write the input
102          * queue size, input start address, output queue
103          * size and output start address
104          */
105         /* Write the JR input queue size to the HW register */
106         hw_set_input_ring_size(job_ring, SEC_JOB_RING_SIZE);
107
108         /* Write the JR output queue size to the HW register */
109         hw_set_output_ring_size(job_ring, SEC_JOB_RING_SIZE);
110
111         /* Write the JR input queue start address */
112         hw_set_input_ring_start_addr(job_ring,
113                         caam_jr_dma_vtop(job_ring->input_ring));
114         CAAM_JR_DEBUG(" Set input ring base address to : Virtual: 0x%" PRIx64
115                       ",Physical: 0x%" PRIx64 ", Read from HW: 0x%" PRIx64,
116                       (uint64_t)(uintptr_t)job_ring->input_ring,
117                       caam_jr_dma_vtop(job_ring->input_ring),
118                       hw_get_inp_queue_base(job_ring));
119
120         /* Write the JR output queue start address */
121         hw_set_output_ring_start_addr(job_ring,
122                         caam_jr_dma_vtop(job_ring->output_ring));
123         CAAM_JR_DEBUG(" Set output ring base address to: Virtual: 0x%" PRIx64
124                       ",Physical: 0x%" PRIx64 ", Read from HW: 0x%" PRIx64,
125                       (uint64_t)(uintptr_t)job_ring->output_ring,
126                       caam_jr_dma_vtop(job_ring->output_ring),
127                       hw_get_out_queue_base(job_ring));
128         return ret;
129 }
130
131 int
132 hw_shutdown_job_ring(struct sec_job_ring_t *job_ring)
133 {
134         unsigned int timeout = SEC_TIMEOUT;
135         uint32_t tmp = 0;
136         int usleep_interval = 10;
137
138         if (job_ring->register_base_addr == NULL) {
139                 CAAM_JR_ERR("Jr[%p] has reg base addr as NULL.driver not init",
140                         job_ring);
141                 return 0;
142         }
143
144         CAAM_JR_INFO("Resetting Job ring %p", job_ring);
145
146         /*
147          * Mask interrupts since we are going to poll
148          * for reset completion status
149          * Also, at POR, interrupts are ENABLED on a JR, thus
150          * this is the point where I can disable them without
151          * changing the code logic too much
152          */
153         caam_jr_disable_irqs(job_ring->irq_fd);
154
155         /* initiate flush (required prior to reset) */
156         SET_JR_REG(JRCR, job_ring, JR_REG_JRCR_VAL_RESET);
157
158         /* dummy read */
159         tmp = GET_JR_REG(JRCR, job_ring);
160
161         do {
162                 tmp = GET_JR_REG(JRINT, job_ring);
163                 usleep(usleep_interval);
164         } while (((tmp & JRINT_ERR_HALT_MASK) ==
165                         JRINT_ERR_HALT_INPROGRESS) && --timeout);
166
167         CAAM_JR_INFO("JRINT is %x", tmp);
168         if ((tmp & JRINT_ERR_HALT_MASK) != JRINT_ERR_HALT_COMPLETE ||
169                 timeout == 0) {
170                 CAAM_JR_ERR("0x%x, %d", tmp, timeout);
171                 /* unmask interrupts */
172                 if (job_ring->jr_mode != SEC_NOTIFICATION_TYPE_POLL)
173                         caam_jr_enable_irqs(job_ring->irq_fd);
174                 return -1;
175         }
176
177         /* Initiate reset */
178         timeout = SEC_TIMEOUT;
179         SET_JR_REG(JRCR, job_ring, JR_REG_JRCR_VAL_RESET);
180
181         do {
182                 tmp = GET_JR_REG(JRCR, job_ring);
183                 usleep(usleep_interval);
184         } while ((tmp & JR_REG_JRCR_VAL_RESET) && --timeout);
185
186         CAAM_JR_DEBUG("JRCR is %x", tmp);
187         if (timeout == 0) {
188                 CAAM_JR_ERR("Failed to reset hw job ring %p", job_ring);
189                 /* unmask interrupts */
190                 if (job_ring->jr_mode != SEC_NOTIFICATION_TYPE_POLL)
191                         caam_jr_enable_irqs(job_ring->irq_fd);
192                 return -1;
193         }
194         /* unmask interrupts */
195         if (job_ring->jr_mode != SEC_NOTIFICATION_TYPE_POLL)
196                 caam_jr_enable_irqs(job_ring->irq_fd);
197         return 0;
198
199 }
200
201 void
202 hw_handle_job_ring_error(struct sec_job_ring_t *job_ring __rte_unused,
203                          uint32_t error_code)
204 {
205         union hw_error_code hw_err_code;
206
207         hw_err_code.error = error_code;
208         switch (hw_err_code.error_desc.value.ssrc) {
209         case SEC_HW_ERR_SSRC_NO_SRC:
210                 ASSERT(hw_err_code.error_desc.no_status_src.res == 0);
211                 CAAM_JR_ERR("No Status Source ");
212                 break;
213         case SEC_HW_ERR_SSRC_CCB_ERR:
214                 CAAM_JR_ERR("CCB Status Source");
215                 hw_handle_ccb_err(hw_err_code);
216                 break;
217         case SEC_HW_ERR_SSRC_JMP_HALT_U:
218                 CAAM_JR_ERR("Jump Halt User Status Source");
219                 hw_handle_jmp_halt_user_err(hw_err_code);
220                 break;
221         case SEC_HW_ERR_SSRC_DECO:
222                 CAAM_JR_ERR("DECO Status Source");
223                 hw_handle_deco_err(hw_err_code);
224                 break;
225         case SEC_HW_ERR_SSRC_JR:
226                 CAAM_JR_ERR("Job Ring Status Source");
227                 hw_handle_jr_err(hw_err_code);
228                 break;
229         case SEC_HW_ERR_SSRC_JMP_HALT_COND:
230                 CAAM_JR_ERR("Jump Halt Condition Codes");
231                 hw_handle_jmp_halt_cond_err(hw_err_code);
232                 break;
233         default:
234                 ASSERT(0);
235                 CAAM_JR_ERR("Unknown SSRC");
236                 break;
237         }
238 }
239
240 void
241 hw_job_ring_error_print(struct sec_job_ring_t *job_ring, int code)
242 {
243         switch (code) {
244         case JRINT_ERR_WRITE_STATUS:
245                 CAAM_JR_ERR("Error writing status to Output Ring ");
246                 break;
247         case JRINT_ERR_BAD_INPUT_BASE:
248                 CAAM_JR_ERR(
249                 "Bad Input Ring Base (%p) (not on a 4-byte boundary) ",
250                 (void *)job_ring);
251                 break;
252         case JRINT_ERR_BAD_OUTPUT_BASE:
253                 CAAM_JR_ERR(
254                 "Bad Output Ring Base (%p) (not on a 4-byte boundary) ",
255                 (void *)job_ring);
256                 break;
257         case JRINT_ERR_WRITE_2_IRBA:
258                 CAAM_JR_ERR(
259                 "Invalid write to Input Ring Base Address Register ");
260                 break;
261         case JRINT_ERR_WRITE_2_ORBA:
262                 CAAM_JR_ERR(
263                 "Invalid write to Output Ring Base Address Register ");
264                 break;
265         case JRINT_ERR_RES_B4_HALT:
266                 CAAM_JR_ERR(
267                 "Job Ring [%p] released before Job Ring is halted",
268                 (void *)job_ring);
269                 break;
270         case JRINT_ERR_REM_TOO_MANY:
271                 CAAM_JR_ERR("Removed too many jobs from job ring [%p]",
272                         (void *)job_ring);
273                 break;
274         case JRINT_ERR_ADD_TOO_MANY:
275                 CAAM_JR_ERR("Added too many jobs on job ring [%p]", job_ring);
276                 break;
277         default:
278                 CAAM_JR_ERR(" Unknown SEC JR Error :%d",
279                                 code);
280                 break;
281         }
282 }
283
284 int
285 hw_job_ring_set_coalescing_param(struct sec_job_ring_t *job_ring,
286                                  uint16_t irq_coalescing_timer,
287                                  uint8_t irq_coalescing_count)
288 {
289         uint32_t reg_val = 0;
290
291         ASSERT(job_ring != NULL);
292         if (job_ring->register_base_addr == NULL) {
293                 CAAM_JR_ERR("Jr[%p] has reg base addr as NULL.driver not init",
294                         job_ring);
295                 return -1;
296         }
297         /* Set descriptor count coalescing */
298         reg_val |= (irq_coalescing_count << JR_REG_JRCFG_LO_ICDCT_SHIFT);
299
300         /* Set coalescing timer value */
301         reg_val |= (irq_coalescing_timer << JR_REG_JRCFG_LO_ICTT_SHIFT);
302
303         /* Update parameters in HW */
304         SET_JR_REG_LO(JRCFG, job_ring, reg_val);
305         CAAM_JR_DEBUG("Set coalescing params on jr %p timer:%d, desc count: %d",
306                         job_ring, irq_coalescing_timer, irq_coalescing_timer);
307
308         return 0;
309 }
310
311 int
312 hw_job_ring_enable_coalescing(struct sec_job_ring_t *job_ring)
313 {
314         uint32_t reg_val = 0;
315
316         ASSERT(job_ring != NULL);
317         if (job_ring->register_base_addr == NULL) {
318                 CAAM_JR_ERR("Jr[%p] has reg base addr as NULL.driver not init",
319                         job_ring);
320                 return -1;
321         }
322
323         /* Get the current value of the register */
324         reg_val = GET_JR_REG_LO(JRCFG, job_ring);
325
326         /* Enable coalescing */
327         reg_val |= JR_REG_JRCFG_LO_ICEN_EN;
328
329         /* Write in hw */
330         SET_JR_REG_LO(JRCFG, job_ring, reg_val);
331
332         CAAM_JR_DEBUG("Enabled coalescing on jr %p ",
333                         job_ring);
334
335         return 0;
336 }
337
338 int
339 hw_job_ring_disable_coalescing(struct sec_job_ring_t *job_ring)
340 {
341         uint32_t reg_val = 0;
342
343         ASSERT(job_ring != NULL);
344
345         if (job_ring->register_base_addr == NULL) {
346                 CAAM_JR_ERR("Jr[%p] has reg base addr as NULL.driver not init",
347                         job_ring);
348                 return -1;
349         }
350
351         /* Get the current value of the register */
352         reg_val = GET_JR_REG_LO(JRCFG, job_ring);
353
354         /* Disable coalescing */
355         reg_val &= ~JR_REG_JRCFG_LO_ICEN_EN;
356
357         /* Write in hw */
358         SET_JR_REG_LO(JRCFG, job_ring, reg_val);
359         CAAM_JR_DEBUG("Disabled coalescing on jr %p ", job_ring);
360
361         return 0;
362 }