Re: [Intel-gfx] [PATCH 1/3] drm: Export routines for inserting preallocated nodes into the mm manager

2012-12-12 Thread Jani Nikula
On Fri, 07 Dec 2012, Chris Wilson  wrote:
> Required by i915 in order to avoid the allocation in the middle of
> manipulating the drm_mm lists.
>
> Use a pair of stubs to preserve the existing EXPORT_SYMBOLs for
> backporting; to be removed later.

Regardless of whether you choose to do anything about the two nitpicks
below or not,

Reviewed-by: Jani Nikula 

>
> Cc: Dave Airlie 
> Cc: dri-de...@lists.freedesktop.org
> Signed-off-by: Chris Wilson 
> ---
>  drivers/gpu/drm/drm_mm.c |   42 ++
>  include/drm/drm_mm.h |   27 +++
>  2 files changed, 53 insertions(+), 16 deletions(-)
>
> diff --git a/drivers/gpu/drm/drm_mm.c b/drivers/gpu/drm/drm_mm.c
> index 0761a03..d93dc05 100644
> --- a/drivers/gpu/drm/drm_mm.c
> +++ b/drivers/gpu/drm/drm_mm.c
> @@ -184,19 +184,27 @@ EXPORT_SYMBOL(drm_mm_get_block_generic);
>   * -ENOSPC if no suitable free area is available. The preallocated memory 
> node
>   * must be cleared.
>   */
> -int drm_mm_insert_node(struct drm_mm *mm, struct drm_mm_node *node,
> -unsigned long size, unsigned alignment)
> +int drm_mm_insert_node_generic(struct drm_mm *mm, struct drm_mm_node *node,
> +unsigned long size, unsigned alignment,
> +unsigned long color, int atomic)
>  {
>   struct drm_mm_node *hole_node;
>  
> - hole_node = drm_mm_search_free(mm, size, alignment, false);
> + hole_node = drm_mm_search_free_generic(mm, size, alignment,
> +color, atomic);

The last param for drm_mm_search_free_generic is a bool, any reason not
to make atomic a bool too?

>   if (!hole_node)
>   return -ENOSPC;
>  
> - drm_mm_insert_helper(hole_node, node, size, alignment, 0);
> -
> + drm_mm_insert_helper(hole_node, node, size, alignment, color);
>   return 0;
>  }
> +EXPORT_SYMBOL(drm_mm_insert_node_generic);
> +
> +int drm_mm_insert_node(struct drm_mm *mm, struct drm_mm_node *node,
> +unsigned long size, unsigned alignment)
> +{
> + return drm_mm_insert_node_generic(mm, node, size, alignment, 0, false);
> +}
>  EXPORT_SYMBOL(drm_mm_insert_node);
>  
>  static void drm_mm_insert_helper_range(struct drm_mm_node *hole_node,
> @@ -275,22 +283,32 @@ EXPORT_SYMBOL(drm_mm_get_block_range_generic);
>   * -ENOSPC if no suitable free area is available. This is for range
>   * restricted allocations. The preallocated memory node must be cleared.
>   */
> -int drm_mm_insert_node_in_range(struct drm_mm *mm, struct drm_mm_node *node,
> - unsigned long size, unsigned alignment,
> - unsigned long start, unsigned long end)
> +int drm_mm_insert_node_in_range_generic(struct drm_mm *mm, struct 
> drm_mm_node *node,
> + unsigned long size, unsigned alignment, 
> unsigned long color,
> + unsigned long start, unsigned long end,
> + int atomic)
>  {
>   struct drm_mm_node *hole_node;
>  
> - hole_node = drm_mm_search_free_in_range(mm, size, alignment,
> - start, end, false);
> + hole_node = drm_mm_search_free_in_range_generic(mm,
> + size, alignment, color,
> + start, end, atomic);

Same as above.

>   if (!hole_node)
>   return -ENOSPC;
>  
> - drm_mm_insert_helper_range(hole_node, node, size, alignment, 0,
> + drm_mm_insert_helper_range(hole_node, node,
> +size, alignment, color,
>  start, end);
> -
>   return 0;
>  }
> +EXPORT_SYMBOL(drm_mm_insert_node_in_range_generic);
> +
> +int drm_mm_insert_node_in_range(struct drm_mm *mm, struct drm_mm_node *node,
> + unsigned long size, unsigned alignment,
> + unsigned long start, unsigned long end)
> +{
> + return drm_mm_insert_node_in_range_generic(mm, node, size, alignment, 
> 0, start, end, false);
> +}
>  EXPORT_SYMBOL(drm_mm_insert_node_in_range);
>  
>  /**
> diff --git a/include/drm/drm_mm.h b/include/drm/drm_mm.h
> index 06d7f79..87b0968 100644
> --- a/include/drm/drm_mm.h
> +++ b/include/drm/drm_mm.h
> @@ -158,12 +158,31 @@ static inline struct drm_mm_node 
> *drm_mm_get_block_atomic_range(
>   return drm_mm_get_block_range_generic(parent, size, alignment, 0,
>   start, end, 1);
>  }
> -extern int drm_mm_insert_node(struct drm_mm *mm, struct drm_mm_node *node,
> -   unsigned long size, unsigned alignment);
> +
> +extern int drm_mm_insert_node(struct drm_mm *mm,
> +   struct drm_mm_node *node,
> +   unsigned long size,
> +   

Re: [Intel-gfx] [PATCH 2/3] drm/i915: Preallocate the drm_mm_node prior to manipulating the GTT drm_mm manager

2012-12-12 Thread Jani Nikula
On Fri, 07 Dec 2012, Chris Wilson  wrote:
> As we may reap neighbouring objects in order to free up pages for
> allocations, we need to be careful not to allocate in the middle of the
> drm_mm manager. To accomplish this, we can simply allocate the
> drm_mm_node up front and then use the combined search & insert
> drm_mm routines, reducing our code footprint in the process.
>
> Fixes (partially) i-g-t/gem_tiled_swapping
>
> Reported-by: Mika Kuoppala 
> Signed-off-by: Chris Wilson 
> ---
>  drivers/gpu/drm/i915/i915_gem.c |   64 
> +--
>  1 file changed, 27 insertions(+), 37 deletions(-)
>
> diff --git a/drivers/gpu/drm/i915/i915_gem.c b/drivers/gpu/drm/i915/i915_gem.c
> index c1f6919..d17f52d 100644
> --- a/drivers/gpu/drm/i915/i915_gem.c
> +++ b/drivers/gpu/drm/i915/i915_gem.c
> @@ -2890,7 +2890,7 @@ i915_gem_object_bind_to_gtt(struct drm_i915_gem_object 
> *obj,
>  {
>   struct drm_device *dev = obj->base.dev;
>   drm_i915_private_t *dev_priv = dev->dev_private;
> - struct drm_mm_node *free_space;
> + struct drm_mm_node *node;
>   u32 size, fence_size, fence_alignment, unfenced_alignment;
>   bool mappable, fenceable;
>   int ret;
> @@ -2936,66 +2936,56 @@ i915_gem_object_bind_to_gtt(struct 
> drm_i915_gem_object *obj,
>  
>   i915_gem_object_pin_pages(obj);
>  
> + node = kzalloc(sizeof(*node), GFP_KERNEL);
> + if (node == NULL) {
> + i915_gem_object_unpin_pages(obj);
> + return -ENOMEM;
> + }

Any reason not to do the kzalloc before i915_gem_object_pin_pages, with
a slight simplification of the error path there?

Otherwise, with the disclaimer that I'm a newbie in drm mm,

Reviewed-by: Jani Nikula 


> +
>   search_free:
>   if (map_and_fenceable)
> - free_space = 
> drm_mm_search_free_in_range_color(&dev_priv->mm.gtt_space,
> -size, alignment, 
> obj->cache_level,
> -0, 
> dev_priv->mm.gtt_mappable_end,
> -false);
> + ret = 
> drm_mm_insert_node_in_range_generic(&dev_priv->mm.gtt_space, node,
> +   size, alignment, 
> obj->cache_level,
> +   0, 
> dev_priv->mm.gtt_mappable_end,
> +   false);
>   else
> - free_space = drm_mm_search_free_color(&dev_priv->mm.gtt_space,
> -   size, alignment, 
> obj->cache_level,
> -   false);
> -
> - if (free_space != NULL) {
> - if (map_and_fenceable)
> - free_space =
> - drm_mm_get_block_range_generic(free_space,
> -size, alignment, 
> obj->cache_level,
> -0, 
> dev_priv->mm.gtt_mappable_end,
> -false);
> - else
> - free_space =
> - drm_mm_get_block_generic(free_space,
> -  size, alignment, 
> obj->cache_level,
> -  false);
> - }
> - if (free_space == NULL) {
> + ret = drm_mm_insert_node_generic(&dev_priv->mm.gtt_space, node,
> +  size, alignment, 
> obj->cache_level,
> +  false);
> + if (ret) {
>   ret = i915_gem_evict_something(dev, size, alignment,
>  obj->cache_level,
>  map_and_fenceable,
>  nonblocking);
> - if (ret) {
> - i915_gem_object_unpin_pages(obj);
> - return ret;
> - }
> + if (ret == 0)
> + goto search_free;
>  
> - goto search_free;
> + i915_gem_object_unpin_pages(obj);
> + kfree(node);
> + return ret;
>   }
> - if (WARN_ON(!i915_gem_valid_gtt_space(dev,
> -   free_space,
> -   obj->cache_level))) {
> + if (WARN_ON(!i915_gem_valid_gtt_space(dev, node, obj->cache_level))) {
>   i915_gem_object_unpin_pages(obj);
> - drm_mm_put_block(free_space);
> + drm_mm_put_block(node);
>   return -EINVAL;
>   }
>  
>   ret = i915_gem_gtt_prepare_object(obj);
>   if (ret) {
>   i915_gem_object_unpin_pages(obj);
> - drm_mm_put_block(fr

Re: [Intel-gfx] [PATCH 2/3] drm/i915: Preallocate the drm_mm_node prior to manipulating the GTT drm_mm manager

2012-12-12 Thread Chris Wilson
On Wed, 12 Dec 2012 12:18:35 +0200, Jani Nikula  
wrote:
> On Fri, 07 Dec 2012, Chris Wilson  wrote:
> > As we may reap neighbouring objects in order to free up pages for
> > allocations, we need to be careful not to allocate in the middle of the
> > drm_mm manager. To accomplish this, we can simply allocate the
> > drm_mm_node up front and then use the combined search & insert
> > drm_mm routines, reducing our code footprint in the process.
> >
> > Fixes (partially) i-g-t/gem_tiled_swapping
> >
> > Reported-by: Mika Kuoppala 
> > Signed-off-by: Chris Wilson 
> > ---
> >  drivers/gpu/drm/i915/i915_gem.c |   64 
> > +--
> >  1 file changed, 27 insertions(+), 37 deletions(-)
> >
> > diff --git a/drivers/gpu/drm/i915/i915_gem.c 
> > b/drivers/gpu/drm/i915/i915_gem.c
> > index c1f6919..d17f52d 100644
> > --- a/drivers/gpu/drm/i915/i915_gem.c
> > +++ b/drivers/gpu/drm/i915/i915_gem.c
> > @@ -2890,7 +2890,7 @@ i915_gem_object_bind_to_gtt(struct 
> > drm_i915_gem_object *obj,
> >  {
> > struct drm_device *dev = obj->base.dev;
> > drm_i915_private_t *dev_priv = dev->dev_private;
> > -   struct drm_mm_node *free_space;
> > +   struct drm_mm_node *node;
> > u32 size, fence_size, fence_alignment, unfenced_alignment;
> > bool mappable, fenceable;
> > int ret;
> > @@ -2936,66 +2936,56 @@ i915_gem_object_bind_to_gtt(struct 
> > drm_i915_gem_object *obj,
> >  
> > i915_gem_object_pin_pages(obj);
> >  
> > +   node = kzalloc(sizeof(*node), GFP_KERNEL);
> > +   if (node == NULL) {
> > +   i915_gem_object_unpin_pages(obj);
> > +   return -ENOMEM;
> > +   }
> 
> Any reason not to do the kzalloc before i915_gem_object_pin_pages, with
> a slight simplification of the error path there?

No reason at all. In my defense, I was trying to make the code as similar
as possible...
-Chris

-- 
Chris Wilson, Intel Open Source Technology Centre
___
Intel-gfx mailing list
Intel-gfx@lists.freedesktop.org
http://lists.freedesktop.org/mailman/listinfo/intel-gfx


Re: [Intel-gfx] [PATCH 3/3] drm/i915: Preallocate mm node for GTT mmap offset

2012-12-12 Thread Jani Nikula
On Fri, 07 Dec 2012, Chris Wilson  wrote:
> As the shrinker may be invoked for the allocation, and it may reap
> neighbouring objects in the offset range mm, we need to be careful in
> the order in which we allocate the node, search for free space and then
> insert the node into the mmap offset range manager.
>
> Fixes i-g-t/gem_tiled_swapping
>
> Reported-by: Mika Kuoppala 
> Signed-off-by: Chris Wilson 
> ---
>  drivers/gpu/drm/i915/i915_gem.c |   59 
> ---
>  1 file changed, 49 insertions(+), 10 deletions(-)
>
> diff --git a/drivers/gpu/drm/i915/i915_gem.c b/drivers/gpu/drm/i915/i915_gem.c
> index d17f52d..3ab97c6 100644
> --- a/drivers/gpu/drm/i915/i915_gem.c
> +++ b/drivers/gpu/drm/i915/i915_gem.c
> @@ -1512,14 +1512,29 @@ i915_gem_get_unfenced_gtt_alignment(struct drm_device 
> *dev,
>  static int i915_gem_object_create_mmap_offset(struct drm_i915_gem_object 
> *obj)
>  {
>   struct drm_i915_private *dev_priv = obj->base.dev->dev_private;
> + struct drm_gem_mm *mm = obj->base.dev->mm_private;
> + struct drm_map_list *list;
>   int ret;
>  
> - if (obj->base.map_list.map)
> + list = &obj->base.map_list;
> + if (list->map)
>   return 0;
>  
> - ret = drm_gem_create_mmap_offset(&obj->base);
> - if (ret != -ENOSPC)
> - return ret;
> + /* Set the object up for mmap'ing */
> + list->map = kzalloc(sizeof(struct drm_map_list), GFP_KERNEL);

sizeof(struct drm_local_map) or sizeof(*list->map) instead?

Hmm, it's like this in drm_gem_create_mmap_offset too, either it's a bug
or I'm being clueless.

Other than that, with the same disclaimer as on the previous patch,

Reviewed-by: Jani Nikula 

> + if (!list->map)
> + return -ENOMEM;
> +
> + list->map->type = _DRM_GEM;
> + list->map->size = obj->base.size;
> + list->map->handle = &obj->base;
> +
> + /* Get a DRM GEM mmap offset allocated... */
> + list->file_offset_node = kzalloc(sizeof(struct drm_mm_node), 
> GFP_KERNEL);
> + if (list->file_offset_node == NULL) {
> + ret = -ENOMEM;
> + goto out_free_list;
> + }
>  
>   /* Badly fragmented mmap space? The only way we can recover
>* space is by destroying unwanted objects. We can't randomly release
> @@ -1528,13 +1543,37 @@ static int i915_gem_object_create_mmap_offset(struct 
> drm_i915_gem_object *obj)
>* offsets on purgeable objects by truncating it and marking it purged,
>* which prevents userspace from ever using that object again.
>*/
> - i915_gem_purge(dev_priv, obj->base.size >> PAGE_SHIFT);
> - ret = drm_gem_create_mmap_offset(&obj->base);
> - if (ret != -ENOSPC)
> - return ret;
> + ret = drm_mm_insert_node(&mm->offset_manager, list->file_offset_node,
> +  obj->base.size / PAGE_SIZE, 0);
> + if (ret) {
> + i915_gem_purge(dev_priv, obj->base.size >> PAGE_SHIFT);
> + ret = drm_mm_insert_node(&mm->offset_manager, 
> list->file_offset_node,
> +  obj->base.size / PAGE_SIZE, 0);
> + }
> + if (ret) {
> + i915_gem_shrink_all(dev_priv);
> + ret = drm_mm_insert_node(&mm->offset_manager, 
> list->file_offset_node,
> +  obj->base.size / PAGE_SIZE, 0);
> + }
> + if (ret) {
> + kfree(list->file_offset_node);
> + goto out_free_list;
> + }
> +
> + list->hash.key = list->file_offset_node->start;
> + ret = drm_ht_insert_item(&mm->offset_hash, &list->hash);
> + if (ret)
> + goto out_free_mm;
>  
> - i915_gem_shrink_all(dev_priv);
> - return drm_gem_create_mmap_offset(&obj->base);
> + return 0;
> +
> +out_free_mm:
> + drm_mm_put_block(list->file_offset_node);
> +out_free_list:
> + kfree(list->map);
> + list->map = NULL;
> +
> + return ret;
>  }
>  
>  static void i915_gem_object_free_mmap_offset(struct drm_i915_gem_object *obj)
> -- 
> 1.7.10.4
>
> ___
> Intel-gfx mailing list
> Intel-gfx@lists.freedesktop.org
> http://lists.freedesktop.org/mailman/listinfo/intel-gfx
___
Intel-gfx mailing list
Intel-gfx@lists.freedesktop.org
http://lists.freedesktop.org/mailman/listinfo/intel-gfx


Re: [Intel-gfx] [PATCH 3/3] drm/i915: Preallocate mm node for GTT mmap offset

2012-12-12 Thread Chris Wilson
On Wed, 12 Dec 2012 12:48:43 +0200, Jani Nikula  
wrote:
> On Fri, 07 Dec 2012, Chris Wilson  wrote:
> > As the shrinker may be invoked for the allocation, and it may reap
> > neighbouring objects in the offset range mm, we need to be careful in
> > the order in which we allocate the node, search for free space and then
> > insert the node into the mmap offset range manager.
> >
> > Fixes i-g-t/gem_tiled_swapping
> >
> > Reported-by: Mika Kuoppala 
> > Signed-off-by: Chris Wilson 
> > ---
> >  drivers/gpu/drm/i915/i915_gem.c |   59 
> > ---
> >  1 file changed, 49 insertions(+), 10 deletions(-)
> >
> > diff --git a/drivers/gpu/drm/i915/i915_gem.c 
> > b/drivers/gpu/drm/i915/i915_gem.c
> > index d17f52d..3ab97c6 100644
> > --- a/drivers/gpu/drm/i915/i915_gem.c
> > +++ b/drivers/gpu/drm/i915/i915_gem.c
> > @@ -1512,14 +1512,29 @@ i915_gem_get_unfenced_gtt_alignment(struct 
> > drm_device *dev,
> >  static int i915_gem_object_create_mmap_offset(struct drm_i915_gem_object 
> > *obj)
> >  {
> > struct drm_i915_private *dev_priv = obj->base.dev->dev_private;
> > +   struct drm_gem_mm *mm = obj->base.dev->mm_private;
> > +   struct drm_map_list *list;
> > int ret;
> >  
> > -   if (obj->base.map_list.map)
> > +   list = &obj->base.map_list;
> > +   if (list->map)
> > return 0;
> >  
> > -   ret = drm_gem_create_mmap_offset(&obj->base);
> > -   if (ret != -ENOSPC)
> > -   return ret;
> > +   /* Set the object up for mmap'ing */
> > +   list->map = kzalloc(sizeof(struct drm_map_list), GFP_KERNEL);
> 
> sizeof(struct drm_local_map) or sizeof(*list->map) instead?
> 
> Hmm, it's like this in drm_gem_create_mmap_offset too, either it's a bug
> or I'm being clueless.

You're right it's a a bug but fortunately in the safe direction, I'd
vote for sizeof(*list->map) as unequivocal.
-Chris

-- 
Chris Wilson, Intel Open Source Technology Centre
___
Intel-gfx mailing list
Intel-gfx@lists.freedesktop.org
http://lists.freedesktop.org/mailman/listinfo/intel-gfx


[Intel-gfx] [PATCH 00/37] [RFC] revamped modeset locking

2012-12-12 Thread Daniel Vetter
Hi all,

First thing first: It works, I now no longer have a few dropped frames every 10s
on my testbox here with the pageflip i-g-t tests.

Random notes:

- New design has per-crtc locks to protect the crtc input-side (pageflip,
  cursor) for r/w and the output state of the crtc (mode, dpms) as read-only. It
  also required completely revamped fb lifecycle management, those are now
  refcounted for real (which is a nice cleanup). Imo the proposed rwsem hack
  from Dave/Ajax is too ugly to life in comparison.

- Smoke tested on i915, compile tested for x86 drivers, probably all arm drivers
  trivially broken. I plan add tons of i-g-t testscases to exercise all the
  cornercases with i915 (so that lockdep has full coverage among other things)
  and at least run radeon/nouveau a bit. I also need to set up an arm
  crosscompiler. Generally testing feedback on !i915 highly welcome.

- Driver audit: I've tried to not break anything more than it already is, and
  for the big three desktop drivers fixup any related breakage I've noticed. Big
  unknown is vmwgfx since that driver is over my head. Generally review from
  driver devs is required to check all corner-cases.

- Merging, presuming people like this idea here: I think it'd be good to slurp
  in the driver changes as early as possible. The big rework probably has to go
  in with a separate pull directly to drm-next for all drivers - there are
  simply too many sync-points in this rework where all drivers need to follow
  the new rules before core drm changes can be applied.

- Having a global lock which synchronizing object destruction is a royal pain,
  since it reliably results in that locking getting in the way almost everywhere
  when trying to implement refcounting.  It's fixed now for fb & the mode_config
  mutex, but I'm already eagerly looking forward to simplifying 
dev->struct_mutex
  gem_bo cleanup rules.

- drm teardown/setup synchronization and locking is terminally broken. Insane
  volunteers welcome, I don't want to do this.

- I've mentioned that reading too much driver code causes nightmares, right?
  vmwgfx ...

Please bring on the flames.

Cheers, Daniel

Daniel Vetter (37):
  drm: review locking rules in drm_crtc.c
  drm/doc: integrate drm_crtc.c kerneldoc
  drm: add drm_modeset_lock|unlock_all
  drm/i915: rework locking for intel_dpio|sbi_read|write
  drm/i915: use drm_modeset_lock_all
  drm/gma500: use drm_modeset_lock_all
  drm/ast: use drm_modeset_lock_all
  drm/shmobile: use drm_modeset_lock_all
  drm/vmgfx: use drm_modeset_lock_all
  drm: add per-crtc locks
  drm/radeon: add W|RREG32_IDX for MM_INDEX|DATA based mmio accesss
  drm/radeon: make indirect register access concurrency-safe
  drm/nouveau: protect evo_wait/evo_kick sections with a channel mutex
  drm: only take the crtc lock for ->cursor_set
  drm: only take the crtc lock for ->cursor_move
  drm/: reorder framebuffer init sequence
  drm: revamp locking around fb creation/destruction
  drm: create drm_framebuffer_lookup
  drm/gma500: move fbcon restore to lastclose
  drm: revamp framebuffer cleanup interfaces
  drm: reference framebuffers which are on the idr
  drm: nest modeset locks within fpriv->fbs_lock
  drm/i915: fixup overlay stolen memory leak
  drm: push modeset_lock_all into ->fb_create driver callbacks
  drm: don't take modeset locks in getfb ioctl
  drm: fb refcounting for dirtyfb_ioctl
  drm: refcounting for sprite framebuffers
  drm: encapsulate crtc->set_config calls
  drm: refcounting for crtc framebuffers
  drm/i915: dump refcount into framebuffer debugfs file
  drm/vmwgfx: add proper framebuffer refcounting
  drm: optimize drm_framebuffer_remove
  drm/nouveau: try to protect nbo->pin_refcount
  drm/ttm: fix fence locking in ttm_buffer_object_transfer
  drm/radeon: fix fence locking in the pageflip callback
  drm: only grab the crtc lock for pageflips
  drm: don't hold crtc mutexes for connector ->detect callbacks

 Documentation/DocBook/drm.tmpl|4 +
 drivers/gpu/drm/ast/ast_drv.c |4 +-
 drivers/gpu/drm/ast/ast_drv.h |2 +
 drivers/gpu/drm/ast/ast_fb.c  |1 +
 drivers/gpu/drm/ast/ast_main.c|6 +-
 drivers/gpu/drm/cirrus/cirrus_fbdev.c |1 +
 drivers/gpu/drm/cirrus/cirrus_main.c  |   11 +-
 drivers/gpu/drm/drm_crtc.c|  782 +
 drivers/gpu/drm/drm_fb_cma_helper.c   |   15 +-
 drivers/gpu/drm/drm_fb_helper.c   |   26 +-
 drivers/gpu/drm/drm_fops.c|1 +
 drivers/gpu/drm/exynos/exynos_drm_fb.c|   20 +-
 drivers/gpu/drm/exynos/exynos_drm_fbdev.c |4 +-
 drivers/gpu/drm/gma500/framebuffer.c  |   29 +-
 drivers/gpu/drm/gma500/psb_drv.c  |   15 +-
 drivers/gpu/drm/i2c/ch7006_drv.c  |2 +-
 drivers/gpu/drm/i915/i915_debugfs.c   |   19 +-
 drivers/gpu/drm/i915/i915_dma.c   |4 +-
 drivers/gpu/drm/i915/i915_drv.h   |2 +-
 drivers/gpu/drm/i915/intel_disp

[Intel-gfx] [PATCH 01/37] drm: review locking rules in drm_crtc.c

2012-12-12 Thread Daniel Vetter
- config_cleanup was confused: It claimed that callers need to hold
  the modeset lock, but the connector|encoder_cleanup helpers grabbed
  that themselves (note that crtc_cleanup did _not_ grab the modeset
  lock). Which resulted in all drivers _not_ hodling the lock. Since
  this is for single-threaded cleanup code, drop the requirement from
  docs and also drop the lock_grabbing from all _cleanup functions.

- Kill the LOCKING section in the doctype, since clearly we're not
  good enough to keep them up-to-date. And misleading locking
  documentation is worse than useless (see e.g. the comment in the
  vmgfx driver about the cleanup mess). And since for most functions
  the very first line either grabs the lock or has a WARN_ON(!locked)
  the documentation doesn't really add anything.

- Instead put in some effort into explaining the only two special
  cases a bit better: config_init and config_cleanup are both called
  from single-threaded setup/teardown code, so don't do any locking.
  It's the driver's job though to enforce this.

- Where lacking, add a WARN_ON(!is_locked). Not many places though,
  since locking around fbdev setup/teardown is through-roughly screwed
  up, and so will break almost every single WARN annotation I've tried
  to add.

- Add a drm_modeset_is_locked helper - the Grate Modset Locking Rework
  will use the compiler to assist in the big reorg by renaming the
  mode lock, so start encapsulating things. Unfortunately this ended
  up in the "wrong" header file since it needs the definition of
  struct drm_device.

v2: Drop most WARNS again - we hit them all over the place, mostly in
the setup and teardown sequences. And trying to fix it up leads to
nice deadlocks, since the locking in the setup code is really
inconsistent.

Signed-off-by: Daniel Vetter 
---
 drivers/gpu/drm/drm_crtc.c |  105 ++--
 include/drm/drmP.h |5 +++
 2 files changed, 18 insertions(+), 92 deletions(-)

diff --git a/drivers/gpu/drm/drm_crtc.c b/drivers/gpu/drm/drm_crtc.c
index d6d0072..7902d3c 100644
--- a/drivers/gpu/drm/drm_crtc.c
+++ b/drivers/gpu/drm/drm_crtc.c
@@ -208,8 +208,6 @@ char *drm_get_connector_status_name(enum 
drm_connector_status status)
  * @ptr: object pointer, used to generate unique ID
  * @type: object type
  *
- * LOCKING:
- *
  * Create a unique identifier based on @ptr in @dev's identifier space.  Used
  * for tracking modes, CRTCs and connectors.
  *
@@ -247,9 +245,6 @@ again:
  * @dev: DRM device
  * @id: ID to free
  *
- * LOCKING:
- * Caller must hold DRM mode_config lock.
- *
  * Free @id from @dev's unique identifier pool.
  */
 static void drm_mode_object_put(struct drm_device *dev,
@@ -279,9 +274,6 @@ EXPORT_SYMBOL(drm_mode_object_find);
  * drm_framebuffer_init - initialize a framebuffer
  * @dev: DRM device
  *
- * LOCKING:
- * Caller must hold mode config lock.
- *
  * Allocates an ID for the framebuffer's parent mode object, sets its mode
  * functions & device file and adds it to the master fd list.
  *
@@ -317,15 +309,12 @@ static void drm_framebuffer_free(struct kref *kref)
 
 /**
  * drm_framebuffer_unreference - unref a framebuffer
- *
- * LOCKING:
- * Caller must hold mode config lock.
  */
 void drm_framebuffer_unreference(struct drm_framebuffer *fb)
 {
struct drm_device *dev = fb->dev;
DRM_DEBUG("FB ID: %d\n", fb->base.id);
-   WARN_ON(!mutex_is_locked(&dev->mode_config.mutex));
+   WARN_ON(!drm_modeset_is_locked(dev));
kref_put(&fb->refcount, drm_framebuffer_free);
 }
 EXPORT_SYMBOL(drm_framebuffer_unreference);
@@ -344,15 +333,13 @@ EXPORT_SYMBOL(drm_framebuffer_reference);
  * drm_framebuffer_cleanup - remove a framebuffer object
  * @fb: framebuffer to remove
  *
- * LOCKING:
- * Caller must hold mode config lock.
- *
  * Scans all the CRTCs in @dev's mode_config.  If they're using @fb, removes
  * it, setting it to NULL.
  */
 void drm_framebuffer_cleanup(struct drm_framebuffer *fb)
 {
struct drm_device *dev = fb->dev;
+
/*
 * This could be moved to drm_framebuffer_remove(), but for
 * debugging is nice to keep around the list of fb's that are
@@ -370,9 +357,6 @@ EXPORT_SYMBOL(drm_framebuffer_cleanup);
  * drm_framebuffer_remove - remove and unreference a framebuffer object
  * @fb: framebuffer to remove
  *
- * LOCKING:
- * Caller must hold mode config lock.
- *
  * Scans all the CRTCs and planes in @dev's mode_config.  If they're
  * using @fb, removes it, setting it to NULL.
  */
@@ -384,6 +368,8 @@ void drm_framebuffer_remove(struct drm_framebuffer *fb)
struct drm_mode_set set;
int ret;
 
+   WARN_ON(!drm_modeset_is_locked(dev));
+
/* remove from any CRTC */
list_for_each_entry(crtc, &dev->mode_config.crtc_list, head) {
if (crtc->fb == fb) {
@@ -421,9 +407,6 @@ EXPORT_SYMBOL(drm_framebuffer_remove);
  * @crtc: CRTC object to init
  * @funcs: callbacks for the new CRTC
  *
- * LOCKING:
- * 

[Intel-gfx] [PATCH 02/37] drm/doc: integrate drm_crtc.c kerneldoc

2012-12-12 Thread Daniel Vetter
And do a quick pass to adjust them to the last few (years?) of changes
...

This time actually compile-tested ;-)

Signed-off-by: Daniel Vetter 
---
 Documentation/DocBook/drm.tmpl |4 ++
 drivers/gpu/drm/drm_crtc.c |   92 +++-
 2 files changed, 48 insertions(+), 48 deletions(-)

diff --git a/Documentation/DocBook/drm.tmpl b/Documentation/DocBook/drm.tmpl
index 4ee2304..caab791 100644
--- a/Documentation/DocBook/drm.tmpl
+++ b/Documentation/DocBook/drm.tmpl
@@ -1609,6 +1609,10 @@ void intel_crt_init(struct drm_device *dev)
 make its properties available to applications.
   
 
+
+  KMS API Functions
+!Edrivers/gpu/drm/drm_crtc.c
+
   
 
   
diff --git a/drivers/gpu/drm/drm_crtc.c b/drivers/gpu/drm/drm_crtc.c
index 7902d3c..f22d4a7 100644
--- a/drivers/gpu/drm/drm_crtc.c
+++ b/drivers/gpu/drm/drm_crtc.c
@@ -203,10 +203,10 @@ char *drm_get_connector_status_name(enum 
drm_connector_status status)
 }
 
 /**
- * drm_mode_object_get - allocate a new identifier
+ * drm_mode_object_get - allocate a new modeset identifier
  * @dev: DRM device
- * @ptr: object pointer, used to generate unique ID
- * @type: object type
+ * @obj: object pointer, used to generate unique ID
+ * @obj_type: object type
  *
  * Create a unique identifier based on @ptr in @dev's identifier space.  Used
  * for tracking modes, CRTCs and connectors.
@@ -241,9 +241,9 @@ again:
 }
 
 /**
- * drm_mode_object_put - free an identifer
+ * drm_mode_object_put - free a modeset identifer
  * @dev: DRM device
- * @id: ID to free
+ * @object: object to free
  *
  * Free @id from @dev's unique identifier pool.
  */
@@ -273,6 +273,8 @@ EXPORT_SYMBOL(drm_mode_object_find);
 /**
  * drm_framebuffer_init - initialize a framebuffer
  * @dev: DRM device
+ * @fb: framebuffer to be initialized
+ * @funcs: ... with these functions
  *
  * Allocates an ID for the framebuffer's parent mode object, sets its mode
  * functions & device file and adds it to the master fd list.
@@ -309,6 +311,9 @@ static void drm_framebuffer_free(struct kref *kref)
 
 /**
  * drm_framebuffer_unreference - unref a framebuffer
+ * @fb: framebuffer to unref
+ *
+ * This functions decrements the fb's refcount and frees it if it drops to 
zero.
  */
 void drm_framebuffer_unreference(struct drm_framebuffer *fb)
 {
@@ -321,6 +326,7 @@ EXPORT_SYMBOL(drm_framebuffer_unreference);
 
 /**
  * drm_framebuffer_reference - incr the fb refcnt
+ * @fb: framebuffer
  */
 void drm_framebuffer_reference(struct drm_framebuffer *fb)
 {
@@ -493,7 +499,7 @@ EXPORT_SYMBOL(drm_mode_remove);
  * @dev: DRM device
  * @connector: the connector to init
  * @funcs: callbacks for this connector
- * @name: user visible name of the connector
+ * @connector_type: user visible type of the connector
  *
  * Initialises a preallocated connector. Connectors should be
  * subclassed as part of driver connector objects.
@@ -1145,10 +1151,9 @@ static int drm_crtc_convert_umode(struct 
drm_display_mode *out,
 
 /**
  * drm_mode_getresources - get graphics configuration
- * @inode: inode from the ioctl
- * @filp: file * from the ioctl
- * @cmd: cmd from ioctl
- * @arg: arg from ioctl
+ * @dev: drm device for the ioctl
+ * @data: data pointer for the ioctl
+ * @file_priv: drm file for the ioctl call
  *
  * Construct a set of configuration description structures and return
  * them to the user, including CRTC, connector and framebuffer configuration.
@@ -1330,10 +1335,9 @@ out:
 
 /**
  * drm_mode_getcrtc - get CRTC configuration
- * @inode: inode from the ioctl
- * @filp: file * from the ioctl
- * @cmd: cmd from ioctl
- * @arg: arg from ioctl
+ * @dev: drm device for the ioctl
+ * @data: data pointer for the ioctl
+ * @file_priv: drm file for the ioctl call
  *
  * Construct a CRTC configuration structure to return to the user.
  *
@@ -1387,10 +1391,9 @@ out:
 
 /**
  * drm_mode_getconnector - get connector configuration
- * @inode: inode from the ioctl
- * @filp: file * from the ioctl
- * @cmd: cmd from ioctl
- * @arg: arg from ioctl
+ * @dev: drm device for the ioctl
+ * @data: data pointer for the ioctl
+ * @file_priv: drm file for the ioctl call
  *
  * Construct a connector configuration structure to return to the user.
  *
@@ -1675,7 +1678,7 @@ out:
  * drm_mode_setplane - set up or tear down an plane
  * @dev: DRM device
  * @data: ioctl data*
- * @file_prive: DRM file info
+ * @file_priv: DRM file info
  *
  * Set plane info, including placement, fb, scaling, and other factors.
  * Or pass a NULL fb to disable.
@@ -1801,10 +1804,9 @@ out:
 
 /**
  * drm_mode_setcrtc - set CRTC configuration
- * @inode: inode from the ioctl
- * @filp: file * from the ioctl
- * @cmd: cmd from ioctl
- * @arg: arg from ioctl
+ * @dev: drm device for the ioctl
+ * @data: data pointer for the ioctl
+ * @file_priv: drm file for the ioctl call
  *
  * Build a new CRTC configuration based on user request.
  *
@@ -2056,10 +2058,9 @@ EXPORT_SYMBOL(drm_mode_legacy_fb_format);
 
 /

[Intel-gfx] [PATCH 03/37] drm: add drm_modeset_lock|unlock_all

2012-12-12 Thread Daniel Vetter
This is the first step towards introducing the new modeset locking
scheme. The plan is to put helper functions into place at all the
right places step-by-step, so that the final patch to switch on the
new locking scheme doesn't need to touch every single driver.

This helper here will serve as the shotgun solutions for all places
where a more fine-grained locking isn't (yet) implemented.

Signed-off-by: Daniel Vetter 
---
 drivers/gpu/drm/drm_crtc.c|  147 +
 drivers/gpu/drm/drm_crtc_helper.c |8 +-
 drivers/gpu/drm/drm_fb_helper.c   |   20 ++---
 include/drm/drm_crtc.h|3 +
 4 files changed, 102 insertions(+), 76 deletions(-)

diff --git a/drivers/gpu/drm/drm_crtc.c b/drivers/gpu/drm/drm_crtc.c
index f22d4a7..5d223af 100644
--- a/drivers/gpu/drm/drm_crtc.c
+++ b/drivers/gpu/drm/drm_crtc.c
@@ -37,6 +37,29 @@
 #include 
 #include 
 
+/**
+ * drm_modeset_lock_all - take all modeset locks
+ * @dev: drm device
+ *
+ * This function takes all modeset locks, suitable where a more fine-grained
+ * scheme isn't (yet) implemented.
+ */
+void drm_modeset_lock_all(struct drm_device *dev)
+{
+   mutex_lock(&dev->mode_config.mutex);
+}
+EXPORT_SYMBOL(drm_modeset_lock_all);
+
+/**
+ * drm_modeset_unlock_all - drop all modeset locks
+ * @drm: device
+ */
+void drm_modeset_unlock_all(struct drm_device *dev)
+{
+   mutex_unlock(&dev->mode_config.mutex);
+}
+EXPORT_SYMBOL(drm_modeset_unlock_all);
+
 /* Avoid boilerplate.  I'm tired of typing. */
 #define DRM_ENUM_NAME_FN(fnname, list) \
char *fnname(int val)   \
@@ -427,7 +450,7 @@ int drm_crtc_init(struct drm_device *dev, struct drm_crtc 
*crtc,
crtc->funcs = funcs;
crtc->invert_dimensions = false;
 
-   mutex_lock(&dev->mode_config.mutex);
+   drm_modeset_lock_all(dev);
 
ret = drm_mode_object_get(dev, &crtc->base, DRM_MODE_OBJECT_CRTC);
if (ret)
@@ -439,7 +462,7 @@ int drm_crtc_init(struct drm_device *dev, struct drm_crtc 
*crtc,
dev->mode_config.num_crtc++;
 
  out:
-   mutex_unlock(&dev->mode_config.mutex);
+   drm_modeset_unlock_all(dev);
 
return ret;
 }
@@ -514,7 +537,7 @@ int drm_connector_init(struct drm_device *dev,
 {
int ret;
 
-   mutex_lock(&dev->mode_config.mutex);
+   drm_modeset_lock_all(dev);
 
ret = drm_mode_object_get(dev, &connector->base, 
DRM_MODE_OBJECT_CONNECTOR);
if (ret)
@@ -544,7 +567,7 @@ int drm_connector_init(struct drm_device *dev,
  dev->mode_config.dpms_property, 0);
 
  out:
-   mutex_unlock(&dev->mode_config.mutex);
+   drm_modeset_unlock_all(dev);
 
return ret;
 }
@@ -594,7 +617,7 @@ int drm_encoder_init(struct drm_device *dev,
 {
int ret;
 
-   mutex_lock(&dev->mode_config.mutex);
+   drm_modeset_lock_all(dev);
 
ret = drm_mode_object_get(dev, &encoder->base, DRM_MODE_OBJECT_ENCODER);
if (ret)
@@ -608,7 +631,7 @@ int drm_encoder_init(struct drm_device *dev,
dev->mode_config.num_encoder++;
 
  out:
-   mutex_unlock(&dev->mode_config.mutex);
+   drm_modeset_unlock_all(dev);
 
return ret;
 }
@@ -617,11 +640,11 @@ EXPORT_SYMBOL(drm_encoder_init);
 void drm_encoder_cleanup(struct drm_encoder *encoder)
 {
struct drm_device *dev = encoder->dev;
-   mutex_lock(&dev->mode_config.mutex);
+   drm_modeset_lock_all(dev);
drm_mode_object_put(dev, &encoder->base);
list_del(&encoder->head);
dev->mode_config.num_encoder--;
-   mutex_unlock(&dev->mode_config.mutex);
+   drm_modeset_unlock_all(dev);
 }
 EXPORT_SYMBOL(drm_encoder_cleanup);
 
@@ -633,7 +656,7 @@ int drm_plane_init(struct drm_device *dev, struct drm_plane 
*plane,
 {
int ret;
 
-   mutex_lock(&dev->mode_config.mutex);
+   drm_modeset_lock_all(dev);
 
ret = drm_mode_object_get(dev, &plane->base, DRM_MODE_OBJECT_PLANE);
if (ret)
@@ -667,7 +690,7 @@ int drm_plane_init(struct drm_device *dev, struct drm_plane 
*plane,
}
 
  out:
-   mutex_unlock(&dev->mode_config.mutex);
+   drm_modeset_unlock_all(dev);
 
return ret;
 }
@@ -677,7 +700,7 @@ void drm_plane_cleanup(struct drm_plane *plane)
 {
struct drm_device *dev = plane->dev;
 
-   mutex_lock(&dev->mode_config.mutex);
+   drm_modeset_lock_all(dev);
kfree(plane->format_types);
drm_mode_object_put(dev, &plane->base);
/* if not added to a list, it must be a private plane */
@@ -685,7 +708,7 @@ void drm_plane_cleanup(struct drm_plane *plane)
list_del(&plane->head);
dev->mode_config.num_plane--;
}
-   mutex_unlock(&dev->mode_config.mutex);
+   drm_modeset_unlock_all(dev);
 }
 EXPORT_SYMBOL(drm_plane_cleanup);
 
@@ -965,9 +988,9 @@ void drm_mode_config_init(struct drm_device *dev)
INIT_LIST_HEAD(&dev->mode_config.plane_list

[Intel-gfx] [PATCH 04/37] drm/i915: rework locking for intel_dpio|sbi_read|write

2012-12-12 Thread Daniel Vetter
Spinning for up to 200 us with interrupts locked out is not good. So
let's just spin (and even that seems to be excessive).

And we don't call these functions from interrupt context, so this is
not required. Besides that doing anything in interrupt contexts which
might take a few hundred us is a no-go. So just convert the entire
thing to a mutex. Also move the mutex-grabbing out of the read/write
functions (add a WARN_ON(!is_locked)) instead) since all callers are
nicely grouped together.

Finally the real motivation for this change: Dont grab the modeset
mutex in the dpio debugfs file, we don't need that consistency. And
correctness of the dpio interface is ensured with the dpio_lock.

Signed-off-by: Daniel Vetter 
---
 drivers/gpu/drm/i915/i915_debugfs.c  |4 +--
 drivers/gpu/drm/i915/i915_dma.c  |2 +-
 drivers/gpu/drm/i915/i915_drv.h  |2 +-
 drivers/gpu/drm/i915/intel_display.c |   53 ++
 4 files changed, 25 insertions(+), 36 deletions(-)

diff --git a/drivers/gpu/drm/i915/i915_debugfs.c 
b/drivers/gpu/drm/i915/i915_debugfs.c
index 58e6676..35d2ace 100644
--- a/drivers/gpu/drm/i915/i915_debugfs.c
+++ b/drivers/gpu/drm/i915/i915_debugfs.c
@@ -1553,7 +1553,7 @@ static int i915_dpio_info(struct seq_file *m, void *data)
return 0;
}
 
-   ret = mutex_lock_interruptible(&dev->mode_config.mutex);
+   ret = mutex_lock_interruptible(&dev_priv->dpio_lock);
if (ret)
return ret;
 
@@ -1582,7 +1582,7 @@ static int i915_dpio_info(struct seq_file *m, void *data)
seq_printf(m, "DPIO_FASTCLK_DISABLE: 0x%08x\n",
   intel_dpio_read(dev_priv, DPIO_FASTCLK_DISABLE));
 
-   mutex_unlock(&dev->mode_config.mutex);
+   mutex_unlock(&dev_priv->dpio_lock);
 
return 0;
 }
diff --git a/drivers/gpu/drm/i915/i915_dma.c b/drivers/gpu/drm/i915/i915_dma.c
index 2635ee6..ad488f6 100644
--- a/drivers/gpu/drm/i915/i915_dma.c
+++ b/drivers/gpu/drm/i915/i915_dma.c
@@ -1579,7 +1579,7 @@ int i915_driver_load(struct drm_device *dev, unsigned 
long flags)
spin_lock_init(&dev_priv->irq_lock);
spin_lock_init(&dev_priv->error_lock);
spin_lock_init(&dev_priv->rps.lock);
-   spin_lock_init(&dev_priv->dpio_lock);
+   mutex_init(&dev_priv->dpio_lock);
 
mutex_init(&dev_priv->rps.hw_lock);
 
diff --git a/drivers/gpu/drm/i915/i915_drv.h b/drivers/gpu/drm/i915/i915_drv.h
index e2944e9..6fa0c00 100644
--- a/drivers/gpu/drm/i915/i915_drv.h
+++ b/drivers/gpu/drm/i915/i915_drv.h
@@ -655,7 +655,7 @@ typedef struct drm_i915_private {
spinlock_t irq_lock;
 
/* DPIO indirect register protection */
-   spinlock_t dpio_lock;
+   struct mutex dpio_lock;
 
/** Cached value of IMR to avoid reads in updating the bitfield */
u32 pipestat[2];
diff --git a/drivers/gpu/drm/i915/intel_display.c 
b/drivers/gpu/drm/i915/intel_display.c
index d303f2a..a0d8869 100644
--- a/drivers/gpu/drm/i915/intel_display.c
+++ b/drivers/gpu/drm/i915/intel_display.c
@@ -416,13 +416,11 @@ static const intel_limit_t intel_limits_vlv_dp = {
 
 u32 intel_dpio_read(struct drm_i915_private *dev_priv, int reg)
 {
-   unsigned long flags;
-   u32 val = 0;
+   WARN_ON(!mutex_is_locked(&dev_priv->dpio_lock));
 
-   spin_lock_irqsave(&dev_priv->dpio_lock, flags);
if (wait_for_atomic_us((I915_READ(DPIO_PKT) & DPIO_BUSY) == 0, 100)) {
DRM_ERROR("DPIO idle wait timed out\n");
-   goto out_unlock;
+   return 0;
}
 
I915_WRITE(DPIO_REG, reg);
@@ -430,24 +428,20 @@ u32 intel_dpio_read(struct drm_i915_private *dev_priv, 
int reg)
   DPIO_BYTE);
if (wait_for_atomic_us((I915_READ(DPIO_PKT) & DPIO_BUSY) == 0, 100)) {
DRM_ERROR("DPIO read wait timed out\n");
-   goto out_unlock;
+   return 0;
}
-   val = I915_READ(DPIO_DATA);
 
-out_unlock:
-   spin_unlock_irqrestore(&dev_priv->dpio_lock, flags);
-   return val;
+   return I915_READ(DPIO_DATA);
 }
 
 static void intel_dpio_write(struct drm_i915_private *dev_priv, int reg,
 u32 val)
 {
-   unsigned long flags;
+   WARN_ON(!mutex_is_locked(&dev_priv->dpio_lock));
 
-   spin_lock_irqsave(&dev_priv->dpio_lock, flags);
if (wait_for_atomic_us((I915_READ(DPIO_PKT) & DPIO_BUSY) == 0, 100)) {
DRM_ERROR("DPIO idle wait timed out\n");
-   goto out_unlock;
+   return;
}
 
I915_WRITE(DPIO_DATA, val);
@@ -456,9 +450,6 @@ static void intel_dpio_write(struct drm_i915_private 
*dev_priv, int reg,
   DPIO_BYTE);
if (wait_for_atomic_us((I915_READ(DPIO_PKT) & DPIO_BUSY) == 0, 100))
DRM_ERROR("DPIO write wait timed out\n");
-
-out_unlock:
-   spin_unlock_irqrestore(&dev_priv->dpio_lock, flags);
 }
 
 static void vlv_init_dpio(struct drm_device *dev)
@@

[Intel-gfx] [PATCH 05/37] drm/i915: use drm_modeset_lock_all

2012-12-12 Thread Daniel Vetter
Two exceptions:
- debugfs files only read information which is not related to crtc, so
  can stay on the modeset_config lock.
- Same holds for the edp vdd work in intel_dp.c. Add a corresponding
  WARN_ON and a comment next to the intel_dp struct fields for
  documentation.

Signed-off-by: Daniel Vetter 
---
 drivers/gpu/drm/i915/intel_dp.c  |2 ++
 drivers/gpu/drm/i915/intel_fb.c  |4 ++--
 drivers/gpu/drm/i915/intel_lvds.c|4 ++--
 drivers/gpu/drm/i915/intel_overlay.c |   14 +++---
 drivers/gpu/drm/i915/intel_sprite.c  |8 
 5 files changed, 17 insertions(+), 15 deletions(-)

diff --git a/drivers/gpu/drm/i915/intel_dp.c b/drivers/gpu/drm/i915/intel_dp.c
index b51043e..66ec9ca 100644
--- a/drivers/gpu/drm/i915/intel_dp.c
+++ b/drivers/gpu/drm/i915/intel_dp.c
@@ -1052,6 +1052,8 @@ static void ironlake_panel_vdd_off_sync(struct intel_dp 
*intel_dp)
struct drm_i915_private *dev_priv = dev->dev_private;
u32 pp;
 
+   WARN_ON(!mutex_is_locked(&dev->mode_config.mutex));
+
if (!intel_dp->want_panel_vdd && ironlake_edp_have_panel_vdd(intel_dp)) 
{
pp = ironlake_get_pp_control(dev_priv);
pp &= ~EDP_FORCE_VDD;
diff --git a/drivers/gpu/drm/i915/intel_fb.c b/drivers/gpu/drm/i915/intel_fb.c
index b7773e5..ed7bb33 100644
--- a/drivers/gpu/drm/i915/intel_fb.c
+++ b/drivers/gpu/drm/i915/intel_fb.c
@@ -282,7 +282,7 @@ void intel_fb_restore_mode(struct drm_device *dev)
struct drm_mode_config *config = &dev->mode_config;
struct drm_plane *plane;
 
-   mutex_lock(&dev->mode_config.mutex);
+   drm_modeset_lock_all(dev);
 
ret = drm_fb_helper_restore_fbdev_mode(&dev_priv->fbdev->helper);
if (ret)
@@ -292,5 +292,5 @@ void intel_fb_restore_mode(struct drm_device *dev)
list_for_each_entry(plane, &config->plane_list, head)
plane->funcs->disable_plane(plane);
 
-   mutex_unlock(&dev->mode_config.mutex);
+   drm_modeset_unlock_all(dev);
 }
diff --git a/drivers/gpu/drm/i915/intel_lvds.c 
b/drivers/gpu/drm/i915/intel_lvds.c
index 7781069..2719665 100644
--- a/drivers/gpu/drm/i915/intel_lvds.c
+++ b/drivers/gpu/drm/i915/intel_lvds.c
@@ -586,9 +586,9 @@ static int intel_lid_notify(struct notifier_block *nb, 
unsigned long val,
 
dev_priv->modeset_on_lid = 0;
 
-   mutex_lock(&dev->mode_config.mutex);
+   drm_modeset_lock_all(dev);
intel_modeset_setup_hw_state(dev, true);
-   mutex_unlock(&dev->mode_config.mutex);
+   drm_modeset_unlock_all(dev);
 
return NOTIFY_OK;
 }
diff --git a/drivers/gpu/drm/i915/intel_overlay.c 
b/drivers/gpu/drm/i915/intel_overlay.c
index fabe0ac..1e901c3 100644
--- a/drivers/gpu/drm/i915/intel_overlay.c
+++ b/drivers/gpu/drm/i915/intel_overlay.c
@@ -1045,13 +1045,13 @@ int intel_overlay_put_image(struct drm_device *dev, 
void *data,
}
 
if (!(put_image_rec->flags & I915_OVERLAY_ENABLE)) {
-   mutex_lock(&dev->mode_config.mutex);
+   drm_modeset_lock_all(dev);
mutex_lock(&dev->struct_mutex);
 
ret = intel_overlay_switch_off(overlay);
 
mutex_unlock(&dev->struct_mutex);
-   mutex_unlock(&dev->mode_config.mutex);
+   drm_modeset_unlock_all(dev);
 
return ret;
}
@@ -1075,7 +1075,7 @@ int intel_overlay_put_image(struct drm_device *dev, void 
*data,
goto out_free;
}
 
-   mutex_lock(&dev->mode_config.mutex);
+   drm_modeset_lock_all(dev);
mutex_lock(&dev->struct_mutex);
 
if (new_bo->tiling_mode) {
@@ -1157,7 +1157,7 @@ int intel_overlay_put_image(struct drm_device *dev, void 
*data,
goto out_unlock;
 
mutex_unlock(&dev->struct_mutex);
-   mutex_unlock(&dev->mode_config.mutex);
+   drm_modeset_unlock_all(dev);
 
kfree(params);
 
@@ -1165,7 +1165,7 @@ int intel_overlay_put_image(struct drm_device *dev, void 
*data,
 
 out_unlock:
mutex_unlock(&dev->struct_mutex);
-   mutex_unlock(&dev->mode_config.mutex);
+   drm_modeset_unlock_all(dev);
drm_gem_object_unreference_unlocked(&new_bo->base);
 out_free:
kfree(params);
@@ -1241,7 +1241,7 @@ int intel_overlay_attrs(struct drm_device *dev, void 
*data,
return -ENODEV;
}
 
-   mutex_lock(&dev->mode_config.mutex);
+   drm_modeset_lock_all(dev);
mutex_lock(&dev->struct_mutex);
 
ret = -EINVAL;
@@ -1307,7 +1307,7 @@ int intel_overlay_attrs(struct drm_device *dev, void 
*data,
ret = 0;
 out_unlock:
mutex_unlock(&dev->struct_mutex);
-   mutex_unlock(&dev->mode_config.mutex);
+   drm_modeset_unlock_all(dev);
 
return ret;
 }
diff --git a/drivers/gpu/drm/i915/intel_sprite.c 
b/drivers/gpu/drm/i915/intel_sprite.c
index 827dcd4..d9f45d4c 100644
--- a/drivers/gpu/drm/i915/intel_sprite.c
+++ b/drivers/gpu/drm/i915/intel_sprite.c
@@ -595,7 +595,7 @@ i

[Intel-gfx] [PATCH 06/37] drm/gma500: use drm_modeset_lock_all

2012-12-12 Thread Daniel Vetter
Only two places:
- suspend/resume
- Some really strange mode validation tool with too much funny-lucking
  hand-rolled conversion code.

Better safe than sorry, so convert both places to keep the locking
semantics as much as possible.

Signed-off-by: Daniel Vetter 
---
 drivers/gpu/drm/gma500/psb_drv.c |4 ++--
 1 file changed, 2 insertions(+), 2 deletions(-)

diff --git a/drivers/gpu/drm/gma500/psb_drv.c b/drivers/gpu/drm/gma500/psb_drv.c
index dd1fbfa..2bf0c92 100644
--- a/drivers/gpu/drm/gma500/psb_drv.c
+++ b/drivers/gpu/drm/gma500/psb_drv.c
@@ -476,7 +476,7 @@ static int psb_mode_operation_ioctl(struct drm_device *dev, 
void *data,
case PSB_MODE_OPERATION_MODE_VALID:
umode = &arg->mode;
 
-   mutex_lock(&dev->mode_config.mutex);
+   drm_modeset_lock_all(dev);
 
obj = drm_mode_object_find(dev, obj_id,
DRM_MODE_OBJECT_CONNECTOR);
@@ -525,7 +525,7 @@ static int psb_mode_operation_ioctl(struct drm_device *dev, 
void *data,
if (mode)
drm_mode_destroy(dev, mode);
 mode_op_out:
-   mutex_unlock(&dev->mode_config.mutex);
+   drm_modeset_unlock_all(dev);
return ret;
 
default:
-- 
1.7.10.4

___
Intel-gfx mailing list
Intel-gfx@lists.freedesktop.org
http://lists.freedesktop.org/mailman/listinfo/intel-gfx


[Intel-gfx] [PATCH 07/37] drm/ast: use drm_modeset_lock_all

2012-12-12 Thread Daniel Vetter
Just a call to drm_helper_resume_force_mode, obviously wants full
locking for that.

Signed-off-by: Daniel Vetter 
---
 drivers/gpu/drm/ast/ast_drv.c |4 ++--
 1 file changed, 2 insertions(+), 2 deletions(-)

diff --git a/drivers/gpu/drm/ast/ast_drv.c b/drivers/gpu/drm/ast/ast_drv.c
index 31123b6..f5f24b3 100644
--- a/drivers/gpu/drm/ast/ast_drv.c
+++ b/drivers/gpu/drm/ast/ast_drv.c
@@ -95,9 +95,9 @@ static int ast_drm_thaw(struct drm_device *dev)
ast_post_gpu(dev);
 
drm_mode_config_reset(dev);
-   mutex_lock(&dev->mode_config.mutex);
+   drm_modeset_lock_all(dev);
drm_helper_resume_force_mode(dev);
-   mutex_unlock(&dev->mode_config.mutex);
+   drm_modeset_unlock_all(dev);
 
console_lock();
ast_fbdev_set_suspend(dev, 0);
-- 
1.7.10.4

___
Intel-gfx mailing list
Intel-gfx@lists.freedesktop.org
http://lists.freedesktop.org/mailman/listinfo/intel-gfx


[Intel-gfx] [PATCH 08/37] drm/shmobile: use drm_modeset_lock_all

2012-12-12 Thread Daniel Vetter
Only a resume method to account for.

Signed-off-by: Daniel Vetter 
---
 drivers/gpu/drm/shmobile/shmob_drm_drv.c |4 ++--
 1 file changed, 2 insertions(+), 2 deletions(-)

diff --git a/drivers/gpu/drm/shmobile/shmob_drm_drv.c 
b/drivers/gpu/drm/shmobile/shmob_drm_drv.c
index 1c350fc..e77f255 100644
--- a/drivers/gpu/drm/shmobile/shmob_drm_drv.c
+++ b/drivers/gpu/drm/shmobile/shmob_drm_drv.c
@@ -313,9 +313,9 @@ static int shmob_drm_pm_resume(struct device *dev)
 {
struct shmob_drm_device *sdev = dev_get_drvdata(dev);
 
-   mutex_lock(&sdev->ddev->mode_config.mutex);
+   drm_modeset_lock_all(dev);
shmob_drm_crtc_resume(&sdev->crtc);
-   mutex_unlock(&sdev->ddev->mode_config.mutex);
+   drm_modeset_unlock_all(dev);
 
drm_kms_helper_poll_enable(sdev->ddev);
return 0;
-- 
1.7.10.4

___
Intel-gfx mailing list
Intel-gfx@lists.freedesktop.org
http://lists.freedesktop.org/mailman/listinfo/intel-gfx


[Intel-gfx] [PATCH 09/37] drm/vmgfx: use drm_modeset_lock_all

2012-12-12 Thread Daniel Vetter
Ok, this one here is a bit more complicated, but for an RFC I've
figured I can be a bit sloppy. So just convert ever mutex_lock call,
including the interruptible one. Since other places (e.g. in the
execbuf ioctl) take the mode_config.mutex without bothering with
interruptible handling, I've figured I should be able to get away with
this in a few more places ...

Signed-off-by: Daniel Vetter 
---
 drivers/gpu/drm/vmwgfx/vmwgfx_ioctl.c |   18 --
 1 file changed, 4 insertions(+), 14 deletions(-)

diff --git a/drivers/gpu/drm/vmwgfx/vmwgfx_ioctl.c 
b/drivers/gpu/drm/vmwgfx/vmwgfx_ioctl.c
index 2f7c08e..13e4371 100644
--- a/drivers/gpu/drm/vmwgfx/vmwgfx_ioctl.c
+++ b/drivers/gpu/drm/vmwgfx/vmwgfx_ioctl.c
@@ -161,11 +161,7 @@ int vmw_present_ioctl(struct drm_device *dev, void *data,
goto out_no_copy;
}
 
-   ret = mutex_lock_interruptible(&dev->mode_config.mutex);
-   if (unlikely(ret != 0)) {
-   ret = -ERESTARTSYS;
-   goto out_no_mode_mutex;
-   }
+   drm_modeset_lock_all(dev);
 
obj = drm_mode_object_find(dev, arg->fb_id, DRM_MODE_OBJECT_FB);
if (!obj) {
@@ -198,8 +194,7 @@ out_no_surface:
ttm_read_unlock(&vmaster->lock);
 out_no_ttm_lock:
 out_no_fb:
-   mutex_unlock(&dev->mode_config.mutex);
-out_no_mode_mutex:
+   drm_modeset_unlock_all(dev);
 out_no_copy:
kfree(clips);
 out_clips:
@@ -249,11 +244,7 @@ int vmw_present_readback_ioctl(struct drm_device *dev, 
void *data,
goto out_no_copy;
}
 
-   ret = mutex_lock_interruptible(&dev->mode_config.mutex);
-   if (unlikely(ret != 0)) {
-   ret = -ERESTARTSYS;
-   goto out_no_mode_mutex;
-   }
+   drm_modeset_lock_all(dev);
 
obj = drm_mode_object_find(dev, arg->fb_id, DRM_MODE_OBJECT_FB);
if (!obj) {
@@ -280,8 +271,7 @@ int vmw_present_readback_ioctl(struct drm_device *dev, void 
*data,
ttm_read_unlock(&vmaster->lock);
 out_no_ttm_lock:
 out_no_fb:
-   mutex_unlock(&dev->mode_config.mutex);
-out_no_mode_mutex:
+   drm_modeset_unlock_all(dev);
 out_no_copy:
kfree(clips);
 out_clips:
-- 
1.7.10.4

___
Intel-gfx mailing list
Intel-gfx@lists.freedesktop.org
http://lists.freedesktop.org/mailman/listinfo/intel-gfx


[Intel-gfx] [PATCH 10/37] drm: add per-crtc locks

2012-12-12 Thread Daniel Vetter
*drumroll*

The basic idea is to protect per-crtc state which can change without
touching the output configuration with separate mutexes, i.e.  all the
input side state to a crtc like framebuffers, cursor settings or plane
configuration. Holding such a crtc lock gives a read-lock on all the
other crtc state which can be changed by e.g. a modeset.

All non-crtc state is still protected by the mode_config mutex.
Callers that need to change modeset state of a crtc (e.g. dpms or
set_mode) need to grab both the mode_config lock and nested within any
crtc locks.

Note that since there can only ever be one holder of the mode_config
lock we can grab the subordinate crtc locks in any order (if we need
to grab more than one of them). Lockdep can handle such nesting with
the mutex_lock_nest_lock call correctly.

With this functions that only touch connectors/encoders but not crtcs
only need to take the mode_config lock. The biggest such case is the
output probing, which means that we can now pageflip and move cursors
while the output probe code is reading an edid.

Most cases neatly fall into the three buckets:
- Only touches connectors and similar output state and so only needs
  the mode_config lock.
- Touches the global configuration and so needs all locks.
- Only touches the crtc input side and so only needs the crtc lock.

But a few cases that need special consideration:

- Load detection which requires a crtc. The mode_config lock already
  prevents a modeset change, so we can use any unused crtc as we like
  to do load detection. The only thing to consider is that such
  temporary state changes don't leak out to userspace through ioctls
  that only take the crtc look (like a pageflip). Hence the load
  detect code needs to grab the crtc of any output pipes it touches
  (but only if it touches state used by the pageflip or cursor
  ioctls).

- Atomic pageflip when moving planes. The first case is sane hw, where
  planes have a fixed association with crtcs - nothing needs to be
  done there. More insane^Wflexible hw needs to have plane->crtc
  mapping which is separately protect with a lock that nests within
  the crtc lock. If the plane is unused we can just assign it to the
  current crtc and continue. But if a plane is already in use by
  another crtc we can't just reassign it.

  Two solution present themselves: Either go back to a slow-path which
  takes all modeset locks, potentially incure quite a hefty delay. Or
  simply disallowing such changes in one atomic pageflip - in general
  the vblanks of two crtcs are not synced, so there's no sane way to
  atomically flip such plane changes accross more than one crtc. I'd
  heavily favour the later approach, going as far as mandating it as
  part of the ABI of such a new a nuclear pageflip.

  And if we _really_ want such semantics, we can always get them by
  introducing another pageflip mutex between the mode_config.mutex and
  the individual crtc locks. Pageflips crossing more than one crtc
  would then need to take that lock first, to lock out concurrent
  multi-crtc pageflips.

- Optimized global modeset operations: We could just take the
  mode_config lock and then lazily lock all crtc which are affected by
  a modeset operation. This has the advantage that pageflip could
  continue unhampered on unaffected crtc. But if e.g. global resources
  like plls need to be reassigned and so affect unrelated crtcs we can
  still do that - nested locking works in any order.

This patch just adds the locks and takes them in drm_modeset_lock_all,
no real locking changes yet.

v2: Need to initialize the new lock in crtc_init and lock it righ
away, for otherwise the modeset_unlock_all below will try to unlock a
not-locked mutex.

Signed-off-by: Daniel Vetter 
---
 drivers/gpu/drm/drm_crtc.c |   12 
 include/drm/drm_crtc.h |9 +
 2 files changed, 21 insertions(+)

diff --git a/drivers/gpu/drm/drm_crtc.c b/drivers/gpu/drm/drm_crtc.c
index 5d223af..91e8068 100644
--- a/drivers/gpu/drm/drm_crtc.c
+++ b/drivers/gpu/drm/drm_crtc.c
@@ -46,7 +46,12 @@
  */
 void drm_modeset_lock_all(struct drm_device *dev)
 {
+   struct drm_crtc *crtc;
+
mutex_lock(&dev->mode_config.mutex);
+
+   list_for_each_entry(crtc, &dev->mode_config.crtc_list, head)
+   mutex_lock_nest_lock(&crtc->mutex, &dev->mode_config.mutex);
 }
 EXPORT_SYMBOL(drm_modeset_lock_all);
 
@@ -56,6 +61,11 @@ EXPORT_SYMBOL(drm_modeset_lock_all);
  */
 void drm_modeset_unlock_all(struct drm_device *dev)
 {
+   struct drm_crtc *crtc;
+
+   list_for_each_entry(crtc, &dev->mode_config.crtc_list, head)
+   mutex_unlock(&crtc->mutex);
+
mutex_unlock(&dev->mode_config.mutex);
 }
 EXPORT_SYMBOL(drm_modeset_unlock_all);
@@ -451,6 +461,8 @@ int drm_crtc_init(struct drm_device *dev, struct drm_crtc 
*crtc,
crtc->invert_dimensions = false;
 
drm_modeset_lock_all(dev);
+   mutex_init(&crtc->mutex);
+   mutex_lock_nest_lock(&crtc-

[Intel-gfx] [PATCH 17/37] drm: revamp locking around fb creation/destruction

2012-12-12 Thread Daniel Vetter
Well, at least step 1. The goal here is that framebuffer objects can
survive outside of the mode_config lock, with just a reference held
as protection. The first step to get there is to introduce a special
fb_lock which protects fb lookup, creation and destruction, to make
them appear atomic.

This new fb_lock can nest within the mode_config lock. But the idea is
(once the reference counting part is completed) that we only quickly
take that fb_lock to lookup a framebuffer and grab a reference,
without any other locks involved.

vmwgfx is the only driver which does framebuffer lookups itself, also
wrap those calls to drm_mode_object_find with the new lock.

Also protect the fb_list walking in i915 and omapdrm with the new lock.

As a slight complication there's also the list of user-created fbs
attached to the file private. The problem now is that at fclose() time
we need to walk that list, eventually do a modeset call to remove the
fb from active usage (and are required to be able to take the
mode_config lock), but in the end we need to grab the new fb_lock to
remove the fb from the list. The easiest solution is to add another
mutex to protect this per-file list.

Currently that new fbs_lock nests within the modeset locks and so
appears redudant. But later patches will switch around this sequence
so that taking the modeset locks in the fb destruction path is
optional in the fastpath. Ultimately the goal is that addfb and rmfb
do not require the mode_config lock, since otherwise they have the
potential to introduce stalls in the pageflip sequence of a compositor
(if the compositor e.g. switches to a fullscreen client or if it
enables a plane). But that requires a few more steps and hoops to jump
through.

Note that framebuffer creation/destruction is now double-protected -
once by the fb_lock and in parts by the idr_lock. The later would be
unnecessariy if framebuffers would have their own idr allocator. But
that's material for another patch (series).

v2: Properly initialize the fb->filp_head list in _init, otherwise the
newly added WARN to check whether the fb isn't on a fpriv list any
more will fail for driver-private objects.

Signed-off-by: Daniel Vetter 
---
 drivers/gpu/drm/drm_crtc.c |  113 ++--
 drivers/gpu/drm/drm_fops.c |1 +
 drivers/gpu/drm/i915/i915_debugfs.c|5 +-
 drivers/gpu/drm/vmwgfx/vmwgfx_ioctl.c  |4 ++
 drivers/staging/omapdrm/omap_debugfs.c |2 +
 include/drm/drmP.h |8 +++
 include/drm/drm_crtc.h |   14 
 7 files changed, 111 insertions(+), 36 deletions(-)

diff --git a/drivers/gpu/drm/drm_crtc.c b/drivers/gpu/drm/drm_crtc.c
index 3b2f25d..5a46ea1 100644
--- a/drivers/gpu/drm/drm_crtc.c
+++ b/drivers/gpu/drm/drm_crtc.c
@@ -262,15 +262,21 @@ again:
 
mutex_lock(&dev->mode_config.idr_mutex);
ret = idr_get_new_above(&dev->mode_config.crtc_idr, obj, 1, &new_id);
+
+   if (!ret) {
+   /*
+* Set up the object linking under the protection of the idr
+* lock so that other users can't see inconsistent state.
+*/
+   obj->id = new_id;
+   obj->type = obj_type;
+   }
mutex_unlock(&dev->mode_config.idr_mutex);
+
if (ret == -EAGAIN)
goto again;
-   else if (ret)
-   return ret;
 
-   obj->id = new_id;
-   obj->type = obj_type;
-   return 0;
+   return ret;
 }
 
 /**
@@ -312,6 +318,12 @@ EXPORT_SYMBOL(drm_mode_object_find);
  * Allocates an ID for the framebuffer's parent mode object, sets its mode
  * functions & device file and adds it to the master fd list.
  *
+ * IMPORTANT:
+ * This functions publishes the fb and makes it available for concurrent access
+ * by other users. Which means by this point the fb _must_ be fully set up -
+ * since all the fb attributes are invariant over its lifetime, no further
+ * locking but only correct reference counting is required.
+ *
  * RETURNS:
  * Zero on success, error code on failure.
  */
@@ -320,16 +332,19 @@ int drm_framebuffer_init(struct drm_device *dev, struct 
drm_framebuffer *fb,
 {
int ret;
 
+   mutex_lock(&dev->mode_config.fb_lock);
kref_init(&fb->refcount);
+   INIT_LIST_HEAD(&fb->filp_head);
+   fb->dev = dev;
+   fb->funcs = funcs;
 
ret = drm_mode_object_get(dev, &fb->base, DRM_MODE_OBJECT_FB);
if (ret)
return ret;
 
-   fb->dev = dev;
-   fb->funcs = funcs;
dev->mode_config.num_fb++;
list_add(&fb->head, &dev->mode_config.fb_list);
+   mutex_unlock(&dev->mode_config.fb_lock);
 
return 0;
 }
@@ -387,8 +402,10 @@ void drm_framebuffer_cleanup(struct drm_framebuffer *fb)
 * this.)
 */
drm_mode_object_put(dev, &fb->base);
+   mutex_lock(&dev->mode_config.fb_lock);
list_del(&fb->head);
dev->mode_config.num_fb--;
+   mute

[Intel-gfx] [PATCH 36/37] drm: only grab the crtc lock for pageflips

2012-12-12 Thread Daniel Vetter
The pagelip ioctl itself is rather simply, so the hard work for this
patch is auditing all the drivers:

- exynos: Pageflip is protect with dev->struct_mutex and ...
  synchronous. But nothing fancy going on, besides a check whether the
  crtc is enabled, which should probably be somewhere in the drm core
  so that we have unified behaviour across all drivers.

- i915: hw-state is protected with dev->struct_mutex, the delayed
  unpin work together with the other stuff the pageflip complete irq
  handler needs is protected by the event_lock spinlock.

- nouveau: With the pin/unpin functions fixed, everything looks safe:
  A bit of ttm wrestling and refcounting, and a few channel accesses.
  The later are either already proteced sufficiently, or are now safe
  with the channel locking introduced to make cursor updates safe.

- radeon: The irq_get/put functions look a bit race, since the
  atomic_inc/dec isn't protect with locks. Otoh they're all per-crtc,
  so we should be safe with per-crtc locking from the drm core. Then
  there's tons of per-crtc register access, which could potentially go
  through the indirect reg acces. But that's fixed to make cursor
  updates concurrent. Bookeeping for the drm even is also protected
  with the even_lock, which also protects against the pageflip irq
  handler since radeon hw seems to have no way to queue these up
  asynchronously. Otherwise just a bit of ttm-based buffer handling
  and fencing, which is now safe with the previous patch to hold
  bdev->fence_lock while grabbing the ttm fence.

- shmob: Only one crtc. That's an easy one ...

- vmwgfx: As usual a bit special with tons different things:
  - Flippable check using is_implicit and num_implicit. Changes to
those seem to be nicely covered with the global modeset lock, so
we should be fine.
  - Some dirty cliprect handling stuff, or at least that is my guess.
Looks like it's fine since either it's per-crtc, invariant or
(like the execbuf stuff launched) protected otherwise.
  - Adding the actual flip to the fence_event list. On a quick look
this seems to have solid locking in place, too.
  ... but generally this is all way over my head.

- imx: Impressive display of races between the page_flip
  implementation and the irq handler. Also, ipu_drm_set_base which
  gets eventually called from the irq handler to update the display
  base isn't really protected against concurrent set_config calls from
  process context.  In any case, going for per-crtc locking won't make
  this worse, so nothing to do.

- omap: Does just some prep work on per-crtc data and grabs a ref on
  the backing storage, then calls down into omap_gem_op_async which
  does some nicely-protected async callback stuff, or directly calls
  the passed-in page_flip_cb. That seems to lock most of the stuff it
  touches properly, safe for the eventually called omap_plane_dpms,
  which updates modeset state. Which will be a problem if this is
  called asynchronously, since the sync_op waiter callback code in
  omap_gem.c does not seem to take the right modeset locks. So looks a
  bit racy already with the old locking, and no worse off with the new
  per-crtc locks.

Signed-off-by: Daniel Vetter 
---
 drivers/gpu/drm/drm_crtc.c |7 ---
 1 file changed, 4 insertions(+), 3 deletions(-)

diff --git a/drivers/gpu/drm/drm_crtc.c b/drivers/gpu/drm/drm_crtc.c
index 6dd441c..36c75e6 100644
--- a/drivers/gpu/drm/drm_crtc.c
+++ b/drivers/gpu/drm/drm_crtc.c
@@ -3716,12 +3716,12 @@ int drm_mode_page_flip_ioctl(struct drm_device *dev,
page_flip->reserved != 0)
return -EINVAL;
 
-   drm_modeset_lock_all(dev);
obj = drm_mode_object_find(dev, page_flip->crtc_id, 
DRM_MODE_OBJECT_CRTC);
if (!obj)
-   goto out;
+   return -EINVAL;
crtc = obj_to_crtc(obj);
 
+   mutex_lock(&crtc->mutex);
if (crtc->fb == NULL) {
/* The framebuffer is currently unbound, presumably
 * due to a hotplug event, that userspace has not
@@ -3803,7 +3803,8 @@ out:
drm_framebuffer_unreference(fb);
if (old_fb)
drm_framebuffer_unreference(old_fb);
-   drm_modeset_unlock_all(dev);
+   mutex_unlock(&crtc->mutex);
+
return ret;
 }
 
-- 
1.7.10.4

___
Intel-gfx mailing list
Intel-gfx@lists.freedesktop.org
http://lists.freedesktop.org/mailman/listinfo/intel-gfx


[Intel-gfx] [PATCH 37/37] drm: don't hold crtc mutexes for connector ->detect callbacks

2012-12-12 Thread Daniel Vetter
The coup de grace of the entire journey. No more dropped frames every
10s on my testbox!

I've tried to audit all ->detect and ->get_modes callbacks, but things
became a bit fuzzy after trying to piece together the umpteenth
implemenation. Afaict most drivers just have bog-standard output
register frobbing with a notch of i2c edid reading, nothing which
could potentially race with the newly concurrent pageflip/set_cursor
code. The big exception is load-detection code which requires a
running pipe, but radeon/nouveau seem to to this without touching any
state which can be observed from page_flip (e.g. disabled crtcs
temporarily getting enabled and so a pageflip succeeding).

The only special case I could find is the i915 load detect code. That
uses the normal modeset interface to enable the load-detect crtc, and
so userspace could try to squeeze in a pageflip on the load-detect
pipe. So we need to grab the relevant crtc mutex in there, to avoid
the temporary crtc enabling to sneak out and be visible to userspace.

Note that the sysfs files already stopped grabbing the per-crtc locks,
since I didn't want to bother with doing a interruptible
modeset_lock_all. But since there's very little in-between breakage
(essentially just the ability for userspace to pageflip on load-detect
crtcs when it shouldn't on the i915 driver) I figured I don't need to
bother.

Signed-off-by: Daniel Vetter 
---
 drivers/gpu/drm/drm_crtc.c   |5 +++--
 drivers/gpu/drm/drm_crtc_helper.c|8 
 drivers/gpu/drm/i915/intel_display.c |   10 --
 3 files changed, 15 insertions(+), 8 deletions(-)

diff --git a/drivers/gpu/drm/drm_crtc.c b/drivers/gpu/drm/drm_crtc.c
index 36c75e6..313d7d2 100644
--- a/drivers/gpu/drm/drm_crtc.c
+++ b/drivers/gpu/drm/drm_crtc.c
@@ -1616,7 +1616,7 @@ int drm_mode_getconnector(struct drm_device *dev, void 
*data,
 
DRM_DEBUG_KMS("[CONNECTOR:%d:?]\n", out_resp->connector_id);
 
-   drm_modeset_lock_all(dev);
+   mutex_lock(&dev->mode_config.mutex);
 
obj = drm_mode_object_find(dev, out_resp->connector_id,
   DRM_MODE_OBJECT_CONNECTOR);
@@ -1713,7 +1713,8 @@ int drm_mode_getconnector(struct drm_device *dev, void 
*data,
out_resp->count_encoders = encoders_count;
 
 out:
-   drm_modeset_unlock_all(dev);
+   mutex_unlock(&dev->mode_config.mutex);
+
return ret;
 }
 
diff --git a/drivers/gpu/drm/drm_crtc_helper.c 
b/drivers/gpu/drm/drm_crtc_helper.c
index 400ef86..7b2d378 100644
--- a/drivers/gpu/drm/drm_crtc_helper.c
+++ b/drivers/gpu/drm/drm_crtc_helper.c
@@ -980,7 +980,7 @@ static void output_poll_execute(struct work_struct *work)
if (!drm_kms_helper_poll)
return;
 
-   drm_modeset_lock_all(dev);
+   mutex_lock(&dev->mode_config.mutex);
list_for_each_entry(connector, &dev->mode_config.connector_list, head) {
 
/* Ignore forced connectors. */
@@ -1010,7 +1010,7 @@ static void output_poll_execute(struct work_struct *work)
changed = true;
}
 
-   drm_modeset_unlock_all(dev);
+   mutex_unlock(&dev->mode_config.mutex);
 
if (changed)
drm_kms_helper_hotplug_event(dev);
@@ -1070,7 +1070,7 @@ void drm_helper_hpd_irq_event(struct drm_device *dev)
if (!dev->mode_config.poll_enabled)
return;
 
-   drm_modeset_lock_all(dev);
+   mutex_lock(&dev->mode_config.mutex);
list_for_each_entry(connector, &dev->mode_config.connector_list, head) {
 
/* Only handle HPD capable connectors. */
@@ -1088,7 +1088,7 @@ void drm_helper_hpd_irq_event(struct drm_device *dev)
changed = true;
}
 
-   drm_modeset_unlock_all(dev);
+   mutex_unlock(&dev->mode_config.mutex);
 
if (changed)
drm_kms_helper_hotplug_event(dev);
diff --git a/drivers/gpu/drm/i915/intel_display.c 
b/drivers/gpu/drm/i915/intel_display.c
index fd8cfeb..2429d39 100644
--- a/drivers/gpu/drm/i915/intel_display.c
+++ b/drivers/gpu/drm/i915/intel_display.c
@@ -6390,6 +6390,8 @@ bool intel_get_load_detect_pipe(struct drm_connector 
*connector,
if (encoder->crtc) {
crtc = encoder->crtc;
 
+   mutex_lock(&crtc->mutex);
+
old->dpms_mode = connector->dpms;
old->load_detect_temp = false;
 
@@ -6419,6 +6421,7 @@ bool intel_get_load_detect_pipe(struct drm_connector 
*connector,
return false;
}
 
+   mutex_lock(&crtc->mutex);
intel_encoder->new_crtc = to_intel_crtc(crtc);
to_intel_connector(connector)->new_encoder = intel_encoder;
 
@@ -6446,6 +6449,7 @@ bool intel_get_load_detect_pipe(struct drm_connector 
*connector,
DRM_DEBUG_KMS("reusing fbdev for load-detection framebuffer\n");
if (IS_ERR(fb)) {
DRM_DEBUG_KMS("failed to allocate framebuffer for 
load-detection\n");
+   mutex_unloc

[Intel-gfx] [PATCH 25/37] drm: don't take modeset locks in getfb ioctl

2012-12-12 Thread Daniel Vetter
We only need to push the fb unreference a bit down. While at it,
properly pass the return value from ->create_handle back to userspace.

Most drivers either return -ENODEV if they don't have a concept of
buffer objects (ast, cirrus, ...) or just install a handle for the
underlying gem object (which is ok since we hold a reference on that
through the framebuffer). But a few drivers needed tiny fixups:

- cirrus/ast/mga200: Return a consistent -ENODEV to signal to
  userspace that these drivers don't bother with implementing the
  ->create_handle callback, since it's rather pointless for them to do
  so with no accel support.

- udl: Didn't even bother with a callback, leading to a nice
  userspace-triggerable OOPS. Nice work. Fix this up and return
  -ENODEV like the other simple drivers. It could be somewhat useful
  to implement the real ->create_handle since udl buffers could be
  used with prime, but alas ...

- vmwgfx: This driver bothered with an implementation to return 0 as
  the handle (which is the canonical nofb handle). Dunno what this is
  for, but I've lost myself in vmwgfx too often. Just leave this
  as-is.

Signed-off-by: Daniel Vetter 
---
 drivers/gpu/drm/ast/ast_main.c |2 +-
 drivers/gpu/drm/cirrus/cirrus_main.c   |2 +-
 drivers/gpu/drm/drm_crtc.c |   17 ++---
 drivers/gpu/drm/mgag200/mgag200_main.c |2 +-
 drivers/gpu/drm/udl/udl_fb.c   |9 -
 5 files changed, 17 insertions(+), 15 deletions(-)

diff --git a/drivers/gpu/drm/ast/ast_main.c b/drivers/gpu/drm/ast/ast_main.c
index d5ba709..a94f13e 100644
--- a/drivers/gpu/drm/ast/ast_main.c
+++ b/drivers/gpu/drm/ast/ast_main.c
@@ -250,7 +250,7 @@ static int ast_user_framebuffer_create_handle(struct 
drm_framebuffer *fb,
  struct drm_file *file,
  unsigned int *handle)
 {
-   return -EINVAL;
+   return -ENODEV;
 }
 
 static const struct drm_framebuffer_funcs ast_fb_funcs = {
diff --git a/drivers/gpu/drm/cirrus/cirrus_main.c 
b/drivers/gpu/drm/cirrus/cirrus_main.c
index 2eac87b..e9de084 100644
--- a/drivers/gpu/drm/cirrus/cirrus_main.c
+++ b/drivers/gpu/drm/cirrus/cirrus_main.c
@@ -27,7 +27,7 @@ static int cirrus_user_framebuffer_create_handle(struct 
drm_framebuffer *fb,
 struct drm_file *file_priv,
 unsigned int *handle)
 {
-   return 0;
+   return -NODEV;
 }
 
 static const struct drm_framebuffer_funcs cirrus_fb_funcs = {
diff --git a/drivers/gpu/drm/drm_crtc.c b/drivers/gpu/drm/drm_crtc.c
index 9ad807d..28838cf 100644
--- a/drivers/gpu/drm/drm_crtc.c
+++ b/drivers/gpu/drm/drm_crtc.c
@@ -2526,29 +2526,24 @@ int drm_mode_getfb(struct drm_device *dev,
 {
struct drm_mode_fb_cmd *r = data;
struct drm_framebuffer *fb;
-   int ret = 0;
+   int ret;
 
if (!drm_core_check_feature(dev, DRIVER_MODESET))
return -EINVAL;
 
-   drm_modeset_lock_all(dev);
fb = drm_framebuffer_lookup(dev, r->fb_id);
-   if (!fb) {
-   ret = -EINVAL;
-   goto out;
-   }
-   /* fb is protect by the mode_config lock, so drop the ref immediately */
-   drm_framebuffer_unreference(fb);
+   if (!fb)
+   return -EINVAL;
 
r->height = fb->height;
r->width = fb->width;
r->depth = fb->depth;
r->bpp = fb->bits_per_pixel;
r->pitch = fb->pitches[0];
-   fb->funcs->create_handle(fb, file_priv, &r->handle);
+   ret = fb->funcs->create_handle(fb, file_priv, &r->handle);
+
+   drm_framebuffer_unreference(fb);
 
-out:
-   drm_modeset_unlock_all(dev);
return ret;
 }
 
diff --git a/drivers/gpu/drm/mgag200/mgag200_main.c 
b/drivers/gpu/drm/mgag200/mgag200_main.c
index 266438a..90fd681 100644
--- a/drivers/gpu/drm/mgag200/mgag200_main.c
+++ b/drivers/gpu/drm/mgag200/mgag200_main.c
@@ -27,7 +27,7 @@ static int mga_user_framebuffer_create_handle(struct 
drm_framebuffer *fb,
 struct drm_file *file_priv,
 unsigned int *handle)
 {
-   return 0;
+   return -ENODEV;
 }
 
 static const struct drm_framebuffer_funcs mga_fb_funcs = {
diff --git a/drivers/gpu/drm/udl/udl_fb.c b/drivers/gpu/drm/udl/udl_fb.c
index c09c04e..cb61ff7 100644
--- a/drivers/gpu/drm/udl/udl_fb.c
+++ b/drivers/gpu/drm/udl/udl_fb.c
@@ -419,10 +419,17 @@ static void udl_user_framebuffer_destroy(struct 
drm_framebuffer *fb)
kfree(ufb);
 }
 
+static int udl_user_framebuffer_create_handle(struct drm_framebuffer *fb,
+ struct drm_file *file_priv,
+ unsigned int *handle)
+{
+   return -ENODEV;
+}
+
 static const struct drm_framebuffer_funcs udlfb_funcs = {
.destroy = udl_user_framebuffer_destroy,

[Intel-gfx] [PATCH 34/37] drm/ttm: fix fence locking in ttm_buffer_object_transfer

2012-12-12 Thread Daniel Vetter
Noticed while reviewing the fence locking in the radone pageflip
handler.

Signed-off-by: Daniel Vetter 
---
 drivers/gpu/drm/ttm/ttm_bo_util.c |2 ++
 1 file changed, 2 insertions(+)

diff --git a/drivers/gpu/drm/ttm/ttm_bo_util.c 
b/drivers/gpu/drm/ttm/ttm_bo_util.c
index b9c4e51..5c8b207 100644
--- a/drivers/gpu/drm/ttm/ttm_bo_util.c
+++ b/drivers/gpu/drm/ttm/ttm_bo_util.c
@@ -441,7 +441,9 @@ static int ttm_buffer_object_transfer(struct 
ttm_buffer_object *bo,
fbo->vm_node = NULL;
atomic_set(&fbo->cpu_writers, 0);
 
+   spin_lock(&bdev->fence_lock);
fbo->sync_obj = driver->sync_obj_ref(bo->sync_obj);
+   spin_unlock(&bdev->fence_lock);
kref_init(&fbo->list_kref);
kref_init(&fbo->kref);
fbo->destroy = &ttm_transfered_destroy;
-- 
1.7.10.4

___
Intel-gfx mailing list
Intel-gfx@lists.freedesktop.org
http://lists.freedesktop.org/mailman/listinfo/intel-gfx


[Intel-gfx] [PATCH 13/37] drm/nouveau: protect evo_wait/evo_kick sections with a channel mutex

2012-12-12 Thread Daniel Vetter
With per-crtc locks modeset operations can run in parallel, and the
cursor code uses the device-global evo master channel for hw frobbing.
But the pageflip code can also sync with the master under some
circumstances. Hence just wrap things up in a mutex to ensure that
pushbuf access doesn't intermingle.

The approach here is a bit overkill since the per-crtc channels used
to schedule the pageflips could probably be used without this pushbuf
locking, but I'm not familiar enough with the nouveau codebase to be
sure of that.

Signed-off-by: Daniel Vetter 
---
 drivers/gpu/drm/nouveau/nv50_display.c |8 
 1 file changed, 8 insertions(+)

diff --git a/drivers/gpu/drm/nouveau/nv50_display.c 
b/drivers/gpu/drm/nouveau/nv50_display.c
index 3587408..5751d63 100644
--- a/drivers/gpu/drm/nouveau/nv50_display.c
+++ b/drivers/gpu/drm/nouveau/nv50_display.c
@@ -128,6 +128,11 @@ struct nv50_dmac {
struct nv50_chan base;
dma_addr_t handle;
u32 *ptr;
+
+   /* Protects against concurrent pushbuf access to this channel, lock is
+* grabbed by evo_wait (if the pushbuf reservation is successful) and
+* dropped again by evo_kick. */
+   struct mutex lock;
 };
 
 static void
@@ -395,11 +400,13 @@ evo_wait(void *evoc, int nr)
struct nv50_dmac *dmac = evoc;
u32 put = nv_ro32(dmac->base.user, 0x) / 4;
 
+   mutex_lock(&dmac->lock);
if (put + nr >= (PAGE_SIZE / 4) - 8) {
dmac->ptr[put] = 0x2000;
 
nv_wo32(dmac->base.user, 0x, 0x);
if (!nv_wait(dmac->base.user, 0x0004, ~0, 0x)) {
+   mutex_unlock(&dmac->lock);
NV_ERROR(dmac->base.user, "channel stalled\n");
return NULL;
}
@@ -415,6 +422,7 @@ evo_kick(u32 *push, void *evoc)
 {
struct nv50_dmac *dmac = evoc;
nv_wo32(dmac->base.user, 0x, (push - dmac->ptr) << 2);
+   mutex_unlock(&dmac->lock);
 }
 
 #define evo_mthd(p,m,s) *((p)++) = (((s) << 18) | (m))
-- 
1.7.10.4

___
Intel-gfx mailing list
Intel-gfx@lists.freedesktop.org
http://lists.freedesktop.org/mailman/listinfo/intel-gfx


[Intel-gfx] [PATCH 31/37] drm/vmwgfx: add proper framebuffer refcounting

2012-12-12 Thread Daniel Vetter
Afact vmwgfx already has all the right refcounting implemented on the
backing storage, and we only need to ensure that the drm fb doesn't
disappear untimely. So holding onto the fb reference from _lookup
until vmw_kms_present has completed should be enough.

Signed-off-by: Daniel Vetter 
---
 drivers/gpu/drm/vmwgfx/vmwgfx_ioctl.c |8 +++-
 1 file changed, 3 insertions(+), 5 deletions(-)

diff --git a/drivers/gpu/drm/vmwgfx/vmwgfx_ioctl.c 
b/drivers/gpu/drm/vmwgfx/vmwgfx_ioctl.c
index 4a73e9e..4a16b79 100644
--- a/drivers/gpu/drm/vmwgfx/vmwgfx_ioctl.c
+++ b/drivers/gpu/drm/vmwgfx/vmwgfx_ioctl.c
@@ -169,8 +169,6 @@ int vmw_present_ioctl(struct drm_device *dev, void *data,
ret = -EINVAL;
goto out_no_fb;
}
-   /* fb is protect by the mode_config lock, so drop the ref immediately */
-   drm_framebuffer_unreference(fb);
vfb = vmw_framebuffer_to_vfb(fb);
 
ret = ttm_read_lock(&vmaster->lock, true);
@@ -195,6 +193,7 @@ int vmw_present_ioctl(struct drm_device *dev, void *data,
 out_no_surface:
ttm_read_unlock(&vmaster->lock);
 out_no_ttm_lock:
+   drm_framebuffer_unreference(fb);
 out_no_fb:
drm_modeset_unlock_all(dev);
 out_no_copy:
@@ -254,14 +253,12 @@ int vmw_present_readback_ioctl(struct drm_device *dev, 
void *data,
ret = -EINVAL;
goto out_no_fb;
}
-   /* fb is protect by the mode_config lock, so drop the ref immediately */
-   drm_framebuffer_unreference(fb);
 
vfb = vmw_framebuffer_to_vfb(fb);
if (!vfb->dmabuf) {
DRM_ERROR("Framebuffer not dmabuf backed.\n");
ret = -EINVAL;
-   goto out_no_fb;
+   goto out_no_ttm_lock;
}
 
ret = ttm_read_lock(&vmaster->lock, true);
@@ -274,6 +271,7 @@ int vmw_present_readback_ioctl(struct drm_device *dev, void 
*data,
 
ttm_read_unlock(&vmaster->lock);
 out_no_ttm_lock:
+   drm_framebuffer_unreference(fb);
 out_no_fb:
drm_modeset_unlock_all(dev);
 out_no_copy:
-- 
1.7.10.4

___
Intel-gfx mailing list
Intel-gfx@lists.freedesktop.org
http://lists.freedesktop.org/mailman/listinfo/intel-gfx


[Intel-gfx] [PATCH 18/37] drm: create drm_framebuffer_lookup

2012-12-12 Thread Daniel Vetter
And replace all fb lookups with it. Also add a WARN to
drm_mode_object_find since that is now no longer the blessed interface
to look up an fb. And add kerneldoc to both functions.

This only updates all callsites, but immediately drops the acquired
refence again. Hence all callers still rely on the fact that a mode fb
can't disappear while they're holding the struct mutex. Subsequent
patches will instate proper use of refcounts, and then rework the rmfb
and unref code to no longer serialize fb destruction with the
mode_config lock. We don't want that since otherwise a compositor
might end up stalling for a few frames in rmfb.

v2: Don't use kreg_get_unless_zero - Greg KH doesn't like that kind of
interface.

Signed-off-by: Daniel Vetter 
---
 drivers/gpu/drm/drm_crtc.c|  109 ++---
 drivers/gpu/drm/vmwgfx/vmwgfx_ioctl.c |   24 
 include/drm/drm_crtc.h|2 +
 3 files changed, 86 insertions(+), 49 deletions(-)

diff --git a/drivers/gpu/drm/drm_crtc.c b/drivers/gpu/drm/drm_crtc.c
index 5a46ea1..75ffc3b 100644
--- a/drivers/gpu/drm/drm_crtc.c
+++ b/drivers/gpu/drm/drm_crtc.c
@@ -294,11 +294,24 @@ static void drm_mode_object_put(struct drm_device *dev,
mutex_unlock(&dev->mode_config.idr_mutex);
 }
 
+/**
+ * drm_mode_object_find - look up a drm object with static lifetime
+ * @dev: drm device
+ * @id: id of the mode object
+ * @type: type of the mode object
+ *
+ * Note that framebuffers cannot be looked up with this functions - since those
+ * are reference counted, they need special treatment.
+ */
 struct drm_mode_object *drm_mode_object_find(struct drm_device *dev,
uint32_t id, uint32_t type)
 {
struct drm_mode_object *obj = NULL;
 
+   /* Framebuffers are reference counted and need their own lookup
+* function.*/
+   WARN_ON(type == DRM_MODE_OBJECT_FB);
+
mutex_lock(&dev->mode_config.idr_mutex);
obj = idr_find(&dev->mode_config.crtc_idr, id);
if (!obj || (obj->type != type) || (obj->id != id))
@@ -358,6 +371,40 @@ static void drm_framebuffer_free(struct kref *kref)
 }
 
 /**
+ * drm_framebuffer_lookup - look up a drm framebuffer and grab a reference
+ * @dev: drm device
+ * @id: id of the fb object
+ *
+ * If successful, this grabs an additional reference to the framebuffer -
+ * callers need to make sure to eventually unreference the returned framebuffer
+ * again.
+ */
+struct drm_framebuffer *drm_framebuffer_lookup(struct drm_device *dev,
+  uint32_t id)
+{
+   struct drm_mode_object *obj = NULL;
+   struct drm_framebuffer *fb;
+
+   mutex_lock(&dev->mode_config.fb_lock);
+
+   mutex_lock(&dev->mode_config.idr_mutex);
+   obj = idr_find(&dev->mode_config.crtc_idr, id);
+   if (!obj || (obj->type != DRM_MODE_OBJECT_FB) || (obj->id != id))
+   fb = NULL;
+   else
+   fb = obj_to_fb(obj);
+   mutex_unlock(&dev->mode_config.idr_mutex);
+
+   if (fb)
+   kref_get(&fb->refcount);
+
+   mutex_unlock(&dev->mode_config.fb_lock);
+
+   return fb;
+}
+EXPORT_SYMBOL(drm_framebuffer_lookup);
+
+/**
  * drm_framebuffer_unreference - unref a framebuffer
  * @fb: framebuffer to unref
  *
@@ -1789,17 +1836,15 @@ int drm_mode_setplane(struct drm_device *dev, void 
*data,
}
crtc = obj_to_crtc(obj);
 
-   mutex_lock(&dev->mode_config.fb_lock);
-   obj = drm_mode_object_find(dev, plane_req->fb_id,
-  DRM_MODE_OBJECT_FB);
-   mutex_unlock(&dev->mode_config.fb_lock);
-   if (!obj) {
+   fb = drm_framebuffer_lookup(dev, plane_req->fb_id);
+   if (!fb) {
DRM_DEBUG_KMS("Unknown framebuffer ID %d\n",
  plane_req->fb_id);
ret = -ENOENT;
goto out;
}
-   fb = obj_to_fb(obj);
+   /* fb is protect by the mode_config lock, so drop the ref immediately */
+   drm_framebuffer_unreference(fb);
 
/* Check whether this plane supports the fb pixel format. */
for (i = 0; i < plane->format_count; i++)
@@ -1919,17 +1964,16 @@ int drm_mode_setcrtc(struct drm_device *dev, void *data,
}
fb = crtc->fb;
} else {
-   mutex_lock(&dev->mode_config.fb_lock);
-   obj = drm_mode_object_find(dev, crtc_req->fb_id,
-  DRM_MODE_OBJECT_FB);
-   mutex_unlock(&dev->mode_config.fb_lock);
-   if (!obj) {
+   fb = drm_framebuffer_lookup(dev, crtc_req->fb_id);
+   if (!fb) {
DRM_DEBUG_KMS("Unknown FB ID%d\n",
crtc_req->fb_id);
ret = -EINVAL;
goto out;
 

[Intel-gfx] [PATCH 19/37] drm/gma500: move fbcon restore to lastclose

2012-12-12 Thread Daniel Vetter
Doing this within the fb->destroy callback leads to a locking
nightmare. And all other drm drivers that restore the fbcon do
it in lastclose, too.

With this adjustments all fb->destroy callbacks optionally drop
references to any gem objects used as backing storage, call
drm_framebuffer_cleanup and then kfree the struct. Which nicely
simplifies the locking for framebuffer unreferencing and freeing,
since this doesn't require that we hold the mode_config lock. A
slight exception is the vmwgfx surface backed framebuffer, it also
calls drm_master_put and removes the object from a device-private
framebuffer list. Both seem to have solid locking in place already.

Conclusion is that now it is no longer required to hold the
mode_config lock while freeing a framebuffer.

v2: Drop the corresponding mutex_lock WARN check from
drm_framebuffer_unreference.

Signed-off-by: Daniel Vetter 
---
 drivers/gpu/drm/drm_crtc.c   |2 --
 drivers/gpu/drm/gma500/framebuffer.c |   24 
 drivers/gpu/drm/gma500/psb_drv.c |   11 +++
 3 files changed, 11 insertions(+), 26 deletions(-)

diff --git a/drivers/gpu/drm/drm_crtc.c b/drivers/gpu/drm/drm_crtc.c
index 75ffc3b..17cdd32 100644
--- a/drivers/gpu/drm/drm_crtc.c
+++ b/drivers/gpu/drm/drm_crtc.c
@@ -412,9 +412,7 @@ EXPORT_SYMBOL(drm_framebuffer_lookup);
  */
 void drm_framebuffer_unreference(struct drm_framebuffer *fb)
 {
-   struct drm_device *dev = fb->dev;
DRM_DEBUG("FB ID: %d\n", fb->base.id);
-   WARN_ON(!drm_modeset_is_locked(dev));
kref_put(&fb->refcount, drm_framebuffer_free);
 }
 EXPORT_SYMBOL(drm_framebuffer_unreference);
diff --git a/drivers/gpu/drm/gma500/framebuffer.c 
b/drivers/gpu/drm/gma500/framebuffer.c
index 38e7e75..49800d2 100644
--- a/drivers/gpu/drm/gma500/framebuffer.c
+++ b/drivers/gpu/drm/gma500/framebuffer.c
@@ -668,30 +668,6 @@ static void psb_user_framebuffer_destroy(struct 
drm_framebuffer *fb)
 {
struct psb_framebuffer *psbfb = to_psb_fb(fb);
struct gtt_range *r = psbfb->gtt;
-   struct drm_device *dev = fb->dev;
-   struct drm_psb_private *dev_priv = dev->dev_private;
-   struct psb_fbdev *fbdev = dev_priv->fbdev;
-   struct drm_crtc *crtc;
-   int reset = 0;
-
-   /* Should never get stolen memory for a user fb */
-   WARN_ON(r->stolen);
-
-   /* Check if we are erroneously live */
-   list_for_each_entry(crtc, &dev->mode_config.crtc_list, head)
-   if (crtc->fb == fb)
-   reset = 1;
-
-   if (reset)
-   /*
-* Now force a sane response before we permit the DRM CRTC
-* layer to do stupid things like blank the display. Instead
-* we reset this framebuffer as if the user had forced a reset.
-* We must do this before the cleanup so that the DRM layer
-* doesn't get a chance to stick its oar in where it isn't
-* wanted.
-*/
-   drm_fb_helper_restore_fbdev_mode(&fbdev->psb_fb_helper);
 
/* Let DRM do its clean up */
drm_framebuffer_cleanup(fb);
diff --git a/drivers/gpu/drm/gma500/psb_drv.c b/drivers/gpu/drm/gma500/psb_drv.c
index 2bf0c92..5518305 100644
--- a/drivers/gpu/drm/gma500/psb_drv.c
+++ b/drivers/gpu/drm/gma500/psb_drv.c
@@ -149,6 +149,17 @@ static struct drm_ioctl_desc psb_ioctls[] = {
 
 static void psb_lastclose(struct drm_device *dev)
 {
+   int ret;
+   struct drm_psb_private *dev_priv = dev->dev_private;
+   struct psb_fbdev *fbdev = dev_priv->fbdev;
+
+   drm_modeset_lock_all(dev);
+   ret = drm_fb_helper_restore_fbdev_mode(&fbdev->psb_fb_helper);
+   if (ret)
+   DRM_DEBUG("failed to restore crtc mode\n");
+
+   drm_modeset_unlock_all(dev);
+
return;
 }
 
-- 
1.7.10.4

___
Intel-gfx mailing list
Intel-gfx@lists.freedesktop.org
http://lists.freedesktop.org/mailman/listinfo/intel-gfx


[Intel-gfx] [PATCH 27/37] drm: refcounting for sprite framebuffers

2012-12-12 Thread Daniel Vetter
Now plane->fb holds a reference onto it's framebuffer. Nothing too
fancy going on here:
- Extract __drm_framebuffer_unreference to be called when we know
  we're not dropping the last reference, e.g. useful in the fb cleanup
  code.
- Reduce the locked sections in the set_plane ioctl to only protect
  plane->fb/plane->crtc and the driver callback (i.e. hw state).
  Everything either doesn't disappear (crtc, plane) or is refcounted
  (fb), and all the data we check is invariant over the respective
  object's lifetimes.

Signed-off-by: Daniel Vetter 
---
 drivers/gpu/drm/drm_crtc.c |   30 +-
 1 file changed, 21 insertions(+), 9 deletions(-)

diff --git a/drivers/gpu/drm/drm_crtc.c b/drivers/gpu/drm/drm_crtc.c
index 8132e13..ccf15ad 100644
--- a/drivers/gpu/drm/drm_crtc.c
+++ b/drivers/gpu/drm/drm_crtc.c
@@ -444,6 +444,12 @@ static void drm_framebuffer_free_bug(struct kref *kref)
BUG();
 }
 
+static void __drm_framebuffer_unreference(struct drm_framebuffer *fb)
+{
+   DRM_DEBUG("FB ID: %d\n", fb->base.id);
+   kref_put(&fb->refcount, drm_framebuffer_free_bug);
+}
+
 /* dev->mode_config.fb_lock must be held! */
 static void __drm_framebuffer_unregister(struct drm_device *dev,
 struct drm_framebuffer *fb)
@@ -454,7 +460,7 @@ static void __drm_framebuffer_unregister(struct drm_device 
*dev,
 
fb->base.id = 0;
 
-   kref_put(&fb->refcount, drm_framebuffer_free_bug);
+   __drm_framebuffer_unreference(fb);
 }
 
 /**
@@ -543,6 +549,7 @@ void drm_framebuffer_remove(struct drm_framebuffer *fb)
if (ret)
DRM_ERROR("failed to disable plane with busy 
fb\n");
/* disconnect the plane from the fb and crtc: */
+   __drm_framebuffer_unreference(plane->fb);
plane->fb = NULL;
plane->crtc = NULL;
}
@@ -1849,7 +1856,7 @@ int drm_mode_setplane(struct drm_device *dev, void *data,
struct drm_mode_object *obj;
struct drm_plane *plane;
struct drm_crtc *crtc;
-   struct drm_framebuffer *fb;
+   struct drm_framebuffer *fb = NULL, *old_fb = NULL;
int ret = 0;
unsigned int fb_width, fb_height;
int i;
@@ -1857,8 +1864,6 @@ int drm_mode_setplane(struct drm_device *dev, void *data,
if (!drm_core_check_feature(dev, DRIVER_MODESET))
return -EINVAL;
 
-   drm_modeset_lock_all(dev);
-
/*
 * First, find the plane, crtc, and fb objects.  If not available,
 * we don't bother to call the driver.
@@ -1868,16 +1873,18 @@ int drm_mode_setplane(struct drm_device *dev, void 
*data,
if (!obj) {
DRM_DEBUG_KMS("Unknown plane ID %d\n",
  plane_req->plane_id);
-   ret = -ENOENT;
-   goto out;
+   return -ENOENT;
}
plane = obj_to_plane(obj);
 
/* No fb means shut it down */
if (!plane_req->fb_id) {
+   drm_modeset_lock_all(dev);
+   old_fb = plane->fb;
plane->funcs->disable_plane(plane);
plane->crtc = NULL;
plane->fb = NULL;
+   drm_modeset_unlock_all(dev);
goto out;
}
 
@@ -1898,8 +1905,6 @@ int drm_mode_setplane(struct drm_device *dev, void *data,
ret = -ENOENT;
goto out;
}
-   /* fb is protect by the mode_config lock, so drop the ref immediately */
-   drm_framebuffer_unreference(fb);
 
/* Check whether this plane supports the fb pixel format. */
for (i = 0; i < plane->format_count; i++)
@@ -1945,18 +1950,25 @@ int drm_mode_setplane(struct drm_device *dev, void 
*data,
goto out;
}
 
+   drm_modeset_lock_all(dev);
ret = plane->funcs->update_plane(plane, crtc, fb,
 plane_req->crtc_x, plane_req->crtc_y,
 plane_req->crtc_w, plane_req->crtc_h,
 plane_req->src_x, plane_req->src_y,
 plane_req->src_w, plane_req->src_h);
if (!ret) {
+   old_fb = plane->fb;
+   fb = NULL;
plane->crtc = crtc;
plane->fb = fb;
}
+   drm_modeset_unlock_all(dev);
 
 out:
-   drm_modeset_unlock_all(dev);
+   if (fb)
+   drm_framebuffer_unreference(fb);
+   if (old_fb)
+   drm_framebuffer_unreference(old_fb);
 
return ret;
 }
-- 
1.7.10.4

___
Intel-gfx mailing list
Intel-gfx@lists.freedesktop.org
http://lists.freedesktop.org/mailman/listinfo/intel-gfx


[Intel-gfx] [PATCH 24/37] drm: push modeset_lock_all into ->fb_create driver callbacks

2012-12-12 Thread Daniel Vetter
And drop it where it's not needed. Most driver just lookup the gem
object, allocate an fb struct, fill in all the useful fields and then
register it with drm_framebuffer_init.

All of these operations are already separately locked, and since we
only put the fb into the fpriv->fbs list _after_ having called
->fb_create, we can't also race with rmfb. We can otoh race with other
ioctls that put the framebuffer to use, but all drivers have been
reorganized already to call drm_framebuffer_init last in the fb
creation sequence.

So essentially, we can completely remove any modeset locks from the
addfb ioctl paths. Yeah!

Also, reference-counting is solid - we get a reference from fb_create
which we transfer to the fpriv->fbs list. And after unlocking the
fpriv->fbs_lock we don't touch the framebuffer any longer. Furthermore
drm_framebuffer_init has added a 2nd reference for the idr lookup, and
any access through that table will do it's own refcounting.

Signed-off-by: Daniel Vetter 
---
 drivers/gpu/drm/drm_crtc.c |9 -
 1 file changed, 9 deletions(-)

diff --git a/drivers/gpu/drm/drm_crtc.c b/drivers/gpu/drm/drm_crtc.c
index 33e95bb..9ad807d 100644
--- a/drivers/gpu/drm/drm_crtc.c
+++ b/drivers/gpu/drm/drm_crtc.c
@@ -2255,18 +2255,12 @@ int drm_mode_addfb(struct drm_device *dev,
if ((config->min_height > r.height) || (r.height > config->max_height))
return -EINVAL;
 
-   drm_modeset_lock_all(dev);
-
-   /* TODO check buffer is sufficiently large */
-   /* TODO setup destructor callback */
-
fb = dev->mode_config.funcs->fb_create(dev, file_priv, &r);
if (IS_ERR(fb)) {
DRM_DEBUG_KMS("could not create framebuffer\n");
drm_modeset_unlock_all(dev);
return PTR_ERR(fb);
}
-   drm_modeset_unlock_all(dev);
 
mutex_lock(&file_priv->fbs_lock);
or->fb_id = fb->base.id;
@@ -2441,15 +2435,12 @@ int drm_mode_addfb2(struct drm_device *dev,
if (ret)
return ret;
 
-   drm_modeset_lock_all(dev);
-
fb = dev->mode_config.funcs->fb_create(dev, file_priv, r);
if (IS_ERR(fb)) {
DRM_DEBUG_KMS("could not create framebuffer\n");
drm_modeset_unlock_all(dev);
return PTR_ERR(fb);
}
-   drm_modeset_unlock_all(dev);
 
mutex_lock(&file_priv->fbs_lock);
r->fb_id = fb->base.id;
-- 
1.7.10.4

___
Intel-gfx mailing list
Intel-gfx@lists.freedesktop.org
http://lists.freedesktop.org/mailman/listinfo/intel-gfx


[Intel-gfx] [PATCH 23/37] drm/i915: fixup overlay stolen memory leak

2012-12-12 Thread Daniel Vetter
We need to clean up the overlay first, before taking down the
stolen memory allocator.

This regression has been introducec in

commit 8040513870399f1cb032cb8bc805df5042fedcdf
Author: Chris Wilson 
Date:   Thu Nov 15 11:32:29 2012 +

drm/i915: Allocate overlay registers from stolen memory

Note: This is just a quick hack to shut up a warning in the module
unload code, so that I can check again whether we don't leak any
framebuffers.

Cc: Chris Wilson 
Signed-off-by: Daniel Vetter 
---
 drivers/gpu/drm/i915/i915_dma.c |2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/drivers/gpu/drm/i915/i915_dma.c b/drivers/gpu/drm/i915/i915_dma.c
index ad488f6..532ad39 100644
--- a/drivers/gpu/drm/i915/i915_dma.c
+++ b/drivers/gpu/drm/i915/i915_dma.c
@@ -1720,9 +1720,9 @@ int i915_driver_unload(struct drm_device *dev)
mutex_unlock(&dev->struct_mutex);
i915_gem_cleanup_aliasing_ppgtt(dev);
i915_gem_cleanup_stolen(dev);
-   drm_mm_takedown(&dev_priv->mm.stolen);
 
intel_cleanup_overlay(dev);
+   drm_mm_takedown(&dev_priv->mm.stolen);
 
if (!I915_NEED_GFX_HWS(dev))
i915_free_hws(dev);
-- 
1.7.10.4

___
Intel-gfx mailing list
Intel-gfx@lists.freedesktop.org
http://lists.freedesktop.org/mailman/listinfo/intel-gfx


[Intel-gfx] [PATCH 32/37] drm: optimize drm_framebuffer_remove

2012-12-12 Thread Daniel Vetter
Now that all framebuffer usage is properly refcounted, we are no
longer required to hold the modeset locks while dropping the last
reference. Hence implemented a fastpath which avoids the potential
stalls associated with grabbing mode_config.lock for the case where
there's no other reference around.

Explain in a big comment why it is safe. Also update kerneldocs with
the new locking rules around drm_framebuffer_remove.

Signed-off-by: Daniel Vetter 
---
 drivers/gpu/drm/drm_crtc.c |   72 +++-
 1 file changed, 45 insertions(+), 27 deletions(-)

diff --git a/drivers/gpu/drm/drm_crtc.c b/drivers/gpu/drm/drm_crtc.c
index 6562eba..6dd441c 100644
--- a/drivers/gpu/drm/drm_crtc.c
+++ b/drivers/gpu/drm/drm_crtc.c
@@ -516,7 +516,11 @@ EXPORT_SYMBOL(drm_framebuffer_cleanup);
  *
  * Scans all the CRTCs and planes in @dev's mode_config.  If they're
  * using @fb, removes it, setting it to NULL. Then drops the reference to the
- * passed-in framebuffer.
+ * passed-in framebuffer. Might take the modeset locks.
+ *
+ * Note that this function optimizes the cleanup away if the caller holds the
+ * last reference to the framebuffer. It is also guaranteed to not take the
+ * modeset locks in this case.
  */
 void drm_framebuffer_remove(struct drm_framebuffer *fb)
 {
@@ -526,33 +530,51 @@ void drm_framebuffer_remove(struct drm_framebuffer *fb)
struct drm_mode_set set;
int ret;
 
-   WARN_ON(!drm_modeset_is_locked(dev));
WARN_ON(!list_empty(&fb->filp_head));
 
-   /* remove from any CRTC */
-   list_for_each_entry(crtc, &dev->mode_config.crtc_list, head) {
-   if (crtc->fb == fb) {
-   /* should turn off the crtc */
-   memset(&set, 0, sizeof(struct drm_mode_set));
-   set.crtc = crtc;
-   set.fb = NULL;
-   ret = drm_mode_set_config_internal(&set);
-   if (ret)
-   DRM_ERROR("failed to reset crtc %p when fb was 
deleted\n", crtc);
+   /*
+* drm ABI mandates that we remove any deleted framebuffers from active
+* useage. But since most sane clients only remove framebuffers they no
+* longer need, try to optimize this away.
+*
+* Since we're holding a reference ourselves, observing a refcount of 1
+* means that we're the last holder and can skip it. Also, the refcount
+* can never increase from 1 again, so we don't need any barriers or
+* locks.
+*
+* Note that userspace could try to race with use and instate a new
+* usage _after_ we've cleared all current ones. End result will be an
+* in-use fb with fb-id == 0. Userspace is allowed to shoot its own foot
+* in this manner.
+*/
+   if (atomic_read(&fb->refcount.refcount) > 1) {
+   drm_modeset_lock_all(dev);
+   /* remove from any CRTC */
+   list_for_each_entry(crtc, &dev->mode_config.crtc_list, head) {
+   if (crtc->fb == fb) {
+   /* should turn off the crtc */
+   memset(&set, 0, sizeof(struct drm_mode_set));
+   set.crtc = crtc;
+   set.fb = NULL;
+   ret = drm_mode_set_config_internal(&set);
+   if (ret)
+   DRM_ERROR("failed to reset crtc %p when 
fb was deleted\n", crtc);
+   }
}
-   }
 
-   list_for_each_entry(plane, &dev->mode_config.plane_list, head) {
-   if (plane->fb == fb) {
-   /* should turn off the crtc */
-   ret = plane->funcs->disable_plane(plane);
-   if (ret)
-   DRM_ERROR("failed to disable plane with busy 
fb\n");
-   /* disconnect the plane from the fb and crtc: */
-   __drm_framebuffer_unreference(plane->fb);
-   plane->fb = NULL;
-   plane->crtc = NULL;
+   list_for_each_entry(plane, &dev->mode_config.plane_list, head) {
+   if (plane->fb == fb) {
+   /* should turn off the crtc */
+   ret = plane->funcs->disable_plane(plane);
+   if (ret)
+   DRM_ERROR("failed to disable plane with 
busy fb\n");
+   /* disconnect the plane from the fb and crtc: */
+   __drm_framebuffer_unreference(plane->fb);
+   plane->fb = NULL;
+   plane->crtc = NULL;
+   }
}
+   drm_modeset_unlock_all(dev);
}
 
drm_framebuffer_unr

[Intel-gfx] [PATCH 15/37] drm: only take the crtc lock for ->cursor_move

2012-12-12 Thread Daniel Vetter
->cursor_move uses mostly the same facilities in drivers as
->cursor_set, so pretty much nothing to fix up:

- ast/gma500/i915: They all use per-crtc registers to update the
  cursor position. ast again touches the global cursor cache, but
  that's ok since there's only one crtc.

- nouveau: nv50+ is again special, updates happen through the per-crtc
  channel (without pushbufs), so it's not protected by the new evo
  lock introduced earlier. But since this channel is per-crtc, we
  should be fine anyway.

- radeon: A bit a mess: avivo asics need a workaround when both output
  pipes are enabled, which means it'll access the crtc list. Just
  reading that flag is ok though as long as radeon _always_ grabs all
  locks when changing the crtc configuration. Which means with the
  current scheme it cannot do an optimized modeset which only locks
  the relevant crtcs. This can be fixed though by introducing a bit of
  global state with separate locks and ensure in the modeset code that
  the cursor will be updated appropriately when enabling the 2nd pipe
  (on affected asics).

- vmwgfx: I still don't understand what it's doing exactly, so apply
  the same trick for now.

Signed-off-by: Daniel Vetter 
---
 drivers/gpu/drm/drm_crtc.c |6 ++
 drivers/gpu/drm/radeon/radeon_cursor.c |8 +++-
 drivers/gpu/drm/vmwgfx/vmwgfx_kms.c|   13 +
 3 files changed, 22 insertions(+), 5 deletions(-)

diff --git a/drivers/gpu/drm/drm_crtc.c b/drivers/gpu/drm/drm_crtc.c
index 62b5002..3b2f25d 100644
--- a/drivers/gpu/drm/drm_crtc.c
+++ b/drivers/gpu/drm/drm_crtc.c
@@ -2031,28 +2031,26 @@ int drm_mode_cursor_ioctl(struct drm_device *dev,
}
crtc = obj_to_crtc(obj);
 
+   mutex_lock(&crtc->mutex);
if (req->flags & DRM_MODE_CURSOR_BO) {
if (!crtc->funcs->cursor_set) {
ret = -ENXIO;
goto out;
}
/* Turns off the cursor if handle is 0 */
-   mutex_lock(&crtc->mutex);
ret = crtc->funcs->cursor_set(crtc, file_priv, req->handle,
  req->width, req->height);
-   mutex_unlock(&crtc->mutex);
}
 
if (req->flags & DRM_MODE_CURSOR_MOVE) {
if (crtc->funcs->cursor_move) {
-   drm_modeset_lock_all(dev);
ret = crtc->funcs->cursor_move(crtc, req->x, req->y);
-   drm_modeset_unlock_all(dev);
} else {
ret = -EFAULT;
goto out;
}
}
+   mutex_unlock(&crtc->mutex);
 out:
return ret;
 }
diff --git a/drivers/gpu/drm/radeon/radeon_cursor.c 
b/drivers/gpu/drm/radeon/radeon_cursor.c
index ad6df62..c1680e6 100644
--- a/drivers/gpu/drm/radeon/radeon_cursor.c
+++ b/drivers/gpu/drm/radeon/radeon_cursor.c
@@ -245,8 +245,14 @@ int radeon_crtc_cursor_move(struct drm_crtc *crtc,
int i = 0;
struct drm_crtc *crtc_p;
 
-   /* avivo cursor image can't end on 128 pixel boundary or
+   /*
+* avivo cursor image can't end on 128 pixel boundary or
 * go past the end of the frame if both crtcs are enabled
+*
+* NOTE: It is safe to access crtc->enabled of other crtcs
+* without holding either the mode_config lock or the other
+* crtc's lock as long as write access to this flag _always_
+* grabs all locks.
 */
list_for_each_entry(crtc_p, &crtc->dev->mode_config.crtc_list, 
head) {
if (crtc_p->enabled)
diff --git a/drivers/gpu/drm/vmwgfx/vmwgfx_kms.c 
b/drivers/gpu/drm/vmwgfx/vmwgfx_kms.c
index 74b6734..385b8849 100644
--- a/drivers/gpu/drm/vmwgfx/vmwgfx_kms.c
+++ b/drivers/gpu/drm/vmwgfx/vmwgfx_kms.c
@@ -264,10 +264,23 @@ int vmw_du_crtc_cursor_move(struct drm_crtc *crtc, int x, 
int y)
du->cursor_x = x + crtc->x;
du->cursor_y = y + crtc->y;
 
+   /*
+* FIXME: Unclear whether there's any global state touched by the
+* cursor_set function, especially vmw_cursor_update_position looks
+* suspicious. For now take the easy route and reacquire all locks. We
+* can do this since the caller in the drm core doesn't check anything
+* which is protected by any looks.
+*/
+   mutex_unlock(&crtc->mutex);
+   drm_modeset_lock_all(dev_priv->dev);
+
vmw_cursor_update_position(dev_priv, shown,
   du->cursor_x + du->hotspot_x,
   du->cursor_y + du->hotspot_y);
 
+   drm_modeset_unlock_all(dev_priv->dev);
+   mutex_lock(&crtc->mutex);
+
return 0;
 }
 
-- 
1.7.10.4

___
Intel-gfx mailing list
Intel-gfx@lists.freedesktop.org
http://lists.free

[Intel-gfx] [PATCH 30/37] drm/i915: dump refcount into framebuffer debugfs file

2012-12-12 Thread Daniel Vetter
Useful for checking whether the new refcounting works as advertised.

Signed-off-by: Daniel Vetter 
---
 drivers/gpu/drm/i915/i915_debugfs.c |   10 ++
 1 file changed, 6 insertions(+), 4 deletions(-)

diff --git a/drivers/gpu/drm/i915/i915_debugfs.c 
b/drivers/gpu/drm/i915/i915_debugfs.c
index da1c8b6..e2dc77c 100644
--- a/drivers/gpu/drm/i915/i915_debugfs.c
+++ b/drivers/gpu/drm/i915/i915_debugfs.c
@@ -1369,11 +1369,12 @@ static int i915_gem_framebuffer_info(struct seq_file 
*m, void *data)
ifbdev = dev_priv->fbdev;
fb = to_intel_framebuffer(ifbdev->helper.fb);
 
-   seq_printf(m, "fbcon size: %d x %d, depth %d, %d bpp, obj ",
+   seq_printf(m, "fbcon size: %d x %d, depth %d, %d bpp, refcount %d, obj 
",
   fb->base.width,
   fb->base.height,
   fb->base.depth,
-  fb->base.bits_per_pixel);
+  fb->base.bits_per_pixel,
+  atomic_read(&fb->base.refcount.refcount));
describe_obj(m, fb->obj);
seq_printf(m, "\n");
mutex_unlock(&dev->mode_config.mutex);
@@ -1383,11 +1384,12 @@ static int i915_gem_framebuffer_info(struct seq_file 
*m, void *data)
if (&fb->base == ifbdev->helper.fb)
continue;
 
-   seq_printf(m, "user size: %d x %d, depth %d, %d bpp, obj ",
+   seq_printf(m, "user size: %d x %d, depth %d, %d bpp, refcount 
%d, obj ",
   fb->base.width,
   fb->base.height,
   fb->base.depth,
-  fb->base.bits_per_pixel);
+  fb->base.bits_per_pixel,
+  atomic_read(&fb->base.refcount.refcount));
describe_obj(m, fb->obj);
seq_printf(m, "\n");
}
-- 
1.7.10.4

___
Intel-gfx mailing list
Intel-gfx@lists.freedesktop.org
http://lists.freedesktop.org/mailman/listinfo/intel-gfx


[Intel-gfx] [PATCH 29/37] drm: refcounting for crtc framebuffers

2012-12-12 Thread Daniel Vetter
With the prep patch to encapsulate ->set_crtc calls, this is now
rather easy. Hooray for inconsistent semantics between ->set_crtc and
->page_flip, where the driver callback is supposed to update the fb
pointer, and ->update_plane, where the drm core does the same.

Also, since the drm core functions check crtc->fb before calling into
driver callbacks, we can't really reduce the critical sections
protected by the mode_config locks.

Signed-off-by: Daniel Vetter 
---
 drivers/gpu/drm/drm_crtc.c |   37 ++---
 1 file changed, 30 insertions(+), 7 deletions(-)

diff --git a/drivers/gpu/drm/drm_crtc.c b/drivers/gpu/drm/drm_crtc.c
index 229853e..6562eba 100644
--- a/drivers/gpu/drm/drm_crtc.c
+++ b/drivers/gpu/drm/drm_crtc.c
@@ -1983,8 +1983,21 @@ out:
 int drm_mode_set_config_internal(struct drm_mode_set *set)
 {
struct drm_crtc *crtc = set->crtc;
+   struct drm_framebuffer *fb, *old_fb;
+   int ret;
+
+   old_fb = crtc->fb;
+   fb = set->fb;
 
-   return crtc->funcs->set_config(set);
+   ret = crtc->funcs->set_config(set);
+   if (ret == 0) {
+   if (old_fb)
+   drm_framebuffer_unreference(old_fb);
+   if (fb)
+   drm_framebuffer_reference(fb);
+   }
+
+   return ret;
 }
 EXPORT_SYMBOL(drm_mode_set_config_internal);
 
@@ -2045,6 +2058,8 @@ int drm_mode_setcrtc(struct drm_device *dev, void *data,
goto out;
}
fb = crtc->fb;
+   /* Make refcounting symmetric with the lookup path. */
+   drm_framebuffer_reference(fb);
} else {
fb = drm_framebuffer_lookup(dev, crtc_req->fb_id);
if (!fb) {
@@ -2053,9 +2068,6 @@ int drm_mode_setcrtc(struct drm_device *dev, void *data,
ret = -EINVAL;
goto out;
}
-   /* fb is protect by the mode_config lock, so drop the
-* ref immediately */
-   drm_framebuffer_unreference(fb);
}
 
mode = drm_mode_create(dev);
@@ -2155,6 +2167,9 @@ int drm_mode_setcrtc(struct drm_device *dev, void *data,
ret = drm_mode_set_config_internal(&set);
 
 out:
+   if (fb)
+   drm_framebuffer_unreference(fb);
+
kfree(connector_set);
drm_mode_destroy(dev, mode);
drm_modeset_unlock_all(dev);
@@ -3673,7 +3688,7 @@ int drm_mode_page_flip_ioctl(struct drm_device *dev,
struct drm_mode_crtc_page_flip *page_flip = data;
struct drm_mode_object *obj;
struct drm_crtc *crtc;
-   struct drm_framebuffer *fb;
+   struct drm_framebuffer *fb = NULL, *old_fb = NULL;
struct drm_pending_vblank_event *e = NULL;
unsigned long flags;
int hdisplay, vdisplay;
@@ -3704,8 +3719,6 @@ int drm_mode_page_flip_ioctl(struct drm_device *dev,
fb = drm_framebuffer_lookup(dev, page_flip->fb_id);
if (!fb)
goto out;
-   /* fb is protect by the mode_config lock, so drop the ref immediately */
-   drm_framebuffer_unreference(fb);
 
hdisplay = crtc->mode.hdisplay;
vdisplay = crtc->mode.vdisplay;
@@ -3751,6 +3764,7 @@ int drm_mode_page_flip_ioctl(struct drm_device *dev,
(void (*) (struct drm_pending_event *)) kfree;
}
 
+   old_fb = crtc->fb;
ret = crtc->funcs->page_flip(crtc, fb, e);
if (ret) {
if (page_flip->flags & DRM_MODE_PAGE_FLIP_EVENT) {
@@ -3759,9 +3773,18 @@ int drm_mode_page_flip_ioctl(struct drm_device *dev,
spin_unlock_irqrestore(&dev->event_lock, flags);
kfree(e);
}
+   /* Keep the old fb, don't unref it. */
+   old_fb = NULL;
+   } else {
+   /* Unref only the old framebuffer. */
+   fb = NULL;
}
 
 out:
+   if (fb)
+   drm_framebuffer_unreference(fb);
+   if (old_fb)
+   drm_framebuffer_unreference(old_fb);
drm_modeset_unlock_all(dev);
return ret;
 }
-- 
1.7.10.4

___
Intel-gfx mailing list
Intel-gfx@lists.freedesktop.org
http://lists.freedesktop.org/mailman/listinfo/intel-gfx


[Intel-gfx] [PATCH 14/37] drm: only take the crtc lock for ->cursor_set

2012-12-12 Thread Daniel Vetter
First convert ->cursor_set to only take the crtc lock, since that
seems to be the function with the least amount of state - the core
ioctl function doesn't check anything which can change at runtime, so
we don't have any object lifetime issues to contend.

The only thing which is important is that the driver's implementation
doesn't touch any state outside of that single crtc which is not yet
properly protected by other locking:

- ast: access the global ast->cache_kmap. Luckily we only have on crtc
  on this driver, so this is fine. Add a comment.

- gma500: calls gma_power_begin|and and psb_gtt_pin|unpin, both which
  have their own locking to protect their state. Everything else is
  crtc-local.

- i915: touches a bit of global gem state, all protected by the One
  Lock to Rule Them All (dev->struct_mutex).

- nouveau: Pre-nv50 is all nice, nv50+ uses the evo channels to queue
  up all display changes. And some of these channels are device
  global. But this is fine now since the previous patch introduced an
  evo channel mutex.

- radeon: Uses some indirect register access for cursor updates, but
  with the previous patches to protect these indirect 2-register
  access patterns with a spinlock, this should be fine now, too.

- vmwgfx: I have no idea how that works - update_cursor_position
  doesn't take any per-crtc argument and I haven't figured out any
  other place where this could be set in some form of a side-channel.
  But vmwgfx definitely has more than one crtc (or at least can
  register more than one), so I have no idea how this is supposed to
  not fail with the current code already. Hence take the easy way out
  and simply acquire all locks (which requires dropping the crtc lock
  the core acquired for us). That way it's not worse off for
  consistency than the old code.

Signed-off-by: Daniel Vetter 
---
 drivers/gpu/drm/ast/ast_drv.h   |2 ++
 drivers/gpu/drm/drm_crtc.c  |6 --
 drivers/gpu/drm/vmwgfx/vmwgfx_kms.c |   32 ++--
 3 files changed, 32 insertions(+), 8 deletions(-)

diff --git a/drivers/gpu/drm/ast/ast_drv.h b/drivers/gpu/drm/ast/ast_drv.h
index 5ccf984..5284292 100644
--- a/drivers/gpu/drm/ast/ast_drv.h
+++ b/drivers/gpu/drm/ast/ast_drv.h
@@ -98,6 +98,8 @@ struct ast_private {
 
struct drm_gem_object *cursor_cache;
uint64_t cursor_cache_gpu_addr;
+   /* Acces to this cache is protected by the crtc->mutex of the only crtc
+* we have. */
struct ttm_bo_kmap_obj cache_kmap;
int next_cursor;
 };
diff --git a/drivers/gpu/drm/drm_crtc.c b/drivers/gpu/drm/drm_crtc.c
index 91e8068..62b5002 100644
--- a/drivers/gpu/drm/drm_crtc.c
+++ b/drivers/gpu/drm/drm_crtc.c
@@ -2023,7 +2023,6 @@ int drm_mode_cursor_ioctl(struct drm_device *dev,
if (!req->flags || (~DRM_MODE_CURSOR_FLAGS & req->flags))
return -EINVAL;
 
-   drm_modeset_lock_all(dev);
obj = drm_mode_object_find(dev, req->crtc_id, DRM_MODE_OBJECT_CRTC);
if (!obj) {
DRM_DEBUG_KMS("Unknown CRTC ID %d\n", req->crtc_id);
@@ -2038,20 +2037,23 @@ int drm_mode_cursor_ioctl(struct drm_device *dev,
goto out;
}
/* Turns off the cursor if handle is 0 */
+   mutex_lock(&crtc->mutex);
ret = crtc->funcs->cursor_set(crtc, file_priv, req->handle,
  req->width, req->height);
+   mutex_unlock(&crtc->mutex);
}
 
if (req->flags & DRM_MODE_CURSOR_MOVE) {
if (crtc->funcs->cursor_move) {
+   drm_modeset_lock_all(dev);
ret = crtc->funcs->cursor_move(crtc, req->x, req->y);
+   drm_modeset_unlock_all(dev);
} else {
ret = -EFAULT;
goto out;
}
}
 out:
-   drm_modeset_unlock_all(dev);
return ret;
 }
 
diff --git a/drivers/gpu/drm/vmwgfx/vmwgfx_kms.c 
b/drivers/gpu/drm/vmwgfx/vmwgfx_kms.c
index 5474394..74b6734 100644
--- a/drivers/gpu/drm/vmwgfx/vmwgfx_kms.c
+++ b/drivers/gpu/drm/vmwgfx/vmwgfx_kms.c
@@ -180,16 +180,29 @@ int vmw_du_crtc_cursor_set(struct drm_crtc *crtc, struct 
drm_file *file_priv,
struct vmw_dma_buffer *dmabuf = NULL;
int ret;
 
+   /*
+* FIXME: Unclear whether there's any global state touched by the
+* cursor_set function, especially vmw_cursor_update_position looks
+* suspicious. For now take the easy route and reacquire all locks. We
+* can do this since the caller in the drm core doesn't check anything
+* which is protected by any looks.
+*/
+   mutex_unlock(&crtc->mutex);
+   drm_modeset_lock_all(dev_priv->dev);
+
/* A lot of the code assumes this */
-   if (handle && (width != 64 || height != 64))
-   return -EINVAL;
+   if (handle && (width != 64 || height

[Intel-gfx] [PATCH 35/37] drm/radeon: fix fence locking in the pageflip callback

2012-12-12 Thread Daniel Vetter
We need to hold bdev->fence_lock while grabbing a reference to
the fence, to prevent concurrent clearing/changing of the
ttm_bo->sync_obj field.

Signed-off-by: Daniel Vetter 
---
 drivers/gpu/drm/radeon/radeon_display.c |4 
 1 file changed, 4 insertions(+)

diff --git a/drivers/gpu/drm/radeon/radeon_display.c 
b/drivers/gpu/drm/radeon/radeon_display.c
index 8724196..069d5cc 100644
--- a/drivers/gpu/drm/radeon/radeon_display.c
+++ b/drivers/gpu/drm/radeon/radeon_display.c
@@ -378,8 +378,12 @@ static int radeon_crtc_page_flip(struct drm_crtc *crtc,
work->old_rbo = rbo;
obj = new_radeon_fb->obj;
rbo = gem_to_radeon_bo(obj);
+
+   spin_lock(&rbo->tbo.bdev->fence_lock);
if (rbo->tbo.sync_obj)
work->fence = radeon_fence_ref(rbo->tbo.sync_obj);
+   spin_unlock(&rbo->tbo.bdev->fence_lock);
+
INIT_WORK(&work->work, radeon_unpin_work_func);
 
/* We borrow the event spin lock for protecting unpin_work */
-- 
1.7.10.4

___
Intel-gfx mailing list
Intel-gfx@lists.freedesktop.org
http://lists.freedesktop.org/mailman/listinfo/intel-gfx


[Intel-gfx] [PATCH 16/37] drm/: reorder framebuffer init sequence

2012-12-12 Thread Daniel Vetter
With more fine-grained locking we can no longer rely on the big
mode_config lock to prevent concurrent access to mode resources
like framebuffers. Instead a framebuffer becomes accessible to
other threads as soon as it is added to the relevant lookup
structures. Hence it needs to be fully set up by the time drivers
call drm_framebuffer_init.

This patch here is the drivers part of that reorg. Nothing really fancy
going on safe for three special cases.

- exynos needs to be careful to properly unref all handles.
- nouveau gets a resource leak fixed for free: one of the error
  cases didn't cleanup the framebuffer, which is now moot since
  the framebuffer is only registered once it is fully set up.
- vmwgfx requires a slight reordering of operations, I'm hoping I didn't
  break anything (but it's refcount management only, so should be safe).

Signed-off-by: Daniel Vetter 
---
 drivers/gpu/drm/ast/ast_main.c|4 ++--
 drivers/gpu/drm/cirrus/cirrus_main.c  |9 +++--
 drivers/gpu/drm/drm_fb_cma_helper.c   |   10 +-
 drivers/gpu/drm/exynos/exynos_drm_fb.c|   20 +++-
 drivers/gpu/drm/gma500/framebuffer.c  |4 ++--
 drivers/gpu/drm/i915/intel_display.c  |5 +++--
 drivers/gpu/drm/mgag200/mgag200_main.c|8 +---
 drivers/gpu/drm/nouveau/nouveau_display.c |   10 +-
 drivers/gpu/drm/radeon/radeon_display.c   |2 +-
 drivers/gpu/drm/udl/udl_fb.c  |2 +-
 drivers/gpu/drm/vmwgfx/vmwgfx_kms.c   |   28 ++--
 drivers/staging/omapdrm/omap_fb.c |   16 
 12 files changed, 64 insertions(+), 54 deletions(-)

diff --git a/drivers/gpu/drm/ast/ast_main.c b/drivers/gpu/drm/ast/ast_main.c
index f668e6c..d5ba709 100644
--- a/drivers/gpu/drm/ast/ast_main.c
+++ b/drivers/gpu/drm/ast/ast_main.c
@@ -266,13 +266,13 @@ int ast_framebuffer_init(struct drm_device *dev,
 {
int ret;
 
+   drm_helper_mode_fill_fb_struct(&ast_fb->base, mode_cmd);
+   ast_fb->obj = obj;
ret = drm_framebuffer_init(dev, &ast_fb->base, &ast_fb_funcs);
if (ret) {
DRM_ERROR("framebuffer init failed %d\n", ret);
return ret;
}
-   drm_helper_mode_fill_fb_struct(&ast_fb->base, mode_cmd);
-   ast_fb->obj = obj;
return 0;
 }
 
diff --git a/drivers/gpu/drm/cirrus/cirrus_main.c 
b/drivers/gpu/drm/cirrus/cirrus_main.c
index 6a9b12e..2eac87b 100644
--- a/drivers/gpu/drm/cirrus/cirrus_main.c
+++ b/drivers/gpu/drm/cirrus/cirrus_main.c
@@ -42,13 +42,13 @@ int cirrus_framebuffer_init(struct drm_device *dev,
 {
int ret;
 
+   drm_helper_mode_fill_fb_struct(&gfb->base, mode_cmd);
+   gfb->obj = obj;
ret = drm_framebuffer_init(dev, &gfb->base, &cirrus_fb_funcs);
if (ret) {
DRM_ERROR("drm_framebuffer_init failed: %d\n", ret);
return ret;
}
-   drm_helper_mode_fill_fb_struct(&gfb->base, mode_cmd);
-   gfb->obj = obj;
return 0;
 }
 
@@ -79,6 +79,11 @@ cirrus_user_framebuffer_create(struct drm_device *dev,
 
ret = cirrus_framebuffer_init(dev, cirrus_fb, mode_cmd, obj);
if (ret) {
+   ret = drm_framebuffer_init(dev, &gfb->base, &cirrus_fb_funcs);
+   if (ret) {
+   DRM_ERROR("drm_framebuffer_init failed: %d\n", ret);
+   return ret;
+   }
drm_gem_object_unreference_unlocked(obj);
kfree(cirrus_fb);
return ERR_PTR(ret);
diff --git a/drivers/gpu/drm/drm_fb_cma_helper.c 
b/drivers/gpu/drm/drm_fb_cma_helper.c
index fd9d0af..e1e0cb0 100644
--- a/drivers/gpu/drm/drm_fb_cma_helper.c
+++ b/drivers/gpu/drm/drm_fb_cma_helper.c
@@ -85,6 +85,11 @@ static struct drm_fb_cma *drm_fb_cma_alloc(struct drm_device 
*dev,
if (!fb_cma)
return ERR_PTR(-ENOMEM);
 
+   drm_helper_mode_fill_fb_struct(&fb_cma->fb, mode_cmd);
+
+   for (i = 0; i < num_planes; i++)
+   fb_cma->obj[i] = obj[i];
+
ret = drm_framebuffer_init(dev, &fb_cma->fb, &drm_fb_cma_funcs);
if (ret) {
dev_err(dev->dev, "Failed to initalize framebuffer: %d\n", ret);
@@ -92,11 +97,6 @@ static struct drm_fb_cma *drm_fb_cma_alloc(struct drm_device 
*dev,
return ERR_PTR(ret);
}
 
-   drm_helper_mode_fill_fb_struct(&fb_cma->fb, mode_cmd);
-
-   for (i = 0; i < num_planes; i++)
-   fb_cma->obj[i] = obj[i];
-
return fb_cma;
 }
 
diff --git a/drivers/gpu/drm/exynos/exynos_drm_fb.c 
b/drivers/gpu/drm/exynos/exynos_drm_fb.c
index 4ef4cd3..179c177 100644
--- a/drivers/gpu/drm/exynos/exynos_drm_fb.c
+++ b/drivers/gpu/drm/exynos/exynos_drm_fb.c
@@ -136,15 +136,15 @@ exynos_drm_framebuffer_init(struct drm_device *dev,
return ERR_PTR(-ENOMEM);
}
 
+   drm_helper_mode_fill_fb_struct(&exynos_fb->fb, mode_cmd);
+   exynos_fb->exynos_gem_obj[0] = to_exynos_gem_obj(obj);
+
ret

[Intel-gfx] [PATCH 11/37] drm/radeon: add W|RREG32_IDX for MM_INDEX|DATA based mmio accesss

2012-12-12 Thread Daniel Vetter
Just refactoring to make the next patche simpler. Now all indirect register
access in the new modesetting driver should go through the r100_mm_(w|r)reg
fucntions.

RADEON_READ_MM from the old driver seems to be totally unused, so just kill
it.

Signed-off-by: Daniel Vetter 
---
 drivers/gpu/drm/radeon/r100.c   |   10 ++
 drivers/gpu/drm/radeon/radeon.h |   16 ++--
 drivers/gpu/drm/radeon/radeon_combios.c |6 ++
 drivers/gpu/drm/radeon/radeon_cp.c  |   14 --
 drivers/gpu/drm/radeon/radeon_cursor.c  |   17 +
 drivers/gpu/drm/radeon/radeon_drv.h |1 -
 6 files changed, 27 insertions(+), 37 deletions(-)

diff --git a/drivers/gpu/drm/radeon/r100.c b/drivers/gpu/drm/radeon/r100.c
index 376884f..ae4c857 100644
--- a/drivers/gpu/drm/radeon/r100.c
+++ b/drivers/gpu/drm/radeon/r100.c
@@ -4135,9 +4135,10 @@ int r100_init(struct radeon_device *rdev)
return 0;
 }
 
-uint32_t r100_mm_rreg(struct radeon_device *rdev, uint32_t reg)
+uint32_t r100_mm_rreg(struct radeon_device *rdev, uint32_t reg,
+ bool always_indirect)
 {
-   if (reg < rdev->rmmio_size)
+   if (reg < rdev->rmmio_size && !always_indirect)
return readl(((void __iomem *)rdev->rmmio) + reg);
else {
writel(reg, ((void __iomem *)rdev->rmmio) + RADEON_MM_INDEX);
@@ -4145,9 +4146,10 @@ uint32_t r100_mm_rreg(struct radeon_device *rdev, 
uint32_t reg)
}
 }
 
-void r100_mm_wreg(struct radeon_device *rdev, uint32_t reg, uint32_t v)
+void r100_mm_wreg(struct radeon_device *rdev, uint32_t reg, uint32_t v,
+ bool always_indirect)
 {
-   if (reg < rdev->rmmio_size)
+   if (reg < rdev->rmmio_size && !always_indirect)
writel(v, ((void __iomem *)rdev->rmmio) + reg);
else {
writel(reg, ((void __iomem *)rdev->rmmio) + RADEON_MM_INDEX);
diff --git a/drivers/gpu/drm/radeon/radeon.h b/drivers/gpu/drm/radeon/radeon.h
index 8c42d54..bcb00b8 100644
--- a/drivers/gpu/drm/radeon/radeon.h
+++ b/drivers/gpu/drm/radeon/radeon.h
@@ -1614,8 +1614,10 @@ int radeon_device_init(struct radeon_device *rdev,
 void radeon_device_fini(struct radeon_device *rdev);
 int radeon_gpu_wait_for_idle(struct radeon_device *rdev);
 
-uint32_t r100_mm_rreg(struct radeon_device *rdev, uint32_t reg);
-void r100_mm_wreg(struct radeon_device *rdev, uint32_t reg, uint32_t v);
+uint32_t r100_mm_rreg(struct radeon_device *rdev, uint32_t reg,
+ bool always_indirect);
+void r100_mm_wreg(struct radeon_device *rdev, uint32_t reg, uint32_t v,
+ bool always_indirect);
 u32 r100_io_rreg(struct radeon_device *rdev, u32 reg);
 void r100_io_wreg(struct radeon_device *rdev, u32 reg, u32 v);
 
@@ -1631,9 +1633,11 @@ void r100_io_wreg(struct radeon_device *rdev, u32 reg, 
u32 v);
 #define WREG8(reg, v) writeb(v, (rdev->rmmio) + (reg))
 #define RREG16(reg) readw((rdev->rmmio) + (reg))
 #define WREG16(reg, v) writew(v, (rdev->rmmio) + (reg))
-#define RREG32(reg) r100_mm_rreg(rdev, (reg))
-#define DREG32(reg) printk(KERN_INFO "REGISTER: " #reg " : 0x%08X\n", 
r100_mm_rreg(rdev, (reg)))
-#define WREG32(reg, v) r100_mm_wreg(rdev, (reg), (v))
+#define RREG32(reg) r100_mm_rreg(rdev, (reg), false)
+#define RREG32_IDX(reg) r100_mm_rreg(rdev, (reg), true)
+#define DREG32(reg) printk(KERN_INFO "REGISTER: " #reg " : 0x%08X\n", 
r100_mm_rreg(rdev, (reg), false))
+#define WREG32(reg, v) r100_mm_wreg(rdev, (reg), (v), false)
+#define WREG32_IDX(reg, v) r100_mm_wreg(rdev, (reg), (v), true)
 #define REG_SET(FIELD, v) (((v) << FIELD##_SHIFT) & FIELD##_MASK)
 #define REG_GET(FIELD, v) (((v) << FIELD##_SHIFT) & FIELD##_MASK)
 #define RREG32_PLL(reg) rdev->pll_rreg(rdev, (reg))
@@ -1658,7 +1662,7 @@ void r100_io_wreg(struct radeon_device *rdev, u32 reg, 
u32 v);
tmp_ |= ((val) & ~(mask));  \
WREG32_PLL(reg, tmp_);  \
} while (0)
-#define DREG32_SYS(sqf, rdev, reg) seq_printf((sqf), #reg " : 0x%08X\n", 
r100_mm_rreg((rdev), (reg)))
+#define DREG32_SYS(sqf, rdev, reg) seq_printf((sqf), #reg " : 0x%08X\n", 
r100_mm_rreg((rdev), (reg), false))
 #define RREG32_IO(reg) r100_io_rreg(rdev, (reg))
 #define WREG32_IO(reg, v) r100_io_wreg(rdev, (reg), (v))
 
diff --git a/drivers/gpu/drm/radeon/radeon_combios.c 
b/drivers/gpu/drm/radeon/radeon_combios.c
index 45b660b..4af8912 100644
--- a/drivers/gpu/drm/radeon/radeon_combios.c
+++ b/drivers/gpu/drm/radeon/radeon_combios.c
@@ -3246,11 +3246,9 @@ static uint32_t combios_detect_ram(struct drm_device 
*dev, int ram,
while (ram--) {
addr = ram * 1024 * 1024;
/* write to each page */
-   WREG32(RADEON_MM_INDEX, (addr) | RADEON_MM_APER);
-   WREG32(RADEON_MM_DATA, 0xdeadbeef);
+   WREG32_IDX((addr) | RADEON_MM_APER, 0xdeadbeef);
/* read back and verify */
-   WREG32(RAD

[Intel-gfx] [PATCH 20/37] drm: revamp framebuffer cleanup interfaces

2012-12-12 Thread Daniel Vetter
We have two classes of framebuffer
- Created by the driver (atm only for fbdev), and the driver holds
  onto the last reference count until destruction.
- Created by userspace and associated with a given fd. These
  framebuffers will be reaped when their assoiciated fb is closed.

Now these two cases are set up differently, the framebuffers are on
different lists and hence destruction needs to clean up different
things. Also, for userspace framebuffers we remove them from any
current usage, whereas for internal framebuffers it is assumed that
the driver has done this already.

Long story short, we need two different ways to cleanup such drivers.
Three functions are involved in total:
- drm_framebuffer_remove: Convenience function which removes the fb
  from all active usage and then drops the passed-in reference.
- drm_framebuffer_unregister_private: Will remove driver-private
  framebuffers from relevant lists and drop the corresponding
  references. Should be called for driver-private framebuffers before
  dropping the last reference (or like for a lot of the drivers where
  the fbdev is embedded someplace else, before doing the cleanup
  manually).
- drm_framebuffer_cleanup: Final cleanup for both classes of fbs,
  should be called by the driver's ->destroy callback once the last
  reference is gone.

This patch just rolls out the new interfaces and updates all drivers
(by adding calls to drm_framebuffer_unregister_private at all the
right places)- no functional changes yet. Follow-on patches will move
drm core code around and update the lifetime management for
framebuffers, so that we are no longer required to keep framebuffers
alive by locking mode_config.mutex.

I've also updated the kerneldoc already.

vmwgfx seems to again be a bit special, at least I haven't figured out
how the fbdev support in that driver works. It smells like it's
external though.

v2: The i915 driver creates another private framebuffer in the
load-detect code. Adjust its cleanup code, too.

Signed-off-by: Daniel Vetter 
---
 drivers/gpu/drm/ast/ast_fb.c  |1 +
 drivers/gpu/drm/cirrus/cirrus_fbdev.c |1 +
 drivers/gpu/drm/drm_crtc.c|   31 ++---
 drivers/gpu/drm/drm_fb_cma_helper.c   |5 -
 drivers/gpu/drm/exynos/exynos_drm_fbdev.c |4 +++-
 drivers/gpu/drm/gma500/framebuffer.c  |1 +
 drivers/gpu/drm/i915/intel_display.c  |6 --
 drivers/gpu/drm/i915/intel_fb.c   |1 +
 drivers/gpu/drm/mgag200/mgag200_fb.c  |1 +
 drivers/gpu/drm/nouveau/nouveau_fbcon.c   |1 +
 drivers/gpu/drm/radeon/radeon_fb.c|2 ++
 drivers/gpu/drm/udl/udl_fb.c  |1 +
 drivers/staging/omapdrm/omap_fbdev.c  |8 ++--
 include/drm/drm_crtc.h|1 +
 14 files changed, 55 insertions(+), 9 deletions(-)

diff --git a/drivers/gpu/drm/ast/ast_fb.c b/drivers/gpu/drm/ast/ast_fb.c
index d9ec779..3e6584b 100644
--- a/drivers/gpu/drm/ast/ast_fb.c
+++ b/drivers/gpu/drm/ast/ast_fb.c
@@ -290,6 +290,7 @@ static void ast_fbdev_destroy(struct drm_device *dev,
drm_fb_helper_fini(&afbdev->helper);
 
vfree(afbdev->sysram);
+   drm_framebuffer_unregister_private(&afb->base);
drm_framebuffer_cleanup(&afb->base);
 }
 
diff --git a/drivers/gpu/drm/cirrus/cirrus_fbdev.c 
b/drivers/gpu/drm/cirrus/cirrus_fbdev.c
index 6c6b4c8..3daea0f 100644
--- a/drivers/gpu/drm/cirrus/cirrus_fbdev.c
+++ b/drivers/gpu/drm/cirrus/cirrus_fbdev.c
@@ -258,6 +258,7 @@ static int cirrus_fbdev_destroy(struct drm_device *dev,
 
vfree(gfbdev->sysram);
drm_fb_helper_fini(&gfbdev->helper);
+   drm_framebuffer_unregister_private(&gfb->base);
drm_framebuffer_cleanup(&gfb->base);
 
return 0;
diff --git a/drivers/gpu/drm/drm_crtc.c b/drivers/gpu/drm/drm_crtc.c
index 17cdd32..e2d70f6 100644
--- a/drivers/gpu/drm/drm_crtc.c
+++ b/drivers/gpu/drm/drm_crtc.c
@@ -68,6 +68,7 @@ void drm_modeset_unlock_all(struct drm_device *dev)
 
mutex_unlock(&dev->mode_config.mutex);
 }
+
 EXPORT_SYMBOL(drm_modeset_unlock_all);
 
 /* Avoid boilerplate.  I'm tired of typing. */
@@ -429,11 +430,34 @@ void drm_framebuffer_reference(struct drm_framebuffer *fb)
 EXPORT_SYMBOL(drm_framebuffer_reference);
 
 /**
+ * drm_framebuffer_unregister_private - unregister a private fb from the 
lookup idr
+ * @fb: fb to unregister
+ *
+ * Drivers need to call this when cleaning up driver-private framebuffers, e.g.
+ * those used for fbdev. Note that the caller must hold a reference of it's 
own,
+ * i.e. the object may not be destroyed through this call (since it'll lead to 
a
+ * locking inversion).
+ */
+void drm_framebuffer_unregister_private(struct drm_framebuffer *fb)
+{
+}
+EXPORT_SYMBOL(drm_framebuffer_unregister_private);
+
+/**
  * drm_framebuffer_cleanup - remove a framebuffer object
  * @fb: framebuffer to remove
  *
- * Scans all the CRTCs in @dev's mode_config.  If they're using @fb, removes
- * it, s

[Intel-gfx] [PATCH 12/37] drm/radeon: make indirect register access concurrency-safe

2012-12-12 Thread Daniel Vetter
With the new per-crtc locking mutliple set-cursor calls could happen
in parallel. Out of sheer paranoia I've opted for an irqsave spinlock.
But if there's indeed an access from interrupt contexts to these regs
it's already broken with the old code, so this can likely just be
reduced to a normal spinlock. Otoh the pageflip completion happens
from the vblank irq handler ...

Signed-off-by: Daniel Vetter 
---
 drivers/gpu/drm/radeon/r100.c  |   13 -
 drivers/gpu/drm/radeon/radeon.h|2 ++
 drivers/gpu/drm/radeon/radeon_device.c |1 +
 3 files changed, 15 insertions(+), 1 deletion(-)

diff --git a/drivers/gpu/drm/radeon/r100.c b/drivers/gpu/drm/radeon/r100.c
index ae4c857..8ff7cac 100644
--- a/drivers/gpu/drm/radeon/r100.c
+++ b/drivers/gpu/drm/radeon/r100.c
@@ -4141,8 +4141,15 @@ uint32_t r100_mm_rreg(struct radeon_device *rdev, 
uint32_t reg,
if (reg < rdev->rmmio_size && !always_indirect)
return readl(((void __iomem *)rdev->rmmio) + reg);
else {
+   unsigned long flags;
+   uint32_t ret;
+
+   spin_lock_irqsave(&rdev->mmio_idx_lock, flags);
writel(reg, ((void __iomem *)rdev->rmmio) + RADEON_MM_INDEX);
-   return readl(((void __iomem *)rdev->rmmio) + RADEON_MM_DATA);
+   ret = readl(((void __iomem *)rdev->rmmio) + RADEON_MM_DATA);
+   spin_unlock_irqrestore(&rdev->mmio_idx_lock, flags);
+
+   return ret;
}
 }
 
@@ -4152,8 +4159,12 @@ void r100_mm_wreg(struct radeon_device *rdev, uint32_t 
reg, uint32_t v,
if (reg < rdev->rmmio_size && !always_indirect)
writel(v, ((void __iomem *)rdev->rmmio) + reg);
else {
+   unsigned long flags;
+
+   spin_lock_irqsave(&rdev->mmio_idx_lock, flags);
writel(reg, ((void __iomem *)rdev->rmmio) + RADEON_MM_INDEX);
writel(v, ((void __iomem *)rdev->rmmio) + RADEON_MM_DATA);
+   spin_unlock_irqrestore(&rdev->mmio_idx_lock, flags);
}
 }
 
diff --git a/drivers/gpu/drm/radeon/radeon.h b/drivers/gpu/drm/radeon/radeon.h
index bcb00b8..3dedb39 100644
--- a/drivers/gpu/drm/radeon/radeon.h
+++ b/drivers/gpu/drm/radeon/radeon.h
@@ -1539,6 +1539,8 @@ struct radeon_device {
/* Register mmio */
resource_size_t rmmio_base;
resource_size_t rmmio_size;
+   /* protects concurrent MM_INDEX/DATA based register access */
+   spinlock_t mmio_idx_lock;
void __iomem*rmmio;
radeon_rreg_t   mc_rreg;
radeon_wreg_t   mc_wreg;
diff --git a/drivers/gpu/drm/radeon/radeon_device.c 
b/drivers/gpu/drm/radeon/radeon_device.c
index e2f5f88..49b0659 100644
--- a/drivers/gpu/drm/radeon/radeon_device.c
+++ b/drivers/gpu/drm/radeon/radeon_device.c
@@ -1059,6 +1059,7 @@ int radeon_device_init(struct radeon_device *rdev,
 
/* Registers mapping */
/* TODO: block userspace mapping of io register */
+   spin_lock_init(&rdev->mmio_idx_lock);
rdev->rmmio_base = pci_resource_start(rdev->pdev, 2);
rdev->rmmio_size = pci_resource_len(rdev->pdev, 2);
rdev->rmmio = ioremap(rdev->rmmio_base, rdev->rmmio_size);
-- 
1.7.10.4

___
Intel-gfx mailing list
Intel-gfx@lists.freedesktop.org
http://lists.freedesktop.org/mailman/listinfo/intel-gfx


[Intel-gfx] [PATCH 33/37] drm/nouveau: try to protect nbo->pin_refcount

2012-12-12 Thread Daniel Vetter
... by moving the bo_pin/bo_unpin manipulation of the pin_refcount
under the protection of the ttm reservation lock. pin/unpin seems
to get called from all over the place, so atm this is completely racy.

After this patch there are only a few places in cleanup functions
left which access ->pin_refcount without locking. But I'm hoping that
those are safe and some other code invariant guarantees that this
won't blow up.

In any case, I only need to fix up pin/unpin to make ->pageflip work
safely, so let's keep it at that.

Add a comment to the header to explain the new locking rule.

Signed-off-by: Daniel Vetter 
---
 drivers/gpu/drm/nouveau/nouveau_bo.c |   22 +++---
 drivers/gpu/drm/nouveau/nouveau_bo.h |2 ++
 2 files changed, 13 insertions(+), 11 deletions(-)

diff --git a/drivers/gpu/drm/nouveau/nouveau_bo.c 
b/drivers/gpu/drm/nouveau/nouveau_bo.c
index 4c950b4..2aa4745 100644
--- a/drivers/gpu/drm/nouveau/nouveau_bo.c
+++ b/drivers/gpu/drm/nouveau/nouveau_bo.c
@@ -300,17 +300,18 @@ nouveau_bo_pin(struct nouveau_bo *nvbo, uint32_t memtype)
struct ttm_buffer_object *bo = &nvbo->bo;
int ret;
 
+   ret = ttm_bo_reserve(bo, false, false, false, 0);
+   if (ret)
+   goto out;
+
if (nvbo->pin_refcnt && !(memtype & (1 << bo->mem.mem_type))) {
NV_ERROR(drm, "bo %p pinned elsewhere: 0x%08x vs 0x%08x\n", bo,
 1 << bo->mem.mem_type, memtype);
-   return -EINVAL;
+   ret = -EINVAL;
+   goto out;
}
 
if (nvbo->pin_refcnt++)
-   return 0;
-
-   ret = ttm_bo_reserve(bo, false, false, false, 0);
-   if (ret)
goto out;
 
nouveau_bo_placement_set(nvbo, memtype, 0);
@@ -328,10 +329,8 @@ nouveau_bo_pin(struct nouveau_bo *nvbo, uint32_t memtype)
break;
}
}
-   ttm_bo_unreserve(bo);
 out:
-   if (unlikely(ret))
-   nvbo->pin_refcnt--;
+   ttm_bo_unreserve(bo);
return ret;
 }
 
@@ -342,13 +341,13 @@ nouveau_bo_unpin(struct nouveau_bo *nvbo)
struct ttm_buffer_object *bo = &nvbo->bo;
int ret;
 
-   if (--nvbo->pin_refcnt)
-   return 0;
-
ret = ttm_bo_reserve(bo, false, false, false, 0);
if (ret)
return ret;
 
+   if (--nvbo->pin_refcnt)
+   goto out;
+
nouveau_bo_placement_set(nvbo, bo->mem.placement, 0);
 
ret = nouveau_bo_validate(nvbo, false, false, false);
@@ -365,6 +364,7 @@ nouveau_bo_unpin(struct nouveau_bo *nvbo)
}
}
 
+out:
ttm_bo_unreserve(bo);
return ret;
 }
diff --git a/drivers/gpu/drm/nouveau/nouveau_bo.h 
b/drivers/gpu/drm/nouveau/nouveau_bo.h
index dec51b1..cd5631b 100644
--- a/drivers/gpu/drm/nouveau/nouveau_bo.h
+++ b/drivers/gpu/drm/nouveau/nouveau_bo.h
@@ -28,6 +28,8 @@ struct nouveau_bo {
struct nouveau_drm_tile *tile;
 
struct drm_gem_object *gem;
+
+   /* protect by the ttm reservation lock */
int pin_refcnt;
 
struct ttm_bo_kmap_obj dma_buf_vmap;
-- 
1.7.10.4

___
Intel-gfx mailing list
Intel-gfx@lists.freedesktop.org
http://lists.freedesktop.org/mailman/listinfo/intel-gfx


[Intel-gfx] [PATCH 26/37] drm: fb refcounting for dirtyfb_ioctl

2012-12-12 Thread Daniel Vetter
We only need to ensure that the fb stays around for long enough. While
at it, only grab the modeset locks when we need them (since most
drivers don't implement the dirty callback, this should help jitter
and stalls when using the generic modeset driver).

Signed-off-by: Daniel Vetter 
---
 drivers/gpu/drm/drm_crtc.c |   15 ++-
 1 file changed, 6 insertions(+), 9 deletions(-)

diff --git a/drivers/gpu/drm/drm_crtc.c b/drivers/gpu/drm/drm_crtc.c
index 28838cf..8132e13 100644
--- a/drivers/gpu/drm/drm_crtc.c
+++ b/drivers/gpu/drm/drm_crtc.c
@@ -2561,14 +2561,9 @@ int drm_mode_dirtyfb_ioctl(struct drm_device *dev,
if (!drm_core_check_feature(dev, DRIVER_MODESET))
return -EINVAL;
 
-   drm_modeset_lock_all(dev);
fb = drm_framebuffer_lookup(dev, r->fb_id);
-   if (!fb) {
-   ret = -EINVAL;
-   goto out_err1;
-   }
-   /* fb is protect by the mode_config lock, so drop the ref immediately */
-   drm_framebuffer_unreference(fb);
+   if (!fb)
+   return -EINVAL;
 
num_clips = r->num_clips;
clips_ptr = (struct drm_clip_rect __user *)(unsigned long)r->clips_ptr;
@@ -2606,17 +2601,19 @@ int drm_mode_dirtyfb_ioctl(struct drm_device *dev,
}
 
if (fb->funcs->dirty) {
+   drm_modeset_lock_all(dev);
ret = fb->funcs->dirty(fb, file_priv, flags, r->color,
   clips, num_clips);
+   drm_modeset_unlock_all(dev);
} else {
ret = -ENOSYS;
-   goto out_err2;
}
 
 out_err2:
kfree(clips);
 out_err1:
-   drm_modeset_unlock_all(dev);
+   drm_framebuffer_unreference(fb);
+
return ret;
 }
 
-- 
1.7.10.4

___
Intel-gfx mailing list
Intel-gfx@lists.freedesktop.org
http://lists.freedesktop.org/mailman/listinfo/intel-gfx


[Intel-gfx] [PATCH 21/37] drm: reference framebuffers which are on the idr

2012-12-12 Thread Daniel Vetter
Since otherwise looking and reference-counting around
drm_framebuffer_lookup will be an unmanageable mess. With this change,
an object can either be found in the idr and will stay around once we
incremented the reference counter. Or it will be gone for good and
can't be looked up using its id any more.

Atomicity is guaranteed by the dev->mode_config.fb_lock. The
newly-introduce fpriv->fbs_lock looks a bit redundant, but the next
patch will shuffle the locking order between these two locks and all
the modeset locks taken in modeset_lock_all, so we'll need it.

Also, since userspace could do really funky stuff and race e.g. a
getresources with an rmfb, we need to make sure that the kernel
doesn't fall over trying to look-up an inexistent fb, or causing
confusion by having two fbs around with the same id. Simply reset the
framebuffer id to 0, which marks it as reaped. Any lookups of that id
will fail, so the object is really gone for good from userspace's pov.

Note that we still need to protect the "remove framebuffer from all
use-cases" and the final unreference with the modeset-lock, since most
framebuffer use-sites don't implement proper reference counting yet.
We can only lift this once _all_ users are converted.

With this change, two references are held on alife, but unused
framebuffers:
- The reference for the idr lookup, created in this patch.
- For user-created framebuffers the fpriv->fbs reference, for
  driver-private fbs the driver is supposed to hold it's own last
  reference.

Note that the dev->mode_config.fb_list itself does _not_ hold a
reference onto the framebuffers (this list is essentially only used
for debugfs files). Hence if there's anything left there when the
driver has cleaned up all it's modeset resources, this is a ref-leak.
WARN about it.

Now we only need to fix up all other places to properly reference
count framebuffers.

Signed-off-by: Daniel Vetter 
---
 drivers/gpu/drm/drm_crtc.c |  118 ++--
 1 file changed, 80 insertions(+), 38 deletions(-)

diff --git a/drivers/gpu/drm/drm_crtc.c b/drivers/gpu/drm/drm_crtc.c
index e2d70f6..20ccdc4 100644
--- a/drivers/gpu/drm/drm_crtc.c
+++ b/drivers/gpu/drm/drm_crtc.c
@@ -356,6 +356,9 @@ int drm_framebuffer_init(struct drm_device *dev, struct 
drm_framebuffer *fb,
if (ret)
return ret;
 
+   /* Grab the idr reference. */
+   drm_framebuffer_reference(fb);
+
dev->mode_config.num_fb++;
list_add(&fb->head, &dev->mode_config.fb_list);
mutex_unlock(&dev->mode_config.fb_lock);
@@ -371,6 +374,23 @@ static void drm_framebuffer_free(struct kref *kref)
fb->funcs->destroy(fb);
 }
 
+static struct drm_framebuffer *__drm_framebuffer_lookup(struct drm_device *dev,
+   uint32_t id)
+{
+   struct drm_mode_object *obj = NULL;
+   struct drm_framebuffer *fb;
+
+   mutex_lock(&dev->mode_config.idr_mutex);
+   obj = idr_find(&dev->mode_config.crtc_idr, id);
+   if (!obj || (obj->type != DRM_MODE_OBJECT_FB) || (obj->id != id))
+   fb = NULL;
+   else
+   fb = obj_to_fb(obj);
+   mutex_unlock(&dev->mode_config.idr_mutex);
+
+   return fb;
+}
+
 /**
  * drm_framebuffer_lookup - look up a drm framebuffer and grab a reference
  * @dev: drm device
@@ -383,22 +403,12 @@ static void drm_framebuffer_free(struct kref *kref)
 struct drm_framebuffer *drm_framebuffer_lookup(struct drm_device *dev,
   uint32_t id)
 {
-   struct drm_mode_object *obj = NULL;
struct drm_framebuffer *fb;
 
mutex_lock(&dev->mode_config.fb_lock);
-
-   mutex_lock(&dev->mode_config.idr_mutex);
-   obj = idr_find(&dev->mode_config.crtc_idr, id);
-   if (!obj || (obj->type != DRM_MODE_OBJECT_FB) || (obj->id != id))
-   fb = NULL;
-   else
-   fb = obj_to_fb(obj);
-   mutex_unlock(&dev->mode_config.idr_mutex);
-
+   fb = __drm_framebuffer_lookup(dev, id);
if (fb)
kref_get(&fb->refcount);
-
mutex_unlock(&dev->mode_config.fb_lock);
 
return fb;
@@ -429,6 +439,24 @@ void drm_framebuffer_reference(struct drm_framebuffer *fb)
 }
 EXPORT_SYMBOL(drm_framebuffer_reference);
 
+static void drm_framebuffer_free_bug(struct kref *kref)
+{
+   BUG();
+}
+
+/* dev->mode_config.fb_lock must be held! */
+static void __drm_framebuffer_unregister(struct drm_device *dev,
+struct drm_framebuffer *fb)
+{
+   mutex_lock(&dev->mode_config.idr_mutex);
+   idr_remove(&dev->mode_config.crtc_idr, fb->base.id);
+   mutex_unlock(&dev->mode_config.idr_mutex);
+
+   fb->base.id = 0;
+
+   kref_put(&fb->refcount, drm_framebuffer_free_bug);
+}
+
 /**
  * drm_framebuffer_unregister_private - unregister a private fb from the 
lookup idr
  * @fb: fb to unregister
@@ -440,6 +468,12 @@ EXPORT_SYMBOL(drm_framebuffe

[Intel-gfx] [PATCH 22/37] drm: nest modeset locks within fpriv->fbs_lock

2012-12-12 Thread Daniel Vetter
Atm we still need to unconditionally take the modeset locks in the
rmfb paths. But eventually we only want to take them if there are
other users around as a slow-path. This way sane userspace avoids
blocking on edid reads and other stuff in rmfb if it ensures that the
fb isn't used anywhere by a crtc/plane.

We can do a quick check for such other users once framebuffers are
properly refcounting by locking at the refcount - if it's more than 1,
there are other users left. Again, rmfb racing against other ioctls
isn't a real problem, userspace is allowed to shoot its foot.

This patch just prepares this by moving the modeset locks to nest
within fpriv->fbs_lock. Now the distinction between the fbs_lock and
the device-global fb_lock is clear, since we need to hold the fbs_lock
outside of any modeset_locks in fb_release.

Signed-off-by: Daniel Vetter 
---
 drivers/gpu/drm/drm_crtc.c |8 
 1 file changed, 4 insertions(+), 4 deletions(-)

diff --git a/drivers/gpu/drm/drm_crtc.c b/drivers/gpu/drm/drm_crtc.c
index 20ccdc4..33e95bb 100644
--- a/drivers/gpu/drm/drm_crtc.c
+++ b/drivers/gpu/drm/drm_crtc.c
@@ -2266,13 +2266,13 @@ int drm_mode_addfb(struct drm_device *dev,
drm_modeset_unlock_all(dev);
return PTR_ERR(fb);
}
+   drm_modeset_unlock_all(dev);
 
mutex_lock(&file_priv->fbs_lock);
or->fb_id = fb->base.id;
list_add(&fb->filp_head, &file_priv->fbs);
DRM_DEBUG_KMS("[FB:%d]\n", fb->base.id);
mutex_unlock(&file_priv->fbs_lock);
-   drm_modeset_unlock_all(dev);
 
return ret;
 }
@@ -2449,6 +2449,7 @@ int drm_mode_addfb2(struct drm_device *dev,
drm_modeset_unlock_all(dev);
return PTR_ERR(fb);
}
+   drm_modeset_unlock_all(dev);
 
mutex_lock(&file_priv->fbs_lock);
r->fb_id = fb->base.id;
@@ -2456,7 +2457,6 @@ int drm_mode_addfb2(struct drm_device *dev,
DRM_DEBUG_KMS("[FB:%d]\n", fb->base.id);
mutex_unlock(&file_priv->fbs_lock);
 
-   drm_modeset_unlock_all(dev);
 
return ret;
 }
@@ -2651,7 +2651,6 @@ void drm_fb_release(struct drm_file *priv)
struct drm_device *dev = priv->minor->dev;
struct drm_framebuffer *fb, *tfb;
 
-   drm_modeset_lock_all(dev);
mutex_lock(&priv->fbs_lock);
list_for_each_entry_safe(fb, tfb, &priv->fbs, filp_head) {
 
@@ -2663,10 +2662,11 @@ void drm_fb_release(struct drm_file *priv)
list_del_init(&fb->filp_head);
 
/* This will also drop the fpriv->fbs reference. */
+   drm_modeset_lock_all(dev);
drm_framebuffer_remove(fb);
+   drm_modeset_unlock_all(dev);
}
mutex_unlock(&priv->fbs_lock);
-   drm_modeset_unlock_all(dev);
 }
 
 /**
-- 
1.7.10.4

___
Intel-gfx mailing list
Intel-gfx@lists.freedesktop.org
http://lists.freedesktop.org/mailman/listinfo/intel-gfx


[Intel-gfx] [PATCH 28/37] drm: encapsulate crtc->set_config calls

2012-12-12 Thread Daniel Vetter
With refcounting we need to adjust framebuffer refcounts at each
callsite - much easier to do if they all call the same little helper
function.

Signed-off-by: Daniel Vetter 
---
 drivers/gpu/drm/drm_crtc.c |   19 +--
 drivers/gpu/drm/drm_fb_helper.c|6 +++---
 drivers/gpu/drm/i2c/ch7006_drv.c   |2 +-
 drivers/gpu/drm/nouveau/nv04_display.c |2 +-
 drivers/gpu/drm/nouveau/nv17_tv.c  |2 +-
 drivers/gpu/drm/vmwgfx/vmwgfx_drv.c|2 +-
 include/drm/drm_crtc.h |1 +
 7 files changed, 25 insertions(+), 9 deletions(-)

diff --git a/drivers/gpu/drm/drm_crtc.c b/drivers/gpu/drm/drm_crtc.c
index ccf15ad..229853e 100644
--- a/drivers/gpu/drm/drm_crtc.c
+++ b/drivers/gpu/drm/drm_crtc.c
@@ -536,7 +536,7 @@ void drm_framebuffer_remove(struct drm_framebuffer *fb)
memset(&set, 0, sizeof(struct drm_mode_set));
set.crtc = crtc;
set.fb = NULL;
-   ret = crtc->funcs->set_config(&set);
+   ret = drm_mode_set_config_internal(&set);
if (ret)
DRM_ERROR("failed to reset crtc %p when fb was 
deleted\n", crtc);
}
@@ -1974,6 +1974,21 @@ out:
 }
 
 /**
+ * drm_mode_set_config_internal - helper to call ->set_config
+ * @set: modeset config to set
+ *
+ * This is a little helper to wrap internal calls to the ->set_config driver
+ * interface. The only thing it adds is correct refcounting dance.
+ */
+int drm_mode_set_config_internal(struct drm_mode_set *set)
+{
+   struct drm_crtc *crtc = set->crtc;
+
+   return crtc->funcs->set_config(set);
+}
+EXPORT_SYMBOL(drm_mode_set_config_internal);
+
+/**
  * drm_mode_setcrtc - set CRTC configuration
  * @dev: drm device for the ioctl
  * @data: data pointer for the ioctl
@@ -2137,7 +2152,7 @@ int drm_mode_setcrtc(struct drm_device *dev, void *data,
set.connectors = connector_set;
set.num_connectors = crtc_req->count_connectors;
set.fb = fb;
-   ret = crtc->funcs->set_config(&set);
+   ret = drm_mode_set_config_internal(&set);
 
 out:
kfree(connector_set);
diff --git a/drivers/gpu/drm/drm_fb_helper.c b/drivers/gpu/drm/drm_fb_helper.c
index d84ec67..403d53e 100644
--- a/drivers/gpu/drm/drm_fb_helper.c
+++ b/drivers/gpu/drm/drm_fb_helper.c
@@ -245,7 +245,7 @@ bool drm_fb_helper_restore_fbdev_mode(struct drm_fb_helper 
*fb_helper)
int i, ret;
for (i = 0; i < fb_helper->crtc_count; i++) {
struct drm_mode_set *mode_set = 
&fb_helper->crtc_info[i].mode_set;
-   ret = mode_set->crtc->funcs->set_config(mode_set);
+   ret = drm_mode_set_config_internal(mode_set);
if (ret)
error = true;
}
@@ -675,7 +675,7 @@ int drm_fb_helper_set_par(struct fb_info *info)
drm_modeset_lock_all(dev);
for (i = 0; i < fb_helper->crtc_count; i++) {
crtc = fb_helper->crtc_info[i].mode_set.crtc;
-   ret = 
crtc->funcs->set_config(&fb_helper->crtc_info[i].mode_set);
+   ret = 
drm_mode_set_config_internal(&fb_helper->crtc_info[i].mode_set);
if (ret) {
drm_modeset_unlock_all(dev);
return ret;
@@ -711,7 +711,7 @@ int drm_fb_helper_pan_display(struct fb_var_screeninfo *var,
modeset->y = var->yoffset;
 
if (modeset->num_connectors) {
-   ret = crtc->funcs->set_config(modeset);
+   ret = drm_mode_set_config_internal(modeset);
if (!ret) {
info->var.xoffset = var->xoffset;
info->var.yoffset = var->yoffset;
diff --git a/drivers/gpu/drm/i2c/ch7006_drv.c b/drivers/gpu/drm/i2c/ch7006_drv.c
index 599099f..c5c947c 100644
--- a/drivers/gpu/drm/i2c/ch7006_drv.c
+++ b/drivers/gpu/drm/i2c/ch7006_drv.c
@@ -364,7 +364,7 @@ static int ch7006_encoder_set_property(struct drm_encoder 
*encoder,
.crtc = crtc,
};
 
-   crtc->funcs->set_config(&modeset);
+   drm_mode_set_config_internal(&modeset);
}
}
 
diff --git a/drivers/gpu/drm/nouveau/nv04_display.c 
b/drivers/gpu/drm/nouveau/nv04_display.c
index 2cd6fb8..4c6e9f8 100644
--- a/drivers/gpu/drm/nouveau/nv04_display.c
+++ b/drivers/gpu/drm/nouveau/nv04_display.c
@@ -140,7 +140,7 @@ nv04_display_destroy(struct drm_device *dev)
.crtc = crtc,
};
 
-   crtc->funcs->set_config(&modeset);
+   drm_mode_set_config_internal(&modeset);
}
 
/* Restore state */
diff --git a/drivers/gpu/drm/nouveau/nv17_tv.c 
b/drivers/gpu/drm/nouveau/nv17_tv.c
index 897b636..bb3abfc 100644
--- a/drivers/gpu/drm/nouveau/nv17_tv.c
+++ b/drivers/gpu/drm/

[Intel-gfx] [PATCH] tests/gem_seqno_wrap: dont sync when crossing half of seqno space

2012-12-12 Thread Mika Kuoppala
For seqno comparison to work they have to be less than UINT32_MAX/2
apart. So when crossing the half way of seqno space, be careful not
to sync anything as this causes gpu hangs. Do real test with
syncing only when we are about to wrap.
---
 tests/gem_seqno_wrap.c |  161 +++-
 1 file changed, 117 insertions(+), 44 deletions(-)

diff --git a/tests/gem_seqno_wrap.c b/tests/gem_seqno_wrap.c
index b70f886..5ce8c93 100644
--- a/tests/gem_seqno_wrap.c
+++ b/tests/gem_seqno_wrap.c
@@ -47,7 +47,7 @@
 #include "intel_gpu_tools.h"
 #include "rendercopy.h"
 
-#define BUFFERS_TO_SYNC 128
+#define SAFETY_REGION 0x1f
 
 static int devid;
 static uint32_t last_seqno = 0;
@@ -64,6 +64,8 @@ struct option_struct {
int timeout;
int dontwrap;
int prewrap_space;
+   int random;
+   int buffers;
 };
 
 static struct option_struct options;
@@ -159,21 +161,34 @@ static void render_copyfunc(struct scratch_buf *src,
}
 }
 
-static int run_sync_test(void)
+static void exchange_uint(void *array, unsigned i, unsigned j)
+{
+   unsigned *i_arr = array;
+   unsigned i_tmp;
+
+   i_tmp = i_arr[i];
+   i_arr[i] = i_arr[j];
+   i_arr[j] = i_tmp;
+}
+
+static int run_sync_test(int num_buffers, bool verify)
 {
drm_intel_bufmgr *bufmgr;
-   int num_buffers = BUFFERS_TO_SYNC, max;
+   int max;
drm_intel_bo *src[128], *dst1[128], *dst2[128];
int width = 128, height = 128;
int fd;
int i;
int r = -1;
int failed = 0;
-
+   unsigned int *p_dst1, *p_dst2;
struct scratch_buf s_src[128], s_dst[128];
 
fd = drm_open_any();
assert(fd >= 0);
+
+   gem_quiescent_gpu(fd);
+
devid = intel_get_drm_devid(fd);
 
max = gem_aperture_size (fd) / (1024 * 1024) / 2;
@@ -187,7 +202,16 @@ static int run_sync_test(void)
batch_3d = intel_batchbuffer_alloc(bufmgr, intel_get_drm_devid(fd));
assert(batch_3d);
 
+   p_dst1 = malloc(num_buffers * sizeof(unsigned int));
+   if (p_dst1 == NULL)
+   return -ENOMEM;
+
+   p_dst2 = malloc(num_buffers * sizeof(unsigned int));
+   if (p_dst2 == NULL)
+   return -ENOMEM;
+
for (i = 0; i < num_buffers; i++) {
+   p_dst1[i] = p_dst2[i] = i;
src[i] = create_bo(bufmgr, i, width, height);
dst1[i] = create_bo(bufmgr, ~i, width, height);
dst2[i] = create_bo(bufmgr, ~i, width, height);
@@ -195,19 +219,27 @@ static int run_sync_test(void)
init_buffer(bufmgr, &s_dst[i], dst1[i], width, height);
}
 
-   /* dummy = create_bo(bufmgr, 0, width, height); */
-
-   for (i = 0; i < num_buffers; i++) {
-   render_copyfunc(&s_src[i], &s_dst[i], width, height);
-   intel_copy_bo(batch_blt, dst2[i], dst1[i], width, height);
-   }
-
-   for (i = 0; i < num_buffers; i++) {
-   r = cmp_bo(dst2[i], i, width, height);
-   if (r) {
-   printf("buffer %d differs, seqno_before_test 0x%x, 
approximated seqno on test fail 0x%x\n",
-  i, last_seqno_write, last_seqno_write + i * 2);
-   failed = -1;
+   drmtest_permute_array(p_dst1, num_buffers, exchange_uint);
+   drmtest_permute_array(p_dst2, num_buffers, exchange_uint);
+
+   for (i = 0; i < num_buffers; i++)
+   render_copyfunc(&s_src[i], &s_dst[p_dst1[i]], width, height);
+
+   /* Only sync between buffers if this is actual test run and
+* not a seqno filler */
+   if (verify) {
+   for (i = 0; i < num_buffers; i++)
+   intel_copy_bo(batch_blt, dst2[p_dst2[i]], 
dst1[p_dst1[i]],
+ width, height);
+
+   for (i = 0; i < num_buffers; i++) {
+   r = cmp_bo(dst2[p_dst2[i]], i, width, height);
+   if (r) {
+   printf("buffer %d differs, seqno_before_test 
0x%x, "
+  " approximated seqno on test fail 
0x%x\n",
+  i, last_seqno_write, last_seqno_write + 
i * 2);
+   failed = -1;
+   }
}
}
 
@@ -221,6 +253,11 @@ static int run_sync_test(void)
intel_batchbuffer_free(batch_blt);
drm_intel_bufmgr_destroy(bufmgr);
 
+   free(p_dst1);
+   free(p_dst2);
+
+   gem_quiescent_gpu(fd);
+
close(fd);
 
return failed;
@@ -270,7 +307,9 @@ static int run_cmd(char *s)
if (r == pid) {
if(WIFEXITED(status)) {
if (WEXITSTATUS(status))
-   fprintf(stderr, "child returned 
with %d\n", WEXITSTATUS(status));
+

Re: [Intel-gfx] [PATCH 00/37] [RFC] revamped modeset locking

2012-12-12 Thread Daniel Vetter
On Wed, Dec 12, 2012 at 02:06:40PM +0100, Daniel Vetter wrote:
> Hi all,
> 
> First thing first: It works, I now no longer have a few dropped frames every 
> 10s
> on my testbox here with the pageflip i-g-t tests.
> 
> Random notes:
> 
> - New design has per-crtc locks to protect the crtc input-side (pageflip,
>   cursor) for r/w and the output state of the crtc (mode, dpms) as read-only. 
> It
>   also required completely revamped fb lifecycle management, those are now
>   refcounted for real (which is a nice cleanup). Imo the proposed rwsem hack
>   from Dave/Ajax is too ugly to life in comparison.
> 
> - Smoke tested on i915, compile tested for x86 drivers, probably all arm 
> drivers
>   trivially broken. I plan add tons of i-g-t testscases to exercise all the
>   cornercases with i915 (so that lockdep has full coverage among other things)
>   and at least run radeon/nouveau a bit. I also need to set up an arm
>   crosscompiler. Generally testing feedback on !i915 highly welcome.
> 
> - Driver audit: I've tried to not break anything more than it already is, and
>   for the big three desktop drivers fixup any related breakage I've noticed. 
> Big
>   unknown is vmwgfx since that driver is over my head. Generally review from
>   driver devs is required to check all corner-cases.
> 
> - Merging, presuming people like this idea here: I think it'd be good to slurp
>   in the driver changes as early as possible. The big rework probably has to 
> go
>   in with a separate pull directly to drm-next for all drivers - there are
>   simply too many sync-points in this rework where all drivers need to follow
>   the new rules before core drm changes can be applied.
> 
> - Having a global lock which synchronizing object destruction is a royal pain,
>   since it reliably results in that locking getting in the way almost 
> everywhere
>   when trying to implement refcounting.  It's fixed now for fb & the 
> mode_config
>   mutex, but I'm already eagerly looking forward to simplifying 
> dev->struct_mutex
>   gem_bo cleanup rules.
> 
> - drm teardown/setup synchronization and locking is terminally broken. Insane
>   volunteers welcome, I don't want to do this.
> 
> - I've mentioned that reading too much driver code causes nightmares, right?
>   vmwgfx ...
> 
> Please bring on the flames.

I've forgotten to add: Patch series pushed out to the drm-kms-locking
branch in my personal fdo repo:

http://cgit.freedesktop.org/~danvet/drm/log/?h=drm-kms-locking

-Daniel
-- 
Daniel Vetter
Software Engineer, Intel Corporation
+41 (0) 79 365 57 48 - http://blog.ffwll.ch
___
Intel-gfx mailing list
Intel-gfx@lists.freedesktop.org
http://lists.freedesktop.org/mailman/listinfo/intel-gfx


Re: [Intel-gfx] [PATCH 34/37] drm/ttm: fix fence locking in ttm_buffer_object_transfer

2012-12-12 Thread Daniel Vetter
On Wed, Dec 12, 2012 at 3:48 PM, Jerome Glisse  wrote:
> Instead of that i would just move the call to
> ttm_buffer_object_transfer to happen before releasing the fence_lock
> in ttm_bo_move_accel_cleanup , something like :

Yeah, looks better. Fixed up locally.
-Daniel
-- 
Daniel Vetter
Software Engineer, Intel Corporation
+41 (0) 79 365 57 48 - http://blog.ffwll.ch
___
Intel-gfx mailing list
Intel-gfx@lists.freedesktop.org
http://lists.freedesktop.org/mailman/listinfo/intel-gfx


[Intel-gfx] gfx context switch

2012-12-12 Thread Zhang, Xiong Y
Hi, all:

When gfx executes batch buffer in render ring buffer, it will do context switch 
.

Since only when the previous batch buffer has finished, the next batch buffer 
can start. the batch buffer is executed in order. So I think there is no need 
to do context switch.

Why i915 driver introduce context switch ?  If context switch is disabled, what 
error will occur ?

Why gfx need context switch, can somebody give me a example to use context 
switch ?

Thanks in advance.
___
Intel-gfx mailing list
Intel-gfx@lists.freedesktop.org
http://lists.freedesktop.org/mailman/listinfo/intel-gfx


[Intel-gfx] [PATCH 00/81] drm/i915: Atomic mode setting / page flip, yet again

2012-12-12 Thread ville . syrjala
Another month, another massive atomic patchset.

I managed to clean up warts left over from the modeset-rework rebase,
but other than that I haven't really found the time to touch this too
much since the last time I posted patches from this set.

Seeing as my schedule isn't getting any less busy in the forseeable
future, it would be nice to get this monster merged sooner rather
than never.

Ever since the code started to resemble something sane, I've tried
to avoid squashing patches, just in case someone was actually trying
to follow what's changed. But clearly some of the patches can
be squashed, and that would probably allow some of the earlier ones
to be dropped entirely.

What's clearly needed is a test tool that will stresss the mode
setting side of the code more. My glplane test just changes the
modes in the beginning, and then just does flips and other plane
stuff. I'll try to get something done on that front before Christmas.

Repo is here:
https://gitorious.org/vsyrjala/linux/commits/drm_atomic_23

The repo also contains 64bit get_user() implementation for x86-32,
which I sent to lkml and x86 people for review. So this should now
be testable even on a 32bit system.
___
Intel-gfx mailing list
Intel-gfx@lists.freedesktop.org
http://lists.freedesktop.org/mailman/listinfo/intel-gfx


[Intel-gfx] [PATCH 01/81] drm: Add struct drm_region and assorted utility functions

2012-12-12 Thread ville . syrjala
From: Ville Syrjälä 

struct drm_region represents a two dimensional region. The utility
functions are there to help driver writers.

Signed-off-by: Ville Syrjälä 
---
 drivers/gpu/drm/drm_crtc.c |  155 
 include/drm/drm_crtc.h |   24 +++
 2 files changed, 179 insertions(+), 0 deletions(-)

diff --git a/drivers/gpu/drm/drm_crtc.c b/drivers/gpu/drm/drm_crtc.c
index d6d0072..f64e572 100644
--- a/drivers/gpu/drm/drm_crtc.c
+++ b/drivers/gpu/drm/drm_crtc.c
@@ -3923,3 +3923,158 @@ int drm_format_vert_chroma_subsampling(uint32_t format)
}
 }
 EXPORT_SYMBOL(drm_format_vert_chroma_subsampling);
+
+/**
+ * drm_region_adjust_size - adjust the size of the region
+ * @r: region to be adjusted
+ * @x: horizontal adjustment
+ * @y: vertical adjustment
+ *
+ * Change the size of region @r by @x in the horizontal direction,
+ * and by @y in the vertical direction, while keeping the center
+ * of @r stationary.
+ *
+ * Positive @x and @y increase the size, negative values decrease it.
+ */
+void drm_region_adjust_size(struct drm_region *r, int x, int y)
+{
+   r->x1 -= x >> 1;
+   r->y1 -= y >> 1;
+   r->x2 += (x + 1) >> 1;
+   r->y2 += (y + 1) >> 1;
+}
+EXPORT_SYMBOL(drm_region_adjust_size);
+
+/**
+ * drm_region_translate - translate the region
+ * @r: region to be tranlated
+ * @x: horizontal translation
+ * @y: vertical translation
+ *
+ * Move region @r by @x in the horizontal direction,
+ * and by @y in the vertical direction.
+ */
+void drm_region_translate(struct drm_region *r, int x, int y)
+{
+   r->x1 += x;
+   r->y1 += y;
+   r->x2 += x;
+   r->y2 += y;
+}
+EXPORT_SYMBOL(drm_region_translate);
+
+/**
+ * drm_region_subsample - subsample a region
+ * @r: region to be subsampled
+ * @hsub: horizontal subsampling factor
+ * @vsub: vertical subsampling factor
+ *
+ * Divide the coordinates of region @r by @hsub and @vsub.
+ */
+void drm_region_subsample(struct drm_region *r, int hsub, int vsub)
+{
+   r->x1 /= hsub;
+   r->y1 /= vsub;
+   r->x2 /= hsub;
+   r->y2 /= vsub;
+}
+EXPORT_SYMBOL(drm_region_subsample);
+
+/**
+ * drm_region_width - determine the region width
+ * @r: region whose width is returned
+ *
+ * RETURNS:
+ * The width of the region.
+ */
+int drm_region_width(const struct drm_region *r)
+{
+   return r->x2 - r->x1;
+}
+EXPORT_SYMBOL(drm_region_width);
+
+/**
+ * drm_region_height - determine the region height
+ * @r: region whose height is returned
+ *
+ * RETURNS:
+ * The height of the region.
+ */
+int drm_region_height(const struct drm_region *r)
+{
+   return r->y2 - r->y1;
+}
+EXPORT_SYMBOL(drm_region_height);
+
+/**
+ * drm_region_visible - determine if the the region is visible
+ * @r: region whose visibility is returned
+ *
+ * RETURNS:
+ * @true if the region is visible, @false otherwise.
+ */
+bool drm_region_visible(const struct drm_region *r)
+{
+   return drm_region_width(r) > 0 && drm_region_height(r) > 0;
+}
+EXPORT_SYMBOL(drm_region_visible);
+
+/**
+ * drm_region_clip - clip one region by another region
+ * @r: region to be clipped
+ * @clip: clip region
+ *
+ * Clip region @r by region @clip.
+ *
+ * RETURNS:
+ * @true if the region is still visible after being clipped,
+ * @false otherwise.
+ */
+bool drm_region_clip(struct drm_region *r, const struct drm_region *clip)
+{
+   r->x1 = max(r->x1, clip->x1);
+   r->y1 = max(r->y1, clip->y1);
+   r->x2 = min(r->x2, clip->x2);
+   r->y2 = min(r->y2, clip->y2);
+
+   return drm_region_visible(r);
+}
+EXPORT_SYMBOL(drm_region_clip);
+
+/**
+ * drm_region_clip_scaled - perform a scaled clip operation
+ * @src: source window region
+ * @dst: destination window region
+ * @clip: clip region
+ * @hscale: horizontal scaling factor
+ * @vscale: vertical scaling factor
+ *
+ * Clip region @dst by region @clip. Clip region @src by the same
+ * amounts multiplied by @hscale and @vscale.
+ *
+ * RETUTRNS:
+ * @true if region @dst is still visible after being clipped,
+ * @false otherwise
+ */
+bool drm_region_clip_scaled(struct drm_region *src, struct drm_region *dst,
+   const struct drm_region *clip,
+   int hscale, int vscale)
+{
+   int diff;
+
+   diff = clip->x1 - dst->x1;
+   if (diff > 0)
+   src->x1 += diff * hscale;
+   diff = clip->y1 - dst->y1;
+   if (diff > 0)
+   src->y1 += diff * vscale;
+   diff = dst->x2 - clip->x2;
+   if (diff > 0)
+   src->x2 -= diff * hscale;
+   diff = dst->y2 - clip->y2;
+   if (diff > 0)
+   src->y2 -= diff * vscale;
+
+   return drm_region_clip(dst, clip);
+}
+EXPORT_SYMBOL(drm_region_clip_scaled);
diff --git a/include/drm/drm_crtc.h b/include/drm/drm_crtc.h
index 3538eda..0ac6d83 100644
--- a/include/drm/drm_crtc.h
+++ b/include/drm/drm_crtc.h
@@ -1082,4 +1082,28 @@ extern int drm_format_plane_cpp(uint32_t format, int 
plane);
 ex

[Intel-gfx] [PATCH 02/81] drm: Add drm_calc_{hscale, vscale}() utility functions

2012-12-12 Thread ville . syrjala
From: Ville Syrjälä 

Signed-off-by: Ville Syrjälä 
---
 drivers/gpu/drm/drm_crtc.c |  102 
 include/drm/drm_crtc.h |4 ++
 2 files changed, 106 insertions(+), 0 deletions(-)

diff --git a/drivers/gpu/drm/drm_crtc.c b/drivers/gpu/drm/drm_crtc.c
index f64e572..8918179 100644
--- a/drivers/gpu/drm/drm_crtc.c
+++ b/drivers/gpu/drm/drm_crtc.c
@@ -4078,3 +4078,105 @@ bool drm_region_clip_scaled(struct drm_region *src, 
struct drm_region *dst,
return drm_region_clip(dst, clip);
 }
 EXPORT_SYMBOL(drm_region_clip_scaled);
+
+/**
+ * drm_calc_hscale - calculate the horizontal scaling factor
+ * @src: source window region
+ * @dst: destination window region
+ * @min_hscale: minimum allowed horizontal scaling factor
+ * @max_hscale: maximum allowed horizontal scaling factor
+ *
+ * Calculate the horizontal scaling factor as
+ * (@src width) / (@dst width).
+ *
+ * If the calculated scaling factor is below @min_hscale,
+ * decrease the width of region @dst to compensate.
+ *
+ * If the calculcated scaling factor is above @max_hscale,
+ * decrease the width of region @src to compensate.
+ *
+ * RETURNS:
+ * The horizontal scaling factor.
+ */
+int drm_calc_hscale(struct drm_region *src, struct drm_region *dst,
+   int min_hscale, int max_hscale)
+{
+   int src_w = drm_region_width(src);
+   int dst_w = drm_region_width(dst);
+   int hscale;
+
+   if (dst_w <= 0)
+   return 0;
+
+   hscale = src_w / dst_w;
+
+   if (hscale < min_hscale) {
+   int max_dst_w = src_w / min_hscale;
+
+   drm_region_adjust_size(dst, max_dst_w - dst_w, 0);
+
+   return min_hscale;
+   }
+
+   if (hscale > max_hscale) {
+   int max_src_w = dst_w * max_hscale;
+
+   drm_region_adjust_size(src, max_src_w - src_w, 0);
+
+   return max_hscale;
+   }
+
+   return hscale;
+}
+EXPORT_SYMBOL(drm_calc_hscale);
+
+/**
+ * drm_calc_vscale - calculate the vertical scaling factor
+ * @src: source window region
+ * @dst: destination window region
+ * @min_vscale: minimum allowed vertical scaling factor
+ * @max_vscale: maximum allowed vertical scaling factor
+ *
+ * Calculate the vertical scaling factor as
+ * (@src height) / (@dst height).
+ *
+ * If the calculated scaling factor is below @min_vscale,
+ * decrease the height of region @dst to compensate.
+ *
+ * If the calculcated scaling factor is above @max_vscale,
+ * decrease the height of region @src to compensate.
+ *
+ * RETURNS:
+ * The vertical scaling factor.
+ */
+int drm_calc_vscale(struct drm_region *src, struct drm_region *dst,
+   int min_vscale, int max_vscale)
+{
+   int src_h = drm_region_height(src);
+   int dst_h = drm_region_height(dst);
+   int vscale;
+
+   if (dst_h <= 0)
+   return 0;
+
+   vscale = src_h / dst_h;
+
+   if (vscale < min_vscale) {
+   int max_dst_h = src_h / min_vscale;
+
+   drm_region_adjust_size(dst, 0, max_dst_h - dst_h);
+
+   return min_vscale;
+   }
+
+   if (vscale > max_vscale) {
+   int max_src_h = dst_h * max_vscale;
+
+   drm_region_adjust_size(src, 0, max_src_h - src_h);
+
+   return max_vscale;
+   }
+
+   return vscale;
+}
+EXPORT_SYMBOL(drm_calc_vscale);
diff --git a/include/drm/drm_crtc.h b/include/drm/drm_crtc.h
index 0ac6d83..a80a346 100644
--- a/include/drm/drm_crtc.h
+++ b/include/drm/drm_crtc.h
@@ -1105,5 +1105,9 @@ extern bool drm_region_clip_scaled(struct drm_region *src,
   struct drm_region *dst,
   const struct drm_region *clip,
   int hscale, int vscale);
+extern int drm_calc_hscale(struct drm_region *src, struct drm_region *dst,
+  int min_hscale, int max_hscale);
+extern int drm_calc_vscale(struct drm_region *src, struct drm_region *dst,
+  int min_vscale, int max_vscale);
 
 #endif /* __DRM_CRTC_H__ */
-- 
1.7.8.6

___
Intel-gfx mailing list
Intel-gfx@lists.freedesktop.org
http://lists.freedesktop.org/mailman/listinfo/intel-gfx


[Intel-gfx] [PATCH 03/81] drm: Keep a copy of last plane coordinates

2012-12-12 Thread ville . syrjala
From: Ville Syrjälä 

If the update_plane() operation succeeds, make a copy of the requested
src and crtc coordinates, so that the the plane may be reclipped if the
display mode changed later.

Signed-off-by: Ville Syrjälä 
---
 drivers/gpu/drm/drm_crtc.c |8 
 include/drm/drm_crtc.h |4 
 2 files changed, 12 insertions(+), 0 deletions(-)

diff --git a/drivers/gpu/drm/drm_crtc.c b/drivers/gpu/drm/drm_crtc.c
index 8918179..3164131 100644
--- a/drivers/gpu/drm/drm_crtc.c
+++ b/drivers/gpu/drm/drm_crtc.c
@@ -1852,6 +1852,14 @@ int drm_mode_setplane(struct drm_device *dev, void *data,
if (!ret) {
plane->crtc = crtc;
plane->fb = fb;
+   plane->crtc_x = plane_req->crtc_x;
+   plane->crtc_y = plane_req->crtc_y;
+   plane->crtc_w = plane_req->crtc_w;
+   plane->crtc_h = plane_req->crtc_h;
+   plane->src_x = plane_req->src_x;
+   plane->src_y = plane_req->src_y;
+   plane->src_w = plane_req->src_w;
+   plane->src_h = plane_req->src_h;
}
 
 out:
diff --git a/include/drm/drm_crtc.h b/include/drm/drm_crtc.h
index a80a346..6b7d809 100644
--- a/include/drm/drm_crtc.h
+++ b/include/drm/drm_crtc.h
@@ -672,6 +672,10 @@ struct drm_plane {
void *helper_private;
 
struct drm_object_properties properties;
+
+   uint32_t src_x, src_y, src_w, src_h;
+   int32_t crtc_x, crtc_y;
+   uint32_t crtc_w, crtc_h;
 };
 
 /**
-- 
1.7.8.6

___
Intel-gfx mailing list
Intel-gfx@lists.freedesktop.org
http://lists.freedesktop.org/mailman/listinfo/intel-gfx


[Intel-gfx] [PATCH 04/81] drm: Add restore_fbdev_mode() hook to drm_fb_helper

2012-12-12 Thread ville . syrjala
From: Ville Syrjälä 

Add an optional driver specific restore_fbdev_mode() hook to
drm_fb_helper. If the driver doesn't provide the hook,
drm_fb_helper_restore_fbdev_mode() is called directly as before.

In this hook the driver can disable additional planes, cursors etc.
that shouldn't be visible while fbdev is in control.

Signed-off-by: Ville Syrjälä 
---
 drivers/gpu/drm/drm_fb_helper.c |5 -
 include/drm/drm_fb_helper.h |1 +
 2 files changed, 5 insertions(+), 1 deletions(-)

diff --git a/drivers/gpu/drm/drm_fb_helper.c b/drivers/gpu/drm/drm_fb_helper.c
index 05e623a..6902097 100644
--- a/drivers/gpu/drm/drm_fb_helper.c
+++ b/drivers/gpu/drm/drm_fb_helper.c
@@ -265,7 +265,10 @@ static bool drm_fb_helper_force_kernel_mode(void)
if (helper->dev->switch_power_state == DRM_SWITCH_POWER_OFF)
continue;
 
-   ret = drm_fb_helper_restore_fbdev_mode(helper);
+   if (helper->funcs->restore_fbdev_mode)
+   ret = helper->funcs->restore_fbdev_mode(helper);
+   else
+   ret = drm_fb_helper_restore_fbdev_mode(helper);
if (ret)
error = true;
}
diff --git a/include/drm/drm_fb_helper.h b/include/drm/drm_fb_helper.h
index 5120b01..7f76e9c 100644
--- a/include/drm/drm_fb_helper.h
+++ b/include/drm/drm_fb_helper.h
@@ -56,6 +56,7 @@ struct drm_fb_helper_funcs {
 
int (*fb_probe)(struct drm_fb_helper *helper,
struct drm_fb_helper_surface_size *sizes);
+   int (*restore_fbdev_mode)(struct drm_fb_helper *helper);
 };
 
 struct drm_fb_helper_connector {
-- 
1.7.8.6

___
Intel-gfx mailing list
Intel-gfx@lists.freedesktop.org
http://lists.freedesktop.org/mailman/listinfo/intel-gfx


[Intel-gfx] [PATCH 05/81] drm: Export drm_property_create_blob() and drm_property_destroy_blob()

2012-12-12 Thread ville . syrjala
From: Ville Syrjälä 

Signed-off-by: Ville Syrjälä 
---
 drivers/gpu/drm/drm_crtc.c |8 +---
 include/drm/drm_crtc.h |4 
 2 files changed, 9 insertions(+), 3 deletions(-)

diff --git a/drivers/gpu/drm/drm_crtc.c b/drivers/gpu/drm/drm_crtc.c
index 3164131..38b8ce3 100644
--- a/drivers/gpu/drm/drm_crtc.c
+++ b/drivers/gpu/drm/drm_crtc.c
@@ -3112,8 +3112,8 @@ done:
return ret;
 }
 
-static struct drm_property_blob *drm_property_create_blob(struct drm_device 
*dev, int length,
- void *data)
+struct drm_property_blob *drm_property_create_blob(struct drm_device *dev, int 
length,
+  void *data)
 {
struct drm_property_blob *blob;
int ret;
@@ -3138,14 +3138,16 @@ static struct drm_property_blob 
*drm_property_create_blob(struct drm_device *dev
list_add_tail(&blob->head, &dev->mode_config.property_blob_list);
return blob;
 }
+EXPORT_SYMBOL(drm_property_create_blob);
 
-static void drm_property_destroy_blob(struct drm_device *dev,
+void drm_property_destroy_blob(struct drm_device *dev,
   struct drm_property_blob *blob)
 {
drm_mode_object_put(dev, &blob->base);
list_del(&blob->head);
kfree(blob);
 }
+EXPORT_SYMBOL(drm_property_destroy_blob);
 
 int drm_mode_getblob_ioctl(struct drm_device *dev,
   void *data, struct drm_file *file_priv)
diff --git a/include/drm/drm_crtc.h b/include/drm/drm_crtc.h
index 6b7d809..27812e0 100644
--- a/include/drm/drm_crtc.h
+++ b/include/drm/drm_crtc.h
@@ -970,6 +970,10 @@ struct drm_property *drm_property_create_range(struct 
drm_device *dev, int flags
 const char *name,
 uint64_t min, uint64_t max);
 extern void drm_property_destroy(struct drm_device *dev, struct drm_property 
*property);
+extern struct drm_property_blob *drm_property_create_blob(struct drm_device 
*dev,
+ int length, void 
*data);
+extern void drm_property_destroy_blob(struct drm_device *dev,
+ struct drm_property_blob *blob);
 extern int drm_property_add_enum(struct drm_property *property, int index,
 uint64_t value, const char *name);
 extern int drm_mode_create_dvi_i_properties(struct drm_device *dev);
-- 
1.7.8.6

___
Intel-gfx mailing list
Intel-gfx@lists.freedesktop.org
http://lists.freedesktop.org/mailman/listinfo/intel-gfx


[Intel-gfx] [PATCH 06/81] drm: Allow signed values for range properties

2012-12-12 Thread ville . syrjala
From: Ville Syrjälä 

Treat a range property as signed when the unsigned minimum value is
larger than the unsigned maximum value.

Signed-off-by: Ville Syrjälä 
---
 drivers/gpu/drm/drm_crtc.c |   17 ++---
 1 files changed, 14 insertions(+), 3 deletions(-)

diff --git a/drivers/gpu/drm/drm_crtc.c b/drivers/gpu/drm/drm_crtc.c
index 38b8ce3..7badd2a 100644
--- a/drivers/gpu/drm/drm_crtc.c
+++ b/drivers/gpu/drm/drm_crtc.c
@@ -3213,14 +3213,25 @@ int drm_mode_connector_update_edid_property(struct 
drm_connector *connector,
 }
 EXPORT_SYMBOL(drm_mode_connector_update_edid_property);
 
-static bool drm_property_change_is_valid(struct drm_property *property,
+static bool range_property_is_signed(const struct drm_property *property)
+{
+   return property->values[0] > property->values[1];
+}
+
+static bool drm_property_change_is_valid(const struct drm_property *property,
 uint64_t value)
 {
if (property->flags & DRM_MODE_PROP_IMMUTABLE)
return false;
if (property->flags & DRM_MODE_PROP_RANGE) {
-   if (value < property->values[0] || value > property->values[1])
-   return false;
+   if (range_property_is_signed(property)) {
+   if ((int64_t)value < (int64_t)property->values[0] ||
+   (int64_t)value > (int64_t)property->values[1])
+   return false;
+   } else {
+   if (value < property->values[0] || value > 
property->values[1])
+   return false;
+   }
return true;
} else if (property->flags & DRM_MODE_PROP_BITMASK) {
int i;
-- 
1.7.8.6

___
Intel-gfx mailing list
Intel-gfx@lists.freedesktop.org
http://lists.freedesktop.org/mailman/listinfo/intel-gfx


[Intel-gfx] [PATCH 07/81] drm: Allow drm_mode_object_find() to look up an object of any type

2012-12-12 Thread ville . syrjala
From: Ville Syrjälä 

To avoid having to pass object types from userspace for atomic mode
setting ioctl, allow drm_mode_object_find() to look up an object of any
type. This will only work as long as the all object types share the ID
space.

Signed-off-by: Ville Syrjälä 
---
 drivers/gpu/drm/drm_crtc.c |3 ++-
 include/drm/drm_crtc.h |1 +
 2 files changed, 3 insertions(+), 1 deletions(-)

diff --git a/drivers/gpu/drm/drm_crtc.c b/drivers/gpu/drm/drm_crtc.c
index 7badd2a..2dd3649 100644
--- a/drivers/gpu/drm/drm_crtc.c
+++ b/drivers/gpu/drm/drm_crtc.c
@@ -267,7 +267,8 @@ struct drm_mode_object *drm_mode_object_find(struct 
drm_device *dev,
 
mutex_lock(&dev->mode_config.idr_mutex);
obj = idr_find(&dev->mode_config.crtc_idr, id);
-   if (!obj || (obj->type != type) || (obj->id != id))
+   if (!obj || (type != DRM_MODE_OBJECT_ANY && obj->type != type) ||
+   (obj->id != id))
obj = NULL;
mutex_unlock(&dev->mode_config.idr_mutex);
 
diff --git a/include/drm/drm_crtc.h b/include/drm/drm_crtc.h
index 27812e0..28a972a 100644
--- a/include/drm/drm_crtc.h
+++ b/include/drm/drm_crtc.h
@@ -48,6 +48,7 @@ struct drm_object_properties;
 #define DRM_MODE_OBJECT_FB 0xfbfbfbfb
 #define DRM_MODE_OBJECT_BLOB 0x
 #define DRM_MODE_OBJECT_PLANE 0x
+#define DRM_MODE_OBJECT_ANY 0
 
 struct drm_mode_object {
uint32_t id;
-- 
1.7.8.6

___
Intel-gfx mailing list
Intel-gfx@lists.freedesktop.org
http://lists.freedesktop.org/mailman/listinfo/intel-gfx


[Intel-gfx] [PATCH 08/81] drm: Export drm_encoder_crtc_ok

2012-12-12 Thread ville . syrjala
From: Ville Syrjälä 

---
 drivers/gpu/drm/drm_crtc_helper.c |5 +++--
 include/drm/drm_crtc_helper.h |3 +++
 2 files changed, 6 insertions(+), 2 deletions(-)

diff --git a/drivers/gpu/drm/drm_crtc_helper.c 
b/drivers/gpu/drm/drm_crtc_helper.c
index 7b2d378..0d62c94 100644
--- a/drivers/gpu/drm/drm_crtc_helper.c
+++ b/drivers/gpu/drm/drm_crtc_helper.c
@@ -312,8 +312,8 @@ EXPORT_SYMBOL(drm_helper_disable_unused_functions);
  *
  * Return false if @encoder can't be driven by @crtc, true otherwise.
  */
-static bool drm_encoder_crtc_ok(struct drm_encoder *encoder,
-   struct drm_crtc *crtc)
+bool drm_encoder_crtc_ok(struct drm_encoder *encoder,
+struct drm_crtc *crtc)
 {
struct drm_device *dev;
struct drm_crtc *tmp;
@@ -333,6 +333,7 @@ static bool drm_encoder_crtc_ok(struct drm_encoder *encoder,
return true;
return false;
 }
+EXPORT_SYMBOL(drm_encoder_crtc_ok);
 
 /*
  * Check the CRTC we're going to map each output to vs. its current
diff --git a/include/drm/drm_crtc_helper.h b/include/drm/drm_crtc_helper.h
index f43d556..5abae74 100644
--- a/include/drm/drm_crtc_helper.h
+++ b/include/drm/drm_crtc_helper.h
@@ -169,4 +169,7 @@ extern void drm_kms_helper_hotplug_event(struct drm_device 
*dev);
 extern void drm_kms_helper_poll_disable(struct drm_device *dev);
 extern void drm_kms_helper_poll_enable(struct drm_device *dev);
 
+extern bool drm_encoder_crtc_ok(struct drm_encoder *encoder,
+   struct drm_crtc *crtc);
+
 #endif
-- 
1.7.8.6

___
Intel-gfx mailing list
Intel-gfx@lists.freedesktop.org
http://lists.freedesktop.org/mailman/listinfo/intel-gfx


[Intel-gfx] [PATCH 09/81] drm: Export drm_crtc_prepare_encoders()

2012-12-12 Thread ville . syrjala
From: Ville Syrjälä 

---
 drivers/gpu/drm/drm_crtc_helper.c |3 ++-
 include/drm/drm_crtc_helper.h |1 +
 2 files changed, 3 insertions(+), 1 deletions(-)

diff --git a/drivers/gpu/drm/drm_crtc_helper.c 
b/drivers/gpu/drm/drm_crtc_helper.c
index 0d62c94..30eb557 100644
--- a/drivers/gpu/drm/drm_crtc_helper.c
+++ b/drivers/gpu/drm/drm_crtc_helper.c
@@ -340,7 +340,7 @@ EXPORT_SYMBOL(drm_encoder_crtc_ok);
  * CRTC.  If they don't match, we have to disable the output and the CRTC
  * since the driver will have to re-route things.
  */
-static void
+void
 drm_crtc_prepare_encoders(struct drm_device *dev)
 {
struct drm_encoder_helper_funcs *encoder_funcs;
@@ -357,6 +357,7 @@ drm_crtc_prepare_encoders(struct drm_device *dev)
drm_encoder_disable(encoder);
}
 }
+EXPORT_SYMBOL(drm_crtc_prepare_encoders);
 
 /**
  * drm_crtc_helper_set_mode - internal helper to set a mode
diff --git a/include/drm/drm_crtc_helper.h b/include/drm/drm_crtc_helper.h
index 5abae74..7702a3a 100644
--- a/include/drm/drm_crtc_helper.h
+++ b/include/drm/drm_crtc_helper.h
@@ -171,5 +171,6 @@ extern void drm_kms_helper_poll_enable(struct drm_device 
*dev);
 
 extern bool drm_encoder_crtc_ok(struct drm_encoder *encoder,
struct drm_crtc *crtc);
+extern void drm_crtc_prepare_encoders(struct drm_device *dev);
 
 #endif
-- 
1.7.8.6

___
Intel-gfx mailing list
Intel-gfx@lists.freedesktop.org
http://lists.freedesktop.org/mailman/listinfo/intel-gfx


[Intel-gfx] [PATCH 10/81] drm: Refactor object property check code

2012-12-12 Thread ville . syrjala
From: Ville Syrjälä 

Refactor the code to check whether an object has a specific property
to a new function.

Signed-off-by: Ville Syrjälä 
---
 drivers/gpu/drm/drm_crtc.c |   20 ++--
 1 files changed, 14 insertions(+), 6 deletions(-)

diff --git a/drivers/gpu/drm/drm_crtc.c b/drivers/gpu/drm/drm_crtc.c
index 2dd3649..0a9a7cb 100644
--- a/drivers/gpu/drm/drm_crtc.c
+++ b/drivers/gpu/drm/drm_crtc.c
@@ -3374,6 +3374,19 @@ out:
return ret;
 }
 
+static bool object_has_prop(const struct drm_mode_object *obj, u32 prop_id)
+{
+   int i;
+
+   if (!obj->properties)
+   return false;
+
+   for (i = 0; i < obj->properties->count; i++)
+   if (obj->properties->ids[i] == prop_id)
+   return true;
+   return false;
+}
+
 int drm_mode_obj_set_property_ioctl(struct drm_device *dev, void *data,
struct drm_file *file_priv)
 {
@@ -3382,7 +3395,6 @@ int drm_mode_obj_set_property_ioctl(struct drm_device 
*dev, void *data,
struct drm_mode_object *prop_obj;
struct drm_property *property;
int ret = -EINVAL;
-   int i;
 
if (!drm_core_check_feature(dev, DRIVER_MODESET))
return -EINVAL;
@@ -3395,11 +3407,7 @@ int drm_mode_obj_set_property_ioctl(struct drm_device 
*dev, void *data,
if (!arg_obj->properties)
goto out;
 
-   for (i = 0; i < arg_obj->properties->count; i++)
-   if (arg_obj->properties->ids[i] == arg->prop_id)
-   break;
-
-   if (i == arg_obj->properties->count)
+   if (!object_has_prop(arg_obj, arg->prop_id))
goto out;
 
prop_obj = drm_mode_object_find(dev, arg->prop_id,
-- 
1.7.8.6

___
Intel-gfx mailing list
Intel-gfx@lists.freedesktop.org
http://lists.freedesktop.org/mailman/listinfo/intel-gfx


[Intel-gfx] [PATCH 11/81] drm: Export mode<->umode conversion functions

2012-12-12 Thread ville . syrjala
From: Ville Syrjälä 

Export drm_crtc_convert_to_umode() and drm_crtc_convert_umode().

Signed-off-by: Ville Syrjälä 
---
 drivers/gpu/drm/drm_crtc.c |   10 ++
 include/drm/drm_crtc.h |4 
 2 files changed, 10 insertions(+), 4 deletions(-)

diff --git a/drivers/gpu/drm/drm_crtc.c b/drivers/gpu/drm/drm_crtc.c
index 0a9a7cb..3709f8c 100644
--- a/drivers/gpu/drm/drm_crtc.c
+++ b/drivers/gpu/drm/drm_crtc.c
@@ -1119,8 +1119,8 @@ EXPORT_SYMBOL(drm_mode_config_cleanup);
  * Convert a drm_display_mode into a drm_mode_modeinfo structure to return to
  * the user.
  */
-static void drm_crtc_convert_to_umode(struct drm_mode_modeinfo *out,
- const struct drm_display_mode *in)
+void drm_crtc_convert_to_umode(struct drm_mode_modeinfo *out,
+  const struct drm_display_mode *in)
 {
WARN(in->hdisplay > USHRT_MAX || in->hsync_start > USHRT_MAX ||
 in->hsync_end > USHRT_MAX || in->htotal > USHRT_MAX ||
@@ -1146,6 +1146,7 @@ static void drm_crtc_convert_to_umode(struct 
drm_mode_modeinfo *out,
strncpy(out->name, in->name, DRM_DISPLAY_MODE_LEN);
out->name[DRM_DISPLAY_MODE_LEN-1] = 0;
 }
+EXPORT_SYMBOL(drm_crtc_convert_to_umode);
 
 /**
  * drm_crtc_convert_to_umode - convert a modeinfo into a drm_display_mode
@@ -1161,8 +1162,8 @@ static void drm_crtc_convert_to_umode(struct 
drm_mode_modeinfo *out,
  * RETURNS:
  * Zero on success, errno on failure.
  */
-static int drm_crtc_convert_umode(struct drm_display_mode *out,
- const struct drm_mode_modeinfo *in)
+int drm_crtc_convert_umode(struct drm_display_mode *out,
+  const struct drm_mode_modeinfo *in)
 {
if (in->clock > INT_MAX || in->vrefresh > INT_MAX)
return -ERANGE;
@@ -1186,6 +1187,7 @@ static int drm_crtc_convert_umode(struct drm_display_mode 
*out,
 
return 0;
 }
+EXPORT_SYMBOL(drm_crtc_convert_umode);
 
 /**
  * drm_mode_getresources - get graphics configuration
diff --git a/include/drm/drm_crtc.h b/include/drm/drm_crtc.h
index 28a972a..23f2f37 100644
--- a/include/drm/drm_crtc.h
+++ b/include/drm/drm_crtc.h
@@ -1090,6 +1090,10 @@ extern int drm_format_num_planes(uint32_t format);
 extern int drm_format_plane_cpp(uint32_t format, int plane);
 extern int drm_format_horz_chroma_subsampling(uint32_t format);
 extern int drm_format_vert_chroma_subsampling(uint32_t format);
+extern void drm_crtc_convert_to_umode(struct drm_mode_modeinfo *out,
+ const struct drm_display_mode *in);
+extern int drm_crtc_convert_umode(struct drm_display_mode *out,
+ const struct drm_mode_modeinfo *in);
 
 /**
  * drm_region - two dimensional region
-- 
1.7.8.6

___
Intel-gfx mailing list
Intel-gfx@lists.freedesktop.org
http://lists.freedesktop.org/mailman/listinfo/intel-gfx


[Intel-gfx] [PATCH 12/81] drm: Make blobs resizeable

2012-12-12 Thread ville . syrjala
From: Ville Syrjälä 

When first allocated blobs can be given a maximum size for which memory
is allocated. Later the data inside the blob can be replaced, assuming
that the maximum size is not exceeded.

Signed-off-by: Ville Syrjälä 
---
 drivers/gpu/drm/drm_crtc.c |   45 ++-
 include/drm/drm_crtc.h |8 ++-
 2 files changed, 46 insertions(+), 7 deletions(-)

diff --git a/drivers/gpu/drm/drm_crtc.c b/drivers/gpu/drm/drm_crtc.c
index 3709f8c..aeda9f4 100644
--- a/drivers/gpu/drm/drm_crtc.c
+++ b/drivers/gpu/drm/drm_crtc.c
@@ -2926,6 +2926,9 @@ void drm_property_destroy(struct drm_device *dev, struct 
drm_property *property)
 {
struct drm_property_enum *prop_enum, *pt;
 
+   if (!property)
+   return;
+
list_for_each_entry_safe(prop_enum, pt, &property->enum_blob_list, 
head) {
list_del(&prop_enum->head);
kfree(prop_enum);
@@ -3115,16 +3118,24 @@ done:
return ret;
 }
 
-struct drm_property_blob *drm_property_create_blob(struct drm_device *dev, int 
length,
-  void *data)
+struct drm_property_blob *drm_property_create_blob(struct drm_device *dev,
+  unsigned int length,
+  unsigned int max_length,
+  const void *data)
 {
struct drm_property_blob *blob;
int ret;
 
-   if (!length || !data)
+   if (!!length != !!data)
return NULL;
 
-   blob = kzalloc(sizeof(struct drm_property_blob)+length, GFP_KERNEL);
+   if (max_length < length)
+   max_length = length;
+
+   if (max_length == 0)
+   return NULL;
+
+   blob = kzalloc(sizeof(struct drm_property_blob)+max_length, GFP_KERNEL);
if (!blob)
return NULL;
 
@@ -3134,18 +3145,40 @@ struct drm_property_blob 
*drm_property_create_blob(struct drm_device *dev, int l
return NULL;
}
 
+   blob->max_length = max_length;
blob->length = length;
 
-   memcpy(blob->data, data, length);
+   if (length)
+   memcpy(blob->data, data, length);
 
list_add_tail(&blob->head, &dev->mode_config.property_blob_list);
return blob;
 }
 EXPORT_SYMBOL(drm_property_create_blob);
 
+int drm_property_blob_replace_data(struct drm_property_blob *blob,
+  unsigned int length, const void *data)
+{
+   if (!!length != !!data)
+   return -EINVAL;
+
+   if (length > blob->max_length)
+   return -ENOSPC;
+
+   blob->length = length;
+   if (length)
+   memcpy(blob->data, data, length);
+
+   return 0;
+}
+EXPORT_SYMBOL(drm_property_blob_replace_data);
+
 void drm_property_destroy_blob(struct drm_device *dev,
   struct drm_property_blob *blob)
 {
+   if (!blob)
+   return;
+
drm_mode_object_put(dev, &blob->base);
list_del(&blob->head);
kfree(blob);
@@ -3204,7 +3237,7 @@ int drm_mode_connector_update_edid_property(struct 
drm_connector *connector,
 
size = EDID_LENGTH * (1 + edid->extensions);
connector->edid_blob_ptr = drm_property_create_blob(connector->dev,
-   size, edid);
+   size, 0, edid);
if (!connector->edid_blob_ptr)
return -EINVAL;
 
diff --git a/include/drm/drm_crtc.h b/include/drm/drm_crtc.h
index 23f2f37..5b8b1b7 100644
--- a/include/drm/drm_crtc.h
+++ b/include/drm/drm_crtc.h
@@ -276,6 +276,7 @@ struct drm_property_blob {
struct drm_mode_object base;
struct list_head head;
unsigned int length;
+   unsigned int max_length;
unsigned char data[];
 };
 
@@ -972,7 +973,12 @@ struct drm_property *drm_property_create_range(struct 
drm_device *dev, int flags
 uint64_t min, uint64_t max);
 extern void drm_property_destroy(struct drm_device *dev, struct drm_property 
*property);
 extern struct drm_property_blob *drm_property_create_blob(struct drm_device 
*dev,
- int length, void 
*data);
+ unsigned int level,
+ unsigned int 
max_length,
+ const void *data);
+extern int drm_property_blob_replace_data(struct drm_property_blob *blob,
+ unsigned int length,
+ const void *data);
 extern void drm_property_destroy_blob(struct drm_device *dev,
  struct drm_property_blob *blob);
 extern int drm_property_add_enum(stru

[Intel-gfx] [PATCH 13/81] drm: Add drm_flip helper

2012-12-12 Thread ville . syrjala
From: Ville Syrjälä 

The drm_flip mechanism can be used to implement robust page flipping
support, and also to synchronize the flips on multiple hardware
scanout engines (eg. CRTCs and overlays).

Signed-off-by: Ville Syrjälä 
---
 drivers/gpu/drm/Makefile   |2 +-
 drivers/gpu/drm/drm_flip.c |  376 
 include/drm/drm_flip.h |  244 
 3 files changed, 621 insertions(+), 1 deletions(-)
 create mode 100644 drivers/gpu/drm/drm_flip.c
 create mode 100644 include/drm/drm_flip.h

diff --git a/drivers/gpu/drm/Makefile b/drivers/gpu/drm/Makefile
index 6f58c81..f2965de 100644
--- a/drivers/gpu/drm/Makefile
+++ b/drivers/gpu/drm/Makefile
@@ -12,7 +12,7 @@ drm-y   :=drm_auth.o drm_buffer.o drm_bufs.o 
drm_cache.o \
drm_platform.o drm_sysfs.o drm_hashtab.o drm_mm.o \
drm_crtc.o drm_modes.o drm_edid.o \
drm_info.o drm_debugfs.o drm_encoder_slave.o \
-   drm_trace_points.o drm_global.o drm_prime.o
+   drm_trace_points.o drm_global.o drm_prime.o drm_flip.o
 
 drm-$(CONFIG_COMPAT) += drm_ioc32.o
 drm-$(CONFIG_DRM_GEM_CMA_HELPER) += drm_gem_cma_helper.o
diff --git a/drivers/gpu/drm/drm_flip.c b/drivers/gpu/drm/drm_flip.c
new file mode 100644
index 000..6ccc3f8
--- /dev/null
+++ b/drivers/gpu/drm/drm_flip.c
@@ -0,0 +1,376 @@
+/*
+ * Copyright (C) 2012 Intel Corporation
+ *
+ * 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
+ * THE AUTHORS OR COPYRIGHT HOLDERS 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.
+ *
+ * Authors:
+ * Ville Syrjälä 
+ */
+
+#include 
+
+static void drm_flip_driver_cleanup(struct work_struct *work)
+{
+   struct drm_flip *flip, *next;
+   struct drm_flip_driver *driver =
+   container_of(work, struct drm_flip_driver, cleanup_work);
+   LIST_HEAD(list);
+
+   spin_lock_irq(&driver->lock);
+
+   list_cut_position(&list,
+ &driver->cleanup_list,
+ driver->cleanup_list.prev);
+
+   spin_unlock_irq(&driver->lock);
+
+   if (list_empty(&list))
+   return;
+
+   list_for_each_entry_safe(flip, next, &list, list) {
+   struct drm_flip_helper *helper = flip->helper;
+
+   WARN_ON(!flip->finished);
+
+   helper->funcs->cleanup(flip);
+   }
+}
+
+static void drm_flip_driver_finish(struct work_struct *work)
+{
+   struct drm_flip *flip, *next;
+   struct drm_flip_driver *driver =
+   container_of(work, struct drm_flip_driver, finish_work);
+   LIST_HEAD(list);
+   bool need_cleanup = false;
+
+   spin_lock_irq(&driver->lock);
+
+   list_cut_position(&list,
+ &driver->finish_list,
+ driver->finish_list.prev);
+
+   spin_unlock_irq(&driver->lock);
+
+   if (list_empty(&list))
+   return;
+
+   list_for_each_entry_safe(flip, next, &list, list) {
+   struct drm_flip_helper *helper = flip->helper;
+
+   helper->funcs->finish(flip);
+
+   spin_lock_irq(&driver->lock);
+
+   flip->finished = true;
+
+   /*
+* It's possible that drm_flip_set_scanout() was called after we
+* pulled this flip from finish_list, in which case the flip
+* could be in need of cleanup, but not on cleanup_list.
+*/
+   if (flip == helper->scanout_flip) {
+   list_del_init(&flip->list);
+   } else {
+   need_cleanup = true;
+   list_move_tail(&flip->list, &driver->cleanup_list);
+   }
+
+   spin_unlock_irq(&driver->lock);
+   }
+
+   if (need_cleanup)
+   queue_work(driver->wq, &driver->cleanup_work);
+}
+
+static bool drm_flip_set_scanout(struct drm_flip_helper *helper,
+struct drm_fl

[Intel-gfx] [PATCH 15/81] drm: Add the atomic modeset ioctl

2012-12-12 Thread ville . syrjala
From: Ville Syrjälä 

This new ioctl can be used to update an arbitrary set of object
properties in one operation.

The ioctl simply takes a list of object IDs and property IDs and their
values. For setting values of blob properties, the property value
indicates the length of the data, and the actual data is passed via
another blob pointer.

Three flags are currently supported to alter the behaviour of the ioctl:
- DRM_MODE_ATOMIC_TEST_ONLY indicates that the new state chould only be
  checked for validity, but not hardware state is to be modified.
- DRM_MODE_ATOMIC_EVENT requests that asynchronous completion events be
  sent back to user space. A new event type is added for this purpose.
- DRM_MODE_ATOMIC_NONBLOCK indicates that the operation must be
  completed asynchronously without blocking the the caller for
  significant amounts of time.

Internally the driver must implement the functions pointers in struct
drm_atomic_funcs to support the new ioctl.

Signed-off-by: Ville Syrjälä 
---
 drivers/gpu/drm/drm_crtc.c  |  146 +++
 drivers/gpu/drm/drm_drv.c   |1 +
 include/drm/drmP.h  |8 +++
 include/drm/drm_crtc.h  |   13 
 include/uapi/drm/drm.h  |   12 
 include/uapi/drm/drm_mode.h |   17 +
 6 files changed, 197 insertions(+), 0 deletions(-)

diff --git a/drivers/gpu/drm/drm_crtc.c b/drivers/gpu/drm/drm_crtc.c
index aeda9f4..897ff46 100644
--- a/drivers/gpu/drm/drm_crtc.c
+++ b/drivers/gpu/drm/drm_crtc.c
@@ -4245,3 +4245,149 @@ int drm_calc_vscale(struct drm_region *src, struct 
drm_region *dst,
return vscale;
 }
 EXPORT_SYMBOL(drm_calc_vscale);
+
+int drm_mode_atomic_ioctl(struct drm_device *dev,
+ void *data, struct drm_file *file_priv)
+{
+   struct drm_mode_atomic *arg = data;
+   uint32_t __user *objs_ptr = (uint32_t __user *)(unsigned 
long)(arg->objs_ptr);
+   uint32_t __user *count_props_ptr = (uint32_t __user *)(unsigned 
long)(arg->count_props_ptr);
+   uint32_t __user *props_ptr = (uint32_t __user *)(unsigned 
long)(arg->props_ptr);
+   uint64_t __user *prop_values_ptr = (uint64_t __user *)(unsigned 
long)(arg->prop_values_ptr);
+   uint64_t __user *blob_values_ptr = (uint64_t __user *)(unsigned 
long)(arg->blob_values_ptr);
+   unsigned int copied_objs = 0;
+   unsigned int copied_props = 0;
+   unsigned int copied_blobs = 0;
+   void *state;
+   int ret = 0;
+   unsigned int i, j;
+
+   if (!dev->driver->atomic_funcs ||
+   !dev->driver->atomic_funcs->begin ||
+   !dev->driver->atomic_funcs->set ||
+   !dev->driver->atomic_funcs->check ||
+   !dev->driver->atomic_funcs->commit ||
+   !dev->driver->atomic_funcs->end)
+   return -ENOSYS;
+
+   if (arg->flags & ~(DRM_MODE_ATOMIC_TEST_ONLY | DRM_MODE_ATOMIC_EVENT | 
DRM_MODE_ATOMIC_NONBLOCK))
+   return -EINVAL;
+
+   /* can't test and expect an event at the same time. */
+   if (arg->flags & DRM_MODE_ATOMIC_TEST_ONLY && arg->flags & 
DRM_MODE_ATOMIC_EVENT)
+   return -EINVAL;
+
+   mutex_lock(&dev->mode_config.mutex);
+
+   state = dev->driver->atomic_funcs->begin(dev, file_priv, arg->flags, 
arg->user_data);
+   if (IS_ERR(state)) {
+   ret = PTR_ERR(state);
+   goto unlock;
+   }
+
+   for (i = 0; i < arg->count_objs; i++) {
+   uint32_t obj_id, count_props;
+   struct drm_mode_object *obj;
+
+   if (get_user(obj_id, objs_ptr + copied_objs)) {
+   ret = -EFAULT;
+   goto out;
+   }
+
+   obj = drm_mode_object_find(dev, obj_id, DRM_MODE_OBJECT_ANY);
+   if (!obj || !obj->properties) {
+   ret = -ENOENT;
+   goto out;
+   }
+
+   if (get_user(count_props, count_props_ptr + copied_objs)) {
+   ret = -EFAULT;
+   goto out;
+   }
+
+   copied_objs++;
+
+   for (j = 0; j < count_props; j++) {
+   uint32_t prop_id;
+   uint64_t prop_value;
+   struct drm_mode_object *prop_obj;
+   struct drm_property *prop;
+   void *blob_data = NULL;
+
+   if (get_user(prop_id, props_ptr + copied_props)) {
+   ret = -EFAULT;
+   goto out;
+   }
+
+   if (!object_has_prop(obj, prop_id)) {
+   ret = -EINVAL;
+   goto out;
+   }
+
+   prop_obj = drm_mode_object_find(dev, prop_id, 
DRM_MODE_OBJECT_PROPERTY);
+   if (!prop_obj) {
+   ret = -ENOENT;
+   goto

[Intel-gfx] [PATCH 14/81] drm: Add mode_blob and connector_ids_blob to drm_crtc

2012-12-12 Thread ville . syrjala
From: Ville Syrjälä 

These will be ued by standard properties MODE and CONNECTOR_IDS.

Signed-off-by: Ville Syrjälä 
---
 include/drm/drm_crtc.h |3 +++
 1 files changed, 3 insertions(+), 0 deletions(-)

diff --git a/include/drm/drm_crtc.h b/include/drm/drm_crtc.h
index 5b8b1b7..d05d302 100644
--- a/include/drm/drm_crtc.h
+++ b/include/drm/drm_crtc.h
@@ -423,6 +423,9 @@ struct drm_crtc {
void *helper_private;
 
struct drm_object_properties properties;
+
+   struct drm_property_blob *mode_blob;
+   struct drm_property_blob *connector_ids_blob;
 };
 
 
-- 
1.7.8.6

___
Intel-gfx mailing list
Intel-gfx@lists.freedesktop.org
http://lists.freedesktop.org/mailman/listinfo/intel-gfx


[Intel-gfx] [PATCH 16/81] drm/i915: Use drm_format_plane_cpp() rather than bits_per_pixel/8

2012-12-12 Thread ville . syrjala
From: Ville Syrjälä 

bits_per_pixel may not be populated for all pixel formats, so
let's just use drm_format_plane_cpp().

Signed-off-by: Ville Syrjälä 
---
 drivers/gpu/drm/i915/intel_display.c |   12 ++--
 1 files changed, 6 insertions(+), 6 deletions(-)

diff --git a/drivers/gpu/drm/i915/intel_display.c 
b/drivers/gpu/drm/i915/intel_display.c
index 21dd4db..a4e71e5 100644
--- a/drivers/gpu/drm/i915/intel_display.c
+++ b/drivers/gpu/drm/i915/intel_display.c
@@ -1991,6 +1991,7 @@ static int i9xx_update_plane(struct drm_crtc *crtc, 
struct drm_framebuffer *fb,
unsigned long linear_offset;
u32 dspcntr;
u32 reg;
+   unsigned int cpp = drm_format_plane_cpp(fb->pixel_format, 0);
 
switch (plane) {
case 0:
@@ -2049,13 +2050,12 @@ static int i9xx_update_plane(struct drm_crtc *crtc, 
struct drm_framebuffer *fb,
 
I915_WRITE(reg, dspcntr);
 
-   linear_offset = y * fb->pitches[0] + x * (fb->bits_per_pixel / 8);
+   linear_offset = y * fb->pitches[0] + x * cpp;
 
if (INTEL_INFO(dev)->gen >= 4) {
intel_crtc->dspaddr_offset =
intel_gen4_compute_offset_xtiled(&x, &y,
-fb->bits_per_pixel / 8,
-fb->pitches[0]);
+cpp, fb->pitches[0]);
linear_offset -= intel_crtc->dspaddr_offset;
} else {
intel_crtc->dspaddr_offset = linear_offset;
@@ -2088,6 +2088,7 @@ static int ironlake_update_plane(struct drm_crtc *crtc,
unsigned long linear_offset;
u32 dspcntr;
u32 reg;
+   unsigned int cpp = drm_format_plane_cpp(fb->pixel_format, 0);
 
switch (plane) {
case 0:
@@ -2144,11 +2145,10 @@ static int ironlake_update_plane(struct drm_crtc *crtc,
 
I915_WRITE(reg, dspcntr);
 
-   linear_offset = y * fb->pitches[0] + x * (fb->bits_per_pixel / 8);
+   linear_offset = y * fb->pitches[0] + x * cpp;
intel_crtc->dspaddr_offset =
intel_gen4_compute_offset_xtiled(&x, &y,
-fb->bits_per_pixel / 8,
-fb->pitches[0]);
+cpp, fb->pitches[0]);
linear_offset -= intel_crtc->dspaddr_offset;
 
DRM_DEBUG_KMS("Writing base %08X %08lX %d %d %d\n",
-- 
1.7.8.6

___
Intel-gfx mailing list
Intel-gfx@lists.freedesktop.org
http://lists.freedesktop.org/mailman/listinfo/intel-gfx


[Intel-gfx] [PATCH 17/81] drm/i915: Implement proper clipping for video sprites

2012-12-12 Thread ville . syrjala
From: Ville Syrjälä 

Properly clip the source when the destination gets clipped
by the pipe dimensions.

Sadly the video sprite hardware is rather limited so it can't do proper
sub-pixel postitioning. Resort to a best effort approach, where the
source coordinates are rounded to the nearest (macro)pixel boundary.

Also do some additional checking against various hardware limits.

Signed-off-by: Ville Syrjälä 
---
 drivers/gpu/drm/i915/intel_sprite.c |  171 +++
 1 files changed, 111 insertions(+), 60 deletions(-)

diff --git a/drivers/gpu/drm/i915/intel_sprite.c 
b/drivers/gpu/drm/i915/intel_sprite.c
index 827dcd4..77ca0da 100644
--- a/drivers/gpu/drm/i915/intel_sprite.c
+++ b/drivers/gpu/drm/i915/intel_sprite.c
@@ -120,11 +120,10 @@ ivb_update_plane(struct drm_plane *plane, struct 
drm_framebuffer *fb,
I915_WRITE(SPRSTRIDE(pipe), fb->pitches[0]);
I915_WRITE(SPRPOS(pipe), (crtc_y << 16) | crtc_x);
 
-   linear_offset = y * fb->pitches[0] + x * (fb->bits_per_pixel / 8);
+   linear_offset = y * fb->pitches[0] + x * pixel_size;
sprsurf_offset =
intel_gen4_compute_offset_xtiled(&x, &y,
-fb->bits_per_pixel / 8,
-fb->pitches[0]);
+pixel_size, fb->pitches[0]);
linear_offset -= sprsurf_offset;
 
/* HSW consolidates SPRTILEOFF and SPRLINOFF into a single SPROFFSET
@@ -286,11 +285,10 @@ ilk_update_plane(struct drm_plane *plane, struct 
drm_framebuffer *fb,
I915_WRITE(DVSSTRIDE(pipe), fb->pitches[0]);
I915_WRITE(DVSPOS(pipe), (crtc_y << 16) | crtc_x);
 
-   linear_offset = y * fb->pitches[0] + x * (fb->bits_per_pixel / 8);
+   linear_offset = y * fb->pitches[0] + x * pixel_size;
dvssurf_offset =
intel_gen4_compute_offset_xtiled(&x, &y,
-fb->bits_per_pixel / 8,
-fb->pitches[0]);
+pixel_size, fb->pitches[0]);
linear_offset -= dvssurf_offset;
 
if (obj->tiling_mode != I915_TILING_NONE)
@@ -409,6 +407,20 @@ ilk_get_colorkey(struct drm_plane *plane, struct 
drm_intel_sprite_colorkey *key)
key->flags = I915_SET_COLORKEY_NONE;
 }
 
+static bool
+format_is_yuv(uint32_t format)
+{
+   switch (format) {
+   case DRM_FORMAT_YUYV:
+   case DRM_FORMAT_UYVY:
+   case DRM_FORMAT_VYUY:
+   case DRM_FORMAT_YVYU:
+   return true;
+   default:
+   return false;
+   }
+}
+
 static int
 intel_update_plane(struct drm_plane *plane, struct drm_crtc *crtc,
   struct drm_framebuffer *fb, int crtc_x, int crtc_y,
@@ -420,35 +432,68 @@ intel_update_plane(struct drm_plane *plane, struct 
drm_crtc *crtc,
struct drm_i915_private *dev_priv = dev->dev_private;
struct intel_crtc *intel_crtc = to_intel_crtc(crtc);
struct intel_plane *intel_plane = to_intel_plane(plane);
-   struct intel_framebuffer *intel_fb;
-   struct drm_i915_gem_object *obj, *old_obj;
+   struct intel_framebuffer *intel_fb = to_intel_framebuffer(fb);
+   struct drm_i915_gem_object *obj = intel_fb->obj;
+   struct drm_i915_gem_object *old_obj = intel_plane->obj;
int pipe = intel_plane->pipe;
enum transcoder cpu_transcoder = intel_pipe_to_cpu_transcoder(dev_priv,
  pipe);
int ret = 0;
-   int x = src_x >> 16, y = src_y >> 16;
int primary_w = crtc->mode.hdisplay, primary_h = crtc->mode.vdisplay;
bool disable_primary = false;
-
-   intel_fb = to_intel_framebuffer(fb);
-   obj = intel_fb->obj;
-
-   old_obj = intel_plane->obj;
-
-   src_w = src_w >> 16;
-   src_h = src_h >> 16;
-
-   /* Pipe must be running... */
-   if (!(I915_READ(PIPECONF(cpu_transcoder)) & PIPECONF_ENABLE))
-   return -EINVAL;
-
-   if (crtc_x >= primary_w || crtc_y >= primary_h)
-   return -EINVAL;
+   bool visible;
+   int hscale, vscale;
+   int cpp = drm_format_plane_cpp(fb->pixel_format, 0);
+   struct drm_region src = {
+   .x1 = src_x,
+   .x2 = src_x + src_w,
+   .y1 = src_y,
+   .y2 = src_y + src_h,
+   };
+   struct drm_region dst = {
+   .x1 = crtc_x,
+   .x2 = crtc_x + crtc_w,
+   .y1 = crtc_y,
+   .y2 = crtc_y + crtc_h,
+   };
+   const struct drm_region clip = {
+   .x2 = crtc->mode.hdisplay,
+   .y2 = crtc->mode.vdisplay,
+   };
 
/* Don't modify another pipe's plane */
if (intel_plane->pipe != intel_crtc->pipe)
return -EINVAL;
 
+   if (fb->width < 3 || fb->height < 3 || fb->pitches[

[Intel-gfx] [PATCH 18/81] drm/i915: Implement restore_fbdev_mode hook

2012-12-12 Thread ville . syrjala
From: Ville Syrjälä 

Convert intel_fb_restore_mode to be useable as the
drm_fb_helper.restore_fbdev_mode hook. This will cause all planes to be
disabled when swithing back to fbcon.

Signed-off-by: Ville Syrjälä 
---
 drivers/gpu/drm/i915/i915_dma.c  |2 +-
 drivers/gpu/drm/i915/intel_drv.h |2 +-
 drivers/gpu/drm/i915/intel_fb.c  |   14 ++
 3 files changed, 12 insertions(+), 6 deletions(-)

diff --git a/drivers/gpu/drm/i915/i915_dma.c b/drivers/gpu/drm/i915/i915_dma.c
index 6fec5d4..392c9a1 100644
--- a/drivers/gpu/drm/i915/i915_dma.c
+++ b/drivers/gpu/drm/i915/i915_dma.c
@@ -1790,7 +1790,7 @@ void i915_driver_lastclose(struct drm_device * dev)
return;
 
if (drm_core_check_feature(dev, DRIVER_MODESET)) {
-   intel_fb_restore_mode(dev);
+   intel_fb_restore_mode(&dev_priv->fbdev->helper);
vga_switcheroo_process_delayed_switch();
return;
}
diff --git a/drivers/gpu/drm/i915/intel_drv.h b/drivers/gpu/drm/i915/intel_drv.h
index 6724be8..16770cb 100644
--- a/drivers/gpu/drm/i915/intel_drv.h
+++ b/drivers/gpu/drm/i915/intel_drv.h
@@ -606,7 +606,7 @@ extern int intel_overlay_attrs(struct drm_device *dev, void 
*data,
   struct drm_file *file_priv);
 
 extern void intel_fb_output_poll_changed(struct drm_device *dev);
-extern void intel_fb_restore_mode(struct drm_device *dev);
+extern int intel_fb_restore_mode(struct drm_fb_helper *helper);
 
 extern void assert_pipe(struct drm_i915_private *dev_priv, enum pipe pipe,
bool state);
diff --git a/drivers/gpu/drm/i915/intel_fb.c b/drivers/gpu/drm/i915/intel_fb.c
index b7773e5..3ab7967 100644
--- a/drivers/gpu/drm/i915/intel_fb.c
+++ b/drivers/gpu/drm/i915/intel_fb.c
@@ -195,6 +195,7 @@ static struct drm_fb_helper_funcs intel_fb_helper_funcs = {
.gamma_set = intel_crtc_fb_gamma_set,
.gamma_get = intel_crtc_fb_gamma_get,
.fb_probe = intel_fb_find_or_create_single,
+   .restore_fbdev_mode = intel_fb_restore_mode,
 };
 
 static void intel_fbdev_destroy(struct drm_device *dev,
@@ -275,22 +276,27 @@ void intel_fb_output_poll_changed(struct drm_device *dev)
drm_fb_helper_hotplug_event(&dev_priv->fbdev->helper);
 }
 
-void intel_fb_restore_mode(struct drm_device *dev)
+int intel_fb_restore_mode(struct drm_fb_helper *helper)
 {
+   struct drm_device *dev = helper->dev;
int ret;
-   drm_i915_private_t *dev_priv = dev->dev_private;
struct drm_mode_config *config = &dev->mode_config;
struct drm_plane *plane;
 
mutex_lock(&dev->mode_config.mutex);
 
-   ret = drm_fb_helper_restore_fbdev_mode(&dev_priv->fbdev->helper);
-   if (ret)
+   ret = drm_fb_helper_restore_fbdev_mode(helper);
+   if (ret) {
DRM_DEBUG("failed to restore crtc mode\n");
+   goto out;
+   }
 
/* Be sure to shut off any planes that may be active */
list_for_each_entry(plane, &config->plane_list, head)
plane->funcs->disable_plane(plane);
 
+out:
mutex_unlock(&dev->mode_config.mutex);
+
+   return ret;
 }
-- 
1.7.8.6

___
Intel-gfx mailing list
Intel-gfx@lists.freedesktop.org
http://lists.freedesktop.org/mailman/listinfo/intel-gfx


[Intel-gfx] [PATCH 19/81] drm/i915: Split clipping and checking from update_plane hook

2012-12-12 Thread ville . syrjala
From: Ville Syrjälä 

Split the update_plane() codepath into two separate steps. The first
step checkis and clips the plane, and the second step actually commits
the changes to the hardware. This allows the atomic modesetting code
to perform all checks before clobering hardware state.

The update_plane() hook is reduced to a thin wrapper calling both check
and commit functions.

Buffer (un)pinning is still being performed in the commit step. This
needs to be changed as well, so that the atomic modesetting code can
try to pin all new buffers before touching the hardware.

Signed-off-by: Ville Syrjälä 
---
 drivers/gpu/drm/i915/intel_drv.h|   15 +-
 drivers/gpu/drm/i915/intel_sprite.c |  411 ++-
 2 files changed, 266 insertions(+), 160 deletions(-)

diff --git a/drivers/gpu/drm/i915/intel_drv.h b/drivers/gpu/drm/i915/intel_drv.h
index 16770cb..0d7c2fc 100644
--- a/drivers/gpu/drm/i915/intel_drv.h
+++ b/drivers/gpu/drm/i915/intel_drv.h
@@ -231,6 +231,15 @@ struct intel_crtc {
uint32_t ddi_pll_sel;
 };
 
+struct intel_plane_coords {
+   /* disabled or fully clipped? */
+   bool visible;
+   /* coordinates clipped against pipe dimensions */
+   int32_t crtc_x, crtc_y;
+   uint32_t crtc_w, crtc_h;
+   uint32_t src_x, src_y, src_w, src_h;
+};
+
 struct intel_plane {
struct drm_plane base;
enum pipe pipe;
@@ -240,11 +249,7 @@ struct intel_plane {
u32 lut_r[1024], lut_g[1024], lut_b[1024];
void (*update_plane)(struct drm_plane *plane,
 struct drm_framebuffer *fb,
-struct drm_i915_gem_object *obj,
-int crtc_x, int crtc_y,
-unsigned int crtc_w, unsigned int crtc_h,
-uint32_t x, uint32_t y,
-uint32_t src_w, uint32_t src_h);
+const struct intel_plane_coords *clip);
void (*disable_plane)(struct drm_plane *plane);
int (*update_colorkey)(struct drm_plane *plane,
   struct drm_intel_sprite_colorkey *key);
diff --git a/drivers/gpu/drm/i915/intel_sprite.c 
b/drivers/gpu/drm/i915/intel_sprite.c
index 77ca0da..d64cefd 100644
--- a/drivers/gpu/drm/i915/intel_sprite.c
+++ b/drivers/gpu/drm/i915/intel_sprite.c
@@ -36,16 +36,189 @@
 #include 
 #include "i915_drv.h"
 
+static bool
+format_is_yuv(uint32_t format)
+{
+   switch (format) {
+   case DRM_FORMAT_YUYV:
+   case DRM_FORMAT_UYVY:
+   case DRM_FORMAT_VYUY:
+   case DRM_FORMAT_YVYU:
+   return true;
+   default:
+   return false;
+   }
+}
+
+static void intel_clip_plane(const struct drm_plane *plane,
+const struct drm_crtc *crtc,
+const struct drm_framebuffer *fb,
+struct intel_plane_coords *coords)
+{
+   const struct intel_plane *intel_plane = to_intel_plane(plane);
+   const struct drm_display_mode *mode = &crtc->mode;
+   int hscale, vscale;
+   struct drm_region src = {
+   .x1 = coords->src_x,
+   .x2 = coords->src_x + coords->src_w,
+   .y1 = coords->src_y,
+   .y2 = coords->src_y + coords->src_h,
+   };
+   struct drm_region dst = {
+   .x1 = coords->crtc_x,
+   .x2 = coords->crtc_x + coords->crtc_w,
+   .y1 = coords->crtc_y,
+   .y2 = coords->crtc_y + coords->crtc_h,
+   };
+   const struct drm_region clip = {
+   .x2 = mode->hdisplay,
+   .y2 = mode->vdisplay,
+   };
+
+   hscale = drm_calc_hscale(&src, &dst, 1, intel_plane->max_downscale << 
16);
+   vscale = drm_calc_vscale(&src, &dst, 1, intel_plane->max_downscale << 
16);
+
+   coords->visible = drm_region_clip_scaled(&src, &dst, &clip, hscale, 
vscale);
+
+   coords->crtc_x = dst.x1;
+   coords->crtc_y = dst.y1;
+   coords->crtc_w = drm_region_width(&dst);
+   coords->crtc_h = drm_region_height(&dst);
+
+   /* HW doesn't seem to like smaller sprite, even when scaling */
+   /* FIXME return an error instead? */
+   if (coords->crtc_w < 3 || coords->crtc_h < 3)
+   coords->visible = false;
+
+   /*
+* Hardware doesn't handle subpixel coordinates.
+* Round to nearest (macro)pixel boundary.
+*/
+   if (format_is_yuv(fb->pixel_format)) {
+   coords->src_x = ((src.x1 + 0x1) >> 17) << 1;
+   coords->src_w = (((src.x2 + 0x1) >> 17) << 1) - 
coords->src_x;
+   } else {
+   coords->src_x = (src.x1 + 0x8000) >> 16;
+   coords->src_w = ((src.x2 + 0x8000) >> 16) - coords->src_x;
+   }
+   coords->src_y = (src.y1 + 0x8000) >> 16;
+   coords->src_h = ((src.y2 + 0x8000) >> 16) - coords->src_y;
+
+   /* Account for minimum source size when scaling */

[Intel-gfx] [PATCH 20/81] drm/i915: Factor out i9xx_compute_clocks() like ironlake_compute_clocks()

2012-12-12 Thread ville . syrjala
From: Ville Syrjälä 

Split the clock stuff out.

Signed-off-by: Ville Syrjälä 
---
 drivers/gpu/drm/i915/intel_display.c |  128 --
 1 files changed, 75 insertions(+), 53 deletions(-)

diff --git a/drivers/gpu/drm/i915/intel_display.c 
b/drivers/gpu/drm/i915/intel_display.c
index a4e71e5..0fa9c2a 100644
--- a/drivers/gpu/drm/i915/intel_display.c
+++ b/drivers/gpu/drm/i915/intel_display.c
@@ -4544,6 +4544,76 @@ static void intel_set_pipe_timings(struct intel_crtc 
*intel_crtc,
   ((mode->hdisplay - 1) << 16) | (mode->vdisplay - 1));
 }
 
+static bool i9xx_compute_clocks(struct drm_crtc *crtc,
+   struct drm_display_mode *adjusted_mode,
+   intel_clock_t *clock,
+   bool *has_reduced_clock,
+   intel_clock_t *reduced_clock,
+   int *refclk, int *num_connectors, bool *is_dp)
+{
+   struct drm_device *dev = crtc->dev;
+   struct drm_i915_private *dev_priv = dev->dev_private;
+   struct intel_encoder *encoder;
+   const intel_limit_t *limit;
+   bool ret, is_sdvo = false, is_tv = false, is_lvds = false;
+
+   *num_connectors = 0;
+
+   for_each_encoder_on_crtc(dev, crtc, encoder) {
+   switch (encoder->type) {
+   case INTEL_OUTPUT_LVDS:
+   is_lvds = true;
+   break;
+   case INTEL_OUTPUT_SDVO:
+   case INTEL_OUTPUT_HDMI:
+   is_sdvo = true;
+   if (encoder->needs_tv_clock)
+   is_tv = true;
+   break;
+   case INTEL_OUTPUT_TVOUT:
+   is_tv = true;
+   break;
+   case INTEL_OUTPUT_DISPLAYPORT:
+   *is_dp = true;
+   break;
+   }
+
+   (*num_connectors)++;
+   }
+
+   *refclk = i9xx_get_refclk(crtc, *num_connectors);
+
+   /*
+* Returns a set of divisors for the desired target clock with the given
+* refclk, or FALSE.  The returned values represent the clock equation:
+* reflck * (5 * (m1 + 2) + (m2 + 2)) / (n + 2) / p1 / p2.
+*/
+   limit = intel_limit(crtc, *refclk);
+   ret = limit->find_pll(limit, crtc, adjusted_mode->clock, *refclk, NULL,
+ clock);
+   if (!ret)
+   return false;
+
+   if (is_lvds && dev_priv->lvds_downclock_avail) {
+   /*
+* Ensure we match the reduced clock's P to the target clock.
+* If the clocks don't match, we can't switch the display clock
+* by using the FP0/FP1. In such case we will disable the LVDS
+* downclock feature.
+   */
+   *has_reduced_clock = limit->find_pll(limit, crtc,
+dev_priv->lvds_downclock,
+*refclk,
+clock,
+reduced_clock);
+   }
+
+   if (is_sdvo && is_tv)
+   i9xx_adjust_sdvo_tv_clock(adjusted_mode, clock);
+
+   return true;
+}
+
 static int i9xx_crtc_mode_set(struct drm_crtc *crtc,
  struct drm_display_mode *mode,
  struct drm_display_mode *adjusted_mode,
@@ -4558,44 +4628,13 @@ static int i9xx_crtc_mode_set(struct drm_crtc *crtc,
int refclk, num_connectors = 0;
intel_clock_t clock, reduced_clock;
u32 dspcntr, pipeconf;
-   bool ok, has_reduced_clock = false, is_sdvo = false;
-   bool is_lvds = false, is_tv = false, is_dp = false;
-   struct intel_encoder *encoder;
-   const intel_limit_t *limit;
+   bool ok, has_reduced_clock = false;
+   bool is_dp = false;
int ret;
 
-   for_each_encoder_on_crtc(dev, crtc, encoder) {
-   switch (encoder->type) {
-   case INTEL_OUTPUT_LVDS:
-   is_lvds = true;
-   break;
-   case INTEL_OUTPUT_SDVO:
-   case INTEL_OUTPUT_HDMI:
-   is_sdvo = true;
-   if (encoder->needs_tv_clock)
-   is_tv = true;
-   break;
-   case INTEL_OUTPUT_TVOUT:
-   is_tv = true;
-   break;
-   case INTEL_OUTPUT_DISPLAYPORT:
-   is_dp = true;
-   break;
-   }
-
-   num_connectors++;
-   }
-
-   refclk = i9xx_get_refclk(crtc, num_connectors);
-
-   /*
-* Returns a set of divisors for the desired target clock with the given
-* refclk, or FALSE.  The returned values represent the 

[Intel-gfx] [PATCH 21/81] drm/i915: Consitify adjusted_mode parameter

2012-12-12 Thread ville . syrjala
From: Ville Syrjälä 

i9xx_adjust_sdvo_tv_clock(), i9xx_compute_clocks() and
ironlake_compute_clocks() do not modify the adjusted_mode passed in, so
pass it as const.

Signed-off-by: Ville Syrjälä 
---
 drivers/gpu/drm/i915/intel_display.c |6 +++---
 1 files changed, 3 insertions(+), 3 deletions(-)

diff --git a/drivers/gpu/drm/i915/intel_display.c 
b/drivers/gpu/drm/i915/intel_display.c
index 0fa9c2a..2a2c664 100644
--- a/drivers/gpu/drm/i915/intel_display.c
+++ b/drivers/gpu/drm/i915/intel_display.c
@@ -4159,7 +4159,7 @@ static int i9xx_get_refclk(struct drm_crtc *crtc, int 
num_connectors)
return refclk;
 }
 
-static void i9xx_adjust_sdvo_tv_clock(struct drm_display_mode *adjusted_mode,
+static void i9xx_adjust_sdvo_tv_clock(const struct drm_display_mode 
*adjusted_mode,
  intel_clock_t *clock)
 {
/* SDVO TV has fixed PLL values depend on its clock range,
@@ -4545,7 +4545,7 @@ static void intel_set_pipe_timings(struct intel_crtc 
*intel_crtc,
 }
 
 static bool i9xx_compute_clocks(struct drm_crtc *crtc,
-   struct drm_display_mode *adjusted_mode,
+   const struct drm_display_mode *adjusted_mode,
intel_clock_t *clock,
bool *has_reduced_clock,
intel_clock_t *reduced_clock,
@@ -5135,7 +5135,7 @@ static void haswell_set_pipeconf(struct drm_crtc *crtc,
 }
 
 static bool ironlake_compute_clocks(struct drm_crtc *crtc,
-   struct drm_display_mode *adjusted_mode,
+   const struct drm_display_mode 
*adjusted_mode,
intel_clock_t *clock,
bool *has_reduced_clock,
intel_clock_t *reduced_clock)
-- 
1.7.8.6

___
Intel-gfx mailing list
Intel-gfx@lists.freedesktop.org
http://lists.freedesktop.org/mailman/listinfo/intel-gfx


[Intel-gfx] [PATCH 23/81] drm/i915: store cursor_handle in struct intel_crtc

2012-12-12 Thread ville . syrjala
From: Ander Conselvan de Oliveira 

This way it is possible to check if the cursor changed without doing
any setup. Will be useful for the atomic modesetting api.
---
 drivers/gpu/drm/i915/intel_display.c |1 +
 drivers/gpu/drm/i915/intel_drv.h |2 +-
 2 files changed, 2 insertions(+), 1 deletions(-)

diff --git a/drivers/gpu/drm/i915/intel_display.c 
b/drivers/gpu/drm/i915/intel_display.c
index dcd61fb..2a32cb0 100644
--- a/drivers/gpu/drm/i915/intel_display.c
+++ b/drivers/gpu/drm/i915/intel_display.c
@@ -6260,6 +6260,7 @@ static int intel_crtc_cursor_set(struct drm_crtc *crtc,
mutex_unlock(&dev->struct_mutex);
 
intel_crtc->cursor_addr = addr;
+   intel_crtc->cursor_handle = handle;
intel_crtc->cursor_bo = obj;
intel_crtc->cursor_width = width;
intel_crtc->cursor_height = height;
diff --git a/drivers/gpu/drm/i915/intel_drv.h b/drivers/gpu/drm/i915/intel_drv.h
index 0d7c2fc..e77202c 100644
--- a/drivers/gpu/drm/i915/intel_drv.h
+++ b/drivers/gpu/drm/i915/intel_drv.h
@@ -220,7 +220,7 @@ struct intel_crtc {
unsigned long dspaddr_offset;
 
struct drm_i915_gem_object *cursor_bo;
-   uint32_t cursor_addr;
+   uint32_t cursor_addr, cursor_handle;
int16_t cursor_x, cursor_y;
int16_t cursor_width, cursor_height;
bool cursor_visible;
-- 
1.7.8.6

___
Intel-gfx mailing list
Intel-gfx@lists.freedesktop.org
http://lists.freedesktop.org/mailman/listinfo/intel-gfx


[Intel-gfx] [PATCH 24/81] drm/i915: split cursor setting code into prepare/commit/unref parts

2012-12-12 Thread ville . syrjala
From: Ander Conselvan de Oliveira 

The atomic mode setting API will need to pin the cursor bo without
making changes to the current setup. Only on a later stage the cursor
registers can be written and the previous bo released.

This patch splits intel_crtc_cursor_set() into three parts: prepare,
commit and unref. intel_crtc_cursor_prepare() will pin the cursor bo
and return a gem object and the address to be written to the cursor
registers. intel_crtc_cursor_commit() takes that object and address
and actually changes the cursor. intel_crtc_cursor_unref() is used to
release the previous cursor bo.
---
 drivers/gpu/drm/i915/intel_display.c |   90 +
 1 files changed, 68 insertions(+), 22 deletions(-)

diff --git a/drivers/gpu/drm/i915/intel_display.c 
b/drivers/gpu/drm/i915/intel_display.c
index 2a32cb0..0f25a07 100644
--- a/drivers/gpu/drm/i915/intel_display.c
+++ b/drivers/gpu/drm/i915/intel_display.c
@@ -6173,10 +6173,12 @@ static void intel_crtc_update_cursor(struct drm_crtc 
*crtc,
}
 }
 
-static int intel_crtc_cursor_set(struct drm_crtc *crtc,
+static int intel_crtc_cursor_prepare(struct drm_crtc *crtc,
 struct drm_file *file,
 uint32_t handle,
-uint32_t width, uint32_t height)
+uint32_t width, uint32_t height,
+struct drm_i915_gem_object **obj_ret,
+uint32_t *addr_ret)
 {
struct drm_device *dev = crtc->dev;
struct drm_i915_private *dev_priv = dev->dev_private;
@@ -6188,10 +6190,9 @@ static int intel_crtc_cursor_set(struct drm_crtc *crtc,
/* if we want to turn off the cursor ignore width and height */
if (!handle) {
DRM_DEBUG_KMS("cursor off\n");
-   addr = 0;
-   obj = NULL;
-   mutex_lock(&dev->struct_mutex);
-   goto finish;
+   *addr_ret = 0;
+   *obj_ret = NULL;
+   return 0;
}
 
/* Currently we only support 64x64 cursors */
@@ -6247,17 +6248,46 @@ static int intel_crtc_cursor_set(struct drm_crtc *crtc,
if (IS_GEN2(dev))
I915_WRITE(CURSIZE, (height << 12) | width);
 
- finish:
-   if (intel_crtc->cursor_bo) {
-   if (dev_priv->info->cursor_needs_physical) {
-   if (intel_crtc->cursor_bo != obj)
-   i915_gem_detach_phys_object(dev, 
intel_crtc->cursor_bo);
-   } else
-   i915_gem_object_unpin(intel_crtc->cursor_bo);
-   drm_gem_object_unreference(&intel_crtc->cursor_bo->base);
-   }
+   mutex_unlock(&dev->struct_mutex);
+
+   *obj_ret = obj;
+   *addr_ret = addr;
+
+   return 0;
+fail_unpin:
+   i915_gem_object_unpin(obj);
+fail_locked:
+   mutex_unlock(&dev->struct_mutex);
+fail:
+   drm_gem_object_unreference_unlocked(&obj->base);
+   return ret;
+}
+
+static void intel_crtc_cursor_bo_unref(struct drm_crtc *crtc,
+  struct drm_i915_gem_object *obj)
+{
+   struct drm_device *dev = crtc->dev;
+   struct drm_i915_private *dev_priv = dev->dev_private;
+   struct intel_crtc *intel_crtc = to_intel_crtc(crtc);
+
+   mutex_lock(&dev->struct_mutex);
+
+   if (dev_priv->info->cursor_needs_physical) {
+   if (obj != intel_crtc->cursor_bo)
+   i915_gem_detach_phys_object(dev, obj);
+   } else
+   i915_gem_object_unpin(obj);
+   drm_gem_object_unreference(&obj->base);
 
mutex_unlock(&dev->struct_mutex);
+}
+
+static void intel_crtc_cursor_commit(struct drm_crtc *crtc, uint32_t handle,
+uint32_t width, uint32_t height,
+struct drm_i915_gem_object *obj,
+uint32_t addr)
+{
+   struct intel_crtc *intel_crtc = to_intel_crtc(crtc);
 
intel_crtc->cursor_addr = addr;
intel_crtc->cursor_handle = handle;
@@ -6266,15 +6296,31 @@ static int intel_crtc_cursor_set(struct drm_crtc *crtc,
intel_crtc->cursor_height = height;
 
intel_crtc_update_cursor(crtc, true);
+}
+
+static int intel_crtc_cursor_set(struct drm_crtc *crtc,
+struct drm_file *file,
+uint32_t handle,
+uint32_t width, uint32_t height)
+{
+   struct intel_crtc *intel_crtc = to_intel_crtc(crtc);
+   int ret;
+   struct drm_i915_gem_object *obj, *old_obj;
+   uint32_t addr;
+
+   ret = intel_crtc_cursor_prepare(crtc, file, handle, width, height,
+   &obj, &addr);
+   if (ret)
+   return ret;
+
+   old_obj = intel_crtc->cursor_bo;
+
+   intel_crtc_cursor_commit(crtc, handle, width, height, obj, addr)

[Intel-gfx] [PATCH 25/81] drm/i915: unstatic cursor functions for use with atomic modesetting

2012-12-12 Thread ville . syrjala
From: Ander Conselvan de Oliveira 

---
 drivers/gpu/drm/i915/intel_display.c |   24 
 drivers/gpu/drm/i915/intel_drv.h |   13 +
 2 files changed, 25 insertions(+), 12 deletions(-)

diff --git a/drivers/gpu/drm/i915/intel_display.c 
b/drivers/gpu/drm/i915/intel_display.c
index 0f25a07..2f72881 100644
--- a/drivers/gpu/drm/i915/intel_display.c
+++ b/drivers/gpu/drm/i915/intel_display.c
@@ -6173,12 +6173,12 @@ static void intel_crtc_update_cursor(struct drm_crtc 
*crtc,
}
 }
 
-static int intel_crtc_cursor_prepare(struct drm_crtc *crtc,
-struct drm_file *file,
-uint32_t handle,
-uint32_t width, uint32_t height,
-struct drm_i915_gem_object **obj_ret,
-uint32_t *addr_ret)
+int intel_crtc_cursor_prepare(struct drm_crtc *crtc,
+ struct drm_file *file,
+ uint32_t handle,
+ uint32_t width, uint32_t height,
+ struct drm_i915_gem_object **obj_ret,
+ uint32_t *addr_ret)
 {
struct drm_device *dev = crtc->dev;
struct drm_i915_private *dev_priv = dev->dev_private;
@@ -6263,8 +6263,8 @@ fail:
return ret;
 }
 
-static void intel_crtc_cursor_bo_unref(struct drm_crtc *crtc,
-  struct drm_i915_gem_object *obj)
+void intel_crtc_cursor_bo_unref(struct drm_crtc *crtc,
+   struct drm_i915_gem_object *obj)
 {
struct drm_device *dev = crtc->dev;
struct drm_i915_private *dev_priv = dev->dev_private;
@@ -6282,10 +6282,10 @@ static void intel_crtc_cursor_bo_unref(struct drm_crtc 
*crtc,
mutex_unlock(&dev->struct_mutex);
 }
 
-static void intel_crtc_cursor_commit(struct drm_crtc *crtc, uint32_t handle,
-uint32_t width, uint32_t height,
-struct drm_i915_gem_object *obj,
-uint32_t addr)
+void intel_crtc_cursor_commit(struct drm_crtc *crtc, uint32_t handle,
+ uint32_t width, uint32_t height,
+ struct drm_i915_gem_object *obj,
+ uint32_t addr)
 {
struct intel_crtc *intel_crtc = to_intel_crtc(crtc);
 
diff --git a/drivers/gpu/drm/i915/intel_drv.h b/drivers/gpu/drm/i915/intel_drv.h
index e77202c..785fa04 100644
--- a/drivers/gpu/drm/i915/intel_drv.h
+++ b/drivers/gpu/drm/i915/intel_drv.h
@@ -679,4 +679,17 @@ extern bool
 intel_ddi_connector_get_hw_state(struct intel_connector *intel_connector);
 extern void intel_ddi_fdi_disable(struct drm_crtc *crtc);
 
+extern int intel_crtc_cursor_prepare(struct drm_crtc *crtc,
+struct drm_file *file,
+uint32_t handle,
+uint32_t width, uint32_t height,
+struct drm_i915_gem_object **obj_ret,
+uint32_t *addr_ret);
+extern void intel_crtc_cursor_bo_unref(struct drm_crtc *crtc,
+  struct drm_i915_gem_object *obj);
+extern void intel_crtc_cursor_commit(struct drm_crtc *crtc, uint32_t handle,
+uint32_t width, uint32_t height,
+struct drm_i915_gem_object *obj,
+uint32_t addr);
+
 #endif /* __INTEL_DRV_H__ */
-- 
1.7.8.6

___
Intel-gfx mailing list
Intel-gfx@lists.freedesktop.org
http://lists.freedesktop.org/mailman/listinfo/intel-gfx


[Intel-gfx] [PATCH 26/81] drm/i915: Unstatic intel_finish_fb()

2012-12-12 Thread ville . syrjala
From: Ville Syrjälä 

intel_finish_fb() will be used by the atomic modeset code, so make it
non-static.

Signed-off-by: Ville Syrjälä 
---
 drivers/gpu/drm/i915/intel_display.c |2 +-
 drivers/gpu/drm/i915/intel_drv.h |1 +
 2 files changed, 2 insertions(+), 1 deletions(-)

diff --git a/drivers/gpu/drm/i915/intel_display.c 
b/drivers/gpu/drm/i915/intel_display.c
index 2f72881..a184b70 100644
--- a/drivers/gpu/drm/i915/intel_display.c
+++ b/drivers/gpu/drm/i915/intel_display.c
@@ -2182,7 +2182,7 @@ intel_pipe_set_base_atomic(struct drm_crtc *crtc, struct 
drm_framebuffer *fb,
return dev_priv->display.update_plane(crtc, fb, x, y);
 }
 
-static int
+int
 intel_finish_fb(struct drm_framebuffer *old_fb)
 {
struct drm_i915_gem_object *obj = to_intel_framebuffer(old_fb)->obj;
diff --git a/drivers/gpu/drm/i915/intel_drv.h b/drivers/gpu/drm/i915/intel_drv.h
index 785fa04..59ca0c3 100644
--- a/drivers/gpu/drm/i915/intel_drv.h
+++ b/drivers/gpu/drm/i915/intel_drv.h
@@ -590,6 +590,7 @@ extern int intel_pin_and_fence_fb_obj(struct drm_device 
*dev,
  struct drm_i915_gem_object *obj,
  struct intel_ring_buffer *pipelined);
 extern void intel_unpin_fb_obj(struct drm_i915_gem_object *obj);
+extern int intel_finish_fb(struct drm_framebuffer *old_fb);
 
 extern int intel_framebuffer_init(struct drm_device *dev,
  struct intel_framebuffer *ifb,
-- 
1.7.8.6

___
Intel-gfx mailing list
Intel-gfx@lists.freedesktop.org
http://lists.freedesktop.org/mailman/listinfo/intel-gfx


[Intel-gfx] [PATCH 22/81] drm/i915: Add intel_check_clock()

2012-12-12 Thread ville . syrjala
From: Ville Syrjälä 

intel_check_clock() can be used to check clock validity w/o modifying
hardware state.

Signed-off-by: Ville Syrjälä 
---
 drivers/gpu/drm/i915/i915_drv.h  |2 ++
 drivers/gpu/drm/i915/intel_display.c |   34 ++
 2 files changed, 36 insertions(+), 0 deletions(-)

diff --git a/drivers/gpu/drm/i915/i915_drv.h b/drivers/gpu/drm/i915/i915_drv.h
index ab0bd29..c41982e 100644
--- a/drivers/gpu/drm/i915/i915_drv.h
+++ b/drivers/gpu/drm/i915/i915_drv.h
@@ -1719,6 +1719,8 @@ extern bool intel_fbc_enabled(struct drm_device *dev);
 extern void intel_disable_fbc(struct drm_device *dev);
 extern bool ironlake_set_drps(struct drm_device *dev, u8 val);
 extern void intel_init_pch_refclk(struct drm_device *dev);
+extern int intel_check_clock(struct drm_crtc *crtc,
+const struct drm_display_mode *adjusted_mode);
 extern void gen6_set_rps(struct drm_device *dev, u8 val);
 extern void intel_detect_pch(struct drm_device *dev);
 extern int intel_trans_dp_port_sel(struct drm_crtc *crtc);
diff --git a/drivers/gpu/drm/i915/intel_display.c 
b/drivers/gpu/drm/i915/intel_display.c
index 2a2c664..dcd61fb 100644
--- a/drivers/gpu/drm/i915/intel_display.c
+++ b/drivers/gpu/drm/i915/intel_display.c
@@ -5686,6 +5686,40 @@ static int haswell_crtc_mode_set(struct drm_crtc *crtc,
return ret;
 }
 
+int intel_check_clock(struct drm_crtc *crtc,
+ const struct drm_display_mode *adjusted_mode)
+{
+   struct drm_device *dev = crtc->dev;
+   intel_clock_t clock, reduced_clock;
+   bool has_reduced_clock = false;
+   bool ok;
+
+   if (IS_HASWELL(dev)) {
+   if (!intel_ddi_pll_mode_set(crtc, adjusted_mode->clock))
+   return -EINVAL;
+
+   if (HAS_PCH_IBX(dev) || HAS_PCH_CPT(dev)) {
+   ok = ironlake_compute_clocks(crtc, adjusted_mode, 
&clock,
+&has_reduced_clock,
+&reduced_clock);
+   } else
+   ok = true;
+   } else if (HAS_PCH_SPLIT(dev)) {
+   ok = ironlake_compute_clocks(crtc, adjusted_mode, &clock,
+&has_reduced_clock, 
&reduced_clock);
+   } else {
+   int num_connectors = 0;
+   bool is_dp = false;
+   int refclk;
+
+   ok = i9xx_compute_clocks(crtc, adjusted_mode, &clock,
+&has_reduced_clock, &reduced_clock,
+&refclk, &num_connectors, &is_dp);
+   }
+
+   return ok ? 0 : -EINVAL;
+}
+
 static int intel_crtc_mode_set(struct drm_crtc *crtc,
   struct drm_display_mode *mode,
   struct drm_display_mode *adjusted_mode,
-- 
1.7.8.6

___
Intel-gfx mailing list
Intel-gfx@lists.freedesktop.org
http://lists.freedesktop.org/mailman/listinfo/intel-gfx


[Intel-gfx] [PATCH 29/81] drm/i915: Unstatic intel_crtc_update_sarea_pos()

2012-12-12 Thread ville . syrjala
From: Ville Syrjälä 

Make intel_crtc_update_sarea_pos() available to the atomic mode setting code.

Signed-off-by: Ville Syrjälä 
---
 drivers/gpu/drm/i915/intel_display.c |2 +-
 drivers/gpu/drm/i915/intel_drv.h |1 +
 2 files changed, 2 insertions(+), 1 deletions(-)

diff --git a/drivers/gpu/drm/i915/intel_display.c 
b/drivers/gpu/drm/i915/intel_display.c
index 9918dcb..f7190d2 100644
--- a/drivers/gpu/drm/i915/intel_display.c
+++ b/drivers/gpu/drm/i915/intel_display.c
@@ -2209,7 +2209,7 @@ intel_finish_fb(struct drm_framebuffer *old_fb)
return ret;
 }
 
-static void intel_crtc_update_sarea_pos(struct drm_crtc *crtc, int x, int y)
+void intel_crtc_update_sarea_pos(struct drm_crtc *crtc, int x, int y)
 {
struct drm_device *dev = crtc->dev;
struct drm_i915_master_private *master_priv;
diff --git a/drivers/gpu/drm/i915/intel_drv.h b/drivers/gpu/drm/i915/intel_drv.h
index c1fee22..a7d8df8 100644
--- a/drivers/gpu/drm/i915/intel_drv.h
+++ b/drivers/gpu/drm/i915/intel_drv.h
@@ -694,5 +694,6 @@ extern void intel_crtc_cursor_commit(struct drm_crtc *crtc, 
uint32_t handle,
 uint32_t addr);
 
 extern void intel_crtc_update_sarea(struct drm_crtc *crtc, bool enabled);
+extern void intel_crtc_update_sarea_pos(struct drm_crtc *crtc, int x, int y);
 
 #endif /* __INTEL_DRV_H__ */
-- 
1.7.8.6

___
Intel-gfx mailing list
Intel-gfx@lists.freedesktop.org
http://lists.freedesktop.org/mailman/listinfo/intel-gfx


[Intel-gfx] [PATCH 28/81] drm/i915: Unstatic intel_crtc_update_sarea()

2012-12-12 Thread ville . syrjala
From: Ville Syrjälä 

Make intel_crtc_update_sarea() available for the atomic mode setting
code.

Signed-off-by: Ville Syrjälä 
---
 drivers/gpu/drm/i915/intel_display.c |4 ++--
 drivers/gpu/drm/i915/intel_drv.h |2 ++
 2 files changed, 4 insertions(+), 2 deletions(-)

diff --git a/drivers/gpu/drm/i915/intel_display.c 
b/drivers/gpu/drm/i915/intel_display.c
index 6522e1e..9918dcb 100644
--- a/drivers/gpu/drm/i915/intel_display.c
+++ b/drivers/gpu/drm/i915/intel_display.c
@@ -3652,8 +3652,8 @@ static void i9xx_crtc_off(struct drm_crtc *crtc)
 {
 }
 
-static void intel_crtc_update_sarea(struct drm_crtc *crtc,
-   bool enabled)
+void intel_crtc_update_sarea(struct drm_crtc *crtc,
+bool enabled)
 {
struct drm_device *dev = crtc->dev;
struct drm_i915_master_private *master_priv;
diff --git a/drivers/gpu/drm/i915/intel_drv.h b/drivers/gpu/drm/i915/intel_drv.h
index 59ca0c3..c1fee22 100644
--- a/drivers/gpu/drm/i915/intel_drv.h
+++ b/drivers/gpu/drm/i915/intel_drv.h
@@ -693,4 +693,6 @@ extern void intel_crtc_cursor_commit(struct drm_crtc *crtc, 
uint32_t handle,
 struct drm_i915_gem_object *obj,
 uint32_t addr);
 
+extern void intel_crtc_update_sarea(struct drm_crtc *crtc, bool enabled);
+
 #endif /* __INTEL_DRV_H__ */
-- 
1.7.8.6

___
Intel-gfx mailing list
Intel-gfx@lists.freedesktop.org
http://lists.freedesktop.org/mailman/listinfo/intel-gfx


[Intel-gfx] [PATCH 30/81] drm/i915: Constify mode argument to intel_modeset_adjusted_mode()

2012-12-12 Thread ville . syrjala
From: Ville Syrjälä 

intel_modeset_adjusted_mode() doesn't modify the passed display mode. So
pass it as const.

Signed-off-by: Ville Syrjälä 
---
 drivers/gpu/drm/i915/intel_display.c |2 +-
 1 files changed, 1 insertions(+), 1 deletions(-)

diff --git a/drivers/gpu/drm/i915/intel_display.c 
b/drivers/gpu/drm/i915/intel_display.c
index f7190d2..dac80c4 100644
--- a/drivers/gpu/drm/i915/intel_display.c
+++ b/drivers/gpu/drm/i915/intel_display.c
@@ -7401,7 +7401,7 @@ static void intel_modeset_commit_output_state(struct 
drm_device *dev)
 
 static struct drm_display_mode *
 intel_modeset_adjusted_mode(struct drm_crtc *crtc,
-   struct drm_display_mode *mode)
+   const struct drm_display_mode *mode)
 {
struct drm_device *dev = crtc->dev;
struct drm_display_mode *adjusted_mode;
-- 
1.7.8.6

___
Intel-gfx mailing list
Intel-gfx@lists.freedesktop.org
http://lists.freedesktop.org/mailman/listinfo/intel-gfx


[Intel-gfx] [PATCH 31/81] drm/i915: Unstatic intel_crtc_mode_fixup()

2012-12-12 Thread ville . syrjala
From: Ville Syrjälä 

Make intel_crtc_mode_fixup() available for the upcoming atomic
modesetting code.

Signed-off-by: Ville Syrjälä 
---
 drivers/gpu/drm/i915/intel_display.c |6 +++---
 drivers/gpu/drm/i915/intel_drv.h |4 
 2 files changed, 7 insertions(+), 3 deletions(-)

diff --git a/drivers/gpu/drm/i915/intel_display.c 
b/drivers/gpu/drm/i915/intel_display.c
index dac80c4..2c2fcda 100644
--- a/drivers/gpu/drm/i915/intel_display.c
+++ b/drivers/gpu/drm/i915/intel_display.c
@@ -3851,9 +3851,9 @@ bool intel_connector_get_hw_state(struct intel_connector 
*connector)
return encoder->get_hw_state(encoder, &pipe);
 }
 
-static bool intel_crtc_mode_fixup(struct drm_crtc *crtc,
- const struct drm_display_mode *mode,
- struct drm_display_mode *adjusted_mode)
+bool intel_crtc_mode_fixup(struct drm_crtc *crtc,
+  const struct drm_display_mode *mode,
+  struct drm_display_mode *adjusted_mode)
 {
struct drm_device *dev = crtc->dev;
 
diff --git a/drivers/gpu/drm/i915/intel_drv.h b/drivers/gpu/drm/i915/intel_drv.h
index a7d8df8..ee6c85f 100644
--- a/drivers/gpu/drm/i915/intel_drv.h
+++ b/drivers/gpu/drm/i915/intel_drv.h
@@ -696,4 +696,8 @@ extern void intel_crtc_cursor_commit(struct drm_crtc *crtc, 
uint32_t handle,
 extern void intel_crtc_update_sarea(struct drm_crtc *crtc, bool enabled);
 extern void intel_crtc_update_sarea_pos(struct drm_crtc *crtc, int x, int y);
 
+extern bool intel_crtc_mode_fixup(struct drm_crtc *crtc,
+ const struct drm_display_mode *mode,
+ struct drm_display_mode *adjusted_mode);
+
 #endif /* __INTEL_DRV_H__ */
-- 
1.7.8.6

___
Intel-gfx mailing list
Intel-gfx@lists.freedesktop.org
http://lists.freedesktop.org/mailman/listinfo/intel-gfx


[Intel-gfx] [PATCH 32/81] drm/i915: Introduce intel_plane_regs

2012-12-12 Thread ville . syrjala
From: Ville Syrjälä 

intel_plane_regs can be used to shadow all the typical plane registers.

Signed-off-by: Ville Syrjälä 
---
 drivers/gpu/drm/i915/intel_drv.h |   14 ++
 1 files changed, 14 insertions(+), 0 deletions(-)

diff --git a/drivers/gpu/drm/i915/intel_drv.h b/drivers/gpu/drm/i915/intel_drv.h
index ee6c85f..b11510a 100644
--- a/drivers/gpu/drm/i915/intel_drv.h
+++ b/drivers/gpu/drm/i915/intel_drv.h
@@ -194,6 +194,20 @@ struct intel_connector {
struct edid *edid;
 };
 
+struct intel_plane_regs {
+   u32 cntr;
+   u32 linoff;
+   u32 stride;
+   u32 pos;
+   u32 size;
+   u32 keyval;
+   u32 keymsk;
+   u32 surf;
+   u32 keymaxval;
+   u32 tileoff;
+   u32 scale;
+};
+
 struct intel_crtc {
struct drm_crtc base;
enum pipe pipe;
-- 
1.7.8.6

___
Intel-gfx mailing list
Intel-gfx@lists.freedesktop.org
http://lists.freedesktop.org/mailman/listinfo/intel-gfx


[Intel-gfx] [PATCH 27/81] drm/i915: Pull intel_pipe_set_base() out of the crtc_mode_set() functions

2012-12-12 Thread ville . syrjala
From: Ville Syrjälä 

intel_pipe_set_base() (un)pins the buffers, so it can't be called from
the atomic modeset paths. Pull the intel_pipe_set_base() and watermark
modifications out of i9xx_crtc_mode_set() and ironlake_crtc_mode_set()
into intel_crtc_mode_set(), so that the former two can be used from the
atomic modeset paths.

Signed-off-by: Ville Syrjälä 
---
 drivers/gpu/drm/i915/intel_display.c |   35 -
 1 files changed, 13 insertions(+), 22 deletions(-)

diff --git a/drivers/gpu/drm/i915/intel_display.c 
b/drivers/gpu/drm/i915/intel_display.c
index a184b70..6522e1e 100644
--- a/drivers/gpu/drm/i915/intel_display.c
+++ b/drivers/gpu/drm/i915/intel_display.c
@@ -4630,7 +4630,6 @@ static int i9xx_crtc_mode_set(struct drm_crtc *crtc,
u32 dspcntr, pipeconf;
bool ok, has_reduced_clock = false;
bool is_dp = false;
-   int ret;
 
ok = i9xx_compute_clocks(crtc, adjusted_mode, &clock,
 &has_reduced_clock, &reduced_clock,
@@ -4738,11 +4737,7 @@ static int i9xx_crtc_mode_set(struct drm_crtc *crtc,
I915_WRITE(DSPCNTR(plane), dspcntr);
POSTING_READ(DSPCNTR(plane));
 
-   ret = intel_pipe_set_base(crtc, x, y, fb);
-
-   intel_update_watermarks(dev);
-
-   return ret;
+   return 0;
 }
 
 static void ironlake_init_pch_refclk(struct drm_device *dev)
@@ -5479,7 +5474,6 @@ static int ironlake_crtc_mode_set(struct drm_crtc *crtc,
bool ok, has_reduced_clock = false;
bool is_lvds = false, is_dp = false, is_cpu_edp = false;
struct intel_encoder *encoder;
-   int ret;
bool dither, fdi_config_ok;
 
for_each_encoder_on_crtc(dev, crtc, encoder) {
@@ -5590,13 +5584,7 @@ static int ironlake_crtc_mode_set(struct drm_crtc *crtc,
I915_WRITE(DSPCNTR(plane), DISPPLANE_GAMMA_ENABLE);
POSTING_READ(DSPCNTR(plane));
 
-   ret = intel_pipe_set_base(crtc, x, y, fb);
-
-   intel_update_watermarks(dev);
-
-   intel_update_linetime_watermarks(dev, pipe, adjusted_mode);
-
-   return fdi_config_ok ? ret : -EINVAL;
+   return fdi_config_ok ? 0 : -EINVAL;
 }
 
 static int haswell_crtc_mode_set(struct drm_crtc *crtc,
@@ -5613,7 +5601,6 @@ static int haswell_crtc_mode_set(struct drm_crtc *crtc,
int num_connectors = 0;
bool is_dp = false, is_cpu_edp = false;
struct intel_encoder *encoder;
-   int ret;
bool dither;
 
for_each_encoder_on_crtc(dev, crtc, encoder) {
@@ -5677,13 +5664,7 @@ static int haswell_crtc_mode_set(struct drm_crtc *crtc,
I915_WRITE(DSPCNTR(plane), DISPPLANE_GAMMA_ENABLE);
POSTING_READ(DSPCNTR(plane));
 
-   ret = intel_pipe_set_base(crtc, x, y, fb);
-
-   intel_update_watermarks(dev);
-
-   intel_update_linetime_watermarks(dev, pipe, adjusted_mode);
-
-   return ret;
+   return 0;
 }
 
 int intel_check_clock(struct drm_crtc *crtc,
@@ -5738,6 +5719,16 @@ static int intel_crtc_mode_set(struct drm_crtc *crtc,
 
ret = dev_priv->display.crtc_mode_set(crtc, mode, adjusted_mode,
  x, y, fb);
+
+   if (!ret) {
+   ret = intel_pipe_set_base(crtc, x, y, fb);
+
+   intel_update_watermarks(dev);
+
+   if (HAS_PCH_SPLIT(dev))
+   intel_update_linetime_watermarks(dev, pipe, 
adjusted_mode);
+   }
+
drm_vblank_post_modeset(dev, pipe);
 
if (ret != 0)
-- 
1.7.8.6

___
Intel-gfx mailing list
Intel-gfx@lists.freedesktop.org
http://lists.freedesktop.org/mailman/listinfo/intel-gfx


[Intel-gfx] [PATCH 34/81] drm/i915: Split sprite update_plane() into calc+commit phases

2012-12-12 Thread ville . syrjala
From: Ville Syrjälä 

Separate the part that calculates the register values from the part that
writes the registers. This will be useful in the atomic page flip code.
Also move the watermark magic into a prepare function that can be
performed outside the critical parts of the atomic page flip code.

Signed-off-by: Ville Syrjälä 
---
 drivers/gpu/drm/i915/intel_drv.h|5 +
 drivers/gpu/drm/i915/intel_sprite.c |  416 ++-
 2 files changed, 273 insertions(+), 148 deletions(-)

diff --git a/drivers/gpu/drm/i915/intel_drv.h b/drivers/gpu/drm/i915/intel_drv.h
index 4798f54..05afdd1 100644
--- a/drivers/gpu/drm/i915/intel_drv.h
+++ b/drivers/gpu/drm/i915/intel_drv.h
@@ -270,6 +270,11 @@ struct intel_plane {
   struct drm_intel_sprite_colorkey *key);
void (*get_colorkey)(struct drm_plane *plane,
 struct drm_intel_sprite_colorkey *key);
+   void (*calc)(struct drm_plane *plane, struct drm_framebuffer *fb,
+const struct intel_plane_coords *clip);
+   void (*prepare)(struct drm_plane *plane);
+   void (*commit)(struct drm_plane *plane);
+   struct intel_plane_regs regs;
 };
 
 struct intel_watermark_params {
diff --git a/drivers/gpu/drm/i915/intel_sprite.c 
b/drivers/gpu/drm/i915/intel_sprite.c
index d64cefd..88644df 100644
--- a/drivers/gpu/drm/i915/intel_sprite.c
+++ b/drivers/gpu/drm/i915/intel_sprite.c
@@ -203,14 +203,13 @@ int intel_check_plane(const struct drm_plane *plane,
 }
 
 static void
-ivb_update_plane(struct drm_plane *plane,
-struct drm_framebuffer *fb,
-const struct intel_plane_coords *coords)
+ivb_calc_plane(struct drm_plane *plane,
+  struct drm_framebuffer *fb,
+  const struct intel_plane_coords *coords)
 {
struct drm_device *dev = plane->dev;
-   struct drm_i915_private *dev_priv = dev->dev_private;
struct intel_plane *intel_plane = to_intel_plane(plane);
-   const struct drm_i915_gem_object *obj = to_intel_framebuffer(fb)->obj;
+   const struct drm_i915_gem_object *obj;
int crtc_x = coords->crtc_x;
int crtc_y = coords->crtc_y;
unsigned int crtc_w = coords->crtc_w;
@@ -219,48 +218,56 @@ ivb_update_plane(struct drm_plane *plane,
uint32_t y = coords->src_y;
uint32_t src_w = coords->src_w;
uint32_t src_h = coords->src_h;
-   int pipe = intel_plane->pipe;
-   u32 sprctl, sprscale = 0;
unsigned long sprsurf_offset, linear_offset;
-   int pixel_size = drm_format_plane_cpp(fb->pixel_format, 0);
+   int pixel_size;
+   struct intel_plane_regs *regs = &intel_plane->regs;
 
-   sprctl = I915_READ(SPRCTL(pipe));
+   if (!coords->visible) {
+   regs->cntr &= ~SPRITE_ENABLE;
+   /* Disable the scaler */
+   regs->scale = 0;
+   return;
+   }
+
+   obj = to_intel_framebuffer(fb)->obj;
+   pixel_size = drm_format_plane_cpp(fb->pixel_format, 0);
 
/* Mask out pixel format bits in case we change it */
-   sprctl &= ~SPRITE_PIXFORMAT_MASK;
-   sprctl &= ~SPRITE_RGB_ORDER_RGBX;
-   sprctl &= ~SPRITE_YUV_BYTE_ORDER_MASK;
-   sprctl &= ~SPRITE_TILED;
+   regs->cntr &= ~(SPRITE_PIXFORMAT_MASK |
+   SPRITE_RGB_ORDER_RGBX |
+   SPRITE_YUV_BYTE_ORDER_MASK |
+   SPRITE_TILED |
+   SPRITE_ENABLE);
 
switch (fb->pixel_format) {
case DRM_FORMAT_XBGR:
-   sprctl |= SPRITE_FORMAT_RGBX888 | SPRITE_RGB_ORDER_RGBX;
+   regs->cntr |= SPRITE_FORMAT_RGBX888 | SPRITE_RGB_ORDER_RGBX;
break;
case DRM_FORMAT_XRGB:
-   sprctl |= SPRITE_FORMAT_RGBX888;
+   regs->cntr |= SPRITE_FORMAT_RGBX888;
break;
case DRM_FORMAT_YUYV:
-   sprctl |= SPRITE_FORMAT_YUV422 | SPRITE_YUV_ORDER_YUYV;
+   regs->cntr |= SPRITE_FORMAT_YUV422 | SPRITE_YUV_ORDER_YUYV;
break;
case DRM_FORMAT_YVYU:
-   sprctl |= SPRITE_FORMAT_YUV422 | SPRITE_YUV_ORDER_YVYU;
+   regs->cntr |= SPRITE_FORMAT_YUV422 | SPRITE_YUV_ORDER_YVYU;
break;
case DRM_FORMAT_UYVY:
-   sprctl |= SPRITE_FORMAT_YUV422 | SPRITE_YUV_ORDER_UYVY;
+   regs->cntr |= SPRITE_FORMAT_YUV422 | SPRITE_YUV_ORDER_UYVY;
break;
case DRM_FORMAT_VYUY:
-   sprctl |= SPRITE_FORMAT_YUV422 | SPRITE_YUV_ORDER_VYUY;
+   regs->cntr |= SPRITE_FORMAT_YUV422 | SPRITE_YUV_ORDER_VYUY;
break;
default:
BUG();
}
 
if (obj->tiling_mode != I915_TILING_NONE)
-   sprctl |= SPRITE_TILED;
+   regs->cntr |= SPRITE_TILED;
 
/* must disable */
-   sprctl |= SPRITE_TRICKLE_FEED_DISABLE;
-   sprctl |= SPR

[Intel-gfx] [PATCH 36/81] drm/i915: Add support for atomic modesetting completion events

2012-12-12 Thread ville . syrjala
From: Ville Syrjälä 

Send completion events when the atomic modesetting operations has
finished succesfully.

Signed-off-by: Ville Syrjälä 
---
 drivers/gpu/drm/i915/intel_atomic.c |  195 ++-
 1 files changed, 192 insertions(+), 3 deletions(-)

diff --git a/drivers/gpu/drm/i915/intel_atomic.c 
b/drivers/gpu/drm/i915/intel_atomic.c
index 4899f8c..3adb140 100644
--- a/drivers/gpu/drm/i915/intel_atomic.c
+++ b/drivers/gpu/drm/i915/intel_atomic.c
@@ -53,6 +53,7 @@ struct intel_plane_state {
bool dirty;
bool pinned;
bool changed;
+   struct drm_pending_atomic_event *event;
 
struct {
struct drm_crtc *crtc;
@@ -74,6 +75,7 @@ struct intel_crtc_state {
unsigned long connectors_bitmask;
unsigned long encoders_bitmask;
bool changed;
+   struct drm_pending_atomic_event *event;
 
struct {
bool enabled;
@@ -922,6 +924,111 @@ int intel_commit_plane_nopin(struct drm_plane *plane,
 struct drm_framebuffer *fb,
 const struct intel_plane_coords *coords);
 
+static struct drm_pending_atomic_event *alloc_event(struct drm_device *dev,
+   struct drm_file *file_priv,
+   uint64_t user_data)
+{
+   struct drm_pending_atomic_event *e;
+   unsigned long flags;
+
+   spin_lock_irqsave(&dev->event_lock, flags);
+
+   if (file_priv->event_space < sizeof e->event) {
+   spin_unlock_irqrestore(&dev->event_lock, flags);
+   return ERR_PTR(-ENOSPC);
+   }
+
+   file_priv->event_space -= sizeof e->event;
+   spin_unlock_irqrestore(&dev->event_lock, flags);
+
+   e = kzalloc(sizeof *e, GFP_KERNEL);
+   if (!e) {
+   spin_lock_irqsave(&dev->event_lock, flags);
+   file_priv->event_space += sizeof e->event;
+   spin_unlock_irqrestore(&dev->event_lock, flags);
+
+   return ERR_PTR(-ENOMEM);
+   }
+
+   e->event.base.type = DRM_EVENT_ATOMIC_COMPLETE;
+   e->event.base.length = sizeof e->event;
+   e->event.user_data = user_data;
+   e->base.event = &e->event.base;
+   e->base.file_priv = file_priv;
+   e->base.destroy = (void (*) (struct drm_pending_event *)) kfree;
+
+   return e;
+}
+
+static void free_event(struct drm_pending_atomic_event *e)
+{
+   e->base.file_priv->event_space += sizeof e->event;
+   kfree(e);
+}
+
+static void queue_event(struct drm_device *dev, struct drm_crtc *crtc,
+   struct drm_pending_atomic_event *e)
+{
+   struct timeval tvbl;
+
+   if (crtc) {
+   int pipe = to_intel_crtc(crtc)->pipe;
+
+   /* FIXME this is wrong for flips that are completed not at 
vblank */
+   e->event.sequence = drm_vblank_count_and_time(dev, pipe, &tvbl);
+   e->event.tv_sec = tvbl.tv_sec;
+   e->event.tv_usec = tvbl.tv_usec;
+   } else {
+   e->event.sequence = 0;
+   e->event.tv_sec = 0;
+   e->event.tv_usec = 0;
+   }
+
+   list_add_tail(&e->base.link, &e->base.file_priv->event_list);
+   wake_up_interruptible(&e->base.file_priv->event_wait);
+}
+
+static void queue_remaining_events(struct drm_device *dev, struct 
intel_atomic_state *s)
+{
+   int i;
+
+   for (i = 0; i < dev->mode_config.num_crtc; i++) {
+   struct intel_crtc_state *st = &s->crtc[i];
+
+   if (st->event) {
+   if (st->old.fb)
+   st->event->event.old_fb_id = 
st->old.fb->base.id;
+
+   spin_lock_irq(&dev->event_lock);
+   queue_event(dev, st->crtc, st->event);
+   spin_unlock_irq(&dev->event_lock);
+
+   st->event = NULL;
+   }
+   }
+
+   for (i = 0; i < dev->mode_config.num_plane; i++) {
+   struct intel_plane_state *st = &s->plane[i];
+   struct drm_crtc *crtc;
+
+   if (!st->event)
+   continue;
+
+   crtc = st->plane->crtc;
+   if (!crtc)
+   crtc = st->old.crtc;
+
+   if (st->old.fb)
+   st->event->event.old_fb_id = st->old.fb->base.id;
+
+   spin_lock_irq(&dev->event_lock);
+   queue_event(dev, crtc, st->event);
+   spin_unlock_irq(&dev->event_lock);
+
+   st->event = NULL;
+   }
+}
+
 static void swap_old_new(struct drm_device *dev,
 struct intel_atomic_state *s)
 {
@@ -1426,6 +1533,73 @@ static void update_crtc(struct drm_device *dev,
}
 }
 
+static int alloc_flip_data(struct drm_device *dev, struct intel_atomic_state 
*s)
+{
+   int i;
+
+   for (i = 0; i < dev->mode_config.num_crtc; i++) {
+  

[Intel-gfx] [PATCH 37/81] drm/i915: Add atomic page flip support

2012-12-12 Thread ville . syrjala
From: Ville Syrjälä 

Add support for the DRM_MODE_ATOMIC_NONBLOCK flag.

The drm_flip helper provides the necessary logic to track the
progress of the flips. drm_flip is driven by a few extra calls
from the interrupt handling and crtc_disable code paths.

Since the hardware doesn't provide inter-plane synchronization, some
extra software magic is required to avoid flips for multiple planes
ending up on the wrong sides of the vblank leading edge.

Signed-off-by: Ville Syrjälä 
---
 drivers/gpu/drm/i915/i915_dma.c  |3 +
 drivers/gpu/drm/i915/i915_drv.h  |4 +
 drivers/gpu/drm/i915/i915_irq.c  |   16 +-
 drivers/gpu/drm/i915/intel_atomic.c  |  622 +-
 drivers/gpu/drm/i915/intel_display.c |2 +
 drivers/gpu/drm/i915/intel_drv.h |7 +
 6 files changed, 637 insertions(+), 17 deletions(-)

diff --git a/drivers/gpu/drm/i915/i915_dma.c b/drivers/gpu/drm/i915/i915_dma.c
index 392c9a1..8501bf3 100644
--- a/drivers/gpu/drm/i915/i915_dma.c
+++ b/drivers/gpu/drm/i915/i915_dma.c
@@ -1764,6 +1764,8 @@ int i915_driver_open(struct drm_device *dev, struct 
drm_file *file)
 
idr_init(&file_priv->context_idr);
 
+   INIT_LIST_HEAD(&file_priv->pending_flips);
+
return 0;
 }
 
@@ -1804,6 +1806,7 @@ void i915_driver_preclose(struct drm_device * dev, struct 
drm_file *file_priv)
 {
i915_gem_context_close(dev, file_priv);
i915_gem_release(dev, file_priv);
+   intel_atomic_free_events(dev, file_priv);
 }
 
 void i915_driver_postclose(struct drm_device *dev, struct drm_file *file)
diff --git a/drivers/gpu/drm/i915/i915_drv.h b/drivers/gpu/drm/i915/i915_drv.h
index 66b3b64..0bafe7f 100644
--- a/drivers/gpu/drm/i915/i915_drv.h
+++ b/drivers/gpu/drm/i915/i915_drv.h
@@ -38,6 +38,7 @@
 #include 
 #include 
 #include 
+#include 
 #include 
 #include 
 #include 
@@ -957,6 +958,8 @@ typedef struct drm_i915_private {
/* Old dri1 support infrastructure, beware the dragons ya fools entering
 * here! */
struct i915_dri1_state dri1;
+
+   struct drm_flip_driver flip_driver;
 } drm_i915_private_t;
 
 /* Iterate over initialised rings */
@@ -1179,6 +1182,7 @@ struct drm_i915_file_private {
struct list_head request_list;
} mm;
struct idr context_idr;
+   struct list_head pending_flips;
 };
 
 #define INTEL_INFO(dev)(((struct drm_i915_private *) 
(dev)->dev_private)->info)
diff --git a/drivers/gpu/drm/i915/i915_irq.c b/drivers/gpu/drm/i915/i915_irq.c
index d02e022..430f201 100644
--- a/drivers/gpu/drm/i915/i915_irq.c
+++ b/drivers/gpu/drm/i915/i915_irq.c
@@ -581,8 +581,10 @@ static irqreturn_t valleyview_irq_handler(int irq, void 
*arg)
spin_unlock_irqrestore(&dev_priv->irq_lock, irqflags);
 
for_each_pipe(pipe) {
-   if (pipe_stats[pipe] & PIPE_VBLANK_INTERRUPT_STATUS)
+   if (pipe_stats[pipe] & PIPE_VBLANK_INTERRUPT_STATUS) {
drm_handle_vblank(dev, pipe);
+   intel_atomic_handle_vblank(dev, pipe);
+   }
 
if (pipe_stats[pipe] & PLANE_FLIPDONE_INT_STATUS_VLV) {
intel_prepare_page_flip(dev, pipe);
@@ -727,8 +729,10 @@ static irqreturn_t ivybridge_irq_handler(int irq, void 
*arg)
intel_opregion_gse_intr(dev);
 
for (i = 0; i < 3; i++) {
-   if (de_iir & (DE_PIPEA_VBLANK_IVB << (5 * i)))
+   if (de_iir & (DE_PIPEA_VBLANK_IVB << (5 * i))) {
drm_handle_vblank(dev, i);
+   intel_atomic_handle_vblank(dev, i);
+   }
if (de_iir & (DE_PLANEA_FLIP_DONE_IVB << (5 * i))) {
intel_prepare_page_flip(dev, i);
intel_finish_page_flip_plane(dev, i);
@@ -807,11 +811,15 @@ static irqreturn_t ironlake_irq_handler(int irq, void 
*arg)
if (de_iir & DE_GSE)
intel_opregion_gse_intr(dev);
 
-   if (de_iir & DE_PIPEA_VBLANK)
+   if (de_iir & DE_PIPEA_VBLANK) {
drm_handle_vblank(dev, 0);
+   intel_atomic_handle_vblank(dev, 0);
+   }
 
-   if (de_iir & DE_PIPEB_VBLANK)
+   if (de_iir & DE_PIPEB_VBLANK) {
drm_handle_vblank(dev, 1);
+   intel_atomic_handle_vblank(dev, 1);
+   }
 
if (de_iir & DE_PLANEA_FLIP_DONE) {
intel_prepare_page_flip(dev, 0);
diff --git a/drivers/gpu/drm/i915/intel_atomic.c 
b/drivers/gpu/drm/i915/intel_atomic.c
index 3adb140..238a843 100644
--- a/drivers/gpu/drm/i915/intel_atomic.c
+++ b/drivers/gpu/drm/i915/intel_atomic.c
@@ -26,6 +26,7 @@
 
 #include 
 #include 
+#include 
 
 #include "intel_drv.h"
 
@@ -47,6 +48,20 @@ static struct drm_property *prop_cursor_y;
 static struct drm_property *prop_cursor_w;
 static s

[Intel-gfx] [PATCH 38/81] drm/i915: Unstatic intel_enable_primary() and intel_disable_primary()

2012-12-12 Thread ville . syrjala
From: Ville Syrjälä 

intel_enable_primary() and intel_disable_primary() are needed in the
atomic mode setting code.

Signed-off-by: Ville Syrjälä 
---
 drivers/gpu/drm/i915/intel_drv.h|3 +++
 drivers/gpu/drm/i915/intel_sprite.c |4 ++--
 2 files changed, 5 insertions(+), 2 deletions(-)

diff --git a/drivers/gpu/drm/i915/intel_drv.h b/drivers/gpu/drm/i915/intel_drv.h
index cd37428..92a9518 100644
--- a/drivers/gpu/drm/i915/intel_drv.h
+++ b/drivers/gpu/drm/i915/intel_drv.h
@@ -730,4 +730,7 @@ extern void intel_atomic_fini(struct drm_device *dev);
 extern void intel_atomic_free_events(struct drm_device *dev, struct drm_file 
*file);
 extern void intel_atomic_handle_vblank(struct drm_device *dev, int pipe);
 
+extern void intel_enable_primary(struct drm_crtc *crtc);
+extern void intel_disable_primary(struct drm_crtc *crtc);
+
 #endif /* __INTEL_DRV_H__ */
diff --git a/drivers/gpu/drm/i915/intel_sprite.c 
b/drivers/gpu/drm/i915/intel_sprite.c
index 88644df..693b265 100644
--- a/drivers/gpu/drm/i915/intel_sprite.c
+++ b/drivers/gpu/drm/i915/intel_sprite.c
@@ -610,7 +610,7 @@ void intel_calc_sprite(struct drm_plane *plane,
ilk_calc_plane(plane, fb, coords);
 }
 
-static void
+void
 intel_enable_primary(struct drm_crtc *crtc)
 {
struct drm_device *dev = crtc->dev;
@@ -629,7 +629,7 @@ intel_enable_primary(struct drm_crtc *crtc)
dev_priv->display.commit_plane(crtc);
 }
 
-static void
+void
 intel_disable_primary(struct drm_crtc *crtc)
 {
struct drm_device *dev = crtc->dev;
-- 
1.7.8.6

___
Intel-gfx mailing list
Intel-gfx@lists.freedesktop.org
http://lists.freedesktop.org/mailman/listinfo/intel-gfx


[Intel-gfx] [PATCH 33/81] drm/i915: Split primary plane update_plane() into calc+commit phases

2012-12-12 Thread ville . syrjala
From: Ville Syrjälä 

Separate the part that calculates the register values from the part that
writes the registers. This will be useful in the atomic page flip code.

Signed-off-by: Ville Syrjälä 
---
 drivers/gpu/drm/i915/i915_drv.h  |3 +
 drivers/gpu/drm/i915/intel_display.c |  154 ++
 drivers/gpu/drm/i915/intel_drv.h |1 +
 3 files changed, 105 insertions(+), 53 deletions(-)

diff --git a/drivers/gpu/drm/i915/i915_drv.h b/drivers/gpu/drm/i915/i915_drv.h
index c41982e..66b3b64 100644
--- a/drivers/gpu/drm/i915/i915_drv.h
+++ b/drivers/gpu/drm/i915/i915_drv.h
@@ -297,6 +297,9 @@ struct drm_i915_display_funcs {
  struct drm_i915_gem_object *obj);
int (*update_plane)(struct drm_crtc *crtc, struct drm_framebuffer *fb,
int x, int y);
+   int (*calc_plane)(struct drm_crtc *crtc, struct drm_framebuffer *fb,
+ int x, int y);
+   void (*commit_plane)(struct drm_crtc *crtc);
/* clock updates for mode set */
/* cursor updates */
/* render clock increase/decrease */
diff --git a/drivers/gpu/drm/i915/intel_display.c 
b/drivers/gpu/drm/i915/intel_display.c
index 2c2fcda..c0db749 100644
--- a/drivers/gpu/drm/i915/intel_display.c
+++ b/drivers/gpu/drm/i915/intel_display.c
@@ -1979,8 +1979,30 @@ unsigned long intel_gen4_compute_offset_xtiled(int *x, 
int *y,
return tile_rows * pitch * 8 + tiles * 4096;
 }
 
-static int i9xx_update_plane(struct drm_crtc *crtc, struct drm_framebuffer *fb,
-int x, int y)
+static void intel_commit_plane(struct drm_crtc *crtc)
+{
+   struct drm_device *dev = crtc->dev;
+   struct drm_i915_private *dev_priv = dev->dev_private;
+   struct intel_crtc *intel_crtc = to_intel_crtc(crtc);
+   int plane = intel_crtc->plane;
+   const struct intel_plane_regs *regs = &intel_crtc->primary_regs;
+
+   I915_WRITE(DSPCNTR(plane), regs->cntr);
+   I915_WRITE(DSPSTRIDE(plane), regs->stride);
+
+   if (IS_HASWELL(dev)) {
+   I915_WRITE(DSPOFFSET(plane), regs->tileoff);
+   I915_WRITE(DSPSURF(plane), regs->surf);
+   } else if (INTEL_INFO(dev)->gen >= 4) {
+   I915_WRITE(DSPTILEOFF(plane), regs->tileoff);
+   I915_WRITE(DSPLINOFF(plane), regs->linoff);
+   I915_WRITE(DSPSURF(plane), regs->surf);
+   } else
+   I915_WRITE(DSPADDR(plane), regs->linoff);
+}
+
+static int i9xx_calc_plane(struct drm_crtc *crtc, struct drm_framebuffer *fb,
+  int x, int y)
 {
struct drm_device *dev = crtc->dev;
struct drm_i915_private *dev_priv = dev->dev_private;
@@ -1989,9 +2011,8 @@ static int i9xx_update_plane(struct drm_crtc *crtc, 
struct drm_framebuffer *fb,
struct drm_i915_gem_object *obj;
int plane = intel_crtc->plane;
unsigned long linear_offset;
-   u32 dspcntr;
-   u32 reg;
unsigned int cpp = drm_format_plane_cpp(fb->pixel_format, 0);
+   struct intel_plane_regs *regs = &intel_crtc->primary_regs;
 
switch (plane) {
case 0:
@@ -2005,36 +2026,35 @@ static int i9xx_update_plane(struct drm_crtc *crtc, 
struct drm_framebuffer *fb,
intel_fb = to_intel_framebuffer(fb);
obj = intel_fb->obj;
 
-   reg = DSPCNTR(plane);
-   dspcntr = I915_READ(reg);
+   regs->cntr = I915_READ(DSPCNTR(plane));
/* Mask out pixel format bits in case we change it */
-   dspcntr &= ~DISPPLANE_PIXFORMAT_MASK;
+   regs->cntr &= ~DISPPLANE_PIXFORMAT_MASK;
switch (fb->pixel_format) {
case DRM_FORMAT_C8:
-   dspcntr |= DISPPLANE_8BPP;
+   regs->cntr |= DISPPLANE_8BPP;
break;
case DRM_FORMAT_XRGB1555:
case DRM_FORMAT_ARGB1555:
-   dspcntr |= DISPPLANE_BGRX555;
+   regs->cntr |= DISPPLANE_BGRX555;
break;
case DRM_FORMAT_RGB565:
-   dspcntr |= DISPPLANE_BGRX565;
+   regs->cntr |= DISPPLANE_BGRX565;
break;
case DRM_FORMAT_XRGB:
case DRM_FORMAT_ARGB:
-   dspcntr |= DISPPLANE_BGRX888;
+   regs->cntr |= DISPPLANE_BGRX888;
break;
case DRM_FORMAT_XBGR:
case DRM_FORMAT_ABGR:
-   dspcntr |= DISPPLANE_RGBX888;
+   regs->cntr |= DISPPLANE_RGBX888;
break;
case DRM_FORMAT_XRGB2101010:
case DRM_FORMAT_ARGB2101010:
-   dspcntr |= DISPPLANE_BGRX101010;
+   regs->cntr |= DISPPLANE_BGRX101010;
break;
case DRM_FORMAT_XBGR2101010:
case DRM_FORMAT_ABGR2101010:
-   dspcntr |= DISPPLANE_RGBX101010;
+   regs->cntr |= DISPPLANE_RGBX101010;
break;
default:
DRM_ERROR("Unknown pixel format 0x%08x\n", fb->pixel_format);
@@ -

[Intel-gfx] [PATCH 39/81] drm/i915: Respect primary_disabled in crtc_enable()

2012-12-12 Thread ville . syrjala
From: Ville Syrjälä 

Check primary_disabled state before enabling the primary plane in
crtc_enable() hooks.

Signed-off-by: Ville Syrjälä 
---
 drivers/gpu/drm/i915/intel_display.c |9 ++---
 1 files changed, 6 insertions(+), 3 deletions(-)

diff --git a/drivers/gpu/drm/i915/intel_display.c 
b/drivers/gpu/drm/i915/intel_display.c
index 7394aca..957907c 100644
--- a/drivers/gpu/drm/i915/intel_display.c
+++ b/drivers/gpu/drm/i915/intel_display.c
@@ -3349,7 +3349,8 @@ static void ironlake_crtc_enable(struct drm_crtc *crtc)
intel_crtc_load_lut(crtc);
 
intel_enable_pipe(dev_priv, pipe, is_pch_port);
-   intel_enable_plane(dev_priv, plane, pipe);
+   if (!intel_crtc->primary_disabled)
+   intel_enable_plane(dev_priv, plane, pipe);
 
if (is_pch_port)
ironlake_pch_enable(crtc);
@@ -3429,7 +3430,8 @@ static void haswell_crtc_enable(struct drm_crtc *crtc)
intel_ddi_enable_pipe_func(crtc);
 
intel_enable_pipe(dev_priv, pipe, is_pch_port);
-   intel_enable_plane(dev_priv, plane, pipe);
+   if (!intel_crtc->primary_disabled)
+   intel_enable_plane(dev_priv, plane, pipe);
 
if (is_pch_port)
lpt_pch_enable(crtc);
@@ -3644,7 +3646,8 @@ static void i9xx_crtc_enable(struct drm_crtc *crtc)
 
intel_enable_pll(dev_priv, pipe);
intel_enable_pipe(dev_priv, pipe, false);
-   intel_enable_plane(dev_priv, plane, pipe);
+   if (!intel_crtc->primary_disabled)
+   intel_enable_plane(dev_priv, plane, pipe);
 
intel_crtc_load_lut(crtc);
intel_update_fbc(dev);
-- 
1.7.8.6

___
Intel-gfx mailing list
Intel-gfx@lists.freedesktop.org
http://lists.freedesktop.org/mailman/listinfo/intel-gfx


[Intel-gfx] [PATCH 40/81] drm/i915: Enable/disable primary plane in calc_plane()

2012-12-12 Thread ville . syrjala
From: Ville Syrjälä 

Check the active and primary_disabled flags and set the
DISPLAY_PLANE_ENABLE bit accordingly in calc_plane() hook for the
primary plane.

Signed-off-by: Ville Syrjälä 
---
 drivers/gpu/drm/i915/intel_display.c |   10 ++
 1 files changed, 10 insertions(+), 0 deletions(-)

diff --git a/drivers/gpu/drm/i915/intel_display.c 
b/drivers/gpu/drm/i915/intel_display.c
index 957907c..9903456 100644
--- a/drivers/gpu/drm/i915/intel_display.c
+++ b/drivers/gpu/drm/i915/intel_display.c
@@ -2068,6 +2068,11 @@ static int i9xx_calc_plane(struct drm_crtc *crtc, struct 
drm_framebuffer *fb,
regs->cntr &= ~DISPPLANE_TILED;
}
 
+   if (intel_crtc->active && !intel_crtc->primary_disabled)
+   regs->cntr |= DISPLAY_PLANE_ENABLE;
+   else
+   regs->cntr &= ~DISPLAY_PLANE_ENABLE;
+
linear_offset = y * fb->pitches[0] + x * cpp;
 
if (INTEL_INFO(dev)->gen >= 4) {
@@ -2175,6 +2180,11 @@ static int ironlake_calc_plane(struct drm_crtc *crtc,
/* must disable */
regs->cntr |= DISPPLANE_TRICKLE_FEED_DISABLE;
 
+   if (intel_crtc->active && !intel_crtc->primary_disabled)
+   regs->cntr |= DISPLAY_PLANE_ENABLE;
+   else
+   regs->cntr &= ~DISPLAY_PLANE_ENABLE;
+
linear_offset = y * fb->pitches[0] + x * cpp;
intel_crtc->dspaddr_offset =
intel_gen4_compute_offset_xtiled(&x, &y,
-- 
1.7.8.6

___
Intel-gfx mailing list
Intel-gfx@lists.freedesktop.org
http://lists.freedesktop.org/mailman/listinfo/intel-gfx


[Intel-gfx] [PATCH 41/81] drm/i915: Add primary plane disable logic to atomic mode setting code

2012-12-12 Thread ville . syrjala
From: Ville Syrjälä 

Enable/disable the primary plane accordingly when the sprite plane
coverage changes.

Signed-off-by: Ville Syrjälä 
---
 drivers/gpu/drm/i915/intel_atomic.c |   41 +++
 1 files changed, 41 insertions(+), 0 deletions(-)

diff --git a/drivers/gpu/drm/i915/intel_atomic.c 
b/drivers/gpu/drm/i915/intel_atomic.c
index 238a843..41885fa 100644
--- a/drivers/gpu/drm/i915/intel_atomic.c
+++ b/drivers/gpu/drm/i915/intel_atomic.c
@@ -93,6 +93,7 @@ struct intel_crtc_state {
bool changed;
struct drm_pending_atomic_event *event;
struct intel_flip *flip;
+   bool primary_disabled;
 
struct {
bool enabled;
@@ -318,6 +319,8 @@ static void *intel_atomic_begin(struct drm_device *dev, 
struct drm_file *file,
 
s->old.connectors_bitmask = s->connectors_bitmask;
s->old.encoders_bitmask = s->encoders_bitmask;
+
+   s->primary_disabled = intel_crtc->primary_disabled;
}
 
i = 0;
@@ -1157,6 +1160,9 @@ static int apply_config(struct drm_device *dev,
 intel_crtc->cursor_addr);
}
 
+   if (!st->primary_disabled)
+   intel_enable_primary(crtc);
+
for (j = 0; j < dev->mode_config.num_plane; j++) {
struct intel_plane_state *pst = &s->plane[j];
struct drm_plane *plane = pst->plane;
@@ -1170,6 +1176,9 @@ static int apply_config(struct drm_device *dev,
else if (!pst->coords.visible && pst->old.crtc == crtc)
intel_plane->disable_plane(plane);
}
+
+   if (st->primary_disabled)
+   intel_disable_primary(crtc);
}
 
/* don't restore the old state in end() */
@@ -1207,6 +1216,7 @@ static void restore_state(struct drm_device *dev,
intel_crtc->cursor_width = s->saved_crtcs[i].cursor_width;
intel_crtc->cursor_height = s->saved_crtcs[i].cursor_height;
intel_crtc->cursor_visible = s->saved_crtcs[i].cursor_visible;
+   intel_crtc->primary_disabled = 
s->saved_crtcs[i].primary_disabled;
 
i++;
}
@@ -1346,6 +1356,28 @@ static int check_crtc(struct intel_crtc_state *s)
return 0;
 }
 
+static void update_primary_visibility(struct drm_device *dev,
+ struct intel_atomic_state *s,
+ const struct drm_crtc *crtc,
+ const struct drm_plane *plane,
+ const struct intel_plane_coords *coords)
+{
+   struct intel_crtc *intel_crtc = to_intel_crtc(crtc);
+   bool primary_disabled =
+   coords->visible &&
+   coords->crtc_x == 0 &&
+   coords->crtc_y == 0 &&
+   coords->crtc_w == crtc->mode.hdisplay &&
+   coords->crtc_h == crtc->mode.vdisplay;
+
+   if (primary_disabled != intel_crtc->primary_disabled) {
+   struct intel_crtc_state *st = get_crtc_state(dev, s, crtc);
+   st->fb_dirty = true;
+   st->primary_disabled = primary_disabled;
+   s->dirty = true;
+   }
+}
+
 static int intel_atomic_check(struct drm_device *dev, void *state)
 {
struct intel_atomic_state *s = state;
@@ -1430,6 +1462,12 @@ static int intel_atomic_check(struct drm_device *dev, 
void *state)
ret = intel_check_plane(plane, plane->crtc, plane->fb, 
&st->coords);
if (ret)
return ret;
+
+   /* FIXME doesn't correctly handle cases where plane moves 
between crtcs */
+   if (plane->crtc)
+   update_primary_visibility(dev, s, plane->crtc, plane, 
&st->coords);
+   else if (st->old.crtc)
+   update_primary_visibility(dev, s, st->old.crtc, plane, 
&st->coords);
}
 
return 0;
@@ -2295,6 +2333,9 @@ static void atomic_pipe_commit(struct drm_device *dev,
 
intel_flip->crtc = crtc;
 
+   /* update primary_disabled befoer calc_plane() */
+   intel_crtc->primary_disabled = st->primary_disabled;
+
/* should already be checked so can't fail */
/* FIXME refactor the failing parts? */
dev_priv->display.calc_plane(crtc, crtc->fb, crtc->x, crtc->y);
-- 
1.7.8.6

___
Intel-gfx mailing list
Intel-gfx@lists.freedesktop.org
http://lists.freedesktop.org/mailman/listinfo/intel-gfx


[Intel-gfx] [PATCH 42/81] drm: Add missing EXPORT_SYMBOL()s for drm_flip

2012-12-12 Thread ville . syrjala
From: Ander Conselvan de Oliveira 

---
 drivers/gpu/drm/drm_flip.c |   11 +++
 1 files changed, 11 insertions(+), 0 deletions(-)

diff --git a/drivers/gpu/drm/drm_flip.c b/drivers/gpu/drm/drm_flip.c
index 6ccc3f8..a20e6a4 100644
--- a/drivers/gpu/drm/drm_flip.c
+++ b/drivers/gpu/drm/drm_flip.c
@@ -24,6 +24,7 @@
  * Ville Syrjälä 
  */
 
+#include 
 #include 
 
 static void drm_flip_driver_cleanup(struct work_struct *work)
@@ -141,6 +142,7 @@ void drm_flip_helper_init(struct drm_flip_helper *helper,
helper->driver = driver;
helper->funcs = funcs;
 }
+EXPORT_SYMBOL(drm_flip_helper_init);
 
 void drm_flip_helper_clear(struct drm_flip_helper *helper)
 {
@@ -176,6 +178,7 @@ void drm_flip_helper_clear(struct drm_flip_helper *helper)
if (need_cleanup)
queue_work(driver->wq, &driver->cleanup_work);
 }
+EXPORT_SYMBOL(drm_flip_helper_clear);
 
 void drm_flip_helper_fini(struct drm_flip_helper *helper)
 {
@@ -186,6 +189,7 @@ void drm_flip_helper_fini(struct drm_flip_helper *helper)
flush_work_sync(&driver->finish_work);
flush_work_sync(&driver->cleanup_work);
 }
+EXPORT_SYMBOL(drm_flip_helper_fini);
 
 void drm_flip_helper_vblank(struct drm_flip_helper *helper)
 {
@@ -223,6 +227,7 @@ void drm_flip_helper_vblank(struct drm_flip_helper *helper)
if (need_cleanup)
queue_work(driver->wq, &driver->cleanup_work);
 }
+EXPORT_SYMBOL(drm_flip_helper_vblank);
 
 void drm_flip_driver_init(struct drm_flip_driver *driver,
  const struct drm_flip_driver_funcs *funcs)
@@ -239,6 +244,7 @@ void drm_flip_driver_init(struct drm_flip_driver *driver,
 
driver->wq = create_singlethread_workqueue("drm_flip");
 }
+EXPORT_SYMBOL(drm_flip_driver_init);
 
 void drm_flip_driver_fini(struct drm_flip_driver *driver)
 {
@@ -248,6 +254,7 @@ void drm_flip_driver_fini(struct drm_flip_driver *driver)
WARN_ON(!list_empty(&driver->finish_list));
WARN_ON(!list_empty(&driver->cleanup_list));
 }
+EXPORT_SYMBOL(drm_flip_driver_fini);
 
 void drm_flip_driver_schedule_flips(struct drm_flip_driver *driver,
struct list_head *flips)
@@ -298,6 +305,7 @@ void drm_flip_driver_schedule_flips(struct drm_flip_driver 
*driver,
if (need_cleanup)
queue_work(driver->wq, &driver->cleanup_work);
 }
+EXPORT_SYMBOL(drm_flip_driver_schedule_flips);
 
 void drm_flip_driver_prepare_flips(struct drm_flip_driver *driver,
   struct list_head *flips)
@@ -311,6 +319,7 @@ void drm_flip_driver_prepare_flips(struct drm_flip_driver 
*driver,
helper->funcs->prepare(flip);
}
 }
+EXPORT_SYMBOL(drm_flip_driver_prepare_flips);
 
 void drm_flip_driver_complete_flips(struct drm_flip_driver *driver,
struct list_head *flips)
@@ -365,6 +374,7 @@ void drm_flip_driver_complete_flips(struct drm_flip_driver 
*driver,
if (need_cleanup)
queue_work(driver->wq, &driver->cleanup_work);
 }
+EXPORT_SYMBOL(drm_flip_driver_complete_flips);
 
 void drm_flip_init(struct drm_flip *flip,
   struct drm_flip_helper *helper)
@@ -374,3 +384,4 @@ void drm_flip_init(struct drm_flip *flip,
flip->finished = false;
INIT_LIST_HEAD(&flip->list);
 }
+EXPORT_SYMBOL(drm_flip_init);
-- 
1.7.8.6

___
Intel-gfx mailing list
Intel-gfx@lists.freedesktop.org
http://lists.freedesktop.org/mailman/listinfo/intel-gfx


[Intel-gfx] [PATCH 45/81] drm/i915: Move standard properties under mode_config

2012-12-12 Thread ville . syrjala
From: Ville Syrjälä 

Standard connector properties are kept in the mode_config structure.
Move the CRTC and plane properties there as well.

Signed-off-by: Ville Syrjälä 
---
 drivers/gpu/drm/i915/intel_atomic.c |  293 +++
 include/drm/drm_crtc.h  |   19 +++
 2 files changed, 175 insertions(+), 137 deletions(-)

diff --git a/drivers/gpu/drm/i915/intel_atomic.c 
b/drivers/gpu/drm/i915/intel_atomic.c
index 0e37cf5..0def947 100644
--- a/drivers/gpu/drm/i915/intel_atomic.c
+++ b/drivers/gpu/drm/i915/intel_atomic.c
@@ -30,24 +30,6 @@
 
 #include "intel_drv.h"
 
-static struct drm_property *prop_src_x;
-static struct drm_property *prop_src_y;
-static struct drm_property *prop_src_w;
-static struct drm_property *prop_src_h;
-static struct drm_property *prop_crtc_x;
-static struct drm_property *prop_crtc_y;
-static struct drm_property *prop_crtc_w;
-static struct drm_property *prop_crtc_h;
-static struct drm_property *prop_fb_id;
-static struct drm_property *prop_crtc_id;
-static struct drm_property *prop_mode;
-static struct drm_property *prop_connector_ids;
-static struct drm_property *prop_cursor_id;
-static struct drm_property *prop_cursor_x;
-static struct drm_property *prop_cursor_y;
-static struct drm_property *prop_cursor_w;
-static struct drm_property *prop_cursor_h;
-
 struct intel_flip {
struct drm_flip base;
u32 vbl_count;
@@ -368,27 +350,28 @@ static int plane_set(struct intel_atomic_state *s,
 uint64_t value)
 {
struct drm_plane *plane = state->plane;
+   struct drm_mode_config *config = &plane->dev->mode_config;
struct drm_mode_object *obj;
 
state->changed = true;
 
-   if (prop == prop_src_x) {
+   if (prop == config->src_x_prop) {
plane->src_x = value;
-   } else if (prop == prop_src_y) {
+   } else if (prop == config->src_y_prop) {
plane->src_y = value;
-   } else if (prop == prop_src_w) {
+   } else if (prop == config->src_w_prop) {
plane->src_w = value;
-   } else if (prop == prop_src_h) {
+   } else if (prop == config->src_h_prop) {
plane->src_h = value;
-   } else if (prop == prop_crtc_x) {
+   } else if (prop == config->crtc_x_prop) {
plane->crtc_x = value;
-   } else if (prop == prop_crtc_y) {
+   } else if (prop == config->crtc_y_prop) {
plane->crtc_y = value;
-   } else if (prop == prop_crtc_w) {
+   } else if (prop == config->crtc_w_prop) {
plane->crtc_w = value;
-   } else if (prop == prop_crtc_h) {
+   } else if (prop == config->crtc_h_prop) {
plane->crtc_h = value;
-   } else if (prop == prop_crtc_id) {
+   } else if (prop == config->crtc_id_prop) {
if (value) {
obj = drm_mode_object_find(plane->dev, value, 
DRM_MODE_OBJECT_CRTC);
if (!obj) {
@@ -398,7 +381,7 @@ static int plane_set(struct intel_atomic_state *s,
plane->crtc = obj_to_crtc(obj);
} else
plane->crtc = NULL;
-   } else if (prop == prop_fb_id) {
+   } else if (prop == config->fb_id_prop) {
if (value) {
obj = drm_mode_object_find(plane->dev, value, 
DRM_MODE_OBJECT_FB);
if (!obj) {
@@ -422,16 +405,17 @@ static int crtc_set(struct intel_atomic_state *s,
uint64_t value, const void *blob_data)
 {
struct drm_crtc *crtc = state->crtc;
+   struct drm_mode_config *config = &crtc->dev->mode_config;
struct intel_crtc *intel_crtc = to_intel_crtc(crtc);
struct drm_mode_object *obj;
 
state->changed = true;
 
-   if (prop == prop_src_x) {
+   if (prop == config->src_x_prop) {
crtc->x = value;
-   } else if (prop == prop_src_y) {
+   } else if (prop == config->src_y_prop) {
crtc->y = value;
-   } else if (prop == prop_mode) {
+   } else if (prop == config->mode_prop) {
const struct drm_mode_modeinfo *umode = blob_data;
 
if (value != 0 && value != sizeof *umode) {
@@ -462,7 +446,7 @@ static int crtc_set(struct intel_atomic_state *s,
drm_mode_destroy(crtc->dev, mode);
} else
crtc->enabled = false;
-   } else if (prop == prop_fb_id) {
+   } else if (prop == config->fb_id_prop) {
if (value) {
obj = drm_mode_object_find(crtc->dev, value, 
DRM_MODE_OBJECT_FB);
if (!obj) {
@@ -472,7 +456,7 @@ static int crtc_set(struct intel_atomic_state *s,
crtc->fb = obj_to_fb(obj);
} else
crtc->fb = NULL;
-   } else if (prop == prop_connector_ids) {
+   } else if (prop == config->connector_ids_prop) {
  

[Intel-gfx] [PATCH 48/81] drm/i915: Update CRTC properties after modeset

2012-12-12 Thread ville . syrjala
From: Ville Syrjälä 

Update cursor related CRTC properties after a modeset. The cursor
properties aren't handled by the drm core since not all CRTCs have
cursors.

Signed-off-by: Ville Syrjälä 
---
 drivers/gpu/drm/i915/intel_display.c |   15 +++
 1 files changed, 15 insertions(+), 0 deletions(-)

diff --git a/drivers/gpu/drm/i915/intel_display.c 
b/drivers/gpu/drm/i915/intel_display.c
index 566bf29..321c840 100644
--- a/drivers/gpu/drm/i915/intel_display.c
+++ b/drivers/gpu/drm/i915/intel_display.c
@@ -6368,6 +6368,8 @@ static int intel_crtc_cursor_set(struct drm_crtc *crtc,
if (old_obj)
intel_crtc_cursor_bo_unref(crtc, old_obj);
 
+   intel_crtc_update_properties(crtc);
+
return 0;
 }
 
@@ -6380,6 +6382,8 @@ static int intel_crtc_cursor_move(struct drm_crtc *crtc, 
int x, int y)
 
intel_crtc_update_cursor(crtc, true);
 
+   intel_crtc_update_properties(crtc);
+
return 0;
 }
 
@@ -7341,6 +7345,8 @@ static int intel_crtc_page_flip(struct drm_crtc *crtc,
 
trace_i915_flip_request(intel_crtc->plane, obj);
 
+   intel_crtc_update_properties(crtc);
+
return 0;
 
 cleanup_pending:
@@ -8067,6 +8073,7 @@ next_encoder:
 static int intel_crtc_set_config(struct drm_mode_set *set)
 {
struct drm_device *dev;
+   struct drm_crtc *crtc;
struct drm_mode_set save_set;
struct intel_set_config *config;
int ret;
@@ -8140,6 +8147,10 @@ static int intel_crtc_set_config(struct drm_mode_set 
*set)
 
intel_set_config_free(config);
 
+   /* changes in one CRTC can affect the others */
+   list_for_each_entry(crtc, &dev->mode_config.crtc_list, head)
+   intel_crtc_update_properties(crtc);
+
return 0;
 
 fail:
@@ -8151,6 +8162,10 @@ fail:
save_set.x, save_set.y, save_set.fb))
DRM_ERROR("failed to restore config after modeset failure\n");
 
+   /* changes in one CRTC can affect the others */
+   list_for_each_entry(crtc, &dev->mode_config.crtc_list, head)
+   intel_crtc_update_properties(crtc);
+
 out_config:
intel_set_config_free(config);
return ret;
-- 
1.7.8.6

___
Intel-gfx mailing list
Intel-gfx@lists.freedesktop.org
http://lists.freedesktop.org/mailman/listinfo/intel-gfx


[Intel-gfx] [PATCH 43/81] drm/i915: Clear flip helpers for sprites too

2012-12-12 Thread ville . syrjala
From: Ville Syrjälä 

Don't leave stale flips hanging around the sprites' flip helpers
when the crtc is being disabled.

Signed-off-by: Ville Syrjälä 
---
 drivers/gpu/drm/i915/intel_atomic.c  |   15 +++
 drivers/gpu/drm/i915/intel_display.c |4 ++--
 drivers/gpu/drm/i915/intel_drv.h |1 +
 3 files changed, 18 insertions(+), 2 deletions(-)

diff --git a/drivers/gpu/drm/i915/intel_atomic.c 
b/drivers/gpu/drm/i915/intel_atomic.c
index 41885fa..41fd0d5 100644
--- a/drivers/gpu/drm/i915/intel_atomic.c
+++ b/drivers/gpu/drm/i915/intel_atomic.c
@@ -2449,3 +2449,18 @@ void intel_atomic_handle_vblank(struct drm_device *dev, 
int pipe)
drm_flip_helper_vblank(&intel_plane->flip_helper);
}
 }
+
+void intel_atomic_clear_flips(struct drm_crtc *crtc)
+{
+   struct drm_device *dev = crtc->dev;
+   struct intel_crtc *intel_crtc = to_intel_crtc(crtc);
+   struct intel_plane *intel_plane;
+   int pipe = intel_crtc->pipe;
+
+   drm_flip_helper_clear(&intel_crtc->flip_helper);
+
+   list_for_each_entry(intel_plane, &dev->mode_config.plane_list, 
base.head) {
+   if (intel_plane->pipe == pipe)
+   drm_flip_helper_clear(&intel_plane->flip_helper);
+   }
+}
diff --git a/drivers/gpu/drm/i915/intel_display.c 
b/drivers/gpu/drm/i915/intel_display.c
index 9903456..566bf29 100644
--- a/drivers/gpu/drm/i915/intel_display.c
+++ b/drivers/gpu/drm/i915/intel_display.c
@@ -3566,7 +3566,7 @@ static void haswell_crtc_disable(struct drm_crtc *crtc)
encoder->disable(encoder);
 
intel_crtc_wait_for_pending_flips(crtc);
-   drm_flip_helper_clear(&intel_crtc->flip_helper);
+   intel_atomic_clear_flips(crtc);
drm_vblank_off(dev, pipe);
intel_crtc_update_cursor(crtc, false);
 
@@ -3688,7 +3688,7 @@ static void i9xx_crtc_disable(struct drm_crtc *crtc)
 
/* Give the overlay scaler a chance to disable if it's on this pipe */
intel_crtc_wait_for_pending_flips(crtc);
-   drm_flip_helper_clear(&intel_crtc->flip_helper);
+   intel_atomic_clear_flips(crtc);
drm_vblank_off(dev, pipe);
intel_crtc_dpms_overlay(intel_crtc, false);
intel_crtc_update_cursor(crtc, false);
diff --git a/drivers/gpu/drm/i915/intel_drv.h b/drivers/gpu/drm/i915/intel_drv.h
index 92a9518..5b0789f 100644
--- a/drivers/gpu/drm/i915/intel_drv.h
+++ b/drivers/gpu/drm/i915/intel_drv.h
@@ -729,6 +729,7 @@ extern int intel_atomic_init(struct drm_device *dev);
 extern void intel_atomic_fini(struct drm_device *dev);
 extern void intel_atomic_free_events(struct drm_device *dev, struct drm_file 
*file);
 extern void intel_atomic_handle_vblank(struct drm_device *dev, int pipe);
+extern void intel_atomic_clear_flips(struct drm_crtc *crtc);
 
 extern void intel_enable_primary(struct drm_crtc *crtc);
 extern void intel_disable_primary(struct drm_crtc *crtc);
-- 
1.7.8.6

___
Intel-gfx mailing list
Intel-gfx@lists.freedesktop.org
http://lists.freedesktop.org/mailman/listinfo/intel-gfx


[Intel-gfx] [PATCH 51/81] drm/i915: Unstatic intel_modeset_update_staged_output_state()

2012-12-12 Thread ville . syrjala
From: Ville Syrjälä 

The atomic code needs intel_modeset_update_staged_output_state().

Signed-off-by: Ville Syrjälä 
---
 drivers/gpu/drm/i915/intel_display.c |2 +-
 drivers/gpu/drm/i915/intel_drv.h |2 ++
 2 files changed, 3 insertions(+), 1 deletions(-)

diff --git a/drivers/gpu/drm/i915/intel_display.c 
b/drivers/gpu/drm/i915/intel_display.c
index 451cc3d..c84a839 100644
--- a/drivers/gpu/drm/i915/intel_display.c
+++ b/drivers/gpu/drm/i915/intel_display.c
@@ -7423,7 +7423,7 @@ static bool intel_encoder_crtc_ok(struct drm_encoder 
*encoder,
  * Updates the staged output configuration state, e.g. after we've read out the
  * current hw state.
  */
-static void intel_modeset_update_staged_output_state(struct drm_device *dev)
+void intel_modeset_update_staged_output_state(struct drm_device *dev)
 {
struct intel_encoder *encoder;
struct intel_connector *connector;
diff --git a/drivers/gpu/drm/i915/intel_drv.h b/drivers/gpu/drm/i915/intel_drv.h
index 1230c1b..24dc192 100644
--- a/drivers/gpu/drm/i915/intel_drv.h
+++ b/drivers/gpu/drm/i915/intel_drv.h
@@ -737,4 +737,6 @@ extern void intel_disable_primary(struct drm_crtc *crtc);
 extern void intel_crtc_attach_properties(struct drm_crtc *crtc);
 extern void intel_crtc_update_properties(struct drm_crtc *crtc);
 
+extern void intel_modeset_update_staged_output_state(struct drm_device *dev);
+
 #endif /* __INTEL_DRV_H__ */
-- 
1.7.8.6

___
Intel-gfx mailing list
Intel-gfx@lists.freedesktop.org
http://lists.freedesktop.org/mailman/listinfo/intel-gfx


[Intel-gfx] [PATCH 52/81] drm/i915: Update new_crtc and new_encoder fields after atomic modeset

2012-12-12 Thread ville . syrjala
From: Ville Syrjälä 

The i915 modeset logic requires that these be kept in sync with
the other crtc and encoder pointers.

Signed-off-by: Ville Syrjälä 
---
 drivers/gpu/drm/i915/intel_atomic.c |2 ++
 1 files changed, 2 insertions(+), 0 deletions(-)

diff --git a/drivers/gpu/drm/i915/intel_atomic.c 
b/drivers/gpu/drm/i915/intel_atomic.c
index e58ec3f..c5558cc 100644
--- a/drivers/gpu/drm/i915/intel_atomic.c
+++ b/drivers/gpu/drm/i915/intel_atomic.c
@@ -1701,6 +1701,8 @@ static int intel_atomic_commit(struct drm_device *dev, 
void *state)
 
update_props(dev, s);
 
+   intel_modeset_update_staged_output_state(dev);
+
return 0;
 }
 
-- 
1.7.8.6

___
Intel-gfx mailing list
Intel-gfx@lists.freedesktop.org
http://lists.freedesktop.org/mailman/listinfo/intel-gfx


[Intel-gfx] [PATCH 47/81] drm: Update standard plane properties after update_plane/disable_plane

2012-12-12 Thread ville . syrjala
From: Ville Syrjälä 

Keep the new plane properties when doing operations through the legacy
code paths.

Signed-off-by: Ville Syrjälä 
---
 drivers/gpu/drm/drm_crtc.c |6 ++
 1 files changed, 6 insertions(+), 0 deletions(-)

diff --git a/drivers/gpu/drm/drm_crtc.c b/drivers/gpu/drm/drm_crtc.c
index 897ff46..9d8738f 100644
--- a/drivers/gpu/drm/drm_crtc.c
+++ b/drivers/gpu/drm/drm_crtc.c
@@ -407,6 +407,8 @@ void drm_framebuffer_remove(struct drm_framebuffer *fb)
/* disconnect the plane from the fb and crtc: */
plane->fb = NULL;
plane->crtc = NULL;
+
+   drm_plane_update_properties(plane);
}
}
 
@@ -1780,6 +1782,8 @@ int drm_mode_setplane(struct drm_device *dev, void *data,
plane->funcs->disable_plane(plane);
plane->crtc = NULL;
plane->fb = NULL;
+
+   drm_plane_update_properties(plane);
goto out;
}
 
@@ -1863,6 +1867,8 @@ int drm_mode_setplane(struct drm_device *dev, void *data,
plane->src_y = plane_req->src_y;
plane->src_w = plane_req->src_w;
plane->src_h = plane_req->src_h;
+
+   drm_plane_update_properties(plane);
}
 
 out:
-- 
1.7.8.6

___
Intel-gfx mailing list
Intel-gfx@lists.freedesktop.org
http://lists.freedesktop.org/mailman/listinfo/intel-gfx


[Intel-gfx] [PATCH 44/81] drm/i915: Refactor property handling in atomic code

2012-12-12 Thread ville . syrjala
From: Ville Syrjälä 

Move the property code around a bit to make it easier to move it out to
the drm core later.

Signed-off-by: Ville Syrjälä 
---
 drivers/gpu/drm/i915/intel_atomic.c |  423 ---
 drivers/gpu/drm/i915/intel_drv.h|3 +
 include/drm/drm_crtc.h  |   12 +
 3 files changed, 252 insertions(+), 186 deletions(-)

diff --git a/drivers/gpu/drm/i915/intel_atomic.c 
b/drivers/gpu/drm/i915/intel_atomic.c
index 41fd0d5..0e37cf5 100644
--- a/drivers/gpu/drm/i915/intel_atomic.c
+++ b/drivers/gpu/drm/i915/intel_atomic.c
@@ -1473,87 +1473,6 @@ static int intel_atomic_check(struct drm_device *dev, 
void *state)
return 0;
 }
 
-static void update_plane_props(struct drm_plane *plane)
-{
-   struct drm_mode_object *obj = &plane->base;
-
-   drm_object_property_set_value(obj, prop_src_x, plane->src_x);
-   drm_object_property_set_value(obj, prop_src_y, plane->src_y);
-   drm_object_property_set_value(obj, prop_src_w, plane->src_w);
-   drm_object_property_set_value(obj, prop_src_h, plane->src_h);
-
-   drm_object_property_set_value(obj, prop_crtc_x, plane->crtc_x);
-   drm_object_property_set_value(obj, prop_crtc_y, plane->crtc_y);
-   drm_object_property_set_value(obj, prop_crtc_w, plane->crtc_w);
-   drm_object_property_set_value(obj, prop_crtc_h, plane->crtc_h);
-
-   drm_object_property_set_value(obj, prop_fb_id, plane->fb ? 
plane->fb->base.id : 0);
-   drm_object_property_set_value(obj, prop_crtc_id, plane->crtc ? 
plane->crtc->base.id : 0);
-}
-
-static int update_prop_connector_ids(struct drm_crtc *crtc)
-{
-   struct drm_device *dev = crtc->dev;
-   struct drm_connector *connector;
-   uint64_t value = 0;
-   int i = 0;
-   uint32_t connector_ids[dev->mode_config.num_connector];
-
-   list_for_each_entry(connector, &dev->mode_config.connector_list, head) {
-   if (connector->encoder && connector->encoder->crtc == crtc)
-   connector_ids[i++] = connector->base.id;
-   }
-
-   if (i) {
-   drm_property_blob_replace_data(crtc->connector_ids_blob,
-  i * sizeof connector_ids[0], 
connector_ids);
-   value = crtc->connector_ids_blob->base.id;
-   } else
-   drm_property_blob_replace_data(crtc->connector_ids_blob, 0, 
NULL);
-
-   drm_object_property_set_value(&crtc->base, prop_connector_ids, value);
-
-   return 0;
-}
-
-static int update_prop_mode(struct drm_crtc *crtc)
-{
-   uint64_t value = 0;
-
-   if (crtc->enabled) {
-   struct drm_mode_modeinfo umode;
-
-   drm_crtc_convert_to_umode(&umode, &crtc->mode);
-   drm_property_blob_replace_data(crtc->mode_blob, sizeof umode, 
&umode);
-   value = crtc->mode_blob->base.id;
-   } else
-   drm_property_blob_replace_data(crtc->mode_blob, 0, NULL);
-
-   drm_object_property_set_value(&crtc->base, prop_mode, value);
-
-   return 0;
-}
-
-static void update_crtc_props(struct drm_crtc *crtc)
-{
-   struct drm_mode_object *obj = &crtc->base;
-   struct intel_crtc *intel_crtc = to_intel_crtc(crtc);
-
-   drm_object_property_set_value(obj, prop_src_x, crtc->x);
-   drm_object_property_set_value(obj, prop_src_y, crtc->y);
-
-   drm_object_property_set_value(obj, prop_fb_id, crtc->fb ? 
crtc->fb->base.id : 0);
-
-   drm_object_property_set_value(obj, prop_cursor_id, 
intel_crtc->cursor_handle);
-   drm_object_property_set_value(obj, prop_cursor_x, intel_crtc->cursor_x);
-   drm_object_property_set_value(obj, prop_cursor_y, intel_crtc->cursor_y);
-   drm_object_property_set_value(obj, prop_cursor_w, 
intel_crtc->cursor_width);
-   drm_object_property_set_value(obj, prop_cursor_h, 
intel_crtc->cursor_height);
-
-   update_prop_mode(crtc);
-   update_prop_connector_ids(crtc);
-}
-
 static void update_props(struct drm_device *dev,
 struct intel_atomic_state *s)
 {
@@ -1565,7 +1484,7 @@ static void update_props(struct drm_device *dev,
if (!st->fb_dirty && !st->mode_dirty)
continue;
 
-   update_crtc_props(st->crtc);
+   intel_crtc_update_properties(st->crtc);
}
 
for (i = 0; i < dev->mode_config.num_plane; i++) {
@@ -1574,7 +1493,7 @@ static void update_props(struct drm_device *dev,
if (!st->dirty)
continue;
 
-   update_plane_props(st->plane);
+   drm_plane_update_properties(st->plane);
}
 }
 
@@ -1829,32 +1748,6 @@ static const struct drm_atomic_funcs intel_atomic_funcs 
= {
.end = intel_atomic_end,
 };
 
-static struct {
-   struct drm_property **prop;
-   const char *name;
-   uint64_t min;
-   uint64_t max;
-} props[] = {
-   { &prop_src_x, "SRC_X", 0, UINT_MAX },
-   { &prop_src_y, "

[Intel-gfx] [PATCH 54/81] drm/i915: Kill the pending_flip counter manipulations

2012-12-12 Thread ville . syrjala
From: Ville Syrjälä 

The pending_flip counter is probably going to be remove entirely,
along with i915_gem_execbuffer_wait_for_flips() so don't even try to
use it.

Signed-off-by: Ville Syrjälä 
---
 drivers/gpu/drm/i915/intel_atomic.c |   74 +--
 1 files changed, 2 insertions(+), 72 deletions(-)

diff --git a/drivers/gpu/drm/i915/intel_atomic.c 
b/drivers/gpu/drm/i915/intel_atomic.c
index 1fce359..ac7fe88 100644
--- a/drivers/gpu/drm/i915/intel_atomic.c
+++ b/drivers/gpu/drm/i915/intel_atomic.c
@@ -1536,45 +1536,9 @@ static void atomic_pipe_commit(struct drm_device *dev,
   struct intel_atomic_state *state,
   int pipe);
 
-static int apply_nonblocking(struct drm_device *dev, struct intel_atomic_state 
*s)
+static void apply_nonblocking(struct drm_device *dev, struct 
intel_atomic_state *s)
 {
struct intel_crtc *intel_crtc;
-   int i;
-
-   for (i = 0; i < dev->mode_config.num_crtc; i++) {
-   struct intel_crtc_state *st = &s->crtc[i];
-   struct intel_crtc *intel_crtc = to_intel_crtc(st->crtc);
-   struct drm_i915_gem_object *obj;
-
-   if (!st->old.fb)
-   continue;
-
-   obj = to_intel_framebuffer(st->old.fb)->obj;
-
-   /* Only one bit per plane in pending_flips */
-   if (atomic_read(&obj->pending_flip) & (1 << intel_crtc->plane))
-   return -EBUSY;
-   }
-
-   for (i = 0; i < dev->mode_config.num_plane; i++) {
-   struct intel_plane_state *st = &s->plane[i];
-   struct intel_plane *intel_plane = to_intel_plane(st->plane);
-   struct drm_i915_gem_object *obj;
-
-   if (!st->old.fb)
-   continue;
-
-   obj = to_intel_framebuffer(st->old.fb)->obj;
-
-   if (!st->old.fb)
-   continue;
-
-   obj = to_intel_framebuffer(st->old.fb)->obj;
-
-   /* Only one bit per plane in pending_flips */
-   if (atomic_read(&obj->pending_flip) & (1 << (16 + 
intel_plane->pipe)))
-   return -EBUSY;
-   }
 
list_for_each_entry(intel_crtc, &dev->mode_config.crtc_list, base.head)
atomic_pipe_commit(dev, s, intel_crtc->pipe);
@@ -1582,8 +1546,6 @@ static int apply_nonblocking(struct drm_device *dev, 
struct intel_atomic_state *
/* don't restore the old state in end() */
s->dirty = false;
s->restore_state = false;
-
-   return 0;
 }
 
 static int alloc_flip_data(struct drm_device *dev, struct intel_atomic_state 
*s)
@@ -1695,12 +1657,7 @@ static int intel_atomic_commit(struct drm_device *dev, 
void *state)
 
/* try to apply in a non blocking manner */
if (s->flags & DRM_MODE_ATOMIC_NONBLOCK) {
-   ret = apply_nonblocking(dev, s);
-   if (ret) {
-   unpin_cursors(dev, s);
-   unpin_fbs(dev, s);
-   return ret;
-   }
+   apply_nonblocking(dev, s);
} else {
/* apply in a blocking manner */
ret = apply_config(dev, s);
@@ -1823,7 +1780,6 @@ static void intel_flip_complete(struct drm_flip *flip)
struct intel_flip *intel_flip =
container_of(flip, struct intel_flip, base);
struct drm_device *dev = intel_flip->crtc->dev;
-   struct drm_i915_private *dev_priv = dev->dev_private;
struct drm_crtc *crtc = intel_flip->crtc;
struct intel_crtc *intel_crtc = to_intel_crtc(crtc);
int pipe = intel_crtc->pipe;
@@ -1841,18 +1797,6 @@ static void intel_flip_complete(struct drm_flip *flip)
 
if (intel_flip->vblank_ref)
drm_vblank_put(dev, pipe);
-
-   /* Possibly allow rendering to old_bo again */
-   if (intel_flip->old_bo) {
-   if (intel_flip->plane) {
-   struct intel_plane *intel_plane = 
to_intel_plane(intel_flip->plane);
-   atomic_clear_mask(1 << (16 + intel_plane->pipe), 
&intel_flip->old_bo->pending_flip.counter);
-   } else
-   atomic_clear_mask(1 << intel_crtc->plane, 
&intel_flip->old_bo->pending_flip.counter);
-
-   if (atomic_read(&intel_flip->old_bo->pending_flip) == 0)
-   wake_up(&dev_priv->pending_flip_queue);
-   }
 }
 
 static void intel_flip_finish(struct drm_flip *flip)
@@ -2193,13 +2137,6 @@ static void atomic_pipe_commit(struct drm_device *dev,
mutex_lock(&dev->struct_mutex);
drm_gem_object_reference(&intel_flip->old_bo->base);
mutex_unlock(&dev->struct_mutex);
-
-   /*
-* Block clients from rendering to the new back buffer 
until
-* the flip occurs and the object is 

[Intel-gfx] [PATCH 49/81] drm: Move standard crtc/plane prop handling to drm_crtc.c

2012-12-12 Thread ville . syrjala
From: Ville Syrjälä 

Move some of the property code to drm_crtc.c since it should be shared
by everyone.

Signed-off-by: Ville Syrjälä 
---
 drivers/gpu/drm/drm_crtc.c   |  235 +++
 drivers/gpu/drm/i915/intel_atomic.c  |  256 --
 drivers/gpu/drm/i915/intel_display.c |   29 
 3 files changed, 264 insertions(+), 256 deletions(-)

diff --git a/drivers/gpu/drm/drm_crtc.c b/drivers/gpu/drm/drm_crtc.c
index 9d8738f..527b35b 100644
--- a/drivers/gpu/drm/drm_crtc.c
+++ b/drivers/gpu/drm/drm_crtc.c
@@ -4397,3 +4397,238 @@ int drm_mode_atomic_ioctl(struct drm_device *dev,
 
return ret;
 }
+
+static void drm_crtc_update_connector_ids_property(struct drm_crtc *crtc)
+{
+   struct drm_mode_config *config = &crtc->dev->mode_config;
+   struct drm_connector *connector;
+   uint64_t value = 0;
+   int i = 0;
+   uint32_t connector_ids[config->num_connector];
+
+   list_for_each_entry(connector, &config->connector_list, head) {
+   if (connector->encoder && connector->encoder->crtc == crtc)
+   connector_ids[i++] = connector->base.id;
+   }
+
+   if (i) {
+   drm_property_blob_replace_data(crtc->connector_ids_blob,
+  i * sizeof connector_ids[0], 
connector_ids);
+   value = crtc->connector_ids_blob->base.id;
+   } else
+   drm_property_blob_replace_data(crtc->connector_ids_blob, 0, 
NULL);
+
+   drm_object_property_set_value(&crtc->base, config->connector_ids_prop, 
value);
+}
+
+static void drm_crtc_update_mode_property(struct drm_crtc *crtc)
+{
+   struct drm_mode_config *config = &crtc->dev->mode_config;
+   uint64_t value = 0;
+
+   if (crtc->enabled) {
+   struct drm_mode_modeinfo umode;
+
+   drm_crtc_convert_to_umode(&umode, &crtc->mode);
+   drm_property_blob_replace_data(crtc->mode_blob, sizeof umode, 
&umode);
+   value = crtc->mode_blob->base.id;
+   } else
+   drm_property_blob_replace_data(crtc->mode_blob, 0, NULL);
+
+   drm_object_property_set_value(&crtc->base, config->mode_prop, value);
+}
+
+void drm_crtc_update_properties(struct drm_crtc *crtc)
+{
+   struct drm_mode_object *obj = &crtc->base;
+   struct drm_mode_config *config = &crtc->dev->mode_config;
+
+   drm_object_property_set_value(obj, config->src_x_prop, crtc->x);
+   drm_object_property_set_value(obj, config->src_y_prop, crtc->y);
+   drm_object_property_set_value(obj, config->fb_id_prop, crtc->fb ? 
crtc->fb->base.id : 0);
+
+   drm_crtc_update_mode_property(crtc);
+   drm_crtc_update_connector_ids_property(crtc);
+}
+EXPORT_SYMBOL(drm_crtc_update_properties);
+
+void drm_plane_update_properties(struct drm_plane *plane)
+{
+   struct drm_mode_object *obj = &plane->base;
+   struct drm_mode_config *config = &plane->dev->mode_config;
+
+   drm_object_property_set_value(obj, config->src_x_prop, plane->src_x);
+   drm_object_property_set_value(obj, config->src_y_prop, plane->src_y);
+   drm_object_property_set_value(obj, config->src_w_prop, plane->src_w);
+   drm_object_property_set_value(obj, config->src_h_prop, plane->src_h);
+
+   drm_object_property_set_value(obj, config->crtc_x_prop, plane->crtc_x);
+   drm_object_property_set_value(obj, config->crtc_y_prop, plane->crtc_y);
+   drm_object_property_set_value(obj, config->crtc_w_prop, plane->crtc_w);
+   drm_object_property_set_value(obj, config->crtc_h_prop, plane->crtc_h);
+
+   drm_object_property_set_value(obj, config->fb_id_prop, plane->fb ? 
plane->fb->base.id : 0);
+   drm_object_property_set_value(obj, config->crtc_id_prop, plane->crtc ? 
plane->crtc->base.id : 0);
+}
+EXPORT_SYMBOL(drm_plane_update_properties);
+
+int drm_crtc_create_blobs(struct drm_crtc *crtc)
+{
+   struct drm_device *dev = crtc->dev;
+
+   crtc->mode_blob = drm_property_create_blob(dev, 0, sizeof(struct 
drm_mode_modeinfo), NULL);
+   if (!crtc->mode_blob)
+   return -ENOMEM;
+
+   crtc->connector_ids_blob = drm_property_create_blob(dev, 0, 
dev->mode_config.num_connector * sizeof(uint32_t), NULL);
+   if (!crtc->connector_ids_blob)
+   return -ENOMEM;
+
+   return 0;
+}
+EXPORT_SYMBOL(drm_crtc_create_blobs);
+
+void drm_crtc_destroy_blobs(struct drm_crtc *crtc)
+{
+   struct drm_device *dev = crtc->dev;
+
+   drm_property_destroy_blob(dev, crtc->mode_blob);
+   drm_property_destroy_blob(dev, crtc->connector_ids_blob);
+}
+EXPORT_SYMBOL(drm_crtc_destroy_blobs);
+
+static void drm_property_destroy_null(struct drm_device *dev, struct 
drm_property **prop)
+{
+   drm_property_destroy(dev, *prop);
+   *prop = NULL;
+}
+
+void drm_mode_destroy_properties(struct drm_device *dev)
+{
+   struct drm_mode_config *config = &dev->mode_config;
+
+   drm_property_destroy

[Intel-gfx] [PATCH 50/81] drm/i915: Use intel_best_encoder() directly

2012-12-12 Thread ville . syrjala
From: Ville Syrjälä 

All connectors use intel_best_encoder() as their best_encoder() func, so
just call it directly w/o the indirection.

Signed-off-by: Ville Syrjälä 
---
 drivers/gpu/drm/i915/intel_atomic.c |   10 ++
 1 files changed, 2 insertions(+), 8 deletions(-)

diff --git a/drivers/gpu/drm/i915/intel_atomic.c 
b/drivers/gpu/drm/i915/intel_atomic.c
index 6dd07fb..e58ec3f 100644
--- a/drivers/gpu/drm/i915/intel_atomic.c
+++ b/drivers/gpu/drm/i915/intel_atomic.c
@@ -152,8 +152,6 @@ static int process_connectors(struct intel_crtc_state *s, 
const uint32_t *ids, i
int i;
 
for (i = 0; i < count_ids; i++) {
-   struct drm_encoder *encoder;
-   const struct drm_connector_helper_funcs *connector_funcs;
struct drm_mode_object *obj;
int j;
 
@@ -169,9 +167,8 @@ static int process_connectors(struct intel_crtc_state *s, 
const uint32_t *ids, i
}
 
connector = obj_to_connector(obj);
-   connector_funcs = connector->helper_private;
 
-   encoder = connector_funcs->best_encoder(connector);
+   encoder = intel_best_encoder(connector);
 
if (!drm_encoder_crtc_ok(encoder, crtc))
return -EINVAL;
@@ -180,9 +177,6 @@ static int process_connectors(struct intel_crtc_state *s, 
const uint32_t *ids, i
}
 
list_for_each_entry(connector, &dev->mode_config.connector_list, head) {
-   const struct drm_connector_helper_funcs *connector_funcs =
-   connector->helper_private;
-
for (i = 0; i < count_ids; i++) {
if (connector == connectors[i])
break;
@@ -196,7 +190,7 @@ static int process_connectors(struct intel_crtc_state *s, 
const uint32_t *ids, i
continue;
}
 
-   encoder = connector_funcs->best_encoder(connector);
+   encoder = intel_best_encoder(connector);
 
connector->encoder = encoder;
encoder->crtc = crtc;
-- 
1.7.8.6

___
Intel-gfx mailing list
Intel-gfx@lists.freedesktop.org
http://lists.freedesktop.org/mailman/listinfo/intel-gfx


[Intel-gfx] [PATCH 46/81] drm_crtc_helper: Update standard crtc properties after modeset

2012-12-12 Thread ville . syrjala
From: Ville Syrjälä 

Keep the new CRTC properties when doing modeset through the legacy code
paths.

Signed-off-by: Ville Syrjälä 
---
 drivers/gpu/drm/drm_crtc_helper.c |   10 ++
 1 files changed, 10 insertions(+), 0 deletions(-)

diff --git a/drivers/gpu/drm/drm_crtc_helper.c 
b/drivers/gpu/drm/drm_crtc_helper.c
index 30eb557..19444cd 100644
--- a/drivers/gpu/drm/drm_crtc_helper.c
+++ b/drivers/gpu/drm/drm_crtc_helper.c
@@ -782,6 +782,11 @@ int drm_crtc_helper_set_config(struct drm_mode_set *set)
kfree(save_connectors);
kfree(save_encoders);
kfree(save_crtcs);
+
+   /* changes in one CRTC can affect the others */
+   list_for_each_entry(crtc, &dev->mode_config.crtc_list, head)
+   drm_crtc_update_properties(crtc);
+
return 0;
 
 fail:
@@ -810,6 +815,11 @@ fail:
kfree(save_connectors);
kfree(save_encoders);
kfree(save_crtcs);
+
+   /* changes in one CRTC can affect the others */
+   list_for_each_entry(crtc, &dev->mode_config.crtc_list, head)
+   drm_crtc_update_properties(crtc);
+
return ret;
 }
 EXPORT_SYMBOL(drm_crtc_helper_set_config);
-- 
1.7.8.6

___
Intel-gfx mailing list
Intel-gfx@lists.freedesktop.org
http://lists.freedesktop.org/mailman/listinfo/intel-gfx


  1   2   >