1 /* SPDX-License-Identifier: BSD-3-Clause
2 * Copyright 2017-2018 NXP
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>
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>
19 /* RTA header files */
20 #include <hw/desc/common.h>
21 #include <hw/desc/algo.h>
22 #include <hw/desc/ipsec.h>
24 /* Used to retry resetting a job ring in SEC hardware. */
25 #define SEC_TIMEOUT 100000
27 /* @brief Process Jump Halt Condition related errors
29 * @param [in] error_code The error code in the descriptor status word
32 hw_handle_jmp_halt_cond_err(union hw_error_code error_code)
34 CAAM_JR_DEBUG("JMP: %d, Descriptor Index: 0x%x, Condition: 0x%x",
35 error_code.error_desc.jmp_halt_cond_src.jmp,
36 error_code.error_desc.jmp_halt_cond_src.desc_idx,
37 error_code.error_desc.jmp_halt_cond_src.cond);
41 /* @brief Process DECO related errors
43 * @param [in] error_code The error code in the descriptor status word
46 hw_handle_deco_err(union hw_error_code error_code)
48 CAAM_JR_DEBUG("JMP: %d, Descriptor Index: 0x%x",
49 error_code.error_desc.deco_src.jmp,
50 error_code.error_desc.deco_src.desc_idx);
52 switch (error_code.error_desc.deco_src.desc_err) {
53 case SEC_HW_ERR_DECO_HFN_THRESHOLD:
54 CAAM_JR_DEBUG(" Warning: Descriptor completed normally,"
55 "but 3GPP HFN matches or exceeds the Threshold ");
58 CAAM_JR_DEBUG("Error 0x%04x not implemented",
59 error_code.error_desc.deco_src.desc_err);
64 /* @brief Process Jump Halt User Status related errors
66 * @param [in] error_code The error code in the descriptor status word
69 hw_handle_jmp_halt_user_err(union hw_error_code error_code __rte_unused)
71 CAAM_JR_DEBUG(" Not implemented");
74 /* @brief Process CCB related errors
76 * @param [in] error_code The error code in the descriptor status word
79 hw_handle_ccb_err(union hw_error_code hw_error_code __rte_unused)
81 CAAM_JR_DEBUG(" Not implemented");
84 /* @brief Process Job Ring related errors
86 * @param [in] error_code The error code in the descriptor status word
89 hw_handle_jr_err(union hw_error_code hw_error_code __rte_unused)
91 CAAM_JR_DEBUG(" Not implemented");
95 caam_jr_enable_irqs(uint32_t uio_fd __rte_unused)
101 caam_jr_disable_irqs(uint32_t uio_fd __rte_unused)
107 hw_reset_job_ring(struct sec_job_ring_t *job_ring)
111 ASSERT(job_ring->register_base_addr != NULL);
113 /* First reset the job ring in hw */
114 ret = hw_shutdown_job_ring(job_ring);
115 SEC_ASSERT(ret == 0, ret, "Failed resetting job ring in hardware");
117 /* In order to have the HW JR in a workable state
118 * after a reset, I need to re-write the input
119 * queue size, input start address, output queue
120 * size and output start address
122 /* Write the JR input queue size to the HW register */
123 hw_set_input_ring_size(job_ring, SEC_JOB_RING_SIZE);
125 /* Write the JR output queue size to the HW register */
126 hw_set_output_ring_size(job_ring, SEC_JOB_RING_SIZE);
128 /* Write the JR input queue start address */
129 hw_set_input_ring_start_addr(job_ring,
130 caam_jr_dma_vtop(job_ring->input_ring));
131 CAAM_JR_DEBUG(" Set input ring base address to : Virtual: 0x%" PRIx64
132 ",Physical: 0x%" PRIx64 ", Read from HW: 0x%" PRIx64,
133 (uint64_t)(uintptr_t)job_ring->input_ring,
134 caam_jr_dma_vtop(job_ring->input_ring),
135 hw_get_inp_queue_base(job_ring));
137 /* Write the JR output queue start address */
138 hw_set_output_ring_start_addr(job_ring,
139 caam_jr_dma_vtop(job_ring->output_ring));
140 CAAM_JR_DEBUG(" Set output ring base address to: Virtual: 0x%" PRIx64
141 ",Physical: 0x%" PRIx64 ", Read from HW: 0x%" PRIx64,
142 (uint64_t)(uintptr_t)job_ring->output_ring,
143 caam_jr_dma_vtop(job_ring->output_ring),
144 hw_get_out_queue_base(job_ring));
149 hw_shutdown_job_ring(struct sec_job_ring_t *job_ring)
151 unsigned int timeout = SEC_TIMEOUT;
153 int usleep_interval = 10;
155 if (job_ring->register_base_addr == NULL) {
156 CAAM_JR_ERR("Jr[%p] has reg base addr as NULL.driver not init",
161 CAAM_JR_INFO("Resetting Job ring %p", job_ring);
164 * Mask interrupts since we are going to poll
165 * for reset completion status
166 * Also, at POR, interrupts are ENABLED on a JR, thus
167 * this is the point where I can disable them without
168 * changing the code logic too much
170 caam_jr_disable_irqs(job_ring->irq_fd);
172 /* initiate flush (required prior to reset) */
173 SET_JR_REG(JRCR, job_ring, JR_REG_JRCR_VAL_RESET);
176 tmp = GET_JR_REG(JRCR, job_ring);
179 tmp = GET_JR_REG(JRINT, job_ring);
180 usleep(usleep_interval);
181 } while (((tmp & JRINT_ERR_HALT_MASK) ==
182 JRINT_ERR_HALT_INPROGRESS) && --timeout);
184 CAAM_JR_INFO("JRINT is %x", tmp);
185 if ((tmp & JRINT_ERR_HALT_MASK) != JRINT_ERR_HALT_COMPLETE ||
187 CAAM_JR_ERR("0x%x, %d", tmp, timeout);
188 /* unmask interrupts */
189 if (job_ring->jr_mode != SEC_NOTIFICATION_TYPE_POLL)
190 caam_jr_enable_irqs(job_ring->irq_fd);
195 timeout = SEC_TIMEOUT;
196 SET_JR_REG(JRCR, job_ring, JR_REG_JRCR_VAL_RESET);
199 tmp = GET_JR_REG(JRCR, job_ring);
200 usleep(usleep_interval);
201 } while ((tmp & JR_REG_JRCR_VAL_RESET) && --timeout);
203 CAAM_JR_DEBUG("JRCR is %x", tmp);
205 CAAM_JR_ERR("Failed to reset hw job ring %p", job_ring);
206 /* unmask interrupts */
207 if (job_ring->jr_mode != SEC_NOTIFICATION_TYPE_POLL)
208 caam_jr_enable_irqs(job_ring->irq_fd);
211 /* unmask interrupts */
212 if (job_ring->jr_mode != SEC_NOTIFICATION_TYPE_POLL)
213 caam_jr_enable_irqs(job_ring->irq_fd);
219 hw_handle_job_ring_error(struct sec_job_ring_t *job_ring __rte_unused,
222 union hw_error_code hw_err_code;
224 hw_err_code.error = error_code;
225 switch (hw_err_code.error_desc.value.ssrc) {
226 case SEC_HW_ERR_SSRC_NO_SRC:
227 ASSERT(hw_err_code.error_desc.no_status_src.res == 0);
228 CAAM_JR_ERR("No Status Source ");
230 case SEC_HW_ERR_SSRC_CCB_ERR:
231 CAAM_JR_ERR("CCB Status Source");
232 hw_handle_ccb_err(hw_err_code);
234 case SEC_HW_ERR_SSRC_JMP_HALT_U:
235 CAAM_JR_ERR("Jump Halt User Status Source");
236 hw_handle_jmp_halt_user_err(hw_err_code);
238 case SEC_HW_ERR_SSRC_DECO:
239 CAAM_JR_ERR("DECO Status Source");
240 hw_handle_deco_err(hw_err_code);
242 case SEC_HW_ERR_SSRC_JR:
243 CAAM_JR_ERR("Job Ring Status Source");
244 hw_handle_jr_err(hw_err_code);
246 case SEC_HW_ERR_SSRC_JMP_HALT_COND:
247 CAAM_JR_ERR("Jump Halt Condition Codes");
248 hw_handle_jmp_halt_cond_err(hw_err_code);
252 CAAM_JR_ERR("Unknown SSRC");
258 hw_job_ring_error_print(struct sec_job_ring_t *job_ring, int code)
261 case JRINT_ERR_WRITE_STATUS:
262 CAAM_JR_ERR("Error writing status to Output Ring ");
264 case JRINT_ERR_BAD_INPUT_BASE:
266 "Bad Input Ring Base (%p) (not on a 4-byte boundary) ",
269 case JRINT_ERR_BAD_OUTPUT_BASE:
271 "Bad Output Ring Base (%p) (not on a 4-byte boundary) ",
274 case JRINT_ERR_WRITE_2_IRBA:
276 "Invalid write to Input Ring Base Address Register ");
278 case JRINT_ERR_WRITE_2_ORBA:
280 "Invalid write to Output Ring Base Address Register ");
282 case JRINT_ERR_RES_B4_HALT:
284 "Job Ring [%p] released before Job Ring is halted",
287 case JRINT_ERR_REM_TOO_MANY:
288 CAAM_JR_ERR("Removed too many jobs from job ring [%p]",
291 case JRINT_ERR_ADD_TOO_MANY:
292 CAAM_JR_ERR("Added too many jobs on job ring [%p]", job_ring);
295 CAAM_JR_ERR(" Unknown SEC JR Error :%d",
302 hw_job_ring_set_coalescing_param(struct sec_job_ring_t *job_ring,
303 uint16_t irq_coalescing_timer,
304 uint8_t irq_coalescing_count)
306 uint32_t reg_val = 0;
308 ASSERT(job_ring != NULL);
309 if (job_ring->register_base_addr == NULL) {
310 CAAM_JR_ERR("Jr[%p] has reg base addr as NULL.driver not init",
314 /* Set descriptor count coalescing */
315 reg_val |= (irq_coalescing_count << JR_REG_JRCFG_LO_ICDCT_SHIFT);
317 /* Set coalescing timer value */
318 reg_val |= (irq_coalescing_timer << JR_REG_JRCFG_LO_ICTT_SHIFT);
320 /* Update parameters in HW */
321 SET_JR_REG_LO(JRCFG, job_ring, reg_val);
322 CAAM_JR_DEBUG("Set coalescing params on jr %p timer:%d, desc count: %d",
323 job_ring, irq_coalescing_timer, irq_coalescing_timer);
329 hw_job_ring_enable_coalescing(struct sec_job_ring_t *job_ring)
331 uint32_t reg_val = 0;
333 ASSERT(job_ring != NULL);
334 if (job_ring->register_base_addr == NULL) {
335 CAAM_JR_ERR("Jr[%p] has reg base addr as NULL.driver not init",
340 /* Get the current value of the register */
341 reg_val = GET_JR_REG_LO(JRCFG, job_ring);
343 /* Enable coalescing */
344 reg_val |= JR_REG_JRCFG_LO_ICEN_EN;
347 SET_JR_REG_LO(JRCFG, job_ring, reg_val);
349 CAAM_JR_DEBUG("Enabled coalescing on jr %p ",
356 hw_job_ring_disable_coalescing(struct sec_job_ring_t *job_ring)
358 uint32_t reg_val = 0;
360 ASSERT(job_ring != NULL);
362 if (job_ring->register_base_addr == NULL) {
363 CAAM_JR_ERR("Jr[%p] has reg base addr as NULL.driver not init",
368 /* Get the current value of the register */
369 reg_val = GET_JR_REG_LO(JRCFG, job_ring);
371 /* Disable coalescing */
372 reg_val &= ~JR_REG_JRCFG_LO_ICEN_EN;
375 SET_JR_REG_LO(JRCFG, job_ring, reg_val);
376 CAAM_JR_DEBUG("Disabled coalescing on jr %p ", job_ring);