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