Files
kernel_xiaomi_sm8250/drivers/usb/core/notify.c
Manu Gautam b31fc5d204 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 <mgautam@codeaurora.org>
2018-08-09 15:57:54 -07:00

103 lines
2.7 KiB
C

// SPDX-License-Identifier: GPL-2.0
/*
* All the USB notify logic
*
* (C) Copyright 2005 Greg Kroah-Hartman <gregkh@suse.de>
*
* notifier functions originally based on those in kernel/sys.c
* but fixed up to not be so broken.
*
* Released under the GPLv2 only.
*/
#include <linux/kernel.h>
#include <linux/export.h>
#include <linux/notifier.h>
#include <linux/usb.h>
#include <linux/mutex.h>
#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
* @nb: pointer to the notifier block for the callback events.
*
* These changes are either USB devices or busses being added or removed.
*/
void usb_register_notify(struct notifier_block *nb)
{
blocking_notifier_chain_register(&usb_notifier_list, nb);
}
EXPORT_SYMBOL_GPL(usb_register_notify);
/**
* usb_unregister_notify - unregister a notifier callback
* @nb: pointer to the notifier block for the callback events.
*
* usb_register_notify() must have been previously called for this function
* to work properly.
*/
void usb_unregister_notify(struct notifier_block *nb)
{
blocking_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);
}
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);
}
void usb_notify_add_bus(struct usb_bus *ubus)
{
blocking_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_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);
}