--- zzzz-none-000/linux-4.4.271/drivers/hwtracing/coresight/coresight.c 2021-06-03 06:22:09.000000000 +0000 +++ dakota-7530ac-750/linux-4.4.271/drivers/hwtracing/coresight/coresight.c 2023-01-11 09:25:41.000000000 +0000 @@ -1,4 +1,4 @@ -/* Copyright (c) 2012, The Linux Foundation. All rights reserved. +/* Copyright (c) 2012, 2016 The Linux Foundation. All rights reserved. * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License version 2 and @@ -25,9 +25,12 @@ #include #include +#include + #include "coresight-priv.h" static DEFINE_MUTEX(coresight_mutex); +static struct coresight_device *curr_sink; static int coresight_id_match(struct device *dev, void *data) { @@ -385,7 +388,146 @@ } EXPORT_SYMBOL_GPL(coresight_disable); -static ssize_t enable_sink_show(struct device *dev, +void coresight_abort(void) +{ + if (!mutex_trylock(&coresight_mutex)) { + pr_err_ratelimited("coresight: abort could not be processed\n"); + return; + } + if (!curr_sink) + goto out; + + if (curr_sink->enable && sink_ops(curr_sink)->abort) { + sink_ops(curr_sink)->abort(curr_sink); + curr_sink->enable = false; + } + +out: + mutex_unlock(&coresight_mutex); +} +EXPORT_SYMBOL_GPL(coresight_abort); + +static int coresight_panic_handler(struct notifier_block *this, + unsigned long event, void *ptr) +{ + if (!curr_sink) + goto out; + + if (curr_sink->enable && sink_ops(curr_sink)->abort) { + sink_ops(curr_sink)->abort(curr_sink); + curr_sink->enable = false; + } + +out: + return NOTIFY_DONE; +} + +static struct notifier_block panic_nb = { + .notifier_call = coresight_panic_handler, +}; + +static int coresight_disable_all_source(struct device *dev, void *data) +{ + struct coresight_device *csdev; + LIST_HEAD(path); + + csdev = to_coresight_device(dev); + + /* + * No need to care about components that are not sources or not enabled + */ + if (!csdev->enable || csdev->type != CORESIGHT_DEV_TYPE_SOURCE) + return 0; + + coresight_disable_source(csdev); + + return 0; +} + +static int coresight_toggle_source_path(struct device *dev, void *data) +{ + struct coresight_device *csdev; + bool *enable = data; + int ret; + LIST_HEAD(path); + + csdev = to_coresight_device(dev); + + /* + * No need to care about components that are not sources or not enabled + */ + if (!csdev->enable || csdev->type != CORESIGHT_DEV_TYPE_SOURCE) + return 0; + + if (*enable) { + ret = coresight_build_paths(csdev, &path, true); + if (ret) { + dev_err(&csdev->dev, "building path(s) failed\n"); + return ret; + } + } else { + if (coresight_build_paths(csdev, &path, false)) + dev_err(&csdev->dev, "releasing path(s) failed\n"); + } + + return 0; +} + +static int coresight_switch_sink(struct coresight_device *csdev) +{ + int ret; + LIST_HEAD(slist); + bool enable = false; + + mutex_lock(&coresight_mutex); + + /* If curr_sink is same as new requested sink then do nothing. */ + if (curr_sink == csdev) + goto out; + + /* + * If curr_sink is NULL then sink is getting set for the first time. + * No source should be enabled at this time. + */ + if (!curr_sink) { + csdev->activated = true; + goto out; + } + + /* curr_sink is different from csdev */ + bus_for_each_dev(&coresight_bustype, NULL, + &enable, coresight_toggle_source_path); + + csdev->activated = true; + curr_sink->activated = false; + + enable = true; + ret = bus_for_each_dev(&coresight_bustype, NULL, &enable, + coresight_toggle_source_path); + if (ret) + goto err; +out: + curr_sink = csdev; + mutex_unlock(&coresight_mutex); + return 0; + +err: + /* Disable sources */ + bus_for_each_dev(&coresight_bustype, NULL, + &enable, coresight_disable_all_source); + + enable = false; + bus_for_each_dev(&coresight_bustype, NULL, + &enable, coresight_toggle_source_path); + + csdev->activated = false; + curr_sink->activated = true; + + mutex_unlock(&coresight_mutex); + return ret; +} + +static ssize_t curr_sink_show(struct device *dev, struct device_attribute *attr, char *buf) { struct coresight_device *csdev = to_coresight_device(dev); @@ -393,7 +535,7 @@ return scnprintf(buf, PAGE_SIZE, "%u\n", (unsigned)csdev->activated); } -static ssize_t enable_sink_store(struct device *dev, +static ssize_t curr_sink_store(struct device *dev, struct device_attribute *attr, const char *buf, size_t size) { @@ -406,16 +548,13 @@ return ret; if (val) - csdev->activated = true; - else - csdev->activated = false; + coresight_switch_sink(csdev); return size; - } -static DEVICE_ATTR_RW(enable_sink); +static DEVICE_ATTR_RW(curr_sink); -static ssize_t enable_source_show(struct device *dev, +static ssize_t enable_show(struct device *dev, struct device_attribute *attr, char *buf) { struct coresight_device *csdev = to_coresight_device(dev); @@ -423,7 +562,7 @@ return scnprintf(buf, PAGE_SIZE, "%u\n", (unsigned)csdev->enable); } -static ssize_t enable_source_store(struct device *dev, +static ssize_t enable_store(struct device *dev, struct device_attribute *attr, const char *buf, size_t size) { @@ -445,16 +584,16 @@ return size; } -static DEVICE_ATTR_RW(enable_source); +static DEVICE_ATTR_RW(enable); static struct attribute *coresight_sink_attrs[] = { - &dev_attr_enable_sink.attr, + &dev_attr_curr_sink.attr, NULL, }; ATTRIBUTE_GROUPS(coresight_sink); static struct attribute *coresight_source_attrs[] = { - &dev_attr_enable_source.attr, + &dev_attr_enable.attr, NULL, }; ATTRIBUTE_GROUPS(coresight_source); @@ -672,7 +811,16 @@ static int __init coresight_init(void) { - return bus_register(&coresight_bustype); + int ret = 0; + + ret = bus_register(&coresight_bustype); + if (ret) + return ret; + + ret = atomic_notifier_chain_register(&panic_notifier_list, + &panic_nb); + + return ret; } postcore_initcall(coresight_init); @@ -719,6 +867,8 @@ } for (i = 0; i < csdev->nr_outport; i++) { + if (desc->pdata->child_names[i] == NULL) + continue; conns[i].outport = desc->pdata->outports[i]; conns[i].child_name = desc->pdata->child_names[i]; conns[i].child_port = desc->pdata->child_ports[i]; @@ -747,6 +897,21 @@ coresight_fixup_device_conns(csdev); coresight_fixup_orphan_conns(csdev); + if (csdev->type == CORESIGHT_DEV_TYPE_SINK || + csdev->type == CORESIGHT_DEV_TYPE_LINKSINK) { + if (desc->pdata->default_sink) { + if (curr_sink) { + dev_warn(&csdev->dev, + "overwritting curr sink %s", + dev_name(&curr_sink->dev)); + curr_sink->activated = false; + } + + curr_sink = csdev; + curr_sink->activated = true; + } + } + mutex_unlock(&coresight_mutex); return csdev;