summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorArun Murthy <arun.murthy@stericsson.com>2012-01-24 16:29:56 +0530
committerPhilippe Langlais <philippe.langlais@stericsson.com>2012-06-05 10:40:26 +0200
commit9b0f381cd6325b90595f9d466ebe671e06e2ceb6 (patch)
tree434b9bf6c6f397e67eb53118fcb9945a5a7e4080
parentc8a9c6d42e88f81512515075186659c9a420b440 (diff)
u8500-shrm: initiate MSR after fifo full
On APE side after FIFO fill, shrm driver stops further receiving messages from the user space and keeps waiting indefinetly for the modem to read and empty the fifo. If modem is not responsive then it ends up in an indefinite loop. Hence after arriving at fifo full wait for some time say 1sec and then issue a modem reset which will turn out in a MSR. ST-Ericsson Linux next: NA ST-Ericsson ID: 407459 ST-Ericsson FOSS-OUT ID: Trivial Change-Id: I9ac5cc4029f6b092809297513810798805485b60 Signed-off-by: Arun Murthy <arun.murthy@stericsson.com> Reviewed-on: http://gerrit.lud.stericsson.com/gerrit/46338 Reviewed-by: Ashok G X <ashok.g@stericsson.com> Tested-by: Ashok G X <ashok.g@stericsson.com> Reviewed-by: Srinidhi KASAGAR <srinidhi.kasagar@stericsson.com>
-rw-r--r--drivers/modem/shrm/shrm_protocol.c29
1 files changed, 28 insertions, 1 deletions
diff --git a/drivers/modem/shrm/shrm_protocol.c b/drivers/modem/shrm/shrm_protocol.c
index 5997c35297b..b9613f544e5 100644
--- a/drivers/modem/shrm/shrm_protocol.c
+++ b/drivers/modem/shrm/shrm_protocol.c
@@ -32,6 +32,7 @@
#define L2_HEADER_RTC_CALIBRATION 0xC8
#define MAX_PAYLOAD 1024
#define MOD_STUCK_TIMEOUT 6
+#define FIFO_FULL_TIMEOUT 1
#define PRCM_HOSTACCESS_REQ 0x334
@@ -43,6 +44,7 @@ static received_msg_handler rx_audio_handler;
static struct hrtimer timer;
static struct hrtimer mod_stuck_timer_0;
static struct hrtimer mod_stuck_timer_1;
+static struct hrtimer fifo_full_timer;
struct sock *shrm_nl_sk;
static char shrm_common_tx_state = SHRM_SLEEP_STATE;
@@ -53,6 +55,7 @@ static char shrm_audio_rx_state = SHRM_SLEEP_STATE;
static atomic_t ac_sleep_disable_count = ATOMIC_INIT(0);
static atomic_t ac_msg_pend_1 = ATOMIC_INIT(0);
static atomic_t mod_stuck = ATOMIC_INIT(0);
+static atomic_t fifo_full = ATOMIC_INIT(0);
static struct shrm_dev *shm_dev;
/* Spin lock and tasklet declaration */
@@ -108,6 +111,13 @@ static u32 get_host_accessport_val(void)
return prcm_hostaccess;
}
+static enum hrtimer_restart shm_fifo_full_timeout(struct hrtimer *timer)
+{
+ queue_kthread_work(&shm_dev->shm_mod_stuck_kw,
+ &shm_dev->shm_mod_reset_req);
+ return HRTIMER_NORESTART;
+}
+
static enum hrtimer_restart shm_mod_stuck_timeout(struct hrtimer *timer)
{
unsigned long flags;
@@ -115,7 +125,7 @@ static enum hrtimer_restart shm_mod_stuck_timeout(struct hrtimer *timer)
spin_lock_irqsave(&mod_stuck_lock, flags);
/* Check MSR is already in progress */
if (shm_dev->msr_flag || boot_state == BOOT_UNKNOWN ||
- atomic_read(&mod_stuck)) {
+ atomic_read(&mod_stuck) || atomic_read(&fifo_full)) {
spin_unlock_irqrestore(&mod_stuck_lock, flags);
return HRTIMER_NORESTART;
}
@@ -539,7 +549,9 @@ static int shrm_modem_reset_sequence(void)
hrtimer_cancel(&timer);
hrtimer_cancel(&mod_stuck_timer_0);
hrtimer_cancel(&mod_stuck_timer_1);
+ hrtimer_cancel(&fifo_full_timer);
atomic_set(&mod_stuck, 0);
+ atomic_set(&fifo_full, 0);
tasklet_disable_nosync(&shm_ac_read_0_tasklet);
tasklet_disable_nosync(&shm_ac_read_1_tasklet);
tasklet_disable_nosync(&shm_ca_0_tasklet);
@@ -801,6 +813,8 @@ int shrm_protocol_init(struct shrm_dev *shrm,
mod_stuck_timer_0.function = shm_mod_stuck_timeout;
hrtimer_init(&mod_stuck_timer_1, CLOCK_MONOTONIC, HRTIMER_MODE_REL);
mod_stuck_timer_1.function = shm_mod_stuck_timeout;
+ hrtimer_init(&fifo_full_timer, CLOCK_MONOTONIC, HRTIMER_MODE_REL);
+ fifo_full_timer.function = shm_fifo_full_timeout;
init_kthread_worker(&shrm->shm_common_ch_wr_kw);
shrm->shm_common_ch_wr_kw_task = kthread_run(kthread_worker_fn,
@@ -995,6 +1009,8 @@ irqreturn_t ac_read_notif_0_irq_handler(int irq, void *ctrlr)
dev_dbg(shrm->dev, "%s IN\n", __func__);
/* Cancel the modem stuck timer */
hrtimer_cancel(&mod_stuck_timer_0);
+ if(atomic_read(&fifo_full))
+ hrtimer_cancel(&fifo_full_timer);
if (check_modem_in_reset()) {
dev_err(shrm->dev, "%s:Modem state reset or unknown.\n",
@@ -1026,6 +1042,8 @@ irqreturn_t ac_read_notif_1_irq_handler(int irq, void *ctrlr)
dev_dbg(shrm->dev, "%s IN+\n", __func__);
/* Cancel the modem stuck timer */
hrtimer_cancel(&mod_stuck_timer_1);
+ if(atomic_read(&fifo_full))
+ hrtimer_cancel(&fifo_full_timer);
if (check_modem_in_reset()) {
dev_err(shrm->dev, "%s:Modem state reset or unknown.\n",
@@ -1165,6 +1183,15 @@ int shm_write_msg(struct shrm_dev *shrm, u8 l2_header,
ret = shm_write_msg_to_fifo(shrm, channel, l2_header, addr, length);
if (ret < 0) {
dev_err(shrm->dev, "write message to fifo failed\n");
+ if (ret == -EAGAIN) {
+ if(!atomic_read(&fifo_full)) {
+ /* Start a timer so as to handle this gently */
+ atomic_set(&fifo_full, 1);
+ hrtimer_start(&fifo_full_timer, ktime_set(
+ FIFO_FULL_TIMEOUT, 0),
+ HRTIMER_MODE_REL);
+ }
+ }
return ret;
}
/*