coresight: Add barrier packet for synchronisation
authorMathieu Poirier <mathieu.poirier@linaro.org>
Wed, 2 Aug 2017 16:21:57 +0000 (10:21 -0600)
committerGreg Kroah-Hartman <gregkh@linuxfoundation.org>
Mon, 28 Aug 2017 14:05:47 +0000 (16:05 +0200)
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: Mathieu Poirier <mathieu.poirier@linaro.org>
Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
drivers/hwtracing/coresight/coresight-etb10.c
drivers/hwtracing/coresight/coresight-priv.h
drivers/hwtracing/coresight/coresight-tmc-etf.c
drivers/hwtracing/coresight/coresight-tmc-etr.c
drivers/hwtracing/coresight/coresight.c

index 50f4846e627126db69128bca456a5ce4820ff96a..42360306f049cefba9a911ec45d93e519e3a7f4b 100644 (file)
@@ -200,8 +200,10 @@ static void etb_disable_hw(struct etb_drvdata *drvdata)
 
 static void etb_dump_hw(struct etb_drvdata *drvdata)
 {
+       bool lost = false;
        int i;
        u8 *buf_ptr;
+       const u32 *barrier;
        u32 read_data, depth;
        u32 read_ptr, write_ptr;
        u32 frame_off, frame_endoff;
@@ -223,16 +225,24 @@ static void etb_dump_hw(struct etb_drvdata *drvdata)
        }
 
        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);
-       else
+       } else {
                writel_relaxed(write_ptr, drvdata->base + ETB_RAM_READ_POINTER);
+               lost = true;
+       }
 
        depth = drvdata->buffer_depth;
        buf_ptr = drvdata->buf;
+       barrier = barrier_pkt;
        for (i = 0; i < depth; i++) {
                read_data = readl_relaxed(drvdata->base +
                                          ETB_RAM_READ_DATA_REG);
+               if (lost && *barrier) {
+                       read_data = *barrier;
+                       barrier++;
+               }
+
                *(u32 *)buf_ptr = read_data;
                buf_ptr += 4;
        }
@@ -354,6 +364,7 @@ static void etb_update_buffer(struct coresight_device *csdev,
        bool lost = false;
        int i, cur;
        u8 *buf_ptr;
+       const u32 *barrier;
        u32 read_ptr, write_ptr, capacity;
        u32 status, read_data, to_read;
        unsigned long offset;
@@ -438,10 +449,17 @@ static void etb_update_buffer(struct coresight_device *csdev,
 
        cur = buf->cur;
        offset = buf->offset;
+       barrier = barrier_pkt;
+
        for (i = 0; i < to_read; i += 4) {
                buf_ptr = buf->data_pages[cur] + offset;
                read_data = readl_relaxed(drvdata->base +
                                          ETB_RAM_READ_DATA_REG);
+               if (lost && *barrier) {
+                       read_data = *barrier;
+                       barrier++;
+               }
+
                *(u32 *)buf_ptr = read_data;
                buf_ptr += 4;
 
index 5f662d82052c5c148ba334f1569d5dbd1f975df6..3e25b1dd1a1a640da3222e19a8ce1e87865d6103 100644 (file)
@@ -56,6 +56,8 @@ static ssize_t name##_show(struct device *_dev,                               \
 }                                                                      \
 static DEVICE_ATTR_RO(name)
 
+extern const u32 barrier_pkt[5];
+
 enum etm_addr_type {
        ETM_ADDR_TYPE_NONE,
        ETM_ADDR_TYPE_SINGLE,
index 2e0fb5b9372cc92ea6a6e0ab62f8431fe8356fbb..d189b28bd5c44583548bf408063f0bb23babafab 100644 (file)
@@ -43,17 +43,34 @@ static void tmc_etb_enable_hw(struct tmc_drvdata *drvdata)
 
 static void tmc_etb_dump_hw(struct tmc_drvdata *drvdata)
 {
+       bool lost = false;
        char *bufp;
-       u32 read_data;
+       const u32 *barrier;
+       u32 read_data, status;
        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;
        drvdata->len = 0;
+       barrier = barrier_pkt;
        while (1) {
                for (i = 0; i < drvdata->memwidth; i++) {
                        read_data = readl_relaxed(drvdata->base + TMC_RRD);
                        if (read_data == 0xFFFFFFFF)
                                return;
+
+                       if (lost && *barrier) {
+                               read_data = *barrier;
+                               barrier++;
+                       }
+
                        memcpy(bufp, &read_data, 4);
                        bufp += 4;
                        drvdata->len += 4;
@@ -371,6 +388,7 @@ static void tmc_update_etf_buffer(struct coresight_device *csdev,
 {
        bool lost = false;
        int i, cur;
+       const u32 *barrier;
        u32 *buf_ptr;
        u32 read_ptr, write_ptr;
        u32 status, to_read;
@@ -451,12 +469,18 @@ static void tmc_update_etf_buffer(struct coresight_device *csdev,
 
        cur = buf->cur;
        offset = buf->offset;
+       barrier = barrier_pkt;
 
        /* for every byte to read */
        for (i = 0; i < to_read; i += 4) {
                buf_ptr = buf->data_pages[cur] + offset;
                *buf_ptr = readl_relaxed(drvdata->base + TMC_RRD);
 
+               if (lost && *barrier) {
+                       *buf_ptr = *barrier;
+                       barrier++;
+               }
+
                offset += 4;
                if (offset >= PAGE_SIZE) {
                        offset = 0;
index 5d312699b3b9d3a27e3039459d0c5f13097f548c..b8fb981de7b695f792000f535d37cf530e29e849 100644 (file)
@@ -59,6 +59,8 @@ static void tmc_etr_enable_hw(struct tmc_drvdata *drvdata)
 
 static void tmc_etr_dump_hw(struct tmc_drvdata *drvdata)
 {
+       const u32 *barrier;
+       u32 *temp;
        u32 rwp, val;
 
        rwp = readl_relaxed(drvdata->base + TMC_RWP);
@@ -71,6 +73,16 @@ static void tmc_etr_dump_hw(struct tmc_drvdata *drvdata)
        if (val & TMC_STS_FULL) {
                drvdata->buf = drvdata->vaddr + rwp - drvdata->paddr;
                drvdata->len = drvdata->size;
+
+               barrier = barrier_pkt;
+               temp = (u32 *)drvdata->buf;
+
+               while (*barrier) {
+                       *temp = *barrier;
+                       temp++;
+                       barrier++;
+               }
+
        } else {
                drvdata->buf = drvdata->vaddr;
                drvdata->len = rwp - drvdata->paddr;
index 6a0202b7384f6cecdd7a8f8a6cc32a76bdd7b1ce..b8091bef21dc79085c450c783b5784d229c3b333 100644 (file)
@@ -53,6 +53,14 @@ static DEFINE_PER_CPU(struct list_head *, tracer_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)
 {
        int trace_id, i_trace_id;