[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;