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:
Dmitry Torokhov 2023-05-23 14:04:31 -07:00 committed by Jiri Kosina
parent 34da76dca4
commit 207733f926

View file

@ -2587,48 +2587,37 @@ 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 int hid_device_probe(struct device *dev) static bool hid_check_device_match(struct hid_device *hdev,
struct hid_driver *hdrv,
const struct hid_device_id **id)
{ {
struct hid_driver *hdrv = to_hid_driver(dev->driver); *id = hid_match_device(hdev, hdrv);
struct hid_device *hdev = to_hid_device(dev); if (!*id)
const struct hid_device_id *id; return -ENODEV;
int ret = 0;
if (down_interruptible(&hdev->driver_input_lock)) { if (hdrv->match)
ret = -EINTR; return hdrv->match(hdev, hid_ignore_special_drivers);
goto end;
}
hdev->io_started = false;
clear_bit(ffs(HID_STAT_REPROBED), &hdev->status);
if (!hdev->driver) {
id = hid_match_device(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-generic implements .match(), so we must be dealing with a
* hid_ignore_special_drivers is set, we can safely * different HID driver here, and can simply check if
* return. * hid_ignore_special_drivers is set or not.
*/ */
if (hid_ignore_special_drivers) { return !hid_ignore_special_drivers;
ret = -ENODEV;
goto unlock;
}
} }
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 */ /* reset the quirks that has been previously set */
hdev->quirks = hid_lookup_quirk(hdev); hdev->quirks = hid_lookup_quirk(hdev);
hdev->driver = hdrv; hdev->driver = hdrv;
if (hdrv->probe) { if (hdrv->probe) {
ret = hdrv->probe(hdev, id); ret = hdrv->probe(hdev, id);
} else { /* default probe */ } else { /* default probe */
@ -2636,15 +2625,33 @@ static int hid_device_probe(struct device *dev)
if (!ret) if (!ret)
ret = hid_hw_start(hdev, HID_CONNECT_DEFAULT); ret = hid_hw_start(hdev, HID_CONNECT_DEFAULT);
} }
if (ret) { if (ret) {
hid_close_report(hdev); hid_close_report(hdev);
hdev->driver = NULL; hdev->driver = NULL;
} }
return ret;
} }
unlock:
static int hid_device_probe(struct device *dev)
{
struct hid_device *hdev = to_hid_device(dev);
struct hid_driver *hdrv = to_hid_driver(dev->driver);
int ret = 0;
if (down_interruptible(&hdev->driver_input_lock))
return -EINTR;
hdev->io_started = false;
clear_bit(ffs(HID_STAT_REPROBED), &hdev->status);
if (!hdev->driver)
ret = __hid_device_probe(hdev, hdrv);
if (!hdev->io_started) if (!hdev->io_started)
up(&hdev->driver_input_lock); up(&hdev->driver_input_lock);
end:
return ret; return ret;
} }