Groups | Search | Server Info | Keyboard shortcuts | Login | Register [http] [https] [nntp] [nntps]


Groups > linux.kernel > #1382533 > unrolled thread

Re: [PATCH V2 11/15] coresight: tmc: make sysFS and Perf mode mutually exclusive

Started bySuzuki K Poulose <Suzuki.Poulose@arm.com>
First post2016-04-19 15:50 +0200
Last post2016-04-19 18:20 +0200
Articles 2 — 2 participants

Back to article view | Back to linux.kernel

This discussion starts older than the indexed window; earlier articles aren't shown. The article labeled Started by below is the oldest one visible, not the original post.


Contents

  Re: [PATCH V2 11/15] coresight: tmc: make sysFS and Perf mode  mutually exclusive Suzuki K Poulose <Suzuki.Poulose@arm.com> - 2016-04-19 15:50 +0200
    Re: [PATCH V2 11/15] coresight: tmc: make sysFS and Perf mode  mutually exclusive Mathieu Poirier <mathieu.poirier@linaro.org> - 2016-04-19 18:20 +0200

#1382533 — Re: [PATCH V2 11/15] coresight: tmc: make sysFS and Perf mode mutually exclusive

FromSuzuki K Poulose <Suzuki.Poulose@arm.com>
Date2016-04-19 15:50 +0200
SubjectRe: [PATCH V2 11/15] coresight: tmc: make sysFS and Perf mode mutually exclusive
Message-ID<rpEcq-7GG-31@gated-at.bofh.it>
On 12/04/16 18:54, Mathieu Poirier wrote:
> The sysFS and Perf access methods can't be allowed to interfere
> with one another.  As such introducing guards to access
> functions that prevents moving forward if a TMC is already
> being used.
>
> Signed-off-by: Mathieu Poirier <mathieu.poirier@linaro.org>
> ---
>   drivers/hwtracing/coresight/coresight-tmc-etf.c | 59 +++++++++++++++++++++-
>   drivers/hwtracing/coresight/coresight-tmc-etr.c | 67 +++++++++++++++++++++++--
>   2 files changed, 119 insertions(+), 7 deletions(-)
>
> diff --git a/drivers/hwtracing/coresight/coresight-tmc-etf.c b/drivers/hwtracing/coresight/coresight-tmc-etf.c
> index 9b4cdaed09f5..50d32e8ef4ea 100644
> --- a/drivers/hwtracing/coresight/coresight-tmc-etf.c
> +++ b/drivers/hwtracing/coresight/coresight-tmc-etf.c
> @@ -111,7 +111,7 @@ static void tmc_etf_disable_hw(struct tmc_drvdata *drvdata)
>   	CS_LOCK(drvdata->base);
>   }
>
> -static int tmc_enable_etf_sink(struct coresight_device *csdev, u32 mode)
> +static int tmc_enable_etf_sink_sysfs(struct coresight_device *csdev, u32 mode)
>   {
>   	bool allocated = false;
>   	char *buf = NULL;
> @@ -189,6 +189,53 @@ out:
>   	return 0;
>   }
>
> +static int tmc_enable_etf_sink_perf(struct coresight_device *csdev, u32 mode)
> +{
> +	int ret = 0;
> +	u32 val;

To be on the safer side, I believe 'val' should be unsigned long, to match the size of local_t.

> +	unsigned long flags;
> +	struct tmc_drvdata *drvdata = dev_get_drvdata(csdev->dev.parent);
> +
> +	 /* This shouldn't be happening */
> +	WARN_ON(mode != CS_MODE_PERF);

I think the above check, and the mode parameter itself is superfluous, given
that this is a static function used internally only for the PERF mode.
Similarly for the _sysfs version.

> +
> +	spin_lock_irqsave(&drvdata->spinlock, flags);
> +	if (drvdata->reading) {
> +		ret = -EINVAL;
> +		goto out;
> +	}
> +
> +	val = local_xchg(&drvdata->mode, mode);

We should be using local_cmpxchg() here. Otherwise, we could corrupt the mode.
Similarly for the _sysfs version. I though the previous version of your series
did that.

> +	/*
> +	 * In Perf mode there can be only one writer per sink.  There
> +	 * is also no need to continue if the ETB/ETR is already operated
> +	 * from sysFS.
> +	 */
> +	if (val != CS_MODE_DISABLED) {
> +		ret = -EINVAL;
> +		goto out;
> +	}


>   static void tmc_disable_etf_sink(struct coresight_device *csdev)
>   {
>   	u32 val;
> @@ -271,6 +318,7 @@ const struct coresight_ops tmc_etf_cs_ops = {
>
>   int tmc_read_prepare_etb(struct tmc_drvdata *drvdata)
>   {
> +	u32 val;
>   	enum tmc_mode mode;
>   	int ret = 0;
>   	unsigned long flags;
> @@ -289,6 +337,13 @@ int tmc_read_prepare_etb(struct tmc_drvdata *drvdata)
>   		goto out;
>   	}
>
> +	val = local_read(&drvdata->mode);
> +	/* Don't interfere if operated from Perf */
> +	if (val == CS_MODE_PERF) {
> +		ret = -EINVAL;
> +		goto out;
> +	}

Could we get here when CS_DISABLED ? If not, we could get rid of the check
for CS_MODE_SYSFS below.

> +
>   	/* If drvdata::buf is NULL the trace data has been read already */
>   	if (drvdata->buf == NULL) {
>   		ret = -EINVAL;
> @@ -296,7 +351,7 @@ int tmc_read_prepare_etb(struct tmc_drvdata *drvdata)
>   	}
>
>   	/* Disable the TMC if need be */
> -	if (local_read(&drvdata->mode) == CS_MODE_SYSFS)
> +	if (val == CS_MODE_SYSFS)
>   		tmc_etb_disable_hw(drvdata);
See above

>   	drvdata->reading = true;
> diff --git a/drivers/hwtracing/coresight/coresight-tmc-etr.c b/drivers/hwtracing/coresight/coresight-tmc-etr.c
> index de5cf0056802..04fc63d85696 100644
> --- a/drivers/hwtracing/coresight/coresight-tmc-etr.c
> +++ b/drivers/hwtracing/coresight/coresight-tmc-etr.c
> @@ -87,7 +87,7 @@ static void tmc_etr_disable_hw(struct tmc_drvdata *drvdata)
>   	CS_LOCK(drvdata->base);
>   }
>
> -static int tmc_enable_etr_sink(struct coresight_device *csdev, u32 mode)
> +static int tmc_enable_etr_sink_sysfs(struct coresight_device *csdev, u32 mode)
>   {
>   	bool allocated = false;
>   	u32 val;
> @@ -166,6 +166,53 @@ out:
>   	return 0;
>   }
>

> +static int tmc_enable_etr_sink_perf(struct coresight_device *csdev, u32 mode)
...

>   static void tmc_disable_etr_sink(struct coresight_device *csdev)

Same comments as for the etb side.

Suzuki

  {

[toc] | [next] | [standalone]


#1382679

FromMathieu Poirier <mathieu.poirier@linaro.org>
Date2016-04-19 18:20 +0200
Message-ID<rpGxB-1bm-45@gated-at.bofh.it>
In reply to#1382533
On 19 April 2016 at 07:42, Suzuki K Poulose <Suzuki.Poulose@arm.com> wrote:
> On 12/04/16 18:54, Mathieu Poirier wrote:
>>
>> The sysFS and Perf access methods can't be allowed to interfere
>> with one another.  As such introducing guards to access
>> functions that prevents moving forward if a TMC is already
>> being used.
>>
>> Signed-off-by: Mathieu Poirier <mathieu.poirier@linaro.org>
>> ---
>>   drivers/hwtracing/coresight/coresight-tmc-etf.c | 59
>> +++++++++++++++++++++-
>>   drivers/hwtracing/coresight/coresight-tmc-etr.c | 67
>> +++++++++++++++++++++++--
>>   2 files changed, 119 insertions(+), 7 deletions(-)
>>
>> diff --git a/drivers/hwtracing/coresight/coresight-tmc-etf.c
>> b/drivers/hwtracing/coresight/coresight-tmc-etf.c
>> index 9b4cdaed09f5..50d32e8ef4ea 100644
>> --- a/drivers/hwtracing/coresight/coresight-tmc-etf.c
>> +++ b/drivers/hwtracing/coresight/coresight-tmc-etf.c
>> @@ -111,7 +111,7 @@ static void tmc_etf_disable_hw(struct tmc_drvdata
>> *drvdata)
>>         CS_LOCK(drvdata->base);
>>   }
>>
>> -static int tmc_enable_etf_sink(struct coresight_device *csdev, u32 mode)
>> +static int tmc_enable_etf_sink_sysfs(struct coresight_device *csdev, u32
>> mode)
>>   {
>>         bool allocated = false;
>>         char *buf = NULL;
>> @@ -189,6 +189,53 @@ out:
>>         return 0;
>>   }
>>
>> +static int tmc_enable_etf_sink_perf(struct coresight_device *csdev, u32
>> mode)
>> +{
>> +       int ret = 0;
>> +       u32 val;
>
>
> To be on the safer side, I believe 'val' should be unsigned long, to match
> the size of local_t.
>
>> +       unsigned long flags;
>> +       struct tmc_drvdata *drvdata = dev_get_drvdata(csdev->dev.parent);
>> +
>> +        /* This shouldn't be happening */
>> +       WARN_ON(mode != CS_MODE_PERF);
>
>
> I think the above check, and the mode parameter itself is superfluous, given
> that this is a static function used internally only for the PERF mode.
> Similarly for the _sysfs version.

We definitely misunderstood each other then - the only reason I added
the checks is after what (I thought) you suggested in the previous
revision.

>
>> +
>> +       spin_lock_irqsave(&drvdata->spinlock, flags);
>> +       if (drvdata->reading) {
>> +               ret = -EINVAL;
>> +               goto out;
>> +       }
>> +
>> +       val = local_xchg(&drvdata->mode, mode);
>
>
> We should be using local_cmpxchg() here. Otherwise, we could corrupt the
> mode.

The newly added (above) check allows us to do that now.  There can
only be one value coming in (CS_MODE_PERF) and the current type can
only be CS_MODE_PERF/DISABLED.

> Similarly for the _sysfs version. I though the previous version of your
> series
> did that.
>
>> +       /*
>> +        * In Perf mode there can be only one writer per sink.  There
>> +        * is also no need to continue if the ETB/ETR is already operated
>> +        * from sysFS.
>> +        */
>> +       if (val != CS_MODE_DISABLED) {
>> +               ret = -EINVAL;
>> +               goto out;
>> +       }
>
>
>
>>   static void tmc_disable_etf_sink(struct coresight_device *csdev)
>>   {
>>         u32 val;
>> @@ -271,6 +318,7 @@ const struct coresight_ops tmc_etf_cs_ops = {
>>
>>   int tmc_read_prepare_etb(struct tmc_drvdata *drvdata)
>>   {
>> +       u32 val;
>>         enum tmc_mode mode;
>>         int ret = 0;
>>         unsigned long flags;
>> @@ -289,6 +337,13 @@ int tmc_read_prepare_etb(struct tmc_drvdata *drvdata)
>>                 goto out;
>>         }
>>
>> +       val = local_read(&drvdata->mode);
>> +       /* Don't interfere if operated from Perf */
>> +       if (val == CS_MODE_PERF) {
>> +               ret = -EINVAL;
>> +               goto out;
>> +       }
>
>
> Could we get here when CS_DISABLED ? If not, we could get rid of the check
> for CS_MODE_SYSFS below.
>
>> +
>>         /* If drvdata::buf is NULL the trace data has been read already */
>>         if (drvdata->buf == NULL) {
>>                 ret = -EINVAL;
>> @@ -296,7 +351,7 @@ int tmc_read_prepare_etb(struct tmc_drvdata *drvdata)
>>         }
>>
>>         /* Disable the TMC if need be */
>> -       if (local_read(&drvdata->mode) == CS_MODE_SYSFS)
>> +       if (val == CS_MODE_SYSFS)
>>                 tmc_etb_disable_hw(drvdata);
>
> See above

Yes, we can get here when mode is set to CS_MODE_DISABLED.  Someone
can read the /dev/xyz entry whenever they want, including when a sink
hasn't been enabled.

Thanks,
Mathieu

>
>>         drvdata->reading = true;
>> diff --git a/drivers/hwtracing/coresight/coresight-tmc-etr.c
>> b/drivers/hwtracing/coresight/coresight-tmc-etr.c
>> index de5cf0056802..04fc63d85696 100644
>> --- a/drivers/hwtracing/coresight/coresight-tmc-etr.c
>> +++ b/drivers/hwtracing/coresight/coresight-tmc-etr.c
>> @@ -87,7 +87,7 @@ static void tmc_etr_disable_hw(struct tmc_drvdata
>> *drvdata)
>>         CS_LOCK(drvdata->base);
>>   }
>>
>> -static int tmc_enable_etr_sink(struct coresight_device *csdev, u32 mode)
>> +static int tmc_enable_etr_sink_sysfs(struct coresight_device *csdev, u32
>> mode)
>>   {
>>         bool allocated = false;
>>         u32 val;
>> @@ -166,6 +166,53 @@ out:
>>         return 0;
>>   }
>>
>
>> +static int tmc_enable_etr_sink_perf(struct coresight_device *csdev, u32
>> mode)
>
> ...
>
>>   static void tmc_disable_etr_sink(struct coresight_device *csdev)
>
>
> Same comments as for the etb side.
>
> Suzuki
>
>  {
>

[toc] | [prev] | [standalone]


Back to top | Article view | linux.kernel


csiph-web