* [linux-pm] [RFC] Deferred disk spinup during system resume
@ 2011-01-07 1:17 maksim.rayskiy
2011-01-07 3:16 ` Jeff Garzik
0 siblings, 1 reply; 7+ messages in thread
From: maksim.rayskiy @ 2011-01-07 1:17 UTC (permalink / raw)
To: linux-scsi, tj, jgarzik; +Cc: Maksim Rayskiy
Jeff,
Okay, I moved EH scheduling to ata_qc_issue(). But since now START taskfile is
created in ata_eh_maybe_verify() I do not see why the same code has to
remain in ata_scsi_start_stop_xlat. Does it make sense?
Maksim.
Signed-off-by: Maksim Rayskiy <maksim.rayskiy@gmail.com>
---
drivers/ata/libata-core.c | 8 ++
drivers/ata/libata-eh.c | 45 ++++++++
drivers/ata/libata-scsi.c | 24 +----
drivers/char/defkeymap.c | 262 +++++++++++++++++++++++++++++++++++++++++++++
include/linux/libata.h | 4 +-
5 files changed, 323 insertions(+), 20 deletions(-)
create mode 100644 drivers/char/defkeymap.c
diff --git a/drivers/ata/libata-core.c b/drivers/ata/libata-core.c
index 7f77c67..0a9d400 100644
--- a/drivers/ata/libata-core.c
+++ b/drivers/ata/libata-core.c
@@ -4978,6 +4978,14 @@ void ata_qc_issue(struct ata_queued_cmd *qc)
struct ata_link *link = qc->dev->link;
u8 prot = qc->tf.protocol;
+ if (unlikely(link->eh_info.dev_action[qc->dev->devno] &
+ ATA_EH_VERIFY)) {
+ ata_port_schedule_eh(ap);
+ qc->scsidone(qc->scsicmd);
+ ata_qc_free(qc);
+ return;
+ }
+
/* Make sure only one non-NCQ command is outstanding. The
* check is skipped for old EH because it reuses active qc to
* request ATAPI sense.
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..aadcd0d 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;
@@ -1293,25 +1294,10 @@ static unsigned int ata_scsi_start_stop_xlat(struct ata_queued_cmd *qc)
if (((cdb[4] >> 4) & 0xf) != 0)
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 */
- } else {
+ if (cdb[4] & 0x1)
+ /* spinup is asynchronous */
+ dev->link->eh_info.dev_action[dev->devno] |= ATA_EH_VERIFY;
+ 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/drivers/char/defkeymap.c b/drivers/char/defkeymap.c
new file mode 100644
index 0000000..d2208df
--- /dev/null
+++ b/drivers/char/defkeymap.c
@@ -0,0 +1,262 @@
+/* Do not edit this file! It was automatically generated by */
+/* loadkeys --mktable defkeymap.map > defkeymap.c */
+
+#include <linux/types.h>
+#include <linux/keyboard.h>
+#include <linux/kd.h>
+
+u_short plain_map[NR_KEYS] = {
+ 0xf200, 0xf01b, 0xf031, 0xf032, 0xf033, 0xf034, 0xf035, 0xf036,
+ 0xf037, 0xf038, 0xf039, 0xf030, 0xf02d, 0xf03d, 0xf07f, 0xf009,
+ 0xfb71, 0xfb77, 0xfb65, 0xfb72, 0xfb74, 0xfb79, 0xfb75, 0xfb69,
+ 0xfb6f, 0xfb70, 0xf05b, 0xf05d, 0xf201, 0xf702, 0xfb61, 0xfb73,
+ 0xfb64, 0xfb66, 0xfb67, 0xfb68, 0xfb6a, 0xfb6b, 0xfb6c, 0xf03b,
+ 0xf027, 0xf060, 0xf700, 0xf05c, 0xfb7a, 0xfb78, 0xfb63, 0xfb76,
+ 0xfb62, 0xfb6e, 0xfb6d, 0xf02c, 0xf02e, 0xf02f, 0xf700, 0xf30c,
+ 0xf703, 0xf020, 0xf207, 0xf100, 0xf101, 0xf102, 0xf103, 0xf104,
+ 0xf105, 0xf106, 0xf107, 0xf108, 0xf109, 0xf208, 0xf209, 0xf307,
+ 0xf308, 0xf309, 0xf30b, 0xf304, 0xf305, 0xf306, 0xf30a, 0xf301,
+ 0xf302, 0xf303, 0xf300, 0xf310, 0xf206, 0xf200, 0xf03c, 0xf10a,
+ 0xf10b, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200,
+ 0xf30e, 0xf702, 0xf30d, 0xf01c, 0xf701, 0xf205, 0xf114, 0xf603,
+ 0xf118, 0xf601, 0xf602, 0xf117, 0xf600, 0xf119, 0xf115, 0xf116,
+ 0xf11a, 0xf10c, 0xf10d, 0xf11b, 0xf11c, 0xf110, 0xf311, 0xf11d,
+ 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200,
+};
+
+u_short shift_map[NR_KEYS] = {
+ 0xf200, 0xf01b, 0xf021, 0xf040, 0xf023, 0xf024, 0xf025, 0xf05e,
+ 0xf026, 0xf02a, 0xf028, 0xf029, 0xf05f, 0xf02b, 0xf07f, 0xf009,
+ 0xfb51, 0xfb57, 0xfb45, 0xfb52, 0xfb54, 0xfb59, 0xfb55, 0xfb49,
+ 0xfb4f, 0xfb50, 0xf07b, 0xf07d, 0xf201, 0xf702, 0xfb41, 0xfb53,
+ 0xfb44, 0xfb46, 0xfb47, 0xfb48, 0xfb4a, 0xfb4b, 0xfb4c, 0xf03a,
+ 0xf022, 0xf07e, 0xf700, 0xf07c, 0xfb5a, 0xfb58, 0xfb43, 0xfb56,
+ 0xfb42, 0xfb4e, 0xfb4d, 0xf03c, 0xf03e, 0xf03f, 0xf700, 0xf30c,
+ 0xf703, 0xf020, 0xf207, 0xf10a, 0xf10b, 0xf10c, 0xf10d, 0xf10e,
+ 0xf10f, 0xf110, 0xf111, 0xf112, 0xf113, 0xf213, 0xf203, 0xf307,
+ 0xf308, 0xf309, 0xf30b, 0xf304, 0xf305, 0xf306, 0xf30a, 0xf301,
+ 0xf302, 0xf303, 0xf300, 0xf310, 0xf206, 0xf200, 0xf03e, 0xf10a,
+ 0xf10b, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200,
+ 0xf30e, 0xf702, 0xf30d, 0xf200, 0xf701, 0xf205, 0xf114, 0xf603,
+ 0xf20b, 0xf601, 0xf602, 0xf117, 0xf600, 0xf20a, 0xf115, 0xf116,
+ 0xf11a, 0xf10c, 0xf10d, 0xf11b, 0xf11c, 0xf110, 0xf311, 0xf11d,
+ 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200,
+};
+
+u_short altgr_map[NR_KEYS] = {
+ 0xf200, 0xf200, 0xf200, 0xf040, 0xf200, 0xf024, 0xf200, 0xf200,
+ 0xf07b, 0xf05b, 0xf05d, 0xf07d, 0xf05c, 0xf200, 0xf200, 0xf200,
+ 0xfb71, 0xfb77, 0xf918, 0xfb72, 0xfb74, 0xfb79, 0xfb75, 0xfb69,
+ 0xfb6f, 0xfb70, 0xf200, 0xf07e, 0xf201, 0xf702, 0xf914, 0xfb73,
+ 0xf917, 0xf919, 0xfb67, 0xfb68, 0xfb6a, 0xfb6b, 0xfb6c, 0xf200,
+ 0xf200, 0xf200, 0xf700, 0xf200, 0xfb7a, 0xfb78, 0xf916, 0xfb76,
+ 0xf915, 0xfb6e, 0xfb6d, 0xf200, 0xf200, 0xf200, 0xf700, 0xf30c,
+ 0xf703, 0xf200, 0xf207, 0xf50c, 0xf50d, 0xf50e, 0xf50f, 0xf510,
+ 0xf511, 0xf512, 0xf513, 0xf514, 0xf515, 0xf208, 0xf202, 0xf911,
+ 0xf912, 0xf913, 0xf30b, 0xf90e, 0xf90f, 0xf910, 0xf30a, 0xf90b,
+ 0xf90c, 0xf90d, 0xf90a, 0xf310, 0xf206, 0xf200, 0xf07c, 0xf516,
+ 0xf517, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200,
+ 0xf30e, 0xf702, 0xf30d, 0xf200, 0xf701, 0xf205, 0xf114, 0xf603,
+ 0xf118, 0xf601, 0xf602, 0xf117, 0xf600, 0xf119, 0xf115, 0xf116,
+ 0xf11a, 0xf10c, 0xf10d, 0xf11b, 0xf11c, 0xf110, 0xf311, 0xf11d,
+ 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200,
+};
+
+u_short ctrl_map[NR_KEYS] = {
+ 0xf200, 0xf200, 0xf200, 0xf000, 0xf01b, 0xf01c, 0xf01d, 0xf01e,
+ 0xf01f, 0xf07f, 0xf200, 0xf200, 0xf01f, 0xf200, 0xf008, 0xf200,
+ 0xf011, 0xf017, 0xf005, 0xf012, 0xf014, 0xf019, 0xf015, 0xf009,
+ 0xf00f, 0xf010, 0xf01b, 0xf01d, 0xf201, 0xf702, 0xf001, 0xf013,
+ 0xf004, 0xf006, 0xf007, 0xf008, 0xf00a, 0xf00b, 0xf00c, 0xf200,
+ 0xf007, 0xf000, 0xf700, 0xf01c, 0xf01a, 0xf018, 0xf003, 0xf016,
+ 0xf002, 0xf00e, 0xf00d, 0xf200, 0xf20e, 0xf07f, 0xf700, 0xf30c,
+ 0xf703, 0xf000, 0xf207, 0xf100, 0xf101, 0xf102, 0xf103, 0xf104,
+ 0xf105, 0xf106, 0xf107, 0xf108, 0xf109, 0xf208, 0xf204, 0xf307,
+ 0xf308, 0xf309, 0xf30b, 0xf304, 0xf305, 0xf306, 0xf30a, 0xf301,
+ 0xf302, 0xf303, 0xf300, 0xf310, 0xf206, 0xf200, 0xf200, 0xf10a,
+ 0xf10b, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200,
+ 0xf30e, 0xf702, 0xf30d, 0xf01c, 0xf701, 0xf205, 0xf114, 0xf603,
+ 0xf118, 0xf601, 0xf602, 0xf117, 0xf600, 0xf119, 0xf115, 0xf116,
+ 0xf11a, 0xf10c, 0xf10d, 0xf11b, 0xf11c, 0xf110, 0xf311, 0xf11d,
+ 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200,
+};
+
+u_short shift_ctrl_map[NR_KEYS] = {
+ 0xf200, 0xf200, 0xf200, 0xf000, 0xf200, 0xf200, 0xf200, 0xf200,
+ 0xf200, 0xf200, 0xf200, 0xf200, 0xf01f, 0xf200, 0xf200, 0xf200,
+ 0xf011, 0xf017, 0xf005, 0xf012, 0xf014, 0xf019, 0xf015, 0xf009,
+ 0xf00f, 0xf010, 0xf200, 0xf200, 0xf201, 0xf702, 0xf001, 0xf013,
+ 0xf004, 0xf006, 0xf007, 0xf008, 0xf00a, 0xf00b, 0xf00c, 0xf200,
+ 0xf200, 0xf200, 0xf700, 0xf200, 0xf01a, 0xf018, 0xf003, 0xf016,
+ 0xf002, 0xf00e, 0xf00d, 0xf200, 0xf200, 0xf200, 0xf700, 0xf30c,
+ 0xf703, 0xf200, 0xf207, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200,
+ 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf208, 0xf200, 0xf307,
+ 0xf308, 0xf309, 0xf30b, 0xf304, 0xf305, 0xf306, 0xf30a, 0xf301,
+ 0xf302, 0xf303, 0xf300, 0xf310, 0xf206, 0xf200, 0xf200, 0xf200,
+ 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200,
+ 0xf30e, 0xf702, 0xf30d, 0xf200, 0xf701, 0xf205, 0xf114, 0xf603,
+ 0xf118, 0xf601, 0xf602, 0xf117, 0xf600, 0xf119, 0xf115, 0xf116,
+ 0xf11a, 0xf10c, 0xf10d, 0xf11b, 0xf11c, 0xf110, 0xf311, 0xf11d,
+ 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200,
+};
+
+u_short alt_map[NR_KEYS] = {
+ 0xf200, 0xf81b, 0xf831, 0xf832, 0xf833, 0xf834, 0xf835, 0xf836,
+ 0xf837, 0xf838, 0xf839, 0xf830, 0xf82d, 0xf83d, 0xf87f, 0xf809,
+ 0xf871, 0xf877, 0xf865, 0xf872, 0xf874, 0xf879, 0xf875, 0xf869,
+ 0xf86f, 0xf870, 0xf85b, 0xf85d, 0xf80d, 0xf702, 0xf861, 0xf873,
+ 0xf864, 0xf866, 0xf867, 0xf868, 0xf86a, 0xf86b, 0xf86c, 0xf83b,
+ 0xf827, 0xf860, 0xf700, 0xf85c, 0xf87a, 0xf878, 0xf863, 0xf876,
+ 0xf862, 0xf86e, 0xf86d, 0xf82c, 0xf82e, 0xf82f, 0xf700, 0xf30c,
+ 0xf703, 0xf820, 0xf207, 0xf500, 0xf501, 0xf502, 0xf503, 0xf504,
+ 0xf505, 0xf506, 0xf507, 0xf508, 0xf509, 0xf208, 0xf209, 0xf907,
+ 0xf908, 0xf909, 0xf30b, 0xf904, 0xf905, 0xf906, 0xf30a, 0xf901,
+ 0xf902, 0xf903, 0xf900, 0xf310, 0xf206, 0xf200, 0xf83c, 0xf50a,
+ 0xf50b, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200,
+ 0xf30e, 0xf702, 0xf30d, 0xf01c, 0xf701, 0xf205, 0xf114, 0xf603,
+ 0xf118, 0xf210, 0xf211, 0xf117, 0xf600, 0xf119, 0xf115, 0xf116,
+ 0xf11a, 0xf10c, 0xf10d, 0xf11b, 0xf11c, 0xf110, 0xf311, 0xf11d,
+ 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200,
+};
+
+u_short ctrl_alt_map[NR_KEYS] = {
+ 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200,
+ 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200,
+ 0xf811, 0xf817, 0xf805, 0xf812, 0xf814, 0xf819, 0xf815, 0xf809,
+ 0xf80f, 0xf810, 0xf200, 0xf200, 0xf201, 0xf702, 0xf801, 0xf813,
+ 0xf804, 0xf806, 0xf807, 0xf808, 0xf80a, 0xf80b, 0xf80c, 0xf200,
+ 0xf200, 0xf200, 0xf700, 0xf200, 0xf81a, 0xf818, 0xf803, 0xf816,
+ 0xf802, 0xf80e, 0xf80d, 0xf200, 0xf200, 0xf200, 0xf700, 0xf30c,
+ 0xf703, 0xf200, 0xf207, 0xf500, 0xf501, 0xf502, 0xf503, 0xf504,
+ 0xf505, 0xf506, 0xf507, 0xf508, 0xf509, 0xf208, 0xf200, 0xf307,
+ 0xf308, 0xf309, 0xf30b, 0xf304, 0xf305, 0xf306, 0xf30a, 0xf301,
+ 0xf302, 0xf303, 0xf300, 0xf20c, 0xf206, 0xf200, 0xf200, 0xf50a,
+ 0xf50b, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200,
+ 0xf30e, 0xf702, 0xf30d, 0xf200, 0xf701, 0xf205, 0xf114, 0xf603,
+ 0xf118, 0xf601, 0xf602, 0xf117, 0xf600, 0xf119, 0xf115, 0xf20c,
+ 0xf11a, 0xf10c, 0xf10d, 0xf11b, 0xf11c, 0xf110, 0xf311, 0xf11d,
+ 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200,
+};
+
+ushort *key_maps[MAX_NR_KEYMAPS] = {
+ plain_map, shift_map, altgr_map, NULL,
+ ctrl_map, shift_ctrl_map, NULL, NULL,
+ alt_map, NULL, NULL, NULL,
+ ctrl_alt_map, NULL
+};
+
+unsigned int keymap_count = 7;
+
+/*
+ * Philosophy: most people do not define more strings, but they who do
+ * often want quite a lot of string space. So, we statically allocate
+ * the default and allocate dynamically in chunks of 512 bytes.
+ */
+
+char func_buf[] = {
+ '\033', '[', '[', 'A', 0,
+ '\033', '[', '[', 'B', 0,
+ '\033', '[', '[', 'C', 0,
+ '\033', '[', '[', 'D', 0,
+ '\033', '[', '[', 'E', 0,
+ '\033', '[', '1', '7', '~', 0,
+ '\033', '[', '1', '8', '~', 0,
+ '\033', '[', '1', '9', '~', 0,
+ '\033', '[', '2', '0', '~', 0,
+ '\033', '[', '2', '1', '~', 0,
+ '\033', '[', '2', '3', '~', 0,
+ '\033', '[', '2', '4', '~', 0,
+ '\033', '[', '2', '5', '~', 0,
+ '\033', '[', '2', '6', '~', 0,
+ '\033', '[', '2', '8', '~', 0,
+ '\033', '[', '2', '9', '~', 0,
+ '\033', '[', '3', '1', '~', 0,
+ '\033', '[', '3', '2', '~', 0,
+ '\033', '[', '3', '3', '~', 0,
+ '\033', '[', '3', '4', '~', 0,
+ '\033', '[', '1', '~', 0,
+ '\033', '[', '2', '~', 0,
+ '\033', '[', '3', '~', 0,
+ '\033', '[', '4', '~', 0,
+ '\033', '[', '5', '~', 0,
+ '\033', '[', '6', '~', 0,
+ '\033', '[', 'M', 0,
+ '\033', '[', 'P', 0,
+};
+
+char *funcbufptr = func_buf;
+int funcbufsize = sizeof(func_buf);
+int funcbufleft = 0; /* space left */
+
+char *func_table[MAX_NR_FUNC] = {
+ func_buf + 0,
+ func_buf + 5,
+ func_buf + 10,
+ func_buf + 15,
+ func_buf + 20,
+ func_buf + 25,
+ func_buf + 31,
+ func_buf + 37,
+ func_buf + 43,
+ func_buf + 49,
+ func_buf + 55,
+ func_buf + 61,
+ func_buf + 67,
+ func_buf + 73,
+ func_buf + 79,
+ func_buf + 85,
+ func_buf + 91,
+ func_buf + 97,
+ func_buf + 103,
+ func_buf + 109,
+ func_buf + 115,
+ func_buf + 120,
+ func_buf + 125,
+ func_buf + 130,
+ func_buf + 135,
+ func_buf + 140,
+ func_buf + 145,
+ NULL,
+ NULL,
+ func_buf + 149,
+ NULL,
+};
+
+struct kbdiacruc accent_table[MAX_DIACR] = {
+ {'`', 'A', 0300}, {'`', 'a', 0340},
+ {'\'', 'A', 0301}, {'\'', 'a', 0341},
+ {'^', 'A', 0302}, {'^', 'a', 0342},
+ {'~', 'A', 0303}, {'~', 'a', 0343},
+ {'"', 'A', 0304}, {'"', 'a', 0344},
+ {'O', 'A', 0305}, {'o', 'a', 0345},
+ {'0', 'A', 0305}, {'0', 'a', 0345},
+ {'A', 'A', 0305}, {'a', 'a', 0345},
+ {'A', 'E', 0306}, {'a', 'e', 0346},
+ {',', 'C', 0307}, {',', 'c', 0347},
+ {'`', 'E', 0310}, {'`', 'e', 0350},
+ {'\'', 'E', 0311}, {'\'', 'e', 0351},
+ {'^', 'E', 0312}, {'^', 'e', 0352},
+ {'"', 'E', 0313}, {'"', 'e', 0353},
+ {'`', 'I', 0314}, {'`', 'i', 0354},
+ {'\'', 'I', 0315}, {'\'', 'i', 0355},
+ {'^', 'I', 0316}, {'^', 'i', 0356},
+ {'"', 'I', 0317}, {'"', 'i', 0357},
+ {'-', 'D', 0320}, {'-', 'd', 0360},
+ {'~', 'N', 0321}, {'~', 'n', 0361},
+ {'`', 'O', 0322}, {'`', 'o', 0362},
+ {'\'', 'O', 0323}, {'\'', 'o', 0363},
+ {'^', 'O', 0324}, {'^', 'o', 0364},
+ {'~', 'O', 0325}, {'~', 'o', 0365},
+ {'"', 'O', 0326}, {'"', 'o', 0366},
+ {'/', 'O', 0330}, {'/', 'o', 0370},
+ {'`', 'U', 0331}, {'`', 'u', 0371},
+ {'\'', 'U', 0332}, {'\'', 'u', 0372},
+ {'^', 'U', 0333}, {'^', 'u', 0373},
+ {'"', 'U', 0334}, {'"', 'u', 0374},
+ {'\'', 'Y', 0335}, {'\'', 'y', 0375},
+ {'T', 'H', 0336}, {'t', 'h', 0376},
+ {'s', 's', 0337}, {'"', 'y', 0377},
+ {'s', 'z', 0337}, {'i', 'j', 0377},
+};
+
+unsigned int accent_table_size = 68;
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
^ permalink raw reply related [flat|nested] 7+ messages in thread* Re: [linux-pm] [RFC] Deferred disk spinup during system resume
2011-01-07 1:17 [linux-pm] [RFC] Deferred disk spinup during system resume maksim.rayskiy
@ 2011-01-07 3:16 ` Jeff Garzik
2011-01-07 3:46 ` Maksim Rayskiy
0 siblings, 1 reply; 7+ messages in thread
From: Jeff Garzik @ 2011-01-07 3:16 UTC (permalink / raw)
To: maksim.rayskiy; +Cc: linux-scsi, tj
On 01/06/2011 08:17 PM, maksim.rayskiy@gmail.com wrote:
> Jeff,
>
> Okay, I moved EH scheduling to ata_qc_issue(). But since now START taskfile is
> created in ata_eh_maybe_verify() I do not see why the same code has to
> remain in ata_scsi_start_stop_xlat. Does it make sense?
The taskfile you are to pass to the hardware is created in
atapi_start_stop_xlat(), so you should not create a new taskfile in
ata_eh_maybe_verify()
Jeff
^ permalink raw reply [flat|nested] 7+ messages in thread
* Re: [linux-pm] [RFC] Deferred disk spinup during system resume
2011-01-07 3:16 ` Jeff Garzik
@ 2011-01-07 3:46 ` Maksim Rayskiy
0 siblings, 0 replies; 7+ messages in thread
From: Maksim Rayskiy @ 2011-01-07 3:46 UTC (permalink / raw)
To: Jeff Garzik; +Cc: linux-scsi, tj
>> Okay, I moved EH scheduling to ata_qc_issue(). But since now START
>> taskfile is
>> created in ata_eh_maybe_verify() I do not see why the same code has to
>> remain in ata_scsi_start_stop_xlat. Does it make sense?
>
> The taskfile you are to pass to the hardware is created in
> atapi_start_stop_xlat(), so you should not create a new taskfile in
> ata_eh_maybe_verify()
>
I can only see that the taskfile is being created in
ata_scsi_translate(). I want START request to return immediately, so I
need to schedule a deferred execution.
Do you suggest I create a new work_struct for this purpose (something
like link->spinup_task)? If I do that, I do not need to use
ata_port_schedule_eh() at all.
Thanks,
Maksim.
--
To unsubscribe from this list: send the line "unsubscribe linux-scsi" in
the body of a message to majordomo@vger.kernel.org
More majordomo info at http://vger.kernel.org/majordomo-info.html
^ permalink raw reply [flat|nested] 7+ messages in thread
* [RFC] Deferred disk spinup during system resume
@ 2010-12-30 19:40 Maksim Rayskiy
2010-12-30 22:46 ` [linux-pm] " Rafael J. Wysocki
0 siblings, 1 reply; 7+ messages in thread
From: Maksim Rayskiy @ 2010-12-30 19:40 UTC (permalink / raw)
To: linux-scsi, linux-pm
Hello,
When resuming from system suspend, scsi disks are being spun up which
takes quite a lot of time (5+ seconds in my case). The spinup is done
synchronously, so this time adds up to overall system resume time.
Ours is an embedded platform and we are using flash-based rootfs, so
there is no immediate need in harddrive after resume. What is much
more important for us is to minimize time-to-full-power. To speed up
resume, we would like to have an option to defer the spinup or run it
in parallel with system resume. I could not find any existing
mechanism to do the trick, but I might have missed something.
Can anybody comment on this?
Thanks,
Maksim.
^ permalink raw reply [flat|nested] 7+ messages in thread
* Re: [linux-pm] [RFC] Deferred disk spinup during system resume
2010-12-30 19:40 Maksim Rayskiy
@ 2010-12-30 22:46 ` Rafael J. Wysocki
2010-12-31 0:49 ` Maksim Rayskiy
0 siblings, 1 reply; 7+ messages in thread
From: Rafael J. Wysocki @ 2010-12-30 22:46 UTC (permalink / raw)
To: Maksim Rayskiy; +Cc: linux-pm, linux-scsi, Tejun Heo
On Thursday, December 30, 2010, Maksim Rayskiy wrote:
> Hello,
>
> When resuming from system suspend, scsi disks are being spun up which
> takes quite a lot of time (5+ seconds in my case). The spinup is done
> synchronously, so this time adds up to overall system resume time.
> Ours is an embedded platform and we are using flash-based rootfs, so
> there is no immediate need in harddrive after resume. What is much
> more important for us is to minimize time-to-full-power. To speed up
> resume, we would like to have an option to defer the spinup or run it
> in parallel with system resume. I could not find any existing
> mechanism to do the trick, but I might have missed something.
>
> Can anybody comment on this?
Do you use asynchronous suspend/resume?
Rafael
^ permalink raw reply [flat|nested] 7+ messages in thread
* Re: [linux-pm] [RFC] Deferred disk spinup during system resume
2010-12-30 22:46 ` [linux-pm] " Rafael J. Wysocki
@ 2010-12-31 0:49 ` Maksim Rayskiy
2010-12-31 11:27 ` Tejun Heo
0 siblings, 1 reply; 7+ messages in thread
From: Maksim Rayskiy @ 2010-12-31 0:49 UTC (permalink / raw)
To: Rafael J. Wysocki; +Cc: linux-pm, linux-scsi, Tejun Heo
>> When resuming from system suspend, scsi disks are being spun up which
>> takes quite a lot of time (5+ seconds in my case). The spinup is done
>> synchronously, so this time adds up to overall system resume time.
>> Ours is an embedded platform and we are using flash-based rootfs, so
>> there is no immediate need in harddrive after resume. What is much
>> more important for us is to minimize time-to-full-power. To speed up
>> resume, we would like to have an option to defer the spinup or run it
>> in parallel with system resume. I could not find any existing
>> mechanism to do the trick, but I might have missed something.
>>
>> Can anybody comment on this?
>
> Do you use asynchronous suspend/resume?
>
Yes, asynchronous suspend/resume is enabled - it saves about 0.5
second in my case. But resume blocks anyway because disk driver is
waiting on sd_resume() to complete.
I am wondering if we could let the resume proceed while spinup is
going on, just mark the scsi device as quiescent to block any data
transfers.
Maksim.
> Rafael
> --
^ permalink raw reply [flat|nested] 7+ messages in thread
* Re: [linux-pm] [RFC] Deferred disk spinup during system resume
2010-12-31 0:49 ` Maksim Rayskiy
@ 2010-12-31 11:27 ` Tejun Heo
2010-12-31 11:45 ` Tejun Heo
0 siblings, 1 reply; 7+ messages in thread
From: Tejun Heo @ 2010-12-31 11:27 UTC (permalink / raw)
To: Maksim Rayskiy; +Cc: Rafael J. Wysocki, linux-pm, linux-scsi
On Thu, Dec 30, 2010 at 04:49:29PM -0800, Maksim Rayskiy wrote:
> >> When resuming from system suspend, scsi disks are being spun up which
> >> takes quite a lot of time (5+ seconds in my case). The spinup is done
> >> synchronously, so this time adds up to overall system resume time.
> >> Ours is an embedded platform and we are using flash-based rootfs, so
> >> there is no immediate need in harddrive after resume. What is much
> >> more important for us is to minimize time-to-full-power. To speed up
> >> resume, we would like to have an option to defer the spinup or run it
> >> in parallel with system resume. I could not find any existing
> >> mechanism to do the trick, but I might have missed something.
> >>
> >> Can anybody comment on this?
> >
> > Do you use asynchronous suspend/resume?
> >
>
> Yes, asynchronous suspend/resume is enabled - it saves about 0.5
> second in my case. But resume blocks anyway because disk driver is
> waiting on sd_resume() to complete.
>
> I am wondering if we could let the resume proceed while spinup is
> going on, just mark the scsi device as quiescent to block any data
> transfers.
Yeah, it was asynchronous for a while when suspend/resume were
implemented in libata proper. It's a bit trickier to do that with sd
doing the higher level part. Hmmm... most SATA disks spin up
automatically anyway so disabling START_STOP from sd should do the
trick. Does the following achieve async resume?
echo 0 > /sys/block/sdX/device/scsi_disk/h:c:i:l/manage_start_stop
The problem is that the above would also prevent the kernel from
issuing STANDBY_NOW on suspend or power down. Maybe we should just
make start_stop_xlat schedule async EH action instead.
Thanks.
--
tejun
^ permalink raw reply [flat|nested] 7+ messages in thread
* Re: [linux-pm] [RFC] Deferred disk spinup during system resume
2010-12-31 11:27 ` Tejun Heo
@ 2010-12-31 11:45 ` Tejun Heo
0 siblings, 0 replies; 7+ messages in thread
From: Tejun Heo @ 2010-12-31 11:45 UTC (permalink / raw)
To: Maksim Rayskiy; +Cc: Rafael J. Wysocki, linux-pm, linux-scsi
On Fri, Dec 31, 2010 at 12:27:32PM +0100, Tejun Heo wrote:
> On Thu, Dec 30, 2010 at 04:49:29PM -0800, Maksim Rayskiy wrote:
> > >> When resuming from system suspend, scsi disks are being spun up which
> > >> takes quite a lot of time (5+ seconds in my case). The spinup is done
> > >> synchronously, so this time adds up to overall system resume time.
> > >> Ours is an embedded platform and we are using flash-based rootfs, so
> > >> there is no immediate need in harddrive after resume. What is much
> > >> more important for us is to minimize time-to-full-power. To speed up
> > >> resume, we would like to have an option to defer the spinup or run it
> > >> in parallel with system resume. I could not find any existing
> > >> mechanism to do the trick, but I might have missed something.
> > >>
> > >> Can anybody comment on this?
> > >
> > > Do you use asynchronous suspend/resume?
> > >
> >
> > Yes, asynchronous suspend/resume is enabled - it saves about 0.5
> > second in my case. But resume blocks anyway because disk driver is
> > waiting on sd_resume() to complete.
> >
> > I am wondering if we could let the resume proceed while spinup is
> > going on, just mark the scsi device as quiescent to block any data
> > transfers.
>
> Yeah, it was asynchronous for a while when suspend/resume were
> implemented in libata proper. It's a bit trickier to do that with sd
> doing the higher level part. Hmmm... most SATA disks spin up
> automatically anyway so disabling START_STOP from sd should do the
> trick. Does the following achieve async resume?
>
> echo 0 > /sys/block/sdX/device/scsi_disk/h:c:i:l/manage_start_stop
>
> The problem is that the above would also prevent the kernel from
> issuing STANDBY_NOW on suspend or power down. Maybe we should just
> make start_stop_xlat schedule async EH action instead.
So, something like the following. It's completely untested. Proceed
with caution.
diff --git a/drivers/ata/libata-eh.c b/drivers/ata/libata-eh.c
index 17a6378..d8d2aa8 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
@@ -3749,6 +3791,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..219d491 100644
--- a/include/linux/libata.h
+++ b/include/linux/libata.h
@@ -326,6 +326,7 @@ 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,
^ permalink raw reply related [flat|nested] 7+ messages in thread
end of thread, other threads:[~2011-01-07 3:46 UTC | newest]
Thread overview: 7+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2011-01-07 1:17 [linux-pm] [RFC] Deferred disk spinup during system resume maksim.rayskiy
2011-01-07 3:16 ` Jeff Garzik
2011-01-07 3:46 ` Maksim Rayskiy
-- strict thread matches above, loose matches on Subject: below --
2010-12-30 19:40 Maksim Rayskiy
2010-12-30 22:46 ` [linux-pm] " Rafael J. Wysocki
2010-12-31 0:49 ` Maksim Rayskiy
2010-12-31 11:27 ` Tejun Heo
2010-12-31 11:45 ` Tejun Heo
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox