Re: [PATCH v18 0/4] Introduce usb charger framework to deal with the usb gadget power negotation

2016-10-27 Thread Baolin Wang
Hi Felipe,

On 19 October 2016 at 10:37, Baolin Wang <baolin.w...@linaro.org> wrote:
> Currently the Linux kernel does not provide any standard integration of this
> feature that integrates the USB subsystem with the system power regulation
> provided by PMICs meaning that either vendors must add this in their kernels
> or USB gadget devices based on Linux (such as mobile phones) may not behave
> as they should. Thus provide a standard framework for doing this in kernel.
>
> Now introduce one user with wm831x_power to support and test the usb charger,
> which is pending testing. Moreover there may be other potential users will use
> it in future.
>
> Changes since v17:
>  - Remove goto section in usb_charger_register() function.
>  - Remove 'extern' in charger.h file.
>  - Move the kfree() to usb_charger_exit() function.
>
> Changes since v16:
>  - Modify the charger current range with introducing the maximum and minimum
>  current.
>  - Remove the getting charger type method from power supply.
>  - Add the getting charger type method from extcon system.
>  - Introduce new usb_charger_get_current() API for users to get the maximum 
> and
>  minimum current.
>  - Rename some APIs and other optimization.
>
> Changes since v15:
>  - Add charger state checking to avoid sending out duplicate notifies to 
> users.
>  - Add one work to notify power users the current has been changed.
>
> Changes since v14:
>  - Add kernel documentation for struct usb_cahrger.
>  - Remove some redundant WARN() functions.
>
> Changes since v13:
>  - Remove the charger checking in usb_gadget_vbus_draw() function.
>  - Rename some functions in charger.c file.
>  - Rebase on git://git.kernel.org/pub/scm/linux/kernel/git/balbi/usb.git 
> tags/usb-for-v4.8
>
> Changes since v12:
>  - Remove the class and device things.
>  - Link usb charger to udc-core.ko.
>  - Create one "charger" subdirectory which holds all charger-related 
> attributes.
>
> Changes since v11:
>  - Reviewed and tested by Li Jun.
>
> Changes since v10:
>  - Introduce usb_charger_get_state() function to check charger state.
>  - Remove the mutex lock in usb_charger_set_cur_limit_by_type() function
>  in case will be issued in atomic context.

Could you apply this patchset into your branch if there are no other
comments? Thanks.

>
> Baolin Wang (4):
>   usb: gadget: Introduce the usb charger framework
>   usb: gadget: Support for the usb charger framework
>   usb: gadget: Integrate with the usb gadget supporting for usb charger
>   power: wm831x_power: Support USB charger current limit management
>
>  drivers/power/wm831x_power.c |   75 
>  drivers/usb/gadget/Kconfig   |8 +
>  drivers/usb/gadget/udc/Makefile  |1 +
>  drivers/usb/gadget/udc/charger.c |  877 
> ++
>  drivers/usb/gadget/udc/core.c|   19 +-
>  include/linux/mfd/wm831x/pdata.h |3 +
>  include/linux/usb/charger.h  |  185 
>  include/linux/usb/gadget.h   |3 +
>  include/uapi/linux/usb/charger.h |   31 ++
>  9 files changed, 1201 insertions(+), 1 deletion(-)
>  create mode 100644 drivers/usb/gadget/udc/charger.c
>  create mode 100644 include/linux/usb/charger.h
>  create mode 100644 include/uapi/linux/usb/charger.h
>
> --
> 1.7.9.5
>



-- 
Baolin.wang
Best Regards
--
To unsubscribe from this list: send the line "unsubscribe linux-usb" in
the body of a message to majord...@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html


Re: [PATCH v18 0/4] Introduce usb charger framework to deal with the usb gadget power negotation

2016-11-07 Thread Baolin Wang
On 3 November 2016 at 09:25, NeilBrown <ne...@suse.com> wrote:
> On Tue, Nov 01 2016, Baolin Wang wrote:
>
>
>>> So I won't be responding on this topic any further until I see a genuine
>>> attempt to understand and resolve the inconsistencies with
>>> usb_register_notifier().
>>
>> Any better solution?
>
> I'm not sure exactly what you are asking, so I'll assume you are asking
> the question I want to answer :-)
>
> 1/ Liase with the extcon developers to resolve the inconsistencies
>   with USB connector types.
>   e.g. current there is both "EXTCON_USB" and "EXTCON_CHG_USB_SDP"
>   which both seem to suggest a standard downstream port.  There is no
>   documentation describing how these relate, and no consistent practice
>   to copy.
>   I suspect the intention is that
> EXTCON_USB and EXTCON_USB_HOST indicated that data capabilities of
> the cable, while EXTCON_CHG_USB* indicate the power capabilities of
> the cable.
> So EXTCON_CHG_USB_SDP should always appear together with EXTCON_USB
> while EXTCON_CHG_USB_DCP would not, and EXTCON_CHG_USB_ACA
> would normally appear with EXTCON_USB_HOST (I think).
>   Some drivers follow this model, particularly extcon-max14577.c
>   but it is not consistent.
>
>   This policy should be well documented and possibly existing drivers
>   should be updated to follow it.
>
>   At the same time it would make sense to resolve EXTCON_CHG_USB_SLOW
>   and EXTCON_CHG_USB_FAST.  These names don't mean much.
>   They were recently removed from drivers/power/axp288_charger.c
>   which is good, but are still used in drivers/extcon/extcon-max*
>   Possibly they should be changed to names from the standard, or
>   possibly they should be renamed to identify the current they are
>   expected to provide. e.g. EXTCON_CHG_USB_500MA and EXTCON_CHG_USB_1A
>
> 2/ Change all usb phys to register an extcon and to send appropriate
>notifications.  Many already do, but I don't think it is universal.
>It is probable that the extcon should be registered using common code
>instead of each phy driver having its own
>extcon_get_edev_by_phandle()
>or whatever.
>If the usb phy driver needs to look at battery charger registers to
>know what sort of cable was connected (which I believe is the case
>for the chips you are interested in), then it should do that.
>
> 3/ Currently some USB controllers discover that a cable was connected by
>listening on an extcon, and some by registering for a usb_notifier
>(described below) ... though there seem to only be 2 left which do that.
>Now that all USB phys send connection information via extcon (see 2),
>the USB controllers should be changed to all find out about the cable
>using extcon.
>
> 4/ struct usb_phy contains:
> /* for notification of usb_phy_events */
> struct atomic_notifier_head notifier;
>
>   This is used inconsistently.  Sometimes the argument passed
>   is NULL, sometimes it is a pointer to 'vbus_draw' - the current
>   limited negotiated via USB, sometimes it is a pointer the the gadget
>   though as far as I can tell, that last one is never used.
>
>   This should be changed to be consistent.  This notifier is no longer
>   needed to tell the USB controller that a cable was connected (extcon
>   now does that, see 3) so it is only used to communicate the
>   'vbus_draw' information.
>   So it should be changed to *only* send a notification when vbus_draw
>   is known, and it should carry that information.
>   This should probably be done in common code, and removed
>   from individual drivers.
>
> 5/ Now that all cable connection notifications are sent over extcon and
>all vbus_draw notifications are sent over the usb_phy notifier, write
>some support code that a power supply client can use to be told what
>power is available.
>e.g. a battery charger driver would call:
>register_power_client(.)
>or similar, providing a phandle (or similar) for the usb phy and a
>function to call back when the available current changes (or maybe a
>work_struct containing the function pointer)
>
>register_power_client() would then register with extcon and separately
>with the usb_phy notifier.  When the different events arrive it
>calculates what ranges of currents are expected and calls the
>call-back function with those details.
>
> 6/ Any battery charger that needs to know the available current can now
>call register_power_client() and get the information delivered.

I agree with your most opinions, but these are optimization. Firstly I
think we should upstream the USB charger driver. Wha

Re: [PATCH v4] USB hub_probe: rework ugly goto-into-compound-statement

2016-11-09 Thread Baolin Wang
Hi,

On 9 November 2016 at 23:35, Eugene Korenevsky  wrote:
> Rework smelling code (goto inside compound statement). Perhaps this is
> legacy. Anyway such code is not appropriate for Linux kernel.
>
> Changes since v3: fix typo
> Changes since v2: extract the code to static function
> Changes since v1: fix spaces instead of tab, add missing 'Signed-off-by'
>
> Signed-off-by: Eugene Korenevsky 
> ---
>  drivers/usb/core/hub.c | 35 ++-
>  1 file changed, 18 insertions(+), 17 deletions(-)
>
> diff --git a/drivers/usb/core/hub.c b/drivers/usb/core/hub.c
> index cbb1467..b770c8d 100644
> --- a/drivers/usb/core/hub.c
> +++ b/drivers/usb/core/hub.c
> @@ -1722,10 +1722,25 @@ static void hub_disconnect(struct usb_interface *intf)
> kref_put(>kref, hub_release);
>  }
>
> +static int hub_check_descriptor_sanity(struct usb_host_interface *desc)
> +{
> +   /* Some hubs have a subclass of 1, which AFAICT according to the */
> +   /*  specs is not defined, but it works */
> +   if (desc->desc.bInterfaceSubClass != 0 &&
> +   desc->desc.bInterfaceSubClass != 1)
> +   return 0;
> +
> +   /* Multiple endpoints? What kind of mutant ninja-hub is this? */
> +   if (desc->desc.bNumEndpoints != 1)
> +   return 0;

We usually return 0 as successful result, can you return kernel error
number if we check the descriptor failed? Or change the return value
of the function as bool type.

> +
> +   /* If it's not an interrupt in endpoint, we'd better punt! */
> +   return usb_endpoint_is_int_in(>endpoint[0].desc);
> +}
> +
>  static int hub_probe(struct usb_interface *intf, const struct usb_device_id 
> *id)
>  {
> struct usb_host_interface *desc;
> -   struct usb_endpoint_descriptor *endpoint;
> struct usb_device *hdev;
> struct usb_hub *hub;
>
> @@ -1800,25 +1815,11 @@ static int hub_probe(struct usb_interface *intf, 
> const struct usb_device_id *id)
> }
>  #endif
>
> -   /* Some hubs have a subclass of 1, which AFAICT according to the */
> -   /*  specs is not defined, but it works */
> -   if ((desc->desc.bInterfaceSubClass != 0) &&
> -   (desc->desc.bInterfaceSubClass != 1)) {
> -descriptor_error:
> +   if (!hub_check_descriptor_sanity(desc)) {
> dev_err(>dev, "bad descriptor, ignoring hub\n");
> return -EIO;
> }
>
> -   /* Multiple endpoints? What kind of mutant ninja-hub is this? */
> -   if (desc->desc.bNumEndpoints != 1)
> -   goto descriptor_error;
> -
> -   endpoint = >endpoint[0].desc;
> -
> -   /* If it's not an interrupt in endpoint, we'd better punt! */
> -   if (!usb_endpoint_is_int_in(endpoint))
> -   goto descriptor_error;
> -
> /* We found a hub */
> dev_info(>dev, "USB hub found\n");
>
> @@ -1845,7 +1846,7 @@ static int hub_probe(struct usb_interface *intf, const 
> struct usb_device_id *id)
> if (id->driver_info & HUB_QUIRK_CHECK_PORT_AUTOSUSPEND)
> hub->quirk_check_port_auto_suspend = 1;
>
> -   if (hub_configure(hub, endpoint) >= 0)
> +   if (hub_configure(hub, >endpoint[0].desc) >= 0)
> return 0;
>
> hub_disconnect(intf);
> --
> 2.10.2
>
>
> --
> To unsubscribe from this list: send the line "unsubscribe linux-usb" in
> the body of a message to majord...@vger.kernel.org
> More majordomo info at  http://vger.kernel.org/majordomo-info.html



-- 
Baolin.wang
Best Regards
--
To unsubscribe from this list: send the line "unsubscribe linux-usb" in
the body of a message to majord...@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html


Re: [PATCH v3 5/6] usb: dwc3: use bus->sysdev for DMA configuration

2016-11-10 Thread Baolin Wang
Hi,

On 10 November 2016 at 16:20, Sriram Dash <sriram.d...@nxp.com> wrote:
> From: Arnd Bergmann <a...@arndb.de>
>
> The dma ops for dwc3 devices are not set properly. So, use a
> physical device sysdev, which will be inherited from parent,
> to set the hardware / firmware parameters like dma.
>
> Signed-off-by: Arnd Bergmann <a...@arndb.de>
> Signed-off-by: Sriram Dash <sriram.d...@nxp.com>
> ---
> Changes in v3:
>   - No update
>
> Changes in v2:
>   - integrate dwc3 driver changes together
>
>  drivers/usb/dwc3/core.c   | 28 +++-
>  drivers/usb/dwc3/core.h   |  1 +
>  drivers/usb/dwc3/ep0.c|  8 
>  drivers/usb/dwc3/gadget.c | 37 +++--
>  drivers/usb/dwc3/host.c   | 12 
>  5 files changed, 43 insertions(+), 43 deletions(-)
>

Tested on my dwc3 platform, it can work well as host or gadget. You
can add my tested tag for patch 1/4/5 after fixing Felipe's issue.
Tested-by: Baolin Wang <baolin.w...@linaro.org>

-- 
Baolin.wang
Best Regards
--
To unsubscribe from this list: send the line "unsubscribe linux-usb" in
the body of a message to majord...@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html


Re: [PATCH v18 0/4] Introduce usb charger framework to deal with the usb gadget power negotation

2016-11-10 Thread Baolin Wang
Hi

On 8 November 2016 at 04:36, NeilBrown <ne...@suse.com> wrote:
> On Mon, Nov 07 2016, Baolin Wang wrote:
>
>> On 3 November 2016 at 09:25, NeilBrown <ne...@suse.com> wrote:
>>> On Tue, Nov 01 2016, Baolin Wang wrote:
>>
>> I agree with your most opinions, but these are optimization.
>
> I see them as bug fixes, not optimizations.
>
>>  Firstly I
>> think we should upstream the USB charger driver.
>
> I think you missed the point.  The point is that we don't *need* your
> "USB charger driver" because all the infrastructure we need is *already*
> present in the kernel.  It is buggy and not used uniformly, and could
> usefully be polished and improved.  But the structure is already
> present.
>
> If everyone just added new infrastructure when they didn't like, or
> didn't understand, what was already present, the kernel would become
> like the Mad Hatter's tea party, full of dirty dishes.
>
>>  What I want to ask is
>> how can we notify power driver if we don't set the
>> usb_register_notifier(), then I think you give the answer is: power
>> driver can register by 'struct usb_phy->notifier'. But why usb phy
>> should notify the power driver how much current should be drawn, and I
>> still think we should notify the current in usb charger driver which
>> is better, and do not need to notify current for power driver in usb
>> phy driver.
>
> I accept that it isn't clear that the phy *should* be involved in
> communicating the negotiated power availability, but nor is it clear
> that it shouldn't.  The power does travel through the physical
> interface, so physically it plays a role.
>
> But more importantly, it already *does* get told (in some cases).
> There is an interface "usb_phy_set_power()" which exists explicitly to
> tell the phy what power has been negotiated.  Given that infrastructure
> exists and works, it make sense to use it.
>
> If you think it is a broken design and should be removed, then fine:
> make a case for that.  Examine the history.  Make sure you know why it
> is there (or make sure that information cannot be found), and then
> present a case as to why it should be removed and replaced with
> something else.  But don't just leave it there and pretend it doesn't
> exist and create something similar-but-different and hope people will
> know why yours is better.  That way lies madness.

Like Peter said, it is not only PHY can detect the USB charger type,
which means there are other places can detect the charger type.
Second, some controller need to detect the charger type manually which
USB phy did not support. Third, it did not handle what current should
be drawn in USB phy. Fourth, we need integrate all charger plugin/out
event in one framework, not from extcon, maybe type-c in future. In a
word, we need one standard integration of this feature we need, though
like you said we should do some clean up or fix to make it better.

-- 
Baolin.wang
Best Regards
--
To unsubscribe from this list: send the line "unsubscribe linux-usb" in
the body of a message to majord...@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html


Re: usb_ep_{dis,en}able() calling context (was: Re: [PATCH 2/3] usb: dwc3: gadget: wait for End Transfer to complete)

2016-10-18 Thread Baolin Wang
Hi,

On 18 October 2016 at 16:21, Felipe Balbi <felipe.ba...@linux.intel.com> wrote:
>
> Hi,
>
> Baolin Wang <baolin.w...@linaro.org> writes:
>> Sure. The problem I met was, when we change the USB function with
>> configfs frequently, sometimes it will hang the system to crash. The
>> reason is,  we will start end transfer command when disable the
>> endpoint, but sometimes the end transfer command complete event comes
>> after we have freed the gadget irq (since the xHCI will share the same
>> interrupt number with gadget, thus when free the gadget irq, it will
>> not shutdown this gadget irq line), it will trigger the interrupt line
>> all the time.
>
> okay, thanks for describing it again. Another option would be to only
> wait_for_completion() before calling free_irq() is any endpoint has
> END_TRANSFER_PENDING flag set. Something like below:

I tested below patch, but it failed and I still met the kernel crash
with changing USB function.

>
> diff --git a/drivers/usb/dwc3/core.h b/drivers/usb/dwc3/core.h
> index 5fc437021ac7..0cb3b78d28b7 100644
> --- a/drivers/usb/dwc3/core.h
> +++ b/drivers/usb/dwc3/core.h
> @@ -26,6 +26,7 @@
>  #include 
>  #include 
>  #include 
> +#include 
>
>  #include 
>  #include 
> @@ -505,6 +506,7 @@ struct dwc3_event_buffer {
>   * @endpoint: usb endpoint
>   * @pending_list: list of pending requests for this endpoint
>   * @started_list: list of started requests on this endpoint
> + * @wait_end_transfer: wait_queue_head_t for waiting on End Transfer complete
>   * @lock: spinlock for endpoint request queue traversal
>   * @regs: pointer to first endpoint register
>   * @trb_pool: array of transaction buffers
> @@ -530,6 +532,8 @@ struct dwc3_ep {
> struct list_headpending_list;
> struct list_headstarted_list;
>
> +   wait_queue_head_t   wait_end_transfer;
> +
> spinlock_t  lock;
> void __iomem*regs;
>
> @@ -546,6 +550,7 @@ struct dwc3_ep {
>  #define DWC3_EP_BUSY   (1 << 4)
>  #define DWC3_EP_PENDING_REQUEST(1 << 5)
>  #define DWC3_EP_MISSED_ISOC(1 << 6)
> +#define DWC3_EP_END_TRANSFER_PENDING (1 << 7)
>
> /* This last one is specific to EP0 */
>  #define DWC3_EP0_DIR_IN(1 << 31)
> @@ -1050,6 +1055,9 @@ struct dwc3_event_depevt {
>  #define DEPEVT_TRANSFER_BUS_EXPIRY 2
>
> u32 parameters:16;
> +
> +/* For Command Complete Events */
> +#define DEPEVT_PARAMETER_CMD(n) (((n) & (0xf << 8)) >> 8)
>  } __packed;
>
>  /**
> diff --git a/drivers/usb/dwc3/gadget.c b/drivers/usb/dwc3/gadget.c
> index 3b53a5714df4..5929a75b3455 100644
> --- a/drivers/usb/dwc3/gadget.c
> +++ b/drivers/usb/dwc3/gadget.c
> @@ -598,6 +598,8 @@ static int __dwc3_gadget_ep_enable(struct dwc3_ep *dep,
> reg |= DWC3_DALEPENA_EP(dep->number);
> dwc3_writel(dwc->regs, DWC3_DALEPENA, reg);
>
> +   init_waitqueue_head(>wait_end_transfer);
> +
> if (usb_endpoint_xfer_control(desc))
> return 0;
>
> @@ -1783,12 +1785,28 @@ static int dwc3_gadget_start(struct usb_gadget *g,
>
>  static void __dwc3_gadget_stop(struct dwc3 *dwc)
>  {
> +   int epnum;
> +
> if (pm_runtime_suspended(dwc->dev))
> return;
>
> dwc3_gadget_disable_irq(dwc);
> __dwc3_gadget_ep_disable(dwc->eps[0]);
> __dwc3_gadget_ep_disable(dwc->eps[1]);
> +
> +   for (epnum = 2; epnum < DWC3_ENDPOINTS_NUM; epnum++) {
> +   struct dwc3_ep  *dep = dwc->eps[epnum];
> +
> +   if (!(dep->flags & DWC3_EP_ENABLED))
> +   continue;

We should not check the DWC3_EP_ENABLED flag, since we will clear all
flags in __dwc3_gadget_ep_disable() after setting
DWC3_EP_END_TRANSFER_PENDING flags in dwc3_stop_active_transfer().

> +
> +   if (!(dep->flags & DWC3_EP_END_TRANSFER_PENDING))
> +   continue;

Ditto.

> +
> +   wait_event_lock_irq(dep->wait_end_transfer,
> +   !(dep->flags & DWC3_EP_END_TRANSFER_PENDING),
> +   dwc->lock);
> +   }
>  }
>
>  static int dwc3_gadget_stop(struct usb_gadget *g)
> @@ -2171,6 +2189,7 @@ static void dwc3_endpoint_interrupt(struct dwc3 *dwc,
>  {
> struct dwc3_ep  *dep;
> u8  epnum = event->endpoint_number;
> +   u8  cmd;

Here we should add below modificatio

Re: usb_ep_{dis,en}able() calling context (was: Re: [PATCH 2/3] usb: dwc3: gadget: wait for End Transfer to complete)

2016-10-18 Thread Baolin Wang
On 18 October 2016 at 16:21, Felipe Balbi <felipe.ba...@linux.intel.com> wrote:
>
> Hi,
>
> Baolin Wang <baolin.w...@linaro.org> writes:
>>> Alan Stern <st...@rowland.harvard.edu> writes:
>>>>> Baolin Wang <baolin.w...@linaro.org> writes:
>>>>> >> Felipe Balbi <felipe.ba...@linux.intel.com> writes:
>>>>> >>> Instead of just delaying for 100us, we should
>>>>> >>> actually wait for End Transfer Command Complete
>>>>> >>> interrupt before moving on. Note that this should
>>>>> >>> only be done if we're dealing with one of the core
>>>>> >>> revisions that actually require the interrupt before
>>>>> >>> moving on.
>>>>> >>>
>>>>> >>> Reported-by: Baolin Wang <baolin.w...@linaro.org>
>>>>> >>> Signed-off-by: Felipe Balbi <felipe.ba...@linux.intel.com>
>>>>> >>
>>>>> >> I've updated this one in order to fix the comment we had about delaying
>>>>> >> 100us. No further changes were made, only the comment. Here it is:
>>>>> >>
>>>>> >> 8<
>>>>> >> From f3fa94f3171709f787a30e3c5ce69a668960b66e Mon Sep 17 00:00:00 2001
>>>>> >> From: Felipe Balbi <felipe.ba...@linux.intel.com>
>>>>> >> Date: Thu, 13 Oct 2016 14:09:47 +0300
>>>>> >> Subject: [PATCH v2] usb: dwc3: gadget: wait for End Transfer to 
>>>>> >> complete
>>>>> >>
>>>>> >> Instead of just delaying for 100us, we should
>>>>> >> actually wait for End Transfer Command Complete
>>>>> >> interrupt before moving on. Note that this should
>>>>> >> only be done if we're dealing with one of the core
>>>>> >> revisions that actually require the interrupt before
>>>>> >> moving on.
>>>>> >>
>>>>> >> Reported-by: Baolin Wang <baolin.w...@linaro.org>
>>>>> >> Signed-off-by: Felipe Balbi <felipe.ba...@linux.intel.com>
>>>>> >
>>>>> > From my testing, there are still some problems caused by the nested
>>>>> > lock, at lease I found 2 functions will issue the usb_ep_disable()
>>>>> > function with spinlock:
>>>>>
>>>>> Thanks for testing. Seems like I really need to revisit locking in the
>>>>> entire gadget API. In either case, we need to have a larger discussion
>>>>> about this situation.
>>>>>
>>>>> IMO, usb_ep_disable() and usb_ep_enable() should only be callable from
>>>>> process context, but that has never been a requirement before. Still,
>>>>> it's not far-fetched to assume that a controller (such as dwc3, but
>>>>> probably others) might sleep while cancelling a transfer because they
>>>>> need to wait for an Interrupt.
>>>>>
>>>>> In fact, we know of two controllers that need this: dwc3 and dwc3.1.
>>>>
>>>> It's not clear that this should be the deciding factor.  That is, does
>>>> usb_ep_disable() need to wait until all the endpoint's outstanding
>>>> transfers have been completed before it returns?  I don't think it
>>>> does.
>>>
>>> not all, no. And, frankly, this is really only a problem if we're
>>> unregistering a gadget while there are still pending transfers.
>>>
>>> The original problem statement is that we unregister a gadget, issue End
>>> Transfer, but CmdCompletion for the EndTransfer comes way too
>>> late. Baolin, can you clarify again what happens when the IRQ comes
>>> late?
>>
>> Sure. The problem I met was, when we change the USB function with
>> configfs frequently, sometimes it will hang the system to crash. The
>> reason is,  we will start end transfer command when disable the
>> endpoint, but sometimes the end transfer command complete event comes
>> after we have freed the gadget irq (since the xHCI will share the same
>> interrupt number with gadget, thus when free the gadget irq, it will
>> not shutdown this gadget irq line), it will trigger the interrupt line
>> all the time.
>
> okay, thanks for describing it again. Another option would be to only
> wait_for_completion() before cal

Re: usb_ep_{dis,en}able() calling context (was: Re: [PATCH 2/3] usb: dwc3: gadget: wait for End Transfer to complete)

2016-10-18 Thread Baolin Wang
Hi,

On 18 October 2016 at 15:19, Felipe Balbi <felipe.ba...@linux.intel.com> wrote:
>
> Hi,
>
> Alan Stern <st...@rowland.harvard.edu> writes:
>>> Baolin Wang <baolin.w...@linaro.org> writes:
>>> >> Felipe Balbi <felipe.ba...@linux.intel.com> writes:
>>> >>> Instead of just delaying for 100us, we should
>>> >>> actually wait for End Transfer Command Complete
>>> >>> interrupt before moving on. Note that this should
>>> >>> only be done if we're dealing with one of the core
>>> >>> revisions that actually require the interrupt before
>>> >>> moving on.
>>> >>>
>>> >>> Reported-by: Baolin Wang <baolin.w...@linaro.org>
>>> >>> Signed-off-by: Felipe Balbi <felipe.ba...@linux.intel.com>
>>> >>
>>> >> I've updated this one in order to fix the comment we had about delaying
>>> >> 100us. No further changes were made, only the comment. Here it is:
>>> >>
>>> >> 8<
>>> >> From f3fa94f3171709f787a30e3c5ce69a668960b66e Mon Sep 17 00:00:00 2001
>>> >> From: Felipe Balbi <felipe.ba...@linux.intel.com>
>>> >> Date: Thu, 13 Oct 2016 14:09:47 +0300
>>> >> Subject: [PATCH v2] usb: dwc3: gadget: wait for End Transfer to complete
>>> >>
>>> >> Instead of just delaying for 100us, we should
>>> >> actually wait for End Transfer Command Complete
>>> >> interrupt before moving on. Note that this should
>>> >> only be done if we're dealing with one of the core
>>> >> revisions that actually require the interrupt before
>>> >> moving on.
>>> >>
>>> >> Reported-by: Baolin Wang <baolin.w...@linaro.org>
>>> >> Signed-off-by: Felipe Balbi <felipe.ba...@linux.intel.com>
>>> >
>>> > From my testing, there are still some problems caused by the nested
>>> > lock, at lease I found 2 functions will issue the usb_ep_disable()
>>> > function with spinlock:
>>>
>>> Thanks for testing. Seems like I really need to revisit locking in the
>>> entire gadget API. In either case, we need to have a larger discussion
>>> about this situation.
>>>
>>> IMO, usb_ep_disable() and usb_ep_enable() should only be callable from
>>> process context, but that has never been a requirement before. Still,
>>> it's not far-fetched to assume that a controller (such as dwc3, but
>>> probably others) might sleep while cancelling a transfer because they
>>> need to wait for an Interrupt.
>>>
>>> In fact, we know of two controllers that need this: dwc3 and dwc3.1.
>>
>> It's not clear that this should be the deciding factor.  That is, does
>> usb_ep_disable() need to wait until all the endpoint's outstanding
>> transfers have been completed before it returns?  I don't think it
>> does.
>
> not all, no. And, frankly, this is really only a problem if we're
> unregistering a gadget while there are still pending transfers.
>
> The original problem statement is that we unregister a gadget, issue End
> Transfer, but CmdCompletion for the EndTransfer comes way too
> late. Baolin, can you clarify again what happens when the IRQ comes
> late?

Sure. The problem I met was, when we change the USB function with
configfs frequently, sometimes it will hang the system to crash. The
reason is,  we will start end transfer command when disable the
endpoint, but sometimes the end transfer command complete event comes
after we have freed the gadget irq (since the xHCI will share the same
interrupt number with gadget, thus when free the gadget irq, it will
not shutdown this gadget irq line), it will trigger the interrupt line
all the time.

>
>>> I wonder if there are any other controllers with this
>>> requirement. Either way, We should also consider if there are any strong
>>> reasons to call usb_ep_disable() with interrupts disabled and locks held
>>> considering that UDC _must_ call ->complete() for each and every
>>> request.
>>>
>>> If we go ahead with this, it'll mean a rather large series (again) to
>>> fix all the calling semantics in every single gadget driver for both
>>> usb_ep_enable() and usb_ep_disable(). Then, making sure all UDC drivers
>>> respect the requirement, then we update documentation about the
>>> functions and add might_sleep() to their implementation i

Re: usb_ep_{dis,en}able() calling context (was: Re: [PATCH 2/3] usb: dwc3: gadget: wait for End Transfer to complete)

2016-10-20 Thread Baolin Wang
Hi,

On 19 October 2016 at 18:09, Felipe Balbi <felipe.ba...@linux.intel.com> wrote:
>
> Hi,
>
> Baolin Wang <baolin.w...@linaro.org> writes:
>>
>> We should not check the DWC3_EP_ENABLED flag, since we will clear all
>> flags in __dwc3_gadget_ep_disable() after setting
>> DWC3_EP_END_TRANSFER_PENDING flags in dwc3_stop_active_transfer().
>
> good catch.
>
>>
>>> +
>>> +   if (!(dep->flags & DWC3_EP_END_TRANSFER_PENDING))
>>> +   continue;
>>
>> Ditto.
>
> yeah, END_TRANSFER_PENDING should only be cleared by command completion,
> so ep_disable needs to be patched.
>
>>> +
>>> +   wait_event_lock_irq(dep->wait_end_transfer,
>>> +   !(dep->flags & 
>>> DWC3_EP_END_TRANSFER_PENDING),
>>> +   dwc->lock);
>>> +   }
>>>  }
>>>
>>>  static int dwc3_gadget_stop(struct usb_gadget *g)
>>> @@ -2171,6 +2189,7 @@ static void dwc3_endpoint_interrupt(struct dwc3 *dwc,
>>>  {
>>> struct dwc3_ep  *dep;
>>> u8  epnum = event->endpoint_number;
>>> +   u8  cmd;
>>
>> Here we should add below modification, or the event can not be handled.
>>
>> - if (!(dep->flags & DWC3_EP_ENABLED))
>> + if (!(dep->flags & DWC3_EP_ENABLED) &&
>> + !(dep->flags & DWC3_EP_END_TRANSFER_PENDING))
>> return;
>
> this seems unnecessary to me. The only interrupt with a disabled
> endpoint should be due to END_TRANSFER cmd completion. In fact, I'm now
> thinking that maybe usb_ep_disable() should also block until EndTransfer
> completes.
>
> This would means replacing wake_up() with wake_up_all()
>
>>> I'll run some tests with this in a couple hours.
>>
>> I would like to send out new version based on my original patch
>> according to your suggestion, or you can send out new version I can
>> help to test. Thanks.
>
> From ce24ab50d57a18287a99ea776e9bdc7d5cfd282c Mon Sep 17 00:00:00 2001
> From: Baolin Wang <baolin.w...@linaro.org>
> Date: Thu, 13 Oct 2016 14:09:47 +0300
> Subject: [PATCH] usb: dwc3: gadget: wait for End Transfer to complete
>
> Instead of just delaying for 100us, we should
> actually wait for End Transfer Command Complete
> interrupt before moving on. Note that this should
> only be done if we're dealing with one of the core
> revisions that actually require the interrupt before
> moving on.
>
> [ felipe.ba...@linux.intel.com: minor improvements ]
>
> NYET-Signed-off-by: Baolin Wang <baolin.w...@linaro.org>
> Signed-off-by: Felipe Balbi <felipe.ba...@linux.intel.com>
> ---
>  drivers/usb/dwc3/core.h   |  8 
>  drivers/usb/dwc3/gadget.c | 40 +---
>  2 files changed, 45 insertions(+), 3 deletions(-)
>
> diff --git a/drivers/usb/dwc3/core.h b/drivers/usb/dwc3/core.h
> index 5fc437021ac7..0cb3b78d28b7 100644
> --- a/drivers/usb/dwc3/core.h
> +++ b/drivers/usb/dwc3/core.h
> @@ -26,6 +26,7 @@
>  #include 
>  #include 
>  #include 
> +#include 
>
>  #include 
>  #include 
> @@ -505,6 +506,7 @@ struct dwc3_event_buffer {
>   * @endpoint: usb endpoint
>   * @pending_list: list of pending requests for this endpoint
>   * @started_list: list of started requests on this endpoint
> + * @wait_end_transfer: wait_queue_head_t for waiting on End Transfer complete
>   * @lock: spinlock for endpoint request queue traversal
>   * @regs: pointer to first endpoint register
>   * @trb_pool: array of transaction buffers
> @@ -530,6 +532,8 @@ struct dwc3_ep {
> struct list_headpending_list;
> struct list_headstarted_list;
>
> +   wait_queue_head_t   wait_end_transfer;
> +
> spinlock_t  lock;
> void __iomem*regs;
>
> @@ -546,6 +550,7 @@ struct dwc3_ep {
>  #define DWC3_EP_BUSY   (1 << 4)
>  #define DWC3_EP_PENDING_REQUEST(1 << 5)
>  #define DWC3_EP_MISSED_ISOC(1 << 6)
> +#define DWC3_EP_END_TRANSFER_PENDING (1 << 7)
>
> /* This last one is specific to EP0 */
>  #define DWC3_EP0_DIR_IN(1 << 31)
> @@ -1050,6 +1055,9 @@ struct dwc3_event_depevt {
>  #define DEPEVT_TRANSFER_BUS_EXPIRY 2
>
> u32 parameters:16;
> +
> +/* For Command Complete Events */
> +#define DEPEVT_PARAMETER_CMD(n) (((n) & (0xf << 8)) >> 8)
>  } __packed;
>
>  /**
> diff --git a/drivers/u

Re: [PATCH v2] usb: dwc3: gadget: Wait for end transfer complete before free irq

2016-10-14 Thread Baolin Wang
Hi Felipe,

On 14 October 2016 at 15:46, Felipe Balbi <ba...@kernel.org> wrote:
>
> Hi,
>
> Baolin Wang <baolin.w...@linaro.org> writes:
>>>>>>>>>> I see what the problem is. Databook tells us we *must* set CMDIOC 
>>>>>>>>>> when
>>>>>>>>>> issuing EndTransfer command and we should always wait for Command
>>>>>>>>>> Complete IRQ. However, we took a shortcut and just delayed for 100us
>>>>>>>>>> after issuing End Transfer.
>>>>>>>>>
>>>>>>>>> Yes, but 100us delay is not enough in some scenarios, like changing
>>>>>>>>> function with configfs frequently, we will met problems.
>>>>>>>>
>>>>>>>> heh, 100us *is* enough. However we still get an IRQ because we 
>>>>>>>> requested
>>>>>>>> for it. If you want to fix this, then you need to find a way to get rid
>>>>>>>> of that 100us udelay() and add a proper wait_for_completion() to delay
>>>>>>>> execution until command complete IRQ fires up.
>>>>>>>
>>>>>>> I haven't tested this yet, but it shows the idea (I think we might still
>>>>>>> have a race with ep_queue if we're still waiting for End Transfer, but
>>>>>>
>>>>>> Yes, maybe we need check DWC3_EP_END_TRANSFER_PENDING flag when
>>>>>> queuing one request.
>>>>>
>>>>> Yeah, I'll add that check later. I still need to make sure we would
>>>>> still try to kick any transfers that might have been queued while
>>>>> waiting for End Transfer Command Complete IRQ.
>>>>
>>>> OK. But I still worried if there are other races in some places which
>>>
>>> There are no other places where this needs to be sorted out.
>>>
>>>> is not easy to find out by testing. No introducing race condition
>>>> would be one better solution, anyway I would like to test the patch
>>>> you send out firstly.
>>>
>>> Right, but your patch was working around another problem, rather then
>>> fixing it.
>>>
>>> Here's another version which should make sure everything remains working
>>> as it should.
>>>
>>> 8<
>>> From 1f922a902a21d5cee32082be18bbfbf1d46137e4 Mon Sep 17 00:00:00 2001
>>> From: Felipe Balbi <felipe.ba...@linux.intel.com>
>>> Date: Thu, 13 Oct 2016 14:09:47 +0300
>>> Subject: [PATCH] usb: dwc3: gadget: wait for End Transfer to complete
>>>
>>> Instead of just delaying for 100us, we should
>>> actually wait for End Transfer Command Complete
>>> interrupt before moving on. Note that this should
>>> only be done if we're dealing with one of the core
>>> revisions that actually require the interrupt before
>>> moving on.
>>>
>>> Reported-by: Baolin Wang <baolin.w...@linaro.org>
>>> Signed-off-by: Felipe Balbi <felipe.ba...@linux.intel.com>
>>> ---
>>>  drivers/usb/dwc3/core.h   | 10 +-
>>>  drivers/usb/dwc3/gadget.c | 31 ---
>>>  2 files changed, 37 insertions(+), 4 deletions(-)
>>>
>>> diff --git a/drivers/usb/dwc3/core.h b/drivers/usb/dwc3/core.h
>>> index e878366ead00..cf495d932252 100644
>>> --- a/drivers/usb/dwc3/core.h
>>> +++ b/drivers/usb/dwc3/core.h
>>> @@ -26,6 +26,7 @@
>>>  #include 
>>>  #include 
>>>  #include 
>>> +#include 
>>>
>>>  #include 
>>>  #include 
>>> @@ -504,6 +505,7 @@ struct dwc3_event_buffer {
>>>   * @endpoint: usb endpoint
>>>   * @pending_list: list of pending requests for this endpoint
>>>   * @started_list: list of started requests on this endpoint
>>> + * @wait_end_transfer: wait_queue_head_t for waiting on End Transfer 
>>> complete
>>>   * @lock: spinlock for endpoint request queue traversal
>>>   * @regs: pointer to first endpoint register
>>>   * @trb_pool: array of transaction buffers
>>> @@ -529,6 +531,8 @@ struct dwc3_ep {
>>> struct list_headpending_list;
>>> struct list_headstarted_list;
>>>
>>> +   wait_queue_head_t   wait_end_transfer;
>>> +
>>> spinlock_t  lock;

[PATCH v4] usb: dwc3: Wait for control tranfer completed when stopping gadget

2016-10-14 Thread Baolin Wang
When we change the USB function with configfs dynamically, we possibly met this
situation: one core is doing the control transfer, another core is trying to
unregister the USB gadget from userspace, we must wait for completing this
control tranfer, or it will hang the controller to set the DEVCTRLHLT flag.

Signed-off-by: Baolin Wang <baolin.w...@linaro.org>
---
Changes since v3:
 - Remove the patch 1 which will cause start gadget failed.
 - Remove try_again and refactor the code.

Changes since v2:
 - Move disconnect checking into dwc3_send_gadget_ep_cmd().
 - Rename completion name and issue complete() at one place.
 - Move completion initialization into dwc3_gadget_init().

Changes since v1:
 - Split into 2 separate ptaches.
 - Choose complete mechanism instead of polling.
---
 drivers/usb/dwc3/core.h   |2 ++
 drivers/usb/dwc3/ep0.c|2 ++
 drivers/usb/dwc3/gadget.c |   28 +++-
 3 files changed, 31 insertions(+), 1 deletion(-)

diff --git a/drivers/usb/dwc3/core.h b/drivers/usb/dwc3/core.h
index b2317e7..23765a1 100644
--- a/drivers/usb/dwc3/core.h
+++ b/drivers/usb/dwc3/core.h
@@ -745,6 +745,7 @@ struct dwc3_scratchpad_array {
  * @ep0_usb_req: dummy req used while handling STD USB requests
  * @ep0_bounce_addr: dma address of ep0_bounce
  * @scratch_addr: dma address of scratchbuf
+ * @ep0_in_setup: one control transfer is completed and enter setup phase
  * @lock: for synchronizing
  * @dev: pointer to our struct device
  * @xhci: pointer to our xHCI child
@@ -843,6 +844,7 @@ struct dwc3 {
dma_addr_t  ep0_bounce_addr;
dma_addr_t  scratch_addr;
struct dwc3_request ep0_usb_req;
+   struct completion   ep0_in_setup;
 
/* device lock */
spinlock_t  lock;
diff --git a/drivers/usb/dwc3/ep0.c b/drivers/usb/dwc3/ep0.c
index fe79d77..06c167a 100644
--- a/drivers/usb/dwc3/ep0.c
+++ b/drivers/usb/dwc3/ep0.c
@@ -311,6 +311,8 @@ void dwc3_ep0_out_start(struct dwc3 *dwc)
ret = dwc3_ep0_start_trans(dwc, 0, dwc->ctrl_req_addr, 8,
DWC3_TRBCTL_CONTROL_SETUP, false);
WARN_ON(ret < 0);
+
+   complete(>ep0_in_setup);
 }
 
 static struct dwc3_ep *dwc3_wIndex_to_dep(struct dwc3 *dwc, __le16 wIndex_le)
diff --git a/drivers/usb/dwc3/gadget.c b/drivers/usb/dwc3/gadget.c
index 1783406..3722c90 100644
--- a/drivers/usb/dwc3/gadget.c
+++ b/drivers/usb/dwc3/gadget.c
@@ -1434,6 +1434,13 @@ static int dwc3_gadget_run_stop(struct dwc3 *dwc, int 
is_on, int suspend)
if (pm_runtime_suspended(dwc->dev))
return 0;
 
+   /*
+* Per databook, when we want to stop the gadget, if a control transfer
+* is still in process, complete it and get the core into setup phase.
+*/
+   if (!is_on && dwc->ep0state != EP0_SETUP_PHASE)
+   return -EBUSY;
+
reg = dwc3_readl(dwc->regs, DWC3_DCTL);
if (is_on) {
if (dwc->revision <= DWC3_REVISION_187A) {
@@ -1480,11 +1487,28 @@ static int dwc3_gadget_pullup(struct usb_gadget *g, int 
is_on)
 {
struct dwc3 *dwc = gadget_to_dwc(g);
unsigned long   flags;
-   int ret;
+   int ret = 0;
 
is_on = !!is_on;
 
spin_lock_irqsave(>lock, flags);
+   if (!is_on && !pm_runtime_suspended(dwc->dev) &&
+   dwc->ep0state != EP0_SETUP_PHASE) {
+   reinit_completion(>ep0_in_setup);
+   ret = -EBUSY;
+   }
+   spin_unlock_irqrestore(>lock, flags);
+
+   if (ret == -EBUSY) {
+   ret = wait_for_completion_timeout(>ep0_in_setup,
+ msecs_to_jiffies(500));
+   if (ret == 0) {
+   dev_err(dwc->dev, "timeout to wait for setup phase.\n");
+   return -ETIMEDOUT;
+   }
+   }
+
+   spin_lock_irqsave(>lock, flags);
ret = dwc3_gadget_run_stop(dwc, is_on, false);
spin_unlock_irqrestore(>lock, flags);
 
@@ -2911,6 +2935,8 @@ int dwc3_gadget_init(struct dwc3 *dwc)
goto err4;
}
 
+   init_completion(>ep0_in_setup);
+
dwc->gadget.ops = _gadget_ops;
dwc->gadget.speed   = USB_SPEED_UNKNOWN;
dwc->gadget.sg_supported= true;
-- 
1.7.9.5

--
To unsubscribe from this list: send the line "unsubscribe linux-usb" in
the body of a message to majord...@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html


Re: [PATCH v4] usb: dwc3: Wait for control tranfer completed when stopping gadget

2016-10-17 Thread Baolin Wang
Hi,

On 17 October 2016 at 19:53, Felipe Balbi <ba...@kernel.org> wrote:
>
> Hi,
>
> Baolin Wang <baolin.w...@linaro.org> writes:
>>> Baolin Wang <baolin.w...@linaro.org> writes:
>>>> When we change the USB function with configfs dynamically, we possibly met 
>>>> this
>>>> situation: one core is doing the control transfer, another core is trying 
>>>> to
>>>> unregister the USB gadget from userspace, we must wait for completing this
>>>> control tranfer, or it will hang the controller to set the DEVCTRLHLT flag.
>>>>
>>>> Signed-off-by: Baolin Wang <baolin.w...@linaro.org>
>>>
>>> Can you make sure this still works?
>>
>> With applying this patch, It can work well on my platform, but I have
>> some worries about the risk of accessing 'dwc->ep0state' without lock
>> protection in dwc3_gadget_pullup() function.
>
> hmm, I might be missing something, but I think there's no risk here. If
> anything, a wmb() is probably enough before reading ep0state. No?

OK, I agree with you and I think a wmb() is not useful here.

-- 
Baolin.wang
Best Regards
--
To unsubscribe from this list: send the line "unsubscribe linux-usb" in
the body of a message to majord...@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html


[PATCH v18 3/4] usb: gadget: Integrate with the usb gadget supporting for usb charger

2016-10-18 Thread Baolin Wang
When the usb gadget supporting for usb charger is ready, the usb charger
can implement the usb_charger_plug_by_gadget() function, usb_charger_exit()
function and dev_to_uchger() function by getting 'struct usb_charger' from
'struct gadget'.

Signed-off-by: Baolin Wang <baolin.w...@linaro.org>
Reviewed-by: Li Jun <jun...@nxp.com>
Tested-by: Li Jun <jun...@nxp.com>
---
 drivers/usb/gadget/udc/charger.c |   97 +-
 1 file changed, 96 insertions(+), 1 deletion(-)

diff --git a/drivers/usb/gadget/udc/charger.c b/drivers/usb/gadget/udc/charger.c
index d885e86..56aee28 100644
--- a/drivers/usb/gadget/udc/charger.c
+++ b/drivers/usb/gadget/udc/charger.c
@@ -38,7 +38,9 @@ static DEFINE_MUTEX(charger_lock);
 
 static struct usb_charger *dev_to_uchger(struct device *dev)
 {
-   return NULL;
+   struct usb_gadget *gadget = container_of(dev, struct usb_gadget, dev);
+
+   return gadget->charger;
 }
 
 /*
@@ -308,6 +310,18 @@ static int __usb_charger_set_cur_limit_by_type(struct 
usb_charger *uchger,
 int usb_charger_set_cur_limit_by_gadget(struct usb_gadget *gadget,
unsigned int cur_limit)
 {
+   struct usb_charger *uchger = gadget->charger;
+   int ret;
+
+   if (!uchger)
+   return -EINVAL;
+
+   ret = __usb_charger_set_cur_limit_by_type(uchger, uchger->type,
+ cur_limit);
+   if (ret)
+   return ret;
+
+   schedule_work(>work);
return 0;
 }
 EXPORT_SYMBOL_GPL(usb_charger_set_cur_limit_by_gadget);
@@ -625,11 +639,66 @@ static int usb_charger_plug_by_extcon(struct 
notifier_block *nb,
 int usb_charger_plug_by_gadget(struct usb_gadget *gadget,
   unsigned long state)
 {
+   struct usb_charger *uchger = gadget->charger;
+   enum usb_charger_state uchger_state;
+
+   if (WARN(!uchger, "charger can not be NULL"))
+   return -EINVAL;
+
+   /*
+* Report event to power to setting the current limitation
+* for this usb charger when one usb charger state is changed
+* with detecting by usb gadget state.
+*/
+   if (uchger->old_gadget_state != state) {
+   uchger->old_gadget_state = state;
+
+   if (state >= USB_STATE_ATTACHED) {
+   uchger_state = USB_CHARGER_PRESENT;
+   } else if (state == USB_STATE_NOTATTACHED) {
+   mutex_lock(>lock);
+
+   /*
+* Need check the charger type to make sure the usb
+* cable is removed, in case it just changes the usb
+* function with configfs.
+*/
+   uchger->type = __usb_charger_get_type(uchger);
+   if (uchger->type != UNKNOWN_TYPE) {
+   mutex_unlock(>lock);
+   return 0;
+   }
+
+   mutex_unlock(>lock);
+   uchger_state = USB_CHARGER_REMOVE;
+   } else {
+   uchger_state = USB_CHARGER_DEFAULT;
+   }
+
+   usb_charger_notify_state(uchger, uchger_state);
+   }
+
return 0;
 }
 EXPORT_SYMBOL_GPL(usb_charger_plug_by_gadget);
 
 /*
+ * usb_charger_unregister() - Unregister a usb charger.
+ * @uchger - the usb charger to be unregistered.
+ */
+static int usb_charger_unregister(struct usb_charger *uchger)
+{
+   ida_simple_remove(_charger_ida, uchger->id);
+   sysfs_remove_groups(>gadget->dev.kobj, usb_charger_groups);
+
+   mutex_lock(_lock);
+   list_del(>list);
+   mutex_unlock(_lock);
+
+   return 0;
+}
+
+/*
  * usb_charger_register() - Register a new usb charger.
  * @uchger - the new usb charger instance.
  */
@@ -737,6 +806,7 @@ int usb_charger_init(struct usb_gadget *ugadget)
}
 
uchger->gadget = ugadget;
+   ugadget->charger = uchger;
uchger->old_gadget_state = USB_STATE_NOTATTACHED;
 
/* Register a new usb charger */
@@ -774,6 +844,31 @@ fail_extcon:
 
 int usb_charger_exit(struct usb_gadget *ugadget)
 {
+   struct usb_charger *uchger = ugadget->charger;
+
+   if (!uchger)
+   return -EINVAL;
+
+   usb_charger_unregister(uchger);
+   ugadget->charger = NULL;
+
+   extcon_unregister_notifier(uchger->extcon_dev,
+  EXTCON_USB,
+  >extcon_nb.nb);
+   extcon_unregister_notifier(uchger->extcon_dev,
+  EXTCON_CHG_USB_SDP,
+  >extcon_type_nb.nb);
+   extcon_unregister_notifier(uchger->extcon_dev,
+  EXTCON_CHG_USB_CDP,

[PATCH v18 1/4] usb: gadget: Introduce the usb charger framework

2016-10-18 Thread Baolin Wang
This patch introduces the usb charger driver based on usb gadget that
makes an enhancement to a power driver. It works well in practice but
that requires a system with suitable hardware.

The basic conception of the usb charger is that, when one usb charger
is added or removed by reporting from the usb gadget state change or
the extcon device state change, the usb charger will report to power
user to set the current limitation.

The usb charger will register notifiees on the usb gadget or the extcon
device to get notified the usb charger state. It also supplies the
notification mechanism to userspace When the usb charger state is changed.

Power user will register a notifiee on the usb charger to get notified
by status changes from the usb charger. It will report to power user
to set the current limitation when detecting the usb charger is added
or removed from extcon device state or usb gadget state.

This patch doesn't yet integrate with the gadget code, so some functions
which rely on the 'gadget' are not completed, that will be implemented
in the following patches.

Signed-off-by: Baolin Wang <baolin.w...@linaro.org>
Reviewed-by: Li Jun <jun...@nxp.com>
Tested-by: Li Jun <jun...@nxp.com>
---
 drivers/usb/gadget/Kconfig   |8 +
 drivers/usb/gadget/udc/Makefile  |1 +
 drivers/usb/gadget/udc/charger.c |  782 ++
 include/linux/usb/charger.h  |  185 +
 include/uapi/linux/usb/charger.h |   31 ++
 5 files changed, 1007 insertions(+)
 create mode 100644 drivers/usb/gadget/udc/charger.c
 create mode 100644 include/linux/usb/charger.h
 create mode 100644 include/uapi/linux/usb/charger.h

diff --git a/drivers/usb/gadget/Kconfig b/drivers/usb/gadget/Kconfig
index 2ea3fc3..7520677 100644
--- a/drivers/usb/gadget/Kconfig
+++ b/drivers/usb/gadget/Kconfig
@@ -134,6 +134,14 @@ config U_SERIAL_CONSOLE
help
   It supports the serial gadget can be used as a console.
 
+config USB_CHARGER
+   bool "USB charger support"
+   select EXTCON
+   help
+ The usb charger driver based on the usb gadget that makes an
+ enhancement to a power driver which can set the current limitation
+ when the usb charger is added or removed.
+
 source "drivers/usb/gadget/udc/Kconfig"
 
 #
diff --git a/drivers/usb/gadget/udc/Makefile b/drivers/usb/gadget/udc/Makefile
index 98e74ed..ede2351 100644
--- a/drivers/usb/gadget/udc/Makefile
+++ b/drivers/usb/gadget/udc/Makefile
@@ -2,6 +2,7 @@
 CFLAGS_trace.o := -I$(src)
 
 udc-core-y := core.o trace.o
+udc-core-$(CONFIG_USB_CHARGER) += charger.o
 
 #
 # USB peripheral controller drivers
diff --git a/drivers/usb/gadget/udc/charger.c b/drivers/usb/gadget/udc/charger.c
new file mode 100644
index 000..d885e86
--- /dev/null
+++ b/drivers/usb/gadget/udc/charger.c
@@ -0,0 +1,782 @@
+/*
+ * charger.c -- USB charger driver
+ *
+ * Copyright (C) 2016 Linaro Ltd.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ */
+
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+
+/* Default current range by charger type. */
+#define DEFAULT_SDP_CUR_MIN2
+#define DEFAULT_SDP_CUR_MAX500
+#define DEFAULT_SDP_CUR_MIN_SS 150
+#define DEFAULT_SDP_CUR_MAX_SS 900
+#define DEFAULT_DCP_CUR_MIN500
+#define DEFAULT_DCP_CUR_MAX5000
+#define DEFAULT_CDP_CUR_MIN1500
+#define DEFAULT_CDP_CUR_MAX5000
+#define DEFAULT_ACA_CUR_MIN1500
+#define DEFAULT_ACA_CUR_MAX5000
+
+static DEFINE_IDA(usb_charger_ida);
+static LIST_HEAD(charger_list);
+static DEFINE_MUTEX(charger_lock);
+
+static struct usb_charger *dev_to_uchger(struct device *dev)
+{
+   return NULL;
+}
+
+/*
+ * charger_current_show() - Show the charger current.
+ */
+static ssize_t charger_current_show(struct device *dev,
+   struct device_attribute *attr,
+   char *buf)
+{
+   struct usb_charger *uchger = dev_to_uchger(dev);
+   unsigned int min, max;
+
+   usb_charger_get_current(uchger, , );
+   return sprintf(buf, "%u-%u\n", min, max);
+}
+static DEVICE_ATTR_RO(charger_current);
+
+/*
+ * charger_type_show() - Show the charger type.
+ *
+ * It can be SDP/DCP/CDP/ACA type, else for unknown type.
+ */
+static ssize_t charger_type_show(struct device *dev,
+struct device_attribute *attr,
+char *buf)
+{
+   struct usb_charger *uchger = dev_to_uchger(dev);
+   int cnt;
+
+   switch (uchger->type) {
+   case SDP_TYPE:
+   cnt = sprintf(buf, "%s\n", "SDP");
+   break;
+   case DCP_TYPE:
+   cnt = sprintf(buf, "%s\n

[PATCH v18 2/4] usb: gadget: Support for the usb charger framework

2016-10-18 Thread Baolin Wang
For supporting the usb charger, it adds the usb_charger_init() and
usb_charger_exit() functions for usb charger initialization and exit.

It will report to the usb charger when the gadget state is changed,
then the usb charger can do the power things.

Signed-off-by: Baolin Wang <baolin.w...@linaro.org>
Reviewed-by: Li Jun <jun...@nxp.com>
Tested-by: Li Jun <jun...@nxp.com>
---
 drivers/usb/gadget/udc/core.c |   19 ++-
 include/linux/usb/gadget.h|3 +++
 2 files changed, 21 insertions(+), 1 deletion(-)

diff --git a/drivers/usb/gadget/udc/core.c b/drivers/usb/gadget/udc/core.c
index 9483489..90df022 100644
--- a/drivers/usb/gadget/udc/core.c
+++ b/drivers/usb/gadget/udc/core.c
@@ -25,6 +25,7 @@
 #include 
 #include 
 
+#include 
 #include 
 #include 
 #include 
@@ -576,12 +577,17 @@ EXPORT_SYMBOL_GPL(usb_gadget_vbus_connect);
  * reporting how much power the device may consume.  For example, this
  * could affect how quickly batteries are recharged.
  *
+ * It will also notify the USB charger how much power the device may
+ * consume if there is a USB charger linking with the gadget.
+ *
  * Returns zero on success, else negative errno.
  */
 int usb_gadget_vbus_draw(struct usb_gadget *gadget, unsigned mA)
 {
int ret = 0;
 
+   usb_charger_set_cur_limit_by_gadget(gadget, mA);
+
if (!gadget->ops->vbus_draw) {
ret = -EOPNOTSUPP;
goto out;
@@ -963,6 +969,9 @@ static void usb_gadget_state_work(struct work_struct *work)
struct usb_gadget *gadget = work_to_gadget(work);
struct usb_udc *udc = gadget->udc;
 
+   /* when the gadget state is changed, then report to USB charger */
+   usb_charger_plug_by_gadget(gadget, gadget->state);
+
if (udc)
sysfs_notify(>dev.kobj, NULL, "state");
 }
@@ -1132,6 +1141,10 @@ int usb_add_gadget_udc_release(struct device *parent, 
struct usb_gadget *gadget,
if (ret)
goto err4;
 
+   ret = usb_charger_init(gadget);
+   if (ret)
+   goto err5;
+
usb_gadget_set_state(gadget, USB_STATE_NOTATTACHED);
udc->vbus = true;
 
@@ -1143,7 +1156,7 @@ int usb_add_gadget_udc_release(struct device *parent, 
struct usb_gadget *gadget,
if (ret != -EPROBE_DEFER)
list_del(>pending);
if (ret)
-   goto err5;
+   goto err6;
break;
}
}
@@ -1152,6 +1165,9 @@ int usb_add_gadget_udc_release(struct device *parent, 
struct usb_gadget *gadget,
 
return 0;
 
+err6:
+   usb_charger_exit(gadget);
+
 err5:
device_del(>dev);
 
@@ -1263,6 +1279,7 @@ void usb_del_gadget_udc(struct usb_gadget *gadget)
kobject_uevent(>dev.kobj, KOBJ_REMOVE);
flush_work(>work);
device_unregister(>dev);
+   usb_charger_exit(gadget);
device_unregister(>dev);
 }
 EXPORT_SYMBOL_GPL(usb_del_gadget_udc);
diff --git a/include/linux/usb/gadget.h b/include/linux/usb/gadget.h
index 8e81f9e..82a0d63 100644
--- a/include/linux/usb/gadget.h
+++ b/include/linux/usb/gadget.h
@@ -24,6 +24,7 @@
 #include 
 #include 
 #include 
+#include 
 
 #define UDC_TRACE_STR_MAX  512
 
@@ -328,6 +329,7 @@ struct usb_gadget_ops {
  * @in_epnum: last used in ep number
  * @mA: last set mA value
  * @otg_caps: OTG capabilities of this gadget.
+ * @charger: Negotiate the power with the usb charger.
  * @sg_supported: true if we can handle scatter-gather
  * @is_otg: True if the USB device port uses a Mini-AB jack, so that the
  * gadget driver must provide a USB OTG descriptor.
@@ -387,6 +389,7 @@ struct usb_gadget {
unsignedin_epnum;
unsignedmA;
struct usb_otg_caps *otg_caps;
+   struct usb_charger  *charger;
 
unsignedsg_supported:1;
unsignedis_otg:1;
-- 
1.7.9.5

--
To unsubscribe from this list: send the line "unsubscribe linux-usb" in
the body of a message to majord...@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html


[PATCH v18 0/4] Introduce usb charger framework to deal with the usb gadget power negotation

2016-10-18 Thread Baolin Wang
Currently the Linux kernel does not provide any standard integration of this
feature that integrates the USB subsystem with the system power regulation
provided by PMICs meaning that either vendors must add this in their kernels
or USB gadget devices based on Linux (such as mobile phones) may not behave
as they should. Thus provide a standard framework for doing this in kernel.

Now introduce one user with wm831x_power to support and test the usb charger,
which is pending testing. Moreover there may be other potential users will use
it in future.

Changes since v17:
 - Remove goto section in usb_charger_register() function.
 - Remove 'extern' in charger.h file.
 - Move the kfree() to usb_charger_exit() function.

Changes since v16:
 - Modify the charger current range with introducing the maximum and minimum
 current.
 - Remove the getting charger type method from power supply.
 - Add the getting charger type method from extcon system.
 - Introduce new usb_charger_get_current() API for users to get the maximum and
 minimum current.
 - Rename some APIs and other optimization.

Changes since v15:
 - Add charger state checking to avoid sending out duplicate notifies to users.
 - Add one work to notify power users the current has been changed.

Changes since v14:
 - Add kernel documentation for struct usb_cahrger.
 - Remove some redundant WARN() functions.

Changes since v13:
 - Remove the charger checking in usb_gadget_vbus_draw() function.
 - Rename some functions in charger.c file.
 - Rebase on git://git.kernel.org/pub/scm/linux/kernel/git/balbi/usb.git 
tags/usb-for-v4.8

Changes since v12:
 - Remove the class and device things.
 - Link usb charger to udc-core.ko.
 - Create one "charger" subdirectory which holds all charger-related attributes.

Changes since v11:
 - Reviewed and tested by Li Jun.

Changes since v10:
 - Introduce usb_charger_get_state() function to check charger state.
 - Remove the mutex lock in usb_charger_set_cur_limit_by_type() function
 in case will be issued in atomic context.

Baolin Wang (4):
  usb: gadget: Introduce the usb charger framework
  usb: gadget: Support for the usb charger framework
  usb: gadget: Integrate with the usb gadget supporting for usb charger
  power: wm831x_power: Support USB charger current limit management

 drivers/power/wm831x_power.c |   75 
 drivers/usb/gadget/Kconfig   |8 +
 drivers/usb/gadget/udc/Makefile  |1 +
 drivers/usb/gadget/udc/charger.c |  877 ++
 drivers/usb/gadget/udc/core.c|   19 +-
 include/linux/mfd/wm831x/pdata.h |3 +
 include/linux/usb/charger.h  |  185 
 include/linux/usb/gadget.h   |3 +
 include/uapi/linux/usb/charger.h |   31 ++
 9 files changed, 1201 insertions(+), 1 deletion(-)
 create mode 100644 drivers/usb/gadget/udc/charger.c
 create mode 100644 include/linux/usb/charger.h
 create mode 100644 include/uapi/linux/usb/charger.h

-- 
1.7.9.5

--
To unsubscribe from this list: send the line "unsubscribe linux-usb" in
the body of a message to majord...@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html


[PATCH v18 4/4] power: wm831x_power: Support USB charger current limit management

2016-10-18 Thread Baolin Wang
Integrate with the newly added USB charger interface to limit the current
we draw from the USB input based on the input device configuration
identified by the USB stack, allowing us to charge more quickly from high
current inputs without drawing more current than specified from others.

Signed-off-by: Mark Brown <broo...@kernel.org>
Signed-off-by: Baolin Wang <baolin.w...@linaro.org>
Acked-by: Lee Jones <lee.jo...@linaro.org>
Acked-by: Charles Keepax <ckee...@opensource.wolfsonmicro.com>
Acked-by: Peter Chen <peter.c...@freescale.com>
Acked-by: Sebastian Reichel <s...@kernel.org>
---
 drivers/power/wm831x_power.c |   75 ++
 include/linux/mfd/wm831x/pdata.h |3 ++
 2 files changed, 78 insertions(+)

diff --git a/drivers/power/wm831x_power.c b/drivers/power/wm831x_power.c
index 7082301..2bcd775 100644
--- a/drivers/power/wm831x_power.c
+++ b/drivers/power/wm831x_power.c
@@ -13,6 +13,7 @@
 #include 
 #include 
 #include 
+#include 
 
 #include 
 #include 
@@ -31,6 +32,8 @@ struct wm831x_power {
char usb_name[20];
char battery_name[20];
bool have_battery;
+   struct usb_charger *usb_charger;
+   struct notifier_block usb_notify;
 };
 
 static int wm831x_power_check_online(struct wm831x *wm831x, int supply,
@@ -125,6 +128,49 @@ static enum power_supply_property wm831x_usb_props[] = {
POWER_SUPPLY_PROP_VOLTAGE_NOW,
 };
 
+/* In milliamps */
+static const unsigned int wm831x_usb_limits[] = {
+   0,
+   2,
+   100,
+   500,
+   900,
+   1500,
+   1800,
+   550,
+};
+
+static int wm831x_usb_limit_change(struct notifier_block *nb,
+  unsigned long state, void *data)
+{
+   struct wm831x_power *wm831x_power = container_of(nb,
+struct wm831x_power,
+usb_notify);
+   struct usb_charger *uchger = (struct usb_charger *)data;
+   unsigned int i, best, min, limit;
+
+   if (state == USB_CHARGER_PRESENT)
+   usb_charger_get_current(uchger, , );
+   else
+   limit = 0;
+
+   /* Find the highest supported limit */
+   best = 0;
+   for (i = 0; i < ARRAY_SIZE(wm831x_usb_limits); i++) {
+   if (limit >= wm831x_usb_limits[i] &&
+   wm831x_usb_limits[best] < wm831x_usb_limits[i])
+   best = i;
+   }
+
+   dev_dbg(wm831x_power->wm831x->dev,
+   "Limiting USB current to %umA", wm831x_usb_limits[best]);
+
+   wm831x_set_bits(wm831x_power->wm831x, WM831X_POWER_STATE,
+   WM831X_USB_ILIM_MASK, best);
+
+   return 0;
+}
+
 /*
  * Battery properties
  */
@@ -607,8 +653,31 @@ static int wm831x_power_probe(struct platform_device *pdev)
}
}
 
+   if (wm831x_pdata && wm831x_pdata->usb_gadget) {
+   power->usb_charger =
+   usb_charger_find_by_name(wm831x_pdata->usb_gadget);
+   if (IS_ERR(power->usb_charger)) {
+   ret = PTR_ERR(power->usb_charger);
+   dev_err(>dev,
+   "Failed to find USB gadget: %d\n", ret);
+   goto err_bat_irq;
+   }
+
+   power->usb_notify.notifier_call = wm831x_usb_limit_change;
+
+   ret = usb_charger_register_notify(power->usb_charger,
+ >usb_notify);
+   if (ret != 0) {
+   dev_err(>dev,
+   "Failed to register notifier: %d\n", ret);
+   goto err_usb_charger;
+   }
+   }
+
return ret;
 
+err_usb_charger:
+   /* put_device on charger */
 err_bat_irq:
--i;
for (; i >= 0; i--) {
@@ -637,6 +706,12 @@ static int wm831x_power_remove(struct platform_device 
*pdev)
struct wm831x *wm831x = wm831x_power->wm831x;
int irq, i;
 
+   if (wm831x_power->usb_charger) {
+   usb_charger_unregister_notify(wm831x_power->usb_charger,
+ _power->usb_notify);
+   /* Free charger */
+   }
+
for (i = 0; i < ARRAY_SIZE(wm831x_bat_irqs); i++) {
irq = wm831x_irq(wm831x, 
 platform_get_irq_byname(pdev,
diff --git a/include/linux/mfd/wm831x/pdata.h b/include/linux/mfd/wm831x/pdata.h
index dcc9631..5af8399 100644
--- a/include/linux/mfd/wm831x/pdata.h
+++ b/include/linux/mfd/wm831x/pdata.h
@@ -126,6 +126,9 @@ struct wm831x_pdata {
   

Re: [PATCH v18 0/4] Introduce usb charger framework to deal with the usb gadget power negotation

2016-11-14 Thread Baolin Wang
On 14 November 2016 at 12:21, NeilBrown <ne...@suse.com> wrote:
> On Thu, Nov 10 2016, Baolin Wang wrote:
>
>> Hi
>>
>> On 8 November 2016 at 04:36, NeilBrown <ne...@suse.com> wrote:
>>> On Mon, Nov 07 2016, Baolin Wang wrote:
>>>
>>>> On 3 November 2016 at 09:25, NeilBrown <ne...@suse.com> wrote:
>>>>> On Tue, Nov 01 2016, Baolin Wang wrote:
>>>>
>>>> I agree with your most opinions, but these are optimization.
>>>
>>> I see them as bug fixes, not optimizations.
>>>
>>>>  Firstly I
>>>> think we should upstream the USB charger driver.
>>>
>>> I think you missed the point.  The point is that we don't *need* your
>>> "USB charger driver" because all the infrastructure we need is *already*
>>> present in the kernel.  It is buggy and not used uniformly, and could
>>> usefully be polished and improved.  But the structure is already
>>> present.
>>>
>>> If everyone just added new infrastructure when they didn't like, or
>>> didn't understand, what was already present, the kernel would become
>>> like the Mad Hatter's tea party, full of dirty dishes.
>>>
>>>>  What I want to ask is
>>>> how can we notify power driver if we don't set the
>>>> usb_register_notifier(), then I think you give the answer is: power
>>>> driver can register by 'struct usb_phy->notifier'. But why usb phy
>>>> should notify the power driver how much current should be drawn, and I
>>>> still think we should notify the current in usb charger driver which
>>>> is better, and do not need to notify current for power driver in usb
>>>> phy driver.
>>>
>>> I accept that it isn't clear that the phy *should* be involved in
>>> communicating the negotiated power availability, but nor is it clear
>>> that it shouldn't.  The power does travel through the physical
>>> interface, so physically it plays a role.
>>>
>>> But more importantly, it already *does* get told (in some cases).
>>> There is an interface "usb_phy_set_power()" which exists explicitly to
>>> tell the phy what power has been negotiated.  Given that infrastructure
>>> exists and works, it make sense to use it.
>>>
>>> If you think it is a broken design and should be removed, then fine:
>>> make a case for that.  Examine the history.  Make sure you know why it
>>> is there (or make sure that information cannot be found), and then
>>> present a case as to why it should be removed and replaced with
>>> something else.  But don't just leave it there and pretend it doesn't
>>> exist and create something similar-but-different and hope people will
>>> know why yours is better.  That way lies madness.
>>
>> Like Peter said, it is not only PHY can detect the USB charger type,
>> which means there are other places can detect the charger type.
>
> If I understand Peter's example correctly, it shows a configuration
> where the USB PHysical interface is partly implemented in the SOC and
> partly in the PMIC.  I appreciate that would make it more challenging to
> implement a PHY driver, but there is no reason it should impact anything
> outside of the PHY.

Like Peter's example, it need to use controller register to pull up dp
to begin the secondary detection, which is not belonged to phy driver
and I don't think it is suitable we implemented these in phy driver.

>
>> Second, some controller need to detect the charger type manually which
>> USB phy did not support.
>
> "manually" is an odd term to use in this context.

Sorry for the confusing.

> I think you mean that to detect the charger type you need to issue some
> command to the hardware and wait for it to respond, then assess the
> response.

Yes.

> That isn't at all surprising.  The charger type is detected by measuring
> resistance between ID and GND, which may require setting up a potential
> and activating ADCs to measure the voltage.  This can all be done
> internally to the phy driver.
> Sometimes it is easy (I did https://lkml.org/lkml/2015/2/23/746 for
> twl4030, though it never got upstream).
> The code for the imx7d does look more complex, but not intrinsically
> different.

But you should implement these in every phy driver, why not one
standard framework?

>
>> Third, it did not handle what current should
>> be drawn in USB phy.
>
> The standards define that.  The e

[PATCH] usb: dwc3: core: Disable USB2.0 phy suspend when dwc3 acts as host role

2016-11-15 Thread Baolin Wang
When dwc3 controller acts as host role with attaching slow speed device
(like mouse or keypad). Then if we plugged out the slow speed device,
it will timeout to run the deconfiguration endpoint command to drop the
endpoint's resources. Some xHCI command timeout log as below when
disconnecting one slow device:

[   99.807739] c0 xhci-hcd.0.auto: Port Status Change Event for port 1
[   99.814699] c0 xhci-hcd.0.auto: resume root hub
[   99.819992] c0 xhci-hcd.0.auto: handle_port_status: starting port
   polling.
[   99.827808] c0 xhci-hcd.0.auto: get port status, actual port 0 status
   = 0x202a0
[   99.835903] c0 xhci-hcd.0.auto: Get port status returned 0x10100
[   99.850052] c0 xhci-hcd.0.auto: clear port connect change, actual
   port 0 status  = 0x2a0
[   99.859313] c0 xhci-hcd.0.auto: Cancel URB ffc01ed6cd00, dev 1,
   ep 0x81, starting at offset 0xc406d210
[   99.869645] c0 xhci-hcd.0.auto: // Ding dong!
[   99.874776] c0 xhci-hcd.0.auto: Stopped on Transfer TRB
[   99.880713] c0 xhci-hcd.0.auto: Removing canceled TD starting at
   0xc406d210 (dma).
[   99.889012] c0 xhci-hcd.0.auto: Finding endpoint context
[   99.895069] c0 xhci-hcd.0.auto: Cycle state = 0x1
[   99.900519] c0 xhci-hcd.0.auto: New dequeue segment =
   ffc1112f0880 (virtual)
[   99.908655] c0 xhci-hcd.0.auto: New dequeue pointer = 0xc406d220 (DMA)
[   99.915927] c0 xhci-hcd.0.auto: Set TR Deq Ptr cmd, new deq seg =
   ffc1112f0880 (0xc406d000 dma),
   new deq ptr = ff8002175220
   (0xc406d220 dma), new cycle = 1
[   99.931242] c0 xhci-hcd.0.auto: // Ding dong!
[   99.936360] c0 xhci-hcd.0.auto: Successful Set TR Deq Ptr cmd,
   deq = @c406d220
[   99.944458] c0 xhci-hcd.0.auto: xhci_hub_status_data: stopping port
   polling.
[  100.047619] c0 xhci-hcd.0.auto: xhci_drop_endpoint called for udev
   ffc01ae08800
[  100.057002] c0 xhci-hcd.0.auto: drop ep 0x81, slot id 1, new drop
   flags = 0x8, new add flags = 0x0
[  100.067878] c0 xhci-hcd.0.auto: xhci_check_bandwidth called for udev
   ffc01ae08800
[  100.076868] c0 xhci-hcd.0.auto: New Input Control Context:

..

[  100.427252] c0 xhci-hcd.0.auto: // Ding dong!
[  105.430728] c0 xhci-hcd.0.auto: Command timeout
[  105.436029] c0 xhci-hcd.0.auto: Abort command ring
[  113.558223] c0 xhci-hcd.0.auto: Command completion event does not match
   command
[  113.569778] c0 xhci-hcd.0.auto: Timeout while waiting for configure
   endpoint command

The reason is it will suspend USB phy to disable phy clock when
disconnecting the slow USB decice, that will hang on the xHCI commands
executing which depends on the phy clock.

Thus we should disable USB2.0 phy suspend feature when dwc3 acts as host
role.

Signed-off-by: Baolin Wang <baolin.w...@linaro.org>
---
 drivers/usb/dwc3/core.c |   14 ++
 1 file changed, 14 insertions(+)

diff --git a/drivers/usb/dwc3/core.c b/drivers/usb/dwc3/core.c
index 9a4a5e4..0b646cf 100644
--- a/drivers/usb/dwc3/core.c
+++ b/drivers/usb/dwc3/core.c
@@ -565,6 +565,20 @@ static int dwc3_phy_setup(struct dwc3 *dwc)
if (dwc->revision > DWC3_REVISION_194A)
reg |= DWC3_GUSB2PHYCFG_SUSPHY;
 
+   /*
+* When dwc3 controller acts as host role with attaching one slow speed
+* device (like mouse or keypad). Then if we plugged out the slow speed
+* device, it will timeout to run the deconfiguration endpoint command.
+* The reason is it will suspend USB phy to disable phy clock when
+* disconnecting slow speed decice, which will affect the xHCI commands
+* executing.
+*
+* Thus we should disable USB 2.0 phy suspend feature when dwc3 acts as
+* host role.
+*/
+   if (dwc->dr_mode == USB_DR_MODE_HOST || dwc->dr_mode == USB_DR_MODE_OTG)
+   reg &= ~DWC3_GUSB2PHYCFG_SUSPHY;
+
if (dwc->dis_u2_susphy_quirk)
reg &= ~DWC3_GUSB2PHYCFG_SUSPHY;
 
-- 
1.7.9.5

--
To unsubscribe from this list: send the line "unsubscribe linux-usb" in
the body of a message to majord...@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html


[PATCH] usb: host: xhci: Remove unused 'addr_64' variable in xhci_hcd structure

2016-11-15 Thread Baolin Wang
Since the 'addr_64' variable as legacy is unused now, then remove it from
xhci_hcd structure.

Signed-off-by: Baolin Wang <baolin.w...@linaro.org>
---
 drivers/usb/host/xhci.h |1 -
 1 file changed, 1 deletion(-)

diff --git a/drivers/usb/host/xhci.h b/drivers/usb/host/xhci.h
index 3e5922d..9dbaacf 100644
--- a/drivers/usb/host/xhci.h
+++ b/drivers/usb/host/xhci.h
@@ -1547,7 +1547,6 @@ struct xhci_hcd {
u8  max_ports;
u8  isoc_threshold;
int event_ring_max;
-   int addr_64;
/* 4KB min, 128MB max */
int page_size;
/* Valid values are 12 to 20, inclusive */
-- 
1.7.9.5

--
To unsubscribe from this list: send the line "unsubscribe linux-usb" in
the body of a message to majord...@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html


[PATCH v3 2/2] usb: dwc3: core: Support the dwc3 host suspend/resume

2016-11-23 Thread Baolin Wang
For some mobile devices with strict power management, we also want to suspend
the host when the slave is detached for power saving. Thus we add the host
suspend/resume functions to support this requirement.

Signed-off-by: Baolin Wang <baolin.w...@linaro.org>
---
Changes since v2:
 - Remove pm_children_suspended() and other unused macros.

Changes since v1:
  - Add pm_runtime.h head file to avoid kbuild error.
---
 drivers/usb/dwc3/Kconfig |7 +++
 drivers/usb/dwc3/core.c  |   26 +-
 drivers/usb/dwc3/core.h  |   15 +++
 drivers/usb/dwc3/host.c  |   37 +
 4 files changed, 84 insertions(+), 1 deletion(-)

diff --git a/drivers/usb/dwc3/Kconfig b/drivers/usb/dwc3/Kconfig
index a45b4f1..47bb2f3 100644
--- a/drivers/usb/dwc3/Kconfig
+++ b/drivers/usb/dwc3/Kconfig
@@ -47,6 +47,13 @@ config USB_DWC3_DUAL_ROLE
 
 endchoice
 
+config USB_DWC3_HOST_SUSPEND
+   bool "Choose if the DWC3 host (xhci) can be suspend/resume"
+   depends on USB_DWC3_HOST=y || USB_DWC3_DUAL_ROLE=y
+   help
+ We can suspend the host when the slave is detached for power saving,
+ and resume the host when one slave is attached.
+
 comment "Platform Glue Driver Support"
 
 config USB_DWC3_OMAP
diff --git a/drivers/usb/dwc3/core.c b/drivers/usb/dwc3/core.c
index 9a4a5e4..7ad4bc3 100644
--- a/drivers/usb/dwc3/core.c
+++ b/drivers/usb/dwc3/core.c
@@ -1091,6 +1091,7 @@ static int dwc3_probe(struct platform_device *pdev)
pm_runtime_use_autosuspend(dev);
pm_runtime_set_autosuspend_delay(dev, DWC3_DEFAULT_AUTOSUSPEND_DELAY);
pm_runtime_enable(dev);
+   pm_suspend_ignore_children(dev, true);
ret = pm_runtime_get_sync(dev);
if (ret < 0)
goto err1;
@@ -1215,15 +1216,27 @@ static int dwc3_remove(struct platform_device *pdev)
 static int dwc3_suspend_common(struct dwc3 *dwc)
 {
unsigned long   flags;
+   int ret;
 
switch (dwc->dr_mode) {
case USB_DR_MODE_PERIPHERAL:
+   spin_lock_irqsave(>lock, flags);
+   dwc3_gadget_suspend(dwc);
+   spin_unlock_irqrestore(>lock, flags);
+   break;
case USB_DR_MODE_OTG:
+   ret = dwc3_host_suspend(dwc);
+   if (ret)
+   return ret;
+
spin_lock_irqsave(>lock, flags);
dwc3_gadget_suspend(dwc);
spin_unlock_irqrestore(>lock, flags);
break;
case USB_DR_MODE_HOST:
+   ret = dwc3_host_suspend(dwc);
+   if (ret)
+   return ret;
default:
/* do nothing */
break;
@@ -1245,12 +1258,23 @@ static int dwc3_resume_common(struct dwc3 *dwc)
 
switch (dwc->dr_mode) {
case USB_DR_MODE_PERIPHERAL:
+   spin_lock_irqsave(>lock, flags);
+   dwc3_gadget_resume(dwc);
+   spin_unlock_irqrestore(>lock, flags);
+   break;
case USB_DR_MODE_OTG:
+   ret = dwc3_host_resume(dwc);
+   if (ret)
+   return ret;
+
spin_lock_irqsave(>lock, flags);
dwc3_gadget_resume(dwc);
spin_unlock_irqrestore(>lock, flags);
-   /* FALLTHROUGH */
+   break;
case USB_DR_MODE_HOST:
+   ret = dwc3_host_resume(dwc);
+   if (ret)
+   return ret;
default:
/* do nothing */
break;
diff --git a/drivers/usb/dwc3/core.h b/drivers/usb/dwc3/core.h
index b585a30..db41908 100644
--- a/drivers/usb/dwc3/core.h
+++ b/drivers/usb/dwc3/core.h
@@ -1226,4 +1226,19 @@ static inline void dwc3_ulpi_exit(struct dwc3 *dwc)
 { }
 #endif
 
+#if IS_ENABLED(CONFIG_USB_DWC3_HOST_SUSPEND)
+int dwc3_host_suspend(struct dwc3 *dwc);
+int dwc3_host_resume(struct dwc3 *dwc);
+#else
+static inline int dwc3_host_suspend(struct dwc3 *dwc)
+{
+   return 0;
+}
+
+static inline int dwc3_host_resume(struct dwc3 *dwc)
+{
+   return 0;
+}
+#endif
+
 #endif /* __DRIVERS_USB_DWC3_CORE_H */
diff --git a/drivers/usb/dwc3/host.c b/drivers/usb/dwc3/host.c
index ed82464..8e5309d6 100644
--- a/drivers/usb/dwc3/host.c
+++ b/drivers/usb/dwc3/host.c
@@ -16,6 +16,7 @@
  */
 
 #include 
+#include 
 
 #include "core.h"
 
@@ -130,3 +131,39 @@ void dwc3_host_exit(struct dwc3 *dwc)
  dev_name(>xhci->dev));
platform_device_unregister(dwc->xhci);
 }
+
+#ifdef CONFIG_USB_DWC3_HOST_SUSPEND
+int dwc3_host_suspend(struct dwc3 *dwc)
+{
+   struct device *xhci = >xhci->dev;
+   int ret;
+
+   /*
+* Note: if we get the -EBUSY, which means the xHCI children devices are
+* not in suspend state yet, the glue layer need to wait for a while and
+* 

[PATCH v3 1/2] usb: host: plat: Enable xhci plat runtime PM

2016-11-23 Thread Baolin Wang
Enable the xhci plat runtime PM for parent device to suspend/resume xhci.
Also call pm_runtime_get_noresume() in probe() function in case the parent
device doesn't call suspend/resume callback by runtime PM now.

Signed-off-by: Baolin Wang <baolin.w...@linaro.org>
---
Changes since v2:
 - Add pm_runtime_get_noresume() in probe() function.
 - Add pm_runtime_set_suspended()/pm_runtime_put_noidle() in remove() function.

Changes since v1:
 - No updates.
---
 drivers/usb/host/xhci-plat.c |   41 -
 1 file changed, 36 insertions(+), 5 deletions(-)

diff --git a/drivers/usb/host/xhci-plat.c b/drivers/usb/host/xhci-plat.c
index ed56bf9..f174502 100644
--- a/drivers/usb/host/xhci-plat.c
+++ b/drivers/usb/host/xhci-plat.c
@@ -246,6 +246,10 @@ static int xhci_plat_probe(struct platform_device *pdev)
if (ret)
goto dealloc_usb2_hcd;
 
+   pm_runtime_get_noresume(>dev);
+   pm_runtime_set_active(>dev);
+   pm_runtime_enable(>dev);
+
return 0;
 
 
@@ -274,6 +278,10 @@ static int xhci_plat_remove(struct platform_device *dev)
struct xhci_hcd *xhci = hcd_to_xhci(hcd);
struct clk *clk = xhci->clk;
 
+   pm_runtime_set_suspended(>dev);
+   pm_runtime_put_noidle(>dev);
+   pm_runtime_disable(>dev);
+
usb_remove_hcd(xhci->shared_hcd);
usb_phy_shutdown(hcd->usb_phy);
 
@@ -311,14 +319,37 @@ static int xhci_plat_resume(struct device *dev)
 
return xhci_resume(xhci, 0);
 }
+#endif /* CONFIG_PM_SLEEP */
+
+#ifdef CONFIG_PM
+static int xhci_plat_runtime_suspend(struct device *dev)
+{
+   struct usb_hcd  *hcd = dev_get_drvdata(dev);
+   struct xhci_hcd *xhci = hcd_to_xhci(hcd);
+
+   return xhci_suspend(xhci, device_may_wakeup(dev));
+}
+
+static int xhci_plat_runtime_resume(struct device *dev)
+{
+   struct usb_hcd  *hcd = dev_get_drvdata(dev);
+   struct xhci_hcd *xhci = hcd_to_xhci(hcd);
+
+   return xhci_resume(xhci, 0);
+}
+
+static int xhci_plat_runtime_idle(struct device *dev)
+{
+   return 0;
+}
+#endif /* CONFIG_PM */
 
 static const struct dev_pm_ops xhci_plat_pm_ops = {
SET_SYSTEM_SLEEP_PM_OPS(xhci_plat_suspend, xhci_plat_resume)
+
+   SET_RUNTIME_PM_OPS(xhci_plat_runtime_suspend, xhci_plat_runtime_resume,
+  xhci_plat_runtime_idle)
 };
-#define DEV_PM_OPS (_plat_pm_ops)
-#else
-#define DEV_PM_OPS NULL
-#endif /* CONFIG_PM */
 
 static const struct acpi_device_id usb_xhci_acpi_match[] = {
/* XHCI-compliant USB Controller */
@@ -332,7 +363,7 @@ static int xhci_plat_resume(struct device *dev)
.remove = xhci_plat_remove,
.driver = {
.name = "xhci-hcd",
-   .pm = DEV_PM_OPS,
+   .pm = _plat_pm_ops,
.of_match_table = of_match_ptr(usb_xhci_of_match),
.acpi_match_table = ACPI_PTR(usb_xhci_acpi_match),
},
-- 
1.7.9.5

--
To unsubscribe from this list: send the line "unsubscribe linux-usb" in
the body of a message to majord...@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html


[PATCH] usb: xhci: Remove unuseful 'return' statement

2016-11-24 Thread Baolin Wang
Since these 'return' statements are not generally useful in void function,
remove them.

Signed-off-by: Baolin Wang <baolin.w...@linaro.org>
---
 drivers/usb/host/xhci-hub.c  |2 --
 drivers/usb/host/xhci-mem.c  |1 -
 drivers/usb/host/xhci-ring.c |4 
 drivers/usb/host/xhci.c  |3 ---
 4 files changed, 10 deletions(-)

diff --git a/drivers/usb/host/xhci-hub.c b/drivers/usb/host/xhci-hub.c
index 0ef1690..470ad66 100644
--- a/drivers/usb/host/xhci-hub.c
+++ b/drivers/usb/host/xhci-hub.c
@@ -444,8 +444,6 @@ void xhci_ring_device(struct xhci_hcd *xhci, int slot_id)
xhci_ring_ep_doorbell(xhci, slot_id, i, 0);
}
}
-
-   return;
 }
 
 static void xhci_disable_port(struct usb_hcd *hcd, struct xhci_hcd *xhci,
diff --git a/drivers/usb/host/xhci-mem.c b/drivers/usb/host/xhci-mem.c
index 48a26d378..d6f59a3 100644
--- a/drivers/usb/host/xhci-mem.c
+++ b/drivers/usb/host/xhci-mem.c
@@ -1146,7 +1146,6 @@ int xhci_setup_addressable_virt_dev(struct xhci_hcd 
*xhci, struct usb_device *ud
case USB_SPEED_WIRELESS:
xhci_dbg(xhci, "FIXME xHCI doesn't support wireless speeds\n");
return -EINVAL;
-   break;
default:
/* Speed was set earlier, this shouldn't happen. */
return -EINVAL;
diff --git a/drivers/usb/host/xhci-ring.c b/drivers/usb/host/xhci-ring.c
index d415911..2057d08 100644
--- a/drivers/usb/host/xhci-ring.c
+++ b/drivers/usb/host/xhci-ring.c
@@ -157,7 +157,6 @@ static void inc_deq(struct xhci_hcd *xhci, struct xhci_ring 
*ring)
ring->deq_seg = ring->deq_seg->next;
ring->dequeue = ring->deq_seg->trbs;
}
-   return;
 }
 
 /*
@@ -1167,7 +1166,6 @@ static void xhci_handle_cmd_config_ep(struct xhci_hcd 
*xhci, int slot_id,
ring_doorbell_for_active_rings(xhci, slot_id, ep_index);
return;
}
-   return;
 }
 
 static void xhci_handle_cmd_reset_dev(struct xhci_hcd *xhci, int slot_id,
@@ -1258,7 +1256,6 @@ static void xhci_handle_stopped_cmd_ring(struct xhci_hcd 
*xhci,
mod_timer(>cmd_timer, jiffies + XHCI_CMD_DEFAULT_TIMEOUT);
xhci_ring_cmd_db(xhci);
}
-   return;
 }
 
 
@@ -1307,7 +1304,6 @@ void xhci_handle_command_timeout(unsigned long data)
xhci_dbg(xhci, "Command timeout on stopped ring\n");
xhci_handle_stopped_cmd_ring(xhci, xhci->current_cmd);
spin_unlock_irqrestore(>lock, flags);
-   return;
 }
 
 static void handle_cmd_completion(struct xhci_hcd *xhci,
diff --git a/drivers/usb/host/xhci.c b/drivers/usb/host/xhci.c
index cf30cb6..dc337b3 100644
--- a/drivers/usb/host/xhci.c
+++ b/drivers/usb/host/xhci.c
@@ -269,8 +269,6 @@ static void xhci_free_irq(struct xhci_hcd *xhci)
return;
if (pdev->irq > 0)
free_irq(pdev->irq, xhci_to_hcd(xhci));
-
-   return;
 }
 
 /*
@@ -351,7 +349,6 @@ static void xhci_cleanup_msix(struct xhci_hcd *xhci)
}
 
hcd->msix_enabled = 0;
-   return;
 }
 
 static void __maybe_unused xhci_msix_sync_irqs(struct xhci_hcd *xhci)
-- 
1.7.9.5

--
To unsubscribe from this list: send the line "unsubscribe linux-usb" in
the body of a message to majord...@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html


Re: [PATCH v3 1/2] usb: host: plat: Enable xhci plat runtime PM

2016-11-24 Thread Baolin Wang
On 24 November 2016 at 01:39, kbuild test robot <l...@intel.com> wrote:
> Hi Baolin,
>
> [auto build test ERROR on v4.9-rc6]
> [also build test ERROR on next-20161123]
> [cannot apply to balbi-usb/next usb/usb-testing]
> [if your patch is applied to the wrong git tree, please drop us a note to 
> help improve the system]
>
> url:
> https://github.com/0day-ci/linux/commits/Baolin-Wang/usb-host-plat-Enable-xhci-plat-runtime-PM/20161124-012323
> config: x86_64-randconfig-x008-201647 (attached as .config)
> compiler: gcc-6 (Debian 6.2.0-3) 6.2.0 20160901
> reproduce:
> # save the attached .config to linux build tree
> make ARCH=x86_64
>
> All errors (new ones prefixed by >>):
>
>drivers/usb/host/xhci-plat.c: In function 'xhci_plat_remove':
>>> drivers/usb/host/xhci-plat.c:281:28: error: 'pdev' undeclared (first use in 
>>> this function)
>  pm_runtime_set_suspended(>dev);

Oops, will fix my mistake in new patch. Please ignore this patch. Sorry.

-- 
Baolin.wang
Best Regards
--
To unsubscribe from this list: send the line "unsubscribe linux-usb" in
the body of a message to majord...@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html


[PATCH v2] usb: xhci: Remove unuseful 'return' and 'break' statement

2016-11-24 Thread Baolin Wang
Since these 'return' statements are not generally useful in void
function, remove them. Also remove one unuseful 'break' statement
in xhci_setup_addressable_virt_dev() function.

Signed-off-by: Baolin Wang <baolin.w...@linaro.org>
---
Changes since v1:
 - Add description of removing 'break' statement in commitlog.
---
 drivers/usb/host/xhci-hub.c  |2 --
 drivers/usb/host/xhci-mem.c  |1 -
 drivers/usb/host/xhci-ring.c |4 
 drivers/usb/host/xhci.c  |3 ---
 4 files changed, 10 deletions(-)

diff --git a/drivers/usb/host/xhci-hub.c b/drivers/usb/host/xhci-hub.c
index 0ef1690..470ad66 100644
--- a/drivers/usb/host/xhci-hub.c
+++ b/drivers/usb/host/xhci-hub.c
@@ -444,8 +444,6 @@ void xhci_ring_device(struct xhci_hcd *xhci, int slot_id)
xhci_ring_ep_doorbell(xhci, slot_id, i, 0);
}
}
-
-   return;
 }
 
 static void xhci_disable_port(struct usb_hcd *hcd, struct xhci_hcd *xhci,
diff --git a/drivers/usb/host/xhci-mem.c b/drivers/usb/host/xhci-mem.c
index 48a26d378..d6f59a3 100644
--- a/drivers/usb/host/xhci-mem.c
+++ b/drivers/usb/host/xhci-mem.c
@@ -1146,7 +1146,6 @@ int xhci_setup_addressable_virt_dev(struct xhci_hcd 
*xhci, struct usb_device *ud
case USB_SPEED_WIRELESS:
xhci_dbg(xhci, "FIXME xHCI doesn't support wireless speeds\n");
return -EINVAL;
-   break;
default:
/* Speed was set earlier, this shouldn't happen. */
return -EINVAL;
diff --git a/drivers/usb/host/xhci-ring.c b/drivers/usb/host/xhci-ring.c
index d415911..2057d08 100644
--- a/drivers/usb/host/xhci-ring.c
+++ b/drivers/usb/host/xhci-ring.c
@@ -157,7 +157,6 @@ static void inc_deq(struct xhci_hcd *xhci, struct xhci_ring 
*ring)
ring->deq_seg = ring->deq_seg->next;
ring->dequeue = ring->deq_seg->trbs;
}
-   return;
 }
 
 /*
@@ -1167,7 +1166,6 @@ static void xhci_handle_cmd_config_ep(struct xhci_hcd 
*xhci, int slot_id,
ring_doorbell_for_active_rings(xhci, slot_id, ep_index);
return;
}
-   return;
 }
 
 static void xhci_handle_cmd_reset_dev(struct xhci_hcd *xhci, int slot_id,
@@ -1258,7 +1256,6 @@ static void xhci_handle_stopped_cmd_ring(struct xhci_hcd 
*xhci,
mod_timer(>cmd_timer, jiffies + XHCI_CMD_DEFAULT_TIMEOUT);
xhci_ring_cmd_db(xhci);
}
-   return;
 }
 
 
@@ -1307,7 +1304,6 @@ void xhci_handle_command_timeout(unsigned long data)
xhci_dbg(xhci, "Command timeout on stopped ring\n");
xhci_handle_stopped_cmd_ring(xhci, xhci->current_cmd);
spin_unlock_irqrestore(>lock, flags);
-   return;
 }
 
 static void handle_cmd_completion(struct xhci_hcd *xhci,
diff --git a/drivers/usb/host/xhci.c b/drivers/usb/host/xhci.c
index cf30cb6..dc337b3 100644
--- a/drivers/usb/host/xhci.c
+++ b/drivers/usb/host/xhci.c
@@ -269,8 +269,6 @@ static void xhci_free_irq(struct xhci_hcd *xhci)
return;
if (pdev->irq > 0)
free_irq(pdev->irq, xhci_to_hcd(xhci));
-
-   return;
 }
 
 /*
@@ -351,7 +349,6 @@ static void xhci_cleanup_msix(struct xhci_hcd *xhci)
}
 
hcd->msix_enabled = 0;
-   return;
 }
 
 static void __maybe_unused xhci_msix_sync_irqs(struct xhci_hcd *xhci)
-- 
1.7.9.5

--
To unsubscribe from this list: send the line "unsubscribe linux-usb" in
the body of a message to majord...@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html


Re: [PATCH] usb: xhci: Remove unuseful 'return' statement

2016-11-24 Thread Baolin Wang
Hi,

On 24 November 2016 at 17:30, Sergei Shtylyov
<sergei.shtyl...@cogentembedded.com> wrote:
> Hello.
>
> On 11/24/2016 11:13 AM, Baolin Wang wrote:
>
>> Since these 'return' statements are not generally useful in void function,
>> remove them.
>>
>> Signed-off-by: Baolin Wang <baolin.w...@linaro.org>
>
> [...]
>>
>> diff --git a/drivers/usb/host/xhci-mem.c b/drivers/usb/host/xhci-mem.c
>> index 48a26d378..d6f59a3 100644
>> --- a/drivers/usb/host/xhci-mem.c
>> +++ b/drivers/usb/host/xhci-mem.c
>> @@ -1146,7 +1146,6 @@ int xhci_setup_addressable_virt_dev(struct xhci_hcd
>> *xhci, struct usb_device *ud
>> case USB_SPEED_WIRELESS:
>> xhci_dbg(xhci, "FIXME xHCI doesn't support wireless
>> speeds\n");
>> return -EINVAL;
>> -   break;
>
>
>Here you're removing *break* instead but not mentioning this in the patch
> description...

OK. I will add description to explain it in new patch. Thanks.

-- 
Baolin.wang
Best Regards
--
To unsubscribe from this list: send the line "unsubscribe linux-usb" in
the body of a message to majord...@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html


Re: [PATCH v2] usb: xhci: Remove unuseful 'return' and 'break' statement

2016-11-28 Thread Baolin Wang
On 28 November 2016 at 23:14, Mathias Nyman
<mathias.ny...@linux.intel.com> wrote:
> On 28.11.2016 09:41, Baolin Wang wrote:
>>
>> On 28 November 2016 at 15:21, Greg KH <gre...@linuxfoundation.org> wrote:
>>>
>>> On Mon, Nov 28, 2016 at 02:29:25PM +0800, Baolin Wang wrote:
>>>>
>>>> Hi Mathias,
>>>>
>>>> On 24 November 2016 at 19:16, Baolin Wang <baolin.w...@linaro.org>
>>>> wrote:
>>>>>
>>>>> Since these 'return' statements are not generally useful in void
>>>>> function, remove them. Also remove one unuseful 'break' statement
>>>>> in xhci_setup_addressable_virt_dev() function.
>>>>>
>>>>> Signed-off-by: Baolin Wang <baolin.w...@linaro.org>
>>>>> ---
>>>>> Changes since v1:
>>>>>   - Add description of removing 'break' statement in commitlog.
>>>>> ---
>>>>
>>>>
>>>> Could you apply this patch if there are no other comments? Thanks.
>>>
>>>
>>> Less than a week response for a simple cleanup patch?  Why the rush and
>>> pressure?  Relax, this really isn't an important patch...
>>
>>
>> I am sorry for the pressure, I just thought it is one simple cleanup
>> patch. It is okay for me to wait for.
>>
>
> Looks ok.
>
> If it applies I'll send it forward to usb-next after 4.10-rc1,
> It should end up in 4.11

Thanks.

-- 
Baolin.wang
Best Regards
--
To unsubscribe from this list: send the line "unsubscribe linux-usb" in
the body of a message to majord...@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html


Re: [PATCH v2 1/4] usb: host: xhci: dynamically allocate devs array

2016-11-28 Thread Baolin Wang
On 28 November 2016 at 19:00, Felipe Balbi <felipe.ba...@linux.intel.com> wrote:
> Instead of always defaulting to a 256-entry array,
> we can dynamically allocate devs based on what HW
> tells us it supports.
>
> Note that we can't, yet, purge MAX_HC_SLOTS
> completely because of struct
> xhci_device_context_array reliance on it.
>
> Signed-off-by: Felipe Balbi <felipe.ba...@linux.intel.com>
> ---
>  drivers/usb/host/xhci-hub.c  |  2 +-
>  drivers/usb/host/xhci-mem.c  |  4 ++--
>  drivers/usb/host/xhci-ring.c |  2 +-
>  drivers/usb/host/xhci.c  | 19 +++
>  drivers/usb/host/xhci.h  |  2 +-
>  5 files changed, 20 insertions(+), 9 deletions(-)
>
> Changes since v1:
> - accounted for invalid slot 0 which driver assumes to exist.

Tested on my dwc3 platform, it can work well as host role.
Tested-by: Baolin Wang <baolin.w...@linaro.org>

-- 
Baolin.wang
Best Regards
--
To unsubscribe from this list: send the line "unsubscribe linux-usb" in
the body of a message to majord...@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html


Re: [PATCH v2] usb: xhci: Remove unuseful 'return' and 'break' statement

2016-11-27 Thread Baolin Wang
On 28 November 2016 at 15:21, Greg KH <gre...@linuxfoundation.org> wrote:
> On Mon, Nov 28, 2016 at 02:29:25PM +0800, Baolin Wang wrote:
>> Hi Mathias,
>>
>> On 24 November 2016 at 19:16, Baolin Wang <baolin.w...@linaro.org> wrote:
>> > Since these 'return' statements are not generally useful in void
>> > function, remove them. Also remove one unuseful 'break' statement
>> > in xhci_setup_addressable_virt_dev() function.
>> >
>> > Signed-off-by: Baolin Wang <baolin.w...@linaro.org>
>> > ---
>> > Changes since v1:
>> >  - Add description of removing 'break' statement in commitlog.
>> > ---
>>
>> Could you apply this patch if there are no other comments? Thanks.
>
> Less than a week response for a simple cleanup patch?  Why the rush and
> pressure?  Relax, this really isn't an important patch...

I am sorry for the pressure, I just thought it is one simple cleanup
patch. It is okay for me to wait for.

-- 
Baolin.wang
Best Regards
--
To unsubscribe from this list: send the line "unsubscribe linux-usb" in
the body of a message to majord...@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html


Re: [PATCH v18 0/4] Introduce usb charger framework to deal with the usb gadget power negotation

2016-11-27 Thread Baolin Wang
On 25 November 2016 at 21:00, Mark Brown  wrote:
> On Tue, Nov 22, 2016 at 09:40:07AM +1100, NeilBrown wrote:
>
>> I agree that the question of where the responsibility for information
>> aggregation lies is open for discussion. If fact all details on how
>> things should work are always open for discussion.
>> I don't agree that this is the main different between our positions,
>> though I can see how you might get that impression.
>
>> You could even fix them so they look *exactly* like the notifiers that
>> Baolin is proposing.  This is my key point.  It is not the end result
>> that I particularly object to (though I do object to some details).  It
>
> Ah, OK.  This really hadn't been at all clear - both Baolin and I had
> the impression that the it was both that were blockers for you.  What
> were the details here?
>
>> is the process of getting to the end result that I don't like.  If the
>> current system doesn't work and something different is needed, then the
>> correct thing to do is to transform the existing system into something
>> new that works better.  This should be a clear series of steps.  Each
>
> Sometimes there's something to be said for working out what we want
> things to look like before setting out to make these gradual
> refactorings and sometimes the refactorings are just more pain than
> they're worth, especially when they go across subsystems.  In this case
> I do worry about the cross subsystem aspect causing hassle, it may be
> more practical to do anything that represents an interface change by
> adding the new interface, converting the users to it and then removing
> the old interface.
>
> At the very least the series should grow to incorporate conversion of
> the existing users though.  Baolin, I think this does need adding to the
> series but probably best to think about how to do it - some of Neil's
> suggestions for incremental steps do seem like they should be useful
> for organizing things here, probably we can get some things that can be
> done internally within individual drivers merged while everything else
> is under discussion.

OK. I will think about how to incorporate conversion of the existing
users according to Neil's suggestion.

>
>> But I think here my key point got lost too, in part because it was hard
>> to refer to an actual instance.
>> My point was that in the present patch set, the "usb charger" is given
>> a name which is dependant on discovery order, and only supports
>> lookup-by-name.  This cannot work.
>
> There's two bits here: one is the way names are assigned and the other
> is the lookup by name.  I agree that the lookup by name isn't
> particularly useful as things stand, that could just be dropped until
> some naming mechanism is added.  We'd be more likely to use phandles in
> DT systems, I don't know what ACPI systems would look like but I guess
> it'd be something similar.
>
>> If they supported lookup by phy-name or lookup-by-active (i.e. "find me
>> any usb-charger which has power available"), or look up by some other
>> attribute, then discover-order naming could work.  But the only
>> lookup-mechanism is by-name, and the names aren't reliably stable.  So
>> the name/lookup system proposed cannot possibly do anything useful
>> with more than one usb_charger.
>
> Baolin, I think adding a DT binding and lookup mechanism makes sense
> here - do you agree?

Yes, I agree. But 'usb charger' is one virtual device and we described
nothing in DT about 'usb charger'. But as you and Neil said, we need
one usful method to look up the USB charger. I will think about that.
Thanks.

-- 
Baolin.wang
Best Regards
--
To unsubscribe from this list: send the line "unsubscribe linux-usb" in
the body of a message to majord...@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html


Re: [PATCH v2] usb: xhci: Remove unuseful 'return' and 'break' statement

2016-11-27 Thread Baolin Wang
Hi Mathias,

On 24 November 2016 at 19:16, Baolin Wang <baolin.w...@linaro.org> wrote:
> Since these 'return' statements are not generally useful in void
> function, remove them. Also remove one unuseful 'break' statement
> in xhci_setup_addressable_virt_dev() function.
>
> Signed-off-by: Baolin Wang <baolin.w...@linaro.org>
> ---
> Changes since v1:
>  - Add description of removing 'break' statement in commitlog.
> ---

Could you apply this patch if there are no other comments? Thanks.

-- 
Baolin.wang
Best Regards
--
To unsubscribe from this list: send the line "unsubscribe linux-usb" in
the body of a message to majord...@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html


[PATCH v4 1/2] usb: host: plat: Enable xhci plat runtime PM

2016-11-27 Thread Baolin Wang
Enable the xhci plat runtime PM for parent device to suspend/resume xhci.
Also call pm_runtime_get_noresume() in probe() function in case the parent
device doesn't call suspend/resume callback by runtime PM now.

Signed-off-by: Baolin Wang <baolin.w...@linaro.org>
---
Changes since v3:
 - Fix kbuild error.

Changes since v2:
 - Add pm_runtime_get_noresume() in probe() function.
 - Add pm_runtime_set_suspended()/pm_runtime_put_noidle() in remove() function.

Changes since v1:
 - No updates.
---
 drivers/usb/host/xhci-plat.c |   41 -
 1 file changed, 36 insertions(+), 5 deletions(-)

diff --git a/drivers/usb/host/xhci-plat.c b/drivers/usb/host/xhci-plat.c
index ed56bf9..5805c6a 100644
--- a/drivers/usb/host/xhci-plat.c
+++ b/drivers/usb/host/xhci-plat.c
@@ -246,6 +246,10 @@ static int xhci_plat_probe(struct platform_device *pdev)
if (ret)
goto dealloc_usb2_hcd;
 
+   pm_runtime_get_noresume(>dev);
+   pm_runtime_set_active(>dev);
+   pm_runtime_enable(>dev);
+
return 0;
 
 
@@ -274,6 +278,10 @@ static int xhci_plat_remove(struct platform_device *dev)
struct xhci_hcd *xhci = hcd_to_xhci(hcd);
struct clk *clk = xhci->clk;
 
+   pm_runtime_set_suspended(>dev);
+   pm_runtime_put_noidle(>dev);
+   pm_runtime_disable(>dev);
+
usb_remove_hcd(xhci->shared_hcd);
usb_phy_shutdown(hcd->usb_phy);
 
@@ -311,14 +319,37 @@ static int xhci_plat_resume(struct device *dev)
 
return xhci_resume(xhci, 0);
 }
+#endif /* CONFIG_PM_SLEEP */
+
+#ifdef CONFIG_PM
+static int xhci_plat_runtime_suspend(struct device *dev)
+{
+   struct usb_hcd  *hcd = dev_get_drvdata(dev);
+   struct xhci_hcd *xhci = hcd_to_xhci(hcd);
+
+   return xhci_suspend(xhci, device_may_wakeup(dev));
+}
+
+static int xhci_plat_runtime_resume(struct device *dev)
+{
+   struct usb_hcd  *hcd = dev_get_drvdata(dev);
+   struct xhci_hcd *xhci = hcd_to_xhci(hcd);
+
+   return xhci_resume(xhci, 0);
+}
+
+static int xhci_plat_runtime_idle(struct device *dev)
+{
+   return 0;
+}
+#endif /* CONFIG_PM */
 
 static const struct dev_pm_ops xhci_plat_pm_ops = {
SET_SYSTEM_SLEEP_PM_OPS(xhci_plat_suspend, xhci_plat_resume)
+
+   SET_RUNTIME_PM_OPS(xhci_plat_runtime_suspend, xhci_plat_runtime_resume,
+  xhci_plat_runtime_idle)
 };
-#define DEV_PM_OPS (_plat_pm_ops)
-#else
-#define DEV_PM_OPS NULL
-#endif /* CONFIG_PM */
 
 static const struct acpi_device_id usb_xhci_acpi_match[] = {
/* XHCI-compliant USB Controller */
@@ -332,7 +363,7 @@ static int xhci_plat_resume(struct device *dev)
.remove = xhci_plat_remove,
.driver = {
.name = "xhci-hcd",
-   .pm = DEV_PM_OPS,
+   .pm = _plat_pm_ops,
.of_match_table = of_match_ptr(usb_xhci_of_match),
.acpi_match_table = ACPI_PTR(usb_xhci_acpi_match),
},
-- 
1.7.9.5

--
To unsubscribe from this list: send the line "unsubscribe linux-usb" in
the body of a message to majord...@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html


[PATCH v4 2/2] usb: dwc3: core: Support the dwc3 host suspend/resume

2016-11-27 Thread Baolin Wang
For some mobile devices with strict power management, we also want to suspend
the host when the slave is detached for power saving. Thus we add the host
suspend/resume functions to support this requirement.

Signed-off-by: Baolin Wang <baolin.w...@linaro.org>
---
Changes since v3:
 - No updates.

Changes since v2:
 - Remove pm_children_suspended() and other unused macros.

 Changes since v1:
   - Add pm_runtime.h head file to avoid kbuild error.
---
 drivers/usb/dwc3/Kconfig |7 +++
 drivers/usb/dwc3/core.c  |   26 +-
 drivers/usb/dwc3/core.h  |   15 +++
 drivers/usb/dwc3/host.c  |   37 +
 4 files changed, 84 insertions(+), 1 deletion(-)

diff --git a/drivers/usb/dwc3/Kconfig b/drivers/usb/dwc3/Kconfig
index a45b4f1..47bb2f3 100644
--- a/drivers/usb/dwc3/Kconfig
+++ b/drivers/usb/dwc3/Kconfig
@@ -47,6 +47,13 @@ config USB_DWC3_DUAL_ROLE
 
 endchoice
 
+config USB_DWC3_HOST_SUSPEND
+   bool "Choose if the DWC3 host (xhci) can be suspend/resume"
+   depends on USB_DWC3_HOST=y || USB_DWC3_DUAL_ROLE=y
+   help
+ We can suspend the host when the slave is detached for power saving,
+ and resume the host when one slave is attached.
+
 comment "Platform Glue Driver Support"
 
 config USB_DWC3_OMAP
diff --git a/drivers/usb/dwc3/core.c b/drivers/usb/dwc3/core.c
index 9a4a5e4..7ad4bc3 100644
--- a/drivers/usb/dwc3/core.c
+++ b/drivers/usb/dwc3/core.c
@@ -1091,6 +1091,7 @@ static int dwc3_probe(struct platform_device *pdev)
pm_runtime_use_autosuspend(dev);
pm_runtime_set_autosuspend_delay(dev, DWC3_DEFAULT_AUTOSUSPEND_DELAY);
pm_runtime_enable(dev);
+   pm_suspend_ignore_children(dev, true);
ret = pm_runtime_get_sync(dev);
if (ret < 0)
goto err1;
@@ -1215,15 +1216,27 @@ static int dwc3_remove(struct platform_device *pdev)
 static int dwc3_suspend_common(struct dwc3 *dwc)
 {
unsigned long   flags;
+   int ret;
 
switch (dwc->dr_mode) {
case USB_DR_MODE_PERIPHERAL:
+   spin_lock_irqsave(>lock, flags);
+   dwc3_gadget_suspend(dwc);
+   spin_unlock_irqrestore(>lock, flags);
+   break;
case USB_DR_MODE_OTG:
+   ret = dwc3_host_suspend(dwc);
+   if (ret)
+   return ret;
+
spin_lock_irqsave(>lock, flags);
dwc3_gadget_suspend(dwc);
spin_unlock_irqrestore(>lock, flags);
break;
case USB_DR_MODE_HOST:
+   ret = dwc3_host_suspend(dwc);
+   if (ret)
+   return ret;
default:
/* do nothing */
break;
@@ -1245,12 +1258,23 @@ static int dwc3_resume_common(struct dwc3 *dwc)
 
switch (dwc->dr_mode) {
case USB_DR_MODE_PERIPHERAL:
+   spin_lock_irqsave(>lock, flags);
+   dwc3_gadget_resume(dwc);
+   spin_unlock_irqrestore(>lock, flags);
+   break;
case USB_DR_MODE_OTG:
+   ret = dwc3_host_resume(dwc);
+   if (ret)
+   return ret;
+
spin_lock_irqsave(>lock, flags);
dwc3_gadget_resume(dwc);
spin_unlock_irqrestore(>lock, flags);
-   /* FALLTHROUGH */
+   break;
case USB_DR_MODE_HOST:
+   ret = dwc3_host_resume(dwc);
+   if (ret)
+   return ret;
default:
/* do nothing */
break;
diff --git a/drivers/usb/dwc3/core.h b/drivers/usb/dwc3/core.h
index b585a30..db41908 100644
--- a/drivers/usb/dwc3/core.h
+++ b/drivers/usb/dwc3/core.h
@@ -1226,4 +1226,19 @@ static inline void dwc3_ulpi_exit(struct dwc3 *dwc)
 { }
 #endif
 
+#if IS_ENABLED(CONFIG_USB_DWC3_HOST_SUSPEND)
+int dwc3_host_suspend(struct dwc3 *dwc);
+int dwc3_host_resume(struct dwc3 *dwc);
+#else
+static inline int dwc3_host_suspend(struct dwc3 *dwc)
+{
+   return 0;
+}
+
+static inline int dwc3_host_resume(struct dwc3 *dwc)
+{
+   return 0;
+}
+#endif
+
 #endif /* __DRIVERS_USB_DWC3_CORE_H */
diff --git a/drivers/usb/dwc3/host.c b/drivers/usb/dwc3/host.c
index ed82464..8e5309d6 100644
--- a/drivers/usb/dwc3/host.c
+++ b/drivers/usb/dwc3/host.c
@@ -16,6 +16,7 @@
  */
 
 #include 
+#include 
 
 #include "core.h"
 
@@ -130,3 +131,39 @@ void dwc3_host_exit(struct dwc3 *dwc)
  dev_name(>xhci->dev));
platform_device_unregister(dwc->xhci);
 }
+
+#ifdef CONFIG_USB_DWC3_HOST_SUSPEND
+int dwc3_host_suspend(struct dwc3 *dwc)
+{
+   struct device *xhci = >xhci->dev;
+   int ret;
+
+   /*
+* Note: if we get the -EBUSY, which means the xHCI children devices are
+* not in suspend state yet, the glue layer need to wait 

[PATCH 2/2] usb: dwc3: core: Support the dwc3 host suspend/resume

2016-11-18 Thread Baolin Wang
For some mobile devices with strict power management, we also want to suspend
the host when the slave is detached for power saving. Thus we add the host
suspend/resume functions to support this requirement.

Signed-off-by: Baolin Wang <baolin.w...@linaro.org>
---
 drivers/usb/dwc3/Kconfig |7 ++
 drivers/usb/dwc3/core.c  |   26 ++-
 drivers/usb/dwc3/core.h  |   15 +
 drivers/usb/dwc3/host.c  |   53 ++
 4 files changed, 100 insertions(+), 1 deletion(-)

diff --git a/drivers/usb/dwc3/Kconfig b/drivers/usb/dwc3/Kconfig
index a45b4f1..47bb2f3 100644
--- a/drivers/usb/dwc3/Kconfig
+++ b/drivers/usb/dwc3/Kconfig
@@ -47,6 +47,13 @@ config USB_DWC3_DUAL_ROLE
 
 endchoice
 
+config USB_DWC3_HOST_SUSPEND
+   bool "Choose if the DWC3 host (xhci) can be suspend/resume"
+   depends on USB_DWC3_HOST=y || USB_DWC3_DUAL_ROLE=y
+   help
+ We can suspend the host when the slave is detached for power saving,
+ and resume the host when one slave is attached.
+
 comment "Platform Glue Driver Support"
 
 config USB_DWC3_OMAP
diff --git a/drivers/usb/dwc3/core.c b/drivers/usb/dwc3/core.c
index 9a4a5e4..7ad4bc3 100644
--- a/drivers/usb/dwc3/core.c
+++ b/drivers/usb/dwc3/core.c
@@ -1091,6 +1091,7 @@ static int dwc3_probe(struct platform_device *pdev)
pm_runtime_use_autosuspend(dev);
pm_runtime_set_autosuspend_delay(dev, DWC3_DEFAULT_AUTOSUSPEND_DELAY);
pm_runtime_enable(dev);
+   pm_suspend_ignore_children(dev, true);
ret = pm_runtime_get_sync(dev);
if (ret < 0)
goto err1;
@@ -1215,15 +1216,27 @@ static int dwc3_remove(struct platform_device *pdev)
 static int dwc3_suspend_common(struct dwc3 *dwc)
 {
unsigned long   flags;
+   int ret;
 
switch (dwc->dr_mode) {
case USB_DR_MODE_PERIPHERAL:
+   spin_lock_irqsave(>lock, flags);
+   dwc3_gadget_suspend(dwc);
+   spin_unlock_irqrestore(>lock, flags);
+   break;
case USB_DR_MODE_OTG:
+   ret = dwc3_host_suspend(dwc);
+   if (ret)
+   return ret;
+
spin_lock_irqsave(>lock, flags);
dwc3_gadget_suspend(dwc);
spin_unlock_irqrestore(>lock, flags);
break;
case USB_DR_MODE_HOST:
+   ret = dwc3_host_suspend(dwc);
+   if (ret)
+   return ret;
default:
/* do nothing */
break;
@@ -1245,12 +1258,23 @@ static int dwc3_resume_common(struct dwc3 *dwc)
 
switch (dwc->dr_mode) {
case USB_DR_MODE_PERIPHERAL:
+   spin_lock_irqsave(>lock, flags);
+   dwc3_gadget_resume(dwc);
+   spin_unlock_irqrestore(>lock, flags);
+   break;
case USB_DR_MODE_OTG:
+   ret = dwc3_host_resume(dwc);
+   if (ret)
+   return ret;
+
spin_lock_irqsave(>lock, flags);
dwc3_gadget_resume(dwc);
spin_unlock_irqrestore(>lock, flags);
-   /* FALLTHROUGH */
+   break;
case USB_DR_MODE_HOST:
+   ret = dwc3_host_resume(dwc);
+   if (ret)
+   return ret;
default:
/* do nothing */
break;
diff --git a/drivers/usb/dwc3/core.h b/drivers/usb/dwc3/core.h
index b585a30..db41908 100644
--- a/drivers/usb/dwc3/core.h
+++ b/drivers/usb/dwc3/core.h
@@ -1226,4 +1226,19 @@ static inline void dwc3_ulpi_exit(struct dwc3 *dwc)
 { }
 #endif
 
+#if IS_ENABLED(CONFIG_USB_DWC3_HOST_SUSPEND)
+int dwc3_host_suspend(struct dwc3 *dwc);
+int dwc3_host_resume(struct dwc3 *dwc);
+#else
+static inline int dwc3_host_suspend(struct dwc3 *dwc)
+{
+   return 0;
+}
+
+static inline int dwc3_host_resume(struct dwc3 *dwc)
+{
+   return 0;
+}
+#endif
+
 #endif /* __DRIVERS_USB_DWC3_CORE_H */
diff --git a/drivers/usb/dwc3/host.c b/drivers/usb/dwc3/host.c
index ed82464..541d27c 100644
--- a/drivers/usb/dwc3/host.c
+++ b/drivers/usb/dwc3/host.c
@@ -19,6 +19,9 @@
 
 #include "core.h"
 
+#define DWC3_HOST_SUSPEND_COUNT100
+#define DWC3_HOST_SUSPEND_TIMEOUT  100
+
 static int dwc3_host_get_irq(struct dwc3 *dwc)
 {
struct platform_device  *dwc3_pdev = to_platform_device(dwc->dev);
@@ -130,3 +133,53 @@ void dwc3_host_exit(struct dwc3 *dwc)
  dev_name(>xhci->dev));
platform_device_unregister(dwc->xhci);
 }
+
+#ifdef CONFIG_USB_DWC3_HOST_SUSPEND
+int dwc3_host_suspend(struct dwc3 *dwc)
+{
+   struct device *xhci = >xhci->dev;
+   int ret, cnt = DWC3_HOST_SUSPEND_COUNT;
+
+   /*
+* We need make sure the children of the xHCI device had been into
+* suspend state, or we 

[PATCH 1/2] usb: host: plat: Enable xhci plat runtime PM

2016-11-18 Thread Baolin Wang
Enable the xhci plat runtime PM for parent device to suspend/resume xhci.

Signed-off-by: Baolin Wang <baolin.w...@linaro.org>
---
 drivers/usb/host/xhci-plat.c |   37 -
 1 file changed, 32 insertions(+), 5 deletions(-)

diff --git a/drivers/usb/host/xhci-plat.c b/drivers/usb/host/xhci-plat.c
index ed56bf9..13f86ad 100644
--- a/drivers/usb/host/xhci-plat.c
+++ b/drivers/usb/host/xhci-plat.c
@@ -246,6 +246,9 @@ static int xhci_plat_probe(struct platform_device *pdev)
if (ret)
goto dealloc_usb2_hcd;
 
+   pm_runtime_set_active(>dev);
+   pm_runtime_enable(>dev);
+
return 0;
 
 
@@ -274,6 +277,7 @@ static int xhci_plat_remove(struct platform_device *dev)
struct xhci_hcd *xhci = hcd_to_xhci(hcd);
struct clk *clk = xhci->clk;
 
+   pm_runtime_disable(>dev);
usb_remove_hcd(xhci->shared_hcd);
usb_phy_shutdown(hcd->usb_phy);
 
@@ -311,14 +315,37 @@ static int xhci_plat_resume(struct device *dev)
 
return xhci_resume(xhci, 0);
 }
+#endif /* CONFIG_PM_SLEEP */
+
+#ifdef CONFIG_PM
+static int xhci_plat_runtime_suspend(struct device *dev)
+{
+   struct usb_hcd  *hcd = dev_get_drvdata(dev);
+   struct xhci_hcd *xhci = hcd_to_xhci(hcd);
+
+   return xhci_suspend(xhci, device_may_wakeup(dev));
+}
+
+static int xhci_plat_runtime_resume(struct device *dev)
+{
+   struct usb_hcd  *hcd = dev_get_drvdata(dev);
+   struct xhci_hcd *xhci = hcd_to_xhci(hcd);
+
+   return xhci_resume(xhci, 0);
+}
+
+static int xhci_plat_runtime_idle(struct device *dev)
+{
+   return 0;
+}
+#endif /* CONFIG_PM */
 
 static const struct dev_pm_ops xhci_plat_pm_ops = {
SET_SYSTEM_SLEEP_PM_OPS(xhci_plat_suspend, xhci_plat_resume)
+
+   SET_RUNTIME_PM_OPS(xhci_plat_runtime_suspend, xhci_plat_runtime_resume,
+  xhci_plat_runtime_idle)
 };
-#define DEV_PM_OPS (_plat_pm_ops)
-#else
-#define DEV_PM_OPS NULL
-#endif /* CONFIG_PM */
 
 static const struct acpi_device_id usb_xhci_acpi_match[] = {
/* XHCI-compliant USB Controller */
@@ -332,7 +359,7 @@ static int xhci_plat_resume(struct device *dev)
.remove = xhci_plat_remove,
.driver = {
.name = "xhci-hcd",
-   .pm = DEV_PM_OPS,
+   .pm = _plat_pm_ops,
.of_match_table = of_match_ptr(usb_xhci_of_match),
.acpi_match_table = ACPI_PTR(usb_xhci_acpi_match),
},
-- 
1.7.9.5

--
To unsubscribe from this list: send the line "unsubscribe linux-usb" in
the body of a message to majord...@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html


Re: [PATCH] usb: dwc3: core: Disable USB2.0 phy suspend when dwc3 acts as host role

2016-11-15 Thread Baolin Wang
Hi,

On 15 November 2016 at 18:49, Felipe Balbi <ba...@kernel.org> wrote:
>
> Hi,
>
> Baolin Wang <baolin.w...@linaro.org> writes:
>> When dwc3 controller acts as host role with attaching slow speed device
>> (like mouse or keypad). Then if we plugged out the slow speed device,
>> it will timeout to run the deconfiguration endpoint command to drop the
>> endpoint's resources. Some xHCI command timeout log as below when
>> disconnecting one slow device:
>>
>> [   99.807739] c0 xhci-hcd.0.auto: Port Status Change Event for port 1
>> [   99.814699] c0 xhci-hcd.0.auto: resume root hub
>> [   99.819992] c0 xhci-hcd.0.auto: handle_port_status: starting port
>>  polling.
>> [   99.827808] c0 xhci-hcd.0.auto: get port status, actual port 0 status
>>  = 0x202a0
>> [   99.835903] c0 xhci-hcd.0.auto: Get port status returned 0x10100
>> [   99.850052] c0 xhci-hcd.0.auto: clear port connect change, actual
>>  port 0 status  = 0x2a0
>> [   99.859313] c0 xhci-hcd.0.auto: Cancel URB ffc01ed6cd00, dev 1,
>>  ep 0x81, starting at offset 0xc406d210
>> [   99.869645] c0 xhci-hcd.0.auto: // Ding dong!
>> [   99.874776] c0 xhci-hcd.0.auto: Stopped on Transfer TRB
>> [   99.880713] c0 xhci-hcd.0.auto: Removing canceled TD starting at
>>  0xc406d210 (dma).
>> [   99.889012] c0 xhci-hcd.0.auto: Finding endpoint context
>> [   99.895069] c0 xhci-hcd.0.auto: Cycle state = 0x1
>> [   99.900519] c0 xhci-hcd.0.auto: New dequeue segment =
>>  ffc1112f0880 (virtual)
>> [   99.908655] c0 xhci-hcd.0.auto: New dequeue pointer = 0xc406d220 (DMA)
>> [   99.915927] c0 xhci-hcd.0.auto: Set TR Deq Ptr cmd, new deq seg =
>>  ffc1112f0880 (0xc406d000 dma),
>>  new deq ptr = ff8002175220
>>  (0xc406d220 dma), new cycle = 1
>> [   99.931242] c0 xhci-hcd.0.auto: // Ding dong!
>> [   99.936360] c0 xhci-hcd.0.auto: Successful Set TR Deq Ptr cmd,
>>  deq = @c406d220
>> [   99.944458] c0 xhci-hcd.0.auto: xhci_hub_status_data: stopping port
>>  polling.
>> [  100.047619] c0 xhci-hcd.0.auto: xhci_drop_endpoint called for udev
>>  ffc01ae08800
>> [  100.057002] c0 xhci-hcd.0.auto: drop ep 0x81, slot id 1, new drop
>>  flags = 0x8, new add flags = 0x0
>> [  100.067878] c0 xhci-hcd.0.auto: xhci_check_bandwidth called for udev
>>  ffc01ae08800
>> [  100.076868] c0 xhci-hcd.0.auto: New Input Control Context:
>>
>> ..
>>
>> [  100.427252] c0 xhci-hcd.0.auto: // Ding dong!
>> [  105.430728] c0 xhci-hcd.0.auto: Command timeout
>> [  105.436029] c0 xhci-hcd.0.auto: Abort command ring
>> [  113.558223] c0 xhci-hcd.0.auto: Command completion event does not match
>>  command
>> [  113.569778] c0 xhci-hcd.0.auto: Timeout while waiting for configure
>>      endpoint command
>>
>> The reason is it will suspend USB phy to disable phy clock when
>> disconnecting the slow USB decice, that will hang on the xHCI commands
>> executing which depends on the phy clock.
>>
>> Thus we should disable USB2.0 phy suspend feature when dwc3 acts as host
>> role.
>>
>> Signed-off-by: Baolin Wang <baolin.w...@linaro.org>
>> ---
>>  drivers/usb/dwc3/core.c |   14 ++
>>  1 file changed, 14 insertions(+)
>>
>> diff --git a/drivers/usb/dwc3/core.c b/drivers/usb/dwc3/core.c
>> index 9a4a5e4..0b646cf 100644
>> --- a/drivers/usb/dwc3/core.c
>> +++ b/drivers/usb/dwc3/core.c
>> @@ -565,6 +565,20 @@ static int dwc3_phy_setup(struct dwc3 *dwc)
>>   if (dwc->revision > DWC3_REVISION_194A)
>>   reg |= DWC3_GUSB2PHYCFG_SUSPHY;
>>
>> + /*
>> +  * When dwc3 controller acts as host role with attaching one slow speed
>> +  * device (like mouse or keypad). Then if we plugged out the slow speed
>> +  * device, it will timeout to run the deconfiguration endpoint command.
>> +  * The reason is it will suspend USB phy to disable phy clock when
>> +  * disconnecting slow speed decice, which will affect the xHCI commands
>> +  * executing.
>> +  *
>> +  * Thus we should disable USB 2.0 phy suspend featur

Re: [PATCH 2/2] usb: dwc3: core: Support the dwc3 host suspend/resume

2016-11-20 Thread Baolin Wang
On 18 November 2016 at 21:14, kbuild test robot <l...@intel.com> wrote:
> Hi Baolin,
>
> [auto build test ERROR on next-20161117]
> [cannot apply to balbi-usb/next usb/usb-testing v4.9-rc5 v4.9-rc4 v4.9-rc3 
> v4.9-rc5]
> [if your patch is applied to the wrong git tree, please drop us a note to 
> help improve the system]
>
> url:
> https://github.com/0day-ci/linux/commits/Baolin-Wang/usb-host-plat-Enable-xhci-plat-runtime-PM/20161118-202029
> config: i386-allmodconfig (attached as .config)
> compiler: gcc-6 (Debian 6.2.0-3) 6.2.0 20160901
> reproduce:
> # save the attached .config to linux build tree
> make ARCH=i386
>
> All errors (new ones prefixed by >>):
>
>drivers/usb/dwc3/host.c: In function 'dwc3_host_suspend':
>>> drivers/usb/dwc3/host.c:157:10: error: implicit declaration of function 
>>> 'pm_children_suspended' [-Werror=implicit-function-declaration]
>  while (!pm_children_suspended(xhci) && --cnt > 0)
>  ^
>cc1: some warnings being treated as errors
>
> vim +/pm_children_suspended +157 drivers/usb/dwc3/host.c
>
>151  int ret, cnt = DWC3_HOST_SUSPEND_COUNT;
>152
>153  /*
>154   * We need make sure the children of the xHCI device had been 
> into
>155   * suspend state, or we will suspend xHCI device failed.
>156   */
>  > 157  while (!pm_children_suspended(xhci) && --cnt > 0)
>158  msleep(DWC3_HOST_SUSPEND_TIMEOUT);
>159
>160  if (cnt <= 0) {

I will send out new patch to fix this building error.

-- 
Baolin.wang
Best Regards
--
To unsubscribe from this list: send the line "unsubscribe linux-usb" in
the body of a message to majord...@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html


[PATCH v2 2/2] usb: dwc3: core: Support the dwc3 host suspend/resume

2016-11-20 Thread Baolin Wang
For some mobile devices with strict power management, we also want to suspend
the host when the slave is detached for power saving. Thus we add the host
suspend/resume functions to support this requirement.

Signed-off-by: Baolin Wang <baolin.w...@linaro.org>
---
Changes since v1:
 - Add pm_runtime.h head file to avoid kbuild error.
---
 drivers/usb/dwc3/Kconfig |7 ++
 drivers/usb/dwc3/core.c  |   26 +-
 drivers/usb/dwc3/core.h  |   15 +
 drivers/usb/dwc3/host.c  |   54 ++
 4 files changed, 101 insertions(+), 1 deletion(-)

diff --git a/drivers/usb/dwc3/Kconfig b/drivers/usb/dwc3/Kconfig
index a45b4f1..47bb2f3 100644
--- a/drivers/usb/dwc3/Kconfig
+++ b/drivers/usb/dwc3/Kconfig
@@ -47,6 +47,13 @@ config USB_DWC3_DUAL_ROLE
 
 endchoice
 
+config USB_DWC3_HOST_SUSPEND
+   bool "Choose if the DWC3 host (xhci) can be suspend/resume"
+   depends on USB_DWC3_HOST=y || USB_DWC3_DUAL_ROLE=y
+   help
+ We can suspend the host when the slave is detached for power saving,
+ and resume the host when one slave is attached.
+
 comment "Platform Glue Driver Support"
 
 config USB_DWC3_OMAP
diff --git a/drivers/usb/dwc3/core.c b/drivers/usb/dwc3/core.c
index 9a4a5e4..7ad4bc3 100644
--- a/drivers/usb/dwc3/core.c
+++ b/drivers/usb/dwc3/core.c
@@ -1091,6 +1091,7 @@ static int dwc3_probe(struct platform_device *pdev)
pm_runtime_use_autosuspend(dev);
pm_runtime_set_autosuspend_delay(dev, DWC3_DEFAULT_AUTOSUSPEND_DELAY);
pm_runtime_enable(dev);
+   pm_suspend_ignore_children(dev, true);
ret = pm_runtime_get_sync(dev);
if (ret < 0)
goto err1;
@@ -1215,15 +1216,27 @@ static int dwc3_remove(struct platform_device *pdev)
 static int dwc3_suspend_common(struct dwc3 *dwc)
 {
unsigned long   flags;
+   int ret;
 
switch (dwc->dr_mode) {
case USB_DR_MODE_PERIPHERAL:
+   spin_lock_irqsave(>lock, flags);
+   dwc3_gadget_suspend(dwc);
+   spin_unlock_irqrestore(>lock, flags);
+   break;
case USB_DR_MODE_OTG:
+   ret = dwc3_host_suspend(dwc);
+   if (ret)
+   return ret;
+
spin_lock_irqsave(>lock, flags);
dwc3_gadget_suspend(dwc);
spin_unlock_irqrestore(>lock, flags);
break;
case USB_DR_MODE_HOST:
+   ret = dwc3_host_suspend(dwc);
+   if (ret)
+   return ret;
default:
/* do nothing */
break;
@@ -1245,12 +1258,23 @@ static int dwc3_resume_common(struct dwc3 *dwc)
 
switch (dwc->dr_mode) {
case USB_DR_MODE_PERIPHERAL:
+   spin_lock_irqsave(>lock, flags);
+   dwc3_gadget_resume(dwc);
+   spin_unlock_irqrestore(>lock, flags);
+   break;
case USB_DR_MODE_OTG:
+   ret = dwc3_host_resume(dwc);
+   if (ret)
+   return ret;
+
spin_lock_irqsave(>lock, flags);
dwc3_gadget_resume(dwc);
spin_unlock_irqrestore(>lock, flags);
-   /* FALLTHROUGH */
+   break;
case USB_DR_MODE_HOST:
+   ret = dwc3_host_resume(dwc);
+   if (ret)
+   return ret;
default:
/* do nothing */
break;
diff --git a/drivers/usb/dwc3/core.h b/drivers/usb/dwc3/core.h
index b585a30..db41908 100644
--- a/drivers/usb/dwc3/core.h
+++ b/drivers/usb/dwc3/core.h
@@ -1226,4 +1226,19 @@ static inline void dwc3_ulpi_exit(struct dwc3 *dwc)
 { }
 #endif
 
+#if IS_ENABLED(CONFIG_USB_DWC3_HOST_SUSPEND)
+int dwc3_host_suspend(struct dwc3 *dwc);
+int dwc3_host_resume(struct dwc3 *dwc);
+#else
+static inline int dwc3_host_suspend(struct dwc3 *dwc)
+{
+   return 0;
+}
+
+static inline int dwc3_host_resume(struct dwc3 *dwc)
+{
+   return 0;
+}
+#endif
+
 #endif /* __DRIVERS_USB_DWC3_CORE_H */
diff --git a/drivers/usb/dwc3/host.c b/drivers/usb/dwc3/host.c
index ed82464..20e84fc 100644
--- a/drivers/usb/dwc3/host.c
+++ b/drivers/usb/dwc3/host.c
@@ -16,9 +16,13 @@
  */
 
 #include 
+#include 
 
 #include "core.h"
 
+#define DWC3_HOST_SUSPEND_COUNT100
+#define DWC3_HOST_SUSPEND_TIMEOUT  100
+
 static int dwc3_host_get_irq(struct dwc3 *dwc)
 {
struct platform_device  *dwc3_pdev = to_platform_device(dwc->dev);
@@ -130,3 +134,53 @@ void dwc3_host_exit(struct dwc3 *dwc)
  dev_name(>xhci->dev));
platform_device_unregister(dwc->xhci);
 }
+
+#ifdef CONFIG_USB_DWC3_HOST_SUSPEND
+int dwc3_host_suspend(struct dwc3 *dwc)
+{
+   struct device *xhci = >xhci->dev;
+   int ret, cnt = DWC3_HOST_SUSPEND_COUNT;
+
+   /*
+ 

[PATCH v2 1/2] usb: host: plat: Enable xhci plat runtime PM

2016-11-20 Thread Baolin Wang
Enable the xhci plat runtime PM for parent device to suspend/resume xhci.

Signed-off-by: Baolin Wang <baolin.w...@linaro.org>
---
Changes since v1:
 - No updates.
---
 drivers/usb/host/xhci-plat.c |   37 -
 1 file changed, 32 insertions(+), 5 deletions(-)

diff --git a/drivers/usb/host/xhci-plat.c b/drivers/usb/host/xhci-plat.c
index ed56bf9..13f86ad 100644
--- a/drivers/usb/host/xhci-plat.c
+++ b/drivers/usb/host/xhci-plat.c
@@ -246,6 +246,9 @@ static int xhci_plat_probe(struct platform_device *pdev)
if (ret)
goto dealloc_usb2_hcd;
 
+   pm_runtime_set_active(>dev);
+   pm_runtime_enable(>dev);
+
return 0;
 
 
@@ -274,6 +277,7 @@ static int xhci_plat_remove(struct platform_device *dev)
struct xhci_hcd *xhci = hcd_to_xhci(hcd);
struct clk *clk = xhci->clk;
 
+   pm_runtime_disable(>dev);
usb_remove_hcd(xhci->shared_hcd);
usb_phy_shutdown(hcd->usb_phy);
 
@@ -311,14 +315,37 @@ static int xhci_plat_resume(struct device *dev)
 
return xhci_resume(xhci, 0);
 }
+#endif /* CONFIG_PM_SLEEP */
+
+#ifdef CONFIG_PM
+static int xhci_plat_runtime_suspend(struct device *dev)
+{
+   struct usb_hcd  *hcd = dev_get_drvdata(dev);
+   struct xhci_hcd *xhci = hcd_to_xhci(hcd);
+
+   return xhci_suspend(xhci, device_may_wakeup(dev));
+}
+
+static int xhci_plat_runtime_resume(struct device *dev)
+{
+   struct usb_hcd  *hcd = dev_get_drvdata(dev);
+   struct xhci_hcd *xhci = hcd_to_xhci(hcd);
+
+   return xhci_resume(xhci, 0);
+}
+
+static int xhci_plat_runtime_idle(struct device *dev)
+{
+   return 0;
+}
+#endif /* CONFIG_PM */
 
 static const struct dev_pm_ops xhci_plat_pm_ops = {
SET_SYSTEM_SLEEP_PM_OPS(xhci_plat_suspend, xhci_plat_resume)
+
+   SET_RUNTIME_PM_OPS(xhci_plat_runtime_suspend, xhci_plat_runtime_resume,
+  xhci_plat_runtime_idle)
 };
-#define DEV_PM_OPS (_plat_pm_ops)
-#else
-#define DEV_PM_OPS NULL
-#endif /* CONFIG_PM */
 
 static const struct acpi_device_id usb_xhci_acpi_match[] = {
/* XHCI-compliant USB Controller */
@@ -332,7 +359,7 @@ static int xhci_plat_resume(struct device *dev)
.remove = xhci_plat_remove,
.driver = {
.name = "xhci-hcd",
-   .pm = DEV_PM_OPS,
+   .pm = _plat_pm_ops,
.of_match_table = of_match_ptr(usb_xhci_of_match),
.acpi_match_table = ACPI_PTR(usb_xhci_acpi_match),
},
-- 
1.7.9.5

--
To unsubscribe from this list: send the line "unsubscribe linux-usb" in
the body of a message to majord...@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html


[PATCH v2] usb: dwc3: gadget: wait for End Transfer to complete

2016-10-31 Thread Baolin Wang
Instead of just delaying for 100us, we should
actually wait for End Transfer Command Complete
interrupt before moving on. Note that this should
only be done if we're dealing with one of the core
revisions that actually require the interrupt before
moving on.

[ felipe.ba...@linux.intel.com: minor improvements ]

Signed-off-by: Baolin Wang <baolin.w...@linaro.org>
---
Changes since v1:
 - Move the suspend checking to right place to avoid checking twice.
---
 drivers/usb/dwc3/core.h   |8 
 drivers/usb/dwc3/gadget.c |   49 +
 2 files changed, 53 insertions(+), 4 deletions(-)

diff --git a/drivers/usb/dwc3/core.h b/drivers/usb/dwc3/core.h
index 23765a1..c5fd862 100644
--- a/drivers/usb/dwc3/core.h
+++ b/drivers/usb/dwc3/core.h
@@ -26,6 +26,7 @@
 #include 
 #include 
 #include 
+#include 
 
 #include 
 #include 
@@ -496,6 +497,7 @@ struct dwc3_event_buffer {
  * @endpoint: usb endpoint
  * @pending_list: list of pending requests for this endpoint
  * @started_list: list of started requests on this endpoint
+ * @wait_end_transfer: wait_queue_head_t for waiting on End Transfer complete
  * @lock: spinlock for endpoint request queue traversal
  * @regs: pointer to first endpoint register
  * @trb_pool: array of transaction buffers
@@ -521,6 +523,8 @@ struct dwc3_ep {
struct list_headpending_list;
struct list_headstarted_list;
 
+   wait_queue_head_t   wait_end_transfer;
+
spinlock_t  lock;
void __iomem*regs;
 
@@ -537,6 +541,7 @@ struct dwc3_ep {
 #define DWC3_EP_BUSY   (1 << 4)
 #define DWC3_EP_PENDING_REQUEST(1 << 5)
 #define DWC3_EP_MISSED_ISOC(1 << 6)
+#define DWC3_EP_END_TRANSFER_PENDING   (1 << 7)
 
/* This last one is specific to EP0 */
 #define DWC3_EP0_DIR_IN(1 << 31)
@@ -1044,6 +1049,9 @@ struct dwc3_event_depevt {
 #define DEPEVT_TRANSFER_BUS_EXPIRY 2
 
u32 parameters:16;
+
+/* For Command Complete Events */
+#define DEPEVT_PARAMETER_CMD(n)(((n) & (0xf << 8)) >> 8)
 } __packed;
 
 /**
diff --git a/drivers/usb/dwc3/gadget.c b/drivers/usb/dwc3/gadget.c
index 3722c90..e248bd3 100644
--- a/drivers/usb/dwc3/gadget.c
+++ b/drivers/usb/dwc3/gadget.c
@@ -570,11 +570,14 @@ static int __dwc3_gadget_ep_enable(struct dwc3_ep *dep,
dep->comp_desc = comp_desc;
dep->type = usb_endpoint_type(desc);
dep->flags |= DWC3_EP_ENABLED;
+   dep->flags &= ~DWC3_EP_END_TRANSFER_PENDING;
 
reg = dwc3_readl(dwc->regs, DWC3_DALEPENA);
reg |= DWC3_DALEPENA_EP(dep->number);
dwc3_writel(dwc->regs, DWC3_DALEPENA, reg);
 
+   init_waitqueue_head(>wait_end_transfer);
+
if (usb_endpoint_xfer_control(desc))
return 0;
 
@@ -647,7 +650,7 @@ static int __dwc3_gadget_ep_disable(struct dwc3_ep *dep)
dep->endpoint.desc = NULL;
dep->comp_desc = NULL;
dep->type = 0;
-   dep->flags = 0;
+   dep->flags &= DWC3_EP_END_TRANSFER_PENDING;
 
return 0;
 }
@@ -1736,12 +1739,38 @@ static int dwc3_gadget_stop(struct usb_gadget *g)
 {
struct dwc3 *dwc = gadget_to_dwc(g);
unsigned long   flags;
+   int epnum;
 
spin_lock_irqsave(>lock, flags);
__dwc3_gadget_stop(dwc);
dwc->gadget_driver  = NULL;
+
+   /*
+* If the dwc3 core has been in suspend state, we will never get
+* the command complete event, thus ignore.
+*/
+   if (pm_runtime_suspended(dwc->dev)) {
+   spin_unlock_irqrestore(>lock, flags);
+   goto out;
+   }
+
+   for (epnum = 2; epnum < DWC3_ENDPOINTS_NUM; epnum++) {
+   struct dwc3_ep  *dep = dwc->eps[epnum];
+
+   if (!dep)
+   continue;
+
+   if (!(dep->flags & DWC3_EP_END_TRANSFER_PENDING))
+   continue;
+
+   wait_event_lock_irq(dep->wait_end_transfer,
+   !(dep->flags & 
DWC3_EP_END_TRANSFER_PENDING),
+   dwc->lock);
+   }
+
spin_unlock_irqrestore(>lock, flags);
 
+out:
free_irq(dwc->irq_gadget, dwc->ev_buf);
 
return 0;
@@ -2105,10 +2134,12 @@ static void dwc3_endpoint_interrupt(struct dwc3 *dwc,
 {
struct dwc3_ep  *dep;
u8  epnum = event->endpoint_number;
+   u8  cmd;
 
dep = dwc->eps[epnum];
 
-   if (!(dep->flags & DWC3_EP_ENABLED))
+   if (!(dep->flags & DWC3_EP_ENABLED) &&
+   !(dep->flags & DWC3_EP_END_TRANSFER_PENDING))
return;

Re: [PATCH v1] usb: dwc3: gadget: wait for End Transfer to complete

2016-10-31 Thread Baolin Wang
Hi,

On 31 October 2016 at 20:53, Felipe Balbi <ba...@kernel.org> wrote:
>
> Hi,
>
> Baolin Wang <baolin.w...@linaro.org> writes:
>> Instead of just delaying for 100us, we should
>> actually wait for End Transfer Command Complete
>> interrupt before moving on. Note that this should
>> only be done if we're dealing with one of the core
>> revisions that actually require the interrupt before
>> moving on.
>>
>> [ felipe.ba...@linux.intel.com: minor improvements ]
>>
>> Signed-off-by: Baolin Wang <baolin.w...@linaro.org>
>
> I made one extra modification to prevent us from checking for
> pm_runtime_suspended() twice:
>
> commit 8f48e8d6d3dfe75b5582c8a7b1ee5739a393748c
> Author: Baolin Wang <baolin.w...@linaro.org>
> Date:   Mon Oct 31 19:38:36 2016 +0800
>
> usb: dwc3: gadget: wait for End Transfer to complete
>
> Instead of just delaying for 100us, we should
> actually wait for End Transfer Command Complete
> interrupt before moving on. Note that this should
> only be done if we're dealing with one of the core
> revisions that actually require the interrupt before
> moving on.
>
> [ felipe.ba...@linux.intel.com: minor improvements ]
>
> Signed-off-by: Baolin Wang <baolin.w...@linaro.org>
> Signed-off-by: Felipe Balbi <felipe.ba...@linux.intel.com>
>
> diff --git a/drivers/usb/dwc3/core.h b/drivers/usb/dwc3/core.h
> index 5fc437021ac7..c2b86856e85d 100644
> --- a/drivers/usb/dwc3/core.h
> +++ b/drivers/usb/dwc3/core.h
> @@ -26,6 +26,7 @@
>  #include 
>  #include 
>  #include 
> +#include 
>
>  #include 
>  #include 
> @@ -505,6 +506,7 @@ struct dwc3_event_buffer {
>   * @endpoint: usb endpoint
>   * @pending_list: list of pending requests for this endpoint
>   * @started_list: list of started requests on this endpoint
> + * @wait_end_transfer: wait_queue_head_t for waiting on End Transfer complete
>   * @lock: spinlock for endpoint request queue traversal
>   * @regs: pointer to first endpoint register
>   * @trb_pool: array of transaction buffers
> @@ -530,6 +532,8 @@ struct dwc3_ep {
> struct list_headpending_list;
> struct list_headstarted_list;
>
> +   wait_queue_head_t   wait_end_transfer;
> +
> spinlock_t  lock;
> void __iomem*regs;
>
> @@ -546,6 +550,7 @@ struct dwc3_ep {
>  #define DWC3_EP_BUSY   (1 << 4)
>  #define DWC3_EP_PENDING_REQUEST(1 << 5)
>  #define DWC3_EP_MISSED_ISOC(1 << 6)
> +#define DWC3_EP_END_TRANSFER_PENDING   (1 << 7)
>
> /* This last one is specific to EP0 */
>  #define DWC3_EP0_DIR_IN(1 << 31)
> @@ -1050,6 +1055,9 @@ struct dwc3_event_depevt {
>  #define DEPEVT_TRANSFER_BUS_EXPIRY 2
>
> u32 parameters:16;
> +
> +/* For Command Complete Events */
> +#define DEPEVT_PARAMETER_CMD(n)(((n) & (0xf << 8)) >> 8)
>  } __packed;
>
>  /**
> diff --git a/drivers/usb/dwc3/gadget.c b/drivers/usb/dwc3/gadget.c
> index 3b53a5714df4..d544e7369776 100644
> --- a/drivers/usb/dwc3/gadget.c
> +++ b/drivers/usb/dwc3/gadget.c
> @@ -593,11 +593,14 @@ static int __dwc3_gadget_ep_enable(struct dwc3_ep *dep,
> dep->comp_desc = comp_desc;
> dep->type = usb_endpoint_type(desc);
> dep->flags |= DWC3_EP_ENABLED;
> +   dep->flags &= ~DWC3_EP_END_TRANSFER_PENDING;
>
> reg = dwc3_readl(dwc->regs, DWC3_DALEPENA);
> reg |= DWC3_DALEPENA_EP(dep->number);
> dwc3_writel(dwc->regs, DWC3_DALEPENA, reg);
>
> +   init_waitqueue_head(>wait_end_transfer);
> +
> if (usb_endpoint_xfer_control(desc))
> return 0;
>
> @@ -699,7 +702,7 @@ static int __dwc3_gadget_ep_disable(struct dwc3_ep *dep)
> dep->endpoint.desc = NULL;
> dep->comp_desc = NULL;
> dep->type = 0;
> -   dep->flags = 0;
> +   dep->flags &= DWC3_EP_END_TRANSFER_PENDING;
>
> return 0;
>  }
> @@ -1783,9 +1786,6 @@ static int dwc3_gadget_start(struct usb_gadget *g,
>
>  static void __dwc3_gadget_stop(struct dwc3 *dwc)
>  {
> -   if (pm_runtime_suspended(dwc->dev))
> -   return;
> -
> dwc3_gadget_disable_irq(dwc);
> __dwc3_gadget_ep_disable(dwc->eps[0]);
> __dwc3_gadget_ep_disable(dwc->eps[1]);
> @@ -1795,10 +1795,29 @@ static int dwc3_gadget_stop(struct usb_gadget *g)
>  {
> struct dwc3   

Re: [PATCH v2] usb: dwc3: gadget: wait for End Transfer to complete

2016-11-01 Thread Baolin Wang
Hi,

On 1 November 2016 at 19:36, Felipe Balbi <ba...@kernel.org> wrote:
>
> Hi,
>
> Baolin Wang <baolin.w...@linaro.org> writes:
>> Hi,
>>
>> On 1 November 2016 at 19:01, Felipe Balbi <ba...@kernel.org> wrote:
>>>
>>> Hi,
>>>
>>> Baolin Wang <baolin.w...@linaro.org> writes:
>>>> Changes since v1:
>>>>  - Move the suspend checking to right place to avoid checking twice.
>>>
>>> there is still one problem
>>>
>>>> @@ -1736,12 +1739,38 @@ static int dwc3_gadget_stop(struct usb_gadget *g)
>>>>  {
>>>>   struct dwc3 *dwc = gadget_to_dwc(g);
>>>>   unsigned long   flags;
>>>> + int epnum;
>>>>
>>>>   spin_lock_irqsave(>lock, flags);
>>>>   __dwc3_gadget_stop(dwc);
>>>
>>> this tries to access registers. If __dwc3_gadget_stop() runs while
>>> clocks are gated, we will get Data Abort exception.
>>
>> We have suspend checking in __dwc3_gadget_stop(), thus it will not
>> access registers if clocks are disabled.
>>
>>>
>>> How about this version, instead?
>>
>> I think it is OK except we missed set 'dwc->gadget_driver = NULL'.
>
> argh. Man, next time we meet in a conference, I owe you a beer :-)

Okay:) Now it looks good to me. Thanks.

>
> 8<--
> From 06a204f1c2276ca1ffe68d8d59ef2e2ead337bba Mon Sep 17 00:00:00 2001
> From: Baolin Wang <baolin.w...@linaro.org>
> Date: Mon, 31 Oct 2016 19:38:36 +0800
> Subject: [PATCH] usb: dwc3: gadget: wait for End Transfer to complete
>
> Instead of just delaying for 100us, we should
> actually wait for End Transfer Command Complete
> interrupt before moving on. Note that this should
> only be done if we're dealing with one of the core
> revisions that actually require the interrupt before
> moving on.
>
> [ felipe.ba...@linux.intel.com: minor improvements ]
>
> Signed-off-by: Baolin Wang <baolin.w...@linaro.org>
> Signed-off-by: Felipe Balbi <felipe.ba...@linux.intel.com>
> ---
>  drivers/usb/dwc3/core.h   |  8 
>  drivers/usb/dwc3/gadget.c | 49 
> +++
>  2 files changed, 49 insertions(+), 8 deletions(-)
>
> diff --git a/drivers/usb/dwc3/core.h b/drivers/usb/dwc3/core.h
> index 5fc437021ac7..c2b86856e85d 100644
> --- a/drivers/usb/dwc3/core.h
> +++ b/drivers/usb/dwc3/core.h
> @@ -26,6 +26,7 @@
>  #include 
>  #include 
>  #include 
> +#include 
>
>  #include 
>  #include 
> @@ -505,6 +506,7 @@ struct dwc3_event_buffer {
>   * @endpoint: usb endpoint
>   * @pending_list: list of pending requests for this endpoint
>   * @started_list: list of started requests on this endpoint
> + * @wait_end_transfer: wait_queue_head_t for waiting on End Transfer complete
>   * @lock: spinlock for endpoint request queue traversal
>   * @regs: pointer to first endpoint register
>   * @trb_pool: array of transaction buffers
> @@ -530,6 +532,8 @@ struct dwc3_ep {
> struct list_headpending_list;
> struct list_headstarted_list;
>
> +   wait_queue_head_t   wait_end_transfer;
> +
> spinlock_t  lock;
> void __iomem*regs;
>
> @@ -546,6 +550,7 @@ struct dwc3_ep {
>  #define DWC3_EP_BUSY   (1 << 4)
>  #define DWC3_EP_PENDING_REQUEST(1 << 5)
>  #define DWC3_EP_MISSED_ISOC(1 << 6)
> +#define DWC3_EP_END_TRANSFER_PENDING   (1 << 7)
>
> /* This last one is specific to EP0 */
>  #define DWC3_EP0_DIR_IN(1 << 31)
> @@ -1050,6 +1055,9 @@ struct dwc3_event_depevt {
>  #define DEPEVT_TRANSFER_BUS_EXPIRY 2
>
> u32 parameters:16;
> +
> +/* For Command Complete Events */
> +#define DEPEVT_PARAMETER_CMD(n)(((n) & (0xf << 8)) >> 8)
>  } __packed;
>
>  /**
> diff --git a/drivers/usb/dwc3/gadget.c b/drivers/usb/dwc3/gadget.c
> index 4743e53cc295..64d01ff8c119 100644
> --- a/drivers/usb/dwc3/gadget.c
> +++ b/drivers/usb/dwc3/gadget.c
> @@ -593,11 +593,14 @@ static int __dwc3_gadget_ep_enable(struct dwc3_ep *dep,
> dep->comp_desc = comp_desc;
> dep->type = usb_endpoint_type(desc);
> dep->flags |= DWC3_EP_ENABLED;
> +   dep->flags &= ~DWC3_EP_END_TRANSFER_PENDING;
>
> reg = dwc3_readl(dwc->regs, DWC3_DALEPENA);
> r

Re: [PATCH v2] usb: dwc3: gadget: wait for End Transfer to complete

2016-11-01 Thread Baolin Wang
Hi,

On 1 November 2016 at 19:01, Felipe Balbi <ba...@kernel.org> wrote:
>
> Hi,
>
> Baolin Wang <baolin.w...@linaro.org> writes:
>> Changes since v1:
>>  - Move the suspend checking to right place to avoid checking twice.
>
> there is still one problem
>
>> @@ -1736,12 +1739,38 @@ static int dwc3_gadget_stop(struct usb_gadget *g)
>>  {
>>   struct dwc3 *dwc = gadget_to_dwc(g);
>>   unsigned long   flags;
>> + int epnum;
>>
>>   spin_lock_irqsave(>lock, flags);
>>   __dwc3_gadget_stop(dwc);
>
> this tries to access registers. If __dwc3_gadget_stop() runs while
> clocks are gated, we will get Data Abort exception.

We have suspend checking in __dwc3_gadget_stop(), thus it will not
access registers if clocks are disabled.

>
> How about this version, instead?

I think it is OK except we missed set 'dwc->gadget_driver = NULL'.

>
> 8<------
> From e21260f349271ff1d12e919be20a9ee47e29e4b4 Mon Sep 17 00:00:00 2001
> From: Baolin Wang <baolin.w...@linaro.org>
> Date: Mon, 31 Oct 2016 19:38:36 +0800
> Subject: [PATCH] usb: dwc3: gadget: wait for End Transfer to complete
>
> Instead of just delaying for 100us, we should
> actually wait for End Transfer Command Complete
> interrupt before moving on. Note that this should
> only be done if we're dealing with one of the core
> revisions that actually require the interrupt before
> moving on.
>
> [ felipe.ba...@linux.intel.com: minor improvements ]
>
> Signed-off-by: Baolin Wang <baolin.w...@linaro.org>
> Signed-off-by: Felipe Balbi <felipe.ba...@linux.intel.com>
> ---
>  drivers/usb/dwc3/core.h   |  8 
>  drivers/usb/dwc3/gadget.c | 49 
> +++
>  2 files changed, 49 insertions(+), 8 deletions(-)
>
> diff --git a/drivers/usb/dwc3/core.h b/drivers/usb/dwc3/core.h
> index 5fc437021ac7..c2b86856e85d 100644
> --- a/drivers/usb/dwc3/core.h
> +++ b/drivers/usb/dwc3/core.h
> @@ -26,6 +26,7 @@
>  #include 
>  #include 
>  #include 
> +#include 
>
>  #include 
>  #include 
> @@ -505,6 +506,7 @@ struct dwc3_event_buffer {
>   * @endpoint: usb endpoint
>   * @pending_list: list of pending requests for this endpoint
>   * @started_list: list of started requests on this endpoint
> + * @wait_end_transfer: wait_queue_head_t for waiting on End Transfer complete
>   * @lock: spinlock for endpoint request queue traversal
>   * @regs: pointer to first endpoint register
>   * @trb_pool: array of transaction buffers
> @@ -530,6 +532,8 @@ struct dwc3_ep {
> struct list_headpending_list;
> struct list_headstarted_list;
>
> +   wait_queue_head_t   wait_end_transfer;
> +
> spinlock_t  lock;
> void __iomem*regs;
>
> @@ -546,6 +550,7 @@ struct dwc3_ep {
>  #define DWC3_EP_BUSY   (1 << 4)
>  #define DWC3_EP_PENDING_REQUEST(1 << 5)
>  #define DWC3_EP_MISSED_ISOC(1 << 6)
> +#define DWC3_EP_END_TRANSFER_PENDING   (1 << 7)
>
> /* This last one is specific to EP0 */
>  #define DWC3_EP0_DIR_IN(1 << 31)
> @@ -1050,6 +1055,9 @@ struct dwc3_event_depevt {
>  #define DEPEVT_TRANSFER_BUS_EXPIRY 2
>
> u32 parameters:16;
> +
> +/* For Command Complete Events */
> +#define DEPEVT_PARAMETER_CMD(n)(((n) & (0xf << 8)) >> 8)
>  } __packed;
>
>  /**
> diff --git a/drivers/usb/dwc3/gadget.c b/drivers/usb/dwc3/gadget.c
> index 4743e53cc295..a375fd28ed96 100644
> --- a/drivers/usb/dwc3/gadget.c
> +++ b/drivers/usb/dwc3/gadget.c
> @@ -593,11 +593,14 @@ static int __dwc3_gadget_ep_enable(struct dwc3_ep *dep,
> dep->comp_desc = comp_desc;
> dep->type = usb_endpoint_type(desc);
> dep->flags |= DWC3_EP_ENABLED;
> +   dep->flags &= ~DWC3_EP_END_TRANSFER_PENDING;
>
> reg = dwc3_readl(dwc->regs, DWC3_DALEPENA);
> reg |= DWC3_DALEPENA_EP(dep->number);
> dwc3_writel(dwc->regs, DWC3_DALEPENA, reg);
>
> +   init_waitqueue_head(>wait_end_transfer);
> +
> if (usb_endpoint_xfer_control(desc))
> return 0;
>
> @@ -699,7 +702,7 @@ static int __dwc3_gadget_ep_disable(struct dwc3_ep *dep)
> dep->endpoint.desc = NULL;
> dep->comp_desc = NULL;
> dep->type = 0;
> -   dep->flags = 0;
> +   dep->flags &= DWC3_EP_

Re: [PATCH v18 0/4] Introduce usb charger framework to deal with the usb gadget power negotation

2016-11-01 Thread Baolin Wang
Hi,

On 31 October 2016 at 08:00, NeilBrown <ne...@suse.com> wrote:
> On Fri, Oct 28 2016, Baolin Wang wrote:
>
>>>
>>> 3/ usb_charger_notify_state() does nothing if the state doesn't change.
>>>   When the extcon detects an SDP, it will be called to set the state
>>>   to USB_CHARGER_PRESENT.  The value of cur.sdp_max will be whatever
>>>   it happened to be before, which is probably wrong.
>>
>> Sorry, I did not get your points here, could you please explain it 
>> explicitly?
>
> usb_charger_get_current() is used to get the min/max current that is
> supported.
> In the case that an SDP (non-super-speed) has been detected it will
> report the values sdp_min and sdp_max.  Ignoring usb_charger_set_current(),
> sdp_max is set
>  - to DEFAULT_SDP_CUR_MAX (500) at initializaion
>  - to cur_limit when usb_charger_set_cur_limit_by_gadget() is called
>  which happens after USB negotiation, once an allowed vbus_draw is
>  negotiated.
>
> This means that the first time you plug in an SDP cable, the reported
> max will be 500, even though nothing has been negotiated.   The maximum
> before negotiation is much less than that  - I don't remember exactly
> how much.
>
> If negotiation completes, the sdp_max will be set to whatever was
> negotiated.  Maybe 200mA.
> If you unplug, and then plug another SDP cable in, the sdp_max will
> still be 200mA - different from the first time, but still not correct.
> It will remain incorrect until (and unless) USB negotiation completes.

Yes. I need some modification to reset current to default values when
cable unplugged.

>
>>
>>>   When after USB negotiation completes,
>>>   usb_charger_set_cur_limit_by_gadget()
>>>   will call into usb_charger_notify_state() to set USB_CHARGER_PRESENT
>>>   again, but with a new current.  This will be ignored, as the state is
>>>   already USB_CHARGER_PRESENT.
>>
>> No, we will notify the user the current has been changed by one work.
>
> I can see no evidence in the code to justify this assertion, and you
> didn't even try to provide any.

We have one work to notify the user the current has been changed,
please see usb_charger_notify_work().

>
>>
>>>
>>> 4/ I still strongly object to the ->get_charger_type() interface.
>>>  You previously said:
>>>
>>>  No. User can implement the get_charger_type() method to access the
>>>  PMIC registers to get the charger type, which is one very common 
>>> method.
>>>
>>>  I suggest that if the PMIC registers report the charger type, then the
>>>  PMIC driver should register an EXTCON and report the charger type
>>>  through that.  Then the information would be directly available to
>>>  user-space, and the usb-charger framework would have a single uniform
>>>  mechanism for being told the cable type.
>>
>> We just access only one PMIC register to get the charger type, which
>> is no need add one driver for that and there are no any events for
>> extcon. Some sample code in power driver can be like below:
>
> If there are no events, then how do you know when a charger has been
> plugged in?  Do you poll?

We just monitor the plug-in and plug-out events by extcon,  and get
the charger type by accessing PMIC registers when one cable is
plugged.

>
> In any case, one of the major values provided by using an OS like Linux
> is uniform interfaces.  If a device can detect what sort of cable is
> inserted, then that information should be presented as an EXTCON.

Fine. I can remove this callback. We can add it if we need it in future.

>
>>>
>>>  Related:  I don't like charger_type_show().  I don't think
>>>  the usb-charger should export that information to user-space because
>>>  extcon already does that, and duplication is confusing and pointless.
>>
>> I think we should combine all charger related information into one
>> place for user. Moreover if we don't get charger type from extcon, we
>> should also need one place to export the charger type.
>
> Yes and no.
>
> Certainly a uniform consistent interface should be presented.
> "a usb charger" is not the right abstraction.  It is not a thing that
> should have independent existence.  To everybody else in the world, a
> "usb charger" in a box that you plug into the wall, and which has a
> cable to plug into your device.  It is not part of the device itself.
> In general, you cannot point to any component in a device that is the
> "usb charger" so it isn't clear that Linux should even know about a "usb
> charger".

Yes,  we 

Re: [PATCH 75/82] usb: dwc3: gadget: wait for End Transfer to complete

2016-10-31 Thread Baolin Wang
Hi Feilpe,

On 31 October 2016 at 18:55, Felipe Balbi <felipe.ba...@linux.intel.com> wrote:
>
> Hi Baolin,
>
> Felipe Balbi <felipe.ba...@linux.intel.com> writes:
>> From: Baolin Wang <baolin.w...@linaro.org>
>>
>> Instead of just delaying for 100us, we should
>> actually wait for End Transfer Command Complete
>> interrupt before moving on. Note that this should
>> only be done if we're dealing with one of the core
>> revisions that actually require the interrupt before
>> moving on.
>>
>> [ felipe.ba...@linux.intel.com: minor improvements ]
>>
>> NYET-Signed-off-by: Baolin Wang <baolin.w...@linaro.org>
>> Signed-off-by: Felipe Balbi <felipe.ba...@linux.intel.com>
>
> I guess I should drop this patch from the queue since you wanted to send
> your own version, right?

Yes, I think so. Since I just pasted the sample code in previous email
and I did not see in your patchset, I will send out the new patch.

>
> Let me know ;-)
>
> --
> balbi



-- 
Baolin.wang
Best Regards
--
To unsubscribe from this list: send the line "unsubscribe linux-usb" in
the body of a message to majord...@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html


[PATCH v1] usb: dwc3: gadget: wait for End Transfer to complete

2016-10-31 Thread Baolin Wang
Instead of just delaying for 100us, we should
actually wait for End Transfer Command Complete
interrupt before moving on. Note that this should
only be done if we're dealing with one of the core
revisions that actually require the interrupt before
moving on.

[ felipe.ba...@linux.intel.com: minor improvements ]

Signed-off-by: Baolin Wang <baolin.w...@linaro.org>
---
 drivers/usb/dwc3/core.h   |8 
 drivers/usb/dwc3/gadget.c |   47 +
 2 files changed, 51 insertions(+), 4 deletions(-)

diff --git a/drivers/usb/dwc3/core.h b/drivers/usb/dwc3/core.h
index 23765a1..c5fd862 100644
--- a/drivers/usb/dwc3/core.h
+++ b/drivers/usb/dwc3/core.h
@@ -26,6 +26,7 @@
 #include 
 #include 
 #include 
+#include 
 
 #include 
 #include 
@@ -496,6 +497,7 @@ struct dwc3_event_buffer {
  * @endpoint: usb endpoint
  * @pending_list: list of pending requests for this endpoint
  * @started_list: list of started requests on this endpoint
+ * @wait_end_transfer: wait_queue_head_t for waiting on End Transfer complete
  * @lock: spinlock for endpoint request queue traversal
  * @regs: pointer to first endpoint register
  * @trb_pool: array of transaction buffers
@@ -521,6 +523,8 @@ struct dwc3_ep {
struct list_headpending_list;
struct list_headstarted_list;
 
+   wait_queue_head_t   wait_end_transfer;
+
spinlock_t  lock;
void __iomem*regs;
 
@@ -537,6 +541,7 @@ struct dwc3_ep {
 #define DWC3_EP_BUSY   (1 << 4)
 #define DWC3_EP_PENDING_REQUEST(1 << 5)
 #define DWC3_EP_MISSED_ISOC(1 << 6)
+#define DWC3_EP_END_TRANSFER_PENDING   (1 << 7)
 
/* This last one is specific to EP0 */
 #define DWC3_EP0_DIR_IN(1 << 31)
@@ -1044,6 +1049,9 @@ struct dwc3_event_depevt {
 #define DEPEVT_TRANSFER_BUS_EXPIRY 2
 
u32 parameters:16;
+
+/* For Command Complete Events */
+#define DEPEVT_PARAMETER_CMD(n)(((n) & (0xf << 8)) >> 8)
 } __packed;
 
 /**
diff --git a/drivers/usb/dwc3/gadget.c b/drivers/usb/dwc3/gadget.c
index 3722c90..018611d 100644
--- a/drivers/usb/dwc3/gadget.c
+++ b/drivers/usb/dwc3/gadget.c
@@ -570,11 +570,14 @@ static int __dwc3_gadget_ep_enable(struct dwc3_ep *dep,
dep->comp_desc = comp_desc;
dep->type = usb_endpoint_type(desc);
dep->flags |= DWC3_EP_ENABLED;
+   dep->flags &= ~DWC3_EP_END_TRANSFER_PENDING;
 
reg = dwc3_readl(dwc->regs, DWC3_DALEPENA);
reg |= DWC3_DALEPENA_EP(dep->number);
dwc3_writel(dwc->regs, DWC3_DALEPENA, reg);
 
+   init_waitqueue_head(>wait_end_transfer);
+
if (usb_endpoint_xfer_control(desc))
return 0;
 
@@ -647,7 +650,7 @@ static int __dwc3_gadget_ep_disable(struct dwc3_ep *dep)
dep->endpoint.desc = NULL;
dep->comp_desc = NULL;
dep->type = 0;
-   dep->flags = 0;
+   dep->flags &= DWC3_EP_END_TRANSFER_PENDING;
 
return 0;
 }
@@ -1736,10 +1739,34 @@ static int dwc3_gadget_stop(struct usb_gadget *g)
 {
struct dwc3 *dwc = gadget_to_dwc(g);
unsigned long   flags;
+   int epnum;
 
spin_lock_irqsave(>lock, flags);
__dwc3_gadget_stop(dwc);
dwc->gadget_driver  = NULL;
+
+   for (epnum = 2; epnum < DWC3_ENDPOINTS_NUM; epnum++) {
+   struct dwc3_ep  *dep = dwc->eps[epnum];
+
+   /*
+* If the dwc3 core has been in suspend state, we will never get
+* the command complete event, thus ignore.
+*/
+   if (pm_runtime_suspended(dwc->dev))
+   break;
+
+   if (!dep)
+   continue;
+
+   if (!(dep->flags & DWC3_EP_END_TRANSFER_PENDING))
+   continue;
+
+
+   wait_event_lock_irq(dep->wait_end_transfer,
+   !(dep->flags & 
DWC3_EP_END_TRANSFER_PENDING),
+   dwc->lock);
+   }
+
spin_unlock_irqrestore(>lock, flags);
 
free_irq(dwc->irq_gadget, dwc->ev_buf);
@@ -2105,10 +2132,12 @@ static void dwc3_endpoint_interrupt(struct dwc3 *dwc,
 {
struct dwc3_ep  *dep;
u8  epnum = event->endpoint_number;
+   u8  cmd;
 
dep = dwc->eps[epnum];
 
-   if (!(dep->flags & DWC3_EP_ENABLED))
+   if (!(dep->flags & DWC3_EP_ENABLED) &&
+   !(dep->flags & DWC3_EP_END_TRANSFER_PENDING))
return;
 
if (epnum == 0 || epnum == 1) {
@@ -2180,6 +2209,13 @@ static void dwc3_endpoint_interrupt(struct dwc3 *dwc,
dwc

Re: [PATCH v18 0/4] Introduce usb charger framework to deal with the usb gadget power negotation

2016-10-31 Thread Baolin Wang
On 29 October 2016 at 01:03, Mark Brown <broo...@kernel.org> wrote:
> On Fri, Oct 28, 2016 at 08:51:41PM +0800, Baolin Wang wrote:
>> On 28 October 2016 at 06:00, NeilBrown <ne...@suse.com> wrote:
>
>> > 1/ I think we agreed that it doesn't make sense for there to be
>> >  two chargers registered in a system.
>
>> Yes, until now...
>
>> >  However usb_charger_register() still allows that, and assigns
>> >  and arbitrary name to each based on discovery order.
>> >  This *cannot* make sense.
>
>> Fine, I can change that to allow only one charger to register.
>
> Yeah, it's a reasonable change.  I'm not sure the prior discussion was
> 100% conclusive on the issue (I remember there being some debate about
> leaving things there to avoid any need for future refactoring to touch
> the interface).

I think we should leave these things to avoid refactoring in future.

>
>> > 2/ Why do you have usb_charger_set_current()??
>> >   No code ever calls it.
>> >   This updates the min and max current which are defined in a
>> >   standard.  It never makes sense to change the min and max
>> >   for a particular cable type.
>
>> Mark, do we have some scenarios which want to change the current
>> limitation? If not, okay, I agree with you to remove this function.
>
> I'm not aware of any, we can always add it back if the need arises.

OK.

>
>> >  Related:  I don't like charger_type_show().  I don't think
>> >  the usb-charger should export that information to user-space because
>> >  extcon already does that, and duplication is confusing and pointless.
>
>> I think we should combine all charger related information into one
>> place for user. Moreover if we don't get charger type from extcon, we
>> should also need one place to export the charger type.
>
> I had also thought there was some software negotation as well as the
> physical charger in cases where the device is plugged into an active
> host?  I could be wrong.
>
>> > 5/ There is no convincing example usage of this framework.
>> >   wm8931x_power.c just scratches the surface.
>> >   If it is so good, it should be easy to convert a lot of other
>> >   drivers over to it.  If you did that it would be much easier
>> >   to see how it works and what the strengths/weaknesses were.
>
>> Jun have send out one patchset[1] based on my patchset, and he tested
>> mypatchset. Thanks for your comments.
>> [1]http://www.spinics.net/lists/linux-usb/msg139809.html
>
> I think it's a good idea to pick up Jun's patches into your patch set,
> that way Jun doesn't need to rebase and it might help with review of
> your patches too.

Yes, I think so. I will ask for Jun's help.


-- 
Baolin.wang
Best Regards
--
To unsubscribe from this list: send the line "unsubscribe linux-usb" in
the body of a message to majord...@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html


Re: [PATCH v18 0/4] Introduce usb charger framework to deal with the usb gadget power negotation

2016-10-28 Thread Baolin Wang
Hi,

On 28 October 2016 at 06:00, NeilBrown <ne...@suse.com> wrote:
> On Thu, Oct 27 2016, Baolin Wang wrote:
>
>> Hi Felipe,
>>
>> On 19 October 2016 at 10:37, Baolin Wang <baolin.w...@linaro.org> wrote:
>>> Currently the Linux kernel does not provide any standard integration of this
>>> feature that integrates the USB subsystem with the system power regulation
>>> provided by PMICs meaning that either vendors must add this in their kernels
>>> or USB gadget devices based on Linux (such as mobile phones) may not behave
>>> as they should. Thus provide a standard framework for doing this in kernel.
>>>
>>> Now introduce one user with wm831x_power to support and test the usb 
>>> charger,
>>> which is pending testing. Moreover there may be other potential users will 
>>> use
>>> it in future.
>>>
>>> Changes since v17:
>>>  - Remove goto section in usb_charger_register() function.
>>>  - Remove 'extern' in charger.h file.
>>>  - Move the kfree() to usb_charger_exit() function.
>>>
>>> Changes since v16:
>>>  - Modify the charger current range with introducing the maximum and minimum
>>>  current.
>>>  - Remove the getting charger type method from power supply.
>>>  - Add the getting charger type method from extcon system.
>>>  - Introduce new usb_charger_get_current() API for users to get the maximum 
>>> and
>>>  minimum current.
>>>  - Rename some APIs and other optimization.
>>>
>>> Changes since v15:
>>>  - Add charger state checking to avoid sending out duplicate notifies to 
>>> users.
>>>  - Add one work to notify power users the current has been changed.
>>>
>>> Changes since v14:
>>>  - Add kernel documentation for struct usb_cahrger.
>>>  - Remove some redundant WARN() functions.
>>>
>>> Changes since v13:
>>>  - Remove the charger checking in usb_gadget_vbus_draw() function.
>>>  - Rename some functions in charger.c file.
>>>  - Rebase on git://git.kernel.org/pub/scm/linux/kernel/git/balbi/usb.git 
>>> tags/usb-for-v4.8
>>>
>>> Changes since v12:
>>>  - Remove the class and device things.
>>>  - Link usb charger to udc-core.ko.
>>>  - Create one "charger" subdirectory which holds all charger-related 
>>> attributes.
>>>
>>> Changes since v11:
>>>  - Reviewed and tested by Li Jun.
>>>
>>> Changes since v10:
>>>  - Introduce usb_charger_get_state() function to check charger state.
>>>  - Remove the mutex lock in usb_charger_set_cur_limit_by_type() function
>>>  in case will be issued in atomic context.
>>
>> Could you apply this patchset into your branch if there are no other
>> comments? Thanks.
>
> Some of my previous comments are still outstanding.  You seem to have
> just brushed them off without apparently understanding.

I am very appreciate for your comments, and I've explained your
comments but you did not reply me..

> And no-one else seems to care enough to try to bridge the gap...
>
> Let me try again.
>
> 1/ I think we agreed that it doesn't make sense for there to be
>  two chargers registered in a system.

Yes, until now...

>  However usb_charger_register() still allows that, and assigns
>  and arbitrary name to each based on discovery order.
>  This *cannot* make sense.

Fine, I can change that to allow only one charger to register.

>
> 2/ Why do you have usb_charger_set_current()??
>   No code ever calls it.
>   This updates the min and max current which are defined in a
>   standard.  It never makes sense to change the min and max
>   for a particular cable type.

Mark, do we have some scenarios which want to change the current
limitation? If not, okay, I agree with you to remove this function.

>
> 3/ usb_charger_notify_state() does nothing if the state doesn't change.
>   When the extcon detects an SDP, it will be called to set the state
>   to USB_CHARGER_PRESENT.  The value of cur.sdp_max will be whatever
>   it happened to be before, which is probably wrong.

Sorry, I did not get your points here, could you please explain it explicitly?

>   When after USB negotiation completes,
>   usb_charger_set_cur_limit_by_gadget()
>   will call into usb_charger_notify_state() to set USB_CHARGER_PRESENT
>   again, but with a new current.  This will be ignored, as the state is
>   already USB_CHARGER_PRESENT.

No, we will notify the user the current has been changed by one work.

>
>  (as an aside
>  +enum usb_charger_state {
>  +  US

[PATCH v2] usb: dwc3: gadget: Wait for end transfer complete before free irq

2016-10-12 Thread Baolin Wang
When we change the USB function with configfs frequently, sometimes it will
hang the system to crash. The reason is the gadget driver can not hanle the
end transfer complete event after free the gadget irq (since the xHCI will
share the same interrupt number with gadget, thus when free the gadget irq,
it will not shutdown this gadget irq line), which will trigger the interrupt
all the time.

Thus we should check if we need wait for the end transfer command completion
before free gadget irq.

Signed-off-by: Baolin Wang <baolin.w...@linaro.org>
---
Changes since v1:
 - Simply the operation of cleaning the dep flags.
---
 drivers/usb/dwc3/core.h   |3 ++
 drivers/usb/dwc3/gadget.c |   73 +++--
 2 files changed, 73 insertions(+), 3 deletions(-)

diff --git a/drivers/usb/dwc3/core.h b/drivers/usb/dwc3/core.h
index 9128725..f01d8fd 100644
--- a/drivers/usb/dwc3/core.h
+++ b/drivers/usb/dwc3/core.h
@@ -537,6 +537,7 @@ struct dwc3_ep {
 #define DWC3_EP_BUSY   (1 << 4)
 #define DWC3_EP_PENDING_REQUEST(1 << 5)
 #define DWC3_EP_MISSED_ISOC(1 << 6)
+#define DWC3_EP_CMDCMPLT_BUSY  (1 << 7)
 
/* This last one is specific to EP0 */
 #define DWC3_EP0_DIR_IN(1 << 31)
@@ -746,6 +747,7 @@ struct dwc3_scratchpad_array {
  * @ep0_bounce_addr: dma address of ep0_bounce
  * @scratch_addr: dma address of scratchbuf
  * @ep0_in_setup: One control transfer is completed and enter setup phase
+ * @cmd_complete: endpoint command completion
  * @lock: for synchronizing
  * @dev: pointer to our struct device
  * @xhci: pointer to our xHCI child
@@ -845,6 +847,7 @@ struct dwc3 {
dma_addr_t  scratch_addr;
struct dwc3_request ep0_usb_req;
struct completion   ep0_in_setup;
+   struct completion   cmd_complete;
 
/* device lock */
spinlock_t  lock;
diff --git a/drivers/usb/dwc3/gadget.c b/drivers/usb/dwc3/gadget.c
index fef023a..32e3d4d 100644
--- a/drivers/usb/dwc3/gadget.c
+++ b/drivers/usb/dwc3/gadget.c
@@ -573,6 +573,7 @@ static int __dwc3_gadget_ep_enable(struct dwc3_ep *dep,
dep->comp_desc = comp_desc;
dep->type = usb_endpoint_type(desc);
dep->flags |= DWC3_EP_ENABLED;
+   dep->flags &= ~DWC3_EP_CMDCMPLT_BUSY;
 
reg = dwc3_readl(dwc->regs, DWC3_DALEPENA);
reg |= DWC3_DALEPENA_EP(dep->number);
@@ -650,7 +651,7 @@ static int __dwc3_gadget_ep_disable(struct dwc3_ep *dep)
dep->endpoint.desc = NULL;
dep->comp_desc = NULL;
dep->type = 0;
-   dep->flags = 0;
+   dep->flags &= DWC3_EP_CMDCMPLT_BUSY;
 
return 0;
 }
@@ -1732,6 +1733,54 @@ static void __dwc3_gadget_stop(struct dwc3 *dwc)
__dwc3_gadget_ep_disable(dwc->eps[1]);
 }
 
+static void dwc3_wait_command_complete(struct dwc3 *dwc)
+{
+   u32 epnum, epstart = 2;
+   int ret, wait_cmd_complete = 0;
+   unsigned long flags;
+
+check_next:
+   spin_lock_irqsave(>lock, flags);
+   /*
+* If the gadget has been in suspend state, then don't
+* need to wait for the end transfer complete event.
+*/
+   if (pm_runtime_suspended(dwc->dev)) {
+   spin_unlock_irqrestore(>lock, flags);
+   return;
+   }
+
+   for (epnum = epstart; epnum < DWC3_ENDPOINTS_NUM; epnum++) {
+   struct dwc3_ep *dep;
+
+   dep = dwc->eps[epnum];
+   if (!dep)
+   continue;
+
+   if (dep->flags & DWC3_EP_CMDCMPLT_BUSY) {
+   reinit_completion(>cmd_complete);
+   epstart = epnum + 1;
+   wait_cmd_complete = 1;
+   break;
+   }
+   }
+   spin_unlock_irqrestore(>lock, flags);
+
+   /*
+* Wait for 500ms to complete the end transfer command before free irq.
+*/
+   if (wait_cmd_complete) {
+   wait_cmd_complete = 0;
+   ret = wait_for_completion_timeout(>cmd_complete,
+ msecs_to_jiffies(500));
+   if (ret == 0)
+   dev_warn(dwc->dev,
+"timeout to wait for command complete.\n");
+
+   goto check_next;
+   }
+}
+
 static int dwc3_gadget_stop(struct usb_gadget *g)
 {
struct dwc3 *dwc = gadget_to_dwc(g);
@@ -1742,6 +1791,17 @@ static int dwc3_gadget_stop(struct usb_gadget *g)
dwc->gadget_driver  = NULL;
spin_unlock_irqrestore(>lock, flags);
 
+   /*
+* Since the xHCI will share the same interrupt with gadget, thus when
+* free the gadget irq, it will not shutdown this gadget irq line. Then
+* the gadget drive

Re: [PATCH v2] usb: dwc3: gadget: Wait for end transfer complete before free irq

2016-10-14 Thread Baolin Wang
Hi Felipe,

On 13 October 2016 at 21:34, Felipe Balbi <ba...@kernel.org> wrote:
>
>
> Hi,
>
> Baolin Wang <baolin.w...@linaro.org> writes:
>>> Baolin Wang <baolin.w...@linaro.org> writes:
>>>>>> Baolin Wang <baolin.w...@linaro.org> writes:
>>>>>>>>>> I'm thinking this is a bug in configfs interface of Gadget API, not
>>>>>>>>>> dwc3. The only reason for this to happen would be if we get to
>>>>>>>>>> ->udc_stop() with endpoints still enabled.
>>>>>>>>>>
>>>>>>>>>> Can you check if that's the case? i.e. can you check if any endpoints
>>>>>>>>>> are still enabled when we get here?
>>>>>>>>>
>>>>>>>>> No, it is not any endpoints are still enabled. Like I said in commit
>>>>>>>>> message, we will start end transfer command when disable the endpoint,
>>>>>>>>> if the end transfer command complete event comes after we have freed
>>>>>>>>> the gadget irq, it will trigger the interrupt line all the time to
>>>>>>>>> crash the system.
>>>>>>>>
>>>>>>>> I see what the problem is. Databook tells us we *must* set CMDIOC when
>>>>>>>> issuing EndTransfer command and we should always wait for Command
>>>>>>>> Complete IRQ. However, we took a shortcut and just delayed for 100us
>>>>>>>> after issuing End Transfer.
>>>>>>>
>>>>>>> Yes, but 100us delay is not enough in some scenarios, like changing
>>>>>>> function with configfs frequently, we will met problems.
>>>>>>
>>>>>> heh, 100us *is* enough. However we still get an IRQ because we requested
>>>>>> for it. If you want to fix this, then you need to find a way to get rid
>>>>>> of that 100us udelay() and add a proper wait_for_completion() to delay
>>>>>> execution until command complete IRQ fires up.
>>>>>
>>>>> I haven't tested this yet, but it shows the idea (I think we might still
>>>>> have a race with ep_queue if we're still waiting for End Transfer, but
>>>>
>>>> Yes, maybe we need check DWC3_EP_END_TRANSFER_PENDING flag when
>>>> queuing one request.
>>>
>>> Yeah, I'll add that check later. I still need to make sure we would
>>> still try to kick any transfers that might have been queued while
>>> waiting for End Transfer Command Complete IRQ.
>>
>> OK. But I still worried if there are other races in some places which
>
> There are no other places where this needs to be sorted out.
>
>> is not easy to find out by testing. No introducing race condition
>> would be one better solution, anyway I would like to test the patch
>> you send out firstly.
>
> Right, but your patch was working around another problem, rather then
> fixing it.
>
> Here's another version which should make sure everything remains working
> as it should.
>
> 8<
> From 1f922a902a21d5cee32082be18bbfbf1d46137e4 Mon Sep 17 00:00:00 2001
> From: Felipe Balbi <felipe.ba...@linux.intel.com>
> Date: Thu, 13 Oct 2016 14:09:47 +0300
> Subject: [PATCH] usb: dwc3: gadget: wait for End Transfer to complete
>
> Instead of just delaying for 100us, we should
> actually wait for End Transfer Command Complete
> interrupt before moving on. Note that this should
> only be done if we're dealing with one of the core
> revisions that actually require the interrupt before
> moving on.
>
> Reported-by: Baolin Wang <baolin.w...@linaro.org>
> Signed-off-by: Felipe Balbi <felipe.ba...@linux.intel.com>
> ---
>  drivers/usb/dwc3/core.h   | 10 +-
>  drivers/usb/dwc3/gadget.c | 31 ---
>  2 files changed, 37 insertions(+), 4 deletions(-)
>
> diff --git a/drivers/usb/dwc3/core.h b/drivers/usb/dwc3/core.h
> index e878366ead00..cf495d932252 100644
> --- a/drivers/usb/dwc3/core.h
> +++ b/drivers/usb/dwc3/core.h
> @@ -26,6 +26,7 @@
>  #include 
>  #include 
>  #include 
> +#include 
>
>  #include 
>  #include 
> @@ -504,6 +505,7 @@ struct dwc3_event_buffer {
>   * @endpoint: usb endpoint
>   * @pending_list: list of pending requests for this endpoint
>   * @started_list: list of started requests on this endpoint
> + * @wait_end_transfer: wai

Re: [RESEND PATCH v3 1/2] usb: dwc3: gadget: Add disconnect checking when changing function dynamically

2016-10-13 Thread Baolin Wang
On 13 October 2016 at 16:28, Janusz Dziedzic <janusz.dzied...@tieto.com> wrote:
> On 13 October 2016 at 10:21, Baolin Wang <baolin.w...@linaro.org> wrote:
>> Hi,
>>
>> On 13 October 2016 at 16:16, Janusz Dziedzic <janusz.dzied...@tieto.com> 
>> wrote:
>>> On 13 October 2016 at 09:37, Baolin Wang <baolin.w...@linaro.org> wrote:
>>>> Hi,
>>>>
>>>> On 13 October 2016 at 15:06, Felipe Balbi <ba...@kernel.org> wrote:
>>>>>
>>>>> Hi,
>>>>>
>>>>> Baolin Wang <baolin.w...@linaro.org> writes:
>>>>>> When system has stpped the gadget, we should avoid queuing any requests
>>>>>
>>>>> queueing is *not* a problem. Starting is. In fact, that's what your
>>>>> patch is doing.
>>>>
>>>> OK.
>>>>
>>>>>
>>>>>> which will cause tranfer failed. Thus adding some disconnect checking to
>>>>>^^^
>>>>>transfer
>>>>
>>>> Sorry for spelling mistake, will fix it.
>>>>
>>>>>
>>>>>> avoid this situation.
>>>>>>
>>>>>> Signed-off-by: Baolin Wang <baolin.w...@linaro.org>
>>>>>> ---
>>>>>> Changes since v2:
>>>>>>  - Move disconnect checking into dwc3_send_gadget_ep_cmd().
>>>>>>  - Rename completion name and issue complete() at one place.
>>>>>>  - Move completion initialization into dwc3_gadget_init().
>>>>>>
>>>>>> Changes since v1:
>>>>>>  - Split into 2 separate ptaches.
>>>>>>  - Choose complete mechanism instead of polling.
>>>>>> ---
>>>>>>  drivers/usb/dwc3/gadget.c |3 +++
>>>>>>  1 file changed, 3 insertions(+)
>>>>>>
>>>>>> diff --git a/drivers/usb/dwc3/gadget.c b/drivers/usb/dwc3/gadget.c
>>>>>> index 1783406..ca2ae5b 100644
>>>>>> --- a/drivers/usb/dwc3/gadget.c
>>>>>> +++ b/drivers/usb/dwc3/gadget.c
>>>>>> @@ -241,6 +241,9 @@ int dwc3_send_gadget_ep_cmd(struct dwc3_ep *dep, 
>>>>>> unsigned cmd,
>>>>>>   int susphy = false;
>>>>>>   int ret = -EINVAL;
>>>>>>
>>>>>> + if (!dwc->pullups_connected)
>>>>>> + return -ESHUTDOWN;
>>>>>> +
>>>
>>> you skip trace_dwc3_gadget_ep_cmd()
>>
>> Yes, we did not need trace here since we did not send out the command.
>>
> What in such case: enumeration will not work and this will be because
> this ESHUTDOWN or wrong pullups_connected usage. Without a trace you
> will not know where the problem is.
> In my opinion this trace could be useful.

We have returned the '-ESHUTDOWN' error number for user to know what happened.

>
> BR
> Janusz
>
>>>
>>> BR
>>> Janusz
>>>
>>>>>>   /*
>>>>>>* Synopsys Databook 2.60a states, on section 6.3.2.5.[1-8], that 
>>>>>> if
>>>>>>* we're issuing an endpoint command, we must check if
>>>>>> --
>>>>>> 1.7.9.5
>>>>>>
>>>>>> --
>>>>>> To unsubscribe from this list: send the line "unsubscribe linux-usb" in
>>>>>> the body of a message to majord...@vger.kernel.org
>>>>>> More majordomo info at  http://vger.kernel.org/majordomo-info.html
>>>>>
>>>>> --
>>>>> balbi
>>>>
>>>>
>>>>
>>>> --
>>>> Baolin.wang
>>>> Best Regards
>>>> --
>>>> To unsubscribe from this list: send the line "unsubscribe linux-usb" in
>>>> the body of a message to majord...@vger.kernel.org
>>>> More majordomo info at  http://vger.kernel.org/majordomo-info.html
>>
>>
>>
>> --
>> Baolin.wang
>> Best Regards



-- 
Baolin.wang
Best Regards
--
To unsubscribe from this list: send the line "unsubscribe linux-usb" in
the body of a message to majord...@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html


Re: [RESEND PATCH v3 1/2] usb: dwc3: gadget: Add disconnect checking when changing function dynamically

2016-10-13 Thread Baolin Wang
Hi,

On 13 October 2016 at 16:16, Janusz Dziedzic <janusz.dzied...@tieto.com> wrote:
> On 13 October 2016 at 09:37, Baolin Wang <baolin.w...@linaro.org> wrote:
>> Hi,
>>
>> On 13 October 2016 at 15:06, Felipe Balbi <ba...@kernel.org> wrote:
>>>
>>> Hi,
>>>
>>> Baolin Wang <baolin.w...@linaro.org> writes:
>>>> When system has stpped the gadget, we should avoid queuing any requests
>>>
>>> queueing is *not* a problem. Starting is. In fact, that's what your
>>> patch is doing.
>>
>> OK.
>>
>>>
>>>> which will cause tranfer failed. Thus adding some disconnect checking to
>>>    ^^^
>>>transfer
>>
>> Sorry for spelling mistake, will fix it.
>>
>>>
>>>> avoid this situation.
>>>>
>>>> Signed-off-by: Baolin Wang <baolin.w...@linaro.org>
>>>> ---
>>>> Changes since v2:
>>>>  - Move disconnect checking into dwc3_send_gadget_ep_cmd().
>>>>  - Rename completion name and issue complete() at one place.
>>>>  - Move completion initialization into dwc3_gadget_init().
>>>>
>>>> Changes since v1:
>>>>  - Split into 2 separate ptaches.
>>>>  - Choose complete mechanism instead of polling.
>>>> ---
>>>>  drivers/usb/dwc3/gadget.c |3 +++
>>>>  1 file changed, 3 insertions(+)
>>>>
>>>> diff --git a/drivers/usb/dwc3/gadget.c b/drivers/usb/dwc3/gadget.c
>>>> index 1783406..ca2ae5b 100644
>>>> --- a/drivers/usb/dwc3/gadget.c
>>>> +++ b/drivers/usb/dwc3/gadget.c
>>>> @@ -241,6 +241,9 @@ int dwc3_send_gadget_ep_cmd(struct dwc3_ep *dep, 
>>>> unsigned cmd,
>>>>   int susphy = false;
>>>>   int ret = -EINVAL;
>>>>
>>>> + if (!dwc->pullups_connected)
>>>> + return -ESHUTDOWN;
>>>> +
>
> you skip trace_dwc3_gadget_ep_cmd()

Yes, we did not need trace here since we did not send out the command.

>
> BR
> Janusz
>
>>>>   /*
>>>>* Synopsys Databook 2.60a states, on section 6.3.2.5.[1-8], that if
>>>>* we're issuing an endpoint command, we must check if
>>>> --
>>>> 1.7.9.5
>>>>
>>>> --
>>>> To unsubscribe from this list: send the line "unsubscribe linux-usb" in
>>>> the body of a message to majord...@vger.kernel.org
>>>> More majordomo info at  http://vger.kernel.org/majordomo-info.html
>>>
>>> --
>>> balbi
>>
>>
>>
>> --
>> Baolin.wang
>> Best Regards
>> --
>> To unsubscribe from this list: send the line "unsubscribe linux-usb" in
>> the body of a message to majord...@vger.kernel.org
>> More majordomo info at  http://vger.kernel.org/majordomo-info.html



-- 
Baolin.wang
Best Regards
--
To unsubscribe from this list: send the line "unsubscribe linux-usb" in
the body of a message to majord...@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html


Re: [RESEND PATCH v3 1/2] usb: dwc3: gadget: Add disconnect checking when changing function dynamically

2016-10-13 Thread Baolin Wang
Hi,

On 13 October 2016 at 15:06, Felipe Balbi <ba...@kernel.org> wrote:
>
> Hi,
>
> Baolin Wang <baolin.w...@linaro.org> writes:
>> When system has stpped the gadget, we should avoid queuing any requests
>
> queueing is *not* a problem. Starting is. In fact, that's what your
> patch is doing.

OK.

>
>> which will cause tranfer failed. Thus adding some disconnect checking to
>^^^
>transfer

Sorry for spelling mistake, will fix it.

>
>> avoid this situation.
>>
>> Signed-off-by: Baolin Wang <baolin.w...@linaro.org>
>> ---
>> Changes since v2:
>>  - Move disconnect checking into dwc3_send_gadget_ep_cmd().
>>  - Rename completion name and issue complete() at one place.
>>  - Move completion initialization into dwc3_gadget_init().
>>
>> Changes since v1:
>>  - Split into 2 separate ptaches.
>>  - Choose complete mechanism instead of polling.
>> ---
>>  drivers/usb/dwc3/gadget.c |3 +++
>>  1 file changed, 3 insertions(+)
>>
>> diff --git a/drivers/usb/dwc3/gadget.c b/drivers/usb/dwc3/gadget.c
>> index 1783406..ca2ae5b 100644
>> --- a/drivers/usb/dwc3/gadget.c
>> +++ b/drivers/usb/dwc3/gadget.c
>> @@ -241,6 +241,9 @@ int dwc3_send_gadget_ep_cmd(struct dwc3_ep *dep, 
>> unsigned cmd,
>>   int susphy = false;
>>   int ret = -EINVAL;
>>
>> + if (!dwc->pullups_connected)
>> + return -ESHUTDOWN;
>> +
>>   /*
>>* Synopsys Databook 2.60a states, on section 6.3.2.5.[1-8], that if
>>* we're issuing an endpoint command, we must check if
>> --
>> 1.7.9.5
>>
>> --
>> To unsubscribe from this list: send the line "unsubscribe linux-usb" in
>> the body of a message to majord...@vger.kernel.org
>> More majordomo info at  http://vger.kernel.org/majordomo-info.html
>
> --
> balbi



-- 
Baolin.wang
Best Regards
--
To unsubscribe from this list: send the line "unsubscribe linux-usb" in
the body of a message to majord...@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html


Re: [RESEND PATCH v3 2/2] usb: dwc3: Wait for control tranfer completed when stopping gadget

2016-10-13 Thread Baolin Wang
Hi,

On 13 October 2016 at 15:08, Felipe Balbi <ba...@kernel.org> wrote:
>
> Hi,
>
> Baolin Wang <baolin.w...@linaro.org> writes:
>> @@ -1487,10 +1496,22 @@ static int dwc3_gadget_pullup(struct usb_gadget *g, 
>> int is_on)
>>
>>   is_on = !!is_on;
>>
>> +try_again:
>>   spin_lock_irqsave(>lock, flags);
>>   ret = dwc3_gadget_run_stop(dwc, is_on, false);
>>   spin_unlock_irqrestore(>lock, flags);
>>
>> + if (ret == -EBUSY) {
>> + ret = wait_for_completion_timeout(>ep0_in_setup,
>> +   msecs_to_jiffies(500));
>> + if (ret == 0) {
>> + dev_err(dwc->dev, "timeout to stop gadget.\n");
>> + ret = -ETIMEDOUT;
>> + } else {
>> + goto try_again;
>
> you are not really reading my comments. It's the third time I tell you
> there's no need for try_again. If you can't complete a control transfer
> in 500ms, you already have other issues. Take this thing out of here.

I think you misunderstood the code. If there is 500ms timeout, we will
return '-ETIMEDOUT' error. If the control transfer is completed before
timeout, we can not just return and we need try again to stop the
gadget, right? Any other good suggestion? Thanks.


-- 
Baolin.wang
Best Regards
--
To unsubscribe from this list: send the line "unsubscribe linux-usb" in
the body of a message to majord...@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html


Re: [PATCH v2] usb: dwc3: gadget: Wait for end transfer complete before free irq

2016-10-13 Thread Baolin Wang
Hi,

On 13 October 2016 at 15:51, Felipe Balbi <ba...@kernel.org> wrote:
>
> Hi,
>
> Baolin Wang <baolin.w...@linaro.org> writes:
>> Hi,
>>
>> On 13 October 2016 at 15:02, Felipe Balbi <ba...@kernel.org> wrote:
>>>
>>> Hi,
>>>
>>> Baolin Wang <baolin.w...@linaro.org> writes:
>>>> @@ -1742,6 +1791,17 @@ static int dwc3_gadget_stop(struct usb_gadget *g)
>>>>   dwc->gadget_driver  = NULL;
>>>>   spin_unlock_irqrestore(>lock, flags);
>>>>
>>>> + /*
>>>> +  * Since the xHCI will share the same interrupt with gadget, thus 
>>>> when
>>>> +  * free the gadget irq, it will not shutdown this gadget irq line. 
>>>> Then
>>>> +  * the gadget driver can not handle the end transfer command complete
>>>> +  * event after free the gadget irq, which will hang the system to 
>>>> crash.
>>>> +  *
>>>> +  * So we should wait for the end transfer command complete event 
>>>> before
>>>> +  * free it to avoid this situation.
>>>> +  */
>>>> + dwc3_wait_command_complete(dwc);
>>>
>>> this doesn't make sense. We have already masked all interrupts before
>>> getting here. We have also, already, disabled all endpoints.
>>
>> No, you just mask the interrupts described in DEVTEN register, and you
>> did not disable the endpoint command complete event.
>
> True that
>
>>> I'm thinking this is a bug in configfs interface of Gadget API, not
>>> dwc3. The only reason for this to happen would be if we get to
>>> ->udc_stop() with endpoints still enabled.
>>>
>>> Can you check if that's the case? i.e. can you check if any endpoints
>>> are still enabled when we get here?
>>
>> No, it is not any endpoints are still enabled. Like I said in commit
>> message, we will start end transfer command when disable the endpoint,
>> if the end transfer command complete event comes after we have freed
>> the gadget irq, it will trigger the interrupt line all the time to
>> crash the system.
>
> I see what the problem is. Databook tells us we *must* set CMDIOC when
> issuing EndTransfer command and we should always wait for Command
> Complete IRQ. However, we took a shortcut and just delayed for 100us
> after issuing End Transfer.

Yes, but 100us delay is not enough in some scenarios, like changing
function with configfs frequently, we will met problems.

>
> It seems as if *that* should be fixed. We should start actually waiting
> for Command Complete IRQ.
>
> --
> balbi



-- 
Baolin.wang
Best Regards
--
To unsubscribe from this list: send the line "unsubscribe linux-usb" in
the body of a message to majord...@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html


Re: [PATCH v2] usb: dwc3: gadget: Wait for end transfer complete before free irq

2016-10-13 Thread Baolin Wang
Hi,

On 13 October 2016 at 15:02, Felipe Balbi <ba...@kernel.org> wrote:
>
> Hi,
>
> Baolin Wang <baolin.w...@linaro.org> writes:
>> @@ -1742,6 +1791,17 @@ static int dwc3_gadget_stop(struct usb_gadget *g)
>>   dwc->gadget_driver  = NULL;
>>   spin_unlock_irqrestore(>lock, flags);
>>
>> + /*
>> +  * Since the xHCI will share the same interrupt with gadget, thus when
>> +  * free the gadget irq, it will not shutdown this gadget irq line. Then
>> +  * the gadget driver can not handle the end transfer command complete
>> +  * event after free the gadget irq, which will hang the system to 
>> crash.
>> +  *
>> +  * So we should wait for the end transfer command complete event before
>> +  * free it to avoid this situation.
>> +  */
>> + dwc3_wait_command_complete(dwc);
>
> this doesn't make sense. We have already masked all interrupts before
> getting here. We have also, already, disabled all endpoints.

No, you just mask the interrupts described in DEVTEN register, and you
did not disable the endpoint command complete event.

>
> I'm thinking this is a bug in configfs interface of Gadget API, not
> dwc3. The only reason for this to happen would be if we get to
> ->udc_stop() with endpoints still enabled.
>
> Can you check if that's the case? i.e. can you check if any endpoints
> are still enabled when we get here?

No, it is not any endpoints are still enabled. Like I said in commit
message, we will start end transfer command when disable the endpoint,
if the end transfer command complete event comes after we have freed
the gadget irq, it will trigger the interrupt line all the time to
crash the system.

-- 
Baolin.wang
Best Regards
--
To unsubscribe from this list: send the line "unsubscribe linux-usb" in
the body of a message to majord...@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html


Re: [RESEND PATCH v3 2/2] usb: dwc3: Wait for control tranfer completed when stopping gadget

2016-10-13 Thread Baolin Wang
On 13 October 2016 at 15:54, Felipe Balbi <ba...@kernel.org> wrote:
>
> Hi,
>
> Baolin Wang <baolin.w...@linaro.org> writes:
>> Hi,
>>
>> On 13 October 2016 at 15:08, Felipe Balbi <ba...@kernel.org> wrote:
>>>
>>> Hi,
>>>
>>> Baolin Wang <baolin.w...@linaro.org> writes:
>>>> @@ -1487,10 +1496,22 @@ static int dwc3_gadget_pullup(struct usb_gadget 
>>>> *g, int is_on)
>>>>
>>>>   is_on = !!is_on;
>>>>
>>>> +try_again:
>>>>   spin_lock_irqsave(>lock, flags);
>>>>   ret = dwc3_gadget_run_stop(dwc, is_on, false);
>>>>   spin_unlock_irqrestore(>lock, flags);
>>>>
>>>> + if (ret == -EBUSY) {
>>>> + ret = wait_for_completion_timeout(>ep0_in_setup,
>>>> +   msecs_to_jiffies(500));
>>>> + if (ret == 0) {
>>>> + dev_err(dwc->dev, "timeout to stop gadget.\n");
>>>> + ret = -ETIMEDOUT;
>>>> + } else {
>>>> + goto try_again;
>>>
>>> you are not really reading my comments. It's the third time I tell you
>>> there's no need for try_again. If you can't complete a control transfer
>>> in 500ms, you already have other issues. Take this thing out of here.
>>
>> I think you misunderstood the code. If there is 500ms timeout, we will
>> return '-ETIMEDOUT' error. If the control transfer is completed before
>> timeout, we can not just return and we need try again to stop the
>> gadget, right? Any other good suggestion? Thanks.
>
> Yeah, change the patch a bit so you wait for completion before calling
> dwc3_gadget_runt_stop()? I mean, move the !is_on && ep0_state check
> before calling dwc3_gadget_run_stop() and wait_for_completion_timeout()
> there.

OK. I will refactor the patch. Thanks.

>
> --
> balbi



-- 
Baolin.wang
Best Regards
--
To unsubscribe from this list: send the line "unsubscribe linux-usb" in
the body of a message to majord...@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html


Re: [RESEND PATCH v3 1/2] usb: dwc3: gadget: Add disconnect checking when changing function dynamically

2016-10-13 Thread Baolin Wang
On 13 October 2016 at 17:49, Felipe Balbi <ba...@kernel.org> wrote:
>
> Hi,
>
> Baolin Wang <baolin.w...@linaro.org> writes:
>>>>>>>> diff --git a/drivers/usb/dwc3/gadget.c b/drivers/usb/dwc3/gadget.c
>>>>>>>> index 1783406..ca2ae5b 100644
>>>>>>>> --- a/drivers/usb/dwc3/gadget.c
>>>>>>>> +++ b/drivers/usb/dwc3/gadget.c
>>>>>>>> @@ -241,6 +241,9 @@ int dwc3_send_gadget_ep_cmd(struct dwc3_ep *dep, 
>>>>>>>> unsigned cmd,
>>>>>>>>   int susphy = false;
>>>>>>>>   int ret = -EINVAL;
>>>>>>>>
>>>>>>>> + if (!dwc->pullups_connected)
>>>>>>>> + return -ESHUTDOWN;
>>>>>>>> +
>>>>>
>>>>> you skip trace_dwc3_gadget_ep_cmd()
>>>>
>>>> Yes, we did not need trace here since we did not send out the command.
>>>>
>>> What in such case: enumeration will not work and this will be because
>>> this ESHUTDOWN or wrong pullups_connected usage. Without a trace you
>>> will not know where the problem is.
>>> In my opinion this trace could be useful.
>>
>> We have returned the '-ESHUTDOWN' error number for user to know what
>> happened.
>
> No, this is actually not good and Janusz has a very valid point
> here. When we're debugging something in dwc3, we want to rely on
> tracepoints to tell us what's going on. I don't want to have to add more
> debugging messages to print out that ESHUTDOWN error just so I can
> figure out what's going on. You should be patching this in a way that
> the tracepoint is still printed out properly.

Fine. Will fix this in next version.

>
> Keep in mind that you should be setting ret to -ESHUTDOWN and make sure
> the trace is printed. Same patch should, then, patch trace.h to handle
> -ESHUTDOWN as an error case, i.e. following hunk should be added:
>
> diff --git a/drivers/usb/dwc3/debug.h b/drivers/usb/dwc3/debug.h
> index d93780e84f07..70b783f0507d 100644
> --- a/drivers/usb/dwc3/debug.h
> +++ b/drivers/usb/dwc3/debug.h
> @@ -319,6 +319,8 @@ static inline const char *dwc3_ep_cmd_status_string(int 
> status)
> switch (status) {
> case -ETIMEDOUT:
> return "Timed Out";
> +   case -ESHUTDOWN:
> +   return "Shut Down";
> case 0:
> return "Successful";
> case DEPEVT_TRANSFER_NO_RESOURCE:
>
> --
> balbi



-- 
Baolin.wang
Best Regards
--
To unsubscribe from this list: send the line "unsubscribe linux-usb" in
the body of a message to majord...@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html


Re: [RESEND PATCH v3 1/2] usb: dwc3: gadget: Add disconnect checking when changing function dynamically

2016-10-13 Thread Baolin Wang
Hi,

On 13 October 2016 at 19:22, Felipe Balbi <ba...@kernel.org> wrote:
>
> Hi,
>
> Janusz Dziedzic <janusz.dzied...@tieto.com> writes:
>>>> Baolin Wang <baolin.w...@linaro.org> writes:
>>>>>>>>>>> diff --git a/drivers/usb/dwc3/gadget.c b/drivers/usb/dwc3/gadget.c
>>>>>>>>>>> index 1783406..ca2ae5b 100644
>>>>>>>>>>> --- a/drivers/usb/dwc3/gadget.c
>>>>>>>>>>> +++ b/drivers/usb/dwc3/gadget.c
>>>>>>>>>>> @@ -241,6 +241,9 @@ int dwc3_send_gadget_ep_cmd(struct dwc3_ep 
>>>>>>>>>>> *dep, unsigned cmd,
>>>>>>>>>>>   int susphy = false;
>>>>>>>>>>>   int ret = -EINVAL;
>>>>>>>>>>>
>>>>>>>>>>> + if (!dwc->pullups_connected)
>>>>>>>>>>> + return -ESHUTDOWN;
>>>>>>>>>>> +
>>>>>>>>
>>>>>>>> you skip trace_dwc3_gadget_ep_cmd()
>>>>>>>
>>>>>>> Yes, we did not need trace here since we did not send out the command.
>>>>>>>
>>>>>> What in such case: enumeration will not work and this will be because
>>>>>> this ESHUTDOWN or wrong pullups_connected usage. Without a trace you
>>>>>> will not know where the problem is.
>>>>>> In my opinion this trace could be useful.
>>>>>
>>>>> We have returned the '-ESHUTDOWN' error number for user to know what
>>>>> happened.
>>>>
>>>> No, this is actually not good and Janusz has a very valid point
>>>> here. When we're debugging something in dwc3, we want to rely on
>>>> tracepoints to tell us what's going on. I don't want to have to add more
>>>> debugging messages to print out that ESHUTDOWN error just so I can
>>>> figure out what's going on. You should be patching this in a way that
>>>> the tracepoint is still printed out properly.
>>>
>>> Fine. Will fix this in next version.
>>>
>>
>> BTW, did you test this patch with device mode?
>> Seems in my setup this fail - DWC3_DEPCMD_SETEPCONFIG for ep0out and
>> gadget_start() failed (enumeration fail).
>> Don't we need to queue ep0 cmds before pullup?
>
> Baolin, it's clear to me that you're not testing any of the patches
> you're sending me. I just reviewed this part of the code and we _do_
> indeed enable the control pipe before connecting pullups and that *must*
> be done this way, otherwise we won't be able to receive first Setup
> packet from host.

I am very sorry for this mistake. Since the original patch is adding
some 'pullups_connected' check in other places to avoid queuing
requests, but you suggested me this only affected the endpoint command
transfer, so I just follow your advice without one clear testing. I
really sorry for that. Please ignore this patch and I promise I will
test it enough before sending out any patches. Sorry again for
troubles.

>
> How have you tested this? Against which tree?
>
> --
> balbi



-- 
Baolin.wang
Best Regards
--
To unsubscribe from this list: send the line "unsubscribe linux-usb" in
the body of a message to majord...@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html


Re: [PATCH v2] usb: dwc3: gadget: Wait for end transfer complete before free irq

2016-10-13 Thread Baolin Wang
On 13 October 2016 at 18:56, Felipe Balbi <ba...@kernel.org> wrote:
>
> Hi,
>
> Felipe Balbi <ba...@kernel.org> writes:
>> Hi,
>>
>> Baolin Wang <baolin.w...@linaro.org> writes:
>>>>>> I'm thinking this is a bug in configfs interface of Gadget API, not
>>>>>> dwc3. The only reason for this to happen would be if we get to
>>>>>> ->udc_stop() with endpoints still enabled.
>>>>>>
>>>>>> Can you check if that's the case? i.e. can you check if any endpoints
>>>>>> are still enabled when we get here?
>>>>>
>>>>> No, it is not any endpoints are still enabled. Like I said in commit
>>>>> message, we will start end transfer command when disable the endpoint,
>>>>> if the end transfer command complete event comes after we have freed
>>>>> the gadget irq, it will trigger the interrupt line all the time to
>>>>> crash the system.
>>>>
>>>> I see what the problem is. Databook tells us we *must* set CMDIOC when
>>>> issuing EndTransfer command and we should always wait for Command
>>>> Complete IRQ. However, we took a shortcut and just delayed for 100us
>>>> after issuing End Transfer.
>>>
>>> Yes, but 100us delay is not enough in some scenarios, like changing
>>> function with configfs frequently, we will met problems.
>>
>> heh, 100us *is* enough. However we still get an IRQ because we requested
>> for it. If you want to fix this, then you need to find a way to get rid
>> of that 100us udelay() and add a proper wait_for_completion() to delay
>> execution until command complete IRQ fires up.
>
> I haven't tested this yet, but it shows the idea (I think we might still
> have a race with ep_queue if we're still waiting for End Transfer, but

Yes, maybe we need check DWC3_EP_END_TRANSFER_PENDING flag when
queuing one request.

> that's easy to sort out by checking for DWC3_EP_END_TRANSFER_PENDING
> before calling kick_transfer). Could you have a look and, perhaps, run a
> test?

Sure. I will test it and send out the result tomorrow.

>
> diff --git a/drivers/usb/dwc3/core.h b/drivers/usb/dwc3/core.h
> index e878366ead00..24a77e9f9bba 100644
> --- a/drivers/usb/dwc3/core.h
> +++ b/drivers/usb/dwc3/core.h
> @@ -26,6 +26,7 @@
>  #include 
>  #include 
>  #include 
> +#include 
>
>  #include 
>  #include 
> @@ -504,6 +505,7 @@ struct dwc3_event_buffer {
>   * @endpoint: usb endpoint
>   * @pending_list: list of pending requests for this endpoint
>   * @started_list: list of started requests on this endpoint
> + * @wait_end_transfer: wait_queue_head_t for waiting on End Transfer complete
>   * @lock: spinlock for endpoint request queue traversal
>   * @regs: pointer to first endpoint register
>   * @trb_pool: array of transaction buffers
> @@ -529,6 +531,8 @@ struct dwc3_ep {
> struct list_headpending_list;
> struct list_headstarted_list;
>
> +   wait_queue_head_t   wait_end_transfer;
> +
> spinlock_t  lock;
> void __iomem*regs;
>
> @@ -545,7 +549,7 @@ struct dwc3_ep {
>  #define DWC3_EP_BUSY   (1 << 4)
>  #define DWC3_EP_PENDING_REQUEST(1 << 5)
>  #define DWC3_EP_MISSED_ISOC(1 << 6)
> -
> +#define DWC3_EP_END_TRANSFER_PENDING (1 << 7)
> /* This last one is specific to EP0 */
>  #define DWC3_EP0_DIR_IN(1 << 31)
>
> @@ -1047,6 +1051,9 @@ struct dwc3_event_depevt {
>  #define DEPEVT_TRANSFER_BUS_EXPIRY 2
>
> u32 parameters:16;
> +
> +/* For Command Complete Events */
> +#define DEPEVT_PARAMETER_CMD(n) (((n) & (0xf << 24)) >> 24)
>  } __packed;
>
>  /**
> diff --git a/drivers/usb/dwc3/gadget.c b/drivers/usb/dwc3/gadget.c
> index 3ba05b12e49a..8037bff43485 100644
> --- a/drivers/usb/dwc3/gadget.c
> +++ b/drivers/usb/dwc3/gadget.c
> @@ -598,6 +598,8 @@ static int __dwc3_gadget_ep_enable(struct dwc3_ep *dep,
> reg |= DWC3_DALEPENA_EP(dep->number);
> dwc3_writel(dwc->regs, DWC3_DALEPENA, reg);
>
> +   init_waitqueue_head(>wait_end_transfer);
> +
> if (usb_endpoint_xfer_control(desc))
> return 0;
>
> @@ -2156,6 +2158,7 @@ static void dwc3_endpoint_interrupt(struct dwc3 *dwc,
>  {
> struct dwc3_ep  *dep;
> u8  epnum = event->endpoint_number;
> +   u8  cmd;
>
> dep = dwc->eps[epnum];
>
> @@ -

Re: [RESEND PATCH v3 1/2] usb: dwc3: gadget: Add disconnect checking when changing function dynamically

2016-10-13 Thread Baolin Wang
Hi Felipe,

On 13 October 2016 at 19:22, Felipe Balbi <ba...@kernel.org> wrote:
>
> Hi,
>
> Janusz Dziedzic <janusz.dzied...@tieto.com> writes:
>>>> Baolin Wang <baolin.w...@linaro.org> writes:
>>>>>>>>>>> diff --git a/drivers/usb/dwc3/gadget.c b/drivers/usb/dwc3/gadget.c
>>>>>>>>>>> index 1783406..ca2ae5b 100644
>>>>>>>>>>> --- a/drivers/usb/dwc3/gadget.c
>>>>>>>>>>> +++ b/drivers/usb/dwc3/gadget.c
>>>>>>>>>>> @@ -241,6 +241,9 @@ int dwc3_send_gadget_ep_cmd(struct dwc3_ep 
>>>>>>>>>>> *dep, unsigned cmd,
>>>>>>>>>>>   int susphy = false;
>>>>>>>>>>>   int ret = -EINVAL;
>>>>>>>>>>>
>>>>>>>>>>> + if (!dwc->pullups_connected)
>>>>>>>>>>> + return -ESHUTDOWN;
>>>>>>>>>>> +
>>>>>>>>
>>>>>>>> you skip trace_dwc3_gadget_ep_cmd()
>>>>>>>
>>>>>>> Yes, we did not need trace here since we did not send out the command.
>>>>>>>
>>>>>> What in such case: enumeration will not work and this will be because
>>>>>> this ESHUTDOWN or wrong pullups_connected usage. Without a trace you
>>>>>> will not know where the problem is.
>>>>>> In my opinion this trace could be useful.
>>>>>
>>>>> We have returned the '-ESHUTDOWN' error number for user to know what
>>>>> happened.
>>>>
>>>> No, this is actually not good and Janusz has a very valid point
>>>> here. When we're debugging something in dwc3, we want to rely on
>>>> tracepoints to tell us what's going on. I don't want to have to add more
>>>> debugging messages to print out that ESHUTDOWN error just so I can
>>>> figure out what's going on. You should be patching this in a way that
>>>> the tracepoint is still printed out properly.
>>>
>>> Fine. Will fix this in next version.
>>>
>>
>> BTW, did you test this patch with device mode?
>> Seems in my setup this fail - DWC3_DEPCMD_SETEPCONFIG for ep0out and
>> gadget_start() failed (enumeration fail).
>> Don't we need to queue ep0 cmds before pullup?
>
> Baolin, it's clear to me that you're not testing any of the patches

I am sure I tested every patch I send to you. But this one is really
my mistake and I thought this is just one small change with just eye
review. I am really sorry for troubles.

> you're sending me. I just reviewed this part of the code and we _do_
> indeed enable the control pipe before connecting pullups and that *must*
> be done this way, otherwise we won't be able to receive first Setup
> packet from host.
>
> How have you tested this? Against which tree?
>
> --
> balbi



-- 
Baolin.wang
Best Regards
--
To unsubscribe from this list: send the line "unsubscribe linux-usb" in
the body of a message to majord...@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html


Re: [PATCH v2] usb: dwc3: gadget: Wait for end transfer complete before free irq

2016-10-13 Thread Baolin Wang
Hi Felipe,

On 13 October 2016 at 19:23, Felipe Balbi <ba...@kernel.org> wrote:
>
> Hi,
>
> Baolin Wang <baolin.w...@linaro.org> writes:
>>>> Baolin Wang <baolin.w...@linaro.org> writes:
>>>>>>>> I'm thinking this is a bug in configfs interface of Gadget API, not
>>>>>>>> dwc3. The only reason for this to happen would be if we get to
>>>>>>>> ->udc_stop() with endpoints still enabled.
>>>>>>>>
>>>>>>>> Can you check if that's the case? i.e. can you check if any endpoints
>>>>>>>> are still enabled when we get here?
>>>>>>>
>>>>>>> No, it is not any endpoints are still enabled. Like I said in commit
>>>>>>> message, we will start end transfer command when disable the endpoint,
>>>>>>> if the end transfer command complete event comes after we have freed
>>>>>>> the gadget irq, it will trigger the interrupt line all the time to
>>>>>>> crash the system.
>>>>>>
>>>>>> I see what the problem is. Databook tells us we *must* set CMDIOC when
>>>>>> issuing EndTransfer command and we should always wait for Command
>>>>>> Complete IRQ. However, we took a shortcut and just delayed for 100us
>>>>>> after issuing End Transfer.
>>>>>
>>>>> Yes, but 100us delay is not enough in some scenarios, like changing
>>>>> function with configfs frequently, we will met problems.
>>>>
>>>> heh, 100us *is* enough. However we still get an IRQ because we requested
>>>> for it. If you want to fix this, then you need to find a way to get rid
>>>> of that 100us udelay() and add a proper wait_for_completion() to delay
>>>> execution until command complete IRQ fires up.
>>>
>>> I haven't tested this yet, but it shows the idea (I think we might still
>>> have a race with ep_queue if we're still waiting for End Transfer, but
>>
>> Yes, maybe we need check DWC3_EP_END_TRANSFER_PENDING flag when
>> queuing one request.
>
> Yeah, I'll add that check later. I still need to make sure we would
> still try to kick any transfers that might have been queued while
> waiting for End Transfer Command Complete IRQ.

OK. But I still worried if there are other races in some places which
is not easy to find out by testing. No introducing race condition
would be one better solution, anyway I would like to test the patch
you send out firstly.

>
>>> that's easy to sort out by checking for DWC3_EP_END_TRANSFER_PENDING
>>> before calling kick_transfer). Could you have a look and, perhaps, run a
>>> test?
>>
>> Sure. I will test it and send out the result tomorrow.
>
> Thank you
>
> --
> balbi



-- 
Baolin.wang
Best Regards
--
To unsubscribe from this list: send the line "unsubscribe linux-usb" in
the body of a message to majord...@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html


Re: [RESEND PATCH v3 1/2] usb: dwc3: gadget: Add disconnect checking when changing function dynamically

2016-10-13 Thread Baolin Wang
On 13 October 2016 at 20:17, Felipe Balbi <ba...@kernel.org> wrote:
>
> Hi,
>
> Baolin Wang <baolin.w...@linaro.org> writes:
>>>>>>>>>>>>> @@ -241,6 +241,9 @@ int dwc3_send_gadget_ep_cmd(struct dwc3_ep 
>>>>>>>>>>>>> *dep, unsigned cmd,
>>>>>>>>>>>>>   int susphy = false;
>>>>>>>>>>>>>   int ret = -EINVAL;
>>>>>>>>>>>>>
>>>>>>>>>>>>> + if (!dwc->pullups_connected)
>>>>>>>>>>>>> + return -ESHUTDOWN;
>>>>>>>>>>>>> +
>>>>>>>>>>
>>>>>>>>>> you skip trace_dwc3_gadget_ep_cmd()
>>>>>>>>>
>>>>>>>>> Yes, we did not need trace here since we did not send out the command.
>>>>>>>>>
>>>>>>>> What in such case: enumeration will not work and this will be because
>>>>>>>> this ESHUTDOWN or wrong pullups_connected usage. Without a trace you
>>>>>>>> will not know where the problem is.
>>>>>>>> In my opinion this trace could be useful.
>>>>>>>
>>>>>>> We have returned the '-ESHUTDOWN' error number for user to know what
>>>>>>> happened.
>>>>>>
>>>>>> No, this is actually not good and Janusz has a very valid point
>>>>>> here. When we're debugging something in dwc3, we want to rely on
>>>>>> tracepoints to tell us what's going on. I don't want to have to add more
>>>>>> debugging messages to print out that ESHUTDOWN error just so I can
>>>>>> figure out what's going on. You should be patching this in a way that
>>>>>> the tracepoint is still printed out properly.
>>>>>
>>>>> Fine. Will fix this in next version.
>>>>>
>>>>
>>>> BTW, did you test this patch with device mode?
>>>> Seems in my setup this fail - DWC3_DEPCMD_SETEPCONFIG for ep0out and
>>>> gadget_start() failed (enumeration fail).
>>>> Don't we need to queue ep0 cmds before pullup?
>>>
>>> Baolin, it's clear to me that you're not testing any of the patches
>>
>> I am sure I tested every patch I send to you. But this one is really
>> my mistake and I thought this is just one small change with just eye
>> review. I am really sorry for troubles.
>
> fair enough, luckily Janusz caught it before any harm could be
> done. Thanks for taking the time to explain.

Thanks for understanding and thanks for Janusz's testing.


-- 
Baolin.wang
Best Regards
--
To unsubscribe from this list: send the line "unsubscribe linux-usb" in
the body of a message to majord...@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html


[PATCH v17 3/4] usb: gadget: Integrate with the usb gadget supporting for usb charger

2016-10-10 Thread Baolin Wang
When the usb gadget supporting for usb charger is ready, the usb charger
can implement the usb_charger_plug_by_gadget() function, usb_charger_exit()
function and dev_to_uchger() function by getting 'struct usb_charger' from
'struct gadget'.

Signed-off-by: Baolin Wang <baolin.w...@linaro.org>
Reviewed-by: Li Jun <jun...@nxp.com>
Tested-by: Li Jun <jun...@nxp.com>
---
 drivers/usb/gadget/udc/charger.c |   97 +-
 1 file changed, 95 insertions(+), 2 deletions(-)

diff --git a/drivers/usb/gadget/udc/charger.c b/drivers/usb/gadget/udc/charger.c
index 16dc477..691cd75 100644
--- a/drivers/usb/gadget/udc/charger.c
+++ b/drivers/usb/gadget/udc/charger.c
@@ -38,7 +38,9 @@ static DEFINE_MUTEX(charger_lock);
 
 static struct usb_charger *dev_to_uchger(struct device *dev)
 {
-   return NULL;
+   struct usb_gadget *gadget = container_of(dev, struct usb_gadget, dev);
+
+   return gadget->charger;
 }
 
 /*
@@ -308,6 +310,18 @@ static int __usb_charger_set_cur_limit_by_type(struct 
usb_charger *uchger,
 int usb_charger_set_cur_limit_by_gadget(struct usb_gadget *gadget,
unsigned int cur_limit)
 {
+   struct usb_charger *uchger = gadget->charger;
+   int ret;
+
+   if (!uchger)
+   return -EINVAL;
+
+   ret = __usb_charger_set_cur_limit_by_type(uchger, uchger->type,
+ cur_limit);
+   if (ret)
+   return ret;
+
+   schedule_work(>work);
return 0;
 }
 EXPORT_SYMBOL_GPL(usb_charger_set_cur_limit_by_gadget);
@@ -625,11 +639,67 @@ static int usb_charger_plug_by_extcon(struct 
notifier_block *nb,
 int usb_charger_plug_by_gadget(struct usb_gadget *gadget,
   unsigned long state)
 {
+   struct usb_charger *uchger = gadget->charger;
+   enum usb_charger_state uchger_state;
+
+   if (WARN(!uchger, "charger can not be NULL"))
+   return -EINVAL;
+
+   /*
+* Report event to power to setting the current limitation
+* for this usb charger when one usb charger state is changed
+* with detecting by usb gadget state.
+*/
+   if (uchger->old_gadget_state != state) {
+   uchger->old_gadget_state = state;
+
+   if (state >= USB_STATE_ATTACHED) {
+   uchger_state = USB_CHARGER_PRESENT;
+   } else if (state == USB_STATE_NOTATTACHED) {
+   mutex_lock(>lock);
+
+   /*
+* Need check the charger type to make sure the usb
+* cable is removed, in case it just changes the usb
+* function with configfs.
+*/
+   uchger->type = __usb_charger_get_type(uchger);
+   if (uchger->type != UNKNOWN_TYPE) {
+   mutex_unlock(>lock);
+   return 0;
+   }
+
+   mutex_unlock(>lock);
+   uchger_state = USB_CHARGER_REMOVE;
+   } else {
+   uchger_state = USB_CHARGER_DEFAULT;
+   }
+
+   usb_charger_notify_state(uchger, uchger_state);
+   }
+
return 0;
 }
 EXPORT_SYMBOL_GPL(usb_charger_plug_by_gadget);
 
 /*
+ * usb_charger_unregister() - Unregister a usb charger.
+ * @uchger - the usb charger to be unregistered.
+ */
+static int usb_charger_unregister(struct usb_charger *uchger)
+{
+   ida_simple_remove(_charger_ida, uchger->id);
+   sysfs_remove_groups(>gadget->dev.kobj, usb_charger_groups);
+
+   mutex_lock(_lock);
+   list_del(>list);
+   mutex_unlock(_lock);
+
+   kfree(uchger);
+   return 0;
+}
+
+/*
  * usb_charger_register() - Register a new usb charger.
  * @uchger - the new usb charger instance.
  */
@@ -740,6 +810,7 @@ int usb_charger_init(struct usb_gadget *ugadget)
}
 
uchger->gadget = ugadget;
+   ugadget->charger = uchger;
uchger->old_gadget_state = USB_STATE_NOTATTACHED;
 
/* Register a new usb charger */
@@ -777,7 +848,29 @@ fail_extcon:
 
 int usb_charger_exit(struct usb_gadget *ugadget)
 {
-   return 0;
+   struct usb_charger *uchger = ugadget->charger;
+
+   if (!uchger)
+   return -EINVAL;
+
+   ugadget->charger = NULL;
+   extcon_unregister_notifier(uchger->extcon_dev,
+  EXTCON_USB,
+  >extcon_nb.nb);
+   extcon_unregister_notifier(uchger->extcon_dev,
+  EXTCON_CHG_USB_SDP,
+  >extcon_type_nb.nb);
+   extcon_unregister_notifier(uchger->extcon_dev,
+  EXTCON_CHG_USB_CDP,

[PATCH] usb: dwc3: gadget: Wait for end transfer complete before free irq

2016-10-10 Thread Baolin Wang
When we change the USB function with configfs frequently, sometimes it will
hang the system to crash. The reason is the gadget driver can not hanle the
end transfer complete event after free the gadget irq (since the xHCI will
share the same interrupt number with gadget, thus when free the gadget irq,
it will not shutdown this gadget irq line), which will trigger the interrupt
all the time.

Thus we should check if we need wait for the end transfer command completion
before free gadget irq.

Signed-off-by: Baolin Wang <baolin.w...@linaro.org>
---
 drivers/usb/dwc3/core.h   |3 ++
 drivers/usb/dwc3/gadget.c |   73 +++--
 2 files changed, 73 insertions(+), 3 deletions(-)

diff --git a/drivers/usb/dwc3/core.h b/drivers/usb/dwc3/core.h
index 9128725..f01d8fd 100644
--- a/drivers/usb/dwc3/core.h
+++ b/drivers/usb/dwc3/core.h
@@ -537,6 +537,7 @@ struct dwc3_ep {
 #define DWC3_EP_BUSY   (1 << 4)
 #define DWC3_EP_PENDING_REQUEST(1 << 5)
 #define DWC3_EP_MISSED_ISOC(1 << 6)
+#define DWC3_EP_CMDCMPLT_BUSY  (1 << 7)
 
/* This last one is specific to EP0 */
 #define DWC3_EP0_DIR_IN(1 << 31)
@@ -746,6 +747,7 @@ struct dwc3_scratchpad_array {
  * @ep0_bounce_addr: dma address of ep0_bounce
  * @scratch_addr: dma address of scratchbuf
  * @ep0_in_setup: One control transfer is completed and enter setup phase
+ * @cmd_complete: endpoint command completion
  * @lock: for synchronizing
  * @dev: pointer to our struct device
  * @xhci: pointer to our xHCI child
@@ -845,6 +847,7 @@ struct dwc3 {
dma_addr_t  scratch_addr;
struct dwc3_request ep0_usb_req;
struct completion   ep0_in_setup;
+   struct completion   cmd_complete;
 
/* device lock */
spinlock_t  lock;
diff --git a/drivers/usb/dwc3/gadget.c b/drivers/usb/dwc3/gadget.c
index fef023a..36db8ba 100644
--- a/drivers/usb/dwc3/gadget.c
+++ b/drivers/usb/dwc3/gadget.c
@@ -573,6 +573,7 @@ static int __dwc3_gadget_ep_enable(struct dwc3_ep *dep,
dep->comp_desc = comp_desc;
dep->type = usb_endpoint_type(desc);
dep->flags |= DWC3_EP_ENABLED;
+   dep->flags &= ~DWC3_EP_CMDCMPLT_BUSY;
 
reg = dwc3_readl(dwc->regs, DWC3_DALEPENA);
reg |= DWC3_DALEPENA_EP(dep->number);
@@ -650,7 +651,7 @@ static int __dwc3_gadget_ep_disable(struct dwc3_ep *dep)
dep->endpoint.desc = NULL;
dep->comp_desc = NULL;
dep->type = 0;
-   dep->flags = 0;
+   dep->flags = 0 | (dep->flags & DWC3_EP_CMDCMPLT_BUSY);
 
return 0;
 }
@@ -1732,6 +1733,54 @@ static void __dwc3_gadget_stop(struct dwc3 *dwc)
__dwc3_gadget_ep_disable(dwc->eps[1]);
 }
 
+static void dwc3_wait_command_complete(struct dwc3 *dwc)
+{
+   u32 epnum, epstart = 2;
+   int ret, wait_cmd_complete = 0;
+   unsigned long flags;
+
+check_next:
+   spin_lock_irqsave(>lock, flags);
+   /*
+* If the gadget has been in suspend state, then don't
+* need to wait for the end transfer complete event.
+*/
+   if (pm_runtime_suspended(dwc->dev)) {
+   spin_unlock_irqrestore(>lock, flags);
+   return;
+   }
+
+   for (epnum = epstart; epnum < DWC3_ENDPOINTS_NUM; epnum++) {
+   struct dwc3_ep *dep;
+
+   dep = dwc->eps[epnum];
+   if (!dep)
+   continue;
+
+   if (dep->flags & DWC3_EP_CMDCMPLT_BUSY) {
+   reinit_completion(>cmd_complete);
+   epstart = epnum + 1;
+   wait_cmd_complete = 1;
+   break;
+   }
+   }
+   spin_unlock_irqrestore(>lock, flags);
+
+   /*
+* Wait for 500ms to complete the end transfer command before free irq.
+*/
+   if (wait_cmd_complete) {
+   wait_cmd_complete = 0;
+   ret = wait_for_completion_timeout(>cmd_complete,
+ msecs_to_jiffies(500));
+   if (ret == 0)
+   dev_warn(dwc->dev,
+"timeout to wait for command complete.\n");
+
+   goto check_next;
+   }
+}
+
 static int dwc3_gadget_stop(struct usb_gadget *g)
 {
struct dwc3 *dwc = gadget_to_dwc(g);
@@ -1742,6 +1791,17 @@ static int dwc3_gadget_stop(struct usb_gadget *g)
dwc->gadget_driver  = NULL;
spin_unlock_irqrestore(>lock, flags);
 
+   /*
+* Since the xHCI will share the same interrupt with gadget, thus when
+* free the gadget irq, it will not shutdown this gadget irq line. Then
+* the gadget driver can not handle the end transfer command complete
+* event

[PATCH v17 0/4] Introduce usb charger framework to deal with the usb gadget power negotation

2016-10-10 Thread Baolin Wang
Currently the Linux kernel does not provide any standard integration of this
feature that integrates the USB subsystem with the system power regulation
provided by PMICs meaning that either vendors must add this in their kernels
or USB gadget devices based on Linux (such as mobile phones) may not behave
as they should. Thus provide a standard framework for doing this in kernel.

Now introduce one user with wm831x_power to support and test the usb charger,
which is pending testing. Moreover there may be other potential users will use
it in future.

Changes since v16:
 - Modify the charger current range with introducing the maximum and minimum
 current.
 - Remove the getting charger type method from power supply.
 - Add the getting charger type method from extcon system.
 - Introduce new usb_charger_get_current() API for users to get the maximum and
 minimum current.
 - Rename some APIs and other optimization.

Changes since v15:
 - Add charger state checking to avoid sending out duplicate notifies to users.
 - Add one work to notify power users the current has been changed.

Changes since v14:
 - Add kernel documentation for struct usb_cahrger.
 - Remove some redundant WARN() functions.

Changes since v13:
 - Remove the charger checking in usb_gadget_vbus_draw() function.
 - Rename some functions in charger.c file.
 - Rebase on git://git.kernel.org/pub/scm/linux/kernel/git/balbi/usb.git 
tags/usb-for-v4.8

Changes since v12:
 - Remove the class and device things.
 - Link usb charger to udc-core.ko.
 - Create one "charger" subdirectory which holds all charger-related attributes.

Changes since v11:
 - Reviewed and tested by Li Jun.

Changes since v10:
 - Introduce usb_charger_get_state() function to check charger state.
 - Remove the mutex lock in usb_charger_set_cur_limit_by_type() function
 in case will be issued in atomic context.

Baolin Wang (4):
  usb: gadget: Introduce the usb charger framework
  usb: gadget: Support for the usb charger framework
  usb: gadget: Integrate with the usb gadget supporting for usb charger
  power: wm831x_power: Support USB charger current limit management

 drivers/power/wm831x_power.c |   75 
 drivers/usb/gadget/Kconfig   |8 +
 drivers/usb/gadget/udc/Makefile  |1 +
 drivers/usb/gadget/udc/charger.c |  878 ++
 drivers/usb/gadget/udc/core.c|   19 +-
 include/linux/mfd/wm831x/pdata.h |3 +
 include/linux/usb/charger.h  |  186 
 include/linux/usb/gadget.h   |3 +
 include/uapi/linux/usb/charger.h |   31 ++
 9 files changed, 1203 insertions(+), 1 deletion(-)
 create mode 100644 drivers/usb/gadget/udc/charger.c
 create mode 100644 include/linux/usb/charger.h
 create mode 100644 include/uapi/linux/usb/charger.h

-- 
1.7.9.5

--
To unsubscribe from this list: send the line "unsubscribe linux-usb" in
the body of a message to majord...@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html


[PATCH v17 1/4] usb: gadget: Introduce the usb charger framework

2016-10-10 Thread Baolin Wang
This patch introduces the usb charger driver based on usb gadget that
makes an enhancement to a power driver. It works well in practice but
that requires a system with suitable hardware.

The basic conception of the usb charger is that, when one usb charger
is added or removed by reporting from the usb gadget state change or
the extcon device state change, the usb charger will report to power
user to set the current limitation.

The usb charger will register notifiees on the usb gadget or the extcon
device to get notified the usb charger state. It also supplies the
notification mechanism to userspace When the usb charger state is changed.

Power user will register a notifiee on the usb charger to get notified
by status changes from the usb charger. It will report to power user
to set the current limitation when detecting the usb charger is added
or removed from extcon device state or usb gadget state.

This patch doesn't yet integrate with the gadget code, so some functions
which rely on the 'gadget' are not completed, that will be implemented
in the following patches.

Signed-off-by: Baolin Wang <baolin.w...@linaro.org>
Reviewed-by: Li Jun <jun...@nxp.com>
Tested-by: Li Jun <jun...@nxp.com>
---
 drivers/usb/gadget/Kconfig   |8 +
 drivers/usb/gadget/udc/Makefile  |1 +
 drivers/usb/gadget/udc/charger.c |  785 ++
 include/linux/usb/charger.h  |  186 +
 include/uapi/linux/usb/charger.h |   31 ++
 5 files changed, 1011 insertions(+)
 create mode 100644 drivers/usb/gadget/udc/charger.c
 create mode 100644 include/linux/usb/charger.h
 create mode 100644 include/uapi/linux/usb/charger.h

diff --git a/drivers/usb/gadget/Kconfig b/drivers/usb/gadget/Kconfig
index 2ea3fc3..7520677 100644
--- a/drivers/usb/gadget/Kconfig
+++ b/drivers/usb/gadget/Kconfig
@@ -134,6 +134,14 @@ config U_SERIAL_CONSOLE
help
   It supports the serial gadget can be used as a console.
 
+config USB_CHARGER
+   bool "USB charger support"
+   select EXTCON
+   help
+ The usb charger driver based on the usb gadget that makes an
+ enhancement to a power driver which can set the current limitation
+ when the usb charger is added or removed.
+
 source "drivers/usb/gadget/udc/Kconfig"
 
 #
diff --git a/drivers/usb/gadget/udc/Makefile b/drivers/usb/gadget/udc/Makefile
index 98e74ed..ede2351 100644
--- a/drivers/usb/gadget/udc/Makefile
+++ b/drivers/usb/gadget/udc/Makefile
@@ -2,6 +2,7 @@
 CFLAGS_trace.o := -I$(src)
 
 udc-core-y := core.o trace.o
+udc-core-$(CONFIG_USB_CHARGER) += charger.o
 
 #
 # USB peripheral controller drivers
diff --git a/drivers/usb/gadget/udc/charger.c b/drivers/usb/gadget/udc/charger.c
new file mode 100644
index 000..16dc477
--- /dev/null
+++ b/drivers/usb/gadget/udc/charger.c
@@ -0,0 +1,785 @@
+/*
+ * charger.c -- USB charger driver
+ *
+ * Copyright (C) 2016 Linaro Ltd.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ */
+
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+
+/* Default current range by charger type. */
+#define DEFAULT_SDP_CUR_MIN2
+#define DEFAULT_SDP_CUR_MAX500
+#define DEFAULT_SDP_CUR_MIN_SS 150
+#define DEFAULT_SDP_CUR_MAX_SS 900
+#define DEFAULT_DCP_CUR_MIN500
+#define DEFAULT_DCP_CUR_MAX5000
+#define DEFAULT_CDP_CUR_MIN1500
+#define DEFAULT_CDP_CUR_MAX5000
+#define DEFAULT_ACA_CUR_MIN1500
+#define DEFAULT_ACA_CUR_MAX5000
+
+static DEFINE_IDA(usb_charger_ida);
+static LIST_HEAD(charger_list);
+static DEFINE_MUTEX(charger_lock);
+
+static struct usb_charger *dev_to_uchger(struct device *dev)
+{
+   return NULL;
+}
+
+/*
+ * charger_current_show() - Show the charger current.
+ */
+static ssize_t charger_current_show(struct device *dev,
+   struct device_attribute *attr,
+   char *buf)
+{
+   struct usb_charger *uchger = dev_to_uchger(dev);
+   unsigned int min, max;
+
+   usb_charger_get_current(uchger, , );
+   return sprintf(buf, "%u-%u\n", min, max);
+}
+static DEVICE_ATTR_RO(charger_current);
+
+/*
+ * charger_type_show() - Show the charger type.
+ *
+ * It can be SDP/DCP/CDP/ACA type, else for unknown type.
+ */
+static ssize_t charger_type_show(struct device *dev,
+struct device_attribute *attr,
+char *buf)
+{
+   struct usb_charger *uchger = dev_to_uchger(dev);
+   int cnt;
+
+   switch (uchger->type) {
+   case SDP_TYPE:
+   cnt = sprintf(buf, "%s\n", "SDP");
+   break;
+   case DCP_TYPE:
+   cnt = sprintf(buf, "%s\n

[PATCH v17 2/4] usb: gadget: Support for the usb charger framework

2016-10-10 Thread Baolin Wang
For supporting the usb charger, it adds the usb_charger_init() and
usb_charger_exit() functions for usb charger initialization and exit.

It will report to the usb charger when the gadget state is changed,
then the usb charger can do the power things.

Signed-off-by: Baolin Wang <baolin.w...@linaro.org>
Reviewed-by: Li Jun <jun...@nxp.com>
Tested-by: Li Jun <jun...@nxp.com>
---
 drivers/usb/gadget/udc/core.c |   19 ++-
 include/linux/usb/gadget.h|3 +++
 2 files changed, 21 insertions(+), 1 deletion(-)

diff --git a/drivers/usb/gadget/udc/core.c b/drivers/usb/gadget/udc/core.c
index 9483489..90df022 100644
--- a/drivers/usb/gadget/udc/core.c
+++ b/drivers/usb/gadget/udc/core.c
@@ -25,6 +25,7 @@
 #include 
 #include 
 
+#include 
 #include 
 #include 
 #include 
@@ -576,12 +577,17 @@ EXPORT_SYMBOL_GPL(usb_gadget_vbus_connect);
  * reporting how much power the device may consume.  For example, this
  * could affect how quickly batteries are recharged.
  *
+ * It will also notify the USB charger how much power the device may
+ * consume if there is a USB charger linking with the gadget.
+ *
  * Returns zero on success, else negative errno.
  */
 int usb_gadget_vbus_draw(struct usb_gadget *gadget, unsigned mA)
 {
int ret = 0;
 
+   usb_charger_set_cur_limit_by_gadget(gadget, mA);
+
if (!gadget->ops->vbus_draw) {
ret = -EOPNOTSUPP;
goto out;
@@ -963,6 +969,9 @@ static void usb_gadget_state_work(struct work_struct *work)
struct usb_gadget *gadget = work_to_gadget(work);
struct usb_udc *udc = gadget->udc;
 
+   /* when the gadget state is changed, then report to USB charger */
+   usb_charger_plug_by_gadget(gadget, gadget->state);
+
if (udc)
sysfs_notify(>dev.kobj, NULL, "state");
 }
@@ -1132,6 +1141,10 @@ int usb_add_gadget_udc_release(struct device *parent, 
struct usb_gadget *gadget,
if (ret)
goto err4;
 
+   ret = usb_charger_init(gadget);
+   if (ret)
+   goto err5;
+
usb_gadget_set_state(gadget, USB_STATE_NOTATTACHED);
udc->vbus = true;
 
@@ -1143,7 +1156,7 @@ int usb_add_gadget_udc_release(struct device *parent, 
struct usb_gadget *gadget,
if (ret != -EPROBE_DEFER)
list_del(>pending);
if (ret)
-   goto err5;
+   goto err6;
break;
}
}
@@ -1152,6 +1165,9 @@ int usb_add_gadget_udc_release(struct device *parent, 
struct usb_gadget *gadget,
 
return 0;
 
+err6:
+   usb_charger_exit(gadget);
+
 err5:
device_del(>dev);
 
@@ -1263,6 +1279,7 @@ void usb_del_gadget_udc(struct usb_gadget *gadget)
kobject_uevent(>dev.kobj, KOBJ_REMOVE);
flush_work(>work);
device_unregister(>dev);
+   usb_charger_exit(gadget);
device_unregister(>dev);
 }
 EXPORT_SYMBOL_GPL(usb_del_gadget_udc);
diff --git a/include/linux/usb/gadget.h b/include/linux/usb/gadget.h
index 8e81f9e..82a0d63 100644
--- a/include/linux/usb/gadget.h
+++ b/include/linux/usb/gadget.h
@@ -24,6 +24,7 @@
 #include 
 #include 
 #include 
+#include 
 
 #define UDC_TRACE_STR_MAX  512
 
@@ -328,6 +329,7 @@ struct usb_gadget_ops {
  * @in_epnum: last used in ep number
  * @mA: last set mA value
  * @otg_caps: OTG capabilities of this gadget.
+ * @charger: Negotiate the power with the usb charger.
  * @sg_supported: true if we can handle scatter-gather
  * @is_otg: True if the USB device port uses a Mini-AB jack, so that the
  * gadget driver must provide a USB OTG descriptor.
@@ -387,6 +389,7 @@ struct usb_gadget {
unsignedin_epnum;
unsignedmA;
struct usb_otg_caps *otg_caps;
+   struct usb_charger  *charger;
 
unsignedsg_supported:1;
unsignedis_otg:1;
-- 
1.7.9.5

--
To unsubscribe from this list: send the line "unsubscribe linux-usb" in
the body of a message to majord...@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html


[PATCH v17 4/4] power: wm831x_power: Support USB charger current limit management

2016-10-10 Thread Baolin Wang
Integrate with the newly added USB charger interface to limit the current
we draw from the USB input based on the input device configuration
identified by the USB stack, allowing us to charge more quickly from high
current inputs without drawing more current than specified from others.

Signed-off-by: Mark Brown <broo...@kernel.org>
Signed-off-by: Baolin Wang <baolin.w...@linaro.org>
Acked-by: Lee Jones <lee.jo...@linaro.org>
Acked-by: Charles Keepax <ckee...@opensource.wolfsonmicro.com>
Acked-by: Peter Chen <peter.c...@freescale.com>
Acked-by: Sebastian Reichel <s...@kernel.org>
---
 drivers/power/wm831x_power.c |   75 ++
 include/linux/mfd/wm831x/pdata.h |3 ++
 2 files changed, 78 insertions(+)

diff --git a/drivers/power/wm831x_power.c b/drivers/power/wm831x_power.c
index 7082301..2bcd775 100644
--- a/drivers/power/wm831x_power.c
+++ b/drivers/power/wm831x_power.c
@@ -13,6 +13,7 @@
 #include 
 #include 
 #include 
+#include 
 
 #include 
 #include 
@@ -31,6 +32,8 @@ struct wm831x_power {
char usb_name[20];
char battery_name[20];
bool have_battery;
+   struct usb_charger *usb_charger;
+   struct notifier_block usb_notify;
 };
 
 static int wm831x_power_check_online(struct wm831x *wm831x, int supply,
@@ -125,6 +128,49 @@ static enum power_supply_property wm831x_usb_props[] = {
POWER_SUPPLY_PROP_VOLTAGE_NOW,
 };
 
+/* In milliamps */
+static const unsigned int wm831x_usb_limits[] = {
+   0,
+   2,
+   100,
+   500,
+   900,
+   1500,
+   1800,
+   550,
+};
+
+static int wm831x_usb_limit_change(struct notifier_block *nb,
+  unsigned long state, void *data)
+{
+   struct wm831x_power *wm831x_power = container_of(nb,
+struct wm831x_power,
+usb_notify);
+   struct usb_charger *uchger = (struct usb_charger *)data;
+   unsigned int i, best, min, limit;
+
+   if (state == USB_CHARGER_PRESENT)
+   usb_charger_get_current(uchger, , );
+   else
+   limit = 0;
+
+   /* Find the highest supported limit */
+   best = 0;
+   for (i = 0; i < ARRAY_SIZE(wm831x_usb_limits); i++) {
+   if (limit >= wm831x_usb_limits[i] &&
+   wm831x_usb_limits[best] < wm831x_usb_limits[i])
+   best = i;
+   }
+
+   dev_dbg(wm831x_power->wm831x->dev,
+   "Limiting USB current to %umA", wm831x_usb_limits[best]);
+
+   wm831x_set_bits(wm831x_power->wm831x, WM831X_POWER_STATE,
+   WM831X_USB_ILIM_MASK, best);
+
+   return 0;
+}
+
 /*
  * Battery properties
  */
@@ -607,8 +653,31 @@ static int wm831x_power_probe(struct platform_device *pdev)
}
}
 
+   if (wm831x_pdata && wm831x_pdata->usb_gadget) {
+   power->usb_charger =
+   usb_charger_find_by_name(wm831x_pdata->usb_gadget);
+   if (IS_ERR(power->usb_charger)) {
+   ret = PTR_ERR(power->usb_charger);
+   dev_err(>dev,
+   "Failed to find USB gadget: %d\n", ret);
+   goto err_bat_irq;
+   }
+
+   power->usb_notify.notifier_call = wm831x_usb_limit_change;
+
+   ret = usb_charger_register_notify(power->usb_charger,
+ >usb_notify);
+   if (ret != 0) {
+   dev_err(>dev,
+   "Failed to register notifier: %d\n", ret);
+   goto err_usb_charger;
+   }
+   }
+
return ret;
 
+err_usb_charger:
+   /* put_device on charger */
 err_bat_irq:
--i;
for (; i >= 0; i--) {
@@ -637,6 +706,12 @@ static int wm831x_power_remove(struct platform_device 
*pdev)
struct wm831x *wm831x = wm831x_power->wm831x;
int irq, i;
 
+   if (wm831x_power->usb_charger) {
+   usb_charger_unregister_notify(wm831x_power->usb_charger,
+ _power->usb_notify);
+   /* Free charger */
+   }
+
for (i = 0; i < ARRAY_SIZE(wm831x_bat_irqs); i++) {
irq = wm831x_irq(wm831x, 
 platform_get_irq_byname(pdev,
diff --git a/include/linux/mfd/wm831x/pdata.h b/include/linux/mfd/wm831x/pdata.h
index dcc9631..5af8399 100644
--- a/include/linux/mfd/wm831x/pdata.h
+++ b/include/linux/mfd/wm831x/pdata.h
@@ -126,6 +126,9 @@ struct wm831x_pdata {
   

Re: [PATCH v17 3/4] usb: gadget: Integrate with the usb gadget supporting for usb charger

2016-10-10 Thread Baolin Wang
Hi Baolu,

On 11 October 2016 at 12:32, Lu Baolu <baolu...@linux.intel.com> wrote:
> Hi,
>
> On 10/11/2016 12:07 PM, Baolin Wang wrote:
>>>>  /*
>>>> >> + * usb_charger_unregister() - Unregister a usb charger.
>>>> >> + * @uchger - the usb charger to be unregistered.
>>>> >> + */
>>>> >> +static int usb_charger_unregister(struct usb_charger *uchger)
>>>> >> +{
>>>> >> + ida_simple_remove(_charger_ida, uchger->id);
>>>> >> + sysfs_remove_groups(>gadget->dev.kobj, 
>>>> >> usb_charger_groups);
>>>> >> +
>>>> >> + mutex_lock(_lock);
>>>> >> + list_del(>list);
>>>> >> + mutex_unlock(_lock);
>>>> >> +
>>>> >> + kfree(uchger);
>>> >
>>> > Any reasons you want to put kfree() here? You allocated the memory
>>> > in usb_charger_init(). Isn't usb_charger_exit() a better place?
>> The usb_charger_exit() will issue usb_charger_unregister() and we need
>> use the usb_charger structure in usb_charger_unregister() to
>> unregister the usb charger.
>>
>
> This seems not to be a strong reason. :-)
>
> You can unregister the charger first and then free the structure.
> Just do the reverse operation of what you have done in the init
> function.

Make sense to me. I will modify this in next version. Thanks for your comments.

-- 
Baolin.wang
Best Regards
--
To unsubscribe from this list: send the line "unsubscribe linux-usb" in
the body of a message to majord...@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html


Re: [PATCH v17 3/4] usb: gadget: Integrate with the usb gadget supporting for usb charger

2016-10-10 Thread Baolin Wang
Hi Baolu,

On 11 October 2016 at 11:06, Lu Baolu <baolu...@linux.intel.com> wrote:
> Hi,
>
> On 10/10/2016 02:22 PM, Baolin Wang wrote:
>> When the usb gadget supporting for usb charger is ready, the usb charger
>> can implement the usb_charger_plug_by_gadget() function, usb_charger_exit()
>> function and dev_to_uchger() function by getting 'struct usb_charger' from
>> 'struct gadget'.
>>
>> Signed-off-by: Baolin Wang <baolin.w...@linaro.org>
>> Reviewed-by: Li Jun <jun...@nxp.com>
>> Tested-by: Li Jun <jun...@nxp.com>
>> ---
>>  drivers/usb/gadget/udc/charger.c |   97 
>> +-
>>  1 file changed, 95 insertions(+), 2 deletions(-)
>>
>> diff --git a/drivers/usb/gadget/udc/charger.c 
>> b/drivers/usb/gadget/udc/charger.c
>> index 16dc477..691cd75 100644
>> --- a/drivers/usb/gadget/udc/charger.c
>> +++ b/drivers/usb/gadget/udc/charger.c
>> @@ -38,7 +38,9 @@ static DEFINE_MUTEX(charger_lock);
>>
>>  static struct usb_charger *dev_to_uchger(struct device *dev)
>>  {
>> - return NULL;
>> + struct usb_gadget *gadget = container_of(dev, struct usb_gadget, dev);
>> +
>> + return gadget->charger;
>>  }
>>
>>  /*
>> @@ -308,6 +310,18 @@ static int __usb_charger_set_cur_limit_by_type(struct 
>> usb_charger *uchger,
>>  int usb_charger_set_cur_limit_by_gadget(struct usb_gadget *gadget,
>>   unsigned int cur_limit)
>>  {
>> + struct usb_charger *uchger = gadget->charger;
>> + int ret;
>> +
>> + if (!uchger)
>> + return -EINVAL;
>> +
>> + ret = __usb_charger_set_cur_limit_by_type(uchger, uchger->type,
>> +   cur_limit);
>> + if (ret)
>> + return ret;
>> +
>> + schedule_work(>work);
>>   return 0;
>>  }
>>  EXPORT_SYMBOL_GPL(usb_charger_set_cur_limit_by_gadget);
>> @@ -625,11 +639,67 @@ static int usb_charger_plug_by_extcon(struct 
>> notifier_block *nb,
>>  int usb_charger_plug_by_gadget(struct usb_gadget *gadget,
>>  unsigned long state)
>>  {
>> + struct usb_charger *uchger = gadget->charger;
>> + enum usb_charger_state uchger_state;
>> +
>> + if (WARN(!uchger, "charger can not be NULL"))
>> + return -EINVAL;
>> +
>> + /*
>> +  * Report event to power to setting the current limitation
>> +  * for this usb charger when one usb charger state is changed
>> +  * with detecting by usb gadget state.
>> +  */
>> + if (uchger->old_gadget_state != state) {
>> + uchger->old_gadget_state = state;
>> +
>> + if (state >= USB_STATE_ATTACHED) {
>> + uchger_state = USB_CHARGER_PRESENT;
>> + } else if (state == USB_STATE_NOTATTACHED) {
>> + mutex_lock(>lock);
>> +
>> + /*
>> +  * Need check the charger type to make sure the usb
>> +  * cable is removed, in case it just changes the usb
>> +  * function with configfs.
>> +  */
>> + uchger->type = __usb_charger_get_type(uchger);
>> + if (uchger->type != UNKNOWN_TYPE) {
>> + mutex_unlock(>lock);
>> + return 0;
>> + }
>> +
>> + mutex_unlock(>lock);
>> + uchger_state = USB_CHARGER_REMOVE;
>> + } else {
>> + uchger_state = USB_CHARGER_DEFAULT;
>> + }
>> +
>> + usb_charger_notify_state(uchger, uchger_state);
>> + }
>> +
>>   return 0;
>>  }
>>  EXPORT_SYMBOL_GPL(usb_charger_plug_by_gadget);
>>
>>  /*
>> + * usb_charger_unregister() - Unregister a usb charger.
>> + * @uchger - the usb charger to be unregistered.
>> + */
>> +static int usb_charger_unregister(struct usb_charger *uchger)
>> +{
>> + ida_simple_remove(_charger_ida, uchger->id);
>> + sysfs_remove_groups(>gadget->dev.kobj, usb_charger_groups);
>> +
>> + mutex_lock(_lock);
>> + list_del(>list);
>> + mutex_unlock(_lock);
>> +
>> + kfree(uchger);
>
> Any reasons you want to put kfree() here? You allocated the memo

Re: [PATCH v17 1/4] usb: gadget: Introduce the usb charger framework

2016-10-10 Thread Baolin Wang
Hi Baolu,

On 11 October 2016 at 10:59, Lu Baolu <baolu...@linux.intel.com> wrote:
> Hi Baolin,
>
> Some review comments below.
>
> On 10/10/2016 02:22 PM, Baolin Wang wrote:
>> This patch introduces the usb charger driver based on usb gadget that
>> makes an enhancement to a power driver. It works well in practice but
>> that requires a system with suitable hardware.
>>
>> The basic conception of the usb charger is that, when one usb charger
>> is added or removed by reporting from the usb gadget state change or
>> the extcon device state change, the usb charger will report to power
>> user to set the current limitation.
>>
>> The usb charger will register notifiees on the usb gadget or the extcon
>> device to get notified the usb charger state. It also supplies the
>> notification mechanism to userspace When the usb charger state is changed.
>>
>> Power user will register a notifiee on the usb charger to get notified
>> by status changes from the usb charger. It will report to power user
>> to set the current limitation when detecting the usb charger is added
>> or removed from extcon device state or usb gadget state.
>>
>> This patch doesn't yet integrate with the gadget code, so some functions
>> which rely on the 'gadget' are not completed, that will be implemented
>> in the following patches.
>>
>> Signed-off-by: Baolin Wang <baolin.w...@linaro.org>
>> Reviewed-by: Li Jun <jun...@nxp.com>
>> Tested-by: Li Jun <jun...@nxp.com>
>> ---
>>  drivers/usb/gadget/Kconfig   |8 +
>>  drivers/usb/gadget/udc/Makefile  |1 +
>>  drivers/usb/gadget/udc/charger.c |  785 
>> ++
>>  include/linux/usb/charger.h  |  186 +
>>  include/uapi/linux/usb/charger.h |   31 ++
>>  5 files changed, 1011 insertions(+)
>>  create mode 100644 drivers/usb/gadget/udc/charger.c
>>  create mode 100644 include/linux/usb/charger.h
>>  create mode 100644 include/uapi/linux/usb/charger.h
>>
>> diff --git a/drivers/usb/gadget/Kconfig b/drivers/usb/gadget/Kconfig
>> index 2ea3fc3..7520677 100644
>> --- a/drivers/usb/gadget/Kconfig
>> +++ b/drivers/usb/gadget/Kconfig
>> @@ -134,6 +134,14 @@ config U_SERIAL_CONSOLE
>>   help
>>  It supports the serial gadget can be used as a console.
>>
>> +config USB_CHARGER
>> + bool "USB charger support"
>> + select EXTCON
>> + help
>> +   The usb charger driver based on the usb gadget that makes an
>> +   enhancement to a power driver which can set the current limitation
>> +   when the usb charger is added or removed.
>> +
>>  source "drivers/usb/gadget/udc/Kconfig"
>>
>>  #
>> diff --git a/drivers/usb/gadget/udc/Makefile 
>> b/drivers/usb/gadget/udc/Makefile
>> index 98e74ed..ede2351 100644
>> --- a/drivers/usb/gadget/udc/Makefile
>> +++ b/drivers/usb/gadget/udc/Makefile
>> @@ -2,6 +2,7 @@
>>  CFLAGS_trace.o   := -I$(src)
>>
>>  udc-core-y   := core.o trace.o
>> +udc-core-$(CONFIG_USB_CHARGER)   += charger.o
>>
>>  #
>>  # USB peripheral controller drivers
>> diff --git a/drivers/usb/gadget/udc/charger.c 
>> b/drivers/usb/gadget/udc/charger.c
>> new file mode 100644
>> index 000..16dc477
>> --- /dev/null
>> +++ b/drivers/usb/gadget/udc/charger.c
>> @@ -0,0 +1,785 @@
>> +/*
>> + * charger.c -- USB charger driver
>> + *
>> + * Copyright (C) 2016 Linaro Ltd.
>> + *
>> + * This program is free software; you can redistribute it and/or modify
>> + * it under the terms of the GNU General Public License version 2 as
>> + * published by the Free Software Foundation.
>> + */
>> +
>> +#include 
>> +#include 
>> +#include 
>> +#include 
>> +#include 
>> +#include 
>> +#include 
>> +#include 
>> +#include 
>> +#include 
>> +#include 
>> +
>> +/* Default current range by charger type. */
>> +#define DEFAULT_SDP_CUR_MIN  2
>> +#define DEFAULT_SDP_CUR_MAX  500
>> +#define DEFAULT_SDP_CUR_MIN_SS   150
>> +#define DEFAULT_SDP_CUR_MAX_SS   900
>> +#define DEFAULT_DCP_CUR_MIN  500
>> +#define DEFAULT_DCP_CUR_MAX  5000
>> +#define DEFAULT_CDP_CUR_MIN  1500
>> +#define DEFAULT_CDP_CUR_MAX  5000
>> +#define DEFAULT_ACA_CUR_MIN  1500
>> +#define DEFAULT_ACA_CUR_MAX  5000
>> +
>> +static DEFINE_IDA(usb_charger_ida);
>> +static LIST_HEAD(charger_list);
>> +sta

Re: [PATCH 2/3] usb: dwc3: gadget: wait for End Transfer to complete

2016-10-16 Thread Baolin Wang
Hi Felipe,

On 14 October 2016 at 19:04, Felipe Balbi <felipe.ba...@linux.intel.com> wrote:
>
> Hi,
>
> Felipe Balbi <felipe.ba...@linux.intel.com> writes:
>> Instead of just delaying for 100us, we should
>> actually wait for End Transfer Command Complete
>> interrupt before moving on. Note that this should
>> only be done if we're dealing with one of the core
>> revisions that actually require the interrupt before
>> moving on.
>>
>> Reported-by: Baolin Wang <baolin.w...@linaro.org>
>> Signed-off-by: Felipe Balbi <felipe.ba...@linux.intel.com>
>
> I've updated this one in order to fix the comment we had about delaying
> 100us. No further changes were made, only the comment. Here it is:
>
> 8<
> From f3fa94f3171709f787a30e3c5ce69a668960b66e Mon Sep 17 00:00:00 2001
> From: Felipe Balbi <felipe.ba...@linux.intel.com>
> Date: Thu, 13 Oct 2016 14:09:47 +0300
> Subject: [PATCH v2] usb: dwc3: gadget: wait for End Transfer to complete
>
> Instead of just delaying for 100us, we should
> actually wait for End Transfer Command Complete
> interrupt before moving on. Note that this should
> only be done if we're dealing with one of the core
> revisions that actually require the interrupt before
> moving on.
>
> Reported-by: Baolin Wang <baolin.w...@linaro.org>
> Signed-off-by: Felipe Balbi <felipe.ba...@linux.intel.com>

>From my testing, there are still some problems caused by the nested
lock, at lease I found 2 functions will issue the usb_ep_disable()
function with spinlock:

1. In f_fs.c file
static void ffs_func_eps_disable(struct ffs_function *func)
{
struct ffs_ep *ep = func->eps;
struct ffs_epfile *epfile = func->ffs->epfiles;
unsigned count= func->ffs->eps_count;
unsigned long flags;

do {
if (epfile)
mutex_lock(>mutex);
spin_lock_irqsave(>ffs->eps_lock, flags);
/* pending requests get nuked */
if (likely(ep->ep))
usb_ep_disable(ep->ep);
++ep;
spin_unlock_irqrestore(>ffs->eps_lock, flags);

if (epfile) {
epfile->ep = NULL;
kfree(epfile->read_buffer);
epfile->read_buffer = NULL;
mutex_unlock(>mutex);
++epfile;
}
} while (--count);
}

2. In f_phonet.c file
static void __pn_reset(struct usb_function *f)
{
struct f_phonet *fp = func_to_pn(f);
struct net_device *dev = fp->dev;
struct phonet_port *port = netdev_priv(dev);

netif_carrier_off(dev);
port->usb = NULL;

usb_ep_disable(fp->out_ep);
usb_ep_disable(fp->in_ep);
if (fp->rx.skb) {
dev_kfree_skb_irq(fp->rx.skb);
fp->rx.skb = NULL;
}
}

static void pn_disconnect(struct usb_function *f)
{
struct f_phonet *fp = func_to_pn(f);
struct phonet_port *port = netdev_priv(fp->dev);
unsigned long flags;

/* remain disabled until set_alt */
spin_lock_irqsave(>lock, flags);
__pn_reset(f);
spin_unlock_irqrestore(>lock, flags);
}

> ---
>
> . Changes since v1:
> - Fix comment
>
>  drivers/usb/dwc3/core.h   | 10 ++-
>  drivers/usb/dwc3/gadget.c | 71 
> +++
>  2 files changed, 50 insertions(+), 31 deletions(-)
>
> diff --git a/drivers/usb/dwc3/core.h b/drivers/usb/dwc3/core.h
> index e878366ead00..2f6f7c4bc8d4 100644
> --- a/drivers/usb/dwc3/core.h
> +++ b/drivers/usb/dwc3/core.h
> @@ -26,6 +26,7 @@
>  #include 
>  #include 
>  #include 
> +#include 
>
>  #include 
>  #include 
> @@ -504,6 +505,7 @@ struct dwc3_event_buffer {
>   * @endpoint: usb endpoint
>   * @pending_list: list of pending requests for this endpoint
>   * @started_list: list of started requests on this endpoint
> + * @wait_end_transfer: wait_queue_head_t for waiting on End Transfer complete
>   * @lock: spinlock for endpoint request queue traversal
>   * @regs: pointer to first endpoint register
>   * @trb_pool: array of transaction buffers
> @@ -529,6 +531,8 @@ struct dwc3_ep {
> struct list_headpending_list;
> struct list_headstarted_list;
>
> +   wait_queue_head_t   wait_end_transfer;
> +
> spinlock_t  lock;
> void __iomem*regs;
>
> @@ -545,7 +549,8 @@ struct dwc3_ep {
>  #define DWC3_EP_BUSY   (1 << 4)
>  #define DWC3_EP_PENDING_REQUEST(1 << 5)
>  #define DWC3_EP_MISSED_ISOC(1 << 6)
> -
> +#define DWC3_EP_END_TRANSFER_PENDING (1 << 7)
> +#define DWC3_EP_KICK_POST_END_TRANSFER (1 << 8)
> /* Th

Re: [PATCH v4] usb: dwc3: Wait for control tranfer completed when stopping gadget

2016-10-17 Thread Baolin Wang
Hi,

On 17 October 2016 at 18:10, Felipe Balbi <ba...@kernel.org> wrote:
>
> Hi,
>
> Baolin Wang <baolin.w...@linaro.org> writes:
>> When we change the USB function with configfs dynamically, we possibly met 
>> this
>> situation: one core is doing the control transfer, another core is trying to
>> unregister the USB gadget from userspace, we must wait for completing this
>> control tranfer, or it will hang the controller to set the DEVCTRLHLT flag.
>>
>> Signed-off-by: Baolin Wang <baolin.w...@linaro.org>
>
> Can you make sure this still works?

With applying this patch, It can work well on my platform, but I have
some worries about the risk of accessing 'dwc->ep0state' without lock
protection in dwc3_gadget_pullup() function.

>
> 8<----
> From 797c7caab630f650b9ab5e462e8588462e055073 Mon Sep 17 00:00:00 2001
> From: Baolin Wang <baolin.w...@linaro.org>
> Date: Fri, 14 Oct 2016 17:11:33 +0800
> Subject: [PATCH] usb: dwc3: gadget: don't clear RUN/STOP when it's invalid to
>  do so
>
> When we change the USB function with configfs dynamically, we possibly
> met this situation: one core is doing the control transfer, another core
> is trying to unregister the USB gadget from userspace, we must wait for
> completing this control tranfer, or it will hang the controller to set
> the DEVCTRLHLT flag.
>
> [ felipe.ba...@linux.intel.com: several fixes to the patch
> - call complete() before starting following SETUP transfer
> - add a macro for ep0_in_setup's timeout
> - change commit subject slightly
>     - break lines at 72 characters (git adds an 8-character tab)
> - avoid changes to dwc3_gadget_run_stop() ]
>
> Signed-off-by: Baolin Wang <baolin.w...@linaro.org>
> Signed-off-by: Felipe Balbi <felipe.ba...@linux.intel.com>
> ---
>  drivers/usb/dwc3/core.h   |  3 +++
>  drivers/usb/dwc3/ep0.c|  2 ++
>  drivers/usb/dwc3/gadget.c | 17 +
>  3 files changed, 22 insertions(+)
>
> diff --git a/drivers/usb/dwc3/core.h b/drivers/usb/dwc3/core.h
> index 2f6f7c4bc8d4..80e4e9aa2d33 100644
> --- a/drivers/usb/dwc3/core.h
> +++ b/drivers/usb/dwc3/core.h
> @@ -38,6 +38,7 @@
>  #define DWC3_MSG_MAX   500
>
>  /* Global constants */
> +#define DWC3_PULL_UP_TIMEOUT   500 /* ms */
>  #define DWC3_ZLP_BUF_SIZE  1024/* size of a superspeed bulk */
>  #define DWC3_EP0_BOUNCE_SIZE   512
>  #define DWC3_ENDPOINTS_NUM 32
> @@ -756,6 +757,7 @@ struct dwc3_scratchpad_array {
>   * @ep0_usb_req: dummy req used while handling STD USB requests
>   * @ep0_bounce_addr: dma address of ep0_bounce
>   * @scratch_addr: dma address of scratchbuf
> + * @ep0_in_setup: one control transfer is completed and enter setup phase
>   * @lock: for synchronizing
>   * @dev: pointer to our struct device
>   * @xhci: pointer to our xHCI child
> @@ -853,6 +855,7 @@ struct dwc3 {
> dma_addr_t  ep0_bounce_addr;
> dma_addr_t  scratch_addr;
> struct dwc3_request ep0_usb_req;
> +   struct completion   ep0_in_setup;
>
> /* device lock */
> spinlock_t  lock;
> diff --git a/drivers/usb/dwc3/ep0.c b/drivers/usb/dwc3/ep0.c
> index 5e642d65a3b2..417cfd3f04ab 100644
> --- a/drivers/usb/dwc3/ep0.c
> +++ b/drivers/usb/dwc3/ep0.c
> @@ -284,6 +284,8 @@ void dwc3_ep0_out_start(struct dwc3 *dwc)
>  {
> int ret;
>
> +   complete(>ep0_in_setup);
> +
> ret = dwc3_ep0_start_trans(dwc, 0, dwc->ctrl_req_addr, 8,
> DWC3_TRBCTL_CONTROL_SETUP, false);
> WARN_ON(ret < 0);
> diff --git a/drivers/usb/dwc3/gadget.c b/drivers/usb/dwc3/gadget.c
> index b53712cbc499..da79716be50d 100644
> --- a/drivers/usb/dwc3/gadget.c
> +++ b/drivers/usb/dwc3/gadget.c
> @@ -1557,6 +1557,21 @@ static int dwc3_gadget_pullup(struct usb_gadget *g, 
> int is_on)
>
> is_on = !!is_on;
>
> +   /*
> +* Per databook, when we want to stop the gadget, if a control 
> transfer
> +* is still in process, complete it and get the core into setup phase.
> +*/
> +   if (!is_on && dwc->ep0state != EP0_SETUP_PHASE) {
> +   reinit_completion(>ep0_in_setup);
> +
> +   ret = wait_for_completion_timeout(>ep0_in_setup,
> +   msecs_to_jiffies(DWC3_PULL_UP_TIMEOUT));
> +   if (ret == 0) {
> +   dev_err(dwc->dev, "timed out waiting for SETUP 
> phase\n");
> +   return -ETIMEDOUT;

[PATCH] usb: gadget: f_fs: Fix possibe deadlock

2016-12-08 Thread Baolin Wang
When system try to close /dev/usb-ffs/adb/ep0 on one core, at the same
time another core try to attach new UDC, which will cause deadlock as
below scenario. Thus we should release ffs lock before issuing
unregister_gadget_item().

[   52.642225] c1 ==
[   52.642228] c1 [ INFO: possible circular locking dependency detected ]
[   52.642236] c1 4.4.6+ #1 Tainted: GW  O
[   52.642241] c1 ---
[   52.642245] c1 usb ffs open/2808 is trying to acquire lock:
[   52.642270] c0  (udc_lock){+.+.+.}, at: []
usb_gadget_unregister_driver+0x3c/0xc8
[   52.642272] c1  but task is already holding lock:
[   52.642283] c0  (ffs_lock){+.+.+.}, at: []
ffs_data_clear+0x30/0x140
[   52.642285] c1 which lock already depends on the new lock.
[   52.642287] c1
   the existing dependency chain (in reverse order) is:
[   52.642295] c0
   -> #1 (ffs_lock){+.+.+.}:
[   52.642307] c0[] __lock_acquire+0x20f0/0x2238
[   52.642314] c0[] lock_acquire+0xe4/0x298
[   52.642322] c0[] mutex_lock_nested+0x7c/0x3cc
[   52.642328] c0[] ffs_func_bind+0x504/0x6e8
[   52.642334] c0[] usb_add_function+0x84/0x184
[   52.642340] c0[] 
configfs_composite_bind+0x264/0x39c
[   52.642346] c0[] udc_bind_to_driver+0x58/0x11c
[   52.642352] c0[] usb_udc_attach_driver+0x90/0xc8
[   52.642358] c0[] 
gadget_dev_desc_UDC_store+0xd4/0x128
[   52.642369] c0[] configfs_write_file+0xd0/0x13c
[   52.642376] c0[] vfs_write+0xb8/0x214
[   52.642381] c0[] SyS_write+0x54/0xb0
[   52.642388] c0[] el0_svc_naked+0x24/0x28
[   52.642395] c0
  -> #0 (udc_lock){+.+.+.}:
[   52.642401] c0[] print_circular_bug+0x84/0x2e4
[   52.642407] c0[] __lock_acquire+0x2138/0x2238
[   52.642412] c0[] lock_acquire+0xe4/0x298
[   52.642420] c0[] mutex_lock_nested+0x7c/0x3cc
[   52.642427] c0[] 
usb_gadget_unregister_driver+0x3c/0xc8
[   52.642432] c0[] unregister_gadget_item+0x28/0x44
[   52.642439] c0[] ffs_data_clear+0x138/0x140
[   52.642444] c0[] ffs_data_reset+0x20/0x6c
[   52.642450] c0[] ffs_data_closed+0xac/0x12c
[   52.642454] c0[] ffs_ep0_release+0x20/0x2c
[   52.642460] c0[] __fput+0xb0/0x1f4
[   52.642466] c0[] fput+0x20/0x2c
[   52.642473] c0[] task_work_run+0xb4/0xe8
[   52.642482] c0[] do_exit+0x360/0xb9c
[   52.642487] c0[] do_group_exit+0x4c/0xb0
[   52.642494] c0[] get_signal+0x380/0x89c
[   52.642501] c0[] do_signal+0x154/0x518
[   52.642507] c0[] do_notify_resume+0x70/0x78
[   52.642512] c0[] work_pending+0x1c/0x20
[   52.642514] c1
  other info that might help us debug this:
[   52.642517] c1  Possible unsafe locking scenario:
[   52.642518] c1CPU0CPU1
[   52.642520] c1
[   52.642525] c0   lock(ffs_lock);
[   52.642529] c0lock(udc_lock);
[   52.642533] c0lock(ffs_lock);
[   52.642537] c0   lock(udc_lock);
[   52.642539] c1
  *** DEADLOCK ***
[   52.642543] c1 1 lock held by usb ffs open/2808:
[   52.642555] c0  #0:  (ffs_lock){+.+.+.}, at: []
ffs_data_clear+0x30/0x140
[   52.642557] c1 stack backtrace:
[   52.642563] c1 CPU: 1 PID: 2808 Comm: usb ffs open Tainted: G
[   52.642565] c1 Hardware name: Spreadtrum SP9860g Board (DT)
[   52.642568] c1 Call trace:
[   52.642573] c1 [] dump_backtrace+0x0/0x170
[   52.642577] c1 [] show_stack+0x20/0x28
[   52.642583] c1 [] dump_stack+0xa8/0xe0
[   52.642587] c1 [] print_circular_bug+0x1fc/0x2e4
[   52.642591] c1 [] __lock_acquire+0x2138/0x2238
[   52.642595] c1 [] lock_acquire+0xe4/0x298
[   52.642599] c1 [] mutex_lock_nested+0x7c/0x3cc
[   52.642604] c1 [] usb_gadget_unregister_driver+0x3c/0xc8
[   52.642608] c1 [] unregister_gadget_item+0x28/0x44
[   52.642613] c1 [] ffs_data_clear+0x138/0x140
[   52.642618] c1 [] ffs_data_reset+0x20/0x6c
[   52.642621] c1 [] ffs_data_closed+0xac/0x12c
[   52.642625] c1 [] ffs_ep0_release+0x20/0x2c
[   52.642629] c1 [] __fput+0xb0/0x1f4
[   52.642633] c1 [] fput+0x20/0x2c
[   52.642636] c1 [] task_work_run+0xb4/0xe8
[   52.642640] c1 [] do_exit+0x360/0xb9c
[   52.642644] c1 [] do_group_exit+0x4c/0xb0
[   52.642647] c1 [] get_signal+0x380/0x89c
[   52.642651] c1 [] do_signal+0x154/0x518
[   52.642656] c1 [] do_notify_resume+0x70/0x78
[   52.642659] c1 [] work_pending+0x1c/0x20

Signed-off-by: Baolin Wang <baolin.w...@linaro.org>
---
 drivers/usb/gadget/function/f_fs.c |8 ++--
 1 file changed, 6 insertions(+), 2 deletions(-)

diff --git a/drivers/usb/gadget/function/f_fs.c 
b/drivers/usb/gadget/function/f_fs.c
index 0780d83..93de3b9 100644
--- a/drivers/usb/gadget/fun

Re: [PATCH v4 1/2] usb: host: plat: Enable xhci plat runtime PM

2016-12-07 Thread Baolin Wang
Hi Mathias and Felipe,

On 28 November 2016 at 14:43, Baolin Wang <baolin.w...@linaro.org> wrote:
> Enable the xhci plat runtime PM for parent device to suspend/resume xhci.
> Also call pm_runtime_get_noresume() in probe() function in case the parent
> device doesn't call suspend/resume callback by runtime PM now.
>
> Signed-off-by: Baolin Wang <baolin.w...@linaro.org>
> ---
> Changes since v3:
>  - Fix kbuild error.
>
> Changes since v2:
>  - Add pm_runtime_get_noresume() in probe() function.
>  - Add pm_runtime_set_suspended()/pm_runtime_put_noidle() in remove() 
> function.
>
> Changes since v1:
>  - No updates.
> ---
>  drivers/usb/host/xhci-plat.c |   41 -
>  1 file changed, 36 insertions(+), 5 deletions(-)
>
> diff --git a/drivers/usb/host/xhci-plat.c b/drivers/usb/host/xhci-plat.c
> index ed56bf9..5805c6a 100644
> --- a/drivers/usb/host/xhci-plat.c
> +++ b/drivers/usb/host/xhci-plat.c
> @@ -246,6 +246,10 @@ static int xhci_plat_probe(struct platform_device *pdev)
> if (ret)
> goto dealloc_usb2_hcd;
>
> +   pm_runtime_get_noresume(>dev);
> +   pm_runtime_set_active(>dev);
> +   pm_runtime_enable(>dev);
> +
> return 0;
>
>
> @@ -274,6 +278,10 @@ static int xhci_plat_remove(struct platform_device *dev)
> struct xhci_hcd *xhci = hcd_to_xhci(hcd);
> struct clk *clk = xhci->clk;
>
> +   pm_runtime_set_suspended(>dev);
> +   pm_runtime_put_noidle(>dev);
> +   pm_runtime_disable(>dev);
> +
> usb_remove_hcd(xhci->shared_hcd);
> usb_phy_shutdown(hcd->usb_phy);
>
> @@ -311,14 +319,37 @@ static int xhci_plat_resume(struct device *dev)
>
> return xhci_resume(xhci, 0);
>  }
> +#endif /* CONFIG_PM_SLEEP */
> +
> +#ifdef CONFIG_PM
> +static int xhci_plat_runtime_suspend(struct device *dev)
> +{
> +   struct usb_hcd  *hcd = dev_get_drvdata(dev);
> +   struct xhci_hcd *xhci = hcd_to_xhci(hcd);
> +
> +   return xhci_suspend(xhci, device_may_wakeup(dev));
> +}
> +
> +static int xhci_plat_runtime_resume(struct device *dev)
> +{
> +   struct usb_hcd  *hcd = dev_get_drvdata(dev);
> +   struct xhci_hcd *xhci = hcd_to_xhci(hcd);
> +
> +   return xhci_resume(xhci, 0);
> +}
> +
> +static int xhci_plat_runtime_idle(struct device *dev)
> +{
> +   return 0;
> +}
> +#endif /* CONFIG_PM */
>
>  static const struct dev_pm_ops xhci_plat_pm_ops = {
> SET_SYSTEM_SLEEP_PM_OPS(xhci_plat_suspend, xhci_plat_resume)
> +
> +   SET_RUNTIME_PM_OPS(xhci_plat_runtime_suspend, 
> xhci_plat_runtime_resume,
> +  xhci_plat_runtime_idle)
>  };
> -#define DEV_PM_OPS (_plat_pm_ops)
> -#else
> -#define DEV_PM_OPS NULL
> -#endif /* CONFIG_PM */
>
>  static const struct acpi_device_id usb_xhci_acpi_match[] = {
> /* XHCI-compliant USB Controller */
> @@ -332,7 +363,7 @@ static int xhci_plat_resume(struct device *dev)
> .remove = xhci_plat_remove,
> .driver = {
> .name = "xhci-hcd",
> -   .pm = DEV_PM_OPS,
> +   .pm = _plat_pm_ops,
> .of_match_table = of_match_ptr(usb_xhci_of_match),
> .acpi_match_table = ACPI_PTR(usb_xhci_acpi_match),
> },
> --
> 1.7.9.5
>

Do you have any comments about this patch? Thanks.

-- 
Baolin.wang
Best Regards
--
To unsubscribe from this list: send the line "unsubscribe linux-usb" in
the body of a message to majord...@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html


Re: [PATCH v4 2/2] usb: dwc3: core: Support the dwc3 host suspend/resume

2016-12-08 Thread Baolin Wang
Hi,

On 8 December 2016 at 19:02, Felipe Balbi <ba...@kernel.org> wrote:
>
> Hi,
>
> Baolin Wang <baolin.w...@linaro.org> writes:
>>>> On 28 November 2016 at 14:43, Baolin Wang <baolin.w...@linaro.org> wrote:
>>>>> For some mobile devices with strict power management, we also want to 
>>>>> suspend
>>>>> the host when the slave is detached for power saving. Thus we add the host
>>>>> suspend/resume functions to support this requirement.
>>>>>
>>>>> Signed-off-by: Baolin Wang <baolin.w...@linaro.org>
>>>>> ---
>>>>> Changes since v3:
>>>>>  - No updates.
>>>>>
>>>>> Changes since v2:
>>>>>  - Remove pm_children_suspended() and other unused macros.
>>>>>
>>>>>  Changes since v1:
>>>>>- Add pm_runtime.h head file to avoid kbuild error.
>>>>> ---
>>>>>  drivers/usb/dwc3/Kconfig |7 +++
>>>>>  drivers/usb/dwc3/core.c  |   26 +-
>>>>>  drivers/usb/dwc3/core.h  |   15 +++
>>>>>  drivers/usb/dwc3/host.c  |   37 +
>>>>>  4 files changed, 84 insertions(+), 1 deletion(-)
>>>>>
>>>>> diff --git a/drivers/usb/dwc3/Kconfig b/drivers/usb/dwc3/Kconfig
>>>>> index a45b4f1..47bb2f3 100644
>>>>> --- a/drivers/usb/dwc3/Kconfig
>>>>> +++ b/drivers/usb/dwc3/Kconfig
>>>>> @@ -47,6 +47,13 @@ config USB_DWC3_DUAL_ROLE
>>>>>
>>>>>  endchoice
>>>>>
>>>>> +config USB_DWC3_HOST_SUSPEND
>>>>> +   bool "Choose if the DWC3 host (xhci) can be suspend/resume"
>>>>> +   depends on USB_DWC3_HOST=y || USB_DWC3_DUAL_ROLE=y
>>>
>>> why do you need another Kconfig for this? Just enable it already :-p
>>
>> I assume some platforms may do not need this feature. But okay, I can
>> remove this kconfig and enable it.
>
> thanks :-)
>
>>>>> diff --git a/drivers/usb/dwc3/core.c b/drivers/usb/dwc3/core.c
>>>>> index 9a4a5e4..7ad4bc3 100644
>>>>> --- a/drivers/usb/dwc3/core.c
>>>>> +++ b/drivers/usb/dwc3/core.c
>>>>> @@ -1091,6 +1091,7 @@ static int dwc3_probe(struct platform_device *pdev)
>>>>> pm_runtime_use_autosuspend(dev);
>>>>> pm_runtime_set_autosuspend_delay(dev, 
>>>>> DWC3_DEFAULT_AUTOSUSPEND_DELAY);
>>>>> pm_runtime_enable(dev);
>>>>> +   pm_suspend_ignore_children(dev, true);
>>>
>>> why do you need this?
>>
>> Since the dwc3 device is the parent deive of xhci device, if we want
>> to suspend dwc3 device, we need to suspend child device (xhci device)
>> manually by issuing pm_runtime_put_sync() in dwc3_host_suspend(). In
>> pm_runtime_put_sync(), it will check if the children (xhci device) of
>> dwc3 device have been in suspend state, if not we will suspend dwc3
>> device failed.
>>
>> We get/put the child device manually in parent device's runtime
>> callback, we need to ignore the child device's runtime state, or it
>> will failed due to the dependency.
>
> I see. Good explanation :-)
>
> There's one thing though, if you want to runtime suspend the gadget and
> dwc3 is working on peripheral mode, host side (XHCI) should already be
> runtime suspended because there's nothing attached to it. Why isn't it
> runtime suspended?

Since we have get the runtime count for xHCI device in
xhci_plat_probe(), in case it will suspend automatically if some
controllers do not want xHCI enters runtime suspend automatically. So
the parent device (dwc3 device) need to get/put the xHCI device's
runtime count  to resume/suspend xHCI.

-- 
Baolin.wang
Best Regards
--
To unsubscribe from this list: send the line "unsubscribe linux-usb" in
the body of a message to majord...@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html


Re: [PATCH v4 2/2] usb: dwc3: core: Support the dwc3 host suspend/resume

2016-12-07 Thread Baolin Wang
Hi Felipe,

On 28 November 2016 at 14:43, Baolin Wang <baolin.w...@linaro.org> wrote:
> For some mobile devices with strict power management, we also want to suspend
> the host when the slave is detached for power saving. Thus we add the host
> suspend/resume functions to support this requirement.
>
> Signed-off-by: Baolin Wang <baolin.w...@linaro.org>
> ---
> Changes since v3:
>  - No updates.
>
> Changes since v2:
>  - Remove pm_children_suspended() and other unused macros.
>
>  Changes since v1:
>- Add pm_runtime.h head file to avoid kbuild error.
> ---
>  drivers/usb/dwc3/Kconfig |7 +++
>  drivers/usb/dwc3/core.c  |   26 +-
>  drivers/usb/dwc3/core.h  |   15 +++
>  drivers/usb/dwc3/host.c  |   37 +
>  4 files changed, 84 insertions(+), 1 deletion(-)
>
> diff --git a/drivers/usb/dwc3/Kconfig b/drivers/usb/dwc3/Kconfig
> index a45b4f1..47bb2f3 100644
> --- a/drivers/usb/dwc3/Kconfig
> +++ b/drivers/usb/dwc3/Kconfig
> @@ -47,6 +47,13 @@ config USB_DWC3_DUAL_ROLE
>
>  endchoice
>
> +config USB_DWC3_HOST_SUSPEND
> +   bool "Choose if the DWC3 host (xhci) can be suspend/resume"
> +   depends on USB_DWC3_HOST=y || USB_DWC3_DUAL_ROLE=y
> +   help
> + We can suspend the host when the slave is detached for power saving,
> + and resume the host when one slave is attached.
> +
>  comment "Platform Glue Driver Support"
>
>  config USB_DWC3_OMAP
> diff --git a/drivers/usb/dwc3/core.c b/drivers/usb/dwc3/core.c
> index 9a4a5e4..7ad4bc3 100644
> --- a/drivers/usb/dwc3/core.c
> +++ b/drivers/usb/dwc3/core.c
> @@ -1091,6 +1091,7 @@ static int dwc3_probe(struct platform_device *pdev)
> pm_runtime_use_autosuspend(dev);
> pm_runtime_set_autosuspend_delay(dev, DWC3_DEFAULT_AUTOSUSPEND_DELAY);
> pm_runtime_enable(dev);
> +   pm_suspend_ignore_children(dev, true);
> ret = pm_runtime_get_sync(dev);
> if (ret < 0)
> goto err1;
> @@ -1215,15 +1216,27 @@ static int dwc3_remove(struct platform_device *pdev)
>  static int dwc3_suspend_common(struct dwc3 *dwc)
>  {
> unsigned long   flags;
> +   int ret;
>
> switch (dwc->dr_mode) {
> case USB_DR_MODE_PERIPHERAL:
> +   spin_lock_irqsave(>lock, flags);
> +   dwc3_gadget_suspend(dwc);
> +   spin_unlock_irqrestore(>lock, flags);
> +   break;
> case USB_DR_MODE_OTG:
> +   ret = dwc3_host_suspend(dwc);
> +   if (ret)
> +   return ret;
> +
> spin_lock_irqsave(>lock, flags);
> dwc3_gadget_suspend(dwc);
> spin_unlock_irqrestore(>lock, flags);
> break;
> case USB_DR_MODE_HOST:
> +   ret = dwc3_host_suspend(dwc);
> +   if (ret)
> +   return ret;
> default:
> /* do nothing */
> break;
> @@ -1245,12 +1258,23 @@ static int dwc3_resume_common(struct dwc3 *dwc)
>
> switch (dwc->dr_mode) {
> case USB_DR_MODE_PERIPHERAL:
> +   spin_lock_irqsave(>lock, flags);
> +   dwc3_gadget_resume(dwc);
> +   spin_unlock_irqrestore(>lock, flags);
> +   break;
> case USB_DR_MODE_OTG:
> +   ret = dwc3_host_resume(dwc);
> +   if (ret)
> +   return ret;
> +
> spin_lock_irqsave(>lock, flags);
> dwc3_gadget_resume(dwc);
> spin_unlock_irqrestore(>lock, flags);
> -   /* FALLTHROUGH */
> +   break;
> case USB_DR_MODE_HOST:
> +   ret = dwc3_host_resume(dwc);
> +   if (ret)
> +   return ret;
> default:
> /* do nothing */
> break;
> diff --git a/drivers/usb/dwc3/core.h b/drivers/usb/dwc3/core.h
> index b585a30..db41908 100644
> --- a/drivers/usb/dwc3/core.h
> +++ b/drivers/usb/dwc3/core.h
> @@ -1226,4 +1226,19 @@ static inline void dwc3_ulpi_exit(struct dwc3 *dwc)
>  { }
>  #endif
>
> +#if IS_ENABLED(CONFIG_USB_DWC3_HOST_SUSPEND)
> +int dwc3_host_suspend(struct dwc3 *dwc);
> +int dwc3_host_resume(struct dwc3 *dwc);
> +#else
> +static inline int dwc3_host_suspend(struct dwc3 *dwc)
> +{
> +   return 0;
> +}
> +
> +static inline int dwc3_host_resume(struct dwc3 *dwc)
> +{
> +   return 0;
> +}
> +#endif
> +
>  #endif /* _

Re: [PATCH v4 2/2] usb: dwc3: core: Support the dwc3 host suspend/resume

2016-12-08 Thread Baolin Wang
Hi,

On 8 December 2016 at 17:40, Felipe Balbi <ba...@kernel.org> wrote:
>
> Hi,
>
> Baolin Wang <baolin.w...@linaro.org> writes:
>> Hi Felipe,
>>
>> On 28 November 2016 at 14:43, Baolin Wang <baolin.w...@linaro.org> wrote:
>>> For some mobile devices with strict power management, we also want to 
>>> suspend
>>> the host when the slave is detached for power saving. Thus we add the host
>>> suspend/resume functions to support this requirement.
>>>
>>> Signed-off-by: Baolin Wang <baolin.w...@linaro.org>
>>> ---
>>> Changes since v3:
>>>  - No updates.
>>>
>>> Changes since v2:
>>>  - Remove pm_children_suspended() and other unused macros.
>>>
>>>  Changes since v1:
>>>- Add pm_runtime.h head file to avoid kbuild error.
>>> ---
>>>  drivers/usb/dwc3/Kconfig |7 +++
>>>  drivers/usb/dwc3/core.c  |   26 +-
>>>  drivers/usb/dwc3/core.h  |   15 +++
>>>  drivers/usb/dwc3/host.c  |   37 +
>>>  4 files changed, 84 insertions(+), 1 deletion(-)
>>>
>>> diff --git a/drivers/usb/dwc3/Kconfig b/drivers/usb/dwc3/Kconfig
>>> index a45b4f1..47bb2f3 100644
>>> --- a/drivers/usb/dwc3/Kconfig
>>> +++ b/drivers/usb/dwc3/Kconfig
>>> @@ -47,6 +47,13 @@ config USB_DWC3_DUAL_ROLE
>>>
>>>  endchoice
>>>
>>> +config USB_DWC3_HOST_SUSPEND
>>> +   bool "Choose if the DWC3 host (xhci) can be suspend/resume"
>>> +   depends on USB_DWC3_HOST=y || USB_DWC3_DUAL_ROLE=y
>
> why do you need another Kconfig for this? Just enable it already :-p

I assume some platforms may do not need this feature. But okay, I can
remove this kconfig and enable it.

>
>>> diff --git a/drivers/usb/dwc3/core.c b/drivers/usb/dwc3/core.c
>>> index 9a4a5e4..7ad4bc3 100644
>>> --- a/drivers/usb/dwc3/core.c
>>> +++ b/drivers/usb/dwc3/core.c
>>> @@ -1091,6 +1091,7 @@ static int dwc3_probe(struct platform_device *pdev)
>>> pm_runtime_use_autosuspend(dev);
>>> pm_runtime_set_autosuspend_delay(dev, 
>>> DWC3_DEFAULT_AUTOSUSPEND_DELAY);
>>> pm_runtime_enable(dev);
>>> +   pm_suspend_ignore_children(dev, true);
>
> why do you need this?

Since the dwc3 device is the parent deive of xhci device, if we want
to suspend dwc3 device, we need to suspend child device (xhci device)
manually by issuing pm_runtime_put_sync() in dwc3_host_suspend(). In
pm_runtime_put_sync(), it will check if the children (xhci device) of
dwc3 device have been in suspend state, if not we will suspend dwc3
device failed.

We get/put the child device manually in parent device's runtime
callback, we need to ignore the child device's runtime state, or it
will failed due to the dependency.

>
>>> @@ -1215,15 +1216,27 @@ static int dwc3_remove(struct platform_device *pdev)
>>>  static int dwc3_suspend_common(struct dwc3 *dwc)
>>>  {
>>> unsigned long   flags;
>>> +   int ret;
>>>
>>> switch (dwc->dr_mode) {
>>> case USB_DR_MODE_PERIPHERAL:
>>> +   spin_lock_irqsave(>lock, flags);
>>> +   dwc3_gadget_suspend(dwc);
>>> +   spin_unlock_irqrestore(>lock, flags);
>>> +   break;
>>> case USB_DR_MODE_OTG:
>>> +   ret = dwc3_host_suspend(dwc);
>>> +   if (ret)
>>> +   return ret;
>>> +
>>> spin_lock_irqsave(>lock, flags);
>>> dwc3_gadget_suspend(dwc);
>>> spin_unlock_irqrestore(>lock, flags);
>>> break;
>>> case USB_DR_MODE_HOST:
>>> +   ret = dwc3_host_suspend(dwc);
>>> +   if (ret)
>>> +   return ret;
>>> default:
>>> /* do nothing */
>>> break;
>>> @@ -1245,12 +1258,23 @@ static int dwc3_resume_common(struct dwc3 *dwc)
>>>
>>> switch (dwc->dr_mode) {
>>> case USB_DR_MODE_PERIPHERAL:
>>> +   spin_lock_irqsave(>lock, flags);
>>> +   dwc3_gadget_resume(dwc);
>>> +   spin_unlock_irqrestore(>lock, flags);
>>> +   break;
>>> case USB_DR_MODE_OTG:
>>> +   ret = dwc3_host_resume(dwc);
>>> +  

[PATCH v5 2/2] usb: dwc3: core: Support the dwc3 host suspend/resume

2016-12-12 Thread Baolin Wang
For some mobile devices with strict power management, we also want to suspend
the host when the slave is detached for power saving. Thus we add the host
suspend/resume functions to support this requirement.

Signed-off-by: Baolin Wang <baolin.w...@linaro.org>
---
Changes since v4:
 - Remove Kconfig and just enable host suspend/resume.
 - Simplify the dwc3_host_suspend/resume() function.

Changes since v3:
 - No updates.

Changes since v2:
 - Remove pm_children_suspended() and other unused macros.

Changes since v1:
 - Add pm_runtime.h head file to avoid kbuild error.
---
 drivers/usb/dwc3/core.c |   26 +-
 drivers/usb/dwc3/core.h |7 +++
 drivers/usb/dwc3/host.c |   21 +
 3 files changed, 53 insertions(+), 1 deletion(-)

diff --git a/drivers/usb/dwc3/core.c b/drivers/usb/dwc3/core.c
index 9a4a5e4..7ad4bc3 100644
--- a/drivers/usb/dwc3/core.c
+++ b/drivers/usb/dwc3/core.c
@@ -1091,6 +1091,7 @@ static int dwc3_probe(struct platform_device *pdev)
pm_runtime_use_autosuspend(dev);
pm_runtime_set_autosuspend_delay(dev, DWC3_DEFAULT_AUTOSUSPEND_DELAY);
pm_runtime_enable(dev);
+   pm_suspend_ignore_children(dev, true);
ret = pm_runtime_get_sync(dev);
if (ret < 0)
goto err1;
@@ -1215,15 +1216,27 @@ static int dwc3_remove(struct platform_device *pdev)
 static int dwc3_suspend_common(struct dwc3 *dwc)
 {
unsigned long   flags;
+   int ret;
 
switch (dwc->dr_mode) {
case USB_DR_MODE_PERIPHERAL:
+   spin_lock_irqsave(>lock, flags);
+   dwc3_gadget_suspend(dwc);
+   spin_unlock_irqrestore(>lock, flags);
+   break;
case USB_DR_MODE_OTG:
+   ret = dwc3_host_suspend(dwc);
+   if (ret)
+   return ret;
+
spin_lock_irqsave(>lock, flags);
dwc3_gadget_suspend(dwc);
spin_unlock_irqrestore(>lock, flags);
break;
case USB_DR_MODE_HOST:
+   ret = dwc3_host_suspend(dwc);
+   if (ret)
+   return ret;
default:
/* do nothing */
break;
@@ -1245,12 +1258,23 @@ static int dwc3_resume_common(struct dwc3 *dwc)
 
switch (dwc->dr_mode) {
case USB_DR_MODE_PERIPHERAL:
+   spin_lock_irqsave(>lock, flags);
+   dwc3_gadget_resume(dwc);
+   spin_unlock_irqrestore(>lock, flags);
+   break;
case USB_DR_MODE_OTG:
+   ret = dwc3_host_resume(dwc);
+   if (ret)
+   return ret;
+
spin_lock_irqsave(>lock, flags);
dwc3_gadget_resume(dwc);
spin_unlock_irqrestore(>lock, flags);
-   /* FALLTHROUGH */
+   break;
case USB_DR_MODE_HOST:
+   ret = dwc3_host_resume(dwc);
+   if (ret)
+   return ret;
default:
/* do nothing */
break;
diff --git a/drivers/usb/dwc3/core.h b/drivers/usb/dwc3/core.h
index b585a30..1099168 100644
--- a/drivers/usb/dwc3/core.h
+++ b/drivers/usb/dwc3/core.h
@@ -1158,11 +1158,18 @@ static inline bool dwc3_is_usb31(struct dwc3 *dwc)
 #if IS_ENABLED(CONFIG_USB_DWC3_HOST) || IS_ENABLED(CONFIG_USB_DWC3_DUAL_ROLE)
 int dwc3_host_init(struct dwc3 *dwc);
 void dwc3_host_exit(struct dwc3 *dwc);
+int dwc3_host_suspend(struct dwc3 *dwc);
+int dwc3_host_resume(struct dwc3 *dwc);
 #else
 static inline int dwc3_host_init(struct dwc3 *dwc)
 { return 0; }
 static inline void dwc3_host_exit(struct dwc3 *dwc)
 { }
+
+static inline int dwc3_host_suspend(struct dwc3 *dwc)
+{ return 0; }
+static inline int dwc3_host_resume(struct dwc3 *dwc)
+{ return 0; }
 #endif
 
 #if IS_ENABLED(CONFIG_USB_DWC3_GADGET) || IS_ENABLED(CONFIG_USB_DWC3_DUAL_ROLE)
diff --git a/drivers/usb/dwc3/host.c b/drivers/usb/dwc3/host.c
index ed82464..7959ef0 100644
--- a/drivers/usb/dwc3/host.c
+++ b/drivers/usb/dwc3/host.c
@@ -16,6 +16,7 @@
  */
 
 #include 
+#include 
 
 #include "core.h"
 
@@ -130,3 +131,23 @@ void dwc3_host_exit(struct dwc3 *dwc)
  dev_name(>xhci->dev));
platform_device_unregister(dwc->xhci);
 }
+
+int dwc3_host_suspend(struct dwc3 *dwc)
+{
+   struct device *xhci = >xhci->dev;
+
+   /*
+* Note: if we get the -EBUSY, which means the xHCI children devices are
+* not in suspend state yet, the glue layer need to wait for a while and
+* try to suspend xHCI device again.
+*/
+   return pm_runtime_put_sync(xhci);
+}
+
+int dwc3_host_resume(struct dwc3 *dwc)
+{
+   struct device *xhci = >xhci->dev;
+
+   /* Resume the xHCI device synchronously. */
+   return pm_runtime_get_sync(xhci);
+}
-- 
1.7.9.5

--
To unsubscribe from this list: se

[PATCH v5 1/2] usb: host: plat: Enable xhci plat runtime PM

2016-12-12 Thread Baolin Wang
Enable the xhci plat runtime PM for parent device to suspend/resume xhci.
Also call pm_runtime_get_noresume() in probe() function in case the parent
device doesn't call suspend/resume callback by runtime PM now.

Signed-off-by: Baolin Wang <baolin.w...@linaro.org>
---
Changes since v4:
 - No updates.

Changes since v3:
 - Fix kbuild error.

Changes since v2:
 - Add pm_runtime_get_noresume() in probe() function.
 - Add pm_runtime_set_suspended()/pm_runtime_put_noidle() in remove() function.

Changes since v1:
 - No updates.
---
 drivers/usb/host/xhci-plat.c |   41 -
 1 file changed, 36 insertions(+), 5 deletions(-)

diff --git a/drivers/usb/host/xhci-plat.c b/drivers/usb/host/xhci-plat.c
index ed56bf9..5805c6a 100644
--- a/drivers/usb/host/xhci-plat.c
+++ b/drivers/usb/host/xhci-plat.c
@@ -246,6 +246,10 @@ static int xhci_plat_probe(struct platform_device *pdev)
if (ret)
goto dealloc_usb2_hcd;
 
+   pm_runtime_get_noresume(>dev);
+   pm_runtime_set_active(>dev);
+   pm_runtime_enable(>dev);
+
return 0;
 
 
@@ -274,6 +278,10 @@ static int xhci_plat_remove(struct platform_device *dev)
struct xhci_hcd *xhci = hcd_to_xhci(hcd);
struct clk *clk = xhci->clk;
 
+   pm_runtime_set_suspended(>dev);
+   pm_runtime_put_noidle(>dev);
+   pm_runtime_disable(>dev);
+
usb_remove_hcd(xhci->shared_hcd);
usb_phy_shutdown(hcd->usb_phy);
 
@@ -311,14 +319,37 @@ static int xhci_plat_resume(struct device *dev)
 
return xhci_resume(xhci, 0);
 }
+#endif /* CONFIG_PM_SLEEP */
+
+#ifdef CONFIG_PM
+static int xhci_plat_runtime_suspend(struct device *dev)
+{
+   struct usb_hcd  *hcd = dev_get_drvdata(dev);
+   struct xhci_hcd *xhci = hcd_to_xhci(hcd);
+
+   return xhci_suspend(xhci, device_may_wakeup(dev));
+}
+
+static int xhci_plat_runtime_resume(struct device *dev)
+{
+   struct usb_hcd  *hcd = dev_get_drvdata(dev);
+   struct xhci_hcd *xhci = hcd_to_xhci(hcd);
+
+   return xhci_resume(xhci, 0);
+}
+
+static int xhci_plat_runtime_idle(struct device *dev)
+{
+   return 0;
+}
+#endif /* CONFIG_PM */
 
 static const struct dev_pm_ops xhci_plat_pm_ops = {
SET_SYSTEM_SLEEP_PM_OPS(xhci_plat_suspend, xhci_plat_resume)
+
+   SET_RUNTIME_PM_OPS(xhci_plat_runtime_suspend, xhci_plat_runtime_resume,
+  xhci_plat_runtime_idle)
 };
-#define DEV_PM_OPS (_plat_pm_ops)
-#else
-#define DEV_PM_OPS NULL
-#endif /* CONFIG_PM */
 
 static const struct acpi_device_id usb_xhci_acpi_match[] = {
/* XHCI-compliant USB Controller */
@@ -332,7 +363,7 @@ static int xhci_plat_resume(struct device *dev)
.remove = xhci_plat_remove,
.driver = {
.name = "xhci-hcd",
-   .pm = DEV_PM_OPS,
+   .pm = _plat_pm_ops,
.of_match_table = of_match_ptr(usb_xhci_of_match),
.acpi_match_table = ACPI_PTR(usb_xhci_acpi_match),
},
-- 
1.7.9.5

--
To unsubscribe from this list: send the line "unsubscribe linux-usb" in
the body of a message to majord...@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html


Re: [PATCH 2/2] usb: host: xhci: Handle the right timeout command

2016-12-12 Thread Baolin Wang
Hi Mathias,

On 12 December 2016 at 23:52, Mathias Nyman
<mathias.ny...@linux.intel.com> wrote:
> On 05.12.2016 09:51, Baolin Wang wrote:
>>
>> If a command event is found on the event ring during an interrupt,
>> we need to stop the command timer with del_timer(). Since del_timer()
>> can fail if the timer is running and waiting on the xHCI lock, then
>> it maybe get the wrong timeout command in xhci_handle_command_timeout()
>> if host fetched a new command and updated the xhci->current_cmd in
>> handle_cmd_completion(). For this situation, we need a way to signal
>> to the command timer that everything is fine and it should exit.
>
>
> Ah, right, this could actually happen.
>
>>
>>
>> We should introduce a counter (xhci->current_cmd_pending) for the number
>> of pending commands. If we need to cancel the command timer and
>> del_timer()
>> succeeds, we decrement the number of pending commands. If del_timer()
>> fails,
>> we leave the number of pending commands alone.
>>
>> For handling timeout command, in xhci_handle_command_timeout() we will
>> check
>> the counter after decrementing it, if the counter
>> (xhci->current_cmd_pending)
>> is 0, which means xhci->current_cmd is the right timeout command. If the
>> counter (xhci->current_cmd_pending) is greater than 0, which means current
>> timeout command has been handled by host and host has fetched new command
>> as
>> xhci->current_cmd, then just return and wait for new current command.
>
>
> A counter like this could work.
>
> Writing the abort bit can generate either ABORT+STOP, or just STOP
> event, this seems to cover both.
>
> quick check, case 1: timeout and cmd completion at the same time.
>
> cpu1cpu2
>
> queue_command(first), p++ (=1)
> queue_command(more),
> --completion irq fires---- timer times out at same time--
> handle_cmd_completion() handle_cmd_timeout(),)
> lock(xhci_lock  )   spin_on(xhci_lock)
> del_timer() fail, p (=1, nochange)
> cur_cmd = list_next(), p++ (=2)
> unlock(xhci_lock)
> lock(xhci_lock)
> p-- (=1)
> if (p > 0), exit
> OK works
>
> case 2: normal timeout case with ABORT+STOP, no race.
>
> cpu1cpu2
>
> queue_command(first), p++ (=1)
> queue_command(more),
> handle_cmd_timeout()
> p-- (P=0), don't exit
> mod_timer(), p++ (P=1)
> write_abort_bit()
> handle_cmd_comletion(ABORT)
> del_timer(), ok, p-- (p = 0)
> handle_cmd_completion(STOP)
> del_timer(), fail, (P=0)
> handle_stopped_cmd_ring()
> cur_cmd = list_next(), p++ (=1)
> mod_timer()
>
> OK, works, and same for just STOP case, with the only difference that
> during handle_cmd_completion(STOP) p is decremented (p--)

Yes, that's the cases what I want to handle, thanks for your explicit
explanation.

>
> So unless there is a way to find out if cur_cmd is valid in command timeout
> in command timeout with the help of existing flags and lists this would be a
> working
> solution.
>
> -Mathias
>



-- 
Baolin.wang
Best Regards
--
To unsubscribe from this list: send the line "unsubscribe linux-usb" in
the body of a message to majord...@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html


[PATCH] usb: host: xhci: Clean up commands when stop endpoint command is timeout

2016-12-13 Thread Baolin Wang
Since the stop endpoint command is timeout, we will halt the xHCI
controller and issuing the usb_hc_died() to report abnormal shutdown
of a host controller, but before that, we should clean up the command
queue to free commands memory and complete the pending commands.

Signed-off-by: Baolin Wang <baolin.w...@linaro.org>
---
 drivers/usb/host/xhci-ring.c |1 +
 1 file changed, 1 insertion(+)

diff --git a/drivers/usb/host/xhci-ring.c b/drivers/usb/host/xhci-ring.c
index edc9ac2..92b48fe 100644
--- a/drivers/usb/host/xhci-ring.c
+++ b/drivers/usb/host/xhci-ring.c
@@ -904,6 +904,7 @@ void xhci_stop_endpoint_command_watchdog(unsigned long arg)
xhci_kill_endpoint_urbs(xhci, i, j);
}
spin_unlock_irqrestore(>lock, flags);
+   xhci_cleanup_command_queue(xhci);
xhci_dbg_trace(xhci, trace_xhci_dbg_cancel_urb,
"Calling usb_hc_died()");
usb_hc_died(xhci_to_hcd(xhci));
-- 
1.7.9.5

--
To unsubscribe from this list: send the line "unsubscribe linux-usb" in
the body of a message to majord...@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html


Re: [PATCH] usb: gadget: f_fs: Fix possibe deadlock

2016-12-08 Thread Baolin Wang
Hi Michal,

On 8 December 2016 at 23:18, Michal Nazarewicz <min...@mina86.com> wrote:
> On Thu, Dec 08 2016, Baolin Wang wrote:
>> When system try to close /dev/usb-ffs/adb/ep0 on one core, at the same
>> time another core try to attach new UDC, which will cause deadlock as
>> below scenario. Thus we should release ffs lock before issuing
>> unregister_gadget_item().
>>
>> [   52.642225] c1 ==
>> [   52.642228] c1 [ INFO: possible circular locking dependency detected ]
>> [   52.642236] c1 4.4.6+ #1 Tainted: GW  O
>> [   52.642241] c1 ---
>> [   52.642245] c1 usb ffs open/2808 is trying to acquire lock:
>> [   52.642270] c0  (udc_lock){+.+.+.}, at: []
>>   usb_gadget_unregister_driver+0x3c/0xc8
>> [   52.642272] c1  but task is already holding lock:
>> [   52.642283] c0  (ffs_lock){+.+.+.}, at: []
>>   ffs_data_clear+0x30/0x140
>> [   52.642285] c1 which lock already depends on the new lock.
>> [   52.642287] c1
>>the existing dependency chain (in reverse order) is:
>> [   52.642295] c0
>>  -> #1 (ffs_lock){+.+.+.}:
>> [   52.642307] c0[] __lock_acquire+0x20f0/0x2238
>> [   52.642314] c0[] lock_acquire+0xe4/0x298
>> [   52.642322] c0[] mutex_lock_nested+0x7c/0x3cc
>> [   52.642328] c0[] ffs_func_bind+0x504/0x6e8
>> [   52.642334] c0[] usb_add_function+0x84/0x184
>> [   52.642340] c0[] 
>> configfs_composite_bind+0x264/0x39c
>> [   52.642346] c0[] udc_bind_to_driver+0x58/0x11c
>> [   52.642352] c0[] usb_udc_attach_driver+0x90/0xc8
>> [   52.642358] c0[] 
>> gadget_dev_desc_UDC_store+0xd4/0x128
>> [   52.642369] c0[] configfs_write_file+0xd0/0x13c
>> [   52.642376] c0[] vfs_write+0xb8/0x214
>> [   52.642381] c0[] SyS_write+0x54/0xb0
>> [   52.642388] c0[] el0_svc_naked+0x24/0x28
>> [   52.642395] c0
>>   -> #0 (udc_lock){+.+.+.}:
>> [   52.642401] c0[] print_circular_bug+0x84/0x2e4
>> [   52.642407] c0[] __lock_acquire+0x2138/0x2238
>> [   52.642412] c0[] lock_acquire+0xe4/0x298
>> [   52.642420] c0[] mutex_lock_nested+0x7c/0x3cc
>> [   52.642427] c0[] 
>> usb_gadget_unregister_driver+0x3c/0xc8
>> [   52.642432] c0[] 
>> unregister_gadget_item+0x28/0x44
>> [   52.642439] c0[] ffs_data_clear+0x138/0x140
>> [   52.642444] c0[] ffs_data_reset+0x20/0x6c
>> [   52.642450] c0[] ffs_data_closed+0xac/0x12c
>> [   52.642454] c0[] ffs_ep0_release+0x20/0x2c
>> [   52.642460] c0[] __fput+0xb0/0x1f4
>> [   52.642466] c0[] fput+0x20/0x2c
>> [   52.642473] c0[] task_work_run+0xb4/0xe8
>> [   52.642482] c0[] do_exit+0x360/0xb9c
>> [   52.642487] c0[] do_group_exit+0x4c/0xb0
>> [   52.642494] c0[] get_signal+0x380/0x89c
>> [   52.642501] c0[] do_signal+0x154/0x518
>> [   52.642507] c0[] do_notify_resume+0x70/0x78
>> [   52.642512] c0[] work_pending+0x1c/0x20
>> [   52.642514] c1
>>   other info that might help us debug this:
>> [   52.642517] c1  Possible unsafe locking scenario:
>> [   52.642518] c1CPU0CPU1
>> [   52.642520] c1
>> [   52.642525] c0   lock(ffs_lock);
>> [   52.642529] c0lock(udc_lock);
>> [   52.642533] c0lock(ffs_lock);
>> [   52.642537] c0   lock(udc_lock);
>> [   52.642539] c1
>>   *** DEADLOCK ***
>> [   52.642543] c1 1 lock held by usb ffs open/2808:
>> [   52.642555] c0  #0:  (ffs_lock){+.+.+.}, at: []
>>   ffs_data_clear+0x30/0x140
>> [   52.642557] c1 stack backtrace:
>> [   52.642563] c1 CPU: 1 PID: 2808 Comm: usb ffs open Tainted: G
>> [   52.642565] c1 Hardware name: Spreadtrum SP9860g Board (DT)
>> [   52.642568] c1 Call trace:
>> [   52.642573] c1 [] dump_backtrace+0x0/0x170
>> [   52.642577] c1 [] show_stack+0x20/0x28
>> [   52.642583] c1 [] dump_stack+0xa8/0xe0
>> [   52.642587] c1 [] print_circular_bug+0x1fc/0x2e4
>> [   52.642591] c1 [] __lock_acquire+0x2138/0x2238
>> [   52.642595] c1 [] lock_acquire+0xe4/0x298
>> [   52.642599] c1 [] mutex_lock_nested+0x7c/0x3cc
>> [   52.642604] c1 [] usb_gadget_unregister_driver+0x3c/0xc8
>> [   52.642608] c1 [] unregister_gadget_item+0x2

Re: [PATCH v4 2/2] usb: dwc3: core: Support the dwc3 host suspend/resume

2016-12-08 Thread Baolin Wang
Hi,

On 9 December 2016 at 01:52, Felipe Balbi <ba...@kernel.org> wrote:
>
> Hi,
>
> Baolin Wang <baolin.w...@linaro.org> writes:
>>> Baolin Wang <baolin.w...@linaro.org> writes:
>>>>>> On 28 November 2016 at 14:43, Baolin Wang <baolin.w...@linaro.org> wrote:
>>>>>>> For some mobile devices with strict power management, we also want to 
>>>>>>> suspend
>>>>>>> the host when the slave is detached for power saving. Thus we add the 
>>>>>>> host
>>>>>>> suspend/resume functions to support this requirement.
>>>>>>>
>>>>>>> Signed-off-by: Baolin Wang <baolin.w...@linaro.org>
>>>>>>> ---
>>>>>>> Changes since v3:
>>>>>>>  - No updates.
>>>>>>>
>>>>>>> Changes since v2:
>>>>>>>  - Remove pm_children_suspended() and other unused macros.
>>>>>>>
>>>>>>>  Changes since v1:
>>>>>>>- Add pm_runtime.h head file to avoid kbuild error.
>>>>>>> ---
>>>>>>>  drivers/usb/dwc3/Kconfig |7 +++
>>>>>>>  drivers/usb/dwc3/core.c  |   26 +-
>>>>>>>  drivers/usb/dwc3/core.h  |   15 +++
>>>>>>>  drivers/usb/dwc3/host.c  |   37 +
>>>>>>>  4 files changed, 84 insertions(+), 1 deletion(-)
>>>>>>>
>>>>>>> diff --git a/drivers/usb/dwc3/Kconfig b/drivers/usb/dwc3/Kconfig
>>>>>>> index a45b4f1..47bb2f3 100644
>>>>>>> --- a/drivers/usb/dwc3/Kconfig
>>>>>>> +++ b/drivers/usb/dwc3/Kconfig
>>>>>>> @@ -47,6 +47,13 @@ config USB_DWC3_DUAL_ROLE
>>>>>>>
>>>>>>>  endchoice
>>>>>>>
>>>>>>> +config USB_DWC3_HOST_SUSPEND
>>>>>>> +   bool "Choose if the DWC3 host (xhci) can be suspend/resume"
>>>>>>> +   depends on USB_DWC3_HOST=y || USB_DWC3_DUAL_ROLE=y
>>>>>
>>>>> why do you need another Kconfig for this? Just enable it already :-p
>>>>
>>>> I assume some platforms may do not need this feature. But okay, I can
>>>> remove this kconfig and enable it.
>>>
>>> thanks :-)
>>>
>>>>>>> diff --git a/drivers/usb/dwc3/core.c b/drivers/usb/dwc3/core.c
>>>>>>> index 9a4a5e4..7ad4bc3 100644
>>>>>>> --- a/drivers/usb/dwc3/core.c
>>>>>>> +++ b/drivers/usb/dwc3/core.c
>>>>>>> @@ -1091,6 +1091,7 @@ static int dwc3_probe(struct platform_device 
>>>>>>> *pdev)
>>>>>>> pm_runtime_use_autosuspend(dev);
>>>>>>> pm_runtime_set_autosuspend_delay(dev, 
>>>>>>> DWC3_DEFAULT_AUTOSUSPEND_DELAY);
>>>>>>> pm_runtime_enable(dev);
>>>>>>> +   pm_suspend_ignore_children(dev, true);
>>>>>
>>>>> why do you need this?
>>>>
>>>> Since the dwc3 device is the parent deive of xhci device, if we want
>>>> to suspend dwc3 device, we need to suspend child device (xhci device)
>>>> manually by issuing pm_runtime_put_sync() in dwc3_host_suspend(). In
>>>> pm_runtime_put_sync(), it will check if the children (xhci device) of
>>>> dwc3 device have been in suspend state, if not we will suspend dwc3
>>>> device failed.
>>>>
>>>> We get/put the child device manually in parent device's runtime
>>>> callback, we need to ignore the child device's runtime state, or it
>>>> will failed due to the dependency.
>>>
>>> I see. Good explanation :-)
>>>
>>> There's one thing though, if you want to runtime suspend the gadget and
>>> dwc3 is working on peripheral mode, host side (XHCI) should already be
>>> runtime suspended because there's nothing attached to it. Why isn't it
>>> runtime suspended?
>>
>> Since we have get the runtime count for xHCI device in
>> xhci_plat_probe(), in case it will suspend automatically if some
>> controllers do not want xHCI enters runtime suspend automatically. So
>> the parent device (dwc3 device) need to get/put the xHCI device's
>> runtime count  to resume/suspend xHCI.
>
> IMHO, that's a bug in xh

[PATCH] usb: dwc3: ep0: Fix the possible missed request for handling delay STATUS phase

2017-01-14 Thread Baolin Wang
When handing the SETUP packet by composite_setup(), we will release the
dwc->lock. If we get the 'USB_GADGET_DELAYED_STATUS' result from setup
function, which means we need to delay handling the STATUS phase.

But during the lock release period, maybe the request for handling delay
STATUS phase has been queued into list before we set 'dwc->delayed_status'
flag or entering 'EP0_STATUS_PHASE' phase, then we will miss the chance
to handle the STATUS phase. Thus we should check if the request for delay
STATUS phase has been enqueued when entering 'EP0_STATUS_PHASE' phase in
dwc3_ep0_xfernotready(), if so, we should handle it.

Signed-off-by: Baolin Wang <baolin.w...@linaro.org>
---
 drivers/usb/dwc3/ep0.c |   14 ++
 1 file changed, 14 insertions(+)

diff --git a/drivers/usb/dwc3/ep0.c b/drivers/usb/dwc3/ep0.c
index 9bb1f85..e689ced 100644
--- a/drivers/usb/dwc3/ep0.c
+++ b/drivers/usb/dwc3/ep0.c
@@ -1123,7 +1123,21 @@ static void dwc3_ep0_xfernotready(struct dwc3 *dwc,
dwc->ep0state = EP0_STATUS_PHASE;
 
if (dwc->delayed_status) {
+   struct dwc3_ep *dep = dwc->eps[0];
+
WARN_ON_ONCE(event->endpoint_number != 1);
+   /*
+* We should handle the delay STATUS phase here if the
+* request for handling delay STATUS has been queued
+* into the list.
+*/
+   if (!list_empty(>pending_list)) {
+   dwc->delayed_status = false;
+   usb_gadget_set_state(>gadget,
+USB_STATE_CONFIGURED);
+   dwc3_ep0_do_control_status(dwc, event);
+   }
+
return;
}
 
-- 
1.7.9.5

--
To unsubscribe from this list: send the line "unsubscribe linux-usb" in
the body of a message to majord...@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html


Re: [PATCH 22/25] usb: host: xhci: remove unnecessary list_for_each_entry_safe()

2016-12-02 Thread Baolin Wang
Hi Felipe,

On 2 December 2016 at 18:15, Sergei Shtylyov
 wrote:
> Hello!
>
> On 12/1/2016 4:31 PM, Felipe Balbi wrote:
>
>> the _save() version of list iterators are supposed to be used when
>
>
>_safe().
>
>> list_entry is going to be removed from the list while iterating. Since
>> xhci_handle_stopped_cmd_ring() is not removing anything from the list,
>> just converting commands into No-Op TRBs, we don't need to use the safe
>> version.
>>
>> Signed-off-by: Felipe Balbi 
>> ---
>>  drivers/usb/host/xhci-ring.c | 21 ++---
>>  1 file changed, 10 insertions(+), 11 deletions(-)
>>
>> diff --git a/drivers/usb/host/xhci-ring.c b/drivers/usb/host/xhci-ring.c
>> index 50244dee6b43..ebb52ffab805 100644
>> --- a/drivers/usb/host/xhci-ring.c
>> +++ b/drivers/usb/host/xhci-ring.c
>
> [...]
>>
>> @@ -1250,7 +1250,6 @@ static void xhci_handle_stopped_cmd_ring(struct
>> xhci_hcd *xhci,
>> mod_timer(>cmd_timer, jiffies +
>> XHCI_CMD_DEFAULT_TIMEOUT);
>> xhci_ring_cmd_db(xhci);
>> }
>> -   return;
>
>
>Not mentioned in the patch description?

Just a note, this has been fixed by my previous patch:
https://lkml.org/lkml/2016/11/24/219

-- 
Baolin.wang
Best Regards
--
To unsubscribe from this list: send the line "unsubscribe linux-usb" in
the body of a message to majord...@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html


[PATCH] usb: host: xhci: Handle the right timeout command

2016-12-02 Thread Baolin Wang
If a command event is found on the event ring during an interrupt,
we need to stop the command timer with del_timer(). Since del_timer()
can fail if the timer is running and waiting on the xHCI lock, then
it maybe get the wrong timeout command in xhci_handle_command_timeout()
if host fetched a new command and updated the xhci->current_cmd in
handle_cmd_completion(). For this situation, we need a way to signal
to the command timer that everything is fine and it should exit.

We should introduce a counter (xhci->current_cmd_pending) for the number
of pending commands. If we need to cancel the command timer and del_timer()
succeeds, we decrement the number of pending commands. If del_timer() fails,
we leave the number of pending commands alone.

For handling timeout command, in xhci_handle_command_timeout() we will check
the counter after decrementing it, if the counter (xhci->current_cmd_pending)
is 0, which means xhci->current_cmd is the right timeout command. If the
counter (xhci->current_cmd_pending) is greater than 0, which means current
timeout command has been handled by host and host has fetched new command
as xhci->current_cmd, then just return and wait for new current command.

Signed-off-by: Baolin Wang <baolin.w...@linaro.org>
---
This patch is based on Lu Baolu's new fix patch:
usb: xhci: fix possible wild pointer
---
 drivers/usb/host/xhci-ring.c |   26 +-
 drivers/usb/host/xhci.h  |1 +
 2 files changed, 26 insertions(+), 1 deletion(-)

diff --git a/drivers/usb/host/xhci-ring.c b/drivers/usb/host/xhci-ring.c
index 62dd1c7..a62904e 100644
--- a/drivers/usb/host/xhci-ring.c
+++ b/drivers/usb/host/xhci-ring.c
@@ -1253,6 +1253,7 @@ static void xhci_handle_stopped_cmd_ring(struct xhci_hcd 
*xhci,
if ((xhci->cmd_ring->dequeue != xhci->cmd_ring->enqueue) &&
!(xhci->xhc_state & XHCI_STATE_DYING)) {
xhci->current_cmd = cur_cmd;
+   xhci->current_cmd_pending++;
mod_timer(>cmd_timer, jiffies + XHCI_CMD_DEFAULT_TIMEOUT);
xhci_ring_cmd_db(xhci);
}
@@ -1274,6 +1275,21 @@ void xhci_handle_command_timeout(unsigned long data)
return;
}
 
+   xhci->current_cmd_pending--;
+   /*
+* If the current_cmd_pending is 0, which means current command is
+* timeout.
+*
+* If the current_cmd_pending is greater than 0, which means current
+* timeout command has been handled by host and host has fetched new
+* command as xhci->current_cmd, then just return and wait for new
+* current command.
+*/
+   if (xhci->current_cmd_pending > 0) {
+   spin_unlock_irqrestore(>lock, flags);
+   return;
+   }
+
if (xhci->current_cmd->status == COMP_CMD_ABORT)
second_timeout = true;
xhci->current_cmd->status = COMP_CMD_ABORT;
@@ -1336,7 +1352,13 @@ static void handle_cmd_completion(struct xhci_hcd *xhci,
 
cmd = list_entry(xhci->cmd_list.next, struct xhci_command, cmd_list);
 
-   del_timer(>cmd_timer);
+   /*
+* If the command timer is running on another CPU, we don't decrement
+* current_cmd_pending, since we didn't successfully stop the command
+* timer.
+*/
+   if (del_timer(>cmd_timer))
+   xhci->current_cmd_pending--;
 
trace_xhci_cmd_completion(cmd_trb, (struct xhci_generic_trb *) event);
 
@@ -1424,6 +1446,7 @@ static void handle_cmd_completion(struct xhci_hcd *xhci,
if (cmd->cmd_list.next != >cmd_list) {
xhci->current_cmd = list_entry(cmd->cmd_list.next,
   struct xhci_command, cmd_list);
+   xhci->current_cmd_pending++;
mod_timer(>cmd_timer, jiffies + XHCI_CMD_DEFAULT_TIMEOUT);
} else if (xhci->current_cmd == cmd) {
xhci->current_cmd = NULL;
@@ -3924,6 +3947,7 @@ static int queue_command(struct xhci_hcd *xhci, struct 
xhci_command *cmd,
if (xhci->cmd_list.next == >cmd_list &&
!timer_pending(>cmd_timer)) {
xhci->current_cmd = cmd;
+   xhci->current_cmd_pending++;
mod_timer(>cmd_timer, jiffies + XHCI_CMD_DEFAULT_TIMEOUT);
}
 
diff --git a/drivers/usb/host/xhci.h b/drivers/usb/host/xhci.h
index 9dbaacf..5d81257 100644
--- a/drivers/usb/host/xhci.h
+++ b/drivers/usb/host/xhci.h
@@ -1567,6 +1567,7 @@ struct xhci_hcd {
unsigned intcmd_ring_reserved_trbs;
struct timer_list   cmd_timer;
struct xhci_command *current_cmd;
+   u32 current_cmd_pending;
struct xhci_ring*event_ring;
struct xhci_ersterst;
/* Scratchpad */
-- 
1.7.9.5

--
To unsubscribe from 

Re: [RFC] usb: host: xhci: Remove the watchdog timer and use command timer to watch stop endpoint command

2016-12-01 Thread Baolin Wang
On 2 December 2016 at 09:17, Lu Baolu <baolu...@linux.intel.com> wrote:
> Hi,
>
> On 12/01/2016 04:03 PM, Baolin Wang wrote:
>> On 1 December 2016 at 15:44, Lu Baolu <baolu...@linux.intel.com> wrote:
>>> Hi,
>>>
>>> On 12/01/2016 03:35 PM, Baolin Wang wrote:
>>>> On 1 December 2016 at 14:35, Lu Baolu <baolu...@linux.intel.com> wrote:
>>>>> Hi,
>>>>>
>>>>> On 12/01/2016 02:04 PM, Baolin Wang wrote:
>>>>>> Hi Baolu,
>>>>>>
>>>>>> On 1 December 2016 at 13:45, Lu Baolu <baolu...@linux.intel.com> wrote:
>>>>>>> Hi,
>>>>>>>
>>>>>>> On 11/30/2016 05:02 PM, Baolin Wang wrote:
>>>>>>>> If the hardware never responds to the stop endpoint command, the
>>>>>>>> URBs will never be completed, and we might hang the USB subsystem.
>>>>>>>> The original watchdog timer is used to watch if one stop endpoint
>>>>>>>> command is timeout, if timeout, then the watchdog timer will set
>>>>>>>> XHCI_STATE_DYING, try to halt the xHCI host, and give back all
>>>>>>>> pending URBs.
>>>>>>>>
>>>>>>>> But now we already have one command timer to control command timeout,
>>>>>>>> thus we can also use the command timer to watch the stop endpoint
>>>>>>>> command, instead of one duplicate watchdog timer which need to be
>>>>>>>> removed.
>>>>>>>>
>>>>>>>> Meanwhile we don't need the 'stop_cmds_pending' flag to identy if
>>>>>>>> this is the last stop endpoint command of one endpoint. Since we
>>>>>>>> can make sure we only set one stop endpoint command for one endpoint
>>>>>>>> by 'EP_HALT_PENDING' flag in xhci_urb_dequeue() function. Thus remove
>>>>>>>> this flag.
>>>>>>> I am afraid you can't do this. "stop_cmds_pending" was added
>>>>>>> to fix the problem described in the comments that you want to
>>>>>>> remove. But I didn't find any fix of this problem in your patch.
>>>>>> Now we can not pending another stop endpoint command for the same one
>>>>>> endpoint, since will check 'EP_HALT_PENDING' flag in
>>>>>> xhci_urb_dequeue() function to avoid this. But after some
>>>>>> investigation, I think I missed the stop endpoint command in
>>>>>> xhci_stop_device() which did not check the 'EP_HALT_PENDING' flag,
>>>>>> maybe need to add 'EP_HALT_PENDING' flag checking in
>>>>>> xhci_stop_device() function. DId I miss something else? Thanks.
>>>>> Consider below three threads running on different CPUs at the same time.
>>>>>
>>>>> Thread A: xhci_handle_cmd_stop_ep()  --- in interrupt handler
>>>>> Thread B: xhci_stop_endpoint_command_timeout() --- timer expired
>>>>> Thread C: xhci_urb_dequeue --- called by usb core
>>>>>
>>>>> They are serialized by xhci->lock. Let's consider below sequence:
>>>>>
>>>>> Thread A:
>>>>> - delete xhci->cmd_timer), but will fail due to Thread B.
>>>>> - clear EP_HALT_PENDING bit
>>>>>
>>>>> Thread B:
>>>>> - halt the host controller
>>>>>
>>>>> Thread C:
>>>>> - set EP_HALT_PENDING bit
>>>>> - enqueue another stop endpoint command
>>>>> - add the timer back
>>>> Ah, thanks for you comments.
>>>> If thread B halted the host, then the thread C xhci_urb_dequeue() will
>>>> check host state failed, then just return and can not set another stop
>>>> endpoint command.
>>> Not so simple. Thread B will release xhci->lock before xhci_halt().
>> Yes.
>>
>>>> But from your example, I think your meaning is we
>>>> should not halt the host by thread B, since we have handled the stop
>>>> endpoint command event.
>>>>
>>>> So I think we need to check the xhci command of this stop endpoint
>>>> command in xhci_stop_endpoint_command_timeout(), if the xhci command
>>>> of this stop endpoint command is not in the command list (which means
>>>> the stop endpoint command event has been handled), then just return
>>>> and do not halt the controller. Right?
>>>>
>>> I'd like suggest you to put this change into a separated patch.
>>> It's actually a different topic from the main purpose of this patch.
>> OK, I will. Thanks for your comments.
>>
>
> If you are going to work out a v2 patch, please consider whether
> we can totally leverage the common command mechanism to
> handle this stop endpoint command.
>
> Currently, when a stop endpoint command is issued for urb unlink,
> there are two timers for this command. This is duplicated and we
> should remove the stop-endpoint-only timer. The timeout functions
> are also different. The stop-endpoint-only timer just halt the host
> controller (this should be the last sort of way), while the common
> command timer will try to recover the situation by aborting and
> restart the command ring.

Yes, thanks for your reminding and I will think about that.

-- 
Baolin.wang
Best Regards
--
To unsubscribe from this list: send the line "unsubscribe linux-usb" in
the body of a message to majord...@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html


Re: [PATCH 1/1] usb: xhci: fix possible wild pointer

2016-12-01 Thread Baolin Wang
On 2 December 2016 at 10:29, Lu Baolu <baolu...@linux.intel.com> wrote:
> handle_cmd_completion() frees a command structure which might
> be still referenced by xhci->current_cmd. This might cause
> problem when xhci->current_cmd is accessed after that.
>
> A real-life case could be like this. The host takes a very long
> time to respond to a command, and the command timer is fired at
> the same time when the command completion event arrives. The
> command completion handler frees xhci->current_cmd before the
> timer function can grab xhci->lock. Afterward, timer function
> grabs the lock and go ahead with checking and setting members
> of xhci->current_cmd.
>
> Cc: <sta...@vger.kernel.org> # v3.16+
> Signed-off-by: Lu Baolu <baolu...@linux.intel.com>

Nice catch. I was also curious where set xhci->current_cmd to be NULL
when current command is freed.
Tested-by: Baolin Wang <baolin.w...@linaro.org>

> ---
>  drivers/usb/host/xhci-ring.c | 16 +++-
>  1 file changed, 11 insertions(+), 5 deletions(-)
>
> diff --git a/drivers/usb/host/xhci-ring.c b/drivers/usb/host/xhci-ring.c
> index bdf6b13..13e05f6 100644
> --- a/drivers/usb/host/xhci-ring.c
> +++ b/drivers/usb/host/xhci-ring.c
> @@ -1267,14 +1267,16 @@ void xhci_handle_command_timeout(unsigned long data)
> bool second_timeout = false;
> xhci = (struct xhci_hcd *) data;
>
> -   /* mark this command to be cancelled */
> spin_lock_irqsave(>lock, flags);
> -   if (xhci->current_cmd) {
> -   if (xhci->current_cmd->status == COMP_CMD_ABORT)
> -   second_timeout = true;
> -   xhci->current_cmd->status = COMP_CMD_ABORT;
> +   if (!xhci->current_cmd) {
> +   spin_unlock_irqrestore(>lock, flags);
> +   return;
> }
>
> +   if (xhci->current_cmd->status == COMP_CMD_ABORT)
> +   second_timeout = true;
> +   xhci->current_cmd->status = COMP_CMD_ABORT;
> +
> /* Make sure command ring is running before aborting it */
> hw_ring_state = xhci_read_64(xhci, >op_regs->cmd_ring);
> if ((xhci->cmd_ring_state & CMD_RING_STATE_RUNNING) &&
> @@ -1422,6 +1424,10 @@ static void handle_cmd_completion(struct xhci_hcd 
> *xhci,
> xhci->current_cmd = list_entry(cmd->cmd_list.next,
>struct xhci_command, cmd_list);
> mod_timer(>cmd_timer, jiffies + 
> XHCI_CMD_DEFAULT_TIMEOUT);
> +   } else if (xhci->current_cmd == cmd) {
> +   xhci->current_cmd = NULL;
> +   } else {
> +   xhci_warn(xhci, "WARN current_cmd doesn't match command\n");
> }
>
>  event_handled:
> --
> 2.1.4
>
> --
> To unsubscribe from this list: send the line "unsubscribe linux-usb" in
> the body of a message to majord...@vger.kernel.org
> More majordomo info at  http://vger.kernel.org/majordomo-info.html



-- 
Baolin.wang
Best Regards
--
To unsubscribe from this list: send the line "unsubscribe linux-usb" in
the body of a message to majord...@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html


Re: [RFC] usb: host: xhci: Remove the watchdog timer and use command timer to watch stop endpoint command

2016-12-01 Thread Baolin Wang
On 1 December 2016 at 21:28, Mathias Nyman
<mathias.ny...@linux.intel.com> wrote:
> On 01.12.2016 06:54, Baolin Wang wrote:
>>
>> On 30 November 2016 at 22:09, Mathias Nyman
>> <mathias.ny...@linux.intel.com> wrote:
>>>
>>> On 30.11.2016 11:02, Baolin Wang wrote:
>>>>
>>>>
>>>> If the hardware never responds to the stop endpoint command, the
>>>> URBs will never be completed, and we might hang the USB subsystem.
>>>> The original watchdog timer is used to watch if one stop endpoint
>>>> command is timeout, if timeout, then the watchdog timer will set
>>>> XHCI_STATE_DYING, try to halt the xHCI host, and give back all
>>>> pending URBs.
>>>>
>>>> But now we already have one command timer to control command timeout,
>>>> thus we can also use the command timer to watch the stop endpoint
>>>> command, instead of one duplicate watchdog timer which need to be
>>>> removed.
>>>>
>>>> Meanwhile we don't need the 'stop_cmds_pending' flag to identy if
>>>> this is the last stop endpoint command of one endpoint. Since we
>>>> can make sure we only set one stop endpoint command for one endpoint
>>>> by 'EP_HALT_PENDING' flag in xhci_urb_dequeue() function. Thus remove
>>>> this flag.
>>>>
>>>> We also need to clean up the command queue before trying to halt the
>>>> xHCI host in xhci_stop_endpoint_command_timeout() function.
>>>
>>>
>>>
>>> This isn't a bad idea.
>>>
>>> There are anyway some corner cases and details that need to be
>>> checked, such as suspend (which will clear the command queue), module
>>> unload
>>> and abrupt host removal (like pci hotplug removal of host controller)
>>> we need to make sure we can trust the command timer to always return the
>>> canceled URB
>>
>>
>> Yes, you are right, we need to check these carefully.
>>
>> Suspend process, module unload and abrupt host removal, they all will
>> issue usb_disconnect() firstly before clear the command queue, it will
>> check URBs for every endpoint by
>> usb_disconnect()--->usb_disable_device()--->usb_disable_endpoint(),
>> which will make sure every URBs of endpoints will be cancelled by the
>> stop endpoint command responding or the timeout function of stop
>> endpoint command (xhci_stop_endpoint_command_timeout()) in
>> usb_hcd_flush_endpoint(). From that point, we can make sure the
>> command timer will be useful to handle stop endpoint command timeout.
>> Please correct me if I said something wrong. Thanks.
>>
>
> This relies on current queued command that times out to be the stop endpoint
> command.
>
> If host partially, or completely hangs there might be any number of commands
> in the
> command queue, and we would need to wait for each one of them to timeout,
> finish
> before we finally get to the stop endpoint command, and give back the urb.
>
> I think it would be better to first fix the issues with the current watchdog
> function, get
> those fixes into stable, and then think about moving to the command queue
> timer.

OK, make sense. Thanks.

>
> In short, this patch doesn't currently fix any existing issue, but might
> cause the
> timeout to be more unreliable
>
> -Mathias



-- 
Baolin.wang
Best Regards
--
To unsubscribe from this list: send the line "unsubscribe linux-usb" in
the body of a message to majord...@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html


[RFC] usb: host: xhci: Remove the watchdog timer and use command timer to watch stop endpoint command

2016-11-30 Thread Baolin Wang
If the hardware never responds to the stop endpoint command, the
URBs will never be completed, and we might hang the USB subsystem.
The original watchdog timer is used to watch if one stop endpoint
command is timeout, if timeout, then the watchdog timer will set
XHCI_STATE_DYING, try to halt the xHCI host, and give back all
pending URBs.

But now we already have one command timer to control command timeout,
thus we can also use the command timer to watch the stop endpoint
command, instead of one duplicate watchdog timer which need to be
removed.

Meanwhile we don't need the 'stop_cmds_pending' flag to identy if
this is the last stop endpoint command of one endpoint. Since we
can make sure we only set one stop endpoint command for one endpoint
by 'EP_HALT_PENDING' flag in xhci_urb_dequeue() function. Thus remove
this flag.

We also need to clean up the command queue before trying to halt the
xHCI host in xhci_stop_endpoint_command_timeout() function.

Signed-off-by: Baolin Wang <baolin.w...@linaro.org>
---
 drivers/usb/host/xhci-mem.c  |   10 +--
 drivers/usb/host/xhci-ring.c |   61 +-
 drivers/usb/host/xhci.c  |8 +-
 drivers/usb/host/xhci.h  |5 
 4 files changed, 21 insertions(+), 63 deletions(-)

diff --git a/drivers/usb/host/xhci-mem.c b/drivers/usb/host/xhci-mem.c
index d6f59a3..2a5cd89 100644
--- a/drivers/usb/host/xhci-mem.c
+++ b/drivers/usb/host/xhci-mem.c
@@ -844,14 +844,6 @@ void xhci_free_stream_info(struct xhci_hcd *xhci,
 
 /* Device context manipulation */
 
-static void xhci_init_endpoint_timer(struct xhci_hcd *xhci,
-   struct xhci_virt_ep *ep)
-{
-   setup_timer(>stop_cmd_timer, xhci_stop_endpoint_command_watchdog,
-   (unsigned long)ep);
-   ep->xhci = xhci;
-}
-
 static void xhci_free_tt_info(struct xhci_hcd *xhci,
struct xhci_virt_device *virt_dev,
int slot_id)
@@ -1014,7 +1006,7 @@ int xhci_alloc_virt_device(struct xhci_hcd *xhci, int 
slot_id,
 
/* Initialize the cancellation list and watchdog timers for each ep */
for (i = 0; i < 31; i++) {
-   xhci_init_endpoint_timer(xhci, >eps[i]);
+   dev->eps[i].xhci = xhci;
INIT_LIST_HEAD(>eps[i].cancelled_td_list);
INIT_LIST_HEAD(>eps[i].bw_endpoint_list);
}
diff --git a/drivers/usb/host/xhci-ring.c b/drivers/usb/host/xhci-ring.c
index 2057d08..67a1bd6 100644
--- a/drivers/usb/host/xhci-ring.c
+++ b/drivers/usb/host/xhci-ring.c
@@ -561,18 +561,6 @@ static void td_to_noop(struct xhci_hcd *xhci, struct 
xhci_ring *ep_ring,
}
 }
 
-static void xhci_stop_watchdog_timer_in_irq(struct xhci_hcd *xhci,
-   struct xhci_virt_ep *ep)
-{
-   ep->ep_state &= ~EP_HALT_PENDING;
-   /* Can't del_timer_sync in interrupt, so we attempt to cancel.  If the
-* timer is running on another CPU, we don't decrement stop_cmds_pending
-* (since we didn't successfully stop the watchdog timer).
-*/
-   if (del_timer(>stop_cmd_timer))
-   ep->stop_cmds_pending--;
-}
-
 /* Must be called with xhci->lock held in interrupt context */
 static void xhci_giveback_urb_in_irq(struct xhci_hcd *xhci,
struct xhci_td *cur_td, int status)
@@ -664,7 +652,7 @@ static void xhci_handle_cmd_stop_ep(struct xhci_hcd *xhci, 
int slot_id,
ep = >devs[slot_id]->eps[ep_index];
 
if (list_empty(>cancelled_td_list)) {
-   xhci_stop_watchdog_timer_in_irq(xhci, ep);
+   ep->ep_state &= ~EP_HALT_PENDING;
ep->stopped_td = NULL;
ring_doorbell_for_active_rings(xhci, slot_id, ep_index);
return;
@@ -719,7 +707,7 @@ static void xhci_handle_cmd_stop_ep(struct xhci_hcd *xhci, 
int slot_id,
list_del_init(_td->td_list);
}
last_unlinked_td = cur_td;
-   xhci_stop_watchdog_timer_in_irq(xhci, ep);
+   ep->ep_state &= ~EP_HALT_PENDING;
 
/* If necessary, queue a Set Transfer Ring Dequeue Pointer command */
if (deq_state.new_deq_ptr && deq_state.new_deq_seg) {
@@ -817,38 +805,19 @@ static void xhci_kill_endpoint_urbs(struct xhci_hcd *xhci,
}
 }
 
-/* Watchdog timer function for when a stop endpoint command fails to complete.
+/* This timeout function for when a stop endpoint command fails to complete.
  * In this case, we assume the host controller is broken or dying or dead.  The
  * host may still be completing some other events, so we have to be careful to
  * let the event ring handler and the URB dequeueing/enqueueing functions know
  * through xhci->state.
- *
- * The timer may also fire if the host takes a very long time to respond to the
- * command, and the stop endpoint command completion handler cannot delete the
- * timer before the timer fu

Re: [PATCH] usb: host: xhci: Handle the right timeout command

2016-12-04 Thread Baolin Wang
On 2 December 2016 at 19:21, Baolin Wang <baolin.w...@linaro.org> wrote:
> If a command event is found on the event ring during an interrupt,
> we need to stop the command timer with del_timer(). Since del_timer()
> can fail if the timer is running and waiting on the xHCI lock, then
> it maybe get the wrong timeout command in xhci_handle_command_timeout()
> if host fetched a new command and updated the xhci->current_cmd in
> handle_cmd_completion(). For this situation, we need a way to signal
> to the command timer that everything is fine and it should exit.
>
> We should introduce a counter (xhci->current_cmd_pending) for the number
> of pending commands. If we need to cancel the command timer and del_timer()
> succeeds, we decrement the number of pending commands. If del_timer() fails,
> we leave the number of pending commands alone.
>
> For handling timeout command, in xhci_handle_command_timeout() we will check
> the counter after decrementing it, if the counter (xhci->current_cmd_pending)
> is 0, which means xhci->current_cmd is the right timeout command. If the
> counter (xhci->current_cmd_pending) is greater than 0, which means current
> timeout command has been handled by host and host has fetched new command
> as xhci->current_cmd, then just return and wait for new current command.
>
> Signed-off-by: Baolin Wang <baolin.w...@linaro.org>
> ---
> This patch is based on Lu Baolu's new fix patch:
> usb: xhci: fix possible wild pointer
> ---
>  drivers/usb/host/xhci-ring.c |   26 +-
>  drivers/usb/host/xhci.h  |1 +
>  2 files changed, 26 insertions(+), 1 deletion(-)
>
> diff --git a/drivers/usb/host/xhci-ring.c b/drivers/usb/host/xhci-ring.c
> index 62dd1c7..a62904e 100644
> --- a/drivers/usb/host/xhci-ring.c
> +++ b/drivers/usb/host/xhci-ring.c
> @@ -1253,6 +1253,7 @@ static void xhci_handle_stopped_cmd_ring(struct 
> xhci_hcd *xhci,
> if ((xhci->cmd_ring->dequeue != xhci->cmd_ring->enqueue) &&
> !(xhci->xhc_state & XHCI_STATE_DYING)) {
> xhci->current_cmd = cur_cmd;
> +   xhci->current_cmd_pending++;
> mod_timer(>cmd_timer, jiffies + 
> XHCI_CMD_DEFAULT_TIMEOUT);
> xhci_ring_cmd_db(xhci);
> }
> @@ -1274,6 +1275,21 @@ void xhci_handle_command_timeout(unsigned long data)
> return;
> }
>
> +   xhci->current_cmd_pending--;

I realized I should move the decrement before 'xhci->current_cmd'
checking, and I will wait for a while for new comments before sending
out v2 patch.

> +   /*
> +* If the current_cmd_pending is 0, which means current command is
> +* timeout.
> +*
> +* If the current_cmd_pending is greater than 0, which means current
> +* timeout command has been handled by host and host has fetched new
> +* command as xhci->current_cmd, then just return and wait for new
> +* current command.
> +*/
> +   if (xhci->current_cmd_pending > 0) {
> +   spin_unlock_irqrestore(>lock, flags);
> +   return;
> +   }
> +
> if (xhci->current_cmd->status == COMP_CMD_ABORT)
> second_timeout = true;
> xhci->current_cmd->status = COMP_CMD_ABORT;
> @@ -1336,7 +1352,13 @@ static void handle_cmd_completion(struct xhci_hcd 
> *xhci,
>
> cmd = list_entry(xhci->cmd_list.next, struct xhci_command, cmd_list);
>
> -   del_timer(>cmd_timer);
> +   /*
> +* If the command timer is running on another CPU, we don't decrement
> +* current_cmd_pending, since we didn't successfully stop the command
> +* timer.
> +*/
> +   if (del_timer(>cmd_timer))
> +   xhci->current_cmd_pending--;
>
> trace_xhci_cmd_completion(cmd_trb, (struct xhci_generic_trb *) event);
>
> @@ -1424,6 +1446,7 @@ static void handle_cmd_completion(struct xhci_hcd *xhci,
> if (cmd->cmd_list.next != >cmd_list) {
> xhci->current_cmd = list_entry(cmd->cmd_list.next,
>struct xhci_command, cmd_list);
> +   xhci->current_cmd_pending++;
> mod_timer(>cmd_timer, jiffies + 
> XHCI_CMD_DEFAULT_TIMEOUT);
> } else if (xhci->current_cmd == cmd) {
> xhci->current_cmd = NULL;
> @@ -3924,6 +3947,7 @@ static int queue_command(struct xhci_hcd *xhci, struct 
> xhci_command *cmd,
> if (xhci->cmd_list.next == >cmd_list &&
> !timer_pending(>cmd_timer)) {
>

[PATCH 2/2] usb: host: xhci: Handle the right timeout command

2016-12-05 Thread Baolin Wang
If a command event is found on the event ring during an interrupt,
we need to stop the command timer with del_timer(). Since del_timer()
can fail if the timer is running and waiting on the xHCI lock, then
it maybe get the wrong timeout command in xhci_handle_command_timeout()
if host fetched a new command and updated the xhci->current_cmd in
handle_cmd_completion(). For this situation, we need a way to signal
to the command timer that everything is fine and it should exit.

We should introduce a counter (xhci->current_cmd_pending) for the number
of pending commands. If we need to cancel the command timer and del_timer()
succeeds, we decrement the number of pending commands. If del_timer() fails,
we leave the number of pending commands alone.

For handling timeout command, in xhci_handle_command_timeout() we will check
the counter after decrementing it, if the counter (xhci->current_cmd_pending)
is 0, which means xhci->current_cmd is the right timeout command. If the
counter (xhci->current_cmd_pending) is greater than 0, which means current
timeout command has been handled by host and host has fetched new command as
xhci->current_cmd, then just return and wait for new current command.

Signed-off-by: Baolin Wang <baolin.w...@linaro.org>
---
 drivers/usb/host/xhci-ring.c |   29 -
 drivers/usb/host/xhci.h  |1 +
 2 files changed, 29 insertions(+), 1 deletion(-)

diff --git a/drivers/usb/host/xhci-ring.c b/drivers/usb/host/xhci-ring.c
index 9965a4c..edc9ac2 100644
--- a/drivers/usb/host/xhci-ring.c
+++ b/drivers/usb/host/xhci-ring.c
@@ -1253,6 +1253,7 @@ static void xhci_handle_stopped_cmd_ring(struct xhci_hcd 
*xhci,
if ((xhci->cmd_ring->dequeue != xhci->cmd_ring->enqueue) &&
!(xhci->xhc_state & XHCI_STATE_DYING)) {
xhci->current_cmd = cur_cmd;
+   xhci->current_cmd_pending++;
mod_timer(>cmd_timer, jiffies + XHCI_CMD_DEFAULT_TIMEOUT);
xhci_ring_cmd_db(xhci);
}
@@ -1269,11 +1270,27 @@ void xhci_handle_command_timeout(unsigned long data)
xhci = (struct xhci_hcd *) data;
 
spin_lock_irqsave(>lock, flags);
+   xhci->current_cmd_pending--;
+
if (!xhci->current_cmd) {
spin_unlock_irqrestore(>lock, flags);
return;
}
 
+   /*
+* If the current_cmd_pending is 0, which means current command is
+* timeout.
+*
+* If the current_cmd_pending is greater than 0, which means current
+* timeout command has been handled by host and host has fetched new
+* command as xhci->current_cmd, then just return and wait for new
+* current command.
+*/
+   if (xhci->current_cmd_pending > 0) {
+   spin_unlock_irqrestore(>lock, flags);
+   return;
+   }
+
if (xhci->current_cmd->status == COMP_CMD_ABORT)
second_timeout = true;
xhci->current_cmd->status = COMP_CMD_ABORT;
@@ -1282,6 +1299,8 @@ void xhci_handle_command_timeout(unsigned long data)
hw_ring_state = xhci_read_64(xhci, >op_regs->cmd_ring);
if ((xhci->cmd_ring_state & CMD_RING_STATE_RUNNING) &&
(hw_ring_state & CMD_RING_RUNNING))  {
+   /* Will add command timer again to wait for abort event */
+   xhci->current_cmd_pending++;
spin_unlock_irqrestore(>lock, flags);
xhci_dbg(xhci, "Command timeout\n");
ret = xhci_abort_cmd_ring(xhci);
@@ -1336,7 +1355,13 @@ static void handle_cmd_completion(struct xhci_hcd *xhci,
 
cmd = list_entry(xhci->cmd_list.next, struct xhci_command, cmd_list);
 
-   del_timer(>cmd_timer);
+   /*
+* If the command timer is running on another CPU, we don't decrement
+* current_cmd_pending, since we didn't successfully stop the command
+* timer.
+*/
+   if (del_timer(>cmd_timer))
+   xhci->current_cmd_pending--;
 
trace_xhci_cmd_completion(cmd_trb, (struct xhci_generic_trb *) event);
 
@@ -1427,6 +1452,7 @@ static void handle_cmd_completion(struct xhci_hcd *xhci,
if (cmd->cmd_list.next != >cmd_list) {
xhci->current_cmd = list_entry(cmd->cmd_list.next,
   struct xhci_command, cmd_list);
+   xhci->current_cmd_pending++;
mod_timer(>cmd_timer, jiffies + XHCI_CMD_DEFAULT_TIMEOUT);
} else if (xhci->current_cmd == cmd) {
xhci->current_cmd = NULL;
@@ -3927,6 +3953,7 @@ static int queue_command(struct xhci_hcd *xhci, struct 
xhci_command *cmd,
if (xhci->cmd_list.next == >cmd_list &&
!timer_pending(>cmd_timer)) {
xhci->current_cmd = cmd;
+  

[PATCH 1/2] usb: host: xhci: Fix possible wild pointer when handling abort command

2016-12-04 Thread Baolin Wang
When current command was supposed to be aborted, host will free the command
in handle_cmd_completion() function. But it might be still referenced by
xhci->current_cmd, which need to set NULL.

Signed-off-by: Baolin Wang <baolin.w...@linaro.org>
---
This patch is based on Lu Baolu's new fix patch:
usb: xhci: fix possible wild pointer
https://www.spinics.net/lists/linux-usb/msg150219.html
---
 drivers/usb/host/xhci-ring.c |5 -
 1 file changed, 4 insertions(+), 1 deletion(-)

diff --git a/drivers/usb/host/xhci-ring.c b/drivers/usb/host/xhci-ring.c
index 62dd1c7..9965a4c 100644
--- a/drivers/usb/host/xhci-ring.c
+++ b/drivers/usb/host/xhci-ring.c
@@ -1362,8 +1362,11 @@ static void handle_cmd_completion(struct xhci_hcd *xhci,
 */
if (cmd_comp_code == COMP_CMD_ABORT) {
xhci->cmd_ring_state = CMD_RING_STATE_STOPPED;
-   if (cmd->status == COMP_CMD_ABORT)
+   if (cmd->status == COMP_CMD_ABORT) {
+   if (xhci->current_cmd == cmd)
+   xhci->current_cmd = NULL;
goto event_handled;
+   }
}
 
cmd_type = TRB_FIELD_TO_TYPE(le32_to_cpu(cmd_trb->generic.field[3]));
-- 
1.7.9.5

--
To unsubscribe from this list: send the line "unsubscribe linux-usb" in
the body of a message to majord...@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html


Re: [RFC] usb: host: xhci: Remove the watchdog timer and use command timer to watch stop endpoint command

2016-11-30 Thread Baolin Wang
Hi Baolu,

On 1 December 2016 at 13:45, Lu Baolu <baolu...@linux.intel.com> wrote:
> Hi,
>
> On 11/30/2016 05:02 PM, Baolin Wang wrote:
>> If the hardware never responds to the stop endpoint command, the
>> URBs will never be completed, and we might hang the USB subsystem.
>> The original watchdog timer is used to watch if one stop endpoint
>> command is timeout, if timeout, then the watchdog timer will set
>> XHCI_STATE_DYING, try to halt the xHCI host, and give back all
>> pending URBs.
>>
>> But now we already have one command timer to control command timeout,
>> thus we can also use the command timer to watch the stop endpoint
>> command, instead of one duplicate watchdog timer which need to be
>> removed.
>>
>> Meanwhile we don't need the 'stop_cmds_pending' flag to identy if
>> this is the last stop endpoint command of one endpoint. Since we
>> can make sure we only set one stop endpoint command for one endpoint
>> by 'EP_HALT_PENDING' flag in xhci_urb_dequeue() function. Thus remove
>> this flag.
>
> I am afraid you can't do this. "stop_cmds_pending" was added
> to fix the problem described in the comments that you want to
> remove. But I didn't find any fix of this problem in your patch.

Now we can not pending another stop endpoint command for the same one
endpoint, since will check 'EP_HALT_PENDING' flag in
xhci_urb_dequeue() function to avoid this. But after some
investigation, I think I missed the stop endpoint command in
xhci_stop_device() which did not check the 'EP_HALT_PENDING' flag,
maybe need to add 'EP_HALT_PENDING' flag checking in
xhci_stop_device() function. DId I miss something else? Thanks.

>
> - * The timer may also fire if the host takes a very long time to respond to 
> the
> - * command, and the stop endpoint command completion handler cannot delete 
> the
> - * timer before the timer function is called.  Another endpoint cancellation 
> may
> - * sneak in before the timer function can grab the lock, and that may queue
> - * another stop endpoint command and add the timer back.  So we cannot use a
> - * simple flag to say whether there is a pending stop endpoint command for a
> - * particular endpoint.
> - *
> - * Instead we use a combination of that flag and a counter for the number of
> - * pending stop endpoint commands.  If the timer is the tail end of the last
> - * stop endpoint command, and the endpoint's command is still pending, we 
> assume
> - * the host is dying.
>
> Best regards,
> Lu Baolu
>
>>
>> We also need to clean up the command queue before trying to halt the
>> xHCI host in xhci_stop_endpoint_command_timeout() function.
>>
>> Signed-off-by: Baolin Wang <baolin.w...@linaro.org>
>



-- 
Baolin.wang
Best Regards
--
To unsubscribe from this list: send the line "unsubscribe linux-usb" in
the body of a message to majord...@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html


Re: [RFC] usb: host: xhci: Remove the watchdog timer and use command timer to watch stop endpoint command

2016-11-30 Thread Baolin Wang
On 1 December 2016 at 14:04, Baolin Wang <baolin.w...@linaro.org> wrote:
> Hi Baolu,
>
> On 1 December 2016 at 13:45, Lu Baolu <baolu...@linux.intel.com> wrote:
>> Hi,
>>
>> On 11/30/2016 05:02 PM, Baolin Wang wrote:
>>> If the hardware never responds to the stop endpoint command, the
>>> URBs will never be completed, and we might hang the USB subsystem.
>>> The original watchdog timer is used to watch if one stop endpoint
>>> command is timeout, if timeout, then the watchdog timer will set
>>> XHCI_STATE_DYING, try to halt the xHCI host, and give back all
>>> pending URBs.
>>>
>>> But now we already have one command timer to control command timeout,
>>> thus we can also use the command timer to watch the stop endpoint
>>> command, instead of one duplicate watchdog timer which need to be
>>> removed.
>>>
>>> Meanwhile we don't need the 'stop_cmds_pending' flag to identy if
>>> this is the last stop endpoint command of one endpoint. Since we
>>> can make sure we only set one stop endpoint command for one endpoint
>>> by 'EP_HALT_PENDING' flag in xhci_urb_dequeue() function. Thus remove
>>> this flag.
>>
>> I am afraid you can't do this. "stop_cmds_pending" was added
>> to fix the problem described in the comments that you want to
>> remove. But I didn't find any fix of this problem in your patch.
>
> Now we can not pending another stop endpoint command for the same one
> endpoint, since will check 'EP_HALT_PENDING' flag in
> xhci_urb_dequeue() function to avoid this. But after some
> investigation, I think I missed the stop endpoint command in
> xhci_stop_device() which did not check the 'EP_HALT_PENDING' flag,
> maybe need to add 'EP_HALT_PENDING' flag checking in
> xhci_stop_device() function. DId I miss something else? Thanks.

Sorry, wait, we will wait for the stop endpoint command finished in
xhci_stop_device() function. So we don't need check 'EP_HALT_PENDING'
flag as the orignal code did.

-- 
Baolin.wang
Best Regards
--
To unsubscribe from this list: send the line "unsubscribe linux-usb" in
the body of a message to majord...@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html


Re: [RFC] usb: host: xhci: Remove the watchdog timer and use command timer to watch stop endpoint command

2016-12-01 Thread Baolin Wang
On 1 December 2016 at 15:44, Lu Baolu <baolu...@linux.intel.com> wrote:
> Hi,
>
> On 12/01/2016 03:35 PM, Baolin Wang wrote:
>> On 1 December 2016 at 14:35, Lu Baolu <baolu...@linux.intel.com> wrote:
>>> Hi,
>>>
>>> On 12/01/2016 02:04 PM, Baolin Wang wrote:
>>>> Hi Baolu,
>>>>
>>>> On 1 December 2016 at 13:45, Lu Baolu <baolu...@linux.intel.com> wrote:
>>>>> Hi,
>>>>>
>>>>> On 11/30/2016 05:02 PM, Baolin Wang wrote:
>>>>>> If the hardware never responds to the stop endpoint command, the
>>>>>> URBs will never be completed, and we might hang the USB subsystem.
>>>>>> The original watchdog timer is used to watch if one stop endpoint
>>>>>> command is timeout, if timeout, then the watchdog timer will set
>>>>>> XHCI_STATE_DYING, try to halt the xHCI host, and give back all
>>>>>> pending URBs.
>>>>>>
>>>>>> But now we already have one command timer to control command timeout,
>>>>>> thus we can also use the command timer to watch the stop endpoint
>>>>>> command, instead of one duplicate watchdog timer which need to be
>>>>>> removed.
>>>>>>
>>>>>> Meanwhile we don't need the 'stop_cmds_pending' flag to identy if
>>>>>> this is the last stop endpoint command of one endpoint. Since we
>>>>>> can make sure we only set one stop endpoint command for one endpoint
>>>>>> by 'EP_HALT_PENDING' flag in xhci_urb_dequeue() function. Thus remove
>>>>>> this flag.
>>>>> I am afraid you can't do this. "stop_cmds_pending" was added
>>>>> to fix the problem described in the comments that you want to
>>>>> remove. But I didn't find any fix of this problem in your patch.
>>>> Now we can not pending another stop endpoint command for the same one
>>>> endpoint, since will check 'EP_HALT_PENDING' flag in
>>>> xhci_urb_dequeue() function to avoid this. But after some
>>>> investigation, I think I missed the stop endpoint command in
>>>> xhci_stop_device() which did not check the 'EP_HALT_PENDING' flag,
>>>> maybe need to add 'EP_HALT_PENDING' flag checking in
>>>> xhci_stop_device() function. DId I miss something else? Thanks.
>>> Consider below three threads running on different CPUs at the same time.
>>>
>>> Thread A: xhci_handle_cmd_stop_ep()  --- in interrupt handler
>>> Thread B: xhci_stop_endpoint_command_timeout() --- timer expired
>>> Thread C: xhci_urb_dequeue --- called by usb core
>>>
>>> They are serialized by xhci->lock. Let's consider below sequence:
>>>
>>> Thread A:
>>> - delete xhci->cmd_timer), but will fail due to Thread B.
>>> - clear EP_HALT_PENDING bit
>>>
>>> Thread B:
>>> - halt the host controller
>>>
>>> Thread C:
>>> - set EP_HALT_PENDING bit
>>> - enqueue another stop endpoint command
>>> - add the timer back
>> Ah, thanks for you comments.
>> If thread B halted the host, then the thread C xhci_urb_dequeue() will
>> check host state failed, then just return and can not set another stop
>> endpoint command.
>
> Not so simple. Thread B will release xhci->lock before xhci_halt().

Yes.

>
>> But from your example, I think your meaning is we
>> should not halt the host by thread B, since we have handled the stop
>> endpoint command event.
>>
>> So I think we need to check the xhci command of this stop endpoint
>> command in xhci_stop_endpoint_command_timeout(), if the xhci command
>> of this stop endpoint command is not in the command list (which means
>> the stop endpoint command event has been handled), then just return
>> and do not halt the controller. Right?
>>
>
> I'd like suggest you to put this change into a separated patch.
> It's actually a different topic from the main purpose of this patch.

OK, I will. Thanks for your comments.

-- 
Baolin.wang
Best Regards
--
To unsubscribe from this list: send the line "unsubscribe linux-usb" in
the body of a message to majord...@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html


Re: [RFC] usb: host: xhci: Remove the watchdog timer and use command timer to watch stop endpoint command

2016-11-30 Thread Baolin Wang
On 1 December 2016 at 14:35, Lu Baolu <baolu...@linux.intel.com> wrote:
> Hi,
>
> On 12/01/2016 02:04 PM, Baolin Wang wrote:
>> Hi Baolu,
>>
>> On 1 December 2016 at 13:45, Lu Baolu <baolu...@linux.intel.com> wrote:
>>> Hi,
>>>
>>> On 11/30/2016 05:02 PM, Baolin Wang wrote:
>>>> If the hardware never responds to the stop endpoint command, the
>>>> URBs will never be completed, and we might hang the USB subsystem.
>>>> The original watchdog timer is used to watch if one stop endpoint
>>>> command is timeout, if timeout, then the watchdog timer will set
>>>> XHCI_STATE_DYING, try to halt the xHCI host, and give back all
>>>> pending URBs.
>>>>
>>>> But now we already have one command timer to control command timeout,
>>>> thus we can also use the command timer to watch the stop endpoint
>>>> command, instead of one duplicate watchdog timer which need to be
>>>> removed.
>>>>
>>>> Meanwhile we don't need the 'stop_cmds_pending' flag to identy if
>>>> this is the last stop endpoint command of one endpoint. Since we
>>>> can make sure we only set one stop endpoint command for one endpoint
>>>> by 'EP_HALT_PENDING' flag in xhci_urb_dequeue() function. Thus remove
>>>> this flag.
>>> I am afraid you can't do this. "stop_cmds_pending" was added
>>> to fix the problem described in the comments that you want to
>>> remove. But I didn't find any fix of this problem in your patch.
>> Now we can not pending another stop endpoint command for the same one
>> endpoint, since will check 'EP_HALT_PENDING' flag in
>> xhci_urb_dequeue() function to avoid this. But after some
>> investigation, I think I missed the stop endpoint command in
>> xhci_stop_device() which did not check the 'EP_HALT_PENDING' flag,
>> maybe need to add 'EP_HALT_PENDING' flag checking in
>> xhci_stop_device() function. DId I miss something else? Thanks.
>
> Consider below three threads running on different CPUs at the same time.
>
> Thread A: xhci_handle_cmd_stop_ep()  --- in interrupt handler
> Thread B: xhci_stop_endpoint_command_timeout() --- timer expired
> Thread C: xhci_urb_dequeue --- called by usb core
>
> They are serialized by xhci->lock. Let's consider below sequence:
>
> Thread A:
> - delete xhci->cmd_timer), but will fail due to Thread B.
> - clear EP_HALT_PENDING bit
>
> Thread B:
> - halt the host controller
>
> Thread C:
> - set EP_HALT_PENDING bit
> - enqueue another stop endpoint command
> - add the timer back

Ah, thanks for you comments.
If thread B halted the host, then the thread C xhci_urb_dequeue() will
check host state failed, then just return and can not set another stop
endpoint command. But from your example, I think your meaning is we
should not halt the host by thread B, since we have handled the stop
endpoint command event.

So I think we need to check the xhci command of this stop endpoint
command in xhci_stop_endpoint_command_timeout(), if the xhci command
of this stop endpoint command is not in the command list (which means
the stop endpoint command event has been handled), then just return
and do not halt the controller. Right?

-- 
Baolin.wang
Best Regards
--
To unsubscribe from this list: send the line "unsubscribe linux-usb" in
the body of a message to majord...@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html


Re: [RFC] usb: host: xhci: Remove the watchdog timer and use command timer to watch stop endpoint command

2016-11-30 Thread Baolin Wang
On 30 November 2016 at 22:09, Mathias Nyman
<mathias.ny...@linux.intel.com> wrote:
> On 30.11.2016 11:02, Baolin Wang wrote:
>>
>> If the hardware never responds to the stop endpoint command, the
>> URBs will never be completed, and we might hang the USB subsystem.
>> The original watchdog timer is used to watch if one stop endpoint
>> command is timeout, if timeout, then the watchdog timer will set
>> XHCI_STATE_DYING, try to halt the xHCI host, and give back all
>> pending URBs.
>>
>> But now we already have one command timer to control command timeout,
>> thus we can also use the command timer to watch the stop endpoint
>> command, instead of one duplicate watchdog timer which need to be
>> removed.
>>
>> Meanwhile we don't need the 'stop_cmds_pending' flag to identy if
>> this is the last stop endpoint command of one endpoint. Since we
>> can make sure we only set one stop endpoint command for one endpoint
>> by 'EP_HALT_PENDING' flag in xhci_urb_dequeue() function. Thus remove
>> this flag.
>>
>> We also need to clean up the command queue before trying to halt the
>> xHCI host in xhci_stop_endpoint_command_timeout() function.
>
>
> This isn't a bad idea.
>
> There are anyway some corner cases and details that need to be
> checked, such as suspend (which will clear the command queue), module unload
> and abrupt host removal (like pci hotplug removal of host controller)
> we need to make sure we can trust the command timer to always return the
> canceled URB

Yes, you are right, we need to check these carefully.

Suspend process, module unload and abrupt host removal, they all will
issue usb_disconnect() firstly before clear the command queue, it will
check URBs for every endpoint by
usb_disconnect()--->usb_disable_device()--->usb_disable_endpoint(),
which will make sure every URBs of endpoints will be cancelled by the
stop endpoint command responding or the timeout function of stop
endpoint command (xhci_stop_endpoint_command_timeout()) in
usb_hcd_flush_endpoint(). From that point, we can make sure the
command timer will be useful to handle stop endpoint command timeout.
Please correct me if I said something wrong. Thanks.

-- 
Baolin.wang
Best Regards
--
To unsubscribe from this list: send the line "unsubscribe linux-usb" in
the body of a message to majord...@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html


<    1   2   3   4   5   6   >