aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/scsi
diff options
context:
space:
mode:
authorBrian King <brking@linux.vnet.ibm.com>2013-01-31 00:45:08 -0500
committerJames Bottomley <JBottomley@Parallels.com>2013-02-24 03:24:48 -0500
commitbfae7820b87c61c5065338b55405b304d9890085 (patch)
tree91a44896815ff906ed424c2fcbd5dd15ac87f86f /drivers/scsi
parent4d7007b49d523d8f954ae047118d82c130f673ce (diff)
[SCSI] ipr: Fix oops while resetting an ipr adapter
When resetting an ipr adapter, we use scsi_block_requests to block any new commands from scsi core, and then unblock after the reset. When hotplug removing an adapter, we shut it down and go through this same code, but we've seen issues with scsi_unblock_requests running after the adapter's memory has been freed. There is really no need to block/unblock when the adapter is being removed, so this patch skips the block/unblock and will immediately fail any commands that happen to make it to queuecommand while the adapter is being shutdown. Signed-off-by: Brian King <brking@linux.vnet.ibm.com> Signed-off-by: Wen Xiong <wenxiong@linux.vnet.ibm.com> Signed-off-by: James Bottomley <JBottomley@Parallels.com>
Diffstat (limited to 'drivers/scsi')
-rw-r--r--drivers/scsi/ipr.c33
-rw-r--r--drivers/scsi/ipr.h1
2 files changed, 24 insertions, 10 deletions
diff --git a/drivers/scsi/ipr.c b/drivers/scsi/ipr.c
index 8fa79b83f2d3..f328089a1060 100644
--- a/drivers/scsi/ipr.c
+++ b/drivers/scsi/ipr.c
@@ -6112,7 +6112,7 @@ static int ipr_queuecommand(struct Scsi_Host *shost,
6112 * We have told the host to stop giving us new requests, but 6112 * We have told the host to stop giving us new requests, but
6113 * ERP ops don't count. FIXME 6113 * ERP ops don't count. FIXME
6114 */ 6114 */
6115 if (unlikely(!hrrq->allow_cmds && !hrrq->ioa_is_dead)) { 6115 if (unlikely(!hrrq->allow_cmds && !hrrq->ioa_is_dead && !hrrq->removing_ioa)) {
6116 spin_unlock_irqrestore(hrrq->lock, hrrq_flags); 6116 spin_unlock_irqrestore(hrrq->lock, hrrq_flags);
6117 return SCSI_MLQUEUE_HOST_BUSY; 6117 return SCSI_MLQUEUE_HOST_BUSY;
6118 } 6118 }
@@ -6121,7 +6121,7 @@ static int ipr_queuecommand(struct Scsi_Host *shost,
6121 * FIXME - Create scsi_set_host_offline interface 6121 * FIXME - Create scsi_set_host_offline interface
6122 * and the ioa_is_dead check can be removed 6122 * and the ioa_is_dead check can be removed
6123 */ 6123 */
6124 if (unlikely(hrrq->ioa_is_dead || !res)) { 6124 if (unlikely(hrrq->ioa_is_dead || hrrq->removing_ioa || !res)) {
6125 spin_unlock_irqrestore(hrrq->lock, hrrq_flags); 6125 spin_unlock_irqrestore(hrrq->lock, hrrq_flags);
6126 goto err_nodev; 6126 goto err_nodev;
6127 } 6127 }
@@ -6741,14 +6741,17 @@ static int ipr_ioa_bringdown_done(struct ipr_cmnd *ipr_cmd)
6741 struct ipr_ioa_cfg *ioa_cfg = ipr_cmd->ioa_cfg; 6741 struct ipr_ioa_cfg *ioa_cfg = ipr_cmd->ioa_cfg;
6742 6742
6743 ENTER; 6743 ENTER;
6744 if (!ioa_cfg->hrrq[IPR_INIT_HRRQ].removing_ioa) {
6745 ipr_trace;
6746 spin_unlock_irq(ioa_cfg->host->host_lock);
6747 scsi_unblock_requests(ioa_cfg->host);
6748 spin_lock_irq(ioa_cfg->host->host_lock);
6749 }
6750
6744 ioa_cfg->in_reset_reload = 0; 6751 ioa_cfg->in_reset_reload = 0;
6745 ioa_cfg->reset_retries = 0; 6752 ioa_cfg->reset_retries = 0;
6746 list_add_tail(&ipr_cmd->queue, &ipr_cmd->hrrq->hrrq_free_q); 6753 list_add_tail(&ipr_cmd->queue, &ipr_cmd->hrrq->hrrq_free_q);
6747 wake_up_all(&ioa_cfg->reset_wait_q); 6754 wake_up_all(&ioa_cfg->reset_wait_q);
6748
6749 spin_unlock_irq(ioa_cfg->host->host_lock);
6750 scsi_unblock_requests(ioa_cfg->host);
6751 spin_lock_irq(ioa_cfg->host->host_lock);
6752 LEAVE; 6755 LEAVE;
6753 6756
6754 return IPR_RC_JOB_RETURN; 6757 return IPR_RC_JOB_RETURN;
@@ -8494,7 +8497,8 @@ static void _ipr_initiate_ioa_reset(struct ipr_ioa_cfg *ioa_cfg,
8494 spin_unlock(&ioa_cfg->hrrq[i]._lock); 8497 spin_unlock(&ioa_cfg->hrrq[i]._lock);
8495 } 8498 }
8496 wmb(); 8499 wmb();
8497 scsi_block_requests(ioa_cfg->host); 8500 if (!ioa_cfg->hrrq[IPR_INIT_HRRQ].removing_ioa)
8501 scsi_block_requests(ioa_cfg->host);
8498 8502
8499 ipr_cmd = ipr_get_free_ipr_cmnd(ioa_cfg); 8503 ipr_cmd = ipr_get_free_ipr_cmnd(ioa_cfg);
8500 ioa_cfg->reset_cmd = ipr_cmd; 8504 ioa_cfg->reset_cmd = ipr_cmd;
@@ -8549,9 +8553,11 @@ static void ipr_initiate_ioa_reset(struct ipr_ioa_cfg *ioa_cfg,
8549 ipr_fail_all_ops(ioa_cfg); 8553 ipr_fail_all_ops(ioa_cfg);
8550 wake_up_all(&ioa_cfg->reset_wait_q); 8554 wake_up_all(&ioa_cfg->reset_wait_q);
8551 8555
8552 spin_unlock_irq(ioa_cfg->host->host_lock); 8556 if (!ioa_cfg->hrrq[IPR_INIT_HRRQ].removing_ioa) {
8553 scsi_unblock_requests(ioa_cfg->host); 8557 spin_unlock_irq(ioa_cfg->host->host_lock);
8554 spin_lock_irq(ioa_cfg->host->host_lock); 8558 scsi_unblock_requests(ioa_cfg->host);
8559 spin_lock_irq(ioa_cfg->host->host_lock);
8560 }
8555 return; 8561 return;
8556 } else { 8562 } else {
8557 ioa_cfg->in_ioa_bringdown = 1; 8563 ioa_cfg->in_ioa_bringdown = 1;
@@ -9695,6 +9701,7 @@ static void __ipr_remove(struct pci_dev *pdev)
9695{ 9701{
9696 unsigned long host_lock_flags = 0; 9702 unsigned long host_lock_flags = 0;
9697 struct ipr_ioa_cfg *ioa_cfg = pci_get_drvdata(pdev); 9703 struct ipr_ioa_cfg *ioa_cfg = pci_get_drvdata(pdev);
9704 int i;
9698 ENTER; 9705 ENTER;
9699 9706
9700 spin_lock_irqsave(ioa_cfg->host->host_lock, host_lock_flags); 9707 spin_lock_irqsave(ioa_cfg->host->host_lock, host_lock_flags);
@@ -9704,6 +9711,12 @@ static void __ipr_remove(struct pci_dev *pdev)
9704 spin_lock_irqsave(ioa_cfg->host->host_lock, host_lock_flags); 9711 spin_lock_irqsave(ioa_cfg->host->host_lock, host_lock_flags);
9705 } 9712 }
9706 9713
9714 for (i = 0; i < ioa_cfg->hrrq_num; i++) {
9715 spin_lock(&ioa_cfg->hrrq[i]._lock);
9716 ioa_cfg->hrrq[i].removing_ioa = 1;
9717 spin_unlock(&ioa_cfg->hrrq[i]._lock);
9718 }
9719 wmb();
9707 ipr_initiate_ioa_bringdown(ioa_cfg, IPR_SHUTDOWN_NORMAL); 9720 ipr_initiate_ioa_bringdown(ioa_cfg, IPR_SHUTDOWN_NORMAL);
9708 9721
9709 spin_unlock_irqrestore(ioa_cfg->host->host_lock, host_lock_flags); 9722 spin_unlock_irqrestore(ioa_cfg->host->host_lock, host_lock_flags);
diff --git a/drivers/scsi/ipr.h b/drivers/scsi/ipr.h
index 1a9a246932ae..21a6ff1ed5c6 100644
--- a/drivers/scsi/ipr.h
+++ b/drivers/scsi/ipr.h
@@ -493,6 +493,7 @@ struct ipr_hrr_queue {
493 u8 allow_interrupts:1; 493 u8 allow_interrupts:1;
494 u8 ioa_is_dead:1; 494 u8 ioa_is_dead:1;
495 u8 allow_cmds:1; 495 u8 allow_cmds:1;
496 u8 removing_ioa:1;
496 497
497 struct blk_iopoll iopoll; 498 struct blk_iopoll iopoll;
498}; 499};