aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--drivers/scsi/libsas/sas_scsi_host.c51
-rw-r--r--include/scsi/libsas.h3
2 files changed, 31 insertions, 23 deletions
diff --git a/drivers/scsi/libsas/sas_scsi_host.c b/drivers/scsi/libsas/sas_scsi_host.c
index d0c04ebeb8b0..f867455dd339 100644
--- a/drivers/scsi/libsas/sas_scsi_host.c
+++ b/drivers/scsi/libsas/sas_scsi_host.c
@@ -560,6 +560,7 @@ enum scsi_eh_timer_return sas_scsi_timed_out(struct scsi_cmnd *cmd)
560 } 560 }
561 561
562 spin_lock_irqsave(&task->task_state_lock, flags); 562 spin_lock_irqsave(&task->task_state_lock, flags);
563 BUG_ON(task->task_state_flags & SAS_TASK_STATE_ABORTED);
563 if (task->task_state_flags & SAS_TASK_STATE_DONE) { 564 if (task->task_state_flags & SAS_TASK_STATE_DONE) {
564 spin_unlock_irqrestore(&task->task_state_lock, flags); 565 spin_unlock_irqrestore(&task->task_state_lock, flags);
565 SAS_DPRINTK("command 0x%p, task 0x%p, timed out: EH_HANDLED\n", 566 SAS_DPRINTK("command 0x%p, task 0x%p, timed out: EH_HANDLED\n",
@@ -830,44 +831,42 @@ void sas_shutdown_queue(struct sas_ha_struct *sas_ha)
830 spin_unlock_irqrestore(&core->task_queue_lock, flags); 831 spin_unlock_irqrestore(&core->task_queue_lock, flags);
831} 832}
832 833
833static int do_sas_task_abort(struct sas_task *task) 834/*
835 * Call the LLDD task abort routine directly. This function is intended for
836 * use by upper layers that need to tell the LLDD to abort a task.
837 */
838int __sas_task_abort(struct sas_task *task)
834{ 839{
835 struct scsi_cmnd *sc = task->uldd_task;
836 struct sas_internal *si = 840 struct sas_internal *si =
837 to_sas_internal(task->dev->port->ha->core.shost->transportt); 841 to_sas_internal(task->dev->port->ha->core.shost->transportt);
838 unsigned long flags; 842 unsigned long flags;
839 int res; 843 int res;
840 844
841 spin_lock_irqsave(&task->task_state_lock, flags); 845 spin_lock_irqsave(&task->task_state_lock, flags);
842 if (task->task_state_flags & SAS_TASK_STATE_ABORTED) { 846 if (task->task_state_flags & SAS_TASK_STATE_ABORTED ||
847 task->task_state_flags & SAS_TASK_STATE_DONE) {
843 spin_unlock_irqrestore(&task->task_state_lock, flags); 848 spin_unlock_irqrestore(&task->task_state_lock, flags);
844 SAS_DPRINTK("%s: Task %p already aborted.\n", __FUNCTION__, 849 SAS_DPRINTK("%s: Task %p already finished.\n", __FUNCTION__,
845 task); 850 task);
846 return 0; 851 return 0;
847 } 852 }
848 853 task->task_state_flags |= SAS_TASK_STATE_ABORTED;
849 if (!(task->task_state_flags & SAS_TASK_STATE_DONE))
850 task->task_state_flags |= SAS_TASK_STATE_ABORTED;
851 spin_unlock_irqrestore(&task->task_state_lock, flags); 854 spin_unlock_irqrestore(&task->task_state_lock, flags);
852 855
853 if (!si->dft->lldd_abort_task) 856 if (!si->dft->lldd_abort_task)
854 return -ENODEV; 857 return -ENODEV;
855 858
856 res = si->dft->lldd_abort_task(task); 859 res = si->dft->lldd_abort_task(task);
860
861 spin_lock_irqsave(&task->task_state_lock, flags);
857 if ((task->task_state_flags & SAS_TASK_STATE_DONE) || 862 if ((task->task_state_flags & SAS_TASK_STATE_DONE) ||
858 (res == TMF_RESP_FUNC_COMPLETE)) 863 (res == TMF_RESP_FUNC_COMPLETE))
859 { 864 {
860 /* SMP commands don't have scsi_cmds(?) */ 865 spin_unlock_irqrestore(&task->task_state_lock, flags);
861 if (!sc) { 866 task->task_done(task);
862 task->task_done(task);
863 return 0;
864 }
865 scsi_req_abort_cmd(sc);
866 scsi_schedule_eh(sc->device->host);
867 return 0; 867 return 0;
868 } 868 }
869 869
870 spin_lock_irqsave(&task->task_state_lock, flags);
871 if (!(task->task_state_flags & SAS_TASK_STATE_DONE)) 870 if (!(task->task_state_flags & SAS_TASK_STATE_DONE))
872 task->task_state_flags &= ~SAS_TASK_STATE_ABORTED; 871 task->task_state_flags &= ~SAS_TASK_STATE_ABORTED;
873 spin_unlock_irqrestore(&task->task_state_lock, flags); 872 spin_unlock_irqrestore(&task->task_state_lock, flags);
@@ -875,17 +874,24 @@ static int do_sas_task_abort(struct sas_task *task)
875 return -EAGAIN; 874 return -EAGAIN;
876} 875}
877 876
878void sas_task_abort(struct work_struct *work) 877/*
878 * Tell an upper layer that it needs to initiate an abort for a given task.
879 * This should only ever be called by an LLDD.
880 */
881void sas_task_abort(struct sas_task *task)
879{ 882{
880 struct sas_task *task = 883 struct scsi_cmnd *sc = task->uldd_task;
881 container_of(work, struct sas_task, abort_work);
882 int i;
883 884
884 for (i = 0; i < 5; i++) 885 /* Escape for libsas internal commands */
885 if (!do_sas_task_abort(task)) 886 if (!sc) {
887 if (!del_timer(&task->timer))
886 return; 888 return;
889 task->timer.function(task->timer.data);
890 return;
891 }
887 892
888 SAS_DPRINTK("%s: Could not kill task!\n", __FUNCTION__); 893 scsi_req_abort_cmd(sc);
894 scsi_schedule_eh(sc->device->host);
889} 895}
890 896
891EXPORT_SYMBOL_GPL(sas_queuecommand); 897EXPORT_SYMBOL_GPL(sas_queuecommand);
@@ -895,6 +901,7 @@ EXPORT_SYMBOL_GPL(sas_slave_destroy);
895EXPORT_SYMBOL_GPL(sas_change_queue_depth); 901EXPORT_SYMBOL_GPL(sas_change_queue_depth);
896EXPORT_SYMBOL_GPL(sas_change_queue_type); 902EXPORT_SYMBOL_GPL(sas_change_queue_type);
897EXPORT_SYMBOL_GPL(sas_bios_param); 903EXPORT_SYMBOL_GPL(sas_bios_param);
904EXPORT_SYMBOL_GPL(__sas_task_abort);
898EXPORT_SYMBOL_GPL(sas_task_abort); 905EXPORT_SYMBOL_GPL(sas_task_abort);
899EXPORT_SYMBOL_GPL(sas_phy_reset); 906EXPORT_SYMBOL_GPL(sas_phy_reset);
900EXPORT_SYMBOL_GPL(sas_phy_enable); 907EXPORT_SYMBOL_GPL(sas_phy_enable);
diff --git a/include/scsi/libsas.h b/include/scsi/libsas.h
index 75df71f08ce1..c83426344e8f 100644
--- a/include/scsi/libsas.h
+++ b/include/scsi/libsas.h
@@ -650,6 +650,7 @@ void sas_unregister_dev(struct domain_device *);
650 650
651void sas_init_dev(struct domain_device *); 651void sas_init_dev(struct domain_device *);
652 652
653void sas_task_abort(struct work_struct *); 653void sas_task_abort(struct sas_task *);
654int __sas_task_abort(struct sas_task *);
654 655
655#endif /* _SASLIB_H_ */ 656#endif /* _SASLIB_H_ */