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
next prev parent reply other threads:[~2008-06-02 20:01 UTC|newest]
Thread overview: 41+ 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 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 an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.