summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorvjagadish <vjagadish@nvidia.com>2011-09-30 12:45:48 +0530
committerRohan Somvanshi <rsomvanshi@nvidia.com>2011-10-11 07:10:34 -0700
commitebe88906855200ce846059e80b722d1badced378 (patch)
treefbb4489d67446b2fa2157a0d99dc190b3f2668a0
parent7304266897a867abd479149df8aaa22c467fd1e7 (diff)
usb: host: tegra: invalid context error on insertion of USB Drive
kernel mutexes may not be used in hardware or software interrupt contexts such as tasklets and timers. Bug 876433 Reviewed-on: http://git-master/r/53734 (cherry picked from commit 17f7d52511d38e98c7305319818f62c641d42c0e) Change-Id: I87f3918d3772100e255185af2236ccdabb97fe85 Reviewed-on: http://git-master/r/56938 Reviewed-by: Suresh Mangipudi <smangipudi@nvidia.com> Tested-by: Suresh Mangipudi <smangipudi@nvidia.com> Reviewed-by: Venkat Moganty <vmoganty@nvidia.com>
-rw-r--r--drivers/usb/host/ehci-tegra.c20
1 files changed, 16 insertions, 4 deletions
diff --git a/drivers/usb/host/ehci-tegra.c b/drivers/usb/host/ehci-tegra.c
index 2ee41aa81124..fcce552769ba 100644
--- a/drivers/usb/host/ehci-tegra.c
+++ b/drivers/usb/host/ehci-tegra.c
@@ -70,6 +70,7 @@ struct tegra_ehci_hcd {
struct work_struct clk_timer_work;
struct timer_list clk_timer;
bool clock_enabled;
+ bool timer_event;
int hsic_connect_retries;
struct mutex tegra_ehci_hcd_mutex;
};
@@ -838,11 +839,10 @@ void clk_timer_callback(unsigned long data)
unsigned long flags;
if (!timer_pending(&tegra->clk_timer)) {
- clk_disable(tegra->emc_clk);
- clk_disable(tegra->sclk_clk);
spin_lock_irqsave(&tegra->ehci->lock, flags);
- tegra->clock_enabled = 0;
+ tegra->timer_event = 1;
spin_unlock_irqrestore(&tegra->ehci->lock, flags);
+ schedule_work(&tegra->clk_timer_work);
}
}
@@ -851,11 +851,23 @@ static void clk_timer_work_handler(struct work_struct* clk_timer_work) {
struct tegra_ehci_hcd, clk_timer_work);
int ret;
unsigned long flags;
- bool clock_enabled;
+ bool clock_enabled, timer_event;
spin_lock_irqsave(&tegra->ehci->lock, flags);
clock_enabled = tegra->clock_enabled;
+ timer_event = tegra->timer_event;
spin_unlock_irqrestore(&tegra->ehci->lock, flags);
+
+ if (timer_event) {
+ clk_disable(tegra->emc_clk);
+ clk_disable(tegra->sclk_clk);
+ spin_lock_irqsave(&tegra->ehci->lock, flags);
+ tegra->clock_enabled = 0;
+ tegra->timer_event = 0;
+ spin_unlock_irqrestore(&tegra->ehci->lock, flags);
+ return;
+ }
+
if ((!clock_enabled)) {
ret = mod_timer(&tegra->clk_timer, jiffies + msecs_to_jiffies(2000));
if (ret)