[SCSI] megaraid_sas: Check MFI_REG_STATE.fault.resetAdapter
authoradam radford <aradford@gmail.com>
Thu, 12 May 2011 01:34:08 +0000 (18:34 -0700)
committerJames Bottomley <jbottomley@parallels.com>
Tue, 24 May 2011 16:34:59 +0000 (12:34 -0400)
The following patch for megaraid_sas fixes the function
megasas_reset_fusion() and makes the reset code check
MFI_REG_STATE.fault.resetAdapter.

Signed-off-by: Adam Radford <aradford@gmail.com>
Signed-off-by: James Bottomley <jbottomley@parallels.com>
drivers/scsi/megaraid/megaraid_sas.h
drivers/scsi/megaraid/megaraid_sas_fusion.c

index 046dcc6..982ef83 100644 (file)
@@ -76,8 +76,8 @@
 #define MFI_STATE_READY                                0xB0000000
 #define MFI_STATE_OPERATIONAL                  0xC0000000
 #define MFI_STATE_FAULT                                0xF0000000
-#define  MFI_RESET_REQUIRED                    0x00000001
-
+#define MFI_RESET_REQUIRED                     0x00000001
+#define MFI_RESET_ADAPTER                      0x00000002
 #define MEGAMFI_FRAME_SIZE                     64
 
 /*
index 25dd5ce..de43795 100644 (file)
@@ -2010,17 +2010,11 @@ int megasas_reset_fusion(struct Scsi_Host *shost)
        struct fusion_context *fusion;
        struct megasas_cmd *cmd_mfi;
        union MEGASAS_REQUEST_DESCRIPTOR_UNION *req_desc;
-       u32 host_diag, abs_state;
+       u32 host_diag, abs_state, status_reg, reset_adapter;
 
        instance = (struct megasas_instance *)shost->hostdata;
        fusion = instance->ctrl_context;
 
-       mutex_lock(&instance->reset_mutex);
-       set_bit(MEGASAS_FUSION_IN_RESET, &instance->reset_flags);
-       instance->adprecovery = MEGASAS_ADPRESET_SM_INFAULT;
-       instance->instancet->disable_intr(instance->reg_set);
-       msleep(1000);
-
        if (instance->adprecovery == MEGASAS_HW_CRITICAL_ERROR) {
                printk(KERN_WARNING "megaraid_sas: Hardware critical error, "
                       "returning FAILED.\n");
@@ -2028,6 +2022,12 @@ int megasas_reset_fusion(struct Scsi_Host *shost)
                goto out;
        }
 
+       mutex_lock(&instance->reset_mutex);
+       set_bit(MEGASAS_FUSION_IN_RESET, &instance->reset_flags);
+       instance->adprecovery = MEGASAS_ADPRESET_SM_INFAULT;
+       instance->instancet->disable_intr(instance->reg_set);
+       msleep(1000);
+
        /* First try waiting for commands to complete */
        if (megasas_wait_for_outstanding_fusion(instance)) {
                printk(KERN_WARNING "megaraid_sas: resetting fusion "
@@ -2044,7 +2044,12 @@ int megasas_reset_fusion(struct Scsi_Host *shost)
                        }
                }
 
-               if (instance->disableOnlineCtrlReset == 1) {
+               status_reg = instance->instancet->read_fw_status_reg(
+                       instance->reg_set);
+               abs_state = status_reg & MFI_STATE_MASK;
+               reset_adapter = status_reg & MFI_RESET_ADAPTER;
+               if (instance->disableOnlineCtrlReset ||
+                   (abs_state == MFI_STATE_FAULT && !reset_adapter)) {
                        /* Reset not supported, kill adapter */
                        printk(KERN_WARNING "megaraid_sas: Reset not supported"
                               ", killing adapter.\n");
@@ -2073,6 +2078,7 @@ int megasas_reset_fusion(struct Scsi_Host *shost)
 
                        /* Check that the diag write enable (DRWE) bit is on */
                        host_diag = readl(&instance->reg_set->fusion_host_diag);
+                       retry = 0;
                        while (!(host_diag & HOST_DIAG_WRITE_ENABLE)) {
                                msleep(100);
                                host_diag =
@@ -2110,7 +2116,7 @@ int megasas_reset_fusion(struct Scsi_Host *shost)
 
                        abs_state =
                                instance->instancet->read_fw_status_reg(
-                                       instance->reg_set);
+                                       instance->reg_set) & MFI_STATE_MASK;
                        retry = 0;
 
                        while ((abs_state <= MFI_STATE_FW_INIT) &&
@@ -2118,7 +2124,7 @@ int megasas_reset_fusion(struct Scsi_Host *shost)
                                msleep(100);
                                abs_state =
                                instance->instancet->read_fw_status_reg(
-                                       instance->reg_set);
+                                       instance->reg_set) & MFI_STATE_MASK;
                        }
                        if (abs_state <= MFI_STATE_FW_INIT) {
                                printk(KERN_WARNING "megaraid_sas: firmware "