Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit 377e9254 authored by Sagar Dharia's avatar Sagar Dharia Committed by Gerrit - the friendly Code Review server
Browse files

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: default avatarSagar Dharia <sdharia@codeaurora.org>
parent 6f19e644
Loading
Loading
Loading
Loading
+22 −20
Original line number Diff line number Diff line
/* 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;
+7 −13
Original line number Diff line number Diff line
@@ -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)