aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorKashyap, Desai <kashyap.desai@lsi.com>2010-06-17 03:58:55 -0400
committerJames Bottomley <James.Bottomley@suse.de>2010-07-27 13:02:06 -0400
commitd274213a1ae59e8abde8d43e1e3a478fe9f28794 (patch)
treea13dcb559d8a444c862fd57bf0c114dd7425018a
parentab6ce92541ea24c6a92be8498d7d1b26c14ec62d (diff)
[SCSI] mpt2sas: Hold Controller reset when another reset is in progress
Driver should not allow multiple host reset when already host reset is in progress. It is possible that host reset was sent by scsi mid layer while there was already an host reset active, either issued via IOCTL interface or internaly, like a config page timeout. Since there was a host reset active, the driver would return a FAILED response to the scsi mid layer. The solution is make sure pending host resets will wait for the active host reset to complete before returning control back up the call stack. Signed-off-by: Kashyap Desai <kashyap.desai@lsi.com> Signed-off-by: James Bottomley <James.Bottomley@suse.de>
-rw-r--r--drivers/scsi/mpt2sas/mpt2sas_base.c29
-rw-r--r--drivers/scsi/mpt2sas/mpt2sas_base.h4
-rw-r--r--drivers/scsi/mpt2sas/mpt2sas_scsih.c1
3 files changed, 27 insertions, 7 deletions
diff --git a/drivers/scsi/mpt2sas/mpt2sas_base.c b/drivers/scsi/mpt2sas/mpt2sas_base.c
index 0ec1ed389c20..f0c0df4278d7 100644
--- a/drivers/scsi/mpt2sas/mpt2sas_base.c
+++ b/drivers/scsi/mpt2sas/mpt2sas_base.c
@@ -3804,7 +3804,7 @@ _wait_for_commands_to_complete(struct MPT2SAS_ADAPTER *ioc, int sleep_flag)
3804 return; 3804 return;
3805 3805
3806 /* wait for pending commands to complete */ 3806 /* wait for pending commands to complete */
3807 wait_event_timeout(ioc->reset_wq, ioc->pending_io_count == 0, 3 * HZ); 3807 wait_event_timeout(ioc->reset_wq, ioc->pending_io_count == 0, 10 * HZ);
3808} 3808}
3809 3809
3810/** 3810/**
@@ -3828,13 +3828,24 @@ mpt2sas_base_hard_reset_handler(struct MPT2SAS_ADAPTER *ioc, int sleep_flag,
3828 if (mpt2sas_fwfault_debug) 3828 if (mpt2sas_fwfault_debug)
3829 mpt2sas_halt_firmware(ioc); 3829 mpt2sas_halt_firmware(ioc);
3830 3830
3831 spin_lock_irqsave(&ioc->ioc_reset_in_progress_lock, flags); 3831 /* TODO - What we really should be doing is pulling
3832 if (ioc->shost_recovery) { 3832 * out all the code associated with NO_SLEEP; its never used.
3833 spin_unlock_irqrestore(&ioc->ioc_reset_in_progress_lock, flags); 3833 * That is legacy code from mpt fusion driver, ported over.
3834 printk(MPT2SAS_ERR_FMT "%s: busy\n", 3834 * I will leave this BUG_ON here for now till its been resolved.
3835 ioc->name, __func__); 3835 */
3836 return -EBUSY; 3836 BUG_ON(sleep_flag == NO_SLEEP);
3837
3838 /* wait for an active reset in progress to complete */
3839 if (!mutex_trylock(&ioc->reset_in_progress_mutex)) {
3840 do {
3841 ssleep(1);
3842 } while (ioc->shost_recovery == 1);
3843 dtmprintk(ioc, printk(MPT2SAS_DEBUG_FMT "%s: exit\n", ioc->name,
3844 __func__));
3845 return ioc->ioc_reset_in_progress_status;
3837 } 3846 }
3847
3848 spin_lock_irqsave(&ioc->ioc_reset_in_progress_lock, flags);
3838 ioc->shost_recovery = 1; 3849 ioc->shost_recovery = 1;
3839 spin_unlock_irqrestore(&ioc->ioc_reset_in_progress_lock, flags); 3850 spin_unlock_irqrestore(&ioc->ioc_reset_in_progress_lock, flags);
3840 3851
@@ -3853,9 +3864,13 @@ mpt2sas_base_hard_reset_handler(struct MPT2SAS_ADAPTER *ioc, int sleep_flag,
3853 ioc->name, __func__, ((r == 0) ? "SUCCESS" : "FAILED"))); 3864 ioc->name, __func__, ((r == 0) ? "SUCCESS" : "FAILED")));
3854 3865
3855 spin_lock_irqsave(&ioc->ioc_reset_in_progress_lock, flags); 3866 spin_lock_irqsave(&ioc->ioc_reset_in_progress_lock, flags);
3867 ioc->ioc_reset_in_progress_status = r;
3856 ioc->shost_recovery = 0; 3868 ioc->shost_recovery = 0;
3857 complete(&ioc->shost_recovery_done); 3869 complete(&ioc->shost_recovery_done);
3858 spin_unlock_irqrestore(&ioc->ioc_reset_in_progress_lock, flags); 3870 spin_unlock_irqrestore(&ioc->ioc_reset_in_progress_lock, flags);
3871 mutex_unlock(&ioc->reset_in_progress_mutex);
3859 3872
3873 dtmprintk(ioc, printk(MPT2SAS_DEBUG_FMT "%s: exit\n", ioc->name,
3874 __func__));
3860 return r; 3875 return r;
3861} 3876}
diff --git a/drivers/scsi/mpt2sas/mpt2sas_base.h b/drivers/scsi/mpt2sas/mpt2sas_base.h
index 0f41fcd4e52b..6032cbf31c7e 100644
--- a/drivers/scsi/mpt2sas/mpt2sas_base.h
+++ b/drivers/scsi/mpt2sas/mpt2sas_base.h
@@ -600,9 +600,13 @@ struct MPT2SAS_ADAPTER {
600 int aen_event_read_flag; 600 int aen_event_read_flag;
601 u8 broadcast_aen_busy; 601 u8 broadcast_aen_busy;
602 u8 shost_recovery; 602 u8 shost_recovery;
603
604 struct mutex reset_in_progress_mutex;
603 struct completion shost_recovery_done; 605 struct completion shost_recovery_done;
604 spinlock_t ioc_reset_in_progress_lock; 606 spinlock_t ioc_reset_in_progress_lock;
605 u8 ioc_link_reset_in_progress; 607 u8 ioc_link_reset_in_progress;
608 int ioc_reset_in_progress_status;
609
606 u8 ignore_loginfos; 610 u8 ignore_loginfos;
607 u8 remove_host; 611 u8 remove_host;
608 u8 wait_for_port_enable_to_complete; 612 u8 wait_for_port_enable_to_complete;
diff --git a/drivers/scsi/mpt2sas/mpt2sas_scsih.c b/drivers/scsi/mpt2sas/mpt2sas_scsih.c
index 456ea7c3b099..9ce225303938 100644
--- a/drivers/scsi/mpt2sas/mpt2sas_scsih.c
+++ b/drivers/scsi/mpt2sas/mpt2sas_scsih.c
@@ -6557,6 +6557,7 @@ _scsih_probe(struct pci_dev *pdev, const struct pci_device_id *id)
6557 ioc->tm_sas_control_cb_idx = tm_sas_control_cb_idx; 6557 ioc->tm_sas_control_cb_idx = tm_sas_control_cb_idx;
6558 ioc->logging_level = logging_level; 6558 ioc->logging_level = logging_level;
6559 /* misc semaphores and spin locks */ 6559 /* misc semaphores and spin locks */
6560 mutex_init(&ioc->reset_in_progress_mutex);
6560 spin_lock_init(&ioc->ioc_reset_in_progress_lock); 6561 spin_lock_init(&ioc->ioc_reset_in_progress_lock);
6561 spin_lock_init(&ioc->scsi_lookup_lock); 6562 spin_lock_init(&ioc->scsi_lookup_lock);
6562 spin_lock_init(&ioc->sas_device_lock); 6563 spin_lock_init(&ioc->sas_device_lock);