diff options
| author | Sagar Dharia <sdharia@codeaurora.org> | 2016-01-07 13:16:58 -0700 |
|---|---|---|
| committer | David Keitel <dkeitel@codeaurora.org> | 2016-03-23 21:17:20 -0700 |
| commit | 8957b9e33d29145ab17ec78d47fe5cd60295052d (patch) | |
| tree | 368197c90a7d2a6a43ff22fc449e0e79e0c4334f | |
| parent | 30e849fa8babb67b9afa00c60705f5d20ad9dd30 (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.c | 42 | ||||
| -rw-r--r-- | drivers/slimbus/slim-msm.c | 20 |
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) |
