aboutsummaryrefslogtreecommitdiff
path: root/drivers/input/serio/libps2.c
diff options
context:
space:
mode:
authorLinus Torvalds <torvalds@linux-foundation.org>2009-09-23 15:39:36 -0700
committerLinus Torvalds <torvalds@linux-foundation.org>2009-09-23 15:39:36 -0700
commit0dd52d0df02733dfc2d5f3824e41b96492305384 (patch)
tree4cfd84b7a66d71d83c624275d889136fb23a33c9 /drivers/input/serio/libps2.c
parentc37efa932598de5e30330a1414e34d9e082e0d9e (diff)
parentfde1132374c9ba7da98a73b9a3c150dca6cf8502 (diff)
Merge branch 'for-linus' of git://git.kernel.org/pub/scm/linux/kernel/git/dtor/input
* 'for-linus' of git://git.kernel.org/pub/scm/linux/kernel/git/dtor/input: Input: add driver for Atmel AT42QT2160 Sensor Chip Input: max7359 - use threaded IRQs Input: add driver for Maxim MAX7359 key switch controller Input: add driver for ADP5588 QWERTY I2C Keypad Input: add touchscreen driver for MELFAS MCS-5000 controller Input: add driver for OpenCores Keyboard Controller Input: dm355evm_keys - remove dm355evm_keys_hardirq Input: synaptics_i2c - switch to using __cancel_delayed_work() Input: ad7879 - add support for AD7889 Input: atkbd - rely on input core to restore state on resume Input: add generic suspend and resume for input devices Input: libps2 - additional locking for i8042 ports
Diffstat (limited to 'drivers/input/serio/libps2.c')
-rw-r--r--drivers/input/serio/libps2.c28
1 files changed, 24 insertions, 4 deletions
diff --git a/drivers/input/serio/libps2.c b/drivers/input/serio/libps2.c
index 3a95b508bf2..769ba65a585 100644
--- a/drivers/input/serio/libps2.c
+++ b/drivers/input/serio/libps2.c
@@ -17,6 +17,7 @@
#include <linux/interrupt.h>
#include <linux/input.h>
#include <linux/serio.h>
+#include <linux/i8042.h>
#include <linux/init.h>
#include <linux/libps2.h>
@@ -54,6 +55,24 @@ int ps2_sendbyte(struct ps2dev *ps2dev, unsigned char byte, int timeout)
}
EXPORT_SYMBOL(ps2_sendbyte);
+void ps2_begin_command(struct ps2dev *ps2dev)
+{
+ mutex_lock(&ps2dev->cmd_mutex);
+
+ if (i8042_check_port_owner(ps2dev->serio))
+ i8042_lock_chip();
+}
+EXPORT_SYMBOL(ps2_begin_command);
+
+void ps2_end_command(struct ps2dev *ps2dev)
+{
+ if (i8042_check_port_owner(ps2dev->serio))
+ i8042_unlock_chip();
+
+ mutex_unlock(&ps2dev->cmd_mutex);
+}
+EXPORT_SYMBOL(ps2_end_command);
+
/*
* ps2_drain() waits for device to transmit requested number of bytes
* and discards them.
@@ -66,7 +85,7 @@ void ps2_drain(struct ps2dev *ps2dev, int maxbytes, int timeout)
maxbytes = sizeof(ps2dev->cmdbuf);
}
- mutex_lock(&ps2dev->cmd_mutex);
+ ps2_begin_command(ps2dev);
serio_pause_rx(ps2dev->serio);
ps2dev->flags = PS2_FLAG_CMD;
@@ -76,7 +95,8 @@ void ps2_drain(struct ps2dev *ps2dev, int maxbytes, int timeout)
wait_event_timeout(ps2dev->wait,
!(ps2dev->flags & PS2_FLAG_CMD),
msecs_to_jiffies(timeout));
- mutex_unlock(&ps2dev->cmd_mutex);
+
+ ps2_end_command(ps2dev);
}
EXPORT_SYMBOL(ps2_drain);
@@ -237,9 +257,9 @@ int ps2_command(struct ps2dev *ps2dev, unsigned char *param, int command)
{
int rc;
- mutex_lock(&ps2dev->cmd_mutex);
+ ps2_begin_command(ps2dev);
rc = __ps2_command(ps2dev, param, command);
- mutex_unlock(&ps2dev->cmd_mutex);
+ ps2_end_command(ps2dev);
return rc;
}