aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/ata/libata-core.c
diff options
context:
space:
mode:
authorDan Williams <dan.j.williams@intel.com>2014-03-14 16:52:48 -0400
committerTejun Heo <tj@kernel.org>2014-03-18 16:08:38 -0400
commitbc6e7c4b0d1a1f742d96556f63d68f17f4e232c3 (patch)
tree1253c9a09dc834bbb42ef02e58ee0a117ed17ff8 /drivers/ata/libata-core.c
parent6a96918a6aa7b434d15710fc9e06589c6c8bd3a6 (diff)
libata, libsas: kill pm_result and related cleanup
Tejun says: "At least for libata, worrying about suspend/resume failures don't make whole lot of sense. If suspend failed, just proceed with suspend. If the device can't be woken up afterwards, that's that. There isn't anything we could have done differently anyway. The same for resume, if spinup fails, the device is dud and the following commands will invoke EH actions and will eventually fail. Again, there really isn't any *choice* to make. Just making sure the errors are handled gracefully (ie. don't crash) and the following commands are handled correctly should be enough." The only libata user that actually cares about the result from a suspend operation is libsas. However, it only cares about whether queuing a new operation collides with an in-flight one. All libsas does with the error is retry, but we can just let libata wait for the previous operation before continuing. Other cleanups include: 1/ Unifying all ata port pm operations on an ata_port_pm_ prefix 2/ Marking all ata port pm helper routines as returning void, only ata_port_pm_ entry points need to fake a 0 return value. 3/ Killing ata_port_{suspend|resume}_common() in favor of calling ata_port_request_pm() directly 4/ Killing the wrappers that just do a to_ata_port() conversion 5/ Clearly marking the entry points that do async operations with an _async suffix. Reference: http://marc.info/?l=linux-scsi&m=138995409532286&w=2 Cc: Phillip Susi <psusi@ubuntu.com> Cc: Alan Stern <stern@rowland.harvard.edu> Suggested-by: Tejun Heo <tj@kernel.org> Signed-off-by: Todd Brandt <todd.e.brandt@intel.com> Signed-off-by: Dan Williams <dan.j.williams@intel.com> Signed-off-by: Tejun Heo <tj@kernel.org>
Diffstat (limited to 'drivers/ata/libata-core.c')
-rw-r--r--drivers/ata/libata-core.c135
1 files changed, 60 insertions, 75 deletions
diff --git a/drivers/ata/libata-core.c b/drivers/ata/libata-core.c
index 1a3dbd1b196e..66110ed2c1c0 100644
--- a/drivers/ata/libata-core.c
+++ b/drivers/ata/libata-core.c
@@ -5351,22 +5351,17 @@ bool ata_link_offline(struct ata_link *link)
5351} 5351}
5352 5352
5353#ifdef CONFIG_PM 5353#ifdef CONFIG_PM
5354static int ata_port_request_pm(struct ata_port *ap, pm_message_t mesg, 5354static void ata_port_request_pm(struct ata_port *ap, pm_message_t mesg,
5355 unsigned int action, unsigned int ehi_flags, 5355 unsigned int action, unsigned int ehi_flags,
5356 int *async) 5356 bool async)
5357{ 5357{
5358 struct ata_link *link; 5358 struct ata_link *link;
5359 unsigned long flags; 5359 unsigned long flags;
5360 int rc = 0;
5361 5360
5362 /* Previous resume operation might still be in 5361 /* Previous resume operation might still be in
5363 * progress. Wait for PM_PENDING to clear. 5362 * progress. Wait for PM_PENDING to clear.
5364 */ 5363 */
5365 if (ap->pflags & ATA_PFLAG_PM_PENDING) { 5364 if (ap->pflags & ATA_PFLAG_PM_PENDING) {
5366 if (async) {
5367 *async = -EAGAIN;
5368 return 0;
5369 }
5370 ata_port_wait_eh(ap); 5365 ata_port_wait_eh(ap);
5371 WARN_ON(ap->pflags & ATA_PFLAG_PM_PENDING); 5366 WARN_ON(ap->pflags & ATA_PFLAG_PM_PENDING);
5372 } 5367 }
@@ -5375,11 +5370,6 @@ static int ata_port_request_pm(struct ata_port *ap, pm_message_t mesg,
5375 spin_lock_irqsave(ap->lock, flags); 5370 spin_lock_irqsave(ap->lock, flags);
5376 5371
5377 ap->pm_mesg = mesg; 5372 ap->pm_mesg = mesg;
5378 if (async)
5379 ap->pm_result = async;
5380 else
5381 ap->pm_result = &rc;
5382
5383 ap->pflags |= ATA_PFLAG_PM_PENDING; 5373 ap->pflags |= ATA_PFLAG_PM_PENDING;
5384 ata_for_each_link(link, ap, HOST_FIRST) { 5374 ata_for_each_link(link, ap, HOST_FIRST) {
5385 link->eh_info.action |= action; 5375 link->eh_info.action |= action;
@@ -5390,87 +5380,81 @@ static int ata_port_request_pm(struct ata_port *ap, pm_message_t mesg,
5390 5380
5391 spin_unlock_irqrestore(ap->lock, flags); 5381 spin_unlock_irqrestore(ap->lock, flags);
5392 5382
5393 /* wait and check result */
5394 if (!async) { 5383 if (!async) {
5395 ata_port_wait_eh(ap); 5384 ata_port_wait_eh(ap);
5396 WARN_ON(ap->pflags & ATA_PFLAG_PM_PENDING); 5385 WARN_ON(ap->pflags & ATA_PFLAG_PM_PENDING);
5397 } 5386 }
5398
5399 return rc;
5400} 5387}
5401 5388
5402static int __ata_port_suspend_common(struct ata_port *ap, pm_message_t mesg, int *async) 5389/*
5390 * On some hardware, device fails to respond after spun down for suspend. As
5391 * the device won't be used before being resumed, we don't need to touch the
5392 * device. Ask EH to skip the usual stuff and proceed directly to suspend.
5393 *
5394 * http://thread.gmane.org/gmane.linux.ide/46764
5395 */
5396static const unsigned int ata_port_suspend_ehi = ATA_EHI_QUIET
5397 | ATA_EHI_NO_AUTOPSY
5398 | ATA_EHI_NO_RECOVERY;
5399
5400static void ata_port_suspend(struct ata_port *ap, pm_message_t mesg)
5403{ 5401{
5404 /* 5402 ata_port_request_pm(ap, mesg, 0, ata_port_suspend_ehi, false);
5405 * On some hardware, device fails to respond after spun down
5406 * for suspend. As the device won't be used before being
5407 * resumed, we don't need to touch the device. Ask EH to skip
5408 * the usual stuff and proceed directly to suspend.
5409 *
5410 * http://thread.gmane.org/gmane.linux.ide/46764
5411 */
5412 unsigned int ehi_flags = ATA_EHI_QUIET | ATA_EHI_NO_AUTOPSY |
5413 ATA_EHI_NO_RECOVERY;
5414 return ata_port_request_pm(ap, mesg, 0, ehi_flags, async);
5415} 5403}
5416 5404
5417static int ata_port_suspend_common(struct device *dev, pm_message_t mesg) 5405static void ata_port_suspend_async(struct ata_port *ap, pm_message_t mesg)
5418{ 5406{
5419 struct ata_port *ap = to_ata_port(dev); 5407 ata_port_request_pm(ap, mesg, 0, ata_port_suspend_ehi, true);
5420
5421 return __ata_port_suspend_common(ap, mesg, NULL);
5422} 5408}
5423 5409
5424static int ata_port_suspend(struct device *dev) 5410static int ata_port_pm_suspend(struct device *dev)
5425{ 5411{
5412 struct ata_port *ap = to_ata_port(dev);
5413
5426 if (pm_runtime_suspended(dev)) 5414 if (pm_runtime_suspended(dev))
5427 return 0; 5415 return 0;
5428 5416
5429 return ata_port_suspend_common(dev, PMSG_SUSPEND); 5417 ata_port_suspend(ap, PMSG_SUSPEND);
5418 return 0;
5430} 5419}
5431 5420
5432static int ata_port_do_freeze(struct device *dev) 5421static int ata_port_pm_freeze(struct device *dev)
5433{ 5422{
5423 struct ata_port *ap = to_ata_port(dev);
5424
5434 if (pm_runtime_suspended(dev)) 5425 if (pm_runtime_suspended(dev))
5435 return 0; 5426 return 0;
5436 5427
5437 return ata_port_suspend_common(dev, PMSG_FREEZE); 5428 ata_port_suspend(ap, PMSG_FREEZE);
5429 return 0;
5438} 5430}
5439 5431
5440static int ata_port_poweroff(struct device *dev) 5432static int ata_port_pm_poweroff(struct device *dev)
5441{ 5433{
5442 return ata_port_suspend_common(dev, PMSG_HIBERNATE); 5434 ata_port_suspend(to_ata_port(dev), PMSG_HIBERNATE);
5435 return 0;
5443} 5436}
5444 5437
5445static int __ata_port_resume_common(struct ata_port *ap, pm_message_t mesg, 5438static const unsigned int ata_port_resume_ehi = ATA_EHI_NO_AUTOPSY
5446 int *async) 5439 | ATA_EHI_QUIET;
5447{
5448 int rc;
5449 5440
5450 rc = ata_port_request_pm(ap, mesg, ATA_EH_RESET, 5441static void ata_port_resume(struct ata_port *ap, pm_message_t mesg)
5451 ATA_EHI_NO_AUTOPSY | ATA_EHI_QUIET, async); 5442{
5452 return rc; 5443 ata_port_request_pm(ap, mesg, ATA_EH_RESET, ata_port_resume_ehi, false);
5453} 5444}
5454 5445
5455static int ata_port_resume_common(struct device *dev, pm_message_t mesg) 5446static void ata_port_resume_async(struct ata_port *ap, pm_message_t mesg)
5456{ 5447{
5457 struct ata_port *ap = to_ata_port(dev); 5448 ata_port_request_pm(ap, mesg, ATA_EH_RESET, ata_port_resume_ehi, true);
5458
5459 return __ata_port_resume_common(ap, mesg, NULL);
5460} 5449}
5461 5450
5462static int ata_port_resume(struct device *dev) 5451static int ata_port_pm_resume(struct device *dev)
5463{ 5452{
5464 int rc; 5453 ata_port_resume(to_ata_port(dev), PMSG_RESUME);
5465 5454 pm_runtime_disable(dev);
5466 rc = ata_port_resume_common(dev, PMSG_RESUME); 5455 pm_runtime_set_active(dev);
5467 if (!rc) { 5456 pm_runtime_enable(dev);
5468 pm_runtime_disable(dev); 5457 return 0;
5469 pm_runtime_set_active(dev);
5470 pm_runtime_enable(dev);
5471 }
5472
5473 return rc;
5474} 5458}
5475 5459
5476/* 5460/*
@@ -5499,21 +5483,23 @@ static int ata_port_runtime_idle(struct device *dev)
5499 5483
5500static int ata_port_runtime_suspend(struct device *dev) 5484static int ata_port_runtime_suspend(struct device *dev)
5501{ 5485{
5502 return ata_port_suspend_common(dev, PMSG_AUTO_SUSPEND); 5486 ata_port_suspend(to_ata_port(dev), PMSG_AUTO_SUSPEND);
5487 return 0;
5503} 5488}
5504 5489
5505static int ata_port_runtime_resume(struct device *dev) 5490static int ata_port_runtime_resume(struct device *dev)
5506{ 5491{
5507 return ata_port_resume_common(dev, PMSG_AUTO_RESUME); 5492 ata_port_resume(to_ata_port(dev), PMSG_AUTO_RESUME);
5493 return 0;
5508} 5494}
5509 5495
5510static const struct dev_pm_ops ata_port_pm_ops = { 5496static const struct dev_pm_ops ata_port_pm_ops = {
5511 .suspend = ata_port_suspend, 5497 .suspend = ata_port_pm_suspend,
5512 .resume = ata_port_resume, 5498 .resume = ata_port_pm_resume,
5513 .freeze = ata_port_do_freeze, 5499 .freeze = ata_port_pm_freeze,
5514 .thaw = ata_port_resume, 5500 .thaw = ata_port_pm_resume,
5515 .poweroff = ata_port_poweroff, 5501 .poweroff = ata_port_pm_poweroff,
5516 .restore = ata_port_resume, 5502 .restore = ata_port_pm_resume,
5517 5503
5518 .runtime_suspend = ata_port_runtime_suspend, 5504 .runtime_suspend = ata_port_runtime_suspend,
5519 .runtime_resume = ata_port_runtime_resume, 5505 .runtime_resume = ata_port_runtime_resume,
@@ -5525,18 +5511,17 @@ static const struct dev_pm_ops ata_port_pm_ops = {
5525 * level. sas suspend/resume is async to allow parallel port recovery 5511 * level. sas suspend/resume is async to allow parallel port recovery
5526 * since sas has multiple ata_port instances per Scsi_Host. 5512 * since sas has multiple ata_port instances per Scsi_Host.
5527 */ 5513 */
5528int ata_sas_port_async_suspend(struct ata_port *ap, int *async) 5514void ata_sas_port_suspend(struct ata_port *ap)
5529{ 5515{
5530 return __ata_port_suspend_common(ap, PMSG_SUSPEND, async); 5516 ata_port_suspend_async(ap, PMSG_SUSPEND);
5531} 5517}
5532EXPORT_SYMBOL_GPL(ata_sas_port_async_suspend); 5518EXPORT_SYMBOL_GPL(ata_sas_port_suspend);
5533 5519
5534int ata_sas_port_async_resume(struct ata_port *ap, int *async) 5520void ata_sas_port_resume(struct ata_port *ap)
5535{ 5521{
5536 return __ata_port_resume_common(ap, PMSG_RESUME, async); 5522 ata_port_resume_async(ap, PMSG_RESUME);
5537} 5523}
5538EXPORT_SYMBOL_GPL(ata_sas_port_async_resume); 5524EXPORT_SYMBOL_GPL(ata_sas_port_resume);
5539
5540 5525
5541/** 5526/**
5542 * ata_host_suspend - suspend host 5527 * ata_host_suspend - suspend host