Commit 9468613b2bb0a386af563953b613efc6c77bd8c1

Authored by Russell King
Committed by Russell King
1 parent 84b5abe69f

[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>

Showing 3 changed files with 31 additions and 14 deletions Side-by-side Diff

drivers/pcmcia/pxa2xx_base.c
... ... @@ -166,7 +166,7 @@
166 166 }
167 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 171 int ret;
172 172 struct pcmcia_low_level *ops;
173 173  
174 174  
175 175  
176 176  
177 177  
178 178  
179 179  
180 180  
... ... @@ -203,35 +203,52 @@
203 203  
204 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)
209 210 {
210   - struct pcmcia_low_level *ops = dev->platform_data;
  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)
  225 +{
  226 + struct pcmcia_low_level *ops = dev->dev.platform_data;
211 227 int nr = ops ? ops->nr : 0;
212 228  
213 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 235 .probe = pxa2xx_drv_pcmcia_probe,
220   - .remove = soc_common_drv_pcmcia_remove,
221   - .suspend = pcmcia_socket_dev_suspend,
  236 + .remove = pxa2xx_drv_pcmcia_remove,
  237 + .suspend = pxa2xx_drv_pcmcia_suspend,
222 238 .resume = pxa2xx_drv_pcmcia_resume,
223   - .name = "pxa2xx-pcmcia",
224   - .bus = &platform_bus_type,
  239 + .driver = {
  240 + .name = "pxa2xx-pcmcia",
  241 + },
225 242 };
226 243  
227 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 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 254 fs_initcall(pxa2xx_pcmcia_init);
drivers/pcmcia/pxa2xx_base.h
1 1 /* temporary measure */
2   -extern int pxa2xx_drv_pcmcia_probe(struct device *);
  2 +extern int __pxa2xx_drv_pcmcia_probe(struct device *);
drivers/pcmcia/pxa2xx_lubbock.c
... ... @@ -260,7 +260,7 @@
260 260 lubbock_set_misc_wr((1 << 15) | (1 << 14), 0);
261 261  
262 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 266 return ret;