mirror of
https://github.com/torvalds/linux
synced 2024-10-08 20:34:15 +00:00
HID: split apart hid_device_probe to make logic more apparent
hid_device_probe() has a complex flow and locks and unlocks a mutex. Move the most of the logic into __hid_device_probe() and hid_check_device_match() and leave the locking in hid_device_probe() which makes the code more clear. Signed-off-by: Dmitry Torokhov <dmitry.torokhov@gmail.com> Signed-off-by: Jiri Kosina <jkosina@suse.cz>
This commit is contained in:
parent
34da76dca4
commit
207733f926
|
@ -2587,64 +2587,71 @@ bool hid_compare_device_paths(struct hid_device *hdev_a,
|
||||||
}
|
}
|
||||||
EXPORT_SYMBOL_GPL(hid_compare_device_paths);
|
EXPORT_SYMBOL_GPL(hid_compare_device_paths);
|
||||||
|
|
||||||
|
static bool hid_check_device_match(struct hid_device *hdev,
|
||||||
|
struct hid_driver *hdrv,
|
||||||
|
const struct hid_device_id **id)
|
||||||
|
{
|
||||||
|
*id = hid_match_device(hdev, hdrv);
|
||||||
|
if (!*id)
|
||||||
|
return -ENODEV;
|
||||||
|
|
||||||
|
if (hdrv->match)
|
||||||
|
return hdrv->match(hdev, hid_ignore_special_drivers);
|
||||||
|
|
||||||
|
/*
|
||||||
|
* hid-generic implements .match(), so we must be dealing with a
|
||||||
|
* different HID driver here, and can simply check if
|
||||||
|
* hid_ignore_special_drivers is set or not.
|
||||||
|
*/
|
||||||
|
return !hid_ignore_special_drivers;
|
||||||
|
}
|
||||||
|
|
||||||
|
static int __hid_device_probe(struct hid_device *hdev, struct hid_driver *hdrv)
|
||||||
|
{
|
||||||
|
const struct hid_device_id *id;
|
||||||
|
int ret;
|
||||||
|
|
||||||
|
if (!hid_check_device_match(hdev, hdrv, &id))
|
||||||
|
return -ENODEV;
|
||||||
|
|
||||||
|
/* reset the quirks that has been previously set */
|
||||||
|
hdev->quirks = hid_lookup_quirk(hdev);
|
||||||
|
hdev->driver = hdrv;
|
||||||
|
|
||||||
|
if (hdrv->probe) {
|
||||||
|
ret = hdrv->probe(hdev, id);
|
||||||
|
} else { /* default probe */
|
||||||
|
ret = hid_open_report(hdev);
|
||||||
|
if (!ret)
|
||||||
|
ret = hid_hw_start(hdev, HID_CONNECT_DEFAULT);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (ret) {
|
||||||
|
hid_close_report(hdev);
|
||||||
|
hdev->driver = NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
static int hid_device_probe(struct device *dev)
|
static int hid_device_probe(struct device *dev)
|
||||||
{
|
{
|
||||||
struct hid_driver *hdrv = to_hid_driver(dev->driver);
|
|
||||||
struct hid_device *hdev = to_hid_device(dev);
|
struct hid_device *hdev = to_hid_device(dev);
|
||||||
const struct hid_device_id *id;
|
struct hid_driver *hdrv = to_hid_driver(dev->driver);
|
||||||
int ret = 0;
|
int ret = 0;
|
||||||
|
|
||||||
if (down_interruptible(&hdev->driver_input_lock)) {
|
if (down_interruptible(&hdev->driver_input_lock))
|
||||||
ret = -EINTR;
|
return -EINTR;
|
||||||
goto end;
|
|
||||||
}
|
|
||||||
hdev->io_started = false;
|
|
||||||
|
|
||||||
|
hdev->io_started = false;
|
||||||
clear_bit(ffs(HID_STAT_REPROBED), &hdev->status);
|
clear_bit(ffs(HID_STAT_REPROBED), &hdev->status);
|
||||||
|
|
||||||
if (!hdev->driver) {
|
if (!hdev->driver)
|
||||||
id = hid_match_device(hdev, hdrv);
|
ret = __hid_device_probe(hdev, hdrv);
|
||||||
if (id == NULL) {
|
|
||||||
ret = -ENODEV;
|
|
||||||
goto unlock;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (hdrv->match) {
|
|
||||||
if (!hdrv->match(hdev, hid_ignore_special_drivers)) {
|
|
||||||
ret = -ENODEV;
|
|
||||||
goto unlock;
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
/*
|
|
||||||
* hid-generic implements .match(), so if
|
|
||||||
* hid_ignore_special_drivers is set, we can safely
|
|
||||||
* return.
|
|
||||||
*/
|
|
||||||
if (hid_ignore_special_drivers) {
|
|
||||||
ret = -ENODEV;
|
|
||||||
goto unlock;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/* reset the quirks that has been previously set */
|
|
||||||
hdev->quirks = hid_lookup_quirk(hdev);
|
|
||||||
hdev->driver = hdrv;
|
|
||||||
if (hdrv->probe) {
|
|
||||||
ret = hdrv->probe(hdev, id);
|
|
||||||
} else { /* default probe */
|
|
||||||
ret = hid_open_report(hdev);
|
|
||||||
if (!ret)
|
|
||||||
ret = hid_hw_start(hdev, HID_CONNECT_DEFAULT);
|
|
||||||
}
|
|
||||||
if (ret) {
|
|
||||||
hid_close_report(hdev);
|
|
||||||
hdev->driver = NULL;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
unlock:
|
|
||||||
if (!hdev->io_started)
|
if (!hdev->io_started)
|
||||||
up(&hdev->driver_input_lock);
|
up(&hdev->driver_input_lock);
|
||||||
end:
|
|
||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
Loading…
Reference in a new issue