libata: reimplement suspend/resume support and fix spindown on poweroff
Subsystems (2)
PATCH 1/1 libata: reimplement suspend/resume support and fix spindown on poweroff
Hello,
This is another take at using sdev->manage_start_stop to reimplement suspend/resume and fix spindown on poweroff. As Robert pointed out in the other thread[1], sadly, ATA spec does NOT require cache flush on standby and some distros don't flush cache prior to put the drive into standby mode during shutdown. This means that we can't skip cache flush in the kernel shutdown path because data loss is possible. Also, we just can't switch to new method because there are drives which spin up if told to spin down while it's already spun down.
So, that leaves us with migrating to new behavior (kernel side sync/shutdown) while maintaining backward compatibility. This patchset tries to do that by supplying a scheduled-to-be-removed module parameter libata.spindown_compat which defaults to 1. When set, it makes libata skip spindown during shutdown sequence thus maintaining the old behavior of issuing only cache flush on shutdown.
So, distros should update their shutdown(8) to do the followings.
* Check whether /sys/modules/libata/parameters/spindown_compat exists. If it does, write 0 to it.
* For each libata harddisk {
* Check whether /sys/class/scsi_disk/h:c:i:l/manage_start_stop exists. Iff it doesn't, synchronize cache and spin the disk down as before.
}
If shutdown(8) does the above, nothing will change on older kernels (some drives will spin up and have to do emergency unload but they aren't too many) and everything should work properly on kernels with spindown_compat or later ones which won't have it. If shutdown(8) isn't updated, the kernel will behave the same way as older kernels would.
To accelerate userland update, if shutdown(8) isn't updated (spindown_compat not cleared), libata will complain loudly about it, point the user to http://linux-ata.org/shutdown.html (which should be written) and pause for 5 seconds during shutdown. Hopefully, this makes the users bug distros sufficiently so that userland tools can be updated quickly. Note that the pausing happens only during shutdown not during reboot or suspend, so it shouldn't be too much of annoyance.
This change requires sdev->manage_start_stop updates from scsi-misc-2.6.
The merged git tree can be found at...
http://htj.dyndns.org/git/?p=libata-tj.git;a=shortlog;h=spindown
git://htj.dyndns.org/libata-tj spindown
Thanks.
Signature · 3 lines
tejun [1] http://thread.gmane.org/gmane.linux.ide/18167
PATCH 1/2 libata: reimplement suspend/resume support using sdev->manage_start_stop
Reimplement suspend/resume support using sdev->manage_start_stop.
* Device suspend/resume is now SCSI layer's responsibility and the code is simplified a lot.
* DPM is dropped. This also simplifies code a lot. Suspend/resume status is port-wide now.
* ata_scsi_device_suspend/resume() and ata_dev_ready() removed.
* Resume now has to wait for disk to spin up before proceeding. I couldn't find easy way out as libata is in EH waiting for the disk to be ready and sd is waiting for EH to complete to issue START_STOP.
* sdev->manage_start_stop is set to 1 in ata_scsi_slave_config(). This fixes spindown on shutdown and suspend-to-disk.
--- drivers/ata/ahci.c | 4 - drivers/ata/ata_generic.c | 6 +- drivers/ata/ata_piix.c | 4 - drivers/ata/libata-core.c | 39 +------ drivers/ata/libata-eh.c | 237 +-------------------------------------- drivers/ata/libata-scsi.c | 129 +--------------------- drivers/ata/pata_ali.c | 4 - drivers/ata/pata_amd.c | 4 - drivers/ata/pata_atiixp.c | 4 - drivers/ata/pata_cmd640.c | 4 - drivers/ata/pata_cmd64x.c | 4 - drivers/ata/pata_cs5520.c | 4 - drivers/ata/pata_cs5530.c | 4 - drivers/ata/pata_cs5535.c | 4 - drivers/ata/pata_cypress.c | 4 - drivers/ata/pata_efar.c | 4 - drivers/ata/pata_hpt366.c | 4 - drivers/ata/pata_hpt3x3.c | 4 - drivers/ata/pata_it8213.c | 4 - drivers/ata/pata_it821x.c | 4 - drivers/ata/pata_ixp4xx_cf.c | 2 +- drivers/ata/pata_jmicron.c | 4 - drivers/ata/pata_marvell.c | 4 - drivers/ata/pata_mpc52xx.c | 4 - drivers/ata/pata_mpiix.c | 4 - drivers/ata/pata_netcell.c | 4 - drivers/ata/pata_ns87410.c | 4 - drivers/ata/pata_oldpiix.c | 4 - drivers/ata/pata_opti.c | 4 - drivers/ata/pata_optidma.c | 4 - drivers/ata/pata_pdc202xx_old.c | 4 - drivers/ata/pata_radisys.c | 4 - drivers/ata/pata_rz1000.c | 6 +- drivers/ata/pata_sc1200.c | 4 - drivers/ata/pata_scc.c | 4 - drivers/ata/pata_serverworks.c | 4 - drivers/ata/pata_sil680.c | 4 - drivers/ata/pata_sis.c | 4 - drivers/ata/pata_triflex.c | 4 - drivers/ata/pata_via.c | 4 - drivers/ata/sata_inic162x.c | 4 - drivers/ata/sata_nv.c | 8 -- drivers/ata/sata_sil.c | 4 - drivers/ata/sata_sil24.c | 4 - include/linux/libata.h | 14 +-- 45 files changed, 14 insertions(+), 575 deletions(-)
drivers/ata/ahci.c +0 -4
@@ -250,10 +250,6 @@ static struct scsi_host_template ahci_sh .slave_configure = ata_scsi_slave_config, .slave_destroy = ata_scsi_slave_destroy, .bios_param = ata_std_bios_param, -#ifdef CONFIG_PM - .suspend = ata_scsi_device_suspend, - .resume = ata_scsi_device_resume, -#endif };static const struct ata_port_operations ahci_ops = {
drivers/ata/ata_generic.c +1 -5
@@ -54,7 +54,7 @@ static int generic_set_mode(struct ata_pfor (i =0 ; i <ATA_MAX_DEVICES ; i++) {struct ata_device *dev = &ap->device[i]; -if (ata_dev_ready (dev)) { +if (ata_dev_enabled (dev)) {/* We don't really care */ dev->pio_mode =XFER_PIO_0 ; dev->dma_mode =XFER_MW_DMA_0 ;
@@ -90,10 +90,6 @@ static struct scsi_host_template generic .slave_configure = ata_scsi_slave_config, .slave_destroy = ata_scsi_slave_destroy, .bios_param = ata_std_bios_param, -#ifdef CONFIG_PM - .resume = ata_scsi_device_resume, - .suspend = ata_scsi_device_suspend, -#endif };static struct ata_port_operations generic_port_ops = {
drivers/ata/ata_piix.c +0 -4
@@ -275,10 +275,6 @@ static struct scsi_host_template piix_sh .slave_configure = ata_scsi_slave_config, .slave_destroy = ata_scsi_slave_destroy, .bios_param = ata_std_bios_param, -#ifdef CONFIG_PM - .resume = ata_scsi_device_resume, - .suspend = ata_scsi_device_suspend, -#endif };static const struct ata_port_operations piix_pata_ops = {
drivers/ata/libata-core.c +4 -35
@@ -2858,7 +2858,7 @@ int ata_do_set_mode(struct ata_port *ap, dev = &ap->device[i];/* don't update suspended devices' xfer mode */ -if (!ata_dev_ready (dev)) +if (!ata_dev_enabled (dev))continue ; rc =ata_dev_set_mode (dev);
@@ -5793,37 +5793,11 @@ static int ata_host_request_pm(struct at*/ int ata_host_suspend (struct ata_host *host,pm_message_t mesg) { -int i, j, rc; +int rc; rc =ata_host_request_pm (host, mesg,0 ,ATA_EHI_QUIET ,1 ); -if (rc) - goto fail; - -/* EH is quiescent now. Fail if we have any ready device. -* This happens if hotplug occurs between completion of device -* suspension and here. -*/ -for (i =0 ; i < host->n_ports; i++) { -struct ata_port *ap = host->ports[i]; - -for (j =0 ; j <ATA_MAX_DEVICES ; j++) { -struct ata_device *dev = &ap->device[j]; - -if (ata_dev_ready (dev)) { -ata_port_printk (ap,KERN_WARNING , -"suspend failed, device %d " -"still active\n" , dev->devno); - rc = -EBUSY ; - goto fail; - } - } - } - - host->dev->power.power_state = mesg; -return 0 ; - - fail: -ata_host_resume (host); +if (rc ==0 ) + host->dev->power.power_state = mesg;return rc; }
@@ -6836,11 +6810,6 @@ EXPORT_SYMBOL_GPL(ata_pci_default_filterEXPORT_SYMBOL_GPL (ata_pci_clear_simplex);#endif /* CONFIG_PCI */ -#ifdef CONFIG_PM -EXPORT_SYMBOL_GPL (ata_scsi_device_suspend); -EXPORT_SYMBOL_GPL (ata_scsi_device_resume); -#endif /* CONFIG_PM */ -EXPORT_SYMBOL_GPL (ata_eng_timeout);EXPORT_SYMBOL_GPL (ata_port_schedule_eh);EXPORT_SYMBOL_GPL (ata_port_abort);
drivers/ata/libata-eh.c +4 -233
307 lines not on this page · raw message
drivers/ata/libata-scsi.c +2 -127
141 lines not on this page · raw message
drivers/ata/pata_ali.c +0 -4
@@ -291,10 +291,6 @@ static struct scsi_host_template ali_sht .slave_configure = ata_scsi_slave_config, .slave_destroy = ata_scsi_slave_destroy, .bios_param = ata_std_bios_param, -#ifdef CONFIG_PM - .resume = ata_scsi_device_resume, - .suspend = ata_scsi_device_suspend, -#endif };/*
drivers/ata/pata_amd.c +0 -4
@@ -323,10 +323,6 @@ static struct scsi_host_template amd_sht .slave_configure = ata_scsi_slave_config, .slave_destroy = ata_scsi_slave_destroy, .bios_param = ata_std_bios_param, -#ifdef CONFIG_PM - .resume = ata_scsi_device_resume, - .suspend = ata_scsi_device_suspend, -#endif };static struct ata_port_operations amd33_port_ops = {
drivers/ata/pata_atiixp.c +0 -4
@@ -229,10 +229,6 @@ static struct scsi_host_template atiixp_ .slave_configure = ata_scsi_slave_config, .slave_destroy = ata_scsi_slave_destroy, .bios_param = ata_std_bios_param, -#ifdef CONFIG_PM - .resume = ata_scsi_device_resume, - .suspend = ata_scsi_device_suspend, -#endif };static struct ata_port_operations atiixp_port_ops = {
drivers/ata/pata_cmd640.c +0 -4
@@ -181,10 +181,6 @@ static struct scsi_host_template cmd640_ .slave_configure = ata_scsi_slave_config, .slave_destroy = ata_scsi_slave_destroy, .bios_param = ata_std_bios_param, -#ifdef CONFIG_PM - .resume = ata_scsi_device_resume, - .suspend = ata_scsi_device_suspend, -#endif };static struct ata_port_operations cmd640_port_ops = {
drivers/ata/pata_cmd64x.c +0 -4
@@ -266,10 +266,6 @@ static struct scsi_host_template cmd64x_ .slave_configure = ata_scsi_slave_config, .slave_destroy = ata_scsi_slave_destroy, .bios_param = ata_std_bios_param, -#ifdef CONFIG_PM - .resume = ata_scsi_device_resume, - .suspend = ata_scsi_device_suspend, -#endif };static struct ata_port_operations cmd64x_port_ops = {
drivers/ata/pata_cs5520.c +0 -4
@@ -155,10 +155,6 @@ static struct scsi_host_template cs5520_ .slave_configure = ata_scsi_slave_config, .slave_destroy = ata_scsi_slave_destroy, .bios_param = ata_std_bios_param, -#ifdef CONFIG_PM - .resume = ata_scsi_device_resume, - .suspend = ata_scsi_device_suspend, -#endif };static struct ata_port_operations cs5520_port_ops = {
drivers/ata/pata_cs5530.c +0 -4
@@ -176,10 +176,6 @@ static struct scsi_host_template cs5530_ .slave_configure = ata_scsi_slave_config, .slave_destroy = ata_scsi_slave_destroy, .bios_param = ata_std_bios_param, -#ifdef CONFIG_PM - .resume = ata_scsi_device_resume, - .suspend = ata_scsi_device_suspend, -#endif };static struct ata_port_operations cs5530_port_ops = {
drivers/ata/pata_cs5535.c +0 -4
@@ -172,10 +172,6 @@ static struct scsi_host_template cs5535_ .slave_configure = ata_scsi_slave_config, .slave_destroy = ata_scsi_slave_destroy, .bios_param = ata_std_bios_param, -#ifdef CONFIG_PM - .resume = ata_scsi_device_resume, - .suspend = ata_scsi_device_suspend, -#endif };static struct ata_port_operations cs5535_port_ops = {
drivers/ata/pata_cypress.c +0 -4
@@ -125,10 +125,6 @@ static struct scsi_host_template cy82c69 .slave_configure = ata_scsi_slave_config, .slave_destroy = ata_scsi_slave_destroy, .bios_param = ata_std_bios_param, -#ifdef CONFIG_PM - .resume = ata_scsi_device_resume, - .suspend = ata_scsi_device_suspend, -#endif };static struct ata_port_operations cy82c693_port_ops = {
drivers/ata/pata_efar.c +0 -4
@@ -246,10 +246,6 @@ static struct scsi_host_template efar_sh .slave_configure = ata_scsi_slave_config, .slave_destroy = ata_scsi_slave_destroy, .bios_param = ata_std_bios_param, -#ifdef CONFIG_PM - .resume = ata_scsi_device_resume, - .suspend = ata_scsi_device_suspend, -#endif };static const struct ata_port_operations efar_ops = {
drivers/ata/pata_hpt366.c +0 -4
@@ -331,10 +331,6 @@ static struct scsi_host_template hpt36x_ .slave_configure = ata_scsi_slave_config, .slave_destroy = ata_scsi_slave_destroy, .bios_param = ata_std_bios_param, -#ifdef CONFIG_PM - .resume = ata_scsi_device_resume, - .suspend = ata_scsi_device_suspend, -#endif };/*
drivers/ata/pata_hpt3x3.c +0 -4
@@ -100,10 +100,6 @@ static struct scsi_host_template hpt3x3_ .slave_configure = ata_scsi_slave_config, .slave_destroy = ata_scsi_slave_destroy, .bios_param = ata_std_bios_param, -#ifdef CONFIG_PM - .resume = ata_scsi_device_resume, - .suspend = ata_scsi_device_suspend, -#endif };static struct ata_port_operations hpt3x3_port_ops = {
drivers/ata/pata_it8213.c +0 -4
@@ -255,10 +255,6 @@ static struct scsi_host_template it8213_ .dma_boundary = ATA_DMA_BOUNDARY, .slave_configure = ata_scsi_slave_config, .bios_param = ata_std_bios_param, -#ifdef CONFIG_PM - .resume = ata_scsi_device_resume, - .suspend = ata_scsi_device_suspend, -#endif };static const struct ata_port_operations it8213_ops = {
drivers/ata/pata_it821x.c +0 -4
@@ -620,10 +620,6 @@ static struct scsi_host_template it821x_ .slave_configure = ata_scsi_slave_config, .slave_destroy = ata_scsi_slave_destroy, .bios_param = ata_std_bios_param, -#ifdef CONFIG_PM - .resume = ata_scsi_device_resume, - .suspend = ata_scsi_device_suspend, -#endif };static struct ata_port_operations it821x_smart_port_ops = {
drivers/ata/pata_ixp4xx_cf.c +1 -1
@@ -31,7 +31,7 @@ static int ixp4xx_set_mode(struct ata_pofor (i =0 ; i <ATA_MAX_DEVICES ; i++) {struct ata_device *dev = &ap->device[i]; -if (ata_dev_ready (dev)) { +if (ata_dev_enabled (dev)) {ata_dev_printk (dev,KERN_INFO ,"configured for PIO0\n" ); dev->pio_mode =XFER_PIO_0 ; dev->xfer_mode =XFER_PIO_0 ;
drivers/ata/pata_jmicron.c +0 -4
@@ -137,10 +137,6 @@ static struct scsi_host_template jmicron .slave_destroy = ata_scsi_slave_destroy, /* Use standard CHS mapping rules */ .bios_param = ata_std_bios_param, -#ifdef CONFIG_PM - .suspend = ata_scsi_device_suspend, - .resume = ata_scsi_device_resume, -#endif };static const struct ata_port_operations jmicron_ops = {
drivers/ata/pata_marvell.c +0 -4
@@ -104,10 +104,6 @@ static struct scsi_host_template marvell .slave_destroy = ata_scsi_slave_destroy, /* Use standard CHS mapping rules */ .bios_param = ata_std_bios_param, -#ifdef CONFIG_PM - .resume = ata_scsi_device_resume, - .suspend = ata_scsi_device_suspend, -#endif };static const struct ata_port_operations marvell_ops = {
drivers/ata/pata_mpc52xx.c +0 -4
@@ -280,10 +280,6 @@ static struct scsi_host_template mpc52xx .dma_boundary = ATA_DMA_BOUNDARY, .slave_configure = ata_scsi_slave_config, .bios_param = ata_std_bios_param, -#ifdef CONFIG_PM - .suspend = ata_scsi_device_suspend, - .resume = ata_scsi_device_resume, -#endif };static struct ata_port_operations mpc52xx_ata_port_ops = {
drivers/ata/pata_mpiix.c +0 -4
@@ -164,10 +164,6 @@ static struct scsi_host_template mpiix_s .slave_configure = ata_scsi_slave_config, .slave_destroy = ata_scsi_slave_destroy, .bios_param = ata_std_bios_param, -#ifdef CONFIG_PM - .resume = ata_scsi_device_resume, - .suspend = ata_scsi_device_suspend, -#endif };static struct ata_port_operations mpiix_port_ops = {
drivers/ata/pata_netcell.c +0 -4
@@ -37,10 +37,6 @@ static struct scsi_host_template netcell .slave_destroy = ata_scsi_slave_destroy, /* Use standard CHS mapping rules */ .bios_param = ata_std_bios_param, -#ifdef CONFIG_PM - .resume = ata_scsi_device_resume, - .suspend = ata_scsi_device_suspend, -#endif };static const struct ata_port_operations netcell_ops = {
drivers/ata/pata_ns87410.c +0 -4
@@ -156,10 +156,6 @@ static struct scsi_host_template ns87410 .slave_configure = ata_scsi_slave_config, .slave_destroy = ata_scsi_slave_destroy, .bios_param = ata_std_bios_param, -#ifdef CONFIG_PM - .resume = ata_scsi_device_resume, - .suspend = ata_scsi_device_suspend, -#endif };static struct ata_port_operations ns87410_port_ops = {
drivers/ata/pata_oldpiix.c +0 -4
@@ -232,10 +232,6 @@ static struct scsi_host_template oldpiix .slave_configure = ata_scsi_slave_config, .slave_destroy = ata_scsi_slave_destroy, .bios_param = ata_std_bios_param, -#ifdef CONFIG_PM - .resume = ata_scsi_device_resume, - .suspend = ata_scsi_device_suspend, -#endif };static const struct ata_port_operations oldpiix_pata_ops = {
drivers/ata/pata_opti.c +0 -4
@@ -177,10 +177,6 @@ static struct scsi_host_template opti_sh .slave_configure = ata_scsi_slave_config, .slave_destroy = ata_scsi_slave_destroy, .bios_param = ata_std_bios_param, -#ifdef CONFIG_PM - .resume = ata_scsi_device_resume, - .suspend = ata_scsi_device_suspend, -#endif };static struct ata_port_operations opti_port_ops = {
drivers/ata/pata_optidma.c +0 -4
@@ -362,10 +362,6 @@ static struct scsi_host_template optidma .slave_configure = ata_scsi_slave_config, .slave_destroy = ata_scsi_slave_destroy, .bios_param = ata_std_bios_param, -#ifdef CONFIG_PM - .resume = ata_scsi_device_resume, - .suspend = ata_scsi_device_suspend, -#endif };static struct ata_port_operations optidma_port_ops = {
drivers/ata/pata_pdc202xx_old.c +0 -4
@@ -244,10 +244,6 @@ static struct scsi_host_template pdc202x .slave_configure = ata_scsi_slave_config, .slave_destroy = ata_scsi_slave_destroy, .bios_param = ata_std_bios_param, -#ifdef CONFIG_PM - .resume = ata_scsi_device_resume, - .suspend = ata_scsi_device_suspend, -#endif };static struct ata_port_operations pdc2024x_port_ops = {
drivers/ata/pata_radisys.c +0 -4
@@ -200,10 +200,6 @@ static struct scsi_host_template radisys .slave_configure = ata_scsi_slave_config, .slave_destroy = ata_scsi_slave_destroy, .bios_param = ata_std_bios_param, -#ifdef CONFIG_PM - .resume = ata_scsi_device_resume, - .suspend = ata_scsi_device_suspend, -#endif };static const struct ata_port_operations radisys_pata_ops = {
drivers/ata/pata_rz1000.c +1 -5
@@ -40,7 +40,7 @@ static int rz1000_set_mode(struct ata_pofor (i =0 ; i <ATA_MAX_DEVICES ; i++) {struct ata_device *dev = &ap->device[i]; -if (ata_dev_ready (dev)) { +if (ata_dev_enabled (dev)) {/* We don't really care */ dev->pio_mode =XFER_PIO_0 ; dev->xfer_mode =XFER_PIO_0 ;
@@ -69,10 +69,6 @@ static struct scsi_host_template rz1000_ .slave_configure = ata_scsi_slave_config, .slave_destroy = ata_scsi_slave_destroy, .bios_param = ata_std_bios_param, -#ifdef CONFIG_PM - .resume = ata_scsi_device_resume, - .suspend = ata_scsi_device_suspend, -#endif };static struct ata_port_operations rz1000_port_ops = {
drivers/ata/pata_sc1200.c +0 -4
@@ -194,10 +194,6 @@ static struct scsi_host_template sc1200_ .slave_configure = ata_scsi_slave_config, .slave_destroy = ata_scsi_slave_destroy, .bios_param = ata_std_bios_param, -#ifdef CONFIG_PM - .resume = ata_scsi_device_resume, - .suspend = ata_scsi_device_suspend, -#endif };static struct ata_port_operations sc1200_port_ops = {
drivers/ata/pata_scc.c +0 -4
@@ -984,10 +984,6 @@ static struct scsi_host_template scc_sht .slave_configure = ata_scsi_slave_config, .slave_destroy = ata_scsi_slave_destroy, .bios_param = ata_std_bios_param, -#ifdef CONFIG_PM - .resume = ata_scsi_device_resume, - .suspend = ata_scsi_device_suspend, -#endif };static const struct ata_port_operations scc_pata_ops = {
drivers/ata/pata_serverworks.c +0 -4
@@ -313,10 +313,6 @@ static struct scsi_host_template serverw .slave_configure = ata_scsi_slave_config, .slave_destroy = ata_scsi_slave_destroy, .bios_param = ata_std_bios_param, -#ifdef CONFIG_PM - .resume = ata_scsi_device_resume, - .suspend = ata_scsi_device_suspend, -#endif };static struct ata_port_operations serverworks_osb4_port_ops = {
drivers/ata/pata_sil680.c +0 -4
@@ -230,10 +230,6 @@ static struct scsi_host_template sil680_ .slave_configure = ata_scsi_slave_config, .slave_destroy = ata_scsi_slave_destroy, .bios_param = ata_std_bios_param, -#ifdef CONFIG_PM - .suspend = ata_scsi_device_suspend, - .resume = ata_scsi_device_resume, -#endif };static struct ata_port_operations sil680_port_ops = {
drivers/ata/pata_sis.c +0 -4
@@ -520,10 +520,6 @@ static struct scsi_host_template sis_sht .slave_configure = ata_scsi_slave_config, .slave_destroy = ata_scsi_slave_destroy, .bios_param = ata_std_bios_param, -#ifdef CONFIG_PM - .resume = ata_scsi_device_resume, - .suspend = ata_scsi_device_suspend, -#endif };static const struct ata_port_operations sis_133_ops = {
drivers/ata/pata_triflex.c +0 -4
@@ -192,10 +192,6 @@ static struct scsi_host_template triflex .slave_configure = ata_scsi_slave_config, .slave_destroy = ata_scsi_slave_destroy, .bios_param = ata_std_bios_param, -#ifdef CONFIG_PM - .resume = ata_scsi_device_resume, - .suspend = ata_scsi_device_suspend, -#endif };static struct ata_port_operations triflex_port_ops = {
drivers/ata/pata_via.c +0 -4
@@ -300,10 +300,6 @@ static struct scsi_host_template via_sht .slave_configure = ata_scsi_slave_config, .slave_destroy = ata_scsi_slave_destroy, .bios_param = ata_std_bios_param, -#ifdef CONFIG_PM - .resume = ata_scsi_device_resume, - .suspend = ata_scsi_device_suspend, -#endif };static struct ata_port_operations via_port_ops = {
drivers/ata/sata_inic162x.c +0 -4
@@ -135,10 +135,6 @@ static struct scsi_host_template inic_sh .slave_configure = inic_slave_config, .slave_destroy = ata_scsi_slave_destroy, .bios_param = ata_std_bios_param, -#ifdef CONFIG_PM - .suspend = ata_scsi_device_suspend, - .resume = ata_scsi_device_resume, -#endif };static const int scr_map[] = {
drivers/ata/sata_nv.c +0 -8
@@ -323,10 +323,6 @@ static struct scsi_host_template nv_sht .slave_configure = ata_scsi_slave_config, .slave_destroy = ata_scsi_slave_destroy, .bios_param = ata_std_bios_param, -#ifdef CONFIG_PM - .suspend = ata_scsi_device_suspend, - .resume = ata_scsi_device_resume, -#endif };static struct scsi_host_template nv_adma_sht = {
@@ -345,10 +341,6 @@ static struct scsi_host_template nv_adma .slave_configure = nv_adma_slave_config, .slave_destroy = ata_scsi_slave_destroy, .bios_param = ata_std_bios_param, -#ifdef CONFIG_PM - .suspend = ata_scsi_device_suspend, - .resume = ata_scsi_device_resume, -#endif };static const struct ata_port_operations nv_generic_ops = {
drivers/ata/sata_sil.c +0 -4
@@ -182,10 +182,6 @@ static struct scsi_host_template sil_sht .slave_configure = ata_scsi_slave_config, .slave_destroy = ata_scsi_slave_destroy, .bios_param = ata_std_bios_param, -#ifdef CONFIG_PM - .suspend = ata_scsi_device_suspend, - .resume = ata_scsi_device_resume, -#endif };static const struct ata_port_operations sil_ops = {
drivers/ata/sata_sil24.c +0 -4
@@ -380,10 +380,6 @@ static struct scsi_host_template sil24_s .slave_configure = ata_scsi_slave_config, .slave_destroy = ata_scsi_slave_destroy, .bios_param = ata_std_bios_param, -#ifdef CONFIG_PM - .suspend = ata_scsi_device_suspend, - .resume = ata_scsi_device_resume, -#endif };static const struct ata_port_operations sil24_ops = {
include/linux/libata.h +1 -13
@@ -140,7 +140,6 @@ enum {ATA_DFLAG_PIO = (1 <<8 ),/* device limited to PIO mode */ ATA_DFLAG_NCQ_OFF = (1 <<9 ),/* device limited to non-NCQ mode */ -ATA_DFLAG_SUSPENDED = (1 <<10 ),/* device suspended */ ATA_DFLAG_INIT_MASK = (1 <<16 ) -1 , ATA_DFLAG_DETACH = (1 << 16),
@@ -268,13 +267,9 @@ enum {ATA_EH_REVALIDATE = (1 <<0 ),ATA_EH_SOFTRESET = (1 <<1 ),ATA_EH_HARDRESET = (1 <<2 ), -ATA_EH_SUSPEND = (1 <<3 ), -ATA_EH_RESUME = (1 <<4 ), -ATA_EH_PM_FREEZE = (1 <<5 ),ATA_EH_RESET_MASK =ATA_EH_SOFTRESET |ATA_EH_HARDRESET , -ATA_EH_PERDEV_MASK =ATA_EH_REVALIDATE |ATA_EH_SUSPEND | -ATA_EH_RESUME |ATA_EH_PM_FREEZE , +ATA_EH_PERDEV_MASK =ATA_EH_REVALIDATE ,/* ata_eh_info->flags */ ATA_EHI_HOTPLUGGED = (1 << 0), /* could have been hotplugged */
@@ -742,8 +737,6 @@ extern int sata_scr_write_flush(struct aextern int ata_port_online (struct ata_port *ap);extern int ata_port_offline (struct ata_port *ap);#ifdef CONFIG_PM -extern int ata_scsi_device_resume (struct scsi_device *); -extern int ata_scsi_device_suspend (struct scsi_device *,pm_message_t mesg);extern int ata_host_suspend (struct ata_host *host,pm_message_t mesg);extern void ata_host_resume (struct ata_host *host);#endif
@@ -1018,11 +1011,6 @@ static inline unsigned int ata_dev_absenreturn ata_class_absent (dev->class); } -static inline unsigned int ata_dev_ready (const struct ata_device *dev) -{ -return ata_dev_enabled (dev) && !(dev->flags &ATA_DFLAG_SUSPENDED ); -} -/* * port helpers */
Signature · 1 line
1.4.3.4
Re: [PATCH 1/2] libata: reimplement suspend/resume support using sdev->manage_start_stop
Quoted 15 lines · Tejun Heo
Reimplement suspend/resume support using
sdev->manage_start_stop.* Device suspend/resume is now SCSI layer's responsibility and the code is simplified a lot.
* DPM is dropped. This also simplifies code a lot. Suspend/resume status is port-wide now.
* ata_scsi_device_suspend/resume() and
ata_dev_ready()removed.* Resume now has to wait for disk to spin up before proceeding. I couldn't find easy way out as libata is in EH waiting for the disk to be ready and sd is waiting for EH to complete to issue
START_STOP.
Quoted 4 lines
*
sdev->manage_start_stopis set to 1 inata_scsi_slave_config(). This fixes spindown on shutdown and suspend-to-disk.Signed-off-by Tejun Heo <[email protected]>
applied patches 1-2, but explicitly did not send them upstream today.
I'm hoping we can get this into 2.6.22 -- but also expose it in -mm for a few days as well.
I agree it is important to fix this issue.
Jeff
Re: [PATCH 1/2] libata: reimplement suspend/resume support using sdev->manage_start_stop
Quoted 19 lines · Jeff Garzik
Quoted 18 lines · Tejun Heo
Reimplement suspend/resume support using
sdev->manage_start_stop.* Device suspend/resume is now SCSI layer's responsibility and the code is simplified a lot.
* DPM is dropped. This also simplifies code a lot. Suspend/resume status is port-wide now.
* ata_scsi_device_suspend/resume() and
ata_dev_ready()removed.* Resume now has to wait for disk to spin up before proceeding. I couldn't find easy way out as libata is in EH waiting for the disk to be ready and sd is waiting for EH to complete to issue
START_STOP.*
sdev->manage_start_stopis set to 1 inata_scsi_slave_config(). This fixes spindown on shutdown and suspend-to-disk.
Quoted 6 lines
Quoted 1 line
Signed-off-by Tejun Heo <[email protected]>applied patches 1-2, but explicitly did not send them upstream today.
I'm hoping we can get this into 2.6.22 -- but also expose it in -mm for a few days as well.
Okay, will prepare the scary webpage then.
Signature · 1 line
tejun
Re: [PATCH 1/2] libata: reimplement suspend/resume support using sdev->manage_start_stop
Quoted 20 lines · Tejun Heo
Quoted 19 lines · Jeff Garzik
Quoted 18 lines · Tejun Heo
Reimplement suspend/resume support using
sdev->manage_start_stop.* Device suspend/resume is now SCSI layer's responsibility and the code is simplified a lot.
* DPM is dropped. This also simplifies code a lot. Suspend/resume status is port-wide now.
* ata_scsi_device_suspend/resume() and
ata_dev_ready()removed.* Resume now has to wait for disk to spin up before proceeding. I couldn't find easy way out as libata is in EH waiting for the disk to be ready and sd is waiting for EH to complete to issue
START_STOP.*
sdev->manage_start_stopis set to 1 inata_scsi_slave_config(). This fixes spindown on shutdown and suspend-to-disk.
Quoted 7 lines
Quoted 5 lines
Quoted 1 line
Signed-off-by Tejun Heo <[email protected]>applied patches 1-2, but explicitly did not send them upstream today.
I'm hoping we can get this into 2.6.22 -- but also expose it in -mm for a few days as well.
Okay, will prepare the scary webpage then.
huh?
Jeff
PATCH 2/2 libata: implement libata.spindown_compat
In reply to Tejun HeoNow that libata uses sd->manage_start_stop, libata spins down disk on shutdown. In an attempt to compensate libata's previous shortcoming, some distros sync and spin down disks attached via libata in their shutdown(8). Some disks spin back up just to spin down again on STANDBYNOW1 if the command is issued when the disk is spun down, so this double spinning down causes problem.
This patch implements module parameter libata.spindown_compat which, when set to one (default value), prevents libata from spinning down disks on shutdown thus avoiding double spinning down. Note that libata spins down disks for suspend to mem and disk, so with libata.spindown_compat set to one, disks should be properly spun down in all cases without modifying shutdown(8).
shutdown(8) should be fixed eventually. Some drive do spin up on SYNCHRONZE_CACHE even when their cache is clean. Those disks currently spin up briefly when sd tries to shutdown the device and then the machine powers off immediately, which can't be good for the head. We can't skip SYNCHRONIZE_CACHE during shudown as it can be dangerous data integrity-wise.
So, this spindown_compat parameter is already scheduled for removal by the end of the next year and here's what shutdown(8) should do.
* Check whether /sys/modules/libata/parameters/spindown_compat exists. If it does, write 0 to it.
* For each libata harddisk {
* Check whether /sys/class/scsi_disk/h:c:i:l/manage_start_stop exists. Iff it doesn't, synchronize cache and spin the disk down as before.
}
The above procedure will make shutdown(8) work properly with kernels before this change, ones with this workaround and later ones without it.
To accelerate shutdown(8) updates, if the compat mode is in use, this patch prints BIG FAT warning for five seconds during shutdown (the optimal interval to annoy the user just the right amount discovered by hours of tireless usability testing).
--- Documentation/feature-removal-schedule.txt | 19 +++++++++++++++++++ drivers/ata/libata-core.c | 6 ++++++ drivers/ata/libata-scsi.c | 28 +++++++++++++++++++++++++++- drivers/ata/libata.h | 1 + 4 files changed, 53 insertions(+), 1 deletions(-)
Documentation/feature-removal-schedule.txt +19 -0
@@ -314,3 +314,22 @@ Why: Code was merged, then submitter imm Who: David S. Miller <[email protected]> --------------------------- + +What: libata.spindown_compat module parameter +When: Dec 2008 +Why: halt(8) synchronizes caches for and spins down libata disks + because libata didn't use to spin down disk on system halt + (only synchronized caches). + Spin down on system halt is now implemented and can be tested + using sysfs node /sys/class/scsi_disk/h:c:i:l/manage_start_stop. + Because issuing spin down command to an already spun down disk + makes some disks spin up just to spin down again, the old + behavior needs to be maintained till userspace tool is updated + to check the sysfs node and not to spin down disks with the + node set to one. + This module parameter is to give userspace tool the time to + get updated and should be removed after userspace is + reasonably updated. +Who: Tejun Heo <[email protected]> + +---------------------------
drivers/ata/libata-core.c +6 -0
@@ -101,6 +101,12 @@ int libata_noacpi = 1;module_param_named (noacpi, libata_noacpi, int,0444 );MODULE_PARM_DESC (noacpi,"Disables the use of ACPI in suspend/resume when set" ); +int ata_spindown_compat =1 ; +module_param_named (spindown_compat, ata_spindown_compat, int,0644 ); +MODULE_PARM_DESC (spindown_compat,"Enable backward compatible spindown " +"behavior. Will be removed. More info can be found in " +"Documentation/feature-removal-schedule.txt\n" ); +MODULE_AUTHOR ("Jeff Garzik" );MODULE_DESCRIPTION ("Library module for ATA devices" );MODULE_LICENSE ("GPL" );
drivers/ata/libata-scsi.c +27 -1
@@ -944,9 +944,35 @@ static unsigned int ata_scsi_start_stop_ } tf->command =ATA_CMD_VERIFY ;/* READ VERIFY */ - }else + }else { +/* XXX: This is for backward compatibility, will be +* removed. Read Documentation/feature-removal-schedule.txt +* for more info. +*/ +if (ata_spindown_compat && + (system_state ==SYSTEM_HALT || + system_state ==SYSTEM_POWER_OFF )) { +static int warned =0 ; + +if (!warned) { +spin_unlock_irq (qc->ap->lock); +ata_dev_printk (qc->dev,KERN_WARNING , +"DISK MIGHT NOT BE SPUN DOWN PROPERLY. " +"UPDATE SHUTDOWN UTILITY\n" ); +ata_dev_printk (qc->dev,KERN_WARNING , +"For more info, visit " +"http://linux-ata.org/shutdown.html\n" ); + warned =1 ; +ssleep (5 ); +spin_lock_irq (qc->ap->lock); + } + scmd->result =SAM_STAT_GOOD ; +return 1 ; + } +/* Issue ATA STANDBY IMMEDIATE command */ tf->command =ATA_CMD_STANDBYNOW1 ; + }/* * Standby and Idle condition timers could be implemented but that
drivers/ata/libata.h +1 -0
@@ -58,6 +58,7 @@ extern int atapi_enabled;extern int atapi_dmadir;extern int libata_fua;extern int libata_noacpi; +extern int ata_spindown_compat;extern struct ata_queued_cmd *ata_qc_new_init (struct ata_device *dev); extern int ata_build_rw_tf(struct ata_taskfile *tf, struct ata_device *dev, u64 block, u32 n_block, unsigned int tf_flags,
Signature · 1 line
1.4.3.4
Doesn't apply to today Linus' git tree:
[fcomolli@tycho linux-2.6]$ git pull git://htj.dyndns.org/libata-tj spindown
remote: Generating pack...
remote: Done counting 14283 objects.
remote: Result has 11254 objects.
remote: Deltifying 11254 objects.
remote: 100% (11254/11254) done
Indexing 11254 objects.
remote: Total 11254 (delta 9842), reused 11241 (delta 9832)
100% (11254/11254) done
Resolving 9842 deltas.
100% (9842/9842) done
1948 objects were added to complete this thin pack.
100% (44114/44114) done
Auto-merged Documentation/feature-removal-schedule.txt
CONFLICT (content): Merge conflict in Documentation/feature-removal-schedule.txt Automatic merge failed; fix conflicts and then commit the result.
I don't know git enough to identify the conflict. Can anyone help me?
Thanks in advance.
Fabio
Quoted 56 lines · Tejun Heo
Hello,
This is another take at using
sdev->manage_start_stopto reimplement suspend/resume and fix spindown on poweroff. As Robert pointed out in the other thread[1], sadly, ATA spec does NOT require cache flush on standby and some distros don't flush cache prior to put the drive into standby mode during shutdown. This means that we can't skip cache flush in the kernel shutdown path because data loss is possible. Also, we just can't switch to new method because there are drives which spin up if told to spin down while it's already spun down.So, that leaves us with migrating to new behavior (kernel side sync/shutdown) while maintaining backward compatibility. This patchset tries to do that by supplying a scheduled-to-be-removed module parameter libata.spindown_compat which defaults to 1. When set, it makes libata skip spindown during shutdown sequence thus maintaining the old behavior of issuing only cache flush on shutdown.
So, distros should update their shutdown(8) to do the followings.
* Check whether
/sys/modules/libata/parameters/spindown_compatexists. If it does, write 0 to it.* For each libata harddisk {
* Check whether /sys/class/scsi_disk/h:c:i:l/manage_start_stop exists. Iff it doesn't, synchronize cache and spin the disk down as before.
}If shutdown(8) does the above, nothing will change on older kernels (some drives will spin up and have to do emergency unload but they aren't too many) and everything should work properly on kernels with
spindown_compator later ones which won't have it. If shutdown(8) isn't updated, the kernel will behave the same way as older kernels would.To accelerate userland update, if shutdown(8) isn't updated (
spindown_compatnot cleared), libata will complain loudly about it, point the user to http://linux-ata.org/shutdown.html (which should be written) and pause for 5 seconds during shutdown. Hopefully, this makes the users bug distros sufficiently so that userland tools can be updated quickly. Note that the pausing happens only during shutdown not during reboot or suspend, so it shouldn't be too much of annoyance.This change requires
sdev->manage_start_stopupdates from scsi-misc-2.6.
The merged git tree can be found at...http://htj.dyndns.org/git/?p=libata-tj.git;a=shortlog;h=spindown
git://htj.dyndns.org/libata-tjspindownThanks.
--
tejun
Quoted 21 lines · Fabio Comolli
Doesn't apply to today Linus' git tree:
[fcomolli@tycho linux-2.6]$ git pull
git://htj.dyndns.org/libata-tj
spindown
remote: Generating pack...
remote: Done counting 14283 objects.
remote: Result has 11254 objects.
remote: Deltifying 11254 objects.
remote: 100% (11254/11254) done
Indexing 11254 objects.
remote: Total 11254 (delta 9842), reused 11241 (delta 9832) 100% (11254/11254) done
Resolving 9842 deltas.
100% (9842/9842) done
1948 objects were added to complete this thin pack.
100% (44114/44114) done
Auto-mergedDocumentation/feature-removal-schedule.txtCONFLICT (content): Merge conflict inDocumentation/feature-removal-schedule.txt
Automatic merge failed; fix conflicts and then commit the result.
Quoted 1 line
I don't know git enough to identify the conflict. Can anyone help me?
That's a conflict in feature-removal-schedule.txt document. Open the file, look for <<<< or >>>> and fix them up, do "git-update-index Documentation/feature-removal-schedule.txt" followed by "git commit" and you should be done. Alternatively, you can just test the spindown branch as-is by doing 'git-fetch git://htj.dyndns.org/libata-tj
spindown:spindown', then 'git checkout spindown'.
Signature · 1 line
tejun
OK, your instructions worked fine. I tested 4 combinations:
* libata.spindown_compat=1 (default): the "pop" remains with and without the "-n"
parameter added to the halt command;
* libata.spindown_compat=0: no "pop" with and without the "-n" parameter added to the halt command.
As I read somewhere (maybe on lkml, I don't remember) that the "-n" parameter was necessary to silence the "pop", I tried the old IDE layer without the "-n" and it works the same as libata.
The conclusion is that your patch works (if the parameter is set to 0).
Hope this helps. Regards,
Fabio
Quoted 84 lines · Fabio Comolli
Doesn't apply to today Linus' git tree:
[fcomolli@tycho linux-2.6]$ git pull
git://htj.dyndns.org/libata-tjspindown
remote: Generating pack...
remote: Done counting 14283 objects.
remote: Result has 11254 objects.
remote: Deltifying 11254 objects.
remote: 100% (11254/11254) done
Indexing 11254 objects.
remote: Total 11254 (delta 9842), reused 11241 (delta 9832)
100% (11254/11254) done
Resolving 9842 deltas.
100% (9842/9842) done
1948 objects were added to complete this thin pack.
100% (44114/44114) done
Auto-mergedDocumentation/feature-removal-schedule.txt
CONFLICT (content): Merge conflict inDocumentation/feature-removal-schedule.txtAutomatic merge failed; fix conflicts and then commit the result.I don't know git enough to identify the conflict. Can anyone help me?
Thanks in advance.
FabioQuoted 56 lines · Tejun Heo
Hello,
This is another take at using
sdev->manage_start_stopto reimplement suspend/resume and fix spindown on poweroff. As Robert pointed out in the other thread[1], sadly, ATA spec does NOT require cache flush on standby and some distros don't flush cache prior to put the drive into standby mode during shutdown. This means that we can't skip cache flush in the kernel shutdown path because data loss is possible. Also, we just can't switch to new method because there are drives which spin up if told to spin down while it's already spun down.So, that leaves us with migrating to new behavior (kernel side sync/shutdown) while maintaining backward compatibility. This patchset tries to do that by supplying a scheduled-to-be-removed module parameter libata.spindown_compat which defaults to 1. When set, it makes libata skip spindown during shutdown sequence thus maintaining the old behavior of issuing only cache flush on shutdown.
So, distros should update their shutdown(8) to do the followings.
* Check whether
/sys/modules/libata/parameters/spindown_compatexists. If it does, write 0 to it.* For each libata harddisk {
* Check whether /sys/class/scsi_disk/h:c:i:l/manage_start_stop exists. Iff it doesn't, synchronize cache and spin the disk down as before.
}If shutdown(8) does the above, nothing will change on older kernels (some drives will spin up and have to do emergency unload but they aren't too many) and everything should work properly on kernels with
spindown_compator later ones which won't have it. If shutdown(8) isn't updated, the kernel will behave the same way as older kernels would.To accelerate userland update, if shutdown(8) isn't updated (
spindown_compatnot cleared), libata will complain loudly about it, point the user to http://linux-ata.org/shutdown.html (which should be written) and pause for 5 seconds during shutdown. Hopefully, this makes the users bug distros sufficiently so that userland tools can be updated quickly. Note that the pausing happens only during shutdown not during reboot or suspend, so it shouldn't be too much of annoyance.This change requires
sdev->manage_start_stopupdates from scsi-misc-2.6.
The merged git tree can be found at...http://htj.dyndns.org/git/?p=libata-tj.git;a=shortlog;h=spindown
git://htj.dyndns.org/libata-tjspindownThanks.
--
tejun