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__ */ 513