From 9468613b2bb0a386af563953b613efc6c77bd8c1 Mon Sep 17 00:00:00 2001
From: Russell King <rmk@dyn-67.arm.linux.org.uk>
Date: Sat, 28 Oct 2006 22:42:56 +0100
Subject: [PATCH] [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>
---
 drivers/pcmcia/pxa2xx_base.c    | 41 +++++++++++++++++++++++----------
 drivers/pcmcia/pxa2xx_base.h    |  2 +-
 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 b3518131ea0d5..dca9f8549b325 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,
 }
 #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);
diff --git a/drivers/pcmcia/pxa2xx_base.h b/drivers/pcmcia/pxa2xx_base.h
index e46cff345d472..235d681652c3f 100644
--- a/drivers/pcmcia/pxa2xx_base.h
+++ b/drivers/pcmcia/pxa2xx_base.h
@@ -1,3 +1,3 @@
 /* temporary measure */
-extern int pxa2xx_drv_pcmcia_probe(struct device *);
+extern int __pxa2xx_drv_pcmcia_probe(struct device *);
 
diff --git a/drivers/pcmcia/pxa2xx_lubbock.c b/drivers/pcmcia/pxa2xx_lubbock.c
index fd1f691c7c2c6..a92f11143c433 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)
 		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;
-- 
GitLab