📄 zfcp_dbf.c
字号:
/* * * linux/drivers/s390/scsi/zfcp_dbf.c * * FCP adapter driver for IBM eServer zSeries * * Debugging facilities * * (C) Copyright IBM Corp. 2005 * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2, or (at your option) * any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. */#define ZFCP_DBF_REVISION "$Revision$"#include <asm/debug.h>#include <linux/ctype.h>#include "zfcp_ext.h"static u32 dbfsize = 4;module_param(dbfsize, uint, 0400);MODULE_PARM_DESC(dbfsize, "number of pages for each debug feature area (default 4)");#define ZFCP_LOG_AREA ZFCP_LOG_AREA_OTHERstatic inline intzfcp_dbf_stck(char *out_buf, const char *label, unsigned long long stck){ unsigned long long sec; struct timespec xtime; int len = 0; stck -= 0x8126d60e46000000LL - (0x3c26700LL * 1000000 * 4096); sec = stck >> 12; do_div(sec, 1000000); xtime.tv_sec = sec; stck -= (sec * 1000000) << 12; xtime.tv_nsec = ((stck * 1000) >> 12); len += sprintf(out_buf + len, "%-24s%011lu:%06lu\n", label, xtime.tv_sec, xtime.tv_nsec); return len;}static int zfcp_dbf_tag(char *out_buf, const char *label, const char *tag){ int len = 0, i; len += sprintf(out_buf + len, "%-24s", label); for (i = 0; i < ZFCP_DBF_TAG_SIZE; i++) len += sprintf(out_buf + len, "%c", tag[i]); len += sprintf(out_buf + len, "\n"); return len;}static intzfcp_dbf_view(char *out_buf, const char *label, const char *format, ...){ va_list arg; int len = 0; len += sprintf(out_buf + len, "%-24s", label); va_start(arg, format); len += vsprintf(out_buf + len, format, arg); va_end(arg); len += sprintf(out_buf + len, "\n"); return len;}static intzfcp_dbf_view_dump(char *out_buf, const char *label, char *buffer, int buflen, int offset, int total_size){ int len = 0; if (offset == 0) len += sprintf(out_buf + len, "%-24s ", label); while (buflen--) { if (offset > 0) { if ((offset % 32) == 0) len += sprintf(out_buf + len, "\n%-24c ", ' '); else if ((offset % 4) == 0) len += sprintf(out_buf + len, " "); } len += sprintf(out_buf + len, "%02x", *buffer++); if (++offset == total_size) { len += sprintf(out_buf + len, "\n"); break; } } if (total_size == 0) len += sprintf(out_buf + len, "\n"); return len;}static inline intzfcp_dbf_view_header(debug_info_t * id, struct debug_view *view, int area, debug_entry_t * entry, char *out_buf){ struct zfcp_dbf_dump *dump = (struct zfcp_dbf_dump *)DEBUG_DATA(entry); int len = 0; if (strncmp(dump->tag, "dump", ZFCP_DBF_TAG_SIZE) != 0) { len += zfcp_dbf_stck(out_buf + len, "timestamp", entry->id.stck); len += zfcp_dbf_view(out_buf + len, "cpu", "%02i", entry->id.fields.cpuid); } else { len += zfcp_dbf_view_dump(out_buf + len, NULL, dump->data, dump->size, dump->offset, dump->total_size); if ((dump->offset + dump->size) == dump->total_size) len += sprintf(out_buf + len, "\n"); } return len;}inline void zfcp_hba_dbf_event_fsf_response(struct zfcp_fsf_req *fsf_req){ struct zfcp_adapter *adapter = fsf_req->adapter; struct fsf_qtcb *qtcb = fsf_req->qtcb; union fsf_prot_status_qual *prot_status_qual = &qtcb->prefix.prot_status_qual; union fsf_status_qual *fsf_status_qual = &qtcb->header.fsf_status_qual; struct scsi_cmnd *scsi_cmnd; struct zfcp_port *port; struct zfcp_unit *unit; struct zfcp_send_els *send_els; struct zfcp_hba_dbf_record *rec = &adapter->hba_dbf_buf; struct zfcp_hba_dbf_record_response *response = &rec->type.response; int level; unsigned long flags; spin_lock_irqsave(&adapter->hba_dbf_lock, flags); memset(rec, 0, sizeof(struct zfcp_hba_dbf_record)); strncpy(rec->tag, "resp", ZFCP_DBF_TAG_SIZE); if ((qtcb->prefix.prot_status != FSF_PROT_GOOD) && (qtcb->prefix.prot_status != FSF_PROT_FSF_STATUS_PRESENTED)) { strncpy(rec->tag2, "perr", ZFCP_DBF_TAG_SIZE); level = 1; } else if (qtcb->header.fsf_status != FSF_GOOD) { strncpy(rec->tag2, "ferr", ZFCP_DBF_TAG_SIZE); level = 1; } else if ((fsf_req->fsf_command == FSF_QTCB_OPEN_PORT_WITH_DID) || (fsf_req->fsf_command == FSF_QTCB_OPEN_LUN)) { strncpy(rec->tag2, "open", ZFCP_DBF_TAG_SIZE); level = 4; } else if ((prot_status_qual->doubleword[0] != 0) || (prot_status_qual->doubleword[1] != 0) || (fsf_status_qual->doubleword[0] != 0) || (fsf_status_qual->doubleword[1] != 0)) { strncpy(rec->tag2, "qual", ZFCP_DBF_TAG_SIZE); level = 3; } else { strncpy(rec->tag2, "norm", ZFCP_DBF_TAG_SIZE); level = 6; } response->fsf_command = fsf_req->fsf_command; response->fsf_reqid = (unsigned long)fsf_req; response->fsf_seqno = fsf_req->seq_no; response->fsf_issued = fsf_req->issued; response->fsf_prot_status = qtcb->prefix.prot_status; response->fsf_status = qtcb->header.fsf_status; memcpy(response->fsf_prot_status_qual, prot_status_qual, FSF_PROT_STATUS_QUAL_SIZE); memcpy(response->fsf_status_qual, fsf_status_qual, FSF_STATUS_QUALIFIER_SIZE); response->fsf_req_status = fsf_req->status; response->sbal_first = fsf_req->sbal_first; response->sbal_curr = fsf_req->sbal_curr; response->sbal_last = fsf_req->sbal_last; response->pool = fsf_req->pool != NULL; response->erp_action = (unsigned long)fsf_req->erp_action; switch (fsf_req->fsf_command) { case FSF_QTCB_FCP_CMND: if (fsf_req->status & ZFCP_STATUS_FSFREQ_TASK_MANAGEMENT) break; scsi_cmnd = (struct scsi_cmnd *)fsf_req->data; if (scsi_cmnd != NULL) { response->data.send_fcp.scsi_cmnd = (unsigned long)scsi_cmnd; response->data.send_fcp.scsi_serial = scsi_cmnd->serial_number; } break; case FSF_QTCB_OPEN_PORT_WITH_DID: case FSF_QTCB_CLOSE_PORT: case FSF_QTCB_CLOSE_PHYSICAL_PORT: port = (struct zfcp_port *)fsf_req->data; response->data.port.wwpn = port->wwpn; response->data.port.d_id = port->d_id; response->data.port.port_handle = qtcb->header.port_handle; break; case FSF_QTCB_OPEN_LUN: case FSF_QTCB_CLOSE_LUN: unit = (struct zfcp_unit *)fsf_req->data; port = unit->port; response->data.unit.wwpn = port->wwpn; response->data.unit.fcp_lun = unit->fcp_lun; response->data.unit.port_handle = qtcb->header.port_handle; response->data.unit.lun_handle = qtcb->header.lun_handle; break; case FSF_QTCB_SEND_ELS: send_els = (struct zfcp_send_els *)fsf_req->data; response->data.send_els.d_id = qtcb->bottom.support.d_id; response->data.send_els.ls_code = send_els->ls_code >> 24; break; case FSF_QTCB_ABORT_FCP_CMND: case FSF_QTCB_SEND_GENERIC: case FSF_QTCB_EXCHANGE_CONFIG_DATA: case FSF_QTCB_EXCHANGE_PORT_DATA: case FSF_QTCB_DOWNLOAD_CONTROL_FILE: case FSF_QTCB_UPLOAD_CONTROL_FILE: break; } debug_event(adapter->hba_dbf, level, rec, sizeof(struct zfcp_hba_dbf_record)); spin_unlock_irqrestore(&adapter->hba_dbf_lock, flags);}inline voidzfcp_hba_dbf_event_fsf_unsol(const char *tag, struct zfcp_adapter *adapter, struct fsf_status_read_buffer *status_buffer){ struct zfcp_hba_dbf_record *rec = &adapter->hba_dbf_buf; unsigned long flags; spin_lock_irqsave(&adapter->hba_dbf_lock, flags); memset(rec, 0, sizeof(struct zfcp_hba_dbf_record)); strncpy(rec->tag, "stat", ZFCP_DBF_TAG_SIZE); strncpy(rec->tag2, tag, ZFCP_DBF_TAG_SIZE); rec->type.status.failed = adapter->status_read_failed; if (status_buffer != NULL) { rec->type.status.status_type = status_buffer->status_type; rec->type.status.status_subtype = status_buffer->status_subtype; memcpy(&rec->type.status.queue_designator, &status_buffer->queue_designator, sizeof(struct fsf_queue_designator)); switch (status_buffer->status_type) { case FSF_STATUS_READ_SENSE_DATA_AVAIL: rec->type.status.payload_size = ZFCP_DBF_UNSOL_PAYLOAD_SENSE_DATA_AVAIL; break; case FSF_STATUS_READ_BIT_ERROR_THRESHOLD: rec->type.status.payload_size = ZFCP_DBF_UNSOL_PAYLOAD_BIT_ERROR_THRESHOLD; break; case FSF_STATUS_READ_LINK_DOWN: switch (status_buffer->status_subtype) { case FSF_STATUS_READ_SUB_NO_PHYSICAL_LINK: case FSF_STATUS_READ_SUB_FDISC_FAILED: rec->type.status.payload_size = sizeof(struct fsf_link_down_info); } break; case FSF_STATUS_READ_FEATURE_UPDATE_ALERT: rec->type.status.payload_size = ZFCP_DBF_UNSOL_PAYLOAD_FEATURE_UPDATE_ALERT; break; } memcpy(&rec->type.status.payload, &status_buffer->payload, rec->type.status.payload_size); } debug_event(adapter->hba_dbf, 2, rec, sizeof(struct zfcp_hba_dbf_record)); spin_unlock_irqrestore(&adapter->hba_dbf_lock, flags);}inline voidzfcp_hba_dbf_event_qdio(struct zfcp_adapter *adapter, unsigned int status, unsigned int qdio_error, unsigned int siga_error, int sbal_index, int sbal_count){ struct zfcp_hba_dbf_record *rec = &adapter->hba_dbf_buf; unsigned long flags; spin_lock_irqsave(&adapter->hba_dbf_lock, flags); memset(rec, 0, sizeof(struct zfcp_hba_dbf_record)); strncpy(rec->tag, "qdio", ZFCP_DBF_TAG_SIZE); rec->type.qdio.status = status; rec->type.qdio.qdio_error = qdio_error; rec->type.qdio.siga_error = siga_error; rec->type.qdio.sbal_index = sbal_index; rec->type.qdio.sbal_count = sbal_count; debug_event(adapter->hba_dbf, 0, rec, sizeof(struct zfcp_hba_dbf_record)); spin_unlock_irqrestore(&adapter->hba_dbf_lock, flags);}static inline intzfcp_hba_dbf_view_response(char *out_buf, struct zfcp_hba_dbf_record_response *rec){ int len = 0; len += zfcp_dbf_view(out_buf + len, "fsf_command", "0x%08x",
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -