msm: bam_dmux: delay shutdown until DL polling is complete
Bam_dmux assumes that a shutdown event will not occur while downlink (DL)
polling is active. If this assumption does not hold, bam_dmux stops
polling, but does not cleanly switch back to interrupt mode until the next
power-on event. This is a problem because the next power-on event could
occur in the distant future and until that time some resources may be
incorrectly accessed or not released. Instead, if a shutdown event occurs
while DL polling is active, delay processing of that event until polling
completes.
CRs-Fixed: 503046
Change-Id: I67e4216b4820942e6070944557cd13f59600a2aa
Signed-off-by: Brent Hronik <bhronik@codeaurora.org>
diff --git a/arch/arm/mach-msm/bam_dmux.c b/arch/arm/mach-msm/bam_dmux.c
index 26282f7..986357e 100644
--- a/arch/arm/mach-msm/bam_dmux.c
+++ b/arch/arm/mach-msm/bam_dmux.c
@@ -231,6 +231,7 @@
/* A2 power collaspe */
#define UL_TIMEOUT_DELAY 1000 /* in ms */
#define ENABLE_DISCONNECT_ACK 0x1
+#define SHUTDOWN_TIMEOUT_MS 500
static void toggle_apps_ack(void);
static void reconnect_to_bam(void);
static void disconnect_to_bam(void);
@@ -271,6 +272,7 @@
static int power_management_only_mode;
static int in_ssr;
static int ssr_skipped_disconnect;
+static struct completion shutdown_completion;
struct outside_notify_func {
void (*notify)(void *, int, unsigned long);
@@ -1065,6 +1067,7 @@
goto fail;
}
polling_mode = 0;
+ complete_all(&shutdown_completion);
release_wakelock();
/* handle any rx packets before interrupt was enabled */
@@ -1265,6 +1268,7 @@
" not disabled\n", __func__, ret);
break;
}
+ INIT_COMPLETION(shutdown_completion);
grab_wakelock();
polling_mode = 1;
/*
@@ -1744,6 +1748,14 @@
struct list_head *node;
struct rx_pkt_info *info;
unsigned long flags;
+ unsigned long time_remaining;
+
+ time_remaining = wait_for_completion_timeout(&shutdown_completion,
+ msecs_to_jiffies(SHUTDOWN_TIMEOUT_MS));
+ if (time_remaining == 0) {
+ pr_err("%s: shutdown completion timed out\n", __func__);
+ ssrestart_check();
+ }
bam_connection_is_active = 0;
@@ -2346,6 +2358,8 @@
init_completion(&ul_wakeup_ack_completion);
init_completion(&bam_connection_completion);
init_completion(&dfab_unvote_completion);
+ init_completion(&shutdown_completion);
+ complete_all(&shutdown_completion);
INIT_DELAYED_WORK(&ul_timeout_work, ul_timeout);
INIT_DELAYED_WORK(&queue_rx_work, queue_rx_work_func);
wake_lock_init(&bam_wakelock, WAKE_LOCK_SUSPEND, "bam_dmux_wakelock");