summaryrefslogtreecommitdiff
path: root/drivers/input/mouse/psmouse-base.c
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/input/mouse/psmouse-base.c')
-rw-r--r--drivers/input/mouse/psmouse-base.c141
1 files changed, 53 insertions, 88 deletions
diff --git a/drivers/input/mouse/psmouse-base.c b/drivers/input/mouse/psmouse-base.c
index 77ea7da3b1c5..23164688210d 100644
--- a/drivers/input/mouse/psmouse-base.c
+++ b/drivers/input/mouse/psmouse-base.c
@@ -26,7 +26,6 @@
#include "synaptics.h"
#include "logips2pp.h"
#include "alps.h"
-#include "hgpk.h"
#include "lifebook.h"
#include "trackpoint.h"
#include "touchkit_ps2.h"
@@ -114,8 +113,6 @@ ATTRIBUTE_GROUPS(psmouse_dev);
*/
static DEFINE_MUTEX(psmouse_mutex);
-static struct workqueue_struct *kpsmoused_wq;
-
struct psmouse *psmouse_from_serio(struct serio *serio)
{
struct ps2dev *ps2dev = serio_get_drvdata(serio);
@@ -241,12 +238,6 @@ psmouse_ret_t psmouse_process_byte(struct psmouse *psmouse)
return PSMOUSE_FULL_PACKET;
}
-void psmouse_queue_work(struct psmouse *psmouse, struct delayed_work *work,
- unsigned long delay)
-{
- queue_delayed_work(kpsmoused_wq, work, delay);
-}
-
/*
* __psmouse_set_state() sets new psmouse state and resets all flags.
*/
@@ -265,9 +256,8 @@ static inline void __psmouse_set_state(struct psmouse *psmouse, enum psmouse_sta
*/
void psmouse_set_state(struct psmouse *psmouse, enum psmouse_state new_state)
{
- serio_pause_rx(psmouse->ps2dev.serio);
+ guard(serio_pause_rx)(psmouse->ps2dev.serio);
__psmouse_set_state(psmouse, new_state);
- serio_continue_rx(psmouse->ps2dev.serio);
}
/*
@@ -276,7 +266,15 @@ void psmouse_set_state(struct psmouse *psmouse, enum psmouse_state new_state)
*/
static int psmouse_handle_byte(struct psmouse *psmouse)
{
- psmouse_ret_t rc = psmouse->protocol_handler(psmouse);
+ psmouse_ret_t rc;
+
+ /* protocol_handler is NULL when device is being disconnected */
+ if (unlikely(!psmouse->protocol_handler)) {
+ psmouse->pktcnt = 0;
+ return 0;
+ }
+
+ rc = psmouse->protocol_handler(psmouse);
switch (rc) {
case PSMOUSE_BAD_DATA:
@@ -380,7 +378,7 @@ static void psmouse_receive_byte(struct ps2dev *ps2dev, u8 data)
psmouse->name, psmouse->phys, psmouse->pktcnt);
psmouse->badbyte = psmouse->packet[0];
__psmouse_set_state(psmouse, PSMOUSE_RESYNCING);
- psmouse_queue_work(psmouse, &psmouse->resync_work, 0);
+ schedule_work(&psmouse->resync_work);
return;
}
@@ -393,9 +391,7 @@ static void psmouse_receive_byte(struct ps2dev *ps2dev, u8 data)
return;
}
- if (psmouse->packet[1] == PSMOUSE_RET_ID ||
- (psmouse->protocol->type == PSMOUSE_HGPK &&
- psmouse->packet[1] == PSMOUSE_RET_BAT)) {
+ if (psmouse->packet[1] == PSMOUSE_RET_ID) {
__psmouse_set_state(psmouse, PSMOUSE_IGNORE);
serio_reconnect(ps2dev->serio);
return;
@@ -418,7 +414,7 @@ static void psmouse_receive_byte(struct ps2dev *ps2dev, u8 data)
time_after(jiffies, psmouse->last + psmouse->resync_time * HZ)) {
psmouse->badbyte = psmouse->packet[0];
__psmouse_set_state(psmouse, PSMOUSE_RESYNCING);
- psmouse_queue_work(psmouse, &psmouse->resync_work, 0);
+ schedule_work(&psmouse->resync_work);
return;
}
@@ -495,13 +491,16 @@ static int psmouse_poll(struct psmouse *psmouse)
PSMOUSE_CMD_POLL | (psmouse->pktsize << 8));
}
-static bool psmouse_check_pnp_id(const char *id, const char * const ids[])
+static bool psmouse_check_pnp_id(const char *p, const char * const ids[])
{
- int i;
+ const char * const *id;
+ size_t len;
- for (i = 0; ids[i]; i++)
- if (!strcasecmp(id, ids[i]))
+ for (id = ids; *id; id++) {
+ len = strlen(*id);
+ if (!strncasecmp(p, *id, len) && (p[len] == ' ' || p[len] == '\0'))
return true;
+ }
return false;
}
@@ -512,28 +511,26 @@ static bool psmouse_check_pnp_id(const char *id, const char * const ids[])
bool psmouse_matches_pnp_id(struct psmouse *psmouse, const char * const ids[])
{
struct serio *serio = psmouse->ps2dev.serio;
- char *p, *fw_id_copy, *save_ptr;
- bool found = false;
+ const char *p = serio->firmware_id;
- if (strncmp(serio->firmware_id, "PNP: ", 5))
+ if (!strstarts(p, "PNP: "))
return false;
- fw_id_copy = kstrndup(&serio->firmware_id[5],
- sizeof(serio->firmware_id) - 5,
- GFP_KERNEL);
- if (!fw_id_copy)
- return false;
+ p += 5;
+ while (*p) {
+ p = skip_spaces(p);
+ if (!*p)
+ break;
- save_ptr = fw_id_copy;
- while ((p = strsep(&fw_id_copy, " ")) != NULL) {
- if (psmouse_check_pnp_id(p, ids)) {
- found = true;
+ if (psmouse_check_pnp_id(p, ids))
+ return true;
+
+ p = strchr(p, ' ');
+ if (!p)
break;
- }
}
- kfree(save_ptr);
- return found;
+ return false;
}
/*
@@ -837,14 +834,6 @@ static const struct psmouse_protocol psmouse_protocols[] = {
.detect = touchkit_ps2_detect,
},
#endif
-#ifdef CONFIG_MOUSE_PS2_OLPC
- {
- .type = PSMOUSE_HGPK,
- .name = "OLPC HGPK",
- .alias = "hgpk",
- .detect = hgpk_detect,
- },
-#endif
#ifdef CONFIG_MOUSE_PS2_ELANTECH
{
.type = PSMOUSE_ELANTECH,
@@ -1153,13 +1142,6 @@ static int psmouse_extensions(struct psmouse *psmouse,
return PSMOUSE_ALPS;
}
- /* Try OLPC HGPK touchpad */
- if (max_proto > PSMOUSE_IMEX &&
- psmouse_try_protocol(psmouse, PSMOUSE_HGPK, &max_proto,
- set_properties, true)) {
- return PSMOUSE_HGPK;
- }
-
/* Try Elantech touchpad */
if (max_proto > PSMOUSE_IMEX &&
psmouse_try_protocol(psmouse, PSMOUSE_ELANTECH,
@@ -1331,16 +1313,16 @@ int psmouse_deactivate(struct psmouse *psmouse)
static void psmouse_resync(struct work_struct *work)
{
struct psmouse *parent = NULL, *psmouse =
- container_of(work, struct psmouse, resync_work.work);
+ container_of(work, struct psmouse, resync_work);
struct serio *serio = psmouse->ps2dev.serio;
psmouse_ret_t rc = PSMOUSE_GOOD_DATA;
bool failed = false, enabled = false;
int i;
- mutex_lock(&psmouse_mutex);
+ guard(mutex)(&psmouse_mutex);
if (psmouse->state != PSMOUSE_RESYNCING)
- goto out;
+ return;
if (serio->parent && serio->id.type == SERIO_PS_PSTHRU) {
parent = psmouse_from_serio(serio->parent);
@@ -1418,8 +1400,6 @@ static void psmouse_resync(struct work_struct *work)
if (parent)
psmouse_activate(parent);
- out:
- mutex_unlock(&psmouse_mutex);
}
/*
@@ -1430,7 +1410,7 @@ static void psmouse_cleanup(struct serio *serio)
struct psmouse *psmouse = psmouse_from_serio(serio);
struct psmouse *parent = NULL;
- mutex_lock(&psmouse_mutex);
+ guard(mutex)(&psmouse_mutex);
if (serio->parent && serio->id.type == SERIO_PS_PSTHRU) {
parent = psmouse_from_serio(serio->parent);
@@ -1466,8 +1446,6 @@ static void psmouse_cleanup(struct serio *serio)
psmouse_activate(parent);
}
-
- mutex_unlock(&psmouse_mutex);
}
/*
@@ -1478,20 +1456,20 @@ static void psmouse_disconnect(struct serio *serio)
struct psmouse *psmouse = psmouse_from_serio(serio);
struct psmouse *parent = NULL;
- mutex_lock(&psmouse_mutex);
+ disable_work_sync(&psmouse->resync_work);
- psmouse_set_state(psmouse, PSMOUSE_CMD_MODE);
+ guard(mutex)(&psmouse_mutex);
- /* make sure we don't have a resync in progress */
- mutex_unlock(&psmouse_mutex);
- flush_workqueue(kpsmoused_wq);
- mutex_lock(&psmouse_mutex);
+ psmouse_set_state(psmouse, PSMOUSE_CMD_MODE);
if (serio->parent && serio->id.type == SERIO_PS_PSTHRU) {
parent = psmouse_from_serio(serio->parent);
psmouse_deactivate(parent);
}
+ scoped_guard(serio_pause_rx, serio)
+ psmouse->protocol_handler = NULL;
+
if (psmouse->disconnect)
psmouse->disconnect(psmouse);
@@ -1510,8 +1488,6 @@ static void psmouse_disconnect(struct serio *serio)
if (parent)
psmouse_activate(parent);
-
- mutex_unlock(&psmouse_mutex);
}
static int psmouse_switch_protocol(struct psmouse *psmouse,
@@ -1591,14 +1567,14 @@ static int psmouse_connect(struct serio *serio, struct serio_driver *drv)
psmouse_deactivate(parent);
}
- psmouse = kzalloc(sizeof(*psmouse), GFP_KERNEL);
+ psmouse = kzalloc_obj(*psmouse);
input_dev = input_allocate_device();
if (!psmouse || !input_dev)
goto err_free;
ps2_init(&psmouse->ps2dev, serio,
psmouse_pre_receive_byte, psmouse_receive_byte);
- INIT_DELAYED_WORK(&psmouse->resync_work, psmouse_resync);
+ INIT_WORK(&psmouse->resync_work, psmouse_resync);
psmouse->dev = input_dev;
scnprintf(psmouse->phys, sizeof(psmouse->phys), "%s/input0", serio->phys);
@@ -1680,14 +1656,12 @@ static int __psmouse_reconnect(struct serio *serio, bool fast_reconnect)
enum psmouse_type type;
int rc = -1;
- mutex_lock(&psmouse_mutex);
+ lockdep_assert_held(&psmouse_mutex);
if (fast_reconnect) {
reconnect_handler = psmouse->fast_reconnect;
- if (!reconnect_handler) {
- rc = -ENOENT;
- goto out_unlock;
- }
+ if (!reconnect_handler)
+ return -ENOENT;
} else {
reconnect_handler = psmouse->reconnect;
}
@@ -1739,18 +1713,20 @@ out:
if (parent)
psmouse_activate(parent);
-out_unlock:
- mutex_unlock(&psmouse_mutex);
return rc;
}
static int psmouse_reconnect(struct serio *serio)
{
+ guard(mutex)(&psmouse_mutex);
+
return __psmouse_reconnect(serio, false);
}
static int psmouse_fast_reconnect(struct serio *serio)
{
+ guard(mutex)(&psmouse_mutex);
+
return __psmouse_reconnect(serio, true);
}
@@ -2035,27 +2011,17 @@ static int __init psmouse_init(void)
lifebook_module_init();
synaptics_module_init();
- hgpk_module_init();
err = psmouse_smbus_module_init();
if (err)
return err;
- kpsmoused_wq = alloc_ordered_workqueue("kpsmoused", 0);
- if (!kpsmoused_wq) {
- pr_err("failed to create kpsmoused workqueue\n");
- err = -ENOMEM;
- goto err_smbus_exit;
- }
-
err = serio_register_driver(&psmouse_drv);
if (err)
- goto err_destroy_wq;
+ goto err_smbus_exit;
return 0;
-err_destroy_wq:
- destroy_workqueue(kpsmoused_wq);
err_smbus_exit:
psmouse_smbus_module_exit();
return err;
@@ -2064,7 +2030,6 @@ err_smbus_exit:
static void __exit psmouse_exit(void)
{
serio_unregister_driver(&psmouse_drv);
- destroy_workqueue(kpsmoused_wq);
psmouse_smbus_module_exit();
}