]> xenbits.xensource.com Git - people/aperard/linux-chromebook.git/commitdiff
CHROMIUM: exynos: Fix lockdep warning in exynos_ohci_suspend
authorMichael Spang <spang@chromium.org>
Fri, 26 Oct 2012 21:55:34 +0000 (17:55 -0400)
committerGerrit <chrome-bot@google.com>
Fri, 30 Nov 2012 18:52:57 +0000 (10:52 -0800)
On the first suspend with lockdep (CONFIG_PROVE_LOCKING) enabled I get
the following warning:

[   27.873728] powerd_suspend/2517 [HC0[0]:SC0[0]:HE0:SE1] is trying to acquire:
[   27.873734]  (clocks_mutex){+.+...}, at: [<403ea954>] clk_get_sys+0x34/0xd8
[   27.873752]
[   27.873754] and this task is already holding:
[   27.873759]  (&(&ohci->lock)->rlock){-.....}, at: [<40335d6c>] exynos_ohci_suspend+0x34/0x94
[   27.873774] which would create a new lock dependency:
[   27.873779]  (&(&ohci->lock)->rlock){-.....} -> (clocks_mutex){+.+...}
[   27.873794]
[   27.873795] but this new dependency connects a HARDIRQ-irq-safe lock:
[   27.873800]  (&(&ohci->lock)->rlock){-.....}

We can avoid this by not calling phy_exit() with the OHCI mutex held.

TEST=suspend with CONFIG_PROVE_LOCKING enabled
BUG=chromium-os:35769

Change-Id: I1c1616b4958094bae5a97ea522262606f4aa749e
Signed-off-by: Michael Spang <spang@chromium.org>
Reviewed-on: https://gerrit.chromium.org/gerrit/36730
Reviewed-by: Olof Johansson <olofj@chromium.org>
drivers/usb/host/ohci-exynos.c

index f564fa6cae3b567d447c42b329ea9c5b6b76b229..97759747d20a73d78f374b92d84288585cc1ef37 100644 (file)
@@ -204,6 +204,18 @@ static void exynos_ohci_shutdown(struct platform_device *pdev)
 }
 
 #ifdef CONFIG_PM
+static int exynos_ohci_halted(struct ohci_hcd *ohci)
+{
+       int ret;
+       unsigned long flags;
+       spin_lock_irqsave(&ohci->lock, flags);
+       ret = (ohci->rh_state == OHCI_RH_SUSPENDED
+              || ohci->rh_state == OHCI_RH_HALTED);
+       spin_unlock_irqrestore(&ohci->lock, flags);
+       return ret;
+}
+
+
 static int exynos_ohci_suspend(struct device *dev)
 {
        struct exynos_ohci_hcd *exynos_ohci = dev_get_drvdata(dev);
@@ -211,32 +223,24 @@ static int exynos_ohci_suspend(struct device *dev)
        struct ohci_hcd *ohci = hcd_to_ohci(hcd);
        struct platform_device *pdev = to_platform_device(dev);
        struct exynos4_ohci_platdata *pdata = pdev->dev.platform_data;
-       unsigned long flags;
-       int rc = 0;
 
        /*
         * Root hub was already suspended. Disable irq emission and
         * mark HW unaccessible, bail out if RH has been resumed. Use
-        * the spinlock to properly synchronize with possible pending
+        * exynos_ohci_halted to properly synchronize with possible pending
         * RH suspend or resume activity.
         */
-       spin_lock_irqsave(&ohci->lock, flags);
-       if (ohci->rh_state != OHCI_RH_SUSPENDED &&
-                       ohci->rh_state != OHCI_RH_HALTED) {
-               rc = -EINVAL;
-               goto fail;
-       }
+       if (!exynos_ohci_halted(ohci))
+               return -EINVAL;
 
        clear_bit(HCD_FLAG_HW_ACCESSIBLE, &hcd->flags);
 
        if (pdata && pdata->phy_exit)
                pdata->phy_exit(pdev, S5P_USB_PHY_HOST);
-fail:
-       spin_unlock_irqrestore(&ohci->lock, flags);
 
        clk_disable(exynos_ohci->clk);
 
-       return rc;
+       return 0;
 }
 
 static int exynos_ohci_resume(struct device *dev)