summaryrefslogtreecommitdiffstats
path: root/drivers/ata/sata_via.c
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/ata/sata_via.c')
-rw-r--r--drivers/ata/sata_via.c35
1 files changed, 31 insertions, 4 deletions
diff --git a/drivers/ata/sata_via.c b/drivers/ata/sata_via.c
index 08f65492cc8..4730c42a5ee 100644
--- a/drivers/ata/sata_via.c
+++ b/drivers/ata/sata_via.c
@@ -308,7 +308,7 @@ static void svia_noop_freeze(struct ata_port *ap)
* certain way. Leave it alone and just clear pending IRQ.
*/
ap->ops->sff_check_status(ap);
- ata_sff_irq_clear(ap);
+ ata_bmdma_irq_clear(ap);
}
/**
@@ -463,7 +463,7 @@ static int vt6420_prepare_host(struct pci_dev *pdev, struct ata_host **r_host)
struct ata_host *host;
int rc;
- rc = ata_pci_sff_prepare_host(pdev, ppi, &host);
+ rc = ata_pci_bmdma_prepare_host(pdev, ppi, &host);
if (rc)
return rc;
*r_host = host;
@@ -520,7 +520,7 @@ static int vt8251_prepare_host(struct pci_dev *pdev, struct ata_host **r_host)
struct ata_host *host;
int i, rc;
- rc = ata_pci_sff_prepare_host(pdev, ppi, &host);
+ rc = ata_pci_bmdma_prepare_host(pdev, ppi, &host);
if (rc)
return rc;
*r_host = host;
@@ -575,6 +575,33 @@ static void svia_configure(struct pci_dev *pdev)
tmp8 |= NATIVE_MODE_ALL;
pci_write_config_byte(pdev, SATA_NATIVE_MODE, tmp8);
}
+
+ /*
+ * vt6421 has problems talking to some drives. The following
+ * is the fix from Joseph Chan <JosephChan@via.com.tw>.
+ *
+ * When host issues HOLD, device may send up to 20DW of data
+ * before acknowledging it with HOLDA and the host should be
+ * able to buffer them in FIFO. Unfortunately, some WD drives
+ * send upto 40DW before acknowledging HOLD and, in the
+ * default configuration, this ends up overflowing vt6421's
+ * FIFO, making the controller abort the transaction with
+ * R_ERR.
+ *
+ * Rx52[2] is the internal 128DW FIFO Flow control watermark
+ * adjusting mechanism enable bit and the default value 0
+ * means host will issue HOLD to device when the left FIFO
+ * size goes below 32DW. Setting it to 1 makes the watermark
+ * 64DW.
+ *
+ * https://bugzilla.kernel.org/show_bug.cgi?id=15173
+ * http://article.gmane.org/gmane.linux.ide/46352
+ */
+ if (pdev->device == 0x3249) {
+ pci_read_config_byte(pdev, 0x52, &tmp8);
+ tmp8 |= 1 << 2;
+ pci_write_config_byte(pdev, 0x52, tmp8);
+ }
}
static int svia_init_one(struct pci_dev *pdev, const struct pci_device_id *ent)
@@ -628,7 +655,7 @@ static int svia_init_one(struct pci_dev *pdev, const struct pci_device_id *ent)
svia_configure(pdev);
pci_set_master(pdev);
- return ata_host_activate(host, pdev->irq, ata_sff_interrupt,
+ return ata_host_activate(host, pdev->irq, ata_bmdma_interrupt,
IRQF_SHARED, &svia_sht);
}