Re: [RFC] xhci: Let completion handlers run before rings are restarted.

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

 



On Mon, Jun 04, 2012 at 03:08:06PM -0400, Alan Stern wrote:
> On Mon, 4 Jun 2012, Sarah Sharp wrote:
> 
> > This patch changes the xHCI ring handling code to allow the URB
> > completion handler to run before ringing the doorbell on an endpoint
> > ring.  This means adding a new flag to prevent the doorbell ring
> > (EP_STAY_HALTED), to avoid a race condition with the URB completion
> > handler and a completing Set TR Dequeue Pointer command (which will
> > restart the ring).  The new flag temporarily stops the ring until the
> > URB completion function has a chance to cancel any pending URBs.  That
> > will set a different cancellation pending flag, which will also halt the
> > endpoint ring.
> > 
> > Make sure to set the new EP_STAY_HALTED flag before calling
> > xhci_cleanup_halted_endpoint().  That function will queue a Set TR
> > Dequeue command, which will ring the doorbell and restart the ring after
> > it completes.  We need to make sure that the URB completion handlers
> > have a chance to run before the ring is restarted.
> 
> I really don't understand the structure of your driver, but this sounds 
> like it's more complicated than necessary.

It's not really that complex.  But yes, I agree that the xHCI ring
handling code is pretty hairy, so this patch probably looks complex.

> The general approach for 
> handling a stopped endpoint ring should be:
> 
> 	Give back all the URBs that are complete;
> 
> 	Clean up the ring;
> 
> 	Restart it if any URBs remain queued.

I can't give back URBs before cleaning up the ring because finish_td()
sets several variables in the xhci_virt_endpoint that the cancellation
code uses to move the dequeue pointer.  That code perhaps somewhat easy
to push upwards and duplicate, but...

The real reason I want to keep this patch as coded is that I really
don't want to change the behavior of the order of the URB completion WRT
the ring cleanup and cancellation code.  The cleanup and cancellation
code is really complicated, and I would have to spend a month working
out all the code paths that a behavioral change would touch.

> As far as I can see, the only state you need to keep track of is 
> whether the ring is active, stopping, or stopped.  There shouldn't be 
> any need for an EP_STAY_HALTED flag.

There are several other "stopping" endpoint states, so it's really not
as simple as you make it out to be:

#define SET_DEQ_PENDING         (1 << 0)
#define EP_HALTED               (1 << 1)        /* For stall handling */
#define EP_HALT_PENDING         (1 << 2)        /* For URB cancellation */
/* Transitioning the endpoint to using streams, don't enqueue URBs */
#define EP_GETTING_STREAMS      (1 << 3)
#define EP_HAS_STREAMS          (1 << 4)
/* Transitioning the endpoint to not using streams, don't enqueue URBs */
#define EP_GETTING_NO_STREAMS   (1 << 5)

EP_HALTED means the endpoint is halted due to an error, and it's a
condition that can only be cleared by the USB core, a class driver, or
the xHCI driver if the USB core *should* be clearing the halt but it
doesn't, like for control stalls.

The other four states indicate that the ring is stopped, and the
doorbell cannot be rung for various reasons.  These flags may also
indicate that other resources, such as the endpoint or stream ring
pointers, should not be manipulated.  We can't (and don't) ring the
endpoint doorbell until all of the conditions have been cleared:

 - SET_DEQ_PENDING: A Set TR Dequeue command is pending.
 - EP_HALT_PENDING: A Stop Endpoint command is pending.
 - EP_GETTING_STREAMS: A Configure Endpoint command is pending to add
   streams.
 - EP_GETTING_NO_STREAMS: A Configure Endpoint command is pending to
   remove streams.

So at this point, we're just adding a fifth "stopping" condition that
prevents the endpoint ring from being rung, EP_STAY_HALTED.  I think
adding a new flag will cause less breakage than changing the order of
the URB completion and cancellation/ring clean up.

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


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

  Powered by Linux