Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux

scsi: pm80xx: Fix race condition caused by static variables

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>

authored by

Francisco Gutierrez and committed by
Martin K. Petersen
d6477ee3 e5e11f66

+17 -10
+12 -10
drivers/scsi/pm8001/pm8001_ctl.c
··· 534 534 char *str = buf; 535 535 u32 read_size = 536 536 pm8001_ha->main_cfg_tbl.pm80xx_tbl.event_log_size / 1024; 537 - static u32 start, end, count; 538 537 u32 max_read_times = 32; 539 538 u32 max_count = (read_size * 1024) / (max_read_times * 4); 540 539 u32 *temp = (u32 *)pm8001_ha->memoryMap.region[IOP].virt_ptr; 541 540 542 - if ((count % max_count) == 0) { 543 - start = 0; 544 - end = max_read_times; 545 - count = 0; 541 + mutex_lock(&pm8001_ha->iop_log_lock); 542 + 543 + if ((pm8001_ha->iop_log_count % max_count) == 0) { 544 + pm8001_ha->iop_log_start = 0; 545 + pm8001_ha->iop_log_end = max_read_times; 546 + pm8001_ha->iop_log_count = 0; 546 547 } else { 547 - start = end; 548 - end = end + max_read_times; 548 + pm8001_ha->iop_log_start = pm8001_ha->iop_log_end; 549 + pm8001_ha->iop_log_end = pm8001_ha->iop_log_end + max_read_times; 549 550 } 550 551 551 - for (; start < end; start++) 552 - str += sprintf(str, "%08x ", *(temp+start)); 553 - count++; 552 + for (; pm8001_ha->iop_log_start < pm8001_ha->iop_log_end; pm8001_ha->iop_log_start++) 553 + str += sprintf(str, "%08x ", *(temp+pm8001_ha->iop_log_start)); 554 + pm8001_ha->iop_log_count++; 555 + mutex_unlock(&pm8001_ha->iop_log_lock); 554 556 return str - buf; 555 557 } 556 558 static DEVICE_ATTR(iop_log, S_IRUGO, pm8001_ctl_iop_log_show, NULL);
+1
drivers/scsi/pm8001/pm8001_init.c
··· 552 552 pm8001_ha->id = pm8001_id++; 553 553 pm8001_ha->logging_level = logging_level; 554 554 pm8001_ha->non_fatal_count = 0; 555 + mutex_init(&pm8001_ha->iop_log_lock); 555 556 if (link_rate >= 1 && link_rate <= 15) 556 557 pm8001_ha->link_rate = (link_rate << 8); 557 558 else {
+4
drivers/scsi/pm8001/pm8001_sas.h
··· 547 547 u32 ci_offset; 548 548 u32 pi_offset; 549 549 u32 max_memcnt; 550 + u32 iop_log_start; 551 + u32 iop_log_end; 552 + u32 iop_log_count; 553 + struct mutex iop_log_lock; 550 554 }; 551 555 552 556 struct pm8001_work {