]> git.ipfire.org Git - thirdparty/kernel/stable.git/commitdiff
scsi: qla2xxx: Move FCE Trace buffer allocation to user control
authorQuinn Tran <qutran@marvell.com>
Fri, 15 Nov 2024 13:03:09 +0000 (18:33 +0530)
committerGreg Kroah-Hartman <gregkh@linuxfoundation.org>
Fri, 21 Feb 2025 12:49:46 +0000 (13:49 +0100)
commit 841df27d619ee1f5ca6473e15227b39d6136562d upstream.

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: df613b96077c ("[SCSI] qla2xxx: Add Fibre Channel Event (FCE) tracing support.")
Signed-off-by: Quinn Tran <qutran@marvell.com>
Signed-off-by: Nilesh Javali <njavali@marvell.com>
Link: https://lore.kernel.org/r/20241115130313.46826-4-njavali@marvell.com
Reviewed-by: Himanshu Madhani <himanshu.madhani@oracle.com>
Signed-off-by: Martin K. Petersen <martin.petersen@oracle.com>
Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
drivers/scsi/qla2xxx/qla_def.h
drivers/scsi/qla2xxx/qla_dfs.c
drivers/scsi/qla2xxx/qla_gbl.h
drivers/scsi/qla2xxx/qla_init.c

index 8490181424c75ef69e31382b0e586193d4313e71..f8b949eaffcffb14b256cba5c94fbf01e72addcb 100644 (file)
@@ -4043,6 +4043,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;
index 081af4d420a05fe9c96f6df3cabab58462ce0a68..4a82b377928d49bfb0e1ff5096867b4cf9021362 100644 (file)
@@ -409,26 +409,31 @@ qla2x00_dfs_fce_show(struct seq_file *s, void *unused)
 
        mutex_lock(&ha->fce_mutex);
 
-       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);
-       seq_puts(s, "FCE Enable Registers\n");
-       seq_printf(s, "%08x %08x %08x %08x %08x %08x\n",
-           ha->fce_mb[0], ha->fce_mb[2], ha->fce_mb[3], ha->fce_mb[4],
-           ha->fce_mb[5], ha->fce_mb[6]);
-
-       fce = (uint32_t *) ha->fce;
-       fce_start = (unsigned long long) ha->fce_dma;
-       for (cnt = 0; cnt < fce_calc_size(ha->fce_bufs) / 4; cnt++) {
-               if (cnt % 8 == 0)
-                       seq_printf(s, "\n%llx: ",
-                           (unsigned long long)((cnt * 4) + fce_start));
-               else
-                       seq_putc(s, ' ');
-               seq_printf(s, "%08x", *fce++);
-       }
+       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);
+               seq_puts(s, "FCE Enable Registers\n");
+               seq_printf(s, "%08x %08x %08x %08x %08x %08x\n",
+                          ha->fce_mb[0], ha->fce_mb[2], ha->fce_mb[3], ha->fce_mb[4],
+                          ha->fce_mb[5], ha->fce_mb[6]);
+
+               fce = (uint32_t *)ha->fce;
+               fce_start = (unsigned long long)ha->fce_dma;
+               for (cnt = 0; cnt < fce_calc_size(ha->fce_bufs) / 4; cnt++) {
+                       if (cnt % 8 == 0)
+                               seq_printf(s, "\n%llx: ",
+                                          (unsigned long long)((cnt * 4) + fce_start));
+                       else
+                               seq_putc(s, ' ');
+                       seq_printf(s, "%08x", *fce++);
+               }
 
-       seq_puts(s, "\nEnd\n");
+               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 @@ out:
        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
@@ -671,8 +753,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;
index 73cd869caf6093c719cd0e38e434dae39703117a..f991fb81c72b9ddc00cc1eb6fe25b7c5f40e4106 100644 (file)
@@ -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);
 
index a65c60160820917a24e0cdbbf5c9782b165d0c01..682e74196f4b011399bac02e2910f3e129710831 100644 (file)
@@ -2682,7 +2682,7 @@ exit:
        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;
@@ -3718,25 +3718,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. */
@@ -3746,7 +3745,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,
@@ -3755,6 +3754,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
@@ -3845,9 +3854,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;