[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>
This commit is contained in:
Russell King 2006-10-28 22:42:56 +01:00 committed by Russell King
parent 84b5abe69f
commit 9468613b2b
3 changed files with 31 additions and 14 deletions

View File

@ -166,7 +166,7 @@ pxa2xx_pcmcia_frequency_change(struct soc_pcmcia_socket *skt,
} }
#endif #endif
int pxa2xx_drv_pcmcia_probe(struct device *dev) int __pxa2xx_drv_pcmcia_probe(struct device *dev)
{ {
int ret; int ret;
struct pcmcia_low_level *ops; struct pcmcia_low_level *ops;
@ -203,35 +203,52 @@ int pxa2xx_drv_pcmcia_probe(struct device *dev)
return ret; return ret;
} }
EXPORT_SYMBOL(pxa2xx_drv_pcmcia_probe); EXPORT_SYMBOL(__pxa2xx_drv_pcmcia_probe);
static int pxa2xx_drv_pcmcia_resume(struct device *dev)
static int pxa2xx_drv_pcmcia_probe(struct platform_device *dev)
{ {
struct pcmcia_low_level *ops = dev->platform_data; return __pxa2xx_drv_pcmcia_probe(&dev->dev);
}
static int pxa2xx_drv_pcmcia_remove(struct platform_device *dev)
{
return soc_common_drv_pcmcia_remove(&dev->dev);
}
static int pxa2xx_drv_pcmcia_suspend(struct platform_device *dev, pm_message_t state)
{
return pcmcia_socket_dev_suspend(&dev->dev, state);
}
static int pxa2xx_drv_pcmcia_resume(struct platform_device *dev)
{
struct pcmcia_low_level *ops = dev->dev.platform_data;
int nr = ops ? ops->nr : 0; int nr = ops ? ops->nr : 0;
MECR = nr > 1 ? MECR_CIT | MECR_NOS : (nr > 0 ? MECR_CIT : 0); MECR = nr > 1 ? MECR_CIT | MECR_NOS : (nr > 0 ? MECR_CIT : 0);
return pcmcia_socket_dev_resume(dev); return pcmcia_socket_dev_resume(&dev->dev);
} }
static struct device_driver pxa2xx_pcmcia_driver = { static struct platform_driver pxa2xx_pcmcia_driver = {
.probe = pxa2xx_drv_pcmcia_probe, .probe = pxa2xx_drv_pcmcia_probe,
.remove = soc_common_drv_pcmcia_remove, .remove = pxa2xx_drv_pcmcia_remove,
.suspend = pcmcia_socket_dev_suspend, .suspend = pxa2xx_drv_pcmcia_suspend,
.resume = pxa2xx_drv_pcmcia_resume, .resume = pxa2xx_drv_pcmcia_resume,
.name = "pxa2xx-pcmcia", .driver = {
.bus = &platform_bus_type, .name = "pxa2xx-pcmcia",
},
}; };
static int __init pxa2xx_pcmcia_init(void) static int __init pxa2xx_pcmcia_init(void)
{ {
return driver_register(&pxa2xx_pcmcia_driver); return platform_driver_register(&pxa2xx_pcmcia_driver);
} }
static void __exit pxa2xx_pcmcia_exit(void) static void __exit pxa2xx_pcmcia_exit(void)
{ {
driver_unregister(&pxa2xx_pcmcia_driver); platform_driver_unregister(&pxa2xx_pcmcia_driver);
} }
fs_initcall(pxa2xx_pcmcia_init); fs_initcall(pxa2xx_pcmcia_init);

View File

@ -1,3 +1,3 @@
/* temporary measure */ /* temporary measure */
extern int pxa2xx_drv_pcmcia_probe(struct device *); extern int __pxa2xx_drv_pcmcia_probe(struct device *);

View File

@ -260,7 +260,7 @@ int __init pcmcia_lubbock_init(struct sa1111_dev *sadev)
lubbock_set_misc_wr((1 << 15) | (1 << 14), 0); lubbock_set_misc_wr((1 << 15) | (1 << 14), 0);
sadev->dev.platform_data = &lubbock_pcmcia_ops; sadev->dev.platform_data = &lubbock_pcmcia_ops;
ret = pxa2xx_drv_pcmcia_probe(&sadev->dev); ret = __pxa2xx_drv_pcmcia_probe(&sadev->dev);
} }
return ret; return ret;