diff options
author | Hannes Reinecke <hare@suse.de> | 2007-10-19 12:32:21 +0400 |
---|---|---|
committer | James Bottomley <jejb@mulgrave.localdomain> | 2007-10-21 20:10:50 +0400 |
commit | b5720729f58a4a05b0e2c8c61ac3ed3a3e9f94e5 (patch) | |
tree | 7f1271417db63a27474d50d3e43e399a5cef4d93 /drivers/scsi/aic7xxx/aic79xx_osm_pci.c | |
parent | eb7a1698d24783dd215cb86a12cadebe9b4e7046 (diff) | |
download | linux-b5720729f58a4a05b0e2c8c61ac3ed3a3e9f94e5.tar.xz |
[SCSI] aic7xxx: Add suspend/resume support
The aic7xxx driver already contains fragments for suspend/resume
support. So we only need to update them to the current interface
and have full PCI suspend/resume.
Signed-off-by: Hannes Reinecke <hare@suse.de>
Tested-by: Jens Axboe <jens.axboe@oracle.com>
Signed-off-by: James Bottomley <James.Bottomley@SteelEye.com>
Diffstat (limited to 'drivers/scsi/aic7xxx/aic79xx_osm_pci.c')
-rw-r--r-- | drivers/scsi/aic7xxx/aic79xx_osm_pci.c | 50 |
1 files changed, 50 insertions, 0 deletions
diff --git a/drivers/scsi/aic7xxx/aic79xx_osm_pci.c b/drivers/scsi/aic7xxx/aic79xx_osm_pci.c index c62ce41f2793..66f0259edb69 100644 --- a/drivers/scsi/aic7xxx/aic79xx_osm_pci.c +++ b/drivers/scsi/aic7xxx/aic79xx_osm_pci.c @@ -50,6 +50,8 @@ static int ahd_linux_pci_reserve_io_regions(struct ahd_softc *ahd, static int ahd_linux_pci_reserve_mem_region(struct ahd_softc *ahd, u_long *bus_addr, uint8_t __iomem **maddr); +static int ahd_linux_pci_dev_suspend(struct pci_dev *pdev, pm_message_t mesg); +static int ahd_linux_pci_dev_resume(struct pci_dev *pdev); static void ahd_linux_pci_dev_remove(struct pci_dev *pdev); /* Define the macro locally since it's different for different class of chips. @@ -86,10 +88,58 @@ MODULE_DEVICE_TABLE(pci, ahd_linux_pci_id_table); static struct pci_driver aic79xx_pci_driver = { .name = "aic79xx", .probe = ahd_linux_pci_dev_probe, +#ifdef CONFIG_PM + .suspend = ahd_linux_pci_dev_suspend, + .resume = ahd_linux_pci_dev_resume, +#endif .remove = ahd_linux_pci_dev_remove, .id_table = ahd_linux_pci_id_table }; +static int +ahd_linux_pci_dev_suspend(struct pci_dev *pdev, pm_message_t mesg) +{ + struct ahd_softc *ahd = pci_get_drvdata(pdev); + int rc; + + if ((rc = ahd_suspend(ahd))) + return rc; + + ahd_pci_suspend(ahd); + + pci_save_state(pdev); + pci_disable_device(pdev); + + if (mesg.event == PM_EVENT_SUSPEND) + pci_set_power_state(pdev, PCI_D3hot); + + return rc; +} + +static int +ahd_linux_pci_dev_resume(struct pci_dev *pdev) +{ + struct ahd_softc *ahd = pci_get_drvdata(pdev); + int rc; + + pci_set_power_state(pdev, PCI_D0); + pci_restore_state(pdev); + + if ((rc = pci_enable_device(pdev))) { + dev_printk(KERN_ERR, &pdev->dev, + "failed to enable device after resume (%d)\n", rc); + return rc; + } + + pci_set_master(pdev); + + ahd_pci_resume(ahd); + + ahd_resume(ahd); + + return rc; +} + static void ahd_linux_pci_dev_remove(struct pci_dev *pdev) { |