aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/ata/libata-core.c
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/libata-core.c
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/libata-core.c')
-rw-r--r--drivers/ata/libata-core.c29
1 files changed, 24 insertions, 5 deletions
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;