aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/scsi/isci/init.c
diff options
context:
space:
mode:
authorArtur Wojcik <artur.wojcik@intel.com>2012-06-22 02:41:56 -0400
committerJames Bottomley <JBottomley@Parallels.com>2012-08-24 05:10:24 -0400
commite468dc112f38220ee78bc0de64190eca9812749b (patch)
treed6bfa83c3c72e288a01b1b4ced2c1116c20f095c /drivers/scsi/isci/init.c
parent303694eeee5eacad5b84105a15afd9e351e1891b (diff)
[SCSI] isci: implement suspend/resume support
Provide a "simple-dev-pm-ops" implementation that shuts down the domain and the device on suspend, and resumes the device and the domain on resume. All of the mechanics of restoring domain connectivity are handled by libsas once isci has notified libsas that all links should be back up. libsas is in charge of handling links that did not resume, or resumed out of order. Signed-off-by: Artur Wojcik <artur.wojcik@intel.com> Signed-off-by: Jacek Danecki <jacek.danecki@intel.com> Signed-off-by: Dan Williams <dan.j.williams@intel.com> Signed-off-by: James Bottomley <JBottomley@Parallels.com>
Diffstat (limited to 'drivers/scsi/isci/init.c')
-rw-r--r--drivers/scsi/isci/init.c58
1 files changed, 57 insertions, 1 deletions
diff --git a/drivers/scsi/isci/init.c b/drivers/scsi/isci/init.c
index 92c1d86d1fc6..da142a8726dc 100644
--- a/drivers/scsi/isci/init.c
+++ b/drivers/scsi/isci/init.c
@@ -156,7 +156,7 @@ static struct scsi_host_template isci_sht = {
156 .target_alloc = sas_target_alloc, 156 .target_alloc = sas_target_alloc,
157 .slave_configure = sas_slave_configure, 157 .slave_configure = sas_slave_configure,
158 .scan_finished = isci_host_scan_finished, 158 .scan_finished = isci_host_scan_finished,
159 .scan_start = isci_host_scan_start, 159 .scan_start = isci_host_start,
160 .change_queue_depth = sas_change_queue_depth, 160 .change_queue_depth = sas_change_queue_depth,
161 .change_queue_type = sas_change_queue_type, 161 .change_queue_type = sas_change_queue_type,
162 .bios_param = sas_bios_param, 162 .bios_param = sas_bios_param,
@@ -722,11 +722,67 @@ static void __devexit isci_pci_remove(struct pci_dev *pdev)
722 } 722 }
723} 723}
724 724
725#ifdef CONFIG_PM
726static int isci_suspend(struct device *dev)
727{
728 struct pci_dev *pdev = to_pci_dev(dev);
729 struct isci_host *ihost;
730 int i;
731
732 for_each_isci_host(i, ihost, pdev) {
733 sas_suspend_ha(&ihost->sas_ha);
734 isci_host_deinit(ihost);
735 }
736
737 pci_save_state(pdev);
738 pci_disable_device(pdev);
739 pci_set_power_state(pdev, PCI_D3hot);
740
741 return 0;
742}
743
744static int isci_resume(struct device *dev)
745{
746 struct pci_dev *pdev = to_pci_dev(dev);
747 struct isci_host *ihost;
748 int rc, i;
749
750 pci_set_power_state(pdev, PCI_D0);
751 pci_restore_state(pdev);
752
753 rc = pcim_enable_device(pdev);
754 if (rc) {
755 dev_err(&pdev->dev,
756 "enabling device failure after resume(%d)\n", rc);
757 return rc;
758 }
759
760 pci_set_master(pdev);
761
762 for_each_isci_host(i, ihost, pdev) {
763 sas_prep_resume_ha(&ihost->sas_ha);
764
765 isci_host_init(ihost);
766 isci_host_start(ihost->sas_ha.core.shost);
767 wait_for_start(ihost);
768
769 sas_resume_ha(&ihost->sas_ha);
770 }
771
772 return 0;
773}
774
775static SIMPLE_DEV_PM_OPS(isci_pm_ops, isci_suspend, isci_resume);
776#endif
777
725static struct pci_driver isci_pci_driver = { 778static struct pci_driver isci_pci_driver = {
726 .name = DRV_NAME, 779 .name = DRV_NAME,
727 .id_table = isci_id_table, 780 .id_table = isci_id_table,
728 .probe = isci_pci_probe, 781 .probe = isci_pci_probe,
729 .remove = __devexit_p(isci_pci_remove), 782 .remove = __devexit_p(isci_pci_remove),
783#ifdef CONFIG_PM
784 .driver.pm = &isci_pm_ops,
785#endif
730}; 786};
731 787
732static __init int isci_init(void) 788static __init int isci_init(void)