lkml.org 
[lkml]   [2012]   [Jun]   [12]   [last100]   RSS Feed
Views: [wrap][no wrap]   [headers]  [forward] 
 
Messages in this thread
    Patch in this message
    /
    From
    Subject[PATCH 06/15] ARM: etm: Add some missing locks and error checks
    Date
    From: Arve Hjønnevåg <arve@android.com>

    It is not safe to call etm_lock or etb_lock without holding the
    mutex since another thread may also have unlocked the registers.

    Also add some missing checks for valid etb_regs in the etm sysfs
    entries.

    CC: Russell King <linux@arm.linux.org.uk>
    CC: Paul Gortmaker <paul.gortmaker@windriver.com>
    CC: Alexander Shishkin <alexander.shishkin@linux.intel.com>
    CC: Mathieu Poirier <mathieu.poirier@linaro.org>

    Acked-by: Alexander Shishkin <alexander.shishkin@linux.intel.com>
    Signed-off-by: Arve Hjønnevåg <arve@android.com>
    Signed-off-by: John Stultz <john.stultz@linaro.org>
    ---
    arch/arm/kernel/etm.c | 57 +++++++++++++++++++++++++++++++++---------------
    1 files changed, 39 insertions(+), 18 deletions(-)

    diff --git a/arch/arm/kernel/etm.c b/arch/arm/kernel/etm.c
    index c651cf9..3d21cf6 100644
    --- a/arch/arm/kernel/etm.c
    +++ b/arch/arm/kernel/etm.c
    @@ -264,8 +264,13 @@ static void etm_dump(void)

    static void sysrq_etm_dump(int key)
    {
    + if (!mutex_trylock(&tracer.mutex)) {
    + printk(KERN_INFO "Tracing hardware busy\n");
    + return;
    + }
    dev_dbg(tracer.dev, "Dumping ETB buffer\n");
    etm_dump();
    + mutex_unlock(&tracer.mutex);
    }

    static struct sysrq_key_op sysrq_etm_op = {
    @@ -374,6 +379,7 @@ static int __devinit etb_probe(struct amba_device *dev, const struct amba_id *id
    if (ret)
    goto out;

    + mutex_lock(&t->mutex);
    t->etb_regs = ioremap_nocache(dev->res.start, resource_size(&dev->res));
    if (!t->etb_regs) {
    ret = -ENOMEM;
    @@ -382,6 +388,16 @@ static int __devinit etb_probe(struct amba_device *dev, const struct amba_id *id

    amba_set_drvdata(dev, t);

    + etb_unlock(t);
    + t->etb_bufsz = etb_readl(t, ETBR_DEPTH);
    + dev_dbg(&dev->dev, "Size: %x\n", t->etb_bufsz);
    +
    + /* make sure trace capture is disabled */
    + etb_writel(t, 0, ETBR_CTRL);
    + etb_writel(t, 0x1000, ETBR_FORMATTERCTRL);
    + etb_lock(t);
    + mutex_unlock(&t->mutex);
    +
    etb_miscdev.parent = &dev->dev;

    ret = misc_register(&etb_miscdev);
    @@ -395,25 +411,19 @@ static int __devinit etb_probe(struct amba_device *dev, const struct amba_id *id
    else
    clk_enable(t->emu_clk);

    - etb_unlock(t);
    - t->etb_bufsz = etb_readl(t, ETBR_DEPTH);
    - dev_dbg(&dev->dev, "Size: %x\n", t->etb_bufsz);
    -
    - /* make sure trace capture is disabled */
    - etb_writel(t, 0, ETBR_CTRL);
    - etb_writel(t, 0x1000, ETBR_FORMATTERCTRL);
    - etb_lock(t);
    -
    dev_dbg(&dev->dev, "ETB AMBA driver initialized.\n");

    out:
    return ret;

    out_unmap:
    + mutex_lock(&t->mutex);
    amba_set_drvdata(dev, NULL);
    iounmap(t->etb_regs);
    + t->etb_regs = NULL;

    out_release:
    + mutex_unlock(&t->mutex);
    amba_release_regions(dev);

    return ret;
    @@ -475,7 +485,10 @@ static ssize_t trace_running_store(struct kobject *kobj,
    return -EINVAL;

    mutex_lock(&tracer.mutex);
    - ret = value ? trace_start(&tracer) : trace_stop(&tracer);
    + if (!tracer.etb_regs)
    + ret = -ENODEV;
    + else
    + ret = value ? trace_start(&tracer) : trace_stop(&tracer);
    mutex_unlock(&tracer.mutex);

    return ret ? : n;
    @@ -491,18 +504,25 @@ static ssize_t trace_info_show(struct kobject *kobj,
    u32 etb_wa, etb_ra, etb_st, etb_fc, etm_ctrl, etm_st;
    int datalen;

    - etb_unlock(&tracer);
    - datalen = etb_getdatalen(&tracer);
    - etb_wa = etb_readl(&tracer, ETBR_WRITEADDR);
    - etb_ra = etb_readl(&tracer, ETBR_READADDR);
    - etb_st = etb_readl(&tracer, ETBR_STATUS);
    - etb_fc = etb_readl(&tracer, ETBR_FORMATTERCTRL);
    - etb_lock(&tracer);
    + mutex_lock(&tracer.mutex);
    + if (tracer.etb_regs) {
    + etb_unlock(&tracer);
    + datalen = etb_getdatalen(&tracer);
    + etb_wa = etb_readl(&tracer, ETBR_WRITEADDR);
    + etb_ra = etb_readl(&tracer, ETBR_READADDR);
    + etb_st = etb_readl(&tracer, ETBR_STATUS);
    + etb_fc = etb_readl(&tracer, ETBR_FORMATTERCTRL);
    + etb_lock(&tracer);
    + } else {
    + etb_wa = etb_ra = etb_st = etb_fc = ~0;
    + datalen = -1;
    + }

    etm_unlock(&tracer);
    etm_ctrl = etm_readl(&tracer, ETMR_CTRL);
    etm_st = etm_readl(&tracer, ETMR_STATUS);
    etm_lock(&tracer);
    + mutex_unlock(&tracer.mutex);

    return sprintf(buf, "Trace buffer len: %d\nComparator pairs: %d\n"
    "ETBR_WRITEADDR:\t%08x\n"
    @@ -652,7 +672,6 @@ static int __devinit etm_probe(struct amba_device *dev, const struct amba_id *id

    amba_set_drvdata(dev, t);

    - mutex_init(&t->mutex);
    t->dev = &dev->dev;
    t->flags = TRACER_CYCLE_ACC | TRACER_TRACE_DATA;
    t->etm_portsz = 1;
    @@ -746,6 +765,8 @@ static int __init etm_init(void)
    {
    int retval;

    + mutex_init(&tracer.mutex);
    +
    retval = amba_driver_register(&etb_driver);
    if (retval) {
    printk(KERN_ERR "Failed to register etb\n");
    --
    1.7.3.2.146.gca209
    --
    To unsubscribe from this list: send the line "unsubscribe linux-kernel" in
    the body of a message to majordomo@vger.kernel.org
    More majordomo info at http://vger.kernel.org/majordomo-info.html
    Please read the FAQ at http://www.tux.org/lkml/

    \
     
     \ /
      Last update: 2012-06-13 07:41    [W:0.032 / U:1.104 seconds]
    ©2003-2016 Jasper Spaans. hosted at Digital OceanAdvertise on this site