Commit | Line | Data |
---|---|---|
2b604c9b CS |
1 | /* |
2 | * This file is part of the zfcp device driver for | |
3 | * FCP adapters for IBM System z9 and zSeries. | |
4 | * | |
d46f384a | 5 | * Copyright IBM Corp. 2008, 2009 |
2b604c9b CS |
6 | * |
7 | * This program is free software; you can redistribute it and/or modify | |
8 | * it under the terms of the GNU General Public License as published by | |
9 | * the Free Software Foundation; either version 2, or (at your option) | |
10 | * any later version. | |
11 | * | |
12 | * This program is distributed in the hope that it will be useful, | |
13 | * but WITHOUT ANY WARRANTY; without even the implied warranty of | |
14 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | |
15 | * GNU General Public License for more details. | |
16 | * | |
17 | * You should have received a copy of the GNU General Public License | |
18 | * along with this program; if not, write to the Free Software | |
19 | * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. | |
20 | */ | |
21 | ||
22 | #ifndef ZFCP_DBF_H | |
23 | #define ZFCP_DBF_H | |
24 | ||
4318e08c | 25 | #include <scsi/fc/fc_fcp.h> |
dcd20e23 | 26 | #include "zfcp_ext.h" |
2b604c9b | 27 | #include "zfcp_fsf.h" |
dcd20e23 | 28 | #include "zfcp_def.h" |
2b604c9b | 29 | |
ae0904f6 | 30 | #define ZFCP_DBF_TAG_LEN 7 |
2b604c9b | 31 | #define ZFCP_DBF_TAG_SIZE 4 |
5ffd51a5 | 32 | #define ZFCP_DBF_ID_SIZE 7 |
2b604c9b | 33 | |
d21e9daa CS |
34 | #define ZFCP_DBF_INVALID_LUN 0xFFFFFFFFFFFFFFFFull |
35 | ||
2b604c9b CS |
36 | struct zfcp_dbf_dump { |
37 | u8 tag[ZFCP_DBF_TAG_SIZE]; | |
38 | u32 total_size; /* size of total dump data */ | |
39 | u32 offset; /* how much data has being already dumped */ | |
40 | u32 size; /* how much data comes with this record */ | |
41 | u8 data[]; /* dump data */ | |
42 | } __attribute__ ((packed)); | |
43 | ||
ae0904f6 SS |
44 | /** |
45 | * struct zfcp_dbf_rec_trigger - trace record for triggered recovery action | |
46 | * @ready: number of ready recovery actions | |
47 | * @running: number of running recovery actions | |
48 | * @want: wanted recovery action | |
49 | * @need: needed recovery action | |
50 | */ | |
51 | struct zfcp_dbf_rec_trigger { | |
2b604c9b CS |
52 | u32 ready; |
53 | u32 running; | |
2b604c9b CS |
54 | u8 want; |
55 | u8 need; | |
ae0904f6 SS |
56 | } __packed; |
57 | ||
58 | /** | |
59 | * struct zfcp_dbf_rec_running - trace record for running recovery | |
60 | * @fsf_req_id: request id for fsf requests | |
61 | * @rec_status: status of the fsf request | |
62 | * @rec_step: current step of the recovery action | |
63 | * rec_count: recovery counter | |
64 | */ | |
65 | struct zfcp_dbf_rec_running { | |
66 | u64 fsf_req_id; | |
67 | u32 rec_status; | |
68 | u16 rec_step; | |
69 | u8 rec_action; | |
70 | u8 rec_count; | |
71 | } __packed; | |
2b604c9b | 72 | |
ae0904f6 SS |
73 | /** |
74 | * enum zfcp_dbf_rec_id - recovery trace record id | |
75 | * @ZFCP_DBF_REC_TRIG: triggered recovery identifier | |
76 | * @ZFCP_DBF_REC_RUN: running recovery identifier | |
77 | */ | |
78 | enum zfcp_dbf_rec_id { | |
79 | ZFCP_DBF_REC_TRIG = 1, | |
80 | ZFCP_DBF_REC_RUN = 2, | |
7337891f | 81 | }; |
2b604c9b | 82 | |
ae0904f6 SS |
83 | /** |
84 | * struct zfcp_dbf_rec - trace record for error recovery actions | |
85 | * @id: unique number of recovery record type | |
86 | * @tag: identifier string specifying the location of initiation | |
87 | * @lun: logical unit number | |
88 | * @wwpn: word wide port number | |
89 | * @d_id: destination ID | |
90 | * @adapter_status: current status of the adapter | |
91 | * @port_status: current status of the port | |
92 | * @lun_status: current status of the lun | |
93 | * @u.trig: structure zfcp_dbf_rec_trigger | |
94 | * @u.run: structure zfcp_dbf_rec_running | |
95 | */ | |
96 | struct zfcp_dbf_rec { | |
2b604c9b | 97 | u8 id; |
ae0904f6 SS |
98 | char tag[ZFCP_DBF_TAG_LEN]; |
99 | u64 lun; | |
100 | u64 wwpn; | |
101 | u32 d_id; | |
102 | u32 adapter_status; | |
103 | u32 port_status; | |
104 | u32 lun_status; | |
2b604c9b | 105 | union { |
ae0904f6 SS |
106 | struct zfcp_dbf_rec_trigger trig; |
107 | struct zfcp_dbf_rec_running run; | |
2b604c9b | 108 | } u; |
ae0904f6 | 109 | } __packed; |
2b604c9b | 110 | |
2c55b750 SS |
111 | /** |
112 | * enum zfcp_dbf_san_id - SAN trace record identifier | |
113 | * @ZFCP_DBF_SAN_REQ: request trace record id | |
114 | * @ZFCP_DBF_SAN_RES: response trace record id | |
115 | * @ZFCP_DBF_SAN_ELS: extended link service record id | |
116 | */ | |
117 | enum zfcp_dbf_san_id { | |
118 | ZFCP_DBF_SAN_REQ = 1, | |
119 | ZFCP_DBF_SAN_RES = 2, | |
120 | ZFCP_DBF_SAN_ELS = 3, | |
121 | }; | |
122 | ||
123 | /** struct zfcp_dbf_san - trace record for SAN requests and responses | |
124 | * @id: unique number of recovery record type | |
125 | * @tag: identifier string specifying the location of initiation | |
126 | * @fsf_req_id: request id for fsf requests | |
127 | * @payload: unformatted information related to request/response | |
128 | * @d_id: destination id | |
129 | */ | |
130 | struct zfcp_dbf_san { | |
131 | u8 id; | |
132 | char tag[ZFCP_DBF_TAG_LEN]; | |
133 | u64 fsf_req_id; | |
134 | u32 d_id; | |
135 | #define ZFCP_DBF_SAN_MAX_PAYLOAD (FC_CT_HDR_LEN + 32) | |
136 | char payload[ZFCP_DBF_SAN_MAX_PAYLOAD]; | |
137 | } __packed; | |
138 | ||
5771710b | 139 | struct zfcp_dbf_hba_record_response { |
2b604c9b CS |
140 | u32 fsf_command; |
141 | u64 fsf_reqid; | |
142 | u32 fsf_seqno; | |
143 | u64 fsf_issued; | |
144 | u32 fsf_prot_status; | |
145 | u32 fsf_status; | |
146 | u8 fsf_prot_status_qual[FSF_PROT_STATUS_QUAL_SIZE]; | |
147 | u8 fsf_status_qual[FSF_STATUS_QUALIFIER_SIZE]; | |
148 | u32 fsf_req_status; | |
149 | u8 sbal_first; | |
e891bffe | 150 | u8 sbal_last; |
c3baa9a2 | 151 | u8 sbal_response; |
2b604c9b CS |
152 | u8 pool; |
153 | u64 erp_action; | |
154 | union { | |
155 | struct { | |
6bc473dd | 156 | u64 cmnd; |
ef3eb71d | 157 | u32 data_dir; |
6bc473dd | 158 | } fcp; |
2b604c9b CS |
159 | struct { |
160 | u64 wwpn; | |
161 | u32 d_id; | |
162 | u32 port_handle; | |
163 | } port; | |
164 | struct { | |
165 | u64 wwpn; | |
166 | u64 fcp_lun; | |
167 | u32 port_handle; | |
168 | u32 lun_handle; | |
169 | } unit; | |
170 | struct { | |
171 | u32 d_id; | |
6bc473dd MP |
172 | } els; |
173 | } u; | |
2b604c9b CS |
174 | } __attribute__ ((packed)); |
175 | ||
5771710b | 176 | struct zfcp_dbf_hba_record_status { |
2b604c9b CS |
177 | u8 failed; |
178 | u32 status_type; | |
179 | u32 status_subtype; | |
180 | struct fsf_queue_designator | |
181 | queue_designator; | |
182 | u32 payload_size; | |
183 | #define ZFCP_DBF_UNSOL_PAYLOAD 80 | |
184 | #define ZFCP_DBF_UNSOL_PAYLOAD_SENSE_DATA_AVAIL 32 | |
185 | #define ZFCP_DBF_UNSOL_PAYLOAD_BIT_ERROR_THRESHOLD 56 | |
186 | #define ZFCP_DBF_UNSOL_PAYLOAD_FEATURE_UPDATE_ALERT 2 * sizeof(u32) | |
187 | u8 payload[ZFCP_DBF_UNSOL_PAYLOAD]; | |
188 | } __attribute__ ((packed)); | |
189 | ||
5771710b | 190 | struct zfcp_dbf_hba_record_qdio { |
2b604c9b | 191 | u32 qdio_error; |
2b604c9b CS |
192 | u8 sbal_index; |
193 | u8 sbal_count; | |
194 | } __attribute__ ((packed)); | |
195 | ||
5771710b | 196 | struct zfcp_dbf_hba_record { |
2b604c9b CS |
197 | u8 tag[ZFCP_DBF_TAG_SIZE]; |
198 | u8 tag2[ZFCP_DBF_TAG_SIZE]; | |
199 | union { | |
5771710b SS |
200 | struct zfcp_dbf_hba_record_response response; |
201 | struct zfcp_dbf_hba_record_status status; | |
202 | struct zfcp_dbf_hba_record_qdio qdio; | |
57069386 | 203 | struct fsf_bit_error_payload berr; |
6bc473dd | 204 | } u; |
2b604c9b CS |
205 | } __attribute__ ((packed)); |
206 | ||
5771710b | 207 | struct zfcp_dbf_scsi_record { |
2b604c9b CS |
208 | u8 tag[ZFCP_DBF_TAG_SIZE]; |
209 | u8 tag2[ZFCP_DBF_TAG_SIZE]; | |
210 | u32 scsi_id; | |
211 | u32 scsi_lun; | |
212 | u32 scsi_result; | |
213 | u64 scsi_cmnd; | |
2b604c9b CS |
214 | #define ZFCP_DBF_SCSI_OPCODE 16 |
215 | u8 scsi_opcode[ZFCP_DBF_SCSI_OPCODE]; | |
216 | u8 scsi_retries; | |
217 | u8 scsi_allowed; | |
218 | u64 fsf_reqid; | |
219 | u32 fsf_seqno; | |
220 | u64 fsf_issued; | |
6bc473dd MP |
221 | u64 old_fsf_reqid; |
222 | u8 rsp_validity; | |
223 | u8 rsp_scsi_status; | |
224 | u32 rsp_resid; | |
225 | u8 rsp_code; | |
2b604c9b CS |
226 | #define ZFCP_DBF_SCSI_FCP_SNS_INFO 16 |
227 | #define ZFCP_DBF_SCSI_MAX_FCP_SNS_INFO 256 | |
6bc473dd MP |
228 | u32 sns_info_len; |
229 | u8 sns_info[ZFCP_DBF_SCSI_FCP_SNS_INFO]; | |
2b604c9b CS |
230 | } __attribute__ ((packed)); |
231 | ||
d46f384a | 232 | struct zfcp_dbf { |
5771710b SS |
233 | debug_info_t *rec; |
234 | debug_info_t *hba; | |
235 | debug_info_t *san; | |
236 | debug_info_t *scsi; | |
237 | spinlock_t rec_lock; | |
238 | spinlock_t hba_lock; | |
239 | spinlock_t san_lock; | |
240 | spinlock_t scsi_lock; | |
ae0904f6 | 241 | struct zfcp_dbf_rec rec_buf; |
5771710b | 242 | struct zfcp_dbf_hba_record hba_buf; |
2c55b750 | 243 | struct zfcp_dbf_san san_buf; |
5771710b SS |
244 | struct zfcp_dbf_scsi_record scsi_buf; |
245 | struct zfcp_adapter *adapter; | |
d46f384a CS |
246 | }; |
247 | ||
2e261af8 | 248 | static inline |
5771710b SS |
249 | void zfcp_dbf_hba_fsf_resp(const char *tag2, int level, |
250 | struct zfcp_fsf_req *req, struct zfcp_dbf *dbf) | |
2e261af8 | 251 | { |
5771710b SS |
252 | if (level <= dbf->hba->level) |
253 | _zfcp_dbf_hba_fsf_response(tag2, level, req, dbf); | |
2e261af8 CS |
254 | } |
255 | ||
256 | /** | |
5771710b | 257 | * zfcp_dbf_hba_fsf_response - trace event for request completion |
2e261af8 CS |
258 | * @fsf_req: request that has been completed |
259 | */ | |
5771710b | 260 | static inline void zfcp_dbf_hba_fsf_response(struct zfcp_fsf_req *req) |
2e261af8 CS |
261 | { |
262 | struct zfcp_dbf *dbf = req->adapter->dbf; | |
263 | struct fsf_qtcb *qtcb = req->qtcb; | |
264 | ||
265 | if ((qtcb->prefix.prot_status != FSF_PROT_GOOD) && | |
266 | (qtcb->prefix.prot_status != FSF_PROT_FSF_STATUS_PRESENTED)) { | |
5771710b | 267 | zfcp_dbf_hba_fsf_resp("perr", 1, req, dbf); |
2e261af8 CS |
268 | |
269 | } else if (qtcb->header.fsf_status != FSF_GOOD) { | |
5771710b | 270 | zfcp_dbf_hba_fsf_resp("ferr", 1, req, dbf); |
2e261af8 CS |
271 | |
272 | } else if ((req->fsf_command == FSF_QTCB_OPEN_PORT_WITH_DID) || | |
273 | (req->fsf_command == FSF_QTCB_OPEN_LUN)) { | |
5771710b | 274 | zfcp_dbf_hba_fsf_resp("open", 4, req, dbf); |
2e261af8 CS |
275 | |
276 | } else if (qtcb->header.log_length) { | |
5771710b | 277 | zfcp_dbf_hba_fsf_resp("qtcb", 5, req, dbf); |
2e261af8 CS |
278 | |
279 | } else { | |
5771710b | 280 | zfcp_dbf_hba_fsf_resp("norm", 6, req, dbf); |
2e261af8 CS |
281 | } |
282 | } | |
283 | ||
284 | /** | |
5771710b | 285 | * zfcp_dbf_hba_fsf_unsol - trace event for an unsolicited status buffer |
2e261af8 | 286 | * @tag: tag indicating which kind of unsolicited status has been received |
5771710b | 287 | * @dbf: reference to dbf structure |
2e261af8 CS |
288 | * @status_buffer: buffer containing payload of unsolicited status |
289 | */ | |
290 | static inline | |
5771710b SS |
291 | void zfcp_dbf_hba_fsf_unsol(const char *tag, struct zfcp_dbf *dbf, |
292 | struct fsf_status_read_buffer *buf) | |
2e261af8 | 293 | { |
2e261af8 CS |
294 | int level = 2; |
295 | ||
5771710b SS |
296 | if (level <= dbf->hba->level) |
297 | _zfcp_dbf_hba_fsf_unsol(tag, level, dbf, buf); | |
2e261af8 CS |
298 | } |
299 | ||
dcd20e23 | 300 | static inline |
5771710b SS |
301 | void zfcp_dbf_scsi(const char *tag, const char *tag2, int level, |
302 | struct zfcp_dbf *dbf, struct scsi_cmnd *scmd, | |
303 | struct zfcp_fsf_req *req, unsigned long old_id) | |
dcd20e23 | 304 | { |
5771710b SS |
305 | if (level <= dbf->scsi->level) |
306 | _zfcp_dbf_scsi(tag, tag2, level, dbf, scmd, req, old_id); | |
dcd20e23 CS |
307 | } |
308 | ||
309 | /** | |
5771710b | 310 | * zfcp_dbf_scsi_result - trace event for SCSI command completion |
ab72528a | 311 | * @dbf: adapter dbf trace |
dcd20e23 | 312 | * @scmd: SCSI command pointer |
ab72528a | 313 | * @req: FSF request used to issue SCSI command |
dcd20e23 CS |
314 | */ |
315 | static inline | |
ab72528a CS |
316 | void zfcp_dbf_scsi_result(struct zfcp_dbf *dbf, struct scsi_cmnd *scmd, |
317 | struct zfcp_fsf_req *req) | |
dcd20e23 | 318 | { |
ab72528a CS |
319 | if (scmd->result != 0) |
320 | zfcp_dbf_scsi("rslt", "erro", 3, dbf, scmd, req, 0); | |
321 | else if (scmd->retries > 0) | |
322 | zfcp_dbf_scsi("rslt", "retr", 4, dbf, scmd, req, 0); | |
323 | else | |
324 | zfcp_dbf_scsi("rslt", "norm", 6, dbf, scmd, req, 0); | |
325 | } | |
326 | ||
327 | /** | |
328 | * zfcp_dbf_scsi_fail_send - trace event for failure to send SCSI command | |
329 | * @dbf: adapter dbf trace | |
330 | * @scmd: SCSI command pointer | |
331 | */ | |
332 | static inline | |
333 | void zfcp_dbf_scsi_fail_send(struct zfcp_dbf *dbf, struct scsi_cmnd *scmd) | |
334 | { | |
335 | zfcp_dbf_scsi("rslt", "fail", 4, dbf, scmd, NULL, 0); | |
dcd20e23 CS |
336 | } |
337 | ||
338 | /** | |
5771710b | 339 | * zfcp_dbf_scsi_abort - trace event for SCSI command abort |
dcd20e23 CS |
340 | * @tag: tag indicating success or failure of abort operation |
341 | * @adapter: adapter thas has been used to issue SCSI command to be aborted | |
342 | * @scmd: SCSI command to be aborted | |
343 | * @new_req: request containing abort (might be NULL) | |
344 | * @old_id: identifier of request containg SCSI command to be aborted | |
345 | */ | |
346 | static inline | |
5771710b SS |
347 | void zfcp_dbf_scsi_abort(const char *tag, struct zfcp_dbf *dbf, |
348 | struct scsi_cmnd *scmd, struct zfcp_fsf_req *new_req, | |
349 | unsigned long old_id) | |
dcd20e23 | 350 | { |
5771710b | 351 | zfcp_dbf_scsi("abrt", tag, 1, dbf, scmd, new_req, old_id); |
dcd20e23 CS |
352 | } |
353 | ||
354 | /** | |
5771710b | 355 | * zfcp_dbf_scsi_devreset - trace event for Logical Unit or Target Reset |
dcd20e23 | 356 | * @tag: tag indicating success or failure of reset operation |
b62a8d9b | 357 | * @scmnd: SCSI command which caused this error recovery |
dcd20e23 | 358 | * @flag: indicates type of reset (Target Reset, Logical Unit Reset) |
dcd20e23 CS |
359 | */ |
360 | static inline | |
b62a8d9b | 361 | void zfcp_dbf_scsi_devreset(const char *tag, struct scsi_cmnd *scmnd, u8 flag) |
dcd20e23 | 362 | { |
b62a8d9b CS |
363 | struct zfcp_scsi_dev *zfcp_sdev = sdev_to_zfcp(scmnd->device); |
364 | ||
4318e08c | 365 | zfcp_dbf_scsi(flag == FCP_TMF_TGT_RESET ? "trst" : "lrst", tag, 1, |
b62a8d9b | 366 | zfcp_sdev->port->adapter->dbf, scmnd, NULL, 0); |
dcd20e23 CS |
367 | } |
368 | ||
2b604c9b | 369 | #endif /* ZFCP_DBF_H */ |