linux-ide.vger.kernel.org archive mirror
 help / color / mirror / Atom feed
From: Tejun Heo <htejun@gmail.com>
To: Jeff Garzik <jeff@garzik.org>,
	Alan Cox <alan@lxorguk.ukuu.org.uk>,
	linux-ide@vger.kernel.org, Forrest Zhao <forrest.zhao@gmail.com>
Cc: Tejun Heo <htejun@gmail.com>
Subject: [PATCH 06/12] libata: improve SATA PHY speed down logic
Date: Sun, 1 Jul 2007 18:53:38 +0900	[thread overview]
Message-ID: <11832836183133-git-send-email-htejun@gmail.com> (raw)
In-Reply-To: <118328361627-git-send-email-htejun@gmail.com>

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>
---
 drivers/ata/libata-core.c |   29 ++++++++++++++++++++++-------
 drivers/ata/libata-eh.c   |    6 ++++++
 include/linux/libata.h    |    1 +
 3 files changed, 29 insertions(+), 7 deletions(-)

diff --git a/drivers/ata/libata-core.c b/drivers/ata/libata-core.c
index 147235c..49fe30a 100644
--- a/drivers/ata/libata-core.c
+++ b/drivers/ata/libata-core.c
@@ -2413,21 +2413,35 @@ int sata_down_spd_limit(struct ata_port *ap)
 	u32 sstatus, spd, mask;
 	int rc, highbit;
 
+	if (!sata_scr_valid(ap))
+		return -EOPNOTSUPP;
+
+	/* If SCR can be read, use it to determine the current SPD.
+	 * If not, use cached value in ap->sata_spd.
+	 */
 	rc = sata_scr_read(ap, SCR_STATUS, &sstatus);
-	if (rc)
-		return rc;
+	if (rc == 0)
+		spd = (sstatus >> 4) & 0xf;
+	else
+		spd = ap->sata_spd;
 
 	mask = ap->sata_spd_limit;
 	if (mask <= 1)
 		return -EINVAL;
+
+	/* unconditionally mask off the highest bit */
 	highbit = fls(mask) - 1;
 	mask &= ~(1 << highbit);
 
-	spd = (sstatus >> 4) & 0xf;
-	if (spd <= 1)
-		return -EINVAL;
-	spd--;
-	mask &= (1 << spd) - 1;
+	/* Mask off all speeds higher than or equal to the current
+	 * one.  Force 1.5Gbps if current SPD is not available.
+	 */
+	if (spd > 1)
+		mask &= (1 << (spd - 1)) - 1;
+	else
+		mask &= 1;
+
+	/* were we already at the bottom? */
 	if (!mask)
 		return -EINVAL;
 
@@ -5941,6 +5955,7 @@ void ata_dev_init(struct ata_device *dev)
 
 	/* SATA spd limit is bound to the first device */
 	ap->sata_spd_limit = ap->hw_sata_spd_limit;
+	ap->sata_spd = 0;
 
 	/* High bits of dev->flags are used to record warm plug
 	 * requests which occur asynchronously.  Synchronize using
diff --git a/drivers/ata/libata-eh.c b/drivers/ata/libata-eh.c
index 8d8961f..d18c475 100644
--- a/drivers/ata/libata-eh.c
+++ b/drivers/ata/libata-eh.c
@@ -1734,12 +1734,18 @@ static int ata_eh_reset(struct ata_port *ap, int classify,
 	}
 
 	if (rc == 0) {
+		u32 sstatus;
+
 		/* After the reset, the device state is PIO 0 and the
 		 * controller state is undefined.  Record the mode.
 		 */
 		for (i = 0; i < ATA_MAX_DEVICES; i++)
 			ap->device[i].pio_mode = XFER_PIO_0;
 
+		/* record current link speed */
+		if (sata_scr_read(ap, SCR_STATUS, &sstatus) == 0)
+			ap->sata_spd = (sstatus >> 4) & 0xf;
+
 		if (postreset)
 			postreset(ap, classes);
 
diff --git a/include/linux/libata.h b/include/linux/libata.h
index bc91ca0..05670b5 100644
--- a/include/linux/libata.h
+++ b/include/linux/libata.h
@@ -531,6 +531,7 @@ struct ata_port {
 	unsigned int		cbl;	/* cable type; ATA_CBL_xxx */
 	unsigned int		hw_sata_spd_limit;
 	unsigned int		sata_spd_limit;	/* SATA PHY speed limit */
+	unsigned int		sata_spd;	/* current SATA PHY speed */
 
 	/* record runtime error info, protected by host lock */
 	struct ata_eh_info	eh_info;
-- 
1.5.0.3



  parent reply	other threads:[~2007-07-01  9:53 UTC|newest]

Thread overview: 27+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2007-07-01  9:53 [PATCHSET 1/4] libata: misc updates in preparation of PMP support Tejun Heo
2007-07-01  9:53 ` [PATCH 01/12] libata: update EH report formatting Tejun Heo
2007-07-03 14:22   ` Jeff Garzik
2007-07-03 15:02     ` Tejun Heo
2007-07-01  9:53 ` [PATCH 03/12] libata: make ->scr_read/write callbacks return error code Tejun Heo
2007-07-03 14:26   ` Jeff Garzik
2007-07-01  9:53 ` [PATCH 05/12] ahci: implement SCR_NOTIFICATION r/w Tejun Heo
2007-07-03 14:31   ` Jeff Garzik
2007-07-03 15:00     ` Tejun Heo
2007-07-13 11:53     ` Tejun Heo
2007-07-01  9:53 ` [PATCH 04/12] ahci: make NO_NCQ handling more consistent Tejun Heo
2007-07-03 14:28   ` Jeff Garzik
2007-07-01  9:53 ` [PATCH 02/12] libata: implement AC_ERR_NCQ Tejun Heo
2007-07-03 14:24   ` Jeff Garzik
2007-07-03 14:58     ` Tejun Heo
2007-07-01  9:53 ` [PATCH 07/12] libata: quickly trigger SATA SPD down after debouncing failed Tejun Heo
2007-07-01  9:53 ` [PATCH 09/12] libata: reorganize ata_ehi_hotplugged() Tejun Heo
2007-07-01  9:53 ` [PATCH 12/12] libata: implement EH fast drain Tejun Heo
2007-07-03 14:37   ` Jeff Garzik
2007-07-03 15:09     ` Tejun Heo
2007-07-01  9:53 ` [PATCH 10/12] libata: clear HOTPLUG flag after a reset Tejun Heo
2007-07-03 14:34   ` Jeff Garzik
2007-07-01  9:53 ` Tejun Heo [this message]
2007-07-01  9:53 ` [PATCH 08/12] libata: improve SCSI scan failure handling Tejun Heo
2007-07-01  9:53 ` [PATCH 11/12] libata: schedule probing after SError access failure during autopsy Tejun Heo
2007-07-03 14:35   ` Jeff Garzik
2007-07-03 15:05     ` Tejun Heo

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=11832836183133-git-send-email-htejun@gmail.com \
    --to=htejun@gmail.com \
    --cc=alan@lxorguk.ukuu.org.uk \
    --cc=forrest.zhao@gmail.com \
    --cc=jeff@garzik.org \
    --cc=linux-ide@vger.kernel.org \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).