Commit | Line | Data |
---|---|---|
a3667aae NKI |
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 | ||
30564db7 BVA |
191 | struct csio_cmd_priv { |
192 | uint8_t fc_tm_flags; /* task management flags */ | |
193 | uint16_t wr_status; | |
194 | }; | |
195 | ||
196 | static inline struct csio_cmd_priv *csio_priv(struct scsi_cmnd *cmd) | |
197 | { | |
198 | return scsi_cmd_priv(cmd); | |
199 | } | |
200 | ||
a3667aae NKI |
201 | static inline struct csio_ioreq * |
202 | csio_get_scsi_ioreq(struct csio_scsim *scm) | |
203 | { | |
204 | struct csio_sm *req; | |
205 | ||
206 | if (likely(!list_empty(&scm->ioreq_freelist))) { | |
207 | req = list_first_entry(&scm->ioreq_freelist, | |
208 | struct csio_sm, sm_list); | |
209 | list_del_init(&req->sm_list); | |
210 | CSIO_DEC_STATS(scm, n_free_ioreq); | |
211 | return (struct csio_ioreq *)req; | |
212 | } else | |
213 | return NULL; | |
214 | } | |
215 | ||
216 | static inline void | |
217 | csio_put_scsi_ioreq(struct csio_scsim *scm, struct csio_ioreq *ioreq) | |
218 | { | |
219 | list_add_tail(&ioreq->sm.sm_list, &scm->ioreq_freelist); | |
220 | CSIO_INC_STATS(scm, n_free_ioreq); | |
221 | } | |
222 | ||
223 | static inline void | |
224 | csio_put_scsi_ioreq_list(struct csio_scsim *scm, struct list_head *reqlist, | |
225 | int n) | |
226 | { | |
227 | list_splice_init(reqlist, &scm->ioreq_freelist); | |
228 | scm->stats.n_free_ioreq += n; | |
229 | } | |
230 | ||
231 | static inline struct csio_dma_buf * | |
232 | csio_get_scsi_ddp(struct csio_scsim *scm) | |
233 | { | |
234 | struct csio_dma_buf *ddp; | |
235 | ||
236 | if (likely(!list_empty(&scm->ddp_freelist))) { | |
237 | ddp = list_first_entry(&scm->ddp_freelist, | |
238 | struct csio_dma_buf, list); | |
239 | list_del_init(&ddp->list); | |
240 | CSIO_DEC_STATS(scm, n_free_ddp); | |
241 | return ddp; | |
242 | } else | |
243 | return NULL; | |
244 | } | |
245 | ||
246 | static inline void | |
247 | csio_put_scsi_ddp(struct csio_scsim *scm, struct csio_dma_buf *ddp) | |
248 | { | |
249 | list_add_tail(&ddp->list, &scm->ddp_freelist); | |
250 | CSIO_INC_STATS(scm, n_free_ddp); | |
251 | } | |
252 | ||
253 | static inline void | |
254 | csio_put_scsi_ddp_list(struct csio_scsim *scm, struct list_head *reqlist, | |
255 | int n) | |
256 | { | |
257 | list_splice_tail_init(reqlist, &scm->ddp_freelist); | |
258 | scm->stats.n_free_ddp += n; | |
259 | } | |
260 | ||
261 | static inline void | |
262 | csio_scsi_completed(struct csio_ioreq *ioreq, struct list_head *cbfn_q) | |
263 | { | |
264 | csio_post_event(&ioreq->sm, CSIO_SCSIE_COMPLETED); | |
265 | if (csio_list_deleted(&ioreq->sm.sm_list)) | |
266 | list_add_tail(&ioreq->sm.sm_list, cbfn_q); | |
267 | } | |
268 | ||
269 | static inline void | |
270 | csio_scsi_aborted(struct csio_ioreq *ioreq, struct list_head *cbfn_q) | |
271 | { | |
272 | csio_post_event(&ioreq->sm, CSIO_SCSIE_ABORTED); | |
273 | list_add_tail(&ioreq->sm.sm_list, cbfn_q); | |
274 | } | |
275 | ||
276 | static inline void | |
277 | csio_scsi_closed(struct csio_ioreq *ioreq, struct list_head *cbfn_q) | |
278 | { | |
279 | csio_post_event(&ioreq->sm, CSIO_SCSIE_CLOSED); | |
280 | list_add_tail(&ioreq->sm.sm_list, cbfn_q); | |
281 | } | |
282 | ||
283 | static inline void | |
284 | csio_scsi_drvcleanup(struct csio_ioreq *ioreq) | |
285 | { | |
286 | csio_post_event(&ioreq->sm, CSIO_SCSIE_DRVCLEANUP); | |
287 | } | |
288 | ||
289 | /* | |
290 | * csio_scsi_start_io - Kick starts the IO SM. | |
291 | * @req: io request SM. | |
292 | * | |
293 | * needs to be called with lock held. | |
294 | */ | |
295 | static inline int | |
296 | csio_scsi_start_io(struct csio_ioreq *ioreq) | |
297 | { | |
298 | csio_post_event(&ioreq->sm, CSIO_SCSIE_START_IO); | |
299 | return ioreq->drv_status; | |
300 | } | |
301 | ||
302 | /* | |
303 | * csio_scsi_start_tm - Kicks off the Task management IO SM. | |
304 | * @req: io request SM. | |
305 | * | |
306 | * needs to be called with lock held. | |
307 | */ | |
308 | static inline int | |
309 | csio_scsi_start_tm(struct csio_ioreq *ioreq) | |
310 | { | |
311 | csio_post_event(&ioreq->sm, CSIO_SCSIE_START_TM); | |
312 | return ioreq->drv_status; | |
313 | } | |
314 | ||
315 | /* | |
316 | * csio_scsi_abort - Abort an IO request | |
317 | * @req: io request SM. | |
318 | * | |
319 | * needs to be called with lock held. | |
320 | */ | |
321 | static inline int | |
322 | csio_scsi_abort(struct csio_ioreq *ioreq) | |
323 | { | |
324 | csio_post_event(&ioreq->sm, CSIO_SCSIE_ABORT); | |
325 | return ioreq->drv_status; | |
326 | } | |
327 | ||
328 | /* | |
329 | * csio_scsi_close - Close an IO request | |
330 | * @req: io request SM. | |
331 | * | |
332 | * needs to be called with lock held. | |
333 | */ | |
334 | static inline int | |
335 | csio_scsi_close(struct csio_ioreq *ioreq) | |
336 | { | |
337 | csio_post_event(&ioreq->sm, CSIO_SCSIE_CLOSE); | |
338 | return ioreq->drv_status; | |
339 | } | |
340 | ||
341 | void csio_scsi_cleanup_io_q(struct csio_scsim *, struct list_head *); | |
342 | int csio_scsim_cleanup_io(struct csio_scsim *, bool abort); | |
343 | int csio_scsim_cleanup_io_lnode(struct csio_scsim *, | |
344 | struct csio_lnode *); | |
345 | struct csio_ioreq *csio_scsi_cmpl_handler(struct csio_hw *, void *, uint32_t, | |
346 | struct csio_fl_dma_buf *, | |
347 | void *, uint8_t **); | |
348 | int csio_scsi_qconfig(struct csio_hw *); | |
349 | int csio_scsim_init(struct csio_scsim *, struct csio_hw *); | |
350 | void csio_scsim_exit(struct csio_scsim *); | |
351 | ||
352 | #endif /* __CSIO_SCSI_H__ */ |