Back to home page

OSCL-LXR

 
 

    


0001 /***********************license start***************
0002  * Author: Cavium Networks
0003  *
0004  * Contact: support@caviumnetworks.com
0005  * This file is part of the OCTEON SDK
0006  *
0007  * Copyright (c) 2003-2008 Cavium Networks
0008  *
0009  * This file is free software; you can redistribute it and/or modify
0010  * it under the terms of the GNU General Public License, Version 2, as
0011  * published by the Free Software Foundation.
0012  *
0013  * This file is distributed in the hope that it will be useful, but
0014  * AS-IS and WITHOUT ANY WARRANTY; without even the implied warranty
0015  * of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE, TITLE, or
0016  * NONINFRINGEMENT.  See the GNU General Public License for more
0017  * details.
0018  *
0019  * You should have received a copy of the GNU General Public License
0020  * along with this file; if not, write to the Free Software
0021  * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
0022  * or visit http://www.gnu.org/licenses/.
0023  *
0024  * This file may also be available under a different license from Cavium.
0025  * Contact Cavium Networks for more information
0026  ***********************license end**************************************/
0027 
0028 /**
0029  *
0030  * This header file defines the work queue entry (wqe) data structure.
0031  * Since this is a commonly used structure that depends on structures
0032  * from several hardware blocks, those definitions have been placed
0033  * in this file to create a single point of definition of the wqe
0034  * format.
0035  * Data structures are still named according to the block that they
0036  * relate to.
0037  *
0038  */
0039 
0040 #ifndef __CVMX_WQE_H__
0041 #define __CVMX_WQE_H__
0042 
0043 #include <asm/octeon/cvmx-packet.h>
0044 
0045 
0046 #define OCT_TAG_TYPE_STRING(x)                      \
0047     (((x) == CVMX_POW_TAG_TYPE_ORDERED) ?  "ORDERED" :      \
0048         (((x) == CVMX_POW_TAG_TYPE_ATOMIC) ?  "ATOMIC" :    \
0049             (((x) == CVMX_POW_TAG_TYPE_NULL) ?  "NULL" :    \
0050                 "NULL_NULL")))
0051 
0052 /**
0053  * HW decode / err_code in work queue entry
0054  */
0055 typedef union {
0056     uint64_t u64;
0057 
0058     /* Use this struct if the hardware determines that the packet is IP */
0059     struct {
0060 #ifdef __BIG_ENDIAN_BITFIELD
0061         /* HW sets this to the number of buffers used by this packet */
0062         uint64_t bufs:8;
0063         /* HW sets to the number of L2 bytes prior to the IP */
0064         uint64_t ip_offset:8;
0065         /* set to 1 if we found DSA/VLAN in the L2 */
0066         uint64_t vlan_valid:1;
0067         /* Set to 1 if the DSA/VLAN tag is stacked */
0068         uint64_t vlan_stacked:1;
0069         uint64_t unassigned:1;
0070         /* HW sets to the DSA/VLAN CFI flag (valid when vlan_valid) */
0071         uint64_t vlan_cfi:1;
0072         /* HW sets to the DSA/VLAN_ID field (valid when vlan_valid) */
0073         uint64_t vlan_id:12;
0074         /* Ring Identifier (if PCIe). Requires PIP_GBL_CTL[RING_EN]=1 */
0075         uint64_t pr:4;
0076         uint64_t unassigned2:8;
0077         /* the packet needs to be decompressed */
0078         uint64_t dec_ipcomp:1;
0079         /* the packet is either TCP or UDP */
0080         uint64_t tcp_or_udp:1;
0081         /* the packet needs to be decrypted (ESP or AH) */
0082         uint64_t dec_ipsec:1;
0083         /* the packet is IPv6 */
0084         uint64_t is_v6:1;
0085 
0086         /*
0087          * (rcv_error, not_IP, IP_exc, is_frag, L4_error,
0088          * software, etc.).
0089          */
0090 
0091         /*
0092          * reserved for software use, hardware will clear on
0093          * packet creation.
0094          */
0095         uint64_t software:1;
0096         /* exceptional conditions below */
0097         /* the receive interface hardware detected an L4 error
0098          * (only applies if !is_frag) (only applies if
0099          * !rcv_error && !not_IP && !IP_exc && !is_frag)
0100          * failure indicated in err_code below, decode:
0101          *
0102          * - 1 = Malformed L4
0103          * - 2 = L4 Checksum Error: the L4 checksum value is
0104          * - 3 = UDP Length Error: The UDP length field would
0105          *   make the UDP data longer than what remains in
0106          *   the IP packet (as defined by the IP header
0107          *   length field).
0108          * - 4 = Bad L4 Port: either the source or destination
0109          *   TCP/UDP port is 0.
0110          * - 8 = TCP FIN Only: the packet is TCP and only the
0111          *   FIN flag set.
0112          * - 9 = TCP No Flags: the packet is TCP and no flags
0113          *   are set.
0114          * - 10 = TCP FIN RST: the packet is TCP and both FIN
0115          *    and RST are set.
0116          * - 11 = TCP SYN URG: the packet is TCP and both SYN
0117          *    and URG are set.
0118          * - 12 = TCP SYN RST: the packet is TCP and both SYN
0119          *    and RST are set.
0120          * - 13 = TCP SYN FIN: the packet is TCP and both SYN
0121          *    and FIN are set.
0122          */
0123         uint64_t L4_error:1;
0124         /* set if the packet is a fragment */
0125         uint64_t is_frag:1;
0126         /* the receive interface hardware detected an IP error
0127          * / exception (only applies if !rcv_error && !not_IP)
0128          * failure indicated in err_code below, decode:
0129          *
0130          * - 1 = Not IP: the IP version field is neither 4 nor
0131          *   6.
0132          * - 2 = IPv4 Header Checksum Error: the IPv4 header
0133          *   has a checksum violation.
0134          * - 3 = IP Malformed Header: the packet is not long
0135          *   enough to contain the IP header.
0136          * - 4 = IP Malformed: the packet is not long enough
0137          *   to contain the bytes indicated by the IP
0138          *   header. Pad is allowed.
0139          * - 5 = IP TTL Hop: the IPv4 TTL field or the IPv6
0140          *   Hop Count field are zero.
0141          * - 6 = IP Options
0142          */
0143         uint64_t IP_exc:1;
0144         /*
0145          * Set if the hardware determined that the packet is a
0146          * broadcast.
0147          */
0148         uint64_t is_bcast:1;
0149         /*
0150          * St if the hardware determined that the packet is a
0151          * multi-cast.
0152          */
0153         uint64_t is_mcast:1;
0154         /*
0155          * Set if the packet may not be IP (must be zero in
0156          * this case).
0157          */
0158         uint64_t not_IP:1;
0159         /*
0160          * The receive interface hardware detected a receive
0161          * error (must be zero in this case).
0162          */
0163         uint64_t rcv_error:1;
0164         /* lower err_code = first-level descriptor of the
0165          * work */
0166         /* zero for packet submitted by hardware that isn't on
0167          * the slow path */
0168         /* type is cvmx_pip_err_t */
0169         uint64_t err_code:8;
0170 #else
0171             uint64_t err_code:8;
0172             uint64_t rcv_error:1;
0173             uint64_t not_IP:1;
0174             uint64_t is_mcast:1;
0175             uint64_t is_bcast:1;
0176             uint64_t IP_exc:1;
0177             uint64_t is_frag:1;
0178             uint64_t L4_error:1;
0179             uint64_t software:1;
0180             uint64_t is_v6:1;
0181             uint64_t dec_ipsec:1;
0182             uint64_t tcp_or_udp:1;
0183             uint64_t dec_ipcomp:1;
0184             uint64_t unassigned2:4;
0185             uint64_t unassigned2a:4;
0186             uint64_t pr:4;
0187             uint64_t vlan_id:12;
0188             uint64_t vlan_cfi:1;
0189             uint64_t unassigned:1;
0190             uint64_t vlan_stacked:1;
0191             uint64_t vlan_valid:1;
0192             uint64_t ip_offset:8;
0193             uint64_t bufs:8;
0194 #endif
0195     } s;
0196     struct {
0197 #ifdef __BIG_ENDIAN_BITFIELD
0198         uint64_t bufs:8;
0199         uint64_t ip_offset:8;
0200         uint64_t vlan_valid:1;
0201         uint64_t vlan_stacked:1;
0202         uint64_t unassigned:1;
0203         uint64_t vlan_cfi:1;
0204         uint64_t vlan_id:12;
0205         uint64_t port:12;       /* MAC/PIP port number. */
0206         uint64_t dec_ipcomp:1;
0207         uint64_t tcp_or_udp:1;
0208         uint64_t dec_ipsec:1;
0209         uint64_t is_v6:1;
0210         uint64_t software:1;
0211         uint64_t L4_error:1;
0212         uint64_t is_frag:1;
0213         uint64_t IP_exc:1;
0214         uint64_t is_bcast:1;
0215         uint64_t is_mcast:1;
0216         uint64_t not_IP:1;
0217         uint64_t rcv_error:1;
0218         uint64_t err_code:8;
0219 #else
0220         uint64_t err_code:8;
0221         uint64_t rcv_error:1;
0222         uint64_t not_IP:1;
0223         uint64_t is_mcast:1;
0224         uint64_t is_bcast:1;
0225         uint64_t IP_exc:1;
0226         uint64_t is_frag:1;
0227         uint64_t L4_error:1;
0228         uint64_t software:1;
0229         uint64_t is_v6:1;
0230         uint64_t dec_ipsec:1;
0231         uint64_t tcp_or_udp:1;
0232         uint64_t dec_ipcomp:1;
0233         uint64_t port:12;
0234         uint64_t vlan_id:12;
0235         uint64_t vlan_cfi:1;
0236         uint64_t unassigned:1;
0237         uint64_t vlan_stacked:1;
0238         uint64_t vlan_valid:1;
0239         uint64_t ip_offset:8;
0240         uint64_t bufs:8;
0241 #endif
0242     } s_cn68xx;
0243 
0244     /* use this to get at the 16 vlan bits */
0245     struct {
0246 #ifdef __BIG_ENDIAN_BITFIELD
0247         uint64_t unused1:16;
0248         uint64_t vlan:16;
0249         uint64_t unused2:32;
0250 #else
0251             uint64_t unused2:32;
0252             uint64_t vlan:16;
0253             uint64_t unused1:16;
0254 
0255 #endif
0256     } svlan;
0257 
0258     /*
0259      * use this struct if the hardware could not determine that
0260      * the packet is ip.
0261      */
0262     struct {
0263 #ifdef __BIG_ENDIAN_BITFIELD
0264         /*
0265          * HW sets this to the number of buffers used by this
0266          * packet.
0267          */
0268         uint64_t bufs:8;
0269         uint64_t unused:8;
0270         /* set to 1 if we found DSA/VLAN in the L2 */
0271         uint64_t vlan_valid:1;
0272         /* Set to 1 if the DSA/VLAN tag is stacked */
0273         uint64_t vlan_stacked:1;
0274         uint64_t unassigned:1;
0275         /*
0276          * HW sets to the DSA/VLAN CFI flag (valid when
0277          * vlan_valid)
0278          */
0279         uint64_t vlan_cfi:1;
0280         /*
0281          * HW sets to the DSA/VLAN_ID field (valid when
0282          * vlan_valid).
0283          */
0284         uint64_t vlan_id:12;
0285         /*
0286          * Ring Identifier (if PCIe). Requires
0287          * PIP_GBL_CTL[RING_EN]=1
0288          */
0289         uint64_t pr:4;
0290         uint64_t unassigned2:12;
0291         /*
0292          * reserved for software use, hardware will clear on
0293          * packet creation.
0294          */
0295         uint64_t software:1;
0296         uint64_t unassigned3:1;
0297         /*
0298          * set if the hardware determined that the packet is
0299          * rarp.
0300          */
0301         uint64_t is_rarp:1;
0302         /*
0303          * set if the hardware determined that the packet is
0304          * arp
0305          */
0306         uint64_t is_arp:1;
0307         /*
0308          * set if the hardware determined that the packet is a
0309          * broadcast.
0310          */
0311         uint64_t is_bcast:1;
0312         /*
0313          * set if the hardware determined that the packet is a
0314          * multi-cast
0315          */
0316         uint64_t is_mcast:1;
0317         /*
0318          * set if the packet may not be IP (must be one in
0319          * this case)
0320          */
0321         uint64_t not_IP:1;
0322         /* The receive interface hardware detected a receive
0323          * error.  Failure indicated in err_code below,
0324          * decode:
0325          *
0326          * - 1 = partial error: a packet was partially
0327          *   received, but internal buffering / bandwidth
0328          *   was not adequate to receive the entire
0329          *   packet.
0330          * - 2 = jabber error: the RGMII packet was too large
0331          *   and is truncated.
0332          * - 3 = overrun error: the RGMII packet is longer
0333          *   than allowed and had an FCS error.
0334          * - 4 = oversize error: the RGMII packet is longer
0335          *   than allowed.
0336          * - 5 = alignment error: the RGMII packet is not an
0337          *   integer number of bytes
0338          *   and had an FCS error (100M and 10M only).
0339          * - 6 = fragment error: the RGMII packet is shorter
0340          *   than allowed and had an FCS error.
0341          * - 7 = GMX FCS error: the RGMII packet had an FCS
0342          *   error.
0343          * - 8 = undersize error: the RGMII packet is shorter
0344          *   than allowed.
0345          * - 9 = extend error: the RGMII packet had an extend
0346          *   error.
0347          * - 10 = length mismatch error: the RGMII packet had
0348          *    a length that did not match the length field
0349          *    in the L2 HDR.
0350          * - 11 = RGMII RX error/SPI4 DIP4 Error: the RGMII
0351          *    packet had one or more data reception errors
0352          *    (RXERR) or the SPI4 packet had one or more
0353          *    DIP4 errors.
0354          * - 12 = RGMII skip error/SPI4 Abort Error: the RGMII
0355          *    packet was not large enough to cover the
0356          *    skipped bytes or the SPI4 packet was
0357          *    terminated with an About EOPS.
0358          * - 13 = RGMII nibble error/SPI4 Port NXA Error: the
0359          *    RGMII packet had a studder error (data not
0360          *    repeated - 10/100M only) or the SPI4 packet
0361          *    was sent to an NXA.
0362          * - 16 = FCS error: a SPI4.2 packet had an FCS error.
0363          * - 17 = Skip error: a packet was not large enough to
0364          *    cover the skipped bytes.
0365          * - 18 = L2 header malformed: the packet is not long
0366          *    enough to contain the L2.
0367          */
0368 
0369         uint64_t rcv_error:1;
0370         /*
0371          * lower err_code = first-level descriptor of the
0372          * work
0373          */
0374         /*
0375          * zero for packet submitted by hardware that isn't on
0376          * the slow path
0377          */
0378         /* type is cvmx_pip_err_t (union, so can't use directly */
0379         uint64_t err_code:8;
0380 #else
0381             uint64_t err_code:8;
0382             uint64_t rcv_error:1;
0383             uint64_t not_IP:1;
0384             uint64_t is_mcast:1;
0385             uint64_t is_bcast:1;
0386             uint64_t is_arp:1;
0387             uint64_t is_rarp:1;
0388             uint64_t unassigned3:1;
0389             uint64_t software:1;
0390             uint64_t unassigned2:4;
0391             uint64_t unassigned2a:8;
0392             uint64_t pr:4;
0393             uint64_t vlan_id:12;
0394             uint64_t vlan_cfi:1;
0395             uint64_t unassigned:1;
0396             uint64_t vlan_stacked:1;
0397             uint64_t vlan_valid:1;
0398             uint64_t unused:8;
0399             uint64_t bufs:8;
0400 #endif
0401     } snoip;
0402 
0403 } cvmx_pip_wqe_word2;
0404 
0405 union cvmx_pip_wqe_word0 {
0406     struct {
0407 #ifdef __BIG_ENDIAN_BITFIELD
0408         /**
0409          * raw chksum result generated by the HW
0410          */
0411         uint16_t hw_chksum;
0412         /**
0413          * Field unused by hardware - available for software
0414          */
0415         uint8_t unused;
0416         /**
0417          * Next pointer used by hardware for list maintenance.
0418          * May be written/read by HW before the work queue
0419          * entry is scheduled to a PP (Only 36 bits used in
0420          * Octeon 1)
0421          */
0422         uint64_t next_ptr:40;
0423 #else
0424         uint64_t next_ptr:40;
0425         uint8_t unused;
0426         uint16_t hw_chksum;
0427 #endif
0428     } cn38xx;
0429     struct {
0430 #ifdef __BIG_ENDIAN_BITFIELD
0431         uint64_t l4ptr:8;       /* 56..63 */
0432         uint64_t unused0:8;     /* 48..55 */
0433         uint64_t l3ptr:8;       /* 40..47 */
0434         uint64_t l2ptr:8;       /* 32..39 */
0435         uint64_t unused1:18;    /* 14..31 */
0436         uint64_t bpid:6;        /* 8..13 */
0437         uint64_t unused2:2;     /* 6..7 */
0438         uint64_t pknd:6;        /* 0..5 */
0439 #else
0440         uint64_t pknd:6;        /* 0..5 */
0441         uint64_t unused2:2;     /* 6..7 */
0442         uint64_t bpid:6;        /* 8..13 */
0443         uint64_t unused1:18;    /* 14..31 */
0444         uint64_t l2ptr:8;       /* 32..39 */
0445         uint64_t l3ptr:8;       /* 40..47 */
0446         uint64_t unused0:8;     /* 48..55 */
0447         uint64_t l4ptr:8;       /* 56..63 */
0448 #endif
0449     } cn68xx;
0450 };
0451 
0452 union cvmx_wqe_word0 {
0453     uint64_t u64;
0454     union cvmx_pip_wqe_word0 pip;
0455 };
0456 
0457 union cvmx_wqe_word1 {
0458     uint64_t u64;
0459     struct {
0460 #ifdef __BIG_ENDIAN_BITFIELD
0461         uint64_t len:16;
0462         uint64_t varies:14;
0463         /**
0464          * the type of the tag (ORDERED, ATOMIC, NULL)
0465          */
0466         uint64_t tag_type:2;
0467         uint64_t tag:32;
0468 #else
0469         uint64_t tag:32;
0470         uint64_t tag_type:2;
0471         uint64_t varies:14;
0472         uint64_t len:16;
0473 #endif
0474     };
0475     struct {
0476 #ifdef __BIG_ENDIAN_BITFIELD
0477         uint64_t len:16;
0478         uint64_t zero_0:1;
0479         /**
0480          * HW sets this to what it thought the priority of
0481          * the input packet was
0482          */
0483         uint64_t qos:3;
0484 
0485         uint64_t zero_1:1;
0486         /**
0487          * the group that the work queue entry will be scheduled to
0488          */
0489         uint64_t grp:6;
0490         uint64_t zero_2:3;
0491         uint64_t tag_type:2;
0492         uint64_t tag:32;
0493 #else
0494         uint64_t tag:32;
0495         uint64_t tag_type:2;
0496         uint64_t zero_2:3;
0497         uint64_t grp:6;
0498         uint64_t zero_1:1;
0499         uint64_t qos:3;
0500         uint64_t zero_0:1;
0501         uint64_t len:16;
0502 #endif
0503     } cn68xx;
0504     struct {
0505 #ifdef __BIG_ENDIAN_BITFIELD
0506         /**
0507          * HW sets to the total number of bytes in the packet
0508          */
0509         uint64_t len:16;
0510         /**
0511          * HW sets this to input physical port
0512          */
0513         uint64_t ipprt:6;
0514 
0515         /**
0516          * HW sets this to what it thought the priority of
0517          * the input packet was
0518          */
0519         uint64_t qos:3;
0520 
0521         /**
0522          * the group that the work queue entry will be scheduled to
0523          */
0524         uint64_t grp:4;
0525         /**
0526          * the type of the tag (ORDERED, ATOMIC, NULL)
0527          */
0528         uint64_t tag_type:3;
0529         /**
0530          * the synchronization/ordering tag
0531          */
0532         uint64_t tag:32;
0533 #else
0534         uint64_t tag:32;
0535         uint64_t tag_type:2;
0536         uint64_t zero_2:1;
0537         uint64_t grp:4;
0538         uint64_t qos:3;
0539         uint64_t ipprt:6;
0540         uint64_t len:16;
0541 #endif
0542     } cn38xx;
0543 };
0544 
0545 /**
0546  * Work queue entry format
0547  *
0548  * must be 8-byte aligned
0549  */
0550 struct cvmx_wqe {
0551 
0552     /*****************************************************************
0553      * WORD 0
0554      *  HW WRITE: the following 64 bits are filled by HW when a packet arrives
0555      */
0556     union cvmx_wqe_word0 word0;
0557 
0558     /*****************************************************************
0559      * WORD 1
0560      *  HW WRITE: the following 64 bits are filled by HW when a packet arrives
0561      */
0562     union cvmx_wqe_word1 word1;
0563 
0564     /**
0565      * WORD 2 HW WRITE: the following 64-bits are filled in by
0566      *   hardware when a packet arrives This indicates a variety of
0567      *   status and error conditions.
0568      */
0569     cvmx_pip_wqe_word2 word2;
0570 
0571     /**
0572      * Pointer to the first segment of the packet.
0573      */
0574     union cvmx_buf_ptr packet_ptr;
0575 
0576     /**
0577      *   HW WRITE: octeon will fill in a programmable amount from the
0578      *         packet, up to (at most, but perhaps less) the amount
0579      *         needed to fill the work queue entry to 128 bytes
0580      *
0581      *   If the packet is recognized to be IP, the hardware starts
0582      *   (except that the IPv4 header is padded for appropriate
0583      *   alignment) writing here where the IP header starts.  If the
0584      *   packet is not recognized to be IP, the hardware starts
0585      *   writing the beginning of the packet here.
0586      */
0587     uint8_t packet_data[96];
0588 
0589     /**
0590      * If desired, SW can make the work Q entry any length. For the
0591      * purposes of discussion here, Assume 128B always, as this is all that
0592      * the hardware deals with.
0593      *
0594      */
0595 
0596 } CVMX_CACHE_LINE_ALIGNED;
0597 
0598 static inline int cvmx_wqe_get_port(struct cvmx_wqe *work)
0599 {
0600     int port;
0601 
0602     if (octeon_has_feature(OCTEON_FEATURE_CN68XX_WQE))
0603         port = work->word2.s_cn68xx.port;
0604     else
0605         port = work->word1.cn38xx.ipprt;
0606 
0607     return port;
0608 }
0609 
0610 static inline void cvmx_wqe_set_port(struct cvmx_wqe *work, int port)
0611 {
0612     if (octeon_has_feature(OCTEON_FEATURE_CN68XX_WQE))
0613         work->word2.s_cn68xx.port = port;
0614     else
0615         work->word1.cn38xx.ipprt = port;
0616 }
0617 
0618 static inline int cvmx_wqe_get_grp(struct cvmx_wqe *work)
0619 {
0620     int grp;
0621 
0622     if (octeon_has_feature(OCTEON_FEATURE_CN68XX_WQE))
0623         grp = work->word1.cn68xx.grp;
0624     else
0625         grp = work->word1.cn38xx.grp;
0626 
0627     return grp;
0628 }
0629 
0630 static inline void cvmx_wqe_set_grp(struct cvmx_wqe *work, int grp)
0631 {
0632     if (octeon_has_feature(OCTEON_FEATURE_CN68XX_WQE))
0633         work->word1.cn68xx.grp = grp;
0634     else
0635         work->word1.cn38xx.grp = grp;
0636 }
0637 
0638 static inline int cvmx_wqe_get_qos(struct cvmx_wqe *work)
0639 {
0640     int qos;
0641 
0642     if (octeon_has_feature(OCTEON_FEATURE_CN68XX_WQE))
0643         qos = work->word1.cn68xx.qos;
0644     else
0645         qos = work->word1.cn38xx.qos;
0646 
0647     return qos;
0648 }
0649 
0650 static inline void cvmx_wqe_set_qos(struct cvmx_wqe *work, int qos)
0651 {
0652     if (octeon_has_feature(OCTEON_FEATURE_CN68XX_WQE))
0653         work->word1.cn68xx.qos = qos;
0654     else
0655         work->word1.cn38xx.qos = qos;
0656 }
0657 
0658 #endif /* __CVMX_WQE_H__ */