Commit 6aabcdff authored by Shaohua Li's avatar Shaohua Li Committed by Dmitry Torokhov

Input: serio - offload resume to kseriod

When resuming AUX ports psmouse driver calls psmouse_extensions()
to determine if the attached mouse is still the same, which may take
a while to complete for generic mice. Offload the resume process to
kseriod so the rest of the system may continue resuming without
waiting for the mouse.
Signed-off-by: default avatarShaohua Li <shaohua.li@intel.com>
Signed-off-by: default avatarDmitry Torokhov <dtor@mail.ru>
parent a822bea7
...@@ -63,8 +63,9 @@ static LIST_HEAD(serio_list); ...@@ -63,8 +63,9 @@ static LIST_HEAD(serio_list);
static struct bus_type serio_bus; static struct bus_type serio_bus;
static void serio_add_port(struct serio *serio); static void serio_add_port(struct serio *serio);
static void serio_reconnect_port(struct serio *serio); static int serio_reconnect_port(struct serio *serio);
static void serio_disconnect_port(struct serio *serio); static void serio_disconnect_port(struct serio *serio);
static void serio_reconnect_chain(struct serio *serio);
static void serio_attach_driver(struct serio_driver *drv); static void serio_attach_driver(struct serio_driver *drv);
static int serio_connect_driver(struct serio *serio, struct serio_driver *drv) static int serio_connect_driver(struct serio *serio, struct serio_driver *drv)
...@@ -161,6 +162,7 @@ static void serio_find_driver(struct serio *serio) ...@@ -161,6 +162,7 @@ static void serio_find_driver(struct serio *serio)
enum serio_event_type { enum serio_event_type {
SERIO_RESCAN_PORT, SERIO_RESCAN_PORT,
SERIO_RECONNECT_PORT, SERIO_RECONNECT_PORT,
SERIO_RECONNECT_CHAIN,
SERIO_REGISTER_PORT, SERIO_REGISTER_PORT,
SERIO_ATTACH_DRIVER, SERIO_ATTACH_DRIVER,
}; };
...@@ -315,6 +317,10 @@ static void serio_handle_event(void) ...@@ -315,6 +317,10 @@ static void serio_handle_event(void)
serio_find_driver(event->object); serio_find_driver(event->object);
break; break;
case SERIO_RECONNECT_CHAIN:
serio_reconnect_chain(event->object);
break;
case SERIO_ATTACH_DRIVER: case SERIO_ATTACH_DRIVER:
serio_attach_driver(event->object); serio_attach_driver(event->object);
break; break;
...@@ -470,7 +476,7 @@ static ssize_t serio_rebind_driver(struct device *dev, struct device_attribute * ...@@ -470,7 +476,7 @@ static ssize_t serio_rebind_driver(struct device *dev, struct device_attribute *
if (!strncmp(buf, "none", count)) { if (!strncmp(buf, "none", count)) {
serio_disconnect_port(serio); serio_disconnect_port(serio);
} else if (!strncmp(buf, "reconnect", count)) { } else if (!strncmp(buf, "reconnect", count)) {
serio_reconnect_port(serio); serio_reconnect_chain(serio);
} else if (!strncmp(buf, "rescan", count)) { } else if (!strncmp(buf, "rescan", count)) {
serio_disconnect_port(serio); serio_disconnect_port(serio);
serio_find_driver(serio); serio_find_driver(serio);
...@@ -619,15 +625,31 @@ static void serio_destroy_port(struct serio *serio) ...@@ -619,15 +625,31 @@ static void serio_destroy_port(struct serio *serio)
put_device(&serio->dev); put_device(&serio->dev);
} }
/*
* Reconnect serio port (re-initialize attached device).
* If reconnect fails (old device is no longer attached or
* there was no device to begin with) we do full rescan in
* hope of finding a driver for the port.
*/
static int serio_reconnect_port(struct serio *serio)
{
int error = serio_reconnect_driver(serio);
if (error) {
serio_disconnect_port(serio);
serio_find_driver(serio);
}
return error;
}
/* /*
* Reconnect serio port and all its children (re-initialize attached devices) * Reconnect serio port and all its children (re-initialize attached devices)
*/ */
static void serio_reconnect_port(struct serio *serio) static void serio_reconnect_chain(struct serio *serio)
{ {
do { do {
if (serio_reconnect_driver(serio)) { if (serio_reconnect_port(serio)) {
serio_disconnect_port(serio);
serio_find_driver(serio);
/* Ok, old children are now gone, we are done */ /* Ok, old children are now gone, we are done */
break; break;
} }
...@@ -673,7 +695,7 @@ void serio_rescan(struct serio *serio) ...@@ -673,7 +695,7 @@ void serio_rescan(struct serio *serio)
void serio_reconnect(struct serio *serio) void serio_reconnect(struct serio *serio)
{ {
serio_queue_event(serio, NULL, SERIO_RECONNECT_PORT); serio_queue_event(serio, NULL, SERIO_RECONNECT_CHAIN);
} }
/* /*
...@@ -927,19 +949,16 @@ static int serio_suspend(struct device *dev, pm_message_t state) ...@@ -927,19 +949,16 @@ static int serio_suspend(struct device *dev, pm_message_t state)
static int serio_resume(struct device *dev) static int serio_resume(struct device *dev)
{ {
struct serio *serio = to_serio_port(dev); /*
* Driver reconnect can take a while, so better let kseriod
if (dev->power.power_state.event != PM_EVENT_ON && * deal with it.
serio_reconnect_driver(serio)) { */
/* if (dev->power.power_state.event != PM_EVENT_ON) {
* Driver re-probing can take a while, so better let kseriod dev->power.power_state = PMSG_ON;
* deal with it. serio_queue_event(to_serio_port(dev), NULL,
*/ SERIO_RECONNECT_PORT);
serio_rescan(serio);
} }
dev->power.power_state = PMSG_ON;
return 0; return 0;
} }
#endif /* CONFIG_PM */ #endif /* CONFIG_PM */
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment