diff options
author | Linus Torvalds <torvalds@linux-foundation.org> | 2020-06-07 10:59:32 -0700 |
---|---|---|
committer | Linus Torvalds <torvalds@linux-foundation.org> | 2020-06-07 10:59:32 -0700 |
commit | 9aa900c8094dba7a60dc805ecec1e9f720744ba1 (patch) | |
tree | 3cc09a579f8ea6d3a182076ba722f7c1648e682d /drivers/hwtracing | |
parent | f558b8364e19f9222e7976c64e9367f66bab02cc (diff) | |
parent | 05c8a4fc44a916dd897769ca69b42381f9177ec4 (diff) |
Merge tag 'char-misc-5.8-rc1' of git://git.kernel.org/pub/scm/linux/kernel/git/gregkh/char-misc
Pull char/misc driver updates from Greg KH:
"Here is the large set of char/misc driver patches for 5.8-rc1
Included in here are:
- habanalabs driver updates, loads
- mhi bus driver updates
- extcon driver updates
- clk driver updates (approved by the clock maintainer)
- firmware driver updates
- fpga driver updates
- gnss driver updates
- coresight driver updates
- interconnect driver updates
- parport driver updates (it's still alive!)
- nvmem driver updates
- soundwire driver updates
- visorbus driver updates
- w1 driver updates
- various misc driver updates
In short, loads of different driver subsystem updates along with the
drivers as well.
All have been in linux-next for a while with no reported issues"
* tag 'char-misc-5.8-rc1' of git://git.kernel.org/pub/scm/linux/kernel/git/gregkh/char-misc: (233 commits)
habanalabs: correctly cast u64 to void*
habanalabs: initialize variable to default value
extcon: arizona: Fix runtime PM imbalance on error
extcon: max14577: Add proper dt-compatible strings
extcon: adc-jack: Fix an error handling path in 'adc_jack_probe()'
extcon: remove redundant assignment to variable idx
w1: omap-hdq: print dev_err if irq flags are not cleared
w1: omap-hdq: fix interrupt handling which did show spurious timeouts
w1: omap-hdq: fix return value to be -1 if there is a timeout
w1: omap-hdq: cleanup to add missing newline for some dev_dbg
/dev/mem: Revoke mappings when a driver claims the region
misc: xilinx-sdfec: convert get_user_pages() --> pin_user_pages()
misc: xilinx-sdfec: cleanup return value in xsdfec_table_write()
misc: xilinx-sdfec: improve get_user_pages_fast() error handling
nvmem: qfprom: remove incorrect write support
habanalabs: handle MMU cache invalidation timeout
habanalabs: don't allow hard reset with open processes
habanalabs: GAUDI does not support soft-reset
habanalabs: add print for soft reset due to event
habanalabs: improve MMU cache invalidation code
...
Diffstat (limited to 'drivers/hwtracing')
-rw-r--r-- | drivers/hwtracing/coresight/Makefile | 3 | ||||
-rw-r--r-- | drivers/hwtracing/coresight/coresight-cti-platform.c | 11 | ||||
-rw-r--r-- | drivers/hwtracing/coresight/coresight-cti-sysfs.c | 16 | ||||
-rw-r--r-- | drivers/hwtracing/coresight/coresight-cti.c | 232 | ||||
-rw-r--r-- | drivers/hwtracing/coresight/coresight-cti.h | 8 | ||||
-rw-r--r-- | drivers/hwtracing/coresight/coresight-etb10.c | 2 | ||||
-rw-r--r-- | drivers/hwtracing/coresight/coresight-etm3x.c | 2 | ||||
-rw-r--r-- | drivers/hwtracing/coresight/coresight-etm4x-sysfs.c | 2 | ||||
-rw-r--r-- | drivers/hwtracing/coresight/coresight-etm4x.c | 33 | ||||
-rw-r--r-- | drivers/hwtracing/coresight/coresight-platform.c | 91 | ||||
-rw-r--r-- | drivers/hwtracing/coresight/coresight-priv.h | 21 | ||||
-rw-r--r-- | drivers/hwtracing/coresight/coresight-sysfs.c | 204 | ||||
-rw-r--r-- | drivers/hwtracing/coresight/coresight-tmc-etf.c | 16 | ||||
-rw-r--r-- | drivers/hwtracing/coresight/coresight-tmc.c | 2 | ||||
-rw-r--r-- | drivers/hwtracing/coresight/coresight.c | 82 |
15 files changed, 619 insertions, 106 deletions
diff --git a/drivers/hwtracing/coresight/Makefile b/drivers/hwtracing/coresight/Makefile index 0e3e72f0f510..19497d1d92bf 100644 --- a/drivers/hwtracing/coresight/Makefile +++ b/drivers/hwtracing/coresight/Makefile @@ -2,7 +2,8 @@ # # Makefile for CoreSight drivers. # -obj-$(CONFIG_CORESIGHT) += coresight.o coresight-etm-perf.o coresight-platform.o +obj-$(CONFIG_CORESIGHT) += coresight.o coresight-etm-perf.o \ + coresight-platform.o coresight-sysfs.o obj-$(CONFIG_CORESIGHT_LINK_AND_SINK_TMC) += coresight-tmc.o \ coresight-tmc-etf.o \ coresight-tmc-etr.o diff --git a/drivers/hwtracing/coresight/coresight-cti-platform.c b/drivers/hwtracing/coresight/coresight-cti-platform.c index 2fdaeec80ee5..98f830c6ed50 100644 --- a/drivers/hwtracing/coresight/coresight-cti-platform.c +++ b/drivers/hwtracing/coresight/coresight-cti-platform.c @@ -2,11 +2,17 @@ /* * Copyright (c) 2019, The Linaro Limited. All rights reserved. */ +#include <linux/coresight.h> +#include <linux/device.h> +#include <linux/err.h> +#include <linux/of.h> +#include <linux/property.h> +#include <linux/slab.h> #include <dt-bindings/arm/coresight-cti-dt.h> -#include <linux/of.h> #include "coresight-cti.h" +#include "coresight-priv.h" /* Number of CTI signals in the v8 architecturally defined connection */ #define NR_V8PE_IN_SIGS 2 @@ -429,8 +435,7 @@ static int cti_plat_create_impdef_connections(struct device *dev, } /* get the hardware configuration & connection data. */ -int cti_plat_get_hw_data(struct device *dev, - struct cti_drvdata *drvdata) +static int cti_plat_get_hw_data(struct device *dev, struct cti_drvdata *drvdata) { int rc = 0; struct cti_device *cti_dev = &drvdata->ctidev; diff --git a/drivers/hwtracing/coresight/coresight-cti-sysfs.c b/drivers/hwtracing/coresight/coresight-cti-sysfs.c index 1f8fb7c15e80..392757f3a019 100644 --- a/drivers/hwtracing/coresight/coresight-cti-sysfs.c +++ b/drivers/hwtracing/coresight/coresight-cti-sysfs.c @@ -4,7 +4,13 @@ * Author: Mike Leach <mike.leach@linaro.org> */ +#include <linux/atomic.h> #include <linux/coresight.h> +#include <linux/device.h> +#include <linux/io.h> +#include <linux/kernel.h> +#include <linux/spinlock.h> +#include <linux/sysfs.h> #include "coresight-cti.h" @@ -1036,8 +1042,8 @@ static int cti_create_con_sysfs_attr(struct device *dev, enum cti_conn_attr_type attr_type, int attr_idx) { - struct dev_ext_attribute *eattr = 0; - char *name = 0; + struct dev_ext_attribute *eattr; + char *name; eattr = devm_kzalloc(dev, sizeof(struct dev_ext_attribute), GFP_KERNEL); @@ -1139,7 +1145,7 @@ static int cti_create_con_attr_set(struct device *dev, int con_idx, } /* create the array of group pointers for the CTI sysfs groups */ -int cti_create_cons_groups(struct device *dev, struct cti_device *ctidev) +static int cti_create_cons_groups(struct device *dev, struct cti_device *ctidev) { int nr_groups; @@ -1156,8 +1162,8 @@ int cti_create_cons_groups(struct device *dev, struct cti_device *ctidev) int cti_create_cons_sysfs(struct device *dev, struct cti_drvdata *drvdata) { struct cti_device *ctidev = &drvdata->ctidev; - int err = 0, con_idx = 0, i; - struct cti_trig_con *tc = NULL; + int err, con_idx = 0, i; + struct cti_trig_con *tc; err = cti_create_cons_groups(dev, ctidev); if (err) diff --git a/drivers/hwtracing/coresight/coresight-cti.c b/drivers/hwtracing/coresight/coresight-cti.c index aa6e0249bd70..40387d58c8e7 100644 --- a/drivers/hwtracing/coresight/coresight-cti.c +++ b/drivers/hwtracing/coresight/coresight-cti.c @@ -4,7 +4,22 @@ * Author: Mike Leach <mike.leach@linaro.org> */ +#include <linux/amba/bus.h> +#include <linux/atomic.h> +#include <linux/bits.h> +#include <linux/coresight.h> +#include <linux/cpu_pm.h> +#include <linux/cpuhotplug.h> +#include <linux/device.h> +#include <linux/io.h> +#include <linux/kernel.h> +#include <linux/list.h> +#include <linux/mutex.h> +#include <linux/pm_runtime.h> #include <linux/property.h> +#include <linux/spinlock.h> + +#include "coresight-priv.h" #include "coresight-cti.h" /** @@ -19,7 +34,7 @@ */ /* net of CTI devices connected via CTM */ -LIST_HEAD(ect_net); +static LIST_HEAD(ect_net); /* protect the list */ static DEFINE_MUTEX(ect_mutex); @@ -27,6 +42,12 @@ static DEFINE_MUTEX(ect_mutex); #define csdev_to_cti_drvdata(csdev) \ dev_get_drvdata(csdev->dev.parent) +/* power management handling */ +static int nr_cti_cpu; + +/* quick lookup list for CPU bound CTIs when power handling */ +static struct cti_drvdata *cti_cpu_drvdata[NR_CPUS]; + /* * CTI naming. CTI bound to cores will have the name cti_cpu<N> where * N is the CPU ID. System CTIs will have the name cti_sys<I> where I @@ -116,6 +137,35 @@ cti_err_not_enabled: return rc; } +/* re-enable CTI on CPU when using CPU hotplug */ +static void cti_cpuhp_enable_hw(struct cti_drvdata *drvdata) +{ + struct cti_config *config = &drvdata->config; + struct device *dev = &drvdata->csdev->dev; + + pm_runtime_get_sync(dev->parent); + spin_lock(&drvdata->spinlock); + config->hw_powered = true; + + /* no need to do anything if no enable request */ + if (!atomic_read(&drvdata->config.enable_req_count)) + goto cti_hp_not_enabled; + + /* try to claim the device */ + if (coresight_claim_device(drvdata->base)) + goto cti_hp_not_enabled; + + cti_write_all_hw_regs(drvdata); + config->hw_enabled = true; + spin_unlock(&drvdata->spinlock); + return; + + /* did not re-enable due to no claim / no request */ +cti_hp_not_enabled: + spin_unlock(&drvdata->spinlock); + pm_runtime_put(dev->parent); +} + /* disable hardware */ static int cti_disable_hw(struct cti_drvdata *drvdata) { @@ -442,6 +492,34 @@ int cti_channel_setop(struct device *dev, enum cti_chan_set_op op, return err; } +static bool cti_add_sysfs_link(struct cti_drvdata *drvdata, + struct cti_trig_con *tc) +{ + struct coresight_sysfs_link link_info; + int link_err = 0; + + link_info.orig = drvdata->csdev; + link_info.orig_name = tc->con_dev_name; + link_info.target = tc->con_dev; + link_info.target_name = dev_name(&drvdata->csdev->dev); + + link_err = coresight_add_sysfs_link(&link_info); + if (link_err) + dev_warn(&drvdata->csdev->dev, + "Failed to set CTI sysfs link %s<=>%s\n", + link_info.orig_name, link_info.target_name); + return !link_err; +} + +static void cti_remove_sysfs_link(struct cti_trig_con *tc) +{ + struct coresight_sysfs_link link_info; + + link_info.orig_name = tc->con_dev_name; + link_info.target = tc->con_dev; + coresight_remove_sysfs_link(&link_info); +} + /* * Look for a matching connection device name in the list of connections. * If found then swap in the csdev name, set trig con association pointer @@ -452,6 +530,8 @@ cti_match_fixup_csdev(struct cti_device *ctidev, const char *node_name, struct coresight_device *csdev) { struct cti_trig_con *tc; + struct cti_drvdata *drvdata = container_of(ctidev, struct cti_drvdata, + ctidev); list_for_each_entry(tc, &ctidev->trig_cons, node) { if (tc->con_dev_name) { @@ -459,7 +539,12 @@ cti_match_fixup_csdev(struct cti_device *ctidev, const char *node_name, /* match: so swap in csdev name & dev */ tc->con_dev_name = dev_name(&csdev->dev); tc->con_dev = csdev; - return true; + /* try to set sysfs link */ + if (cti_add_sysfs_link(drvdata, tc)) + return true; + /* link failed - remove CTI reference */ + tc->con_dev = NULL; + break; } } } @@ -522,6 +607,7 @@ void cti_remove_assoc_from_csdev(struct coresight_device *csdev) ctidev = &ctidrv->ctidev; list_for_each_entry(tc, &ctidev->trig_cons, node) { if (tc->con_dev == csdev->ect_dev) { + cti_remove_sysfs_link(tc); tc->con_dev = NULL; break; } @@ -543,10 +629,16 @@ static void cti_update_conn_xrefs(struct cti_drvdata *drvdata) struct cti_device *ctidev = &drvdata->ctidev; list_for_each_entry(tc, &ctidev->trig_cons, node) { - if (tc->con_dev) - /* set tc->con_dev->ect_dev */ - coresight_set_assoc_ectdev_mutex(tc->con_dev, + if (tc->con_dev) { + /* if we can set the sysfs link */ + if (cti_add_sysfs_link(drvdata, tc)) + /* set the CTI/csdev association */ + coresight_set_assoc_ectdev_mutex(tc->con_dev, drvdata->csdev); + else + /* otherwise remove reference from CTI */ + tc->con_dev = NULL; + } } } @@ -559,7 +651,113 @@ static void cti_remove_conn_xrefs(struct cti_drvdata *drvdata) if (tc->con_dev) { coresight_set_assoc_ectdev_mutex(tc->con_dev, NULL); + cti_remove_sysfs_link(tc); + tc->con_dev = NULL; + } + } +} + +/** cti PM callbacks **/ +static int cti_cpu_pm_notify(struct notifier_block *nb, unsigned long cmd, + void *v) +{ + struct cti_drvdata *drvdata; + unsigned int cpu = smp_processor_id(); + int notify_res = NOTIFY_OK; + + if (!cti_cpu_drvdata[cpu]) + return NOTIFY_OK; + + drvdata = cti_cpu_drvdata[cpu]; + + if (WARN_ON_ONCE(drvdata->ctidev.cpu != cpu)) + return NOTIFY_BAD; + + spin_lock(&drvdata->spinlock); + + switch (cmd) { + case CPU_PM_ENTER: + /* CTI regs all static - we have a copy & nothing to save */ + drvdata->config.hw_powered = false; + if (drvdata->config.hw_enabled) + coresight_disclaim_device(drvdata->base); + break; + + case CPU_PM_ENTER_FAILED: + drvdata->config.hw_powered = true; + if (drvdata->config.hw_enabled) { + if (coresight_claim_device(drvdata->base)) + drvdata->config.hw_enabled = false; + } + break; + + case CPU_PM_EXIT: + /* write hardware registers to re-enable. */ + drvdata->config.hw_powered = true; + drvdata->config.hw_enabled = false; + + /* check enable reference count to enable HW */ + if (atomic_read(&drvdata->config.enable_req_count)) { + /* check we can claim the device as we re-power */ + if (coresight_claim_device(drvdata->base)) + goto cti_notify_exit; + + drvdata->config.hw_enabled = true; + cti_write_all_hw_regs(drvdata); + } + break; + + default: + notify_res = NOTIFY_DONE; + break; + } + +cti_notify_exit: + spin_unlock(&drvdata->spinlock); + return notify_res; +} + +static struct notifier_block cti_cpu_pm_nb = { + .notifier_call = cti_cpu_pm_notify, +}; + +/* CPU HP handlers */ +static int cti_starting_cpu(unsigned int cpu) +{ + struct cti_drvdata *drvdata = cti_cpu_drvdata[cpu]; + + if (!drvdata) + return 0; + + cti_cpuhp_enable_hw(drvdata); + return 0; +} + +static int cti_dying_cpu(unsigned int cpu) +{ + struct cti_drvdata *drvdata = cti_cpu_drvdata[cpu]; + + if (!drvdata) + return 0; + + spin_lock(&drvdata->spinlock); + drvdata->config.hw_powered = false; + coresight_disclaim_device(drvdata->base); + spin_unlock(&drvdata->spinlock); + return 0; +} + +/* release PM registrations */ +static void cti_pm_release(struct cti_drvdata *drvdata) +{ + if (drvdata->ctidev.cpu >= 0) { + if (--nr_cti_cpu == 0) { + cpu_pm_unregister_notifier(&cti_cpu_pm_nb); + + cpuhp_remove_state_nocalls( + CPUHP_AP_ARM_CORESIGHT_CTI_STARTING); } + cti_cpu_drvdata[drvdata->ctidev.cpu] = NULL; } } @@ -578,12 +776,12 @@ int cti_disable(struct coresight_device *csdev) return cti_disable_hw(drvdata); } -const struct coresight_ops_ect cti_ops_ect = { +static const struct coresight_ops_ect cti_ops_ect = { .enable = cti_enable, .disable = cti_disable, }; -const struct coresight_ops cti_ops = { +static const struct coresight_ops cti_ops = { .ect_ops = &cti_ops_ect, }; @@ -598,6 +796,7 @@ static void cti_device_release(struct device *dev) mutex_lock(&ect_mutex); cti_remove_conn_xrefs(drvdata); + cti_pm_release(drvdata); /* remove from the list */ list_for_each_entry_safe(ect_item, ect_tmp, &ect_net, node) { @@ -673,6 +872,24 @@ static int cti_probe(struct amba_device *adev, const struct amba_id *id) goto err_out; } + /* setup CPU power management handling for CPU bound CTI devices. */ + if (drvdata->ctidev.cpu >= 0) { + cti_cpu_drvdata[drvdata->ctidev.cpu] = drvdata; + if (!nr_cti_cpu++) { + cpus_read_lock(); + ret = cpuhp_setup_state_nocalls_cpuslocked( + CPUHP_AP_ARM_CORESIGHT_CTI_STARTING, + "arm/coresight_cti:starting", + cti_starting_cpu, cti_dying_cpu); + + if (!ret) + ret = cpu_pm_register_notifier(&cti_cpu_pm_nb); + cpus_read_unlock(); + if (ret) + goto err_out; + } + } + /* create dynamic attributes for connections */ ret = cti_create_cons_sysfs(dev, drvdata); if (ret) { @@ -711,6 +928,7 @@ static int cti_probe(struct amba_device *adev, const struct amba_id *id) return 0; err_out: + cti_pm_release(drvdata); return ret; } diff --git a/drivers/hwtracing/coresight/coresight-cti.h b/drivers/hwtracing/coresight/coresight-cti.h index 004df3ab9dd0..acf7b545e6b9 100644 --- a/drivers/hwtracing/coresight/coresight-cti.h +++ b/drivers/hwtracing/coresight/coresight-cti.h @@ -7,8 +7,14 @@ #ifndef _CORESIGHT_CORESIGHT_CTI_H #define _CORESIGHT_CORESIGHT_CTI_H -#include <asm/local.h> +#include <linux/coresight.h> +#include <linux/device.h> +#include <linux/fwnode.h> +#include <linux/list.h> #include <linux/spinlock.h> +#include <linux/sysfs.h> +#include <linux/types.h> + #include "coresight-priv.h" /* diff --git a/drivers/hwtracing/coresight/coresight-etb10.c b/drivers/hwtracing/coresight/coresight-etb10.c index 3810290e6d07..03e3f2590191 100644 --- a/drivers/hwtracing/coresight/coresight-etb10.c +++ b/drivers/hwtracing/coresight/coresight-etb10.c @@ -717,7 +717,7 @@ static const struct attribute_group coresight_etb_mgmt_group = { .name = "mgmt", }; -const struct attribute_group *coresight_etb_groups[] = { +static const struct attribute_group *coresight_etb_groups[] = { &coresight_etb_group, &coresight_etb_mgmt_group, NULL, diff --git a/drivers/hwtracing/coresight/coresight-etm3x.c b/drivers/hwtracing/coresight/coresight-etm3x.c index e2cb6873c3f2..bf22dcfd3327 100644 --- a/drivers/hwtracing/coresight/coresight-etm3x.c +++ b/drivers/hwtracing/coresight/coresight-etm3x.c @@ -504,7 +504,7 @@ static int etm_enable_perf(struct coresight_device *csdev, static int etm_enable_sysfs(struct coresight_device *csdev) { struct etm_drvdata *drvdata = dev_get_drvdata(csdev->dev.parent); - struct etm_enable_arg arg = { 0 }; + struct etm_enable_arg arg = { }; int ret; spin_lock(&drvdata->spinlock); diff --git a/drivers/hwtracing/coresight/coresight-etm4x-sysfs.c b/drivers/hwtracing/coresight/coresight-etm4x-sysfs.c index ce41482431f9..b673e738bc9a 100644 --- a/drivers/hwtracing/coresight/coresight-etm4x-sysfs.c +++ b/drivers/hwtracing/coresight/coresight-etm4x-sysfs.c @@ -205,7 +205,7 @@ static ssize_t reset_store(struct device *dev, * started state. ARM recommends start-stop logic is set before * each trace run. */ - config->vinst_ctrl |= BIT(0); + config->vinst_ctrl = BIT(0); if (drvdata->nr_addr_cmp == true) { config->mode |= ETM_MODE_VIEWINST_STARTSTOP; /* SSSTATUS, bit[9] */ diff --git a/drivers/hwtracing/coresight/coresight-etm4x.c b/drivers/hwtracing/coresight/coresight-etm4x.c index a90d757f7043..747afc875f91 100644 --- a/drivers/hwtracing/coresight/coresight-etm4x.c +++ b/drivers/hwtracing/coresight/coresight-etm4x.c @@ -412,7 +412,7 @@ out: static int etm4_enable_sysfs(struct coresight_device *csdev) { struct etmv4_drvdata *drvdata = dev_get_drvdata(csdev->dev.parent); - struct etm4_enable_arg arg = { 0 }; + struct etm4_enable_arg arg = { }; int ret; spin_lock(&drvdata->spinlock); @@ -791,7 +791,7 @@ static void etm4_set_default_config(struct etmv4_config *config) config->ts_ctrl = 0x0; /* TRCVICTLR::EVENT = 0x01, select the always on logic */ - config->vinst_ctrl |= BIT(0); + config->vinst_ctrl = BIT(0); } static u64 etm4_get_ns_access_type(struct etmv4_config *config) @@ -894,17 +894,8 @@ static void etm4_set_start_stop_filter(struct etmv4_config *config, static void etm4_set_default_filter(struct etmv4_config *config) { - u64 start, stop; - - /* - * Configure address range comparator '0' to encompass all - * possible addresses. - */ - start = 0x0; - stop = ~0x0; - - etm4_set_comparator_filter(config, start, stop, - ETM_DEFAULT_ADDR_COMP); + /* Trace everything 'default' filter achieved by no filtering */ + config->viiectlr = 0x0; /* * TRCVICTLR::SSSTATUS == 1, the start-stop logic is @@ -925,11 +916,9 @@ static void etm4_set_default(struct etmv4_config *config) /* * Make default initialisation trace everything * - * Select the "always true" resource selector on the - * "Enablign Event" line and configure address range comparator - * '0' to trace all the possible address range. From there - * configure the "include/exclude" engine to include address - * range comparator '0'. + * This is done by a minimum default config sufficient to enable + * full instruction trace - with a default filter for trace all + * achieved by having no filtering. */ etm4_set_default_config(config); etm4_set_default_filter(config); @@ -1527,6 +1516,7 @@ static int etm4_probe(struct amba_device *adev, const struct amba_id *id) return 0; err_arch_supported: + etmdrvdata[drvdata->cpu] = NULL; if (--etm4_count == 0) { etm4_cpu_pm_unregister(); @@ -1552,10 +1542,13 @@ static const struct amba_id etm4_ids[] = { CS_AMBA_ID(0x000bb95a), /* Cortex-A72 */ CS_AMBA_ID(0x000bb959), /* Cortex-A73 */ CS_AMBA_UCI_ID(0x000bb9da, uci_id_etm4),/* Cortex-A35 */ + CS_AMBA_UCI_ID(0x000bbd0c, uci_id_etm4),/* Neoverse N1 */ CS_AMBA_UCI_ID(0x000f0205, uci_id_etm4),/* Qualcomm Kryo */ CS_AMBA_UCI_ID(0x000f0211, uci_id_etm4),/* Qualcomm Kryo */ - CS_AMBA_ID(0x000bb802), /* Qualcomm Kryo 385 Cortex-A55 */ - CS_AMBA_ID(0x000bb803), /* Qualcomm Kryo 385 Cortex-A75 */ + CS_AMBA_UCI_ID(0x000bb802, uci_id_etm4),/* Qualcomm Kryo 385 Cortex-A55 */ + CS_AMBA_UCI_ID(0x000bb803, uci_id_etm4),/* Qualcomm Kryo 385 Cortex-A75 */ + CS_AMBA_UCI_ID(0x000bb805, uci_id_etm4),/* Qualcomm Kryo 4XX Cortex-A55 */ + CS_AMBA_UCI_ID(0x000bb804, uci_id_etm4),/* Qualcomm Kryo 4XX Cortex-A76 */ CS_AMBA_UCI_ID(0x000cc0af, uci_id_etm4),/* Marvell ThunderX2 */ {}, }; diff --git a/drivers/hwtracing/coresight/coresight-platform.c b/drivers/hwtracing/coresight/coresight-platform.c index 43418a2126ff..e4912abda3aa 100644 --- a/drivers/hwtracing/coresight/coresight-platform.c +++ b/drivers/hwtracing/coresight/coresight-platform.c @@ -87,6 +87,7 @@ static void of_coresight_get_ports_legacy(const struct device_node *node, int *nr_inport, int *nr_outport) { struct device_node *ep = NULL; + struct of_endpoint endpoint; int in = 0, out = 0; do { @@ -94,10 +95,16 @@ static void of_coresight_get_ports_legacy(const struct device_node *node, if (!ep) break; - if (of_coresight_legacy_ep_is_input(ep)) - in++; - else - out++; + if (of_graph_parse_endpoint(ep, &endpoint)) + continue; + + if (of_coresight_legacy_ep_is_input(ep)) { + in = (endpoint.port + 1 > in) ? + endpoint.port + 1 : in; + } else { + out = (endpoint.port + 1) > out ? + endpoint.port + 1 : out; + } } while (ep); @@ -137,9 +144,16 @@ of_coresight_count_ports(struct device_node *port_parent) { int i = 0; struct device_node *ep = NULL; + struct of_endpoint endpoint; + + while ((ep = of_graph_get_next_endpoint(port_parent, ep))) { + /* Defer error handling to parsing */ + if (of_graph_parse_endpoint(ep, &endpoint)) + continue; + if (endpoint.port + 1 > i) + i = endpoint.port + 1; + } - while ((ep = of_graph_get_next_endpoint(port_parent, ep))) - i++; return i; } @@ -191,14 +205,12 @@ static int of_coresight_get_cpu(struct device *dev) * Parses the local port, remote device name and the remote port. * * Returns : - * 1 - If the parsing is successful and a connection record - * was created for an output connection. * 0 - If the parsing completed without any fatal errors. * -Errno - Fatal error, abort the scanning. */ static int of_coresight_parse_endpoint(struct device *dev, struct device_node *ep, - struct coresight_connection *conn) + struct coresight_platform_data *pdata) { int ret = 0; struct of_endpoint endpoint, rendpoint; @@ -206,6 +218,7 @@ static int of_coresight_parse_endpoint(struct device *dev, struct device_node *rep = NULL; struct device *rdev = NULL; struct fwnode_handle *rdev_fwnode; + struct coresight_connection *conn; do { /* Parse the local port details */ @@ -232,6 +245,13 @@ static int of_coresight_parse_endpoint(struct device *dev, break; } + conn = &pdata->conns[endpoint.port]; + if (conn->child_fwnode) { + dev_warn(dev, "Duplicate output port %d\n", + endpoint.port); + ret = -EINVAL; + break; + } conn->outport = endpoint.port; /* * Hold the refcount to the target device. This could be @@ -244,7 +264,6 @@ static int of_coresight_parse_endpoint(struct device *dev, conn->child_fwnode = fwnode_handle_get(rdev_fwnode); conn->child_port = rendpoint.port; /* Connection record updated */ - ret = 1; } while (0); of_node_put(rparent); @@ -258,7 +277,6 @@ static int of_get_coresight_platform_data(struct device *dev, struct coresight_platform_data *pdata) { int ret = 0; - struct coresight_connection *conn; struct device_node *ep = NULL; const struct device_node *parent = NULL; bool legacy_binding = false; @@ -287,8 +305,6 @@ static int of_get_coresight_platform_data(struct device *dev, dev_warn_once(dev, "Uses obsolete Coresight DT bindings\n"); } - conn = pdata->conns; - /* Iterate through each output port to discover topology */ while ((ep = of_graph_get_next_endpoint(parent, ep))) { /* @@ -300,15 +316,9 @@ static int of_get_coresight_platform_data(struct device *dev, if (legacy_binding && of_coresight_legacy_ep_is_input(ep)) continue; - ret = of_coresight_parse_endpoint(dev, ep, conn); - switch (ret) { - case 1: - conn++; /* Fall through */ - case 0: - break; - default: + ret = of_coresight_parse_endpoint(dev, ep, pdata); + if (ret) return ret; - } } return 0; @@ -501,7 +511,7 @@ static inline bool acpi_validate_dsd_graph(const union acpi_object *graph) } /* acpi_get_dsd_graph - Find the _DSD Graph property for the given device. */ -const union acpi_object * +static const union acpi_object * acpi_get_dsd_graph(struct acpi_device *adev) { int i; @@ -564,7 +574,7 @@ acpi_validate_coresight_graph(const union acpi_object *cs_graph) * Returns the pointer to the CoreSight Graph Package when found. Otherwise * returns NULL. */ -const union acpi_object * +static const union acpi_object * acpi_get_coresight_graph(struct acpi_device *adev) { const union acpi_object *graph_list, *graph; @@ -647,6 +657,16 @@ static int acpi_coresight_parse_link(struct acpi_device *adev, * coresight_remove_match(). */ conn->child_fwnode = fwnode_handle_get(&r_adev->fwnode); + } else if (dir == ACPI_CORESIGHT_LINK_SLAVE) { + /* + * We are only interested in the port number + * for the input ports at this component. + * Store the port number in child_port. + */ + conn->child_port = fields[0].integer.value; + } else { + /* Invalid direction */ + return -EINVAL; } return dir; @@ -692,10 +712,20 @@ static int acpi_coresight_parse_graph(struct acpi_device *adev, return dir; if (dir == ACPI_CORESIGHT_LINK_MASTER) { - pdata->nr_outport++; + if (ptr->outport > pdata->nr_outport) + pdata->nr_outport = ptr->outport; ptr++; } else { - pdata->nr_inport++; + WARN_ON(pdata->nr_inport == ptr->child_port); + /* + * We do not track input port connections for a device. + * However we need the highest port number described, + * which can be recorded now and reuse this connection + * record for an output connection. Hence, do not move + * the ptr for input connections + */ + if (ptr->child_port > pdata->nr_inport) + pdata->nr_inport = ptr->child_port; } } @@ -704,8 +734,13 @@ static int acpi_coresight_parse_graph(struct acpi_device *adev, return rc; /* Copy the connection information to the final location */ - for (i = 0; i < pdata->nr_outport; i++) - pdata->conns[i] = conns[i]; + for (i = 0; conns + i < ptr; i++) { + int port = conns[i].outport; + + /* Duplicate output port */ + WARN_ON(pdata->conns[port].child_fwnode); + pdata->conns[port] = conns[i]; + } devm_kfree(&adev->dev, conns); return 0; @@ -822,7 +857,7 @@ coresight_get_platform_data(struct device *dev) error: if (!IS_ERR_OR_NULL(pdata)) /* Cleanup the connection information */ - coresight_release_platform_data(pdata); + coresight_release_platform_data(NULL, pdata); return ERR_PTR(ret); } EXPORT_SYMBOL_GPL(coresight_get_platform_data); diff --git a/drivers/hwtracing/coresight/coresight-priv.h b/drivers/hwtracing/coresight/coresight-priv.h index 890f9a5c97c6..36c943ae94d5 100644 --- a/drivers/hwtracing/coresight/coresight-priv.h +++ b/drivers/hwtracing/coresight/coresight-priv.h @@ -153,6 +153,15 @@ struct coresight_device *coresight_get_sink_by_id(u32 id); struct list_head *coresight_build_path(struct coresight_device *csdev, struct coresight_device *sink); void coresight_release_path(struct list_head *path); +int coresight_add_sysfs_link(struct coresight_sysfs_link *info); +void coresight_remove_sysfs_link(struct coresight_sysfs_link *info); +int coresight_create_conns_sysfs_group(struct coresight_device *csdev); +void coresight_remove_conns_sysfs_group(struct coresight_device *csdev); +int coresight_make_links(struct coresight_device *orig, + struct coresight_connection *conn, + struct coresight_device *target); +void coresight_remove_links(struct coresight_device *orig, + struct coresight_connection *conn); #ifdef CONFIG_CORESIGHT_SOURCE_ETM3X extern int etm_readl_cp14(u32 off, unsigned int *val); @@ -206,12 +215,16 @@ cti_remove_assoc_from_csdev(struct coresight_device *csdev) {} /* extract the data value from a UCI structure given amba_id pointer. */ static inline void *coresight_get_uci_data(const struct amba_id *id) { - if (id->data) - return ((struct amba_cs_uci_id *)(id->data))->data; - return 0; + struct amba_cs_uci_id *uci_id = id->data; + + if (!uci_id) + return NULL; + + return uci_id->data; } -void coresight_release_platform_data(struct coresight_platform_data *pdata); +void coresight_release_platform_data(struct coresight_device *csdev, + struct coresight_platform_data *pdata); struct coresight_device * coresight_find_csdev_by_fwnode(struct fwnode_handle *r_fwnode); void coresight_set_assoc_ectdev_mutex(struct coresight_device *csdev, diff --git a/drivers/hwtracing/coresight/coresight-sysfs.c b/drivers/hwtracing/coresight/coresight-sysfs.c new file mode 100644 index 000000000000..82afeaf2ccc4 --- /dev/null +++ b/drivers/hwtracing/coresight/coresight-sysfs.c @@ -0,0 +1,204 @@ +// SPDX-License-Identifier: GPL-2.0 +/* + * Copyright (c) 2019, Linaro Limited, All rights reserved. + * Author: Mike Leach <mike.leach@linaro.org> + */ + +#include <linux/device.h> +#include <linux/kernel.h> + +#include "coresight-priv.h" + +/* + * Connections group - links attribute. + * Count of created links between coresight components in the group. + */ +static ssize_t nr_links_show(struct device *dev, + |