2/3: Add sas_abort_task to libsas
Subsystems (2)
PATCH 1/1 2/3: Add sas_abort_task to libsas
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 <[email protected]>
--
drivers/scsi/libsas/sas_scsi_host.c +60 -0
@@ -34,6 +34,7 @@ #include <scsi/scsi_transport.h>#include <scsi/scsi_transport_sas.h> #include <scsi/sas_ata.h> #include "../scsi_sas_internal.h" +#include "../scsi_transport_api.h" #include <linux/err.h> #include <linux/blkdev.h>
@@ -855,6 +856,64 @@ void sas_target_destroy(struct scsi_targreturn ; } +static int do_sas_task_abort (struct sas_task *task) +{ +struct scsi_cmnd *sc = task->uldd_task; +struct sas_internal *si = +to_sas_internal (task->dev->port->ha->core.shost->transportt); +unsigned long flags; +int res; + +spin_lock_irqsave (&task->task_state_lock, flags); +if (task->task_state_flags &SAS_TASK_STATE_ABORTED ) { +spin_unlock_irqrestore (&task->task_state_lock, flags); +SAS_DPRINTK ("%s: Task %p already aborted.\n" , __FUNCTION__, + task); +return 0 ; + } + + task->task_state_flags |=SAS_TASK_INITIATOR_ABORTED ; +if (!(task->task_state_flags &SAS_TASK_STATE_DONE )) + task->task_state_flags |=SAS_TASK_STATE_ABORTED ; +spin_unlock_irqrestore (&task->task_state_lock, flags); + +if (!si->dft->lldd_abort_task) +return -ENODEV ; + + res = si->dft->lldd_abort_task (task); +if ((task->task_state_flags &SAS_TASK_STATE_DONE ) || + (res ==TMF_RESP_FUNC_COMPLETE )) + { +/* SMP commands don't have scsi_cmds(?) */ +if (!sc) { + task->task_done (task); +return 0 ; + } +scsi_req_abort_cmd (sc); +scsi_schedule_eh (sc->device->host); +return 0 ; + } + +spin_lock_irqsave (&task->task_state_lock, flags); + task->task_state_flags &= ~SAS_TASK_INITIATOR_ABORTED ; +if (!(task->task_state_flags &SAS_TASK_STATE_DONE )) + task->task_state_flags &= ~SAS_TASK_STATE_ABORTED ; +spin_unlock_irqrestore (&task->task_state_lock, flags); + +return -EAGAIN ; +} + +void sas_task_abort (struct sas_task *task) +{ +int i; + +for (i =0 ; i <5 ; i++) +if (!do_sas_task_abort (task)) +return ; + +SAS_DPRINTK ("%s: Could not kill task!\n" , __FUNCTION__); +} +EXPORT_SYMBOL_GPL (sas_queuecommand);EXPORT_SYMBOL_GPL (sas_target_alloc);EXPORT_SYMBOL_GPL (sas_slave_configure);
@@ -865,3 +924,4 @@ EXPORT_SYMBOL_GPL(sas_bios_param);EXPORT_SYMBOL_GPL (sas_slave_alloc);EXPORT_SYMBOL_GPL (sas_target_destroy);EXPORT_SYMBOL_GPL (sas_ioctl); +EXPORT_SYMBOL_GPL (sas_task_abort);
include/scsi/libsas.h +3 -0
@@ -536,6 +536,8 @@ struct sas_task {void *lldd_task;/* for use by LLDDs */ void *uldd_task; + +struct work_struct abort_work; };
@@ -639,5 +641,6 @@ void sas_init_dev(struct domain_device *extern void sas_target_destroy (struct scsi_target *);extern int sas_slave_alloc (struct scsi_device *);extern int sas_ioctl (struct scsi_device *sdev,int cmd,void __user *arg); +void sas_task_abort (struct sas_task *task);#endif /* _SASLIB_H_ */