Skip to content

Commit b1fa0c7

Browse files
shivasharan-szychao66
authored andcommitted
scsi: megaraid_sas: Block PCI config space access from userspace during OCR
ANBZ: torvalds#721 commit 78409d4 upstream. While an online controller reset(OCR) is in progress, there is short duration where all access to controller's PCI config space from the host needs to be blocked. This is due to a hardware limitation of MegaRAID controllers. With this patch, driver will block all access to controller's config space from userland applications by calling pci_cfg_access_lock() while OCR is in progress and unlocking after controller comes back to ready state. Added helper function which locks the config space before initiating OCR and wait for controller to become READY. Signed-off-by: Shivasharan S <shivasharan.srikanteshwara@broadcom.com> Signed-off-by: Martin K. Petersen <martin.petersen@oracle.com> Signed-off-by: Guixin Liu <kanie@linux.alibaba.com> Reviewed-by: Liu Song <liusong@linux.alibaba.com> Reviewed-by: Xunlei Pang <xlpang@linux.alibaba.com> Link: https://gitee.com/anolis/cloud-kernel/pulls/598
1 parent 2aefe79 commit b1fa0c7

File tree

3 files changed

+74
-10
lines changed

3 files changed

+74
-10
lines changed

drivers/scsi/megaraid/megaraid_sas.h

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2570,4 +2570,7 @@ void megasas_free_fusion_context(struct megasas_instance *instance);
25702570
void megasas_set_dma_settings(struct megasas_instance *instance,
25712571
struct megasas_dcmd_frame *dcmd,
25722572
dma_addr_t dma_addr, u32 dma_len);
2573+
int megasas_adp_reset_wait_for_ready(struct megasas_instance *instance,
2574+
bool do_adp_reset,
2575+
int ocr_context);
25732576
#endif /*LSI_MEGARAID_SAS_H */

drivers/scsi/megaraid/megaraid_sas_base.c

Lines changed: 9 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -5303,13 +5303,15 @@ static int megasas_init_fw(struct megasas_instance *instance)
53035303
}
53045304

53055305
if (megasas_transition_to_ready(instance, 0)) {
5306+
dev_info(&instance->pdev->dev,
5307+
"Failed to transition controller to ready from %s!\n",
5308+
__func__);
53065309
if (instance->adapter_type != MFI_SERIES) {
53075310
status_reg = instance->instancet->read_fw_status_reg(
53085311
instance);
53095312
if (status_reg & MFI_RESET_ADAPTER) {
5310-
instance->instancet->adp_reset
5311-
(instance, instance->reg_set);
5312-
if (megasas_transition_to_ready(instance, 0))
5313+
if (megasas_adp_reset_wait_for_ready
5314+
(instance, true, 0) == FAILED)
53135315
goto fail_ready_state;
53145316
} else {
53155317
goto fail_ready_state;
@@ -5319,16 +5321,17 @@ static int megasas_init_fw(struct megasas_instance *instance)
53195321
instance->instancet->adp_reset
53205322
(instance, instance->reg_set);
53215323
atomic_set(&instance->fw_reset_no_pci_access, 0);
5322-
dev_info(&instance->pdev->dev,
5323-
"FW restarted successfully from %s!\n",
5324-
__func__);
53255324

53265325
/*waiting for about 30 second before retry*/
53275326
ssleep(30);
53285327

53295328
if (megasas_transition_to_ready(instance, 0))
53305329
goto fail_ready_state;
53315330
}
5331+
5332+
dev_info(&instance->pdev->dev,
5333+
"FW restarted successfully from %s!\n",
5334+
__func__);
53325335
}
53335336

53345337
megasas_init_ctrl_params(instance);

drivers/scsi/megaraid/megaraid_sas_fusion.c

Lines changed: 62 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -4506,6 +4506,62 @@ int megasas_check_mpio_paths(struct megasas_instance *instance,
45064506
return retval;
45074507
}
45084508

4509+
/**
4510+
* megasas_adp_reset_wait_for_ready - initiate chip reset and wait for
4511+
* controller to come to ready state
4512+
* @instance - adapter's soft state
4513+
* @do_adp_reset - If true, do a chip reset
4514+
* @ocr_context - If called from OCR context this will
4515+
* be set to 1, else 0
4516+
*
4517+
* This function initates a chip reset followed by a wait for controller to
4518+
* transition to ready state.
4519+
* During this, driver will block all access to PCI config space from userspace
4520+
*/
4521+
int
4522+
megasas_adp_reset_wait_for_ready(struct megasas_instance *instance,
4523+
bool do_adp_reset,
4524+
int ocr_context)
4525+
{
4526+
int ret = FAILED;
4527+
4528+
/*
4529+
* Block access to PCI config space from userspace
4530+
* when diag reset is initiated from driver
4531+
*/
4532+
if (megasas_dbg_lvl & OCR_LOGS)
4533+
dev_info(&instance->pdev->dev,
4534+
"Block access to PCI config space %s %d\n",
4535+
__func__, __LINE__);
4536+
4537+
pci_cfg_access_lock(instance->pdev);
4538+
4539+
if (do_adp_reset) {
4540+
if (instance->instancet->adp_reset
4541+
(instance, instance->reg_set))
4542+
goto out;
4543+
}
4544+
4545+
/* Wait for FW to become ready */
4546+
if (megasas_transition_to_ready(instance, ocr_context)) {
4547+
dev_warn(&instance->pdev->dev,
4548+
"Failed to transition controller to ready for scsi%d.\n",
4549+
instance->host->host_no);
4550+
goto out;
4551+
}
4552+
4553+
ret = SUCCESS;
4554+
out:
4555+
if (megasas_dbg_lvl & OCR_LOGS)
4556+
dev_info(&instance->pdev->dev,
4557+
"Unlock access to PCI config space %s %d\n",
4558+
__func__, __LINE__);
4559+
4560+
pci_cfg_access_unlock(instance->pdev);
4561+
4562+
return ret;
4563+
}
4564+
45094565
/* Core fusion reset function */
45104566
int megasas_reset_fusion(struct Scsi_Host *shost, int reason)
45114567
{
@@ -4646,10 +4702,12 @@ int megasas_reset_fusion(struct Scsi_Host *shost, int reason)
46464702

46474703
/* Now try to reset the chip */
46484704
for (i = 0; i < max_reset_tries; i++) {
4649-
4650-
if (do_adp_reset &&
4651-
instance->instancet->adp_reset
4652-
(instance, instance->reg_set))
4705+
/*
4706+
* Do adp reset and wait for
4707+
* controller to transition to ready
4708+
*/
4709+
if (megasas_adp_reset_wait_for_ready(instance,
4710+
do_adp_reset, 1) == FAILED)
46534711
continue;
46544712

46554713
/* Wait for FW to become ready */

0 commit comments

Comments
 (0)