a636640c4a4b2b4c719479017acb58ea0d80e541
[dpdk.git] / drivers / crypto / dpaa2_sec / hw / desc / pdcp.h
1 /* SPDX-License-Identifier: BSD-3-Clause or GPL-2.0+
2  * Copyright 2008-2013 Freescale Semiconductor, Inc.
3  */
4
5 #ifndef __DESC_PDCP_H__
6 #define __DESC_PDCP_H__
7
8 #include "hw/rta.h"
9 #include "common.h"
10
11 /**
12  * DOC: PDCP Shared Descriptor Constructors
13  *
14  * Shared descriptors for PDCP protocol.
15  */
16
17 /**
18  * PDCP_NULL_MAX_FRAME_LEN - The maximum frame frame length that is supported by
19  *                           PDCP NULL protocol.
20  */
21 #define PDCP_NULL_MAX_FRAME_LEN         0x00002FFF
22
23 /**
24  * PDCP_MAC_I_LEN - The length of the MAC-I for PDCP protocol operation
25  */
26 #define PDCP_MAC_I_LEN                  0x00000004
27
28 /**
29  * PDCP_MAX_FRAME_LEN_STATUS - The status returned in FD status/command field in
30  *                             case the input frame is larger than
31  *                             PDCP_NULL_MAX_FRAME_LEN.
32  */
33 #define PDCP_MAX_FRAME_LEN_STATUS       0xF1
34
35 /**
36  * PDCP_C_PLANE_SN_MASK - This mask is used in the PDCP descriptors for
37  *                        extracting the sequence number (SN) from the PDCP
38  *                        Control Plane header. For PDCP Control Plane, the SN
39  *                        is constant (5 bits) as opposed to PDCP Data Plane
40  *                        (7/12/15 bits).
41  */
42 #define PDCP_C_PLANE_SN_MASK            0x1F000000
43 #define PDCP_C_PLANE_SN_MASK_BE         0x0000001F
44
45 /**
46  * PDCP_U_PLANE_15BIT_SN_MASK - This mask is used in the PDCP descriptors for
47  *                              extracting the sequence number (SN) from the
48  *                              PDCP User Plane header. For PDCP Control Plane,
49  *                              the SN is constant (5 bits) as opposed to PDCP
50  *                              Data Plane (7/12/15 bits).
51  */
52 #define PDCP_U_PLANE_15BIT_SN_MASK      0xFF7F0000
53 #define PDCP_U_PLANE_15BIT_SN_MASK_BE   0x00007FFF
54
55 /**
56  * PDCP_BEARER_MASK - This mask is used masking out the bearer for PDCP
57  *                    processing with SNOW f9 in LTE.
58  *
59  * The value on which this mask is applied is formatted as below:
60  *     Count-C (32 bit) | Bearer (5 bit) | Direction (1 bit) | 0 (26 bits)
61  *
62  * Applying this mask is done for creating the upper 64 bits of the IV needed
63  * for SNOW f9.
64  *
65  * The lower 32 bits of the mask are used for masking the direction for AES
66  * CMAC IV.
67  */
68 #define PDCP_BEARER_MASK                0x00000004FFFFFFFFull
69 #define PDCP_BEARER_MASK_BE             0xFFFFFFFF04000000ull
70
71 /**
72  * PDCP_DIR_MASK - This mask is used masking out the direction for PDCP
73  *                 processing with SNOW f9 in LTE.
74  *
75  * The value on which this mask is applied is formatted as below:
76  *     Bearer (5 bit) | Direction (1 bit) | 0 (26 bits)
77  *
78  * Applying this mask is done for creating the lower 32 bits of the IV needed
79  * for SNOW f9.
80  *
81  * The upper 32 bits of the mask are used for masking the direction for AES
82  * CMAC IV.
83  */
84 #define PDCP_DIR_MASK                   0x00000000000000F8ull
85 #define PDCP_DIR_MASK_BE                        0xF800000000000000ull
86
87 /**
88  * PDCP_NULL_INT_MAC_I_VAL - The value of the PDCP PDU MAC-I in case NULL
89  *                           integrity is used.
90  */
91
92 #define PDCP_NULL_INT_MAC_I_VAL         0x00000000
93
94 /**
95  * PDCP_NULL_INT_ICV_CHECK_FAILED_STATUS - The status used to report ICV check
96  *                                         failed in case of NULL integrity
97  *                                         Control Plane processing.
98  */
99 #define PDCP_NULL_INT_ICV_CHECK_FAILED_STATUS   0x0A
100 /**
101  * PDCP_DPOVRD_HFN_OV_EN - Value to be used in the FD status/cmd field to
102  *                         indicate the HFN override mechanism is active for the
103  *                         frame.
104  */
105 #define PDCP_DPOVRD_HFN_OV_EN           0x80000000
106
107 /**
108  * PDCP_P4080REV2_HFN_OV_BUFLEN - The length in bytes of the supplementary space
109  *                                that must be provided by the user at the
110  *                                beginning of the input frame buffer for
111  *                                P4080 REV 2.
112  *
113  * The format of the frame buffer is the following:
114  *
115  *  |<---PDCP_P4080REV2_HFN_OV_BUFLEN-->|
116  * //===================================||============||==============\\
117  * || PDCP_DPOVRD_HFN_OV_EN | HFN value || PDCP Header|| PDCP Payload ||
118  * \\===================================||============||==============//
119  *
120  * If HFN override mechanism is not desired, then the MSB of the first 4 bytes
121  * must be set to 0b.
122  */
123 #define PDCP_P4080REV2_HFN_OV_BUFLEN    4
124
125 /**
126  * enum cipher_type_pdcp - Type selectors for cipher types in PDCP protocol OP
127  *                         instructions.
128  * @PDCP_CIPHER_TYPE_NULL: NULL
129  * @PDCP_CIPHER_TYPE_SNOW: SNOW F8
130  * @PDCP_CIPHER_TYPE_AES: AES
131  * @PDCP_CIPHER_TYPE_ZUC: ZUCE
132  * @PDCP_CIPHER_TYPE_INVALID: invalid option
133  */
134 enum cipher_type_pdcp {
135         PDCP_CIPHER_TYPE_NULL,
136         PDCP_CIPHER_TYPE_SNOW,
137         PDCP_CIPHER_TYPE_AES,
138         PDCP_CIPHER_TYPE_ZUC,
139         PDCP_CIPHER_TYPE_INVALID
140 };
141
142 /**
143  * enum auth_type_pdcp - Type selectors for integrity types in PDCP protocol OP
144  *                       instructions.
145  * @PDCP_AUTH_TYPE_NULL: NULL
146  * @PDCP_AUTH_TYPE_SNOW: SNOW F9
147  * @PDCP_AUTH_TYPE_AES: AES CMAC
148  * @PDCP_AUTH_TYPE_ZUC: ZUCA
149  * @PDCP_AUTH_TYPE_INVALID: invalid option
150  */
151 enum auth_type_pdcp {
152         PDCP_AUTH_TYPE_NULL,
153         PDCP_AUTH_TYPE_SNOW,
154         PDCP_AUTH_TYPE_AES,
155         PDCP_AUTH_TYPE_ZUC,
156         PDCP_AUTH_TYPE_INVALID
157 };
158
159 /**
160  * enum pdcp_dir - Type selectors for direction for PDCP protocol
161  * @PDCP_DIR_UPLINK: uplink direction
162  * @PDCP_DIR_DOWNLINK: downlink direction
163  * @PDCP_DIR_INVALID: invalid option
164  */
165 enum pdcp_dir {
166         PDCP_DIR_UPLINK = 0,
167         PDCP_DIR_DOWNLINK = 1,
168         PDCP_DIR_INVALID
169 };
170
171 /**
172  * enum pdcp_plane - PDCP domain selectors
173  * @PDCP_CONTROL_PLANE: Control Plane
174  * @PDCP_DATA_PLANE: Data Plane
175  * @PDCP_SHORT_MAC: Short MAC
176  */
177 enum pdcp_plane {
178         PDCP_CONTROL_PLANE,
179         PDCP_DATA_PLANE,
180         PDCP_SHORT_MAC
181 };
182
183 /**
184  * enum pdcp_sn_size - Sequence Number Size selectors for PDCP protocol
185  * @PDCP_SN_SIZE_5: 5bit sequence number
186  * @PDCP_SN_SIZE_7: 7bit sequence number
187  * @PDCP_SN_SIZE_12: 12bit sequence number
188  * @PDCP_SN_SIZE_15: 15bit sequence number
189  * @PDCP_SN_SIZE_18: 18bit sequence number
190  */
191 enum pdcp_sn_size {
192         PDCP_SN_SIZE_5 = 5,
193         PDCP_SN_SIZE_7 = 7,
194         PDCP_SN_SIZE_12 = 12,
195         PDCP_SN_SIZE_15 = 15
196 };
197
198 /*
199  * PDCP Control Plane Protocol Data Blocks
200  */
201 #define PDCP_C_PLANE_PDB_HFN_SHIFT              5
202 #define PDCP_C_PLANE_PDB_BEARER_SHIFT           27
203 #define PDCP_C_PLANE_PDB_DIR_SHIFT              26
204 #define PDCP_C_PLANE_PDB_HFN_THR_SHIFT          5
205
206 #define PDCP_U_PLANE_PDB_OPT_SHORT_SN           0x2
207 #define PDCP_U_PLANE_PDB_OPT_15B_SN             0x4
208 #define PDCP_U_PLANE_PDB_SHORT_SN_HFN_SHIFT     7
209 #define PDCP_U_PLANE_PDB_LONG_SN_HFN_SHIFT      12
210 #define PDCP_U_PLANE_PDB_15BIT_SN_HFN_SHIFT     15
211 #define PDCP_U_PLANE_PDB_BEARER_SHIFT           27
212 #define PDCP_U_PLANE_PDB_DIR_SHIFT              26
213 #define PDCP_U_PLANE_PDB_SHORT_SN_HFN_THR_SHIFT 7
214 #define PDCP_U_PLANE_PDB_LONG_SN_HFN_THR_SHIFT  12
215 #define PDCP_U_PLANE_PDB_15BIT_SN_HFN_THR_SHIFT 15
216
217 struct pdcp_pdb {
218         union {
219                 uint32_t opt;
220                 uint32_t rsvd;
221         } opt_res;
222         uint32_t hfn_res;       /* HyperFrame number,(27, 25 or 21 bits),
223                                  * left aligned & right-padded with zeros.
224                                  */
225         uint32_t bearer_dir_res;/* Bearer(5 bits), packet direction (1 bit),
226                                  * left aligned & right-padded with zeros.
227                                  */
228         uint32_t hfn_thr_res;   /* HyperFrame number threshold (27, 25 or 21
229                                  * bits), left aligned & right-padded with
230                                  * zeros.
231                                  */
232 };
233
234 /*
235  * PDCP internal PDB types
236  */
237 enum pdb_type_e {
238         PDCP_PDB_TYPE_NO_PDB,
239         PDCP_PDB_TYPE_FULL_PDB,
240         PDCP_PDB_TYPE_REDUCED_PDB,
241         PDCP_PDB_TYPE_INVALID
242 };
243
244 /*
245  * Function for appending the portion of a PDCP Control Plane shared descriptor
246  * which performs NULL encryption and integrity (i.e. copies the input frame
247  * to the output frame, appending 32 bits of zeros at the end (MAC-I for
248  * NULL integrity).
249  */
250 static inline int
251 pdcp_insert_cplane_null_op(struct program *p,
252                            bool swap __maybe_unused,
253                            struct alginfo *cipherdata __maybe_unused,
254                            struct alginfo *authdata __maybe_unused,
255                            unsigned int dir,
256                            enum pdcp_sn_size sn_size __maybe_unused,
257                            unsigned char era_2_sw_hfn_ovrd __maybe_unused)
258 {
259         LABEL(local_offset);
260         REFERENCE(move_cmd_read_descbuf);
261         REFERENCE(move_cmd_write_descbuf);
262
263         if (rta_sec_era > RTA_SEC_ERA_2) {
264                 MATHB(p, SEQINSZ, ADD, ZERO, VSEQINSZ, 4, 0);
265                 if (dir == OP_TYPE_ENCAP_PROTOCOL)
266                         MATHB(p, SEQINSZ, ADD, PDCP_MAC_I_LEN, VSEQOUTSZ, 4,
267                               IMMED2);
268                 else
269                         MATHB(p, SEQINSZ, SUB, PDCP_MAC_I_LEN, VSEQOUTSZ, 4,
270                               IMMED2);
271         } else {
272                 MATHB(p, SEQINSZ, ADD, ONE, VSEQINSZ, 4, 0);
273                 MATHB(p, VSEQINSZ, SUB, ONE, VSEQINSZ, 4, 0);
274
275                 if (dir == OP_TYPE_ENCAP_PROTOCOL) {
276                         MATHB(p, SEQINSZ, ADD, PDCP_MAC_I_LEN, VSEQOUTSZ, 4,
277                               IMMED2);
278                         MATHB(p, VSEQINSZ, SUB, ONE, MATH0, 4, 0);
279                 } else {
280                         MATHB(p, VSEQINSZ, SUB, PDCP_MAC_I_LEN, VSEQINSZ, 4,
281                               IMMED2);
282                         MATHB(p, SEQINSZ, SUB, PDCP_MAC_I_LEN, VSEQOUTSZ, 4,
283                               IMMED2);
284                         MATHB(p, VSEQOUTSZ, SUB, ONE, MATH0, 4, 0);
285                 }
286
287                 MATHB(p, MATH0, ADD, ONE, MATH0, 4, 0);
288
289                 /*
290                  * Since MOVELEN is available only starting with
291                  * SEC ERA 3, use poor man's MOVELEN: create a MOVE
292                  * command dynamically by writing the length from M1 by
293                  * OR-ing the command in the M1 register and MOVE the
294                  * result into the descriptor buffer. Care must be taken
295                  * wrt. the location of the command because of SEC
296                  * pipelining. The actual MOVEs are written at the end
297                  * of the descriptor due to calculations needed on the
298                  * offset in the descriptor for the MOVE command.
299                  */
300                 move_cmd_read_descbuf = MOVE(p, DESCBUF, 0, MATH0, 0, 6,
301                                              IMMED);
302                 move_cmd_write_descbuf = MOVE(p, MATH0, 0, DESCBUF, 0, 8,
303                                               WAITCOMP | IMMED);
304         }
305         MATHB(p, VSEQINSZ, SUB, PDCP_NULL_MAX_FRAME_LEN, NONE, 4,
306               IMMED2);
307         JUMP(p, PDCP_MAX_FRAME_LEN_STATUS, HALT_STATUS, ALL_FALSE, MATH_N);
308
309         if (rta_sec_era > RTA_SEC_ERA_2) {
310                 if (dir == OP_TYPE_ENCAP_PROTOCOL)
311                         MATHB(p, VSEQINSZ, ADD, ZERO, MATH0, 4, 0);
312                 else
313                         MATHB(p, VSEQOUTSZ, ADD, ZERO, MATH0, 4, 0);
314         }
315         SEQFIFOSTORE(p, MSG, 0, 0, VLF);
316         SEQFIFOLOAD(p, MSG1, 0, VLF | LAST1 | FLUSH1);
317
318         if (rta_sec_era > RTA_SEC_ERA_2) {
319                 MOVE(p, AB1, 0, OFIFO, 0, MATH0, 0);
320         } else {
321                 SET_LABEL(p, local_offset);
322
323                 /* Shut off automatic Info FIFO entries */
324                 LOAD(p, 0, DCTRL, LDOFF_DISABLE_AUTO_NFIFO, 0, IMMED);
325                 /* Placeholder for MOVE command with length from M1 register */
326                 MOVE(p, IFIFOAB1, 0, OFIFO, 0, 0, IMMED);
327                 /* Enable automatic Info FIFO entries */
328                 LOAD(p, 0, DCTRL, LDOFF_ENABLE_AUTO_NFIFO, 0, IMMED);
329         }
330
331         if (dir == OP_TYPE_ENCAP_PROTOCOL) {
332                 MATHB(p, MATH1, XOR, MATH1, MATH0, 8, 0);
333                 MOVE(p, MATH0, 0, OFIFO, 0, 4, IMMED);
334         }
335
336         if (rta_sec_era < RTA_SEC_ERA_3) {
337                 PATCH_MOVE(p, move_cmd_read_descbuf, local_offset);
338                 PATCH_MOVE(p, move_cmd_write_descbuf, local_offset);
339         }
340
341         return 0;
342 }
343
344 static inline int
345 insert_copy_frame_op(struct program *p,
346                      struct alginfo *cipherdata __maybe_unused,
347                      unsigned int dir __maybe_unused)
348 {
349         LABEL(local_offset);
350         REFERENCE(move_cmd_read_descbuf);
351         REFERENCE(move_cmd_write_descbuf);
352
353         if (rta_sec_era > RTA_SEC_ERA_2) {
354                 MATHB(p, SEQINSZ, ADD, ZERO, VSEQINSZ,  4, 0);
355                 MATHB(p, SEQINSZ, ADD, ZERO, VSEQOUTSZ,  4, 0);
356         } else {
357                 MATHB(p, SEQINSZ, ADD, ONE, VSEQINSZ,  4, 0);
358                 MATHB(p, VSEQINSZ, SUB, ONE, VSEQINSZ,  4, 0);
359                 MATHB(p, SEQINSZ, ADD, ONE, VSEQOUTSZ,  4, 0);
360                 MATHB(p, VSEQOUTSZ, SUB, ONE, VSEQOUTSZ,  4, 0);
361                 MATHB(p, VSEQINSZ, SUB, ONE, MATH0,  4, 0);
362                 MATHB(p, MATH0, ADD, ONE, MATH0,  4, 0);
363
364                 /*
365                  * Since MOVELEN is available only starting with
366                  * SEC ERA 3, use poor man's MOVELEN: create a MOVE
367                  * command dynamically by writing the length from M1 by
368                  * OR-ing the command in the M1 register and MOVE the
369                  * result into the descriptor buffer. Care must be taken
370                  * wrt. the location of the command because of SEC
371                  * pipelining. The actual MOVEs are written at the end
372                  * of the descriptor due to calculations needed on the
373                  * offset in the descriptor for the MOVE command.
374                  */
375                 move_cmd_read_descbuf = MOVE(p, DESCBUF, 0, MATH0, 0, 6,
376                                              IMMED);
377                 move_cmd_write_descbuf = MOVE(p, MATH0, 0, DESCBUF, 0, 8,
378                                               WAITCOMP | IMMED);
379         }
380         MATHB(p, SEQINSZ, SUB, PDCP_NULL_MAX_FRAME_LEN, NONE,  4,
381               IFB | IMMED2);
382         JUMP(p, PDCP_MAX_FRAME_LEN_STATUS, HALT_STATUS, ALL_FALSE, MATH_N);
383
384         if (rta_sec_era > RTA_SEC_ERA_2)
385                 MATHB(p, VSEQINSZ, ADD, ZERO, MATH0,  4, 0);
386
387         SEQFIFOLOAD(p, MSG1, 0, VLF | LAST1 | FLUSH1);
388         if (rta_sec_era > RTA_SEC_ERA_2) {
389                 MOVE(p, AB1, 0, OFIFO, 0, MATH0, 0);
390         } else {
391                 SET_LABEL(p, local_offset);
392
393                 /* Shut off automatic Info FIFO entries */
394                 LOAD(p, 0, DCTRL, LDOFF_DISABLE_AUTO_NFIFO, 0, IMMED);
395
396                 /* Placeholder for MOVE command with length from M0 register */
397                 MOVE(p, IFIFOAB1, 0, OFIFO, 0, 0, IMMED);
398
399                 /* Enable automatic Info FIFO entries */
400                 LOAD(p, 0, DCTRL, LDOFF_ENABLE_AUTO_NFIFO, 0, IMMED);
401         }
402
403         SEQFIFOSTORE(p, MSG, 0, 0, VLF);
404
405         if (rta_sec_era < RTA_SEC_ERA_3) {
406                 PATCH_MOVE(p, move_cmd_read_descbuf, local_offset);
407                 PATCH_MOVE(p, move_cmd_write_descbuf, local_offset);
408         }
409         return 0;
410 }
411
412 static inline int
413 pdcp_insert_cplane_int_only_op(struct program *p,
414                                bool swap __maybe_unused,
415                                struct alginfo *cipherdata __maybe_unused,
416                                struct alginfo *authdata, unsigned int dir,
417                                enum pdcp_sn_size sn_size,
418                                unsigned char era_2_sw_hfn_ovrd)
419 {
420         if (rta_sec_era >= RTA_SEC_ERA_8 && sn_size == PDCP_SN_SIZE_12) {
421                 KEY(p, KEY2, authdata->key_enc_flags, authdata->key,
422                     authdata->keylen, INLINE_KEY(authdata));
423
424                 PROTOCOL(p, dir, OP_PCLID_LTE_PDCP_USER_RN,
425                          (uint16_t)authdata->algtype);
426                 return 0;
427         }
428
429         LABEL(local_offset);
430         REFERENCE(move_cmd_read_descbuf);
431         REFERENCE(move_cmd_write_descbuf);
432
433         switch (authdata->algtype) {
434         case PDCP_AUTH_TYPE_SNOW:
435                 /* Insert Auth Key */
436                 KEY(p, KEY2, authdata->key_enc_flags, authdata->key,
437                     authdata->keylen, INLINE_KEY(authdata));
438                 SEQLOAD(p, MATH0, 7, 1, 0);
439                 JUMP(p, 1, LOCAL_JUMP, ALL_TRUE, CALM);
440
441                 if (rta_sec_era > RTA_SEC_ERA_2 ||
442                     (rta_sec_era == RTA_SEC_ERA_2 &&
443                                    era_2_sw_hfn_ovrd == 0)) {
444                         SEQINPTR(p, 0, 1, RTO);
445                 } else {
446                         SEQINPTR(p, 0, 5, RTO);
447                         SEQFIFOLOAD(p, SKIP, 4, 0);
448                 }
449
450                 if (swap == false) {
451                         MATHB(p, MATH0, AND, PDCP_C_PLANE_SN_MASK, MATH1,  8,
452                               IFB | IMMED2);
453                         MATHB(p, MATH1, SHLD, MATH1, MATH1,  8, 0);
454
455                         MOVEB(p, DESCBUF, 8, MATH2, 0, 8, WAITCOMP | IMMED);
456
457                         MATHB(p, MATH2, AND, PDCP_BEARER_MASK, MATH2, 8,
458                               IMMED2);
459                         MOVEB(p, DESCBUF, 0x0C, MATH3, 0, 4, WAITCOMP | IMMED);
460                         MATHB(p, MATH3, AND, PDCP_DIR_MASK, MATH3, 8, IMMED2);
461                         MATHB(p, MATH1, OR, MATH2, MATH2, 8, 0);
462                         MOVEB(p, MATH2, 0, CONTEXT2, 0, 0x0C, WAITCOMP | IMMED);
463                 } else {
464                         MATHB(p, MATH0, AND, PDCP_C_PLANE_SN_MASK_BE, MATH1,  8,
465                               IFB | IMMED2);
466                         MATHB(p, MATH1, SHLD, MATH1, MATH1,  8, 0);
467
468                         MOVE(p, DESCBUF, 8, MATH2, 0, 8, WAITCOMP | IMMED);
469                         MATHB(p, MATH2, AND, PDCP_BEARER_MASK_BE, MATH2, 8,
470                               IMMED2);
471
472                         MOVE(p, DESCBUF, 0x0C, MATH3, 0, 4, WAITCOMP | IMMED);
473                         MATHB(p, MATH3, AND, PDCP_DIR_MASK_BE, MATH3, 8,
474                               IMMED2);
475                         MATHB(p, MATH1, OR, MATH2, MATH2, 8, 0);
476                         MOVE(p, MATH2, 0, CONTEXT2, 0, 0x0C, WAITCOMP | IMMED);
477                 }
478
479                 if (dir == OP_TYPE_DECAP_PROTOCOL) {
480                         MATHB(p, SEQINSZ, SUB, PDCP_MAC_I_LEN, MATH1, 4,
481                               IMMED2);
482                 } else {
483                         if (rta_sec_era > RTA_SEC_ERA_2) {
484                                 MATHB(p, SEQINSZ, SUB, ZERO, MATH1, 4,
485                                       0);
486                         } else {
487                                 MATHB(p, SEQINSZ, ADD, ONE, MATH1, 4,
488                                       0);
489                                 MATHB(p, MATH1, SUB, ONE, MATH1, 4,
490                                       0);
491                         }
492                 }
493
494                 if (rta_sec_era > RTA_SEC_ERA_2) {
495                         MATHB(p, MATH1, SUB, ZERO, VSEQINSZ, 4, 0);
496                         MATHB(p, MATH1, SUB, ZERO, VSEQOUTSZ, 4, 0);
497                 } else {
498                         MATHB(p, ZERO, ADD, MATH1, VSEQINSZ, 4, 0);
499                         MATHB(p, ZERO, ADD, MATH1, VSEQOUTSZ, 4, 0);
500
501                         /*
502                          * Since MOVELEN is available only starting with
503                          * SEC ERA 3, use poor man's MOVELEN: create a MOVE
504                          * command dynamically by writing the length from M1 by
505                          * OR-ing the command in the M1 register and MOVE the
506                          * result into the descriptor buffer. Care must be taken
507                          * wrt. the location of the command because of SEC
508                          * pipelining. The actual MOVEs are written at the end
509                          * of the descriptor due to calculations needed on the
510                          * offset in the descriptor for the MOVE command.
511                          */
512                         move_cmd_read_descbuf = MOVE(p, DESCBUF, 0, MATH1, 0, 6,
513                                                      IMMED);
514                         move_cmd_write_descbuf = MOVE(p, MATH1, 0, DESCBUF, 0,
515                                                       8, WAITCOMP | IMMED);
516                 }
517
518                 SEQFIFOSTORE(p, MSG, 0, 0, VLF);
519                 ALG_OPERATION(p, OP_ALG_ALGSEL_SNOW_F9, OP_ALG_AAI_F9,
520                               OP_ALG_AS_INITFINAL,
521                               dir == OP_TYPE_ENCAP_PROTOCOL ?
522                                      ICV_CHECK_DISABLE : ICV_CHECK_ENABLE,
523                               DIR_ENC);
524
525                 if (rta_sec_era > RTA_SEC_ERA_2) {
526                         SEQFIFOLOAD(p, MSGINSNOOP, 0,
527                                     VLF | LAST1 | LAST2 | FLUSH1);
528                         MOVE(p, AB1, 0, OFIFO, 0, MATH1, 0);
529                 } else {
530                         SEQFIFOLOAD(p, MSGINSNOOP, 0,
531                                     VLF | LAST1 | LAST2 | FLUSH1);
532                         SET_LABEL(p, local_offset);
533
534                         /* Shut off automatic Info FIFO entries */
535                         LOAD(p, 0, DCTRL, LDOFF_DISABLE_AUTO_NFIFO, 0, IMMED);
536                         /*
537                          * Placeholder for MOVE command with length from M1
538                          * register
539                          */
540                         MOVE(p, IFIFOAB1, 0, OFIFO, 0, 0, IMMED);
541                         /* Enable automatic Info FIFO entries */
542                         LOAD(p, 0, DCTRL, LDOFF_ENABLE_AUTO_NFIFO, 0, IMMED);
543                 }
544
545                 if (dir == OP_TYPE_DECAP_PROTOCOL)
546                         SEQFIFOLOAD(p, ICV2, 4, LAST2);
547                 else
548                         SEQSTORE(p, CONTEXT2, 0, 4, 0);
549
550                 break;
551
552         case PDCP_AUTH_TYPE_AES:
553                 /* Insert Auth Key */
554                 KEY(p, KEY1, authdata->key_enc_flags, authdata->key,
555                     authdata->keylen, INLINE_KEY(authdata));
556                 SEQLOAD(p, MATH0, 7, 1, 0);
557                 JUMP(p, 1, LOCAL_JUMP, ALL_TRUE, CALM);
558                 if (rta_sec_era > RTA_SEC_ERA_2 ||
559                     (rta_sec_era == RTA_SEC_ERA_2 &&
560                      era_2_sw_hfn_ovrd == 0)) {
561                         SEQINPTR(p, 0, 1, RTO);
562                 } else {
563                         SEQINPTR(p, 0, 5, RTO);
564                         SEQFIFOLOAD(p, SKIP, 4, 0);
565                 }
566
567                 if (swap == false) {
568                         MATHB(p, MATH0, AND, PDCP_C_PLANE_SN_MASK, MATH1, 8,
569                               IFB | IMMED2);
570                         MATHB(p, MATH1, SHLD, MATH1, MATH1, 8, 0);
571
572                         MOVEB(p, DESCBUF, 8, MATH2, 0, 8, WAITCOMP | IMMED);
573                         MATHB(p, MATH1, OR, MATH2, MATH2, 8, 0);
574                         MOVEB(p, MATH2, 0, IFIFOAB1, 0, 8, IMMED);
575                 } else {
576                         MATHB(p, MATH0, AND, PDCP_C_PLANE_SN_MASK_BE, MATH1, 8,
577                               IFB | IMMED2);
578                         MATHB(p, MATH1, SHLD, MATH1, MATH1, 8, 0);
579
580                         MOVE(p, DESCBUF, 8, MATH2, 0, 8, WAITCOMP | IMMED);
581                         MATHB(p, MATH1, OR, MATH2, MATH2, 8, 0);
582                         MOVE(p, MATH2, 0, IFIFOAB1, 0, 8, IMMED);
583                 }
584
585                 if (dir == OP_TYPE_DECAP_PROTOCOL) {
586                         MATHB(p, SEQINSZ, SUB, PDCP_MAC_I_LEN, MATH1, 4,
587                               IMMED2);
588                 } else {
589                         if (rta_sec_era > RTA_SEC_ERA_2) {
590                                 MATHB(p, SEQINSZ, SUB, ZERO, MATH1, 4,
591                                       0);
592                         } else {
593                                 MATHB(p, SEQINSZ, ADD, ONE, MATH1, 4,
594                                       0);
595                                 MATHB(p, MATH1, SUB, ONE, MATH1, 4,
596                                       0);
597                         }
598                 }
599
600                 if (rta_sec_era > RTA_SEC_ERA_2) {
601                         MATHB(p, MATH1, SUB, ZERO, VSEQINSZ, 4, 0);
602                         MATHB(p, MATH1, SUB, ZERO, VSEQOUTSZ, 4, 0);
603                 } else {
604                         MATHB(p, ZERO, ADD, MATH1, VSEQINSZ, 4, 0);
605                         MATHB(p, ZERO, ADD, MATH1, VSEQOUTSZ, 4, 0);
606
607                         /*
608                          * Since MOVELEN is available only starting with
609                          * SEC ERA 3, use poor man's MOVELEN: create a MOVE
610                          * command dynamically by writing the length from M1 by
611                          * OR-ing the command in the M1 register and MOVE the
612                          * result into the descriptor buffer. Care must be taken
613                          * wrt. the location of the command because of SEC
614                          * pipelining. The actual MOVEs are written at the end
615                          * of the descriptor due to calculations needed on the
616                          * offset in the descriptor for the MOVE command.
617                          */
618                         move_cmd_read_descbuf = MOVE(p, DESCBUF, 0, MATH1, 0, 6,
619                                                      IMMED);
620                         move_cmd_write_descbuf = MOVE(p, MATH1, 0, DESCBUF, 0,
621                                                       8, WAITCOMP | IMMED);
622                 }
623                 SEQFIFOSTORE(p, MSG, 0, 0, VLF);
624                 ALG_OPERATION(p, OP_ALG_ALGSEL_AES,
625                               OP_ALG_AAI_CMAC,
626                               OP_ALG_AS_INITFINAL,
627                               dir == OP_TYPE_ENCAP_PROTOCOL ?
628                                      ICV_CHECK_DISABLE : ICV_CHECK_ENABLE,
629                               DIR_ENC);
630
631                 if (rta_sec_era > RTA_SEC_ERA_2) {
632                         MOVE(p, AB2, 0, OFIFO, 0, MATH1, 0);
633                         SEQFIFOLOAD(p, MSGINSNOOP, 0,
634                                     VLF | LAST1 | LAST2 | FLUSH1);
635                 } else {
636                         SEQFIFOLOAD(p, MSGINSNOOP, 0,
637                                     VLF | LAST1 | LAST2 | FLUSH1);
638                         SET_LABEL(p, local_offset);
639
640                         /* Shut off automatic Info FIFO entries */
641                         LOAD(p, 0, DCTRL, LDOFF_DISABLE_AUTO_NFIFO, 0, IMMED);
642
643                         /*
644                          * Placeholder for MOVE command with length from
645                          * M1 register
646                          */
647                         MOVE(p, IFIFOAB2, 0, OFIFO, 0, 0, IMMED);
648
649                         /* Enable automatic Info FIFO entries */
650                         LOAD(p, 0, DCTRL, LDOFF_ENABLE_AUTO_NFIFO, 0, IMMED);
651                 }
652
653                 if (dir == OP_TYPE_DECAP_PROTOCOL)
654                         SEQFIFOLOAD(p, ICV1, 4, LAST1 | FLUSH1);
655                 else
656                         SEQSTORE(p, CONTEXT1, 0, 4, 0);
657
658                 break;
659
660         case PDCP_AUTH_TYPE_ZUC:
661                 if (rta_sec_era < RTA_SEC_ERA_5) {
662                         pr_err("Invalid era for selected algorithm\n");
663                         return -ENOTSUP;
664                 }
665                 /* Insert Auth Key */
666                 KEY(p, KEY2, authdata->key_enc_flags, authdata->key,
667                     authdata->keylen, INLINE_KEY(authdata));
668                 SEQLOAD(p, MATH0, 7, 1, 0);
669                 JUMP(p, 1, LOCAL_JUMP, ALL_TRUE, CALM);
670                 SEQINPTR(p, 0, 1, RTO);
671                 if (swap == false) {
672                         MATHB(p, MATH0, AND, PDCP_C_PLANE_SN_MASK, MATH1, 8,
673                               IFB | IMMED2);
674                         MATHB(p, MATH1, SHLD, MATH1, MATH1, 8, 0);
675
676                         MOVEB(p, DESCBUF, 8, MATH2, 0, 8, WAITCOMP | IMMED);
677                         MATHB(p, MATH1, OR, MATH2, MATH2, 8, 0);
678                         MOVEB(p, MATH2, 0, CONTEXT2, 0, 8, IMMED);
679
680                 } else {
681                         MATHB(p, MATH0, AND, PDCP_C_PLANE_SN_MASK_BE, MATH1, 8,
682                               IFB | IMMED2);
683                         MATHB(p, MATH1, SHLD, MATH1, MATH1, 8, 0);
684
685                         MOVE(p, DESCBUF, 8, MATH2, 0, 8, WAITCOMP | IMMED);
686                         MATHB(p, MATH1, OR, MATH2, MATH2, 8, 0);
687                         MOVE(p, MATH2, 0, CONTEXT2, 0, 8, IMMED);
688                 }
689                 if (dir == OP_TYPE_DECAP_PROTOCOL)
690                         MATHB(p, SEQINSZ, SUB, PDCP_MAC_I_LEN, MATH1, 4,
691                               IMMED2);
692                 else
693                         MATHB(p, SEQINSZ, SUB, ZERO, MATH1, 4, 0);
694
695                 MATHB(p, MATH1, SUB, ZERO, VSEQINSZ, 4, 0);
696                 MATHB(p, MATH1, SUB, ZERO, VSEQOUTSZ, 4, 0);
697                 SEQFIFOSTORE(p, MSG, 0, 0, VLF);
698                 ALG_OPERATION(p, OP_ALG_ALGSEL_ZUCA,
699                               OP_ALG_AAI_F9,
700                               OP_ALG_AS_INITFINAL,
701                               dir == OP_TYPE_ENCAP_PROTOCOL ?
702                                      ICV_CHECK_DISABLE : ICV_CHECK_ENABLE,
703                               DIR_ENC);
704                 SEQFIFOLOAD(p, MSGINSNOOP, 0, VLF | LAST1 | LAST2 | FLUSH1);
705                 MOVE(p, AB1, 0, OFIFO, 0, MATH1, 0);
706
707                 if (dir == OP_TYPE_DECAP_PROTOCOL)
708                         SEQFIFOLOAD(p, ICV2, 4, LAST2);
709                 else
710                         SEQSTORE(p, CONTEXT2, 0, 4, 0);
711
712                 break;
713
714         default:
715                 pr_err("%s: Invalid integrity algorithm selected: %d\n",
716                        "pdcp_insert_cplane_int_only_op", authdata->algtype);
717                 return -EINVAL;
718         }
719
720         if (rta_sec_era < RTA_SEC_ERA_3) {
721                 PATCH_MOVE(p, move_cmd_read_descbuf, local_offset);
722                 PATCH_MOVE(p, move_cmd_write_descbuf, local_offset);
723         }
724
725         return 0;
726 }
727
728 static inline int
729 pdcp_insert_cplane_enc_only_op(struct program *p,
730                                bool swap __maybe_unused,
731                                struct alginfo *cipherdata,
732                                struct alginfo *authdata __maybe_unused,
733                                unsigned int dir,
734                                enum pdcp_sn_size sn_size,
735                                unsigned char era_2_sw_hfn_ovrd __maybe_unused)
736 {
737         /* Insert Cipher Key */
738         KEY(p, KEY1, cipherdata->key_enc_flags, cipherdata->key,
739             cipherdata->keylen, INLINE_KEY(cipherdata));
740
741         if (rta_sec_era >= RTA_SEC_ERA_8) {
742                 if (sn_size == PDCP_SN_SIZE_5)
743                         PROTOCOL(p, dir, OP_PCLID_LTE_PDCP_CTRL_MIXED,
744                                  (uint16_t)cipherdata->algtype << 8);
745                 else
746                         PROTOCOL(p, dir, OP_PCLID_LTE_PDCP_USER_RN,
747                                  (uint16_t)cipherdata->algtype << 8);
748                 return 0;
749         }
750
751         SEQLOAD(p, MATH0, 7, 1, 0);
752         JUMP(p, 1, LOCAL_JUMP, ALL_TRUE, CALM);
753         if (swap == false)
754                 MATHB(p, MATH0, AND, PDCP_C_PLANE_SN_MASK, MATH1, 8,
755                         IFB | IMMED2);
756         else
757                 MATHB(p, MATH0, AND, PDCP_C_PLANE_SN_MASK_BE, MATH1, 8,
758                         IFB | IMMED2);
759         SEQSTORE(p, MATH0, 7, 1, 0);
760         MATHB(p, MATH1, SHLD, MATH1, MATH1, 8, 0);
761         MOVEB(p, DESCBUF, 8, MATH2, 0, 8, WAITCOMP | IMMED);
762         MATHB(p, MATH1, OR, MATH2, MATH2, 8, 0);
763
764         switch (cipherdata->algtype) {
765         case PDCP_CIPHER_TYPE_SNOW:
766                 MOVEB(p, MATH2, 0, CONTEXT1, 0, 8, WAITCOMP | IMMED);
767
768                 if (rta_sec_era > RTA_SEC_ERA_2) {
769                         MATHB(p, SEQINSZ, SUB, ZERO, VSEQINSZ, 4, 0);
770                 } else {
771                         MATHB(p, SEQINSZ, SUB, ONE, MATH1, 4, 0);
772                         MATHB(p, MATH1, ADD, ONE, VSEQINSZ, 4, 0);
773                 }
774
775                 if (dir == OP_TYPE_ENCAP_PROTOCOL)
776                         MATHB(p, SEQINSZ, ADD, PDCP_MAC_I_LEN, VSEQOUTSZ, 4,
777                               IMMED2);
778                 else
779                         MATHB(p, SEQINSZ, SUB, PDCP_MAC_I_LEN, VSEQOUTSZ, 4,
780                               IMMED2);
781                 SEQFIFOSTORE(p, MSG, 0, 0, VLF | CONT);
782                 ALG_OPERATION(p, OP_ALG_ALGSEL_SNOW_F8,
783                               OP_ALG_AAI_F8,
784                               OP_ALG_AS_INITFINAL, ICV_CHECK_DISABLE,
785                               dir == OP_TYPE_ENCAP_PROTOCOL ?
786                                         DIR_ENC : DIR_DEC);
787                 break;
788
789         case PDCP_CIPHER_TYPE_AES:
790                 MOVEB(p, MATH2, 0, CONTEXT1, 0x10, 0x10, WAITCOMP | IMMED);
791
792                 if (rta_sec_era > RTA_SEC_ERA_2) {
793                         MATHB(p, SEQINSZ, SUB, ZERO, VSEQINSZ, 4, 0);
794                 } else {
795                         MATHB(p, SEQINSZ, SUB, ONE, MATH1, 4, 0);
796                         MATHB(p, MATH1, ADD, ONE, VSEQINSZ, 4, 0);
797                 }
798
799                 if (dir == OP_TYPE_ENCAP_PROTOCOL)
800                         MATHB(p, SEQINSZ, ADD, PDCP_MAC_I_LEN, VSEQOUTSZ, 4,
801                               IMMED2);
802                 else
803                         MATHB(p, SEQINSZ, SUB, PDCP_MAC_I_LEN, VSEQOUTSZ, 4,
804                               IMMED2);
805
806                 SEQFIFOSTORE(p, MSG, 0, 0, VLF | CONT);
807                 ALG_OPERATION(p, OP_ALG_ALGSEL_AES,
808                               OP_ALG_AAI_CTR,
809                               OP_ALG_AS_INITFINAL,
810                               ICV_CHECK_DISABLE,
811                               dir == OP_TYPE_ENCAP_PROTOCOL ?
812                                         DIR_ENC : DIR_DEC);
813                 break;
814
815         case PDCP_CIPHER_TYPE_ZUC:
816                 if (rta_sec_era < RTA_SEC_ERA_5) {
817                         pr_err("Invalid era for selected algorithm\n");
818                         return -ENOTSUP;
819                 }
820
821                 MOVEB(p, MATH2, 0, CONTEXT1, 0, 0x08, IMMED);
822                 MOVEB(p, MATH2, 0, CONTEXT1, 0x08, 0x08, WAITCOMP | IMMED);
823                 MATHB(p, SEQINSZ, SUB, ZERO, VSEQINSZ, 4, 0);
824                 if (dir == OP_TYPE_ENCAP_PROTOCOL)
825                         MATHB(p, SEQINSZ, ADD, PDCP_MAC_I_LEN, VSEQOUTSZ, 4,
826                               IMMED2);
827                 else
828                         MATHB(p, SEQINSZ, SUB, PDCP_MAC_I_LEN, VSEQOUTSZ, 4,
829                               IMMED2);
830
831                 SEQFIFOSTORE(p, MSG, 0, 0, VLF | CONT);
832                 ALG_OPERATION(p, OP_ALG_ALGSEL_ZUCE,
833                               OP_ALG_AAI_F8,
834                               OP_ALG_AS_INITFINAL,
835                               ICV_CHECK_DISABLE,
836                               dir == OP_TYPE_ENCAP_PROTOCOL ?
837                                         DIR_ENC : DIR_DEC);
838                 break;
839
840         default:
841                 pr_err("%s: Invalid encrypt algorithm selected: %d\n",
842                        "pdcp_insert_cplane_enc_only_op", cipherdata->algtype);
843                 return -EINVAL;
844         }
845
846         if (dir == OP_TYPE_ENCAP_PROTOCOL) {
847                 SEQFIFOLOAD(p, MSG1, 0, VLF);
848                 FIFOLOAD(p, MSG1, PDCP_NULL_INT_MAC_I_VAL, 4,
849                          LAST1 | FLUSH1 | IMMED);
850         } else {
851                 SEQFIFOLOAD(p, MSG1, 0, VLF | LAST1 | FLUSH1);
852                 MOVE(p, OFIFO, 0, MATH1, 4, PDCP_MAC_I_LEN, WAITCOMP | IMMED);
853                 MATHB(p, MATH1, XOR, PDCP_NULL_INT_MAC_I_VAL, NONE, 4, IMMED2);
854                 JUMP(p, PDCP_NULL_INT_ICV_CHECK_FAILED_STATUS,
855                      HALT_STATUS, ALL_FALSE, MATH_Z);
856         }
857
858         return 0;
859 }
860
861 static inline int
862 pdcp_insert_cplane_acc_op(struct program *p,
863                           bool swap __maybe_unused,
864                           struct alginfo *cipherdata,
865                           struct alginfo *authdata,
866                           unsigned int dir,
867                           enum pdcp_sn_size sn_size,
868                           unsigned char era_2_hfn_ovrd __maybe_unused)
869 {
870         /* Insert Auth Key */
871         KEY(p, KEY2, authdata->key_enc_flags, authdata->key, authdata->keylen,
872             INLINE_KEY(authdata));
873
874         /* Insert Cipher Key */
875         KEY(p, KEY1, cipherdata->key_enc_flags, cipherdata->key,
876             cipherdata->keylen, INLINE_KEY(cipherdata));
877
878         if (sn_size == PDCP_SN_SIZE_5)
879                 PROTOCOL(p, dir, OP_PCLID_LTE_PDCP_CTRL,
880                          (uint16_t)cipherdata->algtype);
881         else
882                 PROTOCOL(p, dir, OP_PCLID_LTE_PDCP_USER_RN,
883                          ((uint16_t)cipherdata->algtype << 8) |
884                           (uint16_t)authdata->algtype);
885
886         return 0;
887 }
888
889 static inline int
890 pdcp_insert_cplane_snow_aes_op(struct program *p,
891                                bool swap __maybe_unused,
892                                struct alginfo *cipherdata,
893                                struct alginfo *authdata,
894                                unsigned int dir,
895                                enum pdcp_sn_size sn_size,
896                                unsigned char era_2_sw_hfn_ovrd)
897 {
898         LABEL(back_to_sd_offset);
899         LABEL(end_desc);
900         LABEL(local_offset);
901         LABEL(jump_to_beginning);
902         LABEL(fifo_load_mac_i_offset);
903         REFERENCE(seqin_ptr_read);
904         REFERENCE(seqin_ptr_write);
905         REFERENCE(seq_out_read);
906         REFERENCE(jump_back_to_sd_cmd);
907         REFERENCE(move_mac_i_to_desc_buf);
908
909         if (rta_sec_era >= RTA_SEC_ERA_8) {
910                 KEY(p, KEY1, cipherdata->key_enc_flags, cipherdata->key,
911                                 cipherdata->keylen, INLINE_KEY(cipherdata));
912                 KEY(p, KEY2, authdata->key_enc_flags, authdata->key,
913                                 authdata->keylen, INLINE_KEY(authdata));
914
915                 if (sn_size == PDCP_SN_SIZE_5)
916                         PROTOCOL(p, dir, OP_PCLID_LTE_PDCP_CTRL_MIXED,
917                                  ((uint16_t)cipherdata->algtype << 8) |
918                                  (uint16_t)authdata->algtype);
919                 else
920                         PROTOCOL(p, dir, OP_PCLID_LTE_PDCP_USER_RN,
921                                  ((uint16_t)cipherdata->algtype << 8) |
922                                  (uint16_t)authdata->algtype);
923
924                 return 0;
925         }
926
927         SEQLOAD(p, MATH0, 7, 1, 0);
928         JUMP(p, 1, LOCAL_JUMP, ALL_TRUE, CALM);
929         if (swap == false)
930                 MATHB(p, MATH0, AND, PDCP_C_PLANE_SN_MASK, MATH1, 8,
931                         IFB | IMMED2);
932         else
933                 MATHB(p, MATH0, AND, PDCP_C_PLANE_SN_MASK_BE, MATH1, 8,
934                         IFB | IMMED2);
935         MATHB(p, MATH1, SHLD, MATH1, MATH1, 8, 0);
936         MOVE(p, DESCBUF, 4, MATH2, 0, 0x08, WAITCOMP | IMMED);
937         MATHB(p, MATH1, OR, MATH2, MATH2, 8, 0);
938         SEQSTORE(p, MATH0, 7, 1, 0);
939         if (dir == OP_TYPE_ENCAP_PROTOCOL) {
940                 if (rta_sec_era > RTA_SEC_ERA_2 ||
941                     (rta_sec_era == RTA_SEC_ERA_2 &&
942                                    era_2_sw_hfn_ovrd == 0)) {
943                         SEQINPTR(p, 0, 1, RTO);
944                 } else {
945                         SEQINPTR(p, 0, 5, RTO);
946                         SEQFIFOLOAD(p, SKIP, 4, 0);
947                 }
948                 KEY(p, KEY1, authdata->key_enc_flags, authdata->key,
949                     authdata->keylen, INLINE_KEY(authdata));
950                 MOVE(p, MATH2, 0, IFIFOAB1, 0, 0x08, IMMED);
951
952                 if (rta_sec_era > RTA_SEC_ERA_2) {
953                         MATHB(p, SEQINSZ, SUB, ZERO, VSEQINSZ, 4, 0);
954                         MATHB(p, SEQINSZ, SUB, ZERO, MATH1, 4, 0);
955                         MATHB(p, VSEQINSZ, ADD, PDCP_MAC_I_LEN - 1, VSEQOUTSZ,
956                               4, IMMED2);
957                 } else {
958                         MATHB(p, SEQINSZ, SUB, MATH3, VSEQINSZ, 4, 0);
959                         MATHB(p, VSEQINSZ, ADD, PDCP_MAC_I_LEN - 1, VSEQOUTSZ,
960                               4, IMMED2);
961                         /*
962                          * Note: Although the calculations below might seem a
963                          * little off, the logic is the following:
964                          *
965                          * - SEQ IN PTR RTO below needs the full length of the
966                          *   frame; in case of P4080_REV_2_HFN_OV_WORKAROUND,
967                          *   this means the length of the frame to be processed
968                          *   + 4 bytes (the HFN override flag and value).
969                          *   The length of the frame to be processed minus 1
970                          *   byte is in the VSIL register (because
971                          *   VSIL = SIL + 3, due to 1 byte, the header being
972                          *   already written by the SEQ STORE above). So for
973                          *   calculating the length to use in RTO, I add one
974                          *   to the VSIL value in order to obtain the total
975                          *   frame length. This helps in case of P4080 which
976                          *   can have the value 0 as an operand in a MATH
977                          *   command only as SRC1 When the HFN override
978                          *   workaround is not enabled, the length of the
979                          *   frame is given by the SIL register; the
980                          *   calculation is similar to the one in the SEC 4.2
981                          *   and SEC 5.3 cases.
982                          */
983                         if (era_2_sw_hfn_ovrd)
984                                 MATHB(p, VSEQOUTSZ, ADD, ONE, MATH1, 4,
985                                       0);
986                         else
987                                 MATHB(p, SEQINSZ, ADD, MATH3, MATH1, 4,
988                                       0);
989                 }
990                 /*
991                  * Placeholder for filling the length in
992                  * SEQIN PTR RTO below
993                  */
994                 seqin_ptr_read = MOVE(p, DESCBUF, 0, MATH1, 0, 6, IMMED);
995                 seqin_ptr_write = MOVE(p, MATH1, 0, DESCBUF, 0, 8,
996                                        WAITCOMP | IMMED);
997                 ALG_OPERATION(p, OP_ALG_ALGSEL_AES,
998                               OP_ALG_AAI_CMAC,
999                               OP_ALG_AS_INITFINAL,
1000                               ICV_CHECK_DISABLE,
1001                               DIR_DEC);
1002                 SEQFIFOLOAD(p, MSG1, 0, VLF | LAST1 | FLUSH1);
1003                 MOVE(p, CONTEXT1, 0, MATH3, 0, 4, WAITCOMP | IMMED);
1004                 if (rta_sec_era <= RTA_SEC_ERA_3)
1005                         LOAD(p, CLRW_CLR_C1KEY |
1006                              CLRW_CLR_C1CTX |
1007                              CLRW_CLR_C1ICV |
1008                              CLRW_CLR_C1DATAS |
1009                              CLRW_CLR_C1MODE,
1010                              CLRW, 0, 4, IMMED);
1011                 else
1012                         LOAD(p, CLRW_RESET_CLS1_CHA |
1013                              CLRW_CLR_C1KEY |
1014                              CLRW_CLR_C1CTX |
1015                              CLRW_CLR_C1ICV |
1016                              CLRW_CLR_C1DATAS |
1017                              CLRW_CLR_C1MODE,
1018                              CLRW, 0, 4, IMMED);
1019
1020                 if (rta_sec_era <= RTA_SEC_ERA_3)
1021                         LOAD(p, CCTRL_RESET_CHA_ALL, CCTRL, 0, 4, IMMED);
1022
1023                 KEY(p, KEY1, cipherdata->key_enc_flags, cipherdata->key,
1024                     cipherdata->keylen, INLINE_KEY(cipherdata));
1025                 SET_LABEL(p, local_offset);
1026                 MOVE(p, MATH2, 0, CONTEXT1, 0, 8, IMMED);
1027                 SEQINPTR(p, 0, 0, RTO);
1028
1029                 if (rta_sec_era == RTA_SEC_ERA_2 && era_2_sw_hfn_ovrd) {
1030                         SEQFIFOLOAD(p, SKIP, 5, 0);
1031                         MATHB(p, SEQINSZ, ADD, ONE, SEQINSZ, 4, 0);
1032                 }
1033
1034                 MATHB(p, SEQINSZ, SUB, ONE, VSEQINSZ, 4, 0);
1035                 ALG_OPERATION(p, OP_ALG_ALGSEL_SNOW_F8,
1036                               OP_ALG_AAI_F8,
1037                               OP_ALG_AS_INITFINAL,
1038                               ICV_CHECK_DISABLE,
1039                               DIR_ENC);
1040                 SEQFIFOSTORE(p, MSG, 0, 0, VLF);
1041
1042                 if (rta_sec_era > RTA_SEC_ERA_2 ||
1043                     (rta_sec_era == RTA_SEC_ERA_2 &&
1044                                    era_2_sw_hfn_ovrd == 0))
1045                         SEQFIFOLOAD(p, SKIP, 1, 0);
1046
1047                 SEQFIFOLOAD(p, MSG1, 0, VLF);
1048                 MOVE(p, MATH3, 0, IFIFOAB1, 0, 4, LAST1 | FLUSH1 | IMMED);
1049                 PATCH_MOVE(p, seqin_ptr_read, local_offset);
1050                 PATCH_MOVE(p, seqin_ptr_write, local_offset);
1051         } else {
1052                 MOVE(p, MATH2, 0, CONTEXT1, 0, 8, IMMED);
1053
1054                 if (rta_sec_era >= RTA_SEC_ERA_5)
1055                         MOVE(p, CONTEXT1, 0, CONTEXT2, 0, 8, IMMED);
1056
1057                 if (rta_sec_era > RTA_SEC_ERA_2)
1058                         MATHB(p, SEQINSZ, SUB, ZERO, VSEQINSZ, 4, 0);
1059                 else
1060                         MATHB(p, SEQINSZ, SUB, MATH3, VSEQINSZ, 4, 0);
1061
1062                 MATHB(p, SEQINSZ, SUB, PDCP_MAC_I_LEN, VSEQOUTSZ, 4, IMMED2);
1063 /*
1064  * TODO: To be changed when proper support is added in RTA (can't load a
1065  * command that is also written by RTA (or patch it for that matter).
1066  * Change when proper RTA support is added.
1067  */
1068                 if (p->ps)
1069                         WORD(p, 0x168B0004);
1070                 else
1071                         WORD(p, 0x16880404);
1072
1073                 jump_back_to_sd_cmd = JUMP(p, 0, LOCAL_JUMP, ALL_TRUE, 0);
1074                 /*
1075                  * Placeholder for command reading  the SEQ OUT command in
1076                  * JD. Done for rereading the decrypted data and performing
1077                  * the integrity check
1078                  */
1079 /*
1080  * TODO: RTA currently doesn't support patching of length of a MOVE command
1081  * Thus, it is inserted as a raw word, as per PS setting.
1082  */
1083                 if (p->ps)
1084                         seq_out_read = MOVE(p, DESCBUF, 0, MATH1, 0, 20,
1085                                             WAITCOMP | IMMED);
1086                 else
1087                         seq_out_read = MOVE(p, DESCBUF, 0, MATH1, 0, 16,
1088                                             WAITCOMP | IMMED);
1089
1090                 MATHB(p, MATH1, XOR, CMD_SEQ_IN_PTR ^ CMD_SEQ_OUT_PTR, MATH1, 4,
1091                       IMMED2);
1092                 /* Placeholder for overwriting the SEQ IN  with SEQ OUT */
1093 /*
1094  * TODO: RTA currently doesn't support patching of length of a MOVE command
1095  * Thus, it is inserted as a raw word, as per PS setting.
1096  */
1097                 if (p->ps)
1098                         MOVE(p, MATH1, 0, DESCBUF, 0, 24, IMMED);
1099                 else
1100                         MOVE(p, MATH1, 0, DESCBUF, 0, 20, IMMED);
1101
1102                 KEY(p, KEY1, cipherdata->key_enc_flags, cipherdata->key,
1103                     cipherdata->keylen, INLINE_KEY(cipherdata));
1104
1105                 if (rta_sec_era >= RTA_SEC_ERA_4)
1106                         MOVE(p, CONTEXT1, 0, CONTEXT2, 0, 8, IMMED);
1107                 else
1108                         MOVE(p, CONTEXT1, 0, MATH3, 0, 8, IMMED);
1109
1110                 ALG_OPERATION(p, OP_ALG_ALGSEL_SNOW_F8,
1111                               OP_ALG_AAI_F8,
1112                               OP_ALG_AS_INITFINAL,
1113                               ICV_CHECK_DISABLE,
1114                               DIR_DEC);
1115                 SEQFIFOSTORE(p, MSG, 0, 0, VLF | CONT);
1116                 SEQFIFOLOAD(p, MSG1, 0, VLF | LAST1 | FLUSH1);
1117
1118                 if (rta_sec_era <= RTA_SEC_ERA_3)
1119                         move_mac_i_to_desc_buf = MOVE(p, OFIFO, 0, DESCBUF, 0,
1120                                                       4, WAITCOMP | IMMED);
1121                 else
1122                         MOVE(p, OFIFO, 0, MATH3, 0, 4, IMMED);
1123
1124                 if (rta_sec_era <= RTA_SEC_ERA_3)
1125                         LOAD(p, CCTRL_RESET_CHA_ALL, CCTRL, 0, 4, IMMED);
1126                 else
1127                         LOAD(p, CLRW_RESET_CLS1_CHA |
1128                              CLRW_CLR_C1KEY |
1129                              CLRW_CLR_C1CTX |
1130                              CLRW_CLR_C1ICV |
1131                              CLRW_CLR_C1DATAS |
1132                              CLRW_CLR_C1MODE,
1133                              CLRW, 0, 4, IMMED);
1134
1135                 KEY(p, KEY1, authdata->key_enc_flags, authdata->key,
1136                     authdata->keylen, INLINE_KEY(authdata));
1137                 /*
1138                  * Placeholder for jump in SD for executing the new SEQ IN PTR
1139                  * command (which is actually the old SEQ OUT PTR command
1140                  * copied over from JD.
1141                  */
1142                 SET_LABEL(p, jump_to_beginning);
1143                 JUMP(p, 1 - jump_to_beginning, LOCAL_JUMP, ALL_TRUE, 0);
1144                 SET_LABEL(p, back_to_sd_offset);
1145                 ALG_OPERATION(p, OP_ALG_ALGSEL_AES,
1146                               OP_ALG_AAI_CMAC,
1147                               OP_ALG_AS_INITFINAL,
1148                               ICV_CHECK_ENABLE,
1149                               DIR_DEC);
1150
1151                 /* Read the # of bytes written in the output buffer + 1 (HDR) */
1152                 MATHB(p, VSEQOUTSZ, ADD, ONE, VSEQINSZ, 4, 0);
1153
1154                 if (rta_sec_era <= RTA_SEC_ERA_3)
1155                         MOVE(p, MATH3, 0, IFIFOAB1, 0, 8, IMMED);
1156                 else
1157                         MOVE(p, CONTEXT2, 0, IFIFOAB1, 0, 8, IMMED);
1158
1159                 if (rta_sec_era == RTA_SEC_ERA_2 && era_2_sw_hfn_ovrd)
1160                         SEQFIFOLOAD(p, SKIP, 4, 0);
1161
1162                 SEQFIFOLOAD(p, MSG1, 0, VLF | LAST1 | FLUSH1);
1163
1164                 if (rta_sec_era >= RTA_SEC_ERA_4) {
1165                         LOAD(p, NFIFOENTRY_STYPE_ALTSOURCE |
1166                              NFIFOENTRY_DEST_CLASS1 |
1167                              NFIFOENTRY_DTYPE_ICV |
1168                              NFIFOENTRY_LC1 |
1169                              NFIFOENTRY_FC1 | 4, NFIFO_SZL, 0, 4, IMMED);
1170                         MOVE(p, MATH3, 0, ALTSOURCE, 0, 4, IMMED);
1171                 } else {
1172                         SET_LABEL(p, fifo_load_mac_i_offset);
1173                         FIFOLOAD(p, ICV1, fifo_load_mac_i_offset, 4,
1174                                  LAST1 | FLUSH1 | IMMED);
1175                 }
1176
1177                 SET_LABEL(p, end_desc);
1178
1179                 if (!p->ps) {
1180                         PATCH_MOVE(p, seq_out_read, end_desc + 1);
1181                         PATCH_JUMP(p, jump_back_to_sd_cmd,
1182                                    back_to_sd_offset + jump_back_to_sd_cmd - 5);
1183
1184                         if (rta_sec_era <= RTA_SEC_ERA_3)
1185                                 PATCH_MOVE(p, move_mac_i_to_desc_buf,
1186                                            fifo_load_mac_i_offset + 1);
1187                 } else {
1188                         PATCH_MOVE(p, seq_out_read, end_desc + 2);
1189                         PATCH_JUMP(p, jump_back_to_sd_cmd,
1190                                    back_to_sd_offset + jump_back_to_sd_cmd - 5);
1191
1192                         if (rta_sec_era <= RTA_SEC_ERA_3)
1193                                 PATCH_MOVE(p, move_mac_i_to_desc_buf,
1194                                            fifo_load_mac_i_offset + 1);
1195                 }
1196         }
1197
1198         return 0;
1199 }
1200
1201 static inline int
1202 pdcp_insert_cplane_aes_snow_op(struct program *p,
1203                                bool swap __maybe_unused,
1204                                struct alginfo *cipherdata,
1205                                struct alginfo *authdata,
1206                                unsigned int dir,
1207                                enum pdcp_sn_size sn_size,
1208                                unsigned char era_2_sw_hfn_ovrd __maybe_unused)
1209 {
1210         KEY(p, KEY1, cipherdata->key_enc_flags, cipherdata->key,
1211             cipherdata->keylen, INLINE_KEY(cipherdata));
1212         KEY(p, KEY2, authdata->key_enc_flags, authdata->key, authdata->keylen,
1213             INLINE_KEY(authdata));
1214
1215         if (rta_sec_era >= RTA_SEC_ERA_8) {
1216                 int pclid;
1217
1218                 if (sn_size == PDCP_SN_SIZE_5)
1219                         pclid = OP_PCLID_LTE_PDCP_CTRL_MIXED;
1220                 else
1221                         pclid = OP_PCLID_LTE_PDCP_USER_RN;
1222
1223                 PROTOCOL(p, dir, pclid,
1224                          ((uint16_t)cipherdata->algtype << 8) |
1225                          (uint16_t)authdata->algtype);
1226
1227                 return 0;
1228         }
1229
1230         if (dir == OP_TYPE_ENCAP_PROTOCOL)
1231                 MATHB(p, SEQINSZ, SUB, ONE, VSEQINSZ, 4, 0);
1232
1233         SEQLOAD(p, MATH0, 7, 1, 0);
1234         JUMP(p, 1, LOCAL_JUMP, ALL_TRUE, CALM);
1235         MOVE(p, MATH0, 7, IFIFOAB2, 0, 1, IMMED);
1236         if (swap == false)
1237                 MATHB(p, MATH0, AND, PDCP_C_PLANE_SN_MASK, MATH1, 8,
1238                         IFB | IMMED2);
1239         else
1240                 MATHB(p, MATH0, AND, PDCP_C_PLANE_SN_MASK_BE, MATH1, 8,
1241                         IFB | IMMED2);
1242
1243         SEQSTORE(p, MATH0, 7, 1, 0);
1244         MATHB(p, MATH1, SHLD, MATH1, MATH1, 8, 0);
1245         MOVE(p, DESCBUF, 4, MATH2, 0, 8, WAITCOMP | IMMED);
1246         MATHB(p, MATH1, OR, MATH2, MATH1, 8, 0);
1247         MOVE(p, MATH1, 0, CONTEXT1, 16, 8, IMMED);
1248         MOVE(p, MATH1, 0, CONTEXT2, 0, 4, IMMED);
1249         if (swap == false) {
1250                 MATHB(p, MATH1, AND, lower_32_bits(PDCP_BEARER_MASK), MATH2, 4,
1251                         IMMED2);
1252                 MATHB(p, MATH1, AND, upper_32_bits(PDCP_DIR_MASK), MATH3, 4,
1253                         IMMED2);
1254         } else {
1255                 MATHB(p, MATH1, AND, lower_32_bits(PDCP_BEARER_MASK_BE), MATH2,
1256                         4, IMMED2);
1257                 MATHB(p, MATH1, AND, upper_32_bits(PDCP_DIR_MASK_BE), MATH3,
1258                         4, IMMED2);
1259         }
1260         MATHB(p, MATH3, SHLD, MATH3, MATH3, 8, 0);
1261         MOVE(p, MATH2, 4, OFIFO, 0, 12, IMMED);
1262         MOVE(p, OFIFO, 0, CONTEXT2, 4, 12, IMMED);
1263         if (dir == OP_TYPE_ENCAP_PROTOCOL) {
1264                 MATHB(p, SEQINSZ, ADD, PDCP_MAC_I_LEN, VSEQOUTSZ, 4, IMMED2);
1265         } else {
1266                 MATHB(p, SEQINSZ, SUB, PDCP_MAC_I_LEN, MATH1, 4, IMMED2);
1267
1268                 MATHB(p, ZERO, ADD, MATH1, VSEQOUTSZ, 4, 0);
1269                 MATHB(p, ZERO, ADD, MATH1, VSEQINSZ, 4, 0);
1270         }
1271
1272         if (dir == OP_TYPE_ENCAP_PROTOCOL)
1273                 SEQFIFOSTORE(p, MSG, 0, 0, VLF);
1274         else
1275                 SEQFIFOSTORE(p, MSG, 0, 0, VLF | CONT);
1276
1277         ALG_OPERATION(p, OP_ALG_ALGSEL_SNOW_F9,
1278                       OP_ALG_AAI_F9,
1279                       OP_ALG_AS_INITFINAL,
1280                       dir == OP_TYPE_ENCAP_PROTOCOL ?
1281                              ICV_CHECK_DISABLE : ICV_CHECK_ENABLE,
1282                       DIR_DEC);
1283         ALG_OPERATION(p, OP_ALG_ALGSEL_AES,
1284                       OP_ALG_AAI_CTR,
1285                       OP_ALG_AS_INITFINAL,
1286                       ICV_CHECK_DISABLE,
1287                       dir == OP_TYPE_ENCAP_PROTOCOL ? DIR_ENC : DIR_DEC);
1288
1289         if (dir == OP_TYPE_ENCAP_PROTOCOL) {
1290                 SEQFIFOLOAD(p, MSGINSNOOP, 0, VLF | LAST2);
1291                 MOVE(p, CONTEXT2, 0, IFIFOAB1, 0, 4, LAST1 | FLUSH1 | IMMED);
1292         } else {
1293                 SEQFIFOLOAD(p, MSGOUTSNOOP, 0, VLF | LAST2);
1294                 SEQFIFOLOAD(p, MSG1, 4, LAST1 | FLUSH1);
1295                 JUMP(p, 1, LOCAL_JUMP, ALL_TRUE, CLASS1 | NOP | NIFP);
1296
1297                 if (rta_sec_era >= RTA_SEC_ERA_6)
1298                         LOAD(p, 0, DCTRL, 0, LDLEN_RST_CHA_OFIFO_PTR, IMMED);
1299
1300                 MOVE(p, OFIFO, 0, MATH0, 0, 4, WAITCOMP | IMMED);
1301
1302                 NFIFOADD(p, IFIFO, ICV2, 4, LAST2);
1303
1304                 if (rta_sec_era <= RTA_SEC_ERA_2) {
1305                         /* Shut off automatic Info FIFO entries */
1306                         LOAD(p, 0, DCTRL, LDOFF_DISABLE_AUTO_NFIFO, 0, IMMED);
1307                         MOVE(p, MATH0, 0, IFIFOAB2, 0, 4, WAITCOMP | IMMED);
1308                 } else {
1309                         MOVE(p, MATH0, 0, IFIFO, 0, 4, WAITCOMP | IMMED);
1310                 }
1311         }
1312
1313         return 0;
1314 }
1315
1316 static inline int
1317 pdcp_insert_cplane_snow_zuc_op(struct program *p,
1318                                bool swap __maybe_unused,
1319                                struct alginfo *cipherdata,
1320                                struct alginfo *authdata,
1321                                unsigned int dir,
1322                                enum pdcp_sn_size sn_size,
1323                                unsigned char era_2_sw_hfn_ovrd __maybe_unused)
1324 {
1325         LABEL(keyjump);
1326         REFERENCE(pkeyjump);
1327
1328         if (rta_sec_era < RTA_SEC_ERA_5) {
1329                 pr_err("Invalid era for selected algorithm\n");
1330                 return -ENOTSUP;
1331         }
1332
1333         pkeyjump = JUMP(p, keyjump, LOCAL_JUMP, ALL_TRUE, SHRD | SELF | BOTH);
1334         KEY(p, KEY1, cipherdata->key_enc_flags, cipherdata->key,
1335             cipherdata->keylen, INLINE_KEY(cipherdata));
1336         KEY(p, KEY2, authdata->key_enc_flags, authdata->key, authdata->keylen,
1337             INLINE_KEY(authdata));
1338
1339         SET_LABEL(p, keyjump);
1340
1341         if (rta_sec_era >= RTA_SEC_ERA_8) {
1342                 int pclid;
1343
1344                 if (sn_size == PDCP_SN_SIZE_5)
1345                         pclid = OP_PCLID_LTE_PDCP_CTRL_MIXED;
1346                 else
1347                         pclid = OP_PCLID_LTE_PDCP_USER_RN;
1348
1349                 PROTOCOL(p, dir, pclid,
1350                          ((uint16_t)cipherdata->algtype << 8) |
1351                          (uint16_t)authdata->algtype);
1352                 return 0;
1353         }
1354
1355         SEQLOAD(p, MATH0, 7, 1, 0);
1356         JUMP(p, 1, LOCAL_JUMP, ALL_TRUE, CALM);
1357         MOVE(p, MATH0, 7, IFIFOAB2, 0, 1, IMMED);
1358         if (swap == false)
1359                 MATHB(p, MATH0, AND, PDCP_C_PLANE_SN_MASK, MATH1, 8,
1360                         IFB | IMMED2);
1361         else
1362                 MATHB(p, MATH0, AND, PDCP_C_PLANE_SN_MASK, MATH1, 8,
1363                         IFB | IMMED2);
1364
1365         MATHB(p, MATH1, SHLD, MATH1, MATH1, 8, 0);
1366         MOVE(p, DESCBUF, 4, MATH2, 0, 8, WAITCOMP | IMMED);
1367         MATHB(p, MATH1, OR, MATH2, MATH2, 8, 0);
1368         MOVE(p, MATH2, 0, CONTEXT1, 0, 8, IMMED);
1369         MOVE(p, MATH2, 0, CONTEXT2, 0, 8, WAITCOMP | IMMED);
1370
1371         if (dir == OP_TYPE_ENCAP_PROTOCOL)
1372                 MATHB(p, SEQINSZ, ADD, PDCP_MAC_I_LEN, VSEQOUTSZ, 4, IMMED2);
1373         else
1374                 MATHB(p, SEQINSZ, SUB, PDCP_MAC_I_LEN, VSEQOUTSZ, 4, IMMED2);
1375
1376         MATHB(p, SEQINSZ, SUB, ZERO, VSEQINSZ, 4, 0);
1377         SEQSTORE(p, MATH0, 7, 1, 0);
1378
1379         if (dir == OP_TYPE_ENCAP_PROTOCOL) {
1380                 SEQFIFOSTORE(p, MSG, 0, 0, VLF);
1381                 SEQFIFOLOAD(p, MSGINSNOOP, 0, VLF | LAST2);
1382         } else {
1383                 SEQFIFOSTORE(p, MSG, 0, 0, VLF | CONT);
1384                 SEQFIFOLOAD(p, MSGOUTSNOOP, 0, VLF | LAST1 | FLUSH1);
1385         }
1386
1387         ALG_OPERATION(p, OP_ALG_ALGSEL_ZUCA,
1388                       OP_ALG_AAI_F9,
1389                       OP_ALG_AS_INITFINAL,
1390                       dir == OP_TYPE_ENCAP_PROTOCOL ?
1391                              ICV_CHECK_DISABLE : ICV_CHECK_ENABLE,
1392                       DIR_ENC);
1393
1394         ALG_OPERATION(p, OP_ALG_ALGSEL_SNOW_F8,
1395                       OP_ALG_AAI_F8,
1396                       OP_ALG_AS_INITFINAL,
1397                       ICV_CHECK_DISABLE,
1398                       dir == OP_TYPE_ENCAP_PROTOCOL ? DIR_ENC : DIR_DEC);
1399         if (dir == OP_TYPE_ENCAP_PROTOCOL) {
1400                 MOVE(p, CONTEXT2, 0, IFIFOAB1, 0, 4, LAST1 | FLUSH1 | IMMED);
1401         } else {
1402                 /* Save ICV */
1403                 MOVE(p, OFIFO, 0, MATH0, 0, 4, IMMED);
1404                 LOAD(p, NFIFOENTRY_STYPE_ALTSOURCE |
1405                      NFIFOENTRY_DEST_CLASS2 |
1406                      NFIFOENTRY_DTYPE_ICV |
1407                      NFIFOENTRY_LC2 | 4, NFIFO_SZL, 0, 4, IMMED);
1408                 MOVE(p, MATH0, 0, ALTSOURCE, 0, 4, WAITCOMP | IMMED);
1409         }
1410
1411         /* Reset ZUCA mode and done interrupt */
1412         LOAD(p, CLRW_CLR_C2MODE, CLRW, 0, 4, IMMED);
1413         LOAD(p, CIRQ_ZADI, ICTRL, 0, 4, IMMED);
1414
1415         PATCH_JUMP(p, pkeyjump, keyjump);
1416         return 0;
1417 }
1418
1419 static inline int
1420 pdcp_insert_cplane_aes_zuc_op(struct program *p,
1421                               bool swap __maybe_unused,
1422                               struct alginfo *cipherdata,
1423                               struct alginfo *authdata,
1424                               unsigned int dir,
1425                               enum pdcp_sn_size sn_size,
1426                               unsigned char era_2_sw_hfn_ovrd __maybe_unused)
1427 {
1428         LABEL(keyjump);
1429         REFERENCE(pkeyjump);
1430
1431         if (rta_sec_era < RTA_SEC_ERA_5) {
1432                 pr_err("Invalid era for selected algorithm\n");
1433                 return -ENOTSUP;
1434         }
1435
1436         pkeyjump = JUMP(p, keyjump, LOCAL_JUMP, ALL_TRUE, SHRD | SELF | BOTH);
1437         KEY(p, KEY1, cipherdata->key_enc_flags, cipherdata->key,
1438             cipherdata->keylen, INLINE_KEY(cipherdata));
1439         KEY(p, KEY2, authdata->key_enc_flags, authdata->key, authdata->keylen,
1440             INLINE_KEY(authdata));
1441
1442         if (rta_sec_era >= RTA_SEC_ERA_8) {
1443                 int pclid;
1444
1445                 if (sn_size == PDCP_SN_SIZE_5)
1446                         pclid = OP_PCLID_LTE_PDCP_CTRL_MIXED;
1447                 else
1448                         pclid = OP_PCLID_LTE_PDCP_USER_RN;
1449
1450                 PROTOCOL(p, dir, pclid,
1451                          ((uint16_t)cipherdata->algtype << 8) |
1452                          (uint16_t)authdata->algtype);
1453
1454                 return 0;
1455         }
1456
1457         SET_LABEL(p, keyjump);
1458         SEQLOAD(p, MATH0, 7, 1, 0);
1459         JUMP(p, 1, LOCAL_JUMP, ALL_TRUE, CALM);
1460         MOVE(p, MATH0, 7, IFIFOAB2, 0, 1, IMMED);
1461         if (swap == false)
1462                 MATHB(p, MATH0, AND, PDCP_C_PLANE_SN_MASK, MATH1, 8,
1463                         IFB | IMMED2);
1464         else
1465                 MATHB(p, MATH0, AND, PDCP_C_PLANE_SN_MASK, MATH1, 8,
1466                         IFB | IMMED2);
1467
1468         MATHB(p, MATH1, SHLD, MATH1, MATH1, 8, 0);
1469         MOVE(p, DESCBUF, 4, MATH2, 0, 8, WAITCOMP | IMMED);
1470         MATHB(p, MATH1, OR, MATH2, MATH2, 8, 0);
1471         MOVE(p, MATH2, 0, CONTEXT1, 16, 8, IMMED);
1472         MOVE(p, MATH2, 0, CONTEXT2, 0, 8, WAITCOMP | IMMED);
1473
1474         if (dir == OP_TYPE_ENCAP_PROTOCOL)
1475                 MATHB(p, SEQINSZ, ADD, PDCP_MAC_I_LEN, VSEQOUTSZ, 4, IMMED2);
1476         else
1477                 MATHB(p, SEQINSZ, SUB, PDCP_MAC_I_LEN, VSEQOUTSZ, 4, IMMED2);
1478
1479         MATHB(p, SEQINSZ, SUB, ZERO, VSEQINSZ, 4, 0);
1480         SEQSTORE(p, MATH0, 7, 1, 0);
1481
1482         if (dir == OP_TYPE_ENCAP_PROTOCOL) {
1483                 SEQFIFOSTORE(p, MSG, 0, 0, VLF);
1484                 SEQFIFOLOAD(p, MSGINSNOOP, 0, VLF | LAST2);
1485         } else {
1486                 SEQFIFOSTORE(p, MSG, 0, 0, VLF | CONT);
1487                 SEQFIFOLOAD(p, MSGOUTSNOOP, 0, VLF | LAST1 | FLUSH1);
1488         }
1489
1490         ALG_OPERATION(p, OP_ALG_ALGSEL_ZUCA,
1491                       OP_ALG_AAI_F9,
1492                       OP_ALG_AS_INITFINAL,
1493                       dir == OP_TYPE_ENCAP_PROTOCOL ?
1494                              ICV_CHECK_DISABLE : ICV_CHECK_ENABLE,
1495                       DIR_ENC);
1496
1497         ALG_OPERATION(p, OP_ALG_ALGSEL_AES,
1498                       OP_ALG_AAI_CTR,
1499                       OP_ALG_AS_INITFINAL,
1500                       ICV_CHECK_DISABLE,
1501                       dir == OP_TYPE_ENCAP_PROTOCOL ? DIR_ENC : DIR_DEC);
1502
1503         if (dir == OP_TYPE_ENCAP_PROTOCOL) {
1504                 MOVE(p, CONTEXT2, 0, IFIFOAB1, 0, 4, LAST1 | FLUSH1 | IMMED);
1505         } else {
1506                 /* Save ICV */
1507                 MOVE(p, OFIFO, 0, MATH0, 0, 4, IMMED);
1508
1509                 LOAD(p, NFIFOENTRY_STYPE_ALTSOURCE |
1510                      NFIFOENTRY_DEST_CLASS2 |
1511                      NFIFOENTRY_DTYPE_ICV |
1512                      NFIFOENTRY_LC2 | 4, NFIFO_SZL, 0, 4, IMMED);
1513                 MOVE(p, MATH0, 0, ALTSOURCE, 0, 4, WAITCOMP | IMMED);
1514         }
1515
1516         /* Reset ZUCA mode and done interrupt */
1517         LOAD(p, CLRW_CLR_C2MODE, CLRW, 0, 4, IMMED);
1518         LOAD(p, CIRQ_ZADI, ICTRL, 0, 4, IMMED);
1519
1520         PATCH_JUMP(p, pkeyjump, keyjump);
1521
1522         return 0;
1523 }
1524
1525 static inline int
1526 pdcp_insert_cplane_zuc_snow_op(struct program *p,
1527                                bool swap __maybe_unused,
1528                                struct alginfo *cipherdata,
1529                                struct alginfo *authdata,
1530                                unsigned int dir,
1531                                enum pdcp_sn_size sn_size,
1532                                unsigned char era_2_sw_hfn_ovrd __maybe_unused)
1533 {
1534         LABEL(keyjump);
1535         REFERENCE(pkeyjump);
1536
1537         if (rta_sec_era < RTA_SEC_ERA_5) {
1538                 pr_err("Invalid era for selected algorithm\n");
1539                 return -ENOTSUP;
1540         }
1541
1542         pkeyjump = JUMP(p, keyjump, LOCAL_JUMP, ALL_TRUE, SHRD | SELF | BOTH);
1543         KEY(p, KEY1, cipherdata->key_enc_flags, cipherdata->key,
1544             cipherdata->keylen, INLINE_KEY(cipherdata));
1545         KEY(p, KEY2, authdata->key_enc_flags, authdata->key, authdata->keylen,
1546             INLINE_KEY(authdata));
1547
1548         if (rta_sec_era >= RTA_SEC_ERA_8) {
1549                 int pclid;
1550
1551                 if (sn_size == PDCP_SN_SIZE_5)
1552                         pclid = OP_PCLID_LTE_PDCP_CTRL_MIXED;
1553                 else
1554                         pclid = OP_PCLID_LTE_PDCP_USER_RN;
1555
1556                 PROTOCOL(p, dir, pclid,
1557                          ((uint16_t)cipherdata->algtype << 8) |
1558                          (uint16_t)authdata->algtype);
1559
1560                 return 0;
1561         }
1562
1563         SET_LABEL(p, keyjump);
1564         SEQLOAD(p, MATH0, 7, 1, 0);
1565         JUMP(p, 1, LOCAL_JUMP, ALL_TRUE, CALM);
1566         MOVE(p, MATH0, 7, IFIFOAB2, 0, 1, IMMED);
1567         if (swap == false)
1568                 MATHB(p, MATH0, AND, PDCP_C_PLANE_SN_MASK, MATH1, 8,
1569                         IFB | IMMED2);
1570         else
1571                 MATHB(p, MATH0, AND, PDCP_C_PLANE_SN_MASK, MATH1, 8,
1572                         IFB | IMMED2);
1573
1574         MATHB(p, MATH1, SHLD, MATH1, MATH1, 8, 0);
1575         MOVE(p, DESCBUF, 4, MATH2, 0, 8, WAITCOMP | IMMED);
1576         MATHB(p, MATH1, OR, MATH2, MATH1, 8, 0);
1577         MOVE(p, MATH1, 0, CONTEXT1, 0, 8, IMMED);
1578         MOVE(p, MATH1, 0, CONTEXT2, 0, 4, IMMED);
1579         if (swap == false) {
1580                 MATHB(p, MATH1, AND, lower_32_bits(PDCP_BEARER_MASK), MATH2,
1581                         4, IMMED2);
1582                 MATHB(p, MATH1, AND, upper_32_bits(PDCP_DIR_MASK), MATH3,
1583                         4, IMMED2);
1584         } else {
1585                 MATHB(p, MATH1, AND, lower_32_bits(PDCP_BEARER_MASK_BE), MATH2,
1586                         4, IMMED2);
1587                 MATHB(p, MATH1, AND, upper_32_bits(PDCP_DIR_MASK_BE), MATH3,
1588                         4, IMMED2);
1589         }
1590         MATHB(p, MATH3, SHLD, MATH3, MATH3, 8, 0);
1591         MOVE(p, MATH2, 4, OFIFO, 0, 12, IMMED);
1592         MOVE(p, OFIFO, 0, CONTEXT2, 4, 12, IMMED);
1593
1594         if (dir == OP_TYPE_ENCAP_PROTOCOL) {
1595                 MATHB(p, SEQINSZ, ADD, PDCP_MAC_I_LEN, VSEQOUTSZ, 4, IMMED2);
1596                 MATHB(p, SEQINSZ, SUB, ZERO, VSEQINSZ, 4, 0);
1597         } else {
1598                 MATHB(p, SEQINSZ, SUB, PDCP_MAC_I_LEN, VSEQOUTSZ, 4, IMMED2);
1599                 MATHB(p, VSEQOUTSZ, SUB, ZERO, VSEQINSZ, 4, 0);
1600         }
1601
1602         SEQSTORE(p, MATH0, 7, 1, 0);
1603
1604         if (dir == OP_TYPE_ENCAP_PROTOCOL) {
1605                 SEQFIFOSTORE(p, MSG, 0, 0, VLF);
1606                 SEQFIFOLOAD(p, MSGINSNOOP, 0, VLF | LAST2);
1607         } else {
1608                 SEQFIFOSTORE(p, MSG, 0, 0, VLF | CONT);
1609                 SEQFIFOLOAD(p, MSGOUTSNOOP, 0, VLF | LAST2);
1610         }
1611
1612         ALG_OPERATION(p, OP_ALG_ALGSEL_SNOW_F9,
1613                       OP_ALG_AAI_F9,
1614                       OP_ALG_AS_INITFINAL,
1615                       dir == OP_TYPE_ENCAP_PROTOCOL ?
1616                              ICV_CHECK_DISABLE : ICV_CHECK_ENABLE,
1617                       DIR_DEC);
1618
1619         ALG_OPERATION(p, OP_ALG_ALGSEL_ZUCE,
1620                       OP_ALG_AAI_F8,
1621                       OP_ALG_AS_INITFINAL,
1622                       ICV_CHECK_DISABLE,
1623                       dir == OP_TYPE_ENCAP_PROTOCOL ? DIR_ENC : DIR_DEC);
1624
1625         if (dir == OP_TYPE_ENCAP_PROTOCOL) {
1626                 MOVE(p, CONTEXT2, 0, IFIFOAB1, 0, 4, LAST1 | FLUSH1 | IMMED);
1627         } else {
1628                 SEQFIFOLOAD(p, MSG1, 4, LAST1 | FLUSH1);
1629                 JUMP(p, 1, LOCAL_JUMP, ALL_TRUE, CLASS1 | NOP | NIFP);
1630
1631                 if (rta_sec_era >= RTA_SEC_ERA_6)
1632                         /*
1633                          * For SEC ERA 6, there's a problem with the OFIFO
1634                          * pointer, and thus it needs to be reset here before
1635                          * moving to M0.
1636                          */
1637                         LOAD(p, 0, DCTRL, 0, LDLEN_RST_CHA_OFIFO_PTR, IMMED);
1638
1639                 /* Put ICV to M0 before sending it to C2 for comparison. */
1640                 MOVE(p, OFIFO, 0, MATH0, 0, 4, WAITCOMP | IMMED);
1641
1642                 LOAD(p, NFIFOENTRY_STYPE_ALTSOURCE |
1643                      NFIFOENTRY_DEST_CLASS2 |
1644                      NFIFOENTRY_DTYPE_ICV |
1645                      NFIFOENTRY_LC2 | 4, NFIFO_SZL, 0, 4, IMMED);
1646                 MOVE(p, MATH0, 0, ALTSOURCE, 0, 4, IMMED);
1647         }
1648
1649         PATCH_JUMP(p, pkeyjump, keyjump);
1650         return 0;
1651 }
1652
1653 static inline int
1654 pdcp_insert_cplane_zuc_aes_op(struct program *p,
1655                               bool swap __maybe_unused,
1656                               struct alginfo *cipherdata,
1657                               struct alginfo *authdata,
1658                               unsigned int dir,
1659                               enum pdcp_sn_size sn_size,
1660                               unsigned char era_2_sw_hfn_ovrd __maybe_unused)
1661 {
1662         if (rta_sec_era < RTA_SEC_ERA_5) {
1663                 pr_err("Invalid era for selected algorithm\n");
1664                 return -ENOTSUP;
1665         }
1666
1667         if (rta_sec_era >= RTA_SEC_ERA_8) {
1668                 int pclid;
1669
1670                 KEY(p, KEY1, cipherdata->key_enc_flags, cipherdata->key,
1671                                 cipherdata->keylen, INLINE_KEY(cipherdata));
1672                 KEY(p, KEY2, authdata->key_enc_flags, authdata->key,
1673                                 authdata->keylen, INLINE_KEY(authdata));
1674
1675                 if (sn_size == PDCP_SN_SIZE_5)
1676                         pclid = OP_PCLID_LTE_PDCP_CTRL_MIXED;
1677                 else
1678                         pclid = OP_PCLID_LTE_PDCP_USER_RN;
1679
1680                 PROTOCOL(p, dir, pclid,
1681                          ((uint16_t)cipherdata->algtype << 8) |
1682                          (uint16_t)authdata->algtype);
1683                 return 0;
1684         }
1685
1686         SEQLOAD(p, MATH0, 7, 1, 0);
1687         JUMP(p, 1, LOCAL_JUMP, ALL_TRUE, CALM);
1688         if (swap == false)
1689                 MATHB(p, MATH0, AND, PDCP_C_PLANE_SN_MASK, MATH1, 8,
1690                         IFB | IMMED2);
1691         else
1692                 MATHB(p, MATH0, AND, PDCP_C_PLANE_SN_MASK, MATH1, 8,
1693                         IFB | IMMED2);
1694
1695         MATHB(p, MATH1, SHLD, MATH1, MATH1, 8, 0);
1696         MOVE(p, DESCBUF, 4, MATH2, 0, 0x08, WAITCOMP | IMMED);
1697         MATHB(p, MATH1, OR, MATH2, MATH2, 8, 0);
1698         SEQSTORE(p, MATH0, 7, 1, 0);
1699         if (dir == OP_TYPE_ENCAP_PROTOCOL) {
1700                 KEY(p, KEY1, authdata->key_enc_flags, authdata->key,
1701                     authdata->keylen, INLINE_KEY(authdata));
1702                 MOVE(p, MATH2, 0, IFIFOAB1, 0, 0x08, IMMED);
1703                 MOVE(p, MATH0, 7, IFIFOAB1, 0, 1, IMMED);
1704
1705                 MATHB(p, SEQINSZ, SUB, ZERO, VSEQINSZ, 4, 0);
1706                 MATHB(p, VSEQINSZ, ADD, PDCP_MAC_I_LEN, VSEQOUTSZ, 4, IMMED2);
1707
1708                 ALG_OPERATION(p, OP_ALG_ALGSEL_AES,
1709                               OP_ALG_AAI_CMAC,
1710                               OP_ALG_AS_INITFINAL,
1711                               ICV_CHECK_DISABLE,
1712                               DIR_DEC);
1713                 SEQFIFOLOAD(p, MSG1, 0, VLF | LAST1 | FLUSH1);
1714                 MOVE(p, CONTEXT1, 0, MATH3, 0, 4, WAITCOMP | IMMED);
1715                 LOAD(p, CLRW_RESET_CLS1_CHA |
1716                      CLRW_CLR_C1KEY |
1717                      CLRW_CLR_C1CTX |
1718                      CLRW_CLR_C1ICV |
1719                      CLRW_CLR_C1DATAS |
1720                      CLRW_CLR_C1MODE,
1721                      CLRW, 0, 4, IMMED);
1722
1723                 KEY(p, KEY1, cipherdata->key_enc_flags, cipherdata->key,
1724                     cipherdata->keylen, INLINE_KEY(cipherdata));
1725
1726                 MOVE(p, MATH2, 0, CONTEXT1, 0, 8, IMMED);
1727                 SEQINPTR(p, 0, PDCP_NULL_MAX_FRAME_LEN, RTO);
1728
1729                 ALG_OPERATION(p, OP_ALG_ALGSEL_ZUCE,
1730                               OP_ALG_AAI_F8,
1731                               OP_ALG_AS_INITFINAL,
1732                               ICV_CHECK_DISABLE,
1733                               DIR_ENC);
1734                 SEQFIFOSTORE(p, MSG, 0, 0, VLF);
1735
1736                 SEQFIFOLOAD(p, SKIP, 1, 0);
1737
1738                 SEQFIFOLOAD(p, MSG1, 0, VLF);
1739                 MOVE(p, MATH3, 0, IFIFOAB1, 0, 4, LAST1 | FLUSH1 | IMMED);
1740         } else {
1741                 MOVE(p, MATH2, 0, CONTEXT1, 0, 8, IMMED);
1742
1743                 MOVE(p, CONTEXT1, 0, CONTEXT2, 0, 8, IMMED);
1744
1745                 MATHB(p, SEQINSZ, SUB, ZERO, VSEQINSZ, 4, 0);
1746
1747                 MATHB(p, SEQINSZ, SUB, PDCP_MAC_I_LEN, VSEQOUTSZ, 4, IMMED2);
1748
1749                 KEY(p, KEY1, cipherdata->key_enc_flags, cipherdata->key,
1750                     cipherdata->keylen, INLINE_KEY(cipherdata));
1751
1752                 MOVE(p, CONTEXT1, 0, CONTEXT2, 0, 8, IMMED);
1753
1754                 ALG_OPERATION(p, OP_ALG_ALGSEL_ZUCE,
1755                               OP_ALG_AAI_F8,
1756                               OP_ALG_AS_INITFINAL,
1757                               ICV_CHECK_DISABLE,
1758                               DIR_DEC);
1759                 SEQFIFOSTORE(p, MSG, 0, 0, VLF | CONT);
1760                 SEQFIFOLOAD(p, MSG1, 0, VLF | LAST1 | FLUSH1);
1761
1762                 MOVE(p, OFIFO, 0, MATH3, 0, 4, IMMED);
1763
1764                 LOAD(p, CLRW_RESET_CLS1_CHA |
1765                      CLRW_CLR_C1KEY |
1766                      CLRW_CLR_C1CTX |
1767                      CLRW_CLR_C1ICV |
1768                      CLRW_CLR_C1DATAS |
1769                      CLRW_CLR_C1MODE,
1770                      CLRW, 0, 4, IMMED);
1771
1772                 KEY(p, KEY1, authdata->key_enc_flags, authdata->key,
1773                     authdata->keylen, INLINE_KEY(authdata));
1774
1775                 SEQINPTR(p, 0, 0, SOP);
1776
1777                 ALG_OPERATION(p, OP_ALG_ALGSEL_AES,
1778                               OP_ALG_AAI_CMAC,
1779                               OP_ALG_AS_INITFINAL,
1780                               ICV_CHECK_ENABLE,
1781                               DIR_DEC);
1782
1783                 MATHB(p, SEQINSZ, SUB, ZERO, VSEQINSZ, 4, 0);
1784
1785                 MOVE(p, CONTEXT2, 0, IFIFOAB1, 0, 8, IMMED);
1786
1787                 SEQFIFOLOAD(p, MSG1, 0, VLF | LAST1 | FLUSH1);
1788
1789                 LOAD(p, NFIFOENTRY_STYPE_ALTSOURCE |
1790                      NFIFOENTRY_DEST_CLASS1 |
1791                      NFIFOENTRY_DTYPE_ICV |
1792                      NFIFOENTRY_LC1 |
1793                      NFIFOENTRY_FC1 | 4, NFIFO_SZL, 0, 4, IMMED);
1794                 MOVE(p, MATH3, 0, ALTSOURCE, 0, 4, IMMED);
1795         }
1796
1797         return 0;
1798 }
1799
1800 static inline int
1801 pdcp_insert_uplane_15bit_op(struct program *p,
1802                             bool swap __maybe_unused,
1803                             struct alginfo *cipherdata,
1804                             struct alginfo *authdata,
1805                             unsigned int dir)
1806 {
1807         int op;
1808
1809         /* Insert auth key if requested */
1810         if (authdata && authdata->algtype)
1811                 KEY(p, KEY2, authdata->key_enc_flags, authdata->key,
1812                     authdata->keylen, INLINE_KEY(authdata));
1813
1814         /* Insert Cipher Key */
1815         KEY(p, KEY1, cipherdata->key_enc_flags, cipherdata->key,
1816             cipherdata->keylen, INLINE_KEY(cipherdata));
1817
1818         if (rta_sec_era >= RTA_SEC_ERA_8) {
1819                 PROTOCOL(p, dir, OP_PCLID_LTE_PDCP_USER,
1820                          (uint16_t)cipherdata->algtype);
1821                 return 0;
1822         }
1823
1824         SEQLOAD(p, MATH0, 6, 2, 0);
1825         JUMP(p, 1, LOCAL_JUMP, ALL_TRUE, CALM);
1826         if (swap == false)
1827                 MATHB(p, MATH0, AND, PDCP_U_PLANE_15BIT_SN_MASK, MATH1, 8,
1828                       IFB | IMMED2);
1829         else
1830                 MATHB(p, MATH0, AND, PDCP_U_PLANE_15BIT_SN_MASK_BE, MATH1, 8,
1831                       IFB | IMMED2);
1832         SEQSTORE(p, MATH0, 6, 2, 0);
1833         MATHB(p, MATH1, SHLD, MATH1, MATH1, 8, 0);
1834         MOVEB(p, DESCBUF, 8, MATH2, 0, 8, WAITCOMP | IMMED);
1835         MATHB(p, MATH1, OR, MATH2, MATH2, 8, 0);
1836
1837         MATHB(p, SEQINSZ, SUB, MATH3, VSEQINSZ, 4, 0);
1838         MATHB(p, SEQINSZ, SUB, MATH3, VSEQOUTSZ, 4, 0);
1839
1840         SEQFIFOSTORE(p, MSG, 0, 0, VLF);
1841
1842         op = dir == OP_TYPE_ENCAP_PROTOCOL ? DIR_ENC : DIR_DEC;
1843         switch (cipherdata->algtype) {
1844         case PDCP_CIPHER_TYPE_SNOW:
1845                 MOVEB(p, MATH2, 0, CONTEXT1, 0, 8, WAITCOMP | IMMED);
1846                 ALG_OPERATION(p, OP_ALG_ALGSEL_SNOW_F8,
1847                               OP_ALG_AAI_F8,
1848                               OP_ALG_AS_INITFINAL,
1849                               ICV_CHECK_DISABLE,
1850                               op);
1851                 break;
1852
1853         case PDCP_CIPHER_TYPE_AES:
1854                 MOVEB(p, MATH2, 0, CONTEXT1, 0x10, 0x10, WAITCOMP | IMMED);
1855                 ALG_OPERATION(p, OP_ALG_ALGSEL_AES,
1856                               OP_ALG_AAI_CTR,
1857                               OP_ALG_AS_INITFINAL,
1858                               ICV_CHECK_DISABLE,
1859                               op);
1860                 break;
1861
1862         case PDCP_CIPHER_TYPE_ZUC:
1863                 if (rta_sec_era < RTA_SEC_ERA_5) {
1864                         pr_err("Invalid era for selected algorithm\n");
1865                         return -ENOTSUP;
1866                 }
1867                 MOVEB(p, MATH2, 0, CONTEXT1, 0, 0x08, IMMED);
1868                 MOVEB(p, MATH2, 0, CONTEXT1, 0x08, 0x08, WAITCOMP | IMMED);
1869
1870                 ALG_OPERATION(p, OP_ALG_ALGSEL_ZUCE,
1871                               OP_ALG_AAI_F8,
1872                               OP_ALG_AS_INITFINAL,
1873                               ICV_CHECK_DISABLE,
1874                               op);
1875                 break;
1876
1877         default:
1878                 pr_err("%s: Invalid encrypt algorithm selected: %d\n",
1879                        "pdcp_insert_uplane_15bit_op", cipherdata->algtype);
1880                 return -EINVAL;
1881         }
1882
1883         SEQFIFOLOAD(p, MSG1, 0, VLF | LAST1 | FLUSH1);
1884
1885         return 0;
1886 }
1887
1888 /*
1889  * Function for inserting the snippet of code responsible for creating
1890  * the HFN override code via either DPOVRD or via the input frame.
1891  */
1892 static inline int
1893 insert_hfn_ov_op(struct program *p,
1894                  uint32_t shift,
1895                  enum pdb_type_e pdb_type,
1896                  unsigned char era_2_sw_hfn_ovrd)
1897 {
1898         uint32_t imm = PDCP_DPOVRD_HFN_OV_EN;
1899         uint16_t hfn_pdb_offset;
1900
1901         if (rta_sec_era == RTA_SEC_ERA_2 && !era_2_sw_hfn_ovrd)
1902                 return 0;
1903
1904         switch (pdb_type) {
1905         case PDCP_PDB_TYPE_NO_PDB:
1906                 /*
1907                  * If there is no PDB, then HFN override mechanism does not
1908                  * make any sense, thus in this case the function will
1909                  * return the pointer to the current position in the
1910                  * descriptor buffer
1911                  */
1912                 return 0;
1913
1914         case PDCP_PDB_TYPE_REDUCED_PDB:
1915                 hfn_pdb_offset = 4;
1916                 break;
1917
1918         case PDCP_PDB_TYPE_FULL_PDB:
1919                 hfn_pdb_offset = 8;
1920                 break;
1921
1922         default:
1923                 return -EINVAL;
1924         }
1925
1926         if (rta_sec_era > RTA_SEC_ERA_2) {
1927                 MATHB(p, DPOVRD, AND, imm, NONE, 8, IFB | IMMED2);
1928         } else {
1929                 SEQLOAD(p, MATH0, 4, 4, 0);
1930                 JUMP(p, 1, LOCAL_JUMP, ALL_TRUE, CALM);
1931                 MATHB(p, MATH0, AND, imm, NONE, 8, IFB | IMMED2);
1932                 SEQSTORE(p, MATH0, 4, 4, 0);
1933         }
1934
1935         if (rta_sec_era >= RTA_SEC_ERA_8)
1936                 JUMP(p, 6, LOCAL_JUMP, ALL_TRUE, MATH_Z);
1937         else
1938                 JUMP(p, 5, LOCAL_JUMP, ALL_TRUE, MATH_Z);
1939
1940         if (rta_sec_era > RTA_SEC_ERA_2)
1941                 MATHB(p, DPOVRD, LSHIFT, shift, MATH0, 4, IMMED2);
1942         else
1943                 MATHB(p, MATH0, LSHIFT, shift, MATH0, 4, IMMED2);
1944
1945         MATHB(p, MATH0, SHLD, MATH0, MATH0, 8, 0);
1946         MOVE(p, MATH0, 0, DESCBUF, hfn_pdb_offset, 4, IMMED);
1947
1948         if (rta_sec_era >= RTA_SEC_ERA_8)
1949                 /*
1950                  * For ERA8, DPOVRD could be handled by the PROTOCOL command
1951                  * itself. For now, this is not done. Thus, clear DPOVRD here
1952                  * to alleviate any side-effects.
1953                  */
1954                 MATHB(p, DPOVRD, AND, ZERO, DPOVRD, 4, STL);
1955
1956         return 0;
1957 }
1958
1959 /*
1960  * PDCP Control PDB creation function
1961  */
1962 static inline enum pdb_type_e
1963 cnstr_pdcp_c_plane_pdb(struct program *p,
1964                        uint32_t hfn,
1965                        enum pdcp_sn_size sn_size,
1966                        unsigned char bearer,
1967                        unsigned char direction,
1968                        uint32_t hfn_threshold,
1969                        struct alginfo *cipherdata,
1970                        struct alginfo *authdata)
1971 {
1972         struct pdcp_pdb pdb;
1973         enum pdb_type_e
1974                 pdb_mask[PDCP_CIPHER_TYPE_INVALID][PDCP_AUTH_TYPE_INVALID] = {
1975                         {       /* NULL */
1976                                 PDCP_PDB_TYPE_NO_PDB,           /* NULL */
1977                                 PDCP_PDB_TYPE_FULL_PDB,         /* SNOW f9 */
1978                                 PDCP_PDB_TYPE_FULL_PDB,         /* AES CMAC */
1979                                 PDCP_PDB_TYPE_FULL_PDB          /* ZUC-I */
1980                         },
1981                         {       /* SNOW f8 */
1982                                 PDCP_PDB_TYPE_FULL_PDB,         /* NULL */
1983                                 PDCP_PDB_TYPE_FULL_PDB,         /* SNOW f9 */
1984                                 PDCP_PDB_TYPE_REDUCED_PDB,      /* AES CMAC */
1985                                 PDCP_PDB_TYPE_REDUCED_PDB       /* ZUC-I */
1986                         },
1987                         {       /* AES CTR */
1988                                 PDCP_PDB_TYPE_FULL_PDB,         /* NULL */
1989                                 PDCP_PDB_TYPE_REDUCED_PDB,      /* SNOW f9 */
1990                                 PDCP_PDB_TYPE_FULL_PDB,         /* AES CMAC */
1991                                 PDCP_PDB_TYPE_REDUCED_PDB       /* ZUC-I */
1992                         },
1993                         {       /* ZUC-E */
1994                                 PDCP_PDB_TYPE_FULL_PDB,         /* NULL */
1995                                 PDCP_PDB_TYPE_REDUCED_PDB,      /* SNOW f9 */
1996                                 PDCP_PDB_TYPE_REDUCED_PDB,      /* AES CMAC */
1997                                 PDCP_PDB_TYPE_FULL_PDB          /* ZUC-I */
1998                         },
1999         };
2000
2001         if (rta_sec_era >= RTA_SEC_ERA_8) {
2002                 memset(&pdb, 0x00, sizeof(struct pdcp_pdb));
2003
2004                 /* To support 12-bit seq numbers, we use u-plane opt in pdb.
2005                  * SEC supports 5-bit only with c-plane opt in pdb.
2006                  */
2007                 if (sn_size == PDCP_SN_SIZE_12) {
2008                         pdb.hfn_res = hfn << PDCP_U_PLANE_PDB_LONG_SN_HFN_SHIFT;
2009                         pdb.bearer_dir_res = (uint32_t)
2010                                 ((bearer << PDCP_U_PLANE_PDB_BEARER_SHIFT) |
2011                                  (direction << PDCP_U_PLANE_PDB_DIR_SHIFT));
2012
2013                         pdb.hfn_thr_res =
2014                         hfn_threshold << PDCP_U_PLANE_PDB_LONG_SN_HFN_THR_SHIFT;
2015
2016                 } else {
2017                         /* This means 5-bit c-plane.
2018                          * Here we use c-plane opt in pdb
2019                          */
2020
2021                         /* This is a HW issue. Bit 2 should be set to zero,
2022                          * but it does not work this way. Override here.
2023                          */
2024                         pdb.opt_res.rsvd = 0x00000002;
2025
2026                         /* Copy relevant information from user to PDB */
2027                         pdb.hfn_res = hfn << PDCP_C_PLANE_PDB_HFN_SHIFT;
2028                         pdb.bearer_dir_res = (uint32_t)
2029                                 ((bearer << PDCP_C_PLANE_PDB_BEARER_SHIFT) |
2030                                 (direction << PDCP_C_PLANE_PDB_DIR_SHIFT));
2031                         pdb.hfn_thr_res =
2032                         hfn_threshold << PDCP_C_PLANE_PDB_HFN_THR_SHIFT;
2033                 }
2034
2035                 /* copy PDB in descriptor*/
2036                 __rta_out32(p, pdb.opt_res.opt);
2037                 __rta_out32(p, pdb.hfn_res);
2038                 __rta_out32(p, pdb.bearer_dir_res);
2039                 __rta_out32(p, pdb.hfn_thr_res);
2040
2041                 return PDCP_PDB_TYPE_FULL_PDB;
2042         }
2043
2044         switch (pdb_mask[cipherdata->algtype][authdata->algtype]) {
2045         case PDCP_PDB_TYPE_NO_PDB:
2046                 break;
2047
2048         case PDCP_PDB_TYPE_REDUCED_PDB:
2049                 __rta_out32(p, (hfn << PDCP_C_PLANE_PDB_HFN_SHIFT));
2050                 __rta_out32(p,
2051                             (uint32_t)((bearer <<
2052                                         PDCP_C_PLANE_PDB_BEARER_SHIFT) |
2053                                         (direction <<
2054                                          PDCP_C_PLANE_PDB_DIR_SHIFT)));
2055                 break;
2056
2057         case PDCP_PDB_TYPE_FULL_PDB:
2058                 memset(&pdb, 0x00, sizeof(struct pdcp_pdb));
2059
2060                 /* This is a HW issue. Bit 2 should be set to zero,
2061                  * but it does not work this way. Override here.
2062                  */
2063                 pdb.opt_res.rsvd = 0x00000002;
2064
2065                 /* Copy relevant information from user to PDB */
2066                 pdb.hfn_res = hfn << PDCP_C_PLANE_PDB_HFN_SHIFT;
2067                 pdb.bearer_dir_res = (uint32_t)
2068                         ((bearer << PDCP_C_PLANE_PDB_BEARER_SHIFT) |
2069                          (direction << PDCP_C_PLANE_PDB_DIR_SHIFT));
2070                 pdb.hfn_thr_res =
2071                         hfn_threshold << PDCP_C_PLANE_PDB_HFN_THR_SHIFT;
2072
2073                 /* copy PDB in descriptor*/
2074                 __rta_out32(p, pdb.opt_res.opt);
2075                 __rta_out32(p, pdb.hfn_res);
2076                 __rta_out32(p, pdb.bearer_dir_res);
2077                 __rta_out32(p, pdb.hfn_thr_res);
2078
2079                 break;
2080
2081         default:
2082                 return PDCP_PDB_TYPE_INVALID;
2083         }
2084
2085         return pdb_mask[cipherdata->algtype][authdata->algtype];
2086 }
2087
2088 /*
2089  * PDCP UPlane PDB creation function
2090  */
2091 static inline int
2092 cnstr_pdcp_u_plane_pdb(struct program *p,
2093                        enum pdcp_sn_size sn_size,
2094                        uint32_t hfn, unsigned short bearer,
2095                        unsigned short direction,
2096                        uint32_t hfn_threshold)
2097 {
2098         struct pdcp_pdb pdb;
2099         /* Read options from user */
2100         /* Depending on sequence number length, the HFN and HFN threshold
2101          * have different lengths.
2102          */
2103         memset(&pdb, 0x00, sizeof(struct pdcp_pdb));
2104
2105         switch (sn_size) {
2106         case PDCP_SN_SIZE_7:
2107                 pdb.opt_res.opt |= PDCP_U_PLANE_PDB_OPT_SHORT_SN;
2108                 pdb.hfn_res = hfn << PDCP_U_PLANE_PDB_SHORT_SN_HFN_SHIFT;
2109                 pdb.hfn_thr_res =
2110                         hfn_threshold<<PDCP_U_PLANE_PDB_SHORT_SN_HFN_THR_SHIFT;
2111                 break;
2112
2113         case PDCP_SN_SIZE_12:
2114                 pdb.opt_res.opt &= (uint32_t)(~PDCP_U_PLANE_PDB_OPT_SHORT_SN);
2115                 pdb.hfn_res = hfn << PDCP_U_PLANE_PDB_LONG_SN_HFN_SHIFT;
2116                 pdb.hfn_thr_res =
2117                         hfn_threshold<<PDCP_U_PLANE_PDB_LONG_SN_HFN_THR_SHIFT;
2118                 break;
2119
2120         case PDCP_SN_SIZE_15:
2121                 pdb.opt_res.opt = (uint32_t)(PDCP_U_PLANE_PDB_OPT_15B_SN);
2122                 pdb.hfn_res = hfn << PDCP_U_PLANE_PDB_15BIT_SN_HFN_SHIFT;
2123                 pdb.hfn_thr_res =
2124                         hfn_threshold<<PDCP_U_PLANE_PDB_15BIT_SN_HFN_THR_SHIFT;
2125                 break;
2126
2127         default:
2128                 pr_err("Invalid Sequence Number Size setting in PDB\n");
2129                 return -EINVAL;
2130         }
2131
2132         pdb.bearer_dir_res = (uint32_t)
2133                                 ((bearer << PDCP_U_PLANE_PDB_BEARER_SHIFT) |
2134                                  (direction << PDCP_U_PLANE_PDB_DIR_SHIFT));
2135
2136         /* copy PDB in descriptor*/
2137         __rta_out32(p, pdb.opt_res.opt);
2138         __rta_out32(p, pdb.hfn_res);
2139         __rta_out32(p, pdb.bearer_dir_res);
2140         __rta_out32(p, pdb.hfn_thr_res);
2141
2142         return 0;
2143 }
2144 /**
2145  * cnstr_shdsc_pdcp_c_plane_encap - Function for creating a PDCP Control Plane
2146  *                                  encapsulation descriptor.
2147  * @descbuf: pointer to buffer for descriptor construction
2148  * @ps: if 36/40bit addressing is desired, this parameter must be true
2149  * @swap: must be true when core endianness doesn't match SEC endianness
2150  * @hfn: starting Hyper Frame Number to be used together with the SN from the
2151  *       PDCP frames.
2152  * @sn_size: size of sequence numbers, only 5/12 bit sequence numbers are valid
2153  * @bearer: radio bearer ID
2154  * @direction: the direction of the PDCP frame (UL/DL)
2155  * @hfn_threshold: HFN value that once reached triggers a warning from SEC that
2156  *                 keys should be renegotiated at the earliest convenience.
2157  * @cipherdata: pointer to block cipher transform definitions
2158  *              Valid algorithm values are those from cipher_type_pdcp enum.
2159  * @authdata: pointer to authentication transform definitions
2160  *            Valid algorithm values are those from auth_type_pdcp enum.
2161  * @era_2_sw_hfn_ovrd: if software HFN override mechanism is desired for
2162  *                     this descriptor. Note: Can only be used for
2163  *                     SEC ERA 2.
2164  * Return: size of descriptor written in words or negative number on error.
2165  *         Once the function returns, the value of this parameter can be used
2166  *         for reclaiming the space that wasn't used for the descriptor.
2167  *
2168  * Note: descbuf must be large enough to contain a full 256 byte long
2169  * descriptor; after the function returns, by subtracting the actual number of
2170  * bytes used, the user can reuse the remaining buffer space for other purposes.
2171  */
2172 static inline int
2173 cnstr_shdsc_pdcp_c_plane_encap(uint32_t *descbuf,
2174                                bool ps,
2175                                bool swap,
2176                                uint32_t hfn,
2177                                enum pdcp_sn_size sn_size,
2178                                unsigned char bearer,
2179                                unsigned char direction,
2180                                uint32_t hfn_threshold,
2181                                struct alginfo *cipherdata,
2182                                struct alginfo *authdata,
2183                                unsigned char era_2_sw_hfn_ovrd)
2184 {
2185         static int
2186                 (*pdcp_cp_fp[PDCP_CIPHER_TYPE_INVALID][PDCP_AUTH_TYPE_INVALID])
2187                         (struct program*, bool swap, struct alginfo *,
2188                          struct alginfo *, unsigned int, enum pdcp_sn_size,
2189                         unsigned char __maybe_unused) = {
2190                 {       /* NULL */
2191                         pdcp_insert_cplane_null_op,     /* NULL */
2192                         pdcp_insert_cplane_int_only_op, /* SNOW f9 */
2193                         pdcp_insert_cplane_int_only_op, /* AES CMAC */
2194                         pdcp_insert_cplane_int_only_op  /* ZUC-I */
2195                 },
2196                 {       /* SNOW f8 */
2197                         pdcp_insert_cplane_enc_only_op, /* NULL */
2198                         pdcp_insert_cplane_acc_op,      /* SNOW f9 */
2199                         pdcp_insert_cplane_snow_aes_op, /* AES CMAC */
2200                         pdcp_insert_cplane_snow_zuc_op  /* ZUC-I */
2201                 },
2202                 {       /* AES CTR */
2203                         pdcp_insert_cplane_enc_only_op, /* NULL */
2204                         pdcp_insert_cplane_aes_snow_op, /* SNOW f9 */
2205                         pdcp_insert_cplane_acc_op,      /* AES CMAC */
2206                         pdcp_insert_cplane_aes_zuc_op   /* ZUC-I */
2207                 },
2208                 {       /* ZUC-E */
2209                         pdcp_insert_cplane_enc_only_op, /* NULL */
2210                         pdcp_insert_cplane_zuc_snow_op, /* SNOW f9 */
2211                         pdcp_insert_cplane_zuc_aes_op,  /* AES CMAC */
2212                         pdcp_insert_cplane_acc_op       /* ZUC-I */
2213                 },
2214         };
2215         static enum rta_share_type
2216                 desc_share[PDCP_CIPHER_TYPE_INVALID][PDCP_AUTH_TYPE_INVALID] = {
2217                 {       /* NULL */
2218                         SHR_WAIT,       /* NULL */
2219                         SHR_ALWAYS,     /* SNOW f9 */
2220                         SHR_ALWAYS,     /* AES CMAC */
2221                         SHR_ALWAYS      /* ZUC-I */
2222                 },
2223                 {       /* SNOW f8 */
2224                         SHR_ALWAYS,     /* NULL */
2225                         SHR_ALWAYS,     /* SNOW f9 */
2226                         SHR_WAIT,       /* AES CMAC */
2227                         SHR_WAIT        /* ZUC-I */
2228                 },
2229                 {       /* AES CTR */
2230                         SHR_ALWAYS,     /* NULL */
2231                         SHR_ALWAYS,     /* SNOW f9 */
2232                         SHR_ALWAYS,     /* AES CMAC */
2233                         SHR_WAIT        /* ZUC-I */
2234                 },
2235                 {       /* ZUC-E */
2236                         SHR_ALWAYS,     /* NULL */
2237                         SHR_WAIT,       /* SNOW f9 */
2238                         SHR_WAIT,       /* AES CMAC */
2239                         SHR_ALWAYS      /* ZUC-I */
2240                 },
2241         };
2242         enum pdb_type_e pdb_type;
2243         struct program prg;
2244         struct program *p = &prg;
2245         int err;
2246         LABEL(pdb_end);
2247
2248         if (rta_sec_era != RTA_SEC_ERA_2 && era_2_sw_hfn_ovrd) {
2249                 pr_err("Cannot select SW HFN override for other era than 2");
2250                 return -EINVAL;
2251         }
2252
2253         if (sn_size != PDCP_SN_SIZE_12 && sn_size != PDCP_SN_SIZE_5) {
2254                 pr_err("C-plane supports only 5-bit and 12-bit sequence numbers\n");
2255                 return -EINVAL;
2256         }
2257
2258         PROGRAM_CNTXT_INIT(p, descbuf, 0);
2259         if (swap)
2260                 PROGRAM_SET_BSWAP(p);
2261         if (ps)
2262                 PROGRAM_SET_36BIT_ADDR(p);
2263
2264         SHR_HDR(p, desc_share[cipherdata->algtype][authdata->algtype], 0, 0);
2265
2266         pdb_type = cnstr_pdcp_c_plane_pdb(p,
2267                         hfn,
2268                         sn_size,
2269                         bearer,
2270                         direction,
2271                         hfn_threshold,
2272                         cipherdata,
2273                         authdata);
2274
2275         SET_LABEL(p, pdb_end);
2276
2277         err = insert_hfn_ov_op(p, sn_size, pdb_type,
2278                                era_2_sw_hfn_ovrd);
2279         if (err)
2280                 return err;
2281
2282         err = pdcp_cp_fp[cipherdata->algtype][authdata->algtype](p,
2283                 swap,
2284                 cipherdata,
2285                 authdata,
2286                 OP_TYPE_ENCAP_PROTOCOL,
2287                 sn_size,
2288                 era_2_sw_hfn_ovrd);
2289         if (err)
2290                 return err;
2291
2292         PATCH_HDR(p, 0, pdb_end);
2293
2294         return PROGRAM_FINALIZE(p);
2295 }
2296
2297 /**
2298  * cnstr_shdsc_pdcp_c_plane_decap - Function for creating a PDCP Control Plane
2299  *                                  decapsulation descriptor.
2300  * @descbuf: pointer to buffer for descriptor construction
2301  * @ps: if 36/40bit addressing is desired, this parameter must be true
2302  * @swap: must be true when core endianness doesn't match SEC endianness
2303  * @hfn: starting Hyper Frame Number to be used together with the SN from the
2304  *       PDCP frames.
2305  * @sn_size: size of sequence numbers, only 5/12 bit sequence numbers are valid
2306  * @bearer: radio bearer ID
2307  * @direction: the direction of the PDCP frame (UL/DL)
2308  * @hfn_threshold: HFN value that once reached triggers a warning from SEC that
2309  *                 keys should be renegotiated at the earliest convenience.
2310  * @cipherdata: pointer to block cipher transform definitions
2311  *              Valid algorithm values are those from cipher_type_pdcp enum.
2312  * @authdata: pointer to authentication transform definitions
2313  *            Valid algorithm values are those from auth_type_pdcp enum.
2314  * @era_2_sw_hfn_ovrd: if software HFN override mechanism is desired for
2315  *                     this descriptor. Note: Can only be used for
2316  *                     SEC ERA 2.
2317  *
2318  * Return: size of descriptor written in words or negative number on error.
2319  *         Once the function returns, the value of this parameter can be used
2320  *         for reclaiming the space that wasn't used for the descriptor.
2321  *
2322  * Note: descbuf must be large enough to contain a full 256 byte long
2323  * descriptor; after the function returns, by subtracting the actual number of
2324  * bytes used, the user can reuse the remaining buffer space for other purposes.
2325  */
2326 static inline int
2327 cnstr_shdsc_pdcp_c_plane_decap(uint32_t *descbuf,
2328                                bool ps,
2329                                bool swap,
2330                                uint32_t hfn,
2331                                enum pdcp_sn_size sn_size,
2332                                unsigned char bearer,
2333                                unsigned char direction,
2334                                uint32_t hfn_threshold,
2335                                struct alginfo *cipherdata,
2336                                struct alginfo *authdata,
2337                                unsigned char era_2_sw_hfn_ovrd)
2338 {
2339         static int
2340                 (*pdcp_cp_fp[PDCP_CIPHER_TYPE_INVALID][PDCP_AUTH_TYPE_INVALID])
2341                         (struct program*, bool swap, struct alginfo *,
2342                          struct alginfo *, unsigned int, enum pdcp_sn_size,
2343                          unsigned char) = {
2344                 {       /* NULL */
2345                         pdcp_insert_cplane_null_op,     /* NULL */
2346                         pdcp_insert_cplane_int_only_op, /* SNOW f9 */
2347                         pdcp_insert_cplane_int_only_op, /* AES CMAC */
2348                         pdcp_insert_cplane_int_only_op  /* ZUC-I */
2349                 },
2350                 {       /* SNOW f8 */
2351                         pdcp_insert_cplane_enc_only_op, /* NULL */
2352                         pdcp_insert_cplane_acc_op,      /* SNOW f9 */
2353                         pdcp_insert_cplane_snow_aes_op, /* AES CMAC */
2354                         pdcp_insert_cplane_snow_zuc_op  /* ZUC-I */
2355                 },
2356                 {       /* AES CTR */
2357                         pdcp_insert_cplane_enc_only_op, /* NULL */
2358                         pdcp_insert_cplane_aes_snow_op, /* SNOW f9 */
2359                         pdcp_insert_cplane_acc_op,      /* AES CMAC */
2360                         pdcp_insert_cplane_aes_zuc_op   /* ZUC-I */
2361                 },
2362                 {       /* ZUC-E */
2363                         pdcp_insert_cplane_enc_only_op, /* NULL */
2364                         pdcp_insert_cplane_zuc_snow_op, /* SNOW f9 */
2365                         pdcp_insert_cplane_zuc_aes_op,  /* AES CMAC */
2366                         pdcp_insert_cplane_acc_op       /* ZUC-I */
2367                 },
2368         };
2369         static enum rta_share_type
2370                 desc_share[PDCP_CIPHER_TYPE_INVALID][PDCP_AUTH_TYPE_INVALID] = {
2371                 {       /* NULL */
2372                         SHR_WAIT,       /* NULL */
2373                         SHR_ALWAYS,     /* SNOW f9 */
2374                         SHR_ALWAYS,     /* AES CMAC */
2375                         SHR_ALWAYS      /* ZUC-I */
2376                 },
2377                 {       /* SNOW f8 */
2378                         SHR_ALWAYS,     /* NULL */
2379                         SHR_ALWAYS,     /* SNOW f9 */
2380                         SHR_WAIT,       /* AES CMAC */
2381                         SHR_WAIT        /* ZUC-I */
2382                 },
2383                 {       /* AES CTR */
2384                         SHR_ALWAYS,     /* NULL */
2385                         SHR_ALWAYS,     /* SNOW f9 */
2386                         SHR_ALWAYS,     /* AES CMAC */
2387                         SHR_WAIT        /* ZUC-I */
2388                 },
2389                 {       /* ZUC-E */
2390                         SHR_ALWAYS,     /* NULL */
2391                         SHR_WAIT,       /* SNOW f9 */
2392                         SHR_WAIT,       /* AES CMAC */
2393                         SHR_ALWAYS      /* ZUC-I */
2394                 },
2395         };
2396         enum pdb_type_e pdb_type;
2397         struct program prg;
2398         struct program *p = &prg;
2399         int err;
2400         LABEL(pdb_end);
2401
2402         if (rta_sec_era != RTA_SEC_ERA_2 && era_2_sw_hfn_ovrd) {
2403                 pr_err("Cannot select SW HFN override for other era than 2");
2404                 return -EINVAL;
2405         }
2406
2407         if (sn_size != PDCP_SN_SIZE_12 && sn_size != PDCP_SN_SIZE_5) {
2408                 pr_err("C-plane supports only 5-bit and 12-bit sequence numbers\n");
2409                 return -EINVAL;
2410         }
2411
2412         PROGRAM_CNTXT_INIT(p, descbuf, 0);
2413         if (swap)
2414                 PROGRAM_SET_BSWAP(p);
2415         if (ps)
2416                 PROGRAM_SET_36BIT_ADDR(p);
2417
2418         SHR_HDR(p, desc_share[cipherdata->algtype][authdata->algtype], 0, 0);
2419
2420         pdb_type = cnstr_pdcp_c_plane_pdb(p,
2421                         hfn,
2422                         sn_size,
2423                         bearer,
2424                         direction,
2425                         hfn_threshold,
2426                         cipherdata,
2427                         authdata);
2428
2429         SET_LABEL(p, pdb_end);
2430
2431         err = insert_hfn_ov_op(p, sn_size, pdb_type,
2432                                era_2_sw_hfn_ovrd);
2433         if (err)
2434                 return err;
2435
2436         err = pdcp_cp_fp[cipherdata->algtype][authdata->algtype](p,
2437                 swap,
2438                 cipherdata,
2439                 authdata,
2440                 OP_TYPE_DECAP_PROTOCOL,
2441                 sn_size,
2442                 era_2_sw_hfn_ovrd);
2443         if (err)
2444                 return err;
2445
2446         PATCH_HDR(p, 0, pdb_end);
2447
2448         return PROGRAM_FINALIZE(p);
2449 }
2450
2451 /**
2452  * cnstr_shdsc_pdcp_u_plane_encap - Function for creating a PDCP User Plane
2453  *                                  encapsulation descriptor.
2454  * @descbuf: pointer to buffer for descriptor construction
2455  * @ps: if 36/40bit addressing is desired, this parameter must be true
2456  * @swap: must be true when core endianness doesn't match SEC endianness
2457  * @sn_size: selects Sequence Number Size: 7/12/15 bits
2458  * @hfn: starting Hyper Frame Number to be used together with the SN from the
2459  *       PDCP frames.
2460  * @bearer: radio bearer ID
2461  * @direction: the direction of the PDCP frame (UL/DL)
2462  * @hfn_threshold: HFN value that once reached triggers a warning from SEC that
2463  *                 keys should be renegotiated at the earliest convenience.
2464  * @cipherdata: pointer to block cipher transform definitions
2465  *              Valid algorithm values are those from cipher_type_pdcp enum.
2466  * @era_2_sw_hfn_ovrd: if software HFN override mechanism is desired for
2467  *                     this descriptor. Note: Can only be used for
2468  *                     SEC ERA 2.
2469  *
2470  * Return: size of descriptor written in words or negative number on error.
2471  *         Once the function returns, the value of this parameter can be used
2472  *         for reclaiming the space that wasn't used for the descriptor.
2473  *
2474  * Note: descbuf must be large enough to contain a full 256 byte long
2475  * descriptor; after the function returns, by subtracting the actual number of
2476  * bytes used, the user can reuse the remaining buffer space for other purposes.
2477  */
2478 static inline int
2479 cnstr_shdsc_pdcp_u_plane_encap(uint32_t *descbuf,
2480                                bool ps,
2481                                bool swap,
2482                                enum pdcp_sn_size sn_size,
2483                                uint32_t hfn,
2484                                unsigned short bearer,
2485                                unsigned short direction,
2486                                uint32_t hfn_threshold,
2487                                struct alginfo *cipherdata,
2488                                struct alginfo *authdata,
2489                                unsigned char era_2_sw_hfn_ovrd)
2490 {
2491         struct program prg;
2492         struct program *p = &prg;
2493         int err;
2494         LABEL(pdb_end);
2495
2496         if (rta_sec_era != RTA_SEC_ERA_2 && era_2_sw_hfn_ovrd) {
2497                 pr_err("Cannot select SW HFN ovrd for other era than 2");
2498                 return -EINVAL;
2499         }
2500
2501         if (authdata && !authdata->algtype && rta_sec_era < RTA_SEC_ERA_8) {
2502                 pr_err("Cannot use u-plane auth with era < 8");
2503                 return -EINVAL;
2504         }
2505
2506         PROGRAM_CNTXT_INIT(p, descbuf, 0);
2507         if (swap)
2508                 PROGRAM_SET_BSWAP(p);
2509         if (ps)
2510                 PROGRAM_SET_36BIT_ADDR(p);
2511
2512         SHR_HDR(p, SHR_ALWAYS, 0, 0);
2513         if (cnstr_pdcp_u_plane_pdb(p, sn_size, hfn, bearer, direction,
2514                                    hfn_threshold)) {
2515                 pr_err("Error creating PDCP UPlane PDB\n");
2516                 return -EINVAL;
2517         }
2518         SET_LABEL(p, pdb_end);
2519
2520         err = insert_hfn_ov_op(p, sn_size, PDCP_PDB_TYPE_FULL_PDB,
2521                                era_2_sw_hfn_ovrd);
2522         if (err)
2523                 return err;
2524
2525         /* Insert auth key if requested */
2526         if (authdata && authdata->algtype) {
2527                 KEY(p, KEY2, authdata->key_enc_flags,
2528                     (uint64_t)authdata->key, authdata->keylen,
2529                     INLINE_KEY(authdata));
2530         }
2531
2532         switch (sn_size) {
2533         case PDCP_SN_SIZE_7:
2534         case PDCP_SN_SIZE_12:
2535                 switch (cipherdata->algtype) {
2536                 case PDCP_CIPHER_TYPE_ZUC:
2537                         if (rta_sec_era < RTA_SEC_ERA_5) {
2538                                 pr_err("Invalid era for selected algorithm\n");
2539                                 return -ENOTSUP;
2540                         }
2541                         /* fallthrough */
2542                 case PDCP_CIPHER_TYPE_AES:
2543                 case PDCP_CIPHER_TYPE_SNOW:
2544                 case PDCP_CIPHER_TYPE_NULL:
2545                         /* Insert Cipher Key */
2546                         KEY(p, KEY1, cipherdata->key_enc_flags,
2547                             (uint64_t)cipherdata->key, cipherdata->keylen,
2548                             INLINE_KEY(cipherdata));
2549
2550                         if (authdata)
2551                                 PROTOCOL(p, OP_TYPE_ENCAP_PROTOCOL,
2552                                          OP_PCLID_LTE_PDCP_USER_RN,
2553                                          ((uint16_t)cipherdata->algtype << 8) |
2554                                          (uint16_t)authdata->algtype);
2555                         else
2556                                 PROTOCOL(p, OP_TYPE_ENCAP_PROTOCOL,
2557                                          OP_PCLID_LTE_PDCP_USER,
2558                                          (uint16_t)cipherdata->algtype);
2559                         break;
2560                 default:
2561                         pr_err("%s: Invalid encrypt algorithm selected: %d\n",
2562                                "cnstr_pcl_shdsc_pdcp_u_plane_decap",
2563                                cipherdata->algtype);
2564                         return -EINVAL;
2565                 }
2566                 break;
2567
2568         case PDCP_SN_SIZE_15:
2569                 switch (cipherdata->algtype) {
2570                 case PDCP_CIPHER_TYPE_NULL:
2571                         insert_copy_frame_op(p,
2572                                              cipherdata,
2573                                              OP_TYPE_ENCAP_PROTOCOL);
2574                         break;
2575
2576                 default:
2577                         err = pdcp_insert_uplane_15bit_op(p, swap, cipherdata,
2578                                         authdata, OP_TYPE_ENCAP_PROTOCOL);
2579                         if (err)
2580                                 return err;
2581                         break;
2582                 }
2583                 break;
2584
2585         case PDCP_SN_SIZE_5:
2586         default:
2587                 pr_err("Invalid SN size selected\n");
2588                 return -ENOTSUP;
2589         }
2590
2591         PATCH_HDR(p, 0, pdb_end);
2592         return PROGRAM_FINALIZE(p);
2593 }
2594
2595 /**
2596  * cnstr_shdsc_pdcp_u_plane_decap - Function for creating a PDCP User Plane
2597  *                                  decapsulation descriptor.
2598  * @descbuf: pointer to buffer for descriptor construction
2599  * @ps: if 36/40bit addressing is desired, this parameter must be true
2600  * @swap: must be true when core endianness doesn't match SEC endianness
2601  * @sn_size: selects Sequence Number Size: 7/12/15 bits
2602  * @hfn: starting Hyper Frame Number to be used together with the SN from the
2603  *       PDCP frames.
2604  * @bearer: radio bearer ID
2605  * @direction: the direction of the PDCP frame (UL/DL)
2606  * @hfn_threshold: HFN value that once reached triggers a warning from SEC that
2607  *                 keys should be renegotiated at the earliest convenience.
2608  * @cipherdata: pointer to block cipher transform definitions
2609  *              Valid algorithm values are those from cipher_type_pdcp enum.
2610  * @era_2_sw_hfn_ovrd: if software HFN override mechanism is desired for
2611  *                     this descriptor. Note: Can only be used for
2612  *                     SEC ERA 2.
2613  *
2614  * Return: size of descriptor written in words or negative number on error.
2615  *         Once the function returns, the value of this parameter can be used
2616  *         for reclaiming the space that wasn't used for the descriptor.
2617  *
2618  * Note: descbuf must be large enough to contain a full 256 byte long
2619  * descriptor; after the function returns, by subtracting the actual number of
2620  * bytes used, the user can reuse the remaining buffer space for other purposes.
2621  */
2622 static inline int
2623 cnstr_shdsc_pdcp_u_plane_decap(uint32_t *descbuf,
2624                                bool ps,
2625                                bool swap,
2626                                enum pdcp_sn_size sn_size,
2627                                uint32_t hfn,
2628                                unsigned short bearer,
2629                                unsigned short direction,
2630                                uint32_t hfn_threshold,
2631                                struct alginfo *cipherdata,
2632                                struct alginfo *authdata,
2633                                unsigned char era_2_sw_hfn_ovrd)
2634 {
2635         struct program prg;
2636         struct program *p = &prg;
2637         int err;
2638         LABEL(pdb_end);
2639
2640         if (rta_sec_era != RTA_SEC_ERA_2 && era_2_sw_hfn_ovrd) {
2641                 pr_err("Cannot select SW HFN override for other era than 2");
2642                 return -EINVAL;
2643         }
2644
2645         if (authdata && !authdata->algtype && rta_sec_era < RTA_SEC_ERA_8) {
2646                 pr_err("Cannot use u-plane auth with era < 8");
2647                 return -EINVAL;
2648         }
2649
2650         PROGRAM_CNTXT_INIT(p, descbuf, 0);
2651         if (swap)
2652                 PROGRAM_SET_BSWAP(p);
2653         if (ps)
2654                 PROGRAM_SET_36BIT_ADDR(p);
2655
2656         SHR_HDR(p, SHR_ALWAYS, 0, 0);
2657         if (cnstr_pdcp_u_plane_pdb(p, sn_size, hfn, bearer, direction,
2658                                    hfn_threshold)) {
2659                 pr_err("Error creating PDCP UPlane PDB\n");
2660                 return -EINVAL;
2661         }
2662         SET_LABEL(p, pdb_end);
2663
2664         err = insert_hfn_ov_op(p, sn_size, PDCP_PDB_TYPE_FULL_PDB,
2665                                era_2_sw_hfn_ovrd);
2666         if (err)
2667                 return err;
2668
2669         /* Insert auth key if requested */
2670         if (authdata && authdata->algtype)
2671                 KEY(p, KEY2, authdata->key_enc_flags,
2672                     (uint64_t)authdata->key, authdata->keylen,
2673                     INLINE_KEY(authdata));
2674
2675         switch (sn_size) {
2676         case PDCP_SN_SIZE_7:
2677         case PDCP_SN_SIZE_12:
2678                 switch (cipherdata->algtype) {
2679                 case PDCP_CIPHER_TYPE_ZUC:
2680                         if (rta_sec_era < RTA_SEC_ERA_5) {
2681                                 pr_err("Invalid era for selected algorithm\n");
2682                                 return -ENOTSUP;
2683                         }
2684                         /* fallthrough */
2685                 case PDCP_CIPHER_TYPE_AES:
2686                 case PDCP_CIPHER_TYPE_SNOW:
2687                 case PDCP_CIPHER_TYPE_NULL:
2688                         /* Insert Cipher Key */
2689                         KEY(p, KEY1, cipherdata->key_enc_flags,
2690                             cipherdata->key, cipherdata->keylen,
2691                             INLINE_KEY(cipherdata));
2692                         if (authdata)
2693                                 PROTOCOL(p, OP_TYPE_DECAP_PROTOCOL,
2694                                          OP_PCLID_LTE_PDCP_USER_RN,
2695                                          ((uint16_t)cipherdata->algtype << 8) |
2696                                          (uint16_t)authdata->algtype);
2697                         else
2698                                 PROTOCOL(p, OP_TYPE_DECAP_PROTOCOL,
2699                                          OP_PCLID_LTE_PDCP_USER,
2700                                          (uint16_t)cipherdata->algtype);
2701                         break;
2702                 default:
2703                         pr_err("%s: Invalid encrypt algorithm selected: %d\n",
2704                                "cnstr_pcl_shdsc_pdcp_u_plane_decap",
2705                                cipherdata->algtype);
2706                         return -EINVAL;
2707                 }
2708                 break;
2709
2710         case PDCP_SN_SIZE_15:
2711                 switch (cipherdata->algtype) {
2712                 case PDCP_CIPHER_TYPE_NULL:
2713                         insert_copy_frame_op(p,
2714                                              cipherdata,
2715                                              OP_TYPE_DECAP_PROTOCOL);
2716                         break;
2717
2718                 default:
2719                         err = pdcp_insert_uplane_15bit_op(p, swap, cipherdata,
2720                                 authdata, OP_TYPE_DECAP_PROTOCOL);
2721                         if (err)
2722                                 return err;
2723                         break;
2724                 }
2725                 break;
2726
2727         case PDCP_SN_SIZE_5:
2728         default:
2729                 pr_err("Invalid SN size selected\n");
2730                 return -ENOTSUP;
2731         }
2732
2733         PATCH_HDR(p, 0, pdb_end);
2734         return PROGRAM_FINALIZE(p);
2735 }
2736
2737 /**
2738  * cnstr_shdsc_pdcp_short_mac - Function for creating a PDCP Short MAC
2739  *                              descriptor.
2740  * @descbuf: pointer to buffer for descriptor construction
2741  * @ps: if 36/40bit addressing is desired, this parameter must be true
2742  * @swap: must be true when core endianness doesn't match SEC endianness
2743  * @authdata: pointer to authentication transform definitions
2744  *            Valid algorithm values are those from auth_type_pdcp enum.
2745  *
2746  * Return: size of descriptor written in words or negative number on error.
2747  *         Once the function returns, the value of this parameter can be used
2748  *         for reclaiming the space that wasn't used for the descriptor.
2749  *
2750  * Note: descbuf must be large enough to contain a full 256 byte long
2751  * descriptor; after the function returns, by subtracting the actual number of
2752  * bytes used, the user can reuse the remaining buffer space for other purposes.
2753  */
2754 static inline int
2755 cnstr_shdsc_pdcp_short_mac(uint32_t *descbuf,
2756                            bool ps,
2757                            bool swap,
2758                            struct alginfo *authdata)
2759 {
2760         struct program prg;
2761         struct program *p = &prg;
2762         uint32_t iv[3] = {0, 0, 0};
2763         LABEL(local_offset);
2764         REFERENCE(move_cmd_read_descbuf);
2765         REFERENCE(move_cmd_write_descbuf);
2766
2767         PROGRAM_CNTXT_INIT(p, descbuf, 0);
2768         if (swap)
2769                 PROGRAM_SET_BSWAP(p);
2770         if (ps)
2771                 PROGRAM_SET_36BIT_ADDR(p);
2772
2773         SHR_HDR(p, SHR_ALWAYS, 1, 0);
2774
2775         if (rta_sec_era > RTA_SEC_ERA_2) {
2776                 MATHB(p, SEQINSZ, SUB, ZERO, VSEQINSZ, 4, 0);
2777                 MATHB(p, SEQINSZ, SUB, ZERO, MATH1, 4, 0);
2778         } else {
2779                 MATHB(p, SEQINSZ, ADD, ONE, MATH1, 4, 0);
2780                 MATHB(p, MATH1, SUB, ONE, MATH1, 4, 0);
2781                 MATHB(p, ZERO, ADD, MATH1, VSEQINSZ, 4, 0);
2782                 MOVE(p, MATH1, 0, MATH0, 0, 8, IMMED);
2783
2784                 /*
2785                  * Since MOVELEN is available only starting with
2786                  * SEC ERA 3, use poor man's MOVELEN: create a MOVE
2787                  * command dynamically by writing the length from M1 by
2788                  * OR-ing the command in the M1 register and MOVE the
2789                  * result into the descriptor buffer. Care must be taken
2790                  * wrt. the location of the command because of SEC
2791                  * pipelining. The actual MOVEs are written at the end
2792                  * of the descriptor due to calculations needed on the
2793                  * offset in the descriptor for the MOVE command.
2794                  */
2795                 move_cmd_read_descbuf = MOVE(p, DESCBUF, 0, MATH0, 0, 6,
2796                                              IMMED);
2797                 move_cmd_write_descbuf = MOVE(p, MATH0, 0, DESCBUF, 0, 8,
2798                                               WAITCOMP | IMMED);
2799         }
2800         MATHB(p, ZERO, ADD, MATH1, VSEQOUTSZ, 4, 0);
2801
2802         switch (authdata->algtype) {
2803         case PDCP_AUTH_TYPE_NULL:
2804                 SEQFIFOSTORE(p, MSG, 0, 0, VLF);
2805                 if (rta_sec_era > RTA_SEC_ERA_2) {
2806                         MOVE(p, AB1, 0, OFIFO, 0, MATH1, 0);
2807                 } else {
2808                         SET_LABEL(p, local_offset);
2809
2810                         /* Shut off automatic Info FIFO entries */
2811                         LOAD(p, 0, DCTRL, LDOFF_DISABLE_AUTO_NFIFO, 0, IMMED);
2812
2813                         /* Placeholder for MOVE command with length from M1
2814                          * register
2815                          */
2816                         MOVE(p, IFIFOAB1, 0, OFIFO, 0, 0, IMMED);
2817
2818                         /* Enable automatic Info FIFO entries */
2819                         LOAD(p, 0, DCTRL, LDOFF_ENABLE_AUTO_NFIFO, 0, IMMED);
2820                 }
2821
2822                 LOAD(p, (uintptr_t)iv, MATH0, 0, 8, IMMED | COPY);
2823                 SEQFIFOLOAD(p, MSG1, 0, VLF | LAST1 | LAST2 | FLUSH1);
2824                 SEQSTORE(p, MATH0, 0, 4, 0);
2825
2826                 break;
2827
2828         case PDCP_AUTH_TYPE_SNOW:
2829                 iv[0] = 0xFFFFFFFF;
2830                 iv[1] = swap ? swab32(0x04000000) : 0x04000000;
2831                 iv[2] = swap ? swab32(0xF8000000) : 0xF8000000;
2832
2833                 KEY(p, KEY2, authdata->key_enc_flags, authdata->key,
2834                     authdata->keylen, INLINE_KEY(authdata));
2835                 LOAD(p, (uintptr_t)&iv, CONTEXT2, 0, 12, IMMED | COPY);
2836                 ALG_OPERATION(p, OP_ALG_ALGSEL_SNOW_F9,
2837                               OP_ALG_AAI_F9,
2838                               OP_ALG_AS_INITFINAL,
2839                               ICV_CHECK_DISABLE,
2840                               DIR_ENC);
2841                 SEQFIFOSTORE(p, MSG, 0, 0, VLF);
2842
2843                 if (rta_sec_era > RTA_SEC_ERA_2) {
2844                         MOVE(p, AB1, 0, OFIFO, 0, MATH1, 0);
2845                 } else {
2846                         SET_LABEL(p, local_offset);
2847
2848
2849                         /* Shut off automatic Info FIFO entries */
2850                         LOAD(p, 0, DCTRL, LDOFF_DISABLE_AUTO_NFIFO, 0, IMMED);
2851
2852                         /* Placeholder for MOVE command with length from M1
2853                          * register
2854                          */
2855                         MOVE(p, IFIFOAB1, 0, OFIFO, 0, 0, IMMED);
2856
2857                         /* Enable automatic Info FIFO entries */
2858                         LOAD(p, 0, DCTRL, LDOFF_ENABLE_AUTO_NFIFO, 0, IMMED);
2859                 }
2860                 SEQFIFOLOAD(p, MSGINSNOOP, 0, VLF | LAST1 | LAST2 | FLUSH1);
2861                 SEQSTORE(p, CONTEXT2, 0, 4, 0);
2862
2863                 break;
2864
2865         case PDCP_AUTH_TYPE_AES:
2866                 iv[0] = 0xFFFFFFFF;
2867                 iv[1] = swap ? swab32(0xFC000000) : 0xFC000000;
2868                 iv[2] = 0x00000000; /* unused */
2869
2870                 KEY(p, KEY1, authdata->key_enc_flags, authdata->key,
2871                     authdata->keylen, INLINE_KEY(authdata));
2872                 LOAD(p, (uintptr_t)&iv, MATH0, 0, 8, IMMED | COPY);
2873                 MOVE(p, MATH0, 0, IFIFOAB1, 0, 8, IMMED);
2874                 ALG_OPERATION(p, OP_ALG_ALGSEL_AES,
2875                               OP_ALG_AAI_CMAC,
2876                               OP_ALG_AS_INITFINAL,
2877                               ICV_CHECK_DISABLE,
2878                               DIR_ENC);
2879                 SEQFIFOSTORE(p, MSG, 0, 0, VLF);
2880
2881                 if (rta_sec_era > RTA_SEC_ERA_2) {
2882                         MOVE(p, AB2, 0, OFIFO, 0, MATH1, 0);
2883                 } else {
2884                         SET_LABEL(p, local_offset);
2885
2886                         /* Shut off automatic Info FIFO entries */
2887                         LOAD(p, 0, DCTRL, LDOFF_DISABLE_AUTO_NFIFO, 0, IMMED);
2888
2889                         /* Placeholder for MOVE command with length from M1
2890                          * register
2891                          */
2892                         MOVE(p, IFIFOAB2, 0, OFIFO, 0, 0, IMMED);
2893
2894                         /* Enable automatic Info FIFO entries */
2895                         LOAD(p, 0, DCTRL, LDOFF_ENABLE_AUTO_NFIFO, 0, IMMED);
2896                 }
2897                 SEQFIFOLOAD(p, MSGINSNOOP, 0, VLF | LAST1 | LAST2 | FLUSH1);
2898                 SEQSTORE(p, CONTEXT1, 0, 4, 0);
2899
2900                 break;
2901
2902         case PDCP_AUTH_TYPE_ZUC:
2903                 if (rta_sec_era < RTA_SEC_ERA_5) {
2904                         pr_err("Invalid era for selected algorithm\n");
2905                         return -ENOTSUP;
2906                 }
2907                 iv[0] = 0xFFFFFFFF;
2908                 iv[1] = swap ? swab32(0xFC000000) : 0xFC000000;
2909                 iv[2] = 0x00000000; /* unused */
2910
2911                 KEY(p, KEY2, authdata->key_enc_flags, authdata->key,
2912                     authdata->keylen, INLINE_KEY(authdata));
2913                 LOAD(p, (uintptr_t)&iv, CONTEXT2, 0, 12, IMMED | COPY);
2914                 ALG_OPERATION(p, OP_ALG_ALGSEL_ZUCA,
2915                               OP_ALG_AAI_F9,
2916                               OP_ALG_AS_INITFINAL,
2917                               ICV_CHECK_DISABLE,
2918                               DIR_ENC);
2919                 SEQFIFOSTORE(p, MSG, 0, 0, VLF);
2920                 MOVE(p, AB1, 0, OFIFO, 0, MATH1, 0);
2921                 SEQFIFOLOAD(p, MSGINSNOOP, 0, VLF | LAST1 | LAST2 | FLUSH1);
2922                 SEQSTORE(p, CONTEXT2, 0, 4, 0);
2923
2924                 break;
2925
2926         default:
2927                 pr_err("%s: Invalid integrity algorithm selected: %d\n",
2928                        "cnstr_shdsc_pdcp_short_mac", authdata->algtype);
2929                 return -EINVAL;
2930         }
2931
2932
2933         if (rta_sec_era < RTA_SEC_ERA_3) {
2934                 PATCH_MOVE(p, move_cmd_read_descbuf, local_offset);
2935                 PATCH_MOVE(p, move_cmd_write_descbuf, local_offset);
2936         }
2937
2938         return PROGRAM_FINALIZE(p);
2939 }
2940
2941 #endif /* __DESC_PDCP_H__ */