diff options
| -rw-r--r-- | drivers/ata/libata-core.c | 41 | ||||
| -rw-r--r-- | include/linux/libata.h | 1 |
2 files changed, 42 insertions, 0 deletions
diff --git a/drivers/ata/libata-core.c b/drivers/ata/libata-core.c index 3c5965d56c47..9fbf0595f3d4 100644 --- a/drivers/ata/libata-core.c +++ b/drivers/ata/libata-core.c | |||
| @@ -2232,6 +2232,40 @@ retry: | |||
| 2232 | return rc; | 2232 | return rc; |
| 2233 | } | 2233 | } |
| 2234 | 2234 | ||
| 2235 | static int ata_do_link_spd_horkage(struct ata_device *dev) | ||
| 2236 | { | ||
| 2237 | struct ata_link *plink = ata_dev_phys_link(dev); | ||
| 2238 | u32 target, target_limit; | ||
| 2239 | |||
| 2240 | if (!sata_scr_valid(plink)) | ||
| 2241 | return 0; | ||
| 2242 | |||
| 2243 | if (dev->horkage & ATA_HORKAGE_1_5_GBPS) | ||
| 2244 | target = 1; | ||
| 2245 | else | ||
| 2246 | return 0; | ||
| 2247 | |||
| 2248 | target_limit = (1 << target) - 1; | ||
| 2249 | |||
| 2250 | /* if already on stricter limit, no need to push further */ | ||
| 2251 | if (plink->sata_spd_limit <= target_limit) | ||
| 2252 | return 0; | ||
| 2253 | |||
| 2254 | plink->sata_spd_limit = target_limit; | ||
| 2255 | |||
| 2256 | /* Request another EH round by returning -EAGAIN if link is | ||
| 2257 | * going faster than the target speed. Forward progress is | ||
| 2258 | * guaranteed by setting sata_spd_limit to target_limit above. | ||
| 2259 | */ | ||
| 2260 | if (plink->sata_spd > target) { | ||
| 2261 | ata_dev_printk(dev, KERN_INFO, | ||
| 2262 | "applying link speed limit horkage to %s\n", | ||
| 2263 | sata_spd_string(target)); | ||
| 2264 | return -EAGAIN; | ||
| 2265 | } | ||
| 2266 | return 0; | ||
| 2267 | } | ||
| 2268 | |||
| 2235 | static inline u8 ata_dev_knobble(struct ata_device *dev) | 2269 | static inline u8 ata_dev_knobble(struct ata_device *dev) |
| 2236 | { | 2270 | { |
| 2237 | struct ata_port *ap = dev->link->ap; | 2271 | struct ata_port *ap = dev->link->ap; |
| @@ -2322,6 +2356,10 @@ int ata_dev_configure(struct ata_device *dev) | |||
| 2322 | return 0; | 2356 | return 0; |
| 2323 | } | 2357 | } |
| 2324 | 2358 | ||
| 2359 | rc = ata_do_link_spd_horkage(dev); | ||
| 2360 | if (rc) | ||
| 2361 | return rc; | ||
| 2362 | |||
| 2325 | /* let ACPI work its magic */ | 2363 | /* let ACPI work its magic */ |
| 2326 | rc = ata_acpi_on_devcfg(dev); | 2364 | rc = ata_acpi_on_devcfg(dev); |
| 2327 | if (rc) | 2365 | if (rc) |
| @@ -4223,6 +4261,9 @@ static const struct ata_blacklist_entry ata_device_blacklist [] = { | |||
| 4223 | /* Devices that do not need bridging limits applied */ | 4261 | /* Devices that do not need bridging limits applied */ |
| 4224 | { "MTRON MSP-SATA*", NULL, ATA_HORKAGE_BRIDGE_OK, }, | 4262 | { "MTRON MSP-SATA*", NULL, ATA_HORKAGE_BRIDGE_OK, }, |
| 4225 | 4263 | ||
| 4264 | /* Devices which aren't very happy with higher link speeds */ | ||
| 4265 | { "WD My Book", NULL, ATA_HORKAGE_1_5_GBPS, }, | ||
| 4266 | |||
| 4226 | /* End Marker */ | 4267 | /* End Marker */ |
| 4227 | { } | 4268 | { } |
| 4228 | }; | 4269 | }; |
diff --git a/include/linux/libata.h b/include/linux/libata.h index 9dcefee5843c..5d87bc09a1f5 100644 --- a/include/linux/libata.h +++ b/include/linux/libata.h | |||
| @@ -380,6 +380,7 @@ enum { | |||
| 380 | ATA_HORKAGE_ATAPI_MOD16_DMA = (1 << 11), /* use ATAPI DMA for commands | 380 | ATA_HORKAGE_ATAPI_MOD16_DMA = (1 << 11), /* use ATAPI DMA for commands |
| 381 | not multiple of 16 bytes */ | 381 | not multiple of 16 bytes */ |
| 382 | ATA_HORKAGE_FIRMWARE_WARN = (1 << 12), /* firwmare update warning */ | 382 | ATA_HORKAGE_FIRMWARE_WARN = (1 << 12), /* firwmare update warning */ |
| 383 | ATA_HORKAGE_1_5_GBPS = (1 << 13), /* force 1.5 Gbps */ | ||
| 383 | 384 | ||
| 384 | /* DMA mask for user DMA control: User visible values; DO NOT | 385 | /* DMA mask for user DMA control: User visible values; DO NOT |
| 385 | renumber */ | 386 | renumber */ |
