[SCSI] qla2xxx: Basic infrastructure for dynamic logging.
[pandora-kernel.git] / drivers / scsi / qla2xxx / qla_dbg.c
index c53719a..dba9eed 100644 (file)
@@ -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  |
+ * -----------------------------------------------------
+ * | Module Init and Probe        |       0x0109       |
+ * | Mailbox commands             |       0x1120       |
+ * | Device Discovery             |       0x207d       |
+ * | Queue Command and IO tracing |       0x304f       |
+ * | DPC Thread                   |       0x401c       |
+ * | Async Events                 |       0x5058       |
+ * | Timer Routines               |       0x600d       |
+ * | User Space Interactions      |       0x70a1       |
+ * | Task Management              |       0x8032       |
+ * | AER/EEH                      |       0x9010       |
+ * | Virtual Port                 |       0xa007       |
+ * | ISP82XX Specific             |       0xb028       |
+ * | 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)
 {
@@ -1722,3 +1748,255 @@ qla2x00_dump_buffer_zipped(uint8_t *b, uint32_t size)
                printk(KERN_DEBUG "\n");
        }
 }
+/*
+ * 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
+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);
+       }
+
+       va_end(ap);
+
+}
+
+/*
+ * 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
+ql_dbg_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 & 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);
+       }
+
+       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
+ql_log(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 <= 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;
+               }
+       }
+
+       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;
+               }
+       }
+
+       va_end(ap);
+}
+
+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 = &reg82->mailbox_in[0];
+               else if (IS_FWI2_CAPABLE(ha))
+                       mbx_reg = &reg24->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++));
+       }
+}
+
+
+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");
+       }
+}