@@ -342,6 +342,22 @@ extern uint ql_errlev;
extern int ql2xnum_msg_trace;
extern int ql2xextended_error_logging_msg_trace;
+#define QLA_SRB_TRACE_DEFINES \
+ int ql2xextended_error_logging_srb_trace = 1; \
+ module_param(ql2xextended_error_logging_srb_trace, int, \
+ S_IRUGO|S_IWUSR); \
+ MODULE_PARM_DESC(ql2xextended_error_logging_srb_trace, \
+ "Option to log srb messages to buffer; uses same " \
+ "ql2xextended_error_logging masks."); \
+ \
+ int ql2xnum_srb_trace = 0; \
+ module_param(ql2xnum_srb_trace, int, S_IRUGO); \
+ MODULE_PARM_DESC(ql2xnum_srb_trace, \
+ "Number of srb trace entries in power of 2. (default 0)");
+
+extern int ql2xnum_srb_trace;
+extern int ql2xextended_error_logging_srb_trace;
+
extern struct qla_trace qla_message_trace;
extern void qla_tracing_init(void);
extern void qla_tracing_exit(void);
@@ -495,6 +511,57 @@ __ql_msg_trace(struct qla_trace *trc, scsi_qla_host_t *vha,
qla_trace_put(trc);
}
+#define ql_srb_trace_ext(_level, _vha, _fcport, _fmt, _args...) do { \
+ if (_fcport) { \
+ __ql_srb_trace(_level, _vha, \
+ DBG_FCPORT_PRFMT(_fcport, _fmt, ##_args)); \
+ } else { \
+ __ql_srb_trace(_level, _vha, \
+ "%s: " _fmt "\n", __func__, ##_args); \
+ } \
+} while (0)
+
+#define ql_srb_trace(_level, _vha, _fmt, _args...) \
+ __ql_srb_trace(_level, _vha, _fmt, ##_args)
+
+static inline void
+__ql_srb_trace(int level, scsi_qla_host_t *vha, const char *fmt, ...)
+{
+ int tl;
+ char *buf;
+ u64 t_us;
+ uint cpu;
+ struct va_format vaf;
+ va_list va;
+
+ if (!test_bit(QLA_TRACE_ENABLED, &vha->hw->srb_trace.flags))
+ return;
+
+ if (!ql_mask_match_ext(level, &ql2xextended_error_logging_srb_trace))
+ return;
+
+ t_us = ktime_to_us(ktime_get());
+ cpu = raw_smp_processor_id();
+ buf = qla_get_trace_next(&vha->hw->srb_trace);
+ if (!buf)
+ return;
+
+ va_start(va, fmt);
+
+ vaf.fmt = fmt;
+ vaf.va = &va;
+
+ tl = snprintf(buf, QLA_TRACE_LINE_SIZE, "%12llu %03u %pV",
+ t_us, cpu, &vaf);
+
+ tl = min(tl, QLA_TRACE_LINE_SIZE - 1);
+ buf[tl] = '\0';
+
+ qla_trace_put(&vha->hw->srb_trace);
+
+ va_end(va);
+}
+
static inline void
qla_trace_init(struct qla_trace *trc, char *name, u32 num_entries)
{
@@ -4793,6 +4793,11 @@ struct qla_hw_data {
spinlock_t sadb_lock; /* protects list */
struct els_reject elsrej;
u8 edif_post_stop_cnt_down;
+
+#ifdef QLA_TRACING
+ QLA_DFS_DEFINE_DENTRY(srb_trace);
+ struct qla_trace srb_trace;
+#endif /* QLA_TRACING */
};
#define RX_ELS_SIZE (roundup(sizeof(struct enode) + ELS_MAX_PAYLOAD, SMP_CACHE_BYTES))
@@ -5493,6 +5498,12 @@ struct ql_vnd_tgt_stats_resp {
struct ql_vnd_stats stats;
} __packed;
+#define DBG_FCPORT_PRFMT(_fp, _fmt, _args...) \
+ "%s: %8phC: " _fmt " (state=%d disc_state=%d scan_state=%d loopid=0x%x deleted=%d flags=0x%x)\n", \
+ __func__, _fp->port_name, ##_args, atomic_read(&_fp->state), \
+ _fp->disc_state, _fp->scan_state, _fp->loop_id, _fp->deleted, \
+ _fp->flags
+
#include "qla_target.h"
#include "qla_gbl.h"
#include "qla_dbg.h"
@@ -5501,10 +5512,4 @@ struct ql_vnd_tgt_stats_resp {
#define IS_SESSION_DELETED(_fcport) (_fcport->disc_state == DSC_DELETE_PEND || \
_fcport->disc_state == DSC_DELETED)
-#define DBG_FCPORT_PRFMT(_fp, _fmt, _args...) \
- "%s: %8phC: " _fmt " (state=%d disc_state=%d scan_state=%d loopid=0x%x deleted=%d flags=0x%x)\n", \
- __func__, _fp->port_name, ##_args, atomic_read(&_fp->state), \
- _fp->disc_state, _fp->scan_state, _fp->loop_id, _fp->deleted, \
- _fp->flags
-
#endif
@@ -599,12 +599,26 @@ 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);
}
+
+static int
+qla_dfs_srb_trace_show(struct seq_file *s, void *unused)
+{
+ return qla_dfs_trace_show(s, unused);
+}
+
+static ssize_t
+qla_dfs_srb_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 */
/*
@@ -699,6 +713,7 @@ static const struct file_operations qla_dfs_##_name##_ops = { \
#ifdef QLA_TRACING
QLA_DFS_SETUP_RW(message_trace, struct qla_trace *);
+QLA_DFS_SETUP_RW(srb_trace, struct qla_trace *);
#endif /* QLA_TRACING */
static int
@@ -811,6 +826,7 @@ qla2x00_dfs_setup(scsi_qla_host_t *vha)
#ifdef QLA_TRACING
QLA_DFS_ROOT_CREATE_FILE(message_trace, 0600, &qla_message_trace);
+ QLA_DFS_CREATE_FILE(ha, srb_trace, 0600, ha->dfs_dir, &ha->srb_trace);
#endif /* QLA_TRACING */
if (IS_QLA27XX(ha) || IS_QLA83XX(ha) || IS_QLA28XX(ha)) {
@@ -875,6 +891,7 @@ qla2x00_dfs_remove(scsi_qla_host_t *vha)
#ifdef QLA_TRACING
QLA_DFS_ROOT_REMOVE_FILE(message_trace);
+ QLA_DFS_REMOVE_FILE(ha, srb_trace);
#endif /* QLA_TRACING */
if (ha->dfs_dir) {
@@ -201,6 +201,10 @@ qla2xxx_get_qpair_sp(scsi_qla_host_t *vha, struct qla_qpair *qpair,
return NULL;
sp = mempool_alloc(qpair->srb_mempool, flag);
+ /* Avoid trace for calls from qla2x00_get_sp */
+ if (vha->hw->base_qpair != qpair)
+ ql_srb_trace_ext(ql_dbg_io, vha, fcport,
+ "sp=%px", sp);
if (sp)
qla2xxx_init_sp(sp, vha, qpair, fcport);
else
@@ -214,6 +218,10 @@ void qla2xxx_rel_free_warning(srb_t *sp);
static inline void
qla2xxx_rel_qpair_sp(struct qla_qpair *qpair, srb_t *sp)
{
+ /* Avoid trace for calls from qla2x00_get_sp */
+ if (qpair->vha->hw->base_qpair != qpair)
+ ql_srb_trace_ext(ql_dbg_io, sp->vha, sp->fcport,
+ "sp=%px type=%d", sp, sp->type);
sp->qpair = NULL;
sp->done = qla2xxx_rel_done_warning;
sp->free = qla2xxx_rel_free_warning;
@@ -234,6 +242,7 @@ qla2x00_get_sp(scsi_qla_host_t *vha, fc_port_t *fcport, gfp_t flag)
qpair = vha->hw->base_qpair;
sp = qla2xxx_get_qpair_sp(vha, qpair, fcport, flag);
+ ql_srb_trace_ext(ql_dbg_disc, vha, fcport, "sp=%px", sp);
if (!sp)
goto done;
@@ -247,6 +256,9 @@ qla2x00_get_sp(scsi_qla_host_t *vha, fc_port_t *fcport, gfp_t flag)
static inline void
qla2x00_rel_sp(srb_t *sp)
{
+ ql_srb_trace_ext(ql_dbg_disc, sp->vha, sp->fcport,
+ "sp=%px type=%d", sp, sp->type);
+
QLA_VHA_MARK_NOT_BUSY(sp->vha);
qla2xxx_rel_qpair_sp(sp->qpair, sp);
}
@@ -3826,6 +3826,10 @@ qla2x00_start_sp(srb_t *sp)
if (vha->hw->flags.eeh_busy)
return -EIO;
+ ql_srb_trace_ext(ql_dbg_disc, vha, sp->fcport,
+ "caller=%ps sp=%px type=%d",
+ __builtin_return_address(0), sp, sp->type);
+
spin_lock_irqsave(qp->qp_lock_ptr, flags);
pkt = __qla2x00_alloc_iocbs(sp->qpair, sp);
if (!pkt) {
@@ -3197,6 +3197,11 @@ qla2x00_status_entry(scsi_qla_host_t *vha, struct rsp_que *rsp, void *pkt)
}
return;
}
+
+ ql_srb_trace_ext(ql_dbg_io, vha, sp->fcport,
+ "sp=%px handle=0x%x type=%d done=%ps",
+ sp, sp->handle, sp->type, sp->done);
+
qla_put_iocbs(sp->qpair, &sp->iores);
if (sp->cmd_type != TYPE_SRB) {
@@ -119,6 +119,8 @@ MODULE_PARM_DESC(ql2xextended_error_logging,
QLA_MESSAGE_TRACE_DEFINES;
+QLA_SRB_TRACE_DEFINES;
+
int ql2xshiftctondsd = 6;
module_param(ql2xshiftctondsd, int, S_IRUGO);
MODULE_PARM_DESC(ql2xshiftctondsd,
@@ -752,6 +754,10 @@ void qla2x00_sp_compl(srb_t *sp, int res)
struct scsi_cmnd *cmd = GET_CMD_SP(sp);
struct completion *comp = sp->comp;
+ ql_srb_trace_ext(ql_dbg_io, sp->vha, sp->fcport,
+ "sp=%px handle=0x%x cmd=%px res=%x",
+ sp, sp->handle, cmd, res);
+
/* kref: INIT */
kref_put(&sp->cmd_kref, qla2x00_sp_release);
cmd->result = res;
@@ -844,6 +850,10 @@ void qla2xxx_qpair_sp_compl(srb_t *sp, int res)
struct scsi_cmnd *cmd = GET_CMD_SP(sp);
struct completion *comp = sp->comp;
+ ql_srb_trace_ext(ql_dbg_io, sp->vha, sp->fcport,
+ "sp=%px handle=0x%x cmd=%px res=%x",
+ sp, sp->handle, cmd, res);
+
/* ref: INIT */
kref_put(&sp->cmd_kref, qla2x00_sp_release);
cmd->result = res;
@@ -870,6 +880,10 @@ qla2xxx_queuecommand(struct Scsi_Host *host, struct scsi_cmnd *cmd)
goto qc24_fail_command;
}
+ ql_srb_trace_ext(ql_dbg_io, fcport->vha, fcport,
+ "cmd=%px mq=%d remchk=0x%x",
+ cmd, ha->mqenable, fc_remote_port_chkready(rport));
+
if (ha->mqenable) {
uint32_t tag;
uint16_t hwq;
@@ -877,6 +891,10 @@ qla2xxx_queuecommand(struct Scsi_Host *host, struct scsi_cmnd *cmd)
tag = blk_mq_unique_tag(scsi_cmd_to_rq(cmd));
hwq = blk_mq_unique_tag_to_hwq(tag);
+
+ ql_srb_trace_ext(ql_dbg_io, fcport->vha, fcport,
+ "tag=%px hwq=%d", tag, hwq);
+
qpair = ha->queue_pair_map[hwq];
if (qpair)
@@ -1298,6 +1316,10 @@ qla2xxx_eh_abort(struct scsi_cmnd *cmd)
vha->cmd_timeout_cnt++;
+ ql_srb_trace_ext(ql_dbg_io, sp->vha, sp->fcport,
+ "sp=%px cmd=%px fast_fail_sts=0x%x",
+ sp, cmd, fast_fail_status);
+
if ((sp->fcport && sp->fcport->deleted) || !qpair)
return fast_fail_status != SUCCESS ? fast_fail_status : FAILED;
@@ -3528,6 +3550,8 @@ qla2x00_probe_one(struct pci_dev *pdev, const struct pci_device_id *id)
ql_dbg(ql_dbg_init, base_vha, 0x00f2,
"Init done and hba is online.\n");
+ qla_trace_init(&ha->srb_trace, "srb_trace", ql2xnum_srb_trace);
+
if (qla_ini_mode_enabled(base_vha) ||
qla_dual_mode_enabled(base_vha))
scsi_scan_host(host);
@@ -3600,6 +3624,8 @@ qla2x00_probe_one(struct pci_dev *pdev, const struct pci_device_id *id)
rsp = NULL;
probe_hw_failed:
+ qla_trace_uninit(&ha->srb_trace);
+
qla2x00_mem_free(ha);
qla2x00_free_req_que(ha, req);
qla2x00_free_rsp_que(ha, rsp);
@@ -3883,6 +3909,8 @@ qla2x00_remove_one(struct pci_dev *pdev)
qla2x00_delete_all_vps(ha, base_vha);
+ qla_trace_uninit(&ha->srb_trace);
+
qla2x00_dfs_remove(base_vha);
qla84xx_put_chip(base_vha);