aboutsummaryrefslogtreecommitdiffstats
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
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>
-rw-r--r--drivers/ata/libata-core.c29
-rw-r--r--drivers/ata/libata-eh.c6
-rw-r--r--include/linux/libata.h1
3 files changed, 29 insertions, 7 deletions
diff --git a/drivers/ata/libata-core.c b/drivers/ata/libata-core.c
index 5718c247e23a..c325b7a4246a 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
diff --git a/drivers/ata/libata-eh.c b/drivers/ata/libata-eh.c
index 19f9947bd96b..183eaf466d4f 100644
--- a/drivers/ata/libata-eh.c
+++ b/drivers/ata/libata-eh.c
@@ -1799,12 +1799,18 @@ static int ata_eh_reset(struct ata_port *ap, int classify,
1799 } 1799 }
1800 1800
1801 if (rc == 0) { 1801 if (rc == 0) {
1802 u32 sstatus;
1803
1802 /* After the reset, the device state is PIO 0 and the 1804 /* After the reset, the device state is PIO 0 and the
1803 * controller state is undefined. Record the mode. 1805 * controller state is undefined. Record the mode.
1804 */ 1806 */
1805 for (i = 0; i < ATA_MAX_DEVICES; i++) 1807 for (i = 0; i < ATA_MAX_DEVICES; i++)
1806 ap->device[i].pio_mode = XFER_PIO_0; 1808 ap->device[i].pio_mode = XFER_PIO_0;
1807 1809
1810 /* record current link speed */
1811 if (sata_scr_read(ap, SCR_STATUS, &sstatus) == 0)
1812 ap->sata_spd = (sstatus >> 4) & 0xf;
1813
1808 if (postreset) 1814 if (postreset)
1809 postreset(ap, classes); 1815 postreset(ap, classes);
1810 1816
diff --git a/include/linux/libata.h b/include/linux/libata.h
index c732b3e78e28..16ebdf152c75 100644
--- a/include/linux/libata.h
+++ b/include/linux/libata.h
@@ -531,6 +531,7 @@ struct ata_port {
531 unsigned int cbl; /* cable type; ATA_CBL_xxx */ 531 unsigned int cbl; /* cable type; ATA_CBL_xxx */
532 unsigned int hw_sata_spd_limit; 532 unsigned int hw_sata_spd_limit;
533 unsigned int sata_spd_limit; /* SATA PHY speed limit */ 533 unsigned int sata_spd_limit; /* SATA PHY speed limit */
534 unsigned int sata_spd; /* current SATA PHY speed */
534 535
535 /* record runtime error info, protected by host lock */ 536 /* record runtime error info, protected by host lock */
536 struct ata_eh_info eh_info; 537 struct ata_eh_info eh_info;