summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorSagar Dharia <sdharia@codeaurora.org>2016-01-07 13:16:58 -0700
committerDavid Keitel <dkeitel@codeaurora.org>2016-03-23 21:17:20 -0700
commit8957b9e33d29145ab17ec78d47fe5cd60295052d (patch)
tree368197c90a7d2a6a43ff22fc449e0e79e0c4334f
parent30e849fa8babb67b9afa00c60705f5d20ad9dd30 (diff)
slim: msm: Improve bulk message timeout error handling
If a bulk message times out due to interrupt starvation, a late coming interrupt may access structures that are not valid. Improve timeout error handling by resetting variables, and changing relevant logging. Change-Id: Ie0ee2fd9c2ce1628c69e1975fe713a2a26d9e716 Signed-off-by: Sagar Dharia <sdharia@codeaurora.org>
-rw-r--r--drivers/slimbus/slim-msm-ngd.c42
-rw-r--r--drivers/slimbus/slim-msm.c20
2 files changed, 29 insertions, 33 deletions
diff --git a/drivers/slimbus/slim-msm-ngd.c b/drivers/slimbus/slim-msm-ngd.c
index c529e221f68e..7cb2dcef80ef 100644
--- a/drivers/slimbus/slim-msm-ngd.c
+++ b/drivers/slimbus/slim-msm-ngd.c
@@ -1,4 +1,4 @@
-/* Copyright (c) 2011-2015, The Linux Foundation. All rights reserved.
+/* Copyright (c) 2011-2016, The Linux Foundation. All rights reserved.
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License version 2 and
@@ -284,6 +284,21 @@ static int ngd_get_tid(struct slim_controller *ctrl, struct slim_msg_txn *txn,
spin_unlock_irqrestore(&ctrl->txn_lock, flags);
return 0;
}
+
+static void slim_reinit_tx_msgq(struct msm_slim_ctrl *dev)
+{
+ /*
+ * disconnect/recoonect pipe so that subsequent
+ * transactions don't timeout due to unavailable
+ * descriptors
+ */
+ if (dev->state != MSM_CTRL_DOWN) {
+ msm_slim_disconnect_endp(dev, &dev->tx_msgq,
+ &dev->use_tx_msgqs);
+ msm_slim_connect_endp(dev, &dev->tx_msgq);
+ }
+}
+
static int ngd_xfer_msg(struct slim_controller *ctrl, struct slim_msg_txn *txn)
{
DECLARE_COMPLETION_ONSTACK(done);
@@ -570,19 +585,7 @@ static int ngd_xfer_msg(struct slim_controller *ctrl, struct slim_msg_txn *txn)
i, *(pbuf + i));
if (idx < MSM_TX_BUFS)
dev->wr_comp[idx] = NULL;
- /*
- * disconnect/recoonect pipe so that subsequent
- * transactions don't timeout due to unavailable
- * descriptors
- */
- if (dev->state != MSM_CTRL_DOWN) {
- /* print BAM debug info for TX pipe */
- sps_get_bam_debug_info(dev->bam.hdl, 93,
- SPS_BAM_PIPE(4), 0, 2);
- msm_slim_disconnect_endp(dev, &dev->tx_msgq,
- &dev->use_tx_msgqs);
- msm_slim_connect_endp(dev, &dev->tx_msgq);
- }
+ slim_reinit_tx_msgq(dev);
} else if (!timeout) {
ret = -ETIMEDOUT;
SLIM_WARN(dev, "timeout non-BAM TX,len:%d", txn->rl);
@@ -791,11 +794,6 @@ static int ngd_bulk_wr(struct slim_controller *ctrl, u8 la, u8 mt, u8 mc,
}
}
header = dev->bulk.base;
- /* SLIM_INFO only prints to internal buffer log, does not do pr_info */
- for (i = 0; i < (dev->bulk.size); i += 16, header += 4)
- SLIM_INFO(dev, "bulk sz:%d:0x%x, 0x%x, 0x%x, 0x%x",
- dev->bulk.size, *header, *(header+1), *(header+2),
- *(header+3));
if (comp_cb) {
dev->bulk.cb = comp_cb;
dev->bulk.ctx = ctx;
@@ -827,8 +825,12 @@ static int ngd_bulk_wr(struct slim_controller *ctrl, u8 la, u8 mt, u8 mc,
}
}
retpath:
- if (ret)
+ if (ret) {
dev->bulk.in_progress = false;
+ dev->bulk.ctx = NULL;
+ dev->bulk.wr_dma = 0;
+ slim_reinit_tx_msgq(dev);
+ }
mutex_unlock(&dev->tx_lock);
msm_slim_put_ctrl(dev);
return ret;
diff --git a/drivers/slimbus/slim-msm.c b/drivers/slimbus/slim-msm.c
index e17a5c7857b8..1ca5109615fe 100644
--- a/drivers/slimbus/slim-msm.c
+++ b/drivers/slimbus/slim-msm.c
@@ -531,7 +531,6 @@ void msm_slim_tx_msg_return(struct msm_slim_ctrl *dev, int err)
return;
}
if (addr == dev->bulk.wr_dma) {
- SLIM_INFO(dev, "BULK WR complete");
dma_unmap_single(dev->dev, dev->bulk.wr_dma,
dev->bulk.size, DMA_TO_DEVICE);
if (!dev->bulk.cb)
@@ -541,20 +540,19 @@ void msm_slim_tx_msg_return(struct msm_slim_ctrl *dev, int err)
dev->bulk.in_progress = false;
pm_runtime_mark_last_busy(dev->dev);
return;
+ } else if (addr < mem->phys_base ||
+ (addr > (mem->phys_base +
+ (MSM_TX_BUFS * SLIM_MSGQ_BUF_LEN)))) {
+ SLIM_WARN(dev, "BUF out of bounds:base:0x%pa, io:0x%pa",
+ &mem->phys_base, &addr);
+ continue;
}
idx = (int) ((addr - mem->phys_base)
/ SLIM_MSGQ_BUF_LEN);
- if (idx < MSM_TX_BUFS && dev->wr_comp[idx]) {
+ if (dev->wr_comp[idx]) {
struct completion *comp = dev->wr_comp[idx];
dev->wr_comp[idx] = NULL;
complete(comp);
- } else if (idx >= MSM_TX_BUFS) {
- SLIM_ERR(dev, "BUF out of bounds:base:0x%pa, io:0x%pa",
- &mem->phys_base, &addr);
- /* print BAM debug info for TX pipe */
- sps_get_bam_debug_info(dev->bam.hdl, 93,
- SPS_BAM_PIPE(4), 0, 2);
- continue;
}
if (err) {
int i;
@@ -563,10 +561,6 @@ void msm_slim_tx_msg_return(struct msm_slim_ctrl *dev, int err)
/* print the descriptor that resulted in error */
for (i = 0; i < (SLIM_MSGQ_BUF_LEN >> 2); i++)
SLIM_WARN(dev, "err desc[%d]:0x%x", i, addr[i]);
- /* print BAM debug info for TX pipe for invalid TX */
- if (err == -EINVAL)
- sps_get_bam_debug_info(dev->bam.hdl, 93,
- SPS_BAM_PIPE(4), 0, 2);
}
/* reclaim all packets that were delivered out of order */
if (idx != dev->tx_head)