Skip to content

Commit

Permalink
[SCSI] libsas: add mutex for SMP task execution
Browse files Browse the repository at this point in the history
SAS does not tag SMP requests, and at least one lldd (isci) does not permit
more than one in-flight request at a time.

[jejb: fix sas_init_dev tab issues while we're at it]
Signed-off-by: Jeff Skirvin <jeffrey.d.skirvin@intel.com>
Signed-off-by: Dan Williams <dan.j.williams@intel.com>
Signed-off-by: James Bottomley <JBottomley@Parallels.com>
  • Loading branch information
Jeff Skirvin authored and James Bottomley committed Feb 19, 2012
1 parent 1f4fe89 commit 89d3cf6
Show file tree
Hide file tree
Showing 3 changed files with 34 additions and 28 deletions.
31 changes: 16 additions & 15 deletions drivers/scsi/libsas/sas_discover.c
Original file line number Diff line number Diff line change
Expand Up @@ -37,21 +37,22 @@

void sas_init_dev(struct domain_device *dev)
{
switch (dev->dev_type) {
case SAS_END_DEV:
break;
case EDGE_DEV:
case FANOUT_DEV:
INIT_LIST_HEAD(&dev->ex_dev.children);
break;
case SATA_DEV:
case SATA_PM:
case SATA_PM_PORT:
INIT_LIST_HEAD(&dev->sata_dev.children);
break;
default:
break;
}
switch (dev->dev_type) {
case SAS_END_DEV:
break;
case EDGE_DEV:
case FANOUT_DEV:
INIT_LIST_HEAD(&dev->ex_dev.children);
mutex_init(&dev->ex_dev.cmd_mutex);
break;
case SATA_DEV:
case SATA_PM:
case SATA_PM_PORT:
INIT_LIST_HEAD(&dev->sata_dev.children);
break;
default:
break;
}
}

/* ---------- Domain device discovery ---------- */
Expand Down
29 changes: 16 additions & 13 deletions drivers/scsi/libsas/sas_expander.c
Original file line number Diff line number Diff line change
Expand Up @@ -72,11 +72,13 @@ static int smp_execute_task(struct domain_device *dev, void *req, int req_size,
struct sas_internal *i =
to_sas_internal(dev->port->ha->core.shost->transportt);

mutex_lock(&dev->ex_dev.cmd_mutex);
for (retry = 0; retry < 3; retry++) {
task = sas_alloc_task(GFP_KERNEL);
if (!task)
return -ENOMEM;

if (!task) {
res = -ENOMEM;
break;
}
task->dev = dev;
task->task_proto = dev->tproto;
sg_init_one(&task->smp_task.smp_req, req, req_size);
Expand All @@ -94,7 +96,7 @@ static int smp_execute_task(struct domain_device *dev, void *req, int req_size,
if (res) {
del_timer(&task->timer);
SAS_DPRINTK("executing SMP task failed:%d\n", res);
goto ex_err;
break;
}

wait_for_completion(&task->completion);
Expand All @@ -104,21 +106,23 @@ static int smp_execute_task(struct domain_device *dev, void *req, int req_size,
i->dft->lldd_abort_task(task);
if (!(task->task_state_flags & SAS_TASK_STATE_DONE)) {
SAS_DPRINTK("SMP task aborted and not done\n");
goto ex_err;
break;
}
}
if (task->task_status.resp == SAS_TASK_COMPLETE &&
task->task_status.stat == SAM_STAT_GOOD) {
res = 0;
break;
} if (task->task_status.resp == SAS_TASK_COMPLETE &&
task->task_status.stat == SAS_DATA_UNDERRUN) {
}
if (task->task_status.resp == SAS_TASK_COMPLETE &&
task->task_status.stat == SAS_DATA_UNDERRUN) {
/* no error, but return the number of bytes of
* underrun */
res = task->task_status.residual;
break;
} if (task->task_status.resp == SAS_TASK_COMPLETE &&
task->task_status.stat == SAS_DATA_OVERRUN) {
}
if (task->task_status.resp == SAS_TASK_COMPLETE &&
task->task_status.stat == SAS_DATA_OVERRUN) {
res = -EMSGSIZE;
break;
} else {
Expand All @@ -131,11 +135,10 @@ static int smp_execute_task(struct domain_device *dev, void *req, int req_size,
task = NULL;
}
}
ex_err:
mutex_unlock(&dev->ex_dev.cmd_mutex);

BUG_ON(retry == 3 && task != NULL);
if (task != NULL) {
sas_free_task(task);
}
sas_free_task(task);
return res;
}

Expand Down
2 changes: 2 additions & 0 deletions include/scsi/libsas.h
Original file line number Diff line number Diff line change
Expand Up @@ -153,6 +153,8 @@ struct expander_device {

struct ex_phy *ex_phy;
struct sas_port *parent_port;

struct mutex cmd_mutex;
};

/* ---------- SATA device ---------- */
Expand Down

0 comments on commit 89d3cf6

Please sign in to comment.