[SCSI] sas_ata: Satisfy libata qc function locking requirements
authorDarrick J. Wong <djwong@us.ibm.com>
Tue, 30 Jan 2007 09:18:35 +0000 (01:18 -0800)
committerJames Bottomley <jejb@mulgrave.localdomain>
Wed, 18 Jul 2007 16:14:55 +0000 (11:14 -0500)
ata_qc_complete and ata_sas_queuecmd require that the port lock be held
when they are called.  sas_ata doesn't do this, leading to BUG messages
about qc tags newly allocated qc tags already being in use.  This patch
fixes the locking, which should clean up the rest of those messages.

So far I've tested this against an IBM x206m with two SATA disks with no
BUG messages and no other signs of things going wrong, and the machine
finally passed the pounder stress test.

Signed-off-by: Darrick J. Wong <djwong@us.ibm.com>
Signed-off-by: James Bottomley <James.Bottomley@SteelEye.com>
drivers/scsi/libsas/sas_ata.c
drivers/scsi/libsas/sas_scsi_host.c

index de42b5b801cd75d6b3a19bbd082c1ae287f7bb28..0bb1a149a9c28eab56a72587d43fb016f2074c3c 100644 (file)
@@ -92,7 +92,9 @@ static void sas_ata_task_done(struct sas_task *task)
        struct task_status_struct *stat = &task->task_status;
        struct ata_task_resp *resp = (struct ata_task_resp *)stat->buf;
        enum ata_completion_errors ac;
+       unsigned long flags;
 
+       spin_lock_irqsave(dev->sata_dev.ap->lock, flags);
        if (stat->stat == SAS_PROTO_RESPONSE) {
                ata_tf_from_fis(resp->ending_fis, &dev->sata_dev.tf);
                qc->err_mask |= ac_err_mask(dev->sata_dev.tf.command);
@@ -113,6 +115,8 @@ static void sas_ata_task_done(struct sas_task *task)
        }
 
        ata_qc_complete(qc);
+       spin_unlock_irqrestore(dev->sata_dev.ap->lock, flags);
+
        list_del_init(&task->list);
        sas_free_task(task);
 }
index dbc2a912114f1880b0172055d703b0c9553bfbd4..ba5c91b813125ff43590cf1b9ea743cb618ecf19 100644 (file)
@@ -216,8 +216,12 @@ int sas_queuecommand(struct scsi_cmnd *cmd,
                struct sas_task *task;
 
                if (dev_is_sata(dev)) {
+                       unsigned long flags;
+
+                       spin_lock_irqsave(dev->sata_dev.ap->lock, flags);
                        res = ata_sas_queuecmd(cmd, scsi_done,
                                               dev->sata_dev.ap);
+                       spin_unlock_irqrestore(dev->sata_dev.ap->lock, flags);
                        goto out;
                }