Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit 79a5eb60 authored by Darrick J. Wong's avatar Darrick J. Wong Committed by James Bottomley
Browse files

[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: default avatarDarrick J. Wong <djwong@us.ibm.com>
Signed-off-by: default avatarJames Bottomley <James.Bottomley@SteelEye.com>
parent f456393e
Loading
Loading
Loading
Loading
+60 −0
Original line number Original line Diff line number Diff line
@@ -33,6 +33,7 @@
#include <scsi/scsi_transport.h>
#include <scsi/scsi_transport.h>
#include <scsi/scsi_transport_sas.h>
#include <scsi/scsi_transport_sas.h>
#include "../scsi_sas_internal.h"
#include "../scsi_sas_internal.h"
#include "../scsi_transport_api.h"


#include <linux/err.h>
#include <linux/err.h>
#include <linux/blkdev.h>
#include <linux/blkdev.h>
@@ -798,6 +799,64 @@ void sas_shutdown_queue(struct sas_ha_struct *sas_ha)
	spin_unlock_irqrestore(&core->task_queue_lock, flags);
	spin_unlock_irqrestore(&core->task_queue_lock, flags);
}
}


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_queuecommand);
EXPORT_SYMBOL_GPL(sas_target_alloc);
EXPORT_SYMBOL_GPL(sas_target_alloc);
EXPORT_SYMBOL_GPL(sas_slave_configure);
EXPORT_SYMBOL_GPL(sas_slave_configure);
@@ -805,3 +864,4 @@ EXPORT_SYMBOL_GPL(sas_slave_destroy);
EXPORT_SYMBOL_GPL(sas_change_queue_depth);
EXPORT_SYMBOL_GPL(sas_change_queue_depth);
EXPORT_SYMBOL_GPL(sas_change_queue_type);
EXPORT_SYMBOL_GPL(sas_change_queue_type);
EXPORT_SYMBOL_GPL(sas_bios_param);
EXPORT_SYMBOL_GPL(sas_bios_param);
EXPORT_SYMBOL_GPL(sas_task_abort);
+4 −0
Original line number Original line Diff line number Diff line
@@ -528,6 +528,8 @@ struct sas_task {


	void   *lldd_task;	  /* for use by LLDDs */
	void   *lldd_task;	  /* for use by LLDDs */
	void   *uldd_task;
	void   *uldd_task;

	struct work_struct abort_work;
};
};




@@ -627,4 +629,6 @@ void sas_unregister_dev(struct domain_device *);


void sas_init_dev(struct domain_device *);
void sas_init_dev(struct domain_device *);


void sas_task_abort(struct sas_task *task);

#endif /* _SASLIB_H_ */
#endif /* _SASLIB_H_ */