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

Commit 79855d17 authored by Christoph Hellwig's avatar Christoph Hellwig
Browse files

libsas: remove task_collector mode



The task_collector mode (or "latency_injector", (C) Dan Willians) is an
optional I/O path in libsas that queues up scsi commands instead of
directly sending it to the hardware.  It generall increases latencies
to in the optiomal case slightly reduce mmio traffic to the hardware.

Only the obsolete aic94xx driver and the mvsas driver allowed to use
it without recompiling the kernel, and most drivers didn't support it
at all.

Remove the giant blob of code to allow better optimizations for scsi-mq
in the future.

Signed-off-by: default avatarChristoph Hellwig <hch@lst.de>
Reviewed-by: default avatarHannes Reinecke <hare@suse.de>
Acked-by: default avatarDan Williams <dan.j.williams@intel.com>
parent 309e7cc4
Loading
Loading
Loading
Loading
+4 −78
Original line number Diff line number Diff line
@@ -226,9 +226,6 @@ static int register_sas_ha(struct my_sas_ha *my_ha)
	my_ha->sas_ha.lldd_dev_found = my_dev_found;
	my_ha->sas_ha.lldd_dev_gone = my_dev_gone;

	my_ha->sas_ha.lldd_max_execute_num = lldd_max_execute_num; (1)

	my_ha->sas_ha.lldd_queue_size = ha_can_queue;
	my_ha->sas_ha.lldd_execute_task = my_execute_task;

	my_ha->sas_ha.lldd_abort_task     = my_abort_task;
@@ -247,28 +244,6 @@ static int register_sas_ha(struct my_sas_ha *my_ha)
	return sas_register_ha(&my_ha->sas_ha);
}

(1) This is normally a LLDD parameter, something of the
lines of a task collector.  What it tells the SAS Layer is
whether the SAS layer should run in Direct Mode (default:
value 0 or 1) or Task Collector Mode (value greater than 1).

In Direct Mode, the SAS Layer calls Execute Task as soon as
it has a command to send to the SDS, _and_ this is a single
command, i.e. not linked.

Some hardware (e.g. aic94xx) has the capability to DMA more
than one task at a time (interrupt) from host memory.  Task
Collector Mode is an optional feature for HAs which support
this in their hardware.  (Again, it is completely optional
even if your hardware supports it.)

In Task Collector Mode, the SAS Layer would do _natural_
coalescing of tasks and at the appropriate moment it would
call your driver to DMA more than one task in a single HA
interrupt. DMBS may want to use this by insmod/modprobe
setting the lldd_max_execute_num to something greater than
1.

(2) SAS 1.1 does not define I_T Nexus Reset TMF.

Events
@@ -325,71 +300,22 @@ PHYE_SPINUP_HOLD -- SATA is present, COMWAKE not sent.

The Execute Command SCSI RPC:

	int (*lldd_execute_task)(struct sas_task *, int num,
				 unsigned long gfp_flags);
	int (*lldd_execute_task)(struct sas_task *, gfp_t gfp_flags);

Used to queue a task to the SAS LLDD.  @task is the tasks to
be executed.  @num should be the number of tasks being
queued at this function call (they are linked listed via
task::list), @gfp_mask should be the gfp_mask defining the
context of the caller.
Used to queue a task to the SAS LLDD.  @task is the task to be executed.
@gfp_mask is the gfp_mask defining the context of the caller.

This function should implement the Execute Command SCSI RPC,
or if you're sending a SCSI Task as linked commands, you
should also use this function.

That is, when lldd_execute_task() is called, the command(s)
That is, when lldd_execute_task() is called, the command
go out on the transport *immediately*.  There is *no*
queuing of any sort and at any level in a SAS LLDD.

The use of task::list is two-fold, one for linked commands,
the other discussed below.

It is possible to queue up more than one task at a time, by
initializing the list element of struct sas_task, and
passing the number of tasks enlisted in this manner in num.

Returns: -SAS_QUEUE_FULL, -ENOMEM, nothing was queued;
	 0, the task(s) were queued.

If you want to pass num > 1, then either
A) you're the only caller of this function and keep track
   of what you've queued to the LLDD, or
B) you know what you're doing and have a strategy of
   retrying.

As opposed to queuing one task at a time (function call),
batch queuing of tasks, by having num > 1, greatly
simplifies LLDD code, sequencer code, and _hardware design_,
and has some performance advantages in certain situations
(DBMS).

The LLDD advertises if it can take more than one command at
a time at lldd_execute_task(), by setting the
lldd_max_execute_num parameter (controlled by "collector"
module parameter in aic94xx SAS LLDD).

You should leave this to the default 1, unless you know what
you're doing.

This is a function of the LLDD, to which the SAS layer can
cater to.

int lldd_queue_size
	The host adapter's queue size.  This is the maximum
number of commands the lldd can have pending to domain
devices on behalf of all upper layers submitting through
lldd_execute_task().

You really want to set this to something (much) larger than
1.

This _really_ has absolutely nothing to do with queuing.
There is no queuing in SAS LLDDs.

struct sas_task {
	dev -- the device this task is destined to
	list -- must be initialized (INIT_LIST_HEAD)
	task_proto -- _one_ of enum sas_proto
	scatter -- pointer to scatter gather list array
	num_scatter -- number of elements in scatter
+1 −1
Original line number Diff line number Diff line
@@ -78,7 +78,7 @@ void asd_dev_gone(struct domain_device *dev);

void asd_invalidate_edb(struct asd_ascb *ascb, int edb_id);

int  asd_execute_task(struct sas_task *, int num, gfp_t gfp_flags);
int  asd_execute_task(struct sas_task *task, gfp_t gfp_flags);

void asd_set_dmamode(struct domain_device *dev);

+1 −2
Original line number Diff line number Diff line
@@ -1200,8 +1200,7 @@ static void asd_start_scb_timers(struct list_head *list)
 * Case A: we can send the whole batch at once.  Increment "pending"
 * in the beginning of this function, when it is checked, in order to
 * eliminate races when this function is called by multiple processes.
 * Case B: should never happen if the managing layer considers
 * lldd_queue_size.
 * Case B: should never happen.
 */
int asd_post_ascb_list(struct asd_ha_struct *asd_ha, struct asd_ascb *ascb,
		       int num)
+0 −11
Original line number Diff line number Diff line
@@ -49,14 +49,6 @@ MODULE_PARM_DESC(use_msi, "\n"
	"\tEnable(1) or disable(0) using PCI MSI.\n"
	"\tDefault: 0");

static int lldd_max_execute_num = 0;
module_param_named(collector, lldd_max_execute_num, int, S_IRUGO);
MODULE_PARM_DESC(collector, "\n"
	"\tIf greater than one, tells the SAS Layer to run in Task Collector\n"
	"\tMode.  If 1 or 0, tells the SAS Layer to run in Direct Mode.\n"
	"\tThe aic94xx SAS LLDD supports both modes.\n"
	"\tDefault: 0 (Direct Mode).\n");

static struct scsi_transport_template *aic94xx_transport_template;
static int asd_scan_finished(struct Scsi_Host *, unsigned long);
static void asd_scan_start(struct Scsi_Host *);
@@ -711,9 +703,6 @@ static int asd_register_sas_ha(struct asd_ha_struct *asd_ha)
	asd_ha->sas_ha.sas_port= sas_ports;
	asd_ha->sas_ha.num_phys= ASD_MAX_PHYS;

	asd_ha->sas_ha.lldd_queue_size = asd_ha->seq.can_queue;
	asd_ha->sas_ha.lldd_max_execute_num = lldd_max_execute_num;

	return sas_register_ha(&asd_ha->sas_ha);
}

+6 −7
Original line number Diff line number Diff line
@@ -543,8 +543,7 @@ static int asd_can_queue(struct asd_ha_struct *asd_ha, int num)
	return res;
}

int asd_execute_task(struct sas_task *task, const int num,
		     gfp_t gfp_flags)
int asd_execute_task(struct sas_task *task, gfp_t gfp_flags)
{
	int res = 0;
	LIST_HEAD(alist);
@@ -553,11 +552,11 @@ int asd_execute_task(struct sas_task *task, const int num,
	struct asd_ha_struct *asd_ha = task->dev->port->ha->lldd_ha;
	unsigned long flags;

	res = asd_can_queue(asd_ha, num);
	res = asd_can_queue(asd_ha, 1);
	if (res)
		return res;

	res = num;
	res = 1;
	ascb = asd_ascb_alloc_list(asd_ha, &res, gfp_flags);
	if (res) {
		res = -ENOMEM;
@@ -568,7 +567,7 @@ int asd_execute_task(struct sas_task *task, const int num,
	list_for_each_entry(a, &alist, list) {
		a->uldd_task = t;
		t->lldd_task = a;
		t = list_entry(t->list.next, struct sas_task, list);
		break;
	}
	list_for_each_entry(a, &alist, list) {
		t = a->uldd_task;
@@ -601,7 +600,7 @@ int asd_execute_task(struct sas_task *task, const int num,
	}
	list_del_init(&alist);

	res = asd_post_ascb_list(asd_ha, ascb, num);
	res = asd_post_ascb_list(asd_ha, ascb, 1);
	if (unlikely(res)) {
		a = NULL;
		__list_add(&alist, ascb->list.prev, &ascb->list);
@@ -639,6 +638,6 @@ int asd_execute_task(struct sas_task *task, const int num,
out_err:
	if (ascb)
		asd_ascb_free_list(ascb);
	asd_can_dequeue(asd_ha, num);
	asd_can_dequeue(asd_ha, 1);
	return res;
}
Loading