diff --git a/drivers/usb/host/ehci-msm-hsic.c b/drivers/usb/host/ehci-msm-hsic.c index e49e2a0ce5b..4dd6d689535 100644 --- a/drivers/usb/host/ehci-msm-hsic.c +++ b/drivers/usb/host/ehci-msm-hsic.c @@ -27,7 +27,6 @@ #include #include #include -#include #include #include @@ -57,14 +56,13 @@ struct msm_hsic_hcd { struct clk *phy_clk; struct clk *cal_clk; struct regulator *hsic_vddcx; - bool async_int; atomic_t in_lpm; - struct wake_lock wlock; int peripheral_status_irq; int wakeup_irq; int wakeup_gpio; bool wakeup_irq_enabled; - atomic_t pm_usage_cnt; + bool irq_enabled; + bool async_int; uint32_t bus_perf_client; uint32_t wakeup_int_cnt; enum usb_vdd_type vdd_type; @@ -599,13 +597,15 @@ static int msm_hsic_suspend(struct msm_hsic_hcd *mehci) disable_irq(hcd->irq); - /* make sure we don't race against a remote wakeup */ - if (test_bit(HCD_FLAG_WAKEUP_PENDING, &hcd->flags) || + /* make sure we don't race against the root hub being resumed */ + if (HCD_RH_RUNNING(hcd) || HCD_WAKEUP_PENDING(hcd) || readl_relaxed(USB_PORTSC) & PORT_RESUME) { - dev_dbg(mehci->dev, "wakeup pending, aborting suspend\n"); + dev_warn(mehci->dev, "%s: Root hub is not suspended\n", + __func__); enable_irq(hcd->irq); return -EBUSY; } + mehci->irq_enabled = false; /* * PHY may take some time or even fail to enter into low power @@ -666,14 +666,13 @@ static int msm_hsic_suspend(struct msm_hsic_hcd *mehci) } atomic_set(&mehci->in_lpm, 1); + mehci->irq_enabled = true; enable_irq(hcd->irq); mehci->wakeup_irq_enabled = 1; enable_irq_wake(mehci->wakeup_irq); enable_irq(mehci->wakeup_irq); - wake_unlock(&mehci->wlock); - dev_info(mehci->dev, "HSIC-USB in low power mode\n"); return 0; @@ -697,8 +696,6 @@ static int msm_hsic_resume(struct msm_hsic_hcd *mehci) mehci->wakeup_irq_enabled = 0; } - wake_lock(&mehci->wlock); - if (mehci->bus_perf_client && debug_bus_voting_enabled) { ret = msm_bus_scale_client_update_request( mehci->bus_perf_client, 1); @@ -757,14 +754,15 @@ skip_phy_resume: if (mehci->async_int) { mehci->async_int = false; pm_runtime_put_noidle(mehci->dev); - enable_irq(hcd->irq); } - if (atomic_read(&mehci->pm_usage_cnt)) { - atomic_set(&mehci->pm_usage_cnt, 0); - pm_runtime_put_noidle(mehci->dev); + if (!mehci->irq_enabled) { + enable_irq(hcd->irq); + mehci->irq_enabled = true; } + pm_relax(mehci->dev); + dev_info(mehci->dev, "HSIC-USB exited from low power mode\n"); return 0; @@ -777,9 +775,11 @@ static irqreturn_t msm_hsic_irq(struct usb_hcd *hcd) if (atomic_read(&mehci->in_lpm)) { disable_irq_nosync(hcd->irq); + mehci->irq_enabled = false; dev_dbg(mehci->dev, "phy async intr\n"); mehci->async_int = true; pm_runtime_get(mehci->dev); + pm_stay_awake(mehci->dev); return IRQ_HANDLED; } @@ -996,7 +996,9 @@ static irqreturn_t msm_hsic_wakeup_irq(int irq, void *data) dev_dbg(mehci->dev, "%s: hsic remote wakeup interrupt cnt: %u\n", __func__, mehci->wakeup_int_cnt); - wake_lock(&mehci->wlock); + mehci->async_int = true; + pm_runtime_get(mehci->dev); + pm_stay_awake(mehci->dev); if (mehci->wakeup_irq_enabled) { mehci->wakeup_irq_enabled = 0; @@ -1004,11 +1006,6 @@ static irqreturn_t msm_hsic_wakeup_irq(int irq, void *data) disable_irq_nosync(irq); } - if (!atomic_read(&mehci->pm_usage_cnt)) { - atomic_set(&mehci->pm_usage_cnt, 1); - pm_runtime_get(mehci->dev); - } - return IRQ_HANDLED; } @@ -1303,9 +1300,8 @@ static int __devinit ehci_hsic_msm_probe(struct platform_device *pdev) goto unconfig_gpio; } + mehci->irq_enabled = true; device_init_wakeup(&pdev->dev, 1); - wake_lock_init(&mehci->wlock, WAKE_LOCK_SUSPEND, dev_name(&pdev->dev)); - wake_lock(&mehci->wlock); if (mehci->peripheral_status_irq) { ret = request_threaded_irq(mehci->peripheral_status_irq, @@ -1412,7 +1408,6 @@ static int __devexit ehci_hsic_msm_remove(struct platform_device *pdev) msm_hsic_init_vddcx(mehci, 0); msm_hsic_init_clocks(mehci, 0); - wake_lock_destroy(&mehci->wlock); iounmap(hcd->regs); usb_put_hcd(hcd);