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