megaraid_sas: MFI adapter OCR changes
authorSumit Saxena <sumit.saxena@avagotech.com>
Thu, 28 Jan 2016 15:34:33 +0000 (21:04 +0530)
committerMartin K. Petersen <martin.petersen@oracle.com>
Wed, 24 Feb 2016 02:27:02 +0000 (21:27 -0500)
Optimized MFI adapters' OCR path, particularly
megasas_wait_for_outstanding() function.

Signed-off-by: Kashyap Desai <kashyap.desai@avagotech.com>
Signed-off-by: Sumit Saxena <sumit.saxena@avagotech.com>
Reviewed-by: Tomas Henzl <thenzl@redhat.com>
Signed-off-by: Martin K. Petersen <martin.petersen@oracle.com>
drivers/scsi/megaraid/megaraid_sas_base.c

index 1bd5da49b897adf0f39d68e2e478624e18cd24c3..d2ea97769c76d82d01ef917e05a873e9c4ebc19a 100644 (file)
@@ -2455,15 +2455,19 @@ void megasas_sriov_heartbeat_handler(unsigned long instance_addr)
  */
 static int megasas_wait_for_outstanding(struct megasas_instance *instance)
 {
-       int i;
+       int i, sl, outstanding;
        u32 reset_index;
        u32 wait_time = MEGASAS_RESET_WAIT_TIME;
        unsigned long flags;
        struct list_head clist_local;
        struct megasas_cmd *reset_cmd;
        u32 fw_state;
-       u8 kill_adapter_flag;
 
+       if (atomic_read(&instance->adprecovery) == MEGASAS_HW_CRITICAL_ERROR) {
+               dev_info(&instance->pdev->dev, "%s:%d HBA is killed.\n",
+               __func__, __LINE__);
+               return FAILED;
+       }
 
        if (atomic_read(&instance->adprecovery) != MEGASAS_HBA_OPERATIONAL) {
 
@@ -2520,7 +2524,7 @@ static int megasas_wait_for_outstanding(struct megasas_instance *instance)
        }
 
        for (i = 0; i < resetwaittime; i++) {
-               int outstanding = atomic_read(&instance->fw_outstanding);
+               outstanding = atomic_read(&instance->fw_outstanding);
 
                if (!outstanding)
                        break;
@@ -2539,65 +2543,60 @@ static int megasas_wait_for_outstanding(struct megasas_instance *instance)
        }
 
        i = 0;
-       kill_adapter_flag = 0;
+       outstanding = atomic_read(&instance->fw_outstanding);
+       fw_state = instance->instancet->read_fw_status_reg(instance->reg_set) & MFI_STATE_MASK;
+
+       if ((!outstanding && (fw_state == MFI_STATE_OPERATIONAL)))
+               goto no_outstanding;
+
+       if (instance->disableOnlineCtrlReset)
+               goto kill_hba_and_failed;
        do {
-               fw_state = instance->instancet->read_fw_status_reg(
-                                       instance->reg_set) & MFI_STATE_MASK;
-               if ((fw_state == MFI_STATE_FAULT) &&
-                       (instance->disableOnlineCtrlReset == 0)) {
-                       if (i == 3) {
-                               kill_adapter_flag = 2;
-                               break;
-                       }
+               if ((fw_state == MFI_STATE_FAULT) || atomic_read(&instance->fw_outstanding)) {
+                       dev_info(&instance->pdev->dev,
+                               "%s:%d waiting_for_outstanding: before issue OCR. FW state = 0x%x, oustanding 0x%x\n",
+                               __func__, __LINE__, fw_state, atomic_read(&instance->fw_outstanding));
+                       if (i == 3)
+                               goto kill_hba_and_failed;
                        megasas_do_ocr(instance);
-                       kill_adapter_flag = 1;
 
-                       /* wait for 1 secs to let FW finish the pending cmds */
-                       msleep(1000);
+                       if (atomic_read(&instance->adprecovery) == MEGASAS_HW_CRITICAL_ERROR) {
+                               dev_info(&instance->pdev->dev, "%s:%d OCR failed and HBA is killed.\n",
+                               __func__, __LINE__);
+                               return FAILED;
+                       }
+                       dev_info(&instance->pdev->dev, "%s:%d waiting_for_outstanding: after issue OCR.\n",
+                               __func__, __LINE__);
+
+                       for (sl = 0; sl < 10; sl++)
+                               msleep(500);
+
+                       outstanding = atomic_read(&instance->fw_outstanding);
+
+                       fw_state = instance->instancet->read_fw_status_reg(instance->reg_set) & MFI_STATE_MASK;
+                       if ((!outstanding && (fw_state == MFI_STATE_OPERATIONAL)))
+                               goto no_outstanding;
                }
                i++;
        } while (i <= 3);
 
-       if (atomic_read(&instance->fw_outstanding) && !kill_adapter_flag) {
-               if (instance->disableOnlineCtrlReset == 0) {
-                       megasas_do_ocr(instance);
+no_outstanding:
 
-                       /* wait for 5 secs to let FW finish the pending cmds */
-                       for (i = 0; i < wait_time; i++) {
-                               int outstanding =
-                                       atomic_read(&instance->fw_outstanding);
-                               if (!outstanding)
-                                       return SUCCESS;
-                               msleep(1000);
-                       }
-               }
-       }
+       dev_info(&instance->pdev->dev, "%s:%d no more pending commands remain after reset handling.\n",
+               __func__, __LINE__);
+       return SUCCESS;
 
-       if (atomic_read(&instance->fw_outstanding) ||
-                                       (kill_adapter_flag == 2)) {
-               dev_notice(&instance->pdev->dev, "pending cmds after reset\n");
-               /*
-                * Send signal to FW to stop processing any pending cmds.
-                * The controller will be taken offline by the OS now.
-                */
-               if ((instance->pdev->device ==
-                       PCI_DEVICE_ID_LSI_SAS0073SKINNY) ||
-                       (instance->pdev->device ==
-                       PCI_DEVICE_ID_LSI_SAS0071SKINNY)) {
-                       writel(MFI_STOP_ADP,
-                               &instance->reg_set->doorbell);
-               } else {
-                       writel(MFI_STOP_ADP,
-                               &instance->reg_set->inbound_doorbell);
-               }
-               megasas_dump_pending_frames(instance);
-               atomic_set(&instance->adprecovery, MEGASAS_HW_CRITICAL_ERROR);
-               return FAILED;
-       }
+kill_hba_and_failed:
 
-       dev_notice(&instance->pdev->dev, "no pending cmds after reset\n");
+       /* Reset not supported, kill adapter */
+       dev_info(&instance->pdev->dev, "%s:%d killing adapter scsi%d"
+               " disableOnlineCtrlReset %d fw_outstanding %d \n",
+               __func__, __LINE__, instance->host->host_no, instance->disableOnlineCtrlReset,
+               atomic_read(&instance->fw_outstanding));
+       megasas_dump_pending_frames(instance);
+       megaraid_sas_kill_hba(instance);
 
-       return SUCCESS;
+       return FAILED;
 }
 
 /**