common/dpaax: fix 12-bit null auth case
[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         pkeyjump = JUMP(p, keyjump, LOCAL_JUMP, ALL_TRUE, SHRD | SELF | BOTH);
1891         KEY(p, KEY1, cipherdata->key_enc_flags, cipherdata->key,
1892             cipherdata->keylen, INLINE_KEY(cipherdata));
1893         KEY(p, KEY2, authdata->key_enc_flags, authdata->key, authdata->keylen,
1894             INLINE_KEY(authdata));
1895
1896         SET_LABEL(p, keyjump);
1897
1898         if ((rta_sec_era >= RTA_SEC_ERA_8 && sn_size != PDCP_SN_SIZE_18) ||
1899                 (rta_sec_era == RTA_SEC_ERA_10)) {
1900                 int pclid;
1901
1902                 if (sn_size == PDCP_SN_SIZE_5)
1903                         pclid = OP_PCLID_LTE_PDCP_CTRL_MIXED;
1904                 else
1905                         pclid = OP_PCLID_LTE_PDCP_USER_RN;
1906
1907                 PROTOCOL(p, dir, pclid,
1908                          ((uint16_t)cipherdata->algtype << 8) |
1909                          (uint16_t)authdata->algtype);
1910                 return 0;
1911         }
1912         /* Non-proto is supported only for 5bit cplane and 18bit uplane */
1913         switch (sn_size) {
1914         case PDCP_SN_SIZE_5:
1915                 offset = 7;
1916                 length = 1;
1917                 sn_mask = (swap == false) ? PDCP_C_PLANE_SN_MASK :
1918                                         PDCP_C_PLANE_SN_MASK_BE;
1919                 break;
1920         case PDCP_SN_SIZE_18:
1921                 offset = 5;
1922                 length = 3;
1923                 sn_mask = (swap == false) ? PDCP_U_PLANE_18BIT_SN_MASK :
1924                                         PDCP_U_PLANE_18BIT_SN_MASK_BE;
1925                 break;
1926         case PDCP_SN_SIZE_7:
1927         case PDCP_SN_SIZE_12:
1928         case PDCP_SN_SIZE_15:
1929                 pr_err("Invalid sn_size for %s\n", __func__);
1930                 return -ENOTSUP;
1931
1932         }
1933
1934         SEQLOAD(p, MATH0, offset, length, 0);
1935         JUMP(p, 1, LOCAL_JUMP, ALL_TRUE, CALM);
1936         MOVEB(p, MATH0, offset, IFIFOAB2, 0, length, IMMED);
1937         MATHB(p, MATH0, AND, sn_mask, MATH1, 8, IFB | IMMED2);
1938
1939         MATHB(p, MATH1, SHLD, MATH1, MATH1, 8, 0);
1940         MOVEB(p, DESCBUF, 4, MATH2, 0, 8, WAITCOMP | IMMED);
1941         MATHB(p, MATH1, OR, MATH2, MATH2, 8, 0);
1942         MOVEB(p, MATH2, 0, CONTEXT1, 0, 8, IMMED);
1943         MOVEB(p, MATH2, 0, CONTEXT2, 0, 8, WAITCOMP | IMMED);
1944
1945         if (dir == OP_TYPE_ENCAP_PROTOCOL)
1946                 MATHB(p, SEQINSZ, ADD, PDCP_MAC_I_LEN, VSEQOUTSZ, 4, IMMED2);
1947         else
1948                 MATHB(p, SEQINSZ, SUB, PDCP_MAC_I_LEN, VSEQOUTSZ, 4, IMMED2);
1949
1950         MATHB(p, SEQINSZ, SUB, ZERO, VSEQINSZ, 4, 0);
1951         SEQSTORE(p, MATH0, offset, length, 0);
1952
1953         if (dir == OP_TYPE_ENCAP_PROTOCOL) {
1954                 SEQFIFOSTORE(p, MSG, 0, 0, VLF);
1955                 SEQFIFOLOAD(p, MSGINSNOOP, 0, VLF | LAST2);
1956         } else {
1957                 SEQFIFOSTORE(p, MSG, 0, 0, VLF | CONT);
1958                 SEQFIFOLOAD(p, MSGOUTSNOOP, 0, VLF | LAST1 | FLUSH1);
1959         }
1960
1961         ALG_OPERATION(p, OP_ALG_ALGSEL_ZUCA,
1962                       OP_ALG_AAI_F9,
1963                       OP_ALG_AS_INITFINAL,
1964                       dir == OP_TYPE_ENCAP_PROTOCOL ?
1965                              ICV_CHECK_DISABLE : ICV_CHECK_ENABLE,
1966                       DIR_ENC);
1967
1968         ALG_OPERATION(p, OP_ALG_ALGSEL_SNOW_F8,
1969                       OP_ALG_AAI_F8,
1970                       OP_ALG_AS_INITFINAL,
1971                       ICV_CHECK_DISABLE,
1972                       dir == OP_TYPE_ENCAP_PROTOCOL ? DIR_ENC : DIR_DEC);
1973         if (dir == OP_TYPE_ENCAP_PROTOCOL) {
1974                 MOVE(p, CONTEXT2, 0, IFIFOAB1, 0, 4, LAST1 | FLUSH1 | IMMED);
1975         } else {
1976                 /* Save ICV */
1977                 MOVE(p, OFIFO, 0, MATH0, 0, 4, IMMED);
1978                 LOAD(p, NFIFOENTRY_STYPE_ALTSOURCE |
1979                      NFIFOENTRY_DEST_CLASS2 |
1980                      NFIFOENTRY_DTYPE_ICV |
1981                      NFIFOENTRY_LC2 | 4, NFIFO_SZL, 0, 4, IMMED);
1982                 MOVE(p, MATH0, 0, ALTSOURCE, 0, 4, WAITCOMP | IMMED);
1983         }
1984
1985         /* Reset ZUCA mode and done interrupt */
1986         LOAD(p, CLRW_CLR_C2MODE, CLRW, 0, 4, IMMED);
1987         LOAD(p, CIRQ_ZADI, ICTRL, 0, 4, IMMED);
1988
1989         PATCH_JUMP(p, pkeyjump, keyjump);
1990         return 0;
1991 }
1992
1993 static inline int
1994 pdcp_insert_cplane_aes_zuc_op(struct program *p,
1995                               bool swap __maybe_unused,
1996                               struct alginfo *cipherdata,
1997                               struct alginfo *authdata,
1998                               unsigned int dir,
1999                               enum pdcp_sn_size sn_size,
2000                               unsigned char era_2_sw_hfn_ovrd __maybe_unused)
2001 {
2002         uint32_t offset = 0, length = 0, sn_mask = 0;
2003         LABEL(keyjump);
2004         REFERENCE(pkeyjump);
2005
2006         if (rta_sec_era < RTA_SEC_ERA_5) {
2007                 pr_err("Invalid era for selected algorithm\n");
2008                 return -ENOTSUP;
2009         }
2010
2011         pkeyjump = JUMP(p, keyjump, LOCAL_JUMP, ALL_TRUE, SHRD | SELF | BOTH);
2012         KEY(p, KEY1, cipherdata->key_enc_flags, cipherdata->key,
2013             cipherdata->keylen, INLINE_KEY(cipherdata));
2014         KEY(p, KEY2, authdata->key_enc_flags, authdata->key, authdata->keylen,
2015             INLINE_KEY(authdata));
2016
2017         if ((rta_sec_era >= RTA_SEC_ERA_8 && sn_size != PDCP_SN_SIZE_18) ||
2018                 (rta_sec_era == RTA_SEC_ERA_10)) {
2019                 int pclid;
2020
2021                 if (sn_size == PDCP_SN_SIZE_5)
2022                         pclid = OP_PCLID_LTE_PDCP_CTRL_MIXED;
2023                 else
2024                         pclid = OP_PCLID_LTE_PDCP_USER_RN;
2025
2026                 PROTOCOL(p, dir, pclid,
2027                          ((uint16_t)cipherdata->algtype << 8) |
2028                          (uint16_t)authdata->algtype);
2029
2030                 return 0;
2031         }
2032         /* Non-proto is supported only for 5bit cplane and 18bit uplane */
2033         switch (sn_size) {
2034         case PDCP_SN_SIZE_5:
2035                 offset = 7;
2036                 length = 1;
2037                 sn_mask = (swap == false) ? PDCP_C_PLANE_SN_MASK :
2038                                         PDCP_C_PLANE_SN_MASK_BE;
2039                 break;
2040         case PDCP_SN_SIZE_18:
2041                 offset = 5;
2042                 length = 3;
2043                 sn_mask = (swap == false) ? PDCP_U_PLANE_18BIT_SN_MASK :
2044                                         PDCP_U_PLANE_18BIT_SN_MASK_BE;
2045                 break;
2046         case PDCP_SN_SIZE_7:
2047         case PDCP_SN_SIZE_12:
2048         case PDCP_SN_SIZE_15:
2049                 pr_err("Invalid sn_size for %s\n", __func__);
2050                 return -ENOTSUP;
2051
2052         }
2053
2054         SET_LABEL(p, keyjump);
2055         SEQLOAD(p, MATH0, offset, length, 0);
2056         JUMP(p, 1, LOCAL_JUMP, ALL_TRUE, CALM);
2057         MOVEB(p, MATH0, offset, IFIFOAB2, 0, length, IMMED);
2058         MATHB(p, MATH0, AND, sn_mask, MATH1, 8, IFB | IMMED2);
2059
2060         MATHB(p, MATH1, SHLD, MATH1, MATH1, 8, 0);
2061         MOVEB(p, DESCBUF, 4, MATH2, 0, 8, WAITCOMP | IMMED);
2062         MATHB(p, MATH1, OR, MATH2, MATH2, 8, 0);
2063         MOVEB(p, MATH2, 0, CONTEXT1, 16, 8, IMMED);
2064         MOVEB(p, MATH2, 0, CONTEXT2, 0, 8, WAITCOMP | IMMED);
2065
2066         if (dir == OP_TYPE_ENCAP_PROTOCOL)
2067                 MATHB(p, SEQINSZ, ADD, PDCP_MAC_I_LEN, VSEQOUTSZ, 4, IMMED2);
2068         else
2069                 MATHB(p, SEQINSZ, SUB, PDCP_MAC_I_LEN, VSEQOUTSZ, 4, IMMED2);
2070
2071         MATHB(p, SEQINSZ, SUB, ZERO, VSEQINSZ, 4, 0);
2072         SEQSTORE(p, MATH0, offset, length, 0);
2073
2074         if (dir == OP_TYPE_ENCAP_PROTOCOL) {
2075                 SEQFIFOSTORE(p, MSG, 0, 0, VLF);
2076                 SEQFIFOLOAD(p, MSGINSNOOP, 0, VLF | LAST2);
2077         } else {
2078                 SEQFIFOSTORE(p, MSG, 0, 0, VLF | CONT);
2079                 SEQFIFOLOAD(p, MSGOUTSNOOP, 0, VLF | LAST1 | FLUSH1);
2080         }
2081
2082         ALG_OPERATION(p, OP_ALG_ALGSEL_ZUCA,
2083                       OP_ALG_AAI_F9,
2084                       OP_ALG_AS_INITFINAL,
2085                       dir == OP_TYPE_ENCAP_PROTOCOL ?
2086                              ICV_CHECK_DISABLE : ICV_CHECK_ENABLE,
2087                       DIR_ENC);
2088
2089         ALG_OPERATION(p, OP_ALG_ALGSEL_AES,
2090                       OP_ALG_AAI_CTR,
2091                       OP_ALG_AS_INITFINAL,
2092                       ICV_CHECK_DISABLE,
2093                       dir == OP_TYPE_ENCAP_PROTOCOL ? DIR_ENC : DIR_DEC);
2094
2095         if (dir == OP_TYPE_ENCAP_PROTOCOL) {
2096                 MOVE(p, CONTEXT2, 0, IFIFOAB1, 0, 4, LAST1 | FLUSH1 | IMMED);
2097         } else {
2098                 /* Save ICV */
2099                 MOVE(p, OFIFO, 0, MATH0, 0, 4, IMMED);
2100
2101                 LOAD(p, NFIFOENTRY_STYPE_ALTSOURCE |
2102                      NFIFOENTRY_DEST_CLASS2 |
2103                      NFIFOENTRY_DTYPE_ICV |
2104                      NFIFOENTRY_LC2 | 4, NFIFO_SZL, 0, 4, IMMED);
2105                 MOVE(p, MATH0, 0, ALTSOURCE, 0, 4, WAITCOMP | IMMED);
2106         }
2107
2108         /* Reset ZUCA mode and done interrupt */
2109         LOAD(p, CLRW_CLR_C2MODE, CLRW, 0, 4, IMMED);
2110         LOAD(p, CIRQ_ZADI, ICTRL, 0, 4, IMMED);
2111
2112         PATCH_JUMP(p, pkeyjump, keyjump);
2113
2114         return 0;
2115 }
2116
2117 static inline int
2118 pdcp_insert_cplane_zuc_snow_op(struct program *p,
2119                                bool swap __maybe_unused,
2120                                struct alginfo *cipherdata,
2121                                struct alginfo *authdata,
2122                                unsigned int dir,
2123                                enum pdcp_sn_size sn_size,
2124                                unsigned char era_2_sw_hfn_ovrd __maybe_unused)
2125 {
2126         uint32_t offset = 0, length = 0, sn_mask = 0;
2127         LABEL(keyjump);
2128         REFERENCE(pkeyjump);
2129
2130         if (rta_sec_era < RTA_SEC_ERA_5) {
2131                 pr_err("Invalid era for selected algorithm\n");
2132                 return -ENOTSUP;
2133         }
2134
2135         pkeyjump = JUMP(p, keyjump, LOCAL_JUMP, ALL_TRUE, SHRD | SELF | BOTH);
2136         KEY(p, KEY1, cipherdata->key_enc_flags, cipherdata->key,
2137             cipherdata->keylen, INLINE_KEY(cipherdata));
2138         KEY(p, KEY2, authdata->key_enc_flags, authdata->key, authdata->keylen,
2139             INLINE_KEY(authdata));
2140
2141         if ((rta_sec_era >= RTA_SEC_ERA_8 && sn_size != PDCP_SN_SIZE_18) ||
2142                 (rta_sec_era == RTA_SEC_ERA_10)) {
2143                 int pclid;
2144
2145                 if (sn_size == PDCP_SN_SIZE_5)
2146                         pclid = OP_PCLID_LTE_PDCP_CTRL_MIXED;
2147                 else
2148                         pclid = OP_PCLID_LTE_PDCP_USER_RN;
2149
2150                 PROTOCOL(p, dir, pclid,
2151                          ((uint16_t)cipherdata->algtype << 8) |
2152                          (uint16_t)authdata->algtype);
2153
2154                 return 0;
2155         }
2156         /* Non-proto is supported only for 5bit cplane and 18bit uplane */
2157         switch (sn_size) {
2158         case PDCP_SN_SIZE_5:
2159                 offset = 7;
2160                 length = 1;
2161                 sn_mask = (swap == false) ? PDCP_C_PLANE_SN_MASK :
2162                                         PDCP_C_PLANE_SN_MASK_BE;
2163                 break;
2164         case PDCP_SN_SIZE_18:
2165                 offset = 5;
2166                 length = 3;
2167                 sn_mask = (swap == false) ? PDCP_U_PLANE_18BIT_SN_MASK :
2168                                         PDCP_U_PLANE_18BIT_SN_MASK_BE;
2169                 break;
2170         case PDCP_SN_SIZE_7:
2171         case PDCP_SN_SIZE_12:
2172         case PDCP_SN_SIZE_15:
2173                 pr_err("Invalid sn_size for %s\n", __func__);
2174                 return -ENOTSUP;
2175
2176         }
2177         SET_LABEL(p, keyjump);
2178         SEQLOAD(p, MATH0, offset, length, 0);
2179         JUMP(p, 1, LOCAL_JUMP, ALL_TRUE, CALM);
2180         MOVEB(p, MATH0, offset, IFIFOAB2, 0, length, IMMED);
2181         MATHB(p, MATH0, AND, sn_mask, MATH1, 8, IFB | IMMED2);
2182
2183         MATHB(p, MATH1, SHLD, MATH1, MATH1, 8, 0);
2184         MOVEB(p, DESCBUF, 4, MATH2, 0, 8, WAITCOMP | IMMED);
2185         MATHB(p, MATH1, OR, MATH2, MATH1, 8, 0);
2186         MOVEB(p, MATH1, 0, CONTEXT1, 0, 8, IMMED);
2187         MOVEB(p, MATH1, 0, CONTEXT2, 0, 4, IMMED);
2188         if (swap == false) {
2189                 MATHB(p, MATH1, AND, upper_32_bits(PDCP_BEARER_MASK), MATH2,
2190                       4, IMMED2);
2191                 MATHB(p, MATH1, AND, lower_32_bits(PDCP_DIR_MASK), MATH3,
2192                       4, IMMED2);
2193         } else {
2194                 MATHB(p, MATH1, AND, lower_32_bits(PDCP_BEARER_MASK_BE), MATH2,
2195                         4, IMMED2);
2196                 MATHB(p, MATH1, AND, upper_32_bits(PDCP_DIR_MASK_BE), MATH3,
2197                         4, IMMED2);
2198         }
2199         MATHB(p, MATH3, SHLD, MATH3, MATH3, 8, 0);
2200         MOVEB(p, MATH2, 4, OFIFO, 0, 12, IMMED);
2201         MOVE(p, OFIFO, 0, CONTEXT2, 4, 12, IMMED);
2202
2203         if (dir == OP_TYPE_ENCAP_PROTOCOL) {
2204                 MATHB(p, SEQINSZ, ADD, PDCP_MAC_I_LEN, VSEQOUTSZ, 4, IMMED2);
2205                 MATHB(p, SEQINSZ, SUB, ZERO, VSEQINSZ, 4, 0);
2206         } else {
2207                 MATHB(p, SEQINSZ, SUB, PDCP_MAC_I_LEN, VSEQOUTSZ, 4, IMMED2);
2208                 MATHB(p, VSEQOUTSZ, SUB, ZERO, VSEQINSZ, 4, 0);
2209         }
2210
2211         SEQSTORE(p, MATH0, offset, length, 0);
2212
2213         if (dir == OP_TYPE_ENCAP_PROTOCOL) {
2214                 SEQFIFOSTORE(p, MSG, 0, 0, VLF);
2215                 SEQFIFOLOAD(p, MSGINSNOOP, 0, VLF | LAST2);
2216         } else {
2217                 SEQFIFOSTORE(p, MSG, 0, 0, VLF | CONT);
2218                 SEQFIFOLOAD(p, MSGOUTSNOOP, 0, VLF | LAST2);
2219         }
2220
2221         ALG_OPERATION(p, OP_ALG_ALGSEL_SNOW_F9,
2222                       OP_ALG_AAI_F9,
2223                       OP_ALG_AS_INITFINAL,
2224                       dir == OP_TYPE_ENCAP_PROTOCOL ?
2225                              ICV_CHECK_DISABLE : ICV_CHECK_ENABLE,
2226                       DIR_DEC);
2227
2228         ALG_OPERATION(p, OP_ALG_ALGSEL_ZUCE,
2229                       OP_ALG_AAI_F8,
2230                       OP_ALG_AS_INITFINAL,
2231                       ICV_CHECK_DISABLE,
2232                       dir == OP_TYPE_ENCAP_PROTOCOL ? DIR_ENC : DIR_DEC);
2233
2234         if (dir == OP_TYPE_ENCAP_PROTOCOL) {
2235                 MOVE(p, CONTEXT2, 0, IFIFOAB1, 0, 4, LAST1 | FLUSH1 | IMMED);
2236         } else {
2237                 SEQFIFOLOAD(p, MSG1, 4, LAST1 | FLUSH1);
2238                 JUMP(p, 1, LOCAL_JUMP, ALL_TRUE, CLASS1 | NOP | NIFP);
2239
2240                 if (rta_sec_era >= RTA_SEC_ERA_6)
2241                         /*
2242                          * For SEC ERA 6, there's a problem with the OFIFO
2243                          * pointer, and thus it needs to be reset here before
2244                          * moving to M0.
2245                          */
2246                         LOAD(p, 0, DCTRL, 0, LDLEN_RST_CHA_OFIFO_PTR, IMMED);
2247
2248                 /* Put ICV to M0 before sending it to C2 for comparison. */
2249                 MOVEB(p, OFIFO, 0, MATH0, 0, 4, WAITCOMP | IMMED);
2250
2251                 LOAD(p, NFIFOENTRY_STYPE_ALTSOURCE |
2252                      NFIFOENTRY_DEST_CLASS2 |
2253                      NFIFOENTRY_DTYPE_ICV |
2254                      NFIFOENTRY_LC2 | 4, NFIFO_SZL, 0, 4, IMMED);
2255                 MOVEB(p, MATH0, 0, ALTSOURCE, 0, 4, IMMED);
2256         }
2257
2258         PATCH_JUMP(p, pkeyjump, keyjump);
2259         return 0;
2260 }
2261
2262 static inline int
2263 pdcp_insert_cplane_zuc_aes_op(struct program *p,
2264                               bool swap __maybe_unused,
2265                               struct alginfo *cipherdata,
2266                               struct alginfo *authdata,
2267                               unsigned int dir,
2268                               enum pdcp_sn_size sn_size,
2269                               unsigned char era_2_sw_hfn_ovrd __maybe_unused)
2270 {
2271         uint32_t offset = 0, length = 0, sn_mask = 0;
2272         if (rta_sec_era < RTA_SEC_ERA_5) {
2273                 pr_err("Invalid era for selected algorithm\n");
2274                 return -ENOTSUP;
2275         }
2276
2277         if ((rta_sec_era >= RTA_SEC_ERA_8 && sn_size != PDCP_SN_SIZE_18) ||
2278                 (rta_sec_era == RTA_SEC_ERA_10)) {
2279                 int pclid;
2280
2281                 KEY(p, KEY1, cipherdata->key_enc_flags, cipherdata->key,
2282                                 cipherdata->keylen, INLINE_KEY(cipherdata));
2283                 KEY(p, KEY2, authdata->key_enc_flags, authdata->key,
2284                                 authdata->keylen, INLINE_KEY(authdata));
2285
2286                 if (sn_size == PDCP_SN_SIZE_5)
2287                         pclid = OP_PCLID_LTE_PDCP_CTRL_MIXED;
2288                 else
2289                         pclid = OP_PCLID_LTE_PDCP_USER_RN;
2290
2291                 PROTOCOL(p, dir, pclid,
2292                          ((uint16_t)cipherdata->algtype << 8) |
2293                          (uint16_t)authdata->algtype);
2294                 return 0;
2295         }
2296         /* Non-proto is supported only for 5bit cplane and 18bit uplane */
2297         switch (sn_size) {
2298         case PDCP_SN_SIZE_5:
2299                 offset = 7;
2300                 length = 1;
2301                 sn_mask = (swap == false) ? PDCP_C_PLANE_SN_MASK :
2302                                         PDCP_C_PLANE_SN_MASK_BE;
2303                 break;
2304         case PDCP_SN_SIZE_18:
2305                 offset = 5;
2306                 length = 3;
2307                 sn_mask = (swap == false) ? PDCP_U_PLANE_18BIT_SN_MASK :
2308                                         PDCP_U_PLANE_18BIT_SN_MASK_BE;
2309                 break;
2310         case PDCP_SN_SIZE_7:
2311         case PDCP_SN_SIZE_12:
2312         case PDCP_SN_SIZE_15:
2313                 pr_err("Invalid sn_size for %s\n", __func__);
2314                 return -ENOTSUP;
2315         }
2316
2317         SEQLOAD(p, MATH0, offset, length, 0);
2318         JUMP(p, 1, LOCAL_JUMP, ALL_TRUE, CALM);
2319         MATHB(p, MATH0, AND, sn_mask, MATH1, 8, IFB | IMMED2);
2320
2321         MATHB(p, MATH1, SHLD, MATH1, MATH1, 8, 0);
2322         MOVEB(p, DESCBUF, 4, MATH2, 0, 0x08, WAITCOMP | IMMED);
2323         MATHB(p, MATH1, OR, MATH2, MATH2, 8, 0);
2324         SEQSTORE(p, MATH0, offset, length, 0);
2325         if (dir == OP_TYPE_ENCAP_PROTOCOL) {
2326                 KEY(p, KEY1, authdata->key_enc_flags, authdata->key,
2327                     authdata->keylen, INLINE_KEY(authdata));
2328                 MOVEB(p, MATH2, 0, IFIFOAB1, 0, 0x08, IMMED);
2329                 MOVEB(p, MATH0, offset, IFIFOAB1, 0, length, IMMED);
2330
2331                 MATHB(p, SEQINSZ, SUB, ZERO, VSEQINSZ, 4, 0);
2332                 MATHB(p, VSEQINSZ, ADD, PDCP_MAC_I_LEN, VSEQOUTSZ, 4, IMMED2);
2333
2334                 ALG_OPERATION(p, OP_ALG_ALGSEL_AES,
2335                               OP_ALG_AAI_CMAC,
2336                               OP_ALG_AS_INITFINAL,
2337                               ICV_CHECK_DISABLE,
2338                               DIR_DEC);
2339                 SEQFIFOLOAD(p, MSG1, 0, VLF | LAST1 | FLUSH1);
2340                 MOVEB(p, CONTEXT1, 0, MATH3, 0, 4, WAITCOMP | IMMED);
2341                 LOAD(p, CLRW_RESET_CLS1_CHA |
2342                      CLRW_CLR_C1KEY |
2343                      CLRW_CLR_C1CTX |
2344                      CLRW_CLR_C1ICV |
2345                      CLRW_CLR_C1DATAS |
2346                      CLRW_CLR_C1MODE,
2347                      CLRW, 0, 4, IMMED);
2348
2349                 KEY(p, KEY1, cipherdata->key_enc_flags, cipherdata->key,
2350                     cipherdata->keylen, INLINE_KEY(cipherdata));
2351
2352                 MOVEB(p, MATH2, 0, CONTEXT1, 0, 8, IMMED);
2353                 SEQINPTR(p, 0, PDCP_NULL_MAX_FRAME_LEN, RTO);
2354
2355                 ALG_OPERATION(p, OP_ALG_ALGSEL_ZUCE,
2356                               OP_ALG_AAI_F8,
2357                               OP_ALG_AS_INITFINAL,
2358                               ICV_CHECK_DISABLE,
2359                               DIR_ENC);
2360                 SEQFIFOSTORE(p, MSG, 0, 0, VLF);
2361
2362                 SEQFIFOLOAD(p, SKIP, length, 0);
2363
2364                 SEQFIFOLOAD(p, MSG1, 0, VLF);
2365                 MOVEB(p, MATH3, 0, IFIFOAB1, 0, 4, LAST1 | FLUSH1 | IMMED);
2366         } else {
2367                 MOVEB(p, MATH2, 0, CONTEXT1, 0, 8, IMMED);
2368
2369                 MOVE(p, CONTEXT1, 0, CONTEXT2, 0, 8, IMMED);
2370
2371                 MATHB(p, SEQINSZ, SUB, ZERO, VSEQINSZ, 4, 0);
2372
2373                 MATHB(p, SEQINSZ, SUB, PDCP_MAC_I_LEN, VSEQOUTSZ, 4, IMMED2);
2374
2375                 KEY(p, KEY1, cipherdata->key_enc_flags, cipherdata->key,
2376                     cipherdata->keylen, INLINE_KEY(cipherdata));
2377
2378                 MOVE(p, CONTEXT1, 0, CONTEXT2, 0, 8, IMMED);
2379
2380                 ALG_OPERATION(p, OP_ALG_ALGSEL_ZUCE,
2381                               OP_ALG_AAI_F8,
2382                               OP_ALG_AS_INITFINAL,
2383                               ICV_CHECK_DISABLE,
2384                               DIR_DEC);
2385                 SEQFIFOSTORE(p, MSG, 0, 0, VLF | CONT);
2386                 SEQFIFOLOAD(p, MSG1, 0, VLF | LAST1 | FLUSH1);
2387
2388                 MOVEB(p, OFIFO, 0, MATH3, 0, 4, IMMED);
2389
2390                 LOAD(p, CLRW_RESET_CLS1_CHA |
2391                      CLRW_CLR_C1KEY |
2392                      CLRW_CLR_C1CTX |
2393                      CLRW_CLR_C1ICV |
2394                      CLRW_CLR_C1DATAS |
2395                      CLRW_CLR_C1MODE,
2396                      CLRW, 0, 4, IMMED);
2397
2398                 KEY(p, KEY1, authdata->key_enc_flags, authdata->key,
2399                     authdata->keylen, INLINE_KEY(authdata));
2400
2401                 SEQINPTR(p, 0, 0, SOP);
2402
2403                 ALG_OPERATION(p, OP_ALG_ALGSEL_AES,
2404                               OP_ALG_AAI_CMAC,
2405                               OP_ALG_AS_INITFINAL,
2406                               ICV_CHECK_ENABLE,
2407                               DIR_DEC);
2408
2409                 MATHB(p, SEQINSZ, SUB, ZERO, VSEQINSZ, 4, 0);
2410
2411                 MOVE(p, CONTEXT2, 0, IFIFOAB1, 0, 8, IMMED);
2412
2413                 SEQFIFOLOAD(p, MSG1, 0, VLF | LAST1 | FLUSH1);
2414
2415                 LOAD(p, NFIFOENTRY_STYPE_ALTSOURCE |
2416                      NFIFOENTRY_DEST_CLASS1 |
2417                      NFIFOENTRY_DTYPE_ICV |
2418                      NFIFOENTRY_LC1 |
2419                      NFIFOENTRY_FC1 | 4, NFIFO_SZL, 0, 4, IMMED);
2420                 MOVEB(p, MATH3, 0, ALTSOURCE, 0, 4, IMMED);
2421         }
2422
2423         return 0;
2424 }
2425
2426 static inline int
2427 pdcp_insert_uplane_no_int_op(struct program *p,
2428                             bool swap __maybe_unused,
2429                             struct alginfo *cipherdata,
2430                             unsigned int dir,
2431                             enum pdcp_sn_size sn_size)
2432 {
2433         int op;
2434         uint32_t sn_mask;
2435
2436         /* Insert Cipher Key */
2437         KEY(p, KEY1, cipherdata->key_enc_flags, cipherdata->key,
2438             cipherdata->keylen, INLINE_KEY(cipherdata));
2439
2440         if ((rta_sec_era >= RTA_SEC_ERA_8 && sn_size == PDCP_SN_SIZE_15) ||
2441                         (rta_sec_era >= RTA_SEC_ERA_10)) {
2442                 PROTOCOL(p, dir, OP_PCLID_LTE_PDCP_USER,
2443                          (uint16_t)cipherdata->algtype);
2444                 return 0;
2445         }
2446
2447         if (sn_size == PDCP_SN_SIZE_15) {
2448                 SEQLOAD(p, MATH0, 6, 2, 0);
2449                 sn_mask = (swap == false) ? PDCP_U_PLANE_15BIT_SN_MASK :
2450                                         PDCP_U_PLANE_15BIT_SN_MASK_BE;
2451         } else { /* SN Size == PDCP_SN_SIZE_18 */
2452                 SEQLOAD(p, MATH0, 5, 3, 0);
2453                 sn_mask = (swap == false) ? PDCP_U_PLANE_18BIT_SN_MASK :
2454                                         PDCP_U_PLANE_18BIT_SN_MASK_BE;
2455         }
2456         JUMP(p, 1, LOCAL_JUMP, ALL_TRUE, CALM);
2457         MATHB(p, MATH0, AND, sn_mask, MATH1, 8, IFB | IMMED2);
2458
2459         if (sn_size == PDCP_SN_SIZE_15)
2460                 SEQSTORE(p, MATH0, 6, 2, 0);
2461         else /* SN Size == PDCP_SN_SIZE_18 */
2462                 SEQSTORE(p, MATH0, 5, 3, 0);
2463
2464         MATHB(p, MATH1, SHLD, MATH1, MATH1, 8, 0);
2465         MOVEB(p, DESCBUF, 8, MATH2, 0, 8, WAITCOMP | IMMED);
2466         MATHB(p, MATH1, OR, MATH2, MATH2, 8, 0);
2467
2468         MATHB(p, SEQINSZ, SUB, MATH3, VSEQINSZ, 4, 0);
2469         MATHB(p, SEQINSZ, SUB, MATH3, VSEQOUTSZ, 4, 0);
2470
2471         SEQFIFOSTORE(p, MSG, 0, 0, VLF);
2472
2473         op = dir == OP_TYPE_ENCAP_PROTOCOL ? DIR_ENC : DIR_DEC;
2474         switch (cipherdata->algtype) {
2475         case PDCP_CIPHER_TYPE_SNOW:
2476                 MOVEB(p, MATH2, 0, CONTEXT1, 0, 8, WAITCOMP | IMMED);
2477                 ALG_OPERATION(p, OP_ALG_ALGSEL_SNOW_F8,
2478                               OP_ALG_AAI_F8,
2479                               OP_ALG_AS_INITFINAL,
2480                               ICV_CHECK_DISABLE,
2481                               op);
2482                 break;
2483
2484         case PDCP_CIPHER_TYPE_AES:
2485                 MOVEB(p, MATH2, 0, CONTEXT1, 0x10, 0x10, WAITCOMP | IMMED);
2486                 ALG_OPERATION(p, OP_ALG_ALGSEL_AES,
2487                               OP_ALG_AAI_CTR,
2488                               OP_ALG_AS_INITFINAL,
2489                               ICV_CHECK_DISABLE,
2490                               op);
2491                 break;
2492
2493         case PDCP_CIPHER_TYPE_ZUC:
2494                 if (rta_sec_era < RTA_SEC_ERA_5) {
2495                         pr_err("Invalid era for selected algorithm\n");
2496                         return -ENOTSUP;
2497                 }
2498                 MOVEB(p, MATH2, 0, CONTEXT1, 0, 0x08, IMMED);
2499                 MOVEB(p, MATH2, 0, CONTEXT1, 0x08, 0x08, WAITCOMP | IMMED);
2500
2501                 ALG_OPERATION(p, OP_ALG_ALGSEL_ZUCE,
2502                               OP_ALG_AAI_F8,
2503                               OP_ALG_AS_INITFINAL,
2504                               ICV_CHECK_DISABLE,
2505                               op);
2506                 break;
2507
2508         default:
2509                 pr_err("%s: Invalid encrypt algorithm selected: %d\n",
2510                        "pdcp_insert_uplane_15bit_op", cipherdata->algtype);
2511                 return -EINVAL;
2512         }
2513
2514         SEQFIFOLOAD(p, MSG1, 0, VLF | LAST1 | FLUSH1);
2515
2516         return 0;
2517 }
2518
2519 /*
2520  * Function for inserting the snippet of code responsible for creating
2521  * the HFN override code via either DPOVRD or via the input frame.
2522  */
2523 static inline int
2524 insert_hfn_ov_op(struct program *p,
2525                  uint32_t shift,
2526                  enum pdb_type_e pdb_type,
2527                  unsigned char era_2_sw_hfn_ovrd)
2528 {
2529         uint32_t imm = PDCP_DPOVRD_HFN_OV_EN;
2530         uint16_t hfn_pdb_offset;
2531         LABEL(keyjump);
2532         REFERENCE(pkeyjump);
2533
2534         if (rta_sec_era == RTA_SEC_ERA_2 && !era_2_sw_hfn_ovrd)
2535                 return 0;
2536
2537         switch (pdb_type) {
2538         case PDCP_PDB_TYPE_NO_PDB:
2539                 /*
2540                  * If there is no PDB, then HFN override mechanism does not
2541                  * make any sense, thus in this case the function will
2542                  * return the pointer to the current position in the
2543                  * descriptor buffer
2544                  */
2545                 return 0;
2546
2547         case PDCP_PDB_TYPE_REDUCED_PDB:
2548                 hfn_pdb_offset = 4;
2549                 break;
2550
2551         case PDCP_PDB_TYPE_FULL_PDB:
2552                 hfn_pdb_offset = 8;
2553                 break;
2554
2555         default:
2556                 return -EINVAL;
2557         }
2558
2559         if (rta_sec_era > RTA_SEC_ERA_2) {
2560                 MATHB(p, DPOVRD, AND, imm, NONE, 8, IFB | IMMED2);
2561         } else {
2562                 SEQLOAD(p, MATH0, 4, 4, 0);
2563                 JUMP(p, 1, LOCAL_JUMP, ALL_TRUE, CALM);
2564                 MATHB(p, MATH0, AND, imm, NONE, 8, IFB | IMMED2);
2565                 SEQSTORE(p, MATH0, 4, 4, 0);
2566         }
2567
2568         pkeyjump = JUMP(p, keyjump, LOCAL_JUMP, ALL_TRUE, MATH_Z);
2569
2570         if (rta_sec_era > RTA_SEC_ERA_2)
2571                 MATHI(p, DPOVRD, LSHIFT, shift, MATH0, 4, IMMED2);
2572         else
2573                 MATHB(p, MATH0, LSHIFT, shift, MATH0, 4, IMMED2);
2574
2575         MATHB(p, MATH0, SHLD, MATH0, MATH0, 8, 0);
2576         MOVE(p, MATH0, 0, DESCBUF, hfn_pdb_offset, 4, IMMED);
2577
2578         if (rta_sec_era >= RTA_SEC_ERA_8)
2579                 /*
2580                  * For ERA8, DPOVRD could be handled by the PROTOCOL command
2581                  * itself. For now, this is not done. Thus, clear DPOVRD here
2582                  * to alleviate any side-effects.
2583                  */
2584                 MATHB(p, DPOVRD, AND, ZERO, DPOVRD, 4, STL);
2585
2586         SET_LABEL(p, keyjump);
2587         PATCH_JUMP(p, pkeyjump, keyjump);
2588         return 0;
2589 }
2590
2591 /*
2592  * PDCP Control PDB creation function
2593  */
2594 static inline enum pdb_type_e
2595 cnstr_pdcp_c_plane_pdb(struct program *p,
2596                        uint32_t hfn,
2597                        enum pdcp_sn_size sn_size,
2598                        unsigned char bearer,
2599                        unsigned char direction,
2600                        uint32_t hfn_threshold,
2601                        struct alginfo *cipherdata,
2602                        struct alginfo *authdata)
2603 {
2604         struct pdcp_pdb pdb;
2605         enum pdb_type_e
2606                 pdb_mask[PDCP_CIPHER_TYPE_INVALID][PDCP_AUTH_TYPE_INVALID] = {
2607                         {       /* NULL */
2608                                 PDCP_PDB_TYPE_NO_PDB,           /* NULL */
2609                                 PDCP_PDB_TYPE_FULL_PDB,         /* SNOW f9 */
2610                                 PDCP_PDB_TYPE_FULL_PDB,         /* AES CMAC */
2611                                 PDCP_PDB_TYPE_FULL_PDB          /* ZUC-I */
2612                         },
2613                         {       /* SNOW f8 */
2614                                 PDCP_PDB_TYPE_FULL_PDB,         /* NULL */
2615                                 PDCP_PDB_TYPE_FULL_PDB,         /* SNOW f9 */
2616                                 PDCP_PDB_TYPE_REDUCED_PDB,      /* AES CMAC */
2617                                 PDCP_PDB_TYPE_REDUCED_PDB       /* ZUC-I */
2618                         },
2619                         {       /* AES CTR */
2620                                 PDCP_PDB_TYPE_FULL_PDB,         /* NULL */
2621                                 PDCP_PDB_TYPE_REDUCED_PDB,      /* SNOW f9 */
2622                                 PDCP_PDB_TYPE_FULL_PDB,         /* AES CMAC */
2623                                 PDCP_PDB_TYPE_REDUCED_PDB       /* ZUC-I */
2624                         },
2625                         {       /* ZUC-E */
2626                                 PDCP_PDB_TYPE_FULL_PDB,         /* NULL */
2627                                 PDCP_PDB_TYPE_REDUCED_PDB,      /* SNOW f9 */
2628                                 PDCP_PDB_TYPE_REDUCED_PDB,      /* AES CMAC */
2629                                 PDCP_PDB_TYPE_FULL_PDB          /* ZUC-I */
2630                         },
2631         };
2632
2633         if (rta_sec_era >= RTA_SEC_ERA_8) {
2634                 memset(&pdb, 0x00, sizeof(struct pdcp_pdb));
2635
2636                 /* To support 12-bit seq numbers, we use u-plane opt in pdb.
2637                  * SEC supports 5-bit only with c-plane opt in pdb.
2638                  */
2639                 if (sn_size == PDCP_SN_SIZE_12) {
2640                         pdb.hfn_res = hfn << PDCP_U_PLANE_PDB_LONG_SN_HFN_SHIFT;
2641                         pdb.bearer_dir_res = (uint32_t)
2642                                 ((bearer << PDCP_U_PLANE_PDB_BEARER_SHIFT) |
2643                                  (direction << PDCP_U_PLANE_PDB_DIR_SHIFT));
2644
2645                         pdb.hfn_thr_res =
2646                         hfn_threshold << PDCP_U_PLANE_PDB_LONG_SN_HFN_THR_SHIFT;
2647
2648                 } else {
2649                         /* This means 5-bit c-plane.
2650                          * Here we use c-plane opt in pdb
2651                          */
2652
2653                         /* This is a HW issue. Bit 2 should be set to zero,
2654                          * but it does not work this way. Override here.
2655                          */
2656                         pdb.opt_res.rsvd = 0x00000002;
2657
2658                         /* Copy relevant information from user to PDB */
2659                         pdb.hfn_res = hfn << PDCP_C_PLANE_PDB_HFN_SHIFT;
2660                         pdb.bearer_dir_res = (uint32_t)
2661                                 ((bearer << PDCP_C_PLANE_PDB_BEARER_SHIFT) |
2662                                 (direction << PDCP_C_PLANE_PDB_DIR_SHIFT));
2663                         pdb.hfn_thr_res =
2664                         hfn_threshold << PDCP_C_PLANE_PDB_HFN_THR_SHIFT;
2665                 }
2666
2667                 /* copy PDB in descriptor*/
2668                 __rta_out32(p, pdb.opt_res.opt);
2669                 __rta_out32(p, pdb.hfn_res);
2670                 __rta_out32(p, pdb.bearer_dir_res);
2671                 __rta_out32(p, pdb.hfn_thr_res);
2672
2673                 return PDCP_PDB_TYPE_FULL_PDB;
2674         }
2675
2676         switch (pdb_mask[cipherdata->algtype][authdata->algtype]) {
2677         case PDCP_PDB_TYPE_NO_PDB:
2678                 break;
2679
2680         case PDCP_PDB_TYPE_REDUCED_PDB:
2681                 __rta_out32(p, (hfn << PDCP_C_PLANE_PDB_HFN_SHIFT));
2682                 __rta_out32(p,
2683                             (uint32_t)((bearer <<
2684                                         PDCP_C_PLANE_PDB_BEARER_SHIFT) |
2685                                         (direction <<
2686                                          PDCP_C_PLANE_PDB_DIR_SHIFT)));
2687                 break;
2688
2689         case PDCP_PDB_TYPE_FULL_PDB:
2690                 memset(&pdb, 0x00, sizeof(struct pdcp_pdb));
2691
2692                 /* This is a HW issue. Bit 2 should be set to zero,
2693                  * but it does not work this way. Override here.
2694                  */
2695                 pdb.opt_res.rsvd = 0x00000002;
2696
2697                 /* Copy relevant information from user to PDB */
2698                 pdb.hfn_res = hfn << PDCP_C_PLANE_PDB_HFN_SHIFT;
2699                 pdb.bearer_dir_res = (uint32_t)
2700                         ((bearer << PDCP_C_PLANE_PDB_BEARER_SHIFT) |
2701                          (direction << PDCP_C_PLANE_PDB_DIR_SHIFT));
2702                 pdb.hfn_thr_res =
2703                         hfn_threshold << PDCP_C_PLANE_PDB_HFN_THR_SHIFT;
2704
2705                 /* copy PDB in descriptor*/
2706                 __rta_out32(p, pdb.opt_res.opt);
2707                 __rta_out32(p, pdb.hfn_res);
2708                 __rta_out32(p, pdb.bearer_dir_res);
2709                 __rta_out32(p, pdb.hfn_thr_res);
2710
2711                 break;
2712
2713         default:
2714                 return PDCP_PDB_TYPE_INVALID;
2715         }
2716
2717         return pdb_mask[cipherdata->algtype][authdata->algtype];
2718 }
2719
2720 /*
2721  * PDCP UPlane PDB creation function
2722  */
2723 static inline enum pdb_type_e
2724 cnstr_pdcp_u_plane_pdb(struct program *p,
2725                        enum pdcp_sn_size sn_size,
2726                        uint32_t hfn, unsigned short bearer,
2727                        unsigned short direction,
2728                        uint32_t hfn_threshold,
2729                        struct alginfo *cipherdata,
2730                        struct alginfo *authdata)
2731 {
2732         struct pdcp_pdb pdb;
2733         enum pdb_type_e pdb_type = PDCP_PDB_TYPE_FULL_PDB;
2734         enum pdb_type_e
2735                 pdb_mask[PDCP_CIPHER_TYPE_INVALID][PDCP_AUTH_TYPE_INVALID] = {
2736                         {       /* NULL */
2737                                 PDCP_PDB_TYPE_NO_PDB,           /* NULL */
2738                                 PDCP_PDB_TYPE_FULL_PDB,         /* SNOW f9 */
2739                                 PDCP_PDB_TYPE_FULL_PDB,         /* AES CMAC */
2740                                 PDCP_PDB_TYPE_FULL_PDB          /* ZUC-I */
2741                         },
2742                         {       /* SNOW f8 */
2743                                 PDCP_PDB_TYPE_FULL_PDB,         /* NULL */
2744                                 PDCP_PDB_TYPE_FULL_PDB,         /* SNOW f9 */
2745                                 PDCP_PDB_TYPE_REDUCED_PDB,      /* AES CMAC */
2746                                 PDCP_PDB_TYPE_REDUCED_PDB       /* ZUC-I */
2747                         },
2748                         {       /* AES CTR */
2749                                 PDCP_PDB_TYPE_FULL_PDB,         /* NULL */
2750                                 PDCP_PDB_TYPE_REDUCED_PDB,      /* SNOW f9 */
2751                                 PDCP_PDB_TYPE_FULL_PDB,         /* AES CMAC */
2752                                 PDCP_PDB_TYPE_REDUCED_PDB       /* ZUC-I */
2753                         },
2754                         {       /* ZUC-E */
2755                                 PDCP_PDB_TYPE_FULL_PDB,         /* NULL */
2756                                 PDCP_PDB_TYPE_REDUCED_PDB,      /* SNOW f9 */
2757                                 PDCP_PDB_TYPE_REDUCED_PDB,      /* AES CMAC */
2758                                 PDCP_PDB_TYPE_FULL_PDB          /* ZUC-I */
2759                         },
2760         };
2761
2762         /* Read options from user */
2763         /* Depending on sequence number length, the HFN and HFN threshold
2764          * have different lengths.
2765          */
2766         memset(&pdb, 0x00, sizeof(struct pdcp_pdb));
2767
2768         switch (sn_size) {
2769         case PDCP_SN_SIZE_7:
2770                 pdb.opt_res.opt |= PDCP_U_PLANE_PDB_OPT_SHORT_SN;
2771                 pdb.hfn_res = hfn << PDCP_U_PLANE_PDB_SHORT_SN_HFN_SHIFT;
2772                 pdb.hfn_thr_res =
2773                         hfn_threshold<<PDCP_U_PLANE_PDB_SHORT_SN_HFN_THR_SHIFT;
2774                 break;
2775
2776         case PDCP_SN_SIZE_12:
2777                 pdb.opt_res.opt &= (uint32_t)(~PDCP_U_PLANE_PDB_OPT_SHORT_SN);
2778                 pdb.hfn_res = hfn << PDCP_U_PLANE_PDB_LONG_SN_HFN_SHIFT;
2779                 pdb.hfn_thr_res =
2780                         hfn_threshold<<PDCP_U_PLANE_PDB_LONG_SN_HFN_THR_SHIFT;
2781                 break;
2782
2783         case PDCP_SN_SIZE_15:
2784                 pdb.opt_res.opt = (uint32_t)(PDCP_U_PLANE_PDB_OPT_15B_SN);
2785                 pdb.hfn_res = hfn << PDCP_U_PLANE_PDB_15BIT_SN_HFN_SHIFT;
2786                 pdb.hfn_thr_res =
2787                         hfn_threshold<<PDCP_U_PLANE_PDB_15BIT_SN_HFN_THR_SHIFT;
2788                 break;
2789
2790         case PDCP_SN_SIZE_18:
2791                 pdb.opt_res.opt = (uint32_t)(PDCP_U_PLANE_PDB_OPT_18B_SN);
2792                 pdb.hfn_res = hfn << PDCP_U_PLANE_PDB_18BIT_SN_HFN_SHIFT;
2793                 pdb.hfn_thr_res =
2794                         hfn_threshold<<PDCP_U_PLANE_PDB_18BIT_SN_HFN_THR_SHIFT;
2795
2796                 if (rta_sec_era <= RTA_SEC_ERA_8) {
2797                         if (cipherdata && authdata)
2798                                 pdb_type = pdb_mask[cipherdata->algtype]
2799                                                    [authdata->algtype];
2800                 }
2801                 break;
2802
2803         default:
2804                 pr_err("Invalid Sequence Number Size setting in PDB\n");
2805                 return -EINVAL;
2806         }
2807
2808         pdb.bearer_dir_res = (uint32_t)
2809                                 ((bearer << PDCP_U_PLANE_PDB_BEARER_SHIFT) |
2810                                  (direction << PDCP_U_PLANE_PDB_DIR_SHIFT));
2811
2812         switch (pdb_type) {
2813         case PDCP_PDB_TYPE_NO_PDB:
2814                 break;
2815
2816         case PDCP_PDB_TYPE_REDUCED_PDB:
2817                 __rta_out32(p, pdb.hfn_res);
2818                 __rta_out32(p, pdb.bearer_dir_res);
2819                 break;
2820
2821         case PDCP_PDB_TYPE_FULL_PDB:
2822                 /* copy PDB in descriptor*/
2823                 __rta_out32(p, pdb.opt_res.opt);
2824                 __rta_out32(p, pdb.hfn_res);
2825                 __rta_out32(p, pdb.bearer_dir_res);
2826                 __rta_out32(p, pdb.hfn_thr_res);
2827
2828                 break;
2829
2830         default:
2831                 return PDCP_PDB_TYPE_INVALID;
2832         }
2833
2834         return pdb_type;
2835 }
2836 /**
2837  * cnstr_shdsc_pdcp_c_plane_encap - Function for creating a PDCP Control Plane
2838  *                                  encapsulation descriptor.
2839  * @descbuf: pointer to buffer for descriptor construction
2840  * @ps: if 36/40bit addressing is desired, this parameter must be true
2841  * @swap: must be true when core endianness doesn't match SEC endianness
2842  * @hfn: starting Hyper Frame Number to be used together with the SN from the
2843  *       PDCP frames.
2844  * @sn_size: size of sequence numbers, only 5/12 bit sequence numbers are valid
2845  * @bearer: radio bearer ID
2846  * @direction: the direction of the PDCP frame (UL/DL)
2847  * @hfn_threshold: HFN value that once reached triggers a warning from SEC that
2848  *                 keys should be renegotiated at the earliest convenience.
2849  * @cipherdata: pointer to block cipher transform definitions
2850  *              Valid algorithm values are those from cipher_type_pdcp enum.
2851  * @authdata: pointer to authentication transform definitions
2852  *            Valid algorithm values are those from auth_type_pdcp enum.
2853  * @era_2_sw_hfn_ovrd: if software HFN override mechanism is desired for
2854  *                     this descriptor. Note: Can only be used for
2855  *                     SEC ERA 2.
2856  * Return: size of descriptor written in words or negative number on error.
2857  *         Once the function returns, the value of this parameter can be used
2858  *         for reclaiming the space that wasn't used for the descriptor.
2859  *
2860  * Note: descbuf must be large enough to contain a full 256 byte long
2861  * descriptor; after the function returns, by subtracting the actual number of
2862  * bytes used, the user can reuse the remaining buffer space for other purposes.
2863  */
2864 static inline int
2865 cnstr_shdsc_pdcp_c_plane_encap(uint32_t *descbuf,
2866                                bool ps,
2867                                bool swap,
2868                                uint32_t hfn,
2869                                enum pdcp_sn_size sn_size,
2870                                unsigned char bearer,
2871                                unsigned char direction,
2872                                uint32_t hfn_threshold,
2873                                struct alginfo *cipherdata,
2874                                struct alginfo *authdata,
2875                                unsigned char era_2_sw_hfn_ovrd)
2876 {
2877         static int
2878                 (*pdcp_cp_fp[PDCP_CIPHER_TYPE_INVALID][PDCP_AUTH_TYPE_INVALID])
2879                         (struct program*, bool swap, struct alginfo *,
2880                          struct alginfo *, unsigned int, enum pdcp_sn_size,
2881                         unsigned char __maybe_unused) = {
2882                 {       /* NULL */
2883                         pdcp_insert_cplane_null_op,     /* NULL */
2884                         pdcp_insert_cplane_int_only_op, /* SNOW f9 */
2885                         pdcp_insert_cplane_int_only_op, /* AES CMAC */
2886                         pdcp_insert_cplane_int_only_op  /* ZUC-I */
2887                 },
2888                 {       /* SNOW f8 */
2889                         pdcp_insert_cplane_enc_only_op, /* NULL */
2890                         pdcp_insert_cplane_acc_op,      /* SNOW f9 */
2891                         pdcp_insert_cplane_snow_aes_op, /* AES CMAC */
2892                         pdcp_insert_cplane_snow_zuc_op  /* ZUC-I */
2893                 },
2894                 {       /* AES CTR */
2895                         pdcp_insert_cplane_enc_only_op, /* NULL */
2896                         pdcp_insert_cplane_aes_snow_op, /* SNOW f9 */
2897                         pdcp_insert_cplane_acc_op,      /* AES CMAC */
2898                         pdcp_insert_cplane_aes_zuc_op   /* ZUC-I */
2899                 },
2900                 {       /* ZUC-E */
2901                         pdcp_insert_cplane_enc_only_op, /* NULL */
2902                         pdcp_insert_cplane_zuc_snow_op, /* SNOW f9 */
2903                         pdcp_insert_cplane_zuc_aes_op,  /* AES CMAC */
2904                         pdcp_insert_cplane_acc_op       /* ZUC-I */
2905                 },
2906         };
2907         static enum rta_share_type
2908                 desc_share[PDCP_CIPHER_TYPE_INVALID][PDCP_AUTH_TYPE_INVALID] = {
2909                 {       /* NULL */
2910                         SHR_WAIT,       /* NULL */
2911                         SHR_ALWAYS,     /* SNOW f9 */
2912                         SHR_ALWAYS,     /* AES CMAC */
2913                         SHR_ALWAYS      /* ZUC-I */
2914                 },
2915                 {       /* SNOW f8 */
2916                         SHR_ALWAYS,     /* NULL */
2917                         SHR_ALWAYS,     /* SNOW f9 */
2918                         SHR_WAIT,       /* AES CMAC */
2919                         SHR_WAIT        /* ZUC-I */
2920                 },
2921                 {       /* AES CTR */
2922                         SHR_ALWAYS,     /* NULL */
2923                         SHR_ALWAYS,     /* SNOW f9 */
2924                         SHR_ALWAYS,     /* AES CMAC */
2925                         SHR_WAIT        /* ZUC-I */
2926                 },
2927                 {       /* ZUC-E */
2928                         SHR_ALWAYS,     /* NULL */
2929                         SHR_WAIT,       /* SNOW f9 */
2930                         SHR_WAIT,       /* AES CMAC */
2931                         SHR_ALWAYS      /* ZUC-I */
2932                 },
2933         };
2934         enum pdb_type_e pdb_type;
2935         struct program prg;
2936         struct program *p = &prg;
2937         int err;
2938         LABEL(pdb_end);
2939
2940         if (rta_sec_era != RTA_SEC_ERA_2 && era_2_sw_hfn_ovrd) {
2941                 pr_err("Cannot select SW HFN override for other era than 2");
2942                 return -EINVAL;
2943         }
2944
2945         if (sn_size != PDCP_SN_SIZE_12 && sn_size != PDCP_SN_SIZE_5) {
2946                 pr_err("C-plane supports only 5-bit and 12-bit sequence numbers\n");
2947                 return -EINVAL;
2948         }
2949
2950         PROGRAM_CNTXT_INIT(p, descbuf, 0);
2951         if (swap)
2952                 PROGRAM_SET_BSWAP(p);
2953         if (ps)
2954                 PROGRAM_SET_36BIT_ADDR(p);
2955
2956         SHR_HDR(p, desc_share[cipherdata->algtype][authdata->algtype], 0, 0);
2957
2958         pdb_type = cnstr_pdcp_c_plane_pdb(p,
2959                         hfn,
2960                         sn_size,
2961                         bearer,
2962                         direction,
2963                         hfn_threshold,
2964                         cipherdata,
2965                         authdata);
2966
2967         SET_LABEL(p, pdb_end);
2968
2969         err = insert_hfn_ov_op(p, sn_size, pdb_type,
2970                                era_2_sw_hfn_ovrd);
2971         if (err)
2972                 return err;
2973
2974         err = pdcp_cp_fp[cipherdata->algtype][authdata->algtype](p,
2975                 swap,
2976                 cipherdata,
2977                 authdata,
2978                 OP_TYPE_ENCAP_PROTOCOL,
2979                 sn_size,
2980                 era_2_sw_hfn_ovrd);
2981         if (err)
2982                 return err;
2983
2984         PATCH_HDR(p, 0, pdb_end);
2985
2986         return PROGRAM_FINALIZE(p);
2987 }
2988
2989 /**
2990  * cnstr_shdsc_pdcp_c_plane_decap - Function for creating a PDCP Control Plane
2991  *                                  decapsulation descriptor.
2992  * @descbuf: pointer to buffer for descriptor construction
2993  * @ps: if 36/40bit addressing is desired, this parameter must be true
2994  * @swap: must be true when core endianness doesn't match SEC endianness
2995  * @hfn: starting Hyper Frame Number to be used together with the SN from the
2996  *       PDCP frames.
2997  * @sn_size: size of sequence numbers, only 5/12 bit sequence numbers are valid
2998  * @bearer: radio bearer ID
2999  * @direction: the direction of the PDCP frame (UL/DL)
3000  * @hfn_threshold: HFN value that once reached triggers a warning from SEC that
3001  *                 keys should be renegotiated at the earliest convenience.
3002  * @cipherdata: pointer to block cipher transform definitions
3003  *              Valid algorithm values are those from cipher_type_pdcp enum.
3004  * @authdata: pointer to authentication transform definitions
3005  *            Valid algorithm values are those from auth_type_pdcp enum.
3006  * @era_2_sw_hfn_ovrd: if software HFN override mechanism is desired for
3007  *                     this descriptor. Note: Can only be used for
3008  *                     SEC ERA 2.
3009  *
3010  * Return: size of descriptor written in words or negative number on error.
3011  *         Once the function returns, the value of this parameter can be used
3012  *         for reclaiming the space that wasn't used for the descriptor.
3013  *
3014  * Note: descbuf must be large enough to contain a full 256 byte long
3015  * descriptor; after the function returns, by subtracting the actual number of
3016  * bytes used, the user can reuse the remaining buffer space for other purposes.
3017  */
3018 static inline int
3019 cnstr_shdsc_pdcp_c_plane_decap(uint32_t *descbuf,
3020                                bool ps,
3021                                bool swap,
3022                                uint32_t hfn,
3023                                enum pdcp_sn_size sn_size,
3024                                unsigned char bearer,
3025                                unsigned char direction,
3026                                uint32_t hfn_threshold,
3027                                struct alginfo *cipherdata,
3028                                struct alginfo *authdata,
3029                                unsigned char era_2_sw_hfn_ovrd)
3030 {
3031         static int
3032                 (*pdcp_cp_fp[PDCP_CIPHER_TYPE_INVALID][PDCP_AUTH_TYPE_INVALID])
3033                         (struct program*, bool swap, struct alginfo *,
3034                          struct alginfo *, unsigned int, enum pdcp_sn_size,
3035                          unsigned char) = {
3036                 {       /* NULL */
3037                         pdcp_insert_cplane_null_op,     /* NULL */
3038                         pdcp_insert_cplane_int_only_op, /* SNOW f9 */
3039                         pdcp_insert_cplane_int_only_op, /* AES CMAC */
3040                         pdcp_insert_cplane_int_only_op  /* ZUC-I */
3041                 },
3042                 {       /* SNOW f8 */
3043                         pdcp_insert_cplane_enc_only_op, /* NULL */
3044                         pdcp_insert_cplane_acc_op,      /* SNOW f9 */
3045                         pdcp_insert_cplane_snow_aes_op, /* AES CMAC */
3046                         pdcp_insert_cplane_snow_zuc_op  /* ZUC-I */
3047                 },
3048                 {       /* AES CTR */
3049                         pdcp_insert_cplane_enc_only_op, /* NULL */
3050                         pdcp_insert_cplane_aes_snow_op, /* SNOW f9 */
3051                         pdcp_insert_cplane_acc_op,      /* AES CMAC */
3052                         pdcp_insert_cplane_aes_zuc_op   /* ZUC-I */
3053                 },
3054                 {       /* ZUC-E */
3055                         pdcp_insert_cplane_enc_only_op, /* NULL */
3056                         pdcp_insert_cplane_zuc_snow_op, /* SNOW f9 */
3057                         pdcp_insert_cplane_zuc_aes_op,  /* AES CMAC */
3058                         pdcp_insert_cplane_acc_op       /* ZUC-I */
3059                 },
3060         };
3061         static enum rta_share_type
3062                 desc_share[PDCP_CIPHER_TYPE_INVALID][PDCP_AUTH_TYPE_INVALID] = {
3063                 {       /* NULL */
3064                         SHR_WAIT,       /* NULL */
3065                         SHR_ALWAYS,     /* SNOW f9 */
3066                         SHR_ALWAYS,     /* AES CMAC */
3067                         SHR_ALWAYS      /* ZUC-I */
3068                 },
3069                 {       /* SNOW f8 */
3070                         SHR_ALWAYS,     /* NULL */
3071                         SHR_ALWAYS,     /* SNOW f9 */
3072                         SHR_WAIT,       /* AES CMAC */
3073                         SHR_WAIT        /* ZUC-I */
3074                 },
3075                 {       /* AES CTR */
3076                         SHR_ALWAYS,     /* NULL */
3077                         SHR_ALWAYS,     /* SNOW f9 */
3078                         SHR_ALWAYS,     /* AES CMAC */
3079                         SHR_WAIT        /* ZUC-I */
3080                 },
3081                 {       /* ZUC-E */
3082                         SHR_ALWAYS,     /* NULL */
3083                         SHR_WAIT,       /* SNOW f9 */
3084                         SHR_WAIT,       /* AES CMAC */
3085                         SHR_ALWAYS      /* ZUC-I */
3086                 },
3087         };
3088         enum pdb_type_e pdb_type;
3089         struct program prg;
3090         struct program *p = &prg;
3091         int err;
3092         LABEL(pdb_end);
3093
3094         if (rta_sec_era != RTA_SEC_ERA_2 && era_2_sw_hfn_ovrd) {
3095                 pr_err("Cannot select SW HFN override for other era than 2");
3096                 return -EINVAL;
3097         }
3098
3099         if (sn_size != PDCP_SN_SIZE_12 && sn_size != PDCP_SN_SIZE_5) {
3100                 pr_err("C-plane supports only 5-bit and 12-bit sequence numbers\n");
3101                 return -EINVAL;
3102         }
3103
3104         PROGRAM_CNTXT_INIT(p, descbuf, 0);
3105         if (swap)
3106                 PROGRAM_SET_BSWAP(p);
3107         if (ps)
3108                 PROGRAM_SET_36BIT_ADDR(p);
3109
3110         SHR_HDR(p, desc_share[cipherdata->algtype][authdata->algtype], 0, 0);
3111
3112         pdb_type = cnstr_pdcp_c_plane_pdb(p,
3113                         hfn,
3114                         sn_size,
3115                         bearer,
3116                         direction,
3117                         hfn_threshold,
3118                         cipherdata,
3119                         authdata);
3120
3121         SET_LABEL(p, pdb_end);
3122
3123         err = insert_hfn_ov_op(p, sn_size, pdb_type,
3124                                era_2_sw_hfn_ovrd);
3125         if (err)
3126                 return err;
3127
3128         err = pdcp_cp_fp[cipherdata->algtype][authdata->algtype](p,
3129                 swap,
3130                 cipherdata,
3131                 authdata,
3132                 OP_TYPE_DECAP_PROTOCOL,
3133                 sn_size,
3134                 era_2_sw_hfn_ovrd);
3135         if (err)
3136                 return err;
3137
3138         PATCH_HDR(p, 0, pdb_end);
3139
3140         return PROGRAM_FINALIZE(p);
3141 }
3142
3143 static int
3144 pdcp_insert_uplane_with_int_op(struct program *p,
3145                               bool swap __maybe_unused,
3146                               struct alginfo *cipherdata,
3147                               struct alginfo *authdata,
3148                               enum pdcp_sn_size sn_size,
3149                               unsigned char era_2_sw_hfn_ovrd,
3150                               unsigned int dir)
3151 {
3152         static int
3153                 (*pdcp_cp_fp[PDCP_CIPHER_TYPE_INVALID][PDCP_AUTH_TYPE_INVALID])
3154                         (struct program*, bool swap, struct alginfo *,
3155                          struct alginfo *, unsigned int, enum pdcp_sn_size,
3156                         unsigned char __maybe_unused) = {
3157                 {       /* NULL */
3158                         pdcp_insert_cplane_null_op,     /* NULL */
3159                         pdcp_insert_cplane_int_only_op, /* SNOW f9 */
3160                         pdcp_insert_cplane_int_only_op, /* AES CMAC */
3161                         pdcp_insert_cplane_int_only_op  /* ZUC-I */
3162                 },
3163                 {       /* SNOW f8 */
3164                         pdcp_insert_cplane_enc_only_op, /* NULL */
3165                         pdcp_insert_uplane_snow_snow_op, /* SNOW f9 */
3166                         pdcp_insert_cplane_snow_aes_op, /* AES CMAC */
3167                         pdcp_insert_cplane_snow_zuc_op  /* ZUC-I */
3168                 },
3169                 {       /* AES CTR */
3170                         pdcp_insert_cplane_enc_only_op, /* NULL */
3171                         pdcp_insert_cplane_aes_snow_op, /* SNOW f9 */
3172                         pdcp_insert_uplane_aes_aes_op,  /* AES CMAC */
3173                         pdcp_insert_cplane_aes_zuc_op   /* ZUC-I */
3174                 },
3175                 {       /* ZUC-E */
3176                         pdcp_insert_cplane_enc_only_op, /* NULL */
3177                         pdcp_insert_cplane_zuc_snow_op, /* SNOW f9 */
3178                         pdcp_insert_cplane_zuc_aes_op,  /* AES CMAC */
3179                         pdcp_insert_uplane_zuc_zuc_op   /* ZUC-I */
3180                 },
3181         };
3182         int err;
3183
3184         err = pdcp_cp_fp[cipherdata->algtype][authdata->algtype](p,
3185                 swap,
3186                 cipherdata,
3187                 authdata,
3188                 dir,
3189                 sn_size,
3190                 era_2_sw_hfn_ovrd);
3191         if (err)
3192                 return err;
3193
3194         return 0;
3195 }
3196
3197
3198 /**
3199  * cnstr_shdsc_pdcp_u_plane_encap - Function for creating a PDCP User Plane
3200  *                                  encapsulation descriptor.
3201  * @descbuf: pointer to buffer for descriptor construction
3202  * @ps: if 36/40bit addressing is desired, this parameter must be true
3203  * @swap: must be true when core endianness doesn't match SEC endianness
3204  * @sn_size: selects Sequence Number Size: 7/12/15 bits
3205  * @hfn: starting Hyper Frame Number to be used together with the SN from the
3206  *       PDCP frames.
3207  * @bearer: radio bearer ID
3208  * @direction: the direction of the PDCP frame (UL/DL)
3209  * @hfn_threshold: HFN value that once reached triggers a warning from SEC that
3210  *                 keys should be renegotiated at the earliest convenience.
3211  * @cipherdata: pointer to block cipher transform definitions
3212  *              Valid algorithm values are those from cipher_type_pdcp enum.
3213  * @era_2_sw_hfn_ovrd: if software HFN override mechanism is desired for
3214  *                     this descriptor. Note: Can only be used for
3215  *                     SEC ERA 2.
3216  *
3217  * Return: size of descriptor written in words or negative number on error.
3218  *         Once the function returns, the value of this parameter can be used
3219  *         for reclaiming the space that wasn't used for the descriptor.
3220  *
3221  * Note: descbuf must be large enough to contain a full 256 byte long
3222  * descriptor; after the function returns, by subtracting the actual number of
3223  * bytes used, the user can reuse the remaining buffer space for other purposes.
3224  */
3225 static inline int
3226 cnstr_shdsc_pdcp_u_plane_encap(uint32_t *descbuf,
3227                                bool ps,
3228                                bool swap,
3229                                enum pdcp_sn_size sn_size,
3230                                uint32_t hfn,
3231                                unsigned short bearer,
3232                                unsigned short direction,
3233                                uint32_t hfn_threshold,
3234                                struct alginfo *cipherdata,
3235                                struct alginfo *authdata,
3236                                unsigned char era_2_sw_hfn_ovrd)
3237 {
3238         struct program prg;
3239         struct program *p = &prg;
3240         int err;
3241         enum pdb_type_e pdb_type;
3242         static enum rta_share_type
3243                 desc_share[PDCP_CIPHER_TYPE_INVALID][PDCP_AUTH_TYPE_INVALID] = {
3244                 {       /* NULL */
3245                         SHR_WAIT,       /* NULL */
3246                         SHR_ALWAYS,     /* SNOW f9 */
3247                         SHR_ALWAYS,     /* AES CMAC */
3248                         SHR_ALWAYS      /* ZUC-I */
3249                 },
3250                 {       /* SNOW f8 */
3251                         SHR_ALWAYS,     /* NULL */
3252                         SHR_ALWAYS,     /* SNOW f9 */
3253                         SHR_WAIT,       /* AES CMAC */
3254                         SHR_WAIT        /* ZUC-I */
3255                 },
3256                 {       /* AES CTR */
3257                         SHR_ALWAYS,     /* NULL */
3258                         SHR_ALWAYS,     /* SNOW f9 */
3259                         SHR_ALWAYS,     /* AES CMAC */
3260                         SHR_WAIT        /* ZUC-I */
3261                 },
3262                 {       /* ZUC-E */
3263                         SHR_ALWAYS,     /* NULL */
3264                         SHR_WAIT,       /* SNOW f9 */
3265                         SHR_WAIT,       /* AES CMAC */
3266                         SHR_ALWAYS      /* ZUC-I */
3267                 },
3268         };
3269         LABEL(pdb_end);
3270
3271         if (rta_sec_era != RTA_SEC_ERA_2 && era_2_sw_hfn_ovrd) {
3272                 pr_err("Cannot select SW HFN ovrd for other era than 2");
3273                 return -EINVAL;
3274         }
3275
3276         if (authdata && !authdata->algtype && rta_sec_era < RTA_SEC_ERA_8) {
3277                 pr_err("Cannot use u-plane auth with era < 8");
3278                 return -EINVAL;
3279         }
3280
3281         PROGRAM_CNTXT_INIT(p, descbuf, 0);
3282         if (swap)
3283                 PROGRAM_SET_BSWAP(p);
3284         if (ps)
3285                 PROGRAM_SET_36BIT_ADDR(p);
3286
3287         if (authdata)
3288                 SHR_HDR(p, desc_share[cipherdata->algtype][authdata->algtype], 0, 0);
3289         else
3290                 SHR_HDR(p, SHR_ALWAYS, 0, 0);
3291         pdb_type = cnstr_pdcp_u_plane_pdb(p, sn_size, hfn,
3292                                           bearer, direction, hfn_threshold,
3293                                           cipherdata, authdata);
3294         if (pdb_type == PDCP_PDB_TYPE_INVALID) {
3295                 pr_err("Error creating PDCP UPlane PDB\n");
3296                 return -EINVAL;
3297         }
3298         SET_LABEL(p, pdb_end);
3299
3300         err = insert_hfn_ov_op(p, sn_size, pdb_type, era_2_sw_hfn_ovrd);
3301         if (err)
3302                 return err;
3303
3304         switch (sn_size) {
3305         case PDCP_SN_SIZE_7:
3306         case PDCP_SN_SIZE_12:
3307                 switch (cipherdata->algtype) {
3308                 case PDCP_CIPHER_TYPE_ZUC:
3309                         if (rta_sec_era < RTA_SEC_ERA_5) {
3310                                 pr_err("Invalid era for selected algorithm\n");
3311                                 return -ENOTSUP;
3312                         }
3313                         /* fallthrough */
3314                 case PDCP_CIPHER_TYPE_AES:
3315                 case PDCP_CIPHER_TYPE_SNOW:
3316                 case PDCP_CIPHER_TYPE_NULL:
3317                         if (rta_sec_era == RTA_SEC_ERA_8 &&
3318                                         authdata && authdata->algtype == 0){
3319                                 err = pdcp_insert_uplane_with_int_op(p, swap,
3320                                                 cipherdata, authdata,
3321                                                 sn_size, era_2_sw_hfn_ovrd,
3322                                                 OP_TYPE_ENCAP_PROTOCOL);
3323                                 if (err)
3324                                         return err;
3325                                 break;
3326                         }
3327
3328                         if (pdb_type != PDCP_PDB_TYPE_FULL_PDB) {
3329                                 pr_err("PDB type must be FULL for PROTO desc\n");
3330                                 return -EINVAL;
3331                         }
3332
3333                         /* Insert auth key if requested */
3334                         if (authdata && authdata->algtype) {
3335                                 KEY(p, KEY2, authdata->key_enc_flags,
3336                                     (uint64_t)authdata->key, authdata->keylen,
3337                                     INLINE_KEY(authdata));
3338                         }
3339                         /* Insert Cipher Key */
3340                         KEY(p, KEY1, cipherdata->key_enc_flags,
3341                             (uint64_t)cipherdata->key, cipherdata->keylen,
3342                             INLINE_KEY(cipherdata));
3343
3344                         if (authdata)
3345                                 PROTOCOL(p, OP_TYPE_ENCAP_PROTOCOL,
3346                                          OP_PCLID_LTE_PDCP_USER_RN,
3347                                          ((uint16_t)cipherdata->algtype << 8) |
3348                                          (uint16_t)authdata->algtype);
3349                         else
3350                                 PROTOCOL(p, OP_TYPE_ENCAP_PROTOCOL,
3351                                          OP_PCLID_LTE_PDCP_USER,
3352                                          (uint16_t)cipherdata->algtype);
3353                         break;
3354                 default:
3355                         pr_err("%s: Invalid encrypt algorithm selected: %d\n",
3356                                "cnstr_pcl_shdsc_pdcp_u_plane_decap",
3357                                cipherdata->algtype);
3358                         return -EINVAL;
3359                 }
3360                 break;
3361
3362         case PDCP_SN_SIZE_15:
3363         case PDCP_SN_SIZE_18:
3364                 if (authdata) {
3365                         err = pdcp_insert_uplane_with_int_op(p, swap,
3366                                         cipherdata, authdata,
3367                                         sn_size, era_2_sw_hfn_ovrd,
3368                                         OP_TYPE_ENCAP_PROTOCOL);
3369                         if (err)
3370                                 return err;
3371
3372                         break;
3373                 }
3374
3375                 switch (cipherdata->algtype) {
3376                 case PDCP_CIPHER_TYPE_NULL:
3377                         insert_copy_frame_op(p,
3378                                              cipherdata,
3379                                              OP_TYPE_ENCAP_PROTOCOL);
3380                         break;
3381
3382                 default:
3383                         err = pdcp_insert_uplane_no_int_op(p, swap, cipherdata,
3384                                         OP_TYPE_ENCAP_PROTOCOL, sn_size);
3385                         if (err)
3386                                 return err;
3387                         break;
3388                 }
3389                 break;
3390
3391         case PDCP_SN_SIZE_5:
3392         default:
3393                 pr_err("Invalid SN size selected\n");
3394                 return -ENOTSUP;
3395         }
3396
3397         PATCH_HDR(p, 0, pdb_end);
3398         return PROGRAM_FINALIZE(p);
3399 }
3400
3401 /**
3402  * cnstr_shdsc_pdcp_u_plane_decap - Function for creating a PDCP User Plane
3403  *                                  decapsulation descriptor.
3404  * @descbuf: pointer to buffer for descriptor construction
3405  * @ps: if 36/40bit addressing is desired, this parameter must be true
3406  * @swap: must be true when core endianness doesn't match SEC endianness
3407  * @sn_size: selects Sequence Number Size: 7/12/15 bits
3408  * @hfn: starting Hyper Frame Number to be used together with the SN from the
3409  *       PDCP frames.
3410  * @bearer: radio bearer ID
3411  * @direction: the direction of the PDCP frame (UL/DL)
3412  * @hfn_threshold: HFN value that once reached triggers a warning from SEC that
3413  *                 keys should be renegotiated at the earliest convenience.
3414  * @cipherdata: pointer to block cipher transform definitions
3415  *              Valid algorithm values are those from cipher_type_pdcp enum.
3416  * @era_2_sw_hfn_ovrd: if software HFN override mechanism is desired for
3417  *                     this descriptor. Note: Can only be used for
3418  *                     SEC ERA 2.
3419  *
3420  * Return: size of descriptor written in words or negative number on error.
3421  *         Once the function returns, the value of this parameter can be used
3422  *         for reclaiming the space that wasn't used for the descriptor.
3423  *
3424  * Note: descbuf must be large enough to contain a full 256 byte long
3425  * descriptor; after the function returns, by subtracting the actual number of
3426  * bytes used, the user can reuse the remaining buffer space for other purposes.
3427  */
3428 static inline int
3429 cnstr_shdsc_pdcp_u_plane_decap(uint32_t *descbuf,
3430                                bool ps,
3431                                bool swap,
3432                                enum pdcp_sn_size sn_size,
3433                                uint32_t hfn,
3434                                unsigned short bearer,
3435                                unsigned short direction,
3436                                uint32_t hfn_threshold,
3437                                struct alginfo *cipherdata,
3438                                struct alginfo *authdata,
3439                                unsigned char era_2_sw_hfn_ovrd)
3440 {
3441         struct program prg;
3442         struct program *p = &prg;
3443         int err;
3444         enum pdb_type_e pdb_type;
3445         static enum rta_share_type
3446                 desc_share[PDCP_CIPHER_TYPE_INVALID][PDCP_AUTH_TYPE_INVALID] = {
3447                 {       /* NULL */
3448                         SHR_WAIT,       /* NULL */
3449                         SHR_ALWAYS,     /* SNOW f9 */
3450                         SHR_ALWAYS,     /* AES CMAC */
3451                         SHR_ALWAYS      /* ZUC-I */
3452                 },
3453                 {       /* SNOW f8 */
3454                         SHR_ALWAYS,     /* NULL */
3455                         SHR_ALWAYS,     /* SNOW f9 */
3456                         SHR_WAIT,       /* AES CMAC */
3457                         SHR_WAIT        /* ZUC-I */
3458                 },
3459                 {       /* AES CTR */
3460                         SHR_ALWAYS,     /* NULL */
3461                         SHR_ALWAYS,     /* SNOW f9 */
3462                         SHR_ALWAYS,     /* AES CMAC */
3463                         SHR_WAIT        /* ZUC-I */
3464                 },
3465                 {       /* ZUC-E */
3466                         SHR_ALWAYS,     /* NULL */
3467                         SHR_WAIT,       /* SNOW f9 */
3468                         SHR_WAIT,       /* AES CMAC */
3469                         SHR_ALWAYS      /* ZUC-I */
3470                 },
3471         };
3472
3473         LABEL(pdb_end);
3474
3475         if (rta_sec_era != RTA_SEC_ERA_2 && era_2_sw_hfn_ovrd) {
3476                 pr_err("Cannot select SW HFN override for other era than 2");
3477                 return -EINVAL;
3478         }
3479
3480         if (authdata && !authdata->algtype && rta_sec_era < RTA_SEC_ERA_8) {
3481                 pr_err("Cannot use u-plane auth with era < 8");
3482                 return -EINVAL;
3483         }
3484
3485         PROGRAM_CNTXT_INIT(p, descbuf, 0);
3486         if (swap)
3487                 PROGRAM_SET_BSWAP(p);
3488         if (ps)
3489                 PROGRAM_SET_36BIT_ADDR(p);
3490         if (authdata)
3491                 SHR_HDR(p, desc_share[cipherdata->algtype][authdata->algtype], 0, 0);
3492         else
3493                 SHR_HDR(p, SHR_ALWAYS, 0, 0);
3494
3495         pdb_type = cnstr_pdcp_u_plane_pdb(p, sn_size, hfn, bearer,
3496                                           direction, hfn_threshold,
3497                                           cipherdata, authdata);
3498         if (pdb_type == PDCP_PDB_TYPE_INVALID) {
3499                 pr_err("Error creating PDCP UPlane PDB\n");
3500                 return -EINVAL;
3501         }
3502         SET_LABEL(p, pdb_end);
3503
3504         err = insert_hfn_ov_op(p, sn_size, pdb_type, era_2_sw_hfn_ovrd);
3505         if (err)
3506                 return err;
3507
3508         switch (sn_size) {
3509         case PDCP_SN_SIZE_7:
3510         case PDCP_SN_SIZE_12:
3511                 switch (cipherdata->algtype) {
3512                 case PDCP_CIPHER_TYPE_ZUC:
3513                         if (rta_sec_era < RTA_SEC_ERA_5) {
3514                                 pr_err("Invalid era for selected algorithm\n");
3515                                 return -ENOTSUP;
3516                         }
3517                         /* fallthrough */
3518                 case PDCP_CIPHER_TYPE_AES:
3519                 case PDCP_CIPHER_TYPE_SNOW:
3520                 case PDCP_CIPHER_TYPE_NULL:
3521                         if (pdb_type != PDCP_PDB_TYPE_FULL_PDB) {
3522                                 pr_err("PDB type must be FULL for PROTO desc\n");
3523                                 return -EINVAL;
3524                         }
3525
3526                         /* Insert auth key if requested */
3527                         if (authdata && authdata->algtype)
3528                                 KEY(p, KEY2, authdata->key_enc_flags,
3529                                     (uint64_t)authdata->key, authdata->keylen,
3530                                     INLINE_KEY(authdata));
3531                         else if (authdata && authdata->algtype == 0) {
3532                                 err = pdcp_insert_uplane_with_int_op(p, swap,
3533                                                 cipherdata, authdata,
3534                                                 sn_size, era_2_sw_hfn_ovrd,
3535                                                 OP_TYPE_DECAP_PROTOCOL);
3536                                 if (err)
3537                                         return err;
3538                                 break;
3539                         }
3540
3541                         /* Insert Cipher Key */
3542                         KEY(p, KEY1, cipherdata->key_enc_flags,
3543                             cipherdata->key, cipherdata->keylen,
3544                             INLINE_KEY(cipherdata));
3545                         if (authdata)
3546                                 PROTOCOL(p, OP_TYPE_DECAP_PROTOCOL,
3547                                          OP_PCLID_LTE_PDCP_USER_RN,
3548                                          ((uint16_t)cipherdata->algtype << 8) |
3549                                          (uint16_t)authdata->algtype);
3550                         else
3551                                 PROTOCOL(p, OP_TYPE_DECAP_PROTOCOL,
3552                                          OP_PCLID_LTE_PDCP_USER,
3553                                          (uint16_t)cipherdata->algtype);
3554                         break;
3555                 default:
3556                         pr_err("%s: Invalid encrypt algorithm selected: %d\n",
3557                                "cnstr_pcl_shdsc_pdcp_u_plane_decap",
3558                                cipherdata->algtype);
3559                         return -EINVAL;
3560                 }
3561                 break;
3562
3563         case PDCP_SN_SIZE_15:
3564         case PDCP_SN_SIZE_18:
3565                 if (authdata) {
3566                         err = pdcp_insert_uplane_with_int_op(p, swap,
3567                                         cipherdata, authdata,
3568                                         sn_size, era_2_sw_hfn_ovrd,
3569                                         OP_TYPE_DECAP_PROTOCOL);
3570                         if (err)
3571                                 return err;
3572
3573                         break;
3574                 }
3575
3576                 switch (cipherdata->algtype) {
3577                 case PDCP_CIPHER_TYPE_NULL:
3578                         insert_copy_frame_op(p,
3579                                              cipherdata,
3580                                              OP_TYPE_DECAP_PROTOCOL);
3581                         break;
3582
3583                 default:
3584                         err = pdcp_insert_uplane_no_int_op(p, swap, cipherdata,
3585                                 OP_TYPE_DECAP_PROTOCOL, sn_size);
3586                         if (err)
3587                                 return err;
3588                         break;
3589                 }
3590                 break;
3591
3592         case PDCP_SN_SIZE_5:
3593         default:
3594                 pr_err("Invalid SN size selected\n");
3595                 return -ENOTSUP;
3596         }
3597
3598         PATCH_HDR(p, 0, pdb_end);
3599         return PROGRAM_FINALIZE(p);
3600 }
3601
3602 /**
3603  * cnstr_shdsc_pdcp_short_mac - Function for creating a PDCP Short MAC
3604  *                              descriptor.
3605  * @descbuf: pointer to buffer for descriptor construction
3606  * @ps: if 36/40bit addressing is desired, this parameter must be true
3607  * @swap: must be true when core endianness doesn't match SEC endianness
3608  * @authdata: pointer to authentication transform definitions
3609  *            Valid algorithm values are those from auth_type_pdcp enum.
3610  *
3611  * Return: size of descriptor written in words or negative number on error.
3612  *         Once the function returns, the value of this parameter can be used
3613  *         for reclaiming the space that wasn't used for the descriptor.
3614  *
3615  * Note: descbuf must be large enough to contain a full 256 byte long
3616  * descriptor; after the function returns, by subtracting the actual number of
3617  * bytes used, the user can reuse the remaining buffer space for other purposes.
3618  */
3619 static inline int
3620 cnstr_shdsc_pdcp_short_mac(uint32_t *descbuf,
3621                            bool ps,
3622                            bool swap,
3623                            struct alginfo *authdata)
3624 {
3625         struct program prg;
3626         struct program *p = &prg;
3627         uint32_t iv[3] = {0, 0, 0};
3628         LABEL(local_offset);
3629         REFERENCE(move_cmd_read_descbuf);
3630         REFERENCE(move_cmd_write_descbuf);
3631
3632         PROGRAM_CNTXT_INIT(p, descbuf, 0);
3633         if (swap)
3634                 PROGRAM_SET_BSWAP(p);
3635         if (ps)
3636                 PROGRAM_SET_36BIT_ADDR(p);
3637
3638         SHR_HDR(p, SHR_ALWAYS, 1, 0);
3639
3640         if (rta_sec_era > RTA_SEC_ERA_2) {
3641                 MATHB(p, SEQINSZ, SUB, ZERO, VSEQINSZ, 4, 0);
3642                 MATHB(p, SEQINSZ, SUB, ZERO, MATH1, 4, 0);
3643         } else {
3644                 MATHB(p, SEQINSZ, ADD, ONE, MATH1, 4, 0);
3645                 MATHB(p, MATH1, SUB, ONE, MATH1, 4, 0);
3646                 MATHB(p, ZERO, ADD, MATH1, VSEQINSZ, 4, 0);
3647                 MOVE(p, MATH1, 0, MATH0, 0, 8, IMMED);
3648
3649                 /*
3650                  * Since MOVELEN is available only starting with
3651                  * SEC ERA 3, use poor man's MOVELEN: create a MOVE
3652                  * command dynamically by writing the length from M1 by
3653                  * OR-ing the command in the M1 register and MOVE the
3654                  * result into the descriptor buffer. Care must be taken
3655                  * wrt. the location of the command because of SEC
3656                  * pipelining. The actual MOVEs are written at the end
3657                  * of the descriptor due to calculations needed on the
3658                  * offset in the descriptor for the MOVE command.
3659                  */
3660                 move_cmd_read_descbuf = MOVE(p, DESCBUF, 0, MATH0, 0, 6,
3661                                              IMMED);
3662                 move_cmd_write_descbuf = MOVE(p, MATH0, 0, DESCBUF, 0, 8,
3663                                               WAITCOMP | IMMED);
3664         }
3665         MATHB(p, ZERO, ADD, MATH1, VSEQOUTSZ, 4, 0);
3666
3667         switch (authdata->algtype) {
3668         case PDCP_AUTH_TYPE_NULL:
3669                 SEQFIFOSTORE(p, MSG, 0, 0, VLF);
3670                 if (rta_sec_era > RTA_SEC_ERA_2) {
3671                         MOVE(p, AB1, 0, OFIFO, 0, MATH1, 0);
3672                 } else {
3673                         SET_LABEL(p, local_offset);
3674
3675                         /* Shut off automatic Info FIFO entries */
3676                         LOAD(p, 0, DCTRL, LDOFF_DISABLE_AUTO_NFIFO, 0, IMMED);
3677
3678                         /* Placeholder for MOVE command with length from M1
3679                          * register
3680                          */
3681                         MOVE(p, IFIFOAB1, 0, OFIFO, 0, 0, IMMED);
3682
3683                         /* Enable automatic Info FIFO entries */
3684                         LOAD(p, 0, DCTRL, LDOFF_ENABLE_AUTO_NFIFO, 0, IMMED);
3685                 }
3686
3687                 LOAD(p, (uintptr_t)iv, MATH0, 0, 8, IMMED | COPY);
3688                 SEQFIFOLOAD(p, MSG1, 0, VLF | LAST1 | LAST2 | FLUSH1);
3689                 SEQSTORE(p, MATH0, 0, 4, 0);
3690
3691                 break;
3692
3693         case PDCP_AUTH_TYPE_SNOW:
3694                 iv[0] = 0xFFFFFFFF;
3695                 iv[1] = swap ? swab32(0x04000000) : 0x04000000;
3696                 iv[2] = swap ? swab32(0xF8000000) : 0xF8000000;
3697
3698                 KEY(p, KEY2, authdata->key_enc_flags, authdata->key,
3699                     authdata->keylen, INLINE_KEY(authdata));
3700                 LOAD(p, (uintptr_t)&iv, CONTEXT2, 0, 12, IMMED | COPY);
3701                 ALG_OPERATION(p, OP_ALG_ALGSEL_SNOW_F9,
3702                               OP_ALG_AAI_F9,
3703                               OP_ALG_AS_INITFINAL,
3704                               ICV_CHECK_DISABLE,
3705                               DIR_ENC);
3706                 SEQFIFOSTORE(p, MSG, 0, 0, VLF);
3707
3708                 if (rta_sec_era > RTA_SEC_ERA_2) {
3709                         MOVE(p, AB1, 0, OFIFO, 0, MATH1, 0);
3710                 } else {
3711                         SET_LABEL(p, local_offset);
3712
3713
3714                         /* Shut off automatic Info FIFO entries */
3715                         LOAD(p, 0, DCTRL, LDOFF_DISABLE_AUTO_NFIFO, 0, IMMED);
3716
3717                         /* Placeholder for MOVE command with length from M1
3718                          * register
3719                          */
3720                         MOVE(p, IFIFOAB1, 0, OFIFO, 0, 0, IMMED);
3721
3722                         /* Enable automatic Info FIFO entries */
3723                         LOAD(p, 0, DCTRL, LDOFF_ENABLE_AUTO_NFIFO, 0, IMMED);
3724                 }
3725                 SEQFIFOLOAD(p, MSGINSNOOP, 0, VLF | LAST1 | LAST2 | FLUSH1);
3726                 SEQSTORE(p, CONTEXT2, 0, 4, 0);
3727
3728                 break;
3729
3730         case PDCP_AUTH_TYPE_AES:
3731                 iv[0] = 0xFFFFFFFF;
3732                 iv[1] = swap ? swab32(0xFC000000) : 0xFC000000;
3733                 iv[2] = 0x00000000; /* unused */
3734
3735                 KEY(p, KEY1, authdata->key_enc_flags, authdata->key,
3736                     authdata->keylen, INLINE_KEY(authdata));
3737                 LOAD(p, (uintptr_t)&iv, MATH0, 0, 8, IMMED | COPY);
3738                 MOVE(p, MATH0, 0, IFIFOAB1, 0, 8, IMMED);
3739                 ALG_OPERATION(p, OP_ALG_ALGSEL_AES,
3740                               OP_ALG_AAI_CMAC,
3741                               OP_ALG_AS_INITFINAL,
3742                               ICV_CHECK_DISABLE,
3743                               DIR_ENC);
3744                 SEQFIFOSTORE(p, MSG, 0, 0, VLF);
3745
3746                 if (rta_sec_era > RTA_SEC_ERA_2) {
3747                         MOVE(p, AB2, 0, OFIFO, 0, MATH1, 0);
3748                 } else {
3749                         SET_LABEL(p, local_offset);
3750
3751                         /* Shut off automatic Info FIFO entries */
3752                         LOAD(p, 0, DCTRL, LDOFF_DISABLE_AUTO_NFIFO, 0, IMMED);
3753
3754                         /* Placeholder for MOVE command with length from M1
3755                          * register
3756                          */
3757                         MOVE(p, IFIFOAB2, 0, OFIFO, 0, 0, IMMED);
3758
3759                         /* Enable automatic Info FIFO entries */
3760                         LOAD(p, 0, DCTRL, LDOFF_ENABLE_AUTO_NFIFO, 0, IMMED);
3761                 }
3762                 SEQFIFOLOAD(p, MSGINSNOOP, 0, VLF | LAST1 | LAST2 | FLUSH1);
3763                 SEQSTORE(p, CONTEXT1, 0, 4, 0);
3764
3765                 break;
3766
3767         case PDCP_AUTH_TYPE_ZUC:
3768                 if (rta_sec_era < RTA_SEC_ERA_5) {
3769                         pr_err("Invalid era for selected algorithm\n");
3770                         return -ENOTSUP;
3771                 }
3772                 iv[0] = 0xFFFFFFFF;
3773                 iv[1] = swap ? swab32(0xFC000000) : 0xFC000000;
3774                 iv[2] = 0x00000000; /* unused */
3775
3776                 KEY(p, KEY2, authdata->key_enc_flags, authdata->key,
3777                     authdata->keylen, INLINE_KEY(authdata));
3778                 LOAD(p, (uintptr_t)&iv, CONTEXT2, 0, 12, IMMED | COPY);
3779                 ALG_OPERATION(p, OP_ALG_ALGSEL_ZUCA,
3780                               OP_ALG_AAI_F9,
3781                               OP_ALG_AS_INITFINAL,
3782                               ICV_CHECK_DISABLE,
3783                               DIR_ENC);
3784                 SEQFIFOSTORE(p, MSG, 0, 0, VLF);
3785                 MOVE(p, AB1, 0, OFIFO, 0, MATH1, 0);
3786                 SEQFIFOLOAD(p, MSGINSNOOP, 0, VLF | LAST1 | LAST2 | FLUSH1);
3787                 SEQSTORE(p, CONTEXT2, 0, 4, 0);
3788
3789                 break;
3790
3791         default:
3792                 pr_err("%s: Invalid integrity algorithm selected: %d\n",
3793                        "cnstr_shdsc_pdcp_short_mac", authdata->algtype);
3794                 return -EINVAL;
3795         }
3796
3797
3798         if (rta_sec_era < RTA_SEC_ERA_3) {
3799                 PATCH_MOVE(p, move_cmd_read_descbuf, local_offset);
3800                 PATCH_MOVE(p, move_cmd_write_descbuf, local_offset);
3801         }
3802
3803         return PROGRAM_FINALIZE(p);
3804 }
3805
3806 #endif /* __DESC_PDCP_H__ */