root/sys/dev/dpaa2/dpaa2_ni.h
/*-
 * SPDX-License-Identifier: BSD-2-Clause
 *
 * Copyright © 2021-2023 Dmitry Salychev
 * Copyright © 2022 Mathew McBride
 *
 * Redistribution and use in source and binary forms, with or without
 * modification, are permitted provided that the following conditions
 * are met:
 * 1. Redistributions of source code must retain the above copyright
 *    notice, this list of conditions and the following disclaimer.
 * 2. Redistributions in binary form must reproduce the above copyright
 *    notice, this list of conditions and the following disclaimer in the
 *    documentation and/or other materials provided with the distribution.
 *
 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
 * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
 * SUCH DAMAGE.
 */

#ifndef _DPAA2_NI_H
#define _DPAA2_NI_H

#include <sys/rman.h>
#include <sys/bus.h>
#include <sys/queue.h>
#include <sys/taskqueue.h>
#include <sys/mbuf.h>
#include <sys/param.h>
#include <sys/socket.h>
#include <sys/buf_ring.h>
#include <sys/proc.h>
#include <sys/lock.h>
#include <sys/mutex.h>

#include <net/if.h>
#include <net/ethernet.h>
#include <net/if_media.h>

#include "dpaa2_types.h"
#include "dpaa2_mcp.h"
#include "dpaa2_swp.h"
#include "dpaa2_io.h"
#include "dpaa2_mac.h"
#include "dpaa2_ni_dpkg.h"
#include "dpaa2_channel.h"

/* Name of the DPAA2 network interface. */
#define DPAA2_NI_IFNAME         "dpni"

/* Maximum resources per DPNI: 16 DPIOs + 16 DPCONs + 1 DPBP + 1 DPMCP. */
#define DPAA2_NI_MAX_RESOURCES  34

#define DPAA2_NI_MSI_COUNT      1  /* MSIs per DPNI */
#define DPAA2_NI_MAX_POOLS      8  /* buffer pools per DPNI */

#define DPAA2_NI_BUFS_INIT      (5u * DPAA2_SWP_BUFS_PER_CMD)

/* Maximum number of buffers allocated per Tx ring. */
#define DPAA2_NI_BUFS_PER_TX    (1 << 7)
#define DPAA2_NI_MAX_BPTX       (1 << 8)

/* Number of the DPNI statistics counters. */
#define DPAA2_NI_STAT_COUNTERS  7u
#define DPAA2_NI_STAT_SYSCTLS   9u

/* Error and status bits in the frame annotation status word. */
#define DPAA2_NI_FAS_DISC       0x80000000 /* debug frame */
#define DPAA2_NI_FAS_MS         0x40000000 /* MACSEC frame */
#define DPAA2_NI_FAS_PTP        0x08000000
#define DPAA2_NI_FAS_MC         0x04000000 /* Ethernet multicast frame */
#define DPAA2_NI_FAS_BC         0x02000000 /* Ethernet broadcast frame */
#define DPAA2_NI_FAS_KSE        0x00040000
#define DPAA2_NI_FAS_EOFHE      0x00020000
#define DPAA2_NI_FAS_MNLE       0x00010000
#define DPAA2_NI_FAS_TIDE       0x00008000
#define DPAA2_NI_FAS_PIEE       0x00004000
#define DPAA2_NI_FAS_FLE        0x00002000 /* Frame length error */
#define DPAA2_NI_FAS_FPE        0x00001000 /* Frame physical error */
#define DPAA2_NI_FAS_PTE        0x00000080
#define DPAA2_NI_FAS_ISP        0x00000040
#define DPAA2_NI_FAS_PHE        0x00000020
#define DPAA2_NI_FAS_BLE        0x00000010
#define DPAA2_NI_FAS_L3CV       0x00000008 /* L3 csum validation performed */
#define DPAA2_NI_FAS_L3CE       0x00000004 /* L3 csum error */
#define DPAA2_NI_FAS_L4CV       0x00000002 /* L4 csum validation performed */
#define DPAA2_NI_FAS_L4CE       0x00000001 /* L4 csum error */

/* Mask for errors on the ingress path. */
#define DPAA2_NI_FAS_RX_ERR_MASK (DPAA2_NI_FAS_KSE |    \
    DPAA2_NI_FAS_EOFHE |                                \
    DPAA2_NI_FAS_MNLE |                                 \
    DPAA2_NI_FAS_TIDE |                                 \
    DPAA2_NI_FAS_PIEE |                                 \
    DPAA2_NI_FAS_FLE |                                  \
    DPAA2_NI_FAS_FPE |                                  \
    DPAA2_NI_FAS_PTE |                                  \
    DPAA2_NI_FAS_ISP |                                  \
    DPAA2_NI_FAS_PHE |                                  \
    DPAA2_NI_FAS_BLE |                                  \
    DPAA2_NI_FAS_L3CE |                                 \
    DPAA2_NI_FAS_L4CE                                   \
)

/* Option bits to select specific queue configuration options to apply. */
#define DPAA2_NI_QUEUE_OPT_USER_CTX     0x00000001
#define DPAA2_NI_QUEUE_OPT_DEST         0x00000002
#define DPAA2_NI_QUEUE_OPT_FLC          0x00000004
#define DPAA2_NI_QUEUE_OPT_HOLD_ACTIVE  0x00000008
#define DPAA2_NI_QUEUE_OPT_SET_CGID     0x00000040
#define DPAA2_NI_QUEUE_OPT_CLEAR_CGID   0x00000080

/* DPNI link configuration options. */
#define DPAA2_NI_LINK_OPT_AUTONEG       ((uint64_t) 0x01u)
#define DPAA2_NI_LINK_OPT_HALF_DUPLEX   ((uint64_t) 0x02u)
#define DPAA2_NI_LINK_OPT_PAUSE         ((uint64_t) 0x04u)
#define DPAA2_NI_LINK_OPT_ASYM_PAUSE    ((uint64_t) 0x08u)
#define DPAA2_NI_LINK_OPT_PFC_PAUSE     ((uint64_t) 0x10u)

/*
 * Number of times to retry a frame enqueue before giving up. Value determined
 * empirically, in order to minimize the number of frames dropped on Tx.
 */
#define DPAA2_NI_ENQUEUE_RETRIES        10

/* Channel storage buffer configuration */
#define DPAA2_ETH_STORE_FRAMES          16u
#define DPAA2_ETH_STORE_SIZE \
        ((DPAA2_ETH_STORE_FRAMES + 1) * sizeof(struct dpaa2_dq))

/*
 * NOTE: Don't forget to update dpaa2_ni_spec in case of any changes in macros!
 */
/* DPMCP resources */
#define DPAA2_NI_MCP_RES_NUM    (1u)
#define DPAA2_NI_MCP_RID_OFF    (0u)
#define DPAA2_NI_MCP_RID(rid)   ((rid) + DPAA2_NI_MCP_RID_OFF)
/* DPIO resources (software portals) */
#define DPAA2_NI_IO_RES_NUM     (16u)
#define DPAA2_NI_IO_RID_OFF     (DPAA2_NI_MCP_RID_OFF + DPAA2_NI_MCP_RES_NUM)
#define DPAA2_NI_IO_RID(rid)    ((rid) + DPAA2_NI_IO_RID_OFF)
/* DPBP resources (buffer pools) */
#define DPAA2_NI_BP_RES_NUM     (1u)
#define DPAA2_NI_BP_RID_OFF     (DPAA2_NI_IO_RID_OFF + DPAA2_NI_IO_RES_NUM)
#define DPAA2_NI_BP_RID(rid)    ((rid) + DPAA2_NI_BP_RID_OFF)
/* DPCON resources (channels) */
#define DPAA2_NI_CON_RES_NUM    (16u)
#define DPAA2_NI_CON_RID_OFF    (DPAA2_NI_BP_RID_OFF + DPAA2_NI_BP_RES_NUM)
#define DPAA2_NI_CON_RID(rid)   ((rid) + DPAA2_NI_CON_RID_OFF)

enum dpaa2_ni_dest_type {
        DPAA2_NI_DEST_NONE = 0,
        DPAA2_NI_DEST_DPIO,
        DPAA2_NI_DEST_DPCON
};

enum dpaa2_ni_ofl_type {
        DPAA2_NI_OFL_RX_L3_CSUM = 0,
        DPAA2_NI_OFL_RX_L4_CSUM,
        DPAA2_NI_OFL_TX_L3_CSUM,
        DPAA2_NI_OFL_TX_L4_CSUM,
        DPAA2_NI_OFL_FLCTYPE_HASH /* FD flow context for AIOP/CTLU */
};

/**
 * @brief DPNI ingress traffic distribution mode.
 */
enum dpaa2_ni_dist_mode {
        DPAA2_NI_DIST_MODE_NONE = 0,
        DPAA2_NI_DIST_MODE_HASH,
        DPAA2_NI_DIST_MODE_FS
};

/**
 * @brief DPNI behavior in case of errors.
 */
enum dpaa2_ni_err_action {
        DPAA2_NI_ERR_DISCARD = 0,
        DPAA2_NI_ERR_CONTINUE,
        DPAA2_NI_ERR_SEND_TO_ERROR_QUEUE
};

struct dpaa2_channel;
struct dpaa2_ni_fq;

/**
 * @brief Attributes of the DPNI object.
 *
 * options:      ...
 * wriop_ver:    Revision of the underlying WRIOP hardware block.
 */
struct dpaa2_ni_attr {
        uint32_t                 options;
        uint16_t                 wriop_ver;
        struct {
                uint16_t         fs;
                uint8_t          mac;
                uint8_t          vlan;
                uint8_t          qos;
        } entries;
        struct {
                uint8_t          queues;
                uint8_t          rx_tcs;
                uint8_t          tx_tcs;
                uint8_t          channels;
                uint8_t          cgs;
        } num;
        struct {
                uint8_t          fs;
                uint8_t          qos;
        } key_size;
};

/**
 * @brief Configuration of the network interface queue.
 *
 * NOTE: This configuration is used to obtain information of a queue by
 *       DPNI_GET_QUEUE command and update it by DPNI_SET_QUEUE one.
 *
 * It includes binding of the queue to a DPIO or DPCON object to receive
 * notifications and traffic on the CPU.
 *
 * user_ctx:    (r/w) User defined data, presented along with the frames
 *              being dequeued from this queue.
 * flow_ctx:    (r/w) Set default FLC value for traffic dequeued from this queue.
 *              Please check description of FD structure for more information.
 *              Note that FLC values set using DPNI_ADD_FS_ENTRY, if any, take
 *              precedence over values per queue.
 * dest_id:     (r/w) The ID of a DPIO or DPCON object, depending on
 *              DEST_TYPE (in flags) value. This field is ignored for DEST_TYPE
 *              set to 0 (DPNI_DEST_NONE).
 * fqid:        (r) Frame queue ID, can be used to enqueue/dequeue or execute
 *              other commands on the queue through DPIO. Note that Tx queues
 *              are logical queues and not all management commands are available
 *              on these queue types.
 * qdbin:       (r) Queue destination bin. Can be used with the DPIO enqueue
 *              operation based on QDID, QDBIN and QPRI.
 * type:        Type of the queue to set configuration to.
 * tc:          Traffic class. Ignored for QUEUE_TYPE 2 and 3 (Tx confirmation
 *              and Rx error queues).
 * idx:         Selects a specific queue out of the set of queues in a TC.
 *              Accepted values are in range 0 to NUM_QUEUES–1. This field is
 *              ignored for QUEUE_TYPE 3 (Rx error queue). For access to the
 *              shared Tx confirmation queue (for Tx confirmation mode 1), this
 *              field must be set to 0xff.
 * cgid:        (r/w) Congestion group ID.
 * chan_id:     (w) Channel index to be configured. Used only when QUEUE_TYPE is
 *              set to DPNI_QUEUE_TX.
 * priority:    (r/w) Sets the priority in the destination DPCON or DPIO for
 *              dequeued traffic. Supported values are 0 to # of priorities in
 *              destination DPCON or DPIO - 1. This field is ignored for
 *              DEST_TYPE set to 0 (DPNI_DEST_NONE), except if this DPNI is in
 *              AIOP context. In that case the DPNI_SET_QUEUE can be used to
 *              override the default assigned priority of the FQ from the TC.
 * options:     Option bits selecting specific configuration options to apply.
 *              See DPAA2_NI_QUEUE_OPT_* for details.
 * dest_type:   Type of destination for dequeued traffic.
 * cgid_valid:  (r) Congestion group ID is valid.
 * stash_control: (r/w) If true, lowest 6 bits of FLC are used for stash control.
 *              Please check description of FD structure for more information.
 * hold_active: (r/w) If true, this flag prevents the queue from being
 *              rescheduled between DPIOs while it carries traffic and is active
 *              on one DPIO. Can help reduce reordering if one queue is services
 *              on multiple CPUs, but the queue is also more likely to be trapped
 *              in one DPIO, especially when congested.
 */
struct dpaa2_ni_queue_cfg {
        uint64_t                 user_ctx;
        uint64_t                 flow_ctx;
        uint32_t                 dest_id;
        uint32_t                 fqid;
        uint16_t                 qdbin;
        enum dpaa2_ni_queue_type type;
        uint8_t                  tc;
        uint8_t                  idx;
        uint8_t                  cgid;
        uint8_t                  chan_id;
        uint8_t                  priority;
        uint8_t                  options;

        enum dpaa2_ni_dest_type  dest_type;
        bool                     cgid_valid;
        bool                     stash_control;
        bool                     hold_active;
};

/**
 * @brief Buffer layout attributes.
 *
 * pd_size:             Size kept for private data (in bytes).
 * fd_align:            Frame data alignment.
 * head_size:           Data head room.
 * tail_size:           Data tail room.
 * options:             ...
 * pass_timestamp:      Timestamp is included in the buffer layout.
 * pass_parser_result:  Parsing results are included in the buffer layout.
 * pass_frame_status:   Frame status is included in the buffer layout.
 * pass_sw_opaque:      SW annotation is activated.
 * queue_type:          Type of a queue this configuration applies to.
 */
struct dpaa2_ni_buf_layout {
        uint16_t        pd_size;
        uint16_t        fd_align;
        uint16_t        head_size;
        uint16_t        tail_size;
        uint16_t        options;
        bool            pass_timestamp;
        bool            pass_parser_result;
        bool            pass_frame_status;
        bool            pass_sw_opaque;
        enum dpaa2_ni_queue_type queue_type;
};

/**
 * @brief Buffer pools configuration for a network interface.
 */
struct dpaa2_ni_pools_cfg {
        uint8_t         pools_num;
        struct {
                uint32_t bp_obj_id;
                uint16_t buf_sz;
                int      backup_flag; /* 0 - regular pool, 1 - backup pool */
        } pools[DPAA2_NI_MAX_POOLS];
};

/**
 * @brief Errors behavior configuration for a network interface.
 *
 * err_mask:            The errors mask to configure.
 * action:              Desired action for the errors selected in the mask.
 * set_err_fas:         Set to true to mark the errors in frame annotation
 *                      status (FAS); relevant for non-discard actions only.
 */
struct dpaa2_ni_err_cfg {
        uint32_t        err_mask;
        enum dpaa2_ni_err_action action;
        bool            set_err_fas;
};

/**
 * @brief Link configuration.
 *
 * options:     Mask of available options.
 * adv_speeds:  Speeds that are advertised for autoneg.
 * rate:        Rate in Mbps.
 */
struct dpaa2_ni_link_cfg {
        uint64_t        options;
        uint64_t        adv_speeds;
        uint32_t        rate;
};

/**
 * @brief Link state.
 *
 * options:     Mask of available options.
 * adv_speeds:  Speeds that are advertised for autoneg.
 * sup_speeds:  Speeds capability of the PHY.
 * rate:        Rate in Mbps.
 * link_up:     Link state (true if link is up, false otherwise).
 * state_valid: Ignore/Update the state of the link.
 */
struct dpaa2_ni_link_state {
        uint64_t        options;
        uint64_t        adv_speeds;
        uint64_t        sup_speeds;
        uint32_t        rate;
        bool            link_up;
        bool            state_valid;
};

/**
 * @brief QoS table configuration.
 *
 * kcfg_busaddr:        Address of the buffer in I/O virtual address space which
 *                      holds the QoS table key configuration.
 * default_tc:          Default traffic class to use in case of a lookup miss in
 *                      the QoS table.
 * discard_on_miss:     Set to true to discard frames in case of no match.
 *                      Default traffic class will be used otherwise.
 * keep_entries:        Set to true to keep existing QoS table entries. This
 *                      option will work properly only for DPNI objects created
 *                      with DPNI_OPT_HAS_KEY_MASKING option.
 */
struct dpaa2_ni_qos_table {
        uint64_t        kcfg_busaddr;
        uint8_t         default_tc;
        bool            discard_on_miss;
        bool            keep_entries;
};

/**
 * @brief Context to add multicast physical addresses to the filter table.
 *
 * ifp:         Network interface associated with the context.
 * error:       Result of the last MC command.
 * nent:        Number of entries added.
 */
struct dpaa2_ni_mcaddr_ctx {
        struct ifnet    *ifp;
        int              error;
        int              nent;
};

struct dpaa2_eth_dist_fields {
        uint64_t        rxnfc_field;
        enum net_prot   cls_prot;
        int             cls_field;
        int             size;
        uint64_t        id;
};

struct dpni_mask_cfg {
        uint8_t         mask;
        uint8_t         offset;
} __packed;

struct dpni_dist_extract {
        uint8_t         prot;
        uint8_t         efh_type; /* EFH type is in the 4 LSBs. */
        uint8_t         size;
        uint8_t         offset;
        uint32_t        field;
        uint8_t         hdr_index;
        uint8_t         constant;
        uint8_t         num_of_repeats;
        uint8_t         num_of_byte_masks;
        uint8_t         extract_type; /* Extraction type is in the 4 LSBs */
        uint8_t         _reserved[3];
        struct dpni_mask_cfg masks[4];
} __packed;

struct dpni_ext_set_rx_tc_dist {
        uint8_t         num_extracts;
        uint8_t         _reserved[7];
        struct dpni_dist_extract extracts[DPKG_MAX_NUM_OF_EXTRACTS];
} __packed;

/**
 * @brief Software context for the DPAA2 Network Interface driver.
 */
struct dpaa2_ni_softc {
        device_t                 dev;
        struct resource         *res[DPAA2_NI_MAX_RESOURCES];
        uint16_t                 api_major;
        uint16_t                 api_minor;
        uint64_t                 rx_hash_fields;
        uint16_t                 tx_data_off;
        uint16_t                 tx_qdid;
        uint32_t                 link_options;
        int                      link_state;

        uint16_t                 buf_align;
        uint16_t                 buf_sz;

        uint64_t                 rx_anomaly_frames;
        uint64_t                 rx_single_buf_frames;
        uint64_t                 rx_sg_buf_frames;
        uint64_t                 rx_enq_rej_frames;
        uint64_t                 rx_ieoi_err_frames;
        uint64_t                 tx_single_buf_frames;
        uint64_t                 tx_sg_frames;

        struct dpaa2_ni_attr     attr;

        struct ifnet            *ifp;
        uint32_t                 if_flags;
        struct mtx               lock;
        device_t                 miibus;
        struct mii_data         *mii;
        bool                     fixed_link;
        struct ifmedia           fixed_ifmedia;
        int                      media_status;

        bus_dma_tag_t            rxd_dmat; /* for Rx distribution key */
        bus_dma_tag_t            qos_dmat; /* for QoS table key */

        struct dpaa2_buf         qos_kcfg; /* QoS table key config */
        struct dpaa2_buf         rxd_kcfg; /* Rx distribution key config */

        uint32_t                 chan_n;
        struct dpaa2_channel    *channels[DPAA2_MAX_CHANNELS];
        struct dpaa2_ni_fq       rxe_queue; /* one per DPNI */

        /* sysctl(9) */
        struct dpaa2_atomic      buf_num;
        struct dpaa2_atomic      buf_free;

        int                      irq_rid[DPAA2_NI_MSI_COUNT];
        struct resource         *irq_res;
        void                    *intr;

        struct taskqueue        *bp_taskq;

        struct callout           mii_callout;

        struct {
                uint32_t         dpmac_id;
                uint8_t          addr[ETHER_ADDR_LEN];
                device_t         phy_dev;
                int              phy_loc;
        } mac; /* Info about connected DPMAC (if exists) */
};

extern struct resource_spec dpaa2_ni_spec[];

#endif /* _DPAA2_NI_H */