diff options
author | Albert Lee <albertcc@tw.ibm.com> | 2007-04-01 23:39:25 -0400 |
---|---|---|
committer | Jeff Garzik <jeff@garzik.org> | 2007-04-04 02:12:27 -0400 |
commit | 6f23a31d1cbe791a1ce86ffa9b23251ab0a1ef45 (patch) | |
tree | 1c8f50f7e880d156e632a96dee270cb982d96edc | |
parent | 18d6e9d51891f91af4e7351cbab3cb180bb9f430 (diff) |
libata: Limit ATAPI DMA to R/W commands only for TORiSAN DVD drives (take 3)
patch 4/4:
Limit ATAPI DMA to R/W commands only for TORiSAN DRD-N216 DVD-ROM drives
(http://bugzilla.kernel.org/show_bug.cgi?id=6710)
Signed-off-by: Albert Lee <albertcc@tw.ibm.com>
Signed-off-by: Jeff Garzik <jeff@garzik.org>
-rw-r--r-- | drivers/ata/libata-core.c | 27 | ||||
-rw-r--r-- | include/linux/libata.h | 1 |
2 files changed, 27 insertions, 1 deletions
diff --git a/drivers/ata/libata-core.c b/drivers/ata/libata-core.c index 84f6f8575966..cf2338cbe4ea 100644 --- a/drivers/ata/libata-core.c +++ b/drivers/ata/libata-core.c | |||
@@ -1787,6 +1787,10 @@ int ata_dev_configure(struct ata_device *dev) | |||
1787 | if (ata_device_blacklisted(dev) & ATA_HORKAGE_MAX_SEC_128) | 1787 | if (ata_device_blacklisted(dev) & ATA_HORKAGE_MAX_SEC_128) |
1788 | dev->max_sectors = min(ATA_MAX_SECTORS_128, dev->max_sectors); | 1788 | dev->max_sectors = min(ATA_MAX_SECTORS_128, dev->max_sectors); |
1789 | 1789 | ||
1790 | /* limit ATAPI DMA to R/W commands only */ | ||
1791 | if (ata_device_blacklisted(dev) & ATA_HORKAGE_DMA_RW_ONLY) | ||
1792 | dev->horkage |= ATA_HORKAGE_DMA_RW_ONLY; | ||
1793 | |||
1790 | if (ap->ops->dev_config) | 1794 | if (ap->ops->dev_config) |
1791 | ap->ops->dev_config(ap, dev); | 1795 | ap->ops->dev_config(ap, dev); |
1792 | 1796 | ||
@@ -3356,7 +3360,8 @@ static const struct ata_blacklist_entry ata_device_blacklist [] = { | |||
3356 | { "SAMSUNG CD-ROM SN-124","N001", ATA_HORKAGE_NODMA }, | 3360 | { "SAMSUNG CD-ROM SN-124","N001", ATA_HORKAGE_NODMA }, |
3357 | 3361 | ||
3358 | /* Weird ATAPI devices */ | 3362 | /* Weird ATAPI devices */ |
3359 | { "TORiSAN DVD-ROM DRD-N216", NULL, ATA_HORKAGE_MAX_SEC_128 }, | 3363 | { "TORiSAN DVD-ROM DRD-N216", NULL, ATA_HORKAGE_MAX_SEC_128 | |
3364 | ATA_HORKAGE_DMA_RW_ONLY }, | ||
3360 | 3365 | ||
3361 | /* Devices we expect to fail diagnostics */ | 3366 | /* Devices we expect to fail diagnostics */ |
3362 | 3367 | ||
@@ -3680,6 +3685,26 @@ int ata_check_atapi_dma(struct ata_queued_cmd *qc) | |||
3680 | struct ata_port *ap = qc->ap; | 3685 | struct ata_port *ap = qc->ap; |
3681 | int rc = 0; /* Assume ATAPI DMA is OK by default */ | 3686 | int rc = 0; /* Assume ATAPI DMA is OK by default */ |
3682 | 3687 | ||
3688 | /* some drives can only do ATAPI DMA on read/write */ | ||
3689 | if (unlikely(qc->dev->horkage & ATA_HORKAGE_DMA_RW_ONLY)) { | ||
3690 | struct scsi_cmnd *cmd = qc->scsicmd; | ||
3691 | u8 *scsicmd = cmd->cmnd; | ||
3692 | |||
3693 | switch (scsicmd[0]) { | ||
3694 | case READ_10: | ||
3695 | case WRITE_10: | ||
3696 | case READ_12: | ||
3697 | case WRITE_12: | ||
3698 | case READ_6: | ||
3699 | case WRITE_6: | ||
3700 | /* atapi dma maybe ok */ | ||
3701 | break; | ||
3702 | default: | ||
3703 | /* turn off atapi dma */ | ||
3704 | return 1; | ||
3705 | } | ||
3706 | } | ||
3707 | |||
3683 | if (ap->ops->check_atapi_dma) | 3708 | if (ap->ops->check_atapi_dma) |
3684 | rc = ap->ops->check_atapi_dma(qc); | 3709 | rc = ap->ops->check_atapi_dma(qc); |
3685 | 3710 | ||
diff --git a/include/linux/libata.h b/include/linux/libata.h index c04aec360406..0cfbcb6f08eb 100644 --- a/include/linux/libata.h +++ b/include/linux/libata.h | |||
@@ -312,6 +312,7 @@ enum { | |||
312 | ATA_HORKAGE_NODMA = (1 << 1), /* DMA problems */ | 312 | ATA_HORKAGE_NODMA = (1 << 1), /* DMA problems */ |
313 | ATA_HORKAGE_NONCQ = (1 << 2), /* Don't use NCQ */ | 313 | ATA_HORKAGE_NONCQ = (1 << 2), /* Don't use NCQ */ |
314 | ATA_HORKAGE_MAX_SEC_128 = (1 << 3), /* Limit max sects to 128 */ | 314 | ATA_HORKAGE_MAX_SEC_128 = (1 << 3), /* Limit max sects to 128 */ |
315 | ATA_HORKAGE_DMA_RW_ONLY = (1 << 4), /* ATAPI DMA for RW only */ | ||
315 | }; | 316 | }; |
316 | 317 | ||
317 | enum hsm_task_states { | 318 | enum hsm_task_states { |