diff options
Diffstat (limited to 'drivers/ata/ahci.c')
-rw-r--r-- | drivers/ata/ahci.c | 84 |
1 files changed, 79 insertions, 5 deletions
diff --git a/drivers/ata/ahci.c b/drivers/ata/ahci.c index 15a23031833f..fe3eba5d6b3e 100644 --- a/drivers/ata/ahci.c +++ b/drivers/ata/ahci.c | |||
@@ -219,6 +219,8 @@ enum { | |||
219 | AHCI_HFLAG_SECT255 = (1 << 8), /* max 255 sectors */ | 219 | AHCI_HFLAG_SECT255 = (1 << 8), /* max 255 sectors */ |
220 | AHCI_HFLAG_YES_NCQ = (1 << 9), /* force NCQ cap on */ | 220 | AHCI_HFLAG_YES_NCQ = (1 << 9), /* force NCQ cap on */ |
221 | AHCI_HFLAG_NO_SUSPEND = (1 << 10), /* don't suspend */ | 221 | AHCI_HFLAG_NO_SUSPEND = (1 << 10), /* don't suspend */ |
222 | AHCI_HFLAG_SRST_TOUT_IS_OFFLINE = (1 << 11), /* treat SRST timeout as | ||
223 | link offline */ | ||
222 | 224 | ||
223 | /* ap->flags bits */ | 225 | /* ap->flags bits */ |
224 | 226 | ||
@@ -513,11 +515,16 @@ static const struct pci_device_id ahci_pci_tbl[] = { | |||
513 | { PCI_VDEVICE(INTEL, 0x502a), board_ahci }, /* Tolapai */ | 515 | { PCI_VDEVICE(INTEL, 0x502a), board_ahci }, /* Tolapai */ |
514 | { PCI_VDEVICE(INTEL, 0x502b), board_ahci }, /* Tolapai */ | 516 | { PCI_VDEVICE(INTEL, 0x502b), board_ahci }, /* Tolapai */ |
515 | { PCI_VDEVICE(INTEL, 0x3a05), board_ahci }, /* ICH10 */ | 517 | { PCI_VDEVICE(INTEL, 0x3a05), board_ahci }, /* ICH10 */ |
518 | { PCI_VDEVICE(INTEL, 0x3a22), board_ahci }, /* ICH10 */ | ||
516 | { PCI_VDEVICE(INTEL, 0x3a25), board_ahci }, /* ICH10 */ | 519 | { PCI_VDEVICE(INTEL, 0x3a25), board_ahci }, /* ICH10 */ |
520 | { PCI_VDEVICE(INTEL, 0x3b22), board_ahci }, /* PCH AHCI */ | ||
521 | { PCI_VDEVICE(INTEL, 0x3b23), board_ahci }, /* PCH AHCI */ | ||
517 | { PCI_VDEVICE(INTEL, 0x3b24), board_ahci }, /* PCH RAID */ | 522 | { PCI_VDEVICE(INTEL, 0x3b24), board_ahci }, /* PCH RAID */ |
518 | { PCI_VDEVICE(INTEL, 0x3b25), board_ahci }, /* PCH RAID */ | 523 | { PCI_VDEVICE(INTEL, 0x3b25), board_ahci }, /* PCH RAID */ |
524 | { PCI_VDEVICE(INTEL, 0x3b29), board_ahci }, /* PCH AHCI */ | ||
519 | { PCI_VDEVICE(INTEL, 0x3b2b), board_ahci }, /* PCH RAID */ | 525 | { PCI_VDEVICE(INTEL, 0x3b2b), board_ahci }, /* PCH RAID */ |
520 | { PCI_VDEVICE(INTEL, 0x3b2c), board_ahci }, /* PCH RAID */ | 526 | { PCI_VDEVICE(INTEL, 0x3b2c), board_ahci }, /* PCH RAID */ |
527 | { PCI_VDEVICE(INTEL, 0x3b2f), board_ahci }, /* PCH AHCI */ | ||
521 | 528 | ||
522 | /* JMicron 360/1/3/5/6, match class to avoid IDE function */ | 529 | /* JMicron 360/1/3/5/6, match class to avoid IDE function */ |
523 | { PCI_VENDOR_ID_JMICRON, PCI_ANY_ID, PCI_ANY_ID, PCI_ANY_ID, | 530 | { PCI_VENDOR_ID_JMICRON, PCI_ANY_ID, PCI_ANY_ID, PCI_ANY_ID, |
@@ -1658,6 +1665,7 @@ static int ahci_do_softreset(struct ata_link *link, unsigned int *class, | |||
1658 | int (*check_ready)(struct ata_link *link)) | 1665 | int (*check_ready)(struct ata_link *link)) |
1659 | { | 1666 | { |
1660 | struct ata_port *ap = link->ap; | 1667 | struct ata_port *ap = link->ap; |
1668 | struct ahci_host_priv *hpriv = ap->host->private_data; | ||
1661 | const char *reason = NULL; | 1669 | const char *reason = NULL; |
1662 | unsigned long now, msecs; | 1670 | unsigned long now, msecs; |
1663 | struct ata_taskfile tf; | 1671 | struct ata_taskfile tf; |
@@ -1696,12 +1704,21 @@ static int ahci_do_softreset(struct ata_link *link, unsigned int *class, | |||
1696 | 1704 | ||
1697 | /* wait for link to become ready */ | 1705 | /* wait for link to become ready */ |
1698 | rc = ata_wait_after_reset(link, deadline, check_ready); | 1706 | rc = ata_wait_after_reset(link, deadline, check_ready); |
1699 | /* link occupied, -ENODEV too is an error */ | 1707 | if (rc == -EBUSY && hpriv->flags & AHCI_HFLAG_SRST_TOUT_IS_OFFLINE) { |
1700 | if (rc) { | 1708 | /* |
1709 | * Workaround for cases where link online status can't | ||
1710 | * be trusted. Treat device readiness timeout as link | ||
1711 | * offline. | ||
1712 | */ | ||
1713 | ata_link_printk(link, KERN_INFO, | ||
1714 | "device not ready, treating as offline\n"); | ||
1715 | *class = ATA_DEV_NONE; | ||
1716 | } else if (rc) { | ||
1717 | /* link occupied, -ENODEV too is an error */ | ||
1701 | reason = "device not ready"; | 1718 | reason = "device not ready"; |
1702 | goto fail; | 1719 | goto fail; |
1703 | } | 1720 | } else |
1704 | *class = ahci_dev_classify(ap); | 1721 | *class = ahci_dev_classify(ap); |
1705 | 1722 | ||
1706 | DPRINTK("EXIT, class=%u\n", *class); | 1723 | DPRINTK("EXIT, class=%u\n", *class); |
1707 | return 0; | 1724 | return 0; |
@@ -1768,7 +1785,8 @@ static int ahci_sb600_softreset(struct ata_link *link, unsigned int *class, | |||
1768 | irq_sts = readl(port_mmio + PORT_IRQ_STAT); | 1785 | irq_sts = readl(port_mmio + PORT_IRQ_STAT); |
1769 | if (irq_sts & PORT_IRQ_BAD_PMP) { | 1786 | if (irq_sts & PORT_IRQ_BAD_PMP) { |
1770 | ata_link_printk(link, KERN_WARNING, | 1787 | ata_link_printk(link, KERN_WARNING, |
1771 | "failed due to HW bug, retry pmp=0\n"); | 1788 | "applying SB600 PMP SRST workaround " |
1789 | "and retrying\n"); | ||
1772 | rc = ahci_do_softreset(link, class, 0, deadline, | 1790 | rc = ahci_do_softreset(link, class, 0, deadline, |
1773 | ahci_check_ready); | 1791 | ahci_check_ready); |
1774 | } | 1792 | } |
@@ -2721,6 +2739,56 @@ static bool ahci_broken_suspend(struct pci_dev *pdev) | |||
2721 | return !ver || strcmp(ver, dmi->driver_data) < 0; | 2739 | return !ver || strcmp(ver, dmi->driver_data) < 0; |
2722 | } | 2740 | } |
2723 | 2741 | ||
2742 | static bool ahci_broken_online(struct pci_dev *pdev) | ||
2743 | { | ||
2744 | #define ENCODE_BUSDEVFN(bus, slot, func) \ | ||
2745 | (void *)(unsigned long)(((bus) << 8) | PCI_DEVFN((slot), (func))) | ||
2746 | static const struct dmi_system_id sysids[] = { | ||
2747 | /* | ||
2748 | * There are several gigabyte boards which use | ||
2749 | * SIMG5723s configured as hardware RAID. Certain | ||
2750 | * 5723 firmware revisions shipped there keep the link | ||
2751 | * online but fail to answer properly to SRST or | ||
2752 | * IDENTIFY when no device is attached downstream | ||
2753 | * causing libata to retry quite a few times leading | ||
2754 | * to excessive detection delay. | ||
2755 | * | ||
2756 | * As these firmwares respond to the second reset try | ||
2757 | * with invalid device signature, considering unknown | ||
2758 | * sig as offline works around the problem acceptably. | ||
2759 | */ | ||
2760 | { | ||
2761 | .ident = "EP45-DQ6", | ||
2762 | .matches = { | ||
2763 | DMI_MATCH(DMI_BOARD_VENDOR, | ||
2764 | "Gigabyte Technology Co., Ltd."), | ||
2765 | DMI_MATCH(DMI_BOARD_NAME, "EP45-DQ6"), | ||
2766 | }, | ||
2767 | .driver_data = ENCODE_BUSDEVFN(0x0a, 0x00, 0), | ||
2768 | }, | ||
2769 | { | ||
2770 | .ident = "EP45-DS5", | ||
2771 | .matches = { | ||
2772 | DMI_MATCH(DMI_BOARD_VENDOR, | ||
2773 | "Gigabyte Technology Co., Ltd."), | ||
2774 | DMI_MATCH(DMI_BOARD_NAME, "EP45-DS5"), | ||
2775 | }, | ||
2776 | .driver_data = ENCODE_BUSDEVFN(0x03, 0x00, 0), | ||
2777 | }, | ||
2778 | { } /* terminate list */ | ||
2779 | }; | ||
2780 | #undef ENCODE_BUSDEVFN | ||
2781 | const struct dmi_system_id *dmi = dmi_first_match(sysids); | ||
2782 | unsigned int val; | ||
2783 | |||
2784 | if (!dmi) | ||
2785 | return false; | ||
2786 | |||
2787 | val = (unsigned long)dmi->driver_data; | ||
2788 | |||
2789 | return pdev->bus->number == (val >> 8) && pdev->devfn == (val & 0xff); | ||
2790 | } | ||
2791 | |||
2724 | static int ahci_init_one(struct pci_dev *pdev, const struct pci_device_id *ent) | 2792 | static int ahci_init_one(struct pci_dev *pdev, const struct pci_device_id *ent) |
2725 | { | 2793 | { |
2726 | static int printed_version; | 2794 | static int printed_version; |
@@ -2836,6 +2904,12 @@ static int ahci_init_one(struct pci_dev *pdev, const struct pci_device_id *ent) | |||
2836 | "BIOS update required for suspend/resume\n"); | 2904 | "BIOS update required for suspend/resume\n"); |
2837 | } | 2905 | } |
2838 | 2906 | ||
2907 | if (ahci_broken_online(pdev)) { | ||
2908 | hpriv->flags |= AHCI_HFLAG_SRST_TOUT_IS_OFFLINE; | ||
2909 | dev_info(&pdev->dev, | ||
2910 | "online status unreliable, applying workaround\n"); | ||
2911 | } | ||
2912 | |||
2839 | /* CAP.NP sometimes indicate the index of the last enabled | 2913 | /* CAP.NP sometimes indicate the index of the last enabled |
2840 | * port, at other times, that of the last possible port, so | 2914 | * port, at other times, that of the last possible port, so |
2841 | * determining the maximum port number requires looking at | 2915 | * determining the maximum port number requires looking at |