diff options
-rw-r--r-- | drivers/ata/ahci.c | 96 | ||||
-rw-r--r-- | drivers/ata/ata_piix.c | 7 | ||||
-rw-r--r-- | drivers/ata/libata-core.c | 18 |
3 files changed, 31 insertions, 90 deletions
diff --git a/drivers/ata/ahci.c b/drivers/ata/ahci.c index 4688dbf2d111..54f38c21dd95 100644 --- a/drivers/ata/ahci.c +++ b/drivers/ata/ahci.c | |||
@@ -193,6 +193,8 @@ enum { | |||
193 | ATA_FLAG_ACPI_SATA | ATA_FLAG_AN | | 193 | ATA_FLAG_ACPI_SATA | ATA_FLAG_AN | |
194 | ATA_FLAG_IPM, | 194 | ATA_FLAG_IPM, |
195 | AHCI_LFLAG_COMMON = ATA_LFLAG_SKIP_D2H_BSY, | 195 | AHCI_LFLAG_COMMON = ATA_LFLAG_SKIP_D2H_BSY, |
196 | |||
197 | ICH_MAP = 0x90, /* ICH MAP register */ | ||
196 | }; | 198 | }; |
197 | 199 | ||
198 | struct ahci_cmd_hdr { | 200 | struct ahci_cmd_hdr { |
@@ -1271,9 +1273,9 @@ static int ahci_do_softreset(struct ata_link *link, unsigned int *class, | |||
1271 | 1273 | ||
1272 | /* prepare for SRST (AHCI-1.1 10.4.1) */ | 1274 | /* prepare for SRST (AHCI-1.1 10.4.1) */ |
1273 | rc = ahci_kick_engine(ap, 1); | 1275 | rc = ahci_kick_engine(ap, 1); |
1274 | if (rc) | 1276 | if (rc && rc != -EOPNOTSUPP) |
1275 | ata_link_printk(link, KERN_WARNING, | 1277 | ata_link_printk(link, KERN_WARNING, |
1276 | "failed to reset engine (errno=%d)", rc); | 1278 | "failed to reset engine (errno=%d)\n", rc); |
1277 | 1279 | ||
1278 | ata_tf_init(link->device, &tf); | 1280 | ata_tf_init(link->device, &tf); |
1279 | 1281 | ||
@@ -1638,7 +1640,7 @@ static void ahci_port_intr(struct ata_port *ap) | |||
1638 | struct ahci_host_priv *hpriv = ap->host->private_data; | 1640 | struct ahci_host_priv *hpriv = ap->host->private_data; |
1639 | int resetting = !!(ap->pflags & ATA_PFLAG_RESETTING); | 1641 | int resetting = !!(ap->pflags & ATA_PFLAG_RESETTING); |
1640 | u32 status, qc_active; | 1642 | u32 status, qc_active; |
1641 | int rc, known_irq = 0; | 1643 | int rc; |
1642 | 1644 | ||
1643 | status = readl(port_mmio + PORT_IRQ_STAT); | 1645 | status = readl(port_mmio + PORT_IRQ_STAT); |
1644 | writel(status, port_mmio + PORT_IRQ_STAT); | 1646 | writel(status, port_mmio + PORT_IRQ_STAT); |
@@ -1696,80 +1698,12 @@ static void ahci_port_intr(struct ata_port *ap) | |||
1696 | 1698 | ||
1697 | rc = ata_qc_complete_multiple(ap, qc_active, NULL); | 1699 | rc = ata_qc_complete_multiple(ap, qc_active, NULL); |
1698 | 1700 | ||
1699 | /* If resetting, spurious or invalid completions are expected, | 1701 | /* while resetting, invalid completions are expected */ |
1700 | * return unconditionally. | 1702 | if (unlikely(rc < 0 && !resetting)) { |
1701 | */ | ||
1702 | if (resetting) | ||
1703 | return; | ||
1704 | |||
1705 | if (rc > 0) | ||
1706 | return; | ||
1707 | if (rc < 0) { | ||
1708 | ehi->err_mask |= AC_ERR_HSM; | 1703 | ehi->err_mask |= AC_ERR_HSM; |
1709 | ehi->action |= ATA_EH_SOFTRESET; | 1704 | ehi->action |= ATA_EH_SOFTRESET; |
1710 | ata_port_freeze(ap); | 1705 | ata_port_freeze(ap); |
1711 | return; | ||
1712 | } | 1706 | } |
1713 | |||
1714 | /* hmmm... a spurious interrupt */ | ||
1715 | |||
1716 | /* if !NCQ, ignore. No modern ATA device has broken HSM | ||
1717 | * implementation for non-NCQ commands. | ||
1718 | */ | ||
1719 | if (!ap->link.sactive) | ||
1720 | return; | ||
1721 | |||
1722 | if (status & PORT_IRQ_D2H_REG_FIS) { | ||
1723 | if (!pp->ncq_saw_d2h) | ||
1724 | ata_port_printk(ap, KERN_INFO, | ||
1725 | "D2H reg with I during NCQ, " | ||
1726 | "this message won't be printed again\n"); | ||
1727 | pp->ncq_saw_d2h = 1; | ||
1728 | known_irq = 1; | ||
1729 | } | ||
1730 | |||
1731 | if (status & PORT_IRQ_DMAS_FIS) { | ||
1732 | if (!pp->ncq_saw_dmas) | ||
1733 | ata_port_printk(ap, KERN_INFO, | ||
1734 | "DMAS FIS during NCQ, " | ||
1735 | "this message won't be printed again\n"); | ||
1736 | pp->ncq_saw_dmas = 1; | ||
1737 | known_irq = 1; | ||
1738 | } | ||
1739 | |||
1740 | if (status & PORT_IRQ_SDB_FIS) { | ||
1741 | const __le32 *f = pp->rx_fis + RX_FIS_SDB; | ||
1742 | |||
1743 | if (le32_to_cpu(f[1])) { | ||
1744 | /* SDB FIS containing spurious completions | ||
1745 | * might be dangerous, whine and fail commands | ||
1746 | * with HSM violation. EH will turn off NCQ | ||
1747 | * after several such failures. | ||
1748 | */ | ||
1749 | ata_ehi_push_desc(ehi, | ||
1750 | "spurious completions during NCQ " | ||
1751 | "issue=0x%x SAct=0x%x FIS=%08x:%08x", | ||
1752 | readl(port_mmio + PORT_CMD_ISSUE), | ||
1753 | readl(port_mmio + PORT_SCR_ACT), | ||
1754 | le32_to_cpu(f[0]), le32_to_cpu(f[1])); | ||
1755 | ehi->err_mask |= AC_ERR_HSM; | ||
1756 | ehi->action |= ATA_EH_SOFTRESET; | ||
1757 | ata_port_freeze(ap); | ||
1758 | } else { | ||
1759 | if (!pp->ncq_saw_sdb) | ||
1760 | ata_port_printk(ap, KERN_INFO, | ||
1761 | "spurious SDB FIS %08x:%08x during NCQ, " | ||
1762 | "this message won't be printed again\n", | ||
1763 | le32_to_cpu(f[0]), le32_to_cpu(f[1])); | ||
1764 | pp->ncq_saw_sdb = 1; | ||
1765 | } | ||
1766 | known_irq = 1; | ||
1767 | } | ||
1768 | |||
1769 | if (!known_irq) | ||
1770 | ata_port_printk(ap, KERN_INFO, "spurious interrupt " | ||
1771 | "(irq_stat 0x%x active_tag 0x%x sactive 0x%x)\n", | ||
1772 | status, ap->link.active_tag, ap->link.sactive); | ||
1773 | } | 1707 | } |
1774 | 1708 | ||
1775 | static void ahci_irq_clear(struct ata_port *ap) | 1709 | static void ahci_irq_clear(struct ata_port *ap) |
@@ -2273,6 +2207,22 @@ static int ahci_init_one(struct pci_dev *pdev, const struct pci_device_id *ent) | |||
2273 | if (rc) | 2207 | if (rc) |
2274 | return rc; | 2208 | return rc; |
2275 | 2209 | ||
2210 | if (pdev->vendor == PCI_VENDOR_ID_INTEL && | ||
2211 | (pdev->device == 0x2652 || pdev->device == 0x2653)) { | ||
2212 | u8 map; | ||
2213 | |||
2214 | /* ICH6s share the same PCI ID for both piix and ahci | ||
2215 | * modes. Enabling ahci mode while MAP indicates | ||
2216 | * combined mode is a bad idea. Yield to ata_piix. | ||
2217 | */ | ||
2218 | pci_read_config_byte(pdev, ICH_MAP, &map); | ||
2219 | if (map & 0x3) { | ||
2220 | dev_printk(KERN_INFO, &pdev->dev, "controller is in " | ||
2221 | "combined mode, can't enable AHCI mode\n"); | ||
2222 | return -ENODEV; | ||
2223 | } | ||
2224 | } | ||
2225 | |||
2276 | hpriv = devm_kzalloc(dev, sizeof(*hpriv), GFP_KERNEL); | 2226 | hpriv = devm_kzalloc(dev, sizeof(*hpriv), GFP_KERNEL); |
2277 | if (!hpriv) | 2227 | if (!hpriv) |
2278 | return -ENOMEM; | 2228 | return -ENOMEM; |
diff --git a/drivers/ata/ata_piix.c b/drivers/ata/ata_piix.c index b538e1d22bf2..bb62a588f489 100644 --- a/drivers/ata/ata_piix.c +++ b/drivers/ata/ata_piix.c | |||
@@ -974,6 +974,13 @@ static int piix_broken_suspend(void) | |||
974 | }, | 974 | }, |
975 | }, | 975 | }, |
976 | { | 976 | { |
977 | .ident = "TECRA M4", | ||
978 | .matches = { | ||
979 | DMI_MATCH(DMI_SYS_VENDOR, "TOSHIBA"), | ||
980 | DMI_MATCH(DMI_PRODUCT_NAME, "Tecra M4"), | ||
981 | }, | ||
982 | }, | ||
983 | { | ||
977 | .ident = "TECRA M5", | 984 | .ident = "TECRA M5", |
978 | .matches = { | 985 | .matches = { |
979 | DMI_MATCH(DMI_SYS_VENDOR, "TOSHIBA"), | 986 | DMI_MATCH(DMI_SYS_VENDOR, "TOSHIBA"), |
diff --git a/drivers/ata/libata-core.c b/drivers/ata/libata-core.c index b514a80f1370..e4dea8623a71 100644 --- a/drivers/ata/libata-core.c +++ b/drivers/ata/libata-core.c | |||
@@ -4140,6 +4140,7 @@ static const struct ata_blacklist_entry ata_device_blacklist [] = { | |||
4140 | /* Devices where NCQ should be avoided */ | 4140 | /* Devices where NCQ should be avoided */ |
4141 | /* NCQ is slow */ | 4141 | /* NCQ is slow */ |
4142 | { "WDC WD740ADFD-00", NULL, ATA_HORKAGE_NONCQ }, | 4142 | { "WDC WD740ADFD-00", NULL, ATA_HORKAGE_NONCQ }, |
4143 | { "WDC WD740ADFD-00NLR1", NULL, ATA_HORKAGE_NONCQ, }, | ||
4143 | /* http://thread.gmane.org/gmane.linux.ide/14907 */ | 4144 | /* http://thread.gmane.org/gmane.linux.ide/14907 */ |
4144 | { "FUJITSU MHT2060BH", NULL, ATA_HORKAGE_NONCQ }, | 4145 | { "FUJITSU MHT2060BH", NULL, ATA_HORKAGE_NONCQ }, |
4145 | /* NCQ is broken */ | 4146 | /* NCQ is broken */ |
@@ -4154,23 +4155,6 @@ static const struct ata_blacklist_entry ata_device_blacklist [] = { | |||
4154 | { "HTS541060G9SA00", "MB3OC60D", ATA_HORKAGE_NONCQ, }, | 4155 | { "HTS541060G9SA00", "MB3OC60D", ATA_HORKAGE_NONCQ, }, |
4155 | { "HTS541080G9SA00", "MB4OC60D", ATA_HORKAGE_NONCQ, }, | 4156 | { "HTS541080G9SA00", "MB4OC60D", ATA_HORKAGE_NONCQ, }, |
4156 | { "HTS541010G9SA00", "MBZOC60D", ATA_HORKAGE_NONCQ, }, | 4157 | { "HTS541010G9SA00", "MBZOC60D", ATA_HORKAGE_NONCQ, }, |
4157 | /* Drives which do spurious command completion */ | ||
4158 | { "HTS541680J9SA00", "SB2IC7EP", ATA_HORKAGE_NONCQ, }, | ||
4159 | { "HTS541612J9SA00", "SBDIC7JP", ATA_HORKAGE_NONCQ, }, | ||
4160 | { "HDT722516DLA380", "V43OA96A", ATA_HORKAGE_NONCQ, }, | ||
4161 | { "Hitachi HTS541616J9SA00", "SB4OC70P", ATA_HORKAGE_NONCQ, }, | ||
4162 | { "Hitachi HTS542525K9SA00", "BBFOC31P", ATA_HORKAGE_NONCQ, }, | ||
4163 | { "WDC WD740ADFD-00NLR1", NULL, ATA_HORKAGE_NONCQ, }, | ||
4164 | { "WDC WD3200AAJS-00RYA0", "12.01B01", ATA_HORKAGE_NONCQ, }, | ||
4165 | { "FUJITSU MHV2080BH", "00840028", ATA_HORKAGE_NONCQ, }, | ||
4166 | { "ST9120822AS", "3.CLF", ATA_HORKAGE_NONCQ, }, | ||
4167 | { "ST9160821AS", "3.CLF", ATA_HORKAGE_NONCQ, }, | ||
4168 | { "ST9160821AS", "3.ALD", ATA_HORKAGE_NONCQ, }, | ||
4169 | { "ST9160821AS", "3.CCD", ATA_HORKAGE_NONCQ, }, | ||
4170 | { "ST3160812AS", "3.ADJ", ATA_HORKAGE_NONCQ, }, | ||
4171 | { "ST980813AS", "3.ADB", ATA_HORKAGE_NONCQ, }, | ||
4172 | { "SAMSUNG HD401LJ", "ZZ100-15", ATA_HORKAGE_NONCQ, }, | ||
4173 | { "Maxtor 7V300F0", "VA111900", ATA_HORKAGE_NONCQ, }, | ||
4174 | 4158 | ||
4175 | /* devices which puke on READ_NATIVE_MAX */ | 4159 | /* devices which puke on READ_NATIVE_MAX */ |
4176 | { "HDS724040KLSA80", "KFAOA20N", ATA_HORKAGE_BROKEN_HPA, }, | 4160 | { "HDS724040KLSA80", "KFAOA20N", ATA_HORKAGE_BROKEN_HPA, }, |