From 3dfe8aaaeede22b0601c95cf1a4c2eadcb3851ba Mon Sep 17 00:00:00 2001 From: Bryan O'Donoghue Date: Fri, 24 Jul 2015 10:02:56 +0100 Subject: [PATCH] greybus: loopback: convert loopback wake/sleep to a waitqueue Current code will incrementally poll for gb->type == 0 and sleep. This type of polling strategy wastes cycles. This patch changes the sleep strategy by introducing a wait-queue which waits for gb->type != 0 or kthread_should_stop() to wake-up and work or to wake-up and terminate. Signed-off-by: Bryan O'Donoghue Signed-off-by: Greg Kroah-Hartman --- drivers/staging/greybus/loopback.c | 34 +++++++++++++++++------------- 1 file changed, 19 insertions(+), 15 deletions(-) diff --git a/drivers/staging/greybus/loopback.c b/drivers/staging/greybus/loopback.c index 08f0bee198c2..229494833a16 100644 --- a/drivers/staging/greybus/loopback.c +++ b/drivers/staging/greybus/loopback.c @@ -31,6 +31,7 @@ struct gb_loopback { u8 version_minor; struct task_struct *task; + wait_queue_head_t wq; int type; u32 size; @@ -113,15 +114,6 @@ static DEVICE_ATTR_RW(field) static void gb_loopback_reset_stats(struct gb_loopback *gb); static void gb_loopback_check_attr(struct gb_loopback *gb) { - switch (gb->type) { - case GB_LOOPBACK_TYPE_PING: - case GB_LOOPBACK_TYPE_TRANSFER: - case GB_LOOPBACK_TYPE_SINK: - break; - default: - gb->type = 0; - break; - } if (gb->ms_wait > GB_LOOPBACK_MS_WAIT_MAX) gb->ms_wait = GB_LOOPBACK_MS_WAIT_MAX; if (gb->size > gb->size_max) @@ -129,6 +121,17 @@ static void gb_loopback_check_attr(struct gb_loopback *gb) gb->error = 0; gb->iteration_count = 0; gb_loopback_reset_stats(gb); + + switch (gb->type) { + case GB_LOOPBACK_TYPE_PING: + case GB_LOOPBACK_TYPE_TRANSFER: + case GB_LOOPBACK_TYPE_SINK: + wake_up(&gb->wq); + break; + default: + gb->type = 0; + break; + } } /* Time to send and receive one message */ @@ -397,11 +400,12 @@ static int gb_loopback_fn(void *data) struct timeval tlat = {0, 0}; struct gb_loopback *gb = (struct gb_loopback *)data; - while (!kthread_should_stop()) { - if (!gb->type) { - msleep(1000); - continue; - } + while (1) { + if (!gb->type) + wait_event_interruptible(gb->wq, gb->type || + kthread_should_stop()); + if (kthread_should_stop()) + break; if (gb->iteration_max) { if (gb->iteration_count < gb->iteration_max) { gb->iteration_count++; @@ -429,7 +433,6 @@ static int gb_loopback_fn(void *data) gb->ts = gb->te; if (gb->ms_wait) msleep(gb->ms_wait); - } return 0; } @@ -463,6 +466,7 @@ static int gb_loopback_connection_init(struct gb_connection *connection) gb->size_max -= sizeof(struct gb_loopback_transfer_request); gb_loopback_reset_stats(gb); + init_waitqueue_head(&gb->wq); gb->task = kthread_run(gb_loopback_fn, gb, "gb_loopback"); if (IS_ERR(gb->task)) { retval = PTR_ERR(gb->task);