1 // SPDX-License-Identifier: GPL-2.0 2 /* 3 * Copyright (c) 2019, Linaro Limited, All rights reserved. 4 * Author: Mike Leach <mike.leach@linaro.org> 5 */ 6 7 #include <linux/device.h> 8 #include <linux/idr.h> 9 #include <linux/kernel.h> 10 #include <linux/property.h> 11 12 #include "coresight-priv.h" 13 #include "coresight-trace-id.h" 14 15 /* 16 * Use IDR to map the hash of the source's device name 17 * to the pointer of path for the source. The idr is for 18 * the sources which aren't associated with CPU. 19 */ 20 static DEFINE_IDR(path_idr); 21 22 /* 23 * When operating Coresight drivers from the sysFS interface, only a single 24 * path can exist from a tracer (associated to a CPU) to a sink. 25 */ 26 static DEFINE_PER_CPU(struct coresight_path *, tracer_path); 27 28 ssize_t coresight_simple_show_pair(struct device *_dev, 29 struct device_attribute *attr, char *buf) 30 { 31 struct coresight_device *csdev = container_of(_dev, struct coresight_device, dev); 32 struct cs_pair_attribute *cs_attr = container_of(attr, struct cs_pair_attribute, attr); 33 u64 val; 34 35 pm_runtime_get_sync(_dev->parent); 36 val = csdev_access_relaxed_read_pair(&csdev->access, cs_attr->lo_off, cs_attr->hi_off); 37 pm_runtime_put_sync(_dev->parent); 38 return sysfs_emit(buf, "0x%llx\n", val); 39 } 40 EXPORT_SYMBOL_GPL(coresight_simple_show_pair); 41 42 ssize_t coresight_simple_show32(struct device *_dev, 43 struct device_attribute *attr, char *buf) 44 { 45 struct coresight_device *csdev = container_of(_dev, struct coresight_device, dev); 46 struct cs_off_attribute *cs_attr = container_of(attr, struct cs_off_attribute, attr); 47 u64 val; 48 49 pm_runtime_get_sync(_dev->parent); 50 val = csdev_access_relaxed_read32(&csdev->access, cs_attr->off); 51 pm_runtime_put_sync(_dev->parent); 52 return sysfs_emit(buf, "0x%llx\n", val); 53 } 54 EXPORT_SYMBOL_GPL(coresight_simple_show32); 55 56 static int coresight_enable_source_sysfs(struct coresight_device *csdev, 57 enum cs_mode mode, 58 struct coresight_path *path) 59 { 60 int ret; 61 62 /* 63 * Comparison with CS_MODE_SYSFS works without taking any device 64 * specific spinlock because the truthyness of that comparison can only 65 * change with coresight_mutex held, which we already have here. 66 */ 67 lockdep_assert_held(&coresight_mutex); 68 if (coresight_get_mode(csdev) != CS_MODE_SYSFS) { 69 ret = source_ops(csdev)->enable(csdev, NULL, mode, path); 70 if (ret) 71 return ret; 72 } 73 74 csdev->refcnt++; 75 76 return 0; 77 } 78 79 /** 80 * coresight_disable_source_sysfs - Drop the reference count by 1 and disable 81 * the device if there are no users left. 82 * 83 * @csdev: The coresight device to disable 84 * @data: Opaque data to pass on to the disable function of the source device. 85 * For example in perf mode this is a pointer to the struct perf_event. 86 * 87 * Returns true if the device has been disabled. 88 */ 89 static bool coresight_disable_source_sysfs(struct coresight_device *csdev, 90 void *data) 91 { 92 lockdep_assert_held(&coresight_mutex); 93 if (coresight_get_mode(csdev) != CS_MODE_SYSFS) 94 return false; 95 96 csdev->refcnt--; 97 if (csdev->refcnt == 0) { 98 coresight_disable_source(csdev, data); 99 return true; 100 } 101 return false; 102 } 103 104 /** 105 * coresight_find_activated_sysfs_sink - returns the first sink activated via 106 * sysfs using connection based search starting from the source reference. 107 * 108 * @csdev: Coresight source device reference 109 */ 110 static struct coresight_device * 111 coresight_find_activated_sysfs_sink(struct coresight_device *csdev) 112 { 113 int i; 114 struct coresight_device *sink = NULL; 115 116 if ((csdev->type == CORESIGHT_DEV_TYPE_SINK || 117 csdev->type == CORESIGHT_DEV_TYPE_LINKSINK) && 118 csdev->sysfs_sink_activated) 119 return csdev; 120 121 /* 122 * Recursively explore each port found on this element. 123 */ 124 for (i = 0; i < csdev->pdata->nr_outconns; i++) { 125 struct coresight_device *child_dev; 126 127 child_dev = csdev->pdata->out_conns[i]->dest_dev; 128 if (child_dev) 129 sink = coresight_find_activated_sysfs_sink(child_dev); 130 if (sink) 131 return sink; 132 } 133 134 return NULL; 135 } 136 137 /** coresight_validate_source - make sure a source has the right credentials to 138 * be used via sysfs. 139 * @csdev: the device structure for a source. 140 * @function: the function this was called from. 141 * 142 * Assumes the coresight_mutex is held. 143 */ 144 static int coresight_validate_source_sysfs(struct coresight_device *csdev, 145 const char *function) 146 { 147 u32 type, subtype; 148 149 type = csdev->type; 150 subtype = csdev->subtype.source_subtype; 151 152 if (type != CORESIGHT_DEV_TYPE_SOURCE) { 153 dev_err(&csdev->dev, "wrong device type in %s\n", function); 154 return -EINVAL; 155 } 156 157 if (subtype != CORESIGHT_DEV_SUBTYPE_SOURCE_PROC && 158 subtype != CORESIGHT_DEV_SUBTYPE_SOURCE_SOFTWARE && 159 subtype != CORESIGHT_DEV_SUBTYPE_SOURCE_TPDM && 160 subtype != CORESIGHT_DEV_SUBTYPE_SOURCE_OTHERS) { 161 dev_err(&csdev->dev, "wrong device subtype in %s\n", function); 162 return -EINVAL; 163 } 164 165 return 0; 166 } 167 168 int coresight_enable_sysfs(struct coresight_device *csdev) 169 { 170 int cpu, ret = 0; 171 struct coresight_device *sink; 172 struct coresight_path *path; 173 enum coresight_dev_subtype_source subtype; 174 u32 hash; 175 176 subtype = csdev->subtype.source_subtype; 177 178 mutex_lock(&coresight_mutex); 179 180 ret = coresight_validate_source_sysfs(csdev, __func__); 181 if (ret) 182 goto out; 183 184 /* 185 * mode == SYSFS implies that it's already enabled. Don't look at the 186 * refcount to determine this because we don't claim the source until 187 * coresight_enable_source() so can still race with Perf mode which 188 * doesn't hold coresight_mutex. 189 */ 190 if (coresight_get_mode(csdev) == CS_MODE_SYSFS) { 191 /* 192 * There could be multiple applications driving the software 193 * source. So keep the refcount for each such user when the 194 * source is already enabled. 195 */ 196 if (subtype == CORESIGHT_DEV_SUBTYPE_SOURCE_SOFTWARE) 197 csdev->refcnt++; 198 goto out; 199 } 200 201 sink = coresight_find_activated_sysfs_sink(csdev); 202 if (!sink) { 203 ret = -EINVAL; 204 goto out; 205 } 206 207 path = coresight_build_path(csdev, sink); 208 if (IS_ERR(path)) { 209 pr_err("building path(s) failed\n"); 210 ret = PTR_ERR(path); 211 goto out; 212 } 213 214 coresight_path_assign_trace_id(path, CS_MODE_SYSFS); 215 if (!IS_VALID_CS_TRACE_ID(path->trace_id)) 216 goto err_path; 217 218 ret = coresight_enable_path(path, CS_MODE_SYSFS, NULL); 219 if (ret) 220 goto err_path; 221 222 ret = coresight_enable_source_sysfs(csdev, CS_MODE_SYSFS, path); 223 if (ret) 224 goto err_source; 225 226 switch (subtype) { 227 case CORESIGHT_DEV_SUBTYPE_SOURCE_PROC: 228 /* 229 * When working from sysFS it is important to keep track 230 * of the paths that were created so that they can be 231 * undone in 'coresight_disable()'. Since there can only 232 * be a single session per tracer (when working from sysFS) 233 * a per-cpu variable will do just fine. 234 */ 235 cpu = source_ops(csdev)->cpu_id(csdev); 236 per_cpu(tracer_path, cpu) = path; 237 break; 238 case CORESIGHT_DEV_SUBTYPE_SOURCE_SOFTWARE: 239 case CORESIGHT_DEV_SUBTYPE_SOURCE_TPDM: 240 case CORESIGHT_DEV_SUBTYPE_SOURCE_OTHERS: 241 /* 242 * Use the hash of source's device name as ID 243 * and map the ID to the pointer of the path. 244 */ 245 hash = hashlen_hash(hashlen_string(NULL, dev_name(&csdev->dev))); 246 ret = idr_alloc_u32(&path_idr, path, &hash, hash, GFP_KERNEL); 247 if (ret) 248 goto err_source; 249 break; 250 default: 251 /* We can't be here */ 252 break; 253 } 254 255 out: 256 mutex_unlock(&coresight_mutex); 257 return ret; 258 259 err_source: 260 coresight_disable_path(path); 261 262 err_path: 263 coresight_release_path(path); 264 goto out; 265 } 266 EXPORT_SYMBOL_GPL(coresight_enable_sysfs); 267 268 void coresight_disable_sysfs(struct coresight_device *csdev) 269 { 270 int cpu, ret; 271 struct coresight_path *path = NULL; 272 u32 hash; 273 274 mutex_lock(&coresight_mutex); 275 276 ret = coresight_validate_source_sysfs(csdev, __func__); 277 if (ret) 278 goto out; 279 280 if (!coresight_disable_source_sysfs(csdev, NULL)) 281 goto out; 282 283 switch (csdev->subtype.source_subtype) { 284 case CORESIGHT_DEV_SUBTYPE_SOURCE_PROC: 285 cpu = source_ops(csdev)->cpu_id(csdev); 286 path = per_cpu(tracer_path, cpu); 287 per_cpu(tracer_path, cpu) = NULL; 288 break; 289 case CORESIGHT_DEV_SUBTYPE_SOURCE_SOFTWARE: 290 case CORESIGHT_DEV_SUBTYPE_SOURCE_TPDM: 291 case CORESIGHT_DEV_SUBTYPE_SOURCE_OTHERS: 292 hash = hashlen_hash(hashlen_string(NULL, dev_name(&csdev->dev))); 293 /* Find the path by the hash. */ 294 path = idr_find(&path_idr, hash); 295 if (path == NULL) { 296 pr_err("Path is not found for %s\n", dev_name(&csdev->dev)); 297 goto out; 298 } 299 idr_remove(&path_idr, hash); 300 break; 301 default: 302 /* We can't be here */ 303 break; 304 } 305 306 coresight_disable_path(path); 307 coresight_release_path(path); 308 309 out: 310 mutex_unlock(&coresight_mutex); 311 } 312 EXPORT_SYMBOL_GPL(coresight_disable_sysfs); 313 314 static ssize_t enable_sink_show(struct device *dev, 315 struct device_attribute *attr, char *buf) 316 { 317 struct coresight_device *csdev = to_coresight_device(dev); 318 319 return scnprintf(buf, PAGE_SIZE, "%u\n", csdev->sysfs_sink_activated); 320 } 321 322 static ssize_t enable_sink_store(struct device *dev, 323 struct device_attribute *attr, 324 const char *buf, size_t size) 325 { 326 int ret; 327 unsigned long val; 328 struct coresight_device *csdev = to_coresight_device(dev); 329 330 ret = kstrtoul(buf, 10, &val); 331 if (ret) 332 return ret; 333 334 csdev->sysfs_sink_activated = !!val; 335 336 return size; 337 338 } 339 static DEVICE_ATTR_RW(enable_sink); 340 341 static ssize_t enable_source_show(struct device *dev, 342 struct device_attribute *attr, char *buf) 343 { 344 struct coresight_device *csdev = to_coresight_device(dev); 345 346 guard(mutex)(&coresight_mutex); 347 return scnprintf(buf, PAGE_SIZE, "%u\n", 348 coresight_get_mode(csdev) == CS_MODE_SYSFS); 349 } 350 351 static ssize_t enable_source_store(struct device *dev, 352 struct device_attribute *attr, 353 const char *buf, size_t size) 354 { 355 int ret = 0; 356 unsigned long val; 357 struct coresight_device *csdev = to_coresight_device(dev); 358 359 ret = kstrtoul(buf, 10, &val); 360 if (ret) 361 return ret; 362 363 if (val) { 364 ret = coresight_enable_sysfs(csdev); 365 if (ret) 366 return ret; 367 } else { 368 coresight_disable_sysfs(csdev); 369 } 370 371 return size; 372 } 373 static DEVICE_ATTR_RW(enable_source); 374 375 static ssize_t label_show(struct device *dev, 376 struct device_attribute *attr, char *buf) 377 { 378 379 const char *str; 380 int ret; 381 382 ret = fwnode_property_read_string(dev_fwnode(dev), "label", &str); 383 if (ret == 0) 384 return sysfs_emit(buf, "%s\n", str); 385 else 386 return ret; 387 } 388 static DEVICE_ATTR_RO(label); 389 390 static umode_t label_is_visible(struct kobject *kobj, 391 struct attribute *attr, int n) 392 { 393 struct device *dev = kobj_to_dev(kobj); 394 395 if (attr == &dev_attr_label.attr) { 396 if (fwnode_property_present(dev_fwnode(dev), "label")) 397 return attr->mode; 398 else 399 return 0; 400 } 401 402 return attr->mode; 403 } 404 405 static struct attribute *coresight_sink_attrs[] = { 406 &dev_attr_enable_sink.attr, 407 &dev_attr_label.attr, 408 NULL, 409 }; 410 411 static struct attribute_group coresight_sink_group = { 412 .attrs = coresight_sink_attrs, 413 .is_visible = label_is_visible, 414 }; 415 __ATTRIBUTE_GROUPS(coresight_sink); 416 417 static struct attribute *coresight_source_attrs[] = { 418 &dev_attr_enable_source.attr, 419 &dev_attr_label.attr, 420 NULL, 421 }; 422 423 static struct attribute_group coresight_source_group = { 424 .attrs = coresight_source_attrs, 425 .is_visible = label_is_visible, 426 }; 427 __ATTRIBUTE_GROUPS(coresight_source); 428 429 static struct attribute *coresight_link_attrs[] = { 430 &dev_attr_label.attr, 431 NULL, 432 }; 433 434 static struct attribute_group coresight_link_group = { 435 .attrs = coresight_link_attrs, 436 .is_visible = label_is_visible, 437 }; 438 __ATTRIBUTE_GROUPS(coresight_link); 439 440 static struct attribute *coresight_helper_attrs[] = { 441 &dev_attr_label.attr, 442 NULL, 443 }; 444 445 static struct attribute_group coresight_helper_group = { 446 .attrs = coresight_helper_attrs, 447 .is_visible = label_is_visible, 448 }; 449 __ATTRIBUTE_GROUPS(coresight_helper); 450 451 const struct device_type coresight_dev_type[] = { 452 [CORESIGHT_DEV_TYPE_SINK] = { 453 .name = "sink", 454 .groups = coresight_sink_groups, 455 }, 456 [CORESIGHT_DEV_TYPE_LINK] = { 457 .name = "link", 458 .groups = coresight_link_groups, 459 }, 460 [CORESIGHT_DEV_TYPE_LINKSINK] = { 461 .name = "linksink", 462 .groups = coresight_sink_groups, 463 }, 464 [CORESIGHT_DEV_TYPE_SOURCE] = { 465 .name = "source", 466 .groups = coresight_source_groups, 467 }, 468 [CORESIGHT_DEV_TYPE_HELPER] = { 469 .name = "helper", 470 .groups = coresight_helper_groups, 471 } 472 }; 473 /* Ensure the enum matches the names and groups */ 474 static_assert(ARRAY_SIZE(coresight_dev_type) == CORESIGHT_DEV_TYPE_MAX); 475 476 /* 477 * Connections group - links attribute. 478 * Count of created links between coresight components in the group. 479 */ 480 static ssize_t nr_links_show(struct device *dev, 481 struct device_attribute *attr, 482 char *buf) 483 { 484 struct coresight_device *csdev = to_coresight_device(dev); 485 486 return sprintf(buf, "%d\n", csdev->nr_links); 487 } 488 static DEVICE_ATTR_RO(nr_links); 489 490 static struct attribute *coresight_conns_attrs[] = { 491 &dev_attr_nr_links.attr, 492 NULL, 493 }; 494 495 static struct attribute_group coresight_conns_group = { 496 .attrs = coresight_conns_attrs, 497 .name = "connections", 498 }; 499 500 /* 501 * Create connections group for CoreSight devices. 502 * This group will then be used to collate the sysfs links between 503 * devices. 504 */ 505 int coresight_create_conns_sysfs_group(struct coresight_device *csdev) 506 { 507 int ret = 0; 508 509 if (!csdev) 510 return -EINVAL; 511 512 ret = sysfs_create_group(&csdev->dev.kobj, &coresight_conns_group); 513 if (ret) 514 return ret; 515 516 csdev->has_conns_grp = true; 517 return ret; 518 } 519 520 void coresight_remove_conns_sysfs_group(struct coresight_device *csdev) 521 { 522 if (!csdev) 523 return; 524 525 if (csdev->has_conns_grp) { 526 sysfs_remove_group(&csdev->dev.kobj, &coresight_conns_group); 527 csdev->has_conns_grp = false; 528 } 529 } 530 531 int coresight_add_sysfs_link(struct coresight_sysfs_link *info) 532 { 533 int ret = 0; 534 535 if (!info) 536 return -EINVAL; 537 if (!info->orig || !info->target || 538 !info->orig_name || !info->target_name) 539 return -EINVAL; 540 if (!info->orig->has_conns_grp || !info->target->has_conns_grp) 541 return -EINVAL; 542 543 /* first link orig->target */ 544 ret = sysfs_add_link_to_group(&info->orig->dev.kobj, 545 coresight_conns_group.name, 546 &info->target->dev.kobj, 547 info->orig_name); 548 if (ret) 549 return ret; 550 551 /* second link target->orig */ 552 ret = sysfs_add_link_to_group(&info->target->dev.kobj, 553 coresight_conns_group.name, 554 &info->orig->dev.kobj, 555 info->target_name); 556 557 /* error in second link - remove first - otherwise inc counts */ 558 if (ret) { 559 sysfs_remove_link_from_group(&info->orig->dev.kobj, 560 coresight_conns_group.name, 561 info->orig_name); 562 } else { 563 info->orig->nr_links++; 564 info->target->nr_links++; 565 } 566 567 return ret; 568 } 569 EXPORT_SYMBOL_GPL(coresight_add_sysfs_link); 570 571 void coresight_remove_sysfs_link(struct coresight_sysfs_link *info) 572 { 573 if (!info) 574 return; 575 if (!info->orig || !info->target || 576 !info->orig_name || !info->target_name) 577 return; 578 579 sysfs_remove_link_from_group(&info->orig->dev.kobj, 580 coresight_conns_group.name, 581 info->orig_name); 582 583 sysfs_remove_link_from_group(&info->target->dev.kobj, 584 coresight_conns_group.name, 585 info->target_name); 586 587 info->orig->nr_links--; 588 info->target->nr_links--; 589 } 590 EXPORT_SYMBOL_GPL(coresight_remove_sysfs_link); 591 592 /* 593 * coresight_make_links: Make a link for a connection from a @orig 594 * device to @target, represented by @conn. 595 * 596 * e.g, for devOrig[output_X] -> devTarget[input_Y] is represented 597 * as two symbolic links : 598 * 599 * /sys/.../devOrig/out:X -> /sys/.../devTarget/ 600 * /sys/.../devTarget/in:Y -> /sys/.../devOrig/ 601 * 602 * The link names are allocated for a device where it appears. i.e, the 603 * "out" link on the master and "in" link on the slave device. 604 * The link info is stored in the connection record for avoiding 605 * the reconstruction of names for removal. 606 */ 607 int coresight_make_links(struct coresight_device *orig, 608 struct coresight_connection *conn, 609 struct coresight_device *target) 610 { 611 int ret = -ENOMEM; 612 char *outs = NULL, *ins = NULL; 613 struct coresight_sysfs_link *link = NULL; 614 615 /* Helper devices aren't shown in sysfs */ 616 if (conn->dest_port == -1 && conn->src_port == -1) 617 return 0; 618 619 do { 620 outs = devm_kasprintf(&orig->dev, GFP_KERNEL, 621 "out:%d", conn->src_port); 622 if (!outs) 623 break; 624 ins = devm_kasprintf(&target->dev, GFP_KERNEL, 625 "in:%d", conn->dest_port); 626 if (!ins) 627 break; 628 link = devm_kzalloc(&orig->dev, 629 sizeof(struct coresight_sysfs_link), 630 GFP_KERNEL); 631 if (!link) 632 break; 633 634 link->orig = orig; 635 link->target = target; 636 link->orig_name = outs; 637 link->target_name = ins; 638 639 ret = coresight_add_sysfs_link(link); 640 if (ret) 641 break; 642 643 conn->link = link; 644 return 0; 645 } while (0); 646 647 return ret; 648 } 649 650 /* 651 * coresight_remove_links: Remove the sysfs links for a given connection @conn, 652 * from @orig device to @target device. See coresight_make_links() for more 653 * details. 654 */ 655 void coresight_remove_links(struct coresight_device *orig, 656 struct coresight_connection *conn) 657 { 658 if (!orig || !conn->link) 659 return; 660 661 coresight_remove_sysfs_link(conn->link); 662 663 devm_kfree(&conn->dest_dev->dev, conn->link->target_name); 664 devm_kfree(&orig->dev, conn->link->orig_name); 665 devm_kfree(&orig->dev, conn->link); 666 conn->link = NULL; 667 } 668