David:

Your reply to my last message was so far off-base with respect to the 
ideas I had intended to convey, I can only assume there's been a serious 
communications failure.  I'll do my best to clarify things below and show 
where you went astray.


My main point: There's no need to use locktree() in hub_events() or 
usb_reset_device().  (Although your latest changes didn't actually add 
locktree to usb_reset_device, there was a comment about doing it.)

Basically, there are no situations where using locktree in either of those 
two places would provide any advantage, although there are times when 
doing so would cause unnecessary delays.  If you disagree, then try to 
provide an example where using locktree in either of those routines would 
work but using down(&dev->serialize) wouldn't!


On Fri, 30 Jul 2004, David Brownell wrote:

> > Suppose an upstream hub is locked for some reason while another thread 
> > wants to work on a downstream device, either to reset it or to do event 
> > processing (if the downstream device is another hub):
> 
> Hubs aren't the only, or main, thing to lock ... see the other patch.

[I'll vent a little frustration just in this one place...  Why did you say
that hubs aren't the only thing to lock?  It's certainly true, but how is
it relevant to what I was saying?  Are you referring to the "upstream hub"
I mentioned?  If so then your remark is pointless -- obviously any
upstream device _must_ be a hub.  If not, then are you referring to my
parenthetical comment about the downstream device being a hub?  Again,
that would be pointless -- I'm specifically talking about the changes you
made to khubd, which only does event processing on hubs!]

Remember that the whole point of my discussion was to examine the worth of
using locktree in usb_reset_device() and hub_events(), and the only
situation in which locktree(usbdev) differs from down(&usbdev->serialize)  
is when some hub upstream from usbdev is already locked.

> Remember that the khubd change was a "minimal change" patch;
> I think you want a performance-tuned one!

Not at all.  And a "minimal change" patch wouldn't have changed
down(&hdev->serialize) in hub_events() to locktree(hdev)!


> >     2.      The upstream hub is being suspended.  Your recursive suspend
> >     code will lock the downstream device when it gets there.  So
> 
> That is, two tasks concurrently changing power/state needing to
> coordinate with each other.  In this case they're both suspending,
> and the "topmost" suspend started first.

"... two tasks ... both suspending..."?  Where did that come from?  I was 
talking about two threads, one suspending an upstream hub, then other 
running either usb_reset_device() on a downstream device or else running 
hub_events on a downstream hub.  Your later comments seem to include the 
same mistaken assumption that I was talking about two threads both 
suspending or resuming.

> >     it doesn't matter what sort of locking is used by the other
> >     thread working on the device; both locktree and regular locking
> >     will have to wait until the device is suspended.
> 
> I don't know what you mean by "regular", but that's certainly
> not true of what's (not) in RC2 ... :)

By "regular" locking I mean down(&usbdev->serialize) or its equivalent.  
In other words, the kind of locking that was in hub_events() before you
changed it to use locktree.


> >     3.      The upstream hub is being resumed.  Under these circumstances
> >     it's unlikely that anyone would want to do anything to the
> >     downstream device since it must still be suspended, but never
> >     mind that. 
> 
> >     Resume processing will recursively lock devices 
> >     below the upstream hub as they are resumed.  The downstream
> >     device will get locked in its turn, so again it doesn't matter
> >     whether the other thread uses locktree or regular locking.
> 
> Erm, and what is this second thread doing that sequence wouldn't matter?

I didn't say that _sequencing_ wouldn't matter; I said that the _type of
locking_ wouldn't matter.  And as I mentioned above, the second thread
is either doing usb_reset_device() or hub_events().

> Disconnecting ... locktree uses the (newish) spinlock and is failfast for
> all callers, so not that.  Resetting .... the resume needs to finish first,
> not that then.

Come again?

>  Powering off ... ditto, to ensure clean shutdown.
> Suspending ... same.
> 
> That is, the sequence DOES matter, and that's another part of what
> locktree() is delivering.

Of course sequence matters, and NO, locktree does not deliver it any more 
than regular down(&usbdev->serialize) type locking does, apart from 
causing certain races to go one way rather than the other.


> >     4.      The upstream hub is being reset.  Part of the code I added
> >     (probably in one of the patches that Greg hasn't applied yet)
> >     changed usb_reset_device() so that when a hub is reset all of
> >     its children are disconnected first.  Once the downstream
> >     device is gone, the question of whether to use locktree or
> >     regular locking is moot.
> 
> Mostly controlled by the spinlock ... maybe not as much as it
> should be though.  Locktree handles that just fine.

Sure it does.  My point is that regular locking does too, so locktree 
isn't needed.


> >     5.      The upstream hub is processing an overcurrent-change notification
> >     for the port leading to the downstream device.  All khubd does
> >     when this happens is to clear the overcurrent-change feature.
> >     There's no need for the other thread to wait for that to
> >     complete, as locktree would make it do.
> 
> It's not locktree() that makes that specific policy, it's khubd.
> 
> Those (potential) performance issues each could be
> handled by khubd doing down(&hdev->child[i]->serialize)
> and then up(&hdev->serialize) before playing with that
> particular port.  (Enumeration wouldn't quite work that
> way, though, child[i] being NULL.)  But it'd have to get the
> hub lock, with locktree(), at the top of each loop.

Okay, here's a substantial point to consider.

First, notice that it's _not_ okay for khubd to completely drop all locks 
on a hub while processing its events.  There has to be some way for it to 
synchronize when the hub is disconnected.  Until recently this was done 
using the private khubd_semaphore.  I recall you being very keen on the 
idea that this semaphore could now go away and be replaced with 
hdev->serialize.  Have you changed your mind about that?

We could go back to using a private lock instead of ->serialize.  That 
would relieve some of the pressure on locktree.  But why bother when 
there's not really any need to use locktree in hub_events to begin with?


> > In short, I don't see any situations in which using locktree() for hub 
> > event processing or device resets will provide any advantage at all.  But
> > there _are_ situations (2 and 5) in which it will provide useless delays.
> 
> See above; event sequencing is important, and it's easy to drop
> the hub lock earlier on certain event paths.

Let's talk about event sequencing too.  As an example, let's consider
thread A doing a suspend on an upstream hub H while thread B is trying to
reset a downstream device D.  The question is, does using locktree(D) in
thread B give better sequencing than just doing down(&D->serialize)?

        Case 1: B starts its reset before A starts its suspend.  No
        matter which locking scheme B uses, it will succeed immediately.
        Thread A will block when its recursive tree descent reaches D
        until the reset has completed, and A will suspend D then.
        Result: tie score.

        Case 2: B starts its reset after A has started its suspend but
        before A has begun to suspend D.  If B uses locktree then B will
        have to wait until A has finished suspending everything below H
        and releases the lock.  Then B will see that D is suspended and
        the reset will fail.  If B uses regular locking then B will lock
        D and reset it right away.  A will have to wait until the reset
        is complete, then it will suspend D and continue.  Result: with
        regular locking the reset succeeds instead of failing and does so
        more quickly.

        Case 3: B starts its reset after A has suspended D but before A 
        has finished suspending everything below H.  If B uses locktree
        then B will have to wait until A has finished, then B will see
        that D is suspended and the reset will fail.  If B uses regular
        locking then B will lock D right away, will see that D is 
        suspended, and will fail.  Result: with regular locking the reset
        fails right away instead of after a delay.

        Case 4: B starts its reset after A has finished its suspend.  No
        matter which locking scheme B uses, the lock will succeed 
        immediately and then the reset will fail.  Result: tie score.

As you can see, in every case there are no sequencing errors and in no 
case does regular locking do worse than locktree -- but in some cases it 
does better.  Other scenarios in which A is doing a resume or a reset, or 
where B is running hub_events(), all work out similarly.


> > I foresee more problems.  For example, whose responsibility should it 
> > ultimately be to suspend a subtree of nodes in the USB tree -- the driver
> > core's or usbcore's?
> 
> For now, USB ... the driver core doesn't handle this yet.

That was a rhetorical question.  The point I was making (see just below)
is that the driver core can't be expected to handle this in the future,
since it doesn't possess the requisite knowledge.  So usbcore has to do it
both now _and_ in the future.

> > The driver core doesn't have the knowledge to apply 
> > the proper locking.  And what should happen when there are non-USB devices
> > located below a USB node (a SCSI disk for example), who's responsible for 
> > locking them?
> 
> Locking them for what purpose?

I meant to say "suspending them", not "locking them", sorry.  Given that
usbcore must take responsibility for suspending USB devices and can't
delegate it to the driver core, what happens when the device tree
traversal needed for proper suspension goes outside the USB boundary?

Alan Stern



-------------------------------------------------------
This SF.Net email is sponsored by OSTG. Have you noticed the changes on
Linux.com, ITManagersJournal and NewsForge in the past few weeks? Now,
one more big change to announce. We are now OSTG- Open Source Technology
Group. Come see the changes on the new OSTG site. www.ostg.com
_______________________________________________
[EMAIL PROTECTED]
To unsubscribe, use the last form field at:
https://lists.sourceforge.net/lists/listinfo/linux-usb-devel

Reply via email to