[Bug 119211] amdgpu disables fan by default

2016-05-29 Thread bugzilla-dae...@bugzilla.kernel.org
https://bugzilla.kernel.org/show_bug.cgi?id=119211

--- Comment #2 from Stas Sergeev  ---
Even besides the fact that GPU was so hot I
couldn't even touch it?

-- 
You are receiving this mail because:
You are watching the assignee of the bug.


[Bug 119211] amdgpu disables fan by default

2016-05-29 Thread bugzilla-dae...@bugzilla.kernel.org
https://bugzilla.kernel.org/show_bug.cgi?id=119211

--- Comment #1 from Vedran Miletić  ---
You should produce some GPU load before the fan activates.

-- 
You are receiving this mail because:
You are watching the assignee of the bug.


[Bug 119211] New: amdgpu disables fan by default

2016-05-29 Thread bugzilla-dae...@bugzilla.kernel.org
https://bugzilla.kernel.org/show_bug.cgi?id=119211

Bug ID: 119211
   Summary: amdgpu disables fan by default
   Product: Drivers
   Version: 2.5
Kernel Version: 4.5.5
  Hardware: All
OS: Linux
  Tree: Fedora
Status: NEW
  Severity: normal
  Priority: P1
 Component: Video(DRI - non Intel)
  Assignee: drivers_video-dri at kernel-bugs.osdl.org
  Reporter: stsp at list.ru
Regression: No

I have radeon R9 380.
After the KMS driver activates, the fans on
the GPU stops. They can be activated again by
properly setting up fancontrol, but this wasn't
configured on my PC. As the result, for the last
few years I have replaced many motherboards, all
starting to have bad capacitors around the video
card. But only now I have noticed that the fans
are not rotating... :(

The driver should activate fans by default, or
don't touch the initial settings (fans are rotating
before linux have started), but not stop them by default.

-- 
You are receiving this mail because:
You are watching the assignee of the bug.


[PATCH v2] gpu: drm: amd: amdkfd: Remove create_workqueue()

2016-05-29 Thread Bhaktipriya Shridhar
Thanks Oded. Sending v3 right away :)

On Sun, May 29, 2016 at 8:31 PM, Oded Gabbay  wrote:
> On Thu, May 26, 2016 at 10:37 PM, Bhaktipriya Shridhar
>  wrote:
>> alloc_workqueue replaces deprecated create_workqueue().
>>
>> create_workqueue has been replaced with alloc_workqueue with max_active
>> as 0 since there is no need for throttling the number of active work items.
>>
>> WQ_MEM_RECLAIM has not been set to because kfd_process_wq will not be used in
>> memory reclaim path.
>>
>> kfd_process_wq is used for delay destruction. A work item embedded in
>> kfd_process gets queued to kfd_process_wq and when it executes it
>> destroys and frees the containing kfd_process and thus itself.
>>
>> This requires a dedicated workqueue because a work item once queued, may
>> get freed at any point of time and any external entity cannot
>> flush the work item. So, in order to wait for such a work item,
>> it needs to be put on a dedicated workqueue.
>>
>> kfd_module_exit() calls kfd_process_destroy_wq which ensures that all
>> pending work items are finished before the module is removed.
>>
>> flush_workqueue is unnecessary since destroy_workqueue() itself calls
>> drain_workqueue() which flushes repeatedly till the workqueue becomes empty.
>>
>> Hence flush_workqueue has been removed.
>>
>> Signed-off-by: Bhaktipriya Shridhar 
>> ---
>>  Changes in v2:
>> - added explanation for setting concurrency value to
>>   WQ_DFL_ACTIVE
>> - added explanation for dropping WQ_MEM_RECLAIM
>>
>>  drivers/gpu/drm/amd/amdkfd/kfd_process.c | 3 +--
>>  1 file changed, 1 insertion(+), 2 deletions(-)
>>
>> diff --git a/drivers/gpu/drm/amd/amdkfd/kfd_process.c 
>> b/drivers/gpu/drm/amd/amdkfd/kfd_process.c
>> index ac00579..b21d3fc8 100644
>> --- a/drivers/gpu/drm/amd/amdkfd/kfd_process.c
>> +++ b/drivers/gpu/drm/amd/amdkfd/kfd_process.c
>> @@ -63,13 +63,12 @@ static struct kfd_process *create_process(const struct 
>> task_struct *thread);
>>  void kfd_process_create_wq(void)
>>  {
>> if (!kfd_process_wq)
>> -   kfd_process_wq = create_workqueue("kfd_process_wq");
>> +   kfd_process_wq = alloc_workqueue("kfd_process_wq",0,0);
>
> You are missing a space between the arguments. Seem you forgot to run
> checkpatch.pl ;)
>
> Send a new patch and I'll add it to amdkfd's tree.
>
> Thanks,
>
>Oded
>
>>  }
>>
>>  void kfd_process_destroy_wq(void)
>>  {
>> if (kfd_process_wq) {
>> -   flush_workqueue(kfd_process_wq);
>> destroy_workqueue(kfd_process_wq);
>> kfd_process_wq = NULL;
>> }
>> --
>> 2.1.4
>>


[Bug 96271] TF2: GPU lockup on HD 7950

2016-05-29 Thread bugzilla-dae...@freedesktop.org
https://bugs.freedesktop.org/show_bug.cgi?id=96271

--- Comment #2 from Stephen Liang <hi+freedesktop at stephenliang.pw> ---
One more thing, I did run an apitrace and replayed the apitrace to see if that
reproduces the hang. The replay didn't hang my machine initially but after
running it a 2-3 times, it was able to hang the machine. I would attach the
apitrace but it is 2-3 GB and the hang is several hundreds of thousands of
frames in (and it's not reproducible every time during replay, just sometimes).

-- 
You are receiving this mail because:
You are the assignee for the bug.
-- next part --
An HTML attachment was scrubbed...
URL: 
<https://lists.freedesktop.org/archives/dri-devel/attachments/20160529/3ea313f6/attachment.html>


[PATCH v3] gpu: drm: amd: amdkfd: Remove create_workqueue()

2016-05-29 Thread Bhaktipriya Shridhar
alloc_workqueue replaces deprecated create_workqueue().

create_workqueue has been replaced with alloc_workqueue with max_active
as 0 since there is no need for throttling the number of active work items.

WQ_MEM_RECLAIM has not been set to because kfd_process_wq will not be
used in memory reclaim path.

kfd_process_wq is used for delay destruction. A work item embedded in
kfd_process gets queued to kfd_process_wq and when it executes it
destroys and frees the containing kfd_process and thus itself.

This requires a dedicated workqueue because a work item once queued, may
get freed at any point of time and any external entity cannot
flush the work item. So, in order to wait for such a work item,
it needs to be put on a dedicated workqueue.

kfd_module_exit() calls kfd_process_destroy_wq which ensures that all
pending work items are finished before the module is removed.

flush_workqueue is unnecessary since destroy_workqueue() itself calls
drain_workqueue() which flushes repeatedly till the workqueue
becomes empty.

Hence flush_workqueue has been removed.

Signed-off-by: Bhaktipriya Shridhar 
---
 Changes in v3:
- Corrected space between arguments.

 drivers/gpu/drm/amd/amdkfd/kfd_process.c | 3 +--
 1 file changed, 1 insertion(+), 2 deletions(-)

diff --git a/drivers/gpu/drm/amd/amdkfd/kfd_process.c 
b/drivers/gpu/drm/amd/amdkfd/kfd_process.c
index ac00579..6482fee 100644
--- a/drivers/gpu/drm/amd/amdkfd/kfd_process.c
+++ b/drivers/gpu/drm/amd/amdkfd/kfd_process.c
@@ -63,13 +63,12 @@ static struct kfd_process *create_process(const struct 
task_struct *thread);
 void kfd_process_create_wq(void)
 {
if (!kfd_process_wq)
-   kfd_process_wq = create_workqueue("kfd_process_wq");
+   kfd_process_wq = alloc_workqueue("kfd_process_wq", 0, 0);
 }

 void kfd_process_destroy_wq(void)
 {
if (kfd_process_wq) {
-   flush_workqueue(kfd_process_wq);
destroy_workqueue(kfd_process_wq);
kfd_process_wq = NULL;
}
--
2.1.4



[Bug 96271] TF2: GPU lockup on HD 7950

2016-05-29 Thread bugzilla-dae...@freedesktop.org
https://bugs.freedesktop.org/show_bug.cgi?id=96271

--- Comment #1 from Stephen Liang <hi+freedesktop at stephenliang.pw> ---
Created attachment 124166
  --> https://bugs.freedesktop.org/attachment.cgi?id=124166=edit
output from GALLIUM_DDEBUG="800 noflush" steam steam://rungameid/440

-- 
You are receiving this mail because:
You are the assignee for the bug.
-- next part --
An HTML attachment was scrubbed...
URL: 
<https://lists.freedesktop.org/archives/dri-devel/attachments/20160529/6e116a2b/attachment.html>


[Bug 96271] TF2: GPU lockup on HD 7950

2016-05-29 Thread bugzilla-dae...@freedesktop.org
https://bugs.freedesktop.org/show_bug.cgi?id=96271

Bug ID: 96271
   Summary: TF2: GPU lockup on HD 7950
   Product: Mesa
   Version: git
  Hardware: x86-64 (AMD64)
OS: Linux (All)
Status: NEW
  Severity: normal
  Priority: medium
 Component: Drivers/Gallium/radeonsi
  Assignee: dri-devel at lists.freedesktop.org
  Reporter: hi+freedesktop at stephenliang.pw
QA Contact: dri-devel at lists.freedesktop.org

Created attachment 124165
  --> https://bugs.freedesktop.org/attachment.cgi?id=124165=edit
dmesg on kernel 4.7

I'm getting a GPU lockup on Team Fortress 2 which seems to be related to bug
#80419 since my dmesg is the same as comment #44 but this is occurring on Team
Fortress 2 rather than XCOM.

If I run native TF2 with GALLIUM_DDEBUG=800, I cannot reproduce the bug but the
frame rate drops significantly. With GALLIUM_DDEBUG="800 noflush", I was able
to reproduce the hang. This leads me to believe that the issue is related how
high the FPS is running. 

My kernel is: Linux localhost.localdomain 4.4.9-300.fc23.x86_64
I've also tried 4.6 and 4.7, all of which hangs.

My ATI driver is: 7.7.99-3.20160524git040a7b8.fc23 (latest commit in git for
radeon)
I've also tried 7.6.1-3.20160215gitd41fccc.fc23 (the latest stable from fedora
23), all of which hangs.

My mesa version is: 11.3.0-0.37.git357495b.fc23
I've also tried 11.1.0-2.20151218.fc23 (the latest stable from fedora 23), all
of which hangs.

I've attached the GALLIUM_DDEBUG output and dmesg. One curious thing is that on
kernel 4.7, the kernel detects a hang and is able to reset the GPU resulting in
a temporary freeze that eventually resumes. However, the freeze will come again
after a short while (and resumes).

As a data point, I don't get any lockups while playing Skyrim on Wine.

-- 
You are receiving this mail because:
You are the assignee for the bug.
-- next part --
An HTML attachment was scrubbed...
URL: 
<https://lists.freedesktop.org/archives/dri-devel/attachments/20160529/9758336b/attachment.html>


[PATCH 26/26] drm/virtio: Don't reinvent a flipping wheel

2016-05-29 Thread Daniel Vetter
Now that the core helpers support nonblocking atomic commits there's
no need to invent that wheel separately (instead of fixing the bug in
the atomic implementation of virtio, as it should have been done!).

Cc: Gerd Hoffmann 
Signed-off-by: Daniel Vetter 
---
 drivers/gpu/drm/virtio/virtgpu_display.c | 48 ++--
 1 file changed, 2 insertions(+), 46 deletions(-)

diff --git a/drivers/gpu/drm/virtio/virtgpu_display.c 
b/drivers/gpu/drm/virtio/virtgpu_display.c
index d4305da88f44..325c6f73814b 100644
--- a/drivers/gpu/drm/virtio/virtgpu_display.c
+++ b/drivers/gpu/drm/virtio/virtgpu_display.c
@@ -118,58 +118,13 @@ static int virtio_gpu_crtc_cursor_move(struct drm_crtc 
*crtc,
return 0;
 }

-static int virtio_gpu_page_flip(struct drm_crtc *crtc,
-   struct drm_framebuffer *fb,
-   struct drm_pending_vblank_event *event,
-   uint32_t flags)
-{
-   struct virtio_gpu_device *vgdev = crtc->dev->dev_private;
-   struct virtio_gpu_output *output =
-   container_of(crtc, struct virtio_gpu_output, crtc);
-   struct drm_plane *plane = crtc->primary;
-   struct virtio_gpu_framebuffer *vgfb;
-   struct virtio_gpu_object *bo;
-   unsigned long irqflags;
-   uint32_t handle;
-
-   plane->fb = fb;
-   vgfb = to_virtio_gpu_framebuffer(plane->fb);
-   bo = gem_to_virtio_gpu_obj(vgfb->obj);
-   handle = bo->hw_res_handle;
-
-   DRM_DEBUG("handle 0x%x%s, crtc %dx%d\n", handle,
- bo->dumb ? ", dumb" : "",
- crtc->mode.hdisplay, crtc->mode.vdisplay);
-   if (bo->dumb) {
-   virtio_gpu_cmd_transfer_to_host_2d
-   (vgdev, handle, 0,
-cpu_to_le32(crtc->mode.hdisplay),
-cpu_to_le32(crtc->mode.vdisplay),
-0, 0, NULL);
-   }
-   virtio_gpu_cmd_set_scanout(vgdev, output->index, handle,
-  crtc->mode.hdisplay,
-  crtc->mode.vdisplay, 0, 0);
-   virtio_gpu_cmd_resource_flush(vgdev, handle, 0, 0,
- crtc->mode.hdisplay,
- crtc->mode.vdisplay);
-
-   if (event) {
-   spin_lock_irqsave(>dev->event_lock, irqflags);
-   drm_send_vblank_event(crtc->dev, -1, event);
-   spin_unlock_irqrestore(>dev->event_lock, irqflags);
-   }
-
-   return 0;
-}
-
 static const struct drm_crtc_funcs virtio_gpu_crtc_funcs = {
.cursor_set2= virtio_gpu_crtc_cursor_set,
.cursor_move= virtio_gpu_crtc_cursor_move,
.set_config = drm_atomic_helper_set_config,
.destroy= drm_crtc_cleanup,

-   .page_flip  = virtio_gpu_page_flip,
+   .page_flip  = drm_atomic_helper_page_flip,
.reset  = drm_atomic_helper_crtc_reset,
.atomic_duplicate_state = drm_atomic_helper_crtc_duplicate_state,
.atomic_destroy_state   = drm_atomic_helper_crtc_destroy_state,
@@ -267,6 +222,7 @@ static void virtio_gpu_crtc_atomic_flush(struct drm_crtc 
*crtc,
spin_lock_irqsave(>dev->event_lock, flags);
if (crtc->state->event)
drm_crtc_send_vblank_event(crtc, crtc->state->event);
+   crtc->state->event = NULL;
spin_unlock_irqrestore(>dev->event_lock, flags);
 }

-- 
2.8.1



[PATCH 25/26] drm/rockchip: Nuke pending event handling in preclose

2016-05-29 Thread Daniel Vetter
This is now handled by the core, drivers can totally ignore lifetime
issues of drm events.

Cc: Tomeu Vizoso 
Cc: Mark yao 
Signed-off-by: Daniel Vetter 
---
 drivers/gpu/drm/rockchip/rockchip_drm_drv.c | 22 --
 drivers/gpu/drm/rockchip/rockchip_drm_drv.h |  1 -
 drivers/gpu/drm/rockchip/rockchip_drm_vop.c | 20 
 3 files changed, 43 deletions(-)

diff --git a/drivers/gpu/drm/rockchip/rockchip_drm_drv.c 
b/drivers/gpu/drm/rockchip/rockchip_drm_drv.c
index 2fac6799ceb2..2251121343e6 100644
--- a/drivers/gpu/drm/rockchip/rockchip_drm_drv.c
+++ b/drivers/gpu/drm/rockchip/rockchip_drm_drv.c
@@ -257,27 +257,6 @@ static int rockchip_drm_unload(struct drm_device *drm_dev)
return 0;
 }

-static void rockchip_drm_crtc_cancel_pending_vblank(struct drm_crtc *crtc,
-   struct drm_file *file_priv)
-{
-   struct rockchip_drm_private *priv = crtc->dev->dev_private;
-   int pipe = drm_crtc_index(crtc);
-
-   if (pipe < ROCKCHIP_MAX_CRTC &&
-   priv->crtc_funcs[pipe] &&
-   priv->crtc_funcs[pipe]->cancel_pending_vblank)
-   priv->crtc_funcs[pipe]->cancel_pending_vblank(crtc, file_priv);
-}
-
-static void rockchip_drm_preclose(struct drm_device *dev,
- struct drm_file *file_priv)
-{
-   struct drm_crtc *crtc;
-
-   list_for_each_entry(crtc, >mode_config.crtc_list, head)
-   rockchip_drm_crtc_cancel_pending_vblank(crtc, file_priv);
-}
-
 void rockchip_drm_lastclose(struct drm_device *dev)
 {
struct rockchip_drm_private *priv = dev->dev_private;
@@ -303,7 +282,6 @@ static struct drm_driver rockchip_drm_driver = {
  DRIVER_PRIME | DRIVER_ATOMIC,
.load   = rockchip_drm_load,
.unload = rockchip_drm_unload,
-   .preclose   = rockchip_drm_preclose,
.lastclose  = rockchip_drm_lastclose,
.get_vblank_counter = drm_vblank_no_hw_counter,
.enable_vblank  = rockchip_drm_crtc_enable_vblank,
diff --git a/drivers/gpu/drm/rockchip/rockchip_drm_drv.h 
b/drivers/gpu/drm/rockchip/rockchip_drm_drv.h
index 7684503ff765..005634484441 100644
--- a/drivers/gpu/drm/rockchip/rockchip_drm_drv.h
+++ b/drivers/gpu/drm/rockchip/rockchip_drm_drv.h
@@ -40,7 +40,6 @@ struct rockchip_crtc_funcs {
int (*enable_vblank)(struct drm_crtc *crtc);
void (*disable_vblank)(struct drm_crtc *crtc);
void (*wait_for_update)(struct drm_crtc *crtc);
-   void (*cancel_pending_vblank)(struct drm_crtc *crtc, struct drm_file 
*file_priv);
 };

 struct rockchip_crtc_state {
diff --git a/drivers/gpu/drm/rockchip/rockchip_drm_vop.c 
b/drivers/gpu/drm/rockchip/rockchip_drm_vop.c
index 8cde1ea62978..37a1339c30ae 100644
--- a/drivers/gpu/drm/rockchip/rockchip_drm_vop.c
+++ b/drivers/gpu/drm/rockchip/rockchip_drm_vop.c
@@ -884,30 +884,10 @@ static void vop_crtc_wait_for_update(struct drm_crtc 
*crtc)
WARN_ON(!wait_for_completion_timeout(>wait_update_complete, 100));
 }

-static void vop_crtc_cancel_pending_vblank(struct drm_crtc *crtc,
-  struct drm_file *file_priv)
-{
-   struct drm_device *drm = crtc->dev;
-   struct vop *vop = to_vop(crtc);
-   struct drm_pending_vblank_event *e;
-   unsigned long flags;
-
-   spin_lock_irqsave(>event_lock, flags);
-   e = vop->event;
-   if (e && e->base.file_priv == file_priv) {
-   vop->event = NULL;
-
-   kfree(>base);
-   file_priv->event_space += sizeof(e->event);
-   }
-   spin_unlock_irqrestore(>event_lock, flags);
-}
-
 static const struct rockchip_crtc_funcs private_crtc_funcs = {
.enable_vblank = vop_crtc_enable_vblank,
.disable_vblank = vop_crtc_disable_vblank,
.wait_for_update = vop_crtc_wait_for_update,
-   .cancel_pending_vblank = vop_crtc_cancel_pending_vblank,
 };

 static bool vop_crtc_mode_fixup(struct drm_crtc *crtc,
-- 
2.8.1



[PATCH 24/26] drm/rockchip: convert to helper nonblocking atomic commit

2016-05-29 Thread Daniel Vetter
So totally untested ...

v2: Fixes from Tomeu.

v3: Send out vblank events correctly when shutting down a crtc for
good. This is part of the atomic interface contract.

v4: Properly protect vop->event.

Cc: Tomeu Vizoso 
Cc: Mark yao 
Signed-off-by: Daniel Vetter 
---
 drivers/gpu/drm/rockchip/rockchip_drm_drv.c |  3 --
 drivers/gpu/drm/rockchip/rockchip_drm_drv.h | 10 
 drivers/gpu/drm/rockchip/rockchip_drm_fb.c  | 72 -
 drivers/gpu/drm/rockchip/rockchip_drm_vop.c | 15 +-
 4 files changed, 22 insertions(+), 78 deletions(-)

diff --git a/drivers/gpu/drm/rockchip/rockchip_drm_drv.c 
b/drivers/gpu/drm/rockchip/rockchip_drm_drv.c
index 09a4d429c0f0..2fac6799ceb2 100644
--- a/drivers/gpu/drm/rockchip/rockchip_drm_drv.c
+++ b/drivers/gpu/drm/rockchip/rockchip_drm_drv.c
@@ -145,9 +145,6 @@ static int rockchip_drm_load(struct drm_device *drm_dev, 
unsigned long flags)
if (!private)
return -ENOMEM;

-   mutex_init(>commit.lock);
-   INIT_WORK(>commit.work, rockchip_drm_atomic_work);
-
drm_dev->dev_private = private;

drm_mode_config_init(drm_dev);
diff --git a/drivers/gpu/drm/rockchip/rockchip_drm_drv.h 
b/drivers/gpu/drm/rockchip/rockchip_drm_drv.h
index 56f43a364c7f..7684503ff765 100644
--- a/drivers/gpu/drm/rockchip/rockchip_drm_drv.h
+++ b/drivers/gpu/drm/rockchip/rockchip_drm_drv.h
@@ -43,13 +43,6 @@ struct rockchip_crtc_funcs {
void (*cancel_pending_vblank)(struct drm_crtc *crtc, struct drm_file 
*file_priv);
 };

-struct rockchip_atomic_commit {
-   struct work_struct  work;
-   struct drm_atomic_state *state;
-   struct drm_device *dev;
-   struct mutex lock;
-};
-
 struct rockchip_crtc_state {
struct drm_crtc_state base;
int output_type;
@@ -68,11 +61,8 @@ struct rockchip_drm_private {
struct drm_fb_helper fbdev_helper;
struct drm_gem_object *fbdev_bo;
const struct rockchip_crtc_funcs *crtc_funcs[ROCKCHIP_MAX_CRTC];
-
-   struct rockchip_atomic_commit commit;
 };

-void rockchip_drm_atomic_work(struct work_struct *work);
 int rockchip_register_crtc_funcs(struct drm_crtc *crtc,
 const struct rockchip_crtc_funcs *crtc_funcs);
 void rockchip_unregister_crtc_funcs(struct drm_crtc *crtc);
diff --git a/drivers/gpu/drm/rockchip/rockchip_drm_fb.c 
b/drivers/gpu/drm/rockchip/rockchip_drm_fb.c
index 5ea141dfae5b..9198ee1ddc87 100644
--- a/drivers/gpu/drm/rockchip/rockchip_drm_fb.c
+++ b/drivers/gpu/drm/rockchip/rockchip_drm_fb.c
@@ -229,87 +229,32 @@ rockchip_atomic_wait_for_complete(struct drm_device *dev, 
struct drm_atomic_stat
 }

 static void
-rockchip_atomic_commit_complete(struct rockchip_atomic_commit *commit)
+rockchip_atomic_commit_tail(struct drm_atomic_state *state)
 {
-   struct drm_atomic_state *state = commit->state;
-   struct drm_device *dev = commit->dev;
+   struct drm_device *dev = state->dev;

-   /*
-* TODO: do fence wait here.
-*/
-
-   /*
-* Rockchip crtc support runtime PM, can't update display planes
-* when crtc is disabled.
-*
-* drm_atomic_helper_commit comments detail that:
-* For drivers supporting runtime PM the recommended sequence is
-*
-* drm_atomic_helper_commit_modeset_disables(dev, state);
-*
-* drm_atomic_helper_commit_modeset_enables(dev, state);
-*
-* drm_atomic_helper_commit_planes(dev, state, true);
-*
-* See the kerneldoc entries for these three functions for more details.
-*/
drm_atomic_helper_commit_modeset_disables(dev, state);

drm_atomic_helper_commit_modeset_enables(dev, state);

drm_atomic_helper_commit_planes(dev, state, true);

+   drm_atomic_helper_commit_hw_done(state);
+
rockchip_atomic_wait_for_complete(dev, state);

drm_atomic_helper_cleanup_planes(dev, state);
-
-   drm_atomic_state_free(state);
-}
-
-void rockchip_drm_atomic_work(struct work_struct *work)
-{
-   struct rockchip_atomic_commit *commit = container_of(work,
-   struct rockchip_atomic_commit, work);
-
-   rockchip_atomic_commit_complete(commit);
 }

-int rockchip_drm_atomic_commit(struct drm_device *dev,
-  struct drm_atomic_state *state,
-  bool nonblock)
-{
-   struct rockchip_drm_private *private = dev->dev_private;
-   struct rockchip_atomic_commit *commit = >commit;
-   int ret;
-
-   ret = drm_atomic_helper_prepare_planes(dev, state);
-   if (ret)
-   return ret;
-
-   /* serialize outstanding nonblocking commits */
-   mutex_lock(>lock);
-   flush_work(>work);
-
-   drm_atomic_helper_swap_state(state, true);
-
-   commit->dev = dev;
-   commit->state = state;
-
-   if (nonblock)
-   schedule_work(>work);
-   else
-

[PATCH 23/26] drm/i915: Roll out the helper nonblock tracking

2016-05-29 Thread Daniel Vetter
Right now still all blocking, no worker anywhere to be seen.

Signed-off-by: Daniel Vetter 
---
 drivers/gpu/drm/i915/intel_display.c | 10 +-
 1 file changed, 9 insertions(+), 1 deletion(-)

diff --git a/drivers/gpu/drm/i915/intel_display.c 
b/drivers/gpu/drm/i915/intel_display.c
index 66a254fa2a96..4b81cffef24e 100644
--- a/drivers/gpu/drm/i915/intel_display.c
+++ b/drivers/gpu/drm/i915/intel_display.c
@@ -13654,6 +13654,10 @@ static int intel_atomic_commit(struct drm_device *dev,
unsigned long put_domains[I915_MAX_PIPES] = {};
unsigned crtc_vblank_mask = 0;

+   ret = drm_atomic_helper_setup_commit(state, nonblock);
+   if (ret)
+   return ret;
+
ret = intel_atomic_prepare_commit(dev, state, nonblock);
if (ret) {
DRM_DEBUG_ATOMIC("Preparing state failed with %i\n", ret);
@@ -13665,6 +13669,8 @@ static int intel_atomic_commit(struct drm_device *dev,
dev_priv->wm.skl_results = intel_state->wm_results;
intel_shared_dpll_commit(state);

+   drm_atomic_helper_wait_for_dependencies(state);
+
if (intel_state->modeset) {
memcpy(dev_priv->min_pixclk, intel_state->min_pixclk,
   sizeof(intel_state->min_pixclk));
@@ -13760,7 +13766,7 @@ static int intel_atomic_commit(struct drm_device *dev,
crtc_vblank_mask |= 1 << i;
}

-   /* FIXME: add subpixel order */
+   drm_atomic_helper_commit_hw_done(state);

if (!state->legacy_cursor_update)
intel_atomic_wait_for_vblanks(dev, dev_priv, crtc_vblank_mask);
@@ -13795,6 +13801,8 @@ static int intel_atomic_commit(struct drm_device *dev,
drm_atomic_helper_cleanup_planes(dev, state);
mutex_unlock(>struct_mutex);

+   drm_atomic_helper_commit_cleanup_done(state);
+
drm_atomic_state_free(state);

/* As one of the primary mmio accessors, KMS has a high likelihood
-- 
2.8.1



[PATCH 22/26] drm/i915: Signal drm events for atomic

2016-05-29 Thread Daniel Vetter
This is part of what atomic must implement. And it's also required
to be able to use the helper nonblocking support.

v2: Always send out the drm event, remove the planes_changed check.

Signed-off-by: Daniel Vetter 
---
 drivers/gpu/drm/i915/intel_display.c | 13 ++---
 drivers/gpu/drm/i915/intel_sprite.c  | 14 ++
 2 files changed, 24 insertions(+), 3 deletions(-)

diff --git a/drivers/gpu/drm/i915/intel_display.c 
b/drivers/gpu/drm/i915/intel_display.c
index d32274071393..66a254fa2a96 100644
--- a/drivers/gpu/drm/i915/intel_display.c
+++ b/drivers/gpu/drm/i915/intel_display.c
@@ -13731,13 +13731,21 @@ static int intel_atomic_commit(struct drm_device *dev,
bool modeset = needs_modeset(crtc->state);
struct intel_crtc_state *pipe_config =
to_intel_crtc_state(crtc->state);
-   bool update_pipe = !modeset && pipe_config->update_pipe;

if (modeset && crtc->state->active) {
update_scanline_offset(to_intel_crtc(crtc));
dev_priv->display.crtc_enable(crtc);
}

+   /* Complete events for now disable pipes here. */
+   if (modeset && !crtc->state->active && crtc->state->event) {
+   spin_lock_irq(>event_lock);
+   drm_crtc_send_vblank_event(crtc, crtc->state->event);
+   spin_unlock_irq(>event_lock);
+
+   crtc->state->event = NULL;
+   }
+
if (!modeset)

intel_pre_plane_update(to_intel_crtc_state(old_crtc_state));

@@ -13745,8 +13753,7 @@ static int intel_atomic_commit(struct drm_device *dev,
drm_atomic_get_existing_plane_state(state, crtc->primary))
intel_fbc_enable(intel_crtc);

-   if (crtc->state->active &&
-   (crtc->state->planes_changed || update_pipe))
+   if (crtc->state->active)
drm_atomic_helper_commit_planes_on_crtc(old_crtc_state);

if (pipe_config->base.active && needs_vblank_wait(pipe_config))
diff --git a/drivers/gpu/drm/i915/intel_sprite.c 
b/drivers/gpu/drm/i915/intel_sprite.c
index 97b1a54eb09f..8864cc983ea2 100644
--- a/drivers/gpu/drm/i915/intel_sprite.c
+++ b/drivers/gpu/drm/i915/intel_sprite.c
@@ -166,6 +166,20 @@ void intel_pipe_update_end(struct intel_crtc *crtc, struct 
intel_flip_work *work

trace_i915_pipe_update_end(crtc, end_vbl_count, scanline_end);

+   /* We're still in the vblank-evade critical section, this can't race.
+* Would be slightly nice to just grab the vblank count and arm the
+* event outside of the critical section - the spinlock might spin for a
+* while ... */
+   if (crtc->base.state->event) {
+   WARN_ON(drm_crtc_vblank_get(>base) != 0);
+
+   spin_lock(>base.dev->event_lock);
+   drm_crtc_arm_vblank_event(>base, crtc->base.state->event);
+   spin_unlock(>base.dev->event_lock);
+
+   crtc->base.state->event = NULL;
+   }
+
local_irq_enable();

if (crtc->debug.start_vbl_count &&
-- 
2.8.1



[PATCH 21/26] drm/atomic-helper: nonblocking commit support

2016-05-29 Thread Daniel Vetter
Design ideas:

- split up the actual commit into different phases, and have
  completions for each of them. This will be useful for the future
  when we want to interleave phases much more aggressively, for e.g.
  queue depth > 1. For not it's just a minimal optimization compared
  to current common nonblocking implementation patterns from drivers,
  which all stall for the entire commit to complete, including vblank
  waits and cleanups.

- Extract a separate atomic_commit_hw hook since that's the part most
  drivers will need to overwrite, hopefully allowing even more shared
  code.

- Enforce EBUSY seamntics by attaching one of the completions to the
  flip_done vblank event. Side benefit of forcing atomic drivers using
  these helpers to implement event handlign at least semi-correct. I'm
  evil that way ;-)

- Ridiculously modular, as usual.

- The main tracking unit for a commit stays struct drm_atomic_state,
  and the ownership rules for that are unchanged. Ownership still
  gets transferred to the driver (and subsequently to the worker) on
  successful commits. What is added is a small, per-crtc, refcounted
  structure to track pending commits called struct drm_crtc_commit.
  No actual state is attached to that though, it's purely for ordering
  and waiting.

- Dependencies are implicitly handled by assuming that any CRTC part
  of _atomic_state is a dependency, and that the current commit
  must wait for any commits to complete on those CRTC. This way
  drivers can easily add more depencies using
  drm_atomic_get_crtc_state(), which is very natural since in most
  case a dependency exists iff there's some bit of state that needs to
  be cross checked.

  Removing depencies is not possible, drivers simply need to be
  careful to not include every CRTC in a commit if that's not
  necessary. Which is a good idea anyway, since that also avoids
  ww_mutex lock contention.

- Queue depth > 1 sees some prep work in this patch by adding a stall
  paramater to drm_atomic_helper_swap_states(). To be able to push
  commits entirely free-standing and in a deeper queue through the
  back-end the driver must not access any obj->state pointers. This
  means we need to track the old state in drm_atomic_state (much
  easier with the consolidated arrays), and pass them all explicitly
  to driver backends (this will be serious amounts of churn).

  Once that's done stall can be set to false in swap_states.

Features: Contains bugs because totally untested.

v2: Dont ask for flip_done signalling when the CRTC is off and stays
off: Drivers don't handle events in that case. Instead complete right
away. This way future commits don't need to have special-case logic,
but can keep blocking for the flip_done completion.

v3: Tons of fixes:
- Stall for preceeding commit for real, not the current one by
  accident.
- Add WARN_ON in case drivers don't fire the drm event.
- Don't double-free drm events.

v4: Make legacy cursor not stall.

v5: Extend the helper hook to cover the entire commit tail. Some
drivers need special code for cleanup and vblank waiting, this makes
it a bit more useful. Inspired by the rockchip driver.

v6: Add WARN_ON to catch drivers who forget to send out the
drm event.

Cc: Tomeu Vizoso 
Cc: Daniel Stone 
Signed-off-by: Daniel Vetter 
---
 drivers/gpu/drm/drm_atomic.c |  22 ++
 drivers/gpu/drm/drm_atomic_helper.c  | 366 ---
 drivers/gpu/drm/drm_crtc.c   |   3 +
 drivers/gpu/drm/drm_fops.c   |   6 +
 include/drm/drmP.h   |   1 +
 include/drm/drm_atomic.h |   6 +
 include/drm/drm_atomic_helper.h  |   8 +
 include/drm/drm_crtc.h   | 119 +-
 include/drm/drm_modeset_helper_vtables.h |  36 +++
 9 files changed, 534 insertions(+), 33 deletions(-)

diff --git a/drivers/gpu/drm/drm_atomic.c b/drivers/gpu/drm/drm_atomic.c
index 1db198df3014..50aa341ca9ff 100644
--- a/drivers/gpu/drm/drm_atomic.c
+++ b/drivers/gpu/drm/drm_atomic.c
@@ -33,6 +33,20 @@

 #include "drm_crtc_internal.h"

+static void crtc_commit_free(struct kref *kref)
+{
+   struct drm_crtc_commit *commit =
+   container_of(kref, struct drm_crtc_commit, ref);
+
+   kfree(commit);
+}
+
+void drm_crtc_commit_put(struct drm_crtc_commit *commit)
+{
+   kref_put(>ref, crtc_commit_free);
+}
+EXPORT_SYMBOL(drm_crtc_commit_put);
+
 /**
  * drm_atomic_state_default_release -
  * release memory initialized by drm_atomic_state_init
@@ -148,6 +162,14 @@ void drm_atomic_state_default_clear(struct 
drm_atomic_state *state)

crtc->funcs->atomic_destroy_state(crtc,
  state->crtcs[i].state);
+
+   if (state->crtcs[i].commit) {
+   kfree(state->crtcs[i].commit->event);
+   state->crtcs[i].commit->event = NULL;
+   drm_crtc_commit_put(state->crtcs[i].commit);
+   }

[PATCH 20/26] drm/atomic: kerneldoc for drm_atomic_crtc_needs_modeset

2016-05-29 Thread Daniel Vetter
Just a bit of drive-by ocd.

Signed-off-by: Daniel Vetter 
---
 include/drm/drm_atomic.h | 7 +++
 1 file changed, 7 insertions(+)

diff --git a/include/drm/drm_atomic.h b/include/drm/drm_atomic.h
index d9504dfcd1cc..465a1212f4f0 100644
--- a/include/drm/drm_atomic.h
+++ b/include/drm/drm_atomic.h
@@ -198,6 +198,13 @@ int __must_check drm_atomic_nonblocking_commit(struct 
drm_atomic_state *state);
 (plane_state) = (__state)->planes[__i].state, 1);  \
 (__i)++)   \
for_each_if (plane_state)
+
+/**
+ * drm_atomic_crtc_needs_modeset - compute combined modeset need
+ * @state: _crtc_state for the CRTC
+ *
+ * This computes the combined need for a modeset for @state.
+ */
 static inline bool
 drm_atomic_crtc_needs_modeset(struct drm_crtc_state *state)
 {
-- 
2.8.1



[PATCH 19/26] drm/sun4i: Implement some semblance of vblank event handling

2016-05-29 Thread Daniel Vetter
atomic_flush seems to be the right place, right after we commit the
plane updates. Again use the fullproof version, since the pipe might
be off.

Cc: Boris Brezillon 
Cc: Maxime Ripard 
Signed-off-by: Daniel Vetter 
---
 drivers/gpu/drm/sun4i/sun4i_crtc.c | 12 
 1 file changed, 12 insertions(+)

diff --git a/drivers/gpu/drm/sun4i/sun4i_crtc.c 
b/drivers/gpu/drm/sun4i/sun4i_crtc.c
index 4182a21f5923..f628b6d8f23f 100644
--- a/drivers/gpu/drm/sun4i/sun4i_crtc.c
+++ b/drivers/gpu/drm/sun4i/sun4i_crtc.c
@@ -51,10 +51,22 @@ static void sun4i_crtc_atomic_flush(struct drm_crtc *crtc,
 {
struct sun4i_crtc *scrtc = drm_crtc_to_sun4i_crtc(crtc);
struct sun4i_drv *drv = scrtc->drv;
+   struct drm_pending_vblank_event *event = crtc->state->event;

DRM_DEBUG_DRIVER("Committing plane changes\n");

sun4i_backend_commit(drv->backend);
+
+   if (event) {
+   crtc->state->event = NULL;
+
+   spin_lock_irq(>dev->event_lock);
+   if (drm_crtc_vblank_get(crtc) == 0)
+   drm_crtc_arm_vblank_event(crtc, event);
+   else
+   drm_crtc_send_vblank_event(crtc, event);
+   spin_unlock_irq(>dev->event_lock);
+   }
 }

 static void sun4i_crtc_disable(struct drm_crtc *crtc)
-- 
2.8.1



[PATCH 18/26] drm/hisilicon: Implement some semblance of vblank event handling

2016-05-29 Thread Daniel Vetter
atomic_flush seems to be the right place, but I'm not entirely sure
whether this will catch them all. It could be that when disabling the
crtc we'll miss the vblank.

While at it nuke the dummy functions.

v2: Be more robust and either arm, when the CRTC is on, or just send
the event out right away.

Cc: Xinliang Liu 
Cc: Xinwei Kong 
Cc: Archit Taneja 
Signed-off-by: Daniel Vetter 
---
 drivers/gpu/drm/hisilicon/kirin/kirin_drm_ade.c | 20 
 1 file changed, 12 insertions(+), 8 deletions(-)

diff --git a/drivers/gpu/drm/hisilicon/kirin/kirin_drm_ade.c 
b/drivers/gpu/drm/hisilicon/kirin/kirin_drm_ade.c
index fba6372d060e..ed76baad525f 100644
--- a/drivers/gpu/drm/hisilicon/kirin/kirin_drm_ade.c
+++ b/drivers/gpu/drm/hisilicon/kirin/kirin_drm_ade.c
@@ -502,13 +502,6 @@ static void ade_crtc_disable(struct drm_crtc *crtc)
acrtc->enable = false;
 }

-static int ade_crtc_atomic_check(struct drm_crtc *crtc,
-struct drm_crtc_state *state)
-{
-   /* do nothing */
-   return 0;
-}
-
 static void ade_crtc_mode_set_nofb(struct drm_crtc *crtc)
 {
struct ade_crtc *acrtc = to_ade_crtc(crtc);
@@ -537,6 +530,7 @@ static void ade_crtc_atomic_flush(struct drm_crtc *crtc,
 {
struct ade_crtc *acrtc = to_ade_crtc(crtc);
struct ade_hw_ctx *ctx = acrtc->ctx;
+   struct drm_pending_vblank_event *event = crtc->state->event;
void __iomem *base = ctx->base;

/* only crtc is enabled regs take effect */
@@ -545,12 +539,22 @@ static void ade_crtc_atomic_flush(struct drm_crtc *crtc,
/* flush ade registers */
writel(ADE_ENABLE, base + ADE_EN);
}
+
+   if (event) {
+   crtc->state->event = NULL;
+
+   spin_lock_irq(>dev->event_lock);
+   if (drm_crtc_vblank_get(crtc) == 0)
+   drm_crtc_arm_vblank_event(crtc, event);
+   else
+   drm_crtc_send_vblank_event(crtc, event);
+   spin_unlock_irq(>dev->event_lock);
+   }
 }

 static const struct drm_crtc_helper_funcs ade_crtc_helper_funcs = {
.enable = ade_crtc_enable,
.disable= ade_crtc_disable,
-   .atomic_check   = ade_crtc_atomic_check,
.mode_set_nofb  = ade_crtc_mode_set_nofb,
.atomic_begin   = ade_crtc_atomic_begin,
.atomic_flush   = ade_crtc_atomic_flush,
-- 
2.8.1



[PATCH 17/26] drm/fsl-du: Implement some semblance of vblank event handling

2016-05-29 Thread Daniel Vetter
No idea how exactly fsl-du commits hw state changes, but here in flush
is probably the safest place.

While at it nuke the dummy functions.

v2: Be more robust and either arm, when the CRTC is on, or just send
the event out right away.

Cc: Stefan Agner 
Signed-off-by: Daniel Vetter 
---
 drivers/gpu/drm/fsl-dcu/fsl_dcu_drm_crtc.c | 23 +++
 1 file changed, 11 insertions(+), 12 deletions(-)

diff --git a/drivers/gpu/drm/fsl-dcu/fsl_dcu_drm_crtc.c 
b/drivers/gpu/drm/fsl-dcu/fsl_dcu_drm_crtc.c
index 89c0084c2814..706de3278f1c 100644
--- a/drivers/gpu/drm/fsl-dcu/fsl_dcu_drm_crtc.c
+++ b/drivers/gpu/drm/fsl-dcu/fsl_dcu_drm_crtc.c
@@ -22,20 +22,21 @@
 #include "fsl_dcu_drm_drv.h"
 #include "fsl_dcu_drm_plane.h"

-static void fsl_dcu_drm_crtc_atomic_begin(struct drm_crtc *crtc,
+static void fsl_dcu_drm_crtc_atomic_flush(struct drm_crtc *crtc,
  struct drm_crtc_state *old_crtc_state)
 {
-}
+   struct drm_pending_vblank_event *event = crtc->state->event;

-static int fsl_dcu_drm_crtc_atomic_check(struct drm_crtc *crtc,
-struct drm_crtc_state *state)
-{
-   return 0;
-}
+   if (event) {
+   crtc->state->event = NULL;

-static void fsl_dcu_drm_crtc_atomic_flush(struct drm_crtc *crtc,
- struct drm_crtc_state *old_crtc_state)
-{
+   spin_lock_irq(>dev->event_lock);
+   if (drm_crtc_vblank_get(crtc) == 0)
+   drm_crtc_arm_vblank_event(crtc, event);
+   else
+   drm_crtc_send_vblank_event(crtc, event);
+   spin_unlock_irq(>dev->event_lock);
+   }
 }

 static void fsl_dcu_drm_disable_crtc(struct drm_crtc *crtc)
@@ -117,8 +118,6 @@ static void fsl_dcu_drm_crtc_mode_set_nofb(struct drm_crtc 
*crtc)
 }

 static const struct drm_crtc_helper_funcs fsl_dcu_drm_crtc_helper_funcs = {
-   .atomic_begin = fsl_dcu_drm_crtc_atomic_begin,
-   .atomic_check = fsl_dcu_drm_crtc_atomic_check,
.atomic_flush = fsl_dcu_drm_crtc_atomic_flush,
.disable = fsl_dcu_drm_disable_crtc,
.enable = fsl_dcu_drm_crtc_enable,
-- 
2.8.1



[PATCH 16/26] drm/hdlcd: Use helper support for nonblocking commits

2016-05-29 Thread Daniel Vetter
Again, just doing them as blocking commits isn't cool.

>From a cursory check hdlcd does seem to at least try to handle
drm_pending_vblank_event, so hopefully this works.

Cc: Liviu Dudau 
Signed-off-by: Daniel Vetter 
---
 drivers/gpu/drm/arm/hdlcd_drv.c | 8 +---
 1 file changed, 1 insertion(+), 7 deletions(-)

diff --git a/drivers/gpu/drm/arm/hdlcd_drv.c b/drivers/gpu/drm/arm/hdlcd_drv.c
index 4f909378d581..6d1877238cf0 100644
--- a/drivers/gpu/drm/arm/hdlcd_drv.c
+++ b/drivers/gpu/drm/arm/hdlcd_drv.c
@@ -112,17 +112,11 @@ static void hdlcd_fb_output_poll_changed(struct 
drm_device *drm)
drm_fbdev_cma_hotplug_event(hdlcd->fbdev);
 }

-static int hdlcd_atomic_commit(struct drm_device *dev,
-  struct drm_atomic_state *state, bool nonblock)
-{
-   return drm_atomic_helper_commit(dev, state, false);
-}
-
 static const struct drm_mode_config_funcs hdlcd_mode_config_funcs = {
.fb_create = drm_fb_cma_create,
.output_poll_changed = hdlcd_fb_output_poll_changed,
.atomic_check = drm_atomic_helper_check,
-   .atomic_commit = hdlcd_atomic_commit,
+   .atomic_commit = drm_atomic_helper_commit,
 };

 static void hdlcd_setup_mode_config(struct drm_device *drm)
-- 
2.8.1



[PATCH 15/26] drm/arc: Implement nonblocking commit correctly

2016-05-29 Thread Daniel Vetter
Committing with block it is not.

Thanks to the fixed up vblank event handling we can just use the
helper support for nonblocking commits now.

Cc: Carlos Palminha 
Cc: Alexey Brodkin 
Cc: linux-snps-arc at lists.infradead.org
Signed-off-by: Daniel Vetter 
---
 drivers/gpu/drm/arc/arcpgu_drv.c | 8 +---
 1 file changed, 1 insertion(+), 7 deletions(-)

diff --git a/drivers/gpu/drm/arc/arcpgu_drv.c b/drivers/gpu/drm/arc/arcpgu_drv.c
index d407fd79a400..a92e533531c3 100644
--- a/drivers/gpu/drm/arc/arcpgu_drv.c
+++ b/drivers/gpu/drm/arc/arcpgu_drv.c
@@ -32,17 +32,11 @@ static void arcpgu_fb_output_poll_changed(struct drm_device 
*dev)
drm_fbdev_cma_hotplug_event(arcpgu->fbdev);
 }

-static int arcpgu_atomic_commit(struct drm_device *dev,
-   struct drm_atomic_state *state, bool async)
-{
-   return drm_atomic_helper_commit(dev, state, false);
-}
-
 static struct drm_mode_config_funcs arcpgu_drm_modecfg_funcs = {
.fb_create  = drm_fb_cma_create,
.output_poll_changed = arcpgu_fb_output_poll_changed,
.atomic_check = drm_atomic_helper_check,
-   .atomic_commit = arcpgu_atomic_commit,
+   .atomic_commit = drm_atomic_helper_commit,
 };

 static void arcpgu_setup_mode_config(struct drm_device *drm)
-- 
2.8.1



[PATCH 14/26] drm/arc: Actually bother with handling atomic events.

2016-05-29 Thread Daniel Vetter
The drm core has a nice ready-made helper for exactly the simple case
where it should fire on the next vblank.

Note that arming the vblank event in _begin is probably too early, and
might easily result in the vblank firing too early, before the new set
of planes are actually disabled. But that's kinda a minor issue
compared to just outright hanging userspace.

v2: Be more robust and either arm, when the CRTC is on, or just send
the event out right away.

Cc: Carlos Palminha 
Cc: Alexey Brodkin 
Cc: linux-snps-arc at lists.infradead.org
Signed-off-by: Daniel Vetter 
---
 drivers/gpu/drm/arc/arcpgu_crtc.c | 15 ---
 1 file changed, 8 insertions(+), 7 deletions(-)

diff --git a/drivers/gpu/drm/arc/arcpgu_crtc.c 
b/drivers/gpu/drm/arc/arcpgu_crtc.c
index d5ca0c280e68..c9f183b11df9 100644
--- a/drivers/gpu/drm/arc/arcpgu_crtc.c
+++ b/drivers/gpu/drm/arc/arcpgu_crtc.c
@@ -145,16 +145,17 @@ static int arc_pgu_crtc_atomic_check(struct drm_crtc 
*crtc,
 static void arc_pgu_crtc_atomic_begin(struct drm_crtc *crtc,
  struct drm_crtc_state *state)
 {
-   struct arcpgu_drm_private *arcpgu = crtc_to_arcpgu_priv(crtc);
-   unsigned long flags;
-
-   if (crtc->state->event) {
-   struct drm_pending_vblank_event *event = crtc->state->event;
+   struct drm_pending_vblank_event *event = crtc->state->event;

+   if (event) {
crtc->state->event = NULL;
-   event->pipe = drm_crtc_index(crtc);

-   WARN_ON(drm_crtc_vblank_get(crtc) != 0);
+   spin_lock_irq(>dev->event_lock);
+   if (drm_crtc_vblank_get(crtc) == 0)
+   drm_crtc_arm_vblank_event(crtc, event);
+   else
+   drm_crtc_send_vblank_event(crtc, event);
+   spin_unlock_irq(>dev->event_lock);
}
 }

-- 
2.8.1



[PATCH 13/26] drm/arc: Nuke event_list

2016-05-29 Thread Daniel Vetter
This is just used for cleanup in preclose, and with the reworked event
handling code this is now done properly by the core.

Nuke it!

But it also shows that arc totally fails at sending out drm events for
flips. Next patch will hack that up.

Cc: Carlos Palminha 
Cc: Alexey Brodkin 
Cc: linux-snps-arc at lists.infradead.org
Signed-off-by: Daniel Vetter 
---
 drivers/gpu/drm/arc/arcpgu.h  |  1 -
 drivers/gpu/drm/arc/arcpgu_crtc.c |  4 
 drivers/gpu/drm/arc/arcpgu_drv.c  | 19 ---
 3 files changed, 24 deletions(-)

diff --git a/drivers/gpu/drm/arc/arcpgu.h b/drivers/gpu/drm/arc/arcpgu.h
index 86574b698a78..8c01a25d279a 100644
--- a/drivers/gpu/drm/arc/arcpgu.h
+++ b/drivers/gpu/drm/arc/arcpgu.h
@@ -22,7 +22,6 @@ struct arcpgu_drm_private {
struct clk  *clk;
struct drm_fbdev_cma*fbdev;
struct drm_framebuffer  *fb;
-   struct list_headevent_list;
struct drm_crtc crtc;
struct drm_plane*plane;
 };
diff --git a/drivers/gpu/drm/arc/arcpgu_crtc.c 
b/drivers/gpu/drm/arc/arcpgu_crtc.c
index 92f8beff8e60..d5ca0c280e68 100644
--- a/drivers/gpu/drm/arc/arcpgu_crtc.c
+++ b/drivers/gpu/drm/arc/arcpgu_crtc.c
@@ -155,10 +155,6 @@ static void arc_pgu_crtc_atomic_begin(struct drm_crtc 
*crtc,
event->pipe = drm_crtc_index(crtc);

WARN_ON(drm_crtc_vblank_get(crtc) != 0);
-
-   spin_lock_irqsave(>dev->event_lock, flags);
-   list_add_tail(>base.link, >event_list);
-   spin_unlock_irqrestore(>dev->event_lock, flags);
}
 }

diff --git a/drivers/gpu/drm/arc/arcpgu_drv.c b/drivers/gpu/drm/arc/arcpgu_drv.c
index bc53ebb83f75..d407fd79a400 100644
--- a/drivers/gpu/drm/arc/arcpgu_drv.c
+++ b/drivers/gpu/drm/arc/arcpgu_drv.c
@@ -81,22 +81,6 @@ static const struct file_operations arcpgu_drm_ops = {
.mmap = arcpgu_gem_mmap,
 };

-static void arcpgu_preclose(struct drm_device *drm, struct drm_file *file)
-{
-   struct arcpgu_drm_private *arcpgu = drm->dev_private;
-   struct drm_pending_vblank_event *e, *t;
-   unsigned long flags;
-
-   spin_lock_irqsave(>event_lock, flags);
-   list_for_each_entry_safe(e, t, >event_list, base.link) {
-   if (e->base.file_priv != file)
-   continue;
-   list_del(>base.link);
-   e->base.destroy(>base);
-   }
-   spin_unlock_irqrestore(>event_lock, flags);
-}
-
 static void arcpgu_lastclose(struct drm_device *drm)
 {
struct arcpgu_drm_private *arcpgu = drm->dev_private;
@@ -122,8 +106,6 @@ static int arcpgu_load(struct drm_device *drm)
if (IS_ERR(arcpgu->clk))
return PTR_ERR(arcpgu->clk);

-   INIT_LIST_HEAD(>event_list);
-
arcpgu_setup_mode_config(drm);

res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
@@ -192,7 +174,6 @@ int arcpgu_unload(struct drm_device *drm)
 static struct drm_driver arcpgu_drm_driver = {
.driver_features = DRIVER_MODESET | DRIVER_GEM | DRIVER_PRIME |
   DRIVER_ATOMIC,
-   .preclose = arcpgu_preclose,
.lastclose = arcpgu_lastclose,
.name = "drm-arcpgu",
.desc = "ARC PGU Controller",
-- 
2.8.1



[PATCH 12/26] drm/atomic-helper: Massage swap_state signature somewhat

2016-05-29 Thread Daniel Vetter
- dev is redundant, we have state->atomic
- add stall parameter, which must be set when swapping needs to stall
  for preceeding commits to stop looking at ->state pointers. Currently
  all drivers need this to be, just prep work for a glorious future.

Signed-off-by: Daniel Vetter 
---
 drivers/gpu/drm/atmel-hlcdc/atmel_hlcdc_dc.c | 2 +-
 drivers/gpu/drm/drm_atomic_helper.c  | 8 
 drivers/gpu/drm/exynos/exynos_drm_drv.c  | 2 +-
 drivers/gpu/drm/i915/intel_display.c | 2 +-
 drivers/gpu/drm/mediatek/mtk_drm_drv.c   | 2 +-
 drivers/gpu/drm/msm/msm_atomic.c | 2 +-
 drivers/gpu/drm/omapdrm/omap_drv.c   | 2 +-
 drivers/gpu/drm/rcar-du/rcar_du_kms.c| 2 +-
 drivers/gpu/drm/rockchip/rockchip_drm_fb.c   | 2 +-
 drivers/gpu/drm/sti/sti_drv.c| 2 +-
 drivers/gpu/drm/tegra/drm.c  | 2 +-
 drivers/gpu/drm/vc4/vc4_kms.c| 2 +-
 include/drm/drm_atomic_helper.h  | 4 ++--
 13 files changed, 17 insertions(+), 17 deletions(-)

diff --git a/drivers/gpu/drm/atmel-hlcdc/atmel_hlcdc_dc.c 
b/drivers/gpu/drm/atmel-hlcdc/atmel_hlcdc_dc.c
index 6485fa5bee8b..9ecf16c7911d 100644
--- a/drivers/gpu/drm/atmel-hlcdc/atmel_hlcdc_dc.c
+++ b/drivers/gpu/drm/atmel-hlcdc/atmel_hlcdc_dc.c
@@ -519,7 +519,7 @@ static int atmel_hlcdc_dc_atomic_commit(struct drm_device 
*dev,
}

/* Swap the state, this is the point of no return. */
-   drm_atomic_helper_swap_state(dev, state);
+   drm_atomic_helper_swap_state(state, true);

if (async)
queue_work(dc->wq, >work);
diff --git a/drivers/gpu/drm/drm_atomic_helper.c 
b/drivers/gpu/drm/drm_atomic_helper.c
index 5298eb668ca7..fecbb52cbb85 100644
--- a/drivers/gpu/drm/drm_atomic_helper.c
+++ b/drivers/gpu/drm/drm_atomic_helper.c
@@ -1160,7 +1160,7 @@ int drm_atomic_helper_commit(struct drm_device *dev,
 * the software side now.
 */

-   drm_atomic_helper_swap_state(dev, state);
+   drm_atomic_helper_swap_state(state, true);

/*
 * Everything below can be run asynchronously without the need to grab
@@ -1531,8 +1531,8 @@ EXPORT_SYMBOL(drm_atomic_helper_cleanup_planes);

 /**
  * drm_atomic_helper_swap_state - store atomic state into current sw state
- * @dev: DRM device
  * @state: atomic state
+ * @stall: stall for proceeding commits
  *
  * This function stores the atomic state into the current state pointers in all
  * driver objects. It should be called after all failing steps have been done
@@ -1554,8 +1554,8 @@ EXPORT_SYMBOL(drm_atomic_helper_cleanup_planes);
  * 5. Call drm_atomic_helper_cleanup_planes() with @state, which since step 3
  * contains the old state. Also do any other cleanup required with that state.
  */
-void drm_atomic_helper_swap_state(struct drm_device *dev,
- struct drm_atomic_state *state)
+void drm_atomic_helper_swap_state(struct drm_atomic_state *state,
+ bool stall)
 {
int i;
struct drm_connector *connector;
diff --git a/drivers/gpu/drm/exynos/exynos_drm_drv.c 
b/drivers/gpu/drm/exynos/exynos_drm_drv.c
index cabc5fd0246d..deba76982358 100644
--- a/drivers/gpu/drm/exynos/exynos_drm_drv.c
+++ b/drivers/gpu/drm/exynos/exynos_drm_drv.c
@@ -299,7 +299,7 @@ int exynos_atomic_commit(struct drm_device *dev, struct 
drm_atomic_state *state,
priv->pending |= commit->crtcs;
spin_unlock(>lock);

-   drm_atomic_helper_swap_state(dev, state);
+   drm_atomic_helper_swap_state(state, true);

if (nonblock)
schedule_work(>work);
diff --git a/drivers/gpu/drm/i915/intel_display.c 
b/drivers/gpu/drm/i915/intel_display.c
index 9ccd76699f48..d32274071393 100644
--- a/drivers/gpu/drm/i915/intel_display.c
+++ b/drivers/gpu/drm/i915/intel_display.c
@@ -13660,7 +13660,7 @@ static int intel_atomic_commit(struct drm_device *dev,
return ret;
}

-   drm_atomic_helper_swap_state(dev, state);
+   drm_atomic_helper_swap_state(state, true);
dev_priv->wm.distrust_bios_wm = false;
dev_priv->wm.skl_results = intel_state->wm_results;
intel_shared_dpll_commit(state);
diff --git a/drivers/gpu/drm/mediatek/mtk_drm_drv.c 
b/drivers/gpu/drm/mediatek/mtk_drm_drv.c
index 06a417b2f91e..c33bf98c5d5e 100644
--- a/drivers/gpu/drm/mediatek/mtk_drm_drv.c
+++ b/drivers/gpu/drm/mediatek/mtk_drm_drv.c
@@ -91,7 +91,7 @@ static int mtk_atomic_commit(struct drm_device *drm,
mutex_lock(>commit.lock);
flush_work(>commit.work);

-   drm_atomic_helper_swap_state(drm, state);
+   drm_atomic_helper_swap_state(state, true);

if (async)
mtk_atomic_schedule(private, state);
diff --git a/drivers/gpu/drm/msm/msm_atomic.c b/drivers/gpu/drm/msm/msm_atomic.c
index 9c0e4261dbba..d02bd6a50e90 100644
--- a/drivers/gpu/drm/msm/msm_atomic.c
+++ b/drivers/gpu/drm/msm/msm_atomic.c
@@ -238,7 +238,7 @@ int 

[PATCH 11/26] drm/fence: add fence to drm_pending_event

2016-05-29 Thread Daniel Vetter
From: Gustavo Padovan 

Now a drm_pending_event can either send a real drm_event or signal a
fence, or both. It allow us to signal via fences when the buffer is
displayed on the screen. Which in turn means that the previous buffer
is not in use anymore and can be freed or sent back to another driver
for processing.

v2: Comments from Daniel Vetter
- call fence_signal in drm_send_event_locked()
- remove unneeded !e->event check

v3: Remove drm_pending_event->destroy to fix a leak when e->file_priv
is not set.

Signed-off-by: Gustavo Padovan  (v2)
Signed-off-by: Daniel Vetter 
---
 drivers/gpu/drm/drm_atomic.c| 19 +--
 drivers/gpu/drm/drm_fops.c  | 16 +---
 drivers/gpu/drm/nouveau/nouveau_usif.c  |  1 -
 drivers/gpu/drm/rockchip/rockchip_drm_vop.c |  2 +-
 include/drm/drmP.h  |  3 ++-
 5 files changed, 25 insertions(+), 16 deletions(-)

diff --git a/drivers/gpu/drm/drm_atomic.c b/drivers/gpu/drm/drm_atomic.c
index 674b2e490aa9..1db198df3014 100644
--- a/drivers/gpu/drm/drm_atomic.c
+++ b/drivers/gpu/drm/drm_atomic.c
@@ -1412,7 +1412,8 @@ EXPORT_SYMBOL(drm_atomic_nonblocking_commit);
  */

 static struct drm_pending_vblank_event *create_vblank_event(
-   struct drm_device *dev, struct drm_file *file_priv, uint64_t 
user_data)
+   struct drm_device *dev, struct drm_file *file_priv,
+   struct fence *fence, uint64_t user_data)
 {
struct drm_pending_vblank_event *e = NULL;
int ret;
@@ -1425,12 +1426,17 @@ static struct drm_pending_vblank_event 
*create_vblank_event(
e->event.base.length = sizeof(e->event);
e->event.user_data = user_data;

-   ret = drm_event_reserve_init(dev, file_priv, >base, >event.base);
-   if (ret) {
-   kfree(e);
-   return NULL;
+   if (file_priv) {
+   ret = drm_event_reserve_init(dev, file_priv, >base,
+>event.base);
+   if (ret) {
+   kfree(e);
+   return NULL;
+   }
}

+   e->base.fence = fence;
+
return e;
 }

@@ -1670,7 +1676,8 @@ retry:
for_each_crtc_in_state(state, crtc, crtc_state, i) {
struct drm_pending_vblank_event *e;

-   e = create_vblank_event(dev, file_priv, arg->user_data);
+   e = create_vblank_event(dev, file_priv, NULL,
+   arg->user_data);
if (!e) {
ret = -ENOMEM;
goto out;
diff --git a/drivers/gpu/drm/drm_fops.c b/drivers/gpu/drm/drm_fops.c
index 868871068956..4c4b30f7a9f2 100644
--- a/drivers/gpu/drm/drm_fops.c
+++ b/drivers/gpu/drm/drm_fops.c
@@ -294,7 +294,7 @@ static void drm_events_release(struct drm_file *file_priv)
/* Remove unconsumed events */
list_for_each_entry_safe(e, et, _priv->event_list, link) {
list_del(>link);
-   e->destroy(e);
+   kfree(e);
}

spin_unlock_irqrestore(>event_lock, flags);
@@ -525,7 +525,7 @@ put_back_event:
}

ret += length;
-   e->destroy(e);
+   kfree(e);
}
}
mutex_unlock(_priv->event_read_lock);
@@ -602,9 +602,6 @@ int drm_event_reserve_init_locked(struct drm_device *dev,
list_add(>pending_link, _priv->pending_event_list);
p->file_priv = file_priv;

-   /* we *could* pass this in as arg, but everyone uses kfree: */
-   p->destroy = (void (*) (struct drm_pending_event *)) kfree;
-
return 0;
 }
 EXPORT_SYMBOL(drm_event_reserve_init_locked);
@@ -667,7 +664,7 @@ void drm_event_cancel_free(struct drm_device *dev,
list_del(>pending_link);
}
spin_unlock_irqrestore(>event_lock, flags);
-   p->destroy(p);
+   kfree(p);
 }
 EXPORT_SYMBOL(drm_event_cancel_free);

@@ -689,8 +686,13 @@ void drm_send_event_locked(struct drm_device *dev, struct 
drm_pending_event *e)
 {
assert_spin_locked(>event_lock);

+   if (e->fence) {
+   fence_signal(e->fence);
+   fence_put(e->fence);
+   }
+
if (!e->file_priv) {
-   e->destroy(e);
+   kfree(e);
return;
}

diff --git a/drivers/gpu/drm/nouveau/nouveau_usif.c 
b/drivers/gpu/drm/nouveau/nouveau_usif.c
index 675e9e077a95..08f9c6fa0f7f 100644
--- a/drivers/gpu/drm/nouveau/nouveau_usif.c
+++ b/drivers/gpu/drm/nouveau/nouveau_usif.c
@@ -212,7 +212,6 @@ usif_notify_get(struct drm_file *f, void *data, u32 size, 
void *argv, u32 argc)
ntfy->p->base.event = >p->e.base;
ntfy->p->base.file_priv = f;
ntfy->p->base.pid = current->pid;
-   

[PATCH 10/26] drm: Consolidate crtc arrays in drm_atomic_state

2016-05-29 Thread Daniel Vetter
It's silly to have 2 mallocs when we could tie these two together.

Also, Gustavo adds another one in his per-crtc out-fence patches. And
I want to add more stuff here for nonblocking commit helpers.

In the future we can use this to store a pointer to the preceeding
state, making an atomic update entirely free-standing. This will be
needed to be able to queue them up with a depth > 1.

Cc: Gustavo Padovan 
Signed-off-by: Daniel Vetter 
---
 drivers/gpu/drm/drm_atomic.c| 17 ++---
 drivers/gpu/drm/drm_atomic_helper.c |  2 +-
 include/drm/drm_atomic.h| 10 +-
 include/drm/drm_crtc.h  |  8 ++--
 4 files changed, 18 insertions(+), 19 deletions(-)

diff --git a/drivers/gpu/drm/drm_atomic.c b/drivers/gpu/drm/drm_atomic.c
index 68fd99d2fd01..674b2e490aa9 100644
--- a/drivers/gpu/drm/drm_atomic.c
+++ b/drivers/gpu/drm/drm_atomic.c
@@ -45,7 +45,6 @@ void drm_atomic_state_default_release(struct drm_atomic_state 
*state)
 {
kfree(state->connectors);
kfree(state->crtcs);
-   kfree(state->crtc_states);
kfree(state->planes);
 }
 EXPORT_SYMBOL(drm_atomic_state_default_release);
@@ -70,10 +69,6 @@ drm_atomic_state_init(struct drm_device *dev, struct 
drm_atomic_state *state)
   sizeof(*state->crtcs), GFP_KERNEL);
if (!state->crtcs)
goto fail;
-   state->crtc_states = kcalloc(dev->mode_config.num_crtc,
-sizeof(*state->crtc_states), GFP_KERNEL);
-   if (!state->crtc_states)
-   goto fail;
state->planes = kcalloc(dev->mode_config.num_total_plane,
sizeof(*state->planes), GFP_KERNEL);
if (!state->planes)
@@ -146,15 +141,15 @@ void drm_atomic_state_default_clear(struct 
drm_atomic_state *state)
}

for (i = 0; i < config->num_crtc; i++) {
-   struct drm_crtc *crtc = state->crtcs[i];
+   struct drm_crtc *crtc = state->crtcs[i].ptr;

if (!crtc)
continue;

crtc->funcs->atomic_destroy_state(crtc,
- state->crtc_states[i]);
-   state->crtcs[i] = NULL;
-   state->crtc_states[i] = NULL;
+ state->crtcs[i].state);
+   state->crtcs[i].ptr = NULL;
+   state->crtcs[i].state = NULL;
}

for (i = 0; i < config->num_total_plane; i++) {
@@ -264,8 +259,8 @@ drm_atomic_get_crtc_state(struct drm_atomic_state *state,
if (!crtc_state)
return ERR_PTR(-ENOMEM);

-   state->crtc_states[index] = crtc_state;
-   state->crtcs[index] = crtc;
+   state->crtcs[index].state = crtc_state;
+   state->crtcs[index].ptr = crtc;
crtc_state->state = state;

DRM_DEBUG_ATOMIC("Added [CRTC:%d:%s] %p state to %p\n",
diff --git a/drivers/gpu/drm/drm_atomic_helper.c 
b/drivers/gpu/drm/drm_atomic_helper.c
index f70d576f745e..5298eb668ca7 100644
--- a/drivers/gpu/drm/drm_atomic_helper.c
+++ b/drivers/gpu/drm/drm_atomic_helper.c
@@ -1573,7 +1573,7 @@ void drm_atomic_helper_swap_state(struct drm_device *dev,

for_each_crtc_in_state(state, crtc, crtc_state, i) {
crtc->state->state = state;
-   swap(state->crtc_states[i], crtc->state);
+   swap(state->crtcs[i].state, crtc->state);
crtc->state->state = NULL;
}

diff --git a/include/drm/drm_atomic.h b/include/drm/drm_atomic.h
index 8e616d39353b..d9504dfcd1cc 100644
--- a/include/drm/drm_atomic.h
+++ b/include/drm/drm_atomic.h
@@ -71,7 +71,7 @@ static inline struct drm_crtc_state *
 drm_atomic_get_existing_crtc_state(struct drm_atomic_state *state,
   struct drm_crtc *crtc)
 {
-   return state->crtc_states[drm_crtc_index(crtc)];
+   return state->crtcs[drm_crtc_index(crtc)].state;
 }

 /**
@@ -183,11 +183,11 @@ int __must_check drm_atomic_nonblocking_commit(struct 
drm_atomic_state *state);
 (__i)++)   \
for_each_if (connector)

-#define for_each_crtc_in_state(state, crtc, crtc_state, __i)   \
+#define for_each_crtc_in_state(__state, crtc, crtc_state, __i) \
for ((__i) = 0; \
-(__i) < (state)->dev->mode_config.num_crtc &&  \
-((crtc) = (state)->crtcs[__i], \
-(crtc_state) = (state)->crtc_states[__i], 1);  \
+(__i) < (__state)->dev->mode_config.num_crtc &&\
+((crtc) = (__state)->crtcs[__i].ptr,   \
+(crtc_state) = (__state)->crtcs[__i].state, 1);\
 (__i)++)   \
for_each_if (crtc_state)

diff --git a/include/drm/drm_crtc.h b/include/drm/drm_crtc.h
index 

[PATCH 09/26] drm: Consolidate plane arrays in drm_atomic_state

2016-05-29 Thread Daniel Vetter
It's kinda pointless to have 2 separate mallocs for these. And when we
add more per-plane state in the future it's even more pointless.

Right now there's no such thing planned, but both Gustavo's per-crtc
fence patches, and some nonblocking commit helpers I'm playing around
with will add more per-crtc stuff. It makes sense to also consolidate
planes, just for consistency.

In the future we can use this to store a pointer to the preceeding
state, making an atomic update entirely free-standing. This will be
needed to be able to queue them up with a depth > 1.

Cc: Gustavo Padovan 
Signed-off-by: Daniel Vetter 
---
 drivers/gpu/drm/drm_atomic.c| 17 ++---
 drivers/gpu/drm/drm_atomic_helper.c |  2 +-
 drivers/gpu/drm/i915/intel_atomic.c |  2 +-
 include/drm/drm_atomic.h| 14 +++---
 include/drm/drm_crtc.h  | 11 +++
 5 files changed, 22 insertions(+), 24 deletions(-)

diff --git a/drivers/gpu/drm/drm_atomic.c b/drivers/gpu/drm/drm_atomic.c
index a6395e9654af..68fd99d2fd01 100644
--- a/drivers/gpu/drm/drm_atomic.c
+++ b/drivers/gpu/drm/drm_atomic.c
@@ -47,7 +47,6 @@ void drm_atomic_state_default_release(struct drm_atomic_state 
*state)
kfree(state->crtcs);
kfree(state->crtc_states);
kfree(state->planes);
-   kfree(state->plane_states);
 }
 EXPORT_SYMBOL(drm_atomic_state_default_release);

@@ -79,10 +78,6 @@ drm_atomic_state_init(struct drm_device *dev, struct 
drm_atomic_state *state)
sizeof(*state->planes), GFP_KERNEL);
if (!state->planes)
goto fail;
-   state->plane_states = kcalloc(dev->mode_config.num_total_plane,
- sizeof(*state->plane_states), GFP_KERNEL);
-   if (!state->plane_states)
-   goto fail;

state->dev = dev;

@@ -163,15 +158,15 @@ void drm_atomic_state_default_clear(struct 
drm_atomic_state *state)
}

for (i = 0; i < config->num_total_plane; i++) {
-   struct drm_plane *plane = state->planes[i];
+   struct drm_plane *plane = state->planes[i].ptr;

if (!plane)
continue;

plane->funcs->atomic_destroy_state(plane,
-  state->plane_states[i]);
-   state->planes[i] = NULL;
-   state->plane_states[i] = NULL;
+  state->planes[i].state);
+   state->planes[i].ptr = NULL;
+   state->planes[i].state = NULL;
}
 }
 EXPORT_SYMBOL(drm_atomic_state_default_clear);
@@ -630,8 +625,8 @@ drm_atomic_get_plane_state(struct drm_atomic_state *state,
if (!plane_state)
return ERR_PTR(-ENOMEM);

-   state->plane_states[index] = plane_state;
-   state->planes[index] = plane;
+   state->planes[index].state = plane_state;
+   state->planes[index].ptr = plane;
plane_state->state = state;

DRM_DEBUG_ATOMIC("Added [PLANE:%d:%s] %p state to %p\n",
diff --git a/drivers/gpu/drm/drm_atomic_helper.c 
b/drivers/gpu/drm/drm_atomic_helper.c
index 0fb4868fdad6..f70d576f745e 100644
--- a/drivers/gpu/drm/drm_atomic_helper.c
+++ b/drivers/gpu/drm/drm_atomic_helper.c
@@ -1579,7 +1579,7 @@ void drm_atomic_helper_swap_state(struct drm_device *dev,

for_each_plane_in_state(state, plane, plane_state, i) {
plane->state->state = state;
-   swap(state->plane_states[i], plane->state);
+   swap(state->planes[i].state, plane->state);
plane->state->state = NULL;
}
 }
diff --git a/drivers/gpu/drm/i915/intel_atomic.c 
b/drivers/gpu/drm/i915/intel_atomic.c
index 3e6d9ff8840a..7542f5f5db1d 100644
--- a/drivers/gpu/drm/i915/intel_atomic.c
+++ b/drivers/gpu/drm/i915/intel_atomic.c
@@ -191,7 +191,7 @@ int intel_atomic_setup_scalers(struct drm_device *dev,

/* plane scaler case: assign as a plane scaler */
/* find the plane that set the bit as scaler_user */
-   plane = drm_state->planes[i];
+   plane = drm_state->planes[i].ptr;

/*
 * to enable/disable hq mode, add planes that are using 
scaler
diff --git a/include/drm/drm_atomic.h b/include/drm/drm_atomic.h
index 37478adb6a16..8e616d39353b 100644
--- a/include/drm/drm_atomic.h
+++ b/include/drm/drm_atomic.h
@@ -86,7 +86,7 @@ static inline struct drm_plane_state *
 drm_atomic_get_existing_plane_state(struct drm_atomic_state *state,
struct drm_plane *plane)
 {
-   return state->plane_states[drm_plane_index(plane)];
+   return state->planes[drm_plane_index(plane)].state;
 }

 /**
@@ -139,8 +139,8 @@ static inline const struct drm_plane_state *
 __drm_atomic_get_current_plane_state(struct drm_atomic_state *state,
 struct 

[PATCH 08/26] drm: Consolidate connector arrays in drm_atomic_state

2016-05-29 Thread Daniel Vetter
It's kinda pointless to have 2 separate mallocs for these. And when we
add more per-connector state in the future it's even more pointless.

Right now there's no such thing planned, but both Gustavo's per-crtc
fence patches, and some nonblocking commit helpers I'm playing around
with will add more per-crtc stuff. It makes sense to also consolidate
connectors, just for consistency.

In the future we can use this to store a pointer to the preceeding
state, making an atomic update entirely free-standing. This will be
needed to be able to queue them up with a depth > 1.

Cc: Gustavo Padovan 
Signed-off-by: Daniel Vetter 
---
 drivers/gpu/drm/drm_atomic.c| 27 +--
 drivers/gpu/drm/drm_atomic_helper.c |  2 +-
 include/drm/drm_atomic.h| 10 +-
 include/drm/drm_crtc.h  | 11 +++
 4 files changed, 22 insertions(+), 28 deletions(-)

diff --git a/drivers/gpu/drm/drm_atomic.c b/drivers/gpu/drm/drm_atomic.c
index 3ff1ed7b33db..a6395e9654af 100644
--- a/drivers/gpu/drm/drm_atomic.c
+++ b/drivers/gpu/drm/drm_atomic.c
@@ -44,7 +44,6 @@
 void drm_atomic_state_default_release(struct drm_atomic_state *state)
 {
kfree(state->connectors);
-   kfree(state->connector_states);
kfree(state->crtcs);
kfree(state->crtc_states);
kfree(state->planes);
@@ -139,15 +138,15 @@ void drm_atomic_state_default_clear(struct 
drm_atomic_state *state)
DRM_DEBUG_ATOMIC("Clearing atomic state %p\n", state);

for (i = 0; i < state->num_connector; i++) {
-   struct drm_connector *connector = state->connectors[i];
+   struct drm_connector *connector = state->connectors[i].ptr;

if (!connector)
continue;

connector->funcs->atomic_destroy_state(connector,
-  
state->connector_states[i]);
-   state->connectors[i] = NULL;
-   state->connector_states[i] = NULL;
+  
state->connectors[i].state);
+   state->connectors[i].ptr = NULL;
+   state->connectors[i].state = NULL;
drm_connector_unreference(connector);
}

@@ -896,8 +895,7 @@ drm_atomic_get_connector_state(struct drm_atomic_state 
*state,
index = drm_connector_index(connector);

if (index >= state->num_connector) {
-   struct drm_connector **c;
-   struct drm_connector_state **cs;
+   struct __drm_connnectors_state *c;
int alloc = max(index + 1, config->num_connector);

c = krealloc(state->connectors, alloc * 
sizeof(*state->connectors), GFP_KERNEL);
@@ -908,26 +906,19 @@ drm_atomic_get_connector_state(struct drm_atomic_state 
*state,
memset(>connectors[state->num_connector], 0,
   sizeof(*state->connectors) * (alloc - 
state->num_connector));

-   cs = krealloc(state->connector_states, alloc * 
sizeof(*state->connector_states), GFP_KERNEL);
-   if (!cs)
-   return ERR_PTR(-ENOMEM);
-
-   state->connector_states = cs;
-   memset(>connector_states[state->num_connector], 0,
-  sizeof(*state->connector_states) * (alloc - 
state->num_connector));
state->num_connector = alloc;
}

-   if (state->connector_states[index])
-   return state->connector_states[index];
+   if (state->connectors[index].state)
+   return state->connectors[index].state;

connector_state = connector->funcs->atomic_duplicate_state(connector);
if (!connector_state)
return ERR_PTR(-ENOMEM);

drm_connector_reference(connector);
-   state->connector_states[index] = connector_state;
-   state->connectors[index] = connector;
+   state->connectors[index].state = connector_state;
+   state->connectors[index].ptr = connector;
connector_state->state = state;

DRM_DEBUG_ATOMIC("Added [CONNECTOR:%d] %p state to %p\n",
diff --git a/drivers/gpu/drm/drm_atomic_helper.c 
b/drivers/gpu/drm/drm_atomic_helper.c
index 464541c87c40..0fb4868fdad6 100644
--- a/drivers/gpu/drm/drm_atomic_helper.c
+++ b/drivers/gpu/drm/drm_atomic_helper.c
@@ -1567,7 +1567,7 @@ void drm_atomic_helper_swap_state(struct drm_device *dev,

for_each_connector_in_state(state, connector, conn_state, i) {
connector->state->state = state;
-   swap(state->connector_states[i], connector->state);
+   swap(state->connectors[i].state, connector->state);
connector->state->state = NULL;
}

diff --git a/include/drm/drm_atomic.h b/include/drm/drm_atomic.h
index 4e97186293be..37478adb6a16 100644
--- a/include/drm/drm_atomic.h
+++ b/include/drm/drm_atomic.h
@@ -106,7 +106,7 @@ drm_atomic_get_existing_connector_state(struct 

[PATCH 07/26] drm/exynos: Use for_each_crtc_in_state

2016-05-29 Thread Daniel Vetter
We want to hide drm_atomic_state internals better.

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

diff --git a/drivers/gpu/drm/exynos/exynos_drm_drv.c 
b/drivers/gpu/drm/exynos/exynos_drm_drv.c
index 2dd820e23b0c..cabc5fd0246d 100644
--- a/drivers/gpu/drm/exynos/exynos_drm_drv.c
+++ b/drivers/gpu/drm/exynos/exynos_drm_drv.c
@@ -267,6 +267,8 @@ int exynos_atomic_commit(struct drm_device *dev, struct 
drm_atomic_state *state,
 {
struct exynos_drm_private *priv = dev->dev_private;
struct exynos_atomic_commit *commit;
+   struct drm_crtc *crtc;
+   struct drm_crtc_state *crtc_state;
int i, ret;

commit = kzalloc(sizeof(*commit), GFP_KERNEL);
@@ -288,10 +290,8 @@ int exynos_atomic_commit(struct drm_device *dev, struct 
drm_atomic_state *state,
/* Wait until all affected CRTCs have completed previous commits and
 * mark them as pending.
 */
-   for (i = 0; i < dev->mode_config.num_crtc; ++i) {
-   if (state->crtcs[i])
-   commit->crtcs |= 1 << drm_crtc_index(state->crtcs[i]);
-   }
+   for_each_crtc_in_state(state, crtc, crtc_state, i)
+   commit->crtcs |= 1 << drm_crtc_index(crtc);

wait_event(priv->wait, !commit_is_pending(priv, commit->crtcs));

-- 
2.8.1



[PATCH 06/26] drm/atomic: Add __drm_atomic_get_current_plane_state

2016-05-29 Thread Daniel Vetter
... and use it in msm Again just want to encapsulate
drm_atomic_state internals a bit.

The const threading is a bit awkward in vc4 since C sucks, but I still
think it's worth to enforce this. Eventually I want to make all the
obj->state pointers const too, but that's a lot more work ...

Cc: Eric Anholt 
Cc: Rob Clark 
Signed-off-by: Daniel Vetter 
---
 drivers/gpu/drm/msm/mdp/mdp5/mdp5_crtc.c | 10 +++--
 drivers/gpu/drm/vc4/vc4_crtc.c   | 11 +++---
 drivers/gpu/drm/vc4/vc4_drv.h|  2 +-
 drivers/gpu/drm/vc4/vc4_plane.c  |  5 +++--
 include/drm/drm_atomic.h | 36 
 5 files changed, 46 insertions(+), 18 deletions(-)

diff --git a/drivers/gpu/drm/msm/mdp/mdp5/mdp5_crtc.c 
b/drivers/gpu/drm/msm/mdp/mdp5/mdp5_crtc.c
index 88fe256c1931..6d4086ee0503 100644
--- a/drivers/gpu/drm/msm/mdp/mdp5/mdp5_crtc.c
+++ b/drivers/gpu/drm/msm/mdp/mdp5/mdp5_crtc.c
@@ -383,19 +383,15 @@ static int mdp5_crtc_atomic_check(struct drm_crtc *crtc,
 */
hw_cfg = mdp5_cfg_get_hw_config(mdp5_kms->cfg);
drm_atomic_crtc_state_for_each_plane(plane, state) {
-   struct drm_plane_state *pstate;
+   const struct drm_plane_state *pstate;
if (cnt >= (hw_cfg->lm.nb_stages)) {
dev_err(dev->dev, "too many planes!\n");
return -EINVAL;
}

-   pstate = state->state->plane_states[drm_plane_index(plane)];
+   pstate = __drm_atomic_get_current_plane_state(state->state,
+ plane);

-   /* plane might not have changed, in which case take
-* current state:
-*/
-   if (!pstate)
-   pstate = plane->state;
pstates[cnt].plane = plane;
pstates[cnt].state = to_mdp5_plane_state(pstate);

diff --git a/drivers/gpu/drm/vc4/vc4_crtc.c b/drivers/gpu/drm/vc4/vc4_crtc.c
index 904d0754ad78..703bda170105 100644
--- a/drivers/gpu/drm/vc4/vc4_crtc.c
+++ b/drivers/gpu/drm/vc4/vc4_crtc.c
@@ -405,14 +405,9 @@ static int vc4_crtc_atomic_check(struct drm_crtc *crtc,
return -EINVAL;

drm_atomic_crtc_state_for_each_plane(plane, state) {
-   struct drm_plane_state *plane_state =
-   state->state->plane_states[drm_plane_index(plane)];
-
-   /* plane might not have changed, in which case take
-* current state:
-*/
-   if (!plane_state)
-   plane_state = plane->state;
+   const struct drm_plane_state *plane_state =
+   __drm_atomic_get_current_plane_state(state->state,
+plane);

dlist_count += vc4_plane_dlist_size(plane_state);
}
diff --git a/drivers/gpu/drm/vc4/vc4_drv.h b/drivers/gpu/drm/vc4/vc4_drv.h
index 37cac59401d7..c799baabc008 100644
--- a/drivers/gpu/drm/vc4/vc4_drv.h
+++ b/drivers/gpu/drm/vc4/vc4_drv.h
@@ -469,7 +469,7 @@ int vc4_kms_load(struct drm_device *dev);
 struct drm_plane *vc4_plane_init(struct drm_device *dev,
 enum drm_plane_type type);
 u32 vc4_plane_write_dlist(struct drm_plane *plane, u32 __iomem *dlist);
-u32 vc4_plane_dlist_size(struct drm_plane_state *state);
+u32 vc4_plane_dlist_size(const struct drm_plane_state *state);
 void vc4_plane_async_set_fb(struct drm_plane *plane,
struct drm_framebuffer *fb);

diff --git a/drivers/gpu/drm/vc4/vc4_plane.c b/drivers/gpu/drm/vc4/vc4_plane.c
index 4037b52fde31..5d2c3d9fd17a 100644
--- a/drivers/gpu/drm/vc4/vc4_plane.c
+++ b/drivers/gpu/drm/vc4/vc4_plane.c
@@ -690,9 +690,10 @@ u32 vc4_plane_write_dlist(struct drm_plane *plane, u32 
__iomem *dlist)
return vc4_state->dlist_count;
 }

-u32 vc4_plane_dlist_size(struct drm_plane_state *state)
+u32 vc4_plane_dlist_size(const struct drm_plane_state *state)
 {
-   struct vc4_plane_state *vc4_state = to_vc4_plane_state(state);
+   const struct vc4_plane_state *vc4_state =
+   container_of(state, typeof(*vc4_state), base);

return vc4_state->dlist_count;
 }
diff --git a/include/drm/drm_atomic.h b/include/drm/drm_atomic.h
index 92c84e9ab09a..4e97186293be 100644
--- a/include/drm/drm_atomic.h
+++ b/include/drm/drm_atomic.h
@@ -109,6 +109,42 @@ drm_atomic_get_existing_connector_state(struct 
drm_atomic_state *state,
return state->connector_states[index];
 }

+/**
+ * __drm_atomic_get_current_plane_state - get current plane state
+ * @state: global atomic state object
+ * @plane: plane to grab
+ *
+ * This function returns the plane state for the given plane, either from
+ * @state, or if the plane isn't part of the atomic state update, from @plane.
+ * This is useful in atomic check callbacks, when drivers need to peek at, but
+ * not 

[PATCH 05/26] drm/vc4: Use for_each_plane_in_state

2016-05-29 Thread Daniel Vetter
We want to hide drm_atomic_stat internals a bit better.

Cc: Eric Anholt 
Signed-off-by: Daniel Vetter 
---
 drivers/gpu/drm/vc4/vc4_kms.c | 10 +++---
 1 file changed, 3 insertions(+), 7 deletions(-)

diff --git a/drivers/gpu/drm/vc4/vc4_kms.c b/drivers/gpu/drm/vc4/vc4_kms.c
index cb37751bc99f..39c0b2048bfd 100644
--- a/drivers/gpu/drm/vc4/vc4_kms.c
+++ b/drivers/gpu/drm/vc4/vc4_kms.c
@@ -111,6 +111,8 @@ static int vc4_atomic_commit(struct drm_device *dev,
int i;
uint64_t wait_seqno = 0;
struct vc4_commit *c;
+   struct drm_plane *plane;
+   struct drm_plane_state *new_state;

c = commit_init(state);
if (!c)
@@ -130,13 +132,7 @@ static int vc4_atomic_commit(struct drm_device *dev,
return ret;
}

-   for (i = 0; i < dev->mode_config.num_total_plane; i++) {
-   struct drm_plane *plane = state->planes[i];
-   struct drm_plane_state *new_state = state->plane_states[i];
-
-   if (!plane)
-   continue;
-
+   for_each_plane_in_state(state, plane, new_state, i) {
if ((plane->state->fb != new_state->fb) && new_state->fb) {
struct drm_gem_cma_object *cma_bo =
drm_fb_cma_get_gem_obj(new_state->fb, 0);
-- 
2.8.1



[PATCH 04/26] drm/rcar-du: Use for_each_*_in_state

2016-05-29 Thread Daniel Vetter
We want to hide drm_atomic_state internals better.

Cc: Laurent Pinchart 
Signed-off-by: Daniel Vetter 
---
 drivers/gpu/drm/rcar-du/rcar_du_kms.c   |  8 
 drivers/gpu/drm/rcar-du/rcar_du_plane.c | 20 
 2 files changed, 12 insertions(+), 16 deletions(-)

diff --git a/drivers/gpu/drm/rcar-du/rcar_du_kms.c 
b/drivers/gpu/drm/rcar-du/rcar_du_kms.c
index e70a4f33d970..f315c55c1f65 100644
--- a/drivers/gpu/drm/rcar-du/rcar_du_kms.c
+++ b/drivers/gpu/drm/rcar-du/rcar_du_kms.c
@@ -288,6 +288,8 @@ static int rcar_du_atomic_commit(struct drm_device *dev,
 {
struct rcar_du_device *rcdu = dev->dev_private;
struct rcar_du_commit *commit;
+   struct drm_crtc *crtc;
+   struct drm_crtc_state *crtc_state;
unsigned int i;
int ret;

@@ -309,10 +311,8 @@ static int rcar_du_atomic_commit(struct drm_device *dev,
/* Wait until all affected CRTCs have completed previous commits and
 * mark them as pending.
 */
-   for (i = 0; i < dev->mode_config.num_crtc; ++i) {
-   if (state->crtcs[i])
-   commit->crtcs |= 1 << drm_crtc_index(state->crtcs[i]);
-   }
+   for_each_crtc_in_state(state, crtc, crtc_state, i)
+   commit->crtcs |= 1 << drm_crtc_index(crtc);

spin_lock(>commit.wait.lock);
ret = wait_event_interruptible_locked(rcdu->commit.wait,
diff --git a/drivers/gpu/drm/rcar-du/rcar_du_plane.c 
b/drivers/gpu/drm/rcar-du/rcar_du_plane.c
index d445e67f78e1..bfe31ca870cc 100644
--- a/drivers/gpu/drm/rcar-du/rcar_du_plane.c
+++ b/drivers/gpu/drm/rcar-du/rcar_du_plane.c
@@ -140,18 +140,17 @@ int rcar_du_atomic_check_planes(struct drm_device *dev,
bool needs_realloc = false;
unsigned int groups = 0;
unsigned int i;
+   struct drm_plane *drm_plane;
+   struct drm_plane_state *drm_plane_state;

/* Check if hardware planes need to be reallocated. */
-   for (i = 0; i < dev->mode_config.num_total_plane; ++i) {
+   for_each_plane_in_state(state, drm_plane, drm_plane_state, i) {
struct rcar_du_plane_state *plane_state;
struct rcar_du_plane *plane;
unsigned int index;

-   if (!state->planes[i])
-   continue;
-
-   plane = to_rcar_plane(state->planes[i]);
-   plane_state = to_rcar_plane_state(state->plane_states[i]);
+   plane = to_rcar_plane(drm_plane);
+   plane_state = to_rcar_plane_state(drm_plane_state);

dev_dbg(rcdu->dev, "%s: checking plane (%u,%tu)\n", __func__,
plane->group->index, plane - plane->group->planes);
@@ -247,18 +246,15 @@ int rcar_du_atomic_check_planes(struct drm_device *dev,
}

/* Reallocate hardware planes for each plane that needs it. */
-   for (i = 0; i < dev->mode_config.num_total_plane; ++i) {
+   for_each_plane_in_state(state, drm_plane, drm_plane_state, i) {
struct rcar_du_plane_state *plane_state;
struct rcar_du_plane *plane;
unsigned int crtc_planes;
unsigned int free;
int idx;

-   if (!state->planes[i])
-   continue;
-
-   plane = to_rcar_plane(state->planes[i]);
-   plane_state = to_rcar_plane_state(state->plane_states[i]);
+   plane = to_rcar_plane(drm_plane);
+   plane_state = to_rcar_plane_state(drm_plane_state);

dev_dbg(rcdu->dev, "%s: allocating plane (%u,%tu)\n", __func__,
plane->group->index, plane - plane->group->planes);
-- 
2.8.1



[PATCH 03/26] drm/msm: Use for_each_*_in_state

2016-05-29 Thread Daniel Vetter
We want to hide drm_atomic_state internals

Cc: Rob Clark 
Signed-off-by: Daniel Vetter 
---
 drivers/gpu/drm/msm/mdp/mdp4/mdp4_kms.c| 20 +++--
 drivers/gpu/drm/msm/mdp/mdp5/mdp5_kms.c| 12 +++---
 drivers/gpu/drm/msm/msm_atomic.c   | 35 ++
 drivers/gpu/drm/rockchip/rockchip_drm_fb.c |  1 +
 4 files changed, 23 insertions(+), 45 deletions(-)

diff --git a/drivers/gpu/drm/msm/mdp/mdp4/mdp4_kms.c 
b/drivers/gpu/drm/msm/mdp/mdp4/mdp4_kms.c
index 67442d50a6c2..f145d256e332 100644
--- a/drivers/gpu/drm/msm/mdp/mdp4/mdp4_kms.c
+++ b/drivers/gpu/drm/msm/mdp/mdp4/mdp4_kms.c
@@ -106,31 +106,27 @@ out:
 static void mdp4_prepare_commit(struct msm_kms *kms, struct drm_atomic_state 
*state)
 {
struct mdp4_kms *mdp4_kms = to_mdp4_kms(to_mdp_kms(kms));
-   int i, ncrtcs = state->dev->mode_config.num_crtc;
+   int i;
+   struct drm_crtc *crtc;
+   struct drm_crtc_state *crtc_state;

mdp4_enable(mdp4_kms);

/* see 119ecb7fd */
-   for (i = 0; i < ncrtcs; i++) {
-   struct drm_crtc *crtc = state->crtcs[i];
-   if (!crtc)
-   continue;
+   for_each_crtc_in_state(state, crtc, crtc_state, i)
drm_crtc_vblank_get(crtc);
-   }
 }

 static void mdp4_complete_commit(struct msm_kms *kms, struct drm_atomic_state 
*state)
 {
struct mdp4_kms *mdp4_kms = to_mdp4_kms(to_mdp_kms(kms));
-   int i, ncrtcs = state->dev->mode_config.num_crtc;
+   int i;
+   struct drm_crtc *crtc;
+   struct drm_crtc_state *crtc_state;

/* see 119ecb7fd */
-   for (i = 0; i < ncrtcs; i++) {
-   struct drm_crtc *crtc = state->crtcs[i];
-   if (!crtc)
-   continue;
+   for_each_crtc_in_state(state, crtc, crtc_state, i)
drm_crtc_vblank_put(crtc);
-   }

mdp4_disable(mdp4_kms);
 }
diff --git a/drivers/gpu/drm/msm/mdp/mdp5/mdp5_kms.c 
b/drivers/gpu/drm/msm/mdp/mdp5/mdp5_kms.c
index 484b4d15e71d..f0c285b1c027 100644
--- a/drivers/gpu/drm/msm/mdp/mdp5/mdp5_kms.c
+++ b/drivers/gpu/drm/msm/mdp/mdp5/mdp5_kms.c
@@ -78,17 +78,11 @@ static void mdp5_complete_commit(struct msm_kms *kms, 
struct drm_atomic_state *s
 {
int i;
struct mdp5_kms *mdp5_kms = to_mdp5_kms(to_mdp_kms(kms));
-   int nplanes = mdp5_kms->dev->mode_config.num_total_plane;
-
-   for (i = 0; i < nplanes; i++) {
-   struct drm_plane *plane = state->planes[i];
-   struct drm_plane_state *plane_state = state->plane_states[i];
-
-   if (!plane)
-   continue;
+   struct drm_plane *plane;
+   struct drm_plane_state *plane_state;

+   for_each_plane_in_state(state, plane, plane_state, i)
mdp5_plane_complete_commit(plane, plane_state);
-   }

mdp5_disable(mdp5_kms);
 }
diff --git a/drivers/gpu/drm/msm/msm_atomic.c b/drivers/gpu/drm/msm/msm_atomic.c
index e3892c263f27..9c0e4261dbba 100644
--- a/drivers/gpu/drm/msm/msm_atomic.c
+++ b/drivers/gpu/drm/msm/msm_atomic.c
@@ -84,17 +84,12 @@ static void msm_atomic_wait_for_commit_done(struct 
drm_device *dev,
struct drm_atomic_state *old_state)
 {
struct drm_crtc *crtc;
+   struct drm_crtc_state *crtc_state;
struct msm_drm_private *priv = old_state->dev->dev_private;
struct msm_kms *kms = priv->kms;
-   int ncrtcs = old_state->dev->mode_config.num_crtc;
int i;

-   for (i = 0; i < ncrtcs; i++) {
-   crtc = old_state->crtcs[i];
-
-   if (!crtc)
-   continue;
-
+   for_each_crtc_in_state(old_state, crtc, crtc_state, i) {
if (!crtc->state->enable)
continue;

@@ -192,9 +187,11 @@ int msm_atomic_commit(struct drm_device *dev,
struct drm_atomic_state *state, bool nonblock)
 {
struct msm_drm_private *priv = dev->dev_private;
-   int nplanes = dev->mode_config.num_total_plane;
-   int ncrtcs = dev->mode_config.num_crtc;
struct msm_commit *c;
+   struct drm_crtc *crtc;
+   struct drm_crtc_state *crtc_state;
+   struct drm_plane *plane;
+   struct drm_plane_state *plane_state;
int i, ret;

ret = drm_atomic_helper_prepare_planes(dev, state);
@@ -210,28 +207,18 @@ int msm_atomic_commit(struct drm_device *dev,
/*
 * Figure out what crtcs we have:
 */
-   for (i = 0; i < ncrtcs; i++) {
-   struct drm_crtc *crtc = state->crtcs[i];
-   if (!crtc)
-   continue;
+   for_each_crtc_in_state(state, crtc, crtc_state, i)
c->crtc_mask |= (1 << drm_crtc_index(crtc));
-   }

/*
 * Figure out what fence to wait for:
 */
-   for (i = 0; i < nplanes; i++) {
-   struct drm_plane *plane = state->planes[i];
-   struct drm_plane_state *new_state = 

[PATCH 02/26] drm/i915: Use drm_atomic_get_existing_plane_state

2016-05-29 Thread Daniel Vetter
We want to encapsulate the drm_atomic_state internals.

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

diff --git a/drivers/gpu/drm/i915/intel_atomic.c 
b/drivers/gpu/drm/i915/intel_atomic.c
index 50ff90aea721..3e6d9ff8840a 100644
--- a/drivers/gpu/drm/i915/intel_atomic.c
+++ b/drivers/gpu/drm/i915/intel_atomic.c
@@ -223,7 +223,9 @@ int intel_atomic_setup_scalers(struct drm_device *dev,
continue;
}

-   plane_state = 
to_intel_plane_state(drm_state->plane_states[i]);
+   plane_state = to_intel_plane_state(
+   drm_atomic_get_existing_plane_state(drm_state,
+   plane));
scaler_id = _state->scaler_id;
}

-- 
2.8.1



[PATCH 01/26] drm/atomic-helper: use for_each_*_in_state more

2016-05-29 Thread Daniel Vetter
This avois leaking drm_atomic_state internals into the helpers. The
only place where this still happens after this patch is 
drm_atomic_helper_swap_state().
It's unavoidable there, and maybe a good indicator we should actually
move that function into drm_atomic.c.

Signed-off-by: Daniel Vetter 
---
 drivers/gpu/drm/drm_atomic_helper.c | 47 +
 1 file changed, 16 insertions(+), 31 deletions(-)

diff --git a/drivers/gpu/drm/drm_atomic_helper.c 
b/drivers/gpu/drm/drm_atomic_helper.c
index ddfa0d120e39..464541c87c40 100644
--- a/drivers/gpu/drm/drm_atomic_helper.c
+++ b/drivers/gpu/drm/drm_atomic_helper.c
@@ -611,7 +611,7 @@ drm_atomic_helper_check_planes(struct drm_device *dev,
if (!funcs || !funcs->atomic_check)
continue;

-   ret = funcs->atomic_check(crtc, state->crtc_states[i]);
+   ret = funcs->atomic_check(crtc, crtc_state);
if (ret) {
DRM_DEBUG_ATOMIC("[CRTC:%d:%s] atomic driver check 
failed\n",
 crtc->base.id, crtc->name);
@@ -1249,16 +1249,12 @@ EXPORT_SYMBOL(drm_atomic_helper_commit);
 int drm_atomic_helper_prepare_planes(struct drm_device *dev,
 struct drm_atomic_state *state)
 {
-   int nplanes = dev->mode_config.num_total_plane;
-   int ret, i;
+   struct drm_plane *plane;
+   struct drm_plane_state *plane_state;
+   int ret, i, j;

-   for (i = 0; i < nplanes; i++) {
+   for_each_plane_in_state(state, plane, plane_state, i) {
const struct drm_plane_helper_funcs *funcs;
-   struct drm_plane *plane = state->planes[i];
-   struct drm_plane_state *plane_state = state->plane_states[i];
-
-   if (!plane)
-   continue;

funcs = plane->helper_private;

@@ -1272,12 +1268,10 @@ int drm_atomic_helper_prepare_planes(struct drm_device 
*dev,
return 0;

 fail:
-   for (i--; i >= 0; i--) {
+   for_each_plane_in_state(state, plane, plane_state, j) {
const struct drm_plane_helper_funcs *funcs;
-   struct drm_plane *plane = state->planes[i];
-   struct drm_plane_state *plane_state = state->plane_states[i];

-   if (!plane)
+   if (j >= i)
continue;

funcs = plane->helper_private;
@@ -1564,35 +1558,26 @@ void drm_atomic_helper_swap_state(struct drm_device 
*dev,
  struct drm_atomic_state *state)
 {
int i;
+   struct drm_connector *connector;
+   struct drm_connector_state *conn_state;
+   struct drm_crtc *crtc;
+   struct drm_crtc_state *crtc_state;
+   struct drm_plane *plane;
+   struct drm_plane_state *plane_state;

-   for (i = 0; i < state->num_connector; i++) {
-   struct drm_connector *connector = state->connectors[i];
-
-   if (!connector)
-   continue;
-
+   for_each_connector_in_state(state, connector, conn_state, i) {
connector->state->state = state;
swap(state->connector_states[i], connector->state);
connector->state->state = NULL;
}

-   for (i = 0; i < dev->mode_config.num_crtc; i++) {
-   struct drm_crtc *crtc = state->crtcs[i];
-
-   if (!crtc)
-   continue;
-
+   for_each_crtc_in_state(state, crtc, crtc_state, i) {
crtc->state->state = state;
swap(state->crtc_states[i], crtc->state);
crtc->state->state = NULL;
}

-   for (i = 0; i < dev->mode_config.num_total_plane; i++) {
-   struct drm_plane *plane = state->planes[i];
-
-   if (!plane)
-   continue;
-
+   for_each_plane_in_state(state, plane, plane_state, i) {
plane->state->state = state;
swap(state->plane_states[i], plane->state);
plane->state->state = NULL;
-- 
2.8.1



[PATCH 00/26] RFC: generic nonblocking support in the atomic helpers

2016-05-29 Thread Daniel Vetter
Hi all,

So I finally unlazied and implemented generic nonblocking atomic commit support
in the atomic helpers. Still an early draft, but stopped being a fireworks show
on i915 at least. Rockchip still oopses somewhere, virtio conversion is entirely
untested. Same for arc/hdlcd/fsl-du/sun4i. All these untested drivers must be
converted since they've been a bit too lazy in their atomic implementations and
simply didn't bother implementing nonblocking.

The main patch adding the helpers explains the design, I just want to highlight
one key aspect: This code fully relies on correct handling of crtc_state->event,
drivers which don't get this right will fall over. To avoid too much trouble the
helpers all have a 10s timeout, in case of broken drivers. This is both good -
hopefully no more atomic drivers that just outright forget to implement drm
event handling. And also a bit annoying for getting this series in since the
above mentioned 5 atomic drivers all look like they haven't been properly tested
with events.

Stuff left to do:
- Debug at least rockchip I'd say to make sure it works there flawlessly.
  Would be good to also convert some other drivers.
- Get as much debugging on the other 4 drivers which have to be converted. Otoh
  they already have a broken atomic implementation in-tree, so me.
- Kerneldoc for a bunch of functions is still missing, plus the updated overview
  section for nonblocking commits.
- Bugfixing, but I hope that the helpers themselves are solid now.

Cheers, Daniel

Daniel Vetter (25):
  drm/atomic-helper: use for_each_*_in_state more
  drm/i915: Use drm_atomic_get_existing_plane_state
  drm/msm: Use for_each_*_in_state
  drm/rcar-du: Use for_each_*_in_state
  drm/vc4: Use for_each_plane_in_state
  drm/atomic: Add __drm_atomic_get_current_plane_state
  drm/exynos: Use for_each_crtc_in_state
  drm: Consolidate connector arrays in drm_atomic_state
  drm: Consolidate plane arrays in drm_atomic_state
  drm: Consolidate crtc arrays in drm_atomic_state
  drm/atomic-helper: Massage swap_state signature somewhat
  drm/arc: Nuke event_list
  drm/arc: Actually bother with handling atomic events.
  drm/arc: Implement nonblocking commit correctly
  drm/hdlcd: Use helper support for nonblocking commits
  drm/fsl-du: Implement some semblance of vblank event handling
  drm/hisilicon: Implement some semblance of vblank event handling
  drm/sun4i: Implement some semblance of vblank event handling
  drm/atomic: kerneldoc for drm_atomic_crtc_needs_modeset
  drm/atomic-helper: nonblocking commit support
  drm/i915: Signal drm events for atomic
  drm/i915: Roll out the helper nonblock tracking
  drm/rockchip: convert to helper nonblocking atomic commit
  drm/rockchip: Nuke pending event handling in preclose
  drm/virtio: Don't reinvent a flipping wheel

Gustavo Padovan (1):
  drm/fence: add fence to drm_pending_event

 drivers/gpu/drm/arc/arcpgu.h|   1 -
 drivers/gpu/drm/arc/arcpgu_crtc.c   |  19 +-
 drivers/gpu/drm/arc/arcpgu_drv.c|  27 +-
 drivers/gpu/drm/arm/hdlcd_drv.c |   8 +-
 drivers/gpu/drm/atmel-hlcdc/atmel_hlcdc_dc.c|   2 +-
 drivers/gpu/drm/drm_atomic.c| 102 +++---
 drivers/gpu/drm/drm_atomic_helper.c | 421 
 drivers/gpu/drm/drm_crtc.c  |   3 +
 drivers/gpu/drm/drm_fops.c  |  22 +-
 drivers/gpu/drm/exynos/exynos_drm_drv.c |  10 +-
 drivers/gpu/drm/fsl-dcu/fsl_dcu_drm_crtc.c  |  23 +-
 drivers/gpu/drm/hisilicon/kirin/kirin_drm_ade.c |  20 +-
 drivers/gpu/drm/i915/intel_atomic.c |   6 +-
 drivers/gpu/drm/i915/intel_display.c|  25 +-
 drivers/gpu/drm/i915/intel_sprite.c |  14 +
 drivers/gpu/drm/mediatek/mtk_drm_drv.c  |   2 +-
 drivers/gpu/drm/msm/mdp/mdp4/mdp4_kms.c |  20 +-
 drivers/gpu/drm/msm/mdp/mdp5/mdp5_crtc.c|  10 +-
 drivers/gpu/drm/msm/mdp/mdp5/mdp5_kms.c |  12 +-
 drivers/gpu/drm/msm/msm_atomic.c|  37 +--
 drivers/gpu/drm/nouveau/nouveau_usif.c  |   1 -
 drivers/gpu/drm/omapdrm/omap_drv.c  |   2 +-
 drivers/gpu/drm/rcar-du/rcar_du_kms.c   |  10 +-
 drivers/gpu/drm/rcar-du/rcar_du_plane.c |  20 +-
 drivers/gpu/drm/rockchip/rockchip_drm_drv.c |  25 --
 drivers/gpu/drm/rockchip/rockchip_drm_drv.h |  11 -
 drivers/gpu/drm/rockchip/rockchip_drm_fb.c  |  73 +---
 drivers/gpu/drm/rockchip/rockchip_drm_vop.c |  35 +-
 drivers/gpu/drm/sti/sti_drv.c   |   2 +-
 drivers/gpu/drm/sun4i/sun4i_crtc.c  |  12 +
 drivers/gpu/drm/tegra/drm.c |   2 +-
 drivers/gpu/drm/vc4/vc4_crtc.c  |  11 +-
 drivers/gpu/drm/vc4/vc4_drv.h   |   2 +-
 drivers/gpu/drm/vc4/vc4_kms.c   |  12 +-
 drivers/gpu/drm/vc4/vc4_plane.c |   5 +-
 drivers/gpu/drm/virtio/virtgpu_display.c|  48 +--
 

[RFT v3] drm: use late_initcall() for amdkfd and radeon

2016-05-29 Thread Daniel Vetter
On Fri, May 27, 2016 at 3:18 AM, Luis R. Rodriguez  wrote:
> To get KFD support in radeon we need the following
> initialization to happen in this order, their
> respective driver file that has its init routine
> listed next to it:
>
> 0. AMD IOMMUv1:arch/x86/kernel/pci-dma.c
> 1. AMD IOMMUv2:drivers/iommu/amd_iommu_v2.c
> 2. AMD KFD:drivers/gpu/drm/amd/amdkfd/kfd_module.c
> 3. AMD Radeon: drivers/gpu/drm/radeon/radeon_drv.c
>
> Order is rather implicit, but these drivers can currently
> only do so much given the amount of leg room available.
> Below are the respective init routines and how they are
> initialized:
>
> arch/x86/kernel/pci-dma.c   rootfs_initcall(pci_iommu_init);
> drivers/iommu/amd_iommu_v2.cmodule_init(amd_iommu_v2_init);
> drivers/gpu/drm/amd/amdkfd/kfd_module.c module_init(kfd_module_init);
> drivers/gpu/drm/radeon/radeon_drv.c module_init(radeon_init);
>
> When a driver is built-in module_init() folds to use
> device_initcall(), and we have the following possible
> orders:
>
> #define pure_initcall(fn)__define_initcall(fn, 0)
> #define core_initcall(fn)__define_initcall(fn, 1)
> #define postcore_initcall(fn)__define_initcall(fn, 2)
> #define arch_initcall(fn)__define_initcall(fn, 3)
> #define subsys_initcall(fn)  __define_initcall(fn, 4)
> #define fs_initcall(fn)  __define_initcall(fn, 5)
> -
> #define rootfs_initcall(fn)  __define_initcall(fn, rootfs)
> #define device_initcall(fn)  __define_initcall(fn, 6)
> #define late_initcall(fn)__define_initcall(fn, 7)
>
> Since we start off from rootfs_initcall(), it gives us 3 more
> levels of leg room to play with for order semantics, this isn't
> enough to address all required levels of dependencies, this
> is specially true given that AMD-KFD needs to be loaded before
> the radeon driver -- -but this it not enforced by symbols.
> If the AMD-KFD driver is not loaded prior to the radeon driver
> because otherwise the radeon driver will not initialize the
> AMD-KFD driver and you get no KFD functionality in userspace.
>
> Commit 1bacc894c227fad8a7 ("drivers: Move iommu/ before gpu/ in
> Makefile") works around some of the possibe races between
> the AMD IOMMU v2 and GPU drivers by changing the link order.
> This is fragile, however its the bets we can do, given that
> making the GPU drivers use late_initcall() would also implicate
> a similar race between them. That possible race is fortunatley
> addressed given that the drm Makefile currently has amdkfd
> linked prior to radeon:
>
> drivers/gpu/drm/Makefile
> ...
> obj-$(CONFIG_HSA_AMD) += amd/amdkfd/
> obj-$(CONFIG_DRM_RADEON)+= radeon/
> ...
>
> Changing amdkfd and radeon to late_initcall() however is
> still the right call in orde to annotate explicitly a
> delayed dependency requirement between the GPU drivers
> and the IOMMUs.
>
> We can't address the fragile nature of the link order
> right now, but in the future that might be possible.
>
> Signed-off-by: Luis R. Rodriguez 
> ---
>
> Please note, the changes to drivers/Makefile are just
> for the sake of forcing the possible race to occur,
> if this works well the actual [PATCH] submission will
> skip those changes as its pointless to remove those
> work arounds as it stands, due to the limited nature
> of the levels available for addressing requirements.
>
> Also, if you are aware of further dependency hell
> things like these -- please do let me know as I am
> interested in looking at addressing them.

This should be fixed with -EDEFER_PROBE instead. Frobbing initcall
levels should then just be done as an optimization to avoid too much
reprobing.

Thanks, Daniel
-- 
Daniel Vetter
Software Engineer, Intel Corporation
+41 (0) 79 365 57 48 - http://blog.ffwll.ch


[Bug 119181] Hang in amdgpu_vm_bo_update_mapping with powerplay enabled

2016-05-29 Thread bugzilla-dae...@bugzilla.kernel.org
https://bugzilla.kernel.org/show_bug.cgi?id=119181

--- Comment #1 from Hristo Venev  ---
The hang does not occur when the power state is set to low. There are also no
rendering glitches (otherwise some frames seem to have random triangles on
them).

-- 
You are receiving this mail because:
You are watching the assignee of the bug.


[PATCH v2] gpu: drm: amd: amdkfd: Remove create_workqueue()

2016-05-29 Thread Oded Gabbay
On Thu, May 26, 2016 at 10:37 PM, Bhaktipriya Shridhar
 wrote:
> alloc_workqueue replaces deprecated create_workqueue().
>
> create_workqueue has been replaced with alloc_workqueue with max_active
> as 0 since there is no need for throttling the number of active work items.
>
> WQ_MEM_RECLAIM has not been set to because kfd_process_wq will not be used in
> memory reclaim path.
>
> kfd_process_wq is used for delay destruction. A work item embedded in
> kfd_process gets queued to kfd_process_wq and when it executes it
> destroys and frees the containing kfd_process and thus itself.
>
> This requires a dedicated workqueue because a work item once queued, may
> get freed at any point of time and any external entity cannot
> flush the work item. So, in order to wait for such a work item,
> it needs to be put on a dedicated workqueue.
>
> kfd_module_exit() calls kfd_process_destroy_wq which ensures that all
> pending work items are finished before the module is removed.
>
> flush_workqueue is unnecessary since destroy_workqueue() itself calls
> drain_workqueue() which flushes repeatedly till the workqueue becomes empty.
>
> Hence flush_workqueue has been removed.
>
> Signed-off-by: Bhaktipriya Shridhar 
> ---
>  Changes in v2:
> - added explanation for setting concurrency value to
>   WQ_DFL_ACTIVE
> - added explanation for dropping WQ_MEM_RECLAIM
>
>  drivers/gpu/drm/amd/amdkfd/kfd_process.c | 3 +--
>  1 file changed, 1 insertion(+), 2 deletions(-)
>
> diff --git a/drivers/gpu/drm/amd/amdkfd/kfd_process.c 
> b/drivers/gpu/drm/amd/amdkfd/kfd_process.c
> index ac00579..b21d3fc8 100644
> --- a/drivers/gpu/drm/amd/amdkfd/kfd_process.c
> +++ b/drivers/gpu/drm/amd/amdkfd/kfd_process.c
> @@ -63,13 +63,12 @@ static struct kfd_process *create_process(const struct 
> task_struct *thread);
>  void kfd_process_create_wq(void)
>  {
> if (!kfd_process_wq)
> -   kfd_process_wq = create_workqueue("kfd_process_wq");
> +   kfd_process_wq = alloc_workqueue("kfd_process_wq",0,0);

You are missing a space between the arguments. Seem you forgot to run
checkpatch.pl ;)

Send a new patch and I'll add it to amdkfd's tree.

Thanks,

   Oded

>  }
>
>  void kfd_process_destroy_wq(void)
>  {
> if (kfd_process_wq) {
> -   flush_workqueue(kfd_process_wq);
> destroy_workqueue(kfd_process_wq);
> kfd_process_wq = NULL;
> }
> --
> 2.1.4
>


[Bug 119181] New: Hang in amdgpu_vm_bo_update_mapping with powerplay enabled

2016-05-29 Thread bugzilla-dae...@bugzilla.kernel.org
https://bugzilla.kernel.org/show_bug.cgi?id=119181

Bug ID: 119181
   Summary: Hang in amdgpu_vm_bo_update_mapping with powerplay
enabled
   Product: Drivers
   Version: 2.5
Kernel Version: 4.5.4
  Hardware: All
OS: Linux
  Tree: Mainline
Status: NEW
  Severity: normal
  Priority: P1
 Component: Video(DRI - non Intel)
  Assignee: drivers_video-dri at kernel-bugs.osdl.org
  Reporter: mustrumr97 at gmail.com
Regression: No

Created attachment 218111
  --> https://bugzilla.kernel.org/attachment.cgi?id=218111=edit
Stack trace (sysrq-w)

This happens after a few minutes in a 3D-intensive workload (e.g. Kerbal Space
Program). The game hangs, but the mouse is moving. A few seconds later the
mouse stops moving.

1. The game is waiting on an ioctl (libdrm:
amdgpu_fence_wait/amdgpu_cs_query_fence_status)
2. Xorg is in D state (see attached stack trace).
3. CPU load at ~0%.
4. Nothing interesting in kernel log.

The kernel has voluntary preemption enabled, the GPU is 1002:6938 (AMD Radeon
380X). It is at 56°C, quickly drops down to 51 when forced to low performance
state, goes up to 56 when at auto.

-- 
You are receiving this mail because:
You are watching the assignee of the bug.


[Nouveau] [PATCH 1/9] drm/nouveau: Don't leak runtime pm ref on driver unload

2016-05-29 Thread Lukas Wunner
Hi Peter,

On Fri, May 27, 2016 at 03:07:33AM +0200, Peter Wu wrote:
> On Tue, May 24, 2016 at 06:03:27PM +0200, Lukas Wunner wrote:
> > nouveau_drm_load() calls pm_runtime_put() if nouveau_runtime_pm != 0,
> > but nouveau_drm_unload() calls pm_runtime_get_sync() unconditionally.
> > We therefore leak a runtime pm ref whenever nouveau is loaded with
> > runpm=0 and then unloaded. The GPU will subsequently never runtime
> > suspend even if nouveau is loaded again with runpm=1.
> > 
> > Fix by taking the runtime pm ref under the same condition that it was
> > released on driver load.
> > 
> > Fixes: 5addcf0a5f0f ("nouveau: add runtime PM support (v0.9)")
> > Cc: Dave Airlie 
> > Reported-by: Karol Herbst 
> > Tested-by: Karol Herbst 
> > Signed-off-by: Lukas Wunner 
> 
> Looks good, I tested this scenario:
> 
> ru(){ cat /sys/bus/pci/devices/\:01:00.0/power/runtime_usage;}
> ru # reports 1
> modprobe nouveau runpm=0
> ru # reports 2
> rmmod nouveau
> ru # reports 1
> 
> Without runpm=0 the count drops to 0 in the second step and stays 0 in
> the third step. After applying patch 2/9, this correctly reports 1 as
> expected (this is the same as manually setting power/control to on).

How exactly did you reach the situation where the root port didn't wake
up when you tried to load nouveau again? (IRC conversation this week.)

What's happening is, the PCI core will keep unbound devices (i.e.,
without driver) in D0 but the runtime status is allowed to change
to "suspended". So it'll appear to the kernel as if it was suspended
but in reality it stays in D0.

Once runtime pm for PCIe ports gets merged, the root port above the
GPU will indeed go to D3 in such a situation because the check
pm_children_suspended() (called from rpm_check_suspend_allowed())
returns true.

I'm not sure if this is desirable or not. If we keep unbound devices
in D0, should we allow ports above them to go to D3?

In any case, when nouveau is loaded again, local_pci_probe() will
call pm_runtime_get_sync(), which will implicitly set the runtime
status to "active" and which should also wake parents. So how did
you ever reach a point where you loaded nouveau and the root port
stayed asleep? Clearly we have a bug there, question is where.
This shouldn't work only if pm_runtime_forbid() was called on
driver unload.

Thanks for the extensive testing!

Lukas

> 
> Peter
> 
> > ---
> >  drivers/gpu/drm/nouveau/nouveau_drm.c | 5 -
> >  1 file changed, 4 insertions(+), 1 deletion(-)
> > 
> > diff --git a/drivers/gpu/drm/nouveau/nouveau_drm.c 
> > b/drivers/gpu/drm/nouveau/nouveau_drm.c
> > index 11f8dd9..faf7438 100644
> > --- a/drivers/gpu/drm/nouveau/nouveau_drm.c
> > +++ b/drivers/gpu/drm/nouveau/nouveau_drm.c
> > @@ -498,7 +498,10 @@ nouveau_drm_unload(struct drm_device *dev)
> >  {
> > struct nouveau_drm *drm = nouveau_drm(dev);
> >  
> > -   pm_runtime_get_sync(dev->dev);
> > +   if (nouveau_runtime_pm != 0) {
> > +   pm_runtime_get_sync(dev->dev);
> > +   }
> > +
> > nouveau_fbcon_fini(dev);
> > nouveau_accel_fini(drm);
> > nouveau_hwmon_fini(dev);
> > -- 
> > 2.8.1
> > 
> > ___
> > Nouveau mailing list
> > Nouveau at lists.freedesktop.org
> > https://lists.freedesktop.org/mailman/listinfo/nouveau
> 
> -- 
> Kind regards,
> Peter Wu
> https://lekensteyn.nl


[RFT v3] drm: use late_initcall() for amdkfd and radeon

2016-05-29 Thread Oded Gabbay
On Fri, May 27, 2016 at 4:18 AM, Luis R. Rodriguez  wrote:
> To get KFD support in radeon we need the following
> initialization to happen in this order, their
> respective driver file that has its init routine
> listed next to it:
>
> 0. AMD IOMMUv1:arch/x86/kernel/pci-dma.c
> 1. AMD IOMMUv2:drivers/iommu/amd_iommu_v2.c
> 2. AMD KFD:drivers/gpu/drm/amd/amdkfd/kfd_module.c
> 3. AMD Radeon: drivers/gpu/drm/radeon/radeon_drv.c

Also AMD amdgpu (for VI+ APUs)
>
> Order is rather implicit, but these drivers can currently
> only do so much given the amount of leg room available.
> Below are the respective init routines and how they are
> initialized:
>
> arch/x86/kernel/pci-dma.c   rootfs_initcall(pci_iommu_init);
> drivers/iommu/amd_iommu_v2.cmodule_init(amd_iommu_v2_init);
> drivers/gpu/drm/amd/amdkfd/kfd_module.c module_init(kfd_module_init);
> drivers/gpu/drm/radeon/radeon_drv.c module_init(radeon_init);
>
> When a driver is built-in module_init() folds to use
> device_initcall(), and we have the following possible
> orders:
>
> #define pure_initcall(fn)__define_initcall(fn, 0)
> #define core_initcall(fn)__define_initcall(fn, 1)
> #define postcore_initcall(fn)__define_initcall(fn, 2)
> #define arch_initcall(fn)__define_initcall(fn, 3)
> #define subsys_initcall(fn)  __define_initcall(fn, 4)
> #define fs_initcall(fn)  __define_initcall(fn, 5)
> -
> #define rootfs_initcall(fn)  __define_initcall(fn, rootfs)
> #define device_initcall(fn)  __define_initcall(fn, 6)
> #define late_initcall(fn)__define_initcall(fn, 7)
>
> Since we start off from rootfs_initcall(), it gives us 3 more
> levels of leg room to play with for order semantics, this isn't
> enough to address all required levels of dependencies, this
> is specially true given that AMD-KFD needs to be loaded before
> the radeon driver -- -but this it not enforced by symbols.
> If the AMD-KFD driver is not loaded prior to the radeon driver
> because otherwise the radeon driver will not initialize the
> AMD-KFD driver and you get no KFD functionality in userspace.
>
> Commit 1bacc894c227fad8a7 ("drivers: Move iommu/ before gpu/ in
> Makefile") works around some of the possibe races between
> the AMD IOMMU v2 and GPU drivers by changing the link order.
> This is fragile, however its the bets we can do, given that
> making the GPU drivers use late_initcall() would also implicate
> a similar race between them. That possible race is fortunatley
> addressed given that the drm Makefile currently has amdkfd
> linked prior to radeon:
>
> drivers/gpu/drm/Makefile
> ...
> obj-$(CONFIG_HSA_AMD) += amd/amdkfd/
> obj-$(CONFIG_DRM_RADEON)+= radeon/
> ...
>
> Changing amdkfd and radeon to late_initcall() however is
> still the right call in orde to annotate explicitly a
> delayed dependency requirement between the GPU drivers
> and the IOMMUs.
>
> We can't address the fragile nature of the link order
> right now, but in the future that might be possible.
>
> Signed-off-by: Luis R. Rodriguez 
> ---
>
> Please note, the changes to drivers/Makefile are just
> for the sake of forcing the possible race to occur,
> if this works well the actual [PATCH] submission will
> skip those changes as its pointless to remove those
> work arounds as it stands, due to the limited nature
> of the levels available for addressing requirements.
>
> Also, if you are aware of further dependency hell
> things like these -- please do let me know as I am
> interested in looking at addressing them.
>
>  drivers/Makefile| 6 ++
>  drivers/gpu/drm/amd/amdkfd/kfd_module.c | 2 +-
>  drivers/gpu/drm/radeon/radeon_drv.c | 2 +-
>  3 files changed, 4 insertions(+), 6 deletions(-)
>
> diff --git a/drivers/Makefile b/drivers/Makefile
> index 0b6f3d60193d..0fbe3982041f 100644
> --- a/drivers/Makefile
> +++ b/drivers/Makefile
> @@ -50,10 +50,7 @@ obj-$(CONFIG_RESET_CONTROLLER)   += reset/
>  obj-y  += tty/
>  obj-y  += char/
>
> -# iommu/ comes before gpu as gpu are using iommu controllers
> -obj-$(CONFIG_IOMMU_SUPPORT)+= iommu/
> -
> -# gpu/ comes after char for AGP vs DRM startup and after iommu
> +# gpu/ comes after char for AGP vs DRM startup
>  obj-y  += gpu/
>
>  obj-$(CONFIG_CONNECTOR)+= connector/
> @@ -147,6 +144,7 @@ obj-y   += clk/
>
>  obj-$(CONFIG_MAILBOX)  += mailbox/
>  obj-$(CONFIG_HWSPINLOCK)   += hwspinlock/
> +obj-$(CONFIG_IOMMU_SUPPORT)+= iommu/
>  obj-$(CONFIG_REMOTEPROC)   += remoteproc/
>  obj-$(CONFIG_RPMSG)+= rpmsg/
>
> diff --git a/drivers/gpu/drm/amd/amdkfd/kfd_module.c 
> b/drivers/gpu/drm/amd/amdkfd/kfd_module.c
> index 850a5623661f..3d1dab8a31c7 100644
> --- a/drivers/gpu/drm/amd/amdkfd/kfd_module.c

[path v2 7/7] drm/hisilicon/hibmc: Add maintainer for Hibmc DRM

2016-05-29 Thread Rongrong Zou
Signed-off-by: Rongrong Zou 
Signed-off-by: Jianhua Li 
---
 MAINTAINERS | 7 +++
 1 file changed, 7 insertions(+)

diff --git a/MAINTAINERS b/MAINTAINERS
index f466673..a8a62e0 100644
--- a/MAINTAINERS
+++ b/MAINTAINERS
@@ -3957,6 +3957,13 @@ T:   git git://github.com/patjak/drm-gma500
 S: Maintained
 F: drivers/gpu/drm/gma500/

+DRM DRIVERS FOR HIBMC
+M: lijianhua 
+M: Rongrong Zou 
+L: dri-devel at lists.freedesktop.org
+S: Maintained
+F: drivers/gpu/drm/hisilicon/hibmc
+
 DRM DRIVERS FOR HISILICON
 M: Xinliang Liu 
 R: Xinwei Kong 
-- 
1.9.1



[path v2 6/7] drm/hisilicon/hibmc: Add support for frame buffer

2016-05-29 Thread Rongrong Zou
Add support for fbdev.

Signed-off-by: Rongrong Zou 
Signed-off-by: Jianhua Li 
---
 drivers/gpu/drm/hisilicon/hibmc/Makefile  |   2 +-
 drivers/gpu/drm/hisilicon/hibmc/hibmc_drm_drv.c   |  20 ++
 drivers/gpu/drm/hisilicon/hibmc/hibmc_drm_drv.h   |  17 ++
 drivers/gpu/drm/hisilicon/hibmc/hibmc_drm_fbdev.c | 286 ++
 4 files changed, 324 insertions(+), 1 deletion(-)
 create mode 100644 drivers/gpu/drm/hisilicon/hibmc/hibmc_drm_fbdev.c

diff --git a/drivers/gpu/drm/hisilicon/hibmc/Makefile 
b/drivers/gpu/drm/hisilicon/hibmc/Makefile
index 4e7797a..92e7b33 100644
--- a/drivers/gpu/drm/hisilicon/hibmc/Makefile
+++ b/drivers/gpu/drm/hisilicon/hibmc/Makefile
@@ -1,4 +1,4 @@
-hibmc-drm-y := hibmc_drm_drv.o hibmc_drm_de.o hibmc_drm_vdac.o 
hibmc_drm_power.o
+hibmc-drm-y := hibmc_drm_drv.o hibmc_drm_de.o hibmc_drm_vdac.o 
hibmc_drm_fbdev.o hibmc_drm_power.o

 obj-$(CONFIG_DRM_HISI_HIBMC)   +=hibmc-drm.o
 #obj-y += hibmc-drm.o
diff --git a/drivers/gpu/drm/hisilicon/hibmc/hibmc_drm_drv.c 
b/drivers/gpu/drm/hisilicon/hibmc/hibmc_drm_drv.c
index 70d79d2..e36a7ec 100644
--- a/drivers/gpu/drm/hisilicon/hibmc/hibmc_drm_drv.c
+++ b/drivers/gpu/drm/hisilicon/hibmc/hibmc_drm_drv.c
@@ -72,9 +72,16 @@ static int hibmc_pm_suspend(struct device *dev)
 {
struct pci_dev *pdev = to_pci_dev(dev);
struct drm_device *drm_dev = pci_get_drvdata(pdev);
+   struct hibmc_drm_device *hidev = drm_dev->dev_private;

drm_kms_helper_poll_disable(drm_dev);

+   if (hidev->fbdev.initialized) {
+   console_lock();
+   drm_fb_helper_set_suspend(>fbdev.helper, 1);
+   console_unlock();
+   }
+
return 0;
 }

@@ -82,8 +89,16 @@ static int hibmc_pm_resume(struct device *dev)
 {
struct pci_dev *pdev = to_pci_dev(dev);
struct drm_device *drm_dev = pci_get_drvdata(pdev);
+   struct hibmc_drm_device *hidev = drm_dev->dev_private;

drm_helper_resume_force_mode(drm_dev);
+
+   if (hidev->fbdev.initialized) {
+   console_lock();
+   drm_fb_helper_set_suspend(>fbdev.helper, 0);
+   console_unlock();
+   }
+
drm_kms_helper_poll_enable(drm_dev);

return 0;
@@ -245,6 +260,7 @@ static int hibmc_unload(struct drm_device *dev)
 {
struct hibmc_drm_device *hidev = dev->dev_private;

+   hibmc_fbdev_fini(hidev);
hibmc_kms_fini(hidev);
hibmc_hw_fini(hidev);
dev->dev_private = NULL;
@@ -278,6 +294,10 @@ static int hibmc_load(struct drm_device *dev, unsigned 
long flags)
/* reset all the states of crtc/plane/encoder/connector */
drm_mode_config_reset(dev);

+   ret = hibmc_fbdev_init(hidev);
+   if (ret)
+   goto err;
+
return 0;

 err:
diff --git a/drivers/gpu/drm/hisilicon/hibmc/hibmc_drm_drv.h 
b/drivers/gpu/drm/hisilicon/hibmc/hibmc_drm_drv.h
index eb5a892..1f32f2e 100644
--- a/drivers/gpu/drm/hisilicon/hibmc/hibmc_drm_drv.h
+++ b/drivers/gpu/drm/hisilicon/hibmc/hibmc_drm_drv.h
@@ -23,6 +23,18 @@
 #include 
 #include 

+struct hibmc_framebuffer {
+   struct drm_framebuffer fb;
+   struct drm_gem_cma_object *obj;
+   bool is_fbdev_fb;
+};
+
+struct hibmc_fbdev {
+   struct hibmc_framebuffer fb;
+   struct drm_fb_helper helper;
+   bool initialized;
+};
+
 struct hibmc_drm_device {
/* hw */
void __iomem   *mmio;
@@ -37,11 +49,16 @@ struct hibmc_drm_device {
struct drm_encoder encoder;
struct drm_connector connector;
bool mode_config_initialized;
+
+   /* fbdev */
+   struct hibmc_fbdev fbdev;
 };

 int hibmc_plane_init(struct hibmc_drm_device *hidev);
 int hibmc_crtc_init(struct hibmc_drm_device *hidev);
 int hibmc_encoder_init(struct hibmc_drm_device *hidev);
 int hibmc_connector_init(struct hibmc_drm_device *hidev);
+int hibmc_fbdev_init(struct hibmc_drm_device *hidev);
+void hibmc_fbdev_fini(struct hibmc_drm_device *hidev);

 #endif
diff --git a/drivers/gpu/drm/hisilicon/hibmc/hibmc_drm_fbdev.c 
b/drivers/gpu/drm/hisilicon/hibmc/hibmc_drm_fbdev.c
new file mode 100644
index 000..774bfb0
--- /dev/null
+++ b/drivers/gpu/drm/hisilicon/hibmc/hibmc_drm_fbdev.c
@@ -0,0 +1,286 @@
+/* Hisilicon Hibmc SoC drm driver
+ *
+ * Based on the bochs drm driver.
+ *
+ * Copyright (c) 2016 Huawei Limited.
+ *
+ * Author:
+ * Rongrong Zou 
+ * Rongrong Zou 
+ * Jianhua Li 
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ */
+
+#include 
+#include 
+#include 
+#include 
+
+#include "hibmc_drm_drv.h"
+
+/* -- */
+
+static void hibmc_drm_fb_destroy(struct drm_framebuffer *fb)
+{
+   struct hibmc_drm_device *hidev =
+   container_of(fb, 

[path v2 5/7] drm/hisilicon/hibmc: Add connector for VDAC

2016-05-29 Thread Rongrong Zou
Add connector funcs and helper funcs for VDAC.

Signed-off-by: Rongrong Zou 
Signed-off-by: Jianhua Li 
---
 drivers/gpu/drm/hisilicon/hibmc/hibmc_drm_drv.c  | 21 ++
 drivers/gpu/drm/hisilicon/hibmc/hibmc_drm_drv.h  |  3 +-
 drivers/gpu/drm/hisilicon/hibmc/hibmc_drm_vdac.c | 89 
 3 files changed, 112 insertions(+), 1 deletion(-)

diff --git a/drivers/gpu/drm/hisilicon/hibmc/hibmc_drm_drv.c 
b/drivers/gpu/drm/hisilicon/hibmc/hibmc_drm_drv.c
index 962072f..70d79d2 100644
--- a/drivers/gpu/drm/hisilicon/hibmc/hibmc_drm_drv.c
+++ b/drivers/gpu/drm/hisilicon/hibmc/hibmc_drm_drv.c
@@ -135,6 +135,14 @@ static int hibmc_kms_init(struct hibmc_drm_device *hidev)
return ret;
}

+   ret = hibmc_connector_init(hidev);
+   if (ret) {
+   DRM_ERROR("failed to init connector\n");
+   return ret;
+   }
+
+   drm_mode_connector_attach_encoder(>connector,
+ >encoder);
return 0;
 }

@@ -278,6 +286,12 @@ err:
return ret;
 }

+static void hibmc_connector_unplug_all(struct drm_device *dev)
+{
+   mutex_lock(>mode_config.mutex);
+   drm_connector_unregister_all(dev);
+   mutex_unlock(>mode_config.mutex);
+}

 static int hibmc_pci_probe(struct pci_dev *pdev,
   const struct pci_device_id *ent)
@@ -304,8 +318,14 @@ static int hibmc_pci_probe(struct pci_dev *pdev,
if (ret)
goto err_unload;

+   ret = drm_connector_register_all(dev);
+   if (ret)
+   goto err_unregister;
+
return 0;

+err_unregister:
+   drm_dev_unregister(dev);
 err_unload:
hibmc_unload(dev);
 err_disable:
@@ -320,6 +340,7 @@ static void hibmc_pci_remove(struct pci_dev *pdev)
 {
struct drm_device *dev = pci_get_drvdata(pdev);

+   hibmc_connector_unplug_all(dev);
drm_dev_unregister(dev);
hibmc_unload(dev);
drm_dev_unref(dev);
diff --git a/drivers/gpu/drm/hisilicon/hibmc/hibmc_drm_drv.h 
b/drivers/gpu/drm/hisilicon/hibmc/hibmc_drm_drv.h
index d0c5982..eb5a892 100644
--- a/drivers/gpu/drm/hisilicon/hibmc/hibmc_drm_drv.h
+++ b/drivers/gpu/drm/hisilicon/hibmc/hibmc_drm_drv.h
@@ -35,12 +35,13 @@ struct hibmc_drm_device {
struct drm_plane plane;
struct drm_crtc crtc;
struct drm_encoder encoder;
+   struct drm_connector connector;
bool mode_config_initialized;
 };

 int hibmc_plane_init(struct hibmc_drm_device *hidev);
 int hibmc_crtc_init(struct hibmc_drm_device *hidev);
 int hibmc_encoder_init(struct hibmc_drm_device *hidev);
-
+int hibmc_connector_init(struct hibmc_drm_device *hidev);

 #endif
diff --git a/drivers/gpu/drm/hisilicon/hibmc/hibmc_drm_vdac.c 
b/drivers/gpu/drm/hisilicon/hibmc/hibmc_drm_vdac.c
index cb9a130..b39ec65 100644
--- a/drivers/gpu/drm/hisilicon/hibmc/hibmc_drm_vdac.c
+++ b/drivers/gpu/drm/hisilicon/hibmc/hibmc_drm_vdac.c
@@ -24,6 +24,13 @@
 #include "hibmc_drm_drv.h"
 #include "hibmc_drm_regs.h"

+static int defx = 800;
+static int defy = 600;
+
+module_param(defx, int, 0444);
+module_param(defy, int, 0444);
+MODULE_PARM_DESC(defx, "default x resolution");
+MODULE_PARM_DESC(defy, "default y resolution");

 static void hibmc_encoder_disable(struct drm_encoder *encoder)
 {
@@ -83,3 +90,85 @@ int hibmc_encoder_init(struct hibmc_drm_device *hidev)
return 0;
 }

+static int hibmc_connector_get_modes(struct drm_connector *connector)
+{
+   int count;
+
+   count = drm_add_modes_noedid(connector, 800, 600);
+   drm_set_preferred_mode(connector, defx, defy);
+   return count;
+}
+
+static int hibmc_connector_mode_valid(struct drm_connector *connector,
+ struct drm_display_mode *mode)
+{
+   struct hibmc_drm_device *hiprivate =
+container_of(connector, struct hibmc_drm_device, connector);
+   unsigned long size = mode->hdisplay * mode->vdisplay * 4;
+
+   /*
+   * Make sure we can fit two framebuffers into video memory.
+   * This allows up to 1600x1200 with 16 MB (default size).
+   * If you want more try this:
+   * 'qemu -vga std -global VGA.vgamem_mb=32 $otherargs'
+   */
+   if (size * 2 > hiprivate->fb_size)
+   return MODE_BAD;
+
+   return MODE_OK;
+}
+
+static struct drm_encoder *
+hibmc_connector_best_encoder(struct drm_connector *connector)
+{
+   int enc_id = connector->encoder_ids[0];
+
+   /* pick the encoder ids */
+   if (enc_id)
+   return drm_encoder_find(connector->dev, enc_id);
+
+   return NULL;
+}
+
+static enum drm_connector_status hibmc_connector_detect(struct drm_connector
+*connector, bool force)
+{
+   return connector_status_connected;
+}
+
+static const struct drm_connector_helper_funcs
+   hibmc_connector_connector_helper_funcs = {
+   .get_modes = hibmc_connector_get_modes,
+   .mode_valid = 

[path v2 4/7] drm/hisilicon/hibmc: Add encoder for VDAC

2016-05-29 Thread Rongrong Zou
Add encoder funcs and helpers for VDAC.

Signed-off-by: Rongrong Zou 
Signed-off-by: Jianhua Li 
---
 drivers/gpu/drm/hisilicon/hibmc/Makefile |  2 +-
 drivers/gpu/drm/hisilicon/hibmc/hibmc_drm_drv.c  |  6 ++
 drivers/gpu/drm/hisilicon/hibmc/hibmc_drm_drv.h  |  2 +
 drivers/gpu/drm/hisilicon/hibmc/hibmc_drm_vdac.c | 85 
 4 files changed, 94 insertions(+), 1 deletion(-)
 create mode 100644 drivers/gpu/drm/hisilicon/hibmc/hibmc_drm_vdac.c

diff --git a/drivers/gpu/drm/hisilicon/hibmc/Makefile 
b/drivers/gpu/drm/hisilicon/hibmc/Makefile
index faa7e64..4e7797a 100644
--- a/drivers/gpu/drm/hisilicon/hibmc/Makefile
+++ b/drivers/gpu/drm/hisilicon/hibmc/Makefile
@@ -1,4 +1,4 @@
-hibmc-drm-y := hibmc_drm_drv.o hibmc_drm_de.o hibmc_drm_power.o
+hibmc-drm-y := hibmc_drm_drv.o hibmc_drm_de.o hibmc_drm_vdac.o 
hibmc_drm_power.o

 obj-$(CONFIG_DRM_HISI_HIBMC)   +=hibmc-drm.o
 #obj-y += hibmc-drm.o
diff --git a/drivers/gpu/drm/hisilicon/hibmc/hibmc_drm_drv.c 
b/drivers/gpu/drm/hisilicon/hibmc/hibmc_drm_drv.c
index f7837cc..962072f 100644
--- a/drivers/gpu/drm/hisilicon/hibmc/hibmc_drm_drv.c
+++ b/drivers/gpu/drm/hisilicon/hibmc/hibmc_drm_drv.c
@@ -129,6 +129,12 @@ static int hibmc_kms_init(struct hibmc_drm_device *hidev)
return ret;
}

+   ret = hibmc_encoder_init(hidev);
+   if (ret) {
+   DRM_ERROR("failed to init encoder\n");
+   return ret;
+   }
+
return 0;
 }

diff --git a/drivers/gpu/drm/hisilicon/hibmc/hibmc_drm_drv.h 
b/drivers/gpu/drm/hisilicon/hibmc/hibmc_drm_drv.h
index e64ec8d..d0c5982 100644
--- a/drivers/gpu/drm/hisilicon/hibmc/hibmc_drm_drv.h
+++ b/drivers/gpu/drm/hisilicon/hibmc/hibmc_drm_drv.h
@@ -34,11 +34,13 @@ struct hibmc_drm_device {
struct drm_device  *dev;
struct drm_plane plane;
struct drm_crtc crtc;
+   struct drm_encoder encoder;
bool mode_config_initialized;
 };

 int hibmc_plane_init(struct hibmc_drm_device *hidev);
 int hibmc_crtc_init(struct hibmc_drm_device *hidev);
+int hibmc_encoder_init(struct hibmc_drm_device *hidev);


 #endif
diff --git a/drivers/gpu/drm/hisilicon/hibmc/hibmc_drm_vdac.c 
b/drivers/gpu/drm/hisilicon/hibmc/hibmc_drm_vdac.c
new file mode 100644
index 000..cb9a130
--- /dev/null
+++ b/drivers/gpu/drm/hisilicon/hibmc/hibmc_drm_vdac.c
@@ -0,0 +1,85 @@
+/* Hisilicon Hibmc SoC drm driver
+ *
+ * Based on the bochs drm driver.
+ *
+ * Copyright (c) 2016 Huawei Limited.
+ *
+ * Author:
+ * Rongrong Zou 
+ * Rongrong Zou 
+ * Jianhua Li 
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ */
+
+#include 
+#include 
+#include 
+#include 
+
+#include "hibmc_drm_drv.h"
+#include "hibmc_drm_regs.h"
+
+
+static void hibmc_encoder_disable(struct drm_encoder *encoder)
+{
+}
+
+static void hibmc_encoder_enable(struct drm_encoder *encoder)
+{
+}
+
+static void hibmc_encoder_mode_set(struct drm_encoder *encoder,
+  struct drm_display_mode *mode,
+  struct drm_display_mode *adj_mode)
+{
+   u32 reg;
+   struct drm_device *dev = encoder->dev;
+   struct hibmc_drm_device *hidev = dev->dev_private;
+
+   /* just open DISPLAY_CONTROL_HISILE register bit 3:0*/
+   reg = readl(hidev->mmio + DISPLAY_CONTROL_HISILE);
+   reg |= 0xf;
+   writel(reg, hidev->mmio + DISPLAY_CONTROL_HISILE);
+}
+
+static int hibmc_encoder_atomic_check(struct drm_encoder *encoder,
+ struct drm_crtc_state *crtc_state,
+ struct drm_connector_state *conn_state)
+{
+   return 0;
+}
+
+static const struct drm_encoder_helper_funcs hibmc_encoder_helper_funcs = {
+   .mode_set = hibmc_encoder_mode_set,
+   .disable = hibmc_encoder_disable,
+   .enable = hibmc_encoder_enable,
+   .atomic_check = hibmc_encoder_atomic_check,
+};
+
+static const struct drm_encoder_funcs hibmc_encoder_encoder_funcs = {
+   .destroy = drm_encoder_cleanup,
+};
+
+int hibmc_encoder_init(struct hibmc_drm_device *hidev)
+{
+   struct drm_device *dev = hidev->dev;
+   struct drm_encoder *encoder = >encoder;
+   int ret;
+
+   encoder->possible_crtcs = 0x1;
+   ret = drm_encoder_init(dev, encoder, _encoder_encoder_funcs,
+  DRM_MODE_ENCODER_DAC, NULL);
+   if (ret) {
+   DRM_ERROR("failed to init encoder\n");
+   return ret;
+   }
+
+   drm_encoder_helper_add(encoder, _encoder_helper_funcs);
+   return 0;
+}
+
-- 
1.9.1



[path v2 3/7] drm/hisilicon/hibmc: Add crtc for DE

2016-05-29 Thread Rongrong Zou
Add crtc funcs and helper funcs for DE.

Signed-off-by: Rongrong Zou 
Signed-off-by: Jianhua Li 
---
 drivers/gpu/drm/hisilicon/hibmc/hibmc_drm_de.c  | 307 
 drivers/gpu/drm/hisilicon/hibmc/hibmc_drm_de.h  |  29 +++
 drivers/gpu/drm/hisilicon/hibmc/hibmc_drm_drv.c |   6 +
 drivers/gpu/drm/hisilicon/hibmc/hibmc_drm_drv.h |   2 +
 4 files changed, 344 insertions(+)
 create mode 100644 drivers/gpu/drm/hisilicon/hibmc/hibmc_drm_de.h

diff --git a/drivers/gpu/drm/hisilicon/hibmc/hibmc_drm_de.c 
b/drivers/gpu/drm/hisilicon/hibmc/hibmc_drm_de.c
index e8e5853..87a7e52 100644
--- a/drivers/gpu/drm/hisilicon/hibmc/hibmc_drm_de.c
+++ b/drivers/gpu/drm/hisilicon/hibmc/hibmc_drm_de.c
@@ -26,6 +26,7 @@

 #include "hibmc_drm_drv.h"
 #include "hibmc_drm_regs.h"
+#include "hibmc_drm_de.h"
 #include "hibmc_drm_power.h"

 /* -- */
@@ -168,3 +169,309 @@ int hibmc_plane_init(struct hibmc_drm_device *hidev)
return 0;
 }

+static void hibmc_crtc_enable(struct drm_crtc *crtc)
+{
+   unsigned int reg;
+   /* power mode 0 is default. */
+   struct hibmc_drm_device *hidev = crtc->dev->dev_private;
+
+   hibmc_set_power_mode(hidev, HIBMC_PW_MODE_CTL_MODE_MODE0);
+
+   /* Enable display power gate & LOCALMEM power gate*/
+   reg = readl(hidev->mmio + HIBMC_CURRENT_GATE);
+   reg &= ~HIBMC_CURR_GATE_LOCALMEM_MASK;
+   reg &= ~HIBMC_CURR_GATE_DISPLAY_MASK;
+   reg |= HIBMC_CURR_GATE_LOCALMEM(ON);
+   reg |= HIBMC_CURR_GATE_DISPLAY(ON);
+   hibmc_set_current_gate(hidev, reg);
+}
+
+static void hibmc_crtc_disable(struct drm_crtc *crtc)
+{
+   unsigned int reg;
+   struct hibmc_drm_device *hidev = crtc->dev->dev_private;
+
+   hibmc_set_power_mode(hidev, HIBMC_PW_MODE_CTL_MODE_SLEEP);
+
+   /* Enable display power gate & LOCALMEM power gate*/
+   reg = readl(hidev->mmio + HIBMC_CURRENT_GATE);
+   reg &= ~HIBMC_CURR_GATE_LOCALMEM_MASK;
+   reg &= ~HIBMC_CURR_GATE_DISPLAY_MASK;
+   reg |= HIBMC_CURR_GATE_LOCALMEM(OFF);
+   reg |= HIBMC_CURR_GATE_DISPLAY(OFF);
+   hibmc_set_current_gate(hidev, reg);
+}
+
+static int hibmc_crtc_atomic_check(struct drm_crtc *crtc,
+   struct drm_crtc_state *state)
+{
+   return 0;
+}
+
+static unsigned int format_pll_reg(void)
+{
+   unsigned int pllreg = 0;
+   struct panel_pll pll = {0};
+
+   /* Note that all PLL's have the same format. Here,
+   * we just use Panel PLL parameter to work out the bit
+   * fields in the register.On returning a 32 bit number, the value can
+   * be applied to any PLL in the calling function.
+   */
+   pllreg |= HIBMC_PLL_CTRL_BYPASS(OFF) & HIBMC_PLL_CTRL_BYPASS_MASK;
+   pllreg |= HIBMC_PLL_CTRL_POWER(ON) & HIBMC_PLL_CTRL_POWER_MASK;
+   pllreg |= HIBMC_PLL_CTRL_INPUT(OSC) & HIBMC_PLL_CTRL_INPUT_MASK;
+   pllreg |= HIBMC_PLL_CTRL_POD(pll.POD) & HIBMC_PLL_CTRL_POD_MASK;
+   pllreg |= HIBMC_PLL_CTRL_OD(pll.OD) & HIBMC_PLL_CTRL_OD_MASK;
+   pllreg |= HIBMC_PLL_CTRL_N(pll.N) & HIBMC_PLL_CTRL_N_MASK;
+   pllreg |= HIBMC_PLL_CTRL_M(pll.M) & HIBMC_PLL_CTRL_M_MASK;
+
+   return pllreg;
+}
+
+static void set_vclock_hisilicon(struct drm_device *dev, unsigned long pll)
+{
+   unsigned long tmp0, tmp1;
+   struct hibmc_drm_device *hidev = dev->dev_private;
+
+/* 1. outer_bypass_n=0 */
+   tmp0 = readl(hidev->mmio + CRT_PLL1_HS);
+   tmp0 &= 0xBFFF;
+   writel(tmp0, hidev->mmio + CRT_PLL1_HS);
+
+   /* 2. pll_pd=1?inter_bypass=1 */
+   writel(0x2100, hidev->mmio + CRT_PLL1_HS);
+
+   /* 3. config pll */
+   writel(pll, hidev->mmio + CRT_PLL1_HS);
+
+   /* 4. delay  */
+   mdelay(1);
+
+   /* 5. pll_pd =0 */
+   tmp1 = pll & ~0x0100;
+   writel(tmp1, hidev->mmio + CRT_PLL1_HS);
+
+   /* 6. delay  */
+   mdelay(1);
+
+   /* 7. inter_bypass=0 */
+   tmp1 &= ~0x2000;
+   writel(tmp1, hidev->mmio + CRT_PLL1_HS);
+
+   /* 8. delay  */
+   mdelay(1);
+
+   /* 9. outer_bypass_n=1 */
+   tmp1 |= 0x4000;
+   writel(tmp1, hidev->mmio + CRT_PLL1_HS);
+}
+
+/* This function takes care the extra registers and bit fields required to
+*setup a mode in board.
+*Explanation about Display Control register:
+*FPGA only supports 7 predefined pixel clocks, and clock select is
+*in bit 4:0 of new register 0x802a8.
+*/
+static unsigned int display_ctrl_adjust(struct drm_device *dev,
+   struct drm_display_mode *mode,
+   unsigned int ctrl)
+{
+   unsigned long x, y;
+   unsigned long pll1; /* bit[31:0] of PLL */
+   unsigned long pll2; /* bit[63:32] of PLL */
+   struct hibmc_drm_device *hidev = dev->dev_private;
+
+   x = mode->hdisplay;
+   y = mode->vdisplay;
+
+   /* Hisilicon has to set up a new register for PLL control
+

[path v2 2/7] drm/hisilicon/hibmc: Add plane for DE

2016-05-29 Thread Rongrong Zou
Add plane funcs and helper funcs for DE.

Signed-off-by: Rongrong Zou 
Signed-off-by: Jianhua Li 
---
 drivers/gpu/drm/hisilicon/hibmc/Makefile|   2 +-
 drivers/gpu/drm/hisilicon/hibmc/hibmc_drm_de.c  | 170 
 drivers/gpu/drm/hisilicon/hibmc/hibmc_drm_drv.c |  41 +-
 drivers/gpu/drm/hisilicon/hibmc/hibmc_drm_drv.h |   3 +
 4 files changed, 214 insertions(+), 2 deletions(-)
 create mode 100644 drivers/gpu/drm/hisilicon/hibmc/hibmc_drm_de.c

diff --git a/drivers/gpu/drm/hisilicon/hibmc/Makefile 
b/drivers/gpu/drm/hisilicon/hibmc/Makefile
index 533f9ed..faa7e64 100644
--- a/drivers/gpu/drm/hisilicon/hibmc/Makefile
+++ b/drivers/gpu/drm/hisilicon/hibmc/Makefile
@@ -1,4 +1,4 @@
-hibmc-drm-y := hibmc_drm_drv.o hibmc_drm_power.o
+hibmc-drm-y := hibmc_drm_drv.o hibmc_drm_de.o hibmc_drm_power.o

 obj-$(CONFIG_DRM_HISI_HIBMC)   +=hibmc-drm.o
 #obj-y += hibmc-drm.o
diff --git a/drivers/gpu/drm/hisilicon/hibmc/hibmc_drm_de.c 
b/drivers/gpu/drm/hisilicon/hibmc/hibmc_drm_de.c
new file mode 100644
index 000..e8e5853
--- /dev/null
+++ b/drivers/gpu/drm/hisilicon/hibmc/hibmc_drm_de.c
@@ -0,0 +1,170 @@
+/* Hisilicon Hibmc SoC drm driver
+ *
+ * Based on the bochs drm driver.
+ *
+ * Copyright (c) 2016 Huawei Limited.
+ *
+ * Author:
+ * Rongrong Zou 
+ * Rongrong Zou 
+ * Jianhua Li 
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ */
+
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+
+#include "hibmc_drm_drv.h"
+#include "hibmc_drm_regs.h"
+#include "hibmc_drm_power.h"
+
+/* -- */
+
+static int hibmc_plane_prepare_fb(struct drm_plane *plane,
+  const struct drm_plane_state *new_state)
+{
+   /* do nothing */
+   return 0;
+}
+
+static void hibmc_plane_cleanup_fb(struct drm_plane *plane,
+  const struct drm_plane_state *old_state)
+{
+   /* do nothing */
+}
+
+static int hibmc_plane_atomic_check(struct drm_plane *plane,
+   struct drm_plane_state *state)
+{
+   struct drm_framebuffer *fb = state->fb;
+   struct drm_crtc *crtc = state->crtc;
+   struct drm_crtc_state *crtc_state;
+   u32 src_x = state->src_x >> 16;
+   u32 src_y = state->src_y >> 16;
+   u32 src_w = state->src_w >> 16;
+   u32 src_h = state->src_h >> 16;
+   int crtc_x = state->crtc_x;
+   int crtc_y = state->crtc_y;
+   u32 crtc_w = state->crtc_w;
+   u32 crtc_h = state->crtc_h;
+
+   if (!crtc || !fb)
+   return 0;
+
+   crtc_state = drm_atomic_get_crtc_state(state->state, crtc);
+   if (IS_ERR(crtc_state))
+   return PTR_ERR(crtc_state);
+
+   if (src_w != crtc_w || src_h != crtc_h) {
+   DRM_ERROR("Scale not support!!!\n");
+   return -EINVAL;
+   }
+
+   if (src_x + src_w > fb->width ||
+   src_y + src_h > fb->height)
+   return -EINVAL;
+
+   if (crtc_x < 0 || crtc_y < 0)
+   return -EINVAL;
+
+   if (crtc_x + crtc_w > crtc_state->adjusted_mode.hdisplay ||
+   crtc_y + crtc_h > crtc_state->adjusted_mode.vdisplay)
+   return -EINVAL;
+
+   return 0;
+}
+
+static void hibmc_plane_atomic_update(struct drm_plane *plane,
+ struct drm_plane_state *old_state)
+{
+   struct drm_plane_state  *state  = plane->state;
+   u32 reg;
+   unsigned int line_l;
+   struct hibmc_drm_device *hidev =
+   (struct hibmc_drm_device *)plane->dev->dev_private;
+
+   /* now just support one plane */
+   writel(0, hidev->mmio + HIBMC_CRT_FB_ADDRESS);
+   reg = state->fb->width * (state->fb->bits_per_pixel >> 3);
+   /* now line_pad is 16 */
+   reg = PADDING(16, reg);
+
+   line_l = state->fb->width * state->fb->bits_per_pixel / 8;
+   line_l = PADDING(16, line_l);
+   writel((HIBMC_CRT_FB_WIDTH_WIDTH(reg) & HIBMC_CRT_FB_WIDTH_WIDTH_MASK) |
+  (HIBMC_CRT_FB_WIDTH_OFFS(line_l) & HIBMC_CRT_FB_WIDTH_OFFS_MASK),
+  hidev->mmio + HIBMC_CRT_FB_WIDTH);
+
+   /* SET PIXEL FORMAT */
+   reg = readl(hidev->mmio + HIBMC_CRT_DISP_CTL);
+   reg = reg & ~HIBMC_CRT_DISP_CTL_FORMAT_MASK;
+   reg = reg | (HIBMC_CRT_DISP_CTL_FORMAT(state->fb->bits_per_pixel >> 4) &
+HIBMC_CRT_DISP_CTL_FORMAT_MASK);
+   writel(reg, hidev->mmio + HIBMC_CRT_DISP_CTL);
+}
+
+static void hibmc_plane_atomic_disable(struct drm_plane *plane,
+  struct drm_plane_state *old_state)
+{
+}
+
+static const u32 channel_formats1[] = {
+   DRM_FORMAT_RGB565, DRM_FORMAT_BGR565, DRM_FORMAT_RGB888,
+   

[path v2 1/7] drm/hisilicon/hibmc: Add hisilicon hibmc drm master driver

2016-05-29 Thread Rongrong Zou
Add DRM master driver for Hisilicon Hibmc SoC which used for
Out-of-band management. Blow is the general hardware connection,
both the Hibmc and the host CPU are on the same mother board.

+--+   +--+
|  | PCIe  |  Hibmc   |
|host CPU( |<->| display  |
|arm64,x86)|   |subsystem |
+--+   +--+

Signed-off-by: Rongrong Zou 
Signed-off-by: Jianhua Li 
---
 drivers/gpu/drm/hisilicon/Kconfig |   1 +
 drivers/gpu/drm/hisilicon/Makefile|   3 +-
 drivers/gpu/drm/hisilicon/hibmc/Kconfig   |  13 +
 drivers/gpu/drm/hisilicon/hibmc/Makefile  |   4 +
 drivers/gpu/drm/hisilicon/hibmc/hibmc_drm_drv.c   | 307 ++
 drivers/gpu/drm/hisilicon/hibmc/hibmc_drm_drv.h   |  39 +++
 drivers/gpu/drm/hisilicon/hibmc/hibmc_drm_power.c |  91 +++
 drivers/gpu/drm/hisilicon/hibmc/hibmc_drm_power.h |  28 ++
 drivers/gpu/drm/hisilicon/hibmc/hibmc_drm_regs.h  | 214 +++
 9 files changed, 699 insertions(+), 1 deletion(-)
 create mode 100644 drivers/gpu/drm/hisilicon/hibmc/Kconfig
 create mode 100644 drivers/gpu/drm/hisilicon/hibmc/Makefile
 create mode 100644 drivers/gpu/drm/hisilicon/hibmc/hibmc_drm_drv.c
 create mode 100644 drivers/gpu/drm/hisilicon/hibmc/hibmc_drm_drv.h
 create mode 100644 drivers/gpu/drm/hisilicon/hibmc/hibmc_drm_power.c
 create mode 100644 drivers/gpu/drm/hisilicon/hibmc/hibmc_drm_power.h
 create mode 100644 drivers/gpu/drm/hisilicon/hibmc/hibmc_drm_regs.h

diff --git a/drivers/gpu/drm/hisilicon/Kconfig 
b/drivers/gpu/drm/hisilicon/Kconfig
index 558c61b..2fd2724 100644
--- a/drivers/gpu/drm/hisilicon/Kconfig
+++ b/drivers/gpu/drm/hisilicon/Kconfig
@@ -2,4 +2,5 @@
 # hisilicon drm device configuration.
 # Please keep this list sorted alphabetically

+source "drivers/gpu/drm/hisilicon/hibmc/Kconfig"
 source "drivers/gpu/drm/hisilicon/kirin/Kconfig"
diff --git a/drivers/gpu/drm/hisilicon/Makefile 
b/drivers/gpu/drm/hisilicon/Makefile
index e3f6d49..4d7185c 100644
--- a/drivers/gpu/drm/hisilicon/Makefile
+++ b/drivers/gpu/drm/hisilicon/Makefile
@@ -2,4 +2,5 @@
 # Makefile for hisilicon drm drivers.
 # Please keep this list sorted alphabetically

-obj-$(CONFIG_DRM_HISI_KIRIN) += kirin/
+obj-$(CONFIG_DRM_HISI_HIBMC) += hibmc/
+obj-$(CONFIG_DRM_HISI_KIRIN) += kirin/
\ No newline at end of file
diff --git a/drivers/gpu/drm/hisilicon/hibmc/Kconfig 
b/drivers/gpu/drm/hisilicon/hibmc/Kconfig
new file mode 100644
index 000..1e7810d
--- /dev/null
+++ b/drivers/gpu/drm/hisilicon/hibmc/Kconfig
@@ -0,0 +1,13 @@
+config DRM_HISI_HIBMC
+   tristate "DRM Support for Hisilicon Hibmc"
+   depends on DRM && PCI
+   select DRM_KMS_HELPER
+   select DRM_KMS_FB_HELPER
+   select DRM_GEM_CMA_HELPER
+   select DRM_KMS_CMA_HELPER
+   select FB_SYS_FILLRECT
+   select FB_SYS_COPYAREA
+   select FB_SYS_IMAGEBLIT
+   help
+ Choose this option if you have a Hisilicon Hibmc soc chipset.
+ If M is selected the module will be called hibmc-drm.
diff --git a/drivers/gpu/drm/hisilicon/hibmc/Makefile 
b/drivers/gpu/drm/hisilicon/hibmc/Makefile
new file mode 100644
index 000..533f9ed
--- /dev/null
+++ b/drivers/gpu/drm/hisilicon/hibmc/Makefile
@@ -0,0 +1,4 @@
+hibmc-drm-y := hibmc_drm_drv.o hibmc_drm_power.o
+
+obj-$(CONFIG_DRM_HISI_HIBMC)   +=hibmc-drm.o
+#obj-y += hibmc-drm.o
diff --git a/drivers/gpu/drm/hisilicon/hibmc/hibmc_drm_drv.c 
b/drivers/gpu/drm/hisilicon/hibmc/hibmc_drm_drv.c
new file mode 100644
index 000..7eaacd8
--- /dev/null
+++ b/drivers/gpu/drm/hisilicon/hibmc/hibmc_drm_drv.c
@@ -0,0 +1,307 @@
+/* Hisilicon Hibmc SoC drm driver
+ *
+ * Based on the bochs drm driver.
+ *
+ * Copyright (c) 2016 Huawei Limited.
+ *
+ * Author:
+ * Rongrong Zou 
+ * Rongrong Zou 
+ * Jianhua Li 
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ */
+
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+
+#include "hibmc_drm_drv.h"
+#include "hibmc_drm_regs.h"
+#include "hibmc_drm_power.h"
+
+static const struct file_operations hibmc_fops = {
+   .owner  = THIS_MODULE,
+   .open   = drm_open,
+   .release= drm_release,
+   .unlocked_ioctl = drm_ioctl,
+#ifdef CONFIG_COMPAT
+   .compat_ioctl   = drm_compat_ioctl,
+#endif
+   .poll   = drm_poll,
+   .read   = drm_read,
+   .llseek = no_llseek,
+};
+
+static int hibmc_enable_vblank(struct drm_device *dev, unsigned int pipe)
+{
+   return 0;
+}
+
+static void hibmc_disable_vblank(struct drm_device *dev, unsigned int pipe)
+{
+}
+
+static struct drm_driver hibmc_driver = {
+   .driver_features= DRIVER_GEM | DRIVER_MODESET,
+   .fops   = _fops,
+   

[path v2 0/7] Add DRM driver for Hisilicon Hibmc

2016-05-29 Thread Rongrong Zou
This patch set adds a new drm driver for Hisilicon Hibmc. Hibmc is a
base board management controller, usually it is used on server for
Out-of-band management purpose. In this patch set, we just support basic
function for Hibmc display subsystem. Hibmc display subsystem is connected
to host CPU by PCIe as blow:

+--+   +--+
|  | PCIe  |  Hibmc   |
|host CPU( |<->| display  |
|arm64,x86)|   |subsystem |
+--+   +--+

Hardware Detail for Hibmc display subsystem
---

  The display subsystem of Hibmc is show as bellow:
  ++  ++  ++ ++
  ||  ||  || ||
  | FB |->| DE |->|VDAC|>|external|
  ||  ||  || | VGA|
  ++  ++  ++ ++

  -DE(Display Engine) is the display controller.
  -VDAC(Video Digital-to-Analog converter) converts the RGB diaital data
  stream from DE to VGA analog signals.

Change History


Changes in v2:
  -Remove self-defined macros for bit operations.
  -Remove unused register.
  -Replace those deprecated functions with new version of them.
  -use drm_connector_register_all() to register connector after
   drm_dev_register().

The patch v1 is at
https://lists.freedesktop.org/archives/dri-devel/2016-February/101921.html
Sorry for too late sending.


Rongrong Zou (7):
  idrm/hisilicon/hibmc: Add hisilicon hibmc drm master driver
  drm/hisilicon/hibmc: Add plane for DE
  drm/hisilicon/hibmc: Add crtc for DE
  drm/hisilicon/hibmc: Add encoder for VDAC
  drm/hisilicon/hibmc: Add connector for VDAC
  drm/hisilicon/hibmc: Add support for frame buffer
  drm/hisilicon/hibmc: Add maintainer for Hibmc DRM

 MAINTAINERS   |   7 +
 drivers/gpu/drm/hisilicon/Kconfig |   1 +
 drivers/gpu/drm/hisilicon/Makefile|   3 +-
 drivers/gpu/drm/hisilicon/hibmc/Kconfig   |  13 +
 drivers/gpu/drm/hisilicon/hibmc/Makefile  |   4 +
 drivers/gpu/drm/hisilicon/hibmc/hibmc_drm_de.c| 477 ++
 drivers/gpu/drm/hisilicon/hibmc/hibmc_drm_de.h|  29 ++
 drivers/gpu/drm/hisilicon/hibmc/hibmc_drm_drv.c   | 399 ++
 drivers/gpu/drm/hisilicon/hibmc/hibmc_drm_drv.h   |  64 +++
 drivers/gpu/drm/hisilicon/hibmc/hibmc_drm_fbdev.c | 286 +
 drivers/gpu/drm/hisilicon/hibmc/hibmc_drm_power.c |  91 +
 drivers/gpu/drm/hisilicon/hibmc/hibmc_drm_power.h |  28 ++
 drivers/gpu/drm/hisilicon/hibmc/hibmc_drm_regs.h  | 214 ++
 drivers/gpu/drm/hisilicon/hibmc/hibmc_drm_vdac.c  | 174 
 14 files changed, 1789 insertions(+), 1 deletion(-)
 create mode 100644 drivers/gpu/drm/hisilicon/hibmc/Kconfig
 create mode 100644 drivers/gpu/drm/hisilicon/hibmc/Makefile
 create mode 100644 drivers/gpu/drm/hisilicon/hibmc/hibmc_drm_de.c
 create mode 100644 drivers/gpu/drm/hisilicon/hibmc/hibmc_drm_de.h
 create mode 100644 drivers/gpu/drm/hisilicon/hibmc/hibmc_drm_drv.c
 create mode 100644 drivers/gpu/drm/hisilicon/hibmc/hibmc_drm_drv.h
 create mode 100644 drivers/gpu/drm/hisilicon/hibmc/hibmc_drm_fbdev.c
 create mode 100644 drivers/gpu/drm/hisilicon/hibmc/hibmc_drm_power.c
 create mode 100644 drivers/gpu/drm/hisilicon/hibmc/hibmc_drm_power.h
 create mode 100644 drivers/gpu/drm/hisilicon/hibmc/hibmc_drm_regs.h
 create mode 100644 drivers/gpu/drm/hisilicon/hibmc/hibmc_drm_vdac.c

-- 
1.9.1



[PATCH v4 3/3] drm: Add helper for simple display pipeline

2016-05-29 Thread Noralf Trønnes

Den 12.05.2016 20:25, skrev Noralf Trønnes:
> Provides helper functions for drivers that have a simple display
> pipeline. Plane, crtc and encoder are collapsed into one entity.
>
> Cc: jsarha at ti.com
> Signed-off-by: Noralf Trønnes 
> ---

[...]

> diff --git a/drivers/gpu/drm/drm_simple_kms_helper.c 
> b/drivers/gpu/drm/drm_simple_kms_helper.c
> new file mode 100644
> index 000..d45417a
> --- /dev/null
> +++ b/drivers/gpu/drm/drm_simple_kms_helper.c
> @@ -0,0 +1,208 @@
> +/*
> + * Copyright (C) 2016 Noralf Trønnes
> + *
> + * This program is free software; you can redistribute it and/or modify
> + * it under the terms of the GNU General Public License as published by
> + * the Free Software Foundation; either version 2 of the License, or
> + * (at your option) any later version.
> + */
> +
> +#include 
> +#include 
> +#include 
> +#include 
> +#include 
> +#include 
> +#include 
> +
> +/**
> + * DOC: overview
> + *
> + * This helper library provides helpers for drivers for simple display
> + * hardware.
> + *
> + * drm_simple_display_pipe_init() initializes a simple display pipeline
> + * which has only one full-screen scanout buffer feeding one output. The
> + * pipeline is represented by struct _simple_display_pipe and binds
> + * together _plane, _crtc and _encoder structures into one fixed
> + * entity. Some flexibility for code reuse is provided through a separately
> + * allocated _connector object and supporting optional _bridge
> + * encoder drivers.
> + */
> +
> +static const struct drm_encoder_funcs drm_simple_kms_encoder_funcs = {
> + .destroy = drm_encoder_cleanup,
> +};
> +
> +static void drm_simple_kms_crtc_enable(struct drm_crtc *crtc)
> +{
> + struct drm_simple_display_pipe *pipe;
> +
> + pipe = container_of(crtc, struct drm_simple_display_pipe, crtc);
> + if (!pipe->funcs || !pipe->funcs->enable)
> + return;
> +
> + pipe->funcs->enable(pipe, crtc->state);
> +}
> +
> +static void drm_simple_kms_crtc_disable(struct drm_crtc *crtc)
> +{
> + struct drm_simple_display_pipe *pipe;
> +
> + pipe = container_of(crtc, struct drm_simple_display_pipe, crtc);
> + if (!pipe->funcs || !pipe->funcs->disable)
> + return;
> +
> + pipe->funcs->disable(pipe);
> +}
> +
> +static const struct drm_crtc_helper_funcs drm_simple_kms_crtc_helper_funcs = 
> {
> + .disable = drm_simple_kms_crtc_disable,
> + .enable = drm_simple_kms_crtc_enable,
> +};
> +
> +static const struct drm_crtc_funcs drm_simple_kms_crtc_funcs = {
> + .reset = drm_atomic_helper_crtc_reset,
> + .destroy = drm_crtc_cleanup,
> + .set_config = drm_atomic_helper_set_config,
> + .page_flip = drm_atomic_helper_page_flip,
> + .atomic_duplicate_state = drm_atomic_helper_crtc_duplicate_state,
> + .atomic_destroy_state = drm_atomic_helper_crtc_destroy_state,
> +};
> +
> +static int drm_simple_kms_plane_atomic_check(struct drm_plane *plane,
> + struct drm_plane_state *plane_state)
> +{
> + struct drm_rect src = {
> + .x1 = plane_state->src_x,
> + .y1 = plane_state->src_y,
> + .x2 = plane_state->src_x + plane_state->src_w,
> + .y2 = plane_state->src_y + plane_state->src_h,
> + };
> + struct drm_rect dest = {
> + .x1 = plane_state->crtc_x,
> + .y1 = plane_state->crtc_y,
> + .x2 = plane_state->crtc_x + plane_state->crtc_w,
> + .y2 = plane_state->crtc_y + plane_state->crtc_h,
> + };
> + struct drm_rect clip = { 0 };
> + struct drm_simple_display_pipe *pipe;
> + struct drm_crtc_state *crtc_state;
> + bool visible;
> + int ret;
> +
> + pipe = container_of(plane, struct drm_simple_display_pipe, plane);
> + crtc_state = drm_atomic_get_existing_crtc_state(plane_state->state,
> + >crtc);
> + if (crtc_state->enable != !!plane_state->crtc)
> + return -EINVAL; /* plane must match crtc enable state */
> +
> + if (!crtc_state->enable)
> + return 0; /* nothing to check when disabling or disabled */
> +
> + clip.x2 = crtc_state->adjusted_mode.hdisplay;
> + clip.y2 = crtc_state->adjusted_mode.vdisplay;
> + ret = drm_plane_helper_check_update(plane, >crtc,
> + plane_state->fb,
> + , , ,
> + DRM_PLANE_HELPER_NO_SCALING,
> + DRM_PLANE_HELPER_NO_SCALING,
> + false, true, );
> + if (ret)
> + return ret;
> +
> + if (!visible)
> + return -EINVAL;
> +
> + if (!pipe->funcs || !pipe->funcs->check)
> + return 0;
> +
> + return pipe->funcs->check(pipe, plane_state, crtc_state);
> +}
> +
> +static void drm_simple_kms_plane_atomic_update(struct drm_plane *plane,
> +  

[Nouveau] Should I expect nouveau on 4.6 to work on a GM206?

2016-05-29 Thread Ilia Mirkin
On Sun, May 29, 2016 at 3:07 PM, Andy Lutomirski  wrote:
> On Sat, May 28, 2016 at 5:48 PM, Ilia Mirkin  wrote:
>> Do you have mesa 11.2 or later? GM20x support was only added in mesa 11.2.
>>
>
> I just upgraded to 11.2.  I'm getting errors like this in the log:
>
> [ 5383.723240] nouveau :09:00.0: fifo: read fault at 011000
> engine 07 [PBDMA0] client 06 [HOST] reason 00 [PDE] on channel -1
> [007f9ed000 unknown]
> [ 5398.722676] nouveau :09:00.0: systemd-logind[30778]: failed to
> idle channel 2 [systemd-logind[30778]]
> [ 5413.722853] nouveau :09:00.0: systemd-logind[30778]: failed to
> idle channel 2 [systemd-logind[30778]]
>
> and the display output in general is unreliable enough that I'm having
> trouble telling whether the performance is remotely reasonable.

If you're having trouble telling, that means it's not :) The error you
pasted is quite odd. Was there anything in the log before those
messages? If there's no channel associated, that means that it's the
background copying between vram and sysmem? Not sure.

Note that with maxwell we have yet to add EXA support to
xf86-video-nouveau, so you're ending up with GLAMOR (and Ben and I
disagree on whether EXA support should be added in the first place).
There was also an issue that glamor was hitting with nouveau which
appears to have dissipated, either due to a change in nouveau or a
change in glamor. So you might consider upgrading to Xorg 1.18.3 (as
glamor is part of X).

FWIW a few other people have been using GM20x without incident, but
this can all be very sensitive to your desktop/etc. Lots of things
like to use GL nowadays - I stick to a more classic desktop - no
compositor, simple window manager, etc.

  -ilia


[Bug 96239] [radeonsi tessellation] [R9 290/390] Random "texture flickering" (Shadow of Mordor, Tomb Raider, Unigine Heaven 4.0)

2016-05-29 Thread bugzilla-dae...@freedesktop.org
https://bugs.freedesktop.org/show_bug.cgi?id=96239

--- Comment #10 from Jan Ziak <0xe2.0x9a.0x9b at gmail.com> ---
Passing +1 to S_03093C_OFFCHIP_BUFFERING() explains why changing offchip_blocks
from 256 to 64 increases the severity of the issue.

-- 
You are receiving this mail because:
You are the assignee for the bug.
-- next part --
An HTML attachment was scrubbed...
URL: 
<https://lists.freedesktop.org/archives/dri-devel/attachments/20160529/da6b935c/attachment.html>


[Nouveau] Should I expect nouveau on 4.6 to work on a GM206?

2016-05-29 Thread Andy Lutomirski
On Sun, May 29, 2016 at 12:22 PM, Ilia Mirkin  wrote:
> On Sun, May 29, 2016 at 3:07 PM, Andy Lutomirski  wrote:
>> On Sat, May 28, 2016 at 5:48 PM, Ilia Mirkin  wrote:
>>> Do you have mesa 11.2 or later? GM20x support was only added in mesa 11.2.
>>>
>>
>> I just upgraded to 11.2.  I'm getting errors like this in the log:
>>
>> [ 5383.723240] nouveau :09:00.0: fifo: read fault at 011000
>> engine 07 [PBDMA0] client 06 [HOST] reason 00 [PDE] on channel -1
>> [007f9ed000 unknown]
>> [ 5398.722676] nouveau :09:00.0: systemd-logind[30778]: failed to
>> idle channel 2 [systemd-logind[30778]]
>> [ 5413.722853] nouveau :09:00.0: systemd-logind[30778]: failed to
>> idle channel 2 [systemd-logind[30778]]
>>
>> and the display output in general is unreliable enough that I'm having
>> trouble telling whether the performance is remotely reasonable.
>
> If you're having trouble telling, that means it's not :) The error you
> pasted is quite odd. Was there anything in the log before those
> messages? If there's no channel associated, that means that it's the
> background copying between vram and sysmem? Not sure.

Don't get too excited yet.  In the process of upgrading mesa, I
managed to boot 4.5 without noticing.  I'll post back later today with
actual valid test results.

>
> Note that with maxwell we have yet to add EXA support to
> xf86-video-nouveau, so you're ending up with GLAMOR (and Ben and I
> disagree on whether EXA support should be added in the first place).
> There was also an issue that glamor was hitting with nouveau which
> appears to have dissipated, either due to a change in nouveau or a
> change in glamor. So you might consider upgrading to Xorg 1.18.3 (as
> glamor is part of X).
>
> FWIW a few other people have been using GM20x without incident, but
> this can all be very sensitive to your desktop/etc. Lots of things
> like to use GL nowadays - I stick to a more classic desktop - no
> compositor, simple window manager, etc.

This is GNOME 3 on Fedora 24 Beta.

--Andy


[Bug 96239] [radeonsi tessellation] [R9 290/390] Random "texture flickering" (Shadow of Mordor, Tomb Raider, Unigine Heaven 4.0)

2016-05-29 Thread bugzilla-dae...@freedesktop.org
https://bugs.freedesktop.org/show_bug.cgi?id=96239

--- Comment #9 from Jan Ziak <0xe2.0x9a.0x9b at gmail.com> ---
Created attachment 124155
  --> https://bugs.freedesktop.org/attachment.cgi?id=124155=edit
S_03093C_OFFCHIP_BUFFERING(offchip_blocks) if >= CIK

This patch fixes the issue on my R9 390.

The code is just a guesswork. Maybe it should be (2*offchip_blocks-1) instead?

-- 
You are receiving this mail because:
You are the assignee for the bug.
-- next part --
An HTML attachment was scrubbed...
URL: 
<https://lists.freedesktop.org/archives/dri-devel/attachments/20160529/fb62b862/attachment.html>


[Nouveau] Should I expect nouveau on 4.6 to work on a GM206?

2016-05-29 Thread Andy Lutomirski
On Sat, May 28, 2016 at 5:48 PM, Ilia Mirkin  wrote:
> Do you have mesa 11.2 or later? GM20x support was only added in mesa 11.2.
>

I just upgraded to 11.2.  I'm getting errors like this in the log:

[ 5383.723240] nouveau :09:00.0: fifo: read fault at 011000
engine 07 [PBDMA0] client 06 [HOST] reason 00 [PDE] on channel -1
[007f9ed000 unknown]
[ 5398.722676] nouveau :09:00.0: systemd-logind[30778]: failed to
idle channel 2 [systemd-logind[30778]]
[ 5413.722853] nouveau :09:00.0: systemd-logind[30778]: failed to
idle channel 2 [systemd-logind[30778]]

and the display output in general is unreliable enough that I'm having
trouble telling whether the performance is remotely reasonable.

--Andy

> Cheers,
>
>   -ilia
>
> On Sat, May 28, 2016 at 4:51 PM, Andy Lutomirski  wrote:
>> I have the signed firmware (I think) and I'm running a fresh 4.6
>> kernel.  I got an image to show up briefly, rendering the Fedora
>> sign-in screen at something like one frame per ten seconds.  But then
>> I got all kinds of garbage, and I see:
>>
>> [  719.300820] nouveau :09:00.0: disp: outp 04:0006:0f44: link
>> training failed
>>
>> dmesg |grep nouveau says:
>>
>> [   10.053162] fb: switching to nouveaufb from EFI VGA
>> [   10.053349] nouveau :09:00.0: NVIDIA GM206 (126010a1)
>> [   10.174033] nouveau :09:00.0: bios: version 84.06.0d.00.01
>> [   10.174854] nouveau :09:00.0: disp: dcb 15 type 8 unknown
>> [   10.178375] nouveau :09:00.0: fb: 2048 MiB GDDR5
>> [   10.202108] nouveau :09:00.0: DRM: VRAM: 2048 MiB
>> [   10.202109] nouveau :09:00.0: DRM: GART: 1048576 MiB
>> [   10.202113] nouveau :09:00.0: DRM: TMDS table version 2.0
>> [   10.202114] nouveau :09:00.0: DRM: DCB version 4.1
>> [   10.202116] nouveau :09:00.0: DRM: DCB outp 00: 01000f02 00020030
>> [   10.202117] nouveau :09:00.0: DRM: DCB outp 01: 02000f00 
>> [   10.202118] nouveau :09:00.0: DRM: DCB outp 02: 02811f76 04400020
>> [   10.202120] nouveau :09:00.0: DRM: DCB outp 03: 02011f72 00020020
>> [   10.202121] nouveau :09:00.0: DRM: DCB outp 04: 04822f86 04400010
>> [   10.202122] nouveau :09:00.0: DRM: DCB outp 05: 04022f82 00020010
>> [   10.202123] nouveau :09:00.0: DRM: DCB outp 06: 04833f96 04400020
>> [   10.202124] nouveau :09:00.0: DRM: DCB outp 07: 04033f92 00020020
>> [   10.202125] nouveau :09:00.0: DRM: DCB outp 08: 02044f62 00020010
>> [   10.202126] nouveau :09:00.0: DRM: DCB outp 15: 01df5ff8 
>> [   10.202127] nouveau :09:00.0: DRM: DCB conn 00: 1030
>> [   10.202128] nouveau :09:00.0: DRM: DCB conn 01: 00020146
>> [   10.202129] nouveau :09:00.0: DRM: DCB conn 02: 01000246
>> [   10.202130] nouveau :09:00.0: DRM: DCB conn 03: 02000346
>> [   10.202131] nouveau :09:00.0: DRM: DCB conn 04: 00010461
>> [   10.202132] nouveau :09:00.0: DRM: DCB conn 05: 0570
>> [   10.202134] nouveau :09:00.0: DRM: Pointer to flat panel table invalid
>> [   10.214683] nouveau :09:00.0: DRM: unknown connector type 70
>> [   10.214728] nouveau :09:00.0: DRM: failed to create encoder 1/8/0: -19
>> [   10.214730] nouveau :09:00.0: DRM: Unknown-1 has no encoders, removing
>> [   10.369691] nouveau :09:00.0: DRM: MM: using COPY for buffer copies
>> [   10.478561] nouveau :09:00.0: priv: GPC0: 419df4  (1e40820e)
>> [   10.478578] nouveau :09:00.0: priv: GPC1: 419df4  (1e40820e)
>> [   10.607100] nouveau :09:00.0: DRM: allocated 3840x2160 fb:
>> 0x6, bo 88044aad7400
>> [   10.607276] fbcon: nouveaufb (fb0) is primary device
>> [   10.607576] nouveau :09:00.0: fb0: nouveaufb frame buffer device
>> [   10.617064] [drm] Initialized nouveau 1.3.1 20120801 for
>> :09:00.0 on minor 0
>> [  719.282184] nouveau :09:00.0: disp: outp 04:0006:0f44: link
>> training failed
>> [  719.300820] nouveau :09:00.0: disp: outp 04:0006:0f44: link
>> training failed
>>
>>
>>
>> Thanks,
>> Andy
>> ___
>> Nouveau mailing list
>> Nouveau at lists.freedesktop.org
>> https://lists.freedesktop.org/mailman/listinfo/nouveau


[Bug 96239] [radeonsi tessellation] [R9 290/390] Random "texture flickering" (Shadow of Mordor, Tomb Raider, Unigine Heaven 4.0)

2016-05-29 Thread bugzilla-dae...@freedesktop.org
https://bugs.freedesktop.org/show_bug.cgi?id=96239

--- Comment #8 from Jan Ziak <0xe2.0x9a.0x9b at gmail.com> ---
(In reply to Bas Nieuwenhuizen from comment #4)
> Does the attached patch help? If not I would appreciate it if someone could
> find the first commit that fails (using e.g. bisect).

Checking out for example f91c85b29b8261ab3f44d292ed2130d4f577d976 and starting
Tomb Raider restarts the X server on my machine.

-- 
You are receiving this mail because:
You are the assignee for the bug.
-- next part --
An HTML attachment was scrubbed...
URL: 
<https://lists.freedesktop.org/archives/dri-devel/attachments/20160529/ecfc2378/attachment.html>


[Bug 96239] [radeonsi tessellation] [R9 290/390] Random "texture flickering" (Shadow of Mordor, Tomb Raider, Unigine Heaven 4.0)

2016-05-29 Thread bugzilla-dae...@freedesktop.org
https://bugs.freedesktop.org/show_bug.cgi?id=96239

Jan Ziak <0xe2.0x9a.0x9b at gmail.com> changed:

   What|Removed |Added

Summary|[radeonsi tessellation] |[radeonsi tessellation] [R9
   |Random "texture flickering" |290/390] Random "texture
   |(Shadow of Mordor, Tomb |flickering" (Shadow of
   |Raider, Unigine Heaven 4.0) |Mordor, Tomb Raider,
   ||Unigine Heaven 4.0)

-- 
You are receiving this mail because:
You are the assignee for the bug.
-- next part --
An HTML attachment was scrubbed...
URL: 
<https://lists.freedesktop.org/archives/dri-devel/attachments/20160529/39c9d116/attachment.html>


[Intel-gfx] 4.7-rc0: redshift stopped working on intel display

2016-05-29 Thread Matthew Auld
Could you try to apply the following patch [1], hopefully this fixes
the issue for you.

[1] https://patchwork.freedesktop.org/patch/89111/


[Bug 96239] [radeonsi tessellation] Random "texture flickering" (Shadow of Mordor, Tomb Raider, Unigine Heaven 4.0)

2016-05-29 Thread bugzilla-dae...@freedesktop.org
https://bugs.freedesktop.org/show_bug.cgi?id=96239

--- Comment #7 from Jan Ziak <0xe2.0x9a.0x9b at gmail.com> ---
Created attachment 124154
  --> https://bugs.freedesktop.org/attachment.cgi?id=124154=edit
Tomb Raider ci-64-tess-blocks screenshot

-- 
You are receiving this mail because:
You are the assignee for the bug.
-- next part --
An HTML attachment was scrubbed...
URL: 
<https://lists.freedesktop.org/archives/dri-devel/attachments/20160529/14a3d356/attachment.html>


[Bug 96239] [radeonsi tessellation] Random "texture flickering" (Shadow of Mordor, Tomb Raider, Unigine Heaven 4.0)

2016-05-29 Thread bugzilla-dae...@freedesktop.org
https://bugs.freedesktop.org/show_bug.cgi?id=96239

--- Comment #6 from Jan Ziak <0xe2.0x9a.0x9b at gmail.com> ---
(In reply to Bas Nieuwenhuizen from comment #4)
> Created attachment 124151 [details] [review]
> ci-64-tess-blocks.patch
> 
> Does the attached patch help? If not I would appreciate it if someone could
> find the first commit that fails (using e.g. bisect).
> 
> Also, I noticed all reporters use hawaii/grenada pro chips. If anyone with a
> different chip also has this issue, please let me know.

Unfortunately, ci-64-tess-blocks.patch is making the issue more severe. The
frequency of "black triangles on screen" in Tomb Raider is higher.

-- 
You are receiving this mail because:
You are the assignee for the bug.
-- next part --
An HTML attachment was scrubbed...
URL: 
<https://lists.freedesktop.org/archives/dri-devel/attachments/20160529/a0c797fe/attachment.html>


[PATCH] drm/amdkfd: print once about mem_banks truncation

2016-05-29 Thread Oded Gabbay
This print can really spam the kernel log in case we are truncating
mem_banks, so just print this info once. It should also not be classified
as warning.

Signed-off-by: Oded Gabbay 
---
 drivers/gpu/drm/amd/amdkfd/kfd_topology.c | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/drivers/gpu/drm/amd/amdkfd/kfd_topology.c 
b/drivers/gpu/drm/amd/amdkfd/kfd_topology.c
index 74909e7..884c96f 100644
--- a/drivers/gpu/drm/amd/amdkfd/kfd_topology.c
+++ b/drivers/gpu/drm/amd/amdkfd/kfd_topology.c
@@ -666,7 +666,7 @@ static ssize_t node_show(struct kobject *kobj, struct 
attribute *attr,
dev->node_props.simd_count);

if (dev->mem_bank_count < dev->node_props.mem_banks_count) {
-   pr_warn("kfd: mem_banks_count truncated from %d to %d\n",
+   pr_info_once("kfd: mem_banks_count truncated from %d to %d\n",
dev->node_props.mem_banks_count,
dev->mem_bank_count);
sysfs_show_32bit_prop(buffer, "mem_banks_count",
-- 
2.5.5



[Bug 80004] Serious Sam 3 BFE - incorrect weapon rendering

2016-05-29 Thread bugzilla-dae...@freedesktop.org
https://bugs.freedesktop.org/show_bug.cgi?id=80004

Vitaliy Filippov  changed:

   What|Removed |Added

 Resolution|--- |FIXED
 Status|NEW |RESOLVED

--- Comment #11 from Vitaliy Filippov  ---
The bug does not reproduce anymore with current mesa 11.3

-- 
You are receiving this mail because:
You are the assignee for the bug.
-- next part --
An HTML attachment was scrubbed...
URL: 
<https://lists.freedesktop.org/archives/dri-devel/attachments/20160529/2b719567/attachment.html>


[Bug 96239] [radeonsi tessellation] Random "texture flickering" (Shadow of Mordor, Tomb Raider, Unigine Heaven 4.0)

2016-05-29 Thread bugzilla-dae...@freedesktop.org
https://bugs.freedesktop.org/show_bug.cgi?id=96239

--- Comment #5 from Rafael Castillo  ---
i can confirm this patches generates 0 issues on TAHITI R9-280 and CAPE VERDE
HD7700, so it seems it is specific to hawaii/grenada pro

-- 
You are receiving this mail because:
You are the assignee for the bug.
-- next part --
An HTML attachment was scrubbed...
URL: 
<https://lists.freedesktop.org/archives/dri-devel/attachments/20160529/c9904553/attachment-0001.html>


[Bug 96239] [radeonsi tessellation] Random "texture flickering" (Shadow of Mordor, Tomb Raider, Unigine Heaven 4.0)

2016-05-29 Thread bugzilla-dae...@freedesktop.org
https://bugs.freedesktop.org/show_bug.cgi?id=96239

--- Comment #4 from Bas Nieuwenhuizen  ---
Created attachment 124151
  --> https://bugs.freedesktop.org/attachment.cgi?id=124151=edit
ci-64-tess-blocks.patch

Does the attached patch help? If not I would appreciate it if someone could
find the first commit that fails (using e.g. bisect).

Also, I noticed all reporters use hawaii/grenada pro chips. If anyone with a
different chip also has this issue, please let me know.

-- 
You are receiving this mail because:
You are the assignee for the bug.
-- next part --
An HTML attachment was scrubbed...
URL: