aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--drivers/scsi/ipr.c92
-rw-r--r--drivers/scsi/ipr.h1
2 files changed, 93 insertions, 0 deletions
diff --git a/drivers/scsi/ipr.c b/drivers/scsi/ipr.c
index df4e27cd996a..9219953ee949 100644
--- a/drivers/scsi/ipr.c
+++ b/drivers/scsi/ipr.c
@@ -683,6 +683,7 @@ static void ipr_init_ipr_cmnd(struct ipr_cmnd *ipr_cmd,
683 ipr_reinit_ipr_cmnd(ipr_cmd); 683 ipr_reinit_ipr_cmnd(ipr_cmd);
684 ipr_cmd->u.scratch = 0; 684 ipr_cmd->u.scratch = 0;
685 ipr_cmd->sibling = NULL; 685 ipr_cmd->sibling = NULL;
686 ipr_cmd->eh_comp = NULL;
686 ipr_cmd->fast_done = fast_done; 687 ipr_cmd->fast_done = fast_done;
687 init_timer(&ipr_cmd->timer); 688 init_timer(&ipr_cmd->timer);
688} 689}
@@ -848,6 +849,8 @@ static void ipr_scsi_eh_done(struct ipr_cmnd *ipr_cmd)
848 849
849 scsi_dma_unmap(ipr_cmd->scsi_cmd); 850 scsi_dma_unmap(ipr_cmd->scsi_cmd);
850 scsi_cmd->scsi_done(scsi_cmd); 851 scsi_cmd->scsi_done(scsi_cmd);
852 if (ipr_cmd->eh_comp)
853 complete(ipr_cmd->eh_comp);
851 list_add_tail(&ipr_cmd->queue, &ipr_cmd->hrrq->hrrq_free_q); 854 list_add_tail(&ipr_cmd->queue, &ipr_cmd->hrrq->hrrq_free_q);
852} 855}
853 856
@@ -4811,6 +4814,84 @@ static int ipr_slave_alloc(struct scsi_device *sdev)
4811 return rc; 4814 return rc;
4812} 4815}
4813 4816
4817/**
4818 * ipr_match_lun - Match function for specified LUN
4819 * @ipr_cmd: ipr command struct
4820 * @device: device to match (sdev)
4821 *
4822 * Returns:
4823 * 1 if command matches sdev / 0 if command does not match sdev
4824 **/
4825static int ipr_match_lun(struct ipr_cmnd *ipr_cmd, void *device)
4826{
4827 if (ipr_cmd->scsi_cmd && ipr_cmd->scsi_cmd->device == device)
4828 return 1;
4829 return 0;
4830}
4831
4832/**
4833 * ipr_wait_for_ops - Wait for matching commands to complete
4834 * @ipr_cmd: ipr command struct
4835 * @device: device to match (sdev)
4836 * @match: match function to use
4837 *
4838 * Returns:
4839 * SUCCESS / FAILED
4840 **/
4841static int ipr_wait_for_ops(struct ipr_ioa_cfg *ioa_cfg, void *device,
4842 int (*match)(struct ipr_cmnd *, void *))
4843{
4844 struct ipr_cmnd *ipr_cmd;
4845 int wait;
4846 unsigned long flags;
4847 struct ipr_hrr_queue *hrrq;
4848 signed long timeout = IPR_ABORT_TASK_TIMEOUT;
4849 DECLARE_COMPLETION_ONSTACK(comp);
4850
4851 ENTER;
4852 do {
4853 wait = 0;
4854
4855 for_each_hrrq(hrrq, ioa_cfg) {
4856 spin_lock_irqsave(hrrq->lock, flags);
4857 list_for_each_entry(ipr_cmd, &hrrq->hrrq_pending_q, queue) {
4858 if (match(ipr_cmd, device)) {
4859 ipr_cmd->eh_comp = ∁
4860 wait++;
4861 }
4862 }
4863 spin_unlock_irqrestore(hrrq->lock, flags);
4864 }
4865
4866 if (wait) {
4867 timeout = wait_for_completion_timeout(&comp, timeout);
4868
4869 if (!timeout) {
4870 wait = 0;
4871
4872 for_each_hrrq(hrrq, ioa_cfg) {
4873 spin_lock_irqsave(hrrq->lock, flags);
4874 list_for_each_entry(ipr_cmd, &hrrq->hrrq_pending_q, queue) {
4875 if (match(ipr_cmd, device)) {
4876 ipr_cmd->eh_comp = NULL;
4877 wait++;
4878 }
4879 }
4880 spin_unlock_irqrestore(hrrq->lock, flags);
4881 }
4882
4883 if (wait)
4884 dev_err(&ioa_cfg->pdev->dev, "Timed out waiting for aborted commands\n");
4885 LEAVE;
4886 return wait ? FAILED : SUCCESS;
4887 }
4888 }
4889 } while (wait);
4890
4891 LEAVE;
4892 return SUCCESS;
4893}
4894
4814static int ipr_eh_host_reset(struct scsi_cmnd *cmd) 4895static int ipr_eh_host_reset(struct scsi_cmnd *cmd)
4815{ 4896{
4816 struct ipr_ioa_cfg *ioa_cfg; 4897 struct ipr_ioa_cfg *ioa_cfg;
@@ -5030,11 +5111,17 @@ static int __ipr_eh_dev_reset(struct scsi_cmnd *scsi_cmd)
5030static int ipr_eh_dev_reset(struct scsi_cmnd *cmd) 5111static int ipr_eh_dev_reset(struct scsi_cmnd *cmd)
5031{ 5112{
5032 int rc; 5113 int rc;
5114 struct ipr_ioa_cfg *ioa_cfg;
5115
5116 ioa_cfg = (struct ipr_ioa_cfg *) cmd->device->host->hostdata;
5033 5117
5034 spin_lock_irq(cmd->device->host->host_lock); 5118 spin_lock_irq(cmd->device->host->host_lock);
5035 rc = __ipr_eh_dev_reset(cmd); 5119 rc = __ipr_eh_dev_reset(cmd);
5036 spin_unlock_irq(cmd->device->host->host_lock); 5120 spin_unlock_irq(cmd->device->host->host_lock);
5037 5121
5122 if (rc == SUCCESS)
5123 rc = ipr_wait_for_ops(ioa_cfg, cmd->device, ipr_match_lun);
5124
5038 return rc; 5125 return rc;
5039} 5126}
5040 5127
@@ -5234,13 +5321,18 @@ static int ipr_eh_abort(struct scsi_cmnd *scsi_cmd)
5234{ 5321{
5235 unsigned long flags; 5322 unsigned long flags;
5236 int rc; 5323 int rc;
5324 struct ipr_ioa_cfg *ioa_cfg;
5237 5325
5238 ENTER; 5326 ENTER;
5239 5327
5328 ioa_cfg = (struct ipr_ioa_cfg *) scsi_cmd->device->host->hostdata;
5329
5240 spin_lock_irqsave(scsi_cmd->device->host->host_lock, flags); 5330 spin_lock_irqsave(scsi_cmd->device->host->host_lock, flags);
5241 rc = ipr_cancel_op(scsi_cmd); 5331 rc = ipr_cancel_op(scsi_cmd);
5242 spin_unlock_irqrestore(scsi_cmd->device->host->host_lock, flags); 5332 spin_unlock_irqrestore(scsi_cmd->device->host->host_lock, flags);
5243 5333
5334 if (rc == SUCCESS)
5335 rc = ipr_wait_for_ops(ioa_cfg, scsi_cmd->device, ipr_match_lun);
5244 LEAVE; 5336 LEAVE;
5245 return rc; 5337 return rc;
5246} 5338}
diff --git a/drivers/scsi/ipr.h b/drivers/scsi/ipr.h
index b4f3eec51bc9..ec03b42fa2b9 100644
--- a/drivers/scsi/ipr.h
+++ b/drivers/scsi/ipr.h
@@ -1606,6 +1606,7 @@ struct ipr_cmnd {
1606 struct scsi_device *sdev; 1606 struct scsi_device *sdev;
1607 } u; 1607 } u;
1608 1608
1609 struct completion *eh_comp;
1609 struct ipr_hrr_queue *hrrq; 1610 struct ipr_hrr_queue *hrrq;
1610 struct ipr_ioa_cfg *ioa_cfg; 1611 struct ipr_ioa_cfg *ioa_cfg;
1611}; 1612};