X-Git-Url: http://git.onelab.eu/?a=blobdiff_plain;f=drivers%2Fusb%2Fcore%2Fnotify.c;fp=drivers%2Fusb%2Fcore%2Fnotify.c;h=fbbebab52fbd1fbfa23b3d7d48618905067d9424;hb=64ba3f394c830ec48a1c31b53dcae312c56f1604;hp=6b36897ca151998ab28f07c12f0e9baef9e372fe;hpb=be1e6109ac94a859551f8e1774eb9a8469fe055c;p=linux-2.6.git diff --git a/drivers/usb/core/notify.c b/drivers/usb/core/notify.c index 6b36897ca..fbbebab52 100644 --- a/drivers/usb/core/notify.c +++ b/drivers/usb/core/notify.c @@ -9,13 +9,63 @@ */ +#include #include #include #include -#include #include "usb.h" -static BLOCKING_NOTIFIER_HEAD(usb_notifier_list); + +static struct notifier_block *usb_notifier_list; +static DECLARE_MUTEX(usb_notifier_lock); + +static void usb_notifier_chain_register(struct notifier_block **list, + struct notifier_block *n) +{ + down(&usb_notifier_lock); + while (*list) { + if (n->priority > (*list)->priority) + break; + list = &((*list)->next); + } + n->next = *list; + *list = n; + up(&usb_notifier_lock); +} + +static void usb_notifier_chain_unregister(struct notifier_block **nl, + struct notifier_block *n) +{ + down(&usb_notifier_lock); + while ((*nl)!=NULL) { + if ((*nl)==n) { + *nl = n->next; + goto exit; + } + nl=&((*nl)->next); + } +exit: + up(&usb_notifier_lock); +} + +static int usb_notifier_call_chain(struct notifier_block **n, + unsigned long val, void *v) +{ + int ret=NOTIFY_DONE; + struct notifier_block *nb = *n; + + down(&usb_notifier_lock); + while (nb) { + ret = nb->notifier_call(nb,val,v); + if (ret&NOTIFY_STOP_MASK) { + goto exit; + } + nb = nb->next; + } +exit: + up(&usb_notifier_lock); + return ret; +} /** * usb_register_notify - register a notifier callback whenever a usb change happens @@ -25,7 +75,7 @@ static BLOCKING_NOTIFIER_HEAD(usb_notifier_list); */ void usb_register_notify(struct notifier_block *nb) { - blocking_notifier_chain_register(&usb_notifier_list, nb); + usb_notifier_chain_register(&usb_notifier_list, nb); } EXPORT_SYMBOL_GPL(usb_register_notify); @@ -38,31 +88,27 @@ EXPORT_SYMBOL_GPL(usb_register_notify); */ void usb_unregister_notify(struct notifier_block *nb) { - blocking_notifier_chain_unregister(&usb_notifier_list, nb); + usb_notifier_chain_unregister(&usb_notifier_list, nb); } EXPORT_SYMBOL_GPL(usb_unregister_notify); void usb_notify_add_device(struct usb_device *udev) { - blocking_notifier_call_chain(&usb_notifier_list, USB_DEVICE_ADD, udev); + usb_notifier_call_chain(&usb_notifier_list, USB_DEVICE_ADD, udev); } void usb_notify_remove_device(struct usb_device *udev) { - /* Protect against simultaneous usbfs open */ - mutex_lock(&usbfs_mutex); - blocking_notifier_call_chain(&usb_notifier_list, - USB_DEVICE_REMOVE, udev); - mutex_unlock(&usbfs_mutex); + usb_notifier_call_chain(&usb_notifier_list, USB_DEVICE_REMOVE, udev); } void usb_notify_add_bus(struct usb_bus *ubus) { - blocking_notifier_call_chain(&usb_notifier_list, USB_BUS_ADD, ubus); + usb_notifier_call_chain(&usb_notifier_list, USB_BUS_ADD, ubus); } void usb_notify_remove_bus(struct usb_bus *ubus) { - blocking_notifier_call_chain(&usb_notifier_list, USB_BUS_REMOVE, ubus); + usb_notifier_call_chain(&usb_notifier_list, USB_BUS_REMOVE, ubus); }