xref: /dpdk/drivers/common/dpaax/caamflib/desc/pdcp.h (revision 68a03efeed657e6e05f281479b33b51102797e15)
1 /* SPDX-License-Identifier: BSD-3-Clause or GPL-2.0+
2  * Copyright 2008-2013 Freescale Semiconductor, Inc.
3  * Copyright 2019-2020 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 /**
274  * rta_inline_pdcp_query() - Provide indications if a key can be passed as
275  *                           immediate data or shall be referenced in a
276  *                           shared descriptor.
277  * Return: 0 if data can be inlined or 1 if referenced.
278  */
279 static inline int
280 rta_inline_pdcp_query(enum auth_type_pdcp auth_alg,
281 		      enum cipher_type_pdcp cipher_alg,
282 		      enum pdcp_sn_size sn_size,
283 		      int8_t hfn_ovd)
284 {
285 	/**
286 	 * Shared Descriptors for some of the cases does not fit in the
287 	 * MAX_DESC_SIZE of the descriptor especially when non-protocol
288 	 * descriptors are formed as in 18bit cases and when HFN override
289 	 * is enabled as 2 extra words are added in the job descriptor.
290 	 * The cases which exceed are for RTA_SEC_ERA=8 and HFN override
291 	 * enabled and 18bit uplane and either of following Algo combinations.
292 	 * - SNOW-AES
293 	 * - AES-SNOW
294 	 * - SNOW-SNOW
295 	 * - ZUC-SNOW
296 	 *
297 	 * We cannot make inline for all cases, as this will impact performance
298 	 * due to extra memory accesses for the keys.
299 	 */
300 	if ((rta_sec_era == RTA_SEC_ERA_8) && hfn_ovd &&
301 			(sn_size == PDCP_SN_SIZE_18) &&
302 			((cipher_alg == PDCP_CIPHER_TYPE_SNOW &&
303 				auth_alg == PDCP_AUTH_TYPE_AES) ||
304 			(cipher_alg == PDCP_CIPHER_TYPE_AES &&
305 				auth_alg == PDCP_AUTH_TYPE_SNOW) ||
306 			(cipher_alg == PDCP_CIPHER_TYPE_SNOW &&
307 				auth_alg == PDCP_AUTH_TYPE_SNOW) ||
308 			(cipher_alg == PDCP_CIPHER_TYPE_ZUC &&
309 				auth_alg == PDCP_AUTH_TYPE_SNOW))) {
310 
311 		return 1;
312 	}
313 
314 	return 0;
315 }
316 
317 /*
318  * Function for appending the portion of a PDCP Control Plane shared descriptor
319  * which performs NULL encryption and integrity (i.e. copies the input frame
320  * to the output frame, appending 32 bits of zeros at the end (MAC-I for
321  * NULL integrity).
322  */
323 static inline int
324 pdcp_insert_cplane_null_op(struct program *p,
325 			   bool swap __maybe_unused,
326 			   struct alginfo *cipherdata __maybe_unused,
327 			   struct alginfo *authdata __maybe_unused,
328 			   unsigned int dir,
329 			   enum pdcp_sn_size sn_size __maybe_unused,
330 			   unsigned char era_2_sw_hfn_ovrd __maybe_unused)
331 {
332 	LABEL(local_offset);
333 	REFERENCE(move_cmd_read_descbuf);
334 	REFERENCE(move_cmd_write_descbuf);
335 
336 	if (rta_sec_era > RTA_SEC_ERA_2) {
337 		MATHB(p, SEQINSZ, ADD, ZERO, VSEQINSZ, 4, 0);
338 		if (dir == OP_TYPE_ENCAP_PROTOCOL)
339 			MATHB(p, SEQINSZ, ADD, PDCP_MAC_I_LEN, VSEQOUTSZ, 4,
340 			      IMMED2);
341 		else
342 			MATHB(p, SEQINSZ, SUB, PDCP_MAC_I_LEN, VSEQOUTSZ, 4,
343 			      IMMED2);
344 	} else {
345 		MATHB(p, SEQINSZ, ADD, ONE, VSEQINSZ, 4, 0);
346 		MATHB(p, VSEQINSZ, SUB, ONE, VSEQINSZ, 4, 0);
347 
348 		if (dir == OP_TYPE_ENCAP_PROTOCOL) {
349 			MATHB(p, SEQINSZ, ADD, PDCP_MAC_I_LEN, VSEQOUTSZ, 4,
350 			      IMMED2);
351 			MATHB(p, VSEQINSZ, SUB, ONE, MATH0, 4, 0);
352 		} else {
353 			MATHB(p, VSEQINSZ, SUB, PDCP_MAC_I_LEN, VSEQINSZ, 4,
354 			      IMMED2);
355 			MATHB(p, SEQINSZ, SUB, PDCP_MAC_I_LEN, VSEQOUTSZ, 4,
356 			      IMMED2);
357 			MATHB(p, VSEQOUTSZ, SUB, ONE, MATH0, 4, 0);
358 		}
359 
360 		MATHB(p, MATH0, ADD, ONE, MATH0, 4, 0);
361 
362 		/*
363 		 * Since MOVELEN is available only starting with
364 		 * SEC ERA 3, use poor man's MOVELEN: create a MOVE
365 		 * command dynamically by writing the length from M1 by
366 		 * OR-ing the command in the M1 register and MOVE the
367 		 * result into the descriptor buffer. Care must be taken
368 		 * wrt. the location of the command because of SEC
369 		 * pipelining. The actual MOVEs are written at the end
370 		 * of the descriptor due to calculations needed on the
371 		 * offset in the descriptor for the MOVE command.
372 		 */
373 		move_cmd_read_descbuf = MOVE(p, DESCBUF, 0, MATH0, 0, 6,
374 					     IMMED);
375 		move_cmd_write_descbuf = MOVE(p, MATH0, 0, DESCBUF, 0, 8,
376 					      WAITCOMP | IMMED);
377 	}
378 	MATHB(p, VSEQINSZ, SUB, PDCP_NULL_MAX_FRAME_LEN, NONE, 4,
379 	      IMMED2);
380 	JUMP(p, PDCP_MAX_FRAME_LEN_STATUS, HALT_STATUS, ALL_FALSE, MATH_N);
381 
382 	if (rta_sec_era > RTA_SEC_ERA_2) {
383 		if (dir == OP_TYPE_ENCAP_PROTOCOL)
384 			MATHB(p, VSEQINSZ, ADD, ZERO, MATH0, 4, 0);
385 		else
386 			MATHB(p, VSEQOUTSZ, ADD, ZERO, MATH0, 4, 0);
387 	}
388 	SEQFIFOSTORE(p, MSG, 0, 0, VLF);
389 	SEQFIFOLOAD(p, MSG1, 0, VLF | LAST1 | FLUSH1);
390 
391 	if (rta_sec_era > RTA_SEC_ERA_2) {
392 		MOVE(p, AB1, 0, OFIFO, 0, MATH0, 0);
393 	} else {
394 		SET_LABEL(p, local_offset);
395 
396 		/* Shut off automatic Info FIFO entries */
397 		LOAD(p, 0, DCTRL, LDOFF_DISABLE_AUTO_NFIFO, 0, IMMED);
398 		/* Placeholder for MOVE command with length from M1 register */
399 		MOVE(p, IFIFOAB1, 0, OFIFO, 0, 0, IMMED);
400 		/* Enable automatic Info FIFO entries */
401 		LOAD(p, 0, DCTRL, LDOFF_ENABLE_AUTO_NFIFO, 0, IMMED);
402 	}
403 
404 	if (dir == OP_TYPE_ENCAP_PROTOCOL) {
405 		MATHB(p, MATH1, XOR, MATH1, MATH0, 8, 0);
406 		MOVE(p, MATH0, 0, OFIFO, 0, 4, IMMED);
407 	}
408 
409 	if (rta_sec_era < RTA_SEC_ERA_3) {
410 		PATCH_MOVE(p, move_cmd_read_descbuf, local_offset);
411 		PATCH_MOVE(p, move_cmd_write_descbuf, local_offset);
412 	}
413 
414 	return 0;
415 }
416 
417 static inline int
418 insert_copy_frame_op(struct program *p,
419 		     struct alginfo *cipherdata __maybe_unused,
420 		     unsigned int dir __maybe_unused)
421 {
422 	LABEL(local_offset);
423 	REFERENCE(move_cmd_read_descbuf);
424 	REFERENCE(move_cmd_write_descbuf);
425 
426 	if (rta_sec_era > RTA_SEC_ERA_2) {
427 		MATHB(p, SEQINSZ, ADD, ZERO, VSEQINSZ,  4, 0);
428 		MATHB(p, SEQINSZ, ADD, ZERO, VSEQOUTSZ,  4, 0);
429 	} else {
430 		MATHB(p, SEQINSZ, ADD, ONE, VSEQINSZ,  4, 0);
431 		MATHB(p, VSEQINSZ, SUB, ONE, VSEQINSZ,  4, 0);
432 		MATHB(p, SEQINSZ, ADD, ONE, VSEQOUTSZ,  4, 0);
433 		MATHB(p, VSEQOUTSZ, SUB, ONE, VSEQOUTSZ,  4, 0);
434 		MATHB(p, VSEQINSZ, SUB, ONE, MATH0,  4, 0);
435 		MATHB(p, MATH0, ADD, ONE, MATH0,  4, 0);
436 
437 		/*
438 		 * Since MOVELEN is available only starting with
439 		 * SEC ERA 3, use poor man's MOVELEN: create a MOVE
440 		 * command dynamically by writing the length from M1 by
441 		 * OR-ing the command in the M1 register and MOVE the
442 		 * result into the descriptor buffer. Care must be taken
443 		 * wrt. the location of the command because of SEC
444 		 * pipelining. The actual MOVEs are written at the end
445 		 * of the descriptor due to calculations needed on the
446 		 * offset in the descriptor for the MOVE command.
447 		 */
448 		move_cmd_read_descbuf = MOVE(p, DESCBUF, 0, MATH0, 0, 6,
449 					     IMMED);
450 		move_cmd_write_descbuf = MOVE(p, MATH0, 0, DESCBUF, 0, 8,
451 					      WAITCOMP | IMMED);
452 	}
453 	MATHB(p, SEQINSZ, SUB, PDCP_NULL_MAX_FRAME_LEN, NONE,  4,
454 	      IFB | IMMED2);
455 	JUMP(p, PDCP_MAX_FRAME_LEN_STATUS, HALT_STATUS, ALL_FALSE, MATH_N);
456 
457 	if (rta_sec_era > RTA_SEC_ERA_2)
458 		MATHB(p, VSEQINSZ, ADD, ZERO, MATH0,  4, 0);
459 
460 	SEQFIFOLOAD(p, MSG1, 0, VLF | LAST1 | FLUSH1);
461 	if (rta_sec_era > RTA_SEC_ERA_2) {
462 		MOVE(p, AB1, 0, OFIFO, 0, MATH0, 0);
463 	} else {
464 		SET_LABEL(p, local_offset);
465 
466 		/* Shut off automatic Info FIFO entries */
467 		LOAD(p, 0, DCTRL, LDOFF_DISABLE_AUTO_NFIFO, 0, IMMED);
468 
469 		/* Placeholder for MOVE command with length from M0 register */
470 		MOVE(p, IFIFOAB1, 0, OFIFO, 0, 0, IMMED);
471 
472 		/* Enable automatic Info FIFO entries */
473 		LOAD(p, 0, DCTRL, LDOFF_ENABLE_AUTO_NFIFO, 0, IMMED);
474 	}
475 
476 	SEQFIFOSTORE(p, MSG, 0, 0, VLF);
477 
478 	if (rta_sec_era < RTA_SEC_ERA_3) {
479 		PATCH_MOVE(p, move_cmd_read_descbuf, local_offset);
480 		PATCH_MOVE(p, move_cmd_write_descbuf, local_offset);
481 	}
482 	return 0;
483 }
484 
485 static inline int
486 pdcp_insert_cplane_int_only_op(struct program *p,
487 			       bool swap __maybe_unused,
488 			       struct alginfo *cipherdata __maybe_unused,
489 			       struct alginfo *authdata, unsigned int dir,
490 			       enum pdcp_sn_size sn_size,
491 			       unsigned char era_2_sw_hfn_ovrd)
492 {
493 	uint32_t offset = 0, length = 0, sn_mask = 0;
494 
495 	/* 12 bit SN is only supported for protocol offload case */
496 	if (rta_sec_era >= RTA_SEC_ERA_8 && sn_size == PDCP_SN_SIZE_12) {
497 		KEY(p, KEY2, authdata->key_enc_flags, authdata->key,
498 		    authdata->keylen, INLINE_KEY(authdata));
499 
500 		PROTOCOL(p, dir, OP_PCLID_LTE_PDCP_USER_RN,
501 			 (uint16_t)authdata->algtype);
502 		return 0;
503 	}
504 
505 	/* Non-proto is supported only for 5bit cplane and 18bit uplane */
506 	switch (sn_size) {
507 	case PDCP_SN_SIZE_5:
508 		offset = 7;
509 		length = 1;
510 		sn_mask = (swap == false) ? PDCP_C_PLANE_SN_MASK :
511 					PDCP_C_PLANE_SN_MASK_BE;
512 		break;
513 	case PDCP_SN_SIZE_18:
514 		offset = 5;
515 		length = 3;
516 		sn_mask = (swap == false) ? PDCP_U_PLANE_18BIT_SN_MASK :
517 					PDCP_U_PLANE_18BIT_SN_MASK_BE;
518 		break;
519 	case PDCP_SN_SIZE_7:
520 	case PDCP_SN_SIZE_12:
521 	case PDCP_SN_SIZE_15:
522 		pr_err("Invalid sn_size for %s\n", __func__);
523 		return -ENOTSUP;
524 
525 	}
526 	LABEL(local_offset);
527 	REFERENCE(move_cmd_read_descbuf);
528 	REFERENCE(move_cmd_write_descbuf);
529 
530 	switch (authdata->algtype) {
531 	case PDCP_AUTH_TYPE_SNOW:
532 		/* Insert Auth Key */
533 		KEY(p, KEY2, authdata->key_enc_flags, authdata->key,
534 		    authdata->keylen, INLINE_KEY(authdata));
535 		SEQLOAD(p, MATH0, offset, length, 0);
536 		JUMP(p, 1, LOCAL_JUMP, ALL_TRUE, CALM);
537 
538 		if (rta_sec_era > RTA_SEC_ERA_2 ||
539 		    (rta_sec_era == RTA_SEC_ERA_2 &&
540 				   era_2_sw_hfn_ovrd == 0)) {
541 			SEQINPTR(p, 0, length, RTO);
542 		} else {
543 			SEQINPTR(p, 0, 5, RTO);
544 			SEQFIFOLOAD(p, SKIP, 4, 0);
545 		}
546 
547 		if (swap == false) {
548 			MATHB(p, MATH0, AND, sn_mask, MATH1,  8,
549 			      IFB | IMMED2);
550 			MATHB(p, MATH1, SHLD, MATH1, MATH1,  8, 0);
551 
552 			MOVEB(p, DESCBUF, 8, MATH2, 0, 8, WAITCOMP | IMMED);
553 
554 			MATHB(p, MATH2, AND, PDCP_BEARER_MASK, MATH2, 8,
555 			      IMMED2);
556 			MOVEB(p, DESCBUF, 0x0C, MATH3, 0, 4, WAITCOMP | IMMED);
557 			MATHB(p, MATH3, AND, PDCP_DIR_MASK, MATH3, 8, IMMED2);
558 			MATHB(p, MATH1, OR, MATH2, MATH2, 8, 0);
559 			MOVEB(p, MATH2, 0, CONTEXT2, 0, 0x0C, WAITCOMP | IMMED);
560 		} else {
561 			MATHB(p, MATH0, AND, sn_mask, MATH1,  8,
562 			      IFB | IMMED2);
563 			MATHB(p, MATH1, SHLD, MATH1, MATH1,  8, 0);
564 
565 			MOVE(p, DESCBUF, 8, MATH2, 0, 8, WAITCOMP | IMMED);
566 			MATHB(p, MATH2, AND, PDCP_BEARER_MASK_BE, MATH2, 8,
567 			      IMMED2);
568 
569 			MOVE(p, DESCBUF, 0x0C, MATH3, 0, 4, WAITCOMP | IMMED);
570 			MATHB(p, MATH3, AND, PDCP_DIR_MASK_BE, MATH3, 8,
571 			      IMMED2);
572 			MATHB(p, MATH1, OR, MATH2, MATH2, 8, 0);
573 			MOVE(p, MATH2, 0, CONTEXT2, 0, 0x0C, WAITCOMP | IMMED);
574 		}
575 
576 		if (dir == OP_TYPE_DECAP_PROTOCOL) {
577 			MATHB(p, SEQINSZ, SUB, PDCP_MAC_I_LEN, MATH1, 4,
578 			      IMMED2);
579 		} else {
580 			if (rta_sec_era > RTA_SEC_ERA_2) {
581 				MATHB(p, SEQINSZ, SUB, ZERO, MATH1, 4,
582 				      0);
583 			} else {
584 				MATHB(p, SEQINSZ, ADD, ONE, MATH1, 4,
585 				      0);
586 				MATHB(p, MATH1, SUB, ONE, MATH1, 4,
587 				      0);
588 			}
589 		}
590 
591 		if (rta_sec_era > RTA_SEC_ERA_2) {
592 			MATHB(p, MATH1, SUB, ZERO, VSEQINSZ, 4, 0);
593 			MATHB(p, MATH1, SUB, ZERO, VSEQOUTSZ, 4, 0);
594 		} else {
595 			MATHB(p, ZERO, ADD, MATH1, VSEQINSZ, 4, 0);
596 			MATHB(p, ZERO, ADD, MATH1, VSEQOUTSZ, 4, 0);
597 
598 			/*
599 			 * Since MOVELEN is available only starting with
600 			 * SEC ERA 3, use poor man's MOVELEN: create a MOVE
601 			 * command dynamically by writing the length from M1 by
602 			 * OR-ing the command in the M1 register and MOVE the
603 			 * result into the descriptor buffer. Care must be taken
604 			 * wrt. the location of the command because of SEC
605 			 * pipelining. The actual MOVEs are written at the end
606 			 * of the descriptor due to calculations needed on the
607 			 * offset in the descriptor for the MOVE command.
608 			 */
609 			move_cmd_read_descbuf = MOVE(p, DESCBUF, 0, MATH1, 0, 6,
610 						     IMMED);
611 			move_cmd_write_descbuf = MOVE(p, MATH1, 0, DESCBUF, 0,
612 						      8, WAITCOMP | IMMED);
613 		}
614 
615 		SEQFIFOSTORE(p, MSG, 0, 0, VLF);
616 		ALG_OPERATION(p, OP_ALG_ALGSEL_SNOW_F9, OP_ALG_AAI_F9,
617 			      OP_ALG_AS_INITFINAL,
618 			      dir == OP_TYPE_ENCAP_PROTOCOL ?
619 				     ICV_CHECK_DISABLE : ICV_CHECK_ENABLE,
620 			      DIR_ENC);
621 
622 		if (rta_sec_era > RTA_SEC_ERA_2) {
623 			SEQFIFOLOAD(p, MSGINSNOOP, 0,
624 				    VLF | LAST1 | LAST2 | FLUSH1);
625 			MOVE(p, AB1, 0, OFIFO, 0, MATH1, 0);
626 		} else {
627 			SEQFIFOLOAD(p, MSGINSNOOP, 0,
628 				    VLF | LAST1 | LAST2 | FLUSH1);
629 			SET_LABEL(p, local_offset);
630 
631 			/* Shut off automatic Info FIFO entries */
632 			LOAD(p, 0, DCTRL, LDOFF_DISABLE_AUTO_NFIFO, 0, IMMED);
633 			/*
634 			 * Placeholder for MOVE command with length from M1
635 			 * register
636 			 */
637 			MOVE(p, IFIFOAB1, 0, OFIFO, 0, 0, IMMED);
638 			/* Enable automatic Info FIFO entries */
639 			LOAD(p, 0, DCTRL, LDOFF_ENABLE_AUTO_NFIFO, 0, IMMED);
640 		}
641 
642 		if (dir == OP_TYPE_DECAP_PROTOCOL)
643 			SEQFIFOLOAD(p, ICV2, 4, LAST2);
644 		else
645 			SEQSTORE(p, CONTEXT2, 0, 4, 0);
646 
647 		break;
648 
649 	case PDCP_AUTH_TYPE_AES:
650 		/* Insert Auth Key */
651 		KEY(p, KEY1, authdata->key_enc_flags, authdata->key,
652 		    authdata->keylen, INLINE_KEY(authdata));
653 		SEQLOAD(p, MATH0, offset, length, 0);
654 		JUMP(p, 1, LOCAL_JUMP, ALL_TRUE, CALM);
655 		if (rta_sec_era > RTA_SEC_ERA_2 ||
656 		    (rta_sec_era == RTA_SEC_ERA_2 &&
657 		     era_2_sw_hfn_ovrd == 0)) {
658 			SEQINPTR(p, 0, length, RTO);
659 		} else {
660 			SEQINPTR(p, 0, 5, RTO);
661 			SEQFIFOLOAD(p, SKIP, 4, 0);
662 		}
663 
664 		if (swap == false) {
665 			MATHB(p, MATH0, AND, sn_mask, MATH1, 8,
666 			      IFB | IMMED2);
667 			MATHB(p, MATH1, SHLD, MATH1, MATH1, 8, 0);
668 
669 			MOVEB(p, DESCBUF, 8, MATH2, 0, 8, WAITCOMP | IMMED);
670 			MATHB(p, MATH1, OR, MATH2, MATH2, 8, 0);
671 			MOVEB(p, MATH2, 0, IFIFOAB1, 0, 8, IMMED);
672 		} else {
673 			MATHB(p, MATH0, AND, sn_mask, MATH1, 8,
674 			      IFB | IMMED2);
675 			MATHB(p, MATH1, SHLD, MATH1, MATH1, 8, 0);
676 
677 			MOVE(p, DESCBUF, 8, MATH2, 0, 8, WAITCOMP | IMMED);
678 			MATHB(p, MATH1, OR, MATH2, MATH2, 8, 0);
679 			MOVE(p, MATH2, 0, IFIFOAB1, 0, 8, IMMED);
680 		}
681 
682 		if (dir == OP_TYPE_DECAP_PROTOCOL) {
683 			MATHB(p, SEQINSZ, SUB, PDCP_MAC_I_LEN, MATH1, 4,
684 			      IMMED2);
685 		} else {
686 			if (rta_sec_era > RTA_SEC_ERA_2) {
687 				MATHB(p, SEQINSZ, SUB, ZERO, MATH1, 4,
688 				      0);
689 			} else {
690 				MATHB(p, SEQINSZ, ADD, ONE, MATH1, 4,
691 				      0);
692 				MATHB(p, MATH1, SUB, ONE, MATH1, 4,
693 				      0);
694 			}
695 		}
696 
697 		if (rta_sec_era > RTA_SEC_ERA_2) {
698 			MATHB(p, MATH1, SUB, ZERO, VSEQINSZ, 4, 0);
699 			MATHB(p, MATH1, SUB, ZERO, VSEQOUTSZ, 4, 0);
700 		} else {
701 			MATHB(p, ZERO, ADD, MATH1, VSEQINSZ, 4, 0);
702 			MATHB(p, ZERO, ADD, MATH1, VSEQOUTSZ, 4, 0);
703 
704 			/*
705 			 * Since MOVELEN is available only starting with
706 			 * SEC ERA 3, use poor man's MOVELEN: create a MOVE
707 			 * command dynamically by writing the length from M1 by
708 			 * OR-ing the command in the M1 register and MOVE the
709 			 * result into the descriptor buffer. Care must be taken
710 			 * wrt. the location of the command because of SEC
711 			 * pipelining. The actual MOVEs are written at the end
712 			 * of the descriptor due to calculations needed on the
713 			 * offset in the descriptor for the MOVE command.
714 			 */
715 			move_cmd_read_descbuf = MOVE(p, DESCBUF, 0, MATH1, 0, 6,
716 						     IMMED);
717 			move_cmd_write_descbuf = MOVE(p, MATH1, 0, DESCBUF, 0,
718 						      8, WAITCOMP | IMMED);
719 		}
720 		SEQFIFOSTORE(p, MSG, 0, 0, VLF);
721 		ALG_OPERATION(p, OP_ALG_ALGSEL_AES,
722 			      OP_ALG_AAI_CMAC,
723 			      OP_ALG_AS_INITFINAL,
724 			      dir == OP_TYPE_ENCAP_PROTOCOL ?
725 				     ICV_CHECK_DISABLE : ICV_CHECK_ENABLE,
726 			      DIR_ENC);
727 
728 		if (rta_sec_era > RTA_SEC_ERA_2) {
729 			MOVE(p, AB2, 0, OFIFO, 0, MATH1, 0);
730 			SEQFIFOLOAD(p, MSGINSNOOP, 0,
731 				    VLF | LAST1 | LAST2 | FLUSH1);
732 		} else {
733 			SEQFIFOLOAD(p, MSGINSNOOP, 0,
734 				    VLF | LAST1 | LAST2 | FLUSH1);
735 			SET_LABEL(p, local_offset);
736 
737 			/* Shut off automatic Info FIFO entries */
738 			LOAD(p, 0, DCTRL, LDOFF_DISABLE_AUTO_NFIFO, 0, IMMED);
739 
740 			/*
741 			 * Placeholder for MOVE command with length from
742 			 * M1 register
743 			 */
744 			MOVE(p, IFIFOAB2, 0, OFIFO, 0, 0, IMMED);
745 
746 			/* Enable automatic Info FIFO entries */
747 			LOAD(p, 0, DCTRL, LDOFF_ENABLE_AUTO_NFIFO, 0, IMMED);
748 		}
749 
750 		if (dir == OP_TYPE_DECAP_PROTOCOL)
751 			SEQFIFOLOAD(p, ICV1, 4, LAST1 | FLUSH1);
752 		else
753 			SEQSTORE(p, CONTEXT1, 0, 4, 0);
754 
755 		break;
756 
757 	case PDCP_AUTH_TYPE_ZUC:
758 		if (rta_sec_era < RTA_SEC_ERA_5) {
759 			pr_err("Invalid era for selected algorithm\n");
760 			return -ENOTSUP;
761 		}
762 		/* Insert Auth Key */
763 		KEY(p, KEY2, authdata->key_enc_flags, authdata->key,
764 		    authdata->keylen, INLINE_KEY(authdata));
765 		SEQLOAD(p, MATH0, offset, length, 0);
766 		JUMP(p, 1, LOCAL_JUMP, ALL_TRUE, CALM);
767 		SEQINPTR(p, 0, length, RTO);
768 		if (swap == false) {
769 			MATHB(p, MATH0, AND, sn_mask, MATH1, 8,
770 			      IFB | IMMED2);
771 			MATHB(p, MATH1, SHLD, MATH1, MATH1, 8, 0);
772 
773 			MOVEB(p, DESCBUF, 8, MATH2, 0, 8, WAITCOMP | IMMED);
774 			MATHB(p, MATH1, OR, MATH2, MATH2, 8, 0);
775 			MOVEB(p, MATH2, 0, CONTEXT2, 0, 8, IMMED);
776 
777 		} else {
778 			MATHB(p, MATH0, AND, sn_mask, MATH1, 8,
779 			      IFB | IMMED2);
780 			MATHB(p, MATH1, SHLD, MATH1, MATH1, 8, 0);
781 
782 			MOVE(p, DESCBUF, 8, MATH2, 0, 8, WAITCOMP | IMMED);
783 			MATHB(p, MATH1, OR, MATH2, MATH2, 8, 0);
784 			MOVE(p, MATH2, 0, CONTEXT2, 0, 8, IMMED);
785 		}
786 		if (dir == OP_TYPE_DECAP_PROTOCOL)
787 			MATHB(p, SEQINSZ, SUB, PDCP_MAC_I_LEN, MATH1, 4,
788 			      IMMED2);
789 		else
790 			MATHB(p, SEQINSZ, SUB, ZERO, MATH1, 4, 0);
791 
792 		MATHB(p, MATH1, SUB, ZERO, VSEQINSZ, 4, 0);
793 		MATHB(p, MATH1, SUB, ZERO, VSEQOUTSZ, 4, 0);
794 		SEQFIFOSTORE(p, MSG, 0, 0, VLF);
795 		ALG_OPERATION(p, OP_ALG_ALGSEL_ZUCA,
796 			      OP_ALG_AAI_F9,
797 			      OP_ALG_AS_INITFINAL,
798 			      dir == OP_TYPE_ENCAP_PROTOCOL ?
799 				     ICV_CHECK_DISABLE : ICV_CHECK_ENABLE,
800 			      DIR_ENC);
801 		SEQFIFOLOAD(p, MSGINSNOOP, 0, VLF | LAST1 | LAST2 | FLUSH1);
802 		MOVE(p, AB1, 0, OFIFO, 0, MATH1, 0);
803 
804 		if (dir == OP_TYPE_DECAP_PROTOCOL)
805 			SEQFIFOLOAD(p, ICV2, 4, LAST2);
806 		else
807 			SEQSTORE(p, CONTEXT2, 0, 4, 0);
808 
809 		break;
810 
811 	default:
812 		pr_err("%s: Invalid integrity algorithm selected: %d\n",
813 		       "pdcp_insert_cplane_int_only_op", authdata->algtype);
814 		return -EINVAL;
815 	}
816 
817 	if (rta_sec_era < RTA_SEC_ERA_3) {
818 		PATCH_MOVE(p, move_cmd_read_descbuf, local_offset);
819 		PATCH_MOVE(p, move_cmd_write_descbuf, local_offset);
820 	}
821 
822 	return 0;
823 }
824 
825 static inline int
826 pdcp_insert_cplane_enc_only_op(struct program *p,
827 			       bool swap __maybe_unused,
828 			       struct alginfo *cipherdata,
829 			       struct alginfo *authdata __maybe_unused,
830 			       unsigned int dir,
831 			       enum pdcp_sn_size sn_size,
832 			       unsigned char era_2_sw_hfn_ovrd __maybe_unused)
833 {
834 	uint32_t offset = 0, length = 0, sn_mask = 0;
835 	/* Insert Cipher Key */
836 	KEY(p, KEY1, cipherdata->key_enc_flags, cipherdata->key,
837 	    cipherdata->keylen, INLINE_KEY(cipherdata));
838 
839 	if ((rta_sec_era >= RTA_SEC_ERA_8 && sn_size != PDCP_SN_SIZE_18 &&
840 			!(rta_sec_era == RTA_SEC_ERA_8 &&
841 				authdata->algtype == 0))
842 			|| (rta_sec_era == RTA_SEC_ERA_10)) {
843 		if (sn_size == PDCP_SN_SIZE_5)
844 			PROTOCOL(p, dir, OP_PCLID_LTE_PDCP_CTRL_MIXED,
845 				 (uint16_t)cipherdata->algtype << 8);
846 		else
847 			PROTOCOL(p, dir, OP_PCLID_LTE_PDCP_USER_RN,
848 				 (uint16_t)cipherdata->algtype << 8);
849 		return 0;
850 	}
851 	/* Non-proto is supported only for 5bit cplane and 18bit uplane */
852 	switch (sn_size) {
853 	case PDCP_SN_SIZE_5:
854 		offset = 7;
855 		length = 1;
856 		sn_mask = (swap == false) ? PDCP_C_PLANE_SN_MASK :
857 					PDCP_C_PLANE_SN_MASK_BE;
858 		break;
859 	case PDCP_SN_SIZE_18:
860 		offset = 5;
861 		length = 3;
862 		sn_mask = (swap == false) ? PDCP_U_PLANE_18BIT_SN_MASK :
863 					PDCP_U_PLANE_18BIT_SN_MASK_BE;
864 		break;
865 	case PDCP_SN_SIZE_12:
866 		offset = 6;
867 		length = 2;
868 		sn_mask = (swap == false) ? PDCP_12BIT_SN_MASK :
869 					PDCP_12BIT_SN_MASK_BE;
870 		break;
871 	case PDCP_SN_SIZE_7:
872 	case PDCP_SN_SIZE_15:
873 		pr_err("Invalid sn_size for %s\n", __func__);
874 		return -ENOTSUP;
875 	}
876 
877 	SEQLOAD(p, MATH0, offset, length, 0);
878 	JUMP(p, 1, LOCAL_JUMP, ALL_TRUE, CALM);
879 	MATHB(p, MATH0, AND, sn_mask, MATH1, 8, IFB | IMMED2);
880 	SEQSTORE(p, MATH0, offset, length, 0);
881 	MATHB(p, MATH1, SHLD, MATH1, MATH1, 8, 0);
882 	MOVEB(p, DESCBUF, 8, MATH2, 0, 8, WAITCOMP | IMMED);
883 	MATHB(p, MATH1, OR, MATH2, MATH2, 8, 0);
884 
885 	switch (cipherdata->algtype) {
886 	case PDCP_CIPHER_TYPE_SNOW:
887 		MOVEB(p, MATH2, 0, CONTEXT1, 0, 8, WAITCOMP | IMMED);
888 
889 		if (rta_sec_era > RTA_SEC_ERA_2) {
890 			MATHB(p, SEQINSZ, SUB, ZERO, VSEQINSZ, 4, 0);
891 		} else {
892 			MATHB(p, SEQINSZ, SUB, ONE, MATH1, 4, 0);
893 			MATHB(p, MATH1, ADD, ONE, VSEQINSZ, 4, 0);
894 		}
895 
896 		if (dir == OP_TYPE_ENCAP_PROTOCOL)
897 			MATHB(p, SEQINSZ, ADD, PDCP_MAC_I_LEN, VSEQOUTSZ, 4,
898 			      IMMED2);
899 		else
900 			MATHB(p, SEQINSZ, SUB, PDCP_MAC_I_LEN, VSEQOUTSZ, 4,
901 			      IMMED2);
902 		SEQFIFOSTORE(p, MSG, 0, 0, VLF | CONT);
903 		ALG_OPERATION(p, OP_ALG_ALGSEL_SNOW_F8,
904 			      OP_ALG_AAI_F8,
905 			      OP_ALG_AS_INITFINAL, ICV_CHECK_DISABLE,
906 			      dir == OP_TYPE_ENCAP_PROTOCOL ?
907 					DIR_ENC : DIR_DEC);
908 		break;
909 
910 	case PDCP_CIPHER_TYPE_AES:
911 		MOVEB(p, MATH2, 0, CONTEXT1, 0x10, 0x10, WAITCOMP | IMMED);
912 
913 		if (rta_sec_era > RTA_SEC_ERA_2) {
914 			MATHB(p, SEQINSZ, SUB, ZERO, VSEQINSZ, 4, 0);
915 		} else {
916 			MATHB(p, SEQINSZ, SUB, ONE, MATH1, 4, 0);
917 			MATHB(p, MATH1, ADD, ONE, VSEQINSZ, 4, 0);
918 		}
919 
920 		if (dir == OP_TYPE_ENCAP_PROTOCOL)
921 			MATHB(p, SEQINSZ, ADD, PDCP_MAC_I_LEN, VSEQOUTSZ, 4,
922 			      IMMED2);
923 		else
924 			MATHB(p, SEQINSZ, SUB, PDCP_MAC_I_LEN, VSEQOUTSZ, 4,
925 			      IMMED2);
926 
927 		SEQFIFOSTORE(p, MSG, 0, 0, VLF | CONT);
928 		ALG_OPERATION(p, OP_ALG_ALGSEL_AES,
929 			      OP_ALG_AAI_CTR,
930 			      OP_ALG_AS_INITFINAL,
931 			      ICV_CHECK_DISABLE,
932 			      dir == OP_TYPE_ENCAP_PROTOCOL ?
933 					DIR_ENC : DIR_DEC);
934 		break;
935 
936 	case PDCP_CIPHER_TYPE_ZUC:
937 		if (rta_sec_era < RTA_SEC_ERA_5) {
938 			pr_err("Invalid era for selected algorithm\n");
939 			return -ENOTSUP;
940 		}
941 
942 		MOVEB(p, MATH2, 0, CONTEXT1, 0, 0x08, IMMED);
943 		MOVEB(p, MATH2, 0, CONTEXT1, 0x08, 0x08, WAITCOMP | IMMED);
944 		MATHB(p, SEQINSZ, SUB, ZERO, VSEQINSZ, 4, 0);
945 		if (dir == OP_TYPE_ENCAP_PROTOCOL)
946 			MATHB(p, SEQINSZ, ADD, PDCP_MAC_I_LEN, VSEQOUTSZ, 4,
947 			      IMMED2);
948 		else
949 			MATHB(p, SEQINSZ, SUB, PDCP_MAC_I_LEN, VSEQOUTSZ, 4,
950 			      IMMED2);
951 
952 		SEQFIFOSTORE(p, MSG, 0, 0, VLF | CONT);
953 		ALG_OPERATION(p, OP_ALG_ALGSEL_ZUCE,
954 			      OP_ALG_AAI_F8,
955 			      OP_ALG_AS_INITFINAL,
956 			      ICV_CHECK_DISABLE,
957 			      dir == OP_TYPE_ENCAP_PROTOCOL ?
958 					DIR_ENC : DIR_DEC);
959 		break;
960 
961 	default:
962 		pr_err("%s: Invalid encrypt algorithm selected: %d\n",
963 		       "pdcp_insert_cplane_enc_only_op", cipherdata->algtype);
964 		return -EINVAL;
965 	}
966 
967 	if (dir == OP_TYPE_ENCAP_PROTOCOL) {
968 		SEQFIFOLOAD(p, MSG1, 0, VLF);
969 		FIFOLOAD(p, MSG1, PDCP_NULL_INT_MAC_I_VAL, 4,
970 			 LAST1 | FLUSH1 | IMMED);
971 	} else {
972 		SEQFIFOLOAD(p, MSG1, 0, VLF | LAST1 | FLUSH1);
973 		MOVE(p, OFIFO, 0, MATH1, 4, PDCP_MAC_I_LEN, WAITCOMP | IMMED);
974 		MATHB(p, MATH1, XOR, PDCP_NULL_INT_MAC_I_VAL, NONE, 4, IMMED2);
975 		JUMP(p, PDCP_NULL_INT_ICV_CHECK_FAILED_STATUS,
976 		     HALT_STATUS, ALL_FALSE, MATH_Z);
977 	}
978 
979 	return 0;
980 }
981 
982 static inline int
983 pdcp_insert_uplane_snow_snow_op(struct program *p,
984 			      bool swap __maybe_unused,
985 			      struct alginfo *cipherdata,
986 			      struct alginfo *authdata,
987 			      unsigned int dir,
988 			      enum pdcp_sn_size sn_size,
989 			      unsigned char era_2_sw_hfn_ovrd __maybe_unused)
990 {
991 	uint32_t offset = 0, length = 0, sn_mask = 0;
992 
993 	KEY(p, KEY1, cipherdata->key_enc_flags, cipherdata->key,
994 	    cipherdata->keylen, INLINE_KEY(cipherdata));
995 	KEY(p, KEY2, authdata->key_enc_flags, authdata->key, authdata->keylen,
996 	    INLINE_KEY(authdata));
997 
998 	if (rta_sec_era >= RTA_SEC_ERA_8 && sn_size != PDCP_SN_SIZE_18) {
999 		int pclid;
1000 
1001 		if (sn_size == PDCP_SN_SIZE_5)
1002 			pclid = OP_PCLID_LTE_PDCP_CTRL_MIXED;
1003 		else
1004 			pclid = OP_PCLID_LTE_PDCP_USER_RN;
1005 
1006 		PROTOCOL(p, dir, pclid,
1007 			 ((uint16_t)cipherdata->algtype << 8) |
1008 			 (uint16_t)authdata->algtype);
1009 
1010 		return 0;
1011 	}
1012 	/* Non-proto is supported only for 5bit cplane and 18bit uplane */
1013 	switch (sn_size) {
1014 	case PDCP_SN_SIZE_5:
1015 		offset = 7;
1016 		length = 1;
1017 		sn_mask = (swap == false) ? PDCP_C_PLANE_SN_MASK :
1018 					PDCP_C_PLANE_SN_MASK_BE;
1019 		break;
1020 	case PDCP_SN_SIZE_18:
1021 		offset = 5;
1022 		length = 3;
1023 		sn_mask = (swap == false) ? PDCP_U_PLANE_18BIT_SN_MASK :
1024 					PDCP_U_PLANE_18BIT_SN_MASK_BE;
1025 		break;
1026 	case PDCP_SN_SIZE_7:
1027 	case PDCP_SN_SIZE_12:
1028 	case PDCP_SN_SIZE_15:
1029 		pr_err("Invalid sn_size for %s\n", __func__);
1030 		return -ENOTSUP;
1031 	}
1032 
1033 	if (dir == OP_TYPE_ENCAP_PROTOCOL)
1034 		MATHB(p, SEQINSZ, SUB, length, VSEQINSZ, 4, IMMED2);
1035 
1036 	SEQLOAD(p, MATH0, offset, length, 0);
1037 	JUMP(p, 1, LOCAL_JUMP, ALL_TRUE, CALM);
1038 	MOVEB(p, MATH0, offset, IFIFOAB2, 0, length, IMMED);
1039 	MATHB(p, MATH0, AND, sn_mask, MATH1, 8, IFB | IMMED2);
1040 
1041 	SEQSTORE(p, MATH0, offset, length, 0);
1042 	MATHB(p, MATH1, SHLD, MATH1, MATH1, 8, 0);
1043 	MOVEB(p, DESCBUF, 8, MATH2, 0, 8, WAITCOMP | IMMED);
1044 	MATHB(p, MATH1, OR, MATH2, MATH1, 8, 0);
1045 	MOVEB(p, MATH1, 0, CONTEXT1, 0, 8, IMMED);
1046 	MOVEB(p, MATH1, 0, CONTEXT2, 0, 4, WAITCOMP | IMMED);
1047 	if (swap == false) {
1048 		MATHB(p, MATH1, AND, upper_32_bits(PDCP_BEARER_MASK),
1049 		      MATH2, 4, IMMED2);
1050 		MATHB(p, MATH1, AND, lower_32_bits(PDCP_DIR_MASK),
1051 		      MATH3, 4, IMMED2);
1052 	} else {
1053 		MATHB(p, MATH1, AND, lower_32_bits(PDCP_BEARER_MASK_BE),
1054 		      MATH2, 4, IMMED2);
1055 		MATHB(p, MATH1, AND, upper_32_bits(PDCP_DIR_MASK_BE),
1056 		      MATH3, 4, IMMED2);
1057 	}
1058 	MATHB(p, MATH3, SHLD, MATH3, MATH3, 8, 0);
1059 
1060 	MOVEB(p, MATH2, 4, OFIFO, 0, 12, IMMED);
1061 	MOVE(p, OFIFO, 0, CONTEXT2, 4, 12, IMMED);
1062 	if (dir == OP_TYPE_ENCAP_PROTOCOL) {
1063 		MATHB(p, SEQINSZ, ADD, PDCP_MAC_I_LEN, VSEQOUTSZ, 4, IMMED2);
1064 	} else {
1065 		MATHI(p, SEQINSZ, SUB, PDCP_MAC_I_LEN, VSEQOUTSZ, 4, IMMED2);
1066 		MATHI(p, SEQINSZ, SUB, PDCP_MAC_I_LEN, VSEQINSZ, 4, IMMED2);
1067 	}
1068 
1069 	if (dir == OP_TYPE_ENCAP_PROTOCOL)
1070 		SEQFIFOSTORE(p, MSG, 0, 0, VLF);
1071 	else
1072 		SEQFIFOSTORE(p, MSG, 0, 0, VLF | CONT);
1073 
1074 	ALG_OPERATION(p, OP_ALG_ALGSEL_SNOW_F9,
1075 		      OP_ALG_AAI_F9,
1076 		      OP_ALG_AS_INITFINAL,
1077 		      dir == OP_TYPE_ENCAP_PROTOCOL ?
1078 			     ICV_CHECK_DISABLE : ICV_CHECK_ENABLE,
1079 		      DIR_DEC);
1080 	ALG_OPERATION(p, OP_ALG_ALGSEL_SNOW_F8,
1081 		      OP_ALG_AAI_F8,
1082 		      OP_ALG_AS_INITFINAL,
1083 		      ICV_CHECK_DISABLE,
1084 		      dir == OP_TYPE_ENCAP_PROTOCOL ? DIR_ENC : DIR_DEC);
1085 
1086 	if (dir == OP_TYPE_ENCAP_PROTOCOL) {
1087 		SEQFIFOLOAD(p, MSGINSNOOP, 0, VLF | LAST2);
1088 		MOVE(p, CONTEXT2, 0, IFIFOAB1, 0, 4, LAST1 | FLUSH1 | IMMED);
1089 	} else {
1090 		SEQFIFOLOAD(p, MSGOUTSNOOP, 0, VLF | LAST2);
1091 		SEQFIFOLOAD(p, MSG1, 4, LAST1 | FLUSH1);
1092 		JUMP(p, 1, LOCAL_JUMP, ALL_TRUE, CLASS1 | NOP | NIFP);
1093 
1094 		if (rta_sec_era >= RTA_SEC_ERA_6)
1095 			LOAD(p, 0, DCTRL, 0, LDLEN_RST_CHA_OFIFO_PTR, IMMED);
1096 
1097 		MOVE(p, OFIFO, 0, MATH0, 0, 4, WAITCOMP | IMMED);
1098 
1099 		NFIFOADD(p, IFIFO, ICV2, 4, LAST2);
1100 
1101 		if (rta_sec_era <= RTA_SEC_ERA_2) {
1102 			/* Shut off automatic Info FIFO entries */
1103 			LOAD(p, 0, DCTRL, LDOFF_DISABLE_AUTO_NFIFO, 0, IMMED);
1104 			MOVE(p, MATH0, 0, IFIFOAB2, 0, 4, WAITCOMP | IMMED);
1105 		} else {
1106 			MOVE(p, MATH0, 0, IFIFO, 0, 4, WAITCOMP | IMMED);
1107 		}
1108 	}
1109 
1110 	return 0;
1111 }
1112 
1113 static inline int
1114 pdcp_insert_uplane_zuc_zuc_op(struct program *p,
1115 			      bool swap __maybe_unused,
1116 			      struct alginfo *cipherdata,
1117 			      struct alginfo *authdata,
1118 			      unsigned int dir,
1119 			      enum pdcp_sn_size sn_size,
1120 			      unsigned char era_2_sw_hfn_ovrd __maybe_unused)
1121 {
1122 	uint32_t offset = 0, length = 0, sn_mask = 0;
1123 
1124 	LABEL(keyjump);
1125 	REFERENCE(pkeyjump);
1126 
1127 	if (rta_sec_era < RTA_SEC_ERA_5) {
1128 		pr_err("Invalid era for selected algorithm\n");
1129 		return -ENOTSUP;
1130 	}
1131 
1132 	pkeyjump = JUMP(p, keyjump, LOCAL_JUMP, ALL_TRUE, SHRD | SELF | BOTH);
1133 	KEY(p, KEY1, cipherdata->key_enc_flags, cipherdata->key,
1134 	    cipherdata->keylen, INLINE_KEY(cipherdata));
1135 	KEY(p, KEY2, authdata->key_enc_flags, authdata->key, authdata->keylen,
1136 	    INLINE_KEY(authdata));
1137 
1138 	SET_LABEL(p, keyjump);
1139 	PATCH_JUMP(p, pkeyjump, keyjump);
1140 
1141 	if (rta_sec_era >= RTA_SEC_ERA_8 && sn_size != PDCP_SN_SIZE_18) {
1142 		int pclid;
1143 
1144 		if (sn_size == PDCP_SN_SIZE_5)
1145 			pclid = OP_PCLID_LTE_PDCP_CTRL_MIXED;
1146 		else
1147 			pclid = OP_PCLID_LTE_PDCP_USER_RN;
1148 
1149 		PROTOCOL(p, dir, pclid,
1150 			 ((uint16_t)cipherdata->algtype << 8) |
1151 			 (uint16_t)authdata->algtype);
1152 
1153 		return 0;
1154 	}
1155 	/* Non-proto is supported only for 5bit cplane and 18bit uplane */
1156 	switch (sn_size) {
1157 	case PDCP_SN_SIZE_5:
1158 		offset = 7;
1159 		length = 1;
1160 		sn_mask = (swap == false) ? PDCP_C_PLANE_SN_MASK :
1161 					PDCP_C_PLANE_SN_MASK_BE;
1162 		break;
1163 	case PDCP_SN_SIZE_18:
1164 		offset = 5;
1165 		length = 3;
1166 		sn_mask = (swap == false) ? PDCP_U_PLANE_18BIT_SN_MASK :
1167 					PDCP_U_PLANE_18BIT_SN_MASK_BE;
1168 		break;
1169 	case PDCP_SN_SIZE_7:
1170 	case PDCP_SN_SIZE_12:
1171 	case PDCP_SN_SIZE_15:
1172 		pr_err("Invalid sn_size for %s\n", __func__);
1173 		return -ENOTSUP;
1174 	}
1175 
1176 	SEQLOAD(p, MATH0, offset, length, 0);
1177 	JUMP(p, 1, LOCAL_JUMP, ALL_TRUE, CALM);
1178 	MOVEB(p, MATH0, offset, IFIFOAB2, 0, length, IMMED);
1179 	MATHB(p, MATH0, AND, sn_mask, MATH1, 8, IFB | IMMED2);
1180 	MATHB(p, MATH1, SHLD, MATH1, MATH1, 8, 0);
1181 
1182 	MOVEB(p, DESCBUF, 8, MATH2, 0, 8, WAITCOMP | IMMED);
1183 	MATHB(p, MATH1, OR, MATH2, MATH2, 8, 0);
1184 	MOVEB(p, MATH2, 0, CONTEXT1, 0, 8, IMMED);
1185 
1186 	MOVEB(p, MATH2, 0, CONTEXT2, 0, 8, WAITCOMP | IMMED);
1187 
1188 	if (dir == OP_TYPE_ENCAP_PROTOCOL)
1189 		MATHB(p, SEQINSZ, ADD, PDCP_MAC_I_LEN, VSEQOUTSZ, 4, IMMED2);
1190 	else
1191 		MATHB(p, SEQINSZ, SUB, PDCP_MAC_I_LEN, VSEQOUTSZ, 4, IMMED2);
1192 
1193 	MATHB(p, SEQINSZ, SUB, ZERO, VSEQINSZ, 4, 0);
1194 	SEQSTORE(p, MATH0, offset, length, 0);
1195 
1196 	if (dir == OP_TYPE_ENCAP_PROTOCOL) {
1197 		SEQFIFOSTORE(p, MSG, 0, 0, VLF);
1198 		SEQFIFOLOAD(p, MSGINSNOOP, 0, VLF | LAST2);
1199 	} else {
1200 		SEQFIFOSTORE(p, MSG, 0, 0, VLF | CONT);
1201 		SEQFIFOLOAD(p, MSGOUTSNOOP, 0, VLF | LAST1 | FLUSH1);
1202 	}
1203 
1204 	ALG_OPERATION(p, OP_ALG_ALGSEL_ZUCA,
1205 		      OP_ALG_AAI_F9,
1206 		      OP_ALG_AS_INITFINAL,
1207 		      dir == OP_TYPE_ENCAP_PROTOCOL ?
1208 			     ICV_CHECK_DISABLE : ICV_CHECK_ENABLE,
1209 		      DIR_ENC);
1210 
1211 	ALG_OPERATION(p, OP_ALG_ALGSEL_ZUCE,
1212 		      OP_ALG_AAI_F8,
1213 		      OP_ALG_AS_INITFINAL,
1214 		      ICV_CHECK_DISABLE,
1215 		      dir == OP_TYPE_ENCAP_PROTOCOL ? DIR_ENC : DIR_DEC);
1216 
1217 	if (dir == OP_TYPE_ENCAP_PROTOCOL) {
1218 		MOVE(p, CONTEXT2, 0, IFIFOAB1, 0, 4, LAST1 | FLUSH1 | IMMED);
1219 	} else {
1220 		/* Save ICV */
1221 		MOVEB(p, OFIFO, 0, MATH0, 0, 4, IMMED);
1222 
1223 		LOAD(p, NFIFOENTRY_STYPE_ALTSOURCE |
1224 		     NFIFOENTRY_DEST_CLASS2 |
1225 		     NFIFOENTRY_DTYPE_ICV |
1226 		     NFIFOENTRY_LC2 | 4, NFIFO_SZL, 0, 4, IMMED);
1227 		MOVEB(p, MATH0, 0, ALTSOURCE, 0, 4, WAITCOMP | IMMED);
1228 	}
1229 
1230 	/* Reset ZUCA mode and done interrupt */
1231 	LOAD(p, CLRW_CLR_C2MODE, CLRW, 0, 4, IMMED);
1232 	LOAD(p, CIRQ_ZADI, ICTRL, 0, 4, IMMED);
1233 
1234 	return 0;
1235 }
1236 
1237 static inline int
1238 pdcp_insert_uplane_aes_aes_op(struct program *p,
1239 			      bool swap __maybe_unused,
1240 			      struct alginfo *cipherdata,
1241 			      struct alginfo *authdata,
1242 			      unsigned int dir,
1243 			      enum pdcp_sn_size sn_size,
1244 			      unsigned char era_2_sw_hfn_ovrd __maybe_unused)
1245 {
1246 	uint32_t offset = 0, length = 0, sn_mask = 0;
1247 
1248 	if ((rta_sec_era >= RTA_SEC_ERA_8 && sn_size != PDCP_SN_SIZE_18)) {
1249 		/* Insert Auth Key */
1250 		KEY(p, KEY2, authdata->key_enc_flags, authdata->key,
1251 		    authdata->keylen, INLINE_KEY(authdata));
1252 
1253 		/* Insert Cipher Key */
1254 		KEY(p, KEY1, cipherdata->key_enc_flags, cipherdata->key,
1255 		    cipherdata->keylen, INLINE_KEY(cipherdata));
1256 
1257 		PROTOCOL(p, dir, OP_PCLID_LTE_PDCP_USER_RN,
1258 			 ((uint16_t)cipherdata->algtype << 8) |
1259 			  (uint16_t)authdata->algtype);
1260 		return 0;
1261 	}
1262 
1263 	/* Non-proto is supported only for 5bit cplane and 18bit uplane */
1264 	switch (sn_size) {
1265 	case PDCP_SN_SIZE_18:
1266 		offset = 5;
1267 		length = 3;
1268 		sn_mask = (swap == false) ? PDCP_U_PLANE_18BIT_SN_MASK :
1269 					PDCP_U_PLANE_18BIT_SN_MASK_BE;
1270 		break;
1271 
1272 	default:
1273 		pr_err("Invalid sn_size for %s\n", __func__);
1274 		return -ENOTSUP;
1275 	}
1276 
1277 	SEQLOAD(p, MATH0, offset, length, 0);
1278 	JUMP(p, 1, LOCAL_JUMP, ALL_TRUE, CALM);
1279 	MATHB(p, MATH0, AND, sn_mask, MATH1, 8, IFB | IMMED2);
1280 
1281 	MATHB(p, MATH1, SHLD, MATH1, MATH1, 8, 0);
1282 	MOVEB(p, DESCBUF, 8, MATH2, 0, 0x08, WAITCOMP | IMMED);
1283 	MATHB(p, MATH1, OR, MATH2, MATH2, 8, 0);
1284 	SEQSTORE(p, MATH0, offset, length, 0);
1285 
1286 	if (dir == OP_TYPE_ENCAP_PROTOCOL) {
1287 		KEY(p, KEY1, authdata->key_enc_flags, authdata->key,
1288 		    authdata->keylen, INLINE_KEY(authdata));
1289 		MOVEB(p, MATH2, 0, IFIFOAB1, 0, 0x08, IMMED);
1290 		MOVEB(p, MATH0, offset, IFIFOAB1, 0, length, IMMED);
1291 
1292 		MATHB(p, SEQINSZ, SUB, ZERO, VSEQINSZ, 4, 0);
1293 		MATHB(p, VSEQINSZ, ADD, PDCP_MAC_I_LEN, VSEQOUTSZ, 4, IMMED2);
1294 
1295 		ALG_OPERATION(p, OP_ALG_ALGSEL_AES,
1296 			      OP_ALG_AAI_CMAC,
1297 			      OP_ALG_AS_INITFINAL,
1298 			      ICV_CHECK_DISABLE,
1299 			      DIR_DEC);
1300 		SEQFIFOLOAD(p, MSG1, 0, VLF | LAST1 | FLUSH1);
1301 		MOVEB(p, CONTEXT1, 0, MATH3, 0, 4, WAITCOMP | IMMED);
1302 
1303 		LOAD(p, CLRW_RESET_CLS1_CHA |
1304 		     CLRW_CLR_C1KEY |
1305 		     CLRW_CLR_C1CTX |
1306 		     CLRW_CLR_C1ICV |
1307 		     CLRW_CLR_C1DATAS |
1308 		     CLRW_CLR_C1MODE,
1309 		     CLRW, 0, 4, IMMED);
1310 
1311 		KEY(p, KEY1, cipherdata->key_enc_flags, cipherdata->key,
1312 		    cipherdata->keylen, INLINE_KEY(cipherdata));
1313 
1314 		MOVEB(p, MATH2, 0, CONTEXT1, 16, 8, IMMED);
1315 		SEQINPTR(p, 0, PDCP_NULL_MAX_FRAME_LEN, RTO);
1316 
1317 		ALG_OPERATION(p, OP_ALG_ALGSEL_AES,
1318 			      OP_ALG_AAI_CTR,
1319 			      OP_ALG_AS_INITFINAL,
1320 			      ICV_CHECK_DISABLE,
1321 			      DIR_ENC);
1322 
1323 		SEQFIFOSTORE(p, MSG, 0, 0, VLF);
1324 
1325 		SEQFIFOLOAD(p, SKIP, length, 0);
1326 
1327 		SEQFIFOLOAD(p, MSG1, 0, VLF);
1328 		MOVEB(p, MATH3, 0, IFIFOAB1, 0, 4, LAST1 | FLUSH1 | IMMED);
1329 	} else {
1330 		MOVEB(p, MATH2, 0, CONTEXT1, 16, 8, IMMED);
1331 		MOVEB(p, MATH2, 0, CONTEXT2, 0, 8, IMMED);
1332 
1333 		MATHB(p, SEQINSZ, SUB, ZERO, VSEQINSZ, 4, 0);
1334 		MATHB(p, SEQINSZ, SUB, PDCP_MAC_I_LEN, VSEQOUTSZ, 4, IMMED2);
1335 
1336 		KEY(p, KEY1, cipherdata->key_enc_flags, cipherdata->key,
1337 		    cipherdata->keylen, INLINE_KEY(cipherdata));
1338 
1339 		ALG_OPERATION(p, OP_ALG_ALGSEL_AES,
1340 			      OP_ALG_AAI_CTR,
1341 			      OP_ALG_AS_INITFINAL,
1342 			      ICV_CHECK_DISABLE,
1343 			      DIR_DEC);
1344 
1345 		SEQFIFOSTORE(p, MSG, 0, 0, VLF | CONT);
1346 		SEQFIFOLOAD(p, MSG1, 0, VLF | LAST1 | FLUSH1);
1347 
1348 		MOVEB(p, OFIFO, 0, MATH3, 0, 4, IMMED);
1349 
1350 		LOAD(p, CLRW_RESET_CLS1_CHA |
1351 		     CLRW_CLR_C1KEY |
1352 		     CLRW_CLR_C1CTX |
1353 		     CLRW_CLR_C1ICV |
1354 		     CLRW_CLR_C1DATAS |
1355 		     CLRW_CLR_C1MODE,
1356 		     CLRW, 0, 4, IMMED);
1357 
1358 		KEY(p, KEY1, authdata->key_enc_flags, authdata->key,
1359 		    authdata->keylen, INLINE_KEY(authdata));
1360 
1361 		SEQINPTR(p, 0, 0, SOP);
1362 
1363 		ALG_OPERATION(p, OP_ALG_ALGSEL_AES,
1364 			      OP_ALG_AAI_CMAC,
1365 			      OP_ALG_AS_INITFINAL,
1366 			      ICV_CHECK_ENABLE,
1367 			      DIR_DEC);
1368 
1369 		MATHB(p, SEQINSZ, SUB, ZERO, VSEQINSZ, 4, 0);
1370 
1371 		MOVE(p, CONTEXT2, 0, IFIFOAB1, 0, 8, IMMED);
1372 
1373 		SEQFIFOLOAD(p, MSG1, 0, VLF | LAST1 | FLUSH1);
1374 
1375 		LOAD(p, NFIFOENTRY_STYPE_ALTSOURCE |
1376 		     NFIFOENTRY_DEST_CLASS1 |
1377 		     NFIFOENTRY_DTYPE_ICV |
1378 		     NFIFOENTRY_LC1 |
1379 		     NFIFOENTRY_FC1 | 4, NFIFO_SZL, 0, 4, IMMED);
1380 		MOVEB(p, MATH3, 0, ALTSOURCE, 0, 4, IMMED);
1381 	}
1382 
1383 	return 0;
1384 }
1385 
1386 static inline int
1387 pdcp_insert_cplane_acc_op(struct program *p,
1388 			  bool swap __maybe_unused,
1389 			  struct alginfo *cipherdata,
1390 			  struct alginfo *authdata,
1391 			  unsigned int dir,
1392 			  enum pdcp_sn_size sn_size,
1393 			  unsigned char era_2_hfn_ovrd __maybe_unused)
1394 {
1395 	/* Insert Auth Key */
1396 	KEY(p, KEY2, authdata->key_enc_flags, authdata->key, authdata->keylen,
1397 	    INLINE_KEY(authdata));
1398 
1399 	/* Insert Cipher Key */
1400 	KEY(p, KEY1, cipherdata->key_enc_flags, cipherdata->key,
1401 	    cipherdata->keylen, INLINE_KEY(cipherdata));
1402 
1403 	if (sn_size == PDCP_SN_SIZE_5)
1404 		PROTOCOL(p, dir, OP_PCLID_LTE_PDCP_CTRL,
1405 			 (uint16_t)cipherdata->algtype);
1406 	else
1407 		PROTOCOL(p, dir, OP_PCLID_LTE_PDCP_USER_RN,
1408 			 ((uint16_t)cipherdata->algtype << 8) |
1409 			  (uint16_t)authdata->algtype);
1410 
1411 	return 0;
1412 }
1413 
1414 static inline int
1415 pdcp_insert_cplane_snow_aes_op(struct program *p,
1416 			       bool swap __maybe_unused,
1417 			       struct alginfo *cipherdata,
1418 			       struct alginfo *authdata,
1419 			       unsigned int dir,
1420 			       enum pdcp_sn_size sn_size,
1421 			       unsigned char era_2_sw_hfn_ovrd)
1422 {
1423 	uint32_t offset = 0, length = 0, sn_mask = 0;
1424 
1425 	LABEL(back_to_sd_offset);
1426 	LABEL(end_desc);
1427 	LABEL(local_offset);
1428 	LABEL(jump_to_beginning);
1429 	LABEL(fifo_load_mac_i_offset);
1430 	REFERENCE(seqin_ptr_read);
1431 	REFERENCE(seqin_ptr_write);
1432 	REFERENCE(seq_out_read);
1433 	REFERENCE(jump_back_to_sd_cmd);
1434 	REFERENCE(move_mac_i_to_desc_buf);
1435 
1436 	if ((rta_sec_era >= RTA_SEC_ERA_8 && sn_size != PDCP_SN_SIZE_18) ||
1437 		(rta_sec_era == RTA_SEC_ERA_10)) {
1438 		KEY(p, KEY1, cipherdata->key_enc_flags, cipherdata->key,
1439 				cipherdata->keylen, INLINE_KEY(cipherdata));
1440 		KEY(p, KEY2, authdata->key_enc_flags, authdata->key,
1441 				authdata->keylen, INLINE_KEY(authdata));
1442 
1443 		if (sn_size == PDCP_SN_SIZE_5)
1444 			PROTOCOL(p, dir, OP_PCLID_LTE_PDCP_CTRL_MIXED,
1445 				 ((uint16_t)cipherdata->algtype << 8) |
1446 				 (uint16_t)authdata->algtype);
1447 		else
1448 			PROTOCOL(p, dir, OP_PCLID_LTE_PDCP_USER_RN,
1449 				 ((uint16_t)cipherdata->algtype << 8) |
1450 				 (uint16_t)authdata->algtype);
1451 
1452 		return 0;
1453 	}
1454 	/* Non-proto is supported only for 5bit cplane and 18bit uplane */
1455 	switch (sn_size) {
1456 	case PDCP_SN_SIZE_5:
1457 		offset = 7;
1458 		length = 1;
1459 		sn_mask = (swap == false) ? PDCP_C_PLANE_SN_MASK :
1460 					PDCP_C_PLANE_SN_MASK_BE;
1461 		break;
1462 	case PDCP_SN_SIZE_18:
1463 		offset = 5;
1464 		length = 3;
1465 		sn_mask = (swap == false) ? PDCP_U_PLANE_18BIT_SN_MASK :
1466 					PDCP_U_PLANE_18BIT_SN_MASK_BE;
1467 		break;
1468 	case PDCP_SN_SIZE_7:
1469 	case PDCP_SN_SIZE_12:
1470 	case PDCP_SN_SIZE_15:
1471 		pr_err("Invalid sn_size for %s\n", __func__);
1472 		return -ENOTSUP;
1473 
1474 	}
1475 
1476 	SEQLOAD(p, MATH0, offset, length, 0);
1477 	JUMP(p, 1, LOCAL_JUMP, ALL_TRUE, CALM);
1478 	MATHB(p, MATH0, AND, sn_mask, MATH1, 8, IFB | IMMED2);
1479 	MATHB(p, MATH1, SHLD, MATH1, MATH1, 8, 0);
1480 	MOVEB(p, DESCBUF, 4, MATH2, 0, 0x08, WAITCOMP | IMMED);
1481 	MATHB(p, MATH1, OR, MATH2, MATH2, 8, 0);
1482 	SEQSTORE(p, MATH0, offset, length, 0);
1483 	if (dir == OP_TYPE_ENCAP_PROTOCOL) {
1484 		if (rta_sec_era > RTA_SEC_ERA_2 ||
1485 		    (rta_sec_era == RTA_SEC_ERA_2 &&
1486 				   era_2_sw_hfn_ovrd == 0)) {
1487 			SEQINPTR(p, 0, length, RTO);
1488 		} else {
1489 			SEQINPTR(p, 0, 5, RTO);
1490 			SEQFIFOLOAD(p, SKIP, 4, 0);
1491 		}
1492 		KEY(p, KEY1, authdata->key_enc_flags, authdata->key,
1493 		    authdata->keylen, INLINE_KEY(authdata));
1494 		MOVEB(p, MATH2, 0, IFIFOAB1, 0, 0x08, IMMED);
1495 
1496 		if (rta_sec_era > RTA_SEC_ERA_2) {
1497 			MATHB(p, SEQINSZ, SUB, ZERO, VSEQINSZ, 4, 0);
1498 			MATHB(p, SEQINSZ, SUB, ZERO, MATH1, 4, 0);
1499 			MATHB(p, VSEQINSZ, ADD, PDCP_MAC_I_LEN - 1, VSEQOUTSZ,
1500 			      4, IMMED2);
1501 		} else {
1502 			MATHB(p, SEQINSZ, SUB, MATH3, VSEQINSZ, 4, 0);
1503 			MATHB(p, VSEQINSZ, ADD, PDCP_MAC_I_LEN - 1, VSEQOUTSZ,
1504 			      4, IMMED2);
1505 			/*
1506 			 * Note: Although the calculations below might seem a
1507 			 * little off, the logic is the following:
1508 			 *
1509 			 * - SEQ IN PTR RTO below needs the full length of the
1510 			 *   frame; in case of P4080_REV_2_HFN_OV_WORKAROUND,
1511 			 *   this means the length of the frame to be processed
1512 			 *   + 4 bytes (the HFN override flag and value).
1513 			 *   The length of the frame to be processed minus 1
1514 			 *   byte is in the VSIL register (because
1515 			 *   VSIL = SIL + 3, due to 1 byte, the header being
1516 			 *   already written by the SEQ STORE above). So for
1517 			 *   calculating the length to use in RTO, I add one
1518 			 *   to the VSIL value in order to obtain the total
1519 			 *   frame length. This helps in case of P4080 which
1520 			 *   can have the value 0 as an operand in a MATH
1521 			 *   command only as SRC1 When the HFN override
1522 			 *   workaround is not enabled, the length of the
1523 			 *   frame is given by the SIL register; the
1524 			 *   calculation is similar to the one in the SEC 4.2
1525 			 *   and SEC 5.3 cases.
1526 			 */
1527 			if (era_2_sw_hfn_ovrd)
1528 				MATHB(p, VSEQOUTSZ, ADD, ONE, MATH1, 4,
1529 				      0);
1530 			else
1531 				MATHB(p, SEQINSZ, ADD, MATH3, MATH1, 4,
1532 				      0);
1533 		}
1534 		/*
1535 		 * Placeholder for filling the length in
1536 		 * SEQIN PTR RTO below
1537 		 */
1538 		seqin_ptr_read = MOVE(p, DESCBUF, 0, MATH1, 0, 6, IMMED);
1539 		seqin_ptr_write = MOVE(p, MATH1, 0, DESCBUF, 0, 8,
1540 				       WAITCOMP | IMMED);
1541 		ALG_OPERATION(p, OP_ALG_ALGSEL_AES,
1542 			      OP_ALG_AAI_CMAC,
1543 			      OP_ALG_AS_INITFINAL,
1544 			      ICV_CHECK_DISABLE,
1545 			      DIR_DEC);
1546 		SEQFIFOLOAD(p, MSG1, 0, VLF | LAST1 | FLUSH1);
1547 		MOVEB(p, CONTEXT1, 0, MATH3, 0, 4, WAITCOMP | IMMED);
1548 		if (rta_sec_era <= RTA_SEC_ERA_3)
1549 			LOAD(p, CLRW_CLR_C1KEY |
1550 			     CLRW_CLR_C1CTX |
1551 			     CLRW_CLR_C1ICV |
1552 			     CLRW_CLR_C1DATAS |
1553 			     CLRW_CLR_C1MODE,
1554 			     CLRW, 0, 4, IMMED);
1555 		else
1556 			LOAD(p, CLRW_RESET_CLS1_CHA |
1557 			     CLRW_CLR_C1KEY |
1558 			     CLRW_CLR_C1CTX |
1559 			     CLRW_CLR_C1ICV |
1560 			     CLRW_CLR_C1DATAS |
1561 			     CLRW_CLR_C1MODE,
1562 			     CLRW, 0, 4, IMMED);
1563 
1564 		if (rta_sec_era <= RTA_SEC_ERA_3)
1565 			LOAD(p, CCTRL_RESET_CHA_ALL, CCTRL, 0, 4, IMMED);
1566 
1567 		KEY(p, KEY1, cipherdata->key_enc_flags, cipherdata->key,
1568 		    cipherdata->keylen, INLINE_KEY(cipherdata));
1569 		SET_LABEL(p, local_offset);
1570 		MOVEB(p, MATH2, 0, CONTEXT1, 0, 8, IMMED);
1571 		SEQINPTR(p, 0, 0, RTO);
1572 
1573 		if (rta_sec_era == RTA_SEC_ERA_2 && era_2_sw_hfn_ovrd) {
1574 			SEQFIFOLOAD(p, SKIP, 5, 0);
1575 			MATHB(p, SEQINSZ, ADD, ONE, SEQINSZ, 4, 0);
1576 		}
1577 
1578 		MATHB(p, SEQINSZ, SUB, length, VSEQINSZ, 4, IMMED2);
1579 		ALG_OPERATION(p, OP_ALG_ALGSEL_SNOW_F8,
1580 			      OP_ALG_AAI_F8,
1581 			      OP_ALG_AS_INITFINAL,
1582 			      ICV_CHECK_DISABLE,
1583 			      DIR_ENC);
1584 		SEQFIFOSTORE(p, MSG, 0, 0, VLF);
1585 
1586 		if (rta_sec_era > RTA_SEC_ERA_2 ||
1587 		    (rta_sec_era == RTA_SEC_ERA_2 &&
1588 				   era_2_sw_hfn_ovrd == 0))
1589 			SEQFIFOLOAD(p, SKIP, length, 0);
1590 
1591 		SEQFIFOLOAD(p, MSG1, 0, VLF);
1592 		MOVEB(p, MATH3, 0, IFIFOAB1, 0, 4, LAST1 | FLUSH1 | IMMED);
1593 		PATCH_MOVE(p, seqin_ptr_read, local_offset);
1594 		PATCH_MOVE(p, seqin_ptr_write, local_offset);
1595 	} else {
1596 		MOVEB(p, MATH2, 0, CONTEXT1, 0, 8, IMMED);
1597 
1598 		if (rta_sec_era >= RTA_SEC_ERA_5)
1599 			MOVE(p, CONTEXT1, 0, CONTEXT2, 0, 8, IMMED);
1600 
1601 		if (rta_sec_era > RTA_SEC_ERA_2)
1602 			MATHB(p, SEQINSZ, SUB, ZERO, VSEQINSZ, 4, 0);
1603 		else
1604 			MATHB(p, SEQINSZ, SUB, MATH3, VSEQINSZ, 4, 0);
1605 
1606 		MATHI(p, SEQINSZ, SUB, PDCP_MAC_I_LEN, VSEQOUTSZ, 4, IMMED2);
1607 /*
1608  * TODO: To be changed when proper support is added in RTA (can't load a
1609  * command that is also written by RTA (or patch it for that matter).
1610  * Change when proper RTA support is added.
1611  */
1612 		if (p->ps)
1613 			WORD(p, 0x168B0004);
1614 		else
1615 			WORD(p, 0x16880404);
1616 
1617 		jump_back_to_sd_cmd = JUMP(p, 0, LOCAL_JUMP, ALL_TRUE, 0);
1618 		/*
1619 		 * Placeholder for command reading  the SEQ OUT command in
1620 		 * JD. Done for rereading the decrypted data and performing
1621 		 * the integrity check
1622 		 */
1623 /*
1624  * TODO: RTA currently doesn't support patching of length of a MOVE command
1625  * Thus, it is inserted as a raw word, as per PS setting.
1626  */
1627 		if (p->ps)
1628 			seq_out_read = MOVE(p, DESCBUF, 0, MATH1, 0, 20,
1629 					    WAITCOMP | IMMED);
1630 		else
1631 			seq_out_read = MOVE(p, DESCBUF, 0, MATH1, 0, 16,
1632 					    WAITCOMP | IMMED);
1633 
1634 		MATHB(p, MATH1, XOR, CMD_SEQ_IN_PTR ^ CMD_SEQ_OUT_PTR, MATH1, 4,
1635 		      IMMED2);
1636 		/* Placeholder for overwriting the SEQ IN  with SEQ OUT */
1637 /*
1638  * TODO: RTA currently doesn't support patching of length of a MOVE command
1639  * Thus, it is inserted as a raw word, as per PS setting.
1640  */
1641 		if (p->ps)
1642 			MOVE(p, MATH1, 0, DESCBUF, 0, 24, IMMED);
1643 		else
1644 			MOVE(p, MATH1, 0, DESCBUF, 0, 20, IMMED);
1645 
1646 		KEY(p, KEY1, cipherdata->key_enc_flags, cipherdata->key,
1647 		    cipherdata->keylen, INLINE_KEY(cipherdata));
1648 
1649 		if (rta_sec_era >= RTA_SEC_ERA_4)
1650 			MOVE(p, CONTEXT1, 0, CONTEXT2, 0, 8, IMMED);
1651 		else
1652 			MOVE(p, CONTEXT1, 0, MATH3, 0, 8, IMMED);
1653 
1654 		ALG_OPERATION(p, OP_ALG_ALGSEL_SNOW_F8,
1655 			      OP_ALG_AAI_F8,
1656 			      OP_ALG_AS_INITFINAL,
1657 			      ICV_CHECK_DISABLE,
1658 			      DIR_DEC);
1659 		SEQFIFOSTORE(p, MSG, 0, 0, VLF | CONT);
1660 		SEQFIFOLOAD(p, MSG1, 0, VLF | LAST1 | FLUSH1);
1661 
1662 		if (rta_sec_era <= RTA_SEC_ERA_3)
1663 			move_mac_i_to_desc_buf = MOVE(p, OFIFO, 0, DESCBUF, 0,
1664 						      4, WAITCOMP | IMMED);
1665 		else
1666 			MOVE(p, OFIFO, 0, MATH3, 0, 4, IMMED);
1667 
1668 		if (rta_sec_era <= RTA_SEC_ERA_3)
1669 			LOAD(p, CCTRL_RESET_CHA_ALL, CCTRL, 0, 4, IMMED);
1670 		else
1671 			LOAD(p, CLRW_RESET_CLS1_CHA |
1672 			     CLRW_CLR_C1KEY |
1673 			     CLRW_CLR_C1CTX |
1674 			     CLRW_CLR_C1ICV |
1675 			     CLRW_CLR_C1DATAS |
1676 			     CLRW_CLR_C1MODE,
1677 			     CLRW, 0, 4, IMMED);
1678 
1679 		KEY(p, KEY1, authdata->key_enc_flags, authdata->key,
1680 		    authdata->keylen, INLINE_KEY(authdata));
1681 		/*
1682 		 * Placeholder for jump in SD for executing the new SEQ IN PTR
1683 		 * command (which is actually the old SEQ OUT PTR command
1684 		 * copied over from JD.
1685 		 */
1686 		SET_LABEL(p, jump_to_beginning);
1687 		JUMP(p, 1 - jump_to_beginning, LOCAL_JUMP, ALL_TRUE, 0);
1688 		SET_LABEL(p, back_to_sd_offset);
1689 		ALG_OPERATION(p, OP_ALG_ALGSEL_AES,
1690 			      OP_ALG_AAI_CMAC,
1691 			      OP_ALG_AS_INITFINAL,
1692 			      ICV_CHECK_ENABLE,
1693 			      DIR_DEC);
1694 
1695 		/* Read the # of bytes written in the output buffer + 1 (HDR) */
1696 		MATHI(p, VSEQOUTSZ, ADD, length, VSEQINSZ, 4, IMMED2);
1697 
1698 		if (rta_sec_era <= RTA_SEC_ERA_3)
1699 			MOVE(p, MATH3, 0, IFIFOAB1, 0, 8, IMMED);
1700 		else
1701 			MOVE(p, CONTEXT2, 0, IFIFOAB1, 0, 8, IMMED);
1702 
1703 		if (rta_sec_era == RTA_SEC_ERA_2 && era_2_sw_hfn_ovrd)
1704 			SEQFIFOLOAD(p, SKIP, 4, 0);
1705 
1706 		SEQFIFOLOAD(p, MSG1, 0, VLF | LAST1 | FLUSH1);
1707 
1708 		if (rta_sec_era >= RTA_SEC_ERA_4) {
1709 			LOAD(p, NFIFOENTRY_STYPE_ALTSOURCE |
1710 			     NFIFOENTRY_DEST_CLASS1 |
1711 			     NFIFOENTRY_DTYPE_ICV |
1712 			     NFIFOENTRY_LC1 |
1713 			     NFIFOENTRY_FC1 | 4, NFIFO_SZL, 0, 4, IMMED);
1714 			MOVE(p, MATH3, 0, ALTSOURCE, 0, 4, IMMED);
1715 		} else {
1716 			SET_LABEL(p, fifo_load_mac_i_offset);
1717 			FIFOLOAD(p, ICV1, fifo_load_mac_i_offset, 4,
1718 				 LAST1 | FLUSH1 | IMMED);
1719 		}
1720 
1721 		SET_LABEL(p, end_desc);
1722 
1723 		if (!p->ps) {
1724 			PATCH_MOVE(p, seq_out_read, end_desc + 1);
1725 			PATCH_JUMP(p, jump_back_to_sd_cmd,
1726 				   back_to_sd_offset + jump_back_to_sd_cmd - 5);
1727 
1728 			if (rta_sec_era <= RTA_SEC_ERA_3)
1729 				PATCH_MOVE(p, move_mac_i_to_desc_buf,
1730 					   fifo_load_mac_i_offset + 1);
1731 		} else {
1732 			PATCH_MOVE(p, seq_out_read, end_desc + 2);
1733 			PATCH_JUMP(p, jump_back_to_sd_cmd,
1734 				   back_to_sd_offset + jump_back_to_sd_cmd - 5);
1735 
1736 			if (rta_sec_era <= RTA_SEC_ERA_3)
1737 				PATCH_MOVE(p, move_mac_i_to_desc_buf,
1738 					   fifo_load_mac_i_offset + 1);
1739 		}
1740 	}
1741 
1742 	return 0;
1743 }
1744 
1745 static inline int
1746 pdcp_insert_cplane_aes_snow_op(struct program *p,
1747 			       bool swap __maybe_unused,
1748 			       struct alginfo *cipherdata,
1749 			       struct alginfo *authdata,
1750 			       unsigned int dir,
1751 			       enum pdcp_sn_size sn_size,
1752 			       unsigned char era_2_sw_hfn_ovrd __maybe_unused)
1753 {
1754 	uint32_t offset = 0, length = 0, sn_mask = 0;
1755 
1756 	KEY(p, KEY1, cipherdata->key_enc_flags, cipherdata->key,
1757 	    cipherdata->keylen, INLINE_KEY(cipherdata));
1758 	KEY(p, KEY2, authdata->key_enc_flags, authdata->key, authdata->keylen,
1759 	    INLINE_KEY(authdata));
1760 
1761 	if ((rta_sec_era >= RTA_SEC_ERA_8 && sn_size != PDCP_SN_SIZE_18) ||
1762 		(rta_sec_era == RTA_SEC_ERA_10)) {
1763 		int pclid;
1764 
1765 		if (sn_size == PDCP_SN_SIZE_5)
1766 			pclid = OP_PCLID_LTE_PDCP_CTRL_MIXED;
1767 		else
1768 			pclid = OP_PCLID_LTE_PDCP_USER_RN;
1769 
1770 		PROTOCOL(p, dir, pclid,
1771 			 ((uint16_t)cipherdata->algtype << 8) |
1772 			 (uint16_t)authdata->algtype);
1773 
1774 		return 0;
1775 	}
1776 	/* Non-proto is supported only for 5bit cplane and 18bit uplane */
1777 	switch (sn_size) {
1778 	case PDCP_SN_SIZE_5:
1779 		offset = 7;
1780 		length = 1;
1781 		sn_mask = (swap == false) ? PDCP_C_PLANE_SN_MASK :
1782 					PDCP_C_PLANE_SN_MASK_BE;
1783 		break;
1784 	case PDCP_SN_SIZE_18:
1785 		offset = 5;
1786 		length = 3;
1787 		sn_mask = (swap == false) ? PDCP_U_PLANE_18BIT_SN_MASK :
1788 					PDCP_U_PLANE_18BIT_SN_MASK_BE;
1789 		break;
1790 	case PDCP_SN_SIZE_7:
1791 	case PDCP_SN_SIZE_12:
1792 	case PDCP_SN_SIZE_15:
1793 		pr_err("Invalid sn_size for %s\n", __func__);
1794 		return -ENOTSUP;
1795 
1796 	}
1797 
1798 	if (dir == OP_TYPE_ENCAP_PROTOCOL)
1799 		MATHB(p, SEQINSZ, SUB, length, VSEQINSZ, 4, IMMED2);
1800 
1801 	SEQLOAD(p, MATH0, offset, length, 0);
1802 	JUMP(p, 1, LOCAL_JUMP, ALL_TRUE, CALM);
1803 	MOVEB(p, MATH0, offset, IFIFOAB2, 0, length, IMMED);
1804 	MATHB(p, MATH0, AND, sn_mask, MATH1, 8, IFB | IMMED2);
1805 
1806 	SEQSTORE(p, MATH0, offset, length, 0);
1807 	MATHB(p, MATH1, SHLD, MATH1, MATH1, 8, 0);
1808 	MOVEB(p, DESCBUF, 4, MATH2, 0, 8, WAITCOMP | IMMED);
1809 	MATHB(p, MATH1, OR, MATH2, MATH1, 8, 0);
1810 	MOVEB(p, MATH1, 0, CONTEXT1, 16, 8, IMMED);
1811 	MOVEB(p, MATH1, 0, CONTEXT2, 0, 4, IMMED);
1812 	if (swap == false) {
1813 		MATHB(p, MATH1, AND, upper_32_bits(PDCP_BEARER_MASK), MATH2, 4,
1814 		      IMMED2);
1815 		MATHB(p, MATH1, AND, lower_32_bits(PDCP_DIR_MASK), MATH3, 4,
1816 		      IMMED2);
1817 	} else {
1818 		MATHB(p, MATH1, AND, lower_32_bits(PDCP_BEARER_MASK_BE), MATH2,
1819 			4, IMMED2);
1820 		MATHB(p, MATH1, AND, upper_32_bits(PDCP_DIR_MASK_BE), MATH3,
1821 			4, IMMED2);
1822 	}
1823 	MATHB(p, MATH3, SHLD, MATH3, MATH3, 8, 0);
1824 	MOVEB(p, MATH2, 4, OFIFO, 0, 12, IMMED);
1825 	MOVE(p, OFIFO, 0, CONTEXT2, 4, 12, IMMED);
1826 	if (dir == OP_TYPE_ENCAP_PROTOCOL) {
1827 		MATHB(p, SEQINSZ, ADD, PDCP_MAC_I_LEN, VSEQOUTSZ, 4, IMMED2);
1828 	} else {
1829 		MATHB(p, SEQINSZ, SUB, PDCP_MAC_I_LEN, MATH1, 4, IMMED2);
1830 
1831 		MATHB(p, ZERO, ADD, MATH1, VSEQOUTSZ, 4, 0);
1832 		MATHB(p, ZERO, ADD, MATH1, VSEQINSZ, 4, 0);
1833 	}
1834 
1835 	if (dir == OP_TYPE_ENCAP_PROTOCOL)
1836 		SEQFIFOSTORE(p, MSG, 0, 0, VLF);
1837 	else
1838 		SEQFIFOSTORE(p, MSG, 0, 0, VLF | CONT);
1839 
1840 	ALG_OPERATION(p, OP_ALG_ALGSEL_SNOW_F9,
1841 		      OP_ALG_AAI_F9,
1842 		      OP_ALG_AS_INITFINAL,
1843 		      dir == OP_TYPE_ENCAP_PROTOCOL ?
1844 			     ICV_CHECK_DISABLE : ICV_CHECK_ENABLE,
1845 		      DIR_DEC);
1846 	ALG_OPERATION(p, OP_ALG_ALGSEL_AES,
1847 		      OP_ALG_AAI_CTR,
1848 		      OP_ALG_AS_INITFINAL,
1849 		      ICV_CHECK_DISABLE,
1850 		      dir == OP_TYPE_ENCAP_PROTOCOL ? DIR_ENC : DIR_DEC);
1851 
1852 	if (dir == OP_TYPE_ENCAP_PROTOCOL) {
1853 		SEQFIFOLOAD(p, MSGINSNOOP, 0, VLF | LAST2);
1854 		MOVE(p, CONTEXT2, 0, IFIFOAB1, 0, 4, LAST1 | FLUSH1 | IMMED);
1855 	} else {
1856 		SEQFIFOLOAD(p, MSGOUTSNOOP, 0, VLF | LAST2);
1857 		SEQFIFOLOAD(p, MSG1, 4, LAST1 | FLUSH1);
1858 		JUMP(p, 1, LOCAL_JUMP, ALL_TRUE, CLASS1 | NOP | NIFP);
1859 
1860 		if (rta_sec_era >= RTA_SEC_ERA_6)
1861 			LOAD(p, 0, DCTRL, 0, LDLEN_RST_CHA_OFIFO_PTR, IMMED);
1862 
1863 		MOVE(p, OFIFO, 0, MATH0, 0, 4, WAITCOMP | IMMED);
1864 
1865 		NFIFOADD(p, IFIFO, ICV2, 4, LAST2);
1866 
1867 		if (rta_sec_era <= RTA_SEC_ERA_2) {
1868 			/* Shut off automatic Info FIFO entries */
1869 			LOAD(p, 0, DCTRL, LDOFF_DISABLE_AUTO_NFIFO, 0, IMMED);
1870 			MOVE(p, MATH0, 0, IFIFOAB2, 0, 4, WAITCOMP | IMMED);
1871 		} else {
1872 			MOVE(p, MATH0, 0, IFIFO, 0, 4, WAITCOMP | IMMED);
1873 		}
1874 	}
1875 
1876 	return 0;
1877 }
1878 
1879 static inline int
1880 pdcp_insert_cplane_snow_zuc_op(struct program *p,
1881 			       bool swap __maybe_unused,
1882 			       struct alginfo *cipherdata,
1883 			       struct alginfo *authdata,
1884 			       unsigned int dir,
1885 			       enum pdcp_sn_size sn_size,
1886 			       unsigned char era_2_sw_hfn_ovrd __maybe_unused)
1887 {
1888 	uint32_t offset = 0, length = 0, sn_mask = 0;
1889 
1890 	LABEL(keyjump);
1891 	REFERENCE(pkeyjump);
1892 
1893 	if (rta_sec_era < RTA_SEC_ERA_5) {
1894 		pr_err("Invalid era for selected algorithm\n");
1895 		return -ENOTSUP;
1896 	}
1897 
1898 	if ((rta_sec_era >= RTA_SEC_ERA_8 && sn_size != PDCP_SN_SIZE_18) ||
1899 		(rta_sec_era == RTA_SEC_ERA_10)) {
1900 		int pclid;
1901 		KEY(p, KEY1, cipherdata->key_enc_flags, cipherdata->key,
1902 		    cipherdata->keylen, INLINE_KEY(cipherdata));
1903 		KEY(p, KEY2, authdata->key_enc_flags, authdata->key, authdata->keylen,
1904 		    INLINE_KEY(authdata));
1905 
1906 		if (sn_size == PDCP_SN_SIZE_5)
1907 			pclid = OP_PCLID_LTE_PDCP_CTRL_MIXED;
1908 		else
1909 			pclid = OP_PCLID_LTE_PDCP_USER_RN;
1910 
1911 		PROTOCOL(p, dir, pclid,
1912 			 ((uint16_t)cipherdata->algtype << 8) |
1913 			 (uint16_t)authdata->algtype);
1914 		return 0;
1915 	}
1916 	/* Non-proto is supported only for 5bit cplane and 18bit uplane */
1917 	switch (sn_size) {
1918 	case PDCP_SN_SIZE_5:
1919 		offset = 7;
1920 		length = 1;
1921 		sn_mask = (swap == false) ? PDCP_C_PLANE_SN_MASK :
1922 					PDCP_C_PLANE_SN_MASK_BE;
1923 		break;
1924 	case PDCP_SN_SIZE_18:
1925 		offset = 5;
1926 		length = 3;
1927 		sn_mask = (swap == false) ? PDCP_U_PLANE_18BIT_SN_MASK :
1928 					PDCP_U_PLANE_18BIT_SN_MASK_BE;
1929 		break;
1930 	case PDCP_SN_SIZE_7:
1931 	case PDCP_SN_SIZE_12:
1932 	case PDCP_SN_SIZE_15:
1933 		pr_err("Invalid sn_size for %s\n", __func__);
1934 		return -ENOTSUP;
1935 
1936 	}
1937 
1938 	pkeyjump = JUMP(p, keyjump, LOCAL_JUMP, ALL_TRUE, SHRD | SELF | BOTH);
1939 	KEY(p, KEY1, cipherdata->key_enc_flags, cipherdata->key,
1940 	    cipherdata->keylen, INLINE_KEY(cipherdata));
1941 	KEY(p, KEY2, authdata->key_enc_flags, authdata->key, authdata->keylen,
1942 	    INLINE_KEY(authdata));
1943 
1944 	SET_LABEL(p, keyjump);
1945 	SEQLOAD(p, MATH0, offset, length, 0);
1946 	JUMP(p, 1, LOCAL_JUMP, ALL_TRUE, CALM);
1947 	MOVEB(p, MATH0, offset, IFIFOAB2, 0, length, IMMED);
1948 	MATHB(p, MATH0, AND, sn_mask, MATH1, 8, IFB | IMMED2);
1949 
1950 	MATHB(p, MATH1, SHLD, MATH1, MATH1, 8, 0);
1951 	MOVEB(p, DESCBUF, 4, MATH2, 0, 8, WAITCOMP | IMMED);
1952 	MATHB(p, MATH1, OR, MATH2, MATH2, 8, 0);
1953 	MOVEB(p, MATH2, 0, CONTEXT1, 0, 8, IMMED);
1954 	MOVEB(p, MATH2, 0, CONTEXT2, 0, 8, WAITCOMP | IMMED);
1955 
1956 	if (dir == OP_TYPE_ENCAP_PROTOCOL)
1957 		MATHB(p, SEQINSZ, ADD, PDCP_MAC_I_LEN, VSEQOUTSZ, 4, IMMED2);
1958 	else
1959 		MATHB(p, SEQINSZ, SUB, PDCP_MAC_I_LEN, VSEQOUTSZ, 4, IMMED2);
1960 
1961 	MATHB(p, SEQINSZ, SUB, ZERO, VSEQINSZ, 4, 0);
1962 	SEQSTORE(p, MATH0, offset, length, 0);
1963 
1964 	if (dir == OP_TYPE_ENCAP_PROTOCOL) {
1965 		SEQFIFOSTORE(p, MSG, 0, 0, VLF);
1966 		SEQFIFOLOAD(p, MSGINSNOOP, 0, VLF | LAST2);
1967 	} else {
1968 		SEQFIFOSTORE(p, MSG, 0, 0, VLF | CONT);
1969 		SEQFIFOLOAD(p, MSGOUTSNOOP, 0, VLF | LAST1 | FLUSH1);
1970 	}
1971 
1972 	ALG_OPERATION(p, OP_ALG_ALGSEL_ZUCA,
1973 		      OP_ALG_AAI_F9,
1974 		      OP_ALG_AS_INITFINAL,
1975 		      dir == OP_TYPE_ENCAP_PROTOCOL ?
1976 			     ICV_CHECK_DISABLE : ICV_CHECK_ENABLE,
1977 		      DIR_ENC);
1978 
1979 	ALG_OPERATION(p, OP_ALG_ALGSEL_SNOW_F8,
1980 		      OP_ALG_AAI_F8,
1981 		      OP_ALG_AS_INITFINAL,
1982 		      ICV_CHECK_DISABLE,
1983 		      dir == OP_TYPE_ENCAP_PROTOCOL ? DIR_ENC : DIR_DEC);
1984 	if (dir == OP_TYPE_ENCAP_PROTOCOL) {
1985 		MOVE(p, CONTEXT2, 0, IFIFOAB1, 0, 4, LAST1 | FLUSH1 | IMMED);
1986 	} else {
1987 		/* Save ICV */
1988 		MOVE(p, OFIFO, 0, MATH0, 0, 4, IMMED);
1989 		LOAD(p, NFIFOENTRY_STYPE_ALTSOURCE |
1990 		     NFIFOENTRY_DEST_CLASS2 |
1991 		     NFIFOENTRY_DTYPE_ICV |
1992 		     NFIFOENTRY_LC2 | 4, NFIFO_SZL, 0, 4, IMMED);
1993 		MOVE(p, MATH0, 0, ALTSOURCE, 0, 4, WAITCOMP | IMMED);
1994 	}
1995 
1996 	/* Reset ZUCA mode and done interrupt */
1997 	LOAD(p, CLRW_CLR_C2MODE, CLRW, 0, 4, IMMED);
1998 	LOAD(p, CIRQ_ZADI, ICTRL, 0, 4, IMMED);
1999 
2000 	PATCH_JUMP(p, pkeyjump, keyjump);
2001 	return 0;
2002 }
2003 
2004 static inline int
2005 pdcp_insert_cplane_aes_zuc_op(struct program *p,
2006 			      bool swap __maybe_unused,
2007 			      struct alginfo *cipherdata,
2008 			      struct alginfo *authdata,
2009 			      unsigned int dir,
2010 			      enum pdcp_sn_size sn_size,
2011 			      unsigned char era_2_sw_hfn_ovrd __maybe_unused)
2012 {
2013 	uint32_t offset = 0, length = 0, sn_mask = 0;
2014 	LABEL(keyjump);
2015 	REFERENCE(pkeyjump);
2016 
2017 	if (rta_sec_era < RTA_SEC_ERA_5) {
2018 		pr_err("Invalid era for selected algorithm\n");
2019 		return -ENOTSUP;
2020 	}
2021 
2022 	if ((rta_sec_era >= RTA_SEC_ERA_8 && sn_size != PDCP_SN_SIZE_18) ||
2023 		(rta_sec_era == RTA_SEC_ERA_10)) {
2024 		int pclid;
2025 		KEY(p, KEY1, cipherdata->key_enc_flags, cipherdata->key,
2026 		    cipherdata->keylen, INLINE_KEY(cipherdata));
2027 		KEY(p, KEY2, authdata->key_enc_flags, authdata->key, authdata->keylen,
2028 		    INLINE_KEY(authdata));
2029 
2030 		if (sn_size == PDCP_SN_SIZE_5)
2031 			pclid = OP_PCLID_LTE_PDCP_CTRL_MIXED;
2032 		else
2033 			pclid = OP_PCLID_LTE_PDCP_USER_RN;
2034 
2035 		PROTOCOL(p, dir, pclid,
2036 			 ((uint16_t)cipherdata->algtype << 8) |
2037 			 (uint16_t)authdata->algtype);
2038 
2039 		return 0;
2040 	}
2041 	/* Non-proto is supported only for 5bit cplane and 18bit uplane */
2042 	switch (sn_size) {
2043 	case PDCP_SN_SIZE_5:
2044 		offset = 7;
2045 		length = 1;
2046 		sn_mask = (swap == false) ? PDCP_C_PLANE_SN_MASK :
2047 					PDCP_C_PLANE_SN_MASK_BE;
2048 		break;
2049 	case PDCP_SN_SIZE_18:
2050 		offset = 5;
2051 		length = 3;
2052 		sn_mask = (swap == false) ? PDCP_U_PLANE_18BIT_SN_MASK :
2053 					PDCP_U_PLANE_18BIT_SN_MASK_BE;
2054 		break;
2055 	case PDCP_SN_SIZE_7:
2056 	case PDCP_SN_SIZE_12:
2057 	case PDCP_SN_SIZE_15:
2058 		pr_err("Invalid sn_size for %s\n", __func__);
2059 		return -ENOTSUP;
2060 
2061 	}
2062 	pkeyjump = JUMP(p, keyjump, LOCAL_JUMP, ALL_TRUE, SHRD | SELF | BOTH);
2063 	KEY(p, KEY1, cipherdata->key_enc_flags, cipherdata->key,
2064 	    cipherdata->keylen, INLINE_KEY(cipherdata));
2065 	KEY(p, KEY2, authdata->key_enc_flags, authdata->key, authdata->keylen,
2066 	    INLINE_KEY(authdata));
2067 
2068 	SET_LABEL(p, keyjump);
2069 
2070 	SEQLOAD(p, MATH0, offset, length, 0);
2071 	JUMP(p, 1, LOCAL_JUMP, ALL_TRUE, CALM);
2072 	MOVEB(p, MATH0, offset, IFIFOAB2, 0, length, IMMED);
2073 	MATHB(p, MATH0, AND, sn_mask, MATH1, 8, IFB | IMMED2);
2074 
2075 	MATHB(p, MATH1, SHLD, MATH1, MATH1, 8, 0);
2076 	MOVEB(p, DESCBUF, 4, MATH2, 0, 8, WAITCOMP | IMMED);
2077 	MATHB(p, MATH1, OR, MATH2, MATH2, 8, 0);
2078 	MOVEB(p, MATH2, 0, CONTEXT1, 16, 8, IMMED);
2079 	MOVEB(p, MATH2, 0, CONTEXT2, 0, 8, WAITCOMP | IMMED);
2080 
2081 	if (dir == OP_TYPE_ENCAP_PROTOCOL)
2082 		MATHB(p, SEQINSZ, ADD, PDCP_MAC_I_LEN, VSEQOUTSZ, 4, IMMED2);
2083 	else
2084 		MATHB(p, SEQINSZ, SUB, PDCP_MAC_I_LEN, VSEQOUTSZ, 4, IMMED2);
2085 
2086 	MATHB(p, SEQINSZ, SUB, ZERO, VSEQINSZ, 4, 0);
2087 	SEQSTORE(p, MATH0, offset, length, 0);
2088 
2089 	if (dir == OP_TYPE_ENCAP_PROTOCOL) {
2090 		SEQFIFOSTORE(p, MSG, 0, 0, VLF);
2091 		SEQFIFOLOAD(p, MSGINSNOOP, 0, VLF | LAST2);
2092 	} else {
2093 		SEQFIFOSTORE(p, MSG, 0, 0, VLF | CONT);
2094 		SEQFIFOLOAD(p, MSGOUTSNOOP, 0, VLF | LAST1 | FLUSH1);
2095 	}
2096 
2097 	ALG_OPERATION(p, OP_ALG_ALGSEL_ZUCA,
2098 		      OP_ALG_AAI_F9,
2099 		      OP_ALG_AS_INITFINAL,
2100 		      dir == OP_TYPE_ENCAP_PROTOCOL ?
2101 			     ICV_CHECK_DISABLE : ICV_CHECK_ENABLE,
2102 		      DIR_ENC);
2103 
2104 	ALG_OPERATION(p, OP_ALG_ALGSEL_AES,
2105 		      OP_ALG_AAI_CTR,
2106 		      OP_ALG_AS_INITFINAL,
2107 		      ICV_CHECK_DISABLE,
2108 		      dir == OP_TYPE_ENCAP_PROTOCOL ? DIR_ENC : DIR_DEC);
2109 
2110 	if (dir == OP_TYPE_ENCAP_PROTOCOL) {
2111 		MOVE(p, CONTEXT2, 0, IFIFOAB1, 0, 4, LAST1 | FLUSH1 | IMMED);
2112 	} else {
2113 		/* Save ICV */
2114 		MOVE(p, OFIFO, 0, MATH0, 0, 4, IMMED);
2115 
2116 		LOAD(p, NFIFOENTRY_STYPE_ALTSOURCE |
2117 		     NFIFOENTRY_DEST_CLASS2 |
2118 		     NFIFOENTRY_DTYPE_ICV |
2119 		     NFIFOENTRY_LC2 | 4, NFIFO_SZL, 0, 4, IMMED);
2120 		MOVE(p, MATH0, 0, ALTSOURCE, 0, 4, WAITCOMP | IMMED);
2121 	}
2122 
2123 	/* Reset ZUCA mode and done interrupt */
2124 	LOAD(p, CLRW_CLR_C2MODE, CLRW, 0, 4, IMMED);
2125 	LOAD(p, CIRQ_ZADI, ICTRL, 0, 4, IMMED);
2126 
2127 	PATCH_JUMP(p, pkeyjump, keyjump);
2128 
2129 	return 0;
2130 }
2131 
2132 static inline int
2133 pdcp_insert_cplane_zuc_snow_op(struct program *p,
2134 			       bool swap __maybe_unused,
2135 			       struct alginfo *cipherdata,
2136 			       struct alginfo *authdata,
2137 			       unsigned int dir,
2138 			       enum pdcp_sn_size sn_size,
2139 			       unsigned char era_2_sw_hfn_ovrd __maybe_unused)
2140 {
2141 	uint32_t offset = 0, length = 0, sn_mask = 0;
2142 	LABEL(keyjump);
2143 	REFERENCE(pkeyjump);
2144 
2145 	if (rta_sec_era < RTA_SEC_ERA_5) {
2146 		pr_err("Invalid era for selected algorithm\n");
2147 		return -ENOTSUP;
2148 	}
2149 
2150 	if ((rta_sec_era >= RTA_SEC_ERA_8 && sn_size != PDCP_SN_SIZE_18) ||
2151 		(rta_sec_era == RTA_SEC_ERA_10)) {
2152 		int pclid;
2153 		KEY(p, KEY1, cipherdata->key_enc_flags, cipherdata->key,
2154 		    cipherdata->keylen, INLINE_KEY(cipherdata));
2155 		KEY(p, KEY2, authdata->key_enc_flags, authdata->key, authdata->keylen,
2156 		    INLINE_KEY(authdata));
2157 
2158 		if (sn_size == PDCP_SN_SIZE_5)
2159 			pclid = OP_PCLID_LTE_PDCP_CTRL_MIXED;
2160 		else
2161 			pclid = OP_PCLID_LTE_PDCP_USER_RN;
2162 
2163 		PROTOCOL(p, dir, pclid,
2164 			 ((uint16_t)cipherdata->algtype << 8) |
2165 			 (uint16_t)authdata->algtype);
2166 
2167 		return 0;
2168 	}
2169 	/* Non-proto is supported only for 5bit cplane and 18bit uplane */
2170 	switch (sn_size) {
2171 	case PDCP_SN_SIZE_5:
2172 		offset = 7;
2173 		length = 1;
2174 		sn_mask = (swap == false) ? PDCP_C_PLANE_SN_MASK :
2175 					PDCP_C_PLANE_SN_MASK_BE;
2176 		break;
2177 	case PDCP_SN_SIZE_18:
2178 		offset = 5;
2179 		length = 3;
2180 		sn_mask = (swap == false) ? PDCP_U_PLANE_18BIT_SN_MASK :
2181 					PDCP_U_PLANE_18BIT_SN_MASK_BE;
2182 		break;
2183 	case PDCP_SN_SIZE_7:
2184 	case PDCP_SN_SIZE_12:
2185 	case PDCP_SN_SIZE_15:
2186 		pr_err("Invalid sn_size for %s\n", __func__);
2187 		return -ENOTSUP;
2188 
2189 	}
2190 	pkeyjump = JUMP(p, keyjump, LOCAL_JUMP, ALL_TRUE, SHRD | SELF | BOTH);
2191 	KEY(p, KEY1, cipherdata->key_enc_flags, cipherdata->key,
2192 	    cipherdata->keylen, INLINE_KEY(cipherdata));
2193 	KEY(p, KEY2, authdata->key_enc_flags, authdata->key, authdata->keylen,
2194 	    INLINE_KEY(authdata));
2195 
2196 	SET_LABEL(p, keyjump);
2197 	SEQLOAD(p, MATH0, offset, length, 0);
2198 	JUMP(p, 1, LOCAL_JUMP, ALL_TRUE, CALM);
2199 	MOVEB(p, MATH0, offset, IFIFOAB2, 0, length, IMMED);
2200 	MATHB(p, MATH0, AND, sn_mask, MATH1, 8, IFB | IMMED2);
2201 
2202 	MATHB(p, MATH1, SHLD, MATH1, MATH1, 8, 0);
2203 	MOVEB(p, DESCBUF, 4, MATH2, 0, 8, WAITCOMP | IMMED);
2204 	MATHB(p, MATH1, OR, MATH2, MATH1, 8, 0);
2205 	MOVEB(p, MATH1, 0, CONTEXT1, 0, 8, IMMED);
2206 	MOVEB(p, MATH1, 0, CONTEXT2, 0, 4, IMMED);
2207 	if (swap == false) {
2208 		MATHB(p, MATH1, AND, upper_32_bits(PDCP_BEARER_MASK), MATH2,
2209 		      4, IMMED2);
2210 		MATHB(p, MATH1, AND, lower_32_bits(PDCP_DIR_MASK), MATH3,
2211 		      4, IMMED2);
2212 	} else {
2213 		MATHB(p, MATH1, AND, lower_32_bits(PDCP_BEARER_MASK_BE), MATH2,
2214 			4, IMMED2);
2215 		MATHB(p, MATH1, AND, upper_32_bits(PDCP_DIR_MASK_BE), MATH3,
2216 			4, IMMED2);
2217 	}
2218 	MATHB(p, MATH3, SHLD, MATH3, MATH3, 8, 0);
2219 	MOVEB(p, MATH2, 4, OFIFO, 0, 12, IMMED);
2220 	MOVE(p, OFIFO, 0, CONTEXT2, 4, 12, IMMED);
2221 
2222 	if (dir == OP_TYPE_ENCAP_PROTOCOL) {
2223 		MATHB(p, SEQINSZ, ADD, PDCP_MAC_I_LEN, VSEQOUTSZ, 4, IMMED2);
2224 		MATHB(p, SEQINSZ, SUB, ZERO, VSEQINSZ, 4, 0);
2225 	} else {
2226 		MATHB(p, SEQINSZ, SUB, PDCP_MAC_I_LEN, VSEQOUTSZ, 4, IMMED2);
2227 		MATHB(p, VSEQOUTSZ, SUB, ZERO, VSEQINSZ, 4, 0);
2228 	}
2229 
2230 	SEQSTORE(p, MATH0, offset, length, 0);
2231 
2232 	if (dir == OP_TYPE_ENCAP_PROTOCOL) {
2233 		SEQFIFOSTORE(p, MSG, 0, 0, VLF);
2234 		SEQFIFOLOAD(p, MSGINSNOOP, 0, VLF | LAST2);
2235 	} else {
2236 		SEQFIFOSTORE(p, MSG, 0, 0, VLF | CONT);
2237 		SEQFIFOLOAD(p, MSGOUTSNOOP, 0, VLF | LAST2);
2238 	}
2239 
2240 	ALG_OPERATION(p, OP_ALG_ALGSEL_SNOW_F9,
2241 		      OP_ALG_AAI_F9,
2242 		      OP_ALG_AS_INITFINAL,
2243 		      dir == OP_TYPE_ENCAP_PROTOCOL ?
2244 			     ICV_CHECK_DISABLE : ICV_CHECK_ENABLE,
2245 		      DIR_DEC);
2246 
2247 	ALG_OPERATION(p, OP_ALG_ALGSEL_ZUCE,
2248 		      OP_ALG_AAI_F8,
2249 		      OP_ALG_AS_INITFINAL,
2250 		      ICV_CHECK_DISABLE,
2251 		      dir == OP_TYPE_ENCAP_PROTOCOL ? DIR_ENC : DIR_DEC);
2252 
2253 	if (dir == OP_TYPE_ENCAP_PROTOCOL) {
2254 		MOVE(p, CONTEXT2, 0, IFIFOAB1, 0, 4, LAST1 | FLUSH1 | IMMED);
2255 	} else {
2256 		SEQFIFOLOAD(p, MSG1, 4, LAST1 | FLUSH1);
2257 		JUMP(p, 1, LOCAL_JUMP, ALL_TRUE, CLASS1 | NOP | NIFP);
2258 
2259 		if (rta_sec_era >= RTA_SEC_ERA_6)
2260 			/*
2261 			 * For SEC ERA 6, there's a problem with the OFIFO
2262 			 * pointer, and thus it needs to be reset here before
2263 			 * moving to M0.
2264 			 */
2265 			LOAD(p, 0, DCTRL, 0, LDLEN_RST_CHA_OFIFO_PTR, IMMED);
2266 
2267 		/* Put ICV to M0 before sending it to C2 for comparison. */
2268 		MOVEB(p, OFIFO, 0, MATH0, 0, 4, WAITCOMP | IMMED);
2269 
2270 		LOAD(p, NFIFOENTRY_STYPE_ALTSOURCE |
2271 		     NFIFOENTRY_DEST_CLASS2 |
2272 		     NFIFOENTRY_DTYPE_ICV |
2273 		     NFIFOENTRY_LC2 | 4, NFIFO_SZL, 0, 4, IMMED);
2274 		MOVEB(p, MATH0, 0, ALTSOURCE, 0, 4, IMMED);
2275 	}
2276 
2277 	PATCH_JUMP(p, pkeyjump, keyjump);
2278 	return 0;
2279 }
2280 
2281 static inline int
2282 pdcp_insert_cplane_zuc_aes_op(struct program *p,
2283 			      bool swap __maybe_unused,
2284 			      struct alginfo *cipherdata,
2285 			      struct alginfo *authdata,
2286 			      unsigned int dir,
2287 			      enum pdcp_sn_size sn_size,
2288 			      unsigned char era_2_sw_hfn_ovrd __maybe_unused)
2289 {
2290 	uint32_t offset = 0, length = 0, sn_mask = 0;
2291 	if (rta_sec_era < RTA_SEC_ERA_5) {
2292 		pr_err("Invalid era for selected algorithm\n");
2293 		return -ENOTSUP;
2294 	}
2295 
2296 	if ((rta_sec_era >= RTA_SEC_ERA_8 && sn_size != PDCP_SN_SIZE_18) ||
2297 		(rta_sec_era == RTA_SEC_ERA_10)) {
2298 		int pclid;
2299 
2300 		KEY(p, KEY1, cipherdata->key_enc_flags, cipherdata->key,
2301 				cipherdata->keylen, INLINE_KEY(cipherdata));
2302 		KEY(p, KEY2, authdata->key_enc_flags, authdata->key,
2303 				authdata->keylen, INLINE_KEY(authdata));
2304 
2305 		if (sn_size == PDCP_SN_SIZE_5)
2306 			pclid = OP_PCLID_LTE_PDCP_CTRL_MIXED;
2307 		else
2308 			pclid = OP_PCLID_LTE_PDCP_USER_RN;
2309 
2310 		PROTOCOL(p, dir, pclid,
2311 			 ((uint16_t)cipherdata->algtype << 8) |
2312 			 (uint16_t)authdata->algtype);
2313 		return 0;
2314 	}
2315 	/* Non-proto is supported only for 5bit cplane and 18bit uplane */
2316 	switch (sn_size) {
2317 	case PDCP_SN_SIZE_5:
2318 		offset = 7;
2319 		length = 1;
2320 		sn_mask = (swap == false) ? PDCP_C_PLANE_SN_MASK :
2321 					PDCP_C_PLANE_SN_MASK_BE;
2322 		break;
2323 	case PDCP_SN_SIZE_18:
2324 		offset = 5;
2325 		length = 3;
2326 		sn_mask = (swap == false) ? PDCP_U_PLANE_18BIT_SN_MASK :
2327 					PDCP_U_PLANE_18BIT_SN_MASK_BE;
2328 		break;
2329 	case PDCP_SN_SIZE_7:
2330 	case PDCP_SN_SIZE_12:
2331 	case PDCP_SN_SIZE_15:
2332 		pr_err("Invalid sn_size for %s\n", __func__);
2333 		return -ENOTSUP;
2334 	}
2335 
2336 	SEQLOAD(p, MATH0, offset, length, 0);
2337 	JUMP(p, 1, LOCAL_JUMP, ALL_TRUE, CALM);
2338 	MATHB(p, MATH0, AND, sn_mask, MATH1, 8, IFB | IMMED2);
2339 
2340 	MATHB(p, MATH1, SHLD, MATH1, MATH1, 8, 0);
2341 	MOVEB(p, DESCBUF, 4, MATH2, 0, 0x08, WAITCOMP | IMMED);
2342 	MATHB(p, MATH1, OR, MATH2, MATH2, 8, 0);
2343 	SEQSTORE(p, MATH0, offset, length, 0);
2344 	if (dir == OP_TYPE_ENCAP_PROTOCOL) {
2345 		KEY(p, KEY1, authdata->key_enc_flags, authdata->key,
2346 		    authdata->keylen, INLINE_KEY(authdata));
2347 		MOVEB(p, MATH2, 0, IFIFOAB1, 0, 0x08, IMMED);
2348 		MOVEB(p, MATH0, offset, IFIFOAB1, 0, length, IMMED);
2349 
2350 		MATHB(p, SEQINSZ, SUB, ZERO, VSEQINSZ, 4, 0);
2351 		MATHB(p, VSEQINSZ, ADD, PDCP_MAC_I_LEN, VSEQOUTSZ, 4, IMMED2);
2352 
2353 		ALG_OPERATION(p, OP_ALG_ALGSEL_AES,
2354 			      OP_ALG_AAI_CMAC,
2355 			      OP_ALG_AS_INITFINAL,
2356 			      ICV_CHECK_DISABLE,
2357 			      DIR_DEC);
2358 		SEQFIFOLOAD(p, MSG1, 0, VLF | LAST1 | FLUSH1);
2359 		MOVEB(p, CONTEXT1, 0, MATH3, 0, 4, WAITCOMP | IMMED);
2360 		LOAD(p, CLRW_RESET_CLS1_CHA |
2361 		     CLRW_CLR_C1KEY |
2362 		     CLRW_CLR_C1CTX |
2363 		     CLRW_CLR_C1ICV |
2364 		     CLRW_CLR_C1DATAS |
2365 		     CLRW_CLR_C1MODE,
2366 		     CLRW, 0, 4, IMMED);
2367 
2368 		KEY(p, KEY1, cipherdata->key_enc_flags, cipherdata->key,
2369 		    cipherdata->keylen, INLINE_KEY(cipherdata));
2370 
2371 		MOVEB(p, MATH2, 0, CONTEXT1, 0, 8, IMMED);
2372 		SEQINPTR(p, 0, PDCP_NULL_MAX_FRAME_LEN, RTO);
2373 
2374 		ALG_OPERATION(p, OP_ALG_ALGSEL_ZUCE,
2375 			      OP_ALG_AAI_F8,
2376 			      OP_ALG_AS_INITFINAL,
2377 			      ICV_CHECK_DISABLE,
2378 			      DIR_ENC);
2379 		SEQFIFOSTORE(p, MSG, 0, 0, VLF);
2380 
2381 		SEQFIFOLOAD(p, SKIP, length, 0);
2382 
2383 		SEQFIFOLOAD(p, MSG1, 0, VLF);
2384 		MOVEB(p, MATH3, 0, IFIFOAB1, 0, 4, LAST1 | FLUSH1 | IMMED);
2385 	} else {
2386 		MOVEB(p, MATH2, 0, CONTEXT1, 0, 8, IMMED);
2387 
2388 		MOVE(p, CONTEXT1, 0, CONTEXT2, 0, 8, IMMED);
2389 
2390 		MATHB(p, SEQINSZ, SUB, ZERO, VSEQINSZ, 4, 0);
2391 
2392 		MATHB(p, SEQINSZ, SUB, PDCP_MAC_I_LEN, VSEQOUTSZ, 4, IMMED2);
2393 
2394 		KEY(p, KEY1, cipherdata->key_enc_flags, cipherdata->key,
2395 		    cipherdata->keylen, INLINE_KEY(cipherdata));
2396 
2397 		MOVE(p, CONTEXT1, 0, CONTEXT2, 0, 8, IMMED);
2398 
2399 		ALG_OPERATION(p, OP_ALG_ALGSEL_ZUCE,
2400 			      OP_ALG_AAI_F8,
2401 			      OP_ALG_AS_INITFINAL,
2402 			      ICV_CHECK_DISABLE,
2403 			      DIR_DEC);
2404 		SEQFIFOSTORE(p, MSG, 0, 0, VLF | CONT);
2405 		SEQFIFOLOAD(p, MSG1, 0, VLF | LAST1 | FLUSH1);
2406 
2407 		MOVEB(p, OFIFO, 0, MATH3, 0, 4, IMMED);
2408 
2409 		LOAD(p, CLRW_RESET_CLS1_CHA |
2410 		     CLRW_CLR_C1KEY |
2411 		     CLRW_CLR_C1CTX |
2412 		     CLRW_CLR_C1ICV |
2413 		     CLRW_CLR_C1DATAS |
2414 		     CLRW_CLR_C1MODE,
2415 		     CLRW, 0, 4, IMMED);
2416 
2417 		KEY(p, KEY1, authdata->key_enc_flags, authdata->key,
2418 		    authdata->keylen, INLINE_KEY(authdata));
2419 
2420 		SEQINPTR(p, 0, 0, SOP);
2421 
2422 		ALG_OPERATION(p, OP_ALG_ALGSEL_AES,
2423 			      OP_ALG_AAI_CMAC,
2424 			      OP_ALG_AS_INITFINAL,
2425 			      ICV_CHECK_ENABLE,
2426 			      DIR_DEC);
2427 
2428 		MATHB(p, SEQINSZ, SUB, ZERO, VSEQINSZ, 4, 0);
2429 
2430 		MOVE(p, CONTEXT2, 0, IFIFOAB1, 0, 8, IMMED);
2431 
2432 		SEQFIFOLOAD(p, MSG1, 0, VLF | LAST1 | FLUSH1);
2433 
2434 		LOAD(p, NFIFOENTRY_STYPE_ALTSOURCE |
2435 		     NFIFOENTRY_DEST_CLASS1 |
2436 		     NFIFOENTRY_DTYPE_ICV |
2437 		     NFIFOENTRY_LC1 |
2438 		     NFIFOENTRY_FC1 | 4, NFIFO_SZL, 0, 4, IMMED);
2439 		MOVEB(p, MATH3, 0, ALTSOURCE, 0, 4, IMMED);
2440 	}
2441 
2442 	return 0;
2443 }
2444 
2445 static inline int
2446 pdcp_insert_uplane_no_int_op(struct program *p,
2447 			    bool swap __maybe_unused,
2448 			    struct alginfo *cipherdata,
2449 			    unsigned int dir,
2450 			    enum pdcp_sn_size sn_size)
2451 {
2452 	int op;
2453 	uint32_t sn_mask;
2454 
2455 	/* Insert Cipher Key */
2456 	KEY(p, KEY1, cipherdata->key_enc_flags, cipherdata->key,
2457 	    cipherdata->keylen, INLINE_KEY(cipherdata));
2458 
2459 	if ((rta_sec_era >= RTA_SEC_ERA_8 && sn_size == PDCP_SN_SIZE_15) ||
2460 			(rta_sec_era >= RTA_SEC_ERA_10)) {
2461 		PROTOCOL(p, dir, OP_PCLID_LTE_PDCP_USER,
2462 			 (uint16_t)cipherdata->algtype);
2463 		return 0;
2464 	}
2465 
2466 	if (sn_size == PDCP_SN_SIZE_15) {
2467 		SEQLOAD(p, MATH0, 6, 2, 0);
2468 		sn_mask = (swap == false) ? PDCP_U_PLANE_15BIT_SN_MASK :
2469 					PDCP_U_PLANE_15BIT_SN_MASK_BE;
2470 	} else { /* SN Size == PDCP_SN_SIZE_18 */
2471 		SEQLOAD(p, MATH0, 5, 3, 0);
2472 		sn_mask = (swap == false) ? PDCP_U_PLANE_18BIT_SN_MASK :
2473 					PDCP_U_PLANE_18BIT_SN_MASK_BE;
2474 	}
2475 	JUMP(p, 1, LOCAL_JUMP, ALL_TRUE, CALM);
2476 	MATHB(p, MATH0, AND, sn_mask, MATH1, 8, IFB | IMMED2);
2477 
2478 	if (sn_size == PDCP_SN_SIZE_15)
2479 		SEQSTORE(p, MATH0, 6, 2, 0);
2480 	else /* SN Size == PDCP_SN_SIZE_18 */
2481 		SEQSTORE(p, MATH0, 5, 3, 0);
2482 
2483 	MATHB(p, MATH1, SHLD, MATH1, MATH1, 8, 0);
2484 	MOVEB(p, DESCBUF, 8, MATH2, 0, 8, WAITCOMP | IMMED);
2485 	MATHB(p, MATH1, OR, MATH2, MATH2, 8, 0);
2486 
2487 	MATHB(p, SEQINSZ, SUB, MATH3, VSEQINSZ, 4, 0);
2488 	MATHB(p, SEQINSZ, SUB, MATH3, VSEQOUTSZ, 4, 0);
2489 
2490 	SEQFIFOSTORE(p, MSG, 0, 0, VLF);
2491 
2492 	op = dir == OP_TYPE_ENCAP_PROTOCOL ? DIR_ENC : DIR_DEC;
2493 	switch (cipherdata->algtype) {
2494 	case PDCP_CIPHER_TYPE_SNOW:
2495 		MOVEB(p, MATH2, 0, CONTEXT1, 0, 8, WAITCOMP | IMMED);
2496 		ALG_OPERATION(p, OP_ALG_ALGSEL_SNOW_F8,
2497 			      OP_ALG_AAI_F8,
2498 			      OP_ALG_AS_INITFINAL,
2499 			      ICV_CHECK_DISABLE,
2500 			      op);
2501 		break;
2502 
2503 	case PDCP_CIPHER_TYPE_AES:
2504 		MOVEB(p, MATH2, 0, CONTEXT1, 0x10, 0x10, WAITCOMP | IMMED);
2505 		ALG_OPERATION(p, OP_ALG_ALGSEL_AES,
2506 			      OP_ALG_AAI_CTR,
2507 			      OP_ALG_AS_INITFINAL,
2508 			      ICV_CHECK_DISABLE,
2509 			      op);
2510 		break;
2511 
2512 	case PDCP_CIPHER_TYPE_ZUC:
2513 		if (rta_sec_era < RTA_SEC_ERA_5) {
2514 			pr_err("Invalid era for selected algorithm\n");
2515 			return -ENOTSUP;
2516 		}
2517 		MOVEB(p, MATH2, 0, CONTEXT1, 0, 0x08, IMMED);
2518 		MOVEB(p, MATH2, 0, CONTEXT1, 0x08, 0x08, WAITCOMP | IMMED);
2519 
2520 		ALG_OPERATION(p, OP_ALG_ALGSEL_ZUCE,
2521 			      OP_ALG_AAI_F8,
2522 			      OP_ALG_AS_INITFINAL,
2523 			      ICV_CHECK_DISABLE,
2524 			      op);
2525 		break;
2526 
2527 	default:
2528 		pr_err("%s: Invalid encrypt algorithm selected: %d\n",
2529 		       "pdcp_insert_uplane_15bit_op", cipherdata->algtype);
2530 		return -EINVAL;
2531 	}
2532 
2533 	SEQFIFOLOAD(p, MSG1, 0, VLF | LAST1 | FLUSH1);
2534 
2535 	return 0;
2536 }
2537 
2538 /*
2539  * Function for inserting the snippet of code responsible for creating
2540  * the HFN override code via either DPOVRD or via the input frame.
2541  */
2542 static inline int
2543 insert_hfn_ov_op(struct program *p,
2544 		 uint32_t shift,
2545 		 enum pdb_type_e pdb_type,
2546 		 unsigned char era_2_sw_hfn_ovrd)
2547 {
2548 	uint32_t imm = PDCP_DPOVRD_HFN_OV_EN;
2549 	uint16_t hfn_pdb_offset;
2550 	LABEL(keyjump);
2551 	REFERENCE(pkeyjump);
2552 
2553 	if (rta_sec_era == RTA_SEC_ERA_2 && !era_2_sw_hfn_ovrd)
2554 		return 0;
2555 
2556 	switch (pdb_type) {
2557 	case PDCP_PDB_TYPE_NO_PDB:
2558 		/*
2559 		 * If there is no PDB, then HFN override mechanism does not
2560 		 * make any sense, thus in this case the function will
2561 		 * return the pointer to the current position in the
2562 		 * descriptor buffer
2563 		 */
2564 		return 0;
2565 
2566 	case PDCP_PDB_TYPE_REDUCED_PDB:
2567 		hfn_pdb_offset = 4;
2568 		break;
2569 
2570 	case PDCP_PDB_TYPE_FULL_PDB:
2571 		hfn_pdb_offset = 8;
2572 		break;
2573 
2574 	default:
2575 		return -EINVAL;
2576 	}
2577 
2578 	if (rta_sec_era > RTA_SEC_ERA_2) {
2579 		MATHB(p, DPOVRD, AND, imm, NONE, 8, IFB | IMMED2);
2580 	} else {
2581 		SEQLOAD(p, MATH0, 4, 4, 0);
2582 		JUMP(p, 1, LOCAL_JUMP, ALL_TRUE, CALM);
2583 		MATHB(p, MATH0, AND, imm, NONE, 8, IFB | IMMED2);
2584 		SEQSTORE(p, MATH0, 4, 4, 0);
2585 	}
2586 
2587 	pkeyjump = JUMP(p, keyjump, LOCAL_JUMP, ALL_TRUE, MATH_Z);
2588 
2589 	if (rta_sec_era > RTA_SEC_ERA_2)
2590 		MATHI(p, DPOVRD, LSHIFT, shift, MATH0, 4, IMMED2);
2591 	else
2592 		MATHB(p, MATH0, LSHIFT, shift, MATH0, 4, IMMED2);
2593 
2594 	MATHB(p, MATH0, SHLD, MATH0, MATH0, 8, 0);
2595 	MOVE(p, MATH0, 0, DESCBUF, hfn_pdb_offset, 4, IMMED);
2596 
2597 	if (rta_sec_era >= RTA_SEC_ERA_8)
2598 		/*
2599 		 * For ERA8, DPOVRD could be handled by the PROTOCOL command
2600 		 * itself. For now, this is not done. Thus, clear DPOVRD here
2601 		 * to alleviate any side-effects.
2602 		 */
2603 		MATHB(p, DPOVRD, AND, ZERO, DPOVRD, 4, STL);
2604 
2605 	SET_LABEL(p, keyjump);
2606 	PATCH_JUMP(p, pkeyjump, keyjump);
2607 	return 0;
2608 }
2609 
2610 /*
2611  * PDCP Control PDB creation function
2612  */
2613 static inline enum pdb_type_e
2614 cnstr_pdcp_c_plane_pdb(struct program *p,
2615 		       uint32_t hfn,
2616 		       enum pdcp_sn_size sn_size,
2617 		       unsigned char bearer,
2618 		       unsigned char direction,
2619 		       uint32_t hfn_threshold,
2620 		       struct alginfo *cipherdata,
2621 		       struct alginfo *authdata)
2622 {
2623 	struct pdcp_pdb pdb;
2624 	enum pdb_type_e
2625 		pdb_mask[PDCP_CIPHER_TYPE_INVALID][PDCP_AUTH_TYPE_INVALID] = {
2626 			{	/* NULL */
2627 				PDCP_PDB_TYPE_NO_PDB,		/* NULL */
2628 				PDCP_PDB_TYPE_FULL_PDB,		/* SNOW f9 */
2629 				PDCP_PDB_TYPE_FULL_PDB,		/* AES CMAC */
2630 				PDCP_PDB_TYPE_FULL_PDB		/* ZUC-I */
2631 			},
2632 			{	/* SNOW f8 */
2633 				PDCP_PDB_TYPE_FULL_PDB,		/* NULL */
2634 				PDCP_PDB_TYPE_FULL_PDB,		/* SNOW f9 */
2635 				PDCP_PDB_TYPE_REDUCED_PDB,	/* AES CMAC */
2636 				PDCP_PDB_TYPE_REDUCED_PDB	/* ZUC-I */
2637 			},
2638 			{	/* AES CTR */
2639 				PDCP_PDB_TYPE_FULL_PDB,		/* NULL */
2640 				PDCP_PDB_TYPE_REDUCED_PDB,	/* SNOW f9 */
2641 				PDCP_PDB_TYPE_FULL_PDB,		/* AES CMAC */
2642 				PDCP_PDB_TYPE_REDUCED_PDB	/* ZUC-I */
2643 			},
2644 			{	/* ZUC-E */
2645 				PDCP_PDB_TYPE_FULL_PDB,		/* NULL */
2646 				PDCP_PDB_TYPE_REDUCED_PDB,	/* SNOW f9 */
2647 				PDCP_PDB_TYPE_REDUCED_PDB,	/* AES CMAC */
2648 				PDCP_PDB_TYPE_FULL_PDB		/* ZUC-I */
2649 			},
2650 	};
2651 
2652 	if (rta_sec_era >= RTA_SEC_ERA_8) {
2653 		memset(&pdb, 0x00, sizeof(struct pdcp_pdb));
2654 
2655 		/* To support 12-bit seq numbers, we use u-plane opt in pdb.
2656 		 * SEC supports 5-bit only with c-plane opt in pdb.
2657 		 */
2658 		if (sn_size == PDCP_SN_SIZE_12) {
2659 			pdb.hfn_res = hfn << PDCP_U_PLANE_PDB_LONG_SN_HFN_SHIFT;
2660 			pdb.bearer_dir_res = (uint32_t)
2661 				((bearer << PDCP_U_PLANE_PDB_BEARER_SHIFT) |
2662 				 (direction << PDCP_U_PLANE_PDB_DIR_SHIFT));
2663 
2664 			pdb.hfn_thr_res =
2665 			hfn_threshold << PDCP_U_PLANE_PDB_LONG_SN_HFN_THR_SHIFT;
2666 
2667 		} else {
2668 			/* This means 5-bit c-plane.
2669 			 * Here we use c-plane opt in pdb
2670 			 */
2671 
2672 			/* This is a HW issue. Bit 2 should be set to zero,
2673 			 * but it does not work this way. Override here.
2674 			 */
2675 			pdb.opt_res.rsvd = 0x00000002;
2676 
2677 			/* Copy relevant information from user to PDB */
2678 			pdb.hfn_res = hfn << PDCP_C_PLANE_PDB_HFN_SHIFT;
2679 			pdb.bearer_dir_res = (uint32_t)
2680 				((bearer << PDCP_C_PLANE_PDB_BEARER_SHIFT) |
2681 				(direction << PDCP_C_PLANE_PDB_DIR_SHIFT));
2682 			pdb.hfn_thr_res =
2683 			hfn_threshold << PDCP_C_PLANE_PDB_HFN_THR_SHIFT;
2684 		}
2685 
2686 		/* copy PDB in descriptor*/
2687 		__rta_out32(p, pdb.opt_res.opt);
2688 		__rta_out32(p, pdb.hfn_res);
2689 		__rta_out32(p, pdb.bearer_dir_res);
2690 		__rta_out32(p, pdb.hfn_thr_res);
2691 
2692 		return PDCP_PDB_TYPE_FULL_PDB;
2693 	}
2694 
2695 	switch (pdb_mask[cipherdata->algtype][authdata->algtype]) {
2696 	case PDCP_PDB_TYPE_NO_PDB:
2697 		break;
2698 
2699 	case PDCP_PDB_TYPE_REDUCED_PDB:
2700 		__rta_out32(p, (hfn << PDCP_C_PLANE_PDB_HFN_SHIFT));
2701 		__rta_out32(p,
2702 			    (uint32_t)((bearer <<
2703 					PDCP_C_PLANE_PDB_BEARER_SHIFT) |
2704 					(direction <<
2705 					 PDCP_C_PLANE_PDB_DIR_SHIFT)));
2706 		break;
2707 
2708 	case PDCP_PDB_TYPE_FULL_PDB:
2709 		memset(&pdb, 0x00, sizeof(struct pdcp_pdb));
2710 
2711 		/* This is a HW issue. Bit 2 should be set to zero,
2712 		 * but it does not work this way. Override here.
2713 		 */
2714 		pdb.opt_res.rsvd = 0x00000002;
2715 
2716 		/* Copy relevant information from user to PDB */
2717 		pdb.hfn_res = hfn << PDCP_C_PLANE_PDB_HFN_SHIFT;
2718 		pdb.bearer_dir_res = (uint32_t)
2719 			((bearer << PDCP_C_PLANE_PDB_BEARER_SHIFT) |
2720 			 (direction << PDCP_C_PLANE_PDB_DIR_SHIFT));
2721 		pdb.hfn_thr_res =
2722 			hfn_threshold << PDCP_C_PLANE_PDB_HFN_THR_SHIFT;
2723 
2724 		/* copy PDB in descriptor*/
2725 		__rta_out32(p, pdb.opt_res.opt);
2726 		__rta_out32(p, pdb.hfn_res);
2727 		__rta_out32(p, pdb.bearer_dir_res);
2728 		__rta_out32(p, pdb.hfn_thr_res);
2729 
2730 		break;
2731 
2732 	default:
2733 		return PDCP_PDB_TYPE_INVALID;
2734 	}
2735 
2736 	return pdb_mask[cipherdata->algtype][authdata->algtype];
2737 }
2738 
2739 /*
2740  * PDCP UPlane PDB creation function
2741  */
2742 static inline enum pdb_type_e
2743 cnstr_pdcp_u_plane_pdb(struct program *p,
2744 		       enum pdcp_sn_size sn_size,
2745 		       uint32_t hfn, unsigned short bearer,
2746 		       unsigned short direction,
2747 		       uint32_t hfn_threshold,
2748 		       struct alginfo *cipherdata,
2749 		       struct alginfo *authdata)
2750 {
2751 	struct pdcp_pdb pdb;
2752 	enum pdb_type_e pdb_type = PDCP_PDB_TYPE_FULL_PDB;
2753 	enum pdb_type_e
2754 		pdb_mask[PDCP_CIPHER_TYPE_INVALID][PDCP_AUTH_TYPE_INVALID] = {
2755 			{	/* NULL */
2756 				PDCP_PDB_TYPE_NO_PDB,		/* NULL */
2757 				PDCP_PDB_TYPE_FULL_PDB,		/* SNOW f9 */
2758 				PDCP_PDB_TYPE_FULL_PDB,		/* AES CMAC */
2759 				PDCP_PDB_TYPE_FULL_PDB		/* ZUC-I */
2760 			},
2761 			{	/* SNOW f8 */
2762 				PDCP_PDB_TYPE_FULL_PDB,		/* NULL */
2763 				PDCP_PDB_TYPE_FULL_PDB,		/* SNOW f9 */
2764 				PDCP_PDB_TYPE_REDUCED_PDB,	/* AES CMAC */
2765 				PDCP_PDB_TYPE_REDUCED_PDB	/* ZUC-I */
2766 			},
2767 			{	/* AES CTR */
2768 				PDCP_PDB_TYPE_FULL_PDB,		/* NULL */
2769 				PDCP_PDB_TYPE_REDUCED_PDB,	/* SNOW f9 */
2770 				PDCP_PDB_TYPE_FULL_PDB,		/* AES CMAC */
2771 				PDCP_PDB_TYPE_REDUCED_PDB	/* ZUC-I */
2772 			},
2773 			{	/* ZUC-E */
2774 				PDCP_PDB_TYPE_FULL_PDB,		/* NULL */
2775 				PDCP_PDB_TYPE_REDUCED_PDB,	/* SNOW f9 */
2776 				PDCP_PDB_TYPE_REDUCED_PDB,	/* AES CMAC */
2777 				PDCP_PDB_TYPE_FULL_PDB		/* ZUC-I */
2778 			},
2779 	};
2780 
2781 	/* Read options from user */
2782 	/* Depending on sequence number length, the HFN and HFN threshold
2783 	 * have different lengths.
2784 	 */
2785 	memset(&pdb, 0x00, sizeof(struct pdcp_pdb));
2786 
2787 	switch (sn_size) {
2788 	case PDCP_SN_SIZE_7:
2789 		pdb.opt_res.opt |= PDCP_U_PLANE_PDB_OPT_SHORT_SN;
2790 		pdb.hfn_res = hfn << PDCP_U_PLANE_PDB_SHORT_SN_HFN_SHIFT;
2791 		pdb.hfn_thr_res =
2792 			hfn_threshold<<PDCP_U_PLANE_PDB_SHORT_SN_HFN_THR_SHIFT;
2793 		break;
2794 
2795 	case PDCP_SN_SIZE_12:
2796 		pdb.opt_res.opt &= (uint32_t)(~PDCP_U_PLANE_PDB_OPT_SHORT_SN);
2797 		pdb.hfn_res = hfn << PDCP_U_PLANE_PDB_LONG_SN_HFN_SHIFT;
2798 		pdb.hfn_thr_res =
2799 			hfn_threshold<<PDCP_U_PLANE_PDB_LONG_SN_HFN_THR_SHIFT;
2800 		break;
2801 
2802 	case PDCP_SN_SIZE_15:
2803 		pdb.opt_res.opt = (uint32_t)(PDCP_U_PLANE_PDB_OPT_15B_SN);
2804 		pdb.hfn_res = hfn << PDCP_U_PLANE_PDB_15BIT_SN_HFN_SHIFT;
2805 		pdb.hfn_thr_res =
2806 			hfn_threshold<<PDCP_U_PLANE_PDB_15BIT_SN_HFN_THR_SHIFT;
2807 		break;
2808 
2809 	case PDCP_SN_SIZE_18:
2810 		pdb.opt_res.opt = (uint32_t)(PDCP_U_PLANE_PDB_OPT_18B_SN);
2811 		pdb.hfn_res = hfn << PDCP_U_PLANE_PDB_18BIT_SN_HFN_SHIFT;
2812 		pdb.hfn_thr_res =
2813 			hfn_threshold<<PDCP_U_PLANE_PDB_18BIT_SN_HFN_THR_SHIFT;
2814 
2815 		if (rta_sec_era <= RTA_SEC_ERA_8) {
2816 			if (cipherdata && authdata)
2817 				pdb_type = pdb_mask[cipherdata->algtype]
2818 						   [authdata->algtype];
2819 		}
2820 		break;
2821 
2822 	default:
2823 		pr_err("Invalid Sequence Number Size setting in PDB\n");
2824 		return -EINVAL;
2825 	}
2826 
2827 	pdb.bearer_dir_res = (uint32_t)
2828 				((bearer << PDCP_U_PLANE_PDB_BEARER_SHIFT) |
2829 				 (direction << PDCP_U_PLANE_PDB_DIR_SHIFT));
2830 
2831 	switch (pdb_type) {
2832 	case PDCP_PDB_TYPE_NO_PDB:
2833 		break;
2834 
2835 	case PDCP_PDB_TYPE_REDUCED_PDB:
2836 		__rta_out32(p, pdb.hfn_res);
2837 		__rta_out32(p, pdb.bearer_dir_res);
2838 		break;
2839 
2840 	case PDCP_PDB_TYPE_FULL_PDB:
2841 		/* copy PDB in descriptor*/
2842 		__rta_out32(p, pdb.opt_res.opt);
2843 		__rta_out32(p, pdb.hfn_res);
2844 		__rta_out32(p, pdb.bearer_dir_res);
2845 		__rta_out32(p, pdb.hfn_thr_res);
2846 
2847 		break;
2848 
2849 	default:
2850 		return PDCP_PDB_TYPE_INVALID;
2851 	}
2852 
2853 	return pdb_type;
2854 }
2855 /**
2856  * cnstr_shdsc_pdcp_c_plane_encap - Function for creating a PDCP Control Plane
2857  *                                  encapsulation descriptor.
2858  * @descbuf: pointer to buffer for descriptor construction
2859  * @ps: if 36/40bit addressing is desired, this parameter must be true
2860  * @swap: must be true when core endianness doesn't match SEC endianness
2861  * @hfn: starting Hyper Frame Number to be used together with the SN from the
2862  *       PDCP frames.
2863  * @sn_size: size of sequence numbers, only 5/12 bit sequence numbers are valid
2864  * @bearer: radio bearer ID
2865  * @direction: the direction of the PDCP frame (UL/DL)
2866  * @hfn_threshold: HFN value that once reached triggers a warning from SEC that
2867  *                 keys should be renegotiated at the earliest convenience.
2868  * @cipherdata: pointer to block cipher transform definitions
2869  *              Valid algorithm values are those from cipher_type_pdcp enum.
2870  * @authdata: pointer to authentication transform definitions
2871  *            Valid algorithm values are those from auth_type_pdcp enum.
2872  * @era_2_sw_hfn_ovrd: if software HFN override mechanism is desired for
2873  *                     this descriptor. Note: Can only be used for
2874  *                     SEC ERA 2.
2875  * Return: size of descriptor written in words or negative number on error.
2876  *         Once the function returns, the value of this parameter can be used
2877  *         for reclaiming the space that wasn't used for the descriptor.
2878  *
2879  * Note: descbuf must be large enough to contain a full 256 byte long
2880  * descriptor; after the function returns, by subtracting the actual number of
2881  * bytes used, the user can reuse the remaining buffer space for other purposes.
2882  */
2883 static inline int
2884 cnstr_shdsc_pdcp_c_plane_encap(uint32_t *descbuf,
2885 			       bool ps,
2886 			       bool swap,
2887 			       uint32_t hfn,
2888 			       enum pdcp_sn_size sn_size,
2889 			       unsigned char bearer,
2890 			       unsigned char direction,
2891 			       uint32_t hfn_threshold,
2892 			       struct alginfo *cipherdata,
2893 			       struct alginfo *authdata,
2894 			       unsigned char era_2_sw_hfn_ovrd)
2895 {
2896 	static int
2897 		(*pdcp_cp_fp[PDCP_CIPHER_TYPE_INVALID][PDCP_AUTH_TYPE_INVALID])
2898 			(struct program*, bool swap, struct alginfo *,
2899 			 struct alginfo *, unsigned int, enum pdcp_sn_size,
2900 			unsigned char __maybe_unused) = {
2901 		{	/* NULL */
2902 			pdcp_insert_cplane_null_op,	/* NULL */
2903 			pdcp_insert_cplane_int_only_op,	/* SNOW f9 */
2904 			pdcp_insert_cplane_int_only_op,	/* AES CMAC */
2905 			pdcp_insert_cplane_int_only_op	/* ZUC-I */
2906 		},
2907 		{	/* SNOW f8 */
2908 			pdcp_insert_cplane_enc_only_op,	/* NULL */
2909 			pdcp_insert_cplane_acc_op,	/* SNOW f9 */
2910 			pdcp_insert_cplane_snow_aes_op,	/* AES CMAC */
2911 			pdcp_insert_cplane_snow_zuc_op	/* ZUC-I */
2912 		},
2913 		{	/* AES CTR */
2914 			pdcp_insert_cplane_enc_only_op,	/* NULL */
2915 			pdcp_insert_cplane_aes_snow_op,	/* SNOW f9 */
2916 			pdcp_insert_cplane_acc_op,	/* AES CMAC */
2917 			pdcp_insert_cplane_aes_zuc_op	/* ZUC-I */
2918 		},
2919 		{	/* ZUC-E */
2920 			pdcp_insert_cplane_enc_only_op,	/* NULL */
2921 			pdcp_insert_cplane_zuc_snow_op,	/* SNOW f9 */
2922 			pdcp_insert_cplane_zuc_aes_op,	/* AES CMAC */
2923 			pdcp_insert_cplane_acc_op	/* ZUC-I */
2924 		},
2925 	};
2926 	static enum rta_share_type
2927 		desc_share[PDCP_CIPHER_TYPE_INVALID][PDCP_AUTH_TYPE_INVALID] = {
2928 		{	/* NULL */
2929 			SHR_WAIT,	/* NULL */
2930 			SHR_ALWAYS,	/* SNOW f9 */
2931 			SHR_ALWAYS,	/* AES CMAC */
2932 			SHR_ALWAYS	/* ZUC-I */
2933 		},
2934 		{	/* SNOW f8 */
2935 			SHR_ALWAYS,	/* NULL */
2936 			SHR_ALWAYS,	/* SNOW f9 */
2937 			SHR_WAIT,	/* AES CMAC */
2938 			SHR_WAIT	/* ZUC-I */
2939 		},
2940 		{	/* AES CTR */
2941 			SHR_ALWAYS,	/* NULL */
2942 			SHR_ALWAYS,	/* SNOW f9 */
2943 			SHR_ALWAYS,	/* AES CMAC */
2944 			SHR_WAIT	/* ZUC-I */
2945 		},
2946 		{	/* ZUC-E */
2947 			SHR_ALWAYS,	/* NULL */
2948 			SHR_WAIT,	/* SNOW f9 */
2949 			SHR_WAIT,	/* AES CMAC */
2950 			SHR_ALWAYS	/* ZUC-I */
2951 		},
2952 	};
2953 	enum pdb_type_e pdb_type;
2954 	struct program prg;
2955 	struct program *p = &prg;
2956 	int err;
2957 	LABEL(pdb_end);
2958 
2959 	if (rta_sec_era != RTA_SEC_ERA_2 && era_2_sw_hfn_ovrd) {
2960 		pr_err("Cannot select SW HFN override for other era than 2");
2961 		return -EINVAL;
2962 	}
2963 
2964 	if (sn_size != PDCP_SN_SIZE_12 && sn_size != PDCP_SN_SIZE_5) {
2965 		pr_err("C-plane supports only 5-bit and 12-bit sequence numbers\n");
2966 		return -EINVAL;
2967 	}
2968 
2969 	PROGRAM_CNTXT_INIT(p, descbuf, 0);
2970 	if (swap)
2971 		PROGRAM_SET_BSWAP(p);
2972 	if (ps)
2973 		PROGRAM_SET_36BIT_ADDR(p);
2974 
2975 	SHR_HDR(p, desc_share[cipherdata->algtype][authdata->algtype], 0, 0);
2976 
2977 	pdb_type = cnstr_pdcp_c_plane_pdb(p,
2978 			hfn,
2979 			sn_size,
2980 			bearer,
2981 			direction,
2982 			hfn_threshold,
2983 			cipherdata,
2984 			authdata);
2985 
2986 	SET_LABEL(p, pdb_end);
2987 
2988 	err = insert_hfn_ov_op(p, sn_size, pdb_type,
2989 			       era_2_sw_hfn_ovrd);
2990 	if (err)
2991 		return err;
2992 
2993 	err = pdcp_cp_fp[cipherdata->algtype][authdata->algtype](p,
2994 		swap,
2995 		cipherdata,
2996 		authdata,
2997 		OP_TYPE_ENCAP_PROTOCOL,
2998 		sn_size,
2999 		era_2_sw_hfn_ovrd);
3000 	if (err)
3001 		return err;
3002 
3003 	PATCH_HDR(p, 0, pdb_end);
3004 
3005 	return PROGRAM_FINALIZE(p);
3006 }
3007 
3008 /**
3009  * cnstr_shdsc_pdcp_c_plane_decap - Function for creating a PDCP Control Plane
3010  *                                  decapsulation descriptor.
3011  * @descbuf: pointer to buffer for descriptor construction
3012  * @ps: if 36/40bit addressing is desired, this parameter must be true
3013  * @swap: must be true when core endianness doesn't match SEC endianness
3014  * @hfn: starting Hyper Frame Number to be used together with the SN from the
3015  *       PDCP frames.
3016  * @sn_size: size of sequence numbers, only 5/12 bit sequence numbers are valid
3017  * @bearer: radio bearer ID
3018  * @direction: the direction of the PDCP frame (UL/DL)
3019  * @hfn_threshold: HFN value that once reached triggers a warning from SEC that
3020  *                 keys should be renegotiated at the earliest convenience.
3021  * @cipherdata: pointer to block cipher transform definitions
3022  *              Valid algorithm values are those from cipher_type_pdcp enum.
3023  * @authdata: pointer to authentication transform definitions
3024  *            Valid algorithm values are those from auth_type_pdcp enum.
3025  * @era_2_sw_hfn_ovrd: if software HFN override mechanism is desired for
3026  *                     this descriptor. Note: Can only be used for
3027  *                     SEC ERA 2.
3028  *
3029  * Return: size of descriptor written in words or negative number on error.
3030  *         Once the function returns, the value of this parameter can be used
3031  *         for reclaiming the space that wasn't used for the descriptor.
3032  *
3033  * Note: descbuf must be large enough to contain a full 256 byte long
3034  * descriptor; after the function returns, by subtracting the actual number of
3035  * bytes used, the user can reuse the remaining buffer space for other purposes.
3036  */
3037 static inline int
3038 cnstr_shdsc_pdcp_c_plane_decap(uint32_t *descbuf,
3039 			       bool ps,
3040 			       bool swap,
3041 			       uint32_t hfn,
3042 			       enum pdcp_sn_size sn_size,
3043 			       unsigned char bearer,
3044 			       unsigned char direction,
3045 			       uint32_t hfn_threshold,
3046 			       struct alginfo *cipherdata,
3047 			       struct alginfo *authdata,
3048 			       unsigned char era_2_sw_hfn_ovrd)
3049 {
3050 	static int
3051 		(*pdcp_cp_fp[PDCP_CIPHER_TYPE_INVALID][PDCP_AUTH_TYPE_INVALID])
3052 			(struct program*, bool swap, struct alginfo *,
3053 			 struct alginfo *, unsigned int, enum pdcp_sn_size,
3054 			 unsigned char) = {
3055 		{	/* NULL */
3056 			pdcp_insert_cplane_null_op,	/* NULL */
3057 			pdcp_insert_cplane_int_only_op,	/* SNOW f9 */
3058 			pdcp_insert_cplane_int_only_op,	/* AES CMAC */
3059 			pdcp_insert_cplane_int_only_op	/* ZUC-I */
3060 		},
3061 		{	/* SNOW f8 */
3062 			pdcp_insert_cplane_enc_only_op,	/* NULL */
3063 			pdcp_insert_cplane_acc_op,	/* SNOW f9 */
3064 			pdcp_insert_cplane_snow_aes_op,	/* AES CMAC */
3065 			pdcp_insert_cplane_snow_zuc_op	/* ZUC-I */
3066 		},
3067 		{	/* AES CTR */
3068 			pdcp_insert_cplane_enc_only_op,	/* NULL */
3069 			pdcp_insert_cplane_aes_snow_op,	/* SNOW f9 */
3070 			pdcp_insert_cplane_acc_op,	/* AES CMAC */
3071 			pdcp_insert_cplane_aes_zuc_op	/* ZUC-I */
3072 		},
3073 		{	/* ZUC-E */
3074 			pdcp_insert_cplane_enc_only_op,	/* NULL */
3075 			pdcp_insert_cplane_zuc_snow_op,	/* SNOW f9 */
3076 			pdcp_insert_cplane_zuc_aes_op,	/* AES CMAC */
3077 			pdcp_insert_cplane_acc_op	/* ZUC-I */
3078 		},
3079 	};
3080 	static enum rta_share_type
3081 		desc_share[PDCP_CIPHER_TYPE_INVALID][PDCP_AUTH_TYPE_INVALID] = {
3082 		{	/* NULL */
3083 			SHR_WAIT,	/* NULL */
3084 			SHR_ALWAYS,	/* SNOW f9 */
3085 			SHR_ALWAYS,	/* AES CMAC */
3086 			SHR_ALWAYS	/* ZUC-I */
3087 		},
3088 		{	/* SNOW f8 */
3089 			SHR_ALWAYS,	/* NULL */
3090 			SHR_ALWAYS,	/* SNOW f9 */
3091 			SHR_WAIT,	/* AES CMAC */
3092 			SHR_WAIT	/* ZUC-I */
3093 		},
3094 		{	/* AES CTR */
3095 			SHR_ALWAYS,	/* NULL */
3096 			SHR_ALWAYS,	/* SNOW f9 */
3097 			SHR_ALWAYS,	/* AES CMAC */
3098 			SHR_WAIT	/* ZUC-I */
3099 		},
3100 		{	/* ZUC-E */
3101 			SHR_ALWAYS,	/* NULL */
3102 			SHR_WAIT,	/* SNOW f9 */
3103 			SHR_WAIT,	/* AES CMAC */
3104 			SHR_ALWAYS	/* ZUC-I */
3105 		},
3106 	};
3107 	enum pdb_type_e pdb_type;
3108 	struct program prg;
3109 	struct program *p = &prg;
3110 	int err;
3111 	LABEL(pdb_end);
3112 
3113 	if (rta_sec_era != RTA_SEC_ERA_2 && era_2_sw_hfn_ovrd) {
3114 		pr_err("Cannot select SW HFN override for other era than 2");
3115 		return -EINVAL;
3116 	}
3117 
3118 	if (sn_size != PDCP_SN_SIZE_12 && sn_size != PDCP_SN_SIZE_5) {
3119 		pr_err("C-plane supports only 5-bit and 12-bit sequence numbers\n");
3120 		return -EINVAL;
3121 	}
3122 
3123 	PROGRAM_CNTXT_INIT(p, descbuf, 0);
3124 	if (swap)
3125 		PROGRAM_SET_BSWAP(p);
3126 	if (ps)
3127 		PROGRAM_SET_36BIT_ADDR(p);
3128 
3129 	SHR_HDR(p, desc_share[cipherdata->algtype][authdata->algtype], 0, 0);
3130 
3131 	pdb_type = cnstr_pdcp_c_plane_pdb(p,
3132 			hfn,
3133 			sn_size,
3134 			bearer,
3135 			direction,
3136 			hfn_threshold,
3137 			cipherdata,
3138 			authdata);
3139 
3140 	SET_LABEL(p, pdb_end);
3141 
3142 	err = insert_hfn_ov_op(p, sn_size, pdb_type,
3143 			       era_2_sw_hfn_ovrd);
3144 	if (err)
3145 		return err;
3146 
3147 	err = pdcp_cp_fp[cipherdata->algtype][authdata->algtype](p,
3148 		swap,
3149 		cipherdata,
3150 		authdata,
3151 		OP_TYPE_DECAP_PROTOCOL,
3152 		sn_size,
3153 		era_2_sw_hfn_ovrd);
3154 	if (err)
3155 		return err;
3156 
3157 	PATCH_HDR(p, 0, pdb_end);
3158 
3159 	return PROGRAM_FINALIZE(p);
3160 }
3161 
3162 static int
3163 pdcp_insert_uplane_with_int_op(struct program *p,
3164 			      bool swap __maybe_unused,
3165 			      struct alginfo *cipherdata,
3166 			      struct alginfo *authdata,
3167 			      enum pdcp_sn_size sn_size,
3168 			      unsigned char era_2_sw_hfn_ovrd,
3169 			      unsigned int dir)
3170 {
3171 	static int
3172 		(*pdcp_cp_fp[PDCP_CIPHER_TYPE_INVALID][PDCP_AUTH_TYPE_INVALID])
3173 			(struct program*, bool swap, struct alginfo *,
3174 			 struct alginfo *, unsigned int, enum pdcp_sn_size,
3175 			unsigned char __maybe_unused) = {
3176 		{	/* NULL */
3177 			pdcp_insert_cplane_null_op,	/* NULL */
3178 			pdcp_insert_cplane_int_only_op,	/* SNOW f9 */
3179 			pdcp_insert_cplane_int_only_op,	/* AES CMAC */
3180 			pdcp_insert_cplane_int_only_op	/* ZUC-I */
3181 		},
3182 		{	/* SNOW f8 */
3183 			pdcp_insert_cplane_enc_only_op,	/* NULL */
3184 			pdcp_insert_uplane_snow_snow_op, /* SNOW f9 */
3185 			pdcp_insert_cplane_snow_aes_op,	/* AES CMAC */
3186 			pdcp_insert_cplane_snow_zuc_op	/* ZUC-I */
3187 		},
3188 		{	/* AES CTR */
3189 			pdcp_insert_cplane_enc_only_op,	/* NULL */
3190 			pdcp_insert_cplane_aes_snow_op,	/* SNOW f9 */
3191 			pdcp_insert_uplane_aes_aes_op,	/* AES CMAC */
3192 			pdcp_insert_cplane_aes_zuc_op	/* ZUC-I */
3193 		},
3194 		{	/* ZUC-E */
3195 			pdcp_insert_cplane_enc_only_op,	/* NULL */
3196 			pdcp_insert_cplane_zuc_snow_op,	/* SNOW f9 */
3197 			pdcp_insert_cplane_zuc_aes_op,	/* AES CMAC */
3198 			pdcp_insert_uplane_zuc_zuc_op	/* ZUC-I */
3199 		},
3200 	};
3201 	int err;
3202 
3203 	err = pdcp_cp_fp[cipherdata->algtype][authdata->algtype](p,
3204 		swap,
3205 		cipherdata,
3206 		authdata,
3207 		dir,
3208 		sn_size,
3209 		era_2_sw_hfn_ovrd);
3210 	if (err)
3211 		return err;
3212 
3213 	return 0;
3214 }
3215 
3216 
3217 /**
3218  * cnstr_shdsc_pdcp_u_plane_encap - Function for creating a PDCP User Plane
3219  *                                  encapsulation descriptor.
3220  * @descbuf: pointer to buffer for descriptor construction
3221  * @ps: if 36/40bit addressing is desired, this parameter must be true
3222  * @swap: must be true when core endianness doesn't match SEC endianness
3223  * @sn_size: selects Sequence Number Size: 7/12/15 bits
3224  * @hfn: starting Hyper Frame Number to be used together with the SN from the
3225  *       PDCP frames.
3226  * @bearer: radio bearer ID
3227  * @direction: the direction of the PDCP frame (UL/DL)
3228  * @hfn_threshold: HFN value that once reached triggers a warning from SEC that
3229  *                 keys should be renegotiated at the earliest convenience.
3230  * @cipherdata: pointer to block cipher transform definitions
3231  *              Valid algorithm values are those from cipher_type_pdcp enum.
3232  * @era_2_sw_hfn_ovrd: if software HFN override mechanism is desired for
3233  *                     this descriptor. Note: Can only be used for
3234  *                     SEC ERA 2.
3235  *
3236  * Return: size of descriptor written in words or negative number on error.
3237  *         Once the function returns, the value of this parameter can be used
3238  *         for reclaiming the space that wasn't used for the descriptor.
3239  *
3240  * Note: descbuf must be large enough to contain a full 256 byte long
3241  * descriptor; after the function returns, by subtracting the actual number of
3242  * bytes used, the user can reuse the remaining buffer space for other purposes.
3243  */
3244 static inline int
3245 cnstr_shdsc_pdcp_u_plane_encap(uint32_t *descbuf,
3246 			       bool ps,
3247 			       bool swap,
3248 			       enum pdcp_sn_size sn_size,
3249 			       uint32_t hfn,
3250 			       unsigned short bearer,
3251 			       unsigned short direction,
3252 			       uint32_t hfn_threshold,
3253 			       struct alginfo *cipherdata,
3254 			       struct alginfo *authdata,
3255 			       unsigned char era_2_sw_hfn_ovrd)
3256 {
3257 	struct program prg;
3258 	struct program *p = &prg;
3259 	int err;
3260 	enum pdb_type_e pdb_type;
3261 	static enum rta_share_type
3262 		desc_share[PDCP_CIPHER_TYPE_INVALID][PDCP_AUTH_TYPE_INVALID] = {
3263 		{	/* NULL */
3264 			SHR_WAIT,	/* NULL */
3265 			SHR_ALWAYS,	/* SNOW f9 */
3266 			SHR_ALWAYS,	/* AES CMAC */
3267 			SHR_ALWAYS	/* ZUC-I */
3268 		},
3269 		{	/* SNOW f8 */
3270 			SHR_ALWAYS,	/* NULL */
3271 			SHR_ALWAYS,	/* SNOW f9 */
3272 			SHR_WAIT,	/* AES CMAC */
3273 			SHR_WAIT	/* ZUC-I */
3274 		},
3275 		{	/* AES CTR */
3276 			SHR_ALWAYS,	/* NULL */
3277 			SHR_ALWAYS,	/* SNOW f9 */
3278 			SHR_ALWAYS,	/* AES CMAC */
3279 			SHR_WAIT	/* ZUC-I */
3280 		},
3281 		{	/* ZUC-E */
3282 			SHR_ALWAYS,	/* NULL */
3283 			SHR_WAIT,	/* SNOW f9 */
3284 			SHR_WAIT,	/* AES CMAC */
3285 			SHR_WAIT	/* ZUC-I */
3286 		},
3287 	};
3288 	LABEL(pdb_end);
3289 
3290 	if (rta_sec_era != RTA_SEC_ERA_2 && era_2_sw_hfn_ovrd) {
3291 		pr_err("Cannot select SW HFN ovrd for other era than 2");
3292 		return -EINVAL;
3293 	}
3294 
3295 	if (authdata && !authdata->algtype && rta_sec_era < RTA_SEC_ERA_8) {
3296 		pr_err("Cannot use u-plane auth with era < 8");
3297 		return -EINVAL;
3298 	}
3299 
3300 	PROGRAM_CNTXT_INIT(p, descbuf, 0);
3301 	if (swap)
3302 		PROGRAM_SET_BSWAP(p);
3303 	if (ps)
3304 		PROGRAM_SET_36BIT_ADDR(p);
3305 
3306 	if (authdata)
3307 		SHR_HDR(p, desc_share[cipherdata->algtype][authdata->algtype], 0, 0);
3308 	else
3309 		SHR_HDR(p, SHR_ALWAYS, 0, 0);
3310 	pdb_type = cnstr_pdcp_u_plane_pdb(p, sn_size, hfn,
3311 					  bearer, direction, hfn_threshold,
3312 					  cipherdata, authdata);
3313 	if (pdb_type == PDCP_PDB_TYPE_INVALID) {
3314 		pr_err("Error creating PDCP UPlane PDB\n");
3315 		return -EINVAL;
3316 	}
3317 	SET_LABEL(p, pdb_end);
3318 
3319 	err = insert_hfn_ov_op(p, sn_size, pdb_type, era_2_sw_hfn_ovrd);
3320 	if (err)
3321 		return err;
3322 
3323 	switch (sn_size) {
3324 	case PDCP_SN_SIZE_7:
3325 	case PDCP_SN_SIZE_12:
3326 		switch (cipherdata->algtype) {
3327 		case PDCP_CIPHER_TYPE_ZUC:
3328 			if (rta_sec_era < RTA_SEC_ERA_5) {
3329 				pr_err("Invalid era for selected algorithm\n");
3330 				return -ENOTSUP;
3331 			}
3332 			/* fallthrough */
3333 		case PDCP_CIPHER_TYPE_AES:
3334 		case PDCP_CIPHER_TYPE_SNOW:
3335 		case PDCP_CIPHER_TYPE_NULL:
3336 			if (rta_sec_era == RTA_SEC_ERA_8 &&
3337 					authdata && authdata->algtype == 0){
3338 				err = pdcp_insert_uplane_with_int_op(p, swap,
3339 						cipherdata, authdata,
3340 						sn_size, era_2_sw_hfn_ovrd,
3341 						OP_TYPE_ENCAP_PROTOCOL);
3342 				if (err)
3343 					return err;
3344 				break;
3345 			}
3346 
3347 			if (pdb_type != PDCP_PDB_TYPE_FULL_PDB) {
3348 				pr_err("PDB type must be FULL for PROTO desc\n");
3349 				return -EINVAL;
3350 			}
3351 
3352 			/* Insert auth key if requested */
3353 			if (authdata && authdata->algtype) {
3354 				KEY(p, KEY2, authdata->key_enc_flags,
3355 				    (uint64_t)authdata->key, authdata->keylen,
3356 				    INLINE_KEY(authdata));
3357 			}
3358 			/* Insert Cipher Key */
3359 			KEY(p, KEY1, cipherdata->key_enc_flags,
3360 			    (uint64_t)cipherdata->key, cipherdata->keylen,
3361 			    INLINE_KEY(cipherdata));
3362 
3363 			if (authdata)
3364 				PROTOCOL(p, OP_TYPE_ENCAP_PROTOCOL,
3365 					 OP_PCLID_LTE_PDCP_USER_RN,
3366 					 ((uint16_t)cipherdata->algtype << 8) |
3367 					 (uint16_t)authdata->algtype);
3368 			else
3369 				PROTOCOL(p, OP_TYPE_ENCAP_PROTOCOL,
3370 					 OP_PCLID_LTE_PDCP_USER,
3371 					 (uint16_t)cipherdata->algtype);
3372 			break;
3373 		default:
3374 			pr_err("%s: Invalid encrypt algorithm selected: %d\n",
3375 			       "cnstr_pcl_shdsc_pdcp_u_plane_decap",
3376 			       cipherdata->algtype);
3377 			return -EINVAL;
3378 		}
3379 		break;
3380 
3381 	case PDCP_SN_SIZE_15:
3382 	case PDCP_SN_SIZE_18:
3383 		if (authdata) {
3384 			err = pdcp_insert_uplane_with_int_op(p, swap,
3385 					cipherdata, authdata,
3386 					sn_size, era_2_sw_hfn_ovrd,
3387 					OP_TYPE_ENCAP_PROTOCOL);
3388 			if (err)
3389 				return err;
3390 
3391 			break;
3392 		}
3393 
3394 		switch (cipherdata->algtype) {
3395 		case PDCP_CIPHER_TYPE_NULL:
3396 			insert_copy_frame_op(p,
3397 					     cipherdata,
3398 					     OP_TYPE_ENCAP_PROTOCOL);
3399 			break;
3400 
3401 		default:
3402 			err = pdcp_insert_uplane_no_int_op(p, swap, cipherdata,
3403 					OP_TYPE_ENCAP_PROTOCOL, sn_size);
3404 			if (err)
3405 				return err;
3406 			break;
3407 		}
3408 		break;
3409 
3410 	case PDCP_SN_SIZE_5:
3411 	default:
3412 		pr_err("Invalid SN size selected\n");
3413 		return -ENOTSUP;
3414 	}
3415 
3416 	PATCH_HDR(p, 0, pdb_end);
3417 	return PROGRAM_FINALIZE(p);
3418 }
3419 
3420 /**
3421  * cnstr_shdsc_pdcp_u_plane_decap - Function for creating a PDCP User Plane
3422  *                                  decapsulation descriptor.
3423  * @descbuf: pointer to buffer for descriptor construction
3424  * @ps: if 36/40bit addressing is desired, this parameter must be true
3425  * @swap: must be true when core endianness doesn't match SEC endianness
3426  * @sn_size: selects Sequence Number Size: 7/12/15 bits
3427  * @hfn: starting Hyper Frame Number to be used together with the SN from the
3428  *       PDCP frames.
3429  * @bearer: radio bearer ID
3430  * @direction: the direction of the PDCP frame (UL/DL)
3431  * @hfn_threshold: HFN value that once reached triggers a warning from SEC that
3432  *                 keys should be renegotiated at the earliest convenience.
3433  * @cipherdata: pointer to block cipher transform definitions
3434  *              Valid algorithm values are those from cipher_type_pdcp enum.
3435  * @era_2_sw_hfn_ovrd: if software HFN override mechanism is desired for
3436  *                     this descriptor. Note: Can only be used for
3437  *                     SEC ERA 2.
3438  *
3439  * Return: size of descriptor written in words or negative number on error.
3440  *         Once the function returns, the value of this parameter can be used
3441  *         for reclaiming the space that wasn't used for the descriptor.
3442  *
3443  * Note: descbuf must be large enough to contain a full 256 byte long
3444  * descriptor; after the function returns, by subtracting the actual number of
3445  * bytes used, the user can reuse the remaining buffer space for other purposes.
3446  */
3447 static inline int
3448 cnstr_shdsc_pdcp_u_plane_decap(uint32_t *descbuf,
3449 			       bool ps,
3450 			       bool swap,
3451 			       enum pdcp_sn_size sn_size,
3452 			       uint32_t hfn,
3453 			       unsigned short bearer,
3454 			       unsigned short direction,
3455 			       uint32_t hfn_threshold,
3456 			       struct alginfo *cipherdata,
3457 			       struct alginfo *authdata,
3458 			       unsigned char era_2_sw_hfn_ovrd)
3459 {
3460 	struct program prg;
3461 	struct program *p = &prg;
3462 	int err;
3463 	enum pdb_type_e pdb_type;
3464 	static enum rta_share_type
3465 		desc_share[PDCP_CIPHER_TYPE_INVALID][PDCP_AUTH_TYPE_INVALID] = {
3466 		{	/* NULL */
3467 			SHR_WAIT,	/* NULL */
3468 			SHR_ALWAYS,	/* SNOW f9 */
3469 			SHR_ALWAYS,	/* AES CMAC */
3470 			SHR_ALWAYS	/* ZUC-I */
3471 		},
3472 		{	/* SNOW f8 */
3473 			SHR_ALWAYS,	/* NULL */
3474 			SHR_ALWAYS,	/* SNOW f9 */
3475 			SHR_WAIT,	/* AES CMAC */
3476 			SHR_WAIT	/* ZUC-I */
3477 		},
3478 		{	/* AES CTR */
3479 			SHR_ALWAYS,	/* NULL */
3480 			SHR_ALWAYS,	/* SNOW f9 */
3481 			SHR_ALWAYS,	/* AES CMAC */
3482 			SHR_WAIT	/* ZUC-I */
3483 		},
3484 		{	/* ZUC-E */
3485 			SHR_ALWAYS,	/* NULL */
3486 			SHR_WAIT,	/* SNOW f9 */
3487 			SHR_WAIT,	/* AES CMAC */
3488 			SHR_WAIT	/* ZUC-I */
3489 		},
3490 	};
3491 
3492 	LABEL(pdb_end);
3493 
3494 	if (rta_sec_era != RTA_SEC_ERA_2 && era_2_sw_hfn_ovrd) {
3495 		pr_err("Cannot select SW HFN override for other era than 2");
3496 		return -EINVAL;
3497 	}
3498 
3499 	if (authdata && !authdata->algtype && rta_sec_era < RTA_SEC_ERA_8) {
3500 		pr_err("Cannot use u-plane auth with era < 8");
3501 		return -EINVAL;
3502 	}
3503 
3504 	PROGRAM_CNTXT_INIT(p, descbuf, 0);
3505 	if (swap)
3506 		PROGRAM_SET_BSWAP(p);
3507 	if (ps)
3508 		PROGRAM_SET_36BIT_ADDR(p);
3509 	if (authdata)
3510 		SHR_HDR(p, desc_share[cipherdata->algtype][authdata->algtype], 0, 0);
3511 	else
3512 		SHR_HDR(p, SHR_ALWAYS, 0, 0);
3513 
3514 	pdb_type = cnstr_pdcp_u_plane_pdb(p, sn_size, hfn, bearer,
3515 					  direction, hfn_threshold,
3516 					  cipherdata, authdata);
3517 	if (pdb_type == PDCP_PDB_TYPE_INVALID) {
3518 		pr_err("Error creating PDCP UPlane PDB\n");
3519 		return -EINVAL;
3520 	}
3521 	SET_LABEL(p, pdb_end);
3522 
3523 	err = insert_hfn_ov_op(p, sn_size, pdb_type, era_2_sw_hfn_ovrd);
3524 	if (err)
3525 		return err;
3526 
3527 	switch (sn_size) {
3528 	case PDCP_SN_SIZE_7:
3529 	case PDCP_SN_SIZE_12:
3530 		switch (cipherdata->algtype) {
3531 		case PDCP_CIPHER_TYPE_ZUC:
3532 			if (rta_sec_era < RTA_SEC_ERA_5) {
3533 				pr_err("Invalid era for selected algorithm\n");
3534 				return -ENOTSUP;
3535 			}
3536 			/* fallthrough */
3537 		case PDCP_CIPHER_TYPE_AES:
3538 		case PDCP_CIPHER_TYPE_SNOW:
3539 		case PDCP_CIPHER_TYPE_NULL:
3540 			if (pdb_type != PDCP_PDB_TYPE_FULL_PDB) {
3541 				pr_err("PDB type must be FULL for PROTO desc\n");
3542 				return -EINVAL;
3543 			}
3544 
3545 			/* Insert auth key if requested */
3546 			if (authdata && authdata->algtype)
3547 				KEY(p, KEY2, authdata->key_enc_flags,
3548 				    (uint64_t)authdata->key, authdata->keylen,
3549 				    INLINE_KEY(authdata));
3550 			else if (authdata && authdata->algtype == 0) {
3551 				err = pdcp_insert_uplane_with_int_op(p, swap,
3552 						cipherdata, authdata,
3553 						sn_size, era_2_sw_hfn_ovrd,
3554 						OP_TYPE_DECAP_PROTOCOL);
3555 				if (err)
3556 					return err;
3557 				break;
3558 			}
3559 
3560 			/* Insert Cipher Key */
3561 			KEY(p, KEY1, cipherdata->key_enc_flags,
3562 			    cipherdata->key, cipherdata->keylen,
3563 			    INLINE_KEY(cipherdata));
3564 			if (authdata)
3565 				PROTOCOL(p, OP_TYPE_DECAP_PROTOCOL,
3566 					 OP_PCLID_LTE_PDCP_USER_RN,
3567 					 ((uint16_t)cipherdata->algtype << 8) |
3568 					 (uint16_t)authdata->algtype);
3569 			else
3570 				PROTOCOL(p, OP_TYPE_DECAP_PROTOCOL,
3571 					 OP_PCLID_LTE_PDCP_USER,
3572 					 (uint16_t)cipherdata->algtype);
3573 			break;
3574 		default:
3575 			pr_err("%s: Invalid encrypt algorithm selected: %d\n",
3576 			       "cnstr_pcl_shdsc_pdcp_u_plane_decap",
3577 			       cipherdata->algtype);
3578 			return -EINVAL;
3579 		}
3580 		break;
3581 
3582 	case PDCP_SN_SIZE_15:
3583 	case PDCP_SN_SIZE_18:
3584 		if (authdata) {
3585 			err = pdcp_insert_uplane_with_int_op(p, swap,
3586 					cipherdata, authdata,
3587 					sn_size, era_2_sw_hfn_ovrd,
3588 					OP_TYPE_DECAP_PROTOCOL);
3589 			if (err)
3590 				return err;
3591 
3592 			break;
3593 		}
3594 
3595 		switch (cipherdata->algtype) {
3596 		case PDCP_CIPHER_TYPE_NULL:
3597 			insert_copy_frame_op(p,
3598 					     cipherdata,
3599 					     OP_TYPE_DECAP_PROTOCOL);
3600 			break;
3601 
3602 		default:
3603 			err = pdcp_insert_uplane_no_int_op(p, swap, cipherdata,
3604 				OP_TYPE_DECAP_PROTOCOL, sn_size);
3605 			if (err)
3606 				return err;
3607 			break;
3608 		}
3609 		break;
3610 
3611 	case PDCP_SN_SIZE_5:
3612 	default:
3613 		pr_err("Invalid SN size selected\n");
3614 		return -ENOTSUP;
3615 	}
3616 
3617 	PATCH_HDR(p, 0, pdb_end);
3618 	return PROGRAM_FINALIZE(p);
3619 }
3620 
3621 /**
3622  * cnstr_shdsc_pdcp_short_mac - Function for creating a PDCP Short MAC
3623  *                              descriptor.
3624  * @descbuf: pointer to buffer for descriptor construction
3625  * @ps: if 36/40bit addressing is desired, this parameter must be true
3626  * @swap: must be true when core endianness doesn't match SEC endianness
3627  * @authdata: pointer to authentication transform definitions
3628  *            Valid algorithm values are those from auth_type_pdcp enum.
3629  *
3630  * Return: size of descriptor written in words or negative number on error.
3631  *         Once the function returns, the value of this parameter can be used
3632  *         for reclaiming the space that wasn't used for the descriptor.
3633  *
3634  * Note: descbuf must be large enough to contain a full 256 byte long
3635  * descriptor; after the function returns, by subtracting the actual number of
3636  * bytes used, the user can reuse the remaining buffer space for other purposes.
3637  */
3638 static inline int
3639 cnstr_shdsc_pdcp_short_mac(uint32_t *descbuf,
3640 			   bool ps,
3641 			   bool swap,
3642 			   struct alginfo *authdata)
3643 {
3644 	struct program prg;
3645 	struct program *p = &prg;
3646 	uint32_t iv[3] = {0, 0, 0};
3647 	LABEL(local_offset);
3648 	REFERENCE(move_cmd_read_descbuf);
3649 	REFERENCE(move_cmd_write_descbuf);
3650 
3651 	PROGRAM_CNTXT_INIT(p, descbuf, 0);
3652 	if (swap)
3653 		PROGRAM_SET_BSWAP(p);
3654 	if (ps)
3655 		PROGRAM_SET_36BIT_ADDR(p);
3656 
3657 	SHR_HDR(p, SHR_ALWAYS, 1, 0);
3658 
3659 	if (rta_sec_era > RTA_SEC_ERA_2) {
3660 		MATHB(p, SEQINSZ, SUB, ZERO, VSEQINSZ, 4, 0);
3661 		MATHB(p, SEQINSZ, SUB, ZERO, MATH1, 4, 0);
3662 	} else {
3663 		MATHB(p, SEQINSZ, ADD, ONE, MATH1, 4, 0);
3664 		MATHB(p, MATH1, SUB, ONE, MATH1, 4, 0);
3665 		MATHB(p, ZERO, ADD, MATH1, VSEQINSZ, 4, 0);
3666 		MOVE(p, MATH1, 0, MATH0, 0, 8, IMMED);
3667 
3668 		/*
3669 		 * Since MOVELEN is available only starting with
3670 		 * SEC ERA 3, use poor man's MOVELEN: create a MOVE
3671 		 * command dynamically by writing the length from M1 by
3672 		 * OR-ing the command in the M1 register and MOVE the
3673 		 * result into the descriptor buffer. Care must be taken
3674 		 * wrt. the location of the command because of SEC
3675 		 * pipelining. The actual MOVEs are written at the end
3676 		 * of the descriptor due to calculations needed on the
3677 		 * offset in the descriptor for the MOVE command.
3678 		 */
3679 		move_cmd_read_descbuf = MOVE(p, DESCBUF, 0, MATH0, 0, 6,
3680 					     IMMED);
3681 		move_cmd_write_descbuf = MOVE(p, MATH0, 0, DESCBUF, 0, 8,
3682 					      WAITCOMP | IMMED);
3683 	}
3684 	MATHB(p, ZERO, ADD, MATH1, VSEQOUTSZ, 4, 0);
3685 
3686 	switch (authdata->algtype) {
3687 	case PDCP_AUTH_TYPE_NULL:
3688 		SEQFIFOSTORE(p, MSG, 0, 0, VLF);
3689 		if (rta_sec_era > RTA_SEC_ERA_2) {
3690 			MOVE(p, AB1, 0, OFIFO, 0, MATH1, 0);
3691 		} else {
3692 			SET_LABEL(p, local_offset);
3693 
3694 			/* Shut off automatic Info FIFO entries */
3695 			LOAD(p, 0, DCTRL, LDOFF_DISABLE_AUTO_NFIFO, 0, IMMED);
3696 
3697 			/* Placeholder for MOVE command with length from M1
3698 			 * register
3699 			 */
3700 			MOVE(p, IFIFOAB1, 0, OFIFO, 0, 0, IMMED);
3701 
3702 			/* Enable automatic Info FIFO entries */
3703 			LOAD(p, 0, DCTRL, LDOFF_ENABLE_AUTO_NFIFO, 0, IMMED);
3704 		}
3705 
3706 		LOAD(p, (uintptr_t)iv, MATH0, 0, 8, IMMED | COPY);
3707 		SEQFIFOLOAD(p, MSG1, 0, VLF | LAST1 | LAST2 | FLUSH1);
3708 		SEQSTORE(p, MATH0, 0, 4, 0);
3709 
3710 		break;
3711 
3712 	case PDCP_AUTH_TYPE_SNOW:
3713 		iv[0] = 0xFFFFFFFF;
3714 		iv[1] = swap ? swab32(0x04000000) : 0x04000000;
3715 		iv[2] = swap ? swab32(0xF8000000) : 0xF8000000;
3716 
3717 		KEY(p, KEY2, authdata->key_enc_flags, authdata->key,
3718 		    authdata->keylen, INLINE_KEY(authdata));
3719 		LOAD(p, (uintptr_t)&iv, CONTEXT2, 0, 12, IMMED | COPY);
3720 		ALG_OPERATION(p, OP_ALG_ALGSEL_SNOW_F9,
3721 			      OP_ALG_AAI_F9,
3722 			      OP_ALG_AS_INITFINAL,
3723 			      ICV_CHECK_DISABLE,
3724 			      DIR_ENC);
3725 		SEQFIFOSTORE(p, MSG, 0, 0, VLF);
3726 
3727 		if (rta_sec_era > RTA_SEC_ERA_2) {
3728 			MOVE(p, AB1, 0, OFIFO, 0, MATH1, 0);
3729 		} else {
3730 			SET_LABEL(p, local_offset);
3731 
3732 
3733 			/* Shut off automatic Info FIFO entries */
3734 			LOAD(p, 0, DCTRL, LDOFF_DISABLE_AUTO_NFIFO, 0, IMMED);
3735 
3736 			/* Placeholder for MOVE command with length from M1
3737 			 * register
3738 			 */
3739 			MOVE(p, IFIFOAB1, 0, OFIFO, 0, 0, IMMED);
3740 
3741 			/* Enable automatic Info FIFO entries */
3742 			LOAD(p, 0, DCTRL, LDOFF_ENABLE_AUTO_NFIFO, 0, IMMED);
3743 		}
3744 		SEQFIFOLOAD(p, MSGINSNOOP, 0, VLF | LAST1 | LAST2 | FLUSH1);
3745 		SEQSTORE(p, CONTEXT2, 0, 4, 0);
3746 
3747 		break;
3748 
3749 	case PDCP_AUTH_TYPE_AES:
3750 		iv[0] = 0xFFFFFFFF;
3751 		iv[1] = swap ? swab32(0xFC000000) : 0xFC000000;
3752 		iv[2] = 0x00000000; /* unused */
3753 
3754 		KEY(p, KEY1, authdata->key_enc_flags, authdata->key,
3755 		    authdata->keylen, INLINE_KEY(authdata));
3756 		LOAD(p, (uintptr_t)&iv, MATH0, 0, 8, IMMED | COPY);
3757 		MOVE(p, MATH0, 0, IFIFOAB1, 0, 8, IMMED);
3758 		ALG_OPERATION(p, OP_ALG_ALGSEL_AES,
3759 			      OP_ALG_AAI_CMAC,
3760 			      OP_ALG_AS_INITFINAL,
3761 			      ICV_CHECK_DISABLE,
3762 			      DIR_ENC);
3763 		SEQFIFOSTORE(p, MSG, 0, 0, VLF);
3764 
3765 		if (rta_sec_era > RTA_SEC_ERA_2) {
3766 			MOVE(p, AB2, 0, OFIFO, 0, MATH1, 0);
3767 		} else {
3768 			SET_LABEL(p, local_offset);
3769 
3770 			/* Shut off automatic Info FIFO entries */
3771 			LOAD(p, 0, DCTRL, LDOFF_DISABLE_AUTO_NFIFO, 0, IMMED);
3772 
3773 			/* Placeholder for MOVE command with length from M1
3774 			 * register
3775 			 */
3776 			MOVE(p, IFIFOAB2, 0, OFIFO, 0, 0, IMMED);
3777 
3778 			/* Enable automatic Info FIFO entries */
3779 			LOAD(p, 0, DCTRL, LDOFF_ENABLE_AUTO_NFIFO, 0, IMMED);
3780 		}
3781 		SEQFIFOLOAD(p, MSGINSNOOP, 0, VLF | LAST1 | LAST2 | FLUSH1);
3782 		SEQSTORE(p, CONTEXT1, 0, 4, 0);
3783 
3784 		break;
3785 
3786 	case PDCP_AUTH_TYPE_ZUC:
3787 		if (rta_sec_era < RTA_SEC_ERA_5) {
3788 			pr_err("Invalid era for selected algorithm\n");
3789 			return -ENOTSUP;
3790 		}
3791 		iv[0] = 0xFFFFFFFF;
3792 		iv[1] = swap ? swab32(0xFC000000) : 0xFC000000;
3793 		iv[2] = 0x00000000; /* unused */
3794 
3795 		KEY(p, KEY2, authdata->key_enc_flags, authdata->key,
3796 		    authdata->keylen, INLINE_KEY(authdata));
3797 		LOAD(p, (uintptr_t)&iv, CONTEXT2, 0, 12, IMMED | COPY);
3798 		ALG_OPERATION(p, OP_ALG_ALGSEL_ZUCA,
3799 			      OP_ALG_AAI_F9,
3800 			      OP_ALG_AS_INITFINAL,
3801 			      ICV_CHECK_DISABLE,
3802 			      DIR_ENC);
3803 		SEQFIFOSTORE(p, MSG, 0, 0, VLF);
3804 		MOVE(p, AB1, 0, OFIFO, 0, MATH1, 0);
3805 		SEQFIFOLOAD(p, MSGINSNOOP, 0, VLF | LAST1 | LAST2 | FLUSH1);
3806 		SEQSTORE(p, CONTEXT2, 0, 4, 0);
3807 
3808 		break;
3809 
3810 	default:
3811 		pr_err("%s: Invalid integrity algorithm selected: %d\n",
3812 		       "cnstr_shdsc_pdcp_short_mac", authdata->algtype);
3813 		return -EINVAL;
3814 	}
3815 
3816 
3817 	if (rta_sec_era < RTA_SEC_ERA_3) {
3818 		PATCH_MOVE(p, move_cmd_read_descbuf, local_offset);
3819 		PATCH_MOVE(p, move_cmd_write_descbuf, local_offset);
3820 	}
3821 
3822 	return PROGRAM_FINALIZE(p);
3823 }
3824 
3825 #endif /* __DESC_PDCP_H__ */
3826