Re: XHCI's lock usage on hardirq handler

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

 



On Tue, 29 Nov 2016, Felipe Balbi wrote:

> Hi Greg,
> 
> Greg KH <greg@xxxxxxxxx> writes:
> > On Tue, Nov 29, 2016 at 03:58:57PM +0200, Felipe Balbi wrote:
> >> 
> >> Hi,
> >> 
> >> Greg KH <greg@xxxxxxxxx> writes:
> >> > On Tue, Nov 29, 2016 at 01:48:59PM +0200, Felipe Balbi wrote:
> >> >> 
> >> >> Hi folks,
> >> >> 
> >> >> I've been staring at this part of the code for a while. To make things
> >> >> easier here's the part of XHCI I mean:
> >> >> 
> >> >> > irqreturn_t xhci_irq(struct usb_hcd *hcd)
> >> >> > {
> >> >> > 	struct xhci_hcd *xhci = hcd_to_xhci(hcd);
> >> >> > 	union xhci_trb *event_ring_deq;
> >> >> > 	irqreturn_t ret = IRQ_NONE;
> >> >> > 	dma_addr_t deq;
> >> >> > 	u64 temp_64;
> >> >> > 	u32 status;
> >> >> >
> >> >> > 	spin_lock(&xhci->lock);
> >> >> 
> >> >> considering this is running in hardirq context, this is lock *really*
> >> >> necessary? I mean, could this race with khubd or something else?
> >> >
> >> > It could be a threaded irq, right?
> >> 
> >> except that it isn't :-) Should we handle threaded_irq when we get to it?
> >
> > How do you know it isn't?  Doesn't the -rt patchset turn all of these
> > irqs into threaded irqs automatically without the driver knowing that or
> > not?
> 
> Yes, all IRQs are turned into threaded. You can also do the same with
> threadirqs CMDLINE option. The catch here is that both -RT and
> threadirqs option force IRQF_ONESHOT which will keep IRQs disabled until
> the thread runs, so there shouldn't be any possible races either :-)
> 
> > The driver shouldn't really care either way.
> 
> agreed :-)
> 
> >> > Not that this really matters, it's hard to figure out what this lock
> >> > actually "protects", it seems like "everything for this hcd", which
> >> > seems like a lot, but was probably safest/easiest to get up and running,
> >> > and mirrors what ehci does from what I can tell.
> >> 
> >> The problem is that now locking in xhci is rather convoluted and it
> >> became really difficult to track its usage. I don't mind having a "lock
> >> everything from this controller" lock, but currently the usage is
> >> difficult to track because the lock is apparently sprinkled all over the
> >> place willy-nilly.
> >> 
> >> It lacks proper __releases()/__acquires() annotation where code
> >> *actually* releases the lock and reacquires later. We also have the
> >> inverse: annotation being added to functions which *don't* release and
> >> reacquire locks.
> >> 
> >> IOW, the code is made hard to maintain because of one simple thing :-)
> >
> > Ok, no objection from me to clean it up :)
> 
> alright, thanks
> 
> >> >> My understanding is that this lock is completely unnecessary and it
> >> >> should be safe to remove it. In fact we would have the benefit of
> >> >> removing __releases()/__acquires() from a few places (some of which are
> >> >> wrong, btw!!) and removing the actual spin_unlock(); do_something();
> >> >> spin_lock(); which have been sprinkled in several places.
> >> >
> >> > Drop the lock entirely?  Ok, but what then protects the fields that this
> >> > lock was protecting from being accessed at the same time?  How about the
> >> > host controller removal path?
> >> 
> >> well, for those cases we need locking. But from hardirq handler we don't
> >> need any, right? Unless there's some case where the hardirq handler
> >> itself could race with something else.
> >
> > irq being run on one processor and something else happening on another
> > one that touches the driver?
> 
> and that's exactly my doubt. Is it even possible to have anything racing
> with the hardirq handler in this case? I mean, sure we have khubd. But
> that remains sleeping until an IRQ wakes it up :-)
> 
> Also, from driver removal point of view, we will call free_irq() which
> will call synchronize_irq() and, again, it'll wait for hardirq handler
> to complete.
> 
> So the question I have really is: can XHCI hardirq handler race with
> anything else happening anywhere in any other CPU?

Yes, of course.  It can race with URB submission and cancellation.  Not 
to mention calls to the hub_control routine.

The question of how fine-grained locking should be is a difficult one.  
uhci-hcd, ohci-hcd, and ehci-hcd all use a coarse-grained approach: A
single lock protects everything.  (Before I took over its
maintainership, uhci-hcd was exactly the opposite -- separate spinlocks
for each endpoint and each URB, maybe others, I can't remember.  
Locking order problems.  It looked awful.)

Unless you have a good reason to split up the big lock into multiple 
sub-locks, I say don't worry about it.

Alan Stern

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