Commit 160ea20b authored by Eric Wong's avatar Eric Wong Committed by Jeff Garzik

[libata sata_sil] cleaner, better version of errata workarounds

No longer unfairly punishes non-errata Seagate and Maxtor drives.
parent 7dd3d2d7
...@@ -64,6 +64,9 @@ enum { ...@@ -64,6 +64,9 @@ enum {
SIL_IDE3_CTL = 0x2CA, SIL_IDE3_CTL = 0x2CA,
SIL_IDE3_BMDMA = 0x208, SIL_IDE3_BMDMA = 0x208,
SIL_IDE3_SCR = 0x380, SIL_IDE3_SCR = 0x380,
SIL_QUIRK_MOD15WRITE = (1 << 0),
SIL_QUIRK_UDMA5MAX = (1 << 1),
}; };
static void sil_set_piomode (struct ata_port *ap, struct ata_device *adev, static void sil_set_piomode (struct ata_port *ap, struct ata_device *adev,
...@@ -82,6 +85,27 @@ static struct pci_device_id sil_pci_tbl[] = { ...@@ -82,6 +85,27 @@ static struct pci_device_id sil_pci_tbl[] = {
{ } /* terminate list */ { } /* terminate list */
}; };
/* TODO firmware versions should be added - eric */
struct sil_drivelist {
const char * product;
unsigned int quirk;
} sil_blacklist [] = {
{ "ST320012AS", SIL_QUIRK_MOD15WRITE },
{ "ST330013AS", SIL_QUIRK_MOD15WRITE },
{ "ST340017AS", SIL_QUIRK_MOD15WRITE },
{ "ST360015AS", SIL_QUIRK_MOD15WRITE },
{ "ST380023AS", SIL_QUIRK_MOD15WRITE },
{ "ST3120023AS", SIL_QUIRK_MOD15WRITE },
{ "ST340014ASL", SIL_QUIRK_MOD15WRITE },
{ "ST360014ASL", SIL_QUIRK_MOD15WRITE },
{ "ST380011ASL", SIL_QUIRK_MOD15WRITE },
{ "ST3120022ASL", SIL_QUIRK_MOD15WRITE },
{ "ST3160021ASL", SIL_QUIRK_MOD15WRITE },
{ "Maxtor 4D060H3", SIL_QUIRK_UDMA5MAX },
{ }
};
static struct pci_driver sil_pci_driver = { static struct pci_driver sil_pci_driver = {
.name = DRV_NAME, .name = DRV_NAME,
.id_table = sil_pci_tbl, .id_table = sil_pci_tbl,
...@@ -207,34 +231,52 @@ static void sil_scr_write (struct ata_port *ap, unsigned int sc_reg, u32 val) ...@@ -207,34 +231,52 @@ static void sil_scr_write (struct ata_port *ap, unsigned int sc_reg, u32 val)
* information on these errata, I will create a more exhaustive * information on these errata, I will create a more exhaustive
* list, and apply the fixups to only the specific * list, and apply the fixups to only the specific
* devices/hosts/firmwares that need it. * devices/hosts/firmwares that need it.
*
* 20040111 - Seagate drives affected by the Mod15Write bug are blacklisted
* The Maxtor quirk is in the blacklist, but I'm keeping the original
* pessimistic fix for the following reasons:
* - There seems to be less info on it, only one device gleaned off the
* Windows driver, maybe only one is affected. More info would be greatly
* appreciated.
* - But then again UDMA5 is hardly anything to complain about
*/ */
static void sil_dev_config(struct ata_port *ap, struct ata_device *dev) static void sil_dev_config(struct ata_port *ap, struct ata_device *dev)
{ {
unsigned int n, quirks = 0;
u32 class_rev = 0;
const char *s = &dev->product[0]; const char *s = &dev->product[0];
unsigned int len = strnlen(s, sizeof(dev->product)); unsigned int len = strnlen(s, sizeof(dev->product));
pci_read_config_dword(ap->host_set->pdev, PCI_CLASS_REVISION, &class_rev);
class_rev &= 0xff;
/* ATAPI specifies that empty space is blank-filled; remove blanks */ /* ATAPI specifies that empty space is blank-filled; remove blanks */
while ((len > 0) && (s[len - 1] == ' ')) while ((len > 0) && (s[len - 1] == ' '))
len--; len--;
/* limit to udma5 */ for (n = 0; sil_blacklist[n].product; n++)
if (!memcmp(s, "Maxtor ", 7)) { if (!memcmp(sil_blacklist[n].product, s,
printk(KERN_INFO "ata%u(%u): applying pessimistic Maxtor errata fix\n", strlen(sil_blacklist[n].product))) {
ap->id, dev->devno); quirks = sil_blacklist[n].quirk;
ap->udma_mask &= ATA_UDMA5; break;
return;
} }
/* limit requests to 15 sectors */ /* limit requests to 15 sectors */
if ((len > 4) && (!memcmp(s, "ST", 2))) { if ((class_rev <= 0x01) && (quirks & SIL_QUIRK_MOD15WRITE)) {
if ((!memcmp(s + len - 2, "AS", 2)) || printk(KERN_INFO "ata%u(%u): applying Seagate errata fix\n",
(!memcmp(s + len - 3, "ASL", 3))) {
printk(KERN_INFO "ata%u(%u): applying pessimistic Seagate errata fix\n",
ap->id, dev->devno); ap->id, dev->devno);
ap->host->max_sectors = 15; ap->host->max_sectors = 15;
ap->host->hostt->max_sectors = 15; ap->host->hostt->max_sectors = 15;
return; return;
} }
/* limit to udma5 */
/* is this for (class_rev <= 0x01) only, too? */
if (quirks & SIL_QUIRK_UDMA5MAX) {
printk(KERN_INFO "ata%u(%u): applying Maxtor errata fix %s\n",
ap->id, dev->devno, s);
ap->udma_mask &= ATA_UDMA5;
return;
} }
} }
......
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