> I'm going to guess that you will object to the race condition that exists
> between the time the flag is tested and the URB is submitted.  Yes,
> there's a race.  But it is unavoidable, unless you want to surround every
> call to the usb core with a spinlock_irq or the equivalent.  And in any

That's exactly what's needed. But why irq? Disconnect() runs from task
context.

> case it doesn't matter, since we only want to guarantee that no URB will
> be submitted after disconnect() _returns_.  We don't need to (and in fact
> cannot) guarantee that no URB will be submitted after disconnect() _is
> called_.

Right. But why should this matter? If there's a race there's a race.
Unless you can guarantee that disconnect() setting a flag for disconnection
and an urb being submitted or a synchronous helper running don't race
it's a bug.

> Perhaps the real question is: Do we need to guarantee that no URBs will
> remain outstanding after disconnect() returns?  This seems to be what you

        if (!(dev = urb->dev) || !dev->bus || dev->devnum <= 0)
                return -ENODEV;
        if (!(op = dev->bus->op) || !op->submit_urb)
                return -ENODEV;

from usb_submit_urb(). This is deadly. Unlinking after disconnect() is
deadly as well.
But for an indeterminate amount of time after usb_submit_urb is called,
it's dangerous. Shortly, it's safe only if they are dead.

> are getting at.  Unfortunately, I haven't seen written down anywhere
> exactly what conditions the driver needs to satisfy.  It would be nice if
> this sort of thing could be added to the documentation somewhere.

Yes.

> > > Here's a suggestion that would help all existing usb drivers.  Add an
> > > additional parameter to usb_control_msg (and the other synchronous
> > > message subroutines as well) that takes a struct urb **.  The
> > > subroutines can use it to store a pointer to the dynamically allocated
> > > URB, so that the driver would have the ability to cancel the URB
> > > whenever it wanted.
> >
> > No, not whenever, only after the synchronous call has set the pointer.
> > Which you cannot know.
>
> I'm afraid you're right about that.  Maybe the synchronous call routines
> should be eliminated entirely.

Now, a week before freeze?

> > I think that it won't work. The correct sequence is:
> > ...
> > down()
> > if (device_not_disconnected)
> >     synchronous_call()
> > up()
> > ...
> >
> > and in disconnect():
> >
> > down()
> > mark_as_disconnected()
> > up()
> >
> > As you can see, the check for disconnection cannot be in the synchronous
> > helper.
>
> I'm not clear on how this helps.  Yes, if you do it this way then you
> never have to cancel a synchronous message.  But instead you force
> disconnect() to hang around waiting until the synchronous message
> completes.  Is that really any better?  And if it is, why not have

Disconnect() may block. As long as there's an upper limit, it's safe.

> disconnect() do the mark_as_disconnected() before doing the down()?

Why not. I see no real difference.

> > The solution you suggest only works if you can ensure that the
> > synchronous call has given you a handle to unlink the urb before
> > disconnect() runs. To do so requires the synchronous helper to be called
> > with a lock against disconnect() already held.
>
> Well no, I only need to insure that the synchronous call has given me a
> handle before disconnect() _returns_.  But I agree that it's a problem.

You cannot do that as well. Furthermore you must not call a synchronous
call after disconnect() has returned. The device pointer you pass is
dangerous.

> My feeling is that we need either to rethink the synchronous calls or get
> rid of them altogether.  There's another aspect of usb-storage that runs

It's a week till feature freeze.

> into difficulties with regard to synchronous calls.  The problem is that
> most of the things that usb-storage does come about because of calls from
> the scsi layer, and most of these calls are protected by a timeout and
> abort handler.  But not all of them are, and also there are a few things
> usb-storage does on its own behalf (initialization, mostly) that also do
> not have the protection of an abort handler.
>
> As a result, we have to be able to abort some calls on demand but not
> others, and we have to use timeouts for some calls but not others.  It's a
> real mess, and we haven't gotten it straightened out yet.  My vote goes
> for making things as uniform as possible, but Matt Dharm doesn't agree.
> He has said that the driver should use different code paths for the
> different situations.  Maybe this discussion about the problems with
> synchronous calls will make us rethink the whole question.

I am afraid I don't know the storage driver well enough to comment on that.

        Regards
                Oliver



-------------------------------------------------------
This sf.net email is sponsored by: Influence the future
of Java(TM) technology. Join the Java Community
Process(SM) (JCP(SM)) program now.
http://ads.sourceforge.net/cgi-bin/redirect.pl?sunm0002en

_______________________________________________
[EMAIL PROTECTED]
To unsubscribe, use the last form field at:
https://lists.sourceforge.net/lists/listinfo/linux-usb-devel

Reply via email to