summaryrefslogtreecommitdiff
path: root/drivers/soc/qcom/hab
diff options
context:
space:
mode:
authorYao Jiang <yaojia@codeaurora.org>2018-09-27 09:43:32 +0800
committerGerrit - the friendly Code Review server <code-review@localhost>2018-10-03 07:29:16 -0700
commit4873e89e68d4cd315c07ad8d019fac6275dba323 (patch)
treec88871748a1075287a2d0b695da78dfe96551f6a /drivers/soc/qcom/hab
parent070bf44aba13d672db9295f2ef2e98204c8e70ff (diff)
soc: qcom: hab: fix the soft lockup in vchan free schedule
With a certain probability soft lockup when do hab vchan free schedule. one vchan do the local hab close while another vchan in the same context through softirq also try to acquire write lock in the free schedule at the same time, it will cause watchdog bite. Disable local softirq could avoid race condition handling between tasklet and process context. Change-Id: I4ee9b980dab7ecb1986af1d61f70157fc30d1048 Signed-off-by: Yao Jiang <yaojia@codeaurora.org>
Diffstat (limited to 'drivers/soc/qcom/hab')
-rw-r--r--drivers/soc/qcom/hab/hab.c12
-rw-r--r--drivers/soc/qcom/hab/hab_vchan.c8
2 files changed, 10 insertions, 10 deletions
diff --git a/drivers/soc/qcom/hab/hab.c b/drivers/soc/qcom/hab/hab.c
index 65935f6eb48f..db4961f5f15f 100644
--- a/drivers/soc/qcom/hab/hab.c
+++ b/drivers/soc/qcom/hab/hab.c
@@ -117,7 +117,7 @@ void hab_ctx_free(struct kref *ref)
struct export_desc *exp, *exp_tmp;
/* garbage-collect exp/imp buffers */
- write_lock(&ctx->exp_lock);
+ write_lock_bh(&ctx->exp_lock);
list_for_each_entry_safe(exp, exp_tmp, &ctx->exp_whse, node) {
list_del(&exp->node);
pr_debug("potential leak exp %d vcid %X recovered\n",
@@ -125,7 +125,7 @@ void hab_ctx_free(struct kref *ref)
habmem_hyp_revoke(exp->payload, exp->payload_count);
habmem_remove_export(exp);
}
- write_unlock(&ctx->exp_lock);
+ write_unlock_bh(&ctx->exp_lock);
spin_lock_bh(&ctx->imp_lock);
list_for_each_entry_safe(exp, exp_tmp, &ctx->imp_whse, node) {
@@ -159,27 +159,27 @@ void hab_ctx_free(struct kref *ref)
ctx->kernel, ctx->closing, ctx->owner);
/* check vchans in this ctx */
- write_lock(&ctx->ctx_lock);
+ write_lock_bh(&ctx->ctx_lock);
list_for_each_entry(vchan, &ctx->vchannels, node) {
pr_warn("leak vchan id %X cnt %X remote %d in ctx\n",
vchan->id, get_refcnt(vchan->refcount),
vchan->otherend_id);
}
- write_unlock(&ctx->ctx_lock);
+ write_unlock_bh(&ctx->ctx_lock);
/* check pending open */
if (ctx->pending_cnt)
pr_warn("potential leak of pendin_open nodes %d\n",
ctx->pending_cnt);
- write_lock(&ctx->ctx_lock);
+ write_lock_bh(&ctx->ctx_lock);
list_for_each_entry(node, &ctx->pending_open, node) {
pr_warn("leak pending open vcid %X type %d subid %d openid %d\n",
node->request.xdata.vchan_id, node->request.type,
node->request.xdata.sub_id,
node->request.xdata.open_id);
}
- write_unlock(&ctx->ctx_lock);
+ write_unlock_bh(&ctx->ctx_lock);
/* check vchans belong to this ctx in all hab/mmid devices */
for (i = 0; i < hab_driver.ndevices; i++) {
diff --git a/drivers/soc/qcom/hab/hab_vchan.c b/drivers/soc/qcom/hab/hab_vchan.c
index e7b46df3f97e..e42b27f5048d 100644
--- a/drivers/soc/qcom/hab/hab_vchan.c
+++ b/drivers/soc/qcom/hab/hab_vchan.c
@@ -90,7 +90,7 @@ hab_vchan_free(struct kref *ref)
vchan->ctx = NULL;
/* release vchan from pchan. no more msg for this vchan */
- write_lock(&pchan->vchans_lock);
+ write_lock_bh(&pchan->vchans_lock);
list_for_each_entry_safe(vc, vc_tmp, &pchan->vchannels, pnode) {
if (vchan == vc) {
list_del(&vc->pnode);
@@ -99,7 +99,7 @@ hab_vchan_free(struct kref *ref)
break;
}
}
- write_unlock(&pchan->vchans_lock);
+ write_unlock_bh(&pchan->vchans_lock);
/* release idr at the last so same idr will not be used early */
spin_lock_bh(&pchan->vid_lock);
@@ -262,7 +262,7 @@ static void hab_vchan_schedule_free(struct kref *ref)
* similar logic is in ctx free. if ctx free runs first,
* this is skipped
*/
- write_lock(&ctx->ctx_lock);
+ write_lock_bh(&ctx->ctx_lock);
list_for_each_entry_safe(vchan, tmp, &ctx->vchannels, node) {
if (vchan == vchanin) {
pr_debug("vchan free refcnt = %d\n",
@@ -273,7 +273,7 @@ static void hab_vchan_schedule_free(struct kref *ref)
break;
}
}
- write_unlock(&ctx->ctx_lock);
+ write_unlock_bh(&ctx->ctx_lock);
if (bnotify)
hab_vchan_stop_notify(vchan);