aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/scsi/libsas
diff options
context:
space:
mode:
authorDan Williams <dan.j.williams@intel.com>2011-11-17 20:59:50 -0500
committerJames Bottomley <JBottomley@Parallels.com>2012-02-19 14:50:12 -0500
commit312d3e56119a4bc5c36a96818f87f650c069ddc2 (patch)
treed8cf7586656301ff1c4e5a49f9cbddde61e3e561 /drivers/scsi/libsas
parentb1124cd3ec97406c767b90bf7e93ecd2d2915592 (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.c36
-rw-r--r--drivers/scsi/libsas/sas_scsi_host.c6
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
167static unsigned int sas_ata_qc_issue(struct ata_queued_cmd *qc) 167static 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
247static bool sas_ata_qc_fill_rtf(struct ata_queued_cmd *qc) 257static 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