HID: split apart hid_device_probe to make logic more apparent
authorDmitry Torokhov <dmitry.torokhov@gmail.com>
Tue, 23 May 2023 21:04:31 +0000 (14:04 -0700)
committerJiri Kosina <jkosina@suse.cz>
Fri, 26 May 2023 18:45:39 +0000 (20:45 +0200)
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>
drivers/hid/hid-core.c

index 22623eb..1f0bb27 100644 (file)
@@ -2587,64 +2587,71 @@ bool hid_compare_device_paths(struct hid_device *hdev_a,
 }
 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)
 {
-       struct hid_driver *hdrv = to_hid_driver(dev->driver);
        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;
 
-       if (down_interruptible(&hdev->driver_input_lock)) {
-               ret = -EINTR;
-               goto end;
-       }
-       hdev->io_started = false;
+       if (down_interruptible(&hdev->driver_input_lock))
+               return -EINTR;
 
+       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 (!hdev->driver)
+               ret = __hid_device_probe(hdev, hdrv);
 
-               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)
                up(&hdev->driver_input_lock);
-end:
+
        return ret;
 }