diff options
author | Vinayak Pane <vpane@nvidia.com> | 2012-07-17 19:06:54 -0700 |
---|---|---|
committer | Simone Willett <swillett@nvidia.com> | 2012-08-10 22:49:08 -0700 |
commit | 675dfd18c952e6cf5748aaa305086d86b0358582 (patch) | |
tree | 13e9cfc3fc7a94e4e8490f944e61d289d1ce3354 | |
parent | 7c022b1b9bc18c5f2156c67701a0fe382e024a85 (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.c | 9 | ||||
-rw-r--r-- | arch/arm/mach-tegra/baseband-xmm-power.h | 2 | ||||
-rw-r--r-- | arch/arm/mach-tegra/baseband-xmm-power2.c | 2 | ||||
-rw-r--r-- | arch/arm/mach-tegra/board-enterprise.c | 10 | ||||
-rw-r--r-- | arch/arm/mach-tegra/include/mach/tegra-bb-power.h | 2 | ||||
-rw-r--r-- | drivers/misc/tegra-baseband/bb-m7400.c | 2 |
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(); |