video: tegra: host: Add debug_dump_locked()
Arto Merilainen [Thu, 21 Nov 2013 12:42:16 +0000 (14:42 +0200)]
In some occasions we already have lock while calling debug
dump or we lock it immediately after calling the debug dump. This
patch adds an alternative version of the function to skip locking
of a single cdma structure thereby allowing the caller to be
responsible of locking.

Bug 1408228

Change-Id: Ieb436307a32c89f25e508dbb17b736219737e1ec
Signed-off-by: Arto Merilainen <amerilainen@nvidia.com>
Reviewed-on: http://git-master/r/334051
Reviewed-by: Terje Bergstrom <tbergstrom@nvidia.com>
Tested-by: Terje Bergstrom <tbergstrom@nvidia.com>

drivers/video/tegra/host/debug.c
drivers/video/tegra/host/debug.h
drivers/video/tegra/host/dev.c
drivers/video/tegra/host/dev.h
drivers/video/tegra/host/host1x/host1x_cdma.c

index ae26b4e..38d7040 100644 (file)
@@ -4,7 +4,7 @@
  * Copyright (C) 2010 Google, Inc.
  * Author: Erik Gilling <konkers@android.com>
  *
- * Copyright (C) 2011-2013 NVIDIA Corporation. All rights reserved.
+ * Copyright (C) 2011-2013, NVIDIA Corporation. All rights reserved.
  *
  * This software is licensed under the terms of the GNU General Public
  * License version 2, as published by the Free Software Foundation, and
@@ -48,7 +48,8 @@ void nvhost_debug_output(struct output *o, const char* fmt, ...)
        o->fn(o->ctx, o->buf, len);
 }
 
-static int show_channels(struct platform_device *pdev, void *data)
+static int show_channels(struct platform_device *pdev, void *data,
+                        int locked_id)
 {
        struct nvhost_channel *ch;
        struct output *o = data;
@@ -61,12 +62,14 @@ static int show_channels(struct platform_device *pdev, void *data)
        pdata = platform_get_drvdata(pdev);
        m = nvhost_get_host(pdev);
        ch = nvhost_getchannel(pdata->channel, true);
-       mutex_lock(&ch->cdma.lock);
+       if (ch->chid != locked_id)
+               mutex_lock(&ch->cdma.lock);
        nvhost_get_chip_ops()->debug.show_channel_fifo(
                m, ch, o, pdata->index);
        nvhost_get_chip_ops()->debug.show_channel_cdma(
                m, ch, o, pdata->index);
-       mutex_unlock(&ch->cdma.lock);
+       if (ch->chid != locked_id)
+               mutex_unlock(&ch->cdma.lock);
        nvhost_putchannel(ch);
 
        return 0;
@@ -97,20 +100,22 @@ static void show_syncpts(struct nvhost_master *m, struct output *o)
        nvhost_debug_output(o, "\n");
 }
 
-static void show_all(struct nvhost_master *m, struct output *o)
+static void show_all(struct nvhost_master *m, struct output *o,
+                    int locked_id)
 {
        nvhost_module_busy(m->dev);
 
        nvhost_get_chip_ops()->debug.show_mlocks(m, o);
        show_syncpts(m, o);
        nvhost_debug_output(o, "---- channels ----\n");
-       nvhost_device_list_for_all(o, show_channels);
+       nvhost_device_list_for_all(o, show_channels, locked_id);
 
        nvhost_module_idle(m->dev);
 }
 
 #ifdef CONFIG_DEBUG_FS
-static int show_channels_no_fifo(struct platform_device *pdev, void *data)
+static int show_channels_no_fifo(struct platform_device *pdev, void *data,
+                                int locked_id)
 {
        struct nvhost_channel *ch;
        struct output *o = data;
@@ -126,10 +131,12 @@ static int show_channels_no_fifo(struct platform_device *pdev, void *data)
        if (ch) {
                mutex_lock(&ch->reflock);
                if (ch->refcount) {
-                       mutex_lock(&ch->cdma.lock);
+                       if (locked_id != ch->chid)
+                               mutex_lock(&ch->cdma.lock);
                        nvhost_get_chip_ops()->debug.show_channel_cdma(m,
                                        ch, o, pdata->index);
-                       mutex_unlock(&ch->cdma.lock);
+                       if (locked_id != ch->chid)
+                               mutex_unlock(&ch->cdma.lock);
                }
                mutex_unlock(&ch->reflock);
        }
@@ -137,14 +144,15 @@ static int show_channels_no_fifo(struct platform_device *pdev, void *data)
        return 0;
 }
 
-static void show_all_no_fifo(struct nvhost_master *m, struct output *o)
+static void show_all_no_fifo(struct nvhost_master *m, struct output *o,
+                            int locked_id)
 {
        nvhost_module_busy(m->dev);
 
        nvhost_get_chip_ops()->debug.show_mlocks(m, o);
        show_syncpts(m, o);
        nvhost_debug_output(o, "---- channels ----\n");
-       nvhost_device_list_for_all(o, show_channels_no_fifo);
+       nvhost_device_list_for_all(o, show_channels_no_fifo, locked_id);
 
        nvhost_module_idle(m->dev);
 }
@@ -155,7 +163,7 @@ static int nvhost_debug_show_all(struct seq_file *s, void *unused)
                .fn = write_to_seqfile,
                .ctx = s
        };
-       show_all(s->private, &o);
+       show_all(s->private, &o, -1);
        return 0;
 }
 
@@ -165,7 +173,7 @@ static int nvhost_debug_show(struct seq_file *s, void *unused)
                .fn = write_to_seqfile,
                .ctx = s
        };
-       show_all_no_fifo(s->private, &o);
+       show_all_no_fifo(s->private, &o, -1);
        return 0;
 }
 
@@ -253,11 +261,19 @@ void nvhost_debug_init(struct nvhost_master *master)
                        &pdata->nvhost_timeout_default);
 }
 
+void nvhost_debug_dump_locked(struct nvhost_master *master, int locked_id)
+{
+       struct output o = {
+               .fn = write_to_printk
+       };
+       show_all(master, &o, locked_id);
+}
+
 void nvhost_debug_dump(struct nvhost_master *master)
 {
        struct output o = {
                .fn = write_to_printk
        };
-       show_all(master, &o);
+       show_all(master, &o, -1);
 }
 #endif
index f4d5d8c..afa4e6d 100644 (file)
@@ -3,7 +3,7 @@
  *
  * Tegra Graphics Host Debug
  *
- * Copyright (c) 2011-2013 NVIDIA Corporation.
+ * Copyright (C) 2011-2013, NVIDIA Corporation. All rights reserved.
  *
  * This program is free software; you can redistribute it and/or modify it
  * under the terms and conditions of the GNU General Public License,
@@ -40,6 +40,7 @@ static inline void write_to_printk(void *ctx, const char* str, size_t len)
 }
 
 void nvhost_debug_output(struct output *o, const char* fmt, ...);
+void nvhost_debug_dump_locked(struct nvhost_master *master, int locked_id);
 
 extern pid_t nvhost_debug_null_kickoff_pid;
 extern pid_t nvhost_debug_force_timeout_pid;
index a296258..4f8b5af 100644 (file)
@@ -3,7 +3,7 @@
  *
  * Tegra Graphics Host Driver Entrypoint
  *
- * Copyright (c) 2010-2013, NVIDIA Corporation.
+ * Copyright (c) 2010-2013, NVIDIA Corporation. All rights reserved.
  *
  * This program is free software; you can redistribute it and/or modify it
  * under the terms and conditions of the GNU General Public License,
@@ -73,7 +73,8 @@ int nvhost_device_list_add(struct platform_device *pdev)
  * It takes a fptr as an argument and calls that function for each
  * device in the list */
 void nvhost_device_list_for_all(void *data,
-       int (*fptr)(struct platform_device *pdev, void *fdata))
+       int (*fptr)(struct platform_device *pdev, void *fdata, int locked_id),
+       int locked_id)
 {
        struct list_head *pos;
        struct nvhost_device_list *nlist;
@@ -82,7 +83,7 @@ void nvhost_device_list_for_all(void *data,
        list_for_each(pos, &ndev_head.list) {
                nlist = list_entry(pos, struct nvhost_device_list, list);
                if (nlist && nlist->pdev && fptr) {
-                       ret = fptr(nlist->pdev, data);
+                       ret = fptr(nlist->pdev, data, locked_id);
                        if (ret) {
                                pr_info("%s: iterator error\n", __func__);
                                break;
index e094fab..0bc4c0c 100644 (file)
@@ -26,7 +26,8 @@ struct platform_device;
 void nvhost_device_list_init(void);
 int nvhost_device_list_add(struct platform_device *pdev);
 void nvhost_device_list_for_all(void *data,
-       int (*fptr)(struct platform_device *pdev, void *fdata));
+       int (*fptr)(struct platform_device *pdev, void *fdata, int locked_id),
+       int locked_id);
 struct platform_device *nvhost_device_list_match_by_id(u32 id);
 void nvhost_device_list_remove(struct platform_device *pdev);
 
index 4dc6a06..2f25d30 100644 (file)
@@ -485,16 +485,16 @@ static void cdma_timeout_handler(struct work_struct *work)
        sp = &dev->syncpt;
        ch = cdma_to_channel(cdma);
 
-       if (nvhost_debug_force_timeout_dump ||
-               cdma->timeout.timeout_debug_dump)
-               nvhost_debug_dump(cdma_to_dev(cdma));
-
        ret = mutex_trylock(&cdma->lock);
        if (!ret) {
                schedule_delayed_work(&cdma->timeout.wq, msecs_to_jiffies(10));
                return;
        }
 
+       if (nvhost_debug_force_timeout_dump ||
+               cdma->timeout.timeout_debug_dump)
+               nvhost_debug_dump_locked(cdma_to_dev(cdma), ch->chid);
+
        /* is this submit dependent with submits on other channels? */
        if (cdma->timeout.allow_dependency && cdma_check_dependencies(cdma)) {
                dev_dbg(&dev->dev->dev,