summaryrefslogtreecommitdiff
path: root/drivers
diff options
context:
space:
mode:
authorvjagadish <vjagadish@nvidia.com>2011-09-30 12:45:48 +0530
committerVarun Colbert <vcolbert@nvidia.com>2011-10-03 16:42:39 -0700
commit17f7d52511d38e98c7305319818f62c641d42c0e (patch)
tree0b689cacd75a04a8118055f6cf255560fa70b878 /drivers
parent1191be4af6e4b600c88ba2e0f4a341d51a410f4f (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 Change-Id: I3fc6a016095ad21988d19e1651bd08e48a440e30 Reviewed-on: http://git-master/r/53734 Reviewed-by: Venkata Jagadish <vjagadish@nvidia.com> Tested-by: Venkata Jagadish <vjagadish@nvidia.com> Reviewed-by: Rakesh Bodla <rbodla@nvidia.com> Reviewed-by: Venkat Moganty <vmoganty@nvidia.com>
Diffstat (limited to 'drivers')
-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 bc9a1d380b4f..4c33966fc279 100644
--- a/drivers/usb/host/ehci-tegra.c
+++ b/drivers/usb/host/ehci-tegra.c
@@ -69,6 +69,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;
};
@@ -839,11 +840,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);
}
}
@@ -852,11 +852,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)