Re: Data toggles not reset on "set configuration" for ports handled by "xhci_hcd" driver

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

 



On Tue, Aug 25, 2020 at 02:53:56PM +0300, Mathias Nyman wrote:
> On 25.8.2020 11.00, Martin Thierer wrote:
> >> Can you try the code below? It should force dropping and adding the endpoints
> >> for the intrface(s) of that configuration, and xhci should reset the toggles.
> >>
> >> Completely untested, it compiles :)
> > 
> > Sorry, no, that doesn't work:
> > 
> > xhci_hcd 0000:00:14.0: Trying to add endpoint 0x83 without dropping it.
> > BUG: kernel NULL pointer dereference, address: 0000000000000010
> 
> Ah, I see.
> Endpoints weren't dropped on host side as pointer to the endpoints were cleaned up before this.
> And the code to recover from a failed call got messed up as we removed some stuff it depends on.
> 
> Here's a second version. 
> I'm again not able to test this at all from my current location, so it might fail because
> of some silly mistake, but it compiles..
> 
> This version keeps endpoint pointers intact until endpoints are dropped from hcd side, 
> it also removes the recover path (might need to fix one later) 
> 
> diff --git a/drivers/usb/core/message.c b/drivers/usb/core/message.c
> index 6197938dcc2d..e90e8781f872 100644
> --- a/drivers/usb/core/message.c
> +++ b/drivers/usb/core/message.c
> @@ -1537,9 +1537,21 @@ int usb_reset_configuration(struct usb_device *dev)
>  	 * calls during probe() are fine
>  	 */
>  
> +	/*
> +	 * TEST2 flush and disable endpoints but leave the pointers intact until
> +	 * usb_hcd_alloc_bandwidth() has dropped them from host controller side
> +	 */
>  	for (i = 1; i < 16; ++i) {
> -		usb_disable_endpoint(dev, i, true);
> -		usb_disable_endpoint(dev, i + USB_DIR_IN, true);
> +		if (dev->ep_out[i]) {
> +			dev->ep_out[i]->enabled = 0;
> +			usb_hcd_flush_endpoint(dev, dev->ep_out[i]);
> +			usb_hcd_disable_endpoint(dev, dev->ep_out[i]);
> +		}
> +		if (dev->ep_in[i]) {
> +			dev->ep_in[i]->enabled = 0;
> +			usb_hcd_flush_endpoint(dev, dev->ep_in[i]);
> +			usb_hcd_disable_endpoint(dev, dev->ep_in[i]);
> +		}
>  	}

There's got to be a better way to do this, something that doesn't 
involve so much code duplication.  For instance, maybe we could make 
this routine and usb_set_configuration() both call a new 
__usb_set_config(), with an extra flag telling the routine whether to 
change the interface devices and bindings.

Alan Stern



[Index of Archives]     [Linux Media]     [Linux Input]     [Linux Audio Users]     [Yosemite News]     [Linux Kernel]     [Linux SCSI]     [Old Linux USB Devel Archive]

  Powered by Linux