mirror of
https://github.com/torvalds/linux.git
synced 2026-07-31 03:27:03 +02:00
coresight: Control path with range
CPU PM notifiers need to control only part of a path instead of always
operating on the full path.
Add internal enable and disable helpers that take an inclusive node
range [from, to], validate that the requested nodes are ordered before
using them.
Update the existed coresight_{enable|disable}_path() interfaces as
full-path wrappers by passing the first and last path nodes. The helpers
coresight_path_{first|last}_node() are provided for conveniently
fetching the first and last nodes on the path.
In coresight_enable_path_from_to(), if a failure occurs at the last node
in the range, no device is actually enabled in this case, bail out
directly.
Tested-by: Jie Gan <jie.gan@oss.qualcomm.com>
Reviewed-by: Yeoreum Yun <yeoreum.yun@arm.com>
Reviewed-by: James Clark <james.clark@linaro.org>
Tested-by: James Clark <james.clark@linaro.org>
Signed-off-by: Leo Yan <leo.yan@arm.com>
Signed-off-by: Suzuki K Poulose <suzuki.poulose@arm.com>
Link: https://lore.kernel.org/r/20260515-arm_coresight_path_power_management_improvement-v14-16-f88c4a3ecfe9@arm.com
This commit is contained in:
parent
5cae719943
commit
3d3289c0d8
|
|
@ -62,6 +62,24 @@ static LIST_HEAD(coresight_dev_idx_list);
|
|||
|
||||
static const struct cti_assoc_op *cti_assoc_ops;
|
||||
|
||||
static struct coresight_node *
|
||||
coresight_path_first_node(struct coresight_path *path)
|
||||
{
|
||||
if (list_empty(&path->path_list))
|
||||
return NULL;
|
||||
|
||||
return list_first_entry(&path->path_list, struct coresight_node, link);
|
||||
}
|
||||
|
||||
static struct coresight_node *
|
||||
coresight_path_last_node(struct coresight_path *path)
|
||||
{
|
||||
if (list_empty(&path->path_list))
|
||||
return NULL;
|
||||
|
||||
return list_last_entry(&path->path_list, struct coresight_node, link);
|
||||
}
|
||||
|
||||
void coresight_set_cti_ops(const struct cti_assoc_op *cti_op)
|
||||
{
|
||||
cti_assoc_ops = cti_op;
|
||||
|
|
@ -488,19 +506,41 @@ int coresight_resume_source(struct coresight_device *csdev)
|
|||
EXPORT_SYMBOL_GPL(coresight_resume_source);
|
||||
|
||||
/*
|
||||
* coresight_disable_path_from : Disable components in the given path starting
|
||||
* from @nd in the list. If @nd is NULL, all the components, except the SOURCE
|
||||
* are disabled.
|
||||
* Callers must fetch nodes from the path and pass @from and @to to the path
|
||||
* enable/disable functions. Walk the path from @from to locate @to. If @to
|
||||
* is found, it indicates @from and @to are in order. Otherwise, they are out
|
||||
* of order.
|
||||
*/
|
||||
static void coresight_disable_path_from(struct coresight_path *path,
|
||||
struct coresight_node *nd)
|
||||
static bool coresight_path_nodes_in_order(struct coresight_path *path,
|
||||
struct coresight_node *from,
|
||||
struct coresight_node *to)
|
||||
{
|
||||
struct coresight_node *nd;
|
||||
|
||||
if (WARN_ON_ONCE(!from || !to))
|
||||
return false;
|
||||
|
||||
nd = from;
|
||||
list_for_each_entry_from(nd, &path->path_list, link) {
|
||||
if (nd == to)
|
||||
return true;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
static void coresight_disable_path_from_to(struct coresight_path *path,
|
||||
struct coresight_node *from,
|
||||
struct coresight_node *to)
|
||||
{
|
||||
u32 type;
|
||||
struct coresight_device *csdev, *parent, *child;
|
||||
struct coresight_node *nd;
|
||||
|
||||
if (!nd)
|
||||
nd = list_first_entry(&path->path_list, struct coresight_node, link);
|
||||
if (!coresight_path_nodes_in_order(path, from, to))
|
||||
return;
|
||||
|
||||
nd = from;
|
||||
list_for_each_entry_from(nd, &path->path_list, link) {
|
||||
csdev = nd->csdev;
|
||||
type = csdev->type;
|
||||
|
|
@ -534,12 +574,18 @@ static void coresight_disable_path_from(struct coresight_path *path,
|
|||
|
||||
/* Disable all helpers adjacent along the path last */
|
||||
coresight_disable_helpers(csdev, path);
|
||||
|
||||
/* Iterate up to and including @to */
|
||||
if (nd == to)
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
void coresight_disable_path(struct coresight_path *path)
|
||||
{
|
||||
coresight_disable_path_from(path, NULL);
|
||||
coresight_disable_path_from_to(path,
|
||||
coresight_path_first_node(path),
|
||||
coresight_path_last_node(path));
|
||||
}
|
||||
EXPORT_SYMBOL_GPL(coresight_disable_path);
|
||||
|
||||
|
|
@ -572,16 +618,21 @@ static int coresight_enable_helpers(struct coresight_device *csdev,
|
|||
return ret;
|
||||
}
|
||||
|
||||
int coresight_enable_path(struct coresight_path *path, enum cs_mode mode)
|
||||
static int coresight_enable_path_from_to(struct coresight_path *path,
|
||||
enum cs_mode mode,
|
||||
struct coresight_node *from,
|
||||
struct coresight_node *to)
|
||||
{
|
||||
int ret = 0;
|
||||
u32 type;
|
||||
struct coresight_node *nd;
|
||||
struct coresight_device *csdev, *parent, *child;
|
||||
struct coresight_device *source;
|
||||
|
||||
source = coresight_get_source(path);
|
||||
list_for_each_entry_reverse(nd, &path->path_list, link) {
|
||||
if (!coresight_path_nodes_in_order(path, from, to))
|
||||
return -EINVAL;
|
||||
|
||||
nd = to;
|
||||
list_for_each_entry_from_reverse(nd, &path->path_list, link) {
|
||||
csdev = nd->csdev;
|
||||
type = csdev->type;
|
||||
|
||||
|
|
@ -620,7 +671,8 @@ int coresight_enable_path(struct coresight_path *path, enum cs_mode mode)
|
|||
case CORESIGHT_DEV_TYPE_LINK:
|
||||
parent = list_prev_entry(nd, link)->csdev;
|
||||
child = list_next_entry(nd, link)->csdev;
|
||||
ret = coresight_enable_link(csdev, parent, child, source);
|
||||
ret = coresight_enable_link(csdev, parent, child,
|
||||
coresight_get_source(path));
|
||||
if (ret)
|
||||
goto err_disable_helpers;
|
||||
break;
|
||||
|
|
@ -628,6 +680,10 @@ int coresight_enable_path(struct coresight_path *path, enum cs_mode mode)
|
|||
ret = -EINVAL;
|
||||
goto err_disable_helpers;
|
||||
}
|
||||
|
||||
/* Iterate down to and including @from */
|
||||
if (nd == from)
|
||||
break;
|
||||
}
|
||||
|
||||
out:
|
||||
|
|
@ -635,12 +691,23 @@ int coresight_enable_path(struct coresight_path *path, enum cs_mode mode)
|
|||
err_disable_helpers:
|
||||
coresight_disable_helpers(csdev, path);
|
||||
err_disable_path:
|
||||
/* No device is actually enabled */
|
||||
if (nd == to)
|
||||
goto out;
|
||||
|
||||
/* Fetch the previous node, the last successfully enabled one */
|
||||
nd = list_next_entry(nd, link);
|
||||
coresight_disable_path_from(path, nd);
|
||||
coresight_disable_path_from_to(path, nd, to);
|
||||
goto out;
|
||||
}
|
||||
|
||||
int coresight_enable_path(struct coresight_path *path, enum cs_mode mode)
|
||||
{
|
||||
return coresight_enable_path_from_to(path, mode,
|
||||
coresight_path_first_node(path),
|
||||
coresight_path_last_node(path));
|
||||
}
|
||||
|
||||
struct coresight_device *coresight_get_sink(struct coresight_path *path)
|
||||
{
|
||||
struct coresight_device *csdev;
|
||||
|
|
|
|||
Loading…
Reference in New Issue
Block a user