msm: smd: Add SMSM state queue
To reduce the chance of missing SMSM state transitions,
push the SMSM state into a queue in the interrupt handler
and then pull the state for processing the in callback
workqueue.
Change-Id: Ib66bc15f7445369ea7ad2ca271a79ac10b8105a0
CRs-Fixed: 323725
Signed-off-by: Eric Holmberg <eholmber@codeaurora.org>
diff --git a/arch/arm/mach-msm/smd_debug.c b/arch/arm/mach-msm/smd_debug.c
index d7602f2..6171c92 100644
--- a/arch/arm/mach-msm/smd_debug.c
+++ b/arch/arm/mach-msm/smd_debug.c
@@ -1,7 +1,7 @@
/* arch/arm/mach-msm/smd_debug.c
*
* Copyright (C) 2007 Google, Inc.
- * Copyright (c) 2009-2011, Code Aurora Forum. All rights reserved.
+ * Copyright (c) 2009-2012, Code Aurora Forum. All rights reserved.
* Author: Brian Swetland <swetland@google.com>
*
* This software is licensed under the terms of the GNU General Public
@@ -18,6 +18,7 @@
#include <linux/debugfs.h>
#include <linux/list.h>
#include <linux/ctype.h>
+#include <linux/jiffies.h>
#include <mach/msm_iomap.h>
@@ -246,6 +247,7 @@
uint32_t new_state;
};
static struct SMSM_CB_DATA smsm_cb_data;
+static struct completion smsm_cb_completion;
static void smsm_state_cb(void *data, uint32_t old_state, uint32_t new_state)
{
@@ -253,6 +255,7 @@
smsm_cb_data.old_state = old_state;
smsm_cb_data.new_state = new_state;
smsm_cb_data.data = data;
+ complete_all(&smsm_cb_completion);
}
#define UT_EQ_INT(a, b) \
@@ -265,6 +268,16 @@
} \
do {} while (0)
+#define UT_GT_INT(a, b) \
+ if ((a) <= (b)) { \
+ i += scnprintf(buf + i, max - i, \
+ "%s:%d " #a "(%d) > " #b "(%d)\n", \
+ __func__, __LINE__, \
+ a, b); \
+ break; \
+ } \
+ do {} while (0)
+
#define SMSM_CB_TEST_INIT() \
do { \
smsm_cb_data.cb_count = 0; \
@@ -290,16 +303,21 @@
/* de-assert SMSM_SMD_INIT to trigger state update */
UT_EQ_INT(smsm_cb_data.cb_count, 0);
+ INIT_COMPLETION(smsm_cb_completion);
smsm_change_state(SMSM_APPS_STATE, SMSM_SMDINIT, 0x0);
+ UT_GT_INT((int)wait_for_completion_timeout(&smsm_cb_completion,
+ msecs_to_jiffies(20)), 0);
UT_EQ_INT(smsm_cb_data.cb_count, 1);
- UT_EQ_INT(smsm_cb_data.cb_count, 1);
UT_EQ_INT(smsm_cb_data.old_state & SMSM_SMDINIT, SMSM_SMDINIT);
UT_EQ_INT(smsm_cb_data.new_state & SMSM_SMDINIT, 0x0);
UT_EQ_INT((int)smsm_cb_data.data, 0x1234);
/* re-assert SMSM_SMD_INIT to trigger state update */
+ INIT_COMPLETION(smsm_cb_completion);
smsm_change_state(SMSM_APPS_STATE, 0x0, SMSM_SMDINIT);
+ UT_GT_INT((int)wait_for_completion_timeout(&smsm_cb_completion,
+ msecs_to_jiffies(20)), 0);
UT_EQ_INT(smsm_cb_data.cb_count, 2);
UT_EQ_INT(smsm_cb_data.old_state & SMSM_SMDINIT, 0x0);
UT_EQ_INT(smsm_cb_data.new_state & SMSM_SMDINIT, SMSM_SMDINIT);
@@ -310,8 +328,11 @@
UT_EQ_INT(ret, 2);
/* make sure state change doesn't cause any more callbacks */
+ INIT_COMPLETION(smsm_cb_completion);
smsm_change_state(SMSM_APPS_STATE, SMSM_SMDINIT, 0x0);
smsm_change_state(SMSM_APPS_STATE, 0x0, SMSM_SMDINIT);
+ UT_EQ_INT((int)wait_for_completion_timeout(&smsm_cb_completion,
+ msecs_to_jiffies(20)), 0);
UT_EQ_INT(smsm_cb_data.cb_count, 2);
i += scnprintf(buf + i, max - i, "Test %d - PASS\n", test_num);
@@ -329,28 +350,49 @@
UT_EQ_INT(ret, 1);
/* verify both callback bits work */
+ INIT_COMPLETION(smsm_cb_completion);
UT_EQ_INT(smsm_cb_data.cb_count, 0);
smsm_change_state(SMSM_APPS_STATE, SMSM_SMDINIT, 0x0);
+ UT_GT_INT((int)wait_for_completion_timeout(&smsm_cb_completion,
+ msecs_to_jiffies(20)), 0);
UT_EQ_INT(smsm_cb_data.cb_count, 1);
+ INIT_COMPLETION(smsm_cb_completion);
smsm_change_state(SMSM_APPS_STATE, 0x0, SMSM_SMDINIT);
+ UT_GT_INT((int)wait_for_completion_timeout(&smsm_cb_completion,
+ msecs_to_jiffies(20)), 0);
UT_EQ_INT(smsm_cb_data.cb_count, 2);
+ INIT_COMPLETION(smsm_cb_completion);
smsm_change_state(SMSM_APPS_STATE, SMSM_INIT, 0x0);
+ UT_GT_INT((int)wait_for_completion_timeout(&smsm_cb_completion,
+ msecs_to_jiffies(20)), 0);
UT_EQ_INT(smsm_cb_data.cb_count, 3);
+ INIT_COMPLETION(smsm_cb_completion);
smsm_change_state(SMSM_APPS_STATE, 0x0, SMSM_INIT);
+ UT_GT_INT((int)wait_for_completion_timeout(&smsm_cb_completion,
+ msecs_to_jiffies(20)), 0);
UT_EQ_INT(smsm_cb_data.cb_count, 4);
/* deregister 1st callback */
ret = smsm_state_cb_deregister(SMSM_APPS_STATE, SMSM_SMDINIT,
smsm_state_cb, (void *)0x1234);
UT_EQ_INT(ret, 1);
+ INIT_COMPLETION(smsm_cb_completion);
smsm_change_state(SMSM_APPS_STATE, SMSM_SMDINIT, 0x0);
smsm_change_state(SMSM_APPS_STATE, 0x0, SMSM_SMDINIT);
+ UT_EQ_INT((int)wait_for_completion_timeout(&smsm_cb_completion,
+ msecs_to_jiffies(20)), 0);
UT_EQ_INT(smsm_cb_data.cb_count, 4);
+ INIT_COMPLETION(smsm_cb_completion);
smsm_change_state(SMSM_APPS_STATE, SMSM_INIT, 0x0);
+ UT_GT_INT((int)wait_for_completion_timeout(&smsm_cb_completion,
+ msecs_to_jiffies(20)), 0);
UT_EQ_INT(smsm_cb_data.cb_count, 5);
+ INIT_COMPLETION(smsm_cb_completion);
smsm_change_state(SMSM_APPS_STATE, 0x0, SMSM_INIT);
+ UT_GT_INT((int)wait_for_completion_timeout(&smsm_cb_completion,
+ msecs_to_jiffies(20)), 0);
UT_EQ_INT(smsm_cb_data.cb_count, 6);
/* deregister 2nd callback */
@@ -359,8 +401,11 @@
UT_EQ_INT(ret, 2);
/* make sure state change doesn't cause any more callbacks */
+ INIT_COMPLETION(smsm_cb_completion);
smsm_change_state(SMSM_APPS_STATE, SMSM_INIT, 0x0);
smsm_change_state(SMSM_APPS_STATE, 0x0, SMSM_INIT);
+ UT_EQ_INT((int)wait_for_completion_timeout(&smsm_cb_completion,
+ msecs_to_jiffies(20)), 0);
UT_EQ_INT(smsm_cb_data.cb_count, 6);
i += scnprintf(buf + i, max - i, "Test %d - PASS\n", test_num);
@@ -378,12 +423,18 @@
UT_EQ_INT(ret, 0);
/* verify both callbacks work */
+ INIT_COMPLETION(smsm_cb_completion);
UT_EQ_INT(smsm_cb_data.cb_count, 0);
smsm_change_state(SMSM_APPS_STATE, SMSM_SMDINIT, 0x0);
+ UT_GT_INT((int)wait_for_completion_timeout(&smsm_cb_completion,
+ msecs_to_jiffies(20)), 0);
UT_EQ_INT(smsm_cb_data.cb_count, 1);
UT_EQ_INT((int)smsm_cb_data.data, 0x1234);
+ INIT_COMPLETION(smsm_cb_completion);
smsm_change_state(SMSM_APPS_STATE, SMSM_INIT, 0x0);
+ UT_GT_INT((int)wait_for_completion_timeout(&smsm_cb_completion,
+ msecs_to_jiffies(20)), 0);
UT_EQ_INT(smsm_cb_data.cb_count, 2);
UT_EQ_INT((int)smsm_cb_data.data, 0x3456);
@@ -659,6 +710,8 @@
debug_create("version", 0444, dent, debug_read_smem_version);
debug_create("smsm_test", 0444, dent, debug_test_smsm);
+ init_completion(&smsm_cb_completion);
+
return 0;
}