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