diff options
author | Darrick J. Wong <djwong@us.ibm.com> | 2006-10-30 18:18:50 -0500 |
---|---|---|
committer | James Bottomley <jejb@mulgrave.il.steeleye.com> | 2006-11-15 13:27:50 -0500 |
commit | 79a5eb609b74e7b3638861c41b98eafa74920a1f (patch) | |
tree | 741a6fc22589b991d05ceaa755cc05577efe08b2 | |
parent | f456393e195e0aa16029985f63cd93b601a0d315 (diff) |
[SCSI] libsas: add sas_abort_task
This patch adds an external function, sas_abort_task, to enable LLDDs
to abort sas_tasks. It also adds a work_struct so that the actual
work of aborting a task can be shifted from tasklet context (in the
LLDD) onto the scsi_host's workqueue.
Signed-off-by: Darrick J. Wong <djwong@us.ibm.com>
Signed-off-by: James Bottomley <James.Bottomley@SteelEye.com>
-rw-r--r-- | drivers/scsi/libsas/sas_scsi_host.c | 60 | ||||
-rw-r--r-- | include/scsi/libsas.h | 4 |
2 files changed, 64 insertions, 0 deletions
diff --git a/drivers/scsi/libsas/sas_scsi_host.c b/drivers/scsi/libsas/sas_scsi_host.c index 6a97b07849b4..c5fd37522728 100644 --- a/drivers/scsi/libsas/sas_scsi_host.c +++ b/drivers/scsi/libsas/sas_scsi_host.c | |||
@@ -33,6 +33,7 @@ | |||
33 | #include <scsi/scsi_transport.h> | 33 | #include <scsi/scsi_transport.h> |
34 | #include <scsi/scsi_transport_sas.h> | 34 | #include <scsi/scsi_transport_sas.h> |
35 | #include "../scsi_sas_internal.h" | 35 | #include "../scsi_sas_internal.h" |
36 | #include "../scsi_transport_api.h" | ||
36 | 37 | ||
37 | #include <linux/err.h> | 38 | #include <linux/err.h> |
38 | #include <linux/blkdev.h> | 39 | #include <linux/blkdev.h> |
@@ -798,6 +799,64 @@ void sas_shutdown_queue(struct sas_ha_struct *sas_ha) | |||
798 | spin_unlock_irqrestore(&core->task_queue_lock, flags); | 799 | spin_unlock_irqrestore(&core->task_queue_lock, flags); |
799 | } | 800 | } |
800 | 801 | ||
802 | static int do_sas_task_abort(struct sas_task *task) | ||
803 | { | ||
804 | struct scsi_cmnd *sc = task->uldd_task; | ||
805 | struct sas_internal *si = | ||
806 | to_sas_internal(task->dev->port->ha->core.shost->transportt); | ||
807 | unsigned long flags; | ||
808 | int res; | ||
809 | |||
810 | spin_lock_irqsave(&task->task_state_lock, flags); | ||
811 | if (task->task_state_flags & SAS_TASK_STATE_ABORTED) { | ||
812 | spin_unlock_irqrestore(&task->task_state_lock, flags); | ||
813 | SAS_DPRINTK("%s: Task %p already aborted.\n", __FUNCTION__, | ||
814 | task); | ||
815 | return 0; | ||
816 | } | ||
817 | |||
818 | task->task_state_flags |= SAS_TASK_INITIATOR_ABORTED; | ||
819 | if (!(task->task_state_flags & SAS_TASK_STATE_DONE)) | ||
820 | task->task_state_flags |= SAS_TASK_STATE_ABORTED; | ||
821 | spin_unlock_irqrestore(&task->task_state_lock, flags); | ||
822 | |||
823 | if (!si->dft->lldd_abort_task) | ||
824 | return -ENODEV; | ||
825 | |||
826 | res = si->dft->lldd_abort_task(task); | ||
827 | if ((task->task_state_flags & SAS_TASK_STATE_DONE) || | ||
828 | (res == TMF_RESP_FUNC_COMPLETE)) | ||
829 | { | ||
830 | /* SMP commands don't have scsi_cmds(?) */ | ||
831 | if (!sc) { | ||
832 | task->task_done(task); | ||
833 | return 0; | ||
834 | } | ||
835 | scsi_req_abort_cmd(sc); | ||
836 | scsi_schedule_eh(sc->device->host); | ||
837 | return 0; | ||
838 | } | ||
839 | |||
840 | spin_lock_irqsave(&task->task_state_lock, flags); | ||
841 | task->task_state_flags &= ~SAS_TASK_INITIATOR_ABORTED; | ||
842 | if (!(task->task_state_flags & SAS_TASK_STATE_DONE)) | ||
843 | task->task_state_flags &= ~SAS_TASK_STATE_ABORTED; | ||
844 | spin_unlock_irqrestore(&task->task_state_lock, flags); | ||
845 | |||
846 | return -EAGAIN; | ||
847 | } | ||
848 | |||
849 | void sas_task_abort(struct sas_task *task) | ||
850 | { | ||
851 | int i; | ||
852 | |||
853 | for (i = 0; i < 5; i++) | ||
854 | if (!do_sas_task_abort(task)) | ||
855 | return; | ||
856 | |||
857 | SAS_DPRINTK("%s: Could not kill task!\n", __FUNCTION__); | ||
858 | } | ||
859 | |||
801 | EXPORT_SYMBOL_GPL(sas_queuecommand); | 860 | EXPORT_SYMBOL_GPL(sas_queuecommand); |
802 | EXPORT_SYMBOL_GPL(sas_target_alloc); | 861 | EXPORT_SYMBOL_GPL(sas_target_alloc); |
803 | EXPORT_SYMBOL_GPL(sas_slave_configure); | 862 | EXPORT_SYMBOL_GPL(sas_slave_configure); |
@@ -805,3 +864,4 @@ EXPORT_SYMBOL_GPL(sas_slave_destroy); | |||
805 | EXPORT_SYMBOL_GPL(sas_change_queue_depth); | 864 | EXPORT_SYMBOL_GPL(sas_change_queue_depth); |
806 | EXPORT_SYMBOL_GPL(sas_change_queue_type); | 865 | EXPORT_SYMBOL_GPL(sas_change_queue_type); |
807 | EXPORT_SYMBOL_GPL(sas_bios_param); | 866 | EXPORT_SYMBOL_GPL(sas_bios_param); |
867 | EXPORT_SYMBOL_GPL(sas_task_abort); | ||
diff --git a/include/scsi/libsas.h b/include/scsi/libsas.h index 7bf2e8b9903c..a1fc20a47c50 100644 --- a/include/scsi/libsas.h +++ b/include/scsi/libsas.h | |||
@@ -528,6 +528,8 @@ struct sas_task { | |||
528 | 528 | ||
529 | void *lldd_task; /* for use by LLDDs */ | 529 | void *lldd_task; /* for use by LLDDs */ |
530 | void *uldd_task; | 530 | void *uldd_task; |
531 | |||
532 | struct work_struct abort_work; | ||
531 | }; | 533 | }; |
532 | 534 | ||
533 | 535 | ||
@@ -627,4 +629,6 @@ void sas_unregister_dev(struct domain_device *); | |||
627 | 629 | ||
628 | void sas_init_dev(struct domain_device *); | 630 | void sas_init_dev(struct domain_device *); |
629 | 631 | ||
632 | void sas_task_abort(struct sas_task *task); | ||
633 | |||
630 | #endif /* _SASLIB_H_ */ | 634 | #endif /* _SASLIB_H_ */ |