On Tue, Feb 18, 2003, Greg KH <[EMAIL PROTECTED]> wrote:
> On Tue, Feb 18, 2003 at 08:59:15AM -0800, David Brownell wrote:
> > Greg KH wrote:
> > >
> > >Yes, this is a problem, the module can be unloaded and then the
> > >completion fuction can be called.
> > 
> > How?  I don't see it.  Unless the driver completely violates
> > basic rules like implementing disconnect() correctly, which
> > will break more than just module unloading.
> 
> Hm, let me think about this some more before responding...
> 
> > >   I'm trying to fix up the usb device reference counting
> > >logic right now and running into issues where host controllers try to
> > >access urbs after their devices have been removed from the system :(
> > 
> > Not supposed to happen ... when they call giveback(), that's supposed to
> > mean they've forgotten about that URB.  Is it buggy disconnect() logic,
> > or some HCD calling giveback too early?
> 
> I'm seeing uhci_irq() get called for an urb that belongs to a usb device
> that has already been disconnected.  Things go wrong when
> uhci_transfer_result() is called, which calls usb_release_bandwidth()
> which expects dev->bus to be a valid pointer.  I thought that after
> deallocate() is called on the bus for the device, everything would be
> cleaned up.

This is a reference counting problem.

In 2.4, uhci.c holds a reference to the device until after it's done
calling the completion handler.

Now in 2.5, the hcd layer doesn't hold that reference anymore it seems.

That should be fixed.

> Here's the patch to the usb core that shows this quite nicely:
> 
> 
> ===== usb.c 1.190 vs edited =====
> --- 1.190/drivers/usb/core/usb.c      Sun Feb 16 05:48:02 2003
> +++ edited/usb.c      Sun Feb 16 09:03:33 2003
> @@ -750,10 +750,7 @@
>       if (!udev)
>               return;
>  
> -     if (udev->bus && udev->bus->op && udev->bus->op->deallocate)
> -             udev->bus->op->deallocate(udev);
>       usb_destroy_configuration (udev);
> -     usb_bus_put (udev->bus);
>       kfree (udev);
>  }
>  
> @@ -820,6 +817,7 @@
>  void usb_disconnect(struct usb_device **pdev)
>  {
>       struct usb_device * dev = *pdev;
> +     struct usb_bus *bus;
>       int i;
>  
>       if (!dev)
> @@ -853,6 +851,17 @@
>               usbfs_remove_device(dev);
>       }
>       device_unregister(&dev->dev);
> +
> +     /* Detach the bus from the device right now, as it's no longer a
> +      * valid link.  This helps for drivers that keep a reference to
> +      * the device around for a while if userspace holds a device
> +      * open.  It will cause all further urb submissions to fail,
> +      * which is what we want to have happen. */
> +     bus = dev->bus;
> +     if (bus && bus->op && bus->op->deallocate)
> +             bus->op->deallocate(dev);
> +     dev->bus = NULL;
> +     usb_bus_put (bus);
>  
>       /* Decrement the reference count, it'll auto free everything when */
>       /* it hits 0 which could very well be now */
> 
> 
> 
> I have a patch to the usb serial code that tests this logic out by
> holding a reference to the usb device structure while a port is opened
> by a user.  That way, if the device disappears, then all writes and
> reads get a -ENODEV, and when the last consumer leaves the driver, the
> device is finally deleted from memory properly.  This seems to solve the
> nasty race conditions that people have been having with the usb-serial
> drivers lately.
> 
> Time to test this out on ohci to see how well it works...

I think you're solving the symptom, not the problem.

JE



-------------------------------------------------------
This sf.net email is sponsored by:ThinkGeek
Welcome to geek heaven.
http://thinkgeek.com/sf
_______________________________________________
[EMAIL PROTECTED]
To unsubscribe, use the last form field at:
https://lists.sourceforge.net/lists/listinfo/linux-usb-devel

Reply via email to