81 lines
2.3 KiB
Diff
81 lines
2.3 KiB
Diff
From: Ben Hutchings <ben@decadent.org.uk>
|
|
Date: Thu, 12 Jul 2018 00:39:38 +0100
|
|
Subject: HID: Avoid ABI change in 4.17.6
|
|
Forwarded: not-needed
|
|
|
|
Commit 8f732850df1b "HID: core: allow concurrent registration of
|
|
drivers" introduced atomic bit-operations on hid_device::status, and
|
|
changed its type from unsigned int to unsigned long as required for
|
|
those operations.
|
|
|
|
Revert the type change and use cmpxchg() for the bit-operations,
|
|
since it supports unsigned int.
|
|
|
|
---
|
|
--- a/drivers/hid/hid-core.c
|
|
+++ b/drivers/hid/hid-core.c
|
|
@@ -1929,6 +1929,34 @@ static int hid_bus_match(struct device *
|
|
return hid_match_device(hdev, hdrv) != NULL;
|
|
}
|
|
|
|
+static void clear_status_flag(unsigned int flag, unsigned int *status)
|
|
+{
|
|
+ unsigned int expect, old;
|
|
+
|
|
+ expect = READ_ONCE(*status);
|
|
+ for (;;) {
|
|
+ old = cmpxchg(status, expect, expect & ~flag);
|
|
+ if (old == expect)
|
|
+ break;
|
|
+ expect = old;
|
|
+ }
|
|
+}
|
|
+
|
|
+static bool test_and_set_status_flag(unsigned int flag, unsigned int *status)
|
|
+{
|
|
+ unsigned int expect, old;
|
|
+
|
|
+ expect = READ_ONCE(*status);
|
|
+ for (;;) {
|
|
+ old = cmpxchg(status, expect, expect | flag);
|
|
+ if (old == expect)
|
|
+ break;
|
|
+ expect = old;
|
|
+ }
|
|
+
|
|
+ return old & flag;
|
|
+}
|
|
+
|
|
static int hid_device_probe(struct device *dev)
|
|
{
|
|
struct hid_driver *hdrv = to_hid_driver(dev->driver);
|
|
@@ -1942,7 +1970,7 @@ static int hid_device_probe(struct devic
|
|
}
|
|
hdev->io_started = false;
|
|
|
|
- clear_bit(ffs(HID_STAT_REPROBED), &hdev->status);
|
|
+ clear_status_flag(HID_STAT_REPROBED, &hdev->status);
|
|
|
|
if (!hdev->driver) {
|
|
id = hid_match_device(hdev, hdrv);
|
|
@@ -2208,7 +2236,7 @@ static int __hid_bus_reprobe_drivers(str
|
|
|
|
if (hdev->driver == hdrv &&
|
|
!hdrv->match(hdev, hid_ignore_special_drivers) &&
|
|
- !test_and_set_bit(ffs(HID_STAT_REPROBED), &hdev->status))
|
|
+ !test_and_set_status_flag(HID_STAT_REPROBED, &hdev->status))
|
|
return device_reprobe(dev);
|
|
|
|
return 0;
|
|
--- a/include/linux/hid.h
|
|
+++ b/include/linux/hid.h
|
|
@@ -569,7 +569,7 @@ struct hid_device { /* device repo
|
|
bool battery_avoid_query;
|
|
#endif
|
|
|
|
- unsigned long status; /* see STAT flags above */
|
|
+ unsigned int status; /* see STAT flags above */
|
|
unsigned claimed; /* Claimed by hidinput, hiddev? */
|
|
unsigned quirks; /* Various quirks the device can pull on us */
|
|
bool io_started; /* If IO has started */
|