root/sys/dev/dpaa/qman.h
/*-
 * Copyright (c) 2011-2012 Semihalf.
 * All rights reserved.
 *
 * 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 _QMAN_H
#define _QMAN_H

#include <sys/vmem.h>
#include <machine/vmparam.h>

struct qman_fq;
struct qman_fq;
struct dpaa_fd;
struct qman_portal;

/**
 * @group QMan private defines/declarations
 * @{
 */
/**
 * Maximum number of frame queues in all QMans.
 */
#define         QMAN_MAX_FQIDS                  16

/**
 * Pool channel common to all software portals.
 * @note Value of 0 reflects the e_QM_FQ_CHANNEL_POOL1 from e_QmFQChannel
 *       type used in qman_fq_create().
 */
#define         QMAN_COMMON_POOL_CHANNEL        0

#define         QMAN_FQID_BASE                  1

/* Counters */
#define QMAN_COUNTER_FRAME      0
#define QMAN_COUNTER_BYTES      1

/*
 * Portal defines
 */
#define QMAN_CE_PA(base)        (base)
#define QMAN_CI_PA(base)        ((base) + 0x100000)

#define QMAN_PORTAL_CE_PA(base, n)      \
    (QMAN_CE_PA(base) + ((n) * QMAN_PORTAL_CE_SIZE))
#define QMAN_PORTAL_CI_PA(base, n)      \
    (QMAN_CI_PA(base) + ((n) * QMAN_PORTAL_CI_SIZE))

struct qman_softc {
        device_t        sc_dev;                 /* device handle */
        int             sc_rrid;                /* register rid */
        struct resource *sc_rres;               /* register resource */
        int             sc_irid;                /* interrupt rid */
        struct resource *sc_ires;               /* interrupt resource */
        vmem_t          *sc_fqalloc;
        vmem_t          *sc_qpalloc;
        vmem_t          *sc_cgalloc;
        void            *sc_intr_cookie;
        int             sc_qman_base_channel;
        int             sc_qman_major;

        vm_paddr_t      sc_qp_pa;               /* QMAN portal PA */

        int             sc_fq_cpu[QMAN_MAX_FQIDS];
};

struct qman_fd {
        uint64_t dd:2;
        uint64_t liodn_off:6;
        uint64_t bpid:8;
        uint64_t eliodn_off:4;
        uint64_t _rsvd0:4;
        uint64_t addr:40;
        union {
                struct {
                        uint32_t format:3;
                        uint32_t offset:9;
                        uint32_t length:20;
                };
                struct {
                        uint32_t format2:3;
                        uint32_t wlength:29;
                };
        };
        uint32_t cmd_stat;
};

_Static_assert(sizeof(struct qman_fd) == 16, "qman_fd size mismatch");

struct qman_dqrr_entry {
        uint8_t verb;
        uint8_t stat;
        uint16_t seqnum;
        uint8_t tok;
        uint8_t _rsvd0[3];
        uint32_t fqid;
        uint32_t ctxb;
        struct qman_fd fd;
        uint8_t _rsvd1[32];
};

/* Bits for qman_dqrr_entry fields */
#define QMAN_DQRR_STAT_FQ_EMPTY         0x80
#define QMAN_DQRR_STAT_FQ_HELD_ACTIVE   0x40
#define QMAN_DQRR_STAT_FQ_FORCED        0x20
#define QMAN_DQRR_STAT_HAS_FRAME        0x10
#define QMAN_DQRR_STAT_VDQCR            0x02
#define QMAN_DQRR_STAT_EXPIRED          0x01

struct qman_mr_entry {
        union {
                struct {
                        uint8_t verb;
                        uint8_t data[63];
                };
                struct {
                        uint8_t verb;
                        uint8_t dca;
                        uint16_t seqnum;
                        uint32_t rc:8;
                        uint32_t orp:24;
                        uint32_t fqid;
                        uint32_t tag;
                        struct qman_fd fd;
                        uint8_t _rsvd[32];
                } ern;
                struct {
                        uint8_t verb;
                        uint8_t fqs;
                        uint8_t _rsvd0[6];
                        uint32_t fqid;
                        uint32_t ctxb;
                        uint8_t _rsvd1[48];
                } fqscn;
        };
};

_Static_assert(sizeof(struct qman_mr_entry) == 64, "bad sizeof qman_mr");
/** @> */

typedef int (*qman_cb_dqrr)(device_t, struct qman_fq *,
    struct qman_fd *, void *);
typedef void (*qman_cb_mr)(device_t, struct qman_fq *,
    struct qman_mr_entry *);

struct qman_cb {
        qman_cb_dqrr dqrr;
        qman_cb_mr ern;
        qman_cb_mr fqscn;
        void *ctx;
};
/**
 * @group QMan bus interface
 * @{
 */
int qman_attach(device_t dev);
int qman_detach(device_t dev);
int qman_suspend(device_t dev);
int qman_resume(device_t dev);
int qman_shutdown(device_t dev);
/** @> */
int qman_create_affine_portal(device_t, vm_offset_t, vm_offset_t, int);
void qman_set_sdest(uint16_t, int);


/**
 * @group QMan API
 * @{
 */

/**
 * Create Frame Queue Range.
 *
 * @param fqids_num                     Number of frame queues in the range.
 *
 * @param channel                       Dedicated channel serviced by this
 *                                      Frame Queue Range.
 *
 * @param wq                            Work Queue Number within the channel.
 *
 * @param force_fqid                    If TRUE, fore allocation of specific
 *                                      FQID. Notice that there can not be two
 *                                      frame queues with the same ID in the
 *                                      system.
 *
 * @param fqid_or_align                 FQID if @force_fqid == TRUE, alignment
 *                                      of FQIDs entries otherwise.
 *
 * @param init_parked                   If TRUE, FQ state is initialized to
 *                                      "parked" state on creation. Otherwise,
 *                                      to "scheduled" state.
 *
 * @param hold_active                   If TRUE, the FQ may be held in the
 *                                      portal in "held active" state in
 *                                      anticipation of more frames being
 *                                      dequeued from it after the head frame
 *                                      is removed from the FQ and the dequeue
 *                                      response is returned. If FALSE the
 *                                      "held_active" state of the FQ is not
 *                                      allowed. This affects only on queues
 *                                      destined to software portals. Refer to
 *                                      the 6.3.4.6 of DPAA Reference Manual.
 *
 * @param prefer_in_cache               If TRUE, prefer this FQR to be in QMan
 *                                      internal cache memory for all states.
 *
 * @param congst_avoid_ena              If TRUE, enable congestion avoidance
 *                                      mechanism.
 *
 * @param congst_group                  A handle to the congestion group. Only
 *                                      relevant when @congst_avoid_ena == TRUE.
 *
 * @param overhead_accounting_len       For each frame add this number for CG
 *                                      calculation (may be negative), if 0 -
 *                                      disable feature.
 *
 * @param tail_drop_threshold           If not 0 - enable tail drop on this
 *                                      FQR.
 *
 * @return                              A handle to newly created FQR object.
 */
struct qman_fq *qman_fq_create(uint32_t fqids_num, int channel,
    uint8_t wq, bool force_fqid, uint32_t fqid_or_align, bool init_parked,
    bool hold_active, bool prefer_in_cache, bool congst_avoid_ena,
    void *congst_group, int8_t overhead_accounting_len,
    uint32_t tail_drop_threshold);

/**
 * Free Frame Queue Range.
 *
 * @param fq    A handle to FQR to be freed.
 * @return      E_OK on success; error code otherwise.
 */
int qman_fq_free(struct qman_fq *fq);

/**
 * Register the callback function.
 * The callback function will be called when a frame comes from this FQR.
 *
 * @param fq            A handle to FQR.
 * @param callback      A pointer to the callback function.
 * @param app           A pointer to the user's data.
 * @return              E_OK on success; error code otherwise.
 */
int     qman_fq_register_cb(struct qman_fq *fq, qman_cb_dqrr callback,
    void *ctx);

/**
 * Enqueue a frame on a given FQ.
 *
 * @param fq            A handle to FQ.
 * @param frame         A frame to be enqueued to the transmission.
 * @return              E_OK on success; error code otherwise.
 */
int qman_fq_enqueue(struct qman_fq *fq, struct dpaa_fd *frame);

/**
 * Get one of the FQ counter's value.
 *
 * @param fq            A handle to FQ.
 * @param counter       The requested counter.
 * @return              Counter's current value.
 */
uint32_t qman_fq_get_counter(struct qman_fq *fq, int counter);

/**
 * Pull frame from FQ.
 *
 * @param fq            A handle to FQ.
 * @param frame         The received frame.
 * @return              E_OK on success; error code otherwise.
 */
int qman_fq_pull_frame(struct qman_fq *fq, struct dpaa_fd *frame);

/**
 * Get FQID of the FQ.
 * @param fq    A handle to FQ.
 * @return      FQID of the FQ.
 */
uint32_t qman_fq_get_fqid(struct qman_fq *fq);

/*
 * Allocate a QMan channel to be used with an FQ.
 * @return      Channel ID
 */
int qman_alloc_channel(void);

/*
 * Free a channel
 * @param chan  Channel ID returned from qman_alloc_channel().
 */
void qman_free_channel(int);

/**
 * Poll frames from QMan.
 * This polls frames from the current software portal.
 *
 * @param source        Type of frames to be polled.
 * @return              E_OK on success; error otherwise.
 */
int qman_poll(int source);

/**
 * General received frame callback.
 * This is called, when user did not register his own callback for a given
 * frame queue range (fq).
 */
int qman_received_frame_callback(void *ctx, struct qman_fq *fq,
    void *qm_portal, uint32_t fqid_offset, struct dpaa_fd *frame);

/**
 * General rejected frame callback.
 * This is called, when user did not register his own callback for a given
 * frame queue range (fq).
 */
int qman_rejected_frame_callback(void *ctx, struct qman_fq *fq,
    void *qm_portal, uint32_t fqid_offset, struct dpaa_fd *frame,
    void *qm_rejected_frame_info);

/** @} */

#endif /* QMAN_H */