aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorHannes Reinecke <hare@suse.de>2007-10-19 04:32:21 -0400
committerJames Bottomley <jejb@mulgrave.localdomain>2007-10-21 12:10:50 -0400
commitb5720729f58a4a05b0e2c8c61ac3ed3a3e9f94e5 (patch)
tree7f1271417db63a27474d50d3e43e399a5cef4d93
parenteb7a1698d24783dd215cb86a12cadebe9b4e7046 (diff)
[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>
-rw-r--r--drivers/scsi/aic7xxx/aic7770.c16
-rw-r--r--drivers/scsi/aic7xxx/aic79xx.h11
-rw-r--r--drivers/scsi/aic7xxx/aic79xx_core.c7
-rw-r--r--drivers/scsi/aic7xxx/aic79xx_osm_pci.c50
-rw-r--r--drivers/scsi/aic7xxx/aic79xx_pci.c27
-rw-r--r--drivers/scsi/aic7xxx/aic7xxx.h11
-rw-r--r--drivers/scsi/aic7xxx/aic7xxx_osm_pci.c46
-rw-r--r--drivers/scsi/aic7xxx/aic7xxx_pci.c16
8 files changed, 137 insertions, 47 deletions
diff --git a/drivers/scsi/aic7xxx/aic7770.c b/drivers/scsi/aic7xxx/aic7770.c
index c4d17231c828..6d86a9be538f 100644
--- a/drivers/scsi/aic7xxx/aic7770.c
+++ b/drivers/scsi/aic7xxx/aic7770.c
@@ -60,8 +60,6 @@
60#define ID_OLV_274xD 0x04907783 /* Olivetti OEM (Differential) */ 60#define ID_OLV_274xD 0x04907783 /* Olivetti OEM (Differential) */
61 61
62static int aic7770_chip_init(struct ahc_softc *ahc); 62static int aic7770_chip_init(struct ahc_softc *ahc);
63static int aic7770_suspend(struct ahc_softc *ahc);
64static int aic7770_resume(struct ahc_softc *ahc);
65static int aha2840_load_seeprom(struct ahc_softc *ahc); 63static int aha2840_load_seeprom(struct ahc_softc *ahc);
66static ahc_device_setup_t ahc_aic7770_VL_setup; 64static ahc_device_setup_t ahc_aic7770_VL_setup;
67static ahc_device_setup_t ahc_aic7770_EISA_setup; 65static 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)
155 return (error); 153 return (error);
156 154
157 ahc->bus_chip_init = aic7770_chip_init; 155 ahc->bus_chip_init = aic7770_chip_init;
158 ahc->bus_suspend = aic7770_suspend;
159 ahc->bus_resume = aic7770_resume;
160 156
161 error = ahc_reset(ahc, /*reinit*/FALSE); 157 error = ahc_reset(ahc, /*reinit*/FALSE);
162 if (error != 0) 158 if (error != 0)
@@ -272,18 +268,6 @@ aic7770_chip_init(struct ahc_softc *ahc)
272 return (ahc_chip_init(ahc)); 268 return (ahc_chip_init(ahc));
273} 269}
274 270
275static int
276aic7770_suspend(struct ahc_softc *ahc)
277{
278 return (ahc_suspend(ahc));
279}
280
281static int
282aic7770_resume(struct ahc_softc *ahc)
283{
284 return (ahc_resume(ahc));
285}
286
287/* 271/*
288 * Read the 284x SEEPROM. 272 * Read the 284x SEEPROM.
289 */ 273 */
diff --git a/drivers/scsi/aic7xxx/aic79xx.h b/drivers/scsi/aic7xxx/aic79xx.h
index 27adbb294ac1..ce638aa6005a 100644
--- a/drivers/scsi/aic7xxx/aic79xx.h
+++ b/drivers/scsi/aic7xxx/aic79xx.h
@@ -1003,8 +1003,15 @@ struct ahd_suspend_channel_state {
1003 uint8_t seqctl; 1003 uint8_t seqctl;
1004}; 1004};
1005 1005
1006struct ahd_suspend_pci_state {
1007 uint32_t devconfig;
1008 uint8_t command;
1009 uint8_t csize_lattime;
1010};
1011
1006struct ahd_suspend_state { 1012struct ahd_suspend_state {
1007 struct ahd_suspend_channel_state channel[2]; 1013 struct ahd_suspend_channel_state channel[2];
1014 struct ahd_suspend_pci_state pci_state;
1008 uint8_t optionmode; 1015 uint8_t optionmode;
1009 uint8_t dscommand0; 1016 uint8_t dscommand0;
1010 uint8_t dspcistatus; 1017 uint8_t dspcistatus;
@@ -1333,6 +1340,8 @@ struct ahd_pci_identity *ahd_find_pci_device(ahd_dev_softc_t);
1333int ahd_pci_config(struct ahd_softc *, 1340int ahd_pci_config(struct ahd_softc *,
1334 struct ahd_pci_identity *); 1341 struct ahd_pci_identity *);
1335int ahd_pci_test_register_access(struct ahd_softc *); 1342int ahd_pci_test_register_access(struct ahd_softc *);
1343void ahd_pci_suspend(struct ahd_softc *);
1344void ahd_pci_resume(struct ahd_softc *);
1336 1345
1337/************************** SCB and SCB queue management **********************/ 1346/************************** SCB and SCB queue management **********************/
1338void ahd_qinfifo_requeue_tail(struct ahd_softc *ahd, 1347void ahd_qinfifo_requeue_tail(struct ahd_softc *ahd,
@@ -1343,6 +1352,8 @@ struct ahd_softc *ahd_alloc(void *platform_arg, char *name);
1343int ahd_softc_init(struct ahd_softc *); 1352int ahd_softc_init(struct ahd_softc *);
1344void ahd_controller_info(struct ahd_softc *ahd, char *buf); 1353void ahd_controller_info(struct ahd_softc *ahd, char *buf);
1345int ahd_init(struct ahd_softc *ahd); 1354int ahd_init(struct ahd_softc *ahd);
1355int ahd_suspend(struct ahd_softc *ahd);
1356void ahd_resume(struct ahd_softc *ahd);
1346int ahd_default_config(struct ahd_softc *ahd); 1357int ahd_default_config(struct ahd_softc *ahd);
1347int ahd_parse_vpddata(struct ahd_softc *ahd, 1358int ahd_parse_vpddata(struct ahd_softc *ahd,
1348 struct vpd_config *vpd); 1359 struct vpd_config *vpd);
diff --git a/drivers/scsi/aic7xxx/aic79xx_core.c b/drivers/scsi/aic7xxx/aic79xx_core.c
index 05f692bd0adc..a7dd8cdda472 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)
7175 ahd->flags &= ~AHD_ALL_INTERRUPTS; 7175 ahd->flags &= ~AHD_ALL_INTERRUPTS;
7176} 7176}
7177 7177
7178#if 0
7179int 7178int
7180ahd_suspend(struct ahd_softc *ahd) 7179ahd_suspend(struct ahd_softc *ahd)
7181{ 7180{
@@ -7189,19 +7188,15 @@ ahd_suspend(struct ahd_softc *ahd)
7189 ahd_shutdown(ahd); 7188 ahd_shutdown(ahd);
7190 return (0); 7189 return (0);
7191} 7190}
7192#endif /* 0 */
7193 7191
7194#if 0 7192void
7195int
7196ahd_resume(struct ahd_softc *ahd) 7193ahd_resume(struct ahd_softc *ahd)
7197{ 7194{
7198 7195
7199 ahd_reset(ahd, /*reinit*/TRUE); 7196 ahd_reset(ahd, /*reinit*/TRUE);
7200 ahd_intr_enable(ahd, TRUE); 7197 ahd_intr_enable(ahd, TRUE);
7201 ahd_restart(ahd); 7198 ahd_restart(ahd);
7202 return (0);
7203} 7199}
7204#endif /* 0 */
7205 7200
7206/************************** Busy Target Table *********************************/ 7201/************************** Busy Target Table *********************************/
7207/* 7202/*
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,
50static int ahd_linux_pci_reserve_mem_region(struct ahd_softc *ahd, 50static int ahd_linux_pci_reserve_mem_region(struct ahd_softc *ahd,
51 u_long *bus_addr, 51 u_long *bus_addr,
52 uint8_t __iomem **maddr); 52 uint8_t __iomem **maddr);
53static int ahd_linux_pci_dev_suspend(struct pci_dev *pdev, pm_message_t mesg);
54static int ahd_linux_pci_dev_resume(struct pci_dev *pdev);
53static void ahd_linux_pci_dev_remove(struct pci_dev *pdev); 55static void ahd_linux_pci_dev_remove(struct pci_dev *pdev);
54 56
55/* Define the macro locally since it's different for different class of chips. 57/* 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);
86static struct pci_driver aic79xx_pci_driver = { 88static struct pci_driver aic79xx_pci_driver = {
87 .name = "aic79xx", 89 .name = "aic79xx",
88 .probe = ahd_linux_pci_dev_probe, 90 .probe = ahd_linux_pci_dev_probe,
91#ifdef CONFIG_PM
92 .suspend = ahd_linux_pci_dev_suspend,
93 .resume = ahd_linux_pci_dev_resume,
94#endif
89 .remove = ahd_linux_pci_dev_remove, 95 .remove = ahd_linux_pci_dev_remove,
90 .id_table = ahd_linux_pci_id_table 96 .id_table = ahd_linux_pci_id_table
91}; 97};
92 98
99static int
100ahd_linux_pci_dev_suspend(struct pci_dev *pdev, pm_message_t mesg)
101{
102 struct ahd_softc *ahd = pci_get_drvdata(pdev);
103 int rc;
104
105 if ((rc = ahd_suspend(ahd)))
106 return rc;
107
108 ahd_pci_suspend(ahd);
109
110 pci_save_state(pdev);
111 pci_disable_device(pdev);
112
113 if (mesg.event == PM_EVENT_SUSPEND)
114 pci_set_power_state(pdev, PCI_D3hot);
115
116 return rc;
117}
118
119static int
120ahd_linux_pci_dev_resume(struct pci_dev *pdev)
121{
122 struct ahd_softc *ahd = pci_get_drvdata(pdev);
123 int rc;
124
125 pci_set_power_state(pdev, PCI_D0);
126 pci_restore_state(pdev);
127
128 if ((rc = pci_enable_device(pdev))) {
129 dev_printk(KERN_ERR, &pdev->dev,
130 "failed to enable device after resume (%d)\n", rc);
131 return rc;
132 }
133
134 pci_set_master(pdev);
135
136 ahd_pci_resume(ahd);
137
138 ahd_resume(ahd);
139
140 return rc;
141}
142
93static void 143static void
94ahd_linux_pci_dev_remove(struct pci_dev *pdev) 144ahd_linux_pci_dev_remove(struct pci_dev *pdev)
95{ 145{
diff --git a/drivers/scsi/aic7xxx/aic79xx_pci.c b/drivers/scsi/aic7xxx/aic79xx_pci.c
index 0bada0028aa0..7a203a90601a 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)
389 return error; 389 return error;
390} 390}
391 391
392void
393ahd_pci_suspend(struct ahd_softc *ahd)
394{
395 /*
396 * Save chip register configuration data for chip resets
397 * that occur during runtime and resume events.
398 */
399 ahd->suspend_state.pci_state.devconfig =
400 ahd_pci_read_config(ahd->dev_softc, DEVCONFIG, /*bytes*/4);
401 ahd->suspend_state.pci_state.command =
402 ahd_pci_read_config(ahd->dev_softc, PCIR_COMMAND, /*bytes*/1);
403 ahd->suspend_state.pci_state.csize_lattime =
404 ahd_pci_read_config(ahd->dev_softc, CSIZE_LATTIME, /*bytes*/1);
405
406}
407
408void
409ahd_pci_resume(struct ahd_softc *ahd)
410{
411 ahd_pci_write_config(ahd->dev_softc, DEVCONFIG,
412 ahd->suspend_state.pci_state.devconfig, /*bytes*/4);
413 ahd_pci_write_config(ahd->dev_softc, PCIR_COMMAND,
414 ahd->suspend_state.pci_state.command, /*bytes*/1);
415 ahd_pci_write_config(ahd->dev_softc, CSIZE_LATTIME,
416 ahd->suspend_state.pci_state.csize_lattime, /*bytes*/1);
417}
418
392/* 419/*
393 * Perform some simple tests that should catch situations where 420 * Perform some simple tests that should catch situations where
394 * our registers are invalidly mapped. 421 * our registers are invalidly mapped.
diff --git a/drivers/scsi/aic7xxx/aic7xxx.h b/drivers/scsi/aic7xxx/aic7xxx.h
index e1bd57b9f23d..3d4e42d90452 100644
--- a/drivers/scsi/aic7xxx/aic7xxx.h
+++ b/drivers/scsi/aic7xxx/aic7xxx.h
@@ -962,16 +962,6 @@ struct ahc_softc {
962 ahc_bus_chip_init_t bus_chip_init; 962 ahc_bus_chip_init_t bus_chip_init;
963 963
964 /* 964 /*
965 * Bus specific suspend routine.
966 */
967 ahc_bus_suspend_t bus_suspend;
968
969 /*
970 * Bus specific resume routine.
971 */
972 ahc_bus_resume_t bus_resume;
973
974 /*
975 * Target mode related state kept on a per enabled lun basis. 965 * Target mode related state kept on a per enabled lun basis.
976 * Targets that are not enabled will have null entries. 966 * Targets that are not enabled will have null entries.
977 * As an initiator, we keep one target entry for our initiator 967 * 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);
1153int ahc_pci_config(struct ahc_softc *, 1143int ahc_pci_config(struct ahc_softc *,
1154 struct ahc_pci_identity *); 1144 struct ahc_pci_identity *);
1155int ahc_pci_test_register_access(struct ahc_softc *); 1145int ahc_pci_test_register_access(struct ahc_softc *);
1146void ahc_pci_resume(struct ahc_softc *ahc);
1156 1147
1157/*************************** EISA/VL Front End ********************************/ 1148/*************************** EISA/VL Front End ********************************/
1158struct aic7770_identity *aic7770_find_device(uint32_t); 1149struct 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 ea5687df732d..4488946cff2e 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,
49static int ahc_linux_pci_reserve_mem_region(struct ahc_softc *ahc, 49static int ahc_linux_pci_reserve_mem_region(struct ahc_softc *ahc,
50 u_long *bus_addr, 50 u_long *bus_addr,
51 uint8_t __iomem **maddr); 51 uint8_t __iomem **maddr);
52static int ahc_linux_pci_dev_suspend(struct pci_dev *pdev, pm_message_t mesg);
53static int ahc_linux_pci_dev_resume(struct pci_dev *pdev);
52static void ahc_linux_pci_dev_remove(struct pci_dev *pdev); 54static void ahc_linux_pci_dev_remove(struct pci_dev *pdev);
53 55
54/* Define the macro locally since it's different for different class of chips. 56/* 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);
133static struct pci_driver aic7xxx_pci_driver = { 135static struct pci_driver aic7xxx_pci_driver = {
134 .name = "aic7xxx", 136 .name = "aic7xxx",
135 .probe = ahc_linux_pci_dev_probe, 137 .probe = ahc_linux_pci_dev_probe,
138#ifdef CONFIG_PM
139 .suspend = ahc_linux_pci_dev_suspend,
140 .resume = ahc_linux_pci_dev_resume,
141#endif
136 .remove = ahc_linux_pci_dev_remove, 142 .remove = ahc_linux_pci_dev_remove,
137 .id_table = ahc_linux_pci_id_table 143 .id_table = ahc_linux_pci_id_table
138}; 144};
139 145
146static int
147ahc_linux_pci_dev_suspend(struct pci_dev *pdev, pm_message_t mesg)
148{
149 struct ahc_softc *ahc = pci_get_drvdata(pdev);
150 int rc;
151
152 if ((rc = ahc_suspend(ahc)))
153 return rc;
154
155 pci_save_state(pdev);
156 pci_disable_device(pdev);
157
158 if (mesg.event == PM_EVENT_SUSPEND)
159 pci_set_power_state(pdev, PCI_D3hot);
160
161 return rc;
162}
163
164static int
165ahc_linux_pci_dev_resume(struct pci_dev *pdev)
166{
167 struct ahc_softc *ahc = pci_get_drvdata(pdev);
168 int rc;
169
170 pci_set_power_state(pdev, PCI_D0);
171 pci_restore_state(pdev);
172
173 if ((rc = pci_enable_device(pdev))) {
174 dev_printk(KERN_ERR, &pdev->dev,
175 "failed to enable device after resume (%d)\n", rc);
176 return rc;
177 }
178
179 pci_set_master(pdev);
180
181 ahc_pci_resume(ahc);
182
183 return (ahc_resume(ahc));
184}
185
140static void 186static void
141ahc_linux_pci_dev_remove(struct pci_dev *pdev) 187ahc_linux_pci_dev_remove(struct pci_dev *pdev)
142{ 188{
diff --git a/drivers/scsi/aic7xxx/aic7xxx_pci.c b/drivers/scsi/aic7xxx/aic7xxx_pci.c
index 09c8172c9e5e..ae35937b8055 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);
633static uint8_t read_brdctl(struct ahc_softc *ahc); 633static uint8_t read_brdctl(struct ahc_softc *ahc);
634static void ahc_pci_intr(struct ahc_softc *ahc); 634static void ahc_pci_intr(struct ahc_softc *ahc);
635static int ahc_pci_chip_init(struct ahc_softc *ahc); 635static int ahc_pci_chip_init(struct ahc_softc *ahc);
636static int ahc_pci_suspend(struct ahc_softc *ahc);
637static int ahc_pci_resume(struct ahc_softc *ahc);
638 636
639static int 637static int
640ahc_9005_subdevinfo_valid(uint16_t device, uint16_t vendor, 638ahc_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)
791 789
792 ahc->bus_intr = ahc_pci_intr; 790 ahc->bus_intr = ahc_pci_intr;
793 ahc->bus_chip_init = ahc_pci_chip_init; 791 ahc->bus_chip_init = ahc_pci_chip_init;
794 ahc->bus_suspend = ahc_pci_suspend;
795 ahc->bus_resume = ahc_pci_resume;
796 792
797 /* Remeber how the card was setup in case there is no SEEPROM */ 793 /* Remeber how the card was setup in case there is no SEEPROM */
798 if ((ahc_inb(ahc, HCNTRL) & POWRDN) == 0) { 794 if ((ahc_inb(ahc, HCNTRL) & POWRDN) == 0) {
@@ -2024,18 +2020,9 @@ ahc_pci_chip_init(struct ahc_softc *ahc)
2024 return (ahc_chip_init(ahc)); 2020 return (ahc_chip_init(ahc));
2025} 2021}
2026 2022
2027static int 2023void
2028ahc_pci_suspend(struct ahc_softc *ahc)
2029{
2030 return (ahc_suspend(ahc));
2031}
2032
2033static int
2034ahc_pci_resume(struct ahc_softc *ahc) 2024ahc_pci_resume(struct ahc_softc *ahc)
2035{ 2025{
2036
2037 pci_set_power_state(ahc->dev_softc, AHC_POWER_STATE_D0);
2038
2039 /* 2026 /*
2040 * We assume that the OS has restored our register 2027 * We assume that the OS has restored our register
2041 * mappings, etc. Just update the config space registers 2028 * mappings, etc. Just update the config space registers
@@ -2063,7 +2050,6 @@ ahc_pci_resume(struct ahc_softc *ahc)
2063 &sxfrctl1); 2050 &sxfrctl1);
2064 ahc_release_seeprom(&sd); 2051 ahc_release_seeprom(&sd);
2065 } 2052 }
2066 return (ahc_resume(ahc));
2067} 2053}
2068 2054
2069static int 2055static int