mirror of
https://github.com/team-infusion-developers/android_kernel_samsung_msm8976.git
synced 2024-11-07 04:09:21 +00:00
Merge "slim_ngd: Handle invalid/timeout TX errors gracefully"
This commit is contained in:
commit
0e956a7b28
3 changed files with 79 additions and 18 deletions
|
@ -95,19 +95,22 @@ static irqreturn_t ngd_slim_interrupt(int irq, void *d)
|
|||
(stat & NGD_INT_MSG_TX_INVAL) || (stat & NGD_INT_DEV_ERR) ||
|
||||
(stat & NGD_INT_TX_NACKED_2)) {
|
||||
writel_relaxed(stat, ngd + NGD_INT_CLR);
|
||||
dev->err = -EIO;
|
||||
if (stat & NGD_INT_MSG_TX_INVAL)
|
||||
dev->err = -EINVAL;
|
||||
else
|
||||
dev->err = -EIO;
|
||||
|
||||
SLIM_WARN(dev, "NGD interrupt error:0x%x, err:%d\n", stat,
|
||||
dev->err);
|
||||
/* Guarantee that error interrupts are cleared */
|
||||
mb();
|
||||
msm_slim_manage_tx_msgq(dev, false, NULL);
|
||||
msm_slim_manage_tx_msgq(dev, false, NULL, dev->err);
|
||||
|
||||
} else if (stat & NGD_INT_TX_MSG_SENT) {
|
||||
writel_relaxed(NGD_INT_TX_MSG_SENT, ngd + NGD_INT_CLR);
|
||||
/* Make sure interrupt is cleared */
|
||||
mb();
|
||||
msm_slim_manage_tx_msgq(dev, false, NULL);
|
||||
msm_slim_manage_tx_msgq(dev, false, NULL, 0);
|
||||
}
|
||||
if (stat & NGD_INT_RX_MSG_RCVD) {
|
||||
u32 rx_buf[10];
|
||||
|
@ -475,6 +478,13 @@ static int ngd_xfer_msg(struct slim_controller *ctrl, struct slim_msg_txn *txn)
|
|||
}
|
||||
txn->rl--;
|
||||
|
||||
if (txn->len > SLIM_MSGQ_BUF_LEN || txn->rl > SLIM_MSGQ_BUF_LEN) {
|
||||
SLIM_WARN(dev, "msg exeeds HW lim:%d, rl:%d, mc:0x%x, mt:0x%x",
|
||||
txn->len, txn->rl, txn->mc, txn->mt);
|
||||
ret = -EDQUOT;
|
||||
goto ngd_xfer_err;
|
||||
}
|
||||
|
||||
if (txn->mt == SLIM_MSG_MT_CORE && txn->comp &&
|
||||
dev->use_tx_msgqs == MSM_MSGQ_ENABLED &&
|
||||
(txn_mc != SLIM_MSG_MC_REQUEST_INFORMATION &&
|
||||
|
@ -567,9 +577,26 @@ static int ngd_xfer_msg(struct slim_controller *ctrl, struct slim_msg_txn *txn)
|
|||
ret = msm_send_msg_buf(dev, pbuf, txn->rl,
|
||||
NGD_BASE(dev->ctrl.nr, dev->ver) + NGD_TX_MSG);
|
||||
if (!ret && sync_wr) {
|
||||
int i;
|
||||
int timeout = wait_for_completion_timeout(&tx_sent, HZ);
|
||||
if (!timeout) {
|
||||
if (!timeout && dev->use_tx_msgqs == MSM_MSGQ_ENABLED) {
|
||||
struct msm_slim_endp *endpoint = &dev->tx_msgq;
|
||||
struct sps_mem_buffer *mem = &endpoint->buf;
|
||||
u32 idx = (u32) (((u8 *)pbuf - (u8 *)mem->base) /
|
||||
SLIM_MSGQ_BUF_LEN);
|
||||
phys_addr_t addr = mem->phys_base +
|
||||
(idx * SLIM_MSGQ_BUF_LEN);
|
||||
ret = -ETIMEDOUT;
|
||||
SLIM_WARN(dev, "timeout, BAM desc_idx:%d, phys:%llx",
|
||||
idx, (u64)addr);
|
||||
for (i = 0; i < (SLIM_MSGQ_BUF_LEN >> 2) ; i++)
|
||||
SLIM_WARN(dev, "timeout:bam-desc[%d]:0x%x",
|
||||
i, *(pbuf + i));
|
||||
if (idx < MSM_TX_BUFS)
|
||||
dev->wr_comp[idx] = NULL;
|
||||
/* print BAM debug info for TX pipe */
|
||||
sps_get_bam_debug_info(dev->bam.hdl, 93,
|
||||
SPS_BAM_PIPE(4), 0, 2);
|
||||
/*
|
||||
* disconnect/recoonect pipe so that subsequent
|
||||
* transactions don't timeout due to unavailable
|
||||
|
@ -580,6 +607,12 @@ static int ngd_xfer_msg(struct slim_controller *ctrl, struct slim_msg_txn *txn)
|
|||
&dev->use_tx_msgqs);
|
||||
msm_slim_connect_endp(dev, &dev->tx_msgq, NULL);
|
||||
}
|
||||
} else if (!timeout) {
|
||||
ret = -ETIMEDOUT;
|
||||
SLIM_WARN(dev, "timeout non-BAM TX,len:%d", txn->rl);
|
||||
for (i = 0; i < (SLIM_MSGQ_BUF_LEN >> 2) ; i++)
|
||||
SLIM_WARN(dev, "timeout:txbuf[%d]:0x%x", i,
|
||||
dev->tx_buf[i]);
|
||||
} else {
|
||||
ret = dev->err;
|
||||
}
|
||||
|
@ -599,22 +632,27 @@ static int ngd_xfer_msg(struct slim_controller *ctrl, struct slim_msg_txn *txn)
|
|||
|
||||
SLIM_WARN(dev, "conf:0x%x,stat:0x%x,rxmsgq:0x%x\n",
|
||||
conf, stat, rx_msgq);
|
||||
SLIM_WARN(dev, "int_stat:0x%x,int_en:0x%x,int_cll:0x%x\n",
|
||||
SLIM_ERR(dev, "int_stat:0x%x,int_en:0x%x,int_cll:0x%x\n",
|
||||
int_stat, int_en, int_clr);
|
||||
} else if (txn_mt == SLIM_MSG_MT_DEST_REFERRED_USER &&
|
||||
}
|
||||
|
||||
if (txn_mt == SLIM_MSG_MT_DEST_REFERRED_USER &&
|
||||
(txn_mc == SLIM_USR_MC_CONNECT_SRC ||
|
||||
txn_mc == SLIM_USR_MC_CONNECT_SINK ||
|
||||
txn_mc == SLIM_USR_MC_DISCONNECT_PORT)) {
|
||||
int timeout;
|
||||
mutex_unlock(&dev->tx_lock);
|
||||
msm_slim_put_ctrl(dev);
|
||||
timeout = wait_for_completion_timeout(txn->comp, HZ);
|
||||
if (!timeout)
|
||||
ret = -ETIMEDOUT;
|
||||
else
|
||||
ret = txn->ec;
|
||||
if (!ret) {
|
||||
timeout = wait_for_completion_timeout(txn->comp, HZ);
|
||||
/* remote side did not acknowledge */
|
||||
if (!timeout)
|
||||
ret = -EREMOTEIO;
|
||||
else
|
||||
ret = txn->ec;
|
||||
}
|
||||
if (ret) {
|
||||
SLIM_INFO(dev,
|
||||
SLIM_ERR(dev,
|
||||
"connect/disconnect:0x%x,tid:%d err:%d\n",
|
||||
txn->mc, txn->tid, ret);
|
||||
mutex_lock(&ctrl->m_ctrl);
|
||||
|
|
|
@ -417,7 +417,7 @@ static int msm_slim_post_tx_msgq(struct msm_slim_ctrl *dev, u8 *buf, int len)
|
|||
return ret;
|
||||
}
|
||||
|
||||
void msm_slim_tx_msg_return(struct msm_slim_ctrl *dev)
|
||||
void msm_slim_tx_msg_return(struct msm_slim_ctrl *dev, int err)
|
||||
{
|
||||
struct msm_slim_endp *endpoint = &dev->tx_msgq;
|
||||
struct sps_mem_buffer *mem = &endpoint->buf;
|
||||
|
@ -446,6 +446,25 @@ void msm_slim_tx_msg_return(struct msm_slim_ctrl *dev)
|
|||
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%llx, io:0x%x",
|
||||
(u64)mem->phys_base, iovec.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;
|
||||
u32 *addr = (u32 *)mem->base +
|
||||
(idx * (SLIM_MSGQ_BUF_LEN >> 2));
|
||||
/* 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)
|
||||
|
@ -477,7 +496,7 @@ static u32 *msm_slim_modify_tx_buf(struct msm_slim_ctrl *dev,
|
|||
return retbuf;
|
||||
}
|
||||
u32 *msm_slim_manage_tx_msgq(struct msm_slim_ctrl *dev, bool getbuf,
|
||||
struct completion *comp)
|
||||
struct completion *comp, int err)
|
||||
{
|
||||
int ret = 0;
|
||||
int retries = 0;
|
||||
|
@ -485,7 +504,7 @@ u32 *msm_slim_manage_tx_msgq(struct msm_slim_ctrl *dev, bool getbuf,
|
|||
|
||||
mutex_lock(&dev->tx_buf_lock);
|
||||
if (!getbuf) {
|
||||
msm_slim_tx_msg_return(dev);
|
||||
msm_slim_tx_msg_return(dev, err);
|
||||
mutex_unlock(&dev->tx_buf_lock);
|
||||
return NULL;
|
||||
}
|
||||
|
@ -497,7 +516,7 @@ u32 *msm_slim_manage_tx_msgq(struct msm_slim_ctrl *dev, bool getbuf,
|
|||
}
|
||||
|
||||
do {
|
||||
msm_slim_tx_msg_return(dev);
|
||||
msm_slim_tx_msg_return(dev, err);
|
||||
retbuf = msm_slim_modify_tx_buf(dev, comp);
|
||||
if (!retbuf)
|
||||
ret = -EAGAIN;
|
||||
|
@ -551,7 +570,7 @@ u32 *msm_get_msg_buf(struct msm_slim_ctrl *dev, int len,
|
|||
return dev->tx_buf;
|
||||
}
|
||||
|
||||
return msm_slim_manage_tx_msgq(dev, true, comp);
|
||||
return msm_slim_manage_tx_msgq(dev, true, comp, 0);
|
||||
}
|
||||
|
||||
static void
|
||||
|
@ -701,8 +720,12 @@ int msm_slim_connect_endp(struct msm_slim_ctrl *dev,
|
|||
}
|
||||
dev->use_rx_msgqs = MSM_MSGQ_ENABLED;
|
||||
} else {
|
||||
mutex_lock(&dev->tx_buf_lock);
|
||||
dev->tx_tail = 0;
|
||||
dev->tx_head = 0;
|
||||
for (i = 0; i < MSM_TX_BUFS; i++)
|
||||
dev->wr_comp[i] = NULL;
|
||||
mutex_unlock(&dev->tx_buf_lock);
|
||||
dev->use_tx_msgqs = MSM_MSGQ_ENABLED;
|
||||
}
|
||||
|
||||
|
|
|
@ -379,7 +379,7 @@ int msm_send_msg_buf(struct msm_slim_ctrl *dev, u32 *buf, u8 len, u32 tx_reg);
|
|||
u32 *msm_get_msg_buf(struct msm_slim_ctrl *dev, int len,
|
||||
struct completion *comp);
|
||||
u32 *msm_slim_manage_tx_msgq(struct msm_slim_ctrl *dev, bool getbuf,
|
||||
struct completion *comp);
|
||||
struct completion *comp, int err);
|
||||
int msm_slim_rx_msgq_get(struct msm_slim_ctrl *dev, u32 *data, int offset);
|
||||
int msm_slim_sps_init(struct msm_slim_ctrl *dev, struct resource *bam_mem,
|
||||
u32 pipe_reg, bool remote);
|
||||
|
|
Loading…
Reference in a new issue