diff options
Diffstat (limited to 'drivers/ata/ahci.c')
-rw-r--r-- | drivers/ata/ahci.c | 143 |
1 files changed, 106 insertions, 37 deletions
diff --git a/drivers/ata/ahci.c b/drivers/ata/ahci.c index fe3eba5d6b3e..d4cd9c203314 100644 --- a/drivers/ata/ahci.c +++ b/drivers/ata/ahci.c | |||
@@ -329,10 +329,24 @@ static ssize_t ahci_activity_store(struct ata_device *dev, | |||
329 | enum sw_activity val); | 329 | enum sw_activity val); |
330 | static void ahci_init_sw_activity(struct ata_link *link); | 330 | static void ahci_init_sw_activity(struct ata_link *link); |
331 | 331 | ||
332 | static ssize_t ahci_show_host_caps(struct device *dev, | ||
333 | struct device_attribute *attr, char *buf); | ||
334 | static ssize_t ahci_show_host_version(struct device *dev, | ||
335 | struct device_attribute *attr, char *buf); | ||
336 | static ssize_t ahci_show_port_cmd(struct device *dev, | ||
337 | struct device_attribute *attr, char *buf); | ||
338 | |||
339 | DEVICE_ATTR(ahci_host_caps, S_IRUGO, ahci_show_host_caps, NULL); | ||
340 | DEVICE_ATTR(ahci_host_version, S_IRUGO, ahci_show_host_version, NULL); | ||
341 | DEVICE_ATTR(ahci_port_cmd, S_IRUGO, ahci_show_port_cmd, NULL); | ||
342 | |||
332 | static struct device_attribute *ahci_shost_attrs[] = { | 343 | static struct device_attribute *ahci_shost_attrs[] = { |
333 | &dev_attr_link_power_management_policy, | 344 | &dev_attr_link_power_management_policy, |
334 | &dev_attr_em_message_type, | 345 | &dev_attr_em_message_type, |
335 | &dev_attr_em_message, | 346 | &dev_attr_em_message, |
347 | &dev_attr_ahci_host_caps, | ||
348 | &dev_attr_ahci_host_version, | ||
349 | &dev_attr_ahci_port_cmd, | ||
336 | NULL | 350 | NULL |
337 | }; | 351 | }; |
338 | 352 | ||
@@ -539,6 +553,12 @@ static const struct pci_device_id ahci_pci_tbl[] = { | |||
539 | { PCI_VDEVICE(ATI, 0x4394), board_ahci_sb700 }, /* ATI SB700/800 */ | 553 | { PCI_VDEVICE(ATI, 0x4394), board_ahci_sb700 }, /* ATI SB700/800 */ |
540 | { PCI_VDEVICE(ATI, 0x4395), board_ahci_sb700 }, /* ATI SB700/800 */ | 554 | { PCI_VDEVICE(ATI, 0x4395), board_ahci_sb700 }, /* ATI SB700/800 */ |
541 | 555 | ||
556 | /* AMD */ | ||
557 | { PCI_VDEVICE(AMD, 0x7800), board_ahci }, /* AMD SB900 */ | ||
558 | /* AMD is using RAID class only for ahci controllers */ | ||
559 | { PCI_VENDOR_ID_AMD, PCI_ANY_ID, PCI_ANY_ID, PCI_ANY_ID, | ||
560 | PCI_CLASS_STORAGE_RAID << 8, 0xffffff, board_ahci }, | ||
561 | |||
542 | /* VIA */ | 562 | /* VIA */ |
543 | { PCI_VDEVICE(VIA, 0x3349), board_ahci_vt8251 }, /* VIA VT8251 */ | 563 | { PCI_VDEVICE(VIA, 0x3349), board_ahci_vt8251 }, /* VIA VT8251 */ |
544 | { PCI_VDEVICE(VIA, 0x6287), board_ahci_vt8251 }, /* VIA VT8251 */ | 564 | { PCI_VDEVICE(VIA, 0x6287), board_ahci_vt8251 }, /* VIA VT8251 */ |
@@ -702,6 +722,36 @@ static void ahci_enable_ahci(void __iomem *mmio) | |||
702 | WARN_ON(1); | 722 | WARN_ON(1); |
703 | } | 723 | } |
704 | 724 | ||
725 | static ssize_t ahci_show_host_caps(struct device *dev, | ||
726 | struct device_attribute *attr, char *buf) | ||
727 | { | ||
728 | struct Scsi_Host *shost = class_to_shost(dev); | ||
729 | struct ata_port *ap = ata_shost_to_port(shost); | ||
730 | struct ahci_host_priv *hpriv = ap->host->private_data; | ||
731 | |||
732 | return sprintf(buf, "%x\n", hpriv->cap); | ||
733 | } | ||
734 | |||
735 | static ssize_t ahci_show_host_version(struct device *dev, | ||
736 | struct device_attribute *attr, char *buf) | ||
737 | { | ||
738 | struct Scsi_Host *shost = class_to_shost(dev); | ||
739 | struct ata_port *ap = ata_shost_to_port(shost); | ||
740 | void __iomem *mmio = ap->host->iomap[AHCI_PCI_BAR]; | ||
741 | |||
742 | return sprintf(buf, "%x\n", readl(mmio + HOST_VERSION)); | ||
743 | } | ||
744 | |||
745 | static ssize_t ahci_show_port_cmd(struct device *dev, | ||
746 | struct device_attribute *attr, char *buf) | ||
747 | { | ||
748 | struct Scsi_Host *shost = class_to_shost(dev); | ||
749 | struct ata_port *ap = ata_shost_to_port(shost); | ||
750 | void __iomem *port_mmio = ahci_port_base(ap); | ||
751 | |||
752 | return sprintf(buf, "%x\n", readl(port_mmio + PORT_CMD)); | ||
753 | } | ||
754 | |||
705 | /** | 755 | /** |
706 | * ahci_save_initial_config - Save and fixup initial config values | 756 | * ahci_save_initial_config - Save and fixup initial config values |
707 | * @pdev: target PCI device | 757 | * @pdev: target PCI device |
@@ -1584,7 +1634,7 @@ static void ahci_fill_cmd_slot(struct ahci_port_priv *pp, unsigned int tag, | |||
1584 | pp->cmd_slot[tag].tbl_addr_hi = cpu_to_le32((cmd_tbl_dma >> 16) >> 16); | 1634 | pp->cmd_slot[tag].tbl_addr_hi = cpu_to_le32((cmd_tbl_dma >> 16) >> 16); |
1585 | } | 1635 | } |
1586 | 1636 | ||
1587 | static int ahci_kick_engine(struct ata_port *ap, int force_restart) | 1637 | static int ahci_kick_engine(struct ata_port *ap) |
1588 | { | 1638 | { |
1589 | void __iomem *port_mmio = ahci_port_base(ap); | 1639 | void __iomem *port_mmio = ahci_port_base(ap); |
1590 | struct ahci_host_priv *hpriv = ap->host->private_data; | 1640 | struct ahci_host_priv *hpriv = ap->host->private_data; |
@@ -1592,18 +1642,16 @@ static int ahci_kick_engine(struct ata_port *ap, int force_restart) | |||
1592 | u32 tmp; | 1642 | u32 tmp; |
1593 | int busy, rc; | 1643 | int busy, rc; |
1594 | 1644 | ||
1595 | /* do we need to kick the port? */ | ||
1596 | busy = status & (ATA_BUSY | ATA_DRQ); | ||
1597 | if (!busy && !force_restart) | ||
1598 | return 0; | ||
1599 | |||
1600 | /* stop engine */ | 1645 | /* stop engine */ |
1601 | rc = ahci_stop_engine(ap); | 1646 | rc = ahci_stop_engine(ap); |
1602 | if (rc) | 1647 | if (rc) |
1603 | goto out_restart; | 1648 | goto out_restart; |
1604 | 1649 | ||
1605 | /* need to do CLO? */ | 1650 | /* need to do CLO? |
1606 | if (!busy) { | 1651 | * always do CLO if PMP is attached (AHCI-1.3 9.2) |
1652 | */ | ||
1653 | busy = status & (ATA_BUSY | ATA_DRQ); | ||
1654 | if (!busy && !sata_pmp_attached(ap)) { | ||
1607 | rc = 0; | 1655 | rc = 0; |
1608 | goto out_restart; | 1656 | goto out_restart; |
1609 | } | 1657 | } |
@@ -1651,7 +1699,7 @@ static int ahci_exec_polled_cmd(struct ata_port *ap, int pmp, | |||
1651 | tmp = ata_wait_register(port_mmio + PORT_CMD_ISSUE, 0x1, 0x1, | 1699 | tmp = ata_wait_register(port_mmio + PORT_CMD_ISSUE, 0x1, 0x1, |
1652 | 1, timeout_msec); | 1700 | 1, timeout_msec); |
1653 | if (tmp & 0x1) { | 1701 | if (tmp & 0x1) { |
1654 | ahci_kick_engine(ap, 1); | 1702 | ahci_kick_engine(ap); |
1655 | return -EBUSY; | 1703 | return -EBUSY; |
1656 | } | 1704 | } |
1657 | } else | 1705 | } else |
@@ -1674,7 +1722,7 @@ static int ahci_do_softreset(struct ata_link *link, unsigned int *class, | |||
1674 | DPRINTK("ENTER\n"); | 1722 | DPRINTK("ENTER\n"); |
1675 | 1723 | ||
1676 | /* prepare for SRST (AHCI-1.1 10.4.1) */ | 1724 | /* prepare for SRST (AHCI-1.1 10.4.1) */ |
1677 | rc = ahci_kick_engine(ap, 1); | 1725 | rc = ahci_kick_engine(ap); |
1678 | if (rc && rc != -EOPNOTSUPP) | 1726 | if (rc && rc != -EOPNOTSUPP) |
1679 | ata_link_printk(link, KERN_WARNING, | 1727 | ata_link_printk(link, KERN_WARNING, |
1680 | "failed to reset engine (errno=%d)\n", rc); | 1728 | "failed to reset engine (errno=%d)\n", rc); |
@@ -1890,7 +1938,7 @@ static int ahci_p5wdh_hardreset(struct ata_link *link, unsigned int *class, | |||
1890 | rc = ata_wait_after_reset(link, jiffies + 2 * HZ, | 1938 | rc = ata_wait_after_reset(link, jiffies + 2 * HZ, |
1891 | ahci_check_ready); | 1939 | ahci_check_ready); |
1892 | if (rc) | 1940 | if (rc) |
1893 | ahci_kick_engine(ap, 0); | 1941 | ahci_kick_engine(ap); |
1894 | } | 1942 | } |
1895 | return rc; | 1943 | return rc; |
1896 | } | 1944 | } |
@@ -2271,7 +2319,7 @@ static void ahci_post_internal_cmd(struct ata_queued_cmd *qc) | |||
2271 | 2319 | ||
2272 | /* make DMA engine forget about the failed command */ | 2320 | /* make DMA engine forget about the failed command */ |
2273 | if (qc->flags & ATA_QCFLAG_FAILED) | 2321 | if (qc->flags & ATA_QCFLAG_FAILED) |
2274 | ahci_kick_engine(ap, 1); | 2322 | ahci_kick_engine(ap); |
2275 | } | 2323 | } |
2276 | 2324 | ||
2277 | static void ahci_pmp_attach(struct ata_port *ap) | 2325 | static void ahci_pmp_attach(struct ata_port *ap) |
@@ -2603,14 +2651,18 @@ static void ahci_p5wdh_workaround(struct ata_host *host) | |||
2603 | } | 2651 | } |
2604 | 2652 | ||
2605 | /* | 2653 | /* |
2606 | * SB600 ahci controller on ASUS M2A-VM can't do 64bit DMA with older | 2654 | * SB600 ahci controller on certain boards can't do 64bit DMA with |
2607 | * BIOS. The oldest version known to be broken is 0901 and working is | 2655 | * older BIOS. |
2608 | * 1501 which was released on 2007-10-26. Force 32bit DMA on anything | ||
2609 | * older than 1501. Please read bko#9412 for more info. | ||
2610 | */ | 2656 | */ |
2611 | static bool ahci_asus_m2a_vm_32bit_only(struct pci_dev *pdev) | 2657 | static bool ahci_sb600_32bit_only(struct pci_dev *pdev) |
2612 | { | 2658 | { |
2613 | static const struct dmi_system_id sysids[] = { | 2659 | static const struct dmi_system_id sysids[] = { |
2660 | /* | ||
2661 | * The oldest version known to be broken is 0901 and | ||
2662 | * working is 1501 which was released on 2007-10-26. | ||
2663 | * Force 32bit DMA on anything older than 1501. | ||
2664 | * Please read bko#9412 for more info. | ||
2665 | */ | ||
2614 | { | 2666 | { |
2615 | .ident = "ASUS M2A-VM", | 2667 | .ident = "ASUS M2A-VM", |
2616 | .matches = { | 2668 | .matches = { |
@@ -2618,31 +2670,48 @@ static bool ahci_asus_m2a_vm_32bit_only(struct pci_dev *pdev) | |||
2618 | "ASUSTeK Computer INC."), | 2670 | "ASUSTeK Computer INC."), |
2619 | DMI_MATCH(DMI_BOARD_NAME, "M2A-VM"), | 2671 | DMI_MATCH(DMI_BOARD_NAME, "M2A-VM"), |
2620 | }, | 2672 | }, |
2673 | .driver_data = "20071026", /* yyyymmdd */ | ||
2674 | }, | ||
2675 | /* | ||
2676 | * It's yet unknown whether more recent BIOS fixes the | ||
2677 | * problem. Blacklist the whole board for the time | ||
2678 | * being. Please read the following thread for more | ||
2679 | * info. | ||
2680 | * | ||
2681 | * http://thread.gmane.org/gmane.linux.ide/42326 | ||
2682 | */ | ||
2683 | { | ||
2684 | .ident = "Gigabyte GA-MA69VM-S2", | ||
2685 | .matches = { | ||
2686 | DMI_MATCH(DMI_BOARD_VENDOR, | ||
2687 | "Gigabyte Technology Co., Ltd."), | ||
2688 | DMI_MATCH(DMI_BOARD_NAME, "GA-MA69VM-S2"), | ||
2689 | }, | ||
2621 | }, | 2690 | }, |
2622 | { } | 2691 | { } |
2623 | }; | 2692 | }; |
2624 | const char *cutoff_mmdd = "10/26"; | 2693 | const struct dmi_system_id *match; |
2625 | const char *date; | ||
2626 | int year; | ||
2627 | 2694 | ||
2695 | match = dmi_first_match(sysids); | ||
2628 | if (pdev->bus->number != 0 || pdev->devfn != PCI_DEVFN(0x12, 0) || | 2696 | if (pdev->bus->number != 0 || pdev->devfn != PCI_DEVFN(0x12, 0) || |
2629 | !dmi_check_system(sysids)) | 2697 | !match) |
2630 | return false; | 2698 | return false; |
2631 | 2699 | ||
2632 | /* | 2700 | if (match->driver_data) { |
2633 | * Argh.... both version and date are free form strings. | 2701 | int year, month, date; |
2634 | * Let's hope they're using the same date format across | 2702 | char buf[9]; |
2635 | * different versions. | 2703 | |
2636 | */ | 2704 | dmi_get_date(DMI_BIOS_DATE, &year, &month, &date); |
2637 | date = dmi_get_system_info(DMI_BIOS_DATE); | 2705 | snprintf(buf, sizeof(buf), "%04d%02d%02d", year, month, date); |
2638 | year = dmi_get_year(DMI_BIOS_DATE); | ||
2639 | if (date && strlen(date) >= 10 && date[2] == '/' && date[5] == '/' && | ||
2640 | (year > 2007 || | ||
2641 | (year == 2007 && strncmp(date, cutoff_mmdd, 5) >= 0))) | ||
2642 | return false; | ||
2643 | 2706 | ||
2644 | dev_printk(KERN_WARNING, &pdev->dev, "ASUS M2A-VM: BIOS too old, " | 2707 | if (strcmp(buf, match->driver_data) >= 0) |
2645 | "forcing 32bit DMA, update BIOS\n"); | 2708 | return false; |
2709 | |||
2710 | dev_printk(KERN_WARNING, &pdev->dev, "%s: BIOS too old, " | ||
2711 | "forcing 32bit DMA, update BIOS\n", match->ident); | ||
2712 | } else | ||
2713 | dev_printk(KERN_WARNING, &pdev->dev, "%s: this board can't " | ||
2714 | "do 64bit DMA, forcing 32bit\n", match->ident); | ||
2646 | 2715 | ||
2647 | return true; | 2716 | return true; |
2648 | } | 2717 | } |
@@ -2857,8 +2926,8 @@ static int ahci_init_one(struct pci_dev *pdev, const struct pci_device_id *ent) | |||
2857 | if (board_id == board_ahci_sb700 && pdev->revision >= 0x40) | 2926 | if (board_id == board_ahci_sb700 && pdev->revision >= 0x40) |
2858 | hpriv->flags &= ~AHCI_HFLAG_IGN_SERR_INTERNAL; | 2927 | hpriv->flags &= ~AHCI_HFLAG_IGN_SERR_INTERNAL; |
2859 | 2928 | ||
2860 | /* apply ASUS M2A_VM quirk */ | 2929 | /* apply sb600 32bit only quirk */ |
2861 | if (ahci_asus_m2a_vm_32bit_only(pdev)) | 2930 | if (ahci_sb600_32bit_only(pdev)) |
2862 | hpriv->flags |= AHCI_HFLAG_32BIT_ONLY; | 2931 | hpriv->flags |= AHCI_HFLAG_32BIT_ONLY; |
2863 | 2932 | ||
2864 | if (!(hpriv->flags & AHCI_HFLAG_NO_MSI)) | 2933 | if (!(hpriv->flags & AHCI_HFLAG_NO_MSI)) |
@@ -2869,7 +2938,7 @@ static int ahci_init_one(struct pci_dev *pdev, const struct pci_device_id *ent) | |||
2869 | 2938 | ||
2870 | /* prepare host */ | 2939 | /* prepare host */ |
2871 | if (hpriv->cap & HOST_CAP_NCQ) | 2940 | if (hpriv->cap & HOST_CAP_NCQ) |
2872 | pi.flags |= ATA_FLAG_NCQ; | 2941 | pi.flags |= ATA_FLAG_NCQ | ATA_FLAG_FPDMA_AA; |
2873 | 2942 | ||
2874 | if (hpriv->cap & HOST_CAP_PMP) | 2943 | if (hpriv->cap & HOST_CAP_PMP) |
2875 | pi.flags |= ATA_FLAG_PMP; | 2944 | pi.flags |= ATA_FLAG_PMP; |