From: maksim.rayskiy@gmail.com
To: linux-scsi@vger.kernel.org, tj@kernel.org
Subject: [RFC] Deferred disk spinup during system resume
Date: Thu, 6 Jan 2011 12:20:25 -0800 [thread overview]
Message-ID: <1294345225-28407-1-git-send-email-maksim.rayskiy@gmail.com> (raw)
Tejun,
Thanks and sorry for late response, I was testing the patch on several platforms,
including the ones with sata-based rootfs. The patch seems to be working fine for me.
I only had to include ATA_EH_VERIFY into ATA_EH_PERDEV_MASK mask to avoid warning
from ata_eh_clear_action().
Are you going to submit the patch to the mainline?
Maksim.
---
drivers/ata/libata-eh.c | 45 +++++++++++++++++++++++++++++++++++++++++++++
drivers/ata/libata-scsi.c | 21 ++++-----------------
include/linux/libata.h | 4 +++-
3 files changed, 52 insertions(+), 18 deletions(-)
diff --git a/drivers/ata/libata-eh.c b/drivers/ata/libata-eh.c
index 5e59050..3823bc6 100644
--- a/drivers/ata/libata-eh.c
+++ b/drivers/ata/libata-eh.c
@@ -3252,6 +3252,48 @@ static int ata_eh_maybe_retry_flush(struct ata_device *dev)
return rc;
}
+static int ata_eh_maybe_verify(struct ata_device *dev)
+{
+ struct ata_link *link = dev->link;
+ struct ata_taskfile tf;
+ unsigned int err_mask;
+ int rc = 0;
+
+ ata_eh_about_to_do(link, dev, ATA_EH_VERIFY);
+
+ ata_tf_init(dev, &tf);
+
+ if (dev->flags & ATA_DFLAG_LBA) {
+ tf.flags |= ATA_TFLAG_LBA;
+
+ tf.lbah = 0x0;
+ tf.lbam = 0x0;
+ tf.lbal = 0x0;
+ tf.device |= ATA_LBA;
+ } else {
+ /* CHS */
+ tf.lbal = 0x1; /* sect */
+ tf.lbam = 0x0; /* cyl low */
+ tf.lbah = 0x0; /* cyl high */
+ }
+
+ tf.command = ATA_CMD_VERIFY; /* READ VERIFY */
+ tf.flags |= ATA_TFLAG_ISADDR | ATA_TFLAG_LBA48 | ATA_TFLAG_DEVICE;
+ tf.protocol = ATA_PROT_NODATA;
+
+ err_mask = ata_exec_internal(dev, &tf, NULL, DMA_NONE, NULL, 0, 0);
+ if (err_mask) {
+ ata_dev_printk(dev, KERN_WARNING,
+ "READ_VERIFY failed Emask 0x%x\n", err_mask);
+ rc = -EIO;
+ }
+
+ /* don't retry VERIFY */
+ ata_eh_done(link, dev, ATA_EH_VERIFY);
+
+ return rc;
+}
+
/**
* ata_eh_set_lpm - configure SATA interface power management
* @link: link to configure power management
@@ -3738,6 +3780,9 @@ int ata_eh_recover(struct ata_port *ap, ata_prereset_fn_t prereset,
rc = ata_eh_maybe_retry_flush(dev);
if (rc)
goto rest_fail;
+ rc = ata_eh_maybe_verify(dev);
+ if (rc)
+ goto rest_fail;
}
config_lpm:
diff --git a/drivers/ata/libata-scsi.c b/drivers/ata/libata-scsi.c
index 66aa4be..ae8d9ca 100644
--- a/drivers/ata/libata-scsi.c
+++ b/drivers/ata/libata-scsi.c
@@ -1276,6 +1276,7 @@ int ata_scsi_change_queue_depth(struct scsi_device *sdev, int queue_depth,
*/
static unsigned int ata_scsi_start_stop_xlat(struct ata_queued_cmd *qc)
{
+ struct ata_device *dev = qc->dev;
struct scsi_cmnd *scmd = qc->scsicmd;
struct ata_taskfile *tf = &qc->tf;
const u8 *cdb = scmd->cmnd;
@@ -1294,23 +1295,9 @@ static unsigned int ata_scsi_start_stop_xlat(struct ata_queued_cmd *qc)
goto invalid_fld; /* power conditions not supported */
if (cdb[4] & 0x1) {
- tf->nsect = 1; /* 1 sector, lba=0 */
-
- if (qc->dev->flags & ATA_DFLAG_LBA) {
- tf->flags |= ATA_TFLAG_LBA;
-
- tf->lbah = 0x0;
- tf->lbam = 0x0;
- tf->lbal = 0x0;
- tf->device |= ATA_LBA;
- } else {
- /* CHS */
- tf->lbal = 0x1; /* sect */
- tf->lbam = 0x0; /* cyl low */
- tf->lbah = 0x0; /* cyl high */
- }
-
- tf->command = ATA_CMD_VERIFY; /* READ VERIFY */
+ dev->link->eh_info.dev_action[dev->devno] |= ATA_EH_VERIFY;
+ ata_port_schedule_eh(dev->link->ap);
+ goto skip;
} else {
/* Some odd clown BIOSen issue spindown on power off (ACPI S4
* or S5) causing some drives to spin up and down again.
diff --git a/include/linux/libata.h b/include/linux/libata.h
index d947b12..5d91fd0 100644
--- a/include/linux/libata.h
+++ b/include/linux/libata.h
@@ -326,9 +326,11 @@ enum {
ATA_EH_HARDRESET = (1 << 2), /* meaningful only in ->prereset */
ATA_EH_RESET = ATA_EH_SOFTRESET | ATA_EH_HARDRESET,
ATA_EH_ENABLE_LINK = (1 << 3),
+ ATA_EH_VERIFY = (1 << 4), /* used to force spin up */
ATA_EH_PARK = (1 << 5), /* unload heads and stop I/O */
- ATA_EH_PERDEV_MASK = ATA_EH_REVALIDATE | ATA_EH_PARK,
+ ATA_EH_PERDEV_MASK = ATA_EH_REVALIDATE | ATA_EH_PARK |
+ ATA_EH_VERIFY,
ATA_EH_ALL_ACTIONS = ATA_EH_REVALIDATE | ATA_EH_RESET |
ATA_EH_ENABLE_LINK,
--
1.7.0.4
next reply other threads:[~2011-01-06 20:21 UTC|newest]
Thread overview: 7+ messages / expand[flat|nested] mbox.gz Atom feed top
2011-01-06 20:20 maksim.rayskiy [this message]
2011-01-06 22:12 ` [RFC] Deferred disk spinup during system resume Jeff Garzik
-- strict thread matches above, loose matches on Subject: below --
2011-01-07 1:27 maksim.rayskiy
2011-01-07 19:06 ` Tejun Heo
2011-01-07 19:29 ` Jeff Garzik
2011-01-07 20:46 ` Maksim Rayskiy
2010-12-30 19:40 Maksim Rayskiy
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=1294345225-28407-1-git-send-email-maksim.rayskiy@gmail.com \
--to=maksim.rayskiy@gmail.com \
--cc=linux-scsi@vger.kernel.org \
--cc=tj@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