Commit a55ab496 authored by Bart Hartgers's avatar Bart Hartgers Committed by Jeff Garzik

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.htmlSigned-off-by: default avatarBart Hartgers <bart.hartgers@gmail.com>
Signed-off-by: default avatarJeff Garzik <jgarzik@redhat.com>
parent 4b7d1c05
...@@ -40,11 +40,13 @@ ...@@ -40,11 +40,13 @@
#include <linux/blkdev.h> #include <linux/blkdev.h>
#include <linux/delay.h> #include <linux/delay.h>
#include <linux/device.h> #include <linux/device.h>
#include <scsi/scsi.h>
#include <scsi/scsi_cmnd.h>
#include <scsi/scsi_host.h> #include <scsi/scsi_host.h>
#include <linux/libata.h> #include <linux/libata.h>
#define DRV_NAME "sata_via" #define DRV_NAME "sata_via"
#define DRV_VERSION "2.5" #define DRV_VERSION "2.6"
/* /*
* vt8251 is different from other sata controllers of VIA. It has two * 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); ...@@ -80,6 +82,7 @@ static int vt8251_scr_write(struct ata_link *link, unsigned int scr, u32 val);
static void svia_tf_load(struct ata_port *ap, const struct ata_taskfile *tf); static void svia_tf_load(struct ata_port *ap, const struct ata_taskfile *tf);
static void svia_noop_freeze(struct ata_port *ap); static void svia_noop_freeze(struct ata_port *ap);
static int vt6420_prereset(struct ata_link *link, unsigned long deadline); static int vt6420_prereset(struct ata_link *link, unsigned long deadline);
static void vt6420_bmdma_start(struct ata_queued_cmd *qc);
static int vt6421_pata_cable_detect(struct ata_port *ap); static int vt6421_pata_cable_detect(struct ata_port *ap);
static void vt6421_set_pio_mode(struct ata_port *ap, struct ata_device *adev); static void vt6421_set_pio_mode(struct ata_port *ap, struct ata_device *adev);
static void vt6421_set_dma_mode(struct ata_port *ap, struct ata_device *adev); static 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,6 +124,7 @@ static struct ata_port_operations vt6420_sata_ops = {
.inherits = &svia_base_ops, .inherits = &svia_base_ops,
.freeze = svia_noop_freeze, .freeze = svia_noop_freeze,
.prereset = vt6420_prereset, .prereset = vt6420_prereset,
.bmdma_start = vt6420_bmdma_start,
}; };
static struct ata_port_operations vt6421_pata_ops = { static struct ata_port_operations vt6421_pata_ops = {
...@@ -377,6 +381,17 @@ static int vt6420_prereset(struct ata_link *link, unsigned long deadline) ...@@ -377,6 +381,17 @@ static int vt6420_prereset(struct ata_link *link, unsigned long deadline)
return 0; return 0;
} }
static void vt6420_bmdma_start(struct ata_queued_cmd *qc)
{
struct ata_port *ap = qc->ap;
if ((qc->tf.command == ATA_CMD_PACKET) &&
(qc->scsicmd->sc_data_direction == DMA_TO_DEVICE)) {
/* Prevents corruption on some ATAPI burners */
ata_sff_pause(ap);
}
ata_bmdma_start(qc);
}
static int vt6421_pata_cable_detect(struct ata_port *ap) static int vt6421_pata_cable_detect(struct ata_port *ap)
{ {
struct pci_dev *pdev = to_pci_dev(ap->host->dev); struct pci_dev *pdev = to_pci_dev(ap->host->dev);
......
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