Commit 82dd9eff authored by Dmitry Torokhov's avatar Dmitry Torokhov

Input: i8042 - let serio bus suspend ports

Let serio subsystem take care of suspending the ports; concentrate
on suspending/resuming the controller itself.
Signed-off-by: default avatarDmitry Torokhov <dtor@mail.ru>
parent a1cec061
...@@ -790,27 +790,6 @@ static void i8042_controller_reset(void) ...@@ -790,27 +790,6 @@ static void i8042_controller_reset(void)
} }
/*
* Here we try to reset everything back to a state in which the BIOS will be
* able to talk to the hardware when rebooting.
*/
static void i8042_controller_cleanup(void)
{
int i;
/*
* Reset anything that is connected to the ports.
*/
for (i = 0; i < I8042_NUM_PORTS; i++)
if (i8042_ports[i].serio)
serio_cleanup(i8042_ports[i].serio);
i8042_controller_reset();
}
/* /*
* i8042_panic_blink() will flash the keyboard LEDs and is called when * i8042_panic_blink() will flash the keyboard LEDs and is called when
* kernel panics. Flashing LEDs is useful for users running X who may * kernel panics. Flashing LEDs is useful for users running X who may
...@@ -857,13 +836,22 @@ static long i8042_panic_blink(long count) ...@@ -857,13 +836,22 @@ static long i8042_panic_blink(long count)
#undef DELAY #undef DELAY
#ifdef CONFIG_PM
/* /*
* Here we try to restore the original BIOS settings * Here we try to restore the original BIOS settings. We only want to
* do that once, when we really suspend, not when we taking memory
* snapshot for swsusp (in this case we'll perform required cleanup
* as part of shutdown process).
*/ */
static int i8042_suspend(struct platform_device *dev, pm_message_t state) static int i8042_suspend(struct platform_device *dev, pm_message_t state)
{ {
i8042_controller_cleanup(); if (dev->dev.power.power_state.event != state.event) {
if (state.event == PM_EVENT_SUSPEND)
i8042_controller_reset();
dev->dev.power.power_state = state;
}
return 0; return 0;
} }
...@@ -877,6 +865,12 @@ static int i8042_resume(struct platform_device *dev) ...@@ -877,6 +865,12 @@ static int i8042_resume(struct platform_device *dev)
{ {
int error; int error;
/*
* Do not bother with restoring state if we haven't suspened yet
*/
if (dev->dev.power.power_state.event == PM_EVENT_ON)
return 0;
error = i8042_controller_check(); error = i8042_controller_check();
if (error) if (error)
return error; return error;
...@@ -886,9 +880,12 @@ static int i8042_resume(struct platform_device *dev) ...@@ -886,9 +880,12 @@ static int i8042_resume(struct platform_device *dev)
return error; return error;
/* /*
* Restore pre-resume CTR value and disable all ports * Restore original CTR value and disable all ports
*/ */
i8042_ctr = i8042_initial_ctr;
if (i8042_direct)
i8042_ctr &= ~I8042_CTR_XLATE;
i8042_ctr |= I8042_CTR_AUXDIS | I8042_CTR_KBDDIS; i8042_ctr |= I8042_CTR_AUXDIS | I8042_CTR_KBDDIS;
i8042_ctr &= ~(I8042_CTR_AUXINT | I8042_CTR_KBDINT); i8042_ctr &= ~(I8042_CTR_AUXINT | I8042_CTR_KBDINT);
if (i8042_command(&i8042_ctr, I8042_CMD_CTL_WCTR)) { if (i8042_command(&i8042_ctr, I8042_CMD_CTL_WCTR)) {
...@@ -909,8 +906,11 @@ static int i8042_resume(struct platform_device *dev) ...@@ -909,8 +906,11 @@ static int i8042_resume(struct platform_device *dev)
i8042_interrupt(0, NULL); i8042_interrupt(0, NULL);
dev->dev.power.power_state = PMSG_ON;
return 0; return 0;
} }
#endif /* CONFIG_PM */
/* /*
* We need to reset the 8042 back to original mode on system shutdown, * We need to reset the 8042 back to original mode on system shutdown,
...@@ -919,7 +919,7 @@ static int i8042_resume(struct platform_device *dev) ...@@ -919,7 +919,7 @@ static int i8042_resume(struct platform_device *dev)
static void i8042_shutdown(struct platform_device *dev) static void i8042_shutdown(struct platform_device *dev)
{ {
i8042_controller_cleanup(); i8042_controller_reset();
} }
static int __devinit i8042_create_kbd_port(void) static int __devinit i8042_create_kbd_port(void)
...@@ -1154,9 +1154,11 @@ static struct platform_driver i8042_driver = { ...@@ -1154,9 +1154,11 @@ static struct platform_driver i8042_driver = {
}, },
.probe = i8042_probe, .probe = i8042_probe,
.remove = __devexit_p(i8042_remove), .remove = __devexit_p(i8042_remove),
.shutdown = i8042_shutdown,
#ifdef CONFIG_PM
.suspend = i8042_suspend, .suspend = i8042_suspend,
.resume = i8042_resume, .resume = i8042_resume,
.shutdown = i8042_shutdown, #endif
}; };
static int __init i8042_init(void) static int __init i8042_init(void)
......
...@@ -778,6 +778,19 @@ static int serio_driver_remove(struct device *dev) ...@@ -778,6 +778,19 @@ static int serio_driver_remove(struct device *dev)
return 0; return 0;
} }
static void serio_cleanup(struct serio *serio)
{
if (serio->drv && serio->drv->cleanup)
serio->drv->cleanup(serio);
}
static void serio_shutdown(struct device *dev)
{
struct serio *serio = to_serio_port(dev);
serio_cleanup(serio);
}
static void serio_attach_driver(struct serio_driver *drv) static void serio_attach_driver(struct serio_driver *drv)
{ {
int error; int error;
...@@ -910,11 +923,25 @@ static int serio_uevent(struct device *dev, char **envp, int num_envp, char *buf ...@@ -910,11 +923,25 @@ static int serio_uevent(struct device *dev, char **envp, int num_envp, char *buf
#endif /* CONFIG_HOTPLUG */ #endif /* CONFIG_HOTPLUG */
#ifdef CONFIG_PM
static int serio_suspend(struct device *dev, pm_message_t state)
{
if (dev->power.power_state.event != state.event) {
if (state.event == PM_EVENT_SUSPEND)
serio_cleanup(to_serio_port(dev));
dev->power.power_state = state;
}
return 0;
}
static int serio_resume(struct device *dev) static int serio_resume(struct device *dev)
{ {
struct serio *serio = to_serio_port(dev); struct serio *serio = to_serio_port(dev);
if (serio_reconnect_driver(serio)) { if (dev->power.power_state.event != PM_EVENT_ON &&
serio_reconnect_driver(serio)) {
/* /*
* Driver re-probing can take a while, so better let kseriod * Driver re-probing can take a while, so better let kseriod
* deal with it. * deal with it.
...@@ -922,8 +949,11 @@ static int serio_resume(struct device *dev) ...@@ -922,8 +949,11 @@ static int serio_resume(struct device *dev)
serio_rescan(serio); serio_rescan(serio);
} }
dev->power.power_state = PMSG_ON;
return 0; return 0;
} }
#endif /* CONFIG_PM */
/* called from serio_driver->connect/disconnect methods under serio_mutex */ /* called from serio_driver->connect/disconnect methods under serio_mutex */
int serio_open(struct serio *serio, struct serio_driver *drv) int serio_open(struct serio *serio, struct serio_driver *drv)
...@@ -974,7 +1004,11 @@ static struct bus_type serio_bus = { ...@@ -974,7 +1004,11 @@ static struct bus_type serio_bus = {
.uevent = serio_uevent, .uevent = serio_uevent,
.probe = serio_driver_probe, .probe = serio_driver_probe,
.remove = serio_driver_remove, .remove = serio_driver_remove,
.shutdown = serio_shutdown,
#ifdef CONFIG_PM
.suspend = serio_suspend,
.resume = serio_resume, .resume = serio_resume,
#endif
}; };
static int __init serio_init(void) static int __init serio_init(void)
......
...@@ -108,12 +108,6 @@ static inline void serio_drv_write_wakeup(struct serio *serio) ...@@ -108,12 +108,6 @@ static inline void serio_drv_write_wakeup(struct serio *serio)
serio->drv->write_wakeup(serio); serio->drv->write_wakeup(serio);
} }
static inline void serio_cleanup(struct serio *serio)
{
if (serio->drv && serio->drv->cleanup)
serio->drv->cleanup(serio);
}
/* /*
* Use the following functions to manipulate serio's per-port * Use the following functions to manipulate serio's per-port
* driver-specific data. * driver-specific data.
......
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