Branch data Line data Source code
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 : 0 : hw_handle_jmp_halt_cond_err(union hw_error_code error_code)
28 : : {
29 : 0 : 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 : 0 : }
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 : 0 : hw_handle_deco_err(union hw_error_code error_code)
42 : : {
43 : 0 : 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 [ # # ]: 0 : switch (error_code.error_desc.deco_src.desc_err) {
48 : 0 : case SEC_HW_ERR_DECO_HFN_THRESHOLD:
49 : 0 : CAAM_JR_DEBUG(" Warning: Descriptor completed normally,"
50 : : "but 3GPP HFN matches or exceeds the Threshold ");
51 : 0 : break;
52 : 0 : default:
53 : 0 : CAAM_JR_DEBUG("Error 0x%04x not implemented",
54 : : error_code.error_desc.deco_src.desc_err);
55 : 0 : break;
56 : : }
57 : 0 : }
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 : 0 : hw_handle_jmp_halt_user_err(union hw_error_code error_code __rte_unused)
65 : : {
66 : 0 : CAAM_JR_DEBUG(" Not implemented");
67 : 0 : }
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 : 0 : hw_handle_ccb_err(union hw_error_code hw_error_code __rte_unused)
75 : : {
76 : 0 : CAAM_JR_DEBUG(" Not implemented");
77 : 0 : }
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 : 0 : hw_handle_jr_err(union hw_error_code hw_error_code __rte_unused)
85 : : {
86 : 0 : CAAM_JR_DEBUG(" Not implemented");
87 : 0 : }
88 : :
89 : : int
90 : 0 : 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 : 0 : ret = hw_shutdown_job_ring(job_ring);
98 [ # # ]: 0 : 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 : 0 : hw_set_input_ring_size(job_ring, SEC_JOB_RING_SIZE);
107 : :
108 : : /* Write the JR output queue size to the HW register */
109 : 0 : hw_set_output_ring_size(job_ring, SEC_JOB_RING_SIZE);
110 : :
111 : : /* Write the JR input queue start address */
112 : 0 : hw_set_input_ring_start_addr(job_ring,
113 : : caam_jr_dma_vtop(job_ring->input_ring));
114 : 0 : 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 : 0 : hw_set_output_ring_start_addr(job_ring,
122 : : caam_jr_dma_vtop(job_ring->output_ring));
123 : 0 : 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 : 0 : return ret;
129 : : }
130 : :
131 : : int
132 : 0 : 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 [ # # ]: 0 : if (job_ring->register_base_addr == NULL) {
139 : 0 : CAAM_JR_ERR("Jr[%p] has reg base addr as NULL.driver not init",
140 : : job_ring);
141 : 0 : return 0;
142 : : }
143 : :
144 : 0 : 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 : 0 : caam_jr_disable_irqs(job_ring->irq_fd);
154 : :
155 : : /* initiate flush (required prior to reset) */
156 : 0 : SET_JR_REG(JRCR, job_ring, JR_REG_JRCR_VAL_RESET);
157 : :
158 : : /* dummy read */
159 : 0 : tmp = GET_JR_REG(JRCR, job_ring);
160 : :
161 : : do {
162 : 0 : tmp = GET_JR_REG(JRINT, job_ring);
163 : 0 : usleep(usleep_interval);
164 : 0 : } while (((tmp & JRINT_ERR_HALT_MASK) ==
165 [ # # # # ]: 0 : JRINT_ERR_HALT_INPROGRESS) && --timeout);
166 : :
167 : 0 : CAAM_JR_INFO("JRINT is %x", tmp);
168 [ # # # # ]: 0 : if ((tmp & JRINT_ERR_HALT_MASK) != JRINT_ERR_HALT_COMPLETE ||
169 : : timeout == 0) {
170 : 0 : CAAM_JR_ERR("0x%x, %d", tmp, timeout);
171 : : /* unmask interrupts */
172 [ # # ]: 0 : if (job_ring->jr_mode != SEC_NOTIFICATION_TYPE_POLL)
173 : 0 : caam_jr_enable_irqs(job_ring->irq_fd);
174 : 0 : return -1;
175 : : }
176 : :
177 : : /* Initiate reset */
178 : : timeout = SEC_TIMEOUT;
179 : 0 : SET_JR_REG(JRCR, job_ring, JR_REG_JRCR_VAL_RESET);
180 : :
181 : : do {
182 : 0 : tmp = GET_JR_REG(JRCR, job_ring);
183 : 0 : usleep(usleep_interval);
184 [ # # # # ]: 0 : } while ((tmp & JR_REG_JRCR_VAL_RESET) && --timeout);
185 : :
186 : 0 : CAAM_JR_DEBUG("JRCR is %x", tmp);
187 [ # # ]: 0 : if (timeout == 0) {
188 : 0 : CAAM_JR_ERR("Failed to reset hw job ring %p", job_ring);
189 : : /* unmask interrupts */
190 [ # # ]: 0 : if (job_ring->jr_mode != SEC_NOTIFICATION_TYPE_POLL)
191 : 0 : caam_jr_enable_irqs(job_ring->irq_fd);
192 : 0 : return -1;
193 : : }
194 : : /* unmask interrupts */
195 [ # # ]: 0 : if (job_ring->jr_mode != SEC_NOTIFICATION_TYPE_POLL)
196 : 0 : caam_jr_enable_irqs(job_ring->irq_fd);
197 : : return 0;
198 : :
199 : : }
200 : :
201 : : void
202 : 0 : 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 : 0 : hw_err_code.error = error_code;
208 [ # # # # : 0 : switch (hw_err_code.error_desc.value.ssrc) {
# # # ]
209 : 0 : case SEC_HW_ERR_SSRC_NO_SRC:
210 : : ASSERT(hw_err_code.error_desc.no_status_src.res == 0);
211 : 0 : CAAM_JR_ERR("No Status Source ");
212 : 0 : break;
213 : 0 : case SEC_HW_ERR_SSRC_CCB_ERR:
214 : 0 : CAAM_JR_ERR("CCB Status Source");
215 : 0 : hw_handle_ccb_err(hw_err_code);
216 : 0 : break;
217 : 0 : case SEC_HW_ERR_SSRC_JMP_HALT_U:
218 : 0 : CAAM_JR_ERR("Jump Halt User Status Source");
219 : 0 : hw_handle_jmp_halt_user_err(hw_err_code);
220 : 0 : break;
221 : 0 : case SEC_HW_ERR_SSRC_DECO:
222 : 0 : CAAM_JR_ERR("DECO Status Source");
223 : 0 : hw_handle_deco_err(hw_err_code);
224 : 0 : break;
225 : 0 : case SEC_HW_ERR_SSRC_JR:
226 : 0 : CAAM_JR_ERR("Job Ring Status Source");
227 : 0 : hw_handle_jr_err(hw_err_code);
228 : 0 : break;
229 : 0 : case SEC_HW_ERR_SSRC_JMP_HALT_COND:
230 : 0 : CAAM_JR_ERR("Jump Halt Condition Codes");
231 : 0 : hw_handle_jmp_halt_cond_err(hw_err_code);
232 : 0 : break;
233 : 0 : default:
234 : : ASSERT(0);
235 : 0 : CAAM_JR_ERR("Unknown SSRC");
236 : 0 : break;
237 : : }
238 : 0 : }
239 : :
240 : : void
241 : 0 : hw_job_ring_error_print(struct sec_job_ring_t *job_ring, int code)
242 : : {
243 [ # # # # : 0 : switch (code) {
# # # #
# ]
244 : 0 : case JRINT_ERR_WRITE_STATUS:
245 : 0 : CAAM_JR_ERR("Error writing status to Output Ring ");
246 : 0 : break;
247 : 0 : case JRINT_ERR_BAD_INPUT_BASE:
248 : 0 : CAAM_JR_ERR(
249 : : "Bad Input Ring Base (%p) (not on a 4-byte boundary) ",
250 : : (void *)job_ring);
251 : 0 : break;
252 : 0 : case JRINT_ERR_BAD_OUTPUT_BASE:
253 : 0 : CAAM_JR_ERR(
254 : : "Bad Output Ring Base (%p) (not on a 4-byte boundary) ",
255 : : (void *)job_ring);
256 : 0 : break;
257 : 0 : case JRINT_ERR_WRITE_2_IRBA:
258 : 0 : CAAM_JR_ERR(
259 : : "Invalid write to Input Ring Base Address Register ");
260 : 0 : break;
261 : 0 : case JRINT_ERR_WRITE_2_ORBA:
262 : 0 : CAAM_JR_ERR(
263 : : "Invalid write to Output Ring Base Address Register ");
264 : 0 : break;
265 : 0 : case JRINT_ERR_RES_B4_HALT:
266 : 0 : CAAM_JR_ERR(
267 : : "Job Ring [%p] released before Job Ring is halted",
268 : : (void *)job_ring);
269 : 0 : break;
270 : 0 : case JRINT_ERR_REM_TOO_MANY:
271 : 0 : CAAM_JR_ERR("Removed too many jobs from job ring [%p]",
272 : : (void *)job_ring);
273 : 0 : break;
274 : 0 : case JRINT_ERR_ADD_TOO_MANY:
275 : 0 : CAAM_JR_ERR("Added too many jobs on job ring [%p]", job_ring);
276 : 0 : break;
277 : 0 : default:
278 : 0 : CAAM_JR_ERR(" Unknown SEC JR Error :%d",
279 : : code);
280 : 0 : break;
281 : : }
282 : 0 : }
283 : :
284 : : int
285 : 0 : 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 [ # # ]: 0 : if (job_ring->register_base_addr == NULL) {
293 : 0 : CAAM_JR_ERR("Jr[%p] has reg base addr as NULL.driver not init",
294 : : job_ring);
295 : 0 : return -1;
296 : : }
297 : : /* Set descriptor count coalescing */
298 : 0 : reg_val |= (irq_coalescing_count << JR_REG_JRCFG_LO_ICDCT_SHIFT);
299 : :
300 : : /* Set coalescing timer value */
301 : 0 : reg_val |= (irq_coalescing_timer << JR_REG_JRCFG_LO_ICTT_SHIFT);
302 : :
303 : : /* Update parameters in HW */
304 : 0 : SET_JR_REG_LO(JRCFG, job_ring, reg_val);
305 : 0 : 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 : 0 : return 0;
309 : : }
310 : :
311 : : int
312 : 0 : 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 [ # # ]: 0 : if (job_ring->register_base_addr == NULL) {
318 : 0 : CAAM_JR_ERR("Jr[%p] has reg base addr as NULL.driver not init",
319 : : job_ring);
320 : 0 : return -1;
321 : : }
322 : :
323 : : /* Get the current value of the register */
324 : 0 : reg_val = GET_JR_REG_LO(JRCFG, job_ring);
325 : :
326 : : /* Enable coalescing */
327 : 0 : reg_val |= JR_REG_JRCFG_LO_ICEN_EN;
328 : :
329 : : /* Write in hw */
330 : 0 : SET_JR_REG_LO(JRCFG, job_ring, reg_val);
331 : :
332 : 0 : CAAM_JR_DEBUG("Enabled coalescing on jr %p ",
333 : : job_ring);
334 : :
335 : 0 : return 0;
336 : : }
337 : :
338 : : int
339 : 0 : 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 [ # # ]: 0 : if (job_ring->register_base_addr == NULL) {
346 : 0 : CAAM_JR_ERR("Jr[%p] has reg base addr as NULL.driver not init",
347 : : job_ring);
348 : 0 : return -1;
349 : : }
350 : :
351 : : /* Get the current value of the register */
352 : 0 : reg_val = GET_JR_REG_LO(JRCFG, job_ring);
353 : :
354 : : /* Disable coalescing */
355 : 0 : reg_val &= ~JR_REG_JRCFG_LO_ICEN_EN;
356 : :
357 : : /* Write in hw */
358 : 0 : SET_JR_REG_LO(JRCFG, job_ring, reg_val);
359 : 0 : CAAM_JR_DEBUG("Disabled coalescing on jr %p ", job_ring);
360 : :
361 : 0 : return 0;
362 : : }
|