From ce12d71685f78f75ef9dacbe3572420e19cbb100 Mon Sep 17 00:00:00 2001 From: vjagadish Date: Fri, 30 Sep 2011 12:45:48 +0530 Subject: 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 Tested-by: Venkata Jagadish Reviewed-by: Rakesh Bodla Reviewed-by: Venkat Moganty Rebase-Id: R8a7554b6b8ab6156b8451f9123b269d754a271b2 --- drivers/usb/host/ehci-tegra.c | 20 ++++++++++++++++---- 1 file changed, 16 insertions(+), 4 deletions(-) (limited to 'drivers/usb') diff --git a/drivers/usb/host/ehci-tegra.c b/drivers/usb/host/ehci-tegra.c index d88547634577..2a544fc84f5b 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; }; @@ -911,11 +912,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); } } @@ -924,11 +924,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) -- cgit v1.2.3