aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--drivers/ata/libata-core.c27
-rw-r--r--drivers/ata/libata-scsi.c18
-rw-r--r--include/linux/libata.h2
3 files changed, 44 insertions, 3 deletions
diff --git a/drivers/ata/libata-core.c b/drivers/ata/libata-core.c
index 1393a5890ed5..1a3dbd1b196e 100644
--- a/drivers/ata/libata-core.c
+++ b/drivers/ata/libata-core.c
@@ -2222,6 +2222,16 @@ int ata_dev_configure(struct ata_device *dev)
2222 if (rc) 2222 if (rc)
2223 return rc; 2223 return rc;
2224 2224
2225 /* some WD SATA-1 drives have issues with LPM, turn on NOLPM for them */
2226 if ((dev->horkage & ATA_HORKAGE_WD_BROKEN_LPM) &&
2227 (id[ATA_ID_SATA_CAPABILITY] & 0xe) == 0x2)
2228 dev->horkage |= ATA_HORKAGE_NOLPM;
2229
2230 if (dev->horkage & ATA_HORKAGE_NOLPM) {
2231 ata_dev_warn(dev, "LPM support broken, forcing max_power\n");
2232 dev->link->ap->target_lpm_policy = ATA_LPM_MAX_POWER;
2233 }
2234
2225 /* let ACPI work its magic */ 2235 /* let ACPI work its magic */
2226 rc = ata_acpi_on_devcfg(dev); 2236 rc = ata_acpi_on_devcfg(dev);
2227 if (rc) 2237 if (rc)
@@ -4216,6 +4226,23 @@ static const struct ata_blacklist_entry ata_device_blacklist [] = {
4216 { "Micron_M500*", NULL, ATA_HORKAGE_NO_NCQ_TRIM, }, 4226 { "Micron_M500*", NULL, ATA_HORKAGE_NO_NCQ_TRIM, },
4217 { "Crucial_CT???M500SSD1", NULL, ATA_HORKAGE_NO_NCQ_TRIM, }, 4227 { "Crucial_CT???M500SSD1", NULL, ATA_HORKAGE_NO_NCQ_TRIM, },
4218 4228
4229 /*
4230 * Some WD SATA-I drives spin up and down erratically when the link
4231 * is put into the slumber mode. We don't have full list of the
4232 * affected devices. Disable LPM if the device matches one of the
4233 * known prefixes and is SATA-1. As a side effect LPM partial is
4234 * lost too.
4235 *
4236 * https://bugzilla.kernel.org/show_bug.cgi?id=57211
4237 */
4238 { "WDC WD800JD-*", NULL, ATA_HORKAGE_WD_BROKEN_LPM },
4239 { "WDC WD1200JD-*", NULL, ATA_HORKAGE_WD_BROKEN_LPM },
4240 { "WDC WD1600JD-*", NULL, ATA_HORKAGE_WD_BROKEN_LPM },
4241 { "WDC WD2000JD-*", NULL, ATA_HORKAGE_WD_BROKEN_LPM },
4242 { "WDC WD2500JD-*", NULL, ATA_HORKAGE_WD_BROKEN_LPM },
4243 { "WDC WD3000JD-*", NULL, ATA_HORKAGE_WD_BROKEN_LPM },
4244 { "WDC WD3200JD-*", NULL, ATA_HORKAGE_WD_BROKEN_LPM },
4245
4219 /* End Marker */ 4246 /* End Marker */
4220 { } 4247 { }
4221}; 4248};
diff --git a/drivers/ata/libata-scsi.c b/drivers/ata/libata-scsi.c
index 176f62950e3d..75ef9527603e 100644
--- a/drivers/ata/libata-scsi.c
+++ b/drivers/ata/libata-scsi.c
@@ -111,12 +111,14 @@ static const char *ata_lpm_policy_names[] = {
111 [ATA_LPM_MIN_POWER] = "min_power", 111 [ATA_LPM_MIN_POWER] = "min_power",
112}; 112};
113 113
114static ssize_t ata_scsi_lpm_store(struct device *dev, 114static ssize_t ata_scsi_lpm_store(struct device *device,
115 struct device_attribute *attr, 115 struct device_attribute *attr,
116 const char *buf, size_t count) 116 const char *buf, size_t count)
117{ 117{
118 struct Scsi_Host *shost = class_to_shost(dev); 118 struct Scsi_Host *shost = class_to_shost(device);
119 struct ata_port *ap = ata_shost_to_port(shost); 119 struct ata_port *ap = ata_shost_to_port(shost);
120 struct ata_link *link;
121 struct ata_device *dev;
120 enum ata_lpm_policy policy; 122 enum ata_lpm_policy policy;
121 unsigned long flags; 123 unsigned long flags;
122 124
@@ -132,10 +134,20 @@ static ssize_t ata_scsi_lpm_store(struct device *dev,
132 return -EINVAL; 134 return -EINVAL;
133 135
134 spin_lock_irqsave(ap->lock, flags); 136 spin_lock_irqsave(ap->lock, flags);
137
138 ata_for_each_link(link, ap, EDGE) {
139 ata_for_each_dev(dev, &ap->link, ENABLED) {
140 if (dev->horkage & ATA_HORKAGE_NOLPM) {
141 count = -EOPNOTSUPP;
142 goto out_unlock;
143 }
144 }
145 }
146
135 ap->target_lpm_policy = policy; 147 ap->target_lpm_policy = policy;
136 ata_port_schedule_eh(ap); 148 ata_port_schedule_eh(ap);
149out_unlock:
137 spin_unlock_irqrestore(ap->lock, flags); 150 spin_unlock_irqrestore(ap->lock, flags);
138
139 return count; 151 return count;
140} 152}
141 153
diff --git a/include/linux/libata.h b/include/linux/libata.h
index 9b503376738f..bec6dbe939a0 100644
--- a/include/linux/libata.h
+++ b/include/linux/libata.h
@@ -419,6 +419,8 @@ enum {
419 ATA_HORKAGE_MAX_SEC_LBA48 = (1 << 17), /* Set max sects to 65535 */ 419 ATA_HORKAGE_MAX_SEC_LBA48 = (1 << 17), /* Set max sects to 65535 */
420 ATA_HORKAGE_ATAPI_DMADIR = (1 << 18), /* device requires dmadir */ 420 ATA_HORKAGE_ATAPI_DMADIR = (1 << 18), /* device requires dmadir */
421 ATA_HORKAGE_NO_NCQ_TRIM = (1 << 19), /* don't use queued TRIM */ 421 ATA_HORKAGE_NO_NCQ_TRIM = (1 << 19), /* don't use queued TRIM */
422 ATA_HORKAGE_NOLPM = (1 << 20), /* don't use LPM */
423 ATA_HORKAGE_WD_BROKEN_LPM = (1 << 21), /* some WDs have broken LPM */
422 424
423 /* DMA mask for user DMA control: User visible values; DO NOT 425 /* DMA mask for user DMA control: User visible values; DO NOT
424 renumber */ 426 renumber */