scsi: megaraid_sas: Release Mutex lock before OCR in case of DCMD timeout
authorChandrakanth Patil <chandrakanth.patil@broadcom.com>
Tue, 25 Jun 2019 11:04:23 +0000 (16:34 +0530)
committerMartin K. Petersen <martin.petersen@oracle.com>
Thu, 27 Jun 2019 04:07:35 +0000 (00:07 -0400)
Issue: There is possibility of few DCMDs timing out with 'reset_mutex' lock
held. As part of DCMD timeout handling, driver calls function
megasas_reset_fusion which also tries to acquire same lock 'reset_mutex'
and end up with deadlock.

Fix: Upon timeout of DCMDs (which are fired with 'reset_mutex' lock held),
driver will release 'reset_mutex' before calling OCR function and will
acquire lock again after OCR function returns.

Signed-off-by: Sumit Saxena <sumit.saxena@broadcom.com>
Signed-off-by: Chandrakanth Patil <chandrakanth.patil@broadcom.com>
Signed-off-by: Martin K. Petersen <martin.petersen@oracle.com>
drivers/scsi/megaraid/megaraid_sas_base.c

index 7d1cf4eca22d77940a6a93ea78d1bb9162f9d398..54bb48ebfc38e421d0a94cf0301f4ccb474d9026 100644 (file)
@@ -4369,8 +4369,10 @@ megasas_get_pd_info(struct megasas_instance *instance, struct scsi_device *sdev)
                switch (dcmd_timeout_ocr_possible(instance)) {
                case INITIATE_OCR:
                        cmd->flags |= DRV_DCMD_SKIP_REFIRE;
+                       mutex_unlock(&instance->reset_mutex);
                        megasas_reset_fusion(instance->host,
                                MFI_IO_TIMEOUT_OCR);
+                       mutex_lock(&instance->reset_mutex);
                        break;
                case KILL_ADAPTER:
                        megaraid_sas_kill_hba(instance);
@@ -4861,8 +4863,10 @@ megasas_host_device_list_query(struct megasas_instance *instance,
                switch (dcmd_timeout_ocr_possible(instance)) {
                case INITIATE_OCR:
                        cmd->flags |= DRV_DCMD_SKIP_REFIRE;
+                       mutex_unlock(&instance->reset_mutex);
                        megasas_reset_fusion(instance->host,
                                MFI_IO_TIMEOUT_OCR);
+                       mutex_lock(&instance->reset_mutex);
                        break;
                case KILL_ADAPTER:
                        megaraid_sas_kill_hba(instance);
@@ -5010,8 +5014,10 @@ void megasas_get_snapdump_properties(struct megasas_instance *instance)
                switch (dcmd_timeout_ocr_possible(instance)) {
                case INITIATE_OCR:
                        cmd->flags |= DRV_DCMD_SKIP_REFIRE;
+                       mutex_unlock(&instance->reset_mutex);
                        megasas_reset_fusion(instance->host,
                                MFI_IO_TIMEOUT_OCR);
+                       mutex_lock(&instance->reset_mutex);
                        break;
                case KILL_ADAPTER:
                        megaraid_sas_kill_hba(instance);
@@ -5141,8 +5147,10 @@ megasas_get_ctrl_info(struct megasas_instance *instance)
                switch (dcmd_timeout_ocr_possible(instance)) {
                case INITIATE_OCR:
                        cmd->flags |= DRV_DCMD_SKIP_REFIRE;
+                       mutex_unlock(&instance->reset_mutex);
                        megasas_reset_fusion(instance->host,
                                MFI_IO_TIMEOUT_OCR);
+                       mutex_lock(&instance->reset_mutex);
                        break;
                case KILL_ADAPTER:
                        megaraid_sas_kill_hba(instance);
@@ -6398,8 +6406,10 @@ megasas_get_target_prop(struct megasas_instance *instance,
                switch (dcmd_timeout_ocr_possible(instance)) {
                case INITIATE_OCR:
                        cmd->flags |= DRV_DCMD_SKIP_REFIRE;
+                       mutex_unlock(&instance->reset_mutex);
                        megasas_reset_fusion(instance->host,
                                             MFI_IO_TIMEOUT_OCR);
+                       mutex_lock(&instance->reset_mutex);
                        break;
                case KILL_ADAPTER:
                        megaraid_sas_kill_hba(instance);
@@ -7801,10 +7811,13 @@ megasas_mgmt_fw_ioctl(struct megasas_instance *instance,
                opcode = le32_to_cpu(cmd->frame->dcmd.opcode);
 
        if (opcode == MR_DCMD_CTRL_SHUTDOWN) {
+               mutex_lock(&instance->reset_mutex);
                if (megasas_get_ctrl_info(instance) != DCMD_SUCCESS) {
                        megasas_return_cmd(instance, cmd);
+                       mutex_unlock(&instance->reset_mutex);
                        return -1;
                }
+               mutex_unlock(&instance->reset_mutex);
        }
 
        if (opcode == MR_DRIVER_SET_APP_CRASHDUMP_MODE) {