On Fri, Mar 30, 2007 at 11:17:28AM +0200, Oliver Neukum wrote: > Am Freitag, 30. M?rz 2007 11:03 schrieb Greg KH: > > On Fri, Mar 30, 2007 at 10:45:26AM +0200, Oliver Neukum wrote: > > > Am Freitag, 30. M?rz 2007 10:39 schrieb Greg KH: > > > > > To solve this with locking would require both CPU A and CPU B to take > > > > > the lock, which means that the urb would have to be submitted with > > > > > GFP_ATOMIC. > > > > > > > > Can't this all be solved with a simple: > > > > > > > > ????????get port spinlock > > > > ????????a = urb->status > > > > ????????write_busy = 0 > > > > ????????unlock spinlock > > > > > > > > In the callback, and in the write path: > > > > > > > > ????????get port spinlock > > > > ????????if write_busy > > > > ????????????????unlock > > > > ????????????????exit > > > > ????????write_busy = 1 > > > > ????????unlock port spinlock > > > > ????????submit_urb > > > > > > > > > > Oops. You are right. That would work. > > > If you think that's simpler, yes it can be done. > > > > Yes, I think that would be both easier to understand, and easier to > > prove correct :) > > However it would not always work out so nicely. > Have a look at this code from usblp: > > timeout = USBLP_WRITE_TIMEOUT; > > rv = wait_event_interruptible_timeout(usblp->wait, > usblp->wcomplete || !usblp->present , timeout); > if (rv < 0) > return writecount ? writecount : -EINTR;
Well, usblp incorrectly (in my opinion) tries to return the status of every urb to userspace. I'm still not quite sure why it needs to do that, and we can't just throw a ton of urbs at the device and then walk away. It's not like userspace does much if we report an error on the exact packet that fails, vs a packet later on, right? > and > > static void usblp_bulk_write(struct urb *urb) > { > struct usblp *usblp = urb->context; > > if (unlikely(!usblp || !usblp->dev || !usblp->used)) > return; > if (unlikely(!usblp->present)) > goto unplug; > if (unlikely(urb->status)) > warn("usblp%d: nonzero read/write bulk status received: %d", > usblp->minor, urb->status); > usblp->wcomplete = 1; > unplug: > wake_up_interruptible(&usblp->wait); > } > > It has the same issue. The correct code is: > > if (unlikely(urb->status)) > warn("usblp%d: nonzero read/write bulk status received: %d", > usblp->minor, urb->status); > smp_mb(); > usblp->wcomplete = 1; > unplug: > wake_up_interruptible(&usblp->wait); > > This can'be solved with a simple spinlock, as wait_event() can sleep. > Neither is simply returning 0 an option. It would mean EOF. > Really somebody went to some effort to find a lockless solution and > did well, he just didn't figure out of order execution units. You'd destroy > that. I think it really comes down to the problem of checking the urb status flag. I _REALLY_ want to get rid of that field and not have drivers us it at all. I would like to pass the value of the status flag to the urb callback directly, and only have the status field be used by the host controllers. The last time I looked into implementing this, I think the UHCI driver had some 'issues' with how it would work, or maybe it was EHCI, sorry it was a few years ago. However, if we are able to fix that, and never let drivers touch that field, then the large majority of these kinds of problems will go away, right? thanks, greg k-h ------------------------------------------------------------------------- Take Surveys. Earn Cash. Influence the Future of IT Join SourceForge.net's Techsay panel and you'll get the chance to share your opinions on IT & business topics through brief surveys-and earn cash http://www.techsay.com/default.php?page=join.php&p=sourceforge&CID=DEVDEV _______________________________________________ linux-usb-devel@lists.sourceforge.net To unsubscribe, use the last form field at: https://lists.sourceforge.net/lists/listinfo/linux-usb-devel