summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorJeff Garzik <jgarzik@pobox.com>2004-07-02 16:23:24 -0400
committerJeff Garzik <jgarzik@pobox.com>2004-07-02 16:23:24 -0400
commitf1469785d893bc80746d017d0b663d9b11858d97 (patch)
tree1cd2109200367059e8159f529c95a5baffaca9f6
parent14d463397e3358aa2ccf0bb6846381c21b36d9b9 (diff)
[libata] add ata_queued_cmd completion hook
-rw-r--r--drivers/scsi/libata-core.c20
-rw-r--r--drivers/scsi/libata-scsi.c20
-rw-r--r--include/linux/libata.h4
3 files changed, 30 insertions, 14 deletions
diff --git a/drivers/scsi/libata-core.c b/drivers/scsi/libata-core.c
index 402733a5d0f3..63c2982cab28 100644
--- a/drivers/scsi/libata-core.c
+++ b/drivers/scsi/libata-core.c
@@ -2293,8 +2293,8 @@ struct ata_queued_cmd *ata_qc_new_init(struct ata_port *ap,
void ata_qc_complete(struct ata_queued_cmd *qc, u8 drv_stat)
{
struct ata_port *ap = qc->ap;
- struct scsi_cmnd *cmd = qc->scsicmd;
unsigned int tag, do_clear = 0;
+ int rc;
assert(qc != NULL); /* ata_qc_from_tag _might_ return NULL */
assert(qc->flags & ATA_QCFLAG_ACTIVE);
@@ -2302,18 +2302,14 @@ void ata_qc_complete(struct ata_queued_cmd *qc, u8 drv_stat)
if (likely(qc->flags & ATA_QCFLAG_SG))
ata_sg_clean(qc);
- if (cmd) {
- if (unlikely(drv_stat & (ATA_ERR | ATA_BUSY | ATA_DRQ))) {
- if (is_atapi_taskfile(&qc->tf))
- cmd->result = SAM_STAT_CHECK_CONDITION;
- else
- ata_to_sense_error(qc);
- } else {
- cmd->result = SAM_STAT_GOOD;
- }
+ /* call completion callback */
+ rc = qc->complete_fn(qc, drv_stat);
- qc->scsidone(cmd);
- }
+ /* if callback indicates not to complete command (non-zero),
+ * return immediately
+ */
+ if (rc != 0)
+ return;
qc->flags = 0;
tag = qc->tag;
diff --git a/drivers/scsi/libata-scsi.c b/drivers/scsi/libata-scsi.c
index 1c24c0eefe0e..1e68ad8f56fc 100644
--- a/drivers/scsi/libata-scsi.c
+++ b/drivers/scsi/libata-scsi.c
@@ -335,6 +335,24 @@ static unsigned int ata_scsi_rw_xlat(struct ata_queued_cmd *qc, u8 *scsicmd)
return 1;
}
+static int ata_scsi_qc_complete(struct ata_queued_cmd *qc, u8 drv_stat)
+{
+ struct scsi_cmnd *cmd = qc->scsicmd;
+
+ if (unlikely(drv_stat & (ATA_ERR | ATA_BUSY | ATA_DRQ))) {
+ if (is_atapi_taskfile(&qc->tf))
+ cmd->result = SAM_STAT_CHECK_CONDITION;
+ else
+ ata_to_sense_error(qc);
+ } else {
+ cmd->result = SAM_STAT_GOOD;
+ }
+
+ qc->scsidone(cmd);
+
+ return 0;
+}
+
/**
* ata_scsi_translate - Translate then issue SCSI command to ATA device
* @ap: ATA port to which the command is addressed
@@ -379,6 +397,8 @@ static void ata_scsi_translate(struct ata_port *ap, struct ata_device *dev,
qc->flags |= ATA_QCFLAG_SG; /* data is present; dma-map it */
}
+ qc->complete_fn = ata_scsi_qc_complete;
+
if (xlat_func(qc, scsicmd))
goto err_out;
diff --git a/include/linux/libata.h b/include/linux/libata.h
index 6e8f0f00054e..c57be1ab010d 100644
--- a/include/linux/libata.h
+++ b/include/linux/libata.h
@@ -158,7 +158,7 @@ struct ata_port;
struct ata_queued_cmd;
/* typedefs */
-typedef void (*ata_qc_cb_t) (struct ata_queued_cmd *qc, unsigned int flags);
+typedef int (*ata_qc_cb_t) (struct ata_queued_cmd *qc, u8 drv_stat);
struct ata_ioports {
unsigned long cmd_addr;
@@ -224,7 +224,7 @@ struct ata_queued_cmd {
struct scatterlist *sg;
- ata_qc_cb_t callback;
+ ata_qc_cb_t complete_fn;
struct completion *waiting;