xref: /dpdk/drivers/common/dpaax/caamflib/desc/pdcp.h (revision 2369bc1343fa5aac2890b2a3e12d65a2f1a2fd31)
1 /* SPDX-License-Identifier: BSD-3-Clause or GPL-2.0+
2  * Copyright 2008-2013 Freescale Semiconductor, Inc.
3  * Copyright 2019-2023 NXP
4  */
5 
6 #ifndef __DESC_PDCP_H__
7 #define __DESC_PDCP_H__
8 
9 #include "rta.h"
10 #include "common.h"
11 
12 /**
13  * DOC: PDCP Shared Descriptor Constructors
14  *
15  * Shared descriptors for PDCP protocol.
16  */
17 
18 /**
19  * PDCP_NULL_MAX_FRAME_LEN - The maximum frame frame length that is supported by
20  *                           PDCP NULL protocol.
21  */
22 #define PDCP_NULL_MAX_FRAME_LEN		0x00002FFF
23 
24 /**
25  * PDCP_MAC_I_LEN - The length of the MAC-I for PDCP protocol operation
26  */
27 #define PDCP_MAC_I_LEN			0x00000004
28 
29 /**
30  * PDCP_MAX_FRAME_LEN_STATUS - The status returned in FD status/command field in
31  *                             case the input frame is larger than
32  *                             PDCP_NULL_MAX_FRAME_LEN.
33  */
34 #define PDCP_MAX_FRAME_LEN_STATUS	0xF1
35 
36 /**
37  * PDCP_C_PLANE_SN_MASK - This mask is used in the PDCP descriptors for
38  *                        extracting the sequence number (SN) from the PDCP
39  *                        Control Plane header. For PDCP Control Plane, the SN
40  *                        is constant (5 bits) as opposed to PDCP Data Plane
41  *                        (7/12/15 bits).
42  */
43 #define PDCP_C_PLANE_SN_MASK		0x1F000000
44 #define PDCP_C_PLANE_SN_MASK_BE		0x0000001F
45 
46 /**
47  * PDCP_7BIT_SN_MASK - This mask is used in the PDCP descriptors for
48  *                              extracting the sequence number (SN) from the
49  *                              PDCP User Plane header.
50  */
51 #define PDCP_7BIT_SN_MASK		0x7F000000
52 #define PDCP_7BIT_SN_MASK_BE		0x0000007F
53 
54 /**
55  * PDCP_12BIT_SN_MASK - This mask is used in the PDCP descriptors for
56  *                              extracting the sequence number (SN) from the
57  *                              PDCP User Plane header.
58  */
59 #define PDCP_12BIT_SN_MASK		0xFF0F0000
60 #define PDCP_12BIT_SN_MASK_BE		0x00000FFF
61 
62 /**
63  * PDCP_U_PLANE_15BIT_SN_MASK - This mask is used in the PDCP descriptors for
64  *                              extracting the sequence number (SN) from the
65  *                              PDCP User Plane header. For PDCP Control Plane,
66  *                              the SN is constant (5 bits) as opposed to PDCP
67  *                              Data Plane (7/12/15 bits).
68  */
69 #define PDCP_U_PLANE_15BIT_SN_MASK	0xFF7F0000
70 #define PDCP_U_PLANE_15BIT_SN_MASK_BE	0x00007FFF
71 
72 /**
73  * PDCP_U_PLANE_18BIT_SN_MASK - This mask is used in the PDCP descriptors for
74  *                              extracting the sequence number (SN) from the
75  *                              PDCP User Plane header.
76  */
77 #define PDCP_U_PLANE_18BIT_SN_MASK	0xFFFF0300
78 #define PDCP_U_PLANE_18BIT_SN_MASK_BE	0x0003FFFF
79 
80 /**
81  * PDCP_BEARER_MASK - This mask is used masking out the bearer for PDCP
82  *                    processing with SNOW f9 in LTE.
83  *
84  * The value on which this mask is applied is formatted as below:
85  *     Count-C (32 bit) | Bearer (5 bit) | Direction (1 bit) | 0 (26 bits)
86  *
87  * Applying this mask is done for creating the upper 64 bits of the IV needed
88  * for SNOW f9.
89  *
90  * The lower 32 bits of the mask are used for masking the direction for AES
91  * CMAC IV.
92  */
93 #define PDCP_BEARER_MASK		0x00000004FFFFFFFFull
94 #define PDCP_BEARER_MASK_BE		0xFFFFFFFF04000000ull
95 
96 /**
97  * PDCP_DIR_MASK - This mask is used masking out the direction for PDCP
98  *                 processing with SNOW f9 in LTE.
99  *
100  * The value on which this mask is applied is formatted as below:
101  *     Bearer (5 bit) | Direction (1 bit) | 0 (26 bits)
102  *
103  * Applying this mask is done for creating the lower 32 bits of the IV needed
104  * for SNOW f9.
105  *
106  * The upper 32 bits of the mask are used for masking the direction for AES
107  * CMAC IV.
108  */
109 #define PDCP_DIR_MASK			0x00000000000000F8ull
110 #define PDCP_DIR_MASK_BE			0xF800000000000000ull
111 
112 /**
113  * PDCP_NULL_INT_MAC_I_VAL - The value of the PDCP PDU MAC-I in case NULL
114  *                           integrity is used.
115  */
116 
117 #define PDCP_NULL_INT_MAC_I_VAL		0x00000000
118 
119 /**
120  * PDCP_NULL_INT_ICV_CHECK_FAILED_STATUS - The status used to report ICV check
121  *                                         failed in case of NULL integrity
122  *                                         Control Plane processing.
123  */
124 #define PDCP_NULL_INT_ICV_CHECK_FAILED_STATUS	0x0A
125 /**
126  * PDCP_DPOVRD_HFN_OV_EN - Value to be used in the FD status/cmd field to
127  *                         indicate the HFN override mechanism is active for the
128  *                         frame.
129  */
130 #define PDCP_DPOVRD_HFN_OV_EN		0x80000000
131 
132 /**
133  * PDCP_P4080REV2_HFN_OV_BUFLEN - The length in bytes of the supplementary space
134  *                                that must be provided by the user at the
135  *                                beginning of the input frame buffer for
136  *                                P4080 REV 2.
137  *
138  * The format of the frame buffer is the following:
139  *
140  *  |<---PDCP_P4080REV2_HFN_OV_BUFLEN-->|
141  * //===================================||============||==============\\
142  * || PDCP_DPOVRD_HFN_OV_EN | HFN value || PDCP Header|| PDCP Payload ||
143  * \\===================================||============||==============//
144  *
145  * If HFN override mechanism is not desired, then the MSB of the first 4 bytes
146  * must be set to 0b.
147  */
148 #define PDCP_P4080REV2_HFN_OV_BUFLEN	4
149 
150 /**
151  * enum cipher_type_pdcp - Type selectors for cipher types in PDCP protocol OP
152  *                         instructions.
153  * @PDCP_CIPHER_TYPE_NULL: NULL
154  * @PDCP_CIPHER_TYPE_SNOW: SNOW F8
155  * @PDCP_CIPHER_TYPE_AES: AES
156  * @PDCP_CIPHER_TYPE_ZUC: ZUCE
157  * @PDCP_CIPHER_TYPE_INVALID: invalid option
158  */
159 enum cipher_type_pdcp {
160 	PDCP_CIPHER_TYPE_NULL,
161 	PDCP_CIPHER_TYPE_SNOW,
162 	PDCP_CIPHER_TYPE_AES,
163 	PDCP_CIPHER_TYPE_ZUC,
164 	PDCP_CIPHER_TYPE_INVALID
165 };
166 
167 /**
168  * enum auth_type_pdcp - Type selectors for integrity types in PDCP protocol OP
169  *                       instructions.
170  * @PDCP_AUTH_TYPE_NULL: NULL
171  * @PDCP_AUTH_TYPE_SNOW: SNOW F9
172  * @PDCP_AUTH_TYPE_AES: AES CMAC
173  * @PDCP_AUTH_TYPE_ZUC: ZUCA
174  * @PDCP_AUTH_TYPE_INVALID: invalid option
175  */
176 enum auth_type_pdcp {
177 	PDCP_AUTH_TYPE_NULL,
178 	PDCP_AUTH_TYPE_SNOW,
179 	PDCP_AUTH_TYPE_AES,
180 	PDCP_AUTH_TYPE_ZUC,
181 	PDCP_AUTH_TYPE_INVALID
182 };
183 
184 /**
185  * enum pdcp_dir - Type selectors for direction for PDCP protocol
186  * @PDCP_DIR_UPLINK: uplink direction
187  * @PDCP_DIR_DOWNLINK: downlink direction
188  * @PDCP_DIR_INVALID: invalid option
189  */
190 enum pdcp_dir {
191 	PDCP_DIR_UPLINK = 0,
192 	PDCP_DIR_DOWNLINK = 1,
193 	PDCP_DIR_INVALID
194 };
195 
196 /**
197  * enum pdcp_plane - PDCP domain selectors
198  * @PDCP_CONTROL_PLANE: Control Plane
199  * @PDCP_DATA_PLANE: Data Plane
200  * @PDCP_SHORT_MAC: Short MAC
201  */
202 enum pdcp_plane {
203 	PDCP_CONTROL_PLANE,
204 	PDCP_DATA_PLANE,
205 	PDCP_SHORT_MAC
206 };
207 
208 /**
209  * enum pdcp_sn_size - Sequence Number Size selectors for PDCP protocol
210  * @PDCP_SN_SIZE_5: 5bit sequence number
211  * @PDCP_SN_SIZE_7: 7bit sequence number
212  * @PDCP_SN_SIZE_12: 12bit sequence number
213  * @PDCP_SN_SIZE_15: 15bit sequence number
214  * @PDCP_SN_SIZE_18: 18bit sequence number
215  */
216 enum pdcp_sn_size {
217 	PDCP_SN_SIZE_5 = 5,
218 	PDCP_SN_SIZE_7 = 7,
219 	PDCP_SN_SIZE_12 = 12,
220 	PDCP_SN_SIZE_15 = 15,
221 	PDCP_SN_SIZE_18 = 18
222 };
223 
224 /*
225  * PDCP Control Plane Protocol Data Blocks
226  */
227 #define PDCP_C_PLANE_PDB_HFN_SHIFT		5
228 #define PDCP_C_PLANE_PDB_BEARER_SHIFT		27
229 #define PDCP_C_PLANE_PDB_DIR_SHIFT		26
230 #define PDCP_C_PLANE_PDB_HFN_THR_SHIFT		5
231 
232 #define PDCP_U_PLANE_PDB_OPT_SHORT_SN		0x2
233 #define PDCP_U_PLANE_PDB_OPT_15B_SN		0x4
234 #define PDCP_U_PLANE_PDB_OPT_18B_SN		0x6
235 #define PDCP_U_PLANE_PDB_SHORT_SN_HFN_SHIFT	7
236 #define PDCP_U_PLANE_PDB_LONG_SN_HFN_SHIFT	12
237 #define PDCP_U_PLANE_PDB_15BIT_SN_HFN_SHIFT	15
238 #define PDCP_U_PLANE_PDB_18BIT_SN_HFN_SHIFT	18
239 #define PDCP_U_PLANE_PDB_BEARER_SHIFT		27
240 #define PDCP_U_PLANE_PDB_DIR_SHIFT		26
241 #define PDCP_U_PLANE_PDB_SHORT_SN_HFN_THR_SHIFT	7
242 #define PDCP_U_PLANE_PDB_LONG_SN_HFN_THR_SHIFT	12
243 #define PDCP_U_PLANE_PDB_15BIT_SN_HFN_THR_SHIFT	15
244 #define PDCP_U_PLANE_PDB_18BIT_SN_HFN_THR_SHIFT	18
245 
246 struct pdcp_pdb {
247 	union {
248 		uint32_t opt;
249 		uint32_t rsvd;
250 	} opt_res;
251 	uint32_t hfn_res;	/* HyperFrame number,(27, 25 or 21 bits),
252 				 * left aligned & right-padded with zeros.
253 				 */
254 	uint32_t bearer_dir_res;/* Bearer(5 bits), packet direction (1 bit),
255 				 * left aligned & right-padded with zeros.
256 				 */
257 	uint32_t hfn_thr_res;	/* HyperFrame number threshold (27, 25 or 21
258 				 * bits), left aligned & right-padded with
259 				 * zeros.
260 				 */
261 };
262 
263 /*
264  * PDCP internal PDB types
265  */
266 enum pdb_type_e {
267 	PDCP_PDB_TYPE_NO_PDB,
268 	PDCP_PDB_TYPE_FULL_PDB,
269 	PDCP_PDB_TYPE_REDUCED_PDB,
270 	PDCP_PDB_TYPE_INVALID
271 };
272 
273 #define REDUCED_PDB_DESCBUF_HFN_BEARER_DIR_OFFSET 4
274 #define FULL_PDB_DESCBUF_HFN_BEARER_DIR_OFFSET 8
275 
276 /**
277  * rta_inline_pdcp_query() - Provide indications if a key can be passed as
278  *                           immediate data or shall be referenced in a
279  *                           shared descriptor.
280  * Return: 0 if data can be inlined or 1 if referenced.
281  */
282 static inline int
283 rta_inline_pdcp_query(enum auth_type_pdcp auth_alg,
284 		      enum cipher_type_pdcp cipher_alg,
285 		      enum pdcp_sn_size sn_size,
286 		      int8_t hfn_ovd)
287 {
288 	/**
289 	 * Shared Descriptors for some of the cases does not fit in the
290 	 * MAX_DESC_SIZE of the descriptor especially when non-protocol
291 	 * descriptors are formed as in 18bit cases and when HFN override
292 	 * is enabled as 2 extra words are added in the job descriptor.
293 	 * The cases which exceed are for RTA_SEC_ERA=8 and HFN override
294 	 * enabled and 18bit uplane and either of following Algo combinations.
295 	 * - SNOW-AES
296 	 * - AES-SNOW
297 	 * - SNOW-SNOW
298 	 * - ZUC-SNOW
299 	 *
300 	 * We cannot make inline for all cases, as this will impact performance
301 	 * due to extra memory accesses for the keys.
302 	 */
303 	if ((rta_sec_era == RTA_SEC_ERA_8) && hfn_ovd &&
304 			(sn_size == PDCP_SN_SIZE_18) &&
305 			((cipher_alg == PDCP_CIPHER_TYPE_SNOW &&
306 				auth_alg == PDCP_AUTH_TYPE_AES) ||
307 			(cipher_alg == PDCP_CIPHER_TYPE_AES &&
308 				auth_alg == PDCP_AUTH_TYPE_SNOW) ||
309 			(cipher_alg == PDCP_CIPHER_TYPE_SNOW &&
310 				auth_alg == PDCP_AUTH_TYPE_SNOW) ||
311 			(cipher_alg == PDCP_CIPHER_TYPE_ZUC &&
312 				auth_alg == PDCP_AUTH_TYPE_SNOW))) {
313 
314 		return 1;
315 	}
316 
317 	return 0;
318 }
319 
320 /*
321  * Function for appending the portion of a PDCP Control Plane shared descriptor
322  * which performs NULL encryption and integrity (i.e. copies the input frame
323  * to the output frame, appending 32 bits of zeros at the end (MAC-I for
324  * NULL integrity).
325  */
326 static inline int
327 pdcp_insert_cplane_null_op(struct program *p,
328 			   bool swap __maybe_unused,
329 			   struct alginfo *cipherdata __maybe_unused,
330 			   struct alginfo *authdata __maybe_unused,
331 			   unsigned int dir,
332 			   enum pdcp_sn_size sn_size __maybe_unused)
333 {
334 	MATHB(p, SEQINSZ, ADD, ZERO, VSEQINSZ, 4, 0);
335 	if (dir == OP_TYPE_ENCAP_PROTOCOL)
336 		MATHB(p, SEQINSZ, ADD, PDCP_MAC_I_LEN, VSEQOUTSZ, 4,
337 		      IMMED2);
338 	else
339 		MATHB(p, SEQINSZ, SUB, PDCP_MAC_I_LEN, VSEQOUTSZ, 4,
340 		      IMMED2);
341 
342 	MATHB(p, VSEQINSZ, SUB, PDCP_NULL_MAX_FRAME_LEN, NONE, 4,
343 	      IMMED2);
344 	JUMP(p, PDCP_MAX_FRAME_LEN_STATUS, HALT_STATUS, ALL_FALSE, MATH_N);
345 
346 	if (dir == OP_TYPE_ENCAP_PROTOCOL)
347 		MATHB(p, VSEQINSZ, ADD, ZERO, MATH0, 4, 0);
348 	else
349 		MATHB(p, VSEQOUTSZ, ADD, ZERO, MATH0, 4, 0);
350 
351 	SEQFIFOSTORE(p, MSG, 0, 0, VLF);
352 	SEQFIFOLOAD(p, MSG1, 0, VLF | LAST1 | FLUSH1);
353 
354 	MOVE(p, AB1, 0, OFIFO, 0, MATH0, 0);
355 
356 	if (dir == OP_TYPE_ENCAP_PROTOCOL) {
357 		MATHB(p, MATH1, XOR, MATH1, MATH0, 8, 0);
358 		MOVE(p, MATH0, 0, OFIFO, 0, 4, IMMED);
359 	}
360 
361 	return 0;
362 }
363 
364 static inline int
365 insert_copy_frame_op(struct program *p,
366 		     struct alginfo *cipherdata __maybe_unused,
367 		     unsigned int dir __maybe_unused)
368 {
369 	MATHB(p, SEQINSZ, ADD, ZERO, VSEQINSZ,  4, 0);
370 	MATHB(p, SEQINSZ, ADD, ZERO, VSEQOUTSZ,  4, 0);
371 
372 	MATHB(p, SEQINSZ, SUB, PDCP_NULL_MAX_FRAME_LEN, NONE,  4,
373 	      IFB | IMMED2);
374 	JUMP(p, PDCP_MAX_FRAME_LEN_STATUS, HALT_STATUS, ALL_FALSE, MATH_N);
375 
376 	MATHB(p, VSEQINSZ, ADD, ZERO, MATH0,  4, 0);
377 
378 	SEQFIFOLOAD(p, MSG1, 0, VLF | LAST1 | FLUSH1);
379 
380 	MOVE(p, AB1, 0, OFIFO, 0, MATH0, 0);
381 
382 	SEQFIFOSTORE(p, MSG, 0, 0, VLF);
383 
384 	return 0;
385 }
386 
387 static inline int
388 pdcp_insert_cplane_int_only_op(struct program *p,
389 			       bool swap __maybe_unused,
390 			       struct alginfo *cipherdata __maybe_unused,
391 			       struct alginfo *authdata, unsigned int dir,
392 			       enum pdcp_sn_size sn_size)
393 {
394 	uint32_t offset = 0, length = 0, sn_mask = 0;
395 
396 	/* 12 bit SN is only supported for protocol offload case */
397 	if (sn_size == PDCP_SN_SIZE_12) {
398 		KEY(p, KEY2, authdata->key_enc_flags, authdata->key,
399 		    authdata->keylen, INLINE_KEY(authdata));
400 
401 		PROTOCOL(p, dir, OP_PCLID_LTE_PDCP_USER_RN,
402 			 (uint16_t)authdata->algtype);
403 		return 0;
404 	}
405 
406 	/* Non-proto is supported only for 5bit cplane and 18bit uplane */
407 	switch (sn_size) {
408 	case PDCP_SN_SIZE_5:
409 		offset = 7;
410 		length = 1;
411 		sn_mask = (swap == false) ? PDCP_C_PLANE_SN_MASK :
412 					PDCP_C_PLANE_SN_MASK_BE;
413 		break;
414 	case PDCP_SN_SIZE_18:
415 		offset = 5;
416 		length = 3;
417 		sn_mask = (swap == false) ? PDCP_U_PLANE_18BIT_SN_MASK :
418 					PDCP_U_PLANE_18BIT_SN_MASK_BE;
419 		break;
420 	case PDCP_SN_SIZE_7:
421 	case PDCP_SN_SIZE_12:
422 	case PDCP_SN_SIZE_15:
423 		pr_err("Invalid sn_size for %s\n", __func__);
424 		return -ENOTSUP;
425 
426 	}
427 
428 	switch (authdata->algtype) {
429 	case PDCP_AUTH_TYPE_SNOW:
430 		/* Insert Auth Key */
431 		KEY(p, KEY2, authdata->key_enc_flags, authdata->key,
432 		    authdata->keylen, INLINE_KEY(authdata));
433 		SEQLOAD(p, MATH0, offset, length, 0);
434 		JUMP(p, 1, LOCAL_JUMP, ALL_TRUE, CALM);
435 
436 		SEQINPTR(p, 0, length, RTO);
437 
438 		if (swap == false) {
439 			MATHB(p, MATH0, AND, sn_mask, MATH1,  8,
440 			      IFB | IMMED2);
441 			MATHB(p, MATH1, SHLD, MATH1, MATH1,  8, 0);
442 
443 			MOVEB(p, DESCBUF, 8, MATH2, 0, 8, WAITCOMP | IMMED);
444 
445 			MATHB(p, MATH2, AND, PDCP_BEARER_MASK, MATH2, 8,
446 			      IMMED2);
447 			MOVEB(p, DESCBUF, 0x0C, MATH3, 0, 4, WAITCOMP | IMMED);
448 			MATHB(p, MATH3, AND, PDCP_DIR_MASK, MATH3, 8, IMMED2);
449 			MATHB(p, MATH1, OR, MATH2, MATH2, 8, 0);
450 			MOVEB(p, MATH2, 0, CONTEXT2, 0, 0x0C, WAITCOMP | IMMED);
451 		} else {
452 			MATHB(p, MATH0, AND, sn_mask, MATH1,  8,
453 			      IFB | IMMED2);
454 			MATHB(p, MATH1, SHLD, MATH1, MATH1,  8, 0);
455 
456 			MOVE(p, DESCBUF, 8, MATH2, 0, 8, WAITCOMP | IMMED);
457 			MATHB(p, MATH2, AND, PDCP_BEARER_MASK_BE, MATH2, 8,
458 			      IMMED2);
459 
460 			MOVE(p, DESCBUF, 0x0C, MATH3, 0, 4, WAITCOMP | IMMED);
461 			MATHB(p, MATH3, AND, PDCP_DIR_MASK_BE, MATH3, 8,
462 			      IMMED2);
463 			MATHB(p, MATH1, OR, MATH2, MATH2, 8, 0);
464 			MOVE(p, MATH2, 0, CONTEXT2, 0, 0x0C, WAITCOMP | IMMED);
465 		}
466 
467 		if (dir == OP_TYPE_DECAP_PROTOCOL) {
468 			MATHB(p, SEQINSZ, SUB, PDCP_MAC_I_LEN, MATH1, 4,
469 			      IMMED2);
470 		} else {
471 			MATHB(p, SEQINSZ, SUB, ZERO, MATH1, 4, 0);
472 		}
473 
474 		MATHB(p, MATH1, SUB, ZERO, VSEQINSZ, 4, 0);
475 		MATHB(p, MATH1, SUB, ZERO, VSEQOUTSZ, 4, 0);
476 
477 		SEQFIFOSTORE(p, MSG, 0, 0, VLF);
478 		ALG_OPERATION(p, OP_ALG_ALGSEL_SNOW_F9, OP_ALG_AAI_F9,
479 			      OP_ALG_AS_INITFINAL,
480 			      dir == OP_TYPE_ENCAP_PROTOCOL ?
481 				     ICV_CHECK_DISABLE : ICV_CHECK_ENABLE,
482 			      DIR_ENC);
483 
484 		SEQFIFOLOAD(p, MSGINSNOOP, 0,
485 				    VLF | LAST1 | LAST2 | FLUSH1);
486 		MOVE(p, AB1, 0, OFIFO, 0, MATH1, 0);
487 
488 		if (dir == OP_TYPE_DECAP_PROTOCOL)
489 			SEQFIFOLOAD(p, ICV2, 4, LAST2);
490 		else
491 			SEQSTORE(p, CONTEXT2, 0, 4, 0);
492 
493 		break;
494 
495 	case PDCP_AUTH_TYPE_AES:
496 		/* Insert Auth Key */
497 		KEY(p, KEY1, authdata->key_enc_flags, authdata->key,
498 		    authdata->keylen, INLINE_KEY(authdata));
499 		SEQLOAD(p, MATH0, offset, length, 0);
500 		JUMP(p, 1, LOCAL_JUMP, ALL_TRUE, CALM);
501 		SEQINPTR(p, 0, length, RTO);
502 
503 		if (swap == false) {
504 			MATHB(p, MATH0, AND, sn_mask, MATH1, 8,
505 			      IFB | IMMED2);
506 			MATHB(p, MATH1, SHLD, MATH1, MATH1, 8, 0);
507 
508 			MOVEB(p, DESCBUF, 8, MATH2, 0, 8, WAITCOMP | IMMED);
509 			MATHB(p, MATH1, OR, MATH2, MATH2, 8, 0);
510 			MOVEB(p, MATH2, 0, IFIFOAB1, 0, 8, IMMED);
511 		} else {
512 			MATHB(p, MATH0, AND, sn_mask, MATH1, 8,
513 			      IFB | IMMED2);
514 			MATHB(p, MATH1, SHLD, MATH1, MATH1, 8, 0);
515 
516 			MOVE(p, DESCBUF, 8, MATH2, 0, 8, WAITCOMP | IMMED);
517 			MATHB(p, MATH1, OR, MATH2, MATH2, 8, 0);
518 			MOVE(p, MATH2, 0, IFIFOAB1, 0, 8, IMMED);
519 		}
520 
521 		if (dir == OP_TYPE_DECAP_PROTOCOL) {
522 			MATHB(p, SEQINSZ, SUB, PDCP_MAC_I_LEN, MATH1, 4,
523 			      IMMED2);
524 		} else {
525 			MATHB(p, SEQINSZ, SUB, ZERO, MATH1, 4, 0);
526 		}
527 
528 		MATHB(p, MATH1, SUB, ZERO, VSEQINSZ, 4, 0);
529 		MATHB(p, MATH1, SUB, ZERO, VSEQOUTSZ, 4, 0);
530 
531 		SEQFIFOSTORE(p, MSG, 0, 0, VLF);
532 		ALG_OPERATION(p, OP_ALG_ALGSEL_AES,
533 			      OP_ALG_AAI_CMAC,
534 			      OP_ALG_AS_INITFINAL,
535 			      dir == OP_TYPE_ENCAP_PROTOCOL ?
536 				     ICV_CHECK_DISABLE : ICV_CHECK_ENABLE,
537 			      DIR_ENC);
538 
539 		MOVE(p, AB2, 0, OFIFO, 0, MATH1, 0);
540 		SEQFIFOLOAD(p, MSGINSNOOP, 0,
541 				    VLF | LAST1 | LAST2 | FLUSH1);
542 
543 		if (dir == OP_TYPE_DECAP_PROTOCOL)
544 			SEQFIFOLOAD(p, ICV1, 4, LAST1 | FLUSH1);
545 		else
546 			SEQSTORE(p, CONTEXT1, 0, 4, 0);
547 
548 		break;
549 
550 	case PDCP_AUTH_TYPE_ZUC:
551 		/* Insert Auth Key */
552 		KEY(p, KEY2, authdata->key_enc_flags, authdata->key,
553 		    authdata->keylen, INLINE_KEY(authdata));
554 		SEQLOAD(p, MATH0, offset, length, 0);
555 		JUMP(p, 1, LOCAL_JUMP, ALL_TRUE, CALM);
556 		SEQINPTR(p, 0, length, RTO);
557 		if (swap == false) {
558 			MATHB(p, MATH0, AND, sn_mask, MATH1, 8,
559 			      IFB | IMMED2);
560 			MATHB(p, MATH1, SHLD, MATH1, MATH1, 8, 0);
561 
562 			MOVEB(p, DESCBUF, 8, MATH2, 0, 8, WAITCOMP | IMMED);
563 			MATHB(p, MATH1, OR, MATH2, MATH2, 8, 0);
564 			MOVEB(p, MATH2, 0, CONTEXT2, 0, 8, IMMED);
565 
566 		} else {
567 			MATHB(p, MATH0, AND, sn_mask, MATH1, 8,
568 			      IFB | IMMED2);
569 			MATHB(p, MATH1, SHLD, MATH1, MATH1, 8, 0);
570 
571 			MOVE(p, DESCBUF, 8, MATH2, 0, 8, WAITCOMP | IMMED);
572 			MATHB(p, MATH1, OR, MATH2, MATH2, 8, 0);
573 			MOVE(p, MATH2, 0, CONTEXT2, 0, 8, IMMED);
574 		}
575 		if (dir == OP_TYPE_DECAP_PROTOCOL)
576 			MATHB(p, SEQINSZ, SUB, PDCP_MAC_I_LEN, MATH1, 4,
577 			      IMMED2);
578 		else
579 			MATHB(p, SEQINSZ, SUB, ZERO, MATH1, 4, 0);
580 
581 		MATHB(p, MATH1, SUB, ZERO, VSEQINSZ, 4, 0);
582 		MATHB(p, MATH1, SUB, ZERO, VSEQOUTSZ, 4, 0);
583 		SEQFIFOSTORE(p, MSG, 0, 0, VLF);
584 		ALG_OPERATION(p, OP_ALG_ALGSEL_ZUCA,
585 			      OP_ALG_AAI_F9,
586 			      OP_ALG_AS_INITFINAL,
587 			      dir == OP_TYPE_ENCAP_PROTOCOL ?
588 				     ICV_CHECK_DISABLE : ICV_CHECK_ENABLE,
589 			      DIR_ENC);
590 		SEQFIFOLOAD(p, MSGINSNOOP, 0, VLF | LAST1 | LAST2 | FLUSH1);
591 		MOVE(p, AB1, 0, OFIFO, 0, MATH1, 0);
592 
593 		if (dir == OP_TYPE_DECAP_PROTOCOL)
594 			SEQFIFOLOAD(p, ICV2, 4, LAST2);
595 		else
596 			SEQSTORE(p, CONTEXT2, 0, 4, 0);
597 
598 		break;
599 
600 	default:
601 		pr_err("%s: Invalid integrity algorithm selected: %d\n",
602 		       "pdcp_insert_cplane_int_only_op", authdata->algtype);
603 		return -EINVAL;
604 	}
605 
606 	return 0;
607 }
608 
609 static inline int
610 pdcp_insert_cplane_enc_only_op(struct program *p,
611 			       bool swap __maybe_unused,
612 			       struct alginfo *cipherdata,
613 			       struct alginfo *authdata __maybe_unused,
614 			       unsigned int dir,
615 			       enum pdcp_sn_size sn_size)
616 {
617 	uint32_t offset = 0, length = 0, sn_mask = 0;
618 	/* Insert Cipher Key */
619 	KEY(p, KEY1, cipherdata->key_enc_flags, cipherdata->key,
620 	    cipherdata->keylen, INLINE_KEY(cipherdata));
621 
622 	if ((sn_size != PDCP_SN_SIZE_18 &&
623 			!(rta_sec_era == RTA_SEC_ERA_8 &&
624 				authdata->algtype == 0))
625 			|| (rta_sec_era == RTA_SEC_ERA_10)) {
626 		if (sn_size == PDCP_SN_SIZE_5)
627 			PROTOCOL(p, dir, OP_PCLID_LTE_PDCP_CTRL_MIXED,
628 				 (uint16_t)cipherdata->algtype << 8);
629 		else
630 			PROTOCOL(p, dir, OP_PCLID_LTE_PDCP_USER_RN,
631 				 (uint16_t)cipherdata->algtype << 8);
632 		return 0;
633 	}
634 	/* Non-proto is supported only for 5bit cplane and 18bit uplane */
635 	switch (sn_size) {
636 	case PDCP_SN_SIZE_5:
637 		offset = 7;
638 		length = 1;
639 		sn_mask = (swap == false) ? PDCP_C_PLANE_SN_MASK :
640 					PDCP_C_PLANE_SN_MASK_BE;
641 		break;
642 	case PDCP_SN_SIZE_18:
643 		offset = 5;
644 		length = 3;
645 		sn_mask = (swap == false) ? PDCP_U_PLANE_18BIT_SN_MASK :
646 					PDCP_U_PLANE_18BIT_SN_MASK_BE;
647 		break;
648 	case PDCP_SN_SIZE_12:
649 		offset = 6;
650 		length = 2;
651 		sn_mask = (swap == false) ? PDCP_12BIT_SN_MASK :
652 					PDCP_12BIT_SN_MASK_BE;
653 		break;
654 	case PDCP_SN_SIZE_7:
655 	case PDCP_SN_SIZE_15:
656 		pr_err("Invalid sn_size for %s\n", __func__);
657 		return -ENOTSUP;
658 	}
659 
660 	SEQLOAD(p, MATH0, offset, length, 0);
661 	JUMP(p, 1, LOCAL_JUMP, ALL_TRUE, CALM);
662 	MATHB(p, MATH0, AND, sn_mask, MATH1, 8, IFB | IMMED2);
663 	SEQSTORE(p, MATH0, offset, length, 0);
664 	MATHB(p, MATH1, SHLD, MATH1, MATH1, 8, 0);
665 	MOVEB(p, DESCBUF, 8, MATH2, 0, 8, WAITCOMP | IMMED);
666 	MATHB(p, MATH1, OR, MATH2, MATH2, 8, 0);
667 
668 	switch (cipherdata->algtype) {
669 	case PDCP_CIPHER_TYPE_SNOW:
670 		MOVEB(p, MATH2, 0, CONTEXT1, 0, 8, WAITCOMP | IMMED);
671 
672 		MATHB(p, SEQINSZ, SUB, ZERO, VSEQINSZ, 4, 0);
673 
674 		if (dir == OP_TYPE_ENCAP_PROTOCOL)
675 			MATHB(p, SEQINSZ, ADD, PDCP_MAC_I_LEN, VSEQOUTSZ, 4,
676 			      IMMED2);
677 		else
678 			MATHB(p, SEQINSZ, SUB, PDCP_MAC_I_LEN, VSEQOUTSZ, 4,
679 			      IMMED2);
680 		SEQFIFOSTORE(p, MSG, 0, 0, VLF | CONT);
681 		ALG_OPERATION(p, OP_ALG_ALGSEL_SNOW_F8,
682 			      OP_ALG_AAI_F8,
683 			      OP_ALG_AS_INITFINAL, ICV_CHECK_DISABLE,
684 			      dir == OP_TYPE_ENCAP_PROTOCOL ?
685 					DIR_ENC : DIR_DEC);
686 		break;
687 
688 	case PDCP_CIPHER_TYPE_AES:
689 		MOVEB(p, MATH2, 0, CONTEXT1, 0x10, 0x10, WAITCOMP | IMMED);
690 
691 		MATHB(p, SEQINSZ, SUB, ZERO, VSEQINSZ, 4, 0);
692 
693 		if (dir == OP_TYPE_ENCAP_PROTOCOL)
694 			MATHB(p, SEQINSZ, ADD, PDCP_MAC_I_LEN, VSEQOUTSZ, 4,
695 			      IMMED2);
696 		else
697 			MATHB(p, SEQINSZ, SUB, PDCP_MAC_I_LEN, VSEQOUTSZ, 4,
698 			      IMMED2);
699 
700 		SEQFIFOSTORE(p, MSG, 0, 0, VLF | CONT);
701 		ALG_OPERATION(p, OP_ALG_ALGSEL_AES,
702 			      OP_ALG_AAI_CTR,
703 			      OP_ALG_AS_INITFINAL,
704 			      ICV_CHECK_DISABLE,
705 			      dir == OP_TYPE_ENCAP_PROTOCOL ?
706 					DIR_ENC : DIR_DEC);
707 		break;
708 
709 	case PDCP_CIPHER_TYPE_ZUC:
710 		MOVEB(p, MATH2, 0, CONTEXT1, 0, 0x08, IMMED);
711 		MOVEB(p, MATH2, 0, CONTEXT1, 0x08, 0x08, WAITCOMP | IMMED);
712 		MATHB(p, SEQINSZ, SUB, ZERO, VSEQINSZ, 4, 0);
713 		if (dir == OP_TYPE_ENCAP_PROTOCOL)
714 			MATHB(p, SEQINSZ, ADD, PDCP_MAC_I_LEN, VSEQOUTSZ, 4,
715 			      IMMED2);
716 		else
717 			MATHB(p, SEQINSZ, SUB, PDCP_MAC_I_LEN, VSEQOUTSZ, 4,
718 			      IMMED2);
719 
720 		SEQFIFOSTORE(p, MSG, 0, 0, VLF | CONT);
721 		ALG_OPERATION(p, OP_ALG_ALGSEL_ZUCE,
722 			      OP_ALG_AAI_F8,
723 			      OP_ALG_AS_INITFINAL,
724 			      ICV_CHECK_DISABLE,
725 			      dir == OP_TYPE_ENCAP_PROTOCOL ?
726 					DIR_ENC : DIR_DEC);
727 		break;
728 
729 	default:
730 		pr_err("%s: Invalid encrypt algorithm selected: %d\n",
731 		       "pdcp_insert_cplane_enc_only_op", cipherdata->algtype);
732 		return -EINVAL;
733 	}
734 
735 	if (dir == OP_TYPE_ENCAP_PROTOCOL) {
736 		SEQFIFOLOAD(p, MSG1, 0, VLF);
737 		FIFOLOAD(p, MSG1, PDCP_NULL_INT_MAC_I_VAL, 4,
738 			 LAST1 | FLUSH1 | IMMED);
739 	} else {
740 		SEQFIFOLOAD(p, MSG1, 0, VLF | LAST1 | FLUSH1);
741 		MOVE(p, OFIFO, 0, MATH1, 4, PDCP_MAC_I_LEN, WAITCOMP | IMMED);
742 		MATHB(p, MATH1, XOR, PDCP_NULL_INT_MAC_I_VAL, NONE, 4, IMMED2);
743 		JUMP(p, PDCP_NULL_INT_ICV_CHECK_FAILED_STATUS,
744 		     HALT_STATUS, ALL_FALSE, MATH_Z);
745 	}
746 
747 	return 0;
748 }
749 
750 static inline int
751 pdcp_insert_uplane_snow_snow_op(struct program *p,
752 			      bool swap __maybe_unused,
753 			      struct alginfo *cipherdata,
754 			      struct alginfo *authdata,
755 			      unsigned int dir,
756 			      enum pdcp_sn_size sn_size)
757 {
758 	uint32_t offset = 0, length = 0, sn_mask = 0;
759 
760 	KEY(p, KEY1, cipherdata->key_enc_flags, cipherdata->key,
761 	    cipherdata->keylen, INLINE_KEY(cipherdata));
762 	KEY(p, KEY2, authdata->key_enc_flags, authdata->key, authdata->keylen,
763 	    INLINE_KEY(authdata));
764 
765 	if (sn_size != PDCP_SN_SIZE_18) {
766 		int pclid;
767 
768 		if (sn_size == PDCP_SN_SIZE_5)
769 			pclid = OP_PCLID_LTE_PDCP_CTRL_MIXED;
770 		else
771 			pclid = OP_PCLID_LTE_PDCP_USER_RN;
772 
773 		PROTOCOL(p, dir, pclid,
774 			 ((uint16_t)cipherdata->algtype << 8) |
775 			 (uint16_t)authdata->algtype);
776 
777 		return 0;
778 	}
779 	/* sn_size is 18 */
780 	offset = 5;
781 	length = 3;
782 	sn_mask = (swap == false) ? PDCP_U_PLANE_18BIT_SN_MASK :
783 				PDCP_U_PLANE_18BIT_SN_MASK_BE;
784 
785 	if (dir == OP_TYPE_ENCAP_PROTOCOL)
786 		MATHB(p, SEQINSZ, SUB, length, VSEQINSZ, 4, IMMED2);
787 
788 	SEQLOAD(p, MATH0, offset, length, 0);
789 	JUMP(p, 1, LOCAL_JUMP, ALL_TRUE, CALM);
790 	MOVEB(p, MATH0, offset, IFIFOAB2, 0, length, IMMED);
791 	MATHB(p, MATH0, AND, sn_mask, MATH1, 8, IFB | IMMED2);
792 
793 	SEQSTORE(p, MATH0, offset, length, 0);
794 	MATHB(p, MATH1, SHLD, MATH1, MATH1, 8, 0);
795 	MOVEB(p, DESCBUF, 8, MATH2, 0, 8, WAITCOMP | IMMED);
796 	MATHB(p, MATH1, OR, MATH2, MATH1, 8, 0);
797 	MOVEB(p, MATH1, 0, CONTEXT1, 0, 8, IMMED);
798 	MOVEB(p, MATH1, 0, CONTEXT2, 0, 4, WAITCOMP | IMMED);
799 	if (swap == false) {
800 		MATHB(p, MATH1, AND, upper_32_bits(PDCP_BEARER_MASK),
801 		      MATH2, 4, IMMED2);
802 		MATHB(p, MATH1, AND, lower_32_bits(PDCP_DIR_MASK),
803 		      MATH3, 4, IMMED2);
804 	} else {
805 		MATHB(p, MATH1, AND, lower_32_bits(PDCP_BEARER_MASK_BE),
806 		      MATH2, 4, IMMED2);
807 		MATHB(p, MATH1, AND, upper_32_bits(PDCP_DIR_MASK_BE),
808 		      MATH3, 4, IMMED2);
809 	}
810 	MATHB(p, MATH3, SHLD, MATH3, MATH3, 8, 0);
811 
812 	MOVEB(p, MATH2, 4, OFIFO, 0, 12, IMMED);
813 	MOVE(p, OFIFO, 0, CONTEXT2, 4, 12, IMMED);
814 	if (dir == OP_TYPE_ENCAP_PROTOCOL) {
815 		MATHB(p, SEQINSZ, ADD, PDCP_MAC_I_LEN, VSEQOUTSZ, 4, IMMED2);
816 	} else {
817 		MATHI(p, SEQINSZ, SUB, PDCP_MAC_I_LEN, VSEQOUTSZ, 4, IMMED2);
818 		MATHI(p, SEQINSZ, SUB, PDCP_MAC_I_LEN, VSEQINSZ, 4, IMMED2);
819 	}
820 
821 	if (dir == OP_TYPE_ENCAP_PROTOCOL)
822 		SEQFIFOSTORE(p, MSG, 0, 0, VLF);
823 	else
824 		SEQFIFOSTORE(p, MSG, 0, 0, VLF | CONT);
825 
826 	ALG_OPERATION(p, OP_ALG_ALGSEL_SNOW_F9,
827 		      OP_ALG_AAI_F9,
828 		      OP_ALG_AS_INITFINAL,
829 		      dir == OP_TYPE_ENCAP_PROTOCOL ?
830 			     ICV_CHECK_DISABLE : ICV_CHECK_ENABLE,
831 		      DIR_DEC);
832 	ALG_OPERATION(p, OP_ALG_ALGSEL_SNOW_F8,
833 		      OP_ALG_AAI_F8,
834 		      OP_ALG_AS_INITFINAL,
835 		      ICV_CHECK_DISABLE,
836 		      dir == OP_TYPE_ENCAP_PROTOCOL ? DIR_ENC : DIR_DEC);
837 
838 	if (dir == OP_TYPE_ENCAP_PROTOCOL) {
839 		SEQFIFOLOAD(p, MSGINSNOOP, 0, VLF | LAST2);
840 		MOVE(p, CONTEXT2, 0, IFIFOAB1, 0, 4, LAST1 | FLUSH1 | IMMED);
841 	} else {
842 		SEQFIFOLOAD(p, MSGOUTSNOOP, 0, VLF | LAST2);
843 		SEQFIFOLOAD(p, MSG1, 4, LAST1 | FLUSH1);
844 		JUMP(p, 1, LOCAL_JUMP, ALL_TRUE, CLASS1 | NOP | NIFP);
845 
846 		LOAD(p, 0, DCTRL, 0, LDLEN_RST_CHA_OFIFO_PTR, IMMED);
847 
848 		MOVE(p, OFIFO, 0, MATH0, 0, 4, WAITCOMP | IMMED);
849 
850 		NFIFOADD(p, IFIFO, ICV2, 4, LAST2);
851 
852 		MOVE(p, MATH0, 0, IFIFO, 0, 4, WAITCOMP | IMMED);
853 	}
854 
855 	return 0;
856 }
857 
858 static inline int
859 pdcp_insert_uplane_zuc_zuc_op(struct program *p,
860 			      bool swap __maybe_unused,
861 			      struct alginfo *cipherdata,
862 			      struct alginfo *authdata,
863 			      unsigned int dir,
864 			      enum pdcp_sn_size sn_size)
865 {
866 	uint32_t offset = 0, length = 0, sn_mask = 0;
867 
868 	LABEL(keyjump);
869 	REFERENCE(pkeyjump);
870 
871 	pkeyjump = JUMP(p, keyjump, LOCAL_JUMP, ALL_TRUE, SHRD | SELF | BOTH);
872 	KEY(p, KEY1, cipherdata->key_enc_flags, cipherdata->key,
873 	    cipherdata->keylen, INLINE_KEY(cipherdata));
874 	KEY(p, KEY2, authdata->key_enc_flags, authdata->key, authdata->keylen,
875 	    INLINE_KEY(authdata));
876 
877 	SET_LABEL(p, keyjump);
878 	PATCH_JUMP(p, pkeyjump, keyjump);
879 
880 	if (sn_size != PDCP_SN_SIZE_18) {
881 		int pclid;
882 
883 		if (sn_size == PDCP_SN_SIZE_5)
884 			pclid = OP_PCLID_LTE_PDCP_CTRL_MIXED;
885 		else
886 			pclid = OP_PCLID_LTE_PDCP_USER_RN;
887 
888 		PROTOCOL(p, dir, pclid,
889 			 ((uint16_t)cipherdata->algtype << 8) |
890 			 (uint16_t)authdata->algtype);
891 
892 		return 0;
893 	}
894 	/* sn_size is 18 */
895 	offset = 5;
896 	length = 3;
897 	sn_mask = (swap == false) ? PDCP_U_PLANE_18BIT_SN_MASK :
898 				PDCP_U_PLANE_18BIT_SN_MASK_BE;
899 
900 	SEQLOAD(p, MATH0, offset, length, 0);
901 	JUMP(p, 1, LOCAL_JUMP, ALL_TRUE, CALM);
902 	MOVEB(p, MATH0, offset, IFIFOAB2, 0, length, IMMED);
903 	MATHB(p, MATH0, AND, sn_mask, MATH1, 8, IFB | IMMED2);
904 	MATHB(p, MATH1, SHLD, MATH1, MATH1, 8, 0);
905 
906 	MOVEB(p, DESCBUF, 8, MATH2, 0, 8, WAITCOMP | IMMED);
907 	MATHB(p, MATH1, OR, MATH2, MATH2, 8, 0);
908 	MOVEB(p, MATH2, 0, CONTEXT1, 0, 8, IMMED);
909 
910 	MOVEB(p, MATH2, 0, CONTEXT2, 0, 8, WAITCOMP | IMMED);
911 
912 	if (dir == OP_TYPE_ENCAP_PROTOCOL)
913 		MATHB(p, SEQINSZ, ADD, PDCP_MAC_I_LEN, VSEQOUTSZ, 4, IMMED2);
914 	else
915 		MATHB(p, SEQINSZ, SUB, PDCP_MAC_I_LEN, VSEQOUTSZ, 4, IMMED2);
916 
917 	MATHB(p, SEQINSZ, SUB, ZERO, VSEQINSZ, 4, 0);
918 	SEQSTORE(p, MATH0, offset, length, 0);
919 
920 	if (dir == OP_TYPE_ENCAP_PROTOCOL) {
921 		SEQFIFOSTORE(p, MSG, 0, 0, VLF);
922 		SEQFIFOLOAD(p, MSGINSNOOP, 0, VLF | LAST2);
923 	} else {
924 		SEQFIFOSTORE(p, MSG, 0, 0, VLF | CONT);
925 		SEQFIFOLOAD(p, MSGOUTSNOOP, 0, VLF | LAST1 | FLUSH1);
926 	}
927 
928 	ALG_OPERATION(p, OP_ALG_ALGSEL_ZUCA,
929 		      OP_ALG_AAI_F9,
930 		      OP_ALG_AS_INITFINAL,
931 		      dir == OP_TYPE_ENCAP_PROTOCOL ?
932 			     ICV_CHECK_DISABLE : ICV_CHECK_ENABLE,
933 		      DIR_ENC);
934 
935 	ALG_OPERATION(p, OP_ALG_ALGSEL_ZUCE,
936 		      OP_ALG_AAI_F8,
937 		      OP_ALG_AS_INITFINAL,
938 		      ICV_CHECK_DISABLE,
939 		      dir == OP_TYPE_ENCAP_PROTOCOL ? DIR_ENC : DIR_DEC);
940 
941 	if (dir == OP_TYPE_ENCAP_PROTOCOL) {
942 		MOVE(p, CONTEXT2, 0, IFIFOAB1, 0, 4, LAST1 | FLUSH1 | IMMED);
943 	} else {
944 		/* Save ICV */
945 		MOVEB(p, OFIFO, 0, MATH0, 0, 4, IMMED);
946 
947 		LOAD(p, NFIFOENTRY_STYPE_ALTSOURCE |
948 		     NFIFOENTRY_DEST_CLASS2 |
949 		     NFIFOENTRY_DTYPE_ICV |
950 		     NFIFOENTRY_LC2 | 4, NFIFO_SZL, 0, 4, IMMED);
951 		MOVEB(p, MATH0, 0, ALTSOURCE, 0, 4, WAITCOMP | IMMED);
952 	}
953 
954 	/* Reset ZUCA mode and done interrupt */
955 	LOAD(p, CLRW_CLR_C2MODE, CLRW, 0, 4, IMMED);
956 	LOAD(p, CIRQ_ZADI, ICTRL, 0, 4, IMMED);
957 
958 	return 0;
959 }
960 
961 static inline int
962 pdcp_insert_uplane_aes_aes_op(struct program *p,
963 			      bool swap __maybe_unused,
964 			      struct alginfo *cipherdata,
965 			      struct alginfo *authdata,
966 			      unsigned int dir,
967 			      enum pdcp_sn_size sn_size)
968 {
969 	uint32_t offset = 0, length = 0, sn_mask = 0;
970 
971 	if (sn_size != PDCP_SN_SIZE_18) {
972 		/* Insert Auth Key */
973 		KEY(p, KEY2, authdata->key_enc_flags, authdata->key,
974 		    authdata->keylen, INLINE_KEY(authdata));
975 
976 		/* Insert Cipher Key */
977 		KEY(p, KEY1, cipherdata->key_enc_flags, cipherdata->key,
978 		    cipherdata->keylen, INLINE_KEY(cipherdata));
979 
980 		PROTOCOL(p, dir, OP_PCLID_LTE_PDCP_USER_RN,
981 			 ((uint16_t)cipherdata->algtype << 8) |
982 			  (uint16_t)authdata->algtype);
983 		return 0;
984 	}
985 
986 	/* Non-proto is supported only for 5bit cplane and 18bit uplane */
987 	switch (sn_size) {
988 	case PDCP_SN_SIZE_18:
989 		offset = 5;
990 		length = 3;
991 		sn_mask = (swap == false) ? PDCP_U_PLANE_18BIT_SN_MASK :
992 					PDCP_U_PLANE_18BIT_SN_MASK_BE;
993 		break;
994 
995 	default:
996 		pr_err("Invalid sn_size for %s\n", __func__);
997 		return -ENOTSUP;
998 	}
999 
1000 	SEQLOAD(p, MATH0, offset, length, 0);
1001 	JUMP(p, 1, LOCAL_JUMP, ALL_TRUE, CALM);
1002 	MATHB(p, MATH0, AND, sn_mask, MATH1, 8, IFB | IMMED2);
1003 
1004 	MATHB(p, MATH1, SHLD, MATH1, MATH1, 8, 0);
1005 	MOVEB(p, DESCBUF, 8, MATH2, 0, 0x08, WAITCOMP | IMMED);
1006 	MATHB(p, MATH1, OR, MATH2, MATH2, 8, 0);
1007 	SEQSTORE(p, MATH0, offset, length, 0);
1008 
1009 	if (dir == OP_TYPE_ENCAP_PROTOCOL) {
1010 		KEY(p, KEY1, authdata->key_enc_flags, authdata->key,
1011 		    authdata->keylen, INLINE_KEY(authdata));
1012 		MOVEB(p, MATH2, 0, IFIFOAB1, 0, 0x08, IMMED);
1013 		MOVEB(p, MATH0, offset, IFIFOAB1, 0, length, IMMED);
1014 
1015 		MATHB(p, SEQINSZ, SUB, ZERO, VSEQINSZ, 4, 0);
1016 		MATHB(p, VSEQINSZ, ADD, PDCP_MAC_I_LEN, VSEQOUTSZ, 4, IMMED2);
1017 
1018 		ALG_OPERATION(p, OP_ALG_ALGSEL_AES,
1019 			      OP_ALG_AAI_CMAC,
1020 			      OP_ALG_AS_INITFINAL,
1021 			      ICV_CHECK_DISABLE,
1022 			      DIR_DEC);
1023 		SEQFIFOLOAD(p, MSG1, 0, VLF | LAST1 | FLUSH1);
1024 		MOVEB(p, CONTEXT1, 0, MATH3, 0, 4, WAITCOMP | IMMED);
1025 
1026 		/* conditional jump with calm added to ensure that the
1027 		 * previous processing has been completed
1028 		 */
1029 		JUMP(p, 1, LOCAL_JUMP, ALL_TRUE, CALM);
1030 
1031 		LOAD(p, CLRW_RESET_CLS1_CHA |
1032 		     CLRW_CLR_C1KEY |
1033 		     CLRW_CLR_C1CTX |
1034 		     CLRW_CLR_C1ICV |
1035 		     CLRW_CLR_C1DATAS |
1036 		     CLRW_CLR_C1MODE,
1037 		     CLRW, 0, 4, IMMED);
1038 
1039 		KEY(p, KEY1, cipherdata->key_enc_flags, cipherdata->key,
1040 		    cipherdata->keylen, INLINE_KEY(cipherdata));
1041 
1042 		MOVEB(p, MATH2, 0, CONTEXT1, 16, 8, IMMED);
1043 		SEQINPTR(p, 0, PDCP_NULL_MAX_FRAME_LEN, RTO);
1044 
1045 		ALG_OPERATION(p, OP_ALG_ALGSEL_AES,
1046 			      OP_ALG_AAI_CTR,
1047 			      OP_ALG_AS_INITFINAL,
1048 			      ICV_CHECK_DISABLE,
1049 			      DIR_ENC);
1050 
1051 		SEQFIFOSTORE(p, MSG, 0, 0, VLF);
1052 
1053 		SEQFIFOLOAD(p, SKIP, length, 0);
1054 
1055 		SEQFIFOLOAD(p, MSG1, 0, VLF);
1056 		MOVEB(p, MATH3, 0, IFIFOAB1, 0, 4, LAST1 | FLUSH1 | IMMED);
1057 	} else {
1058 		MOVEB(p, MATH2, 0, CONTEXT1, 16, 8, IMMED);
1059 		MOVEB(p, MATH2, 0, CONTEXT2, 0, 8, IMMED);
1060 
1061 		MATHB(p, SEQINSZ, SUB, ZERO, VSEQINSZ, 4, 0);
1062 		MATHB(p, SEQINSZ, SUB, PDCP_MAC_I_LEN, VSEQOUTSZ, 4, IMMED2);
1063 
1064 		KEY(p, KEY1, cipherdata->key_enc_flags, cipherdata->key,
1065 		    cipherdata->keylen, INLINE_KEY(cipherdata));
1066 
1067 		ALG_OPERATION(p, OP_ALG_ALGSEL_AES,
1068 			      OP_ALG_AAI_CTR,
1069 			      OP_ALG_AS_INITFINAL,
1070 			      ICV_CHECK_DISABLE,
1071 			      DIR_DEC);
1072 
1073 		SEQFIFOSTORE(p, MSG, 0, 0, VLF | CONT);
1074 		SEQFIFOLOAD(p, MSG1, 0, VLF | LAST1 | FLUSH1);
1075 
1076 		MOVEB(p, OFIFO, 0, MATH3, 0, 4, IMMED);
1077 
1078 		/* conditional jump with calm added to ensure that the
1079 		 * previous processing has been completed
1080 		 */
1081 		JUMP(p, 1, LOCAL_JUMP, ALL_TRUE, CALM);
1082 
1083 		LOAD(p, CLRW_RESET_CLS1_CHA |
1084 		     CLRW_CLR_C1KEY |
1085 		     CLRW_CLR_C1CTX |
1086 		     CLRW_CLR_C1ICV |
1087 		     CLRW_CLR_C1DATAS |
1088 		     CLRW_CLR_C1MODE,
1089 		     CLRW, 0, 4, IMMED);
1090 
1091 		KEY(p, KEY1, authdata->key_enc_flags, authdata->key,
1092 		    authdata->keylen, INLINE_KEY(authdata));
1093 
1094 		SEQINPTR(p, 0, 0, SOP);
1095 
1096 		ALG_OPERATION(p, OP_ALG_ALGSEL_AES,
1097 			      OP_ALG_AAI_CMAC,
1098 			      OP_ALG_AS_INITFINAL,
1099 			      ICV_CHECK_ENABLE,
1100 			      DIR_DEC);
1101 
1102 		MATHB(p, SEQINSZ, SUB, ZERO, VSEQINSZ, 4, 0);
1103 
1104 		MOVE(p, CONTEXT2, 0, IFIFOAB1, 0, 8, IMMED);
1105 
1106 		SEQFIFOLOAD(p, MSG1, 0, VLF | LAST1 | FLUSH1);
1107 
1108 		LOAD(p, NFIFOENTRY_STYPE_ALTSOURCE |
1109 		     NFIFOENTRY_DEST_CLASS1 |
1110 		     NFIFOENTRY_DTYPE_ICV |
1111 		     NFIFOENTRY_LC1 |
1112 		     NFIFOENTRY_FC1 | 4, NFIFO_SZL, 0, 4, IMMED);
1113 		MOVEB(p, MATH3, 0, ALTSOURCE, 0, 4, IMMED);
1114 	}
1115 
1116 	return 0;
1117 }
1118 
1119 static inline int
1120 pdcp_insert_cplane_acc_op(struct program *p,
1121 			  bool swap __maybe_unused,
1122 			  struct alginfo *cipherdata,
1123 			  struct alginfo *authdata,
1124 			  unsigned int dir,
1125 			  enum pdcp_sn_size sn_size)
1126 {
1127 	/* Insert Auth Key */
1128 	KEY(p, KEY2, authdata->key_enc_flags, authdata->key, authdata->keylen,
1129 	    INLINE_KEY(authdata));
1130 
1131 	/* Insert Cipher Key */
1132 	KEY(p, KEY1, cipherdata->key_enc_flags, cipherdata->key,
1133 	    cipherdata->keylen, INLINE_KEY(cipherdata));
1134 
1135 	if (sn_size == PDCP_SN_SIZE_5)
1136 		PROTOCOL(p, dir, OP_PCLID_LTE_PDCP_CTRL,
1137 			 (uint16_t)cipherdata->algtype);
1138 	else
1139 		PROTOCOL(p, dir, OP_PCLID_LTE_PDCP_USER_RN,
1140 			 ((uint16_t)cipherdata->algtype << 8) |
1141 			  (uint16_t)authdata->algtype);
1142 
1143 	return 0;
1144 }
1145 
1146 static inline int
1147 pdcp_insert_cplane_snow_aes_op(struct program *p,
1148 			       bool swap __maybe_unused,
1149 			       struct alginfo *cipherdata,
1150 			       struct alginfo *authdata,
1151 			       unsigned int dir,
1152 			       enum pdcp_sn_size sn_size)
1153 {
1154 	uint32_t offset = 0, length = 0, sn_mask = 0;
1155 
1156 	LABEL(back_to_sd_offset);
1157 	LABEL(end_desc);
1158 	LABEL(local_offset);
1159 	LABEL(jump_to_beginning);
1160 	REFERENCE(seqin_ptr_read);
1161 	REFERENCE(seqin_ptr_write);
1162 	REFERENCE(seq_out_read);
1163 	REFERENCE(jump_back_to_sd_cmd);
1164 
1165 	if ((sn_size != PDCP_SN_SIZE_18) ||
1166 		(rta_sec_era == RTA_SEC_ERA_10)) {
1167 		KEY(p, KEY1, cipherdata->key_enc_flags, cipherdata->key,
1168 				cipherdata->keylen, INLINE_KEY(cipherdata));
1169 		KEY(p, KEY2, authdata->key_enc_flags, authdata->key,
1170 				authdata->keylen, INLINE_KEY(authdata));
1171 
1172 		if (sn_size == PDCP_SN_SIZE_5)
1173 			PROTOCOL(p, dir, OP_PCLID_LTE_PDCP_CTRL_MIXED,
1174 				 ((uint16_t)cipherdata->algtype << 8) |
1175 				 (uint16_t)authdata->algtype);
1176 		else
1177 			PROTOCOL(p, dir, OP_PCLID_LTE_PDCP_USER_RN,
1178 				 ((uint16_t)cipherdata->algtype << 8) |
1179 				 (uint16_t)authdata->algtype);
1180 
1181 		return 0;
1182 	}
1183 	/* sn_size is 18 */
1184 	offset = 5;
1185 	length = 3;
1186 	sn_mask = (swap == false) ? PDCP_U_PLANE_18BIT_SN_MASK :
1187 				PDCP_U_PLANE_18BIT_SN_MASK_BE;
1188 
1189 	SEQLOAD(p, MATH0, offset, length, 0);
1190 	JUMP(p, 1, LOCAL_JUMP, ALL_TRUE, CALM);
1191 	MATHB(p, MATH0, AND, sn_mask, MATH1, 8, IFB | IMMED2);
1192 	MATHB(p, MATH1, SHLD, MATH1, MATH1, 8, 0);
1193 	MOVEB(p, DESCBUF, 4, MATH2, 0, 0x08, WAITCOMP | IMMED);
1194 	MATHB(p, MATH1, OR, MATH2, MATH2, 8, 0);
1195 	SEQSTORE(p, MATH0, offset, length, 0);
1196 	if (dir == OP_TYPE_ENCAP_PROTOCOL) {
1197 		SEQINPTR(p, 0, length, RTO);
1198 
1199 		KEY(p, KEY1, authdata->key_enc_flags, authdata->key,
1200 		    authdata->keylen, INLINE_KEY(authdata));
1201 		MOVEB(p, MATH2, 0, IFIFOAB1, 0, 0x08, IMMED);
1202 
1203 		MATHB(p, SEQINSZ, SUB, ZERO, VSEQINSZ, 4, 0);
1204 		MATHB(p, SEQINSZ, SUB, ZERO, MATH1, 4, 0);
1205 		MATHB(p, VSEQINSZ, ADD, PDCP_MAC_I_LEN - 1, VSEQOUTSZ,
1206 		      4, IMMED2);
1207 
1208 		/*
1209 		 * Placeholder for filling the length in
1210 		 * SEQIN PTR RTO below
1211 		 */
1212 		seqin_ptr_read = MOVE(p, DESCBUF, 0, MATH1, 0, 6, IMMED);
1213 		seqin_ptr_write = MOVE(p, MATH1, 0, DESCBUF, 0, 8,
1214 				       WAITCOMP | IMMED);
1215 		ALG_OPERATION(p, OP_ALG_ALGSEL_AES,
1216 			      OP_ALG_AAI_CMAC,
1217 			      OP_ALG_AS_INITFINAL,
1218 			      ICV_CHECK_DISABLE,
1219 			      DIR_DEC);
1220 		SEQFIFOLOAD(p, MSG1, 0, VLF | LAST1 | FLUSH1);
1221 		MOVEB(p, CONTEXT1, 0, MATH3, 0, 4, WAITCOMP | IMMED);
1222 
1223 		/* conditional jump with calm added to ensure that the
1224 		 * previous processing has been completed
1225 		 */
1226 		JUMP(p, 1, LOCAL_JUMP, ALL_TRUE, CALM);
1227 
1228 		LOAD(p, CLRW_RESET_CLS1_CHA |
1229 		     CLRW_CLR_C1KEY |
1230 		     CLRW_CLR_C1CTX |
1231 		     CLRW_CLR_C1ICV |
1232 		     CLRW_CLR_C1DATAS |
1233 		     CLRW_CLR_C1MODE,
1234 		     CLRW, 0, 4, IMMED);
1235 
1236 		KEY(p, KEY1, cipherdata->key_enc_flags, cipherdata->key,
1237 		    cipherdata->keylen, INLINE_KEY(cipherdata));
1238 		SET_LABEL(p, local_offset);
1239 		MOVEB(p, MATH2, 0, CONTEXT1, 0, 8, IMMED);
1240 		SEQINPTR(p, 0, 0, RTO);
1241 
1242 		MATHB(p, SEQINSZ, SUB, length, VSEQINSZ, 4, IMMED2);
1243 		ALG_OPERATION(p, OP_ALG_ALGSEL_SNOW_F8,
1244 			      OP_ALG_AAI_F8,
1245 			      OP_ALG_AS_INITFINAL,
1246 			      ICV_CHECK_DISABLE,
1247 			      DIR_ENC);
1248 		SEQFIFOSTORE(p, MSG, 0, 0, VLF);
1249 
1250 		SEQFIFOLOAD(p, SKIP, length, 0);
1251 
1252 		SEQFIFOLOAD(p, MSG1, 0, VLF);
1253 		MOVEB(p, MATH3, 0, IFIFOAB1, 0, 4, LAST1 | FLUSH1 | IMMED);
1254 		PATCH_MOVE(p, seqin_ptr_read, local_offset);
1255 		PATCH_MOVE(p, seqin_ptr_write, local_offset);
1256 	} else {
1257 		MOVEB(p, MATH2, 0, CONTEXT1, 0, 8, IMMED);
1258 
1259 		MOVE(p, CONTEXT1, 0, CONTEXT2, 0, 8, IMMED);
1260 
1261 		MATHB(p, SEQINSZ, SUB, ZERO, VSEQINSZ, 4, 0);
1262 
1263 		MATHI(p, SEQINSZ, SUB, PDCP_MAC_I_LEN, VSEQOUTSZ, 4, IMMED2);
1264 /*
1265  * TODO: To be changed when proper support is added in RTA (can't load a
1266  * command that is also written by RTA (or patch it for that matter).
1267  * Change when proper RTA support is added.
1268  */
1269 		if (p->ps)
1270 			WORD(p, 0x168B0004);
1271 		else
1272 			WORD(p, 0x16880404);
1273 
1274 		jump_back_to_sd_cmd = JUMP(p, 0, LOCAL_JUMP, ALL_TRUE, 0);
1275 		/*
1276 		 * Placeholder for command reading  the SEQ OUT command in
1277 		 * JD. Done for rereading the decrypted data and performing
1278 		 * the integrity check
1279 		 */
1280 /*
1281  * TODO: RTA currently doesn't support patching of length of a MOVE command
1282  * Thus, it is inserted as a raw word, as per PS setting.
1283  */
1284 		if (p->ps)
1285 			seq_out_read = MOVE(p, DESCBUF, 0, MATH1, 0, 20,
1286 					    WAITCOMP | IMMED);
1287 		else
1288 			seq_out_read = MOVE(p, DESCBUF, 0, MATH1, 0, 16,
1289 					    WAITCOMP | IMMED);
1290 
1291 		MATHB(p, MATH1, XOR, CMD_SEQ_IN_PTR ^ CMD_SEQ_OUT_PTR, MATH1, 4,
1292 		      IMMED2);
1293 		/* Placeholder for overwriting the SEQ IN  with SEQ OUT */
1294 /*
1295  * TODO: RTA currently doesn't support patching of length of a MOVE command
1296  * Thus, it is inserted as a raw word, as per PS setting.
1297  */
1298 		if (p->ps)
1299 			MOVE(p, MATH1, 0, DESCBUF, 0, 24, IMMED);
1300 		else
1301 			MOVE(p, MATH1, 0, DESCBUF, 0, 20, IMMED);
1302 
1303 		KEY(p, KEY1, cipherdata->key_enc_flags, cipherdata->key,
1304 		    cipherdata->keylen, INLINE_KEY(cipherdata));
1305 
1306 		MOVE(p, CONTEXT1, 0, CONTEXT2, 0, 8, IMMED);
1307 
1308 		ALG_OPERATION(p, OP_ALG_ALGSEL_SNOW_F8,
1309 			      OP_ALG_AAI_F8,
1310 			      OP_ALG_AS_INITFINAL,
1311 			      ICV_CHECK_DISABLE,
1312 			      DIR_DEC);
1313 		SEQFIFOSTORE(p, MSG, 0, 0, VLF | CONT);
1314 		SEQFIFOLOAD(p, MSG1, 0, VLF | LAST1 | FLUSH1);
1315 
1316 		MOVE(p, OFIFO, 0, MATH3, 0, 4, IMMED);
1317 
1318 		LOAD(p, CLRW_RESET_CLS1_CHA |
1319 		     CLRW_CLR_C1KEY |
1320 		     CLRW_CLR_C1CTX |
1321 		     CLRW_CLR_C1ICV |
1322 		     CLRW_CLR_C1DATAS |
1323 		     CLRW_CLR_C1MODE,
1324 		     CLRW, 0, 4, IMMED);
1325 
1326 		KEY(p, KEY1, authdata->key_enc_flags, authdata->key,
1327 		    authdata->keylen, INLINE_KEY(authdata));
1328 		/*
1329 		 * Placeholder for jump in SD for executing the new SEQ IN PTR
1330 		 * command (which is actually the old SEQ OUT PTR command
1331 		 * copied over from JD.
1332 		 */
1333 		SET_LABEL(p, jump_to_beginning);
1334 		JUMP(p, 1 - jump_to_beginning, LOCAL_JUMP, ALL_TRUE, 0);
1335 		SET_LABEL(p, back_to_sd_offset);
1336 		ALG_OPERATION(p, OP_ALG_ALGSEL_AES,
1337 			      OP_ALG_AAI_CMAC,
1338 			      OP_ALG_AS_INITFINAL,
1339 			      ICV_CHECK_ENABLE,
1340 			      DIR_DEC);
1341 
1342 		/* Read the # of bytes written in the output buffer + 1 (HDR) */
1343 		MATHI(p, VSEQOUTSZ, ADD, length, VSEQINSZ, 4, IMMED2);
1344 
1345 		MOVE(p, CONTEXT2, 0, IFIFOAB1, 0, 8, IMMED);
1346 
1347 		SEQFIFOLOAD(p, MSG1, 0, VLF | LAST1 | FLUSH1);
1348 
1349 		LOAD(p, NFIFOENTRY_STYPE_ALTSOURCE |
1350 		     NFIFOENTRY_DEST_CLASS1 |
1351 		     NFIFOENTRY_DTYPE_ICV |
1352 		     NFIFOENTRY_LC1 |
1353 		     NFIFOENTRY_FC1 | 4, NFIFO_SZL, 0, 4, IMMED);
1354 		MOVE(p, MATH3, 0, ALTSOURCE, 0, 4, IMMED);
1355 
1356 
1357 		SET_LABEL(p, end_desc);
1358 
1359 		if (!p->ps) {
1360 			PATCH_MOVE(p, seq_out_read, end_desc + 1);
1361 			PATCH_JUMP(p, jump_back_to_sd_cmd,
1362 				   back_to_sd_offset + jump_back_to_sd_cmd - 5);
1363 		} else {
1364 			PATCH_MOVE(p, seq_out_read, end_desc + 2);
1365 			PATCH_JUMP(p, jump_back_to_sd_cmd,
1366 				   back_to_sd_offset + jump_back_to_sd_cmd - 5);
1367 		}
1368 	}
1369 
1370 	return 0;
1371 }
1372 
1373 static inline int
1374 pdcp_insert_cplane_aes_snow_op(struct program *p,
1375 			       bool swap __maybe_unused,
1376 			       struct alginfo *cipherdata,
1377 			       struct alginfo *authdata,
1378 			       unsigned int dir,
1379 			       enum pdcp_sn_size sn_size)
1380 {
1381 	uint32_t offset = 0, length = 0, sn_mask = 0;
1382 
1383 	KEY(p, KEY1, cipherdata->key_enc_flags, cipherdata->key,
1384 	    cipherdata->keylen, INLINE_KEY(cipherdata));
1385 	KEY(p, KEY2, authdata->key_enc_flags, authdata->key, authdata->keylen,
1386 	    INLINE_KEY(authdata));
1387 
1388 	if ((sn_size != PDCP_SN_SIZE_18) ||
1389 		(rta_sec_era == RTA_SEC_ERA_10)) {
1390 		int pclid;
1391 
1392 		if (sn_size == PDCP_SN_SIZE_5)
1393 			pclid = OP_PCLID_LTE_PDCP_CTRL_MIXED;
1394 		else
1395 			pclid = OP_PCLID_LTE_PDCP_USER_RN;
1396 
1397 		PROTOCOL(p, dir, pclid,
1398 			 ((uint16_t)cipherdata->algtype << 8) |
1399 			 (uint16_t)authdata->algtype);
1400 
1401 		return 0;
1402 	}
1403 	/* sn_size is 18 */
1404 	offset = 5;
1405 	length = 3;
1406 	sn_mask = (swap == false) ? PDCP_U_PLANE_18BIT_SN_MASK :
1407 				PDCP_U_PLANE_18BIT_SN_MASK_BE;
1408 
1409 	if (dir == OP_TYPE_ENCAP_PROTOCOL)
1410 		MATHB(p, SEQINSZ, SUB, length, VSEQINSZ, 4, IMMED2);
1411 
1412 	SEQLOAD(p, MATH0, offset, length, 0);
1413 	JUMP(p, 1, LOCAL_JUMP, ALL_TRUE, CALM);
1414 	MOVEB(p, MATH0, offset, IFIFOAB2, 0, length, IMMED);
1415 	MATHB(p, MATH0, AND, sn_mask, MATH1, 8, IFB | IMMED2);
1416 
1417 	SEQSTORE(p, MATH0, offset, length, 0);
1418 	MATHB(p, MATH1, SHLD, MATH1, MATH1, 8, 0);
1419 	MOVEB(p, DESCBUF, 4, MATH2, 0, 8, WAITCOMP | IMMED);
1420 	MATHB(p, MATH1, OR, MATH2, MATH1, 8, 0);
1421 	MOVEB(p, MATH1, 0, CONTEXT1, 16, 8, IMMED);
1422 	MOVEB(p, MATH1, 0, CONTEXT2, 0, 4, IMMED);
1423 	if (swap == false) {
1424 		MATHB(p, MATH1, AND, upper_32_bits(PDCP_BEARER_MASK), MATH2, 4,
1425 		      IMMED2);
1426 		MATHB(p, MATH1, AND, lower_32_bits(PDCP_DIR_MASK), MATH3, 4,
1427 		      IMMED2);
1428 	} else {
1429 		MATHB(p, MATH1, AND, lower_32_bits(PDCP_BEARER_MASK_BE), MATH2,
1430 			4, IMMED2);
1431 		MATHB(p, MATH1, AND, upper_32_bits(PDCP_DIR_MASK_BE), MATH3,
1432 			4, IMMED2);
1433 	}
1434 	MATHB(p, MATH3, SHLD, MATH3, MATH3, 8, 0);
1435 	MOVEB(p, MATH2, 4, OFIFO, 0, 12, IMMED);
1436 	MOVE(p, OFIFO, 0, CONTEXT2, 4, 12, IMMED);
1437 	if (dir == OP_TYPE_ENCAP_PROTOCOL) {
1438 		MATHB(p, SEQINSZ, ADD, PDCP_MAC_I_LEN, VSEQOUTSZ, 4, IMMED2);
1439 	} else {
1440 		MATHB(p, SEQINSZ, SUB, PDCP_MAC_I_LEN, MATH1, 4, IMMED2);
1441 
1442 		MATHB(p, ZERO, ADD, MATH1, VSEQOUTSZ, 4, 0);
1443 		MATHB(p, ZERO, ADD, MATH1, VSEQINSZ, 4, 0);
1444 	}
1445 
1446 	if (dir == OP_TYPE_ENCAP_PROTOCOL)
1447 		SEQFIFOSTORE(p, MSG, 0, 0, VLF);
1448 	else
1449 		SEQFIFOSTORE(p, MSG, 0, 0, VLF | CONT);
1450 
1451 	ALG_OPERATION(p, OP_ALG_ALGSEL_SNOW_F9,
1452 		      OP_ALG_AAI_F9,
1453 		      OP_ALG_AS_INITFINAL,
1454 		      dir == OP_TYPE_ENCAP_PROTOCOL ?
1455 			     ICV_CHECK_DISABLE : ICV_CHECK_ENABLE,
1456 		      DIR_DEC);
1457 	ALG_OPERATION(p, OP_ALG_ALGSEL_AES,
1458 		      OP_ALG_AAI_CTR,
1459 		      OP_ALG_AS_INITFINAL,
1460 		      ICV_CHECK_DISABLE,
1461 		      dir == OP_TYPE_ENCAP_PROTOCOL ? DIR_ENC : DIR_DEC);
1462 
1463 	if (dir == OP_TYPE_ENCAP_PROTOCOL) {
1464 		SEQFIFOLOAD(p, MSGINSNOOP, 0, VLF | LAST2);
1465 		MOVE(p, CONTEXT2, 0, IFIFOAB1, 0, 4, LAST1 | FLUSH1 | IMMED);
1466 	} else {
1467 		SEQFIFOLOAD(p, MSGOUTSNOOP, 0, VLF | LAST2);
1468 		SEQFIFOLOAD(p, MSG1, 4, LAST1 | FLUSH1);
1469 		JUMP(p, 1, LOCAL_JUMP, ALL_TRUE, CLASS1 | NOP | NIFP);
1470 
1471 		LOAD(p, 0, DCTRL, 0, LDLEN_RST_CHA_OFIFO_PTR, IMMED);
1472 
1473 		MOVE(p, OFIFO, 0, MATH0, 0, 4, WAITCOMP | IMMED);
1474 
1475 		NFIFOADD(p, IFIFO, ICV2, 4, LAST2);
1476 
1477 		MOVE(p, MATH0, 0, IFIFO, 0, 4, WAITCOMP | IMMED);
1478 	}
1479 
1480 	return 0;
1481 }
1482 
1483 static inline int
1484 pdcp_insert_cplane_snow_zuc_op(struct program *p,
1485 			       bool swap __maybe_unused,
1486 			       struct alginfo *cipherdata,
1487 			       struct alginfo *authdata,
1488 			       unsigned int dir,
1489 			       enum pdcp_sn_size sn_size)
1490 {
1491 	uint32_t offset = 0, length = 0, sn_mask = 0;
1492 
1493 	LABEL(keyjump);
1494 	REFERENCE(pkeyjump);
1495 
1496 	if ((sn_size != PDCP_SN_SIZE_18) ||
1497 		(rta_sec_era == RTA_SEC_ERA_10)) {
1498 		int pclid;
1499 		KEY(p, KEY1, cipherdata->key_enc_flags, cipherdata->key,
1500 		    cipherdata->keylen, INLINE_KEY(cipherdata));
1501 		KEY(p, KEY2, authdata->key_enc_flags, authdata->key, authdata->keylen,
1502 		    INLINE_KEY(authdata));
1503 
1504 		if (sn_size == PDCP_SN_SIZE_5)
1505 			pclid = OP_PCLID_LTE_PDCP_CTRL_MIXED;
1506 		else
1507 			pclid = OP_PCLID_LTE_PDCP_USER_RN;
1508 
1509 		PROTOCOL(p, dir, pclid,
1510 			 ((uint16_t)cipherdata->algtype << 8) |
1511 			 (uint16_t)authdata->algtype);
1512 		return 0;
1513 	}
1514 	/* sn_size is 18 */
1515 	offset = 5;
1516 	length = 3;
1517 	sn_mask = (swap == false) ? PDCP_U_PLANE_18BIT_SN_MASK :
1518 				PDCP_U_PLANE_18BIT_SN_MASK_BE;
1519 
1520 	pkeyjump = JUMP(p, keyjump, LOCAL_JUMP, ALL_TRUE, SHRD | SELF | BOTH);
1521 	KEY(p, KEY1, cipherdata->key_enc_flags, cipherdata->key,
1522 	    cipherdata->keylen, INLINE_KEY(cipherdata));
1523 	KEY(p, KEY2, authdata->key_enc_flags, authdata->key, authdata->keylen,
1524 	    INLINE_KEY(authdata));
1525 
1526 	SET_LABEL(p, keyjump);
1527 	SEQLOAD(p, MATH0, offset, length, 0);
1528 	JUMP(p, 1, LOCAL_JUMP, ALL_TRUE, CALM);
1529 	MOVEB(p, MATH0, offset, IFIFOAB2, 0, length, IMMED);
1530 	MATHB(p, MATH0, AND, sn_mask, MATH1, 8, IFB | IMMED2);
1531 
1532 	MATHB(p, MATH1, SHLD, MATH1, MATH1, 8, 0);
1533 	MOVEB(p, DESCBUF, 4, MATH2, 0, 8, WAITCOMP | IMMED);
1534 	MATHB(p, MATH1, OR, MATH2, MATH2, 8, 0);
1535 	MOVEB(p, MATH2, 0, CONTEXT1, 0, 8, IMMED);
1536 	MOVEB(p, MATH2, 0, CONTEXT2, 0, 8, WAITCOMP | IMMED);
1537 
1538 	if (dir == OP_TYPE_ENCAP_PROTOCOL)
1539 		MATHB(p, SEQINSZ, ADD, PDCP_MAC_I_LEN, VSEQOUTSZ, 4, IMMED2);
1540 	else
1541 		MATHB(p, SEQINSZ, SUB, PDCP_MAC_I_LEN, VSEQOUTSZ, 4, IMMED2);
1542 
1543 	MATHB(p, SEQINSZ, SUB, ZERO, VSEQINSZ, 4, 0);
1544 	SEQSTORE(p, MATH0, offset, length, 0);
1545 
1546 	if (dir == OP_TYPE_ENCAP_PROTOCOL) {
1547 		SEQFIFOSTORE(p, MSG, 0, 0, VLF);
1548 		SEQFIFOLOAD(p, MSGINSNOOP, 0, VLF | LAST2);
1549 	} else {
1550 		SEQFIFOSTORE(p, MSG, 0, 0, VLF | CONT);
1551 		SEQFIFOLOAD(p, MSGOUTSNOOP, 0, VLF | LAST1 | FLUSH1);
1552 	}
1553 
1554 	ALG_OPERATION(p, OP_ALG_ALGSEL_ZUCA,
1555 		      OP_ALG_AAI_F9,
1556 		      OP_ALG_AS_INITFINAL,
1557 		      dir == OP_TYPE_ENCAP_PROTOCOL ?
1558 			     ICV_CHECK_DISABLE : ICV_CHECK_ENABLE,
1559 		      DIR_ENC);
1560 
1561 	ALG_OPERATION(p, OP_ALG_ALGSEL_SNOW_F8,
1562 		      OP_ALG_AAI_F8,
1563 		      OP_ALG_AS_INITFINAL,
1564 		      ICV_CHECK_DISABLE,
1565 		      dir == OP_TYPE_ENCAP_PROTOCOL ? DIR_ENC : DIR_DEC);
1566 	if (dir == OP_TYPE_ENCAP_PROTOCOL) {
1567 		MOVE(p, CONTEXT2, 0, IFIFOAB1, 0, 4, LAST1 | FLUSH1 | IMMED);
1568 	} else {
1569 		/* Save ICV */
1570 		MOVE(p, OFIFO, 0, MATH0, 0, 4, IMMED);
1571 		LOAD(p, NFIFOENTRY_STYPE_ALTSOURCE |
1572 		     NFIFOENTRY_DEST_CLASS2 |
1573 		     NFIFOENTRY_DTYPE_ICV |
1574 		     NFIFOENTRY_LC2 | 4, NFIFO_SZL, 0, 4, IMMED);
1575 		MOVE(p, MATH0, 0, ALTSOURCE, 0, 4, WAITCOMP | IMMED);
1576 	}
1577 
1578 	/* Reset ZUCA mode and done interrupt */
1579 	LOAD(p, CLRW_CLR_C2MODE, CLRW, 0, 4, IMMED);
1580 	LOAD(p, CIRQ_ZADI, ICTRL, 0, 4, IMMED);
1581 
1582 	PATCH_JUMP(p, pkeyjump, keyjump);
1583 	return 0;
1584 }
1585 
1586 static inline int
1587 pdcp_insert_cplane_aes_zuc_op(struct program *p,
1588 			      bool swap __maybe_unused,
1589 			      struct alginfo *cipherdata,
1590 			      struct alginfo *authdata,
1591 			      unsigned int dir,
1592 			      enum pdcp_sn_size sn_size)
1593 {
1594 	uint32_t offset = 0, length = 0, sn_mask = 0;
1595 	LABEL(keyjump);
1596 	REFERENCE(pkeyjump);
1597 
1598 	if ((sn_size != PDCP_SN_SIZE_18) ||
1599 		(rta_sec_era == RTA_SEC_ERA_10)) {
1600 		int pclid;
1601 		KEY(p, KEY1, cipherdata->key_enc_flags, cipherdata->key,
1602 		    cipherdata->keylen, INLINE_KEY(cipherdata));
1603 		KEY(p, KEY2, authdata->key_enc_flags, authdata->key, authdata->keylen,
1604 		    INLINE_KEY(authdata));
1605 
1606 		if (sn_size == PDCP_SN_SIZE_5)
1607 			pclid = OP_PCLID_LTE_PDCP_CTRL_MIXED;
1608 		else
1609 			pclid = OP_PCLID_LTE_PDCP_USER_RN;
1610 
1611 		PROTOCOL(p, dir, pclid,
1612 			 ((uint16_t)cipherdata->algtype << 8) |
1613 			 (uint16_t)authdata->algtype);
1614 
1615 		return 0;
1616 	}
1617 	/* sn_size is 18 */
1618 	offset = 5;
1619 	length = 3;
1620 	sn_mask = (swap == false) ? PDCP_U_PLANE_18BIT_SN_MASK :
1621 				PDCP_U_PLANE_18BIT_SN_MASK_BE;
1622 
1623 	pkeyjump = JUMP(p, keyjump, LOCAL_JUMP, ALL_TRUE, SHRD | SELF | BOTH);
1624 	KEY(p, KEY1, cipherdata->key_enc_flags, cipherdata->key,
1625 	    cipherdata->keylen, INLINE_KEY(cipherdata));
1626 	KEY(p, KEY2, authdata->key_enc_flags, authdata->key, authdata->keylen,
1627 	    INLINE_KEY(authdata));
1628 
1629 	SET_LABEL(p, keyjump);
1630 
1631 	SEQLOAD(p, MATH0, offset, length, 0);
1632 	JUMP(p, 1, LOCAL_JUMP, ALL_TRUE, CALM);
1633 	MOVEB(p, MATH0, offset, IFIFOAB2, 0, length, IMMED);
1634 	MATHB(p, MATH0, AND, sn_mask, MATH1, 8, IFB | IMMED2);
1635 
1636 	MATHB(p, MATH1, SHLD, MATH1, MATH1, 8, 0);
1637 	MOVEB(p, DESCBUF, 4, MATH2, 0, 8, WAITCOMP | IMMED);
1638 	MATHB(p, MATH1, OR, MATH2, MATH2, 8, 0);
1639 	MOVEB(p, MATH2, 0, CONTEXT1, 16, 8, IMMED);
1640 	MOVEB(p, MATH2, 0, CONTEXT2, 0, 8, WAITCOMP | IMMED);
1641 
1642 	if (dir == OP_TYPE_ENCAP_PROTOCOL)
1643 		MATHB(p, SEQINSZ, ADD, PDCP_MAC_I_LEN, VSEQOUTSZ, 4, IMMED2);
1644 	else
1645 		MATHB(p, SEQINSZ, SUB, PDCP_MAC_I_LEN, VSEQOUTSZ, 4, IMMED2);
1646 
1647 	MATHB(p, SEQINSZ, SUB, ZERO, VSEQINSZ, 4, 0);
1648 	SEQSTORE(p, MATH0, offset, length, 0);
1649 
1650 	if (dir == OP_TYPE_ENCAP_PROTOCOL) {
1651 		SEQFIFOSTORE(p, MSG, 0, 0, VLF);
1652 		SEQFIFOLOAD(p, MSGINSNOOP, 0, VLF | LAST2);
1653 	} else {
1654 		SEQFIFOSTORE(p, MSG, 0, 0, VLF | CONT);
1655 		SEQFIFOLOAD(p, MSGOUTSNOOP, 0, VLF | LAST1 | FLUSH1);
1656 	}
1657 
1658 	ALG_OPERATION(p, OP_ALG_ALGSEL_ZUCA,
1659 		      OP_ALG_AAI_F9,
1660 		      OP_ALG_AS_INITFINAL,
1661 		      dir == OP_TYPE_ENCAP_PROTOCOL ?
1662 			     ICV_CHECK_DISABLE : ICV_CHECK_ENABLE,
1663 		      DIR_ENC);
1664 
1665 	ALG_OPERATION(p, OP_ALG_ALGSEL_AES,
1666 		      OP_ALG_AAI_CTR,
1667 		      OP_ALG_AS_INITFINAL,
1668 		      ICV_CHECK_DISABLE,
1669 		      dir == OP_TYPE_ENCAP_PROTOCOL ? DIR_ENC : DIR_DEC);
1670 
1671 	if (dir == OP_TYPE_ENCAP_PROTOCOL) {
1672 		MOVE(p, CONTEXT2, 0, IFIFOAB1, 0, 4, LAST1 | FLUSH1 | IMMED);
1673 	} else {
1674 		/* Save ICV */
1675 		MOVE(p, OFIFO, 0, MATH0, 0, 4, IMMED);
1676 
1677 		LOAD(p, NFIFOENTRY_STYPE_ALTSOURCE |
1678 		     NFIFOENTRY_DEST_CLASS2 |
1679 		     NFIFOENTRY_DTYPE_ICV |
1680 		     NFIFOENTRY_LC2 | 4, NFIFO_SZL, 0, 4, IMMED);
1681 		MOVE(p, MATH0, 0, ALTSOURCE, 0, 4, WAITCOMP | IMMED);
1682 	}
1683 
1684 	/* Reset ZUCA mode and done interrupt */
1685 	LOAD(p, CLRW_CLR_C2MODE, CLRW, 0, 4, IMMED);
1686 	LOAD(p, CIRQ_ZADI, ICTRL, 0, 4, IMMED);
1687 
1688 	PATCH_JUMP(p, pkeyjump, keyjump);
1689 
1690 	return 0;
1691 }
1692 
1693 static inline int
1694 pdcp_insert_cplane_zuc_snow_op(struct program *p,
1695 			       bool swap __maybe_unused,
1696 			       struct alginfo *cipherdata,
1697 			       struct alginfo *authdata,
1698 			       unsigned int dir,
1699 			       enum pdcp_sn_size sn_size)
1700 {
1701 	uint32_t offset = 0, length = 0, sn_mask = 0;
1702 	LABEL(keyjump);
1703 	REFERENCE(pkeyjump);
1704 
1705 	if ((sn_size != PDCP_SN_SIZE_18) ||
1706 		(rta_sec_era == RTA_SEC_ERA_10)) {
1707 		int pclid;
1708 		KEY(p, KEY1, cipherdata->key_enc_flags, cipherdata->key,
1709 		    cipherdata->keylen, INLINE_KEY(cipherdata));
1710 		KEY(p, KEY2, authdata->key_enc_flags, authdata->key, authdata->keylen,
1711 		    INLINE_KEY(authdata));
1712 
1713 		if (sn_size == PDCP_SN_SIZE_5)
1714 			pclid = OP_PCLID_LTE_PDCP_CTRL_MIXED;
1715 		else
1716 			pclid = OP_PCLID_LTE_PDCP_USER_RN;
1717 
1718 		PROTOCOL(p, dir, pclid,
1719 			 ((uint16_t)cipherdata->algtype << 8) |
1720 			 (uint16_t)authdata->algtype);
1721 
1722 		return 0;
1723 	}
1724 	/* sn_size is 18 */
1725 	offset = 5;
1726 	length = 3;
1727 	sn_mask = (swap == false) ? PDCP_U_PLANE_18BIT_SN_MASK :
1728 				PDCP_U_PLANE_18BIT_SN_MASK_BE;
1729 
1730 	pkeyjump = JUMP(p, keyjump, LOCAL_JUMP, ALL_TRUE, SHRD | SELF | BOTH);
1731 	KEY(p, KEY1, cipherdata->key_enc_flags, cipherdata->key,
1732 	    cipherdata->keylen, INLINE_KEY(cipherdata));
1733 	KEY(p, KEY2, authdata->key_enc_flags, authdata->key, authdata->keylen,
1734 	    INLINE_KEY(authdata));
1735 
1736 	SET_LABEL(p, keyjump);
1737 	SEQLOAD(p, MATH0, offset, length, 0);
1738 	JUMP(p, 1, LOCAL_JUMP, ALL_TRUE, CALM);
1739 	MOVEB(p, MATH0, offset, IFIFOAB2, 0, length, IMMED);
1740 	MATHB(p, MATH0, AND, sn_mask, MATH1, 8, IFB | IMMED2);
1741 
1742 	MATHB(p, MATH1, SHLD, MATH1, MATH1, 8, 0);
1743 	MOVEB(p, DESCBUF, 4, MATH2, 0, 8, WAITCOMP | IMMED);
1744 	MATHB(p, MATH1, OR, MATH2, MATH1, 8, 0);
1745 	MOVEB(p, MATH1, 0, CONTEXT1, 0, 8, IMMED);
1746 	MOVEB(p, MATH1, 0, CONTEXT2, 0, 4, IMMED);
1747 	if (swap == false) {
1748 		MATHB(p, MATH1, AND, upper_32_bits(PDCP_BEARER_MASK), MATH2,
1749 		      4, IMMED2);
1750 		MATHB(p, MATH1, AND, lower_32_bits(PDCP_DIR_MASK), MATH3,
1751 		      4, IMMED2);
1752 	} else {
1753 		MATHB(p, MATH1, AND, lower_32_bits(PDCP_BEARER_MASK_BE), MATH2,
1754 			4, IMMED2);
1755 		MATHB(p, MATH1, AND, upper_32_bits(PDCP_DIR_MASK_BE), MATH3,
1756 			4, IMMED2);
1757 	}
1758 	MATHB(p, MATH3, SHLD, MATH3, MATH3, 8, 0);
1759 	MOVEB(p, MATH2, 4, OFIFO, 0, 12, IMMED);
1760 	MOVE(p, OFIFO, 0, CONTEXT2, 4, 12, IMMED);
1761 
1762 	if (dir == OP_TYPE_ENCAP_PROTOCOL) {
1763 		MATHB(p, SEQINSZ, ADD, PDCP_MAC_I_LEN, VSEQOUTSZ, 4, IMMED2);
1764 		MATHB(p, SEQINSZ, SUB, ZERO, VSEQINSZ, 4, 0);
1765 	} else {
1766 		MATHB(p, SEQINSZ, SUB, PDCP_MAC_I_LEN, VSEQOUTSZ, 4, IMMED2);
1767 		MATHB(p, VSEQOUTSZ, SUB, ZERO, VSEQINSZ, 4, 0);
1768 	}
1769 
1770 	SEQSTORE(p, MATH0, offset, length, 0);
1771 
1772 	if (dir == OP_TYPE_ENCAP_PROTOCOL) {
1773 		SEQFIFOSTORE(p, MSG, 0, 0, VLF);
1774 		SEQFIFOLOAD(p, MSGINSNOOP, 0, VLF | LAST2);
1775 	} else {
1776 		SEQFIFOSTORE(p, MSG, 0, 0, VLF | CONT);
1777 		SEQFIFOLOAD(p, MSGOUTSNOOP, 0, VLF | LAST2);
1778 	}
1779 
1780 	ALG_OPERATION(p, OP_ALG_ALGSEL_SNOW_F9,
1781 		      OP_ALG_AAI_F9,
1782 		      OP_ALG_AS_INITFINAL,
1783 		      dir == OP_TYPE_ENCAP_PROTOCOL ?
1784 			     ICV_CHECK_DISABLE : ICV_CHECK_ENABLE,
1785 		      DIR_DEC);
1786 
1787 	ALG_OPERATION(p, OP_ALG_ALGSEL_ZUCE,
1788 		      OP_ALG_AAI_F8,
1789 		      OP_ALG_AS_INITFINAL,
1790 		      ICV_CHECK_DISABLE,
1791 		      dir == OP_TYPE_ENCAP_PROTOCOL ? DIR_ENC : DIR_DEC);
1792 
1793 	if (dir == OP_TYPE_ENCAP_PROTOCOL) {
1794 		MOVE(p, CONTEXT2, 0, IFIFOAB1, 0, 4, LAST1 | FLUSH1 | IMMED);
1795 	} else {
1796 		SEQFIFOLOAD(p, MSG1, 4, LAST1 | FLUSH1);
1797 		JUMP(p, 1, LOCAL_JUMP, ALL_TRUE, CLASS1 | NOP | NIFP);
1798 
1799 		/*
1800 		 * For SEC ERA 6, there's a problem with the OFIFO
1801 		 * pointer, and thus it needs to be reset here before
1802 		 * moving to M0.
1803 		 */
1804 		LOAD(p, 0, DCTRL, 0, LDLEN_RST_CHA_OFIFO_PTR, IMMED);
1805 
1806 		/* Put ICV to M0 before sending it to C2 for comparison. */
1807 		MOVEB(p, OFIFO, 0, MATH0, 0, 4, WAITCOMP | IMMED);
1808 
1809 		LOAD(p, NFIFOENTRY_STYPE_ALTSOURCE |
1810 		     NFIFOENTRY_DEST_CLASS2 |
1811 		     NFIFOENTRY_DTYPE_ICV |
1812 		     NFIFOENTRY_LC2 | 4, NFIFO_SZL, 0, 4, IMMED);
1813 		MOVEB(p, MATH0, 0, ALTSOURCE, 0, 4, IMMED);
1814 	}
1815 
1816 	PATCH_JUMP(p, pkeyjump, keyjump);
1817 	return 0;
1818 }
1819 
1820 static inline int
1821 pdcp_insert_cplane_zuc_aes_op(struct program *p,
1822 			      bool swap __maybe_unused,
1823 			      struct alginfo *cipherdata,
1824 			      struct alginfo *authdata,
1825 			      unsigned int dir,
1826 			      enum pdcp_sn_size sn_size)
1827 {
1828 	uint32_t offset = 0, length = 0, sn_mask = 0;
1829 
1830 	if ((sn_size != PDCP_SN_SIZE_18) ||
1831 		(rta_sec_era == RTA_SEC_ERA_10)) {
1832 		int pclid;
1833 
1834 		KEY(p, KEY1, cipherdata->key_enc_flags, cipherdata->key,
1835 				cipherdata->keylen, INLINE_KEY(cipherdata));
1836 		KEY(p, KEY2, authdata->key_enc_flags, authdata->key,
1837 				authdata->keylen, INLINE_KEY(authdata));
1838 
1839 		if (sn_size == PDCP_SN_SIZE_5)
1840 			pclid = OP_PCLID_LTE_PDCP_CTRL_MIXED;
1841 		else
1842 			pclid = OP_PCLID_LTE_PDCP_USER_RN;
1843 
1844 		PROTOCOL(p, dir, pclid,
1845 			 ((uint16_t)cipherdata->algtype << 8) |
1846 			 (uint16_t)authdata->algtype);
1847 		return 0;
1848 	}
1849 
1850 	/* sn_size is 18 */
1851 	offset = 5;
1852 	length = 3;
1853 	sn_mask = (swap == false) ? PDCP_U_PLANE_18BIT_SN_MASK :
1854 				PDCP_U_PLANE_18BIT_SN_MASK_BE;
1855 
1856 	SEQLOAD(p, MATH0, offset, length, 0);
1857 	JUMP(p, 1, LOCAL_JUMP, ALL_TRUE, CALM);
1858 	MATHB(p, MATH0, AND, sn_mask, MATH1, 8, IFB | IMMED2);
1859 
1860 	MATHB(p, MATH1, SHLD, MATH1, MATH1, 8, 0);
1861 	MOVEB(p, DESCBUF, 4, MATH2, 0, 0x08, WAITCOMP | IMMED);
1862 	MATHB(p, MATH1, OR, MATH2, MATH2, 8, 0);
1863 	SEQSTORE(p, MATH0, offset, length, 0);
1864 	if (dir == OP_TYPE_ENCAP_PROTOCOL) {
1865 		KEY(p, KEY1, authdata->key_enc_flags, authdata->key,
1866 		    authdata->keylen, INLINE_KEY(authdata));
1867 		MOVEB(p, MATH2, 0, IFIFOAB1, 0, 0x08, IMMED);
1868 		MOVEB(p, MATH0, offset, IFIFOAB1, 0, length, IMMED);
1869 
1870 		MATHB(p, SEQINSZ, SUB, ZERO, VSEQINSZ, 4, 0);
1871 		MATHB(p, VSEQINSZ, ADD, PDCP_MAC_I_LEN, VSEQOUTSZ, 4, IMMED2);
1872 
1873 		ALG_OPERATION(p, OP_ALG_ALGSEL_AES,
1874 			      OP_ALG_AAI_CMAC,
1875 			      OP_ALG_AS_INITFINAL,
1876 			      ICV_CHECK_DISABLE,
1877 			      DIR_DEC);
1878 		SEQFIFOLOAD(p, MSG1, 0, VLF | LAST1 | FLUSH1);
1879 		MOVEB(p, CONTEXT1, 0, MATH3, 0, 4, WAITCOMP | IMMED);
1880 		LOAD(p, CLRW_RESET_CLS1_CHA |
1881 		     CLRW_CLR_C1KEY |
1882 		     CLRW_CLR_C1CTX |
1883 		     CLRW_CLR_C1ICV |
1884 		     CLRW_CLR_C1DATAS |
1885 		     CLRW_CLR_C1MODE,
1886 		     CLRW, 0, 4, IMMED);
1887 
1888 		KEY(p, KEY1, cipherdata->key_enc_flags, cipherdata->key,
1889 		    cipherdata->keylen, INLINE_KEY(cipherdata));
1890 
1891 		MOVEB(p, MATH2, 0, CONTEXT1, 0, 8, IMMED);
1892 		SEQINPTR(p, 0, PDCP_NULL_MAX_FRAME_LEN, RTO);
1893 
1894 		ALG_OPERATION(p, OP_ALG_ALGSEL_ZUCE,
1895 			      OP_ALG_AAI_F8,
1896 			      OP_ALG_AS_INITFINAL,
1897 			      ICV_CHECK_DISABLE,
1898 			      DIR_ENC);
1899 		SEQFIFOSTORE(p, MSG, 0, 0, VLF);
1900 
1901 		SEQFIFOLOAD(p, SKIP, length, 0);
1902 
1903 		SEQFIFOLOAD(p, MSG1, 0, VLF);
1904 		MOVEB(p, MATH3, 0, IFIFOAB1, 0, 4, LAST1 | FLUSH1 | IMMED);
1905 	} else {
1906 		MOVEB(p, MATH2, 0, CONTEXT1, 0, 8, IMMED);
1907 
1908 		MOVE(p, CONTEXT1, 0, CONTEXT2, 0, 8, IMMED);
1909 
1910 		MATHB(p, SEQINSZ, SUB, ZERO, VSEQINSZ, 4, 0);
1911 
1912 		MATHB(p, SEQINSZ, SUB, PDCP_MAC_I_LEN, VSEQOUTSZ, 4, IMMED2);
1913 
1914 		KEY(p, KEY1, cipherdata->key_enc_flags, cipherdata->key,
1915 		    cipherdata->keylen, INLINE_KEY(cipherdata));
1916 
1917 		MOVE(p, CONTEXT1, 0, CONTEXT2, 0, 8, IMMED);
1918 
1919 		ALG_OPERATION(p, OP_ALG_ALGSEL_ZUCE,
1920 			      OP_ALG_AAI_F8,
1921 			      OP_ALG_AS_INITFINAL,
1922 			      ICV_CHECK_DISABLE,
1923 			      DIR_DEC);
1924 		SEQFIFOSTORE(p, MSG, 0, 0, VLF | CONT);
1925 		SEQFIFOLOAD(p, MSG1, 0, VLF | LAST1 | FLUSH1);
1926 
1927 		MOVEB(p, OFIFO, 0, MATH3, 0, 4, IMMED);
1928 
1929 		/* conditional jump with calm added to ensure that the
1930 		 * previous processing has been completed
1931 		 */
1932 		JUMP(p, 1, LOCAL_JUMP, ALL_TRUE, CALM);
1933 
1934 		LOAD(p, CLRW_RESET_CLS1_CHA |
1935 		     CLRW_CLR_C1KEY |
1936 		     CLRW_CLR_C1CTX |
1937 		     CLRW_CLR_C1ICV |
1938 		     CLRW_CLR_C1DATAS |
1939 		     CLRW_CLR_C1MODE,
1940 		     CLRW, 0, 4, IMMED);
1941 
1942 		KEY(p, KEY1, authdata->key_enc_flags, authdata->key,
1943 		    authdata->keylen, INLINE_KEY(authdata));
1944 
1945 		SEQINPTR(p, 0, 0, SOP);
1946 
1947 		ALG_OPERATION(p, OP_ALG_ALGSEL_AES,
1948 			      OP_ALG_AAI_CMAC,
1949 			      OP_ALG_AS_INITFINAL,
1950 			      ICV_CHECK_ENABLE,
1951 			      DIR_DEC);
1952 
1953 		MATHB(p, SEQINSZ, SUB, ZERO, VSEQINSZ, 4, 0);
1954 
1955 		MOVE(p, CONTEXT2, 0, IFIFOAB1, 0, 8, IMMED);
1956 
1957 		SEQFIFOLOAD(p, MSG1, 0, VLF | LAST1 | FLUSH1);
1958 
1959 		LOAD(p, NFIFOENTRY_STYPE_ALTSOURCE |
1960 		     NFIFOENTRY_DEST_CLASS1 |
1961 		     NFIFOENTRY_DTYPE_ICV |
1962 		     NFIFOENTRY_LC1 |
1963 		     NFIFOENTRY_FC1 | 4, NFIFO_SZL, 0, 4, IMMED);
1964 		MOVEB(p, MATH3, 0, ALTSOURCE, 0, 4, IMMED);
1965 	}
1966 
1967 	return 0;
1968 }
1969 
1970 static inline int
1971 pdcp_insert_uplane_no_int_op(struct program *p,
1972 			    bool swap __maybe_unused,
1973 			    struct alginfo *cipherdata,
1974 			    unsigned int dir,
1975 			    enum pdcp_sn_size sn_size)
1976 {
1977 	int op;
1978 	uint32_t sn_mask;
1979 
1980 	/* Insert Cipher Key */
1981 	KEY(p, KEY1, cipherdata->key_enc_flags, cipherdata->key,
1982 	    cipherdata->keylen, INLINE_KEY(cipherdata));
1983 
1984 	if ((sn_size == PDCP_SN_SIZE_15) ||
1985 			(rta_sec_era >= RTA_SEC_ERA_10)) {
1986 		PROTOCOL(p, dir, OP_PCLID_LTE_PDCP_USER,
1987 			 (uint16_t)cipherdata->algtype);
1988 		return 0;
1989 	}
1990 
1991 	if (sn_size == PDCP_SN_SIZE_15) {
1992 		SEQLOAD(p, MATH0, 6, 2, 0);
1993 		sn_mask = (swap == false) ? PDCP_U_PLANE_15BIT_SN_MASK :
1994 					PDCP_U_PLANE_15BIT_SN_MASK_BE;
1995 	} else { /* SN Size == PDCP_SN_SIZE_18 */
1996 		SEQLOAD(p, MATH0, 5, 3, 0);
1997 		sn_mask = (swap == false) ? PDCP_U_PLANE_18BIT_SN_MASK :
1998 					PDCP_U_PLANE_18BIT_SN_MASK_BE;
1999 	}
2000 	JUMP(p, 1, LOCAL_JUMP, ALL_TRUE, CALM);
2001 	MATHB(p, MATH0, AND, sn_mask, MATH1, 8, IFB | IMMED2);
2002 
2003 	if (sn_size == PDCP_SN_SIZE_15)
2004 		SEQSTORE(p, MATH0, 6, 2, 0);
2005 	else /* SN Size == PDCP_SN_SIZE_18 */
2006 		SEQSTORE(p, MATH0, 5, 3, 0);
2007 
2008 	MATHB(p, MATH1, SHLD, MATH1, MATH1, 8, 0);
2009 	MOVEB(p, DESCBUF, 8, MATH2, 0, 8, WAITCOMP | IMMED);
2010 	MATHB(p, MATH1, OR, MATH2, MATH2, 8, 0);
2011 
2012 	MATHB(p, SEQINSZ, SUB, MATH3, VSEQINSZ, 4, 0);
2013 	MATHB(p, SEQINSZ, SUB, MATH3, VSEQOUTSZ, 4, 0);
2014 
2015 	SEQFIFOSTORE(p, MSG, 0, 0, VLF);
2016 
2017 	op = dir == OP_TYPE_ENCAP_PROTOCOL ? DIR_ENC : DIR_DEC;
2018 	switch (cipherdata->algtype) {
2019 	case PDCP_CIPHER_TYPE_SNOW:
2020 		MOVEB(p, MATH2, 0, CONTEXT1, 0, 8, WAITCOMP | IMMED);
2021 		ALG_OPERATION(p, OP_ALG_ALGSEL_SNOW_F8,
2022 			      OP_ALG_AAI_F8,
2023 			      OP_ALG_AS_INITFINAL,
2024 			      ICV_CHECK_DISABLE,
2025 			      op);
2026 		break;
2027 
2028 	case PDCP_CIPHER_TYPE_AES:
2029 		MOVEB(p, MATH2, 0, CONTEXT1, 0x10, 0x10, WAITCOMP | IMMED);
2030 		ALG_OPERATION(p, OP_ALG_ALGSEL_AES,
2031 			      OP_ALG_AAI_CTR,
2032 			      OP_ALG_AS_INITFINAL,
2033 			      ICV_CHECK_DISABLE,
2034 			      op);
2035 		break;
2036 
2037 	case PDCP_CIPHER_TYPE_ZUC:
2038 		MOVEB(p, MATH2, 0, CONTEXT1, 0, 0x08, IMMED);
2039 		MOVEB(p, MATH2, 0, CONTEXT1, 0x08, 0x08, WAITCOMP | IMMED);
2040 
2041 		ALG_OPERATION(p, OP_ALG_ALGSEL_ZUCE,
2042 			      OP_ALG_AAI_F8,
2043 			      OP_ALG_AS_INITFINAL,
2044 			      ICV_CHECK_DISABLE,
2045 			      op);
2046 		break;
2047 
2048 	default:
2049 		pr_err("%s: Invalid encrypt algorithm selected: %d\n",
2050 		       "pdcp_insert_uplane_15bit_op", cipherdata->algtype);
2051 		return -EINVAL;
2052 	}
2053 
2054 	SEQFIFOLOAD(p, MSG1, 0, VLF | LAST1 | FLUSH1);
2055 
2056 	return 0;
2057 }
2058 
2059 /*
2060  * Function for inserting the snippet of code responsible for creating
2061  * the HFN override code via either DPOVRD or via the input frame.
2062  */
2063 static inline int
2064 insert_hfn_ov_op(struct program *p,
2065 		 uint32_t shift,
2066 		 enum pdb_type_e pdb_type,
2067 		 bool clear_dpovrd_at_end)
2068 {
2069 	uint32_t imm = PDCP_DPOVRD_HFN_OV_EN;
2070 	uint16_t hfn_pdb_offset;
2071 	LABEL(keyjump);
2072 	REFERENCE(pkeyjump);
2073 
2074 	switch (pdb_type) {
2075 	case PDCP_PDB_TYPE_NO_PDB:
2076 		/*
2077 		 * If there is no PDB, then HFN override mechanism does not
2078 		 * make any sense, thus in this case the function will
2079 		 * return the pointer to the current position in the
2080 		 * descriptor buffer
2081 		 */
2082 		return 0;
2083 
2084 	case PDCP_PDB_TYPE_REDUCED_PDB:
2085 		hfn_pdb_offset = REDUCED_PDB_DESCBUF_HFN_BEARER_DIR_OFFSET;
2086 		break;
2087 
2088 	case PDCP_PDB_TYPE_FULL_PDB:
2089 		hfn_pdb_offset = FULL_PDB_DESCBUF_HFN_BEARER_DIR_OFFSET;
2090 		break;
2091 
2092 	default:
2093 		return -EINVAL;
2094 	}
2095 
2096 	MATHB(p, DPOVRD, AND, imm, NONE, 8, IFB | IMMED2);
2097 
2098 	pkeyjump = JUMP(p, keyjump, LOCAL_JUMP, ALL_TRUE, MATH_Z);
2099 
2100 	MATHI(p, DPOVRD, LSHIFT, shift, MATH0, 4, IMMED2);
2101 
2102 	MATHB(p, MATH0, SHLD, MATH0, MATH0, 8, 0);
2103 	MOVE(p, MATH0, 0, DESCBUF, hfn_pdb_offset, 4, IMMED);
2104 
2105 	if (clear_dpovrd_at_end) {
2106 		/*
2107 		 * For ERA8, DPOVRD could be handled by the PROTOCOL command
2108 		 * itself. For now, this is not done. Thus, clear DPOVRD here
2109 		 * to alleviate any side-effects.
2110 		 */
2111 		MATHB(p, DPOVRD, AND, ZERO, DPOVRD, 4, STL);
2112 	}
2113 
2114 	SET_LABEL(p, keyjump);
2115 	PATCH_JUMP(p, pkeyjump, keyjump);
2116 	return 0;
2117 }
2118 
2119 /*
2120  * PDCP Control PDB creation function
2121  */
2122 static inline enum pdb_type_e
2123 cnstr_pdcp_c_plane_pdb(struct program *p,
2124 		       uint32_t hfn,
2125 		       enum pdcp_sn_size sn_size,
2126 		       unsigned char bearer,
2127 		       unsigned char direction,
2128 		       uint32_t hfn_threshold)
2129 {
2130 	struct pdcp_pdb pdb;
2131 
2132 	memset(&pdb, 0x00, sizeof(struct pdcp_pdb));
2133 
2134 	/* To support 12-bit seq numbers, we use u-plane opt in pdb.
2135 	 * SEC supports 5-bit only with c-plane opt in pdb.
2136 	 */
2137 	if (sn_size == PDCP_SN_SIZE_12) {
2138 		pdb.hfn_res = hfn << PDCP_U_PLANE_PDB_LONG_SN_HFN_SHIFT;
2139 		pdb.bearer_dir_res = (uint32_t)
2140 			((bearer << PDCP_U_PLANE_PDB_BEARER_SHIFT) |
2141 			 (direction << PDCP_U_PLANE_PDB_DIR_SHIFT));
2142 
2143 		pdb.hfn_thr_res =
2144 		hfn_threshold << PDCP_U_PLANE_PDB_LONG_SN_HFN_THR_SHIFT;
2145 
2146 	} else {
2147 		/* This means 5-bit c-plane.
2148 		 * Here we use c-plane opt in pdb
2149 		 */
2150 
2151 		/* This is a HW issue. Bit 2 should be set to zero,
2152 		 * but it does not work this way. Override here.
2153 		 */
2154 		pdb.opt_res.rsvd = 0x00000002;
2155 
2156 		/* Copy relevant information from user to PDB */
2157 		pdb.hfn_res = hfn << PDCP_C_PLANE_PDB_HFN_SHIFT;
2158 		pdb.bearer_dir_res = (uint32_t)
2159 			((bearer << PDCP_C_PLANE_PDB_BEARER_SHIFT) |
2160 			(direction << PDCP_C_PLANE_PDB_DIR_SHIFT));
2161 		pdb.hfn_thr_res =
2162 		hfn_threshold << PDCP_C_PLANE_PDB_HFN_THR_SHIFT;
2163 	}
2164 
2165 	/* copy PDB in descriptor*/
2166 	__rta_out32(p, pdb.opt_res.opt);
2167 	__rta_out32(p, pdb.hfn_res);
2168 	__rta_out32(p, pdb.bearer_dir_res);
2169 	__rta_out32(p, pdb.hfn_thr_res);
2170 
2171 	return PDCP_PDB_TYPE_FULL_PDB;
2172 }
2173 
2174 /*
2175  * PDCP UPlane PDB creation function
2176  */
2177 static inline enum pdb_type_e
2178 cnstr_pdcp_u_plane_pdb(struct program *p,
2179 		       enum pdcp_sn_size sn_size,
2180 		       uint32_t hfn, unsigned short bearer,
2181 		       unsigned short direction,
2182 		       uint32_t hfn_threshold,
2183 		       struct alginfo *cipherdata,
2184 		       struct alginfo *authdata)
2185 {
2186 	struct pdcp_pdb pdb;
2187 	enum pdb_type_e pdb_type = PDCP_PDB_TYPE_FULL_PDB;
2188 	enum pdb_type_e
2189 		pdb_mask[PDCP_CIPHER_TYPE_INVALID][PDCP_AUTH_TYPE_INVALID] = {
2190 			{	/* NULL */
2191 				PDCP_PDB_TYPE_NO_PDB,		/* NULL */
2192 				PDCP_PDB_TYPE_FULL_PDB,		/* SNOW f9 */
2193 				PDCP_PDB_TYPE_FULL_PDB,		/* AES CMAC */
2194 				PDCP_PDB_TYPE_FULL_PDB		/* ZUC-I */
2195 			},
2196 			{	/* SNOW f8 */
2197 				PDCP_PDB_TYPE_FULL_PDB,		/* NULL */
2198 				PDCP_PDB_TYPE_FULL_PDB,		/* SNOW f9 */
2199 				PDCP_PDB_TYPE_REDUCED_PDB,	/* AES CMAC */
2200 				PDCP_PDB_TYPE_REDUCED_PDB	/* ZUC-I */
2201 			},
2202 			{	/* AES CTR */
2203 				PDCP_PDB_TYPE_FULL_PDB,		/* NULL */
2204 				PDCP_PDB_TYPE_REDUCED_PDB,	/* SNOW f9 */
2205 				PDCP_PDB_TYPE_FULL_PDB,		/* AES CMAC */
2206 				PDCP_PDB_TYPE_REDUCED_PDB	/* ZUC-I */
2207 			},
2208 			{	/* ZUC-E */
2209 				PDCP_PDB_TYPE_FULL_PDB,		/* NULL */
2210 				PDCP_PDB_TYPE_REDUCED_PDB,	/* SNOW f9 */
2211 				PDCP_PDB_TYPE_REDUCED_PDB,	/* AES CMAC */
2212 				PDCP_PDB_TYPE_FULL_PDB		/* ZUC-I */
2213 			},
2214 	};
2215 
2216 	/* Read options from user */
2217 	/* Depending on sequence number length, the HFN and HFN threshold
2218 	 * have different lengths.
2219 	 */
2220 	memset(&pdb, 0x00, sizeof(struct pdcp_pdb));
2221 
2222 	switch (sn_size) {
2223 	case PDCP_SN_SIZE_7:
2224 		pdb.opt_res.opt |= PDCP_U_PLANE_PDB_OPT_SHORT_SN;
2225 		pdb.hfn_res = hfn << PDCP_U_PLANE_PDB_SHORT_SN_HFN_SHIFT;
2226 		pdb.hfn_thr_res =
2227 			hfn_threshold<<PDCP_U_PLANE_PDB_SHORT_SN_HFN_THR_SHIFT;
2228 		break;
2229 
2230 	case PDCP_SN_SIZE_12:
2231 		pdb.opt_res.opt &= (uint32_t)(~PDCP_U_PLANE_PDB_OPT_SHORT_SN);
2232 		pdb.hfn_res = hfn << PDCP_U_PLANE_PDB_LONG_SN_HFN_SHIFT;
2233 		pdb.hfn_thr_res =
2234 			hfn_threshold<<PDCP_U_PLANE_PDB_LONG_SN_HFN_THR_SHIFT;
2235 		break;
2236 
2237 	case PDCP_SN_SIZE_15:
2238 		pdb.opt_res.opt = (uint32_t)(PDCP_U_PLANE_PDB_OPT_15B_SN);
2239 		pdb.hfn_res = hfn << PDCP_U_PLANE_PDB_15BIT_SN_HFN_SHIFT;
2240 		pdb.hfn_thr_res =
2241 			hfn_threshold<<PDCP_U_PLANE_PDB_15BIT_SN_HFN_THR_SHIFT;
2242 		break;
2243 
2244 	case PDCP_SN_SIZE_18:
2245 		pdb.opt_res.opt = (uint32_t)(PDCP_U_PLANE_PDB_OPT_18B_SN);
2246 		pdb.hfn_res = hfn << PDCP_U_PLANE_PDB_18BIT_SN_HFN_SHIFT;
2247 		pdb.hfn_thr_res =
2248 			hfn_threshold<<PDCP_U_PLANE_PDB_18BIT_SN_HFN_THR_SHIFT;
2249 
2250 		if (rta_sec_era == RTA_SEC_ERA_8) {
2251 			if (cipherdata && authdata)
2252 				pdb_type = pdb_mask[cipherdata->algtype]
2253 						   [authdata->algtype];
2254 		}
2255 		break;
2256 
2257 	default:
2258 		pr_err("Invalid Sequence Number Size setting in PDB\n");
2259 		return -EINVAL;
2260 	}
2261 
2262 	pdb.bearer_dir_res = (uint32_t)
2263 				((bearer << PDCP_U_PLANE_PDB_BEARER_SHIFT) |
2264 				 (direction << PDCP_U_PLANE_PDB_DIR_SHIFT));
2265 
2266 	switch (pdb_type) {
2267 	case PDCP_PDB_TYPE_NO_PDB:
2268 		break;
2269 
2270 	case PDCP_PDB_TYPE_REDUCED_PDB:
2271 		__rta_out32(p, pdb.hfn_res);
2272 		__rta_out32(p, pdb.bearer_dir_res);
2273 		break;
2274 
2275 	case PDCP_PDB_TYPE_FULL_PDB:
2276 		/* copy PDB in descriptor*/
2277 		__rta_out32(p, pdb.opt_res.opt);
2278 		__rta_out32(p, pdb.hfn_res);
2279 		__rta_out32(p, pdb.bearer_dir_res);
2280 		__rta_out32(p, pdb.hfn_thr_res);
2281 
2282 		break;
2283 
2284 	default:
2285 		return PDCP_PDB_TYPE_INVALID;
2286 	}
2287 
2288 	return pdb_type;
2289 }
2290 
2291 /**
2292  * cnstr_shdsc_pdcp_c_plane_encap - Function for creating a PDCP Control Plane
2293  *                                  encapsulation descriptor.
2294  * @descbuf: pointer to buffer for descriptor construction
2295  * @ps: if 36/40bit addressing is desired, this parameter must be true
2296  * @swap: must be true when core endianness doesn't match SEC endianness
2297  * @hfn: starting Hyper Frame Number to be used together with the SN from the
2298  *       PDCP frames.
2299  * @sn_size: size of sequence numbers, only 5/12 bit sequence numbers are valid
2300  * @bearer: radio bearer ID
2301  * @direction: the direction of the PDCP frame (UL/DL)
2302  * @hfn_threshold: HFN value that once reached triggers a warning from SEC that
2303  *                 keys should be renegotiated at the earliest convenience.
2304  * @cipherdata: pointer to block cipher transform definitions
2305  *              Valid algorithm values are those from cipher_type_pdcp enum.
2306  * @authdata: pointer to authentication transform definitions
2307  *            Valid algorithm values are those from auth_type_pdcp enum.
2308  * Return: size of descriptor written in words or negative number on error.
2309  *         Once the function returns, the value of this parameter can be used
2310  *         for reclaiming the space that wasn't used for the descriptor.
2311  *
2312  * Note: descbuf must be large enough to contain a full 256 byte long
2313  * descriptor; after the function returns, by subtracting the actual number of
2314  * bytes used, the user can reuse the remaining buffer space for other purposes.
2315  */
2316 static inline int
2317 cnstr_shdsc_pdcp_c_plane_encap(uint32_t *descbuf,
2318 			       bool ps,
2319 			       bool swap,
2320 			       uint32_t hfn,
2321 			       enum pdcp_sn_size sn_size,
2322 			       unsigned char bearer,
2323 			       unsigned char direction,
2324 			       uint32_t hfn_threshold,
2325 			       struct alginfo *cipherdata,
2326 			       struct alginfo *authdata)
2327 {
2328 	static int
2329 		(*pdcp_cp_fp[PDCP_CIPHER_TYPE_INVALID][PDCP_AUTH_TYPE_INVALID])
2330 			(struct program*, bool swap, struct alginfo *,
2331 			 struct alginfo *, unsigned int dir, enum pdcp_sn_size) = {
2332 		{	/* NULL */
2333 			pdcp_insert_cplane_null_op,	/* NULL */
2334 			pdcp_insert_cplane_int_only_op,	/* SNOW f9 */
2335 			pdcp_insert_cplane_int_only_op,	/* AES CMAC */
2336 			pdcp_insert_cplane_int_only_op	/* ZUC-I */
2337 		},
2338 		{	/* SNOW f8 */
2339 			pdcp_insert_cplane_enc_only_op,	/* NULL */
2340 			pdcp_insert_cplane_acc_op,	/* SNOW f9 */
2341 			pdcp_insert_cplane_snow_aes_op,	/* AES CMAC */
2342 			pdcp_insert_cplane_snow_zuc_op	/* ZUC-I */
2343 		},
2344 		{	/* AES CTR */
2345 			pdcp_insert_cplane_enc_only_op,	/* NULL */
2346 			pdcp_insert_cplane_aes_snow_op,	/* SNOW f9 */
2347 			pdcp_insert_cplane_acc_op,	/* AES CMAC */
2348 			pdcp_insert_cplane_aes_zuc_op	/* ZUC-I */
2349 		},
2350 		{	/* ZUC-E */
2351 			pdcp_insert_cplane_enc_only_op,	/* NULL */
2352 			pdcp_insert_cplane_zuc_snow_op,	/* SNOW f9 */
2353 			pdcp_insert_cplane_zuc_aes_op,	/* AES CMAC */
2354 			pdcp_insert_cplane_acc_op	/* ZUC-I */
2355 		},
2356 	};
2357 	static enum rta_share_type
2358 		desc_share[PDCP_CIPHER_TYPE_INVALID][PDCP_AUTH_TYPE_INVALID] = {
2359 		{	/* NULL */
2360 			SHR_WAIT,	/* NULL */
2361 			SHR_WAIT,	/* SNOW f9 */
2362 			SHR_ALWAYS,	/* AES CMAC */
2363 			SHR_WAIT	/* ZUC-I */
2364 		},
2365 		{	/* SNOW f8 */
2366 			SHR_WAIT,	/* NULL */
2367 			SHR_WAIT,	/* SNOW f9 */
2368 			SHR_WAIT,	/* AES CMAC */
2369 			SHR_WAIT	/* ZUC-I */
2370 		},
2371 		{	/* AES CTR */
2372 			SHR_WAIT,	/* NULL */
2373 			SHR_WAIT,	/* SNOW f9 */
2374 			SHR_ALWAYS,	/* AES CMAC */
2375 			SHR_WAIT	/* ZUC-I */
2376 		},
2377 		{	/* ZUC-E */
2378 			SHR_WAIT,	/* NULL */
2379 			SHR_WAIT,	/* SNOW f9 */
2380 			SHR_WAIT,	/* AES CMAC */
2381 			SHR_WAIT	/* ZUC-I */
2382 		},
2383 	};
2384 	enum pdb_type_e pdb_type;
2385 	struct program prg;
2386 	struct program *p = &prg;
2387 	int err;
2388 	LABEL(pdb_end);
2389 
2390 	if (sn_size != PDCP_SN_SIZE_12 && sn_size != PDCP_SN_SIZE_5) {
2391 		pr_err("C-plane supports only 5-bit and 12-bit sequence numbers\n");
2392 		return -EINVAL;
2393 	}
2394 
2395 	PROGRAM_CNTXT_INIT(p, descbuf, 0);
2396 	if (swap)
2397 		PROGRAM_SET_BSWAP(p);
2398 	if (ps)
2399 		PROGRAM_SET_36BIT_ADDR(p);
2400 
2401 	SHR_HDR(p, desc_share[cipherdata->algtype][authdata->algtype], 0, 0);
2402 
2403 	pdb_type = cnstr_pdcp_c_plane_pdb(p,
2404 			hfn,
2405 			sn_size,
2406 			bearer,
2407 			direction,
2408 			hfn_threshold);
2409 
2410 	SET_LABEL(p, pdb_end);
2411 
2412 	err = insert_hfn_ov_op(p, sn_size, pdb_type, true);
2413 	if (err)
2414 		return err;
2415 
2416 	err = pdcp_cp_fp[cipherdata->algtype][authdata->algtype](p,
2417 		swap,
2418 		cipherdata,
2419 		authdata,
2420 		OP_TYPE_ENCAP_PROTOCOL,
2421 		sn_size);
2422 	if (err)
2423 		return err;
2424 
2425 	PATCH_HDR(p, 0, pdb_end);
2426 
2427 	return PROGRAM_FINALIZE(p);
2428 }
2429 
2430 /**
2431  * cnstr_shdsc_pdcp_c_plane_decap - Function for creating a PDCP Control Plane
2432  *                                  decapsulation descriptor.
2433  * @descbuf: pointer to buffer for descriptor construction
2434  * @ps: if 36/40bit addressing is desired, this parameter must be true
2435  * @swap: must be true when core endianness doesn't match SEC endianness
2436  * @hfn: starting Hyper Frame Number to be used together with the SN from the
2437  *       PDCP frames.
2438  * @sn_size: size of sequence numbers, only 5/12 bit sequence numbers are valid
2439  * @bearer: radio bearer ID
2440  * @direction: the direction of the PDCP frame (UL/DL)
2441  * @hfn_threshold: HFN value that once reached triggers a warning from SEC that
2442  *                 keys should be renegotiated at the earliest convenience.
2443  * @cipherdata: pointer to block cipher transform definitions
2444  *              Valid algorithm values are those from cipher_type_pdcp enum.
2445  * @authdata: pointer to authentication transform definitions
2446  *            Valid algorithm values are those from auth_type_pdcp enum.
2447  *
2448  * Return: size of descriptor written in words or negative number on error.
2449  *         Once the function returns, the value of this parameter can be used
2450  *         for reclaiming the space that wasn't used for the descriptor.
2451  *
2452  * Note: descbuf must be large enough to contain a full 256 byte long
2453  * descriptor; after the function returns, by subtracting the actual number of
2454  * bytes used, the user can reuse the remaining buffer space for other purposes.
2455  */
2456 static inline int
2457 cnstr_shdsc_pdcp_c_plane_decap(uint32_t *descbuf,
2458 			       bool ps,
2459 			       bool swap,
2460 			       uint32_t hfn,
2461 			       enum pdcp_sn_size sn_size,
2462 			       unsigned char bearer,
2463 			       unsigned char direction,
2464 			       uint32_t hfn_threshold,
2465 			       struct alginfo *cipherdata,
2466 			       struct alginfo *authdata)
2467 {
2468 	static int
2469 		(*pdcp_cp_fp[PDCP_CIPHER_TYPE_INVALID][PDCP_AUTH_TYPE_INVALID])
2470 			(struct program*, bool swap, struct alginfo *,
2471 			 struct alginfo *, unsigned int dir, enum pdcp_sn_size) = {
2472 		{	/* NULL */
2473 			pdcp_insert_cplane_null_op,	/* NULL */
2474 			pdcp_insert_cplane_int_only_op,	/* SNOW f9 */
2475 			pdcp_insert_cplane_int_only_op,	/* AES CMAC */
2476 			pdcp_insert_cplane_int_only_op	/* ZUC-I */
2477 		},
2478 		{	/* SNOW f8 */
2479 			pdcp_insert_cplane_enc_only_op,	/* NULL */
2480 			pdcp_insert_cplane_acc_op,	/* SNOW f9 */
2481 			pdcp_insert_cplane_snow_aes_op,	/* AES CMAC */
2482 			pdcp_insert_cplane_snow_zuc_op	/* ZUC-I */
2483 		},
2484 		{	/* AES CTR */
2485 			pdcp_insert_cplane_enc_only_op,	/* NULL */
2486 			pdcp_insert_cplane_aes_snow_op,	/* SNOW f9 */
2487 			pdcp_insert_cplane_acc_op,	/* AES CMAC */
2488 			pdcp_insert_cplane_aes_zuc_op	/* ZUC-I */
2489 		},
2490 		{	/* ZUC-E */
2491 			pdcp_insert_cplane_enc_only_op,	/* NULL */
2492 			pdcp_insert_cplane_zuc_snow_op,	/* SNOW f9 */
2493 			pdcp_insert_cplane_zuc_aes_op,	/* AES CMAC */
2494 			pdcp_insert_cplane_acc_op	/* ZUC-I */
2495 		},
2496 	};
2497 	static enum rta_share_type
2498 		desc_share[PDCP_CIPHER_TYPE_INVALID][PDCP_AUTH_TYPE_INVALID] = {
2499 		{	/* NULL */
2500 			SHR_WAIT,	/* NULL */
2501 			SHR_WAIT,	/* SNOW f9 */
2502 			SHR_ALWAYS,	/* AES CMAC */
2503 			SHR_WAIT	/* ZUC-I */
2504 		},
2505 		{	/* SNOW f8 */
2506 			SHR_WAIT,	/* NULL */
2507 			SHR_WAIT,	/* SNOW f9 */
2508 			SHR_WAIT,	/* AES CMAC */
2509 			SHR_WAIT	/* ZUC-I */
2510 		},
2511 		{	/* AES CTR */
2512 			SHR_WAIT,	/* NULL */
2513 			SHR_WAIT,	/* SNOW f9 */
2514 			SHR_ALWAYS,	/* AES CMAC */
2515 			SHR_WAIT	/* ZUC-I */
2516 		},
2517 		{	/* ZUC-E */
2518 			SHR_WAIT,	/* NULL */
2519 			SHR_WAIT,	/* SNOW f9 */
2520 			SHR_WAIT,	/* AES CMAC */
2521 			SHR_WAIT	/* ZUC-I */
2522 		},
2523 	};
2524 	enum pdb_type_e pdb_type;
2525 	struct program prg;
2526 	struct program *p = &prg;
2527 	int err;
2528 	LABEL(pdb_end);
2529 
2530 	if (sn_size != PDCP_SN_SIZE_12 && sn_size != PDCP_SN_SIZE_5) {
2531 		pr_err("C-plane supports only 5-bit and 12-bit sequence numbers\n");
2532 		return -EINVAL;
2533 	}
2534 
2535 	PROGRAM_CNTXT_INIT(p, descbuf, 0);
2536 	if (swap)
2537 		PROGRAM_SET_BSWAP(p);
2538 	if (ps)
2539 		PROGRAM_SET_36BIT_ADDR(p);
2540 
2541 	SHR_HDR(p, desc_share[cipherdata->algtype][authdata->algtype], 0, 0);
2542 
2543 	pdb_type = cnstr_pdcp_c_plane_pdb(p,
2544 			hfn,
2545 			sn_size,
2546 			bearer,
2547 			direction,
2548 			hfn_threshold);
2549 
2550 	SET_LABEL(p, pdb_end);
2551 
2552 	err = insert_hfn_ov_op(p, sn_size, pdb_type, true);
2553 	if (err)
2554 		return err;
2555 
2556 	err = pdcp_cp_fp[cipherdata->algtype][authdata->algtype](p,
2557 		swap,
2558 		cipherdata,
2559 		authdata,
2560 		OP_TYPE_DECAP_PROTOCOL,
2561 		sn_size);
2562 	if (err)
2563 		return err;
2564 
2565 	PATCH_HDR(p, 0, pdb_end);
2566 
2567 	return PROGRAM_FINALIZE(p);
2568 }
2569 
2570 static int
2571 pdcp_insert_uplane_with_int_op(struct program *p,
2572 			      bool swap __maybe_unused,
2573 			      struct alginfo *cipherdata,
2574 			      struct alginfo *authdata,
2575 			      enum pdcp_sn_size sn_size,
2576 			      unsigned int dir)
2577 {
2578 	static int
2579 		(*pdcp_cp_fp[PDCP_CIPHER_TYPE_INVALID][PDCP_AUTH_TYPE_INVALID])
2580 			(struct program*, bool swap, struct alginfo *,
2581 			 struct alginfo *, unsigned int dir, enum pdcp_sn_size) = {
2582 		{	/* NULL */
2583 			pdcp_insert_cplane_null_op,	/* NULL */
2584 			pdcp_insert_cplane_int_only_op,	/* SNOW f9 */
2585 			pdcp_insert_cplane_int_only_op,	/* AES CMAC */
2586 			pdcp_insert_cplane_int_only_op	/* ZUC-I */
2587 		},
2588 		{	/* SNOW f8 */
2589 			pdcp_insert_cplane_enc_only_op,	/* NULL */
2590 			pdcp_insert_uplane_snow_snow_op, /* SNOW f9 */
2591 			pdcp_insert_cplane_snow_aes_op,	/* AES CMAC */
2592 			pdcp_insert_cplane_snow_zuc_op	/* ZUC-I */
2593 		},
2594 		{	/* AES CTR */
2595 			pdcp_insert_cplane_enc_only_op,	/* NULL */
2596 			pdcp_insert_cplane_aes_snow_op,	/* SNOW f9 */
2597 			pdcp_insert_uplane_aes_aes_op,	/* AES CMAC */
2598 			pdcp_insert_cplane_aes_zuc_op	/* ZUC-I */
2599 		},
2600 		{	/* ZUC-E */
2601 			pdcp_insert_cplane_enc_only_op,	/* NULL */
2602 			pdcp_insert_cplane_zuc_snow_op,	/* SNOW f9 */
2603 			pdcp_insert_cplane_zuc_aes_op,	/* AES CMAC */
2604 			pdcp_insert_uplane_zuc_zuc_op	/* ZUC-I */
2605 		},
2606 	};
2607 	int err;
2608 
2609 	err = pdcp_cp_fp[cipherdata->algtype][authdata->algtype](p,
2610 		swap,
2611 		cipherdata,
2612 		authdata,
2613 		dir,
2614 		sn_size);
2615 	if (err)
2616 		return err;
2617 
2618 	return 0;
2619 }
2620 
2621 
2622 /**
2623  * cnstr_shdsc_pdcp_u_plane_encap - Function for creating a PDCP User Plane
2624  *                                  encapsulation descriptor.
2625  * @descbuf: pointer to buffer for descriptor construction
2626  * @ps: if 36/40bit addressing is desired, this parameter must be true
2627  * @swap: must be true when core endianness doesn't match SEC endianness
2628  * @sn_size: selects Sequence Number Size: 7/12/15 bits
2629  * @hfn: starting Hyper Frame Number to be used together with the SN from the
2630  *       PDCP frames.
2631  * @bearer: radio bearer ID
2632  * @direction: the direction of the PDCP frame (UL/DL)
2633  * @hfn_threshold: HFN value that once reached triggers a warning from SEC that
2634  *                 keys should be renegotiated at the earliest convenience.
2635  * @cipherdata: pointer to block cipher transform definitions
2636  *              Valid algorithm values are those from cipher_type_pdcp enum.
2637  *
2638  * Return: size of descriptor written in words or negative number on error.
2639  *         Once the function returns, the value of this parameter can be used
2640  *         for reclaiming the space that wasn't used for the descriptor.
2641  *
2642  * Note: descbuf must be large enough to contain a full 256 byte long
2643  * descriptor; after the function returns, by subtracting the actual number of
2644  * bytes used, the user can reuse the remaining buffer space for other purposes.
2645  */
2646 static inline int
2647 cnstr_shdsc_pdcp_u_plane_encap(uint32_t *descbuf,
2648 			       bool ps,
2649 			       bool swap,
2650 			       enum pdcp_sn_size sn_size,
2651 			       uint32_t hfn,
2652 			       unsigned short bearer,
2653 			       unsigned short direction,
2654 			       uint32_t hfn_threshold,
2655 			       struct alginfo *cipherdata,
2656 			       struct alginfo *authdata)
2657 {
2658 	struct program prg;
2659 	struct program *p = &prg;
2660 	int err;
2661 	enum pdb_type_e pdb_type;
2662 	static enum rta_share_type
2663 		desc_share[PDCP_CIPHER_TYPE_INVALID][PDCP_AUTH_TYPE_INVALID] = {
2664 		{	/* NULL */
2665 			SHR_WAIT,	/* NULL */
2666 			SHR_WAIT,	/* SNOW f9 */
2667 			SHR_ALWAYS,	/* AES CMAC */
2668 			SHR_WAIT	/* ZUC-I */
2669 		},
2670 		{	/* SNOW f8 */
2671 			SHR_WAIT,	/* NULL */
2672 			SHR_WAIT,	/* SNOW f9 */
2673 			SHR_WAIT,	/* AES CMAC */
2674 			SHR_WAIT	/* ZUC-I */
2675 		},
2676 		{	/* AES CTR */
2677 			SHR_WAIT,	/* NULL */
2678 			SHR_WAIT,	/* SNOW f9 */
2679 			SHR_ALWAYS,	/* AES CMAC */
2680 			SHR_WAIT	/* ZUC-I */
2681 		},
2682 		{	/* ZUC-E */
2683 			SHR_WAIT,	/* NULL */
2684 			SHR_WAIT,	/* SNOW f9 */
2685 			SHR_WAIT,	/* AES CMAC */
2686 			SHR_WAIT	/* ZUC-I */
2687 		},
2688 	};
2689 	LABEL(pdb_end);
2690 
2691 	PROGRAM_CNTXT_INIT(p, descbuf, 0);
2692 	if (swap)
2693 		PROGRAM_SET_BSWAP(p);
2694 	if (ps)
2695 		PROGRAM_SET_36BIT_ADDR(p);
2696 
2697 	if (authdata)
2698 		SHR_HDR(p, desc_share[cipherdata->algtype][authdata->algtype], 0, 0);
2699 	else
2700 		SHR_HDR(p, SHR_WAIT, 0, 0);
2701 	pdb_type = cnstr_pdcp_u_plane_pdb(p, sn_size, hfn,
2702 					  bearer, direction, hfn_threshold,
2703 					  cipherdata, authdata);
2704 	if (pdb_type == PDCP_PDB_TYPE_INVALID) {
2705 		pr_err("Error creating PDCP UPlane PDB\n");
2706 		return -EINVAL;
2707 	}
2708 	SET_LABEL(p, pdb_end);
2709 
2710 	err = insert_hfn_ov_op(p, sn_size, pdb_type, true);
2711 	if (err)
2712 		return err;
2713 
2714 	switch (sn_size) {
2715 	case PDCP_SN_SIZE_7:
2716 	case PDCP_SN_SIZE_12:
2717 		switch (cipherdata->algtype) {
2718 		case PDCP_CIPHER_TYPE_ZUC:
2719 			/* fallthrough */
2720 		case PDCP_CIPHER_TYPE_AES:
2721 		case PDCP_CIPHER_TYPE_SNOW:
2722 		case PDCP_CIPHER_TYPE_NULL:
2723 			if (rta_sec_era == RTA_SEC_ERA_8 &&
2724 					authdata && authdata->algtype == 0){
2725 				err = pdcp_insert_uplane_with_int_op(p, swap,
2726 						cipherdata, authdata,
2727 						sn_size,
2728 						OP_TYPE_ENCAP_PROTOCOL);
2729 				if (err)
2730 					return err;
2731 				break;
2732 			}
2733 
2734 			if (pdb_type != PDCP_PDB_TYPE_FULL_PDB) {
2735 				pr_err("PDB type must be FULL for PROTO desc\n");
2736 				return -EINVAL;
2737 			}
2738 
2739 			/* Insert auth key if requested */
2740 			if (authdata && authdata->algtype) {
2741 				KEY(p, KEY2, authdata->key_enc_flags,
2742 				    (uint64_t)authdata->key, authdata->keylen,
2743 				    INLINE_KEY(authdata));
2744 			}
2745 			/* Insert Cipher Key */
2746 			KEY(p, KEY1, cipherdata->key_enc_flags,
2747 			    (uint64_t)cipherdata->key, cipherdata->keylen,
2748 			    INLINE_KEY(cipherdata));
2749 
2750 			if (authdata)
2751 				PROTOCOL(p, OP_TYPE_ENCAP_PROTOCOL,
2752 					 OP_PCLID_LTE_PDCP_USER_RN,
2753 					 ((uint16_t)cipherdata->algtype << 8) |
2754 					 (uint16_t)authdata->algtype);
2755 			else
2756 				PROTOCOL(p, OP_TYPE_ENCAP_PROTOCOL,
2757 					 OP_PCLID_LTE_PDCP_USER,
2758 					 (uint16_t)cipherdata->algtype);
2759 			break;
2760 		default:
2761 			pr_err("%s: Invalid encrypt algorithm selected: %d\n",
2762 			       "cnstr_pcl_shdsc_pdcp_u_plane_decap",
2763 			       cipherdata->algtype);
2764 			return -EINVAL;
2765 		}
2766 		break;
2767 
2768 	case PDCP_SN_SIZE_15:
2769 	case PDCP_SN_SIZE_18:
2770 		if (authdata) {
2771 			err = pdcp_insert_uplane_with_int_op(p, swap,
2772 					cipherdata, authdata,
2773 					sn_size,
2774 					OP_TYPE_ENCAP_PROTOCOL);
2775 			if (err)
2776 				return err;
2777 
2778 			break;
2779 		}
2780 
2781 		switch (cipherdata->algtype) {
2782 		case PDCP_CIPHER_TYPE_NULL:
2783 			insert_copy_frame_op(p,
2784 					     cipherdata,
2785 					     OP_TYPE_ENCAP_PROTOCOL);
2786 			break;
2787 
2788 		default:
2789 			err = pdcp_insert_uplane_no_int_op(p, swap, cipherdata,
2790 					OP_TYPE_ENCAP_PROTOCOL, sn_size);
2791 			if (err)
2792 				return err;
2793 			break;
2794 		}
2795 		break;
2796 
2797 	case PDCP_SN_SIZE_5:
2798 	default:
2799 		pr_err("Invalid SN size selected\n");
2800 		return -ENOTSUP;
2801 	}
2802 
2803 	PATCH_HDR(p, 0, pdb_end);
2804 	return PROGRAM_FINALIZE(p);
2805 }
2806 
2807 /**
2808  * cnstr_shdsc_pdcp_u_plane_decap - Function for creating a PDCP User Plane
2809  *                                  decapsulation descriptor.
2810  * @descbuf: pointer to buffer for descriptor construction
2811  * @ps: if 36/40bit addressing is desired, this parameter must be true
2812  * @swap: must be true when core endianness doesn't match SEC endianness
2813  * @sn_size: selects Sequence Number Size: 7/12/15 bits
2814  * @hfn: starting Hyper Frame Number to be used together with the SN from the
2815  *       PDCP frames.
2816  * @bearer: radio bearer ID
2817  * @direction: the direction of the PDCP frame (UL/DL)
2818  * @hfn_threshold: HFN value that once reached triggers a warning from SEC that
2819  *                 keys should be renegotiated at the earliest convenience.
2820  * @cipherdata: pointer to block cipher transform definitions
2821  *              Valid algorithm values are those from cipher_type_pdcp enum.
2822  *
2823  * Return: size of descriptor written in words or negative number on error.
2824  *         Once the function returns, the value of this parameter can be used
2825  *         for reclaiming the space that wasn't used for the descriptor.
2826  *
2827  * Note: descbuf must be large enough to contain a full 256 byte long
2828  * descriptor; after the function returns, by subtracting the actual number of
2829  * bytes used, the user can reuse the remaining buffer space for other purposes.
2830  */
2831 static inline int
2832 cnstr_shdsc_pdcp_u_plane_decap(uint32_t *descbuf,
2833 			       bool ps,
2834 			       bool swap,
2835 			       enum pdcp_sn_size sn_size,
2836 			       uint32_t hfn,
2837 			       unsigned short bearer,
2838 			       unsigned short direction,
2839 			       uint32_t hfn_threshold,
2840 			       struct alginfo *cipherdata,
2841 			       struct alginfo *authdata)
2842 {
2843 	struct program prg;
2844 	struct program *p = &prg;
2845 	int err;
2846 	enum pdb_type_e pdb_type;
2847 	static enum rta_share_type
2848 		desc_share[PDCP_CIPHER_TYPE_INVALID][PDCP_AUTH_TYPE_INVALID] = {
2849 		{	/* NULL */
2850 			SHR_WAIT,	/* NULL */
2851 			SHR_WAIT,	/* SNOW f9 */
2852 			SHR_ALWAYS,	/* AES CMAC */
2853 			SHR_WAIT	/* ZUC-I */
2854 		},
2855 		{	/* SNOW f8 */
2856 			SHR_WAIT,	/* NULL */
2857 			SHR_WAIT,	/* SNOW f9 */
2858 			SHR_WAIT,	/* AES CMAC */
2859 			SHR_WAIT	/* ZUC-I */
2860 		},
2861 		{	/* AES CTR */
2862 			SHR_WAIT,	/* NULL */
2863 			SHR_WAIT,	/* SNOW f9 */
2864 			SHR_ALWAYS,	/* AES CMAC */
2865 			SHR_WAIT	/* ZUC-I */
2866 		},
2867 		{	/* ZUC-E */
2868 			SHR_WAIT,	/* NULL */
2869 			SHR_WAIT,	/* SNOW f9 */
2870 			SHR_WAIT,	/* AES CMAC */
2871 			SHR_WAIT	/* ZUC-I */
2872 		},
2873 	};
2874 
2875 	LABEL(pdb_end);
2876 
2877 	PROGRAM_CNTXT_INIT(p, descbuf, 0);
2878 	if (swap)
2879 		PROGRAM_SET_BSWAP(p);
2880 	if (ps)
2881 		PROGRAM_SET_36BIT_ADDR(p);
2882 	if (authdata)
2883 		SHR_HDR(p, desc_share[cipherdata->algtype][authdata->algtype], 0, 0);
2884 	else
2885 		SHR_HDR(p, SHR_WAIT, 0, 0);
2886 
2887 	pdb_type = cnstr_pdcp_u_plane_pdb(p, sn_size, hfn, bearer,
2888 					  direction, hfn_threshold,
2889 					  cipherdata, authdata);
2890 	if (pdb_type == PDCP_PDB_TYPE_INVALID) {
2891 		pr_err("Error creating PDCP UPlane PDB\n");
2892 		return -EINVAL;
2893 	}
2894 	SET_LABEL(p, pdb_end);
2895 
2896 	err = insert_hfn_ov_op(p, sn_size, pdb_type, true);
2897 	if (err)
2898 		return err;
2899 
2900 	switch (sn_size) {
2901 	case PDCP_SN_SIZE_7:
2902 	case PDCP_SN_SIZE_12:
2903 		switch (cipherdata->algtype) {
2904 		case PDCP_CIPHER_TYPE_ZUC:
2905 			/* fallthrough */
2906 		case PDCP_CIPHER_TYPE_AES:
2907 		case PDCP_CIPHER_TYPE_SNOW:
2908 		case PDCP_CIPHER_TYPE_NULL:
2909 			if (pdb_type != PDCP_PDB_TYPE_FULL_PDB) {
2910 				pr_err("PDB type must be FULL for PROTO desc\n");
2911 				return -EINVAL;
2912 			}
2913 
2914 			/* Insert auth key if requested */
2915 			if (authdata && authdata->algtype)
2916 				KEY(p, KEY2, authdata->key_enc_flags,
2917 				    (uint64_t)authdata->key, authdata->keylen,
2918 				    INLINE_KEY(authdata));
2919 			else if (authdata && authdata->algtype == 0) {
2920 				err = pdcp_insert_uplane_with_int_op(p, swap,
2921 						cipherdata, authdata,
2922 						sn_size,
2923 						OP_TYPE_DECAP_PROTOCOL);
2924 				if (err)
2925 					return err;
2926 				break;
2927 			}
2928 
2929 			/* Insert Cipher Key */
2930 			KEY(p, KEY1, cipherdata->key_enc_flags,
2931 			    cipherdata->key, cipherdata->keylen,
2932 			    INLINE_KEY(cipherdata));
2933 			if (authdata)
2934 				PROTOCOL(p, OP_TYPE_DECAP_PROTOCOL,
2935 					 OP_PCLID_LTE_PDCP_USER_RN,
2936 					 ((uint16_t)cipherdata->algtype << 8) |
2937 					 (uint16_t)authdata->algtype);
2938 			else
2939 				PROTOCOL(p, OP_TYPE_DECAP_PROTOCOL,
2940 					 OP_PCLID_LTE_PDCP_USER,
2941 					 (uint16_t)cipherdata->algtype);
2942 			break;
2943 		default:
2944 			pr_err("%s: Invalid encrypt algorithm selected: %d\n",
2945 			       "cnstr_pcl_shdsc_pdcp_u_plane_decap",
2946 			       cipherdata->algtype);
2947 			return -EINVAL;
2948 		}
2949 		break;
2950 
2951 	case PDCP_SN_SIZE_15:
2952 	case PDCP_SN_SIZE_18:
2953 		if (authdata) {
2954 			err = pdcp_insert_uplane_with_int_op(p, swap,
2955 					cipherdata, authdata,
2956 					sn_size,
2957 					OP_TYPE_DECAP_PROTOCOL);
2958 			if (err)
2959 				return err;
2960 
2961 			break;
2962 		}
2963 
2964 		switch (cipherdata->algtype) {
2965 		case PDCP_CIPHER_TYPE_NULL:
2966 			insert_copy_frame_op(p,
2967 					     cipherdata,
2968 					     OP_TYPE_DECAP_PROTOCOL);
2969 			break;
2970 
2971 		default:
2972 			err = pdcp_insert_uplane_no_int_op(p, swap, cipherdata,
2973 				OP_TYPE_DECAP_PROTOCOL, sn_size);
2974 			if (err)
2975 				return err;
2976 			break;
2977 		}
2978 		break;
2979 
2980 	case PDCP_SN_SIZE_5:
2981 	default:
2982 		pr_err("Invalid SN size selected\n");
2983 		return -ENOTSUP;
2984 	}
2985 
2986 	PATCH_HDR(p, 0, pdb_end);
2987 	return PROGRAM_FINALIZE(p);
2988 }
2989 
2990 /**
2991  * cnstr_shdsc_pdcp_short_mac - Function for creating a PDCP Short MAC
2992  *                              descriptor.
2993  * @descbuf: pointer to buffer for descriptor construction
2994  * @ps: if 36/40bit addressing is desired, this parameter must be true
2995  * @swap: must be true when core endianness doesn't match SEC endianness
2996  * @authdata: pointer to authentication transform definitions
2997  *            Valid algorithm values are those from auth_type_pdcp enum.
2998  *
2999  * Return: size of descriptor written in words or negative number on error.
3000  *         Once the function returns, the value of this parameter can be used
3001  *         for reclaiming the space that wasn't used for the descriptor.
3002  *
3003  * Note: descbuf must be large enough to contain a full 256 byte long
3004  * descriptor; after the function returns, by subtracting the actual number of
3005  * bytes used, the user can reuse the remaining buffer space for other purposes.
3006  */
3007 static inline int
3008 cnstr_shdsc_pdcp_short_mac(uint32_t *descbuf,
3009 			   bool ps,
3010 			   bool swap,
3011 			   struct alginfo *authdata)
3012 {
3013 	struct program prg;
3014 	struct program *p = &prg;
3015 	uint32_t iv[3] = {0, 0, 0};
3016 
3017 	PROGRAM_CNTXT_INIT(p, descbuf, 0);
3018 	if (swap)
3019 		PROGRAM_SET_BSWAP(p);
3020 	if (ps)
3021 		PROGRAM_SET_36BIT_ADDR(p);
3022 
3023 	SHR_HDR(p, SHR_ALWAYS, 1, 0);
3024 
3025 	MATHB(p, SEQINSZ, SUB, ZERO, VSEQINSZ, 4, 0);
3026 	MATHB(p, SEQINSZ, SUB, ZERO, MATH1, 4, 0);
3027 
3028 	MATHB(p, ZERO, ADD, MATH1, VSEQOUTSZ, 4, 0);
3029 
3030 	switch (authdata->algtype) {
3031 	case PDCP_AUTH_TYPE_NULL:
3032 		SEQFIFOSTORE(p, MSG, 0, 0, VLF);
3033 		MOVE(p, AB1, 0, OFIFO, 0, MATH1, 0);
3034 
3035 		LOAD(p, (uintptr_t)iv, MATH0, 0, 8, IMMED | COPY);
3036 		SEQFIFOLOAD(p, MSG1, 0, VLF | LAST1 | LAST2 | FLUSH1);
3037 		SEQSTORE(p, MATH0, 0, 4, 0);
3038 
3039 		break;
3040 
3041 	case PDCP_AUTH_TYPE_SNOW:
3042 		/* IV calculation based on 3GPP specs. 36331, section:5.3.7.4 */
3043 		iv[0] = 0xFFFFFFFF;
3044 		iv[1] = swab32(0x04000000);
3045 		iv[2] = swab32(0xF8000000);
3046 
3047 		KEY(p, KEY2, authdata->key_enc_flags, authdata->key,
3048 		    authdata->keylen, INLINE_KEY(authdata));
3049 		LOAD(p, (uintptr_t)&iv, CONTEXT2, 0, 12, IMMED | COPY);
3050 		ALG_OPERATION(p, OP_ALG_ALGSEL_SNOW_F9,
3051 			      OP_ALG_AAI_F9,
3052 			      OP_ALG_AS_INITFINAL,
3053 			      ICV_CHECK_DISABLE,
3054 			      DIR_ENC);
3055 		SEQFIFOSTORE(p, MSG, 0, 0, VLF);
3056 
3057 		MOVE(p, AB1, 0, OFIFO, 0, MATH1, 0);
3058 
3059 		SEQFIFOLOAD(p, MSGINSNOOP, 0, VLF | LAST1 | LAST2 | FLUSH1);
3060 		SEQSTORE(p, CONTEXT2, 0, 4, 0);
3061 
3062 		break;
3063 
3064 	case PDCP_AUTH_TYPE_AES:
3065 		iv[0] = 0xFFFFFFFF;
3066 		iv[1] = swap ? swab32(0xFC000000) : 0xFC000000;
3067 		iv[2] = 0x00000000; /* unused */
3068 
3069 		KEY(p, KEY1, authdata->key_enc_flags, authdata->key,
3070 		    authdata->keylen, INLINE_KEY(authdata));
3071 		LOAD(p, (uintptr_t)&iv, MATH0, 0, 8, IMMED | COPY);
3072 		MOVE(p, MATH0, 0, IFIFOAB1, 0, 8, IMMED);
3073 		ALG_OPERATION(p, OP_ALG_ALGSEL_AES,
3074 			      OP_ALG_AAI_CMAC,
3075 			      OP_ALG_AS_INITFINAL,
3076 			      ICV_CHECK_DISABLE,
3077 			      DIR_ENC);
3078 		SEQFIFOSTORE(p, MSG, 0, 0, VLF);
3079 
3080 		MOVE(p, AB2, 0, OFIFO, 0, MATH1, 0);
3081 
3082 		SEQFIFOLOAD(p, MSGINSNOOP, 0, VLF | LAST1 | LAST2 | FLUSH1);
3083 		SEQSTORE(p, CONTEXT1, 0, 4, 0);
3084 
3085 		break;
3086 
3087 	case PDCP_AUTH_TYPE_ZUC:
3088 		iv[0] = 0xFFFFFFFF;
3089 		iv[1] = swab32(0xFC000000);
3090 		iv[2] = 0x00000000; /* unused */
3091 
3092 		KEY(p, KEY2, authdata->key_enc_flags, authdata->key,
3093 		    authdata->keylen, INLINE_KEY(authdata));
3094 		LOAD(p, (uintptr_t)&iv, CONTEXT2, 0, 12, IMMED | COPY);
3095 		ALG_OPERATION(p, OP_ALG_ALGSEL_ZUCA,
3096 			      OP_ALG_AAI_F9,
3097 			      OP_ALG_AS_INITFINAL,
3098 			      ICV_CHECK_DISABLE,
3099 			      DIR_ENC);
3100 		SEQFIFOSTORE(p, MSG, 0, 0, VLF);
3101 		MOVE(p, AB1, 0, OFIFO, 0, MATH1, 0);
3102 		SEQFIFOLOAD(p, MSGINSNOOP, 0, VLF | LAST1 | LAST2 | FLUSH1);
3103 		SEQSTORE(p, CONTEXT2, 0, 4, 0);
3104 
3105 		break;
3106 
3107 	default:
3108 		pr_err("%s: Invalid integrity algorithm selected: %d\n",
3109 		       "cnstr_shdsc_pdcp_short_mac", authdata->algtype);
3110 		return -EINVAL;
3111 	}
3112 
3113 	return PROGRAM_FINALIZE(p);
3114 }
3115 
3116 #endif /* __DESC_PDCP_H__ */
3117