]> git.proxmox.com Git - mirror_ubuntu-jammy-kernel.git/blame - drivers/scsi/cxgb3i/cxgb3i_ddp.h
sd: Block limits VPD support
[mirror_ubuntu-jammy-kernel.git] / drivers / scsi / cxgb3i / cxgb3i_ddp.h
CommitLineData
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 */
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 * @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 */
71struct 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 */
99struct pagepod_hdr {
100 u32 vld_tid;
101 u32 pgsz_tag_clr;
102 u32 maxoffset;
103 u32 pgoffset;
104 u64 rsvd;
105};
106
107struct 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 */
146static 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
157static 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 */
182static 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 */
194static 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 */
208static 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 */
228static 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 */
250static 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 */
265static 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
284int cxgb3i_ddp_tag_reserve(struct t3cdev *, unsigned int tid,
285 struct cxgb3i_tag_format *, u32 *tag,
286 struct cxgb3i_gather_list *, gfp_t gfp);
287void cxgb3i_ddp_tag_release(struct t3cdev *, u32 tag);
288
289struct 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);
294void cxgb3i_ddp_release_gl(struct cxgb3i_gather_list *gl,
295 struct pci_dev *pdev);
296
297int cxgb3i_setup_conn_host_pagesize(struct t3cdev *, unsigned int tid,
298 int reply);
299int cxgb3i_setup_conn_pagesize(struct t3cdev *, unsigned int tid, int reply,
300 unsigned long pgsz);
301int cxgb3i_setup_conn_digest(struct t3cdev *, unsigned int tid,
302 int hcrc, int dcrc, int reply);
303int cxgb3i_ddp_find_page_index(unsigned long pgsz);
9fa1926a 304int cxgb3i_adapter_ddp_info(struct t3cdev *, struct cxgb3i_tag_format *,
c3673464 305 unsigned int *txsz, unsigned int *rxsz);
0d0c27f2
KX
306
307void cxgb3i_ddp_init(struct t3cdev *);
308void cxgb3i_ddp_cleanup(struct t3cdev *);
c3673464 309#endif