@@ -68,7 +68,7 @@
#define CREATE_TRACE_POINTS
#include <trace/events/qla.h>
-static uint32_t ql_dbg_offset = 0x800;
+uint32_t ql_dbg_offset = 0x800;
static inline void
qla2xxx_prep_dump(struct qla_hw_data *ha, struct qla2xxx_fw_dump *fw_dump)
@@ -2491,6 +2491,8 @@ ql_dbg(uint level, scsi_qla_host_t *vha, uint id, const char *fmt, ...)
struct va_format vaf;
char pbuf[64];
+ ql_msg_trace(1, level, vha, NULL, id, fmt);
+
if (!ql_mask_match(level) && !trace_ql_dbg_log_enabled())
return;
@@ -2533,6 +2535,9 @@ ql_dbg_pci(uint level, struct pci_dev *pdev, uint id, const char *fmt, ...)
if (pdev == NULL)
return;
+
+ ql_msg_trace(1, level, NULL, pdev, id, fmt);
+
if (!ql_mask_match(level))
return;
@@ -2570,6 +2575,8 @@ ql_log(uint level, scsi_qla_host_t *vha, uint id, const char *fmt, ...)
if (level > ql_errlev)
return;
+ ql_msg_trace(0, level, vha, NULL, id, fmt);
+
ql_dbg_prefix(pbuf, ARRAY_SIZE(pbuf), vha, id);
va_start(va, fmt);
@@ -2621,6 +2628,8 @@ ql_log_pci(uint level, struct pci_dev *pdev, uint id, const char *fmt, ...)
if (level > ql_errlev)
return;
+ ql_msg_trace(0, level, NULL, pdev, id, fmt);
+
ql_dbg_prefix(pbuf, ARRAY_SIZE(pbuf), NULL, id);
va_start(va, fmt);
@@ -2783,9 +2792,12 @@ void qla_tracing_init(void)
{
if (is_kdump_kernel())
return;
+
+ qla_trace_init(&qla_message_trace, "message_trace", ql2xnum_msg_trace);
}
void qla_tracing_exit(void)
{
+ qla_trace_uninit(&qla_message_trace);
}
#endif /* QLA_TRACING */
@@ -325,6 +325,24 @@ extern uint ql_errlev;
#ifdef QLA_TRACING
#include <linux/crash_dump.h>
+#define QLA_MTRC_DEF_NUM_REC (4*1024) /* Has to be power of 2 */
+#define QLA_MESSAGE_TRACE_DEFINES \
+ struct qla_trace qla_message_trace; \
+ int ql2xextended_error_logging_msg_trace = 1; \
+ module_param(ql2xextended_error_logging_msg_trace, int, 0600); \
+ MODULE_PARM_DESC(ql2xextended_error_logging_msg_trace, \
+ "Option to log console messages to buffer; uses same " \
+ "ql2xextended_error_logging masks."); \
+ \
+ int ql2xnum_msg_trace = QLA_MTRC_DEF_NUM_REC; \
+ module_param(ql2xnum_msg_trace, int, 0600); \
+ MODULE_PARM_DESC(ql2xnum_msg_trace, \
+ "Number of trace entries in power of 2. (default 4k)");
+
+extern int ql2xnum_msg_trace;
+extern int ql2xextended_error_logging_msg_trace;
+
+extern struct qla_trace qla_message_trace;
extern void qla_tracing_init(void);
extern void qla_tracing_exit(void);
@@ -422,6 +440,61 @@ qla_trace_quiesce(struct qla_trace *trc)
return ret;
}
+#define ql_msg_trace(dbg_msg, level, vha, pdev, id, fmt) do { \
+ struct va_format _vaf; \
+ va_list _va; \
+ u32 dbg_off = dbg_msg ? ql_dbg_offset : 0; \
+ \
+ if (!test_bit(QLA_TRACE_ENABLED, &qla_message_trace.flags)) \
+ break; \
+ \
+ if (dbg_msg && !ql_mask_match_ext(level, \
+ &ql2xextended_error_logging_msg_trace)) \
+ break; \
+ \
+ va_start(_va, fmt); \
+ \
+ _vaf.fmt = fmt; \
+ _vaf.va = &_va; \
+ __ql_msg_trace(&qla_message_trace, vha, pdev, \
+ id + dbg_off, &_vaf); \
+ \
+ va_end(_va); \
+} while (0)
+
+/* Messages beyond QLA_TRACE_LINE_SIZE characters are not printed */
+static inline void
+__ql_msg_trace(struct qla_trace *trc, scsi_qla_host_t *vha,
+ struct pci_dev *pdev, uint id, struct va_format *vaf)
+{
+ int tl;
+ char *buf;
+ u64 t_us = ktime_to_us(ktime_get());
+ uint cpu = raw_smp_processor_id();
+
+ buf = qla_get_trace_next(trc);
+ if (!buf)
+ return;
+
+ if (vha) {
+ const struct pci_dev *_pdev = vha->hw->pdev;
+ tl = snprintf(buf, QLA_TRACE_LINE_SIZE,
+ "%12llu %03u %s [%s]-%04x:%ld: %pV", t_us, cpu,
+ QL_MSGHDR, dev_name(&(_pdev->dev)), id,
+ vha->host_no, vaf);
+ } else {
+ tl = snprintf(buf, QLA_TRACE_LINE_SIZE,
+ "%12llu %03u %s [%s]-%04x: : %pV", t_us, cpu, QL_MSGHDR,
+ pdev ? dev_name(&(pdev->dev)) : "0000:00:00.0",
+ id, vaf);
+ }
+
+ tl = min(tl, QLA_TRACE_LINE_SIZE - 1);
+ buf[tl] = '\0';
+
+ qla_trace_put(trc);
+}
+
static inline void
qla_trace_init(struct qla_trace *trc, char *name, u32 num_entries)
{
@@ -455,10 +528,16 @@ qla_trace_uninit(struct qla_trace *trc)
}
#else /* QLA_TRACING */
+#define ql_msg_trace(dbg_msg, level, vha, pdev, id, fmt) do { } while (0)
#define qla_trace_init(trc, name, num)
#define qla_trace_uninit(trc)
#define qla_tracing_init()
#define qla_tracing_exit()
+#define QLA_MESSAGE_TRACE_DEFINES
+
+#define ql_srb_trace_ext(_level, _vha, _fcport, _fmt, _args...) do { } while (0)
+#define ql_srb_trace(_level, _vha, _fmt, _args...) do { } while (0)
+#define QLA_SRB_TRACE_DEFINES
#endif /* QLA_TRACING */
void __attribute__((format (printf, 4, 5)))
@@ -11,6 +11,10 @@
static struct dentry *qla2x00_dfs_root;
static atomic_t qla2x00_dfs_root_count;
+#ifdef QLA_TRACING
+static QLA_DFS_ROOT_DEFINE_DENTRY(message_trace); /* qla_dfs_message_trace */
+#endif /* QLA_TRACING */
+
#define QLA_DFS_RPORT_DEVLOSS_TMO 1
static int
@@ -589,6 +593,18 @@ qla_dfs_trace_write(struct file *file, const char __user *buffer,
done:
return ret;
}
+
+static int
+qla_dfs_message_trace_show(struct seq_file *s, void *unused)
+{
+ return qla_dfs_trace_show(s, unused);
+}
+static ssize_t
+qla_dfs_message_trace_write(struct file *file, const char __user *buffer,
+ size_t count, loff_t *pos)
+{
+ return qla_dfs_trace_write(file, buffer, count, pos);
+}
#endif /* QLA_TRACING */
/*
@@ -681,6 +697,10 @@ static const struct file_operations qla_dfs_##_name##_ops = { \
} \
} while (0)
+#ifdef QLA_TRACING
+QLA_DFS_SETUP_RW(message_trace, struct qla_trace *);
+#endif /* QLA_TRACING */
+
static int
qla_dfs_naqp_open(struct inode *inode, struct file *file)
{
@@ -788,6 +808,11 @@ qla2x00_dfs_setup(scsi_qla_host_t *vha)
ha->tgt.dfs_tgt_sess = debugfs_create_file("tgt_sess",
S_IRUSR, ha->dfs_dir, vha, &qla2x00_dfs_tgt_sess_fops);
+#ifdef QLA_TRACING
+ QLA_DFS_ROOT_CREATE_FILE(message_trace, 0600, &qla_message_trace);
+
+#endif /* QLA_TRACING */
+
if (IS_QLA27XX(ha) || IS_QLA83XX(ha) || IS_QLA28XX(ha)) {
ha->tgt.dfs_naqp = debugfs_create_file("naqp",
0400, ha->dfs_dir, vha, &dfs_naqp_ops);
@@ -847,6 +872,11 @@ qla2x00_dfs_remove(scsi_qla_host_t *vha)
vha->dfs_rport_root = NULL;
}
+#ifdef QLA_TRACING
+ QLA_DFS_ROOT_REMOVE_FILE(message_trace);
+
+#endif /* QLA_TRACING */
+
if (ha->dfs_dir) {
debugfs_remove(ha->dfs_dir);
ha->dfs_dir = NULL;
@@ -163,6 +163,7 @@ extern int ql2xrdpenable;
extern int ql2xsmartsan;
extern int ql2xallocfwdump;
extern int ql2xextended_error_logging;
+extern uint32_t ql_dbg_offset;
extern int ql2xiidmaenable;
extern int ql2xmqsupport;
extern int ql2xfwloadbin;
@@ -117,6 +117,8 @@ MODULE_PARM_DESC(ql2xextended_error_logging,
"ql2xextended_error_logging=1).\n"
"\t\tDo LOGICAL OR of the value to enable more than one level");
+QLA_MESSAGE_TRACE_DEFINES;
+
int ql2xshiftctondsd = 6;
module_param(ql2xshiftctondsd, int, S_IRUGO);
MODULE_PARM_DESC(ql2xshiftctondsd,