The returned pointer from .alloc_buffer() callback can be an error, if
only checking NULL pointer the driver cannot capture errors. The driver
will proceed even after failure and cause kernel panic.
Change to use IS_ERR_OR_NULL() check for capture error cases.
Fixes: 0bcbf2e30ff2 ("coresight: etm-perf: new PMU driver for ETM tracers")
Reported-by: Tamas Zsoldos <tamas.zsoldos(a)arm.com>
Signed-off-by: Leo Yan <leo.yan(a)arm.com>
---
drivers/hwtracing/coresight/coresight-etm-perf.c | 4 ++--
1 file changed, 2 insertions(+), 2 deletions(-)
diff --git a/drivers/hwtracing/coresight/coresight-etm-perf.c b/drivers/hwtracing/coresight/coresight-etm-perf.c
index f677c08233ba1a28b277674662c6e6db904873dd..440d967f5d0962df187a81b0dd69a7d82a8b62ba 100644
--- a/drivers/hwtracing/coresight/coresight-etm-perf.c
+++ b/drivers/hwtracing/coresight/coresight-etm-perf.c
@@ -198,7 +198,7 @@ static void free_sink_buffer(struct etm_event_data *event_data)
cpumask_t *mask = &event_data->mask;
struct coresight_device *sink;
- if (!event_data->snk_config)
+ if (IS_ERR_OR_NULL(event_data->snk_config))
return;
if (WARN_ON(cpumask_empty(mask)))
@@ -450,7 +450,7 @@ static void *etm_setup_aux(struct perf_event *event, void **pages,
event_data->snk_config =
sink_ops(sink)->alloc_buffer(sink, event, pages,
nr_pages, overwrite);
- if (!event_data->snk_config)
+ if (IS_ERR_OR_NULL(event_data->snk_config))
goto err;
out:
---
base-commit: fa71e9cb4cfa59abb196229667ec84929bdc18fe
change-id: 20250904-cs_etm_auxsetup_fix_error_handling-cb7e07ed9adf
Best regards,
--
Leo Yan <leo.yan(a)arm.com>
On 04/09/2025 02:12, Jie Gan wrote:
>
>
> On 9/3/2025 5:45 PM, Jie Gan wrote:
>>
>>
>> On 9/3/2025 4:57 PM, Suzuki K Poulose wrote:
>>> On 06/08/2025 09:09, Jie Gan wrote:
>>>> Some TPDM devices support both CMB and DSB datasets, requiring
>>>> the system to enable the port with both corresponding element sizes.
>>>>
>>>> Currently, the logic treats tpdm_read_element_size as successful if
>>>> the CMB element size is retrieved correctly, regardless of whether
>>>> the DSB element size is obtained. This behavior causes issues
>>>> when parsing data from TPDM devices that depend on both element sizes.
>>>>
>>>> To address this, the function should explicitly fail if the DSB
>>>> element size cannot be read correctly.
>>>
>>> But what is the device only has CMB ? Back when this was originally
>>
>> We have CMB TPDM, DSB TPDM and CMB&&DSB TPDM.
>>
>>> merged, we raised this question and the answer was, "Only one is
>>> supported, not both." But this sounds like that is wrong.
>>
>> I think we may not answer the previous question clearly. But it
>> definitely has issue here.
>>
>>> Could we defer the "Warning" to the caller. i.e., Let the caller
>>> figure out the if the DSB size is found and predicate that on the
>>> DSB support on the TPDM.
>>
>> Understood, below codes will be added in the caller to check the error:
>> if ((tpdm_data->dsb && !drvdata->dsb_esize) ||
>> (tpdm_data->cmb && !drvdata->cmb_esize))
>> goto err;
>>
>> Thanks,
>> Jie
>>
>
> Hi Suzuki,
>
> I've reviewed the logic here. It's not feasible for the caller to
> perform the check, since we first retrieve TPDM's drvdata, which adds
> complexity to the code. I believe it's better to handle this within the
> function itself.
>
> We are expecting the element_size for cmb if the condition is true, as
> well as dsb:
> if (tpdm_data->dsb)
> ...
> should obtain a valid element size for dsb.
> ...
>
> if (tpdm_data->cmb)
> ...
> should obtain a valid element size for cmb.
> ...
>
Ok, fair enough. Please resend the patch without the dependency on the
static TPDM patch. Given this is a fix, this could go in without waiting
for the new series.
Suzuki
> Thanks,
> Jie
>
>>>
>>> Suzuki
>>>
>>>>
>>>> Fixes: e6d7f5252f73 ("coresight-tpda: Add support to configure CMB
>>>> element")
>>>> Signed-off-by: Jie Gan <jie.gan(a)oss.qualcomm.com>
>>>> ---
>>>> drivers/hwtracing/coresight/coresight-tpda.c | 3 +++
>>>> 1 file changed, 3 insertions(+)
>>>>
>>>> diff --git a/drivers/hwtracing/coresight/coresight-tpda.c b/drivers/
>>>> hwtracing/coresight/coresight-tpda.c
>>>> index 0633f04beb24..333b3cb23685 100644
>>>> --- a/drivers/hwtracing/coresight/coresight-tpda.c
>>>> +++ b/drivers/hwtracing/coresight/coresight-tpda.c
>>>> @@ -71,6 +71,8 @@ static int tpdm_read_element_size(struct
>>>> tpda_drvdata *drvdata,
>>>> if (tpdm_data->dsb) {
>>>> rc = fwnode_property_read_u32(dev_fwnode(csdev->dev.parent),
>>>> "qcom,dsb-element-bits", &drvdata->dsb_esize);
>>>> + if (rc)
>>>> + goto out;
>>>> }
>>>> if (tpdm_data->cmb) {
>>>> @@ -78,6 +80,7 @@ static int tpdm_read_element_size(struct
>>>> tpda_drvdata *drvdata,
>>>> "qcom,cmb-element-bits", &drvdata->cmb_esize);
>>>> }
>>>> +out:
>>>> if (rc)
>>>> dev_warn_once(&csdev->dev,
>>>> "Failed to read TPDM Element size: %d\n", rc);
>>>
>>>
>>
>
On 06/08/2025 09:09, Jie Gan wrote:
> Some TPDM devices support both CMB and DSB datasets, requiring
> the system to enable the port with both corresponding element sizes.
>
> Currently, the logic treats tpdm_read_element_size as successful if
> the CMB element size is retrieved correctly, regardless of whether
> the DSB element size is obtained. This behavior causes issues
> when parsing data from TPDM devices that depend on both element sizes.
>
> To address this, the function should explicitly fail if the DSB
> element size cannot be read correctly.
But what is the device only has CMB ? Back when this was originally
merged, we raised this question and the answer was, "Only one is
supported, not both." But this sounds like that is wrong.
Could we defer the "Warning" to the caller. i.e., Let the caller
figure out the if the DSB size is found and predicate that on the
DSB support on the TPDM.
Suzuki
>
> Fixes: e6d7f5252f73 ("coresight-tpda: Add support to configure CMB element")
> Signed-off-by: Jie Gan <jie.gan(a)oss.qualcomm.com>
> ---
> drivers/hwtracing/coresight/coresight-tpda.c | 3 +++
> 1 file changed, 3 insertions(+)
>
> diff --git a/drivers/hwtracing/coresight/coresight-tpda.c b/drivers/hwtracing/coresight/coresight-tpda.c
> index 0633f04beb24..333b3cb23685 100644
> --- a/drivers/hwtracing/coresight/coresight-tpda.c
> +++ b/drivers/hwtracing/coresight/coresight-tpda.c
> @@ -71,6 +71,8 @@ static int tpdm_read_element_size(struct tpda_drvdata *drvdata,
> if (tpdm_data->dsb) {
> rc = fwnode_property_read_u32(dev_fwnode(csdev->dev.parent),
> "qcom,dsb-element-bits", &drvdata->dsb_esize);
> + if (rc)
> + goto out;
> }
>
> if (tpdm_data->cmb) {
> @@ -78,6 +80,7 @@ static int tpdm_read_element_size(struct tpda_drvdata *drvdata,
> "qcom,cmb-element-bits", &drvdata->cmb_esize);
> }
>
> +out:
> if (rc)
> dev_warn_once(&csdev->dev,
> "Failed to read TPDM Element size: %d\n", rc);
On Tue, 12 Aug 2025 01:24:45 -0700, Yuanfang Zhang wrote:
> The TRCEXTINSELR is only implemented if TRCIDR5.NUMEXTINSEL > 0.
> To avoid invalid accesses, introduce a check on numextinsel
> (derived from TRCIDR5[11:9]) before reading or writing to this register.
>
>
The patch looks good to me. May be we could expose this via sysfs, like we
do for the other fields. That can be a separate patch without the Fixes tag.
I have applied this patch to -next, thanks!
[1/1] coresight-etm4x: Conditionally access register TRCEXTINSELR
https://git.kernel.org/coresight/c/fa71e9cb4cfa
Best regards,
--
Suzuki K Poulose <suzuki.poulose(a)arm.com>
This patch series adds support for the Qualcomm CoreSight Interconnect TNOC
(Trace Network On Chip) block, which acts as a CoreSight graph link forwarding
trace data from subsystems to the Aggregator TNOC. Unlike the Aggregator TNOC,
this block does not support aggregation or ATID assignment.
Signed-off-by: Yuanfang Zhang <yuanfang.zhang(a)oss.qualcomm.com>
---
Changes in v3:
- Add detail for changes in V2.
- Remove '#address-cells' and '#size-cells' properties from in-ports field.
- Fix comment indentation for packet description.
- Link to v2: https://lore.kernel.org/r/20250819-itnoc-v2-0-2d0e6be44e2f@oss.qualcomm.com
Changes in v2:
- Removed the trailing '|' after the description in qcom,coresight-itnoc.yaml.
- Dropped the 'select' section from the YAML file.
- Updated node name to use a more generic naming convention.
- Removed the 'items' property from the compatible field.
- Deleted the description for the reg property.
- Dropped clock-names and adjusted the order of clock-names and clocks.
- Moved additionalProperties to follow the $ref of out-ports.
- Change "atid" type from u32 to int, set it as "-EOPNOTSUPP" for non-AMBA device.
- Link to v1: https://lore.kernel.org/r/20250815-itnoc-v1-0-62c8e4f7ad32@oss.qualcomm.com
---
Yuanfang Zhang (3):
dt-bindings: arm: qcom: Add Coresight Interconnect TNOC
coresight-tnoc: add platform driver to support Interconnect TNOC
coresight-tnoc: Add runtime PM support for Interconnect TNOC
.../bindings/arm/qcom,coresight-itnoc.yaml | 90 +++++++++++++
drivers/hwtracing/coresight/coresight-tnoc.c | 139 +++++++++++++++++++--
2 files changed, 216 insertions(+), 13 deletions(-)
---
base-commit: 2b52cf338d39d684a1c6af298e8204902c026aca
change-id: 20250815-itnoc-460273d1b80c
Best regards,
--
Yuanfang Zhang <yuanfang.zhang(a)oss.qualcomm.com>
On 27/08/2025 11:55 am, Jie Gan wrote:
> Patchset 1 introduces configuration of the cross-trigger registers with
> appropriate values to enable proper generation of cross-trigger packets.
>
> Patchset 2 introduces a logic to configure the TPDA_SYNCR register,
> which determines the frequency of ASYNC packet generation. These packets
> assist userspace tools in accurately identifying each valid packet.
>
> Patchset 3 introduces a sysfs node to initiate a flush request for the
> specific port, forcing the data to synchronize and be transmitted to the
> sink device.
>
> Changes in V3:
> 1. Optimizing codes according to James's comment.
> Link to V2 - https://lore.kernel.org/all/20250827042042.6786-1-jie.gan@oss.qualcomm.com/
>
> Changes in V2:
> 1. Refactoring the code based on James's comment for optimization.
> Link to V1 - https://lore.kernel.org/all/20250826070150.5603-1-jie.gan@oss.qualcomm.com/
>
> Tao Zhang (3):
> coresight: tpda: add sysfs nodes for tpda cross-trigger configuration
> coresight: tpda: add logic to configure TPDA_SYNCR register
> coresight: tpda: add sysfs node to flush specific port
>
> .../testing/sysfs-bus-coresight-devices-tpda | 50 ++++
> drivers/hwtracing/coresight/coresight-tpda.c | 278 ++++++++++++++++++
> drivers/hwtracing/coresight/coresight-tpda.h | 33 ++-
> 3 files changed, 360 insertions(+), 1 deletion(-)
> create mode 100644 Documentation/ABI/testing/sysfs-bus-coresight-devices-tpda
>
Reviewed-by: James Clark <james.clark(a)linaro.org>
On 27/08/2025 10:48 am, Jie Gan wrote:
>
>
> On 8/27/2025 5:17 PM, James Clark wrote:
>>
>>
>> On 27/08/2025 5:20 am, Jie Gan wrote:
>>> From: Tao Zhang <tao.zhang(a)oss.qualcomm.com>
>>>
>>> Setting bit i in the TPDA_FLUSH_CR register initiates a flush request
>>> for port i, forcing the data to synchronize and be transmitted to the
>>> sink device.
>>>
>>> Signed-off-by: Tao Zhang <tao.zhang(a)oss.qualcomm.com>
>>> Co-developed-by: Jie Gan <jie.gan(a)oss.qualcomm.com>
>>> Signed-off-by: Jie Gan <jie.gan(a)oss.qualcomm.com>
>>> ---
>>> .../testing/sysfs-bus-coresight-devices-tpda | 7 ++++
>>> drivers/hwtracing/coresight/coresight-tpda.c | 42 +++++++++++++++++++
>>> drivers/hwtracing/coresight/coresight-tpda.h | 2 +
>>> 3 files changed, 51 insertions(+)
>>>
>>> diff --git a/Documentation/ABI/testing/sysfs-bus-coresight-devices-
>>> tpda b/Documentation/ABI/testing/sysfs-bus-coresight-devices-tpda
>>> index fb651aebeb31..2cf2dcfc13c8 100644
>>> --- a/Documentation/ABI/testing/sysfs-bus-coresight-devices-tpda
>>> +++ b/Documentation/ABI/testing/sysfs-bus-coresight-devices-tpda
>>> @@ -41,3 +41,10 @@ Contact: Jinlong Mao
>>> <jinlong.mao(a)oss.qualcomm.com>, Tao Zhang <tao.zhang(a)oss.qu
>>> Description:
>>> (RW) Configure the CMB/MCMB channel mode for all enabled
>>> ports.
>>> Value 0 means raw channel mapping mode. Value 1 means
>>> channel pair marking mode.
>>> +
>>> +What: /sys/bus/coresight/devices/<tpda-name>/port_flush_req
>>> +Date: August 2025
>>> +KernelVersion: 6.17
>>> +Contact: Jinlong Mao <jinlong.mao(a)oss.qualcomm.com>, Tao Zhang
>>> <tao.zhang(a)oss.qualcomm.com>, Jie Gan <jie.gan(a)oss.qualcomm.com>
>>> +Description:
>>> + (RW) Configure the bit i to requests a flush operation of
>>> port i on the TPDA.
>>> diff --git a/drivers/hwtracing/coresight/coresight-tpda.c b/drivers/
>>> hwtracing/coresight/coresight-tpda.c
>>> index 430f76c559f2..8b1fe128881d 100644
>>> --- a/drivers/hwtracing/coresight/coresight-tpda.c
>>> +++ b/drivers/hwtracing/coresight/coresight-tpda.c
>>> @@ -487,6 +487,47 @@ static ssize_t cmbchan_mode_store(struct device
>>> *dev,
>>> }
>>> static DEVICE_ATTR_RW(cmbchan_mode);
>>> +static ssize_t port_flush_req_show(struct device *dev,
>>> + struct device_attribute *attr,
>>> + char *buf)
>>> +{
>>> + struct tpda_drvdata *drvdata = dev_get_drvdata(dev->parent);
>>> + unsigned long val;
>>> +
>>> + if (!drvdata->csdev->refcnt)
>>> + return -EINVAL;
>>> +
>>> + guard(spinlock)(&drvdata->spinlock);
>>> + CS_UNLOCK(drvdata->base);
>>> + val = readl_relaxed(drvdata->base + TPDA_FLUSH_CR);
>>> + CS_LOCK(drvdata->base);
>>> + return sysfs_emit(buf, "%lx\n", val);
>>
>> Still missing the 0x prefix
>
> Will re-check rest of the codes and add prefix. Sorry I missed it during
> the review process.
>
>>
>>> +}
>>> +
>>> +static ssize_t port_flush_req_store(struct device *dev,
>>> + struct device_attribute *attr,
>>> + const char *buf,
>>> + size_t size)
>>> +{
>>> + struct tpda_drvdata *drvdata = dev_get_drvdata(dev->parent);
>>> + unsigned long val;
>>> +
>>> + if (kstrtoul(buf, 0, &val))
>>> + return -EINVAL;
>>> +
>>> + if (!drvdata->csdev->refcnt || !val)
>>> + return -EINVAL;
>>> +
>>> + val |= FIELD_PREP(TPDA_MAX_INPORTS_MASK, val);
>>
>> Using FIELD_PREP() now that it's the full width of the register makes
>> less sense. Especially when there is no corresponding FIELD_FIT()
>> check, which is fine because everything always fits. But if you
>> didn't know the mask was the full width you'd wonder if the check is
>> missing.
>>
>> I would just write val directly to TPDA_FLUSH_CR so it's simpler.
>>
>> It should also have been val = FIELD_PREP(...)
>
> Yeah, it should have been val = FIELD_PREP(...) here... sorry for the
> mistake here..
>
> I was thinking the unsigned long here could be 64 or 32 bits and we only
> need the value of the lower 32 bits. So that's why I am using val =
> FIELD_PREP(...) here. We shouldn't write a value greater than UINT32_MAX
> to the register.
>
> Thanks,
> Jie
>
writel_relaxed() is always 32 bits though so it is a bit confusing if
you truncate the user value without an error. Also a reason to use u32
instead of unsigned long types.
Are you trying to support arm and arm64 with tpda? Or just arm64? For it
to be consistent you can use kstrtou32(), or use kstrtoull() and then
FIELD_FIT() to error on truncation. kstrtou32() is probably the cleanest.
>>
>>> + guard(spinlock)(&drvdata->spinlock);
>>> + CS_UNLOCK(drvdata->base);
>>> + writel_relaxed(val, drvdata->base + TPDA_FLUSH_CR);
>>> + CS_LOCK(drvdata->base);
>>> +
>>> + return size;
>>> +}
>>> +static DEVICE_ATTR_RW(port_flush_req);
>>> +
>>> static struct attribute *tpda_attrs[] = {
>>> &dev_attr_trig_async_enable.attr,
>>> &dev_attr_trig_flag_ts_enable.attr,
>>> @@ -494,6 +535,7 @@ static struct attribute *tpda_attrs[] = {
>>> &dev_attr_freq_ts_enable.attr,
>>> &dev_attr_global_flush_req.attr,
>>> &dev_attr_cmbchan_mode.attr,
>>> + &dev_attr_port_flush_req.attr,
>>> NULL,
>>> };
>>> diff --git a/drivers/hwtracing/coresight/coresight-tpda.h b/drivers/
>>> hwtracing/coresight/coresight-tpda.h
>>> index 8e1b66115ad1..56d3ad293e46 100644
>>> --- a/drivers/hwtracing/coresight/coresight-tpda.h
>>> +++ b/drivers/hwtracing/coresight/coresight-tpda.h
>>> @@ -10,6 +10,7 @@
>>> #define TPDA_Pn_CR(n) (0x004 + (n * 4))
>>> #define TPDA_FPID_CR (0x084)
>>> #define TPDA_SYNCR (0x08C)
>>> +#define TPDA_FLUSH_CR (0x090)
>>> /* Cross trigger FREQ packets timestamp bit */
>>> #define TPDA_CR_FREQTS BIT(2)
>>> @@ -35,6 +36,7 @@
>>> #define TPDA_SYNCR_MAX_COUNTER_VAL (0xFFF)
>>> #define TPDA_MAX_INPORTS 32
>>> +#define TPDA_MAX_INPORTS_MASK GENMASK(31, 0)
>>> /* Bits 6 ~ 12 is for atid value */
>>> #define TPDA_CR_ATID GENMASK(12, 6)
>>
>>
>
On 27/08/2025 5:20 am, Jie Gan wrote:
> From: Tao Zhang <tao.zhang(a)oss.qualcomm.com>
>
> The TPDA_SYNCR register defines the frequency at which TPDA generates
> ASYNC packets, enabling userspace tools to accurately parse each valid
> packet.
>
> Signed-off-by: Tao Zhang <tao.zhang(a)oss.qualcomm.com>
> Co-developed-by: Jie Gan <jie.gan(a)oss.qualcomm.com>
> Signed-off-by: Jie Gan <jie.gan(a)oss.qualcomm.com>
> ---
> drivers/hwtracing/coresight/coresight-tpda.c | 7 +++++++
> drivers/hwtracing/coresight/coresight-tpda.h | 6 ++++++
> 2 files changed, 13 insertions(+)
>
> diff --git a/drivers/hwtracing/coresight/coresight-tpda.c b/drivers/hwtracing/coresight/coresight-tpda.c
> index 647ab49a98d7..430f76c559f2 100644
> --- a/drivers/hwtracing/coresight/coresight-tpda.c
> +++ b/drivers/hwtracing/coresight/coresight-tpda.c
> @@ -187,6 +187,13 @@ static void tpda_enable_pre_port(struct tpda_drvdata *drvdata)
> */
> if (drvdata->trig_flag_ts)
> writel_relaxed(0x0, drvdata->base + TPDA_FPID_CR);
> +
> + /* Program the counter value for TPDA_SYNCR */
> + val = readl_relaxed(drvdata->base + TPDA_SYNCR);
> + /* Clear the mode */
> + val &= ~TPDA_SYNCR_MODE_CTRL;
> + val |= FIELD_PREP(TPDA_SYNCR_COUNTER_MASK, TPDA_SYNCR_MAX_COUNTER_VAL);
Just use the mask directly if you want to set all the bits. This makes
it seem like the MAX_COUNTER_VAL is something different.
val |= TPDA_SYNCR_COUNTER_MASK
> + writel_relaxed(val, drvdata->base + TPDA_SYNCR);
> }
>
> static int tpda_enable_port(struct tpda_drvdata *drvdata, int port)
> diff --git a/drivers/hwtracing/coresight/coresight-tpda.h b/drivers/hwtracing/coresight/coresight-tpda.h
> index 0be625fb52fd..8e1b66115ad1 100644
> --- a/drivers/hwtracing/coresight/coresight-tpda.h
> +++ b/drivers/hwtracing/coresight/coresight-tpda.h
> @@ -9,6 +9,7 @@
> #define TPDA_CR (0x000)
> #define TPDA_Pn_CR(n) (0x004 + (n * 4))
> #define TPDA_FPID_CR (0x084)
> +#define TPDA_SYNCR (0x08C)
>
> /* Cross trigger FREQ packets timestamp bit */
> #define TPDA_CR_FREQTS BIT(2)
> @@ -27,6 +28,11 @@
> #define TPDA_Pn_CR_CMBSIZE GENMASK(7, 6)
> /* Aggregator port DSB data set element size bit */
> #define TPDA_Pn_CR_DSBSIZE BIT(8)
> +/* TPDA_SYNCR mode control bit */
> +#define TPDA_SYNCR_MODE_CTRL BIT(12)
> +/* TPDA_SYNCR counter mask */
> +#define TPDA_SYNCR_COUNTER_MASK GENMASK(11, 0)
> +#define TPDA_SYNCR_MAX_COUNTER_VAL (0xFFF)
No need to define a numeric value that's the same as the mask. It also
opens the possibility of making a mistake.
>
> #define TPDA_MAX_INPORTS 32
>