Commit f1469785 authored by Jeff Garzik's avatar Jeff Garzik

[libata] add ata_queued_cmd completion hook

parent 14d46339
...@@ -2293,8 +2293,8 @@ struct ata_queued_cmd *ata_qc_new_init(struct ata_port *ap, ...@@ -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) void ata_qc_complete(struct ata_queued_cmd *qc, u8 drv_stat)
{ {
struct ata_port *ap = qc->ap; struct ata_port *ap = qc->ap;
struct scsi_cmnd *cmd = qc->scsicmd;
unsigned int tag, do_clear = 0; unsigned int tag, do_clear = 0;
int rc;
assert(qc != NULL); /* ata_qc_from_tag _might_ return NULL */ assert(qc != NULL); /* ata_qc_from_tag _might_ return NULL */
assert(qc->flags & ATA_QCFLAG_ACTIVE); assert(qc->flags & ATA_QCFLAG_ACTIVE);
...@@ -2302,18 +2302,14 @@ void ata_qc_complete(struct ata_queued_cmd *qc, u8 drv_stat) ...@@ -2302,18 +2302,14 @@ void ata_qc_complete(struct ata_queued_cmd *qc, u8 drv_stat)
if (likely(qc->flags & ATA_QCFLAG_SG)) if (likely(qc->flags & ATA_QCFLAG_SG))
ata_sg_clean(qc); ata_sg_clean(qc);
if (cmd) { /* call completion callback */
if (unlikely(drv_stat & (ATA_ERR | ATA_BUSY | ATA_DRQ))) { rc = qc->complete_fn(qc, drv_stat);
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); /* if callback indicates not to complete command (non-zero),
} * return immediately
*/
if (rc != 0)
return;
qc->flags = 0; qc->flags = 0;
tag = qc->tag; tag = qc->tag;
......
...@@ -335,6 +335,24 @@ static unsigned int ata_scsi_rw_xlat(struct ata_queued_cmd *qc, u8 *scsicmd) ...@@ -335,6 +335,24 @@ static unsigned int ata_scsi_rw_xlat(struct ata_queued_cmd *qc, u8 *scsicmd)
return 1; 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 * ata_scsi_translate - Translate then issue SCSI command to ATA device
* @ap: ATA port to which the command is addressed * @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, ...@@ -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->flags |= ATA_QCFLAG_SG; /* data is present; dma-map it */
} }
qc->complete_fn = ata_scsi_qc_complete;
if (xlat_func(qc, scsicmd)) if (xlat_func(qc, scsicmd))
goto err_out; goto err_out;
......
...@@ -158,7 +158,7 @@ struct ata_port; ...@@ -158,7 +158,7 @@ struct ata_port;
struct ata_queued_cmd; struct ata_queued_cmd;
/* typedefs */ /* 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 { struct ata_ioports {
unsigned long cmd_addr; unsigned long cmd_addr;
...@@ -224,7 +224,7 @@ struct ata_queued_cmd { ...@@ -224,7 +224,7 @@ struct ata_queued_cmd {
struct scatterlist *sg; struct scatterlist *sg;
ata_qc_cb_t callback; ata_qc_cb_t complete_fn;
struct completion *waiting; struct completion *waiting;
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment