[PATCH] sata_sil: Fix FIFO PCI Bus Arbitration

Linux Kernel Mailing List <[email protected]> Fri, 25 Mar 2005 04:41:07 +0000
Newsgroups gmane.linux.kernel.commits.2-4
Message-ID <[email protected]>
ChangeSet 1.1448.129.5, 2005/03/24 23:41:07-05:00, [email protected]

	[PATCH] sata_sil: Fix FIFO PCI Bus Arbitration
	
	This patch set default values for the FIFO PCI Bus Arbitration to avoid
	data corruption. The root cause is due to our PCI bus master handling
	mismatch with the chipset PCI bridge during DMA xfer (write data to the
	device). The patch is to setup the DMA fifo threshold so that there is
	no chance for the DMA engine to change protocol. We have seen this
	problem only on one motherboard.
	
	Signed-off-by: Silicon Image Corporation <[email protected]>
	Signed-off-by: Jeff Garzik <[email protected]>



 sata_sil.c |   28 +++++++++++++++++++++++++++-
 1 files changed, 27 insertions(+), 1 deletion(-)


diff -Nru a/drivers/scsi/sata_sil.c b/drivers/scsi/sata_sil.c
--- a/drivers/scsi/sata_sil.c	2005-04-30 12:14:57 -07:00
+++ b/drivers/scsi/sata_sil.c	2005-04-30 12:14:57 -07:00
@@ -38,12 +38,21 @@
 #include <linux/libata.h>
 
 #define DRV_NAME	"sata_sil"
-#define DRV_VERSION	"0.8"
+#define DRV_VERSION	"0.9"
 
 enum {
 	sil_3112		= 0,
 	sil_3114		= 1,
 
+	SIL_FIFO_R0		= 0x40,
+	SIL_FIFO_W0		= 0x41,
+	SIL_FIFO_R1		= 0x44,
+	SIL_FIFO_W1		= 0x45,
+	SIL_FIFO_R2		= 0x240,
+	SIL_FIFO_W2		= 0x241,
+	SIL_FIFO_R3		= 0x244,
+	SIL_FIFO_W3		= 0x245,
+
 	SIL_SYSCFG		= 0x48,
 	SIL_MASK_IDE0_INT	= (1 << 22),
 	SIL_MASK_IDE1_INT	= (1 << 23),
@@ -199,6 +208,13 @@
 MODULE_DEVICE_TABLE(pci, sil_pci_tbl);
 MODULE_VERSION(DRV_VERSION);
 
+static unsigned char sil_get_device_cache_line(struct pci_dev *pdev)
+{
+	u8 cache_line = 0;
+	pci_read_config_byte(pdev, PCI_CACHE_LINE_SIZE, &cache_line);
+	return cache_line;
+}
+
 static void sil_post_set_mode (struct ata_port *ap)
 {
 	struct ata_host_set *host_set = ap->host_set;
@@ -341,6 +357,7 @@
 	unsigned int i;
 	int pci_dev_busy = 0;
 	u32 tmp, irq_mask;
+	u8 cls;
 
 	if (!printed_version++)
 		printk(KERN_DEBUG DRV_NAME " version " DRV_VERSION "\n");
@@ -401,6 +418,15 @@
 		probe_ent->port[i].scr_addr = base + sil_port[i].scr;
 		ata_std_ports(&probe_ent->port[i]);
 	}
+
+	/* Initialize FIFO PCI bus arbitration */
+	cls = sil_get_device_cache_line(pdev);
+	cls >>= 3;
+	cls++;  /* cls = (line_size/8)+1 */
+	writeb(cls, mmio_base + SIL_FIFO_R0);
+	writeb(cls, mmio_base + SIL_FIFO_W0);
+	writeb(cls, mmio_base + SIL_FIFO_R1);
+	writeb(cls, mmio_base + SIL_FIFO_W2);
 
 	if (ent->driver_data == sil_3114) {
 		irq_mask = SIL_MASK_4PORT;