[PATCH 2/2] input: synaptics_usb: do not rely on input_dev->users

From: Marcus Folkesson
Date: Sat Jan 20 2018 - 16:48:17 EST


If the device is unused and suspended, a call to open will cause the
device to autoresume through the call to usb_autopm_get_interface().

input_dev->users is already incremented by the input subsystem,
therefore this expression will always be evaluated to true:

if ((input_dev->users || (synusb->flags & SYNUSB_IO_ALWAYS)) &&
usb_submit_urb(synusb->urb, GFP_NOIO) < 0) {
retval = -EIO;
}

The same URB will then be fail when resubmitted in synusb_open().

Introduce synusb->is_open to keep track of the state instead.

Signed-off-by: Marcus Folkesson <marcus.folkesson@xxxxxxxxx>
---
drivers/input/mouse/synaptics_usb.c | 9 +++++----
1 file changed, 5 insertions(+), 4 deletions(-)

diff --git a/drivers/input/mouse/synaptics_usb.c b/drivers/input/mouse/synaptics_usb.c
index 2c66913cf5a2..e2b726751220 100644
--- a/drivers/input/mouse/synaptics_usb.c
+++ b/drivers/input/mouse/synaptics_usb.c
@@ -84,6 +84,7 @@ struct synusb {

/* serialize access to open/suspend */
struct mutex pm_mutex;
+ bool is_open;

/* input device related data structures */
struct input_dev *input;
@@ -266,6 +267,7 @@ static int synusb_open(struct input_dev *dev)
}

synusb->intf->needs_remote_wakeup = 1;
+ synusb->is_open = 1;

out:
mutex_unlock(&synusb->pm_mutex);
@@ -283,6 +285,7 @@ static void synusb_close(struct input_dev *dev)
mutex_lock(&synusb->pm_mutex);
usb_kill_urb(synusb->urb);
synusb->intf->needs_remote_wakeup = 0;
+ synusb->is_open = 0;
mutex_unlock(&synusb->pm_mutex);

if (!autopm_error)
@@ -485,12 +488,11 @@ static int synusb_suspend(struct usb_interface *intf, pm_message_t message)
static int synusb_resume(struct usb_interface *intf)
{
struct synusb *synusb = usb_get_intfdata(intf);
- struct input_dev *input_dev = synusb->input;
int retval = 0;

mutex_lock(&synusb->pm_mutex);

- if ((input_dev->users || (synusb->flags & SYNUSB_IO_ALWAYS)) &&
+ if ((synusb->is_open || (synusb->flags & SYNUSB_IO_ALWAYS)) &&
usb_submit_urb(synusb->urb, GFP_NOIO) < 0) {
retval = -EIO;
}
@@ -513,10 +515,9 @@ static int synusb_pre_reset(struct usb_interface *intf)
static int synusb_post_reset(struct usb_interface *intf)
{
struct synusb *synusb = usb_get_intfdata(intf);
- struct input_dev *input_dev = synusb->input;
int retval = 0;

- if ((input_dev->users || (synusb->flags & SYNUSB_IO_ALWAYS)) &&
+ if ((synusb->is_open || (synusb->flags & SYNUSB_IO_ALWAYS)) &&
usb_submit_urb(synusb->urb, GFP_NOIO) < 0) {
retval = -EIO;
}
--
2.15.1