# 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