]> git.ipfire.org Git - thirdparty/kernel/stable.git/commitdiff
scsi: pm80xx: Fix race condition caused by static variables
authorFrancisco Gutierrez <frankramirez@google.com>
Wed, 23 Jul 2025 18:35:43 +0000 (18:35 +0000)
committerGreg Kroah-Hartman <gregkh@linuxfoundation.org>
Thu, 13 Nov 2025 20:34:15 +0000 (15:34 -0500)
[ Upstream commit d6477ee38ccfbeaed885733c13f41d9076e2f94a ]

Eliminate the use of static variables within the log pull implementation
to resolve a race condition and prevent data gaps when pulling logs from
multiple controllers in parallel, ensuring each operation is properly
isolated.

Signed-off-by: Francisco Gutierrez <frankramirez@google.com>
Link: https://lore.kernel.org/r/20250723183543.1443301-1-frankramirez@google.com
Signed-off-by: Martin K. Petersen <martin.petersen@oracle.com>
Signed-off-by: Sasha Levin <sashal@kernel.org>
drivers/scsi/pm8001/pm8001_ctl.c
drivers/scsi/pm8001/pm8001_init.c
drivers/scsi/pm8001/pm8001_sas.h

index 85ff95c6543a57161903dfda1abbd5d4f6a9fc11..0e7497e490f4093d4ba5b31e95a3e92dfbb27ffa 100644 (file)
@@ -534,23 +534,25 @@ static ssize_t pm8001_ctl_iop_log_show(struct device *cdev,
        char *str = buf;
        u32 read_size =
                pm8001_ha->main_cfg_tbl.pm80xx_tbl.event_log_size / 1024;
-       static u32 start, end, count;
        u32 max_read_times = 32;
        u32 max_count = (read_size * 1024) / (max_read_times * 4);
        u32 *temp = (u32 *)pm8001_ha->memoryMap.region[IOP].virt_ptr;
 
-       if ((count % max_count) == 0) {
-               start = 0;
-               end = max_read_times;
-               count = 0;
+       mutex_lock(&pm8001_ha->iop_log_lock);
+
+       if ((pm8001_ha->iop_log_count % max_count) == 0) {
+               pm8001_ha->iop_log_start = 0;
+               pm8001_ha->iop_log_end = max_read_times;
+               pm8001_ha->iop_log_count = 0;
        } else {
-               start = end;
-               end = end + max_read_times;
+               pm8001_ha->iop_log_start = pm8001_ha->iop_log_end;
+               pm8001_ha->iop_log_end = pm8001_ha->iop_log_end + max_read_times;
        }
 
-       for (; start < end; start++)
-               str += sprintf(str, "%08x ", *(temp+start));
-       count++;
+       for (; pm8001_ha->iop_log_start < pm8001_ha->iop_log_end; pm8001_ha->iop_log_start++)
+               str += sprintf(str, "%08x ", *(temp+pm8001_ha->iop_log_start));
+       pm8001_ha->iop_log_count++;
+       mutex_unlock(&pm8001_ha->iop_log_lock);
        return str - buf;
 }
 static DEVICE_ATTR(iop_log, S_IRUGO, pm8001_ctl_iop_log_show, NULL);
index b53b1ae5b74c3039618c65e4620ae744e084b157..5317f82c51fd4945d6f1338fdc36f4f83168f9d5 100644 (file)
@@ -550,6 +550,7 @@ static struct pm8001_hba_info *pm8001_pci_alloc(struct pci_dev *pdev,
        pm8001_ha->id = pm8001_id++;
        pm8001_ha->logging_level = logging_level;
        pm8001_ha->non_fatal_count = 0;
+       mutex_init(&pm8001_ha->iop_log_lock);
        if (link_rate >= 1 && link_rate <= 15)
                pm8001_ha->link_rate = (link_rate << 8);
        else {
index c46470e0cf63b7b18b9572c8d6b4f4ddf489aa2b..efb6dc26bc35b2d7581a99a1f941466faa84acd1 100644 (file)
@@ -537,6 +537,10 @@ struct pm8001_hba_info {
        u32 ci_offset;
        u32 pi_offset;
        u32 max_memcnt;
+       u32 iop_log_start;
+       u32 iop_log_end;
+       u32 iop_log_count;
+       struct mutex iop_log_lock;
 };
 
 struct pm8001_work {