diff options
-rw-r--r-- | drivers/ata/ahci.c | 52 | ||||
-rw-r--r-- | drivers/firmware/dmi_scan.c | 1 |
2 files changed, 51 insertions, 2 deletions
diff --git a/drivers/ata/ahci.c b/drivers/ata/ahci.c index 2141a31f176b..15a23031833f 100644 --- a/drivers/ata/ahci.c +++ b/drivers/ata/ahci.c | |||
@@ -431,8 +431,7 @@ static const struct ata_port_info ahci_port_info[] = { | |||
431 | [board_ahci_sb600] = | 431 | [board_ahci_sb600] = |
432 | { | 432 | { |
433 | AHCI_HFLAGS (AHCI_HFLAG_IGN_SERR_INTERNAL | | 433 | AHCI_HFLAGS (AHCI_HFLAG_IGN_SERR_INTERNAL | |
434 | AHCI_HFLAG_32BIT_ONLY | AHCI_HFLAG_NO_MSI | | 434 | AHCI_HFLAG_NO_MSI | AHCI_HFLAG_SECT255), |
435 | AHCI_HFLAG_SECT255), | ||
436 | .flags = AHCI_FLAG_COMMON, | 435 | .flags = AHCI_FLAG_COMMON, |
437 | .pio_mask = ATA_PIO4, | 436 | .pio_mask = ATA_PIO4, |
438 | .udma_mask = ATA_UDMA6, | 437 | .udma_mask = ATA_UDMA6, |
@@ -2585,6 +2584,51 @@ static void ahci_p5wdh_workaround(struct ata_host *host) | |||
2585 | } | 2584 | } |
2586 | } | 2585 | } |
2587 | 2586 | ||
2587 | /* | ||
2588 | * SB600 ahci controller on ASUS M2A-VM can't do 64bit DMA with older | ||
2589 | * BIOS. The oldest version known to be broken is 0901 and working is | ||
2590 | * 1501 which was released on 2007-10-26. Force 32bit DMA on anything | ||
2591 | * older than 1501. Please read bko#9412 for more info. | ||
2592 | */ | ||
2593 | static bool ahci_asus_m2a_vm_32bit_only(struct pci_dev *pdev) | ||
2594 | { | ||
2595 | static const struct dmi_system_id sysids[] = { | ||
2596 | { | ||
2597 | .ident = "ASUS M2A-VM", | ||
2598 | .matches = { | ||
2599 | DMI_MATCH(DMI_BOARD_VENDOR, | ||
2600 | "ASUSTeK Computer INC."), | ||
2601 | DMI_MATCH(DMI_BOARD_NAME, "M2A-VM"), | ||
2602 | }, | ||
2603 | }, | ||
2604 | { } | ||
2605 | }; | ||
2606 | const char *cutoff_mmdd = "10/26"; | ||
2607 | const char *date; | ||
2608 | int year; | ||
2609 | |||
2610 | if (pdev->bus->number != 0 || pdev->devfn != PCI_DEVFN(0x12, 0) || | ||
2611 | !dmi_check_system(sysids)) | ||
2612 | return false; | ||
2613 | |||
2614 | /* | ||
2615 | * Argh.... both version and date are free form strings. | ||
2616 | * Let's hope they're using the same date format across | ||
2617 | * different versions. | ||
2618 | */ | ||
2619 | date = dmi_get_system_info(DMI_BIOS_DATE); | ||
2620 | year = dmi_get_year(DMI_BIOS_DATE); | ||
2621 | if (date && strlen(date) >= 10 && date[2] == '/' && date[5] == '/' && | ||
2622 | (year > 2007 || | ||
2623 | (year == 2007 && strncmp(date, cutoff_mmdd, 5) >= 0))) | ||
2624 | return false; | ||
2625 | |||
2626 | dev_printk(KERN_WARNING, &pdev->dev, "ASUS M2A-VM: BIOS too old, " | ||
2627 | "forcing 32bit DMA, update BIOS\n"); | ||
2628 | |||
2629 | return true; | ||
2630 | } | ||
2631 | |||
2588 | static bool ahci_broken_system_poweroff(struct pci_dev *pdev) | 2632 | static bool ahci_broken_system_poweroff(struct pci_dev *pdev) |
2589 | { | 2633 | { |
2590 | static const struct dmi_system_id broken_systems[] = { | 2634 | static const struct dmi_system_id broken_systems[] = { |
@@ -2745,6 +2789,10 @@ static int ahci_init_one(struct pci_dev *pdev, const struct pci_device_id *ent) | |||
2745 | if (board_id == board_ahci_sb700 && pdev->revision >= 0x40) | 2789 | if (board_id == board_ahci_sb700 && pdev->revision >= 0x40) |
2746 | hpriv->flags &= ~AHCI_HFLAG_IGN_SERR_INTERNAL; | 2790 | hpriv->flags &= ~AHCI_HFLAG_IGN_SERR_INTERNAL; |
2747 | 2791 | ||
2792 | /* apply ASUS M2A_VM quirk */ | ||
2793 | if (ahci_asus_m2a_vm_32bit_only(pdev)) | ||
2794 | hpriv->flags |= AHCI_HFLAG_32BIT_ONLY; | ||
2795 | |||
2748 | if (!(hpriv->flags & AHCI_HFLAG_NO_MSI)) | 2796 | if (!(hpriv->flags & AHCI_HFLAG_NO_MSI)) |
2749 | pci_enable_msi(pdev); | 2797 | pci_enable_msi(pdev); |
2750 | 2798 | ||
diff --git a/drivers/firmware/dmi_scan.c b/drivers/firmware/dmi_scan.c index 5f1b5400d96a..24c84ae81527 100644 --- a/drivers/firmware/dmi_scan.c +++ b/drivers/firmware/dmi_scan.c | |||
@@ -596,6 +596,7 @@ int dmi_get_year(int field) | |||
596 | 596 | ||
597 | return year; | 597 | return year; |
598 | } | 598 | } |
599 | EXPORT_SYMBOL(dmi_get_year); | ||
599 | 600 | ||
600 | /** | 601 | /** |
601 | * dmi_walk - Walk the DMI table and get called back for every record | 602 | * dmi_walk - Walk the DMI table and get called back for every record |