diff options
author | Tejun Heo <htejun@gmail.com> | 2007-05-04 15:27:47 -0400 |
---|---|---|
committer | Jeff Garzik <jeff@garzik.org> | 2007-05-11 18:01:03 -0400 |
commit | 9666f4009c22f6520ac3fb8a19c9e32ab973e828 (patch) | |
tree | eaac13cd5890af6298e5576a48c29891f0890bd1 /drivers/ata/libata-scsi.c | |
parent | 0a3fd051c7036ef71b58863f8e5da7c3dabd9d3f (diff) |
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.
Signed-off-by: Tejun Heo <htejun@gmail.com>
Signed-off-by: Jeff Garzik <jeff@garzik.org>
Diffstat (limited to 'drivers/ata/libata-scsi.c')
-rw-r--r-- | drivers/ata/libata-scsi.c | 129 |
1 files changed, 2 insertions, 127 deletions
diff --git a/drivers/ata/libata-scsi.c b/drivers/ata/libata-scsi.c index 9afba2ba489e..8f800196d596 100644 --- a/drivers/ata/libata-scsi.c +++ b/drivers/ata/libata-scsi.c | |||
@@ -510,133 +510,6 @@ static void ata_dump_status(unsigned id, struct ata_taskfile *tf) | |||
510 | } | 510 | } |
511 | } | 511 | } |
512 | 512 | ||
513 | #ifdef CONFIG_PM | ||
514 | /** | ||
515 | * ata_scsi_device_suspend - suspend ATA device associated with sdev | ||
516 | * @sdev: the SCSI device to suspend | ||
517 | * @mesg: target power management message | ||
518 | * | ||
519 | * Request suspend EH action on the ATA device associated with | ||
520 | * @sdev and wait for the operation to complete. | ||
521 | * | ||
522 | * LOCKING: | ||
523 | * Kernel thread context (may sleep). | ||
524 | * | ||
525 | * RETURNS: | ||
526 | * 0 on success, -errno otherwise. | ||
527 | */ | ||
528 | int ata_scsi_device_suspend(struct scsi_device *sdev, pm_message_t mesg) | ||
529 | { | ||
530 | struct ata_port *ap = ata_shost_to_port(sdev->host); | ||
531 | struct ata_device *dev = ata_scsi_find_dev(ap, sdev); | ||
532 | unsigned long flags; | ||
533 | unsigned int action; | ||
534 | int rc = 0; | ||
535 | |||
536 | if (!dev) | ||
537 | goto out; | ||
538 | |||
539 | spin_lock_irqsave(ap->lock, flags); | ||
540 | |||
541 | /* wait for the previous resume to complete */ | ||
542 | while (dev->flags & ATA_DFLAG_SUSPENDED) { | ||
543 | spin_unlock_irqrestore(ap->lock, flags); | ||
544 | ata_port_wait_eh(ap); | ||
545 | spin_lock_irqsave(ap->lock, flags); | ||
546 | } | ||
547 | |||
548 | /* if @sdev is already detached, nothing to do */ | ||
549 | if (sdev->sdev_state == SDEV_OFFLINE || | ||
550 | sdev->sdev_state == SDEV_CANCEL || sdev->sdev_state == SDEV_DEL) | ||
551 | goto out_unlock; | ||
552 | |||
553 | /* request suspend */ | ||
554 | action = ATA_EH_SUSPEND; | ||
555 | if (mesg.event != PM_EVENT_SUSPEND) | ||
556 | action |= ATA_EH_PM_FREEZE; | ||
557 | ap->eh_info.dev_action[dev->devno] |= action; | ||
558 | ap->eh_info.flags |= ATA_EHI_QUIET; | ||
559 | ata_port_schedule_eh(ap); | ||
560 | |||
561 | spin_unlock_irqrestore(ap->lock, flags); | ||
562 | |||
563 | /* wait for EH to do the job */ | ||
564 | ata_port_wait_eh(ap); | ||
565 | |||
566 | spin_lock_irqsave(ap->lock, flags); | ||
567 | |||
568 | /* If @sdev is still attached but the associated ATA device | ||
569 | * isn't suspended, the operation failed. | ||
570 | */ | ||
571 | if (sdev->sdev_state != SDEV_OFFLINE && | ||
572 | sdev->sdev_state != SDEV_CANCEL && sdev->sdev_state != SDEV_DEL && | ||
573 | !(dev->flags & ATA_DFLAG_SUSPENDED)) | ||
574 | rc = -EIO; | ||
575 | |||
576 | out_unlock: | ||
577 | spin_unlock_irqrestore(ap->lock, flags); | ||
578 | out: | ||
579 | if (rc == 0) | ||
580 | sdev->sdev_gendev.power.power_state = mesg; | ||
581 | return rc; | ||
582 | } | ||
583 | |||
584 | /** | ||
585 | * ata_scsi_device_resume - resume ATA device associated with sdev | ||
586 | * @sdev: the SCSI device to resume | ||
587 | * | ||
588 | * Request resume EH action on the ATA device associated with | ||
589 | * @sdev and return immediately. This enables parallel | ||
590 | * wakeup/spinup of devices. | ||
591 | * | ||
592 | * LOCKING: | ||
593 | * Kernel thread context (may sleep). | ||
594 | * | ||
595 | * RETURNS: | ||
596 | * 0. | ||
597 | */ | ||
598 | int ata_scsi_device_resume(struct scsi_device *sdev) | ||
599 | { | ||
600 | struct ata_port *ap = ata_shost_to_port(sdev->host); | ||
601 | struct ata_device *dev = ata_scsi_find_dev(ap, sdev); | ||
602 | struct ata_eh_info *ehi = &ap->eh_info; | ||
603 | unsigned long flags; | ||
604 | unsigned int action; | ||
605 | |||
606 | if (!dev) | ||
607 | goto out; | ||
608 | |||
609 | spin_lock_irqsave(ap->lock, flags); | ||
610 | |||
611 | /* if @sdev is already detached, nothing to do */ | ||
612 | if (sdev->sdev_state == SDEV_OFFLINE || | ||
613 | sdev->sdev_state == SDEV_CANCEL || sdev->sdev_state == SDEV_DEL) | ||
614 | goto out_unlock; | ||
615 | |||
616 | /* request resume */ | ||
617 | action = ATA_EH_RESUME; | ||
618 | if (sdev->sdev_gendev.power.power_state.event == PM_EVENT_SUSPEND) | ||
619 | __ata_ehi_hotplugged(ehi); | ||
620 | else | ||
621 | action |= ATA_EH_PM_FREEZE | ATA_EH_SOFTRESET; | ||
622 | ehi->dev_action[dev->devno] |= action; | ||
623 | |||
624 | /* We don't want autopsy and verbose EH messages. Disable | ||
625 | * those if we're the only device on this link. | ||
626 | */ | ||
627 | if (ata_port_max_devices(ap) == 1) | ||
628 | ehi->flags |= ATA_EHI_NO_AUTOPSY | ATA_EHI_QUIET; | ||
629 | |||
630 | ata_port_schedule_eh(ap); | ||
631 | |||
632 | out_unlock: | ||
633 | spin_unlock_irqrestore(ap->lock, flags); | ||
634 | out: | ||
635 | sdev->sdev_gendev.power.power_state = PMSG_ON; | ||
636 | return 0; | ||
637 | } | ||
638 | #endif /* CONFIG_PM */ | ||
639 | |||
640 | /** | 513 | /** |
641 | * ata_to_sense_error - convert ATA error to SCSI error | 514 | * ata_to_sense_error - convert ATA error to SCSI error |
642 | * @id: ATA device number | 515 | * @id: ATA device number |
@@ -929,6 +802,8 @@ int ata_scsi_slave_config(struct scsi_device *sdev) | |||
929 | 802 | ||
930 | blk_queue_max_phys_segments(sdev->request_queue, LIBATA_MAX_PRD); | 803 | blk_queue_max_phys_segments(sdev->request_queue, LIBATA_MAX_PRD); |
931 | 804 | ||
805 | sdev->manage_start_stop = 1; | ||
806 | |||
932 | if (dev) | 807 | if (dev) |
933 | ata_scsi_dev_config(sdev, dev); | 808 | ata_scsi_dev_config(sdev, dev); |
934 | 809 | ||