aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/ata
diff options
context:
space:
mode:
authorShane Huang <shane.huang@amd.com>2012-09-07 10:40:01 -0400
committerJeff Garzik <jgarzik@redhat.com>2012-09-13 01:08:53 -0400
commit65fe1f0f66a57380229a4ced844188103135f37b (patch)
treeeb96e6c8de3bf8c4697618c8ee1dce4bd6d6a9ea /drivers/ata
parent583661a89ed2e484bd295e7b4606099340478c38 (diff)
ahci: implement aggressive SATA device sleep support
Device Sleep is a feature as described in AHCI 1.3.1 Technical Proposal. This feature enables an HBA and SATA storage device to enter the DevSleep interface state, enabling lower power SATA-based systems. Aggressive Device Sleep enables the HBA to assert the DEVSLP signal as soon as there are no commands outstanding to the device and the port specific Device Sleep idle timer has expired. This enables autonomous entry into the DevSleep interface state without waiting for software in power sensitive systems. This patch enables Aggressive Device Sleep only if both host controller and device support it. Tested on AMD reference board together with Device Sleep supported device sample. Signed-off-by: Shane Huang <shane.huang@amd.com> Reviewed-by: Aaron Lu <aaron.lwe@gmail.com> Signed-off-by: Jeff Garzik <jgarzik@redhat.com>
Diffstat (limited to 'drivers/ata')
-rw-r--r--drivers/ata/ahci.h14
-rw-r--r--drivers/ata/libahci.c97
-rw-r--r--drivers/ata/libata-core.c29
-rw-r--r--drivers/ata/libata-eh.c12
-rw-r--r--drivers/ata/libata.h2
5 files changed, 143 insertions, 11 deletions
diff --git a/drivers/ata/ahci.h b/drivers/ata/ahci.h
index 57eb1c212a4c..6441cbecfa1d 100644
--- a/drivers/ata/ahci.h
+++ b/drivers/ata/ahci.h
@@ -115,6 +115,9 @@ enum {
115 HOST_CAP2_BOH = (1 << 0), /* BIOS/OS handoff supported */ 115 HOST_CAP2_BOH = (1 << 0), /* BIOS/OS handoff supported */
116 HOST_CAP2_NVMHCI = (1 << 1), /* NVMHCI supported */ 116 HOST_CAP2_NVMHCI = (1 << 1), /* NVMHCI supported */
117 HOST_CAP2_APST = (1 << 2), /* Automatic partial to slumber */ 117 HOST_CAP2_APST = (1 << 2), /* Automatic partial to slumber */
118 HOST_CAP2_SDS = (1 << 3), /* Support device sleep */
119 HOST_CAP2_SADM = (1 << 4), /* Support aggressive DevSlp */
120 HOST_CAP2_DESO = (1 << 5), /* DevSlp from slumber only */
118 121
119 /* registers for each SATA port */ 122 /* registers for each SATA port */
120 PORT_LST_ADDR = 0x00, /* command list DMA addr */ 123 PORT_LST_ADDR = 0x00, /* command list DMA addr */
@@ -133,6 +136,7 @@ enum {
133 PORT_SCR_ACT = 0x34, /* SATA phy register: SActive */ 136 PORT_SCR_ACT = 0x34, /* SATA phy register: SActive */
134 PORT_SCR_NTF = 0x3c, /* SATA phy register: SNotification */ 137 PORT_SCR_NTF = 0x3c, /* SATA phy register: SNotification */
135 PORT_FBS = 0x40, /* FIS-based Switching */ 138 PORT_FBS = 0x40, /* FIS-based Switching */
139 PORT_DEVSLP = 0x44, /* device sleep */
136 140
137 /* PORT_IRQ_{STAT,MASK} bits */ 141 /* PORT_IRQ_{STAT,MASK} bits */
138 PORT_IRQ_COLD_PRES = (1 << 31), /* cold presence detect */ 142 PORT_IRQ_COLD_PRES = (1 << 31), /* cold presence detect */
@@ -186,6 +190,7 @@ enum {
186 PORT_CMD_ICC_PARTIAL = (0x2 << 28), /* Put i/f in partial state */ 190 PORT_CMD_ICC_PARTIAL = (0x2 << 28), /* Put i/f in partial state */
187 PORT_CMD_ICC_SLUMBER = (0x6 << 28), /* Put i/f in slumber state */ 191 PORT_CMD_ICC_SLUMBER = (0x6 << 28), /* Put i/f in slumber state */
188 192
193 /* PORT_FBS bits */
189 PORT_FBS_DWE_OFFSET = 16, /* FBS device with error offset */ 194 PORT_FBS_DWE_OFFSET = 16, /* FBS device with error offset */
190 PORT_FBS_ADO_OFFSET = 12, /* FBS active dev optimization offset */ 195 PORT_FBS_ADO_OFFSET = 12, /* FBS active dev optimization offset */
191 PORT_FBS_DEV_OFFSET = 8, /* FBS device to issue offset */ 196 PORT_FBS_DEV_OFFSET = 8, /* FBS device to issue offset */
@@ -194,6 +199,15 @@ enum {
194 PORT_FBS_DEC = (1 << 1), /* FBS device error clear */ 199 PORT_FBS_DEC = (1 << 1), /* FBS device error clear */
195 PORT_FBS_EN = (1 << 0), /* Enable FBS */ 200 PORT_FBS_EN = (1 << 0), /* Enable FBS */
196 201
202 /* PORT_DEVSLP bits */
203 PORT_DEVSLP_DM_OFFSET = 25, /* DITO multiplier offset */
204 PORT_DEVSLP_DM_MASK = (0xf << 25), /* DITO multiplier mask */
205 PORT_DEVSLP_DITO_OFFSET = 15, /* DITO offset */
206 PORT_DEVSLP_MDAT_OFFSET = 10, /* Minimum assertion time */
207 PORT_DEVSLP_DETO_OFFSET = 2, /* DevSlp exit timeout */
208 PORT_DEVSLP_DSP = (1 << 1), /* DevSlp present */
209 PORT_DEVSLP_ADSE = (1 << 0), /* Aggressive DevSlp enable */
210
197 /* hpriv->flags bits */ 211 /* hpriv->flags bits */
198 212
199#define AHCI_HFLAGS(flags) .private_data = (void *)(flags) 213#define AHCI_HFLAGS(flags) .private_data = (void *)(flags)
diff --git a/drivers/ata/libahci.c b/drivers/ata/libahci.c
index 555c07afa05b..4201e535a8c8 100644
--- a/drivers/ata/libahci.c
+++ b/drivers/ata/libahci.c
@@ -45,6 +45,7 @@
45#include <scsi/scsi_cmnd.h> 45#include <scsi/scsi_cmnd.h>
46#include <linux/libata.h> 46#include <linux/libata.h>
47#include "ahci.h" 47#include "ahci.h"
48#include "libata.h"
48 49
49static int ahci_skip_host_reset; 50static int ahci_skip_host_reset;
50int ahci_ignore_sss; 51int ahci_ignore_sss;
@@ -76,6 +77,7 @@ static void ahci_qc_prep(struct ata_queued_cmd *qc);
76static int ahci_pmp_qc_defer(struct ata_queued_cmd *qc); 77static int ahci_pmp_qc_defer(struct ata_queued_cmd *qc);
77static void ahci_freeze(struct ata_port *ap); 78static void ahci_freeze(struct ata_port *ap);
78static void ahci_thaw(struct ata_port *ap); 79static void ahci_thaw(struct ata_port *ap);
80static void ahci_set_aggressive_devslp(struct ata_port *ap, bool sleep);
79static void ahci_enable_fbs(struct ata_port *ap); 81static void ahci_enable_fbs(struct ata_port *ap);
80static void ahci_disable_fbs(struct ata_port *ap); 82static void ahci_disable_fbs(struct ata_port *ap);
81static void ahci_pmp_attach(struct ata_port *ap); 83static void ahci_pmp_attach(struct ata_port *ap);
@@ -193,6 +195,10 @@ module_param(ahci_em_messages, int, 0444);
193MODULE_PARM_DESC(ahci_em_messages, 195MODULE_PARM_DESC(ahci_em_messages,
194 "AHCI Enclosure Management Message control (0 = off, 1 = on)"); 196 "AHCI Enclosure Management Message control (0 = off, 1 = on)");
195 197
198int devslp_idle_timeout = 1000; /* device sleep idle timeout in ms */
199module_param(devslp_idle_timeout, int, 0644);
200MODULE_PARM_DESC(devslp_idle_timeout, "device sleep idle timeout");
201
196static void ahci_enable_ahci(void __iomem *mmio) 202static void ahci_enable_ahci(void __iomem *mmio)
197{ 203{
198 int i; 204 int i;
@@ -702,6 +708,16 @@ static int ahci_set_lpm(struct ata_link *link, enum ata_lpm_policy policy,
702 } 708 }
703 } 709 }
704 710
711 /* set aggressive device sleep */
712 if ((hpriv->cap2 & HOST_CAP2_SDS) &&
713 (hpriv->cap2 & HOST_CAP2_SADM) &&
714 (link->device->flags & ATA_DFLAG_DEVSLP)) {
715 if (policy == ATA_LPM_MIN_POWER)
716 ahci_set_aggressive_devslp(ap, true);
717 else
718 ahci_set_aggressive_devslp(ap, false);
719 }
720
705 if (policy == ATA_LPM_MAX_POWER) { 721 if (policy == ATA_LPM_MAX_POWER) {
706 sata_link_scr_lpm(link, policy, false); 722 sata_link_scr_lpm(link, policy, false);
707 723
@@ -1890,6 +1906,81 @@ static void ahci_post_internal_cmd(struct ata_queued_cmd *qc)
1890 ahci_kick_engine(ap); 1906 ahci_kick_engine(ap);
1891} 1907}
1892 1908
1909static void ahci_set_aggressive_devslp(struct ata_port *ap, bool sleep)
1910{
1911 void __iomem *port_mmio = ahci_port_base(ap);
1912 struct ata_device *dev = ap->link.device;
1913 u32 devslp, dm, dito, mdat, deto;
1914 int rc;
1915 unsigned int err_mask;
1916
1917 devslp = readl(port_mmio + PORT_DEVSLP);
1918 if (!(devslp & PORT_DEVSLP_DSP)) {
1919 dev_err(ap->host->dev, "port does not support device sleep\n");
1920 return;
1921 }
1922
1923 /* disable device sleep */
1924 if (!sleep) {
1925 if (devslp & PORT_DEVSLP_ADSE) {
1926 writel(devslp & ~PORT_DEVSLP_ADSE,
1927 port_mmio + PORT_DEVSLP);
1928 err_mask = ata_dev_set_feature(dev,
1929 SETFEATURES_SATA_DISABLE,
1930 SATA_DEVSLP);
1931 if (err_mask && err_mask != AC_ERR_DEV)
1932 ata_dev_warn(dev, "failed to disable DEVSLP\n");
1933 }
1934 return;
1935 }
1936
1937 /* device sleep was already enabled */
1938 if (devslp & PORT_DEVSLP_ADSE)
1939 return;
1940
1941 /* set DITO, MDAT, DETO and enable DevSlp, need to stop engine first */
1942 rc = ahci_stop_engine(ap);
1943 if (rc)
1944 return;
1945
1946 dm = (devslp & PORT_DEVSLP_DM_MASK) >> PORT_DEVSLP_DM_OFFSET;
1947 dito = devslp_idle_timeout / (dm + 1);
1948 if (dito > 0x3ff)
1949 dito = 0x3ff;
1950
1951 /* Use the nominal value 10 ms if the read MDAT is zero,
1952 * the nominal value of DETO is 20 ms.
1953 */
1954 if (dev->sata_settings[ATA_LOG_DEVSLP_VALID] &
1955 ATA_LOG_DEVSLP_VALID_MASK) {
1956 mdat = dev->sata_settings[ATA_LOG_DEVSLP_MDAT] &
1957 ATA_LOG_DEVSLP_MDAT_MASK;
1958 if (!mdat)
1959 mdat = 10;
1960 deto = dev->sata_settings[ATA_LOG_DEVSLP_DETO];
1961 if (!deto)
1962 deto = 20;
1963 } else {
1964 mdat = 10;
1965 deto = 20;
1966 }
1967
1968 devslp |= ((dito << PORT_DEVSLP_DITO_OFFSET) |
1969 (mdat << PORT_DEVSLP_MDAT_OFFSET) |
1970 (deto << PORT_DEVSLP_DETO_OFFSET) |
1971 PORT_DEVSLP_ADSE);
1972 writel(devslp, port_mmio + PORT_DEVSLP);
1973
1974 ahci_start_engine(ap);
1975
1976 /* enable device sleep feature for the drive */
1977 err_mask = ata_dev_set_feature(dev,
1978 SETFEATURES_SATA_ENABLE,
1979 SATA_DEVSLP);
1980 if (err_mask && err_mask != AC_ERR_DEV)
1981 ata_dev_warn(dev, "failed to enable DEVSLP\n");
1982}
1983
1893static void ahci_enable_fbs(struct ata_port *ap) 1984static void ahci_enable_fbs(struct ata_port *ap)
1894{ 1985{
1895 struct ahci_port_priv *pp = ap->private_data; 1986 struct ahci_port_priv *pp = ap->private_data;
@@ -2164,7 +2255,8 @@ void ahci_print_info(struct ata_host *host, const char *scc_s)
2164 "flags: " 2255 "flags: "
2165 "%s%s%s%s%s%s%s" 2256 "%s%s%s%s%s%s%s"
2166 "%s%s%s%s%s%s%s" 2257 "%s%s%s%s%s%s%s"
2167 "%s%s%s%s%s%s\n" 2258 "%s%s%s%s%s%s%s"
2259 "%s%s\n"
2168 , 2260 ,
2169 2261
2170 cap & HOST_CAP_64 ? "64bit " : "", 2262 cap & HOST_CAP_64 ? "64bit " : "",
@@ -2184,6 +2276,9 @@ void ahci_print_info(struct ata_host *host, const char *scc_s)
2184 cap & HOST_CAP_CCC ? "ccc " : "", 2276 cap & HOST_CAP_CCC ? "ccc " : "",
2185 cap & HOST_CAP_EMS ? "ems " : "", 2277 cap & HOST_CAP_EMS ? "ems " : "",
2186 cap & HOST_CAP_SXS ? "sxs " : "", 2278 cap & HOST_CAP_SXS ? "sxs " : "",
2279 cap2 & HOST_CAP2_DESO ? "deso " : "",
2280 cap2 & HOST_CAP2_SADM ? "sadm " : "",
2281 cap2 & HOST_CAP2_SDS ? "sds " : "",
2187 cap2 & HOST_CAP2_APST ? "apst " : "", 2282 cap2 & HOST_CAP2_APST ? "apst " : "",
2188 cap2 & HOST_CAP2_NVMHCI ? "nvmp " : "", 2283 cap2 & HOST_CAP2_NVMHCI ? "nvmp " : "",
2189 cap2 & HOST_CAP2_BOH ? "boh " : "" 2284 cap2 & HOST_CAP2_BOH ? "boh " : ""
diff --git a/drivers/ata/libata-core.c b/drivers/ata/libata-core.c
index 5eee1c1537d2..25daf39368f6 100644
--- a/drivers/ata/libata-core.c
+++ b/drivers/ata/libata-core.c
@@ -2155,6 +2155,7 @@ int ata_dev_configure(struct ata_device *dev)
2155 int print_info = ehc->i.flags & ATA_EHI_PRINTINFO; 2155 int print_info = ehc->i.flags & ATA_EHI_PRINTINFO;
2156 const u16 *id = dev->id; 2156 const u16 *id = dev->id;
2157 unsigned long xfer_mask; 2157 unsigned long xfer_mask;
2158 unsigned int err_mask;
2158 char revbuf[7]; /* XYZ-99\0 */ 2159 char revbuf[7]; /* XYZ-99\0 */
2159 char fwrevbuf[ATA_ID_FW_REV_LEN+1]; 2160 char fwrevbuf[ATA_ID_FW_REV_LEN+1];
2160 char modelbuf[ATA_ID_PROD_LEN+1]; 2161 char modelbuf[ATA_ID_PROD_LEN+1];
@@ -2323,6 +2324,26 @@ int ata_dev_configure(struct ata_device *dev)
2323 } 2324 }
2324 } 2325 }
2325 2326
2327 /* check and mark DevSlp capability */
2328 if (ata_id_has_devslp(dev->id))
2329 dev->flags |= ATA_DFLAG_DEVSLP;
2330
2331 /* Obtain SATA Settings page from Identify Device Data Log,
2332 * which contains DevSlp timing variables etc.
2333 * Exclude old devices with ata_id_has_ncq()
2334 */
2335 if (ata_id_has_ncq(dev->id)) {
2336 err_mask = ata_read_log_page(dev,
2337 ATA_LOG_SATA_ID_DEV_DATA,
2338 ATA_LOG_SATA_SETTINGS,
2339 dev->sata_settings,
2340 1);
2341 if (err_mask)
2342 ata_dev_dbg(dev,
2343 "failed to get Identify Device Data, Emask 0x%x\n",
2344 err_mask);
2345 }
2346
2326 dev->cdb_len = 16; 2347 dev->cdb_len = 16;
2327 } 2348 }
2328 2349
@@ -2351,8 +2372,6 @@ int ata_dev_configure(struct ata_device *dev)
2351 (ap->flags & ATA_FLAG_AN) && ata_id_has_atapi_AN(id) && 2372 (ap->flags & ATA_FLAG_AN) && ata_id_has_atapi_AN(id) &&
2352 (!sata_pmp_attached(ap) || 2373 (!sata_pmp_attached(ap) ||
2353 sata_scr_read(&ap->link, SCR_NOTIFICATION, &sntf) == 0)) { 2374 sata_scr_read(&ap->link, SCR_NOTIFICATION, &sntf) == 0)) {
2354 unsigned int err_mask;
2355
2356 /* issue SET feature command to turn this on */ 2375 /* issue SET feature command to turn this on */
2357 err_mask = ata_dev_set_feature(dev, 2376 err_mask = ata_dev_set_feature(dev,
2358 SETFEATURES_SATA_ENABLE, SATA_AN); 2377 SETFEATURES_SATA_ENABLE, SATA_AN);
@@ -3598,7 +3617,7 @@ int sata_link_scr_lpm(struct ata_link *link, enum ata_lpm_policy policy,
3598 switch (policy) { 3617 switch (policy) {
3599 case ATA_LPM_MAX_POWER: 3618 case ATA_LPM_MAX_POWER:
3600 /* disable all LPM transitions */ 3619 /* disable all LPM transitions */
3601 scontrol |= (0x3 << 8); 3620 scontrol |= (0x7 << 8);
3602 /* initiate transition to active state */ 3621 /* initiate transition to active state */
3603 if (spm_wakeup) { 3622 if (spm_wakeup) {
3604 scontrol |= (0x4 << 12); 3623 scontrol |= (0x4 << 12);
@@ -3608,12 +3627,12 @@ int sata_link_scr_lpm(struct ata_link *link, enum ata_lpm_policy policy,
3608 case ATA_LPM_MED_POWER: 3627 case ATA_LPM_MED_POWER:
3609 /* allow LPM to PARTIAL */ 3628 /* allow LPM to PARTIAL */
3610 scontrol &= ~(0x1 << 8); 3629 scontrol &= ~(0x1 << 8);
3611 scontrol |= (0x2 << 8); 3630 scontrol |= (0x6 << 8);
3612 break; 3631 break;
3613 case ATA_LPM_MIN_POWER: 3632 case ATA_LPM_MIN_POWER:
3614 if (ata_link_nr_enabled(link) > 0) 3633 if (ata_link_nr_enabled(link) > 0)
3615 /* no restrictions on LPM transitions */ 3634 /* no restrictions on LPM transitions */
3616 scontrol &= ~(0x3 << 8); 3635 scontrol &= ~(0x7 << 8);
3617 else { 3636 else {
3618 /* empty port, power off */ 3637 /* empty port, power off */
3619 scontrol &= ~0xf; 3638 scontrol &= ~0xf;
diff --git a/drivers/ata/libata-eh.c b/drivers/ata/libata-eh.c
index 7d4535e989bf..26598941e1b3 100644
--- a/drivers/ata/libata-eh.c
+++ b/drivers/ata/libata-eh.c
@@ -1487,6 +1487,7 @@ static const char *ata_err_string(unsigned int err_mask)
1487/** 1487/**
1488 * ata_read_log_page - read a specific log page 1488 * ata_read_log_page - read a specific log page
1489 * @dev: target device 1489 * @dev: target device
1490 * @log: log to read
1490 * @page: page to read 1491 * @page: page to read
1491 * @buf: buffer to store read page 1492 * @buf: buffer to store read page
1492 * @sectors: number of sectors to read 1493 * @sectors: number of sectors to read
@@ -1499,17 +1500,18 @@ static const char *ata_err_string(unsigned int err_mask)
1499 * RETURNS: 1500 * RETURNS:
1500 * 0 on success, AC_ERR_* mask otherwise. 1501 * 0 on success, AC_ERR_* mask otherwise.
1501 */ 1502 */
1502static unsigned int ata_read_log_page(struct ata_device *dev, 1503unsigned int ata_read_log_page(struct ata_device *dev, u8 log,
1503 u8 page, void *buf, unsigned int sectors) 1504 u8 page, void *buf, unsigned int sectors)
1504{ 1505{
1505 struct ata_taskfile tf; 1506 struct ata_taskfile tf;
1506 unsigned int err_mask; 1507 unsigned int err_mask;
1507 1508
1508 DPRINTK("read log page - page %d\n", page); 1509 DPRINTK("read log page - log 0x%x, page 0x%x\n", log, page);
1509 1510
1510 ata_tf_init(dev, &tf); 1511 ata_tf_init(dev, &tf);
1511 tf.command = ATA_CMD_READ_LOG_EXT; 1512 tf.command = ATA_CMD_READ_LOG_EXT;
1512 tf.lbal = page; 1513 tf.lbal = log;
1514 tf.lbam = page;
1513 tf.nsect = sectors; 1515 tf.nsect = sectors;
1514 tf.hob_nsect = sectors >> 8; 1516 tf.hob_nsect = sectors >> 8;
1515 tf.flags |= ATA_TFLAG_ISADDR | ATA_TFLAG_LBA48 | ATA_TFLAG_DEVICE; 1517 tf.flags |= ATA_TFLAG_ISADDR | ATA_TFLAG_LBA48 | ATA_TFLAG_DEVICE;
@@ -1545,7 +1547,7 @@ static int ata_eh_read_log_10h(struct ata_device *dev,
1545 u8 csum; 1547 u8 csum;
1546 int i; 1548 int i;
1547 1549
1548 err_mask = ata_read_log_page(dev, ATA_LOG_SATA_NCQ, buf, 1); 1550 err_mask = ata_read_log_page(dev, ATA_LOG_SATA_NCQ, 0, buf, 1);
1549 if (err_mask) 1551 if (err_mask)
1550 return -EIO; 1552 return -EIO;
1551 1553
diff --git a/drivers/ata/libata.h b/drivers/ata/libata.h
index 50e4dff0604e..7148a58020b9 100644
--- a/drivers/ata/libata.h
+++ b/drivers/ata/libata.h
@@ -165,6 +165,8 @@ extern void ata_eh_about_to_do(struct ata_link *link, struct ata_device *dev,
165 unsigned int action); 165 unsigned int action);
166extern void ata_eh_done(struct ata_link *link, struct ata_device *dev, 166extern void ata_eh_done(struct ata_link *link, struct ata_device *dev,
167 unsigned int action); 167 unsigned int action);
168extern unsigned int ata_read_log_page(struct ata_device *dev, u8 log,
169 u8 page, void *buf, unsigned int sectors);
168extern void ata_eh_autopsy(struct ata_port *ap); 170extern void ata_eh_autopsy(struct ata_port *ap);
169const char *ata_get_cmd_descript(u8 command); 171const char *ata_get_cmd_descript(u8 command);
170extern void ata_eh_report(struct ata_port *ap); 172extern void ata_eh_report(struct ata_port *ap);