[SCSI] zfcp: transport class adaptations
[linux-2.6/libata-dev.git] / drivers / s390 / scsi / zfcp_dbf.c
blob95599719f8ab9e02c8294b53e3885c7df7087c6a
1 /*
3 * linux/drivers/s390/scsi/zfcp_dbf.c
5 * FCP adapter driver for IBM eServer zSeries
7 * Debugging facilities
9 * (C) Copyright IBM Corp. 2005
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.
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.
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.
26 #define ZFCP_DBF_REVISION "$Revision$"
28 #include <asm/debug.h>
29 #include <linux/ctype.h>
30 #include "zfcp_ext.h"
32 static u32 dbfsize = 4;
34 module_param(dbfsize, uint, 0400);
35 MODULE_PARM_DESC(dbfsize,
36 "number of pages for each debug feature area (default 4)");
38 #define ZFCP_LOG_AREA ZFCP_LOG_AREA_OTHER
40 static inline int
41 zfcp_dbf_stck(char *out_buf, const char *label, unsigned long long stck)
43 unsigned long long sec;
44 struct timespec xtime;
45 int len = 0;
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);
56 return len;
59 static int zfcp_dbf_tag(char *out_buf, const char *label, const char *tag)
61 int len = 0, i;
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");
68 return len;
71 static int
72 zfcp_dbf_view(char *out_buf, const char *label, const char *format, ...)
74 va_list arg;
75 int len = 0;
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");
83 return len;
86 static int
87 zfcp_dbf_view_dump(char *out_buf, const char *label,
88 char *buffer, int buflen, int offset, int total_size)
90 int len = 0;
92 if (offset == 0)
93 len += sprintf(out_buf + len, "%-24s ", label);
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, " ");
102 len += sprintf(out_buf + len, "%02x", *buffer++);
103 if (++offset == total_size) {
104 len += sprintf(out_buf + len, "\n");
105 break;
109 if (total_size == 0)
110 len += sprintf(out_buf + len, "\n");
112 return len;
115 static inline int
116 zfcp_dbf_view_header(debug_info_t * id, struct debug_view *view, int area,
117 debug_entry_t * entry, char *out_buf)
119 struct zfcp_dbf_dump *dump = (struct zfcp_dbf_dump *)DEBUG_DATA(entry);
120 int len = 0;
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");
136 return len;
139 inline void zfcp_hba_dbf_event_fsf_response(struct zfcp_fsf_req *fsf_req)
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;
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);
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;
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;
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;
209 break;
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;
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;
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;
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;
245 debug_event(adapter->hba_dbf, level,
246 rec, sizeof(struct zfcp_hba_dbf_record));
247 spin_unlock_irqrestore(&adapter->hba_dbf_lock, flags);
250 inline void
251 zfcp_hba_dbf_event_fsf_unsol(const char *tag, struct zfcp_adapter *adapter,
252 struct fsf_status_read_buffer *status_buffer)
254 struct zfcp_hba_dbf_record *rec = &adapter->hba_dbf_buf;
255 unsigned long flags;
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);
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));
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;
276 case FSF_STATUS_READ_BIT_ERROR_THRESHOLD:
277 rec->type.status.payload_size =
278 ZFCP_DBF_UNSOL_PAYLOAD_BIT_ERROR_THRESHOLD;
279 break;
281 case FSF_STATUS_READ_LINK_DOWN:
282 switch (status_buffer->status_subtype) {
283 case FSF_STATUS_READ_SUB_NO_PHYSICAL_LINK:
284 case FSF_STATUS_READ_SUB_FDISC_FAILED:
285 rec->type.status.payload_size =
286 sizeof(struct fsf_link_down_info);
288 break;
290 case FSF_STATUS_READ_FEATURE_UPDATE_ALERT:
291 rec->type.status.payload_size =
292 ZFCP_DBF_UNSOL_PAYLOAD_FEATURE_UPDATE_ALERT;
293 break;
295 memcpy(&rec->type.status.payload,
296 &status_buffer->payload, rec->type.status.payload_size);
299 debug_event(adapter->hba_dbf, 2,
300 rec, sizeof(struct zfcp_hba_dbf_record));
301 spin_unlock_irqrestore(&adapter->hba_dbf_lock, flags);
304 inline void
305 zfcp_hba_dbf_event_qdio(struct zfcp_adapter *adapter, unsigned int status,
306 unsigned int qdio_error, unsigned int siga_error,
307 int sbal_index, int sbal_count)
309 struct zfcp_hba_dbf_record *rec = &adapter->hba_dbf_buf;
310 unsigned long flags;
312 spin_lock_irqsave(&adapter->hba_dbf_lock, flags);
313 memset(rec, 0, sizeof(struct zfcp_hba_dbf_record));
314 strncpy(rec->tag, "qdio", ZFCP_DBF_TAG_SIZE);
315 rec->type.qdio.status = status;
316 rec->type.qdio.qdio_error = qdio_error;
317 rec->type.qdio.siga_error = siga_error;
318 rec->type.qdio.sbal_index = sbal_index;
319 rec->type.qdio.sbal_count = sbal_count;
320 debug_event(adapter->hba_dbf, 0,
321 rec, sizeof(struct zfcp_hba_dbf_record));
322 spin_unlock_irqrestore(&adapter->hba_dbf_lock, flags);
325 static inline int
326 zfcp_hba_dbf_view_response(char *out_buf,
327 struct zfcp_hba_dbf_record_response *rec)
329 int len = 0;
331 len += zfcp_dbf_view(out_buf + len, "fsf_command", "0x%08x",
332 rec->fsf_command);
333 len += zfcp_dbf_view(out_buf + len, "fsf_reqid", "0x%0Lx",
334 rec->fsf_reqid);
335 len += zfcp_dbf_view(out_buf + len, "fsf_seqno", "0x%08x",
336 rec->fsf_seqno);
337 len += zfcp_dbf_stck(out_buf + len, "fsf_issued", rec->fsf_issued);
338 len += zfcp_dbf_view(out_buf + len, "fsf_prot_status", "0x%08x",
339 rec->fsf_prot_status);
340 len += zfcp_dbf_view(out_buf + len, "fsf_status", "0x%08x",
341 rec->fsf_status);
342 len += zfcp_dbf_view_dump(out_buf + len, "fsf_prot_status_qual",
343 rec->fsf_prot_status_qual,
344 FSF_PROT_STATUS_QUAL_SIZE,
345 0, FSF_PROT_STATUS_QUAL_SIZE);
346 len += zfcp_dbf_view_dump(out_buf + len, "fsf_status_qual",
347 rec->fsf_status_qual,
348 FSF_STATUS_QUALIFIER_SIZE,
349 0, FSF_STATUS_QUALIFIER_SIZE);
350 len += zfcp_dbf_view(out_buf + len, "fsf_req_status", "0x%08x",
351 rec->fsf_req_status);
352 len += zfcp_dbf_view(out_buf + len, "sbal_first", "0x%02x",
353 rec->sbal_first);
354 len += zfcp_dbf_view(out_buf + len, "sbal_curr", "0x%02x",
355 rec->sbal_curr);
356 len += zfcp_dbf_view(out_buf + len, "sbal_last", "0x%02x",
357 rec->sbal_last);
358 len += zfcp_dbf_view(out_buf + len, "pool", "0x%02x", rec->pool);
360 switch (rec->fsf_command) {
361 case FSF_QTCB_FCP_CMND:
362 if (rec->fsf_req_status & ZFCP_STATUS_FSFREQ_TASK_MANAGEMENT)
363 break;
364 len += zfcp_dbf_view(out_buf + len, "scsi_cmnd", "0x%0Lx",
365 rec->data.send_fcp.scsi_cmnd);
366 len += zfcp_dbf_view(out_buf + len, "scsi_serial", "0x%016Lx",
367 rec->data.send_fcp.scsi_serial);
368 break;
370 case FSF_QTCB_OPEN_PORT_WITH_DID:
371 case FSF_QTCB_CLOSE_PORT:
372 case FSF_QTCB_CLOSE_PHYSICAL_PORT:
373 len += zfcp_dbf_view(out_buf + len, "wwpn", "0x%016Lx",
374 rec->data.port.wwpn);
375 len += zfcp_dbf_view(out_buf + len, "d_id", "0x%06x",
376 rec->data.port.d_id);
377 len += zfcp_dbf_view(out_buf + len, "port_handle", "0x%08x",
378 rec->data.port.port_handle);
379 break;
381 case FSF_QTCB_OPEN_LUN:
382 case FSF_QTCB_CLOSE_LUN:
383 len += zfcp_dbf_view(out_buf + len, "wwpn", "0x%016Lx",
384 rec->data.unit.wwpn);
385 len += zfcp_dbf_view(out_buf + len, "fcp_lun", "0x%016Lx",
386 rec->data.unit.fcp_lun);
387 len += zfcp_dbf_view(out_buf + len, "port_handle", "0x%08x",
388 rec->data.unit.port_handle);
389 len += zfcp_dbf_view(out_buf + len, "lun_handle", "0x%08x",
390 rec->data.unit.lun_handle);
391 break;
393 case FSF_QTCB_SEND_ELS:
394 len += zfcp_dbf_view(out_buf + len, "d_id", "0x%06x",
395 rec->data.send_els.d_id);
396 len += zfcp_dbf_view(out_buf + len, "ls_code", "0x%02x",
397 rec->data.send_els.ls_code);
398 break;
400 case FSF_QTCB_ABORT_FCP_CMND:
401 case FSF_QTCB_SEND_GENERIC:
402 case FSF_QTCB_EXCHANGE_CONFIG_DATA:
403 case FSF_QTCB_EXCHANGE_PORT_DATA:
404 case FSF_QTCB_DOWNLOAD_CONTROL_FILE:
405 case FSF_QTCB_UPLOAD_CONTROL_FILE:
406 break;
409 return len;
412 static inline int
413 zfcp_hba_dbf_view_status(char *out_buf, struct zfcp_hba_dbf_record_status *rec)
415 int len = 0;
417 len += zfcp_dbf_view(out_buf + len, "failed", "0x%02x", rec->failed);
418 len += zfcp_dbf_view(out_buf + len, "status_type", "0x%08x",
419 rec->status_type);
420 len += zfcp_dbf_view(out_buf + len, "status_subtype", "0x%08x",
421 rec->status_subtype);
422 len += zfcp_dbf_view_dump(out_buf + len, "queue_designator",
423 (char *)&rec->queue_designator,
424 sizeof(struct fsf_queue_designator),
425 0, sizeof(struct fsf_queue_designator));
426 len += zfcp_dbf_view_dump(out_buf + len, "payload",
427 (char *)&rec->payload,
428 rec->payload_size, 0, rec->payload_size);
430 return len;
433 static inline int
434 zfcp_hba_dbf_view_qdio(char *out_buf, struct zfcp_hba_dbf_record_qdio *rec)
436 int len = 0;
438 len += zfcp_dbf_view(out_buf + len, "status", "0x%08x", rec->status);
439 len += zfcp_dbf_view(out_buf + len, "qdio_error", "0x%08x",
440 rec->qdio_error);
441 len += zfcp_dbf_view(out_buf + len, "siga_error", "0x%08x",
442 rec->siga_error);
443 len += zfcp_dbf_view(out_buf + len, "sbal_index", "0x%02x",
444 rec->sbal_index);
445 len += zfcp_dbf_view(out_buf + len, "sbal_count", "0x%02x",
446 rec->sbal_count);
448 return len;
451 static int
452 zfcp_hba_dbf_view_format(debug_info_t * id, struct debug_view *view,
453 char *out_buf, const char *in_buf)
455 struct zfcp_hba_dbf_record *rec = (struct zfcp_hba_dbf_record *)in_buf;
456 int len = 0;
458 if (strncmp(rec->tag, "dump", ZFCP_DBF_TAG_SIZE) == 0)
459 return 0;
461 len += zfcp_dbf_tag(out_buf + len, "tag", rec->tag);
462 if (isalpha(rec->tag2[0]))
463 len += zfcp_dbf_tag(out_buf + len, "tag2", rec->tag2);
464 if (strncmp(rec->tag, "resp", ZFCP_DBF_TAG_SIZE) == 0)
465 len += zfcp_hba_dbf_view_response(out_buf + len,
466 &rec->type.response);
467 else if (strncmp(rec->tag, "stat", ZFCP_DBF_TAG_SIZE) == 0)
468 len += zfcp_hba_dbf_view_status(out_buf + len,
469 &rec->type.status);
470 else if (strncmp(rec->tag, "qdio", ZFCP_DBF_TAG_SIZE) == 0)
471 len += zfcp_hba_dbf_view_qdio(out_buf + len, &rec->type.qdio);
473 len += sprintf(out_buf + len, "\n");
475 return len;
478 struct debug_view zfcp_hba_dbf_view = {
479 "structured",
480 NULL,
481 &zfcp_dbf_view_header,
482 &zfcp_hba_dbf_view_format,
483 NULL,
484 NULL
487 inline void
488 _zfcp_san_dbf_event_common_ct(const char *tag, struct zfcp_fsf_req *fsf_req,
489 u32 s_id, u32 d_id, void *buffer, int buflen)
491 struct zfcp_send_ct *send_ct = (struct zfcp_send_ct *)fsf_req->data;
492 struct zfcp_port *port = send_ct->port;
493 struct zfcp_adapter *adapter = port->adapter;
494 struct ct_hdr *header = (struct ct_hdr *)buffer;
495 struct zfcp_san_dbf_record *rec = &adapter->san_dbf_buf;
496 struct zfcp_san_dbf_record_ct *ct = &rec->type.ct;
497 unsigned long flags;
499 spin_lock_irqsave(&adapter->san_dbf_lock, flags);
500 memset(rec, 0, sizeof(struct zfcp_san_dbf_record));
501 strncpy(rec->tag, tag, ZFCP_DBF_TAG_SIZE);
502 rec->fsf_reqid = (unsigned long)fsf_req;
503 rec->fsf_seqno = fsf_req->seq_no;
504 rec->s_id = s_id;
505 rec->d_id = d_id;
506 if (strncmp(tag, "octc", ZFCP_DBF_TAG_SIZE) == 0) {
507 ct->type.request.cmd_req_code = header->cmd_rsp_code;
508 ct->type.request.revision = header->revision;
509 ct->type.request.gs_type = header->gs_type;
510 ct->type.request.gs_subtype = header->gs_subtype;
511 ct->type.request.options = header->options;
512 ct->type.request.max_res_size = header->max_res_size;
513 } else if (strncmp(tag, "rctc", ZFCP_DBF_TAG_SIZE) == 0) {
514 ct->type.response.cmd_rsp_code = header->cmd_rsp_code;
515 ct->type.response.revision = header->revision;
516 ct->type.response.reason_code = header->reason_code;
517 ct->type.response.reason_code_expl = header->reason_code_expl;
518 ct->type.response.vendor_unique = header->vendor_unique;
520 ct->payload_size =
521 min(buflen - (int)sizeof(struct ct_hdr), ZFCP_DBF_CT_PAYLOAD);
522 memcpy(ct->payload, buffer + sizeof(struct ct_hdr), ct->payload_size);
523 debug_event(adapter->san_dbf, 3,
524 rec, sizeof(struct zfcp_san_dbf_record));
525 spin_unlock_irqrestore(&adapter->san_dbf_lock, flags);
528 inline void zfcp_san_dbf_event_ct_request(struct zfcp_fsf_req *fsf_req)
530 struct zfcp_send_ct *ct = (struct zfcp_send_ct *)fsf_req->data;
531 struct zfcp_port *port = ct->port;
532 struct zfcp_adapter *adapter = port->adapter;
534 _zfcp_san_dbf_event_common_ct("octc", fsf_req,
535 fc_host_port_id(adapter->scsi_host),
536 port->d_id, zfcp_sg_to_address(ct->req),
537 ct->req->length);
540 inline void zfcp_san_dbf_event_ct_response(struct zfcp_fsf_req *fsf_req)
542 struct zfcp_send_ct *ct = (struct zfcp_send_ct *)fsf_req->data;
543 struct zfcp_port *port = ct->port;
544 struct zfcp_adapter *adapter = port->adapter;
546 _zfcp_san_dbf_event_common_ct("rctc", fsf_req, port->d_id,
547 fc_host_port_id(adapter->scsi_host),
548 zfcp_sg_to_address(ct->resp),
549 ct->resp->length);
552 static inline void
553 _zfcp_san_dbf_event_common_els(const char *tag, int level,
554 struct zfcp_fsf_req *fsf_req, u32 s_id,
555 u32 d_id, u8 ls_code, void *buffer, int buflen)
557 struct zfcp_adapter *adapter = fsf_req->adapter;
558 struct zfcp_san_dbf_record *rec = &adapter->san_dbf_buf;
559 struct zfcp_dbf_dump *dump = (struct zfcp_dbf_dump *)rec;
560 unsigned long flags;
561 int offset = 0;
563 spin_lock_irqsave(&adapter->san_dbf_lock, flags);
564 do {
565 memset(rec, 0, sizeof(struct zfcp_san_dbf_record));
566 if (offset == 0) {
567 strncpy(rec->tag, tag, ZFCP_DBF_TAG_SIZE);
568 rec->fsf_reqid = (unsigned long)fsf_req;
569 rec->fsf_seqno = fsf_req->seq_no;
570 rec->s_id = s_id;
571 rec->d_id = d_id;
572 rec->type.els.ls_code = ls_code;
573 buflen = min(buflen, ZFCP_DBF_ELS_MAX_PAYLOAD);
574 rec->type.els.payload_size = buflen;
575 memcpy(rec->type.els.payload,
576 buffer, min(buflen, ZFCP_DBF_ELS_PAYLOAD));
577 offset += min(buflen, ZFCP_DBF_ELS_PAYLOAD);
578 } else {
579 strncpy(dump->tag, "dump", ZFCP_DBF_TAG_SIZE);
580 dump->total_size = buflen;
581 dump->offset = offset;
582 dump->size = min(buflen - offset,
583 (int)sizeof(struct zfcp_san_dbf_record)
584 - (int)sizeof(struct zfcp_dbf_dump));
585 memcpy(dump->data, buffer + offset, dump->size);
586 offset += dump->size;
588 debug_event(adapter->san_dbf, level,
589 rec, sizeof(struct zfcp_san_dbf_record));
590 } while (offset < buflen);
591 spin_unlock_irqrestore(&adapter->san_dbf_lock, flags);
594 inline void zfcp_san_dbf_event_els_request(struct zfcp_fsf_req *fsf_req)
596 struct zfcp_send_els *els = (struct zfcp_send_els *)fsf_req->data;
598 _zfcp_san_dbf_event_common_els("oels", 2, fsf_req,
599 fc_host_port_id(els->adapter->scsi_host),
600 els->d_id,
601 *(u8 *) zfcp_sg_to_address(els->req),
602 zfcp_sg_to_address(els->req),
603 els->req->length);
606 inline void zfcp_san_dbf_event_els_response(struct zfcp_fsf_req *fsf_req)
608 struct zfcp_send_els *els = (struct zfcp_send_els *)fsf_req->data;
610 _zfcp_san_dbf_event_common_els("rels", 2, fsf_req, els->d_id,
611 fc_host_port_id(els->adapter->scsi_host),
612 *(u8 *) zfcp_sg_to_address(els->req),
613 zfcp_sg_to_address(els->resp),
614 els->resp->length);
617 inline void zfcp_san_dbf_event_incoming_els(struct zfcp_fsf_req *fsf_req)
619 struct zfcp_adapter *adapter = fsf_req->adapter;
620 struct fsf_status_read_buffer *status_buffer =
621 (struct fsf_status_read_buffer *)fsf_req->data;
622 int length = (int)status_buffer->length -
623 (int)((void *)&status_buffer->payload - (void *)status_buffer);
625 _zfcp_san_dbf_event_common_els("iels", 1, fsf_req, status_buffer->d_id,
626 fc_host_port_id(adapter->scsi_host),
627 *(u8 *) status_buffer->payload,
628 (void *)status_buffer->payload, length);
631 static int
632 zfcp_san_dbf_view_format(debug_info_t * id, struct debug_view *view,
633 char *out_buf, const char *in_buf)
635 struct zfcp_san_dbf_record *rec = (struct zfcp_san_dbf_record *)in_buf;
636 char *buffer = NULL;
637 int buflen = 0, total = 0;
638 int len = 0;
640 if (strncmp(rec->tag, "dump", ZFCP_DBF_TAG_SIZE) == 0)
641 return 0;
643 len += zfcp_dbf_tag(out_buf + len, "tag", rec->tag);
644 len += zfcp_dbf_view(out_buf + len, "fsf_reqid", "0x%0Lx",
645 rec->fsf_reqid);
646 len += zfcp_dbf_view(out_buf + len, "fsf_seqno", "0x%08x",
647 rec->fsf_seqno);
648 len += zfcp_dbf_view(out_buf + len, "s_id", "0x%06x", rec->s_id);
649 len += zfcp_dbf_view(out_buf + len, "d_id", "0x%06x", rec->d_id);
651 if (strncmp(rec->tag, "octc", ZFCP_DBF_TAG_SIZE) == 0) {
652 len += zfcp_dbf_view(out_buf + len, "cmd_req_code", "0x%04x",
653 rec->type.ct.type.request.cmd_req_code);
654 len += zfcp_dbf_view(out_buf + len, "revision", "0x%02x",
655 rec->type.ct.type.request.revision);
656 len += zfcp_dbf_view(out_buf + len, "gs_type", "0x%02x",
657 rec->type.ct.type.request.gs_type);
658 len += zfcp_dbf_view(out_buf + len, "gs_subtype", "0x%02x",
659 rec->type.ct.type.request.gs_subtype);
660 len += zfcp_dbf_view(out_buf + len, "options", "0x%02x",
661 rec->type.ct.type.request.options);
662 len += zfcp_dbf_view(out_buf + len, "max_res_size", "0x%04x",
663 rec->type.ct.type.request.max_res_size);
664 total = rec->type.ct.payload_size;
665 buffer = rec->type.ct.payload;
666 buflen = min(total, ZFCP_DBF_CT_PAYLOAD);
667 } else if (strncmp(rec->tag, "rctc", ZFCP_DBF_TAG_SIZE) == 0) {
668 len += zfcp_dbf_view(out_buf + len, "cmd_rsp_code", "0x%04x",
669 rec->type.ct.type.response.cmd_rsp_code);
670 len += zfcp_dbf_view(out_buf + len, "revision", "0x%02x",
671 rec->type.ct.type.response.revision);
672 len += zfcp_dbf_view(out_buf + len, "reason_code", "0x%02x",
673 rec->type.ct.type.response.reason_code);
674 len +=
675 zfcp_dbf_view(out_buf + len, "reason_code_expl", "0x%02x",
676 rec->type.ct.type.response.reason_code_expl);
677 len +=
678 zfcp_dbf_view(out_buf + len, "vendor_unique", "0x%02x",
679 rec->type.ct.type.response.vendor_unique);
680 total = rec->type.ct.payload_size;
681 buffer = rec->type.ct.payload;
682 buflen = min(total, ZFCP_DBF_CT_PAYLOAD);
683 } else if (strncmp(rec->tag, "oels", ZFCP_DBF_TAG_SIZE) == 0 ||
684 strncmp(rec->tag, "rels", ZFCP_DBF_TAG_SIZE) == 0 ||
685 strncmp(rec->tag, "iels", ZFCP_DBF_TAG_SIZE) == 0) {
686 len += zfcp_dbf_view(out_buf + len, "ls_code", "0x%02x",
687 rec->type.els.ls_code);
688 total = rec->type.els.payload_size;
689 buffer = rec->type.els.payload;
690 buflen = min(total, ZFCP_DBF_ELS_PAYLOAD);
693 len += zfcp_dbf_view_dump(out_buf + len, "payload",
694 buffer, buflen, 0, total);
696 if (buflen == total)
697 len += sprintf(out_buf + len, "\n");
699 return len;
702 struct debug_view zfcp_san_dbf_view = {
703 "structured",
704 NULL,
705 &zfcp_dbf_view_header,
706 &zfcp_san_dbf_view_format,
707 NULL,
708 NULL
711 static inline void
712 _zfcp_scsi_dbf_event_common(const char *tag, const char *tag2, int level,
713 struct zfcp_adapter *adapter,
714 struct scsi_cmnd *scsi_cmnd,
715 struct zfcp_fsf_req *new_fsf_req)
717 struct zfcp_fsf_req *fsf_req =
718 (struct zfcp_fsf_req *)scsi_cmnd->host_scribble;
719 struct zfcp_scsi_dbf_record *rec = &adapter->scsi_dbf_buf;
720 struct zfcp_dbf_dump *dump = (struct zfcp_dbf_dump *)rec;
721 unsigned long flags;
722 struct fcp_rsp_iu *fcp_rsp;
723 char *fcp_rsp_info = NULL, *fcp_sns_info = NULL;
724 int offset = 0, buflen = 0;
726 spin_lock_irqsave(&adapter->scsi_dbf_lock, flags);
727 do {
728 memset(rec, 0, sizeof(struct zfcp_scsi_dbf_record));
729 if (offset == 0) {
730 strncpy(rec->tag, tag, ZFCP_DBF_TAG_SIZE);
731 strncpy(rec->tag2, tag2, ZFCP_DBF_TAG_SIZE);
732 if (scsi_cmnd->device) {
733 rec->scsi_id = scsi_cmnd->device->id;
734 rec->scsi_lun = scsi_cmnd->device->lun;
736 rec->scsi_result = scsi_cmnd->result;
737 rec->scsi_cmnd = (unsigned long)scsi_cmnd;
738 rec->scsi_serial = scsi_cmnd->serial_number;
739 memcpy(rec->scsi_opcode,
740 &scsi_cmnd->cmnd,
741 min((int)scsi_cmnd->cmd_len,
742 ZFCP_DBF_SCSI_OPCODE));
743 rec->scsi_retries = scsi_cmnd->retries;
744 rec->scsi_allowed = scsi_cmnd->allowed;
745 if (fsf_req != NULL) {
746 fcp_rsp = (struct fcp_rsp_iu *)
747 &(fsf_req->qtcb->bottom.io.fcp_rsp);
748 fcp_rsp_info =
749 zfcp_get_fcp_rsp_info_ptr(fcp_rsp);
750 fcp_sns_info =
751 zfcp_get_fcp_sns_info_ptr(fcp_rsp);
753 rec->type.fcp.rsp_validity =
754 fcp_rsp->validity.value;
755 rec->type.fcp.rsp_scsi_status =
756 fcp_rsp->scsi_status;
757 rec->type.fcp.rsp_resid = fcp_rsp->fcp_resid;
758 if (fcp_rsp->validity.bits.fcp_rsp_len_valid)
759 rec->type.fcp.rsp_code =
760 *(fcp_rsp_info + 3);
761 if (fcp_rsp->validity.bits.fcp_sns_len_valid) {
762 buflen = min((int)fcp_rsp->fcp_sns_len,
763 ZFCP_DBF_SCSI_MAX_FCP_SNS_INFO);
764 rec->type.fcp.sns_info_len = buflen;
765 memcpy(rec->type.fcp.sns_info,
766 fcp_sns_info,
767 min(buflen,
768 ZFCP_DBF_SCSI_FCP_SNS_INFO));
769 offset += min(buflen,
770 ZFCP_DBF_SCSI_FCP_SNS_INFO);
773 rec->fsf_reqid = (unsigned long)fsf_req;
774 rec->fsf_seqno = fsf_req->seq_no;
775 rec->fsf_issued = fsf_req->issued;
777 if (new_fsf_req != NULL) {
778 rec->type.new_fsf_req.fsf_reqid =
779 (unsigned long)
780 new_fsf_req;
781 rec->type.new_fsf_req.fsf_seqno =
782 new_fsf_req->seq_no;
783 rec->type.new_fsf_req.fsf_issued =
784 new_fsf_req->issued;
786 } else {
787 strncpy(dump->tag, "dump", ZFCP_DBF_TAG_SIZE);
788 dump->total_size = buflen;
789 dump->offset = offset;
790 dump->size = min(buflen - offset,
791 (int)sizeof(struct
792 zfcp_scsi_dbf_record) -
793 (int)sizeof(struct zfcp_dbf_dump));
794 memcpy(dump->data, fcp_sns_info + offset, dump->size);
795 offset += dump->size;
797 debug_event(adapter->scsi_dbf, level,
798 rec, sizeof(struct zfcp_scsi_dbf_record));
799 } while (offset < buflen);
800 spin_unlock_irqrestore(&adapter->scsi_dbf_lock, flags);
803 inline void
804 zfcp_scsi_dbf_event_result(const char *tag, int level,
805 struct zfcp_adapter *adapter,
806 struct scsi_cmnd *scsi_cmnd)
808 _zfcp_scsi_dbf_event_common("rslt",
809 tag, level, adapter, scsi_cmnd, NULL);
812 inline void
813 zfcp_scsi_dbf_event_abort(const char *tag, struct zfcp_adapter *adapter,
814 struct scsi_cmnd *scsi_cmnd,
815 struct zfcp_fsf_req *new_fsf_req)
817 _zfcp_scsi_dbf_event_common("abrt",
818 tag, 1, adapter, scsi_cmnd, new_fsf_req);
821 inline void
822 zfcp_scsi_dbf_event_devreset(const char *tag, u8 flag, struct zfcp_unit *unit,
823 struct scsi_cmnd *scsi_cmnd)
825 struct zfcp_adapter *adapter = unit->port->adapter;
827 _zfcp_scsi_dbf_event_common(flag == FCP_TARGET_RESET ? "trst" : "lrst",
828 tag, 1, adapter, scsi_cmnd, NULL);
831 static int
832 zfcp_scsi_dbf_view_format(debug_info_t * id, struct debug_view *view,
833 char *out_buf, const char *in_buf)
835 struct zfcp_scsi_dbf_record *rec =
836 (struct zfcp_scsi_dbf_record *)in_buf;
837 int len = 0;
839 if (strncmp(rec->tag, "dump", ZFCP_DBF_TAG_SIZE) == 0)
840 return 0;
842 len += zfcp_dbf_tag(out_buf + len, "tag", rec->tag);
843 len += zfcp_dbf_tag(out_buf + len, "tag2", rec->tag2);
844 len += zfcp_dbf_view(out_buf + len, "scsi_id", "0x%08x", rec->scsi_id);
845 len += zfcp_dbf_view(out_buf + len, "scsi_lun", "0x%08x",
846 rec->scsi_lun);
847 len += zfcp_dbf_view(out_buf + len, "scsi_result", "0x%08x",
848 rec->scsi_result);
849 len += zfcp_dbf_view(out_buf + len, "scsi_cmnd", "0x%0Lx",
850 rec->scsi_cmnd);
851 len += zfcp_dbf_view(out_buf + len, "scsi_serial", "0x%016Lx",
852 rec->scsi_serial);
853 len += zfcp_dbf_view_dump(out_buf + len, "scsi_opcode",
854 rec->scsi_opcode,
855 ZFCP_DBF_SCSI_OPCODE,
856 0, ZFCP_DBF_SCSI_OPCODE);
857 len += zfcp_dbf_view(out_buf + len, "scsi_retries", "0x%02x",
858 rec->scsi_retries);
859 len += zfcp_dbf_view(out_buf + len, "scsi_allowed", "0x%02x",
860 rec->scsi_allowed);
861 len += zfcp_dbf_view(out_buf + len, "fsf_reqid", "0x%0Lx",
862 rec->fsf_reqid);
863 len += zfcp_dbf_view(out_buf + len, "fsf_seqno", "0x%08x",
864 rec->fsf_seqno);
865 len += zfcp_dbf_stck(out_buf + len, "fsf_issued", rec->fsf_issued);
866 if (strncmp(rec->tag, "rslt", ZFCP_DBF_TAG_SIZE) == 0) {
867 len +=
868 zfcp_dbf_view(out_buf + len, "fcp_rsp_validity", "0x%02x",
869 rec->type.fcp.rsp_validity);
870 len +=
871 zfcp_dbf_view(out_buf + len, "fcp_rsp_scsi_status",
872 "0x%02x", rec->type.fcp.rsp_scsi_status);
873 len +=
874 zfcp_dbf_view(out_buf + len, "fcp_rsp_resid", "0x%08x",
875 rec->type.fcp.rsp_resid);
876 len +=
877 zfcp_dbf_view(out_buf + len, "fcp_rsp_code", "0x%08x",
878 rec->type.fcp.rsp_code);
879 len +=
880 zfcp_dbf_view(out_buf + len, "fcp_sns_info_len", "0x%08x",
881 rec->type.fcp.sns_info_len);
882 len +=
883 zfcp_dbf_view_dump(out_buf + len, "fcp_sns_info",
884 rec->type.fcp.sns_info,
885 min((int)rec->type.fcp.sns_info_len,
886 ZFCP_DBF_SCSI_FCP_SNS_INFO), 0,
887 rec->type.fcp.sns_info_len);
888 } else if (strncmp(rec->tag, "abrt", ZFCP_DBF_TAG_SIZE) == 0) {
889 len += zfcp_dbf_view(out_buf + len, "fsf_reqid_abort", "0x%0Lx",
890 rec->type.new_fsf_req.fsf_reqid);
891 len += zfcp_dbf_view(out_buf + len, "fsf_seqno_abort", "0x%08x",
892 rec->type.new_fsf_req.fsf_seqno);
893 len += zfcp_dbf_stck(out_buf + len, "fsf_issued",
894 rec->type.new_fsf_req.fsf_issued);
895 } else if ((strncmp(rec->tag, "trst", ZFCP_DBF_TAG_SIZE) == 0) ||
896 (strncmp(rec->tag, "lrst", ZFCP_DBF_TAG_SIZE) == 0)) {
897 len += zfcp_dbf_view(out_buf + len, "fsf_reqid_reset", "0x%0Lx",
898 rec->type.new_fsf_req.fsf_reqid);
899 len += zfcp_dbf_view(out_buf + len, "fsf_seqno_reset", "0x%08x",
900 rec->type.new_fsf_req.fsf_seqno);
901 len += zfcp_dbf_stck(out_buf + len, "fsf_issued",
902 rec->type.new_fsf_req.fsf_issued);
905 len += sprintf(out_buf + len, "\n");
907 return len;
910 struct debug_view zfcp_scsi_dbf_view = {
911 "structured",
912 NULL,
913 &zfcp_dbf_view_header,
914 &zfcp_scsi_dbf_view_format,
915 NULL,
916 NULL
920 * zfcp_adapter_debug_register - registers debug feature for an adapter
921 * @adapter: pointer to adapter for which debug features should be registered
922 * return: -ENOMEM on error, 0 otherwise
924 int zfcp_adapter_debug_register(struct zfcp_adapter *adapter)
926 char dbf_name[DEBUG_MAX_NAME_LEN];
928 /* debug feature area which records recovery activity */
929 sprintf(dbf_name, "zfcp_%s_erp", zfcp_get_busid_by_adapter(adapter));
930 adapter->erp_dbf = debug_register(dbf_name, dbfsize, 2,
931 sizeof(struct zfcp_erp_dbf_record));
932 if (!adapter->erp_dbf)
933 goto failed;
934 debug_register_view(adapter->erp_dbf, &debug_hex_ascii_view);
935 debug_set_level(adapter->erp_dbf, 3);
937 /* debug feature area which records HBA (FSF and QDIO) conditions */
938 sprintf(dbf_name, "zfcp_%s_hba", zfcp_get_busid_by_adapter(adapter));
939 adapter->hba_dbf = debug_register(dbf_name, dbfsize, 1,
940 sizeof(struct zfcp_hba_dbf_record));
941 if (!adapter->hba_dbf)
942 goto failed;
943 debug_register_view(adapter->hba_dbf, &debug_hex_ascii_view);
944 debug_register_view(adapter->hba_dbf, &zfcp_hba_dbf_view);
945 debug_set_level(adapter->hba_dbf, 3);
947 /* debug feature area which records SAN command failures and recovery */
948 sprintf(dbf_name, "zfcp_%s_san", zfcp_get_busid_by_adapter(adapter));
949 adapter->san_dbf = debug_register(dbf_name, dbfsize, 1,
950 sizeof(struct zfcp_san_dbf_record));
951 if (!adapter->san_dbf)
952 goto failed;
953 debug_register_view(adapter->san_dbf, &debug_hex_ascii_view);
954 debug_register_view(adapter->san_dbf, &zfcp_san_dbf_view);
955 debug_set_level(adapter->san_dbf, 6);
957 /* debug feature area which records SCSI command failures and recovery */
958 sprintf(dbf_name, "zfcp_%s_scsi", zfcp_get_busid_by_adapter(adapter));
959 adapter->scsi_dbf = debug_register(dbf_name, dbfsize, 1,
960 sizeof(struct zfcp_scsi_dbf_record));
961 if (!adapter->scsi_dbf)
962 goto failed;
963 debug_register_view(adapter->scsi_dbf, &debug_hex_ascii_view);
964 debug_register_view(adapter->scsi_dbf, &zfcp_scsi_dbf_view);
965 debug_set_level(adapter->scsi_dbf, 3);
967 return 0;
969 failed:
970 zfcp_adapter_debug_unregister(adapter);
972 return -ENOMEM;
976 * zfcp_adapter_debug_unregister - unregisters debug feature for an adapter
977 * @adapter: pointer to adapter for which debug features should be unregistered
979 void zfcp_adapter_debug_unregister(struct zfcp_adapter *adapter)
981 debug_unregister(adapter->scsi_dbf);
982 debug_unregister(adapter->san_dbf);
983 debug_unregister(adapter->hba_dbf);
984 debug_unregister(adapter->erp_dbf);
985 adapter->scsi_dbf = NULL;
986 adapter->san_dbf = NULL;
987 adapter->hba_dbf = NULL;
988 adapter->erp_dbf = NULL;
991 #undef ZFCP_LOG_AREA