Skip to content

Commit

Permalink
[SCSI] libsas: trim sas_task of slow path infrastructure
Browse files Browse the repository at this point in the history
The timer and the completion are only used for slow path tasks (smp, and
lldd tmfs), yet we incur the allocation space and cpu setup time for
every fast path task.

Cc: Xiangliang Yu <[email protected]>
Acked-by: Jack Wang <[email protected]>
Signed-off-by: Dan Williams <[email protected]>
Signed-off-by: James Bottomley <[email protected]>
  • Loading branch information
djbw authored and James Bottomley committed Jul 20, 2012
1 parent a494fd5 commit f0bf750
Show file tree
Hide file tree
Showing 6 changed files with 73 additions and 46 deletions.
20 changes: 10 additions & 10 deletions drivers/scsi/libsas/sas_expander.c
Original file line number Diff line number Diff line change
Expand Up @@ -51,14 +51,14 @@ static void smp_task_timedout(unsigned long _task)
task->task_state_flags |= SAS_TASK_STATE_ABORTED;
spin_unlock_irqrestore(&task->task_state_lock, flags);

complete(&task->completion);
complete(&task->slow_task->completion);
}

static void smp_task_done(struct sas_task *task)
{
if (!del_timer(&task->timer))
if (!del_timer(&task->slow_task->timer))
return;
complete(&task->completion);
complete(&task->slow_task->completion);
}

/* Give it some long enough timeout. In seconds. */
Expand All @@ -79,7 +79,7 @@ static int smp_execute_task(struct domain_device *dev, void *req, int req_size,
break;
}

task = sas_alloc_task(GFP_KERNEL);
task = sas_alloc_slow_task(GFP_KERNEL);
if (!task) {
res = -ENOMEM;
break;
Expand All @@ -91,20 +91,20 @@ static int smp_execute_task(struct domain_device *dev, void *req, int req_size,

task->task_done = smp_task_done;

task->timer.data = (unsigned long) task;
task->timer.function = smp_task_timedout;
task->timer.expires = jiffies + SMP_TIMEOUT*HZ;
add_timer(&task->timer);
task->slow_task->timer.data = (unsigned long) task;
task->slow_task->timer.function = smp_task_timedout;
task->slow_task->timer.expires = jiffies + SMP_TIMEOUT*HZ;
add_timer(&task->slow_task->timer);

res = i->dft->lldd_execute_task(task, 1, GFP_KERNEL);

if (res) {
del_timer(&task->timer);
del_timer(&task->slow_task->timer);
SAS_DPRINTK("executing SMP task failed:%d\n", res);
break;
}

wait_for_completion(&task->completion);
wait_for_completion(&task->slow_task->completion);
res = -ECOMM;
if ((task->task_state_flags & SAS_TASK_STATE_ABORTED)) {
SAS_DPRINTK("smp task timed out or aborted\n");
Expand Down
23 changes: 21 additions & 2 deletions drivers/scsi/libsas/sas_init.c
Original file line number Diff line number Diff line change
Expand Up @@ -48,18 +48,37 @@ struct sas_task *sas_alloc_task(gfp_t flags)
INIT_LIST_HEAD(&task->list);
spin_lock_init(&task->task_state_lock);
task->task_state_flags = SAS_TASK_STATE_PENDING;
init_timer(&task->timer);
init_completion(&task->completion);
}

return task;
}
EXPORT_SYMBOL_GPL(sas_alloc_task);

struct sas_task *sas_alloc_slow_task(gfp_t flags)
{
struct sas_task *task = sas_alloc_task(flags);
struct sas_task_slow *slow = kmalloc(sizeof(*slow), flags);

if (!task || !slow) {
if (task)
kmem_cache_free(sas_task_cache, task);
kfree(slow);
return NULL;
}

task->slow_task = slow;
init_timer(&slow->timer);
init_completion(&slow->completion);

return task;
}
EXPORT_SYMBOL_GPL(sas_alloc_slow_task);

void sas_free_task(struct sas_task *task)
{
if (task) {
BUG_ON(!list_empty(&task->list));
kfree(task->slow_task);
kmem_cache_free(sas_task_cache, task);
}
}
Expand Down
8 changes: 6 additions & 2 deletions drivers/scsi/libsas/sas_scsi_host.c
Original file line number Diff line number Diff line change
Expand Up @@ -1134,9 +1134,13 @@ void sas_task_abort(struct sas_task *task)

/* Escape for libsas internal commands */
if (!sc) {
if (!del_timer(&task->timer))
struct sas_task_slow *slow = task->slow_task;

if (!slow)
return;
if (!del_timer(&slow->timer))
return;
task->timer.function(task->timer.data);
slow->timer.function(slow->timer.data);
return;
}

Expand Down
20 changes: 10 additions & 10 deletions drivers/scsi/mvsas/mv_sas.c
Original file line number Diff line number Diff line change
Expand Up @@ -1365,17 +1365,17 @@ void mvs_dev_gone(struct domain_device *dev)

static void mvs_task_done(struct sas_task *task)
{
if (!del_timer(&task->timer))
if (!del_timer(&task->slow_task->timer))
return;
complete(&task->completion);
complete(&task->slow_task->completion);
}

static void mvs_tmf_timedout(unsigned long data)
{
struct sas_task *task = (struct sas_task *)data;

task->task_state_flags |= SAS_TASK_STATE_ABORTED;
complete(&task->completion);
complete(&task->slow_task->completion);
}

#define MVS_TASK_TIMEOUT 20
Expand All @@ -1386,7 +1386,7 @@ static int mvs_exec_internal_tmf_task(struct domain_device *dev,
struct sas_task *task = NULL;

for (retry = 0; retry < 3; retry++) {
task = sas_alloc_task(GFP_KERNEL);
task = sas_alloc_slow_task(GFP_KERNEL);
if (!task)
return -ENOMEM;

Expand All @@ -1396,20 +1396,20 @@ static int mvs_exec_internal_tmf_task(struct domain_device *dev,
memcpy(&task->ssp_task, parameter, para_len);
task->task_done = mvs_task_done;

task->timer.data = (unsigned long) task;
task->timer.function = mvs_tmf_timedout;
task->timer.expires = jiffies + MVS_TASK_TIMEOUT*HZ;
add_timer(&task->timer);
task->slow_task->timer.data = (unsigned long) task;
task->slow_task->timer.function = mvs_tmf_timedout;
task->slow_task->timer.expires = jiffies + MVS_TASK_TIMEOUT*HZ;
add_timer(&task->slow_task->timer);

res = mvs_task_exec(task, 1, GFP_KERNEL, NULL, 1, tmf);

if (res) {
del_timer(&task->timer);
del_timer(&task->slow_task->timer);
mv_printk("executing internel task failed:%d\n", res);
goto ex_err;
}

wait_for_completion(&task->completion);
wait_for_completion(&task->slow_task->completion);
res = TMF_RESP_FUNC_FAILED;
/* Even TMF timed out, return direct. */
if ((task->task_state_flags & SAS_TASK_STATE_ABORTED)) {
Expand Down
34 changes: 17 additions & 17 deletions drivers/scsi/pm8001/pm8001_sas.c
Original file line number Diff line number Diff line change
Expand Up @@ -650,17 +650,17 @@ int pm8001_dev_found(struct domain_device *dev)

static void pm8001_task_done(struct sas_task *task)
{
if (!del_timer(&task->timer))
if (!del_timer(&task->slow_task->timer))
return;
complete(&task->completion);
complete(&task->slow_task->completion);
}

static void pm8001_tmf_timedout(unsigned long data)
{
struct sas_task *task = (struct sas_task *)data;

task->task_state_flags |= SAS_TASK_STATE_ABORTED;
complete(&task->completion);
complete(&task->slow_task->completion);
}

#define PM8001_TASK_TIMEOUT 20
Expand All @@ -683,29 +683,29 @@ static int pm8001_exec_internal_tmf_task(struct domain_device *dev,
struct pm8001_hba_info *pm8001_ha = pm8001_find_ha_by_dev(dev);

for (retry = 0; retry < 3; retry++) {
task = sas_alloc_task(GFP_KERNEL);
task = sas_alloc_slow_task(GFP_KERNEL);
if (!task)
return -ENOMEM;

task->dev = dev;
task->task_proto = dev->tproto;
memcpy(&task->ssp_task, parameter, para_len);
task->task_done = pm8001_task_done;
task->timer.data = (unsigned long)task;
task->timer.function = pm8001_tmf_timedout;
task->timer.expires = jiffies + PM8001_TASK_TIMEOUT*HZ;
add_timer(&task->timer);
task->slow_task->timer.data = (unsigned long)task;
task->slow_task->timer.function = pm8001_tmf_timedout;
task->slow_task->timer.expires = jiffies + PM8001_TASK_TIMEOUT*HZ;
add_timer(&task->slow_task->timer);

res = pm8001_task_exec(task, 1, GFP_KERNEL, 1, tmf);

if (res) {
del_timer(&task->timer);
del_timer(&task->slow_task->timer);
PM8001_FAIL_DBG(pm8001_ha,
pm8001_printk("Executing internal task "
"failed\n"));
goto ex_err;
}
wait_for_completion(&task->completion);
wait_for_completion(&task->slow_task->completion);
res = -TMF_RESP_FUNC_FAILED;
/* Even TMF timed out, return direct. */
if ((task->task_state_flags & SAS_TASK_STATE_ABORTED)) {
Expand Down Expand Up @@ -765,17 +765,17 @@ pm8001_exec_internal_task_abort(struct pm8001_hba_info *pm8001_ha,
struct sas_task *task = NULL;

for (retry = 0; retry < 3; retry++) {
task = sas_alloc_task(GFP_KERNEL);
task = sas_alloc_slow_task(GFP_KERNEL);
if (!task)
return -ENOMEM;

task->dev = dev;
task->task_proto = dev->tproto;
task->task_done = pm8001_task_done;
task->timer.data = (unsigned long)task;
task->timer.function = pm8001_tmf_timedout;
task->timer.expires = jiffies + PM8001_TASK_TIMEOUT * HZ;
add_timer(&task->timer);
task->slow_task->timer.data = (unsigned long)task;
task->slow_task->timer.function = pm8001_tmf_timedout;
task->slow_task->timer.expires = jiffies + PM8001_TASK_TIMEOUT * HZ;
add_timer(&task->slow_task->timer);

res = pm8001_tag_alloc(pm8001_ha, &ccb_tag);
if (res)
Expand All @@ -789,13 +789,13 @@ pm8001_exec_internal_task_abort(struct pm8001_hba_info *pm8001_ha,
pm8001_dev, flag, task_tag, ccb_tag);

if (res) {
del_timer(&task->timer);
del_timer(&task->slow_task->timer);
PM8001_FAIL_DBG(pm8001_ha,
pm8001_printk("Executing internal task "
"failed\n"));
goto ex_err;
}
wait_for_completion(&task->completion);
wait_for_completion(&task->slow_task->completion);
res = TMF_RESP_FUNC_FAILED;
/* Even TMF timed out, return direct. */
if ((task->task_state_flags & SAS_TASK_STATE_ABORTED)) {
Expand Down
14 changes: 9 additions & 5 deletions include/scsi/libsas.h
Original file line number Diff line number Diff line change
Expand Up @@ -613,10 +613,6 @@ struct sas_task {

enum sas_protocol task_proto;

/* Used by the discovery code. */
struct timer_list timer;
struct completion completion;

union {
struct sas_ata_task ata_task;
struct sas_smp_task smp_task;
Expand All @@ -633,8 +629,15 @@ struct sas_task {

void *lldd_task; /* for use by LLDDs */
void *uldd_task;
struct sas_task_slow *slow_task;
};

struct work_struct abort_work;
struct sas_task_slow {
/* standard/extra infrastructure for slow path commands (SMP and
* internal lldd commands
*/
struct timer_list timer;
struct completion completion;
};

#define SAS_TASK_STATE_PENDING 1
Expand All @@ -644,6 +647,7 @@ struct sas_task {
#define SAS_TASK_AT_INITIATOR 16

extern struct sas_task *sas_alloc_task(gfp_t flags);
extern struct sas_task *sas_alloc_slow_task(gfp_t flags);
extern void sas_free_task(struct sas_task *task);

struct sas_domain_function_template {
Expand Down

0 comments on commit f0bf750

Please sign in to comment.