aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--drivers/scsi/libata-core.c84
-rw-r--r--drivers/scsi/libata-scsi.c121
-rw-r--r--include/linux/libata.h2
3 files changed, 115 insertions, 92 deletions
diff --git a/drivers/scsi/libata-core.c b/drivers/scsi/libata-core.c
index ad5cac79627c..51dbc5221934 100644
--- a/drivers/scsi/libata-core.c
+++ b/drivers/scsi/libata-core.c
@@ -5009,88 +5009,6 @@ int ata_flush_cache(struct ata_device *dev)
5009 return 0; 5009 return 0;
5010} 5010}
5011 5011
5012static int ata_standby_drive(struct ata_device *dev)
5013{
5014 unsigned int err_mask;
5015
5016 err_mask = ata_do_simple_cmd(dev, ATA_CMD_STANDBYNOW1);
5017 if (err_mask) {
5018 ata_dev_printk(dev, KERN_ERR, "failed to standby drive "
5019 "(err_mask=0x%x)\n", err_mask);
5020 return -EIO;
5021 }
5022
5023 return 0;
5024}
5025
5026static int ata_start_drive(struct ata_device *dev)
5027{
5028 unsigned int err_mask;
5029
5030 err_mask = ata_do_simple_cmd(dev, ATA_CMD_IDLEIMMEDIATE);
5031 if (err_mask) {
5032 ata_dev_printk(dev, KERN_ERR, "failed to start drive "
5033 "(err_mask=0x%x)\n", err_mask);
5034 return -EIO;
5035 }
5036
5037 return 0;
5038}
5039
5040/**
5041 * ata_device_resume - wakeup a previously suspended devices
5042 * @dev: the device to resume
5043 *
5044 * Kick the drive back into action, by sending it an idle immediate
5045 * command and making sure its transfer mode matches between drive
5046 * and host.
5047 *
5048 */
5049int ata_device_resume(struct ata_device *dev)
5050{
5051 struct ata_port *ap = dev->ap;
5052
5053 if (ap->pflags & ATA_PFLAG_SUSPENDED) {
5054 struct ata_device *failed_dev;
5055
5056 ata_busy_sleep(ap, ATA_TMOUT_BOOT_QUICK, ATA_TMOUT_BOOT);
5057 ata_busy_wait(ap, ATA_BUSY | ATA_DRQ, 200000);
5058
5059 ap->pflags &= ~ATA_PFLAG_SUSPENDED;
5060 while (ata_set_mode(ap, &failed_dev))
5061 ata_dev_disable(failed_dev);
5062 }
5063 if (!ata_dev_enabled(dev))
5064 return 0;
5065 if (dev->class == ATA_DEV_ATA)
5066 ata_start_drive(dev);
5067
5068 return 0;
5069}
5070
5071/**
5072 * ata_device_suspend - prepare a device for suspend
5073 * @dev: the device to suspend
5074 * @state: target power management state
5075 *
5076 * Flush the cache on the drive, if appropriate, then issue a
5077 * standbynow command.
5078 */
5079int ata_device_suspend(struct ata_device *dev, pm_message_t state)
5080{
5081 struct ata_port *ap = dev->ap;
5082
5083 if (!ata_dev_enabled(dev))
5084 return 0;
5085 if (dev->class == ATA_DEV_ATA)
5086 ata_flush_cache(dev);
5087
5088 if (state.event != PM_EVENT_FREEZE)
5089 ata_standby_drive(dev);
5090 ap->pflags |= ATA_PFLAG_SUSPENDED;
5091 return 0;
5092}
5093
5094/** 5012/**
5095 * ata_port_start - Set port up for dma. 5013 * ata_port_start - Set port up for dma.
5096 * @ap: Port to initialize 5014 * @ap: Port to initialize
@@ -5946,8 +5864,6 @@ EXPORT_SYMBOL_GPL(ata_pci_default_filter);
5946EXPORT_SYMBOL_GPL(ata_pci_clear_simplex); 5864EXPORT_SYMBOL_GPL(ata_pci_clear_simplex);
5947#endif /* CONFIG_PCI */ 5865#endif /* CONFIG_PCI */
5948 5866
5949EXPORT_SYMBOL_GPL(ata_device_suspend);
5950EXPORT_SYMBOL_GPL(ata_device_resume);
5951EXPORT_SYMBOL_GPL(ata_scsi_device_suspend); 5867EXPORT_SYMBOL_GPL(ata_scsi_device_suspend);
5952EXPORT_SYMBOL_GPL(ata_scsi_device_resume); 5868EXPORT_SYMBOL_GPL(ata_scsi_device_resume);
5953 5869
diff --git a/drivers/scsi/libata-scsi.c b/drivers/scsi/libata-scsi.c
index ba3e515f2b9d..7ced41ecde86 100644
--- a/drivers/scsi/libata-scsi.c
+++ b/drivers/scsi/libata-scsi.c
@@ -397,20 +397,129 @@ void ata_dump_status(unsigned id, struct ata_taskfile *tf)
397 } 397 }
398} 398}
399 399
400int ata_scsi_device_resume(struct scsi_device *sdev) 400/**
401 * ata_scsi_device_suspend - suspend ATA device associated with sdev
402 * @sdev: the SCSI device to suspend
403 * @state: target power management state
404 *
405 * Request suspend EH action on the ATA device associated with
406 * @sdev and wait for the operation to complete.
407 *
408 * LOCKING:
409 * Kernel thread context (may sleep).
410 *
411 * RETURNS:
412 * 0 on success, -errno otherwise.
413 */
414int ata_scsi_device_suspend(struct scsi_device *sdev, pm_message_t state)
401{ 415{
402 struct ata_port *ap = ata_shost_to_port(sdev->host); 416 struct ata_port *ap = ata_shost_to_port(sdev->host);
403 struct ata_device *dev = __ata_scsi_find_dev(ap, sdev); 417 struct ata_device *dev = ata_scsi_find_dev(ap, sdev);
418 unsigned long flags;
419 unsigned int action;
420 int rc = 0;
421
422 if (!dev)
423 goto out;
424
425 spin_lock_irqsave(ap->lock, flags);
426
427 /* wait for the previous resume to complete */
428 while (dev->flags & ATA_DFLAG_SUSPENDED) {
429 spin_unlock_irqrestore(ap->lock, flags);
430 ata_port_wait_eh(ap);
431 spin_lock_irqsave(ap->lock, flags);
432 }
433
434 /* if @sdev is already detached, nothing to do */
435 if (sdev->sdev_state == SDEV_OFFLINE ||
436 sdev->sdev_state == SDEV_CANCEL || sdev->sdev_state == SDEV_DEL)
437 goto out_unlock;
438
439 /* request suspend */
440 action = ATA_EH_SUSPEND;
441 if (state.event != PM_EVENT_SUSPEND)
442 action |= ATA_EH_PM_FREEZE;
443 ap->eh_info.dev_action[dev->devno] |= action;
444 ap->eh_info.flags |= ATA_EHI_QUIET;
445 ata_port_schedule_eh(ap);
446
447 spin_unlock_irqrestore(ap->lock, flags);
448
449 /* wait for EH to do the job */
450 ata_port_wait_eh(ap);
451
452 spin_lock_irqsave(ap->lock, flags);
453
454 /* If @sdev is still attached but the associated ATA device
455 * isn't suspended, the operation failed.
456 */
457 if (sdev->sdev_state != SDEV_OFFLINE &&
458 sdev->sdev_state != SDEV_CANCEL && sdev->sdev_state != SDEV_DEL &&
459 !(dev->flags & ATA_DFLAG_SUSPENDED))
460 rc = -EIO;
404 461
405 return ata_device_resume(dev); 462 out_unlock:
463 spin_unlock_irqrestore(ap->lock, flags);
464 out:
465 if (rc == 0)
466 sdev->sdev_gendev.power.power_state = state;
467 return rc;
406} 468}
407 469
408int ata_scsi_device_suspend(struct scsi_device *sdev, pm_message_t state) 470/**
471 * ata_scsi_device_resume - resume ATA device associated with sdev
472 * @sdev: the SCSI device to resume
473 *
474 * Request resume EH action on the ATA device associated with
475 * @sdev and return immediately. This enables parallel
476 * wakeup/spinup of devices.
477 *
478 * LOCKING:
479 * Kernel thread context (may sleep).
480 *
481 * RETURNS:
482 * 0.
483 */
484int ata_scsi_device_resume(struct scsi_device *sdev)
409{ 485{
410 struct ata_port *ap = ata_shost_to_port(sdev->host); 486 struct ata_port *ap = ata_shost_to_port(sdev->host);
411 struct ata_device *dev = __ata_scsi_find_dev(ap, sdev); 487 struct ata_device *dev = ata_scsi_find_dev(ap, sdev);
488 struct ata_eh_info *ehi = &ap->eh_info;
489 unsigned long flags;
490 unsigned int action;
491
492 if (!dev)
493 goto out;
494
495 spin_lock_irqsave(ap->lock, flags);
496
497 /* if @sdev is already detached, nothing to do */
498 if (sdev->sdev_state == SDEV_OFFLINE ||
499 sdev->sdev_state == SDEV_CANCEL || sdev->sdev_state == SDEV_DEL)
500 goto out_unlock;
412 501
413 return ata_device_suspend(dev, state); 502 /* request resume */
503 action = ATA_EH_RESUME;
504 if (sdev->sdev_gendev.power.power_state.event == PM_EVENT_SUSPEND)
505 __ata_ehi_hotplugged(ehi);
506 else
507 action |= ATA_EH_PM_FREEZE | ATA_EH_SOFTRESET;
508 ehi->dev_action[dev->devno] |= action;
509
510 /* We don't want autopsy and verbose EH messages. Disable
511 * those if we're the only device on this link.
512 */
513 if (ata_port_max_devices(ap) == 1)
514 ehi->flags |= ATA_EHI_NO_AUTOPSY | ATA_EHI_QUIET;
515
516 ata_port_schedule_eh(ap);
517
518 out_unlock:
519 spin_unlock_irqrestore(ap->lock, flags);
520 out:
521 sdev->sdev_gendev.power.power_state = PMSG_ON;
522 return 0;
414} 523}
415 524
416/** 525/**
diff --git a/include/linux/libata.h b/include/linux/libata.h
index 363c7501843a..5ac262608199 100644
--- a/include/linux/libata.h
+++ b/include/linux/libata.h
@@ -687,8 +687,6 @@ extern int ata_port_online(struct ata_port *ap);
687extern int ata_port_offline(struct ata_port *ap); 687extern int ata_port_offline(struct ata_port *ap);
688extern int ata_scsi_device_resume(struct scsi_device *); 688extern int ata_scsi_device_resume(struct scsi_device *);
689extern int ata_scsi_device_suspend(struct scsi_device *, pm_message_t state); 689extern int ata_scsi_device_suspend(struct scsi_device *, pm_message_t state);
690extern int ata_device_resume(struct ata_device *);
691extern int ata_device_suspend(struct ata_device *, pm_message_t state);
692extern int ata_ratelimit(void); 690extern int ata_ratelimit(void);
693extern unsigned int ata_busy_sleep(struct ata_port *ap, 691extern unsigned int ata_busy_sleep(struct ata_port *ap,
694 unsigned long timeout_pat, 692 unsigned long timeout_pat,