net/octeontx2: support 24B custom L2 header parsing
[dpdk.git] / drivers / common / dpaax / caamflib / desc / pdcp.h
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_ALWAYS      /* 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_ALWAYS      /* 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__ */