Petr Cvek <petr.c...@tul.cz> writes:

Hi Petr,

> I found a few problems with the PXA27x UDC.
>
>       usb_function_activate() in drivers/usb/gadget/composite.c
>
> does spin_lock_irqsave() and then calls 
>
>       gadget->ops->pullup() in drivers/usb/gadget/udc/core.c
>
> which is set to pxa_udc_pullup(), which should be called not in interrupt
>
>       /**
>        * pxa_udc_pullup - Offer manual D+ pullup control
>        * @_gadget: usb gadget using the control
>        * @is_active: 0 if disconnect, else connect D+ pullup resistor
>        * Context: !in_interrupt()
>        *
>        * Returns 0 if OK, -EOPNOTSUPP if udc driver doesn't handle D+ pullup
>        */
>
> This finally causes fail at
>
>       udc_enable() in drivers/usb/gadget/udc/pxa27x_udc.c
>       
> at code
>
>       /*
>        * Caller must be able to sleep in order to cope with startup transients
>        */
>       msleep(100);
>
> with a following error (with CONFIG_DEBUG_PREEMPT on):
>
>       BUG: scheduling while atomic: v4l_id/360/0x00000002
>
> With the msleep changed to mdelay, the code (specified as !in_interrupt()) 
> seems to work fine
> (after torture reloads). Can the caller (udc core) be changed to be able to
> sleep?

This question is for Felipe. From the several years back when I wrote this code
I think it was granted that the pullup() callback was not in interrupt context,
but Felipe knows better.

> Second bug was discovered by Robert Jarzmik during discussion in
Please go ahead and submit a patch.

> And as we talking about it, is this return correct?
I think so.

>       if (of_have_populated_dt()) {
>               udc->transceiver =
>                       devm_usb_get_phy_by_phandle(udc->dev, "phys", 0);
>
>               if (IS_ERR(udc->transceiver))
>                       return PTR_ERR(udc->transceiver);
>       } else {
>               udc->transceiver = usb_get_phy(USB_PHY_TYPE_USB2);
>       }
>
> One branch returns on error and second one is fine, udc->transceiver then can 
> hold an error,
> but this is fine for the rest of driver (tested). Question is does it have to 
> return from a first
> branch (e.g. my device does not have phy)?
In the devicetree context (first branch), even if you don't have a phy, you'll
instanciate a "nop" phy, ie. "usb-nop-xceiv". From a hardware perspective, you
have a phy, it's just that you don't have to do anything from a software
perspective to activate your phy.

In the platform_data context (second branch), an error is the common path, as
there is no phy in many old platforms, and pxa27x are old ... hence no check of
error.

> And finally it seems definitions from drivers/usb/gadget/udc/pxa27x_udc.c are 
> duplicated:
>
>       static void udc_enable(struct pxa_udc *udc);
>       static void udc_disable(struct pxa_udc *udc);
>
> I will send patch series as soon as we agree on solutions.
Excellent.

Cheers.

-- 
Robert
--
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

Reply via email to