diff options
| -rw-r--r-- | drivers/scsi/libata-core.c | 17 | ||||
| -rw-r--r-- | drivers/scsi/libata-scsi.c | 5 | ||||
| -rw-r--r-- | drivers/scsi/libata.h | 1 | ||||
| -rw-r--r-- | include/linux/libata.h | 2 |
4 files changed, 25 insertions, 0 deletions
diff --git a/drivers/scsi/libata-core.c b/drivers/scsi/libata-core.c index bc846b86f225..5fdb285cd87d 100644 --- a/drivers/scsi/libata-core.c +++ b/drivers/scsi/libata-core.c @@ -1919,7 +1919,24 @@ static void ata_fill_sg(struct ata_queued_cmd *qc) if (idx) ap->prd[idx - 1].flags_len |= cpu_to_le32(ATA_PRD_EOT); } +/** + * ata_check_atapi_dma - Check whether ATAPI DMA can be supported + * @qc: Metadata associated with taskfile to check + * + * LOCKING: + * RETURNS: 0 when ATAPI DMA can be used + * nonzero otherwise + */ +int ata_check_atapi_dma(struct ata_queued_cmd *qc) +{ + struct ata_port *ap = qc->ap; + int rc = 0; /* Assume ATAPI DMA is OK by default */ + + if (ap->ops->check_atapi_dma) + rc = ap->ops->check_atapi_dma(qc); + return rc; +} /** * ata_qc_prep - Prepare taskfile for submission * @qc: Metadata associated with taskfile to be prepared diff --git a/drivers/scsi/libata-scsi.c b/drivers/scsi/libata-scsi.c index 36320e8a3e5b..1b8bc9bdd7de 100644 --- a/drivers/scsi/libata-scsi.c +++ b/drivers/scsi/libata-scsi.c @@ -1294,6 +1294,11 @@ static unsigned int atapi_xlat(struct ata_queued_cmd *qc, u8 *scsicmd) int using_pio = (dev->flags & ATA_DFLAG_PIO); int nodata = (cmd->sc_data_direction == SCSI_DATA_NONE); + if (!using_pio) + /* Check whether ATAPI DMA is safe */ + if (ata_check_atapi_dma(qc)) + using_pio = 1; + memcpy(&qc->cdb, scsicmd, qc->ap->cdb_len); qc->complete_fn = atapi_qc_complete; diff --git a/drivers/scsi/libata.h b/drivers/scsi/libata.h index f54c93152e09..bd67a21becf5 100644 --- a/drivers/scsi/libata.h +++ b/drivers/scsi/libata.h @@ -38,6 +38,7 @@ struct ata_scsi_args { extern struct ata_queued_cmd *ata_qc_new_init(struct ata_port *ap, struct ata_device *dev); extern int ata_qc_issue(struct ata_queued_cmd *qc); +extern int ata_check_atapi_dma(struct ata_queued_cmd *qc); extern void ata_dev_select(struct ata_port *ap, unsigned int device, unsigned int wait, unsigned int can_sleep); extern void ata_tf_to_host_nolock(struct ata_port *ap, struct ata_taskfile *tf); diff --git a/include/linux/libata.h b/include/linux/libata.h index 95a7b0ddb096..a436be7d78aa 100644 --- a/include/linux/libata.h +++ b/include/linux/libata.h @@ -339,6 +339,8 @@ struct ata_port_operations { void (*phy_reset) (struct ata_port *ap); void (*post_set_mode) (struct ata_port *ap); + int (*check_atapi_dma) (struct ata_queued_cmd *qc); + void (*bmdma_setup) (struct ata_queued_cmd *qc); void (*bmdma_start) (struct ata_queued_cmd *qc); |
