patch-2.3.11 linux/drivers/usb/hub.c
Next file: linux/drivers/usb/hub.h
Previous file: linux/drivers/usb/ezusb.h
Back to the patch index
Back to the overall index
- Lines: 141
- Date:
Mon Jul 19 15:25:27 1999
- Orig file:
v2.3.10/linux/drivers/usb/hub.c
- Orig date:
Wed Jun 30 13:38:20 1999
diff -u --recursive --new-file v2.3.10/linux/drivers/usb/hub.c linux/drivers/usb/hub.c
@@ -3,6 +3,7 @@
*
* (C) Copyright 1999 Linus Torvalds
* (C) Copyright 1999 Johannes Erdfelt
+ * (C) Copyright 1999 Gregory P. Smith
*/
#include <linux/kernel.h>
@@ -20,10 +21,14 @@
/* Wakes up khubd */
static DECLARE_WAIT_QUEUE_HEAD(usb_hub_wait);
static spinlock_t hub_event_lock = SPIN_LOCK_UNLOCKED;
+static spinlock_t hub_list_lock = SPIN_LOCK_UNLOCKED;
/* List of hubs needing servicing */
static struct list_head hub_event_list;
+/* List containing all of the hubs (for cleanup) */
+static struct list_head all_hubs_list;
+
/* PID of khubd */
static int khubd_pid = 0;
@@ -149,6 +154,7 @@
struct usb_interface_descriptor *interface;
struct usb_endpoint_descriptor *endpoint;
struct usb_hub *hub;
+ unsigned long flags;
/* We don't handle multi-config hubs */
if (dev->descriptor.bNumConfigurations != 1)
@@ -196,9 +202,15 @@
INIT_LIST_HEAD(&hub->event_list);
hub->dev = dev;
+ /* Record the new hub's existence */
+ spin_lock_irqsave(&hub_list_lock, flags);
+ INIT_LIST_HEAD(&hub->hub_list);
+ list_add(&hub->hub_list, &all_hubs_list);
+ spin_unlock_irqrestore(&hub_list_lock, flags);
+
usb_hub_configure(hub);
- usb_request_irq(dev, usb_rcvctrlpipe(dev, endpoint->bEndpointAddress), hub_irq, endpoint->bInterval, hub);
+ hub->irq_handle = usb_request_irq(dev, usb_rcvctrlpipe(dev, endpoint->bEndpointAddress), hub_irq, endpoint->bInterval, hub);
/* Wake up khubd */
wake_up(&usb_hub_wait);
@@ -216,9 +228,14 @@
/* Delete it and then reset it */
list_del(&hub->event_list);
INIT_LIST_HEAD(&hub->event_list);
+ list_del(&hub->hub_list);
+ INIT_LIST_HEAD(&hub->hub_list);
spin_unlock_irqrestore(&hub_event_lock, flags);
+ usb_release_irq(hub->dev, hub->irq_handle);
+ hub->irq_handle = NULL;
+
/* Free the memory */
kfree(hub);
}
@@ -353,13 +370,16 @@
static int usb_hub_thread(void *__hub)
{
+ MOD_INC_USE_COUNT;
+
+ printk(KERN_INFO "USB hub driver registered\n");
+
lock_kernel();
/*
* This thread doesn't need any user-level access,
* so get rid of all our resources
*/
- printk("usb_hub_thread at %p\n", &usb_hub_thread);
exit_mm(current);
exit_files(current);
exit_fs(current);
@@ -373,6 +393,8 @@
usb_hub_events();
} while (!signal_pending(current));
+ MOD_DEC_USE_COUNT;
+
printk("usb_hub_thread exiting\n");
return 0;
@@ -393,6 +415,7 @@
int pid;
INIT_LIST_HEAD(&hub_event_list);
+ INIT_LIST_HEAD(&all_hubs_list);
usb_register(&hub_driver);
pid = kernel_thread(usb_hub_thread, NULL, CLONE_FS | CLONE_FILES | CLONE_SIGHAND);
@@ -409,11 +432,39 @@
void usb_hub_cleanup(void)
{
- if (khubd_pid >= 0)
- kill_proc(khubd_pid, SIGINT, 1);
+ struct list_head *next, *tmp, *head = &all_hubs_list;
+ struct usb_hub *hub;
+ unsigned long flags, flags2;
+
+ /* Free the resources allocated by each hub */
+ spin_lock_irqsave(&hub_list_lock, flags);
+ spin_lock_irqsave(&hub_event_lock, flags2);
+
+ tmp = head->next;
+ while (tmp != head) {
+ hub = list_entry(tmp, struct usb_hub, hub_list);
+
+ next = tmp->next;
+
+ list_del(&hub->event_list);
+ INIT_LIST_HEAD(&hub->event_list);
+ list_del(tmp); /* &hub->hub_list */
+ INIT_LIST_HEAD(tmp); /* &hub->hub_list */
+
+ /* XXX we should disconnect each connected port here */
+
+ usb_release_irq(hub->dev, hub->irq_handle);
+ hub->irq_handle = NULL;
+ kfree(hub);
+
+ tmp = next;
+ }
usb_deregister(&hub_driver);
-}
+
+ spin_unlock_irqrestore(&hub_event_lock, flags2);
+ spin_unlock_irqrestore(&hub_list_lock, flags);
+} /* usb_hub_cleanup() */
#ifdef MODULE
int init_module(void){
FUNET's LINUX-ADM group, linux-adm@nic.funet.fi
TCL-scripts by Sam Shen (who was at: slshen@lbl.gov)