aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/scsi/libsas
diff options
context:
space:
mode:
authorDarrick J. Wong <djwong@us.ibm.com>2006-10-30 18:18:50 -0500
committerJames Bottomley <jejb@mulgrave.il.steeleye.com>2006-11-15 13:27:50 -0500
commit79a5eb609b74e7b3638861c41b98eafa74920a1f (patch)
tree741a6fc22589b991d05ceaa755cc05577efe08b2 /drivers/scsi/libsas
parentf456393e195e0aa16029985f63cd93b601a0d315 (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>
Diffstat (limited to 'drivers/scsi/libsas')
-rw-r--r--drivers/scsi/libsas/sas_scsi_host.c60
1 files changed, 60 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
802static 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
849void 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
801EXPORT_SYMBOL_GPL(sas_queuecommand); 860EXPORT_SYMBOL_GPL(sas_queuecommand);
802EXPORT_SYMBOL_GPL(sas_target_alloc); 861EXPORT_SYMBOL_GPL(sas_target_alloc);
803EXPORT_SYMBOL_GPL(sas_slave_configure); 862EXPORT_SYMBOL_GPL(sas_slave_configure);
@@ -805,3 +864,4 @@ EXPORT_SYMBOL_GPL(sas_slave_destroy);
805EXPORT_SYMBOL_GPL(sas_change_queue_depth); 864EXPORT_SYMBOL_GPL(sas_change_queue_depth);
806EXPORT_SYMBOL_GPL(sas_change_queue_type); 865EXPORT_SYMBOL_GPL(sas_change_queue_type);
807EXPORT_SYMBOL_GPL(sas_bios_param); 866EXPORT_SYMBOL_GPL(sas_bios_param);
867EXPORT_SYMBOL_GPL(sas_task_abort);