xref: /dpdk/drivers/common/dpaax/caamflib/desc/sdap.h (revision 6671e82e5c6b4858573f4dae665e7f2442913d93)
1 /* SPDX-License-Identifier: BSD-3-Clause
2  * Copyright 2020-2023 NXP
3  */
4 
5 #ifndef __DESC_SDAP_H__
6 #define __DESC_SDAP_H__
7 
8 #include "rta.h"
9 #include "common.h"
10 #include "pdcp.h"
11 
12 /* The file defines all the functions to do PDCP without protocol support in
13  * SEC
14  */
15 
16 /* Enable SDAP support */
17 #define SDAP_SUPPORT
18 #ifdef SDAP_SUPPORT
19 #define SDAP_BYTE_SIZE 1
20 #define SDAP_BITS_SIZE (SDAP_BYTE_SIZE * 8)
21 #endif
22 
23 /**
24  * rta_inline_pdcp_query() - Provide indications if a key can be passed as
25  *                           immediate data or shall be referenced in a
26  *                           shared descriptor.
27  * Return: 0 if data can be inlined or 1 if referenced.
28  */
29 static inline int
rta_inline_pdcp_sdap_query(enum auth_type_pdcp auth_alg,enum cipher_type_pdcp cipher_alg,__rte_unused enum pdcp_sn_size sn_size,__rte_unused int8_t hfn_ovd)30 rta_inline_pdcp_sdap_query(enum auth_type_pdcp auth_alg,
31 		      enum cipher_type_pdcp cipher_alg,
32 		      __rte_unused enum pdcp_sn_size sn_size,
33 		      __rte_unused int8_t hfn_ovd)
34 {
35 	if ((cipher_alg != PDCP_CIPHER_TYPE_NULL) &&
36 			(auth_alg != PDCP_AUTH_TYPE_NULL))
37 		return 2;
38 	else
39 		return 0;
40 }
41 
key_loading_opti(struct program * p,struct alginfo * cipherdata,struct alginfo * authdata)42 static inline void key_loading_opti(struct program *p,
43 				    struct alginfo *cipherdata,
44 				    struct alginfo *authdata)
45 {
46 	LABEL(lbl_skip_key_loading_jump);
47 	REFERENCE(ref_skip_key_loading_jump);
48 
49 	/* Optimisation to bypass key loading (and decryption of the keys):
50 	 * Jump command testing:
51 	 * - SHRD: Descriptor is shared
52 	 * - SELF: The shared descriptor is in the same DECO
53 	 * - BOTH: The Class 1 and 2 CHA have finished
54 	 * -> If this is true, we jump and skip loading of the keys as they are
55 	 *    already loaded
56 	 */
57 	ref_skip_key_loading_jump =
58 		JUMP(p, lbl_skip_key_loading_jump, LOCAL_JUMP, ALL_TRUE,
59 		     SHRD | SELF | BOTH);
60 
61 	/* Load the keys */
62 	if (cipherdata) {
63 		KEY(p, KEY1, cipherdata->key_enc_flags, cipherdata->key,
64 		    cipherdata->keylen, INLINE_KEY(cipherdata));
65 	}
66 
67 	if (authdata) {
68 		KEY(p, KEY2, authdata->key_enc_flags, authdata->key,
69 		    authdata->keylen, INLINE_KEY(authdata));
70 	}
71 
72 	/* Save the place where we want the jump to go */
73 	SET_LABEL(p, lbl_skip_key_loading_jump);
74 	/* Update the jump command with the position where to jump */
75 	PATCH_JUMP(p, ref_skip_key_loading_jump, lbl_skip_key_loading_jump);
76 }
77 
pdcp_sdap_get_sn_parameters(enum pdcp_sn_size sn_size,bool swap,uint32_t * offset,uint32_t * length,uint32_t * sn_mask)78 static inline int pdcp_sdap_get_sn_parameters(enum pdcp_sn_size sn_size,
79 					      bool swap, uint32_t *offset,
80 					      uint32_t *length,
81 					      uint32_t *sn_mask)
82 {
83 	switch (sn_size) {
84 	case PDCP_SN_SIZE_5:
85 		*offset = 7;
86 		*length = 1;
87 		*sn_mask = (swap == false) ? PDCP_C_PLANE_SN_MASK :
88 					     PDCP_C_PLANE_SN_MASK_BE;
89 		break;
90 	case PDCP_SN_SIZE_7:
91 		*offset = 7;
92 		*length = 1;
93 		*sn_mask = (swap == false) ? PDCP_7BIT_SN_MASK :
94 					     PDCP_7BIT_SN_MASK_BE;
95 		break;
96 	case PDCP_SN_SIZE_12:
97 		*offset = 6;
98 		*length = 2;
99 		*sn_mask = (swap == false) ? PDCP_12BIT_SN_MASK :
100 					     PDCP_12BIT_SN_MASK_BE;
101 		break;
102 	case PDCP_SN_SIZE_15:
103 		*offset = 6;
104 		*length = 2;
105 		*sn_mask = (swap == false) ? PDCP_U_PLANE_15BIT_SN_MASK :
106 					     PDCP_U_PLANE_15BIT_SN_MASK_BE;
107 		break;
108 	case PDCP_SN_SIZE_18:
109 		*offset = 5;
110 		*length = 3;
111 		*sn_mask = (swap == false) ? PDCP_U_PLANE_18BIT_SN_MASK :
112 					     PDCP_U_PLANE_18BIT_SN_MASK_BE;
113 		break;
114 	default:
115 		pr_err("Invalid sn_size for %s\n", __func__);
116 		return -ENOTSUP;
117 	}
118 
119 #ifdef SDAP_SUPPORT
120 	*length += SDAP_BYTE_SIZE;
121 	*offset -= SDAP_BYTE_SIZE;
122 #endif
123 
124 	return 0;
125 }
126 
pdcp_sdap_insert_no_int_op(struct program * p,bool swap __maybe_unused,struct alginfo * cipherdata,unsigned int dir,enum pdcp_sn_size sn_size,enum pdb_type_e pdb_type)127 static inline int pdcp_sdap_insert_no_int_op(struct program *p,
128 					     bool swap __maybe_unused,
129 					     struct alginfo *cipherdata,
130 					     unsigned int dir,
131 					     enum pdcp_sn_size sn_size,
132 					     enum pdb_type_e pdb_type)
133 {
134 	int op;
135 	uint32_t sn_mask = 0;
136 	uint32_t length = 0;
137 	uint32_t offset = 0;
138 	int hfn_bearer_dir_offset_in_descbuf =
139 		(pdb_type == PDCP_PDB_TYPE_FULL_PDB) ?
140 			FULL_PDB_DESCBUF_HFN_BEARER_DIR_OFFSET :
141 			REDUCED_PDB_DESCBUF_HFN_BEARER_DIR_OFFSET;
142 
143 	if (pdcp_sdap_get_sn_parameters(sn_size, swap, &offset, &length,
144 					&sn_mask))
145 		return -ENOTSUP;
146 
147 	/* Load key */
148 	key_loading_opti(p, cipherdata, NULL);
149 
150 	SEQLOAD(p, MATH0, offset, length, 0);
151 	JUMP(p, 1, LOCAL_JUMP, ALL_TRUE, CALM);
152 #ifdef SDAP_SUPPORT
153 	rta_mathi(p, MATH0,
154 		  ((swap == true) ? MATH_FUN_RSHIFT : MATH_FUN_LSHIFT),
155 		  SDAP_BITS_SIZE, MATH1, 8, 0);
156 	MATHB(p, MATH1, AND, sn_mask, MATH1, 8, IFB | IMMED2);
157 #else
158 	MATHB(p, MATH0, AND, sn_mask, MATH1, 8, IFB | IMMED2);
159 #endif
160 
161 	SEQSTORE(p, MATH0, offset, length, 0);
162 
163 	MATHB(p, MATH1, SHLD, MATH1, MATH1, 8, 0);
164 	MOVEB(p, DESCBUF, hfn_bearer_dir_offset_in_descbuf,
165 			MATH2, 0, 8, WAITCOMP | IMMED);
166 	MATHB(p, MATH1, OR, MATH2, MATH2, 8, 0);
167 
168 	MATHB(p, SEQINSZ, SUB, MATH3, VSEQINSZ, 4, 0);
169 	MATHB(p, SEQINSZ, SUB, MATH3, VSEQOUTSZ, 4, 0);
170 
171 	SEQFIFOSTORE(p, MSG, 0, 0, VLF);
172 
173 	op = dir == OP_TYPE_ENCAP_PROTOCOL ? DIR_ENC : DIR_DEC;
174 	switch (cipherdata->algtype) {
175 	case PDCP_CIPHER_TYPE_SNOW:
176 		/* Copy the IV */
177 		MOVEB(p, MATH2, 0, CONTEXT1, 0, 8, WAITCOMP | IMMED);
178 		ALG_OPERATION(p, OP_ALG_ALGSEL_SNOW_F8, OP_ALG_AAI_F8,
179 			      OP_ALG_AS_INITFINAL, ICV_CHECK_DISABLE, op);
180 		break;
181 
182 	case PDCP_CIPHER_TYPE_AES:
183 		/* The first 64 bits are 0 */
184 		MOVEB(p, MATH2, 0, CONTEXT1, 16, 8, WAITCOMP | IMMED);
185 		ALG_OPERATION(p, OP_ALG_ALGSEL_AES, OP_ALG_AAI_CTR,
186 			      OP_ALG_AS_INITFINAL, ICV_CHECK_DISABLE, op);
187 		break;
188 
189 	case PDCP_CIPHER_TYPE_ZUC:
190 		/* The LSB and MSB is the same for ZUC context */
191 		MOVEB(p, MATH2, 0, CONTEXT1, 0, 0x08, IMMED);
192 		MOVEB(p, MATH2, 0, CONTEXT1, 0x08, 0x08, WAITCOMP | IMMED);
193 
194 		ALG_OPERATION(p, OP_ALG_ALGSEL_ZUCE, OP_ALG_AAI_F8,
195 			      OP_ALG_AS_INITFINAL, ICV_CHECK_DISABLE, op);
196 		break;
197 
198 	default:
199 		pr_err("%s: Invalid encrypt algorithm selected: %d\n",
200 		       "pdcp_sdap_insert_15bit_op", cipherdata->algtype);
201 		return -EINVAL;
202 	}
203 
204 	SEQFIFOLOAD(p, MSG1, 0, VLF | LAST1 | FLUSH1);
205 
206 	return 0;
207 }
208 
209 static inline int
pdcp_sdap_insert_enc_only_op(struct program * p,bool swap __maybe_unused,struct alginfo * cipherdata,struct alginfo * authdata __maybe_unused,unsigned int dir,enum pdcp_sn_size sn_size,enum pdb_type_e pdb_type)210 pdcp_sdap_insert_enc_only_op(struct program *p, bool swap __maybe_unused,
211 			     struct alginfo *cipherdata,
212 			     struct alginfo *authdata __maybe_unused,
213 			     unsigned int dir, enum pdcp_sn_size sn_size,
214 			     enum pdb_type_e pdb_type)
215 {
216 	uint32_t offset = 0, length = 0, sn_mask = 0;
217 	int hfn_bearer_dir_offset_in_descbuf =
218 		(pdb_type == PDCP_PDB_TYPE_FULL_PDB) ?
219 			FULL_PDB_DESCBUF_HFN_BEARER_DIR_OFFSET :
220 			REDUCED_PDB_DESCBUF_HFN_BEARER_DIR_OFFSET;
221 
222 	if (pdcp_sdap_get_sn_parameters(sn_size, swap, &offset, &length,
223 					&sn_mask))
224 		return -ENOTSUP;
225 
226 	/* Load key */
227 	key_loading_opti(p, cipherdata, NULL);
228 
229 	/* Load header */
230 	SEQLOAD(p, MATH0, offset, length, 0);
231 	JUMP(p, 1, LOCAL_JUMP, ALL_TRUE, CALM);
232 
233 #ifdef SDAP_SUPPORT
234 	rta_mathi(p, MATH0,
235 		  ((swap == true) ? MATH_FUN_RSHIFT : MATH_FUN_LSHIFT),
236 		  SDAP_BITS_SIZE, MATH1, 8, 0);
237 	MATHB(p, MATH1, AND, sn_mask, MATH1, 8, IFB | IMMED2);
238 #else
239 	MATHB(p, MATH0, AND, sn_mask, MATH1, 8, IFB | IMMED2);
240 #endif
241 
242 	/* Word (32 bit) swap */
243 	MATHB(p, MATH1, SHLD, MATH1, MATH1, 8, 0);
244 	/* Load words from PDB: word 02 (HFN) + word 03 (bearer_dir)*/
245 	MOVEB(p, DESCBUF, hfn_bearer_dir_offset_in_descbuf,
246 			MATH2, 0, 8, WAITCOMP | IMMED);
247 	/* Create basic IV */
248 	MATHB(p, MATH1, OR, MATH2, MATH2, 8, 0);
249 
250 	/* Write header */
251 	SEQSTORE(p, MATH0, offset, length, 0);
252 
253 	MATHB(p, SEQINSZ, SUB, ZERO, VSEQINSZ, 4, 0);
254 
255 	if (dir == OP_TYPE_ENCAP_PROTOCOL)
256 		MATHB(p, SEQINSZ, ADD, PDCP_MAC_I_LEN, VSEQOUTSZ, 4, IMMED2);
257 	else
258 		MATHB(p, SEQINSZ, SUB, PDCP_MAC_I_LEN, VSEQOUTSZ, 4, IMMED2);
259 
260 	switch (cipherdata->algtype) {
261 	case PDCP_CIPHER_TYPE_SNOW:
262 		MOVEB(p, MATH2, 0, CONTEXT1, 0, 8, WAITCOMP | IMMED);
263 		SEQFIFOSTORE(p, MSG, 0, 0, VLF | CONT);
264 		ALG_OPERATION(p, OP_ALG_ALGSEL_SNOW_F8, OP_ALG_AAI_F8,
265 			      OP_ALG_AS_INITFINAL, ICV_CHECK_DISABLE,
266 			      dir == OP_TYPE_ENCAP_PROTOCOL ? DIR_ENC :
267 							      DIR_DEC);
268 		break;
269 
270 	case PDCP_CIPHER_TYPE_AES:
271 		MOVEB(p, MATH2, 0, CONTEXT1, 16, 8, WAITCOMP | IMMED);
272 
273 		SEQFIFOSTORE(p, MSG, 0, 0, VLF | CONT);
274 		ALG_OPERATION(p, OP_ALG_ALGSEL_AES, OP_ALG_AAI_CTR,
275 			      OP_ALG_AS_INITFINAL, ICV_CHECK_DISABLE,
276 			      dir == OP_TYPE_ENCAP_PROTOCOL ? DIR_ENC :
277 							      DIR_DEC);
278 		break;
279 
280 	case PDCP_CIPHER_TYPE_ZUC:
281 		MOVEB(p, MATH2, 0, CONTEXT1, 0, 0x08, IMMED);
282 		MOVEB(p, MATH2, 0, CONTEXT1, 0x08, 0x08, WAITCOMP | IMMED);
283 
284 		SEQFIFOSTORE(p, MSG, 0, 0, VLF | CONT);
285 		ALG_OPERATION(p, OP_ALG_ALGSEL_ZUCE, OP_ALG_AAI_F8,
286 			      OP_ALG_AS_INITFINAL, ICV_CHECK_DISABLE,
287 			      dir == OP_TYPE_ENCAP_PROTOCOL ? DIR_ENC :
288 							      DIR_DEC);
289 		break;
290 
291 	default:
292 		pr_err("%s: Invalid encrypt algorithm selected: %d\n",
293 		       "pdcp_sdap_insert_enc_only_op", cipherdata->algtype);
294 		return -EINVAL;
295 	}
296 
297 	if (dir == OP_TYPE_ENCAP_PROTOCOL) {
298 		SEQFIFOLOAD(p, MSG1, 0, VLF);
299 		FIFOLOAD(p, MSG1, PDCP_NULL_INT_MAC_I_VAL, 4,
300 			 LAST1 | FLUSH1 | IMMED);
301 	} else {
302 		SEQFIFOLOAD(p, MSG1, 0, VLF | LAST1 | FLUSH1);
303 		MOVE(p, OFIFO, 0, MATH1, 4, PDCP_MAC_I_LEN, WAITCOMP | IMMED);
304 		MATHB(p, MATH1, XOR, PDCP_NULL_INT_MAC_I_VAL, NONE, 4, IMMED2);
305 		JUMP(p, PDCP_NULL_INT_ICV_CHECK_FAILED_STATUS, HALT_STATUS,
306 		     ALL_FALSE, MATH_Z);
307 	}
308 
309 	return 0;
310 }
311 
312 /*
313  * This function leverage the use of in/out snooping as SNOW and ZUC both
314  * have a class 1 and class 2 CHA. It also supports AES as cipher.
315  * Supported:
316  *  - cipher:
317  *      - AES-CTR
318  *      - SNOW F8
319  *      - ZUC F8
320  *  - authentication
321  *      - SNOW F8
322  *      - ZUC F8
323  */
324 static inline int
pdcp_sdap_insert_snoop_op(struct program * p,bool swap __maybe_unused,struct alginfo * cipherdata,struct alginfo * authdata,unsigned int dir,enum pdcp_sn_size sn_size,enum pdb_type_e pdb_type)325 pdcp_sdap_insert_snoop_op(struct program *p, bool swap __maybe_unused,
326 			  struct alginfo *cipherdata, struct alginfo *authdata,
327 			  unsigned int dir, enum pdcp_sn_size sn_size,
328 			  enum pdb_type_e pdb_type)
329 {
330 	uint32_t offset = 0, length = 0, sn_mask = 0;
331 	uint32_t int_op_alg = 0;
332 	uint32_t int_op_aai = 0;
333 	uint32_t cipher_op_alg = 0;
334 	uint32_t cipher_op_aai = 0;
335 	int hfn_bearer_dir_offset_in_descbuf =
336 		(pdb_type == PDCP_PDB_TYPE_FULL_PDB) ?
337 			FULL_PDB_DESCBUF_HFN_BEARER_DIR_OFFSET :
338 			REDUCED_PDB_DESCBUF_HFN_BEARER_DIR_OFFSET;
339 
340 	if (pdcp_sdap_get_sn_parameters(sn_size, swap, &offset, &length,
341 					&sn_mask))
342 		return -ENOTSUP;
343 
344 	if (dir == OP_TYPE_ENCAP_PROTOCOL)
345 		MATHB(p, SEQINSZ, SUB, length, VSEQINSZ, 4, IMMED2);
346 
347 	key_loading_opti(p, cipherdata, authdata);
348 
349 	/* Load the PDCP header from the input data
350 	 * Note: SEQINSZ is decremented by length
351 	 */
352 	SEQLOAD(p, MATH0, offset, length, 0);
353 	/* Wait the SN is loaded */
354 	JUMP(p, 1, LOCAL_JUMP, ALL_TRUE, CALM);
355 
356 	/* Pass the PDCP header to integrity block */
357 	MOVEB(p, MATH0, offset, IFIFOAB2, 0, length, IMMED);
358 
359 #ifdef SDAP_SUPPORT
360 	/* If SDAP is enabled, the least significant byte is the SDAP header
361 	 * Remove it by shifting the register
362 	 */
363 	rta_mathi(p, MATH0,
364 		  ((swap == true) ? MATH_FUN_RSHIFT : MATH_FUN_LSHIFT),
365 		  SDAP_BITS_SIZE, MATH1, 8, 0);
366 	/* Mask the PDCP header to keep only the SN */
367 	MATHB(p, MATH1, AND, sn_mask, MATH1, 8, IFB | IMMED2);
368 #else
369 	/* Mask the PDCP header to keep only the SN */
370 	MATHB(p, MATH0, AND, sn_mask, MATH1, 8, IFB | IMMED2);
371 #endif
372 
373 	/* Do a byte swap, it places the SN in upper part of the MATH reg */
374 	MATHB(p, MATH1, SHLD, MATH1, MATH1, 8, 0);
375 
376 	/* Load the HFN / Beare / Dir from the PDB
377 	 * CAAM word are 32bit hence loading 8 byte loads 2 words:
378 	 *  - The HFN at offset hfn_bearer_dir_offset_in_descbuf
379 	 *  - The Bearer / Dir at next word
380 	 */
381 	MOVEB(p, DESCBUF, hfn_bearer_dir_offset_in_descbuf,
382 			MATH2, 0, 8, WAITCOMP | IMMED);
383 
384 	/* Create the 4 first byte of the ICV by or-ing the math registers */
385 	MATHB(p, MATH1, OR, MATH2, MATH1, 8, 0);
386 
387 	/* Set the IV of class 1 CHA */
388 	if (cipherdata->algtype == PDCP_CIPHER_TYPE_AES) {
389 		MOVEB(p, MATH1, 0, CONTEXT1, 16, 8, IMMED);
390 	} else {
391 		/* Set the IV for the confidentiality CHA */
392 		MOVEB(p, MATH1, 0, CONTEXT1, 0, 8, IMMED);
393 	}
394 
395 	/* Set the IV of class 2 CHA */
396 	if (authdata->algtype == PDCP_AUTH_TYPE_ZUC) {
397 		/* Set the IV for the integrity CHA */
398 		MOVEB(p, MATH1, 0, CONTEXT2, 0, 8, WAITCOMP | IMMED);
399 	} else if (authdata->algtype == PDCP_AUTH_TYPE_SNOW) {
400 		MOVEB(p, MATH1, 0, CONTEXT2, 0, 4, WAITCOMP | IMMED);
401 
402 		/* Generate the bottom snow IV for integrity
403 		 * Note: MATH1 lowest 32bits is as follow:
404 		 * | bearer (5) | Dir (1) | zero (26) |
405 		 * the resulting math regs will be:
406 		 *               MATH3                           MATH2
407 		 * | zero (5) | Dir (1) | zero (26) | | Bearer (5) | zero (27) |
408 		 */
409 		if (swap == false) {
410 			MATHB(p, MATH1, AND, upper_32_bits(PDCP_BEARER_MASK),
411 			      MATH2, 4, IMMED2);
412 			MATHB(p, MATH1, AND, lower_32_bits(PDCP_DIR_MASK),
413 			      MATH3, 4, IMMED2);
414 		} else {
415 			MATHB(p, MATH1, AND, lower_32_bits(PDCP_BEARER_MASK_BE),
416 			      MATH2, 4, IMMED2);
417 			MATHB(p, MATH1, AND, upper_32_bits(PDCP_DIR_MASK_BE),
418 			      MATH3, 4, IMMED2);
419 		}
420 		/* Word swap MATH3 reg */
421 		MATHB(p, MATH3, SHLD, MATH3, MATH3, 8, 0);
422 
423 		/* Don't understand, seems to be doing a move of 12 byte
424 		 * (read MATH2 and overread MATH3)
425 		 */
426 		MOVEB(p, MATH2, 4, OFIFO, 0, 12, IMMED);
427 
428 		/* Add the rest of the snow IV to the context */
429 		MOVE(p, OFIFO, 0, CONTEXT2, 4, 12, IMMED);
430 	}
431 
432 	/* Set the variable size of data the register will write */
433 	if (dir == OP_TYPE_ENCAP_PROTOCOL) {
434 		/* We will add the integrity data so add its length */
435 		MATHI(p, SEQINSZ, ADD, PDCP_MAC_I_LEN, VSEQOUTSZ, 4, IMMED2);
436 	} else {
437 		/* We will check the integrity data so remove its length */
438 		MATHI(p, SEQINSZ, SUB, PDCP_MAC_I_LEN, VSEQOUTSZ, 4, IMMED2);
439 		/* Do not take the ICV in the out-snooping configuration */
440 		MATHI(p, SEQINSZ, SUB, PDCP_MAC_I_LEN, VSEQINSZ, 4, IMMED2);
441 	}
442 
443 	/* We write the PDCP header to output*/
444 	SEQSTORE(p, MATH0, offset, length, 0);
445 
446 	/* Definition of the flow of output data */
447 	if (dir == OP_TYPE_ENCAP_PROTOCOL) {
448 		/* We write data according to VSEQOUTSZ */
449 		SEQFIFOSTORE(p, MSG, 0, 0, VLF);
450 	} else {
451 		/* We write data according to VSEQOUTSZ */
452 		SEQFIFOSTORE(p, MSG, 0, 0, VLF | CONT);
453 	}
454 
455 	/* Get parameters for authentication */
456 	if (authdata->algtype == PDCP_AUTH_TYPE_ZUC) {
457 		int_op_alg = OP_ALG_ALGSEL_ZUCA;
458 		int_op_aai = OP_ALG_AAI_F9;
459 	} else if (authdata->algtype == PDCP_AUTH_TYPE_SNOW) {
460 		int_op_alg = OP_ALG_ALGSEL_SNOW_F9;
461 		int_op_aai = OP_ALG_AAI_F9;
462 	} else {
463 		pr_err("%s no support for auth alg: %d\n", __func__,
464 		       authdata->algtype);
465 		return -1;
466 	}
467 
468 	/* Get parameters for ciphering */
469 	if (cipherdata->algtype == PDCP_CIPHER_TYPE_ZUC) {
470 		cipher_op_alg = OP_ALG_ALGSEL_ZUCE;
471 		cipher_op_aai = OP_ALG_AAI_F8;
472 	} else if (cipherdata->algtype == PDCP_CIPHER_TYPE_SNOW) {
473 		cipher_op_alg = OP_ALG_ALGSEL_SNOW_F8;
474 		cipher_op_aai = OP_ALG_AAI_F8;
475 	} else if (cipherdata->algtype == PDCP_CIPHER_TYPE_AES) {
476 		cipher_op_alg = OP_ALG_ALGSEL_AES;
477 		cipher_op_aai = OP_ALG_AAI_CTR;
478 	} else {
479 		pr_err("%s no support for cipher alg: %d\n", __func__,
480 		       authdata->algtype);
481 		return -1;
482 	}
483 
484 	/* Configure the CHA, the class 2 CHA must be configured first or an
485 	 * error will be generated
486 	 */
487 
488 	/* Configure the class 2 CHA (integrity )*/
489 	ALG_OPERATION(p, int_op_alg, int_op_aai, OP_ALG_AS_INITFINAL,
490 		      dir == OP_TYPE_ENCAP_PROTOCOL ? ICV_CHECK_DISABLE :
491 						      ICV_CHECK_ENABLE,
492 		      DIR_ENC);
493 
494 	/* Configure class 1 CHA (confidentiality)*/
495 	ALG_OPERATION(p, cipher_op_alg, cipher_op_aai, OP_ALG_AS_INITFINAL,
496 		      ICV_CHECK_DISABLE,
497 		      dir == OP_TYPE_ENCAP_PROTOCOL ? DIR_ENC : DIR_DEC);
498 
499 	/* Definition of the flow of input data */
500 	if (dir == OP_TYPE_ENCAP_PROTOCOL) {
501 		/* We read data according to VSEQINSZ
502 		 * Note: we perform an in-snooping, eg the data will be read
503 		 * only once. they will be sent to both the integrity CHA and
504 		 * confidentiality CHA
505 		 */
506 		SEQFIFOLOAD(p, MSGINSNOOP, 0, VLF | LAST2);
507 
508 		/* When the integrity CHA is finished, send the ICV stored in
509 		 * the context to the confidentiality CHA for encryption
510 		 */
511 		MOVE(p, CONTEXT2, 0, IFIFOAB1, 0, 4, LAST1 | FLUSH1 | IMMED);
512 	} else {
513 		/* We read data according to VSEQINSZ
514 		 * Note: we perform an out-snooping, eg the data will be read
515 		 * only once. The will first be sent to the confidentiality
516 		 * CHA for decryption, then the CAAM will direct them to the
517 		 * integrity CHA to verify the ICV (which is at the end of the
518 		 * sequence)
519 		 */
520 		SEQFIFOLOAD(p, MSGOUTSNOOP, 0, VLF | LAST2);
521 
522 		/* Process the ICV by class 1 CHA */
523 		SEQFIFOLOAD(p, MSG1, 4, LAST1 | FLUSH1);
524 
525 		/* Wait for class 1 CHA to finish, the ICV data are stalling in
526 		 * the output fifo
527 		 */
528 		JUMP(p, 1, LOCAL_JUMP, ALL_TRUE, CLASS1 | NOP | NIFP);
529 
530 		LOAD(p, 0, DCTRL, 0, LDLEN_RST_CHA_OFIFO_PTR, IMMED);
531 
532 		/* Save the content left in the Output FIFO (the ICV) to MATH0
533 		 */
534 		MOVE(p, OFIFO, 0, MATH0, 0, 4, WAITCOMP | IMMED);
535 
536 		/* Configure a NFIFO entry to take data from the altsource
537 		 * and send it to the class 2 CHA as an ICV
538 		 */
539 		NFIFOADD(p, IFIFO, ICV2, 4, LAST2);
540 
541 		/* Move the content of MATH0 (OFIFO offset) to altsource
542 		 * Note: As configured by the altsource, this will send
543 		 * the
544 		 */
545 		MOVE(p, MATH0, 0, IFIFO, 0, 4, WAITCOMP | IMMED);
546 	}
547 
548 	if (authdata->algtype == PDCP_CIPHER_TYPE_ZUC) {
549 		/* Reset ZUCA mode and done interrupt
550 		 * Note: If it is not done, DECO generate an error: 200031ca
551 		 * -> ZUCA ICV failed
552 		 */
553 		LOAD(p, CLRW_CLR_C2MODE, CLRW, 0, 4, IMMED);
554 		LOAD(p, CIRQ_ZADI, ICTRL, 0, 4, IMMED);
555 	}
556 
557 	return 0;
558 }
559 
560 /* Function used when the integrity algorithm is a class 1 CHA so outsnooping
561  * is not possible
562  * Supported:
563  *  - cipher:
564  *      - AES-CTR
565  *      - SNOW F8
566  *      - ZUC F8
567  *  - authentication
568  *      - AES-CMAC
569  */
pdcp_sdap_insert_no_snoop_op(struct program * p,bool swap __maybe_unused,struct alginfo * cipherdata,struct alginfo * authdata,unsigned int dir,enum pdcp_sn_size sn_size,enum pdb_type_e pdb_type)570 static inline int pdcp_sdap_insert_no_snoop_op(
571 	struct program *p, bool swap __maybe_unused, struct alginfo *cipherdata,
572 	struct alginfo *authdata, unsigned int dir, enum pdcp_sn_size sn_size,
573 	enum pdb_type_e pdb_type)
574 {
575 	uint32_t offset = 0, length = 0, sn_mask = 0;
576 	uint32_t cipher_alg_op = 0;
577 	uint32_t cipher_alg_aai = 0;
578 	int hfn_bearer_dir_offset_in_descbuf =
579 		(pdb_type == PDCP_PDB_TYPE_FULL_PDB) ?
580 			FULL_PDB_DESCBUF_HFN_BEARER_DIR_OFFSET :
581 			REDUCED_PDB_DESCBUF_HFN_BEARER_DIR_OFFSET;
582 
583 	if (pdcp_sdap_get_sn_parameters(sn_size, swap, &offset, &length,
584 					&sn_mask))
585 		return -ENOTSUP;
586 
587 	SEQLOAD(p, MATH0, offset, length, 0);
588 	JUMP(p, 1, LOCAL_JUMP, ALL_TRUE, CALM);
589 
590 #ifdef SDAP_SUPPORT
591 	rta_mathi(p, MATH0,
592 		  ((swap == true) ? MATH_FUN_RSHIFT : MATH_FUN_LSHIFT),
593 		  SDAP_BITS_SIZE, MATH1, 8, 0);
594 	MATHB(p, MATH1, AND, sn_mask, MATH1, 8, IFB | IMMED2);
595 #else
596 	MATHB(p, MATH0, AND, sn_mask, MATH1, 8, IFB | IMMED2);
597 #endif
598 
599 	MATHB(p, MATH1, SHLD, MATH1, MATH1, 8, 0);
600 	MOVEB(p, DESCBUF, hfn_bearer_dir_offset_in_descbuf,
601 			MATH2, 0, 0x08, WAITCOMP | IMMED);
602 	MATHB(p, MATH1, OR, MATH2, MATH2, 8, 0);
603 
604 	SEQSTORE(p, MATH0, offset, length, 0);
605 
606 	if (dir == OP_TYPE_ENCAP_PROTOCOL) {
607 		/* Load authentication key */
608 		KEY(p, KEY1, authdata->key_enc_flags, authdata->key,
609 		    authdata->keylen, INLINE_KEY(authdata));
610 
611 		/* Set the iv for AES authentication */
612 		MOVEB(p, MATH2, 0, IFIFOAB1, 0, 8, IMMED);
613 
614 		/* Pass the header */
615 		MOVEB(p, MATH0, offset, IFIFOAB1, 0, length, IMMED);
616 
617 		/* Configure variable size for I/O */
618 		MATHB(p, SEQINSZ, SUB, ZERO, VSEQINSZ, 4, 0);
619 		MATHB(p, VSEQINSZ, ADD, PDCP_MAC_I_LEN, VSEQOUTSZ, 4, IMMED2);
620 
621 		/* Perform the authentication */
622 		ALG_OPERATION(p, OP_ALG_ALGSEL_AES, OP_ALG_AAI_CMAC,
623 			      OP_ALG_AS_INITFINAL, ICV_CHECK_DISABLE, DIR_DEC);
624 
625 		/* Configure the read of data */
626 		SEQFIFOLOAD(p, MSG1, 0, VLF | LAST1 | FLUSH1);
627 
628 		/* Save the ICV generated */
629 		MOVEB(p, CONTEXT1, 0, MATH3, 0, 4, WAITCOMP | IMMED);
630 
631 		/* conditional jump with calm added to ensure that the
632 		 * previous processing has been completed
633 		 */
634 		JUMP(p, 1, LOCAL_JUMP, ALL_TRUE, CALM);
635 		/* The CHA will be reused so we need to clear it */
636 		LOAD(p, CLRW_RESET_CLS1_CHA |
637 		     CLRW_CLR_C1KEY |
638 		     CLRW_CLR_C1CTX |
639 		     CLRW_CLR_C1ICV |
640 		     CLRW_CLR_C1DATAS |
641 		     CLRW_CLR_C1MODE,
642 		     CLRW, 0, 4, IMMED);
643 
644 		/* Load confidentiality key */
645 		KEY(p, KEY1, cipherdata->key_enc_flags, cipherdata->key,
646 		    cipherdata->keylen, INLINE_KEY(cipherdata));
647 
648 		/* Load the IV for ciphering */
649 		if (cipherdata->algtype == PDCP_CIPHER_TYPE_AES) {
650 			MOVEB(p, MATH2, 0, CONTEXT1, 16, 8, IMMED);
651 			cipher_alg_op = OP_ALG_ALGSEL_AES;
652 			cipher_alg_aai = OP_ALG_AAI_CTR;
653 		} else if (cipherdata->algtype == PDCP_CIPHER_TYPE_ZUC) {
654 			/* Set the IV for the confidentiality CHA */
655 			MOVEB(p, MATH2, 0, CONTEXT1, 0, 8, IMMED);
656 			cipher_alg_op = OP_ALG_ALGSEL_ZUCE;
657 			cipher_alg_aai = OP_ALG_AAI_F8;
658 		} else if (cipherdata->algtype == PDCP_CIPHER_TYPE_SNOW) {
659 			/* Set the IV for the confidentiality CHA */
660 			MOVEB(p, MATH2, 0, CONTEXT1, 0, 8, IMMED);
661 			cipher_alg_op = OP_ALG_ALGSEL_SNOW_F8;
662 			cipher_alg_aai = OP_ALG_AAI_F8;
663 		}
664 
665 		/* Rewind the pointer on input data to reread it */
666 		SEQINPTR(p, 0, PDCP_NULL_MAX_FRAME_LEN, RTO);
667 
668 		/* Define the ciphering operation */
669 		ALG_OPERATION(p, cipher_alg_op, cipher_alg_aai,
670 			      OP_ALG_AS_INITFINAL, ICV_CHECK_DISABLE, DIR_ENC);
671 
672 		/* Define the data to write */
673 		SEQFIFOSTORE(p, MSG, 0, 0, VLF);
674 
675 		/* Skip the header which does not need to be encrypted */
676 		SEQFIFOLOAD(p, SKIP, length, 0);
677 
678 		/* Read the rest of the data */
679 		SEQFIFOLOAD(p, MSG1, 0, VLF);
680 
681 		/* Send the ICV stored in MATH3 for encryption */
682 		MOVEB(p, MATH3, 0, IFIFOAB1, 0, 4, LAST1 | FLUSH1 | IMMED);
683 	} else {
684 		/* Load the IV for ciphering */
685 		if (cipherdata->algtype == PDCP_CIPHER_TYPE_AES) {
686 			MOVEB(p, MATH2, 0, CONTEXT1, 16, 8, IMMED);
687 			cipher_alg_op = OP_ALG_ALGSEL_AES;
688 			cipher_alg_aai = OP_ALG_AAI_CTR;
689 		} else if (cipherdata->algtype == PDCP_CIPHER_TYPE_ZUC) {
690 			/* Set the IV for the confidentiality CHA */
691 			MOVEB(p, MATH2, 0, CONTEXT1, 0, 8, IMMED);
692 			cipher_alg_op = OP_ALG_ALGSEL_ZUCE;
693 			cipher_alg_aai = OP_ALG_AAI_F8;
694 		} else if (cipherdata->algtype == PDCP_CIPHER_TYPE_SNOW) {
695 			/* Set the IV for the confidentiality CHA */
696 			MOVEB(p, MATH2, 0, CONTEXT1, 0, 8, IMMED);
697 			cipher_alg_op = OP_ALG_ALGSEL_SNOW_F8;
698 			cipher_alg_aai = OP_ALG_AAI_F8;
699 		}
700 		MOVEB(p, MATH2, 0, CONTEXT2, 0, 8, IMMED);
701 
702 		/* Read all the data */
703 		MATHB(p, SEQINSZ, SUB, ZERO, VSEQINSZ, 4, 0);
704 
705 		/* Do not write back the ICV */
706 		MATHB(p, SEQINSZ, SUB, PDCP_MAC_I_LEN, VSEQOUTSZ, 4, IMMED2);
707 
708 		/* Load the key for ciphering */
709 		KEY(p, KEY1, cipherdata->key_enc_flags, cipherdata->key,
710 		    cipherdata->keylen, INLINE_KEY(cipherdata));
711 
712 		/* Write all the data */
713 		SEQFIFOSTORE(p, MSG, 0, 0, VLF | CONT);
714 
715 		/* Define the ciphering algorithm */
716 		ALG_OPERATION(p, cipher_alg_op, cipher_alg_aai,
717 			      OP_ALG_AS_INITFINAL, ICV_CHECK_DISABLE, DIR_DEC);
718 
719 		/* Read all the data */
720 		SEQFIFOLOAD(p, MSG1, 0, VLF | LAST1 | FLUSH1);
721 
722 		/* Save the ICV which is stalling in output FIFO to MATH3 */
723 		MOVEB(p, OFIFO, 0, MATH3, 0, 4, IMMED);
724 
725 		/* conditional jump with calm added to ensure that the
726 		 * previous processing has been completed
727 		 */
728 		JUMP(p, 1, LOCAL_JUMP, ALL_TRUE, CALM);
729 		/* Reset class 1 CHA */
730 		LOAD(p, CLRW_RESET_CLS1_CHA |
731 		     CLRW_CLR_C1KEY |
732 		     CLRW_CLR_C1CTX |
733 		     CLRW_CLR_C1ICV |
734 		     CLRW_CLR_C1DATAS |
735 		     CLRW_CLR_C1MODE,
736 		     CLRW, 0, 4, IMMED);
737 
738 		/* Load the key for authentication */
739 		KEY(p, KEY1, authdata->key_enc_flags, authdata->key,
740 		    authdata->keylen, INLINE_KEY(authdata));
741 
742 		/* Start a new sequence */
743 		SEQINPTR(p, 0, 0, SOP);
744 
745 		/* Define the operation to verify the ICV */
746 		ALG_OPERATION(p, OP_ALG_ALGSEL_AES, OP_ALG_AAI_CMAC,
747 			      OP_ALG_AS_INITFINAL, ICV_CHECK_ENABLE, DIR_DEC);
748 
749 		/* Set the variable size input */
750 		MATHB(p, SEQINSZ, SUB, ZERO, VSEQINSZ, 4, 0);
751 
752 		MOVE(p, CONTEXT2, 0, IFIFOAB1, 0, 8, IMMED);
753 
754 		SEQFIFOLOAD(p, MSG1, 0, VLF | LAST1 | FLUSH1);
755 
756 		/* Define an NFIFO entry to load the ICV saved */
757 		LOAD(p, NFIFOENTRY_STYPE_ALTSOURCE |
758 		     NFIFOENTRY_DEST_CLASS1 |
759 		     NFIFOENTRY_DTYPE_ICV |
760 		     NFIFOENTRY_LC1 |
761 		     NFIFOENTRY_FC1 | 4, NFIFO_SZL, 0, 4, IMMED);
762 
763 		/* Load the ICV */
764 		MOVEB(p, MATH3, 0, ALTSOURCE, 0, 4, IMMED);
765 	}
766 
767 	return 0;
768 }
769 
770 static inline int
pdcp_sdap_insert_cplane_null_op(struct program * p,bool swap __maybe_unused,struct alginfo * cipherdata,struct alginfo * authdata,unsigned int dir,enum pdcp_sn_size sn_size,enum pdb_type_e pdb_type __maybe_unused)771 pdcp_sdap_insert_cplane_null_op(struct program *p,
772 			   bool swap __maybe_unused,
773 			   struct alginfo *cipherdata,
774 			   struct alginfo *authdata,
775 			   unsigned int dir,
776 			   enum pdcp_sn_size sn_size,
777 			   enum pdb_type_e pdb_type __maybe_unused)
778 {
779 	return pdcp_insert_cplane_null_op(p, swap, cipherdata, authdata, dir,
780 					  sn_size);
781 }
782 
783 static inline int
pdcp_sdap_insert_cplane_int_only_op(struct program * p,bool swap __maybe_unused,struct alginfo * cipherdata,struct alginfo * authdata,unsigned int dir,enum pdcp_sn_size sn_size,enum pdb_type_e pdb_type __maybe_unused)784 pdcp_sdap_insert_cplane_int_only_op(struct program *p,
785 			   bool swap __maybe_unused,
786 			   struct alginfo *cipherdata,
787 			   struct alginfo *authdata,
788 			   unsigned int dir,
789 			   enum pdcp_sn_size sn_size,
790 			   enum pdb_type_e pdb_type __maybe_unused)
791 {
792 	return pdcp_insert_cplane_int_only_op(p, swap, cipherdata, authdata,
793 				dir, sn_size);
794 }
795 
pdcp_sdap_insert_with_int_op(struct program * p,bool swap __maybe_unused,struct alginfo * cipherdata,struct alginfo * authdata,enum pdcp_sn_size sn_size,unsigned int dir,enum pdb_type_e pdb_type)796 static int pdcp_sdap_insert_with_int_op(
797 	struct program *p, bool swap __maybe_unused, struct alginfo *cipherdata,
798 	struct alginfo *authdata, enum pdcp_sn_size sn_size,
799 	unsigned int dir,
800 	enum pdb_type_e pdb_type)
801 {
802 	static int (
803 		*pdcp_cp_fp[PDCP_CIPHER_TYPE_INVALID][PDCP_AUTH_TYPE_INVALID])(
804 		struct program *, bool swap, struct alginfo *, struct alginfo *,
805 		unsigned int dir, enum pdcp_sn_size, enum pdb_type_e pdb_type) = {
806 		{
807 			/* NULL */
808 			pdcp_sdap_insert_cplane_null_op,     /* NULL */
809 			pdcp_sdap_insert_cplane_int_only_op, /* SNOW f9 */
810 			pdcp_sdap_insert_cplane_int_only_op, /* AES CMAC */
811 			pdcp_sdap_insert_cplane_int_only_op  /* ZUC-I */
812 		},
813 		{
814 			/* SNOW f8 */
815 			pdcp_sdap_insert_enc_only_op, /* NULL */
816 			pdcp_sdap_insert_snoop_op,    /* SNOW f9 */
817 			pdcp_sdap_insert_no_snoop_op, /* AES CMAC */
818 			pdcp_sdap_insert_snoop_op     /* ZUC-I */
819 		},
820 		{
821 			/* AES CTR */
822 			pdcp_sdap_insert_enc_only_op, /* NULL */
823 			pdcp_sdap_insert_snoop_op,    /* SNOW f9 */
824 			pdcp_sdap_insert_no_snoop_op, /* AES CMAC */
825 			pdcp_sdap_insert_snoop_op     /* ZUC-I */
826 		},
827 		{
828 			/* ZUC-E */
829 			pdcp_sdap_insert_enc_only_op, /* NULL */
830 			pdcp_sdap_insert_snoop_op,    /* SNOW f9 */
831 			pdcp_sdap_insert_no_snoop_op, /* AES CMAC */
832 			pdcp_sdap_insert_snoop_op     /* ZUC-I */
833 		},
834 	};
835 	int err;
836 
837 	err = pdcp_cp_fp[cipherdata->algtype]
838 			[authdata->algtype](p, swap, cipherdata, authdata, dir,
839 					sn_size, pdb_type);
840 	if (err)
841 		return err;
842 
843 	return 0;
844 }
845 
846 static inline int
cnstr_shdsc_pdcp_sdap_u_plane(uint32_t * descbuf,bool ps,bool swap,enum pdcp_sn_size sn_size,uint32_t hfn,unsigned short bearer,unsigned short direction,uint32_t hfn_threshold,struct alginfo * cipherdata,struct alginfo * authdata,uint32_t caps_mode)847 cnstr_shdsc_pdcp_sdap_u_plane(uint32_t *descbuf,
848 			       bool ps,
849 			       bool swap,
850 			       enum pdcp_sn_size sn_size,
851 			       uint32_t hfn,
852 			       unsigned short bearer,
853 			       unsigned short direction,
854 			       uint32_t hfn_threshold,
855 			       struct alginfo *cipherdata,
856 			       struct alginfo *authdata,
857 			       uint32_t caps_mode)
858 {
859 	struct program prg;
860 	struct program *p = &prg;
861 	int err;
862 	enum pdb_type_e pdb_type;
863 	static enum rta_share_type
864 		desc_share[PDCP_CIPHER_TYPE_INVALID][PDCP_AUTH_TYPE_INVALID] = {
865 			{
866 				/* NULL */
867 				SHR_WAIT,   /* NULL */
868 				SHR_WAIT, /* SNOW f9 */
869 				SHR_WAIT, /* AES CMAC */
870 				SHR_WAIT  /* ZUC-I */
871 			},
872 			{
873 				/* SNOW f8 */
874 				SHR_WAIT, /* NULL */
875 				SHR_WAIT, /* SNOW f9 */
876 				SHR_WAIT,   /* AES CMAC */
877 				SHR_WAIT    /* ZUC-I */
878 			},
879 			{
880 				/* AES CTR */
881 				SHR_WAIT, /* NULL */
882 				SHR_WAIT, /* SNOW f9 */
883 				SHR_WAIT, /* AES CMAC */
884 				SHR_WAIT    /* ZUC-I */
885 			},
886 			{
887 				/* ZUC-E */
888 				SHR_WAIT, /* NULL */
889 				SHR_WAIT,   /* SNOW f9 */
890 				SHR_WAIT,   /* AES CMAC */
891 				SHR_WAIT    /* ZUC-I */
892 			},
893 		};
894 
895 	LABEL(pdb_end);
896 
897 	/* Check the confidentiality algorithm is supported by the code */
898 	switch (cipherdata->algtype) {
899 	case PDCP_CIPHER_TYPE_NULL:
900 	case PDCP_CIPHER_TYPE_SNOW:
901 	case PDCP_CIPHER_TYPE_AES:
902 	case PDCP_CIPHER_TYPE_ZUC:
903 		break;
904 	default:
905 		pr_err("Cipher algorithm not supported: %d\n",
906 				cipherdata->algtype);
907 		return -ENOTSUP;
908 	}
909 
910 	/* Check the authentication algorithm is supported by the code */
911 	if (authdata) {
912 		switch (authdata->algtype) {
913 		case PDCP_AUTH_TYPE_NULL:
914 		case PDCP_AUTH_TYPE_SNOW:
915 		case PDCP_AUTH_TYPE_AES:
916 		case PDCP_AUTH_TYPE_ZUC:
917 			break;
918 		default:
919 			pr_err("Auth algorithm not supported: %d\n",
920 					authdata->algtype);
921 			return -ENOTSUP;
922 		}
923 	}
924 
925 	/* Check the Sequence Number size is supported by the code */
926 	switch (sn_size) {
927 	case PDCP_SN_SIZE_5:
928 	case PDCP_SN_SIZE_7:
929 	case PDCP_SN_SIZE_12:
930 	case PDCP_SN_SIZE_15:
931 	case PDCP_SN_SIZE_18:
932 		break;
933 	default:
934 		pr_err("SN size not supported: %d\n", sn_size);
935 		return -ENOTSUP;
936 	}
937 
938 	/* Initialize the program */
939 	PROGRAM_CNTXT_INIT(p, descbuf, 0);
940 
941 	if (swap)
942 		PROGRAM_SET_BSWAP(p);
943 
944 	if (ps)
945 		PROGRAM_SET_36BIT_ADDR(p);
946 
947 	/* Select the shared descriptor sharing mode */
948 	if (authdata)
949 		SHR_HDR(p, desc_share[cipherdata->algtype][authdata->algtype],
950 			0, 0);
951 	else
952 		SHR_HDR(p, SHR_WAIT, 0, 0);
953 
954 	/* Construct the PDB */
955 	pdb_type = cnstr_pdcp_u_plane_pdb(p, sn_size, hfn, bearer, direction,
956 					  hfn_threshold, cipherdata, authdata);
957 	if (pdb_type == PDCP_PDB_TYPE_INVALID) {
958 		pr_err("Error creating PDCP UPlane PDB\n");
959 		return -EINVAL;
960 	}
961 	SET_LABEL(p, pdb_end);
962 
963 	/* Inser the HFN override operation */
964 	err = insert_hfn_ov_op(p, sn_size, pdb_type, false);
965 	if (err)
966 		return err;
967 
968 	/* Create the descriptor */
969 	if (!authdata) {
970 		if (cipherdata->algtype == PDCP_CIPHER_TYPE_NULL) {
971 			insert_copy_frame_op(p, cipherdata,
972 					     OP_TYPE_ENCAP_PROTOCOL);
973 		} else {
974 			err = pdcp_sdap_insert_no_int_op(p, swap, cipherdata,
975 							 caps_mode,
976 							 sn_size, pdb_type);
977 			if (err) {
978 				pr_err("Fail pdcp_sdap_insert_no_int_op\n");
979 				return err;
980 			}
981 		}
982 	} else {
983 		err = pdcp_sdap_insert_with_int_op(p, swap, cipherdata,
984 						   authdata, sn_size,
985 						   caps_mode, pdb_type);
986 		if (err) {
987 			pr_err("Fail pdcp_sdap_insert_with_int_op\n");
988 			return err;
989 		}
990 	}
991 
992 	PATCH_HDR(p, 0, pdb_end);
993 
994 	return PROGRAM_FINALIZE(p);
995 }
996 
997 /**
998  * cnstr_shdsc_pdcp_sdap_u_plane_encap - Function for creating a PDCP-SDAP
999  *                                       User Plane encapsulation descriptor.
1000  * @descbuf: pointer to buffer for descriptor construction
1001  * @ps: if 36/40bit addressing is desired, this parameter must be true
1002  * @swap: must be true when core endianness doesn't match SEC endianness
1003  * @sn_size: selects Sequence Number Size: 7/12/15 bits
1004  * @hfn: starting Hyper Frame Number to be used together with the SN from the
1005  *       PDCP frames.
1006  * @bearer: radio bearer ID
1007  * @direction: the direction of the PDCP frame (UL/DL)
1008  * @hfn_threshold: HFN value that once reached triggers a warning from SEC that
1009  *                 keys should be renegotiated at the earliest convenience.
1010  * @cipherdata: pointer to block cipher transform definitions
1011  *              Valid algorithm values are those from cipher_type_pdcp enum.
1012  *
1013  * Return: size of descriptor written in words or negative number on error.
1014  *         Once the function returns, the value of this parameter can be used
1015  *         for reclaiming the space that wasn't used for the descriptor.
1016  *
1017  * Note: descbuf must be large enough to contain a full 256 byte long
1018  * descriptor; after the function returns, by subtracting the actual number of
1019  * bytes used, the user can reuse the remaining buffer space for other purposes.
1020  */
1021 static inline int
cnstr_shdsc_pdcp_sdap_u_plane_encap(uint32_t * descbuf,bool ps,bool swap,enum pdcp_sn_size sn_size,uint32_t hfn,unsigned short bearer,unsigned short direction,uint32_t hfn_threshold,struct alginfo * cipherdata,struct alginfo * authdata)1022 cnstr_shdsc_pdcp_sdap_u_plane_encap(uint32_t *descbuf,
1023 			       bool ps,
1024 			       bool swap,
1025 			       enum pdcp_sn_size sn_size,
1026 			       uint32_t hfn,
1027 			       unsigned short bearer,
1028 			       unsigned short direction,
1029 			       uint32_t hfn_threshold,
1030 			       struct alginfo *cipherdata,
1031 			       struct alginfo *authdata)
1032 {
1033 	return cnstr_shdsc_pdcp_sdap_u_plane(descbuf, ps, swap, sn_size,
1034 			hfn, bearer, direction, hfn_threshold, cipherdata,
1035 			authdata, OP_TYPE_ENCAP_PROTOCOL);
1036 }
1037 
1038 /**
1039  * cnstr_shdsc_pdcp_sdap_u_plane_decap - Function for creating a PDCP-SDAP
1040  *                                       User Plane decapsulation descriptor.
1041  * @descbuf: pointer to buffer for descriptor construction
1042  * @ps: if 36/40bit addressing is desired, this parameter must be true
1043  * @swap: must be true when core endianness doesn't match SEC endianness
1044  * @sn_size: selects Sequence Number Size: 7/12/15 bits
1045  * @hfn: starting Hyper Frame Number to be used together with the SN from the
1046  *       PDCP frames.
1047  * @bearer: radio bearer ID
1048  * @direction: the direction of the PDCP frame (UL/DL)
1049  * @hfn_threshold: HFN value that once reached triggers a warning from SEC that
1050  *                 keys should be renegotiated at the earliest convenience.
1051  * @cipherdata: pointer to block cipher transform definitions
1052  *              Valid algorithm values are those from cipher_type_pdcp enum.
1053  *
1054  * Return: size of descriptor written in words or negative number on error.
1055  *         Once the function returns, the value of this parameter can be used
1056  *         for reclaiming the space that wasn't used for the descriptor.
1057  *
1058  * Note: descbuf must be large enough to contain a full 256 byte long
1059  * descriptor; after the function returns, by subtracting the actual number of
1060  * bytes used, the user can reuse the remaining buffer space for other purposes.
1061  */
1062 static inline int
cnstr_shdsc_pdcp_sdap_u_plane_decap(uint32_t * descbuf,bool ps,bool swap,enum pdcp_sn_size sn_size,uint32_t hfn,unsigned short bearer,unsigned short direction,uint32_t hfn_threshold,struct alginfo * cipherdata,struct alginfo * authdata)1063 cnstr_shdsc_pdcp_sdap_u_plane_decap(uint32_t *descbuf,
1064 			       bool ps,
1065 			       bool swap,
1066 			       enum pdcp_sn_size sn_size,
1067 			       uint32_t hfn,
1068 			       unsigned short bearer,
1069 			       unsigned short direction,
1070 			       uint32_t hfn_threshold,
1071 			       struct alginfo *cipherdata,
1072 			       struct alginfo *authdata)
1073 {
1074 	return cnstr_shdsc_pdcp_sdap_u_plane(descbuf, ps, swap, sn_size, hfn,
1075 			bearer, direction, hfn_threshold, cipherdata, authdata,
1076 			OP_TYPE_DECAP_PROTOCOL);
1077 }
1078 
1079 #endif /* __DESC_SDAP_H__ */
1080