slimbus: Decrement channel reference during reconfigure now
Slimbus clients can specify multiple add/remove channel requests
through control_ch API, followed by reconfiguration request (also
known as "commit request"). Clients may rely on the reconfiguration
request to actuate the channel activation/removal and not the
control-channel API.
So the channel reference should be decremented during reconfiguration
request, and not control_ch API.
CRs-Fixed: 389518
Change-Id: Id6ff57c6a4cad878e35004937fb08daf3b9afe7b
Signed-off-by: Sagar Dharia <sdharia@codeaurora.org>
diff --git a/drivers/slimbus/slimbus.c b/drivers/slimbus/slimbus.c
index e50addb..8dce000 100644
--- a/drivers/slimbus/slimbus.c
+++ b/drivers/slimbus/slimbus.c
@@ -2579,20 +2579,38 @@
u32 segdist;
struct slim_pending_ch *pch;
+ mutex_lock(&ctrl->sched.m_reconf);
+ mutex_lock(&ctrl->m_ctrl);
/*
* If there are no pending changes from this client, avoid sending
* the reconfiguration sequence
*/
if (sb->pending_msgsl == sb->cur_msgsl &&
list_empty(&sb->mark_define) &&
- list_empty(&sb->mark_removal) &&
list_empty(&sb->mark_suspend)) {
- pr_debug("SLIM_CL: skip reconfig sequence");
- return 0;
+ struct list_head *pos, *next;
+ list_for_each_safe(pos, next, &sb->mark_removal) {
+ struct slim_ich *slc;
+ pch = list_entry(pos, struct slim_pending_ch, pending);
+ slc = &ctrl->chans[pch->chan];
+ if (slc->def > 0)
+ slc->def--;
+ /* Disconnect source port to free it up */
+ if (SLIM_HDL_TO_LA(slc->srch) == sb->laddr)
+ slc->srch = 0;
+ if (slc->def != 0) {
+ list_del(&pch->pending);
+ kfree(pch);
+ }
+ }
+ if (list_empty(&sb->mark_removal)) {
+ mutex_unlock(&ctrl->m_ctrl);
+ mutex_unlock(&ctrl->sched.m_reconf);
+ pr_info("SLIM_CL: skip reconfig sequence");
+ return 0;
+ }
}
- mutex_lock(&ctrl->sched.m_reconf);
- mutex_lock(&ctrl->m_ctrl);
ctrl->sched.pending_msgsl += sb->pending_msgsl - sb->cur_msgsl;
list_for_each_entry(pch, &sb->mark_define, pending) {
struct slim_ich *slc = &ctrl->chans[pch->chan];
@@ -2848,13 +2866,7 @@
ret = -ENOTCONN;
break;
}
- if (slc->def > 0)
- slc->def--;
- /* Disconnect source port to free it up */
- if (SLIM_HDL_TO_LA(slc->srch) == sb->laddr)
- slc->srch = 0;
- if (slc->def == 0)
- ret = add_pending_ch(&sb->mark_removal, chan);
+ ret = add_pending_ch(&sb->mark_removal, chan);
if (ret)
break;
}