diff options
-rw-r--r-- | drivers/scsi/libsas/sas_scsi_host.c | 51 | ||||
-rw-r--r-- | include/scsi/libsas.h | 3 |
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 | ||
833 | static 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 | */ | ||
838 | int __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 | ||
878 | void 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 | */ | ||
881 | void 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 | ||
891 | EXPORT_SYMBOL_GPL(sas_queuecommand); | 897 | EXPORT_SYMBOL_GPL(sas_queuecommand); |
@@ -895,6 +901,7 @@ EXPORT_SYMBOL_GPL(sas_slave_destroy); | |||
895 | EXPORT_SYMBOL_GPL(sas_change_queue_depth); | 901 | EXPORT_SYMBOL_GPL(sas_change_queue_depth); |
896 | EXPORT_SYMBOL_GPL(sas_change_queue_type); | 902 | EXPORT_SYMBOL_GPL(sas_change_queue_type); |
897 | EXPORT_SYMBOL_GPL(sas_bios_param); | 903 | EXPORT_SYMBOL_GPL(sas_bios_param); |
904 | EXPORT_SYMBOL_GPL(__sas_task_abort); | ||
898 | EXPORT_SYMBOL_GPL(sas_task_abort); | 905 | EXPORT_SYMBOL_GPL(sas_task_abort); |
899 | EXPORT_SYMBOL_GPL(sas_phy_reset); | 906 | EXPORT_SYMBOL_GPL(sas_phy_reset); |
900 | EXPORT_SYMBOL_GPL(sas_phy_enable); | 907 | EXPORT_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 | ||
651 | void sas_init_dev(struct domain_device *); | 651 | void sas_init_dev(struct domain_device *); |
652 | 652 | ||
653 | void sas_task_abort(struct work_struct *); | 653 | void sas_task_abort(struct sas_task *); |
654 | int __sas_task_abort(struct sas_task *); | ||
654 | 655 | ||
655 | #endif /* _SASLIB_H_ */ | 656 | #endif /* _SASLIB_H_ */ |