]> Pileus Git - ~andy/linux/blobdiff - drivers/scsi/ipr.c
dm raid: fix flush support
[~andy/linux] / drivers / scsi / ipr.c
index fd860d952b288f3cacf6066253f4d75936e0c53e..b538f0883fd2e2314e76115936b606d38a79bc01 100644 (file)
@@ -4613,11 +4613,13 @@ static int __ipr_eh_host_reset(struct scsi_cmnd * scsi_cmd)
        ENTER;
        ioa_cfg = (struct ipr_ioa_cfg *) scsi_cmd->device->host->hostdata;
 
-       dev_err(&ioa_cfg->pdev->dev,
-               "Adapter being reset as a result of error recovery.\n");
+       if (!ioa_cfg->in_reset_reload) {
+               dev_err(&ioa_cfg->pdev->dev,
+                       "Adapter being reset as a result of error recovery.\n");
 
-       if (WAIT_FOR_DUMP == ioa_cfg->sdt_state)
-               ioa_cfg->sdt_state = GET_DUMP;
+               if (WAIT_FOR_DUMP == ioa_cfg->sdt_state)
+                       ioa_cfg->sdt_state = GET_DUMP;
+       }
 
        rc = ipr_reset_reload(ioa_cfg, IPR_SHUTDOWN_ABBREV);
 
@@ -4907,7 +4909,7 @@ static int ipr_cancel_op(struct scsi_cmnd * scsi_cmd)
        struct ipr_ioa_cfg *ioa_cfg;
        struct ipr_resource_entry *res;
        struct ipr_cmd_pkt *cmd_pkt;
-       u32 ioasc;
+       u32 ioasc, int_reg;
        int op_found = 0;
 
        ENTER;
@@ -4920,7 +4922,17 @@ static int ipr_cancel_op(struct scsi_cmnd * scsi_cmd)
         */
        if (ioa_cfg->in_reset_reload || ioa_cfg->ioa_is_dead)
                return FAILED;
-       if (!res || !ipr_is_gscsi(res))
+       if (!res)
+               return FAILED;
+
+       /*
+        * If we are aborting a timed out op, chances are that the timeout was caused
+        * by a still not detected EEH error. In such cases, reading a register will
+        * trigger the EEH recovery infrastructure.
+        */
+       int_reg = readl(ioa_cfg->regs.sense_interrupt_reg);
+
+       if (!ipr_is_gscsi(res))
                return FAILED;
 
        list_for_each_entry(ipr_cmd, &ioa_cfg->pending_q, queue) {
@@ -7638,8 +7650,12 @@ static int ipr_reset_restore_cfg_space(struct ipr_cmnd *ipr_cmd)
  **/
 static int ipr_reset_bist_done(struct ipr_cmnd *ipr_cmd)
 {
+       struct ipr_ioa_cfg *ioa_cfg = ipr_cmd->ioa_cfg;
+
        ENTER;
-       pci_unblock_user_cfg_access(ipr_cmd->ioa_cfg->pdev);
+       if (ioa_cfg->cfg_locked)
+               pci_cfg_access_unlock(ioa_cfg->pdev);
+       ioa_cfg->cfg_locked = 0;
        ipr_cmd->job_step = ipr_reset_restore_cfg_space;
        LEAVE;
        return IPR_RC_JOB_CONTINUE;
@@ -7660,8 +7676,6 @@ static int ipr_reset_start_bist(struct ipr_cmnd *ipr_cmd)
        int rc = PCIBIOS_SUCCESSFUL;
 
        ENTER;
-       pci_block_user_cfg_access(ioa_cfg->pdev);
-
        if (ioa_cfg->ipr_chip->bist_method == IPR_MMIO)
                writel(IPR_UPROCI_SIS64_START_BIST,
                       ioa_cfg->regs.set_uproc_interrupt_reg32);
@@ -7673,7 +7687,9 @@ static int ipr_reset_start_bist(struct ipr_cmnd *ipr_cmd)
                ipr_reset_start_timer(ipr_cmd, IPR_WAIT_FOR_BIST_TIMEOUT);
                rc = IPR_RC_JOB_RETURN;
        } else {
-               pci_unblock_user_cfg_access(ipr_cmd->ioa_cfg->pdev);
+               if (ioa_cfg->cfg_locked)
+                       pci_cfg_access_unlock(ipr_cmd->ioa_cfg->pdev);
+               ioa_cfg->cfg_locked = 0;
                ipr_cmd->s.ioasa.hdr.ioasc = cpu_to_be32(IPR_IOASC_PCI_ACCESS_ERROR);
                rc = IPR_RC_JOB_CONTINUE;
        }
@@ -7716,7 +7732,6 @@ static int ipr_reset_slot_reset(struct ipr_cmnd *ipr_cmd)
        struct pci_dev *pdev = ioa_cfg->pdev;
 
        ENTER;
-       pci_block_user_cfg_access(pdev);
        pci_set_pcie_reset_state(pdev, pcie_warm_reset);
        ipr_cmd->job_step = ipr_reset_slot_reset_done;
        ipr_reset_start_timer(ipr_cmd, IPR_PCI_RESET_TIMEOUT);
@@ -7724,6 +7739,56 @@ static int ipr_reset_slot_reset(struct ipr_cmnd *ipr_cmd)
        return IPR_RC_JOB_RETURN;
 }
 
+/**
+ * ipr_reset_block_config_access_wait - Wait for permission to block config access
+ * @ipr_cmd:   ipr command struct
+ *
+ * Description: This attempts to block config access to the IOA.
+ *
+ * Return value:
+ *     IPR_RC_JOB_CONTINUE / IPR_RC_JOB_RETURN
+ **/
+static int ipr_reset_block_config_access_wait(struct ipr_cmnd *ipr_cmd)
+{
+       struct ipr_ioa_cfg *ioa_cfg = ipr_cmd->ioa_cfg;
+       int rc = IPR_RC_JOB_CONTINUE;
+
+       if (pci_cfg_access_trylock(ioa_cfg->pdev)) {
+               ioa_cfg->cfg_locked = 1;
+               ipr_cmd->job_step = ioa_cfg->reset;
+       } else {
+               if (ipr_cmd->u.time_left) {
+                       rc = IPR_RC_JOB_RETURN;
+                       ipr_cmd->u.time_left -= IPR_CHECK_FOR_RESET_TIMEOUT;
+                       ipr_reset_start_timer(ipr_cmd,
+                                             IPR_CHECK_FOR_RESET_TIMEOUT);
+               } else {
+                       ipr_cmd->job_step = ioa_cfg->reset;
+                       dev_err(&ioa_cfg->pdev->dev,
+                               "Timed out waiting to lock config access. Resetting anyway.\n");
+               }
+       }
+
+       return rc;
+}
+
+/**
+ * ipr_reset_block_config_access - Block config access to the IOA
+ * @ipr_cmd:   ipr command struct
+ *
+ * Description: This attempts to block config access to the IOA
+ *
+ * Return value:
+ *     IPR_RC_JOB_CONTINUE
+ **/
+static int ipr_reset_block_config_access(struct ipr_cmnd *ipr_cmd)
+{
+       ipr_cmd->ioa_cfg->cfg_locked = 0;
+       ipr_cmd->job_step = ipr_reset_block_config_access_wait;
+       ipr_cmd->u.time_left = IPR_WAIT_FOR_RESET_TIMEOUT;
+       return IPR_RC_JOB_CONTINUE;
+}
+
 /**
  * ipr_reset_allowed - Query whether or not IOA can be reset
  * @ioa_cfg:   ioa config struct
@@ -7763,7 +7828,7 @@ static int ipr_reset_wait_to_start_bist(struct ipr_cmnd *ipr_cmd)
                ipr_cmd->u.time_left -= IPR_CHECK_FOR_RESET_TIMEOUT;
                ipr_reset_start_timer(ipr_cmd, IPR_CHECK_FOR_RESET_TIMEOUT);
        } else {
-               ipr_cmd->job_step = ioa_cfg->reset;
+               ipr_cmd->job_step = ipr_reset_block_config_access;
                rc = IPR_RC_JOB_CONTINUE;
        }
 
@@ -7796,7 +7861,7 @@ static int ipr_reset_alert(struct ipr_cmnd *ipr_cmd)
                writel(IPR_UPROCI_RESET_ALERT, ioa_cfg->regs.set_uproc_interrupt_reg32);
                ipr_cmd->job_step = ipr_reset_wait_to_start_bist;
        } else {
-               ipr_cmd->job_step = ioa_cfg->reset;
+               ipr_cmd->job_step = ipr_reset_block_config_access;
        }
 
        ipr_cmd->u.time_left = IPR_WAIT_FOR_RESET_TIMEOUT;