diff options
author | Jeff Skirvin <jeffrey.d.skirvin@intel.com> | 2011-11-16 04:44:13 -0500 |
---|---|---|
committer | James Bottomley <JBottomley@Parallels.com> | 2012-02-19 15:22:49 -0500 |
commit | 89d3cf6ac3cdc4f15a82709f8c78ed169a98be5b (patch) | |
tree | 6da0cf7d0f6e0ff10890f456e754aa6f76013452 /drivers/scsi | |
parent | 1f4fe89c9c78d3163cf1e389bdc6438a44b64244 (diff) |
[SCSI] libsas: add mutex for SMP task execution
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>
Diffstat (limited to 'drivers/scsi')
-rw-r--r-- | drivers/scsi/libsas/sas_discover.c | 31 | ||||
-rw-r--r-- | drivers/scsi/libsas/sas_expander.c | 29 |
2 files changed, 32 insertions, 28 deletions
diff --git a/drivers/scsi/libsas/sas_discover.c b/drivers/scsi/libsas/sas_discover.c index bad5eba4a92b..c56cc6400819 100644 --- a/drivers/scsi/libsas/sas_discover.c +++ b/drivers/scsi/libsas/sas_discover.c | |||
@@ -37,21 +37,22 @@ | |||
37 | 37 | ||
38 | void sas_init_dev(struct domain_device *dev) | 38 | void sas_init_dev(struct domain_device *dev) |
39 | { | 39 | { |
40 | switch (dev->dev_type) { | 40 | switch (dev->dev_type) { |
41 | case SAS_END_DEV: | 41 | case SAS_END_DEV: |
42 | break; | 42 | break; |
43 | case EDGE_DEV: | 43 | case EDGE_DEV: |
44 | case FANOUT_DEV: | 44 | case FANOUT_DEV: |
45 | INIT_LIST_HEAD(&dev->ex_dev.children); | 45 | INIT_LIST_HEAD(&dev->ex_dev.children); |
46 | break; | 46 | mutex_init(&dev->ex_dev.cmd_mutex); |
47 | case SATA_DEV: | 47 | break; |
48 | case SATA_PM: | 48 | case SATA_DEV: |
49 | case SATA_PM_PORT: | 49 | case SATA_PM: |
50 | INIT_LIST_HEAD(&dev->sata_dev.children); | 50 | case SATA_PM_PORT: |
51 | break; | 51 | INIT_LIST_HEAD(&dev->sata_dev.children); |
52 | default: | 52 | break; |
53 | break; | 53 | default: |
54 | } | 54 | break; |
55 | } | ||
55 | } | 56 | } |
56 | 57 | ||
57 | /* ---------- Domain device discovery ---------- */ | 58 | /* ---------- Domain device discovery ---------- */ |
diff --git a/drivers/scsi/libsas/sas_expander.c b/drivers/scsi/libsas/sas_expander.c index d3c1a29b8a2a..7c59f97c0287 100644 --- a/drivers/scsi/libsas/sas_expander.c +++ b/drivers/scsi/libsas/sas_expander.c | |||
@@ -72,11 +72,13 @@ static int smp_execute_task(struct domain_device *dev, void *req, int req_size, | |||
72 | struct sas_internal *i = | 72 | struct sas_internal *i = |
73 | to_sas_internal(dev->port->ha->core.shost->transportt); | 73 | to_sas_internal(dev->port->ha->core.shost->transportt); |
74 | 74 | ||
75 | mutex_lock(&dev->ex_dev.cmd_mutex); | ||
75 | for (retry = 0; retry < 3; retry++) { | 76 | for (retry = 0; retry < 3; retry++) { |
76 | task = sas_alloc_task(GFP_KERNEL); | 77 | task = sas_alloc_task(GFP_KERNEL); |
77 | if (!task) | 78 | if (!task) { |
78 | return -ENOMEM; | 79 | res = -ENOMEM; |
79 | 80 | break; | |
81 | } | ||
80 | task->dev = dev; | 82 | task->dev = dev; |
81 | task->task_proto = dev->tproto; | 83 | task->task_proto = dev->tproto; |
82 | sg_init_one(&task->smp_task.smp_req, req, req_size); | 84 | sg_init_one(&task->smp_task.smp_req, req, req_size); |
@@ -94,7 +96,7 @@ static int smp_execute_task(struct domain_device *dev, void *req, int req_size, | |||
94 | if (res) { | 96 | if (res) { |
95 | del_timer(&task->timer); | 97 | del_timer(&task->timer); |
96 | SAS_DPRINTK("executing SMP task failed:%d\n", res); | 98 | SAS_DPRINTK("executing SMP task failed:%d\n", res); |
97 | goto ex_err; | 99 | break; |
98 | } | 100 | } |
99 | 101 | ||
100 | wait_for_completion(&task->completion); | 102 | wait_for_completion(&task->completion); |
@@ -104,21 +106,23 @@ static int smp_execute_task(struct domain_device *dev, void *req, int req_size, | |||
104 | i->dft->lldd_abort_task(task); | 106 | i->dft->lldd_abort_task(task); |
105 | if (!(task->task_state_flags & SAS_TASK_STATE_DONE)) { | 107 | if (!(task->task_state_flags & SAS_TASK_STATE_DONE)) { |
106 | SAS_DPRINTK("SMP task aborted and not done\n"); | 108 | SAS_DPRINTK("SMP task aborted and not done\n"); |
107 | goto ex_err; | 109 | break; |
108 | } | 110 | } |
109 | } | 111 | } |
110 | if (task->task_status.resp == SAS_TASK_COMPLETE && | 112 | if (task->task_status.resp == SAS_TASK_COMPLETE && |
111 | task->task_status.stat == SAM_STAT_GOOD) { | 113 | task->task_status.stat == SAM_STAT_GOOD) { |
112 | res = 0; | 114 | res = 0; |
113 | break; | 115 | break; |
114 | } if (task->task_status.resp == SAS_TASK_COMPLETE && | 116 | } |
115 | task->task_status.stat == SAS_DATA_UNDERRUN) { | 117 | if (task->task_status.resp == SAS_TASK_COMPLETE && |
118 | task->task_status.stat == SAS_DATA_UNDERRUN) { | ||
116 | /* no error, but return the number of bytes of | 119 | /* no error, but return the number of bytes of |
117 | * underrun */ | 120 | * underrun */ |
118 | res = task->task_status.residual; | 121 | res = task->task_status.residual; |
119 | break; | 122 | break; |
120 | } if (task->task_status.resp == SAS_TASK_COMPLETE && | 123 | } |
121 | task->task_status.stat == SAS_DATA_OVERRUN) { | 124 | if (task->task_status.resp == SAS_TASK_COMPLETE && |
125 | task->task_status.stat == SAS_DATA_OVERRUN) { | ||
122 | res = -EMSGSIZE; | 126 | res = -EMSGSIZE; |
123 | break; | 127 | break; |
124 | } else { | 128 | } else { |
@@ -131,11 +135,10 @@ static int smp_execute_task(struct domain_device *dev, void *req, int req_size, | |||
131 | task = NULL; | 135 | task = NULL; |
132 | } | 136 | } |
133 | } | 137 | } |
134 | ex_err: | 138 | mutex_unlock(&dev->ex_dev.cmd_mutex); |
139 | |||
135 | BUG_ON(retry == 3 && task != NULL); | 140 | BUG_ON(retry == 3 && task != NULL); |
136 | if (task != NULL) { | 141 | sas_free_task(task); |
137 | sas_free_task(task); | ||
138 | } | ||
139 | return res; | 142 | return res; |
140 | } | 143 | } |
141 | 144 | ||