This patch fixes langwell otg and udc runtime pm usage imbalance
problem which sees runtime pm usage count decrements on every
otg b-device hotplug (when peripheral driver is loaded).

pci_set_power_state() calls are also removed since that is
redundent to what pci rpm code already does.

removed interrupt re-enable in runtime resume, it is not needed since
interrupts are enabled during rpm suspend.

use delayed version of langwell_otg_phy_low_power() when programming
phcd (phy clock disable) since it takes 2-4 ms delay for otgsc and
otgcfg (scu sram) to sync. otherwise, phcd programming will fail when
the two registers are not in sync.

Signed-off-by: Jacob Pan <jacob.jun....@linux.intel.com>
---
 drivers/usb/gadget/langwell_udc.c |   14 ++++++--------
 drivers/usb/otg/langwell_otg.c    |    7 +++----
 2 files changed, 9 insertions(+), 12 deletions(-)

diff --git a/drivers/usb/gadget/langwell_udc.c 
b/drivers/usb/gadget/langwell_udc.c
index 2b3277c..56b8442 100644
--- a/drivers/usb/gadget/langwell_udc.c
+++ b/drivers/usb/gadget/langwell_udc.c
@@ -1568,6 +1568,7 @@ static ssize_t show_langwell_udc(struct device *_dev,
 
        next = buf;
        size = PAGE_SIZE;
+       pm_runtime_get(_dev);
        spin_lock_irqsave(&dev->lock, flags);
 
        /* driver basic information */
@@ -1792,6 +1793,8 @@ static ssize_t show_langwell_udc(struct device *_dev,
        }
 
        spin_unlock_irqrestore(&dev->lock, flags);
+       pm_runtime_put(_dev);
+
        return PAGE_SIZE - size;
 }
 static DEVICE_ATTR(langwell_udc, S_IRUGO, show_langwell_udc, NULL);
@@ -1908,6 +1911,8 @@ int usb_gadget_unregister_driver(struct usb_gadget_driver 
*driver)
        if (unlikely(!driver || !driver->unbind || !driver->disconnect))
                return -EINVAL;
 
+       pm_runtime_get(&dev->pdev->dev);
+
        /* exit PHY low power suspend */
        langwell_phy_low_power(dev, 0);
 
@@ -1933,6 +1938,7 @@ int usb_gadget_unregister_driver(struct usb_gadget_driver 
*driver)
        driver->unbind(&dev->gadget);
        dev->gadget.dev.driver = NULL;
        dev->driver = NULL;
+       pm_runtime_put(&dev->pdev->dev);
 
        dev_info(&dev->pdev->dev, "unregistered driver '%s'\n",
                        driver->driver.name);
@@ -3484,9 +3490,6 @@ static int langwell_udc_runtime_suspend(struct device 
*device)
        /* disable PCI device */
        pci_disable_device(pdev);
 
-       /* set device power state */
-       pci_set_power_state(pdev, PCI_D3hot);
-
        dev->vbus_active = 0;
 
        dev_dbg(&dev->pdev->dev, "<--- %s()\n", __func__);
@@ -3504,9 +3507,6 @@ static int langwell_udc_runtime_resume(struct device 
*device)
 
        pdev = to_pci_dev(device);
 
-       /* set device D0 power state */
-       pci_set_power_state(pdev, PCI_D0);
-
        /* restore PCI state */
        pci_restore_state(pdev);
 
@@ -3714,8 +3714,6 @@ static int intel_mid_stop_peripheral(struct 
intel_mid_otg_xceiv *iotg)
                spin_unlock_irqrestore(&dev->lock, flags);
        }
 
-       pm_runtime_put(&dev->pdev->dev);
-
        dev_dbg(&dev->pdev->dev, "<--- %s()\n", __func__);
        return 0;
 }
diff --git a/drivers/usb/otg/langwell_otg.c b/drivers/usb/otg/langwell_otg.c
index ae7a51f..a450952 100644
--- a/drivers/usb/otg/langwell_otg.c
+++ b/drivers/usb/otg/langwell_otg.c
@@ -2374,10 +2374,9 @@ static int langwell_otg_runtime_suspend(struct device 
*dev)
        case OTG_STATE_A_IDLE:
        case OTG_STATE_B_IDLE:
                /* Transceiver handle it itself */
-               langwell_otg_phy_low_power(1);
+               langwell_otg_phy_low_power_wait(1);
                pci_save_state(pdev);
                pci_disable_device(pdev);
-               pci_set_power_state(pdev, PCI_D3hot);
                break;
        case OTG_STATE_A_WAIT_BCON:
        case OTG_STATE_A_HOST:
@@ -2387,6 +2386,7 @@ static int langwell_otg_runtime_suspend(struct device 
*dev)
                break;
        case OTG_STATE_A_PERIPHERAL:
        case OTG_STATE_B_PERIPHERAL:
+               langwell_otg_phy_low_power_wait(1);
                if (lnw->iotg.runtime_suspend_peripheral)
                        ret = lnw->iotg.runtime_suspend_peripheral(&lnw->iotg);
                break;
@@ -2408,14 +2408,12 @@ static int langwell_otg_runtime_resume(struct device 
*dev)
 
        pdev = to_pci_dev(dev);
 
-       langwell_otg_intr(1);
        langwell_otg_phy_low_power(0);
 
        switch (lnw->iotg.otg.state) {
        case OTG_STATE_A_IDLE:
        case OTG_STATE_B_IDLE:
                /* Transceiver handle it itself */
-               pci_set_power_state(pdev, PCI_D0);
                pci_restore_state(pdev);
                ret = pci_enable_device(pdev);
                if (ret)
@@ -2432,6 +2430,7 @@ static int langwell_otg_runtime_resume(struct device *dev)
        case OTG_STATE_B_PERIPHERAL:
                if (lnw->iotg.runtime_resume_peripheral)
                        ret = lnw->iotg.runtime_resume_peripheral(&lnw->iotg);
+               langwell_otg_phy_low_power(0);
                break;
        default:
                break;
-- 
1.7.1

_______________________________________________
MeeGo-kernel mailing list
MeeGo-kernel@lists.meego.com
http://lists.meego.com/listinfo/meego-kernel

Reply via email to