Lines Matching +full:dt +full:- +full:node

1 // SPDX-License-Identifier: GPL-2.0
5 * Copyright (c) 2017-2019, Linaro Ltd.
14 #include <linux/interconnect-provider.h>
39 seq_printf(s, "%-42s %12u %12u\n", in icc_summary_show_one()
40 n->name, n->avg_bw, n->peak_bw); in icc_summary_show_one()
47 seq_puts(s, " node tag avg peak\n"); in icc_summary_show()
48 seq_puts(s, "--------------------------------------------------------------------\n"); in icc_summary_show()
55 list_for_each_entry(n, &provider->nodes, node_list) { in icc_summary_show()
59 hlist_for_each_entry(r, &n->req_list, req_node) { in icc_summary_show()
62 if (!r->dev) in icc_summary_show()
65 if (r->enabled) { in icc_summary_show()
66 avg_bw = r->avg_bw; in icc_summary_show()
67 peak_bw = r->peak_bw; in icc_summary_show()
70 seq_printf(s, " %-27s %12u %12u %12u\n", in icc_summary_show()
71 dev_name(r->dev), r->tag, avg_bw, peak_bw); in icc_summary_show()
85 seq_printf(s, "%s\"%d:%s\" -> \"%d:%s\"\n", in icc_graph_show_link()
87 n->id, n->name, m->id, m->name); in icc_graph_show_link()
93 n->id, n->name, n->id, n->name); in icc_graph_show_node()
94 seq_printf(s, "\n\t\t\t|avg_bw=%ukBps", n->avg_bw); in icc_graph_show_node()
95 seq_printf(s, "\n\t\t\t|peak_bw=%ukBps", n->peak_bw); in icc_graph_show_node()
113 if (provider->dev) in icc_graph_show()
115 dev_name(provider->dev)); in icc_graph_show()
118 list_for_each_entry(n, &provider->nodes, node_list) in icc_graph_show()
122 list_for_each_entry(n, &provider->nodes, node_list) in icc_graph_show()
123 for (i = 0; i < n->num_links; ++i) in icc_graph_show()
124 if (n->provider == n->links[i]->provider) in icc_graph_show()
126 n->links[i]); in icc_graph_show()
133 list_for_each_entry(n, &provider->nodes, node_list) in icc_graph_show()
134 for (i = 0; i < n->num_links; ++i) in icc_graph_show()
135 if (n->provider != n->links[i]->provider) in icc_graph_show()
137 n->links[i]); in icc_graph_show()
154 struct icc_node *node = dst; in path_init() local
160 return ERR_PTR(-ENOMEM); in path_init()
162 path->num_nodes = num_nodes; in path_init()
164 for (i = num_nodes - 1; i >= 0; i--) { in path_init()
165 node->provider->users++; in path_init()
166 hlist_add_head(&path->reqs[i].req_node, &node->req_list); in path_init()
167 path->reqs[i].node = node; in path_init()
168 path->reqs[i].dev = dev; in path_init()
169 path->reqs[i].enabled = true; in path_init()
170 /* reference to previous node was saved during path traversal */ in path_init()
171 node = node->reverse; in path_init()
180 struct icc_path *path = ERR_PTR(-EPROBE_DEFER); in path_find()
181 struct icc_node *n, *node = NULL; in path_find() local
192 list_add(&src->search_list, &traverse_list); in path_find()
193 src->reverse = NULL; in path_find()
196 list_for_each_entry_safe(node, n, &traverse_list, search_list) { in path_find()
197 if (node == dst) { in path_find()
203 for (i = 0; i < node->num_links; i++) { in path_find()
204 struct icc_node *tmp = node->links[i]; in path_find()
207 path = ERR_PTR(-ENOENT); in path_find()
211 if (tmp->is_traversed) in path_find()
214 tmp->is_traversed = true; in path_find()
215 tmp->reverse = node; in path_find()
216 list_add_tail(&tmp->search_list, &edge_list); in path_find()
235 n->is_traversed = false; in path_find()
245 * bandwidth requirements from each consumer are aggregated at each node.
250 static int aggregate_requests(struct icc_node *node) in aggregate_requests() argument
252 struct icc_provider *p = node->provider; in aggregate_requests()
256 node->avg_bw = 0; in aggregate_requests()
257 node->peak_bw = 0; in aggregate_requests()
259 if (p->pre_aggregate) in aggregate_requests()
260 p->pre_aggregate(node); in aggregate_requests()
262 hlist_for_each_entry(r, &node->req_list, req_node) { in aggregate_requests()
263 if (r->enabled) { in aggregate_requests()
264 avg_bw = r->avg_bw; in aggregate_requests()
265 peak_bw = r->peak_bw; in aggregate_requests()
270 p->aggregate(node, r->tag, avg_bw, peak_bw, in aggregate_requests()
271 &node->avg_bw, &node->peak_bw); in aggregate_requests()
275 node->avg_bw = max(node->avg_bw, node->init_avg); in aggregate_requests()
276 node->peak_bw = max(node->peak_bw, node->init_peak); in aggregate_requests()
287 int ret = -EINVAL; in apply_constraints()
290 for (i = 0; i < path->num_nodes; i++) { in apply_constraints()
291 next = path->reqs[i].node; in apply_constraints()
292 p = next->provider; in apply_constraints()
294 /* both endpoints should be valid master-slave pairs */ in apply_constraints()
295 if (!prev || (p != prev->provider && !p->inter_set)) { in apply_constraints()
301 ret = p->set(prev, next); in apply_constraints()
311 int icc_std_aggregate(struct icc_node *node, u32 tag, u32 avg_bw, in icc_std_aggregate() argument
321 /* of_icc_xlate_onecell() - Translate function using a single index.
322 * @spec: OF phandle args to map into an interconnect node.
326 * interconnect providers that have one device tree node and provide
335 unsigned int idx = spec->args[0]; in of_icc_xlate_onecell()
337 if (idx >= icc_data->num_nodes) { in of_icc_xlate_onecell()
339 return ERR_PTR(-EINVAL); in of_icc_xlate_onecell()
342 return icc_data->nodes[idx]; in of_icc_xlate_onecell()
347 * of_icc_get_from_provider() - Look-up interconnect node
348 * @spec: OF phandle args to use for look-up
350 * Looks for interconnect provider under the node specified by @spec and if
351 * found, uses xlate function of the provider to map phandle args to node.
358 struct icc_node *node = ERR_PTR(-EPROBE_DEFER); in of_icc_get_from_provider() local
363 return ERR_PTR(-EINVAL); in of_icc_get_from_provider()
367 if (provider->dev->of_node == spec->np) { in of_icc_get_from_provider()
368 if (provider->xlate_extended) { in of_icc_get_from_provider()
369 data = provider->xlate_extended(spec, provider->data); in of_icc_get_from_provider()
371 node = data->node; in of_icc_get_from_provider()
375 node = provider->xlate(spec, provider->data); in of_icc_get_from_provider()
376 if (!IS_ERR(node)) in of_icc_get_from_provider()
383 if (IS_ERR(node)) in of_icc_get_from_provider()
384 return ERR_CAST(node); in of_icc_get_from_provider()
389 return ERR_PTR(-ENOMEM); in of_icc_get_from_provider()
390 data->node = node; in of_icc_get_from_provider()
408 return ERR_PTR(-ENOMEM); in devm_of_icc_get()
423 * of_icc_get_by_index() - get a path handle from a DT node based on index
435 * when the API is disabled or the "interconnects" DT property is missing.
445 if (!dev || !dev->of_node) in of_icc_get_by_index()
446 return ERR_PTR(-ENODEV); in of_icc_get_by_index()
448 np = dev->of_node; in of_icc_get_by_index()
451 * When the consumer DT node do not have "interconnects" property in of_icc_get_by_index()
460 * without breaking DT compatibility. in of_icc_get_by_index()
463 "#interconnect-cells", idx * 2, in of_icc_get_by_index()
471 "#interconnect-cells", idx * 2 + 1, in of_icc_get_by_index()
481 dev_err_probe(dev, PTR_ERR(src_data), "error finding src node\n"); in of_icc_get_by_index()
488 dev_err_probe(dev, PTR_ERR(dst_data), "error finding dst node\n"); in of_icc_get_by_index()
494 path = path_find(dev, src_data->node, dst_data->node); in of_icc_get_by_index()
501 if (src_data->tag && src_data->tag == dst_data->tag) in of_icc_get_by_index()
502 icc_set_tag(path, src_data->tag); in of_icc_get_by_index()
504 path->name = kasprintf(GFP_KERNEL, "%s-%s", in of_icc_get_by_index()
505 src_data->node->name, dst_data->node->name); in of_icc_get_by_index()
506 if (!path->name) { in of_icc_get_by_index()
508 path = ERR_PTR(-ENOMEM); in of_icc_get_by_index()
519 * of_icc_get() - get a path handle from a DT node based on name
531 * when the API is disabled or the "interconnects" DT property is missing.
538 if (!dev || !dev->of_node) in of_icc_get()
539 return ERR_PTR(-ENODEV); in of_icc_get()
541 np = dev->of_node; in of_icc_get()
544 * When the consumer DT node do not have "interconnects" property in of_icc_get()
553 * without breaking DT compatibility. in of_icc_get()
556 idx = of_property_match_string(np, "interconnect-names", name); in of_icc_get()
566 * icc_set_tag() - set an optional tag on a path
582 for (i = 0; i < path->num_nodes; i++) in icc_set_tag()
583 path->reqs[i].tag = tag; in icc_set_tag()
590 * icc_get_name() - Get name of the icc path
603 return path->name; in icc_get_name()
608 * icc_set_bw() - set bandwidth constraints on an interconnect path
615 * The requests are aggregated and each node is updated accordingly. The entire
617 * The @path can be NULL when the "interconnects" DT properties is missing,
624 struct icc_node *node; in icc_set_bw() local
632 if (WARN_ON(IS_ERR(path) || !path->num_nodes)) in icc_set_bw()
633 return -EINVAL; in icc_set_bw()
637 old_avg = path->reqs[0].avg_bw; in icc_set_bw()
638 old_peak = path->reqs[0].peak_bw; in icc_set_bw()
640 for (i = 0; i < path->num_nodes; i++) { in icc_set_bw()
641 node = path->reqs[i].node; in icc_set_bw()
644 path->reqs[i].avg_bw = avg_bw; in icc_set_bw()
645 path->reqs[i].peak_bw = peak_bw; in icc_set_bw()
647 /* aggregate requests for this node */ in icc_set_bw()
648 aggregate_requests(node); in icc_set_bw()
650 trace_icc_set_bw(path, node, i, avg_bw, peak_bw); in icc_set_bw()
658 for (i = 0; i < path->num_nodes; i++) { in icc_set_bw()
659 node = path->reqs[i].node; in icc_set_bw()
660 path->reqs[i].avg_bw = old_avg; in icc_set_bw()
661 path->reqs[i].peak_bw = old_peak; in icc_set_bw()
662 aggregate_requests(node); in icc_set_bw()
682 if (WARN_ON(IS_ERR(path) || !path->num_nodes)) in __icc_enable()
683 return -EINVAL; in __icc_enable()
687 for (i = 0; i < path->num_nodes; i++) in __icc_enable()
688 path->reqs[i].enabled = enable; in __icc_enable()
692 return icc_set_bw(path, path->reqs[0].avg_bw, in __icc_enable()
693 path->reqs[0].peak_bw); in __icc_enable()
709 * icc_get() - return a handle for path between two endpoints
727 struct icc_path *path = ERR_PTR(-EPROBE_DEFER); in icc_get()
745 path->name = kasprintf(GFP_KERNEL, "%s-%s", src->name, dst->name); in icc_get()
746 if (!path->name) { in icc_get()
748 path = ERR_PTR(-ENOMEM); in icc_get()
757 * icc_put() - release the reference to the icc_path
761 * no longer needed. The constraints will be re-aggregated.
765 struct icc_node *node; in icc_put() local
777 for (i = 0; i < path->num_nodes; i++) { in icc_put()
778 node = path->reqs[i].node; in icc_put()
779 hlist_del(&path->reqs[i].req_node); in icc_put()
780 if (!WARN_ON(!node->provider->users)) in icc_put()
781 node->provider->users--; in icc_put()
785 kfree_const(path->name); in icc_put()
792 struct icc_node *node; in icc_node_create_nolock() local
794 /* check if node already exists */ in icc_node_create_nolock()
795 node = node_find(id); in icc_node_create_nolock()
796 if (node) in icc_node_create_nolock()
797 return node; in icc_node_create_nolock()
799 node = kzalloc(sizeof(*node), GFP_KERNEL); in icc_node_create_nolock()
800 if (!node) in icc_node_create_nolock()
801 return ERR_PTR(-ENOMEM); in icc_node_create_nolock()
803 id = idr_alloc(&icc_idr, node, id, id + 1, GFP_KERNEL); in icc_node_create_nolock()
806 kfree(node); in icc_node_create_nolock()
810 node->id = id; in icc_node_create_nolock()
812 return node; in icc_node_create_nolock()
816 * icc_node_create() - create a node
817 * @id: node id
823 struct icc_node *node; in icc_node_create() local
827 node = icc_node_create_nolock(id); in icc_node_create()
831 return node; in icc_node_create()
836 * icc_node_destroy() - destroy a node
837 * @id: node id
841 struct icc_node *node; in icc_node_destroy() local
845 node = node_find(id); in icc_node_destroy()
846 if (node) { in icc_node_destroy()
847 idr_remove(&icc_idr, node->id); in icc_node_destroy()
848 WARN_ON(!hlist_empty(&node->req_list)); in icc_node_destroy()
853 kfree(node); in icc_node_destroy()
858 * icc_link_create() - create a link between two nodes
859 * @node: source node id
860 * @dst_id: destination node id
863 * interconnect providers and the @dst_id node might not exist (if the
864 * provider driver has not probed yet). So just create the @dst_id node
865 * and when the actual provider driver is probed, the rest of the node
870 int icc_link_create(struct icc_node *node, const int dst_id) in icc_link_create() argument
876 if (!node->provider) in icc_link_create()
877 return -EINVAL; in icc_link_create()
891 new = krealloc(node->links, in icc_link_create()
892 (node->num_links + 1) * sizeof(*node->links), in icc_link_create()
895 ret = -ENOMEM; in icc_link_create()
899 node->links = new; in icc_link_create()
900 node->links[node->num_links++] = dst; in icc_link_create()
910 * icc_link_destroy() - destroy a link between two nodes
911 * @src: pointer to source node
912 * @dst: pointer to destination node
923 return -EINVAL; in icc_link_destroy()
926 return -EINVAL; in icc_link_destroy()
930 for (slot = 0; slot < src->num_links; slot++) in icc_link_destroy()
931 if (src->links[slot] == dst) in icc_link_destroy()
934 if (WARN_ON(slot == src->num_links)) { in icc_link_destroy()
935 ret = -ENXIO; in icc_link_destroy()
939 src->links[slot] = src->links[--src->num_links]; in icc_link_destroy()
941 new = krealloc(src->links, src->num_links * sizeof(*src->links), in icc_link_destroy()
944 src->links = new; in icc_link_destroy()
946 ret = -ENOMEM; in icc_link_destroy()
956 * icc_node_add() - add interconnect node to interconnect provider
957 * @node: pointer to the interconnect node
960 void icc_node_add(struct icc_node *node, struct icc_provider *provider) in icc_node_add() argument
962 if (WARN_ON(node->provider)) in icc_node_add()
967 node->provider = provider; in icc_node_add()
968 list_add_tail(&node->node_list, &provider->nodes); in icc_node_add()
971 if (provider->get_bw) { in icc_node_add()
972 provider->get_bw(node, &node->init_avg, &node->init_peak); in icc_node_add()
974 node->init_avg = INT_MAX; in icc_node_add()
975 node->init_peak = INT_MAX; in icc_node_add()
977 node->avg_bw = node->init_avg; in icc_node_add()
978 node->peak_bw = node->init_peak; in icc_node_add()
980 if (provider->pre_aggregate) in icc_node_add()
981 provider->pre_aggregate(node); in icc_node_add()
983 if (provider->aggregate) in icc_node_add()
984 provider->aggregate(node, 0, node->init_avg, node->init_peak, in icc_node_add()
985 &node->avg_bw, &node->peak_bw); in icc_node_add()
987 provider->set(node, node); in icc_node_add()
988 node->avg_bw = 0; in icc_node_add()
989 node->peak_bw = 0; in icc_node_add()
996 * icc_node_del() - delete interconnect node from interconnect provider
997 * @node: pointer to the interconnect node
999 void icc_node_del(struct icc_node *node) in icc_node_del() argument
1003 list_del(&node->node_list); in icc_node_del()
1010 * icc_nodes_remove() - remove all previously added nodes from provider
1020 return -EINVAL; in icc_nodes_remove()
1022 list_for_each_entry_safe_reverse(n, tmp, &provider->nodes, node_list) { in icc_nodes_remove()
1024 icc_node_destroy(n->id); in icc_nodes_remove()
1032 * icc_provider_add() - add a new interconnect provider
1039 if (WARN_ON(!provider->set)) in icc_provider_add()
1040 return -EINVAL; in icc_provider_add()
1041 if (WARN_ON(!provider->xlate && !provider->xlate_extended)) in icc_provider_add()
1042 return -EINVAL; in icc_provider_add()
1046 INIT_LIST_HEAD(&provider->nodes); in icc_provider_add()
1047 list_add_tail(&provider->provider_list, &icc_providers); in icc_provider_add()
1051 dev_dbg(provider->dev, "interconnect provider added to topology\n"); in icc_provider_add()
1058 * icc_provider_del() - delete previously added interconnect provider
1064 if (provider->users) { in icc_provider_del()
1066 provider->users); in icc_provider_del()
1071 if (!list_empty(&provider->nodes)) { in icc_provider_del()
1077 list_del(&provider->provider_list); in icc_provider_del()
1087 { .compatible = "qcom,sc7180-ipa-virt" }, in of_count_icc_providers()
1088 { .compatible = "qcom,sdx55-ipa-virt" }, in of_count_icc_providers()
1093 if (of_property_read_bool(child, "#interconnect-cells") && in of_count_icc_providers()
1116 dev_dbg(p->dev, "interconnect provider is in synced state\n"); in icc_sync_state()
1117 list_for_each_entry(n, &p->nodes, node_list) { in icc_sync_state()
1118 if (n->init_avg || n->init_peak) { in icc_sync_state()
1119 n->init_avg = 0; in icc_sync_state()
1120 n->init_peak = 0; in icc_sync_state()
1122 p->set(n, n); in icc_sync_state()