2 * cxgb3i_ddp.h: Chelsio S3xx iSCSI DDP Manager.
4 * Copyright (c) 2008 Chelsio Communications, Inc.
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.
10 * Written by: Karen Xie (kxie@chelsio.com)
13 #ifndef __CXGB3I_ULP2_DDP_H__
14 #define __CXGB3I_ULP2_DDP_H__
16 #include <linux/slab.h>
17 #include <linux/vmalloc.h>
20 * struct cxgb3i_tag_format - cxgb3i ulp tag format for an iscsi entity
22 * @sw_bits: # of bits used by iscsi software layer
23 * @rsvd_bits: # of bits used by h/w
24 * @rsvd_shift: h/w bits shift left
25 * @rsvd_mask: reserved bit mask
27 struct cxgb3i_tag_format {
28 unsigned char sw_bits;
29 unsigned char rsvd_bits;
30 unsigned char rsvd_shift;
31 unsigned char filler[1];
36 * struct cxgb3i_gather_list - cxgb3i direct data placement memory
39 * @length: total data buffer length
40 * @offset: initial offset to the 1st page
42 * @pages: page pointers
43 * @phys_addr: physical address
45 struct cxgb3i_gather_list {
51 dma_addr_t phys_addr[0];
55 * struct cxgb3i_ddp_info - cxgb3i direct data placement for pdu payload
57 * @list: list head to link elements
59 * @tdev: pointer to t3cdev used by cxgb3 driver
60 * @max_txsz: max tx packet size for ddp
61 * @max_rxsz: max rx packet size for ddp
62 * @llimit: lower bound of the page pod memory
63 * @ulimit: upper bound of the page pod memory
64 * @nppods: # of page pod entries
65 * @idx_last: page pod entry last used
66 * @idx_bits: # of bits the pagepod index would take
67 * @idx_mask: pagepod index mask
68 * @rsvd_tag_mask: tag mask
69 * @map_lock: lock to synchonize access to the page pod map
70 * @gl_map: ddp memory gather list
71 * @gl_skb: skb used to program the pagepod
73 struct cxgb3i_ddp_info {
74 struct list_head list;
78 unsigned int max_txsz;
79 unsigned int max_rxsz;
83 unsigned int idx_last;
84 unsigned char idx_bits;
85 unsigned char filler[3];
89 struct cxgb3i_gather_list **gl_map;
90 struct sk_buff **gl_skb;
93 #define ISCSI_PDU_NONPAYLOAD_LEN 312 /* bhs(48) + ahs(256) + digest(8) */
94 #define ULP2_MAX_PKT_SIZE 16224
95 #define ULP2_MAX_PDU_PAYLOAD (ULP2_MAX_PKT_SIZE - ISCSI_PDU_NONPAYLOAD_LEN)
96 #define PPOD_PAGES_MAX 4
97 #define PPOD_PAGES_SHIFT 2 /* 4 pages per pod */
100 * struct pagepod_hdr, pagepod - pagepod format
111 struct pagepod_hdr hdr;
112 u64 addr[PPOD_PAGES_MAX + 1];
115 #define PPOD_SIZE sizeof(struct pagepod) /* 64 */
116 #define PPOD_SIZE_SHIFT 6
118 #define PPOD_COLOR_SHIFT 0
119 #define PPOD_COLOR_SIZE 6
120 #define PPOD_COLOR_MASK ((1 << PPOD_COLOR_SIZE) - 1)
122 #define PPOD_IDX_SHIFT PPOD_COLOR_SIZE
123 #define PPOD_IDX_MAX_SIZE 24
126 #define M_PPOD_TID 0xFFFFFF
127 #define V_PPOD_TID(x) ((x) << S_PPOD_TID)
129 #define S_PPOD_VALID 24
130 #define V_PPOD_VALID(x) ((x) << S_PPOD_VALID)
131 #define F_PPOD_VALID V_PPOD_VALID(1U)
133 #define S_PPOD_COLOR 0
134 #define M_PPOD_COLOR 0x3F
135 #define V_PPOD_COLOR(x) ((x) << S_PPOD_COLOR)
138 #define M_PPOD_TAG 0xFFFFFF
139 #define V_PPOD_TAG(x) ((x) << S_PPOD_TAG)
141 #define S_PPOD_PGSZ 30
142 #define M_PPOD_PGSZ 0x3
143 #define V_PPOD_PGSZ(x) ((x) << S_PPOD_PGSZ)
146 * large memory chunk allocation/release
147 * use vmalloc() if kmalloc() fails
149 static inline void *cxgb3i_alloc_big_mem(unsigned int size,
152 void *p = kmalloc(size, gfp);
160 static inline void cxgb3i_free_big_mem(void *addr)
162 if (is_vmalloc_addr(addr))
169 * cxgb3i ddp tag are 32 bits, it consists of reserved bits used by h/w and
170 * non-reserved bits that can be used by the iscsi s/w.
171 * The reserved bits are identified by the rsvd_bits and rsvd_shift fields
172 * in struct cxgb3i_tag_format.
174 * The upper most reserved bit can be used to check if a tag is ddp tag or not:
175 * if the bit is 0, the tag is a valid ddp tag
179 * cxgb3i_is_ddp_tag - check if a given tag is a hw/ddp tag
180 * @tformat: tag format information
181 * @tag: tag to be checked
183 * return true if the tag is a ddp tag, false otherwise.
185 static inline int cxgb3i_is_ddp_tag(struct cxgb3i_tag_format *tformat, u32 tag)
187 return !(tag & (1 << (tformat->rsvd_bits + tformat->rsvd_shift - 1)));
191 * cxgb3i_sw_tag_usable - check if s/w tag has enough bits left for hw bits
192 * @tformat: tag format information
193 * @sw_tag: s/w tag to be checked
195 * return true if the tag can be used for hw ddp tag, false otherwise.
197 static inline int cxgb3i_sw_tag_usable(struct cxgb3i_tag_format *tformat,
200 sw_tag >>= (32 - tformat->rsvd_bits);
205 * cxgb3i_set_non_ddp_tag - mark a given s/w tag as an invalid ddp tag
206 * @tformat: tag format information
207 * @sw_tag: s/w tag to be checked
209 * insert 1 at the upper most reserved bit to mark it as an invalid ddp tag.
211 static inline u32 cxgb3i_set_non_ddp_tag(struct cxgb3i_tag_format *tformat,
214 unsigned char shift = tformat->rsvd_bits + tformat->rsvd_shift - 1;
215 u32 mask = (1 << shift) - 1;
217 if (sw_tag && (sw_tag & ~mask)) {
218 u32 v1 = sw_tag & ((1 << shift) - 1);
219 u32 v2 = (sw_tag >> (shift - 1)) << shift;
221 return v2 | v1 | 1 << shift;
223 return sw_tag | 1 << shift;
227 * cxgb3i_ddp_tag_base - shift s/w tag bits so that reserved bits are not used
228 * @tformat: tag format information
229 * @sw_tag: s/w tag to be checked
231 static inline u32 cxgb3i_ddp_tag_base(struct cxgb3i_tag_format *tformat,
234 u32 mask = (1 << tformat->rsvd_shift) - 1;
236 if (sw_tag && (sw_tag & ~mask)) {
237 u32 v1 = sw_tag & mask;
238 u32 v2 = sw_tag >> tformat->rsvd_shift;
240 v2 <<= tformat->rsvd_shift + tformat->rsvd_bits;
247 * cxgb3i_tag_rsvd_bits - get the reserved bits used by the h/w
248 * @tformat: tag format information
249 * @tag: tag to be checked
251 * return the reserved bits in the tag
253 static inline u32 cxgb3i_tag_rsvd_bits(struct cxgb3i_tag_format *tformat,
256 if (cxgb3i_is_ddp_tag(tformat, tag))
257 return (tag >> tformat->rsvd_shift) & tformat->rsvd_mask;
262 * cxgb3i_tag_nonrsvd_bits - get the non-reserved bits used by the s/w
263 * @tformat: tag format information
264 * @tag: tag to be checked
266 * return the non-reserved bits in the tag.
268 static inline u32 cxgb3i_tag_nonrsvd_bits(struct cxgb3i_tag_format *tformat,
271 unsigned char shift = tformat->rsvd_bits + tformat->rsvd_shift - 1;
274 if (cxgb3i_is_ddp_tag(tformat, tag)) {
275 v1 = tag & ((1 << tformat->rsvd_shift) - 1);
276 v2 = (tag >> (shift + 1)) << tformat->rsvd_shift;
278 u32 mask = (1 << shift) - 1;
280 tag &= ~(1 << shift);
282 v2 = (tag >> 1) & ~mask;
287 int cxgb3i_ddp_tag_reserve(struct t3cdev *, unsigned int tid,
288 struct cxgb3i_tag_format *, u32 *tag,
289 struct cxgb3i_gather_list *, gfp_t gfp);
290 void cxgb3i_ddp_tag_release(struct t3cdev *, u32 tag);
292 struct cxgb3i_gather_list *cxgb3i_ddp_make_gl(unsigned int xferlen,
293 struct scatterlist *sgl,
295 struct pci_dev *pdev,
297 void cxgb3i_ddp_release_gl(struct cxgb3i_gather_list *gl,
298 struct pci_dev *pdev);
300 int cxgb3i_setup_conn_host_pagesize(struct t3cdev *, unsigned int tid,
302 int cxgb3i_setup_conn_pagesize(struct t3cdev *, unsigned int tid, int reply,
304 int cxgb3i_setup_conn_digest(struct t3cdev *, unsigned int tid,
305 int hcrc, int dcrc, int reply);
306 int cxgb3i_ddp_find_page_index(unsigned long pgsz);
307 int cxgb3i_adapter_ddp_info(struct t3cdev *, struct cxgb3i_tag_format *,
308 unsigned int *txsz, unsigned int *rxsz);
310 void cxgb3i_ddp_init(struct t3cdev *);
311 void cxgb3i_ddp_cleanup(struct t3cdev *);