2011-12-16 10:05:17 +07:00
|
|
|
/*
|
2013-02-12 00:43:09 +07:00
|
|
|
* drivers/gpu/drm/omapdrm/omap_debugfs.c
|
2011-12-16 10:05:17 +07:00
|
|
|
*
|
|
|
|
* Copyright (C) 2011 Texas Instruments
|
|
|
|
* Author: Rob Clark <rob.clark@linaro.org>
|
|
|
|
*
|
|
|
|
* This program is free software; you can redistribute it and/or modify it
|
|
|
|
* under the terms of the GNU General Public License version 2 as published by
|
|
|
|
* the Free Software Foundation.
|
|
|
|
*
|
|
|
|
* This program is distributed in the hope that it will be useful, but WITHOUT
|
|
|
|
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
|
|
|
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
|
|
|
|
* more details.
|
|
|
|
*
|
|
|
|
* You should have received a copy of the GNU General Public License along with
|
|
|
|
* this program. If not, see <http://www.gnu.org/licenses/>.
|
|
|
|
*/
|
|
|
|
|
|
|
|
#include "omap_drv.h"
|
|
|
|
#include "omap_dmm_tiler.h"
|
|
|
|
|
2012-03-05 23:48:36 +07:00
|
|
|
#include "drm_fb_helper.h"
|
|
|
|
|
|
|
|
|
2011-12-16 10:05:17 +07:00
|
|
|
#ifdef CONFIG_DEBUG_FS
|
|
|
|
|
2012-03-05 23:48:36 +07:00
|
|
|
static int gem_show(struct seq_file *m, void *arg)
|
|
|
|
{
|
|
|
|
struct drm_info_node *node = (struct drm_info_node *) m->private;
|
|
|
|
struct drm_device *dev = node->minor->dev;
|
|
|
|
struct omap_drm_private *priv = dev->dev_private;
|
|
|
|
int ret;
|
|
|
|
|
|
|
|
ret = mutex_lock_interruptible(&dev->struct_mutex);
|
|
|
|
if (ret)
|
|
|
|
return ret;
|
|
|
|
|
|
|
|
seq_printf(m, "All Objects:\n");
|
|
|
|
omap_gem_describe_objects(&priv->obj_list, m);
|
|
|
|
|
|
|
|
mutex_unlock(&dev->struct_mutex);
|
|
|
|
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
|
|
|
static int mm_show(struct seq_file *m, void *arg)
|
|
|
|
{
|
|
|
|
struct drm_info_node *node = (struct drm_info_node *) m->private;
|
|
|
|
struct drm_device *dev = node->minor->dev;
|
|
|
|
return drm_mm_dump_table(m, dev->mm_private);
|
|
|
|
}
|
|
|
|
|
|
|
|
static int fb_show(struct seq_file *m, void *arg)
|
|
|
|
{
|
|
|
|
struct drm_info_node *node = (struct drm_info_node *) m->private;
|
|
|
|
struct drm_device *dev = node->minor->dev;
|
|
|
|
struct omap_drm_private *priv = dev->dev_private;
|
|
|
|
struct drm_framebuffer *fb;
|
|
|
|
|
|
|
|
seq_printf(m, "fbcon ");
|
|
|
|
omap_framebuffer_describe(priv->fbdev->fb, m);
|
|
|
|
|
drm: revamp locking around fb creation/destruction
Well, at least step 1. The goal here is that framebuffer objects can
survive outside of the mode_config lock, with just a reference held
as protection. The first step to get there is to introduce a special
fb_lock which protects fb lookup, creation and destruction, to make
them appear atomic.
This new fb_lock can nest within the mode_config lock. But the idea is
(once the reference counting part is completed) that we only quickly
take that fb_lock to lookup a framebuffer and grab a reference,
without any other locks involved.
vmwgfx is the only driver which does framebuffer lookups itself, also
wrap those calls to drm_mode_object_find with the new lock.
Also protect the fb_list walking in i915 and omapdrm with the new lock.
As a slight complication there's also the list of user-created fbs
attached to the file private. The problem now is that at fclose() time
we need to walk that list, eventually do a modeset call to remove the
fb from active usage (and are required to be able to take the
mode_config lock), but in the end we need to grab the new fb_lock to
remove the fb from the list. The easiest solution is to add another
mutex to protect this per-file list.
Currently that new fbs_lock nests within the modeset locks and so
appears redudant. But later patches will switch around this sequence
so that taking the modeset locks in the fb destruction path is
optional in the fastpath. Ultimately the goal is that addfb and rmfb
do not require the mode_config lock, since otherwise they have the
potential to introduce stalls in the pageflip sequence of a compositor
(if the compositor e.g. switches to a fullscreen client or if it
enables a plane). But that requires a few more steps and hoops to jump
through.
Note that framebuffer creation/destruction is now double-protected -
once by the fb_lock and in parts by the idr_lock. The later would be
unnecessariy if framebuffers would have their own idr allocator. But
that's material for another patch (series).
v2: Properly initialize the fb->filp_head list in _init, otherwise the
newly added WARN to check whether the fb isn't on a fpriv list any
more will fail for driver-private objects.
v3: Fixup two error-case unlock bugs spotted by Richard Wilbur.
Reviewed-by: Rob Clark <rob@ti.com>
Signed-off-by: Daniel Vetter <daniel.vetter@ffwll.ch>
2012-12-11 03:19:18 +07:00
|
|
|
mutex_lock(&dev->mode_config.fb_lock);
|
2012-03-05 23:48:36 +07:00
|
|
|
list_for_each_entry(fb, &dev->mode_config.fb_list, head) {
|
|
|
|
if (fb == priv->fbdev->fb)
|
|
|
|
continue;
|
|
|
|
|
|
|
|
seq_printf(m, "user ");
|
|
|
|
omap_framebuffer_describe(fb, m);
|
|
|
|
}
|
drm: revamp locking around fb creation/destruction
Well, at least step 1. The goal here is that framebuffer objects can
survive outside of the mode_config lock, with just a reference held
as protection. The first step to get there is to introduce a special
fb_lock which protects fb lookup, creation and destruction, to make
them appear atomic.
This new fb_lock can nest within the mode_config lock. But the idea is
(once the reference counting part is completed) that we only quickly
take that fb_lock to lookup a framebuffer and grab a reference,
without any other locks involved.
vmwgfx is the only driver which does framebuffer lookups itself, also
wrap those calls to drm_mode_object_find with the new lock.
Also protect the fb_list walking in i915 and omapdrm with the new lock.
As a slight complication there's also the list of user-created fbs
attached to the file private. The problem now is that at fclose() time
we need to walk that list, eventually do a modeset call to remove the
fb from active usage (and are required to be able to take the
mode_config lock), but in the end we need to grab the new fb_lock to
remove the fb from the list. The easiest solution is to add another
mutex to protect this per-file list.
Currently that new fbs_lock nests within the modeset locks and so
appears redudant. But later patches will switch around this sequence
so that taking the modeset locks in the fb destruction path is
optional in the fastpath. Ultimately the goal is that addfb and rmfb
do not require the mode_config lock, since otherwise they have the
potential to introduce stalls in the pageflip sequence of a compositor
(if the compositor e.g. switches to a fullscreen client or if it
enables a plane). But that requires a few more steps and hoops to jump
through.
Note that framebuffer creation/destruction is now double-protected -
once by the fb_lock and in parts by the idr_lock. The later would be
unnecessariy if framebuffers would have their own idr allocator. But
that's material for another patch (series).
v2: Properly initialize the fb->filp_head list in _init, otherwise the
newly added WARN to check whether the fb isn't on a fpriv list any
more will fail for driver-private objects.
v3: Fixup two error-case unlock bugs spotted by Richard Wilbur.
Reviewed-by: Rob Clark <rob@ti.com>
Signed-off-by: Daniel Vetter <daniel.vetter@ffwll.ch>
2012-12-11 03:19:18 +07:00
|
|
|
mutex_unlock(&dev->mode_config.fb_lock);
|
2012-03-05 23:48:36 +07:00
|
|
|
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
|
|
|
/* list of debufs files that are applicable to all devices */
|
2011-12-16 10:05:17 +07:00
|
|
|
static struct drm_info_list omap_debugfs_list[] = {
|
2012-03-05 23:48:36 +07:00
|
|
|
{"gem", gem_show, 0},
|
|
|
|
{"mm", mm_show, 0},
|
|
|
|
{"fb", fb_show, 0},
|
|
|
|
};
|
|
|
|
|
|
|
|
/* list of debugfs files that are specific to devices with dmm/tiler */
|
|
|
|
static struct drm_info_list omap_dmm_debugfs_list[] = {
|
2011-12-16 10:05:17 +07:00
|
|
|
{"tiler_map", tiler_map_show, 0},
|
|
|
|
};
|
|
|
|
|
|
|
|
int omap_debugfs_init(struct drm_minor *minor)
|
|
|
|
{
|
2012-03-05 23:48:36 +07:00
|
|
|
struct drm_device *dev = minor->dev;
|
|
|
|
int ret;
|
|
|
|
|
|
|
|
ret = drm_debugfs_create_files(omap_debugfs_list,
|
2011-12-16 10:05:17 +07:00
|
|
|
ARRAY_SIZE(omap_debugfs_list),
|
|
|
|
minor->debugfs_root, minor);
|
2012-03-05 23:48:36 +07:00
|
|
|
|
|
|
|
if (ret) {
|
|
|
|
dev_err(dev->dev, "could not install omap_debugfs_list\n");
|
|
|
|
return ret;
|
|
|
|
}
|
|
|
|
|
2012-03-05 23:48:37 +07:00
|
|
|
if (dmm_is_available())
|
|
|
|
ret = drm_debugfs_create_files(omap_dmm_debugfs_list,
|
|
|
|
ARRAY_SIZE(omap_dmm_debugfs_list),
|
|
|
|
minor->debugfs_root, minor);
|
2012-03-05 23:48:36 +07:00
|
|
|
|
|
|
|
if (ret) {
|
|
|
|
dev_err(dev->dev, "could not install omap_dmm_debugfs_list\n");
|
|
|
|
return ret;
|
|
|
|
}
|
|
|
|
|
|
|
|
return ret;
|
2011-12-16 10:05:17 +07:00
|
|
|
}
|
|
|
|
|
|
|
|
void omap_debugfs_cleanup(struct drm_minor *minor)
|
|
|
|
{
|
|
|
|
drm_debugfs_remove_files(omap_debugfs_list,
|
|
|
|
ARRAY_SIZE(omap_debugfs_list), minor);
|
2012-03-05 23:48:37 +07:00
|
|
|
if (dmm_is_available())
|
|
|
|
drm_debugfs_remove_files(omap_dmm_debugfs_list,
|
|
|
|
ARRAY_SIZE(omap_dmm_debugfs_list), minor);
|
2011-12-16 10:05:17 +07:00
|
|
|
}
|
|
|
|
|
|
|
|
#endif
|