On Fri, Oct 25, 2002, Greg KH <[EMAIL PROTECTED]> wrote:
> On Fri, Oct 25, 2002 at 11:39:54AM -0400, Johannes Erdfelt wrote:
> > This patch drops khubd_sem from the hub driver in favor of using
> > reference counting. This gets rid of the ugly and abusive usage of
> > semaphores to do pretty much the same thing :)
> >
> > I have done some light testing with it and it seems to be fine. Comments
> > and reports are welcome before I submit to Greg.
>
> I like it, but I don't see a patch to add refcnt to the usb_hub
> structure, which I think is needed to enable this patch to build :)
Woops! :)
Can you merge changesets in BitKeeper?
JE
# This is a BitKeeper generated patch for the following project:
# Project Name: greg k-h's linux 2.5 USB kernel tree
# This patch format is intended for GNU patch command version 2.5 or higher.
# This patch includes the following deltas:
# ChangeSet 1.899 -> 1.900
# drivers/usb/core/hub.c 1.65 -> 1.66
#
# The following is the BitKeeper ChangeSet Log
# --------------------------------------------
# 02/10/15 [EMAIL PROTECTED] 1.900
# hub.c:
# Drop khub_sem in favor of using reference counting
# --------------------------------------------
#
diff -Nru a/drivers/usb/core/hub.c b/drivers/usb/core/hub.c
--- a/drivers/usb/core/hub.c Fri Oct 25 09:07:23 2002
+++ b/drivers/usb/core/hub.c Fri Oct 25 09:07:23 2002
@@ -2,10 +2,9 @@
* USB hub driver.
*
* (C) Copyright 1999 Linus Torvalds
- * (C) Copyright 1999 Johannes Erdfelt
+ * (C) Copyright 1999-2002 Johannes Erdfelt
* (C) Copyright 1999 Gregory P. Smith
* (C) Copyright 2001 Brad Hards ([EMAIL PROTECTED])
- *
*/
#include <linux/config.h>
@@ -57,6 +56,17 @@
}
#endif
+static void hub_get(struct usb_hub *hub)
+{
+ atomic_inc(&hub->refcnt);
+}
+
+static void hub_put(struct usb_hub *hub)
+{
+ if (atomic_dec_and_test(&hub->refcnt))
+ kfree(hub);
+}
+
/* USB 2.0 spec Section 11.24.4.5 */
static int usb_get_hub_descriptor(struct usb_device *dev, void *data, int size)
{
@@ -146,6 +156,7 @@
spin_lock_irqsave(&hub_event_lock, flags);
if (list_empty(&hub->event_list)) {
list_add(&hub->event_list, &hub_event_list);
+ hub_get(hub); /* khubd will put */
wake_up(&khubd_wait);
}
spin_unlock_irqrestore(&hub_event_lock, flags);
@@ -419,6 +430,8 @@
kfree(hub->descriptor);
return -1;
}
+
+ hub_get(hub); /* for reference to hub in URB */
/* Wake up khubd */
wake_up(&khubd_wait);
@@ -447,9 +460,6 @@
spin_unlock_irqrestore(&hub_event_lock, flags);
- down(&hub->khubd_sem); /* Wait for khubd to leave this hub alone. */
- up(&hub->khubd_sem);
-
/* assuming we used keventd, it must quiesce too */
if (hub->tt.hub)
flush_scheduled_work ();
@@ -458,6 +468,7 @@
usb_unlink_urb(hub->urb);
usb_free_urb(hub->urb);
hub->urb = NULL;
+ hub_put(hub);
}
if (hub->descriptor) {
@@ -465,8 +476,7 @@
hub->descriptor = NULL;
}
- /* Free the memory */
- kfree(hub);
+ hub_put(hub);
}
static int hub_probe(struct usb_interface *intf, const struct usb_device_id *id)
@@ -524,13 +534,14 @@
memset(hub, 0, sizeof(*hub));
+ atomic_set(&hub->refcnt, 2); /* one for us and one for on the bus */
+
INIT_LIST_HEAD(&hub->event_list);
+ INIT_LIST_HEAD(&hub->hub_list);
hub->intf = intf;
- init_MUTEX(&hub->khubd_sem);
/* Record the new hub's existence */
spin_lock_irqsave(&hub_event_lock, flags);
- INIT_LIST_HEAD(&hub->hub_list);
list_add(&hub->hub_list, &hub_list);
spin_unlock_irqrestore(&hub_event_lock, flags);
@@ -538,6 +549,7 @@
if (usb_hub_configure(hub, endpoint) >= 0) {
strcpy (intf->dev.name, "Hub");
+ hub_put(hub);
return 0;
}
@@ -943,9 +955,6 @@
list_del_init(tmp);
- if (unlikely(down_trylock(&hub->khubd_sem)))
- BUG(); /* never blocks, we were on list */
-
spin_unlock_irqrestore(&hub_event_lock, flags);
if (hub->error) {
@@ -955,8 +964,8 @@
if (usb_hub_reset(hub)) {
err("error resetting hub %s - disconnecting",
dev->devpath);
- up(&hub->khubd_sem);
usb_hub_disconnect(dev);
+ hub_put(hub);
continue;
}
@@ -1038,7 +1047,7 @@
usb_hub_power_on(hub);
}
}
- up(&hub->khubd_sem);
+ hub_put(hub);
} /* end while (1) */
spin_unlock_irqrestore(&hub_event_lock, flags);
# This is a BitKeeper generated patch for the following project:
# Project Name: greg k-h's linux 2.5 USB kernel tree
# This patch format is intended for GNU patch command version 2.5 or higher.
# This patch includes the following deltas:
# ChangeSet 1.907 -> 1.908
# drivers/usb/core/hub.h 1.17 -> 1.18
#
# The following is the BitKeeper ChangeSet Log
# --------------------------------------------
# 02/10/25 [EMAIL PROTECTED] 1.908
# hub.h:
# Drop khub_sem in favor of using reference counting
# --------------------------------------------
#
diff -Nru a/drivers/usb/core/hub.h b/drivers/usb/core/hub.h
--- a/drivers/usb/core/hub.h Fri Oct 25 09:07:28 2002
+++ b/drivers/usb/core/hub.h Fri Oct 25 09:07:28 2002
@@ -170,6 +170,8 @@
extern void usb_hub_tt_clear_buffer (struct usb_device *dev, int pipe);
struct usb_hub {
+ atomic_t refcnt;
+
struct usb_interface *intf; /* the "real" device */
struct urb *urb; /* for interrupt polling pipe */
@@ -183,8 +185,8 @@
struct list_head event_list; /* hubs w/data or errs ready */
struct usb_hub_descriptor *descriptor; /* class descriptor */
- struct semaphore khubd_sem;
struct usb_tt tt; /* Transaction Translator */
};
#endif /* __LINUX_HUB_H */
+