linux/drivers/scsi/cxgb3i/cxgb3i_ddp.h
<<
>>
Prefs
   1/*
   2 * cxgb3i_ddp.h: Chelsio S3xx iSCSI DDP Manager.
   3 *
   4 * Copyright (c) 2008 Chelsio Communications, Inc.
   5 *
   6 * This program is free software; you can redistribute it and/or modify
   7 * it under the terms of the GNU General Public License as published by
   8 * the Free Software Foundation.
   9 *
  10 * Written by: Karen Xie (kxie@chelsio.com)
  11 */
  12
  13#ifndef __CXGB3I_ULP2_DDP_H__
  14#define __CXGB3I_ULP2_DDP_H__
  15
  16#include <linux/vmalloc.h>
  17
  18/**
  19 * struct cxgb3i_tag_format - cxgb3i ulp tag format for an iscsi entity
  20 *
  21 * @sw_bits:    # of bits used by iscsi software layer
  22 * @rsvd_bits:  # of bits used by h/w
  23 * @rsvd_shift: h/w bits shift left
  24 * @rsvd_mask:  reserved bit mask
  25 */
  26struct cxgb3i_tag_format {
  27        unsigned char sw_bits;
  28        unsigned char rsvd_bits;
  29        unsigned char rsvd_shift;
  30        unsigned char filler[1];
  31        u32 rsvd_mask;
  32};
  33
  34/**
  35 * struct cxgb3i_gather_list - cxgb3i direct data placement memory
  36 *
  37 * @tag:        ddp tag
  38 * @length:     total data buffer length
  39 * @offset:     initial offset to the 1st page
  40 * @nelem:      # of pages
  41 * @pages:      page pointers
  42 * @phys_addr:  physical address
  43 */
  44struct cxgb3i_gather_list {
  45        u32 tag;
  46        unsigned int length;
  47        unsigned int offset;
  48        unsigned int nelem;
  49        struct page **pages;
  50        dma_addr_t phys_addr[0];
  51};
  52
  53/**
  54 * struct cxgb3i_ddp_info - cxgb3i direct data placement for pdu payload
  55 *
  56 * @list:       list head to link elements
  57 * @refcnt:     ref. count
  58 * @tdev:       pointer to t3cdev used by cxgb3 driver
  59 * @max_txsz:   max tx packet size for ddp
  60 * @max_rxsz:   max rx packet size for ddp
  61 * @llimit:     lower bound of the page pod memory
  62 * @ulimit:     upper bound of the page pod memory
  63 * @nppods:     # of page pod entries
  64 * @idx_last:   page pod entry last used
  65 * @idx_bits:   # of bits the pagepod index would take
  66 * @idx_mask:   pagepod index mask
  67 * @rsvd_tag_mask: tag mask
  68 * @map_lock:   lock to synchonize access to the page pod map
  69 * @gl_map:     ddp memory gather list
  70 * @gl_skb:     skb used to program the pagepod
  71 */
  72struct cxgb3i_ddp_info {
  73        struct list_head list;
  74        struct kref refcnt;
  75        struct t3cdev *tdev;
  76        struct pci_dev *pdev;
  77        unsigned int max_txsz;
  78        unsigned int max_rxsz;
  79        unsigned int llimit;
  80        unsigned int ulimit;
  81        unsigned int nppods;
  82        unsigned int idx_last;
  83        unsigned char idx_bits;
  84        unsigned char filler[3];
  85        u32 idx_mask;
  86        u32 rsvd_tag_mask;
  87        spinlock_t map_lock;
  88        struct cxgb3i_gather_list **gl_map;
  89        struct sk_buff **gl_skb;
  90};
  91
  92#define ISCSI_PDU_NONPAYLOAD_LEN        312 /* bhs(48) + ahs(256) + digest(8) */
  93#define ULP2_MAX_PKT_SIZE       16224
  94#define ULP2_MAX_PDU_PAYLOAD    (ULP2_MAX_PKT_SIZE - ISCSI_PDU_NONPAYLOAD_LEN)
  95#define PPOD_PAGES_MAX          4
  96#define PPOD_PAGES_SHIFT        2       /* 4 pages per pod */
  97
  98/*
  99 * struct pagepod_hdr, pagepod - pagepod format
 100 */
 101struct pagepod_hdr {
 102        u32 vld_tid;
 103        u32 pgsz_tag_clr;
 104        u32 maxoffset;
 105        u32 pgoffset;
 106        u64 rsvd;
 107};
 108
 109struct pagepod {
 110        struct pagepod_hdr hdr;
 111        u64 addr[PPOD_PAGES_MAX + 1];
 112};
 113
 114#define PPOD_SIZE               sizeof(struct pagepod)  /* 64 */
 115#define PPOD_SIZE_SHIFT         6
 116
 117#define PPOD_COLOR_SHIFT        0
 118#define PPOD_COLOR_SIZE         6
 119#define PPOD_COLOR_MASK         ((1 << PPOD_COLOR_SIZE) - 1)
 120
 121#define PPOD_IDX_SHIFT          PPOD_COLOR_SIZE
 122#define PPOD_IDX_MAX_SIZE       24
 123
 124#define S_PPOD_TID    0
 125#define M_PPOD_TID    0xFFFFFF
 126#define V_PPOD_TID(x) ((x) << S_PPOD_TID)
 127
 128#define S_PPOD_VALID    24
 129#define V_PPOD_VALID(x) ((x) << S_PPOD_VALID)
 130#define F_PPOD_VALID    V_PPOD_VALID(1U)
 131
 132#define S_PPOD_COLOR    0
 133#define M_PPOD_COLOR    0x3F
 134#define V_PPOD_COLOR(x) ((x) << S_PPOD_COLOR)
 135
 136#define S_PPOD_TAG    6
 137#define M_PPOD_TAG    0xFFFFFF
 138#define V_PPOD_TAG(x) ((x) << S_PPOD_TAG)
 139
 140#define S_PPOD_PGSZ    30
 141#define M_PPOD_PGSZ    0x3
 142#define V_PPOD_PGSZ(x) ((x) << S_PPOD_PGSZ)
 143
 144/*
 145 * large memory chunk allocation/release
 146 * use vmalloc() if kmalloc() fails
 147 */
 148static inline void *cxgb3i_alloc_big_mem(unsigned int size,
 149                                         gfp_t gfp)
 150{
 151        void *p = kmalloc(size, gfp);
 152        if (!p)
 153                p = vmalloc(size);
 154        if (p)
 155                memset(p, 0, size);
 156        return p;
 157}
 158
 159static inline void cxgb3i_free_big_mem(void *addr)
 160{
 161        if (is_vmalloc_addr(addr))
 162                vfree(addr);
 163        else
 164                kfree(addr);
 165}
 166
 167/*
 168 * cxgb3i ddp tag are 32 bits, it consists of reserved bits used by h/w and
 169 * non-reserved bits that can be used by the iscsi s/w.
 170 * The reserved bits are identified by the rsvd_bits and rsvd_shift fields
 171 * in struct cxgb3i_tag_format.
 172 *
 173 * The upper most reserved bit can be used to check if a tag is ddp tag or not:
 174 *      if the bit is 0, the tag is a valid ddp tag
 175 */
 176
 177/**
 178 * cxgb3i_is_ddp_tag - check if a given tag is a hw/ddp tag
 179 * @tformat: tag format information
 180 * @tag: tag to be checked
 181 *
 182 * return true if the tag is a ddp tag, false otherwise.
 183 */
 184static inline int cxgb3i_is_ddp_tag(struct cxgb3i_tag_format *tformat, u32 tag)
 185{
 186        return !(tag & (1 << (tformat->rsvd_bits + tformat->rsvd_shift - 1)));
 187}
 188
 189/**
 190 * cxgb3i_sw_tag_usable - check if s/w tag has enough bits left for hw bits
 191 * @tformat: tag format information
 192 * @sw_tag: s/w tag to be checked
 193 *
 194 * return true if the tag can be used for hw ddp tag, false otherwise.
 195 */
 196static inline int cxgb3i_sw_tag_usable(struct cxgb3i_tag_format *tformat,
 197                                        u32 sw_tag)
 198{
 199        sw_tag >>= (32 - tformat->rsvd_bits);
 200        return !sw_tag;
 201}
 202
 203/**
 204 * cxgb3i_set_non_ddp_tag - mark a given s/w tag as an invalid ddp tag
 205 * @tformat: tag format information
 206 * @sw_tag: s/w tag to be checked
 207 *
 208 * insert 1 at the upper most reserved bit to mark it as an invalid ddp tag.
 209 */
 210static inline u32 cxgb3i_set_non_ddp_tag(struct cxgb3i_tag_format *tformat,
 211                                         u32 sw_tag)
 212{
 213        unsigned char shift = tformat->rsvd_bits + tformat->rsvd_shift - 1;
 214        u32 mask = (1 << shift) - 1;
 215
 216        if (sw_tag && (sw_tag & ~mask)) {
 217                u32 v1 = sw_tag & ((1 << shift) - 1);
 218                u32 v2 = (sw_tag >> (shift - 1)) << shift;
 219
 220                return v2 | v1 | 1 << shift;
 221        }
 222        return sw_tag | 1 << shift;
 223}
 224
 225/**
 226 * cxgb3i_ddp_tag_base - shift s/w tag bits so that reserved bits are not used
 227 * @tformat: tag format information
 228 * @sw_tag: s/w tag to be checked
 229 */
 230static inline u32 cxgb3i_ddp_tag_base(struct cxgb3i_tag_format *tformat,
 231                                      u32 sw_tag)
 232{
 233        u32 mask = (1 << tformat->rsvd_shift) - 1;
 234
 235        if (sw_tag && (sw_tag & ~mask)) {
 236                u32 v1 = sw_tag & mask;
 237                u32 v2 = sw_tag >> tformat->rsvd_shift;
 238
 239                v2 <<= tformat->rsvd_shift + tformat->rsvd_bits;
 240                return v2 | v1;
 241        }
 242        return sw_tag;
 243}
 244
 245/**
 246 * cxgb3i_tag_rsvd_bits - get the reserved bits used by the h/w
 247 * @tformat: tag format information
 248 * @tag: tag to be checked
 249 *
 250 * return the reserved bits in the tag
 251 */
 252static inline u32 cxgb3i_tag_rsvd_bits(struct cxgb3i_tag_format *tformat,
 253                                       u32 tag)
 254{
 255        if (cxgb3i_is_ddp_tag(tformat, tag))
 256                return (tag >> tformat->rsvd_shift) & tformat->rsvd_mask;
 257        return 0;
 258}
 259
 260/**
 261 * cxgb3i_tag_nonrsvd_bits - get the non-reserved bits used by the s/w
 262 * @tformat: tag format information
 263 * @tag: tag to be checked
 264 *
 265 * return the non-reserved bits in the tag.
 266 */
 267static inline u32 cxgb3i_tag_nonrsvd_bits(struct cxgb3i_tag_format *tformat,
 268                                          u32 tag)
 269{
 270        unsigned char shift = tformat->rsvd_bits + tformat->rsvd_shift - 1;
 271        u32 v1, v2;
 272
 273        if (cxgb3i_is_ddp_tag(tformat, tag)) {
 274                v1 = tag & ((1 << tformat->rsvd_shift) - 1);
 275                v2 = (tag >> (shift + 1)) << tformat->rsvd_shift;
 276        } else {
 277                u32 mask = (1 << shift) - 1;
 278
 279                tag &= ~(1 << shift);
 280                v1 = tag & mask;
 281                v2 = (tag >> 1) & ~mask;
 282        }
 283        return v1 | v2;
 284}
 285
 286int cxgb3i_ddp_tag_reserve(struct t3cdev *, unsigned int tid,
 287                           struct cxgb3i_tag_format *, u32 *tag,
 288                           struct cxgb3i_gather_list *, gfp_t gfp);
 289void cxgb3i_ddp_tag_release(struct t3cdev *, u32 tag);
 290
 291struct cxgb3i_gather_list *cxgb3i_ddp_make_gl(unsigned int xferlen,
 292                                struct scatterlist *sgl,
 293                                unsigned int sgcnt,
 294                                struct pci_dev *pdev,
 295                                gfp_t gfp);
 296void cxgb3i_ddp_release_gl(struct cxgb3i_gather_list *gl,
 297                                struct pci_dev *pdev);
 298
 299int cxgb3i_setup_conn_host_pagesize(struct t3cdev *, unsigned int tid,
 300                                    int reply);
 301int cxgb3i_setup_conn_pagesize(struct t3cdev *, unsigned int tid, int reply,
 302                               unsigned long pgsz);
 303int cxgb3i_setup_conn_digest(struct t3cdev *, unsigned int tid,
 304                                int hcrc, int dcrc, int reply);
 305int cxgb3i_ddp_find_page_index(unsigned long pgsz);
 306int cxgb3i_adapter_ddp_info(struct t3cdev *, struct cxgb3i_tag_format *,
 307                            unsigned int *txsz, unsigned int *rxsz);
 308
 309void cxgb3i_ddp_init(struct t3cdev *);
 310void cxgb3i_ddp_cleanup(struct t3cdev *);
 311#endif
 312