crypto/dpaax_sec: support PDCP 12-bit C-Plane
[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                             unsigned int dir)
1805 {
1806         int op;
1807         /* Insert Cipher Key */
1808         KEY(p, KEY1, cipherdata->key_enc_flags, cipherdata->key,
1809             cipherdata->keylen, INLINE_KEY(cipherdata));
1810
1811         if (rta_sec_era >= RTA_SEC_ERA_8) {
1812                 PROTOCOL(p, dir, OP_PCLID_LTE_PDCP_USER,
1813                          (uint16_t)cipherdata->algtype);
1814                 return 0;
1815         }
1816
1817         SEQLOAD(p, MATH0, 6, 2, 0);
1818         JUMP(p, 1, LOCAL_JUMP, ALL_TRUE, CALM);
1819         if (swap == false)
1820                 MATHB(p, MATH0, AND, PDCP_U_PLANE_15BIT_SN_MASK, MATH1, 8,
1821                       IFB | IMMED2);
1822         else
1823                 MATHB(p, MATH0, AND, PDCP_U_PLANE_15BIT_SN_MASK_BE, MATH1, 8,
1824                       IFB | IMMED2);
1825         SEQSTORE(p, MATH0, 6, 2, 0);
1826         MATHB(p, MATH1, SHLD, MATH1, MATH1, 8, 0);
1827         MOVEB(p, DESCBUF, 8, MATH2, 0, 8, WAITCOMP | IMMED);
1828         MATHB(p, MATH1, OR, MATH2, MATH2, 8, 0);
1829
1830         MATHB(p, SEQINSZ, SUB, MATH3, VSEQINSZ, 4, 0);
1831         MATHB(p, SEQINSZ, SUB, MATH3, VSEQOUTSZ, 4, 0);
1832
1833         SEQFIFOSTORE(p, MSG, 0, 0, VLF);
1834
1835         op = dir == OP_TYPE_ENCAP_PROTOCOL ? DIR_ENC : DIR_DEC;
1836         switch (cipherdata->algtype) {
1837         case PDCP_CIPHER_TYPE_SNOW:
1838                 MOVEB(p, MATH2, 0, CONTEXT1, 0, 8, WAITCOMP | IMMED);
1839                 ALG_OPERATION(p, OP_ALG_ALGSEL_SNOW_F8,
1840                               OP_ALG_AAI_F8,
1841                               OP_ALG_AS_INITFINAL,
1842                               ICV_CHECK_DISABLE,
1843                               op);
1844                 break;
1845
1846         case PDCP_CIPHER_TYPE_AES:
1847                 MOVEB(p, MATH2, 0, CONTEXT1, 0x10, 0x10, WAITCOMP | IMMED);
1848                 ALG_OPERATION(p, OP_ALG_ALGSEL_AES,
1849                               OP_ALG_AAI_CTR,
1850                               OP_ALG_AS_INITFINAL,
1851                               ICV_CHECK_DISABLE,
1852                               op);
1853                 break;
1854
1855         case PDCP_CIPHER_TYPE_ZUC:
1856                 if (rta_sec_era < RTA_SEC_ERA_5) {
1857                         pr_err("Invalid era for selected algorithm\n");
1858                         return -ENOTSUP;
1859                 }
1860                 MOVEB(p, MATH2, 0, CONTEXT1, 0, 0x08, IMMED);
1861                 MOVEB(p, MATH2, 0, CONTEXT1, 0x08, 0x08, WAITCOMP | IMMED);
1862
1863                 ALG_OPERATION(p, OP_ALG_ALGSEL_ZUCE,
1864                               OP_ALG_AAI_F8,
1865                               OP_ALG_AS_INITFINAL,
1866                               ICV_CHECK_DISABLE,
1867                               op);
1868                 break;
1869
1870         default:
1871                 pr_err("%s: Invalid encrypt algorithm selected: %d\n",
1872                        "pdcp_insert_uplane_15bit_op", cipherdata->algtype);
1873                 return -EINVAL;
1874         }
1875
1876         SEQFIFOLOAD(p, MSG1, 0, VLF | LAST1 | FLUSH1);
1877
1878         return 0;
1879 }
1880
1881 /*
1882  * Function for inserting the snippet of code responsible for creating
1883  * the HFN override code via either DPOVRD or via the input frame.
1884  */
1885 static inline int
1886 insert_hfn_ov_op(struct program *p,
1887                  uint32_t shift,
1888                  enum pdb_type_e pdb_type,
1889                  unsigned char era_2_sw_hfn_ovrd)
1890 {
1891         uint32_t imm = PDCP_DPOVRD_HFN_OV_EN;
1892         uint16_t hfn_pdb_offset;
1893
1894         if (rta_sec_era == RTA_SEC_ERA_2 && !era_2_sw_hfn_ovrd)
1895                 return 0;
1896
1897         switch (pdb_type) {
1898         case PDCP_PDB_TYPE_NO_PDB:
1899                 /*
1900                  * If there is no PDB, then HFN override mechanism does not
1901                  * make any sense, thus in this case the function will
1902                  * return the pointer to the current position in the
1903                  * descriptor buffer
1904                  */
1905                 return 0;
1906
1907         case PDCP_PDB_TYPE_REDUCED_PDB:
1908                 hfn_pdb_offset = 4;
1909                 break;
1910
1911         case PDCP_PDB_TYPE_FULL_PDB:
1912                 hfn_pdb_offset = 8;
1913                 break;
1914
1915         default:
1916                 return -EINVAL;
1917         }
1918
1919         if (rta_sec_era > RTA_SEC_ERA_2) {
1920                 MATHB(p, DPOVRD, AND, imm, NONE, 8, IFB | IMMED2);
1921         } else {
1922                 SEQLOAD(p, MATH0, 4, 4, 0);
1923                 JUMP(p, 1, LOCAL_JUMP, ALL_TRUE, CALM);
1924                 MATHB(p, MATH0, AND, imm, NONE, 8, IFB | IMMED2);
1925                 SEQSTORE(p, MATH0, 4, 4, 0);
1926         }
1927
1928         if (rta_sec_era >= RTA_SEC_ERA_8)
1929                 JUMP(p, 6, LOCAL_JUMP, ALL_TRUE, MATH_Z);
1930         else
1931                 JUMP(p, 5, LOCAL_JUMP, ALL_TRUE, MATH_Z);
1932
1933         if (rta_sec_era > RTA_SEC_ERA_2)
1934                 MATHB(p, DPOVRD, LSHIFT, shift, MATH0, 4, IMMED2);
1935         else
1936                 MATHB(p, MATH0, LSHIFT, shift, MATH0, 4, IMMED2);
1937
1938         MATHB(p, MATH0, SHLD, MATH0, MATH0, 8, 0);
1939         MOVE(p, MATH0, 0, DESCBUF, hfn_pdb_offset, 4, IMMED);
1940
1941         if (rta_sec_era >= RTA_SEC_ERA_8)
1942                 /*
1943                  * For ERA8, DPOVRD could be handled by the PROTOCOL command
1944                  * itself. For now, this is not done. Thus, clear DPOVRD here
1945                  * to alleviate any side-effects.
1946                  */
1947                 MATHB(p, DPOVRD, AND, ZERO, DPOVRD, 4, STL);
1948
1949         return 0;
1950 }
1951
1952 /*
1953  * PDCP Control PDB creation function
1954  */
1955 static inline enum pdb_type_e
1956 cnstr_pdcp_c_plane_pdb(struct program *p,
1957                        uint32_t hfn,
1958                        enum pdcp_sn_size sn_size,
1959                        unsigned char bearer,
1960                        unsigned char direction,
1961                        uint32_t hfn_threshold,
1962                        struct alginfo *cipherdata,
1963                        struct alginfo *authdata)
1964 {
1965         struct pdcp_pdb pdb;
1966         enum pdb_type_e
1967                 pdb_mask[PDCP_CIPHER_TYPE_INVALID][PDCP_AUTH_TYPE_INVALID] = {
1968                         {       /* NULL */
1969                                 PDCP_PDB_TYPE_NO_PDB,           /* NULL */
1970                                 PDCP_PDB_TYPE_FULL_PDB,         /* SNOW f9 */
1971                                 PDCP_PDB_TYPE_FULL_PDB,         /* AES CMAC */
1972                                 PDCP_PDB_TYPE_FULL_PDB          /* ZUC-I */
1973                         },
1974                         {       /* SNOW f8 */
1975                                 PDCP_PDB_TYPE_FULL_PDB,         /* NULL */
1976                                 PDCP_PDB_TYPE_FULL_PDB,         /* SNOW f9 */
1977                                 PDCP_PDB_TYPE_REDUCED_PDB,      /* AES CMAC */
1978                                 PDCP_PDB_TYPE_REDUCED_PDB       /* ZUC-I */
1979                         },
1980                         {       /* AES CTR */
1981                                 PDCP_PDB_TYPE_FULL_PDB,         /* NULL */
1982                                 PDCP_PDB_TYPE_REDUCED_PDB,      /* SNOW f9 */
1983                                 PDCP_PDB_TYPE_FULL_PDB,         /* AES CMAC */
1984                                 PDCP_PDB_TYPE_REDUCED_PDB       /* ZUC-I */
1985                         },
1986                         {       /* ZUC-E */
1987                                 PDCP_PDB_TYPE_FULL_PDB,         /* NULL */
1988                                 PDCP_PDB_TYPE_REDUCED_PDB,      /* SNOW f9 */
1989                                 PDCP_PDB_TYPE_REDUCED_PDB,      /* AES CMAC */
1990                                 PDCP_PDB_TYPE_FULL_PDB          /* ZUC-I */
1991                         },
1992         };
1993
1994         if (rta_sec_era >= RTA_SEC_ERA_8) {
1995                 memset(&pdb, 0x00, sizeof(struct pdcp_pdb));
1996
1997                 /* To support 12-bit seq numbers, we use u-plane opt in pdb.
1998                  * SEC supports 5-bit only with c-plane opt in pdb.
1999                  */
2000                 if (sn_size == PDCP_SN_SIZE_12) {
2001                         pdb.hfn_res = hfn << PDCP_U_PLANE_PDB_LONG_SN_HFN_SHIFT;
2002                         pdb.bearer_dir_res = (uint32_t)
2003                                 ((bearer << PDCP_U_PLANE_PDB_BEARER_SHIFT) |
2004                                  (direction << PDCP_U_PLANE_PDB_DIR_SHIFT));
2005
2006                         pdb.hfn_thr_res =
2007                         hfn_threshold << PDCP_U_PLANE_PDB_LONG_SN_HFN_THR_SHIFT;
2008
2009                 } else {
2010                         /* This means 5-bit c-plane.
2011                          * Here we use c-plane opt in pdb
2012                          */
2013
2014                         /* This is a HW issue. Bit 2 should be set to zero,
2015                          * but it does not work this way. Override here.
2016                          */
2017                         pdb.opt_res.rsvd = 0x00000002;
2018
2019                         /* Copy relevant information from user to PDB */
2020                         pdb.hfn_res = hfn << PDCP_C_PLANE_PDB_HFN_SHIFT;
2021                         pdb.bearer_dir_res = (uint32_t)
2022                                 ((bearer << PDCP_C_PLANE_PDB_BEARER_SHIFT) |
2023                                 (direction << PDCP_C_PLANE_PDB_DIR_SHIFT));
2024                         pdb.hfn_thr_res =
2025                         hfn_threshold << PDCP_C_PLANE_PDB_HFN_THR_SHIFT;
2026                 }
2027
2028                 /* copy PDB in descriptor*/
2029                 __rta_out32(p, pdb.opt_res.opt);
2030                 __rta_out32(p, pdb.hfn_res);
2031                 __rta_out32(p, pdb.bearer_dir_res);
2032                 __rta_out32(p, pdb.hfn_thr_res);
2033
2034                 return PDCP_PDB_TYPE_FULL_PDB;
2035         }
2036
2037         switch (pdb_mask[cipherdata->algtype][authdata->algtype]) {
2038         case PDCP_PDB_TYPE_NO_PDB:
2039                 break;
2040
2041         case PDCP_PDB_TYPE_REDUCED_PDB:
2042                 __rta_out32(p, (hfn << PDCP_C_PLANE_PDB_HFN_SHIFT));
2043                 __rta_out32(p,
2044                             (uint32_t)((bearer <<
2045                                         PDCP_C_PLANE_PDB_BEARER_SHIFT) |
2046                                         (direction <<
2047                                          PDCP_C_PLANE_PDB_DIR_SHIFT)));
2048                 break;
2049
2050         case PDCP_PDB_TYPE_FULL_PDB:
2051                 memset(&pdb, 0x00, sizeof(struct pdcp_pdb));
2052
2053                 /* This is a HW issue. Bit 2 should be set to zero,
2054                  * but it does not work this way. Override here.
2055                  */
2056                 pdb.opt_res.rsvd = 0x00000002;
2057
2058                 /* Copy relevant information from user to PDB */
2059                 pdb.hfn_res = hfn << PDCP_C_PLANE_PDB_HFN_SHIFT;
2060                 pdb.bearer_dir_res = (uint32_t)
2061                         ((bearer << PDCP_C_PLANE_PDB_BEARER_SHIFT) |
2062                          (direction << PDCP_C_PLANE_PDB_DIR_SHIFT));
2063                 pdb.hfn_thr_res =
2064                         hfn_threshold << PDCP_C_PLANE_PDB_HFN_THR_SHIFT;
2065
2066                 /* copy PDB in descriptor*/
2067                 __rta_out32(p, pdb.opt_res.opt);
2068                 __rta_out32(p, pdb.hfn_res);
2069                 __rta_out32(p, pdb.bearer_dir_res);
2070                 __rta_out32(p, pdb.hfn_thr_res);
2071
2072                 break;
2073
2074         default:
2075                 return PDCP_PDB_TYPE_INVALID;
2076         }
2077
2078         return pdb_mask[cipherdata->algtype][authdata->algtype];
2079 }
2080
2081 /*
2082  * PDCP UPlane PDB creation function
2083  */
2084 static inline int
2085 cnstr_pdcp_u_plane_pdb(struct program *p,
2086                        enum pdcp_sn_size sn_size,
2087                        uint32_t hfn, unsigned short bearer,
2088                        unsigned short direction,
2089                        uint32_t hfn_threshold)
2090 {
2091         struct pdcp_pdb pdb;
2092         /* Read options from user */
2093         /* Depending on sequence number length, the HFN and HFN threshold
2094          * have different lengths.
2095          */
2096         memset(&pdb, 0x00, sizeof(struct pdcp_pdb));
2097
2098         switch (sn_size) {
2099         case PDCP_SN_SIZE_7:
2100                 pdb.opt_res.opt |= PDCP_U_PLANE_PDB_OPT_SHORT_SN;
2101                 pdb.hfn_res = hfn << PDCP_U_PLANE_PDB_SHORT_SN_HFN_SHIFT;
2102                 pdb.hfn_thr_res =
2103                         hfn_threshold<<PDCP_U_PLANE_PDB_SHORT_SN_HFN_THR_SHIFT;
2104                 break;
2105
2106         case PDCP_SN_SIZE_12:
2107                 pdb.opt_res.opt &= (uint32_t)(~PDCP_U_PLANE_PDB_OPT_SHORT_SN);
2108                 pdb.hfn_res = hfn << PDCP_U_PLANE_PDB_LONG_SN_HFN_SHIFT;
2109                 pdb.hfn_thr_res =
2110                         hfn_threshold<<PDCP_U_PLANE_PDB_LONG_SN_HFN_THR_SHIFT;
2111                 break;
2112
2113         case PDCP_SN_SIZE_15:
2114                 pdb.opt_res.opt = (uint32_t)(PDCP_U_PLANE_PDB_OPT_15B_SN);
2115                 pdb.hfn_res = hfn << PDCP_U_PLANE_PDB_15BIT_SN_HFN_SHIFT;
2116                 pdb.hfn_thr_res =
2117                         hfn_threshold<<PDCP_U_PLANE_PDB_15BIT_SN_HFN_THR_SHIFT;
2118                 break;
2119
2120         default:
2121                 pr_err("Invalid Sequence Number Size setting in PDB\n");
2122                 return -EINVAL;
2123         }
2124
2125         pdb.bearer_dir_res = (uint32_t)
2126                                 ((bearer << PDCP_U_PLANE_PDB_BEARER_SHIFT) |
2127                                  (direction << PDCP_U_PLANE_PDB_DIR_SHIFT));
2128
2129         /* copy PDB in descriptor*/
2130         __rta_out32(p, pdb.opt_res.opt);
2131         __rta_out32(p, pdb.hfn_res);
2132         __rta_out32(p, pdb.bearer_dir_res);
2133         __rta_out32(p, pdb.hfn_thr_res);
2134
2135         return 0;
2136 }
2137 /**
2138  * cnstr_shdsc_pdcp_c_plane_encap - Function for creating a PDCP Control Plane
2139  *                                  encapsulation descriptor.
2140  * @descbuf: pointer to buffer for descriptor construction
2141  * @ps: if 36/40bit addressing is desired, this parameter must be true
2142  * @swap: must be true when core endianness doesn't match SEC endianness
2143  * @hfn: starting Hyper Frame Number to be used together with the SN from the
2144  *       PDCP frames.
2145  * @sn_size: size of sequence numbers, only 5/12 bit sequence numbers are valid
2146  * @bearer: radio bearer ID
2147  * @direction: the direction of the PDCP frame (UL/DL)
2148  * @hfn_threshold: HFN value that once reached triggers a warning from SEC that
2149  *                 keys should be renegotiated at the earliest convenience.
2150  * @cipherdata: pointer to block cipher transform definitions
2151  *              Valid algorithm values are those from cipher_type_pdcp enum.
2152  * @authdata: pointer to authentication transform definitions
2153  *            Valid algorithm values are those from auth_type_pdcp enum.
2154  * @era_2_sw_hfn_ovrd: if software HFN override mechanism is desired for
2155  *                     this descriptor. Note: Can only be used for
2156  *                     SEC ERA 2.
2157  * Return: size of descriptor written in words or negative number on error.
2158  *         Once the function returns, the value of this parameter can be used
2159  *         for reclaiming the space that wasn't used for the descriptor.
2160  *
2161  * Note: descbuf must be large enough to contain a full 256 byte long
2162  * descriptor; after the function returns, by subtracting the actual number of
2163  * bytes used, the user can reuse the remaining buffer space for other purposes.
2164  */
2165 static inline int
2166 cnstr_shdsc_pdcp_c_plane_encap(uint32_t *descbuf,
2167                                bool ps,
2168                                bool swap,
2169                                uint32_t hfn,
2170                                enum pdcp_sn_size sn_size,
2171                                unsigned char bearer,
2172                                unsigned char direction,
2173                                uint32_t hfn_threshold,
2174                                struct alginfo *cipherdata,
2175                                struct alginfo *authdata,
2176                                unsigned char era_2_sw_hfn_ovrd)
2177 {
2178         static int
2179                 (*pdcp_cp_fp[PDCP_CIPHER_TYPE_INVALID][PDCP_AUTH_TYPE_INVALID])
2180                         (struct program*, bool swap, struct alginfo *,
2181                          struct alginfo *, unsigned int, enum pdcp_sn_size,
2182                         unsigned char __maybe_unused) = {
2183                 {       /* NULL */
2184                         pdcp_insert_cplane_null_op,     /* NULL */
2185                         pdcp_insert_cplane_int_only_op, /* SNOW f9 */
2186                         pdcp_insert_cplane_int_only_op, /* AES CMAC */
2187                         pdcp_insert_cplane_int_only_op  /* ZUC-I */
2188                 },
2189                 {       /* SNOW f8 */
2190                         pdcp_insert_cplane_enc_only_op, /* NULL */
2191                         pdcp_insert_cplane_acc_op,      /* SNOW f9 */
2192                         pdcp_insert_cplane_snow_aes_op, /* AES CMAC */
2193                         pdcp_insert_cplane_snow_zuc_op  /* ZUC-I */
2194                 },
2195                 {       /* AES CTR */
2196                         pdcp_insert_cplane_enc_only_op, /* NULL */
2197                         pdcp_insert_cplane_aes_snow_op, /* SNOW f9 */
2198                         pdcp_insert_cplane_acc_op,      /* AES CMAC */
2199                         pdcp_insert_cplane_aes_zuc_op   /* ZUC-I */
2200                 },
2201                 {       /* ZUC-E */
2202                         pdcp_insert_cplane_enc_only_op, /* NULL */
2203                         pdcp_insert_cplane_zuc_snow_op, /* SNOW f9 */
2204                         pdcp_insert_cplane_zuc_aes_op,  /* AES CMAC */
2205                         pdcp_insert_cplane_acc_op       /* ZUC-I */
2206                 },
2207         };
2208         static enum rta_share_type
2209                 desc_share[PDCP_CIPHER_TYPE_INVALID][PDCP_AUTH_TYPE_INVALID] = {
2210                 {       /* NULL */
2211                         SHR_WAIT,       /* NULL */
2212                         SHR_ALWAYS,     /* SNOW f9 */
2213                         SHR_ALWAYS,     /* AES CMAC */
2214                         SHR_ALWAYS      /* ZUC-I */
2215                 },
2216                 {       /* SNOW f8 */
2217                         SHR_ALWAYS,     /* NULL */
2218                         SHR_ALWAYS,     /* SNOW f9 */
2219                         SHR_WAIT,       /* AES CMAC */
2220                         SHR_WAIT        /* ZUC-I */
2221                 },
2222                 {       /* AES CTR */
2223                         SHR_ALWAYS,     /* NULL */
2224                         SHR_ALWAYS,     /* SNOW f9 */
2225                         SHR_ALWAYS,     /* AES CMAC */
2226                         SHR_WAIT        /* ZUC-I */
2227                 },
2228                 {       /* ZUC-E */
2229                         SHR_ALWAYS,     /* NULL */
2230                         SHR_WAIT,       /* SNOW f9 */
2231                         SHR_WAIT,       /* AES CMAC */
2232                         SHR_ALWAYS      /* ZUC-I */
2233                 },
2234         };
2235         enum pdb_type_e pdb_type;
2236         struct program prg;
2237         struct program *p = &prg;
2238         int err;
2239         LABEL(pdb_end);
2240
2241         if (rta_sec_era != RTA_SEC_ERA_2 && era_2_sw_hfn_ovrd) {
2242                 pr_err("Cannot select SW HFN override for other era than 2");
2243                 return -EINVAL;
2244         }
2245
2246         if (sn_size != PDCP_SN_SIZE_12 && sn_size != PDCP_SN_SIZE_5) {
2247                 pr_err("C-plane supports only 5-bit and 12-bit sequence numbers\n");
2248                 return -EINVAL;
2249         }
2250
2251         PROGRAM_CNTXT_INIT(p, descbuf, 0);
2252         if (swap)
2253                 PROGRAM_SET_BSWAP(p);
2254         if (ps)
2255                 PROGRAM_SET_36BIT_ADDR(p);
2256
2257         SHR_HDR(p, desc_share[cipherdata->algtype][authdata->algtype], 0, 0);
2258
2259         pdb_type = cnstr_pdcp_c_plane_pdb(p,
2260                         hfn,
2261                         sn_size,
2262                         bearer,
2263                         direction,
2264                         hfn_threshold,
2265                         cipherdata,
2266                         authdata);
2267
2268         SET_LABEL(p, pdb_end);
2269
2270         err = insert_hfn_ov_op(p, sn_size, pdb_type,
2271                                era_2_sw_hfn_ovrd);
2272         if (err)
2273                 return err;
2274
2275         err = pdcp_cp_fp[cipherdata->algtype][authdata->algtype](p,
2276                 swap,
2277                 cipherdata,
2278                 authdata,
2279                 OP_TYPE_ENCAP_PROTOCOL,
2280                 sn_size,
2281                 era_2_sw_hfn_ovrd);
2282         if (err)
2283                 return err;
2284
2285         PATCH_HDR(p, 0, pdb_end);
2286
2287         return PROGRAM_FINALIZE(p);
2288 }
2289
2290 /**
2291  * cnstr_shdsc_pdcp_c_plane_decap - Function for creating a PDCP Control Plane
2292  *                                  decapsulation descriptor.
2293  * @descbuf: pointer to buffer for descriptor construction
2294  * @ps: if 36/40bit addressing is desired, this parameter must be true
2295  * @swap: must be true when core endianness doesn't match SEC endianness
2296  * @hfn: starting Hyper Frame Number to be used together with the SN from the
2297  *       PDCP frames.
2298  * @sn_size: size of sequence numbers, only 5/12 bit sequence numbers are valid
2299  * @bearer: radio bearer ID
2300  * @direction: the direction of the PDCP frame (UL/DL)
2301  * @hfn_threshold: HFN value that once reached triggers a warning from SEC that
2302  *                 keys should be renegotiated at the earliest convenience.
2303  * @cipherdata: pointer to block cipher transform definitions
2304  *              Valid algorithm values are those from cipher_type_pdcp enum.
2305  * @authdata: pointer to authentication transform definitions
2306  *            Valid algorithm values are those from auth_type_pdcp enum.
2307  * @era_2_sw_hfn_ovrd: if software HFN override mechanism is desired for
2308  *                     this descriptor. Note: Can only be used for
2309  *                     SEC ERA 2.
2310  *
2311  * Return: size of descriptor written in words or negative number on error.
2312  *         Once the function returns, the value of this parameter can be used
2313  *         for reclaiming the space that wasn't used for the descriptor.
2314  *
2315  * Note: descbuf must be large enough to contain a full 256 byte long
2316  * descriptor; after the function returns, by subtracting the actual number of
2317  * bytes used, the user can reuse the remaining buffer space for other purposes.
2318  */
2319 static inline int
2320 cnstr_shdsc_pdcp_c_plane_decap(uint32_t *descbuf,
2321                                bool ps,
2322                                bool swap,
2323                                uint32_t hfn,
2324                                enum pdcp_sn_size sn_size,
2325                                unsigned char bearer,
2326                                unsigned char direction,
2327                                uint32_t hfn_threshold,
2328                                struct alginfo *cipherdata,
2329                                struct alginfo *authdata,
2330                                unsigned char era_2_sw_hfn_ovrd)
2331 {
2332         static int
2333                 (*pdcp_cp_fp[PDCP_CIPHER_TYPE_INVALID][PDCP_AUTH_TYPE_INVALID])
2334                         (struct program*, bool swap, struct alginfo *,
2335                          struct alginfo *, unsigned int, enum pdcp_sn_size,
2336                          unsigned char) = {
2337                 {       /* NULL */
2338                         pdcp_insert_cplane_null_op,     /* NULL */
2339                         pdcp_insert_cplane_int_only_op, /* SNOW f9 */
2340                         pdcp_insert_cplane_int_only_op, /* AES CMAC */
2341                         pdcp_insert_cplane_int_only_op  /* ZUC-I */
2342                 },
2343                 {       /* SNOW f8 */
2344                         pdcp_insert_cplane_enc_only_op, /* NULL */
2345                         pdcp_insert_cplane_acc_op,      /* SNOW f9 */
2346                         pdcp_insert_cplane_snow_aes_op, /* AES CMAC */
2347                         pdcp_insert_cplane_snow_zuc_op  /* ZUC-I */
2348                 },
2349                 {       /* AES CTR */
2350                         pdcp_insert_cplane_enc_only_op, /* NULL */
2351                         pdcp_insert_cplane_aes_snow_op, /* SNOW f9 */
2352                         pdcp_insert_cplane_acc_op,      /* AES CMAC */
2353                         pdcp_insert_cplane_aes_zuc_op   /* ZUC-I */
2354                 },
2355                 {       /* ZUC-E */
2356                         pdcp_insert_cplane_enc_only_op, /* NULL */
2357                         pdcp_insert_cplane_zuc_snow_op, /* SNOW f9 */
2358                         pdcp_insert_cplane_zuc_aes_op,  /* AES CMAC */
2359                         pdcp_insert_cplane_acc_op       /* ZUC-I */
2360                 },
2361         };
2362         static enum rta_share_type
2363                 desc_share[PDCP_CIPHER_TYPE_INVALID][PDCP_AUTH_TYPE_INVALID] = {
2364                 {       /* NULL */
2365                         SHR_WAIT,       /* NULL */
2366                         SHR_ALWAYS,     /* SNOW f9 */
2367                         SHR_ALWAYS,     /* AES CMAC */
2368                         SHR_ALWAYS      /* ZUC-I */
2369                 },
2370                 {       /* SNOW f8 */
2371                         SHR_ALWAYS,     /* NULL */
2372                         SHR_ALWAYS,     /* SNOW f9 */
2373                         SHR_WAIT,       /* AES CMAC */
2374                         SHR_WAIT        /* ZUC-I */
2375                 },
2376                 {       /* AES CTR */
2377                         SHR_ALWAYS,     /* NULL */
2378                         SHR_ALWAYS,     /* SNOW f9 */
2379                         SHR_ALWAYS,     /* AES CMAC */
2380                         SHR_WAIT        /* ZUC-I */
2381                 },
2382                 {       /* ZUC-E */
2383                         SHR_ALWAYS,     /* NULL */
2384                         SHR_WAIT,       /* SNOW f9 */
2385                         SHR_WAIT,       /* AES CMAC */
2386                         SHR_ALWAYS      /* ZUC-I */
2387                 },
2388         };
2389         enum pdb_type_e pdb_type;
2390         struct program prg;
2391         struct program *p = &prg;
2392         int err;
2393         LABEL(pdb_end);
2394
2395         if (rta_sec_era != RTA_SEC_ERA_2 && era_2_sw_hfn_ovrd) {
2396                 pr_err("Cannot select SW HFN override for other era than 2");
2397                 return -EINVAL;
2398         }
2399
2400         if (sn_size != PDCP_SN_SIZE_12 && sn_size != PDCP_SN_SIZE_5) {
2401                 pr_err("C-plane supports only 5-bit and 12-bit sequence numbers\n");
2402                 return -EINVAL;
2403         }
2404
2405         PROGRAM_CNTXT_INIT(p, descbuf, 0);
2406         if (swap)
2407                 PROGRAM_SET_BSWAP(p);
2408         if (ps)
2409                 PROGRAM_SET_36BIT_ADDR(p);
2410
2411         SHR_HDR(p, desc_share[cipherdata->algtype][authdata->algtype], 0, 0);
2412
2413         pdb_type = cnstr_pdcp_c_plane_pdb(p,
2414                         hfn,
2415                         sn_size,
2416                         bearer,
2417                         direction,
2418                         hfn_threshold,
2419                         cipherdata,
2420                         authdata);
2421
2422         SET_LABEL(p, pdb_end);
2423
2424         err = insert_hfn_ov_op(p, sn_size, pdb_type,
2425                                era_2_sw_hfn_ovrd);
2426         if (err)
2427                 return err;
2428
2429         err = pdcp_cp_fp[cipherdata->algtype][authdata->algtype](p,
2430                 swap,
2431                 cipherdata,
2432                 authdata,
2433                 OP_TYPE_DECAP_PROTOCOL,
2434                 sn_size,
2435                 era_2_sw_hfn_ovrd);
2436         if (err)
2437                 return err;
2438
2439         PATCH_HDR(p, 0, pdb_end);
2440
2441         return PROGRAM_FINALIZE(p);
2442 }
2443
2444 /**
2445  * cnstr_shdsc_pdcp_u_plane_encap - Function for creating a PDCP User Plane
2446  *                                  encapsulation descriptor.
2447  * @descbuf: pointer to buffer for descriptor construction
2448  * @ps: if 36/40bit addressing is desired, this parameter must be true
2449  * @swap: must be true when core endianness doesn't match SEC endianness
2450  * @sn_size: selects Sequence Number Size: 7/12/15 bits
2451  * @hfn: starting Hyper Frame Number to be used together with the SN from the
2452  *       PDCP frames.
2453  * @bearer: radio bearer ID
2454  * @direction: the direction of the PDCP frame (UL/DL)
2455  * @hfn_threshold: HFN value that once reached triggers a warning from SEC that
2456  *                 keys should be renegotiated at the earliest convenience.
2457  * @cipherdata: pointer to block cipher transform definitions
2458  *              Valid algorithm values are those from cipher_type_pdcp enum.
2459  * @era_2_sw_hfn_ovrd: if software HFN override mechanism is desired for
2460  *                     this descriptor. Note: Can only be used for
2461  *                     SEC ERA 2.
2462  *
2463  * Return: size of descriptor written in words or negative number on error.
2464  *         Once the function returns, the value of this parameter can be used
2465  *         for reclaiming the space that wasn't used for the descriptor.
2466  *
2467  * Note: descbuf must be large enough to contain a full 256 byte long
2468  * descriptor; after the function returns, by subtracting the actual number of
2469  * bytes used, the user can reuse the remaining buffer space for other purposes.
2470  */
2471 static inline int
2472 cnstr_shdsc_pdcp_u_plane_encap(uint32_t *descbuf,
2473                                bool ps,
2474                                bool swap,
2475                                enum pdcp_sn_size sn_size,
2476                                uint32_t hfn,
2477                                unsigned short bearer,
2478                                unsigned short direction,
2479                                uint32_t hfn_threshold,
2480                                struct alginfo *cipherdata,
2481                                unsigned char era_2_sw_hfn_ovrd)
2482 {
2483         struct program prg;
2484         struct program *p = &prg;
2485         int err;
2486         LABEL(pdb_end);
2487
2488         if (rta_sec_era != RTA_SEC_ERA_2 && era_2_sw_hfn_ovrd) {
2489                 pr_err("Cannot select SW HFN ovrd for other era than 2");
2490                 return -EINVAL;
2491         }
2492
2493         PROGRAM_CNTXT_INIT(p, descbuf, 0);
2494         if (swap)
2495                 PROGRAM_SET_BSWAP(p);
2496         if (ps)
2497                 PROGRAM_SET_36BIT_ADDR(p);
2498
2499         SHR_HDR(p, SHR_ALWAYS, 0, 0);
2500         if (cnstr_pdcp_u_plane_pdb(p, sn_size, hfn, bearer, direction,
2501                                    hfn_threshold)) {
2502                 pr_err("Error creating PDCP UPlane PDB\n");
2503                 return -EINVAL;
2504         }
2505         SET_LABEL(p, pdb_end);
2506
2507         err = insert_hfn_ov_op(p, sn_size, PDCP_PDB_TYPE_FULL_PDB,
2508                                era_2_sw_hfn_ovrd);
2509         if (err)
2510                 return err;
2511
2512         switch (sn_size) {
2513         case PDCP_SN_SIZE_7:
2514         case PDCP_SN_SIZE_12:
2515                 switch (cipherdata->algtype) {
2516                 case PDCP_CIPHER_TYPE_ZUC:
2517                         if (rta_sec_era < RTA_SEC_ERA_5) {
2518                                 pr_err("Invalid era for selected algorithm\n");
2519                                 return -ENOTSUP;
2520                         }
2521                 case PDCP_CIPHER_TYPE_AES:
2522                 case PDCP_CIPHER_TYPE_SNOW:
2523                         /* Insert Cipher Key */
2524                         KEY(p, KEY1, cipherdata->key_enc_flags,
2525                             (uint64_t)cipherdata->key, cipherdata->keylen,
2526                             INLINE_KEY(cipherdata));
2527                         PROTOCOL(p, OP_TYPE_ENCAP_PROTOCOL,
2528                                  OP_PCLID_LTE_PDCP_USER,
2529                                  (uint16_t)cipherdata->algtype);
2530                         break;
2531                 case PDCP_CIPHER_TYPE_NULL:
2532                         insert_copy_frame_op(p,
2533                                              cipherdata,
2534                                              OP_TYPE_ENCAP_PROTOCOL);
2535                         break;
2536                 default:
2537                         pr_err("%s: Invalid encrypt algorithm selected: %d\n",
2538                                "cnstr_pcl_shdsc_pdcp_u_plane_decap",
2539                                cipherdata->algtype);
2540                         return -EINVAL;
2541                 }
2542                 break;
2543
2544         case PDCP_SN_SIZE_15:
2545                 switch (cipherdata->algtype) {
2546                 case PDCP_CIPHER_TYPE_NULL:
2547                         insert_copy_frame_op(p,
2548                                              cipherdata,
2549                                              OP_TYPE_ENCAP_PROTOCOL);
2550                         break;
2551
2552                 default:
2553                         err = pdcp_insert_uplane_15bit_op(p, swap, cipherdata,
2554                                 OP_TYPE_ENCAP_PROTOCOL);
2555                         if (err)
2556                                 return err;
2557                         break;
2558                 }
2559                 break;
2560
2561         case PDCP_SN_SIZE_5:
2562         default:
2563                 pr_err("Invalid SN size selected\n");
2564                 return -ENOTSUP;
2565         }
2566
2567         PATCH_HDR(p, 0, pdb_end);
2568         return PROGRAM_FINALIZE(p);
2569 }
2570
2571 /**
2572  * cnstr_shdsc_pdcp_u_plane_decap - Function for creating a PDCP User Plane
2573  *                                  decapsulation descriptor.
2574  * @descbuf: pointer to buffer for descriptor construction
2575  * @ps: if 36/40bit addressing is desired, this parameter must be true
2576  * @swap: must be true when core endianness doesn't match SEC endianness
2577  * @sn_size: selects Sequence Number Size: 7/12/15 bits
2578  * @hfn: starting Hyper Frame Number to be used together with the SN from the
2579  *       PDCP frames.
2580  * @bearer: radio bearer ID
2581  * @direction: the direction of the PDCP frame (UL/DL)
2582  * @hfn_threshold: HFN value that once reached triggers a warning from SEC that
2583  *                 keys should be renegotiated at the earliest convenience.
2584  * @cipherdata: pointer to block cipher transform definitions
2585  *              Valid algorithm values are those from cipher_type_pdcp enum.
2586  * @era_2_sw_hfn_ovrd: if software HFN override mechanism is desired for
2587  *                     this descriptor. Note: Can only be used for
2588  *                     SEC ERA 2.
2589  *
2590  * Return: size of descriptor written in words or negative number on error.
2591  *         Once the function returns, the value of this parameter can be used
2592  *         for reclaiming the space that wasn't used for the descriptor.
2593  *
2594  * Note: descbuf must be large enough to contain a full 256 byte long
2595  * descriptor; after the function returns, by subtracting the actual number of
2596  * bytes used, the user can reuse the remaining buffer space for other purposes.
2597  */
2598 static inline int
2599 cnstr_shdsc_pdcp_u_plane_decap(uint32_t *descbuf,
2600                                bool ps,
2601                                bool swap,
2602                                enum pdcp_sn_size sn_size,
2603                                uint32_t hfn,
2604                                unsigned short bearer,
2605                                unsigned short direction,
2606                                uint32_t hfn_threshold,
2607                                struct alginfo *cipherdata,
2608                                unsigned char era_2_sw_hfn_ovrd)
2609 {
2610         struct program prg;
2611         struct program *p = &prg;
2612         int err;
2613         LABEL(pdb_end);
2614
2615         if (rta_sec_era != RTA_SEC_ERA_2 && era_2_sw_hfn_ovrd) {
2616                 pr_err("Cannot select SW HFN override for other era than 2");
2617                 return -EINVAL;
2618         }
2619
2620         PROGRAM_CNTXT_INIT(p, descbuf, 0);
2621         if (swap)
2622                 PROGRAM_SET_BSWAP(p);
2623         if (ps)
2624                 PROGRAM_SET_36BIT_ADDR(p);
2625
2626         SHR_HDR(p, SHR_ALWAYS, 0, 0);
2627         if (cnstr_pdcp_u_plane_pdb(p, sn_size, hfn, bearer, direction,
2628                                    hfn_threshold)) {
2629                 pr_err("Error creating PDCP UPlane PDB\n");
2630                 return -EINVAL;
2631         }
2632         SET_LABEL(p, pdb_end);
2633
2634         err = insert_hfn_ov_op(p, sn_size, PDCP_PDB_TYPE_FULL_PDB,
2635                                era_2_sw_hfn_ovrd);
2636         if (err)
2637                 return err;
2638
2639         switch (sn_size) {
2640         case PDCP_SN_SIZE_7:
2641         case PDCP_SN_SIZE_12:
2642                 switch (cipherdata->algtype) {
2643                 case PDCP_CIPHER_TYPE_ZUC:
2644                         if (rta_sec_era < RTA_SEC_ERA_5) {
2645                                 pr_err("Invalid era for selected algorithm\n");
2646                                 return -ENOTSUP;
2647                         }
2648                 case PDCP_CIPHER_TYPE_AES:
2649                 case PDCP_CIPHER_TYPE_SNOW:
2650                         /* Insert Cipher Key */
2651                         KEY(p, KEY1, cipherdata->key_enc_flags,
2652                             cipherdata->key, cipherdata->keylen,
2653                             INLINE_KEY(cipherdata));
2654                         PROTOCOL(p, OP_TYPE_DECAP_PROTOCOL,
2655                                  OP_PCLID_LTE_PDCP_USER,
2656                                  (uint16_t)cipherdata->algtype);
2657                         break;
2658                 case PDCP_CIPHER_TYPE_NULL:
2659                         insert_copy_frame_op(p,
2660                                              cipherdata,
2661                                              OP_TYPE_DECAP_PROTOCOL);
2662                         break;
2663                 default:
2664                         pr_err("%s: Invalid encrypt algorithm selected: %d\n",
2665                                "cnstr_pcl_shdsc_pdcp_u_plane_decap",
2666                                cipherdata->algtype);
2667                         return -EINVAL;
2668                 }
2669                 break;
2670
2671         case PDCP_SN_SIZE_15:
2672                 switch (cipherdata->algtype) {
2673                 case PDCP_CIPHER_TYPE_NULL:
2674                         insert_copy_frame_op(p,
2675                                              cipherdata,
2676                                              OP_TYPE_DECAP_PROTOCOL);
2677                         break;
2678
2679                 default:
2680                         err = pdcp_insert_uplane_15bit_op(p, swap, cipherdata,
2681                                 OP_TYPE_DECAP_PROTOCOL);
2682                         if (err)
2683                                 return err;
2684                         break;
2685                 }
2686                 break;
2687
2688         case PDCP_SN_SIZE_5:
2689         default:
2690                 pr_err("Invalid SN size selected\n");
2691                 return -ENOTSUP;
2692         }
2693
2694         PATCH_HDR(p, 0, pdb_end);
2695         return PROGRAM_FINALIZE(p);
2696 }
2697
2698 /**
2699  * cnstr_shdsc_pdcp_short_mac - Function for creating a PDCP Short MAC
2700  *                              descriptor.
2701  * @descbuf: pointer to buffer for descriptor construction
2702  * @ps: if 36/40bit addressing is desired, this parameter must be true
2703  * @swap: must be true when core endianness doesn't match SEC endianness
2704  * @authdata: pointer to authentication transform definitions
2705  *            Valid algorithm values are those from auth_type_pdcp enum.
2706  *
2707  * Return: size of descriptor written in words or negative number on error.
2708  *         Once the function returns, the value of this parameter can be used
2709  *         for reclaiming the space that wasn't used for the descriptor.
2710  *
2711  * Note: descbuf must be large enough to contain a full 256 byte long
2712  * descriptor; after the function returns, by subtracting the actual number of
2713  * bytes used, the user can reuse the remaining buffer space for other purposes.
2714  */
2715 static inline int
2716 cnstr_shdsc_pdcp_short_mac(uint32_t *descbuf,
2717                            bool ps,
2718                            bool swap,
2719                            struct alginfo *authdata)
2720 {
2721         struct program prg;
2722         struct program *p = &prg;
2723         uint32_t iv[3] = {0, 0, 0};
2724         LABEL(local_offset);
2725         REFERENCE(move_cmd_read_descbuf);
2726         REFERENCE(move_cmd_write_descbuf);
2727
2728         PROGRAM_CNTXT_INIT(p, descbuf, 0);
2729         if (swap)
2730                 PROGRAM_SET_BSWAP(p);
2731         if (ps)
2732                 PROGRAM_SET_36BIT_ADDR(p);
2733
2734         SHR_HDR(p, SHR_ALWAYS, 1, 0);
2735
2736         if (rta_sec_era > RTA_SEC_ERA_2) {
2737                 MATHB(p, SEQINSZ, SUB, ZERO, VSEQINSZ, 4, 0);
2738                 MATHB(p, SEQINSZ, SUB, ZERO, MATH1, 4, 0);
2739         } else {
2740                 MATHB(p, SEQINSZ, ADD, ONE, MATH1, 4, 0);
2741                 MATHB(p, MATH1, SUB, ONE, MATH1, 4, 0);
2742                 MATHB(p, ZERO, ADD, MATH1, VSEQINSZ, 4, 0);
2743                 MOVE(p, MATH1, 0, MATH0, 0, 8, IMMED);
2744
2745                 /*
2746                  * Since MOVELEN is available only starting with
2747                  * SEC ERA 3, use poor man's MOVELEN: create a MOVE
2748                  * command dynamically by writing the length from M1 by
2749                  * OR-ing the command in the M1 register and MOVE the
2750                  * result into the descriptor buffer. Care must be taken
2751                  * wrt. the location of the command because of SEC
2752                  * pipelining. The actual MOVEs are written at the end
2753                  * of the descriptor due to calculations needed on the
2754                  * offset in the descriptor for the MOVE command.
2755                  */
2756                 move_cmd_read_descbuf = MOVE(p, DESCBUF, 0, MATH0, 0, 6,
2757                                              IMMED);
2758                 move_cmd_write_descbuf = MOVE(p, MATH0, 0, DESCBUF, 0, 8,
2759                                               WAITCOMP | IMMED);
2760         }
2761         MATHB(p, ZERO, ADD, MATH1, VSEQOUTSZ, 4, 0);
2762
2763         switch (authdata->algtype) {
2764         case PDCP_AUTH_TYPE_NULL:
2765                 SEQFIFOSTORE(p, MSG, 0, 0, VLF);
2766                 if (rta_sec_era > RTA_SEC_ERA_2) {
2767                         MOVE(p, AB1, 0, OFIFO, 0, MATH1, 0);
2768                 } else {
2769                         SET_LABEL(p, local_offset);
2770
2771                         /* Shut off automatic Info FIFO entries */
2772                         LOAD(p, 0, DCTRL, LDOFF_DISABLE_AUTO_NFIFO, 0, IMMED);
2773
2774                         /* Placeholder for MOVE command with length from M1
2775                          * register
2776                          */
2777                         MOVE(p, IFIFOAB1, 0, OFIFO, 0, 0, IMMED);
2778
2779                         /* Enable automatic Info FIFO entries */
2780                         LOAD(p, 0, DCTRL, LDOFF_ENABLE_AUTO_NFIFO, 0, IMMED);
2781                 }
2782
2783                 LOAD(p, (uintptr_t)iv, MATH0, 0, 8, IMMED | COPY);
2784                 SEQFIFOLOAD(p, MSG1, 0, VLF | LAST1 | LAST2 | FLUSH1);
2785                 SEQSTORE(p, MATH0, 0, 4, 0);
2786
2787                 break;
2788
2789         case PDCP_AUTH_TYPE_SNOW:
2790                 iv[0] = 0xFFFFFFFF;
2791                 iv[1] = swap ? swab32(0x04000000) : 0x04000000;
2792                 iv[2] = swap ? swab32(0xF8000000) : 0xF8000000;
2793
2794                 KEY(p, KEY2, authdata->key_enc_flags, authdata->key,
2795                     authdata->keylen, INLINE_KEY(authdata));
2796                 LOAD(p, (uintptr_t)&iv, CONTEXT2, 0, 12, IMMED | COPY);
2797                 ALG_OPERATION(p, OP_ALG_ALGSEL_SNOW_F9,
2798                               OP_ALG_AAI_F9,
2799                               OP_ALG_AS_INITFINAL,
2800                               ICV_CHECK_DISABLE,
2801                               DIR_ENC);
2802                 SEQFIFOSTORE(p, MSG, 0, 0, VLF);
2803
2804                 if (rta_sec_era > RTA_SEC_ERA_2) {
2805                         MOVE(p, AB1, 0, OFIFO, 0, MATH1, 0);
2806                 } else {
2807                         SET_LABEL(p, local_offset);
2808
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                 SEQFIFOLOAD(p, MSGINSNOOP, 0, VLF | LAST1 | LAST2 | FLUSH1);
2822                 SEQSTORE(p, CONTEXT2, 0, 4, 0);
2823
2824                 break;
2825
2826         case PDCP_AUTH_TYPE_AES:
2827                 iv[0] = 0xFFFFFFFF;
2828                 iv[1] = swap ? swab32(0xFC000000) : 0xFC000000;
2829                 iv[2] = 0x00000000; /* unused */
2830
2831                 KEY(p, KEY1, authdata->key_enc_flags, authdata->key,
2832                     authdata->keylen, INLINE_KEY(authdata));
2833                 LOAD(p, (uintptr_t)&iv, MATH0, 0, 8, IMMED | COPY);
2834                 MOVE(p, MATH0, 0, IFIFOAB1, 0, 8, IMMED);
2835                 ALG_OPERATION(p, OP_ALG_ALGSEL_AES,
2836                               OP_ALG_AAI_CMAC,
2837                               OP_ALG_AS_INITFINAL,
2838                               ICV_CHECK_DISABLE,
2839                               DIR_ENC);
2840                 SEQFIFOSTORE(p, MSG, 0, 0, VLF);
2841
2842                 if (rta_sec_era > RTA_SEC_ERA_2) {
2843                         MOVE(p, AB2, 0, OFIFO, 0, MATH1, 0);
2844                 } else {
2845                         SET_LABEL(p, local_offset);
2846
2847                         /* Shut off automatic Info FIFO entries */
2848                         LOAD(p, 0, DCTRL, LDOFF_DISABLE_AUTO_NFIFO, 0, IMMED);
2849
2850                         /* Placeholder for MOVE command with length from M1
2851                          * register
2852                          */
2853                         MOVE(p, IFIFOAB2, 0, OFIFO, 0, 0, IMMED);
2854
2855                         /* Enable automatic Info FIFO entries */
2856                         LOAD(p, 0, DCTRL, LDOFF_ENABLE_AUTO_NFIFO, 0, IMMED);
2857                 }
2858                 SEQFIFOLOAD(p, MSGINSNOOP, 0, VLF | LAST1 | LAST2 | FLUSH1);
2859                 SEQSTORE(p, CONTEXT1, 0, 4, 0);
2860
2861                 break;
2862
2863         case PDCP_AUTH_TYPE_ZUC:
2864                 if (rta_sec_era < RTA_SEC_ERA_5) {
2865                         pr_err("Invalid era for selected algorithm\n");
2866                         return -ENOTSUP;
2867                 }
2868                 iv[0] = 0xFFFFFFFF;
2869                 iv[1] = swap ? swab32(0xFC000000) : 0xFC000000;
2870                 iv[2] = 0x00000000; /* unused */
2871
2872                 KEY(p, KEY2, authdata->key_enc_flags, authdata->key,
2873                     authdata->keylen, INLINE_KEY(authdata));
2874                 LOAD(p, (uintptr_t)&iv, CONTEXT2, 0, 12, IMMED | COPY);
2875                 ALG_OPERATION(p, OP_ALG_ALGSEL_ZUCA,
2876                               OP_ALG_AAI_F9,
2877                               OP_ALG_AS_INITFINAL,
2878                               ICV_CHECK_DISABLE,
2879                               DIR_ENC);
2880                 SEQFIFOSTORE(p, MSG, 0, 0, VLF);
2881                 MOVE(p, AB1, 0, OFIFO, 0, MATH1, 0);
2882                 SEQFIFOLOAD(p, MSGINSNOOP, 0, VLF | LAST1 | LAST2 | FLUSH1);
2883                 SEQSTORE(p, CONTEXT2, 0, 4, 0);
2884
2885                 break;
2886
2887         default:
2888                 pr_err("%s: Invalid integrity algorithm selected: %d\n",
2889                        "cnstr_shdsc_pdcp_short_mac", authdata->algtype);
2890                 return -EINVAL;
2891         }
2892
2893
2894         if (rta_sec_era < RTA_SEC_ERA_3) {
2895                 PATCH_MOVE(p, move_cmd_read_descbuf, local_offset);
2896                 PATCH_MOVE(p, move_cmd_write_descbuf, local_offset);
2897         }
2898
2899         return PROGRAM_FINALIZE(p);
2900 }
2901
2902 #endif /* __DESC_PDCP_H__ */