ahci: make ahci_asus_m2a_vm_32bit_only() quirk more generic
authorTejun Heo <htejun@gmail.com>
Sun, 16 Aug 2009 12:04:02 +0000 (21:04 +0900)
committerJeff Garzik <jgarzik@redhat.com>
Wed, 9 Sep 2009 01:17:57 +0000 (21:17 -0400)
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>
drivers/ata/ahci.c

index 147b9be3b4d2e1dce92cb2c911eccb128c14a296..aa03b49a9af29c06fc6067ad038926524c40d18b 100644 (file)
@@ -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))