diff options
Diffstat (limited to 'drivers/input/input.c')
-rw-r--r-- | drivers/input/input.c | 37 |
1 files changed, 35 insertions, 2 deletions
diff --git a/drivers/input/input.c b/drivers/input/input.c index 2266ecbfbc01..5c16001959cc 100644 --- a/drivers/input/input.c +++ b/drivers/input/input.c | |||
@@ -1658,6 +1658,38 @@ void input_unregister_handler(struct input_handler *handler) | |||
1658 | EXPORT_SYMBOL(input_unregister_handler); | 1658 | EXPORT_SYMBOL(input_unregister_handler); |
1659 | 1659 | ||
1660 | /** | 1660 | /** |
1661 | * input_handler_for_each_handle - handle iterator | ||
1662 | * @handler: input handler to iterate | ||
1663 | * @data: data for the callback | ||
1664 | * @fn: function to be called for each handle | ||
1665 | * | ||
1666 | * Iterate over @bus's list of devices, and call @fn for each, passing | ||
1667 | * it @data and stop when @fn returns a non-zero value. The function is | ||
1668 | * using RCU to traverse the list and therefore may be usind in atonic | ||
1669 | * contexts. The @fn callback is invoked from RCU critical section and | ||
1670 | * thus must not sleep. | ||
1671 | */ | ||
1672 | int input_handler_for_each_handle(struct input_handler *handler, void *data, | ||
1673 | int (*fn)(struct input_handle *, void *)) | ||
1674 | { | ||
1675 | struct input_handle *handle; | ||
1676 | int retval = 0; | ||
1677 | |||
1678 | rcu_read_lock(); | ||
1679 | |||
1680 | list_for_each_entry_rcu(handle, &handler->h_list, h_node) { | ||
1681 | retval = fn(handle, data); | ||
1682 | if (retval) | ||
1683 | break; | ||
1684 | } | ||
1685 | |||
1686 | rcu_read_unlock(); | ||
1687 | |||
1688 | return retval; | ||
1689 | } | ||
1690 | EXPORT_SYMBOL(input_handler_for_each_handle); | ||
1691 | |||
1692 | /** | ||
1661 | * input_register_handle - register a new input handle | 1693 | * input_register_handle - register a new input handle |
1662 | * @handle: handle to register | 1694 | * @handle: handle to register |
1663 | * | 1695 | * |
@@ -1690,7 +1722,7 @@ int input_register_handle(struct input_handle *handle) | |||
1690 | * we can't be racing with input_unregister_handle() | 1722 | * we can't be racing with input_unregister_handle() |
1691 | * and so separate lock is not needed here. | 1723 | * and so separate lock is not needed here. |
1692 | */ | 1724 | */ |
1693 | list_add_tail(&handle->h_node, &handler->h_list); | 1725 | list_add_tail_rcu(&handle->h_node, &handler->h_list); |
1694 | 1726 | ||
1695 | if (handler->start) | 1727 | if (handler->start) |
1696 | handler->start(handle); | 1728 | handler->start(handle); |
@@ -1713,7 +1745,7 @@ void input_unregister_handle(struct input_handle *handle) | |||
1713 | { | 1745 | { |
1714 | struct input_dev *dev = handle->dev; | 1746 | struct input_dev *dev = handle->dev; |
1715 | 1747 | ||
1716 | list_del_init(&handle->h_node); | 1748 | list_del_rcu(&handle->h_node); |
1717 | 1749 | ||
1718 | /* | 1750 | /* |
1719 | * Take dev->mutex to prevent race with input_release_device(). | 1751 | * Take dev->mutex to prevent race with input_release_device(). |
@@ -1721,6 +1753,7 @@ void input_unregister_handle(struct input_handle *handle) | |||
1721 | mutex_lock(&dev->mutex); | 1753 | mutex_lock(&dev->mutex); |
1722 | list_del_rcu(&handle->d_node); | 1754 | list_del_rcu(&handle->d_node); |
1723 | mutex_unlock(&dev->mutex); | 1755 | mutex_unlock(&dev->mutex); |
1756 | |||
1724 | synchronize_rcu(); | 1757 | synchronize_rcu(); |
1725 | } | 1758 | } |
1726 | EXPORT_SYMBOL(input_unregister_handle); | 1759 | EXPORT_SYMBOL(input_unregister_handle); |