mirror of
https://github.com/torvalds/linux.git
synced 2026-07-31 19:47:08 +02:00
soc: qcom: rpmh: Optimize locking around flushing cache
In OS-Initiated mode of PSCI, a serialization is established in Linux between the last CPU powering down the cluster / domain and the CPU powering up back. The serialization is established by the genpd framework and therefore it doesn't help to lock around the cache. Refactor out the core of the flush functionality from the locking wrappers. Calling the core functionality avoids a spin trylock, which the RCU framework might consider suspicious under the circumstances. Change-Id: I242fb4827b71152bda36ea5870393054b8703309 Signed-off-by: Lina Iyer <ilina@codeaurora.org> Signed-off-by: Maulik Shah <quic_mkshah@quicinc.com>
This commit is contained in:
parent
7466fd9c13
commit
0d2c70be39
|
|
@ -151,5 +151,6 @@ int rpmh_rsc_mode_solver_set(struct rsc_drv *drv, bool enable);
|
|||
|
||||
void rpmh_tx_done(const struct tcs_request *msg, int r);
|
||||
int rpmh_flush(struct rpmh_ctrlr *ctrlr);
|
||||
int _rpmh_flush(struct rpmh_ctrlr *ctrlr);
|
||||
|
||||
#endif /* __RPM_INTERNAL_H__ */
|
||||
|
|
|
|||
|
|
@ -1064,7 +1064,7 @@ static int rpmh_rsc_pd_cb(struct notifier_block *nb,
|
|||
|
||||
/* We don't need to lock as domin on/off are serialized */
|
||||
if ((action == GENPD_NOTIFY_PRE_OFF) &&
|
||||
(rpmh_rsc_ctrlr_is_busy(drv) || rpmh_flush(&drv->client)))
|
||||
(rpmh_rsc_ctrlr_is_busy(drv) || _rpmh_flush(&drv->client)))
|
||||
return NOTIFY_BAD;
|
||||
|
||||
return NOTIFY_OK;
|
||||
|
|
|
|||
|
|
@ -470,6 +470,45 @@ static int send_single(struct rpmh_ctrlr *ctrlr, enum rpmh_state state,
|
|||
return rpmh_rsc_write_ctrl_data(ctrlr_to_drv(ctrlr), &rpm_msg.msg);
|
||||
}
|
||||
|
||||
int _rpmh_flush(struct rpmh_ctrlr *ctrlr)
|
||||
{
|
||||
struct cache_req *p;
|
||||
int ret = 0;
|
||||
|
||||
if (!ctrlr->dirty) {
|
||||
pr_debug("Skipping flush, TCS has latest data.\n");
|
||||
return ret;
|
||||
}
|
||||
|
||||
/* Invalidate the TCSes first to avoid stale data */
|
||||
rpmh_rsc_invalidate(ctrlr_to_drv(ctrlr));
|
||||
|
||||
/* First flush the cached batch requests */
|
||||
ret = flush_batch(ctrlr);
|
||||
if (ret)
|
||||
return ret;
|
||||
|
||||
list_for_each_entry(p, &ctrlr->cache, list) {
|
||||
if (!is_req_valid(p)) {
|
||||
pr_debug("%s: skipping RPMH req: a:%#x s:%#x w:%#x\n",
|
||||
__func__, p->addr, p->sleep_val, p->wake_val);
|
||||
continue;
|
||||
}
|
||||
ret = send_single(ctrlr, RPMH_SLEEP_STATE, p->addr,
|
||||
p->sleep_val);
|
||||
if (ret)
|
||||
return ret;
|
||||
ret = send_single(ctrlr, RPMH_WAKE_ONLY_STATE, p->addr,
|
||||
p->wake_val);
|
||||
if (ret)
|
||||
return ret;
|
||||
}
|
||||
|
||||
ctrlr->dirty = false;
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
/**
|
||||
* rpmh_flush() - Flushes the buffered sleep and wake sets to TCSes
|
||||
*
|
||||
|
|
@ -481,8 +520,7 @@ static int send_single(struct rpmh_ctrlr *ctrlr, enum rpmh_state state,
|
|||
*/
|
||||
int rpmh_flush(struct rpmh_ctrlr *ctrlr)
|
||||
{
|
||||
struct cache_req *p;
|
||||
int ret = 0;
|
||||
int ret;
|
||||
|
||||
if (rpmh_standalone)
|
||||
return 0;
|
||||
|
|
@ -498,7 +536,6 @@ int rpmh_flush(struct rpmh_ctrlr *ctrlr)
|
|||
* Conditionally check for irqs_disabled only when solver mode
|
||||
* is not available.
|
||||
*/
|
||||
|
||||
if (!(ctrlr->flags & SOLVER_PRESENT))
|
||||
lockdep_assert_irqs_disabled();
|
||||
|
||||
|
|
@ -508,40 +545,9 @@ int rpmh_flush(struct rpmh_ctrlr *ctrlr)
|
|||
*/
|
||||
if (!spin_trylock(&ctrlr->cache_lock))
|
||||
return -EBUSY;
|
||||
|
||||
if (!ctrlr->dirty) {
|
||||
pr_debug("Skipping flush, TCS has latest data.\n");
|
||||
goto exit;
|
||||
}
|
||||
|
||||
/* Invalidate the TCSes first to avoid stale data */
|
||||
rpmh_rsc_invalidate(ctrlr_to_drv(ctrlr));
|
||||
|
||||
/* First flush the cached batch requests */
|
||||
ret = flush_batch(ctrlr);
|
||||
if (ret)
|
||||
goto exit;
|
||||
|
||||
list_for_each_entry(p, &ctrlr->cache, list) {
|
||||
if (!is_req_valid(p)) {
|
||||
pr_debug("%s: skipping RPMH req: a:%#x s:%#x w:%#x",
|
||||
__func__, p->addr, p->sleep_val, p->wake_val);
|
||||
continue;
|
||||
}
|
||||
ret = send_single(ctrlr, RPMH_SLEEP_STATE, p->addr,
|
||||
p->sleep_val);
|
||||
if (ret)
|
||||
goto exit;
|
||||
ret = send_single(ctrlr, RPMH_WAKE_ONLY_STATE, p->addr,
|
||||
p->wake_val);
|
||||
if (ret)
|
||||
goto exit;
|
||||
}
|
||||
|
||||
ctrlr->dirty = false;
|
||||
|
||||
exit:
|
||||
ret = _rpmh_flush(ctrlr);
|
||||
spin_unlock(&ctrlr->cache_lock);
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
|
|
|
|||
Loading…
Reference in New Issue
Block a user