Re: Resume from swsusp stopped working with 2.6.14 and 2.6.15-rc1

Dmitry Torokhov
2005-11-18T23:32:22Z

[-- Attachment #1: Type: text/plain, Size: 1032 bytes --]

On 11/18/05, Pavel Machek <pavel@ucw.cz> wrote:
> Hi!
>
> > >> Bjorn, does it help if you change TIMEOUT in kernel/power/process.c to 30 * HZ?
> > >
> > > Funny, I thought that 6 seconds is way too much. Bjorn, please let us
> > > know if 30 seconds timeout helps.
> >
> > It does.
>
> Ouch, yes, that's clear. It is stopping tasks during *resume*... So I
> guess it gets wrong timing by design. Question is what to do with
> that. Could we make keyboard driver pause the boot until it is done
> resetting hardware? Or we can increase the timeout... would 10 seconds
> be enough?

Well, I think 10 seconds when suspending is a nice and resonable
number. For resume though I think we should wait much longer, maybe
even indefinitely - the only thing that timeout achieves is makes
people fsck because the system can't recover from that state.

In any case the attached should make input more swsusp friendly by
checking freeze condition after processing one event instead of all
pending events.

--
Dmitry

[-- Attachment #2: input-help-swsusp.patch --]
[-- Type: application/octet-stream, Size: 2682 bytes --]

Input: make serio and gameport more swsusp friendly

kseriod and kgameportd used to process all pending events before
checking for freeze condition. This may cause swsusp to time out
while stopping tasks when resuming. Switch to process events one
by one to check freeze status more often.

Signed-off-by: Dmitry Torokhov <dtor@mail.ru>
---

gameport/gameport.c | 12 +++++++++---
serio/serio.c | 12 +++++++++---
2 files changed, 18 insertions(+), 6 deletions(-)

Index: linux/drivers/input/serio/serio.c
===================================================================
--- linux.orig/drivers/input/serio/serio.c
+++ linux/drivers/input/serio/serio.c
@@ -269,14 +269,20 @@ static struct serio_event *serio_get_eve
return event;
}

-static void serio_handle_events(void)
+static void serio_handle_event(void)
{
struct serio_event *event;
struct serio_driver *serio_drv;

down(&serio_sem);

- while ((event = serio_get_event())) {
+ /*
+ * Note that we handle only one event here to give swsusp
+ * a chance to freeze kseriod thread. Serio events should
+ * be pretty rare so we are not concerned about taking
+ * performance hit.
+ */
+ if ((event = serio_get_event())) {

switch (event->type) {
case SERIO_REGISTER_PORT:
@@ -368,7 +374,7 @@ static struct serio *serio_get_pending_c
static int serio_thread(void *nothing)
{
do {
- serio_handle_events();
+ serio_handle_event();
wait_event_interruptible(serio_wait,
kthread_should_stop() || !list_empty(&serio_event_list));
try_to_freeze();
Index: linux/drivers/input/gameport/gameport.c
===================================================================
--- linux.orig/drivers/input/gameport/gameport.c
+++ linux/drivers/input/gameport/gameport.c
@@ -339,14 +339,20 @@ static struct gameport_event *gameport_g
return event;
}

-static void gameport_handle_events(void)
+static void gameport_handle_event(void)
{
struct gameport_event *event;
struct gameport_driver *gameport_drv;

down(&gameport_sem);

- while ((event = gameport_get_event())) {
+ /*
+ * Note that we handle only one event here to give swsusp
+ * a chance to freeze kgameportd thread. Gameport events
+ * should be pretty rare so we are not concerned about
+ * taking performance hit.
+ */
+ if ((event = gameport_get_event())) {

switch (event->type) {
case GAMEPORT_REGISTER_PORT:
@@ -433,7 +439,7 @@ static struct gameport *gameport_get_pen
static int gameport_thread(void *nothing)
{
do {
- gameport_handle_events();
+ gameport_handle_event();
wait_event_interruptible(gameport_wait,
kthread_should_stop() || !list_empty(&gameport_event_list));
try_to_freeze();