[PATCH] libata: reimplement controller-wide PM

Reimplement controller-wide PM. ata_host_set_suspend/resume() are
defined to suspend and resume a host_set. While suspended, EHs for
all ports in the host_set are pegged using ATA_FLAG_SUSPENDED and
frozen.

Because SCSI device hotplug is done asynchronously against the rest of
libata EH and the same mutex is used when adding new device, suspend
cannot wait for hotplug to complete. So, if SCSI device hotplug is in
progress, suspend fails with -EBUSY.

In most cases, host_set resume is followed by device resume. As each
resume operation requires a reset, a single host_set-wide resume
operation may result in multiple resets. To avoid this, resume waits
upto 1 second giving PM to request resume for devices.

Signed-off-by: Tejun Heo <htejun@gmail.com>
Signed-off-by: Jeff Garzik <jeff@garzik.org>

authored by Tejun Heo and committed by Jeff Garzik 500530f6 d6f26d1f

+298 -7
+160 -5
drivers/scsi/libata-core.c
··· 5009 5009 return 0; 5010 5010 } 5011 5011 5012 + static int ata_host_set_request_pm(struct ata_host_set *host_set, 5013 + pm_message_t mesg, unsigned int action, 5014 + unsigned int ehi_flags, int wait) 5015 + { 5016 + unsigned long flags; 5017 + int i, rc; 5018 + 5019 + for (i = 0; i < host_set->n_ports; i++) { 5020 + struct ata_port *ap = host_set->ports[i]; 5021 + 5022 + /* Previous resume operation might still be in 5023 + * progress. Wait for PM_PENDING to clear. 5024 + */ 5025 + if (ap->pflags & ATA_PFLAG_PM_PENDING) { 5026 + ata_port_wait_eh(ap); 5027 + WARN_ON(ap->pflags & ATA_PFLAG_PM_PENDING); 5028 + } 5029 + 5030 + /* request PM ops to EH */ 5031 + spin_lock_irqsave(ap->lock, flags); 5032 + 5033 + ap->pm_mesg = mesg; 5034 + if (wait) { 5035 + rc = 0; 5036 + ap->pm_result = &rc; 5037 + } 5038 + 5039 + ap->pflags |= ATA_PFLAG_PM_PENDING; 5040 + ap->eh_info.action |= action; 5041 + ap->eh_info.flags |= ehi_flags; 5042 + 5043 + ata_port_schedule_eh(ap); 5044 + 5045 + spin_unlock_irqrestore(ap->lock, flags); 5046 + 5047 + /* wait and check result */ 5048 + if (wait) { 5049 + ata_port_wait_eh(ap); 5050 + WARN_ON(ap->pflags & ATA_PFLAG_PM_PENDING); 5051 + if (rc) 5052 + return rc; 5053 + } 5054 + } 5055 + 5056 + return 0; 5057 + } 5058 + 5059 + /** 5060 + * ata_host_set_suspend - suspend host_set 5061 + * @host_set: host_set to suspend 5062 + * @mesg: PM message 5063 + * 5064 + * Suspend @host_set. Actual operation is performed by EH. This 5065 + * function requests EH to perform PM operations and waits for EH 5066 + * to finish. 5067 + * 5068 + * LOCKING: 5069 + * Kernel thread context (may sleep). 5070 + * 5071 + * RETURNS: 5072 + * 0 on success, -errno on failure. 5073 + */ 5074 + int ata_host_set_suspend(struct ata_host_set *host_set, pm_message_t mesg) 5075 + { 5076 + int i, j, rc; 5077 + 5078 + rc = ata_host_set_request_pm(host_set, mesg, 0, ATA_EHI_QUIET, 1); 5079 + if (rc) 5080 + goto fail; 5081 + 5082 + /* EH is quiescent now. Fail if we have any ready device. 5083 + * This happens if hotplug occurs between completion of device 5084 + * suspension and here. 5085 + */ 5086 + for (i = 0; i < host_set->n_ports; i++) { 5087 + struct ata_port *ap = host_set->ports[i]; 5088 + 5089 + for (j = 0; j < ATA_MAX_DEVICES; j++) { 5090 + struct ata_device *dev = &ap->device[j]; 5091 + 5092 + if (ata_dev_ready(dev)) { 5093 + ata_port_printk(ap, KERN_WARNING, 5094 + "suspend failed, device %d " 5095 + "still active\n", dev->devno); 5096 + rc = -EBUSY; 5097 + goto fail; 5098 + } 5099 + } 5100 + } 5101 + 5102 + host_set->dev->power.power_state = mesg; 5103 + return 0; 5104 + 5105 + fail: 5106 + ata_host_set_resume(host_set); 5107 + return rc; 5108 + } 5109 + 5110 + /** 5111 + * ata_host_set_resume - resume host_set 5112 + * @host_set: host_set to resume 5113 + * 5114 + * Resume @host_set. Actual operation is performed by EH. This 5115 + * function requests EH to perform PM operations and returns. 5116 + * Note that all resume operations are performed parallely. 5117 + * 5118 + * LOCKING: 5119 + * Kernel thread context (may sleep). 5120 + */ 5121 + void ata_host_set_resume(struct ata_host_set *host_set) 5122 + { 5123 + ata_host_set_request_pm(host_set, PMSG_ON, ATA_EH_SOFTRESET, 5124 + ATA_EHI_NO_AUTOPSY | ATA_EHI_QUIET, 0); 5125 + host_set->dev->power.power_state = PMSG_ON; 5126 + } 5127 + 5012 5128 /** 5013 5129 * ata_port_start - Set port up for dma. 5014 5130 * @ap: Port to initialize ··· 5767 5651 return (tmp == bits->val) ? 1 : 0; 5768 5652 } 5769 5653 5770 - int ata_pci_device_suspend(struct pci_dev *pdev, pm_message_t state) 5654 + void ata_pci_device_do_suspend(struct pci_dev *pdev, pm_message_t state) 5771 5655 { 5772 5656 pci_save_state(pdev); 5773 - pci_disable_device(pdev); 5774 - pci_set_power_state(pdev, PCI_D3hot); 5775 - return 0; 5657 + 5658 + if (state.event == PM_EVENT_SUSPEND) { 5659 + pci_disable_device(pdev); 5660 + pci_set_power_state(pdev, PCI_D3hot); 5661 + } 5776 5662 } 5777 5663 5778 - int ata_pci_device_resume(struct pci_dev *pdev) 5664 + void ata_pci_device_do_resume(struct pci_dev *pdev) 5779 5665 { 5780 5666 pci_set_power_state(pdev, PCI_D0); 5781 5667 pci_restore_state(pdev); 5782 5668 pci_enable_device(pdev); 5783 5669 pci_set_master(pdev); 5670 + } 5671 + 5672 + int ata_pci_device_suspend(struct pci_dev *pdev, pm_message_t state) 5673 + { 5674 + struct ata_host_set *host_set = dev_get_drvdata(&pdev->dev); 5675 + int rc = 0; 5676 + 5677 + rc = ata_host_set_suspend(host_set, state); 5678 + if (rc) 5679 + return rc; 5680 + 5681 + if (host_set->next) { 5682 + rc = ata_host_set_suspend(host_set->next, state); 5683 + if (rc) { 5684 + ata_host_set_resume(host_set); 5685 + return rc; 5686 + } 5687 + } 5688 + 5689 + ata_pci_device_do_suspend(pdev, state); 5690 + 5691 + return 0; 5692 + } 5693 + 5694 + int ata_pci_device_resume(struct pci_dev *pdev) 5695 + { 5696 + struct ata_host_set *host_set = dev_get_drvdata(&pdev->dev); 5697 + 5698 + ata_pci_device_do_resume(pdev); 5699 + ata_host_set_resume(host_set); 5700 + if (host_set->next) 5701 + ata_host_set_resume(host_set->next); 5702 + 5784 5703 return 0; 5785 5704 } 5786 5705 #endif /* CONFIG_PCI */ ··· 5995 5844 EXPORT_SYMBOL_GPL(sata_scr_write_flush); 5996 5845 EXPORT_SYMBOL_GPL(ata_port_online); 5997 5846 EXPORT_SYMBOL_GPL(ata_port_offline); 5847 + EXPORT_SYMBOL_GPL(ata_host_set_suspend); 5848 + EXPORT_SYMBOL_GPL(ata_host_set_resume); 5998 5849 EXPORT_SYMBOL_GPL(ata_id_string); 5999 5850 EXPORT_SYMBOL_GPL(ata_id_c_string); 6000 5851 EXPORT_SYMBOL_GPL(ata_scsi_simulate); ··· 6011 5858 EXPORT_SYMBOL_GPL(ata_pci_init_native_mode); 6012 5859 EXPORT_SYMBOL_GPL(ata_pci_init_one); 6013 5860 EXPORT_SYMBOL_GPL(ata_pci_remove_one); 5861 + EXPORT_SYMBOL_GPL(ata_pci_device_do_suspend); 5862 + EXPORT_SYMBOL_GPL(ata_pci_device_do_resume); 6014 5863 EXPORT_SYMBOL_GPL(ata_pci_device_suspend); 6015 5864 EXPORT_SYMBOL_GPL(ata_pci_device_resume); 6016 5865 EXPORT_SYMBOL_GPL(ata_pci_default_filter);
+126 -2
drivers/scsi/libata-eh.c
··· 47 47 48 48 static void __ata_port_freeze(struct ata_port *ap); 49 49 static void ata_eh_finish(struct ata_port *ap); 50 + static void ata_eh_handle_port_suspend(struct ata_port *ap); 51 + static void ata_eh_handle_port_resume(struct ata_port *ap); 50 52 51 53 static void ata_ering_record(struct ata_ering *ering, int is_io, 52 54 unsigned int err_mask) ··· 264 262 repeat: 265 263 /* invoke error handler */ 266 264 if (ap->ops->error_handler) { 265 + /* process port resume request */ 266 + ata_eh_handle_port_resume(ap); 267 + 267 268 /* fetch & clear EH info */ 268 269 spin_lock_irqsave(ap->lock, flags); 269 270 ··· 279 274 280 275 spin_unlock_irqrestore(ap->lock, flags); 281 276 282 - /* invoke EH. if unloading, just finish failed qcs */ 283 - if (!(ap->pflags & ATA_PFLAG_UNLOADING)) 277 + /* invoke EH, skip if unloading or suspended */ 278 + if (!(ap->pflags & (ATA_PFLAG_UNLOADING | ATA_PFLAG_SUSPENDED))) 284 279 ap->ops->error_handler(ap); 285 280 else 286 281 ata_eh_finish(ap); 282 + 283 + /* process port suspend request */ 284 + ata_eh_handle_port_suspend(ap); 287 285 288 286 /* Exception might have happend after ->error_handler 289 287 * recovered the port but before this point. Repeat ··· 2108 2100 ata_eh_report(ap); 2109 2101 ata_eh_recover(ap, prereset, softreset, hardreset, postreset); 2110 2102 ata_eh_finish(ap); 2103 + } 2104 + 2105 + /** 2106 + * ata_eh_handle_port_suspend - perform port suspend operation 2107 + * @ap: port to suspend 2108 + * 2109 + * Suspend @ap. 2110 + * 2111 + * LOCKING: 2112 + * Kernel thread context (may sleep). 2113 + */ 2114 + static void ata_eh_handle_port_suspend(struct ata_port *ap) 2115 + { 2116 + unsigned long flags; 2117 + int rc = 0; 2118 + 2119 + /* are we suspending? */ 2120 + spin_lock_irqsave(ap->lock, flags); 2121 + if (!(ap->pflags & ATA_PFLAG_PM_PENDING) || 2122 + ap->pm_mesg.event == PM_EVENT_ON) { 2123 + spin_unlock_irqrestore(ap->lock, flags); 2124 + return; 2125 + } 2126 + spin_unlock_irqrestore(ap->lock, flags); 2127 + 2128 + WARN_ON(ap->pflags & ATA_PFLAG_SUSPENDED); 2129 + 2130 + /* suspend */ 2131 + ata_eh_freeze_port(ap); 2132 + 2133 + if (ap->ops->port_suspend) 2134 + rc = ap->ops->port_suspend(ap, ap->pm_mesg); 2135 + 2136 + /* report result */ 2137 + spin_lock_irqsave(ap->lock, flags); 2138 + 2139 + ap->pflags &= ~ATA_PFLAG_PM_PENDING; 2140 + if (rc == 0) 2141 + ap->pflags |= ATA_PFLAG_SUSPENDED; 2142 + else 2143 + ata_port_schedule_eh(ap); 2144 + 2145 + if (ap->pm_result) { 2146 + *ap->pm_result = rc; 2147 + ap->pm_result = NULL; 2148 + } 2149 + 2150 + spin_unlock_irqrestore(ap->lock, flags); 2151 + 2152 + return; 2153 + } 2154 + 2155 + /** 2156 + * ata_eh_handle_port_resume - perform port resume operation 2157 + * @ap: port to resume 2158 + * 2159 + * Resume @ap. 2160 + * 2161 + * This function also waits upto one second until all devices 2162 + * hanging off this port requests resume EH action. This is to 2163 + * prevent invoking EH and thus reset multiple times on resume. 2164 + * 2165 + * On DPM resume, where some of devices might not be resumed 2166 + * together, this may delay port resume upto one second, but such 2167 + * DPM resumes are rare and 1 sec delay isn't too bad. 2168 + * 2169 + * LOCKING: 2170 + * Kernel thread context (may sleep). 2171 + */ 2172 + static void ata_eh_handle_port_resume(struct ata_port *ap) 2173 + { 2174 + unsigned long timeout; 2175 + unsigned long flags; 2176 + int i, rc = 0; 2177 + 2178 + /* are we resuming? */ 2179 + spin_lock_irqsave(ap->lock, flags); 2180 + if (!(ap->pflags & ATA_PFLAG_PM_PENDING) || 2181 + ap->pm_mesg.event != PM_EVENT_ON) { 2182 + spin_unlock_irqrestore(ap->lock, flags); 2183 + return; 2184 + } 2185 + spin_unlock_irqrestore(ap->lock, flags); 2186 + 2187 + /* spurious? */ 2188 + if (!(ap->pflags & ATA_PFLAG_SUSPENDED)) 2189 + goto done; 2190 + 2191 + if (ap->ops->port_resume) 2192 + rc = ap->ops->port_resume(ap); 2193 + 2194 + /* give devices time to request EH */ 2195 + timeout = jiffies + HZ; /* 1s max */ 2196 + while (1) { 2197 + for (i = 0; i < ATA_MAX_DEVICES; i++) { 2198 + struct ata_device *dev = &ap->device[i]; 2199 + unsigned int action = ata_eh_dev_action(dev); 2200 + 2201 + if ((dev->flags & ATA_DFLAG_SUSPENDED) && 2202 + !(action & ATA_EH_RESUME)) 2203 + break; 2204 + } 2205 + 2206 + if (i == ATA_MAX_DEVICES || time_after(jiffies, timeout)) 2207 + break; 2208 + msleep(10); 2209 + } 2210 + 2211 + done: 2212 + spin_lock_irqsave(ap->lock, flags); 2213 + ap->pflags &= ~(ATA_PFLAG_PM_PENDING | ATA_PFLAG_SUSPENDED); 2214 + if (ap->pm_result) { 2215 + *ap->pm_result = rc; 2216 + ap->pm_result = NULL; 2217 + } 2218 + spin_unlock_irqrestore(ap->lock, flags); 2111 2219 }
+12
include/linux/libata.h
··· 182 182 183 183 ATA_PFLAG_FLUSH_PORT_TASK = (1 << 16), /* flush port task */ 184 184 ATA_PFLAG_SUSPENDED = (1 << 17), /* port is suspended (power) */ 185 + ATA_PFLAG_PM_PENDING = (1 << 18), /* PM operation pending */ 185 186 186 187 /* struct ata_queued_cmd flags */ 187 188 ATA_QCFLAG_ACTIVE = (1 << 0), /* cmd not yet ack'd to scsi lyer */ ··· 550 549 struct list_head eh_done_q; 551 550 wait_queue_head_t eh_wait_q; 552 551 552 + pm_message_t pm_mesg; 553 + int *pm_result; 554 + 553 555 void *private_data; 554 556 555 557 u8 sector_buf[ATA_SECT_SIZE]; /* owned by EH */ ··· 606 602 u32 (*scr_read) (struct ata_port *ap, unsigned int sc_reg); 607 603 void (*scr_write) (struct ata_port *ap, unsigned int sc_reg, 608 604 u32 val); 605 + 606 + int (*port_suspend) (struct ata_port *ap, pm_message_t mesg); 607 + int (*port_resume) (struct ata_port *ap); 609 608 610 609 int (*port_start) (struct ata_port *ap); 611 610 void (*port_stop) (struct ata_port *ap); ··· 674 667 extern int ata_pci_init_one (struct pci_dev *pdev, struct ata_port_info **port_info, 675 668 unsigned int n_ports); 676 669 extern void ata_pci_remove_one (struct pci_dev *pdev); 670 + extern void ata_pci_device_do_suspend(struct pci_dev *pdev, pm_message_t state); 671 + extern void ata_pci_device_do_resume(struct pci_dev *pdev); 677 672 extern int ata_pci_device_suspend(struct pci_dev *pdev, pm_message_t state); 678 673 extern int ata_pci_device_resume(struct pci_dev *pdev); 679 674 extern int ata_pci_clear_simplex(struct pci_dev *pdev); ··· 696 687 extern int ata_port_offline(struct ata_port *ap); 697 688 extern int ata_scsi_device_resume(struct scsi_device *); 698 689 extern int ata_scsi_device_suspend(struct scsi_device *, pm_message_t state); 690 + extern int ata_host_set_suspend(struct ata_host_set *host_set, 691 + pm_message_t mesg); 692 + extern void ata_host_set_resume(struct ata_host_set *host_set); 699 693 extern int ata_ratelimit(void); 700 694 extern unsigned int ata_busy_sleep(struct ata_port *ap, 701 695 unsigned long timeout_pat,