diff options
Diffstat (limited to 'drivers/hid')
-rw-r--r-- | drivers/hid/hid-wiimote.c | 19 |
1 files changed, 19 insertions, 0 deletions
diff --git a/drivers/hid/hid-wiimote.c b/drivers/hid/hid-wiimote.c index deaf23207812..3416f69302cd 100644 --- a/drivers/hid/hid-wiimote.c +++ b/drivers/hid/hid-wiimote.c | |||
@@ -10,6 +10,7 @@ | |||
10 | * any later version. | 10 | * any later version. |
11 | */ | 11 | */ |
12 | 12 | ||
13 | #include <linux/atomic.h> | ||
13 | #include <linux/device.h> | 14 | #include <linux/device.h> |
14 | #include <linux/hid.h> | 15 | #include <linux/hid.h> |
15 | #include <linux/input.h> | 16 | #include <linux/input.h> |
@@ -20,6 +21,7 @@ | |||
20 | #define WIIMOTE_NAME "Nintendo Wii Remote" | 21 | #define WIIMOTE_NAME "Nintendo Wii Remote" |
21 | 22 | ||
22 | struct wiimote_data { | 23 | struct wiimote_data { |
24 | atomic_t ready; | ||
23 | struct hid_device *hdev; | 25 | struct hid_device *hdev; |
24 | struct input_dev *input; | 26 | struct input_dev *input; |
25 | }; | 27 | }; |
@@ -27,12 +29,26 @@ struct wiimote_data { | |||
27 | static int wiimote_input_event(struct input_dev *dev, unsigned int type, | 29 | static int wiimote_input_event(struct input_dev *dev, unsigned int type, |
28 | unsigned int code, int value) | 30 | unsigned int code, int value) |
29 | { | 31 | { |
32 | struct wiimote_data *wdata = input_get_drvdata(dev); | ||
33 | |||
34 | if (!atomic_read(&wdata->ready)) | ||
35 | return -EBUSY; | ||
36 | /* smp_rmb: Make sure wdata->xy is available when wdata->ready is 1 */ | ||
37 | smp_rmb(); | ||
38 | |||
30 | return 0; | 39 | return 0; |
31 | } | 40 | } |
32 | 41 | ||
33 | static int wiimote_hid_event(struct hid_device *hdev, struct hid_report *report, | 42 | static int wiimote_hid_event(struct hid_device *hdev, struct hid_report *report, |
34 | u8 *raw_data, int size) | 43 | u8 *raw_data, int size) |
35 | { | 44 | { |
45 | struct wiimote_data *wdata = hid_get_drvdata(hdev); | ||
46 | |||
47 | if (!atomic_read(&wdata->ready)) | ||
48 | return -EBUSY; | ||
49 | /* smp_rmb: Make sure wdata->xy is available when wdata->ready is 1 */ | ||
50 | smp_rmb(); | ||
51 | |||
36 | if (size < 1) | 52 | if (size < 1) |
37 | return -EINVAL; | 53 | return -EINVAL; |
38 | 54 | ||
@@ -103,6 +119,9 @@ static int wiimote_hid_probe(struct hid_device *hdev, | |||
103 | goto err_stop; | 119 | goto err_stop; |
104 | } | 120 | } |
105 | 121 | ||
122 | /* smp_wmb: Write wdata->xy first before wdata->ready is set to 1 */ | ||
123 | smp_wmb(); | ||
124 | atomic_set(&wdata->ready, 1); | ||
106 | hid_info(hdev, "New device registered\n"); | 125 | hid_info(hdev, "New device registered\n"); |
107 | return 0; | 126 | return 0; |
108 | 127 | ||