[ARM] Fix suspend oops caused by PXA2xx PCMCIA driver
authorRussell King <rmk@dyn-67.arm.linux.org.uk>
Sat, 28 Oct 2006 21:42:56 +0000 (22:42 +0100)
committerRussell King <rmk+kernel@arm.linux.org.uk>
Sat, 28 Oct 2006 21:42:56 +0000 (22:42 +0100)
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>
drivers/pcmcia/pxa2xx_base.c
drivers/pcmcia/pxa2xx_base.h
drivers/pcmcia/pxa2xx_lubbock.c

index b351813..dca9f85 100644 (file)
@@ -166,7 +166,7 @@ pxa2xx_pcmcia_frequency_change(struct soc_pcmcia_socket *skt,
 }
 #endif
 
-int pxa2xx_drv_pcmcia_probe(struct device *dev)
+int __pxa2xx_drv_pcmcia_probe(struct device *dev)
 {
        int ret;
        struct pcmcia_low_level *ops;
@@ -203,35 +203,52 @@ int pxa2xx_drv_pcmcia_probe(struct device *dev)
 
        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)
+{
+       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->platform_data;
+       struct pcmcia_low_level *ops = dev->dev.platform_data;
        int nr = ops ? ops->nr : 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,
-       .remove         = soc_common_drv_pcmcia_remove,
-       .suspend        = pcmcia_socket_dev_suspend,
+       .remove         = pxa2xx_drv_pcmcia_remove,
+       .suspend        = pxa2xx_drv_pcmcia_suspend,
        .resume         = pxa2xx_drv_pcmcia_resume,
-       .name           = "pxa2xx-pcmcia",
-       .bus            = &platform_bus_type,
+       .driver         = {
+               .name   = "pxa2xx-pcmcia",
+       },
 };
 
 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)
 {
-       driver_unregister(&pxa2xx_pcmcia_driver);
+       platform_driver_unregister(&pxa2xx_pcmcia_driver);
 }
 
 fs_initcall(pxa2xx_pcmcia_init);
index e46cff3..235d681 100644 (file)
@@ -1,3 +1,3 @@
 /* temporary measure */
-extern int pxa2xx_drv_pcmcia_probe(struct device *);
+extern int __pxa2xx_drv_pcmcia_probe(struct device *);
 
index fd1f691..a92f111 100644 (file)
@@ -260,7 +260,7 @@ int __init pcmcia_lubbock_init(struct sa1111_dev *sadev)
                lubbock_set_misc_wr((1 << 15) | (1 << 14), 0);
 
                sadev->dev.platform_data = &lubbock_pcmcia_ops;
-               ret = pxa2xx_drv_pcmcia_probe(&sadev->dev);
+               ret = __pxa2xx_drv_pcmcia_probe(&sadev->dev);
        }
 
        return ret;