Merge "drivers: qcom: rpmh: Disallow active requests in solver mode"

This commit is contained in:
qctecmdr 2022-05-10 06:29:35 -07:00 committed by Gerrit - the friendly Code Review server
commit 219f36ae55
5 changed files with 117 additions and 2 deletions

View File

@ -77,12 +77,14 @@ struct rpmh_request {
* @cache: the list of cached requests
* @cache_lock: synchronize access to the cache data
* @dirty: was the cache updated since flush
* @in_solver_mode: Controller is busy in solver mode
* @batch_cache: Cache sleep and wake requests sent as batch
*/
struct rpmh_ctrlr {
struct list_head cache;
spinlock_t cache_lock;
bool dirty;
bool in_solver_mode;
struct list_head batch_cache;
};
@ -95,6 +97,7 @@ struct rpmh_ctrlr {
* @id: Instance id in the controller (Direct Resource Voter).
* @num_tcs: Number of TCSes in this DRV.
* @irq: IRQ at gic.
* @in_solver_mode: Controller is busy in solver mode
* @rsc_pm: CPU PM notifier for controller.
* Used when solver mode is not present.
* @cpus_in_pm: Number of CPUs not in idle power collapse.
@ -118,6 +121,7 @@ struct rsc_drv {
int id;
int num_tcs;
int irq;
bool in_solver_mode;
struct notifier_block rsc_pm;
atomic_t cpus_in_pm;
struct tcs_group tcs[TCS_TYPE_NR];
@ -132,6 +136,7 @@ int rpmh_rsc_write_ctrl_data(struct rsc_drv *drv,
const struct tcs_request *msg);
void rpmh_rsc_invalidate(struct rsc_drv *drv);
void rpmh_rsc_debug(struct rsc_drv *drv, struct completion *compl);
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);

View File

@ -626,6 +626,12 @@ int rpmh_rsc_send_data(struct rsc_drv *drv, const struct tcs_request *msg)
spin_lock_irqsave(&drv->lock, flags);
/* Controller is busy in 'solver' mode */
if (drv->in_solver_mode) {
spin_unlock_irqrestore(&drv->lock, flags);
return -EBUSY;
}
/* Wait forever for a free tcs. It better be there eventually! */
wait_event_lock_irq(drv->tcs_wait,
(tcs_id = claim_tcs_for_req(drv, tcs, msg)) >= 0,
@ -950,6 +956,31 @@ static int rpmh_rsc_cpu_pm_callback(struct notifier_block *nfb,
return ret;
}
/**
* rpmh_rsc_mode_solver_set() - Enable/disable solver mode.
* @drv: The controller.
* @enable: Boolean state to be set - true/false
*
* Return:
* * 0 - success
* * -EBUSY - AMCs are busy
*/
int rpmh_rsc_mode_solver_set(struct rsc_drv *drv, bool enable)
{
int ret = -EBUSY;
if (spin_trylock(&drv->lock)) {
if (!enable || !rpmh_rsc_ctrlr_is_busy(drv)) {
drv->in_solver_mode = enable;
trace_rpmh_solver_set(drv, enable);
ret = 0;
}
spin_unlock(&drv->lock);
}
return ret;
}
static int rpmh_probe_tcs_config(struct platform_device *pdev,
struct rsc_drv *drv, void __iomem *base)
{

View File

@ -76,6 +76,22 @@ static struct rpmh_ctrlr *get_rpmh_ctrlr(const struct device *dev)
return &drv->client;
}
static int check_ctrlr_state(struct rpmh_ctrlr *ctrlr, enum rpmh_state state)
{
int ret = 0;
if (state != RPMH_ACTIVE_ONLY_STATE)
return ret;
/* Do not allow sending active votes when in solver mode */
spin_lock(&ctrlr->cache_lock);
if (ctrlr->in_solver_mode)
ret = -EBUSY;
spin_unlock(&ctrlr->cache_lock);
return ret;
}
void rpmh_tx_done(const struct tcs_request *msg, int r)
{
struct rpmh_request *rpm_msg = container_of(msg, struct rpmh_request,
@ -229,9 +245,14 @@ static int __fill_rpmh_msg(struct rpmh_request *req, enum rpmh_state state,
int rpmh_write_async(const struct device *dev, enum rpmh_state state,
const struct tcs_cmd *cmd, u32 n)
{
struct rpmh_ctrlr *ctrlr = get_rpmh_ctrlr(dev);
struct rpmh_request *rpm_msg;
int ret;
ret = check_ctrlr_state(ctrlr, state);
if (ret)
return ret;
rpm_msg = kzalloc(sizeof(*rpm_msg), GFP_ATOMIC);
if (!rpm_msg)
return -ENOMEM;
@ -265,6 +286,10 @@ int rpmh_write(const struct device *dev, enum rpmh_state state,
struct rpmh_ctrlr *ctrlr = get_rpmh_ctrlr(dev);
int ret;
ret = check_ctrlr_state(ctrlr, state);
if (ret)
return ret;
ret = __fill_rpmh_msg(&rpm_msg, state, cmd, n);
if (ret)
return ret;
@ -343,6 +368,10 @@ int rpmh_write_batch(const struct device *dev, enum rpmh_state state,
int ret, i;
void *ptr;
ret = check_ctrlr_state(ctrlr, state);
if (ret)
return ret;
if (!cmd || !n)
return -EINVAL;
@ -510,3 +539,28 @@ void rpmh_invalidate(const struct device *dev)
spin_unlock_irqrestore(&ctrlr->cache_lock, flags);
}
EXPORT_SYMBOL(rpmh_invalidate);
/**
* rpmh_mode_solver_set: Indicate that the RSC controller hardware has
* been configured to be in solver mode
*
* @dev: The device making the request
* @enable: Boolean value indicating if the controller is in solver mode.
* Return:
* * 0 - Success
* * Error code - Otherwise
*/
int rpmh_mode_solver_set(const struct device *dev, bool enable)
{
int ret;
struct rpmh_ctrlr *ctrlr = get_rpmh_ctrlr(dev);
spin_lock(&ctrlr->cache_lock);
ret = rpmh_rsc_mode_solver_set(ctrlr_to_drv(ctrlr), enable);
if (!ret)
ctrlr->in_solver_mode = enable;
spin_unlock(&ctrlr->cache_lock);
return ret;
}
EXPORT_SYMBOL(rpmh_mode_solver_set);

View File

@ -1,6 +1,6 @@
/* SPDX-License-Identifier: GPL-2.0 */
/*
* Copyright (c) 2016-2018, The Linux Foundation. All rights reserved.
* Copyright (c) 2016-2019, The Linux Foundation. All rights reserved.
*/
#if !defined(_TRACE_RPMH_H) || defined(TRACE_HEADER_MULTI_READ)
@ -71,6 +71,26 @@ TRACE_EVENT(rpmh_send_msg,
__entry->addr, __entry->data, __entry->wait)
);
TRACE_EVENT(rpmh_solver_set,
TP_PROTO(struct rsc_drv *d, bool set),
TP_ARGS(d, set),
TP_STRUCT__entry(
__string(name, d->name)
__field(bool, set)
),
TP_fast_assign(
__assign_str(name, d->name);
__entry->set = set;
),
TP_printk("%s: solver mode set: %d",
__get_str(name), __entry->set)
);
#endif /* _TRACE_RPMH_H */
#undef TRACE_INCLUDE_PATH

View File

@ -1,6 +1,6 @@
/* SPDX-License-Identifier: GPL-2.0 */
/*
* Copyright (c) 2016-2018, The Linux Foundation. All rights reserved.
* Copyright (c) 2016-2019, The Linux Foundation. All rights reserved.
*/
#ifndef __SOC_QCOM_RPMH_H__
@ -20,6 +20,8 @@ int rpmh_write_async(const struct device *dev, enum rpmh_state state,
int rpmh_write_batch(const struct device *dev, enum rpmh_state state,
const struct tcs_cmd *cmd, u32 *n);
int rpmh_mode_solver_set(const struct device *dev, bool enable);
void rpmh_invalidate(const struct device *dev);
#else
@ -38,6 +40,9 @@ static inline int rpmh_write_batch(const struct device *dev,
const struct tcs_cmd *cmd, u32 *n)
{ return -ENODEV; }
static int rpmh_mode_solver_set(const struct device *dev, bool enable)
{ return -ENODEV; }
static inline void rpmh_invalidate(const struct device *dev)
{
}