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