summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorVinayak Pane <vpane@nvidia.com>2012-07-17 19:06:54 -0700
committerSimone Willett <swillett@nvidia.com>2012-08-10 22:49:08 -0700
commit675dfd18c952e6cf5748aaa305086d86b0358582 (patch)
tree13e9cfc3fc7a94e4e8490f944e61d289d1ce3354
parent7c022b1b9bc18c5f2156c67701a0fe382e024a85 (diff)
arm: tegra: xmm: device set to null in unregister
hsic_unregister is being called multiple times during two step enumeration process of xmm. In failure cases when enumeration does not complete properly, kernel panic is seen because of extra unregister-ehci device. Bug 1016593 Change-Id: Ibaeb20ed0dab0e906741fdfad78f7d89a3672f60 Signed-off-by: Vinayak Pane <vpane@nvidia.com> Reviewed-on: http://git-master/r/116626 Reviewed-by: Simone Willett <swillett@nvidia.com> Tested-by: Simone Willett <swillett@nvidia.com>
-rw-r--r--arch/arm/mach-tegra/baseband-xmm-power.c9
-rw-r--r--arch/arm/mach-tegra/baseband-xmm-power.h2
-rw-r--r--arch/arm/mach-tegra/baseband-xmm-power2.c2
-rw-r--r--arch/arm/mach-tegra/board-enterprise.c10
-rw-r--r--arch/arm/mach-tegra/include/mach/tegra-bb-power.h2
-rw-r--r--drivers/misc/tegra-baseband/bb-m7400.c2
6 files changed, 16 insertions, 11 deletions
diff --git a/arch/arm/mach-tegra/baseband-xmm-power.c b/arch/arm/mach-tegra/baseband-xmm-power.c
index f85d6e6c48b6..5a7cecde526b 100644
--- a/arch/arm/mach-tegra/baseband-xmm-power.c
+++ b/arch/arm/mach-tegra/baseband-xmm-power.c
@@ -66,7 +66,7 @@ static struct usb_device_id xmm_pm_ids[] = {
.driver_info = 0 },
{}
};
-
+MODULE_DEVICE_TABLE(usb, xmm_pm_ids);
static struct gpio tegra_baseband_gpios[] = {
{ -1, GPIOF_OUT_INIT_LOW, "BB_RSTn" },
@@ -348,11 +348,10 @@ static int xmm_power_off(struct platform_device *device)
/* unregister usb host controller */
if (pdata->hsic_unregister)
- pdata->hsic_unregister(data->hsic_device);
+ pdata->hsic_unregister(&data->hsic_device);
else
pr_err("%s: hsic_unregister is missing\n", __func__);
-
/* set IPC_HSIC_ACTIVE low */
gpio_set_value(pdata->modem.xmm.ipc_hsic_active, 0);
@@ -819,7 +818,7 @@ static void xmm_device_remove_handler(struct usb_device *udev)
if (usbdev == udev) {
pr_info("Remove device %d <%s %s>\n", udev->devnum,
udev->manufacturer, udev->product);
- usbdev = 0;
+ usbdev = NULL;
}
}
@@ -1038,7 +1037,7 @@ static int xmm_power_driver_remove(struct platform_device *device)
/* unregister usb host controller */
if (pdata->hsic_unregister)
- pdata->hsic_unregister(data->hsic_device);
+ pdata->hsic_unregister(&data->hsic_device);
else
pr_err("%s: hsic_unregister is missing\n", __func__);
diff --git a/arch/arm/mach-tegra/baseband-xmm-power.h b/arch/arm/mach-tegra/baseband-xmm-power.h
index 0c8723fe6766..55c81833ba04 100644
--- a/arch/arm/mach-tegra/baseband-xmm-power.h
+++ b/arch/arm/mach-tegra/baseband-xmm-power.h
@@ -41,7 +41,7 @@ enum baseband_type {
struct baseband_power_platform_data {
enum baseband_type baseband_type;
struct platform_device* (*hsic_register)(void);
- void (*hsic_unregister)(struct platform_device *);
+ void (*hsic_unregister)(struct platform_device **);
union {
struct {
int mdm_reset;
diff --git a/arch/arm/mach-tegra/baseband-xmm-power2.c b/arch/arm/mach-tegra/baseband-xmm-power2.c
index 905759dca329..a79cd6fb499f 100644
--- a/arch/arm/mach-tegra/baseband-xmm-power2.c
+++ b/arch/arm/mach-tegra/baseband-xmm-power2.c
@@ -108,7 +108,7 @@ static void xmm_power2_step1(struct work_struct *work)
/* unregister usb host controller */
if (pdata->hsic_unregister)
- pdata->hsic_unregister(data->hsic_device);
+ pdata->hsic_unregister(&data->hsic_device);
else
pr_err("%s: hsic_unregister is missing\n", __func__);
diff --git a/arch/arm/mach-tegra/board-enterprise.c b/arch/arm/mach-tegra/board-enterprise.c
index 46078a82a9b1..d918a1fb3518 100644
--- a/arch/arm/mach-tegra/board-enterprise.c
+++ b/arch/arm/mach-tegra/board-enterprise.c
@@ -832,9 +832,15 @@ error:
return NULL;
}
-void tegra_usb_hsic_host_unregister(struct platform_device *pdev)
+void tegra_usb_hsic_host_unregister(struct platform_device **platdev)
{
- platform_device_unregister(pdev);
+ struct platform_device *pdev = *platdev;
+
+ if (pdev && &pdev->dev) {
+ platform_device_unregister(pdev);
+ *platdev = NULL;
+ } else
+ pr_err("%s: no platform device\n", __func__);
}
static void enterprise_usb_init(void)
diff --git a/arch/arm/mach-tegra/include/mach/tegra-bb-power.h b/arch/arm/mach-tegra/include/mach/tegra-bb-power.h
index e0b7e3de326f..96e36116f04f 100644
--- a/arch/arm/mach-tegra/include/mach/tegra-bb-power.h
+++ b/arch/arm/mach-tegra/include/mach/tegra-bb-power.h
@@ -50,7 +50,7 @@ union tegra_bb_gpio_id {
};
typedef struct platform_device* (*ehci_register_cb)(void);
-typedef void (*ehci_unregister_cb)(struct platform_device *);
+typedef void (*ehci_unregister_cb)(struct platform_device **);
struct tegra_bb_pdata {
union tegra_bb_gpio_id *id;
diff --git a/drivers/misc/tegra-baseband/bb-m7400.c b/drivers/misc/tegra-baseband/bb-m7400.c
index adabefdb100d..edde7d1786ed 100644
--- a/drivers/misc/tegra-baseband/bb-m7400.c
+++ b/drivers/misc/tegra-baseband/bb-m7400.c
@@ -241,7 +241,7 @@ static int m7400_attrib_write(struct device *dev, int value)
} else {
/* Unregister ehci controller */
if (ehci_device != NULL)
- pdata->ehci_unregister(ehci_device);
+ pdata->ehci_unregister(&ehci_device);
/* Signal AP going down */
m7400_apdown_handshake();