1
2
3
4
5
6
7
8
9
10
11
12
13#ifndef __CXGB3I_ULP2_DDP_H__
14#define __CXGB3I_ULP2_DDP_H__
15
16#include <linux/vmalloc.h>
17
18
19
20
21
22
23
24
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
36
37
38
39
40
41
42
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
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
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
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
97
98
99
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)
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
146
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
169
170
171
172
173
174
175
176
177
178
179
180
181
182
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
191
192
193
194
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
205
206
207
208
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
227
228
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
247
248
249
250
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
262
263
264
265
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