Skip to content

Commit aaac082

Browse files
dtorJiri Kosina
authored andcommitted
HID: serialize hid_hw_open and hid_hw_close
The HID transport drivers either re-implement exactly the same logic (usbhid, i2c-hid) or forget to implement it (usbhid) which causes issues when the same device is accessed via multiple interfaces (for example input device through evdev and also hidraw). Let's muve the locking logic into HID core to make sure the serialized behavior is always enforced. Also let's uninline and move hid_hw_start() and hid_hw_stop() into hid-core as hid_hw_start() is somewhat large and do not believe we get any benefit from these two being inline. Signed-off-by: Dmitry Torokhov <[email protected]> Reviewed-by: Andy Shevchenko <[email protected]> Reviewed-by: Benjamin Tissoires <[email protected]> Signed-off-by: Jiri Kosina <[email protected]>
1 parent 28cbc86 commit aaac082

File tree

2 files changed

+98
-63
lines changed

2 files changed

+98
-63
lines changed

drivers/hid/hid-core.c

Lines changed: 89 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1750,6 +1750,94 @@ void hid_disconnect(struct hid_device *hdev)
17501750
}
17511751
EXPORT_SYMBOL_GPL(hid_disconnect);
17521752

1753+
/**
1754+
* hid_hw_start - start underlying HW
1755+
* @hdev: hid device
1756+
* @connect_mask: which outputs to connect, see HID_CONNECT_*
1757+
*
1758+
* Call this in probe function *after* hid_parse. This will setup HW
1759+
* buffers and start the device (if not defeirred to device open).
1760+
* hid_hw_stop must be called if this was successful.
1761+
*/
1762+
int hid_hw_start(struct hid_device *hdev, unsigned int connect_mask)
1763+
{
1764+
int error;
1765+
1766+
error = hdev->ll_driver->start(hdev);
1767+
if (error)
1768+
return error;
1769+
1770+
if (connect_mask) {
1771+
error = hid_connect(hdev, connect_mask);
1772+
if (error) {
1773+
hdev->ll_driver->stop(hdev);
1774+
return error;
1775+
}
1776+
}
1777+
1778+
return 0;
1779+
}
1780+
EXPORT_SYMBOL_GPL(hid_hw_start);
1781+
1782+
/**
1783+
* hid_hw_stop - stop underlying HW
1784+
* @hdev: hid device
1785+
*
1786+
* This is usually called from remove function or from probe when something
1787+
* failed and hid_hw_start was called already.
1788+
*/
1789+
void hid_hw_stop(struct hid_device *hdev)
1790+
{
1791+
hid_disconnect(hdev);
1792+
hdev->ll_driver->stop(hdev);
1793+
}
1794+
EXPORT_SYMBOL_GPL(hid_hw_stop);
1795+
1796+
/**
1797+
* hid_hw_open - signal underlying HW to start delivering events
1798+
* @hdev: hid device
1799+
*
1800+
* Tell underlying HW to start delivering events from the device.
1801+
* This function should be called sometime after successful call
1802+
* to hid_hiw_start().
1803+
*/
1804+
int hid_hw_open(struct hid_device *hdev)
1805+
{
1806+
int ret;
1807+
1808+
ret = mutex_lock_killable(&hdev->ll_open_lock);
1809+
if (ret)
1810+
return ret;
1811+
1812+
if (!hdev->ll_open_count++) {
1813+
ret = hdev->ll_driver->open(hdev);
1814+
if (ret)
1815+
hdev->ll_open_count--;
1816+
}
1817+
1818+
mutex_unlock(&hdev->ll_open_lock);
1819+
return ret;
1820+
}
1821+
EXPORT_SYMBOL_GPL(hid_hw_open);
1822+
1823+
/**
1824+
* hid_hw_close - signal underlaying HW to stop delivering events
1825+
*
1826+
* @hdev: hid device
1827+
*
1828+
* This function indicates that we are not interested in the events
1829+
* from this device anymore. Delivery of events may or may not stop,
1830+
* depending on the number of users still outstanding.
1831+
*/
1832+
void hid_hw_close(struct hid_device *hdev)
1833+
{
1834+
mutex_lock(&hdev->ll_open_lock);
1835+
if (!--hdev->ll_open_count)
1836+
hdev->ll_driver->close(hdev);
1837+
mutex_unlock(&hdev->ll_open_lock);
1838+
}
1839+
EXPORT_SYMBOL_GPL(hid_hw_close);
1840+
17531841
/*
17541842
* A list of devices for which there is a specialized driver on HID bus.
17551843
*
@@ -2747,6 +2835,7 @@ struct hid_device *hid_allocate_device(void)
27472835
spin_lock_init(&hdev->debug_list_lock);
27482836
sema_init(&hdev->driver_lock, 1);
27492837
sema_init(&hdev->driver_input_lock, 1);
2838+
mutex_init(&hdev->ll_open_lock);
27502839

27512840
return hdev;
27522841
}

include/linux/hid.h

Lines changed: 9 additions & 63 deletions
Original file line numberDiff line numberDiff line change
@@ -34,6 +34,7 @@
3434
#include <linux/workqueue.h>
3535
#include <linux/input.h>
3636
#include <linux/semaphore.h>
37+
#include <linux/mutex.h>
3738
#include <linux/power_supply.h>
3839
#include <uapi/linux/hid.h>
3940

@@ -520,7 +521,10 @@ struct hid_device { /* device report descriptor */
520521
struct semaphore driver_input_lock; /* protects the current driver */
521522
struct device dev; /* device */
522523
struct hid_driver *driver;
524+
523525
struct hid_ll_driver *ll_driver;
526+
struct mutex ll_open_lock;
527+
unsigned int ll_open_count;
524528

525529
#ifdef CONFIG_HID_BATTERY_STRENGTH
526530
/*
@@ -937,69 +941,11 @@ static inline int __must_check hid_parse(struct hid_device *hdev)
937941
return hid_open_report(hdev);
938942
}
939943

940-
/**
941-
* hid_hw_start - start underlaying HW
942-
*
943-
* @hdev: hid device
944-
* @connect_mask: which outputs to connect, see HID_CONNECT_*
945-
*
946-
* Call this in probe function *after* hid_parse. This will setup HW buffers
947-
* and start the device (if not deffered to device open). hid_hw_stop must be
948-
* called if this was successful.
949-
*/
950-
static inline int __must_check hid_hw_start(struct hid_device *hdev,
951-
unsigned int connect_mask)
952-
{
953-
int ret = hdev->ll_driver->start(hdev);
954-
if (ret || !connect_mask)
955-
return ret;
956-
ret = hid_connect(hdev, connect_mask);
957-
if (ret)
958-
hdev->ll_driver->stop(hdev);
959-
return ret;
960-
}
961-
962-
/**
963-
* hid_hw_stop - stop underlaying HW
964-
*
965-
* @hdev: hid device
966-
*
967-
* This is usually called from remove function or from probe when something
968-
* failed and hid_hw_start was called already.
969-
*/
970-
static inline void hid_hw_stop(struct hid_device *hdev)
971-
{
972-
hid_disconnect(hdev);
973-
hdev->ll_driver->stop(hdev);
974-
}
975-
976-
/**
977-
* hid_hw_open - signal underlaying HW to start delivering events
978-
*
979-
* @hdev: hid device
980-
*
981-
* Tell underlying HW to start delivering events from the device.
982-
* This function should be called sometime after successful call
983-
* to hid_hiw_start().
984-
*/
985-
static inline int __must_check hid_hw_open(struct hid_device *hdev)
986-
{
987-
return hdev->ll_driver->open(hdev);
988-
}
989-
990-
/**
991-
* hid_hw_close - signal underlaying HW to stop delivering events
992-
*
993-
* @hdev: hid device
994-
*
995-
* This function indicates that we are not interested in the events
996-
* from this device anymore. Delivery of events may or may not stop,
997-
* depending on the number of users still outstanding.
998-
*/
999-
static inline void hid_hw_close(struct hid_device *hdev)
1000-
{
1001-
hdev->ll_driver->close(hdev);
1002-
}
944+
int __must_check hid_hw_start(struct hid_device *hdev,
945+
unsigned int connect_mask);
946+
void hid_hw_stop(struct hid_device *hdev);
947+
int __must_check hid_hw_open(struct hid_device *hdev);
948+
void hid_hw_close(struct hid_device *hdev);
1003949

1004950
/**
1005951
* hid_hw_power - requests underlying HW to go into given power mode

0 commit comments

Comments
 (0)