diff options
author | Dan Williams <dan.j.williams@intel.com> | 2011-11-17 20:59:50 -0500 |
---|---|---|
committer | James Bottomley <JBottomley@Parallels.com> | 2012-02-19 14:50:12 -0500 |
commit | 312d3e56119a4bc5c36a96818f87f650c069ddc2 (patch) | |
tree | d8cf7586656301ff1c4e5a49f9cbddde61e3e561 /drivers/scsi/libsas | |
parent | b1124cd3ec97406c767b90bf7e93ecd2d2915592 (diff) |
[SCSI] libsas: remove ata_port.lock management duties from lldds
Each libsas driver (mvsas, pm8001, and isci) has invented a different
method for managing the ap->lock. The lock is held by the ata
->queuecommand() path. mvsas drops it prior to acquiring any internal
locks which allows it to hold its internal lock across calls to
task->task_done(). This capability is important as it is the only way
the driver can flush task->task_done() instances to guarantee that it no
longer has any in-flight references to a domain_device at
->lldd_dev_gone() time.
Signed-off-by: Dan Williams <dan.j.williams@intel.com>
Signed-off-by: James Bottomley <JBottomley@Parallels.com>
Diffstat (limited to 'drivers/scsi/libsas')
-rw-r--r-- | drivers/scsi/libsas/sas_ata.c | 36 | ||||
-rw-r--r-- | drivers/scsi/libsas/sas_scsi_host.c | 6 |
2 files changed, 25 insertions, 17 deletions
diff --git a/drivers/scsi/libsas/sas_ata.c b/drivers/scsi/libsas/sas_ata.c index 83118d0b6d0c..81ce39d166d1 100644 --- a/drivers/scsi/libsas/sas_ata.c +++ b/drivers/scsi/libsas/sas_ata.c | |||
@@ -166,23 +166,30 @@ qc_already_gone: | |||
166 | 166 | ||
167 | static unsigned int sas_ata_qc_issue(struct ata_queued_cmd *qc) | 167 | static unsigned int sas_ata_qc_issue(struct ata_queued_cmd *qc) |
168 | { | 168 | { |
169 | int res; | 169 | unsigned long flags; |
170 | struct sas_task *task; | 170 | struct sas_task *task; |
171 | struct domain_device *dev = qc->ap->private_data; | 171 | struct scatterlist *sg; |
172 | int ret = AC_ERR_SYSTEM; | ||
173 | unsigned int si, xfer = 0; | ||
174 | struct ata_port *ap = qc->ap; | ||
175 | struct domain_device *dev = ap->private_data; | ||
172 | struct sas_ha_struct *sas_ha = dev->port->ha; | 176 | struct sas_ha_struct *sas_ha = dev->port->ha; |
173 | struct Scsi_Host *host = sas_ha->core.shost; | 177 | struct Scsi_Host *host = sas_ha->core.shost; |
174 | struct sas_internal *i = to_sas_internal(host->transportt); | 178 | struct sas_internal *i = to_sas_internal(host->transportt); |
175 | struct scatterlist *sg; | 179 | |
176 | unsigned int xfer = 0; | 180 | /* TODO: audit callers to ensure they are ready for qc_issue to |
177 | unsigned int si; | 181 | * unconditionally re-enable interrupts |
182 | */ | ||
183 | local_irq_save(flags); | ||
184 | spin_unlock(ap->lock); | ||
178 | 185 | ||
179 | /* If the device fell off, no sense in issuing commands */ | 186 | /* If the device fell off, no sense in issuing commands */ |
180 | if (dev->gone) | 187 | if (dev->gone) |
181 | return AC_ERR_SYSTEM; | 188 | goto out; |
182 | 189 | ||
183 | task = sas_alloc_task(GFP_ATOMIC); | 190 | task = sas_alloc_task(GFP_ATOMIC); |
184 | if (!task) | 191 | if (!task) |
185 | return AC_ERR_SYSTEM; | 192 | goto out; |
186 | task->dev = dev; | 193 | task->dev = dev; |
187 | task->task_proto = SAS_PROTOCOL_STP; | 194 | task->task_proto = SAS_PROTOCOL_STP; |
188 | task->task_done = sas_ata_task_done; | 195 | task->task_done = sas_ata_task_done; |
@@ -227,21 +234,24 @@ static unsigned int sas_ata_qc_issue(struct ata_queued_cmd *qc) | |||
227 | ASSIGN_SAS_TASK(qc->scsicmd, task); | 234 | ASSIGN_SAS_TASK(qc->scsicmd, task); |
228 | 235 | ||
229 | if (sas_ha->lldd_max_execute_num < 2) | 236 | if (sas_ha->lldd_max_execute_num < 2) |
230 | res = i->dft->lldd_execute_task(task, 1, GFP_ATOMIC); | 237 | ret = i->dft->lldd_execute_task(task, 1, GFP_ATOMIC); |
231 | else | 238 | else |
232 | res = sas_queue_up(task); | 239 | ret = sas_queue_up(task); |
233 | 240 | ||
234 | /* Examine */ | 241 | /* Examine */ |
235 | if (res) { | 242 | if (ret) { |
236 | SAS_DPRINTK("lldd_execute_task returned: %d\n", res); | 243 | SAS_DPRINTK("lldd_execute_task returned: %d\n", ret); |
237 | 244 | ||
238 | if (qc->scsicmd) | 245 | if (qc->scsicmd) |
239 | ASSIGN_SAS_TASK(qc->scsicmd, NULL); | 246 | ASSIGN_SAS_TASK(qc->scsicmd, NULL); |
240 | sas_free_task(task); | 247 | sas_free_task(task); |
241 | return AC_ERR_SYSTEM; | 248 | ret = AC_ERR_SYSTEM; |
242 | } | 249 | } |
243 | 250 | ||
244 | return 0; | 251 | out: |
252 | spin_lock(ap->lock); | ||
253 | local_irq_restore(flags); | ||
254 | return ret; | ||
245 | } | 255 | } |
246 | 256 | ||
247 | static bool sas_ata_qc_fill_rtf(struct ata_queued_cmd *qc) | 257 | static bool sas_ata_qc_fill_rtf(struct ata_queued_cmd *qc) |
diff --git a/drivers/scsi/libsas/sas_scsi_host.c b/drivers/scsi/libsas/sas_scsi_host.c index 2a163c73fd8b..fd60465d4b2d 100644 --- a/drivers/scsi/libsas/sas_scsi_host.c +++ b/drivers/scsi/libsas/sas_scsi_host.c | |||
@@ -198,11 +198,9 @@ int sas_queuecommand(struct Scsi_Host *host, struct scsi_cmnd *cmd) | |||
198 | } | 198 | } |
199 | 199 | ||
200 | if (dev_is_sata(dev)) { | 200 | if (dev_is_sata(dev)) { |
201 | unsigned long flags; | 201 | spin_lock_irq(dev->sata_dev.ap->lock); |
202 | |||
203 | spin_lock_irqsave(dev->sata_dev.ap->lock, flags); | ||
204 | res = ata_sas_queuecmd(cmd, dev->sata_dev.ap); | 202 | res = ata_sas_queuecmd(cmd, dev->sata_dev.ap); |
205 | spin_unlock_irqrestore(dev->sata_dev.ap->lock, flags); | 203 | spin_unlock_irq(dev->sata_dev.ap->lock); |
206 | return res; | 204 | return res; |
207 | } | 205 | } |
208 | 206 | ||