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