1 // SPDX-License-Identifier: GPL-2.0 2 /* 3 * Interconnect framework core driver 4 * 5 * Copyright (c) 2017-2019, Linaro Ltd. 6 * Author: Georgi Djakov <georgi.djakov@linaro.org> 7 */ 8 9 #include <linux/debugfs.h> 10 #include <linux/device.h> 11 #include <linux/idr.h> 12 #include <linux/init.h> 13 #include <linux/interconnect.h> 14 #include <linux/interconnect-provider.h> 15 #include <linux/list.h> 16 #include <linux/module.h> 17 #include <linux/mutex.h> 18 #include <linux/slab.h> 19 #include <linux/of.h> 20 #include <linux/overflow.h> 21 22 #include "internal.h" 23 24 #define CREATE_TRACE_POINTS 25 #include "trace.h" 26 27 static DEFINE_IDR(icc_idr); 28 static LIST_HEAD(icc_providers); 29 static DEFINE_MUTEX(icc_lock); 30 static struct dentry *icc_debugfs_dir; 31 32 static void icc_summary_show_one(struct seq_file *s, struct icc_node *n) 33 { 34 if (!n) 35 return; 36 37 seq_printf(s, "%-42s %12u %12u\n", 38 n->name, n->avg_bw, n->peak_bw); 39 } 40 41 static int icc_summary_show(struct seq_file *s, void *data) 42 { 43 struct icc_provider *provider; 44 45 seq_puts(s, " node tag avg peak\n"); 46 seq_puts(s, "--------------------------------------------------------------------\n"); 47 48 mutex_lock(&icc_lock); 49 50 list_for_each_entry(provider, &icc_providers, provider_list) { 51 struct icc_node *n; 52 53 list_for_each_entry(n, &provider->nodes, node_list) { 54 struct icc_req *r; 55 56 icc_summary_show_one(s, n); 57 hlist_for_each_entry(r, &n->req_list, req_node) { 58 if (!r->dev) 59 continue; 60 61 seq_printf(s, " %-27s %12u %12u %12u\n", 62 dev_name(r->dev), r->tag, r->avg_bw, 63 r->peak_bw); 64 } 65 } 66 } 67 68 mutex_unlock(&icc_lock); 69 70 return 0; 71 } 72 DEFINE_SHOW_ATTRIBUTE(icc_summary); 73 74 static void icc_graph_show_link(struct seq_file *s, int level, 75 struct icc_node *n, struct icc_node *m) 76 { 77 seq_printf(s, "%s\"%d:%s\" -> \"%d:%s\"\n", 78 level == 2 ? "\t\t" : "\t", 79 n->id, n->name, m->id, m->name); 80 } 81 82 static void icc_graph_show_node(struct seq_file *s, struct icc_node *n) 83 { 84 seq_printf(s, "\t\t\"%d:%s\" [label=\"%d:%s", 85 n->id, n->name, n->id, n->name); 86 seq_printf(s, "\n\t\t\t|avg_bw=%ukBps", n->avg_bw); 87 seq_printf(s, "\n\t\t\t|peak_bw=%ukBps", n->peak_bw); 88 seq_puts(s, "\"]\n"); 89 } 90 91 static int icc_graph_show(struct seq_file *s, void *data) 92 { 93 struct icc_provider *provider; 94 struct icc_node *n; 95 int cluster_index = 0; 96 int i; 97 98 seq_puts(s, "digraph {\n\trankdir = LR\n\tnode [shape = record]\n"); 99 mutex_lock(&icc_lock); 100 101 /* draw providers as cluster subgraphs */ 102 cluster_index = 0; 103 list_for_each_entry(provider, &icc_providers, provider_list) { 104 seq_printf(s, "\tsubgraph cluster_%d {\n", ++cluster_index); 105 if (provider->dev) 106 seq_printf(s, "\t\tlabel = \"%s\"\n", 107 dev_name(provider->dev)); 108 109 /* draw nodes */ 110 list_for_each_entry(n, &provider->nodes, node_list) 111 icc_graph_show_node(s, n); 112 113 /* draw internal links */ 114 list_for_each_entry(n, &provider->nodes, node_list) 115 for (i = 0; i < n->num_links; ++i) 116 if (n->provider == n->links[i]->provider) 117 icc_graph_show_link(s, 2, n, 118 n->links[i]); 119 120 seq_puts(s, "\t}\n"); 121 } 122 123 /* draw external links */ 124 list_for_each_entry(provider, &icc_providers, provider_list) 125 list_for_each_entry(n, &provider->nodes, node_list) 126 for (i = 0; i < n->num_links; ++i) 127 if (n->provider != n->links[i]->provider) 128 icc_graph_show_link(s, 1, n, 129 n->links[i]); 130 131 mutex_unlock(&icc_lock); 132 seq_puts(s, "}"); 133 134 return 0; 135 } 136 DEFINE_SHOW_ATTRIBUTE(icc_graph); 137 138 static struct icc_node *node_find(const int id) 139 { 140 return idr_find(&icc_idr, id); 141 } 142 143 static struct icc_path *path_init(struct device *dev, struct icc_node *dst, 144 ssize_t num_nodes) 145 { 146 struct icc_node *node = dst; 147 struct icc_path *path; 148 int i; 149 150 path = kzalloc(struct_size(path, reqs, num_nodes), GFP_KERNEL); 151 if (!path) 152 return ERR_PTR(-ENOMEM); 153 154 path->num_nodes = num_nodes; 155 156 for (i = num_nodes - 1; i >= 0; i--) { 157 node->provider->users++; 158 hlist_add_head(&path->reqs[i].req_node, &node->req_list); 159 path->reqs[i].node = node; 160 path->reqs[i].dev = dev; 161 path->reqs[i].enabled = true; 162 /* reference to previous node was saved during path traversal */ 163 node = node->reverse; 164 } 165 166 return path; 167 } 168 169 static struct icc_path *path_find(struct device *dev, struct icc_node *src, 170 struct icc_node *dst) 171 { 172 struct icc_path *path = ERR_PTR(-EPROBE_DEFER); 173 struct icc_node *n, *node = NULL; 174 struct list_head traverse_list; 175 struct list_head edge_list; 176 struct list_head visited_list; 177 size_t i, depth = 1; 178 bool found = false; 179 180 INIT_LIST_HEAD(&traverse_list); 181 INIT_LIST_HEAD(&edge_list); 182 INIT_LIST_HEAD(&visited_list); 183 184 list_add(&src->search_list, &traverse_list); 185 src->reverse = NULL; 186 187 do { 188 list_for_each_entry_safe(node, n, &traverse_list, search_list) { 189 if (node == dst) { 190 found = true; 191 list_splice_init(&edge_list, &visited_list); 192 list_splice_init(&traverse_list, &visited_list); 193 break; 194 } 195 for (i = 0; i < node->num_links; i++) { 196 struct icc_node *tmp = node->links[i]; 197 198 if (!tmp) { 199 path = ERR_PTR(-ENOENT); 200 goto out; 201 } 202 203 if (tmp->is_traversed) 204 continue; 205 206 tmp->is_traversed = true; 207 tmp->reverse = node; 208 list_add_tail(&tmp->search_list, &edge_list); 209 } 210 } 211 212 if (found) 213 break; 214 215 list_splice_init(&traverse_list, &visited_list); 216 list_splice_init(&edge_list, &traverse_list); 217 218 /* count the hops including the source */ 219 depth++; 220 221 } while (!list_empty(&traverse_list)); 222 223 out: 224 225 /* reset the traversed state */ 226 list_for_each_entry_reverse(n, &visited_list, search_list) 227 n->is_traversed = false; 228 229 if (found) 230 path = path_init(dev, dst, depth); 231 232 return path; 233 } 234 235 /* 236 * We want the path to honor all bandwidth requests, so the average and peak 237 * bandwidth requirements from each consumer are aggregated at each node. 238 * The aggregation is platform specific, so each platform can customize it by 239 * implementing its own aggregate() function. 240 */ 241 242 static int aggregate_requests(struct icc_node *node) 243 { 244 struct icc_provider *p = node->provider; 245 struct icc_req *r; 246 u32 avg_bw, peak_bw; 247 248 node->avg_bw = 0; 249 node->peak_bw = 0; 250 251 if (p->pre_aggregate) 252 p->pre_aggregate(node); 253 254 hlist_for_each_entry(r, &node->req_list, req_node) { 255 if (r->enabled) { 256 avg_bw = r->avg_bw; 257 peak_bw = r->peak_bw; 258 } else { 259 avg_bw = 0; 260 peak_bw = 0; 261 } 262 p->aggregate(node, r->tag, avg_bw, peak_bw, 263 &node->avg_bw, &node->peak_bw); 264 } 265 266 return 0; 267 } 268 269 static int apply_constraints(struct icc_path *path) 270 { 271 struct icc_node *next, *prev = NULL; 272 struct icc_provider *p; 273 int ret = -EINVAL; 274 int i; 275 276 for (i = 0; i < path->num_nodes; i++) { 277 next = path->reqs[i].node; 278 p = next->provider; 279 280 /* both endpoints should be valid master-slave pairs */ 281 if (!prev || (p != prev->provider && !p->inter_set)) { 282 prev = next; 283 continue; 284 } 285 286 /* set the constraints */ 287 ret = p->set(prev, next); 288 if (ret) 289 goto out; 290 291 prev = next; 292 } 293 out: 294 return ret; 295 } 296 297 int icc_std_aggregate(struct icc_node *node, u32 tag, u32 avg_bw, 298 u32 peak_bw, u32 *agg_avg, u32 *agg_peak) 299 { 300 *agg_avg += avg_bw; 301 *agg_peak = max(*agg_peak, peak_bw); 302 303 return 0; 304 } 305 EXPORT_SYMBOL_GPL(icc_std_aggregate); 306 307 /* of_icc_xlate_onecell() - Translate function using a single index. 308 * @spec: OF phandle args to map into an interconnect node. 309 * @data: private data (pointer to struct icc_onecell_data) 310 * 311 * This is a generic translate function that can be used to model simple 312 * interconnect providers that have one device tree node and provide 313 * multiple interconnect nodes. A single cell is used as an index into 314 * an array of icc nodes specified in the icc_onecell_data struct when 315 * registering the provider. 316 */ 317 struct icc_node *of_icc_xlate_onecell(struct of_phandle_args *spec, 318 void *data) 319 { 320 struct icc_onecell_data *icc_data = data; 321 unsigned int idx = spec->args[0]; 322 323 if (idx >= icc_data->num_nodes) { 324 pr_err("%s: invalid index %u\n", __func__, idx); 325 return ERR_PTR(-EINVAL); 326 } 327 328 return icc_data->nodes[idx]; 329 } 330 EXPORT_SYMBOL_GPL(of_icc_xlate_onecell); 331 332 /** 333 * of_icc_get_from_provider() - Look-up interconnect node 334 * @spec: OF phandle args to use for look-up 335 * 336 * Looks for interconnect provider under the node specified by @spec and if 337 * found, uses xlate function of the provider to map phandle args to node. 338 * 339 * Returns a valid pointer to struct icc_node on success or ERR_PTR() 340 * on failure. 341 */ 342 struct icc_node *of_icc_get_from_provider(struct of_phandle_args *spec) 343 { 344 struct icc_node *node = ERR_PTR(-EPROBE_DEFER); 345 struct icc_provider *provider; 346 347 if (!spec) 348 return ERR_PTR(-EINVAL); 349 350 mutex_lock(&icc_lock); 351 list_for_each_entry(provider, &icc_providers, provider_list) { 352 if (provider->dev->of_node == spec->np) 353 node = provider->xlate(spec, provider->data); 354 if (!IS_ERR(node)) 355 break; 356 } 357 mutex_unlock(&icc_lock); 358 359 return node; 360 } 361 EXPORT_SYMBOL_GPL(of_icc_get_from_provider); 362 363 static void devm_icc_release(struct device *dev, void *res) 364 { 365 icc_put(*(struct icc_path **)res); 366 } 367 368 struct icc_path *devm_of_icc_get(struct device *dev, const char *name) 369 { 370 struct icc_path **ptr, *path; 371 372 ptr = devres_alloc(devm_icc_release, sizeof(**ptr), GFP_KERNEL); 373 if (!ptr) 374 return ERR_PTR(-ENOMEM); 375 376 path = of_icc_get(dev, name); 377 if (!IS_ERR(path)) { 378 *ptr = path; 379 devres_add(dev, ptr); 380 } else { 381 devres_free(ptr); 382 } 383 384 return path; 385 } 386 EXPORT_SYMBOL_GPL(devm_of_icc_get); 387 388 /** 389 * of_icc_get_by_index() - get a path handle from a DT node based on index 390 * @dev: device pointer for the consumer device 391 * @idx: interconnect path index 392 * 393 * This function will search for a path between two endpoints and return an 394 * icc_path handle on success. Use icc_put() to release constraints when they 395 * are not needed anymore. 396 * If the interconnect API is disabled, NULL is returned and the consumer 397 * drivers will still build. Drivers are free to handle this specifically, 398 * but they don't have to. 399 * 400 * Return: icc_path pointer on success or ERR_PTR() on error. NULL is returned 401 * when the API is disabled or the "interconnects" DT property is missing. 402 */ 403 struct icc_path *of_icc_get_by_index(struct device *dev, int idx) 404 { 405 struct icc_path *path; 406 struct icc_node *src_node, *dst_node; 407 struct device_node *np; 408 struct of_phandle_args src_args, dst_args; 409 int ret; 410 411 if (!dev || !dev->of_node) 412 return ERR_PTR(-ENODEV); 413 414 np = dev->of_node; 415 416 /* 417 * When the consumer DT node do not have "interconnects" property 418 * return a NULL path to skip setting constraints. 419 */ 420 if (!of_find_property(np, "interconnects", NULL)) 421 return NULL; 422 423 /* 424 * We use a combination of phandle and specifier for endpoint. For now 425 * lets support only global ids and extend this in the future if needed 426 * without breaking DT compatibility. 427 */ 428 ret = of_parse_phandle_with_args(np, "interconnects", 429 "#interconnect-cells", idx * 2, 430 &src_args); 431 if (ret) 432 return ERR_PTR(ret); 433 434 of_node_put(src_args.np); 435 436 ret = of_parse_phandle_with_args(np, "interconnects", 437 "#interconnect-cells", idx * 2 + 1, 438 &dst_args); 439 if (ret) 440 return ERR_PTR(ret); 441 442 of_node_put(dst_args.np); 443 444 src_node = of_icc_get_from_provider(&src_args); 445 446 if (IS_ERR(src_node)) { 447 if (PTR_ERR(src_node) != -EPROBE_DEFER) 448 dev_err(dev, "error finding src node: %ld\n", 449 PTR_ERR(src_node)); 450 return ERR_CAST(src_node); 451 } 452 453 dst_node = of_icc_get_from_provider(&dst_args); 454 455 if (IS_ERR(dst_node)) { 456 if (PTR_ERR(dst_node) != -EPROBE_DEFER) 457 dev_err(dev, "error finding dst node: %ld\n", 458 PTR_ERR(dst_node)); 459 return ERR_CAST(dst_node); 460 } 461 462 mutex_lock(&icc_lock); 463 path = path_find(dev, src_node, dst_node); 464 mutex_unlock(&icc_lock); 465 if (IS_ERR(path)) { 466 dev_err(dev, "%s: invalid path=%ld\n", __func__, PTR_ERR(path)); 467 return path; 468 } 469 470 path->name = kasprintf(GFP_KERNEL, "%s-%s", 471 src_node->name, dst_node->name); 472 if (!path->name) { 473 kfree(path); 474 return ERR_PTR(-ENOMEM); 475 } 476 477 return path; 478 } 479 EXPORT_SYMBOL_GPL(of_icc_get_by_index); 480 481 /** 482 * of_icc_get() - get a path handle from a DT node based on name 483 * @dev: device pointer for the consumer device 484 * @name: interconnect path name 485 * 486 * This function will search for a path between two endpoints and return an 487 * icc_path handle on success. Use icc_put() to release constraints when they 488 * are not needed anymore. 489 * If the interconnect API is disabled, NULL is returned and the consumer 490 * drivers will still build. Drivers are free to handle this specifically, 491 * but they don't have to. 492 * 493 * Return: icc_path pointer on success or ERR_PTR() on error. NULL is returned 494 * when the API is disabled or the "interconnects" DT property is missing. 495 */ 496 struct icc_path *of_icc_get(struct device *dev, const char *name) 497 { 498 struct device_node *np; 499 int idx = 0; 500 501 if (!dev || !dev->of_node) 502 return ERR_PTR(-ENODEV); 503 504 np = dev->of_node; 505 506 /* 507 * When the consumer DT node do not have "interconnects" property 508 * return a NULL path to skip setting constraints. 509 */ 510 if (!of_find_property(np, "interconnects", NULL)) 511 return NULL; 512 513 /* 514 * We use a combination of phandle and specifier for endpoint. For now 515 * lets support only global ids and extend this in the future if needed 516 * without breaking DT compatibility. 517 */ 518 if (name) { 519 idx = of_property_match_string(np, "interconnect-names", name); 520 if (idx < 0) 521 return ERR_PTR(idx); 522 } 523 524 return of_icc_get_by_index(dev, idx); 525 } 526 EXPORT_SYMBOL_GPL(of_icc_get); 527 528 /** 529 * icc_set_tag() - set an optional tag on a path 530 * @path: the path we want to tag 531 * @tag: the tag value 532 * 533 * This function allows consumers to append a tag to the requests associated 534 * with a path, so that a different aggregation could be done based on this tag. 535 */ 536 void icc_set_tag(struct icc_path *path, u32 tag) 537 { 538 int i; 539 540 if (!path) 541 return; 542 543 mutex_lock(&icc_lock); 544 545 for (i = 0; i < path->num_nodes; i++) 546 path->reqs[i].tag = tag; 547 548 mutex_unlock(&icc_lock); 549 } 550 EXPORT_SYMBOL_GPL(icc_set_tag); 551 552 /** 553 * icc_get_name() - Get name of the icc path 554 * @path: reference to the path returned by icc_get() 555 * 556 * This function is used by an interconnect consumer to get the name of the icc 557 * path. 558 * 559 * Returns a valid pointer on success, or NULL otherwise. 560 */ 561 const char *icc_get_name(struct icc_path *path) 562 { 563 if (!path) 564 return NULL; 565 566 return path->name; 567 } 568 EXPORT_SYMBOL_GPL(icc_get_name); 569 570 /** 571 * icc_set_bw() - set bandwidth constraints on an interconnect path 572 * @path: reference to the path returned by icc_get() 573 * @avg_bw: average bandwidth in kilobytes per second 574 * @peak_bw: peak bandwidth in kilobytes per second 575 * 576 * This function is used by an interconnect consumer to express its own needs 577 * in terms of bandwidth for a previously requested path between two endpoints. 578 * The requests are aggregated and each node is updated accordingly. The entire 579 * path is locked by a mutex to ensure that the set() is completed. 580 * The @path can be NULL when the "interconnects" DT properties is missing, 581 * which will mean that no constraints will be set. 582 * 583 * Returns 0 on success, or an appropriate error code otherwise. 584 */ 585 int icc_set_bw(struct icc_path *path, u32 avg_bw, u32 peak_bw) 586 { 587 struct icc_node *node; 588 u32 old_avg, old_peak; 589 size_t i; 590 int ret; 591 592 if (!path) 593 return 0; 594 595 if (WARN_ON(IS_ERR(path) || !path->num_nodes)) 596 return -EINVAL; 597 598 mutex_lock(&icc_lock); 599 600 old_avg = path->reqs[0].avg_bw; 601 old_peak = path->reqs[0].peak_bw; 602 603 for (i = 0; i < path->num_nodes; i++) { 604 node = path->reqs[i].node; 605 606 /* update the consumer request for this path */ 607 path->reqs[i].avg_bw = avg_bw; 608 path->reqs[i].peak_bw = peak_bw; 609 610 /* aggregate requests for this node */ 611 aggregate_requests(node); 612 613 trace_icc_set_bw(path, node, i, avg_bw, peak_bw); 614 } 615 616 ret = apply_constraints(path); 617 if (ret) { 618 pr_debug("interconnect: error applying constraints (%d)\n", 619 ret); 620 621 for (i = 0; i < path->num_nodes; i++) { 622 node = path->reqs[i].node; 623 path->reqs[i].avg_bw = old_avg; 624 path->reqs[i].peak_bw = old_peak; 625 aggregate_requests(node); 626 } 627 apply_constraints(path); 628 } 629 630 mutex_unlock(&icc_lock); 631 632 trace_icc_set_bw_end(path, ret); 633 634 return ret; 635 } 636 EXPORT_SYMBOL_GPL(icc_set_bw); 637 638 static int __icc_enable(struct icc_path *path, bool enable) 639 { 640 int i; 641 642 if (!path) 643 return 0; 644 645 if (WARN_ON(IS_ERR(path) || !path->num_nodes)) 646 return -EINVAL; 647 648 mutex_lock(&icc_lock); 649 650 for (i = 0; i < path->num_nodes; i++) 651 path->reqs[i].enabled = enable; 652 653 mutex_unlock(&icc_lock); 654 655 return icc_set_bw(path, path->reqs[0].avg_bw, 656 path->reqs[0].peak_bw); 657 } 658 659 int icc_enable(struct icc_path *path) 660 { 661 return __icc_enable(path, true); 662 } 663 EXPORT_SYMBOL_GPL(icc_enable); 664 665 int icc_disable(struct icc_path *path) 666 { 667 return __icc_enable(path, false); 668 } 669 EXPORT_SYMBOL_GPL(icc_disable); 670 671 /** 672 * icc_get() - return a handle for path between two endpoints 673 * @dev: the device requesting the path 674 * @src_id: source device port id 675 * @dst_id: destination device port id 676 * 677 * This function will search for a path between two endpoints and return an 678 * icc_path handle on success. Use icc_put() to release 679 * constraints when they are not needed anymore. 680 * If the interconnect API is disabled, NULL is returned and the consumer 681 * drivers will still build. Drivers are free to handle this specifically, 682 * but they don't have to. 683 * 684 * Return: icc_path pointer on success, ERR_PTR() on error or NULL if the 685 * interconnect API is disabled. 686 */ 687 struct icc_path *icc_get(struct device *dev, const int src_id, const int dst_id) 688 { 689 struct icc_node *src, *dst; 690 struct icc_path *path = ERR_PTR(-EPROBE_DEFER); 691 692 mutex_lock(&icc_lock); 693 694 src = node_find(src_id); 695 if (!src) 696 goto out; 697 698 dst = node_find(dst_id); 699 if (!dst) 700 goto out; 701 702 path = path_find(dev, src, dst); 703 if (IS_ERR(path)) { 704 dev_err(dev, "%s: invalid path=%ld\n", __func__, PTR_ERR(path)); 705 goto out; 706 } 707 708 path->name = kasprintf(GFP_KERNEL, "%s-%s", src->name, dst->name); 709 if (!path->name) { 710 kfree(path); 711 path = ERR_PTR(-ENOMEM); 712 } 713 out: 714 mutex_unlock(&icc_lock); 715 return path; 716 } 717 EXPORT_SYMBOL_GPL(icc_get); 718 719 /** 720 * icc_put() - release the reference to the icc_path 721 * @path: interconnect path 722 * 723 * Use this function to release the constraints on a path when the path is 724 * no longer needed. The constraints will be re-aggregated. 725 */ 726 void icc_put(struct icc_path *path) 727 { 728 struct icc_node *node; 729 size_t i; 730 int ret; 731 732 if (!path || WARN_ON(IS_ERR(path))) 733 return; 734 735 ret = icc_set_bw(path, 0, 0); 736 if (ret) 737 pr_err("%s: error (%d)\n", __func__, ret); 738 739 mutex_lock(&icc_lock); 740 for (i = 0; i < path->num_nodes; i++) { 741 node = path->reqs[i].node; 742 hlist_del(&path->reqs[i].req_node); 743 if (!WARN_ON(!node->provider->users)) 744 node->provider->users--; 745 } 746 mutex_unlock(&icc_lock); 747 748 kfree_const(path->name); 749 kfree(path); 750 } 751 EXPORT_SYMBOL_GPL(icc_put); 752 753 static struct icc_node *icc_node_create_nolock(int id) 754 { 755 struct icc_node *node; 756 757 /* check if node already exists */ 758 node = node_find(id); 759 if (node) 760 return node; 761 762 node = kzalloc(sizeof(*node), GFP_KERNEL); 763 if (!node) 764 return ERR_PTR(-ENOMEM); 765 766 id = idr_alloc(&icc_idr, node, id, id + 1, GFP_KERNEL); 767 if (id < 0) { 768 WARN(1, "%s: couldn't get idr\n", __func__); 769 kfree(node); 770 return ERR_PTR(id); 771 } 772 773 node->id = id; 774 775 return node; 776 } 777 778 /** 779 * icc_node_create() - create a node 780 * @id: node id 781 * 782 * Return: icc_node pointer on success, or ERR_PTR() on error 783 */ 784 struct icc_node *icc_node_create(int id) 785 { 786 struct icc_node *node; 787 788 mutex_lock(&icc_lock); 789 790 node = icc_node_create_nolock(id); 791 792 mutex_unlock(&icc_lock); 793 794 return node; 795 } 796 EXPORT_SYMBOL_GPL(icc_node_create); 797 798 /** 799 * icc_node_destroy() - destroy a node 800 * @id: node id 801 */ 802 void icc_node_destroy(int id) 803 { 804 struct icc_node *node; 805 806 mutex_lock(&icc_lock); 807 808 node = node_find(id); 809 if (node) { 810 idr_remove(&icc_idr, node->id); 811 WARN_ON(!hlist_empty(&node->req_list)); 812 } 813 814 mutex_unlock(&icc_lock); 815 816 kfree(node); 817 } 818 EXPORT_SYMBOL_GPL(icc_node_destroy); 819 820 /** 821 * icc_link_create() - create a link between two nodes 822 * @node: source node id 823 * @dst_id: destination node id 824 * 825 * Create a link between two nodes. The nodes might belong to different 826 * interconnect providers and the @dst_id node might not exist (if the 827 * provider driver has not probed yet). So just create the @dst_id node 828 * and when the actual provider driver is probed, the rest of the node 829 * data is filled. 830 * 831 * Return: 0 on success, or an error code otherwise 832 */ 833 int icc_link_create(struct icc_node *node, const int dst_id) 834 { 835 struct icc_node *dst; 836 struct icc_node **new; 837 int ret = 0; 838 839 if (!node->provider) 840 return -EINVAL; 841 842 mutex_lock(&icc_lock); 843 844 dst = node_find(dst_id); 845 if (!dst) { 846 dst = icc_node_create_nolock(dst_id); 847 848 if (IS_ERR(dst)) { 849 ret = PTR_ERR(dst); 850 goto out; 851 } 852 } 853 854 new = krealloc(node->links, 855 (node->num_links + 1) * sizeof(*node->links), 856 GFP_KERNEL); 857 if (!new) { 858 ret = -ENOMEM; 859 goto out; 860 } 861 862 node->links = new; 863 node->links[node->num_links++] = dst; 864 865 out: 866 mutex_unlock(&icc_lock); 867 868 return ret; 869 } 870 EXPORT_SYMBOL_GPL(icc_link_create); 871 872 /** 873 * icc_link_destroy() - destroy a link between two nodes 874 * @src: pointer to source node 875 * @dst: pointer to destination node 876 * 877 * Return: 0 on success, or an error code otherwise 878 */ 879 int icc_link_destroy(struct icc_node *src, struct icc_node *dst) 880 { 881 struct icc_node **new; 882 size_t slot; 883 int ret = 0; 884 885 if (IS_ERR_OR_NULL(src)) 886 return -EINVAL; 887 888 if (IS_ERR_OR_NULL(dst)) 889 return -EINVAL; 890 891 mutex_lock(&icc_lock); 892 893 for (slot = 0; slot < src->num_links; slot++) 894 if (src->links[slot] == dst) 895 break; 896 897 if (WARN_ON(slot == src->num_links)) { 898 ret = -ENXIO; 899 goto out; 900 } 901 902 src->links[slot] = src->links[--src->num_links]; 903 904 new = krealloc(src->links, src->num_links * sizeof(*src->links), 905 GFP_KERNEL); 906 if (new) 907 src->links = new; 908 909 out: 910 mutex_unlock(&icc_lock); 911 912 return ret; 913 } 914 EXPORT_SYMBOL_GPL(icc_link_destroy); 915 916 /** 917 * icc_node_add() - add interconnect node to interconnect provider 918 * @node: pointer to the interconnect node 919 * @provider: pointer to the interconnect provider 920 */ 921 void icc_node_add(struct icc_node *node, struct icc_provider *provider) 922 { 923 mutex_lock(&icc_lock); 924 925 node->provider = provider; 926 list_add_tail(&node->node_list, &provider->nodes); 927 928 mutex_unlock(&icc_lock); 929 } 930 EXPORT_SYMBOL_GPL(icc_node_add); 931 932 /** 933 * icc_node_del() - delete interconnect node from interconnect provider 934 * @node: pointer to the interconnect node 935 */ 936 void icc_node_del(struct icc_node *node) 937 { 938 mutex_lock(&icc_lock); 939 940 list_del(&node->node_list); 941 942 mutex_unlock(&icc_lock); 943 } 944 EXPORT_SYMBOL_GPL(icc_node_del); 945 946 /** 947 * icc_nodes_remove() - remove all previously added nodes from provider 948 * @provider: the interconnect provider we are removing nodes from 949 * 950 * Return: 0 on success, or an error code otherwise 951 */ 952 int icc_nodes_remove(struct icc_provider *provider) 953 { 954 struct icc_node *n, *tmp; 955 956 if (WARN_ON(IS_ERR_OR_NULL(provider))) 957 return -EINVAL; 958 959 list_for_each_entry_safe_reverse(n, tmp, &provider->nodes, node_list) { 960 icc_node_del(n); 961 icc_node_destroy(n->id); 962 } 963 964 return 0; 965 } 966 EXPORT_SYMBOL_GPL(icc_nodes_remove); 967 968 /** 969 * icc_provider_add() - add a new interconnect provider 970 * @provider: the interconnect provider that will be added into topology 971 * 972 * Return: 0 on success, or an error code otherwise 973 */ 974 int icc_provider_add(struct icc_provider *provider) 975 { 976 if (WARN_ON(!provider->set)) 977 return -EINVAL; 978 if (WARN_ON(!provider->xlate)) 979 return -EINVAL; 980 981 mutex_lock(&icc_lock); 982 983 INIT_LIST_HEAD(&provider->nodes); 984 list_add_tail(&provider->provider_list, &icc_providers); 985 986 mutex_unlock(&icc_lock); 987 988 dev_dbg(provider->dev, "interconnect provider added to topology\n"); 989 990 return 0; 991 } 992 EXPORT_SYMBOL_GPL(icc_provider_add); 993 994 /** 995 * icc_provider_del() - delete previously added interconnect provider 996 * @provider: the interconnect provider that will be removed from topology 997 * 998 * Return: 0 on success, or an error code otherwise 999 */ 1000 int icc_provider_del(struct icc_provider *provider) 1001 { 1002 mutex_lock(&icc_lock); 1003 if (provider->users) { 1004 pr_warn("interconnect provider still has %d users\n", 1005 provider->users); 1006 mutex_unlock(&icc_lock); 1007 return -EBUSY; 1008 } 1009 1010 if (!list_empty(&provider->nodes)) { 1011 pr_warn("interconnect provider still has nodes\n"); 1012 mutex_unlock(&icc_lock); 1013 return -EBUSY; 1014 } 1015 1016 list_del(&provider->provider_list); 1017 mutex_unlock(&icc_lock); 1018 1019 return 0; 1020 } 1021 EXPORT_SYMBOL_GPL(icc_provider_del); 1022 1023 static int __init icc_init(void) 1024 { 1025 icc_debugfs_dir = debugfs_create_dir("interconnect", NULL); 1026 debugfs_create_file("interconnect_summary", 0444, 1027 icc_debugfs_dir, NULL, &icc_summary_fops); 1028 debugfs_create_file("interconnect_graph", 0444, 1029 icc_debugfs_dir, NULL, &icc_graph_fops); 1030 return 0; 1031 } 1032 1033 device_initcall(icc_init); 1034 1035 MODULE_AUTHOR("Georgi Djakov <georgi.djakov@linaro.org>"); 1036 MODULE_DESCRIPTION("Interconnect Driver Core"); 1037 MODULE_LICENSE("GPL v2"); 1038