diff options
Diffstat (limited to 'drivers/scsi/qla2xxx/qla_dbg.c')
-rw-r--r-- | drivers/scsi/qla2xxx/qla_dbg.c | 396 |
1 files changed, 288 insertions, 108 deletions
diff --git a/drivers/scsi/qla2xxx/qla_dbg.c b/drivers/scsi/qla2xxx/qla_dbg.c index c53719a9a747..d79cd8a5f831 100644 --- a/drivers/scsi/qla2xxx/qla_dbg.c +++ b/drivers/scsi/qla2xxx/qla_dbg.c @@ -4,10 +4,36 @@ * * See LICENSE.qla2xxx for copyright and licensing details. */ + +/* + * Table for showing the current message id in use for particular level + * Change this table for addition of log/debug messages. + * ---------------------------------------------------------------------- + * | Level | Last Value Used | Holes | + * ---------------------------------------------------------------------- + * | Module Init and Probe | 0x0116 | | + * | Mailbox commands | 0x1126 | | + * | Device Discovery | 0x2083 | | + * | Queue Command and IO tracing | 0x302e | 0x3008 | + * | DPC Thread | 0x401c | | + * | Async Events | 0x5059 | | + * | Timer Routines | 0x600d | | + * | User Space Interactions | 0x709d | | + * | Task Management | 0x8041 | | + * | AER/EEH | 0x900f | | + * | Virtual Port | 0xa007 | | + * | ISP82XX Specific | 0xb04f | | + * | MultiQ | 0xc00b | | + * | Misc | 0xd00b | | + * ---------------------------------------------------------------------- + */ + #include "qla_def.h" #include <linux/delay.h> +static uint32_t ql_dbg_offset = 0x800; + static inline void qla2xxx_prep_dump(struct qla_hw_data *ha, struct qla2xxx_fw_dump *fw_dump) { @@ -383,11 +409,11 @@ qla2xxx_dump_post_process(scsi_qla_host_t *vha, int rval) struct qla_hw_data *ha = vha->hw; if (rval != QLA_SUCCESS) { - qla_printk(KERN_WARNING, ha, - "Failed to dump firmware (%x)!!!\n", rval); + ql_log(ql_log_warn, vha, 0xd000, + "Failed to dump firmware (%x).\n", rval); ha->fw_dumped = 0; } else { - qla_printk(KERN_INFO, ha, + ql_log(ql_log_info, vha, 0xd001, "Firmware dump saved to temp buffer (%ld/%p).\n", vha->host_no, ha->fw_dump); ha->fw_dumped = 1; @@ -419,15 +445,16 @@ qla2300_fw_dump(scsi_qla_host_t *vha, int hardware_locked) spin_lock_irqsave(&ha->hardware_lock, flags); if (!ha->fw_dump) { - qla_printk(KERN_WARNING, ha, - "No buffer available for dump!!!\n"); + ql_log(ql_log_warn, vha, 0xd002, + "No buffer available for dump.\n"); goto qla2300_fw_dump_failed; } if (ha->fw_dumped) { - qla_printk(KERN_WARNING, ha, - "Firmware has been previously dumped (%p) -- ignoring " - "request...\n", ha->fw_dump); + ql_log(ql_log_warn, vha, 0xd003, + "Firmware has been previously dumped (%p) " + "-- ignoring request.\n", + ha->fw_dump); goto qla2300_fw_dump_failed; } fw = &ha->fw_dump->isp.isp23; @@ -582,15 +609,16 @@ qla2100_fw_dump(scsi_qla_host_t *vha, int hardware_locked) spin_lock_irqsave(&ha->hardware_lock, flags); if (!ha->fw_dump) { - qla_printk(KERN_WARNING, ha, - "No buffer available for dump!!!\n"); + ql_log(ql_log_warn, vha, 0xd004, + "No buffer available for dump.\n"); goto qla2100_fw_dump_failed; } if (ha->fw_dumped) { - qla_printk(KERN_WARNING, ha, - "Firmware has been previously dumped (%p) -- ignoring " - "request...\n", ha->fw_dump); + ql_log(ql_log_warn, vha, 0xd005, + "Firmware has been previously dumped (%p) " + "-- ignoring request.\n", + ha->fw_dump); goto qla2100_fw_dump_failed; } fw = &ha->fw_dump->isp.isp21; @@ -779,15 +807,16 @@ qla24xx_fw_dump(scsi_qla_host_t *vha, int hardware_locked) spin_lock_irqsave(&ha->hardware_lock, flags); if (!ha->fw_dump) { - qla_printk(KERN_WARNING, ha, - "No buffer available for dump!!!\n"); + ql_log(ql_log_warn, vha, 0xd006, + "No buffer available for dump.\n"); goto qla24xx_fw_dump_failed; } if (ha->fw_dumped) { - qla_printk(KERN_WARNING, ha, - "Firmware has been previously dumped (%p) -- ignoring " - "request...\n", ha->fw_dump); + ql_log(ql_log_warn, vha, 0xd007, + "Firmware has been previously dumped (%p) " + "-- ignoring request.\n", + ha->fw_dump); goto qla24xx_fw_dump_failed; } fw = &ha->fw_dump->isp.isp24; @@ -1017,15 +1046,16 @@ qla25xx_fw_dump(scsi_qla_host_t *vha, int hardware_locked) spin_lock_irqsave(&ha->hardware_lock, flags); if (!ha->fw_dump) { - qla_printk(KERN_WARNING, ha, - "No buffer available for dump!!!\n"); + ql_log(ql_log_warn, vha, 0xd008, + "No buffer available for dump.\n"); goto qla25xx_fw_dump_failed; } if (ha->fw_dumped) { - qla_printk(KERN_WARNING, ha, - "Firmware has been previously dumped (%p) -- ignoring " - "request...\n", ha->fw_dump); + ql_log(ql_log_warn, vha, 0xd009, + "Firmware has been previously dumped (%p) " + "-- ignoring request.\n", + ha->fw_dump); goto qla25xx_fw_dump_failed; } fw = &ha->fw_dump->isp.isp25; @@ -1328,15 +1358,16 @@ qla81xx_fw_dump(scsi_qla_host_t *vha, int hardware_locked) spin_lock_irqsave(&ha->hardware_lock, flags); if (!ha->fw_dump) { - qla_printk(KERN_WARNING, ha, - "No buffer available for dump!!!\n"); + ql_log(ql_log_warn, vha, 0xd00a, + "No buffer available for dump.\n"); goto qla81xx_fw_dump_failed; } if (ha->fw_dumped) { - qla_printk(KERN_WARNING, ha, - "Firmware has been previously dumped (%p) -- ignoring " - "request...\n", ha->fw_dump); + ql_log(ql_log_warn, vha, 0xd00b, + "Firmware has been previously dumped (%p) " + "-- ignoring request.\n", + ha->fw_dump); goto qla81xx_fw_dump_failed; } fw = &ha->fw_dump->isp.isp81; @@ -1619,106 +1650,255 @@ qla81xx_fw_dump_failed: /****************************************************************************/ /* Driver Debug Functions. */ /****************************************************************************/ - +/* + * This function is for formatting and logging debug information. + * It is to be used when vha is available. It formats the message + * and logs it to the messages file. + * parameters: + * level: The level of the debug messages to be printed. + * If ql2xextended_error_logging value is correctly set, + * this message will appear in the messages file. + * vha: Pointer to the scsi_qla_host_t. + * id: This is a unique identifier for the level. It identifies the + * part of the code from where the message originated. + * msg: The message to be displayed. + */ void -qla2x00_dump_regs(scsi_qla_host_t *vha) -{ - int i; - struct qla_hw_data *ha = vha->hw; - struct device_reg_2xxx __iomem *reg = &ha->iobase->isp; - struct device_reg_24xx __iomem *reg24 = &ha->iobase->isp24; - uint16_t __iomem *mbx_reg; +ql_dbg(uint32_t level, scsi_qla_host_t *vha, int32_t id, char *msg, ...) { + + char pbuf[QL_DBG_BUF_LEN]; + va_list ap; + uint32_t len; + struct pci_dev *pdev = NULL; + + memset(pbuf, 0, QL_DBG_BUF_LEN); + + va_start(ap, msg); + + if ((level & ql2xextended_error_logging) == level) { + if (vha != NULL) { + pdev = vha->hw->pdev; + /* <module-name> <pci-name> <msg-id>:<host> Message */ + sprintf(pbuf, "%s [%s]-%04x:%ld: ", QL_MSGHDR, + dev_name(&(pdev->dev)), id + ql_dbg_offset, + vha->host_no); + } else + sprintf(pbuf, "%s [%s]-%04x: : ", QL_MSGHDR, + "0000:00:00.0", id + ql_dbg_offset); + + len = strlen(pbuf); + vsprintf(pbuf+len, msg, ap); + pr_warning("%s", pbuf); + } - mbx_reg = IS_FWI2_CAPABLE(ha) ? ®24->mailbox0: - MAILBOX_REG(ha, reg, 0); + va_end(ap); - printk("Mailbox registers:\n"); - for (i = 0; i < 6; i++) - printk("scsi(%ld): mbox %d 0x%04x \n", vha->host_no, i, - RD_REG_WORD(mbx_reg++)); } - +/* + * This function is for formatting and logging debug information. + * It is to be used when vha is not available and pci is availble, + * i.e., before host allocation. It formats the message and logs it + * to the messages file. + * parameters: + * level: The level of the debug messages to be printed. + * If ql2xextended_error_logging value is correctly set, + * this message will appear in the messages file. + * pdev: Pointer to the struct pci_dev. + * id: This is a unique id for the level. It identifies the part + * of the code from where the message originated. + * msg: The message to be displayed. + */ void -qla2x00_dump_buffer(uint8_t * b, uint32_t size) -{ - uint32_t cnt; - uint8_t c; +ql_dbg_pci(uint32_t level, struct pci_dev *pdev, int32_t id, char *msg, ...) { - printk(" 0 1 2 3 4 5 6 7 8 9 " - "Ah Bh Ch Dh Eh Fh\n"); - printk("----------------------------------------" - "----------------------\n"); - - for (cnt = 0; cnt < size;) { - c = *b++; - printk("%02x",(uint32_t) c); - cnt++; - if (!(cnt % 16)) - printk("\n"); - else - printk(" "); + char pbuf[QL_DBG_BUF_LEN]; + va_list ap; + uint32_t len; + + if (pdev == NULL) + return; + + memset(pbuf, 0, QL_DBG_BUF_LEN); + + va_start(ap, msg); + + if ((level & ql2xextended_error_logging) == level) { + /* <module-name> <dev-name>:<msg-id> Message */ + sprintf(pbuf, "%s [%s]-%04x: : ", QL_MSGHDR, + dev_name(&(pdev->dev)), id + ql_dbg_offset); + + len = strlen(pbuf); + vsprintf(pbuf+len, msg, ap); + pr_warning("%s", pbuf); } - if (cnt % 16) - printk("\n"); + + va_end(ap); + } +/* + * This function is for formatting and logging log messages. + * It is to be used when vha is available. It formats the message + * and logs it to the messages file. All the messages will be logged + * irrespective of value of ql2xextended_error_logging. + * parameters: + * level: The level of the log messages to be printed in the + * messages file. + * vha: Pointer to the scsi_qla_host_t + * id: This is a unique id for the level. It identifies the + * part of the code from where the message originated. + * msg: The message to be displayed. + */ void -qla2x00_dump_buffer_zipped(uint8_t *b, uint32_t size) -{ - uint32_t cnt; - uint8_t c; - uint8_t last16[16], cur16[16]; - uint32_t lc = 0, num_same16 = 0, j; +ql_log(uint32_t level, scsi_qla_host_t *vha, int32_t id, char *msg, ...) { - printk(KERN_DEBUG " 0 1 2 3 4 5 6 7 8 9 " - "Ah Bh Ch Dh Eh Fh\n"); - printk(KERN_DEBUG "----------------------------------------" - "----------------------\n"); + char pbuf[QL_DBG_BUF_LEN]; + va_list ap; + uint32_t len; + struct pci_dev *pdev = NULL; - for (cnt = 0; cnt < size;) { - c = *b++; + memset(pbuf, 0, QL_DBG_BUF_LEN); - cur16[lc++] = c; + va_start(ap, msg); - cnt++; - if (cnt % 16) - continue; - - /* We have 16 now */ - lc = 0; - if (num_same16 == 0) { - memcpy(last16, cur16, 16); - num_same16++; - continue; + if (level <= ql_errlev) { + if (vha != NULL) { + pdev = vha->hw->pdev; + /* <module-name> <msg-id>:<host> Message */ + sprintf(pbuf, "%s [%s]-%04x:%ld: ", QL_MSGHDR, + dev_name(&(pdev->dev)), id, vha->host_no); + } else + sprintf(pbuf, "%s [%s]-%04x: : ", QL_MSGHDR, + "0000:00:00.0", id); + + len = strlen(pbuf); + vsprintf(pbuf+len, msg, ap); + + switch (level) { + case 0: /* FATAL LOG */ + pr_crit("%s", pbuf); + break; + case 1: + pr_err("%s", pbuf); + break; + case 2: + pr_warn("%s", pbuf); + break; + default: + pr_info("%s", pbuf); + break; } - if (memcmp(cur16, last16, 16) == 0) { - num_same16++; - continue; + } + + va_end(ap); +} + +/* + * This function is for formatting and logging log messages. + * It is to be used when vha is not available and pci is availble, + * i.e., before host allocation. It formats the message and logs + * it to the messages file. All the messages are logged irrespective + * of the value of ql2xextended_error_logging. + * parameters: + * level: The level of the log messages to be printed in the + * messages file. + * pdev: Pointer to the struct pci_dev. + * id: This is a unique id for the level. It identifies the + * part of the code from where the message originated. + * msg: The message to be displayed. + */ +void +ql_log_pci(uint32_t level, struct pci_dev *pdev, int32_t id, char *msg, ...) { + + char pbuf[QL_DBG_BUF_LEN]; + va_list ap; + uint32_t len; + + if (pdev == NULL) + return; + + memset(pbuf, 0, QL_DBG_BUF_LEN); + + va_start(ap, msg); + + if (level <= ql_errlev) { + /* <module-name> <dev-name>:<msg-id> Message */ + sprintf(pbuf, "%s [%s]-%04x: : ", QL_MSGHDR, + dev_name(&(pdev->dev)), id); + + len = strlen(pbuf); + vsprintf(pbuf+len, msg, ap); + switch (level) { + case 0: /* FATAL LOG */ + pr_crit("%s", pbuf); + break; + case 1: + pr_err("%s", pbuf); + break; + case 2: + pr_warn("%s", pbuf); + break; + default: + pr_info("%s", pbuf); + break; } - for (j = 0; j < 16; j++) - printk(KERN_DEBUG "%02x ", (uint32_t)last16[j]); - printk(KERN_DEBUG "\n"); - - if (num_same16 > 1) - printk(KERN_DEBUG "> prev pattern repeats (%u)" - "more times\n", num_same16-1); - memcpy(last16, cur16, 16); - num_same16 = 1; } - if (num_same16) { - for (j = 0; j < 16; j++) - printk(KERN_DEBUG "%02x ", (uint32_t)last16[j]); - printk(KERN_DEBUG "\n"); + va_end(ap); +} - if (num_same16 > 1) - printk(KERN_DEBUG "> prev pattern repeats (%u)" - "more times\n", num_same16-1); +void +ql_dump_regs(uint32_t level, scsi_qla_host_t *vha, int32_t id) +{ + int i; + struct qla_hw_data *ha = vha->hw; + struct device_reg_2xxx __iomem *reg = &ha->iobase->isp; + struct device_reg_24xx __iomem *reg24 = &ha->iobase->isp24; + struct device_reg_82xx __iomem *reg82 = &ha->iobase->isp82; + uint16_t __iomem *mbx_reg; + + if ((level & ql2xextended_error_logging) == level) { + + if (IS_QLA82XX(ha)) + mbx_reg = ®82->mailbox_in[0]; + else if (IS_FWI2_CAPABLE(ha)) + mbx_reg = ®24->mailbox0; + else + mbx_reg = MAILBOX_REG(ha, reg, 0); + + ql_dbg(level, vha, id, "Mailbox registers:\n"); + for (i = 0; i < 6; i++) + ql_dbg(level, vha, id, + "mbox[%d] 0x%04x\n", i, RD_REG_WORD(mbx_reg++)); } - if (lc) { - for (j = 0; j < lc; j++) - printk(KERN_DEBUG "%02x ", (uint32_t)cur16[j]); - printk(KERN_DEBUG "\n"); +} + + +void +ql_dump_buffer(uint32_t level, scsi_qla_host_t *vha, int32_t id, + uint8_t *b, uint32_t size) +{ + uint32_t cnt; + uint8_t c; + if ((level & ql2xextended_error_logging) == level) { + + ql_dbg(level, vha, id, " 0 1 2 3 4 5 6 7 8 " + "9 Ah Bh Ch Dh Eh Fh\n"); + ql_dbg(level, vha, id, "----------------------------------" + "----------------------------\n"); + + ql_dbg(level, vha, id, ""); + for (cnt = 0; cnt < size;) { + c = *b++; + printk("%02x", (uint32_t) c); + cnt++; + if (!(cnt % 16)) + printk("\n"); + else + printk(" "); + } + if (cnt % 16) + ql_dbg(level, vha, id, "\n"); } } |