diff options
author | Arto Merilainen <amerilainen@nvidia.com> | 2014-05-28 09:00:43 +0300 |
---|---|---|
committer | Winnie Hsu <whsu@nvidia.com> | 2014-10-17 10:56:29 -0700 |
commit | 6876f819d21ef127f98999e3f21d83ecd402956b (patch) | |
tree | 5c9ecce93d2db6aa14a337e1120b6f08a12dc72f | |
parent | 83296fee29da1a2e6973157aa9f9d913071657bc (diff) |
video: tegra: host: Fix debug dump
Currently the debug dump routine is vulnerable against tricky races.
As normal operation is more important than getting the full dump
always, this patch reworks mutex usage in debug dump routine:
- lock the channel list is now before going through channels. This
ensures that channel states remain valid even if some of the
channels were finished during dump.
- this patch modifies mutex_lock() calls to mutex_trylock() calls.
This ensures that the function call cannot block.
Bug 1517429
Change-Id: Idf170de196bcededbaec6c9031d268cf2d8bc35d
(cherry picked from commit 544cbc483b973ca1c78173edcf2072434c02b5dd)
Signed-off-by: Arto Merilainen <amerilainen@nvidia.com>
Reviewed-on: http://git-master/r/498508
Reviewed-on: http://git-master/r/538724
GVS: Gerrit_Virtual_Submit
Reviewed-by: Shreshtha Sahu <ssahu@nvidia.com>
Tested-by: Shreshtha Sahu <ssahu@nvidia.com>
Reviewed-by: Venkat Moganty <vmoganty@nvidia.com>
Reviewed-by: Shridhar Rasal <srasal@nvidia.com>
-rw-r--r-- | drivers/video/tegra/host/debug.c | 25 |
1 files changed, 20 insertions, 5 deletions
diff --git a/drivers/video/tegra/host/debug.c b/drivers/video/tegra/host/debug.c index 900d30a84761..eb3394652808 100644 --- a/drivers/video/tegra/host/debug.c +++ b/drivers/video/tegra/host/debug.c @@ -56,7 +56,7 @@ static int show_channels(struct platform_device *pdev, void *data, struct output *o = data; struct nvhost_master *m; struct nvhost_device_data *pdata; - int index; + int index, locked; if (pdev == NULL) return 0; @@ -64,6 +64,13 @@ static int show_channels(struct platform_device *pdev, void *data, m = nvhost_get_host(pdev); pdata = platform_get_drvdata(pdev); + /* acquire lock to prevent channel modifications */ + locked = mutex_trylock(&m->chlist_mutex); + if (!locked) { + nvhost_debug_output(o, "unable to lock channel list\n"); + return 0; + } + for (index = 0; index < pdata->num_channels; index++) { ch = pdata->channels[index]; if (!ch || !ch->dev) { @@ -71,19 +78,27 @@ static int show_channels(struct platform_device *pdev, void *data, index + 1, pdev->name); continue; } - nvhost_getchannel(ch); - if (ch->chid != locked_id) - mutex_lock(&ch->cdma.lock); + + /* ensure that we get a lock */ + locked = mutex_trylock(&ch->cdma.lock); + if (!(locked || ch->chid == locked_id)) { + nvhost_debug_output(o, "failed to lock channel %d cdma\n", + ch->chid); + continue; + } + if (fifo) nvhost_get_chip_ops()->debug.show_channel_fifo( m, ch, o, ch->chid); nvhost_get_chip_ops()->debug.show_channel_cdma( m, ch, o, ch->chid); + if (ch->chid != locked_id) mutex_unlock(&ch->cdma.lock); - nvhost_putchannel(ch); } + mutex_unlock(&m->chlist_mutex); + return 0; } |