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