• Home
  • History
  • Annotate
  • Line#
  • Navigate
  • Raw
  • Download
  • only in /netgear-R7000-V1.0.7.12_1.2.5/components/opensource/linux/linux-2.6.36/drivers/scsi/cxgb3i/
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/slab.h>
17#include <linux/vmalloc.h>
18
19/**
20 * struct cxgb3i_tag_format - cxgb3i ulp tag format for an iscsi entity
21 *
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
26 */
27struct cxgb3i_tag_format {
28	unsigned char sw_bits;
29	unsigned char rsvd_bits;
30	unsigned char rsvd_shift;
31	unsigned char filler[1];
32	u32 rsvd_mask;
33};
34
35/**
36 * struct cxgb3i_gather_list - cxgb3i direct data placement memory
37 *
38 * @tag:	ddp tag
39 * @length:	total data buffer length
40 * @offset:	initial offset to the 1st page
41 * @nelem:	# of pages
42 * @pages:	page pointers
43 * @phys_addr:	physical address
44 */
45struct cxgb3i_gather_list {
46	u32 tag;
47	unsigned int length;
48	unsigned int offset;
49	unsigned int nelem;
50	struct page **pages;
51	dma_addr_t phys_addr[0];
52};
53
54/**
55 * struct cxgb3i_ddp_info - cxgb3i direct data placement for pdu payload
56 *
57 * @list:	list head to link elements
58 * @refcnt:	ref. count
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
72 */
73struct cxgb3i_ddp_info {
74	struct list_head list;
75	struct kref refcnt;
76	struct t3cdev *tdev;
77	struct pci_dev *pdev;
78	unsigned int max_txsz;
79	unsigned int max_rxsz;
80	unsigned int llimit;
81	unsigned int ulimit;
82	unsigned int nppods;
83	unsigned int idx_last;
84	unsigned char idx_bits;
85	unsigned char filler[3];
86	u32 idx_mask;
87	u32 rsvd_tag_mask;
88	spinlock_t map_lock;
89	struct cxgb3i_gather_list **gl_map;
90	struct sk_buff **gl_skb;
91};
92
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 */
98
99/*
100 * struct pagepod_hdr, pagepod - pagepod format
101 */
102struct pagepod_hdr {
103	u32 vld_tid;
104	u32 pgsz_tag_clr;
105	u32 maxoffset;
106	u32 pgoffset;
107	u64 rsvd;
108};
109
110struct pagepod {
111	struct pagepod_hdr hdr;
112	u64 addr[PPOD_PAGES_MAX + 1];
113};
114
115#define PPOD_SIZE		sizeof(struct pagepod)	/* 64 */
116#define PPOD_SIZE_SHIFT		6
117
118#define PPOD_COLOR_SHIFT	0
119#define PPOD_COLOR_SIZE		6
120#define PPOD_COLOR_MASK		((1 << PPOD_COLOR_SIZE) - 1)
121
122#define PPOD_IDX_SHIFT		PPOD_COLOR_SIZE
123#define PPOD_IDX_MAX_SIZE	24
124
125#define S_PPOD_TID    0
126#define M_PPOD_TID    0xFFFFFF
127#define V_PPOD_TID(x) ((x) << S_PPOD_TID)
128
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)
132
133#define S_PPOD_COLOR    0
134#define M_PPOD_COLOR    0x3F
135#define V_PPOD_COLOR(x) ((x) << S_PPOD_COLOR)
136
137#define S_PPOD_TAG    6
138#define M_PPOD_TAG    0xFFFFFF
139#define V_PPOD_TAG(x) ((x) << S_PPOD_TAG)
140
141#define S_PPOD_PGSZ    30
142#define M_PPOD_PGSZ    0x3
143#define V_PPOD_PGSZ(x) ((x) << S_PPOD_PGSZ)
144
145/*
146 * large memory chunk allocation/release
147 * use vmalloc() if kmalloc() fails
148 */
149static inline void *cxgb3i_alloc_big_mem(unsigned int size,
150					 gfp_t gfp)
151{
152	void *p = kmalloc(size, gfp);
153	if (!p)
154		p = vmalloc(size);
155	if (p)
156		memset(p, 0, size);
157	return p;
158}
159
160static inline void cxgb3i_free_big_mem(void *addr)
161{
162	if (is_vmalloc_addr(addr))
163		vfree(addr);
164	else
165		kfree(addr);
166}
167
168/*
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.
173 *
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
176 */
177
178/**
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
182 *
183 * return true if the tag is a ddp tag, false otherwise.
184 */
185static inline int cxgb3i_is_ddp_tag(struct cxgb3i_tag_format *tformat, u32 tag)
186{
187	return !(tag & (1 << (tformat->rsvd_bits + tformat->rsvd_shift - 1)));
188}
189
190/**
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
194 *
195 * return true if the tag can be used for hw ddp tag, false otherwise.
196 */
197static inline int cxgb3i_sw_tag_usable(struct cxgb3i_tag_format *tformat,
198					u32 sw_tag)
199{
200	sw_tag >>= (32 - tformat->rsvd_bits);
201	return !sw_tag;
202}
203
204/**
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
208 *
209 * insert 1 at the upper most reserved bit to mark it as an invalid ddp tag.
210 */
211static inline u32 cxgb3i_set_non_ddp_tag(struct cxgb3i_tag_format *tformat,
212					 u32 sw_tag)
213{
214	unsigned char shift = tformat->rsvd_bits + tformat->rsvd_shift - 1;
215	u32 mask = (1 << shift) - 1;
216
217	if (sw_tag && (sw_tag & ~mask)) {
218		u32 v1 = sw_tag & ((1 << shift) - 1);
219		u32 v2 = (sw_tag >> (shift - 1)) << shift;
220
221		return v2 | v1 | 1 << shift;
222	}
223	return sw_tag | 1 << shift;
224}
225
226/**
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
230 */
231static inline u32 cxgb3i_ddp_tag_base(struct cxgb3i_tag_format *tformat,
232				      u32 sw_tag)
233{
234	u32 mask = (1 << tformat->rsvd_shift) - 1;
235
236	if (sw_tag && (sw_tag & ~mask)) {
237		u32 v1 = sw_tag & mask;
238		u32 v2 = sw_tag >> tformat->rsvd_shift;
239
240		v2 <<= tformat->rsvd_shift + tformat->rsvd_bits;
241		return v2 | v1;
242	}
243	return sw_tag;
244}
245
246/**
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
250 *
251 * return the reserved bits in the tag
252 */
253static inline u32 cxgb3i_tag_rsvd_bits(struct cxgb3i_tag_format *tformat,
254				       u32 tag)
255{
256	if (cxgb3i_is_ddp_tag(tformat, tag))
257		return (tag >> tformat->rsvd_shift) & tformat->rsvd_mask;
258	return 0;
259}
260
261/**
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
265 *
266 * return the non-reserved bits in the tag.
267 */
268static inline u32 cxgb3i_tag_nonrsvd_bits(struct cxgb3i_tag_format *tformat,
269					  u32 tag)
270{
271	unsigned char shift = tformat->rsvd_bits + tformat->rsvd_shift - 1;
272	u32 v1, v2;
273
274	if (cxgb3i_is_ddp_tag(tformat, tag)) {
275		v1 = tag & ((1 << tformat->rsvd_shift) - 1);
276		v2 = (tag >> (shift + 1)) << tformat->rsvd_shift;
277	} else {
278		u32 mask = (1 << shift) - 1;
279
280		tag &= ~(1 << shift);
281		v1 = tag & mask;
282		v2 = (tag >> 1) & ~mask;
283	}
284	return v1 | v2;
285}
286
287int cxgb3i_ddp_tag_reserve(struct t3cdev *, unsigned int tid,
288			   struct cxgb3i_tag_format *, u32 *tag,
289			   struct cxgb3i_gather_list *, gfp_t gfp);
290void cxgb3i_ddp_tag_release(struct t3cdev *, u32 tag);
291
292struct cxgb3i_gather_list *cxgb3i_ddp_make_gl(unsigned int xferlen,
293				struct scatterlist *sgl,
294				unsigned int sgcnt,
295				struct pci_dev *pdev,
296				gfp_t gfp);
297void cxgb3i_ddp_release_gl(struct cxgb3i_gather_list *gl,
298				struct pci_dev *pdev);
299
300int cxgb3i_setup_conn_host_pagesize(struct t3cdev *, unsigned int tid,
301				    int reply);
302int cxgb3i_setup_conn_pagesize(struct t3cdev *, unsigned int tid, int reply,
303			       unsigned long pgsz);
304int cxgb3i_setup_conn_digest(struct t3cdev *, unsigned int tid,
305				int hcrc, int dcrc, int reply);
306int cxgb3i_ddp_find_page_index(unsigned long pgsz);
307int cxgb3i_adapter_ddp_info(struct t3cdev *, struct cxgb3i_tag_format *,
308			    unsigned int *txsz, unsigned int *rxsz);
309
310void cxgb3i_ddp_init(struct t3cdev *);
311void cxgb3i_ddp_cleanup(struct t3cdev *);
312#endif
313