Commit 0c3fc4d5 authored by Mathieu Poirier's avatar Mathieu Poirier Committed by Greg Kroah-Hartman

coresight: Add barrier packet for synchronisation

When a buffer overflow happens the synchronisation patckets usually
present at the beginning of the buffer are lost, a situation that
prevents the decoder from knowing the context of the traces being
decoded.

This patch adds a barrier packet to be used by sink IPs when a buffer
overflow condition is detected.  These barrier packets are then used
by the decoding library as markers to force re-synchronisation.
Signed-off-by: default avatarMathieu Poirier <mathieu.poirier@linaro.org>
Signed-off-by: default avatarGreg Kroah-Hartman <gregkh@linuxfoundation.org>
parent 4f871a9f
...@@ -200,8 +200,10 @@ static void etb_disable_hw(struct etb_drvdata *drvdata) ...@@ -200,8 +200,10 @@ static void etb_disable_hw(struct etb_drvdata *drvdata)
static void etb_dump_hw(struct etb_drvdata *drvdata) static void etb_dump_hw(struct etb_drvdata *drvdata)
{ {
bool lost = false;
int i; int i;
u8 *buf_ptr; u8 *buf_ptr;
const u32 *barrier;
u32 read_data, depth; u32 read_data, depth;
u32 read_ptr, write_ptr; u32 read_ptr, write_ptr;
u32 frame_off, frame_endoff; u32 frame_off, frame_endoff;
...@@ -223,16 +225,24 @@ static void etb_dump_hw(struct etb_drvdata *drvdata) ...@@ -223,16 +225,24 @@ static void etb_dump_hw(struct etb_drvdata *drvdata)
} }
if ((readl_relaxed(drvdata->base + ETB_STATUS_REG) if ((readl_relaxed(drvdata->base + ETB_STATUS_REG)
& ETB_STATUS_RAM_FULL) == 0) & ETB_STATUS_RAM_FULL) == 0) {
writel_relaxed(0x0, drvdata->base + ETB_RAM_READ_POINTER); writel_relaxed(0x0, drvdata->base + ETB_RAM_READ_POINTER);
else } else {
writel_relaxed(write_ptr, drvdata->base + ETB_RAM_READ_POINTER); writel_relaxed(write_ptr, drvdata->base + ETB_RAM_READ_POINTER);
lost = true;
}
depth = drvdata->buffer_depth; depth = drvdata->buffer_depth;
buf_ptr = drvdata->buf; buf_ptr = drvdata->buf;
barrier = barrier_pkt;
for (i = 0; i < depth; i++) { for (i = 0; i < depth; i++) {
read_data = readl_relaxed(drvdata->base + read_data = readl_relaxed(drvdata->base +
ETB_RAM_READ_DATA_REG); ETB_RAM_READ_DATA_REG);
if (lost && *barrier) {
read_data = *barrier;
barrier++;
}
*(u32 *)buf_ptr = read_data; *(u32 *)buf_ptr = read_data;
buf_ptr += 4; buf_ptr += 4;
} }
...@@ -354,6 +364,7 @@ static void etb_update_buffer(struct coresight_device *csdev, ...@@ -354,6 +364,7 @@ static void etb_update_buffer(struct coresight_device *csdev,
bool lost = false; bool lost = false;
int i, cur; int i, cur;
u8 *buf_ptr; u8 *buf_ptr;
const u32 *barrier;
u32 read_ptr, write_ptr, capacity; u32 read_ptr, write_ptr, capacity;
u32 status, read_data, to_read; u32 status, read_data, to_read;
unsigned long offset; unsigned long offset;
...@@ -438,10 +449,17 @@ static void etb_update_buffer(struct coresight_device *csdev, ...@@ -438,10 +449,17 @@ static void etb_update_buffer(struct coresight_device *csdev,
cur = buf->cur; cur = buf->cur;
offset = buf->offset; offset = buf->offset;
barrier = barrier_pkt;
for (i = 0; i < to_read; i += 4) { for (i = 0; i < to_read; i += 4) {
buf_ptr = buf->data_pages[cur] + offset; buf_ptr = buf->data_pages[cur] + offset;
read_data = readl_relaxed(drvdata->base + read_data = readl_relaxed(drvdata->base +
ETB_RAM_READ_DATA_REG); ETB_RAM_READ_DATA_REG);
if (lost && *barrier) {
read_data = *barrier;
barrier++;
}
*(u32 *)buf_ptr = read_data; *(u32 *)buf_ptr = read_data;
buf_ptr += 4; buf_ptr += 4;
......
...@@ -56,6 +56,8 @@ static ssize_t name##_show(struct device *_dev, \ ...@@ -56,6 +56,8 @@ static ssize_t name##_show(struct device *_dev, \
} \ } \
static DEVICE_ATTR_RO(name) static DEVICE_ATTR_RO(name)
extern const u32 barrier_pkt[5];
enum etm_addr_type { enum etm_addr_type {
ETM_ADDR_TYPE_NONE, ETM_ADDR_TYPE_NONE,
ETM_ADDR_TYPE_SINGLE, ETM_ADDR_TYPE_SINGLE,
......
...@@ -43,17 +43,34 @@ static void tmc_etb_enable_hw(struct tmc_drvdata *drvdata) ...@@ -43,17 +43,34 @@ static void tmc_etb_enable_hw(struct tmc_drvdata *drvdata)
static void tmc_etb_dump_hw(struct tmc_drvdata *drvdata) static void tmc_etb_dump_hw(struct tmc_drvdata *drvdata)
{ {
bool lost = false;
char *bufp; char *bufp;
u32 read_data; const u32 *barrier;
u32 read_data, status;
int i; int i;
/*
* Get a hold of the status register and see if a wrap around
* has occurred.
*/
status = readl_relaxed(drvdata->base + TMC_STS);
if (status & TMC_STS_FULL)
lost = true;
bufp = drvdata->buf; bufp = drvdata->buf;
drvdata->len = 0; drvdata->len = 0;
barrier = barrier_pkt;
while (1) { while (1) {
for (i = 0; i < drvdata->memwidth; i++) { for (i = 0; i < drvdata->memwidth; i++) {
read_data = readl_relaxed(drvdata->base + TMC_RRD); read_data = readl_relaxed(drvdata->base + TMC_RRD);
if (read_data == 0xFFFFFFFF) if (read_data == 0xFFFFFFFF)
return; return;
if (lost && *barrier) {
read_data = *barrier;
barrier++;
}
memcpy(bufp, &read_data, 4); memcpy(bufp, &read_data, 4);
bufp += 4; bufp += 4;
drvdata->len += 4; drvdata->len += 4;
...@@ -371,6 +388,7 @@ static void tmc_update_etf_buffer(struct coresight_device *csdev, ...@@ -371,6 +388,7 @@ static void tmc_update_etf_buffer(struct coresight_device *csdev,
{ {
bool lost = false; bool lost = false;
int i, cur; int i, cur;
const u32 *barrier;
u32 *buf_ptr; u32 *buf_ptr;
u32 read_ptr, write_ptr; u32 read_ptr, write_ptr;
u32 status, to_read; u32 status, to_read;
...@@ -451,12 +469,18 @@ static void tmc_update_etf_buffer(struct coresight_device *csdev, ...@@ -451,12 +469,18 @@ static void tmc_update_etf_buffer(struct coresight_device *csdev,
cur = buf->cur; cur = buf->cur;
offset = buf->offset; offset = buf->offset;
barrier = barrier_pkt;
/* for every byte to read */ /* for every byte to read */
for (i = 0; i < to_read; i += 4) { for (i = 0; i < to_read; i += 4) {
buf_ptr = buf->data_pages[cur] + offset; buf_ptr = buf->data_pages[cur] + offset;
*buf_ptr = readl_relaxed(drvdata->base + TMC_RRD); *buf_ptr = readl_relaxed(drvdata->base + TMC_RRD);
if (lost && *barrier) {
*buf_ptr = *barrier;
barrier++;
}
offset += 4; offset += 4;
if (offset >= PAGE_SIZE) { if (offset >= PAGE_SIZE) {
offset = 0; offset = 0;
......
...@@ -59,6 +59,8 @@ static void tmc_etr_enable_hw(struct tmc_drvdata *drvdata) ...@@ -59,6 +59,8 @@ static void tmc_etr_enable_hw(struct tmc_drvdata *drvdata)
static void tmc_etr_dump_hw(struct tmc_drvdata *drvdata) static void tmc_etr_dump_hw(struct tmc_drvdata *drvdata)
{ {
const u32 *barrier;
u32 *temp;
u32 rwp, val; u32 rwp, val;
rwp = readl_relaxed(drvdata->base + TMC_RWP); rwp = readl_relaxed(drvdata->base + TMC_RWP);
...@@ -71,6 +73,16 @@ static void tmc_etr_dump_hw(struct tmc_drvdata *drvdata) ...@@ -71,6 +73,16 @@ static void tmc_etr_dump_hw(struct tmc_drvdata *drvdata)
if (val & TMC_STS_FULL) { if (val & TMC_STS_FULL) {
drvdata->buf = drvdata->vaddr + rwp - drvdata->paddr; drvdata->buf = drvdata->vaddr + rwp - drvdata->paddr;
drvdata->len = drvdata->size; drvdata->len = drvdata->size;
barrier = barrier_pkt;
temp = (u32 *)drvdata->buf;
while (*barrier) {
*temp = *barrier;
temp++;
barrier++;
}
} else { } else {
drvdata->buf = drvdata->vaddr; drvdata->buf = drvdata->vaddr;
drvdata->len = rwp - drvdata->paddr; drvdata->len = rwp - drvdata->paddr;
......
...@@ -53,6 +53,14 @@ static DEFINE_PER_CPU(struct list_head *, tracer_path); ...@@ -53,6 +53,14 @@ static DEFINE_PER_CPU(struct list_head *, tracer_path);
*/ */
static struct list_head *stm_path; static struct list_head *stm_path;
/*
* When losing synchronisation a new barrier packet needs to be inserted at the
* beginning of the data collected in a buffer. That way the decoder knows that
* it needs to look for another sync sequence.
*/
const u32 barrier_pkt[5] = {0x7fffffff, 0x7fffffff,
0x7fffffff, 0x7fffffff, 0x0};
static int coresight_id_match(struct device *dev, void *data) static int coresight_id_match(struct device *dev, void *data)
{ {
int trace_id, i_trace_id; int trace_id, i_trace_id;
......
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