root/drivers/scsi/csiostor/csio_wr.h

/* [<][>][^][v][top][bottom][index][help] */

INCLUDED FROM


   1 /*
   2  * This file is part of the Chelsio FCoE driver for Linux.
   3  *
   4  * Copyright (c) 2008-2012 Chelsio Communications, Inc. All rights reserved.
   5  *
   6  * This software is available to you under a choice of one of two
   7  * licenses.  You may choose to be licensed under the terms of the GNU
   8  * General Public License (GPL) Version 2, available from the file
   9  * COPYING in the main directory of this source tree, or the
  10  * OpenIB.org BSD license below:
  11  *
  12  *     Redistribution and use in source and binary forms, with or
  13  *     without modification, are permitted provided that the following
  14  *     conditions are met:
  15  *
  16  *      - Redistributions of source code must retain the above
  17  *        copyright notice, this list of conditions and the following
  18  *        disclaimer.
  19  *
  20  *      - Redistributions in binary form must reproduce the above
  21  *        copyright notice, this list of conditions and the following
  22  *        disclaimer in the documentation and/or other materials
  23  *        provided with the distribution.
  24  *
  25  * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
  26  * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
  27  * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
  28  * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
  29  * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
  30  * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
  31  * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
  32  * SOFTWARE.
  33  */
  34 
  35 #ifndef __CSIO_WR_H__
  36 #define __CSIO_WR_H__
  37 
  38 #include <linux/cache.h>
  39 
  40 #include "csio_defs.h"
  41 #include "t4fw_api.h"
  42 #include "t4fw_api_stor.h"
  43 
  44 /*
  45  * SGE register field values.
  46  */
  47 #define X_INGPCIEBOUNDARY_32B           0
  48 #define X_INGPCIEBOUNDARY_64B           1
  49 #define X_INGPCIEBOUNDARY_128B          2
  50 #define X_INGPCIEBOUNDARY_256B          3
  51 #define X_INGPCIEBOUNDARY_512B          4
  52 #define X_INGPCIEBOUNDARY_1024B         5
  53 #define X_INGPCIEBOUNDARY_2048B         6
  54 #define X_INGPCIEBOUNDARY_4096B         7
  55 
  56 /* GTS register */
  57 #define X_TIMERREG_COUNTER0             0
  58 #define X_TIMERREG_COUNTER1             1
  59 #define X_TIMERREG_COUNTER2             2
  60 #define X_TIMERREG_COUNTER3             3
  61 #define X_TIMERREG_COUNTER4             4
  62 #define X_TIMERREG_COUNTER5             5
  63 #define X_TIMERREG_RESTART_COUNTER      6
  64 #define X_TIMERREG_UPDATE_CIDX          7
  65 
  66 /*
  67  * Egress Context field values
  68  */
  69 #define X_FETCHBURSTMIN_16B             0
  70 #define X_FETCHBURSTMIN_32B             1
  71 #define X_FETCHBURSTMIN_64B             2
  72 #define X_FETCHBURSTMIN_128B            3
  73 
  74 #define X_FETCHBURSTMAX_64B             0
  75 #define X_FETCHBURSTMAX_128B            1
  76 #define X_FETCHBURSTMAX_256B            2
  77 #define X_FETCHBURSTMAX_512B            3
  78 
  79 #define X_HOSTFCMODE_NONE               0
  80 #define X_HOSTFCMODE_INGRESS_QUEUE      1
  81 #define X_HOSTFCMODE_STATUS_PAGE        2
  82 #define X_HOSTFCMODE_BOTH               3
  83 
  84 /*
  85  * Ingress Context field values
  86  */
  87 #define X_UPDATESCHEDULING_TIMER        0
  88 #define X_UPDATESCHEDULING_COUNTER_OPTTIMER     1
  89 
  90 #define X_UPDATEDELIVERY_NONE           0
  91 #define X_UPDATEDELIVERY_INTERRUPT      1
  92 #define X_UPDATEDELIVERY_STATUS_PAGE    2
  93 #define X_UPDATEDELIVERY_BOTH           3
  94 
  95 #define X_INTERRUPTDESTINATION_PCIE     0
  96 #define X_INTERRUPTDESTINATION_IQ       1
  97 
  98 #define X_RSPD_TYPE_FLBUF               0
  99 #define X_RSPD_TYPE_CPL                 1
 100 #define X_RSPD_TYPE_INTR                2
 101 
 102 /* WR status is at the same position as retval in a CMD header */
 103 #define csio_wr_status(_wr)             \
 104                 (FW_CMD_RETVAL_G(ntohl(((struct fw_cmd_hdr *)(_wr))->lo)))
 105 
 106 struct csio_hw;
 107 
 108 extern int csio_intr_coalesce_cnt;
 109 extern int csio_intr_coalesce_time;
 110 
 111 /* Ingress queue params */
 112 struct csio_iq_params {
 113 
 114         uint8_t         iq_start:1;
 115         uint8_t         iq_stop:1;
 116         uint8_t         pfn:3;
 117 
 118         uint8_t         vfn;
 119 
 120         uint16_t        physiqid;
 121         uint16_t        iqid;
 122 
 123         uint16_t        fl0id;
 124         uint16_t        fl1id;
 125 
 126         uint8_t         viid;
 127 
 128         uint8_t         type;
 129         uint8_t         iqasynch;
 130         uint8_t         reserved4;
 131 
 132         uint8_t         iqandst;
 133         uint8_t         iqanus;
 134         uint8_t         iqanud;
 135 
 136         uint16_t        iqandstindex;
 137 
 138         uint8_t         iqdroprss;
 139         uint8_t         iqpciech;
 140         uint8_t         iqdcaen;
 141 
 142         uint8_t         iqdcacpu;
 143         uint8_t         iqintcntthresh;
 144         uint8_t         iqo;
 145 
 146         uint8_t         iqcprio;
 147         uint8_t         iqesize;
 148 
 149         uint16_t        iqsize;
 150 
 151         uint64_t        iqaddr;
 152 
 153         uint8_t         iqflintiqhsen;
 154         uint8_t         reserved5;
 155         uint8_t         iqflintcongen;
 156         uint8_t         iqflintcngchmap;
 157 
 158         uint32_t        reserved6;
 159 
 160         uint8_t         fl0hostfcmode;
 161         uint8_t         fl0cprio;
 162         uint8_t         fl0paden;
 163         uint8_t         fl0packen;
 164         uint8_t         fl0congen;
 165         uint8_t         fl0dcaen;
 166 
 167         uint8_t         fl0dcacpu;
 168         uint8_t         fl0fbmin;
 169 
 170         uint8_t         fl0fbmax;
 171         uint8_t         fl0cidxfthresho;
 172         uint8_t         fl0cidxfthresh;
 173 
 174         uint16_t        fl0size;
 175 
 176         uint64_t        fl0addr;
 177 
 178         uint64_t        reserved7;
 179 
 180         uint8_t         fl1hostfcmode;
 181         uint8_t         fl1cprio;
 182         uint8_t         fl1paden;
 183         uint8_t         fl1packen;
 184         uint8_t         fl1congen;
 185         uint8_t         fl1dcaen;
 186 
 187         uint8_t         fl1dcacpu;
 188         uint8_t         fl1fbmin;
 189 
 190         uint8_t         fl1fbmax;
 191         uint8_t         fl1cidxfthresho;
 192         uint8_t         fl1cidxfthresh;
 193 
 194         uint16_t        fl1size;
 195 
 196         uint64_t        fl1addr;
 197 };
 198 
 199 /* Egress queue params */
 200 struct csio_eq_params {
 201 
 202         uint8_t         pfn;
 203         uint8_t         vfn;
 204 
 205         uint8_t         eqstart:1;
 206         uint8_t         eqstop:1;
 207 
 208         uint16_t        physeqid;
 209         uint32_t        eqid;
 210 
 211         uint8_t         hostfcmode:2;
 212         uint8_t         cprio:1;
 213         uint8_t         pciechn:3;
 214 
 215         uint16_t        iqid;
 216 
 217         uint8_t         dcaen:1;
 218         uint8_t         dcacpu:5;
 219 
 220         uint8_t         fbmin:3;
 221         uint8_t         fbmax:3;
 222 
 223         uint8_t         cidxfthresho:1;
 224         uint8_t         cidxfthresh:3;
 225 
 226         uint16_t        eqsize;
 227 
 228         uint64_t        eqaddr;
 229 };
 230 
 231 struct csio_dma_buf {
 232         struct list_head        list;
 233         void                    *vaddr;         /* Virtual address */
 234         dma_addr_t              paddr;          /* Physical address */
 235         uint32_t                len;            /* Buffer size */
 236 };
 237 
 238 /* Generic I/O request structure */
 239 struct csio_ioreq {
 240         struct csio_sm          sm;             /* SM, List
 241                                                  * should be the first member
 242                                                  */
 243         int                     iq_idx;         /* Ingress queue index */
 244         int                     eq_idx;         /* Egress queue index */
 245         uint32_t                nsge;           /* Number of SG elements */
 246         uint32_t                tmo;            /* Driver timeout */
 247         uint32_t                datadir;        /* Data direction */
 248         struct csio_dma_buf     dma_buf;        /* Req/resp DMA buffers */
 249         uint16_t                wr_status;      /* WR completion status */
 250         int16_t                 drv_status;     /* Driver internal status */
 251         struct csio_lnode       *lnode;         /* Owner lnode */
 252         struct csio_rnode       *rnode;         /* Src/destination rnode */
 253         void (*io_cbfn) (struct csio_hw *, struct csio_ioreq *);
 254                                                 /* completion callback */
 255         void                    *scratch1;      /* Scratch area 1.
 256                                                  */
 257         void                    *scratch2;      /* Scratch area 2. */
 258         struct list_head        gen_list;       /* Any list associated with
 259                                                  * this ioreq.
 260                                                  */
 261         uint64_t                fw_handle;      /* Unique handle passed
 262                                                  * to FW
 263                                                  */
 264         uint8_t                 dcopy;          /* Data copy required */
 265         uint8_t                 reserved1;
 266         uint16_t                reserved2;
 267         struct completion       cmplobj;        /* ioreq completion object */
 268 } ____cacheline_aligned_in_smp;
 269 
 270 /*
 271  * Egress status page for egress cidx updates
 272  */
 273 struct csio_qstatus_page {
 274         __be32 qid;
 275         __be16 cidx;
 276         __be16 pidx;
 277 };
 278 
 279 
 280 enum {
 281         CSIO_MAX_FLBUF_PER_IQWR = 4,
 282         CSIO_QCREDIT_SZ  = 64,                  /* pidx/cidx increments
 283                                                  * in bytes
 284                                                  */
 285         CSIO_MAX_QID = 0xFFFF,
 286         CSIO_MAX_IQ = 128,
 287 
 288         CSIO_SGE_NTIMERS = 6,
 289         CSIO_SGE_NCOUNTERS = 4,
 290         CSIO_SGE_FL_SIZE_REGS = 16,
 291 };
 292 
 293 /* Defines for type */
 294 enum {
 295         CSIO_EGRESS     = 1,
 296         CSIO_INGRESS    = 2,
 297         CSIO_FREELIST   = 3,
 298 };
 299 
 300 /*
 301  * Structure for footer (last 2 flits) of Ingress Queue Entry.
 302  */
 303 struct csio_iqwr_footer {
 304         __be32                  hdrbuflen_pidx;
 305         __be32                  pldbuflen_qid;
 306         union {
 307                 u8              type_gen;
 308                 __be64          last_flit;
 309         } u;
 310 };
 311 
 312 #define IQWRF_NEWBUF            (1 << 31)
 313 #define IQWRF_LEN_GET(x)        (((x) >> 0) & 0x7fffffffU)
 314 #define IQWRF_GEN_SHIFT         7
 315 #define IQWRF_TYPE_GET(x)       (((x) >> 4) & 0x3U)
 316 
 317 
 318 /*
 319  * WR pair:
 320  * ========
 321  * A WR can start towards the end of a queue, and then continue at the
 322  * beginning, since the queue is considered to be circular. This will
 323  * require a pair of address/len to be passed back to the caller -
 324  * hence the Work request pair structure.
 325  */
 326 struct csio_wr_pair {
 327         void                    *addr1;
 328         uint32_t                size1;
 329         void                    *addr2;
 330         uint32_t                size2;
 331 };
 332 
 333 /*
 334  * The following structure is used by ingress processing to return the
 335  * free list buffers to consumers.
 336  */
 337 struct csio_fl_dma_buf {
 338         struct csio_dma_buf     flbufs[CSIO_MAX_FLBUF_PER_IQWR];
 339                                                 /* Freelist DMA buffers */
 340         int                     offset;         /* Offset within the
 341                                                  * first FL buf.
 342                                                  */
 343         uint32_t                totlen;         /* Total length */
 344         uint8_t                 defer_free;     /* Free of buffer can
 345                                                  * deferred
 346                                                  */
 347 };
 348 
 349 /* Data-types */
 350 typedef void (*iq_handler_t)(struct csio_hw *, void *, uint32_t,
 351                              struct csio_fl_dma_buf *, void *);
 352 
 353 struct csio_iq {
 354         uint16_t                iqid;           /* Queue ID */
 355         uint16_t                physiqid;       /* Physical Queue ID */
 356         uint16_t                genbit;         /* Generation bit,
 357                                                  * initially set to 1
 358                                                  */
 359         int                     flq_idx;        /* Freelist queue index */
 360         iq_handler_t            iq_intx_handler; /* IQ INTx handler routine */
 361 };
 362 
 363 struct csio_eq {
 364         uint16_t                eqid;           /* Qid */
 365         uint16_t                physeqid;       /* Physical Queue ID */
 366         uint8_t                 wrap[512];      /* Temp area for q-wrap around*/
 367 };
 368 
 369 struct csio_fl {
 370         uint16_t                flid;           /* Qid */
 371         uint16_t                packen;         /* Packing enabled? */
 372         int                     offset;         /* Offset within FL buf */
 373         int                     sreg;           /* Size register */
 374         struct csio_dma_buf     *bufs;          /* Free list buffer ptr array
 375                                                  * indexed using flq->cidx/pidx
 376                                                  */
 377 };
 378 
 379 struct csio_qstats {
 380         uint32_t        n_tot_reqs;             /* Total no. of Requests */
 381         uint32_t        n_tot_rsps;             /* Total no. of responses */
 382         uint32_t        n_qwrap;                /* Queue wraps */
 383         uint32_t        n_eq_wr_split;          /* Number of split EQ WRs */
 384         uint32_t        n_qentry;               /* Queue entry */
 385         uint32_t        n_qempty;               /* Queue empty */
 386         uint32_t        n_qfull;                /* Queue fulls */
 387         uint32_t        n_rsp_unknown;          /* Unknown response type */
 388         uint32_t        n_stray_comp;           /* Stray completion intr */
 389         uint32_t        n_flq_refill;           /* Number of FL refills */
 390 };
 391 
 392 /* Queue metadata */
 393 struct csio_q {
 394         uint16_t                type;           /* Type: Ingress/Egress/FL */
 395         uint16_t                pidx;           /* producer index */
 396         uint16_t                cidx;           /* consumer index */
 397         uint16_t                inc_idx;        /* Incremental index */
 398         uint32_t                wr_sz;          /* Size of all WRs in this q
 399                                                  * if fixed
 400                                                  */
 401         void                    *vstart;        /* Base virtual address
 402                                                  * of queue
 403                                                  */
 404         void                    *vwrap;         /* Virtual end address to
 405                                                  * wrap around at
 406                                                  */
 407         uint32_t                credits;        /* Size of queue in credits */
 408         void                    *owner;         /* Owner */
 409         union {                                 /* Queue contexts */
 410                 struct csio_iq  iq;
 411                 struct csio_eq  eq;
 412                 struct csio_fl  fl;
 413         } un;
 414 
 415         dma_addr_t              pstart;         /* Base physical address of
 416                                                  * queue
 417                                                  */
 418         uint32_t                portid;         /* PCIE Channel */
 419         uint32_t                size;           /* Size of queue in bytes */
 420         struct csio_qstats      stats;          /* Statistics */
 421 } ____cacheline_aligned_in_smp;
 422 
 423 struct csio_sge {
 424         uint32_t        csio_fl_align;          /* Calculated and cached
 425                                                  * for fast path
 426                                                  */
 427         uint32_t        sge_control;            /* padding, boundaries,
 428                                                  * lengths, etc.
 429                                                  */
 430         uint32_t        sge_host_page_size;     /* Host page size */
 431         uint32_t        sge_fl_buf_size[CSIO_SGE_FL_SIZE_REGS];
 432                                                 /* free list buffer sizes */
 433         uint16_t        timer_val[CSIO_SGE_NTIMERS];
 434         uint8_t         counter_val[CSIO_SGE_NCOUNTERS];
 435 };
 436 
 437 /* Work request module */
 438 struct csio_wrm {
 439         int                     num_q;          /* Number of queues */
 440         struct csio_q           **q_arr;        /* Array of queue pointers
 441                                                  * allocated dynamically
 442                                                  * based on configured values
 443                                                  */
 444         uint32_t                fw_iq_start;    /* Start ID of IQ for this fn*/
 445         uint32_t                fw_eq_start;    /* Start ID of EQ for this fn*/
 446         struct csio_q           *intr_map[CSIO_MAX_IQ];
 447                                                 /* IQ-id to IQ map table. */
 448         int                     free_qidx;      /* queue idx of free queue */
 449         struct csio_sge         sge;            /* SGE params */
 450 };
 451 
 452 #define csio_get_q(__hw, __idx)         ((__hw)->wrm.q_arr[__idx])
 453 #define csio_q_type(__hw, __idx)        ((__hw)->wrm.q_arr[(__idx)]->type)
 454 #define csio_q_pidx(__hw, __idx)        ((__hw)->wrm.q_arr[(__idx)]->pidx)
 455 #define csio_q_cidx(__hw, __idx)        ((__hw)->wrm.q_arr[(__idx)]->cidx)
 456 #define csio_q_inc_idx(__hw, __idx)     ((__hw)->wrm.q_arr[(__idx)]->inc_idx)
 457 #define csio_q_vstart(__hw, __idx)      ((__hw)->wrm.q_arr[(__idx)]->vstart)
 458 #define csio_q_pstart(__hw, __idx)      ((__hw)->wrm.q_arr[(__idx)]->pstart)
 459 #define csio_q_size(__hw, __idx)        ((__hw)->wrm.q_arr[(__idx)]->size)
 460 #define csio_q_credits(__hw, __idx)     ((__hw)->wrm.q_arr[(__idx)]->credits)
 461 #define csio_q_portid(__hw, __idx)      ((__hw)->wrm.q_arr[(__idx)]->portid)
 462 #define csio_q_wr_sz(__hw, __idx)       ((__hw)->wrm.q_arr[(__idx)]->wr_sz)
 463 #define csio_q_iqid(__hw, __idx)        ((__hw)->wrm.q_arr[(__idx)]->un.iq.iqid)
 464 #define csio_q_physiqid(__hw, __idx)                                    \
 465                                 ((__hw)->wrm.q_arr[(__idx)]->un.iq.physiqid)
 466 #define csio_q_iq_flq_idx(__hw, __idx)                                  \
 467                                 ((__hw)->wrm.q_arr[(__idx)]->un.iq.flq_idx)
 468 #define csio_q_eqid(__hw, __idx)        ((__hw)->wrm.q_arr[(__idx)]->un.eq.eqid)
 469 #define csio_q_flid(__hw, __idx)        ((__hw)->wrm.q_arr[(__idx)]->un.fl.flid)
 470 
 471 #define csio_q_physeqid(__hw, __idx)                                    \
 472                                 ((__hw)->wrm.q_arr[(__idx)]->un.eq.physeqid)
 473 #define csio_iq_has_fl(__iq)            ((__iq)->un.iq.flq_idx != -1)
 474 
 475 #define csio_q_iq_to_flid(__hw, __iq_idx)                               \
 476         csio_q_flid((__hw), (__hw)->wrm.q_arr[(__iq_qidx)]->un.iq.flq_idx)
 477 #define csio_q_set_intr_map(__hw, __iq_idx, __rel_iq_id)                \
 478                 (__hw)->wrm.intr_map[__rel_iq_id] = csio_get_q(__hw, __iq_idx)
 479 #define csio_q_eq_wrap(__hw, __idx)     ((__hw)->wrm.q_arr[(__idx)]->un.eq.wrap)
 480 
 481 struct csio_mb;
 482 
 483 int csio_wr_alloc_q(struct csio_hw *, uint32_t, uint32_t,
 484                     uint16_t, void *, uint32_t, int, iq_handler_t);
 485 int csio_wr_iq_create(struct csio_hw *, void *, int,
 486                                 uint32_t, uint8_t, bool,
 487                                 void (*)(struct csio_hw *, struct csio_mb *));
 488 int csio_wr_eq_create(struct csio_hw *, void *, int, int, uint8_t,
 489                                 void (*)(struct csio_hw *, struct csio_mb *));
 490 int csio_wr_destroy_queues(struct csio_hw *, bool cmd);
 491 
 492 
 493 int csio_wr_get(struct csio_hw *, int, uint32_t,
 494                           struct csio_wr_pair *);
 495 void csio_wr_copy_to_wrp(void *, struct csio_wr_pair *, uint32_t, uint32_t);
 496 int csio_wr_issue(struct csio_hw *, int, bool);
 497 int csio_wr_process_iq(struct csio_hw *, struct csio_q *,
 498                                  void (*)(struct csio_hw *, void *,
 499                                           uint32_t, struct csio_fl_dma_buf *,
 500                                           void *),
 501                                  void *);
 502 int csio_wr_process_iq_idx(struct csio_hw *, int,
 503                                  void (*)(struct csio_hw *, void *,
 504                                           uint32_t, struct csio_fl_dma_buf *,
 505                                           void *),
 506                                  void *);
 507 
 508 void csio_wr_sge_init(struct csio_hw *);
 509 int csio_wrm_init(struct csio_wrm *, struct csio_hw *);
 510 void csio_wrm_exit(struct csio_wrm *, struct csio_hw *);
 511 
 512 #endif /* ifndef __CSIO_WR_H__ */

/* [<][>][^][v][top][bottom][index][help] */