diff options
author | Michael Buesch <mb@bu3sch.de> | 2008-03-29 19:10:50 -0400 |
---|---|---|
committer | John W. Linville <linville@tuxdriver.com> | 2008-04-08 15:05:57 -0400 |
commit | 8fe2b65a18e49bfde56a59ed4ab3fc7aa0c2f325 (patch) | |
tree | a813fe635b7a8c248c586de847d1501c4ccaab6b /drivers/ssb/main.c | |
parent | 5100d5ac81b9330dc57e35adbe50923ba6107b8f (diff) |
ssb: Turn suspend/resume upside down
Turn the SSB bus suspend mechanism upside down.
Instead of deciding by an internal reference count when to suspend/resume,
let the parent bus call us in their suspend/resume routine.
Signed-off-by: Michael Buesch <mb@bu3sch.de>
Signed-off-by: John W. Linville <linville@tuxdriver.com>
Diffstat (limited to 'drivers/ssb/main.c')
-rw-r--r-- | drivers/ssb/main.c | 81 |
1 files changed, 34 insertions, 47 deletions
diff --git a/drivers/ssb/main.c b/drivers/ssb/main.c index 2fcfd73b3b6e..c0cbdba07aee 100644 --- a/drivers/ssb/main.c +++ b/drivers/ssb/main.c | |||
@@ -120,35 +120,12 @@ static void ssb_device_put(struct ssb_device *dev) | |||
120 | put_device(dev->dev); | 120 | put_device(dev->dev); |
121 | } | 121 | } |
122 | 122 | ||
123 | static int ssb_bus_resume(struct ssb_bus *bus) | ||
124 | { | ||
125 | int err; | ||
126 | |||
127 | ssb_pci_xtal(bus, SSB_GPIO_XTAL | SSB_GPIO_PLL, 1); | ||
128 | err = ssb_pcmcia_init(bus); | ||
129 | if (err) { | ||
130 | /* No need to disable XTAL, as we don't have one on PCMCIA. */ | ||
131 | return err; | ||
132 | } | ||
133 | ssb_chipco_resume(&bus->chipco); | ||
134 | |||
135 | return 0; | ||
136 | } | ||
137 | |||
138 | static int ssb_device_resume(struct device *dev) | 123 | static int ssb_device_resume(struct device *dev) |
139 | { | 124 | { |
140 | struct ssb_device *ssb_dev = dev_to_ssb_dev(dev); | 125 | struct ssb_device *ssb_dev = dev_to_ssb_dev(dev); |
141 | struct ssb_driver *ssb_drv; | 126 | struct ssb_driver *ssb_drv; |
142 | struct ssb_bus *bus; | ||
143 | int err = 0; | 127 | int err = 0; |
144 | 128 | ||
145 | bus = ssb_dev->bus; | ||
146 | if (bus->suspend_cnt == bus->nr_devices) { | ||
147 | err = ssb_bus_resume(bus); | ||
148 | if (err) | ||
149 | return err; | ||
150 | } | ||
151 | bus->suspend_cnt--; | ||
152 | if (dev->driver) { | 129 | if (dev->driver) { |
153 | ssb_drv = drv_to_ssb_drv(dev->driver); | 130 | ssb_drv = drv_to_ssb_drv(dev->driver); |
154 | if (ssb_drv && ssb_drv->resume) | 131 | if (ssb_drv && ssb_drv->resume) |
@@ -160,27 +137,10 @@ out: | |||
160 | return err; | 137 | return err; |
161 | } | 138 | } |
162 | 139 | ||
163 | static void ssb_bus_suspend(struct ssb_bus *bus, pm_message_t state) | ||
164 | { | ||
165 | ssb_chipco_suspend(&bus->chipco, state); | ||
166 | ssb_pci_xtal(bus, SSB_GPIO_XTAL | SSB_GPIO_PLL, 0); | ||
167 | |||
168 | /* Reset HW state information in memory, so that HW is | ||
169 | * completely reinitialized on resume. */ | ||
170 | bus->mapped_device = NULL; | ||
171 | #ifdef CONFIG_SSB_DRIVER_PCICORE | ||
172 | bus->pcicore.setup_done = 0; | ||
173 | #endif | ||
174 | #ifdef CONFIG_SSB_DEBUG | ||
175 | bus->powered_up = 0; | ||
176 | #endif | ||
177 | } | ||
178 | |||
179 | static int ssb_device_suspend(struct device *dev, pm_message_t state) | 140 | static int ssb_device_suspend(struct device *dev, pm_message_t state) |
180 | { | 141 | { |
181 | struct ssb_device *ssb_dev = dev_to_ssb_dev(dev); | 142 | struct ssb_device *ssb_dev = dev_to_ssb_dev(dev); |
182 | struct ssb_driver *ssb_drv; | 143 | struct ssb_driver *ssb_drv; |
183 | struct ssb_bus *bus; | ||
184 | int err = 0; | 144 | int err = 0; |
185 | 145 | ||
186 | if (dev->driver) { | 146 | if (dev->driver) { |
@@ -190,17 +150,44 @@ static int ssb_device_suspend(struct device *dev, pm_message_t state) | |||
190 | if (err) | 150 | if (err) |
191 | goto out; | 151 | goto out; |
192 | } | 152 | } |
153 | out: | ||
154 | return err; | ||
155 | } | ||
156 | |||
157 | int ssb_bus_resume(struct ssb_bus *bus) | ||
158 | { | ||
159 | int err; | ||
193 | 160 | ||
194 | bus = ssb_dev->bus; | 161 | /* Reset HW state information in memory, so that HW is |
195 | bus->suspend_cnt++; | 162 | * completely reinitialized. */ |
196 | if (bus->suspend_cnt == bus->nr_devices) { | 163 | bus->mapped_device = NULL; |
197 | /* All devices suspended. Shutdown the bus. */ | 164 | #ifdef CONFIG_SSB_DRIVER_PCICORE |
198 | ssb_bus_suspend(bus, state); | 165 | bus->pcicore.setup_done = 0; |
166 | #endif | ||
167 | |||
168 | err = ssb_bus_powerup(bus, 0); | ||
169 | if (err) | ||
170 | return err; | ||
171 | err = ssb_pcmcia_hardware_setup(bus); | ||
172 | if (err) { | ||
173 | ssb_bus_may_powerdown(bus); | ||
174 | return err; | ||
199 | } | 175 | } |
176 | ssb_chipco_resume(&bus->chipco); | ||
177 | ssb_bus_may_powerdown(bus); | ||
200 | 178 | ||
201 | out: | 179 | return 0; |
202 | return err; | 180 | } |
181 | EXPORT_SYMBOL(ssb_bus_resume); | ||
182 | |||
183 | int ssb_bus_suspend(struct ssb_bus *bus) | ||
184 | { | ||
185 | ssb_chipco_suspend(&bus->chipco); | ||
186 | ssb_pci_xtal(bus, SSB_GPIO_XTAL | SSB_GPIO_PLL, 0); | ||
187 | |||
188 | return 0; | ||
203 | } | 189 | } |
190 | EXPORT_SYMBOL(ssb_bus_suspend); | ||
204 | 191 | ||
205 | #ifdef CONFIG_SSB_PCIHOST | 192 | #ifdef CONFIG_SSB_PCIHOST |
206 | int ssb_devices_freeze(struct ssb_bus *bus) | 193 | int ssb_devices_freeze(struct ssb_bus *bus) |