Commit d274213a authored by Kashyap, Desai's avatar Kashyap, Desai Committed by James Bottomley

[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: default avatarKashyap Desai <kashyap.desai@lsi.com>
Signed-off-by: default avatarJames Bottomley <James.Bottomley@suse.de>
parent ab6ce925
...@@ -3804,7 +3804,7 @@ _wait_for_commands_to_complete(struct MPT2SAS_ADAPTER *ioc, int sleep_flag) ...@@ -3804,7 +3804,7 @@ _wait_for_commands_to_complete(struct MPT2SAS_ADAPTER *ioc, int sleep_flag)
return; return;
/* wait for pending commands to complete */ /* wait for pending commands to complete */
wait_event_timeout(ioc->reset_wq, ioc->pending_io_count == 0, 3 * HZ); wait_event_timeout(ioc->reset_wq, ioc->pending_io_count == 0, 10 * HZ);
} }
/** /**
...@@ -3828,13 +3828,24 @@ mpt2sas_base_hard_reset_handler(struct MPT2SAS_ADAPTER *ioc, int sleep_flag, ...@@ -3828,13 +3828,24 @@ mpt2sas_base_hard_reset_handler(struct MPT2SAS_ADAPTER *ioc, int sleep_flag,
if (mpt2sas_fwfault_debug) if (mpt2sas_fwfault_debug)
mpt2sas_halt_firmware(ioc); mpt2sas_halt_firmware(ioc);
spin_lock_irqsave(&ioc->ioc_reset_in_progress_lock, flags); /* TODO - What we really should be doing is pulling
if (ioc->shost_recovery) { * out all the code associated with NO_SLEEP; its never used.
spin_unlock_irqrestore(&ioc->ioc_reset_in_progress_lock, flags); * That is legacy code from mpt fusion driver, ported over.
printk(MPT2SAS_ERR_FMT "%s: busy\n", * I will leave this BUG_ON here for now till its been resolved.
ioc->name, __func__); */
return -EBUSY; BUG_ON(sleep_flag == NO_SLEEP);
/* wait for an active reset in progress to complete */
if (!mutex_trylock(&ioc->reset_in_progress_mutex)) {
do {
ssleep(1);
} while (ioc->shost_recovery == 1);
dtmprintk(ioc, printk(MPT2SAS_DEBUG_FMT "%s: exit\n", ioc->name,
__func__));
return ioc->ioc_reset_in_progress_status;
} }
spin_lock_irqsave(&ioc->ioc_reset_in_progress_lock, flags);
ioc->shost_recovery = 1; ioc->shost_recovery = 1;
spin_unlock_irqrestore(&ioc->ioc_reset_in_progress_lock, flags); spin_unlock_irqrestore(&ioc->ioc_reset_in_progress_lock, flags);
...@@ -3853,9 +3864,13 @@ mpt2sas_base_hard_reset_handler(struct MPT2SAS_ADAPTER *ioc, int sleep_flag, ...@@ -3853,9 +3864,13 @@ mpt2sas_base_hard_reset_handler(struct MPT2SAS_ADAPTER *ioc, int sleep_flag,
ioc->name, __func__, ((r == 0) ? "SUCCESS" : "FAILED"))); ioc->name, __func__, ((r == 0) ? "SUCCESS" : "FAILED")));
spin_lock_irqsave(&ioc->ioc_reset_in_progress_lock, flags); spin_lock_irqsave(&ioc->ioc_reset_in_progress_lock, flags);
ioc->ioc_reset_in_progress_status = r;
ioc->shost_recovery = 0; ioc->shost_recovery = 0;
complete(&ioc->shost_recovery_done); complete(&ioc->shost_recovery_done);
spin_unlock_irqrestore(&ioc->ioc_reset_in_progress_lock, flags); spin_unlock_irqrestore(&ioc->ioc_reset_in_progress_lock, flags);
mutex_unlock(&ioc->reset_in_progress_mutex);
dtmprintk(ioc, printk(MPT2SAS_DEBUG_FMT "%s: exit\n", ioc->name,
__func__));
return r; return r;
} }
...@@ -600,9 +600,13 @@ struct MPT2SAS_ADAPTER { ...@@ -600,9 +600,13 @@ struct MPT2SAS_ADAPTER {
int aen_event_read_flag; int aen_event_read_flag;
u8 broadcast_aen_busy; u8 broadcast_aen_busy;
u8 shost_recovery; u8 shost_recovery;
struct mutex reset_in_progress_mutex;
struct completion shost_recovery_done; struct completion shost_recovery_done;
spinlock_t ioc_reset_in_progress_lock; spinlock_t ioc_reset_in_progress_lock;
u8 ioc_link_reset_in_progress; u8 ioc_link_reset_in_progress;
int ioc_reset_in_progress_status;
u8 ignore_loginfos; u8 ignore_loginfos;
u8 remove_host; u8 remove_host;
u8 wait_for_port_enable_to_complete; u8 wait_for_port_enable_to_complete;
......
...@@ -6557,6 +6557,7 @@ _scsih_probe(struct pci_dev *pdev, const struct pci_device_id *id) ...@@ -6557,6 +6557,7 @@ _scsih_probe(struct pci_dev *pdev, const struct pci_device_id *id)
ioc->tm_sas_control_cb_idx = tm_sas_control_cb_idx; ioc->tm_sas_control_cb_idx = tm_sas_control_cb_idx;
ioc->logging_level = logging_level; ioc->logging_level = logging_level;
/* misc semaphores and spin locks */ /* misc semaphores and spin locks */
mutex_init(&ioc->reset_in_progress_mutex);
spin_lock_init(&ioc->ioc_reset_in_progress_lock); spin_lock_init(&ioc->ioc_reset_in_progress_lock);
spin_lock_init(&ioc->scsi_lookup_lock); spin_lock_init(&ioc->scsi_lookup_lock);
spin_lock_init(&ioc->sas_device_lock); spin_lock_init(&ioc->sas_device_lock);
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment