diff options
author | Russell King <rmk@dyn-67.arm.linux.org.uk> | 2006-10-28 17:42:56 -0400 |
---|---|---|
committer | Russell King <rmk+kernel@arm.linux.org.uk> | 2006-10-28 17:42:56 -0400 |
commit | 9468613b2bb0a386af563953b613efc6c77bd8c1 (patch) | |
tree | 2181a22d0d4eca134adc9a091303aa6dabd98e91 | |
parent | 84b5abe69ff600a559e1a1fa29f1edad707d4e2f (diff) |
[ARM] Fix suspend oops caused by PXA2xx PCMCIA driver
The PXA2xx PCMCIA driver was registering a device_driver with the
platform_bus_type. Unfortunately, this causes data outside the
device_driver structure to be dereferenced as if it were a
platform_driver structure, causing an oops. Convert the PXA2xx
core driver to use the proper platform_driver structure.
Signed-off-by: Russell King <rmk+kernel@arm.linux.org.uk>
-rw-r--r-- | drivers/pcmcia/pxa2xx_base.c | 41 | ||||
-rw-r--r-- | drivers/pcmcia/pxa2xx_base.h | 2 | ||||
-rw-r--r-- | drivers/pcmcia/pxa2xx_lubbock.c | 2 |
3 files changed, 31 insertions, 14 deletions
diff --git a/drivers/pcmcia/pxa2xx_base.c b/drivers/pcmcia/pxa2xx_base.c index b3518131ea0d..dca9f8549b32 100644 --- a/drivers/pcmcia/pxa2xx_base.c +++ b/drivers/pcmcia/pxa2xx_base.c | |||
@@ -166,7 +166,7 @@ pxa2xx_pcmcia_frequency_change(struct soc_pcmcia_socket *skt, | |||
166 | } | 166 | } |
167 | #endif | 167 | #endif |
168 | 168 | ||
169 | int pxa2xx_drv_pcmcia_probe(struct device *dev) | 169 | int __pxa2xx_drv_pcmcia_probe(struct device *dev) |
170 | { | 170 | { |
171 | int ret; | 171 | int ret; |
172 | struct pcmcia_low_level *ops; | 172 | struct pcmcia_low_level *ops; |
@@ -203,35 +203,52 @@ int pxa2xx_drv_pcmcia_probe(struct device *dev) | |||
203 | 203 | ||
204 | return ret; | 204 | return ret; |
205 | } | 205 | } |
206 | EXPORT_SYMBOL(pxa2xx_drv_pcmcia_probe); | 206 | EXPORT_SYMBOL(__pxa2xx_drv_pcmcia_probe); |
207 | 207 | ||
208 | static int pxa2xx_drv_pcmcia_resume(struct device *dev) | 208 | |
209 | static int pxa2xx_drv_pcmcia_probe(struct platform_device *dev) | ||
210 | { | ||
211 | return __pxa2xx_drv_pcmcia_probe(&dev->dev); | ||
212 | } | ||
213 | |||
214 | static int pxa2xx_drv_pcmcia_remove(struct platform_device *dev) | ||
215 | { | ||
216 | return soc_common_drv_pcmcia_remove(&dev->dev); | ||
217 | } | ||
218 | |||
219 | static int pxa2xx_drv_pcmcia_suspend(struct platform_device *dev, pm_message_t state) | ||
220 | { | ||
221 | return pcmcia_socket_dev_suspend(&dev->dev, state); | ||
222 | } | ||
223 | |||
224 | static int pxa2xx_drv_pcmcia_resume(struct platform_device *dev) | ||
209 | { | 225 | { |
210 | struct pcmcia_low_level *ops = dev->platform_data; | 226 | struct pcmcia_low_level *ops = dev->dev.platform_data; |
211 | int nr = ops ? ops->nr : 0; | 227 | int nr = ops ? ops->nr : 0; |
212 | 228 | ||
213 | MECR = nr > 1 ? MECR_CIT | MECR_NOS : (nr > 0 ? MECR_CIT : 0); | 229 | MECR = nr > 1 ? MECR_CIT | MECR_NOS : (nr > 0 ? MECR_CIT : 0); |
214 | 230 | ||
215 | return pcmcia_socket_dev_resume(dev); | 231 | return pcmcia_socket_dev_resume(&dev->dev); |
216 | } | 232 | } |
217 | 233 | ||
218 | static struct device_driver pxa2xx_pcmcia_driver = { | 234 | static struct platform_driver pxa2xx_pcmcia_driver = { |
219 | .probe = pxa2xx_drv_pcmcia_probe, | 235 | .probe = pxa2xx_drv_pcmcia_probe, |
220 | .remove = soc_common_drv_pcmcia_remove, | 236 | .remove = pxa2xx_drv_pcmcia_remove, |
221 | .suspend = pcmcia_socket_dev_suspend, | 237 | .suspend = pxa2xx_drv_pcmcia_suspend, |
222 | .resume = pxa2xx_drv_pcmcia_resume, | 238 | .resume = pxa2xx_drv_pcmcia_resume, |
223 | .name = "pxa2xx-pcmcia", | 239 | .driver = { |
224 | .bus = &platform_bus_type, | 240 | .name = "pxa2xx-pcmcia", |
241 | }, | ||
225 | }; | 242 | }; |
226 | 243 | ||
227 | static int __init pxa2xx_pcmcia_init(void) | 244 | static int __init pxa2xx_pcmcia_init(void) |
228 | { | 245 | { |
229 | return driver_register(&pxa2xx_pcmcia_driver); | 246 | return platform_driver_register(&pxa2xx_pcmcia_driver); |
230 | } | 247 | } |
231 | 248 | ||
232 | static void __exit pxa2xx_pcmcia_exit(void) | 249 | static void __exit pxa2xx_pcmcia_exit(void) |
233 | { | 250 | { |
234 | driver_unregister(&pxa2xx_pcmcia_driver); | 251 | platform_driver_unregister(&pxa2xx_pcmcia_driver); |
235 | } | 252 | } |
236 | 253 | ||
237 | fs_initcall(pxa2xx_pcmcia_init); | 254 | fs_initcall(pxa2xx_pcmcia_init); |
diff --git a/drivers/pcmcia/pxa2xx_base.h b/drivers/pcmcia/pxa2xx_base.h index e46cff345d47..235d681652c3 100644 --- a/drivers/pcmcia/pxa2xx_base.h +++ b/drivers/pcmcia/pxa2xx_base.h | |||
@@ -1,3 +1,3 @@ | |||
1 | /* temporary measure */ | 1 | /* temporary measure */ |
2 | extern int pxa2xx_drv_pcmcia_probe(struct device *); | 2 | extern int __pxa2xx_drv_pcmcia_probe(struct device *); |
3 | 3 | ||
diff --git a/drivers/pcmcia/pxa2xx_lubbock.c b/drivers/pcmcia/pxa2xx_lubbock.c index fd1f691c7c2c..a92f11143c43 100644 --- a/drivers/pcmcia/pxa2xx_lubbock.c +++ b/drivers/pcmcia/pxa2xx_lubbock.c | |||
@@ -260,7 +260,7 @@ int __init pcmcia_lubbock_init(struct sa1111_dev *sadev) | |||
260 | lubbock_set_misc_wr((1 << 15) | (1 << 14), 0); | 260 | lubbock_set_misc_wr((1 << 15) | (1 << 14), 0); |
261 | 261 | ||
262 | sadev->dev.platform_data = &lubbock_pcmcia_ops; | 262 | sadev->dev.platform_data = &lubbock_pcmcia_ops; |
263 | ret = pxa2xx_drv_pcmcia_probe(&sadev->dev); | 263 | ret = __pxa2xx_drv_pcmcia_probe(&sadev->dev); |
264 | } | 264 | } |
265 | 265 | ||
266 | return ret; | 266 | return ret; |