summaryrefslogtreecommitdiffstats
path: root/drivers/scsi/sata_sil.c
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/scsi/sata_sil.c')
-rw-r--r--drivers/scsi/sata_sil.c62
1 files changed, 51 insertions, 11 deletions
diff --git a/drivers/scsi/sata_sil.c b/drivers/scsi/sata_sil.c
index b017f85e6d6..9face3c6aa2 100644
--- a/drivers/scsi/sata_sil.c
+++ b/drivers/scsi/sata_sil.c
@@ -49,11 +49,13 @@
#define DRV_VERSION "0.9"
enum {
+ SIL_FLAG_RERR_ON_DMA_ACT = (1 << 29),
SIL_FLAG_MOD15WRITE = (1 << 30),
sil_3112 = 0,
sil_3112_m15w = 1,
- sil_3114 = 2,
+ sil_3512 = 2,
+ sil_3114 = 3,
SIL_FIFO_R0 = 0x40,
SIL_FIFO_W0 = 0x41,
@@ -90,7 +92,7 @@ static void sil_post_set_mode (struct ata_port *ap);
static const struct pci_device_id sil_pci_tbl[] = {
{ 0x1095, 0x3112, PCI_ANY_ID, PCI_ANY_ID, 0, 0, sil_3112_m15w },
{ 0x1095, 0x0240, PCI_ANY_ID, PCI_ANY_ID, 0, 0, sil_3112_m15w },
- { 0x1095, 0x3512, PCI_ANY_ID, PCI_ANY_ID, 0, 0, sil_3112 },
+ { 0x1095, 0x3512, PCI_ANY_ID, PCI_ANY_ID, 0, 0, sil_3512 },
{ 0x1095, 0x3114, PCI_ANY_ID, PCI_ANY_ID, 0, 0, sil_3114 },
{ 0x1002, 0x436e, PCI_ANY_ID, PCI_ANY_ID, 0, 0, sil_3112_m15w },
{ 0x1002, 0x4379, PCI_ANY_ID, PCI_ANY_ID, 0, 0, sil_3112_m15w },
@@ -185,7 +187,8 @@ static const struct ata_port_info sil_port_info[] = {
.mwdma_mask = 0x07, /* mwdma0-2 */
.udma_mask = 0x3f, /* udma0-5 */
.port_ops = &sil_ops,
- }, /* sil_3112_15w - keep it sync'd w/ sil_3112 */
+ },
+ /* sil_3112_15w - keep it sync'd w/ sil_3112 */
{
.sht = &sil_sht,
.host_flags = ATA_FLAG_SATA | ATA_FLAG_NO_LEGACY |
@@ -195,11 +198,24 @@ static const struct ata_port_info sil_port_info[] = {
.mwdma_mask = 0x07, /* mwdma0-2 */
.udma_mask = 0x3f, /* udma0-5 */
.port_ops = &sil_ops,
- }, /* sil_3114 */
+ },
+ /* sil_3512 */
{
.sht = &sil_sht,
.host_flags = ATA_FLAG_SATA | ATA_FLAG_NO_LEGACY |
- ATA_FLAG_SRST | ATA_FLAG_MMIO,
+ ATA_FLAG_SRST | ATA_FLAG_MMIO |
+ SIL_FLAG_RERR_ON_DMA_ACT,
+ .pio_mask = 0x1f, /* pio0-4 */
+ .mwdma_mask = 0x07, /* mwdma0-2 */
+ .udma_mask = 0x3f, /* udma0-5 */
+ .port_ops = &sil_ops,
+ },
+ /* sil_3114 */
+ {
+ .sht = &sil_sht,
+ .host_flags = ATA_FLAG_SATA | ATA_FLAG_NO_LEGACY |
+ ATA_FLAG_SRST | ATA_FLAG_MMIO |
+ SIL_FLAG_RERR_ON_DMA_ACT,
.pio_mask = 0x1f, /* pio0-4 */
.mwdma_mask = 0x07, /* mwdma0-2 */
.udma_mask = 0x3f, /* udma0-5 */
@@ -216,12 +232,13 @@ static const struct {
unsigned long scr; /* SATA control register block */
unsigned long sien; /* SATA Interrupt Enable register */
unsigned long xfer_mode;/* data transfer mode register */
+ unsigned long sfis_cfg; /* SATA FIS reception config register */
} sil_port[] = {
/* port 0 ... */
- { 0x80, 0x8A, 0x00, 0x100, 0x148, 0xb4 },
- { 0xC0, 0xCA, 0x08, 0x180, 0x1c8, 0xf4 },
- { 0x280, 0x28A, 0x200, 0x300, 0x348, 0x2b4 },
- { 0x2C0, 0x2CA, 0x208, 0x380, 0x3c8, 0x2f4 },
+ { 0x80, 0x8A, 0x00, 0x100, 0x148, 0xb4, 0x14c },
+ { 0xC0, 0xCA, 0x08, 0x180, 0x1c8, 0xf4, 0x1cc },
+ { 0x280, 0x28A, 0x200, 0x300, 0x348, 0x2b4, 0x34c },
+ { 0x2C0, 0x2CA, 0x208, 0x380, 0x3c8, 0x2f4, 0x3cc },
/* ... port 3 */
};
@@ -231,6 +248,10 @@ MODULE_LICENSE("GPL");
MODULE_DEVICE_TABLE(pci, sil_pci_tbl);
MODULE_VERSION(DRV_VERSION);
+static int slow_down = 0;
+module_param(slow_down, int, 0444);
+MODULE_PARM_DESC(slow_down, "Sledgehammer used to work around random problems, by limiting commands to 15 sectors (0=off, 1=on)");
+
static unsigned char sil_get_device_cache_line(struct pci_dev *pdev)
{
@@ -354,8 +375,10 @@ static void sil_dev_config(struct ata_port *ap, struct ata_device *dev)
}
/* limit requests to 15 sectors */
- if ((ap->flags & SIL_FLAG_MOD15WRITE) && (quirks & SIL_QUIRK_MOD15WRITE)) {
- printk(KERN_INFO "ata%u(%u): applying Seagate errata fix\n",
+ if (slow_down ||
+ ((ap->flags & SIL_FLAG_MOD15WRITE) &&
+ (quirks & SIL_QUIRK_MOD15WRITE))) {
+ printk(KERN_INFO "ata%u(%u): applying Seagate errata fix (mod15write workaround)\n",
ap->id, dev->devno);
ap->host->max_sectors = 15;
ap->host->hostt->max_sectors = 15;
@@ -465,6 +488,23 @@ static int sil_init_one (struct pci_dev *pdev, const struct pci_device_id *ent)
dev_printk(KERN_WARNING, &pdev->dev,
"cache line size not set. Driver may not function\n");
+ /* Apply R_ERR on DMA activate FIS errata workaround */
+ if (probe_ent->host_flags & SIL_FLAG_RERR_ON_DMA_ACT) {
+ int cnt;
+
+ for (i = 0, cnt = 0; i < probe_ent->n_ports; i++) {
+ tmp = readl(mmio_base + sil_port[i].sfis_cfg);
+ if ((tmp & 0x3) != 0x01)
+ continue;
+ if (!cnt)
+ dev_printk(KERN_INFO, &pdev->dev,
+ "Applying R_ERR on DMA activate "
+ "FIS errata fix\n");
+ writel(tmp & ~0x3, mmio_base + sil_port[i].sfis_cfg);
+ cnt++;
+ }
+ }
+
if (ent->driver_data == sil_3114) {
irq_mask = SIL_MASK_4PORT;