uboot/arch/mips/mach-octeon/include/mach/cvmx-wqe.h
<<
>>
Prefs
   1/* SPDX-License-Identifier: GPL-2.0 */
   2/*
   3 * Copyright (C) 2020 Marvell International Ltd.
   4 *
   5 * This header file defines the work queue entry (wqe) data structure.
   6 * Since this is a commonly used structure that depends on structures
   7 * from several hardware blocks, those definitions have been placed
   8 * in this file to create a single point of definition of the wqe
   9 * format.
  10 * Data structures are still named according to the block that they
  11 * relate to.
  12 */
  13
  14#ifndef __CVMX_WQE_H__
  15#define __CVMX_WQE_H__
  16
  17#include "cvmx-packet.h"
  18#include "cvmx-csr-enums.h"
  19#include "cvmx-pki-defs.h"
  20#include "cvmx-pip-defs.h"
  21#include "octeon-feature.h"
  22
  23#define OCT_TAG_TYPE_STRING(x)                                          \
  24        (((x) == CVMX_POW_TAG_TYPE_ORDERED) ?                           \
  25         "ORDERED" :                                                    \
  26         (((x) == CVMX_POW_TAG_TYPE_ATOMIC) ?                           \
  27          "ATOMIC" :                                                    \
  28          (((x) == CVMX_POW_TAG_TYPE_NULL) ? "NULL" : "NULL_NULL")))
  29
  30/* Error levels in WQE WORD2 (ERRLEV).*/
  31#define PKI_ERRLEV_E__RE_M 0x0
  32#define PKI_ERRLEV_E__LA_M 0x1
  33#define PKI_ERRLEV_E__LB_M 0x2
  34#define PKI_ERRLEV_E__LC_M 0x3
  35#define PKI_ERRLEV_E__LD_M 0x4
  36#define PKI_ERRLEV_E__LE_M 0x5
  37#define PKI_ERRLEV_E__LF_M 0x6
  38#define PKI_ERRLEV_E__LG_M 0x7
  39
  40enum cvmx_pki_errlevel {
  41        CVMX_PKI_ERRLEV_E_RE = PKI_ERRLEV_E__RE_M,
  42        CVMX_PKI_ERRLEV_E_LA = PKI_ERRLEV_E__LA_M,
  43        CVMX_PKI_ERRLEV_E_LB = PKI_ERRLEV_E__LB_M,
  44        CVMX_PKI_ERRLEV_E_LC = PKI_ERRLEV_E__LC_M,
  45        CVMX_PKI_ERRLEV_E_LD = PKI_ERRLEV_E__LD_M,
  46        CVMX_PKI_ERRLEV_E_LE = PKI_ERRLEV_E__LE_M,
  47        CVMX_PKI_ERRLEV_E_LF = PKI_ERRLEV_E__LF_M,
  48        CVMX_PKI_ERRLEV_E_LG = PKI_ERRLEV_E__LG_M
  49};
  50
  51#define CVMX_PKI_ERRLEV_MAX BIT(3) /* The size of WORD2:ERRLEV field.*/
  52
  53/* Error code in WQE WORD2 (OPCODE).*/
  54#define CVMX_PKI_OPCODE_RE_NONE       0x0
  55#define CVMX_PKI_OPCODE_RE_PARTIAL    0x1
  56#define CVMX_PKI_OPCODE_RE_JABBER     0x2
  57#define CVMX_PKI_OPCODE_RE_FCS        0x7
  58#define CVMX_PKI_OPCODE_RE_FCS_RCV    0x8
  59#define CVMX_PKI_OPCODE_RE_TERMINATE  0x9
  60#define CVMX_PKI_OPCODE_RE_RX_CTL     0xb
  61#define CVMX_PKI_OPCODE_RE_SKIP       0xc
  62#define CVMX_PKI_OPCODE_RE_DMAPKT     0xf
  63#define CVMX_PKI_OPCODE_RE_PKIPAR     0x13
  64#define CVMX_PKI_OPCODE_RE_PKIPCAM    0x14
  65#define CVMX_PKI_OPCODE_RE_MEMOUT     0x15
  66#define CVMX_PKI_OPCODE_RE_BUFS_OFLOW 0x16
  67#define CVMX_PKI_OPCODE_L2_FRAGMENT   0x20
  68#define CVMX_PKI_OPCODE_L2_OVERRUN    0x21
  69#define CVMX_PKI_OPCODE_L2_PFCS       0x22
  70#define CVMX_PKI_OPCODE_L2_PUNY       0x23
  71#define CVMX_PKI_OPCODE_L2_MAL        0x24
  72#define CVMX_PKI_OPCODE_L2_OVERSIZE   0x25
  73#define CVMX_PKI_OPCODE_L2_UNDERSIZE  0x26
  74#define CVMX_PKI_OPCODE_L2_LENMISM    0x27
  75#define CVMX_PKI_OPCODE_IP_NOT        0x41
  76#define CVMX_PKI_OPCODE_IP_CHK        0x42
  77#define CVMX_PKI_OPCODE_IP_MAL        0x43
  78#define CVMX_PKI_OPCODE_IP_MALD       0x44
  79#define CVMX_PKI_OPCODE_IP_HOP        0x45
  80#define CVMX_PKI_OPCODE_L4_MAL        0x61
  81#define CVMX_PKI_OPCODE_L4_CHK        0x62
  82#define CVMX_PKI_OPCODE_L4_LEN        0x63
  83#define CVMX_PKI_OPCODE_L4_PORT       0x64
  84#define CVMX_PKI_OPCODE_TCP_FLAG      0x65
  85
  86#define CVMX_PKI_OPCODE_MAX BIT(8) /* The size of WORD2:OPCODE field.*/
  87
  88/* Layer types in pki */
  89#define CVMX_PKI_LTYPE_E_NONE_M       0x0
  90#define CVMX_PKI_LTYPE_E_ENET_M       0x1
  91#define CVMX_PKI_LTYPE_E_VLAN_M       0x2
  92#define CVMX_PKI_LTYPE_E_SNAP_PAYLD_M 0x5
  93#define CVMX_PKI_LTYPE_E_ARP_M        0x6
  94#define CVMX_PKI_LTYPE_E_RARP_M       0x7
  95#define CVMX_PKI_LTYPE_E_IP4_M        0x8
  96#define CVMX_PKI_LTYPE_E_IP4_OPT_M    0x9
  97#define CVMX_PKI_LTYPE_E_IP6_M        0xA
  98#define CVMX_PKI_LTYPE_E_IP6_OPT_M    0xB
  99#define CVMX_PKI_LTYPE_E_IPSEC_ESP_M  0xC
 100#define CVMX_PKI_LTYPE_E_IPFRAG_M     0xD
 101#define CVMX_PKI_LTYPE_E_IPCOMP_M     0xE
 102#define CVMX_PKI_LTYPE_E_TCP_M        0x10
 103#define CVMX_PKI_LTYPE_E_UDP_M        0x11
 104#define CVMX_PKI_LTYPE_E_SCTP_M       0x12
 105#define CVMX_PKI_LTYPE_E_UDP_VXLAN_M  0x13
 106#define CVMX_PKI_LTYPE_E_GRE_M        0x14
 107#define CVMX_PKI_LTYPE_E_NVGRE_M      0x15
 108#define CVMX_PKI_LTYPE_E_GTP_M        0x16
 109#define CVMX_PKI_LTYPE_E_SW28_M       0x1C
 110#define CVMX_PKI_LTYPE_E_SW29_M       0x1D
 111#define CVMX_PKI_LTYPE_E_SW30_M       0x1E
 112#define CVMX_PKI_LTYPE_E_SW31_M       0x1F
 113
 114enum cvmx_pki_layer_type {
 115        CVMX_PKI_LTYPE_E_NONE = CVMX_PKI_LTYPE_E_NONE_M,
 116        CVMX_PKI_LTYPE_E_ENET = CVMX_PKI_LTYPE_E_ENET_M,
 117        CVMX_PKI_LTYPE_E_VLAN = CVMX_PKI_LTYPE_E_VLAN_M,
 118        CVMX_PKI_LTYPE_E_SNAP_PAYLD = CVMX_PKI_LTYPE_E_SNAP_PAYLD_M,
 119        CVMX_PKI_LTYPE_E_ARP = CVMX_PKI_LTYPE_E_ARP_M,
 120        CVMX_PKI_LTYPE_E_RARP = CVMX_PKI_LTYPE_E_RARP_M,
 121        CVMX_PKI_LTYPE_E_IP4 = CVMX_PKI_LTYPE_E_IP4_M,
 122        CVMX_PKI_LTYPE_E_IP4_OPT = CVMX_PKI_LTYPE_E_IP4_OPT_M,
 123        CVMX_PKI_LTYPE_E_IP6 = CVMX_PKI_LTYPE_E_IP6_M,
 124        CVMX_PKI_LTYPE_E_IP6_OPT = CVMX_PKI_LTYPE_E_IP6_OPT_M,
 125        CVMX_PKI_LTYPE_E_IPSEC_ESP = CVMX_PKI_LTYPE_E_IPSEC_ESP_M,
 126        CVMX_PKI_LTYPE_E_IPFRAG = CVMX_PKI_LTYPE_E_IPFRAG_M,
 127        CVMX_PKI_LTYPE_E_IPCOMP = CVMX_PKI_LTYPE_E_IPCOMP_M,
 128        CVMX_PKI_LTYPE_E_TCP = CVMX_PKI_LTYPE_E_TCP_M,
 129        CVMX_PKI_LTYPE_E_UDP = CVMX_PKI_LTYPE_E_UDP_M,
 130        CVMX_PKI_LTYPE_E_SCTP = CVMX_PKI_LTYPE_E_SCTP_M,
 131        CVMX_PKI_LTYPE_E_UDP_VXLAN = CVMX_PKI_LTYPE_E_UDP_VXLAN_M,
 132        CVMX_PKI_LTYPE_E_GRE = CVMX_PKI_LTYPE_E_GRE_M,
 133        CVMX_PKI_LTYPE_E_NVGRE = CVMX_PKI_LTYPE_E_NVGRE_M,
 134        CVMX_PKI_LTYPE_E_GTP = CVMX_PKI_LTYPE_E_GTP_M,
 135        CVMX_PKI_LTYPE_E_SW28 = CVMX_PKI_LTYPE_E_SW28_M,
 136        CVMX_PKI_LTYPE_E_SW29 = CVMX_PKI_LTYPE_E_SW29_M,
 137        CVMX_PKI_LTYPE_E_SW30 = CVMX_PKI_LTYPE_E_SW30_M,
 138        CVMX_PKI_LTYPE_E_SW31 = CVMX_PKI_LTYPE_E_SW31_M,
 139        CVMX_PKI_LTYPE_E_MAX = CVMX_PKI_LTYPE_E_SW31
 140};
 141
 142typedef union {
 143        u64 u64;
 144        struct {
 145                u64 ptr_vlan : 8;
 146                u64 ptr_layer_g : 8;
 147                u64 ptr_layer_f : 8;
 148                u64 ptr_layer_e : 8;
 149                u64 ptr_layer_d : 8;
 150                u64 ptr_layer_c : 8;
 151                u64 ptr_layer_b : 8;
 152                u64 ptr_layer_a : 8;
 153        };
 154} cvmx_pki_wqe_word4_t;
 155
 156/**
 157 * HW decode / err_code in work queue entry
 158 */
 159typedef union {
 160        u64 u64;
 161        struct {
 162                u64 bufs : 8;
 163                u64 ip_offset : 8;
 164                u64 vlan_valid : 1;
 165                u64 vlan_stacked : 1;
 166                u64 unassigned : 1;
 167                u64 vlan_cfi : 1;
 168                u64 vlan_id : 12;
 169                u64 varies : 12;
 170                u64 dec_ipcomp : 1;
 171                u64 tcp_or_udp : 1;
 172                u64 dec_ipsec : 1;
 173                u64 is_v6 : 1;
 174                u64 software : 1;
 175                u64 L4_error : 1;
 176                u64 is_frag : 1;
 177                u64 IP_exc : 1;
 178                u64 is_bcast : 1;
 179                u64 is_mcast : 1;
 180                u64 not_IP : 1;
 181                u64 rcv_error : 1;
 182                u64 err_code : 8;
 183        } s;
 184        struct {
 185                u64 bufs : 8;
 186                u64 ip_offset : 8;
 187                u64 vlan_valid : 1;
 188                u64 vlan_stacked : 1;
 189                u64 unassigned : 1;
 190                u64 vlan_cfi : 1;
 191                u64 vlan_id : 12;
 192                u64 port : 12;
 193                u64 dec_ipcomp : 1;
 194                u64 tcp_or_udp : 1;
 195                u64 dec_ipsec : 1;
 196                u64 is_v6 : 1;
 197                u64 software : 1;
 198                u64 L4_error : 1;
 199                u64 is_frag : 1;
 200                u64 IP_exc : 1;
 201                u64 is_bcast : 1;
 202                u64 is_mcast : 1;
 203                u64 not_IP : 1;
 204                u64 rcv_error : 1;
 205                u64 err_code : 8;
 206        } s_cn68xx;
 207        struct {
 208                u64 bufs : 8;
 209                u64 ip_offset : 8;
 210                u64 vlan_valid : 1;
 211                u64 vlan_stacked : 1;
 212                u64 unassigned : 1;
 213                u64 vlan_cfi : 1;
 214                u64 vlan_id : 12;
 215                u64 pr : 4;
 216                u64 unassigned2a : 4;
 217                u64 unassigned2 : 4;
 218                u64 dec_ipcomp : 1;
 219                u64 tcp_or_udp : 1;
 220                u64 dec_ipsec : 1;
 221                u64 is_v6 : 1;
 222                u64 software : 1;
 223                u64 L4_error : 1;
 224                u64 is_frag : 1;
 225                u64 IP_exc : 1;
 226                u64 is_bcast : 1;
 227                u64 is_mcast : 1;
 228                u64 not_IP : 1;
 229                u64 rcv_error : 1;
 230                u64 err_code : 8;
 231        } s_cn38xx;
 232        struct {
 233                u64 unused1 : 16;
 234                u64 vlan : 16;
 235                u64 unused2 : 32;
 236        } svlan;
 237        struct {
 238                u64 bufs : 8;
 239                u64 unused : 8;
 240                u64 vlan_valid : 1;
 241                u64 vlan_stacked : 1;
 242                u64 unassigned : 1;
 243                u64 vlan_cfi : 1;
 244                u64 vlan_id : 12;
 245                u64 varies : 12;
 246                u64 unassigned2 : 4;
 247                u64 software : 1;
 248                u64 unassigned3 : 1;
 249                u64 is_rarp : 1;
 250                u64 is_arp : 1;
 251                u64 is_bcast : 1;
 252                u64 is_mcast : 1;
 253                u64 not_IP : 1;
 254                u64 rcv_error : 1;
 255                u64 err_code : 8;
 256        } snoip;
 257        struct {
 258                u64 bufs : 8;
 259                u64 unused : 8;
 260                u64 vlan_valid : 1;
 261                u64 vlan_stacked : 1;
 262                u64 unassigned : 1;
 263                u64 vlan_cfi : 1;
 264                u64 vlan_id : 12;
 265                u64 port : 12;
 266                u64 unassigned2 : 4;
 267                u64 software : 1;
 268                u64 unassigned3 : 1;
 269                u64 is_rarp : 1;
 270                u64 is_arp : 1;
 271                u64 is_bcast : 1;
 272                u64 is_mcast : 1;
 273                u64 not_IP : 1;
 274                u64 rcv_error : 1;
 275                u64 err_code : 8;
 276        } snoip_cn68xx;
 277        struct {
 278                u64 bufs : 8;
 279                u64 unused : 8;
 280                u64 vlan_valid : 1;
 281                u64 vlan_stacked : 1;
 282                u64 unassigned : 1;
 283                u64 vlan_cfi : 1;
 284                u64 vlan_id : 12;
 285                u64 pr : 4;
 286                u64 unassigned2a : 8;
 287                u64 unassigned2 : 4;
 288                u64 software : 1;
 289                u64 unassigned3 : 1;
 290                u64 is_rarp : 1;
 291                u64 is_arp : 1;
 292                u64 is_bcast : 1;
 293                u64 is_mcast : 1;
 294                u64 not_IP : 1;
 295                u64 rcv_error : 1;
 296                u64 err_code : 8;
 297        } snoip_cn38xx;
 298} cvmx_pip_wqe_word2_t;
 299
 300typedef union {
 301        u64 u64;
 302        struct {
 303                u64 software : 1;
 304                u64 lg_hdr_type : 5;
 305                u64 lf_hdr_type : 5;
 306                u64 le_hdr_type : 5;
 307                u64 ld_hdr_type : 5;
 308                u64 lc_hdr_type : 5;
 309                u64 lb_hdr_type : 5;
 310                u64 is_la_ether : 1;
 311                u64 rsvd_0 : 8;
 312                u64 vlan_valid : 1;
 313                u64 vlan_stacked : 1;
 314                u64 stat_inc : 1;
 315                u64 pcam_flag4 : 1;
 316                u64 pcam_flag3 : 1;
 317                u64 pcam_flag2 : 1;
 318                u64 pcam_flag1 : 1;
 319                u64 is_frag : 1;
 320                u64 is_l3_bcast : 1;
 321                u64 is_l3_mcast : 1;
 322                u64 is_l2_bcast : 1;
 323                u64 is_l2_mcast : 1;
 324                u64 is_raw : 1;
 325                u64 err_level : 3;
 326                u64 err_code : 8;
 327        };
 328} cvmx_pki_wqe_word2_t;
 329
 330typedef union {
 331        u64 u64;
 332        cvmx_pki_wqe_word2_t pki;
 333        cvmx_pip_wqe_word2_t pip;
 334} cvmx_wqe_word2_t;
 335
 336typedef union {
 337        u64 u64;
 338        struct {
 339                u16 hw_chksum;
 340                u8 unused;
 341                u64 next_ptr : 40;
 342        } cn38xx;
 343        struct {
 344                u64 l4ptr : 8;    /* 56..63 */
 345                u64 unused0 : 8;  /* 48..55 */
 346                u64 l3ptr : 8;    /* 40..47 */
 347                u64 l2ptr : 8;    /* 32..39 */
 348                u64 unused1 : 18; /* 14..31 */
 349                u64 bpid : 6;     /* 8..13 */
 350                u64 unused2 : 2;  /* 6..7 */
 351                u64 pknd : 6;     /* 0..5 */
 352        } cn68xx;
 353} cvmx_pip_wqe_word0_t;
 354
 355typedef union {
 356        u64 u64;
 357        struct {
 358                u64 rsvd_0 : 4;
 359                u64 aura : 12;
 360                u64 rsvd_1 : 1;
 361                u64 apad : 3;
 362                u64 channel : 12;
 363                u64 bufs : 8;
 364                u64 style : 8;
 365                u64 rsvd_2 : 10;
 366                u64 pknd : 6;
 367        };
 368} cvmx_pki_wqe_word0_t;
 369
 370/* Use reserved bit, set by HW to 0, to indicate buf_ptr legacy translation*/
 371#define pki_wqe_translated word0.rsvd_1
 372
 373typedef union {
 374        u64 u64;
 375        cvmx_pip_wqe_word0_t pip;
 376        cvmx_pki_wqe_word0_t pki;
 377        struct {
 378                u64 unused : 24;
 379                u64 next_ptr : 40; /* On cn68xx this is unused as well */
 380        } raw;
 381} cvmx_wqe_word0_t;
 382
 383typedef union {
 384        u64 u64;
 385        struct {
 386                u64 len : 16;
 387                u64 rsvd_0 : 2;
 388                u64 rsvd_1 : 2;
 389                u64 grp : 10;
 390                cvmx_pow_tag_type_t tag_type : 2;
 391                u64 tag : 32;
 392        };
 393} cvmx_pki_wqe_word1_t;
 394
 395#define pki_errata20776 word1.rsvd_0
 396
 397typedef union {
 398        u64 u64;
 399        struct {
 400                u64 len : 16;
 401                u64 varies : 14;
 402                cvmx_pow_tag_type_t tag_type : 2;
 403                u64 tag : 32;
 404        };
 405        cvmx_pki_wqe_word1_t cn78xx;
 406        struct {
 407                u64 len : 16;
 408                u64 zero_0 : 1;
 409                u64 qos : 3;
 410                u64 zero_1 : 1;
 411                u64 grp : 6;
 412                u64 zero_2 : 3;
 413                cvmx_pow_tag_type_t tag_type : 2;
 414                u64 tag : 32;
 415        } cn68xx;
 416        struct {
 417                u64 len : 16;
 418                u64 ipprt : 6;
 419                u64 qos : 3;
 420                u64 grp : 4;
 421                u64 zero_2 : 1;
 422                cvmx_pow_tag_type_t tag_type : 2;
 423                u64 tag : 32;
 424        } cn38xx;
 425} cvmx_wqe_word1_t;
 426
 427typedef union {
 428        u64 u64;
 429        struct {
 430                u64 rsvd_0 : 8;
 431                u64 hwerr : 8;
 432                u64 rsvd_1 : 24;
 433                u64 sqid : 8;
 434                u64 rsvd_2 : 4;
 435                u64 vfnum : 12;
 436        };
 437} cvmx_wqe_word3_t;
 438
 439typedef union {
 440        u64 u64;
 441        struct {
 442                u64 rsvd_0 : 21;
 443                u64 sqfc : 11;
 444                u64 rsvd_1 : 5;
 445                u64 sqtail : 11;
 446                u64 rsvd_2 : 3;
 447                u64 sqhead : 13;
 448        };
 449} cvmx_wqe_word4_t;
 450
 451/**
 452 * Work queue entry format.
 453 * Must be 8-byte aligned.
 454 */
 455typedef struct cvmx_wqe_s {
 456        /*-------------------------------------------------------------------*/
 457        /* WORD 0                                                            */
 458        /*-------------------------------------------------------------------*/
 459        /* HW WRITE: the following 64 bits are filled by HW when a packet
 460         * arrives.
 461         */
 462        cvmx_wqe_word0_t word0;
 463
 464        /*-------------------------------------------------------------------*/
 465        /* WORD 1                                                            */
 466        /*-------------------------------------------------------------------*/
 467        /* HW WRITE: the following 64 bits are filled by HW when a packet
 468         * arrives.
 469         */
 470        cvmx_wqe_word1_t word1;
 471
 472        /*-------------------------------------------------------------------*/
 473        /* WORD 2                                                            */
 474        /*-------------------------------------------------------------------*/
 475        /* HW WRITE: the following 64-bits are filled in by hardware when a
 476         * packet arrives. This indicates a variety of status and error
 477         *conditions.
 478         */
 479        cvmx_pip_wqe_word2_t word2;
 480
 481        /* Pointer to the first segment of the packet. */
 482        cvmx_buf_ptr_t packet_ptr;
 483
 484        /* HW WRITE: OCTEON will fill in a programmable amount from the packet,
 485         * up to (at most, but perhaps less) the amount needed to fill the work
 486         * queue entry to 128 bytes. If the packet is recognized to be IP, the
 487         * hardware starts (except that the IPv4 header is padded for
 488         * appropriate alignment) writing here where the IP header starts.
 489         * If the packet is not recognized to be IP, the hardware starts
 490         * writing the beginning of the packet here.
 491         */
 492        u8 packet_data[96];
 493
 494        /* If desired, SW can make the work Q entry any length. For the purposes
 495         * of discussion here, Assume 128B always, as this is all that the hardware
 496         * deals with.
 497         */
 498} CVMX_CACHE_LINE_ALIGNED cvmx_wqe_t;
 499
 500/**
 501 * Work queue entry format for NQM
 502 * Must be 8-byte aligned
 503 */
 504typedef struct cvmx_wqe_nqm_s {
 505        /*-------------------------------------------------------------------*/
 506        /* WORD 0                                                            */
 507        /*-------------------------------------------------------------------*/
 508        /* HW WRITE: the following 64 bits are filled by HW when a packet
 509         * arrives.
 510         */
 511        cvmx_wqe_word0_t word0;
 512
 513        /*-------------------------------------------------------------------*/
 514        /* WORD 1                                                            */
 515        /*-------------------------------------------------------------------*/
 516        /* HW WRITE: the following 64 bits are filled by HW when a packet
 517         * arrives.
 518         */
 519        cvmx_wqe_word1_t word1;
 520
 521        /*-------------------------------------------------------------------*/
 522        /* WORD 2                                                            */
 523        /*-------------------------------------------------------------------*/
 524        /* Reserved */
 525        u64 word2;
 526
 527        /*-------------------------------------------------------------------*/
 528        /* WORD 3                                                            */
 529        /*-------------------------------------------------------------------*/
 530        /* NVMe specific information.*/
 531        cvmx_wqe_word3_t word3;
 532
 533        /*-------------------------------------------------------------------*/
 534        /* WORD 4                                                            */
 535        /*-------------------------------------------------------------------*/
 536        /* NVMe specific information.*/
 537        cvmx_wqe_word4_t word4;
 538
 539        /* HW WRITE: OCTEON will fill in a programmable amount from the packet,
 540         * up to (at most, but perhaps less) the amount needed to fill the work
 541         * queue entry to 128 bytes. If the packet is recognized to be IP, the
 542         * hardware starts (except that the IPv4 header is padded for
 543         * appropriate alignment) writing here where the IP header starts.
 544         * If the packet is not recognized to be IP, the hardware starts
 545         * writing the beginning of the packet here.
 546         */
 547        u8 packet_data[88];
 548
 549        /* If desired, SW can make the work Q entry any length.
 550         * For the purposes of discussion here, assume 128B always, as this is
 551         * all that the hardware deals with.
 552         */
 553} CVMX_CACHE_LINE_ALIGNED cvmx_wqe_nqm_t;
 554
 555/**
 556 * Work queue entry format for 78XX.
 557 * In 78XX packet data always resides in WQE buffer unless option
 558 * DIS_WQ_DAT=1 in PKI_STYLE_BUF, which causes packet data to use separate buffer.
 559 *
 560 * Must be 8-byte aligned.
 561 */
 562typedef struct {
 563        /*-------------------------------------------------------------------*/
 564        /* WORD 0                                                            */
 565        /*-------------------------------------------------------------------*/
 566        /* HW WRITE: the following 64 bits are filled by HW when a packet
 567         * arrives.
 568         */
 569        cvmx_pki_wqe_word0_t word0;
 570
 571        /*-------------------------------------------------------------------*/
 572        /* WORD 1                                                            */
 573        /*-------------------------------------------------------------------*/
 574        /* HW WRITE: the following 64 bits are filled by HW when a packet
 575         * arrives.
 576         */
 577        cvmx_pki_wqe_word1_t word1;
 578
 579        /*-------------------------------------------------------------------*/
 580        /* WORD 2                                                            */
 581        /*-------------------------------------------------------------------*/
 582        /* HW WRITE: the following 64-bits are filled in by hardware when a
 583         * packet arrives. This indicates a variety of status and error
 584         * conditions.
 585         */
 586        cvmx_pki_wqe_word2_t word2;
 587
 588        /*-------------------------------------------------------------------*/
 589        /* WORD 3                                                            */
 590        /*-------------------------------------------------------------------*/
 591        /* Pointer to the first segment of the packet.*/
 592        cvmx_buf_ptr_pki_t packet_ptr;
 593
 594        /*-------------------------------------------------------------------*/
 595        /* WORD 4                                                            */
 596        /*-------------------------------------------------------------------*/
 597        /* HW WRITE: the following 64-bits are filled in by hardware when a
 598         * packet arrives contains a byte pointer to the start of Layer
 599         * A/B/C/D/E/F/G relative of start of packet.
 600         */
 601        cvmx_pki_wqe_word4_t word4;
 602
 603        /*-------------------------------------------------------------------*/
 604        /* WORDs 5/6/7 may be extended there, if WQE_HSZ is set.             */
 605        /*-------------------------------------------------------------------*/
 606        u64 wqe_data[11];
 607
 608} CVMX_CACHE_LINE_ALIGNED cvmx_wqe_78xx_t;
 609
 610/* Node LS-bit position in the WQE[grp] or PKI_QPG_TBL[grp_ok].*/
 611#define CVMX_WQE_GRP_NODE_SHIFT 8
 612
 613/*
 614 * This is an accessor function into the WQE that retreives the
 615 * ingress port number, which can also be used as a destination
 616 * port number for the same port.
 617 *
 618 * @param work - Work Queue Entrey pointer
 619 * @returns returns the normalized port number, also known as "ipd" port
 620 */
 621static inline int cvmx_wqe_get_port(cvmx_wqe_t *work)
 622{
 623        int port;
 624
 625        if (octeon_has_feature(OCTEON_FEATURE_CN78XX_WQE)) {
 626                /* In 78xx wqe entry has channel number not port*/
 627                port = work->word0.pki.channel;
 628                /* For BGX interfaces (0x800 - 0xdff) the 4 LSBs indicate
 629                 * the PFC channel, must be cleared to normalize to "ipd"
 630                 */
 631                if (port & 0x800)
 632                        port &= 0xff0;
 633                /* Node number is in AURA field, make it part of port # */
 634                port |= (work->word0.pki.aura >> 10) << 12;
 635        } else if (octeon_has_feature(OCTEON_FEATURE_CN68XX_WQE)) {
 636                port = work->word2.s_cn68xx.port;
 637        } else {
 638                port = work->word1.cn38xx.ipprt;
 639        }
 640
 641        return port;
 642}
 643
 644static inline void cvmx_wqe_set_port(cvmx_wqe_t *work, int port)
 645{
 646        if (octeon_has_feature(OCTEON_FEATURE_CN78XX_WQE))
 647                work->word0.pki.channel = port;
 648        else if (octeon_has_feature(OCTEON_FEATURE_CN68XX_WQE))
 649                work->word2.s_cn68xx.port = port;
 650        else
 651                work->word1.cn38xx.ipprt = port;
 652}
 653
 654static inline int cvmx_wqe_get_grp(cvmx_wqe_t *work)
 655{
 656        int grp;
 657
 658        if (octeon_has_feature(OCTEON_FEATURE_CN78XX_WQE))
 659                /* legacy: GRP[0..2] :=QOS */
 660                grp = (0xff & work->word1.cn78xx.grp) >> 3;
 661        else if (octeon_has_feature(OCTEON_FEATURE_CN68XX_WQE))
 662                grp = work->word1.cn68xx.grp;
 663        else
 664                grp = work->word1.cn38xx.grp;
 665
 666        return grp;
 667}
 668
 669static inline void cvmx_wqe_set_xgrp(cvmx_wqe_t *work, int grp)
 670{
 671        if (octeon_has_feature(OCTEON_FEATURE_CN78XX_WQE))
 672                work->word1.cn78xx.grp = grp;
 673        else if (octeon_has_feature(OCTEON_FEATURE_CN68XX_WQE))
 674                work->word1.cn68xx.grp = grp;
 675        else
 676                work->word1.cn38xx.grp = grp;
 677}
 678
 679static inline int cvmx_wqe_get_xgrp(cvmx_wqe_t *work)
 680{
 681        int grp;
 682
 683        if (octeon_has_feature(OCTEON_FEATURE_CN78XX_WQE))
 684                grp = work->word1.cn78xx.grp;
 685        else if (octeon_has_feature(OCTEON_FEATURE_CN68XX_WQE))
 686                grp = work->word1.cn68xx.grp;
 687        else
 688                grp = work->word1.cn38xx.grp;
 689
 690        return grp;
 691}
 692
 693static inline void cvmx_wqe_set_grp(cvmx_wqe_t *work, int grp)
 694{
 695        if (octeon_has_feature(OCTEON_FEATURE_CN78XX_WQE)) {
 696                unsigned int node = cvmx_get_node_num();
 697                /* Legacy: GRP[0..2] :=QOS */
 698                work->word1.cn78xx.grp &= 0x7;
 699                work->word1.cn78xx.grp |= 0xff & (grp << 3);
 700                work->word1.cn78xx.grp |= (node << 8);
 701        } else if (octeon_has_feature(OCTEON_FEATURE_CN68XX_WQE)) {
 702                work->word1.cn68xx.grp = grp;
 703        } else {
 704                work->word1.cn38xx.grp = grp;
 705        }
 706}
 707
 708static inline int cvmx_wqe_get_qos(cvmx_wqe_t *work)
 709{
 710        int qos;
 711
 712        if (octeon_has_feature(OCTEON_FEATURE_CN78XX_WQE)) {
 713                /* Legacy: GRP[0..2] :=QOS */
 714                qos = work->word1.cn78xx.grp & 0x7;
 715        } else if (octeon_has_feature(OCTEON_FEATURE_CN68XX_WQE)) {
 716                qos = work->word1.cn68xx.qos;
 717        } else {
 718                qos = work->word1.cn38xx.qos;
 719        }
 720
 721        return qos;
 722}
 723
 724static inline void cvmx_wqe_set_qos(cvmx_wqe_t *work, int qos)
 725{
 726        if (octeon_has_feature(OCTEON_FEATURE_CN78XX_WQE)) {
 727                /* legacy: GRP[0..2] :=QOS */
 728                work->word1.cn78xx.grp &= ~0x7;
 729                work->word1.cn78xx.grp |= qos & 0x7;
 730        } else if (octeon_has_feature(OCTEON_FEATURE_CN68XX_WQE)) {
 731                work->word1.cn68xx.qos = qos;
 732        } else {
 733                work->word1.cn38xx.qos = qos;
 734        }
 735}
 736
 737static inline int cvmx_wqe_get_len(cvmx_wqe_t *work)
 738{
 739        int len;
 740
 741        if (octeon_has_feature(OCTEON_FEATURE_CN78XX_WQE))
 742                len = work->word1.cn78xx.len;
 743        else if (octeon_has_feature(OCTEON_FEATURE_CN68XX_WQE))
 744                len = work->word1.cn68xx.len;
 745        else
 746                len = work->word1.cn38xx.len;
 747
 748        return len;
 749}
 750
 751static inline void cvmx_wqe_set_len(cvmx_wqe_t *work, int len)
 752{
 753        if (octeon_has_feature(OCTEON_FEATURE_CN78XX_WQE))
 754                work->word1.cn78xx.len = len;
 755        else if (octeon_has_feature(OCTEON_FEATURE_CN68XX_WQE))
 756                work->word1.cn68xx.len = len;
 757        else
 758                work->word1.cn38xx.len = len;
 759}
 760
 761/**
 762 * This function returns, if there was L2/L1 errors detected in packet.
 763 *
 764 * @param work  pointer to work queue entry
 765 *
 766 * @return      0 if packet had no error, non-zero to indicate error code.
 767 *
 768 * Please refer to HRM for the specific model for full enumaration of error codes.
 769 * With Octeon1/Octeon2 models, the returned code indicates L1/L2 errors.
 770 * On CN73XX/CN78XX, the return code is the value of PKI_OPCODE_E,
 771 * if it is non-zero, otherwise the returned code will be derived from
 772 * PKI_ERRLEV_E such that an error indicated in LayerA will return 0x20,
 773 * LayerB - 0x30, LayerC - 0x40 and so forth.
 774 */
 775static inline int cvmx_wqe_get_rcv_err(cvmx_wqe_t *work)
 776{
 777        if (octeon_has_feature(OCTEON_FEATURE_CN78XX_WQE)) {
 778                cvmx_wqe_78xx_t *wqe = (cvmx_wqe_78xx_t *)work;
 779
 780                if (wqe->word2.err_level == CVMX_PKI_ERRLEV_E_RE || wqe->word2.err_code != 0)
 781                        return wqe->word2.err_code;
 782                else
 783                        return (wqe->word2.err_level << 4) + 0x10;
 784        } else if (work->word2.snoip.rcv_error) {
 785                return work->word2.snoip.err_code;
 786        }
 787
 788        return 0;
 789}
 790
 791static inline u32 cvmx_wqe_get_tag(cvmx_wqe_t *work)
 792{
 793        return work->word1.tag;
 794}
 795
 796static inline void cvmx_wqe_set_tag(cvmx_wqe_t *work, u32 tag)
 797{
 798        work->word1.tag = tag;
 799}
 800
 801static inline int cvmx_wqe_get_tt(cvmx_wqe_t *work)
 802{
 803        return work->word1.tag_type;
 804}
 805
 806static inline void cvmx_wqe_set_tt(cvmx_wqe_t *work, int tt)
 807{
 808        if (octeon_has_feature(OCTEON_FEATURE_CN78XX_WQE)) {
 809                work->word1.cn78xx.tag_type = (cvmx_pow_tag_type_t)tt;
 810        } else if (octeon_has_feature(OCTEON_FEATURE_CN68XX_WQE)) {
 811                work->word1.cn68xx.tag_type = (cvmx_pow_tag_type_t)tt;
 812                work->word1.cn68xx.zero_2 = 0;
 813        } else {
 814                work->word1.cn38xx.tag_type = (cvmx_pow_tag_type_t)tt;
 815                work->word1.cn38xx.zero_2 = 0;
 816        }
 817}
 818
 819static inline u8 cvmx_wqe_get_unused8(cvmx_wqe_t *work)
 820{
 821        u8 bits;
 822
 823        if (octeon_has_feature(OCTEON_FEATURE_CN78XX_WQE)) {
 824                cvmx_wqe_78xx_t *wqe = (cvmx_wqe_78xx_t *)work;
 825
 826                bits = wqe->word2.rsvd_0;
 827        } else if (octeon_has_feature(OCTEON_FEATURE_CN68XX_WQE)) {
 828                bits = work->word0.pip.cn68xx.unused1;
 829        } else {
 830                bits = work->word0.pip.cn38xx.unused;
 831        }
 832
 833        return bits;
 834}
 835
 836static inline void cvmx_wqe_set_unused8(cvmx_wqe_t *work, u8 v)
 837{
 838        if (octeon_has_feature(OCTEON_FEATURE_CN78XX_WQE)) {
 839                cvmx_wqe_78xx_t *wqe = (cvmx_wqe_78xx_t *)work;
 840
 841                wqe->word2.rsvd_0 = v;
 842        } else if (octeon_has_feature(OCTEON_FEATURE_CN68XX_WQE)) {
 843                work->word0.pip.cn68xx.unused1 = v;
 844        } else {
 845                work->word0.pip.cn38xx.unused = v;
 846        }
 847}
 848
 849static inline u8 cvmx_wqe_get_user_flags(cvmx_wqe_t *work)
 850{
 851        if (octeon_has_feature(OCTEON_FEATURE_CN78XX_WQE))
 852                return work->word0.pki.rsvd_2;
 853        else
 854                return 0;
 855}
 856
 857static inline void cvmx_wqe_set_user_flags(cvmx_wqe_t *work, u8 v)
 858{
 859        if (octeon_has_feature(OCTEON_FEATURE_CN78XX_WQE))
 860                work->word0.pki.rsvd_2 = v;
 861}
 862
 863static inline int cvmx_wqe_get_channel(cvmx_wqe_t *work)
 864{
 865        if (octeon_has_feature(OCTEON_FEATURE_CN78XX_WQE))
 866                return (work->word0.pki.channel);
 867        else
 868                return cvmx_wqe_get_port(work);
 869}
 870
 871static inline void cvmx_wqe_set_channel(cvmx_wqe_t *work, int channel)
 872{
 873        if (octeon_has_feature(OCTEON_FEATURE_CN78XX_WQE))
 874                work->word0.pki.channel = channel;
 875        else
 876                debug("%s: ERROR: not supported for model\n", __func__);
 877}
 878
 879static inline int cvmx_wqe_get_aura(cvmx_wqe_t *work)
 880{
 881        if (octeon_has_feature(OCTEON_FEATURE_CN78XX_WQE))
 882                return (work->word0.pki.aura);
 883        else
 884                return (work->packet_ptr.s.pool);
 885}
 886
 887static inline void cvmx_wqe_set_aura(cvmx_wqe_t *work, int aura)
 888{
 889        if (octeon_has_feature(OCTEON_FEATURE_CN78XX_WQE))
 890                work->word0.pki.aura = aura;
 891        else
 892                work->packet_ptr.s.pool = aura;
 893}
 894
 895static inline int cvmx_wqe_get_style(cvmx_wqe_t *work)
 896{
 897        if (octeon_has_feature(OCTEON_FEATURE_CN78XX_WQE))
 898                return (work->word0.pki.style);
 899        return 0;
 900}
 901
 902static inline void cvmx_wqe_set_style(cvmx_wqe_t *work, int style)
 903{
 904        if (octeon_has_feature(OCTEON_FEATURE_CN78XX_WQE))
 905                work->word0.pki.style = style;
 906}
 907
 908static inline int cvmx_wqe_is_l3_ip(cvmx_wqe_t *work)
 909{
 910        if (octeon_has_feature(OCTEON_FEATURE_CN78XX_WQE)) {
 911                cvmx_wqe_78xx_t *wqe = (cvmx_wqe_78xx_t *)work;
 912                /* Match all 4 values for v4/v6 with.without options */
 913                if ((wqe->word2.lc_hdr_type & 0x1c) == CVMX_PKI_LTYPE_E_IP4)
 914                        return 1;
 915                if ((wqe->word2.le_hdr_type & 0x1c) == CVMX_PKI_LTYPE_E_IP4)
 916                        return 1;
 917                return 0;
 918        } else {
 919                return !work->word2.s_cn38xx.not_IP;
 920        }
 921}
 922
 923static inline int cvmx_wqe_is_l3_ipv4(cvmx_wqe_t *work)
 924{
 925        if (octeon_has_feature(OCTEON_FEATURE_CN78XX_WQE)) {
 926                cvmx_wqe_78xx_t *wqe = (cvmx_wqe_78xx_t *)work;
 927                /* Match 2 values - with/wotuout options */
 928                if ((wqe->word2.lc_hdr_type & 0x1e) == CVMX_PKI_LTYPE_E_IP4)
 929                        return 1;
 930                if ((wqe->word2.le_hdr_type & 0x1e) == CVMX_PKI_LTYPE_E_IP4)
 931                        return 1;
 932                return 0;
 933        } else {
 934                return (!work->word2.s_cn38xx.not_IP &&
 935                        !work->word2.s_cn38xx.is_v6);
 936        }
 937}
 938
 939static inline int cvmx_wqe_is_l3_ipv6(cvmx_wqe_t *work)
 940{
 941        if (octeon_has_feature(OCTEON_FEATURE_CN78XX_WQE)) {
 942                cvmx_wqe_78xx_t *wqe = (cvmx_wqe_78xx_t *)work;
 943                /* Match 2 values - with/wotuout options */
 944                if ((wqe->word2.lc_hdr_type & 0x1e) == CVMX_PKI_LTYPE_E_IP6)
 945                        return 1;
 946                if ((wqe->word2.le_hdr_type & 0x1e) == CVMX_PKI_LTYPE_E_IP6)
 947                        return 1;
 948                return 0;
 949        } else {
 950                return (!work->word2.s_cn38xx.not_IP &&
 951                        work->word2.s_cn38xx.is_v6);
 952        }
 953}
 954
 955static inline bool cvmx_wqe_is_l4_udp_or_tcp(cvmx_wqe_t *work)
 956{
 957        if (octeon_has_feature(OCTEON_FEATURE_CN78XX_WQE)) {
 958                cvmx_wqe_78xx_t *wqe = (cvmx_wqe_78xx_t *)work;
 959
 960                if (wqe->word2.lf_hdr_type == CVMX_PKI_LTYPE_E_TCP)
 961                        return true;
 962                if (wqe->word2.lf_hdr_type == CVMX_PKI_LTYPE_E_UDP)
 963                        return true;
 964                return false;
 965        }
 966
 967        if (work->word2.s_cn38xx.not_IP)
 968                return false;
 969
 970        return (work->word2.s_cn38xx.tcp_or_udp != 0);
 971}
 972
 973static inline int cvmx_wqe_is_l2_bcast(cvmx_wqe_t *work)
 974{
 975        if (octeon_has_feature(OCTEON_FEATURE_CN78XX_WQE)) {
 976                cvmx_wqe_78xx_t *wqe = (cvmx_wqe_78xx_t *)work;
 977
 978                return wqe->word2.is_l2_bcast;
 979        } else {
 980                return work->word2.s_cn38xx.is_bcast;
 981        }
 982}
 983
 984static inline int cvmx_wqe_is_l2_mcast(cvmx_wqe_t *work)
 985{
 986        if (octeon_has_feature(OCTEON_FEATURE_CN78XX_WQE)) {
 987                cvmx_wqe_78xx_t *wqe = (cvmx_wqe_78xx_t *)work;
 988
 989                return wqe->word2.is_l2_mcast;
 990        } else {
 991                return work->word2.s_cn38xx.is_mcast;
 992        }
 993}
 994
 995static inline void cvmx_wqe_set_l2_bcast(cvmx_wqe_t *work, bool bcast)
 996{
 997        if (octeon_has_feature(OCTEON_FEATURE_CN78XX_WQE)) {
 998                cvmx_wqe_78xx_t *wqe = (cvmx_wqe_78xx_t *)work;
 999
1000                wqe->word2.is_l2_bcast = bcast;
1001        } else {
1002                work->word2.s_cn38xx.is_bcast = bcast;
1003        }
1004}
1005
1006static inline void cvmx_wqe_set_l2_mcast(cvmx_wqe_t *work, bool mcast)
1007{
1008        if (octeon_has_feature(OCTEON_FEATURE_CN78XX_WQE)) {
1009                cvmx_wqe_78xx_t *wqe = (cvmx_wqe_78xx_t *)work;
1010
1011                wqe->word2.is_l2_mcast = mcast;
1012        } else {
1013                work->word2.s_cn38xx.is_mcast = mcast;
1014        }
1015}
1016
1017static inline int cvmx_wqe_is_l3_bcast(cvmx_wqe_t *work)
1018{
1019        if (octeon_has_feature(OCTEON_FEATURE_CN78XX_WQE)) {
1020                cvmx_wqe_78xx_t *wqe = (cvmx_wqe_78xx_t *)work;
1021
1022                return wqe->word2.is_l3_bcast;
1023        }
1024        debug("%s: ERROR: not supported for model\n", __func__);
1025        return 0;
1026}
1027
1028static inline int cvmx_wqe_is_l3_mcast(cvmx_wqe_t *work)
1029{
1030        if (octeon_has_feature(OCTEON_FEATURE_CN78XX_WQE)) {
1031                cvmx_wqe_78xx_t *wqe = (cvmx_wqe_78xx_t *)work;
1032
1033                return wqe->word2.is_l3_mcast;
1034        }
1035        debug("%s: ERROR: not supported for model\n", __func__);
1036        return 0;
1037}
1038
1039/**
1040 * This function returns is there was IP error detected in packet.
1041 * For 78XX it does not flag ipv4 options and ipv6 extensions.
1042 * For older chips if PIP_GBL_CTL was proviosned to flag ip4_otions and
1043 * ipv6 extension, it will be flag them.
1044 * @param work  pointer to work queue entry
1045 * @return      1 -- If IP error was found in packet
1046 *          0 -- If no IP error was found in packet.
1047 */
1048static inline int cvmx_wqe_is_ip_exception(cvmx_wqe_t *work)
1049{
1050        if (octeon_has_feature(OCTEON_FEATURE_CN78XX_WQE)) {
1051                cvmx_wqe_78xx_t *wqe = (cvmx_wqe_78xx_t *)work;
1052
1053                if (wqe->word2.err_level == CVMX_PKI_ERRLEV_E_LC)
1054                        return 1;
1055                else
1056                        return 0;
1057        }
1058
1059        return work->word2.s.IP_exc;
1060}
1061
1062static inline int cvmx_wqe_is_l4_error(cvmx_wqe_t *work)
1063{
1064        if (octeon_has_feature(OCTEON_FEATURE_CN78XX_WQE)) {
1065                cvmx_wqe_78xx_t *wqe = (cvmx_wqe_78xx_t *)work;
1066
1067                if (wqe->word2.err_level == CVMX_PKI_ERRLEV_E_LF)
1068                        return 1;
1069                else
1070                        return 0;
1071        } else {
1072                return work->word2.s.L4_error;
1073        }
1074}
1075
1076static inline void cvmx_wqe_set_vlan(cvmx_wqe_t *work, bool set)
1077{
1078        if (octeon_has_feature(OCTEON_FEATURE_CN78XX_WQE)) {
1079                cvmx_wqe_78xx_t *wqe = (cvmx_wqe_78xx_t *)work;
1080
1081                wqe->word2.vlan_valid = set;
1082        } else {
1083                work->word2.s.vlan_valid = set;
1084        }
1085}
1086
1087static inline int cvmx_wqe_is_vlan(cvmx_wqe_t *work)
1088{
1089        if (octeon_has_feature(OCTEON_FEATURE_CN78XX_WQE)) {
1090                cvmx_wqe_78xx_t *wqe = (cvmx_wqe_78xx_t *)work;
1091
1092                return wqe->word2.vlan_valid;
1093        } else {
1094                return work->word2.s.vlan_valid;
1095        }
1096}
1097
1098static inline int cvmx_wqe_is_vlan_stacked(cvmx_wqe_t *work)
1099{
1100        if (octeon_has_feature(OCTEON_FEATURE_CN78XX_WQE)) {
1101                cvmx_wqe_78xx_t *wqe = (cvmx_wqe_78xx_t *)work;
1102
1103                return wqe->word2.vlan_stacked;
1104        } else {
1105                return work->word2.s.vlan_stacked;
1106        }
1107}
1108
1109/**
1110 * Extract packet data buffer pointer from work queue entry.
1111 *
1112 * Returns the legacy (Octeon1/Octeon2) buffer pointer structure
1113 * for the linked buffer list.
1114 * On CN78XX, the native buffer pointer structure is converted into
1115 * the legacy format.
1116 * The legacy buf_ptr is then stored in the WQE, and word0 reserved
1117 * field is set to indicate that the buffer pointers were translated.
1118 * If the packet data is only found inside the work queue entry,
1119 * a standard buffer pointer structure is created for it.
1120 */
1121cvmx_buf_ptr_t cvmx_wqe_get_packet_ptr(cvmx_wqe_t *work);
1122
1123static inline int cvmx_wqe_get_bufs(cvmx_wqe_t *work)
1124{
1125        int bufs;
1126
1127        if (octeon_has_feature(OCTEON_FEATURE_CN78XX_WQE)) {
1128                bufs = work->word0.pki.bufs;
1129        } else {
1130                /* Adjust for packet-in-WQE cases */
1131                if (cvmx_unlikely(work->word2.s_cn38xx.bufs == 0 && !work->word2.s.software))
1132                        (void)cvmx_wqe_get_packet_ptr(work);
1133                bufs = work->word2.s_cn38xx.bufs;
1134        }
1135        return bufs;
1136}
1137
1138/**
1139 * Free Work Queue Entry memory
1140 *
1141 * Will return the WQE buffer to its pool, unless the WQE contains
1142 * non-redundant packet data.
1143 * This function is intended to be called AFTER the packet data
1144 * has been passed along to PKO for transmission and release.
1145 * It can also follow a call to cvmx_helper_free_packet_data()
1146 * to release the WQE after associated data was released.
1147 */
1148void cvmx_wqe_free(cvmx_wqe_t *work);
1149
1150/**
1151 * Check if a work entry has been intiated by software
1152 *
1153 */
1154static inline bool cvmx_wqe_is_soft(cvmx_wqe_t *work)
1155{
1156        if (octeon_has_feature(OCTEON_FEATURE_CN78XX_WQE)) {
1157                cvmx_wqe_78xx_t *wqe = (cvmx_wqe_78xx_t *)work;
1158
1159                return wqe->word2.software;
1160        } else {
1161                return work->word2.s.software;
1162        }
1163}
1164
1165/**
1166 * Allocate a work-queue entry for delivering software-initiated
1167 * event notifications.
1168 * The application data is copied into the work-queue entry,
1169 * if the space is sufficient.
1170 */
1171cvmx_wqe_t *cvmx_wqe_soft_create(void *data_p, unsigned int data_sz);
1172
1173/* Errata (PKI-20776) PKI_BUFLINK_S's are endian-swapped
1174 * CN78XX pass 1.x has a bug where the packet pointer in each segment is
1175 * written in the opposite endianness of the configured mode. Fix these here.
1176 */
1177static inline void cvmx_wqe_pki_errata_20776(cvmx_wqe_t *work)
1178{
1179        cvmx_wqe_78xx_t *wqe = (cvmx_wqe_78xx_t *)work;
1180
1181        if (OCTEON_IS_MODEL(OCTEON_CN78XX_PASS1_X) && !wqe->pki_errata20776) {
1182                u64 bufs;
1183                cvmx_buf_ptr_pki_t buffer_next;
1184
1185                bufs = wqe->word0.bufs;
1186                buffer_next = wqe->packet_ptr;
1187                while (bufs > 1) {
1188                        cvmx_buf_ptr_pki_t next;
1189                        void *nextaddr = cvmx_phys_to_ptr(buffer_next.addr - 8);
1190
1191                        memcpy(&next, nextaddr, sizeof(next));
1192                        next.u64 = __builtin_bswap64(next.u64);
1193                        memcpy(nextaddr, &next, sizeof(next));
1194                        buffer_next = next;
1195                        bufs--;
1196                }
1197                wqe->pki_errata20776 = 1;
1198        }
1199}
1200
1201/**
1202 * @INTERNAL
1203 *
1204 * Extract the native PKI-specific buffer pointer from WQE.
1205 *
1206 * NOTE: Provisional, may be superceded.
1207 */
1208static inline cvmx_buf_ptr_pki_t cvmx_wqe_get_pki_pkt_ptr(cvmx_wqe_t *work)
1209{
1210        cvmx_wqe_78xx_t *wqe = (cvmx_wqe_78xx_t *)work;
1211
1212        if (!octeon_has_feature(OCTEON_FEATURE_CN78XX_WQE)) {
1213                cvmx_buf_ptr_pki_t x = { 0 };
1214                return x;
1215        }
1216
1217        cvmx_wqe_pki_errata_20776(work);
1218        return wqe->packet_ptr;
1219}
1220
1221/**
1222 * Set the buffer segment count for a packet.
1223 *
1224 * @return Returns the actual resulting value in the WQE fielda
1225 *
1226 */
1227static inline unsigned int cvmx_wqe_set_bufs(cvmx_wqe_t *work, unsigned int bufs)
1228{
1229        if (octeon_has_feature(OCTEON_FEATURE_CN78XX_WQE)) {
1230                work->word0.pki.bufs = bufs;
1231                return work->word0.pki.bufs;
1232        }
1233
1234        work->word2.s.bufs = bufs;
1235        return work->word2.s.bufs;
1236}
1237
1238/**
1239 * Get the offset of Layer-3 header,
1240 * only supported when Layer-3 protocol is IPv4 or IPv6.
1241 *
1242 * @return Returns the offset, or 0 if the offset is not known or unsupported.
1243 *
1244 * FIXME: Assuming word4 is present.
1245 */
1246static inline unsigned int cvmx_wqe_get_l3_offset(cvmx_wqe_t *work)
1247{
1248        if (octeon_has_feature(OCTEON_FEATURE_CN78XX_WQE)) {
1249                cvmx_wqe_78xx_t *wqe = (cvmx_wqe_78xx_t *)work;
1250                /* Match 4 values: IPv4/v6 w/wo options */
1251                if ((wqe->word2.lc_hdr_type & 0x1c) == CVMX_PKI_LTYPE_E_IP4)
1252                        return wqe->word4.ptr_layer_c;
1253        } else {
1254                return work->word2.s.ip_offset;
1255        }
1256
1257        return 0;
1258}
1259
1260/**
1261 * Set the offset of Layer-3 header in a packet.
1262 * Typically used when an IP packet is generated by software
1263 * or when the Layer-2 header length is modified, and
1264 * a subsequent recalculation of checksums is anticipated.
1265 *
1266 * @return Returns the actual value of the work entry offset field.
1267 *
1268 * FIXME: Assuming word4 is present.
1269 */
1270static inline unsigned int cvmx_wqe_set_l3_offset(cvmx_wqe_t *work, unsigned int ip_off)
1271{
1272        if (octeon_has_feature(OCTEON_FEATURE_CN78XX_WQE)) {
1273                cvmx_wqe_78xx_t *wqe = (cvmx_wqe_78xx_t *)work;
1274                /* Match 4 values: IPv4/v6 w/wo options */
1275                if ((wqe->word2.lc_hdr_type & 0x1c) == CVMX_PKI_LTYPE_E_IP4)
1276                        wqe->word4.ptr_layer_c = ip_off;
1277        } else {
1278                work->word2.s.ip_offset = ip_off;
1279        }
1280
1281        return cvmx_wqe_get_l3_offset(work);
1282}
1283
1284/**
1285 * Set the indication that the packet contains a IPv4 Layer-3 * header.
1286 * Use 'cvmx_wqe_set_l3_ipv6()' if the protocol is IPv6.
1287 * When 'set' is false, the call will result in an indication
1288 * that the Layer-3 protocol is neither IPv4 nor IPv6.
1289 *
1290 * FIXME: Add IPV4_OPT handling based on L3 header length.
1291 */
1292static inline void cvmx_wqe_set_l3_ipv4(cvmx_wqe_t *work, bool set)
1293{
1294        if (octeon_has_feature(OCTEON_FEATURE_CN78XX_WQE)) {
1295                cvmx_wqe_78xx_t *wqe = (cvmx_wqe_78xx_t *)work;
1296
1297                if (set)
1298                        wqe->word2.lc_hdr_type = CVMX_PKI_LTYPE_E_IP4;
1299                else
1300                        wqe->word2.lc_hdr_type = CVMX_PKI_LTYPE_E_NONE;
1301        } else {
1302                work->word2.s.not_IP = !set;
1303                if (set)
1304                        work->word2.s_cn38xx.is_v6 = 0;
1305        }
1306}
1307
1308/**
1309 * Set packet Layer-3 protocol to IPv6.
1310 *
1311 * FIXME: Add IPV6_OPT handling based on presence of extended headers.
1312 */
1313static inline void cvmx_wqe_set_l3_ipv6(cvmx_wqe_t *work, bool set)
1314{
1315        if (octeon_has_feature(OCTEON_FEATURE_CN78XX_WQE)) {
1316                cvmx_wqe_78xx_t *wqe = (cvmx_wqe_78xx_t *)work;
1317
1318                if (set)
1319                        wqe->word2.lc_hdr_type = CVMX_PKI_LTYPE_E_IP6;
1320                else
1321                        wqe->word2.lc_hdr_type = CVMX_PKI_LTYPE_E_NONE;
1322        } else {
1323                work->word2.s_cn38xx.not_IP = !set;
1324                if (set)
1325                        work->word2.s_cn38xx.is_v6 = 1;
1326        }
1327}
1328
1329/**
1330 * Set a packet Layer-4 protocol type to UDP.
1331 */
1332static inline void cvmx_wqe_set_l4_udp(cvmx_wqe_t *work, bool set)
1333{
1334        if (octeon_has_feature(OCTEON_FEATURE_CN78XX_WQE)) {
1335                cvmx_wqe_78xx_t *wqe = (cvmx_wqe_78xx_t *)work;
1336
1337                if (set)
1338                        wqe->word2.lf_hdr_type = CVMX_PKI_LTYPE_E_UDP;
1339                else
1340                        wqe->word2.lf_hdr_type = CVMX_PKI_LTYPE_E_NONE;
1341        } else {
1342                if (!work->word2.s_cn38xx.not_IP)
1343                        work->word2.s_cn38xx.tcp_or_udp = set;
1344        }
1345}
1346
1347/**
1348 * Set a packet Layer-4 protocol type to TCP.
1349 */
1350static inline void cvmx_wqe_set_l4_tcp(cvmx_wqe_t *work, bool set)
1351{
1352        if (octeon_has_feature(OCTEON_FEATURE_CN78XX_WQE)) {
1353                cvmx_wqe_78xx_t *wqe = (cvmx_wqe_78xx_t *)work;
1354
1355                if (set)
1356                        wqe->word2.lf_hdr_type = CVMX_PKI_LTYPE_E_TCP;
1357                else
1358                        wqe->word2.lf_hdr_type = CVMX_PKI_LTYPE_E_NONE;
1359        } else {
1360                if (!work->word2.s_cn38xx.not_IP)
1361                        work->word2.s_cn38xx.tcp_or_udp = set;
1362        }
1363}
1364
1365/**
1366 * Set the "software" flag in a work entry.
1367 */
1368static inline void cvmx_wqe_set_soft(cvmx_wqe_t *work, bool set)
1369{
1370        if (octeon_has_feature(OCTEON_FEATURE_CN78XX_WQE)) {
1371                cvmx_wqe_78xx_t *wqe = (cvmx_wqe_78xx_t *)work;
1372
1373                wqe->word2.software = set;
1374        } else {
1375                work->word2.s.software = set;
1376        }
1377}
1378
1379/**
1380 * Return true if the packet is an IP fragment.
1381 */
1382static inline bool cvmx_wqe_is_l3_frag(cvmx_wqe_t *work)
1383{
1384        if (octeon_has_feature(OCTEON_FEATURE_CN78XX_WQE)) {
1385                cvmx_wqe_78xx_t *wqe = (cvmx_wqe_78xx_t *)work;
1386
1387                return (wqe->word2.is_frag != 0);
1388        }
1389
1390        if (!work->word2.s_cn38xx.not_IP)
1391                return (work->word2.s.is_frag != 0);
1392
1393        return false;
1394}
1395
1396/**
1397 * Set the indicator that the packet is an fragmented IP packet.
1398 */
1399static inline void cvmx_wqe_set_l3_frag(cvmx_wqe_t *work, bool set)
1400{
1401        if (octeon_has_feature(OCTEON_FEATURE_CN78XX_WQE)) {
1402                cvmx_wqe_78xx_t *wqe = (cvmx_wqe_78xx_t *)work;
1403
1404                wqe->word2.is_frag = set;
1405        } else {
1406                if (!work->word2.s_cn38xx.not_IP)
1407                        work->word2.s.is_frag = set;
1408        }
1409}
1410
1411/**
1412 * Set the packet Layer-3 protocol to RARP.
1413 */
1414static inline void cvmx_wqe_set_l3_rarp(cvmx_wqe_t *work, bool set)
1415{
1416        if (octeon_has_feature(OCTEON_FEATURE_CN78XX_WQE)) {
1417                cvmx_wqe_78xx_t *wqe = (cvmx_wqe_78xx_t *)work;
1418
1419                if (set)
1420                        wqe->word2.lc_hdr_type = CVMX_PKI_LTYPE_E_RARP;
1421                else
1422                        wqe->word2.lc_hdr_type = CVMX_PKI_LTYPE_E_NONE;
1423        } else {
1424                work->word2.snoip.is_rarp = set;
1425        }
1426}
1427
1428/**
1429 * Set the packet Layer-3 protocol to ARP.
1430 */
1431static inline void cvmx_wqe_set_l3_arp(cvmx_wqe_t *work, bool set)
1432{
1433        if (octeon_has_feature(OCTEON_FEATURE_CN78XX_WQE)) {
1434                cvmx_wqe_78xx_t *wqe = (cvmx_wqe_78xx_t *)work;
1435
1436                if (set)
1437                        wqe->word2.lc_hdr_type = CVMX_PKI_LTYPE_E_ARP;
1438                else
1439                        wqe->word2.lc_hdr_type = CVMX_PKI_LTYPE_E_NONE;
1440        } else {
1441                work->word2.snoip.is_arp = set;
1442        }
1443}
1444
1445/**
1446 * Return true if the packet Layer-3 protocol is ARP.
1447 */
1448static inline bool cvmx_wqe_is_l3_arp(cvmx_wqe_t *work)
1449{
1450        if (octeon_has_feature(OCTEON_FEATURE_CN78XX_WQE)) {
1451                cvmx_wqe_78xx_t *wqe = (cvmx_wqe_78xx_t *)work;
1452
1453                return (wqe->word2.lc_hdr_type == CVMX_PKI_LTYPE_E_ARP);
1454        }
1455
1456        if (work->word2.s_cn38xx.not_IP)
1457                return (work->word2.snoip.is_arp != 0);
1458
1459        return false;
1460}
1461
1462#endif /* __CVMX_WQE_H__ */
1463