aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/ata/libata-core.c
diff options
context:
space:
mode:
authorTejun Heo <htejun@gmail.com>2007-07-16 01:29:40 -0400
committerJeff Garzik <jeff@garzik.org>2007-07-20 08:19:05 -0400
commit008a78961ec72990d09d7625ef9499d7317d040d (patch)
treeaa356bbd961b7425017a3037fec509ffb761d332 /drivers/ata/libata-core.c
parentbadc2341579511a247f5993865aa68379e283c5c (diff)
libata: improve SATA PHY speed down logic
sata_down_spd_limit() first reads the current SPD from SStatus and limit the speed to the lower one of one below the current limit or one below the current SPD in SStatus. SPD may not be accessible or valid when SPD down is requested making sata_down_spd_limit() fail when it's most needed. This patch makes the current SPD cached after each successful reset and forces GEN I speed (1.5Gbps) if neither of SStatus or the cached value is valid, so sata_down_spd_limit() is now guaranteed to lower the speed limit if lower speed is available. Signed-off-by: Tejun Heo <htejun@gmail.com> Signed-off-by: Jeff Garzik <jeff@garzik.org>
Diffstat (limited to 'drivers/ata/libata-core.c')
-rw-r--r--drivers/ata/libata-core.c29
1 files changed, 22 insertions, 7 deletions
diff --git a/drivers/ata/libata-core.c b/drivers/ata/libata-core.c
index 5718c247e23..c325b7a4246 100644
--- a/drivers/ata/libata-core.c
+++ b/drivers/ata/libata-core.c
@@ -2389,21 +2389,35 @@ int sata_down_spd_limit(struct ata_port *ap)
2389 u32 sstatus, spd, mask; 2389 u32 sstatus, spd, mask;
2390 int rc, highbit; 2390 int rc, highbit;
2391 2391
2392 if (!sata_scr_valid(ap))
2393 return -EOPNOTSUPP;
2394
2395 /* If SCR can be read, use it to determine the current SPD.
2396 * If not, use cached value in ap->sata_spd.
2397 */
2392 rc = sata_scr_read(ap, SCR_STATUS, &sstatus); 2398 rc = sata_scr_read(ap, SCR_STATUS, &sstatus);
2393 if (rc) 2399 if (rc == 0)
2394 return rc; 2400 spd = (sstatus >> 4) & 0xf;
2401 else
2402 spd = ap->sata_spd;
2395 2403
2396 mask = ap->sata_spd_limit; 2404 mask = ap->sata_spd_limit;
2397 if (mask <= 1) 2405 if (mask <= 1)
2398 return -EINVAL; 2406 return -EINVAL;
2407
2408 /* unconditionally mask off the highest bit */
2399 highbit = fls(mask) - 1; 2409 highbit = fls(mask) - 1;
2400 mask &= ~(1 << highbit); 2410 mask &= ~(1 << highbit);
2401 2411
2402 spd = (sstatus >> 4) & 0xf; 2412 /* Mask off all speeds higher than or equal to the current
2403 if (spd <= 1) 2413 * one. Force 1.5Gbps if current SPD is not available.
2404 return -EINVAL; 2414 */
2405 spd--; 2415 if (spd > 1)
2406 mask &= (1 << spd) - 1; 2416 mask &= (1 << (spd - 1)) - 1;
2417 else
2418 mask &= 1;
2419
2420 /* were we already at the bottom? */
2407 if (!mask) 2421 if (!mask)
2408 return -EINVAL; 2422 return -EINVAL;
2409 2423
@@ -5995,6 +6009,7 @@ void ata_dev_init(struct ata_device *dev)
5995 6009
5996 /* SATA spd limit is bound to the first device */ 6010 /* SATA spd limit is bound to the first device */
5997 ap->sata_spd_limit = ap->hw_sata_spd_limit; 6011 ap->sata_spd_limit = ap->hw_sata_spd_limit;
6012 ap->sata_spd = 0;
5998 6013
5999 /* High bits of dev->flags are used to record warm plug 6014 /* High bits of dev->flags are used to record warm plug
6000 * requests which occur asynchronously. Synchronize using 6015 * requests which occur asynchronously. Synchronize using