summaryrefslogtreecommitdiff
path: root/drivers/soc
diff options
context:
space:
mode:
authorDeven Patel <cdevenp@codeaurora.org>2016-02-22 14:12:02 -0800
committerDavid Keitel <dkeitel@codeaurora.org>2016-03-25 16:03:13 -0700
commit3e36cd9a4228712f040adb806818d5b08e227282 (patch)
treee93edabd88ba417caed5f7df27ad88c0a4b946b0 /drivers/soc
parentc594314ae595d80b3551e2286aedf2cae920c5e5 (diff)
drivers: soc: put APR Tx buffer back into queue in error scenario
When underlying channel fails to send the APR buffer to the remote end, APR should put the Tx buffer back into queue to avoid memory leak. CRs-fixed: 979283 Change-Id: I4f94daa3c9be748a30d532cf9cc8f3aa2284c060 Signed-off-by: Deven Patel <cdevenp@codeaurora.org>
Diffstat (limited to 'drivers/soc')
-rw-r--r--drivers/soc/qcom/qdsp6v2/apr_tal_glink.c29
1 files changed, 21 insertions, 8 deletions
diff --git a/drivers/soc/qcom/qdsp6v2/apr_tal_glink.c b/drivers/soc/qcom/qdsp6v2/apr_tal_glink.c
index fb3ce963a1a9..7aa075c4cff1 100644
--- a/drivers/soc/qcom/qdsp6v2/apr_tal_glink.c
+++ b/drivers/soc/qcom/qdsp6v2/apr_tal_glink.c
@@ -92,6 +92,20 @@ static int apr_get_free_buf(int len, void **buf)
return 0;
}
+static void apr_buf_add_tail(void *buf)
+{
+ struct apr_tx_buf *list;
+ unsigned long flags;
+
+ if (!buf)
+ return;
+
+ spin_lock_irqsave(&buf_list.lock, flags);
+ list = container_of(buf, struct apr_tx_buf, buf);
+ list_add_tail(&list->list, &buf_list.list);
+ spin_unlock_irqrestore(&buf_list.lock, flags);
+}
+
static int __apr_tal_write(struct apr_svc_ch_dev *apr_ch, void *data,
struct apr_pkt_priv *pkt_priv, int len)
{
@@ -137,8 +151,11 @@ int apr_tal_write(struct apr_svc_ch_dev *apr_ch, void *data,
rc = __apr_tal_write(apr_ch, pkt_data, pkt_priv, len);
} while (rc == -EAGAIN && retries++ < APR_MAXIMUM_NUM_OF_RETRIES);
- if (rc == -EAGAIN)
- pr_err("%s: TIMEOUT for write\n", __func__);
+ if (rc < 0) {
+ pr_err("%s: Unable to send the packet, rc:%d\n", __func__, rc);
+ if (pkt_priv->pkt_owner == APR_PKT_OWNER_DRIVER)
+ apr_buf_add_tail(pkt_data);
+ }
exit:
return rc;
}
@@ -177,12 +194,8 @@ void apr_tal_notify_tx_done(void *handle, const void *priv,
pr_debug("%s: tx_done received\n", __func__);
- if (apr_pkt_priv->pkt_owner == APR_PKT_OWNER_DRIVER) {
- spin_lock_irqsave(&buf_list.lock, flags);
- buf = container_of(ptr, struct apr_tx_buf, list);
- list_add_tail(&buf->list, &buf_list.list);
- spin_unlock_irqrestore(&buf_list.lock, flags);
- }
+ if (apr_pkt_priv->pkt_owner == APR_PKT_OWNER_DRIVER)
+ apr_buf_add_tail(ptr);
}
bool apr_tal_notify_rx_intent_req(void *handle, const void *priv,