Commit 841df27d authored by Quinn Tran's avatar Quinn Tran Committed by Martin K. Petersen
Browse files

scsi: qla2xxx: Move FCE Trace buffer allocation to user control



Currently FCE Tracing is enabled to log additional ELS events. Instead,
user will enable or disable this feature through debugfs.

Modify existing DFS knob to allow user to enable or disable this
feature.

echo [1 | 0] > /sys/kernel/debug/qla2xxx/qla2xxx_??/fce
cat  /sys/kernel/debug/qla2xxx/qla2xxx_??/fce

Cc: stable@vger.kernel.org
Fixes: df613b96 ("[SCSI] qla2xxx: Add Fibre Channel Event (FCE) tracing support.")
Signed-off-by: default avatarQuinn Tran <qutran@marvell.com>
Signed-off-by: default avatarNilesh Javali <njavali@marvell.com>
Link: https://lore.kernel.org/r/20241115130313.46826-4-njavali@marvell.com


Reviewed-by: default avatarHimanshu Madhani <himanshu.madhani@oracle.com>
Signed-off-by: default avatarMartin K. Petersen <martin.petersen@oracle.com>
parent a9a09957
Loading
Loading
Loading
Loading
+2 −0
Original line number Diff line number Diff line
@@ -4098,6 +4098,8 @@ struct qla_hw_data {
		uint32_t	npiv_supported		:1;
		uint32_t	pci_channel_io_perm_failure	:1;
		uint32_t	fce_enabled		:1;
		uint32_t	user_enabled_fce	:1;
		uint32_t	fce_dump_buf_alloced	:1;
		uint32_t	fac_supported		:1;

		uint32_t	chip_reset_done		:1;
+102 −22
Original line number Diff line number Diff line
@@ -409,6 +409,7 @@ qla2x00_dfs_fce_show(struct seq_file *s, void *unused)

	mutex_lock(&ha->fce_mutex);

	if (ha->flags.user_enabled_fce) {
		seq_puts(s, "FCE Trace Buffer\n");
		seq_printf(s, "In Pointer = %llx\n\n", (unsigned long long)ha->fce_wr);
		seq_printf(s, "Base = %llx\n\n", (unsigned long long)ha->fce_dma);
@@ -429,6 +430,10 @@ qla2x00_dfs_fce_show(struct seq_file *s, void *unused)
		}

		seq_puts(s, "\nEnd\n");
	} else {
		seq_puts(s, "FCE Trace is currently not enabled\n");
		seq_puts(s, "\techo [ 1 | 0 ] > fce\n");
	}

	mutex_unlock(&ha->fce_mutex);

@@ -467,7 +472,7 @@ qla2x00_dfs_fce_release(struct inode *inode, struct file *file)
	struct qla_hw_data *ha = vha->hw;
	int rval;

	if (ha->flags.fce_enabled)
	if (ha->flags.fce_enabled || !ha->fce)
		goto out;

	mutex_lock(&ha->fce_mutex);
@@ -488,11 +493,88 @@ qla2x00_dfs_fce_release(struct inode *inode, struct file *file)
	return single_release(inode, file);
}

static ssize_t
qla2x00_dfs_fce_write(struct file *file, const char __user *buffer,
		      size_t count, loff_t *pos)
{
	struct seq_file *s = file->private_data;
	struct scsi_qla_host *vha = s->private;
	struct qla_hw_data *ha = vha->hw;
	char *buf;
	int rc = 0;
	unsigned long enable;

	if (!IS_QLA25XX(ha) && !IS_QLA81XX(ha) && !IS_QLA83XX(ha) &&
	    !IS_QLA27XX(ha) && !IS_QLA28XX(ha)) {
		ql_dbg(ql_dbg_user, vha, 0xd034,
		       "this adapter does not support FCE.");
		return -EINVAL;
	}

	buf = memdup_user_nul(buffer, count);
	if (IS_ERR(buf)) {
		ql_dbg(ql_dbg_user, vha, 0xd037,
		    "fail to copy user buffer.");
		return PTR_ERR(buf);
	}

	enable = kstrtoul(buf, 0, 0);
	rc = count;

	mutex_lock(&ha->fce_mutex);

	if (enable) {
		if (ha->flags.user_enabled_fce) {
			mutex_unlock(&ha->fce_mutex);
			goto out_free;
		}
		ha->flags.user_enabled_fce = 1;
		if (!ha->fce) {
			rc = qla2x00_alloc_fce_trace(vha);
			if (rc) {
				ha->flags.user_enabled_fce = 0;
				mutex_unlock(&ha->fce_mutex);
				goto out_free;
			}

			/* adjust fw dump buffer to take into account of this feature */
			if (!ha->flags.fce_dump_buf_alloced)
				qla2x00_alloc_fw_dump(vha);
		}

		if (!ha->flags.fce_enabled)
			qla_enable_fce_trace(vha);

		ql_dbg(ql_dbg_user, vha, 0xd045, "User enabled FCE .\n");
	} else {
		if (!ha->flags.user_enabled_fce) {
			mutex_unlock(&ha->fce_mutex);
			goto out_free;
		}
		ha->flags.user_enabled_fce = 0;
		if (ha->flags.fce_enabled) {
			qla2x00_disable_fce_trace(vha, NULL, NULL);
			ha->flags.fce_enabled = 0;
		}

		qla2x00_free_fce_trace(ha);
		/* no need to re-adjust fw dump buffer */

		ql_dbg(ql_dbg_user, vha, 0xd04f, "User disabled FCE .\n");
	}

	mutex_unlock(&ha->fce_mutex);
out_free:
	kfree(buf);
	return rc;
}

static const struct file_operations dfs_fce_ops = {
	.open		= qla2x00_dfs_fce_open,
	.read		= seq_read,
	.llseek		= seq_lseek,
	.release	= qla2x00_dfs_fce_release,
	.write		= qla2x00_dfs_fce_write,
};

static int
@@ -626,8 +708,6 @@ qla2x00_dfs_setup(scsi_qla_host_t *vha)
	if (!IS_QLA25XX(ha) && !IS_QLA81XX(ha) && !IS_QLA83XX(ha) &&
	    !IS_QLA27XX(ha) && !IS_QLA28XX(ha))
		goto out;
	if (!ha->fce)
		goto out;

	if (qla2x00_dfs_root)
		goto create_dir;
+3 −0
Original line number Diff line number Diff line
@@ -11,6 +11,9 @@
/*
 * Global Function Prototypes in qla_init.c source file.
 */
int  qla2x00_alloc_fce_trace(scsi_qla_host_t *);
void qla2x00_free_fce_trace(struct qla_hw_data *ha);
void qla_enable_fce_trace(scsi_qla_host_t *);
extern int qla2x00_initialize_adapter(scsi_qla_host_t *);
extern int qla24xx_post_prli_work(struct scsi_qla_host *vha, fc_port_t *fcport);

+19 −9
Original line number Diff line number Diff line
@@ -2681,7 +2681,7 @@ qla83xx_nic_core_fw_load(scsi_qla_host_t *vha)
	return rval;
}

static void qla_enable_fce_trace(scsi_qla_host_t *vha)
void qla_enable_fce_trace(scsi_qla_host_t *vha)
{
	int rval;
	struct qla_hw_data *ha = vha->hw;
@@ -3717,25 +3717,24 @@ qla24xx_chip_diag(scsi_qla_host_t *vha)
	return rval;
}

static void
qla2x00_alloc_fce_trace(scsi_qla_host_t *vha)
int qla2x00_alloc_fce_trace(scsi_qla_host_t *vha)
{
	dma_addr_t tc_dma;
	void *tc;
	struct qla_hw_data *ha = vha->hw;

	if (!IS_FWI2_CAPABLE(ha))
		return;
		return -EINVAL;

	if (!IS_QLA25XX(ha) && !IS_QLA81XX(ha) && !IS_QLA83XX(ha) &&
	    !IS_QLA27XX(ha) && !IS_QLA28XX(ha))
		return;
		return -EINVAL;

	if (ha->fce) {
		ql_dbg(ql_dbg_init, vha, 0x00bd,
		       "%s: FCE Mem is already allocated.\n",
		       __func__);
		return;
		return -EIO;
	}

	/* Allocate memory for Fibre Channel Event Buffer. */
@@ -3745,7 +3744,7 @@ qla2x00_alloc_fce_trace(scsi_qla_host_t *vha)
		ql_log(ql_log_warn, vha, 0x00be,
		       "Unable to allocate (%d KB) for FCE.\n",
		       FCE_SIZE / 1024);
		return;
		return -ENOMEM;
	}

	ql_dbg(ql_dbg_init, vha, 0x00c0,
@@ -3754,6 +3753,16 @@ qla2x00_alloc_fce_trace(scsi_qla_host_t *vha)
	ha->fce_dma = tc_dma;
	ha->fce = tc;
	ha->fce_bufs = FCE_NUM_BUFFERS;
	return 0;
}

void qla2x00_free_fce_trace(struct qla_hw_data *ha)
{
	if (!ha->fce)
		return;
	dma_free_coherent(&ha->pdev->dev, FCE_SIZE, ha->fce, ha->fce_dma);
	ha->fce = NULL;
	ha->fce_dma = 0;
}

static void
@@ -3844,9 +3853,10 @@ qla2x00_alloc_fw_dump(scsi_qla_host_t *vha)
		if (ha->tgt.atio_ring)
			mq_size += ha->tgt.atio_q_length * sizeof(request_t);

		qla2x00_alloc_fce_trace(vha);
		if (ha->fce)
		if (ha->fce) {
			fce_size = sizeof(struct qla2xxx_fce_chain) + FCE_SIZE;
			ha->flags.fce_dump_buf_alloced = 1;
		}
		qla2x00_alloc_eft_trace(vha);
		if (ha->eft)
			eft_size = EFT_SIZE;