* [PATCH 1/4] aic7xxx: Add suspend/resume support @ 2007-10-19 8:32 Hannes Reinecke 2007-10-19 8:44 ` Christoph Hellwig 0 siblings, 1 reply; 5+ messages in thread From: Hannes Reinecke @ 2007-10-19 8:32 UTC (permalink / raw) To: James Bottomley; +Cc: linux-scsi 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> --- drivers/scsi/aic7xxx/aic7770.c | 16 ---------- drivers/scsi/aic7xxx/aic79xx.h | 11 +++++++ drivers/scsi/aic7xxx/aic79xx_core.c | 7 +---- drivers/scsi/aic7xxx/aic79xx_osm_pci.c | 50 ++++++++++++++++++++++++++++++++ drivers/scsi/aic7xxx/aic79xx_pci.c | 27 +++++++++++++++++ drivers/scsi/aic7xxx/aic7xxx.h | 11 +------ drivers/scsi/aic7xxx/aic7xxx_osm_pci.c | 46 +++++++++++++++++++++++++++++ drivers/scsi/aic7xxx/aic7xxx_pci.c | 16 +--------- 8 files changed, 137 insertions(+), 47 deletions(-) diff --git a/drivers/scsi/aic7xxx/aic7770.c b/drivers/scsi/aic7xxx/aic7770.c index c4d1723..6d86a9b 100644 --- a/drivers/scsi/aic7xxx/aic7770.c +++ b/drivers/scsi/aic7xxx/aic7770.c @@ -60,8 +60,6 @@ #define ID_OLV_274xD 0x04907783 /* Olivetti OEM (Differential) */ static int aic7770_chip_init(struct ahc_softc *ahc); -static int aic7770_suspend(struct ahc_softc *ahc); -static int aic7770_resume(struct ahc_softc *ahc); static int aha2840_load_seeprom(struct ahc_softc *ahc); static ahc_device_setup_t ahc_aic7770_VL_setup; static ahc_device_setup_t ahc_aic7770_EISA_setup; @@ -155,8 +153,6 @@ aic7770_config(struct ahc_softc *ahc, struct aic7770_identity *entry, u_int io) return (error); ahc->bus_chip_init = aic7770_chip_init; - ahc->bus_suspend = aic7770_suspend; - ahc->bus_resume = aic7770_resume; error = ahc_reset(ahc, /*reinit*/FALSE); if (error != 0) @@ -272,18 +268,6 @@ aic7770_chip_init(struct ahc_softc *ahc) return (ahc_chip_init(ahc)); } -static int -aic7770_suspend(struct ahc_softc *ahc) -{ - return (ahc_suspend(ahc)); -} - -static int -aic7770_resume(struct ahc_softc *ahc) -{ - return (ahc_resume(ahc)); -} - /* * Read the 284x SEEPROM. */ diff --git a/drivers/scsi/aic7xxx/aic79xx.h b/drivers/scsi/aic7xxx/aic79xx.h index 27adbb2..ce638aa 100644 --- a/drivers/scsi/aic7xxx/aic79xx.h +++ b/drivers/scsi/aic7xxx/aic79xx.h @@ -1003,8 +1003,15 @@ struct ahd_suspend_channel_state { uint8_t seqctl; }; +struct ahd_suspend_pci_state { + uint32_t devconfig; + uint8_t command; + uint8_t csize_lattime; +}; + struct ahd_suspend_state { struct ahd_suspend_channel_state channel[2]; + struct ahd_suspend_pci_state pci_state; uint8_t optionmode; uint8_t dscommand0; uint8_t dspcistatus; @@ -1333,6 +1340,8 @@ struct ahd_pci_identity *ahd_find_pci_device(ahd_dev_softc_t); int ahd_pci_config(struct ahd_softc *, struct ahd_pci_identity *); int ahd_pci_test_register_access(struct ahd_softc *); +void ahd_pci_suspend(struct ahd_softc *); +void ahd_pci_resume(struct ahd_softc *); /************************** SCB and SCB queue management **********************/ void ahd_qinfifo_requeue_tail(struct ahd_softc *ahd, @@ -1343,6 +1352,8 @@ struct ahd_softc *ahd_alloc(void *platform_arg, char *name); int ahd_softc_init(struct ahd_softc *); void ahd_controller_info(struct ahd_softc *ahd, char *buf); int ahd_init(struct ahd_softc *ahd); +int ahd_suspend(struct ahd_softc *ahd); +void ahd_resume(struct ahd_softc *ahd); int ahd_default_config(struct ahd_softc *ahd); int ahd_parse_vpddata(struct ahd_softc *ahd, struct vpd_config *vpd); diff --git a/drivers/scsi/aic7xxx/aic79xx_core.c b/drivers/scsi/aic7xxx/aic79xx_core.c index 05f692b..a7dd8cd 100644 --- a/drivers/scsi/aic7xxx/aic79xx_core.c +++ b/drivers/scsi/aic7xxx/aic79xx_core.c @@ -7175,7 +7175,6 @@ ahd_pause_and_flushwork(struct ahd_softc *ahd) ahd->flags &= ~AHD_ALL_INTERRUPTS; } -#if 0 int ahd_suspend(struct ahd_softc *ahd) { @@ -7189,19 +7188,15 @@ ahd_suspend(struct ahd_softc *ahd) ahd_shutdown(ahd); return (0); } -#endif /* 0 */ -#if 0 -int +void ahd_resume(struct ahd_softc *ahd) { ahd_reset(ahd, /*reinit*/TRUE); ahd_intr_enable(ahd, TRUE); ahd_restart(ahd); - return (0); } -#endif /* 0 */ /************************** Busy Target Table *********************************/ /* diff --git a/drivers/scsi/aic7xxx/aic79xx_osm_pci.c b/drivers/scsi/aic7xxx/aic79xx_osm_pci.c index c62ce41..66f0259 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) { diff --git a/drivers/scsi/aic7xxx/aic79xx_pci.c b/drivers/scsi/aic7xxx/aic79xx_pci.c index 0bada00..7a203a9 100644 --- a/drivers/scsi/aic7xxx/aic79xx_pci.c +++ b/drivers/scsi/aic7xxx/aic79xx_pci.c @@ -389,6 +389,33 @@ ahd_pci_config(struct ahd_softc *ahd, struct ahd_pci_identity *entry) return error; } +void +ahd_pci_suspend(struct ahd_softc *ahd) +{ + /* + * Save chip register configuration data for chip resets + * that occur during runtime and resume events. + */ + ahd->suspend_state.pci_state.devconfig = + ahd_pci_read_config(ahd->dev_softc, DEVCONFIG, /*bytes*/4); + ahd->suspend_state.pci_state.command = + ahd_pci_read_config(ahd->dev_softc, PCIR_COMMAND, /*bytes*/1); + ahd->suspend_state.pci_state.csize_lattime = + ahd_pci_read_config(ahd->dev_softc, CSIZE_LATTIME, /*bytes*/1); + +} + +void +ahd_pci_resume(struct ahd_softc *ahd) +{ + ahd_pci_write_config(ahd->dev_softc, DEVCONFIG, + ahd->suspend_state.pci_state.devconfig, /*bytes*/4); + ahd_pci_write_config(ahd->dev_softc, PCIR_COMMAND, + ahd->suspend_state.pci_state.command, /*bytes*/1); + ahd_pci_write_config(ahd->dev_softc, CSIZE_LATTIME, + ahd->suspend_state.pci_state.csize_lattime, /*bytes*/1); +} + /* * Perform some simple tests that should catch situations where * our registers are invalidly mapped. diff --git a/drivers/scsi/aic7xxx/aic7xxx.h b/drivers/scsi/aic7xxx/aic7xxx.h index e1bd57b..3d4e42d 100644 --- a/drivers/scsi/aic7xxx/aic7xxx.h +++ b/drivers/scsi/aic7xxx/aic7xxx.h @@ -962,16 +962,6 @@ struct ahc_softc { ahc_bus_chip_init_t bus_chip_init; /* - * Bus specific suspend routine. - */ - ahc_bus_suspend_t bus_suspend; - - /* - * Bus specific resume routine. - */ - ahc_bus_resume_t bus_resume; - - /* * Target mode related state kept on a per enabled lun basis. * Targets that are not enabled will have null entries. * As an initiator, we keep one target entry for our initiator @@ -1153,6 +1143,7 @@ struct ahc_pci_identity *ahc_find_pci_device(ahc_dev_softc_t); int ahc_pci_config(struct ahc_softc *, struct ahc_pci_identity *); int ahc_pci_test_register_access(struct ahc_softc *); +void ahc_pci_resume(struct ahc_softc *ahc); /*************************** EISA/VL Front End ********************************/ struct aic7770_identity *aic7770_find_device(uint32_t); diff --git a/drivers/scsi/aic7xxx/aic7xxx_osm_pci.c b/drivers/scsi/aic7xxx/aic7xxx_osm_pci.c index ea5687d..4488946 100644 --- a/drivers/scsi/aic7xxx/aic7xxx_osm_pci.c +++ b/drivers/scsi/aic7xxx/aic7xxx_osm_pci.c @@ -49,6 +49,8 @@ static int ahc_linux_pci_reserve_io_region(struct ahc_softc *ahc, static int ahc_linux_pci_reserve_mem_region(struct ahc_softc *ahc, u_long *bus_addr, uint8_t __iomem **maddr); +static int ahc_linux_pci_dev_suspend(struct pci_dev *pdev, pm_message_t mesg); +static int ahc_linux_pci_dev_resume(struct pci_dev *pdev); static void ahc_linux_pci_dev_remove(struct pci_dev *pdev); /* Define the macro locally since it's different for different class of chips. @@ -133,10 +135,54 @@ MODULE_DEVICE_TABLE(pci, ahc_linux_pci_id_table); static struct pci_driver aic7xxx_pci_driver = { .name = "aic7xxx", .probe = ahc_linux_pci_dev_probe, +#ifdef CONFIG_PM + .suspend = ahc_linux_pci_dev_suspend, + .resume = ahc_linux_pci_dev_resume, +#endif .remove = ahc_linux_pci_dev_remove, .id_table = ahc_linux_pci_id_table }; +static int +ahc_linux_pci_dev_suspend(struct pci_dev *pdev, pm_message_t mesg) +{ + struct ahc_softc *ahc = pci_get_drvdata(pdev); + int rc; + + if ((rc = ahc_suspend(ahc))) + return rc; + + 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 +ahc_linux_pci_dev_resume(struct pci_dev *pdev) +{ + struct ahc_softc *ahc = 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); + + ahc_pci_resume(ahc); + + return (ahc_resume(ahc)); +} + static void ahc_linux_pci_dev_remove(struct pci_dev *pdev) { diff --git a/drivers/scsi/aic7xxx/aic7xxx_pci.c b/drivers/scsi/aic7xxx/aic7xxx_pci.c index 09c8172..ae35937 100644 --- a/drivers/scsi/aic7xxx/aic7xxx_pci.c +++ b/drivers/scsi/aic7xxx/aic7xxx_pci.c @@ -633,8 +633,6 @@ static void write_brdctl(struct ahc_softc *ahc, uint8_t value); static uint8_t read_brdctl(struct ahc_softc *ahc); static void ahc_pci_intr(struct ahc_softc *ahc); static int ahc_pci_chip_init(struct ahc_softc *ahc); -static int ahc_pci_suspend(struct ahc_softc *ahc); -static int ahc_pci_resume(struct ahc_softc *ahc); static int ahc_9005_subdevinfo_valid(uint16_t device, uint16_t vendor, @@ -791,8 +789,6 @@ ahc_pci_config(struct ahc_softc *ahc, struct ahc_pci_identity *entry) ahc->bus_intr = ahc_pci_intr; ahc->bus_chip_init = ahc_pci_chip_init; - ahc->bus_suspend = ahc_pci_suspend; - ahc->bus_resume = ahc_pci_resume; /* Remeber how the card was setup in case there is no SEEPROM */ if ((ahc_inb(ahc, HCNTRL) & POWRDN) == 0) { @@ -2024,18 +2020,9 @@ ahc_pci_chip_init(struct ahc_softc *ahc) return (ahc_chip_init(ahc)); } -static int -ahc_pci_suspend(struct ahc_softc *ahc) -{ - return (ahc_suspend(ahc)); -} - -static int +void ahc_pci_resume(struct ahc_softc *ahc) { - - pci_set_power_state(ahc->dev_softc, AHC_POWER_STATE_D0); - /* * We assume that the OS has restored our register * mappings, etc. Just update the config space registers @@ -2063,7 +2050,6 @@ ahc_pci_resume(struct ahc_softc *ahc) &sxfrctl1); ahc_release_seeprom(&sd); } - return (ahc_resume(ahc)); } static int -- 1.5.2.4 ^ permalink raw reply related [flat|nested] 5+ messages in thread
* Re: [PATCH 1/4] aic7xxx: Add suspend/resume support 2007-10-19 8:32 [PATCH 1/4] aic7xxx: Add suspend/resume support Hannes Reinecke @ 2007-10-19 8:44 ` Christoph Hellwig 2007-10-19 12:35 ` Hannes Reinecke 0 siblings, 1 reply; 5+ messages in thread From: Christoph Hellwig @ 2007-10-19 8:44 UTC (permalink / raw) To: Hannes Reinecke; +Cc: James Bottomley, linux-scsi I think this needs a little restructuring. ahd_pci_suspend/ahd_pci_resume should be merged into their callers and use the normal Linux pci accessors, and ahd_suspend/ahd_resume are tiny enough to merged into the caller aswell. > +#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) I think this needsa #ifdef CONFIG_PM aswell. Also any chance you could implement functions before their use so we can avoid forward declarations. > +{ > + struct ahd_softc *ahd = pci_get_drvdata(pdev); > + int rc; > + > + if ((rc = ahd_suspend(ahd))) > + return rc; rc = ahd_suspend(ahd) if (rc) return rc; but as I mentioned above better just inline the content of ahd_suspend into this function. That would also catch that ahd_suspend returns positive errno values and we'd have to invert them here. Same comments apply to the aic7xxx portion. ^ permalink raw reply [flat|nested] 5+ messages in thread
* Re: [PATCH 1/4] aic7xxx: Add suspend/resume support 2007-10-19 8:44 ` Christoph Hellwig @ 2007-10-19 12:35 ` Hannes Reinecke 2007-10-19 13:02 ` Christoph Hellwig 0 siblings, 1 reply; 5+ messages in thread From: Hannes Reinecke @ 2007-10-19 12:35 UTC (permalink / raw) To: Christoph Hellwig; +Cc: James Bottomley, linux-scsi [-- Attachment #1: Type: text/plain, Size: 1687 bytes --] Christoph Hellwig wrote: > I think this needs a little restructuring. ahd_pci_suspend/ahd_pci_resume > should be merged into their callers and use the normal Linux pci accessors, > and ahd_suspend/ahd_resume are tiny enough to merged into the caller aswell. > Yes, partially. ahc_pci_resume() has to stay there as it uses quite some functions from aic7xxx_pci.c. And I'd rather keep the overall structure (ie split between linux-specific and generic pci access) for now. In the long run it should be restructured as we don't do cross-compilation with ***BSD anymore. >> +#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) > > I think this needsa #ifdef CONFIG_PM aswell. Also any chance you > could implement functions before their use so we can avoid forward > declarations. > Yes, no problem. >> +{ >> + struct ahd_softc *ahd = pci_get_drvdata(pdev); >> + int rc; >> + >> + if ((rc = ahd_suspend(ahd))) >> + return rc; > > rc = ahd_suspend(ahd) > if (rc) > return rc; > > but as I mentioned above better just inline the content of ahd_suspend > into this function. That would also catch that ahd_suspend returns > positive errno values and we'd have to invert them here. > Ok. Done. Updated patch attached. More to your liking? Cheers, Hannes -- Dr. Hannes Reinecke zSeries & Storage hare@suse.de +49 911 74053 688 SUSE LINUX Products GmbH, Maxfeldstr. 5, 90409 Nürnberg GF: Markus Rex, HRB 16746 (AG Nürnberg) [-- Attachment #2: 0001-aic7xxx-Add-suspend-resume-support.patch --] [-- Type: text/x-patch, Size: 19837 bytes --] >From 2dc1cdee053846fafc98a819bdad1533ac7c2f04 Mon Sep 17 00:00:00 2001 From: Hannes Reinecke <hare@suse.de> Date: Fri, 19 Oct 2007 09:13:17 +0200 Subject: [PATCH 1/4] 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> --- drivers/scsi/aic7xxx/aic7770.c | 16 ----- drivers/scsi/aic7xxx/aic79xx.h | 9 +++ drivers/scsi/aic7xxx/aic79xx_core.c | 33 +--------- drivers/scsi/aic7xxx/aic79xx_osm_pci.c | 109 ++++++++++++++++++++++++++------ drivers/scsi/aic7xxx/aic79xx_pci.c | 24 ------- drivers/scsi/aic7xxx/aic79xx_pci.h | 25 +++++++ drivers/scsi/aic7xxx/aic7xxx.h | 18 +----- drivers/scsi/aic7xxx/aic7xxx_core.c | 41 +------------ drivers/scsi/aic7xxx/aic7xxx_osm_pci.c | 88 +++++++++++++++++++++----- drivers/scsi/aic7xxx/aic7xxx_pci.c | 16 +----- 10 files changed, 204 insertions(+), 175 deletions(-) diff --git a/drivers/scsi/aic7xxx/aic7770.c b/drivers/scsi/aic7xxx/aic7770.c index c4d1723..6d86a9b 100644 --- a/drivers/scsi/aic7xxx/aic7770.c +++ b/drivers/scsi/aic7xxx/aic7770.c @@ -60,8 +60,6 @@ #define ID_OLV_274xD 0x04907783 /* Olivetti OEM (Differential) */ static int aic7770_chip_init(struct ahc_softc *ahc); -static int aic7770_suspend(struct ahc_softc *ahc); -static int aic7770_resume(struct ahc_softc *ahc); static int aha2840_load_seeprom(struct ahc_softc *ahc); static ahc_device_setup_t ahc_aic7770_VL_setup; static ahc_device_setup_t ahc_aic7770_EISA_setup; @@ -155,8 +153,6 @@ aic7770_config(struct ahc_softc *ahc, struct aic7770_identity *entry, u_int io) return (error); ahc->bus_chip_init = aic7770_chip_init; - ahc->bus_suspend = aic7770_suspend; - ahc->bus_resume = aic7770_resume; error = ahc_reset(ahc, /*reinit*/FALSE); if (error != 0) @@ -272,18 +268,6 @@ aic7770_chip_init(struct ahc_softc *ahc) return (ahc_chip_init(ahc)); } -static int -aic7770_suspend(struct ahc_softc *ahc) -{ - return (ahc_suspend(ahc)); -} - -static int -aic7770_resume(struct ahc_softc *ahc) -{ - return (ahc_resume(ahc)); -} - /* * Read the 284x SEEPROM. */ diff --git a/drivers/scsi/aic7xxx/aic79xx.h b/drivers/scsi/aic7xxx/aic79xx.h index 27adbb2..a96a2ff 100644 --- a/drivers/scsi/aic7xxx/aic79xx.h +++ b/drivers/scsi/aic7xxx/aic79xx.h @@ -1003,8 +1003,15 @@ struct ahd_suspend_channel_state { uint8_t seqctl; }; +struct ahd_suspend_pci_state { + uint32_t devconfig; + uint8_t command; + uint8_t csize_lattime; +}; + struct ahd_suspend_state { struct ahd_suspend_channel_state channel[2]; + struct ahd_suspend_pci_state pci_state; uint8_t optionmode; uint8_t dscommand0; uint8_t dspcistatus; @@ -1343,6 +1350,8 @@ struct ahd_softc *ahd_alloc(void *platform_arg, char *name); int ahd_softc_init(struct ahd_softc *); void ahd_controller_info(struct ahd_softc *ahd, char *buf); int ahd_init(struct ahd_softc *ahd); +void ahd_shutdown(void *arg); +void ahd_restart(struct ahd_softc *ahd); int ahd_default_config(struct ahd_softc *ahd); int ahd_parse_vpddata(struct ahd_softc *ahd, struct vpd_config *vpd); diff --git a/drivers/scsi/aic7xxx/aic79xx_core.c b/drivers/scsi/aic7xxx/aic79xx_core.c index 05f692b..91f6f4f 100644 --- a/drivers/scsi/aic7xxx/aic79xx_core.c +++ b/drivers/scsi/aic7xxx/aic79xx_core.c @@ -255,7 +255,6 @@ static void ahd_freeze_devq(struct ahd_softc *ahd, static void ahd_handle_scb_status(struct ahd_softc *ahd, struct scb *scb); static struct ahd_phase_table_entry* ahd_lookup_phase_entry(int phase); -static void ahd_shutdown(void *arg); static void ahd_update_coalescing_values(struct ahd_softc *ahd, u_int timer, u_int maxcmds, @@ -357,7 +356,7 @@ ahd_complete_scb(struct ahd_softc *ahd, struct scb *scb) /* * Restart the sequencer program from address zero */ -static void +void ahd_restart(struct ahd_softc *ahd) { @@ -5456,7 +5455,7 @@ ahd_free(struct ahd_softc *ahd) return; } -static void +void ahd_shutdown(void *arg) { struct ahd_softc *ahd; @@ -7175,34 +7174,6 @@ ahd_pause_and_flushwork(struct ahd_softc *ahd) ahd->flags &= ~AHD_ALL_INTERRUPTS; } -#if 0 -int -ahd_suspend(struct ahd_softc *ahd) -{ - - ahd_pause_and_flushwork(ahd); - - if (LIST_FIRST(&ahd->pending_scbs) != NULL) { - ahd_unpause(ahd); - return (EBUSY); - } - ahd_shutdown(ahd); - return (0); -} -#endif /* 0 */ - -#if 0 -int -ahd_resume(struct ahd_softc *ahd) -{ - - ahd_reset(ahd, /*reinit*/TRUE); - ahd_intr_enable(ahd, TRUE); - ahd_restart(ahd); - return (0); -} -#endif /* 0 */ - /************************** Busy Target Table *********************************/ /* * Set SCBPTR to the SCB that contains the busy diff --git a/drivers/scsi/aic7xxx/aic79xx_osm_pci.c b/drivers/scsi/aic7xxx/aic79xx_osm_pci.c index c62ce41..d93d488 100644 --- a/drivers/scsi/aic7xxx/aic79xx_osm_pci.c +++ b/drivers/scsi/aic7xxx/aic79xx_osm_pci.c @@ -43,15 +43,6 @@ #include "aic79xx_inline.h" #include "aic79xx_pci.h" -static int ahd_linux_pci_dev_probe(struct pci_dev *pdev, - const struct pci_device_id *ent); -static int ahd_linux_pci_reserve_io_regions(struct ahd_softc *ahd, - u_long *base, u_long *base2); -static int ahd_linux_pci_reserve_mem_region(struct ahd_softc *ahd, - u_long *bus_addr, - uint8_t __iomem **maddr); -static void ahd_linux_pci_dev_remove(struct pci_dev *pdev); - /* Define the macro locally since it's different for different class of chips. */ #define ID(x) \ @@ -83,12 +74,81 @@ static struct pci_device_id ahd_linux_pci_id_table[] = { MODULE_DEVICE_TABLE(pci, ahd_linux_pci_id_table); -static struct pci_driver aic79xx_pci_driver = { - .name = "aic79xx", - .probe = ahd_linux_pci_dev_probe, - .remove = ahd_linux_pci_dev_remove, - .id_table = ahd_linux_pci_id_table -}; +#ifdef CONFIG_PM +int +ahd_linux_pci_dev_suspend(struct pci_dev *pdev, pm_message_t mesg) +{ + struct ahd_softc *ahd = pci_get_drvdata(pdev); + + /* + * Shutdown the HBA + */ + ahd_pause_and_flushwork(ahd); + + if (LIST_FIRST(&ahd->pending_scbs) != NULL) { + ahd_unpause(ahd); + return -EBUSY; + } + + ahd_shutdown(ahd); + + /* + * Save chip register configuration data for chip resets + * that occur during runtime and resume events. + */ + pci_read_config_dword(ahd->dev_softc, DEVCONFIG, + &ahd->suspend_state.pci_state.devconfig); + pci_read_config_byte(ahd->dev_softc, PCIR_COMMAND, + &ahd->suspend_state.pci_state.command); + pci_read_config_byte(ahd->dev_softc, CSIZE_LATTIME, + &ahd->suspend_state.pci_state.csize_lattime); + + pci_save_state(pdev); + pci_disable_device(pdev); + + if (mesg.event == PM_EVENT_SUSPEND) + pci_set_power_state(pdev, PCI_D3hot); + + return 0; +} + +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); + + /* + * Restore additional PCI registers + */ + pci_write_config_dword(ahd->dev_softc, DEVCONFIG, + ahd->suspend_state.pci_state.devconfig); + pci_write_config_byte(ahd->dev_softc, PCIR_COMMAND, + ahd->suspend_state.pci_state.command); + pci_write_config_byte(ahd->dev_softc, CSIZE_LATTIME, + ahd->suspend_state.pci_state.csize_lattime); + + /* + * Restart the HBA + */ + ahd_reset(ahd, /*reinit*/TRUE); + ahd_intr_enable(ahd, TRUE); + ahd_restart(ahd); + + return 0; +} +#endif /* CONFIG_PM */ static void ahd_linux_pci_dev_remove(struct pci_dev *pdev) @@ -195,6 +255,17 @@ ahd_linux_pci_dev_probe(struct pci_dev *pdev, const struct pci_device_id *ent) return (0); } +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 +}; + int ahd_linux_pci_init(void) { @@ -276,7 +347,7 @@ ahd_pci_map_registers(struct ahd_softc *ahd) /* * If its allowed, we prefer memory mapped access. */ - command = ahd_pci_read_config(ahd->dev_softc, PCIR_COMMAND, 4); + pci_read_config_dword(ahd->dev_softc, PCIR_COMMAND, &command); command &= ~(PCIM_CMD_PORTEN|PCIM_CMD_MEMEN); base = 0; maddr = NULL; @@ -287,8 +358,8 @@ ahd_pci_map_registers(struct ahd_softc *ahd) ahd->bshs[0].maddr = maddr; ahd->tags[1] = BUS_SPACE_MEMIO; ahd->bshs[1].maddr = maddr + 0x100; - ahd_pci_write_config(ahd->dev_softc, PCIR_COMMAND, - command | PCIM_CMD_MEMEN, 4); + pci_write_config_dword(ahd->dev_softc, PCIR_COMMAND, + command | PCIM_CMD_MEMEN); if (ahd_pci_test_register_access(ahd) != 0) { @@ -332,7 +403,7 @@ ahd_pci_map_registers(struct ahd_softc *ahd) base, base2); } } - ahd_pci_write_config(ahd->dev_softc, PCIR_COMMAND, command, 4); + pci_write_config_dword(ahd->dev_softc, PCIR_COMMAND, command); return (error); } diff --git a/drivers/scsi/aic7xxx/aic79xx_pci.c b/drivers/scsi/aic7xxx/aic79xx_pci.c index 0bada00..c8617e0 100644 --- a/drivers/scsi/aic7xxx/aic79xx_pci.c +++ b/drivers/scsi/aic7xxx/aic79xx_pci.c @@ -209,12 +209,6 @@ static struct ahd_pci_identity ahd_pci_ident_table [] = static const u_int ahd_num_pci_devs = ARRAY_SIZE(ahd_pci_ident_table); -#define DEVCONFIG 0x40 -#define PCIXINITPAT 0x0000E000ul -#define PCIXINIT_PCI33_66 0x0000E000ul -#define PCIXINIT_PCIX50_66 0x0000C000ul -#define PCIXINIT_PCIX66_100 0x0000A000ul -#define PCIXINIT_PCIX100_133 0x00008000ul #define PCI_BUS_MODES_INDEX(devconfig) \ (((devconfig) & PCIXINITPAT) >> 13) static const char *pci_bus_modes[] = @@ -229,24 +223,6 @@ static const char *pci_bus_modes[] = "PCI 33 or 66Mhz" }; -#define TESTMODE 0x00000800ul -#define IRDY_RST 0x00000200ul -#define FRAME_RST 0x00000100ul -#define PCI64BIT 0x00000080ul -#define MRDCEN 0x00000040ul -#define ENDIANSEL 0x00000020ul -#define MIXQWENDIANEN 0x00000008ul -#define DACEN 0x00000004ul -#define STPWLEVEL 0x00000002ul -#define QWENDIANSEL 0x00000001ul - -#define DEVCONFIG1 0x44 -#define PREQDIS 0x01 - -#define CSIZE_LATTIME 0x0c -#define CACHESIZE 0x000000fful -#define LATTIME 0x0000ff00ul - static int ahd_check_extport(struct ahd_softc *ahd); static void ahd_configure_termination(struct ahd_softc *ahd, u_int adapter_control); diff --git a/drivers/scsi/aic7xxx/aic79xx_pci.h b/drivers/scsi/aic7xxx/aic79xx_pci.h index 16b7c70..67ea5ae 100644 --- a/drivers/scsi/aic7xxx/aic79xx_pci.h +++ b/drivers/scsi/aic7xxx/aic79xx_pci.h @@ -69,4 +69,29 @@ #define ID_AHA_39320D_HP 0x8011900500AC0E11ull #define ID_AHA_39320D_B_HP 0x801C900500AC0E11ull +#define DEVCONFIG 0x40 +#define PCIXINITPAT 0x0000E000ul +#define PCIXINIT_PCI33_66 0x0000E000ul +#define PCIXINIT_PCIX50_66 0x0000C000ul +#define PCIXINIT_PCIX66_100 0x0000A000ul +#define PCIXINIT_PCIX100_133 0x00008000ul + +#define TESTMODE 0x00000800ul +#define IRDY_RST 0x00000200ul +#define FRAME_RST 0x00000100ul +#define PCI64BIT 0x00000080ul +#define MRDCEN 0x00000040ul +#define ENDIANSEL 0x00000020ul +#define MIXQWENDIANEN 0x00000008ul +#define DACEN 0x00000004ul +#define STPWLEVEL 0x00000002ul +#define QWENDIANSEL 0x00000001ul + +#define DEVCONFIG1 0x44 +#define PREQDIS 0x01 + +#define CSIZE_LATTIME 0x0c +#define CACHESIZE 0x000000fful +#define LATTIME 0x0000ff00ul + #endif /* _AIC79XX_PCI_H_ */ diff --git a/drivers/scsi/aic7xxx/aic7xxx.h b/drivers/scsi/aic7xxx/aic7xxx.h index e1bd57b..80ceeaf 100644 --- a/drivers/scsi/aic7xxx/aic7xxx.h +++ b/drivers/scsi/aic7xxx/aic7xxx.h @@ -899,8 +899,6 @@ union ahc_bus_softc { typedef void (*ahc_bus_intr_t)(struct ahc_softc *); typedef int (*ahc_bus_chip_init_t)(struct ahc_softc *); -typedef int (*ahc_bus_suspend_t)(struct ahc_softc *); -typedef int (*ahc_bus_resume_t)(struct ahc_softc *); typedef void ahc_callback_t (void *); struct ahc_softc { @@ -962,16 +960,6 @@ struct ahc_softc { ahc_bus_chip_init_t bus_chip_init; /* - * Bus specific suspend routine. - */ - ahc_bus_suspend_t bus_suspend; - - /* - * Bus specific resume routine. - */ - ahc_bus_resume_t bus_resume; - - /* * Target mode related state kept on a per enabled lun basis. * Targets that are not enabled will have null entries. * As an initiator, we keep one target entry for our initiator @@ -1153,6 +1141,7 @@ struct ahc_pci_identity *ahc_find_pci_device(ahc_dev_softc_t); int ahc_pci_config(struct ahc_softc *, struct ahc_pci_identity *); int ahc_pci_test_register_access(struct ahc_softc *); +void ahc_pci_resume(struct ahc_softc *ahc); /*************************** EISA/VL Front End ********************************/ struct aic7770_identity *aic7770_find_device(uint32_t); @@ -1179,14 +1168,13 @@ int ahc_chip_init(struct ahc_softc *ahc); int ahc_init(struct ahc_softc *ahc); void ahc_intr_enable(struct ahc_softc *ahc, int enable); void ahc_pause_and_flushwork(struct ahc_softc *ahc); -int ahc_suspend(struct ahc_softc *ahc); -int ahc_resume(struct ahc_softc *ahc); void ahc_set_unit(struct ahc_softc *, int); void ahc_set_name(struct ahc_softc *, char *); void ahc_alloc_scbs(struct ahc_softc *ahc); void ahc_free(struct ahc_softc *ahc); int ahc_reset(struct ahc_softc *ahc, int reinit); -void ahc_shutdown(void *arg); +void ahc_restart(struct ahc_softc *ahc); +void ahc_shutdown(struct ahc_softc *ahc); /*************************** Interrupt Services *******************************/ void ahc_clear_intstat(struct ahc_softc *ahc); diff --git a/drivers/scsi/aic7xxx/aic7xxx_core.c b/drivers/scsi/aic7xxx/aic7xxx_core.c index f350b5e..40f7072 100644 --- a/drivers/scsi/aic7xxx/aic7xxx_core.c +++ b/drivers/scsi/aic7xxx/aic7xxx_core.c @@ -3984,13 +3984,10 @@ ahc_free(struct ahc_softc *ahc) } void -ahc_shutdown(void *arg) +ahc_shutdown(struct ahc_softc *ahc) { - struct ahc_softc *ahc; int i; - ahc = (struct ahc_softc *)arg; - /* This will reset most registers to 0, but not all */ ahc_reset(ahc, /*reinit*/FALSE); ahc_outb(ahc, SCSISEQ, 0); @@ -5078,42 +5075,6 @@ ahc_pause_and_flushwork(struct ahc_softc *ahc) ahc->flags &= ~AHC_ALL_INTERRUPTS; } -int -ahc_suspend(struct ahc_softc *ahc) -{ - - ahc_pause_and_flushwork(ahc); - - if (LIST_FIRST(&ahc->pending_scbs) != NULL) { - ahc_unpause(ahc); - return (EBUSY); - } - -#ifdef AHC_TARGET_MODE - /* - * XXX What about ATIOs that have not yet been serviced? - * Perhaps we should just refuse to be suspended if we - * are acting in a target role. - */ - if (ahc->pending_device != NULL) { - ahc_unpause(ahc); - return (EBUSY); - } -#endif - ahc_shutdown(ahc); - return (0); -} - -int -ahc_resume(struct ahc_softc *ahc) -{ - - ahc_reset(ahc, /*reinit*/TRUE); - ahc_intr_enable(ahc, TRUE); - ahc_restart(ahc); - return (0); -} - /************************** Busy Target Table *********************************/ /* * Return the untagged transaction id for a given target/channel lun. diff --git a/drivers/scsi/aic7xxx/aic7xxx_osm_pci.c b/drivers/scsi/aic7xxx/aic7xxx_osm_pci.c index ea5687d..75b3d5a 100644 --- a/drivers/scsi/aic7xxx/aic7xxx_osm_pci.c +++ b/drivers/scsi/aic7xxx/aic7xxx_osm_pci.c @@ -41,15 +41,7 @@ #include "aic7xxx_osm.h" #include "aic7xxx_pci.h" - -static int ahc_linux_pci_dev_probe(struct pci_dev *pdev, - const struct pci_device_id *ent); -static int ahc_linux_pci_reserve_io_region(struct ahc_softc *ahc, - u_long *base); -static int ahc_linux_pci_reserve_mem_region(struct ahc_softc *ahc, - u_long *bus_addr, - uint8_t __iomem **maddr); -static void ahc_linux_pci_dev_remove(struct pci_dev *pdev); +#include "aic7xxx_inline.h" /* Define the macro locally since it's different for different class of chips. */ @@ -130,12 +122,67 @@ static struct pci_device_id ahc_linux_pci_id_table[] = { MODULE_DEVICE_TABLE(pci, ahc_linux_pci_id_table); -static struct pci_driver aic7xxx_pci_driver = { - .name = "aic7xxx", - .probe = ahc_linux_pci_dev_probe, - .remove = ahc_linux_pci_dev_remove, - .id_table = ahc_linux_pci_id_table -}; +#ifdef CONFIG_PM +static int +ahc_linux_pci_dev_suspend(struct pci_dev *pdev, pm_message_t mesg) +{ + struct ahc_softc *ahc = pci_get_drvdata(pdev); + + ahc_pause_and_flushwork(ahc); + + if (LIST_FIRST(&ahc->pending_scbs) != NULL) { + ahc_unpause(ahc); + return -EBUSY; + } + +#ifdef AHC_TARGET_MODE + /* + * XXX What about ATIOs that have not yet been serviced? + * Perhaps we should just refuse to be suspended if we + * are acting in a target role. + */ + if (ahc->pending_device != NULL) { + ahc_unpause(ahc); + return -EBUSY; + } +#endif + ahc_shutdown(ahc); + + pci_save_state(pdev); + pci_disable_device(pdev); + + if (mesg.event == PM_EVENT_SUSPEND) + pci_set_power_state(pdev, PCI_D3hot); + + return 0; +} + +static int +ahc_linux_pci_dev_resume(struct pci_dev *pdev) +{ + struct ahc_softc *ahc = 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); + + ahc_pci_resume(ahc); + + ahc_reset(ahc, /*reinit*/TRUE); + ahc_intr_enable(ahc, TRUE); + ahc_restart(ahc); + + return rc; +} +#endif /* CONFIG_PM */ static void ahc_linux_pci_dev_remove(struct pci_dev *pdev) @@ -243,6 +290,17 @@ ahc_linux_pci_dev_probe(struct pci_dev *pdev, const struct pci_device_id *ent) return (0); } +static struct pci_driver aic7xxx_pci_driver = { + .name = "aic7xxx", + .probe = ahc_linux_pci_dev_probe, +#ifdef CONFIG_PM + .suspend = ahc_linux_pci_dev_suspend, + .resume = ahc_linux_pci_dev_resume, +#endif + .remove = ahc_linux_pci_dev_remove, + .id_table = ahc_linux_pci_id_table +}; + int ahc_linux_pci_init(void) { diff --git a/drivers/scsi/aic7xxx/aic7xxx_pci.c b/drivers/scsi/aic7xxx/aic7xxx_pci.c index 09c8172..ae35937 100644 --- a/drivers/scsi/aic7xxx/aic7xxx_pci.c +++ b/drivers/scsi/aic7xxx/aic7xxx_pci.c @@ -633,8 +633,6 @@ static void write_brdctl(struct ahc_softc *ahc, uint8_t value); static uint8_t read_brdctl(struct ahc_softc *ahc); static void ahc_pci_intr(struct ahc_softc *ahc); static int ahc_pci_chip_init(struct ahc_softc *ahc); -static int ahc_pci_suspend(struct ahc_softc *ahc); -static int ahc_pci_resume(struct ahc_softc *ahc); static int ahc_9005_subdevinfo_valid(uint16_t device, uint16_t vendor, @@ -791,8 +789,6 @@ ahc_pci_config(struct ahc_softc *ahc, struct ahc_pci_identity *entry) ahc->bus_intr = ahc_pci_intr; ahc->bus_chip_init = ahc_pci_chip_init; - ahc->bus_suspend = ahc_pci_suspend; - ahc->bus_resume = ahc_pci_resume; /* Remeber how the card was setup in case there is no SEEPROM */ if ((ahc_inb(ahc, HCNTRL) & POWRDN) == 0) { @@ -2024,18 +2020,9 @@ ahc_pci_chip_init(struct ahc_softc *ahc) return (ahc_chip_init(ahc)); } -static int -ahc_pci_suspend(struct ahc_softc *ahc) -{ - return (ahc_suspend(ahc)); -} - -static int +void ahc_pci_resume(struct ahc_softc *ahc) { - - pci_set_power_state(ahc->dev_softc, AHC_POWER_STATE_D0); - /* * We assume that the OS has restored our register * mappings, etc. Just update the config space registers @@ -2063,7 +2050,6 @@ ahc_pci_resume(struct ahc_softc *ahc) &sxfrctl1); ahc_release_seeprom(&sd); } - return (ahc_resume(ahc)); } static int ^ permalink raw reply related [flat|nested] 5+ messages in thread
* Re: [PATCH 1/4] aic7xxx: Add suspend/resume support 2007-10-19 12:35 ` Hannes Reinecke @ 2007-10-19 13:02 ` Christoph Hellwig 2007-10-19 13:45 ` Hannes Reinecke 0 siblings, 1 reply; 5+ messages in thread From: Christoph Hellwig @ 2007-10-19 13:02 UTC (permalink / raw) To: Hannes Reinecke; +Cc: Christoph Hellwig, James Bottomley, linux-scsi On Fri, Oct 19, 2007 at 02:35:35PM +0200, Hannes Reinecke wrote: > Christoph Hellwig wrote: > > I think this needs a little restructuring. ahd_pci_suspend/ahd_pci_resume > > should be merged into their callers and use the normal Linux pci accessors, > > and ahd_suspend/ahd_resume are tiny enough to merged into the caller aswell. > > > Yes, partially. ahc_pci_resume() has to stay there as it uses quite some > functions from aic7xxx_pci.c. And I'd rather keep the overall structure > (ie split between linux-specific and generic pci access) for now. > In the long run it should be restructured as we don't do cross-compilation > with ***BSD anymore. Ok.. > Ok. Done. > Updated patch attached. > More to your liking? Much better. There's still some if ((rc = fo())) left, but it's probably not worth to delay the patch further because of that. Just clean it up in a followon patch. ^ permalink raw reply [flat|nested] 5+ messages in thread
* Re: [PATCH 1/4] aic7xxx: Add suspend/resume support 2007-10-19 13:02 ` Christoph Hellwig @ 2007-10-19 13:45 ` Hannes Reinecke 0 siblings, 0 replies; 5+ messages in thread From: Hannes Reinecke @ 2007-10-19 13:45 UTC (permalink / raw) To: Christoph Hellwig; +Cc: James Bottomley, linux-scsi [-- Attachment #1: Type: text/plain, Size: 590 bytes --] Christoph Hellwig wrote: > On Fri, Oct 19, 2007 at 02:35:35PM +0200, Hannes Reinecke wrote: [ .. ] >> Ok. Done. >> Updated patch attached. >> More to your liking? > > Much better. There's still some if ((rc = fo())) left, but it's probably > not worth to delay the patch further because of that. Just clean it up > in a followon patch. > Might as well do it now. Fixed patch attached. Cheers, Hannes -- Dr. Hannes Reinecke zSeries & Storage hare@suse.de +49 911 74053 688 SUSE LINUX Products GmbH, Maxfeldstr. 5, 90409 Nürnberg GF: Markus Rex, HRB 16746 (AG Nürnberg) [-- Attachment #2: 0001-aic7xxx-Add-suspend-resume-support.patch --] [-- Type: text/x-patch, Size: 20409 bytes --] >From 2dc1cdee053846fafc98a819bdad1533ac7c2f04 Mon Sep 17 00:00:00 2001 From: Hannes Reinecke <hare@suse.de> Date: Fri, 19 Oct 2007 09:13:17 +0200 Subject: [PATCH 1/4] 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> --- drivers/scsi/aic7xxx/aic7770.c | 16 ----- drivers/scsi/aic7xxx/aic79xx.h | 9 +++ drivers/scsi/aic7xxx/aic79xx_core.c | 33 +--------- drivers/scsi/aic7xxx/aic79xx_osm_pci.c | 112 ++++++++++++++++++++++++++------ drivers/scsi/aic7xxx/aic79xx_pci.c | 24 ------- drivers/scsi/aic7xxx/aic79xx_pci.h | 25 +++++++ drivers/scsi/aic7xxx/aic7xxx.h | 18 +---- drivers/scsi/aic7xxx/aic7xxx_core.c | 41 +----------- drivers/scsi/aic7xxx/aic7xxx_osm_pci.c | 91 +++++++++++++++++++++----- drivers/scsi/aic7xxx/aic7xxx_pci.c | 16 +---- 10 files changed, 208 insertions(+), 177 deletions(-) diff --git a/drivers/scsi/aic7xxx/aic7770.c b/drivers/scsi/aic7xxx/aic7770.c index c4d1723..6d86a9b 100644 --- a/drivers/scsi/aic7xxx/aic7770.c +++ b/drivers/scsi/aic7xxx/aic7770.c @@ -60,8 +60,6 @@ #define ID_OLV_274xD 0x04907783 /* Olivetti OEM (Differential) */ static int aic7770_chip_init(struct ahc_softc *ahc); -static int aic7770_suspend(struct ahc_softc *ahc); -static int aic7770_resume(struct ahc_softc *ahc); static int aha2840_load_seeprom(struct ahc_softc *ahc); static ahc_device_setup_t ahc_aic7770_VL_setup; static ahc_device_setup_t ahc_aic7770_EISA_setup; @@ -155,8 +153,6 @@ aic7770_config(struct ahc_softc *ahc, struct aic7770_identity *entry, u_int io) return (error); ahc->bus_chip_init = aic7770_chip_init; - ahc->bus_suspend = aic7770_suspend; - ahc->bus_resume = aic7770_resume; error = ahc_reset(ahc, /*reinit*/FALSE); if (error != 0) @@ -272,18 +268,6 @@ aic7770_chip_init(struct ahc_softc *ahc) return (ahc_chip_init(ahc)); } -static int -aic7770_suspend(struct ahc_softc *ahc) -{ - return (ahc_suspend(ahc)); -} - -static int -aic7770_resume(struct ahc_softc *ahc) -{ - return (ahc_resume(ahc)); -} - /* * Read the 284x SEEPROM. */ diff --git a/drivers/scsi/aic7xxx/aic79xx.h b/drivers/scsi/aic7xxx/aic79xx.h index 27adbb2..a96a2ff 100644 --- a/drivers/scsi/aic7xxx/aic79xx.h +++ b/drivers/scsi/aic7xxx/aic79xx.h @@ -1003,8 +1003,15 @@ struct ahd_suspend_channel_state { uint8_t seqctl; }; +struct ahd_suspend_pci_state { + uint32_t devconfig; + uint8_t command; + uint8_t csize_lattime; +}; + struct ahd_suspend_state { struct ahd_suspend_channel_state channel[2]; + struct ahd_suspend_pci_state pci_state; uint8_t optionmode; uint8_t dscommand0; uint8_t dspcistatus; @@ -1343,6 +1350,8 @@ struct ahd_softc *ahd_alloc(void *platform_arg, char *name); int ahd_softc_init(struct ahd_softc *); void ahd_controller_info(struct ahd_softc *ahd, char *buf); int ahd_init(struct ahd_softc *ahd); +void ahd_shutdown(void *arg); +void ahd_restart(struct ahd_softc *ahd); int ahd_default_config(struct ahd_softc *ahd); int ahd_parse_vpddata(struct ahd_softc *ahd, struct vpd_config *vpd); diff --git a/drivers/scsi/aic7xxx/aic79xx_core.c b/drivers/scsi/aic7xxx/aic79xx_core.c index 05f692b..91f6f4f 100644 --- a/drivers/scsi/aic7xxx/aic79xx_core.c +++ b/drivers/scsi/aic7xxx/aic79xx_core.c @@ -255,7 +255,6 @@ static void ahd_freeze_devq(struct ahd_softc *ahd, static void ahd_handle_scb_status(struct ahd_softc *ahd, struct scb *scb); static struct ahd_phase_table_entry* ahd_lookup_phase_entry(int phase); -static void ahd_shutdown(void *arg); static void ahd_update_coalescing_values(struct ahd_softc *ahd, u_int timer, u_int maxcmds, @@ -357,7 +356,7 @@ ahd_complete_scb(struct ahd_softc *ahd, struct scb *scb) /* * Restart the sequencer program from address zero */ -static void +void ahd_restart(struct ahd_softc *ahd) { @@ -5456,7 +5455,7 @@ ahd_free(struct ahd_softc *ahd) return; } -static void +void ahd_shutdown(void *arg) { struct ahd_softc *ahd; @@ -7175,34 +7174,6 @@ ahd_pause_and_flushwork(struct ahd_softc *ahd) ahd->flags &= ~AHD_ALL_INTERRUPTS; } -#if 0 -int -ahd_suspend(struct ahd_softc *ahd) -{ - - ahd_pause_and_flushwork(ahd); - - if (LIST_FIRST(&ahd->pending_scbs) != NULL) { - ahd_unpause(ahd); - return (EBUSY); - } - ahd_shutdown(ahd); - return (0); -} -#endif /* 0 */ - -#if 0 -int -ahd_resume(struct ahd_softc *ahd) -{ - - ahd_reset(ahd, /*reinit*/TRUE); - ahd_intr_enable(ahd, TRUE); - ahd_restart(ahd); - return (0); -} -#endif /* 0 */ - /************************** Busy Target Table *********************************/ /* * Set SCBPTR to the SCB that contains the busy diff --git a/drivers/scsi/aic7xxx/aic79xx_osm_pci.c b/drivers/scsi/aic7xxx/aic79xx_osm_pci.c index c62ce41..8aa6302 100644 --- a/drivers/scsi/aic7xxx/aic79xx_osm_pci.c +++ b/drivers/scsi/aic7xxx/aic79xx_osm_pci.c @@ -43,15 +43,6 @@ #include "aic79xx_inline.h" #include "aic79xx_pci.h" -static int ahd_linux_pci_dev_probe(struct pci_dev *pdev, - const struct pci_device_id *ent); -static int ahd_linux_pci_reserve_io_regions(struct ahd_softc *ahd, - u_long *base, u_long *base2); -static int ahd_linux_pci_reserve_mem_region(struct ahd_softc *ahd, - u_long *bus_addr, - uint8_t __iomem **maddr); -static void ahd_linux_pci_dev_remove(struct pci_dev *pdev); - /* Define the macro locally since it's different for different class of chips. */ #define ID(x) \ @@ -83,12 +74,82 @@ static struct pci_device_id ahd_linux_pci_id_table[] = { MODULE_DEVICE_TABLE(pci, ahd_linux_pci_id_table); -static struct pci_driver aic79xx_pci_driver = { - .name = "aic79xx", - .probe = ahd_linux_pci_dev_probe, - .remove = ahd_linux_pci_dev_remove, - .id_table = ahd_linux_pci_id_table -}; +#ifdef CONFIG_PM +int +ahd_linux_pci_dev_suspend(struct pci_dev *pdev, pm_message_t mesg) +{ + struct ahd_softc *ahd = pci_get_drvdata(pdev); + + /* + * Shutdown the HBA + */ + ahd_pause_and_flushwork(ahd); + + if (LIST_FIRST(&ahd->pending_scbs) != NULL) { + ahd_unpause(ahd); + return -EBUSY; + } + + ahd_shutdown(ahd); + + /* + * Save chip register configuration data for chip resets + * that occur during runtime and resume events. + */ + pci_read_config_dword(ahd->dev_softc, DEVCONFIG, + &ahd->suspend_state.pci_state.devconfig); + pci_read_config_byte(ahd->dev_softc, PCIR_COMMAND, + &ahd->suspend_state.pci_state.command); + pci_read_config_byte(ahd->dev_softc, CSIZE_LATTIME, + &ahd->suspend_state.pci_state.csize_lattime); + + pci_save_state(pdev); + pci_disable_device(pdev); + + if (mesg.event == PM_EVENT_SUSPEND) + pci_set_power_state(pdev, PCI_D3hot); + + return 0; +} + +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); + + rc = pci_enable_device(pdev); + if (rc) { + dev_printk(KERN_ERR, &pdev->dev, + "failed to enable device after resume (%d)\n", rc); + return rc; + } + + pci_set_master(pdev); + + /* + * Restore additional PCI registers + */ + pci_write_config_dword(ahd->dev_softc, DEVCONFIG, + ahd->suspend_state.pci_state.devconfig); + pci_write_config_byte(ahd->dev_softc, PCIR_COMMAND, + ahd->suspend_state.pci_state.command); + pci_write_config_byte(ahd->dev_softc, CSIZE_LATTIME, + ahd->suspend_state.pci_state.csize_lattime); + + /* + * Restart the HBA + */ + ahd_reset(ahd, /*reinit*/TRUE); + ahd_intr_enable(ahd, TRUE); + ahd_restart(ahd); + + return 0; +} +#endif /* CONFIG_PM */ static void ahd_linux_pci_dev_remove(struct pci_dev *pdev) @@ -97,7 +158,7 @@ ahd_linux_pci_dev_remove(struct pci_dev *pdev) u_long s; if (ahd->platform_data && ahd->platform_data->host) - scsi_remove_host(ahd->platform_data->host); + scsi_remove_host(ahd->platform_data->host); ahd_lock(ahd, &s); ahd_intr_enable(ahd, FALSE); @@ -195,6 +256,17 @@ ahd_linux_pci_dev_probe(struct pci_dev *pdev, const struct pci_device_id *ent) return (0); } +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 +}; + int ahd_linux_pci_init(void) { @@ -276,7 +348,7 @@ ahd_pci_map_registers(struct ahd_softc *ahd) /* * If its allowed, we prefer memory mapped access. */ - command = ahd_pci_read_config(ahd->dev_softc, PCIR_COMMAND, 4); + pci_read_config_dword(ahd->dev_softc, PCIR_COMMAND, &command); command &= ~(PCIM_CMD_PORTEN|PCIM_CMD_MEMEN); base = 0; maddr = NULL; @@ -287,8 +359,8 @@ ahd_pci_map_registers(struct ahd_softc *ahd) ahd->bshs[0].maddr = maddr; ahd->tags[1] = BUS_SPACE_MEMIO; ahd->bshs[1].maddr = maddr + 0x100; - ahd_pci_write_config(ahd->dev_softc, PCIR_COMMAND, - command | PCIM_CMD_MEMEN, 4); + pci_write_config_dword(ahd->dev_softc, PCIR_COMMAND, + command | PCIM_CMD_MEMEN); if (ahd_pci_test_register_access(ahd) != 0) { @@ -332,7 +404,7 @@ ahd_pci_map_registers(struct ahd_softc *ahd) base, base2); } } - ahd_pci_write_config(ahd->dev_softc, PCIR_COMMAND, command, 4); + pci_write_config_dword(ahd->dev_softc, PCIR_COMMAND, command); return (error); } diff --git a/drivers/scsi/aic7xxx/aic79xx_pci.c b/drivers/scsi/aic7xxx/aic79xx_pci.c index 0bada00..c8617e0 100644 --- a/drivers/scsi/aic7xxx/aic79xx_pci.c +++ b/drivers/scsi/aic7xxx/aic79xx_pci.c @@ -209,12 +209,6 @@ static struct ahd_pci_identity ahd_pci_ident_table [] = static const u_int ahd_num_pci_devs = ARRAY_SIZE(ahd_pci_ident_table); -#define DEVCONFIG 0x40 -#define PCIXINITPAT 0x0000E000ul -#define PCIXINIT_PCI33_66 0x0000E000ul -#define PCIXINIT_PCIX50_66 0x0000C000ul -#define PCIXINIT_PCIX66_100 0x0000A000ul -#define PCIXINIT_PCIX100_133 0x00008000ul #define PCI_BUS_MODES_INDEX(devconfig) \ (((devconfig) & PCIXINITPAT) >> 13) static const char *pci_bus_modes[] = @@ -229,24 +223,6 @@ static const char *pci_bus_modes[] = "PCI 33 or 66Mhz" }; -#define TESTMODE 0x00000800ul -#define IRDY_RST 0x00000200ul -#define FRAME_RST 0x00000100ul -#define PCI64BIT 0x00000080ul -#define MRDCEN 0x00000040ul -#define ENDIANSEL 0x00000020ul -#define MIXQWENDIANEN 0x00000008ul -#define DACEN 0x00000004ul -#define STPWLEVEL 0x00000002ul -#define QWENDIANSEL 0x00000001ul - -#define DEVCONFIG1 0x44 -#define PREQDIS 0x01 - -#define CSIZE_LATTIME 0x0c -#define CACHESIZE 0x000000fful -#define LATTIME 0x0000ff00ul - static int ahd_check_extport(struct ahd_softc *ahd); static void ahd_configure_termination(struct ahd_softc *ahd, u_int adapter_control); diff --git a/drivers/scsi/aic7xxx/aic79xx_pci.h b/drivers/scsi/aic7xxx/aic79xx_pci.h index 16b7c70..67ea5ae 100644 --- a/drivers/scsi/aic7xxx/aic79xx_pci.h +++ b/drivers/scsi/aic7xxx/aic79xx_pci.h @@ -69,4 +69,29 @@ #define ID_AHA_39320D_HP 0x8011900500AC0E11ull #define ID_AHA_39320D_B_HP 0x801C900500AC0E11ull +#define DEVCONFIG 0x40 +#define PCIXINITPAT 0x0000E000ul +#define PCIXINIT_PCI33_66 0x0000E000ul +#define PCIXINIT_PCIX50_66 0x0000C000ul +#define PCIXINIT_PCIX66_100 0x0000A000ul +#define PCIXINIT_PCIX100_133 0x00008000ul + +#define TESTMODE 0x00000800ul +#define IRDY_RST 0x00000200ul +#define FRAME_RST 0x00000100ul +#define PCI64BIT 0x00000080ul +#define MRDCEN 0x00000040ul +#define ENDIANSEL 0x00000020ul +#define MIXQWENDIANEN 0x00000008ul +#define DACEN 0x00000004ul +#define STPWLEVEL 0x00000002ul +#define QWENDIANSEL 0x00000001ul + +#define DEVCONFIG1 0x44 +#define PREQDIS 0x01 + +#define CSIZE_LATTIME 0x0c +#define CACHESIZE 0x000000fful +#define LATTIME 0x0000ff00ul + #endif /* _AIC79XX_PCI_H_ */ diff --git a/drivers/scsi/aic7xxx/aic7xxx.h b/drivers/scsi/aic7xxx/aic7xxx.h index e1bd57b..80ceeaf 100644 --- a/drivers/scsi/aic7xxx/aic7xxx.h +++ b/drivers/scsi/aic7xxx/aic7xxx.h @@ -899,8 +899,6 @@ union ahc_bus_softc { typedef void (*ahc_bus_intr_t)(struct ahc_softc *); typedef int (*ahc_bus_chip_init_t)(struct ahc_softc *); -typedef int (*ahc_bus_suspend_t)(struct ahc_softc *); -typedef int (*ahc_bus_resume_t)(struct ahc_softc *); typedef void ahc_callback_t (void *); struct ahc_softc { @@ -962,16 +960,6 @@ struct ahc_softc { ahc_bus_chip_init_t bus_chip_init; /* - * Bus specific suspend routine. - */ - ahc_bus_suspend_t bus_suspend; - - /* - * Bus specific resume routine. - */ - ahc_bus_resume_t bus_resume; - - /* * Target mode related state kept on a per enabled lun basis. * Targets that are not enabled will have null entries. * As an initiator, we keep one target entry for our initiator @@ -1153,6 +1141,7 @@ struct ahc_pci_identity *ahc_find_pci_device(ahc_dev_softc_t); int ahc_pci_config(struct ahc_softc *, struct ahc_pci_identity *); int ahc_pci_test_register_access(struct ahc_softc *); +void ahc_pci_resume(struct ahc_softc *ahc); /*************************** EISA/VL Front End ********************************/ struct aic7770_identity *aic7770_find_device(uint32_t); @@ -1179,14 +1168,13 @@ int ahc_chip_init(struct ahc_softc *ahc); int ahc_init(struct ahc_softc *ahc); void ahc_intr_enable(struct ahc_softc *ahc, int enable); void ahc_pause_and_flushwork(struct ahc_softc *ahc); -int ahc_suspend(struct ahc_softc *ahc); -int ahc_resume(struct ahc_softc *ahc); void ahc_set_unit(struct ahc_softc *, int); void ahc_set_name(struct ahc_softc *, char *); void ahc_alloc_scbs(struct ahc_softc *ahc); void ahc_free(struct ahc_softc *ahc); int ahc_reset(struct ahc_softc *ahc, int reinit); -void ahc_shutdown(void *arg); +void ahc_restart(struct ahc_softc *ahc); +void ahc_shutdown(struct ahc_softc *ahc); /*************************** Interrupt Services *******************************/ void ahc_clear_intstat(struct ahc_softc *ahc); diff --git a/drivers/scsi/aic7xxx/aic7xxx_core.c b/drivers/scsi/aic7xxx/aic7xxx_core.c index f350b5e..40f7072 100644 --- a/drivers/scsi/aic7xxx/aic7xxx_core.c +++ b/drivers/scsi/aic7xxx/aic7xxx_core.c @@ -3984,13 +3984,10 @@ ahc_free(struct ahc_softc *ahc) } void -ahc_shutdown(void *arg) +ahc_shutdown(struct ahc_softc *ahc) { - struct ahc_softc *ahc; int i; - ahc = (struct ahc_softc *)arg; - /* This will reset most registers to 0, but not all */ ahc_reset(ahc, /*reinit*/FALSE); ahc_outb(ahc, SCSISEQ, 0); @@ -5078,42 +5075,6 @@ ahc_pause_and_flushwork(struct ahc_softc *ahc) ahc->flags &= ~AHC_ALL_INTERRUPTS; } -int -ahc_suspend(struct ahc_softc *ahc) -{ - - ahc_pause_and_flushwork(ahc); - - if (LIST_FIRST(&ahc->pending_scbs) != NULL) { - ahc_unpause(ahc); - return (EBUSY); - } - -#ifdef AHC_TARGET_MODE - /* - * XXX What about ATIOs that have not yet been serviced? - * Perhaps we should just refuse to be suspended if we - * are acting in a target role. - */ - if (ahc->pending_device != NULL) { - ahc_unpause(ahc); - return (EBUSY); - } -#endif - ahc_shutdown(ahc); - return (0); -} - -int -ahc_resume(struct ahc_softc *ahc) -{ - - ahc_reset(ahc, /*reinit*/TRUE); - ahc_intr_enable(ahc, TRUE); - ahc_restart(ahc); - return (0); -} - /************************** Busy Target Table *********************************/ /* * Return the untagged transaction id for a given target/channel lun. diff --git a/drivers/scsi/aic7xxx/aic7xxx_osm_pci.c b/drivers/scsi/aic7xxx/aic7xxx_osm_pci.c index ea5687d..847485f 100644 --- a/drivers/scsi/aic7xxx/aic7xxx_osm_pci.c +++ b/drivers/scsi/aic7xxx/aic7xxx_osm_pci.c @@ -41,15 +41,7 @@ #include "aic7xxx_osm.h" #include "aic7xxx_pci.h" - -static int ahc_linux_pci_dev_probe(struct pci_dev *pdev, - const struct pci_device_id *ent); -static int ahc_linux_pci_reserve_io_region(struct ahc_softc *ahc, - u_long *base); -static int ahc_linux_pci_reserve_mem_region(struct ahc_softc *ahc, - u_long *bus_addr, - uint8_t __iomem **maddr); -static void ahc_linux_pci_dev_remove(struct pci_dev *pdev); +#include "aic7xxx_inline.h" /* Define the macro locally since it's different for different class of chips. */ @@ -130,12 +122,68 @@ static struct pci_device_id ahc_linux_pci_id_table[] = { MODULE_DEVICE_TABLE(pci, ahc_linux_pci_id_table); -static struct pci_driver aic7xxx_pci_driver = { - .name = "aic7xxx", - .probe = ahc_linux_pci_dev_probe, - .remove = ahc_linux_pci_dev_remove, - .id_table = ahc_linux_pci_id_table -}; +#ifdef CONFIG_PM +static int +ahc_linux_pci_dev_suspend(struct pci_dev *pdev, pm_message_t mesg) +{ + struct ahc_softc *ahc = pci_get_drvdata(pdev); + + ahc_pause_and_flushwork(ahc); + + if (LIST_FIRST(&ahc->pending_scbs) != NULL) { + ahc_unpause(ahc); + return -EBUSY; + } + +#ifdef AHC_TARGET_MODE + /* + * XXX What about ATIOs that have not yet been serviced? + * Perhaps we should just refuse to be suspended if we + * are acting in a target role. + */ + if (ahc->pending_device != NULL) { + ahc_unpause(ahc); + return -EBUSY; + } +#endif + ahc_shutdown(ahc); + + pci_save_state(pdev); + pci_disable_device(pdev); + + if (mesg.event == PM_EVENT_SUSPEND) + pci_set_power_state(pdev, PCI_D3hot); + + return 0; +} + +static int +ahc_linux_pci_dev_resume(struct pci_dev *pdev) +{ + struct ahc_softc *ahc = pci_get_drvdata(pdev); + int rc; + + pci_set_power_state(pdev, PCI_D0); + pci_restore_state(pdev); + + rc = pci_enable_device(pdev); + if (rc) { + dev_printk(KERN_ERR, &pdev->dev, + "failed to enable device after resume (%d)\n", rc); + return rc; + } + + pci_set_master(pdev); + + ahc_pci_resume(ahc); + + ahc_reset(ahc, /*reinit*/TRUE); + ahc_intr_enable(ahc, TRUE); + ahc_restart(ahc); + + return rc; +} +#endif /* CONFIG_PM */ static void ahc_linux_pci_dev_remove(struct pci_dev *pdev) @@ -144,7 +192,7 @@ ahc_linux_pci_dev_remove(struct pci_dev *pdev) u_long s; if (ahc->platform_data && ahc->platform_data->host) - scsi_remove_host(ahc->platform_data->host); + scsi_remove_host(ahc->platform_data->host); ahc_lock(ahc, &s); ahc_intr_enable(ahc, FALSE); @@ -243,6 +291,17 @@ ahc_linux_pci_dev_probe(struct pci_dev *pdev, const struct pci_device_id *ent) return (0); } +static struct pci_driver aic7xxx_pci_driver = { + .name = "aic7xxx", + .probe = ahc_linux_pci_dev_probe, +#ifdef CONFIG_PM + .suspend = ahc_linux_pci_dev_suspend, + .resume = ahc_linux_pci_dev_resume, +#endif + .remove = ahc_linux_pci_dev_remove, + .id_table = ahc_linux_pci_id_table +}; + int ahc_linux_pci_init(void) { diff --git a/drivers/scsi/aic7xxx/aic7xxx_pci.c b/drivers/scsi/aic7xxx/aic7xxx_pci.c index 09c8172..ae35937 100644 --- a/drivers/scsi/aic7xxx/aic7xxx_pci.c +++ b/drivers/scsi/aic7xxx/aic7xxx_pci.c @@ -633,8 +633,6 @@ static void write_brdctl(struct ahc_softc *ahc, uint8_t value); static uint8_t read_brdctl(struct ahc_softc *ahc); static void ahc_pci_intr(struct ahc_softc *ahc); static int ahc_pci_chip_init(struct ahc_softc *ahc); -static int ahc_pci_suspend(struct ahc_softc *ahc); -static int ahc_pci_resume(struct ahc_softc *ahc); static int ahc_9005_subdevinfo_valid(uint16_t device, uint16_t vendor, @@ -791,8 +789,6 @@ ahc_pci_config(struct ahc_softc *ahc, struct ahc_pci_identity *entry) ahc->bus_intr = ahc_pci_intr; ahc->bus_chip_init = ahc_pci_chip_init; - ahc->bus_suspend = ahc_pci_suspend; - ahc->bus_resume = ahc_pci_resume; /* Remeber how the card was setup in case there is no SEEPROM */ if ((ahc_inb(ahc, HCNTRL) & POWRDN) == 0) { @@ -2024,18 +2020,9 @@ ahc_pci_chip_init(struct ahc_softc *ahc) return (ahc_chip_init(ahc)); } -static int -ahc_pci_suspend(struct ahc_softc *ahc) -{ - return (ahc_suspend(ahc)); -} - -static int +void ahc_pci_resume(struct ahc_softc *ahc) { - - pci_set_power_state(ahc->dev_softc, AHC_POWER_STATE_D0); - /* * We assume that the OS has restored our register * mappings, etc. Just update the config space registers @@ -2063,7 +2050,6 @@ ahc_pci_resume(struct ahc_softc *ahc) &sxfrctl1); ahc_release_seeprom(&sd); } - return (ahc_resume(ahc)); } static int ^ permalink raw reply related [flat|nested] 5+ messages in thread
end of thread, other threads:[~2007-10-19 13:45 UTC | newest] Thread overview: 5+ messages (download: mbox.gz follow: Atom feed -- links below jump to the message on this page -- 2007-10-19 8:32 [PATCH 1/4] aic7xxx: Add suspend/resume support Hannes Reinecke 2007-10-19 8:44 ` Christoph Hellwig 2007-10-19 12:35 ` Hannes Reinecke 2007-10-19 13:02 ` Christoph Hellwig 2007-10-19 13:45 ` Hannes Reinecke
This is a public inbox, see mirroring instructions for how to clone and mirror all data and code used for this inbox; as well as URLs for NNTP newsgroup(s).