[RFC 0/3] drm: Add DRM text mode

2016-08-02 Thread David Herrmann
Hey

On Thu, Jul 28, 2016 at 4:15 PM, Noralf Trønnes  wrote:
> This patchset explores the idea of adding a DRM text mode
> (like VGA text mode) to get an alternative to fbcon/fbdev.
>
> David Hermann has done alot of work on a fbcon replacement:
> - drm: add kernel-log renderer (Mar 2014)[1]
> - kmscon:
>   development started Nov 2011
>   added to systemd Oct 2014
>   removed from systemd Jul 2015[2]
>
> Since this work seems to have stalled, I propose an alternative solution
> to this problem that will also give VT console support while we're waiting
> for a userspace console.
>
> The idea is that the driver provides a modeset like with the fbdev emulation
> code, and from this a text buffer representation is made. The console code
> can now write to this text buffer and ask for the text buffer to be
> flushed/rendered to the pixel buffer.
>
> In this hack/implementation of the idea, I have just hijacked a CMA backed
> fbdev framebuffer to keep it simple.
> I have reused the default buffer format that VT uses.
> Getting panic handling to actually work, seems to be a challenge as Daniel
> describes on the DRMJanitors page[3].
>
> Is this idea of a DRM text mode worth developing further?

Sorry, haven't done much on this stuff lately. I still appreciate
being put on CC, thanks for that!
I did change my mind several times when working on the VT-replacement
layer and everything involved. In the end, my plan was this:

 * Make VTs obsolete. Make sure a system can run with CONFIG_VT=n.
systemd-logind provides an alternative access-control, but I would not
mind dropping it as well and just go with a setup that only has a
single gfx/input user per seat. No VTs, no multiplexing, etc. (which
is what Ubuntu is going for with the system compositor).

 * Make fbdev obsolete. Provide SimpleDRM as a slow-path for any
graphics device that no real driver exists for. SimpleDRM always runs
a _shadow_ FB, so no direct access to gfx-resources from user-space.
If you need that, use something else.

 * Support turnover from SimpleDRM to other drivers. This is as simple
as destroying the related platform-device before loading a gfx-driver.
Patches exist, but requires i915 to move aperture-management out of
the ->load callback (i.e., out of drm_global_mutex). The best solution
would be to drop ->load entirely. It is not needed, anyway.

 * Write an in-kernel terminal layer that can be loaded as dynamic
module and is a pure API _consumer_. Nothing can depend on it, hence,
it is completely passive and can be loaded on-demand (unlike VTs,
which lots of stuff is hooked into). This terminal/console serves as
debugging console for developers and can be blended over any current
screen content. It simply grabs all input and shadows DRM-Master. It
can be toggled via SYSRQ. User-space is unaware of its existence.

Code for all these parts exists (I even wrote the console replacement
using the DRM atomic APIs). However, I got distracted with kdbus+bus1,
so haven't pushed on it lately.

I can see that the drmcon backend you propose is a nice-to-have, but I
don't think it is the ultimate solution. It is a step forward, though,
so maybe we should just take it and avoid thinking of the ultimate
dream-solution... I don't know.

If there is interest in pushing SimpleDRM and/or related parts, ping
me on IRC (@dvdhrm or via email in private). I'd gladly discuss this
and try to find some time to revive the patches.

Thanks
David


[PATCH 2/3] drm: Convert drm_vma_manager to embedded interval-tree in drm_mm

2016-08-03 Thread David Herrmann
Hi Chris

On Wed, Aug 3, 2016 at 5:04 PM, Chris Wilson  
wrote:
> Having added an interval-tree to struct drm_mm, we can replace the
> auxiliary rb-tree inside the drm_vma_manager with it.
>
> Signed-off-by: Chris Wilson 
> Cc: David Herrmann 
> Cc: dri-devel at lists.freedesktop.org
> ---

Should have done that right from start when writing drm_vma_manager..

Reviewed-by: David Herrmann 

Thanks
David

>  drivers/gpu/drm/drm_vma_manager.c | 43 
> ---
>  include/drm/drm_vma_manager.h |  2 --
>  2 files changed, 9 insertions(+), 36 deletions(-)
>
> diff --git a/drivers/gpu/drm/drm_vma_manager.c 
> b/drivers/gpu/drm/drm_vma_manager.c
> index f306c8855978..0aef432679f9 100644
> --- a/drivers/gpu/drm/drm_vma_manager.c
> +++ b/drivers/gpu/drm/drm_vma_manager.c
> @@ -86,7 +86,6 @@ void drm_vma_offset_manager_init(struct 
> drm_vma_offset_manager *mgr,
>  unsigned long page_offset, unsigned long 
> size)
>  {
> rwlock_init(&mgr->vm_lock);
> -   mgr->vm_addr_space_rb = RB_ROOT;
> drm_mm_init(&mgr->vm_addr_space_mm, page_offset, size);
>  }
>  EXPORT_SYMBOL(drm_vma_offset_manager_init);
> @@ -145,16 +144,16 @@ struct drm_vma_offset_node 
> *drm_vma_offset_lookup_locked(struct drm_vma_offset_m
>  unsigned long start,
>  unsigned long pages)
>  {
> -   struct drm_vma_offset_node *node, *best;
> +   struct drm_mm_node *node, *best;
> struct rb_node *iter;
> unsigned long offset;
>
> -   iter = mgr->vm_addr_space_rb.rb_node;
> +   iter = mgr->vm_addr_space_mm.interval_tree.rb_node;
> best = NULL;
>
> while (likely(iter)) {
> -   node = rb_entry(iter, struct drm_vma_offset_node, vm_rb);
> -   offset = node->vm_node.start;
> +   node = rb_entry(iter, struct drm_mm_node, rb);
> +   offset = node->start;
> if (start >= offset) {
> iter = iter->rb_right;
> best = node;
> @@ -167,38 +166,17 @@ struct drm_vma_offset_node 
> *drm_vma_offset_lookup_locked(struct drm_vma_offset_m
>
> /* verify that the node spans the requested area */
> if (best) {
> -   offset = best->vm_node.start + best->vm_node.size;
> +   offset = best->start + best->size;
> if (offset < start + pages)
> best = NULL;
> }
>
> -   return best;
> -}
> -EXPORT_SYMBOL(drm_vma_offset_lookup_locked);
> -
> -/* internal helper to link @node into the rb-tree */
> -static void _drm_vma_offset_add_rb(struct drm_vma_offset_manager *mgr,
> -  struct drm_vma_offset_node *node)
> -{
> -   struct rb_node **iter = &mgr->vm_addr_space_rb.rb_node;
> -   struct rb_node *parent = NULL;
> -   struct drm_vma_offset_node *iter_node;
> -
> -   while (likely(*iter)) {
> -   parent = *iter;
> -   iter_node = rb_entry(*iter, struct drm_vma_offset_node, 
> vm_rb);
> +   if (!best)
> +   return NULL;
>
> -   if (node->vm_node.start < iter_node->vm_node.start)
> -   iter = &(*iter)->rb_left;
> -   else if (node->vm_node.start > iter_node->vm_node.start)
> -   iter = &(*iter)->rb_right;
> -   else
> -   BUG();
> -   }
> -
> -   rb_link_node(&node->vm_rb, parent, iter);
> -   rb_insert_color(&node->vm_rb, &mgr->vm_addr_space_rb);
> +   return container_of(best, struct drm_vma_offset_node, vm_node);
>  }
> +EXPORT_SYMBOL(drm_vma_offset_lookup_locked);
>
>  /**
>   * drm_vma_offset_add() - Add offset node to manager
> @@ -240,8 +218,6 @@ int drm_vma_offset_add(struct drm_vma_offset_manager *mgr,
> if (ret)
> goto out_unlock;
>
> -   _drm_vma_offset_add_rb(mgr, node);
> -
>  out_unlock:
> write_unlock(&mgr->vm_lock);
> return ret;
> @@ -265,7 +241,6 @@ void drm_vma_offset_remove(struct drm_vma_offset_manager 
> *mgr,
> write_lock(&mgr->vm_lock);
>
> if (drm_mm_node_allocated(&node->vm_node)) {
> -   rb_erase(&node->vm_rb, &mgr->vm_addr_space_rb);
> drm_mm_remove_node(&node->vm_node);
> memset(&node->vm_node, 0, sizeof(node->vm_node));
> }
> 

[PATCH 3/3] drm: Skip initialising the drm_mm_node->hole_stack

2016-08-03 Thread David Herrmann
Hi Chris

On Wed, Aug 3, 2016 at 5:04 PM, Chris Wilson  
wrote:
> As we always add this to the drm_mm->hole_stack as our first operation,
> we do not need to initialise the list node.
>
> Signed-off-by: Chris Wilson 
> Cc: David Herrmann 
> Cc: dri-devel at lists.freedesktop.org
> ---
>  drivers/gpu/drm/drm_mm.c | 6 +-
>  1 file changed, 1 insertion(+), 5 deletions(-)

"hole_follows" tells whether it is linked or not. So yeah, indeed, redundant.

Reviewed-by: David Herrmann 

Thanks
David

> diff --git a/drivers/gpu/drm/drm_mm.c b/drivers/gpu/drm/drm_mm.c
> index 5c188c56894b..3f56d4b0cdae 100644
> --- a/drivers/gpu/drm/drm_mm.c
> +++ b/drivers/gpu/drm/drm_mm.c
> @@ -217,7 +217,6 @@ static void drm_mm_insert_helper(struct drm_mm_node 
> *hole_node,
> node->color = color;
> node->allocated = 1;
>
> -   INIT_LIST_HEAD(&node->hole_stack);
> list_add(&node->node_list, &hole_node->node_list);
>
> drm_mm_interval_tree_add_node(hole_node, node);
> @@ -276,14 +275,13 @@ int drm_mm_reserve_node(struct drm_mm *mm, struct 
> drm_mm_node *node)
> node->mm = mm;
> node->allocated = 1;
>
> -   INIT_LIST_HEAD(&node->hole_stack);
> list_add(&node->node_list, &hole->node_list);
>
> drm_mm_interval_tree_add_node(hole, node);
>
> if (node->start == hole_start) {
> hole->hole_follows = 0;
> -   list_del_init(&hole->hole_stack);
> +   list_del(&hole->hole_stack);
> }
>
> node->hole_follows = 0;
> @@ -379,7 +377,6 @@ static void drm_mm_insert_helper_range(struct drm_mm_node 
> *hole_node,
> node->color = color;
> node->allocated = 1;
>
> -   INIT_LIST_HEAD(&node->hole_stack);
> list_add(&node->node_list, &hole_node->node_list);
>
> drm_mm_interval_tree_add_node(hole_node, node);
> @@ -833,7 +830,6 @@ void drm_mm_init(struct drm_mm * mm, u64 start, u64 size)
>
> /* Clever trick to avoid a special case in the free hole tracking. */
> INIT_LIST_HEAD(&mm->head_node.node_list);
> -   INIT_LIST_HEAD(&mm->head_node.hole_stack);
> mm->head_node.hole_follows = 1;
> mm->head_node.scanned_block = 0;
> mm->head_node.scanned_prev_free = 0;
> --
> 2.8.1
>


[PATCH 1/3] drm: Track drm_mm nodes with an interval tree

2016-08-03 Thread David Herrmann
Hey

On Wed, Aug 3, 2016 at 5:04 PM, Chris Wilson  
wrote:
> In addition to the last-in/first-out stack for accessing drm_mm nodes,
> we occasionally and in the future often want to find a drm_mm_node by an
> address. To do so efficiently we need to track the nodes in an interval
> tree - lookups for a particular address will then be O(lg(N)), where N
> is the number of nodes in the range manager as opposed to O(N).
> Insertion however gains an extra O(lg(N)) step for all nodes
> irrespective of whether the interval tree is in use. For future i915
> patches, eliminating the linear walk is a significant improvement.
>
> v2: Use generic interval-tree template for u64 and faster insertion.
>
> Signed-off-by: Chris Wilson 
> Cc: David Herrmann 
> Cc: dri-devel at lists.freedesktop.org
> ---
>  drivers/gpu/drm/drm_mm.c | 133 
> +++
>  include/drm/drm_mm.h |  12 +
>  2 files changed, 122 insertions(+), 23 deletions(-)
>
> diff --git a/drivers/gpu/drm/drm_mm.c b/drivers/gpu/drm/drm_mm.c
> index cb39f45d6a16..5c188c56894b 100644
> --- a/drivers/gpu/drm/drm_mm.c
> +++ b/drivers/gpu/drm/drm_mm.c
> @@ -46,6 +46,7 @@
>  #include 
>  #include 
>  #include 
> +#include 
>
>  /**
>   * DOC: Overview
> @@ -103,6 +104,72 @@ static struct drm_mm_node 
> *drm_mm_search_free_in_range_generic(const struct drm_
> u64 end,
> enum drm_mm_search_flags 
> flags);
>
> +#define START(node) ((node)->start)
> +#define LAST(node)  ((node)->start + (node)->size - 1)

So this goes nuts with "size == 0". We do not explicitly prevent that
from happening, I think, but might be prevented in the upper layers.
Might wanna add WARN_ONs?

Otherwise, looks good to me:

Reviewed-by: David Herrmann 

Thanks
David

> +
> +INTERVAL_TREE_DEFINE(struct drm_mm_node, rb,
> +u64, __subtree_last,
> +START, LAST, static inline, drm_mm_interval_tree)
> +
> +struct drm_mm_node *
> +drm_mm_interval_first(struct drm_mm *mm, u64 start, u64 last)
> +{
> +   return drm_mm_interval_tree_iter_first(&mm->interval_tree,
> +  start, last);
> +}
> +EXPORT_SYMBOL(drm_mm_interval_first);
> +
> +struct drm_mm_node *
> +drm_mm_interval_next(struct drm_mm_node *node, u64 start, u64 last)
> +{
> +   return drm_mm_interval_tree_iter_next(node, start, last);
> +}
> +EXPORT_SYMBOL(drm_mm_interval_next);
> +
> +static void drm_mm_interval_tree_add_node(struct drm_mm_node *hole_node,
> + struct drm_mm_node *node)
> +{
> +   struct drm_mm *mm = hole_node->mm;
> +   struct rb_node **link, *rb;
> +   struct drm_mm_node *parent;
> +
> +   node->__subtree_last = LAST(node);
> +
> +   if (hole_node->allocated) {
> +   rb = &hole_node->rb;
> +   while (rb) {
> +   parent = rb_entry(rb, struct drm_mm_node, rb);
> +   if (parent->__subtree_last >= node->__subtree_last)
> +   break;
> +
> +   parent->__subtree_last = node->__subtree_last;
> +   rb = rb_parent(rb);
> +   }
> +
> +   rb = &hole_node->rb;
> +   link = &hole_node->rb.rb_right;
> +   } else {
> +   rb = NULL;
> +   link = &mm->interval_tree.rb_node;
> +   }
> +
> +   while (*link) {
> +   rb = *link;
> +   parent = rb_entry(rb, struct drm_mm_node, rb);
> +   if (parent->__subtree_last < node->__subtree_last)
> +   parent->__subtree_last = node->__subtree_last;
> +   if (node->start < parent->start)
> +   link = &parent->rb.rb_left;
> +   else
> +   link = &parent->rb.rb_right;
> +   }
> +
> +   rb_link_node(&node->rb, rb, link);
> +   rb_insert_augmented(&node->rb,
> +   &mm->interval_tree,
> +   &drm_mm_interval_tree_augment);
> +}
> +
>  static void drm_mm_insert_helper(struct drm_mm_node *hole_node,
>  struct drm_mm_node *node,
>  u64 size, unsigned alignment,
> @@ -153,6 +220,8 @@ static void drm_mm_insert_helper(struct drm_mm_node 
> *hole_node,
> INIT_LIST_HEAD(&node->hole_stack);
> list_add(&

[PATCH 0/8] DRM File Context Cleanups

2016-08-03 Thread David Herrmann
Hi

Some rather random cleanups on drm_file and whatever I found on the way. The
idea here really is to get to a point where we can allocate drm_file from a
kernel context to get in-kernel rendering to work. This would allow allocating
dumb-buffers, dma-bufs, etc. from within the kernel and get fbdev generically
working, as well as panic renderers et al.

The only critical thing is drm_file->filp, which points to the underlying
"struct file". We really don't want to fake a "struct file" for in-kernel
renderers (even though it is possible), so this series tries to get rid of all
non-legacy users of it. The only real place left is vm_mmap() in drm_bufs.c.

Tested on i915 only.

Thanks
David

David Herrmann (8):
  drm: rename DRM_MINOR_LEGACY to DRM_MINOR_PRIMARY
  drm: remove redundant drm_file->uid
  drm: reduce GETCLIENT to a minimum
  drm: make vma-manager entries untyped
  drm: use drm_file to tag vm-bos
  drm: use priv->pid to deduce task EUID
  drm: rename drm_file.filp to drm_file.legacy_filp
  drm: provide management functions for drm_file

 drivers/gpu/drm/amd/amdgpu/amdgpu_ttm.c |   3 +-
 drivers/gpu/drm/ast/ast_ttm.c   |   3 +-
 drivers/gpu/drm/bochs/bochs_mm.c|   3 +-
 drivers/gpu/drm/cirrus/cirrus_ttm.c |   3 +-
 drivers/gpu/drm/drm_bufs.c  |   7 +-
 drivers/gpu/drm/drm_drv.c   | 149 ++--
 drivers/gpu/drm/drm_fops.c  | 133 ++--
 drivers/gpu/drm/drm_gem.c   |   8 +-
 drivers/gpu/drm/drm_info.c  |   4 +-
 drivers/gpu/drm/drm_internal.h  |   4 +
 drivers/gpu/drm/drm_ioctl.c |   5 +-
 drivers/gpu/drm/drm_vma_manager.c   |  40 -
 drivers/gpu/drm/mgag200/mgag200_ttm.c   |   3 +-
 drivers/gpu/drm/nouveau/nouveau_bo.c|   3 +-
 drivers/gpu/drm/qxl/qxl_ttm.c   |   3 +-
 drivers/gpu/drm/radeon/radeon_ttm.c |   3 +-
 include/drm/drmP.h  |   7 +-
 include/drm/drm_vma_manager.h   |  18 ++--
 18 files changed, 213 insertions(+), 186 deletions(-)

-- 
2.9.2



[PATCH 1/8] drm: rename DRM_MINOR_LEGACY to DRM_MINOR_PRIMARY

2016-08-03 Thread David Herrmann
The minor referred to by "DRM_MINOR_LEGACY" is called 'dev->primary' and
gets 'cardX' as name assigned. Lets reduce this magnificent number of
names for the same concept by one and rename DRM_MINOR_LEGACY to
DRM_MINOR_PRIMARY (to match the actual struct-member name).

Furthermore, this is in no way a legacy node, so lets not call it that.

Signed-off-by: David Herrmann 
---
 drivers/gpu/drm/drm_drv.c | 14 +++---
 include/drm/drmP.h|  4 ++--
 2 files changed, 9 insertions(+), 9 deletions(-)

diff --git a/drivers/gpu/drm/drm_drv.c b/drivers/gpu/drm/drm_drv.c
index be27ed3..57ce973 100644
--- a/drivers/gpu/drm/drm_drv.c
+++ b/drivers/gpu/drm/drm_drv.c
@@ -112,7 +112,7 @@ static struct drm_minor **drm_minor_get_slot(struct 
drm_device *dev,
 unsigned int type)
 {
switch (type) {
-   case DRM_MINOR_LEGACY:
+   case DRM_MINOR_PRIMARY:
return &dev->primary;
case DRM_MINOR_RENDER:
return &dev->render;
@@ -512,7 +512,7 @@ int drm_dev_init(struct drm_device *dev,
goto err_minors;
}

-   ret = drm_minor_alloc(dev, DRM_MINOR_LEGACY);
+   ret = drm_minor_alloc(dev, DRM_MINOR_PRIMARY);
if (ret)
goto err_minors;

@@ -545,7 +545,7 @@ err_ctxbitmap:
drm_legacy_ctxbitmap_cleanup(dev);
drm_ht_remove(&dev->map_hash);
 err_minors:
-   drm_minor_free(dev, DRM_MINOR_LEGACY);
+   drm_minor_free(dev, DRM_MINOR_PRIMARY);
drm_minor_free(dev, DRM_MINOR_RENDER);
drm_minor_free(dev, DRM_MINOR_CONTROL);
drm_fs_inode_free(dev->anon_inode);
@@ -608,7 +608,7 @@ static void drm_dev_release(struct kref *ref)
drm_ht_remove(&dev->map_hash);
drm_fs_inode_free(dev->anon_inode);

-   drm_minor_free(dev, DRM_MINOR_LEGACY);
+   drm_minor_free(dev, DRM_MINOR_PRIMARY);
drm_minor_free(dev, DRM_MINOR_RENDER);
drm_minor_free(dev, DRM_MINOR_CONTROL);

@@ -684,7 +684,7 @@ int drm_dev_register(struct drm_device *dev, unsigned long 
flags)
if (ret)
goto err_minors;

-   ret = drm_minor_register(dev, DRM_MINOR_LEGACY);
+   ret = drm_minor_register(dev, DRM_MINOR_PRIMARY);
if (ret)
goto err_minors;

@@ -701,7 +701,7 @@ int drm_dev_register(struct drm_device *dev, unsigned long 
flags)
goto out_unlock;

 err_minors:
-   drm_minor_unregister(dev, DRM_MINOR_LEGACY);
+   drm_minor_unregister(dev, DRM_MINOR_PRIMARY);
drm_minor_unregister(dev, DRM_MINOR_RENDER);
drm_minor_unregister(dev, DRM_MINOR_CONTROL);
 out_unlock:
@@ -741,7 +741,7 @@ void drm_dev_unregister(struct drm_device *dev)
list_for_each_entry_safe(r_list, list_temp, &dev->maplist, head)
drm_legacy_rmmap(dev, r_list->map);

-   drm_minor_unregister(dev, DRM_MINOR_LEGACY);
+   drm_minor_unregister(dev, DRM_MINOR_PRIMARY);
drm_minor_unregister(dev, DRM_MINOR_RENDER);
drm_minor_unregister(dev, DRM_MINOR_CONTROL);
 }
diff --git a/include/drm/drmP.h b/include/drm/drmP.h
index d377865..d488a72 100644
--- a/include/drm/drmP.h
+++ b/include/drm/drmP.h
@@ -642,7 +642,7 @@ struct drm_driver {
 };

 enum drm_minor_type {
-   DRM_MINOR_LEGACY,
+   DRM_MINOR_PRIMARY,
DRM_MINOR_CONTROL,
DRM_MINOR_RENDER,
DRM_MINOR_CNT,
@@ -856,7 +856,7 @@ static inline bool drm_is_control_client(const struct 
drm_file *file_priv)

 static inline bool drm_is_primary_client(const struct drm_file *file_priv)
 {
-   return file_priv->minor->type == DRM_MINOR_LEGACY;
+   return file_priv->minor->type == DRM_MINOR_PRIMARY;
 }

 /**/
-- 
2.9.2



[PATCH 2/8] drm: remove redundant drm_file->uid

2016-08-03 Thread David Herrmann
Each DRM file-context caches the EUID of the process that opened the file.
It is used exclusively for debugging purposes in /proc/dri/ and friends.

Note, however, that "struct file" already caches the credentials of a
process at open-time. So lets just use drm_file->filp->f_cred->euid if
available. The pointer-chasing will not hurt us, since it is only about
debugging, anyway.

Check priv->filp for NULL before deref, to prepare for in-kernel contexts
(if they ever appear). We should not rely on "struct file" contexts to be
around at all times, anyway.

Signed-off-by: David Herrmann 
---
 drivers/gpu/drm/drm_fops.c  | 1 -
 drivers/gpu/drm/drm_info.c  | 4 +++-
 drivers/gpu/drm/drm_ioctl.c | 4 +++-
 include/drm/drmP.h  | 1 -
 4 files changed, 6 insertions(+), 4 deletions(-)

diff --git a/drivers/gpu/drm/drm_fops.c b/drivers/gpu/drm/drm_fops.c
index 323c238..e9d66f5 100644
--- a/drivers/gpu/drm/drm_fops.c
+++ b/drivers/gpu/drm/drm_fops.c
@@ -199,7 +199,6 @@ static int drm_open_helper(struct file *filp, struct 
drm_minor *minor)

filp->private_data = priv;
priv->filp = filp;
-   priv->uid = current_euid();
priv->pid = get_pid(task_pid(current));
priv->minor = minor;

diff --git a/drivers/gpu/drm/drm_info.c b/drivers/gpu/drm/drm_info.c
index 9ae353f..247ba2b 100644
--- a/drivers/gpu/drm/drm_info.c
+++ b/drivers/gpu/drm/drm_info.c
@@ -80,6 +80,7 @@ int drm_clients_info(struct seq_file *m, void *data)
struct drm_info_node *node = (struct drm_info_node *) m->private;
struct drm_device *dev = node->minor->dev;
struct drm_file *priv;
+   kuid_t uid;

seq_printf(m,
   "%20s %5s %3s master a %5s %10s\n",
@@ -98,13 +99,14 @@ int drm_clients_info(struct seq_file *m, void *data)

rcu_read_lock(); /* locks pid_task()->comm */
task = pid_task(priv->pid, PIDTYPE_PID);
+   uid = priv->filp ? priv->filp->f_cred->euid : GLOBAL_ROOT_UID;
seq_printf(m, "%20s %5d %3d   %c%c %5d %10u\n",
   task ? task->comm : "",
   pid_vnr(priv->pid),
   priv->minor->index,
   drm_is_current_master(priv) ? 'y' : 'n',
   priv->authenticated ? 'y' : 'n',
-  from_kuid_munged(seq_user_ns(m), priv->uid),
+  from_kuid_munged(seq_user_ns(m), uid),
   priv->magic);
rcu_read_unlock();
}
diff --git a/drivers/gpu/drm/drm_ioctl.c b/drivers/gpu/drm/drm_ioctl.c
index 33af4a5..49cd835 100644
--- a/drivers/gpu/drm/drm_ioctl.c
+++ b/drivers/gpu/drm/drm_ioctl.c
@@ -191,7 +191,9 @@ static int drm_getclient(struct drm_device *dev, void *data,
client->auth = file_priv->authenticated;
client->pid = pid_vnr(file_priv->pid);
client->uid = from_kuid_munged(current_user_ns(),
-  file_priv->uid);
+  file_priv->filp ?
+  file_priv->filp->f_cred->euid :
+  GLOBAL_ROOT_UID);
client->magic = 0;
client->iocs = 0;

diff --git a/include/drm/drmP.h b/include/drm/drmP.h
index d488a72..0f69f56 100644
--- a/include/drm/drmP.h
+++ b/include/drm/drmP.h
@@ -320,7 +320,6 @@ struct drm_file {
unsigned is_master:1;

struct pid *pid;
-   kuid_t uid;
drm_magic_t magic;
struct list_head lhead;
struct drm_minor *minor;
-- 
2.9.2



[PATCH 3/8] drm: reduce GETCLIENT to a minimum

2016-08-03 Thread David Herrmann
The *only* known user of GETCLIENT is libva, which uses it to check
whether its own context is authenticated. It used to iterate all clients,
look for one that matches its own pid and then check its state.

The entire purpose for us to still have a GETCLIENT implementation is to
serve libva. So lets not pretend we do anything else: Make this function
return information on the caller's context only, fake the PID to the
caller's pid so they always match, and just fill in the "authenticated"
bit, nothing else.

This patch reduces the complexity of GETCLIENT to a bare minimum, avoids
any dependency on priv->uid or priv->pid (allows us to get rid of them),
and makes libva happy by always *exactly* returning the information it
wants.

Signed-off-by: David Herrmann 
---
 drivers/gpu/drm/drm_ioctl.c | 7 ++-
 1 file changed, 2 insertions(+), 5 deletions(-)

diff --git a/drivers/gpu/drm/drm_ioctl.c b/drivers/gpu/drm/drm_ioctl.c
index 49cd835..bc5c65e 100644
--- a/drivers/gpu/drm/drm_ioctl.c
+++ b/drivers/gpu/drm/drm_ioctl.c
@@ -189,11 +189,8 @@ static int drm_getclient(struct drm_device *dev, void 
*data,
 */
if (client->idx == 0) {
client->auth = file_priv->authenticated;
-   client->pid = pid_vnr(file_priv->pid);
-   client->uid = from_kuid_munged(current_user_ns(),
-  file_priv->filp ?
-  file_priv->filp->f_cred->euid :
-  GLOBAL_ROOT_UID);
+   client->pid = task_pid_vnr(current);
+   client->uid = overflowuid;
client->magic = 0;
client->iocs = 0;

-- 
2.9.2



[PATCH 4/8] drm: make vma-manager entries untyped

2016-08-03 Thread David Herrmann
Right now, the vma-manager requires all entries to provide a "struct
file*" as identifier. This is confusing, since there is no inherent
connection to "struct file" in the vma-manager at all, but it is
exclusively used as tag.

Replace its usage with a simple "void *tag" and make sure callers can use
arbitrary tags.

Signed-off-by: David Herrmann 
---
 drivers/gpu/drm/drm_vma_manager.c | 40 +++
 include/drm/drm_vma_manager.h | 18 --
 2 files changed, 27 insertions(+), 31 deletions(-)

diff --git a/drivers/gpu/drm/drm_vma_manager.c 
b/drivers/gpu/drm/drm_vma_manager.c
index f306c88..954248e 100644
--- a/drivers/gpu/drm/drm_vma_manager.c
+++ b/drivers/gpu/drm/drm_vma_manager.c
@@ -25,7 +25,6 @@
 #include 
 #include 
 #include 
-#include 
 #include 
 #include 
 #include 
@@ -277,9 +276,9 @@ EXPORT_SYMBOL(drm_vma_offset_remove);
 /**
  * drm_vma_node_allow - Add open-file to list of allowed users
  * @node: Node to modify
- * @filp: Open file to add
+ * @tag: Tag of file to remove
  *
- * Add @filp to the list of allowed open-files for this node. If @filp is
+ * Add @tag to the list of allowed open-files for this node. If @tag is
  * already on this list, the ref-count is incremented.
  *
  * The list of allowed-users is preserved across drm_vma_offset_add() and
@@ -294,7 +293,7 @@ EXPORT_SYMBOL(drm_vma_offset_remove);
  * RETURNS:
  * 0 on success, negative error code on internal failure (out-of-mem)
  */
-int drm_vma_node_allow(struct drm_vma_offset_node *node, struct file *filp)
+int drm_vma_node_allow(struct drm_vma_offset_node *node, void *tag)
 {
struct rb_node **iter;
struct rb_node *parent = NULL;
@@ -315,10 +314,10 @@ int drm_vma_node_allow(struct drm_vma_offset_node *node, 
struct file *filp)
parent = *iter;
entry = rb_entry(*iter, struct drm_vma_offset_file, vm_rb);

-   if (filp == entry->vm_filp) {
+   if (tag == entry->vm_tag) {
entry->vm_count++;
goto unlock;
-   } else if (filp > entry->vm_filp) {
+   } else if (tag > entry->vm_tag) {
iter = &(*iter)->rb_right;
} else {
iter = &(*iter)->rb_left;
@@ -330,7 +329,7 @@ int drm_vma_node_allow(struct drm_vma_offset_node *node, 
struct file *filp)
goto unlock;
}

-   new->vm_filp = filp;
+   new->vm_tag = tag;
new->vm_count = 1;
rb_link_node(&new->vm_rb, parent, iter);
rb_insert_color(&new->vm_rb, &node->vm_files);
@@ -346,17 +345,17 @@ EXPORT_SYMBOL(drm_vma_node_allow);
 /**
  * drm_vma_node_revoke - Remove open-file from list of allowed users
  * @node: Node to modify
- * @filp: Open file to remove
+ * @tag: Tag of file to remove
  *
- * Decrement the ref-count of @filp in the list of allowed open-files on @node.
- * If the ref-count drops to zero, remove @filp from the list. You must call
- * this once for every drm_vma_node_allow() on @filp.
+ * Decrement the ref-count of @tag in the list of allowed open-files on @node.
+ * If the ref-count drops to zero, remove @tag from the list. You must call
+ * this once for every drm_vma_node_allow() on @tag.
  *
  * This is locked against concurrent access internally.
  *
- * If @filp is not on the list, nothing is done.
+ * If @tag is not on the list, nothing is done.
  */
-void drm_vma_node_revoke(struct drm_vma_offset_node *node, struct file *filp)
+void drm_vma_node_revoke(struct drm_vma_offset_node *node, void *tag)
 {
struct drm_vma_offset_file *entry;
struct rb_node *iter;
@@ -366,13 +365,13 @@ void drm_vma_node_revoke(struct drm_vma_offset_node 
*node, struct file *filp)
iter = node->vm_files.rb_node;
while (likely(iter)) {
entry = rb_entry(iter, struct drm_vma_offset_file, vm_rb);
-   if (filp == entry->vm_filp) {
+   if (tag == entry->vm_tag) {
if (!--entry->vm_count) {
rb_erase(&entry->vm_rb, &node->vm_files);
kfree(entry);
}
break;
-   } else if (filp > entry->vm_filp) {
+   } else if (tag > entry->vm_tag) {
iter = iter->rb_right;
} else {
iter = iter->rb_left;
@@ -386,9 +385,9 @@ EXPORT_SYMBOL(drm_vma_node_revoke);
 /**
  * drm_vma_node_is_allowed - Check whether an open-file is granted access
  * @node: Node to check
- * @filp: Open-file to check for
+ * @tag: Tag of file to remove
  *
- * Search the list in @node whether @filp is currently on the list of allowed
+ * Search the list in @node whether @tag is currently on the list of allowe

[PATCH 5/8] drm: use drm_file to tag vm-bos

2016-08-03 Thread David Herrmann
Rather than using "struct file*", use "struct drm_file*" as tag VM tag for
BOs. This will pave the way for "struct drm_file*" without any "struct
file*" back-pointer.

Signed-off-by: David Herrmann 
---
 drivers/gpu/drm/amd/amdgpu/amdgpu_ttm.c | 3 ++-
 drivers/gpu/drm/ast/ast_ttm.c   | 3 ++-
 drivers/gpu/drm/bochs/bochs_mm.c| 3 ++-
 drivers/gpu/drm/cirrus/cirrus_ttm.c | 3 ++-
 drivers/gpu/drm/drm_gem.c   | 8 
 drivers/gpu/drm/mgag200/mgag200_ttm.c   | 3 ++-
 drivers/gpu/drm/nouveau/nouveau_bo.c| 3 ++-
 drivers/gpu/drm/qxl/qxl_ttm.c   | 3 ++-
 drivers/gpu/drm/radeon/radeon_ttm.c | 3 ++-
 9 files changed, 20 insertions(+), 12 deletions(-)

diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_ttm.c 
b/drivers/gpu/drm/amd/amdgpu/amdgpu_ttm.c
index b7742e6..58099c9 100644
--- a/drivers/gpu/drm/amd/amdgpu/amdgpu_ttm.c
+++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_ttm.c
@@ -225,7 +225,8 @@ static int amdgpu_verify_access(struct ttm_buffer_object 
*bo, struct file *filp)

if (amdgpu_ttm_tt_get_usermm(bo->ttm))
return -EPERM;
-   return drm_vma_node_verify_access(&rbo->gem_base.vma_node, filp);
+   return drm_vma_node_verify_access(&rbo->gem_base.vma_node,
+ filp->private_data);
 }

 static void amdgpu_move_null(struct ttm_buffer_object *bo,
diff --git a/drivers/gpu/drm/ast/ast_ttm.c b/drivers/gpu/drm/ast/ast_ttm.c
index b29a412..608df4c 100644
--- a/drivers/gpu/drm/ast/ast_ttm.c
+++ b/drivers/gpu/drm/ast/ast_ttm.c
@@ -150,7 +150,8 @@ static int ast_bo_verify_access(struct ttm_buffer_object 
*bo, struct file *filp)
 {
struct ast_bo *astbo = ast_bo(bo);

-   return drm_vma_node_verify_access(&astbo->gem.vma_node, filp);
+   return drm_vma_node_verify_access(&astbo->gem.vma_node,
+ filp->private_data);
 }

 static int ast_ttm_io_mem_reserve(struct ttm_bo_device *bdev,
diff --git a/drivers/gpu/drm/bochs/bochs_mm.c b/drivers/gpu/drm/bochs/bochs_mm.c
index 5c5638a..269cfca 100644
--- a/drivers/gpu/drm/bochs/bochs_mm.c
+++ b/drivers/gpu/drm/bochs/bochs_mm.c
@@ -128,7 +128,8 @@ static int bochs_bo_verify_access(struct ttm_buffer_object 
*bo,
 {
struct bochs_bo *bochsbo = bochs_bo(bo);

-   return drm_vma_node_verify_access(&bochsbo->gem.vma_node, filp);
+   return drm_vma_node_verify_access(&bochsbo->gem.vma_node,
+ filp->private_data);
 }

 static int bochs_ttm_io_mem_reserve(struct ttm_bo_device *bdev,
diff --git a/drivers/gpu/drm/cirrus/cirrus_ttm.c 
b/drivers/gpu/drm/cirrus/cirrus_ttm.c
index 1cc9ee6..bb2438d 100644
--- a/drivers/gpu/drm/cirrus/cirrus_ttm.c
+++ b/drivers/gpu/drm/cirrus/cirrus_ttm.c
@@ -150,7 +150,8 @@ static int cirrus_bo_verify_access(struct ttm_buffer_object 
*bo, struct file *fi
 {
struct cirrus_bo *cirrusbo = cirrus_bo(bo);

-   return drm_vma_node_verify_access(&cirrusbo->gem.vma_node, filp);
+   return drm_vma_node_verify_access(&cirrusbo->gem.vma_node,
+ filp->private_data);
 }

 static int cirrus_ttm_io_mem_reserve(struct ttm_bo_device *bdev,
diff --git a/drivers/gpu/drm/drm_gem.c b/drivers/gpu/drm/drm_gem.c
index 9134ae1..465bacd 100644
--- a/drivers/gpu/drm/drm_gem.c
+++ b/drivers/gpu/drm/drm_gem.c
@@ -257,7 +257,7 @@ drm_gem_object_release_handle(int id, void *ptr, void *data)

if (drm_core_check_feature(dev, DRIVER_PRIME))
drm_gem_remove_prime_handles(obj, file_priv);
-   drm_vma_node_revoke(&obj->vma_node, file_priv->filp);
+   drm_vma_node_revoke(&obj->vma_node, file_priv);

if (dev->driver->gem_close_object)
dev->driver->gem_close_object(obj, file_priv);
@@ -372,7 +372,7 @@ drm_gem_handle_create_tail(struct drm_file *file_priv,

handle = ret;

-   ret = drm_vma_node_allow(&obj->vma_node, file_priv->filp);
+   ret = drm_vma_node_allow(&obj->vma_node, file_priv);
if (ret)
goto err_remove;

@@ -386,7 +386,7 @@ drm_gem_handle_create_tail(struct drm_file *file_priv,
return 0;

 err_revoke:
-   drm_vma_node_revoke(&obj->vma_node, file_priv->filp);
+   drm_vma_node_revoke(&obj->vma_node, file_priv);
 err_remove:
spin_lock(&file_priv->table_lock);
idr_remove(&file_priv->object_idr, handle);
@@ -991,7 +991,7 @@ int drm_gem_mmap(struct file *filp, struct vm_area_struct 
*vma)
if (!obj)
return -EINVAL;

-   if (!drm_vma_node_is_allowed(node, filp)) {
+   if (!drm_vma_node_is_allowed(node, priv)) {
drm_gem_object_unreference_unlocked(obj);
return -EACCES;
}
diff --git a/drivers/gpu/drm/mgag200/mgag200_ttm.c 
b/drivers/gpu/drm/mgag200

[PATCH 7/8] drm: rename drm_file.filp to drm_file.legacy_filp

2016-08-03 Thread David Herrmann
We don't want anyone but legacy DRM1 code to use drm_file.filp. Especially
for in-kernel contexts, this might be set to NULL, so lets make sure
no-one accesses it, ever.

Signed-off-by: David Herrmann 
---
 drivers/gpu/drm/drm_bufs.c | 7 ---
 drivers/gpu/drm/drm_fops.c | 2 +-
 include/drm/drmP.h | 2 +-
 3 files changed, 6 insertions(+), 5 deletions(-)

diff --git a/drivers/gpu/drm/drm_bufs.c b/drivers/gpu/drm/drm_bufs.c
index c3a12cd..d2803de 100644
--- a/drivers/gpu/drm/drm_bufs.c
+++ b/drivers/gpu/drm/drm_bufs.c
@@ -1456,7 +1456,7 @@ int drm_legacy_mapbufs(struct drm_device *dev, void *data,
if (!drm_core_check_feature(dev, DRIVER_HAVE_DMA))
return -EINVAL;

-   if (!dma)
+   if (!dma || !file_priv->legacy_filp)
return -EINVAL;

spin_lock(&dev->buf_lock);
@@ -1478,12 +1478,13 @@ int drm_legacy_mapbufs(struct drm_device *dev, void 
*data,
retcode = -EINVAL;
goto done;
}
-   virtual = vm_mmap(file_priv->filp, 0, map->size,
+   virtual = vm_mmap(file_priv->legacy_filp, 0, map->size,
  PROT_READ | PROT_WRITE,
  MAP_SHARED,
  token);
} else {
-   virtual = vm_mmap(file_priv->filp, 0, dma->byte_count,
+   virtual = vm_mmap(file_priv->legacy_filp, 0,
+ dma->byte_count,
  PROT_READ | PROT_WRITE,
  MAP_SHARED, 0);
}
diff --git a/drivers/gpu/drm/drm_fops.c b/drivers/gpu/drm/drm_fops.c
index e9d66f5..69ef23c 100644
--- a/drivers/gpu/drm/drm_fops.c
+++ b/drivers/gpu/drm/drm_fops.c
@@ -198,7 +198,7 @@ static int drm_open_helper(struct file *filp, struct 
drm_minor *minor)
return -ENOMEM;

filp->private_data = priv;
-   priv->filp = filp;
+   priv->legacy_filp = filp;
priv->pid = get_pid(task_pid(current));
priv->minor = minor;

diff --git a/include/drm/drmP.h b/include/drm/drmP.h
index 0f69f56..2197ab1 100644
--- a/include/drm/drmP.h
+++ b/include/drm/drmP.h
@@ -330,7 +330,7 @@ struct drm_file {
/** Lock for synchronization of access to object_idr. */
spinlock_t table_lock;

-   struct file *filp;
+   struct file *legacy_filp; /* might be NULL! */
void *driver_priv;

struct drm_master *master; /* master this node is currently associated 
with
-- 
2.9.2



[PATCH 6/8] drm: use priv->pid to deduce task EUID

2016-08-03 Thread David Herrmann
Rather than accessing priv->filp->f_cred, use priv->pid->task->creds. We
want to get rid of "priv->filp", so lets avoid it if possible.

Since we already are in an rcu-read-side, we can use __task_cred() rather
than task_cred_xxx().

Signed-off-by: David Herrmann 
---
 drivers/gpu/drm/drm_info.c | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/drivers/gpu/drm/drm_info.c b/drivers/gpu/drm/drm_info.c
index 247ba2b..1df2d33 100644
--- a/drivers/gpu/drm/drm_info.c
+++ b/drivers/gpu/drm/drm_info.c
@@ -99,7 +99,7 @@ int drm_clients_info(struct seq_file *m, void *data)

rcu_read_lock(); /* locks pid_task()->comm */
task = pid_task(priv->pid, PIDTYPE_PID);
-   uid = priv->filp ? priv->filp->f_cred->euid : GLOBAL_ROOT_UID;
+   uid = task ? __task_cred(task)->euid : GLOBAL_ROOT_UID;
seq_printf(m, "%20s %5d %3d   %c%c %5d %10u\n",
   task ? task->comm : "",
   pid_vnr(priv->pid),
-- 
2.9.2



[PATCH 8/8] drm: provide management functions for drm_file

2016-08-03 Thread David Herrmann
Rather than doing drm_file allocation/destruction right in the fops, lets
provide separate helpers. This decouples drm_file management from the
still-mandatory drm-fops. It prepares for use of drm_file without the
fops, both by possible separate fops implementations and APIs (not that I
am aware of any such plans), and more importantly from in-kernel use where
no real file is available.

Signed-off-by: David Herrmann 
---
 drivers/gpu/drm/drm_drv.c  | 135 +
 drivers/gpu/drm/drm_fops.c | 132 +++-
 drivers/gpu/drm/drm_internal.h |   4 ++
 3 files changed, 147 insertions(+), 124 deletions(-)

diff --git a/drivers/gpu/drm/drm_drv.c b/drivers/gpu/drm/drm_drv.c
index 57ce973..9ab0016 100644
--- a/drivers/gpu/drm/drm_drv.c
+++ b/drivers/gpu/drm/drm_drv.c
@@ -95,6 +95,141 @@ void drm_ut_debug_printk(const char *function_name, const 
char *format, ...)
 }
 EXPORT_SYMBOL(drm_ut_debug_printk);

+/**
+ * drm_file_alloc - allocate file context
+ * @minor: minor to allocate on
+ *
+ * This allocates a new DRM file context. It is not linked into any context and
+ * can be used by the caller freely. Note that the context keeps a pointer to
+ * @minor, so it must be freed before @minor is.
+ *
+ * The legacy paths might require the drm_global_mutex to be held.
+ *
+ * RETURNS:
+ * Pointer to newly allocated context, ERR_PTR on failure.
+ */
+struct drm_file *drm_file_alloc(struct drm_minor *minor)
+{
+   struct drm_device *dev = minor->dev;
+   struct drm_file *file;
+   int ret;
+
+   file = kzalloc(sizeof(*file), GFP_KERNEL);
+   if (!file)
+   return ERR_PTR(-ENOMEM);
+
+   file->pid = get_pid(task_pid(current));
+   file->minor = minor;
+   file->authenticated = capable(CAP_SYS_ADMIN); /* legacy compat */
+   INIT_LIST_HEAD(&file->lhead);
+   INIT_LIST_HEAD(&file->fbs);
+   mutex_init(&file->fbs_lock);
+   INIT_LIST_HEAD(&file->blobs);
+   INIT_LIST_HEAD(&file->pending_event_list);
+   INIT_LIST_HEAD(&file->event_list);
+   init_waitqueue_head(&file->event_wait);
+   file->event_space = 4096; /* set aside 4k for event buffer */
+   mutex_init(&file->event_read_lock);
+
+   if (drm_core_check_feature(dev, DRIVER_GEM))
+   drm_gem_open(dev, file);
+   if (drm_core_check_feature(dev, DRIVER_PRIME))
+   drm_prime_init_file_private(&file->prime);
+
+   if (dev->driver->open) {
+   ret = dev->driver->open(dev, file);
+   if (ret < 0)
+   goto out_prime_destroy;
+   }
+
+   if (drm_is_primary_client(file)) {
+   ret = drm_master_open(file);
+   if (ret)
+   goto out_close;
+   }
+
+   return file;
+
+out_close:
+   if (dev->driver->postclose)
+   dev->driver->postclose(dev, file);
+out_prime_destroy:
+   if (drm_core_check_feature(dev, DRIVER_PRIME))
+   drm_prime_destroy_file_private(&file->prime);
+   if (drm_core_check_feature(dev, DRIVER_GEM))
+   drm_gem_release(dev, file);
+   put_pid(file->pid);
+   kfree(file);
+   return ERR_PTR(ret);
+}
+
+/**
+ * drm_file_free - free file context
+ * @file: context to free, or NULL
+ *
+ * This destroys and deallocates a DRM file context previously allocated via
+ * drm_file_alloc(). The caller must make sure to unlink it from any contexts
+ * before calling this.
+ *
+ * The legacy paths might require the drm_global_mutex to be held.
+ *
+ * If NULL is passed, this is a no-op.
+ *
+ * RETURNS:
+ * 0 on success, or error code on failure.
+ */
+void drm_file_free(struct drm_file *file)
+{
+   struct drm_pending_event *e;
+   struct drm_device *dev;
+
+   if (!file)
+   return;
+
+   dev = file->minor->dev;
+
+   if (dev->driver->preclose)
+   dev->driver->preclose(dev, file);
+   if (!drm_core_check_feature(dev, DRIVER_MODESET))
+   drm_legacy_lock_release(dev, file->legacy_filp);
+   if (drm_core_check_feature(dev, DRIVER_HAVE_DMA))
+   drm_legacy_reclaim_buffers(dev, file);
+
+   spin_lock_irq(&dev->event_lock);
+   while ((e = list_first_entry_or_null(&file->pending_event_list,
+struct drm_pending_event,
+pending_link))) {
+   list_del(&e->pending_link);
+   e->file_priv = NULL;
+   }
+   while ((e = list_first_entry_or_null(&file->event_list,
+struct drm_pending_event, link))) {
+   list_del(&e->link);
+   kfree(e);
+   }
+   spin_u

simpledrm problem: Kconfig:error: recursive dependency detected!

2016-08-04 Thread David Herrmann
Hey

On Thu, Aug 4, 2016 at 9:04 AM, Jani Nikula  
wrote:
> On Wed, 03 Aug 2016, Noralf Trønnes  wrote:
>> Hi,
>>
>> I have changed simpledrm to use drm_simple_kms_helper and now I'm
>> facing this:
>>
>> drivers/video/fbdev/Kconfig:5:error: recursive dependency detected!
>> For a resolution refer to Documentation/kbuild/kconfig-language.txt
>>
>> drivers/video/fbdev/Kconfig:5:  symbol FB is selected by DRM_KMS_FB_HELPER
>>
>> drivers/gpu/drm/Kconfig:42: symbol DRM_KMS_FB_HELPER depends on
>> DRM_KMS_HELPER
>>
>> drivers/gpu/drm/Kconfig:36: symbol DRM_KMS_HELPER is selected by
>> DRM_SIMPLEDRM
>>
>> drivers/gpu/drm/simpledrm/Kconfig:1:symbol DRM_SIMPLEDRM depends on
>> FB_SIMPLE
>>
>> drivers/video/fbdev/Kconfig:2428:   symbol FB_SIMPLE depends on FB
>>
>>
>> Using this Kconfig:
>>
>> config DRM_SIMPLEDRM
>>  tristate "Simple firmware framebuffer DRM driver"
>>  depends on DRM && (FB_SIMPLE = n)
>>  select DRM_KMS_HELPER
>>
>>
>> Is there a solution to this apart from depending on DRM_KMS_HELPER or
>> removing the FB_SIMPLE dependency?
>
> I think the underlying problem is the overuse of "select" all around. I
> think people use it for convenience because unsatisfied "depends" hides
> a menu option in menuconfig while "select" does not, and it's sometimes
> hard to find all the dependencies of an option just to *show* it in
> menuconfig.
>
> I don't know what the exact cause here is, but having hunted these down
> before, it's often a rabbit hole where you end up having to change a ton
> of config options to make it robust, and those changes get rejected
> because the menuconfig convenience is lost, and I've given up. :/
>
> Would be great to have a menuconfig feature to recursively enable and
> option and all dependencies. Perhaps we could then be more strict about
> using "select" for stuff with dependencies.

As a workaround, just drop the FB_SIMPLE dependency. It was really
just meant as a safety net in my original code. Nothing bad happens if
both are enabled. The first to be loaded wins, the other one will very
likely print a confusing error message and exit.

Thanks
David


[PATCH 1/2] drm: Mark up legacy/dri1 drivers with DRM_LEGACY

2016-08-04 Thread David Herrmann
Hi

On Wed, Aug 3, 2016 at 9:11 PM, Daniel Vetter  wrote:
> It's super confusing that new drivers need to be marked with
> DRIVER_MODESET when really it means DRIVER_MODERN. Much better to
> invert the meaning and rename it to something that's suitably
> off-putting.
>
> Since there's over 100 places using DRIVER_MODESET we need to roll out
> this change without a flag day.
>
> v2: Update docs.
>
> Signed-off-by: Daniel Vetter 
> ---
>  Documentation/gpu/drm-internals.rst | 9 ++---
>  drivers/gpu/drm/i810/i810_drv.c | 4 +---
>  drivers/gpu/drm/mga/mga_drv.c   | 2 +-
>  drivers/gpu/drm/r128/r128_drv.c | 2 +-
>  drivers/gpu/drm/savage/savage_drv.c | 2 +-
>  drivers/gpu/drm/sis/sis_drv.c   | 2 +-
>  drivers/gpu/drm/tdfx/tdfx_drv.c | 1 +
>  drivers/gpu/drm/via/via_drv.c   | 2 +-
>  include/drm/drmP.h  | 1 +
>  9 files changed, 14 insertions(+), 11 deletions(-)

Reviewed-by: David Herrmann 

Also, how about this:


diff --git a/drivers/gpu/drm/Kconfig b/drivers/gpu/drm/Kconfig
index fc35731..e609cfc 100644
--- a/drivers/gpu/drm/Kconfig
+++ b/drivers/gpu/drm/Kconfig
@@ -111,6 +111,7 @@ source "drivers/gpu/drm/i2c/Kconfig"
 config DRM_TDFX
  tristate "3dfx Banshee/Voodoo3+"
  depends on DRM && PCI
+ depends on BROKEN
  help
   Choose this option if you have a 3dfx Banshee or Voodoo3 (or later),
   graphics card.  If M is selected, the module will be called tdfx.
@@ -120,6 +121,7 @@ source "drivers/gpu/drm/arm/Kconfig"
 config DRM_R128
  tristate "ATI Rage 128"
  depends on DRM && PCI
+ depends on BROKEN
  select FW_LOADER
  help
   Choose this option if you have an ATI Rage 128 graphics card.  If M
@@ -181,6 +183,7 @@ config DRM_I810
  tristate "Intel I810"
  # !PREEMPT because of missing ioctl locking
  depends on DRM && AGP && AGP_INTEL && (!PREEMPT || BROKEN)
+ depends on BROKEN
  help
   Choose this option if you have an Intel I810 graphics card.  If M is
   selected, the module will be called i810.  AGP support is required
@@ -191,6 +194,7 @@ source "drivers/gpu/drm/i915/Kconfig"
 config DRM_MGA
  tristate "Matrox g200/g400"
  depends on DRM && PCI
+ depends on BROKEN
  select FW_LOADER
  help
   Choose this option if you have a Matrox G200, G400 or G450 graphics
@@ -201,6 +205,7 @@ config DRM_SIS
  tristate "SiS video cards"
  depends on DRM && AGP
  depends on FB_SIS || FB_SIS=n
+ depends on BROKEN
  help
   Choose this option if you have a SiS 630 or compatible video
   chipset. If M is selected the module will be called sis. AGP
@@ -209,6 +214,7 @@ config DRM_SIS
 config DRM_VIA
  tristate "Via unichrome video cards"
  depends on DRM && PCI
+ depends on BROKEN
  help
   Choose this option if you have a Via unichrome or compatible video
   chipset. If M is selected the module will be called via.
@@ -216,6 +222,7 @@ config DRM_VIA
 config DRM_SAVAGE
  tristate "Savage video cards"
  depends on DRM && PCI
+ depends on BROKEN
  help
   Choose this option if you have a Savage3D/4/SuperSavage/Pro/Twister
   chipset. If M is selected the module will be called savage.


[PATCH 2/2] drm: Used DRM_LEGACY for all legacy functions

2016-08-04 Thread David Herrmann
rm_core_check_feature(dev, DRIVER_LEGACY))
> return -EINVAL;
>
> mutex_lock(&dev->struct_mutex);
> @@ -225,7 +225,7 @@ int drm_legacy_setsareactx(struct drm_device *dev, void 
> *data,
> struct drm_map_list *r_list = NULL;
>
> if (!drm_core_check_feature(dev, DRIVER_KMS_LEGACY_CONTEXT) &&
> -   drm_core_check_feature(dev, DRIVER_MODESET))
> +   !drm_core_check_feature(dev, DRIVER_LEGACY))
> return -EINVAL;
>
> mutex_lock(&dev->struct_mutex);
> @@ -329,7 +329,7 @@ int drm_legacy_resctx(struct drm_device *dev, void *data,
> int i;
>
> if (!drm_core_check_feature(dev, DRIVER_KMS_LEGACY_CONTEXT) &&
> -   drm_core_check_feature(dev, DRIVER_MODESET))
> +   !drm_core_check_feature(dev, DRIVER_LEGACY))
> return -EINVAL;
>
> if (res->count >= DRM_RESERVED_CONTEXTS) {
> @@ -363,7 +363,7 @@ int drm_legacy_addctx(struct drm_device *dev, void *data,
> struct drm_ctx *ctx = data;
>
> if (!drm_core_check_feature(dev, DRIVER_KMS_LEGACY_CONTEXT) &&
> -   drm_core_check_feature(dev, DRIVER_MODESET))
> +   !drm_core_check_feature(dev, DRIVER_LEGACY))
> return -EINVAL;
>
> ctx->handle = drm_legacy_ctxbitmap_next(dev);
> @@ -410,7 +410,7 @@ int drm_legacy_getctx(struct drm_device *dev, void *data,
> struct drm_ctx *ctx = data;
>
> if (!drm_core_check_feature(dev, DRIVER_KMS_LEGACY_CONTEXT) &&
> -   drm_core_check_feature(dev, DRIVER_MODESET))
> +   !drm_core_check_feature(dev, DRIVER_LEGACY))
> return -EINVAL;
>
> /* This is 0, because we don't handle any context flags */
> @@ -436,7 +436,7 @@ int drm_legacy_switchctx(struct drm_device *dev, void 
> *data,
> struct drm_ctx *ctx = data;
>
> if (!drm_core_check_feature(dev, DRIVER_KMS_LEGACY_CONTEXT) &&
> -   drm_core_check_feature(dev, DRIVER_MODESET))
> +   !drm_core_check_feature(dev, DRIVER_LEGACY))
> return -EINVAL;
>
> DRM_DEBUG("%d\n", ctx->handle);
> @@ -460,7 +460,7 @@ int drm_legacy_newctx(struct drm_device *dev, void *data,
> struct drm_ctx *ctx = data;
>
> if (!drm_core_check_feature(dev, DRIVER_KMS_LEGACY_CONTEXT) &&
> -   drm_core_check_feature(dev, DRIVER_MODESET))
> +   !drm_core_check_feature(dev, DRIVER_LEGACY))
> return -EINVAL;
>
> DRM_DEBUG("%d\n", ctx->handle);
> @@ -486,7 +486,7 @@ int drm_legacy_rmctx(struct drm_device *dev, void *data,
> struct drm_ctx *ctx = data;
>
> if (!drm_core_check_feature(dev, DRIVER_KMS_LEGACY_CONTEXT) &&
> -   drm_core_check_feature(dev, DRIVER_MODESET))
> +   !drm_core_check_feature(dev, DRIVER_LEGACY))
> return -EINVAL;
>
>     DRM_DEBUG("%d\n", ctx->handle);
> diff --git a/drivers/gpu/drm/drm_dma.c b/drivers/gpu/drm/drm_dma.c
> index ea481800ef56..3f83e2ca80ad 100644
> --- a/drivers/gpu/drm/drm_dma.c
> +++ b/drivers/gpu/drm/drm_dma.c
> @@ -50,9 +50,8 @@ int drm_legacy_dma_setup(struct drm_device *dev)
> int i;
>
> if (!drm_core_check_feature(dev, DRIVER_HAVE_DMA) ||
> -   drm_core_check_feature(dev, DRIVER_MODESET)) {
> +   !drm_core_check_feature(dev, DRIVER_LEGACY))
> return 0;
> -   }
>
> dev->buf_use = 0;
> atomic_set(&dev->buf_alloc, 0);
> @@ -81,9 +80,8 @@ void drm_legacy_dma_takedown(struct drm_device *dev)
> int i, j;
>
> if (!drm_core_check_feature(dev, DRIVER_HAVE_DMA) ||
> -   drm_core_check_feature(dev, DRIVER_MODESET)) {
> +   !drm_core_check_feature(dev, DRIVER_LEGACY))
> return;
> -   }

Both these DRIVER_HAVE_DMA checks are sufficient without the
DRIVER_MODESET/LEGACY checks. I mean, the entire HAVE_DMA flag is
legacy-only. But that's for a future cleanup to rename HAVE_DMA to
LEGACY_DMA.

This patch is:

Reviewed-by: David Herrmann 

Thanks
David

>
> if (!dma)
> return;
> diff --git a/drivers/gpu/drm/drm_fops.c b/drivers/gpu/drm/drm_fops.c
> index 323c238fcac7..036cd275c53e 100644
> --- a/drivers/gpu/drm/drm_fops.c
> +++ b/drivers/gpu/drm/drm_fops.c
> @@ -92,7 +92,7 @@ static int drm_setup(struct drm_device * dev)
> int ret;
>
> if (dev->driver->firstopen &&
> -   !drm_core_check_feature(dev, DRIVER_MODESET)) {
> +   drm_core_check_feature(dev, DRIVER_LEGACY)) {
>  

[PATCH 1/2] drm: hide legacy drivers with CONFIG_DRM_LEGACY

2016-08-04 Thread David Herrmann
Lets move forward and hide the remaining DRI1 drivers behind a config
option, so we have a central place to disable them all. Furthermore, we
can provide a clear warning to anyone enabling them.

Signed-off-by: David Herrmann 
---
 drivers/gpu/drm/Kconfig | 135 
 1 file changed, 78 insertions(+), 57 deletions(-)

diff --git a/drivers/gpu/drm/Kconfig b/drivers/gpu/drm/Kconfig
index fc35731..d8f6203 100644
--- a/drivers/gpu/drm/Kconfig
+++ b/drivers/gpu/drm/Kconfig
@@ -108,24 +108,8 @@ config DRM_KMS_CMA_HELPER

 source "drivers/gpu/drm/i2c/Kconfig"

-config DRM_TDFX
-   tristate "3dfx Banshee/Voodoo3+"
-   depends on DRM && PCI
-   help
- Choose this option if you have a 3dfx Banshee or Voodoo3 (or later),
- graphics card.  If M is selected, the module will be called tdfx.
-
 source "drivers/gpu/drm/arm/Kconfig"

-config DRM_R128
-   tristate "ATI Rage 128"
-   depends on DRM && PCI
-   select FW_LOADER
-   help
- Choose this option if you have an ATI Rage 128 graphics card.  If M
- is selected, the module will be called r128.  AGP support for
- this card is strongly suggested (unless you have a PCI version).
-
 config DRM_RADEON
tristate "ATI Radeon"
depends on DRM && PCI
@@ -177,49 +161,8 @@ source "drivers/gpu/drm/amd/acp/Kconfig"

 source "drivers/gpu/drm/nouveau/Kconfig"

-config DRM_I810
-   tristate "Intel I810"
-   # !PREEMPT because of missing ioctl locking
-   depends on DRM && AGP && AGP_INTEL && (!PREEMPT || BROKEN)
-   help
- Choose this option if you have an Intel I810 graphics card.  If M is
- selected, the module will be called i810.  AGP support is required
- for this driver to work.
-
 source "drivers/gpu/drm/i915/Kconfig"

-config DRM_MGA
-   tristate "Matrox g200/g400"
-   depends on DRM && PCI
-   select FW_LOADER
-   help
- Choose this option if you have a Matrox G200, G400 or G450 graphics
- card.  If M is selected, the module will be called mga.  AGP
- support is required for this driver to work.
-
-config DRM_SIS
-   tristate "SiS video cards"
-   depends on DRM && AGP
-   depends on FB_SIS || FB_SIS=n
-   help
- Choose this option if you have a SiS 630 or compatible video
-  chipset. If M is selected the module will be called sis. AGP
-  support is required for this driver to work.
-
-config DRM_VIA
-   tristate "Via unichrome video cards"
-   depends on DRM && PCI
-   help
- Choose this option if you have a Via unichrome or compatible video
- chipset. If M is selected the module will be called via.
-
-config DRM_SAVAGE
-   tristate "Savage video cards"
-   depends on DRM && PCI
-   help
- Choose this option if you have a Savage3D/4/SuperSavage/Pro/Twister
- chipset. If M is selected the module will be called savage.
-
 config DRM_VGEM
tristate "Virtual GEM provider"
depends on DRM
@@ -290,3 +233,81 @@ source "drivers/gpu/drm/arc/Kconfig"
 source "drivers/gpu/drm/hisilicon/Kconfig"

 source "drivers/gpu/drm/mediatek/Kconfig"
+
+# Keep legacy drivers last
+
+menuconfig DRM_LEGACY
+   bool "Enable legacy drivers (DANGEROUS)"
+   depends on DRM
+   help
+ Enable legacy DRI1 drivers. Those drivers expose unsafe and dangerous
+ APIs to user-space, which can be used to circumvent access
+ restrictions and other security measures. For backwards compatibility
+ those drivers are still available, but their use is highly
+ inadvisable and might harm your system.
+
+ You are recommended to use the safe modeset-only drivers instead, and
+ perform 3D emulation in user-space.
+
+ Unless you have strong reasons to go rogue, say "N".
+
+if DRM_LEGACY
+
+config DRM_TDFX
+   tristate "3dfx Banshee/Voodoo3+"
+   depends on DRM && PCI
+   help
+ Choose this option if you have a 3dfx Banshee or Voodoo3 (or later),
+ graphics card.  If M is selected, the module will be called tdfx.
+
+config DRM_R128
+   tristate "ATI Rage 128"
+   depends on DRM && PCI
+   select FW_LOADER
+   help
+ Choose this option if you have an ATI Rage 128 graphics card.  If M
+ is selected, the module will be called r128.  AGP support for
+ this card is strongly suggested (unless you have a PCI version).
+
+config DRM_I810
+   tristate "Intel I810"
+   # !PREEMPT because of missing ioctl locking
+   depends on DRM && AGP && AGP_

[PATCH 2/2] drm: make DRI1 drivers depend on BROKEN

2016-08-04 Thread David Herrmann
The legacy DRI1 drivers expose highly broken interfaces to user-space. No
modern system should enable them, or you will effectively allow user-space
to circumvent most of your kernel security measures. The DRI1 kernel APIs
are simply broken.

User-space can always use vesafb/efifb/simplefb and friends to get working
graphics.

Lets hide the old drivers behind CONFIG_BROKEN. In case they turn out to
be still used (really?), we can easily revert this and figure out a way to
move them out of sight (e.g., moving all DRI1 drivers to
drivers/gpu/dri1/).

Signed-off-by: David Herrmann 
---
 drivers/gpu/drm/Kconfig | 1 +
 1 file changed, 1 insertion(+)

diff --git a/drivers/gpu/drm/Kconfig b/drivers/gpu/drm/Kconfig
index d8f6203..48d9223 100644
--- a/drivers/gpu/drm/Kconfig
+++ b/drivers/gpu/drm/Kconfig
@@ -239,6 +239,7 @@ source "drivers/gpu/drm/mediatek/Kconfig"
 menuconfig DRM_LEGACY
bool "Enable legacy drivers (DANGEROUS)"
depends on DRM
+   depends on BROKEN
help
  Enable legacy DRI1 drivers. Those drivers expose unsafe and dangerous
  APIs to user-space, which can be used to circumvent access
-- 
2.9.2



[PATCH] drm: Declare that create drm_mm nodes with size 0 is illegal

2016-08-04 Thread David Herrmann
On Wed, Aug 3, 2016 at 8:26 PM, Chris Wilson  
wrote:
> At a higher level, all objects are created with definite size i.e. 0 is
> illegal. In forthcoming patches, this assumption is dependent upon in
> the drm_mm range manager, i.e. trying to create a drm_mm node with size
> 0 will have undefined behaviour. Add a couple of WARNs upon creating the
> drm_mm node to prevent later bugs.
>
> Signed-off-by: Chris Wilson 
> ---
>  drivers/gpu/drm/drm_mm.c | 9 +
>  1 file changed, 9 insertions(+)

Reviewed-by: David Herrmann 

Thanks
David

> diff --git a/drivers/gpu/drm/drm_mm.c b/drivers/gpu/drm/drm_mm.c
> index cb39f45d6a16..e8c15795386d 100644
> --- a/drivers/gpu/drm/drm_mm.c
> +++ b/drivers/gpu/drm/drm_mm.c
> @@ -185,6 +185,9 @@ int drm_mm_reserve_node(struct drm_mm *mm, struct 
> drm_mm_node *node)
>
> BUG_ON(node == NULL);
>
> +   if (WARN_ON(node->size == 0))
> +   return -EINVAL;
> +
> end = node->start + node->size;
>
> /* Find the relevant hole to add our node to */
> @@ -239,6 +242,9 @@ int drm_mm_insert_node_generic(struct drm_mm *mm, struct 
> drm_mm_node *node,
>  {
> struct drm_mm_node *hole_node;
>
> +   if (WARN_ON(size == 0))
> +   return -EINVAL;
> +
> hole_node = drm_mm_search_free_generic(mm, size, alignment,
>color, sflags);
> if (!hole_node)
> @@ -340,6 +346,9 @@ int drm_mm_insert_node_in_range_generic(struct drm_mm 
> *mm, struct drm_mm_node *n
>  {
> struct drm_mm_node *hole_node;
>
> +   if (WARN_ON(size == 0))
> +   return -EINVAL;
> +
> hole_node = drm_mm_search_free_in_range_generic(mm,
> size, alignment, 
> color,
> start, end, sflags);
> --
> 2.8.1
>
> ___
> dri-devel mailing list
> dri-devel at lists.freedesktop.org
> https://lists.freedesktop.org/mailman/listinfo/dri-devel


[PATCH 2/8] drm: remove redundant drm_file->uid

2016-08-04 Thread David Herrmann
Hey

On Wed, Aug 3, 2016 at 9:01 PM, Chris Wilson  
wrote:
> On Wed, Aug 03, 2016 at 08:04:26PM +0200, David Herrmann wrote:
>> @@ -98,13 +99,14 @@ int drm_clients_info(struct seq_file *m, void *data)
>>
>>   rcu_read_lock(); /* locks pid_task()->comm */
>>   task = pid_task(priv->pid, PIDTYPE_PID);
>> + uid = priv->filp ? priv->filp->f_cred->euid : GLOBAL_ROOT_UID;
>>   seq_printf(m, "%20s %5d %3d   %c%c %5d %10u\n",
>>  task ? task->comm : "",
>>  pid_vnr(priv->pid),
>>  priv->minor->index,
>>  drm_is_current_master(priv) ? 'y' : 'n',
>>  priv->authenticated ? 'y' : 'n',
>> -from_kuid_munged(seq_user_ns(m), priv->uid),
>> +from_kuid_munged(seq_user_ns(m), uid),
>>  priv->magic);
>>   rcu_read_unlock();
>>   }
>> diff --git a/drivers/gpu/drm/drm_ioctl.c b/drivers/gpu/drm/drm_ioctl.c
>> index 33af4a5..49cd835 100644
>> --- a/drivers/gpu/drm/drm_ioctl.c
>> +++ b/drivers/gpu/drm/drm_ioctl.c
>> @@ -191,7 +191,9 @@ static int drm_getclient(struct drm_device *dev, void 
>> *data,
>>   client->auth = file_priv->authenticated;
>>   client->pid = pid_vnr(file_priv->pid);
>>   client->uid = from_kuid_munged(current_user_ns(),
>> -file_priv->uid);
>> +file_priv->filp ?
>> +file_priv->filp->f_cred->euid :
>> +GLOBAL_ROOT_UID);
>
> Why can't we use task_euid(pid_task(file_priv->pid)) here as well?

task_euid() changes semantics. With this patch I just tried to get rid
of "filp" usage, but keep semantics, so the ABI does not suddently
change.

Note that both calls are actually changed in follow-ups. "uid" is just
cleared to "overflowuid", since no-one ever looks at that field. And
"pid" is set to "pid_vnr(current)". However, I explicitly split those
patches to make sure it is easier to bisect.

Thanks
David


[PATCH 5/8] drm: use drm_file to tag vm-bos

2016-08-04 Thread David Herrmann
Hey

On Thu, Aug 4, 2016 at 10:16 AM, Daniel Vetter  wrote:
> On Wed, Aug 03, 2016 at 08:08:19PM +0100, Chris Wilson wrote:
>> On Wed, Aug 03, 2016 at 08:04:29PM +0200, David Herrmann wrote:
>> > Rather than using "struct file*", use "struct drm_file*" as tag VM tag for
>> > BOs. This will pave the way for "struct drm_file*" without any "struct
>> > file*" back-pointer.
>> >
>> > Signed-off-by: David Herrmann 
>>
>> Ok, the danger of untyped is having to check each and trying to spot any
>> missed conversions.
>
> Hm yeah ... any reason we can't just switch to struct drm_file instead? At
> least I can't come up with any other use case where we might supply
> something else, and it's always nice to enlist the compiler for a little
> bit of help.

Fair enough. Will change this. Will send v2 once I'm back from vacation.

Thanks
David


[PATCH 0/2] drm: add SimpleDRM driver

2016-08-04 Thread David Herrmann
Hi

On Thu, Aug 4, 2016 at 5:34 PM, Luc Verhaegen  wrote:
> Do we really want to recreate a 400+ email thread again, or are we
> capable of learning from the past?

No we don't. And no-one intends to. I am fully aware of the discussion
that introduced the clock-dependencies to simplefb, and I gladly
accept patches that add such support to SimpleDRM. Did anyone say
otherwise? This series adds initial support for the devices _we_ know
and can test (which is x86 and RPi, in my case). If someone wants
support for more devices, please send patches. Why does this have to
be included (or even discussed) as part of this submission?

Thanks
David


[PATCH 0/2] drm: add SimpleDRM driver

2016-08-04 Thread David Herrmann
Hi

On Thu, Aug 4, 2016 at 10:01 PM, Daniel Vetter  wrote:
> On Thu, Aug 04, 2016 at 02:50:37PM -0500, Ken Phillis Jr wrote:
>> I believe this driver is extremely useful, and I see possible issues with
>> the fact that the driver is GPL Only. This driver is critical for devices
>> that lack a proper DRM driver, and locking it into GPL Only could lead to
>> issues with porting the system over to platforms like FreeBSD,
>> DragonFlyBSD, etc.  Is there any chance the code placed in the
>> "drivers/gpu/drm/simpledrm" folder be placed under a more permissive
>> license setup. I would suggest using MIT[1], BSD 2-Clause[2], or BSD
>> 3-clause[3]. Also as a quick note it is possible to enable this under a
>> dual-license setup with GPLv2/BSD-3 Clause. An example a dual licensed
>> driver is the Intel iwlwifi driver ( see:
>> drivers/net/wireless/intel/iwlwifi/iwl-8000.c )
>
> tbh, most if not all arm drivers are gpl only, and due to code sharing and
> refactoring I'd say a lot of that has leaked all over drm. IANAL and all
> that, but personally I believe that the entire idea of drm being MIT is
> walking on ever thinner ice. And personally I'm not going to extend effort
> to slow this down or prevent it outright, since I think all that code
> sharing with arm folks is extremely beneficial for everyone. At least here
> on Linux.
> -Daniel

On top of that: Feel free to copy SimpleDRM in any way possible.
Consider my original implementation public domain.

Thanks
David


Re: [PATCH v1 1/1] drm: drop drm_bus from todo

2019-01-27 Thread David Herrmann
Hey

On Sat, Jan 26, 2019 at 8:27 PM Sam Ravnborg  wrote:
> David Herrmann removed the last bits of drm_bus in:
> c5786fe5f1c50941dbe27fc8b4aa1afee46ae893 ("drm: Goody bye, drm_bus!")
>
> Remove the todo item.
>
> Signed-off-by: Sam Ravnborg 
> Cc: David Herrmann 
> Cc: David Airlie 
> Cc: Daniel Vetter 
> Cc: Maarten Lankhorst 
> Cc: Maxime Ripard 
> Cc: Sean Paul 
> ---
>  Documentation/gpu/todo.rst | 19 ---
>  1 file changed, 19 deletions(-)

I miss drm_bus!

Reviewed-by: David Herrmann 

Thanks
David

> diff --git a/Documentation/gpu/todo.rst b/Documentation/gpu/todo.rst
> index 38360ede1221..d9515b17d36f 100644
> --- a/Documentation/gpu/todo.rst
> +++ b/Documentation/gpu/todo.rst
> @@ -10,25 +10,6 @@ graphics subsystem useful as newbie projects. Or for slow 
> rainy days.
>  Subsystem-wide refactorings
>  ===
>
> -De-midlayer drivers
> 
> -
> -With the recent ``drm_bus`` cleanup patches for 3.17 it is no longer required
> -to have a ``drm_bus`` structure set up. Drivers can directly set up the
> -``drm_device`` structure instead of relying on bus methods in ``drm_usb.c``
> -and ``drm_pci.c``. The goal is to get rid of the driver's ``->load`` /
> -``->unload`` callbacks and open-code the load/unload sequence properly, using
> -the new two-stage ``drm_device`` setup/teardown.
> -
> -Once all existing drivers are converted we can also remove those bus support
> -files for USB and platform devices.
> -
> -All you need is a GPU for a non-converted driver (currently almost all of
> -them, but also all the virtual ones used by KVM, so everyone qualifies).
> -
> -Contact: Daniel Vetter, Thierry Reding, respective driver maintainers
> -
> -
>  Remove custom dumb_map_offset implementations
>  -
>
> --
> 2.12.0
>
___
dri-devel mailing list
dri-devel@lists.freedesktop.org
https://lists.freedesktop.org/mailman/listinfo/dri-devel


Re: [PATCHv3 06/30] drm/omap: Add support for render nodes

2017-03-29 Thread David Herrmann
Hi

On Wed, Mar 29, 2017 at 2:20 PM, Laurent Pinchart
 wrote:
> Hi Tomi,
>
> (CC'ing Daniel and David)
>
> On Wednesday 29 Mar 2017 11:58:23 Tomi Valkeinen wrote:
>> On 29/03/17 11:22, Laurent Pinchart wrote:
>> > Hi Tomi,
>> >
>> > Thank you for the patch.
>> >
>> > On Tuesday 28 Mar 2017 16:07:52 Tomi Valkeinen wrote:
>> >> From: Hemant Hariyani 
>> >>
>> >> Add support for render nodes in omap driver and allow required
>> >> ioctls to be accessible via render nodes.
>> >
>> > But the OMAP DSS doesn't perform rendering... This seems an abuse of
>> > render nodes, I think the API should instead be implemented by the GPU
>> > driver.
>>
>> I agree that the GPU use case described in the patch sounds a bit odd.
>> Why not allocate from the GPU driver instead. But here a particular
>> issue is that to get TILER buffers we need to ask them from the omapdrm.
>> Probably TILER should not be part of omapdrm, but then, where should it
>> be...
>>
>> We also have writeback in DSS, which can function as a memory to memory
>> or capture device. That's not supported in the mainline, but we have
>> support in the TI kernel.
>>
>> And how about a case where you have the privileged process as KMS
>> master, and another process wants to draw to a buffer with the CPU, and
>> then give the buffer to the privileged process for displaying.
>>
>> So, yes, DSS is not a renderer (well, WB is kind of rendering), but
>> isn't it a valid use case to allocate a buffer from omapdrm?
>
> It could be a valid use case, but it's still an API abuse. It starts sounding
> like a DRM core issue to me. The DRIVER_RENDER flag is not documented, so its
> exact meaning isn't defined. I thought it was supposed to flag the device as a
> renderer (GPU).
>
> commit 1793126fcebd7c18834f95d43b55e387a8803aa8
> Author: David Herrmann 
> Date:   Sun Aug 25 18:29:00 2013 +0200
>
> drm: implement experimental render nodes
>
> Render nodes provide an API for userspace to use non-privileged GPU
> commands without any running DRM-Master. It is useful for offscreen
> rendering, GPGPU clients, and normal render clients which do not perform
> modesetting.
>
> [...]
>
> You instead use the flag as a way to enable unprivileged clients to allocate
> buffers. If that's what the flag should mean, I wonder if there would be a use
> case for *not* setting it.

Correct. You can (and should) enable all your sandboxed commands on
render nodes. That is, if a command only affects the issuing client,
then it is safe for render-nodes. If two clients have a file-context
opened on the render node, they should be unable to affect each other
(minus accounting, resource allocation, etc.).

The name is historic (I did not come up with it either, but failed at
renaming it..). The DRIVER_RENDER flag only controls whether the
render-node is actually instantiated. I will not object doing that
unconditionally. It will create some useless nodes for legacy drivers,
but we should not care.

Thanks
David
___
dri-devel mailing list
dri-devel@lists.freedesktop.org
https://lists.freedesktop.org/mailman/listinfo/dri-devel


Re: [PATCHv3 06/30] drm/omap: Add support for render nodes

2017-03-29 Thread David Herrmann
Hey

On Wed, Mar 29, 2017 at 11:42 PM, Laurent Pinchart
 wrote:
> Hi David,
>
> On Wednesday 29 Mar 2017 14:51:48 David Herrmann wrote:
>> On Wed, Mar 29, 2017 at 2:20 PM, Laurent Pinchart wrote:
>> > On Wednesday 29 Mar 2017 11:58:23 Tomi Valkeinen wrote:
>> >> On 29/03/17 11:22, Laurent Pinchart wrote:
>> >>> On Tuesday 28 Mar 2017 16:07:52 Tomi Valkeinen wrote:
>> >>>> From: Hemant Hariyani 
>> >>>>
>> >>>> Add support for render nodes in omap driver and allow required
>> >>>> ioctls to be accessible via render nodes.
>> >>>
>> >>> But the OMAP DSS doesn't perform rendering... This seems an abuse of
>> >>> render nodes, I think the API should instead be implemented by the GPU
>> >>> driver.
>> >>
>> >> I agree that the GPU use case described in the patch sounds a bit odd.
>> >> Why not allocate from the GPU driver instead. But here a particular
>> >> issue is that to get TILER buffers we need to ask them from the omapdrm.
>> >> Probably TILER should not be part of omapdrm, but then, where should it
>> >> be...
>> >>
>> >> We also have writeback in DSS, which can function as a memory to memory
>> >> or capture device. That's not supported in the mainline, but we have
>> >> support in the TI kernel.
>> >>
>> >> And how about a case where you have the privileged process as KMS
>> >> master, and another process wants to draw to a buffer with the CPU, and
>> >> then give the buffer to the privileged process for displaying.
>> >>
>> >> So, yes, DSS is not a renderer (well, WB is kind of rendering), but
>> >> isn't it a valid use case to allocate a buffer from omapdrm?
>> >
>> > It could be a valid use case, but it's still an API abuse. It starts
>> > sounding like a DRM core issue to me. The DRIVER_RENDER flag is not
>> > documented, so its exact meaning isn't defined. I thought it was supposed
>> > to flag the device as a renderer (GPU).
>> >
>> > commit 1793126fcebd7c18834f95d43b55e387a8803aa8
>> > Author: David Herrmann 
>> > Date:   Sun Aug 25 18:29:00 2013 +0200
>> >
>> > drm: implement experimental render nodes
>> >
>> > Render nodes provide an API for userspace to use non-privileged GPU
>> > commands without any running DRM-Master. It is useful for offscreen
>> > rendering, GPGPU clients, and normal render clients which do not
>> > perform
>> > modesetting.
>> >
>> > [...]
>> >
>> > You instead use the flag as a way to enable unprivileged clients to
>> > allocate buffers. If that's what the flag should mean, I wonder if there
>> > would be a use case for *not* setting it.
>>
>> Correct. You can (and should) enable all your sandboxed commands on
>> render nodes. That is, if a command only affects the issuing client,
>> then it is safe for render-nodes. If two clients have a file-context
>> opened on the render node, they should be unable to affect each other
>> (minus accounting, resource allocation, etc.).
>>
>> The name is historic (I did not come up with it either, but failed at
>> renaming it..). The DRIVER_RENDER flag only controls whether the
>> render-node is actually instantiated. I will not object doing that
>> unconditionally. It will create some useless nodes for legacy drivers,
>> but we should not care.
>
> Couldn't we achieve the same effect without render nodes, by allowing GEM
> object allocation on the main DRM node by unauthenticated clients ?

Using a different inode makes sure you can sand-box the node. That is,
you can now easily mknod a render node in containers and sandboxes
without risk of exposing any other APIs.

I guess you could achieve something similar by careful selection of
which privs to pass to the container. But we preferred a clean cut
back then.

Thanks
David
___
dri-devel mailing list
dri-devel@lists.freedesktop.org
https://lists.freedesktop.org/mailman/listinfo/dri-devel


Re: [PATCH] drm: Document code of conduct

2017-04-11 Thread David Herrmann
Hey

On Tue, Apr 11, 2017 at 8:48 AM, Daniel Vetter  wrote:
> freedesktop.org has adopted a formal&enforced code of conduct:
>
> https://www.fooishbar.org/blog/fdo-contributor-covenant/
> https://www.freedesktop.org/wiki/CodeOfConduct/
>
> Besides formalizing things a bit more I don't think this changes
> anything for us, we've already peer-enforced respectful and
> constructive interactions since a long time. But it's good to document
> things properly.
>
> Note: As Daniel Stone mentioned in the announcement fd.o admins
> started chatting with the communities their hosting, which includs the
> X.org foundation board, to figure out how to fan out enforcement and
> allow projects to run things on their own (with fd.o still as the
> fallback).  So the details of enforcement (and appealing decisions)
> might still change, but since this involves the board and lots more
> people it'll take a while to get there. For now this is good enough I
> think.
>
> For the text itself I went with the same blurb as the Wayland project,
> didn't feel creative yet this early in the morning:
>
> https://cgit.freedesktop.org/wayland/wayland/commit/?id=0eefe99fe0683ae409b665a8b18cc7eb648c6c0c
>
> Cc: Daniel Stone 
> Cc: Keith Packard 
> Cc: tfh...@err.no
> Signed-off-by: Daniel Vetter 

Reviewed-by: David Herrmann 

Thanks
David

> ---
>  Documentation/gpu/introduction.rst | 11 +++
>  1 file changed, 11 insertions(+)
>
> diff --git a/Documentation/gpu/introduction.rst 
> b/Documentation/gpu/introduction.rst
> index 05a82bdfbca4..0f5173e29bdc 100644
> --- a/Documentation/gpu/introduction.rst
> +++ b/Documentation/gpu/introduction.rst
> @@ -85,3 +85,14 @@ This means that there's a blackout-period of about one 
> month where feature work
>  can't be merged. The recommended way to deal with that is having a -next tree
>  that's always open, but making sure to not feed it into linux-next during the
>  blackout period. As an example, drm-misc works like that.
> +
> +Code of Conduct
> +---
> +
> +As a freedesktop.org project, dri-devel and the DRM community follows the
> +Contributor Covenant, found at: 
> https://www.freedesktop.org/wiki/CodeOfConduct
> +
> +Please conduct yourself in a respectful and civilised manner when
> +interacting with community members on mailing lists, IRC, or bug
> +trackers. The community represents the project as a whole, and abusive
> +or bullying behaviour is not tolerated by the project.
> --
> 2.11.0
>
> ___
> dri-devel mailing list
> dri-devel@lists.freedesktop.org
> https://lists.freedesktop.org/mailman/listinfo/dri-devel
___
dri-devel mailing list
dri-devel@lists.freedesktop.org
https://lists.freedesktop.org/mailman/listinfo/dri-devel


drm: GPF in drm_getcap

2016-11-26 Thread David Herrmann
Hi

On Sat, Nov 26, 2016 at 6:17 PM, Dmitry Vyukov  wrote:
> On Fri, Sep 9, 2016 at 1:56 PM, Dmitry Vyukov  wrote:
>> Hello,
>>
>> The following program triggers GPF in drm_getcap:
>>
>> // autogenerated by syzkaller (http://github.com/google/syzkaller)
>> #include 
>> #include 
>> #include 
>> #include 
>> #include 
>> #include 
>> #include 
>> #include 
>>
>> int main()
>> {
>>   int fd = open("/dev/dri/card0", O_RDONLY);
>>   uint64_t data[2] = {0x11, 0x80};
>>   ioctl(fd, 0xc010640cul /*DRM_IOCTL_GET_CAP*/, data);
>>   return 0;
>> }
>>
>>
>> general protection fault:  [#1] SMP DEBUG_PAGEALLOC KASAN
>> Modules linked in:
>> CPU: 1 PID: 5745 Comm: syz-executor Not tainted 4.8.0-rc5-next-20160905+ #14
>> Hardware name: QEMU Standard PC (i440FX + PIIX, 1996), BIOS Bochs 01/01/2011
>> task: 8800310dc540 task.stack: 88003cbc
>> RIP: 0010:[]  []
>> drm_getcap+0x34b/0x4f0 drivers/gpu/drm/drm_ioctl.c:260
>> RSP: 0018:88003cbc7c28  EFLAGS: 00010202
>> RAX: 0058 RBX: 88003cbc7cf8 RCX: c90001db
>> RDX: 005d RSI: 88003cbc7cf8 RDI: 02c0
>> RBP: 88003cbc7c50 R08: ed0007978fa1 R09: ed0007978fa0
>> R10: 88003cbc7d07 R11: ed0007978fa1 R12: fff0
>> R13: dc00 R14: 88003bcc6850 R15: fff2
>> FS:  7fcbf4e03700() GS:88003ed0() knlGS:
>> CS:  0010 DS:  ES:  CR0: 80050033
>> CR2: 006dce00 CR3: 66135000 CR4: 06e0
>> DR0: 001e DR1: 001e DR2: 
>> DR3:  DR6: 0ff0 DR7: 0600
>> Stack:
>>  88003c26db00 88003cbc7cf8 875a3000 88cf0ee0
>>  fff2 88003cbc7dc0 834cb57c e200
>>  1101 875a1ba0 882ae930 0010
>> Call Trace:
>>  [] drm_ioctl+0x54c/0xaf0 drivers/gpu/drm/drm_ioctl.c:728
>>  [< inline >] vfs_ioctl fs/ioctl.c:43
>>  [] do_vfs_ioctl+0x18c/0x1080 fs/ioctl.c:675
>>  [< inline >] SYSC_ioctl fs/ioctl.c:690
>>  [] SyS_ioctl+0x8f/0xc0 fs/ioctl.c:681
>>  [] entry_SYSCALL_64_fastpath+0x23/0xc1
>> Code: 3c 28 00 0f 85 88 01 00 00 49 8b 44 24 10 49 39 c6 4c 8d 60 f0
>> 74 82 e8 64 19 10 fe 49 8d bc 24 d0 02 00 00 48 89 f8 48 c1 e8 03 <42>
>> 80 3c 28 00 0f 85 6f 01 00 00 4d 8b bc 24 d0 02 00 00 49 8d
>> RIP  [] drm_getcap+0x34b/0x4f0 
>> drivers/gpu/drm/drm_ioctl.c:260
>>  RSP 
>> ---[ end trace c6e1afa8cd73b880 ]---
>>
>>
>> On commit 4affa544adb8077403893e62b9e327fcf87de6f7 (Sep 8) of linux-next.
>
> ping
>
> Still happens on 16ae16c6e5616c084168740990fc508bda6655d4 (Nov 24).

I suspect this is because we run drm_for_each_crtc() in
drm_getcap(DRM_PAGE_FLIP_TARGET) on a legacy driver (meaning
mode_config is not initialized). @danvet, how about always
initializing mode_config to 0/empty/dummy?

Dmitry, what driver do you run this on? And is CONFIG_DRM_LEGACY enabled?

Thanks
David


drm: GPF in drm_getcap

2016-11-26 Thread David Herrmann
Hi

On Sat, Nov 26, 2016 at 6:50 PM, Dmitry Vyukov  wrote:
> On Sat, Nov 26, 2016 at 6:35 PM, David Herrmann  
> wrote:
>> Hi
>>
>> On Sat, Nov 26, 2016 at 6:17 PM, Dmitry Vyukov  wrote:
>>> On Fri, Sep 9, 2016 at 1:56 PM, Dmitry Vyukov  wrote:
>>>> Hello,
>>>>
>>>> The following program triggers GPF in drm_getcap:
>>>>
>>>> // autogenerated by syzkaller (http://github.com/google/syzkaller)
>>>> #include 
>>>> #include 
>>>> #include 
>>>> #include 
>>>> #include 
>>>> #include 
>>>> #include 
>>>> #include 
>>>>
>>>> int main()
>>>> {
>>>>   int fd = open("/dev/dri/card0", O_RDONLY);
>>>>   uint64_t data[2] = {0x11, 0x80};
>>>>   ioctl(fd, 0xc010640cul /*DRM_IOCTL_GET_CAP*/, data);
>>>>   return 0;
>>>> }
>>>>
>>>>
>>>> general protection fault:  [#1] SMP DEBUG_PAGEALLOC KASAN
>>>> Modules linked in:
>>>> CPU: 1 PID: 5745 Comm: syz-executor Not tainted 4.8.0-rc5-next-20160905+ 
>>>> #14
>>>> Hardware name: QEMU Standard PC (i440FX + PIIX, 1996), BIOS Bochs 
>>>> 01/01/2011
>>>> task: 8800310dc540 task.stack: 88003cbc
>>>> RIP: 0010:[]  []
>>>> drm_getcap+0x34b/0x4f0 drivers/gpu/drm/drm_ioctl.c:260
>>>> RSP: 0018:88003cbc7c28  EFLAGS: 00010202
>>>> RAX: 0058 RBX: 88003cbc7cf8 RCX: c90001db
>>>> RDX: 005d RSI: 88003cbc7cf8 RDI: 02c0
>>>> RBP: 88003cbc7c50 R08: ed0007978fa1 R09: ed0007978fa0
>>>> R10: 88003cbc7d07 R11: ed0007978fa1 R12: fff0
>>>> R13: dc00 R14: 88003bcc6850 R15: fff2
>>>> FS:  7fcbf4e03700() GS:88003ed0() 
>>>> knlGS:
>>>> CS:  0010 DS:  ES:  CR0: 80050033
>>>> CR2: 006dce00 CR3: 66135000 CR4: 06e0
>>>> DR0: 001e DR1: 001e DR2: 
>>>> DR3:  DR6: 0ff0 DR7: 0600
>>>> Stack:
>>>>  88003c26db00 88003cbc7cf8 875a3000 88cf0ee0
>>>>  fff2 88003cbc7dc0 834cb57c e200
>>>>  1101 875a1ba0 882ae930 0010
>>>> Call Trace:
>>>>  [] drm_ioctl+0x54c/0xaf0 drivers/gpu/drm/drm_ioctl.c:728
>>>>  [< inline >] vfs_ioctl fs/ioctl.c:43
>>>>  [] do_vfs_ioctl+0x18c/0x1080 fs/ioctl.c:675
>>>>  [< inline >] SYSC_ioctl fs/ioctl.c:690
>>>>  [] SyS_ioctl+0x8f/0xc0 fs/ioctl.c:681
>>>>  [] entry_SYSCALL_64_fastpath+0x23/0xc1
>>>> Code: 3c 28 00 0f 85 88 01 00 00 49 8b 44 24 10 49 39 c6 4c 8d 60 f0
>>>> 74 82 e8 64 19 10 fe 49 8d bc 24 d0 02 00 00 48 89 f8 48 c1 e8 03 <42>
>>>> 80 3c 28 00 0f 85 6f 01 00 00 4d 8b bc 24 d0 02 00 00 49 8d
>>>> RIP  [] drm_getcap+0x34b/0x4f0 
>>>> drivers/gpu/drm/drm_ioctl.c:260
>>>>  RSP 
>>>> ---[ end trace c6e1afa8cd73b880 ]---
>>>>
>>>>
>>>> On commit 4affa544adb8077403893e62b9e327fcf87de6f7 (Sep 8) of linux-next.
>>>
>>> ping
>>>
>>> Still happens on 16ae16c6e5616c084168740990fc508bda6655d4 (Nov 24).
>>
>> I suspect this is because we run drm_for_each_crtc() in
>> drm_getcap(DRM_PAGE_FLIP_TARGET) on a legacy driver (meaning
>> mode_config is not initialized). @danvet, how about always
>> initializing mode_config to 0/empty/dummy?
>>
>> Dmitry, what driver do you run this on? And is CONFIG_DRM_LEGACY enabled?
>
>
> CONFIG_DRM_LEGACY is enabled.
>
> How can I understand what driver is used?
> This happens inside of qemu. This is the device:
> crw-rw---T 1 root video 226, 0 Nov 26 17:45 /dev/dri/card0

Usually by looking into `dmesg` and grepping for 'card0', or by inspecting:

/sys/class/drm/card0/device/

or more importantly looking at the symlink:

/sys/class/drm/card0/device/driver

Thanks
David


drm: GPF in drm_getcap

2016-11-26 Thread David Herrmann
Hi

On Sat, Nov 26, 2016 at 7:07 PM, Dmitry Vyukov  wrote:
> grep "card0" dmesg:
> [5.298617] device: 'card0': device_add
> [5.298946] PM: Adding info for No Bus:card0
> [6.436178] device: 'card0': device_add
> [6.436488] PM: Adding info for No Bus:card0
>
>
> # ls -l /dev/dri/card0
> crw-rw---T 1 root video 226, 0 Nov 26 18:05 /dev/dri/card0
>
> # ls -lt /sys/class/drm/card0/device/
> ls: cannot access /sys/class/drm/card0/device/: No such file or directory
>
> # ls -lt /sys/class/drm/card0/device/driver
> ls: cannot access /sys/class/drm/card0/device/driver: No such file or 
> directory

Looks like vgem. Something like this should help:

https://gist.github.com/dvdhrm/1bcdf4f3485aa1614a0198a7b90515e2

I wonder whether it would be more appropriate to return -ENOTSUPP rather than 0.

Thanks
David


Re: [PATCH 08/24] drm: Remove DRM_MINOR_CNT

2017-03-08 Thread David Herrmann
Hi

On Wed, Mar 8, 2017 at 3:12 PM, Daniel Vetter  wrote:
> This was originally added by David Herrmann for range checks, but
> entirely unused. It confused me, so let's remove it.
>
> Cc: David Herrmann 
> Signed-off-by: Daniel Vetter 
> ---
>  include/drm/drmP.h | 1 -
>  1 file changed, 1 deletion(-)

Reviewed-by: David Herrmann 

Thanks
David

> diff --git a/include/drm/drmP.h b/include/drm/drmP.h
> index 826101785876..7bd6752683a4 100644
> --- a/include/drm/drmP.h
> +++ b/include/drm/drmP.h
> @@ -444,7 +444,6 @@ enum drm_minor_type {
> DRM_MINOR_PRIMARY,
> DRM_MINOR_CONTROL,
> DRM_MINOR_RENDER,
> -   DRM_MINOR_CNT,
>  };
>
>  /**
> --
> 2.11.0
>
___
dri-devel mailing list
dri-devel@lists.freedesktop.org
https://lists.freedesktop.org/mailman/listinfo/dri-devel


Re: [PATCH v4] dma-buf/sync-file: Defer creation of sync_file->name

2017-05-15 Thread David Herrmann
Hey

On Mon, May 15, 2017 at 12:10 PM, Chris Wilson  wrote:
> Constructing the name takes the majority of the time for allocating a
> sync_file to wrap a fence, and the name is very rarely used (only via
> the sync_file status user interface). To reduce the impact on the common
> path (that of creating sync_file to pass around), defer the construction
> of the name until it is first used.
>
> v2: Update kerneldoc (kbuild test robot)
> v3: sync_debug.c was peeking at the name
> v4: Comment upon the potential race between two users of
> sync_file_get_name() and claim that such a race is below the level of
> notice. However, to prevent any future nuisance, use a global spinlock
> to serialize the assignment of the name.
>
> Signed-off-by: Chris Wilson 
> Cc: Sumit Semwal 
> Cc: Gustavo Padovan 
> Cc: Daniel Vetter 
> ---
>  drivers/dma-buf/sync_debug.c |  3 ++-
>  drivers/dma-buf/sync_file.c  | 54 
> ++--
>  include/linux/sync_file.h|  5 ++--
>  3 files changed, 52 insertions(+), 10 deletions(-)
>
> diff --git a/drivers/dma-buf/sync_debug.c b/drivers/dma-buf/sync_debug.c
> index 4b1731ee7458..9a93f1085c63 100644
> --- a/drivers/dma-buf/sync_debug.c
> +++ b/drivers/dma-buf/sync_debug.c
> @@ -134,7 +134,8 @@ static void sync_print_sync_file(struct seq_file *s,
>  {
> int i;
>
> -   seq_printf(s, "[%p] %s: %s\n", sync_file, sync_file->name,
> +   seq_printf(s, "[%p] %s: %s\n", sync_file,
> +  sync_file_get_name(sync_file),
>sync_status_str(dma_fence_get_status(sync_file->fence)));
>
> if (dma_fence_is_array(sync_file->fence)) {
> diff --git a/drivers/dma-buf/sync_file.c b/drivers/dma-buf/sync_file.c
> index c9eb4997cfcc..0d54de79ba76 100644
> --- a/drivers/dma-buf/sync_file.c
> +++ b/drivers/dma-buf/sync_file.c
> @@ -80,11 +80,6 @@ struct sync_file *sync_file_create(struct dma_fence *fence)
>
> sync_file->fence = dma_fence_get(fence);
>
> -   snprintf(sync_file->name, sizeof(sync_file->name), "%s-%s%llu-%d",
> -fence->ops->get_driver_name(fence),
> -fence->ops->get_timeline_name(fence), fence->context,
> -fence->seqno);
> -
> return sync_file;
>  }
>  EXPORT_SYMBOL(sync_file_create);
> @@ -129,6 +124,51 @@ struct dma_fence *sync_file_get_fence(int fd)
>  }
>  EXPORT_SYMBOL(sync_file_get_fence);
>
> +/**
> + * sync_file_get_name - get the name of the sync_file
> + * @sync_file: sync_file to get the fence from
> + *
> + * Each sync_file may have a name assigned either by the user (when merging
> + * sync_files together) or created from the fence it contains. However,
> + * construction of the name is deferred until first use.
> + *
> + * Returns: a string representing the name
> + */
> +char *sync_file_get_name(struct sync_file *sync_file)
> +{
> +   static DEFINE_SPINLOCK(name_lock);
> +
> +   if (!sync_file->user_name[0]) {
> +   char buf[sizeof(sync_file->user_name)];
> +   struct dma_fence *fence;
> +   int len;
> +
> +   rcu_read_lock();
> +   fence = sync_file->fence;
> +   len = scnprintf(buf, sizeof(buf), "%s-%s%llu-%d",
> +   fence->ops->get_driver_name(sync_file->fence),
> +   
> fence->ops->get_timeline_name(sync_file->fence),
> +   fence->context,
> +   fence->seqno);
> +
> +   /* This is mildly racy, so we stage the printf into a local
> +* buffer and do the copy with preempt disabled to trim the
> +* race down to a few cycles. To completely eliminate the
> +* race, we do the final assignment underneath a global
> +* spinlock. A global lock should be adequate here for this
> +* rare path (called from the middle of a user sw_sync status
> +* ioctl and from debugfs).
> +*/
> +   spin_lock(&name_lock);
> +   if (!sync_file->user_name[0])
> +   memcpy(sync_file->user_name, buf, len + 1);

A racing reader might get a truncated string here. Note that a racing
reader does not take the lock as soon as the first byte is visible.
Not sure what the name is used for, but with that code it is not
reliable.

Also, please zero-terminate the string... scnprintf() does not
guarantee that, if it follows posix.

> +   spin_unlock(&name_lock);
> +   rcu_read_unlock();
> +   }
> +
> +   return sync_file->user_name;
> +}
> +
>  static int sync_file_set_fence(struct sync_file *sync_file,
>struct dma_fence **fences, int num_fences)
>  {
> @@ -266,7 +306,7 @@ static struct sync_file *sync_file_merge(const char 
> *name, struct sync_file *a,
> goto err;
> }
>
> -   strlcpy(sync_file->name, name, sizeof(sync

Re: [PATCH v4] dma-buf/sync-file: Defer creation of sync_file->name

2017-05-15 Thread David Herrmann
Hey

On Mon, May 15, 2017 at 1:42 PM, Chris Wilson  wrote:
> On Mon, May 15, 2017 at 12:50:04PM +0200, David Herrmann wrote:
>> Hey
>>
>> On Mon, May 15, 2017 at 12:10 PM, Chris Wilson  
>> wrote:
>> > Constructing the name takes the majority of the time for allocating a
>> > sync_file to wrap a fence, and the name is very rarely used (only via
>> > the sync_file status user interface). To reduce the impact on the common
>> > path (that of creating sync_file to pass around), defer the construction
>> > of the name until it is first used.
>> >
>> > v2: Update kerneldoc (kbuild test robot)
>> > v3: sync_debug.c was peeking at the name
>> > v4: Comment upon the potential race between two users of
>> > sync_file_get_name() and claim that such a race is below the level of
>> > notice. However, to prevent any future nuisance, use a global spinlock
>> > to serialize the assignment of the name.
>> >
>> > Signed-off-by: Chris Wilson 
>> > Cc: Sumit Semwal 
>> > Cc: Gustavo Padovan 
>> > Cc: Daniel Vetter 
>> > ---
>> >  drivers/dma-buf/sync_debug.c |  3 ++-
>> >  drivers/dma-buf/sync_file.c  | 54 
>> > ++--
>> >  include/linux/sync_file.h|  5 ++--
>> >  3 files changed, 52 insertions(+), 10 deletions(-)
>> >
>> > diff --git a/drivers/dma-buf/sync_debug.c b/drivers/dma-buf/sync_debug.c
>> > index 4b1731ee7458..9a93f1085c63 100644
>> > --- a/drivers/dma-buf/sync_debug.c
>> > +++ b/drivers/dma-buf/sync_debug.c
>> > @@ -134,7 +134,8 @@ static void sync_print_sync_file(struct seq_file *s,
>> >  {
>> > int i;
>> >
>> > -   seq_printf(s, "[%p] %s: %s\n", sync_file, sync_file->name,
>> > +   seq_printf(s, "[%p] %s: %s\n", sync_file,
>> > +  sync_file_get_name(sync_file),
>> >
>> > sync_status_str(dma_fence_get_status(sync_file->fence)));
>> >
>> > if (dma_fence_is_array(sync_file->fence)) {
>> > diff --git a/drivers/dma-buf/sync_file.c b/drivers/dma-buf/sync_file.c
>> > index c9eb4997cfcc..0d54de79ba76 100644
>> > --- a/drivers/dma-buf/sync_file.c
>> > +++ b/drivers/dma-buf/sync_file.c
>> > @@ -80,11 +80,6 @@ struct sync_file *sync_file_create(struct dma_fence 
>> > *fence)
>> >
>> > sync_file->fence = dma_fence_get(fence);
>> >
>> > -   snprintf(sync_file->name, sizeof(sync_file->name), "%s-%s%llu-%d",
>> > -fence->ops->get_driver_name(fence),
>> > -fence->ops->get_timeline_name(fence), fence->context,
>> > -fence->seqno);
>> > -
>> > return sync_file;
>> >  }
>> >  EXPORT_SYMBOL(sync_file_create);
>> > @@ -129,6 +124,51 @@ struct dma_fence *sync_file_get_fence(int fd)
>> >  }
>> >  EXPORT_SYMBOL(sync_file_get_fence);
>> >
>> > +/**
>> > + * sync_file_get_name - get the name of the sync_file
>> > + * @sync_file: sync_file to get the fence from
>> > + *
>> > + * Each sync_file may have a name assigned either by the user (when 
>> > merging
>> > + * sync_files together) or created from the fence it contains. However,
>> > + * construction of the name is deferred until first use.
>> > + *
>> > + * Returns: a string representing the name
>> > + */
>> > +char *sync_file_get_name(struct sync_file *sync_file)
>> > +{
>> > +   static DEFINE_SPINLOCK(name_lock);
>> > +
>> > +   if (!sync_file->user_name[0]) {
>> > +   char buf[sizeof(sync_file->user_name)];
>> > +   struct dma_fence *fence;
>> > +   int len;
>> > +
>> > +   rcu_read_lock();
>> > +   fence = sync_file->fence;
>> > +   len = scnprintf(buf, sizeof(buf), "%s-%s%llu-%d",
>> > +   
>> > fence->ops->get_driver_name(sync_file->fence),
>> > +   
>> > fence->ops->get_timeline_name(sync_file->fence),
>> > +   fence->context,
>> > +   fence->seqno);
>> > +
>> > +   /* This is mildly racy, so we stage the printf into a local
>> > +* buffe

[PATCH 0/6] DRM Core Cleanups

2016-09-01 Thread David Herrmann
Hey

The remaining cleanup patches pending on dri-devel in one batch. Random cleanups
all over the place. Should all be straightforward.

Thanks
David

David Herrmann (6):
  drm: remove redundant drm_file->uid
  drm: use drm_file to tag vm-bos
  drm: rename drm_file.filp to drm_file.legacy_filp
  drm: provide management functions for drm_file
  drm: drop obsolete drm_core.h
  drm: cleanup drm_core_{init,exit}()

 drivers/gpu/drm/amd/amdgpu/amdgpu_ttm.c |   3 +-
 drivers/gpu/drm/ast/ast_ttm.c   |   3 +-
 drivers/gpu/drm/bochs/bochs_mm.c|   3 +-
 drivers/gpu/drm/cirrus/cirrus_ttm.c |   3 +-
 drivers/gpu/drm/drm_bufs.c  |   7 +-
 drivers/gpu/drm/drm_drv.c   | 191 ++--
 drivers/gpu/drm/drm_fops.c  | 133 ++
 drivers/gpu/drm/drm_gem.c   |   8 +-
 drivers/gpu/drm/drm_info.c  |   4 +-
 drivers/gpu/drm/drm_internal.h  |   7 ++
 drivers/gpu/drm/drm_ioc32.c |   1 -
 drivers/gpu/drm/drm_ioctl.c |   1 -
 drivers/gpu/drm/drm_sysfs.c |   8 +-
 drivers/gpu/drm/drm_vma_manager.c   |  40 +++
 drivers/gpu/drm/mgag200/mgag200_ttm.c   |   3 +-
 drivers/gpu/drm/nouveau/nouveau_bo.c|   3 +-
 drivers/gpu/drm/qxl/qxl_ttm.c   |   3 +-
 drivers/gpu/drm/radeon/radeon_ttm.c |   3 +-
 include/drm/drmP.h  |   3 +-
 include/drm/drm_core.h  |  34 --
 include/drm/drm_vma_manager.h   |  20 ++--
 21 files changed, 235 insertions(+), 246 deletions(-)
 delete mode 100644 include/drm/drm_core.h

-- 
2.9.3



[PATCH 1/6] drm: remove redundant drm_file->uid

2016-09-01 Thread David Herrmann
Each DRM file-context caches the EUID of the process that opened the file.
It is used exclusively for debugging purposes in /proc/dri/ and friends.

Note, however, that we can already fetch the EUID from
priv->pid->task->creds. The pointer-chasing will not hurt us, since it is
only about debugging, anyway.

Since we already are in an rcu-read-side, we can use __task_cred() rather
than task_cred_xxx().

Signed-off-by: David Herrmann 
---
 drivers/gpu/drm/drm_fops.c | 1 -
 drivers/gpu/drm/drm_info.c | 4 +++-
 include/drm/drmP.h | 1 -
 3 files changed, 3 insertions(+), 3 deletions(-)

diff --git a/drivers/gpu/drm/drm_fops.c b/drivers/gpu/drm/drm_fops.c
index 323c238..e9d66f5 100644
--- a/drivers/gpu/drm/drm_fops.c
+++ b/drivers/gpu/drm/drm_fops.c
@@ -199,7 +199,6 @@ static int drm_open_helper(struct file *filp, struct 
drm_minor *minor)

filp->private_data = priv;
priv->filp = filp;
-   priv->uid = current_euid();
priv->pid = get_pid(task_pid(current));
priv->minor = minor;

diff --git a/drivers/gpu/drm/drm_info.c b/drivers/gpu/drm/drm_info.c
index 9ae353f..1df2d33 100644
--- a/drivers/gpu/drm/drm_info.c
+++ b/drivers/gpu/drm/drm_info.c
@@ -80,6 +80,7 @@ int drm_clients_info(struct seq_file *m, void *data)
struct drm_info_node *node = (struct drm_info_node *) m->private;
struct drm_device *dev = node->minor->dev;
struct drm_file *priv;
+   kuid_t uid;

seq_printf(m,
   "%20s %5s %3s master a %5s %10s\n",
@@ -98,13 +99,14 @@ int drm_clients_info(struct seq_file *m, void *data)

rcu_read_lock(); /* locks pid_task()->comm */
task = pid_task(priv->pid, PIDTYPE_PID);
+   uid = task ? __task_cred(task)->euid : GLOBAL_ROOT_UID;
seq_printf(m, "%20s %5d %3d   %c%c %5d %10u\n",
   task ? task->comm : "",
   pid_vnr(priv->pid),
   priv->minor->index,
   drm_is_current_master(priv) ? 'y' : 'n',
   priv->authenticated ? 'y' : 'n',
-  from_kuid_munged(seq_user_ns(m), priv->uid),
+  from_kuid_munged(seq_user_ns(m), uid),
   priv->magic);
rcu_read_unlock();
}
diff --git a/include/drm/drmP.h b/include/drm/drmP.h
index d488a72..0f69f56 100644
--- a/include/drm/drmP.h
+++ b/include/drm/drmP.h
@@ -320,7 +320,6 @@ struct drm_file {
unsigned is_master:1;

struct pid *pid;
-   kuid_t uid;
drm_magic_t magic;
struct list_head lhead;
struct drm_minor *minor;
-- 
2.9.3



[PATCH 2/6] drm: use drm_file to tag vm-bos

2016-09-01 Thread David Herrmann
Rather than using "struct file*", use "struct drm_file*" as tag VM tag for
BOs. This will pave the way for "struct drm_file*" without any "struct
file*" back-pointer.

Signed-off-by: David Herrmann 
---
 drivers/gpu/drm/amd/amdgpu/amdgpu_ttm.c |  3 ++-
 drivers/gpu/drm/ast/ast_ttm.c   |  3 ++-
 drivers/gpu/drm/bochs/bochs_mm.c|  3 ++-
 drivers/gpu/drm/cirrus/cirrus_ttm.c |  3 ++-
 drivers/gpu/drm/drm_gem.c   |  8 +++
 drivers/gpu/drm/drm_vma_manager.c   | 40 -
 drivers/gpu/drm/mgag200/mgag200_ttm.c   |  3 ++-
 drivers/gpu/drm/nouveau/nouveau_bo.c|  3 ++-
 drivers/gpu/drm/qxl/qxl_ttm.c   |  3 ++-
 drivers/gpu/drm/radeon/radeon_ttm.c |  3 ++-
 include/drm/drm_vma_manager.h   | 20 +
 11 files changed, 51 insertions(+), 41 deletions(-)

diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_ttm.c 
b/drivers/gpu/drm/amd/amdgpu/amdgpu_ttm.c
index 9b61c8b..d975346 100644
--- a/drivers/gpu/drm/amd/amdgpu/amdgpu_ttm.c
+++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_ttm.c
@@ -225,7 +225,8 @@ static int amdgpu_verify_access(struct ttm_buffer_object 
*bo, struct file *filp)

if (amdgpu_ttm_tt_get_usermm(bo->ttm))
return -EPERM;
-   return drm_vma_node_verify_access(&rbo->gem_base.vma_node, filp);
+   return drm_vma_node_verify_access(&rbo->gem_base.vma_node,
+ filp->private_data);
 }

 static void amdgpu_move_null(struct ttm_buffer_object *bo,
diff --git a/drivers/gpu/drm/ast/ast_ttm.c b/drivers/gpu/drm/ast/ast_ttm.c
index b29a412..608df4c 100644
--- a/drivers/gpu/drm/ast/ast_ttm.c
+++ b/drivers/gpu/drm/ast/ast_ttm.c
@@ -150,7 +150,8 @@ static int ast_bo_verify_access(struct ttm_buffer_object 
*bo, struct file *filp)
 {
struct ast_bo *astbo = ast_bo(bo);

-   return drm_vma_node_verify_access(&astbo->gem.vma_node, filp);
+   return drm_vma_node_verify_access(&astbo->gem.vma_node,
+ filp->private_data);
 }

 static int ast_ttm_io_mem_reserve(struct ttm_bo_device *bdev,
diff --git a/drivers/gpu/drm/bochs/bochs_mm.c b/drivers/gpu/drm/bochs/bochs_mm.c
index 5c5638a..269cfca 100644
--- a/drivers/gpu/drm/bochs/bochs_mm.c
+++ b/drivers/gpu/drm/bochs/bochs_mm.c
@@ -128,7 +128,8 @@ static int bochs_bo_verify_access(struct ttm_buffer_object 
*bo,
 {
struct bochs_bo *bochsbo = bochs_bo(bo);

-   return drm_vma_node_verify_access(&bochsbo->gem.vma_node, filp);
+   return drm_vma_node_verify_access(&bochsbo->gem.vma_node,
+ filp->private_data);
 }

 static int bochs_ttm_io_mem_reserve(struct ttm_bo_device *bdev,
diff --git a/drivers/gpu/drm/cirrus/cirrus_ttm.c 
b/drivers/gpu/drm/cirrus/cirrus_ttm.c
index 1cc9ee6..bb2438d 100644
--- a/drivers/gpu/drm/cirrus/cirrus_ttm.c
+++ b/drivers/gpu/drm/cirrus/cirrus_ttm.c
@@ -150,7 +150,8 @@ static int cirrus_bo_verify_access(struct ttm_buffer_object 
*bo, struct file *fi
 {
struct cirrus_bo *cirrusbo = cirrus_bo(bo);

-   return drm_vma_node_verify_access(&cirrusbo->gem.vma_node, filp);
+   return drm_vma_node_verify_access(&cirrusbo->gem.vma_node,
+ filp->private_data);
 }

 static int cirrus_ttm_io_mem_reserve(struct ttm_bo_device *bdev,
diff --git a/drivers/gpu/drm/drm_gem.c b/drivers/gpu/drm/drm_gem.c
index 9134ae1..465bacd 100644
--- a/drivers/gpu/drm/drm_gem.c
+++ b/drivers/gpu/drm/drm_gem.c
@@ -257,7 +257,7 @@ drm_gem_object_release_handle(int id, void *ptr, void *data)

if (drm_core_check_feature(dev, DRIVER_PRIME))
drm_gem_remove_prime_handles(obj, file_priv);
-   drm_vma_node_revoke(&obj->vma_node, file_priv->filp);
+   drm_vma_node_revoke(&obj->vma_node, file_priv);

if (dev->driver->gem_close_object)
dev->driver->gem_close_object(obj, file_priv);
@@ -372,7 +372,7 @@ drm_gem_handle_create_tail(struct drm_file *file_priv,

handle = ret;

-   ret = drm_vma_node_allow(&obj->vma_node, file_priv->filp);
+   ret = drm_vma_node_allow(&obj->vma_node, file_priv);
if (ret)
goto err_remove;

@@ -386,7 +386,7 @@ drm_gem_handle_create_tail(struct drm_file *file_priv,
return 0;

 err_revoke:
-   drm_vma_node_revoke(&obj->vma_node, file_priv->filp);
+   drm_vma_node_revoke(&obj->vma_node, file_priv);
 err_remove:
spin_lock(&file_priv->table_lock);
idr_remove(&file_priv->object_idr, handle);
@@ -991,7 +991,7 @@ int drm_gem_mmap(struct file *filp, struct vm_area_struct 
*vma)
if (!obj)
return -EINVAL;

-   if (!drm_vma_node_is_allowed(node, filp)) {
+   if (!drm_vma_node_is_allowed(node, priv)) {
drm_gem_o

[PATCH 3/6] drm: rename drm_file.filp to drm_file.legacy_filp

2016-09-01 Thread David Herrmann
We don't want anyone but legacy DRM1 code to use drm_file.filp. Especially
for in-kernel contexts, this might be set to NULL, so lets make sure
no-one accesses it, ever.

Signed-off-by: David Herrmann 
---
 drivers/gpu/drm/drm_bufs.c | 7 ---
 drivers/gpu/drm/drm_fops.c | 2 +-
 include/drm/drmP.h | 2 +-
 3 files changed, 6 insertions(+), 5 deletions(-)

diff --git a/drivers/gpu/drm/drm_bufs.c b/drivers/gpu/drm/drm_bufs.c
index c3a12cd..d2803de 100644
--- a/drivers/gpu/drm/drm_bufs.c
+++ b/drivers/gpu/drm/drm_bufs.c
@@ -1456,7 +1456,7 @@ int drm_legacy_mapbufs(struct drm_device *dev, void *data,
if (!drm_core_check_feature(dev, DRIVER_HAVE_DMA))
return -EINVAL;

-   if (!dma)
+   if (!dma || !file_priv->legacy_filp)
return -EINVAL;

spin_lock(&dev->buf_lock);
@@ -1478,12 +1478,13 @@ int drm_legacy_mapbufs(struct drm_device *dev, void 
*data,
retcode = -EINVAL;
goto done;
}
-   virtual = vm_mmap(file_priv->filp, 0, map->size,
+   virtual = vm_mmap(file_priv->legacy_filp, 0, map->size,
  PROT_READ | PROT_WRITE,
  MAP_SHARED,
  token);
} else {
-   virtual = vm_mmap(file_priv->filp, 0, dma->byte_count,
+   virtual = vm_mmap(file_priv->legacy_filp, 0,
+ dma->byte_count,
  PROT_READ | PROT_WRITE,
  MAP_SHARED, 0);
}
diff --git a/drivers/gpu/drm/drm_fops.c b/drivers/gpu/drm/drm_fops.c
index e9d66f5..69ef23c 100644
--- a/drivers/gpu/drm/drm_fops.c
+++ b/drivers/gpu/drm/drm_fops.c
@@ -198,7 +198,7 @@ static int drm_open_helper(struct file *filp, struct 
drm_minor *minor)
return -ENOMEM;

filp->private_data = priv;
-   priv->filp = filp;
+   priv->legacy_filp = filp;
priv->pid = get_pid(task_pid(current));
priv->minor = minor;

diff --git a/include/drm/drmP.h b/include/drm/drmP.h
index 0f69f56..2197ab1 100644
--- a/include/drm/drmP.h
+++ b/include/drm/drmP.h
@@ -330,7 +330,7 @@ struct drm_file {
/** Lock for synchronization of access to object_idr. */
spinlock_t table_lock;

-   struct file *filp;
+   struct file *legacy_filp; /* might be NULL! */
void *driver_priv;

struct drm_master *master; /* master this node is currently associated 
with
-- 
2.9.3



[PATCH 4/6] drm: provide management functions for drm_file

2016-09-01 Thread David Herrmann
Rather than doing drm_file allocation/destruction right in the fops, lets
provide separate helpers. This decouples drm_file management from the
still-mandatory drm-fops. It prepares for use of drm_file without the
fops, both by possible separate fops implementations and APIs (not that I
am aware of any such plans), and more importantly from in-kernel use where
no real file is available.

Signed-off-by: David Herrmann 
---
 drivers/gpu/drm/drm_drv.c  | 135 +
 drivers/gpu/drm/drm_fops.c | 132 +++-
 drivers/gpu/drm/drm_internal.h |   4 ++
 3 files changed, 147 insertions(+), 124 deletions(-)

diff --git a/drivers/gpu/drm/drm_drv.c b/drivers/gpu/drm/drm_drv.c
index 57ce973..9ab0016 100644
--- a/drivers/gpu/drm/drm_drv.c
+++ b/drivers/gpu/drm/drm_drv.c
@@ -95,6 +95,141 @@ void drm_ut_debug_printk(const char *function_name, const 
char *format, ...)
 }
 EXPORT_SYMBOL(drm_ut_debug_printk);

+/**
+ * drm_file_alloc - allocate file context
+ * @minor: minor to allocate on
+ *
+ * This allocates a new DRM file context. It is not linked into any context and
+ * can be used by the caller freely. Note that the context keeps a pointer to
+ * @minor, so it must be freed before @minor is.
+ *
+ * The legacy paths might require the drm_global_mutex to be held.
+ *
+ * RETURNS:
+ * Pointer to newly allocated context, ERR_PTR on failure.
+ */
+struct drm_file *drm_file_alloc(struct drm_minor *minor)
+{
+   struct drm_device *dev = minor->dev;
+   struct drm_file *file;
+   int ret;
+
+   file = kzalloc(sizeof(*file), GFP_KERNEL);
+   if (!file)
+   return ERR_PTR(-ENOMEM);
+
+   file->pid = get_pid(task_pid(current));
+   file->minor = minor;
+   file->authenticated = capable(CAP_SYS_ADMIN); /* legacy compat */
+   INIT_LIST_HEAD(&file->lhead);
+   INIT_LIST_HEAD(&file->fbs);
+   mutex_init(&file->fbs_lock);
+   INIT_LIST_HEAD(&file->blobs);
+   INIT_LIST_HEAD(&file->pending_event_list);
+   INIT_LIST_HEAD(&file->event_list);
+   init_waitqueue_head(&file->event_wait);
+   file->event_space = 4096; /* set aside 4k for event buffer */
+   mutex_init(&file->event_read_lock);
+
+   if (drm_core_check_feature(dev, DRIVER_GEM))
+   drm_gem_open(dev, file);
+   if (drm_core_check_feature(dev, DRIVER_PRIME))
+   drm_prime_init_file_private(&file->prime);
+
+   if (dev->driver->open) {
+   ret = dev->driver->open(dev, file);
+   if (ret < 0)
+   goto out_prime_destroy;
+   }
+
+   if (drm_is_primary_client(file)) {
+   ret = drm_master_open(file);
+   if (ret)
+   goto out_close;
+   }
+
+   return file;
+
+out_close:
+   if (dev->driver->postclose)
+   dev->driver->postclose(dev, file);
+out_prime_destroy:
+   if (drm_core_check_feature(dev, DRIVER_PRIME))
+   drm_prime_destroy_file_private(&file->prime);
+   if (drm_core_check_feature(dev, DRIVER_GEM))
+   drm_gem_release(dev, file);
+   put_pid(file->pid);
+   kfree(file);
+   return ERR_PTR(ret);
+}
+
+/**
+ * drm_file_free - free file context
+ * @file: context to free, or NULL
+ *
+ * This destroys and deallocates a DRM file context previously allocated via
+ * drm_file_alloc(). The caller must make sure to unlink it from any contexts
+ * before calling this.
+ *
+ * The legacy paths might require the drm_global_mutex to be held.
+ *
+ * If NULL is passed, this is a no-op.
+ *
+ * RETURNS:
+ * 0 on success, or error code on failure.
+ */
+void drm_file_free(struct drm_file *file)
+{
+   struct drm_pending_event *e;
+   struct drm_device *dev;
+
+   if (!file)
+   return;
+
+   dev = file->minor->dev;
+
+   if (dev->driver->preclose)
+   dev->driver->preclose(dev, file);
+   if (!drm_core_check_feature(dev, DRIVER_MODESET))
+   drm_legacy_lock_release(dev, file->legacy_filp);
+   if (drm_core_check_feature(dev, DRIVER_HAVE_DMA))
+   drm_legacy_reclaim_buffers(dev, file);
+
+   spin_lock_irq(&dev->event_lock);
+   while ((e = list_first_entry_or_null(&file->pending_event_list,
+struct drm_pending_event,
+pending_link))) {
+   list_del(&e->pending_link);
+   e->file_priv = NULL;
+   }
+   while ((e = list_first_entry_or_null(&file->event_list,
+struct drm_pending_event, link))) {
+   list_del(&e->link);
+   kfree(e);
+   }
+   spin_u

[PATCH 5/6] drm: drop obsolete drm_core.h

2016-09-01 Thread David Herrmann
The drm_core.h header contains a set of constants meant to be used
throughout DRM. However, as it turns out, they're each used just once and
don't bring any benefit. They're also grossly mis-named and lack
name-spacing. This patch inlines them, or moves them into drm_internal.h
as appropriate:

 - CORE_AUTHOR and CORE_DESC are inlined into corresponding MODULE_*()
   macros. It's just confusing having to follow 2 pointers when trying to
   find the definition of these fields. Grep'ping for MODULE_AUTHOR()
   should reveal the full information, if there's no strong reason not to.

 - CORE_NAME, CORE_DATE, CORE_MAJOR, CORE_MINOR, and CORE_PATCHLEVEL are
   inlined into the sysfs 'version' attribute. They're stripped
   everywhere else (which is just some printk() statements). CORE_NAME
   just doesn't make *any* sense, as we hard-code it in many places,
   anyway. The other constants are outdated and just serve
   binary-compatibility purposes. Hence, inline them in 'version' sysfs
   attribute (we might even try dropping it..).

 - DRM_IF_MAJOR and DRM_IF_MINOR are moved into drm_internal.h as they're
   only used by the global ioctl handlers. Furthermore, versioning
   interfaces breaks backports and as such is deprecated, anyway. We just
   keep them for historic reasons. I doubt anyone will ever modify them
   again.

Signed-off-by: David Herrmann 
---
 drivers/gpu/drm/drm_drv.c  |  8 +++-
 drivers/gpu/drm/drm_internal.h |  3 +++
 drivers/gpu/drm/drm_ioc32.c|  1 -
 drivers/gpu/drm/drm_ioctl.c|  1 -
 drivers/gpu/drm/drm_sysfs.c|  8 +---
 include/drm/drm_core.h | 34 --
 6 files changed, 7 insertions(+), 48 deletions(-)
 delete mode 100644 include/drm/drm_core.h

diff --git a/drivers/gpu/drm/drm_drv.c b/drivers/gpu/drm/drm_drv.c
index 9ab0016..d771453 100644
--- a/drivers/gpu/drm/drm_drv.c
+++ b/drivers/gpu/drm/drm_drv.c
@@ -33,7 +33,6 @@
 #include 
 #include 
 #include 
-#include 
 #include "drm_crtc_internal.h"
 #include "drm_legacy.h"
 #include "drm_internal.h"
@@ -46,8 +45,8 @@
 unsigned int drm_debug = 0;
 EXPORT_SYMBOL(drm_debug);

-MODULE_AUTHOR(CORE_AUTHOR);
-MODULE_DESCRIPTION(CORE_DESC);
+MODULE_AUTHOR("Gareth Hughes, Leif Delgass, José Fonseca, Jon Smirl");
+MODULE_DESCRIPTION("DRM shared core routines");
 MODULE_LICENSE("GPL and additional rights");
 MODULE_PARM_DESC(debug, "Enable debug output, where each bit enables a debug 
category.\n"
 "\t\tBit 0 (0x01) will enable CORE messages (drm core code)\n"
@@ -966,8 +965,7 @@ static int __init drm_core_init(void)
goto err_p3;
}

-   DRM_INFO("Initialized %s %d.%d.%d %s\n",
-CORE_NAME, CORE_MAJOR, CORE_MINOR, CORE_PATCHLEVEL, CORE_DATE);
+   DRM_INFO("Initialized\n");
return 0;
 err_p3:
drm_sysfs_destroy();
diff --git a/drivers/gpu/drm/drm_internal.h b/drivers/gpu/drm/drm_internal.h
index 9b66cc4..3d6a587 100644
--- a/drivers/gpu/drm/drm_internal.h
+++ b/drivers/gpu/drm/drm_internal.h
@@ -21,6 +21,9 @@
  * OTHER DEALINGS IN THE SOFTWARE.
  */

+#define DRM_IF_MAJOR 1
+#define DRM_IF_MINOR 4
+
 /* drm_irq.c */
 extern unsigned int drm_timestamp_monotonic;

diff --git a/drivers/gpu/drm/drm_ioc32.c b/drivers/gpu/drm/drm_ioc32.c
index 57676f8..2795d6a 100644
--- a/drivers/gpu/drm/drm_ioc32.c
+++ b/drivers/gpu/drm/drm_ioc32.c
@@ -32,7 +32,6 @@
 #include 

 #include 
-#include 

 #define DRM_IOCTL_VERSION32DRM_IOWR(0x00, drm_version32_t)
 #define DRM_IOCTL_GET_UNIQUE32 DRM_IOWR(0x01, drm_unique32_t)
diff --git a/drivers/gpu/drm/drm_ioctl.c b/drivers/gpu/drm/drm_ioctl.c
index bc5c65e..845390f 100644
--- a/drivers/gpu/drm/drm_ioctl.c
+++ b/drivers/gpu/drm/drm_ioctl.c
@@ -29,7 +29,6 @@
  */

 #include 
-#include 
 #include 
 #include "drm_legacy.h"
 #include "drm_internal.h"
diff --git a/drivers/gpu/drm/drm_sysfs.c b/drivers/gpu/drm/drm_sysfs.c
index 32dd821..9a37196 100644
--- a/drivers/gpu/drm/drm_sysfs.c
+++ b/drivers/gpu/drm/drm_sysfs.c
@@ -19,7 +19,6 @@
 #include 

 #include 
-#include 
 #include 
 #include "drm_internal.h"

@@ -37,12 +36,7 @@ static char *drm_devnode(struct device *dev, umode_t *mode)
return kasprintf(GFP_KERNEL, "dri/%s", dev_name(dev));
 }

-static CLASS_ATTR_STRING(version, S_IRUGO,
-   CORE_NAME " "
-   __stringify(CORE_MAJOR) "."
-   __stringify(CORE_MINOR) "."
-   __stringify(CORE_PATCHLEVEL) " "
-   CORE_DATE);
+static CLASS_ATTR_STRING(version, S_IRUGO, "drm 1.1.0 20060810");

 /**
  * drm_sysfs_init - initialize sysfs helpers
diff --git a/include/drm/drm_core.h b/include/drm/drm_core.h
deleted file mode 100644
index 4e75238..000
--- a/include/drm/drm_cor

[PATCH 6/6] drm: cleanup drm_core_{init,exit}()

2016-09-01 Thread David Herrmann
Various cleanups to the DRM core initialization and exit handlers:

 - Register chrdev last: Once register_chrdev() returns, open() will
   succeed on the given chrdevs. This is usually not an issue, as no
   chardevs are registered, yet. However, nodes can be created by
   user-space via mknod(2), even though such major/minor combinations are
   unknown to the kernel. Avoid calling into drm_stub_open() in those
   cases.
   Again, drm_stub_open() would just bail out as the inode is unknown,
   but it's really non-obvious if you hack on drm_stub_open().

 - Unify error-paths into just one label. All the error-path helpers can
   be called even though the constructors were not called yet, or failed.
   Hence, just call all cleanups unconditionally.

 - Call into drm_global_release(). This is a no-op, but provides
   debugging helpers in case there're GLOBALS left on module unload. This
   function was unused until now.

 - Use DRM_ERROR() instead of printk(), and also print the error-code on
   failure (even if it is static!).

 - Don't throw away error-codes of register_chrdev()!

 - Don't hardcode -1 as errno. This is just plain wrong.

 - Order exit-handlers in the exact reverse order of initialization
   (except if the order actually matters for syncing-reasons, which is
   not the case here, though).

v2:
 - Call drm_core_exit() directly from the init-error-handler. Requires to
   drop __exit annotation, though.

Signed-off-by: David Herrmann 
---
 drivers/gpu/drm/drm_drv.c | 48 ++-
 1 file changed, 22 insertions(+), 26 deletions(-)

diff --git a/drivers/gpu/drm/drm_drv.c b/drivers/gpu/drm/drm_drv.c
index d771453..0773547 100644
--- a/drivers/gpu/drm/drm_drv.c
+++ b/drivers/gpu/drm/drm_drv.c
@@ -941,52 +941,48 @@ static const struct file_operations drm_stub_fops = {
.llseek = noop_llseek,
 };

+static void drm_core_exit(void)
+{
+   unregister_chrdev(DRM_MAJOR, "drm");
+   debugfs_remove(drm_debugfs_root);
+   drm_sysfs_destroy();
+   idr_destroy(&drm_minors_idr);
+   drm_connector_ida_destroy();
+   drm_global_release();
+}
+
 static int __init drm_core_init(void)
 {
-   int ret = -ENOMEM;
+   int ret;

drm_global_init();
drm_connector_ida_init();
idr_init(&drm_minors_idr);

-   if (register_chrdev(DRM_MAJOR, "drm", &drm_stub_fops))
-   goto err_p1;
-
ret = drm_sysfs_init();
if (ret < 0) {
-   printk(KERN_ERR "DRM: Error creating drm class.\n");
-   goto err_p2;
+   DRM_ERROR("Cannot create DRM class: %d\n", ret);
+   goto error;
}

drm_debugfs_root = debugfs_create_dir("dri", NULL);
if (!drm_debugfs_root) {
-   DRM_ERROR("Cannot create /sys/kernel/debug/dri\n");
-   ret = -1;
-   goto err_p3;
+   ret = -ENOMEM;
+   DRM_ERROR("Cannot create debugfs-root: %d\n", ret);
+   goto error;
}

+   ret = register_chrdev(DRM_MAJOR, "drm", &drm_stub_fops);
+   if (ret < 0)
+   goto error;
+
DRM_INFO("Initialized\n");
return 0;
-err_p3:
-   drm_sysfs_destroy();
-err_p2:
-   unregister_chrdev(DRM_MAJOR, "drm");

-   idr_destroy(&drm_minors_idr);
-err_p1:
+error:
+   drm_core_exit();
return ret;
 }

-static void __exit drm_core_exit(void)
-{
-   debugfs_remove(drm_debugfs_root);
-   drm_sysfs_destroy();
-
-   unregister_chrdev(DRM_MAJOR, "drm");
-
-   drm_connector_ida_destroy();
-   idr_destroy(&drm_minors_idr);
-}
-
 module_init(drm_core_init);
 module_exit(drm_core_exit);
-- 
2.9.3



[PATCH v4 3/5] drm: add SimpleDRM driver

2016-09-02 Thread David Herrmann
Hey

On Mon, Aug 22, 2016 at 10:25 PM, Noralf Trønnes  wrote:
> The SimpleDRM driver binds to simple-framebuffer devices and provides a
> DRM/KMS API. It provides only a single CRTC+encoder+connector combination
> plus one initial mode.
>
> Userspace can create dumb-buffers which can be blit into the real
> framebuffer similar to UDL. No access to the real framebuffer is allowed
> (compared to earlier version of this driver) to avoid security issues.
> Furthermore, this way we can support arbitrary modes as long as we have a
> conversion-helper.
>
> The driver was originally written by David Herrmann in 2014.
> My main contribution is to make use of drm_simple_kms_helper and
> rework the probe path to avoid use of the deprecated drm_platform_init()
> and drm_driver.{load,unload}().
> Additions have also been made for later changes to the Device Tree binding
> document, like support for clocks, regulators and having the node under
> /chosen. This code was lifted verbatim from simplefb.c.
>
> Cc: dh.herrmann at gmail.com
> Cc: libv at skynet.be
> Signed-off-by: Noralf Trønnes 
> ---
>
> Changes from version 3:
> - Reworked gem code to match udl
> - Dropped PRIME support
> - Dropped dirty_info_property, it's gone
> - Don't use drm_device.platformdev it's deprecated
> - Remove struct sdrm_device #ifdef's
> - Split out sdrm_fb_init() from sdrm_fb_create(), needed by fbdev code
> - Simplify drm_clip validation by extending the check in
>   sdrm_dirty() and drop the one in sdrm_blit()
> - Removed sdrm_dirty_all_unlocked() which was unused.
>
> Changes from version 2:
> - Remove superfluos module.h includes
> - Move includes from header to source files
> - Set plane.fb before flushing in pipe update, or else the previous one
>   gets flushed
> - Added check for vblank event in sdrm_display_pipe_update()
>
> Changes from version 1:
> - Move platform_set_drvdata() before drm_dev_register()
> - Remove drm_legacy_mmap() call.
> - Set mode_config.{min,max}_{width,height} to the actual dimensions
>   of the native framebuffer
> - Remove plane positioning since it won't work with the simple display pipe,
>   meaning sdrm_display_pipe_check() isn't necessary either
> - Support the additions to the Device Tree binding document, including
>   clocks, regulators and having the node under /chosen
>
> Changes from previous version:
> - Remove FB_SIMPLE=n dependency to avoid kconfig recursive error
> - Changed module name to match kconfig help text: sdrm -> simpledrm
> - Use drm_simple_display_pipe
> - Replace deprecated drm_platform_init()
> - sdrm_dumb_create(): drm_gem_object_unreference() -> *_unlocked()
> - sdrm_dumb_map_offset(): drm_gem_object_lookup() remove drm_device parameter
> - sdrm_drm_mmap() changes:
>   Remove struct_mutex locking
>   Add drm_vma_offset_{lock,unlock}_lookup()
>   drm_mmap() -> drm_legacy_mmap()
> - dma_buf_begin_cpu_access() doesn't require start and length anymore
> - Use drm_cvt_mode() instead of open coding a mode
> - Fix format conversion. In the intermediate step, store the 8/6/5 bit color
>   value in the upper part of the 16-bit color variable, not the lower.
> - Support clips == NULL in sdrm_dirty()
> - Set mode_config.preferred_depth
> - Attach mode_config.dirty_info_property to connector
>
>  drivers/gpu/drm/Kconfig  |   2 +
>  drivers/gpu/drm/Makefile |   1 +
>  drivers/gpu/drm/simpledrm/Kconfig|  19 +
>  drivers/gpu/drm/simpledrm/Makefile   |   4 +
>  drivers/gpu/drm/simpledrm/simpledrm.h|  86 +
>  drivers/gpu/drm/simpledrm/simpledrm_damage.c | 235 
>  drivers/gpu/drm/simpledrm/simpledrm_drv.c| 543 
> +++
>  drivers/gpu/drm/simpledrm/simpledrm_gem.c| 202 ++
>  drivers/gpu/drm/simpledrm/simpledrm_kms.c| 234 
>  9 files changed, 1326 insertions(+)
>  create mode 100644 drivers/gpu/drm/simpledrm/Kconfig
>  create mode 100644 drivers/gpu/drm/simpledrm/Makefile
>  create mode 100644 drivers/gpu/drm/simpledrm/simpledrm.h
>  create mode 100644 drivers/gpu/drm/simpledrm/simpledrm_damage.c
>  create mode 100644 drivers/gpu/drm/simpledrm/simpledrm_drv.c
>  create mode 100644 drivers/gpu/drm/simpledrm/simpledrm_gem.c
>  create mode 100644 drivers/gpu/drm/simpledrm/simpledrm_kms.c
>
> diff --git a/drivers/gpu/drm/Kconfig b/drivers/gpu/drm/Kconfig
> index fc35731..a54cc8d 100644
> --- a/drivers/gpu/drm/Kconfig
> +++ b/drivers/gpu/drm/Kconfig
> @@ -290,3 +290,5 @@ source "drivers/gpu/drm/arc/Kconfig"
>  source "drivers/gpu/drm/hisilicon/Kconfig"
>
>  source "drivers/gpu/drm/mediatek/Kconfi

[PATCH v5 0/7] drm: add simpledrm driver

2016-09-02 Thread David Herrmann
Hey

On request of Noralf, I picked up the patches and prepared v5. Works fine with
Xorg, if configured according to:
https://lists.freedesktop.org/archives/dri-devel/2014-January/052777.html
If anyone knows how to make Xorg pick it up dynamically without such a static
configuration, please let me know.

Thanks
David

David Herrmann (7):
  x86/sysfb: add support for 64bit EFI lfb_base
  x86/sysfb: fix lfb_size calculation
  of/platform: expose of_platform_device_destroy()
  video: add generic framebuffer eviction
  drm: switch to sysfb_evict_conflicts()
  drm: add SimpleDRM driver
  drm/simpledrm: add fbdev fallback support

 MAINTAINERS  |   6 +
 arch/x86/kernel/sysfb_simplefb.c |  39 ++-
 drivers/gpu/drm/Kconfig  |   3 +
 drivers/gpu/drm/Makefile |   1 +
 drivers/gpu/drm/amd/amdgpu/amdgpu_drv.c  |  24 +-
 drivers/gpu/drm/bochs/bochs_drv.c|  19 +-
 drivers/gpu/drm/i915/i915_drv.c  |  73 +---
 drivers/gpu/drm/mgag200/mgag200_drv.c|  27 +-
 drivers/gpu/drm/mgag200/mgag200_main.c   |   9 -
 drivers/gpu/drm/nouveau/nouveau_drm.c|  33 +-
 drivers/gpu/drm/radeon/radeon_drv.c  |  24 +-
 drivers/gpu/drm/simpledrm/Kconfig|  19 ++
 drivers/gpu/drm/simpledrm/Makefile   |   9 +
 drivers/gpu/drm/simpledrm/simpledrm.h|  91 +
 drivers/gpu/drm/simpledrm/simpledrm_damage.c | 194 +++
 drivers/gpu/drm/simpledrm/simpledrm_drv.c| 477 +++
 drivers/gpu/drm/simpledrm/simpledrm_fbdev.c  | 143 
 drivers/gpu/drm/simpledrm/simpledrm_gem.c| 109 ++
 drivers/gpu/drm/simpledrm/simpledrm_kms.c| 270 +++
 drivers/gpu/drm/simpledrm/simpledrm_of.c | 265 +++
 drivers/gpu/drm/sun4i/sun4i_drv.c|  24 +-
 drivers/gpu/drm/vc4/vc4_drv.c|  25 +-
 drivers/gpu/drm/virtio/virtgpu_drm_bus.c |  24 +-
 drivers/of/platform.c|  35 +-
 drivers/video/Kconfig|   4 +
 drivers/video/Makefile   |   1 +
 drivers/video/sysfb.c| 327 ++
 include/linux/of_platform.h  |   1 +
 include/linux/sysfb.h|  34 ++
 29 files changed, 2054 insertions(+), 256 deletions(-)
 create mode 100644 drivers/gpu/drm/simpledrm/Kconfig
 create mode 100644 drivers/gpu/drm/simpledrm/Makefile
 create mode 100644 drivers/gpu/drm/simpledrm/simpledrm.h
 create mode 100644 drivers/gpu/drm/simpledrm/simpledrm_damage.c
 create mode 100644 drivers/gpu/drm/simpledrm/simpledrm_drv.c
 create mode 100644 drivers/gpu/drm/simpledrm/simpledrm_fbdev.c
 create mode 100644 drivers/gpu/drm/simpledrm/simpledrm_gem.c
 create mode 100644 drivers/gpu/drm/simpledrm/simpledrm_kms.c
 create mode 100644 drivers/gpu/drm/simpledrm/simpledrm_of.c
 create mode 100644 drivers/video/sysfb.c
 create mode 100644 include/linux/sysfb.h

-- 
2.9.3



[PATCH v5 1/7] x86/sysfb: add support for 64bit EFI lfb_base

2016-09-02 Thread David Herrmann
The screen_info object was extended to support 64bit lfb_base addresses
in:

commit ae2ee627dc87a70910de91b791b3cd0e9c6facdd
Author: Matt Fleming 
Date:   Tue Aug 25 16:32:55 2015 +0100

efifb: Add support for 64-bit frame buffer addresses

However, the x86 simple-framebuffer setup code never made use of it. Fix
it to properly assemble and verify the lfb_base before advertising
simple-framebuffer devices.

In particular, this means if VIDEO_CAPABILITY_64BIT_BASE is set, the
screen_info->ext_lfb_base field will contain the upper 32bit of the
actual lfb_base. Make sure the address is not 0 (i.e., unset), as well as
does not overflow the physical address type.

Signed-off-by: David Herrmann 
---
 arch/x86/kernel/sysfb_simplefb.c | 18 --
 1 file changed, 16 insertions(+), 2 deletions(-)

diff --git a/arch/x86/kernel/sysfb_simplefb.c b/arch/x86/kernel/sysfb_simplefb.c
index 764a29f..35b8641 100644
--- a/arch/x86/kernel/sysfb_simplefb.c
+++ b/arch/x86/kernel/sysfb_simplefb.c
@@ -67,6 +67,20 @@ __init int create_simplefb(const struct screen_info *si,
struct platform_device *pd;
struct resource res;
unsigned long len;
+   u64 base;
+
+   /*
+* If the 64BIT_BASE capability is set, ext_lfb_base will contain the
+* upper half of the base address. Assemble the address, then make sure
+* it is valid and we can actually access it.
+*/
+   base = si->lfb_base;
+   if (si->capabilities & VIDEO_CAPABILITY_64BIT_BASE)
+   base |= (u64)si->ext_lfb_base << 32;
+   if (!base || (u64)(resource_size_t)base != base) {
+   printk(KERN_DEBUG "sysfb: inaccessible VRAM base\n");
+   return -EINVAL;
+   }

/* don't use lfb_size as it may contain the whole VMEM instead of only
 * the part that is occupied by the framebuffer */
@@ -81,8 +95,8 @@ __init int create_simplefb(const struct screen_info *si,
memset(&res, 0, sizeof(res));
res.flags = IORESOURCE_MEM | IORESOURCE_BUSY;
res.name = simplefb_resname;
-   res.start = si->lfb_base;
-   res.end = si->lfb_base + len - 1;
+   res.start = base;
+   res.end = res.start + len - 1;
if (res.end <= res.start)
return -EINVAL;

-- 
2.9.3



[PATCH v5 2/7] x86/sysfb: fix lfb_size calculation

2016-09-02 Thread David Herrmann
The screen_info.lfb_size field is shifted by 16 bits *only* in case of
VBE. This has historical reasons since VBE advertised it similarly.
However, in case of EFI framebuffers, the size is no longer shifted. Fix
the x86 simple-framebuffer setup code to use the correct size in the
non-VBE case.

While at it, avoid variable abbreviations and rename 'len' to 'length',
and use the correct types matching the screen_info definition.

Signed-off-by: David Herrmann 
---
 arch/x86/kernel/sysfb_simplefb.c | 25 +
 1 file changed, 17 insertions(+), 8 deletions(-)

diff --git a/arch/x86/kernel/sysfb_simplefb.c b/arch/x86/kernel/sysfb_simplefb.c
index 35b8641..85195d4 100644
--- a/arch/x86/kernel/sysfb_simplefb.c
+++ b/arch/x86/kernel/sysfb_simplefb.c
@@ -66,8 +66,8 @@ __init int create_simplefb(const struct screen_info *si,
 {
struct platform_device *pd;
struct resource res;
-   unsigned long len;
-   u64 base;
+   u64 base, size;
+   u32 length;

/*
 * If the 64BIT_BASE capability is set, ext_lfb_base will contain the
@@ -82,11 +82,20 @@ __init int create_simplefb(const struct screen_info *si,
return -EINVAL;
}

-   /* don't use lfb_size as it may contain the whole VMEM instead of only
-* the part that is occupied by the framebuffer */
-   len = mode->height * mode->stride;
-   len = PAGE_ALIGN(len);
-   if (len > (u64)si->lfb_size << 16) {
+   /*
+* Don't use lfb_size as IORESOURCE size, since it may contain the
+* entire VMEM, and thus require huge mappings. Use just the part we
+* need, that is, the part where the framebuffer is located. But verify
+* that it does not exceed the advertised VMEM.
+* Note that in case of VBE, the lfb_size is shifted by 16 bits for
+* historical reasons.
+*/
+   size = si->lfb_size;
+   if (si->orig_video_isVGA == VIDEO_TYPE_VLFB)
+   size <<= 16;
+   length = mode->height * mode->stride;
+   length = PAGE_ALIGN(length);
+   if (length > size) {
printk(KERN_WARNING "sysfb: VRAM smaller than advertised\n");
return -EINVAL;
}
@@ -96,7 +105,7 @@ __init int create_simplefb(const struct screen_info *si,
res.flags = IORESOURCE_MEM | IORESOURCE_BUSY;
res.name = simplefb_resname;
res.start = base;
-   res.end = res.start + len - 1;
+   res.end = res.start + length - 1;
if (res.end <= res.start)
return -EINVAL;

-- 
2.9.3



[PATCH v5 3/7] of/platform: expose of_platform_device_destroy()

2016-09-02 Thread David Herrmann
We already expose of_platform_device_create(), but give the caller no
chance to revert its effect. Make sure we also provide the counterpart
of_platform_device_destroy().

This requires a small refactoring, since so far the internal destructor
is used as iterator to for_each_device(), but we don't want to expose it
with the "void *data" parameter. So provide
of_platform_device_depopulate() as new iterator, which calls into
of_platform_device_destroy().

While at it, drop the unused 'children_left' argument by
of_platform_notify(). It is a left-over that somehow was never removed.

Signed-off-by: David Herrmann 
---
 drivers/of/platform.c   | 35 ++-
 include/linux/of_platform.h |  1 +
 2 files changed, 27 insertions(+), 9 deletions(-)

diff --git a/drivers/of/platform.c b/drivers/of/platform.c
index f39ccd5..f9bb563 100644
--- a/drivers/of/platform.c
+++ b/drivers/of/platform.c
@@ -524,15 +524,18 @@ static int __init of_platform_default_populate_init(void)
 arch_initcall_sync(of_platform_default_populate_init);
 #endif

-static int of_platform_device_destroy(struct device *dev, void *data)
+/**
+ * of_platform_device_destroy - unregister an of_device
+ * @dev: device to unregister
+ *
+ * This is the inverse operation of of_platform_device_create(). It unregisters
+ * the passed device, if registered.
+ */
+void of_platform_device_destroy(struct device *dev)
 {
/* Do not touch devices not populated from the device tree */
if (!dev->of_node || !of_node_check_flag(dev->of_node, OF_POPULATED))
-   return 0;
-
-   /* Recurse for any nodes that were treated as busses */
-   if (of_node_check_flag(dev->of_node, OF_POPULATED_BUS))
-   device_for_each_child(dev, NULL, of_platform_device_destroy);
+   return;

if (dev->bus == &platform_bus_type)
platform_device_unregister(to_platform_device(dev));
@@ -544,6 +547,20 @@ static int of_platform_device_destroy(struct device *dev, 
void *data)
of_dma_deconfigure(dev);
of_node_clear_flag(dev->of_node, OF_POPULATED);
of_node_clear_flag(dev->of_node, OF_POPULATED_BUS);
+}
+EXPORT_SYMBOL(of_platform_device_destroy);
+
+static int of_platform_device_depopulate(struct device *dev, void *data)
+{
+   /* Do not touch devices not populated from the device tree */
+   if (!dev->of_node || !of_node_check_flag(dev->of_node, OF_POPULATED))
+   return 0;
+
+   /* Recurse for any nodes that were treated as busses */
+   if (of_node_check_flag(dev->of_node, OF_POPULATED_BUS))
+   device_for_each_child(dev, NULL, of_platform_device_depopulate);
+
+   of_platform_device_destroy(dev);
return 0;
 }

@@ -562,7 +579,8 @@ static int of_platform_device_destroy(struct device *dev, 
void *data)
 void of_platform_depopulate(struct device *parent)
 {
if (parent->of_node && of_node_check_flag(parent->of_node, 
OF_POPULATED_BUS)) {
-   device_for_each_child(parent, NULL, of_platform_device_destroy);
+   device_for_each_child(parent, NULL,
+ of_platform_device_depopulate);
of_node_clear_flag(parent->of_node, OF_POPULATED_BUS);
}
 }
@@ -574,7 +592,6 @@ static int of_platform_notify(struct notifier_block *nb,
 {
struct of_reconfig_data *rd = arg;
struct platform_device *pdev_parent, *pdev;
-   bool children_left;

switch (of_reconfig_get_state_change(action, rd)) {
case OF_RECONFIG_CHANGE_ADD:
@@ -612,7 +629,7 @@ static int of_platform_notify(struct notifier_block *nb,
return NOTIFY_OK;   /* no? not meant for us */

/* unregister takes one ref away */
-   of_platform_device_destroy(&pdev->dev, &children_left);
+   of_platform_device_depopulate(&pdev->dev, NULL);

/* and put the reference of the find */
of_dev_put(pdev);
diff --git a/include/linux/of_platform.h b/include/linux/of_platform.h
index 956a100..a9017d3 100644
--- a/include/linux/of_platform.h
+++ b/include/linux/of_platform.h
@@ -63,6 +63,7 @@ extern struct platform_device *of_find_device_by_node(struct 
device_node *np);
 extern struct platform_device *of_platform_device_create(struct device_node 
*np,
   const char *bus_id,
   struct device *parent);
+extern void of_platform_device_destroy(struct device *dev);

 extern int of_platform_bus_probe(struct device_node *root,
 const struct of_device_id *matches,
-- 
2.9.3



[PATCH v5 4/7] video: add generic framebuffer eviction

2016-09-02 Thread David Herrmann
There are several situations where we want hardware handover from an early
boot GFX driver (e.g., vgacon, vesafb, efifb, simplefb) to a full fletched
GFX driver (e.g., most DRM drivers). So far, we relied on
remove_conflicting_framebuffers() to do this for us, however, this had a
bunch of downsides:

  o It only removes conflicting fbdev drivers. It does not drop vgacon,
early boot console drivers, conflicting DRM drivers, etc.

  o It only unloads the fbdev driver, it does not modify the underlying
device or resources. In case of "screen_info" drivers (e.g., efifb)
this is fine, since no resources are pinned. However, if the driver
binds to a platform-device like "simple-framebuffer", we must make
sure to unregister that device as well. Otherwise, pinned resources
like IORESOURCE_MEM stay around, triggering WARN_ONs if the following
driver requests those resources.

  o It is only available if CONFIG_FB is selected.

This commit adds a new infrastructure that manages system-framebuffers
(short: sysfb). The initial commit provides conflict-resolution for
system-framebuffers. At its core it provides sysfb_evict_conflicts(),
which implements conflict detection and removal for all known types of
GFX driver hand-overs. So far, this includes platform-device removal,
fbdev-firmware-device removal, vgacon removal and VBE detection. To
further simplify the callers, it also provides helpers to figure out what
hand-over to do, based on the device the new drivers binds to:

  o PCI drivers can use sysfb_evict_conflicts_pci(), which will figure out
the apertures automatically, and does VGA/VBE detection.

  o Generic firmware drivers that might be shadowed at any address in
memory can use sysfb_evict_conflicts_firmware(), basically removing
*all* firmware framebuffers in effect.

This only adds the generic sysfb helpers. No users are converted, yet.

Signed-off-by: David Herrmann 
---
 drivers/video/Kconfig  |   4 +
 drivers/video/Makefile |   1 +
 drivers/video/sysfb.c  | 327 +
 include/linux/sysfb.h  |  34 +
 4 files changed, 366 insertions(+)
 create mode 100644 drivers/video/sysfb.c
 create mode 100644 include/linux/sysfb.h

diff --git a/drivers/video/Kconfig b/drivers/video/Kconfig
index 3c20af9..56a8294 100644
--- a/drivers/video/Kconfig
+++ b/drivers/video/Kconfig
@@ -36,6 +36,10 @@ config VIDEOMODE_HELPERS
 config HDMI
bool

+config SYSFB
+   bool
+   select DUMMY_CONSOLE if VT
+
 if VT
source "drivers/video/console/Kconfig"
 endif
diff --git a/drivers/video/Makefile b/drivers/video/Makefile
index 9ad3c17..df7bd75 100644
--- a/drivers/video/Makefile
+++ b/drivers/video/Makefile
@@ -1,5 +1,6 @@
 obj-$(CONFIG_VGASTATE)+= vgastate.o
 obj-$(CONFIG_HDMI)+= hdmi.o
+obj-$(CONFIG_SYSFB)  += sysfb.o

 obj-$(CONFIG_VT) += console/
 obj-$(CONFIG_LOGO)   += logo/
diff --git a/drivers/video/sysfb.c b/drivers/video/sysfb.c
new file mode 100644
index 000..00585c9
--- /dev/null
+++ b/drivers/video/sysfb.c
@@ -0,0 +1,327 @@
+/*
+ * Copyright (C) 2013-2016 Red Hat, Inc.
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU Lesser General Public License as published by the
+ * Free Software Foundation; either version 2.1 of the License, or (at your
+ * option) any later version.
+ */
+
+#define pr_fmt(fmt) "sysfb: " fmt
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+
+static bool sysfb_evict_match_resource(struct sysfb_evict_ctx *ctx,
+  struct resource *mem)
+{
+   struct aperture *g;
+   unsigned int i;
+
+   for (i = 0; i < ctx->ap->count; ++i) {
+   g = &ctx->ap->ranges[i];
+
+   if (mem->start == g->base)
+   return true;
+   if (mem->start >= g->base && mem->end < g->base + g->size)
+   return true;
+   if ((ctx->flags & SYSFB_EVICT_VBE) && mem->start == 0xA)
+   return true;
+   }
+
+   return false;
+}
+
+static int sysfb_evict_platform_device(struct device *dev, void *userdata)
+{
+   struct sysfb_evict_ctx *ctx = userdata;
+   struct platform_device *pdev = to_platform_device(dev);
+   struct resource *mem;
+
+   if (!pdev->name)
+   return 0;
+
+   if (!strcmp(pdev->name, "simple-framebuffer")) {
+   mem = platform_get_resource(pdev, IORESOURCE_MEM, 0);
+   if (!mem)
+   return 0;
+   if (!sysfb_evict_match_resource(ctx, mem))
+   return 0;
+
+#ifdef CONFIG_OF

[PATCH v5 5/7] drm: switch to sysfb_evict_conflicts()

2016-09-02 Thread David Herrmann
Switch over all DRM drivers to use the new sysfb_evict_conflicts()
infrastructure. The only non-trivial conversion is i915, since it does not
make use of the generic PCI resources, but assembles the apertures via
intel ggtt queries.

Signed-off-by: David Herrmann 
---
 drivers/gpu/drm/Kconfig  |  1 +
 drivers/gpu/drm/amd/amdgpu/amdgpu_drv.c  | 24 +--
 drivers/gpu/drm/bochs/bochs_drv.c| 19 +
 drivers/gpu/drm/i915/i915_drv.c  | 73 ++--
 drivers/gpu/drm/mgag200/mgag200_drv.c| 27 +++-
 drivers/gpu/drm/mgag200/mgag200_main.c   |  9 
 drivers/gpu/drm/nouveau/nouveau_drm.c| 33 +++
 drivers/gpu/drm/radeon/radeon_drv.c  | 24 +--
 drivers/gpu/drm/sun4i/sun4i_drv.c| 24 +++
 drivers/gpu/drm/vc4/vc4_drv.c| 25 +++
 drivers/gpu/drm/virtio/virtgpu_drm_bus.c | 24 +--
 11 files changed, 44 insertions(+), 239 deletions(-)

diff --git a/drivers/gpu/drm/Kconfig b/drivers/gpu/drm/Kconfig
index fc35731..f27f9b5 100644
--- a/drivers/gpu/drm/Kconfig
+++ b/drivers/gpu/drm/Kconfig
@@ -12,6 +12,7 @@ menuconfig DRM
select I2C
select I2C_ALGOBIT
select DMA_SHARED_BUFFER
+   select SYSFB
help
  Kernel-level support for the Direct Rendering Infrastructure (DRI)
  introduced in XFree86 4.0. If you say Y here, you need to select
diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_drv.c 
b/drivers/gpu/drm/amd/amdgpu/amdgpu_drv.c
index 9aa533c..a1e67da 100644
--- a/drivers/gpu/drm/amd/amdgpu/amdgpu_drv.c
+++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_drv.c
@@ -38,6 +38,7 @@
 #include 
 #include 
 #include 
+#include 
 #include 
 #include "drm_crtc_helper.h"

@@ -326,27 +327,6 @@ MODULE_DEVICE_TABLE(pci, pciidlist);

 static struct drm_driver kms_driver;

-static int amdgpu_kick_out_firmware_fb(struct pci_dev *pdev)
-{
-   struct apertures_struct *ap;
-   bool primary = false;
-
-   ap = alloc_apertures(1);
-   if (!ap)
-   return -ENOMEM;
-
-   ap->ranges[0].base = pci_resource_start(pdev, 0);
-   ap->ranges[0].size = pci_resource_len(pdev, 0);
-
-#ifdef CONFIG_X86
-   primary = pdev->resource[PCI_ROM_RESOURCE].flags & 
IORESOURCE_ROM_SHADOW;
-#endif
-   remove_conflicting_framebuffers(ap, "amdgpudrmfb", primary);
-   kfree(ap);
-
-   return 0;
-}
-
 static int amdgpu_pci_probe(struct pci_dev *pdev,
const struct pci_device_id *ent)
 {
@@ -368,7 +348,7 @@ static int amdgpu_pci_probe(struct pci_dev *pdev,
return ret;

/* Get rid of things like offb */
-   ret = amdgpu_kick_out_firmware_fb(pdev);
+   ret = sysfb_evict_conflicts_pci(pdev);
if (ret)
return ret;

diff --git a/drivers/gpu/drm/bochs/bochs_drv.c 
b/drivers/gpu/drm/bochs/bochs_drv.c
index abace82..99c4ea3 100644
--- a/drivers/gpu/drm/bochs/bochs_drv.c
+++ b/drivers/gpu/drm/bochs/bochs_drv.c
@@ -8,6 +8,7 @@
 #include 
 #include 
 #include 
+#include 

 #include "bochs.h"

@@ -143,28 +144,12 @@ static const struct dev_pm_ops bochs_pm_ops = {
 /* -- */
 /* pci interface  */

-static int bochs_kick_out_firmware_fb(struct pci_dev *pdev)
-{
-   struct apertures_struct *ap;
-
-   ap = alloc_apertures(1);
-   if (!ap)
-   return -ENOMEM;
-
-   ap->ranges[0].base = pci_resource_start(pdev, 0);
-   ap->ranges[0].size = pci_resource_len(pdev, 0);
-   remove_conflicting_framebuffers(ap, "bochsdrmfb", false);
-   kfree(ap);
-
-   return 0;
-}
-
 static int bochs_pci_probe(struct pci_dev *pdev,
   const struct pci_device_id *ent)
 {
int ret;

-   ret = bochs_kick_out_firmware_fb(pdev);
+   ret = sysfb_evict_conflicts_pci(pdev);
if (ret)
return ret;

diff --git a/drivers/gpu/drm/i915/i915_drv.c b/drivers/gpu/drm/i915/i915_drv.c
index 95ddd56..4d6a65dd 100644
--- a/drivers/gpu/drm/i915/i915_drv.c
+++ b/drivers/gpu/drm/i915/i915_drv.c
@@ -36,6 +36,7 @@
 #include 
 #include 
 #include 
+#include 
 #include 
 #include 
 #include 
@@ -687,70 +688,32 @@ out:
return ret;
 }

-#if IS_ENABLED(CONFIG_FB)
 static int i915_kick_out_firmware_fb(struct drm_i915_private *dev_priv)
 {
-   struct apertures_struct *ap;
+   struct sysfb_evict_ctx ctx = {};
struct pci_dev *pdev = dev_priv->drm.pdev;
struct i915_ggtt *ggtt = &dev_priv->ggtt;
-   bool primary;
int ret;

-   ap = alloc_apertures(1);
-   if (!ap)
-   return -ENOMEM;
-
-   ap->ranges[0].base = ggtt->mappable_base;
-   ap->ranges[0].size = ggtt->mappable_end;
-
-   primary =
-   pdev->resource[PCI_ROM_RESOURCE].flags &

[PATCH v5 6/7] drm: add SimpleDRM driver

2016-09-02 Thread David Herrmann
The SimpleDRM driver binds to simple-framebuffer devices and provides a
DRM/KMS API. It provides only a single CRTC+encoder+connector combination
plus one initial mode.

Userspace can create dumb-buffers which can be blit into the real
framebuffer similar to UDL. No access to the real framebuffer is allowed
(compared to earlier version of this driver) to avoid security issues.
Furthermore, this way we can support arbitrary modes as long as we have a
conversion-helper.

Signed-off-by: David Herrmann 
---
 MAINTAINERS  |   6 +
 drivers/gpu/drm/Kconfig  |   2 +
 drivers/gpu/drm/Makefile |   1 +
 drivers/gpu/drm/simpledrm/Kconfig|  19 ++
 drivers/gpu/drm/simpledrm/Makefile   |   8 +
 drivers/gpu/drm/simpledrm/simpledrm.h|  83 +
 drivers/gpu/drm/simpledrm/simpledrm_damage.c | 194 +++
 drivers/gpu/drm/simpledrm/simpledrm_drv.c| 464 +++
 drivers/gpu/drm/simpledrm/simpledrm_gem.c| 109 +++
 drivers/gpu/drm/simpledrm/simpledrm_kms.c| 263 +++
 drivers/gpu/drm/simpledrm/simpledrm_of.c | 265 +++
 11 files changed, 1414 insertions(+)
 create mode 100644 drivers/gpu/drm/simpledrm/Kconfig
 create mode 100644 drivers/gpu/drm/simpledrm/Makefile
 create mode 100644 drivers/gpu/drm/simpledrm/simpledrm.h
 create mode 100644 drivers/gpu/drm/simpledrm/simpledrm_damage.c
 create mode 100644 drivers/gpu/drm/simpledrm/simpledrm_drv.c
 create mode 100644 drivers/gpu/drm/simpledrm/simpledrm_gem.c
 create mode 100644 drivers/gpu/drm/simpledrm/simpledrm_kms.c
 create mode 100644 drivers/gpu/drm/simpledrm/simpledrm_of.c

diff --git a/MAINTAINERS b/MAINTAINERS
index 0bbe4b1..408863d 100644
--- a/MAINTAINERS
+++ b/MAINTAINERS
@@ -4140,6 +4140,12 @@ S:   Orphan / Obsolete
 F: drivers/gpu/drm/savage/
 F: include/uapi/drm/savage_drm.h

+DRM DRIVER FOR SIMPLE FRAMEBUFFER DEVICES
+M: David Herrmann 
+L: dri-devel at lists.freedesktop.org
+S: Maintained
+F: drivers/gpu/drm/simpledrm/
+
 DRM DRIVER FOR SIS VIDEO CARDS
 S: Orphan / Obsolete
 F: drivers/gpu/drm/sis/
diff --git a/drivers/gpu/drm/Kconfig b/drivers/gpu/drm/Kconfig
index f27f9b5..61cbcd1 100644
--- a/drivers/gpu/drm/Kconfig
+++ b/drivers/gpu/drm/Kconfig
@@ -291,3 +291,5 @@ source "drivers/gpu/drm/arc/Kconfig"
 source "drivers/gpu/drm/hisilicon/Kconfig"

 source "drivers/gpu/drm/mediatek/Kconfig"
+
+source "drivers/gpu/drm/simpledrm/Kconfig"
diff --git a/drivers/gpu/drm/Makefile b/drivers/gpu/drm/Makefile
index 0238bf8..3e6fe99 100644
--- a/drivers/gpu/drm/Makefile
+++ b/drivers/gpu/drm/Makefile
@@ -83,3 +83,4 @@ obj-$(CONFIG_DRM_FSL_DCU) += fsl-dcu/
 obj-$(CONFIG_DRM_ETNAVIV) += etnaviv/
 obj-$(CONFIG_DRM_ARCPGU)+= arc/
 obj-y  += hisilicon/
+obj-y  += simpledrm/
diff --git a/drivers/gpu/drm/simpledrm/Kconfig 
b/drivers/gpu/drm/simpledrm/Kconfig
new file mode 100644
index 000..f45b25d
--- /dev/null
+++ b/drivers/gpu/drm/simpledrm/Kconfig
@@ -0,0 +1,19 @@
+config DRM_SIMPLEDRM
+   tristate "Simple firmware framebuffer DRM driver"
+   depends on DRM
+   select DRM_KMS_HELPER
+   help
+ SimpleDRM can run on all systems with pre-initialized graphics
+ hardware. It uses a framebuffer that was initialized during
+ firmware boot. No page-flipping, modesetting or other advanced
+ features are available. However, other DRM drivers can be loaded
+ later and take over from SimpleDRM if they provide real hardware
+ support.
+
+ SimpleDRM supports "simple-framebuffer" DeviceTree objects and
+ compatible platform framebuffers.
+
+ If unsure, say Y.
+
+ To compile this driver as a module, choose M here: the
+ module will be called simpledrm.
diff --git a/drivers/gpu/drm/simpledrm/Makefile 
b/drivers/gpu/drm/simpledrm/Makefile
new file mode 100644
index 000..d7b179d
--- /dev/null
+++ b/drivers/gpu/drm/simpledrm/Makefile
@@ -0,0 +1,8 @@
+simpledrm-y := \
+   simpledrm_damage.o \
+   simpledrm_drv.o \
+   simpledrm_gem.o \
+   simpledrm_kms.o \
+   simpledrm_of.o
+
+obj-$(CONFIG_DRM_SIMPLEDRM) := simpledrm.o
diff --git a/drivers/gpu/drm/simpledrm/simpledrm.h 
b/drivers/gpu/drm/simpledrm/simpledrm.h
new file mode 100644
index 000..ed6d725
--- /dev/null
+++ b/drivers/gpu/drm/simpledrm/simpledrm.h
@@ -0,0 +1,83 @@
+#ifndef __SDRM_SIMPLEDRM_H
+#define __SDRM_SIMPLEDRM_H
+
+/*
+ * Copyright (C) 2012-2016 Red Hat, Inc.
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU Lesser General Public License as published by the
+ * Free Software Foundation; either version 2.1 of the License, or (at your
+ * option) any later version.
+ */
+
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+#includ

[PATCH v5 7/7] drm/simpledrm: add fbdev fallback support

2016-09-02 Thread David Herrmann
Create a simple fbdev device during SimpleDRM setup so legacy user-space
and fbcon can use it.

Signed-off-by: David Herrmann 
---
 drivers/gpu/drm/simpledrm/Makefile  |   1 +
 drivers/gpu/drm/simpledrm/simpledrm.h   |   8 ++
 drivers/gpu/drm/simpledrm/simpledrm_drv.c   |  13 +++
 drivers/gpu/drm/simpledrm/simpledrm_fbdev.c | 143 
 drivers/gpu/drm/simpledrm/simpledrm_kms.c   |  55 ++-
 5 files changed, 196 insertions(+), 24 deletions(-)
 create mode 100644 drivers/gpu/drm/simpledrm/simpledrm_fbdev.c

diff --git a/drivers/gpu/drm/simpledrm/Makefile 
b/drivers/gpu/drm/simpledrm/Makefile
index d7b179d..e368d14 100644
--- a/drivers/gpu/drm/simpledrm/Makefile
+++ b/drivers/gpu/drm/simpledrm/Makefile
@@ -1,6 +1,7 @@
 simpledrm-y := \
simpledrm_damage.o \
simpledrm_drv.o \
+   simpledrm_fbdev.o \
simpledrm_gem.o \
simpledrm_kms.o \
simpledrm_of.o
diff --git a/drivers/gpu/drm/simpledrm/simpledrm.h 
b/drivers/gpu/drm/simpledrm/simpledrm.h
index ed6d725..d7a2045 100644
--- a/drivers/gpu/drm/simpledrm/simpledrm.h
+++ b/drivers/gpu/drm/simpledrm/simpledrm.h
@@ -19,6 +19,7 @@
 #include 

 struct clk;
+struct drm_fb_helper;
 struct regulator;
 struct simplefb_format;

@@ -49,6 +50,7 @@ struct sdrm_device {
atomic_t n_used;
struct drm_device *ddev;
struct sdrm_hw *hw;
+   struct drm_fb_helper *fbdev;

size_t n_clks;
size_t n_regulators;
@@ -66,6 +68,9 @@ void sdrm_of_unbind(struct sdrm_device *sdrm);
 int sdrm_kms_bind(struct sdrm_device *sdrm);
 void sdrm_kms_unbind(struct sdrm_device *sdrm);

+void sdrm_fbdev_bind(struct sdrm_device *sdrm);
+void sdrm_fbdev_unbind(struct sdrm_device *sdrm);
+
 void sdrm_dirty(struct sdrm_fb *fb, u32 x, u32 y, u32 width, u32 height);

 struct sdrm_bo *sdrm_bo_new(struct drm_device *ddev, size_t size);
@@ -80,4 +85,7 @@ int sdrm_dumb_map_offset(struct drm_file *dfile,
 uint32_t handle,
 uint64_t *offset);

+struct sdrm_fb *sdrm_fb_new(struct sdrm_bo *bo,
+   const struct drm_mode_fb_cmd2 *cmd);
+
 #endif /* __SDRM_SIMPLEDRM_H */
diff --git a/drivers/gpu/drm/simpledrm/simpledrm_drv.c 
b/drivers/gpu/drm/simpledrm/simpledrm_drv.c
index d569120..6aefe49 100644
--- a/drivers/gpu/drm/simpledrm/simpledrm_drv.c
+++ b/drivers/gpu/drm/simpledrm/simpledrm_drv.c
@@ -9,6 +9,7 @@

 #define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
 #include 
+#include 
 #include 
 #include 
 #include 
@@ -210,6 +211,7 @@ error:
 static void sdrm_device_unbind(struct sdrm_device *sdrm)
 {
if (sdrm) {
+   sdrm_fbdev_unbind(sdrm);
sdrm_kms_unbind(sdrm);
sdrm_hw_unbind(sdrm->hw);
sdrm_of_unbind(sdrm);
@@ -232,6 +234,8 @@ static int sdrm_device_bind(struct sdrm_device *sdrm)
if (r < 0)
goto error;

+   sdrm_fbdev_bind(sdrm);
+
return 0;

 error:
@@ -253,6 +257,14 @@ static void sdrm_device_release(struct sdrm_device *sdrm)
}
 }

+static void sdrm_device_lastclose(struct drm_device *ddev)
+{
+   struct sdrm_device *sdrm = ddev->dev_private;
+
+   if (sdrm->fbdev)
+   drm_fb_helper_restore_fbdev_mode_unlocked(sdrm->fbdev);
+}
+
 static int sdrm_fop_open(struct inode *inode, struct file *file)
 {
struct drm_device *ddev;
@@ -411,6 +423,7 @@ static const struct file_operations sdrm_drm_fops = {
 static struct drm_driver sdrm_drm_driver = {
.driver_features = DRIVER_GEM | DRIVER_MODESET | DRIVER_ATOMIC,
.fops = &sdrm_drm_fops,
+   .lastclose = sdrm_device_lastclose,

.gem_free_object = sdrm_bo_free,

diff --git a/drivers/gpu/drm/simpledrm/simpledrm_fbdev.c 
b/drivers/gpu/drm/simpledrm/simpledrm_fbdev.c
new file mode 100644
index 000..17e4e83
--- /dev/null
+++ b/drivers/gpu/drm/simpledrm/simpledrm_fbdev.c
@@ -0,0 +1,143 @@
+/*
+ * Copyright (C) 2012-2016 Red Hat, Inc.
+ * Copyright (C) 2016 Noralf Trønnes
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU Lesser General Public License as published by the
+ * Free Software Foundation; either version 2.1 of the License, or (at your
+ * option) any later version.
+ */
+
+#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+#include "simpledrm.h"
+
+static int sdrm_fbdev_mmap(struct fb_info *info, struct vm_area_struct *vma)
+{
+   return -ENODEV;
+}
+
+static struct fb_ops sdrm_fbdev_ops = {
+   .owner  = THIS_MODULE,
+   .fb_fillrect= drm_fb_helper_sys_fillrect,
+   .fb_copyarea= drm_fb_helper_sys_copyarea,
+   .fb_imageblit   = drm_fb_helper_sys_imageblit,
+   .fb_check_var   = drm_fb_helper_check_var,
+   .fb_set_par = drm_fb_helper_set_par,
+   .fb_setcmap = drm_fb_helper_s

drm: WARNING in ioremap_wc

2016-09-02 Thread David Herrmann
Hey

On Fri, Sep 2, 2016 at 2:23 PM, Dmitry Vyukov  wrote:
> On Mon, Aug 29, 2016 at 8:05 AM, Daniel Vetter  wrote:
>> On Sun, Aug 28, 2016 at 07:36:59PM +0200, Dmitry Vyukov wrote:
>>> Hello,
>>>
>>> The following program triggers WARNING in ioremap_wc:
>>
>> Yup, that should also be fixed in linux-next. Probably better to not
>> report more for 4.8-rc kernels for now ;-)
>>
>> If you have some time to test, you need to cherry pick the following two
>> patches I think:
>>
>> fa5386459f06 ("drm: Used DRM_LEGACY for all legacy functions")
>> 3cbf6a5deb2f ("drm: Mark up legacy/dri1 drivers with DRM_LEGACY")
>>
>> If that's confirmed we can cherry-pick them over to -fixes.
>
>
> Hi Daniel,
>
> I've switched to linux-next and don't see the WARNINGs anymore.
> I wonder how they were discovered? Is somebody else running syzkaller?
> Or they were discovered in some other way?

We independently discovered that some DRM-KMS drivers enabled the DRI1
ioctls, and fixed this. Hence, you should be unable to trigger
anything in drm_bufs.c, drm_context.c, and friends.

Thanks
David


[PATCH v5 6/7] drm: add SimpleDRM driver

2016-09-03 Thread David Herrmann
Hey

On Sat, Sep 3, 2016 at 2:01 PM, Noralf Trønnes  wrote:
>
> Den 02.09.2016 10:22, skrev David Herrmann:
>>
>> The SimpleDRM driver binds to simple-framebuffer devices and provides a
>> DRM/KMS API. It provides only a single CRTC+encoder+connector combination
>> plus one initial mode.
>>
>> Userspace can create dumb-buffers which can be blit into the real
>> framebuffer similar to UDL. No access to the real framebuffer is allowed
>> (compared to earlier version of this driver) to avoid security issues.
>> Furthermore, this way we can support arbitrary modes as long as we have a
>> conversion-helper.
>>
>> Signed-off-by: David Herrmann 
>> ---
>
>
> [...]
>
>> diff --git a/drivers/gpu/drm/simpledrm/simpledrm_drv.c
>> b/drivers/gpu/drm/simpledrm/simpledrm_drv.c
>
>
> [...]
>
>> +static int sdrm_fop_mmap(struct file *file, struct vm_area_struct *vma)
>> +{
>> +   struct drm_file *dfile = file->private_data;
>> +   struct drm_device *dev = dfile->minor->dev;
>> +   struct drm_gem_object *obj = NULL;
>> +   struct drm_vma_offset_node *node;
>> +   int r;
>> +
>> +   drm_vma_offset_lock_lookup(dev->vma_offset_manager);
>> +   node = drm_vma_offset_exact_lookup_locked(dev->vma_offset_manager,
>> + vma->vm_pgoff,
>> + vma_pages(vma));
>> +   if (likely(node)) {
>> +   obj = container_of(node, struct drm_gem_object, vma_node);
>> +   if (!kref_get_unless_zero(&obj->refcount))
>> +   obj = NULL;
>> +   }
>> +   drm_vma_offset_unlock_lookup(dev->vma_offset_manager);
>> +
>> +   if (!obj)
>> +   return -EINVAL;
>> +
>> +   if (!drm_vma_node_is_allowed(node, dfile)) {
>
>
> I get:
> drivers/gpu/drm/simpledrm/simpledrm_drv.c:320:2: warning: passing argument 2
> of ‘drm_vma_node_is_allowed’ from incompatible pointer type [enabled by
> default]
>
> dfile -> file

Yeah, either change that, or apply "[PATCH 0/6] DRM Core Cleanups"
before. I suspect the cleanups to go in before this driver, so didn't
bother changing it.

>> +   drm_gem_object_unreference_unlocked(obj);
>> +   return -EACCES;
>> +   }
>> +
>> +   if (vma->vm_file)
>> +   fput(vma->vm_file);
>> +   vma->vm_file = get_file(obj->filp);
>> +   vma->vm_pgoff = 0;
>> +
>> +   r = obj->filp->f_op->mmap(obj->filp, vma);
>> +   drm_gem_object_unreference_unlocked(obj);
>> +   return r;
>> +}
>
>
> [...]
>
>> diff --git a/drivers/gpu/drm/simpledrm/simpledrm_kms.c
>> b/drivers/gpu/drm/simpledrm/simpledrm_kms.c
>
>
> [...]
>
>
>> +static void sdrm_crtc_send_vblank_event(struct drm_crtc *crtc)
>> +{
>> +   if (crtc->state && crtc->state->event) {
>> +   spin_lock_irq(&crtc->dev->event_lock);
>> +   drm_crtc_send_vblank_event(crtc, crtc->state->event);
>> +   spin_unlock_irq(&crtc->dev->event_lock);
>> +   crtc->state->event = NULL;
>> +   }
>> +}
>> +
>> +void sdrm_display_pipe_update(struct drm_simple_display_pipe *pipe,
>> + struct drm_plane_state *plane_state)
>> +{
>> +   struct drm_framebuffer *dfb = pipe->plane.state->fb;
>> +   struct sdrm_fb *fb;
>> +
>> +   sdrm_crtc_send_vblank_event(&pipe->crtc);
>> +
>> +   if (dfb) {
>> +   fb = container_of(dfb, struct sdrm_fb, base);
>> +   pipe->plane.fb = dfb;
>> +   sdrm_dirty(fb, 0, 0, dfb->width, dfb->height);
>> +   }
>> +}
>> +
>> +static void sdrm_display_pipe_enable(struct drm_simple_display_pipe
>> *pipe,
>> +struct drm_crtc_state *crtc_state)
>> +{
>> +   sdrm_crtc_send_vblank_event(&pipe->crtc);
>> +}
>> +
>> +static void sdrm_display_pipe_disable(struct drm_simple_display_pipe
>> *pipe)
>> +{
>> +   sdrm_crtc_send_vblank_event(&pipe->crtc);
>> +}
>> +
>> +static const struct drm_simple_display_pipe_funcs sdrm_pipe_funcs = {
>> +   .update = sdrm_display_pipe_update,
>> +   .enable = sdrm_display_pipe_enable,
>> +   .disable= sdrm_display_pipe_disable,
>> +};
>
>
> The enable and disable callbacks can be removed.
> This commit in drm-misc fixed the flip done timeout:
> drm/simple-helpers: Always add planes to the state update

Right, Daniel told me on IRC already. With this fix applied, I can run
Xorg on top of it just fine.

I dropped the enable/disable callbacks as well now.

Thanks
David


[PATCH v5 4/7] video: add generic framebuffer eviction

2016-09-05 Thread David Herrmann
Hi

On Sat, Sep 3, 2016 at 2:06 PM, Noralf Trønnes  wrote:
>
> Den 02.09.2016 10:22, skrev David Herrmann:
>>
>> There are several situations where we want hardware handover from an early
>> boot GFX driver (e.g., vgacon, vesafb, efifb, simplefb) to a full fletched
>> GFX driver (e.g., most DRM drivers). So far, we relied on
>> remove_conflicting_framebuffers() to do this for us, however, this had a
>> bunch of downsides:
>>
>>o It only removes conflicting fbdev drivers. It does not drop vgacon,
>>  early boot console drivers, conflicting DRM drivers, etc.
>>
>>o It only unloads the fbdev driver, it does not modify the underlying
>>  device or resources. In case of "screen_info" drivers (e.g., efifb)
>>  this is fine, since no resources are pinned. However, if the driver
>>  binds to a platform-device like "simple-framebuffer", we must make
>>  sure to unregister that device as well. Otherwise, pinned resources
>>  like IORESOURCE_MEM stay around, triggering WARN_ONs if the following
>>  driver requests those resources.
>>
>>o It is only available if CONFIG_FB is selected.
>>
>> This commit adds a new infrastructure that manages system-framebuffers
>> (short: sysfb). The initial commit provides conflict-resolution for
>> system-framebuffers. At its core it provides sysfb_evict_conflicts(),
>> which implements conflict detection and removal for all known types of
>> GFX driver hand-overs. So far, this includes platform-device removal,
>> fbdev-firmware-device removal, vgacon removal and VBE detection. To
>> further simplify the callers, it also provides helpers to figure out what
>> hand-over to do, based on the device the new drivers binds to:
>>
>>o PCI drivers can use sysfb_evict_conflicts_pci(), which will figure
>> out
>>  the apertures automatically, and does VGA/VBE detection.
>>
>>o Generic firmware drivers that might be shadowed at any address in
>>  memory can use sysfb_evict_conflicts_firmware(), basically removing
>>  *all* firmware framebuffers in effect.
>>
>> This only adds the generic sysfb helpers. No users are converted, yet.
>>
>> Signed-off-by: David Herrmann 
>> ---
>>   drivers/video/Kconfig  |   4 +
>>   drivers/video/Makefile |   1 +
>>   drivers/video/sysfb.c  | 327
>> +
>>   include/linux/sysfb.h  |  34 +
>>   4 files changed, 366 insertions(+)
>>   create mode 100644 drivers/video/sysfb.c
>>   create mode 100644 include/linux/sysfb.h
>>
>> diff --git a/drivers/video/Kconfig b/drivers/video/Kconfig
>> index 3c20af9..56a8294 100644
>> --- a/drivers/video/Kconfig
>> +++ b/drivers/video/Kconfig
>> @@ -36,6 +36,10 @@ config VIDEOMODE_HELPERS
>>   config HDMI
>> bool
>>   +config SYSFB
>> +   bool
>> +   select DUMMY_CONSOLE if VT
>> +
>>   if VT
>> source "drivers/video/console/Kconfig"
>>   endif
>> diff --git a/drivers/video/Makefile b/drivers/video/Makefile
>> index 9ad3c17..df7bd75 100644
>> --- a/drivers/video/Makefile
>> +++ b/drivers/video/Makefile
>> @@ -1,5 +1,6 @@
>>   obj-$(CONFIG_VGASTATE)+= vgastate.o
>>   obj-$(CONFIG_HDMI)+= hdmi.o
>> +obj-$(CONFIG_SYSFB)  += sysfb.o
>> obj-$(CONFIG_VT)  += console/
>>   obj-$(CONFIG_LOGO)  += logo/
>> diff --git a/drivers/video/sysfb.c b/drivers/video/sysfb.c
>> new file mode 100644
>> index 000..00585c9
>> --- /dev/null
>> +++ b/drivers/video/sysfb.c
>> @@ -0,0 +1,327 @@
>> +/*
>> + * Copyright (C) 2013-2016 Red Hat, Inc.
>> + *
>> + * This program is free software; you can redistribute it and/or modify
>> it
>> + * under the terms of the GNU Lesser General Public License as published
>> by the
>> + * Free Software Foundation; either version 2.1 of the License, or (at
>> your
>> + * option) any later version.
>> + */
>> +
>> +#define pr_fmt(fmt) "sysfb: " fmt
>> +#include 
>> +#include 
>> +#include 
>> +#include 
>> +#include 
>> +#include 
>> +#include 
>> +#include 
>> +#include 
>> +#include 
>> +#include 
>> +#include 
>> +#include 
>> +#include 
>> +
>> +static bool sysfb_evict_match_resource(struct sysfb_evict_ctx *ctx,
>> +  struct resource *mem)
>> +{
>> +   struct aperture *

[PATCH v5 7/7] drm/simpledrm: add fbdev fallback support

2016-09-05 Thread David Herrmann
Hi

On Sat, Sep 3, 2016 at 7:15 PM, Noralf Trønnes  wrote:
>
> Den 03.09.2016 14:04, skrev Noralf Trønnes:
>>
>>
>> Den 02.09.2016 10:22, skrev David Herrmann:
>>>
>>> Create a simple fbdev device during SimpleDRM setup so legacy user-space
>>> and fbcon can use it.
>>>
>>> Signed-off-by: David Herrmann 
>>
>>
>> [...]
>>
>>> diff --git a/drivers/gpu/drm/simpledrm/simpledrm_fbdev.c
>>> b/drivers/gpu/drm/simpledrm/simpledrm_fbdev.c
>>
>>
>> [...]
>>
>>> +void sdrm_fbdev_bind(struct sdrm_device *sdrm)
>>> +{
>>> +struct drm_fb_helper *fbdev;
>>> +int r;
>>> +
>>> +fbdev = kzalloc(sizeof(*fbdev), GFP_KERNEL);
>>> +if (!fbdev)
>>> +return;
>>> +
>>> +drm_fb_helper_prepare(sdrm->ddev, fbdev, &sdrm_fbdev_funcs);
>>> +
>>> +r = drm_fb_helper_init(sdrm->ddev, fbdev, 1, 1);
>>> +if (r < 0)
>>> +goto error;
>>> +
>>> +r = drm_fb_helper_single_add_all_connectors(fbdev);
>>> +if (r < 0)
>>> +goto error;
>>> +
>>> +r = drm_fb_helper_initial_config(fbdev,
>>> +sdrm->ddev->mode_config.preferred_depth);
>>> +if (r < 0)
>>> +goto error;
>>> +
>>> +if (!fbdev->fbdev)
>>> +goto error;
>>> +
>>> +sdrm->fbdev = fbdev;
>>> +return;
>>> +
>>> +error:
>>> +drm_fb_helper_fini(fbdev);
>>> +kfree(fbdev);
>>> +}
>>> +
>>> +void sdrm_fbdev_unbind(struct sdrm_device *sdrm)
>>> +{
>>> +struct drm_fb_helper *fbdev = sdrm->fbdev;
>>> +
>>> +if (!fbdev)
>>> +return;
>>> +
>>> +sdrm->fbdev = NULL;
>>> +drm_fb_helper_unregister_fbi(fbdev);
>>> +cancel_work_sync(&fbdev->dirty_work);
>>> +drm_fb_helper_release_fbi(fbdev);
>>> +drm_framebuffer_unreference(fbdev->fb);
>>
>>
>> I get a warning that there are still fb's left during unbind:
>>
>> [   48.666003] WARNING: CPU: 0 PID: 716 at drivers/gpu/drm/drm_crtc.c:3855
>> drm_mode_config_cleanup+0x180/0x1f4 [drm]
>>
>> This worked:
>>
>> -   drm_framebuffer_unreference(fbdev->fb);
>> +   drm_framebuffer_unregister_private(fbdev->fb);
>> +   drm_framebuffer_cleanup(fbdev->fb);
>>
>
> Well not quite, this doesn't free the bo, so maybe this:
>
> -   drm_framebuffer_unreference(fbdev->fb);
> +   drm_framebuffer_unregister_private(fbdev->fb);
> +   sdrm_fb_destroy(fbdev->fb);
>
> IIRC the reason ref count doesn't drop to zero, had something to do with
> multiple
> fb_set_par calls taking reference but not being dropped later.

So I don't like this at all. If we leak references, we should fix the
ref-leak or properly document why this is fine to do. Daniel, what is
the exact reason we have unregister_private()? Maybe I should try and
trace the ref-leak.

Thanks
David


drm: NULL pointer dereference in drm_mode_object_find()

2016-09-20 Thread David Herrmann
Hi

On Mon, Sep 5, 2016 at 10:30 AM, Dmitry Vyukov  wrote:
> On Fri, Aug 19, 2016 at 7:10 PM, Alexander Potapenko  
> wrote:
>> Hello,
>>
>> the program below triggers a NULL deref in DRM code when ran on QEMU:
>>
>> ===
>> BUG: unable to handle kernel NULL pointer dereference at   (null)
>> IP: [< inline >] __list_add ./include/linux/list.h:44
>> IP: [< inline >] list_add_tail ./include/linux/list.h:77
>> IP: [< inline >] __mutex_lock_common kernel/locking/mutex.c:543
>> IP: [] __mutex_lock_slowpath+0x6f/0x100
>> kernel/locking/mutex.c:824
>> PGD 1c555067 PUD 1c554067 PMD 0
>> Oops: 0002 [#1] SMP
>> Modules linked in:
>> CPU: 0 PID: 2517 Comm: crash_drm_mode_ Not tainted 4.8.0-rc2+ #1157
>> Hardware name: QEMU Standard PC (i440FX + PIIX, 1996), BIOS Bochs 01/01/2011
>> task: 88001c40a700 task.stack: 88001c984000
>> RIP: 0010:[]  []
>> __mutex_lock_slowpath+0x6f/0x100
>> RSP: 0018:88001c987cb0  EFLAGS: 00010282
>> RAX:  RBX: 88001d5212a0 RCX: c100
>> RDX: 0001 RSI: 88001c40a700 RDI: 88001d5212a4
>> RBP: 88001c987cf8 R08: 88001c984000 R09: 
>> R10:  R11:  R12: 88001c40a700
>> R13: 88001d5212a4 R14:  R15: 88001d5212a8
>> FS:  00dc9880() GS:88001f00() knlGS:
>> CS:  0010 DS:  ES:  CR0: 80050033
>> CR2:  CR3: 1c8a9000 CR4: 000406f0
>> Stack:
>>  88001d5212a8   811a398f
>>  88001d5212a0 88001d5212a0  
>>  81a6eb20 88001c987d10 818e85ba 88001d521000
>> Call Trace:
>>  [< inline >] __mutex_fastpath_lock 
>> ./arch/x86/include/asm/mutex_64.h:28
>>  [] mutex_lock+0x1a/0x30 kernel/locking/mutex.c:102
>>  [] _object_find+0x23/0xc0 drivers/gpu/drm/drm_crtc.c:329
>>  [< inline >] drm_mode_object_find drivers/gpu/drm/drm_crtc.c:360
>>  [< inline >] drm_crtc_find ./include/drm/drm_crtc.h:2999
>>  [] drm_mode_page_flip_ioctl+0x4e/0x300
>> drivers/gpu/drm/drm_crtc.c:5414
>>  [] drm_ioctl+0x2a2/0x460 drivers/gpu/drm/drm_ioctl.c:721
>>  [< inline >] vfs_ioctl fs/ioctl.c:43
>>  [] do_vfs_ioctl+0x8d/0x580 fs/ioctl.c:675
>>  [< inline >] SYSC_ioctl fs/ioctl.c:690
>>  [] SyS_ioctl+0x74/0x80 fs/ioctl.c:681
>>  [] entry_SYSCALL_64_fastpath+0x13/0x8f
>> arch/x86/entry/entry_64.S:207
>> Code: e8 37 23 00 00 8b 03 83 f8 01 0f 84 95 00 00 00 48 8b 43 10 4c
>> 8d 7b 08 48 89 63 10 41 be ff ff ff ff 4c 89 3c 24 48 89 44 24 08 <48>
>> 89 20 4c 89 64 24 10 eb 19 49 c7 04 24 02 00 00 00 c6 43 04
>> RIP  [< inline >] __list_add ./include/linux/list.h:44
>> RIP  [< inline >] list_add_tail ./include/linux/list.h:77
>> RIP  [< inline >] __mutex_lock_common kernel/locking/mutex.c:543
>> RIP  [] __mutex_lock_slowpath+0x6f/0x100
>> kernel/locking/mutex.c:824
>>  RSP 
>> CR2: 
>> ---[ end trace 3cef4eb618ac6bb6 ]---
>> ===
>>
>> // autogenerated by syzkaller (http://github.com/google/syzkaller)
>> #include 
>> #include 
>> #include 
>>
>> int main()
>> {
>>   int fd = open("/dev/dri/card0", 0);
>>   mmap(0x20036000ul, 0x1000ul, 0x3ul, 0x32ul, 0xul, 0x0ul);
>>   memcpy((void*)0x20036ad7,
>>  "\x1e\xa4\x45\xdc\xca\x11\xff\x25\x72\x65\x7e\x4a\x56\x54\x35"
>>  "\x67\xe3\x8b\x41\x5c\x6d\x69\xa5\xf9\x88\x29\xb8\xc9\x6a\x45"
>>  "\x76\xa9\xe7\x14\xd1\xf6\xa3\x59\x07\x4d\xe5\xc8\x39\xbf\x33"
>>  "\xb9\x3d\x21\xd1\xaf\x16\x4d\xbc\xbf\xb1\x0a\x92\x97\xd9\x91"
>>  "\x4d\xd8\xf8\xa1\xa6\xa3\x20\x02\x2c\x5e\x8f\x87\x05\x8b\xeb"
>>  "\x9a\xb9\xbc\xa6\x60\x45\x8d\x19\x01\x7d\xb7\xef\x64\x62\x2e"
>>  "\x5e\x3d\xfe\x65\xbf\xe2\x80\x89\x36\x48\x73\xc6\xa2\x6e\xe2"
>>  "\x1a\x8f\x1b\x11\x6f\x49\x20\xeb\x74\x2d\x41\xb9\x8b\xb4\x8e"
>>  "\x8b\xf5\x6d\xb7\xb1\xa3\xcb\xc4\xc2\x7f\x6d\xef\x32\xef\xa7"
>>  "\x1c\x17\x03\x60\x7b\x31\x1f\x66",
>>  143);
>>   ioctl(fd, 0xbb0ul, 0x20036ad7ul, 0, 0, 0);
>>   return 0;
>> }
>>
>> I build the ToT kernel (commit
>> 952b159f2919a8d514f13999f9f463bddcc1dae7, Aug 18) with defconfig and
>> CONFIG_DRM_VGEM=y.
>
> +dri-devel
>
> I am also hitting this on 0f98f121e1670eaa2a2fbb675e07d6ba7f0e146f of
> linux-next.

Can you tell us which DRM driver this is? vgem does not specify
DRIVER_MODESET, so the page-flip ioctl should not be hooked up. Also,
the mmap() operation should fail on any GEM driver. *confused*

Thanks
David


drm: NULL pointer dereference in drm_mode_object_find()

2016-09-21 Thread David Herrmann
Hi

On Tue, Sep 20, 2016 at 11:25 AM, Alexander Potapenko  
wrote:
> On Tue, Sep 20, 2016 at 11:21 AM, David Herrmann  
> wrote:
>> Hi
>>
>> On Mon, Sep 5, 2016 at 10:30 AM, Dmitry Vyukov  wrote:
>>> On Fri, Aug 19, 2016 at 7:10 PM, Alexander Potapenko  
>>> wrote:
>>>> Hello,
>>>>
>>>> the program below triggers a NULL deref in DRM code when ran on QEMU:
>>>>
>>>> ===
>>>> BUG: unable to handle kernel NULL pointer dereference at   (null)
>>>> IP: [< inline >] __list_add ./include/linux/list.h:44
>>>> IP: [< inline >] list_add_tail ./include/linux/list.h:77
>>>> IP: [< inline >] __mutex_lock_common kernel/locking/mutex.c:543
>>>> IP: [] __mutex_lock_slowpath+0x6f/0x100
>>>> kernel/locking/mutex.c:824
>>>> PGD 1c555067 PUD 1c554067 PMD 0
>>>> Oops: 0002 [#1] SMP
>>>> Modules linked in:
>>>> CPU: 0 PID: 2517 Comm: crash_drm_mode_ Not tainted 4.8.0-rc2+ #1157
>>>> Hardware name: QEMU Standard PC (i440FX + PIIX, 1996), BIOS Bochs 
>>>> 01/01/2011
>>>> task: 88001c40a700 task.stack: 88001c984000
>>>> RIP: 0010:[]  []
>>>> __mutex_lock_slowpath+0x6f/0x100
>>>> RSP: 0018:88001c987cb0  EFLAGS: 00010282
>>>> RAX:  RBX: 88001d5212a0 RCX: c100
>>>> RDX: 0001 RSI: 88001c40a700 RDI: 88001d5212a4
>>>> RBP: 88001c987cf8 R08: 88001c984000 R09: 
>>>> R10:  R11:  R12: 88001c40a700
>>>> R13: 88001d5212a4 R14:  R15: 88001d5212a8
>>>> FS:  00dc9880() GS:88001f00() 
>>>> knlGS:
>>>> CS:  0010 DS:  ES:  CR0: 80050033
>>>> CR2:  CR3: 1c8a9000 CR4: 000406f0
>>>> Stack:
>>>>  88001d5212a8   811a398f
>>>>  88001d5212a0 88001d5212a0  
>>>>  81a6eb20 88001c987d10 818e85ba 88001d521000
>>>> Call Trace:
>>>>  [< inline >] __mutex_fastpath_lock 
>>>> ./arch/x86/include/asm/mutex_64.h:28
>>>>  [] mutex_lock+0x1a/0x30 kernel/locking/mutex.c:102
>>>>  [] _object_find+0x23/0xc0 drivers/gpu/drm/drm_crtc.c:329
>>>>  [< inline >] drm_mode_object_find drivers/gpu/drm/drm_crtc.c:360
>>>>  [< inline >] drm_crtc_find ./include/drm/drm_crtc.h:2999
>>>>  [] drm_mode_page_flip_ioctl+0x4e/0x300
>>>> drivers/gpu/drm/drm_crtc.c:5414
>>>>  [] drm_ioctl+0x2a2/0x460 drivers/gpu/drm/drm_ioctl.c:721
>>>>  [< inline >] vfs_ioctl fs/ioctl.c:43
>>>>  [] do_vfs_ioctl+0x8d/0x580 fs/ioctl.c:675
>>>>  [< inline >] SYSC_ioctl fs/ioctl.c:690
>>>>  [] SyS_ioctl+0x74/0x80 fs/ioctl.c:681
>>>>  [] entry_SYSCALL_64_fastpath+0x13/0x8f
>>>> arch/x86/entry/entry_64.S:207
>>>> Code: e8 37 23 00 00 8b 03 83 f8 01 0f 84 95 00 00 00 48 8b 43 10 4c
>>>> 8d 7b 08 48 89 63 10 41 be ff ff ff ff 4c 89 3c 24 48 89 44 24 08 <48>
>>>> 89 20 4c 89 64 24 10 eb 19 49 c7 04 24 02 00 00 00 c6 43 04
>>>> RIP  [< inline >] __list_add ./include/linux/list.h:44
>>>> RIP  [< inline >] list_add_tail ./include/linux/list.h:77
>>>> RIP  [< inline >] __mutex_lock_common kernel/locking/mutex.c:543
>>>> RIP  [] __mutex_lock_slowpath+0x6f/0x100
>>>> kernel/locking/mutex.c:824
>>>>  RSP 
>>>> CR2: 
>>>> ---[ end trace 3cef4eb618ac6bb6 ]---
>>>> ===
>>>>
>>>> // autogenerated by syzkaller (http://github.com/google/syzkaller)
>>>> #include 
>>>> #include 
>>>> #include 
>>>>
>>>> int main()
>>>> {
>>>>   int fd = open("/dev/dri/card0", 0);
>>>>   mmap(0x20036000ul, 0x1000ul, 0x3ul, 0x32ul, 0xul, 0x0ul);
>>>>   memcpy((void*)0x20036ad7,
>>>>  "\x1e\xa4\x45\xdc\xca\x11\xff\x25\x72\x65\x7e\x4a\x56\x54\x35"
>>>>  "\x67\xe3\x8b\x41\x5c\x6d\x69\xa5\xf9\x88\x29\xb8\xc9\x6a\x45"
>>>>  "

[PATCH] drm/udl: Fix for the X server screen update v3

2016-09-21 Thread David Herrmann
Hi

On Wed, Sep 21, 2016 at 6:47 AM, poma  wrote:
> Within X server, on top of DisplayLink GPU USB2.0 device,
> screen content is not refreshed i.e. updated.
>
> This fixes commit:
>
> - e375882406d0cc24030746638592004755ed4ae0
>   "drm/udl: Use drm_fb_helper deferred_io support"
>
> Thanks Noralf and Daniel for the comments.
>
> Tested-by: poma 

Can you provide your Signed-off-by: line?

Reviewed-by: David Herrmann 

Thanks
David

> ---
>  drivers/gpu/drm/udl/udl_fb.c | 2 +-
>  1 file changed, 1 insertion(+), 1 deletion(-)
>
> diff --git a/drivers/gpu/drm/udl/udl_fb.c b/drivers/gpu/drm/udl/udl_fb.c
> index d5df555..cc2daba 100644
> --- a/drivers/gpu/drm/udl/udl_fb.c
> +++ b/drivers/gpu/drm/udl/udl_fb.c
> @@ -122,7 +122,7 @@ int udl_handle_damage(struct udl_framebuffer *fb, int x, 
> int y,
> return 0;
> cmd = urb->transfer_buffer;
>
> -   for (i = y; i < height ; i++) {
> +   for (i = y; i < y + height ; i++) {
> const int line_offset = fb->base.pitches[0] * i;
> const int byte_offset = line_offset + (x * bpp);
> const int dev_byte_offset = (fb->base.width * bpp * i) + (x * 
> bpp);
> --
> 2.7.4
>
>
> ___
> dri-devel mailing list
> dri-devel at lists.freedesktop.org
> https://lists.freedesktop.org/mailman/listinfo/dri-devel


[PATCH] drm/udl: Fix for the X server screen update v3

2016-09-21 Thread David Herrmann
Hi

On Wed, Sep 21, 2016 at 1:19 PM, poma  wrote:
> On 21.09.2016 09:34, David Herrmann wrote:
>> Hi
>>
>> On Wed, Sep 21, 2016 at 6:47 AM, poma  wrote:
>>> Within X server, on top of DisplayLink GPU USB2.0 device,
>>> screen content is not refreshed i.e. updated.
>>>
>>> This fixes commit:
>>>
>>> - e375882406d0cc24030746638592004755ed4ae0
>>>   "drm/udl: Use drm_fb_helper deferred_io support"
>>>
>>> Thanks Noralf and Daniel for the comments.
>>>
>>> Tested-by: poma 
>>
>> Can you provide your Signed-off-by: line?
>>
>> Reviewed-by: David Herrmann 
>>
>> Thanks
>> David
>>
>
> S-o-b should be performed by the actual kernel developer.
> R-b & T-b, I've already written.

The author of a patch must provide the S-o-b (see
Documentation/SubmittingPatches if you want details). So simply reply
with a "S-o-b: foo " line to this mail. And please include it in
all patches you submit (preferably use `git commit --sign-off`).

Thanks
David


[PATCH 2/2] drm: Don't swallow error codes in drm_dev_alloc()

2016-09-22 Thread David Herrmann
Hey

On Wed, Sep 21, 2016 at 4:59 PM, Tom Gundersen  wrote:
> There are many reasons other than ENOMEM that drm_dev_init() can
> fail. Return ERR_PTR rather than NULL to be able to distinguish
> these in the caller.
>
> Signed-off-by: Tom Gundersen 
> ---

Reviewed-by: David Herrmann 

Thanks
David

>  drivers/gpu/drm/arc/arcpgu_drv.c| 4 ++--
>  drivers/gpu/drm/arm/hdlcd_drv.c | 4 ++--
>  drivers/gpu/drm/arm/malidp_drv.c| 4 ++--
>  drivers/gpu/drm/atmel-hlcdc/atmel_hlcdc_dc.c| 4 ++--
>  drivers/gpu/drm/drm_drv.c   | 6 +++---
>  drivers/gpu/drm/drm_pci.c   | 4 ++--
>  drivers/gpu/drm/drm_platform.c  | 4 ++--
>  drivers/gpu/drm/etnaviv/etnaviv_drv.c   | 4 ++--
>  drivers/gpu/drm/fsl-dcu/fsl_dcu_drm_drv.c   | 4 ++--
>  drivers/gpu/drm/hisilicon/kirin/kirin_drm_drv.c | 4 ++--
>  drivers/gpu/drm/mediatek/mtk_drm_drv.c  | 4 ++--
>  drivers/gpu/drm/msm/msm_drv.c   | 4 ++--
>  drivers/gpu/drm/nouveau/nouveau_drm.c   | 4 ++--
>  drivers/gpu/drm/rcar-du/rcar_du_drv.c   | 4 ++--
>  drivers/gpu/drm/rockchip/rockchip_drm_drv.c | 4 ++--
>  drivers/gpu/drm/sti/sti_drv.c   | 4 ++--
>  drivers/gpu/drm/sun4i/sun4i_drv.c   | 4 ++--
>  drivers/gpu/drm/tegra/drm.c | 4 ++--
>  drivers/gpu/drm/udl/udl_drv.c   | 4 ++--
>  drivers/gpu/drm/vc4/vc4_drv.c   | 4 ++--
>  drivers/gpu/drm/vgem/vgem_drv.c | 4 ++--
>  drivers/gpu/drm/virtio/virtgpu_drm_bus.c| 4 ++--
>  22 files changed, 45 insertions(+), 45 deletions(-)
>
> diff --git a/drivers/gpu/drm/arc/arcpgu_drv.c 
> b/drivers/gpu/drm/arc/arcpgu_drv.c
> index 6d4ff34..28e6471 100644
> --- a/drivers/gpu/drm/arc/arcpgu_drv.c
> +++ b/drivers/gpu/drm/arc/arcpgu_drv.c
> @@ -198,8 +198,8 @@ static int arcpgu_probe(struct platform_device *pdev)
> int ret;
>
> drm = drm_dev_alloc(&arcpgu_drm_driver, &pdev->dev);
> -   if (!drm)
> -   return -ENOMEM;
> +   if (IS_ERR(drm))
> +   return PTR_ERR(drm);
>
> ret = arcpgu_load(drm);
> if (ret)
> diff --git a/drivers/gpu/drm/arm/hdlcd_drv.c b/drivers/gpu/drm/arm/hdlcd_drv.c
> index d83b46a..fb6a418 100644
> --- a/drivers/gpu/drm/arm/hdlcd_drv.c
> +++ b/drivers/gpu/drm/arm/hdlcd_drv.c
> @@ -326,8 +326,8 @@ static int hdlcd_drm_bind(struct device *dev)
> return -ENOMEM;
>
> drm = drm_dev_alloc(&hdlcd_driver, dev);
> -   if (!drm)
> -   return -ENOMEM;
> +   if (IS_ERR(drm))
> +   return PTR_ERR(drm);
>
> drm->dev_private = hdlcd;
> dev_set_drvdata(dev, drm);
> diff --git a/drivers/gpu/drm/arm/malidp_drv.c 
> b/drivers/gpu/drm/arm/malidp_drv.c
> index c383d72..9280358 100644
> --- a/drivers/gpu/drm/arm/malidp_drv.c
> +++ b/drivers/gpu/drm/arm/malidp_drv.c
> @@ -311,8 +311,8 @@ static int malidp_bind(struct device *dev)
> return ret;
>
> drm = drm_dev_alloc(&malidp_driver, dev);
> -   if (!drm) {
> -   ret = -ENOMEM;
> +   if (IS_ERR(drm)) {
> +   ret = PTR_ERR(drm);
> goto alloc_fail;
> }
>
> diff --git a/drivers/gpu/drm/atmel-hlcdc/atmel_hlcdc_dc.c 
> b/drivers/gpu/drm/atmel-hlcdc/atmel_hlcdc_dc.c
> index 8e7483d..5f48431 100644
> --- a/drivers/gpu/drm/atmel-hlcdc/atmel_hlcdc_dc.c
> +++ b/drivers/gpu/drm/atmel-hlcdc/atmel_hlcdc_dc.c
> @@ -797,8 +797,8 @@ static int atmel_hlcdc_dc_drm_probe(struct 
> platform_device *pdev)
> int ret;
>
> ddev = drm_dev_alloc(&atmel_hlcdc_dc_driver, &pdev->dev);
> -   if (!ddev)
> -   return -ENOMEM;
> +   if (IS_ERR(ddev))
> +   return PTR_ERR(ddev);
>
> ret = atmel_hlcdc_dc_load(ddev);
> if (ret)
> diff --git a/drivers/gpu/drm/drm_drv.c b/drivers/gpu/drm/drm_drv.c
> index 99e6751..80c7f25 100644
> --- a/drivers/gpu/drm/drm_drv.c
> +++ b/drivers/gpu/drm/drm_drv.c
> @@ -591,7 +591,7 @@ EXPORT_SYMBOL(drm_dev_init);
>   * own struct should look at using drm_dev_init() instead.
>   *
>   * RETURNS:
> - * Pointer to new DRM device, or NULL if out of memory.
> + * Pointer to new DRM device, or ERR_PTR on failure.
>   */
>  struct drm_device *drm_dev_alloc(struct drm_driver *driver,
>  struct device *parent)
> @@ -601,12 +601,12 @@ struct drm_device *drm_dev_alloc(struct drm_driver 
> *driver,
>
> dev = kzalloc(sizeof(*dev), GFP_KERNEL);
> if (!dev)
> -   re

[PATCH] drm/udl: fix line iterator in damage handling

2016-09-23 Thread David Herrmann
The udl damage handler is supposed to render 'height' lines, but its
iterator has an obvious typo that makes it miss most lines if the
rectangle does not cover 0/0.

Fix the damage handler to correctly render all lines.

This is a fallout from:

commit e375882406d0cc24030746638592004755ed4ae0
Author: Noralf Trønnes 
Date:   Thu Apr 28 17:18:37 2016 +0200

drm/udl: Use drm_fb_helper deferred_io support

Tested-by: poma 
Reviewed-by: Daniel Vetter 
Signed-off-by: David Herrmann 
---
 drivers/gpu/drm/udl/udl_fb.c | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/drivers/gpu/drm/udl/udl_fb.c b/drivers/gpu/drm/udl/udl_fb.c
index 9688bfa..611b6b9 100644
--- a/drivers/gpu/drm/udl/udl_fb.c
+++ b/drivers/gpu/drm/udl/udl_fb.c
@@ -122,7 +122,7 @@ int udl_handle_damage(struct udl_framebuffer *fb, int x, 
int y,
return 0;
cmd = urb->transfer_buffer;

-   for (i = y; i < height ; i++) {
+   for (i = y; i < y + height ; i++) {
const int line_offset = fb->base.pitches[0] * i;
const int byte_offset = line_offset + (x * bpp);
const int dev_byte_offset = (fb->base.width * bpp * i) + (x * 
bpp);
-- 
2.10.0



[PATCH] drm: Convert prime dma-buf <-> handle to rbtree

2016-09-27 Thread David Herrmann
Hi Chris

On Mon, Sep 26, 2016 at 10:44 PM, Chris Wilson  
wrote:
> Currently we use a linear walk to lookup a handle and return a dma-buf,
> and vice versa. A long overdue TODO task is to convert that to a
> hashtable. Since the initial implementation of dma-buf/prime, we now
> have resizeable hashtables we can use (and now a future task is to RCU
> enable the lookup!). However, this patch opts to use an rbtree instead
> to provide O(lgN) lookups (and insertion, deletion). rbtrees were chosen
> over using the RCU backed resizable hashtable to firstly avoid the
> reallocations (rbtrees can be embedded entirely within the parent
> struct) and to favour simpler code with predictable worst case
> behaviour. In simple testing, the difference between using the constant
> lookup and insertion of the rhashtable and the rbtree was less than 10%
> of the wall time (igt/benchmarks/prime_lookup) - both are dramatic
> improvements over the existing linear lists.
>
> v2: Favour rbtree over rhashtable
>
> Bugzilla: https://bugs.freedesktop.org/show_bug.cgi?id=94631
> Signed-off-by: Chris Wilson 
> Cc: Sean Paul 
> Cc: David Herrmann 
> ---
>  drivers/gpu/drm/drm_prime.c | 85 
> +++--
>  include/drm/drmP.h  |  5 +--
>  2 files changed, 77 insertions(+), 13 deletions(-)

Thanks for doing the benchmark and rewriting it with rb-trees. I think
the lack of error-handling is a big plus here. Anyway, this is:

Reviewed-by: David Herrmann 

Your tree-traversals are a bit inconsistent in how you order your
iterator against the element to lookup in your conditions, but.. meh.
A big WARN_ON on conflicts might not hurt either. But looks all good.

Thanks
David

> diff --git a/drivers/gpu/drm/drm_prime.c b/drivers/gpu/drm/drm_prime.c
> index 780589b420a4..57201d68cf61 100644
> --- a/drivers/gpu/drm/drm_prime.c
> +++ b/drivers/gpu/drm/drm_prime.c
> @@ -28,6 +28,7 @@
>
>  #include 
>  #include 
> +#include 
>  #include 
>  #include 
>
> @@ -61,9 +62,11 @@
>   */
>
>  struct drm_prime_member {
> -   struct list_head entry;
> struct dma_buf *dma_buf;
> uint32_t handle;
> +
> +   struct rb_node dmabuf_rb;
> +   struct rb_node handle_rb;
>  };
>
>  struct drm_prime_attachment {
> @@ -75,6 +78,7 @@ static int drm_prime_add_buf_handle(struct 
> drm_prime_file_private *prime_fpriv,
> struct dma_buf *dma_buf, uint32_t handle)
>  {
> struct drm_prime_member *member;
> +   struct rb_node **p, *rb;
>
> member = kmalloc(sizeof(*member), GFP_KERNEL);
> if (!member)
> @@ -83,18 +87,56 @@ static int drm_prime_add_buf_handle(struct 
> drm_prime_file_private *prime_fpriv,
> get_dma_buf(dma_buf);
> member->dma_buf = dma_buf;
> member->handle = handle;
> -   list_add(&member->entry, &prime_fpriv->head);
> +
> +   rb = NULL;
> +   p = &prime_fpriv->dmabufs.rb_node;
> +   while (*p) {
> +   struct drm_prime_member *pos;
> +
> +   rb = *p;
> +   pos = rb_entry(rb, struct drm_prime_member, dmabuf_rb);
> +   if (dma_buf > pos->dma_buf)
> +   p = &rb->rb_right;
> +   else
> +   p = &rb->rb_left;
> +   }
> +   rb_link_node(&member->dmabuf_rb, rb, p);
> +   rb_insert_color(&member->dmabuf_rb, &prime_fpriv->dmabufs);
> +
> +   rb = NULL;
> +   p = &prime_fpriv->handles.rb_node;
> +   while (*p) {
> +   struct drm_prime_member *pos;
> +
> +   rb = *p;
> +   pos = rb_entry(rb, struct drm_prime_member, handle_rb);
> +   if (handle > pos->handle)
> +   p = &rb->rb_right;
> +   else
> +   p = &rb->rb_left;
> +   }
> +   rb_link_node(&member->handle_rb, rb, p);
> +   rb_insert_color(&member->handle_rb, &prime_fpriv->handles);
> +
> return 0;
>  }
>
>  static struct dma_buf *drm_prime_lookup_buf_by_handle(struct 
> drm_prime_file_private *prime_fpriv,
>   uint32_t handle)
>  {
> -   struct drm_prime_member *member;
> +   struct rb_node *rb;
> +
> +   rb = prime_fpriv->handles.rb_node;
> +   while (rb) {
> +   struct drm_prime_member *member;
>
> -   list_for_each_entry(member, &prime_fpriv->head, entry) {
> +   member = rb_entry(rb, struct drm_prime_member, handle_rb);
> 

[PATCH] drm: add fourcc codes for 16bit R and GR

2017-01-02 Thread David Herrmann
Hi

On Mon, Jan 2, 2017 at 11:41 AM, Rainer Hochecker  
wrote:
> From: Rainer Hochecker 
>
> Add fourcc codes for 16bit planes. Required by mesa for
> eglCreateImageKHR to access P010 surfaces created by vaapi.
>
> Signed-off-by: Rainer Hochecker 
> ---
>  include/uapi/drm/drm_fourcc.h | 6 ++
>  1 file changed, 6 insertions(+)
>
> diff --git a/include/uapi/drm/drm_fourcc.h b/include/uapi/drm/drm_fourcc.h
> index a5890bf..e6ab638 100644
> --- a/include/uapi/drm/drm_fourcc.h
> +++ b/include/uapi/drm/drm_fourcc.h
> @@ -41,10 +41,16 @@ extern "C" {
>  /* 8 bpp Red */
>  #define DRM_FORMAT_R8  fourcc_code('R', '8', ' ', ' ') /* [7:0] R */
>
> +/* 16 bpp Red */
> +#define DRM_FORMAT_R16 fourcc_code('R', '1', '6', ' ') /* [15:0] R */
> +
>  /* 16 bpp RG */
>  #define DRM_FORMAT_RG88fourcc_code('R', 'G', '8', '8') /* 
> [15:0] R:G 8:8 little endian */
>  #define DRM_FORMAT_GR88fourcc_code('G', 'R', '8', '8') /* 
> [15:0] G:R 8:8 little endian */
>
> +/* 32 bpp GR */
> +#define DRM_FORMAT_GR16fourcc_code('G', 'R', '1', '6') /* 
> [31:0] G:R 16:16 little endian */
> +

Shouldn't it be 'G', 'R', '3', '2'?

Also, please put dri-devel on CC.

Thanks
David

>  /* 8 bpp RGB */
>  #define DRM_FORMAT_RGB332  fourcc_code('R', 'G', 'B', '8') /* [7:0] 
> R:G:B 3:3:2 */
>  #define DRM_FORMAT_BGR233  fourcc_code('B', 'G', 'R', '8') /* [7:0] 
> B:G:R 2:3:3 */
> --
> 2.9.3
>


[PATCH, RESEND] drm: avoid uninitialized timestamp use in wait_vblank

2016-02-26 Thread David Herrmann
Hi

On Thu, Feb 25, 2016 at 10:09 PM, Arnd Bergmann  wrote:
> gcc warns about the timestamp in drm_wait_vblank being possibly
> used without an initialization:
>
> drivers/gpu/drm/drm_irq.c: In function 'drm_wait_vblank':
> drivers/gpu/drm/drm_irq.c:1755:28: warning: 'now.tv_usec' may be used 
> uninitialized in this function [-Wmaybe-uninitialized]
>vblwait->reply.tval_usec = now.tv_usec;
> drivers/gpu/drm/drm_irq.c:1754:27: warning: 'now.tv_sec' may be used 
> uninitialized in this function [-Wmaybe-uninitialized]
>vblwait->reply.tval_sec = now.tv_sec;
>
> This can happen if drm_vblank_count_and_time() returns 0 in its
> error path. To sanitize the error case, I'm changing that function
> to return a zero timestamp when it fails.
>
> Signed-off-by: Arnd Bergmann 
> Fixes: e6ae8687a87b ("drm: idiot-proof vblank")
> ---
>  drivers/gpu/drm/drm_irq.c | 4 +++-
>  1 file changed, 3 insertions(+), 1 deletion(-)
>
> I'm going through the maybe-unused warnings in randconfig builds, this one is
> apparently not a false positive, although it only happens if something
> else has already gone wrong.
>
> Originally sent out on Jan 13, but I received no reply, so resending now.
>
> diff --git a/drivers/gpu/drm/drm_irq.c b/drivers/gpu/drm/drm_irq.c
> index 881c5a6c180c..6f41ddfbe061 100644
> --- a/drivers/gpu/drm/drm_irq.c
> +++ b/drivers/gpu/drm/drm_irq.c
> @@ -997,8 +997,10 @@ u32 drm_vblank_count_and_time(struct drm_device *dev, 
> unsigned int pipe,
> int count = DRM_TIMESTAMP_MAXRETRIES;
> u32 cur_vblank;
>
> -   if (WARN_ON(pipe >= dev->num_crtcs))
> +   if (WARN_ON(pipe >= dev->num_crtcs)) {
> +   *vblanktime = (struct timeval) { 0 };

The '0' is redundant. Anyway, this is:

Reviewed-by: David Herrmann 

(CC: Daniel, for drm-misc)

Thanks
David

> return 0;
> +   }
>
> /*
>  * Vblank timestamps are read lockless. To ensure consistency the 
> vblank
> --
> 2.7.0
>
> ___
> dri-devel mailing list
> dri-devel at lists.freedesktop.org
> https://lists.freedesktop.org/mailman/listinfo/dri-devel


[PATCH v3 2/2] drm: remove drm_device_is_unplugged and related code

2016-02-26 Thread David Herrmann
Hi

On Fri, Feb 12, 2016 at 8:50 PM, Haixia Shi  wrote:
> v1: Remove the general drm_device_is_unplugged() checks, and move the 
> unplugged
> flag handling logic into drm/udl. In general we want to keep driver-specific
> logic out of common drm code.
>
> v2: Based on discussion with Stephane and David, drop most of the unplugged
> flag handling logic in drm/udl except for udl_detect() and udl_fb_open().
> The intention is to treat the device removal as a connector-unplug, and kep
> the UDL device fully functional.
>
> v3: Based on feedback from David, entirely drop the "unplugged" flag and all
> related code. There is no need to check for the unplugged flag as the existing
> udl_usb_disconnect() behavior already ensures the controller is removed, and
> all code paths that uses the usb-device are not reachable after unplug.
>
> When a UDL monitor is unplugged, we need to still treat it as a fully
> functional device which just happens to have its connector unplugged.
> This allows user-space to properly deallocate fbs and dumb buffers
> before closing the device.
>
> This drops the "unplugged" flag hack, which puts the device in a
> non-functional state after USB unplug and rejects most operations on
> the device such as ioctls with error -ENODEV.
>
> Signed-off-by: Haixia Shi 
> Reviewed-by: Stéphane Marchesin 
> Cc: David Herrmann 
> Cc: Daniel Vetter 
> ---
>  drivers/gpu/drm/drm_drv.c   |  6 --
>  drivers/gpu/drm/drm_fops.c  |  2 --
>  drivers/gpu/drm/drm_gem.c   |  3 ---
>  drivers/gpu/drm/drm_ioctl.c |  3 ---
>  drivers/gpu/drm/drm_vm.c|  3 ---
>  drivers/gpu/drm/udl/udl_connector.c |  2 --
>  drivers/gpu/drm/udl/udl_fb.c|  6 --
>  include/drm/drmP.h  | 14 --
>  8 files changed, 39 deletions(-)
>
> diff --git a/drivers/gpu/drm/drm_drv.c b/drivers/gpu/drm/drm_drv.c
> index 167c8d3..f93ee12 100644
> --- a/drivers/gpu/drm/drm_drv.c
> +++ b/drivers/gpu/drm/drm_drv.c
> @@ -376,9 +376,6 @@ struct drm_minor *drm_minor_acquire(unsigned int minor_id)
>
> if (!minor) {
> return ERR_PTR(-ENODEV);
> -   } else if (drm_device_is_unplugged(minor->dev)) {
> -   drm_dev_unref(minor->dev);
> -   return ERR_PTR(-ENODEV);
> }
>
> return minor;
> @@ -464,9 +461,6 @@ void drm_unplug_dev(struct drm_device *dev)
> drm_minor_unregister(dev, DRM_MINOR_CONTROL);
>
> mutex_lock(&drm_global_mutex);
> -
> -   drm_device_set_unplugged(dev);
> -
> if (dev->open_count == 0) {
> drm_put_dev(dev);
> }
> diff --git a/drivers/gpu/drm/drm_fops.c b/drivers/gpu/drm/drm_fops.c
> index 1ea8790..b4332d4 100644
> --- a/drivers/gpu/drm/drm_fops.c
> +++ b/drivers/gpu/drm/drm_fops.c
> @@ -497,8 +497,6 @@ int drm_release(struct inode *inode, struct file *filp)
>
> if (!--dev->open_count) {
> retcode = drm_lastclose(dev);
> -   if (drm_device_is_unplugged(dev))
> -   drm_put_dev(dev);

Who frees the udl device now? What code-path is responsible to call
drm_dev_unregister() for udl devices? This hunk looks bogus to me.
Please elaborate.

> }
> mutex_unlock(&drm_global_mutex);
>
> diff --git a/drivers/gpu/drm/drm_gem.c b/drivers/gpu/drm/drm_gem.c
> index 2e8c77e..c622e32 100644
> --- a/drivers/gpu/drm/drm_gem.c
> +++ b/drivers/gpu/drm/drm_gem.c
> @@ -900,9 +900,6 @@ int drm_gem_mmap(struct file *filp, struct vm_area_struct 
> *vma)
> struct drm_vma_offset_node *node;
> int ret;
>
> -   if (drm_device_is_unplugged(dev))
> -   return -ENODEV;
> -
> drm_vma_offset_lock_lookup(dev->vma_offset_manager);
> node = drm_vma_offset_exact_lookup_locked(dev->vma_offset_manager,
>   vma->vm_pgoff,
> diff --git a/drivers/gpu/drm/drm_ioctl.c b/drivers/gpu/drm/drm_ioctl.c
> index 8ce2a0c..f959074 100644
> --- a/drivers/gpu/drm/drm_ioctl.c
> +++ b/drivers/gpu/drm/drm_ioctl.c
> @@ -695,9 +695,6 @@ long drm_ioctl(struct file *filp,
>
> dev = file_priv->minor->dev;
>
> -   if (drm_device_is_unplugged(dev))
> -   return -ENODEV;
> -
> is_driver_ioctl = nr >= DRM_COMMAND_BASE && nr < DRM_COMMAND_END;
>
> if (is_driver_ioctl) {
> diff --git a/drivers/gpu/drm/drm_vm.c b/drivers/gpu/drm/drm_vm.c
> index f90bd5f..3a68be4 100644
> --- a/drivers/gpu/drm/drm_vm.c
> +++ b/drivers/gpu/drm/drm_vm.c
> @@ -657,9 +657,6 @@ int drm_legacy_mmap(struct file *filp, struct 
> vm_a

[PATCH] configure.ac: disable annoying warning -Wmissing-field-initializers

2016-01-16 Thread David Herrmann
Hi

On Fri, Jan 15, 2016 at 4:24 PM, Marek Olšák  wrote:
> On Fri, Jan 15, 2016 at 12:12 PM, Emil Velikov  
> wrote:
>> On 12 January 2016 at 23:14, Marek Olšák  wrote:
>>> From: Marek Olšák 
>>>
>>> It warns for all "{}" initializers. Well, I want us to use {}.
>>> ---
>>>  configure.ac | 3 ++-
>>>  intel/intel_decode.c | 2 --
>> The whole of libdrm, minus the intel_decode can get away without using
>> such constructs. And yes that includes radeon and amdgpu.
>>
>> NACK on this one - please be consistent with existing code base.
>
> Consistent with what? {} is the same as memset on each structure
> member. The warning says that a structure member is initialized to
> zero because of {}, which is why {} is used in the first place. It's
> the same as using memset and getting a warning "memset initializes the
> memory to zero". How useful is that?

The only use of this warning is to prevent people from learning that
{} initializes any non-specified field to 0.

Reviewed-by: David Herrmann 

Thanks
David


[PATCH] drm: Add missing __user annotation

2014-07-21 Thread David Herrmann
Hi

On Mon, Jul 21, 2014 at 1:24 PM, Thierry Reding
 wrote:
> From: Thierry Reding 
>
> The drm_copy_field() function copies strings into userspace buffers, so
> the first parameter needs to have a __user annotation to avoid warnings
> from the sparse checker.

Reviewed-by: David Herrmann 

Thanks
David

> Signed-off-by: Thierry Reding 
> ---
>  drivers/gpu/drm/drm_drv.c | 2 +-
>  1 file changed, 1 insertion(+), 1 deletion(-)
>
> diff --git a/drivers/gpu/drm/drm_drv.c b/drivers/gpu/drm/drm_drv.c
> index 8218078b6133..0cc182745e31 100644
> --- a/drivers/gpu/drm/drm_drv.c
> +++ b/drivers/gpu/drm/drm_drv.c
> @@ -233,7 +233,7 @@ module_exit(drm_core_exit);
>  /**
>   * Copy and IOCTL return string to user space
>   */
> -static int drm_copy_field(char *buf, size_t *buf_len, const char *value)
> +static int drm_copy_field(char __user *buf, size_t *buf_len, const char 
> *value)
>  {
> int len;
>
> --
> 2.0.1
>
> ___
> dri-devel mailing list
> dri-devel at lists.freedesktop.org
> http://lists.freedesktop.org/mailman/listinfo/dri-devel


[PATCH 00/12] DRM: Random Cleanups

2014-07-23 Thread David Herrmann
Hi

A bunch of random cleanups I stumbled on when reworking the init-logic. Most of
them should be fairly trivial.

Also available in my fdo-repository:
   http://cgit.freedesktop.org/~dvdhrm/linux/log/?h=drm-next

Comments welcome!
David

David Herrmann (12):
  drm: remove unused "struct drm_freelist"
  drm: drop unused "struct drm_queue"
  drm: call ->firstopen() before ->open()
  drm: extract legacy ctxbitmap flushing
  drm: drop i386 verification
  drm: fix __alpha__ PCI lookup
  drm: drop redundant drm_file->is_master
  drm: don't de-authenticate clients on master-close
  drm: move module initialization to drm_stub.c
  drm: merge drm_drv.c into drm_ioctl.c
  drm: make minor->index available early
  drm: make sysfs device always available for minors

 drivers/gpu/drm/drm_bufs.c |  17 +-
 drivers/gpu/drm/drm_context.c  |  30 ++
 drivers/gpu/drm/drm_crtc.c |   2 +-
 drivers/gpu/drm/drm_drv.c  | 471 -
 drivers/gpu/drm/drm_fops.c | 227 +-
 drivers/gpu/drm/drm_info.c |   2 +-
 drivers/gpu/drm/drm_ioctl.c| 369 +-
 drivers/gpu/drm/drm_lock.c |   2 +-
 drivers/gpu/drm/drm_stub.c | 231 ++
 drivers/gpu/drm/drm_sysfs.c|  90 +++---
 drivers/gpu/drm/i915/i915_gem_execbuffer.c |   4 +-
 drivers/gpu/drm/vmwgfx/vmwgfx_drv.c|   2 +-
 include/drm/drmP.h |  52 +---
 13 files changed, 705 insertions(+), 794 deletions(-)
 delete mode 100644 drivers/gpu/drm/drm_drv.c

-- 
2.0.2



[PATCH 02/12] drm: drop unused "struct drm_queue"

2014-07-23 Thread David Herrmann
This object is unused, drop it.

Signed-off-by: David Herrmann 
---
 include/drm/drmP.h | 17 -
 1 file changed, 17 deletions(-)

diff --git a/include/drm/drmP.h b/include/drm/drmP.h
index 335b7b8..d3d9be6 100644
--- a/include/drm/drmP.h
+++ b/include/drm/drmP.h
@@ -430,23 +430,6 @@ struct drm_file {
struct drm_prime_file_private prime;
 };

-/** Wait queue */
-struct drm_queue {
-   atomic_t use_count; /**< Outstanding uses (+1) */
-   atomic_t finalization;  /**< Finalization in progress */
-   atomic_t block_count;   /**< Count of processes waiting */
-   atomic_t block_read;/**< Queue blocked for reads */
-   wait_queue_head_t read_queue;   /**< Processes waiting on block_read */
-   atomic_t block_write;   /**< Queue blocked for writes */
-   wait_queue_head_t write_queue;  /**< Processes waiting on block_write */
-   atomic_t total_queued;  /**< Total queued statistic */
-   atomic_t total_flushed; /**< Total flushes statistic */
-   atomic_t total_locks;   /**< Total locks statistics */
-   enum drm_ctx_flags flags;   /**< Context preserving and 2D-only */
-   struct drm_waitlist waitlist;   /**< Pending buffers */
-   wait_queue_head_t flush_queue;  /**< Processes waiting until flush */
-};
-
 /**
  * Lock data.
  */
-- 
2.0.2



[PATCH 01/12] drm: remove unused "struct drm_freelist"

2014-07-23 Thread David Herrmann
This object is not used except for static fields in drm_bufs *cough*.
Inline the watermark fields and drop the unused structure definition.

Signed-off-by: David Herrmann 
---
 drivers/gpu/drm/drm_bufs.c | 17 -
 drivers/gpu/drm/drm_info.c |  2 +-
 include/drm/drmP.h | 15 ++-
 3 files changed, 11 insertions(+), 23 deletions(-)

diff --git a/drivers/gpu/drm/drm_bufs.c b/drivers/gpu/drm/drm_bufs.c
index 68175b5..61acb8f 100644
--- a/drivers/gpu/drm/drm_bufs.c
+++ b/drivers/gpu/drm/drm_bufs.c
@@ -1217,7 +1217,6 @@ int drm_infobufs(struct drm_device *dev, void *data,
struct drm_buf_desc __user *to =
&request->list[count];
struct drm_buf_entry *from = &dma->bufs[i];
-   struct drm_freelist *list = 
&dma->bufs[i].freelist;
if (copy_to_user(&to->count,
 &from->buf_count,
 sizeof(from->buf_count)) ||
@@ -1225,19 +1224,19 @@ int drm_infobufs(struct drm_device *dev, void *data,
 &from->buf_size,
 sizeof(from->buf_size)) ||
copy_to_user(&to->low_mark,
-&list->low_mark,
-sizeof(list->low_mark)) ||
+&from->low_mark,
+sizeof(from->low_mark)) ||
copy_to_user(&to->high_mark,
-&list->high_mark,
-sizeof(list->high_mark)))
+&from->high_mark,
+sizeof(from->high_mark)))
return -EFAULT;

DRM_DEBUG("%d %d %d %d %d\n",
  i,
  dma->bufs[i].buf_count,
  dma->bufs[i].buf_size,
- dma->bufs[i].freelist.low_mark,
- dma->bufs[i].freelist.high_mark);
+ dma->bufs[i].low_mark,
+ dma->bufs[i].high_mark);
++count;
}
}
@@ -1290,8 +1289,8 @@ int drm_markbufs(struct drm_device *dev, void *data,
if (request->high_mark < 0 || request->high_mark > entry->buf_count)
return -EINVAL;

-   entry->freelist.low_mark = request->low_mark;
-   entry->freelist.high_mark = request->high_mark;
+   entry->low_mark = request->low_mark;
+   entry->high_mark = request->high_mark;

return 0;
 }
diff --git a/drivers/gpu/drm/drm_info.c b/drivers/gpu/drm/drm_info.c
index 86feedd..ecaf0fa 100644
--- a/drivers/gpu/drm/drm_info.c
+++ b/drivers/gpu/drm/drm_info.c
@@ -132,7 +132,7 @@ int drm_bufs_info(struct seq_file *m, void *data)
   i,
   dma->bufs[i].buf_size,
   dma->bufs[i].buf_count,
-  atomic_read(&dma->bufs[i].freelist.count),
+  0,
   dma->bufs[i].seg_count,
   seg_pages,
   seg_pages * PAGE_SIZE / 1024);
diff --git a/include/drm/drmP.h b/include/drm/drmP.h
index 9b6a445..335b7b8 100644
--- a/include/drm/drmP.h
+++ b/include/drm/drmP.h
@@ -346,18 +346,6 @@ struct drm_waitlist {
spinlock_t write_lock;
 };

-struct drm_freelist {
-   int initialized;   /**< Freelist in use */
-   atomic_t count;/**< Number of free buffers */
-   struct drm_buf *next;  /**< End pointer */
-
-   wait_queue_head_t waiting; /**< Processes waiting on free bufs */
-   int low_mark;  /**< Low water mark */
-   int high_mark; /**< High water mark */
-   atomic_t wfh;  /**< If waiting for high mark */
-   spinlock_t lock;
-};
-
 typedef struct drm_dma_handle {
dma_addr_t busaddr;
void *vaddr;
@@ -375,7 +363,8 @@ struct drm_buf_entry {
int page_order;
struct drm_dma_handle **seglist;

-   struct drm_freelist freelist;
+   int low_mark;   /**< Low water mark */
+   int high_mark;  /**< High water mark */
 };

 /* Event queued up for userspace to read */
-- 
2.0.2



[PATCH 03/12] drm: call ->firstopen() before ->open()

2014-07-23 Thread David Herrmann
Lets order things correctly:
 ->load()
   ->fistopen()
 ->open()
 ->close()
   ->lastclose()
 ->unload()

This doesn't change much as only savage and radeon use ->firstopen() and
they just do map-initialization. Therefore, the global drm mutex makes
sure there cannot be any other f_op between ->open() and ->firstopen().
However, once we get rid of that lock, we really want ->firstopen() to
initialize the device before ->open() is called.

Furthermore, this fixes the clean-up path in drm_open(). We currently
don't cleanup the drm_file object if ->firstopen() fails.

Signed-off-by: David Herrmann 
---
 drivers/gpu/drm/drm_fops.c | 139 +
 include/drm/drmP.h |   2 +-
 2 files changed, 66 insertions(+), 75 deletions(-)

diff --git a/drivers/gpu/drm/drm_fops.c b/drivers/gpu/drm/drm_fops.c
index 021fe5d..8e73519 100644
--- a/drivers/gpu/drm/drm_fops.c
+++ b/drivers/gpu/drm/drm_fops.c
@@ -45,7 +45,7 @@ EXPORT_SYMBOL(drm_global_mutex);

 static int drm_open_helper(struct file *filp, struct drm_minor *minor);

-static int drm_setup(struct drm_device * dev)
+static int drm_firstopen(struct drm_device * dev)
 {
int ret;

@@ -66,6 +66,57 @@ static int drm_setup(struct drm_device * dev)
 }

 /**
+ * drm_legacy_dev_reinit
+ *
+ * Reinitializes a legacy/ums drm device in it's lastclose function.
+ */
+static void drm_legacy_dev_reinit(struct drm_device *dev)
+{
+   if (drm_core_check_feature(dev, DRIVER_MODESET))
+   return;
+
+   dev->sigdata.lock = NULL;
+
+   dev->context_flag = 0;
+   dev->last_context = 0;
+   dev->if_version = 0;
+}
+
+void drm_lastclose(struct drm_device * dev)
+{
+   struct drm_vma_entry *vma, *vma_temp;
+
+   DRM_DEBUG("\n");
+
+   if (dev->driver->lastclose)
+   dev->driver->lastclose(dev);
+   DRM_DEBUG("driver lastclose completed\n");
+
+   if (dev->irq_enabled && !drm_core_check_feature(dev, DRIVER_MODESET))
+   drm_irq_uninstall(dev);
+
+   mutex_lock(&dev->struct_mutex);
+
+   drm_agp_clear(dev);
+
+   drm_legacy_sg_cleanup(dev);
+
+   /* Clear vma list (only built for debugging) */
+   list_for_each_entry_safe(vma, vma_temp, &dev->vmalist, head) {
+   list_del(&vma->head);
+   kfree(vma);
+   }
+
+   drm_legacy_dma_takedown(dev);
+
+   mutex_unlock(&dev->struct_mutex);
+
+   drm_legacy_dev_reinit(dev);
+
+   DRM_DEBUG("lastclose completed\n");
+}
+
+/**
  * Open file.
  *
  * \param inode device inode
@@ -81,31 +132,33 @@ int drm_open(struct inode *inode, struct file *filp)
struct drm_device *dev;
struct drm_minor *minor;
int retcode;
-   int need_setup = 0;

minor = drm_minor_acquire(iminor(inode));
if (IS_ERR(minor))
return PTR_ERR(minor);

dev = minor->dev;
-   if (!dev->open_count++)
-   need_setup = 1;

/* share address_space across all char-devs of a single device */
filp->f_mapping = dev->anon_inode->i_mapping;

+   if (!dev->open_count) {
+   retcode = drm_firstopen(dev);
+   if (retcode)
+   goto err_minor;
+   }
+   ++dev->open_count;
+
retcode = drm_open_helper(filp, minor);
if (retcode)
goto err_undo;
-   if (need_setup) {
-   retcode = drm_setup(dev);
-   if (retcode)
-   goto err_undo;
-   }
+
return 0;

 err_undo:
-   dev->open_count--;
+   if (!--dev->open_count)
+   drm_lastclose(dev);
+err_minor:
drm_minor_release(minor);
return retcode;
 }
@@ -346,67 +399,6 @@ static void drm_events_release(struct drm_file *file_priv)
 }

 /**
- * drm_legacy_dev_reinit
- *
- * Reinitializes a legacy/ums drm device in it's lastclose function.
- */
-static void drm_legacy_dev_reinit(struct drm_device *dev)
-{
-   if (drm_core_check_feature(dev, DRIVER_MODESET))
-   return;
-
-   dev->sigdata.lock = NULL;
-
-   dev->context_flag = 0;
-   dev->last_context = 0;
-   dev->if_version = 0;
-}
-
-/**
- * Take down the DRM device.
- *
- * \param dev DRM device structure.
- *
- * Frees every resource in \p dev.
- *
- * \sa drm_device
- */
-int drm_lastclose(struct drm_device * dev)
-{
-   struct drm_vma_entry *vma, *vma_temp;
-
-   DRM_DEBUG("\n");
-
-   if (dev->driver->lastclose)
-   dev->driver->lastclose(dev);
-   DRM_DEBUG("driver lastclose completed\n");
-
-   if (dev->irq_enabled && !drm_core_check_feature(dev, DRIVER_MODESET))
-   drm_irq_uninstall(dev);
-
-   mutex_lock(&dev->struct_mu

[PATCH 04/12] drm: extract legacy ctxbitmap flushing

2014-07-23 Thread David Herrmann
The ctxbitmap code is only used by legacy drivers so lets try to keep it
as separated as possible. Furthermore, the locking is non-obvious and
kinda weird with ctxlist_mutex *and* struct_mutex. Keeping all ctxbitmap
access in one file is much easier to review and makes drm_release() more
readable.

Signed-off-by: David Herrmann 
---
 drivers/gpu/drm/drm_context.c | 30 ++
 drivers/gpu/drm/drm_fops.c| 20 +---
 include/drm/drmP.h|  1 +
 3 files changed, 32 insertions(+), 19 deletions(-)

diff --git a/drivers/gpu/drm/drm_context.c b/drivers/gpu/drm/drm_context.c
index a4b017b..c045505 100644
--- a/drivers/gpu/drm/drm_context.c
+++ b/drivers/gpu/drm/drm_context.c
@@ -111,6 +111,36 @@ void drm_ctxbitmap_cleanup(struct drm_device * dev)
mutex_unlock(&dev->struct_mutex);
 }

+/**
+ * drm_ctxbitmap_flush() - Flush all contexts owned by a file
+ * @dev: DRM device to operate on
+ * @file: Open file to flush contexts for
+ *
+ * This iterates over all contexts on @dev and drops them if they're owned by
+ * @file. Note that after this call returns, new contexts might be added if
+ * the file is still alive.
+ */
+void drm_ctxbitmap_flush(struct drm_device *dev, struct drm_file *file)
+{
+   struct drm_ctx_list *pos, *tmp;
+
+   mutex_lock(&dev->ctxlist_mutex);
+
+   list_for_each_entry_safe(pos, tmp, &dev->ctxlist, head) {
+   if (pos->tag == file &&
+   pos->handle != DRM_KERNEL_CONTEXT) {
+   if (dev->driver->context_dtor)
+   dev->driver->context_dtor(dev, pos->handle);
+
+   drm_ctxbitmap_free(dev, pos->handle);
+   list_del(&pos->head);
+   kfree(pos);
+   }
+   }
+
+   mutex_unlock(&dev->ctxlist_mutex);
+}
+
 /*@}*/

 /**/
diff --git a/drivers/gpu/drm/drm_fops.c b/drivers/gpu/drm/drm_fops.c
index 8e73519..fb81d1c 100644
--- a/drivers/gpu/drm/drm_fops.c
+++ b/drivers/gpu/drm/drm_fops.c
@@ -452,25 +452,7 @@ int drm_release(struct inode *inode, struct file *filp)
if (dev->driver->driver_features & DRIVER_GEM)
drm_gem_release(dev, file_priv);

-   mutex_lock(&dev->ctxlist_mutex);
-   if (!list_empty(&dev->ctxlist)) {
-   struct drm_ctx_list *pos, *n;
-
-   list_for_each_entry_safe(pos, n, &dev->ctxlist, head) {
-   if (pos->tag == file_priv &&
-   pos->handle != DRM_KERNEL_CONTEXT) {
-   if (dev->driver->context_dtor)
-   dev->driver->context_dtor(dev,
- pos->handle);
-
-   drm_ctxbitmap_free(dev, pos->handle);
-
-   list_del(&pos->head);
-   kfree(pos);
-   }
-   }
-   }
-   mutex_unlock(&dev->ctxlist_mutex);
+   drm_ctxbitmap_flush(dev, file_priv);

mutex_lock(&dev->master_mutex);

diff --git a/include/drm/drmP.h b/include/drm/drmP.h
index d1730c5..d91e09f 100644
--- a/include/drm/drmP.h
+++ b/include/drm/drmP.h
@@ -1242,6 +1242,7 @@ extern int drm_rmctx(struct drm_device *dev, void *data,
 extern int drm_ctxbitmap_init(struct drm_device *dev);
 extern void drm_ctxbitmap_cleanup(struct drm_device *dev);
 extern void drm_ctxbitmap_free(struct drm_device *dev, int ctx_handle);
+extern void drm_ctxbitmap_flush(struct drm_device *dev, struct drm_file *file);

 extern int drm_setsareactx(struct drm_device *dev, void *data,
   struct drm_file *file_priv);
-- 
2.0.2



[PATCH 05/12] drm: drop i386 verification

2014-07-23 Thread David Herrmann
Linux doesn't run on i386, anymore. See:

commit d55c5a93db2d5fa95f233ab153f594365d95b777
Author: H. Peter Anvin 
Date:   Wed Nov 28 11:50:24 2012 -0800

x86, 386 removal: Remove CONFIG_CMPXCHG

All 486+ CPUs support CMPXCHG, so remove the fallback 386 support
code.

Furthermore, as the commit-message states, all 486+ CPUs support the
CMPXCHG instruction and thus even legacy DRM can run fine.

Drop the now superfluous "x86 == 3" check.

Signed-off-by: David Herrmann 
---
 drivers/gpu/drm/drm_fops.c | 4 
 1 file changed, 4 deletions(-)

diff --git a/drivers/gpu/drm/drm_fops.c b/drivers/gpu/drm/drm_fops.c
index fb81d1c..a402061 100644
--- a/drivers/gpu/drm/drm_fops.c
+++ b/drivers/gpu/drm/drm_fops.c
@@ -210,10 +210,6 @@ out_unlock:
  */
 static int drm_cpu_valid(void)
 {
-#if defined(__i386__)
-   if (boot_cpu_data.x86 == 3)
-   return 0;   /* No cmpxchg on a 386 */
-#endif
 #if defined(__sparc__) && !defined(__sparc_v9__)
return 0;   /* No cmpxchg before v9 sparc. */
 #endif
-- 
2.0.2



[PATCH 07/12] drm: drop redundant drm_file->is_master

2014-07-23 Thread David Herrmann
The drm_file->is_master field is redundant as it's equivalent to:
drm_file->master && drm_file->master == drm_file->minor->master

1) "=>"
  Whenever we set drm_file->is_master, we also set:
  drm_file->minor->master = drm_file->master;

  Whenever we clear drm_file->is_master, we also call:
  drm_master_put(&drm_file->minor->master);
  which implicitly clears it to NULL.

2) "<="
  minor->master cannot be set if it is non-NULL. Therefore, it stays as
  is unless a file drops it.

  If minor->master is NULL, it is only set by places that also adjust
  drm_file->is_master.

Therefore, we can safely drop is_master and replace it by an inline helper
that matches:
    drm_file->master && drm_file->master == drm_file->minor->master

Signed-off-by: David Herrmann 
---
 drivers/gpu/drm/drm_crtc.c |  2 +-
 drivers/gpu/drm/drm_drv.c  |  2 +-
 drivers/gpu/drm/drm_fops.c |  4 +---
 drivers/gpu/drm/drm_lock.c |  2 +-
 drivers/gpu/drm/drm_stub.c | 10 +++---
 drivers/gpu/drm/i915/i915_gem_execbuffer.c |  4 ++--
 drivers/gpu/drm/vmwgfx/vmwgfx_drv.c|  2 +-
 include/drm/drmP.h |  9 ++---
 8 files changed, 16 insertions(+), 19 deletions(-)

diff --git a/drivers/gpu/drm/drm_crtc.c b/drivers/gpu/drm/drm_crtc.c
index 1ccf5cb..dec0c77 100644
--- a/drivers/gpu/drm/drm_crtc.c
+++ b/drivers/gpu/drm/drm_crtc.c
@@ -3188,7 +3188,7 @@ int drm_mode_getfb(struct drm_device *dev,
r->bpp = fb->bits_per_pixel;
r->pitch = fb->pitches[0];
if (fb->funcs->create_handle) {
-   if (file_priv->is_master || capable(CAP_SYS_ADMIN) ||
+   if (drm_is_master(file_priv) || capable(CAP_SYS_ADMIN) ||
drm_is_control_client(file_priv)) {
ret = fb->funcs->create_handle(fb, file_priv,
   &r->handle);
diff --git a/drivers/gpu/drm/drm_drv.c b/drivers/gpu/drm/drm_drv.c
index 0cc1827..7aa8121 100644
--- a/drivers/gpu/drm/drm_drv.c
+++ b/drivers/gpu/drm/drm_drv.c
@@ -307,7 +307,7 @@ static int drm_ioctl_permit(u32 flags, struct drm_file 
*file_priv)
return -EACCES;

/* MASTER is only for master or control clients */
-   if (unlikely((flags & DRM_MASTER) && !file_priv->is_master &&
+   if (unlikely((flags & DRM_MASTER) && !drm_is_master(file_priv) &&
 !drm_is_control_client(file_priv)))
return -EACCES;

diff --git a/drivers/gpu/drm/drm_fops.c b/drivers/gpu/drm/drm_fops.c
index afba0bf..f65087e 100644
--- a/drivers/gpu/drm/drm_fops.c
+++ b/drivers/gpu/drm/drm_fops.c
@@ -286,7 +286,6 @@ static int drm_open_helper(struct file *filp, struct 
drm_minor *minor)
goto out_close;
}

-   priv->is_master = 1;
/* take another reference for the copy in the local file priv */
priv->master = drm_master_get(priv->minor->master);
priv->authenticated = 1;
@@ -452,7 +451,7 @@ int drm_release(struct inode *inode, struct file *filp)

mutex_lock(&dev->master_mutex);

-   if (file_priv->is_master) {
+   if (drm_is_master(file_priv)) {
struct drm_master *master = file_priv->master;
struct drm_file *temp;

@@ -488,7 +487,6 @@ int drm_release(struct inode *inode, struct file *filp)
/* drop the master reference held by the file priv */
if (file_priv->master)
drm_master_put(&file_priv->master);
-   file_priv->is_master = 0;
mutex_unlock(&dev->master_mutex);

mutex_lock(&dev->struct_mutex);
diff --git a/drivers/gpu/drm/drm_lock.c b/drivers/gpu/drm/drm_lock.c
index f645268..786401c 100644
--- a/drivers/gpu/drm/drm_lock.c
+++ b/drivers/gpu/drm/drm_lock.c
@@ -111,7 +111,7 @@ int drm_lock(struct drm_device *dev, void *data, struct 
drm_file *file_priv)
/* don't set the block all signals on the master process for now 
 * really probably not the correct answer but lets us debug xkb
 * xserver for now */
-   if (!file_priv->is_master) {
+   if (!drm_is_master(file_priv)) {
sigemptyset(&dev->sigmask);
sigaddset(&dev->sigmask, SIGSTOP);
sigaddset(&dev->sigmask, SIGTSTP);
diff --git a/drivers/gpu/drm/drm_stub.c b/drivers/gpu/drm/drm_stub.c
index 233ea20..18c9b3d 100644
--- a/drivers/gpu/drm/drm_stub.c
+++ b/drivers/gpu/drm/drm_stub.c
@@ -177,7 +177,7 @@ int drm_setmaster_ioctl(struct drm_device *dev, void *data,
int ret = 0;

mutex_lock(&dev->master_mutex);
-   if (file_priv->is_ma

[PATCH 06/12] drm: fix __alpha__ PCI lookup

2014-07-23 Thread David Herrmann
Testing the return value of list_entry() for NULL is a no-op (as it is
just a fancy container_of() / offsetof()). Drop the superfluous if-clause
and instead verify the actual root-node is available. This is probably
what it was meant to test for from the beginning, anyway.

Signed-off-by: David Herrmann 
---
 drivers/gpu/drm/drm_fops.c | 8 
 1 file changed, 4 insertions(+), 4 deletions(-)

diff --git a/drivers/gpu/drm/drm_fops.c b/drivers/gpu/drm/drm_fops.c
index a402061..afba0bf 100644
--- a/drivers/gpu/drm/drm_fops.c
+++ b/drivers/gpu/drm/drm_fops.c
@@ -330,11 +330,11 @@ static int drm_open_helper(struct file *filp, struct 
drm_minor *minor)
dev->hose = pci_dev->sysdata;
pci_dev_put(pci_dev);
}
-   if (!dev->hose) {
+
+   if (!dev->hose && pci_root_buses.next) {
struct pci_bus *b = list_entry(pci_root_buses.next,
-   struct pci_bus, node);
-   if (b)
-   dev->hose = b->sysdata;
+  struct pci_bus, node);
+   dev->hose = b->sysdata;
}
}
 #endif
-- 
2.0.2



[PATCH 08/12] drm: don't de-authenticate clients on master-close

2014-07-23 Thread David Herrmann
If an active DRM-Master closes its device, we deauthenticate all clients
on that master. However, if an inactive DRM-Master closes its device, we
do nothing. This is quite inconsistent and breaks several scenarios:

 1) If this was used as security mechanism, it fails horribly if a master
closes a device while VT switched away. Furthermore, none of the few
drivers using ->master_*() callbacks seems to require it, anyway.

 2) If you spawn weston (or any other non-UMS compositor) in background
while another compositor is active, both will get assigned to the
same "drm_master" object. If the foreground compositor now exits, all
clients of both the foreground AND background compositor will be
de-authenticated leading to unexpected behavior.

Stop this non-sense and keep clients authenticated. We don't do this when
dropping DRM-Master (i.e., switching VTs) so don't do it on active-close
either!

Signed-off-by: David Herrmann 
---
 drivers/gpu/drm/drm_fops.c | 13 ++---
 include/drm/drmP.h |  1 -
 2 files changed, 2 insertions(+), 12 deletions(-)

diff --git a/drivers/gpu/drm/drm_fops.c b/drivers/gpu/drm/drm_fops.c
index f65087e..ff0a13f 100644
--- a/drivers/gpu/drm/drm_fops.c
+++ b/drivers/gpu/drm/drm_fops.c
@@ -252,8 +252,7 @@ static int drm_open_helper(struct file *filp, struct 
drm_minor *minor)
priv->minor = minor;

/* for compatibility root is always authenticated */
-   priv->always_authenticated = capable(CAP_SYS_ADMIN);
-   priv->authenticated = priv->always_authenticated;
+   priv->authenticated = capable(CAP_SYS_ADMIN);
priv->lock_count = 0;

INIT_LIST_HEAD(&priv->lhead);
@@ -453,20 +452,12 @@ int drm_release(struct inode *inode, struct file *filp)

if (drm_is_master(file_priv)) {
struct drm_master *master = file_priv->master;
-   struct drm_file *temp;
-
-   mutex_lock(&dev->struct_mutex);
-   list_for_each_entry(temp, &dev->filelist, lhead) {
-   if ((temp->master == file_priv->master) &&
-   (temp != file_priv))
-   temp->authenticated = 
temp->always_authenticated;
-   }

/**
 * Since the master is disappearing, so is the
 * possibility to lock.
 */
-
+   mutex_lock(&dev->struct_mutex);
if (master->lock.hw_lock) {
if (dev->sigdata.lock == master->lock.hw_lock)
dev->sigdata.lock = NULL;
diff --git a/include/drm/drmP.h b/include/drm/drmP.h
index e1bb585..48d2fe7 100644
--- a/include/drm/drmP.h
+++ b/include/drm/drmP.h
@@ -385,7 +385,6 @@ struct drm_prime_file_private {

 /** File private data */
 struct drm_file {
-   unsigned always_authenticated :1;
unsigned authenticated :1;
/* true when the client has asked us to expose stereo 3D mode flags */
unsigned stereo_allowed :1;
-- 
2.0.2



[PATCH 09/12] drm: move module initialization to drm_stub.c

2014-07-23 Thread David Herrmann
Most of the new DRM management functions are nowadays in drm_stub.c. By
moving the core module initialization to drm_stub.c we can make several
global variables static and keep the stub-open helper local.

The core files now look like this:
  drm_stub.c: Core management
   drm_drv.c: Ioctl dispatcher
 drm_ioctl.c: Actual ioctl backends
  drm_fops.c: Char-dev file-operations

A follow-up patch will move what is left from drm_drv.c into drm_ioctl.c.

Signed-off-by: David Herrmann 
---
 drivers/gpu/drm/drm_drv.c  |  59 ---
 drivers/gpu/drm/drm_fops.c |  39 ---
 drivers/gpu/drm/drm_stub.c | 117 -
 include/drm/drmP.h |   4 --
 4 files changed, 115 insertions(+), 104 deletions(-)

diff --git a/drivers/gpu/drm/drm_drv.c b/drivers/gpu/drm/drm_drv.c
index 7aa8121..190df83 100644
--- a/drivers/gpu/drm/drm_drv.c
+++ b/drivers/gpu/drm/drm_drv.c
@@ -171,65 +171,6 @@ static const struct drm_ioctl_desc drm_ioctls[] = {

 #define DRM_CORE_IOCTL_COUNT   ARRAY_SIZE( drm_ioctls )

-/** File operations structure */
-static const struct file_operations drm_stub_fops = {
-   .owner = THIS_MODULE,
-   .open = drm_stub_open,
-   .llseek = noop_llseek,
-};
-
-static int __init drm_core_init(void)
-{
-   int ret = -ENOMEM;
-
-   drm_global_init();
-   drm_connector_ida_init();
-   idr_init(&drm_minors_idr);
-
-   if (register_chrdev(DRM_MAJOR, "drm", &drm_stub_fops))
-   goto err_p1;
-
-   drm_class = drm_sysfs_create(THIS_MODULE, "drm");
-   if (IS_ERR(drm_class)) {
-   printk(KERN_ERR "DRM: Error creating drm class.\n");
-   ret = PTR_ERR(drm_class);
-   goto err_p2;
-   }
-
-   drm_debugfs_root = debugfs_create_dir("dri", NULL);
-   if (!drm_debugfs_root) {
-   DRM_ERROR("Cannot create /sys/kernel/debug/dri\n");
-   ret = -1;
-   goto err_p3;
-   }
-
-   DRM_INFO("Initialized %s %d.%d.%d %s\n",
-CORE_NAME, CORE_MAJOR, CORE_MINOR, CORE_PATCHLEVEL, CORE_DATE);
-   return 0;
-err_p3:
-   drm_sysfs_destroy();
-err_p2:
-   unregister_chrdev(DRM_MAJOR, "drm");
-
-   idr_destroy(&drm_minors_idr);
-err_p1:
-   return ret;
-}
-
-static void __exit drm_core_exit(void)
-{
-   debugfs_remove(drm_debugfs_root);
-   drm_sysfs_destroy();
-
-   unregister_chrdev(DRM_MAJOR, "drm");
-
-   drm_connector_ida_destroy();
-   idr_destroy(&drm_minors_idr);
-}
-
-module_init(drm_core_init);
-module_exit(drm_core_exit);
-
 /**
  * Copy and IOCTL return string to user space
  */
diff --git a/drivers/gpu/drm/drm_fops.c b/drivers/gpu/drm/drm_fops.c
index ff0a13f..a3bf155 100644
--- a/drivers/gpu/drm/drm_fops.c
+++ b/drivers/gpu/drm/drm_fops.c
@@ -165,45 +165,6 @@ err_minor:
 EXPORT_SYMBOL(drm_open);

 /**
- * File \c open operation.
- *
- * \param inode device inode.
- * \param filp file pointer.
- *
- * Puts the dev->fops corresponding to the device minor number into
- * \p filp, call the \c open method, and restore the file operations.
- */
-int drm_stub_open(struct inode *inode, struct file *filp)
-{
-   struct drm_device *dev;
-   struct drm_minor *minor;
-   int err = -ENODEV;
-   const struct file_operations *new_fops;
-
-   DRM_DEBUG("\n");
-
-   mutex_lock(&drm_global_mutex);
-   minor = drm_minor_acquire(iminor(inode));
-   if (IS_ERR(minor))
-   goto out_unlock;
-
-   dev = minor->dev;
-   new_fops = fops_get(dev->driver->fops);
-   if (!new_fops)
-   goto out_release;
-
-   replace_fops(filp, new_fops);
-   if (filp->f_op->open)
-   err = filp->f_op->open(inode, filp);
-
-out_release:
-   drm_minor_release(minor);
-out_unlock:
-   mutex_unlock(&drm_global_mutex);
-   return err;
-}
-
-/**
  * Check whether DRI will run on this CPU.
  *
  * \return non-zero if the DRI will run on this CPU, or zero otherwise.
diff --git a/drivers/gpu/drm/drm_stub.c b/drivers/gpu/drm/drm_stub.c
index 18c9b3d..b249f14 100644
--- a/drivers/gpu/drm/drm_stub.c
+++ b/drivers/gpu/drm/drm_stub.c
@@ -26,6 +26,7 @@
  * DEALINGS IN THE SOFTWARE.
  */

+#include 
 #include 
 #include 
 #include 
@@ -61,10 +62,10 @@ module_param_named(timestamp_precision_usec, 
drm_timestamp_precision, int, 0600)
 module_param_named(timestamp_monotonic, drm_timestamp_monotonic, int, 0600);

 static DEFINE_SPINLOCK(drm_minor_lock);
-struct idr drm_minors_idr;
+static struct idr drm_minors_idr;

 struct class *drm_class;
-struct dentry *drm_debugfs_root;
+static struct dentry *drm_debugfs_root;

 int drm_err(const char *func, const char *format, ...)
 {
@@ -787,3 +788,115 @@ int drm_dev_set_unique(struct drm_device *dev, const char 
*fmt, ...)
return dev->unique ? 0 :

[PATCH 10/12] drm: merge drm_drv.c into drm_ioctl.c

2014-07-23 Thread David Herrmann
All that is left in drm_drv.c is ioctl management. Merge it into
drm_ioctl.c so we have all ioctl management in one file (and the name is
much more fitting).

Maybe we should now rename drm_stub.c to drm_drv.c again?

Signed-off-by: David Herrmann 
---
 drivers/gpu/drm/drm_drv.c   | 412 
 drivers/gpu/drm/drm_ioctl.c | 369 ++-
 2 files changed, 361 insertions(+), 420 deletions(-)
 delete mode 100644 drivers/gpu/drm/drm_drv.c

diff --git a/drivers/gpu/drm/drm_drv.c b/drivers/gpu/drm/drm_drv.c
deleted file mode 100644
index 190df83..000
--- a/drivers/gpu/drm/drm_drv.c
+++ /dev/null
@@ -1,412 +0,0 @@
-/**
- * \file drm_drv.c
- * Generic driver template
- *
- * \author Rickard E. (Rik) Faith 
- * \author Gareth Hughes 
- *
- * To use this template, you must at least define the following (samples
- * given for the MGA driver):
- *
- * \code
- * #define DRIVER_AUTHOR   "VA Linux Systems, Inc."
- *
- * #define DRIVER_NAME "mga"
- * #define DRIVER_DESC "Matrox G200/G400"
- * #define DRIVER_DATE "20001127"
- *
- * #define drm_x   mga_##x
- * \endcode
- */
-
-/*
- * Created: Thu Nov 23 03:10:50 2000 by gareth at valinux.com
- *
- * Copyright 1999, 2000 Precision Insight, Inc., Cedar Park, Texas.
- * Copyright 2000 VA Linux Systems, Inc., Sunnyvale, California.
- * All Rights Reserved.
- *
- * Permission is hereby granted, free of charge, to any person obtaining a
- * copy of this software and associated documentation files (the "Software"),
- * to deal in the Software without restriction, including without limitation
- * the rights to use, copy, modify, merge, publish, distribute, sublicense,
- * and/or sell copies of the Software, and to permit persons to whom the
- * Software is furnished to do so, subject to the following conditions:
- *
- * The above copyright notice and this permission notice (including the next
- * paragraph) shall be included in all copies or substantial portions of the
- * Software.
- *
- * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
- * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
- * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
- * VA LINUX SYSTEMS AND/OR ITS SUPPLIERS BE LIABLE FOR ANY CLAIM, DAMAGES OR
- * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
- * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
- * OTHER DEALINGS IN THE SOFTWARE.
- */
-
-#include 
-#include 
-#include 
-#include 
-#include 
-
-
-static int drm_version(struct drm_device *dev, void *data,
-  struct drm_file *file_priv);
-
-#define DRM_IOCTL_DEF(ioctl, _func, _flags) \
-   [DRM_IOCTL_NR(ioctl)] = {.cmd = ioctl, .func = _func, .flags = _flags, 
.cmd_drv = 0, .name = #ioctl}
-
-/** Ioctl table */
-static const struct drm_ioctl_desc drm_ioctls[] = {
-   DRM_IOCTL_DEF(DRM_IOCTL_VERSION, drm_version, 
DRM_UNLOCKED|DRM_RENDER_ALLOW),
-   DRM_IOCTL_DEF(DRM_IOCTL_GET_UNIQUE, drm_getunique, 0),
-   DRM_IOCTL_DEF(DRM_IOCTL_GET_MAGIC, drm_getmagic, 0),
-   DRM_IOCTL_DEF(DRM_IOCTL_IRQ_BUSID, drm_irq_by_busid, 
DRM_MASTER|DRM_ROOT_ONLY),
-   DRM_IOCTL_DEF(DRM_IOCTL_GET_MAP, drm_getmap, DRM_UNLOCKED),
-   DRM_IOCTL_DEF(DRM_IOCTL_GET_CLIENT, drm_getclient, DRM_UNLOCKED),
-   DRM_IOCTL_DEF(DRM_IOCTL_GET_STATS, drm_getstats, DRM_UNLOCKED),
-   DRM_IOCTL_DEF(DRM_IOCTL_GET_CAP, drm_getcap, 
DRM_UNLOCKED|DRM_RENDER_ALLOW),
-   DRM_IOCTL_DEF(DRM_IOCTL_SET_CLIENT_CAP, drm_setclientcap, 0),
-   DRM_IOCTL_DEF(DRM_IOCTL_SET_VERSION, drm_setversion, DRM_MASTER),
-
-   DRM_IOCTL_DEF(DRM_IOCTL_SET_UNIQUE, drm_setunique, 
DRM_AUTH|DRM_MASTER|DRM_ROOT_ONLY),
-   DRM_IOCTL_DEF(DRM_IOCTL_BLOCK, drm_noop, 
DRM_AUTH|DRM_MASTER|DRM_ROOT_ONLY),
-   DRM_IOCTL_DEF(DRM_IOCTL_UNBLOCK, drm_noop, 
DRM_AUTH|DRM_MASTER|DRM_ROOT_ONLY),
-   DRM_IOCTL_DEF(DRM_IOCTL_AUTH_MAGIC, drm_authmagic, DRM_AUTH|DRM_MASTER),
-
-   DRM_IOCTL_DEF(DRM_IOCTL_ADD_MAP, drm_addmap_ioctl, 
DRM_AUTH|DRM_MASTER|DRM_ROOT_ONLY),
-   DRM_IOCTL_DEF(DRM_IOCTL_RM_MAP, drm_rmmap_ioctl, DRM_AUTH),
-
-   DRM_IOCTL_DEF(DRM_IOCTL_SET_SAREA_CTX, drm_setsareactx, 
DRM_AUTH|DRM_MASTER|DRM_ROOT_ONLY),
-   DRM_IOCTL_DEF(DRM_IOCTL_GET_SAREA_CTX, drm_getsareactx, DRM_AUTH),
-
-   DRM_IOCTL_DEF(DRM_IOCTL_SET_MASTER, drm_setmaster_ioctl, DRM_ROOT_ONLY),
-   DRM_IOCTL_DEF(DRM_IOCTL_DROP_MASTER, drm_dropmaster_ioctl, 
DRM_ROOT_ONLY),
-
-   DRM_IOCTL_DEF(DRM_IOCTL_ADD_CTX, drm_addctx, DRM_AUTH|DRM_ROOT_ONLY),
-   DRM_IOCTL_DEF(DRM_IOCTL_RM_CTX, drm_rmctx, 
DRM_AUTH|DRM_MASTER|DRM_ROOT_ONLY),
-   DRM_IOCTL_DEF(DRM_IOCTL_MOD_CTX, drm_noop, 
DRM_AUTH|DRM_MASTER|DRM_ROOT_ONLY),
-   DRM_IOCTL_DEF(DRM_IOCTL_GET_CTX, drm_getctx, DRM_AUTH),
-   DRM_IOCTL_DEF(DRM_IOCTL_S

[PATCH 11/12] drm: make minor->index available early

2014-07-23 Thread David Herrmann
Instead of allocating the minor-index during registration, we now do this
during allocation. This way, debug-messages between minor-allocation and
minor-registration will now use the correct minor instead of 0. Same is
done for unregistration vs. free, so debug-messages between
device-shutdown and device-destruction show proper indices.

Even though minor-indices are allocated early, we don't enable minor
lookup early. Instead, we keep the entry set to NULL and replace it during
registration / unregistration. This way, the index is allocated but lookup
only works if registered.

Signed-off-by: David Herrmann 
---
 drivers/gpu/drm/drm_stub.c | 84 +-
 1 file changed, 46 insertions(+), 38 deletions(-)

diff --git a/drivers/gpu/drm/drm_stub.c b/drivers/gpu/drm/drm_stub.c
index b249f14..8b24db5 100644
--- a/drivers/gpu/drm/drm_stub.c
+++ b/drivers/gpu/drm/drm_stub.c
@@ -256,6 +256,8 @@ static struct drm_minor **drm_minor_get_slot(struct 
drm_device *dev,
 static int drm_minor_alloc(struct drm_device *dev, unsigned int type)
 {
struct drm_minor *minor;
+   unsigned long flags;
+   int r;

minor = kzalloc(sizeof(*minor), GFP_KERNEL);
if (!minor)
@@ -264,57 +266,68 @@ static int drm_minor_alloc(struct drm_device *dev, 
unsigned int type)
minor->type = type;
minor->dev = dev;

+   idr_preload(GFP_KERNEL);
+   spin_lock_irqsave(&drm_minor_lock, flags);
+   r = idr_alloc(&drm_minors_idr,
+ NULL,
+ 64 * type,
+ 64 * (type + 1),
+ GFP_NOWAIT);
+   spin_unlock_irqrestore(&drm_minor_lock, flags);
+   idr_preload_end();
+
+   if (r < 0)
+   goto err_free;
+
+   minor->index = r;
+
*drm_minor_get_slot(dev, type) = minor;
return 0;
+
+err_free:
+   kfree(minor);
+   return r;
 }

 static void drm_minor_free(struct drm_device *dev, unsigned int type)
 {
-   struct drm_minor **slot;
+   struct drm_minor **slot, *minor;
+   unsigned long flags;

slot = drm_minor_get_slot(dev, type);
-   if (*slot) {
-   drm_mode_group_destroy(&(*slot)->mode_group);
-   kfree(*slot);
-   *slot = NULL;
-   }
+   minor = *slot;
+   if (!minor)
+   return;
+
+   drm_mode_group_destroy(&minor->mode_group);
+
+   spin_lock_irqsave(&drm_minor_lock, flags);
+   idr_remove(&drm_minors_idr, minor->index);
+   spin_unlock_irqrestore(&drm_minor_lock, flags);
+
+   kfree(minor);
+   *slot = NULL;
 }

 static int drm_minor_register(struct drm_device *dev, unsigned int type)
 {
-   struct drm_minor *new_minor;
+   struct drm_minor *minor;
unsigned long flags;
int ret;
-   int minor_id;

DRM_DEBUG("\n");

-   new_minor = *drm_minor_get_slot(dev, type);
-   if (!new_minor)
+   minor = *drm_minor_get_slot(dev, type);
+   if (!minor)
return 0;

-   idr_preload(GFP_KERNEL);
-   spin_lock_irqsave(&drm_minor_lock, flags);
-   minor_id = idr_alloc(&drm_minors_idr,
-NULL,
-64 * type,
-64 * (type + 1),
-GFP_NOWAIT);
-   spin_unlock_irqrestore(&drm_minor_lock, flags);
-   idr_preload_end();
-
-   if (minor_id < 0)
-   return minor_id;
-
-   new_minor->index = minor_id;
-
-   ret = drm_debugfs_init(new_minor, minor_id, drm_debugfs_root);
+   ret = drm_debugfs_init(minor, minor->index, drm_debugfs_root);
if (ret) {
DRM_ERROR("DRM: Failed to initialize /sys/kernel/debug/dri.\n");
-   goto err_id;
+   return ret;
}

-   ret = drm_sysfs_device_add(new_minor);
+   ret = drm_sysfs_device_add(minor);
if (ret) {
DRM_ERROR("DRM: Error sysfs_device_add.\n");
goto err_debugfs;
@@ -322,19 +335,14 @@ static int drm_minor_register(struct drm_device *dev, 
unsigned int type)

/* replace NULL with @minor so lookups will succeed from now on */
spin_lock_irqsave(&drm_minor_lock, flags);
-   idr_replace(&drm_minors_idr, new_minor, new_minor->index);
+   idr_replace(&drm_minors_idr, minor, minor->index);
spin_unlock_irqrestore(&drm_minor_lock, flags);

-   DRM_DEBUG("new minor assigned %d\n", minor_id);
+   DRM_DEBUG("new minor registered %d\n", minor->index);
return 0;

 err_debugfs:
-   drm_debugfs_cleanup(new_minor);
-err_id:
-   spin_lock_irqsave(&drm_minor_lock, flags);
-   idr_remove(&drm_minors_idr, minor_id);
-   spin_unlock_irqrestore(&drm_minor_lock, flags);
-   new_minor->

[PATCH 12/12] drm: make sysfs device always available for minors

2014-07-23 Thread David Herrmann
For each minor we allocate a sysfs device as minor->kdev. Currently, this
is allocated and registered in drm_minor_register(). This makes it
impossible to add sysfs-attributes to the device before it is registered.
Therefore, they are not added atomically, nor can we move device_add()
*after* ->load() is called.

This patch makes minor->kdev available early, but only adds the device
during minor-registration.

Signed-off-by: David Herrmann 
---
 drivers/gpu/drm/drm_stub.c  | 22 ---
 drivers/gpu/drm/drm_sysfs.c | 90 +++--
 include/drm/drmP.h  |  3 +-
 3 files changed, 54 insertions(+), 61 deletions(-)

diff --git a/drivers/gpu/drm/drm_stub.c b/drivers/gpu/drm/drm_stub.c
index 8b24db5..09c6bfb 100644
--- a/drivers/gpu/drm/drm_stub.c
+++ b/drivers/gpu/drm/drm_stub.c
@@ -281,9 +281,19 @@ static int drm_minor_alloc(struct drm_device *dev, 
unsigned int type)

minor->index = r;

+   minor->kdev = drm_sysfs_minor_alloc(minor);
+   if (IS_ERR(minor->kdev)) {
+   r = PTR_ERR(minor->kdev);
+   goto err_index;
+   }
+
*drm_minor_get_slot(dev, type) = minor;
return 0;

+err_index:
+   spin_lock_irqsave(&drm_minor_lock, flags);
+   idr_remove(&drm_minors_idr, minor->index);
+   spin_unlock_irqrestore(&drm_minor_lock, flags);
 err_free:
kfree(minor);
return r;
@@ -300,6 +310,7 @@ static void drm_minor_free(struct drm_device *dev, unsigned 
int type)
return;

drm_mode_group_destroy(&minor->mode_group);
+   put_device(minor->kdev);

spin_lock_irqsave(&drm_minor_lock, flags);
idr_remove(&drm_minors_idr, minor->index);
@@ -327,11 +338,9 @@ static int drm_minor_register(struct drm_device *dev, 
unsigned int type)
return ret;
}

-   ret = drm_sysfs_device_add(minor);
-   if (ret) {
-   DRM_ERROR("DRM: Error sysfs_device_add.\n");
+   ret = device_add(minor->kdev);
+   if (ret)
goto err_debugfs;
-   }

/* replace NULL with @minor so lookups will succeed from now on */
spin_lock_irqsave(&drm_minor_lock, flags);
@@ -352,7 +361,7 @@ static void drm_minor_unregister(struct drm_device *dev, 
unsigned int type)
unsigned long flags;

minor = *drm_minor_get_slot(dev, type);
-   if (!minor || !minor->kdev)
+   if (!minor || !device_is_registered(minor->kdev))
return;

/* replace @minor with NULL so lookups will fail from now on */
@@ -360,8 +369,9 @@ static void drm_minor_unregister(struct drm_device *dev, 
unsigned int type)
idr_replace(&drm_minors_idr, NULL, minor->index);
spin_unlock_irqrestore(&drm_minor_lock, flags);

+   device_del(minor->kdev);
+   dev_set_drvdata(minor->kdev, NULL); /* safety belt */
drm_debugfs_cleanup(minor);
-   drm_sysfs_device_remove(minor);
 }

 /**
diff --git a/drivers/gpu/drm/drm_sysfs.c b/drivers/gpu/drm/drm_sysfs.c
index 7827dad..ab1a5f6 100644
--- a/drivers/gpu/drm/drm_sysfs.c
+++ b/drivers/gpu/drm/drm_sysfs.c
@@ -493,71 +493,55 @@ static void drm_sysfs_release(struct device *dev)
 }

 /**
- * drm_sysfs_device_add - adds a class device to sysfs for a character driver
- * @dev: DRM device to be added
- * @head: DRM head in question
+ * drm_sysfs_minor_alloc() - Allocate sysfs device for given minor
+ * @minor: minor to allocate sysfs device for
  *
- * Add a DRM device to the DRM's device model class.  We use @dev's PCI device
- * as the parent for the Linux device, and make sure it has a file containing
- * the driver we're using (for userspace compatibility).
+ * This allocates a new sysfs device for @minor and returns it. The device is
+ * not registered nor linked. The caller has to use device_add() and
+ * device_del() to register and unregister it.
+ *
+ * Note that dev_get_drvdata() on the new device will return the minor.
+ * However, the device does not hold a ref-count to the minor nor to the
+ * underlying drm_device. This is unproblematic as long as you access the
+ * private data only in sysfs callbacks. device_del() disables those
+ * synchronously, so they cannot be called after you cleanup a minor.
  */
-int drm_sysfs_device_add(struct drm_minor *minor)
+struct device *drm_sysfs_minor_alloc(struct drm_minor *minor)
 {
-   char *minor_str;
+   const char *minor_str;
+   struct device *kdev;
int r;

if (minor->type == DRM_MINOR_CONTROL)
minor_str = "controlD%d";
-else if (minor->type == DRM_MINOR_RENDER)
-minor_str = "renderD%d";
-else
-minor_str = "card%d";
-
-   minor->kdev = kzalloc(sizeof(*minor->kdev), GFP_KERNEL);
-   if (!minor->kdev) {
-   r = -ENOMEM;
-

[PATCH 10/12] drm: merge drm_drv.c into drm_ioctl.c

2014-07-23 Thread David Herrmann
Hi

On Wed, Jul 23, 2014 at 5:26 PM, David Herrmann  
wrote:
> All that is left in drm_drv.c is ioctl management. Merge it into
> drm_ioctl.c so we have all ioctl management in one file (and the name is
> much more fitting).
>
> Maybe we should now rename drm_stub.c to drm_drv.c again?
>
> Signed-off-by: David Herrmann 

This patch is missing:

diff --git a/drivers/gpu/drm/Makefile b/drivers/gpu/drm/Makefile
index 61d9e9c..9dd9db9 100644
--- a/drivers/gpu/drm/Makefile
+++ b/drivers/gpu/drm/Makefile
@@ -6,7 +6,7 @@ ccflags-y := -Iinclude/drm
drm-y := drm_auth.o drm_buffer.o drm_bufs.o drm_cache.o \
drm_context.o drm_dma.o \
- drm_drv.o drm_fops.o drm_gem.o drm_ioctl.o drm_irq.o \
+ drm_fops.o drm_gem.o drm_ioctl.o drm_irq.o \
drm_lock.o drm_memory.o drm_stub.o drm_vm.o \
drm_agpsupport.o drm_scatter.o drm_pci.o \
drm_platform.o drm_sysfs.o drm_hashtab.o drm_mm.o \


Thanks
David

> ---
>  drivers/gpu/drm/drm_drv.c   | 412 
> 
>  drivers/gpu/drm/drm_ioctl.c | 369 ++-
>  2 files changed, 361 insertions(+), 420 deletions(-)
>  delete mode 100644 drivers/gpu/drm/drm_drv.c
>
> diff --git a/drivers/gpu/drm/drm_drv.c b/drivers/gpu/drm/drm_drv.c
> deleted file mode 100644
> index 190df83..000
> --- a/drivers/gpu/drm/drm_drv.c
> +++ /dev/null
> @@ -1,412 +0,0 @@
> -/**
> - * \file drm_drv.c
> - * Generic driver template
> - *
> - * \author Rickard E. (Rik) Faith 
> - * \author Gareth Hughes 
> - *
> - * To use this template, you must at least define the following (samples
> - * given for the MGA driver):
> - *
> - * \code
> - * #define DRIVER_AUTHOR   "VA Linux Systems, Inc."
> - *
> - * #define DRIVER_NAME "mga"
> - * #define DRIVER_DESC "Matrox G200/G400"
> - * #define DRIVER_DATE "20001127"
> - *
> - * #define drm_x   mga_##x
> - * \endcode
> - */
> -
> -/*
> - * Created: Thu Nov 23 03:10:50 2000 by gareth at valinux.com
> - *
> - * Copyright 1999, 2000 Precision Insight, Inc., Cedar Park, Texas.
> - * Copyright 2000 VA Linux Systems, Inc., Sunnyvale, California.
> - * All Rights Reserved.
> - *
> - * Permission is hereby granted, free of charge, to any person obtaining a
> - * copy of this software and associated documentation files (the "Software"),
> - * to deal in the Software without restriction, including without limitation
> - * the rights to use, copy, modify, merge, publish, distribute, sublicense,
> - * and/or sell copies of the Software, and to permit persons to whom the
> - * Software is furnished to do so, subject to the following conditions:
> - *
> - * The above copyright notice and this permission notice (including the next
> - * paragraph) shall be included in all copies or substantial portions of the
> - * Software.
> - *
> - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
> - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
> - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
> - * VA LINUX SYSTEMS AND/OR ITS SUPPLIERS BE LIABLE FOR ANY CLAIM, DAMAGES OR
> - * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
> - * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
> - * OTHER DEALINGS IN THE SOFTWARE.
> - */
> -
> -#include 
> -#include 
> -#include 
> -#include 
> -#include 
> -
> -
> -static int drm_version(struct drm_device *dev, void *data,
> -  struct drm_file *file_priv);
> -
> -#define DRM_IOCTL_DEF(ioctl, _func, _flags) \
> -   [DRM_IOCTL_NR(ioctl)] = {.cmd = ioctl, .func = _func, .flags = 
> _flags, .cmd_drv = 0, .name = #ioctl}
> -
> -/** Ioctl table */
> -static const struct drm_ioctl_desc drm_ioctls[] = {
> -   DRM_IOCTL_DEF(DRM_IOCTL_VERSION, drm_version, 
> DRM_UNLOCKED|DRM_RENDER_ALLOW),
> -   DRM_IOCTL_DEF(DRM_IOCTL_GET_UNIQUE, drm_getunique, 0),
> -   DRM_IOCTL_DEF(DRM_IOCTL_GET_MAGIC, drm_getmagic, 0),
> -   DRM_IOCTL_DEF(DRM_IOCTL_IRQ_BUSID, drm_irq_by_busid, 
> DRM_MASTER|DRM_ROOT_ONLY),
> -   DRM_IOCTL_DEF(DRM_IOCTL_GET_MAP, drm_getmap, DRM_UNLOCKED),
> -   DRM_IOCTL_DEF(DRM_IOCTL_GET_CLIENT, drm_getclient, DRM_UNLOCKED),
> -   DRM_IOCTL_DEF(DRM_IOCTL_GET_STATS, drm_getstats, DRM_UNLOCKED),
> -   DRM_IOCTL_DEF(DRM_IOCTL_GET_CAP, drm_getcap, 
> DRM_UNLOCKED|DRM_RENDER_ALLOW),
> -   DRM_IOCTL_DEF(DRM_IOCTL_SET_CLIENT_CAP, drm_setclientcap, 0),
> -   DRM_IOCTL_DEF(DRM_IOCTL_SET_VERSION, drm_setversion, DRM_MASTER),
> -
> -   DRM_IOCTL_DEF(DRM_IOCTL_SET_UNIQUE, drm_setunique, 
> DRM_AUTH|DRM_MASTER|DRM_ROOT_ON

[PATCH] [rfc] drm: close race in connector registration

2014-07-24 Thread David Herrmann
Hi

On Thu, Jul 24, 2014 at 3:53 AM, Dave Airlie  wrote:
> From: Dave Airlie 
>
> Daniel pointed out with hotplug that userspace could be trying to oops us
> as root for lols, and that to be correct we shouldn't register the object
> with the idr before we have fully set the connector object up.
>
> His proposed solution was a lot more life changing, this seemed like a simpler
> proposition to me, get the connector object id from the idr, but don't
> register the object until the drm_connector_register callback.
>
> The open question is whether the drm_mode_object_register needs a bigger lock
> than just the idr one, but I can't see why it would, but I can be locking
> challenged.
>
> Signed-off-by: Dave Airlie 
> ---
>  drivers/gpu/drm/drm_crtc.c | 25 +
>  1 file changed, 21 insertions(+), 4 deletions(-)
>
> diff --git a/drivers/gpu/drm/drm_crtc.c b/drivers/gpu/drm/drm_crtc.c
> index 1ccf5cb..9f8cc1a 100644
> --- a/drivers/gpu/drm/drm_crtc.c
> +++ b/drivers/gpu/drm/drm_crtc.c
> @@ -376,13 +376,14 @@ EXPORT_SYMBOL(drm_get_format_name);
>   * New unique (relative to other objects in @dev) integer identifier for the
>   * object.
>   */
> -int drm_mode_object_get(struct drm_device *dev,
> -   struct drm_mode_object *obj, uint32_t obj_type)
> +static int drm_mode_object_get_noreg(struct drm_device *dev,
> +struct drm_mode_object *obj, uint32_t 
> obj_type,
> +bool noreg)
>  {
> int ret;
>
> mutex_lock(&dev->mode_config.idr_mutex);
> -   ret = idr_alloc(&dev->mode_config.crtc_idr, obj, 1, 0, GFP_KERNEL);
> +   ret = idr_alloc(&dev->mode_config.crtc_idr, noreg ? NULL : obj, 1, 0, 
> GFP_KERNEL);
> if (ret >= 0) {
> /*
>  * Set up the object linking under the protection of the idr
> @@ -396,6 +397,20 @@ int drm_mode_object_get(struct drm_device *dev,
> return ret < 0 ? ret : 0;
>  }
>
> +int drm_mode_object_get(struct drm_device *dev,
> +   struct drm_mode_object *obj, uint32_t obj_type)
> +{
> +   return drm_mode_object_get_noreg(dev, obj, obj_type, false);
> +}
> +
> +static void drm_mode_object_register(struct drm_device *dev,
> +struct drm_mode_object *obj)
> +{
> +   mutex_lock(&dev->mode_config.idr_mutex);
> +   idr_replace(&dev->mode_config.crtc_idr, obj, obj->id);
> +   mutex_unlock(&dev->mode_config.idr_mutex);
> +}
> +
>  /**
>   * drm_mode_object_put - free a modeset identifer
>   * @dev: DRM device
> @@ -849,7 +864,7 @@ int drm_connector_init(struct drm_device *dev,
>
> drm_modeset_lock_all(dev);
>
> -   ret = drm_mode_object_get(dev, &connector->base, 
> DRM_MODE_OBJECT_CONNECTOR);
> +   ret = drm_mode_object_get_noreg(dev, &connector->base, 
> DRM_MODE_OBJECT_CONNECTOR, true);
> if (ret)
> goto out_unlock;
>
> @@ -942,6 +957,8 @@ int drm_connector_register(struct drm_connector 
> *connector)
>  {
> int ret;
>
> +   drm_mode_object_register(connector->dev, &connector->base);
> +

This is the same we do for minor-objects, so fine with me. I'd prefer
if the registration is done last in drm_connector_register(), not
first, but I'm not sure the debugfs hooks work without the connector
available in the lookup tables. Maybe worth a try.

Maybe you also want to do the reverse in drm_connector_unregister()?
Making sure no user-space call can look them up anymore.

This patch is:
Reviewed-by: David Herrmann 

Thanks
David

> ret = drm_sysfs_connector_add(connector);
> if (ret)
> return ret;
> --
> 1.9.3
>
> ___
> dri-devel mailing list
> dri-devel at lists.freedesktop.org
> http://lists.freedesktop.org/mailman/listinfo/dri-devel


[PATCH] [rfc] drm: close race in connector registration

2014-07-24 Thread David Herrmann
Hi

On Thu, Jul 24, 2014 at 10:49 AM, Dave Airlie  wrote:
>>
>> This is the same we do for minor-objects, so fine with me. I'd prefer
>> if the registration is done last in drm_connector_register(), not
>> first, but I'm not sure the debugfs hooks work without the connector
>> available in the lookup tables. Maybe worth a try.
>
> I was worried sysfs registration would trigger something in userspace
> to life, which wuold then fail because the connector wasn't there.

Good point. So all fine with me the way it is.

Thanks
David


[PATCH 03/12] drm: call ->firstopen() before ->open()

2014-07-24 Thread David Herrmann
Hi

On Wed, Jul 23, 2014 at 9:25 PM, Daniel Vetter  wrote:
> On Wed, Jul 23, 2014 at 05:26:38PM +0200, David Herrmann wrote:
>> Lets order things correctly:
>>  ->load()
>>->fistopen()
>>  ->open()
>>  ->close()
>>->lastclose()
>>  ->unload()
>>
>> This doesn't change much as only savage and radeon use ->firstopen() and
>> they just do map-initialization. Therefore, the global drm mutex makes
>> sure there cannot be any other f_op between ->open() and ->firstopen().
>> However, once we get rid of that lock, we really want ->firstopen() to
>> initialize the device before ->open() is called.
>>
>> Furthermore, this fixes the clean-up path in drm_open(). We currently
>> don't cleanup the drm_file object if ->firstopen() fails.
>>
>> Signed-off-by: David Herrmann 
>> ---
>>  drivers/gpu/drm/drm_fops.c | 139 
>> +
>>  include/drm/drmP.h |   2 +-
>>  2 files changed, 66 insertions(+), 75 deletions(-)
>>
>> diff --git a/drivers/gpu/drm/drm_fops.c b/drivers/gpu/drm/drm_fops.c
>> index 021fe5d..8e73519 100644
>> --- a/drivers/gpu/drm/drm_fops.c
>> +++ b/drivers/gpu/drm/drm_fops.c
>> @@ -45,7 +45,7 @@ EXPORT_SYMBOL(drm_global_mutex);
>>
>>  static int drm_open_helper(struct file *filp, struct drm_minor *minor);
>>
>> -static int drm_setup(struct drm_device * dev)
>> +static int drm_firstopen(struct drm_device * dev)
>
> All the stuff in here is only for legacy drivers. Imo we should rename
> this to drm_legacy_setup and hide it harder.
>
> Also touching the init ordering for ums drivers is a bit risky, I'd advise
> against it. firstopen is officially dead for kms driver and really there's
> nothing legit you can do in there. imx abused until they've switched over
> to the component framework.
>
> I'd just drop this one tbh.

I did a driver audit when writing this patch, there're only 2 drivers
using firstopen:

 * radeon_cp: sets two fields of dev_private and calls drm_addmap() on
those. In lastclose(), it calls drm_rmmap()
 * savage: sets several fields in dev_private, calls
arch_phys_wc_add() for some regions and requests a drm-map for those
via drm_addmap(). On lastclose(), it reverts exactly those steps.

Taking into account that firstopen() just runs with drm_device
context, not with drm_file context, I really think we should be
calling it _before_ doing ->open(). I even think the drivers would
fail horribly if we don't do this patch and some other user-context
sneaks in between both calls (currently impossible thanks to
drm_global_mutex).

Both ->firstopen() callbacks are fairly trivial. In favor of making
the error-paths work in drm_open() I'd really like to get this in.
This patch is preparing for my drm_file rework that can make
drm_dev_unregister() stop all open files immediately.

But I honestly don't care much for UMS drivers, so if you NACK this,
I'd just ignore the error code and add a comment that we don't do
error-handling for UMS.

Cheers
David


[PATCH 04/12] drm: extract legacy ctxbitmap flushing

2014-07-24 Thread David Herrmann
Hi

On Wed, Jul 23, 2014 at 9:26 PM, Daniel Vetter  wrote:
> On Wed, Jul 23, 2014 at 05:26:39PM +0200, David Herrmann wrote:
>> The ctxbitmap code is only used by legacy drivers so lets try to keep it
>> as separated as possible. Furthermore, the locking is non-obvious and
>> kinda weird with ctxlist_mutex *and* struct_mutex. Keeping all ctxbitmap
>> access in one file is much easier to review and makes drm_release() more
>> readable.
>>
>> Signed-off-by: David Herrmann 
>
> I've started to sprinkle _legacy_ over all the functions only used for
> non-kms drivers, so that the dragon dungeons are clearly marked off. With
> that this is Reviewed-by: Daniel Vetter .

Yeah, that sounds good. But I'd prefer if we keep this patch as-is and
I will send a follow-up which renames all "drm_ctxbitmap_*" functions
to "drm_legacy_ctxbitmap_*". All those are internal to DRM-core so I
can rename them all together and add drivers/gpu/drm/drm-legacy.h.

Comments?
David


[PATCH 11/12] drm: make minor->index available early

2014-07-24 Thread David Herrmann
Hi

On Thu, Jul 24, 2014 at 12:03 PM, Daniel Vetter  wrote:
> On Wed, Jul 23, 2014 at 05:26:46PM +0200, David Herrmann wrote:
>> Instead of allocating the minor-index during registration, we now do this
>> during allocation. This way, debug-messages between minor-allocation and
>> minor-registration will now use the correct minor instead of 0. Same is
>> done for unregistration vs. free, so debug-messages between
>> device-shutdown and device-destruction show proper indices.
>>
>> Even though minor-indices are allocated early, we don't enable minor
>> lookup early. Instead, we keep the entry set to NULL and replace it during
>> registration / unregistration. This way, the index is allocated but lookup
>> only works if registered.
>>
>> Signed-off-by: David Herrmann 
>> ---
>>  drivers/gpu/drm/drm_stub.c | 84 
>> +-
>>  1 file changed, 46 insertions(+), 38 deletions(-)
>>
>> diff --git a/drivers/gpu/drm/drm_stub.c b/drivers/gpu/drm/drm_stub.c
>> index b249f14..8b24db5 100644
>> --- a/drivers/gpu/drm/drm_stub.c
>> +++ b/drivers/gpu/drm/drm_stub.c
>> @@ -256,6 +256,8 @@ static struct drm_minor **drm_minor_get_slot(struct 
>> drm_device *dev,
>>  static int drm_minor_alloc(struct drm_device *dev, unsigned int type)
>>  {
>>   struct drm_minor *minor;
>> + unsigned long flags;
>> + int r;
>>
>>   minor = kzalloc(sizeof(*minor), GFP_KERNEL);
>>   if (!minor)
>> @@ -264,57 +266,68 @@ static int drm_minor_alloc(struct drm_device *dev, 
>> unsigned int type)
>>   minor->type = type;
>>   minor->dev = dev;
>>
>> + idr_preload(GFP_KERNEL);
>> + spin_lock_irqsave(&drm_minor_lock, flags);
>> + r = idr_alloc(&drm_minors_idr,
>> +   NULL,
>> +   64 * type,
>> +   64 * (type + 1),
>> +   GFP_NOWAIT);
>> + spin_unlock_irqrestore(&drm_minor_lock, flags);
>> + idr_preload_end();
>> +
>> + if (r < 0)
>> + goto err_free;
>> +
>> + minor->index = r;
>> +
>>   *drm_minor_get_slot(dev, type) = minor;
>>   return 0;
>> +
>> +err_free:
>> + kfree(minor);
>> + return r;
>>  }
>>
>>  static void drm_minor_free(struct drm_device *dev, unsigned int type)
>>  {
>> - struct drm_minor **slot;
>> + struct drm_minor **slot, *minor;
>> + unsigned long flags;
>>
>>   slot = drm_minor_get_slot(dev, type);
>> - if (*slot) {
>> - drm_mode_group_destroy(&(*slot)->mode_group);
>> - kfree(*slot);
>> - *slot = NULL;
>> - }
>> + minor = *slot;
>> + if (!minor)
>> + return;
>> +
>> + drm_mode_group_destroy(&minor->mode_group);
>> +
>> + spin_lock_irqsave(&drm_minor_lock, flags);
>> + idr_remove(&drm_minors_idr, minor->index);
>> + spin_unlock_irqrestore(&drm_minor_lock, flags);
>
> I don't understand why you do the idr removal in stages too. Otherwise
> this looks good.

If you call drm_minor_unregister(), we now disable lookup but keep
minor->index. If I also released the ID, a new drm_minor might get
access to it before we call drm_minor_free on the old one. This might
cause misleading debug-messages as both minor objects have the same
index. This is not really a problem, but kinda ugly.

> Aside: If two drivers load concurrently (i.e. in the brave new world
> withou drm_global_mutex) we might end up with interleaved minor ids. Dunno
> whether we'll care since userspace should use udev/sysfs lookups anyway.
> igt sometimes doesn't ;-)

I did post a patch some time ago that makes minor-ID allocations
predictable. I got a NACK from you, so this one is one you ;) But I
agree, we really should fix user-space instead of making random IDs
predictable.

Thanks
David


[PATCH 12/12] drm: make sysfs device always available for minors

2014-07-24 Thread David Herrmann
Hi

On Thu, Jul 24, 2014 at 12:36 PM, Daniel Vetter  wrote:
> On Wed, Jul 23, 2014 at 05:26:47PM +0200, David Herrmann wrote:
>> For each minor we allocate a sysfs device as minor->kdev. Currently, this
>> is allocated and registered in drm_minor_register(). This makes it
>> impossible to add sysfs-attributes to the device before it is registered.
>> Therefore, they are not added atomically, nor can we move device_add()
>> *after* ->load() is called.
>>
>> This patch makes minor->kdev available early, but only adds the device
>> during minor-registration.
>>
>> Signed-off-by: David Herrmann 
>
> Some diff got confused with this one. One comment below, but this is
>
> Reviewed-by: Daniel Vetter 
>
>> ---
>>  drivers/gpu/drm/drm_stub.c  | 22 ---
>>  drivers/gpu/drm/drm_sysfs.c | 90 
>> +++--
>>  include/drm/drmP.h  |  3 +-
>>  3 files changed, 54 insertions(+), 61 deletions(-)
>>
>> diff --git a/drivers/gpu/drm/drm_stub.c b/drivers/gpu/drm/drm_stub.c
>> index 8b24db5..09c6bfb 100644
>> --- a/drivers/gpu/drm/drm_stub.c
>> +++ b/drivers/gpu/drm/drm_stub.c
>> @@ -281,9 +281,19 @@ static int drm_minor_alloc(struct drm_device *dev, 
>> unsigned int type)
>>
>>   minor->index = r;
>>
>> + minor->kdev = drm_sysfs_minor_alloc(minor);
>> + if (IS_ERR(minor->kdev)) {
>> + r = PTR_ERR(minor->kdev);
>> + goto err_index;
>> + }
>> +
>>   *drm_minor_get_slot(dev, type) = minor;
>>   return 0;
>>
>> +err_index:
>> + spin_lock_irqsave(&drm_minor_lock, flags);
>> + idr_remove(&drm_minors_idr, minor->index);
>> + spin_unlock_irqrestore(&drm_minor_lock, flags);
>>  err_free:
>>   kfree(minor);
>>   return r;
>> @@ -300,6 +310,7 @@ static void drm_minor_free(struct drm_device *dev, 
>> unsigned int type)
>>   return;
>>
>>   drm_mode_group_destroy(&minor->mode_group);
>> + put_device(minor->kdev);
>>
>>   spin_lock_irqsave(&drm_minor_lock, flags);
>>   idr_remove(&drm_minors_idr, minor->index);
>> @@ -327,11 +338,9 @@ static int drm_minor_register(struct drm_device *dev, 
>> unsigned int type)
>>   return ret;
>>   }
>>
>> - ret = drm_sysfs_device_add(minor);
>> - if (ret) {
>> - DRM_ERROR("DRM: Error sysfs_device_add.\n");
>> + ret = device_add(minor->kdev);
>> + if (ret)
>>   goto err_debugfs;
>> - }
>>
>>   /* replace NULL with @minor so lookups will succeed from now on */
>>   spin_lock_irqsave(&drm_minor_lock, flags);
>> @@ -352,7 +361,7 @@ static void drm_minor_unregister(struct drm_device *dev, 
>> unsigned int type)
>>   unsigned long flags;
>>
>>   minor = *drm_minor_get_slot(dev, type);
>> - if (!minor || !minor->kdev)
>> + if (!minor || !device_is_registered(minor->kdev))
>>   return;
>>
>>   /* replace @minor with NULL so lookups will fail from now on */
>> @@ -360,8 +369,9 @@ static void drm_minor_unregister(struct drm_device *dev, 
>> unsigned int type)
>>   idr_replace(&drm_minors_idr, NULL, minor->index);
>>   spin_unlock_irqrestore(&drm_minor_lock, flags);
>>
>> + device_del(minor->kdev);
>> + dev_set_drvdata(minor->kdev, NULL); /* safety belt */
>>   drm_debugfs_cleanup(minor);
>> - drm_sysfs_device_remove(minor);
>>  }
>>
>>  /**
>> diff --git a/drivers/gpu/drm/drm_sysfs.c b/drivers/gpu/drm/drm_sysfs.c
>> index 7827dad..ab1a5f6 100644
>> --- a/drivers/gpu/drm/drm_sysfs.c
>> +++ b/drivers/gpu/drm/drm_sysfs.c
>> @@ -493,71 +493,55 @@ static void drm_sysfs_release(struct device *dev)
>>  }
>>
>>  /**
>> - * drm_sysfs_device_add - adds a class device to sysfs for a character 
>> driver
>> - * @dev: DRM device to be added
>> - * @head: DRM head in question
>> + * drm_sysfs_minor_alloc() - Allocate sysfs device for given minor
>> + * @minor: minor to allocate sysfs device for
>>   *
>> - * Add a DRM device to the DRM's device model class.  We use @dev's PCI 
>> device
>> - * as the parent for the Linux device, and make sure it has a file 
>> containing
>> - * the driver we're using (for userspace compatibility).
>> + * This allocates a new sysfs device for @minor and returns

[PATCH 02/12] drm: drop unused "struct drm_queue"

2014-07-24 Thread David Herrmann
Hi

On Wed, Jul 23, 2014 at 9:35 PM, Daniel Vetter  wrote:
> On Wed, Jul 23, 2014 at 05:26:37PM +0200, David Herrmann wrote:
>> This object is unused, drop it.
>>
>> Signed-off-by: David Herrmann 
>
> Funny how after even all my "kill stuff with fire" series there's still
> such low hanging fruit left ;-)
>
> Reviewed-by: Daniel Vetter 

I think the problem is, they all depend on each other. With this patch
applied, "drm_waitlist" becomes unused.. noticed it just now. I
already have a followup.

Thanks
David


[PATCH] drm: Unlink dead file_priv from list of active files first

2014-07-24 Thread David Herrmann
Hi

On Thu, Jul 24, 2014 at 3:23 PM, Chris Wilson  
wrote:
> In order to prevent external observers walking the list of open DRM
> files from seeing an invalid drm_file_private in the process of being
> torndown, the first operation we need to take is to unlink the
> drm_file_private from that list.
>
> general protection fault:  [#1] PREEMPT SMP
> Modules linked in: i915 i2c_algo_bit drm_kms_helper drm lpc_ich 
> mfd_core nls_iso8859_1 i2c_hid video hid_generic usbhid hid e1000e ahci ptp 
> libahci pps_core
> CPU: 3 PID: 8220 Comm: cat Not tainted 3.16.0-rc6+ #4
> Hardware name: Intel Corporation Shark Bay Client platform/WhiteTip 
> Mountain 1, BIOS HSWLPTU1.86C.0119.R00.1303230105 03/23/2013
> task: 8800219642c0 ti: 880047024000 task.ti: 880047024000
> RIP: 0010:[]  [] 
> per_file_stats+0x110/0x160 [i915]
> RSP: 0018:880047027d48  EFLAGS: 00010246
> RAX: 6b6b6b6b6b6b6b6b RBX: 880047027e30 RCX: 
> RDX: 0001 RSI:  RDI: 88003a05cd00
> RBP: 880047027d58 R08: 0001 R09: 
> R10: 8800219642c0 R11:  R12: 88003a05cd00
> R13:  R14: 88003a05cd00 R15: 880047027d88
> FS:  7f5f73a13740() GS:88014e38() 
> knlGS:
> CS:  0010 DS:  ES:  CR0: 80050033
> CR2: 023ff038 CR3: 21a4b000 CR4: 001407e0
> Stack:
>  0001  880047027dc8 813438e4
>  880047027e30 a0137b60 880021a8af58 880021a8f1a0
>  8800a2061fb0 8800a2062048 8800a2061fb0 8800a1e23478
> Call Trace:
>  [] idr_for_each+0xf4/0x180
>  [] ? i915_gem_stolen_list_info+0x1f0/0x1f0 [i915]
>  [] i915_gem_object_info+0x5ca/0x6a0 [i915]
>  [] seq_read+0xf5/0x3a0
>  [] vfs_read+0x90/0x150
>  [] SyS_read+0x49/0xb0
>  [] tracesys+0xd0/0xd5
> Code: 01 00 00 49 39 84 24 08 01 00 00 74 55 49 8b 84 24 b8 00 00 00 
> 48 01 43 18 31 c0 5b 41 5c 5d c3 0f 1f 00 49 8b 44 24 08 4c 89 e7 <48> 8b 70 
> 28 48 81 c6 48 80 00 00 e8 80 14 01 00 84 c0 74 bc 49
> RIP  [] per_file_stats+0x110/0x160 [i915]
> RSP 
>
> Reported-by: "Ursulin, Tvrtko" 
> Bugzilla: https://bugs.freedesktop.org/show_bug.cgi?id=81712
> Signed-off-by: Chris Wilson 
> Cc: "Ursulin, Tvrtko" 

I have the same change in my local drm_file cleanup. This is:

Reviewed-by: David Herrmann 

Thanks
David

> ---
>  drivers/gpu/drm/drm_fops.c | 8 
>  1 file changed, 4 insertions(+), 4 deletions(-)
>
> diff --git a/drivers/gpu/drm/drm_fops.c b/drivers/gpu/drm/drm_fops.c
> index a0c63cf..aff8217 100644
> --- a/drivers/gpu/drm/drm_fops.c
> +++ b/drivers/gpu/drm/drm_fops.c
> @@ -416,6 +416,10 @@ int drm_release(struct inode *inode, struct file *filp)
>
> DRM_DEBUG("open_count = %d\n", dev->open_count);
>
> +   mutex_lock(&dev->struct_mutex);
> +   list_del(&file_priv->lhead);
> +   mutex_unlock(&dev->struct_mutex);
> +
> if (dev->driver->preclose)
> dev->driver->preclose(dev, file_priv);
>
> @@ -509,10 +513,6 @@ int drm_release(struct inode *inode, struct file *filp)
> file_priv->is_master = 0;
> mutex_unlock(&dev->master_mutex);
>
> -   mutex_lock(&dev->struct_mutex);
> -   list_del(&file_priv->lhead);
> -   mutex_unlock(&dev->struct_mutex);
> -
> if (dev->driver->postclose)
> dev->driver->postclose(dev, file_priv);
>
> --
> 1.9.1
>
> ___
> dri-devel mailing list
> dri-devel at lists.freedesktop.org
> http://lists.freedesktop.org/mailman/listinfo/dri-devel


[PATCH 07/12] drm: drop redundant drm_file->is_master

2014-07-24 Thread David Herrmann
Hi

On Thu, Jul 24, 2014 at 11:52 AM, Daniel Vetter  wrote:
> On Wed, Jul 23, 2014 at 05:26:42PM +0200, David Herrmann wrote:
>> The drm_file->is_master field is redundant as it's equivalent to:
>> drm_file->master && drm_file->master == drm_file->minor->master
>>
>> 1) "=>"
>>   Whenever we set drm_file->is_master, we also set:
>>   drm_file->minor->master = drm_file->master;
>>
>>   Whenever we clear drm_file->is_master, we also call:
>>   drm_master_put(&drm_file->minor->master);
>>   which implicitly clears it to NULL.
>>
>> 2) "<="
>>   minor->master cannot be set if it is non-NULL. Therefore, it stays as
>>   is unless a file drops it.
>>
>>   If minor->master is NULL, it is only set by places that also adjust
>>   drm_file->is_master.
>>
>> Therefore, we can safely drop is_master and replace it by an inline helper
>> that matches:
>> drm_file->master && drm_file->master == drm_file->minor->master
>>
>> Signed-off-by: David Herrmann 
>
> Docbook for drm_is_master is missing, otherwise Reviewed-by: Daniel Vetter 
> 
>
> And one question below which doesn't really matter for this patch here.
> See below

Fixed, thanks!

> [snip]
>
>> diff --git a/include/drm/drmP.h b/include/drm/drmP.h
>> index d91e09f..e1bb585 100644
>> --- a/include/drm/drmP.h
>> +++ b/include/drm/drmP.h
>> @@ -387,8 +387,6 @@ struct drm_prime_file_private {
>>  struct drm_file {
>>   unsigned always_authenticated :1;
>>   unsigned authenticated :1;
>> - /* Whether we're master for a minor. Protected by master_mutex */
>> - unsigned is_master :1;
>>   /* true when the client has asked us to expose stereo 3D mode flags */
>>   unsigned stereo_allowed :1;
>>   /*
>> @@ -1034,7 +1032,7 @@ struct drm_device {
>>   /** \name Locks */
>>   /*@{ */
>>   struct mutex struct_mutex;  /**< For others */
>> - struct mutex master_mutex;  /**< For drm_minor::master and 
>> drm_file::is_master */
>> + struct mutex master_mutex;  /**< For drm_minor::master */
>>   /*@} */
>>
>>   /** \name Usage Counters */
>> @@ -1172,6 +1170,11 @@ static inline bool drm_is_primary_client(const struct 
>> drm_file *file_priv)
>>   return file_priv->minor->type == DRM_MINOR_LEGACY;
>>  }
>>
>
> Docbook here please ...
>> +static inline bool drm_is_master(const struct drm_file *file)
>> +{
>
> Hm, we don't have any means to synchronize is_master checks with
> concurrent ioctls and stuff. Do we care? Orthogonal issue really.

We don't.. My drm-master reworks contains a comment about that. It's
not really problematic as all ioctls run for a determinate time in
kernel-code except for drm_read(), but drm_read() is per-file, not
per-device, so we're fine. However, with unfortunate timings, we might
really end up with problems.

vmwgfx solves this by using separate locks and verifying them against
the current master. it's not perfect and I'm not sure I like it better
than no locks, but at least they were aware of the problem.

Btw., the only thing I know how to solve it properly is to make
"master_mutex" an rwlock and all f_op entries take the read-lock,
while master modifications take the write-lock. Not sure it's worth
it, though.

Thanks
David

>> + return file->master && file->master == file->minor->master;
>> +}
>> +
>>  /**/
>>  /** \name Internal function definitions */
>>  /*@{*/
>> --
>> 2.0.2
>>
>
> --
> Daniel Vetter
> Software Engineer, Intel Corporation
> +41 (0) 79 365 57 48 - http://blog.ffwll.ch


[PATCH] imx-drm: imx-drm-core: Convert to drm_is_master()

2014-07-25 Thread David Herrmann
Hi

On Fri, Jul 25, 2014 at 5:08 AM, Fabio Estevam  wrote:
> From: Fabio Estevam 
>
> Since commit fe32c9f34b9e ("drm: drop redundant drm_file->is_master")
> we should use drm_is_master, otherwise the following build error is seen:
>
> drivers/staging/imx-drm/imx-drm-core.c: In function 'imx_drm_driver_preclose':
> drivers/staging/imx-drm/imx-drm-core.c:185:11: error: 'struct drm_file' has 
> no member named 'is_master'
>
> Reported-by: kbuild test robot 
> Signed-off-by: Fabio Estevam 

Sorry, I totally missed staging. I amended the imx changes now.

Thanks
David

> ---
> This one should go via David Herrmann's tree.
>
>  drivers/staging/imx-drm/imx-drm-core.c | 2 +-
>  1 file changed, 1 insertion(+), 1 deletion(-)
>
> diff --git a/drivers/staging/imx-drm/imx-drm-core.c 
> b/drivers/staging/imx-drm/imx-drm-core.c
> index 6b22106..7974854 100644
> --- a/drivers/staging/imx-drm/imx-drm-core.c
> +++ b/drivers/staging/imx-drm/imx-drm-core.c
> @@ -182,7 +182,7 @@ static void imx_drm_driver_preclose(struct drm_device 
> *drm,
>  {
> int i;
>
> -   if (!file->is_master)
> +   if (!drm_is_master(file))
> return;
>
> for (i = 0; i < MAX_CRTC; i++)
> --
> 1.8.3.2
>


[PATCH 07/12] drm: drop redundant drm_file->is_master

2014-07-28 Thread David Herrmann
Hi

On Fri, Jul 25, 2014 at 9:56 AM, Daniel Vetter  wrote:
> On Thu, Jul 24, 2014 at 11:38:28PM +0200, David Herrmann wrote:
>> On Thu, Jul 24, 2014 at 11:52 AM, Daniel Vetter  wrote:
>> > On Wed, Jul 23, 2014 at 05:26:42PM +0200, David Herrmann wrote:
>> >> +static inline bool drm_is_master(const struct drm_file *file)
>> >> +{
>> >
>> > Hm, we don't have any means to synchronize is_master checks with
>> > concurrent ioctls and stuff. Do we care? Orthogonal issue really.
>>
>> We don't.. My drm-master reworks contains a comment about that. It's
>> not really problematic as all ioctls run for a determinate time in
>> kernel-code except for drm_read(), but drm_read() is per-file, not
>> per-device, so we're fine. However, with unfortunate timings, we might
>> really end up with problems.
>>
>> vmwgfx solves this by using separate locks and verifying them against
>> the current master. it's not perfect and I'm not sure I like it better
>> than no locks, but at least they were aware of the problem.
>>
>> Btw., the only thing I know how to solve it properly is to make
>> "master_mutex" an rwlock and all f_op entries take the read-lock,
>> while master modifications take the write-lock. Not sure it's worth
>> it, though.
>
> Imo that's terrible. And I'm not even sure we need to care, e.g. if we do
> a master switch to a different compositor any ioctl the new compositor
> does will grab some locks, which will force the old ioctl to complete.
>
> Well mostly, and only if we don't do lockless tricks or lock-dropping and
> it's racy.

There is always a race! Like this:

CPU A:
1: enter drm_ioctl()
2: check file->is_master
3: enter drm_some_ioctl()
4: acquire some DRM internal locks

If CPU B acquires DRM-Master between step 2 and 3, CPU A might execute
an ioctl with an arbitrary delay. Maybe CPU B even executed some ioctl
after acquiring DRM-Master before CPU A had the chance to enter the
ioctl it's about to execute.

Not that I care much, but we have to remember that those races always
exist. Given that DRM-Master is privileged, this is not really
high-priority to fix..

> I guess a proper fix would be to wait for all ioctls on a device to
> complete. The vfs doesn't have any cool infrastructure for this as part of
> the general revoke work that we could reuse?

What the VFS rework does is this:

if (!atomic_inc_unless_negative(file->sth))
return -ENODEV;
ret = file->f_op->some_op();
atomic_dec(file->sth);
return ret;

That is, it wraps all calls to a file-operation with an
atomic-counter. However, there's only one counter per open-file, not
one per file-operation. If we'd want that for DRM-Master, we couldn't
use it as otherwise all file-operations would be blocked. Furthermore,
VFS only allows disabling an open-file. Once disabled, you cannot
enable it again.

So I don't think a read/write lock is a bad idea. RCU doesn't work as
our ioctls are way to heavy for rcu_read_lock(), SRCU is basically
rw-sem for our use-case. A hand-crafted atomic counter is also
equivalent to rw-sem. So yeah, it might lock nasty, but any other
solution will just hide the fact that we have a read/write lock.

Anyhow, I'm not working on a fix, so if no-one else looks at it, we
can just ignore it.

Thanks
David


[PATCH] drm: Don't export internal module variables

2014-06-01 Thread David Herrmann
Hi

On Thu, May 29, 2014 at 7:25 PM, Daniel Vetter  
wrote:
> Drivers really have no business touching these. Noticed because
> exynose _did_ touch the vblank off delay, which could potentially
> affect other drivers.
>
> drm_debug is an exception since it's used in macros and inline
> functions.
>
> v2: Drop bonghits changes. Note to self: Don't submit patches
> before first coffee.
>
> Cc: Inki Dae 
> Signed-off-by: Daniel Vetter 
> ---
>  drivers/gpu/drm/drm_stub.c  | 4 
>  drivers/gpu/drm/exynos/exynos_drm_drv.c | 4 
>  drivers/gpu/drm/exynos/exynos_drm_drv.h | 2 --
>  3 files changed, 10 deletions(-)
>
> diff --git a/drivers/gpu/drm/drm_stub.c b/drivers/gpu/drm/drm_stub.c
> index 3727ac8bc310..998782a88520 100644
> --- a/drivers/gpu/drm/drm_stub.c
> +++ b/drivers/gpu/drm/drm_stub.c
> @@ -43,17 +43,13 @@ unsigned int drm_debug = 0; /* 1 to enable debug output */
>  EXPORT_SYMBOL(drm_debug);
>
>  unsigned int drm_rnodes = 0;   /* 1 to enable experimental render nodes API 
> */
> -EXPORT_SYMBOL(drm_rnodes);
>
>  /* 1 to allow user space to request universal planes (experimental) */
>  unsigned int drm_universal_planes = 0;
> -EXPORT_SYMBOL(drm_universal_planes);
>
>  unsigned int drm_vblank_offdelay = 5000;/* Default to 5000 msecs. */
> -EXPORT_SYMBOL(drm_vblank_offdelay);
>
>  unsigned int drm_timestamp_precision = 20;  /* Default to 20 usecs. */
> -EXPORT_SYMBOL(drm_timestamp_precision);
>
>  /*
>   * Default to use monotonic timestamps for wait-for-vblank and page-flip
> diff --git a/drivers/gpu/drm/exynos/exynos_drm_drv.c 
> b/drivers/gpu/drm/exynos/exynos_drm_drv.c
> index 2d27ba23a6a8..d7c50b0da510 100644
> --- a/drivers/gpu/drm/exynos/exynos_drm_drv.c
> +++ b/drivers/gpu/drm/exynos/exynos_drm_drv.c
> @@ -38,8 +38,6 @@
>  #define DRIVER_MAJOR   1
>  #define DRIVER_MINOR   0
>
> -#define VBLANK_OFF_DELAY   5
> -
>  /* platform device pointer for eynos drm device. */
>  static struct platform_device *exynos_drm_pdev;
>
> @@ -109,8 +107,6 @@ static int exynos_drm_load(struct drm_device *dev, 
> unsigned long flags)
> /* setup possible_clones. */
> exynos_drm_encoder_setup(dev);
>
> -   drm_vblank_offdelay = VBLANK_OFF_DELAY;

You know that this is 5,000 by default and VBLANK_OFF_DELAY is 50,000?
Not sure whether that was a typo or was explicitly set this way. If
that change is intentional:

Reviewed-by: David Herrmann 

Thanks
David

> -
> platform_set_drvdata(dev->platformdev, dev);
>
> /* force connectors detection */
> diff --git a/drivers/gpu/drm/exynos/exynos_drm_drv.h 
> b/drivers/gpu/drm/exynos/exynos_drm_drv.h
> index ce3e6a30deaa..e28f792d628c 100644
> --- a/drivers/gpu/drm/exynos/exynos_drm_drv.h
> +++ b/drivers/gpu/drm/exynos/exynos_drm_drv.h
> @@ -40,8 +40,6 @@ struct drm_device;
>  struct exynos_drm_overlay;
>  struct drm_connector;
>
> -extern unsigned int drm_vblank_offdelay;
> -
>  /* this enumerates display type. */
>  enum exynos_drm_output_type {
> EXYNOS_DISPLAY_TYPE_NONE,
> --
> 1.9.2
>
> ___
> dri-devel mailing list
> dri-devel at lists.freedesktop.org
> http://lists.freedesktop.org/mailman/listinfo/dri-devel


[PATCH] drm: Don't export internal module variables

2014-06-02 Thread David Herrmann
Hi

On Mon, Jun 2, 2014 at 10:01 AM, Daniel Vetter  wrote:
> On Sun, Jun 01, 2014 at 02:04:45PM +0200, David Herrmann wrote:
>> Hi
>>
>> On Thu, May 29, 2014 at 7:25 PM, Daniel Vetter  
>> wrote:
>> > Drivers really have no business touching these. Noticed because
>> > exynose _did_ touch the vblank off delay, which could potentially
>> > affect other drivers.
>> >
>> > drm_debug is an exception since it's used in macros and inline
>> > functions.
>> >
>> > v2: Drop bonghits changes. Note to self: Don't submit patches
>> > before first coffee.
>> >
>> > Cc: Inki Dae 
>> > Signed-off-by: Daniel Vetter 
>> > ---
>> >  drivers/gpu/drm/drm_stub.c  | 4 
>> >  drivers/gpu/drm/exynos/exynos_drm_drv.c | 4 
>> >  drivers/gpu/drm/exynos/exynos_drm_drv.h | 2 --
>> >  3 files changed, 10 deletions(-)
>> >
>> > diff --git a/drivers/gpu/drm/drm_stub.c b/drivers/gpu/drm/drm_stub.c
>> > index 3727ac8bc310..998782a88520 100644
>> > --- a/drivers/gpu/drm/drm_stub.c
>> > +++ b/drivers/gpu/drm/drm_stub.c
>> > @@ -43,17 +43,13 @@ unsigned int drm_debug = 0; /* 1 to enable debug 
>> > output */
>> >  EXPORT_SYMBOL(drm_debug);
>> >
>> >  unsigned int drm_rnodes = 0;   /* 1 to enable experimental render nodes 
>> > API */
>> > -EXPORT_SYMBOL(drm_rnodes);
>> >
>> >  /* 1 to allow user space to request universal planes (experimental) */
>> >  unsigned int drm_universal_planes = 0;
>> > -EXPORT_SYMBOL(drm_universal_planes);
>> >
>> >  unsigned int drm_vblank_offdelay = 5000;/* Default to 5000 msecs. */
>> > -EXPORT_SYMBOL(drm_vblank_offdelay);
>> >
>> >  unsigned int drm_timestamp_precision = 20;  /* Default to 20 usecs. */
>> > -EXPORT_SYMBOL(drm_timestamp_precision);
>> >
>> >  /*
>> >   * Default to use monotonic timestamps for wait-for-vblank and page-flip
>> > diff --git a/drivers/gpu/drm/exynos/exynos_drm_drv.c 
>> > b/drivers/gpu/drm/exynos/exynos_drm_drv.c
>> > index 2d27ba23a6a8..d7c50b0da510 100644
>> > --- a/drivers/gpu/drm/exynos/exynos_drm_drv.c
>> > +++ b/drivers/gpu/drm/exynos/exynos_drm_drv.c
>> > @@ -38,8 +38,6 @@
>> >  #define DRIVER_MAJOR   1
>> >  #define DRIVER_MINOR   0
>> >
>> > -#define VBLANK_OFF_DELAY   5
>> > -
>> >  /* platform device pointer for eynos drm device. */
>> >  static struct platform_device *exynos_drm_pdev;
>> >
>> > @@ -109,8 +107,6 @@ static int exynos_drm_load(struct drm_device *dev, 
>> > unsigned long flags)
>> > /* setup possible_clones. */
>> > exynos_drm_encoder_setup(dev);
>> >
>> > -   drm_vblank_offdelay = VBLANK_OFF_DELAY;
>>
>> You know that this is 5,000 by default and VBLANK_OFF_DELAY is 50,000?
>> Not sure whether that was a typo or was explicitly set this way. If
>> that change is intentional:
>
> Oops, didn't spot that, nice catch. git log says this was added to paper
> over a race in get/put_vblank in exynos. Wtf, imo even more reason to nuke
> this ... I've pimped the commit message a bit - still r-b?

You mean:

commit 52c68814cd7f3592292a02b890b5b8625e9069a7
Author: Inki Dae 
Date:   Fri Dec 16 21:31:12 2011 +0900

drm/exynos: extend vblank off delay time.

Yeah, that one doesn't make any sense. So this is still:

Reviewed-by: David Herrmann 

Thanks
David


[PATCH 4/5] drm/omap: use __GFP_DMA32 for shmem-backed gem

2014-06-02 Thread David Herrmann
Hi Tomi

Any chance you could give this a spin on an omap device? It shouldn't
affect any 32bit devices, so this is mostly a cosmetic change.
However, I'd really like to get rid of that 'TODO' item. So a
"Tested-by:" would be really nice.

Thanks
David

On Sun, May 25, 2014 at 2:34 PM, David Herrmann  
wrote:
> OMAP requires bo-pages to be in the DMA32 zone. Explicitly request this by
> setting __GFP_DMA32 as mapping-gfp-mask during shmem initialization. This
> drops HIGHMEM from the gfp-mask and uses DMA32 instead. shmem-core takes
> care to relocate pages during swap-in in case they have been loaded into
> the wrong zone.
>
> It is _not_ possible to pass __GFP_DMA32 to shmem_read_mapping_page_gfp()
> as the page might have already been swapped-in at that time. The zone-mask
> must be set during initialization and be kept constant for now.
>
> Remove the now superfluous TODO in omap_gem.c.
>
> Cc: Tomi Valkeinen 
> Cc: Rob Clark 
> Signed-off-by: David Herrmann 
> ---
>  drivers/gpu/drm/omapdrm/omap_gem.c | 17 -
>  1 file changed, 8 insertions(+), 9 deletions(-)
>
> diff --git a/drivers/gpu/drm/omapdrm/omap_gem.c 
> b/drivers/gpu/drm/omapdrm/omap_gem.c
> index 95dbce2..1331fd5 100644
> --- a/drivers/gpu/drm/omapdrm/omap_gem.c
> +++ b/drivers/gpu/drm/omapdrm/omap_gem.c
> @@ -233,10 +233,6 @@ static int omap_gem_attach_pages(struct drm_gem_object 
> *obj)
>
> WARN_ON(omap_obj->pages);
>
> -   /* TODO: __GFP_DMA32 .. but somehow GFP_HIGHMEM is coming from the
> -* mapping_gfp_mask(mapping) which conflicts w/ GFP_DMA32.. probably
> -* we actually want CMA memory for it all anyways..
> -*/
> pages = drm_gem_get_pages(obj, GFP_KERNEL);
> if (IS_ERR(pages)) {
> dev_err(obj->dev->dev, "could not get pages: %ld\n", 
> PTR_ERR(pages));
> @@ -1347,6 +1343,7 @@ struct drm_gem_object *omap_gem_new(struct drm_device 
> *dev,
> struct omap_drm_private *priv = dev->dev_private;
> struct omap_gem_object *omap_obj;
> struct drm_gem_object *obj = NULL;
> +   struct address_space *mapping;
> size_t size;
> int ret;
>
> @@ -1404,14 +1401,16 @@ struct drm_gem_object *omap_gem_new(struct drm_device 
> *dev,
> omap_obj->height = gsize.tiled.height;
> }
>
> -   ret = 0;
> -   if (flags & (OMAP_BO_DMA|OMAP_BO_EXT_MEM))
> +   if (flags & (OMAP_BO_DMA|OMAP_BO_EXT_MEM)) {
> drm_gem_private_object_init(dev, obj, size);
> -   else
> +   } else {
> ret = drm_gem_object_init(dev, obj, size);
> +   if (ret)
> +   goto fail;
>
> -   if (ret)
> -   goto fail;
> +   mapping = file_inode(obj->filp)->i_mapping;
> +   mapping_set_gfp_mask(mapping, GFP_USER | __GFP_DMA32);
> +   }
>
> return obj;
>
> --
> 1.9.3
>


[PATCH] drm/i915: Kick out vga console

2014-06-04 Thread David Herrmann
Hi

On Wed, Jun 4, 2014 at 12:57 AM, Daniel Vetter  
wrote:
> From: Chris Wilson 
>
> Touching the VGA resources on an IVB EFI machine causes hard hangs when
> we then kick out the efifb. Ouch.
>
> Apparently this also prevents unclaimed register errors on hsw and
> hard machine hangs on my i855gm when trying to unbind fbcon.
>
> Also, we want this to make I915_FBDEV=n safe.
>
> v2: Rebase and pimp commit message.
>
> v3: We also need to unregister the vga console, otherwise the unbind
> of the fb console before module unload might resurrect it again.
>
> Bugzilla: https://bugs.freedesktop.org/show_bug.cgi?id=67813
> Cc: David Herrmann 
> Cc: Jean-Christophe Plagniol-Villard 
> Cc: Tomi Valkeinen 
> Cc: linux-fbdev at vger.kernel.org
> Signed-off-by: Chris Wilson  (v1)
> Signed-off-by: Daniel Vetter 
> ---
>  drivers/gpu/drm/i915/i915_dma.c  | 34 +-
>  drivers/video/console/dummycon.c |  1 +
>  drivers/video/console/vgacon.c   |  1 +
>  3 files changed, 35 insertions(+), 1 deletion(-)
>
> diff --git a/drivers/gpu/drm/i915/i915_dma.c b/drivers/gpu/drm/i915/i915_dma.c
> index b9159ade5e85..a4df80740b37 100644
> --- a/drivers/gpu/drm/i915/i915_dma.c
> +++ b/drivers/gpu/drm/i915/i915_dma.c
> @@ -36,6 +36,8 @@
>  #include "i915_drv.h"
>  #include "i915_trace.h"
>  #include 
> +#include 
> +#include 
>  #include 
>  #include 
>  #include 
> @@ -1450,6 +1452,29 @@ static void i915_kick_out_firmware_fb(struct 
> drm_i915_private *dev_priv)
>  }
>  #endif
>
> +static int i915_kick_out_vgacon(struct drm_i915_private *dev_priv)
> +{
> +#if !defined(CONFIG_VGA_CONSOLE)
> +   return 0;
> +#else
> +   int ret;
> +
> +#if !defined(CONFIG_DUMMY_CONSOLE)
> +   return -ENODEV;
> +#endif
> +
> +   DRM_INFO("Replacing VGA console driver\n");
> +
> +   console_lock();
> +   ret = do_take_over_console(&dummy_con, 0, MAX_NR_CONSOLES - 1, 1);

You rely on compiler-optimizations here. "dummy_con" is not available
if !CONFIG_DUMMY_CONSOLE, but you use it. This causes linker-failure
if dead-code elimination is not done (-O0).

Thanks
David

> +   if (ret == 0)
> +   ret = do_unregister_con_driver(&vga_con);
> +   console_unlock();
> +
> +   return ret;
> +#endif
> +}
> +
>  static void i915_dump_device_info(struct drm_i915_private *dev_priv)
>  {
> const struct intel_device_info *info = &dev_priv->info;
> @@ -1623,8 +1648,15 @@ int i915_driver_load(struct drm_device *dev, unsigned 
> long flags)
> if (ret)
> goto out_regs;
>
> -   if (drm_core_check_feature(dev, DRIVER_MODESET))
> +   if (drm_core_check_feature(dev, DRIVER_MODESET)) {
> +   ret = i915_kick_out_vgacon(dev_priv);
> +   if (ret) {
> +   DRM_ERROR("failed to remove conflicting VGA 
> console\n");
> +   goto out_gtt;
> +   }
> +
> i915_kick_out_firmware_fb(dev_priv);
> +   }
>
> pci_set_master(dev->pdev);
>
> diff --git a/drivers/video/console/dummycon.c 
> b/drivers/video/console/dummycon.c
> index b63860f7beab..40bec8d64b0a 100644
> --- a/drivers/video/console/dummycon.c
> +++ b/drivers/video/console/dummycon.c
> @@ -77,3 +77,4 @@ const struct consw dummy_con = {
>  .con_set_palette = DUMMY,
>  .con_scrolldelta = DUMMY,
>  };
> +EXPORT_SYMBOL_GPL(dummy_con);
> diff --git a/drivers/video/console/vgacon.c b/drivers/video/console/vgacon.c
> index 9d8feac67637..84acd6223dc5 100644
> --- a/drivers/video/console/vgacon.c
> +++ b/drivers/video/console/vgacon.c
> @@ -1440,5 +1440,6 @@ const struct consw vga_con = {
> .con_build_attr = vgacon_build_attr,
> .con_invert_region = vgacon_invert_region,
>  };
> +EXPORT_SYMBOL(vga_con);
>
>  MODULE_LICENSE("GPL");
> --
> 1.8.1.4
>


[PATCH] drm/i915: Kick out vga console

2014-06-04 Thread David Herrmann
Hi

On Wed, Jun 4, 2014 at 2:20 PM, Jani Nikula  
wrote:
> On Wed, 04 Jun 2014, David Herrmann  wrote:
>> You rely on compiler-optimizations here. "dummy_con" is not available
>> if !CONFIG_DUMMY_CONSOLE, but you use it. This causes linker-failure
>> if dead-code elimination is not done (-O0).
>
> Nested #ifs too. How about
>
> #if !defined(CONFIG_VGA_CONSOLE)
> static inline int i915_kick_out_vgacon(struct drm_i915_private *dev_priv)
> {
> return 0;
> }
> #elif !defined(CONFIG_DUMMY_CONSOLE)
> static inline int i915_kick_out_vgacon(struct drm_i915_private *dev_priv)
> {
> return -ENODEV;
> }
> #else
> static int i915_kick_out_vgacon(struct drm_i915_private *dev_priv)
> {
> /* ... */
> }
> #endif
>
> in proper kernel style?

Or even shorter:

#if defined(CONFIG_VGA_CONSOLE) && defined(CONFIG_DUMMY_CONSOLE)
static inline int i915_kick_out_vgacon(struct drm_i915_private *dev_priv)
{
...
}
#else
static inline int i915_kick_out_vgacon(struct drm_i915_private *dev_priv)
{
return IS_ENABLED(CONFIG_VGA_CONSOLE) ? -ENODEV : 0;
}
#endif

Thanks
David

On Wed, Jun 4, 2014 at 2:20 PM, Jani Nikula  
wrote:
> On Wed, 04 Jun 2014, David Herrmann  wrote:
>> Hi
>>
>> On Wed, Jun 4, 2014 at 12:57 AM, Daniel Vetter  
>> wrote:
>>> From: Chris Wilson 
>>>
>>> Touching the VGA resources on an IVB EFI machine causes hard hangs when
>>> we then kick out the efifb. Ouch.
>>>
>>> Apparently this also prevents unclaimed register errors on hsw and
>>> hard machine hangs on my i855gm when trying to unbind fbcon.
>>>
>>> Also, we want this to make I915_FBDEV=n safe.
>>>
>>> v2: Rebase and pimp commit message.
>>>
>>> v3: We also need to unregister the vga console, otherwise the unbind
>>> of the fb console before module unload might resurrect it again.
>>>
>>> Bugzilla: https://bugs.freedesktop.org/show_bug.cgi?id=67813
>>> Cc: David Herrmann 
>>> Cc: Jean-Christophe Plagniol-Villard 
>>> Cc: Tomi Valkeinen 
>>> Cc: linux-fbdev at vger.kernel.org
>>> Signed-off-by: Chris Wilson  (v1)
>>> Signed-off-by: Daniel Vetter 
>>> ---
>>>  drivers/gpu/drm/i915/i915_dma.c  | 34 +-
>>>  drivers/video/console/dummycon.c |  1 +
>>>  drivers/video/console/vgacon.c   |  1 +
>>>  3 files changed, 35 insertions(+), 1 deletion(-)
>>>
>>> diff --git a/drivers/gpu/drm/i915/i915_dma.c 
>>> b/drivers/gpu/drm/i915/i915_dma.c
>>> index b9159ade5e85..a4df80740b37 100644
>>> --- a/drivers/gpu/drm/i915/i915_dma.c
>>> +++ b/drivers/gpu/drm/i915/i915_dma.c
>>> @@ -36,6 +36,8 @@
>>>  #include "i915_drv.h"
>>>  #include "i915_trace.h"
>>>  #include 
>>> +#include 
>>> +#include 
>>>  #include 
>>>  #include 
>>>  #include 
>>> @@ -1450,6 +1452,29 @@ static void i915_kick_out_firmware_fb(struct 
>>> drm_i915_private *dev_priv)
>>>  }
>>>  #endif
>>>
>>> +static int i915_kick_out_vgacon(struct drm_i915_private *dev_priv)
>>> +{
>>> +#if !defined(CONFIG_VGA_CONSOLE)
>>> +   return 0;
>>> +#else
>>> +   int ret;
>>> +
>>> +#if !defined(CONFIG_DUMMY_CONSOLE)
>>> +   return -ENODEV;
>>> +#endif
>>> +
>>> +   DRM_INFO("Replacing VGA console driver\n");
>>> +
>>> +   console_lock();
>>> +   ret = do_take_over_console(&dummy_con, 0, MAX_NR_CONSOLES - 1, 1);
>>
>> You rely on compiler-optimizations here. "dummy_con" is not available
>> if !CONFIG_DUMMY_CONSOLE, but you use it. This causes linker-failure
>> if dead-code elimination is not done (-O0).
>
> Nested #ifs too. How about
>
> #if !defined(CONFIG_VGA_CONSOLE)
> static inline int i915_kick_out_vgacon(struct drm_i915_private *dev_priv)
> {
> return 0;
> }
> #elif !defined(CONFIG_DUMMY_CONSOLE)
> static inline int i915_kick_out_vgacon(struct drm_i915_private *dev_priv)
> {
> return -ENODEV;
> }
> #else
> static int i915_kick_out_vgacon(struct drm_i915_private *dev_priv)
> {
> /* ... */
> }
> #endif
>
> in proper kernel style?
>
> BR,
> Jani.
>
>
>>
>> Thanks
>> David
>>
>>> +   if (ret == 0)
>>> +   ret = do_unregister_con_driver(&vga_con);
>>> +   console_unlock();
>>> +
>>> +   return 

[PATCH 4/5] drm/omap: use __GFP_DMA32 for shmem-backed gem

2014-06-05 Thread David Herrmann
Hi

On Thu, Jun 5, 2014 at 4:04 PM, Rob Clark  wrote:
> On Thu, Jun 5, 2014 at 9:52 AM, Tomi Valkeinen  
> wrote:
>> Hi,
>>
>> On 02/06/14 16:03, David Herrmann wrote:
>>> Hi Tomi
>>>
>>> Any chance you could give this a spin on an omap device? It shouldn't
>>> affect any 32bit devices, so this is mostly a cosmetic change.
>>> However, I'd really like to get rid of that 'TODO' item. So a
>>> "Tested-by:" would be really nice.
>>
>> I made a quick test on omap4. I verified that the changed code is ran,
>> and I can get a picture on my monitor with omapdrm.
>>
>> So tested by me, but I'm not familiar with shmem so I can't really say
>> anything about the change itself without studying this further.
>
> Thanks for testing it.  The change looks ok, I just had a nagging
> doubt about it because I had problems w/ GFP32 before (but was
> probably just missing mapping_set_gfp_mask()), so was hoping that
> someone could confirm that it actually did work as intended.
>
> Anyways, with that:
>
> Reviewed-by: Rob Clark 

Thanks Tomi and Rob! I think to avoid conflicts with PATCH 5/5, Dave
should take this through drm-next? In case there're no objections to
5/5..

Thanks
David


[PATCH 3/5] vt: Don't ignore unbind errors in vt_unbind

2014-06-06 Thread David Herrmann
Hi

On Thu, Jun 5, 2014 at 4:58 PM, Daniel Vetter  wrote:
> Otherwise the loop will never stop since we don't make any
> forward progress. Noticed while breaking this accidentally
> in a painful attempt to make vga_con unregistering work.
>
> With this patch we'll bail out on the first attempt, which
> at least leaves a useful enough system behind for debugging.
> Livelocks on console_lock just aren't fun.
>
> Cc: Greg Kroah-Hartman 
> Cc: Jiri Slaby 
> Signed-off-by: Daniel Vetter 

We used to return 0 on errors here, which is very backwards to me.. so
your change to use "retval" looks fine to me. This is:

Reviewed-by: David Herrmann 

Thanks
David

> ---
>  drivers/tty/vt/vt.c | 5 -
>  1 file changed, 4 insertions(+), 1 deletion(-)
>
> diff --git a/drivers/tty/vt/vt.c b/drivers/tty/vt/vt.c
> index 5077fe87324d..3c00dcb3b145 100644
> --- a/drivers/tty/vt/vt.c
> +++ b/drivers/tty/vt/vt.c
> @@ -3260,6 +3260,7 @@ static int vt_unbind(struct con_driver *con)
>  {
> const struct consw *csw = NULL;
> int i, more = 1, first = -1, last = -1, deflt = 0;
> +   int ret;
>
> if (!con->con || !(con->flag & CON_DRIVER_FLAG_MODULE) ||
> con_is_graphics(con->con, con->first, con->last))
> @@ -3285,8 +3286,10 @@ static int vt_unbind(struct con_driver *con)
>
> if (first != -1) {
> console_lock();
> -   do_unbind_con_driver(csw, first, last, deflt);
> +   ret = do_unbind_con_driver(csw, first, last, deflt);
> console_unlock();
> +   if (ret != 0)
> +   return ret;
> }
>
> first = -1;
> --
> 1.8.1.4
>
> ___
> dri-devel mailing list
> dri-devel at lists.freedesktop.org
> http://lists.freedesktop.org/mailman/listinfo/dri-devel


[PATCH 1/5] vt: Fix replacement console check when unbinding

2014-06-06 Thread David Herrmann
Hi

On Thu, Jun 5, 2014 at 4:58 PM, Daniel Vetter  wrote:
> I don't fully understand the magic of the vt register/unregister
> logic, but apparently everything but the inital console (as set
> in the conswitchp pointer) is marked with FLAG_MODULE. Which means
> if something unregistered the boot vt driver (e.g. i915.ko kicking
> out vga_con) there's nothing left when trying to unbind e.g. fbcon
> through sysfs.
>
> But we always have the dummy console hanging around, so this test
> is fairly dubious. What we actually want is simply a different console
> than the one we want to unbind.

For unknown reasons, you can disable the dummy console via Kconfig, so
it's not guaranteed to be around. But your comment is still valid.

>
> Cc: Greg Kroah-Hartman 
> Cc: Jiri Slaby 
> Signed-off-by: Daniel Vetter 
> ---
>  drivers/tty/vt/vt.c | 3 +--
>  1 file changed, 1 insertion(+), 2 deletions(-)
>
> diff --git a/drivers/tty/vt/vt.c b/drivers/tty/vt/vt.c
> index 3ad0b61e35b4..ea600f482eeb 100644
> --- a/drivers/tty/vt/vt.c
> +++ b/drivers/tty/vt/vt.c
> @@ -3155,8 +3155,7 @@ int do_unbind_con_driver(const struct consw *csw, int 
> first, int last, int deflt
> for (i = 0; i < MAX_NR_CON_DRIVER; i++) {
> con_back = ®istered_con_driver[i];
>
> -   if (con_back->con &&
> -   !(con_back->flag & CON_DRIVER_FLAG_MODULE)) {
> +   if (con_back->con && con_back->con != csw) {

Funny thing is, if you run do_bind_con_driver() on the range first,
you kick out the existing driver and can then unload it regardless
whether the fallback was FLAG_MODULE or not. Therefore, I think that
change is safe. This is:

Reviewed-by: David Herrmann 

Thanks
David

> defcsw = con_back->con;
> retval = 0;
> break;
> --
> 1.8.1.4
>
> ___
> dri-devel mailing list
> dri-devel at lists.freedesktop.org
> http://lists.freedesktop.org/mailman/listinfo/dri-devel


[PATCH 2/5] vt: Fix up unregistration of vt drivers

2014-06-06 Thread David Herrmann
Hi

On Thu, Jun 5, 2014 at 4:58 PM, Daniel Vetter  wrote:
> A bunch of issues:
> - We should not kick out the default console (which is tracked in
>   conswitchp), so check for that.
> - Add better error codes so callers can differentiate between "something
>   went wrong" and "your driver isn't registered already". i915 needs
>   that so it doesn't fall over when reloading the driver and hence
>   vga_con is already unregistered.
> - There's a mess with the driver flags: What we need to check for is
>   that the driver isn't used any more, i.e. unbound completely (FLAG_INIT).
>   And not whether it's the boot console or not (which is the only one
>   which doesn't have FLAG_MODULE). Otherwise there's no way to kick
>   out the boot console, which i915 wants to do to prevent havoc with
>   vga_con interferring (which tends to hang machines).
>
> Cc: Greg Kroah-Hartman 
> Cc: Jiri Slaby 
> Signed-off-by: Daniel Vetter 
> ---
>  drivers/tty/vt/vt.c | 16 +---
>  1 file changed, 9 insertions(+), 7 deletions(-)
>
> diff --git a/drivers/tty/vt/vt.c b/drivers/tty/vt/vt.c
> index ea600f482eeb..5077fe87324d 100644
> --- a/drivers/tty/vt/vt.c
> +++ b/drivers/tty/vt/vt.c
> @@ -3573,17 +3573,20 @@ err:
>   */
>  int do_unregister_con_driver(const struct consw *csw)
>  {
> -   int i, retval = -ENODEV;
> +   int i;
>
> /* cannot unregister a bound driver */
> if (con_is_bound(csw))
> -   goto err;
> +   return -EBUSY;
> +
> +   if (csw == conswitchp)
> +   return -EINVAL;

Ugh, that fix is correct, but I'd rather like to see
do_unbind_con_driver() do the right thing. It currently resets
conswitchp _only_ if the new fallback is unbound. Why not _always_ set
conswitchp to defcsw _iff_ conswitchp == csw there?

This way, you _know_ here that if !con_is_bound(csw), then csw != conswitchp.

>
> for (i = 0; i < MAX_NR_CON_DRIVER; i++) {
> struct con_driver *con_driver = ®istered_con_driver[i];
>
> if (con_driver->con == csw &&
> -   con_driver->flag & CON_DRIVER_FLAG_MODULE) {
> +   con_driver->flag & CON_DRIVER_FLAG_INIT) {

That makes FLAG_MODULE almost a no-op except for ->unbind(). I wonder
why FLAG_MODULE exists, anyway.

Otherwise looks good.

Thanks
David

> vtconsole_deinit_device(con_driver);
> device_destroy(vtconsole_class,
>MKDEV(0, con_driver->node));
> @@ -3594,12 +3597,11 @@ int do_unregister_con_driver(const struct consw *csw)
> con_driver->flag = 0;
> con_driver->first = 0;
> con_driver->last = 0;
> -   retval = 0;
> -   break;
> +   return 0;
> }
> }
> -err:
> -   return retval;
> +
> +   return -ENODEV;
>  }
>  EXPORT_SYMBOL_GPL(do_unregister_con_driver);
>
> --
> 1.8.1.4
>
> ___
> dri-devel mailing list
> dri-devel at lists.freedesktop.org
> http://lists.freedesktop.org/mailman/listinfo/dri-devel


[PATCH 5/5] drm/i915: Kick out vga console

2014-06-06 Thread David Herrmann
Hi

On Thu, Jun 5, 2014 at 4:58 PM, Daniel Vetter  wrote:
> Touching the VGA resources on an IVB EFI machine causes hard hangs when
> we then kick out the efifb. Ouch.
>
> Apparently this also prevents unclaimed register errors on hsw and
> hard machine hangs on my i855gm when trying to unbind fbcon.
>
> Also, we want this to make I915_FBDEV=n safe.
>
> v2: Rebase and pimp commit message.
>
> v3: We also need to unregister the vga console, otherwise the unbind
> of the fb console before module unload might resurrect it again.
>
> v4: Ignore errors when the vga console is already unregistered - this
> can happen when e.g. reloading i915.ko.
>
> Bugzilla: https://bugs.freedesktop.org/show_bug.cgi?id=67813
> Cc: David Herrmann 
> Cc: Jean-Christophe Plagniol-Villard 
> Cc: Tomi Valkeinen 
> Cc: linux-fbdev at vger.kernel.org
> Cc: Jani Nikula 
> Signed-off-by: Chris Wilson  (v1)
> Signed-off-by: Daniel Vetter 
> ---
>  drivers/gpu/drm/i915/i915_dma.c  | 43 
> +++-
>  drivers/video/console/dummycon.c |  1 +
>  drivers/video/console/vgacon.c   |  1 +
>  3 files changed, 44 insertions(+), 1 deletion(-)
>
> diff --git a/drivers/gpu/drm/i915/i915_dma.c b/drivers/gpu/drm/i915/i915_dma.c
> index 27fe65ac5940..bcb66ddd649e 100644
> --- a/drivers/gpu/drm/i915/i915_dma.c
> +++ b/drivers/gpu/drm/i915/i915_dma.c
> @@ -36,6 +36,8 @@
>  #include "i915_drv.h"
>  #include "i915_trace.h"
>  #include 
> +#include 
> +#include 
>  #include 
>  #include 
>  #include 
> @@ -1449,6 +1451,38 @@ static void i915_kick_out_firmware_fb(struct 
> drm_i915_private *dev_priv)
>  }
>  #endif
>
> +#if !defined(CONFIG_VGA_CONSOLE)
> +static int i915_kick_out_vgacon(struct drm_i915_private *dev_priv)
> +{
> +   return 0;
> +}
> +#elif !defined(CONFIG_DUMMY_CONSOLE)

Why not "select DUMMY_CONSOLE if VT"? It's really stupid to disable
DUMMY_CONSOLE.. Furthermore, we already rely on HW_CONSOLE_BINDING so
this should be safe.

Patch looks good to me:

Reviewed-by: David Herrmann 

Thanks
David

> +static int i915_kick_out_vgacon(struct drm_i915_private *dev_priv)
> +{
> +   return -ENODEV;
> +}
> +#else
> +static int i915_kick_out_vgacon(struct drm_i915_private *dev_priv)
> +{
> +   int ret;
> +
> +   DRM_INFO("Replacing VGA console driver\n");
> +
> +   console_lock();
> +   ret = do_take_over_console(&dummy_con, 0, MAX_NR_CONSOLES - 1, 1);
> +   if (ret == 0) {
> +   ret = do_unregister_con_driver(&vga_con);
> +
> +   /* Ignore "already unregistered". */
> +   if (ret == -ENODEV)
> +   ret = 0;
> +   }
> +   console_unlock();
> +
> +   return ret;
> +}
> +#endif
> +
>  static void i915_dump_device_info(struct drm_i915_private *dev_priv)
>  {
> const struct intel_device_info *info = &dev_priv->info;
> @@ -1622,8 +1656,15 @@ int i915_driver_load(struct drm_device *dev, unsigned 
> long flags)
> if (ret)
> goto out_regs;
>
> -   if (drm_core_check_feature(dev, DRIVER_MODESET))
> +   if (drm_core_check_feature(dev, DRIVER_MODESET)) {
> +   ret = i915_kick_out_vgacon(dev_priv);
> +   if (ret) {
> +   DRM_ERROR("failed to remove conflicting VGA 
> console\n");
> +   goto out_gtt;
> +   }
> +
> i915_kick_out_firmware_fb(dev_priv);
> +   }
>
> pci_set_master(dev->pdev);
>
> diff --git a/drivers/video/console/dummycon.c 
> b/drivers/video/console/dummycon.c
> index b63860f7beab..40bec8d64b0a 100644
> --- a/drivers/video/console/dummycon.c
> +++ b/drivers/video/console/dummycon.c
> @@ -77,3 +77,4 @@ const struct consw dummy_con = {
>  .con_set_palette = DUMMY,
>  .con_scrolldelta = DUMMY,
>  };
> +EXPORT_SYMBOL_GPL(dummy_con);
> diff --git a/drivers/video/console/vgacon.c b/drivers/video/console/vgacon.c
> index 9d8feac67637..84acd6223dc5 100644
> --- a/drivers/video/console/vgacon.c
> +++ b/drivers/video/console/vgacon.c
> @@ -1440,5 +1440,6 @@ const struct consw vga_con = {
> .con_build_attr = vgacon_build_attr,
> .con_invert_region = vgacon_invert_region,
>  };
> +EXPORT_SYMBOL(vga_con);
>
>  MODULE_LICENSE("GPL");
> --
> 1.8.1.4
>


  1   2   3   4   5   6   7   8   9   10   >