linux-ide.vger.kernel.org archive mirror
 help / color / mirror / Atom feed
From: Matthew Garrett <mjg@redhat.com>
To: Jeff Garzik <jeff@garzik.org>
Cc: rwheeler@redhat.com, kristen.c.accardi@intel.com,
	Mark Lord <liml@rtr.ca>, Alan Cox <alan@lxorguk.ukuu.org.uk>,
	Pavel Machek <pavel@ucw.cz>, Theodore Tso <tytso@mit.edu>,
	linux-ide@vger.kernel.org, linux-kernel@vger.kernel.org
Subject: Re: [PATCH] ata: ahci: power off unused ports
Date: Mon, 2 Jun 2008 21:00:53 +0100	[thread overview]
Message-ID: <20080602200053.GA17698@srcf.ucam.org> (raw)
In-Reply-To: <48443EB3.8020303@garzik.org>

On Mon, Jun 02, 2008 at 02:40:51PM -0400, Jeff Garzik wrote:

> A better patch would enable the _possibility_ of power savings on 
> non-AHCI chips, and not add a one-off AHCI-specific user interface that 
> must be supported for years to come.

So how about somethig like the following, where the module parameter 
just gets moved to libata rather than ahci? Entirely untested, I don't 
have ahci on this machine.

diff --git a/drivers/ata/ahci.c b/drivers/ata/ahci.c
index 97f83fb..5913ebb 100644
--- a/drivers/ata/ahci.c
+++ b/drivers/ata/ahci.c
@@ -56,6 +56,7 @@ MODULE_PARM_DESC(skip_host_reset, "skip global host reset (0=don't skip, 1=skip)
 static int ahci_enable_alpm(struct ata_port *ap,
 		enum link_pm policy);
 static void ahci_disable_alpm(struct ata_port *ap);
+static int ahci_is_hotplug_capable(struct ata_port *ap);
 
 enum {
 	AHCI_PCI_BAR		= 5,
@@ -166,6 +167,8 @@ enum {
 	PORT_CMD_ASP		= (1 << 27), /* Aggressive Slumber/Partial */
 	PORT_CMD_ALPE		= (1 << 26), /* Aggressive Link PM enable */
 	PORT_CMD_ATAPI		= (1 << 24), /* Device is ATAPI */
+	PORT_CMD_ESP		= (1 << 21), /* External SATA Port */
+	PORT_CMD_HPCP		= (1 << 18), /* port is hot plug capable */
 	PORT_CMD_PMP		= (1 << 17), /* PMP attached */
 	PORT_CMD_LIST_ON	= (1 << 15), /* cmd list DMA engine running */
 	PORT_CMD_FIS_ON		= (1 << 14), /* FIS DMA engine running */
@@ -1900,6 +1903,15 @@ static int ahci_pci_device_resume(struct pci_dev *pdev)
 }
 #endif
 
+static int ahci_is_hotplug_capable(struct ata_port *ap)
+{
+	void __iomem *port_mmio = ahci_port_base(ap);
+	u8 cmd;
+
+	cmd = readl(port_mmio + PORT_CMD);
+	return ((cmd & PORT_CMD_HPCP) || (cmd & PORT_CMD_ESP));
+}
+
 static int ahci_port_start(struct ata_port *ap)
 {
 	struct device *dev = ap->host->dev;
@@ -1951,6 +1963,9 @@ static int ahci_port_start(struct ata_port *ap)
 
 	ap->private_data = pp;
 
+	/* set some flags based on port capabilities */
+	if (!ahci_is_hotplug_capable(ap))
+		ap->flags |= ATA_FLAG_NO_HOTPLUG;
 	/* engage engines, captain */
 	return ahci_port_resume(ap);
 }
diff --git a/drivers/ata/libata-core.c b/drivers/ata/libata-core.c
index 3c89f20..209efe5 100644
--- a/drivers/ata/libata-core.c
+++ b/drivers/ata/libata-core.c
@@ -157,11 +157,28 @@ int libata_allow_tpm = 0;
 module_param_named(allow_tpm, libata_allow_tpm, int, 0444);
 MODULE_PARM_DESC(allow_tpm, "Permit the use of TPM commands");
 
+static int sata_power_save = 1;
+module_param_named(sata_power_save, sata_power_save, int, 0644);
+MODULE_PARM_DESC(sata_power_save, "Power off unused ports (0=don't power off, 1=power off)");
+
 MODULE_AUTHOR("Jeff Garzik");
 MODULE_DESCRIPTION("Library module for ATA devices");
 MODULE_LICENSE("GPL");
 MODULE_VERSION(DRV_VERSION);
 
+static void ata_phy_offline(struct ata_link *link)
+{
+	u32 scontrol;
+	int rc;
+
+	/* set DET to 4 */
+	rc = sata_scr_read(link, SCR_CONTROL, &scontrol);
+	if (rc)
+		return;
+	scontrol &= ~0xf;
+	scontrol |= (1 << 2);
+	sata_scr_write(link, SCR_CONTROL, scontrol);
+}
 
 /**
  *	ata_force_cbl - force cable type according to libata.force
@@ -2678,6 +2695,7 @@ void ata_port_disable(struct ata_port *ap)
 	ap->link.device[0].class = ATA_DEV_NONE;
 	ap->link.device[1].class = ATA_DEV_NONE;
 	ap->flags |= ATA_FLAG_DISABLED;
+	ata_phy_offline(&ap->link);
 }
 
 /**
@@ -5614,6 +5632,8 @@ int ata_host_register(struct ata_host *host, struct scsi_host_template *sht)
 		if (ap->ops->error_handler) {
 			struct ata_eh_info *ehi = &ap->link.eh_info;
 			unsigned long flags;
+			int device_attached = 0;
+			struct ata_device *dev;
 
 			ata_port_probe(ap);
 
@@ -5632,6 +5652,14 @@ int ata_host_register(struct ata_host *host, struct scsi_host_template *sht)
 
 			/* wait for EH to finish */
 			ata_port_wait_eh(ap);
+			ata_link_for_each_dev(dev, &ap->link)
+				if (ata_dev_enabled(dev))
+					device_attached++;
+			if (!device_attached && sata_power_save &&
+			    (ap->flags & ATA_FLAG_NO_HOTPLUG)) {
+				/* no device present, disable port */
+				ata_port_disable(ap);
+			}
 		} else {
 			DPRINTK("ata%u: bus probe begin\n", ap->print_id);
 			rc = ata_bus_probe(ap);

-- 
Matthew Garrett | mjg59@srcf.ucam.org

  parent reply	other threads:[~2008-06-02 20:01 UTC|newest]

Thread overview: 40+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2008-05-08 23:10 [PATCH] ata: ahci: power off unused ports Kristen Carlson Accardi
2008-05-08 23:37 ` Matthew Garrett
2008-05-08 23:35   ` Kristen Carlson Accardi
2008-05-09  0:14     ` Matthew Garrett
2008-05-09  0:28       ` Kristen Carlson Accardi
2008-05-09 15:58   ` Lennart Sorensen
2008-05-09 16:06     ` Matthew Garrett
2008-05-09 16:14       ` Lennart Sorensen
2008-05-09 17:14         ` Kristen Carlson Accardi
2008-05-09 15:06 ` Mark Lord
2008-05-09 15:28   ` Port control interface (was Re: [PATCH] ata: ahci: power off unused ports) Jeff Garzik
2008-05-27  3:08 ` [PATCH] ata: ahci: power off unused ports Theodore Tso
2008-05-27 21:32   ` Kristen Carlson Accardi
2008-05-27 22:59     ` Theodore Tso
2008-05-27 23:32       ` Kristen Carlson Accardi
2008-05-31  8:00         ` Pavel Machek
2008-06-01 19:16           ` Jeff Garzik
2008-06-02  7:04             ` Alan Cox
2008-06-02  7:43               ` Jeff Garzik
2008-06-02  8:22                 ` Alan Cox
2008-06-02  9:48                   ` Jeff Garzik
2008-06-02 13:54                     ` Alan Cox
2008-06-02 16:55                     ` Kristen Carlson Accardi
2008-06-02 13:03                 ` Mark Lord
2008-06-02 16:07                   ` Jeff Garzik
2008-06-02 17:00                     ` Kristen Carlson Accardi
2008-06-02 17:45                       ` Jeff Garzik
2008-06-02 17:47                         ` Kristen Carlson Accardi
2008-06-02 18:15                           ` Jeff Garzik
2008-06-02 18:16                             ` Kristen Carlson Accardi
2008-06-02 18:30                               ` Ric Wheeler
2008-06-02 18:40                                 ` Jeff Garzik
2008-06-02 18:49                                   ` Ric Wheeler
2008-06-02 18:52                                     ` Jeff Garzik
2008-06-02 20:00                                   ` Matthew Garrett [this message]
2008-06-02 18:38                               ` Jeff Garzik
2008-06-03 16:49                                 ` Kristen Carlson Accardi
2008-06-02 17:07                     ` Greg Freemyer
2008-06-02 16:57                   ` Kristen Carlson Accardi
2008-06-02 17:44                     ` Jeff Garzik

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=20080602200053.GA17698@srcf.ucam.org \
    --to=mjg@redhat.com \
    --cc=alan@lxorguk.ukuu.org.uk \
    --cc=jeff@garzik.org \
    --cc=kristen.c.accardi@intel.com \
    --cc=liml@rtr.ca \
    --cc=linux-ide@vger.kernel.org \
    --cc=linux-kernel@vger.kernel.org \
    --cc=pavel@ucw.cz \
    --cc=rwheeler@redhat.com \
    --cc=tytso@mit.edu \
    /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).