diff options
| author | Jeff Garzik <jgarzik@pobox.com> | 2004-07-02 16:23:24 -0400 |
|---|---|---|
| committer | Jeff Garzik <jgarzik@pobox.com> | 2004-07-02 16:23:24 -0400 |
| commit | f1469785d893bc80746d017d0b663d9b11858d97 (patch) | |
| tree | 1cd2109200367059e8159f529c95a5baffaca9f6 | |
| parent | 14d463397e3358aa2ccf0bb6846381c21b36d9b9 (diff) | |
[libata] add ata_queued_cmd completion hook
| -rw-r--r-- | drivers/scsi/libata-core.c | 20 | ||||
| -rw-r--r-- | drivers/scsi/libata-scsi.c | 20 | ||||
| -rw-r--r-- | include/linux/libata.h | 4 |
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; |
