diff options
Diffstat (limited to 'drivers/scsi/csiostor/csio_scsi.h')
-rw-r--r-- | drivers/scsi/csiostor/csio_scsi.h | 342 |
1 files changed, 342 insertions, 0 deletions
diff --git a/drivers/scsi/csiostor/csio_scsi.h b/drivers/scsi/csiostor/csio_scsi.h new file mode 100644 index 000000000000..2257c3dcf724 --- /dev/null +++ b/drivers/scsi/csiostor/csio_scsi.h | |||
@@ -0,0 +1,342 @@ | |||
1 | /* | ||
2 | * This file is part of the Chelsio FCoE driver for Linux. | ||
3 | * | ||
4 | * Copyright (c) 2008-2012 Chelsio Communications, Inc. All rights reserved. | ||
5 | * | ||
6 | * This software is available to you under a choice of one of two | ||
7 | * licenses. You may choose to be licensed under the terms of the GNU | ||
8 | * General Public License (GPL) Version 2, available from the file | ||
9 | * COPYING in the main directory of this source tree, or the | ||
10 | * OpenIB.org BSD license below: | ||
11 | * | ||
12 | * Redistribution and use in source and binary forms, with or | ||
13 | * without modification, are permitted provided that the following | ||
14 | * conditions are met: | ||
15 | * | ||
16 | * - Redistributions of source code must retain the above | ||
17 | * copyright notice, this list of conditions and the following | ||
18 | * disclaimer. | ||
19 | * | ||
20 | * - Redistributions in binary form must reproduce the above | ||
21 | * copyright notice, this list of conditions and the following | ||
22 | * disclaimer in the documentation and/or other materials | ||
23 | * provided with the distribution. | ||
24 | * | ||
25 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, | ||
26 | * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF | ||
27 | * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND | ||
28 | * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS | ||
29 | * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN | ||
30 | * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN | ||
31 | * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE | ||
32 | * SOFTWARE. | ||
33 | */ | ||
34 | |||
35 | #ifndef __CSIO_SCSI_H__ | ||
36 | #define __CSIO_SCSI_H__ | ||
37 | |||
38 | #include <linux/spinlock_types.h> | ||
39 | #include <linux/completion.h> | ||
40 | #include <scsi/scsi.h> | ||
41 | #include <scsi/scsi_cmnd.h> | ||
42 | #include <scsi/scsi_device.h> | ||
43 | #include <scsi/scsi_host.h> | ||
44 | #include <scsi/scsi_eh.h> | ||
45 | #include <scsi/scsi_tcq.h> | ||
46 | #include <scsi/fc/fc_fcp.h> | ||
47 | |||
48 | #include "csio_defs.h" | ||
49 | #include "csio_wr.h" | ||
50 | |||
51 | extern struct scsi_host_template csio_fcoe_shost_template; | ||
52 | extern struct scsi_host_template csio_fcoe_shost_vport_template; | ||
53 | |||
54 | extern int csio_scsi_eqsize; | ||
55 | extern int csio_scsi_iqlen; | ||
56 | extern int csio_scsi_ioreqs; | ||
57 | extern uint32_t csio_max_scan_tmo; | ||
58 | extern uint32_t csio_delta_scan_tmo; | ||
59 | extern int csio_lun_qdepth; | ||
60 | |||
61 | /* | ||
62 | **************************** NOTE ******************************* | ||
63 | * How do we calculate MAX FCoE SCSI SGEs? Here is the math: | ||
64 | * Max Egress WR size = 512 bytes | ||
65 | * One SCSI egress WR has the following fixed no of bytes: | ||
66 | * 48 (sizeof(struct fw_scsi_write[read]_wr)) - FW WR | ||
67 | * + 32 (sizeof(struct fc_fcp_cmnd)) - Immediate FCP_CMD | ||
68 | * ------ | ||
69 | * 80 | ||
70 | * ------ | ||
71 | * That leaves us with 512 - 96 = 432 bytes for data SGE. Using | ||
72 | * struct ulptx_sgl header for the SGE consumes: | ||
73 | * - 4 bytes for cmnd_sge. | ||
74 | * - 12 bytes for the first SGL. | ||
75 | * That leaves us with 416 bytes for the remaining SGE pairs. Which is | ||
76 | * is 416 / 24 (size(struct ulptx_sge_pair)) = 17 SGE pairs, | ||
77 | * or 34 SGEs. Adding the first SGE fetches us 35 SGEs. | ||
78 | */ | ||
79 | #define CSIO_SCSI_MAX_SGE 35 | ||
80 | #define CSIO_SCSI_ABRT_TMO_MS 60000 | ||
81 | #define CSIO_SCSI_LUNRST_TMO_MS 60000 | ||
82 | #define CSIO_SCSI_TM_POLL_MS 2000 /* should be less than | ||
83 | * all TM timeouts. | ||
84 | */ | ||
85 | #define CSIO_SCSI_IQ_WRSZ 128 | ||
86 | #define CSIO_SCSI_IQSIZE (csio_scsi_iqlen * CSIO_SCSI_IQ_WRSZ) | ||
87 | |||
88 | #define CSIO_MAX_SNS_LEN 128 | ||
89 | #define CSIO_SCSI_RSP_LEN (FCP_RESP_WITH_EXT + 4 + CSIO_MAX_SNS_LEN) | ||
90 | |||
91 | /* Reference to scsi_cmnd */ | ||
92 | #define csio_scsi_cmnd(req) ((req)->scratch1) | ||
93 | |||
94 | struct csio_scsi_stats { | ||
95 | uint64_t n_tot_success; /* Total number of good I/Os */ | ||
96 | uint32_t n_rn_nr_error; /* No. of remote-node-not- | ||
97 | * ready errors | ||
98 | */ | ||
99 | uint32_t n_hw_nr_error; /* No. of hw-module-not- | ||
100 | * ready errors | ||
101 | */ | ||
102 | uint32_t n_dmamap_error; /* No. of DMA map erros */ | ||
103 | uint32_t n_unsupp_sge_error; /* No. of too-many-SGes | ||
104 | * errors. | ||
105 | */ | ||
106 | uint32_t n_no_req_error; /* No. of Out-of-ioreqs error */ | ||
107 | uint32_t n_busy_error; /* No. of -EBUSY errors */ | ||
108 | uint32_t n_hosterror; /* No. of FW_HOSTERROR I/O */ | ||
109 | uint32_t n_rsperror; /* No. of response errors */ | ||
110 | uint32_t n_autosense; /* No. of auto sense replies */ | ||
111 | uint32_t n_ovflerror; /* No. of overflow errors */ | ||
112 | uint32_t n_unflerror; /* No. of underflow errors */ | ||
113 | uint32_t n_rdev_nr_error;/* No. of rdev not | ||
114 | * ready errors | ||
115 | */ | ||
116 | uint32_t n_rdev_lost_error;/* No. of rdev lost errors */ | ||
117 | uint32_t n_rdev_logo_error;/* No. of rdev logo errors */ | ||
118 | uint32_t n_link_down_error;/* No. of link down errors */ | ||
119 | uint32_t n_no_xchg_error; /* No. no exchange error */ | ||
120 | uint32_t n_unknown_error;/* No. of unhandled errors */ | ||
121 | uint32_t n_aborted; /* No. of aborted I/Os */ | ||
122 | uint32_t n_abrt_timedout; /* No. of abort timedouts */ | ||
123 | uint32_t n_abrt_fail; /* No. of abort failures */ | ||
124 | uint32_t n_abrt_dups; /* No. of duplicate aborts */ | ||
125 | uint32_t n_abrt_race_comp; /* No. of aborts that raced | ||
126 | * with completions. | ||
127 | */ | ||
128 | uint32_t n_abrt_busy_error;/* No. of abort failures | ||
129 | * due to -EBUSY. | ||
130 | */ | ||
131 | uint32_t n_closed; /* No. of closed I/Os */ | ||
132 | uint32_t n_cls_busy_error; /* No. of close failures | ||
133 | * due to -EBUSY. | ||
134 | */ | ||
135 | uint32_t n_active; /* No. of IOs in active_q */ | ||
136 | uint32_t n_tm_active; /* No. of TMs in active_q */ | ||
137 | uint32_t n_wcbfn; /* No. of I/Os in worker | ||
138 | * cbfn q | ||
139 | */ | ||
140 | uint32_t n_free_ioreq; /* No. of freelist entries */ | ||
141 | uint32_t n_free_ddp; /* No. of DDP freelist */ | ||
142 | uint32_t n_unaligned; /* No. of Unaligned SGls */ | ||
143 | uint32_t n_inval_cplop; /* No. invalid CPL op's in IQ */ | ||
144 | uint32_t n_inval_scsiop; /* No. invalid scsi op's in IQ*/ | ||
145 | }; | ||
146 | |||
147 | struct csio_scsim { | ||
148 | struct csio_hw *hw; /* Pointer to HW moduel */ | ||
149 | uint8_t max_sge; /* Max SGE */ | ||
150 | uint8_t proto_cmd_len; /* Proto specific SCSI | ||
151 | * cmd length | ||
152 | */ | ||
153 | uint16_t proto_rsp_len; /* Proto specific SCSI | ||
154 | * response length | ||
155 | */ | ||
156 | spinlock_t freelist_lock; /* Lock for ioreq freelist */ | ||
157 | struct list_head active_q; /* Outstanding SCSI I/Os */ | ||
158 | struct list_head ioreq_freelist; /* Free list of ioreq's */ | ||
159 | struct list_head ddp_freelist; /* DDP descriptor freelist */ | ||
160 | struct csio_scsi_stats stats; /* This module's statistics */ | ||
161 | }; | ||
162 | |||
163 | /* State machine defines */ | ||
164 | enum csio_scsi_ev { | ||
165 | CSIO_SCSIE_START_IO = 1, /* Start a regular SCSI IO */ | ||
166 | CSIO_SCSIE_START_TM, /* Start a TM IO */ | ||
167 | CSIO_SCSIE_COMPLETED, /* IO Completed */ | ||
168 | CSIO_SCSIE_ABORT, /* Abort IO */ | ||
169 | CSIO_SCSIE_ABORTED, /* IO Aborted */ | ||
170 | CSIO_SCSIE_CLOSE, /* Close exchange */ | ||
171 | CSIO_SCSIE_CLOSED, /* Exchange closed */ | ||
172 | CSIO_SCSIE_DRVCLEANUP, /* Driver wants to manually | ||
173 | * cleanup this I/O. | ||
174 | */ | ||
175 | }; | ||
176 | |||
177 | enum csio_scsi_lev { | ||
178 | CSIO_LEV_ALL = 1, | ||
179 | CSIO_LEV_LNODE, | ||
180 | CSIO_LEV_RNODE, | ||
181 | CSIO_LEV_LUN, | ||
182 | }; | ||
183 | |||
184 | struct csio_scsi_level_data { | ||
185 | enum csio_scsi_lev level; | ||
186 | struct csio_rnode *rnode; | ||
187 | struct csio_lnode *lnode; | ||
188 | uint64_t oslun; | ||
189 | }; | ||
190 | |||
191 | static inline struct csio_ioreq * | ||
192 | csio_get_scsi_ioreq(struct csio_scsim *scm) | ||
193 | { | ||
194 | struct csio_sm *req; | ||
195 | |||
196 | if (likely(!list_empty(&scm->ioreq_freelist))) { | ||
197 | req = list_first_entry(&scm->ioreq_freelist, | ||
198 | struct csio_sm, sm_list); | ||
199 | list_del_init(&req->sm_list); | ||
200 | CSIO_DEC_STATS(scm, n_free_ioreq); | ||
201 | return (struct csio_ioreq *)req; | ||
202 | } else | ||
203 | return NULL; | ||
204 | } | ||
205 | |||
206 | static inline void | ||
207 | csio_put_scsi_ioreq(struct csio_scsim *scm, struct csio_ioreq *ioreq) | ||
208 | { | ||
209 | list_add_tail(&ioreq->sm.sm_list, &scm->ioreq_freelist); | ||
210 | CSIO_INC_STATS(scm, n_free_ioreq); | ||
211 | } | ||
212 | |||
213 | static inline void | ||
214 | csio_put_scsi_ioreq_list(struct csio_scsim *scm, struct list_head *reqlist, | ||
215 | int n) | ||
216 | { | ||
217 | list_splice_init(reqlist, &scm->ioreq_freelist); | ||
218 | scm->stats.n_free_ioreq += n; | ||
219 | } | ||
220 | |||
221 | static inline struct csio_dma_buf * | ||
222 | csio_get_scsi_ddp(struct csio_scsim *scm) | ||
223 | { | ||
224 | struct csio_dma_buf *ddp; | ||
225 | |||
226 | if (likely(!list_empty(&scm->ddp_freelist))) { | ||
227 | ddp = list_first_entry(&scm->ddp_freelist, | ||
228 | struct csio_dma_buf, list); | ||
229 | list_del_init(&ddp->list); | ||
230 | CSIO_DEC_STATS(scm, n_free_ddp); | ||
231 | return ddp; | ||
232 | } else | ||
233 | return NULL; | ||
234 | } | ||
235 | |||
236 | static inline void | ||
237 | csio_put_scsi_ddp(struct csio_scsim *scm, struct csio_dma_buf *ddp) | ||
238 | { | ||
239 | list_add_tail(&ddp->list, &scm->ddp_freelist); | ||
240 | CSIO_INC_STATS(scm, n_free_ddp); | ||
241 | } | ||
242 | |||
243 | static inline void | ||
244 | csio_put_scsi_ddp_list(struct csio_scsim *scm, struct list_head *reqlist, | ||
245 | int n) | ||
246 | { | ||
247 | list_splice_tail_init(reqlist, &scm->ddp_freelist); | ||
248 | scm->stats.n_free_ddp += n; | ||
249 | } | ||
250 | |||
251 | static inline void | ||
252 | csio_scsi_completed(struct csio_ioreq *ioreq, struct list_head *cbfn_q) | ||
253 | { | ||
254 | csio_post_event(&ioreq->sm, CSIO_SCSIE_COMPLETED); | ||
255 | if (csio_list_deleted(&ioreq->sm.sm_list)) | ||
256 | list_add_tail(&ioreq->sm.sm_list, cbfn_q); | ||
257 | } | ||
258 | |||
259 | static inline void | ||
260 | csio_scsi_aborted(struct csio_ioreq *ioreq, struct list_head *cbfn_q) | ||
261 | { | ||
262 | csio_post_event(&ioreq->sm, CSIO_SCSIE_ABORTED); | ||
263 | list_add_tail(&ioreq->sm.sm_list, cbfn_q); | ||
264 | } | ||
265 | |||
266 | static inline void | ||
267 | csio_scsi_closed(struct csio_ioreq *ioreq, struct list_head *cbfn_q) | ||
268 | { | ||
269 | csio_post_event(&ioreq->sm, CSIO_SCSIE_CLOSED); | ||
270 | list_add_tail(&ioreq->sm.sm_list, cbfn_q); | ||
271 | } | ||
272 | |||
273 | static inline void | ||
274 | csio_scsi_drvcleanup(struct csio_ioreq *ioreq) | ||
275 | { | ||
276 | csio_post_event(&ioreq->sm, CSIO_SCSIE_DRVCLEANUP); | ||
277 | } | ||
278 | |||
279 | /* | ||
280 | * csio_scsi_start_io - Kick starts the IO SM. | ||
281 | * @req: io request SM. | ||
282 | * | ||
283 | * needs to be called with lock held. | ||
284 | */ | ||
285 | static inline int | ||
286 | csio_scsi_start_io(struct csio_ioreq *ioreq) | ||
287 | { | ||
288 | csio_post_event(&ioreq->sm, CSIO_SCSIE_START_IO); | ||
289 | return ioreq->drv_status; | ||
290 | } | ||
291 | |||
292 | /* | ||
293 | * csio_scsi_start_tm - Kicks off the Task management IO SM. | ||
294 | * @req: io request SM. | ||
295 | * | ||
296 | * needs to be called with lock held. | ||
297 | */ | ||
298 | static inline int | ||
299 | csio_scsi_start_tm(struct csio_ioreq *ioreq) | ||
300 | { | ||
301 | csio_post_event(&ioreq->sm, CSIO_SCSIE_START_TM); | ||
302 | return ioreq->drv_status; | ||
303 | } | ||
304 | |||
305 | /* | ||
306 | * csio_scsi_abort - Abort an IO request | ||
307 | * @req: io request SM. | ||
308 | * | ||
309 | * needs to be called with lock held. | ||
310 | */ | ||
311 | static inline int | ||
312 | csio_scsi_abort(struct csio_ioreq *ioreq) | ||
313 | { | ||
314 | csio_post_event(&ioreq->sm, CSIO_SCSIE_ABORT); | ||
315 | return ioreq->drv_status; | ||
316 | } | ||
317 | |||
318 | /* | ||
319 | * csio_scsi_close - Close an IO request | ||
320 | * @req: io request SM. | ||
321 | * | ||
322 | * needs to be called with lock held. | ||
323 | */ | ||
324 | static inline int | ||
325 | csio_scsi_close(struct csio_ioreq *ioreq) | ||
326 | { | ||
327 | csio_post_event(&ioreq->sm, CSIO_SCSIE_CLOSE); | ||
328 | return ioreq->drv_status; | ||
329 | } | ||
330 | |||
331 | void csio_scsi_cleanup_io_q(struct csio_scsim *, struct list_head *); | ||
332 | int csio_scsim_cleanup_io(struct csio_scsim *, bool abort); | ||
333 | int csio_scsim_cleanup_io_lnode(struct csio_scsim *, | ||
334 | struct csio_lnode *); | ||
335 | struct csio_ioreq *csio_scsi_cmpl_handler(struct csio_hw *, void *, uint32_t, | ||
336 | struct csio_fl_dma_buf *, | ||
337 | void *, uint8_t **); | ||
338 | int csio_scsi_qconfig(struct csio_hw *); | ||
339 | int csio_scsim_init(struct csio_scsim *, struct csio_hw *); | ||
340 | void csio_scsim_exit(struct csio_scsim *); | ||
341 | |||
342 | #endif /* __CSIO_SCSI_H__ */ | ||