aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/s390/scsi/zfcp_dbf.c
diff options
context:
space:
mode:
authorMaxim Shchetynin <maxim@de.ibm.com>2005-09-13 15:50:38 -0400
committerJames Bottomley <jejb@mulgrave.(none)>2005-09-19 14:03:00 -0400
commit8a36e4532ea10471f0a8605207d071361d7be2c3 (patch)
treef34e5928de7d73b9aaf385f3fb0847a6c52c297b /drivers/s390/scsi/zfcp_dbf.c
parent810f1e3ea5cc0a812816af97020a27c73441f8e9 (diff)
[SCSI] zfcp: enhancement of zfcp debug features
Debug features (DBFs) els_dbf, cmd_dbf and abt_dbf were removed and san_dbf, hba_dbf and scsi_dbf were introduced. The erp_dbf did not change. The new traces improve debugging of problems with zfcp, scsi-stack, multipath and hardware in the SAN. san_dbf traces things like ELS and CT commands, hba_dbf saves HBA specific information of requests, and scsi_dbf saves FCP and SCSI specific information of requests. Common to all new DBFs is that they provide a so called structured view. This significantly improves readability of the traces. Signed-off-by: Andreas Herrmann <aherrman@de.ibm.com> Signed-off-by: James Bottomley <James.Bottomley@SteelEye.com>
Diffstat (limited to 'drivers/s390/scsi/zfcp_dbf.c')
-rw-r--r--drivers/s390/scsi/zfcp_dbf.c988
1 files changed, 988 insertions, 0 deletions
diff --git a/drivers/s390/scsi/zfcp_dbf.c b/drivers/s390/scsi/zfcp_dbf.c
new file mode 100644
index 000000000000..fff1537335c7
--- /dev/null
+++ b/drivers/s390/scsi/zfcp_dbf.c
@@ -0,0 +1,988 @@
1/*
2 *
3 * linux/drivers/s390/scsi/zfcp_dbf.c
4 *
5 * FCP adapter driver for IBM eServer zSeries
6 *
7 * Debugging facilities
8 *
9 * (C) Copyright IBM Corp. 2005
10 *
11 * This program is free software; you can redistribute it and/or modify
12 * it under the terms of the GNU General Public License as published by
13 * the Free Software Foundation; either version 2, or (at your option)
14 * any later version.
15 *
16 * This program is distributed in the hope that it will be useful,
17 * but WITHOUT ANY WARRANTY; without even the implied warranty of
18 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
19 * GNU General Public License for more details.
20 *
21 * You should have received a copy of the GNU General Public License
22 * along with this program; if not, write to the Free Software
23 * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
24 */
25
26#define ZFCP_DBF_REVISION "$Revision$"
27
28#include <asm/debug.h>
29#include <linux/ctype.h>
30#include "zfcp_ext.h"
31
32static u32 dbfsize = 4;
33
34module_param(dbfsize, uint, 0400);
35MODULE_PARM_DESC(dbfsize,
36 "number of pages for each debug feature area (default 4)");
37
38#define ZFCP_LOG_AREA ZFCP_LOG_AREA_OTHER
39
40static inline int
41zfcp_dbf_stck(char *out_buf, const char *label, unsigned long long stck)
42{
43 unsigned long long sec;
44 struct timespec xtime;
45 int len = 0;
46
47 stck -= 0x8126d60e46000000LL - (0x3c26700LL * 1000000 * 4096);
48 sec = stck >> 12;
49 do_div(sec, 1000000);
50 xtime.tv_sec = sec;
51 stck -= (sec * 1000000) << 12;
52 xtime.tv_nsec = ((stck * 1000) >> 12);
53 len += sprintf(out_buf + len, "%-24s%011lu:%06lu\n",
54 label, xtime.tv_sec, xtime.tv_nsec);
55
56 return len;
57}
58
59static int zfcp_dbf_tag(char *out_buf, const char *label, const char *tag)
60{
61 int len = 0, i;
62
63 len += sprintf(out_buf + len, "%-24s", label);
64 for (i = 0; i < ZFCP_DBF_TAG_SIZE; i++)
65 len += sprintf(out_buf + len, "%c", tag[i]);
66 len += sprintf(out_buf + len, "\n");
67
68 return len;
69}
70
71static int
72zfcp_dbf_view(char *out_buf, const char *label, const char *format, ...)
73{
74 va_list arg;
75 int len = 0;
76
77 len += sprintf(out_buf + len, "%-24s", label);
78 va_start(arg, format);
79 len += vsprintf(out_buf + len, format, arg);
80 va_end(arg);
81 len += sprintf(out_buf + len, "\n");
82
83 return len;
84}
85
86static int
87zfcp_dbf_view_dump(char *out_buf, const char *label,
88 char *buffer, int buflen, int offset, int total_size)
89{
90 int len = 0;
91
92 if (offset == 0)
93 len += sprintf(out_buf + len, "%-24s ", label);
94
95 while (buflen--) {
96 if (offset > 0) {
97 if ((offset % 32) == 0)
98 len += sprintf(out_buf + len, "\n%-24c ", ' ');
99 else if ((offset % 4) == 0)
100 len += sprintf(out_buf + len, " ");
101 }
102 len += sprintf(out_buf + len, "%02x", *buffer++);
103 if (++offset == total_size) {
104 len += sprintf(out_buf + len, "\n");
105 break;
106 }
107 }
108
109 if (total_size == 0)
110 len += sprintf(out_buf + len, "\n");
111
112 return len;
113}
114
115static inline int
116zfcp_dbf_view_header(debug_info_t * id, struct debug_view *view, int area,
117 debug_entry_t * entry, char *out_buf)
118{
119 struct zfcp_dbf_dump *dump = (struct zfcp_dbf_dump *)DEBUG_DATA(entry);
120 int len = 0;
121
122 if (strncmp(dump->tag, "dump", ZFCP_DBF_TAG_SIZE) != 0) {
123 len += zfcp_dbf_stck(out_buf + len, "timestamp",
124 entry->id.stck);
125 len += zfcp_dbf_view(out_buf + len, "cpu", "%02i",
126 entry->id.fields.cpuid);
127 } else {
128 len += zfcp_dbf_view_dump(out_buf + len, NULL,
129 dump->data,
130 dump->size,
131 dump->offset, dump->total_size);
132 if ((dump->offset + dump->size) == dump->total_size)
133 len += sprintf(out_buf + len, "\n");
134 }
135
136 return len;
137}
138
139inline void zfcp_hba_dbf_event_fsf_response(struct zfcp_fsf_req *fsf_req)
140{
141 struct zfcp_adapter *adapter = fsf_req->adapter;
142 struct fsf_qtcb *qtcb = fsf_req->qtcb;
143 union fsf_prot_status_qual *prot_status_qual =
144 &qtcb->prefix.prot_status_qual;
145 union fsf_status_qual *fsf_status_qual = &qtcb->header.fsf_status_qual;
146 struct scsi_cmnd *scsi_cmnd;
147 struct zfcp_port *port;
148 struct zfcp_unit *unit;
149 struct zfcp_send_els *send_els;
150 struct zfcp_hba_dbf_record *rec = &adapter->hba_dbf_buf;
151 struct zfcp_hba_dbf_record_response *response = &rec->type.response;
152 int level;
153 unsigned long flags;
154
155 spin_lock_irqsave(&adapter->hba_dbf_lock, flags);
156 memset(rec, 0, sizeof(struct zfcp_hba_dbf_record));
157 strncpy(rec->tag, "resp", ZFCP_DBF_TAG_SIZE);
158
159 if ((qtcb->prefix.prot_status != FSF_PROT_GOOD) &&
160 (qtcb->prefix.prot_status != FSF_PROT_FSF_STATUS_PRESENTED)) {
161 strncpy(rec->tag2, "perr", ZFCP_DBF_TAG_SIZE);
162 level = 1;
163 } else if (qtcb->header.fsf_status != FSF_GOOD) {
164 strncpy(rec->tag2, "ferr", ZFCP_DBF_TAG_SIZE);
165 level = 1;
166 } else if ((fsf_req->fsf_command == FSF_QTCB_OPEN_PORT_WITH_DID) ||
167 (fsf_req->fsf_command == FSF_QTCB_OPEN_LUN)) {
168 strncpy(rec->tag2, "open", ZFCP_DBF_TAG_SIZE);
169 level = 4;
170 } else if ((prot_status_qual->doubleword[0] != 0) ||
171 (prot_status_qual->doubleword[1] != 0) ||
172 (fsf_status_qual->doubleword[0] != 0) ||
173 (fsf_status_qual->doubleword[1] != 0)) {
174 strncpy(rec->tag2, "qual", ZFCP_DBF_TAG_SIZE);
175 level = 3;
176 } else {
177 strncpy(rec->tag2, "norm", ZFCP_DBF_TAG_SIZE);
178 level = 6;
179 }
180
181 response->fsf_command = fsf_req->fsf_command;
182 response->fsf_reqid = (unsigned long)fsf_req;
183 response->fsf_seqno = fsf_req->seq_no;
184 response->fsf_issued = fsf_req->issued;
185 response->fsf_prot_status = qtcb->prefix.prot_status;
186 response->fsf_status = qtcb->header.fsf_status;
187 memcpy(response->fsf_prot_status_qual,
188 prot_status_qual, FSF_PROT_STATUS_QUAL_SIZE);
189 memcpy(response->fsf_status_qual,
190 fsf_status_qual, FSF_STATUS_QUALIFIER_SIZE);
191 response->fsf_req_status = fsf_req->status;
192 response->sbal_first = fsf_req->sbal_first;
193 response->sbal_curr = fsf_req->sbal_curr;
194 response->sbal_last = fsf_req->sbal_last;
195 response->pool = fsf_req->pool != NULL;
196 response->erp_action = (unsigned long)fsf_req->erp_action;
197
198 switch (fsf_req->fsf_command) {
199 case FSF_QTCB_FCP_CMND:
200 if (fsf_req->status & ZFCP_STATUS_FSFREQ_TASK_MANAGEMENT)
201 break;
202 scsi_cmnd = (struct scsi_cmnd *)fsf_req->data;
203 if (scsi_cmnd != NULL) {
204 response->data.send_fcp.scsi_cmnd
205 = (unsigned long)scsi_cmnd;
206 response->data.send_fcp.scsi_serial
207 = scsi_cmnd->serial_number;
208 }
209 break;
210
211 case FSF_QTCB_OPEN_PORT_WITH_DID:
212 case FSF_QTCB_CLOSE_PORT:
213 case FSF_QTCB_CLOSE_PHYSICAL_PORT:
214 port = (struct zfcp_port *)fsf_req->data;
215 response->data.port.wwpn = port->wwpn;
216 response->data.port.d_id = port->d_id;
217 response->data.port.port_handle = qtcb->header.port_handle;
218 break;
219
220 case FSF_QTCB_OPEN_LUN:
221 case FSF_QTCB_CLOSE_LUN:
222 unit = (struct zfcp_unit *)fsf_req->data;
223 port = unit->port;
224 response->data.unit.wwpn = port->wwpn;
225 response->data.unit.fcp_lun = unit->fcp_lun;
226 response->data.unit.port_handle = qtcb->header.port_handle;
227 response->data.unit.lun_handle = qtcb->header.lun_handle;
228 break;
229
230 case FSF_QTCB_SEND_ELS:
231 send_els = (struct zfcp_send_els *)fsf_req->data;
232 response->data.send_els.d_id = qtcb->bottom.support.d_id;
233 response->data.send_els.ls_code = send_els->ls_code >> 24;
234 break;
235
236 case FSF_QTCB_ABORT_FCP_CMND:
237 case FSF_QTCB_SEND_GENERIC:
238 case FSF_QTCB_EXCHANGE_CONFIG_DATA:
239 case FSF_QTCB_EXCHANGE_PORT_DATA:
240 case FSF_QTCB_DOWNLOAD_CONTROL_FILE:
241 case FSF_QTCB_UPLOAD_CONTROL_FILE:
242 break;
243 }
244
245 debug_event(adapter->hba_dbf, level,
246 rec, sizeof(struct zfcp_hba_dbf_record));
247 spin_unlock_irqrestore(&adapter->hba_dbf_lock, flags);
248}
249
250inline void
251zfcp_hba_dbf_event_fsf_unsol(const char *tag, struct zfcp_adapter *adapter,
252 struct fsf_status_read_buffer *status_buffer)
253{
254 struct zfcp_hba_dbf_record *rec = &adapter->hba_dbf_buf;
255 unsigned long flags;
256
257 spin_lock_irqsave(&adapter->hba_dbf_lock, flags);
258 memset(rec, 0, sizeof(struct zfcp_hba_dbf_record));
259 strncpy(rec->tag, "stat", ZFCP_DBF_TAG_SIZE);
260 strncpy(rec->tag2, tag, ZFCP_DBF_TAG_SIZE);
261
262 rec->type.status.failed = adapter->status_read_failed;
263 if (status_buffer != NULL) {
264 rec->type.status.status_type = status_buffer->status_type;
265 rec->type.status.status_subtype = status_buffer->status_subtype;
266 memcpy(&rec->type.status.queue_designator,
267 &status_buffer->queue_designator,
268 sizeof(struct fsf_queue_designator));
269
270 switch (status_buffer->status_type) {
271 case FSF_STATUS_READ_SENSE_DATA_AVAIL:
272 rec->type.status.payload_size =
273 ZFCP_DBF_UNSOL_PAYLOAD_SENSE_DATA_AVAIL;
274 break;
275
276 case FSF_STATUS_READ_BIT_ERROR_THRESHOLD:
277 rec->type.status.payload_size =
278 ZFCP_DBF_UNSOL_PAYLOAD_BIT_ERROR_THRESHOLD;
279 break;
280
281 case FSF_STATUS_READ_LINK_DOWN:
282 rec->type.status.payload_size = sizeof(u64);
283 break;
284
285 }
286 memcpy(&rec->type.status.payload,
287 &status_buffer->payload, rec->type.status.payload_size);
288 }
289
290 debug_event(adapter->hba_dbf, 2,
291 rec, sizeof(struct zfcp_hba_dbf_record));
292 spin_unlock_irqrestore(&adapter->hba_dbf_lock, flags);
293}
294
295inline void
296zfcp_hba_dbf_event_qdio(struct zfcp_adapter *adapter, unsigned int status,
297 unsigned int qdio_error, unsigned int siga_error,
298 int sbal_index, int sbal_count)
299{
300 struct zfcp_hba_dbf_record *rec = &adapter->hba_dbf_buf;
301 unsigned long flags;
302
303 spin_lock_irqsave(&adapter->hba_dbf_lock, flags);
304 memset(rec, 0, sizeof(struct zfcp_hba_dbf_record));
305 strncpy(rec->tag, "qdio", ZFCP_DBF_TAG_SIZE);
306 rec->type.qdio.status = status;
307 rec->type.qdio.qdio_error = qdio_error;
308 rec->type.qdio.siga_error = siga_error;
309 rec->type.qdio.sbal_index = sbal_index;
310 rec->type.qdio.sbal_count = sbal_count;
311 debug_event(adapter->hba_dbf, 0,
312 rec, sizeof(struct zfcp_hba_dbf_record));
313 spin_unlock_irqrestore(&adapter->hba_dbf_lock, flags);
314}
315
316static inline int
317zfcp_hba_dbf_view_response(char *out_buf,
318 struct zfcp_hba_dbf_record_response *rec)
319{
320 int len = 0;
321
322 len += zfcp_dbf_view(out_buf + len, "fsf_command", "0x%08x",
323 rec->fsf_command);
324 len += zfcp_dbf_view(out_buf + len, "fsf_reqid", "0x%0Lx",
325 rec->fsf_reqid);
326 len += zfcp_dbf_view(out_buf + len, "fsf_seqno", "0x%08x",
327 rec->fsf_seqno);
328 len += zfcp_dbf_stck(out_buf + len, "fsf_issued", rec->fsf_issued);
329 len += zfcp_dbf_view(out_buf + len, "fsf_prot_status", "0x%08x",
330 rec->fsf_prot_status);
331 len += zfcp_dbf_view(out_buf + len, "fsf_status", "0x%08x",
332 rec->fsf_status);
333 len += zfcp_dbf_view_dump(out_buf + len, "fsf_prot_status_qual",
334 rec->fsf_prot_status_qual,
335 FSF_PROT_STATUS_QUAL_SIZE,
336 0, FSF_PROT_STATUS_QUAL_SIZE);
337 len += zfcp_dbf_view_dump(out_buf + len, "fsf_status_qual",
338 rec->fsf_status_qual,
339 FSF_STATUS_QUALIFIER_SIZE,
340 0, FSF_STATUS_QUALIFIER_SIZE);
341 len += zfcp_dbf_view(out_buf + len, "fsf_req_status", "0x%08x",
342 rec->fsf_req_status);
343 len += zfcp_dbf_view(out_buf + len, "sbal_first", "0x%02x",
344 rec->sbal_first);
345 len += zfcp_dbf_view(out_buf + len, "sbal_curr", "0x%02x",
346 rec->sbal_curr);
347 len += zfcp_dbf_view(out_buf + len, "sbal_last", "0x%02x",
348 rec->sbal_last);
349 len += zfcp_dbf_view(out_buf + len, "pool", "0x%02x", rec->pool);
350
351 switch (rec->fsf_command) {
352 case FSF_QTCB_FCP_CMND:
353 if (rec->fsf_req_status & ZFCP_STATUS_FSFREQ_TASK_MANAGEMENT)
354 break;
355 len += zfcp_dbf_view(out_buf + len, "scsi_cmnd", "0x%0Lx",
356 rec->data.send_fcp.scsi_cmnd);
357 len += zfcp_dbf_view(out_buf + len, "scsi_serial", "0x%016Lx",
358 rec->data.send_fcp.scsi_serial);
359 break;
360
361 case FSF_QTCB_OPEN_PORT_WITH_DID:
362 case FSF_QTCB_CLOSE_PORT:
363 case FSF_QTCB_CLOSE_PHYSICAL_PORT:
364 len += zfcp_dbf_view(out_buf + len, "wwpn", "0x%016Lx",
365 rec->data.port.wwpn);
366 len += zfcp_dbf_view(out_buf + len, "d_id", "0x%06x",
367 rec->data.port.d_id);
368 len += zfcp_dbf_view(out_buf + len, "port_handle", "0x%08x",
369 rec->data.port.port_handle);
370 break;
371
372 case FSF_QTCB_OPEN_LUN:
373 case FSF_QTCB_CLOSE_LUN:
374 len += zfcp_dbf_view(out_buf + len, "wwpn", "0x%016Lx",
375 rec->data.unit.wwpn);
376 len += zfcp_dbf_view(out_buf + len, "fcp_lun", "0x%016Lx",
377 rec->data.unit.fcp_lun);
378 len += zfcp_dbf_view(out_buf + len, "port_handle", "0x%08x",
379 rec->data.unit.port_handle);
380 len += zfcp_dbf_view(out_buf + len, "lun_handle", "0x%08x",
381 rec->data.unit.lun_handle);
382 break;
383
384 case FSF_QTCB_SEND_ELS:
385 len += zfcp_dbf_view(out_buf + len, "d_id", "0x%06x",
386 rec->data.send_els.d_id);
387 len += zfcp_dbf_view(out_buf + len, "ls_code", "0x%02x",
388 rec->data.send_els.ls_code);
389 break;
390
391 case FSF_QTCB_ABORT_FCP_CMND:
392 case FSF_QTCB_SEND_GENERIC:
393 case FSF_QTCB_EXCHANGE_CONFIG_DATA:
394 case FSF_QTCB_EXCHANGE_PORT_DATA:
395 case FSF_QTCB_DOWNLOAD_CONTROL_FILE:
396 case FSF_QTCB_UPLOAD_CONTROL_FILE:
397 break;
398 }
399
400 return len;
401}
402
403static inline int
404zfcp_hba_dbf_view_status(char *out_buf, struct zfcp_hba_dbf_record_status *rec)
405{
406 int len = 0;
407
408 len += zfcp_dbf_view(out_buf + len, "failed", "0x%02x", rec->failed);
409 len += zfcp_dbf_view(out_buf + len, "status_type", "0x%08x",
410 rec->status_type);
411 len += zfcp_dbf_view(out_buf + len, "status_subtype", "0x%08x",
412 rec->status_subtype);
413 len += zfcp_dbf_view_dump(out_buf + len, "queue_designator",
414 (char *)&rec->queue_designator,
415 sizeof(struct fsf_queue_designator),
416 0, sizeof(struct fsf_queue_designator));
417 len += zfcp_dbf_view_dump(out_buf + len, "payload",
418 (char *)&rec->payload,
419 rec->payload_size, 0, rec->payload_size);
420
421 return len;
422}
423
424static inline int
425zfcp_hba_dbf_view_qdio(char *out_buf, struct zfcp_hba_dbf_record_qdio *rec)
426{
427 int len = 0;
428
429 len += zfcp_dbf_view(out_buf + len, "status", "0x%08x", rec->status);
430 len += zfcp_dbf_view(out_buf + len, "qdio_error", "0x%08x",
431 rec->qdio_error);
432 len += zfcp_dbf_view(out_buf + len, "siga_error", "0x%08x",
433 rec->siga_error);
434 len += zfcp_dbf_view(out_buf + len, "sbal_index", "0x%02x",
435 rec->sbal_index);
436 len += zfcp_dbf_view(out_buf + len, "sbal_count", "0x%02x",
437 rec->sbal_count);
438
439 return len;
440}
441
442static int
443zfcp_hba_dbf_view_format(debug_info_t * id, struct debug_view *view,
444 char *out_buf, const char *in_buf)
445{
446 struct zfcp_hba_dbf_record *rec = (struct zfcp_hba_dbf_record *)in_buf;
447 int len = 0;
448
449 if (strncmp(rec->tag, "dump", ZFCP_DBF_TAG_SIZE) == 0)
450 return 0;
451
452 len += zfcp_dbf_tag(out_buf + len, "tag", rec->tag);
453 if (isalpha(rec->tag2[0]))
454 len += zfcp_dbf_tag(out_buf + len, "tag2", rec->tag2);
455 if (strncmp(rec->tag, "resp", ZFCP_DBF_TAG_SIZE) == 0)
456 len += zfcp_hba_dbf_view_response(out_buf + len,
457 &rec->type.response);
458 else if (strncmp(rec->tag, "stat", ZFCP_DBF_TAG_SIZE) == 0)
459 len += zfcp_hba_dbf_view_status(out_buf + len,
460 &rec->type.status);
461 else if (strncmp(rec->tag, "qdio", ZFCP_DBF_TAG_SIZE) == 0)
462 len += zfcp_hba_dbf_view_qdio(out_buf + len, &rec->type.qdio);
463
464 len += sprintf(out_buf + len, "\n");
465
466 return len;
467}
468
469struct debug_view zfcp_hba_dbf_view = {
470 "structured",
471 NULL,
472 &zfcp_dbf_view_header,
473 &zfcp_hba_dbf_view_format,
474 NULL,
475 NULL
476};
477
478inline void
479_zfcp_san_dbf_event_common_ct(const char *tag, struct zfcp_fsf_req *fsf_req,
480 fc_id_t s_id, fc_id_t d_id,
481 void *buffer, int buflen)
482{
483 struct zfcp_send_ct *send_ct = (struct zfcp_send_ct *)fsf_req->data;
484 struct zfcp_port *port = send_ct->port;
485 struct zfcp_adapter *adapter = port->adapter;
486 struct ct_hdr *header = (struct ct_hdr *)buffer;
487 struct zfcp_san_dbf_record *rec = &adapter->san_dbf_buf;
488 struct zfcp_san_dbf_record_ct *ct = &rec->type.ct;
489 unsigned long flags;
490
491 spin_lock_irqsave(&adapter->san_dbf_lock, flags);
492 memset(rec, 0, sizeof(struct zfcp_san_dbf_record));
493 strncpy(rec->tag, tag, ZFCP_DBF_TAG_SIZE);
494 rec->fsf_reqid = (unsigned long)fsf_req;
495 rec->fsf_seqno = fsf_req->seq_no;
496 rec->s_id = s_id;
497 rec->d_id = d_id;
498 if (strncmp(tag, "octc", ZFCP_DBF_TAG_SIZE) == 0) {
499 ct->type.request.cmd_req_code = header->cmd_rsp_code;
500 ct->type.request.revision = header->revision;
501 ct->type.request.gs_type = header->gs_type;
502 ct->type.request.gs_subtype = header->gs_subtype;
503 ct->type.request.options = header->options;
504 ct->type.request.max_res_size = header->max_res_size;
505 } else if (strncmp(tag, "rctc", ZFCP_DBF_TAG_SIZE) == 0) {
506 ct->type.response.cmd_rsp_code = header->cmd_rsp_code;
507 ct->type.response.revision = header->revision;
508 ct->type.response.reason_code = header->reason_code;
509 ct->type.response.reason_code_expl = header->reason_code_expl;
510 ct->type.response.vendor_unique = header->vendor_unique;
511 }
512 ct->payload_size =
513 min(buflen - (int)sizeof(struct ct_hdr), ZFCP_DBF_CT_PAYLOAD);
514 memcpy(ct->payload, buffer + sizeof(struct ct_hdr), ct->payload_size);
515 debug_event(adapter->san_dbf, 3,
516 rec, sizeof(struct zfcp_san_dbf_record));
517 spin_unlock_irqrestore(&adapter->san_dbf_lock, flags);
518}
519
520inline void zfcp_san_dbf_event_ct_request(struct zfcp_fsf_req *fsf_req)
521{
522 struct zfcp_send_ct *ct = (struct zfcp_send_ct *)fsf_req->data;
523 struct zfcp_port *port = ct->port;
524 struct zfcp_adapter *adapter = port->adapter;
525
526 _zfcp_san_dbf_event_common_ct("octc",
527 fsf_req, adapter->s_id, port->d_id,
528 zfcp_sg_to_address(ct->req),
529 ct->req->length);
530}
531
532inline void zfcp_san_dbf_event_ct_response(struct zfcp_fsf_req *fsf_req)
533{
534 struct zfcp_send_ct *ct = (struct zfcp_send_ct *)fsf_req->data;
535 struct zfcp_port *port = ct->port;
536 struct zfcp_adapter *adapter = port->adapter;
537
538 _zfcp_san_dbf_event_common_ct("rctc",
539 fsf_req, port->d_id, adapter->s_id,
540 zfcp_sg_to_address(ct->resp),
541 ct->resp->length);
542}
543
544static inline void
545_zfcp_san_dbf_event_common_els(const char *tag, int level,
546 struct zfcp_fsf_req *fsf_req,
547 fc_id_t s_id, fc_id_t d_id, u8 ls_code,
548 void *buffer, int buflen)
549{
550 struct zfcp_adapter *adapter = fsf_req->adapter;
551 struct zfcp_san_dbf_record *rec = &adapter->san_dbf_buf;
552 struct zfcp_dbf_dump *dump = (struct zfcp_dbf_dump *)rec;
553 unsigned long flags;
554 int offset = 0;
555
556 spin_lock_irqsave(&adapter->san_dbf_lock, flags);
557 do {
558 memset(rec, 0, sizeof(struct zfcp_san_dbf_record));
559 if (offset == 0) {
560 strncpy(rec->tag, tag, ZFCP_DBF_TAG_SIZE);
561 rec->fsf_reqid = (unsigned long)fsf_req;
562 rec->fsf_seqno = fsf_req->seq_no;
563 rec->s_id = s_id;
564 rec->d_id = d_id;
565 rec->type.els.ls_code = ls_code;
566 buflen = min(buflen, ZFCP_DBF_ELS_MAX_PAYLOAD);
567 rec->type.els.payload_size = buflen;
568 memcpy(rec->type.els.payload,
569 buffer, min(buflen, ZFCP_DBF_ELS_PAYLOAD));
570 offset += min(buflen, ZFCP_DBF_ELS_PAYLOAD);
571 } else {
572 strncpy(dump->tag, "dump", ZFCP_DBF_TAG_SIZE);
573 dump->total_size = buflen;
574 dump->offset = offset;
575 dump->size = min(buflen - offset,
576 (int)sizeof(struct zfcp_san_dbf_record)
577 - (int)sizeof(struct zfcp_dbf_dump));
578 memcpy(dump->data, buffer + offset, dump->size);
579 offset += dump->size;
580 }
581 debug_event(adapter->san_dbf, level,
582 rec, sizeof(struct zfcp_san_dbf_record));
583 } while (offset < buflen);
584 spin_unlock_irqrestore(&adapter->san_dbf_lock, flags);
585}
586
587inline void zfcp_san_dbf_event_els_request(struct zfcp_fsf_req *fsf_req)
588{
589 struct zfcp_send_els *els = (struct zfcp_send_els *)fsf_req->data;
590
591 _zfcp_san_dbf_event_common_els("oels", 2,
592 fsf_req, els->adapter->s_id, els->d_id,
593 *(u8 *) zfcp_sg_to_address(els->req),
594 zfcp_sg_to_address(els->req),
595 els->req->length);
596}
597
598inline void zfcp_san_dbf_event_els_response(struct zfcp_fsf_req *fsf_req)
599{
600 struct zfcp_send_els *els = (struct zfcp_send_els *)fsf_req->data;
601
602 _zfcp_san_dbf_event_common_els("rels", 2,
603 fsf_req, els->d_id, els->adapter->s_id,
604 *(u8 *) zfcp_sg_to_address(els->req),
605 zfcp_sg_to_address(els->resp),
606 els->resp->length);
607}
608
609inline void zfcp_san_dbf_event_incoming_els(struct zfcp_fsf_req *fsf_req)
610{
611 struct zfcp_adapter *adapter = fsf_req->adapter;
612 struct fsf_status_read_buffer *status_buffer =
613 (struct fsf_status_read_buffer *)fsf_req->data;
614 int length = (int)status_buffer->length -
615 (int)((void *)&status_buffer->payload - (void *)status_buffer);
616
617 _zfcp_san_dbf_event_common_els("iels", 1,
618 fsf_req, status_buffer->d_id,
619 adapter->s_id,
620 *(u8 *) status_buffer->payload,
621 (void *)status_buffer->payload, length);
622}
623
624static int
625zfcp_san_dbf_view_format(debug_info_t * id, struct debug_view *view,
626 char *out_buf, const char *in_buf)
627{
628 struct zfcp_san_dbf_record *rec = (struct zfcp_san_dbf_record *)in_buf;
629 char *buffer = NULL;
630 int buflen = 0, total = 0;
631 int len = 0;
632
633 if (strncmp(rec->tag, "dump", ZFCP_DBF_TAG_SIZE) == 0)
634 return 0;
635
636 len += zfcp_dbf_tag(out_buf + len, "tag", rec->tag);
637 len += zfcp_dbf_view(out_buf + len, "fsf_reqid", "0x%0Lx",
638 rec->fsf_reqid);
639 len += zfcp_dbf_view(out_buf + len, "fsf_seqno", "0x%08x",
640 rec->fsf_seqno);
641 len += zfcp_dbf_view(out_buf + len, "s_id", "0x%06x", rec->s_id);
642 len += zfcp_dbf_view(out_buf + len, "d_id", "0x%06x", rec->d_id);
643
644 if (strncmp(rec->tag, "octc", ZFCP_DBF_TAG_SIZE) == 0) {
645 len += zfcp_dbf_view(out_buf + len, "cmd_req_code", "0x%04x",
646 rec->type.ct.type.request.cmd_req_code);
647 len += zfcp_dbf_view(out_buf + len, "revision", "0x%02x",
648 rec->type.ct.type.request.revision);
649 len += zfcp_dbf_view(out_buf + len, "gs_type", "0x%02x",
650 rec->type.ct.type.request.gs_type);
651 len += zfcp_dbf_view(out_buf + len, "gs_subtype", "0x%02x",
652 rec->type.ct.type.request.gs_subtype);
653 len += zfcp_dbf_view(out_buf + len, "options", "0x%02x",
654 rec->type.ct.type.request.options);
655 len += zfcp_dbf_view(out_buf + len, "max_res_size", "0x%04x",
656 rec->type.ct.type.request.max_res_size);
657 total = rec->type.ct.payload_size;
658 buffer = rec->type.ct.payload;
659 buflen = min(total, ZFCP_DBF_CT_PAYLOAD);
660 } else if (strncmp(rec->tag, "rctc", ZFCP_DBF_TAG_SIZE) == 0) {
661 len += zfcp_dbf_view(out_buf + len, "cmd_rsp_code", "0x%04x",
662 rec->type.ct.type.response.cmd_rsp_code);
663 len += zfcp_dbf_view(out_buf + len, "revision", "0x%02x",
664 rec->type.ct.type.response.revision);
665 len += zfcp_dbf_view(out_buf + len, "reason_code", "0x%02x",
666 rec->type.ct.type.response.reason_code);
667 len +=
668 zfcp_dbf_view(out_buf + len, "reason_code_expl", "0x%02x",
669 rec->type.ct.type.response.reason_code_expl);
670 len +=
671 zfcp_dbf_view(out_buf + len, "vendor_unique", "0x%02x",
672 rec->type.ct.type.response.vendor_unique);
673 total = rec->type.ct.payload_size;
674 buffer = rec->type.ct.payload;
675 buflen = min(total, ZFCP_DBF_CT_PAYLOAD);
676 } else if (strncmp(rec->tag, "oels", ZFCP_DBF_TAG_SIZE) == 0 ||
677 strncmp(rec->tag, "rels", ZFCP_DBF_TAG_SIZE) == 0 ||
678 strncmp(rec->tag, "iels", ZFCP_DBF_TAG_SIZE) == 0) {
679 len += zfcp_dbf_view(out_buf + len, "ls_code", "0x%02x",
680 rec->type.els.ls_code);
681 total = rec->type.els.payload_size;
682 buffer = rec->type.els.payload;
683 buflen = min(total, ZFCP_DBF_ELS_PAYLOAD);
684 }
685
686 len += zfcp_dbf_view_dump(out_buf + len, "payload",
687 buffer, buflen, 0, total);
688
689 if (buflen == total)
690 len += sprintf(out_buf + len, "\n");
691
692 return len;
693}
694
695struct debug_view zfcp_san_dbf_view = {
696 "structured",
697 NULL,
698 &zfcp_dbf_view_header,
699 &zfcp_san_dbf_view_format,
700 NULL,
701 NULL
702};
703
704static inline void
705_zfcp_scsi_dbf_event_common(const char *tag, const char *tag2, int level,
706 struct zfcp_adapter *adapter,
707 struct scsi_cmnd *scsi_cmnd,
708 struct zfcp_fsf_req *new_fsf_req)
709{
710 struct zfcp_fsf_req *fsf_req =
711 (struct zfcp_fsf_req *)scsi_cmnd->host_scribble;
712 struct zfcp_scsi_dbf_record *rec = &adapter->scsi_dbf_buf;
713 struct zfcp_dbf_dump *dump = (struct zfcp_dbf_dump *)rec;
714 unsigned long flags;
715 struct fcp_rsp_iu *fcp_rsp;
716 char *fcp_rsp_info = NULL, *fcp_sns_info = NULL;
717 int offset = 0, buflen = 0;
718
719 spin_lock_irqsave(&adapter->scsi_dbf_lock, flags);
720 do {
721 memset(rec, 0, sizeof(struct zfcp_scsi_dbf_record));
722 if (offset == 0) {
723 strncpy(rec->tag, tag, ZFCP_DBF_TAG_SIZE);
724 strncpy(rec->tag2, tag2, ZFCP_DBF_TAG_SIZE);
725 if (scsi_cmnd->device) {
726 rec->scsi_id = scsi_cmnd->device->id;
727 rec->scsi_lun = scsi_cmnd->device->lun;
728 }
729 rec->scsi_result = scsi_cmnd->result;
730 rec->scsi_cmnd = (unsigned long)scsi_cmnd;
731 rec->scsi_serial = scsi_cmnd->serial_number;
732 memcpy(rec->scsi_opcode,
733 &scsi_cmnd->cmnd,
734 min((int)scsi_cmnd->cmd_len,
735 ZFCP_DBF_SCSI_OPCODE));
736 rec->scsi_retries = scsi_cmnd->retries;
737 rec->scsi_allowed = scsi_cmnd->allowed;
738 if (fsf_req != NULL) {
739 fcp_rsp = (struct fcp_rsp_iu *)
740 &(fsf_req->qtcb->bottom.io.fcp_rsp);
741 fcp_rsp_info =
742 zfcp_get_fcp_rsp_info_ptr(fcp_rsp);
743 fcp_sns_info =
744 zfcp_get_fcp_sns_info_ptr(fcp_rsp);
745
746 rec->type.fcp.rsp_validity =
747 fcp_rsp->validity.value;
748 rec->type.fcp.rsp_scsi_status =
749 fcp_rsp->scsi_status;
750 rec->type.fcp.rsp_resid = fcp_rsp->fcp_resid;
751 if (fcp_rsp->validity.bits.fcp_rsp_len_valid)
752 rec->type.fcp.rsp_code =
753 *(fcp_rsp_info + 3);
754 if (fcp_rsp->validity.bits.fcp_sns_len_valid) {
755 buflen = min((int)fcp_rsp->fcp_sns_len,
756 ZFCP_DBF_SCSI_MAX_FCP_SNS_INFO);
757 rec->type.fcp.sns_info_len = buflen;
758 memcpy(rec->type.fcp.sns_info,
759 fcp_sns_info,
760 min(buflen,
761 ZFCP_DBF_SCSI_FCP_SNS_INFO));
762 offset += min(buflen,
763 ZFCP_DBF_SCSI_FCP_SNS_INFO);
764 }
765
766 rec->fsf_reqid = (unsigned long)fsf_req;
767 rec->fsf_seqno = fsf_req->seq_no;
768 rec->fsf_issued = fsf_req->issued;
769 }
770 if (new_fsf_req != NULL) {
771 rec->type.new_fsf_req.fsf_reqid =
772 (unsigned long)
773 new_fsf_req;
774 rec->type.new_fsf_req.fsf_seqno =
775 new_fsf_req->seq_no;
776 rec->type.new_fsf_req.fsf_issued =
777 new_fsf_req->issued;
778 }
779 } else {
780 strncpy(dump->tag, "dump", ZFCP_DBF_TAG_SIZE);
781 dump->total_size = buflen;
782 dump->offset = offset;
783 dump->size = min(buflen - offset,
784 (int)sizeof(struct
785 zfcp_scsi_dbf_record) -
786 (int)sizeof(struct zfcp_dbf_dump));
787 memcpy(dump->data, fcp_sns_info + offset, dump->size);
788 offset += dump->size;
789 }
790 debug_event(adapter->scsi_dbf, level,
791 rec, sizeof(struct zfcp_scsi_dbf_record));
792 } while (offset < buflen);
793 spin_unlock_irqrestore(&adapter->scsi_dbf_lock, flags);
794}
795
796inline void
797zfcp_scsi_dbf_event_result(const char *tag, int level,
798 struct zfcp_adapter *adapter,
799 struct scsi_cmnd *scsi_cmnd)
800{
801 _zfcp_scsi_dbf_event_common("rslt",
802 tag, level, adapter, scsi_cmnd, NULL);
803}
804
805inline void
806zfcp_scsi_dbf_event_abort(const char *tag, struct zfcp_adapter *adapter,
807 struct scsi_cmnd *scsi_cmnd,
808 struct zfcp_fsf_req *new_fsf_req)
809{
810 _zfcp_scsi_dbf_event_common("abrt",
811 tag, 1, adapter, scsi_cmnd, new_fsf_req);
812}
813
814inline void
815zfcp_scsi_dbf_event_devreset(const char *tag, u8 flag, struct zfcp_unit *unit,
816 struct scsi_cmnd *scsi_cmnd)
817{
818 struct zfcp_adapter *adapter = unit->port->adapter;
819
820 _zfcp_scsi_dbf_event_common(flag == FCP_TARGET_RESET ? "trst" : "lrst",
821 tag, 1, adapter, scsi_cmnd, NULL);
822}
823
824static int
825zfcp_scsi_dbf_view_format(debug_info_t * id, struct debug_view *view,
826 char *out_buf, const char *in_buf)
827{
828 struct zfcp_scsi_dbf_record *rec =
829 (struct zfcp_scsi_dbf_record *)in_buf;
830 int len = 0;
831
832 if (strncmp(rec->tag, "dump", ZFCP_DBF_TAG_SIZE) == 0)
833 return 0;
834
835 len += zfcp_dbf_tag(out_buf + len, "tag", rec->tag);
836 len += zfcp_dbf_tag(out_buf + len, "tag2", rec->tag2);
837 len += zfcp_dbf_view(out_buf + len, "scsi_id", "0x%08x", rec->scsi_id);
838 len += zfcp_dbf_view(out_buf + len, "scsi_lun", "0x%08x",
839 rec->scsi_lun);
840 len += zfcp_dbf_view(out_buf + len, "scsi_result", "0x%08x",
841 rec->scsi_result);
842 len += zfcp_dbf_view(out_buf + len, "scsi_cmnd", "0x%0Lx",
843 rec->scsi_cmnd);
844 len += zfcp_dbf_view(out_buf + len, "scsi_serial", "0x%016Lx",
845 rec->scsi_serial);
846 len += zfcp_dbf_view_dump(out_buf + len, "scsi_opcode",
847 rec->scsi_opcode,
848 ZFCP_DBF_SCSI_OPCODE,
849 0, ZFCP_DBF_SCSI_OPCODE);
850 len += zfcp_dbf_view(out_buf + len, "scsi_retries", "0x%02x",
851 rec->scsi_retries);
852 len += zfcp_dbf_view(out_buf + len, "scsi_allowed", "0x%02x",
853 rec->scsi_allowed);
854 len += zfcp_dbf_view(out_buf + len, "fsf_reqid", "0x%0Lx",
855 rec->fsf_reqid);
856 len += zfcp_dbf_view(out_buf + len, "fsf_seqno", "0x%08x",
857 rec->fsf_seqno);
858 len += zfcp_dbf_stck(out_buf + len, "fsf_issued", rec->fsf_issued);
859 if (strncmp(rec->tag, "rslt", ZFCP_DBF_TAG_SIZE) == 0) {
860 len +=
861 zfcp_dbf_view(out_buf + len, "fcp_rsp_validity", "0x%02x",
862 rec->type.fcp.rsp_validity);
863 len +=
864 zfcp_dbf_view(out_buf + len, "fcp_rsp_scsi_status",
865 "0x%02x", rec->type.fcp.rsp_scsi_status);
866 len +=
867 zfcp_dbf_view(out_buf + len, "fcp_rsp_resid", "0x%08x",
868 rec->type.fcp.rsp_resid);
869 len +=
870 zfcp_dbf_view(out_buf + len, "fcp_rsp_code", "0x%08x",
871 rec->type.fcp.rsp_code);
872 len +=
873 zfcp_dbf_view(out_buf + len, "fcp_sns_info_len", "0x%08x",
874 rec->type.fcp.sns_info_len);
875 len +=
876 zfcp_dbf_view_dump(out_buf + len, "fcp_sns_info",
877 rec->type.fcp.sns_info,
878 min((int)rec->type.fcp.sns_info_len,
879 ZFCP_DBF_SCSI_FCP_SNS_INFO), 0,
880 rec->type.fcp.sns_info_len);
881 } else if (strncmp(rec->tag, "abrt", ZFCP_DBF_TAG_SIZE) == 0) {
882 len += zfcp_dbf_view(out_buf + len, "fsf_reqid_abort", "0x%0Lx",
883 rec->type.new_fsf_req.fsf_reqid);
884 len += zfcp_dbf_view(out_buf + len, "fsf_seqno_abort", "0x%08x",
885 rec->type.new_fsf_req.fsf_seqno);
886 len += zfcp_dbf_stck(out_buf + len, "fsf_issued",
887 rec->type.new_fsf_req.fsf_issued);
888 } else if ((strncmp(rec->tag, "trst", ZFCP_DBF_TAG_SIZE) == 0) ||
889 (strncmp(rec->tag, "lrst", ZFCP_DBF_TAG_SIZE) == 0)) {
890 len += zfcp_dbf_view(out_buf + len, "fsf_reqid_reset", "0x%0Lx",
891 rec->type.new_fsf_req.fsf_reqid);
892 len += zfcp_dbf_view(out_buf + len, "fsf_seqno_reset", "0x%08x",
893 rec->type.new_fsf_req.fsf_seqno);
894 len += zfcp_dbf_stck(out_buf + len, "fsf_issued",
895 rec->type.new_fsf_req.fsf_issued);
896 }
897
898 len += sprintf(out_buf + len, "\n");
899
900 return len;
901}
902
903struct debug_view zfcp_scsi_dbf_view = {
904 "structured",
905 NULL,
906 &zfcp_dbf_view_header,
907 &zfcp_scsi_dbf_view_format,
908 NULL,
909 NULL
910};
911
912/**
913 * zfcp_adapter_debug_register - registers debug feature for an adapter
914 * @adapter: pointer to adapter for which debug features should be registered
915 * return: -ENOMEM on error, 0 otherwise
916 */
917int zfcp_adapter_debug_register(struct zfcp_adapter *adapter)
918{
919 char dbf_name[DEBUG_MAX_NAME_LEN];
920
921 /* debug feature area which records recovery activity */
922 spin_lock_init(&adapter->erp_dbf_lock);
923 sprintf(dbf_name, "zfcp_%s_erp", zfcp_get_busid_by_adapter(adapter));
924 adapter->erp_dbf = debug_register(dbf_name, dbfsize, 2,
925 sizeof(struct zfcp_erp_dbf_record));
926 if (!adapter->erp_dbf)
927 goto failed;
928 debug_register_view(adapter->erp_dbf, &debug_hex_ascii_view);
929 debug_set_level(adapter->erp_dbf, 3);
930
931 /* debug feature area which records HBA (FSF and QDIO) conditions */
932 spin_lock_init(&adapter->hba_dbf_lock);
933 sprintf(dbf_name, "zfcp_%s_hba", zfcp_get_busid_by_adapter(adapter));
934 adapter->hba_dbf = debug_register(dbf_name, dbfsize, 1,
935 sizeof(struct zfcp_hba_dbf_record));
936 if (!adapter->hba_dbf)
937 goto failed;
938 debug_register_view(adapter->hba_dbf, &debug_hex_ascii_view);
939 debug_register_view(adapter->hba_dbf, &zfcp_hba_dbf_view);
940 debug_set_level(adapter->hba_dbf, 3);
941
942 /* debug feature area which records SAN command failures and recovery */
943 spin_lock_init(&adapter->san_dbf_lock);
944 sprintf(dbf_name, "zfcp_%s_san", zfcp_get_busid_by_adapter(adapter));
945 adapter->san_dbf = debug_register(dbf_name, dbfsize, 1,
946 sizeof(struct zfcp_san_dbf_record));
947 if (!adapter->san_dbf)
948 goto failed;
949 debug_register_view(adapter->san_dbf, &debug_hex_ascii_view);
950 debug_register_view(adapter->san_dbf, &zfcp_san_dbf_view);
951 debug_set_level(adapter->san_dbf, 6);
952
953 /* debug feature area which records SCSI command failures and recovery */
954 spin_lock_init(&adapter->scsi_dbf_lock);
955 sprintf(dbf_name, "zfcp_%s_scsi", zfcp_get_busid_by_adapter(adapter));
956 adapter->scsi_dbf = debug_register(dbf_name, dbfsize, 1,
957 sizeof(struct zfcp_scsi_dbf_record));
958 if (!adapter->scsi_dbf)
959 goto failed;
960 debug_register_view(adapter->scsi_dbf, &debug_hex_ascii_view);
961 debug_register_view(adapter->scsi_dbf, &zfcp_scsi_dbf_view);
962 debug_set_level(adapter->scsi_dbf, 3);
963
964 return 0;
965
966 failed:
967 zfcp_adapter_debug_unregister(adapter);
968
969 return -ENOMEM;
970}
971
972/**
973 * zfcp_adapter_debug_unregister - unregisters debug feature for an adapter
974 * @adapter: pointer to adapter for which debug features should be unregistered
975 */
976void zfcp_adapter_debug_unregister(struct zfcp_adapter *adapter)
977{
978 debug_unregister(adapter->scsi_dbf);
979 debug_unregister(adapter->san_dbf);
980 debug_unregister(adapter->hba_dbf);
981 debug_unregister(adapter->erp_dbf);
982 adapter->scsi_dbf = NULL;
983 adapter->san_dbf = NULL;
984 adapter->hba_dbf = NULL;
985 adapter->erp_dbf = NULL;
986}
987
988#undef ZFCP_LOG_AREA