Commit 0916447c authored by Mathieu Poirier's avatar Mathieu Poirier Committed by Greg Kroah-Hartman

coresight: Properly address concurrency in sink::update() functions

When operating in CPU-wide trace scenarios and working with an N:1
source/sink HW topology, update() functions need to be made atomic
in order to avoid racing with start and stop operations.
Signed-off-by: default avatarMathieu Poirier <mathieu.poirier@linaro.org>
Reviewed-by: default avatarSuzuki K Poulose <suzuki.poulose@arm.com>
Tested-by: default avatarLeo Yan <leo.yan@linaro.org>
Tested-by: default avatarRobert Walker <robert.walker@arm.com>
Signed-off-by: default avatarGreg Kroah-Hartman <gregkh@linuxfoundation.org>
parent 12dfc9e0
...@@ -405,7 +405,7 @@ static unsigned long etb_update_buffer(struct coresight_device *csdev, ...@@ -405,7 +405,7 @@ static unsigned long etb_update_buffer(struct coresight_device *csdev,
const u32 *barrier; const u32 *barrier;
u32 read_ptr, write_ptr, capacity; u32 read_ptr, write_ptr, capacity;
u32 status, read_data; u32 status, read_data;
unsigned long offset, to_read; unsigned long offset, to_read, flags;
struct cs_buffers *buf = sink_config; struct cs_buffers *buf = sink_config;
struct etb_drvdata *drvdata = dev_get_drvdata(csdev->dev.parent); struct etb_drvdata *drvdata = dev_get_drvdata(csdev->dev.parent);
...@@ -414,6 +414,7 @@ static unsigned long etb_update_buffer(struct coresight_device *csdev, ...@@ -414,6 +414,7 @@ static unsigned long etb_update_buffer(struct coresight_device *csdev,
capacity = drvdata->buffer_depth * ETB_FRAME_SIZE_WORDS; capacity = drvdata->buffer_depth * ETB_FRAME_SIZE_WORDS;
spin_lock_irqsave(&drvdata->spinlock, flags);
__etb_disable_hw(drvdata); __etb_disable_hw(drvdata);
CS_UNLOCK(drvdata->base); CS_UNLOCK(drvdata->base);
...@@ -524,6 +525,7 @@ static unsigned long etb_update_buffer(struct coresight_device *csdev, ...@@ -524,6 +525,7 @@ static unsigned long etb_update_buffer(struct coresight_device *csdev,
} }
__etb_enable_hw(drvdata); __etb_enable_hw(drvdata);
CS_LOCK(drvdata->base); CS_LOCK(drvdata->base);
spin_unlock_irqrestore(&drvdata->spinlock, flags);
return to_read; return to_read;
} }
......
...@@ -413,7 +413,7 @@ static unsigned long tmc_update_etf_buffer(struct coresight_device *csdev, ...@@ -413,7 +413,7 @@ static unsigned long tmc_update_etf_buffer(struct coresight_device *csdev,
u32 *buf_ptr; u32 *buf_ptr;
u64 read_ptr, write_ptr; u64 read_ptr, write_ptr;
u32 status; u32 status;
unsigned long offset, to_read; unsigned long offset, to_read, flags;
struct cs_buffers *buf = sink_config; struct cs_buffers *buf = sink_config;
struct tmc_drvdata *drvdata = dev_get_drvdata(csdev->dev.parent); struct tmc_drvdata *drvdata = dev_get_drvdata(csdev->dev.parent);
...@@ -424,6 +424,7 @@ static unsigned long tmc_update_etf_buffer(struct coresight_device *csdev, ...@@ -424,6 +424,7 @@ static unsigned long tmc_update_etf_buffer(struct coresight_device *csdev,
if (WARN_ON_ONCE(drvdata->mode != CS_MODE_PERF)) if (WARN_ON_ONCE(drvdata->mode != CS_MODE_PERF))
return 0; return 0;
spin_lock_irqsave(&drvdata->spinlock, flags);
CS_UNLOCK(drvdata->base); CS_UNLOCK(drvdata->base);
tmc_flush_and_stop(drvdata); tmc_flush_and_stop(drvdata);
...@@ -517,6 +518,7 @@ static unsigned long tmc_update_etf_buffer(struct coresight_device *csdev, ...@@ -517,6 +518,7 @@ static unsigned long tmc_update_etf_buffer(struct coresight_device *csdev,
to_read = buf->nr_pages << PAGE_SHIFT; to_read = buf->nr_pages << PAGE_SHIFT;
} }
CS_LOCK(drvdata->base); CS_LOCK(drvdata->base);
spin_unlock_irqrestore(&drvdata->spinlock, flags);
return to_read; return to_read;
} }
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment