From 84411ad344b44e61c1fe2e672b8ac30aabba2610 Mon Sep 17 00:00:00 2001 From: Manu Gautam Date: Fri, 12 Aug 2016 16:55:26 +0530 Subject: [PATCH] usb: hcd: Add USB atomic notifier callback for HC died error Add support for USB atomic notifier callbacks when host controller drivers reports death of controller on some fatal error. Current implementation doesn't help to recover from this condition. Controller platform drivers can register for this callback and take necessary steps to reset and add hcd again. CRs-fixed: 1048766 Change-Id: Ie9064e669424096fee8c35cddccab29faf60cc6b Signed-off-by: Manu Gautam --- drivers/usb/core/hcd.c | 1 + drivers/usb/core/notify.c | 31 +++++++++++++++++++++++++++++++ drivers/usb/core/usb.h | 1 + include/linux/usb.h | 3 +++ 4 files changed, 36 insertions(+) diff --git a/drivers/usb/core/hcd.c b/drivers/usb/core/hcd.c index 5cc655908fda..3df80c73b74a 100644 --- a/drivers/usb/core/hcd.c +++ b/drivers/usb/core/hcd.c @@ -2513,6 +2513,7 @@ void usb_hc_died (struct usb_hcd *hcd) } spin_unlock_irqrestore (&hcd_root_hub_lock, flags); /* Make sure that the other roothub is also deallocated. */ + usb_atomic_notify_dead_bus(&hcd->self); } EXPORT_SYMBOL_GPL (usb_hc_died); diff --git a/drivers/usb/core/notify.c b/drivers/usb/core/notify.c index 7728c91dfa2e..af91b1e7146c 100644 --- a/drivers/usb/core/notify.c +++ b/drivers/usb/core/notify.c @@ -17,6 +17,7 @@ #include "usb.h" static BLOCKING_NOTIFIER_HEAD(usb_notifier_list); +static ATOMIC_NOTIFIER_HEAD(usb_atomic_notifier_list); /** * usb_register_notify - register a notifier callback whenever a usb change happens @@ -67,3 +68,33 @@ void usb_notify_remove_bus(struct usb_bus *ubus) { blocking_notifier_call_chain(&usb_notifier_list, USB_BUS_REMOVE, ubus); } + +/** + * usb_register_atomic_notify - register a atomic notifier callback whenever a + * HC dies + * @nb: pointer to the atomic notifier block for the callback events. + * + */ +void usb_register_atomic_notify(struct notifier_block *nb) +{ + atomic_notifier_chain_register(&usb_atomic_notifier_list, nb); +} +EXPORT_SYMBOL_GPL(usb_register_atomic_notify); + +/** + * usb_unregister_atomic_notify - unregister a atomic notifier callback + * @nb: pointer to the notifier block for the callback events. + * + */ +void usb_unregister_atomic_notify(struct notifier_block *nb) +{ + atomic_notifier_chain_unregister(&usb_atomic_notifier_list, nb); +} +EXPORT_SYMBOL_GPL(usb_unregister_atomic_notify); + + +void usb_atomic_notify_dead_bus(struct usb_bus *ubus) +{ + atomic_notifier_call_chain(&usb_atomic_notifier_list, USB_BUS_DIED, + ubus); +} diff --git a/drivers/usb/core/usb.h b/drivers/usb/core/usb.h index 05b5e17abf92..ccb35af525e2 100644 --- a/drivers/usb/core/usb.h +++ b/drivers/usb/core/usb.h @@ -175,6 +175,7 @@ extern void usb_notify_add_device(struct usb_device *udev); extern void usb_notify_remove_device(struct usb_device *udev); extern void usb_notify_add_bus(struct usb_bus *ubus); extern void usb_notify_remove_bus(struct usb_bus *ubus); +extern void usb_atomic_notify_dead_bus(struct usb_bus *ubus); extern void usb_hub_adjust_deviceremovable(struct usb_device *hdev, struct usb_hub_descriptor *desc); diff --git a/include/linux/usb.h b/include/linux/usb.h index 246945be000c..55240f9a3b94 100644 --- a/include/linux/usb.h +++ b/include/linux/usb.h @@ -1896,8 +1896,11 @@ static inline int usb_translate_errors(int error_code) #define USB_DEVICE_REMOVE 0x0002 #define USB_BUS_ADD 0x0003 #define USB_BUS_REMOVE 0x0004 +#define USB_BUS_DIED 0x0005 extern void usb_register_notify(struct notifier_block *nb); extern void usb_unregister_notify(struct notifier_block *nb); +extern void usb_register_atomic_notify(struct notifier_block *nb); +extern void usb_unregister_atomic_notify(struct notifier_block *nb); /* debugfs stuff */ extern struct dentry *usb_debug_root;