aboutsummaryrefslogtreecommitdiffstats
path: root/debian/patches/debian/hid-avoid-abi-change-in-4.17.6.patch
diff options
context:
space:
mode:
Diffstat (limited to 'debian/patches/debian/hid-avoid-abi-change-in-4.17.6.patch')
-rw-r--r--debian/patches/debian/hid-avoid-abi-change-in-4.17.6.patch80
1 files changed, 80 insertions, 0 deletions
diff --git a/debian/patches/debian/hid-avoid-abi-change-in-4.17.6.patch b/debian/patches/debian/hid-avoid-abi-change-in-4.17.6.patch
new file mode 100644
index 000000000000..050bdf2b4451
--- /dev/null
+++ b/debian/patches/debian/hid-avoid-abi-change-in-4.17.6.patch
@@ -0,0 +1,80 @@
+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 */