]> 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>
Thu, 13 Mar 2025 11:47:10 +0000 (12:47 +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 b8628bceb3aebd6ca31c720ca334a6692c6947b4..6af873de6dfbf0fd6a51e050bad4d1823881457a 100644 (file)
@@ -3883,6 +3883,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 7d778bf3fd7227bee1b33f075eab0cb8b13f5d04..4e773fa8c1289cbe159c21547347b0607fb5cc39 100644 (file)
@@ -365,26 +365,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);
 
@@ -423,7 +428,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);
@@ -444,11 +449,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
@@ -534,8 +616,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 8ef2de6822de9a5de32099464f60581d2fe62c48..9da1d080298d36f75e0ad6b50a937b74aab87126 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 qla2100_pci_config(struct scsi_qla_host *);
index affb3bc39006ce4983bfafde732fdda383a13941..c68a414a949bd062259790e2a82c6f069dc57e22 100644 (file)
@@ -2280,7 +2280,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;
@@ -3263,25 +3263,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. */
@@ -3291,7 +3290,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,
@@ -3300,6 +3299,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
@@ -3390,9 +3399,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;