slimbus: Refine scope of controller and scheduler mutex locks
Controller mutex scope is restricted to controller specific data
structures, such as addressing table, transaction table.
Scheduler lock is used to protect scheduling data structures (such
as channels, and bandwidth).
This way, controller mutex is not needed when expensive
reconfiguration sequence(used for channel scheduling, bandwidth
management) is in progress. Transactions over messaging channel (such
as element read/writes, logical address assignment) can happen in
parallel and don't have to block on reconfiguration sequence which
only affects data channels.
CRs-Fixed: 426945
Change-Id: I2ca20aa76901ee19dba62874c86c2108fac9fa02
Signed-off-by: Sagar Dharia <sdharia@codeaurora.org>
diff --git a/drivers/slimbus/slim-msm-ngd.c b/drivers/slimbus/slim-msm-ngd.c
index 02e1952..78e8a6f 100644
--- a/drivers/slimbus/slim-msm-ngd.c
+++ b/drivers/slimbus/slim-msm-ngd.c
@@ -172,13 +172,16 @@
u8 *tid, struct completion *done)
{
struct msm_slim_ctrl *dev = slim_get_ctrldata(ctrl);
+ mutex_lock(&ctrl->m_ctrl);
if (ctrl->last_tid <= 255) {
ctrl->txnt = krealloc(ctrl->txnt,
(ctrl->last_tid + 1) *
sizeof(struct slim_msg_txn *),
GFP_KERNEL);
- if (!ctrl->txnt)
+ if (!ctrl->txnt) {
+ mutex_unlock(&ctrl->m_ctrl);
return -ENOMEM;
+ }
dev->msg_cnt = ctrl->last_tid;
ctrl->last_tid++;
} else {
@@ -190,6 +193,7 @@
}
if (i >= 256) {
dev_err(&ctrl->dev, "out of TID");
+ mutex_unlock(&ctrl->m_ctrl);
return -ENOMEM;
}
}
@@ -197,6 +201,7 @@
txn->tid = dev->msg_cnt;
txn->comp = done;
*tid = dev->msg_cnt;
+ mutex_unlock(&ctrl->m_ctrl);
return 0;
}
static int ngd_xfer_msg(struct slim_controller *ctrl, struct slim_msg_txn *txn)
@@ -369,6 +374,9 @@
pr_err("connect/disc :0x%x, tid:%d timed out", txn->mc,
txn->tid);
ret = -ETIMEDOUT;
+ mutex_lock(&ctrl->m_ctrl);
+ ctrl->txnt[txn->tid] = NULL;
+ mutex_unlock(&ctrl->m_ctrl);
} else {
ret = txn->ec;
}
@@ -394,6 +402,9 @@
pr_err("master req:0x%x, tid:%d timed out", txn->mc,
txn->tid);
ret = -ETIMEDOUT;
+ mutex_lock(&ctrl->m_ctrl);
+ ctrl->txnt[txn->tid] = NULL;
+ mutex_unlock(&ctrl->m_ctrl);
} else {
ret = txn->ec;
}
@@ -526,10 +537,8 @@
txn.dt = SLIM_MSG_DEST_LOGICALADDR;
txn.la = SLIM_LA_MGR;
txn.ec = 0;
- mutex_lock(&ctrl->m_ctrl);
ret = ngd_get_tid(ctrl, &txn, &wbuf[0], &done);
if (ret) {
- mutex_unlock(&ctrl->m_ctrl);
return ret;
}
memcpy(&wbuf[1], ea, elen);
@@ -543,7 +552,6 @@
ret = -ENXIO;
else if (!ret)
*laddr = txn.la;
- mutex_unlock(&ctrl->m_ctrl);
return ret;
}
@@ -606,20 +614,33 @@
}
if (mc == SLIM_USR_MC_ADDR_REPLY &&
mt == SLIM_MSG_MT_SRC_REFERRED_USER) {
- struct slim_msg_txn *txn = dev->ctrl.txnt[buf[3]];
+ struct slim_msg_txn *txn;
u8 failed_ea[6] = {0, 0, 0, 0, 0, 0};
- if (!txn)
+ mutex_lock(&dev->ctrl.m_ctrl);
+ txn = dev->ctrl.txnt[buf[3]];
+ if (!txn) {
+ pr_err("LADDR response after timeout, tid:0x%x",
+ buf[3]);
+ mutex_unlock(&dev->ctrl.m_ctrl);
return;
+ }
if (memcmp(&buf[4], failed_ea, 6))
txn->la = buf[10];
dev->ctrl.txnt[buf[3]] = NULL;
+ mutex_unlock(&dev->ctrl.m_ctrl);
complete(txn->comp);
}
if (mc == SLIM_USR_MC_GENERIC_ACK &&
mt == SLIM_MSG_MT_SRC_REFERRED_USER) {
- struct slim_msg_txn *txn = dev->ctrl.txnt[buf[3]];
- if (!txn)
+ struct slim_msg_txn *txn;
+ mutex_lock(&dev->ctrl.m_ctrl);
+ txn = dev->ctrl.txnt[buf[3]];
+ if (!txn) {
+ pr_err("ACK received after timeout, tid:0x%x",
+ buf[3]);
+ mutex_unlock(&dev->ctrl.m_ctrl);
return;
+ }
dev_dbg(dev->dev, "got response:tid:%d, response:0x%x",
(int)buf[3], buf[4]);
if (!(buf[4] & MSM_SAT_SUCCSS)) {
@@ -628,6 +649,7 @@
txn->ec = -EIO;
}
dev->ctrl.txnt[buf[3]] = NULL;
+ mutex_unlock(&dev->ctrl.m_ctrl);
complete(txn->comp);
}
}
diff --git a/drivers/slimbus/slimbus.c b/drivers/slimbus/slimbus.c
index d5d6e0c..c320e46 100644
--- a/drivers/slimbus/slimbus.c
+++ b/drivers/slimbus/slimbus.c
@@ -1216,7 +1216,7 @@
if (flow != SLIM_SRC)
return -EINVAL;
- mutex_lock(&ctrl->m_ctrl);
+ mutex_lock(&ctrl->sched.m_reconf);
if (slc->state == SLIM_CH_FREE) {
ret = -ENOTCONN;
@@ -1238,7 +1238,7 @@
slc->srch = srch;
connect_src_err:
- mutex_unlock(&ctrl->m_ctrl);
+ mutex_unlock(&ctrl->sched.m_reconf);
return ret;
}
EXPORT_SYMBOL_GPL(slim_connect_src);
@@ -1265,7 +1265,7 @@
if (!sinkh || !nsink)
return -EINVAL;
- mutex_lock(&ctrl->m_ctrl);
+ mutex_lock(&ctrl->sched.m_reconf);
/*
* Once channel is removed, its ports can be considered disconnected
@@ -1303,7 +1303,7 @@
slc->nsink += nsink;
connect_sink_err:
- mutex_unlock(&ctrl->m_ctrl);
+ mutex_unlock(&ctrl->sched.m_reconf);
return ret;
}
EXPORT_SYMBOL_GPL(slim_connect_sink);
@@ -1320,11 +1320,11 @@
struct slim_controller *ctrl = sb->ctrl;
int i;
- mutex_lock(&ctrl->m_ctrl);
+ mutex_lock(&ctrl->sched.m_reconf);
for (i = 0; i < nph; i++)
disconnect_port_ch(ctrl, ph[i]);
- mutex_unlock(&ctrl->m_ctrl);
+ mutex_unlock(&ctrl->sched.m_reconf);
return 0;
}
EXPORT_SYMBOL_GPL(slim_disconnect_ports);
@@ -1660,13 +1660,13 @@
if (!ctrl)
return -EINVAL;
- mutex_lock(&ctrl->m_ctrl);
+ mutex_lock(&ctrl->sched.m_reconf);
for (i = 0; i < ctrl->nchans; i++) {
if (ctrl->chans[i].state == SLIM_CH_FREE)
break;
}
if (i >= ctrl->nchans) {
- mutex_unlock(&ctrl->m_ctrl);
+ mutex_unlock(&ctrl->sched.m_reconf);
return -EXFULL;
}
*chanh = i;
@@ -1674,7 +1674,7 @@
ctrl->chans[i].state = SLIM_CH_ALLOCATED;
ctrl->chans[i].chan = (u8)(ctrl->reserved + i);
- mutex_unlock(&ctrl->m_ctrl);
+ mutex_unlock(&ctrl->sched.m_reconf);
return 0;
}
EXPORT_SYMBOL_GPL(slim_alloc_ch);
@@ -1698,7 +1698,7 @@
int ret = 0;
if (!ctrl || !chanh)
return -EINVAL;
- mutex_lock(&ctrl->m_ctrl);
+ mutex_lock(&ctrl->sched.m_reconf);
/* start with modulo number */
i = ch % ctrl->nchans;
@@ -1729,7 +1729,7 @@
i = (i + 1) % ctrl->nchans;
}
query_out:
- mutex_unlock(&ctrl->m_ctrl);
+ mutex_unlock(&ctrl->sched.m_reconf);
dev_dbg(&ctrl->dev, "query ch:%d,hdl:%d,ref:%d,ret:%d",
ch, i, ctrl->chans[i].ref, ret);
return ret;
@@ -1751,26 +1751,26 @@
if (!ctrl)
return -EINVAL;
- mutex_lock(&ctrl->m_ctrl);
+ mutex_lock(&ctrl->sched.m_reconf);
if (slc->state == SLIM_CH_FREE) {
- mutex_unlock(&ctrl->m_ctrl);
+ mutex_unlock(&ctrl->sched.m_reconf);
return -ENOTCONN;
}
if (slc->ref > 1) {
slc->ref--;
- mutex_unlock(&ctrl->m_ctrl);
+ mutex_unlock(&ctrl->sched.m_reconf);
dev_dbg(&ctrl->dev, "remove chan:%d,hdl:%d,ref:%d",
slc->chan, chanh, slc->ref);
return 0;
}
if (slc->state >= SLIM_CH_PENDING_ACTIVE) {
dev_err(&ctrl->dev, "Channel:%d should be removed first", chan);
- mutex_unlock(&ctrl->m_ctrl);
+ mutex_unlock(&ctrl->sched.m_reconf);
return -EISCONN;
}
slc->ref--;
slc->state = SLIM_CH_FREE;
- mutex_unlock(&ctrl->m_ctrl);
+ mutex_unlock(&ctrl->sched.m_reconf);
dev_dbg(&ctrl->dev, "remove chan:%d,hdl:%d,ref:%d",
slc->chan, chanh, slc->ref);
return 0;
@@ -1812,7 +1812,7 @@
if (!ctrl || !chanh || !prop || !nchan)
return -EINVAL;
- mutex_lock(&ctrl->m_ctrl);
+ mutex_lock(&ctrl->sched.m_reconf);
for (i = 0; i < nchan; i++) {
u8 chan = SLIM_HDL_TO_CHIDX(chanh[i]);
struct slim_ich *slc = &ctrl->chans[chan];
@@ -1856,7 +1856,7 @@
}
err_define_ch:
dev_dbg(&ctrl->dev, "define_ch: ch:%d, ret:%d", *chanh, ret);
- mutex_unlock(&ctrl->m_ctrl);
+ mutex_unlock(&ctrl->sched.m_reconf);
return ret;
}
EXPORT_SYMBOL_GPL(slim_define_ch);
@@ -2607,7 +2607,6 @@
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
@@ -2631,7 +2630,6 @@
}
}
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;
@@ -2820,7 +2818,6 @@
ctrl->sched.msgsl = ctrl->sched.pending_msgsl;
sb->cur_msgsl = sb->pending_msgsl;
slim_chan_changes(sb, false);
- mutex_unlock(&ctrl->m_ctrl);
mutex_unlock(&ctrl->sched.m_reconf);
return 0;
}
@@ -2828,7 +2825,6 @@
revert_reconfig:
/* Revert channel changes */
slim_chan_changes(sb, true);
- mutex_unlock(&ctrl->m_ctrl);
mutex_unlock(&ctrl->sched.m_reconf);
return ret;
}
@@ -2876,7 +2872,6 @@
return -EINVAL;
mutex_lock(&sb->sldev_reconf);
- mutex_lock(&ctrl->m_ctrl);
do {
struct slim_pending_ch *pch;
u8 add_mark_removal = true;
@@ -2935,7 +2930,6 @@
if (nchan < SLIM_GRP_TO_NCHAN(chanh))
chan = SLIM_HDL_TO_CHIDX(slc->nextgrp);
} while (nchan < SLIM_GRP_TO_NCHAN(chanh));
- mutex_unlock(&ctrl->m_ctrl);
if (!ret && commit == true)
ret = slim_reconfigure_now(sb);
mutex_unlock(&sb->sldev_reconf);