97aee9c
From f1a9a149abc86903e81dd1b2e720f3f89874384b Mon Sep 17 00:00:00 2001
97aee9c
From: Benjamin Tissoires <benjamin.tissoires@redhat.com>
97aee9c
Date: Tue, 2 Apr 2013 11:11:52 +0200
97aee9c
Subject: HID: magicmouse: fix race between input_register() and probe()
97aee9c
97aee9c
From: Benjamin Tissoires <benjamin.tissoires@redhat.com>
97aee9c
97aee9c
commit f1a9a149abc86903e81dd1b2e720f3f89874384b upstream.
97aee9c
97aee9c
Since kernel 3.7, it appears that the input registration occured before
97aee9c
the end of magicmouse_setup_input(). This is shown by receiving a lot of
97aee9c
"EV_SYN SYN_REPORT 1" instead of normal "EV_SYN SYN_REPORT 0".
97aee9c
This value means that the output buffer is full, and the user space
97aee9c
is loosing events.
97aee9c
97aee9c
Using .input_configured guarantees that the race is not occuring, and that
97aee9c
the call of "input_set_events_per_packet(input, 60)" is taken into account
97aee9c
by input_register().
97aee9c
97aee9c
Fixes:
97aee9c
https://bugzilla.redhat.com/show_bug.cgi?id=908604
97aee9c
97aee9c
Reported-and-Tested-By: Clarke Wixon <cwixon@usa.net>
97aee9c
Signed-off-by: Benjamin Tissoires <benjamin.tissoires@redhat.com>
97aee9c
Signed-off-by: Jiri Kosina <jkosina@suse.cz>
97aee9c
Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
97aee9c
97aee9c
---
97aee9c
 drivers/hid/hid-magicmouse.c |   29 ++++++++++++++++++++---------
97aee9c
 1 file changed, 20 insertions(+), 9 deletions(-)
97aee9c
97aee9c
--- a/drivers/hid/hid-magicmouse.c
97aee9c
+++ b/drivers/hid/hid-magicmouse.c
97aee9c
@@ -462,6 +462,21 @@ static int magicmouse_input_mapping(stru
97aee9c
 	return 0;
97aee9c
 }
97aee9c
 
97aee9c
+static void magicmouse_input_configured(struct hid_device *hdev,
97aee9c
+		struct hid_input *hi)
97aee9c
+
97aee9c
+{
97aee9c
+	struct magicmouse_sc *msc = hid_get_drvdata(hdev);
97aee9c
+
97aee9c
+	int ret = magicmouse_setup_input(msc->input, hdev);
97aee9c
+	if (ret) {
97aee9c
+		hid_err(hdev, "magicmouse setup input failed (%d)\n", ret);
97aee9c
+		/* clean msc->input to notify probe() of the failure */
97aee9c
+		msc->input = NULL;
97aee9c
+	}
97aee9c
+}
97aee9c
+
97aee9c
+
97aee9c
 static int magicmouse_probe(struct hid_device *hdev,
97aee9c
 	const struct hid_device_id *id)
97aee9c
 {
97aee9c
@@ -493,15 +508,10 @@ static int magicmouse_probe(struct hid_d
97aee9c
 		goto err_free;
97aee9c
 	}
97aee9c
 
97aee9c
-	/* We do this after hid-input is done parsing reports so that
97aee9c
-	 * hid-input uses the most natural button and axis IDs.
97aee9c
-	 */
97aee9c
-	if (msc->input) {
97aee9c
-		ret = magicmouse_setup_input(msc->input, hdev);
97aee9c
-		if (ret) {
97aee9c
-			hid_err(hdev, "magicmouse setup input failed (%d)\n", ret);
97aee9c
-			goto err_stop_hw;
97aee9c
-		}
97aee9c
+	if (!msc->input) {
97aee9c
+		hid_err(hdev, "magicmouse input not registered\n");
97aee9c
+		ret = -ENOMEM;
97aee9c
+		goto err_stop_hw;
97aee9c
 	}
97aee9c
 
97aee9c
 	if (id->product == USB_DEVICE_ID_APPLE_MAGICMOUSE)
97aee9c
@@ -568,6 +578,7 @@ static struct hid_driver magicmouse_driv
97aee9c
 	.remove = magicmouse_remove,
97aee9c
 	.raw_event = magicmouse_raw_event,
97aee9c
 	.input_mapping = magicmouse_input_mapping,
97aee9c
+	.input_configured = magicmouse_input_configured,
97aee9c
 };
97aee9c
 
97aee9c
 static int __init magicmouse_init(void)