1. 程式人生 > >Android usb子系統的 電源管理 流程分析

Android usb子系統的 電源管理 流程分析

對的處理器是高通MSM8260,主要是針對一些掛起喚醒流程進行分析,以便對整個usb框架流程更好的理解。

由於linux中的電源管理比較複雜,我就找了一個統一的介面,也就是 要想操縱usb的電源管理 必定要調的函式。順便說下,跟蹤程式碼最好的方法是用WARN_ON(1)打呼叫棧。

先看電源管理子系統的一些初始化:



/*系統初始化所用的結構體*/
struct device {

 .....
 struct dev_pm_info power;  //電源管理結構體
 .....
};



/*該結構體定義如下*/ struct dev_pm_info {

 pm_message_t  power_state;
 unsigned int  can_wakeup:1;  //can_wakeup標誌 表示裝置(或驅動)物理上 支援喚醒事件

 unsigned int  should_wakeup:1;  //should_wakeup標誌 控制裝置是否應該嘗試啟用他的喚醒機制
 unsigned  async_suspend:1;
 enum dpm_state  status;  /* Owned by the PM core */

#ifdef CONFIG_PM_SLEEP
 struct list_head entry;  //連結到dpm_list連結串列的節點
 struct completion completion;
#endif

#ifdef CONFIG_PM_RUNTIME
 struct timer_list suspend_timer;  //處理自動掛起的timer

 unsigned long  timer_expires;
 struct work_struct work;  //請求處理用的work
 wait_queue_head_t wait_queue;  //等待佇列頭
 spinlock_t  lock;
 atomic_t  usage_count;
 atomic_t  child_count;
 unsigned int  disable_depth:3;
 unsigned int  ignore_children:1;
 unsigned int  idle_notification:1;
 unsigned int  request_pending:1;
 unsigned int  deferred_resume:1;
 unsigned int  run_wake:1;
 unsigned int  runtime_auto:1;
 enum rpm_request request;
 enum rpm_status  runtime_status;
 int   runtime_error;
#endif
};


/*在裝置加入裝置驅動模型時,對裝置進行初始化*/

device_initialize(&dev->dev);

void device_initialize(struct device *dev)
{
 ............
 device_pm_init(dev);  //繼續進行初始化
 ...............
} void device_pm_init(struct device *dev)
{
 dev->power.status = DPM_ON;
 init_completion(&dev->power.completion);
 complete_all(&dev->power.completion);
 pm_runtime_init(dev);  //呼叫該函式繼續進行初始化
}
void pm_runtime_init(struct device *dev)
{
 spin_lock_init(&dev->power.lock);  dev->power.runtime_status = RPM_SUSPENDED;
 dev->power.idle_notification = false;  dev->power.disable_depth = 1; //初始化時,disable該pm runtime功能
 atomic_set(&dev->power.usage_count, 0);  dev->power.runtime_error = 0;  atomic_set(&dev->power.child_count, 0);
 pm_suspend_ignore_children(dev, false);
 dev->power.runtime_auto = true;  dev->power.request_pending = false;
 dev->power.request = RPM_REQ_NONE;
 dev->power.deferred_resume = false;
 INIT_WORK(&dev->power.work, pm_runtime_work);  //處理autosuspend請求用的work  /*處理work請求定時器*/
 dev->power.timer_expires = 0;
 setup_timer(&dev->power.suspend_timer, pm_suspend_timer_fn,(unsigned long)dev);  init_waitqueue_head(&dev->power.wait_queue);//初始化等待佇列
} ***************************************************************
/*註冊的usb匯流排級別的操作*/
static int usb_runtime_suspend(struct device *dev)//usb的掛機函式
{
 int status = 0;  /* A USB device can be suspended if it passes the various autosuspend
  * checks.  Runtime suspend for a USB device means suspending all the
  * interfaces and then the device itself.
  */
 if (is_usb_device(dev)) {//針對usb裝置
  struct usb_device *udev = to_usb_device(dev);   if (autosuspend_check(udev) != 0)//是否支援自動掛起?
        return -EAGAIN;   status = usb_suspend_both(udev, PMSG_AUTO_SUSPEND);// 如果不支援,則繼續掛機流程   /* If an interface fails the suspend, adjust the last_busy
   * time so that we don't get another suspend attempt right
   * away.
   */
  if (status) {
   udev->last_busy = jiffies + (udev->autosuspend_delay == 0 ? HZ/2 : 0);
  }   /* Prevent the parent from suspending immediately after */
  else if (udev->parent) {
   udev->parent->last_busy = jiffies;
  }
 }  /* Runtime suspend for a USB interface doesn't mean anything. */
 return status;
} static int usb_runtime_resume(struct device *dev)//usb的喚醒函式
{
 /* Runtime resume for a USB device means resuming both the device
  * and all its interfaces.
  */
 if (is_usb_device(dev)) {
  struct usb_device *udev = to_usb_device(dev);
  int   status;   status = usb_resume_both(udev, PMSG_AUTO_RESUME);
  udev->last_busy = jiffies;
  return status;
 }  /* Runtime resume for a USB interface doesn't mean anything. */
 return 0;
} static int usb_runtime_idle(struct device *dev)//usb裝置的idle函式
{
 /* An idle USB device can be suspended if it passes the various
  * autosuspend checks.  An idle interface can be suspended at
  * any time.
  */
 if (is_usb_device(dev)) {
  struct usb_device *udev = to_usb_device(dev);   if (autosuspend_check(udev) != 0)//支援自動掛起
   return 0;
 }  pm_runtime_suspend(dev);
 return 0;
} static struct dev_pm_ops usb_bus_pm_ops = {
 .runtime_suspend = usb_runtime_suspend,
 .runtime_resume = usb_runtime_resume,
 .runtime_idle =  usb_runtime_idle,
}; struct bus_type usb_bus_type = {
 .name =  "usb",
 .match = usb_device_match,
 .uevent = usb_uevent,
 .pm =  &usb_bus_pm_ops,
};

上面是系統和usb子系統的電源管理初始化部分。


/**************************************************************************/ usb子系統電源管理的呼叫過程,必須要呼叫下面兩個函式,就從這兩個函式開始跟起。 /*驅動呼叫的介面開始,傳入的是usb裝置結構體或者usb介面裝置結構體*/
static inline int pm_runtime_put(struct device *dev)
{
 return __pm_runtime_put(dev, false);
} static inline int pm_runtime_put_sync(struct device *dev)
{
 return __pm_runtime_put(dev, true);
} 上面兩個函式一個是同步的一個是不同步的。先跟同步的: /*當sync為true時,走的如下流程*/
int __pm_runtime_put(struct device *dev, bool sync)
{
 int retval = 0;
 if (atomic_dec_and_test(&dev->power.usage_count))
  retval = sync ? pm_runtime_idle(dev) : pm_request_idle(dev);  return retval;
} int pm_runtime_idle(struct device *dev)
{
 int retval;  spin_lock_irq(&dev->power.lock);
 retval = __pm_runtime_idle(dev);
 spin_unlock_irq(&dev->power.lock);  return retval;
}
static int __pm_runtime_idle(struct device *dev)
 __releases(&dev->power.lock) __acquires(&dev->power.lock)
{
 dev->power.idle_notification = true;  if (dev->bus && dev->bus->pm && dev->bus->pm->runtime_idle) {
  spin_unlock_irq(&dev->power.lock);   dev->bus->pm->runtime_idle(dev);//呼叫usb匯流排的idle函式   spin_lock_irq(&dev->power.lock);
 } else if (dev->type && dev->type->pm && dev->type->pm->runtime_idle) {
  spin_unlock_irq(&dev->power.lock);   dev->type->pm->runtime_idle(dev);   spin_lock_irq(&dev->power.lock);
 } else if (dev->class && dev->class->pm
     && dev->class->pm->runtime_idle) {
  spin_unlock_irq(&dev->power.lock);   dev->class->pm->runtime_idle(dev);   spin_lock_irq(&dev->power.lock);
 }  dev->power.idle_notification = false;
 wake_up_all(&dev->power.wait_queue);  out:
 return retval;
} /*usb匯流排的idle函式如下*/ static int usb_runtime_idle(struct device *dev)
{
 /* An idle USB device can be suspended if it passes the various
  * autosuspend checks.  An idle interface can be suspended at
  * any time.
  */
 if (is_usb_device(dev)) {
  struct usb_device *udev = to_usb_device(dev);   if (autosuspend_check(udev) != 0)//檢測是否自動掛起,如果是自動掛起的話,走自動掛起流程
   return 0;
 }  pm_runtime_suspend(dev);//如果不是自動掛起,則繼續suspend
 return 0;
} int pm_runtime_suspend(struct device *dev)
{
 int retval;  spin_lock_irq(&dev->power.lock);
 retval = __pm_runtime_suspend(dev, false);
 spin_unlock_irq(&dev->power.lock);  return retval;
} int __pm_runtime_suspend(struct device *dev, bool from_wq)
 __releases(&dev->power.lock) __acquires(&dev->power.lock)
{
 struct device *parent = NULL;
 bool notify = false;
 int retval = 0;  dev_dbg(dev, "__pm_runtime_suspend()%s!\n",
  from_wq ? " from workqueue" : "");  repeat:  /* Other scheduled or pending requests need to be canceled. */
 pm_runtime_cancel_pending(dev);  if (dev->power.runtime_status == RPM_SUSPENDING) {
  DEFINE_WAIT(wait);   if (from_wq) {
   retval = -EINPROGRESS;
   goto out;
  }   /* Wait for the other suspend running in parallel with us. */
  for (;;) {
   prepare_to_wait(&dev->power.wait_queue, &wait, TASK_UNINTERRUPTIBLE);
   if (dev->power.runtime_status != RPM_SUSPENDING)
    break;    spin_unlock_irq(&dev->power.lock);    schedule();    spin_lock_irq(&dev->power.lock);
  }
  finish_wait(&dev->power.wait_queue, &wait);
  goto repeat;
 }  dev->power.runtime_status = RPM_SUSPENDING;
 dev->power.deferred_resume = false;  if (dev->bus && dev->bus->pm && dev->bus->pm->runtime_suspend) {
  spin_unlock_irq(&dev->power.lock);   retval = dev->bus->pm->runtime_suspend(dev);//呼叫匯流排的runtime suspend函式   spin_lock_irq(&dev->power.lock);
  dev->power.runtime_error = retval;
 } else if (dev->type && dev->type->pm && dev->type->pm->runtime_suspend) {
  spin_unlock_irq(&dev->power.lock);   retval = dev->type->pm->runtime_suspend(dev);   spin_lock_irq(&dev->power.lock);
  dev->power.runtime_error = retval;
 } else if (dev->class && dev->class->pm
     && dev->class->pm->runtime_suspend) {
  spin_unlock_irq(&dev->power.lock);   retval = dev->class->pm->runtime_suspend(dev);   spin_lock_irq(&dev->power.lock);
  dev->power.runtime_error = retval;
 } else {
  retval = -ENOSYS;
 }  wake_up_all(&dev->power.wait_queue);  if (dev->power.deferred_resume) {
  __pm_runtime_resume(dev, false);
  retval = -EAGAIN;
  goto out;
 }  if (notify)
  __pm_runtime_idle(dev);  if (parent && !parent->power.ignore_children) {
  spin_unlock_irq(&dev->power.lock);   pm_request_idle(parent);   spin_lock_irq(&dev->power.lock);
 }  out:
 dev_dbg(dev, "__pm_runtime_suspend() returns %d!\n", retval);  return retval;
} static int usb_runtime_suspend(struct device *dev)
{
 int status = 0;  /* A USB device can be suspended if it passes the various autosuspend
  * checks.  Runtime suspend for a USB device means suspending all the
  * interfaces and then the device itself.
  */
 if (is_usb_device(dev)) {
  struct usb_device *udev = to_usb_device(dev);   if (autosuspend_check(udev) != 0)//是否自動掛起,如果是走自動掛起流程
   return -EAGAIN;   status = usb_suspend_both(udev, PMSG_AUTO_SUSPEND);//否則繼續suspend   /* If an interface fails the suspend, adjust the last_busy
   * time so that we don't get another suspend attempt right
   * away.
   */
  if (status) {
   udev->last_busy = jiffies +(udev->autosuspend_delay == 0 ? HZ/2 : 0);
  }   /* Prevent the parent from suspending immediately after */
  else if (udev->parent) {
   udev->parent->last_busy = jiffies;
  }
 }  /* Runtime suspend for a USB interface doesn't mean anything. */
 return status;
} static int usb_suspend_both(struct usb_device *udev, pm_message_t msg)
{
 int   status = 0;
 int   i = 0, n = 0;
 struct usb_interface *intf;  if (udev->state == USB_STATE_NOTATTACHED || udev->state == USB_STATE_SUSPENDED)
  goto done;  /* Suspend all the interfaces and then udev itself */
 if (udev->actconfig) {//掛起所有的介面
  n = udev->actconfig->desc.bNumInterfaces;
  for (i = n - 1; i >= 0; --i) {
   intf = udev->actconfig->interface[i];
   status = usb_suspend_interface(udev, intf, msg);
   if (status != 0)
    break;
  }
 }
 if (status == 0)
  status = usb_suspend_device(udev, msg);//掛起該裝置本身  /* If the suspend failed, resume interfaces that did get suspended */
 if (status != 0) {
  msg.event ^= (PM_EVENT_SUSPEND | PM_EVENT_RESUME);
  while (++i < n) {
   intf = udev->actconfig->interface[i];
   usb_resume_interface(udev, intf, msg, 0);
  }  /* If the suspend succeeded then prevent any more URB submissions
  * and flush any outstanding URBs.
  */
 } else {
  udev->can_submit = 0;
  for (i = 0; i < 16; ++i) {
   usb_hcd_flush_endpoint(udev, udev->ep_out[i]);
   usb_hcd_flush_endpoint(udev, udev->ep_in[i]);
  }
 }  done:
 dev_vdbg(&udev->dev, "%s: status %d\n", __func__, status);
 return status;
} static int usb_suspend_device(struct usb_device *udev, pm_message_t msg)
{
 struct usb_device_driver *udriver;
 int    status = 0;  if (udev->state == USB_STATE_NOTATTACHED ||
   udev->state == USB_STATE_SUSPENDED)
  goto done;  /* For devices that don't have a driver, we do a generic suspend. */
 if (udev->dev.driver)
  udriver = to_usb_device_driver(udev->dev.driver);
 else {
  udev->do_remote_wakeup = 0;
  udriver = &usb_generic_driver;
 }
 status = udriver->suspend(udev, msg);//呼叫通用的裝置驅動掛起函式  done:
 dev_vdbg(&udev->dev, "%s: status %d\n", __func__, status);
 return status;
} static int generic_suspend(struct usb_device *udev, pm_message_t msg)
{
 int rc;  /* Normal USB devices suspend through their upstream port.
  * Root hubs don't have upstream ports to suspend,
  * so we have to shut down their downstream HC-to-USB
  * interfaces manually by doing a bus (or "global") suspend.
  */
 if (!udev->parent)//針對root hub的
  rc = hcd_bus_suspend(udev, msg);//掛起root hub  /* Non-root devices don't need to do anything for FREEZE or PRETHAW */
 else if (msg.event == PM_EVENT_FREEZE || msg.event == PM_EVENT_PRETHAW)
  rc = 0;
 else
  rc = usb_port_suspend(udev, msg);//掛起每個埠裝置  return rc;
} ********************************************************************* 下面是自動掛起的流程(上面的藍色字型標出呼叫的地方),最終也會走到generic_suspend,相當於兩條小溪最終匯成一起。 /* Internal routine to check whether we may autosuspend a device. */
static int autosuspend_check(struct usb_device *udev)
{
 int   w, i;
 struct usb_interface *intf;
 unsigned long  suspend_time, j;  /* Fail if autosuspend is disabled, or any interfaces are in use, or
  * any interface drivers require remote wakeup but it isn't available.
  */
 w = 0;
 if (udev->actconfig) {
  for (i = 0; i < udev->actconfig->desc.bNumInterfaces; i++) {
   intf = udev->actconfig->interface[i];    /* We don't need to check interfaces that are
    * disabled for runtime PM.  Either they are unbound
    * or else their drivers don't support autosuspend
    * and so they are permanently active.
    */
   if (intf->dev.power.disable_depth)
    continue;
   if (atomic_read(&intf->dev.power.usage_count) > 0)
    return -EBUSY;
   w |= intf->needs_remote_wakeup;    /* Don't allow autosuspend if the device will need
    * a reset-resume and any of its interface drivers
    * doesn't include support or needs remote wakeup.
    */
   if (udev->quirks & USB_QUIRK_RESET_RESUME) {
    struct usb_driver *driver;     driver = to_usb_driver(intf->dev.driver);
    if (!driver->reset_resume ||
      intf->needs_remote_wakeup)
     return -EOPNOTSUPP;
   }
  }
 }
 if (w && !device_can_wakeup(&udev->dev)) {
  dev_dbg(&udev->dev, "remote wakeup needed for autosuspend\n");
  return -EOPNOTSUPP;
 }
 udev->do_remote_wakeup = w;  /* If everything is okay but the device hasn't been idle for long
  * enough, queue a delayed autosuspend request.
  */
 j = ACCESS_ONCE(jiffies);
 suspend_time = udev->last_busy + udev->autosuspend_delay;
 if (time_before(j, suspend_time)) {
  pm_schedule_suspend(&udev->dev, jiffies_to_msecs(round_jiffies_up_relative(suspend_time - j)));//排程
  return -EAGAIN;
 }
 return 0;
} /**
 * pm_schedule_suspend - Set up a timer to submit a suspend request in future.
 * @dev: Device to suspend.
 * @delay: Time to wait before submitting a suspend request, in milliseconds.
 */
int pm_schedule_suspend(struct device *dev, unsigned int delay)
{
 unsigned long flags;
 int retval = 0;  spin_lock_irqsave(&dev->power.lock, flags);  if (dev->power.runtime_error) {
  retval = -EINVAL;
  goto out;
 }  if (!delay) {
  retval = __pm_request_suspend(dev);//如果沒有delay,則立即執行
  goto out;
 }  pm_runtime_deactivate_timer(dev);  if (dev->power.request_pending) {
  /*
   * Pending resume requests take precedence over us, but any
   * other pending requests have to be canceled.
   */
  if (dev->power.request == RPM_REQ_RESUME) {
   retval = -EAGAIN;
   goto out;
  }
  dev->power.request = RPM_REQ_NONE;
 }  if (dev->power.runtime_status == RPM_SUSPENDED)
  retval = 1;
 else if (atomic_read(&dev->power.usage_count) > 0
     || dev->power.disable_depth > 0)
  retval = -EAGAIN;
 else if (!pm_children_suspended(dev))
  retval = -EBUSY;
 if (retval)
  goto out;  dev->power.timer_expires = jiffies + msecs_to_jiffies(delay);
 if (!dev->power.timer_expires)
  dev->power.timer_expires = 1;
 mod_timer(&dev->power.suspend_timer, dev->power.timer_expires);//如果有超時,等待定時器到期,執行處理函數pm_suspend_timer_fn  out:
 spin_unlock_irqrestore(&dev->power.lock, flags);  return retval;
}  /*定時器到期處理函式*/ static void pm_suspend_timer_fn(unsigned long data)
{
 struct device *dev = (struct device *)data;
 unsigned long flags;
 unsigned long expires;  spin_lock_irqsave(&dev->power.lock, flags);  expires = dev->power.timer_expires;
 /* If 'expire' is after 'jiffies' we've been called too early. */
 if (expires > 0 && !time_after(expires, jiffies)) {
  dev->power.timer_expires = 0;
  __pm_request_suspend(dev);//定時器到時,執行該函式
 }  spin_unlock_irqrestore(&dev->power.lock, flags);
} /*無論是定時器超時,還是直接呼叫,都會呼叫下面該函式*/
static int __pm_request_suspend(struct device *dev)
{
 int retval = 0;  if (dev->power.runtime_error)
  return -EINVAL;  if (dev->power.runtime_status == RPM_SUSPENDED)
  retval = 1;
 else if (atomic_read(&dev->power.usage_count) > 0
     || dev->power.disable_depth > 0)
  retval = -EAGAIN;
 else if (dev->power.runtime_status == RPM_SUSPENDING)
  retval = -EINPROGRESS;
 else if (!pm_children_suspended(dev))
  retval = -EBUSY;
 if (retval < 0)
  return retval;  pm_runtime_deactivate_timer(dev);  if (dev->power.request_pending) {
  /*
   * Pending resume requests take precedence over us, but we can
   * overtake any other pending request.
   */
  if (dev->power.request == RPM_REQ_RESUME)
   retval = -EAGAIN;
  else if (dev->power.request != RPM_REQ_SUSPEND)
   dev->power.request = retval ?
      RPM_REQ_NONE : RPM_REQ_SUSPEND;
  return retval;
 } else if (retval) {
  return retval;
 }  dev->power.request = RPM_REQ_SUSPEND;//請求狀態為suspend
 dev->power.request_pending = true;
 queue_work(pm_wq, &dev->power.work);//排程work  return 0;
}
static void pm_runtime_work(struct work_struct *work) {
 struct device *dev = container_of(work, struct device, power.work);
 enum rpm_request req;  spin_lock_irq(&dev->power.lock);  if (!dev->power.request_pending)
  goto out;  req = dev->power.request;
 dev->power.request = RPM_REQ_NONE;
 dev->power.request_pending = false;  switch (req) {
 case RPM_REQ_NONE:
  break;
 case RPM_REQ_IDLE:
  __pm_runtime_idle(dev);
  break;
 case RPM_REQ_SUSPEND:
  __pm_runtime_suspend(dev, true); //呼叫suspend函式
  break;
 case RPM_REQ_RESUME:
  __pm_runtime_resume(dev, true);
  break;
 }  out:
 spin_unlock_irq(&dev->power.lock);
} int __pm_runtime_suspend(struct device *dev, bool from_wq)
 __releases(&dev->power.lock) __acquires(&dev->power.lock)
{
 struct device *parent = NULL;
 bool notify = false;
 int retval = 0;  dev_dbg(dev, "__pm_runtime_suspend()%s!\n",from_wq ? " from workqueue" : "");  ...................  if (dev->bus && dev->bus->pm && dev->bus->pm->runtime_suspend) {
  spin_unlock_irq(&dev->power.lock);   retval = dev->bus->pm->runtime_suspend(dev);//呼叫usb匯流排的runtime_suspend函式   spin_lock_irq(&dev->power.lock);
  dev->power.runtime_error = retval;
 }
 ...................  out:
 dev_dbg(dev, "__pm_runtime_suspend() returns %d!\n", retval);  return retval;
} static int usb_runtime_suspend(struct device *dev)
{
 int status = 0;  if (is_usb_device(dev)) {
  struct usb_device *udev = to_usb_device(dev);   if (autosuspend_check(udev) != 0)
   return -EAGAIN;   status = usb_suspend_both(udev, PMSG_AUTO_SUSPEND);//3  ...............
 return status;
} static int usb_suspend_both(struct usb_device *udev, pm_message_t msg)
{
 int   status = 0;
 int   i = 0, n = 0;
 struct usb_interface *intf;  if (udev->state == USB_STATE_NOTATTACHED ||
   udev->state == USB_STATE_SUSPENDED)
  goto done;  /* Suspend all the interfaces and then udev itself */
 if (udev->actconfig) {//掛起所以埠
  n = udev->actconfig->desc.bNumInterfaces;
  for (i = n - 1; i >= 0; --i) {
   intf = udev->actconfig->interface[i];
   status = usb_suspend_interface(udev, intf, msg);
   if (status != 0)
    break;
  }
 }
 if (status == 0)
  status = usb_suspend_device(udev, msg);//掛起usb裝置本身
  ..............
 } else {   udev->can_submit = 0;
  for (i = 0; i < 16; ++i) {
   usb_hcd_flush_endpoint(udev, udev->ep_out[i]);
   usb_hcd_flush_endpoint(udev, udev->ep_in[i]);
  }
 }  done:
 dev_vdbg(&udev->dev, "%s: status %d\n", __func__, status);
 return status;
} static int usb_suspend_device(struct usb_device *udev, pm_message_t msg)

 if (udev->dev.driver)
  udriver = to_usb_device_driver(udev->dev.driver);
 else {
  udev->do_remote_wakeup = 0;
  udriver = &usb_generic_driver;
 }
 status = udriver->suspend(udev, msg);//5  done:
 dev_vdbg(&udev->dev, "%s: status %d\n", __func__, status);
 return status;
} struct usb_device_driver usb_generic_driver = {
 .name = "usb",
 .probe = generic_probe,
 .disconnect = generic_disconnect,
#ifdef CONFIG_PM
 .suspend = generic_suspend,//6
 .resume = generic_resume,
#endif
 .supports_autosuspend = 1,
}; static int generic_suspend(struct usb_device *udev, pm_message_t msg)
{
 int rc;  if (!udev->parent)
  rc = hcd_bus_suspend(udev, msg);//7  /* Non-root devices don't need to do anything for FREEZE or PRETHAW */
 else if (msg.event == PM_EVENT_FREEZE || msg.event == PM_EVENT_PRETHAW)
  rc = 0;
 else
  rc = usb_port_suspend(udev, msg);  return rc;
} *************************************************** /*通用usb裝置的suspend函式,上面的自動掛起和正常掛起都會走*/
static int generic_suspend(struct usb_device *udev, pm_message_t msg)
{
 int rc;  /* Normal USB devices suspend through their upstream port.
  * Root hubs don't have upstream ports to suspend,
  * so we have to shut down their downstream HC-to-USB
  * interfaces manually by doing a bus (or "global") suspend.
  */
 if (!udev->parent)//針對root hub
  rc = hcd_bus_suspend(udev, msg);//掛起root hub的下流口  /* Non-root devices don't need to do anything for FREEZE or PRETHAW */
 else if (msg.event == PM_EVENT_FREEZE || msg.event == PM_EVENT_PRETHAW)
  rc = 0;
 else
  rc = usb_port_suspend(udev, msg);//關閉usb裝置的上流口  return rc;
} int usb_port_suspend(struct usb_device *udev, pm_message_t msg)
{
 struct usb_hub *hub = hdev_to_hub(udev->parent);
 int  port1 = udev->portnum;
 int  status;  // dev_dbg(hub->intfdev, "suspend port %d\n", port1);  /* enable remote wakeup when appropriate; this lets the device
  * wake up the upstream hub (including maybe the root hub).
  *
  * NOTE:  OTG devices may issue remote wakeup (or SRP) even when
  * we don't explicitly enable it here.
  */
 if (udev->do_remote_wakeup) {
  status = usb_control_msg(udev, usb_sndctrlpipe(udev, 0),
    USB_REQ_SET_FEATURE, USB_RECIP_DEVICE,
    USB_DEVICE_REMOTE_WAKEUP, 0,
    NULL, 0,
    USB_CTRL_SET_TIMEOUT);
 }  /* see 7.1.7.6 */
 status = set_port_feature(hub->hdev, port1, USB_PORT_FEAT_SUSPEND);
  
 /* device has up to 10 msec to fully suspend */
 dev_dbg(&udev->dev, "usb %ssuspend\n",(msg.event & PM_EVENT_AUTO ? "auto-" : ""));
 usb_set_device_state(udev, USB_STATE_SUSPENDED);//設定usb裝置為掛起狀態
 msleep(10);
 }
 return status;
} /*掛起root hub*/ int hcd_bus_suspend(struct usb_device *rhdev, pm_message_t msg)
{
 struct usb_hcd *hcd = container_of(rhdev->bus, struct usb_hcd, self);
 int  status;
 int  old_state = hcd->state;  dev_dbg(&rhdev->dev, "bus %s%s\n",
   (msg.event & PM_EVENT_AUTO ? "auto-" : ""), "suspend");
 if (!hcd->driver->bus_suspend) {
  status = -ENOENT;
 } else {
  hcd->state = HC_STATE_QUIESCING;
  status = hcd->driver->bus_suspend(hcd);//呼叫主機控制器driver的bus suspend
 }
 if (status == 0) {
  usb_set_device_state(rhdev, USB_STATE_SUSPENDED);//設定root hub裝置的狀態為suspend狀態
  hcd->state = HC_STATE_SUSPENDED;
 } else {
  hcd->state = old_state;
  dev_dbg(&rhdev->dev, "bus %s fail, err %d\n","suspend", status);
 }
 return status;
} static struct hc_driver msm_hc_driver = {
 .description  = hcd_name,
 .product_desc   = "Qualcomm On-Chip EHCI Host Controller",
 .hcd_priv_size   = sizeof(struct msmusb_hcd),  /*
  * generic hardware linkage
  */
 .irq    = ehci_msm_irq,
 .flags    = HCD_USB2,  .reset    = ehci_msm_reset,
 .start    = ehci_msm_run,  .stop   = ehci_stop,
 .shutdown  = ehci_shutdown,  /*
  * managing i/o requests and associated device resources
  */
 .urb_enqueue  = ehci_urb_enqueue,
 .urb_dequeue  = ehci_urb_dequeue,
 .endpoint_disable = ehci_endpoint_disable,  /*
  * scheduling support
  */
 .get_frame_number = ehci_get_frame,  /*
  * root hub support
  */
 .hub_status_data = ehci_hub_status_data,
 .hub_control  = ehci_hub_control,
 .bus_suspend  = ehci_msm_bus_suspend,//呼叫該suspend函式
 .bus_resume  = ehci_msm_bus_resume,
 .relinquish_port = ehci_relinquish_port,  .clear_tt_buffer_complete = ehci_clear_tt_buffer_complete,
}; static int ehci_msm_bus_suspend(struct usb_hcd *hcd)
{
 int ret;
 struct msmusb_hcd *mhcd = hcd_to_mhcd(hcd);
 struct device *dev = hcd->self.controller;  ret = ehci_bus_suspend(hcd);//root hub掛起
 if (ret) {
  pr_err("ehci_bus suspend faield\n");
  return ret;
 } /*下面是掛起otg控制器*/
 if (PHY_TYPE(mhcd->pdata->phy_info) == USB_PHY_INTEGRATED)
ret = otg_set_suspend(mhcd->xceiv, 1);//otg掛起,呼叫該函式
 else
  ret = usb_lpm_enter(hcd);  pm_runtime_put_noidle(dev);
 pm_runtime_suspend(dev);
 wake_unlock(&mhcd->wlock);
 return ret;
} static inline int otg_set_suspend(struct otg_transceiver *otg, int suspend)
{
 if (otg->set_suspend != NULL)
  return otg->set_suspend(otg, suspend);
 else
  return 0;
} dev->otg.set_suspend = msm_otg_set_suspend;
static int msm_otg_set_suspend(struct otg_transceiver *xceiv, int suspend)
{
 struct msm_otg *dev = container_of(xceiv, struct msm_otg, otg);
 enum usb_otg_state state;
 unsigned long flags;  if (!dev || (dev != the_msm_otg))
  return -ENODEV;  spin_lock_irqsave(&dev->lock, flags);
 state = dev->otg.state;
 spin_unlock_irqrestore(&dev->lock, flags);  pr_debug("suspend request in state: %s\n",
   state_string(state));  if (suspend) {
  switch (state) {
#ifndef CONFIG_MSM_OTG_ENABLE_A_WAIT_BCON_TIMEOUT
  case OTG_STATE_A_WAIT_BCON:
   if (test_bit(ID_A, &dev->inputs))
    msm_otg_set_power(xceiv, USB_IDCHG_MIN - 100);
   msm_otg_put_suspend(dev);//如果沒有usb裝置連線,則進入該函式
   break;
#endif
  case OTG_STATE_A_HOST:
   clear_bit(A_BUS_REQ, &dev->inputs);
   wake_lock(&dev->wlock);
   queue_work(dev->wq, &dev->sm_work);
   break;
  case OTG_STATE_B_PERIPHERAL:
   if (xceiv->gadget->b_hnp_enable) {
    set_bit(A_BUS_SUSPEND, &dev->inputs);
    set_bit(B_BUS_REQ, &dev->inputs);
    wake_lock(&dev->wlock);
    queue_work(dev->wq, &dev->sm_work);
   }
   break;
  case OTG_STATE_A_PERIPHERAL:
   msm_otg_start_timer(dev, TA_BIDL_ADIS,
     A_BIDL_ADIS);
   break;
  default:
   break;
  }
 } else {
  unsigned long timeout;   switch (state) {
  case OTG_STATE_A_PERIPHERAL:
   /* A-peripheral observed activity on bus.
    * clear A_BIDL_ADIS timer.
    */
   msm_otg_del_timer(dev);
   break;
  case OTG_STATE_A_SUSPEND:
   /* Remote wakeup or resume */
   set_bit(A_BUS_REQ, &dev->inputs);
   spin_lock_irqsave(&dev->lock, flags);
   dev->otg.state = OTG_STATE_A_HOST;
   spin_unlock_irqrestore(&dev->lock, flags);
   if (test_bit(ID_A, &dev->inputs) &&
    (get_aca_bmaxpower(dev) < USB_IDCHG_MIN))
    msm_otg_set_power(xceiv,
     USB_IDCHG_MIN - get_aca_bmaxpower(dev));
   break;
  default:
   break;
  }   if (suspend == atomic_read(&dev->in_lpm))
   return 0;   disable_irq(dev->irq);
  if (dev->pmic_vbus_notif_supp)
   if (can_phy_power_collapse(dev) &&
     dev->pdata->ldo_enable)
    dev->pdata->ldo_enable(1);   msm_otg_get_resume(dev);   if (!is_phy_clk_disabled())
   goto out;   timeout = jiffies + usecs_to_jiffies(100);
  enable_phy_clk();
  while (is_phy_clk_disabled()) {
   if (time_after(jiffies, timeout)) {
    pr_err("%s: Unable to wakeup phy\n", __func__);
    /* Reset both phy and link */
    otg_reset(&dev->otg, 1);
    break;
   }
   udelay(10);
  }
  if (dev->pmic_id_notif_supp) {
   dev->pdata->pmic_id_notif_init(
    &msm_otg_set_id_state, 0);
   dev->pmic_id_notif_supp = 0;
   enable_idgnd(dev);
  }
out:
  enable_idabc(dev);
  enable_irq(dev->irq);  }  return 0;
} //上面是主機控制器呼叫到的該流程. //裝置控制器直接呼叫該函式是裝置進入suspend狀態
/***************************************************************/
static void msm_otg_put_suspend(struct msm_otg *dev)
{
#ifdef CONFIG_PM_RUNTIME
 pm_runtime_put_sync(dev->otg.dev);//呼叫該函式,注意:傳入的是平臺裝置
 if (!atomic_read(&dev->in_lpm))
  pm_runtime_get_sync(dev->otg.dev);
#else
 msm_otg_suspend(dev);
#endif
} static inline int pm_runtime_put_sync(struct device *dev)
{
 return __pm_runtime_put(dev, true);//呼叫該函式
} int __pm_runtime_put(struct device *dev, bool sync)
{
 int retval = 0;  if (atomic_dec_and_test(&dev->power.usage_count))
  retval = sync ? pm_runtime_idle(dev)/*呼叫該函式*/: pm_request_idle(dev);  return retval;
} int pm_runtime_idle(struct device *dev)
{
 int retval;  spin_lock_irq(&dev->power.lock);
 retval = __pm_runtime_idle(dev);//呼叫該函式
 spin_unlock_irq(&dev->power.lock);  return retval;
} static int __pm_runtime_idle(struct device *dev)
 __releases(&dev->power.lock) __acquires(&dev->power.lock)
{
 int retval = 0;
 
 ...............  dev->power.idle_notification = true;  if (dev->bus && dev->bus->pm && dev->bus->pm->runtime_idle) {
  spin_unlock_irq(&dev->power.lock);   dev->bus->pm->runtime_idle(dev);//呼叫該函式   spin_lock_irq(&dev->power.lock);
 } else if (dev->type && dev->type->pm && dev->type->pm->runtime_idle) {
  spin_unlock_irq(&dev->power.lock);   dev->type->pm->runtime_idle(dev);   spin_lock_irq(&dev->power.lock);
 } else if (dev->class && dev->class->pm
     && dev->class->pm->runtime_idle) {
  spin_unlock_irq(&dev->power.lock);   dev->class->pm->runtime_idle(dev);   spin_lock_irq(&dev->power.lock);
 }  dev->power.idle_notification = false;
 wake_up_all(&dev->power.wait_queue);  out:
 return retval;
} static const struct dev_pm_ops platform_dev_pm_ops = {
 .prepare = platform_pm_prepare,
 .complete = platform_pm_complete,
 .suspend = platform_pm_suspend,
 .resume = platform_pm_resume,
 .freeze = platform_pm_freeze,
 .thaw = platform_pm_thaw,
 .poweroff = platform_pm_poweroff,
 .restore = platform_pm_restore,
 .suspend_noirq = platform_pm_suspend_noirq,
 .resume_noirq = platform_pm_resume_noirq,
 .freeze_noirq = platform_pm_freeze_noirq,
 .thaw_noirq = platform_pm_thaw_noirq,
 .poweroff_noirq = platform_pm_poweroff_noirq,
 .restore_noirq = platform_pm_restore_noirq,
 .runtime_suspend = platform_pm_runtime_suspend,
 .runtime_resume = platform_pm_runtime_resume,
 .runtime_idle = platform_pm_runtime_idle,//呼叫該處的函式
}; struct bus_type platform_bus_type = {
 .name  = "platform",
 .dev_attrs = platform_dev_attrs,
 .match  = platform_match,
 .uevent = platform_uevent,
 .pm  = &platform_dev_pm_ops,
}; int __weak platform_pm_runtime_idle(struct device *dev)
{
 return pm_generic_runtime_idle(dev);//呼叫該函式
}; int pm_generic_runtime_idle(struct device *dev)
{
 const struct dev_pm_ops *pm = dev->driver ? dev->driver->pm : NULL;  if (pm && pm->runtime_idle) {
  int ret = pm->runtime_idle(dev);
  if (ret)
   return ret;
 }  pm_runtime_suspend(dev);//呼叫該函式
 return 0;
} int pm_runtime_suspend(struct device *dev)
{
 int retval;  spin_lock_irq(&dev->power.lock);
 retval = __pm_runtime_suspend(dev, false);//呼叫該函式
 spin_unlock_irq(&dev->power.lock);  return retval;
} int __pm_runtime_suspend(struct device *dev, bool from_wq)
 __releases(&dev->power.lock) __acquires(&dev->power.lock)
{
 struct device *parent = NULL;
 bool notify = false;
 int retval = 0;  dev_dbg(dev, "__pm_runtime_suspend()%s!\n",from_wq ? " from workqueue" : "");  repeat:
 dev->power.runtime_status = RPM_SUSPENDING;
 dev->power.deferred_resume = false;  if (dev->bus && dev->bus->pm && dev->bus->pm->runtime_suspend) {
  spin_unlock_irq(&dev->power.lock);   retval = dev->bus->pm->runtime_suspend(dev); //呼叫平臺匯流排的suspend函式   spin_lock_irq(&dev->power.lock);
  dev->power.runtime_error = retval;
 } else if (dev->type && dev->type->pm
     && dev->type->pm->runtime_suspend) {
  spin_unlock_irq(&dev->power.lock);   retval = dev->type->pm->runtime_suspend(dev);   spin_lock_irq(&dev->power.lock);
  dev->power.runtime_error = retval;
 } else if (dev->class && dev->class->pm
     && dev->class->pm->runtime_suspend) {
  spin_unlock_irq(&dev->power.lock);   retval = dev->class->pm->runtime_suspend(dev);   spin_lock_irq(&dev->power.lock);
  dev->power.runtime_error = retval;
 } else {
  retval = -ENOSYS;
 }  if (notify)
  __pm_runtime_idle(dev);  if (parent && !parent->power.ignore_children) {
  spin_unlock_irq(&dev->power.lock);   pm_request_idle(parent);   spin_lock_irq(&dev->power.lock);
 }  out:
 dev_dbg(dev, "__pm_runtime_suspend() returns %d!\n", retval);  return retval;
} int __weak platform_pm_runtime_suspend(struct device *dev)
{
 return pm_generic_runtime_suspend(dev);
}; int pm_generic_runtime_suspend(struct device *dev)
{
 const struct dev_pm_ops *pm = dev->driver ? dev->driver->pm : NULL;
 int ret;  ret = pm && pm->runtime_suspend ? pm->runtime_suspend(dev) : -EINVAL;//呼叫平臺驅動的runtime_suspend函式  return ret;
} /*平臺驅動的註冊函式*/ /*******************************************************************/
static int msm_otg_runtime_suspend(struct device *dev)
{
 struct msm_otg *otg = the_msm_otg;  dev_dbg(dev, "pm_runtime: suspending...\n");
 msm_otg_suspend(otg);
 return  0;
} static int msm_otg_runtime_resume(struct device *dev)
{
 struct msm_otg *otg = the_msm_otg;  dev_dbg(dev, "pm_runtime: resuming...\n");
 msm_otg_resume(otg);
 return  0;
} static int msm_otg_runtime_idle(struct device *dev)
{
 dev_dbg(dev, "pm_runtime: idling...\n");
 return  0;
} static struct dev_pm_ops msm_otg_dev_pm_ops = {
 .runtime_suspend = msm_otg_runtime_suspend,
 .runtime_resume = msm_otg_runtime_resume,
 .runtime_idle = msm_otg_runtime_idle,
}; static struct platform_driver msm_otg_driver = {
 .remove = __exit_p(msm_otg_remove),
 .driver = {
  .name = DRIVER_NAME,
  .owner = THIS_MODULE,
  .pm = &msm_otg_dev_pm_ops,
 },
};
/*******************************************************************/
static int msm_otg_suspend(struct msm_otg *dev)
{
 unsigned long timeout;
 bool host_bus_suspend;
 unsigned ret;
 enum chg_type chg_type = atomic_read(&dev->chg_type);
 unsigned long flags;  disable_irq(dev->irq);
 if (atomic_read(&dev->in_lpm))
  goto out;  atomic_set(&dev->in_lpm, 1);//設定low power mode為1,喚醒的時候要判斷該標記  ...............  if (dev->pdata->config_vddcx)
  dev->pdata->config_vddcx(0);
 pr_info("%s: usb in low power mode\n", __func__);  return 0;
}
到此整個睡眠流程分析完了。