From 0d2c70be3909090b729d13be143df85643922391 Mon Sep 17 00:00:00 2001 From: Lina Iyer Date: Thu, 3 Sep 2020 13:53:28 -0600 Subject: [PATCH] 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 Signed-off-by: Maulik Shah --- drivers/soc/qcom/rpmh-internal.h | 1 + drivers/soc/qcom/rpmh-rsc.c | 2 +- drivers/soc/qcom/rpmh.c | 78 +++++++++++++++++--------------- 3 files changed, 44 insertions(+), 37 deletions(-) diff --git a/drivers/soc/qcom/rpmh-internal.h b/drivers/soc/qcom/rpmh-internal.h index 02ad7da2e75e..81185196e5ef 100644 --- a/drivers/soc/qcom/rpmh-internal.h +++ b/drivers/soc/qcom/rpmh-internal.h @@ -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__ */ diff --git a/drivers/soc/qcom/rpmh-rsc.c b/drivers/soc/qcom/rpmh-rsc.c index 0f6b55ea426a..63fc115b3239 100644 --- a/drivers/soc/qcom/rpmh-rsc.c +++ b/drivers/soc/qcom/rpmh-rsc.c @@ -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; diff --git a/drivers/soc/qcom/rpmh.c b/drivers/soc/qcom/rpmh.c index e4a50fd41412..43a06d93cd56 100644 --- a/drivers/soc/qcom/rpmh.c +++ b/drivers/soc/qcom/rpmh.c @@ -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; }