Add the rt linux 4.1.3-rt3 as base
[kvmfornfv.git] / kernel / drivers / scsi / csiostor / csio_wr.h
diff --git a/kernel/drivers/scsi/csiostor/csio_wr.h b/kernel/drivers/scsi/csiostor/csio_wr.h
new file mode 100644 (file)
index 0000000..0c0dd9a
--- /dev/null
@@ -0,0 +1,512 @@
+/*
+ * This file is part of the Chelsio FCoE driver for Linux.
+ *
+ * Copyright (c) 2008-2012 Chelsio Communications, Inc. All rights reserved.
+ *
+ * This software is available to you under a choice of one of two
+ * licenses.  You may choose to be licensed under the terms of the GNU
+ * General Public License (GPL) Version 2, available from the file
+ * COPYING in the main directory of this source tree, or the
+ * OpenIB.org BSD license below:
+ *
+ *     Redistribution and use in source and binary forms, with or
+ *     without modification, are permitted provided that the following
+ *     conditions are met:
+ *
+ *      - Redistributions of source code must retain the above
+ *        copyright notice, this list of conditions and the following
+ *        disclaimer.
+ *
+ *      - 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.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+ * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+ * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
+ * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
+ * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
+ * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+ * SOFTWARE.
+ */
+
+#ifndef __CSIO_WR_H__
+#define __CSIO_WR_H__
+
+#include <linux/cache.h>
+
+#include "csio_defs.h"
+#include "t4fw_api.h"
+#include "t4fw_api_stor.h"
+
+/*
+ * SGE register field values.
+ */
+#define X_INGPCIEBOUNDARY_32B          0
+#define X_INGPCIEBOUNDARY_64B          1
+#define X_INGPCIEBOUNDARY_128B         2
+#define X_INGPCIEBOUNDARY_256B         3
+#define X_INGPCIEBOUNDARY_512B         4
+#define X_INGPCIEBOUNDARY_1024B                5
+#define X_INGPCIEBOUNDARY_2048B                6
+#define X_INGPCIEBOUNDARY_4096B                7
+
+/* GTS register */
+#define X_TIMERREG_COUNTER0            0
+#define X_TIMERREG_COUNTER1            1
+#define X_TIMERREG_COUNTER2            2
+#define X_TIMERREG_COUNTER3            3
+#define X_TIMERREG_COUNTER4            4
+#define X_TIMERREG_COUNTER5            5
+#define X_TIMERREG_RESTART_COUNTER     6
+#define X_TIMERREG_UPDATE_CIDX         7
+
+/*
+ * Egress Context field values
+ */
+#define X_FETCHBURSTMIN_16B            0
+#define X_FETCHBURSTMIN_32B            1
+#define X_FETCHBURSTMIN_64B            2
+#define X_FETCHBURSTMIN_128B           3
+
+#define X_FETCHBURSTMAX_64B            0
+#define X_FETCHBURSTMAX_128B           1
+#define X_FETCHBURSTMAX_256B           2
+#define X_FETCHBURSTMAX_512B           3
+
+#define X_HOSTFCMODE_NONE              0
+#define X_HOSTFCMODE_INGRESS_QUEUE     1
+#define X_HOSTFCMODE_STATUS_PAGE       2
+#define X_HOSTFCMODE_BOTH              3
+
+/*
+ * Ingress Context field values
+ */
+#define X_UPDATESCHEDULING_TIMER       0
+#define X_UPDATESCHEDULING_COUNTER_OPTTIMER    1
+
+#define X_UPDATEDELIVERY_NONE          0
+#define X_UPDATEDELIVERY_INTERRUPT     1
+#define X_UPDATEDELIVERY_STATUS_PAGE   2
+#define X_UPDATEDELIVERY_BOTH          3
+
+#define X_INTERRUPTDESTINATION_PCIE    0
+#define X_INTERRUPTDESTINATION_IQ      1
+
+#define X_RSPD_TYPE_FLBUF              0
+#define X_RSPD_TYPE_CPL                        1
+#define X_RSPD_TYPE_INTR               2
+
+/* WR status is at the same position as retval in a CMD header */
+#define csio_wr_status(_wr)            \
+               (FW_CMD_RETVAL_G(ntohl(((struct fw_cmd_hdr *)(_wr))->lo)))
+
+struct csio_hw;
+
+extern int csio_intr_coalesce_cnt;
+extern int csio_intr_coalesce_time;
+
+/* Ingress queue params */
+struct csio_iq_params {
+
+       uint8_t         iq_start:1;
+       uint8_t         iq_stop:1;
+       uint8_t         pfn:3;
+
+       uint8_t         vfn;
+
+       uint16_t        physiqid;
+       uint16_t        iqid;
+
+       uint16_t        fl0id;
+       uint16_t        fl1id;
+
+       uint8_t         viid;
+
+       uint8_t         type;
+       uint8_t         iqasynch;
+       uint8_t         reserved4;
+
+       uint8_t         iqandst;
+       uint8_t         iqanus;
+       uint8_t         iqanud;
+
+       uint16_t        iqandstindex;
+
+       uint8_t         iqdroprss;
+       uint8_t         iqpciech;
+       uint8_t         iqdcaen;
+
+       uint8_t         iqdcacpu;
+       uint8_t         iqintcntthresh;
+       uint8_t         iqo;
+
+       uint8_t         iqcprio;
+       uint8_t         iqesize;
+
+       uint16_t        iqsize;
+
+       uint64_t        iqaddr;
+
+       uint8_t         iqflintiqhsen;
+       uint8_t         reserved5;
+       uint8_t         iqflintcongen;
+       uint8_t         iqflintcngchmap;
+
+       uint32_t        reserved6;
+
+       uint8_t         fl0hostfcmode;
+       uint8_t         fl0cprio;
+       uint8_t         fl0paden;
+       uint8_t         fl0packen;
+       uint8_t         fl0congen;
+       uint8_t         fl0dcaen;
+
+       uint8_t         fl0dcacpu;
+       uint8_t         fl0fbmin;
+
+       uint8_t         fl0fbmax;
+       uint8_t         fl0cidxfthresho;
+       uint8_t         fl0cidxfthresh;
+
+       uint16_t        fl0size;
+
+       uint64_t        fl0addr;
+
+       uint64_t        reserved7;
+
+       uint8_t         fl1hostfcmode;
+       uint8_t         fl1cprio;
+       uint8_t         fl1paden;
+       uint8_t         fl1packen;
+       uint8_t         fl1congen;
+       uint8_t         fl1dcaen;
+
+       uint8_t         fl1dcacpu;
+       uint8_t         fl1fbmin;
+
+       uint8_t         fl1fbmax;
+       uint8_t         fl1cidxfthresho;
+       uint8_t         fl1cidxfthresh;
+
+       uint16_t        fl1size;
+
+       uint64_t        fl1addr;
+};
+
+/* Egress queue params */
+struct csio_eq_params {
+
+       uint8_t         pfn;
+       uint8_t         vfn;
+
+       uint8_t         eqstart:1;
+       uint8_t         eqstop:1;
+
+       uint16_t        physeqid;
+       uint32_t        eqid;
+
+       uint8_t         hostfcmode:2;
+       uint8_t         cprio:1;
+       uint8_t         pciechn:3;
+
+       uint16_t        iqid;
+
+       uint8_t         dcaen:1;
+       uint8_t         dcacpu:5;
+
+       uint8_t         fbmin:3;
+       uint8_t         fbmax:3;
+
+       uint8_t         cidxfthresho:1;
+       uint8_t         cidxfthresh:3;
+
+       uint16_t        eqsize;
+
+       uint64_t        eqaddr;
+};
+
+struct csio_dma_buf {
+       struct list_head        list;
+       void                    *vaddr;         /* Virtual address */
+       dma_addr_t              paddr;          /* Physical address */
+       uint32_t                len;            /* Buffer size */
+};
+
+/* Generic I/O request structure */
+struct csio_ioreq {
+       struct csio_sm          sm;             /* SM, List
+                                                * should be the first member
+                                                */
+       int                     iq_idx;         /* Ingress queue index */
+       int                     eq_idx;         /* Egress queue index */
+       uint32_t                nsge;           /* Number of SG elements */
+       uint32_t                tmo;            /* Driver timeout */
+       uint32_t                datadir;        /* Data direction */
+       struct csio_dma_buf     dma_buf;        /* Req/resp DMA buffers */
+       uint16_t                wr_status;      /* WR completion status */
+       int16_t                 drv_status;     /* Driver internal status */
+       struct csio_lnode       *lnode;         /* Owner lnode */
+       struct csio_rnode       *rnode;         /* Src/destination rnode */
+       void (*io_cbfn) (struct csio_hw *, struct csio_ioreq *);
+                                               /* completion callback */
+       void                    *scratch1;      /* Scratch area 1.
+                                                */
+       void                    *scratch2;      /* Scratch area 2. */
+       struct list_head        gen_list;       /* Any list associated with
+                                                * this ioreq.
+                                                */
+       uint64_t                fw_handle;      /* Unique handle passed
+                                                * to FW
+                                                */
+       uint8_t                 dcopy;          /* Data copy required */
+       uint8_t                 reserved1;
+       uint16_t                reserved2;
+       struct completion       cmplobj;        /* ioreq completion object */
+} ____cacheline_aligned_in_smp;
+
+/*
+ * Egress status page for egress cidx updates
+ */
+struct csio_qstatus_page {
+       __be32 qid;
+       __be16 cidx;
+       __be16 pidx;
+};
+
+
+enum {
+       CSIO_MAX_FLBUF_PER_IQWR = 4,
+       CSIO_QCREDIT_SZ  = 64,                  /* pidx/cidx increments
+                                                * in bytes
+                                                */
+       CSIO_MAX_QID = 0xFFFF,
+       CSIO_MAX_IQ = 128,
+
+       CSIO_SGE_NTIMERS = 6,
+       CSIO_SGE_NCOUNTERS = 4,
+       CSIO_SGE_FL_SIZE_REGS = 16,
+};
+
+/* Defines for type */
+enum {
+       CSIO_EGRESS     = 1,
+       CSIO_INGRESS    = 2,
+       CSIO_FREELIST   = 3,
+};
+
+/*
+ * Structure for footer (last 2 flits) of Ingress Queue Entry.
+ */
+struct csio_iqwr_footer {
+       __be32                  hdrbuflen_pidx;
+       __be32                  pldbuflen_qid;
+       union {
+               u8              type_gen;
+               __be64          last_flit;
+       } u;
+};
+
+#define IQWRF_NEWBUF           (1 << 31)
+#define IQWRF_LEN_GET(x)       (((x) >> 0) & 0x7fffffffU)
+#define IQWRF_GEN_SHIFT                7
+#define IQWRF_TYPE_GET(x)      (((x) >> 4) & 0x3U)
+
+
+/*
+ * WR pair:
+ * ========
+ * A WR can start towards the end of a queue, and then continue at the
+ * beginning, since the queue is considered to be circular. This will
+ * require a pair of address/len to be passed back to the caller -
+ * hence the Work request pair structure.
+ */
+struct csio_wr_pair {
+       void                    *addr1;
+       uint32_t                size1;
+       void                    *addr2;
+       uint32_t                size2;
+};
+
+/*
+ * The following structure is used by ingress processing to return the
+ * free list buffers to consumers.
+ */
+struct csio_fl_dma_buf {
+       struct csio_dma_buf     flbufs[CSIO_MAX_FLBUF_PER_IQWR];
+                                               /* Freelist DMA buffers */
+       int                     offset;         /* Offset within the
+                                                * first FL buf.
+                                                */
+       uint32_t                totlen;         /* Total length */
+       uint8_t                 defer_free;     /* Free of buffer can
+                                                * deferred
+                                                */
+};
+
+/* Data-types */
+typedef void (*iq_handler_t)(struct csio_hw *, void *, uint32_t,
+                            struct csio_fl_dma_buf *, void *);
+
+struct csio_iq {
+       uint16_t                iqid;           /* Queue ID */
+       uint16_t                physiqid;       /* Physical Queue ID */
+       uint16_t                genbit;         /* Generation bit,
+                                                * initially set to 1
+                                                */
+       int                     flq_idx;        /* Freelist queue index */
+       iq_handler_t            iq_intx_handler; /* IQ INTx handler routine */
+};
+
+struct csio_eq {
+       uint16_t                eqid;           /* Qid */
+       uint16_t                physeqid;       /* Physical Queue ID */
+       uint8_t                 wrap[512];      /* Temp area for q-wrap around*/
+};
+
+struct csio_fl {
+       uint16_t                flid;           /* Qid */
+       uint16_t                packen;         /* Packing enabled? */
+       int                     offset;         /* Offset within FL buf */
+       int                     sreg;           /* Size register */
+       struct csio_dma_buf     *bufs;          /* Free list buffer ptr array
+                                                * indexed using flq->cidx/pidx
+                                                */
+};
+
+struct csio_qstats {
+       uint32_t        n_tot_reqs;             /* Total no. of Requests */
+       uint32_t        n_tot_rsps;             /* Total no. of responses */
+       uint32_t        n_qwrap;                /* Queue wraps */
+       uint32_t        n_eq_wr_split;          /* Number of split EQ WRs */
+       uint32_t        n_qentry;               /* Queue entry */
+       uint32_t        n_qempty;               /* Queue empty */
+       uint32_t        n_qfull;                /* Queue fulls */
+       uint32_t        n_rsp_unknown;          /* Unknown response type */
+       uint32_t        n_stray_comp;           /* Stray completion intr */
+       uint32_t        n_flq_refill;           /* Number of FL refills */
+};
+
+/* Queue metadata */
+struct csio_q {
+       uint16_t                type;           /* Type: Ingress/Egress/FL */
+       uint16_t                pidx;           /* producer index */
+       uint16_t                cidx;           /* consumer index */
+       uint16_t                inc_idx;        /* Incremental index */
+       uint32_t                wr_sz;          /* Size of all WRs in this q
+                                                * if fixed
+                                                */
+       void                    *vstart;        /* Base virtual address
+                                                * of queue
+                                                */
+       void                    *vwrap;         /* Virtual end address to
+                                                * wrap around at
+                                                */
+       uint32_t                credits;        /* Size of queue in credits */
+       void                    *owner;         /* Owner */
+       union {                                 /* Queue contexts */
+               struct csio_iq  iq;
+               struct csio_eq  eq;
+               struct csio_fl  fl;
+       } un;
+
+       dma_addr_t              pstart;         /* Base physical address of
+                                                * queue
+                                                */
+       uint32_t                portid;         /* PCIE Channel */
+       uint32_t                size;           /* Size of queue in bytes */
+       struct csio_qstats      stats;          /* Statistics */
+} ____cacheline_aligned_in_smp;
+
+struct csio_sge {
+       uint32_t        csio_fl_align;          /* Calculated and cached
+                                                * for fast path
+                                                */
+       uint32_t        sge_control;            /* padding, boundaries,
+                                                * lengths, etc.
+                                                */
+       uint32_t        sge_host_page_size;     /* Host page size */
+       uint32_t        sge_fl_buf_size[CSIO_SGE_FL_SIZE_REGS];
+                                               /* free list buffer sizes */
+       uint16_t        timer_val[CSIO_SGE_NTIMERS];
+       uint8_t         counter_val[CSIO_SGE_NCOUNTERS];
+};
+
+/* Work request module */
+struct csio_wrm {
+       int                     num_q;          /* Number of queues */
+       struct csio_q           **q_arr;        /* Array of queue pointers
+                                                * allocated dynamically
+                                                * based on configured values
+                                                */
+       uint32_t                fw_iq_start;    /* Start ID of IQ for this fn*/
+       uint32_t                fw_eq_start;    /* Start ID of EQ for this fn*/
+       struct csio_q           *intr_map[CSIO_MAX_IQ];
+                                               /* IQ-id to IQ map table. */
+       int                     free_qidx;      /* queue idx of free queue */
+       struct csio_sge         sge;            /* SGE params */
+};
+
+#define csio_get_q(__hw, __idx)                ((__hw)->wrm.q_arr[__idx])
+#define        csio_q_type(__hw, __idx)        ((__hw)->wrm.q_arr[(__idx)]->type)
+#define        csio_q_pidx(__hw, __idx)        ((__hw)->wrm.q_arr[(__idx)]->pidx)
+#define        csio_q_cidx(__hw, __idx)        ((__hw)->wrm.q_arr[(__idx)]->cidx)
+#define        csio_q_inc_idx(__hw, __idx)     ((__hw)->wrm.q_arr[(__idx)]->inc_idx)
+#define        csio_q_vstart(__hw, __idx)      ((__hw)->wrm.q_arr[(__idx)]->vstart)
+#define        csio_q_pstart(__hw, __idx)      ((__hw)->wrm.q_arr[(__idx)]->pstart)
+#define        csio_q_size(__hw, __idx)        ((__hw)->wrm.q_arr[(__idx)]->size)
+#define        csio_q_credits(__hw, __idx)     ((__hw)->wrm.q_arr[(__idx)]->credits)
+#define        csio_q_portid(__hw, __idx)      ((__hw)->wrm.q_arr[(__idx)]->portid)
+#define        csio_q_wr_sz(__hw, __idx)       ((__hw)->wrm.q_arr[(__idx)]->wr_sz)
+#define        csio_q_iqid(__hw, __idx)        ((__hw)->wrm.q_arr[(__idx)]->un.iq.iqid)
+#define csio_q_physiqid(__hw, __idx)                                   \
+                               ((__hw)->wrm.q_arr[(__idx)]->un.iq.physiqid)
+#define csio_q_iq_flq_idx(__hw, __idx)                                 \
+                               ((__hw)->wrm.q_arr[(__idx)]->un.iq.flq_idx)
+#define        csio_q_eqid(__hw, __idx)        ((__hw)->wrm.q_arr[(__idx)]->un.eq.eqid)
+#define        csio_q_flid(__hw, __idx)        ((__hw)->wrm.q_arr[(__idx)]->un.fl.flid)
+
+#define csio_q_physeqid(__hw, __idx)                                   \
+                               ((__hw)->wrm.q_arr[(__idx)]->un.eq.physeqid)
+#define csio_iq_has_fl(__iq)           ((__iq)->un.iq.flq_idx != -1)
+
+#define csio_q_iq_to_flid(__hw, __iq_idx)                              \
+       csio_q_flid((__hw), (__hw)->wrm.q_arr[(__iq_qidx)]->un.iq.flq_idx)
+#define csio_q_set_intr_map(__hw, __iq_idx, __rel_iq_id)               \
+               (__hw)->wrm.intr_map[__rel_iq_id] = csio_get_q(__hw, __iq_idx)
+#define        csio_q_eq_wrap(__hw, __idx)     ((__hw)->wrm.q_arr[(__idx)]->un.eq.wrap)
+
+struct csio_mb;
+
+int csio_wr_alloc_q(struct csio_hw *, uint32_t, uint32_t,
+                   uint16_t, void *, uint32_t, int, iq_handler_t);
+int csio_wr_iq_create(struct csio_hw *, void *, int,
+                               uint32_t, uint8_t, bool,
+                               void (*)(struct csio_hw *, struct csio_mb *));
+int csio_wr_eq_create(struct csio_hw *, void *, int, int, uint8_t,
+                               void (*)(struct csio_hw *, struct csio_mb *));
+int csio_wr_destroy_queues(struct csio_hw *, bool cmd);
+
+
+int csio_wr_get(struct csio_hw *, int, uint32_t,
+                         struct csio_wr_pair *);
+void csio_wr_copy_to_wrp(void *, struct csio_wr_pair *, uint32_t, uint32_t);
+int csio_wr_issue(struct csio_hw *, int, bool);
+int csio_wr_process_iq(struct csio_hw *, struct csio_q *,
+                                void (*)(struct csio_hw *, void *,
+                                         uint32_t, struct csio_fl_dma_buf *,
+                                         void *),
+                                void *);
+int csio_wr_process_iq_idx(struct csio_hw *, int,
+                                void (*)(struct csio_hw *, void *,
+                                         uint32_t, struct csio_fl_dma_buf *,
+                                         void *),
+                                void *);
+
+void csio_wr_sge_init(struct csio_hw *);
+int csio_wrm_init(struct csio_wrm *, struct csio_hw *);
+void csio_wrm_exit(struct csio_wrm *, struct csio_hw *);
+
+#endif /* ifndef __CSIO_WR_H__ */