Skip to content

Commit 1521e22

Browse files
author
Georgi Djakov
committed
interconnect: Introduce xlate_extended() callback
Currently there is the xlate() callback, which is used by providers for mapping the nodes from phandle arguments. That's fine for simple mappings, but the phandle arguments could contain an additional data, such as tag information. Let's create another callback xlate_extended() for the cases where providers want also populate the path tag data. Tested-by: Sibi Sankar <sibis@codeaurora.org> Reviewed-by: Sibi Sankar <sibis@codeaurora.org> Reviewed-by: Matthias Kaehlcke <mka@chromium.org> Tested-by: Matthias Kaehlcke <mka@chromium.org> Link: https://lore.kernel.org/r/20200903133134.17201-2-georgi.djakov@linaro.org Signed-off-by: Georgi Djakov <georgi.djakov@linaro.org>
1 parent cb30e02 commit 1521e22

2 files changed

Lines changed: 65 additions & 25 deletions

File tree

drivers/interconnect/core.c

Lines changed: 50 additions & 23 deletions
Original file line numberDiff line numberDiff line change
@@ -342,27 +342,47 @@ EXPORT_SYMBOL_GPL(of_icc_xlate_onecell);
342342
* Looks for interconnect provider under the node specified by @spec and if
343343
* found, uses xlate function of the provider to map phandle args to node.
344344
*
345-
* Returns a valid pointer to struct icc_node on success or ERR_PTR()
345+
* Returns a valid pointer to struct icc_node_data on success or ERR_PTR()
346346
* on failure.
347347
*/
348-
struct icc_node *of_icc_get_from_provider(struct of_phandle_args *spec)
348+
struct icc_node_data *of_icc_get_from_provider(struct of_phandle_args *spec)
349349
{
350350
struct icc_node *node = ERR_PTR(-EPROBE_DEFER);
351+
struct icc_node_data *data = NULL;
351352
struct icc_provider *provider;
352353

353354
if (!spec)
354355
return ERR_PTR(-EINVAL);
355356

356357
mutex_lock(&icc_lock);
357358
list_for_each_entry(provider, &icc_providers, provider_list) {
358-
if (provider->dev->of_node == spec->np)
359-
node = provider->xlate(spec, provider->data);
360-
if (!IS_ERR(node))
361-
break;
359+
if (provider->dev->of_node == spec->np) {
360+
if (provider->xlate_extended) {
361+
data = provider->xlate_extended(spec, provider->data);
362+
if (!IS_ERR(data)) {
363+
node = data->node;
364+
break;
365+
}
366+
} else {
367+
node = provider->xlate(spec, provider->data);
368+
if (!IS_ERR(node))
369+
break;
370+
}
371+
}
362372
}
363373
mutex_unlock(&icc_lock);
364374

365-
return node;
375+
if (IS_ERR(node))
376+
return ERR_CAST(node);
377+
378+
if (!data) {
379+
data = kzalloc(sizeof(*data), GFP_KERNEL);
380+
if (!data)
381+
return ERR_PTR(-ENOMEM);
382+
data->node = node;
383+
}
384+
385+
return data;
366386
}
367387
EXPORT_SYMBOL_GPL(of_icc_get_from_provider);
368388

@@ -409,7 +429,7 @@ EXPORT_SYMBOL_GPL(devm_of_icc_get);
409429
struct icc_path *of_icc_get_by_index(struct device *dev, int idx)
410430
{
411431
struct icc_path *path;
412-
struct icc_node *src_node, *dst_node;
432+
struct icc_node_data *src_data, *dst_data;
413433
struct device_node *np;
414434
struct of_phandle_args src_args, dst_args;
415435
int ret;
@@ -447,39 +467,46 @@ struct icc_path *of_icc_get_by_index(struct device *dev, int idx)
447467

448468
of_node_put(dst_args.np);
449469

450-
src_node = of_icc_get_from_provider(&src_args);
470+
src_data = of_icc_get_from_provider(&src_args);
451471

452-
if (IS_ERR(src_node)) {
453-
if (PTR_ERR(src_node) != -EPROBE_DEFER)
472+
if (IS_ERR(src_data)) {
473+
if (PTR_ERR(src_data) != -EPROBE_DEFER)
454474
dev_err(dev, "error finding src node: %ld\n",
455-
PTR_ERR(src_node));
456-
return ERR_CAST(src_node);
475+
PTR_ERR(src_data));
476+
return ERR_CAST(src_data);
457477
}
458478

459-
dst_node = of_icc_get_from_provider(&dst_args);
479+
dst_data = of_icc_get_from_provider(&dst_args);
460480

461-
if (IS_ERR(dst_node)) {
462-
if (PTR_ERR(dst_node) != -EPROBE_DEFER)
481+
if (IS_ERR(dst_data)) {
482+
if (PTR_ERR(dst_data) != -EPROBE_DEFER)
463483
dev_err(dev, "error finding dst node: %ld\n",
464-
PTR_ERR(dst_node));
465-
return ERR_CAST(dst_node);
484+
PTR_ERR(dst_data));
485+
kfree(src_data);
486+
return ERR_CAST(dst_data);
466487
}
467488

468489
mutex_lock(&icc_lock);
469-
path = path_find(dev, src_node, dst_node);
490+
path = path_find(dev, src_data->node, dst_data->node);
470491
mutex_unlock(&icc_lock);
471492
if (IS_ERR(path)) {
472493
dev_err(dev, "%s: invalid path=%ld\n", __func__, PTR_ERR(path));
473-
return path;
494+
goto free_icc_data;
474495
}
475496

497+
if (src_data->tag && src_data->tag == dst_data->tag)
498+
icc_set_tag(path, src_data->tag);
499+
476500
path->name = kasprintf(GFP_KERNEL, "%s-%s",
477-
src_node->name, dst_node->name);
501+
src_data->node->name, dst_data->node->name);
478502
if (!path->name) {
479503
kfree(path);
480-
return ERR_PTR(-ENOMEM);
504+
path = ERR_PTR(-ENOMEM);
481505
}
482506

507+
free_icc_data:
508+
kfree(src_data);
509+
kfree(dst_data);
483510
return path;
484511
}
485512
EXPORT_SYMBOL_GPL(of_icc_get_by_index);
@@ -981,7 +1008,7 @@ int icc_provider_add(struct icc_provider *provider)
9811008
{
9821009
if (WARN_ON(!provider->set))
9831010
return -EINVAL;
984-
if (WARN_ON(!provider->xlate))
1011+
if (WARN_ON(!provider->xlate && !provider->xlate_extended))
9851012
return -EINVAL;
9861013

9871014
mutex_lock(&icc_lock);

include/linux/interconnect-provider.h

Lines changed: 15 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -14,6 +14,17 @@
1414
struct icc_node;
1515
struct of_phandle_args;
1616

17+
/**
18+
* struct icc_node_data - icc node data
19+
*
20+
* @node: icc node
21+
* @tag: tag
22+
*/
23+
struct icc_node_data {
24+
struct icc_node *node;
25+
u32 tag;
26+
};
27+
1728
/**
1829
* struct icc_onecell_data - driver data for onecell interconnect providers
1930
*
@@ -39,6 +50,7 @@ struct icc_node *of_icc_xlate_onecell(struct of_phandle_args *spec,
3950
* @pre_aggregate: pointer to device specific function that is called
4051
* before the aggregation begins (optional)
4152
* @xlate: provider-specific callback for mapping nodes from phandle arguments
53+
* @xlate_extended: vendor-specific callback for mapping node data from phandle arguments
4254
* @dev: the device this interconnect provider belongs to
4355
* @users: count of active users
4456
* @inter_set: whether inter-provider pairs will be configured with @set
@@ -52,6 +64,7 @@ struct icc_provider {
5264
u32 peak_bw, u32 *agg_avg, u32 *agg_peak);
5365
void (*pre_aggregate)(struct icc_node *node);
5466
struct icc_node* (*xlate)(struct of_phandle_args *spec, void *data);
67+
struct icc_node_data* (*xlate_extended)(struct of_phandle_args *spec, void *data);
5568
struct device *dev;
5669
int users;
5770
bool inter_set;
@@ -105,7 +118,7 @@ void icc_node_del(struct icc_node *node);
105118
int icc_nodes_remove(struct icc_provider *provider);
106119
int icc_provider_add(struct icc_provider *provider);
107120
int icc_provider_del(struct icc_provider *provider);
108-
struct icc_node *of_icc_get_from_provider(struct of_phandle_args *spec);
121+
struct icc_node_data *of_icc_get_from_provider(struct of_phandle_args *spec);
109122

110123
#else
111124

@@ -157,7 +170,7 @@ static inline int icc_provider_del(struct icc_provider *provider)
157170
return -ENOTSUPP;
158171
}
159172

160-
static inline struct icc_node *of_icc_get_from_provider(struct of_phandle_args *spec)
173+
static inline struct icc_node_data *of_icc_get_from_provider(struct of_phandle_args *spec)
161174
{
162175
return ERR_PTR(-ENOTSUPP);
163176
}

0 commit comments

Comments
 (0)