aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/ata/sata_via.c
diff options
context:
space:
mode:
authorBart Hartgers <bart.hartgers@gmail.com>2010-02-14 07:04:50 -0500
committerJeff Garzik <jgarzik@redhat.com>2010-03-01 15:19:21 -0500
commita55ab496ea9c820b7192c15ef1fbf3291edfe638 (patch)
tree76b835a26c4aaaa2d7e970e76df7b95c0fdcc932 /drivers/ata/sata_via.c
parent4b7d1c0509d0d07edc731f990791dc5518e51617 (diff)
sata_via: Delay on vt6420 when starting ATAPI DMA write
When writing a disc on certain lite-on dvd-writers (also rebadged as optiarc/LG/...) connected to a vt6420, the ATAPI CDB ends up in the datastream and on the disc, causing silent corruption. Delaying between sending the CDB and starting DMA seems to prevent this. I do not know if there are burners that do not suffer from this, but the patch should be safe for those as well. There are many reports of this issue, but AFAICT no solution was found before. For example: http://lkml.indiana.edu/hypermail/linux/kernel/0802.3/0561.html Signed-off-by: Bart Hartgers <bart.hartgers@gmail.com> Signed-off-by: Jeff Garzik <jgarzik@redhat.com>
Diffstat (limited to 'drivers/ata/sata_via.c')
-rw-r--r--drivers/ata/sata_via.c17
1 files changed, 16 insertions, 1 deletions
diff --git a/drivers/ata/sata_via.c b/drivers/ata/sata_via.c
index 2a17fa375164..08f65492cc81 100644
--- a/drivers/ata/sata_via.c
+++ b/drivers/ata/sata_via.c
@@ -40,11 +40,13 @@
40#include <linux/blkdev.h> 40#include <linux/blkdev.h>
41#include <linux/delay.h> 41#include <linux/delay.h>
42#include <linux/device.h> 42#include <linux/device.h>
43#include <scsi/scsi.h>
44#include <scsi/scsi_cmnd.h>
43#include <scsi/scsi_host.h> 45#include <scsi/scsi_host.h>
44#include <linux/libata.h> 46#include <linux/libata.h>
45 47
46#define DRV_NAME "sata_via" 48#define DRV_NAME "sata_via"
47#define DRV_VERSION "2.5" 49#define DRV_VERSION "2.6"
48 50
49/* 51/*
50 * vt8251 is different from other sata controllers of VIA. It has two 52 * vt8251 is different from other sata controllers of VIA. It has two
@@ -80,6 +82,7 @@ static int vt8251_scr_write(struct ata_link *link, unsigned int scr, u32 val);
80static void svia_tf_load(struct ata_port *ap, const struct ata_taskfile *tf); 82static void svia_tf_load(struct ata_port *ap, const struct ata_taskfile *tf);
81static void svia_noop_freeze(struct ata_port *ap); 83static void svia_noop_freeze(struct ata_port *ap);
82static int vt6420_prereset(struct ata_link *link, unsigned long deadline); 84static int vt6420_prereset(struct ata_link *link, unsigned long deadline);
85static void vt6420_bmdma_start(struct ata_queued_cmd *qc);
83static int vt6421_pata_cable_detect(struct ata_port *ap); 86static int vt6421_pata_cable_detect(struct ata_port *ap);
84static void vt6421_set_pio_mode(struct ata_port *ap, struct ata_device *adev); 87static void vt6421_set_pio_mode(struct ata_port *ap, struct ata_device *adev);
85static void vt6421_set_dma_mode(struct ata_port *ap, struct ata_device *adev); 88static void vt6421_set_dma_mode(struct ata_port *ap, struct ata_device *adev);
@@ -121,6 +124,7 @@ static struct ata_port_operations vt6420_sata_ops = {
121 .inherits = &svia_base_ops, 124 .inherits = &svia_base_ops,
122 .freeze = svia_noop_freeze, 125 .freeze = svia_noop_freeze,
123 .prereset = vt6420_prereset, 126 .prereset = vt6420_prereset,
127 .bmdma_start = vt6420_bmdma_start,
124}; 128};
125 129
126static struct ata_port_operations vt6421_pata_ops = { 130static struct ata_port_operations vt6421_pata_ops = {
@@ -377,6 +381,17 @@ static int vt6420_prereset(struct ata_link *link, unsigned long deadline)
377 return 0; 381 return 0;
378} 382}
379 383
384static void vt6420_bmdma_start(struct ata_queued_cmd *qc)
385{
386 struct ata_port *ap = qc->ap;
387 if ((qc->tf.command == ATA_CMD_PACKET) &&
388 (qc->scsicmd->sc_data_direction == DMA_TO_DEVICE)) {
389 /* Prevents corruption on some ATAPI burners */
390 ata_sff_pause(ap);
391 }
392 ata_bmdma_start(qc);
393}
394
380static int vt6421_pata_cable_detect(struct ata_port *ap) 395static int vt6421_pata_cable_detect(struct ata_port *ap)
381{ 396{
382 struct pci_dev *pdev = to_pci_dev(ap->host->dev); 397 struct pci_dev *pdev = to_pci_dev(ap->host->dev);