From 5b7c4cabbb65f5c469464da6c5f614cbd7f730f2 Mon Sep 17 00:00:00 2001 From: Linus Torvalds Date: Tue, 21 Feb 2023 18:24:12 -0800 Subject: Merge tag 'net-next-6.3' of git://git.kernel.org/pub/scm/linux/kernel/git/netdev/net-next Pull networking updates from Jakub Kicinski: "Core: - Add dedicated kmem_cache for typical/small skb->head, avoid having to access struct page at kfree time, and improve memory use. - Introduce sysctl to set default RPS configuration for new netdevs. - Define Netlink protocol specification format which can be used to describe messages used by each family and auto-generate parsers. Add tools for generating kernel data structures and uAPI headers. - Expose all net/core sysctls inside netns. - Remove 4s sleep in netpoll if carrier is instantly detected on boot. - Add configurable limit of MDB entries per port, and port-vlan. - Continue populating drop reasons throughout the stack. - Retire a handful of legacy Qdiscs and classifiers. Protocols: - Support IPv4 big TCP (TSO frames larger than 64kB). - Add IP_LOCAL_PORT_RANGE socket option, to control local port range on socket by socket basis. - Track and report in procfs number of MPTCP sockets used. - Support mixing IPv4 and IPv6 flows in the in-kernel MPTCP path manager. - IPv6: don't check net.ipv6.route.max_size and rely on garbage collection to free memory (similarly to IPv4). - Support Penultimate Segment Pop (PSP) flavor in SRv6 (RFC8986). - ICMP: add per-rate limit counters. - Add support for user scanning requests in ieee802154. - Remove static WEP support. - Support minimal Wi-Fi 7 Extremely High Throughput (EHT) rate reporting. - WiFi 7 EHT channel puncturing support (client & AP). BPF: - Add a rbtree data structure following the "next-gen data structure" precedent set by recently added linked list, that is, by using kfunc + kptr instead of adding a new BPF map type. - Expose XDP hints via kfuncs with initial support for RX hash and timestamp metadata. - Add BPF_F_NO_TUNNEL_KEY extension to bpf_skb_set_tunnel_key to better support decap on GRE tunnel devices not operating in collect metadata. - Improve x86 JIT's codegen for PROBE_MEM runtime error checks. - Remove the need for trace_printk_lock for bpf_trace_printk and bpf_trace_vprintk helpers. - Extend libbpf's bpf_tracing.h support for tracing arguments of kprobes/uprobes and syscall as a special case. - Significantly reduce the search time for module symbols by livepatch and BPF. - Enable cpumasks to be used as kptrs, which is useful for tracing programs tracking which tasks end up running on which CPUs in different time intervals. - Add support for BPF trampoline on s390x and riscv64. - Add capability to export the XDP features supported by the NIC. - Add __bpf_kfunc tag for marking kernel functions as kfuncs. - Add cgroup.memory=nobpf kernel parameter option to disable BPF memory accounting for container environments. Netfilter: - Remove the CLUSTERIP target. It has been marked as obsolete for years, and we still have WARN splats wrt races of the out-of-band /proc interface installed by this target. - Add 'destroy' commands to nf_tables. They are identical to the existing 'delete' commands, but do not return an error if the referenced object (set, chain, rule...) did not exist. Driver API: - Improve cpumask_local_spread() locality to help NICs set the right IRQ affinity on AMD platforms. - Separate C22 and C45 MDIO bus transactions more clearly. - Introduce new DCB table to control DSCP rewrite on egress. - Support configuration of Physical Layer Collision Avoidance (PLCA) Reconciliation Sublayer (RS) (802.3cg-2019). Modern version of shared medium Ethernet. - Support for MAC Merge layer (IEEE 802.3-2018 clause 99). Allowing preemption of low priority frames by high priority frames. - Add support for controlling MACSec offload using netlink SET. - Rework devlink instance refcounts to allow registration and de-registration under the instance lock. Split the code into multiple files, drop some of the unnecessarily granular locks and factor out common parts of netlink operation handling. - Add TX frame aggregation parameters (for USB drivers). - Add a new attr TCA_EXT_WARN_MSG to report TC (offload) warning messages with notifications for debug. - Allow offloading of UDP NEW connections via act_ct. - Add support for per action HW stats in TC. - Support hardware miss to TC action (continue processing in SW from a specific point in the action chain). - Warn if old Wireless Extension user space interface is used with modern cfg80211/mac80211 drivers. Do not support Wireless Extensions for Wi-Fi 7 devices at all. Everyone should switch to using nl80211 interface instead. - Improve the CAN bit timing configuration. Use extack to return error messages directly to user space, update the SJW handling, including the definition of a new default value that will benefit CAN-FD controllers, by increasing their oscillator tolerance. New hardware / drivers: - Ethernet: - nVidia BlueField-3 support (control traffic driver) - Ethernet support for imx93 SoCs - Motorcomm yt8531 gigabit Ethernet PHY - onsemi NCN26000 10BASE-T1S PHY (with support for PLCA) - Microchip LAN8841 PHY (incl. cable diagnostics and PTP) - Amlogic gxl MDIO mux - WiFi: - RealTek RTL8188EU (rtl8xxxu) - Qualcomm Wi-Fi 7 devices (ath12k) - CAN: - Renesas R-Car V4H Drivers: - Bluetooth: - Set Per Platform Antenna Gain (PPAG) for Intel controllers. - Ethernet NICs: - Intel (1G, igc): - support TSN / Qbv / packet scheduling features of i226 model - Intel (100G, ice): - use GNSS subsystem instead of TTY - multi-buffer XDP support - extend support for GPIO pins to E823 devices - nVidia/Mellanox: - update the shared buffer configuration on PFC commands - implement PTP adjphase function for HW offset control - TC support for Geneve and GRE with VF tunnel offload - more efficient crypto key management method - multi-port eswitch support - Netronome/Corigine: - add DCB IEEE support - support IPsec offloading for NFP3800 - Freescale/NXP (enetc): - support XDP_REDIRECT for XDP non-linear buffers - improve reconfig, avoid link flap and waiting for idle - support MAC Merge layer - Other NICs: - sfc/ef100: add basic devlink support for ef100 - ionic: rx_push mode operation (writing descriptors via MMIO) - bnxt: use the auxiliary bus abstraction for RDMA - r8169: disable ASPM and reset bus in case of tx timeout - cpsw: support QSGMII mode for J721e CPSW9G - cpts: support pulse-per-second output - ngbe: add an mdio bus driver - usbnet: optimize usbnet_bh() by avoiding unnecessary queuing - r8152: handle devices with FW with NCM support - amd-xgbe: support 10Mbps, 2.5GbE speeds and rx-adaptation - virtio-net: support multi buffer XDP - virtio/vsock: replace virtio_vsock_pkt with sk_buff - tsnep: XDP support - Ethernet high-speed switches: - nVidia/Mellanox (mlxsw): - add support for latency TLV (in FW control messages) - Microchip (sparx5): - separate explicit and implicit traffic forwarding rules, make the implicit rules always active - add support for egress DSCP rewrite - IS0 VCAP support (Ingress Classification) - IS2 VCAP filters (protos, L3 addrs, L4 ports, flags, ToS etc.) - ES2 VCAP support (Egress Access Control) - support for Per-Stream Filtering and Policing (802.1Q, 8.6.5.1) - Ethernet embedded switches: - Marvell (mv88e6xxx): - add MAB (port auth) offload support - enable PTP receive for mv88e6390 - NXP (ocelot): - support MAC Merge layer - support for the the vsc7512 internal copper phys - Microchip: - lan9303: convert to PHYLINK - lan966x: support TC flower filter statistics - lan937x: PTP support for KSZ9563/KSZ8563 and LAN937x - lan937x: support Credit Based Shaper configuration - ksz9477: support Energy Efficient Ethernet - other: - qca8k: convert to regmap read/write API, use bulk operations - rswitch: Improve TX timestamp accuracy - Intel WiFi (iwlwifi): - EHT (Wi-Fi 7) rate reporting - STEP equalizer support: transfer some STEP (connection to radio on platforms with integrated wifi) related parameters from the BIOS to the firmware. - Qualcomm 802.11ax WiFi (ath11k): - IPQ5018 support - Fine Timing Measurement (FTM) responder role support - channel 177 support - MediaTek WiFi (mt76): - per-PHY LED support - mt7996: EHT (Wi-Fi 7) support - Wireless Ethernet Dispatch (WED) reset support - switch to using page pool allocator - RealTek WiFi (rtw89): - support new version of Bluetooth co-existance - Mobile: - rmnet: support TX aggregation" * tag 'net-next-6.3' of git://git.kernel.org/pub/scm/linux/kernel/git/netdev/net-next: (1872 commits) page_pool: add a comment explaining the fragment counter usage net: ethtool: fix __ethtool_dev_mm_supported() implementation ethtool: pse-pd: Fix double word in comments xsk: add linux/vmalloc.h to xsk.c sefltests: netdevsim: wait for devlink instance after netns removal selftest: fib_tests: Always cleanup before exit net/mlx5e: Align IPsec ASO result memory to be as required by hardware net/mlx5e: TC, Set CT miss to the specific ct action instance net/mlx5e: Rename CHAIN_TO_REG to MAPPED_OBJ_TO_REG net/mlx5: Refactor tc miss handling to a single function net/mlx5: Kconfig: Make tc offload depend on tc skb extension net/sched: flower: Support hardware miss to tc action net/sched: flower: Move filter handle initialization earlier net/sched: cls_api: Support hardware miss to tc action net/sched: Rename user cookie and act cookie sfc: fix builds without CONFIG_RTC_LIB sfc: clean up some inconsistent indentings net/mlx4_en: Introduce flexible array to silence overflow warning net: lan966x: Fix possible deadlock inside PTP net/ulp: Remove redundant ->clone() test in inet_clone_ulp(). ... --- .../hwtracing/coresight/coresight-cti-platform.c | 490 +++++++++++++++++++++ 1 file changed, 490 insertions(+) create mode 100644 drivers/hwtracing/coresight/coresight-cti-platform.c (limited to 'drivers/hwtracing/coresight/coresight-cti-platform.c') diff --git a/drivers/hwtracing/coresight/coresight-cti-platform.c b/drivers/hwtracing/coresight/coresight-cti-platform.c new file mode 100644 index 000000000..ccef04f27 --- /dev/null +++ b/drivers/hwtracing/coresight/coresight-cti-platform.c @@ -0,0 +1,490 @@ +// SPDX-License-Identifier: GPL-2.0 +/* + * Copyright (c) 2019, The Linaro Limited. All rights reserved. + */ +#include +#include +#include +#include +#include +#include + +#include + +#include "coresight-cti.h" +#include "coresight-priv.h" + +/* Number of CTI signals in the v8 architecturally defined connection */ +#define NR_V8PE_IN_SIGS 2 +#define NR_V8PE_OUT_SIGS 3 +#define NR_V8ETM_INOUT_SIGS 4 + +/* CTI device tree trigger connection node keyword */ +#define CTI_DT_CONNS "trig-conns" + +/* CTI device tree connection property keywords */ +#define CTI_DT_V8ARCH_COMPAT "arm,coresight-cti-v8-arch" +#define CTI_DT_CSDEV_ASSOC "arm,cs-dev-assoc" +#define CTI_DT_TRIGIN_SIGS "arm,trig-in-sigs" +#define CTI_DT_TRIGOUT_SIGS "arm,trig-out-sigs" +#define CTI_DT_TRIGIN_TYPES "arm,trig-in-types" +#define CTI_DT_TRIGOUT_TYPES "arm,trig-out-types" +#define CTI_DT_FILTER_OUT_SIGS "arm,trig-filters" +#define CTI_DT_CONN_NAME "arm,trig-conn-name" +#define CTI_DT_CTM_ID "arm,cti-ctm-id" + +#ifdef CONFIG_OF +/* + * CTI can be bound to a CPU, or a system device. + * CPU can be declared at the device top level or in a connections node + * so need to check relative to node not device. + */ +static int of_cti_get_cpu_at_node(const struct device_node *node) +{ + int cpu; + struct device_node *dn; + + if (node == NULL) + return -1; + + dn = of_parse_phandle(node, "cpu", 0); + /* CTI affinity defaults to no cpu */ + if (!dn) + return -1; + cpu = of_cpu_node_to_id(dn); + of_node_put(dn); + + /* No Affinity if no cpu nodes are found */ + return (cpu < 0) ? -1 : cpu; +} + +#else +static int of_cti_get_cpu_at_node(const struct device_node *node) +{ + return -1; +} + +#endif + +/* + * CTI can be bound to a CPU, or a system device. + * CPU can be declared at the device top level or in a connections node + * so need to check relative to node not device. + */ +static int cti_plat_get_cpu_at_node(struct fwnode_handle *fwnode) +{ + if (is_of_node(fwnode)) + return of_cti_get_cpu_at_node(to_of_node(fwnode)); + return -1; +} + +const char *cti_plat_get_node_name(struct fwnode_handle *fwnode) +{ + if (is_of_node(fwnode)) + return of_node_full_name(to_of_node(fwnode)); + return "unknown"; +} + +/* + * Extract a name from the fwnode. + * If the device associated with the node is a coresight_device, then return + * that name and the coresight_device pointer, otherwise return the node name. + */ +static const char * +cti_plat_get_csdev_or_node_name(struct fwnode_handle *fwnode, + struct coresight_device **csdev) +{ + const char *name = NULL; + *csdev = coresight_find_csdev_by_fwnode(fwnode); + if (*csdev) + name = dev_name(&(*csdev)->dev); + else + name = cti_plat_get_node_name(fwnode); + return name; +} + +static bool cti_plat_node_name_eq(struct fwnode_handle *fwnode, + const char *name) +{ + if (is_of_node(fwnode)) + return of_node_name_eq(to_of_node(fwnode), name); + return false; +} + +static int cti_plat_create_v8_etm_connection(struct device *dev, + struct cti_drvdata *drvdata) +{ + int ret = -ENOMEM, i; + struct fwnode_handle *root_fwnode, *cs_fwnode; + const char *assoc_name = NULL; + struct coresight_device *csdev; + struct cti_trig_con *tc = NULL; + + root_fwnode = dev_fwnode(dev); + if (IS_ERR_OR_NULL(root_fwnode)) + return -EINVAL; + + /* Can optionally have an etm node - return if not */ + cs_fwnode = fwnode_find_reference(root_fwnode, CTI_DT_CSDEV_ASSOC, 0); + if (IS_ERR(cs_fwnode)) + return 0; + + /* allocate memory */ + tc = cti_allocate_trig_con(dev, NR_V8ETM_INOUT_SIGS, + NR_V8ETM_INOUT_SIGS); + if (!tc) + goto create_v8_etm_out; + + /* build connection data */ + tc->con_in->used_mask = 0xF0; /* sigs <4,5,6,7> */ + tc->con_out->used_mask = 0xF0; /* sigs <4,5,6,7> */ + + /* + * The EXTOUT type signals from the ETM are connected to a set of input + * triggers on the CTI, the EXTIN being connected to output triggers. + */ + for (i = 0; i < NR_V8ETM_INOUT_SIGS; i++) { + tc->con_in->sig_types[i] = ETM_EXTOUT; + tc->con_out->sig_types[i] = ETM_EXTIN; + } + + /* + * We look to see if the ETM coresight device associated with this + * handle has been registered with the system - i.e. probed before + * this CTI. If so csdev will be non NULL and we can use the device + * name and pass the csdev to the connection entry function where + * the association will be recorded. + * If not, then simply record the name in the connection data, the + * probing of the ETM will call into the CTI driver API to update the + * association then. + */ + assoc_name = cti_plat_get_csdev_or_node_name(cs_fwnode, &csdev); + ret = cti_add_connection_entry(dev, drvdata, tc, csdev, assoc_name); + +create_v8_etm_out: + fwnode_handle_put(cs_fwnode); + return ret; +} + +/* + * Create an architecturally defined v8 connection + * must have a cpu, can have an ETM. + */ +static int cti_plat_create_v8_connections(struct device *dev, + struct cti_drvdata *drvdata) +{ + struct cti_device *cti_dev = &drvdata->ctidev; + struct cti_trig_con *tc = NULL; + int cpuid = 0; + char cpu_name_str[16]; + int ret = -ENOMEM; + + /* Must have a cpu node */ + cpuid = cti_plat_get_cpu_at_node(dev_fwnode(dev)); + if (cpuid < 0) { + dev_warn(dev, + "ARM v8 architectural CTI connection: missing cpu\n"); + return -EINVAL; + } + cti_dev->cpu = cpuid; + + /* Allocate the v8 cpu connection memory */ + tc = cti_allocate_trig_con(dev, NR_V8PE_IN_SIGS, NR_V8PE_OUT_SIGS); + if (!tc) + goto of_create_v8_out; + + /* Set the v8 PE CTI connection data */ + tc->con_in->used_mask = 0x3; /* sigs <0 1> */ + tc->con_in->sig_types[0] = PE_DBGTRIGGER; + tc->con_in->sig_types[1] = PE_PMUIRQ; + tc->con_out->used_mask = 0x7; /* sigs <0 1 2 > */ + tc->con_out->sig_types[0] = PE_EDBGREQ; + tc->con_out->sig_types[1] = PE_DBGRESTART; + tc->con_out->sig_types[2] = PE_CTIIRQ; + scnprintf(cpu_name_str, sizeof(cpu_name_str), "cpu%d", cpuid); + + ret = cti_add_connection_entry(dev, drvdata, tc, NULL, cpu_name_str); + if (ret) + goto of_create_v8_out; + + /* Create the v8 ETM associated connection */ + ret = cti_plat_create_v8_etm_connection(dev, drvdata); + if (ret) + goto of_create_v8_out; + + /* filter pe_edbgreq - PE trigout sig <0> */ + drvdata->config.trig_out_filter |= 0x1; + +of_create_v8_out: + return ret; +} + +static int cti_plat_check_v8_arch_compatible(struct device *dev) +{ + struct fwnode_handle *fwnode = dev_fwnode(dev); + + if (is_of_node(fwnode)) + return of_device_is_compatible(to_of_node(fwnode), + CTI_DT_V8ARCH_COMPAT); + return 0; +} + +static int cti_plat_count_sig_elements(const struct fwnode_handle *fwnode, + const char *name) +{ + int nr_elem = fwnode_property_count_u32(fwnode, name); + + return (nr_elem < 0 ? 0 : nr_elem); +} + +static int cti_plat_read_trig_group(struct cti_trig_grp *tgrp, + const struct fwnode_handle *fwnode, + const char *grp_name) +{ + int idx, err = 0; + u32 *values; + + if (!tgrp->nr_sigs) + return 0; + + values = kcalloc(tgrp->nr_sigs, sizeof(u32), GFP_KERNEL); + if (!values) + return -ENOMEM; + + err = fwnode_property_read_u32_array(fwnode, grp_name, + values, tgrp->nr_sigs); + + if (!err) { + /* set the signal usage mask */ + for (idx = 0; idx < tgrp->nr_sigs; idx++) + tgrp->used_mask |= BIT(values[idx]); + } + + kfree(values); + return err; +} + +static int cti_plat_read_trig_types(struct cti_trig_grp *tgrp, + const struct fwnode_handle *fwnode, + const char *type_name) +{ + int items, err = 0, nr_sigs; + u32 *values = NULL, i; + + /* allocate an array according to number of signals in connection */ + nr_sigs = tgrp->nr_sigs; + if (!nr_sigs) + return 0; + + /* see if any types have been included in the device description */ + items = cti_plat_count_sig_elements(fwnode, type_name); + if (items > nr_sigs) + return -EINVAL; + + /* need an array to store the values iff there are any */ + if (items) { + values = kcalloc(items, sizeof(u32), GFP_KERNEL); + if (!values) + return -ENOMEM; + + err = fwnode_property_read_u32_array(fwnode, type_name, + values, items); + if (err) + goto read_trig_types_out; + } + + /* + * Match type id to signal index, 1st type to 1st index etc. + * If fewer types than signals default remainder to GEN_IO. + */ + for (i = 0; i < nr_sigs; i++) { + if (i < items) { + tgrp->sig_types[i] = + values[i] < CTI_TRIG_MAX ? values[i] : GEN_IO; + } else { + tgrp->sig_types[i] = GEN_IO; + } + } + +read_trig_types_out: + kfree(values); + return err; +} + +static int cti_plat_process_filter_sigs(struct cti_drvdata *drvdata, + const struct fwnode_handle *fwnode) +{ + struct cti_trig_grp *tg = NULL; + int err = 0, nr_filter_sigs; + + nr_filter_sigs = cti_plat_count_sig_elements(fwnode, + CTI_DT_FILTER_OUT_SIGS); + if (nr_filter_sigs == 0) + return 0; + + if (nr_filter_sigs > drvdata->config.nr_trig_max) + return -EINVAL; + + tg = kzalloc(sizeof(*tg), GFP_KERNEL); + if (!tg) + return -ENOMEM; + + err = cti_plat_read_trig_group(tg, fwnode, CTI_DT_FILTER_OUT_SIGS); + if (!err) + drvdata->config.trig_out_filter |= tg->used_mask; + + kfree(tg); + return err; +} + +static int cti_plat_create_connection(struct device *dev, + struct cti_drvdata *drvdata, + struct fwnode_handle *fwnode) +{ + struct cti_trig_con *tc = NULL; + int cpuid = -1, err = 0; + struct coresight_device *csdev = NULL; + const char *assoc_name = "unknown"; + char cpu_name_str[16]; + int nr_sigs_in, nr_sigs_out; + + /* look to see how many in and out signals we have */ + nr_sigs_in = cti_plat_count_sig_elements(fwnode, CTI_DT_TRIGIN_SIGS); + nr_sigs_out = cti_plat_count_sig_elements(fwnode, CTI_DT_TRIGOUT_SIGS); + + if ((nr_sigs_in > drvdata->config.nr_trig_max) || + (nr_sigs_out > drvdata->config.nr_trig_max)) + return -EINVAL; + + tc = cti_allocate_trig_con(dev, nr_sigs_in, nr_sigs_out); + if (!tc) + return -ENOMEM; + + /* look for the signals properties. */ + err = cti_plat_read_trig_group(tc->con_in, fwnode, + CTI_DT_TRIGIN_SIGS); + if (err) + goto create_con_err; + + err = cti_plat_read_trig_types(tc->con_in, fwnode, + CTI_DT_TRIGIN_TYPES); + if (err) + goto create_con_err; + + err = cti_plat_read_trig_group(tc->con_out, fwnode, + CTI_DT_TRIGOUT_SIGS); + if (err) + goto create_con_err; + + err = cti_plat_read_trig_types(tc->con_out, fwnode, + CTI_DT_TRIGOUT_TYPES); + if (err) + goto create_con_err; + + err = cti_plat_process_filter_sigs(drvdata, fwnode); + if (err) + goto create_con_err; + + /* read the connection name if set - may be overridden by later */ + fwnode_property_read_string(fwnode, CTI_DT_CONN_NAME, &assoc_name); + + /* associated cpu ? */ + cpuid = cti_plat_get_cpu_at_node(fwnode); + if (cpuid >= 0) { + drvdata->ctidev.cpu = cpuid; + scnprintf(cpu_name_str, sizeof(cpu_name_str), "cpu%d", cpuid); + assoc_name = cpu_name_str; + } else { + /* associated device ? */ + struct fwnode_handle *cs_fwnode = fwnode_find_reference(fwnode, + CTI_DT_CSDEV_ASSOC, + 0); + if (!IS_ERR(cs_fwnode)) { + assoc_name = cti_plat_get_csdev_or_node_name(cs_fwnode, + &csdev); + fwnode_handle_put(cs_fwnode); + } + } + /* set up a connection */ + err = cti_add_connection_entry(dev, drvdata, tc, csdev, assoc_name); + +create_con_err: + return err; +} + +static int cti_plat_create_impdef_connections(struct device *dev, + struct cti_drvdata *drvdata) +{ + int rc = 0; + struct fwnode_handle *fwnode = dev_fwnode(dev); + struct fwnode_handle *child = NULL; + + if (IS_ERR_OR_NULL(fwnode)) + return -EINVAL; + + fwnode_for_each_child_node(fwnode, child) { + if (cti_plat_node_name_eq(child, CTI_DT_CONNS)) + rc = cti_plat_create_connection(dev, drvdata, + child); + if (rc != 0) + break; + } + fwnode_handle_put(child); + + return rc; +} + +/* get the hardware configuration & connection data. */ +static int cti_plat_get_hw_data(struct device *dev, struct cti_drvdata *drvdata) +{ + int rc = 0; + struct cti_device *cti_dev = &drvdata->ctidev; + + /* get any CTM ID - defaults to 0 */ + device_property_read_u32(dev, CTI_DT_CTM_ID, &cti_dev->ctm_id); + + /* check for a v8 architectural CTI device */ + if (cti_plat_check_v8_arch_compatible(dev)) + rc = cti_plat_create_v8_connections(dev, drvdata); + else + rc = cti_plat_create_impdef_connections(dev, drvdata); + if (rc) + return rc; + + /* if no connections, just add a single default based on max IN-OUT */ + if (cti_dev->nr_trig_con == 0) + rc = cti_add_default_connection(dev, drvdata); + return rc; +} + +struct coresight_platform_data * +coresight_cti_get_platform_data(struct device *dev) +{ + int ret = -ENOENT; + struct coresight_platform_data *pdata = NULL; + struct fwnode_handle *fwnode = dev_fwnode(dev); + struct cti_drvdata *drvdata = dev_get_drvdata(dev); + + if (IS_ERR_OR_NULL(fwnode)) + goto error; + + /* + * Alloc platform data but leave it zero init. CTI does not use the + * same connection infrastructuree as trace path components but an + * empty struct enables us to use the standard coresight component + * registration code. + */ + pdata = devm_kzalloc(dev, sizeof(*pdata), GFP_KERNEL); + if (!pdata) { + ret = -ENOMEM; + goto error; + } + + /* get some CTI specifics */ + ret = cti_plat_get_hw_data(dev, drvdata); + + if (!ret) + return pdata; +error: + return ERR_PTR(ret); +} -- cgit v1.2.3