coresigh: Updates for v6.6
Coresight and hwtracing subsystem updates for Linux v6.6 includes: - ACPI support for CoreSight ETMv4x via system instructions and Arm ETE (v9.x). - Fix potential sleeping in atomic context for TRBE driver - Fix memory leak in ACPI platform parsing code - Fix all warnings with W=1 - Fix warning with double free attempt for TRBE platform data - Miscellaneous cleanups and fixes Signed-off-by: Suzuki K Poulose <suzuki.poulose@arm.com> -----BEGIN PGP SIGNATURE----- iQIzBAABCgAdFiEEuFy0byloRoXZHaWBxcXRZPKyBqEFAmTfqWAACgkQxcXRZPKy BqFxfA//VIzBiM/Az6Zr00ER93MVdWPRJcCOo6VDO3gZSz7bpzHMdUMaohDmNvhy DYWYxmhD8XMzR++SX9gF51CasjziRfOTFNFk8aUIZZiQ/aUCtofUh2SCTZJArnJw igNKJmQIZuYb361k4ctrp01wLScAPjx3crwCJTZqJ1uOxgItksYKxPeWf05W9RPM DD2GWvkRr6sctaW/2P+46SNhT9+QOlA7F2k+qhoCYWIt99yewoBXIBxJA6+37xG2 H2fB8/y4fws5XMFUQ7tlld0vRuLoVSD3uPLGXDl8Owpwrh7C5Ea5jue0tMFtpcr2 IqtbBBJ9CZjEEvQuI8WduvHDkvU6Jlod8O7bX7Fx0Pn6EPBQJVk83sxo0a6VMaGI IWkxaG4oa6zUSKHaR6a9o/RxLRobJ/yLmKt6DsT+Zf8bv4BhZhm2lcTz8N9Ei9sl a5oGMF/TQymZXvR6GqawZKcvxazGTwA4r1EcBB2WG+gtu5jPBQAb80qGO7EyxaOl a75U0WZqkT+EX9K36xUPzxFQn+ncYbwO08uPYfRRQa5QYiA90aZ/6/Lea6HBGhw9 FBALYeM3sxV5qSs5GvcnGJuJWD9pRijNNi0NtqzSSn1Jne8DmSKB4/98gkKibljT BrtjWj7vvMNo0IuVHdzsBqZ8H9WL09hajixkCVCbX2/u+01ZrF4= =KHsb -----END PGP SIGNATURE----- Merge tag 'coresight-next-v6.6' of git://git.kernel.org/pub/scm/linux/kernel/git/coresight/linux into char-misc-next Suzuki writes: coresigh: Updates for v6.6 Coresight and hwtracing subsystem updates for Linux v6.6 includes: - ACPI support for CoreSight ETMv4x via system instructions and Arm ETE (v9.x). - Fix potential sleeping in atomic context for TRBE driver - Fix memory leak in ACPI platform parsing code - Fix all warnings with W=1 - Fix warning with double free attempt for TRBE platform data - Miscellaneous cleanups and fixes Signed-off-by: Suzuki K Poulose <suzuki.poulose@arm.com> * tag 'coresight-next-v6.6' of git://git.kernel.org/pub/scm/linux/kernel/git/coresight/linux: coresight: trbe: Fix TRBE potential sleep in atomic context coresight: Fix memory leak in acpi_buffer->pointer coresight: etm4x: Ensure valid drvdata and clock before clk_put() coresight: trbe: Allocate platform data per device hwtracing: hisi_ptt: Use pci_dev_id() to simplify the code coresight: dummy: simplify the code with module_platform_driver coresight: tmc: Explicit type conversions to prevent integer overflow coresight: trbe: Directly use ID_AA64DFR0_EL1_TraceBuffer_IMP coresight: Fix all W=1 build warnings coresight: etm4x: Add ACPI support in platform driver coresight: platform: acpi: Ignore the absence of graph coresight: etm4x: Change etm4_platform_driver driver for MMIO devices coresight: etm4x: Drop pid argument from etm4_probe() coresight: etm4x: Drop iomem 'base' argument from etm4_probe() coresight: etm4x: Allocate and device assign 'struct etmv4_drvdata' earlier hwtracing: coresight: Explicitly include correct DT includes
This commit is contained in:
commit
5bb5117b14
|
@ -22,7 +22,6 @@
|
|||
static const struct acpi_device_id amba_id_list[] = {
|
||||
{"ARMH0061", 0}, /* PL061 GPIO Device */
|
||||
{"ARMH0330", 0}, /* ARM DMA Controller DMA-330 */
|
||||
{"ARMHC500", 0}, /* ARM CoreSight ETM4x */
|
||||
{"ARMHC501", 0}, /* ARM CoreSight ETR */
|
||||
{"ARMHC502", 0}, /* ARM CoreSight STM */
|
||||
{"ARMHC503", 0}, /* ARM CoreSight Debug */
|
||||
|
|
|
@ -17,7 +17,7 @@
|
|||
#include <linux/mutex.h>
|
||||
#include <linux/clk.h>
|
||||
#include <linux/coresight.h>
|
||||
#include <linux/of_platform.h>
|
||||
#include <linux/property.h>
|
||||
#include <linux/delay.h>
|
||||
#include <linux/pm_runtime.h>
|
||||
|
||||
|
|
|
@ -22,7 +22,7 @@
|
|||
#include "coresight-priv.h"
|
||||
#include "coresight-cti.h"
|
||||
|
||||
/**
|
||||
/*
|
||||
* CTI devices can be associated with a PE, or be connected to CoreSight
|
||||
* hardware. We have a list of all CTIs irrespective of CPU bound or
|
||||
* otherwise.
|
||||
|
|
|
@ -147,17 +147,7 @@ static struct platform_driver dummy_driver = {
|
|||
},
|
||||
};
|
||||
|
||||
static int __init dummy_init(void)
|
||||
{
|
||||
return platform_driver_register(&dummy_driver);
|
||||
}
|
||||
module_init(dummy_init);
|
||||
|
||||
static void __exit dummy_exit(void)
|
||||
{
|
||||
platform_driver_unregister(&dummy_driver);
|
||||
}
|
||||
module_exit(dummy_exit);
|
||||
module_platform_driver(dummy_driver);
|
||||
|
||||
MODULE_LICENSE("GPL");
|
||||
MODULE_DESCRIPTION("CoreSight dummy driver");
|
||||
|
|
|
@ -40,7 +40,7 @@
|
|||
* Invalid offsets will result in fail code return and feature load failure.
|
||||
*
|
||||
* @drvdata: driver data to map into.
|
||||
* @reg: register to map.
|
||||
* @reg_csdev: register to map.
|
||||
* @offset: device offset for the register
|
||||
*/
|
||||
static int etm4_cfg_map_reg_offset(struct etmv4_drvdata *drvdata,
|
||||
|
@ -132,7 +132,7 @@ static int etm4_cfg_map_reg_offset(struct etmv4_drvdata *drvdata,
|
|||
* etm4_cfg_load_feature - load a feature into a device instance.
|
||||
*
|
||||
* @csdev: An ETMv4 CoreSight device.
|
||||
* @feat: The feature to be loaded.
|
||||
* @feat_csdev: The feature to be loaded.
|
||||
*
|
||||
* The function will load a feature instance into the device, checking that
|
||||
* the register definitions are valid for the device.
|
||||
|
|
|
@ -3,6 +3,7 @@
|
|||
* Copyright (c) 2014, The Linux Foundation. All rights reserved.
|
||||
*/
|
||||
|
||||
#include <linux/acpi.h>
|
||||
#include <linux/bitops.h>
|
||||
#include <linux/kernel.h>
|
||||
#include <linux/moduleparam.h>
|
||||
|
@ -30,6 +31,7 @@
|
|||
#include <linux/platform_device.h>
|
||||
#include <linux/pm_runtime.h>
|
||||
#include <linux/property.h>
|
||||
#include <linux/clk/clk-conf.h>
|
||||
|
||||
#include <asm/barrier.h>
|
||||
#include <asm/sections.h>
|
||||
|
@ -66,7 +68,6 @@ static u64 etm4_get_access_type(struct etmv4_config *config);
|
|||
static enum cpuhp_state hp_online;
|
||||
|
||||
struct etm4_init_arg {
|
||||
unsigned int pid;
|
||||
struct device *dev;
|
||||
struct csdev_access *csa;
|
||||
};
|
||||
|
@ -370,9 +371,17 @@ static void etm4_disable_arch_specific(struct etmv4_drvdata *drvdata)
|
|||
}
|
||||
|
||||
static void etm4_check_arch_features(struct etmv4_drvdata *drvdata,
|
||||
unsigned int id)
|
||||
struct csdev_access *csa)
|
||||
{
|
||||
if (etm4_hisi_match_pid(id))
|
||||
/*
|
||||
* TRCPIDR* registers are not required for ETMs with system
|
||||
* instructions. They must be identified by the MIDR+REVIDRs.
|
||||
* Skip the TRCPID checks for now.
|
||||
*/
|
||||
if (!csa->io_mem)
|
||||
return;
|
||||
|
||||
if (etm4_hisi_match_pid(coresight_get_pid(csa)))
|
||||
set_bit(ETM4_IMPDEF_HISI_CORE_COMMIT, drvdata->arch_features);
|
||||
}
|
||||
#else
|
||||
|
@ -385,7 +394,7 @@ static void etm4_disable_arch_specific(struct etmv4_drvdata *drvdata)
|
|||
}
|
||||
|
||||
static void etm4_check_arch_features(struct etmv4_drvdata *drvdata,
|
||||
unsigned int id)
|
||||
struct csdev_access *csa)
|
||||
{
|
||||
}
|
||||
#endif /* CONFIG_ETM4X_IMPDEF_FEATURE */
|
||||
|
@ -1066,11 +1075,21 @@ static bool etm4_init_sysreg_access(struct etmv4_drvdata *drvdata,
|
|||
return true;
|
||||
}
|
||||
|
||||
static bool is_devtype_cpu_trace(void __iomem *base)
|
||||
{
|
||||
u32 devtype = readl(base + TRCDEVTYPE);
|
||||
|
||||
return (devtype == CS_DEVTYPE_PE_TRACE);
|
||||
}
|
||||
|
||||
static bool etm4_init_iomem_access(struct etmv4_drvdata *drvdata,
|
||||
struct csdev_access *csa)
|
||||
{
|
||||
u32 devarch = readl_relaxed(drvdata->base + TRCDEVARCH);
|
||||
|
||||
if (!is_coresight_device(drvdata->base) || !is_devtype_cpu_trace(drvdata->base))
|
||||
return false;
|
||||
|
||||
/*
|
||||
* All ETMs must implement TRCDEVARCH to indicate that
|
||||
* the component is an ETMv4. Even though TRCIDR1 also
|
||||
|
@ -1161,7 +1180,7 @@ static void etm4_init_arch_data(void *info)
|
|||
etm4_os_unlock_csa(drvdata, csa);
|
||||
etm4_cs_unlock(drvdata, csa);
|
||||
|
||||
etm4_check_arch_features(drvdata, init_arg->pid);
|
||||
etm4_check_arch_features(drvdata, csa);
|
||||
|
||||
/* find all capabilities of the tracing unit */
|
||||
etmidr0 = etm4x_relaxed_read32(csa, TRCIDR0);
|
||||
|
@ -2044,19 +2063,16 @@ static int etm4_add_coresight_dev(struct etm4_init_arg *init_arg)
|
|||
return 0;
|
||||
}
|
||||
|
||||
static int etm4_probe(struct device *dev, void __iomem *base, u32 etm_pid)
|
||||
static int etm4_probe(struct device *dev)
|
||||
{
|
||||
struct etmv4_drvdata *drvdata;
|
||||
struct etmv4_drvdata *drvdata = dev_get_drvdata(dev);
|
||||
struct csdev_access access = { 0 };
|
||||
struct etm4_init_arg init_arg = { 0 };
|
||||
struct etm4_init_arg *delayed;
|
||||
|
||||
drvdata = devm_kzalloc(dev, sizeof(*drvdata), GFP_KERNEL);
|
||||
if (!drvdata)
|
||||
if (WARN_ON(!drvdata))
|
||||
return -ENOMEM;
|
||||
|
||||
dev_set_drvdata(dev, drvdata);
|
||||
|
||||
if (pm_save_enable == PARAM_PM_SAVE_FIRMWARE)
|
||||
pm_save_enable = coresight_loses_context_with_cpu(dev) ?
|
||||
PARAM_PM_SAVE_SELF_HOSTED : PARAM_PM_SAVE_NEVER;
|
||||
|
@ -2068,8 +2084,6 @@ static int etm4_probe(struct device *dev, void __iomem *base, u32 etm_pid)
|
|||
return -ENOMEM;
|
||||
}
|
||||
|
||||
drvdata->base = base;
|
||||
|
||||
spin_lock_init(&drvdata->spinlock);
|
||||
|
||||
drvdata->cpu = coresight_get_cpu(dev);
|
||||
|
@ -2078,7 +2092,6 @@ static int etm4_probe(struct device *dev, void __iomem *base, u32 etm_pid)
|
|||
|
||||
init_arg.dev = dev;
|
||||
init_arg.csa = &access;
|
||||
init_arg.pid = etm_pid;
|
||||
|
||||
/*
|
||||
* Serialize against CPUHP callbacks to avoid race condition
|
||||
|
@ -2108,6 +2121,7 @@ static int etm4_probe(struct device *dev, void __iomem *base, u32 etm_pid)
|
|||
|
||||
static int etm4_probe_amba(struct amba_device *adev, const struct amba_id *id)
|
||||
{
|
||||
struct etmv4_drvdata *drvdata;
|
||||
void __iomem *base;
|
||||
struct device *dev = &adev->dev;
|
||||
struct resource *res = &adev->res;
|
||||
|
@ -2118,7 +2132,13 @@ static int etm4_probe_amba(struct amba_device *adev, const struct amba_id *id)
|
|||
if (IS_ERR(base))
|
||||
return PTR_ERR(base);
|
||||
|
||||
ret = etm4_probe(dev, base, id->id);
|
||||
drvdata = devm_kzalloc(dev, sizeof(*drvdata), GFP_KERNEL);
|
||||
if (!drvdata)
|
||||
return -ENOMEM;
|
||||
|
||||
drvdata->base = base;
|
||||
dev_set_drvdata(dev, drvdata);
|
||||
ret = etm4_probe(dev);
|
||||
if (!ret)
|
||||
pm_runtime_put(&adev->dev);
|
||||
|
||||
|
@ -2127,18 +2147,32 @@ static int etm4_probe_amba(struct amba_device *adev, const struct amba_id *id)
|
|||
|
||||
static int etm4_probe_platform_dev(struct platform_device *pdev)
|
||||
{
|
||||
struct resource *res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
|
||||
struct etmv4_drvdata *drvdata;
|
||||
int ret;
|
||||
|
||||
drvdata = devm_kzalloc(&pdev->dev, sizeof(*drvdata), GFP_KERNEL);
|
||||
if (!drvdata)
|
||||
return -ENOMEM;
|
||||
|
||||
drvdata->pclk = coresight_get_enable_apb_pclk(&pdev->dev);
|
||||
if (IS_ERR(drvdata->pclk))
|
||||
return -ENODEV;
|
||||
|
||||
if (res) {
|
||||
drvdata->base = devm_ioremap_resource(&pdev->dev, res);
|
||||
if (IS_ERR(drvdata->base)) {
|
||||
clk_put(drvdata->pclk);
|
||||
return PTR_ERR(drvdata->base);
|
||||
}
|
||||
}
|
||||
|
||||
dev_set_drvdata(&pdev->dev, drvdata);
|
||||
pm_runtime_get_noresume(&pdev->dev);
|
||||
pm_runtime_set_active(&pdev->dev);
|
||||
pm_runtime_enable(&pdev->dev);
|
||||
|
||||
/*
|
||||
* System register based devices could match the
|
||||
* HW by reading appropriate registers on the HW
|
||||
* and thus we could skip the PID.
|
||||
*/
|
||||
ret = etm4_probe(&pdev->dev, NULL, 0);
|
||||
ret = etm4_probe(&pdev->dev);
|
||||
|
||||
pm_runtime_put(&pdev->dev);
|
||||
return ret;
|
||||
|
@ -2178,7 +2212,7 @@ static struct amba_cs_uci_id uci_id_etm4[] = {
|
|||
/* ETMv4 UCI data */
|
||||
.devarch = ETM_DEVARCH_ETMv4x_ARCH,
|
||||
.devarch_mask = ETM_DEVARCH_ID_MASK,
|
||||
.devtype = 0x00000013,
|
||||
.devtype = CS_DEVTYPE_PE_TRACE,
|
||||
}
|
||||
};
|
||||
|
||||
|
@ -2234,6 +2268,10 @@ static int __exit etm4_remove_platform_dev(struct platform_device *pdev)
|
|||
if (drvdata)
|
||||
etm4_remove_dev(drvdata);
|
||||
pm_runtime_disable(&pdev->dev);
|
||||
|
||||
if (drvdata && !IS_ERR_OR_NULL(drvdata->pclk))
|
||||
clk_put(drvdata->pclk);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
@ -2278,19 +2316,55 @@ static struct amba_driver etm4x_amba_driver = {
|
|||
.id_table = etm4_ids,
|
||||
};
|
||||
|
||||
#ifdef CONFIG_PM
|
||||
static int etm4_runtime_suspend(struct device *dev)
|
||||
{
|
||||
struct etmv4_drvdata *drvdata = dev_get_drvdata(dev);
|
||||
|
||||
if (drvdata->pclk && !IS_ERR(drvdata->pclk))
|
||||
clk_disable_unprepare(drvdata->pclk);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int etm4_runtime_resume(struct device *dev)
|
||||
{
|
||||
struct etmv4_drvdata *drvdata = dev_get_drvdata(dev);
|
||||
|
||||
if (drvdata->pclk && !IS_ERR(drvdata->pclk))
|
||||
clk_prepare_enable(drvdata->pclk);
|
||||
|
||||
return 0;
|
||||
}
|
||||
#endif
|
||||
|
||||
static const struct dev_pm_ops etm4_dev_pm_ops = {
|
||||
SET_RUNTIME_PM_OPS(etm4_runtime_suspend, etm4_runtime_resume, NULL)
|
||||
};
|
||||
|
||||
static const struct of_device_id etm4_sysreg_match[] = {
|
||||
{ .compatible = "arm,coresight-etm4x-sysreg" },
|
||||
{ .compatible = "arm,embedded-trace-extension" },
|
||||
{}
|
||||
};
|
||||
|
||||
#ifdef CONFIG_ACPI
|
||||
static const struct acpi_device_id etm4x_acpi_ids[] = {
|
||||
{"ARMHC500", 0}, /* ARM CoreSight ETM4x */
|
||||
{}
|
||||
};
|
||||
MODULE_DEVICE_TABLE(acpi, etm4x_acpi_ids);
|
||||
#endif
|
||||
|
||||
static struct platform_driver etm4_platform_driver = {
|
||||
.probe = etm4_probe_platform_dev,
|
||||
.remove = etm4_remove_platform_dev,
|
||||
.driver = {
|
||||
.name = "coresight-etm4x",
|
||||
.of_match_table = etm4_sysreg_match,
|
||||
.acpi_match_table = ACPI_PTR(etm4x_acpi_ids),
|
||||
.suppress_bind_attrs = true,
|
||||
.pm = &etm4_dev_pm_ops,
|
||||
},
|
||||
};
|
||||
|
||||
|
|
|
@ -701,6 +701,8 @@
|
|||
#define ETM_DEVARCH_ETE_ARCH \
|
||||
(ETM_DEVARCH_ARCHITECT_ARM | ETM_DEVARCH_ARCHID_ETE | ETM_DEVARCH_PRESENT)
|
||||
|
||||
#define CS_DEVTYPE_PE_TRACE 0x00000013
|
||||
|
||||
#define TRCSTATR_IDLE_BIT 0
|
||||
#define TRCSTATR_PMSTABLE_BIT 1
|
||||
#define ETM_DEFAULT_ADDR_COMP 0
|
||||
|
@ -944,6 +946,7 @@ struct etmv4_save_state {
|
|||
|
||||
/**
|
||||
* struct etm4_drvdata - specifics associated to an ETM component
|
||||
* @pclk APB clock if present, otherwise NULL
|
||||
* @base: Memory mapped base address for this component.
|
||||
* @csdev: Component vitals needed by the framework.
|
||||
* @spinlock: Only one at a time pls.
|
||||
|
@ -1009,6 +1012,7 @@ struct etmv4_save_state {
|
|||
* @arch_features: Bitmap of arch features of etmv4 devices.
|
||||
*/
|
||||
struct etmv4_drvdata {
|
||||
struct clk *pclk;
|
||||
void __iomem *base;
|
||||
struct coresight_device *csdev;
|
||||
spinlock_t spinlock;
|
||||
|
|
|
@ -9,9 +9,7 @@
|
|||
#include <linux/slab.h>
|
||||
#include <linux/clk.h>
|
||||
#include <linux/of.h>
|
||||
#include <linux/of_address.h>
|
||||
#include <linux/of_graph.h>
|
||||
#include <linux/of_platform.h>
|
||||
#include <linux/platform_device.h>
|
||||
#include <linux/amba/bus.h>
|
||||
#include <linux/coresight.h>
|
||||
|
@ -494,19 +492,18 @@ 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. */
|
||||
static const union acpi_object *
|
||||
acpi_get_dsd_graph(struct acpi_device *adev)
|
||||
acpi_get_dsd_graph(struct acpi_device *adev, struct acpi_buffer *buf)
|
||||
{
|
||||
int i;
|
||||
struct acpi_buffer buf = { ACPI_ALLOCATE_BUFFER };
|
||||
acpi_status status;
|
||||
const union acpi_object *dsd;
|
||||
|
||||
status = acpi_evaluate_object_typed(adev->handle, "_DSD", NULL,
|
||||
&buf, ACPI_TYPE_PACKAGE);
|
||||
buf, ACPI_TYPE_PACKAGE);
|
||||
if (ACPI_FAILURE(status))
|
||||
return NULL;
|
||||
|
||||
dsd = buf.pointer;
|
||||
dsd = buf->pointer;
|
||||
|
||||
/*
|
||||
* _DSD property consists tuples { Prop_UUID, Package() }
|
||||
|
@ -557,12 +554,12 @@ acpi_validate_coresight_graph(const union acpi_object *cs_graph)
|
|||
* returns NULL.
|
||||
*/
|
||||
static const union acpi_object *
|
||||
acpi_get_coresight_graph(struct acpi_device *adev)
|
||||
acpi_get_coresight_graph(struct acpi_device *adev, struct acpi_buffer *buf)
|
||||
{
|
||||
const union acpi_object *graph_list, *graph;
|
||||
int i, nr_graphs;
|
||||
|
||||
graph_list = acpi_get_dsd_graph(adev);
|
||||
graph_list = acpi_get_dsd_graph(adev, buf);
|
||||
if (!graph_list)
|
||||
return graph_list;
|
||||
|
||||
|
@ -663,18 +660,24 @@ static int acpi_coresight_parse_graph(struct device *dev,
|
|||
struct acpi_device *adev,
|
||||
struct coresight_platform_data *pdata)
|
||||
{
|
||||
int ret = 0;
|
||||
int i, nlinks;
|
||||
const union acpi_object *graph;
|
||||
struct coresight_connection conn, zero_conn = {};
|
||||
struct coresight_connection *new_conn;
|
||||
struct acpi_buffer buf = { ACPI_ALLOCATE_BUFFER, NULL };
|
||||
|
||||
graph = acpi_get_coresight_graph(adev);
|
||||
graph = acpi_get_coresight_graph(adev, &buf);
|
||||
/*
|
||||
* There are no graph connections, which is fine for some components.
|
||||
* e.g., ETE
|
||||
*/
|
||||
if (!graph)
|
||||
return -ENOENT;
|
||||
goto free;
|
||||
|
||||
nlinks = graph->package.elements[2].integer.value;
|
||||
if (!nlinks)
|
||||
return 0;
|
||||
goto free;
|
||||
|
||||
for (i = 0; i < nlinks; i++) {
|
||||
const union acpi_object *link = &graph->package.elements[3 + i];
|
||||
|
@ -682,17 +685,28 @@ static int acpi_coresight_parse_graph(struct device *dev,
|
|||
|
||||
conn = zero_conn;
|
||||
dir = acpi_coresight_parse_link(adev, link, &conn);
|
||||
if (dir < 0)
|
||||
return dir;
|
||||
if (dir < 0) {
|
||||
ret = dir;
|
||||
goto free;
|
||||
}
|
||||
|
||||
if (dir == ACPI_CORESIGHT_LINK_MASTER) {
|
||||
new_conn = coresight_add_out_conn(dev, pdata, &conn);
|
||||
if (IS_ERR(new_conn))
|
||||
return PTR_ERR(new_conn);
|
||||
if (IS_ERR(new_conn)) {
|
||||
ret = PTR_ERR(new_conn);
|
||||
goto free;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return 0;
|
||||
free:
|
||||
/*
|
||||
* When ACPI fails to alloc a buffer, it will free the buffer
|
||||
* created via ACPI_ALLOCATE_BUFFER and set to NULL.
|
||||
* ACPI_FREE can handle NULL pointers, so free it directly.
|
||||
*/
|
||||
ACPI_FREE(buf.pointer);
|
||||
return ret;
|
||||
}
|
||||
|
||||
/*
|
||||
|
|
|
@ -452,7 +452,7 @@ static int tmc_set_etf_buffer(struct coresight_device *csdev,
|
|||
return -EINVAL;
|
||||
|
||||
/* wrap head around to the amount of space we have */
|
||||
head = handle->head & ((buf->nr_pages << PAGE_SHIFT) - 1);
|
||||
head = handle->head & (((unsigned long)buf->nr_pages << PAGE_SHIFT) - 1);
|
||||
|
||||
/* find the page to write to */
|
||||
buf->cur = head / PAGE_SIZE;
|
||||
|
|
|
@ -45,7 +45,8 @@ struct etr_perf_buffer {
|
|||
};
|
||||
|
||||
/* Convert the perf index to an offset within the ETR buffer */
|
||||
#define PERF_IDX2OFF(idx, buf) ((idx) % ((buf)->nr_pages << PAGE_SHIFT))
|
||||
#define PERF_IDX2OFF(idx, buf) \
|
||||
((idx) % ((unsigned long)(buf)->nr_pages << PAGE_SHIFT))
|
||||
|
||||
/* Lower limit for ETR hardware buffer */
|
||||
#define TMC_ETR_PERF_MIN_BUF_SIZE SZ_1M
|
||||
|
@ -1267,7 +1268,7 @@ alloc_etr_buf(struct tmc_drvdata *drvdata, struct perf_event *event,
|
|||
* than the size requested via sysfs.
|
||||
*/
|
||||
if ((nr_pages << PAGE_SHIFT) > drvdata->size) {
|
||||
etr_buf = tmc_alloc_etr_buf(drvdata, (nr_pages << PAGE_SHIFT),
|
||||
etr_buf = tmc_alloc_etr_buf(drvdata, ((ssize_t)nr_pages << PAGE_SHIFT),
|
||||
0, node, NULL);
|
||||
if (!IS_ERR(etr_buf))
|
||||
goto done;
|
||||
|
|
|
@ -325,7 +325,7 @@ ssize_t tmc_sg_table_get_data(struct tmc_sg_table *sg_table,
|
|||
static inline unsigned long
|
||||
tmc_sg_table_buf_size(struct tmc_sg_table *sg_table)
|
||||
{
|
||||
return sg_table->data_pages.nr_pages << PAGE_SHIFT;
|
||||
return (unsigned long)sg_table->data_pages.nr_pages << PAGE_SHIFT;
|
||||
}
|
||||
|
||||
struct coresight_device *tmc_etr_get_catu_device(struct tmc_drvdata *drvdata);
|
||||
|
|
|
@ -1225,6 +1225,16 @@ static void arm_trbe_enable_cpu(void *info)
|
|||
enable_percpu_irq(drvdata->irq, IRQ_TYPE_NONE);
|
||||
}
|
||||
|
||||
static void arm_trbe_disable_cpu(void *info)
|
||||
{
|
||||
struct trbe_drvdata *drvdata = info;
|
||||
struct trbe_cpudata *cpudata = this_cpu_ptr(drvdata->cpudata);
|
||||
|
||||
disable_percpu_irq(drvdata->irq);
|
||||
trbe_reset_local(cpudata);
|
||||
}
|
||||
|
||||
|
||||
static void arm_trbe_register_coresight_cpu(struct trbe_drvdata *drvdata, int cpu)
|
||||
{
|
||||
struct trbe_cpudata *cpudata = per_cpu_ptr(drvdata->cpudata, cpu);
|
||||
|
@ -1244,10 +1254,13 @@ static void arm_trbe_register_coresight_cpu(struct trbe_drvdata *drvdata, int cp
|
|||
if (!desc.name)
|
||||
goto cpu_clear;
|
||||
|
||||
desc.pdata = coresight_get_platform_data(dev);
|
||||
if (IS_ERR(desc.pdata))
|
||||
goto cpu_clear;
|
||||
|
||||
desc.type = CORESIGHT_DEV_TYPE_SINK;
|
||||
desc.subtype.sink_subtype = CORESIGHT_DEV_SUBTYPE_SINK_PERCPU_SYSMEM;
|
||||
desc.ops = &arm_trbe_cs_ops;
|
||||
desc.pdata = dev_get_platdata(dev);
|
||||
desc.groups = arm_trbe_groups;
|
||||
desc.dev = dev;
|
||||
trbe_csdev = coresight_register(&desc);
|
||||
|
@ -1326,18 +1339,12 @@ cpu_clear:
|
|||
cpumask_clear_cpu(cpu, &drvdata->supported_cpus);
|
||||
}
|
||||
|
||||
static void arm_trbe_remove_coresight_cpu(void *info)
|
||||
static void arm_trbe_remove_coresight_cpu(struct trbe_drvdata *drvdata, int cpu)
|
||||
{
|
||||
int cpu = smp_processor_id();
|
||||
struct trbe_drvdata *drvdata = info;
|
||||
struct trbe_cpudata *cpudata = per_cpu_ptr(drvdata->cpudata, cpu);
|
||||
struct coresight_device *trbe_csdev = coresight_get_percpu_sink(cpu);
|
||||
|
||||
disable_percpu_irq(drvdata->irq);
|
||||
trbe_reset_local(cpudata);
|
||||
if (trbe_csdev) {
|
||||
coresight_unregister(trbe_csdev);
|
||||
cpudata->drvdata = NULL;
|
||||
coresight_set_percpu_sink(cpu, NULL);
|
||||
}
|
||||
}
|
||||
|
@ -1366,8 +1373,10 @@ static int arm_trbe_remove_coresight(struct trbe_drvdata *drvdata)
|
|||
{
|
||||
int cpu;
|
||||
|
||||
for_each_cpu(cpu, &drvdata->supported_cpus)
|
||||
smp_call_function_single(cpu, arm_trbe_remove_coresight_cpu, drvdata, 1);
|
||||
for_each_cpu(cpu, &drvdata->supported_cpus) {
|
||||
smp_call_function_single(cpu, arm_trbe_disable_cpu, drvdata, 1);
|
||||
arm_trbe_remove_coresight_cpu(drvdata, cpu);
|
||||
}
|
||||
free_percpu(drvdata->cpudata);
|
||||
return 0;
|
||||
}
|
||||
|
@ -1406,12 +1415,8 @@ static int arm_trbe_cpu_teardown(unsigned int cpu, struct hlist_node *node)
|
|||
{
|
||||
struct trbe_drvdata *drvdata = hlist_entry_safe(node, struct trbe_drvdata, hotplug_node);
|
||||
|
||||
if (cpumask_test_cpu(cpu, &drvdata->supported_cpus)) {
|
||||
struct trbe_cpudata *cpudata = per_cpu_ptr(drvdata->cpudata, cpu);
|
||||
|
||||
disable_percpu_irq(drvdata->irq);
|
||||
trbe_reset_local(cpudata);
|
||||
}
|
||||
if (cpumask_test_cpu(cpu, &drvdata->supported_cpus))
|
||||
arm_trbe_disable_cpu(drvdata);
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
@ -1479,7 +1484,6 @@ static void arm_trbe_remove_irq(struct trbe_drvdata *drvdata)
|
|||
|
||||
static int arm_trbe_device_probe(struct platform_device *pdev)
|
||||
{
|
||||
struct coresight_platform_data *pdata;
|
||||
struct trbe_drvdata *drvdata;
|
||||
struct device *dev = &pdev->dev;
|
||||
int ret;
|
||||
|
@ -1494,12 +1498,7 @@ static int arm_trbe_device_probe(struct platform_device *pdev)
|
|||
if (!drvdata)
|
||||
return -ENOMEM;
|
||||
|
||||
pdata = coresight_get_platform_data(dev);
|
||||
if (IS_ERR(pdata))
|
||||
return PTR_ERR(pdata);
|
||||
|
||||
dev_set_drvdata(dev, drvdata);
|
||||
dev->platform_data = pdata;
|
||||
drvdata->pdev = pdev;
|
||||
ret = arm_trbe_probe_irq(pdev, drvdata);
|
||||
if (ret)
|
||||
|
|
|
@ -23,7 +23,7 @@ static inline bool is_trbe_available(void)
|
|||
unsigned int trbe = cpuid_feature_extract_unsigned_field(aa64dfr0,
|
||||
ID_AA64DFR0_EL1_TraceBuffer_SHIFT);
|
||||
|
||||
return trbe >= 0b0001;
|
||||
return trbe >= ID_AA64DFR0_EL1_TraceBuffer_IMP;
|
||||
}
|
||||
|
||||
static inline bool is_trbe_enabled(void)
|
||||
|
|
|
@ -618,13 +618,13 @@ static int hisi_ptt_notifier_call(struct notifier_block *nb, unsigned long actio
|
|||
if (!root_port)
|
||||
return 0;
|
||||
|
||||
port_devid = PCI_DEVID(root_port->bus->number, root_port->devfn);
|
||||
port_devid = pci_dev_id(root_port);
|
||||
if (port_devid < hisi_ptt->lower_bdf ||
|
||||
port_devid > hisi_ptt->upper_bdf)
|
||||
return 0;
|
||||
|
||||
info.is_port = pci_pcie_type(pdev) == PCI_EXP_TYPE_ROOT_PORT;
|
||||
info.devid = PCI_DEVID(pdev->bus->number, pdev->devfn);
|
||||
info.devid = pci_dev_id(pdev);
|
||||
|
||||
switch (action) {
|
||||
case BUS_NOTIFY_ADD_DEVICE:
|
||||
|
@ -664,7 +664,7 @@ static int hisi_ptt_init_filters(struct pci_dev *pdev, void *data)
|
|||
if (!root_port)
|
||||
return 0;
|
||||
|
||||
port_devid = PCI_DEVID(root_port->bus->number, root_port->devfn);
|
||||
port_devid = pci_dev_id(root_port);
|
||||
if (port_devid < hisi_ptt->lower_bdf ||
|
||||
port_devid > hisi_ptt->upper_bdf)
|
||||
return 0;
|
||||
|
@ -674,7 +674,7 @@ static int hisi_ptt_init_filters(struct pci_dev *pdev, void *data)
|
|||
* should be partial initialized and users would know which filter fails
|
||||
* through the log. Other functions of PTT device are still available.
|
||||
*/
|
||||
filter = hisi_ptt_alloc_add_filter(hisi_ptt, PCI_DEVID(pdev->bus->number, pdev->devfn),
|
||||
filter = hisi_ptt_alloc_add_filter(hisi_ptt, pci_dev_id(pdev),
|
||||
pci_pcie_type(pdev) == PCI_EXP_TYPE_ROOT_PORT);
|
||||
if (!filter)
|
||||
return -ENOMEM;
|
||||
|
|
|
@ -6,6 +6,8 @@
|
|||
#ifndef _LINUX_CORESIGHT_H
|
||||
#define _LINUX_CORESIGHT_H
|
||||
|
||||
#include <linux/amba/bus.h>
|
||||
#include <linux/clk.h>
|
||||
#include <linux/device.h>
|
||||
#include <linux/io.h>
|
||||
#include <linux/perf_event.h>
|
||||
|
@ -386,6 +388,63 @@ static inline u32 csdev_access_relaxed_read32(struct csdev_access *csa,
|
|||
return csa->read(offset, true, false);
|
||||
}
|
||||
|
||||
#define CORESIGHT_CIDRn(i) (0xFF0 + ((i) * 4))
|
||||
|
||||
static inline u32 coresight_get_cid(void __iomem *base)
|
||||
{
|
||||
u32 i, cid = 0;
|
||||
|
||||
for (i = 0; i < 4; i++)
|
||||
cid |= readl(base + CORESIGHT_CIDRn(i)) << (i * 8);
|
||||
|
||||
return cid;
|
||||
}
|
||||
|
||||
static inline bool is_coresight_device(void __iomem *base)
|
||||
{
|
||||
u32 cid = coresight_get_cid(base);
|
||||
|
||||
return cid == CORESIGHT_CID;
|
||||
}
|
||||
|
||||
/*
|
||||
* Attempt to find and enable "APB clock" for the given device
|
||||
*
|
||||
* Returns:
|
||||
*
|
||||
* clk - Clock is found and enabled
|
||||
* NULL - clock is not found
|
||||
* ERROR - Clock is found but failed to enable
|
||||
*/
|
||||
static inline struct clk *coresight_get_enable_apb_pclk(struct device *dev)
|
||||
{
|
||||
struct clk *pclk;
|
||||
int ret;
|
||||
|
||||
pclk = clk_get(dev, "apb_pclk");
|
||||
if (IS_ERR(pclk))
|
||||
return NULL;
|
||||
|
||||
ret = clk_prepare_enable(pclk);
|
||||
if (ret) {
|
||||
clk_put(pclk);
|
||||
return ERR_PTR(ret);
|
||||
}
|
||||
return pclk;
|
||||
}
|
||||
|
||||
#define CORESIGHT_PIDRn(i) (0xFE0 + ((i) * 4))
|
||||
|
||||
static inline u32 coresight_get_pid(struct csdev_access *csa)
|
||||
{
|
||||
u32 i, pid = 0;
|
||||
|
||||
for (i = 0; i < 4; i++)
|
||||
pid |= csdev_access_relaxed_read32(csa, CORESIGHT_PIDRn(i)) << (i * 8);
|
||||
|
||||
return pid;
|
||||
}
|
||||
|
||||
static inline u64 csdev_access_relaxed_read_pair(struct csdev_access *csa,
|
||||
u32 lo_offset, u32 hi_offset)
|
||||
{
|
||||
|
|
Loading…
Reference in New Issue