summaryrefslogtreecommitdiffstats
path: root/drivers/scsi/libata-core.c
diff options
context:
space:
mode:
authorTejun Heo2006-05-15 13:58:03 +0200
committerTejun Heo2006-05-15 13:58:03 +0200
commitf69499f42caf74194df678c9c293f2ee0fe90bc3 (patch)
tree642f3d5792eb6561fd01116f6a247d26f9e3e304 /drivers/scsi/libata-core.c
parent[PATCH] libata-eh-fw: use special reserved tag and qc for internal commands (diff)
downloadkernel-qcow2-linux-f69499f42caf74194df678c9c293f2ee0fe90bc3.tar.gz
kernel-qcow2-linux-f69499f42caf74194df678c9c293f2ee0fe90bc3.tar.xz
kernel-qcow2-linux-f69499f42caf74194df678c9c293f2ee0fe90bc3.zip
[PATCH] libata-eh-fw: update ata_qc_from_tag() to enforce normal/EH qc ownership
New EH framework has clear distinction about who owns a qc. Every qc starts owned by normal execution path - PIO, interrupt or whatever. When an exception condition occurs which affects the qc, the qc gets scheduled for EH. Note that some events (say, link lost and regained, command timeout) may schedule qc's which are not directly related but could have been affected for EH too. Scheduling for EH is atomic w.r.t. ap->host_set->lock and once schedule for EH, normal execution path is not allowed to access the qc in whatever way. (PIO synchronization acts a bit different and will be dealt with later) This patch make ata_qc_from_tag() check whether a qc is active and owned by normal path before returning it. If conditions don't match, NULL is returned and thus access to the qc is denied. __ata_qc_from_tag() is the original ata_qc_from_tag() and is used by libata core/EH layers to access inactive/failed qc's. This change is applied only if the associated LLDD implements new EH as indicated by non-NULL ->error_handler Signed-off-by: Tejun Heo <htejun@gmail.com>
Diffstat (limited to 'drivers/scsi/libata-core.c')
-rw-r--r--drivers/scsi/libata-core.c4
1 files changed, 2 insertions, 2 deletions
diff --git a/drivers/scsi/libata-core.c b/drivers/scsi/libata-core.c
index 966abb5f423e..1c34c1427aa3 100644
--- a/drivers/scsi/libata-core.c
+++ b/drivers/scsi/libata-core.c
@@ -1001,7 +1001,7 @@ unsigned ata_exec_internal(struct ata_device *dev,
if (test_and_set_bit(tag, &ap->qactive))
BUG();
- qc = ata_qc_from_tag(ap, tag);
+ qc = __ata_qc_from_tag(ap, tag);
qc->tag = tag;
qc->scsicmd = NULL;
@@ -4042,7 +4042,7 @@ static struct ata_queued_cmd *ata_qc_new(struct ata_port *ap)
/* the last tag is reserved for internal command. */
for (i = 0; i < ATA_MAX_QUEUE - 1; i++)
if (!test_and_set_bit(i, &ap->qactive)) {
- qc = ata_qc_from_tag(ap, i);
+ qc = __ata_qc_from_tag(ap, i);
break;
}