msm: smd: Do not use wakelock for local DEM notifications
Notify local SMSM callback clients without using a wakelock since SMSM
signaling is used by power management during power-down/-up sequencing
on DEM-based targets. Grabbing a wakelock in this case will abort
power-down sequencing.
Change-Id: I08de41480a9713f8ac52b563c7df8213d465466d
Signed-off-by: Eric Holmberg <eholmber@codeaurora.org>
diff --git a/arch/arm/mach-msm/smd.c b/arch/arm/mach-msm/smd.c
index c502bce..bbfe702 100644
--- a/arch/arm/mach-msm/smd.c
+++ b/arch/arm/mach-msm/smd.c
@@ -65,6 +65,7 @@
#define SMEM_VERSION 0x000B
#define SMD_VERSION 0x00020000
#define SMSM_SNAPSHOT_CNT 64
+#define SMSM_SNAPSHOT_SIZE ((SMSM_NUM_ENTRIES + 1) * 4)
uint32_t SMSM_NUM_ENTRIES = 8;
uint32_t SMSM_NUM_HOSTS = 3;
@@ -328,7 +329,7 @@
static LIST_HEAD(smd_ch_list_loopback);
static void smd_fake_irq_handler(unsigned long arg);
-static void smsm_cb_snapshot(void);
+static void smsm_cb_snapshot(uint32_t use_wakelock);
static void notify_smsm_cb_clients_worker(struct work_struct *work);
static DECLARE_WORK(smsm_cb_work, notify_smsm_cb_clients_worker);
@@ -516,7 +517,13 @@
notify_dsps_smsm();
}
- smsm_cb_snapshot();
+ /*
+ * Notify local SMSM callback clients without wakelock since this
+ * code is used by power management during power-down/-up sequencing
+ * on DEM-based targets. Grabbing a wakelock in this case will
+ * abort the power-down sequencing.
+ */
+ smsm_cb_snapshot(0);
}
void smd_diag(void)
@@ -2345,7 +2352,7 @@
}
EXPORT_SYMBOL(smsm_reset_modem_cont);
-static void smsm_cb_snapshot(void)
+static void smsm_cb_snapshot(uint32_t use_wakelock)
{
int n;
uint32_t new_state;
@@ -2353,11 +2360,12 @@
int ret;
ret = kfifo_avail(&smsm_snapshot_fifo);
- if (ret < (SMSM_NUM_ENTRIES * 4)) {
+ if (ret < SMSM_SNAPSHOT_SIZE) {
pr_err("%s: SMSM snapshot full %d\n", __func__, ret);
return;
}
+ /* queue state entries */
for (n = 0; n < SMSM_NUM_ENTRIES; n++) {
new_state = __raw_readl(SMSM_STATE_ADDR(n));
@@ -2369,13 +2377,23 @@
}
}
- spin_lock_irqsave(&smsm_snapshot_count_lock, flags);
- if (smsm_snapshot_count == 0) {
- SMx_POWER_INFO("SMSM snapshot wake lock\n");
- wake_lock(&smsm_snapshot_wakelock);
+ /* queue wakelock usage flag */
+ ret = kfifo_in(&smsm_snapshot_fifo,
+ &use_wakelock, sizeof(use_wakelock));
+ if (ret != sizeof(use_wakelock)) {
+ pr_err("%s: SMSM snapshot failure %d\n", __func__, ret);
+ return;
}
- ++smsm_snapshot_count;
- spin_unlock_irqrestore(&smsm_snapshot_count_lock, flags);
+
+ if (use_wakelock) {
+ spin_lock_irqsave(&smsm_snapshot_count_lock, flags);
+ if (smsm_snapshot_count == 0) {
+ SMx_POWER_INFO("SMSM snapshot wake lock\n");
+ wake_lock(&smsm_snapshot_wakelock);
+ }
+ ++smsm_snapshot_count;
+ spin_unlock_irqrestore(&smsm_snapshot_count_lock, flags);
+ }
schedule_work(&smsm_cb_work);
}
@@ -2395,7 +2413,7 @@
}
spin_lock_irqsave(&smem_lock, flags);
- smsm_cb_snapshot();
+ smsm_cb_snapshot(1);
spin_unlock_irqrestore(&smem_lock, flags);
return IRQ_HANDLED;
}
@@ -2454,7 +2472,7 @@
notify_other_smsm(SMSM_APPS_STATE, (old_apps ^ apps));
}
- smsm_cb_snapshot();
+ smsm_cb_snapshot(1);
}
spin_unlock_irqrestore(&smem_lock, flags);
return IRQ_HANDLED;
@@ -2597,14 +2615,14 @@
int n;
uint32_t new_state;
uint32_t state_changes;
+ uint32_t use_wakelock;
int ret;
unsigned long flags;
- int snapshot_size = SMSM_NUM_ENTRIES * sizeof(uint32_t);
if (!smd_initialized)
return;
- while (kfifo_len(&smsm_snapshot_fifo) >= snapshot_size) {
+ while (kfifo_len(&smsm_snapshot_fifo) >= SMSM_SNAPSHOT_SIZE) {
mutex_lock(&smsm_lock);
for (n = 0; n < SMSM_NUM_ENTRIES; n++) {
state_info = &smsm_states[n];
@@ -2636,17 +2654,31 @@
}
mutex_unlock(&smsm_lock);
- spin_lock_irqsave(&smsm_snapshot_count_lock, flags);
- if (smsm_snapshot_count) {
- --smsm_snapshot_count;
- if (smsm_snapshot_count == 0) {
- SMx_POWER_INFO("SMSM snapshot wake unlock\n");
- wake_unlock(&smsm_snapshot_wakelock);
- }
- } else {
- pr_err("%s: invalid snapshot count\n", __func__);
+ /* read wakelock flag */
+ ret = kfifo_out(&smsm_snapshot_fifo, &use_wakelock,
+ sizeof(use_wakelock));
+ if (ret != sizeof(use_wakelock)) {
+ pr_err("%s: snapshot underflow %d\n",
+ __func__, ret);
+ return;
}
- spin_unlock_irqrestore(&smsm_snapshot_count_lock, flags);
+
+ if (use_wakelock) {
+ spin_lock_irqsave(&smsm_snapshot_count_lock, flags);
+ if (smsm_snapshot_count) {
+ --smsm_snapshot_count;
+ if (smsm_snapshot_count == 0) {
+ SMx_POWER_INFO("SMSM snapshot"
+ " wake unlock\n");
+ wake_unlock(&smsm_snapshot_wakelock);
+ }
+ } else {
+ pr_err("%s: invalid snapshot count\n",
+ __func__);
+ }
+ spin_unlock_irqrestore(&smsm_snapshot_count_lock,
+ flags);
+ }
}
}