diff options
| -rw-r--r-- | drivers/input/mouse/sentelic.c | 18 | ||||
| -rw-r--r-- | drivers/input/serio/i8042.c | 41 | ||||
| -rw-r--r-- | drivers/input/serio/libps2.c | 28 | ||||
| -rw-r--r-- | drivers/leds/leds-clevo-mail.c | 8 | ||||
| -rw-r--r-- | drivers/platform/x86/acer-wmi.c | 2 | ||||
| -rw-r--r-- | include/linux/i8042.h | 30 | ||||
| -rw-r--r-- | include/linux/libps2.h | 2 |
7 files changed, 117 insertions, 12 deletions
diff --git a/drivers/input/mouse/sentelic.c b/drivers/input/mouse/sentelic.c index 84e2fc04d11b..f84cbd97c884 100644 --- a/drivers/input/mouse/sentelic.c +++ b/drivers/input/mouse/sentelic.c | |||
| @@ -92,7 +92,8 @@ static int fsp_reg_read(struct psmouse *psmouse, int reg_addr, int *reg_val) | |||
| 92 | */ | 92 | */ |
| 93 | ps2_command(ps2dev, NULL, PSMOUSE_CMD_DISABLE); | 93 | ps2_command(ps2dev, NULL, PSMOUSE_CMD_DISABLE); |
| 94 | psmouse_set_state(psmouse, PSMOUSE_CMD_MODE); | 94 | psmouse_set_state(psmouse, PSMOUSE_CMD_MODE); |
| 95 | mutex_lock(&ps2dev->cmd_mutex); | 95 | |
| 96 | ps2_begin_command(ps2dev); | ||
| 96 | 97 | ||
| 97 | if (ps2_sendbyte(ps2dev, 0xf3, FSP_CMD_TIMEOUT) < 0) | 98 | if (ps2_sendbyte(ps2dev, 0xf3, FSP_CMD_TIMEOUT) < 0) |
| 98 | goto out; | 99 | goto out; |
| @@ -126,7 +127,7 @@ static int fsp_reg_read(struct psmouse *psmouse, int reg_addr, int *reg_val) | |||
| 126 | rc = 0; | 127 | rc = 0; |
| 127 | 128 | ||
| 128 | out: | 129 | out: |
| 129 | mutex_unlock(&ps2dev->cmd_mutex); | 130 | ps2_end_command(ps2dev); |
| 130 | ps2_command(ps2dev, NULL, PSMOUSE_CMD_ENABLE); | 131 | ps2_command(ps2dev, NULL, PSMOUSE_CMD_ENABLE); |
| 131 | psmouse_set_state(psmouse, PSMOUSE_ACTIVATED); | 132 | psmouse_set_state(psmouse, PSMOUSE_ACTIVATED); |
| 132 | dev_dbg(&ps2dev->serio->dev, "READ REG: 0x%02x is 0x%02x (rc = %d)\n", | 133 | dev_dbg(&ps2dev->serio->dev, "READ REG: 0x%02x is 0x%02x (rc = %d)\n", |
| @@ -140,7 +141,7 @@ static int fsp_reg_write(struct psmouse *psmouse, int reg_addr, int reg_val) | |||
| 140 | unsigned char v; | 141 | unsigned char v; |
| 141 | int rc = -1; | 142 | int rc = -1; |
| 142 | 143 | ||
| 143 | mutex_lock(&ps2dev->cmd_mutex); | 144 | ps2_begin_command(ps2dev); |
| 144 | 145 | ||
| 145 | if (ps2_sendbyte(ps2dev, 0xf3, FSP_CMD_TIMEOUT) < 0) | 146 | if (ps2_sendbyte(ps2dev, 0xf3, FSP_CMD_TIMEOUT) < 0) |
| 146 | goto out; | 147 | goto out; |
| @@ -179,7 +180,7 @@ static int fsp_reg_write(struct psmouse *psmouse, int reg_addr, int reg_val) | |||
| 179 | rc = 0; | 180 | rc = 0; |
| 180 | 181 | ||
| 181 | out: | 182 | out: |
| 182 | mutex_unlock(&ps2dev->cmd_mutex); | 183 | ps2_end_command(ps2dev); |
| 183 | dev_dbg(&ps2dev->serio->dev, "WRITE REG: 0x%02x to 0x%02x (rc = %d)\n", | 184 | dev_dbg(&ps2dev->serio->dev, "WRITE REG: 0x%02x to 0x%02x (rc = %d)\n", |
| 184 | reg_addr, reg_val, rc); | 185 | reg_addr, reg_val, rc); |
| 185 | return rc; | 186 | return rc; |
| @@ -214,7 +215,8 @@ static int fsp_page_reg_read(struct psmouse *psmouse, int *reg_val) | |||
| 214 | 215 | ||
| 215 | ps2_command(ps2dev, NULL, PSMOUSE_CMD_DISABLE); | 216 | ps2_command(ps2dev, NULL, PSMOUSE_CMD_DISABLE); |
| 216 | psmouse_set_state(psmouse, PSMOUSE_CMD_MODE); | 217 | psmouse_set_state(psmouse, PSMOUSE_CMD_MODE); |
| 217 | mutex_lock(&ps2dev->cmd_mutex); | 218 | |
| 219 | ps2_begin_command(ps2dev); | ||
| 218 | 220 | ||
| 219 | if (ps2_sendbyte(ps2dev, 0xf3, FSP_CMD_TIMEOUT) < 0) | 221 | if (ps2_sendbyte(ps2dev, 0xf3, FSP_CMD_TIMEOUT) < 0) |
| 220 | goto out; | 222 | goto out; |
| @@ -236,7 +238,7 @@ static int fsp_page_reg_read(struct psmouse *psmouse, int *reg_val) | |||
| 236 | rc = 0; | 238 | rc = 0; |
| 237 | 239 | ||
| 238 | out: | 240 | out: |
| 239 | mutex_unlock(&ps2dev->cmd_mutex); | 241 | ps2_end_command(ps2dev); |
| 240 | ps2_command(ps2dev, NULL, PSMOUSE_CMD_ENABLE); | 242 | ps2_command(ps2dev, NULL, PSMOUSE_CMD_ENABLE); |
| 241 | psmouse_set_state(psmouse, PSMOUSE_ACTIVATED); | 243 | psmouse_set_state(psmouse, PSMOUSE_ACTIVATED); |
| 242 | dev_dbg(&ps2dev->serio->dev, "READ PAGE REG: 0x%02x (rc = %d)\n", | 244 | dev_dbg(&ps2dev->serio->dev, "READ PAGE REG: 0x%02x (rc = %d)\n", |
| @@ -250,7 +252,7 @@ static int fsp_page_reg_write(struct psmouse *psmouse, int reg_val) | |||
| 250 | unsigned char v; | 252 | unsigned char v; |
| 251 | int rc = -1; | 253 | int rc = -1; |
| 252 | 254 | ||
| 253 | mutex_lock(&ps2dev->cmd_mutex); | 255 | ps2_begin_command(ps2dev); |
| 254 | 256 | ||
| 255 | if (ps2_sendbyte(ps2dev, 0xf3, FSP_CMD_TIMEOUT) < 0) | 257 | if (ps2_sendbyte(ps2dev, 0xf3, FSP_CMD_TIMEOUT) < 0) |
| 256 | goto out; | 258 | goto out; |
| @@ -275,7 +277,7 @@ static int fsp_page_reg_write(struct psmouse *psmouse, int reg_val) | |||
| 275 | rc = 0; | 277 | rc = 0; |
| 276 | 278 | ||
| 277 | out: | 279 | out: |
| 278 | mutex_unlock(&ps2dev->cmd_mutex); | 280 | ps2_end_command(ps2dev); |
| 279 | dev_dbg(&ps2dev->serio->dev, "WRITE PAGE REG: to 0x%02x (rc = %d)\n", | 281 | dev_dbg(&ps2dev->serio->dev, "WRITE PAGE REG: to 0x%02x (rc = %d)\n", |
| 280 | reg_val, rc); | 282 | reg_val, rc); |
| 281 | return rc; | 283 | return rc; |
diff --git a/drivers/input/serio/i8042.c b/drivers/input/serio/i8042.c index eb3ff94af58c..bc56e52b945f 100644 --- a/drivers/input/serio/i8042.c +++ b/drivers/input/serio/i8042.c | |||
| @@ -87,8 +87,22 @@ static bool i8042_bypass_aux_irq_test; | |||
| 87 | 87 | ||
| 88 | #include "i8042.h" | 88 | #include "i8042.h" |
| 89 | 89 | ||
| 90 | /* | ||
| 91 | * i8042_lock protects serialization between i8042_command and | ||
| 92 | * the interrupt handler. | ||
| 93 | */ | ||
| 90 | static DEFINE_SPINLOCK(i8042_lock); | 94 | static DEFINE_SPINLOCK(i8042_lock); |
| 91 | 95 | ||
| 96 | /* | ||
| 97 | * Writers to AUX and KBD ports as well as users issuing i8042_command | ||
| 98 | * directly should acquire i8042_mutex (by means of calling | ||
| 99 | * i8042_lock_chip() and i8042_unlock_ship() helpers) to ensure that | ||
| 100 | * they do not disturb each other (unfortunately in many i8042 | ||
| 101 | * implementations write to one of the ports will immediately abort | ||
| 102 | * command that is being processed by another port). | ||
| 103 | */ | ||
| 104 | static DEFINE_MUTEX(i8042_mutex); | ||
| 105 | |||
| 92 | struct i8042_port { | 106 | struct i8042_port { |
| 93 | struct serio *serio; | 107 | struct serio *serio; |
| 94 | int irq; | 108 | int irq; |
| @@ -113,6 +127,18 @@ static struct platform_device *i8042_platform_device; | |||
| 113 | 127 | ||
| 114 | static irqreturn_t i8042_interrupt(int irq, void *dev_id); | 128 | static irqreturn_t i8042_interrupt(int irq, void *dev_id); |
| 115 | 129 | ||
| 130 | void i8042_lock_chip(void) | ||
| 131 | { | ||
| 132 | mutex_lock(&i8042_mutex); | ||
| 133 | } | ||
| 134 | EXPORT_SYMBOL(i8042_lock_chip); | ||
| 135 | |||
| 136 | void i8042_unlock_chip(void) | ||
| 137 | { | ||
| 138 | mutex_unlock(&i8042_mutex); | ||
| 139 | } | ||
| 140 | EXPORT_SYMBOL(i8042_unlock_chip); | ||
| 141 | |||
| 116 | /* | 142 | /* |
| 117 | * The i8042_wait_read() and i8042_wait_write functions wait for the i8042 to | 143 | * The i8042_wait_read() and i8042_wait_write functions wait for the i8042 to |
| 118 | * be ready for reading values from it / writing values to it. | 144 | * be ready for reading values from it / writing values to it. |
| @@ -1161,6 +1187,21 @@ static void __devexit i8042_unregister_ports(void) | |||
| 1161 | } | 1187 | } |
| 1162 | } | 1188 | } |
| 1163 | 1189 | ||
| 1190 | /* | ||
| 1191 | * Checks whether port belongs to i8042 controller. | ||
| 1192 | */ | ||
| 1193 | bool i8042_check_port_owner(const struct serio *port) | ||
| 1194 | { | ||
| 1195 | int i; | ||
| 1196 | |||
| 1197 | for (i = 0; i < I8042_NUM_PORTS; i++) | ||
| 1198 | if (i8042_ports[i].serio == port) | ||
| 1199 | return true; | ||
| 1200 | |||
| 1201 | return false; | ||
| 1202 | } | ||
| 1203 | EXPORT_SYMBOL(i8042_check_port_owner); | ||
| 1204 | |||
| 1164 | static void i8042_free_irqs(void) | 1205 | static void i8042_free_irqs(void) |
| 1165 | { | 1206 | { |
| 1166 | if (i8042_aux_irq_registered) | 1207 | if (i8042_aux_irq_registered) |
diff --git a/drivers/input/serio/libps2.c b/drivers/input/serio/libps2.c index 3a95b508bf27..769ba65a585a 100644 --- a/drivers/input/serio/libps2.c +++ b/drivers/input/serio/libps2.c | |||
| @@ -17,6 +17,7 @@ | |||
| 17 | #include <linux/interrupt.h> | 17 | #include <linux/interrupt.h> |
| 18 | #include <linux/input.h> | 18 | #include <linux/input.h> |
| 19 | #include <linux/serio.h> | 19 | #include <linux/serio.h> |
| 20 | #include <linux/i8042.h> | ||
| 20 | #include <linux/init.h> | 21 | #include <linux/init.h> |
| 21 | #include <linux/libps2.h> | 22 | #include <linux/libps2.h> |
| 22 | 23 | ||
| @@ -54,6 +55,24 @@ int ps2_sendbyte(struct ps2dev *ps2dev, unsigned char byte, int timeout) | |||
| 54 | } | 55 | } |
| 55 | EXPORT_SYMBOL(ps2_sendbyte); | 56 | EXPORT_SYMBOL(ps2_sendbyte); |
| 56 | 57 | ||
| 58 | void ps2_begin_command(struct ps2dev *ps2dev) | ||
| 59 | { | ||
| 60 | mutex_lock(&ps2dev->cmd_mutex); | ||
| 61 | |||
| 62 | if (i8042_check_port_owner(ps2dev->serio)) | ||
| 63 | i8042_lock_chip(); | ||
| 64 | } | ||
| 65 | EXPORT_SYMBOL(ps2_begin_command); | ||
| 66 | |||
| 67 | void ps2_end_command(struct ps2dev *ps2dev) | ||
| 68 | { | ||
| 69 | if (i8042_check_port_owner(ps2dev->serio)) | ||
| 70 | i8042_unlock_chip(); | ||
| 71 | |||
| 72 | mutex_unlock(&ps2dev->cmd_mutex); | ||
| 73 | } | ||
| 74 | EXPORT_SYMBOL(ps2_end_command); | ||
| 75 | |||
| 57 | /* | 76 | /* |
| 58 | * ps2_drain() waits for device to transmit requested number of bytes | 77 | * ps2_drain() waits for device to transmit requested number of bytes |
| 59 | * and discards them. | 78 | * and discards them. |
| @@ -66,7 +85,7 @@ void ps2_drain(struct ps2dev *ps2dev, int maxbytes, int timeout) | |||
| 66 | maxbytes = sizeof(ps2dev->cmdbuf); | 85 | maxbytes = sizeof(ps2dev->cmdbuf); |
| 67 | } | 86 | } |
| 68 | 87 | ||
| 69 | mutex_lock(&ps2dev->cmd_mutex); | 88 | ps2_begin_command(ps2dev); |
| 70 | 89 | ||
| 71 | serio_pause_rx(ps2dev->serio); | 90 | serio_pause_rx(ps2dev->serio); |
| 72 | ps2dev->flags = PS2_FLAG_CMD; | 91 | ps2dev->flags = PS2_FLAG_CMD; |
| @@ -76,7 +95,8 @@ void ps2_drain(struct ps2dev *ps2dev, int maxbytes, int timeout) | |||
| 76 | wait_event_timeout(ps2dev->wait, | 95 | wait_event_timeout(ps2dev->wait, |
| 77 | !(ps2dev->flags & PS2_FLAG_CMD), | 96 | !(ps2dev->flags & PS2_FLAG_CMD), |
| 78 | msecs_to_jiffies(timeout)); | 97 | msecs_to_jiffies(timeout)); |
| 79 | mutex_unlock(&ps2dev->cmd_mutex); | 98 | |
| 99 | ps2_end_command(ps2dev); | ||
| 80 | } | 100 | } |
| 81 | EXPORT_SYMBOL(ps2_drain); | 101 | EXPORT_SYMBOL(ps2_drain); |
| 82 | 102 | ||
| @@ -237,9 +257,9 @@ int ps2_command(struct ps2dev *ps2dev, unsigned char *param, int command) | |||
| 237 | { | 257 | { |
| 238 | int rc; | 258 | int rc; |
| 239 | 259 | ||
| 240 | mutex_lock(&ps2dev->cmd_mutex); | 260 | ps2_begin_command(ps2dev); |
| 241 | rc = __ps2_command(ps2dev, param, command); | 261 | rc = __ps2_command(ps2dev, param, command); |
| 242 | mutex_unlock(&ps2dev->cmd_mutex); | 262 | ps2_end_command(ps2dev); |
| 243 | 263 | ||
| 244 | return rc; | 264 | return rc; |
| 245 | } | 265 | } |
diff --git a/drivers/leds/leds-clevo-mail.c b/drivers/leds/leds-clevo-mail.c index 1813c84ea5fc..f2242db54016 100644 --- a/drivers/leds/leds-clevo-mail.c +++ b/drivers/leds/leds-clevo-mail.c | |||
| @@ -93,6 +93,8 @@ static struct dmi_system_id __initdata mail_led_whitelist[] = { | |||
| 93 | static void clevo_mail_led_set(struct led_classdev *led_cdev, | 93 | static void clevo_mail_led_set(struct led_classdev *led_cdev, |
| 94 | enum led_brightness value) | 94 | enum led_brightness value) |
| 95 | { | 95 | { |
| 96 | i8042_lock_chip(); | ||
| 97 | |||
| 96 | if (value == LED_OFF) | 98 | if (value == LED_OFF) |
| 97 | i8042_command(NULL, CLEVO_MAIL_LED_OFF); | 99 | i8042_command(NULL, CLEVO_MAIL_LED_OFF); |
| 98 | else if (value <= LED_HALF) | 100 | else if (value <= LED_HALF) |
| @@ -100,6 +102,8 @@ static void clevo_mail_led_set(struct led_classdev *led_cdev, | |||
| 100 | else | 102 | else |
| 101 | i8042_command(NULL, CLEVO_MAIL_LED_BLINK_1HZ); | 103 | i8042_command(NULL, CLEVO_MAIL_LED_BLINK_1HZ); |
| 102 | 104 | ||
| 105 | i8042_unlock_chip(); | ||
| 106 | |||
| 103 | } | 107 | } |
| 104 | 108 | ||
| 105 | static int clevo_mail_led_blink(struct led_classdev *led_cdev, | 109 | static int clevo_mail_led_blink(struct led_classdev *led_cdev, |
| @@ -108,6 +112,8 @@ static int clevo_mail_led_blink(struct led_classdev *led_cdev, | |||
| 108 | { | 112 | { |
| 109 | int status = -EINVAL; | 113 | int status = -EINVAL; |
| 110 | 114 | ||
| 115 | i8042_lock_chip(); | ||
| 116 | |||
| 111 | if (*delay_on == 0 /* ms */ && *delay_off == 0 /* ms */) { | 117 | if (*delay_on == 0 /* ms */ && *delay_off == 0 /* ms */) { |
| 112 | /* Special case: the leds subsystem requested us to | 118 | /* Special case: the leds subsystem requested us to |
| 113 | * chose one user friendly blinking of the LED, and | 119 | * chose one user friendly blinking of the LED, and |
| @@ -135,6 +141,8 @@ static int clevo_mail_led_blink(struct led_classdev *led_cdev, | |||
| 135 | *delay_on, *delay_off); | 141 | *delay_on, *delay_off); |
| 136 | } | 142 | } |
| 137 | 143 | ||
| 144 | i8042_unlock_chip(); | ||
| 145 | |||
| 138 | return status; | 146 | return status; |
| 139 | } | 147 | } |
| 140 | 148 | ||
diff --git a/drivers/platform/x86/acer-wmi.c b/drivers/platform/x86/acer-wmi.c index fb45f5ee8df1..454970d2d701 100644 --- a/drivers/platform/x86/acer-wmi.c +++ b/drivers/platform/x86/acer-wmi.c | |||
| @@ -746,7 +746,9 @@ static acpi_status WMID_set_u32(u32 value, u32 cap, struct wmi_interface *iface) | |||
| 746 | return AE_BAD_PARAMETER; | 746 | return AE_BAD_PARAMETER; |
| 747 | if (quirks->mailled == 1) { | 747 | if (quirks->mailled == 1) { |
| 748 | param = value ? 0x92 : 0x93; | 748 | param = value ? 0x92 : 0x93; |
| 749 | i8042_lock_chip(); | ||
| 749 | i8042_command(¶m, 0x1059); | 750 | i8042_command(¶m, 0x1059); |
| 751 | i8042_unlock_chip(); | ||
| 750 | return 0; | 752 | return 0; |
| 751 | } | 753 | } |
| 752 | break; | 754 | break; |
diff --git a/include/linux/i8042.h b/include/linux/i8042.h index 7907a72403ee..60c3360ef6ad 100644 --- a/include/linux/i8042.h +++ b/include/linux/i8042.h | |||
| @@ -7,6 +7,7 @@ | |||
| 7 | * the Free Software Foundation. | 7 | * the Free Software Foundation. |
| 8 | */ | 8 | */ |
| 9 | 9 | ||
| 10 | #include <linux/types.h> | ||
| 10 | 11 | ||
| 11 | /* | 12 | /* |
| 12 | * Standard commands. | 13 | * Standard commands. |
| @@ -30,6 +31,35 @@ | |||
| 30 | #define I8042_CMD_MUX_PFX 0x0090 | 31 | #define I8042_CMD_MUX_PFX 0x0090 |
| 31 | #define I8042_CMD_MUX_SEND 0x1090 | 32 | #define I8042_CMD_MUX_SEND 0x1090 |
| 32 | 33 | ||
| 34 | struct serio; | ||
| 35 | |||
| 36 | #if defined(CONFIG_SERIO_I8042) || defined(CONFIG_SERIO_I8042_MODULE) | ||
| 37 | |||
| 38 | void i8042_lock_chip(void); | ||
| 39 | void i8042_unlock_chip(void); | ||
| 33 | int i8042_command(unsigned char *param, int command); | 40 | int i8042_command(unsigned char *param, int command); |
| 41 | bool i8042_check_port_owner(const struct serio *); | ||
| 42 | |||
| 43 | #else | ||
| 44 | |||
| 45 | void i8042_lock_chip(void) | ||
| 46 | { | ||
| 47 | } | ||
| 48 | |||
| 49 | void i8042_unlock_chip(void) | ||
| 50 | { | ||
| 51 | } | ||
| 52 | |||
| 53 | int i8042_command(unsigned char *param, int command) | ||
| 54 | { | ||
| 55 | return -ENOSYS; | ||
| 56 | } | ||
| 57 | |||
| 58 | bool i8042_check_port_owner(const struct serio *serio) | ||
| 59 | { | ||
| 60 | return false; | ||
| 61 | } | ||
| 62 | |||
| 63 | #endif | ||
| 34 | 64 | ||
| 35 | #endif | 65 | #endif |
diff --git a/include/linux/libps2.h b/include/linux/libps2.h index fcf5fbe6a50c..79603a6c356f 100644 --- a/include/linux/libps2.h +++ b/include/linux/libps2.h | |||
| @@ -44,6 +44,8 @@ struct ps2dev { | |||
| 44 | void ps2_init(struct ps2dev *ps2dev, struct serio *serio); | 44 | void ps2_init(struct ps2dev *ps2dev, struct serio *serio); |
| 45 | int ps2_sendbyte(struct ps2dev *ps2dev, unsigned char byte, int timeout); | 45 | int ps2_sendbyte(struct ps2dev *ps2dev, unsigned char byte, int timeout); |
| 46 | void ps2_drain(struct ps2dev *ps2dev, int maxbytes, int timeout); | 46 | void ps2_drain(struct ps2dev *ps2dev, int maxbytes, int timeout); |
| 47 | void ps2_begin_command(struct ps2dev *ps2dev); | ||
| 48 | void ps2_end_command(struct ps2dev *ps2dev); | ||
| 47 | int __ps2_command(struct ps2dev *ps2dev, unsigned char *param, int command); | 49 | int __ps2_command(struct ps2dev *ps2dev, unsigned char *param, int command); |
| 48 | int ps2_command(struct ps2dev *ps2dev, unsigned char *param, int command); | 50 | int ps2_command(struct ps2dev *ps2dev, unsigned char *param, int command); |
| 49 | int ps2_handle_ack(struct ps2dev *ps2dev, unsigned char data); | 51 | int ps2_handle_ack(struct ps2dev *ps2dev, unsigned char data); |
