1. 23 Apr, 2022 4 commits
    • Zheng Yongjun's avatar
      usb: dwc3: pci: Fix pm_runtime_get_sync() error checking · a03e2dda
      Zheng Yongjun authored
      If the device is already in a runtime PM enabled state
      pm_runtime_get_sync() will return 1, so a test for negative
      value should be used to check for errors.
      
      Fixes: 8eed00b2 ("usb: dwc3: pci: Runtime resume child device from wq")
      Signed-off-by: default avatarZheng Yongjun <zhengyongjun3@huawei.com>
      Link: https://lore.kernel.org/r/20220422062652.10575-1-zhengyongjun3@huawei.comSigned-off-by: default avatarGreg Kroah-Hartman <gregkh@linuxfoundation.org>
      a03e2dda
    • Duoming Zhou's avatar
      drivers: usb: host: Fix deadlock in oxu_bus_suspend() · 4d378f2a
      Duoming Zhou authored
      There is a deadlock in oxu_bus_suspend(), which is shown below:
      
         (Thread 1)              |      (Thread 2)
                                 | timer_action()
      oxu_bus_suspend()          |  mod_timer()
       spin_lock_irq() //(1)     |  (wait a time)
       ...                       | oxu_watchdog()
       del_timer_sync()          |  spin_lock_irq() //(2)
       (wait timer to stop)      |  ...
      
      We hold oxu->lock in position (1) of thread 1, and use
      del_timer_sync() to wait timer to stop, but timer handler
      also need oxu->lock in position (2) of thread 2. As a result,
      oxu_bus_suspend() will block forever.
      
      This patch extracts del_timer_sync() from the protection of
      spin_lock_irq(), which could let timer handler to obtain
      the needed lock.
      Signed-off-by: default avatarDuoming Zhou <duoming@zju.edu.cn>
      Link: https://lore.kernel.org/r/20220417120305.64577-1-duoming@zju.edu.cnSigned-off-by: default avatarGreg Kroah-Hartman <gregkh@linuxfoundation.org>
      4d378f2a
    • Wesley Cheng's avatar
      usb: dwc3: gadget: Replace list_for_each_entry_safe() if using giveback · bf594d1d
      Wesley Cheng authored
      The list_for_each_entry_safe() macro saves the current item (n) and
      the item after (n+1), so that n can be safely removed without
      corrupting the list.  However, when traversing the list and removing
      items using gadget giveback, the DWC3 lock is briefly released,
      allowing other routines to execute.  There is a situation where, while
      items are being removed from the cancelled_list using
      dwc3_gadget_ep_cleanup_cancelled_requests(), the pullup disable
      routine is running in parallel (due to UDC unbind).  As the cleanup
      routine removes n, and the pullup disable removes n+1, once the
      cleanup retakes the DWC3 lock, it references a request who was already
      removed/handled.  With list debug enabled, this leads to a panic.
      Ensure all instances of the macro are replaced where gadget giveback
      is used.
      
      Example call stack:
      
      Thread#1:
      __dwc3_gadget_ep_set_halt() - CLEAR HALT
        -> dwc3_gadget_ep_cleanup_cancelled_requests()
          ->list_for_each_entry_safe()
          ->dwc3_gadget_giveback(n)
            ->dwc3_gadget_del_and_unmap_request()- n deleted[cancelled_list]
            ->spin_unlock
            ->Thread#2 executes
            ...
          ->dwc3_gadget_giveback(n+1)
            ->Already removed!
      
      Thread#2:
      dwc3_gadget_pullup()
        ->waiting for dwc3 spin_lock
        ...
        ->Thread#1 released lock
        ->dwc3_stop_active_transfers()
          ->dwc3_remove_requests()
            ->fetches n+1 item from cancelled_list (n removed by Thread#1)
            ->dwc3_gadget_giveback()
              ->dwc3_gadget_del_and_unmap_request()- n+1 deleted[cancelled_list]
              ->spin_unlock
      
      Fixes: d4f1afe5 ("usb: dwc3: gadget: move requests to cancelled_list")
      Signed-off-by: default avatarWesley Cheng <quic_wcheng@quicinc.com>
      Link: https://lore.kernel.org/r/20220414183521.23451-1-quic_wcheng@quicinc.comSigned-off-by: default avatarGreg Kroah-Hartman <gregkh@linuxfoundation.org>
      bf594d1d
    • Wesley Cheng's avatar
      usb: dwc3: EP clear halt leading to clearing of delayed_status · 2840d6df
      Wesley Cheng authored
      The usb_ep_clear_halt() API can be called from the function driver, and
      translates to dwc3_gadget_ep_set_halt().  This routine is shared with when
      the host issues a clear feature ENDPOINT_HALT, and is differentiated by the
      protocol argument.  If the following sequence occurs, there can be a
      situation where the delayed_status flag is improperly cleared for the wrong
      SETUP transaction:
      
      1. Vendor specific control transfer returns USB_GADGET_DELAYED_STATUS.
      2. DWC3 gadget sets dwc->delayed_status to '1'.
      3. Another function driver issues a usb_ep_clear_halt() call.
      4. DWC3 gadget issues dwc3_stop_active_transfer() and sets
         DWC3_EP_PENDING_CLEAR_STALL.
      5. EP command complete interrupt triggers for the end transfer, and
         dwc3_ep0_send_delayed_status() is allowed to run, as delayed_status
         is '1' due to step#1.
      6. STATUS phase is sent, and delayed_status is cleared.
      7. Vendor specific control transfer is finished being handled, and issues
         usb_composite_setup_continue().  This results in queuing of a data
         phase.
      
      Cache the protocol flag so that DWC3 gadget is aware of when the clear halt
      is due to a SETUP request from the host versus when it is sourced from a
      function driver.  This allows for the EP command complete interrupt to know
      if it needs to issue a delayed status phase.
      Signed-off-by: default avatarWesley Cheng <quic_wcheng@quicinc.com>
      Link: https://lore.kernel.org/r/20220414073902.21960-1-quic_wcheng@quicinc.comSigned-off-by: default avatarGreg Kroah-Hartman <gregkh@linuxfoundation.org>
      2840d6df
  2. 22 Apr, 2022 1 commit
  3. 21 Apr, 2022 35 commits