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