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