# This is a BitKeeper generated patch for the following project:
# Project Name: Linux kernel tree
# This patch format is intended for GNU patch command version 2.5 or higher.
# This patch includes the following deltas:
#                  ChangeSet    1.545   -> 1.546  
#       drivers/usb/core/hcd.h  1.6     -> 1.7    
#        include/linux/usb.h    1.31    -> 1.32   
#       drivers/usb/core/usb.c  1.52    -> 1.53   
#       drivers/usb/host/uhci.c 1.41    -> 1.42   
#
# The following is the BitKeeper ChangeSet Log
# --------------------------------------------
# 02/05/13      [EMAIL PROTECTED]    1.546
# [PATCH] USB device reference counting fix for uhci.c and usb core
# 
# Earlier in the 2.5 development cycle a patch was applied that changed
# the reference counting behaviour for USB devices.
# 
# There are a couple of problems with the change:
# - It made the USB code more complicated as a whole with the introduction
#   of an additional cleanup path for devices. Using the traditional method
#   of reference counting, cleanup is handled implictly
# - It reduces functionality by requiring a callback for all references to
#   the device, but doesn't provide a method of providing callbacks for
#   references. It relies on the hardcoded device driver ->disconnect and
#   HCD ->deallocate method for callbacks
# 
# The traditional method of using reference counting supports as many
# reference users as needed, without complicating it with mandatory
# callbacks to cleanup references.
# 
# The change in 2.5 also only helps catch one subset of programming
# problem in device drivers, the case where it decrements too many times.
# That is of dubious debugging value.
# 
# So, this patch reverts the change and makes the reference counting
# behave like it does in the rest of the kernel as well as how the USB
# code does in 2.4.
# 
# This patch doesn't remove all of the superfluous code. Some drivers,
# like usb-ohci, ohci-hcd and ehci-hcd have some code that is no longer
# needed. I wanted to spend some more time with those drivers since the
# changes weren't as trivial as uhci.c and usb-uhci.c.
# 
# I've tested with uhci and usb-ohci with no adverse effects.
# --------------------------------------------
#
diff -Nru a/drivers/usb/core/hcd.h b/drivers/usb/core/hcd.h
--- a/drivers/usb/core/hcd.h    Mon May 13 15:53:48 2002
+++ b/drivers/usb/core/hcd.h    Mon May 13 15:53:49 2002
@@ -182,9 +182,6 @@
 /* -------------------------------------------------------------------------- */
 
 /* Enumeration is only for the hub driver, or HCD virtual root hubs */
-extern struct usb_device *usb_alloc_dev(struct usb_device *parent,
-       struct usb_bus *);
-extern void usb_free_dev(struct usb_device *);
 extern int usb_new_device(struct usb_device *dev);
 extern void usb_connect(struct usb_device *dev);
 extern void usb_disconnect(struct usb_device **);
diff -Nru a/drivers/usb/core/usb.c b/drivers/usb/core/usb.c
--- a/drivers/usb/core/usb.c    Mon May 13 15:53:49 2002
+++ b/drivers/usb/core/usb.c    Mon May 13 15:53:49 2002
@@ -962,7 +962,8 @@
 
        init_MUTEX(&dev->serialize);
 
-       dev->bus->op->allocate(dev);
+       if (dev->bus->op->allocate)
+               dev->bus->op->allocate(dev);
 
        return dev;
 }
@@ -978,16 +979,8 @@
  */
 void usb_free_dev(struct usb_device *dev)
 {
-       if (in_interrupt ())
-               BUG ();
-       if (!atomic_dec_and_test (&dev->refcnt)) {
-               /* MUST go to zero here, else someone's hanging on to
-                * a device that's supposed to have been cleaned up!!
-                */
-               BUG ();
-       }
-
-       dev->bus->op->deallocate (dev);
+       if (dev->bus->op->deallocate)
+               dev->bus->op->deallocate(dev);
        usb_destroy_configuration (dev);
        usb_bus_put (dev->bus);
        kfree (dev);
@@ -1933,8 +1926,9 @@
                put_device(&dev->dev);
        }
 
-       /* Free up the device itself */
-       usb_free_dev(dev);
+       /* Decrement the reference count, it'll auto free everything when */
+       /* it hits 0 which could very well be now */
+       usb_dec_dev_use(dev);
 }
 
 /**
diff -Nru a/drivers/usb/host/uhci.c b/drivers/usb/host/uhci.c
--- a/drivers/usb/host/uhci.c   Mon May 13 15:53:49 2002
+++ b/drivers/usb/host/uhci.c   Mon May 13 15:53:49 2002
@@ -109,19 +109,6 @@
 #define MAX_URB_LOOP   2048            /* Maximum number of linked URB's */
 
 /*
- * Only the USB core should call uhci_alloc_dev and uhci_free_dev
- */
-static int uhci_alloc_dev(struct usb_device *dev)
-{
-       return 0;
-}
-
-static int uhci_free_dev(struct usb_device *dev)
-{
-       return 0;
-}
-
-/*
  * Technically, updating td->status here is a race, but it's not really a
  * problem. The worst that can happen is that we set the IOC bit again
  * generating a spurios interrupt. We could fix this by creating another
@@ -1882,8 +1869,6 @@
 }
 
 struct usb_operations uhci_device_operations = {
-       allocate:               uhci_alloc_dev,
-       deallocate:             uhci_free_dev,
        get_frame_number:       uhci_get_current_frame_number,
        submit_urb:             uhci_submit_urb,
        unlink_urb:             uhci_unlink_urb,
diff -Nru a/include/linux/usb.h b/include/linux/usb.h
--- a/include/linux/usb.h       Mon May 13 15:53:49 2002
+++ b/include/linux/usb.h       Mon May 13 15:53:49 2002
@@ -426,6 +426,11 @@
        struct usb_device *children[USB_MAXCHILDREN];
 };
 
+/* usb_free_dev can be called anywhere from usb_dec_dev_use */
+extern struct usb_device *usb_alloc_dev(struct usb_device *parent,
+       struct usb_bus *);
+extern void usb_free_dev(struct usb_device *);
+
 /* for when layers above USB add new non-USB drivers */
 extern void usb_scan_devices(void);
 
@@ -455,27 +460,11 @@
  * @dev: the device no longer being referenced
  *
  * Each live reference to a device should be refcounted.
- *
- * Drivers for USB interfaces should normally release such references in
- * their disconnect() methods, and record them in probe().
- *
- * Note that driver disconnect() methods must guarantee that when they
- * return, all of their outstanding references to the device (and its
- * interfaces) are cleaned up.  That means that all pending URBs from
- * this driver must have completed, and that no more copies of the device
- * handle are saved in driver records (including other kernel threads).
  */
 static inline void usb_dec_dev_use (struct usb_device *dev)
 {
-       if (atomic_dec_and_test (&dev->refcnt)) {
-               /* May only go to zero when usbcore finishes
-                * usb_disconnect() processing:  khubd or HCDs.
-                *
-                * If you hit this BUG() it's likely a problem
-                * with some driver's disconnect() routine.
-                */
-               BUG ();
-       }
+       if (atomic_dec_and_test(&dev->refcnt))
+               usb_free_dev(dev);
 }
 
 

_______________________________________________________________

Have big pipes? SourceForge.net is looking for download mirrors. We supply
the hardware. You get the recognition. Email Us: [EMAIL PROTECTED]
_______________________________________________
[EMAIL PROTECTED]
To unsubscribe, use the last form field at:
https://lists.sourceforge.net/lists/listinfo/linux-usb-devel

Reply via email to