diff options
author | Ben Collins <bcollins@ubuntu.com> | 2012-06-11 22:16:36 +0400 |
---|---|---|
committer | James Bottomley <JBottomley@Parallels.com> | 2012-07-20 11:58:43 +0400 |
commit | 361ee9c3f3839d6cbd306b5bd34292e0848ecfdc (patch) | |
tree | cef3a3109cbf2280cc4a03a563fc579a8d968b1e | |
parent | ff08784b41e1ab5da6776411b7a8381fe942f2cc (diff) | |
download | linux-361ee9c3f3839d6cbd306b5bd34292e0848ecfdc.tar.xz |
[SCSI] aacraid: Better handling of in-flight events on thread stop
When an error occured that would shut down the driver, some in-flight
events were getting caught up, deadlocking a CPU or two.
Signed-off-by: Ben Collins <bcollins@ubuntu.com>
Acked-by: Achim Leubner <Achim_Leubner@pmc-sierra.com>
Signed-off-by: James Bottomley <JBottomley@Parallels.com>
-rw-r--r-- | drivers/scsi/aacraid/linit.c | 12 |
1 files changed, 11 insertions, 1 deletions
diff --git a/drivers/scsi/aacraid/linit.c b/drivers/scsi/aacraid/linit.c index fdfc4be9c7c6..2be612b0caa5 100644 --- a/drivers/scsi/aacraid/linit.c +++ b/drivers/scsi/aacraid/linit.c @@ -1089,8 +1089,17 @@ static struct scsi_host_template aac_driver_template = { static void __aac_shutdown(struct aac_dev * aac) { - if (aac->aif_thread) + if (aac->aif_thread) { + int i; + /* Clear out events first */ + for (i = 0; i < (aac->scsi_host_ptr->can_queue + AAC_NUM_MGT_FIB); i++) { + struct fib *fib = &aac->fibs[i]; + if (!(fib->hw_fib_va->header.XferState & cpu_to_le32(NoResponseExpected | Async)) && + (fib->hw_fib_va->header.XferState & cpu_to_le32(ResponseExpected))) + up(&fib->event_wait); + } kthread_stop(aac->thread); + } aac_send_shutdown(aac); aac_adapter_disable_int(aac); free_irq(aac->pdev->irq, aac); @@ -1191,6 +1200,7 @@ static int __devinit aac_probe_one(struct pci_dev *pdev, if (IS_ERR(aac->thread)) { printk(KERN_ERR "aacraid: Unable to create command thread.\n"); error = PTR_ERR(aac->thread); + aac->thread = NULL; goto out_deinit; } |