From 4624708d731b33391a32f6fe7dbcc1caea0dc061 Mon Sep 17 00:00:00 2001 From: Steve Sistare Date: Fri, 1 Mar 2019 06:46:28 -0800 Subject: [PATCH 1/5] scsi: megaraid_sas: reduce module load time ANBZ: #635 commit 31b6a05f86e690e1818116fd23c3be915cc9d9ed upstream. megaraid_sas takes 1+ seconds to load while waiting for firmware: [2.822603] megaraid_sas 0000:03:00.0: Waiting for FW to come to ready state [3.871003] megaraid_sas 0000:03:00.0: FW now in Ready state This is due to the following loop in megasas_transition_to_ready(), which waits a minimum of 1 second, even though the FW becomes ready in tens of millisecs: /* * The cur_state should not last for more than max_wait secs */ for (i = 0; i < max_wait; i++) { ... msleep(1000); ... dev_info(&instance->pdev->dev, "FW now in Ready state\n"); This is a regression, caused by a change of the msleep granularity from 1 to 1000 due to concern about waiting too long on systems with coarse jiffies. To fix, increase iterations and use msleep(20), which results in: [2.670627] megaraid_sas 0000:03:00.0: Waiting for FW to come to ready state [2.739386] megaraid_sas 0000:03:00.0: FW now in Ready state Fixes: fb2f3e96d80f ("scsi: megaraid_sas: Fix msleep granularity") Signed-off-by: Steve Sistare Acked-by: Sumit Saxena Signed-off-by: Martin K. Petersen Reviewed-by: Xunlei Pang Signed-off-by: Guixin Liu --- drivers/scsi/megaraid/megaraid_sas_base.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/drivers/scsi/megaraid/megaraid_sas_base.c b/drivers/scsi/megaraid/megaraid_sas_base.c index 68666a2e0600..06f1de143a18 100644 --- a/drivers/scsi/megaraid/megaraid_sas_base.c +++ b/drivers/scsi/megaraid/megaraid_sas_base.c @@ -3928,12 +3928,12 @@ megasas_transition_to_ready(struct megasas_instance *instance, int ocr) /* * The cur_state should not last for more than max_wait secs */ - for (i = 0; i < max_wait; i++) { + for (i = 0; i < max_wait * 50; i++) { curr_abs_state = instance->instancet-> read_fw_status_reg(instance); if (abs_state == curr_abs_state) { - msleep(1000); + msleep(20); } else break; } -- Gitee From ec1afb249348e612b445523a518d1b44fb7b8740 Mon Sep 17 00:00:00 2001 From: Anand Lodnoor Date: Tue, 14 Jan 2020 16:51:19 +0530 Subject: [PATCH 2/5] scsi: megaraid_sas: Do not initiate OCR if controller is not in ready state ANBZ: #635 commit 6d7537270e3283b92f9b327da9d58a4de40fe8d0 upstream. Driver initiates OCR if a DCMD command times out. But there is a deadlock if the driver attempts to invoke another OCR before the mutex lock (reset_mutex) is released from the previous session of OCR. This patch takes care of the above scenario using new flag MEGASAS_FUSION_OCR_NOT_POSSIBLE to indicate if OCR is possible. Cc: stable@vger.kernel.org Link: https://lore.kernel.org/r/1579000882-20246-9-git-send-email-anand.lodnoor@broadcom.com Signed-off-by: Shivasharan S Signed-off-by: Anand Lodnoor Signed-off-by: Martin K. Petersen Reviewed-by: Xunlei Pang Signed-off-by: Guixin Liu --- drivers/scsi/megaraid/megaraid_sas_base.c | 3 ++- drivers/scsi/megaraid/megaraid_sas_fusion.c | 3 ++- drivers/scsi/megaraid/megaraid_sas_fusion.h | 1 + 3 files changed, 5 insertions(+), 2 deletions(-) diff --git a/drivers/scsi/megaraid/megaraid_sas_base.c b/drivers/scsi/megaraid/megaraid_sas_base.c index 06f1de143a18..967252e114a4 100644 --- a/drivers/scsi/megaraid/megaraid_sas_base.c +++ b/drivers/scsi/megaraid/megaraid_sas_base.c @@ -4211,7 +4211,8 @@ dcmd_timeout_ocr_possible(struct megasas_instance *instance) { if (instance->adapter_type == MFI_SERIES) return KILL_ADAPTER; else if (instance->unload || - test_bit(MEGASAS_FUSION_IN_RESET, &instance->reset_flags)) + test_bit(MEGASAS_FUSION_OCR_NOT_POSSIBLE, + &instance->reset_flags)) return IGNORE_TIMEOUT; else return INITIATE_OCR; diff --git a/drivers/scsi/megaraid/megaraid_sas_fusion.c b/drivers/scsi/megaraid/megaraid_sas_fusion.c index e3e47765289d..418f6c3f61b1 100644 --- a/drivers/scsi/megaraid/megaraid_sas_fusion.c +++ b/drivers/scsi/megaraid/megaraid_sas_fusion.c @@ -4567,6 +4567,7 @@ int megasas_reset_fusion(struct Scsi_Host *shost, int reason) if (instance->requestorId && !instance->skip_heartbeat_timer_del) del_timer_sync(&instance->sriov_heartbeat_timer); set_bit(MEGASAS_FUSION_IN_RESET, &instance->reset_flags); + set_bit(MEGASAS_FUSION_OCR_NOT_POSSIBLE, &instance->reset_flags); atomic_set(&instance->adprecovery, MEGASAS_ADPRESET_SM_POLLING); instance->instancet->disable_intr(instance); megasas_sync_irqs((unsigned long)instance); @@ -4755,7 +4756,7 @@ int megasas_reset_fusion(struct Scsi_Host *shost, int reason) atomic_set(&instance->adprecovery, MEGASAS_HBA_OPERATIONAL); } out: - clear_bit(MEGASAS_FUSION_IN_RESET, &instance->reset_flags); + clear_bit(MEGASAS_FUSION_OCR_NOT_POSSIBLE, &instance->reset_flags); mutex_unlock(&instance->reset_mutex); return retval; } diff --git a/drivers/scsi/megaraid/megaraid_sas_fusion.h b/drivers/scsi/megaraid/megaraid_sas_fusion.h index 68517cb7342b..90a47aed4f2e 100644 --- a/drivers/scsi/megaraid/megaraid_sas_fusion.h +++ b/drivers/scsi/megaraid/megaraid_sas_fusion.h @@ -102,6 +102,7 @@ enum MR_RAID_FLAGS_IO_SUB_TYPE { #define MEGASAS_FP_CMD_LEN 16 #define MEGASAS_FUSION_IN_RESET 0 +#define MEGASAS_FUSION_OCR_NOT_POSSIBLE 1 #define THRESHOLD_REPLY_COUNT 50 #define RAID_1_PEER_CMDS 2 #define JBOD_MAPS_COUNT 2 -- Gitee From 5f56b489b9d3bab2011ce65cfacc0b0d74de59d3 Mon Sep 17 00:00:00 2001 From: Sumit Saxena Date: Fri, 8 May 2020 14:22:42 +0530 Subject: [PATCH 3/5] scsi: megaraid_sas: TM command refire leads to controller firmware crash ANBZ: #635 commit 6fd8525a70221c26823b1c7e912fb21f218fb0c5 upstream. When TM command times out, driver invokes the controller reset. Post reset, driver re-fires pended TM commands which leads to firmware crash. Post controller reset, return pended TM commands back to OS. Link: https://lore.kernel.org/r/20200508085242.23406-1-chandrakanth.patil@broadcom.com Cc: stable@vger.kernel.org Signed-off-by: Sumit Saxena Signed-off-by: Chandrakanth Patil Signed-off-by: Martin K. Petersen Reviewed-by: Xunlei Pang Signed-off-by: Guixin Liu --- drivers/scsi/megaraid/megaraid_sas_fusion.c | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/drivers/scsi/megaraid/megaraid_sas_fusion.c b/drivers/scsi/megaraid/megaraid_sas_fusion.c index 418f6c3f61b1..da449e735569 100644 --- a/drivers/scsi/megaraid/megaraid_sas_fusion.c +++ b/drivers/scsi/megaraid/megaraid_sas_fusion.c @@ -3948,6 +3948,7 @@ void megasas_refire_mgmt_cmd(struct megasas_instance *instance) struct fusion_context *fusion; struct megasas_cmd *cmd_mfi; union MEGASAS_REQUEST_DESCRIPTOR_UNION *req_desc; + struct MPI2_RAID_SCSI_IO_REQUEST *scsi_io_req; u16 smid; bool refire_cmd = 0; u8 result; @@ -3998,6 +3999,11 @@ void megasas_refire_mgmt_cmd(struct megasas_instance *instance) break; } + scsi_io_req = (struct MPI2_RAID_SCSI_IO_REQUEST *) + cmd_fusion->io_request; + if (scsi_io_req->Function == MPI2_FUNCTION_SCSI_TASK_MGMT) + result = RETURN_CMD; + switch (result) { case REFIRE_CMD: megasas_fire_cmd_fusion(instance, req_desc); @@ -4195,7 +4201,6 @@ megasas_issue_tm(struct megasas_instance *instance, u16 device_handle, if (!timeleft) { dev_err(&instance->pdev->dev, "task mgmt type 0x%x timed out\n", type); - cmd_mfi->flags |= DRV_DCMD_SKIP_REFIRE; mutex_unlock(&instance->reset_mutex); rc = megasas_reset_fusion(instance->host, MFI_IO_TIMEOUT_OCR); mutex_lock(&instance->reset_mutex); -- Gitee From e8aeef165c1da50a791524770e0176002b31e4a1 Mon Sep 17 00:00:00 2001 From: Arnd Bergmann Date: Fri, 30 Oct 2020 17:44:20 +0100 Subject: [PATCH 4/5] scsi: megaraid_sas: Check user-provided offsets ANBZ: #635 commit 381d34e376e3d9d27730fda8a0e870600e6c8196 upstream. It sounds unwise to let user space pass an unchecked 32-bit offset into a kernel structure in an ioctl. This is an unsigned variable, so checking the upper bound for the size of the structure it points into is sufficient to avoid data corruption, but as the pointer might also be unaligned, it has to be written carefully as well. While I stumbled over this problem by reading the code, I did not continue checking the function for further problems like it. Link: https://lore.kernel.org/r/20201030164450.1253641-2-arnd@kernel.org Fixes: c4a3e0a529ab ("[SCSI] MegaRAID SAS RAID: new driver") Cc: # v2.6.15+ Reviewed-by: Christoph Hellwig Signed-off-by: Arnd Bergmann Signed-off-by: Martin K. Petersen Reviewed-by: Xunlei Pang Signed-off-by: Guixin Liu --- drivers/scsi/megaraid/megaraid_sas_base.c | 16 +++++++++++----- 1 file changed, 11 insertions(+), 5 deletions(-) diff --git a/drivers/scsi/megaraid/megaraid_sas_base.c b/drivers/scsi/megaraid/megaraid_sas_base.c index 967252e114a4..015a1b6428f1 100644 --- a/drivers/scsi/megaraid/megaraid_sas_base.c +++ b/drivers/scsi/megaraid/megaraid_sas_base.c @@ -7242,7 +7242,7 @@ megasas_mgmt_fw_ioctl(struct megasas_instance *instance, int error = 0, i; void *sense = NULL; dma_addr_t sense_handle; - unsigned long *sense_ptr; + void *sense_ptr; u32 opcode = 0; memset(kbuff_arr, 0, sizeof(kbuff_arr)); @@ -7359,6 +7359,13 @@ megasas_mgmt_fw_ioctl(struct megasas_instance *instance, } if (ioc->sense_len) { + /* make sure the pointer is part of the frame */ + if (ioc->sense_off > + (sizeof(union megasas_frame) - sizeof(__le64))) { + error = -EINVAL; + goto out; + } + sense = dma_alloc_coherent(&instance->pdev->dev, ioc->sense_len, &sense_handle, GFP_KERNEL); if (!sense) { @@ -7366,12 +7373,11 @@ megasas_mgmt_fw_ioctl(struct megasas_instance *instance, goto out; } - sense_ptr = - (unsigned long *) ((unsigned long)cmd->frame + ioc->sense_off); + sense_ptr = (void *)cmd->frame + ioc->sense_off; if (instance->consistent_mask_64bit) - *sense_ptr = cpu_to_le64(sense_handle); + put_unaligned_le64(sense_handle, sense_ptr); else - *sense_ptr = cpu_to_le32(sense_handle); + put_unaligned_le32(sense_handle, sense_ptr); } /* -- Gitee From 2b78b7cb088cf42e3a3490bf0ec49f2f0980ad8c Mon Sep 17 00:00:00 2001 From: Arnd Bergmann Date: Tue, 5 Jan 2021 00:41:04 +0100 Subject: [PATCH 5/5] scsi: megaraid_sas: Fix MEGASAS_IOC_FIRMWARE regression ANBZ: #635 commit b112036535eda34460677ea883eaecc3a45a435d upstream. Phil Oester reported that a fix for a possible buffer overrun that I sent caused a regression that manifests in this output: Event Message: A PCI parity error was detected on a component at bus 0 device 5 function 0. Severity: Critical Message ID: PCI1308 The original code tried to handle the sense data pointer differently when using 32-bit 64-bit DMA addressing, which would lead to a 32-bit dma_addr_t value of 0x11223344 to get stored 32-bit kernel: 44 33 22 11 ?? ?? ?? ?? 64-bit LE kernel: 44 33 22 11 00 00 00 00 64-bit BE kernel: 00 00 00 00 44 33 22 11 or a 64-bit dma_addr_t value of 0x1122334455667788 to get stored as 32-bit kernel: 88 77 66 55 ?? ?? ?? ?? 64-bit kernel: 88 77 66 55 44 33 22 11 In my patch, I tried to ensure that the same value is used on both 32-bit and 64-bit kernels, and picked what seemed to be the most sensible combination, storing 32-bit addresses in the first four bytes (as 32-bit kernels already did), and 64-bit addresses in eight consecutive bytes (as 64-bit kernels already did), but evidently this was incorrect. Always storing the dma_addr_t pointer as 64-bit little-endian, i.e. initializing the second four bytes to zero in case of 32-bit addressing, apparently solved the problem for Phil, and is consistent with what all 64-bit little-endian machines did before. I also checked in the history that in previous versions of the code, the pointer was always in the first four bytes without padding, and that previous attempts to fix 64-bit user space, big-endian architectures and 64-bit DMA were clearly flawed and seem to have introduced made this worse. Link: https://lore.kernel.org/r/20210104234137.438275-1-arnd@kernel.org Fixes: 381d34e376e3 ("scsi: megaraid_sas: Check user-provided offsets") Fixes: 107a60dd71b5 ("scsi: megaraid_sas: Add support for 64bit consistent DMA") Fixes: 94cd65ddf4d7 ("[SCSI] megaraid_sas: addded support for big endian architecture") Fixes: 7b2519afa1ab ("[SCSI] megaraid_sas: fix 64 bit sense pointer truncation") Reported-by: Phil Oester Tested-by: Phil Oester Signed-off-by: Arnd Bergmann Signed-off-by: Martin K. Petersen Reviewed-by: Xunlei Pang Signed-off-by: Guixin Liu --- drivers/scsi/megaraid/megaraid_sas_base.c | 6 ++---- 1 file changed, 2 insertions(+), 4 deletions(-) diff --git a/drivers/scsi/megaraid/megaraid_sas_base.c b/drivers/scsi/megaraid/megaraid_sas_base.c index 015a1b6428f1..4a370d4dc0af 100644 --- a/drivers/scsi/megaraid/megaraid_sas_base.c +++ b/drivers/scsi/megaraid/megaraid_sas_base.c @@ -7373,11 +7373,9 @@ megasas_mgmt_fw_ioctl(struct megasas_instance *instance, goto out; } + /* always store 64 bits regardless of addressing */ sense_ptr = (void *)cmd->frame + ioc->sense_off; - if (instance->consistent_mask_64bit) - put_unaligned_le64(sense_handle, sense_ptr); - else - put_unaligned_le32(sense_handle, sense_ptr); + put_unaligned_le64(sense_handle, sense_ptr); } /* -- Gitee