aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorSumit.Saxena@avagotech.com <Sumit.Saxena@avagotech.com>2015-01-05 09:36:18 -0500
committerChristoph Hellwig <hch@lst.de>2015-01-09 09:44:36 -0500
commitc8dd61eff2780c481fcf919c1572e16e397c714e (patch)
tree49397211633101ac487e2b2f4c1a28d01f8322a8
parentc2ced1719a1b903350955a511e1666e6d05a7f5b (diff)
megaraid_sas: complete outstanding IOCTLs before killing adapter
Driver calls megasas_complete_cmd() to call wake_up() for each MFI frame that was issued through the ioctl() interface prior to the kill adapter. This ensures userspace ioctl() system calls issued just before a kill adapter don't get stuck in wait state and IOCTLs are returned to the application. Cc: <stable@vger.kernel.org> Signed-off-by: Sumit Saxena <sumit.saxena@avagotech.com> Signed-off-by: Chaitra Basappa <chaitra.basappa@avagotech.com> Reviewed-by: Martin K. Petersen <martin.petersen@oracle.com> Signed-off-by: Christoph Hellwig <hch@lst.de>
-rw-r--r--drivers/scsi/megaraid/megaraid_sas_base.c65
-rw-r--r--drivers/scsi/megaraid/megaraid_sas_fusion.c4
2 files changed, 54 insertions, 15 deletions
diff --git a/drivers/scsi/megaraid/megaraid_sas_base.c b/drivers/scsi/megaraid/megaraid_sas_base.c
index 9f37ddee4d8c..d4e9c4e1bf58 100644
--- a/drivers/scsi/megaraid/megaraid_sas_base.c
+++ b/drivers/scsi/megaraid/megaraid_sas_base.c
@@ -1692,22 +1692,66 @@ static int megasas_slave_alloc(struct scsi_device *sdev)
1692 return 0; 1692 return 0;
1693} 1693}
1694 1694
1695/*
1696* megasas_complete_outstanding_ioctls - Complete outstanding ioctls after a
1697* kill adapter
1698* @instance: Adapter soft state
1699*
1700*/
1701void megasas_complete_outstanding_ioctls(struct megasas_instance *instance)
1702{
1703 int i;
1704 struct megasas_cmd *cmd_mfi;
1705 struct megasas_cmd_fusion *cmd_fusion;
1706 struct fusion_context *fusion = instance->ctrl_context;
1707
1708 /* Find all outstanding ioctls */
1709 if (fusion) {
1710 for (i = 0; i < instance->max_fw_cmds; i++) {
1711 cmd_fusion = fusion->cmd_list[i];
1712 if (cmd_fusion->sync_cmd_idx != (u32)ULONG_MAX) {
1713 cmd_mfi = instance->cmd_list[cmd_fusion->sync_cmd_idx];
1714 if (cmd_mfi->sync_cmd &&
1715 cmd_mfi->frame->hdr.cmd != MFI_CMD_ABORT)
1716 megasas_complete_cmd(instance,
1717 cmd_mfi, DID_OK);
1718 }
1719 }
1720 } else {
1721 for (i = 0; i < instance->max_fw_cmds; i++) {
1722 cmd_mfi = instance->cmd_list[i];
1723 if (cmd_mfi->sync_cmd && cmd_mfi->frame->hdr.cmd !=
1724 MFI_CMD_ABORT)
1725 megasas_complete_cmd(instance, cmd_mfi, DID_OK);
1726 }
1727 }
1728}
1729
1730
1695void megaraid_sas_kill_hba(struct megasas_instance *instance) 1731void megaraid_sas_kill_hba(struct megasas_instance *instance)
1696{ 1732{
1733 /* Set critical error to block I/O & ioctls in case caller didn't */
1734 instance->adprecovery = MEGASAS_HW_CRITICAL_ERROR;
1735 /* Wait 1 second to ensure IO or ioctls in build have posted */
1736 msleep(1000);
1697 if ((instance->pdev->device == PCI_DEVICE_ID_LSI_SAS0073SKINNY) || 1737 if ((instance->pdev->device == PCI_DEVICE_ID_LSI_SAS0073SKINNY) ||
1698 (instance->pdev->device == PCI_DEVICE_ID_LSI_SAS0071SKINNY) || 1738 (instance->pdev->device == PCI_DEVICE_ID_LSI_SAS0071SKINNY) ||
1699 (instance->pdev->device == PCI_DEVICE_ID_LSI_FUSION) || 1739 (instance->pdev->device == PCI_DEVICE_ID_LSI_FUSION) ||
1700 (instance->pdev->device == PCI_DEVICE_ID_LSI_PLASMA) || 1740 (instance->pdev->device == PCI_DEVICE_ID_LSI_PLASMA) ||
1701 (instance->pdev->device == PCI_DEVICE_ID_LSI_INVADER) || 1741 (instance->pdev->device == PCI_DEVICE_ID_LSI_INVADER) ||
1702 (instance->pdev->device == PCI_DEVICE_ID_LSI_FURY)) { 1742 (instance->pdev->device == PCI_DEVICE_ID_LSI_FURY)) {
1703 writel(MFI_STOP_ADP, &instance->reg_set->doorbell); 1743 writel(MFI_STOP_ADP,
1744 &instance->reg_set->doorbell);
1704 /* Flush */ 1745 /* Flush */
1705 readl(&instance->reg_set->doorbell); 1746 readl(&instance->reg_set->doorbell);
1706 if (instance->mpio && instance->requestorId) 1747 if (instance->mpio && instance->requestorId)
1707 memset(instance->ld_ids, 0xff, MEGASAS_MAX_LD_IDS); 1748 memset(instance->ld_ids, 0xff, MEGASAS_MAX_LD_IDS);
1708 } else { 1749 } else {
1709 writel(MFI_STOP_ADP, &instance->reg_set->inbound_doorbell); 1750 writel(MFI_STOP_ADP,
1751 &instance->reg_set->inbound_doorbell);
1710 } 1752 }
1753 /* Complete outstanding ioctls when adapter is killed */
1754 megasas_complete_outstanding_ioctls(instance);
1711} 1755}
1712 1756
1713 /** 1757 /**
@@ -3031,10 +3075,9 @@ megasas_issue_pending_cmds_again(struct megasas_instance *instance)
3031 "was tried multiple times during reset." 3075 "was tried multiple times during reset."
3032 "Shutting down the HBA\n", 3076 "Shutting down the HBA\n",
3033 cmd, cmd->scmd, cmd->sync_cmd); 3077 cmd, cmd->scmd, cmd->sync_cmd);
3078 instance->instancet->disable_intr(instance);
3079 atomic_set(&instance->fw_reset_no_pci_access, 1);
3034 megaraid_sas_kill_hba(instance); 3080 megaraid_sas_kill_hba(instance);
3035
3036 instance->adprecovery =
3037 MEGASAS_HW_CRITICAL_ERROR;
3038 return; 3081 return;
3039 } 3082 }
3040 } 3083 }
@@ -3168,8 +3211,8 @@ process_fw_state_change_wq(struct work_struct *work)
3168 if (megasas_transition_to_ready(instance, 1)) { 3211 if (megasas_transition_to_ready(instance, 1)) {
3169 printk(KERN_NOTICE "megaraid_sas:adapter not ready\n"); 3212 printk(KERN_NOTICE "megaraid_sas:adapter not ready\n");
3170 3213
3214 atomic_set(&instance->fw_reset_no_pci_access, 1);
3171 megaraid_sas_kill_hba(instance); 3215 megaraid_sas_kill_hba(instance);
3172 instance->adprecovery = MEGASAS_HW_CRITICAL_ERROR;
3173 return ; 3216 return ;
3174 } 3217 }
3175 3218
diff --git a/drivers/scsi/megaraid/megaraid_sas_fusion.c b/drivers/scsi/megaraid/megaraid_sas_fusion.c
index 075c99e987bf..df280b1d263f 100644
--- a/drivers/scsi/megaraid/megaraid_sas_fusion.c
+++ b/drivers/scsi/megaraid/megaraid_sas_fusion.c
@@ -2631,7 +2631,6 @@ int megasas_reset_fusion(struct Scsi_Host *shost, int iotimeout)
2631 instance->host->host_no); 2631 instance->host->host_no);
2632 megaraid_sas_kill_hba(instance); 2632 megaraid_sas_kill_hba(instance);
2633 instance->skip_heartbeat_timer_del = 1; 2633 instance->skip_heartbeat_timer_del = 1;
2634 instance->adprecovery = MEGASAS_HW_CRITICAL_ERROR;
2635 retval = FAILED; 2634 retval = FAILED;
2636 goto out; 2635 goto out;
2637 } 2636 }
@@ -2827,8 +2826,6 @@ int megasas_reset_fusion(struct Scsi_Host *shost, int iotimeout)
2827 dev_info(&instance->pdev->dev, 2826 dev_info(&instance->pdev->dev,
2828 "Failed from %s %d\n", 2827 "Failed from %s %d\n",
2829 __func__, __LINE__); 2828 __func__, __LINE__);
2830 instance->adprecovery =
2831 MEGASAS_HW_CRITICAL_ERROR;
2832 megaraid_sas_kill_hba(instance); 2829 megaraid_sas_kill_hba(instance);
2833 retval = FAILED; 2830 retval = FAILED;
2834 } 2831 }
@@ -2877,7 +2874,6 @@ int megasas_reset_fusion(struct Scsi_Host *shost, int iotimeout)
2877 "adapter scsi%d.\n", instance->host->host_no); 2874 "adapter scsi%d.\n", instance->host->host_no);
2878 megaraid_sas_kill_hba(instance); 2875 megaraid_sas_kill_hba(instance);
2879 instance->skip_heartbeat_timer_del = 1; 2876 instance->skip_heartbeat_timer_del = 1;
2880 instance->adprecovery = MEGASAS_HW_CRITICAL_ERROR;
2881 retval = FAILED; 2877 retval = FAILED;
2882 } else { 2878 } else {
2883 /* For VF: Restart HB timer if we didn't OCR */ 2879 /* For VF: Restart HB timer if we didn't OCR */