diff options
author | Tejun Heo <htejun@gmail.com> | 2009-08-16 21:04:02 +0900 |
---|---|---|
committer | Jeff Garzik <jgarzik@redhat.com> | 2009-09-08 21:17:57 -0400 |
commit | 03d783bf5573ff316a8c703eed811a9a97901a8b (patch) | |
tree | a792099a0f21efcbd94f9c35ed2e11c2c2ed9d82 /drivers/ata/ahci.c | |
parent | 3e5cd1f2576c720f1d0705fdd7ba64f27e8836b7 (diff) | |
download | linux-3.10-03d783bf5573ff316a8c703eed811a9a97901a8b.tar.gz linux-3.10-03d783bf5573ff316a8c703eed811a9a97901a8b.tar.bz2 linux-3.10-03d783bf5573ff316a8c703eed811a9a97901a8b.zip |
ahci: make ahci_asus_m2a_vm_32bit_only() quirk more generic
It turns out ASUS M2A-VM isn't the only one with the 32bit DMA
problem. Make ahci_asus_m2a_vm_32bit_only() more generic using the
new dmi_get_date() and rename it to ahci_sb600_32bit_only(). Cut off
date is now pointed to by dmi_system_id->driver_data in "yyyymmdd"
format and it's now also allowed to be omitted.
Signed-off-by: Tejun Heo <tj@kernel.org>
Cc: Sandor Bodo-Merle <sbodomerle@gmail.com>
Cc: Shane Huang <shane.huang@amd.com>
Signed-off-by: Jeff Garzik <jgarzik@redhat.com>
Diffstat (limited to 'drivers/ata/ahci.c')
-rw-r--r-- | drivers/ata/ahci.c | 53 |
1 files changed, 29 insertions, 24 deletions
diff --git a/drivers/ata/ahci.c b/drivers/ata/ahci.c index 147b9be3b4d..aa03b49a9af 100644 --- a/drivers/ata/ahci.c +++ b/drivers/ata/ahci.c @@ -2647,14 +2647,18 @@ static void ahci_p5wdh_workaround(struct ata_host *host) } /* - * SB600 ahci controller on ASUS M2A-VM can't do 64bit DMA with older - * BIOS. The oldest version known to be broken is 0901 and working is - * 1501 which was released on 2007-10-26. Force 32bit DMA on anything - * older than 1501. Please read bko#9412 for more info. + * SB600 ahci controller on certain boards can't do 64bit DMA with + * older BIOS. */ -static bool ahci_asus_m2a_vm_32bit_only(struct pci_dev *pdev) +static bool ahci_sb600_32bit_only(struct pci_dev *pdev) { static const struct dmi_system_id sysids[] = { + /* + * The oldest version known to be broken is 0901 and + * working is 1501 which was released on 2007-10-26. + * Force 32bit DMA on anything older than 1501. + * Please read bko#9412 for more info. + */ { .ident = "ASUS M2A-VM", .matches = { @@ -2662,31 +2666,32 @@ static bool ahci_asus_m2a_vm_32bit_only(struct pci_dev *pdev) "ASUSTeK Computer INC."), DMI_MATCH(DMI_BOARD_NAME, "M2A-VM"), }, + .driver_data = "20071026", /* yyyymmdd */ }, { } }; - const char *cutoff_mmdd = "10/26"; - const char *date; - int year; + const struct dmi_system_id *match; + match = dmi_first_match(sysids); if (pdev->bus->number != 0 || pdev->devfn != PCI_DEVFN(0x12, 0) || - !dmi_check_system(sysids)) + !match) return false; - /* - * Argh.... both version and date are free form strings. - * Let's hope they're using the same date format across - * different versions. - */ - date = dmi_get_system_info(DMI_BIOS_DATE); - dmi_get_date(DMI_BIOS_DATE, &year, NULL, NULL); - if (date && strlen(date) >= 10 && date[2] == '/' && date[5] == '/' && - (year > 2007 || - (year == 2007 && strncmp(date, cutoff_mmdd, 5) >= 0))) - return false; + if (match->driver_data) { + int year, month, date; + char buf[9]; + + dmi_get_date(DMI_BIOS_DATE, &year, &month, &date); + snprintf(buf, sizeof(buf), "%04d%02d%02d", year, month, date); - dev_printk(KERN_WARNING, &pdev->dev, "ASUS M2A-VM: BIOS too old, " - "forcing 32bit DMA, update BIOS\n"); + if (strcmp(buf, match->driver_data) >= 0) + return false; + + dev_printk(KERN_WARNING, &pdev->dev, "%s: BIOS too old, " + "forcing 32bit DMA, update BIOS\n", match->ident); + } else + dev_printk(KERN_WARNING, &pdev->dev, "%s: this board can't " + "do 64bit DMA, forcing 32bit\n", match->ident); return true; } @@ -2901,8 +2906,8 @@ static int ahci_init_one(struct pci_dev *pdev, const struct pci_device_id *ent) if (board_id == board_ahci_sb700 && pdev->revision >= 0x40) hpriv->flags &= ~AHCI_HFLAG_IGN_SERR_INTERNAL; - /* apply ASUS M2A_VM quirk */ - if (ahci_asus_m2a_vm_32bit_only(pdev)) + /* apply sb600 32bit only quirk */ + if (ahci_sb600_32bit_only(pdev)) hpriv->flags |= AHCI_HFLAG_32BIT_ONLY; if (!(hpriv->flags & AHCI_HFLAG_NO_MSI)) |