ARM: etm: Configure data tracing
Arve Hjønnevåg [Mon, 16 Apr 2012 07:55:09 +0000 (12:55 +0530)]
The old code enabled data tracing, but did not configure the
range. We now configure it to trace all data addresses by default,
and add a trace_data_range attribute to change the range or disable
data tracing.

Change-Id: I9d04e3e1ea0d0b4d4d5bcb93b1b042938ad738b2
Signed-off-by: Arve Hjønnevåg <arve@android.com>

Conflicts:

arch/arm/kernel/etm.c

Signed-off-by: Varun Wadekar <vwadekar@nvidia.com>

arch/arm/kernel/etm.c

index 1752d25..3fdcb8f 100644 (file)
@@ -45,6 +45,8 @@ struct tracectx {
        int             etm_portsz;
        unsigned long   range_start;
        unsigned long   range_end;
+       unsigned long   data_range_start;
+       unsigned long   data_range_end;
        struct device   *dev;
        struct clk      *emu_clk;
        struct mutex    mutex;
@@ -83,17 +85,17 @@ static int etm_setup_address_range(struct tracectx *t, int id, int n,
        etm_writel(t, id, start, ETMR_COMP_VAL(n * 2));
 
        /* second comparator is right next to it */
-       etm_writel(t, id, flags, ETMR_COMP_ACC_TYPE(n * 2 + 1));
-       etm_writel(t, id, end, ETMR_COMP_VAL(n * 2 + 1));
+       etm_writel(t, flags, ETMR_COMP_ACC_TYPE(n * 2 + 1));
+       etm_writel(t, end, ETMR_COMP_VAL(n * 2 + 1));
 
        if (data) {
                flags = exclude ? ETMVDC3_EXCLONLY : 0;
                if (exclude)
                        n += 8;
-               etm_writel(t, id, flags | BIT(n), ETMR_VIEWDATACTRL3);
+               etm_writel(t, flags | BIT(n), ETMR_VIEWDATACTRL3);
        } else {
                flags = exclude ? ETMTE_INCLEXCL : 0;
-               etm_writel(t, id, flags | (1 << n), ETMR_TRACEENCTRL);
+               etm_writel(t, flags | (1 << n), ETMR_TRACEENCTRL);
        }
 
        return 0;
@@ -121,7 +123,7 @@ static int trace_start_etm(struct tracectx *t, int id)
        if (t->flags & TRACER_TRACE_DATA)
                v |= ETMCTRL_DATA_DO_ADDR;
 
-       etm_unlock(t, id);
+       etm_unlock(t);
 
        etm_writel(t, id, v, ETMR_CTRL);
 
@@ -143,6 +145,17 @@ static int trace_start_etm(struct tracectx *t, int id)
        etm_writel(t, 0, ETMR_TRACESSCTRL);
        etm_writel(t, 0x6f, ETMR_TRACEENEVT);
 
+       etm_writel(t, 0, ETMR_VIEWDATACTRL1);
+       etm_writel(t, 0, ETMR_VIEWDATACTRL2);
+
+       if (t->data_range_start || t->data_range_end)
+               etm_setup_address_range(t, 2, t->data_range_start,
+                                       t->data_range_end, 0, 1);
+       else
+               etm_writel(t, ETMVDC3_EXCLONLY, ETMR_VIEWDATACTRL3);
+
+       etm_writel(t, 0x6f, ETMR_VIEWDATAEVT);
+
        v &= ~ETMCTRL_PROGRAM;
        v |= ETMCTRL_PORTSEL;
 
@@ -650,6 +663,48 @@ static ssize_t trace_range_store(struct kobject *kobj,
 static struct kobj_attribute trace_range_attr =
        __ATTR(trace_range, 0644, trace_range_show, trace_range_store);
 
+static ssize_t trace_data_range_show(struct kobject *kobj,
+                                 struct kobj_attribute *attr,
+                                 char *buf)
+{
+       unsigned long range_start;
+       u64 range_end;
+       mutex_lock(&tracer.mutex);
+       range_start = tracer.data_range_start;
+       range_end = tracer.data_range_end;
+       if (!range_end && (tracer.flags & TRACER_TRACE_DATA))
+               range_end = 0x100000000ULL;
+       mutex_unlock(&tracer.mutex);
+       return sprintf(buf, "%08lx %08llx\n", range_start, range_end);
+}
+
+static ssize_t trace_data_range_store(struct kobject *kobj,
+                                  struct kobj_attribute *attr,
+                                  const char *buf, size_t n)
+{
+       unsigned long range_start;
+       u64 range_end;
+
+       if (sscanf(buf, "%lx %llx", &range_start, &range_end) != 2)
+               return -EINVAL;
+
+       mutex_lock(&tracer.mutex);
+       tracer.data_range_start = range_start;
+       tracer.data_range_end = (unsigned long)range_end;
+       if (range_end)
+               tracer.flags |= TRACER_TRACE_DATA;
+       else
+               tracer.flags &= ~TRACER_TRACE_DATA;
+       mutex_unlock(&tracer.mutex);
+
+       return n;
+}
+
+
+static struct kobj_attribute trace_data_range_attr =
+       __ATTR(trace_data_range, 0644,
+               trace_data_range_show, trace_data_range_store);
+
 static int __devinit etm_probe(struct amba_device *dev, const struct amba_id *id)
 {
        struct tracectx *t = &tracer;
@@ -682,6 +737,8 @@ static int __devinit etm_probe(struct amba_device *dev, const struct amba_id *id
 
        amba_set_drvdata(dev, t->etm_regs[t->etm_regs_count]);
 
+       mutex_init(&t->mutex);
+       t->dev = &dev->dev;
        t->flags = TRACER_CYCLE_ACC | TRACER_TRACE_DATA;
        t->etm_portsz = 1;
 
@@ -713,6 +770,11 @@ static int __devinit etm_probe(struct amba_device *dev, const struct amba_id *id
        if (ret)
                dev_dbg(&dev->dev, "Failed to create trace_range in sysfs\n");
 
+       ret = sysfs_create_file(&dev->dev.kobj, &trace_data_range_attr.attr);
+       if (ret)
+               dev_dbg(&dev->dev,
+                       "Failed to create trace_data_range in sysfs\n");
+
        dev_dbg(t->dev, "ETM AMBA driver initialized.\n");
 
 out:
@@ -764,6 +826,7 @@ static int etm_remove(struct amba_device *dev)
        sysfs_remove_file(&dev->dev.kobj, &trace_info_attr.attr);
        sysfs_remove_file(&dev->dev.kobj, &trace_mode_attr.attr);
        sysfs_remove_file(&dev->dev.kobj, &trace_range_attr.attr);
+       sysfs_remove_file(&dev->dev.kobj, &trace_data_range_attr.attr);
 
        return 0;
 }