# 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.596 -> 1.597
# drivers/usb/core/hcd.h 1.4 -> 1.5
# include/linux/usb.h 1.25 -> 1.26
# drivers/usb/core/hub.c 1.21 -> 1.22
# drivers/usb/core/usb.c 1.39 -> 1.40
#
# The following is the BitKeeper ChangeSet Log
# --------------------------------------------
# 02/04/08 [EMAIL PROTECTED] 1.597
# This patch is a more complete fix for the device refcount
# sanity checking and cleanup on device disconnect.
#
# - Splits apart usb_dec_dev_use(), for driver use, and
# usb_free_dev(), for hub/hcd use. Both now have
# kerneldoc, and will BUG() if the refcount and the
# device tree get out of sync. (Except for cleanup of
# root hub init errors, refcount must go to zero only
# at the instant disconnect processing completes.)
#
# - More usbcore-internal function declarations are
# now moved out of <linux/usb.h> into hcd.h
#
# - Driver-accessible refcounting is now inlined; minor
# code shrinkage, it's using atomic inc/dec instructions
# not function calls.
#
# <note from greg k-h, there is still some work to be done with USB device
# reference counting, but this patch is a step in the right direction.>
# --------------------------------------------
#
diff -Nru a/drivers/usb/core/hcd.h b/drivers/usb/core/hcd.h
--- a/drivers/usb/core/hcd.h Mon Apr 8 15:49:08 2002
+++ b/drivers/usb/core/hcd.h Mon Apr 8 15:49:08 2002
@@ -181,6 +181,24 @@
#endif /* CONFIG_PCI */
+/* -------------------------------------------------------------------------- */
+
+/* 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 **);
+
+#ifndef _LINUX_HUB_H
+/* exported to hub driver ONLY to support usb_reset_device () */
+extern int usb_get_configuration(struct usb_device *dev);
+extern void usb_set_maxpacket(struct usb_device *dev);
+extern void usb_destroy_configuration(struct usb_device *dev);
+extern int usb_set_address(struct usb_device *dev);
+#endif /* _LINUX_HUB_H */
+
/*-------------------------------------------------------------------------*/
/*
diff -Nru a/drivers/usb/core/hub.c b/drivers/usb/core/hub.c
--- a/drivers/usb/core/hub.c Mon Apr 8 15:49:08 2002
+++ b/drivers/usb/core/hub.c Mon Apr 8 15:49:08 2002
@@ -29,6 +29,7 @@
#include <asm/uaccess.h>
#include <asm/byteorder.h>
+#include "hcd.h"
#include "hub.h"
/* Wakes up khubd */
diff -Nru a/drivers/usb/core/usb.c b/drivers/usb/core/usb.c
--- a/drivers/usb/core/usb.c Mon Apr 8 15:49:08 2002
+++ b/drivers/usb/core/usb.c Mon Apr 8 15:49:08 2002
@@ -826,49 +826,31 @@
return dev;
}
-// usbcore-internal ...
-// but usb_dec_dev_use() is #defined to this, and that's public!!
-// FIXME the public call should BUG() whenever count goes to zero,
-// the usbcore-internal one should do so _unless_ it does so...
+/**
+ * usb_free_dev - free a usb device structure (usbcore-internal)
+ * @dev: device that's been disconnected
+ * Context: !in_interrupt ()
+ *
+ * Used by hub and virtual root hub drivers. The device is completely
+ * gone, everything is cleaned up, so it's time to get rid of these last
+ * records of this device.
+ */
void usb_free_dev(struct usb_device *dev)
{
- if (atomic_dec_and_test(&dev->refcnt)) {
- /* Normally only goes to zero in usb_disconnect(), from
- * khubd or from roothub shutdown (rmmod/apmd/... thread).
- * Abnormally, roothub init errors can happen, so HCDs
- * call this directly.
- *
- * Otherwise this is a nasty device driver bug, often in
- * disconnect processing.
+ 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!!
*/
- if (in_interrupt ())
- BUG ();
-
- dev->bus->op->deallocate(dev);
- usb_destroy_configuration(dev);
-
- usb_bus_put(dev->bus);
-
- kfree(dev);
+ BUG ();
}
-}
-/**
- * usb_inc_dev_use - record another reference to a device
- * @dev: the device being referenced
- *
- * Each live reference to a device should be refcounted.
- *
- * Device drivers should normally record such references in their
- * open() methods.
- * Drivers should then release them, using usb_dec_dev_use(), in their
- * close() methods.
- */
-void usb_inc_dev_use(struct usb_device *dev)
-{
- atomic_inc(&dev->refcnt);
+ dev->bus->op->deallocate (dev);
+ usb_destroy_configuration (dev);
+ usb_bus_put (dev->bus);
+ kfree (dev);
}
-
/**
* usb_alloc_urb - creates a new urb for a USB driver to use
diff -Nru a/include/linux/usb.h b/include/linux/usb.h
--- a/include/linux/usb.h Mon Apr 8 15:49:08 2002
+++ b/include/linux/usb.h Mon Apr 8 15:49:08 2002
@@ -964,24 +964,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 **);
-
-#ifndef _LINUX_HUB_H
-/* exported to hub driver ONLY to support usb_reset_device () */
-extern int usb_get_configuration(struct usb_device *dev);
-extern void usb_set_maxpacket(struct usb_device *dev);
-extern void usb_destroy_configuration(struct usb_device *dev);
-extern int usb_set_address(struct usb_device *dev);
-#endif /* _LINUX_HUB_H */
-
-/* -------------------------------------------------------------------------- */
-
/* This is arbitrary.
* From USB 2.0 spec Table 11-13, offset 7, a hub can
* have up to 255 ports. The most yet reported is 10.
@@ -1050,9 +1032,49 @@
/* for drivers using iso endpoints */
extern int usb_get_current_frame_number (struct usb_device *usb_dev);
-/* drivers must track when they bind to a device's interfaces */
-extern void usb_inc_dev_use(struct usb_device *);
-#define usb_dec_dev_use usb_free_dev
+/**
+ * usb_inc_dev_use - record another reference to a device
+ * @dev: the device being referenced
+ *
+ * Each live reference to a device should be refcounted.
+ *
+ * Drivers for USB interfaces should normally record such references in
+ * their probe() methods, when they bind to an interface, and release
+ * them usb_dec_dev_use(), in their disconnect() methods.
+ */
+static inline void usb_inc_dev_use (struct usb_device *dev)
+{
+ atomic_inc (&dev->refcnt);
+}
+
+/**
+ * usb_dec_dev_use - drop a reference to a device
+ * @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 ();
+ }
+}
+
/* used these for multi-interface device registration */
extern int usb_find_interface_driver_for_ifnum(struct usb_device *dev, unsigned int
ifnum);
_______________________________________________
[EMAIL PROTECTED]
To unsubscribe, use the last form field at:
https://lists.sourceforge.net/lists/listinfo/linux-usb-devel
Sponsored by http://www.ThinkGeek.com/