X-Git-Url: http://git.onelab.eu/?a=blobdiff_plain;f=drivers%2Fusb%2Fcore%2Fnotify.c;fp=drivers%2Fusb%2Fcore%2Fnotify.c;h=6b36897ca151998ab28f07c12f0e9baef9e372fe;hb=97bf2856c6014879bd04983a3e9dfcdac1e7fe85;hp=fbbebab52fbd1fbfa23b3d7d48618905067d9424;hpb=76828883507a47dae78837ab5dec5a5b4513c667;p=linux-2.6.git diff --git a/drivers/usb/core/notify.c b/drivers/usb/core/notify.c index fbbebab52..6b36897ca 100644 --- a/drivers/usb/core/notify.c +++ b/drivers/usb/core/notify.c @@ -9,63 +9,13 @@ */ -#include #include #include #include +#include #include "usb.h" - -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; -} +static BLOCKING_NOTIFIER_HEAD(usb_notifier_list); /** * usb_register_notify - register a notifier callback whenever a usb change happens @@ -75,7 +25,7 @@ exit: */ void usb_register_notify(struct notifier_block *nb) { - usb_notifier_chain_register(&usb_notifier_list, nb); + blocking_notifier_chain_register(&usb_notifier_list, nb); } EXPORT_SYMBOL_GPL(usb_register_notify); @@ -88,27 +38,31 @@ EXPORT_SYMBOL_GPL(usb_register_notify); */ void usb_unregister_notify(struct notifier_block *nb) { - usb_notifier_chain_unregister(&usb_notifier_list, nb); + blocking_notifier_chain_unregister(&usb_notifier_list, nb); } EXPORT_SYMBOL_GPL(usb_unregister_notify); void usb_notify_add_device(struct usb_device *udev) { - usb_notifier_call_chain(&usb_notifier_list, USB_DEVICE_ADD, udev); + blocking_notifier_call_chain(&usb_notifier_list, USB_DEVICE_ADD, udev); } void usb_notify_remove_device(struct usb_device *udev) { - usb_notifier_call_chain(&usb_notifier_list, USB_DEVICE_REMOVE, 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); } void usb_notify_add_bus(struct usb_bus *ubus) { - usb_notifier_call_chain(&usb_notifier_list, USB_BUS_ADD, ubus); + blocking_notifier_call_chain(&usb_notifier_list, USB_BUS_ADD, ubus); } void usb_notify_remove_bus(struct usb_bus *ubus) { - usb_notifier_call_chain(&usb_notifier_list, USB_BUS_REMOVE, ubus); + blocking_notifier_call_chain(&usb_notifier_list, USB_BUS_REMOVE, ubus); }