diff options
author | Steve Lin <stlin@nvidia.com> | 2012-06-15 14:54:31 -0700 |
---|---|---|
committer | Simone Willett <swillett@nvidia.com> | 2012-06-27 17:29:02 -0700 |
commit | ef6acc75bcf5715d126188a711a70b338d98c028 (patch) | |
tree | a85e848e72d9f72fc037c9f118d50b9f1fd94f8c /arch/arm/mach-tegra/tegra_usb_modem_power.c | |
parent | 025ead78f874daf44daaf5512c77f334ba6d339d (diff) |
arm: tegra: baseband: boost CPU frequency when modem BT3 boots
Boost CPU frequency to ensure the modem core dump can be transfered
before the BT3 watchdog timeout.
Bug 975990
Signed-off-by: Steve Lin <stlin@nvidia.com>
Reviewed-on: http://git-master/r/109325
(cherry picked from commit 028155da1b31742b0133dbad62fe5a6a66f2bf1e)
Change-Id: I9e7960c11521f011bcbd5566bb40fa780723b49f
Reviewed-on: http://git-master/r/104038
Reviewed-by: Uday Raval <uraval@nvidia.com>
Reviewed-by: Automatic_Commit_Validation_User
Tested-by: Steve Lin <stlin@nvidia.com>
GVS: Gerrit_Virtual_Submit
Reviewed-by: Steve Lin <stlin@nvidia.com>
Diffstat (limited to 'arch/arm/mach-tegra/tegra_usb_modem_power.c')
-rw-r--r-- | arch/arm/mach-tegra/tegra_usb_modem_power.c | 44 |
1 files changed, 43 insertions, 1 deletions
diff --git a/arch/arm/mach-tegra/tegra_usb_modem_power.c b/arch/arm/mach-tegra/tegra_usb_modem_power.c index 7590754d0133..bb9495a329a6 100644 --- a/arch/arm/mach-tegra/tegra_usb_modem_power.c +++ b/arch/arm/mach-tegra/tegra_usb_modem_power.c @@ -31,8 +31,12 @@ #include <linux/suspend.h> #include <linux/slab.h> #include <linux/wakelock.h> +#include <linux/pm_qos_params.h> #include <mach/tegra_usb_modem_power.h> +#define BOOST_CPU_FREQ_MIN 1200000 +#define BOOST_CPU_FREQ_TIMEOUT 5000 + #define WAKELOCK_TIMEOUT_FOR_USB_ENUM (HZ * 10) #define WAKELOCK_TIMEOUT_FOR_REMOTE_WAKE (HZ) @@ -50,6 +54,9 @@ struct tegra_usb_modem { struct usb_interface *intf; /* first modem usb interface */ struct workqueue_struct *wq; /* modem workqueue */ struct delayed_work recovery_work; /* modem recovery work */ + struct pm_qos_request_list cpu_boost_req; /* min CPU freq request */ + struct work_struct cpu_boost_work; /* CPU freq boost work */ + struct delayed_work cpu_unboost_work; /* CPU freq unboost work */ const struct tegra_modem_operations *ops; /* modem operations */ unsigned int capability; /* modem capability */ int system_suspend; /* system suspend flag */ @@ -78,6 +85,25 @@ static const struct usb_device_id modem_list[] = { {} }; +static void cpu_freq_unboost(struct work_struct *ws) +{ + struct tegra_usb_modem *modem = container_of(ws, struct tegra_usb_modem, + cpu_unboost_work.work); + + pm_qos_update_request(&modem->cpu_boost_req, PM_QOS_DEFAULT_VALUE); +} + +static void cpu_freq_boost(struct work_struct *ws) +{ + struct tegra_usb_modem *modem = container_of(ws, struct tegra_usb_modem, + cpu_boost_work); + + cancel_delayed_work_sync(&modem->cpu_unboost_work); + pm_qos_update_request(&modem->cpu_boost_req, BOOST_CPU_FREQ_MIN); + queue_delayed_work(modem->wq, &modem->cpu_unboost_work, + msecs_to_jiffies(BOOST_CPU_FREQ_TIMEOUT)); +} + static irqreturn_t tegra_usb_modem_wake_thread(int irq, void *data) { struct tegra_usb_modem *modem = (struct tegra_usb_modem *)data; @@ -121,6 +147,10 @@ static irqreturn_t tegra_usb_modem_boot_thread(int irq, void *data) /* hold wait lock to complete the enumeration */ wake_lock_timeout(&modem->wake_lock, WAKELOCK_TIMEOUT_FOR_USB_ENUM); + /* boost CPU freq */ + if (!work_pending(&modem->cpu_boost_work)) + queue_work(modem->wq, &modem->cpu_boost_work); + /* USB disconnect maybe on going... */ mutex_lock(&modem->lock); if (modem->udev && modem->udev->state != USB_STATE_NOTATTACHED) @@ -413,7 +443,13 @@ static int mdm_init(struct tegra_usb_modem *modem, struct platform_device *pdev) /* create work queue platform_driver_registe */ modem->wq = create_workqueue("tegra_usb_mdm_queue"); - INIT_DELAYED_WORK(&(modem->recovery_work), tegra_usb_modem_recovery); + INIT_DELAYED_WORK(&modem->recovery_work, tegra_usb_modem_recovery); + + INIT_WORK(&modem->cpu_boost_work, cpu_freq_boost); + INIT_DELAYED_WORK(&modem->cpu_unboost_work, cpu_freq_unboost); + + pm_qos_add_request(&modem->cpu_boost_req, PM_QOS_CPU_FREQ_MIN, + PM_QOS_DEFAULT_VALUE); /* request remote wakeup irq from platform data */ ret = mdm_request_wakeable_irq(modem, @@ -510,6 +546,12 @@ static int __exit tegra_usb_modem_remove(struct platform_device *pdev) if (modem->sysfs_file_created) device_remove_file(&pdev->dev, &dev_attr_load_host); + cancel_work_sync(&modem->cpu_boost_work); + cancel_delayed_work_sync(&modem->cpu_unboost_work); + destroy_workqueue(modem->wq); + + pm_qos_remove_request(&modem->cpu_boost_req); + kfree(modem); return 0; } |