[PATCH v3] drm/gem: Fix GEM handle release errors

2022-08-19 Thread Jeffy Chen
Currently we are assuming a one to one mapping between dmabuf and
GEM handle when releasing GEM handles.

But that is not always true, since we would create extra handles for the
GEM obj in cases like gem_open() and getfb{,2}().

A similar issue was reported at:
https://lore.kernel.org/all/20211105083308.392156-1-jay...@rock-chips.com/

Another problem is that the imported dmabuf might not always have
gem_obj->dma_buf set, which would cause leaks in
drm_gem_remove_prime_handles().

Let's fix these for now by using handle to find the exact map to remove.

Signed-off-by: Jeffy Chen 
Reviewed-by: Christian König 

---

Changes in v3:
Rewrite commit message a bit.

Changes in v2:
Fix a typo of rbtree.

 drivers/gpu/drm/drm_gem.c  | 17 +
 drivers/gpu/drm/drm_internal.h |  4 ++--
 drivers/gpu/drm/drm_prime.c| 20 
 3 files changed, 15 insertions(+), 26 deletions(-)

diff --git a/drivers/gpu/drm/drm_gem.c b/drivers/gpu/drm/drm_gem.c
index eb0c2d041f13..ed39da383570 100644
--- a/drivers/gpu/drm/drm_gem.c
+++ b/drivers/gpu/drm/drm_gem.c
@@ -168,21 +168,6 @@ void drm_gem_private_object_init(struct drm_device *dev,
 }
 EXPORT_SYMBOL(drm_gem_private_object_init);
 
-static void
-drm_gem_remove_prime_handles(struct drm_gem_object *obj, struct drm_file *filp)
-{
-   /*
-* Note: obj->dma_buf can't disappear as long as we still hold a
-* handle reference in obj->handle_count.
-*/
-   mutex_lock(>prime.lock);
-   if (obj->dma_buf) {
-   drm_prime_remove_buf_handle_locked(>prime,
-  obj->dma_buf);
-   }
-   mutex_unlock(>prime.lock);
-}
-
 /**
  * drm_gem_object_handle_free - release resources bound to userspace handles
  * @obj: GEM object to clean up.
@@ -253,7 +238,7 @@ drm_gem_object_release_handle(int id, void *ptr, void *data)
if (obj->funcs->close)
obj->funcs->close(obj, file_priv);
 
-   drm_gem_remove_prime_handles(obj, file_priv);
+   drm_prime_remove_buf_handle(_priv->prime, id);
drm_vma_node_revoke(>vma_node, file_priv);
 
drm_gem_object_handle_put_unlocked(obj);
diff --git a/drivers/gpu/drm/drm_internal.h b/drivers/gpu/drm/drm_internal.h
index 1fbbc19f1ac0..7bb98e6a446d 100644
--- a/drivers/gpu/drm/drm_internal.h
+++ b/drivers/gpu/drm/drm_internal.h
@@ -74,8 +74,8 @@ int drm_prime_fd_to_handle_ioctl(struct drm_device *dev, void 
*data,
 
 void drm_prime_init_file_private(struct drm_prime_file_private *prime_fpriv);
 void drm_prime_destroy_file_private(struct drm_prime_file_private 
*prime_fpriv);
-void drm_prime_remove_buf_handle_locked(struct drm_prime_file_private 
*prime_fpriv,
-   struct dma_buf *dma_buf);
+void drm_prime_remove_buf_handle(struct drm_prime_file_private *prime_fpriv,
+uint32_t handle);
 
 /* drm_drv.c */
 struct drm_minor *drm_minor_acquire(unsigned int minor_id);
diff --git a/drivers/gpu/drm/drm_prime.c b/drivers/gpu/drm/drm_prime.c
index e3f09f18110c..bd5366b16381 100644
--- a/drivers/gpu/drm/drm_prime.c
+++ b/drivers/gpu/drm/drm_prime.c
@@ -190,29 +190,33 @@ static int drm_prime_lookup_buf_handle(struct 
drm_prime_file_private *prime_fpri
return -ENOENT;
 }
 
-void drm_prime_remove_buf_handle_locked(struct drm_prime_file_private 
*prime_fpriv,
-   struct dma_buf *dma_buf)
+void drm_prime_remove_buf_handle(struct drm_prime_file_private *prime_fpriv,
+uint32_t handle)
 {
struct rb_node *rb;
 
-   rb = prime_fpriv->dmabufs.rb_node;
+   mutex_lock(_fpriv->lock);
+
+   rb = prime_fpriv->handles.rb_node;
while (rb) {
struct drm_prime_member *member;
 
-   member = rb_entry(rb, struct drm_prime_member, dmabuf_rb);
-   if (member->dma_buf == dma_buf) {
+   member = rb_entry(rb, struct drm_prime_member, handle_rb);
+   if (member->handle == handle) {
rb_erase(>handle_rb, _fpriv->handles);
rb_erase(>dmabuf_rb, _fpriv->dmabufs);
 
-   dma_buf_put(dma_buf);
+   dma_buf_put(member->dma_buf);
kfree(member);
-   return;
-   } else if (member->dma_buf < dma_buf) {
+   break;
+   } else if (member->handle < handle) {
rb = rb->rb_right;
} else {
rb = rb->rb_left;
}
}
+
+   mutex_unlock(_fpriv->lock);
 }
 
 void drm_prime_init_file_private(struct drm_prime_file_private *prime_fpriv)
-- 
2.20.1



Re: [Linaro-mm-sig] Re: [PATCH v2] drm/gem: Fix GEM handle release errors

2022-08-09 Thread Chen Jeffy

Hi Christian,

On 8/9 星期二 18:18, Christian König wrote:

Hi Jeffy,

Am 09.08.22 um 12:02 schrieb Chen Jeffy:

Hi Christian,

On 8/9 星期二 17:08, Christian König wrote:

Hi Jeffy,

Am 09.08.22 um 09:55 schrieb Christian König:

[SNIP]





So we are allowing GEM object to have multiple handles, and GEM 
object could have at most one dma-buf, doesn't that means that 
dma-buf could map to multiple handles?


No, at least not for the same GEM file private. That's the reason 
why the rb is indexed by the dma_buf object and not the handle.


In other words the rb is so that you have exactly one handle for 
each dma_buf in each file private.


I don't think so, because if user get multiple handles for the same 
GEM obj and use drm_gem_prime_handle_to_fd() for those handles


Mhm, that works? This is illegal and should have been prevented 
somehow.


At least I see the problem now. I'm just not sure how to fix it.

Your v2 patch indeed prevents leakage of the drm_prime_member for the 
additional handles, but those shouldn't have been added in the first 
place.


The issue is that with this we make it unpredictable which handle is 
returned. E.g. if we have handle 2,5,7 it can be that because of 
re-balancing the tree sometimes 2 and sometimes 5 is returned.


Maybe cache the latest returned handle in the obj(after 
drm_gem_prime_fd_to_handle), and clear it when that handle been 
deleted in drm_gem_handle_delete()?


That won't work. The handle is per fpriv, but the same object is used by 
multiple fpriv instances. >
What we could maybe do is to prevent adding multiple lockup structures 
when there is already one, but that's not something I can easily judge.


So maybe we need to protect that unique lookup structure been deleted 
before deleting the last handle, and make the handle unique for GEM obj, 
in case of that unique lookup's handle been deleted earlier that others?


How about adding a GEM obj rbtree too, and make drm_prime_member kref-ed?

So the 
drm_prime_add_buf_handle/drm_gem_handle_create_tail/drm_gem_handle_delete 
would be looking up drm_prime_member by GEM obj, then update dmabuf rb 
and inc/dec drm_prime_member's kref, 
drm_gem_prime_fd_to_handle/drm_gem_prime_handle_to_fd remain unchanged.




Daniel seems to be either very busy or on vacation otherwise he would 
have chimed in by now.


Anyway, your patch seems to at least fix the of hand memory leak, so 
feel free to add my rb to the v2 and push it to drm-misc-fixes for now.


Thanks,
Christian.




Something like:
drm_gem_prime_fd_to_handle
  handle = drm_prime_lookup_buf_handle(buf)
  obj = obj_from_handle(handle)
  if !obj->primary_handle
    obj->primary_handle = handle
  return obj->primary_handle

Or maybe limit GEM obj with a single lifetime handle?



That's not really a good idea and breaks a couple of assumptions as 
far as I know.


Ideas?

Thanks,
Christian.










Re: [Linaro-mm-sig] Re: [PATCH v2] drm/gem: Fix GEM handle release errors

2022-08-09 Thread Chen Jeffy

Hi Christian,

On 8/9 星期二 17:08, Christian König wrote:

Hi Jeffy,

Am 09.08.22 um 09:55 schrieb Christian König:

[SNIP]





So we are allowing GEM object to have multiple handles, and GEM 
object could have at most one dma-buf, doesn't that means that 
dma-buf could map to multiple handles?


No, at least not for the same GEM file private. That's the reason 
why the rb is indexed by the dma_buf object and not the handle.


In other words the rb is so that you have exactly one handle for 
each dma_buf in each file private.


I don't think so, because if user get multiple handles for the same 
GEM obj and use drm_gem_prime_handle_to_fd() for those handles


Mhm, that works? This is illegal and should have been prevented somehow.


At least I see the problem now. I'm just not sure how to fix it.

Your v2 patch indeed prevents leakage of the drm_prime_member for the 
additional handles, but those shouldn't have been added in the first place.


The issue is that with this we make it unpredictable which handle is 
returned. E.g. if we have handle 2,5,7 it can be that because of 
re-balancing the tree sometimes 2 and sometimes 5 is returned.


Maybe cache the latest returned handle in the obj(after 
drm_gem_prime_fd_to_handle), and clear it when that handle been deleted 
in drm_gem_handle_delete()?


Something like:
drm_gem_prime_fd_to_handle
  handle = drm_prime_lookup_buf_handle(buf)
  obj = obj_from_handle(handle)
  if !obj->primary_handle
obj->primary_handle = handle
  return obj->primary_handle

Or maybe limit GEM obj with a single lifetime handle?



That's not really a good idea and breaks a couple of assumptions as far 
as I know.


Ideas?

Thanks,
Christian.





Re: [PATCH v2] drm/gem: Fix GEM handle release errors

2022-08-09 Thread Chen Jeffy

Hi Christian,

On 8/9 星期二 15:55, Christian König wrote:

Am 09.08.22 um 03:28 schrieb Chen Jeffy:

Hi Christian,

On 8/9 星期二 2:03, Christian König wrote:

Hi Jeffy,

Am 08.08.22 um 05:51 schrieb Chen Jeffy:

Hi Christian,

Thanks for your reply, and sorry i didn't make it clear.

On 8/8 星期一 0:52, Christian König wrote:

Am 03.08.22 um 10:32 schrieb Jeffy Chen:
Currently we are assuming a one to one mapping between dmabuf and 
handle

when releasing GEM handles.

But that is not always true, since we would create extra handles 
for the

GEM obj in cases like gem_open() and getfb{,2}().

A similar issue was reported at:
https://nam11.safelinks.protection.outlook.com/?url=https%3A%2F%2Flore.kernel.org%2Fall%2F20211105083308.392156-1-jay.xu%40rock-chips.com%2Fdata=05%7C01%7Cchristian.koenig%40amd.com%7C52cd6ca16a3a415b92a708da79a67dec%7C3dd8961fe4884e608e11a82d994e183d%7C0%7C0%7C637956053232922419%7CUnknown%7CTWFpbGZsb3d8eyJWIjoiMC4wLjAwMDAiLCJQIjoiV2luMzIiLCJBTiI6Ik1haWwiLCJXVCI6Mn0%3D%7C3000%7C%7C%7Csdata=hIuH18B10sbVAyS0D4iK6R6WYc%2BZ7mlxGcKdUae%2BW6Y%3Dreserved=0

Another problem is that the drm_gem_remove_prime_handles() now only
remove handle to the exported dmabuf (gem_obj->dma_buf), so the 
imported

ones would leak:
WARNING: CPU: 2 PID: 236 at drivers/gpu/drm/drm_prime.c:228 
drm_prime_destroy_file_private+0x18/0x24


Let's fix these by using handle to find the exact map to remove.


Well we are clearly something missing here. As far as I can see the 
current code is correct.


Creating multiple GEM handles for the same DMA-buf is possible, but 
illegal. >
In other words when a GEM handle is exported as DMA-buf and 
imported again you should intentionally always get the same handle.


These issue are not about having handles for importing an exported 
dma-buf case, but for having multiple handles to a GEM object(which 
means having multiple handles to a dma-buf).


I know the drm-prime is trying to make dma-buf and handle maps one 
to one, but the drm-gem is allowing to create extra handles for a 
GEM object, for example:

drm_gem_open_ioctl -> drm_gem_handle_create_tail
drm_mode_getfb2_ioctl -> drm_gem_handle_create
drm_mode_getfb -> fb->funcs->create_handle


Yes, so far that's correct.




So we are allowing GEM object to have multiple handles, and GEM 
object could have at most one dma-buf, doesn't that means that 
dma-buf could map to multiple handles?


No, at least not for the same GEM file private. That's the reason why 
the rb is indexed by the dma_buf object and not the handle.


In other words the rb is so that you have exactly one handle for each 
dma_buf in each file private.


I don't think so, because if user get multiple handles for the same 
GEM obj and use drm_gem_prime_handle_to_fd() for those handles


Mhm, that works? This is illegal and should have been prevented somehow.

Let me double check the code.

Thanks for pointing that out,
Christian.



Thanks for checking it, my test case is a preload library which hooks 
the drmModeSetCrtc(and other APIs) then use drmModeGetFB to extract 
dmafd from fb_id.





, the current code would try to add multiple maps to rb:
drm_prime_add_buf_handle(buf_1, hdl_1)
drm_prime_add_buf_handle(buf_1, hdl_2)
...
drm_prime_add_buf_handle(buf_1, hdl_n)





Or should we rewrite the GEM framework to limit GEM object with uniq 
handle?


No, the extra handles are expected because when you call 
drm_mode_getfb*() and drm_gem_open_ioctl() the caller now owns the 
returned GEM handle.




The other issue is that we are leaking dma-buf <-> handle map for 
the imported dma-buf, since the drm_gem_remove_prime_handles doesn't 
take care of obj->import_attach->dmabuf.


No, that's correct as well. obj->dma_buf is set even for imported 
DMA-buf objects. See drm_gem_prime_fd_to_handle().


Well, that obj->dma_buf would be set in 
drm_gem_prime_fd_to_handle(create new handle), and cleared when 
releasing the latest handle(release handle).


So it doesn't cover other handle creating path.

For example, a imported dma buf:
drm_gem_prime_fd_to_handle <-- we got a handle and obj->dma_buf and 
obj->import_attach->dmabuf

drm_gem_handle_delete <-- we lost that handle and obj->dma_buf cleared
drm_gem_open_ioctl/or getfb* <-- we got a new handle and 
obj->import_attach->dmabuf
drm_gem_handle_delete <-- we lost that handle and obj->dma_buf is 
null, which means rb leaks.


Another way to solve this would be set this obj->dma_buf again in 
drm_gem_prime_handle_to_fd(), which would make sure obj->dma_buf is 
valid in all current paths lead to drm_prime_add_buf_handle().






Regards,
Christian.



But of cause this can be fixed in other way:
+++ b/drivers/gpu/drm/drm_gem.c
@@ -180,6 +180,9 @@ drm_gem_remove_prime_handles(struct 
drm_gem_object *obj, struct drm_file *filp)

drm_prime_remove_buf_handle_locked(>prime,
obj->dma_buf);
    }
+   if (obj->import_attach)
+ drm_pri

Re: [PATCH v2] drm/gem: Fix GEM handle release errors

2022-08-08 Thread Chen Jeffy

Hi Christian,

On 8/9 星期二 2:03, Christian König wrote:

Hi Jeffy,

Am 08.08.22 um 05:51 schrieb Chen Jeffy:

Hi Christian,

Thanks for your reply, and sorry i didn't make it clear.

On 8/8 星期一 0:52, Christian König wrote:

Am 03.08.22 um 10:32 schrieb Jeffy Chen:
Currently we are assuming a one to one mapping between dmabuf and 
handle

when releasing GEM handles.

But that is not always true, since we would create extra handles for 
the

GEM obj in cases like gem_open() and getfb{,2}().

A similar issue was reported at:
https://nam11.safelinks.protection.outlook.com/?url=https%3A%2F%2Flore.kernel.org%2Fall%2F20211105083308.392156-1-jay.xu%40rock-chips.com%2Fdata=05%7C01%7Cchristian.koenig%40amd.com%7Cd7488e9f235041f7e84408da78f14882%7C3dd8961fe4884e608e11a82d994e183d%7C0%7C0%7C637955274964656400%7CUnknown%7CTWFpbGZsb3d8eyJWIjoiMC4wLjAwMDAiLCJQIjoiV2luMzIiLCJBTiI6Ik1haWwiLCJXVCI6Mn0%3D%7C3000%7C%7C%7Csdata=9G2YbHcYUs1VQYyvjXwLzYawNw%2BP8i%2BjjPBSHx3r2yg%3Dreserved=0

Another problem is that the drm_gem_remove_prime_handles() now only
remove handle to the exported dmabuf (gem_obj->dma_buf), so the 
imported

ones would leak:
WARNING: CPU: 2 PID: 236 at drivers/gpu/drm/drm_prime.c:228 
drm_prime_destroy_file_private+0x18/0x24


Let's fix these by using handle to find the exact map to remove.


Well we are clearly something missing here. As far as I can see the 
current code is correct.


Creating multiple GEM handles for the same DMA-buf is possible, but 
illegal. >
In other words when a GEM handle is exported as DMA-buf and imported 
again you should intentionally always get the same handle.


These issue are not about having handles for importing an exported 
dma-buf case, but for having multiple handles to a GEM object(which 
means having multiple handles to a dma-buf).


I know the drm-prime is trying to make dma-buf and handle maps one to 
one, but the drm-gem is allowing to create extra handles for a GEM 
object, for example:

drm_gem_open_ioctl -> drm_gem_handle_create_tail
drm_mode_getfb2_ioctl -> drm_gem_handle_create
drm_mode_getfb -> fb->funcs->create_handle


Yes, so far that's correct.




So we are allowing GEM object to have multiple handles, and GEM object 
could have at most one dma-buf, doesn't that means that dma-buf could 
map to multiple handles?


No, at least not for the same GEM file private. That's the reason why 
the rb is indexed by the dma_buf object and not the handle.


In other words the rb is so that you have exactly one handle for each 
dma_buf in each file private.


I don't think so, because if user get multiple handles for the same GEM 
obj and use drm_gem_prime_handle_to_fd() for those handles, the current 
code would try to add multiple maps to rb:

drm_prime_add_buf_handle(buf_1, hdl_1)
drm_prime_add_buf_handle(buf_1, hdl_2)
...
drm_prime_add_buf_handle(buf_1, hdl_n)





Or should we rewrite the GEM framework to limit GEM object with uniq 
handle?


No, the extra handles are expected because when you call 
drm_mode_getfb*() and drm_gem_open_ioctl() the caller now owns the 
returned GEM handle.




The other issue is that we are leaking dma-buf <-> handle map for the 
imported dma-buf, since the drm_gem_remove_prime_handles doesn't take 
care of obj->import_attach->dmabuf.


No, that's correct as well. obj->dma_buf is set even for imported 
DMA-buf objects. See drm_gem_prime_fd_to_handle().


Well, that obj->dma_buf would be set in 
drm_gem_prime_fd_to_handle(create new handle), and cleared when 
releasing the latest handle(release handle).


So it doesn't cover other handle creating path.

For example, a imported dma buf:
drm_gem_prime_fd_to_handle <-- we got a handle and obj->dma_buf and 
obj->import_attach->dmabuf

drm_gem_handle_delete <-- we lost that handle and obj->dma_buf cleared
drm_gem_open_ioctl/or getfb* <-- we got a new handle and 
obj->import_attach->dmabuf
drm_gem_handle_delete <-- we lost that handle and obj->dma_buf is null, 
which means rb leaks.




Regards,
Christian.



But of cause this can be fixed in other way:
+++ b/drivers/gpu/drm/drm_gem.c
@@ -180,6 +180,9 @@ drm_gem_remove_prime_handles(struct drm_gem_object 
*obj, struct drm_file *filp)

drm_prime_remove_buf_handle_locked(>prime,
obj->dma_buf);
    }
+   if (obj->import_attach)
+ drm_prime_remove_buf_handle_locked(>prime,
+ obj->import_attach->dmabuf);
    mutex_unlock(>prime.lock);
 }


So this is pretty much a clear NAK to this patch since it shouldn't 
be necessary or something is seriously broken somewhere else.


Regards,
Christian.



Signed-off-by: Jeffy Chen 
---

Changes in v2:
Fix a typo of rbtree.

  drivers/gpu/drm/drm_gem.c  | 17 +
  drivers/gpu/drm/drm_internal.h |  4 ++--
  drivers/gpu/drm/drm_prime.c    | 20 
  3 files changed, 15 insertions(+), 26 deletions(-)

diff --git a/drivers/gpu/drm/drm_gem.c b/drivers/gpu/drm/drm_gem.c

Re: [PATCH] drm/gem: Fix GEM handle release errors

2022-08-08 Thread Chen Jeffy

Hi Christian,

Sorry, i've sent a v2 before, please check that.

On 8/9 星期二 2:05, Christian König wrote:



Am 02.08.22 um 13:33 schrieb Jeffy Chen:

Currently we are assuming a one to one mapping between dmabuf and handle
when releasing GEM handles.

But that is not always true, since we would create extra handles for the
GEM obj in cases like gem_open() and getfb{,2}().

A similar issue was reported at:
https://lore.kernel.org/all/20211105083308.392156-1-jay...@rock-chips.com/

Another problem is that the drm_gem_remove_prime_handles() now only
remove handle to the exported dmabuf (gem_obj->dma_buf), so the imported
ones would leak:
WARNING: CPU: 2 PID: 236 at drivers/gpu/drm/drm_prime.c:228 
drm_prime_destroy_file_private+0x18/0x24


Let's fix these by using handle to find the exact map to remove.

Signed-off-by: Jeffy Chen 
---

  drivers/gpu/drm/drm_gem.c  | 17 +
  drivers/gpu/drm/drm_internal.h |  4 ++--
  drivers/gpu/drm/drm_prime.c    | 16 ++--
  3 files changed, 13 insertions(+), 24 deletions(-)

diff --git a/drivers/gpu/drm/drm_gem.c b/drivers/gpu/drm/drm_gem.c
index eb0c2d041f13..ed39da383570 100644
--- a/drivers/gpu/drm/drm_gem.c
+++ b/drivers/gpu/drm/drm_gem.c
@@ -168,21 +168,6 @@ void drm_gem_private_object_init(struct 
drm_device *dev,

  }
  EXPORT_SYMBOL(drm_gem_private_object_init);
-static void
-drm_gem_remove_prime_handles(struct drm_gem_object *obj, struct 
drm_file *filp)

-{
-    /*
- * Note: obj->dma_buf can't disappear as long as we still hold a
- * handle reference in obj->handle_count.
- */
-    mutex_lock(>prime.lock);
-    if (obj->dma_buf) {
-    drm_prime_remove_buf_handle_locked(>prime,
-   obj->dma_buf);
-    }
-    mutex_unlock(>prime.lock);
-}
-
  /**
   * drm_gem_object_handle_free - release resources bound to userspace 
handles

   * @obj: GEM object to clean up.
@@ -253,7 +238,7 @@ drm_gem_object_release_handle(int id, void *ptr, 
void *data)

  if (obj->funcs->close)
  obj->funcs->close(obj, file_priv);
-    drm_gem_remove_prime_handles(obj, file_priv);
+    drm_prime_remove_buf_handle(_priv->prime, id);
  drm_vma_node_revoke(>vma_node, file_priv);
  drm_gem_object_handle_put_unlocked(obj);
diff --git a/drivers/gpu/drm/drm_internal.h 
b/drivers/gpu/drm/drm_internal.h

index 1fbbc19f1ac0..7bb98e6a446d 100644
--- a/drivers/gpu/drm/drm_internal.h
+++ b/drivers/gpu/drm/drm_internal.h
@@ -74,8 +74,8 @@ int drm_prime_fd_to_handle_ioctl(struct drm_device 
*dev, void *data,
  void drm_prime_init_file_private(struct drm_prime_file_private 
*prime_fpriv);
  void drm_prime_destroy_file_private(struct drm_prime_file_private 
*prime_fpriv);
-void drm_prime_remove_buf_handle_locked(struct drm_prime_file_private 
*prime_fpriv,

-    struct dma_buf *dma_buf);
+void drm_prime_remove_buf_handle(struct drm_prime_file_private 
*prime_fpriv,

+ uint32_t handle);
  /* drm_drv.c */
  struct drm_minor *drm_minor_acquire(unsigned int minor_id);
diff --git a/drivers/gpu/drm/drm_prime.c b/drivers/gpu/drm/drm_prime.c
index e3f09f18110c..c28518ab62d0 100644
--- a/drivers/gpu/drm/drm_prime.c
+++ b/drivers/gpu/drm/drm_prime.c
@@ -190,29 +190,33 @@ static int drm_prime_lookup_buf_handle(struct 
drm_prime_file_private *prime_fpri

  return -ENOENT;
  }
-void drm_prime_remove_buf_handle_locked(struct drm_prime_file_private 
*prime_fpriv,

-    struct dma_buf *dma_buf)
+void drm_prime_remove_buf_handle(struct drm_prime_file_private 
*prime_fpriv,

+ uint32_t handle)
  {
  struct rb_node *rb;
+    mutex_lock(_fpriv->lock);
+
  rb = prime_fpriv->dmabufs.rb_node;
  while (rb) {
  struct drm_prime_member *member;
  member = rb_entry(rb, struct drm_prime_member, dmabuf_rb);
-    if (member->dma_buf == dma_buf) {
+    if (member->handle == handle) {
  rb_erase(>handle_rb, _fpriv->handles);
  rb_erase(>dmabuf_rb, _fpriv->dmabufs);
-    dma_buf_put(dma_buf);
+    dma_buf_put(member->dma_buf);
  kfree(member);
-    return;
-    } else if (member->dma_buf < dma_buf) {
+    break;
+    } else if (member->handle < handle) {


Just to make it clear once more. That change here is completely broken.

The rb is indexed by the dma_buf object, not the handle.

Regards,
Christian.


  rb = rb->rb_right;
  } else {
  rb = rb->rb_left;
  }
  }
+
+    mutex_unlock(_fpriv->lock);
  }
  void drm_prime_init_file_private(struct drm_prime_file_private 
*prime_fpriv)







Re: [PATCH v2] drm/gem: Fix GEM handle release errors

2022-08-07 Thread Chen Jeffy

Hi Christian,

Thanks for your reply, and sorry i didn't make it clear.

On 8/8 星期一 0:52, Christian König wrote:

Am 03.08.22 um 10:32 schrieb Jeffy Chen:

Currently we are assuming a one to one mapping between dmabuf and handle
when releasing GEM handles.

But that is not always true, since we would create extra handles for the
GEM obj in cases like gem_open() and getfb{,2}().

A similar issue was reported at:
https://lore.kernel.org/all/20211105083308.392156-1-jay...@rock-chips.com/

Another problem is that the drm_gem_remove_prime_handles() now only
remove handle to the exported dmabuf (gem_obj->dma_buf), so the imported
ones would leak:
WARNING: CPU: 2 PID: 236 at drivers/gpu/drm/drm_prime.c:228 
drm_prime_destroy_file_private+0x18/0x24


Let's fix these by using handle to find the exact map to remove.


Well we are clearly something missing here. As far as I can see the 
current code is correct.


Creating multiple GEM handles for the same DMA-buf is possible, but 
illegal. >
In other words when a GEM handle is exported as DMA-buf and imported 
again you should intentionally always get the same handle.


These issue are not about having handles for importing an exported 
dma-buf case, but for having multiple handles to a GEM object(which 
means having multiple handles to a dma-buf).


I know the drm-prime is trying to make dma-buf and handle maps one to 
one, but the drm-gem is allowing to create extra handles for a GEM 
object, for example:

drm_gem_open_ioctl -> drm_gem_handle_create_tail
drm_mode_getfb2_ioctl -> drm_gem_handle_create
drm_mode_getfb -> fb->funcs->create_handle

So we are allowing GEM object to have multiple handles, and GEM object 
could have at most one dma-buf, doesn't that means that dma-buf could 
map to multiple handles?


Or should we rewrite the GEM framework to limit GEM object with uniq handle?


The other issue is that we are leaking dma-buf <-> handle map for the 
imported dma-buf, since the drm_gem_remove_prime_handles doesn't take 
care of obj->import_attach->dmabuf.


But of cause this can be fixed in other way:
+++ b/drivers/gpu/drm/drm_gem.c
@@ -180,6 +180,9 @@ drm_gem_remove_prime_handles(struct drm_gem_object 
*obj, struct drm_file *filp)

drm_prime_remove_buf_handle_locked(>prime,
   obj->dma_buf);
}
+   if (obj->import_attach)
+   drm_prime_remove_buf_handle_locked(>prime,
+ 
obj->import_attach->dmabuf);

mutex_unlock(>prime.lock);
 }


So this is pretty much a clear NAK to this patch since it shouldn't be 
necessary or something is seriously broken somewhere else.


Regards,
Christian.



Signed-off-by: Jeffy Chen 
---

Changes in v2:
Fix a typo of rbtree.

  drivers/gpu/drm/drm_gem.c  | 17 +
  drivers/gpu/drm/drm_internal.h |  4 ++--
  drivers/gpu/drm/drm_prime.c    | 20 
  3 files changed, 15 insertions(+), 26 deletions(-)

diff --git a/drivers/gpu/drm/drm_gem.c b/drivers/gpu/drm/drm_gem.c
index eb0c2d041f13..ed39da383570 100644
--- a/drivers/gpu/drm/drm_gem.c
+++ b/drivers/gpu/drm/drm_gem.c
@@ -168,21 +168,6 @@ void drm_gem_private_object_init(struct 
drm_device *dev,

  }
  EXPORT_SYMBOL(drm_gem_private_object_init);
-static void
-drm_gem_remove_prime_handles(struct drm_gem_object *obj, struct 
drm_file *filp)

-{
-    /*
- * Note: obj->dma_buf can't disappear as long as we still hold a
- * handle reference in obj->handle_count.
- */
-    mutex_lock(>prime.lock);
-    if (obj->dma_buf) {
-    drm_prime_remove_buf_handle_locked(>prime,
-   obj->dma_buf);
-    }
-    mutex_unlock(>prime.lock);
-}
-
  /**
   * drm_gem_object_handle_free - release resources bound to userspace 
handles

   * @obj: GEM object to clean up.
@@ -253,7 +238,7 @@ drm_gem_object_release_handle(int id, void *ptr, 
void *data)

  if (obj->funcs->close)
  obj->funcs->close(obj, file_priv);
-    drm_gem_remove_prime_handles(obj, file_priv);
+    drm_prime_remove_buf_handle(_priv->prime, id);
  drm_vma_node_revoke(>vma_node, file_priv);
  drm_gem_object_handle_put_unlocked(obj);
diff --git a/drivers/gpu/drm/drm_internal.h 
b/drivers/gpu/drm/drm_internal.h

index 1fbbc19f1ac0..7bb98e6a446d 100644
--- a/drivers/gpu/drm/drm_internal.h
+++ b/drivers/gpu/drm/drm_internal.h
@@ -74,8 +74,8 @@ int drm_prime_fd_to_handle_ioctl(struct drm_device 
*dev, void *data,
  void drm_prime_init_file_private(struct drm_prime_file_private 
*prime_fpriv);
  void drm_prime_destroy_file_private(struct drm_prime_file_private 
*prime_fpriv);
-void drm_prime_remove_buf_handle_locked(struct drm_prime_file_private 
*prime_fpriv,

-    struct dma_buf *dma_buf);
+void drm_prime_remove_buf_handle(struct drm_prime_file_private 
*prime_fpriv,

+ uint32_t handle);
  /* drm_drv.c */
  struct drm_minor *drm_min

[PATCH v2] drm/gem: Fix GEM handle release errors

2022-08-03 Thread Jeffy Chen
Currently we are assuming a one to one mapping between dmabuf and handle
when releasing GEM handles.

But that is not always true, since we would create extra handles for the
GEM obj in cases like gem_open() and getfb{,2}().

A similar issue was reported at:
https://lore.kernel.org/all/20211105083308.392156-1-jay...@rock-chips.com/

Another problem is that the drm_gem_remove_prime_handles() now only
remove handle to the exported dmabuf (gem_obj->dma_buf), so the imported
ones would leak:
WARNING: CPU: 2 PID: 236 at drivers/gpu/drm/drm_prime.c:228 
drm_prime_destroy_file_private+0x18/0x24

Let's fix these by using handle to find the exact map to remove.

Signed-off-by: Jeffy Chen 
---

Changes in v2:
Fix a typo of rbtree.

 drivers/gpu/drm/drm_gem.c  | 17 +
 drivers/gpu/drm/drm_internal.h |  4 ++--
 drivers/gpu/drm/drm_prime.c| 20 
 3 files changed, 15 insertions(+), 26 deletions(-)

diff --git a/drivers/gpu/drm/drm_gem.c b/drivers/gpu/drm/drm_gem.c
index eb0c2d041f13..ed39da383570 100644
--- a/drivers/gpu/drm/drm_gem.c
+++ b/drivers/gpu/drm/drm_gem.c
@@ -168,21 +168,6 @@ void drm_gem_private_object_init(struct drm_device *dev,
 }
 EXPORT_SYMBOL(drm_gem_private_object_init);
 
-static void
-drm_gem_remove_prime_handles(struct drm_gem_object *obj, struct drm_file *filp)
-{
-   /*
-* Note: obj->dma_buf can't disappear as long as we still hold a
-* handle reference in obj->handle_count.
-*/
-   mutex_lock(>prime.lock);
-   if (obj->dma_buf) {
-   drm_prime_remove_buf_handle_locked(>prime,
-  obj->dma_buf);
-   }
-   mutex_unlock(>prime.lock);
-}
-
 /**
  * drm_gem_object_handle_free - release resources bound to userspace handles
  * @obj: GEM object to clean up.
@@ -253,7 +238,7 @@ drm_gem_object_release_handle(int id, void *ptr, void *data)
if (obj->funcs->close)
obj->funcs->close(obj, file_priv);
 
-   drm_gem_remove_prime_handles(obj, file_priv);
+   drm_prime_remove_buf_handle(_priv->prime, id);
drm_vma_node_revoke(>vma_node, file_priv);
 
drm_gem_object_handle_put_unlocked(obj);
diff --git a/drivers/gpu/drm/drm_internal.h b/drivers/gpu/drm/drm_internal.h
index 1fbbc19f1ac0..7bb98e6a446d 100644
--- a/drivers/gpu/drm/drm_internal.h
+++ b/drivers/gpu/drm/drm_internal.h
@@ -74,8 +74,8 @@ int drm_prime_fd_to_handle_ioctl(struct drm_device *dev, void 
*data,
 
 void drm_prime_init_file_private(struct drm_prime_file_private *prime_fpriv);
 void drm_prime_destroy_file_private(struct drm_prime_file_private 
*prime_fpriv);
-void drm_prime_remove_buf_handle_locked(struct drm_prime_file_private 
*prime_fpriv,
-   struct dma_buf *dma_buf);
+void drm_prime_remove_buf_handle(struct drm_prime_file_private *prime_fpriv,
+uint32_t handle);
 
 /* drm_drv.c */
 struct drm_minor *drm_minor_acquire(unsigned int minor_id);
diff --git a/drivers/gpu/drm/drm_prime.c b/drivers/gpu/drm/drm_prime.c
index e3f09f18110c..bd5366b16381 100644
--- a/drivers/gpu/drm/drm_prime.c
+++ b/drivers/gpu/drm/drm_prime.c
@@ -190,29 +190,33 @@ static int drm_prime_lookup_buf_handle(struct 
drm_prime_file_private *prime_fpri
return -ENOENT;
 }
 
-void drm_prime_remove_buf_handle_locked(struct drm_prime_file_private 
*prime_fpriv,
-   struct dma_buf *dma_buf)
+void drm_prime_remove_buf_handle(struct drm_prime_file_private *prime_fpriv,
+uint32_t handle)
 {
struct rb_node *rb;
 
-   rb = prime_fpriv->dmabufs.rb_node;
+   mutex_lock(_fpriv->lock);
+
+   rb = prime_fpriv->handles.rb_node;
while (rb) {
struct drm_prime_member *member;
 
-   member = rb_entry(rb, struct drm_prime_member, dmabuf_rb);
-   if (member->dma_buf == dma_buf) {
+   member = rb_entry(rb, struct drm_prime_member, handle_rb);
+   if (member->handle == handle) {
rb_erase(>handle_rb, _fpriv->handles);
rb_erase(>dmabuf_rb, _fpriv->dmabufs);
 
-   dma_buf_put(dma_buf);
+   dma_buf_put(member->dma_buf);
kfree(member);
-   return;
-   } else if (member->dma_buf < dma_buf) {
+   break;
+   } else if (member->handle < handle) {
rb = rb->rb_right;
} else {
rb = rb->rb_left;
}
}
+
+   mutex_unlock(_fpriv->lock);
 }
 
 void drm_prime_init_file_private(struct drm_prime_file_private *prime_fpriv)
-- 
2.20.1



[PATCH] drm/gem: Fix GEM handle release errors

2022-08-02 Thread Jeffy Chen
Currently we are assuming a one to one mapping between dmabuf and handle
when releasing GEM handles.

But that is not always true, since we would create extra handles for the
GEM obj in cases like gem_open() and getfb{,2}().

A similar issue was reported at:
https://lore.kernel.org/all/20211105083308.392156-1-jay...@rock-chips.com/

Another problem is that the drm_gem_remove_prime_handles() now only
remove handle to the exported dmabuf (gem_obj->dma_buf), so the imported
ones would leak:
WARNING: CPU: 2 PID: 236 at drivers/gpu/drm/drm_prime.c:228 
drm_prime_destroy_file_private+0x18/0x24

Let's fix these by using handle to find the exact map to remove.

Signed-off-by: Jeffy Chen 
---

 drivers/gpu/drm/drm_gem.c  | 17 +
 drivers/gpu/drm/drm_internal.h |  4 ++--
 drivers/gpu/drm/drm_prime.c| 16 ++--
 3 files changed, 13 insertions(+), 24 deletions(-)

diff --git a/drivers/gpu/drm/drm_gem.c b/drivers/gpu/drm/drm_gem.c
index eb0c2d041f13..ed39da383570 100644
--- a/drivers/gpu/drm/drm_gem.c
+++ b/drivers/gpu/drm/drm_gem.c
@@ -168,21 +168,6 @@ void drm_gem_private_object_init(struct drm_device *dev,
 }
 EXPORT_SYMBOL(drm_gem_private_object_init);
 
-static void
-drm_gem_remove_prime_handles(struct drm_gem_object *obj, struct drm_file *filp)
-{
-   /*
-* Note: obj->dma_buf can't disappear as long as we still hold a
-* handle reference in obj->handle_count.
-*/
-   mutex_lock(>prime.lock);
-   if (obj->dma_buf) {
-   drm_prime_remove_buf_handle_locked(>prime,
-  obj->dma_buf);
-   }
-   mutex_unlock(>prime.lock);
-}
-
 /**
  * drm_gem_object_handle_free - release resources bound to userspace handles
  * @obj: GEM object to clean up.
@@ -253,7 +238,7 @@ drm_gem_object_release_handle(int id, void *ptr, void *data)
if (obj->funcs->close)
obj->funcs->close(obj, file_priv);
 
-   drm_gem_remove_prime_handles(obj, file_priv);
+   drm_prime_remove_buf_handle(_priv->prime, id);
drm_vma_node_revoke(>vma_node, file_priv);
 
drm_gem_object_handle_put_unlocked(obj);
diff --git a/drivers/gpu/drm/drm_internal.h b/drivers/gpu/drm/drm_internal.h
index 1fbbc19f1ac0..7bb98e6a446d 100644
--- a/drivers/gpu/drm/drm_internal.h
+++ b/drivers/gpu/drm/drm_internal.h
@@ -74,8 +74,8 @@ int drm_prime_fd_to_handle_ioctl(struct drm_device *dev, void 
*data,
 
 void drm_prime_init_file_private(struct drm_prime_file_private *prime_fpriv);
 void drm_prime_destroy_file_private(struct drm_prime_file_private 
*prime_fpriv);
-void drm_prime_remove_buf_handle_locked(struct drm_prime_file_private 
*prime_fpriv,
-   struct dma_buf *dma_buf);
+void drm_prime_remove_buf_handle(struct drm_prime_file_private *prime_fpriv,
+uint32_t handle);
 
 /* drm_drv.c */
 struct drm_minor *drm_minor_acquire(unsigned int minor_id);
diff --git a/drivers/gpu/drm/drm_prime.c b/drivers/gpu/drm/drm_prime.c
index e3f09f18110c..c28518ab62d0 100644
--- a/drivers/gpu/drm/drm_prime.c
+++ b/drivers/gpu/drm/drm_prime.c
@@ -190,29 +190,33 @@ static int drm_prime_lookup_buf_handle(struct 
drm_prime_file_private *prime_fpri
return -ENOENT;
 }
 
-void drm_prime_remove_buf_handle_locked(struct drm_prime_file_private 
*prime_fpriv,
-   struct dma_buf *dma_buf)
+void drm_prime_remove_buf_handle(struct drm_prime_file_private *prime_fpriv,
+uint32_t handle)
 {
struct rb_node *rb;
 
+   mutex_lock(_fpriv->lock);
+
rb = prime_fpriv->dmabufs.rb_node;
while (rb) {
struct drm_prime_member *member;
 
member = rb_entry(rb, struct drm_prime_member, dmabuf_rb);
-   if (member->dma_buf == dma_buf) {
+   if (member->handle == handle) {
rb_erase(>handle_rb, _fpriv->handles);
rb_erase(>dmabuf_rb, _fpriv->dmabufs);
 
-   dma_buf_put(dma_buf);
+   dma_buf_put(member->dma_buf);
kfree(member);
-   return;
-   } else if (member->dma_buf < dma_buf) {
+   break;
+   } else if (member->handle < handle) {
rb = rb->rb_right;
} else {
rb = rb->rb_left;
}
}
+
+   mutex_unlock(_fpriv->lock);
 }
 
 void drm_prime_init_file_private(struct drm_prime_file_private *prime_fpriv)
-- 
2.20.1



[PATCH] drm/bridge/synopsys: dw-hdmi: Fix memleak in __dw_hdmi_remove

2018-03-04 Thread Jeffy Chen
The platform_device_register_full() will allocate dma_mask for
hdmi->audio, so we should free before platform_device_unregister().

Reported by kmemleak:
unreferenced object 0xffc0ef70ff00 (size 128):
  comm "kworker/4:1", pid 123, jiffies 4294670080 (age 189.604s)
  hex dump (first 32 bytes):
ff ff ff ff 00 00 00 00 00 00 00 00 00 00 00 00  
00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00  
  backtrace:
[<21946f44>] kmemleak_alloc+0x58/0x8c
[<9c43890d>] kmem_cache_alloc_memcg_trace+0x18c/0x25c
[<0e17cd06>] platform_device_register_full+0x64/0x108
[<418a0882>] __dw_hdmi_probe+0xb9c/0xcc0
[<e0b720fd>] dw_hdmi_bind+0x30/0x88
[<9af347f6>] dw_hdmi_rockchip_bind+0x260/0x2e8

Signed-off-by: Jeffy Chen <jeffy.c...@rock-chips.com>
---

 drivers/gpu/drm/bridge/synopsys/dw-hdmi.c | 4 +++-
 1 file changed, 3 insertions(+), 1 deletion(-)

diff --git a/drivers/gpu/drm/bridge/synopsys/dw-hdmi.c 
b/drivers/gpu/drm/bridge/synopsys/dw-hdmi.c
index f9802399cc0d..d9afdc59d4f4 100644
--- a/drivers/gpu/drm/bridge/synopsys/dw-hdmi.c
+++ b/drivers/gpu/drm/bridge/synopsys/dw-hdmi.c
@@ -2567,8 +2567,10 @@ __dw_hdmi_probe(struct platform_device *pdev,
 
 static void __dw_hdmi_remove(struct dw_hdmi *hdmi)
 {
-   if (hdmi->audio && !IS_ERR(hdmi->audio))
+   if (hdmi->audio && !IS_ERR(hdmi->audio)) {
+   kfree(hdmi->audio->dev.dma_mask);
platform_device_unregister(hdmi->audio);
+   }
if (!IS_ERR(hdmi->cec))
platform_device_unregister(hdmi->cec);
 
-- 
2.11.0


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


[PATCH] drm/rockchip: vop: Init vskiplines in scl_vop_cal_scale()

2018-02-22 Thread Jeffy Chen
Currently we are calling scl_vop_cal_scale() to get vskiplines for yrgb
and cbcr. So the cbcr's vskiplines might be an unexpected value if the
second scl_vop_cal_scale() didn't update it.

Init vskiplines in scl_vop_cal_scale() to avoid that.

Signed-off-by: Jeffy Chen <jeffy.c...@rock-chips.com>
---

 drivers/gpu/drm/rockchip/rockchip_drm_vop.c | 5 -
 1 file changed, 4 insertions(+), 1 deletion(-)

diff --git a/drivers/gpu/drm/rockchip/rockchip_drm_vop.c 
b/drivers/gpu/drm/rockchip/rockchip_drm_vop.c
index 7715853ef90a..9b03c51903ab 100644
--- a/drivers/gpu/drm/rockchip/rockchip_drm_vop.c
+++ b/drivers/gpu/drm/rockchip/rockchip_drm_vop.c
@@ -259,6 +259,9 @@ static uint16_t scl_vop_cal_scale(enum scale_mode mode, 
uint32_t src,
 {
uint16_t val = 1 << SCL_FT_DEFAULT_FIXPOINT_SHIFT;
 
+   if (vskiplines)
+   *vskiplines = 0;
+
if (is_horizontal) {
if (mode == SCALE_UP)
val = GET_SCL_FT_BIC(src, dst);
@@ -299,7 +302,7 @@ static void scl_vop_cal_scl_fac(struct vop *vop, const 
struct vop_win_data *win,
uint16_t vsu_mode;
uint16_t lb_mode;
uint32_t val;
-   int vskiplines = 0;
+   int vskiplines;
 
if (dst_w > 3840) {
DRM_DEV_ERROR(vop->dev, "Maximum dst width (3840) exceeded\n");
-- 
2.11.0


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


Re: [PATCH v6 03/10] drm/bridge: analogix: Do not use device's drvdata

2017-10-20 Thread jeffy

Hi Sean,

On 10/21/2017 12:52 AM, Sean Paul wrote:

On Thu, Oct 19, 2017 at 11:48:05AM +0800, Jeffy Chen wrote:

This patch has somehow lost it's original author. I assume this is not
intentional.


oops, sorry, guess i used some wrongly command during the rebasing... 
will fix that.


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


Re: [PATCH] drm/rockchip: Fix build warning in analogix_dp-rockchip.c

2017-10-20 Thread jeffy

Hi Sean,

On 10/21/2017 01:25 AM, Sean Paul wrote:

I didn't catch this before applying, just right after (of course).

Fixes:
../drivers/gpu/drm/rockchip/analogix_dp-rockchip.c: In function
‘rockchip_dp_of_probe’:
../drivers/gpu/drm/rockchip/analogix_dp-rockchip.c:276:6: warning:
unused variable ‘ret’ [-Wunused-variable]
   int ret;
 ^~~


sorry, i thought i fixed that, but it looks like i amended it to the 
wrong commit by mistake...


Fixes: 102712a32ff5 ("drm/rockchip: analogix_dp: Remove unnecessary init
code")
Cc: Jeffy Chen <jeffy.c...@rock-chips.com>
Cc: Mark Yao <mark@rock-chips.com>
Cc: Sean Paul <seanp...@chromium.org>
Cc: Heiko Stuebner <he...@sntech.de>
Cc: dri-devel@lists.freedesktop.org
Cc: linux-arm-ker...@lists.infradead.org
Cc: linux-rockc...@lists.infradead.org
Signed-off-by: Sean Paul <seanp...@chromium.org>
---
  drivers/gpu/drm/rockchip/analogix_dp-rockchip.c | 1 -
  1 file changed, 1 deletion(-)

diff --git a/drivers/gpu/drm/rockchip/analogix_dp-rockchip.c 
b/drivers/gpu/drm/rockchip/analogix_dp-rockchip.c
index 8cae5ad926cd..39944c0f1c0b 100644
--- a/drivers/gpu/drm/rockchip/analogix_dp-rockchip.c
+++ b/drivers/gpu/drm/rockchip/analogix_dp-rockchip.c
@@ -273,7 +273,6 @@ static int rockchip_dp_of_probe(struct rockchip_dp_device 
*dp)
  {
struct device *dev = dp->dev;
struct device_node *np = dev->of_node;
-   int ret;

dp->grf = syscon_regmap_lookup_by_phandle(np, "rockchip,grf");
if (IS_ERR(dp->grf)) {




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


[PATCH v6 09/10] drm/bridge/synopsys: dw-hdmi: Do not use device's drvdata

2017-10-18 Thread Jeffy Chen
Let plat drivers own the drvdata, so that they could cleanup resources
in their unbind().

Signed-off-by: Jeffy Chen <jeffy.c...@rock-chips.com>
Reviewed-by: Neil Armstrong <narmstr...@baylibre.com>
---

Changes in v6: None
Changes in v5: None

 drivers/gpu/drm/bridge/synopsys/dw-hdmi.c   | 43 ++---
 drivers/gpu/drm/imx/dw_hdmi-imx.c   | 22 +--
 drivers/gpu/drm/meson/meson_dw_hdmi.c   | 20 ++
 drivers/gpu/drm/rcar-du/rcar_dw_hdmi.c  | 14 --
 drivers/gpu/drm/rockchip/dw_hdmi-rockchip.c | 23 ---
 include/drm/bridge/dw_hdmi.h| 17 ++--
 6 files changed, 77 insertions(+), 62 deletions(-)

diff --git a/drivers/gpu/drm/bridge/synopsys/dw-hdmi.c 
b/drivers/gpu/drm/bridge/synopsys/dw-hdmi.c
index ff1b3d2b5d06..6fbfafc5832b 100644
--- a/drivers/gpu/drm/bridge/synopsys/dw-hdmi.c
+++ b/drivers/gpu/drm/bridge/synopsys/dw-hdmi.c
@@ -2072,7 +2072,7 @@ static irqreturn_t dw_hdmi_hardirq(int irq, void *dev_id)
return ret;
 }
 
-void __dw_hdmi_setup_rx_sense(struct dw_hdmi *hdmi, bool hpd, bool rx_sense)
+void dw_hdmi_setup_rx_sense(struct dw_hdmi *hdmi, bool hpd, bool rx_sense)
 {
mutex_lock(>mutex);
 
@@ -2098,13 +2098,6 @@ void __dw_hdmi_setup_rx_sense(struct dw_hdmi *hdmi, bool 
hpd, bool rx_sense)
}
mutex_unlock(>mutex);
 }
-
-void dw_hdmi_setup_rx_sense(struct device *dev, bool hpd, bool rx_sense)
-{
-   struct dw_hdmi *hdmi = dev_get_drvdata(dev);
-
-   __dw_hdmi_setup_rx_sense(hdmi, hpd, rx_sense);
-}
 EXPORT_SYMBOL_GPL(dw_hdmi_setup_rx_sense);
 
 static irqreturn_t dw_hdmi_irq(int irq, void *dev_id)
@@ -2140,9 +2133,8 @@ static irqreturn_t dw_hdmi_irq(int irq, void *dev_id)
 */
if (intr_stat &
(HDMI_IH_PHY_STAT0_RX_SENSE | HDMI_IH_PHY_STAT0_HPD)) {
-   __dw_hdmi_setup_rx_sense(hdmi,
-phy_stat & HDMI_PHY_HPD,
-phy_stat & HDMI_PHY_RX_SENSE);
+   dw_hdmi_setup_rx_sense(hdmi, phy_stat & HDMI_PHY_HPD,
+  phy_stat & HDMI_PHY_RX_SENSE);
 
if ((phy_stat & (HDMI_PHY_RX_SENSE | HDMI_PHY_HPD)) == 0)
cec_notifier_set_phys_addr(hdmi->cec_notifier,
@@ -2512,8 +2504,6 @@ __dw_hdmi_probe(struct platform_device *pdev,
if (hdmi->i2c)
dw_hdmi_i2c_init(hdmi);
 
-   platform_set_drvdata(pdev, hdmi);
-
return hdmi;
 
 err_iahb:
@@ -2559,25 +2549,23 @@ static void __dw_hdmi_remove(struct dw_hdmi *hdmi)
 /* 
-
  * Probe/remove API, used from platforms based on the DRM bridge API.
  */
-int dw_hdmi_probe(struct platform_device *pdev,
- const struct dw_hdmi_plat_data *plat_data)
+struct dw_hdmi *dw_hdmi_probe(struct platform_device *pdev,
+ const struct dw_hdmi_plat_data *plat_data)
 {
struct dw_hdmi *hdmi;
 
hdmi = __dw_hdmi_probe(pdev, plat_data);
if (IS_ERR(hdmi))
-   return PTR_ERR(hdmi);
+   return hdmi;
 
drm_bridge_add(>bridge);
 
-   return 0;
+   return hdmi;
 }
 EXPORT_SYMBOL_GPL(dw_hdmi_probe);
 
-void dw_hdmi_remove(struct platform_device *pdev)
+void dw_hdmi_remove(struct dw_hdmi *hdmi)
 {
-   struct dw_hdmi *hdmi = platform_get_drvdata(pdev);
-
drm_bridge_remove(>bridge);
 
__dw_hdmi_remove(hdmi);
@@ -2587,31 +2575,30 @@ EXPORT_SYMBOL_GPL(dw_hdmi_remove);
 /* 
-
  * Bind/unbind API, used from platforms based on the component framework.
  */
-int dw_hdmi_bind(struct platform_device *pdev, struct drm_encoder *encoder,
-const struct dw_hdmi_plat_data *plat_data)
+struct dw_hdmi *dw_hdmi_bind(struct platform_device *pdev,
+   struct drm_encoder *encoder,
+   const struct dw_hdmi_plat_data *plat_data)
 {
struct dw_hdmi *hdmi;
int ret;
 
hdmi = __dw_hdmi_probe(pdev, plat_data);
if (IS_ERR(hdmi))
-   return PTR_ERR(hdmi);
+   return hdmi;
 
ret = drm_bridge_attach(encoder, >bridge, NULL);
if (ret) {
__dw_hdmi_remove(hdmi);
DRM_ERROR("Failed to initialize bridge with drm\n");
-   return ret;
+   return ERR_PTR(ret);
}
 
-   return 0;
+   return hdmi;
 }
 EXPORT_SYMBOL_GPL(dw_hdmi_bind);
 
-void dw_hdmi_unbind(struct device *dev)
+void dw_hdmi_unbind(struct dw_hdmi *hdmi)
 {
-   struct dw_hdmi *hdmi = dev_get_drvdata(dev);
-
__dw_hdmi_remove(hdmi);
 }
 EXPORT_SYMBOL_GPL(dw_hdmi_unbind);
diff --git a/drivers/gpu/drm/imx/dw_hdmi-imx.c 
b/drivers/gpu/drm/imx/dw_hdmi-imx.c
index b62763aa8706

[PATCH v6 10/10] drm/rockchip: dw_hdmi: Fix error handling path

2017-10-18 Thread Jeffy Chen
Add missing clk_disable_unprepare() in bind()'s error handling path and
unbind().

Also inline clk_prepare_enable() with bind().

Fixes: 12b9f204e804 ("drm: bridge/dw_hdmi: add rockchip rk3288 support")
Signed-off-by: Jeffy Chen <jeffy.c...@rock-chips.com>
---

Changes in v6: None
Changes in v5:
Add disable to unbind(), and inline clk_prepare_enable() with bind().

 drivers/gpu/drm/rockchip/dw_hdmi-rockchip.c | 16 +---
 1 file changed, 9 insertions(+), 7 deletions(-)

diff --git a/drivers/gpu/drm/rockchip/dw_hdmi-rockchip.c 
b/drivers/gpu/drm/rockchip/dw_hdmi-rockchip.c
index 791ab938f998..e936dfe6c03d 100644
--- a/drivers/gpu/drm/rockchip/dw_hdmi-rockchip.c
+++ b/drivers/gpu/drm/rockchip/dw_hdmi-rockchip.c
@@ -193,13 +193,6 @@ static int rockchip_hdmi_parse_dt(struct rockchip_hdmi 
*hdmi)
return PTR_ERR(hdmi->grf_clk);
}
 
-   ret = clk_prepare_enable(hdmi->vpll_clk);
-   if (ret) {
-   DRM_DEV_ERROR(hdmi->dev,
- "Failed to enable HDMI vpll: %d\n", ret);
-   return ret;
-   }
-
return 0;
 }
 
@@ -374,6 +367,13 @@ static int dw_hdmi_rockchip_bind(struct device *dev, 
struct device *master,
return ret;
}
 
+   ret = clk_prepare_enable(hdmi->vpll_clk);
+   if (ret) {
+   DRM_DEV_ERROR(hdmi->dev,
+ "Failed to enable HDMI vpll: %d\n", ret);
+   return ret;
+   }
+
drm_encoder_helper_add(encoder, _hdmi_rockchip_encoder_helper_funcs);
drm_encoder_init(drm, encoder, _hdmi_rockchip_encoder_funcs,
 DRM_MODE_ENCODER_TMDS, NULL);
@@ -381,6 +381,7 @@ static int dw_hdmi_rockchip_bind(struct device *dev, struct 
device *master,
hdmi->hdmi = dw_hdmi_bind(pdev, encoder, plat_data);
if (IS_ERR(hdmi->hdmi)) {
encoder->funcs->destroy(encoder);
+   clk_disable_unprepare(hdmi->vpll_clk);
return PTR_ERR(hdmi->hdmi);
}
 
@@ -396,6 +397,7 @@ static void dw_hdmi_rockchip_unbind(struct device *dev, 
struct device *master,
 
dw_hdmi_unbind(hdmi->hdmi);
hdmi->encoder.funcs->destroy(>encoder);
+   clk_disable_unprepare(hdmi->vpll_clk);
 }
 
 static const struct component_ops dw_hdmi_rockchip_ops = {
-- 
2.11.0


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


[PATCH v6 05/10] drm/rockchip: analogix_dp: Add a sanity check for rockchip_drm_psr_register()

2017-10-18 Thread Jeffy Chen
The rockchip_drm_psr_register() can fail, so add a sanity check for that.

Also reorder the calls in unbind() to match bind().

Signed-off-by: Jeffy Chen <jeffy.c...@rock-chips.com>
---

Changes in v6: None
Changes in v5: None

 drivers/gpu/drm/rockchip/analogix_dp-rockchip.c | 15 +++
 1 file changed, 11 insertions(+), 4 deletions(-)

diff --git a/drivers/gpu/drm/rockchip/analogix_dp-rockchip.c 
b/drivers/gpu/drm/rockchip/analogix_dp-rockchip.c
index 117585df73e1..bd3567ad8b53 100644
--- a/drivers/gpu/drm/rockchip/analogix_dp-rockchip.c
+++ b/drivers/gpu/drm/rockchip/analogix_dp-rockchip.c
@@ -356,15 +356,22 @@ static int rockchip_dp_bind(struct device *dev, struct 
device *master,
dp->psr_state = ~EDP_VSC_PSR_STATE_ACTIVE;
INIT_WORK(>psr_work, analogix_dp_psr_work);
 
-   rockchip_drm_psr_register(>encoder, analogix_dp_psr_set);
+   ret = rockchip_drm_psr_register(>encoder, analogix_dp_psr_set);
+   if (ret < 0)
+   goto err_cleanup_encoder;
 
dp->adp = analogix_dp_bind(dev, dp->drm_dev, >plat_data);
if (IS_ERR(dp->adp)) {
-   dp->encoder.funcs->destroy(>encoder);
-   return PTR_ERR(dp->adp);
+   ret = PTR_ERR(dp->adp);
+   goto err_unreg_psr;
}
 
return 0;
+err_unreg_psr:
+   rockchip_drm_psr_unregister(>encoder);
+err_cleanup_encoder:
+   dp->encoder.funcs->destroy(>encoder);
+   return ret;
 }
 
 static void rockchip_dp_unbind(struct device *dev, struct device *master,
@@ -372,8 +379,8 @@ static void rockchip_dp_unbind(struct device *dev, struct 
device *master,
 {
struct rockchip_dp_device *dp = dev_get_drvdata(dev);
 
-   rockchip_drm_psr_unregister(>encoder);
analogix_dp_unbind(dp->adp);
+   rockchip_drm_psr_unregister(>encoder);
dp->encoder.funcs->destroy(>encoder);
 }
 
-- 
2.11.0


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


[PATCH v6 06/10] drm/rockchip: dw-mipi-dsi: Fix error handling path

2017-10-18 Thread Jeffy Chen
Add missing pm_runtime_disable() in bind()'s error handling path.

Also cleanup encoder & connector in unbind().

Fixes: 80a9a059d4e4 ("drm/rockchip/dsi: add dw-mipi power domain support")
Signed-off-by: Jeffy Chen <jeffy.c...@rock-chips.com>
---

Changes in v6: None
Changes in v5:
Call the destroy hook in the error handling path like in unbind().

 drivers/gpu/drm/rockchip/dw-mipi-dsi.c | 21 +
 1 file changed, 13 insertions(+), 8 deletions(-)

diff --git a/drivers/gpu/drm/rockchip/dw-mipi-dsi.c 
b/drivers/gpu/drm/rockchip/dw-mipi-dsi.c
index b15755b6129c..e72d4e2b61aa 100644
--- a/drivers/gpu/drm/rockchip/dw-mipi-dsi.c
+++ b/drivers/gpu/drm/rockchip/dw-mipi-dsi.c
@@ -1282,7 +1282,7 @@ static int dw_mipi_dsi_bind(struct device *dev, struct 
device *master,
ret = dw_mipi_dsi_register(drm, dsi);
if (ret) {
DRM_DEV_ERROR(dev, "Failed to register mipi_dsi: %d\n", ret);
-   goto err_pllref;
+   goto err_disable_pllref;
}
 
pm_runtime_enable(dev);
@@ -1292,23 +1292,24 @@ static int dw_mipi_dsi_bind(struct device *dev, struct 
device *master,
ret = mipi_dsi_host_register(>dsi_host);
if (ret) {
DRM_DEV_ERROR(dev, "Failed to register MIPI host: %d\n", ret);
-   goto err_cleanup;
+   goto err_disable_pm_runtime;
}
 
if (!dsi->panel) {
ret = -EPROBE_DEFER;
-   goto err_mipi_dsi_host;
+   goto err_unreg_mipi_dsi_host;
}
 
dev_set_drvdata(dev, dsi);
return 0;
 
-err_mipi_dsi_host:
+err_unreg_mipi_dsi_host:
mipi_dsi_host_unregister(>dsi_host);
-err_cleanup:
-   drm_encoder_cleanup(>encoder);
-   drm_connector_cleanup(>connector);
-err_pllref:
+err_disable_pm_runtime:
+   pm_runtime_disable(dev);
+   dsi->connector.funcs->destroy(>connector);
+   dsi->encoder.funcs->destroy(>encoder);
+err_disable_pllref:
clk_disable_unprepare(dsi->pllref_clk);
return ret;
 }
@@ -1320,6 +1321,10 @@ static void dw_mipi_dsi_unbind(struct device *dev, 
struct device *master,
 
mipi_dsi_host_unregister(>dsi_host);
pm_runtime_disable(dev);
+
+   dsi->connector.funcs->destroy(>connector);
+   dsi->encoder.funcs->destroy(>encoder);
+
clk_disable_unprepare(dsi->pllref_clk);
 }
 
-- 
2.11.0


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


[PATCH v6 07/10] drm/rockchip: inno_hdmi: Fix error handling path

2017-10-18 Thread Jeffy Chen
Add missing error handling in bind().

Fixes: 412d4ae6b7a5 ("drm/rockchip: hdmi: add Innosilicon HDMI support")
Signed-off-by: Jeffy Chen <jeffy.c...@rock-chips.com>
---

Changes in v6: None
Changes in v5:
Call the destroy hook in the error handling path like in unbind().
Update cleanup order in unbind().

 drivers/gpu/drm/rockchip/inno_hdmi.c | 22 +-
 1 file changed, 17 insertions(+), 5 deletions(-)

diff --git a/drivers/gpu/drm/rockchip/inno_hdmi.c 
b/drivers/gpu/drm/rockchip/inno_hdmi.c
index ee584d87111f..9a96ff6b022b 100644
--- a/drivers/gpu/drm/rockchip/inno_hdmi.c
+++ b/drivers/gpu/drm/rockchip/inno_hdmi.c
@@ -851,8 +851,10 @@ static int inno_hdmi_bind(struct device *dev, struct 
device *master,
}
 
irq = platform_get_irq(pdev, 0);
-   if (irq < 0)
-   return irq;
+   if (irq < 0) {
+   ret = irq;
+   goto err_disable_clk;
+   }
 
inno_hdmi_reset(hdmi);
 
@@ -860,7 +862,7 @@ static int inno_hdmi_bind(struct device *dev, struct device 
*master,
if (IS_ERR(hdmi->ddc)) {
ret = PTR_ERR(hdmi->ddc);
hdmi->ddc = NULL;
-   return ret;
+   goto err_disable_clk;
}
 
/*
@@ -874,7 +876,7 @@ static int inno_hdmi_bind(struct device *dev, struct device 
*master,
 
ret = inno_hdmi_register(drm, hdmi);
if (ret)
-   return ret;
+   goto err_put_adapter;
 
dev_set_drvdata(dev, hdmi);
 
@@ -884,7 +886,17 @@ static int inno_hdmi_bind(struct device *dev, struct 
device *master,
ret = devm_request_threaded_irq(dev, irq, inno_hdmi_hardirq,
inno_hdmi_irq, IRQF_SHARED,
dev_name(dev), hdmi);
+   if (ret < 0)
+   goto err_cleanup_hdmi;
 
+   return 0;
+err_cleanup_hdmi:
+   hdmi->connector.funcs->destroy(>connector);
+   hdmi->encoder.funcs->destroy(>encoder);
+err_put_adapter:
+   i2c_put_adapter(hdmi->ddc);
+err_disable_clk:
+   clk_disable_unprepare(hdmi->pclk);
return ret;
 }
 
@@ -896,8 +908,8 @@ static void inno_hdmi_unbind(struct device *dev, struct 
device *master,
hdmi->connector.funcs->destroy(>connector);
hdmi->encoder.funcs->destroy(>encoder);
 
-   clk_disable_unprepare(hdmi->pclk);
i2c_put_adapter(hdmi->ddc);
+   clk_disable_unprepare(hdmi->pclk);
 }
 
 static const struct component_ops inno_hdmi_ops = {
-- 
2.11.0


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


[PATCH v6 03/10] drm/bridge: analogix: Do not use device's drvdata

2017-10-18 Thread Jeffy Chen
The driver that instantiates the bridge should own the drvdata, as all
driver model callbacks (probe, remove, shutdown, PM ops, etc.) are also
owned by its driver struct. Moreover, storing two different pointer
types in driver data depending on driver initialization status is barely
a good practice and in fact has led to many bugs in this driver.

Let's clean up this mess and change Analogix entry points to simply
accept some opaque struct pointer, adjusting their users at the same
time to avoid breaking the compilation.

Signed-off-by: Tomasz Figa <tf...@chromium.org>
Signed-off-by: Jeffy Chen <jeffy.c...@rock-chips.com>
Reviewed-by: Andrzej Hajda <a.ha...@samsung.com>
Reviewed-by: Sean Paul <seanp...@chromium.org>
Acked-by: Jingoo Han <jingooh...@gmail.com>
Acked-by: Archit Taneja <arch...@codeaurora.org>
---

Changes in v6: None
Changes in v5: None

 drivers/gpu/drm/bridge/analogix/analogix_dp_core.c | 50 +-
 drivers/gpu/drm/exynos/exynos_dp.c | 26 ++-
 drivers/gpu/drm/rockchip/analogix_dp-rockchip.c| 49 -
 include/drm/bridge/analogix_dp.h   | 19 
 4 files changed, 74 insertions(+), 70 deletions(-)

diff --git a/drivers/gpu/drm/bridge/analogix/analogix_dp_core.c 
b/drivers/gpu/drm/bridge/analogix/analogix_dp_core.c
index 5dd3f1cd074a..74d274b6d31d 100644
--- a/drivers/gpu/drm/bridge/analogix/analogix_dp_core.c
+++ b/drivers/gpu/drm/bridge/analogix/analogix_dp_core.c
@@ -98,17 +98,15 @@ static int analogix_dp_detect_hpd(struct analogix_dp_device 
*dp)
return 0;
 }
 
-int analogix_dp_psr_supported(struct device *dev)
+int analogix_dp_psr_supported(struct analogix_dp_device *dp)
 {
-   struct analogix_dp_device *dp = dev_get_drvdata(dev);
 
return dp->psr_support;
 }
 EXPORT_SYMBOL_GPL(analogix_dp_psr_supported);
 
-int analogix_dp_enable_psr(struct device *dev)
+int analogix_dp_enable_psr(struct analogix_dp_device *dp)
 {
-   struct analogix_dp_device *dp = dev_get_drvdata(dev);
struct edp_vsc_psr psr_vsc;
 
if (!dp->psr_support)
@@ -129,9 +127,8 @@ int analogix_dp_enable_psr(struct device *dev)
 }
 EXPORT_SYMBOL_GPL(analogix_dp_enable_psr);
 
-int analogix_dp_disable_psr(struct device *dev)
+int analogix_dp_disable_psr(struct analogix_dp_device *dp)
 {
-   struct analogix_dp_device *dp = dev_get_drvdata(dev);
struct edp_vsc_psr psr_vsc;
int ret;
 
@@ -1281,8 +1278,9 @@ static ssize_t analogix_dpaux_transfer(struct drm_dp_aux 
*aux,
return analogix_dp_transfer(dp, msg);
 }
 
-int analogix_dp_bind(struct device *dev, struct drm_device *drm_dev,
-struct analogix_dp_plat_data *plat_data)
+struct analogix_dp_device *
+analogix_dp_bind(struct device *dev, struct drm_device *drm_dev,
+struct analogix_dp_plat_data *plat_data)
 {
struct platform_device *pdev = to_platform_device(dev);
struct analogix_dp_device *dp;
@@ -1292,14 +1290,12 @@ int analogix_dp_bind(struct device *dev, struct 
drm_device *drm_dev,
 
if (!plat_data) {
dev_err(dev, "Invalided input plat_data\n");
-   return -EINVAL;
+   return ERR_PTR(-EINVAL);
}
 
dp = devm_kzalloc(dev, sizeof(struct analogix_dp_device), GFP_KERNEL);
if (!dp)
-   return -ENOMEM;
-
-   dev_set_drvdata(dev, dp);
+   return ERR_PTR(-ENOMEM);
 
dp->dev = >dev;
dp->dpms_mode = DRM_MODE_DPMS_OFF;
@@ -1316,7 +1312,7 @@ int analogix_dp_bind(struct device *dev, struct 
drm_device *drm_dev,
 
ret = analogix_dp_dt_parse_pdata(dp);
if (ret)
-   return ret;
+   return ERR_PTR(ret);
 
dp->phy = devm_phy_get(dp->dev, "dp");
if (IS_ERR(dp->phy)) {
@@ -1330,14 +1326,14 @@ int analogix_dp_bind(struct device *dev, struct 
drm_device *drm_dev,
if (ret == -ENOSYS || ret == -ENODEV)
dp->phy = NULL;
else
-   return ret;
+   return ERR_PTR(ret);
}
}
 
dp->clock = devm_clk_get(>dev, "dp");
if (IS_ERR(dp->clock)) {
dev_err(>dev, "failed to get clock\n");
-   return PTR_ERR(dp->clock);
+   return ERR_CAST(dp->clock);
}
 
clk_prepare_enable(dp->clock);
@@ -1346,7 +1342,7 @@ int analogix_dp_bind(struct device *dev, struct 
drm_device *drm_dev,
 
dp->reg_base = devm_ioremap_resource(>dev, res);
if (IS_ERR(dp->reg_base))
-   return PTR_ERR(dp->reg_base);
+   return ERR_CAST(dp->reg_base);
 
dp->force_hpd = of_property_read_bool(dev->of_node, "force-hpd");
 
@@ -1367,7 +1363,

[PATCH v6 02/10] drm/rockchip: analogix_dp: Remove unnecessary init code

2017-10-18 Thread Jeffy Chen
Remove unnecessary init code, since we would do it in the power_on()
callback.

Also move of parse code to probe().

Fixes: 9e32e16e9e98 ("drm: rockchip: dp: add rockchip platform dp driver")
Signed-off-by: Jeffy Chen <jeffy.c...@rock-chips.com>
---

Changes in v6: None
Changes in v5: None

 drivers/gpu/drm/rockchip/analogix_dp-rockchip.c | 27 ++---
 1 file changed, 6 insertions(+), 21 deletions(-)

diff --git a/drivers/gpu/drm/rockchip/analogix_dp-rockchip.c 
b/drivers/gpu/drm/rockchip/analogix_dp-rockchip.c
index 4d3f6ad0abdd..8cae5ad926cd 100644
--- a/drivers/gpu/drm/rockchip/analogix_dp-rockchip.c
+++ b/drivers/gpu/drm/rockchip/analogix_dp-rockchip.c
@@ -269,7 +269,7 @@ static struct drm_encoder_funcs rockchip_dp_encoder_funcs = 
{
.destroy = rockchip_dp_drm_encoder_destroy,
 };
 
-static int rockchip_dp_init(struct rockchip_dp_device *dp)
+static int rockchip_dp_of_probe(struct rockchip_dp_device *dp)
 {
struct device *dev = dp->dev;
struct device_node *np = dev->of_node;
@@ -303,19 +303,6 @@ static int rockchip_dp_init(struct rockchip_dp_device *dp)
return PTR_ERR(dp->rst);
}
 
-   ret = clk_prepare_enable(dp->pclk);
-   if (ret < 0) {
-   DRM_DEV_ERROR(dp->dev, "failed to enable pclk %d\n", ret);
-   return ret;
-   }
-
-   ret = rockchip_dp_pre_init(dp);
-   if (ret < 0) {
-   DRM_DEV_ERROR(dp->dev, "failed to pre init %d\n", ret);
-   clk_disable_unprepare(dp->pclk);
-   return ret;
-   }
-
return 0;
 }
 
@@ -361,10 +348,6 @@ static int rockchip_dp_bind(struct device *dev, struct 
device *master,
if (!dp_data)
return -ENODEV;
 
-   ret = rockchip_dp_init(dp);
-   if (ret < 0)
-   return ret;
-
dp->data = dp_data;
dp->drm_dev = drm_dev;
 
@@ -398,7 +381,6 @@ static void rockchip_dp_unbind(struct device *dev, struct 
device *master,
rockchip_drm_psr_unregister(>encoder);
 
analogix_dp_unbind(dev, master, data);
-   clk_disable_unprepare(dp->pclk);
 }
 
 static const struct component_ops rockchip_dp_component_ops = {
@@ -414,7 +396,7 @@ static int rockchip_dp_probe(struct platform_device *pdev)
int ret;
 
ret = drm_of_find_panel_or_bridge(dev->of_node, 1, 0, , NULL);
-   if (ret)
+   if (ret < 0)
return ret;
 
dp = devm_kzalloc(dev, sizeof(*dp), GFP_KERNEL);
@@ -422,9 +404,12 @@ static int rockchip_dp_probe(struct platform_device *pdev)
return -ENOMEM;
 
dp->dev = dev;
-
dp->plat_data.panel = panel;
 
+   ret = rockchip_dp_of_probe(dp);
+   if (ret < 0)
+   return ret;
+
/*
 * We just use the drvdata until driver run into component
 * add function, and then we would set drvdata to null, so
-- 
2.11.0


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


[PATCH v6 08/10] drm/bridge/synopsys: dw-hdmi: Add missing bridge detach

2017-10-18 Thread Jeffy Chen
We inited connector in attach(), so need a detach() to cleanup.

Also fix wrong use of dw_hdmi_remove() in bind().

Signed-off-by: Jeffy Chen <jeffy.c...@rock-chips.com>
---

Changes in v6: None
Changes in v5: None

 drivers/gpu/drm/bridge/synopsys/dw-hdmi.c | 10 +-
 1 file changed, 9 insertions(+), 1 deletion(-)

diff --git a/drivers/gpu/drm/bridge/synopsys/dw-hdmi.c 
b/drivers/gpu/drm/bridge/synopsys/dw-hdmi.c
index bf14214fa464..ff1b3d2b5d06 100644
--- a/drivers/gpu/drm/bridge/synopsys/dw-hdmi.c
+++ b/drivers/gpu/drm/bridge/synopsys/dw-hdmi.c
@@ -1966,6 +1966,13 @@ static int dw_hdmi_bridge_attach(struct drm_bridge 
*bridge)
return 0;
 }
 
+static void dw_hdmi_bridge_detach(struct drm_bridge *bridge)
+{
+   struct dw_hdmi *hdmi = bridge->driver_private;
+
+   drm_connector_cleanup(>connector);
+}
+
 static enum drm_mode_status
 dw_hdmi_bridge_mode_valid(struct drm_bridge *bridge,
  const struct drm_display_mode *mode)
@@ -2022,6 +2029,7 @@ static void dw_hdmi_bridge_enable(struct drm_bridge 
*bridge)
 
 static const struct drm_bridge_funcs dw_hdmi_bridge_funcs = {
.attach = dw_hdmi_bridge_attach,
+   .detach = dw_hdmi_bridge_detach,
.enable = dw_hdmi_bridge_enable,
.disable = dw_hdmi_bridge_disable,
.mode_set = dw_hdmi_bridge_mode_set,
@@ -2591,7 +2599,7 @@ int dw_hdmi_bind(struct platform_device *pdev, struct 
drm_encoder *encoder,
 
ret = drm_bridge_attach(encoder, >bridge, NULL);
if (ret) {
-   dw_hdmi_remove(pdev);
+   __dw_hdmi_remove(hdmi);
DRM_ERROR("Failed to initialize bridge with drm\n");
return ret;
}
-- 
2.11.0


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


[PATCH v6 04/10] drm/bridge: analogix_dp: Fix connector and encoder cleanup

2017-10-18 Thread Jeffy Chen
Since we are initing connector in the core driver and encoder in the
plat driver, let's clean them up in the right places.

Signed-off-by: Jeffy Chen <jeffy.c...@rock-chips.com>
Reviewed-by: Andrzej Hajda <a.ha...@samsung.com>
---

Changes in v6:
Don't change order of rockchip_drm_psr_register().

Changes in v5: None

 drivers/gpu/drm/bridge/analogix/analogix_dp_core.c |  2 --
 drivers/gpu/drm/exynos/exynos_dp.c |  7 +--
 drivers/gpu/drm/rockchip/analogix_dp-rockchip.c| 12 +---
 3 files changed, 10 insertions(+), 11 deletions(-)

diff --git a/drivers/gpu/drm/bridge/analogix/analogix_dp_core.c 
b/drivers/gpu/drm/bridge/analogix/analogix_dp_core.c
index 74d274b6d31d..3f910ab36ff6 100644
--- a/drivers/gpu/drm/bridge/analogix/analogix_dp_core.c
+++ b/drivers/gpu/drm/bridge/analogix/analogix_dp_core.c
@@ -1409,7 +1409,6 @@ analogix_dp_bind(struct device *dev, struct drm_device 
*drm_dev,
ret = analogix_dp_create_bridge(drm_dev, dp);
if (ret) {
DRM_ERROR("failed to create bridge (%d)\n", ret);
-   drm_encoder_cleanup(dp->encoder);
goto err_disable_pm_runtime;
}
 
@@ -1432,7 +1431,6 @@ void analogix_dp_unbind(struct analogix_dp_device *dp)
 {
analogix_dp_bridge_disable(dp->bridge);
dp->connector.funcs->destroy(>connector);
-   dp->encoder->funcs->destroy(dp->encoder);
 
if (dp->plat_data->panel) {
if (drm_panel_unprepare(dp->plat_data->panel))
diff --git a/drivers/gpu/drm/exynos/exynos_dp.c 
b/drivers/gpu/drm/exynos/exynos_dp.c
index f7e5b2c405ed..33319a858f3a 100644
--- a/drivers/gpu/drm/exynos/exynos_dp.c
+++ b/drivers/gpu/drm/exynos/exynos_dp.c
@@ -185,8 +185,10 @@ static int exynos_dp_bind(struct device *dev, struct 
device *master, void *data)
dp->plat_data.encoder = encoder;
 
dp->adp = analogix_dp_bind(dev, dp->drm_dev, >plat_data);
-   if (IS_ERR(dp->adp))
+   if (IS_ERR(dp->adp)) {
+   dp->encoder.funcs->destroy(>encoder);
return PTR_ERR(dp->adp);
+   }
 
return 0;
 }
@@ -196,7 +198,8 @@ static void exynos_dp_unbind(struct device *dev, struct 
device *master,
 {
struct exynos_dp_device *dp = dev_get_drvdata(dev);
 
-   return analogix_dp_unbind(dp->adp);
+   analogix_dp_unbind(dp->adp);
+   dp->encoder.funcs->destroy(>encoder);
 }
 
 static const struct component_ops exynos_dp_ops = {
diff --git a/drivers/gpu/drm/rockchip/analogix_dp-rockchip.c 
b/drivers/gpu/drm/rockchip/analogix_dp-rockchip.c
index fa0365de31d2..117585df73e1 100644
--- a/drivers/gpu/drm/rockchip/analogix_dp-rockchip.c
+++ b/drivers/gpu/drm/rockchip/analogix_dp-rockchip.c
@@ -261,13 +261,8 @@ static struct drm_encoder_helper_funcs 
rockchip_dp_encoder_helper_funcs = {
.atomic_check = rockchip_dp_drm_encoder_atomic_check,
 };
 
-static void rockchip_dp_drm_encoder_destroy(struct drm_encoder *encoder)
-{
-   drm_encoder_cleanup(encoder);
-}
-
 static struct drm_encoder_funcs rockchip_dp_encoder_funcs = {
-   .destroy = rockchip_dp_drm_encoder_destroy,
+   .destroy = drm_encoder_cleanup,
 };
 
 static int rockchip_dp_of_probe(struct rockchip_dp_device *dp)
@@ -364,8 +359,10 @@ static int rockchip_dp_bind(struct device *dev, struct 
device *master,
rockchip_drm_psr_register(>encoder, analogix_dp_psr_set);
 
dp->adp = analogix_dp_bind(dev, dp->drm_dev, >plat_data);
-   if (IS_ERR(dp->adp))
+   if (IS_ERR(dp->adp)) {
+   dp->encoder.funcs->destroy(>encoder);
return PTR_ERR(dp->adp);
+   }
 
return 0;
 }
@@ -377,6 +374,7 @@ static void rockchip_dp_unbind(struct device *dev, struct 
device *master,
 
rockchip_drm_psr_unregister(>encoder);
analogix_dp_unbind(dp->adp);
+   dp->encoder.funcs->destroy(>encoder);
 }
 
 static const struct component_ops rockchip_dp_component_ops = {
-- 
2.11.0


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


[PATCH v6 00/10] rockchip: kevin: Enable edp display

2017-10-18 Thread Jeffy Chen

Make edp display works on chromebook kevin(at least for boot animation).

Also solve some issues i meet during the bringup.

Changes in v6:
Don't change order of rockchip_drm_psr_register().

Changes in v5:
Call the destroy hook in the error handling path like in unbind().
Call the destroy hook in the error handling path like in unbind().
Update cleanup order in unbind().
Add disable to unbind(), and inline clk_prepare_enable() with bind().

Jeffy Chen (10):
  arm64: dts: rockchip: Enable edp disaplay on kevin
  drm/rockchip: analogix_dp: Remove unnecessary init code
  drm/bridge: analogix: Do not use device's drvdata
  drm/bridge: analogix_dp: Fix connector and encoder cleanup
  drm/rockchip: analogix_dp: Add a sanity check for
rockchip_drm_psr_register()
  drm/rockchip: dw-mipi-dsi: Fix error handling path
  drm/rockchip: inno_hdmi: Fix error handling path
  drm/bridge/synopsys: dw-hdmi: Add missing bridge detach
  drm/bridge/synopsys: dw-hdmi: Do not use device's drvdata
  drm/rockchip: dw_hdmi: Fix error handling path

 arch/arm64/boot/dts/rockchip/rk3399-gru-kevin.dts  | 29 +++
 arch/arm64/boot/dts/rockchip/rk3399-gru.dtsi   | 16 
 drivers/gpu/drm/bridge/analogix/analogix_dp_core.c | 52 +---
 drivers/gpu/drm/bridge/synopsys/dw-hdmi.c  | 53 ++--
 drivers/gpu/drm/exynos/exynos_dp.c | 29 ---
 drivers/gpu/drm/imx/dw_hdmi-imx.c  | 22 +++--
 drivers/gpu/drm/meson/meson_dw_hdmi.c  | 20 +++--
 drivers/gpu/drm/rcar-du/rcar_dw_hdmi.c | 14 +++-
 drivers/gpu/drm/rockchip/analogix_dp-rockchip.c| 95 +++---
 drivers/gpu/drm/rockchip/dw-mipi-dsi.c | 21 +++--
 drivers/gpu/drm/rockchip/dw_hdmi-rockchip.c| 39 +
 drivers/gpu/drm/rockchip/inno_hdmi.c   | 22 +++--
 include/drm/bridge/analogix_dp.h   | 19 +++--
 include/drm/bridge/dw_hdmi.h   | 17 ++--
 14 files changed, 265 insertions(+), 183 deletions(-)

-- 
2.11.0


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


Re: [RFC PATCH v4 4/8] drm/rockchip: dw_hdmi: Fix error handling path

2017-10-18 Thread jeffy

Hi Sean,

Thanks for your review.

On 10/18/2017 02:10 AM, Sean Paul wrote:

On Tue, Oct 17, 2017 at 06:16:20PM +0800, Jeffy Chen wrote:

>Add missing clk_disable_unprepare() in bind()'s error handling path.

This also isn't disabled in unbind(), is that intentional?


i wasn't able to do that because of dw_hdmi drvdata.

i've modified it as tomasz did for dp bridge, and fixed the unbind() in 
the next version :)


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


[PATCH v5 8/9] drm/bridge/synopsys: dw-hdmi: Do not use device's drvdata

2017-10-18 Thread Jeffy Chen
Let plat drivers own the drvdata, so that they could cleanup resources
in their unbind().

Signed-off-by: Jeffy Chen <jeffy.c...@rock-chips.com>
---

Changes in v5: None

 drivers/gpu/drm/bridge/synopsys/dw-hdmi.c   | 43 ++---
 drivers/gpu/drm/imx/dw_hdmi-imx.c   | 22 +--
 drivers/gpu/drm/meson/meson_dw_hdmi.c   | 20 ++
 drivers/gpu/drm/rcar-du/rcar_dw_hdmi.c  | 14 --
 drivers/gpu/drm/rockchip/dw_hdmi-rockchip.c | 23 ---
 include/drm/bridge/dw_hdmi.h| 17 ++--
 6 files changed, 77 insertions(+), 62 deletions(-)

diff --git a/drivers/gpu/drm/bridge/synopsys/dw-hdmi.c 
b/drivers/gpu/drm/bridge/synopsys/dw-hdmi.c
index ff1b3d2b5d06..6fbfafc5832b 100644
--- a/drivers/gpu/drm/bridge/synopsys/dw-hdmi.c
+++ b/drivers/gpu/drm/bridge/synopsys/dw-hdmi.c
@@ -2072,7 +2072,7 @@ static irqreturn_t dw_hdmi_hardirq(int irq, void *dev_id)
return ret;
 }
 
-void __dw_hdmi_setup_rx_sense(struct dw_hdmi *hdmi, bool hpd, bool rx_sense)
+void dw_hdmi_setup_rx_sense(struct dw_hdmi *hdmi, bool hpd, bool rx_sense)
 {
mutex_lock(>mutex);
 
@@ -2098,13 +2098,6 @@ void __dw_hdmi_setup_rx_sense(struct dw_hdmi *hdmi, bool 
hpd, bool rx_sense)
}
mutex_unlock(>mutex);
 }
-
-void dw_hdmi_setup_rx_sense(struct device *dev, bool hpd, bool rx_sense)
-{
-   struct dw_hdmi *hdmi = dev_get_drvdata(dev);
-
-   __dw_hdmi_setup_rx_sense(hdmi, hpd, rx_sense);
-}
 EXPORT_SYMBOL_GPL(dw_hdmi_setup_rx_sense);
 
 static irqreturn_t dw_hdmi_irq(int irq, void *dev_id)
@@ -2140,9 +2133,8 @@ static irqreturn_t dw_hdmi_irq(int irq, void *dev_id)
 */
if (intr_stat &
(HDMI_IH_PHY_STAT0_RX_SENSE | HDMI_IH_PHY_STAT0_HPD)) {
-   __dw_hdmi_setup_rx_sense(hdmi,
-phy_stat & HDMI_PHY_HPD,
-phy_stat & HDMI_PHY_RX_SENSE);
+   dw_hdmi_setup_rx_sense(hdmi, phy_stat & HDMI_PHY_HPD,
+  phy_stat & HDMI_PHY_RX_SENSE);
 
if ((phy_stat & (HDMI_PHY_RX_SENSE | HDMI_PHY_HPD)) == 0)
cec_notifier_set_phys_addr(hdmi->cec_notifier,
@@ -2512,8 +2504,6 @@ __dw_hdmi_probe(struct platform_device *pdev,
if (hdmi->i2c)
dw_hdmi_i2c_init(hdmi);
 
-   platform_set_drvdata(pdev, hdmi);
-
return hdmi;
 
 err_iahb:
@@ -2559,25 +2549,23 @@ static void __dw_hdmi_remove(struct dw_hdmi *hdmi)
 /* 
-
  * Probe/remove API, used from platforms based on the DRM bridge API.
  */
-int dw_hdmi_probe(struct platform_device *pdev,
- const struct dw_hdmi_plat_data *plat_data)
+struct dw_hdmi *dw_hdmi_probe(struct platform_device *pdev,
+ const struct dw_hdmi_plat_data *plat_data)
 {
struct dw_hdmi *hdmi;
 
hdmi = __dw_hdmi_probe(pdev, plat_data);
if (IS_ERR(hdmi))
-   return PTR_ERR(hdmi);
+   return hdmi;
 
drm_bridge_add(>bridge);
 
-   return 0;
+   return hdmi;
 }
 EXPORT_SYMBOL_GPL(dw_hdmi_probe);
 
-void dw_hdmi_remove(struct platform_device *pdev)
+void dw_hdmi_remove(struct dw_hdmi *hdmi)
 {
-   struct dw_hdmi *hdmi = platform_get_drvdata(pdev);
-
drm_bridge_remove(>bridge);
 
__dw_hdmi_remove(hdmi);
@@ -2587,31 +2575,30 @@ EXPORT_SYMBOL_GPL(dw_hdmi_remove);
 /* 
-
  * Bind/unbind API, used from platforms based on the component framework.
  */
-int dw_hdmi_bind(struct platform_device *pdev, struct drm_encoder *encoder,
-const struct dw_hdmi_plat_data *plat_data)
+struct dw_hdmi *dw_hdmi_bind(struct platform_device *pdev,
+   struct drm_encoder *encoder,
+   const struct dw_hdmi_plat_data *plat_data)
 {
struct dw_hdmi *hdmi;
int ret;
 
hdmi = __dw_hdmi_probe(pdev, plat_data);
if (IS_ERR(hdmi))
-   return PTR_ERR(hdmi);
+   return hdmi;
 
ret = drm_bridge_attach(encoder, >bridge, NULL);
if (ret) {
__dw_hdmi_remove(hdmi);
DRM_ERROR("Failed to initialize bridge with drm\n");
-   return ret;
+   return ERR_PTR(ret);
}
 
-   return 0;
+   return hdmi;
 }
 EXPORT_SYMBOL_GPL(dw_hdmi_bind);
 
-void dw_hdmi_unbind(struct device *dev)
+void dw_hdmi_unbind(struct dw_hdmi *hdmi)
 {
-   struct dw_hdmi *hdmi = dev_get_drvdata(dev);
-
__dw_hdmi_remove(hdmi);
 }
 EXPORT_SYMBOL_GPL(dw_hdmi_unbind);
diff --git a/drivers/gpu/drm/imx/dw_hdmi-imx.c 
b/drivers/gpu/drm/imx/dw_hdmi-imx.c
index b62763aa8706..b01d03e02ce0 100644
--- a/drivers/gpu/drm/imx/dw_hdmi-imx.c
+++ b/driver

[PATCH v5 9/9] drm/rockchip: dw_hdmi: Fix error handling path

2017-10-18 Thread Jeffy Chen
Add missing clk_disable_unprepare() in bind()'s error handling path and
unbind().

Also inline clk_prepare_enable() with bind().

Fixes: 12b9f204e804 ("drm: bridge/dw_hdmi: add rockchip rk3288 support")
Signed-off-by: Jeffy Chen <jeffy.c...@rock-chips.com>
---

Changes in v5:
Add disable to unbind(), and inline clk_prepare_enable() with bind().

 drivers/gpu/drm/rockchip/dw_hdmi-rockchip.c | 16 +---
 1 file changed, 9 insertions(+), 7 deletions(-)

diff --git a/drivers/gpu/drm/rockchip/dw_hdmi-rockchip.c 
b/drivers/gpu/drm/rockchip/dw_hdmi-rockchip.c
index 791ab938f998..e936dfe6c03d 100644
--- a/drivers/gpu/drm/rockchip/dw_hdmi-rockchip.c
+++ b/drivers/gpu/drm/rockchip/dw_hdmi-rockchip.c
@@ -193,13 +193,6 @@ static int rockchip_hdmi_parse_dt(struct rockchip_hdmi 
*hdmi)
return PTR_ERR(hdmi->grf_clk);
}
 
-   ret = clk_prepare_enable(hdmi->vpll_clk);
-   if (ret) {
-   DRM_DEV_ERROR(hdmi->dev,
- "Failed to enable HDMI vpll: %d\n", ret);
-   return ret;
-   }
-
return 0;
 }
 
@@ -374,6 +367,13 @@ static int dw_hdmi_rockchip_bind(struct device *dev, 
struct device *master,
return ret;
}
 
+   ret = clk_prepare_enable(hdmi->vpll_clk);
+   if (ret) {
+   DRM_DEV_ERROR(hdmi->dev,
+ "Failed to enable HDMI vpll: %d\n", ret);
+   return ret;
+   }
+
drm_encoder_helper_add(encoder, _hdmi_rockchip_encoder_helper_funcs);
drm_encoder_init(drm, encoder, _hdmi_rockchip_encoder_funcs,
 DRM_MODE_ENCODER_TMDS, NULL);
@@ -381,6 +381,7 @@ static int dw_hdmi_rockchip_bind(struct device *dev, struct 
device *master,
hdmi->hdmi = dw_hdmi_bind(pdev, encoder, plat_data);
if (IS_ERR(hdmi->hdmi)) {
encoder->funcs->destroy(encoder);
+   clk_disable_unprepare(hdmi->vpll_clk);
return PTR_ERR(hdmi->hdmi);
}
 
@@ -396,6 +397,7 @@ static void dw_hdmi_rockchip_unbind(struct device *dev, 
struct device *master,
 
dw_hdmi_unbind(hdmi->hdmi);
hdmi->encoder.funcs->destroy(>encoder);
+   clk_disable_unprepare(hdmi->vpll_clk);
 }
 
 static const struct component_ops dw_hdmi_rockchip_ops = {
-- 
2.11.0


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


[PATCH v5 6/9] drm/rockchip: inno_hdmi: Fix error handling path

2017-10-18 Thread Jeffy Chen
Add missing error handling in bind().

Fixes: 412d4ae6b7a5 ("drm/rockchip: hdmi: add Innosilicon HDMI support")
Signed-off-by: Jeffy Chen <jeffy.c...@rock-chips.com>
---

Changes in v5:
Call the destroy hook in the error handling path like in unbind().
Update cleanup order in unbind().

 drivers/gpu/drm/rockchip/inno_hdmi.c | 22 +-
 1 file changed, 17 insertions(+), 5 deletions(-)

diff --git a/drivers/gpu/drm/rockchip/inno_hdmi.c 
b/drivers/gpu/drm/rockchip/inno_hdmi.c
index ee584d87111f..9a96ff6b022b 100644
--- a/drivers/gpu/drm/rockchip/inno_hdmi.c
+++ b/drivers/gpu/drm/rockchip/inno_hdmi.c
@@ -851,8 +851,10 @@ static int inno_hdmi_bind(struct device *dev, struct 
device *master,
}
 
irq = platform_get_irq(pdev, 0);
-   if (irq < 0)
-   return irq;
+   if (irq < 0) {
+   ret = irq;
+   goto err_disable_clk;
+   }
 
inno_hdmi_reset(hdmi);
 
@@ -860,7 +862,7 @@ static int inno_hdmi_bind(struct device *dev, struct device 
*master,
if (IS_ERR(hdmi->ddc)) {
ret = PTR_ERR(hdmi->ddc);
hdmi->ddc = NULL;
-   return ret;
+   goto err_disable_clk;
}
 
/*
@@ -874,7 +876,7 @@ static int inno_hdmi_bind(struct device *dev, struct device 
*master,
 
ret = inno_hdmi_register(drm, hdmi);
if (ret)
-   return ret;
+   goto err_put_adapter;
 
dev_set_drvdata(dev, hdmi);
 
@@ -884,7 +886,17 @@ static int inno_hdmi_bind(struct device *dev, struct 
device *master,
ret = devm_request_threaded_irq(dev, irq, inno_hdmi_hardirq,
inno_hdmi_irq, IRQF_SHARED,
dev_name(dev), hdmi);
+   if (ret < 0)
+   goto err_cleanup_hdmi;
 
+   return 0;
+err_cleanup_hdmi:
+   hdmi->connector.funcs->destroy(>connector);
+   hdmi->encoder.funcs->destroy(>encoder);
+err_put_adapter:
+   i2c_put_adapter(hdmi->ddc);
+err_disable_clk:
+   clk_disable_unprepare(hdmi->pclk);
return ret;
 }
 
@@ -896,8 +908,8 @@ static void inno_hdmi_unbind(struct device *dev, struct 
device *master,
hdmi->connector.funcs->destroy(>connector);
hdmi->encoder.funcs->destroy(>encoder);
 
-   clk_disable_unprepare(hdmi->pclk);
i2c_put_adapter(hdmi->ddc);
+   clk_disable_unprepare(hdmi->pclk);
 }
 
 static const struct component_ops inno_hdmi_ops = {
-- 
2.11.0


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


[PATCH v5 7/9] drm/bridge/synopsys: dw-hdmi: Add missing bridge detach

2017-10-18 Thread Jeffy Chen
We inited connector in attach(), so need a detach() to cleanup.

Also fix wrong use of dw_hdmi_remove() in bind().

Signed-off-by: Jeffy Chen <jeffy.c...@rock-chips.com>
---

Changes in v5: None

 drivers/gpu/drm/bridge/synopsys/dw-hdmi.c | 10 +-
 1 file changed, 9 insertions(+), 1 deletion(-)

diff --git a/drivers/gpu/drm/bridge/synopsys/dw-hdmi.c 
b/drivers/gpu/drm/bridge/synopsys/dw-hdmi.c
index bf14214fa464..ff1b3d2b5d06 100644
--- a/drivers/gpu/drm/bridge/synopsys/dw-hdmi.c
+++ b/drivers/gpu/drm/bridge/synopsys/dw-hdmi.c
@@ -1966,6 +1966,13 @@ static int dw_hdmi_bridge_attach(struct drm_bridge 
*bridge)
return 0;
 }
 
+static void dw_hdmi_bridge_detach(struct drm_bridge *bridge)
+{
+   struct dw_hdmi *hdmi = bridge->driver_private;
+
+   drm_connector_cleanup(>connector);
+}
+
 static enum drm_mode_status
 dw_hdmi_bridge_mode_valid(struct drm_bridge *bridge,
  const struct drm_display_mode *mode)
@@ -2022,6 +2029,7 @@ static void dw_hdmi_bridge_enable(struct drm_bridge 
*bridge)
 
 static const struct drm_bridge_funcs dw_hdmi_bridge_funcs = {
.attach = dw_hdmi_bridge_attach,
+   .detach = dw_hdmi_bridge_detach,
.enable = dw_hdmi_bridge_enable,
.disable = dw_hdmi_bridge_disable,
.mode_set = dw_hdmi_bridge_mode_set,
@@ -2591,7 +2599,7 @@ int dw_hdmi_bind(struct platform_device *pdev, struct 
drm_encoder *encoder,
 
ret = drm_bridge_attach(encoder, >bridge, NULL);
if (ret) {
-   dw_hdmi_remove(pdev);
+   __dw_hdmi_remove(hdmi);
DRM_ERROR("Failed to initialize bridge with drm\n");
return ret;
}
-- 
2.11.0


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


[PATCH v5 2/9] drm/rockchip: analogix_dp: Remove unnecessary init code

2017-10-18 Thread Jeffy Chen
Remove unnecessary init code, since we would do it in the power_on()
callback.

Also move of parse code to probe().

Fixes: 9e32e16e9e98 ("drm: rockchip: dp: add rockchip platform dp driver")
Signed-off-by: Jeffy Chen <jeffy.c...@rock-chips.com>
---

Changes in v5: None

 drivers/gpu/drm/rockchip/analogix_dp-rockchip.c | 27 ++---
 1 file changed, 6 insertions(+), 21 deletions(-)

diff --git a/drivers/gpu/drm/rockchip/analogix_dp-rockchip.c 
b/drivers/gpu/drm/rockchip/analogix_dp-rockchip.c
index 4d3f6ad0abdd..8cae5ad926cd 100644
--- a/drivers/gpu/drm/rockchip/analogix_dp-rockchip.c
+++ b/drivers/gpu/drm/rockchip/analogix_dp-rockchip.c
@@ -269,7 +269,7 @@ static struct drm_encoder_funcs rockchip_dp_encoder_funcs = 
{
.destroy = rockchip_dp_drm_encoder_destroy,
 };
 
-static int rockchip_dp_init(struct rockchip_dp_device *dp)
+static int rockchip_dp_of_probe(struct rockchip_dp_device *dp)
 {
struct device *dev = dp->dev;
struct device_node *np = dev->of_node;
@@ -303,19 +303,6 @@ static int rockchip_dp_init(struct rockchip_dp_device *dp)
return PTR_ERR(dp->rst);
}
 
-   ret = clk_prepare_enable(dp->pclk);
-   if (ret < 0) {
-   DRM_DEV_ERROR(dp->dev, "failed to enable pclk %d\n", ret);
-   return ret;
-   }
-
-   ret = rockchip_dp_pre_init(dp);
-   if (ret < 0) {
-   DRM_DEV_ERROR(dp->dev, "failed to pre init %d\n", ret);
-   clk_disable_unprepare(dp->pclk);
-   return ret;
-   }
-
return 0;
 }
 
@@ -361,10 +348,6 @@ static int rockchip_dp_bind(struct device *dev, struct 
device *master,
if (!dp_data)
return -ENODEV;
 
-   ret = rockchip_dp_init(dp);
-   if (ret < 0)
-   return ret;
-
dp->data = dp_data;
dp->drm_dev = drm_dev;
 
@@ -398,7 +381,6 @@ static void rockchip_dp_unbind(struct device *dev, struct 
device *master,
rockchip_drm_psr_unregister(>encoder);
 
analogix_dp_unbind(dev, master, data);
-   clk_disable_unprepare(dp->pclk);
 }
 
 static const struct component_ops rockchip_dp_component_ops = {
@@ -414,7 +396,7 @@ static int rockchip_dp_probe(struct platform_device *pdev)
int ret;
 
ret = drm_of_find_panel_or_bridge(dev->of_node, 1, 0, , NULL);
-   if (ret)
+   if (ret < 0)
return ret;
 
dp = devm_kzalloc(dev, sizeof(*dp), GFP_KERNEL);
@@ -422,9 +404,12 @@ static int rockchip_dp_probe(struct platform_device *pdev)
return -ENOMEM;
 
dp->dev = dev;
-
dp->plat_data.panel = panel;
 
+   ret = rockchip_dp_of_probe(dp);
+   if (ret < 0)
+   return ret;
+
/*
 * We just use the drvdata until driver run into component
 * add function, and then we would set drvdata to null, so
-- 
2.11.0


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


[PATCH v5 0/9] rockchip: kevin: Enable edp display

2017-10-18 Thread Jeffy Chen

Make edp display works on chromebook kevin(at least for boot animation).

Also solve some issues i meet during the bringup.

Changes in v5:
Call the destroy hook in the error handling path like in unbind().
Call the destroy hook in the error handling path like in unbind().
Update cleanup order in unbind().
Add disable to unbind(), and inline clk_prepare_enable() with bind().

Jeffy Chen (9):
  arm64: dts: rockchip: Enable edp disaplay on kevin
  drm/rockchip: analogix_dp: Remove unnecessary init code
  drm/bridge: analogix: Do not use device's drvdata
  drm/bridge: analogix_dp: Fix connector & encoder cleanup
  drm/rockchip: dw-mipi-dsi: Fix error handling path
  drm/rockchip: inno_hdmi: Fix error handling path
  drm/bridge/synopsys: dw-hdmi: Add missing bridge detach
  drm/bridge/synopsys: dw-hdmi: Do not use device's drvdata
  drm/rockchip: dw_hdmi: Fix error handling path

 arch/arm64/boot/dts/rockchip/rk3399-gru-kevin.dts  | 29 
 arch/arm64/boot/dts/rockchip/rk3399-gru.dtsi   | 16 
 drivers/gpu/drm/bridge/analogix/analogix_dp_core.c | 52 +
 drivers/gpu/drm/bridge/synopsys/dw-hdmi.c  | 53 ++---
 drivers/gpu/drm/exynos/exynos_dp.c | 29 +---
 drivers/gpu/drm/imx/dw_hdmi-imx.c  | 22 +++---
 drivers/gpu/drm/meson/meson_dw_hdmi.c  | 20 +++--
 drivers/gpu/drm/rcar-du/rcar_dw_hdmi.c | 14 +++-
 drivers/gpu/drm/rockchip/analogix_dp-rockchip.c| 87 ++
 drivers/gpu/drm/rockchip/dw-mipi-dsi.c | 21 --
 drivers/gpu/drm/rockchip/dw_hdmi-rockchip.c| 39 +-
 drivers/gpu/drm/rockchip/inno_hdmi.c   | 22 --
 include/drm/bridge/analogix_dp.h   | 19 +++--
 include/drm/bridge/dw_hdmi.h   | 17 +++--
 14 files changed, 257 insertions(+), 183 deletions(-)

-- 
2.11.0


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


[PATCH v5 5/9] drm/rockchip: dw-mipi-dsi: Fix error handling path

2017-10-18 Thread Jeffy Chen
Add missing pm_runtime_disable() in bind()'s error handling path.

Also cleanup encoder & connector in unbind().

Fixes: 80a9a059d4e4 ("drm/rockchip/dsi: add dw-mipi power domain support")
Signed-off-by: Jeffy Chen <jeffy.c...@rock-chips.com>
---

Changes in v5:
Call the destroy hook in the error handling path like in unbind().

 drivers/gpu/drm/rockchip/dw-mipi-dsi.c | 21 +
 1 file changed, 13 insertions(+), 8 deletions(-)

diff --git a/drivers/gpu/drm/rockchip/dw-mipi-dsi.c 
b/drivers/gpu/drm/rockchip/dw-mipi-dsi.c
index b15755b6129c..e72d4e2b61aa 100644
--- a/drivers/gpu/drm/rockchip/dw-mipi-dsi.c
+++ b/drivers/gpu/drm/rockchip/dw-mipi-dsi.c
@@ -1282,7 +1282,7 @@ static int dw_mipi_dsi_bind(struct device *dev, struct 
device *master,
ret = dw_mipi_dsi_register(drm, dsi);
if (ret) {
DRM_DEV_ERROR(dev, "Failed to register mipi_dsi: %d\n", ret);
-   goto err_pllref;
+   goto err_disable_pllref;
}
 
pm_runtime_enable(dev);
@@ -1292,23 +1292,24 @@ static int dw_mipi_dsi_bind(struct device *dev, struct 
device *master,
ret = mipi_dsi_host_register(>dsi_host);
if (ret) {
DRM_DEV_ERROR(dev, "Failed to register MIPI host: %d\n", ret);
-   goto err_cleanup;
+   goto err_disable_pm_runtime;
}
 
if (!dsi->panel) {
ret = -EPROBE_DEFER;
-   goto err_mipi_dsi_host;
+   goto err_unreg_mipi_dsi_host;
}
 
dev_set_drvdata(dev, dsi);
return 0;
 
-err_mipi_dsi_host:
+err_unreg_mipi_dsi_host:
mipi_dsi_host_unregister(>dsi_host);
-err_cleanup:
-   drm_encoder_cleanup(>encoder);
-   drm_connector_cleanup(>connector);
-err_pllref:
+err_disable_pm_runtime:
+   pm_runtime_disable(dev);
+   dsi->connector.funcs->destroy(>connector);
+   dsi->encoder.funcs->destroy(>encoder);
+err_disable_pllref:
clk_disable_unprepare(dsi->pllref_clk);
return ret;
 }
@@ -1320,6 +1321,10 @@ static void dw_mipi_dsi_unbind(struct device *dev, 
struct device *master,
 
mipi_dsi_host_unregister(>dsi_host);
pm_runtime_disable(dev);
+
+   dsi->connector.funcs->destroy(>connector);
+   dsi->encoder.funcs->destroy(>encoder);
+
clk_disable_unprepare(dsi->pllref_clk);
 }
 
-- 
2.11.0


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


[PATCH v5 4/9] drm/bridge: analogix_dp: Fix connector & encoder cleanup

2017-10-18 Thread Jeffy Chen
Since we are initing connector in the core driver and encoder in the
plat driver, let's clean them up in the right places.

Signed-off-by: Jeffy Chen <jeffy.c...@rock-chips.com>
---

Changes in v5: None

 drivers/gpu/drm/bridge/analogix/analogix_dp_core.c |  2 --
 drivers/gpu/drm/exynos/exynos_dp.c |  7 +--
 drivers/gpu/drm/rockchip/analogix_dp-rockchip.c| 15 ++-
 3 files changed, 11 insertions(+), 13 deletions(-)

diff --git a/drivers/gpu/drm/bridge/analogix/analogix_dp_core.c 
b/drivers/gpu/drm/bridge/analogix/analogix_dp_core.c
index 74d274b6d31d..3f910ab36ff6 100644
--- a/drivers/gpu/drm/bridge/analogix/analogix_dp_core.c
+++ b/drivers/gpu/drm/bridge/analogix/analogix_dp_core.c
@@ -1409,7 +1409,6 @@ analogix_dp_bind(struct device *dev, struct drm_device 
*drm_dev,
ret = analogix_dp_create_bridge(drm_dev, dp);
if (ret) {
DRM_ERROR("failed to create bridge (%d)\n", ret);
-   drm_encoder_cleanup(dp->encoder);
goto err_disable_pm_runtime;
}
 
@@ -1432,7 +1431,6 @@ void analogix_dp_unbind(struct analogix_dp_device *dp)
 {
analogix_dp_bridge_disable(dp->bridge);
dp->connector.funcs->destroy(>connector);
-   dp->encoder->funcs->destroy(dp->encoder);
 
if (dp->plat_data->panel) {
if (drm_panel_unprepare(dp->plat_data->panel))
diff --git a/drivers/gpu/drm/exynos/exynos_dp.c 
b/drivers/gpu/drm/exynos/exynos_dp.c
index f7e5b2c405ed..33319a858f3a 100644
--- a/drivers/gpu/drm/exynos/exynos_dp.c
+++ b/drivers/gpu/drm/exynos/exynos_dp.c
@@ -185,8 +185,10 @@ static int exynos_dp_bind(struct device *dev, struct 
device *master, void *data)
dp->plat_data.encoder = encoder;
 
dp->adp = analogix_dp_bind(dev, dp->drm_dev, >plat_data);
-   if (IS_ERR(dp->adp))
+   if (IS_ERR(dp->adp)) {
+   dp->encoder.funcs->destroy(>encoder);
return PTR_ERR(dp->adp);
+   }
 
return 0;
 }
@@ -196,7 +198,8 @@ static void exynos_dp_unbind(struct device *dev, struct 
device *master,
 {
struct exynos_dp_device *dp = dev_get_drvdata(dev);
 
-   return analogix_dp_unbind(dp->adp);
+   analogix_dp_unbind(dp->adp);
+   dp->encoder.funcs->destroy(>encoder);
 }
 
 static const struct component_ops exynos_dp_ops = {
diff --git a/drivers/gpu/drm/rockchip/analogix_dp-rockchip.c 
b/drivers/gpu/drm/rockchip/analogix_dp-rockchip.c
index fa0365de31d2..c0fb3f3748f4 100644
--- a/drivers/gpu/drm/rockchip/analogix_dp-rockchip.c
+++ b/drivers/gpu/drm/rockchip/analogix_dp-rockchip.c
@@ -261,13 +261,8 @@ static struct drm_encoder_helper_funcs 
rockchip_dp_encoder_helper_funcs = {
.atomic_check = rockchip_dp_drm_encoder_atomic_check,
 };
 
-static void rockchip_dp_drm_encoder_destroy(struct drm_encoder *encoder)
-{
-   drm_encoder_cleanup(encoder);
-}
-
 static struct drm_encoder_funcs rockchip_dp_encoder_funcs = {
-   .destroy = rockchip_dp_drm_encoder_destroy,
+   .destroy = drm_encoder_cleanup,
 };
 
 static int rockchip_dp_of_probe(struct rockchip_dp_device *dp)
@@ -361,12 +356,13 @@ static int rockchip_dp_bind(struct device *dev, struct 
device *master,
dp->psr_state = ~EDP_VSC_PSR_STATE_ACTIVE;
INIT_WORK(>psr_work, analogix_dp_psr_work);
 
-   rockchip_drm_psr_register(>encoder, analogix_dp_psr_set);
-
dp->adp = analogix_dp_bind(dev, dp->drm_dev, >plat_data);
-   if (IS_ERR(dp->adp))
+   if (IS_ERR(dp->adp)) {
+   dp->encoder.funcs->destroy(>encoder);
return PTR_ERR(dp->adp);
+   }
 
+   rockchip_drm_psr_register(>encoder, analogix_dp_psr_set);
return 0;
 }
 
@@ -377,6 +373,7 @@ static void rockchip_dp_unbind(struct device *dev, struct 
device *master,
 
rockchip_drm_psr_unregister(>encoder);
analogix_dp_unbind(dp->adp);
+   dp->encoder.funcs->destroy(>encoder);
 }
 
 static const struct component_ops rockchip_dp_component_ops = {
-- 
2.11.0


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


[PATCH v5 3/9] drm/bridge: analogix: Do not use device's drvdata

2017-10-18 Thread Jeffy Chen
The driver that instantiates the bridge should own the drvdata, as all
driver model callbacks (probe, remove, shutdown, PM ops, etc.) are also
owned by its driver struct. Moreover, storing two different pointer
types in driver data depending on driver initialization status is barely
a good practice and in fact has led to many bugs in this driver.

Let's clean up this mess and change Analogix entry points to simply
accept some opaque struct pointer, adjusting their users at the same
time to avoid breaking the compilation.

Signed-off-by: Tomasz Figa <tf...@chromium.org>
Signed-off-by: Jeffy Chen <jeffy.c...@rock-chips.com>
Reviewed-by: Andrzej Hajda <a.ha...@samsung.com>
Reviewed-by: Sean Paul <seanp...@chromium.org>
Acked-by: Jingoo Han <jingooh...@gmail.com>
Acked-by: Archit Taneja <arch...@codeaurora.org>
---

Changes in v5: None

 drivers/gpu/drm/bridge/analogix/analogix_dp_core.c | 50 +-
 drivers/gpu/drm/exynos/exynos_dp.c | 26 ++-
 drivers/gpu/drm/rockchip/analogix_dp-rockchip.c| 49 -
 include/drm/bridge/analogix_dp.h   | 19 
 4 files changed, 74 insertions(+), 70 deletions(-)

diff --git a/drivers/gpu/drm/bridge/analogix/analogix_dp_core.c 
b/drivers/gpu/drm/bridge/analogix/analogix_dp_core.c
index 5dd3f1cd074a..74d274b6d31d 100644
--- a/drivers/gpu/drm/bridge/analogix/analogix_dp_core.c
+++ b/drivers/gpu/drm/bridge/analogix/analogix_dp_core.c
@@ -98,17 +98,15 @@ static int analogix_dp_detect_hpd(struct analogix_dp_device 
*dp)
return 0;
 }
 
-int analogix_dp_psr_supported(struct device *dev)
+int analogix_dp_psr_supported(struct analogix_dp_device *dp)
 {
-   struct analogix_dp_device *dp = dev_get_drvdata(dev);
 
return dp->psr_support;
 }
 EXPORT_SYMBOL_GPL(analogix_dp_psr_supported);
 
-int analogix_dp_enable_psr(struct device *dev)
+int analogix_dp_enable_psr(struct analogix_dp_device *dp)
 {
-   struct analogix_dp_device *dp = dev_get_drvdata(dev);
struct edp_vsc_psr psr_vsc;
 
if (!dp->psr_support)
@@ -129,9 +127,8 @@ int analogix_dp_enable_psr(struct device *dev)
 }
 EXPORT_SYMBOL_GPL(analogix_dp_enable_psr);
 
-int analogix_dp_disable_psr(struct device *dev)
+int analogix_dp_disable_psr(struct analogix_dp_device *dp)
 {
-   struct analogix_dp_device *dp = dev_get_drvdata(dev);
struct edp_vsc_psr psr_vsc;
int ret;
 
@@ -1281,8 +1278,9 @@ static ssize_t analogix_dpaux_transfer(struct drm_dp_aux 
*aux,
return analogix_dp_transfer(dp, msg);
 }
 
-int analogix_dp_bind(struct device *dev, struct drm_device *drm_dev,
-struct analogix_dp_plat_data *plat_data)
+struct analogix_dp_device *
+analogix_dp_bind(struct device *dev, struct drm_device *drm_dev,
+struct analogix_dp_plat_data *plat_data)
 {
struct platform_device *pdev = to_platform_device(dev);
struct analogix_dp_device *dp;
@@ -1292,14 +1290,12 @@ int analogix_dp_bind(struct device *dev, struct 
drm_device *drm_dev,
 
if (!plat_data) {
dev_err(dev, "Invalided input plat_data\n");
-   return -EINVAL;
+   return ERR_PTR(-EINVAL);
}
 
dp = devm_kzalloc(dev, sizeof(struct analogix_dp_device), GFP_KERNEL);
if (!dp)
-   return -ENOMEM;
-
-   dev_set_drvdata(dev, dp);
+   return ERR_PTR(-ENOMEM);
 
dp->dev = >dev;
dp->dpms_mode = DRM_MODE_DPMS_OFF;
@@ -1316,7 +1312,7 @@ int analogix_dp_bind(struct device *dev, struct 
drm_device *drm_dev,
 
ret = analogix_dp_dt_parse_pdata(dp);
if (ret)
-   return ret;
+   return ERR_PTR(ret);
 
dp->phy = devm_phy_get(dp->dev, "dp");
if (IS_ERR(dp->phy)) {
@@ -1330,14 +1326,14 @@ int analogix_dp_bind(struct device *dev, struct 
drm_device *drm_dev,
if (ret == -ENOSYS || ret == -ENODEV)
dp->phy = NULL;
else
-   return ret;
+   return ERR_PTR(ret);
}
}
 
dp->clock = devm_clk_get(>dev, "dp");
if (IS_ERR(dp->clock)) {
dev_err(>dev, "failed to get clock\n");
-   return PTR_ERR(dp->clock);
+   return ERR_CAST(dp->clock);
}
 
clk_prepare_enable(dp->clock);
@@ -1346,7 +1342,7 @@ int analogix_dp_bind(struct device *dev, struct 
drm_device *drm_dev,
 
dp->reg_base = devm_ioremap_resource(>dev, res);
if (IS_ERR(dp->reg_base))
-   return PTR_ERR(dp->reg_base);
+   return ERR_CAST(dp->reg_base);
 
dp->force_hpd = of_property_read_bool(dev->of_node, "force-hpd");
 
@@ -1367,7 +1363,7 @@ int analogix_dp_bind(struct device 

[RFC PATCH v4 8/8] drm/rockchip: Add device links for master and components

2017-10-17 Thread Jeffy Chen
Since we are trying to access components' resources in the master's
suspend/resume PM callbacks(e.g. panel), add device links to correct
the suspend/resume and shutdown ordering.

Signed-off-by: Jeffy Chen <jeffy.c...@rock-chips.com>
---

Changes in v4: None
Changes in v3: None
Changes in v2:
Use device link to correct the suspend/resume and shutdown ordering,
instead of converting rockchip spi's suspend/resume PM callbacks to
late suspend/resume PM callbacks.

 drivers/gpu/drm/rockchip/rockchip_drm_drv.c | 24 +---
 1 file changed, 21 insertions(+), 3 deletions(-)

diff --git a/drivers/gpu/drm/rockchip/rockchip_drm_drv.c 
b/drivers/gpu/drm/rockchip/rockchip_drm_drv.c
index 76d63de5921d..af18967f699b 100644
--- a/drivers/gpu/drm/rockchip/rockchip_drm_drv.c
+++ b/drivers/gpu/drm/rockchip/rockchip_drm_drv.c
@@ -337,6 +337,8 @@ static struct component_match 
*rockchip_drm_match_add(struct device *dev)
 
if (!d)
break;
+
+   device_link_add(dev, d, DL_FLAG_STATELESS);
component_match_add(dev, , compare_dev, d);
} while (true);
}
@@ -406,6 +408,7 @@ static int rockchip_drm_platform_of_probe(struct device 
*dev)
 static int rockchip_drm_platform_probe(struct platform_device *pdev)
 {
struct device *dev = >dev;
+   struct device_link *link;
struct component_match *match = NULL;
int ret;
 
@@ -414,16 +417,31 @@ static int rockchip_drm_platform_probe(struct 
platform_device *pdev)
return ret;
 
match = rockchip_drm_match_add(dev);
-   if (IS_ERR(match))
-   return PTR_ERR(match);
+   if (IS_ERR(match)) {
+   ret = PTR_ERR(match);
+   goto err_cleanup_dev_links;
+   }
 
-   return component_master_add_with_match(dev, _drm_ops, match);
+   ret = component_master_add_with_match(dev, _drm_ops, match);
+   if (ret < 0)
+   goto err_cleanup_dev_links;
+
+   return 0;
+err_cleanup_dev_links:
+   list_for_each_entry(link, >links.consumers, s_node)
+   device_link_del(link);
+   return ret;
 }
 
 static int rockchip_drm_platform_remove(struct platform_device *pdev)
 {
+   struct device_link *link;
+
component_master_del(>dev, _drm_ops);
 
+   list_for_each_entry(link, >dev.links.consumers, s_node)
+   device_link_del(link);
+
return 0;
 }
 
-- 
2.11.0


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


[RFC PATCH v4 4/8] drm/rockchip: dw_hdmi: Fix error handling path

2017-10-17 Thread Jeffy Chen
Add missing clk_disable_unprepare() in bind()'s error handling path.

Fixes: 12b9f204e804 ("drm: bridge/dw_hdmi: add rockchip rk3288 support")
Signed-off-by: Jeffy Chen <jeffy.c...@rock-chips.com>
---

Changes in v4: None
Changes in v3: None
Changes in v2: None

 drivers/gpu/drm/rockchip/dw_hdmi-rockchip.c | 4 +++-
 1 file changed, 3 insertions(+), 1 deletion(-)

diff --git a/drivers/gpu/drm/rockchip/dw_hdmi-rockchip.c 
b/drivers/gpu/drm/rockchip/dw_hdmi-rockchip.c
index 1eb02a82fd91..582283da7861 100644
--- a/drivers/gpu/drm/rockchip/dw_hdmi-rockchip.c
+++ b/drivers/gpu/drm/rockchip/dw_hdmi-rockchip.c
@@ -383,8 +383,10 @@ static int dw_hdmi_rockchip_bind(struct device *dev, 
struct device *master,
 * If dw_hdmi_bind() fails we'll never call dw_hdmi_unbind(),
 * which would have called the encoder cleanup.  Do it manually.
 */
-   if (ret)
+   if (ret) {
drm_encoder_cleanup(encoder);
+   clk_disable_unprepare(hdmi->vpll_clk);
+   }
 
return ret;
 }
-- 
2.11.0


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


[RFC PATCH v4 6/8] drm/bridge/analogix: Do not use device's drvdata

2017-10-17 Thread Jeffy Chen
From: Tomasz Figa <tf...@chromium.org>

The driver that instantiates the bridge should own the drvdata, as all
driver model callbacks (probe, remove, shutdown, PM ops, etc.) are also
owned by its driver struct. Moreover, storing two different pointer
types in driver data depending on driver initialization status is barely
a good practice and in fact has led to many bugs in this driver.

Let's clean up this mess and change Analogix entry points to simply
accept some opaque struct pointer, adjusting their users at the same
time to avoid breaking the compilation.

Signed-off-by: Tomasz Figa <tf...@chromium.org>
Signed-off-by: Jeffy Chen <jeffy.c...@rock-chips.com>
Reviewed-by: Andrzej Hajda <a.ha...@samsung.com>
---

Changes in v4: None
Changes in v3: None
Changes in v2: None

 drivers/gpu/drm/bridge/analogix/analogix_dp_core.c | 50 +-
 drivers/gpu/drm/exynos/exynos_dp.c | 26 ++-
 drivers/gpu/drm/rockchip/analogix_dp-rockchip.c| 47 +++-
 include/drm/bridge/analogix_dp.h   | 19 
 4 files changed, 73 insertions(+), 69 deletions(-)

diff --git a/drivers/gpu/drm/bridge/analogix/analogix_dp_core.c 
b/drivers/gpu/drm/bridge/analogix/analogix_dp_core.c
index 5dd3f1cd074a..74d274b6d31d 100644
--- a/drivers/gpu/drm/bridge/analogix/analogix_dp_core.c
+++ b/drivers/gpu/drm/bridge/analogix/analogix_dp_core.c
@@ -98,17 +98,15 @@ static int analogix_dp_detect_hpd(struct analogix_dp_device 
*dp)
return 0;
 }
 
-int analogix_dp_psr_supported(struct device *dev)
+int analogix_dp_psr_supported(struct analogix_dp_device *dp)
 {
-   struct analogix_dp_device *dp = dev_get_drvdata(dev);
 
return dp->psr_support;
 }
 EXPORT_SYMBOL_GPL(analogix_dp_psr_supported);
 
-int analogix_dp_enable_psr(struct device *dev)
+int analogix_dp_enable_psr(struct analogix_dp_device *dp)
 {
-   struct analogix_dp_device *dp = dev_get_drvdata(dev);
struct edp_vsc_psr psr_vsc;
 
if (!dp->psr_support)
@@ -129,9 +127,8 @@ int analogix_dp_enable_psr(struct device *dev)
 }
 EXPORT_SYMBOL_GPL(analogix_dp_enable_psr);
 
-int analogix_dp_disable_psr(struct device *dev)
+int analogix_dp_disable_psr(struct analogix_dp_device *dp)
 {
-   struct analogix_dp_device *dp = dev_get_drvdata(dev);
struct edp_vsc_psr psr_vsc;
int ret;
 
@@ -1281,8 +1278,9 @@ static ssize_t analogix_dpaux_transfer(struct drm_dp_aux 
*aux,
return analogix_dp_transfer(dp, msg);
 }
 
-int analogix_dp_bind(struct device *dev, struct drm_device *drm_dev,
-struct analogix_dp_plat_data *plat_data)
+struct analogix_dp_device *
+analogix_dp_bind(struct device *dev, struct drm_device *drm_dev,
+struct analogix_dp_plat_data *plat_data)
 {
struct platform_device *pdev = to_platform_device(dev);
struct analogix_dp_device *dp;
@@ -1292,14 +1290,12 @@ int analogix_dp_bind(struct device *dev, struct 
drm_device *drm_dev,
 
if (!plat_data) {
dev_err(dev, "Invalided input plat_data\n");
-   return -EINVAL;
+   return ERR_PTR(-EINVAL);
}
 
dp = devm_kzalloc(dev, sizeof(struct analogix_dp_device), GFP_KERNEL);
if (!dp)
-   return -ENOMEM;
-
-   dev_set_drvdata(dev, dp);
+   return ERR_PTR(-ENOMEM);
 
dp->dev = >dev;
dp->dpms_mode = DRM_MODE_DPMS_OFF;
@@ -1316,7 +1312,7 @@ int analogix_dp_bind(struct device *dev, struct 
drm_device *drm_dev,
 
ret = analogix_dp_dt_parse_pdata(dp);
if (ret)
-   return ret;
+   return ERR_PTR(ret);
 
dp->phy = devm_phy_get(dp->dev, "dp");
if (IS_ERR(dp->phy)) {
@@ -1330,14 +1326,14 @@ int analogix_dp_bind(struct device *dev, struct 
drm_device *drm_dev,
if (ret == -ENOSYS || ret == -ENODEV)
dp->phy = NULL;
else
-   return ret;
+   return ERR_PTR(ret);
}
}
 
dp->clock = devm_clk_get(>dev, "dp");
if (IS_ERR(dp->clock)) {
dev_err(>dev, "failed to get clock\n");
-   return PTR_ERR(dp->clock);
+   return ERR_CAST(dp->clock);
}
 
clk_prepare_enable(dp->clock);
@@ -1346,7 +1342,7 @@ int analogix_dp_bind(struct device *dev, struct 
drm_device *drm_dev,
 
dp->reg_base = devm_ioremap_resource(>dev, res);
if (IS_ERR(dp->reg_base))
-   return PTR_ERR(dp->reg_base);
+   return ERR_CAST(dp->reg_base);
 
dp->force_hpd = of_property_read_bool(dev->of_node, "force-hpd");
 
@@ -1367,7 +1363,7 @@ int analogix_dp_bind(struct device *dev, struct 
drm_device *drm_dev,
  

[RFC PATCH v4 5/8] drm/rockchip: inno_hdmi: Fix error handling path

2017-10-17 Thread Jeffy Chen
Add missing error handling in bind().

Fixes: 412d4ae6b7a5 ("drm/rockchip: hdmi: add Innosilicon HDMI support")
Signed-off-by: Jeffy Chen <jeffy.c...@rock-chips.com>
---

Changes in v4: None
Changes in v3: None
Changes in v2: None

 drivers/gpu/drm/rockchip/inno_hdmi.c | 20 
 1 file changed, 16 insertions(+), 4 deletions(-)

diff --git a/drivers/gpu/drm/rockchip/inno_hdmi.c 
b/drivers/gpu/drm/rockchip/inno_hdmi.c
index ee584d87111f..9c258b05dfa5 100644
--- a/drivers/gpu/drm/rockchip/inno_hdmi.c
+++ b/drivers/gpu/drm/rockchip/inno_hdmi.c
@@ -851,8 +851,10 @@ static int inno_hdmi_bind(struct device *dev, struct 
device *master,
}
 
irq = platform_get_irq(pdev, 0);
-   if (irq < 0)
-   return irq;
+   if (irq < 0) {
+   ret = irq;
+   goto err_disable_clk;
+   }
 
inno_hdmi_reset(hdmi);
 
@@ -860,7 +862,7 @@ static int inno_hdmi_bind(struct device *dev, struct device 
*master,
if (IS_ERR(hdmi->ddc)) {
ret = PTR_ERR(hdmi->ddc);
hdmi->ddc = NULL;
-   return ret;
+   goto err_disable_clk;
}
 
/*
@@ -874,7 +876,7 @@ static int inno_hdmi_bind(struct device *dev, struct device 
*master,
 
ret = inno_hdmi_register(drm, hdmi);
if (ret)
-   return ret;
+   goto err_put_adapter;
 
dev_set_drvdata(dev, hdmi);
 
@@ -884,7 +886,17 @@ static int inno_hdmi_bind(struct device *dev, struct 
device *master,
ret = devm_request_threaded_irq(dev, irq, inno_hdmi_hardirq,
inno_hdmi_irq, IRQF_SHARED,
dev_name(dev), hdmi);
+   if (ret < 0)
+   goto err_cleanup_hdmi;
 
+   return 0;
+err_cleanup_hdmi:
+   drm_connector_cleanup(>connector);
+   drm_encoder_cleanup(>encoder);
+err_put_adapter:
+   i2c_put_adapter(hdmi->ddc);
+err_disable_clk:
+   clk_disable_unprepare(hdmi->pclk);
return ret;
 }
 
-- 
2.11.0


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


[RFC PATCH v4 0/8] rockchip: kevin: Enable edp display

2017-10-17 Thread Jeffy Chen

Make edp display works on chromebook kevin(at least for boot animation).

Also solve some issues i meet during the bringup.

Changes in v4:
Fix compile warning.

Changes in v3:
Assign orphan pwms to dummy pwmchip instead of adding device link in the
customer driver.

Changes in v2:
Use device link to correct the suspend/resume and shutdown ordering,
instead of converting rockchip spi's suspend/resume PM callbacks to
late suspend/resume PM callbacks.

Jeffy Chen (7):
  arm64: dts: rockchip: Enable edp disaplay on kevin
  drm/rockchip: analogix_dp: Fix error handling path
  drm/rockchip: dw-mipi-dsi: Fix error handling path
  drm/rockchip: dw_hdmi: Fix error handling path
  drm/rockchip: inno_hdmi: Fix error handling path
  pwm: Add dummy pwmchip for orphan pwms
  drm/rockchip: Add device links for master and components

Tomasz Figa (1):
  drm/bridge/analogix: Do not use device's drvdata

 arch/arm64/boot/dts/rockchip/rk3399-gru-kevin.dts  | 29 
 arch/arm64/boot/dts/rockchip/rk3399-gru.dtsi   | 16 +
 drivers/gpu/drm/bridge/analogix/analogix_dp_core.c | 50 ++---
 drivers/gpu/drm/exynos/exynos_dp.c | 26 ---
 drivers/gpu/drm/rockchip/analogix_dp-rockchip.c| 57 +--
 drivers/gpu/drm/rockchip/dw-mipi-dsi.c | 17 +++--
 drivers/gpu/drm/rockchip/dw_hdmi-rockchip.c|  4 +-
 drivers/gpu/drm/rockchip/inno_hdmi.c   | 20 --
 drivers/gpu/drm/rockchip/rockchip_drm_drv.c| 24 ++-
 drivers/pwm/core.c | 81 --
 include/drm/bridge/analogix_dp.h   | 19 ++---
 11 files changed, 254 insertions(+), 89 deletions(-)

-- 
2.11.0


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


[RFC PATCH v4 2/8] drm/rockchip: analogix_dp: Fix error handling path

2017-10-17 Thread Jeffy Chen
Add missing error handling in rockchip_dp_bind().

Fixes: 9e32e16e9e98 ("drm: rockchip: dp: add rockchip platform dp driver")
Signed-off-by: Jeffy Chen <jeffy.c...@rock-chips.com>
---

Changes in v4: None
Changes in v3: None
Changes in v2: None

 drivers/gpu/drm/rockchip/analogix_dp-rockchip.c | 14 --
 1 file changed, 12 insertions(+), 2 deletions(-)

diff --git a/drivers/gpu/drm/rockchip/analogix_dp-rockchip.c 
b/drivers/gpu/drm/rockchip/analogix_dp-rockchip.c
index 4d3f6ad0abdd..4b689c0f3fc1 100644
--- a/drivers/gpu/drm/rockchip/analogix_dp-rockchip.c
+++ b/drivers/gpu/drm/rockchip/analogix_dp-rockchip.c
@@ -371,7 +371,7 @@ static int rockchip_dp_bind(struct device *dev, struct 
device *master,
ret = rockchip_dp_drm_create_encoder(dp);
if (ret) {
DRM_ERROR("failed to create drm encoder\n");
-   return ret;
+   goto err_disable_pclk;
}
 
dp->plat_data.encoder = >encoder;
@@ -387,7 +387,17 @@ static int rockchip_dp_bind(struct device *dev, struct 
device *master,
 
rockchip_drm_psr_register(>encoder, analogix_dp_psr_set);
 
-   return analogix_dp_bind(dev, dp->drm_dev, >plat_data);
+   ret = analogix_dp_bind(dev, dp->drm_dev, >plat_data);
+   if (ret < 0)
+   goto err_unreg_psr;
+   return 0;
+
+err_unreg_psr:
+   rockchip_drm_psr_unregister(>encoder);
+   rockchip_dp_drm_encoder_destroy(>encoder);
+err_disable_pclk:
+   clk_disable_unprepare(dp->pclk);
+   return ret;
 }
 
 static void rockchip_dp_unbind(struct device *dev, struct device *master,
-- 
2.11.0


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


[RFC PATCH v4 3/8] drm/rockchip: dw-mipi-dsi: Fix error handling path

2017-10-17 Thread Jeffy Chen
Add missing pm_runtime_disable() in bind()'s error handling path.

Also cleanup encoder & connector in unbind().

Fixes: 80a9a059d4e4 ("drm/rockchip/dsi: add dw-mipi power domain support")
Signed-off-by: Jeffy Chen <jeffy.c...@rock-chips.com>
---

Changes in v4: None
Changes in v3: None
Changes in v2: None

 drivers/gpu/drm/rockchip/dw-mipi-dsi.c | 17 +++--
 1 file changed, 11 insertions(+), 6 deletions(-)

diff --git a/drivers/gpu/drm/rockchip/dw-mipi-dsi.c 
b/drivers/gpu/drm/rockchip/dw-mipi-dsi.c
index b15755b6129c..a17ff0f6f489 100644
--- a/drivers/gpu/drm/rockchip/dw-mipi-dsi.c
+++ b/drivers/gpu/drm/rockchip/dw-mipi-dsi.c
@@ -1282,7 +1282,7 @@ static int dw_mipi_dsi_bind(struct device *dev, struct 
device *master,
ret = dw_mipi_dsi_register(drm, dsi);
if (ret) {
DRM_DEV_ERROR(dev, "Failed to register mipi_dsi: %d\n", ret);
-   goto err_pllref;
+   goto err_disable_pllref;
}
 
pm_runtime_enable(dev);
@@ -1292,23 +1292,24 @@ static int dw_mipi_dsi_bind(struct device *dev, struct 
device *master,
ret = mipi_dsi_host_register(>dsi_host);
if (ret) {
DRM_DEV_ERROR(dev, "Failed to register MIPI host: %d\n", ret);
-   goto err_cleanup;
+   goto err_disable_pm_runtime;
}
 
if (!dsi->panel) {
ret = -EPROBE_DEFER;
-   goto err_mipi_dsi_host;
+   goto err_unreg_mipi_dsi_host;
}
 
dev_set_drvdata(dev, dsi);
return 0;
 
-err_mipi_dsi_host:
+err_unreg_mipi_dsi_host:
mipi_dsi_host_unregister(>dsi_host);
-err_cleanup:
+err_disable_pm_runtime:
+   pm_runtime_disable(dev);
drm_encoder_cleanup(>encoder);
drm_connector_cleanup(>connector);
-err_pllref:
+err_disable_pllref:
clk_disable_unprepare(dsi->pllref_clk);
return ret;
 }
@@ -1320,6 +1321,10 @@ static void dw_mipi_dsi_unbind(struct device *dev, 
struct device *master,
 
mipi_dsi_host_unregister(>dsi_host);
pm_runtime_disable(dev);
+
+   dsi->connector.funcs->destroy(>connector);
+   dsi->encoder.funcs->destroy(>encoder);
+
clk_disable_unprepare(dsi->pllref_clk);
 }
 
-- 
2.11.0


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


Re: [RESEND PATCH v2 2/5] backlight: pwm_bl: Add device link for pwm_bl and pwm

2017-10-17 Thread jeffy

Hi Brian,

On 10/17/2017 07:57 AM, Brian Norris wrote:

This is going to be a*lot*  of churn throughout the tree, if we expect
all resource consumers to do this. I think we'd want some kind of
agreement from the PM maintainers and (larger) subsystem owners before
going down this route...

And in the PWM case, pwm_get() already has the device pointer. Why can't
we just instrument it instead?


according to pwm_bl driver, we may need to take care of pwm_request() too:

pb->pwm = devm_pwm_get(>dev, NULL);
if (IS_ERR(pb->pwm) && PTR_ERR(pb->pwm) != -EPROBE_DEFER && 
!node) {
dev_err(>dev, "unable to request PWM, trying 
legacy API\n");

pb->legacy = true;
pb->pwm = pwm_request(data->pwm_id, "pwm-backlight");
}

and maybe also *of_pwm_get...

maybe we can add a dummy pwm chip for those orphan pwms?


Brian



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


[RFC PATCH v3 2/5] drm/rockchip: Fix error handling path in rockchip_dp_bind()

2017-10-17 Thread Jeffy Chen
Add missing error handling in rockchip_dp_bind().

Fixes: 9e32e16e9e98 ("drm: rockchip: dp: add rockchip platform dp driver")
Signed-off-by: Jeffy Chen <jeffy.c...@rock-chips.com>
---

Changes in v3: None
Changes in v2: None

 drivers/gpu/drm/rockchip/analogix_dp-rockchip.c | 14 --
 1 file changed, 12 insertions(+), 2 deletions(-)

diff --git a/drivers/gpu/drm/rockchip/analogix_dp-rockchip.c 
b/drivers/gpu/drm/rockchip/analogix_dp-rockchip.c
index 4d3f6ad0abdd..cb8941e8bcdd 100644
--- a/drivers/gpu/drm/rockchip/analogix_dp-rockchip.c
+++ b/drivers/gpu/drm/rockchip/analogix_dp-rockchip.c
@@ -371,7 +371,7 @@ static int rockchip_dp_bind(struct device *dev, struct 
device *master,
ret = rockchip_dp_drm_create_encoder(dp);
if (ret) {
DRM_ERROR("failed to create drm encoder\n");
-   return ret;
+   goto err_deinit_dp;
}
 
dp->plat_data.encoder = >encoder;
@@ -387,7 +387,17 @@ static int rockchip_dp_bind(struct device *dev, struct 
device *master,
 
rockchip_drm_psr_register(>encoder, analogix_dp_psr_set);
 
-   return analogix_dp_bind(dev, dp->drm_dev, >plat_data);
+   ret = analogix_dp_bind(dev, dp->drm_dev, >plat_data);
+   if (ret < 0)
+   goto err_unreg_psr;
+   return 0;
+
+err_unreg_psr:
+   rockchip_drm_psr_unregister(>encoder);
+   rockchip_dp_drm_encoder_destroy(>encoder);
+err_deinit_dp:
+   clk_disable_unprepare(dp->pclk);
+   return ret;
 }
 
 static void rockchip_dp_unbind(struct device *dev, struct device *master,
-- 
2.11.0


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


[RFC PATCH v3 5/5] drm/rockchip: Add device links for master and components

2017-10-17 Thread Jeffy Chen
Since we are trying to access components' resources in the master's
suspend/resume PM callbacks(e.g. panel), add device links to correct
the suspend/resume and shutdown ordering.

Signed-off-by: Jeffy Chen <jeffy.c...@rock-chips.com>
---

Changes in v3: None
Changes in v2:
Use device link to correct the suspend/resume and shutdown ordering,
instead of converting rockchip spi's suspend/resume PM callbacks to
late suspend/resume PM callbacks.

 drivers/gpu/drm/rockchip/rockchip_drm_drv.c | 24 +---
 1 file changed, 21 insertions(+), 3 deletions(-)

diff --git a/drivers/gpu/drm/rockchip/rockchip_drm_drv.c 
b/drivers/gpu/drm/rockchip/rockchip_drm_drv.c
index 76d63de5921d..af18967f699b 100644
--- a/drivers/gpu/drm/rockchip/rockchip_drm_drv.c
+++ b/drivers/gpu/drm/rockchip/rockchip_drm_drv.c
@@ -337,6 +337,8 @@ static struct component_match 
*rockchip_drm_match_add(struct device *dev)
 
if (!d)
break;
+
+   device_link_add(dev, d, DL_FLAG_STATELESS);
component_match_add(dev, , compare_dev, d);
} while (true);
}
@@ -406,6 +408,7 @@ static int rockchip_drm_platform_of_probe(struct device 
*dev)
 static int rockchip_drm_platform_probe(struct platform_device *pdev)
 {
struct device *dev = >dev;
+   struct device_link *link;
struct component_match *match = NULL;
int ret;
 
@@ -414,16 +417,31 @@ static int rockchip_drm_platform_probe(struct 
platform_device *pdev)
return ret;
 
match = rockchip_drm_match_add(dev);
-   if (IS_ERR(match))
-   return PTR_ERR(match);
+   if (IS_ERR(match)) {
+   ret = PTR_ERR(match);
+   goto err_cleanup_dev_links;
+   }
 
-   return component_master_add_with_match(dev, _drm_ops, match);
+   ret = component_master_add_with_match(dev, _drm_ops, match);
+   if (ret < 0)
+   goto err_cleanup_dev_links;
+
+   return 0;
+err_cleanup_dev_links:
+   list_for_each_entry(link, >links.consumers, s_node)
+   device_link_del(link);
+   return ret;
 }
 
 static int rockchip_drm_platform_remove(struct platform_device *pdev)
 {
+   struct device_link *link;
+
component_master_del(>dev, _drm_ops);
 
+   list_for_each_entry(link, >dev.links.consumers, s_node)
+   device_link_del(link);
+
return 0;
 }
 
-- 
2.11.0


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


[RFC PATCH v3 3/5] drm/bridge/analogix: Do not use device's drvdata

2017-10-17 Thread Jeffy Chen
From: Tomasz Figa <tf...@chromium.org>

The driver that instantiates the bridge should own the drvdata, as all
driver model callbacks (probe, remove, shutdown, PM ops, etc.) are also
owned by its driver struct. Moreover, storing two different pointer
types in driver data depending on driver initialization status is barely
a good practice and in fact has led to many bugs in this driver.

Let's clean up this mess and change Analogix entry points to simply
accept some opaque struct pointer, adjusting their users at the same
time to avoid breaking the compilation.

Signed-off-by: Tomasz Figa <tf...@chromium.org>
Signed-off-by: Jeffy Chen <jeffy.c...@rock-chips.com>
Reviewed-by: Andrzej Hajda <a.ha...@samsung.com>
---

Changes in v3: None
Changes in v2: None

 drivers/gpu/drm/bridge/analogix/analogix_dp_core.c | 50 +-
 drivers/gpu/drm/exynos/exynos_dp.c | 26 ++-
 drivers/gpu/drm/rockchip/analogix_dp-rockchip.c| 47 +++-
 include/drm/bridge/analogix_dp.h   | 19 
 4 files changed, 73 insertions(+), 69 deletions(-)

diff --git a/drivers/gpu/drm/bridge/analogix/analogix_dp_core.c 
b/drivers/gpu/drm/bridge/analogix/analogix_dp_core.c
index 5dd3f1cd074a..74d274b6d31d 100644
--- a/drivers/gpu/drm/bridge/analogix/analogix_dp_core.c
+++ b/drivers/gpu/drm/bridge/analogix/analogix_dp_core.c
@@ -98,17 +98,15 @@ static int analogix_dp_detect_hpd(struct analogix_dp_device 
*dp)
return 0;
 }
 
-int analogix_dp_psr_supported(struct device *dev)
+int analogix_dp_psr_supported(struct analogix_dp_device *dp)
 {
-   struct analogix_dp_device *dp = dev_get_drvdata(dev);
 
return dp->psr_support;
 }
 EXPORT_SYMBOL_GPL(analogix_dp_psr_supported);
 
-int analogix_dp_enable_psr(struct device *dev)
+int analogix_dp_enable_psr(struct analogix_dp_device *dp)
 {
-   struct analogix_dp_device *dp = dev_get_drvdata(dev);
struct edp_vsc_psr psr_vsc;
 
if (!dp->psr_support)
@@ -129,9 +127,8 @@ int analogix_dp_enable_psr(struct device *dev)
 }
 EXPORT_SYMBOL_GPL(analogix_dp_enable_psr);
 
-int analogix_dp_disable_psr(struct device *dev)
+int analogix_dp_disable_psr(struct analogix_dp_device *dp)
 {
-   struct analogix_dp_device *dp = dev_get_drvdata(dev);
struct edp_vsc_psr psr_vsc;
int ret;
 
@@ -1281,8 +1278,9 @@ static ssize_t analogix_dpaux_transfer(struct drm_dp_aux 
*aux,
return analogix_dp_transfer(dp, msg);
 }
 
-int analogix_dp_bind(struct device *dev, struct drm_device *drm_dev,
-struct analogix_dp_plat_data *plat_data)
+struct analogix_dp_device *
+analogix_dp_bind(struct device *dev, struct drm_device *drm_dev,
+struct analogix_dp_plat_data *plat_data)
 {
struct platform_device *pdev = to_platform_device(dev);
struct analogix_dp_device *dp;
@@ -1292,14 +1290,12 @@ int analogix_dp_bind(struct device *dev, struct 
drm_device *drm_dev,
 
if (!plat_data) {
dev_err(dev, "Invalided input plat_data\n");
-   return -EINVAL;
+   return ERR_PTR(-EINVAL);
}
 
dp = devm_kzalloc(dev, sizeof(struct analogix_dp_device), GFP_KERNEL);
if (!dp)
-   return -ENOMEM;
-
-   dev_set_drvdata(dev, dp);
+   return ERR_PTR(-ENOMEM);
 
dp->dev = >dev;
dp->dpms_mode = DRM_MODE_DPMS_OFF;
@@ -1316,7 +1312,7 @@ int analogix_dp_bind(struct device *dev, struct 
drm_device *drm_dev,
 
ret = analogix_dp_dt_parse_pdata(dp);
if (ret)
-   return ret;
+   return ERR_PTR(ret);
 
dp->phy = devm_phy_get(dp->dev, "dp");
if (IS_ERR(dp->phy)) {
@@ -1330,14 +1326,14 @@ int analogix_dp_bind(struct device *dev, struct 
drm_device *drm_dev,
if (ret == -ENOSYS || ret == -ENODEV)
dp->phy = NULL;
else
-   return ret;
+   return ERR_PTR(ret);
}
}
 
dp->clock = devm_clk_get(>dev, "dp");
if (IS_ERR(dp->clock)) {
dev_err(>dev, "failed to get clock\n");
-   return PTR_ERR(dp->clock);
+   return ERR_CAST(dp->clock);
}
 
clk_prepare_enable(dp->clock);
@@ -1346,7 +1342,7 @@ int analogix_dp_bind(struct device *dev, struct 
drm_device *drm_dev,
 
dp->reg_base = devm_ioremap_resource(>dev, res);
if (IS_ERR(dp->reg_base))
-   return PTR_ERR(dp->reg_base);
+   return ERR_CAST(dp->reg_base);
 
dp->force_hpd = of_property_read_bool(dev->of_node, "force-hpd");
 
@@ -1367,7 +1363,7 @@ int analogix_dp_bind(struct device *dev, struct 
drm_device *drm_dev,
  

[RFC PATCH v3 0/5] rockchip: kevin: Enable edp display

2017-10-17 Thread Jeffy Chen

Make edp display works on chromebook kevin(at least for boot animation).

Also solve some issues i meet during the bringup.

Changes in v3:
Assign orphan pwms to dummy pwmchip instead of adding device link in the
customer driver.

Changes in v2:
Use device link to correct the suspend/resume and shutdown ordering,
instead of converting rockchip spi's suspend/resume PM callbacks to
late suspend/resume PM callbacks.

Jeffy Chen (4):
  arm64: dts: rockchip: Enable edp disaplay on kevin
  drm/rockchip: Fix error handling path in rockchip_dp_bind()
  pwm: Add dummy pwmchip for orphan pwms
  drm/rockchip: Add device links for master and components

Tomasz Figa (1):
  drm/bridge/analogix: Do not use device's drvdata

 arch/arm64/boot/dts/rockchip/rk3399-gru-kevin.dts  | 29 
 arch/arm64/boot/dts/rockchip/rk3399-gru.dtsi   | 16 +
 drivers/gpu/drm/bridge/analogix/analogix_dp_core.c | 50 ++---
 drivers/gpu/drm/exynos/exynos_dp.c | 26 ---
 drivers/gpu/drm/rockchip/analogix_dp-rockchip.c| 57 +--
 drivers/gpu/drm/rockchip/rockchip_drm_drv.c| 24 ++-
 drivers/pwm/core.c | 84 --
 include/drm/bridge/analogix_dp.h   | 19 ++---
 8 files changed, 226 insertions(+), 79 deletions(-)

-- 
2.11.0


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


[RESEND PATCH v2 5/5] drm/rockchip: Add device links for master and components

2017-10-16 Thread Jeffy Chen
Since we are trying to access components' resources in the master's
suspend/resume PM callbacks(e.g. panel), add device links to correct
the suspend/resume and shutdown ordering.

Signed-off-by: Jeffy Chen <jeffy.c...@rock-chips.com>
---

Changes in v2:
Use device link to correct the suspend/resume and shutdown ordering,
instead of converting rockchip spi's suspend/resume PM callbacks to
late suspend/resume PM callbacks.

 drivers/gpu/drm/rockchip/rockchip_drm_drv.c | 24 +---
 1 file changed, 21 insertions(+), 3 deletions(-)

diff --git a/drivers/gpu/drm/rockchip/rockchip_drm_drv.c 
b/drivers/gpu/drm/rockchip/rockchip_drm_drv.c
index 76d63de5921d..af18967f699b 100644
--- a/drivers/gpu/drm/rockchip/rockchip_drm_drv.c
+++ b/drivers/gpu/drm/rockchip/rockchip_drm_drv.c
@@ -337,6 +337,8 @@ static struct component_match 
*rockchip_drm_match_add(struct device *dev)
 
if (!d)
break;
+
+   device_link_add(dev, d, DL_FLAG_STATELESS);
component_match_add(dev, , compare_dev, d);
} while (true);
}
@@ -406,6 +408,7 @@ static int rockchip_drm_platform_of_probe(struct device 
*dev)
 static int rockchip_drm_platform_probe(struct platform_device *pdev)
 {
struct device *dev = >dev;
+   struct device_link *link;
struct component_match *match = NULL;
int ret;
 
@@ -414,16 +417,31 @@ static int rockchip_drm_platform_probe(struct 
platform_device *pdev)
return ret;
 
match = rockchip_drm_match_add(dev);
-   if (IS_ERR(match))
-   return PTR_ERR(match);
+   if (IS_ERR(match)) {
+   ret = PTR_ERR(match);
+   goto err_cleanup_dev_links;
+   }
 
-   return component_master_add_with_match(dev, _drm_ops, match);
+   ret = component_master_add_with_match(dev, _drm_ops, match);
+   if (ret < 0)
+   goto err_cleanup_dev_links;
+
+   return 0;
+err_cleanup_dev_links:
+   list_for_each_entry(link, >links.consumers, s_node)
+   device_link_del(link);
+   return ret;
 }
 
 static int rockchip_drm_platform_remove(struct platform_device *pdev)
 {
+   struct device_link *link;
+
component_master_del(>dev, _drm_ops);
 
+   list_for_each_entry(link, >dev.links.consumers, s_node)
+   device_link_del(link);
+
return 0;
 }
 
-- 
2.11.0


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


[RESEND PATCH v2 2/5] backlight: pwm_bl: Add device link for pwm_bl and pwm

2017-10-16 Thread Jeffy Chen
When the pwm driver is unbound, the pwm_bl driver would still hold a
reference to that pwm, and crash the kernel later(if someone trying
to access that invalid pwm).

Add a device link to avoid this.

Signed-off-by: Jeffy Chen <jeffy.c...@rock-chips.com>
---

Changes in v2: None

 drivers/video/backlight/pwm_bl.c | 2 ++
 1 file changed, 2 insertions(+)

diff --git a/drivers/video/backlight/pwm_bl.c b/drivers/video/backlight/pwm_bl.c
index 9bd17682655a..a76f147a26e7 100644
--- a/drivers/video/backlight/pwm_bl.c
+++ b/drivers/video/backlight/pwm_bl.c
@@ -328,6 +328,8 @@ static int pwm_backlight_probe(struct platform_device *pdev)
goto err_alloc;
}
 
+   device_link_add(>dev, pb->pwm->chip->dev, DL_FLAG_AUTOREMOVE);
+
dev_dbg(>dev, "got pwm for backlight\n");
 
/*
-- 
2.11.0


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


[RESEND PATCH v2 3/5] drm/rockchip: Fix error handling path in rockchip_dp_bind()

2017-10-16 Thread Jeffy Chen
Add missing error handling in rockchip_dp_bind().

Fixes: 9e32e16e9e98 ("drm: rockchip: dp: add rockchip platform dp driver")
Signed-off-by: Jeffy Chen <jeffy.c...@rock-chips.com>
---

Changes in v2: None

 drivers/gpu/drm/rockchip/analogix_dp-rockchip.c | 14 --
 1 file changed, 12 insertions(+), 2 deletions(-)

diff --git a/drivers/gpu/drm/rockchip/analogix_dp-rockchip.c 
b/drivers/gpu/drm/rockchip/analogix_dp-rockchip.c
index 4d3f6ad0abdd..cb8941e8bcdd 100644
--- a/drivers/gpu/drm/rockchip/analogix_dp-rockchip.c
+++ b/drivers/gpu/drm/rockchip/analogix_dp-rockchip.c
@@ -371,7 +371,7 @@ static int rockchip_dp_bind(struct device *dev, struct 
device *master,
ret = rockchip_dp_drm_create_encoder(dp);
if (ret) {
DRM_ERROR("failed to create drm encoder\n");
-   return ret;
+   goto err_deinit_dp;
}
 
dp->plat_data.encoder = >encoder;
@@ -387,7 +387,17 @@ static int rockchip_dp_bind(struct device *dev, struct 
device *master,
 
rockchip_drm_psr_register(>encoder, analogix_dp_psr_set);
 
-   return analogix_dp_bind(dev, dp->drm_dev, >plat_data);
+   ret = analogix_dp_bind(dev, dp->drm_dev, >plat_data);
+   if (ret < 0)
+   goto err_unreg_psr;
+   return 0;
+
+err_unreg_psr:
+   rockchip_drm_psr_unregister(>encoder);
+   rockchip_dp_drm_encoder_destroy(>encoder);
+err_deinit_dp:
+   clk_disable_unprepare(dp->pclk);
+   return ret;
 }
 
 static void rockchip_dp_unbind(struct device *dev, struct device *master,
-- 
2.11.0


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


[RESEND PATCH v2 4/5] drm/bridge/analogix: Do not use device's drvdata

2017-10-16 Thread Jeffy Chen
From: Tomasz Figa <tf...@chromium.org>

The driver that instantiates the bridge should own the drvdata, as all
driver model callbacks (probe, remove, shutdown, PM ops, etc.) are also
owned by its driver struct. Moreover, storing two different pointer
types in driver data depending on driver initialization status is barely
a good practice and in fact has led to many bugs in this driver.

Let's clean up this mess and change Analogix entry points to simply
accept some opaque struct pointer, adjusting their users at the same
time to avoid breaking the compilation.

Signed-off-by: Tomasz Figa <tf...@chromium.org>
Signed-off-by: Jeffy Chen <jeffy.c...@rock-chips.com>
---

Changes in v2: None

 drivers/gpu/drm/bridge/analogix/analogix_dp_core.c | 50 +-
 drivers/gpu/drm/exynos/exynos_dp.c | 26 ++-
 drivers/gpu/drm/rockchip/analogix_dp-rockchip.c| 47 +++-
 include/drm/bridge/analogix_dp.h   | 19 
 4 files changed, 73 insertions(+), 69 deletions(-)

diff --git a/drivers/gpu/drm/bridge/analogix/analogix_dp_core.c 
b/drivers/gpu/drm/bridge/analogix/analogix_dp_core.c
index 5dd3f1cd074a..74d274b6d31d 100644
--- a/drivers/gpu/drm/bridge/analogix/analogix_dp_core.c
+++ b/drivers/gpu/drm/bridge/analogix/analogix_dp_core.c
@@ -98,17 +98,15 @@ static int analogix_dp_detect_hpd(struct analogix_dp_device 
*dp)
return 0;
 }
 
-int analogix_dp_psr_supported(struct device *dev)
+int analogix_dp_psr_supported(struct analogix_dp_device *dp)
 {
-   struct analogix_dp_device *dp = dev_get_drvdata(dev);
 
return dp->psr_support;
 }
 EXPORT_SYMBOL_GPL(analogix_dp_psr_supported);
 
-int analogix_dp_enable_psr(struct device *dev)
+int analogix_dp_enable_psr(struct analogix_dp_device *dp)
 {
-   struct analogix_dp_device *dp = dev_get_drvdata(dev);
struct edp_vsc_psr psr_vsc;
 
if (!dp->psr_support)
@@ -129,9 +127,8 @@ int analogix_dp_enable_psr(struct device *dev)
 }
 EXPORT_SYMBOL_GPL(analogix_dp_enable_psr);
 
-int analogix_dp_disable_psr(struct device *dev)
+int analogix_dp_disable_psr(struct analogix_dp_device *dp)
 {
-   struct analogix_dp_device *dp = dev_get_drvdata(dev);
struct edp_vsc_psr psr_vsc;
int ret;
 
@@ -1281,8 +1278,9 @@ static ssize_t analogix_dpaux_transfer(struct drm_dp_aux 
*aux,
return analogix_dp_transfer(dp, msg);
 }
 
-int analogix_dp_bind(struct device *dev, struct drm_device *drm_dev,
-struct analogix_dp_plat_data *plat_data)
+struct analogix_dp_device *
+analogix_dp_bind(struct device *dev, struct drm_device *drm_dev,
+struct analogix_dp_plat_data *plat_data)
 {
struct platform_device *pdev = to_platform_device(dev);
struct analogix_dp_device *dp;
@@ -1292,14 +1290,12 @@ int analogix_dp_bind(struct device *dev, struct 
drm_device *drm_dev,
 
if (!plat_data) {
dev_err(dev, "Invalided input plat_data\n");
-   return -EINVAL;
+   return ERR_PTR(-EINVAL);
}
 
dp = devm_kzalloc(dev, sizeof(struct analogix_dp_device), GFP_KERNEL);
if (!dp)
-   return -ENOMEM;
-
-   dev_set_drvdata(dev, dp);
+   return ERR_PTR(-ENOMEM);
 
dp->dev = >dev;
dp->dpms_mode = DRM_MODE_DPMS_OFF;
@@ -1316,7 +1312,7 @@ int analogix_dp_bind(struct device *dev, struct 
drm_device *drm_dev,
 
ret = analogix_dp_dt_parse_pdata(dp);
if (ret)
-   return ret;
+   return ERR_PTR(ret);
 
dp->phy = devm_phy_get(dp->dev, "dp");
if (IS_ERR(dp->phy)) {
@@ -1330,14 +1326,14 @@ int analogix_dp_bind(struct device *dev, struct 
drm_device *drm_dev,
if (ret == -ENOSYS || ret == -ENODEV)
dp->phy = NULL;
else
-   return ret;
+   return ERR_PTR(ret);
}
}
 
dp->clock = devm_clk_get(>dev, "dp");
if (IS_ERR(dp->clock)) {
dev_err(>dev, "failed to get clock\n");
-   return PTR_ERR(dp->clock);
+   return ERR_CAST(dp->clock);
}
 
clk_prepare_enable(dp->clock);
@@ -1346,7 +1342,7 @@ int analogix_dp_bind(struct device *dev, struct 
drm_device *drm_dev,
 
dp->reg_base = devm_ioremap_resource(>dev, res);
if (IS_ERR(dp->reg_base))
-   return PTR_ERR(dp->reg_base);
+   return ERR_CAST(dp->reg_base);
 
dp->force_hpd = of_property_read_bool(dev->of_node, "force-hpd");
 
@@ -1367,7 +1363,7 @@ int analogix_dp_bind(struct device *dev, struct 
drm_device *drm_dev,
"hpd_gpio");
if (ret) {
dev_err(>dev, &

[RESEND PATCH v2 0/5] rockchip: kevin: Enable edp display

2017-10-16 Thread Jeffy Chen

Make edp display works on chromebook kevin(at least for boot animation).

Also solve some issues i meet during the bringup.

Changes in v2:
Use device link to correct the suspend/resume and shutdown ordering,
instead of converting rockchip spi's suspend/resume PM callbacks to
late suspend/resume PM callbacks.

Jeffy Chen (4):
  arm64: dts: rockchip: Enable edp disaplay on kevin
  backlight: pwm_bl: Add device link for pwm_bl and pwm
  drm/rockchip: Fix error handling path in rockchip_dp_bind()
  drm/rockchip: Add device links for master and components

Tomasz Figa (1):
  drm/bridge/analogix: Do not use device's drvdata

 arch/arm64/boot/dts/rockchip/rk3399-gru-kevin.dts  | 29 +++
 arch/arm64/boot/dts/rockchip/rk3399-gru.dtsi   | 16 ++
 drivers/gpu/drm/bridge/analogix/analogix_dp_core.c | 50 ---
 drivers/gpu/drm/exynos/exynos_dp.c | 26 +-
 drivers/gpu/drm/rockchip/analogix_dp-rockchip.c| 57 ++
 drivers/gpu/drm/rockchip/rockchip_drm_drv.c| 24 +++--
 drivers/video/backlight/pwm_bl.c   |  2 +
 include/drm/bridge/analogix_dp.h   | 19 +---
 8 files changed, 151 insertions(+), 72 deletions(-)

-- 
2.11.0


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


[PATCH 0/5] rockchip: kevin: Enable edp display

2017-10-16 Thread Jeffy Chen

Make edp display works on chromebook kevin(at least for boot animation).

Also solve some issues i meet during the bringup.


Jeffy Chen (4):
  arm64: dts: rockchip: Enable edp disaplay on kevin
  backlight: pwm_bl: Add device link for pwm_bl and pwm
  drm/rockchip: Fix error handling path in rockchip_dp_bind()
  drm/rockchip: Add device links for master and components

Tomasz Figa (1):
  drm/bridge/analogix: Do not use device's drvdata

 arch/arm64/boot/dts/rockchip/rk3399-gru-kevin.dts  | 29 +++
 arch/arm64/boot/dts/rockchip/rk3399-gru.dtsi   | 16 ++
 drivers/gpu/drm/bridge/analogix/analogix_dp_core.c | 50 ---
 drivers/gpu/drm/exynos/exynos_dp.c | 26 +-
 drivers/gpu/drm/rockchip/analogix_dp-rockchip.c| 57 ++
 drivers/gpu/drm/rockchip/rockchip_drm_drv.c| 24 +++--
 drivers/video/backlight/pwm_bl.c   |  2 +
 include/drm/bridge/analogix_dp.h   | 19 +---
 8 files changed, 151 insertions(+), 72 deletions(-)

-- 
2.11.0


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


Re: [PATCH] drm/rockchip: Fix memory leak in rockchip_drm_sys_resume()

2017-10-09 Thread jeffy

Hi Sean,

On 09/28/2017 11:16 AM, jeffy wrote:

Hi Sean,

On 09/28/2017 04:27 AM, Sean Paul wrote:

>@@ -299,6 +300,7 @@ static int rockchip_drm_sys_resume(struct device
*dev)
>
>  priv = drm->dev_private;
>  drm_atomic_helper_resume(drm, priv->state);
>+drm_atomic_state_put(priv->state);

Won't this be freed for you eventually in commit_tail()?


i think the drm_atomic_state_put in commit_tail is paired to the
drm_atomic_state_get in drm_atomic_helper_commit.

and the kmemleak shows(after a few suspend/resume):

 unreferenced object 0xffc0ce0fa400 (size 256):
 ...
   backtrace:
 [] __save_stack_trace+0x48/0x6c
 [] create_object+0x138/0x254
 [] kmemleak_alloc+0x58/0x8c
 [] __kmalloc+0x1d4/0x2a0
 [] usb_alloc_urb+0x30/0x60
 [] alloc_ctrl_urb+0x38/0x120 [btusb]
 [] btusb_send_frame+0x64/0xf8 [btusb]


oops, the log is wrong...

it should be:
unreferenced object 0xffc0c75fe600 (size 256):
  comm "bash", pid 168, jiffies 4294748032 (age 557.932s)
  hex dump (first 32 bytes):
e0 4a 02 ce c0 ff ff ff 00 98 f2 c8 c0 ff ff ff  .J..
00 98 f2 c8 c0 ff ff ff 00 45 9f cb c0 ff ff ff  .E..
  backtrace:
[] kmemleak_alloc+0x58/0x8c
[] __kmalloc+0x1dc/0x2d4
[] drm_atomic_state_init+0xb8/0x114
[] drm_atomic_state_alloc+0x70/0xa4
[] drm_atomic_helper_duplicate_state+0x94/0x210
[] drm_atomic_helper_suspend+0xb4/0x160
[] rockchip_drm_sys_suspend+0x5c/0xa0
[] platform_pm_suspend+0x58/0x74
[] dpm_run_callback+0x13c/0x2f0
[] __device_suspend+0x28c/0x3fc
[] dpm_suspend+0x1cc/0x50c
[] dpm_suspend_start+0x8c/0xa4
[] suspend_devices_and_enter+0x12c/0xd84
[] pm_suspend+0xa38/0xb98
[] state_store+0xe0/0x108
[] kobj_attr_store+0x48/0x58


since it's allocated in the drm_atomic_helper_suspend(), maybe it would 
make more sense to unref it in drm_atomic_helper_resume(), i'll send a 
v2 patch for it :)







checking the current code, i saw only i915/intel_display.c has this
drm_atomic_state_put for the state allocated by
drm_atomic_helper_suspend(), there're many drivers missing that(or maybe
they free it in some other way?)


Sean






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


[PATCH v2] drm/atomic: Unref duplicated drm_atomic_state in drm_atomic_helper_resume()

2017-10-09 Thread Jeffy Chen
Kmemleak reported memory leak after suspend and resume:
unreferenced object 0xffc0e31d8880 (size 128):
  comm "bash", pid 181, jiffies 4294763583 (age 24.694s)
  hex dump (first 32 bytes):
01 00 00 00 00 00 00 00 00 20 a2 eb c0 ff ff ff  . ..
01 00 00 00 00 00 00 00 80 87 1d e3 c0 ff ff ff  
  backtrace:
[] __save_stack_trace+0x48/0x6c
[] create_object+0x138/0x254
[] kmemleak_alloc+0x58/0x8c
[] kmem_cache_alloc_trace+0x188/0x254
[] drm_atomic_state_alloc+0x3c/0x88
[] drm_atomic_helper_duplicate_state+0x28/0x158
[] drm_atomic_helper_suspend+0x5c/0xf0

Problem here is that we are duplicating the drm_atomic_state in
drm_atomic_helper_suspend(), but not unreference it in the resume path.

Fixes: 1494276000db ("drm/atomic-helper: Implement subsystem-level 
suspend/resume")
Signed-off-by: Jeffy Chen <jeffy.c...@rock-chips.com>
---

Changes in v2:
Unref duplicated drm_atomic_state in drm_atomic_helper_resume() instead
of specific drivers.

 drivers/gpu/drm/drm_atomic_helper.c | 1 +
 1 file changed, 1 insertion(+)

diff --git a/drivers/gpu/drm/drm_atomic_helper.c 
b/drivers/gpu/drm/drm_atomic_helper.c
index 01c34bc5b5b0..4a262380c631 100644
--- a/drivers/gpu/drm/drm_atomic_helper.c
+++ b/drivers/gpu/drm/drm_atomic_helper.c
@@ -3052,6 +3052,7 @@ int drm_atomic_helper_resume(struct drm_device *dev,
drm_modeset_backoff();
}
 
+   drm_atomic_state_put(state);
drm_modeset_drop_locks();
drm_modeset_acquire_fini();
 
-- 
2.11.0


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


Re: [PATCH] drm/rockchip: Fix memory leak in rockchip_drm_sys_resume()

2017-09-27 Thread jeffy

Hi Sean,

On 09/28/2017 04:27 AM, Sean Paul wrote:

>@@ -299,6 +300,7 @@ static int rockchip_drm_sys_resume(struct device *dev)
>
>priv = drm->dev_private;
>drm_atomic_helper_resume(drm, priv->state);
>+   drm_atomic_state_put(priv->state);

Won't this be freed for you eventually in commit_tail()?

i think the drm_atomic_state_put in commit_tail is paired to the 
drm_atomic_state_get in drm_atomic_helper_commit.


and the kmemleak shows(after a few suspend/resume):

unreferenced object 0xffc0ce0fa400 (size 256):
...
  backtrace:
[] __save_stack_trace+0x48/0x6c
[] create_object+0x138/0x254
[] kmemleak_alloc+0x58/0x8c
[] __kmalloc+0x1d4/0x2a0
[] usb_alloc_urb+0x30/0x60
[] alloc_ctrl_urb+0x38/0x120 [btusb]
[] btusb_send_frame+0x64/0xf8 [btusb]




checking the current code, i saw only i915/intel_display.c has this 
drm_atomic_state_put for the state allocated by 
drm_atomic_helper_suspend(), there're many drivers missing that(or maybe 
they free it in some other way?)



Sean




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


[PATCH] drm/rockchip: Fix memory leak in rockchip_drm_sys_resume()

2017-09-27 Thread Jeffy Chen
Free the drm_atomic_state allocated by drm_atomic_helper_suspend().

Fixes: 5a5873830972 ("drm/rockchip: Use atomic PM helpers")
Signed-off-by: Jeffy Chen <jeffy.c...@rock-chips.com>
---

 drivers/gpu/drm/rockchip/rockchip_drm_drv.c | 2 ++
 1 file changed, 2 insertions(+)

diff --git a/drivers/gpu/drm/rockchip/rockchip_drm_drv.c 
b/drivers/gpu/drm/rockchip/rockchip_drm_drv.c
index 76d63de5921d..80235b672deb 100644
--- a/drivers/gpu/drm/rockchip/rockchip_drm_drv.c
+++ b/drivers/gpu/drm/rockchip/rockchip_drm_drv.c
@@ -15,6 +15,7 @@
  */
 
 #include 
+#include 
 #include 
 #include 
 #include 
@@ -299,6 +300,7 @@ static int rockchip_drm_sys_resume(struct device *dev)
 
priv = drm->dev_private;
drm_atomic_helper_resume(drm, priv->state);
+   drm_atomic_state_put(priv->state);
rockchip_drm_fb_resume(drm);
drm_kms_helper_poll_enable(drm);
 
-- 
2.11.0


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


Re: [v2] timers: Fix excessive granularity of new timers after a nohz idle

2017-08-23 Thread jeffy

Hi Thierry,

i hit a compile error with this patch:

  CC  drivers/gpu/drm/tegra/trace.o
In file included from drivers/gpu/drm/tegra/trace.h:68:0,
 from drivers/gpu/drm/tegra/trace.c:2:
./include/trace/define_trace.h:88:43: fatal error: ./trace.h: No such 
file or directory

compilation terminated.
scripts/Makefile.build:311: recipe for target 
'drivers/gpu/drm/tegra/trace.o' failed



On 08/22/2017 04:43 PM, Nicholas Piggin wrote:

+++ b/drivers/gpu/drm/tegra/Makefile
@@ -24,4 +24,6 @@ tegra-drm-$(CONFIG_ARCH_TEGRA_186_SOC) += \
parker/dsi.o \
parker/sor.o

+tegra-drm-y += trace.o
+


maybe we need this:

+++ b/drivers/gpu/drm/tegra/Makefile
@@ -19,4 +19,6 @@ tegra-drm-y := \

 tegra-drm-y += trace.o

+CFLAGS_trace.o := -I$(src)
+
 obj-$(CONFIG_DRM_TEGRA) += tegra-drm.o

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


Re: [v6,5/7] drm/rockchip: vop: add a series of vop support

2017-07-27 Thread jeffy

Hi mark,

On 07/26/2017 02:19 PM, Mark yao wrote:

Vop Full framework now has following vops:
IP versionchipname
   3.1   rk3288
   3.2   rk3368
   3.4   rk3366
   3.5   rk3399 big
   3.6   rk3399 lit
   3.7   rk3228
   3.8   rk3328

The above IP version is from H/W define, some of vop support get
the IP version from VERSION_INFO register, some are not.
hardcode the IP version for each vop to identify them.

major version: used for IP structure, Vop full framework is 3,
vop little framework is 2.
minor version: on same structure, newer design vop will bigger
then old one.

Signed-off-by: Mark Yao<mark@rock-chips.com>


Reviewed-by: Jeffy Chen <jeffy.c...@rock-chips.com>

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


Re: [v6,4/7] drm/rockchip: vop: group vop registers

2017-07-27 Thread jeffy

Hi mark,

On 07/26/2017 02:19 PM, Mark yao wrote:

Grouping the vop registers facilitates make register
definition clearer, and also is useful for different vop
reuse the same group register.

Signed-off-by: Mark Yao<mark@rock-chips.com>


Reviewed-by: Jeffy Chen <jeffy.c...@rock-chips.com>

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


Re: [v6, 2/7] drm/rockchip: vop: move write_relaxed flags to vop register

2017-07-27 Thread jeffy

Hi mark,

On 07/26/2017 02:19 PM, Mark yao wrote:

Since the drm atomic framework, only a small part of the vop
register needs sync write, Currently seems only following registers
need sync write:
cfg_done, standby and interrupt related register.

All ctrl registers are using the sync write method that is
inefficient, hardcode the write_relaxed flags to vop registers,
then can only do synchronize write for those actual needed register.

Signed-off-by: Mark Yao<mark@rock-chips.com>
Tested-by: Heiko Stuebner<he...@sntech.de>


Reviewed-by: Jeffy Chen <jeffy.c...@rock-chips.com>

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


Re: [v6,7/7] drm/rockchip: vop: rk3328: fix overlay abnormal

2017-07-27 Thread jeffy

Hi mark,

On 07/26/2017 02:19 PM, Mark yao wrote:

It's a hardware bug, all window's overlay channel reset
value is same, hardware overlay would be die.

so we must initial difference id for each overlay channel.

The Channel register is supported on all vop will full design.
Following is the details for this register
VOP_WIN0_CTRL2
   bit[7:4] win_rid_win0_cbr
axi read id of win0 cbr channel
   bit[3:0] win_rid_win0_yrgb
axi read id of win0 yrgb channel

Signed-off-by: Mark Yao<mark@rock-chips.com>


Reviewed-by: Jeffy Chen <jeffy.c...@rock-chips.com>

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


Re: [v6,1/7] drm/rockchip: vop: initialize registers directly

2017-07-27 Thread jeffy

Hi mark,

On 07/26/2017 02:19 PM, Mark yao wrote:

At present we are using init_table to initialize some
registers, but the Register init table use un-document define,
it is unreadable, and sometimes we only want to update tiny
bits, init table method is not friendly, it's diffcult to
reuse for difference chips.

To make it clean, initialize registers directly, and drops
init_table mechanism out.

Signed-off-by: Mark Yao<mark@rock-chips.com>
Tested-by: Heiko Stuebner<he...@sntech.de>


Reviewed-by: Jeffy Chen <jeffy.c...@rock-chips.com>

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


Re: drm: Add missing field copy in compat_drm_version

2017-07-12 Thread jeffy

Hi guys,

i was testing this on arm64 base chromeos(with arm32 userspace).

and the libdrm crashed:
drmVersionPtr drmGetVersion(int fd)
{
...
memclear(*version);

if (drmIoctl(fd, DRM_IOCTL_VERSION, version)) {
...
if (version->name_len)
version->name= drmMalloc(version->name_len + 1); <-- 
rely on the lengths updated by kernel

if (version->date_len)
version->date= drmMalloc(version->date_len + 1);
if (version->desc_len)
version->desc= drmMalloc(version->desc_len + 1);
...
if (version->name_len) version->name[version->name_len] = '\0'; 
<-- crashed here, since the name_len would always be zero, so 
version->name would be nullptr.



On 07/12/2017 02:18 PM, Jeffy Chen wrote:

DRM_IOCTL_VERSION is supposed to update the name_len/date_len/desc_len
fields to user.

Fixes: 012c6741c6aa("switch compat_drm_version() to drm_ioctl_kernel()")
Signed-off-by: Jeffy Chen <jeffy.c...@rock-chips.com>
---

  drivers/gpu/drm/drm_ioc32.c | 3 +++
  1 file changed, 3 insertions(+)

diff --git a/drivers/gpu/drm/drm_ioc32.c b/drivers/gpu/drm/drm_ioc32.c
index 94acf51..2789356 100644
--- a/drivers/gpu/drm/drm_ioc32.c
+++ b/drivers/gpu/drm/drm_ioc32.c
@@ -112,6 +112,9 @@ static int compat_drm_version(struct file *file, unsigned 
int cmd,
v32.version_major = v.version_major;
v32.version_minor = v.version_minor;
v32.version_patchlevel = v.version_patchlevel;
+   v32.name_len = v.name_len;
+   v32.date_len = v.date_len;
+   v32.desc_len = v.desc_len;
if (copy_to_user((void __user *)arg, , sizeof(v32)))
return -EFAULT;
return 0;





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


[PATCH] drm: Add missing field copy in compat_drm_version

2017-07-12 Thread Jeffy Chen
DRM_IOCTL_VERSION is supposed to update the name_len/date_len/desc_len
fields to user.

Fixes: 012c6741c6aa("switch compat_drm_version() to drm_ioctl_kernel()")
Signed-off-by: Jeffy Chen <jeffy.c...@rock-chips.com>

---

 drivers/gpu/drm/drm_ioc32.c | 3 +++
 1 file changed, 3 insertions(+)

diff --git a/drivers/gpu/drm/drm_ioc32.c b/drivers/gpu/drm/drm_ioc32.c
index 94acf51..2789356 100644
--- a/drivers/gpu/drm/drm_ioc32.c
+++ b/drivers/gpu/drm/drm_ioc32.c
@@ -112,6 +112,9 @@ static int compat_drm_version(struct file *file, unsigned 
int cmd,
v32.version_major = v.version_major;
v32.version_minor = v.version_minor;
v32.version_patchlevel = v.version_patchlevel;
+   v32.name_len = v.name_len;
+   v32.date_len = v.date_len;
+   v32.desc_len = v.desc_len;
if (copy_to_user((void __user *)arg, , sizeof(v32)))
return -EFAULT;
return 0;
-- 
2.1.4


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


Re: [PATCH v11] drm: Unplug drm device when unregistering it (v8)

2017-05-30 Thread jeffy

Hi Hans,

thanx for investigating :)

On 05/30/2017 03:06 PM, Hans de Goede wrote:

Hi,

On 29-05-17 22:25, Chris Wilson wrote:

On Fri, Apr 14, 2017 at 11:15:04AM -0400, Sean Paul wrote:

On Thu, Apr 13, 2017 at 03:32:44PM +0800, Jeffy Chen wrote:

After unbinding drm, the user space may still owns the drm dev fd, and
may still be able to call drm ioctl.

We're using an unplugged state to prevent something like that, so let's
reuse it here.

Also drop drm_unplug_dev, because it would be unused after other
changes.

Verified on rk3399 chromebook kevin(with cros 4.4 kernel), no more
crashes
when unbinding drm with ui service still running.

v2: Fix some commit messages.
v3: Reuse unplug status.
v4: Add drm_device_set_plug_state helper.
v5: Fix hang when unregistering drm dev with open_count 0.
v6: Move drm_device_set_plug_state into drm_drv.
v7: Add missing drm_dev_unref in udl_drv.
v8: Fix compiler errors after enable udl.

Signed-off-by: Jeffy Chen <jeffy.c...@rock-chips.com>

---


Hi Jeffy,
Given the trouble we've had with this patch already, coupled with the
fact that
unbinding while userspace is active is a contrived/pathological case,
I don't
think it's worth picking this patch upstream.

If it's really causing issues downstream, you can add my Reviewed-by
for a CHROMIUM
patch, but I'd rather not carry patches in the CrOS repo if we don't
need to.


Would a

Fixes: a39be606f99d ("drm: Do a full device unregister when unplugging")
Reported-by: Marco Diego Aurélio Mesquita <marcodiegomesqu...@gmail.com>
Cc: Hans de Goede <hdego...@redhat.com>

convince us to look into this patch again?


The problem is this patch is wrong, see below.


  drivers/gpu/drm/drm_drv.c | 26 ++
  drivers/gpu/drm/udl/udl_drv.c |  3 ++-
  include/drm/drmP.h|  6 --
  include/drm/drm_drv.h |  1 -
  4 files changed, 12 insertions(+), 24 deletions(-)

diff --git a/drivers/gpu/drm/drm_drv.c b/drivers/gpu/drm/drm_drv.c
index b5c6bb4..e1da4d1 100644
--- a/drivers/gpu/drm/drm_drv.c
+++ b/drivers/gpu/drm/drm_drv.c
@@ -355,22 +355,6 @@ void drm_put_dev(struct drm_device *dev)
  }
  EXPORT_SYMBOL(drm_put_dev);
-void drm_unplug_dev(struct drm_device *dev)
-{
-/* for a USB device */
-drm_dev_unregister(dev);
-
-mutex_lock(_global_mutex);
-
-drm_device_set_unplugged(dev);
-
-if (dev->open_count == 0) {
-drm_put_dev(dev);
-}
-mutex_unlock(_global_mutex);
-}
-EXPORT_SYMBOL(drm_unplug_dev);
-
  /*
   * DRM internal mount
   * We want to be able to allocate our own "struct address_space"
to control
@@ -733,6 +717,13 @@ static void remove_compat_control_link(struct
drm_device *dev)
  kfree(name);
  }
+static inline void drm_device_set_plug_state(struct drm_device *dev,
+ bool plugged)
+{
+smp_wmb();
+atomic_set(>unplugged, !plugged);
+}
+
  /**
   * drm_dev_register - Register DRM device
   * @dev: Device to register
@@ -787,6 +778,8 @@ int drm_dev_register(struct drm_device *dev,
unsigned long flags)
  if (drm_core_check_feature(dev, DRIVER_MODESET))
  drm_modeset_register_all(dev);
+drm_device_set_plug_state(dev, true);
+
  ret = 0;
  DRM_INFO("Initialized %s %d.%d.%d %s for %s on minor %d\n",
@@ -826,6 +819,7 @@ void drm_dev_unregister(struct drm_device *dev)
  drm_lastclose(dev);
  dev->registered = false;
+drm_device_set_plug_state(dev, false);
  if (drm_core_check_feature(dev, DRIVER_MODESET))
  drm_modeset_unregister_all(dev);
diff --git a/drivers/gpu/drm/udl/udl_drv.c
b/drivers/gpu/drm/udl/udl_drv.c
index cd8b017..fc73e24 100644
--- a/drivers/gpu/drm/udl/udl_drv.c
+++ b/drivers/gpu/drm/udl/udl_drv.c
@@ -108,7 +108,8 @@ static void udl_usb_disconnect(struct
usb_interface *interface)
  drm_kms_helper_poll_disable(dev);
  udl_fbdev_unplug(dev);
  udl_drop_usb(dev);
-drm_unplug_dev(dev);
+drm_dev_unregister(dev);
+drm_dev_unref(dev);


The unref here will cause the device struct to get free-ed even if
userspace still holds references to it through the drm_dev. To fix
this we would need to call drm_dev_ref on a open from userspace and
drm_dev_unref from drm_release.


right, but i think we are already did the ref/unref in the open/release 
through drm_minor_acquire/drm_minor_release.


i think the problem would be:
1/ we are trying to unregister when disconnected

2/ the drm_release would try to unregister(by calling drm_put_dev) 
when found it unplugged.


and your patch "drm: Do not call drm_dev_unregister twice on 
drm_unplug_dev" looks like a good way to fix this(to me), maybe we can 
place this patch after yours, and check for open_count here?


-drm_unplug_dev(dev);
+if (dev->open_count == 0)
+drm_dev_unref(dev);




Regards,

Hans





  }
  /*
diff --git a/include/drm/drmP.h b/include/drm/drmP.h
index 3bfafcd..980a204 100644
--- a/include/drm/drmP

Re: drm/rockchip: Correct vop out_mode configure

2017-05-30 Thread jeffy

Hi Mark,

Reviewed-by: Jeffy Chen <jeffy.c...@rock-chips.com>

On 05/27/2017 07:43 PM, yao mark wrote:

Force vop output mode on encoder driver seem not a good idea,

EDP, HDMI, DisplayPort all have 10bit input on rk3399,
On non-10bit vop, vop 8bit output bit[0-7] connect to the
encoder high 8bit [2-9].

So force RGB10 to RGB888 on vop driver would be better.

And another problem, EDP check crtc id on atomic_check,
but encoder maybe NULL, so out_mode configure would fail,
it cause edp no display.

Signed-off-by: Mark Yao <mark@rock-chips.com>
---
  drivers/gpu/drm/rockchip/analogix_dp-rockchip.c | 12 
  drivers/gpu/drm/rockchip/cdn-dp-core.c  |  9 ++---
  drivers/gpu/drm/rockchip/rockchip_drm_vop.c |  8 
  drivers/gpu/drm/rockchip/rockchip_drm_vop.h |  3 +++
  drivers/gpu/drm/rockchip/rockchip_vop_reg.c |  2 ++
  5 files changed, 15 insertions(+), 19 deletions(-)

diff --git a/drivers/gpu/drm/rockchip/analogix_dp-rockchip.c 
b/drivers/gpu/drm/rockchip/analogix_dp-rockchip.c
index 1bccd82..9606121 100644
--- a/drivers/gpu/drm/rockchip/analogix_dp-rockchip.c
+++ b/drivers/gpu/drm/rockchip/analogix_dp-rockchip.c
@@ -237,8 +237,6 @@ rockchip_dp_drm_encoder_atomic_check(struct drm_encoder 
*encoder,
  struct drm_connector_state *conn_state)
  {
struct rockchip_crtc_state *s = to_rockchip_crtc_state(crtc_state);
-   struct rockchip_dp_device *dp = to_dp(encoder);
-   int ret;

/*
 * The hardware IC designed that VOP must output the RGB10 video
@@ -250,16 +248,6 @@ rockchip_dp_drm_encoder_atomic_check(struct drm_encoder 
*encoder,

s->output_mode = ROCKCHIP_OUT_MODE_;
s->output_type = DRM_MODE_CONNECTOR_eDP;
-   if (dp->data->chip_type == RK3399_EDP) {
-   /*
-* For RK3399, VOP Lit must code the out mode to RGB888,
-* VOP Big must code the out mode to RGB10.
-*/
-   ret = drm_of_encoder_active_endpoint_id(dp->dev->of_node,
-   encoder);
-   if (ret > 0)
-   s->output_mode = ROCKCHIP_OUT_MODE_P888;
-   }

return 0;
  }
diff --git a/drivers/gpu/drm/rockchip/cdn-dp-core.c 
b/drivers/gpu/drm/rockchip/cdn-dp-core.c
index a2169dd..14fa1f8 100644
--- a/drivers/gpu/drm/rockchip/cdn-dp-core.c
+++ b/drivers/gpu/drm/rockchip/cdn-dp-core.c
@@ -615,7 +615,6 @@ static void cdn_dp_encoder_enable(struct drm_encoder 
*encoder)
  {
struct cdn_dp_device *dp = encoder_to_dp(encoder);
int ret, val;
-   struct rockchip_crtc_state *state;

ret = drm_of_encoder_active_endpoint_id(dp->dev->of_node, encoder);
if (ret < 0) {
@@ -625,14 +624,10 @@ static void cdn_dp_encoder_enable(struct drm_encoder 
*encoder)

DRM_DEV_DEBUG_KMS(dp->dev, "vop %s output to cdn-dp\n",
  (ret) ? "LIT" : "BIG");
-   state = to_rockchip_crtc_state(encoder->crtc->state);
-   if (ret) {
+   if (ret)
val = DP_SEL_VOP_LIT | (DP_SEL_VOP_LIT << 16);
-   state->output_mode = ROCKCHIP_OUT_MODE_P888;
-   } else {
+   else
val = DP_SEL_VOP_LIT << 16;
-   state->output_mode = ROCKCHIP_OUT_MODE_;
-   }

ret = cdn_dp_grf_write(dp, GRF_SOC_CON9, val);
if (ret)
diff --git a/drivers/gpu/drm/rockchip/rockchip_drm_vop.c 
b/drivers/gpu/drm/rockchip/rockchip_drm_vop.c
index 40a5e6e..c83f481 100644
--- a/drivers/gpu/drm/rockchip/rockchip_drm_vop.c
+++ b/drivers/gpu/drm/rockchip/rockchip_drm_vop.c
@@ -874,6 +874,7 @@ static bool vop_crtc_mode_fixup(struct drm_crtc *crtc,
  static void vop_crtc_enable(struct drm_crtc *crtc)
  {
struct vop *vop = to_vop(crtc);
+   const struct vop_data *vop_data = vop->data;
struct rockchip_crtc_state *s = to_rockchip_crtc_state(crtc->state);
struct drm_display_mode *adjusted_mode = >state->adjusted_mode;
u16 hsync_len = adjusted_mode->hsync_end - adjusted_mode->hsync_start;
@@ -966,6 +967,13 @@ static void vop_crtc_enable(struct drm_crtc *crtc)
DRM_DEV_ERROR(vop->dev, "unsupported connector_type [%d]\n",
  s->output_type);
}
+
+   /*
+* if vop is not support RGB10 output, need force RGB10 to RGB888.
+*/
+   if (s->output_mode == ROCKCHIP_OUT_MODE_ &&
+   !(vop_data->feature & VOP_FEATURE_OUTPUT_RGB10))
+   s->output_mode = ROCKCHIP_OUT_MODE_P888;
VOP_CTRL_SET(vop, out_mode, s->output_mode);

VOP_CTRL_SET(vop, htotal_pw, (htotal << 16) | hsync_len);
diff --git a/drivers/gpu/drm/rockchip/rockchip_drm_vop.h 
b/drivers/gpu/drm/rockchip/rockchip_drm_vop.h
index 5a4faa85..

Re: [PATCH] drm/rockchip: Don't allow zero sized gem buffer

2017-05-25 Thread jeffy

Hi sean,

On 05/25/2017 11:30 PM, Sean Paul wrote:

On Tue, May 23, 2017 at 02:39:43PM +0800, Jeffy Chen wrote:

The system would crash when trying to alloc zero sized gem buffer:
[6.712435] Unable to handle kernel NULL pointer dereference at virtual address 
0010 <--ZERO_SIZE_PTR
...
[6.757502] PC is at sg_alloc_table_from_pages+0x170/0x1ec


It's unfortunate that you didn't include the entire stack trace. From code
inspection, it seems like the 0 size comes from the fb_probe path? Is there
somewhere in the helpers that you could check the mode is sane so all drivers
can benefit?


hmm, sorry, i was testing it on chromeos 4.4 kernel, it turns out that 
we have a custom ioctl for userspace to create gem buffer(the same as 
exynos drm), which might get the the 0 size.


but on upstream kernel, it could only be called by dump_create, and the 
drm_mode_create_dumb_ioctl already did the size check.


will resent this patch, and rewrite the commit message, thanx.



Sean



Signed-off-by: Jeffy Chen <jeffy.c...@rock-chips.com>
---

  drivers/gpu/drm/rockchip/rockchip_drm_gem.c | 5 +
  1 file changed, 5 insertions(+)

diff --git a/drivers/gpu/drm/rockchip/rockchip_drm_gem.c 
b/drivers/gpu/drm/rockchip/rockchip_drm_gem.c
index df9e570..8917922 100644
--- a/drivers/gpu/drm/rockchip/rockchip_drm_gem.c
+++ b/drivers/gpu/drm/rockchip/rockchip_drm_gem.c
@@ -315,6 +315,11 @@ struct rockchip_gem_object *
struct drm_gem_object *obj;
int ret;

+   if (!size) {
+   DRM_ERROR("gem buffer size is zero\n");
+   return ERR_PTR(-EINVAL);
+   }
+
size = round_up(size, PAGE_SIZE);

rk_obj = kzalloc(sizeof(*rk_obj), GFP_KERNEL);
--
2.1.4






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


[PATCH] drm/rockchip: Don't allow zero sized gem buffer

2017-05-23 Thread Jeffy Chen
The system would crash when trying to alloc zero sized gem buffer:
[6.712435] Unable to handle kernel NULL pointer dereference at virtual 
address 0010 <--ZERO_SIZE_PTR
...
[6.757502] PC is at sg_alloc_table_from_pages+0x170/0x1ec

Signed-off-by: Jeffy Chen <jeffy.c...@rock-chips.com>
---

 drivers/gpu/drm/rockchip/rockchip_drm_gem.c | 5 +
 1 file changed, 5 insertions(+)

diff --git a/drivers/gpu/drm/rockchip/rockchip_drm_gem.c 
b/drivers/gpu/drm/rockchip/rockchip_drm_gem.c
index df9e570..8917922 100644
--- a/drivers/gpu/drm/rockchip/rockchip_drm_gem.c
+++ b/drivers/gpu/drm/rockchip/rockchip_drm_gem.c
@@ -315,6 +315,11 @@ struct rockchip_gem_object *
struct drm_gem_object *obj;
int ret;
 
+   if (!size) {
+   DRM_ERROR("gem buffer size is zero\n");
+   return ERR_PTR(-EINVAL);
+   }
+
size = round_up(size, PAGE_SIZE);
 
rk_obj = kzalloc(sizeof(*rk_obj), GFP_KERNEL);
-- 
2.1.4


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


Re: [PATCH v2] drm/rockchip: Set line flag config register in vop_crtc_enable

2017-04-29 Thread jeffy

Hi Sean,

On 04/28/2017 11:03 PM, Sean Paul wrote:

On Fri, Apr 28, 2017 at 03:37:47PM +0800, Jeffy Chen wrote:

We need to set vop config done after update line flag config, it's a
new requirement for chips newer than rk3368.

Since we would only use line flag irq for vact_end, let's move it to
vop_crtc_enable.

v2: Remove unused check and variables.


Hi Jeffy,
v1 was already applied. Please send a follow-on patch to clean this up.

Ok, will do.


Sean



Signed-off-by: Jeffy Chen <jeffy.c...@rock-chips.com>

---

Changes in v2:
Remove unused check and variables.

  drivers/gpu/drm/rockchip/analogix_dp-rockchip.c | 14 +++---
  drivers/gpu/drm/rockchip/rockchip_drm_drv.h |  3 +--
  drivers/gpu/drm/rockchip/rockchip_drm_vop.c | 20 +---
  3 files changed, 13 insertions(+), 24 deletions(-)

diff --git a/drivers/gpu/drm/rockchip/analogix_dp-rockchip.c 
b/drivers/gpu/drm/rockchip/analogix_dp-rockchip.c
index d8fa7a9..1bccd82 100644
--- a/drivers/gpu/drm/rockchip/analogix_dp-rockchip.c
+++ b/drivers/gpu/drm/rockchip/analogix_dp-rockchip.c
@@ -104,26 +104,18 @@ static void analogix_dp_psr_work(struct work_struct *work)
  {
struct rockchip_dp_device *dp =
container_of(work, typeof(*dp), psr_work);
-   struct drm_crtc *crtc = dp->encoder.crtc;
-   int psr_state = dp->psr_state;
-   int vact_end;
int ret;
unsigned long flags;

-   if (!crtc)
-   return;
-
-   vact_end = crtc->mode.vtotal - crtc->mode.vsync_start + 
crtc->mode.vdisplay;
-
-   ret = rockchip_drm_wait_line_flag(dp->encoder.crtc, vact_end,
- PSR_WAIT_LINE_FLAG_TIMEOUT_MS);
+   ret = rockchip_drm_wait_vact_end(dp->encoder.crtc,
+PSR_WAIT_LINE_FLAG_TIMEOUT_MS);
if (ret) {
dev_err(dp->dev, "line flag interrupt did not arrive\n");
return;
}

spin_lock_irqsave(>psr_lock, flags);
-   if (psr_state == EDP_VSC_PSR_STATE_ACTIVE)
+   if (dp->psr_state == EDP_VSC_PSR_STATE_ACTIVE)
analogix_dp_enable_psr(dp->dev);
else
analogix_dp_disable_psr(dp->dev);
diff --git a/drivers/gpu/drm/rockchip/rockchip_drm_drv.h 
b/drivers/gpu/drm/rockchip/rockchip_drm_drv.h
index a48fcce..47905fa 100644
--- a/drivers/gpu/drm/rockchip/rockchip_drm_drv.h
+++ b/drivers/gpu/drm/rockchip/rockchip_drm_drv.h
@@ -62,8 +62,7 @@ int rockchip_drm_dma_attach_device(struct drm_device *drm_dev,
   struct device *dev);
  void rockchip_drm_dma_detach_device(struct drm_device *drm_dev,
struct device *dev);
-int rockchip_drm_wait_line_flag(struct drm_crtc *crtc, unsigned int line_num,
-   unsigned int mstimeout);
+int rockchip_drm_wait_vact_end(struct drm_crtc *crtc, unsigned int mstimeout);

  extern struct platform_driver cdn_dp_driver;
  extern struct platform_driver dw_hdmi_rockchip_pltfm_driver;
diff --git a/drivers/gpu/drm/rockchip/rockchip_drm_vop.c 
b/drivers/gpu/drm/rockchip/rockchip_drm_vop.c
index 3f7a82d..40a5e6e 100644
--- a/drivers/gpu/drm/rockchip/rockchip_drm_vop.c
+++ b/drivers/gpu/drm/rockchip/rockchip_drm_vop.c
@@ -468,7 +468,7 @@ static bool vop_line_flag_irq_is_enabled(struct vop *vop)
return !!line_flag_irq;
  }

-static void vop_line_flag_irq_enable(struct vop *vop, int line_num)
+static void vop_line_flag_irq_enable(struct vop *vop)
  {
unsigned long flags;

@@ -477,7 +477,6 @@ static void vop_line_flag_irq_enable(struct vop *vop, int 
line_num)

spin_lock_irqsave(>irq_lock, flags);

-   VOP_CTRL_SET(vop, line_flag_num[0], line_num);
VOP_INTR_SET_TYPE(vop, clear, LINE_FLAG_INTR, 1);
VOP_INTR_SET_TYPE(vop, enable, LINE_FLAG_INTR, 1);

@@ -981,6 +980,8 @@ static void vop_crtc_enable(struct drm_crtc *crtc)
VOP_CTRL_SET(vop, vact_st_end, val);
VOP_CTRL_SET(vop, vpost_st_end, val);

+   VOP_CTRL_SET(vop, line_flag_num[0], vact_end);
+
clk_set_rate(vop->dclk, adjusted_mode->clock * 1000);

VOP_CTRL_SET(vop, standby, 0);
@@ -1507,19 +1508,16 @@ static void vop_win_init(struct vop *vop)
  }

  /**
- * rockchip_drm_wait_line_flag - acqiure the give line flag event
+ * rockchip_drm_wait_vact_end
   * @crtc: CRTC to enable line flag
- * @line_num: interested line number
   * @mstimeout: millisecond for timeout
   *
- * Driver would hold here until the interested line flag interrupt have
- * happened or timeout to wait.
+ * Wait for vact_end line flag irq or timeout.
   *
   * Returns:
   * Zero on success, negative errno on failure.
   */
-int rockchip_drm_wait_line_flag(struct drm_crtc *crtc, unsigned int line_num,
-   unsigned int mstimeout)
+int rockchip_drm_wait_vact_end(struct drm_crtc *crtc, unsigned int mstimeout)

[PATCH] drm/rockchip: analogix_dp: Remove unused check and variables

2017-04-29 Thread Jeffy Chen
Remove unused check and variables after:
drm/rockchip: Set line flag config register in vop_crtc_enable

Signed-off-by: Jeffy Chen <jeffy.c...@rock-chips.com>

---

 drivers/gpu/drm/rockchip/analogix_dp-rockchip.c | 10 +-
 1 file changed, 1 insertion(+), 9 deletions(-)

diff --git a/drivers/gpu/drm/rockchip/analogix_dp-rockchip.c 
b/drivers/gpu/drm/rockchip/analogix_dp-rockchip.c
index 9bfdbc6..1bccd82 100644
--- a/drivers/gpu/drm/rockchip/analogix_dp-rockchip.c
+++ b/drivers/gpu/drm/rockchip/analogix_dp-rockchip.c
@@ -104,17 +104,9 @@ static void analogix_dp_psr_work(struct work_struct *work)
 {
struct rockchip_dp_device *dp =
container_of(work, typeof(*dp), psr_work);
-   struct drm_crtc *crtc = dp->encoder.crtc;
-   int psr_state = dp->psr_state;
-   int vact_end;
int ret;
unsigned long flags;
 
-   if (!crtc)
-   return;
-
-   vact_end = crtc->mode.vtotal - crtc->mode.vsync_start + 
crtc->mode.vdisplay;
-
ret = rockchip_drm_wait_vact_end(dp->encoder.crtc,
 PSR_WAIT_LINE_FLAG_TIMEOUT_MS);
if (ret) {
@@ -123,7 +115,7 @@ static void analogix_dp_psr_work(struct work_struct *work)
}
 
spin_lock_irqsave(>psr_lock, flags);
-   if (psr_state == EDP_VSC_PSR_STATE_ACTIVE)
+   if (dp->psr_state == EDP_VSC_PSR_STATE_ACTIVE)
analogix_dp_enable_psr(dp->dev);
else
analogix_dp_disable_psr(dp->dev);
-- 
2.1.4


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


[PATCH v2] drm/rockchip: Set line flag config register in vop_crtc_enable

2017-04-28 Thread Jeffy Chen
We need to set vop config done after update line flag config, it's a
new requirement for chips newer than rk3368.

Since we would only use line flag irq for vact_end, let's move it to
vop_crtc_enable.

v2: Remove unused check and variables.

Signed-off-by: Jeffy Chen <jeffy.c...@rock-chips.com>

---

Changes in v2:
Remove unused check and variables.

 drivers/gpu/drm/rockchip/analogix_dp-rockchip.c | 14 +++---
 drivers/gpu/drm/rockchip/rockchip_drm_drv.h |  3 +--
 drivers/gpu/drm/rockchip/rockchip_drm_vop.c | 20 +---
 3 files changed, 13 insertions(+), 24 deletions(-)

diff --git a/drivers/gpu/drm/rockchip/analogix_dp-rockchip.c 
b/drivers/gpu/drm/rockchip/analogix_dp-rockchip.c
index d8fa7a9..1bccd82 100644
--- a/drivers/gpu/drm/rockchip/analogix_dp-rockchip.c
+++ b/drivers/gpu/drm/rockchip/analogix_dp-rockchip.c
@@ -104,26 +104,18 @@ static void analogix_dp_psr_work(struct work_struct *work)
 {
struct rockchip_dp_device *dp =
container_of(work, typeof(*dp), psr_work);
-   struct drm_crtc *crtc = dp->encoder.crtc;
-   int psr_state = dp->psr_state;
-   int vact_end;
int ret;
unsigned long flags;
 
-   if (!crtc)
-   return;
-
-   vact_end = crtc->mode.vtotal - crtc->mode.vsync_start + 
crtc->mode.vdisplay;
-
-   ret = rockchip_drm_wait_line_flag(dp->encoder.crtc, vact_end,
- PSR_WAIT_LINE_FLAG_TIMEOUT_MS);
+   ret = rockchip_drm_wait_vact_end(dp->encoder.crtc,
+PSR_WAIT_LINE_FLAG_TIMEOUT_MS);
if (ret) {
dev_err(dp->dev, "line flag interrupt did not arrive\n");
return;
}
 
spin_lock_irqsave(>psr_lock, flags);
-   if (psr_state == EDP_VSC_PSR_STATE_ACTIVE)
+   if (dp->psr_state == EDP_VSC_PSR_STATE_ACTIVE)
analogix_dp_enable_psr(dp->dev);
else
analogix_dp_disable_psr(dp->dev);
diff --git a/drivers/gpu/drm/rockchip/rockchip_drm_drv.h 
b/drivers/gpu/drm/rockchip/rockchip_drm_drv.h
index a48fcce..47905fa 100644
--- a/drivers/gpu/drm/rockchip/rockchip_drm_drv.h
+++ b/drivers/gpu/drm/rockchip/rockchip_drm_drv.h
@@ -62,8 +62,7 @@ int rockchip_drm_dma_attach_device(struct drm_device *drm_dev,
   struct device *dev);
 void rockchip_drm_dma_detach_device(struct drm_device *drm_dev,
struct device *dev);
-int rockchip_drm_wait_line_flag(struct drm_crtc *crtc, unsigned int line_num,
-   unsigned int mstimeout);
+int rockchip_drm_wait_vact_end(struct drm_crtc *crtc, unsigned int mstimeout);
 
 extern struct platform_driver cdn_dp_driver;
 extern struct platform_driver dw_hdmi_rockchip_pltfm_driver;
diff --git a/drivers/gpu/drm/rockchip/rockchip_drm_vop.c 
b/drivers/gpu/drm/rockchip/rockchip_drm_vop.c
index 3f7a82d..40a5e6e 100644
--- a/drivers/gpu/drm/rockchip/rockchip_drm_vop.c
+++ b/drivers/gpu/drm/rockchip/rockchip_drm_vop.c
@@ -468,7 +468,7 @@ static bool vop_line_flag_irq_is_enabled(struct vop *vop)
return !!line_flag_irq;
 }
 
-static void vop_line_flag_irq_enable(struct vop *vop, int line_num)
+static void vop_line_flag_irq_enable(struct vop *vop)
 {
unsigned long flags;
 
@@ -477,7 +477,6 @@ static void vop_line_flag_irq_enable(struct vop *vop, int 
line_num)
 
spin_lock_irqsave(>irq_lock, flags);
 
-   VOP_CTRL_SET(vop, line_flag_num[0], line_num);
VOP_INTR_SET_TYPE(vop, clear, LINE_FLAG_INTR, 1);
VOP_INTR_SET_TYPE(vop, enable, LINE_FLAG_INTR, 1);
 
@@ -981,6 +980,8 @@ static void vop_crtc_enable(struct drm_crtc *crtc)
VOP_CTRL_SET(vop, vact_st_end, val);
VOP_CTRL_SET(vop, vpost_st_end, val);
 
+   VOP_CTRL_SET(vop, line_flag_num[0], vact_end);
+
clk_set_rate(vop->dclk, adjusted_mode->clock * 1000);
 
VOP_CTRL_SET(vop, standby, 0);
@@ -1507,19 +1508,16 @@ static void vop_win_init(struct vop *vop)
 }
 
 /**
- * rockchip_drm_wait_line_flag - acqiure the give line flag event
+ * rockchip_drm_wait_vact_end
  * @crtc: CRTC to enable line flag
- * @line_num: interested line number
  * @mstimeout: millisecond for timeout
  *
- * Driver would hold here until the interested line flag interrupt have
- * happened or timeout to wait.
+ * Wait for vact_end line flag irq or timeout.
  *
  * Returns:
  * Zero on success, negative errno on failure.
  */
-int rockchip_drm_wait_line_flag(struct drm_crtc *crtc, unsigned int line_num,
-   unsigned int mstimeout)
+int rockchip_drm_wait_vact_end(struct drm_crtc *crtc, unsigned int mstimeout)
 {
struct vop *vop = to_vop(crtc);
unsigned long jiffies_left;
@@ -1527,14 +1525,14 @@ int rockchip_drm_wait_line_flag(struct drm_crtc *crtc, 
unsigned int line_num,
if (!crtc || !vop->is_enable

[PATCH] drm/rockchip: Set line flag config register in vop_crtc_enable

2017-04-27 Thread Jeffy Chen
We need to set vop config done after update line flag config, it's a
new requirement for chips newer than rk3368.

Since we would only use line flag irq for vact_end, let's move it to
vop_crtc_enable.

Signed-off-by: Jeffy Chen <jeffy.c...@rock-chips.com>

---

 drivers/gpu/drm/rockchip/analogix_dp-rockchip.c |  4 ++--
 drivers/gpu/drm/rockchip/rockchip_drm_drv.h |  3 +--
 drivers/gpu/drm/rockchip/rockchip_drm_vop.c | 20 +---
 3 files changed, 12 insertions(+), 15 deletions(-)

diff --git a/drivers/gpu/drm/rockchip/analogix_dp-rockchip.c 
b/drivers/gpu/drm/rockchip/analogix_dp-rockchip.c
index d8fa7a9..9bfdbc6 100644
--- a/drivers/gpu/drm/rockchip/analogix_dp-rockchip.c
+++ b/drivers/gpu/drm/rockchip/analogix_dp-rockchip.c
@@ -115,8 +115,8 @@ static void analogix_dp_psr_work(struct work_struct *work)
 
vact_end = crtc->mode.vtotal - crtc->mode.vsync_start + 
crtc->mode.vdisplay;
 
-   ret = rockchip_drm_wait_line_flag(dp->encoder.crtc, vact_end,
- PSR_WAIT_LINE_FLAG_TIMEOUT_MS);
+   ret = rockchip_drm_wait_vact_end(dp->encoder.crtc,
+PSR_WAIT_LINE_FLAG_TIMEOUT_MS);
if (ret) {
dev_err(dp->dev, "line flag interrupt did not arrive\n");
return;
diff --git a/drivers/gpu/drm/rockchip/rockchip_drm_drv.h 
b/drivers/gpu/drm/rockchip/rockchip_drm_drv.h
index a48fcce..47905fa 100644
--- a/drivers/gpu/drm/rockchip/rockchip_drm_drv.h
+++ b/drivers/gpu/drm/rockchip/rockchip_drm_drv.h
@@ -62,8 +62,7 @@ int rockchip_drm_dma_attach_device(struct drm_device *drm_dev,
   struct device *dev);
 void rockchip_drm_dma_detach_device(struct drm_device *drm_dev,
struct device *dev);
-int rockchip_drm_wait_line_flag(struct drm_crtc *crtc, unsigned int line_num,
-   unsigned int mstimeout);
+int rockchip_drm_wait_vact_end(struct drm_crtc *crtc, unsigned int mstimeout);
 
 extern struct platform_driver cdn_dp_driver;
 extern struct platform_driver dw_hdmi_rockchip_pltfm_driver;
diff --git a/drivers/gpu/drm/rockchip/rockchip_drm_vop.c 
b/drivers/gpu/drm/rockchip/rockchip_drm_vop.c
index 3f7a82d..40a5e6e 100644
--- a/drivers/gpu/drm/rockchip/rockchip_drm_vop.c
+++ b/drivers/gpu/drm/rockchip/rockchip_drm_vop.c
@@ -468,7 +468,7 @@ static bool vop_line_flag_irq_is_enabled(struct vop *vop)
return !!line_flag_irq;
 }
 
-static void vop_line_flag_irq_enable(struct vop *vop, int line_num)
+static void vop_line_flag_irq_enable(struct vop *vop)
 {
unsigned long flags;
 
@@ -477,7 +477,6 @@ static void vop_line_flag_irq_enable(struct vop *vop, int 
line_num)
 
spin_lock_irqsave(>irq_lock, flags);
 
-   VOP_CTRL_SET(vop, line_flag_num[0], line_num);
VOP_INTR_SET_TYPE(vop, clear, LINE_FLAG_INTR, 1);
VOP_INTR_SET_TYPE(vop, enable, LINE_FLAG_INTR, 1);
 
@@ -981,6 +980,8 @@ static void vop_crtc_enable(struct drm_crtc *crtc)
VOP_CTRL_SET(vop, vact_st_end, val);
VOP_CTRL_SET(vop, vpost_st_end, val);
 
+   VOP_CTRL_SET(vop, line_flag_num[0], vact_end);
+
clk_set_rate(vop->dclk, adjusted_mode->clock * 1000);
 
VOP_CTRL_SET(vop, standby, 0);
@@ -1507,19 +1508,16 @@ static void vop_win_init(struct vop *vop)
 }
 
 /**
- * rockchip_drm_wait_line_flag - acqiure the give line flag event
+ * rockchip_drm_wait_vact_end
  * @crtc: CRTC to enable line flag
- * @line_num: interested line number
  * @mstimeout: millisecond for timeout
  *
- * Driver would hold here until the interested line flag interrupt have
- * happened or timeout to wait.
+ * Wait for vact_end line flag irq or timeout.
  *
  * Returns:
  * Zero on success, negative errno on failure.
  */
-int rockchip_drm_wait_line_flag(struct drm_crtc *crtc, unsigned int line_num,
-   unsigned int mstimeout)
+int rockchip_drm_wait_vact_end(struct drm_crtc *crtc, unsigned int mstimeout)
 {
struct vop *vop = to_vop(crtc);
unsigned long jiffies_left;
@@ -1527,14 +1525,14 @@ int rockchip_drm_wait_line_flag(struct drm_crtc *crtc, 
unsigned int line_num,
if (!crtc || !vop->is_enabled)
return -ENODEV;
 
-   if (line_num > crtc->mode.vtotal || mstimeout <= 0)
+   if (mstimeout <= 0)
return -EINVAL;
 
if (vop_line_flag_irq_is_enabled(vop))
return -EBUSY;
 
reinit_completion(>line_flag_completion);
-   vop_line_flag_irq_enable(vop, line_num);
+   vop_line_flag_irq_enable(vop);
 
jiffies_left = wait_for_completion_timeout(>line_flag_completion,
   msecs_to_jiffies(mstimeout));
@@ -1547,7 +1545,7 @@ int rockchip_drm_wait_line_flag(struct drm_crtc *crtc, 
unsigned int line_num,
 
return 0;
 }
-EXPORT_SYMBOL(rockchip_drm_wait_line_flag);
+E

Re: [PATCH v9] drm: Unplug drm device when unregistering it

2017-04-13 Thread jeffy

Hi Sean,

On 04/12/2017 11:03 PM, Sean Paul wrote:

On Wed, Apr 12, 2017 at 04:56:21PM +0800, Jeffy Chen wrote:

After unbinding drm, the user space may still owns the drm dev fd, and
may still be able to call drm ioctl.

We're using an unplugged state to prevent something like that, so let's
reuse it here.

Also drop drm_unplug_dev, because it would be unused after other changes.

Signed-off-by: Jeffy Chen <jeffy.c...@rock-chips.com>

Changes in v9:
Move drm_device_set_plug_state into drm_drv.c .

Changes in v8:
Fix hang when unregistering drm dev with open_count 0.

Changes in v7:
Add drm_device_set_plug_state helper.

Changes in v6:
Reuse unplug status.

Changes in v5:
Fix wrong git account.

Changes in v2:
Fix some commit messages.



Hi Jeffy,
A couple bookkeeping notes:

- Please end the commit message with your Signed-off-by tag
- No need to send cover letters for one patch. All info should be in the commit
   message. Include superfluous information (such as tested on 4.4 kernel) after
   ---
hmm...i'm using u-boot's patman tool to send patches. and the changelogs 
would be formated by the tool.


i'll switch changelogs to drm style.



---
  drivers/gpu/drm/drm_drv.c | 26 ++
  drivers/gpu/drm/udl/udl_drv.c |  2 +-
  include/drm/drmP.h|  6 --
  include/drm/drm_drv.h |  1 -
  4 files changed, 11 insertions(+), 24 deletions(-)

diff --git a/drivers/gpu/drm/drm_drv.c b/drivers/gpu/drm/drm_drv.c
index b5c6bb4..e1da4d1 100644
--- a/drivers/gpu/drm/drm_drv.c
+++ b/drivers/gpu/drm/drm_drv.c
@@ -355,22 +355,6 @@ void drm_put_dev(struct drm_device *dev)
  }
  EXPORT_SYMBOL(drm_put_dev);

-void drm_unplug_dev(struct drm_device *dev)
-{
-   /* for a USB device */
-   drm_dev_unregister(dev);
-
-   mutex_lock(_global_mutex);
-
-   drm_device_set_unplugged(dev);
-
-   if (dev->open_count == 0) {
-   drm_put_dev(dev);
-   }
-   mutex_unlock(_global_mutex);
-}
-EXPORT_SYMBOL(drm_unplug_dev);
-
  /*
   * DRM internal mount
   * We want to be able to allocate our own "struct address_space" to control
@@ -733,6 +717,13 @@ static void remove_compat_control_link(struct drm_device 
*dev)
kfree(name);
  }

+static inline void drm_device_set_plug_state(struct drm_device *dev,
+bool plugged)
+{
+   smp_wmb();
+   atomic_set(>unplugged, !plugged);
+}
+
  /**
   * drm_dev_register - Register DRM device
   * @dev: Device to register
@@ -787,6 +778,8 @@ int drm_dev_register(struct drm_device *dev, unsigned long 
flags)
if (drm_core_check_feature(dev, DRIVER_MODESET))
drm_modeset_register_all(dev);

+   drm_device_set_plug_state(dev, true);
+
ret = 0;

DRM_INFO("Initialized %s %d.%d.%d %s for %s on minor %d\n",
@@ -826,6 +819,7 @@ void drm_dev_unregister(struct drm_device *dev)
drm_lastclose(dev);

dev->registered = false;
+   drm_device_set_plug_state(dev, false);

if (drm_core_check_feature(dev, DRIVER_MODESET))
drm_modeset_unregister_all(dev);
diff --git a/drivers/gpu/drm/udl/udl_drv.c b/drivers/gpu/drm/udl/udl_drv.c
index cd8b017..5dbd916 100644
--- a/drivers/gpu/drm/udl/udl_drv.c
+++ b/drivers/gpu/drm/udl/udl_drv.c
@@ -108,7 +108,7 @@ static void udl_usb_disconnect(struct usb_interface 
*interface)
drm_kms_helper_poll_disable(dev);
udl_fbdev_unplug(dev);
udl_drop_usb(dev);
-   drm_unplug_dev(dev);
+   drm_dev_unregister(dev);


I think you need drm_dev_unref here as well.

right, will do.


Sean


  }

  /*
diff --git a/include/drm/drmP.h b/include/drm/drmP.h
index 3bfafcd..980a204 100644
--- a/include/drm/drmP.h
+++ b/include/drm/drmP.h
@@ -488,12 +488,6 @@ static __inline__ int drm_core_check_feature(struct 
drm_device *dev,
return ((dev->driver->driver_features & feature) ? 1 : 0);
  }

-static inline void drm_device_set_unplugged(struct drm_device *dev)
-{
-   smp_wmb();
-   atomic_set(>unplugged, 1);
-}
-
  static inline int drm_device_is_unplugged(struct drm_device *dev)
  {
int ret = atomic_read(>unplugged);
diff --git a/include/drm/drm_drv.h b/include/drm/drm_drv.h
index 0fefc3f..eb63078 100644
--- a/include/drm/drm_drv.h
+++ b/include/drm/drm_drv.h
@@ -544,7 +544,6 @@ void drm_dev_unregister(struct drm_device *dev);
  void drm_dev_ref(struct drm_device *dev);
  void drm_dev_unref(struct drm_device *dev);
  void drm_put_dev(struct drm_device *dev);
-void drm_unplug_dev(struct drm_device *dev);

  int drm_dev_set_unique(struct drm_device *dev, const char *name);

--
2.1.4






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


[PATCH v11] drm: Unplug drm device when unregistering it (v8)

2017-04-13 Thread Jeffy Chen
After unbinding drm, the user space may still owns the drm dev fd, and
may still be able to call drm ioctl.

We're using an unplugged state to prevent something like that, so let's
reuse it here.

Also drop drm_unplug_dev, because it would be unused after other changes.

Verified on rk3399 chromebook kevin(with cros 4.4 kernel), no more crashes
when unbinding drm with ui service still running.

v2: Fix some commit messages.
v3: Reuse unplug status.
v4: Add drm_device_set_plug_state helper.
v5: Fix hang when unregistering drm dev with open_count 0.
v6: Move drm_device_set_plug_state into drm_drv.
v7: Add missing drm_dev_unref in udl_drv.
v8: Fix compiler errors after enable udl.

Signed-off-by: Jeffy Chen <jeffy.c...@rock-chips.com>

---

 drivers/gpu/drm/drm_drv.c | 26 ++
 drivers/gpu/drm/udl/udl_drv.c |  3 ++-
 include/drm/drmP.h|  6 --
 include/drm/drm_drv.h |  1 -
 4 files changed, 12 insertions(+), 24 deletions(-)

diff --git a/drivers/gpu/drm/drm_drv.c b/drivers/gpu/drm/drm_drv.c
index b5c6bb4..e1da4d1 100644
--- a/drivers/gpu/drm/drm_drv.c
+++ b/drivers/gpu/drm/drm_drv.c
@@ -355,22 +355,6 @@ void drm_put_dev(struct drm_device *dev)
 }
 EXPORT_SYMBOL(drm_put_dev);
 
-void drm_unplug_dev(struct drm_device *dev)
-{
-   /* for a USB device */
-   drm_dev_unregister(dev);
-
-   mutex_lock(_global_mutex);
-
-   drm_device_set_unplugged(dev);
-
-   if (dev->open_count == 0) {
-   drm_put_dev(dev);
-   }
-   mutex_unlock(_global_mutex);
-}
-EXPORT_SYMBOL(drm_unplug_dev);
-
 /*
  * DRM internal mount
  * We want to be able to allocate our own "struct address_space" to control
@@ -733,6 +717,13 @@ static void remove_compat_control_link(struct drm_device 
*dev)
kfree(name);
 }
 
+static inline void drm_device_set_plug_state(struct drm_device *dev,
+bool plugged)
+{
+   smp_wmb();
+   atomic_set(>unplugged, !plugged);
+}
+
 /**
  * drm_dev_register - Register DRM device
  * @dev: Device to register
@@ -787,6 +778,8 @@ int drm_dev_register(struct drm_device *dev, unsigned long 
flags)
if (drm_core_check_feature(dev, DRIVER_MODESET))
drm_modeset_register_all(dev);
 
+   drm_device_set_plug_state(dev, true);
+
ret = 0;
 
DRM_INFO("Initialized %s %d.%d.%d %s for %s on minor %d\n",
@@ -826,6 +819,7 @@ void drm_dev_unregister(struct drm_device *dev)
drm_lastclose(dev);
 
dev->registered = false;
+   drm_device_set_plug_state(dev, false);
 
if (drm_core_check_feature(dev, DRIVER_MODESET))
drm_modeset_unregister_all(dev);
diff --git a/drivers/gpu/drm/udl/udl_drv.c b/drivers/gpu/drm/udl/udl_drv.c
index cd8b017..fc73e24 100644
--- a/drivers/gpu/drm/udl/udl_drv.c
+++ b/drivers/gpu/drm/udl/udl_drv.c
@@ -108,7 +108,8 @@ static void udl_usb_disconnect(struct usb_interface 
*interface)
drm_kms_helper_poll_disable(dev);
udl_fbdev_unplug(dev);
udl_drop_usb(dev);
-   drm_unplug_dev(dev);
+   drm_dev_unregister(dev);
+   drm_dev_unref(dev);
 }
 
 /*
diff --git a/include/drm/drmP.h b/include/drm/drmP.h
index 3bfafcd..980a204 100644
--- a/include/drm/drmP.h
+++ b/include/drm/drmP.h
@@ -488,12 +488,6 @@ static __inline__ int drm_core_check_feature(struct 
drm_device *dev,
return ((dev->driver->driver_features & feature) ? 1 : 0);
 }
 
-static inline void drm_device_set_unplugged(struct drm_device *dev)
-{
-   smp_wmb();
-   atomic_set(>unplugged, 1);
-}
-
 static inline int drm_device_is_unplugged(struct drm_device *dev)
 {
int ret = atomic_read(>unplugged);
diff --git a/include/drm/drm_drv.h b/include/drm/drm_drv.h
index 0fefc3f..eb63078 100644
--- a/include/drm/drm_drv.h
+++ b/include/drm/drm_drv.h
@@ -544,7 +544,6 @@ void drm_dev_unregister(struct drm_device *dev);
 void drm_dev_ref(struct drm_device *dev);
 void drm_dev_unref(struct drm_device *dev);
 void drm_put_dev(struct drm_device *dev);
-void drm_unplug_dev(struct drm_device *dev);
 
 int drm_dev_set_unique(struct drm_device *dev, const char *name);
 
-- 
2.1.4


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


[PATCH v9] drm: Unplug drm device when unregistering it

2017-04-12 Thread Jeffy Chen
After unbinding drm, the user space may still owns the drm dev fd, and
may still be able to call drm ioctl.

We're using an unplugged state to prevent something like that, so let's
reuse it here.

Also drop drm_unplug_dev, because it would be unused after other changes.

Signed-off-by: Jeffy Chen <jeffy.c...@rock-chips.com>

Changes in v9:
Move drm_device_set_plug_state into drm_drv.c .

Changes in v8:
Fix hang when unregistering drm dev with open_count 0.

Changes in v7:
Add drm_device_set_plug_state helper.

Changes in v6:
Reuse unplug status.

Changes in v5:
Fix wrong git account.

Changes in v2:
Fix some commit messages.

---
 drivers/gpu/drm/drm_drv.c | 26 ++
 drivers/gpu/drm/udl/udl_drv.c |  2 +-
 include/drm/drmP.h|  6 --
 include/drm/drm_drv.h |  1 -
 4 files changed, 11 insertions(+), 24 deletions(-)

diff --git a/drivers/gpu/drm/drm_drv.c b/drivers/gpu/drm/drm_drv.c
index b5c6bb4..e1da4d1 100644
--- a/drivers/gpu/drm/drm_drv.c
+++ b/drivers/gpu/drm/drm_drv.c
@@ -355,22 +355,6 @@ void drm_put_dev(struct drm_device *dev)
 }
 EXPORT_SYMBOL(drm_put_dev);
 
-void drm_unplug_dev(struct drm_device *dev)
-{
-   /* for a USB device */
-   drm_dev_unregister(dev);
-
-   mutex_lock(_global_mutex);
-
-   drm_device_set_unplugged(dev);
-
-   if (dev->open_count == 0) {
-   drm_put_dev(dev);
-   }
-   mutex_unlock(_global_mutex);
-}
-EXPORT_SYMBOL(drm_unplug_dev);
-
 /*
  * DRM internal mount
  * We want to be able to allocate our own "struct address_space" to control
@@ -733,6 +717,13 @@ static void remove_compat_control_link(struct drm_device 
*dev)
kfree(name);
 }
 
+static inline void drm_device_set_plug_state(struct drm_device *dev,
+bool plugged)
+{
+   smp_wmb();
+   atomic_set(>unplugged, !plugged);
+}
+
 /**
  * drm_dev_register - Register DRM device
  * @dev: Device to register
@@ -787,6 +778,8 @@ int drm_dev_register(struct drm_device *dev, unsigned long 
flags)
if (drm_core_check_feature(dev, DRIVER_MODESET))
drm_modeset_register_all(dev);
 
+   drm_device_set_plug_state(dev, true);
+
ret = 0;
 
DRM_INFO("Initialized %s %d.%d.%d %s for %s on minor %d\n",
@@ -826,6 +819,7 @@ void drm_dev_unregister(struct drm_device *dev)
drm_lastclose(dev);
 
dev->registered = false;
+   drm_device_set_plug_state(dev, false);
 
if (drm_core_check_feature(dev, DRIVER_MODESET))
drm_modeset_unregister_all(dev);
diff --git a/drivers/gpu/drm/udl/udl_drv.c b/drivers/gpu/drm/udl/udl_drv.c
index cd8b017..5dbd916 100644
--- a/drivers/gpu/drm/udl/udl_drv.c
+++ b/drivers/gpu/drm/udl/udl_drv.c
@@ -108,7 +108,7 @@ static void udl_usb_disconnect(struct usb_interface 
*interface)
drm_kms_helper_poll_disable(dev);
udl_fbdev_unplug(dev);
udl_drop_usb(dev);
-   drm_unplug_dev(dev);
+   drm_dev_unregister(dev);
 }
 
 /*
diff --git a/include/drm/drmP.h b/include/drm/drmP.h
index 3bfafcd..980a204 100644
--- a/include/drm/drmP.h
+++ b/include/drm/drmP.h
@@ -488,12 +488,6 @@ static __inline__ int drm_core_check_feature(struct 
drm_device *dev,
return ((dev->driver->driver_features & feature) ? 1 : 0);
 }
 
-static inline void drm_device_set_unplugged(struct drm_device *dev)
-{
-   smp_wmb();
-   atomic_set(>unplugged, 1);
-}
-
 static inline int drm_device_is_unplugged(struct drm_device *dev)
 {
int ret = atomic_read(>unplugged);
diff --git a/include/drm/drm_drv.h b/include/drm/drm_drv.h
index 0fefc3f..eb63078 100644
--- a/include/drm/drm_drv.h
+++ b/include/drm/drm_drv.h
@@ -544,7 +544,6 @@ void drm_dev_unregister(struct drm_device *dev);
 void drm_dev_ref(struct drm_device *dev);
 void drm_dev_unref(struct drm_device *dev);
 void drm_put_dev(struct drm_device *dev);
-void drm_unplug_dev(struct drm_device *dev);
 
 int drm_dev_set_unique(struct drm_device *dev, const char *name);
 
-- 
2.1.4


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


[PATCH v8 1/2] drm: Unplug drm device when unregistering it

2017-04-12 Thread Jeffy Chen
After unbinding drm, the user space may still owns the drm dev fd, and
may still be able to call drm ioctl.

We're using an unplugged state to prevent something like that, so let's
reuse it here.

Also drop drm_unplug_dev, because it would be unused after other changes.

Signed-off-by: Jeffy Chen <jeffy.c...@rock-chips.com>
Reviewed-by: Sean Paul <seanp...@chromium.org>

---

Changes in v8:
Fix hang when unregistering drm dev with open_count 0

Changes in v7:
Address Sean Paul <seanp...@chromium.org>'s comments.

Changes in v6:
Address Daniel Vetter <dan...@ffwll.ch>'s comments.

Changes in v5:
Fix wrong git account.

Changes in v2:
Fix some commit messages.

 drivers/gpu/drm/drm_drv.c | 19 +++
 drivers/gpu/drm/udl/udl_drv.c |  2 +-
 include/drm/drmP.h|  5 +++--
 include/drm/drm_drv.h |  1 -
 4 files changed, 7 insertions(+), 20 deletions(-)

diff --git a/drivers/gpu/drm/drm_drv.c b/drivers/gpu/drm/drm_drv.c
index b5c6bb4..cc2d018 100644
--- a/drivers/gpu/drm/drm_drv.c
+++ b/drivers/gpu/drm/drm_drv.c
@@ -355,22 +355,6 @@ void drm_put_dev(struct drm_device *dev)
 }
 EXPORT_SYMBOL(drm_put_dev);
 
-void drm_unplug_dev(struct drm_device *dev)
-{
-   /* for a USB device */
-   drm_dev_unregister(dev);
-
-   mutex_lock(_global_mutex);
-
-   drm_device_set_unplugged(dev);
-
-   if (dev->open_count == 0) {
-   drm_put_dev(dev);
-   }
-   mutex_unlock(_global_mutex);
-}
-EXPORT_SYMBOL(drm_unplug_dev);
-
 /*
  * DRM internal mount
  * We want to be able to allocate our own "struct address_space" to control
@@ -787,6 +771,8 @@ int drm_dev_register(struct drm_device *dev, unsigned long 
flags)
if (drm_core_check_feature(dev, DRIVER_MODESET))
drm_modeset_register_all(dev);
 
+   drm_device_set_plug_state(dev, true);
+
ret = 0;
 
DRM_INFO("Initialized %s %d.%d.%d %s for %s on minor %d\n",
@@ -826,6 +812,7 @@ void drm_dev_unregister(struct drm_device *dev)
drm_lastclose(dev);
 
dev->registered = false;
+   drm_device_set_plug_state(dev, false);
 
if (drm_core_check_feature(dev, DRIVER_MODESET))
drm_modeset_unregister_all(dev);
diff --git a/drivers/gpu/drm/udl/udl_drv.c b/drivers/gpu/drm/udl/udl_drv.c
index cd8b017..5dbd916 100644
--- a/drivers/gpu/drm/udl/udl_drv.c
+++ b/drivers/gpu/drm/udl/udl_drv.c
@@ -108,7 +108,7 @@ static void udl_usb_disconnect(struct usb_interface 
*interface)
drm_kms_helper_poll_disable(dev);
udl_fbdev_unplug(dev);
udl_drop_usb(dev);
-   drm_unplug_dev(dev);
+   drm_dev_unregister(dev);
 }
 
 /*
diff --git a/include/drm/drmP.h b/include/drm/drmP.h
index 3bfafcd..a9a5a64 100644
--- a/include/drm/drmP.h
+++ b/include/drm/drmP.h
@@ -488,10 +488,11 @@ static __inline__ int drm_core_check_feature(struct 
drm_device *dev,
return ((dev->driver->driver_features & feature) ? 1 : 0);
 }
 
-static inline void drm_device_set_unplugged(struct drm_device *dev)
+static inline void drm_device_set_plug_state(struct drm_device *dev,
+bool plugged)
 {
smp_wmb();
-   atomic_set(>unplugged, 1);
+   atomic_set(>unplugged, !plugged);
 }
 
 static inline int drm_device_is_unplugged(struct drm_device *dev)
diff --git a/include/drm/drm_drv.h b/include/drm/drm_drv.h
index 0fefc3f..eb63078 100644
--- a/include/drm/drm_drv.h
+++ b/include/drm/drm_drv.h
@@ -544,7 +544,6 @@ void drm_dev_unregister(struct drm_device *dev);
 void drm_dev_ref(struct drm_device *dev);
 void drm_dev_unref(struct drm_device *dev);
 void drm_put_dev(struct drm_device *dev);
-void drm_unplug_dev(struct drm_device *dev);
 
 int drm_dev_set_unique(struct drm_device *dev, const char *name);
 
-- 
2.1.4


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


Re: [PATCH v7 2/2] drm: Prevent release fb after cleanup drm_mode_config

2017-04-12 Thread jeffy

Hi Daniel,

On 04/12/2017 02:36 PM, Daniel Vetter wrote:

On Tue, Apr 11, 2017 at 11:31:42AM +0800, Jeffy Chen wrote:

We are freeing all framebuffers in drm_mode_config_cleanup without
sync the drm_file's fbs list.

So if someone try to unbind drm before release drm dev fd, the fbs
list would remain some invalid fb references. And that would cause
crash later in drm_fb_release.

Add a sanity check to prevent that.

Signed-off-by: Jeffy Chen <jeffy.c...@rock-chips.com>


This feels like duct-tape. The problem is that when we unplug a drm
device, we don't properly clean this up. I think we should first clean up
all the drm files (and make sure all ioctl and anything else completed),
before we proceed further in the driver cleanup.

Like I said, fixing unplug is going to be serious amounts of work, not
sure you really want to do this just for a  pure debug use-cases.
-Daniel
right, and it's ok to drop this 2 patches, the rests are already enough 
for the testing :)




---

Changes in v7:
Update commit message.

Changes in v6: None
Changes in v5: None
Changes in v2: None

  drivers/gpu/drm/drm_framebuffer.c | 5 +
  1 file changed, 5 insertions(+)

diff --git a/drivers/gpu/drm/drm_framebuffer.c 
b/drivers/gpu/drm/drm_framebuffer.c
index e8f9c13..03c1632 100644
--- a/drivers/gpu/drm/drm_framebuffer.c
+++ b/drivers/gpu/drm/drm_framebuffer.c
@@ -583,6 +583,11 @@ void drm_fb_release(struct drm_file *priv)
  {
struct drm_framebuffer *fb, *tfb;
struct drm_mode_rmfb_work arg;
+   struct drm_minor *minor = priv->minor;
+   struct drm_device *dev = minor->dev;
+
+   if (WARN_ON(!dev->mode_config.num_fb && !list_empty(>fbs)))
+   return;

INIT_LIST_HEAD();

--
2.1.4


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





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


[PATCH v8 0/2] drm: rockchip: Fix rockchip drm unbind crash error

2017-04-12 Thread Jeffy Chen

Verified on rk3399 chromebook kevin(with cros 4.4 kernel), no more crashes 
during unbind/bind drm with/out ui service running.

Changes in v8:
Fix hang when unregistering drm dev with open_count 0

Changes in v7:
Address Sean Paul <seanp...@chromium.org>'s comments.
Update commit message.

Changes in v6:
Address Daniel Vetter <dan...@ffwll.ch>'s comments.

Changes in v5:
Fix wrong git account.

Changes in v2:
Fix some commit messages.

Jeffy Chen (2):
  drm: Unplug drm device when unregistering it
  drm: Prevent release fb after cleanup drm_mode_config

 drivers/gpu/drm/drm_drv.c | 19 +++
 drivers/gpu/drm/drm_framebuffer.c |  5 +
 drivers/gpu/drm/udl/udl_drv.c |  2 +-
 include/drm/drmP.h|  5 +++--
 include/drm/drm_drv.h |  1 -
 5 files changed, 12 insertions(+), 20 deletions(-)

-- 
2.1.4


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


[PATCH v9 0/1] drm: rockchip: Fix rockchip drm unbind crash error

2017-04-12 Thread Jeffy Chen

Verified on rk3399 chromebook kevin(with cros 4.4 kernel), no more crashes 
during unbind/bind drm with/out ui service running.

Changes in v9:
Move drm_device_set_plug_state into drm_drv.c .

Changes in v8:
Fix hang when unregistering drm dev with open_count 0.

Changes in v7:
Add drm_device_set_plug_state helper.

Changes in v6:
Reuse unplug status.

Changes in v5:
Fix wrong git account.

Changes in v2:
Fix some commit messages.

Jeffy Chen (1):
  drm: Unplug drm device when unregistering it

 drivers/gpu/drm/drm_drv.c | 26 ++
 drivers/gpu/drm/udl/udl_drv.c |  2 +-
 include/drm/drmP.h|  6 --
 include/drm/drm_drv.h |  1 -
 4 files changed, 11 insertions(+), 24 deletions(-)

-- 
2.1.4


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


Re: [PATCH v7 1/2] drm: Unplug drm device when unregistering it

2017-04-12 Thread jeffy

Hi Daniel,

On 04/12/2017 02:33 PM, Daniel Vetter wrote:

On Tue, Apr 11, 2017 at 11:31:41AM +0800, Jeffy Chen wrote:

After unbinding drm, the user space may still owns the drm dev fd,
and may still be able to call drm ioctl.

We're using an unplugged state to prevent something like that, so
let's reuse it here.

Signed-off-by: Jeffy Chen <jeffy.c...@rock-chips.com>
Reviewed-by: Sean Paul <seanp...@chromium.org>

---

Changes in v7:
Address Sean Paul <seanp...@chromium.org>'s comments.

Changes in v6:
Address Daniel Vetter <dan...@ffwll.ch>'s comments.


Please don't just list the names, but what you've changed. As-is this
isn't very informative ... Also, in drm we prefer the patch changelog
above the --- line, for more credit to the review process.

A few questions below.
-Daniel



Changes in v5:
Fix wrong git account.

Changes in v2:
Fix some commit messages.

  drivers/gpu/drm/drm_drv.c | 8 
  drivers/gpu/drm/udl/udl_drv.c | 2 +-
  include/drm/drmP.h| 5 +++--
  3 files changed, 8 insertions(+), 7 deletions(-)

diff --git a/drivers/gpu/drm/drm_drv.c b/drivers/gpu/drm/drm_drv.c
index b5c6bb4..ad13e20 100644
--- a/drivers/gpu/drm/drm_drv.c
+++ b/drivers/gpu/drm/drm_drv.c
@@ -357,12 +357,9 @@ EXPORT_SYMBOL(drm_put_dev);

  void drm_unplug_dev(struct drm_device *dev)


I think this function can now be unexported and made static?


  {
-   /* for a USB device */
-   drm_dev_unregister(dev);
-
mutex_lock(_global_mutex);

-   drm_device_set_unplugged(dev);
+   drm_device_set_plug_state(dev, false);

if (dev->open_count == 0) {
drm_put_dev(dev);
@@ -787,6 +784,8 @@ int drm_dev_register(struct drm_device *dev, unsigned long 
flags)
if (drm_core_check_feature(dev, DRIVER_MODESET))
drm_modeset_register_all(dev);

+   drm_device_set_plug_state(dev, true);
+
ret = 0;

DRM_INFO("Initialized %s %d.%d.%d %s for %s on minor %d\n",
@@ -826,6 +825,7 @@ void drm_dev_unregister(struct drm_device *dev)
drm_lastclose(dev);

dev->registered = false;
+   drm_unplug_dev(dev);

if (drm_core_check_feature(dev, DRIVER_MODESET))
drm_modeset_unregister_all(dev);
diff --git a/drivers/gpu/drm/udl/udl_drv.c b/drivers/gpu/drm/udl/udl_drv.c
index cd8b017..5dbd916 100644
--- a/drivers/gpu/drm/udl/udl_drv.c
+++ b/drivers/gpu/drm/udl/udl_drv.c
@@ -108,7 +108,7 @@ static void udl_usb_disconnect(struct usb_interface 
*interface)
drm_kms_helper_poll_disable(dev);
udl_fbdev_unplug(dev);
udl_drop_usb(dev);
-   drm_unplug_dev(dev);
+   drm_dev_unregister(dev);
  }

  /*
diff --git a/include/drm/drmP.h b/include/drm/drmP.h
index 3bfafcd..a9a5a64 100644
--- a/include/drm/drmP.h
+++ b/include/drm/drmP.h
@@ -488,10 +488,11 @@ static __inline__ int drm_core_check_feature(struct 
drm_device *dev,
return ((dev->driver->driver_features & feature) ? 1 : 0);
  }

-static inline void drm_device_set_unplugged(struct drm_device *dev)
+static inline void drm_device_set_plug_state(struct drm_device *dev,
+bool plugged)


Why this change here? I thought the plan was to just unplug _all_ devices
at unregister time? Also, I think we want to make this into a static
function in drm_drv.c
calling drm_unplug_dev when unregistering drm device may cause 
hang(drm_unplug_dev will try to put drm dev when open_count is 0).


so i think we only need to update the unplug state at that time?

maybe put drm_device_set_plug_state into drm_drv.c(because no one else 
would use it)?



  {
smp_wmb();
-   atomic_set(>unplugged, 1);
+   atomic_set(>unplugged, !plugged);
  }

  static inline int drm_device_is_unplugged(struct drm_device *dev)
--
2.1.4


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





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


[PATCH v8 2/2] drm: Prevent release fb after cleanup drm_mode_config

2017-04-12 Thread Jeffy Chen
We are freeing all framebuffers in drm_mode_config_cleanup without
sync the drm_file's fbs list.

So if someone try to unbind drm before release drm dev fd, the fbs
list would remain some invalid fb references. And that would cause
crash later in drm_fb_release.

Add a sanity check to prevent that.

Signed-off-by: Jeffy Chen <jeffy.c...@rock-chips.com>

---

Changes in v8: None
Changes in v7:
Update commit message.

Changes in v6: None
Changes in v5: None
Changes in v2: None

 drivers/gpu/drm/drm_framebuffer.c | 5 +
 1 file changed, 5 insertions(+)

diff --git a/drivers/gpu/drm/drm_framebuffer.c 
b/drivers/gpu/drm/drm_framebuffer.c
index e8f9c13..03c1632 100644
--- a/drivers/gpu/drm/drm_framebuffer.c
+++ b/drivers/gpu/drm/drm_framebuffer.c
@@ -583,6 +583,11 @@ void drm_fb_release(struct drm_file *priv)
 {
struct drm_framebuffer *fb, *tfb;
struct drm_mode_rmfb_work arg;
+   struct drm_minor *minor = priv->minor;
+   struct drm_device *dev = minor->dev;
+
+   if (WARN_ON(!dev->mode_config.num_fb && !list_empty(>fbs)))
+   return;
 
INIT_LIST_HEAD();
 
-- 
2.1.4


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


Re: [PATCH v7 1/2] drm: Unplug drm device when unregistering it

2017-04-12 Thread jeffy

Hi Daniel,

missed some questions...

On 04/12/2017 04:17 PM, jeffy wrote:

Hi Daniel,

On 04/12/2017 02:33 PM, Daniel Vetter wrote:

On Tue, Apr 11, 2017 at 11:31:41AM +0800, Jeffy Chen wrote:

After unbinding drm, the user space may still owns the drm dev fd,
and may still be able to call drm ioctl.

We're using an unplugged state to prevent something like that, so
let's reuse it here.

Signed-off-by: Jeffy Chen <jeffy.c...@rock-chips.com>
Reviewed-by: Sean Paul <seanp...@chromium.org>

---

Changes in v7:
Address Sean Paul <seanp...@chromium.org>'s comments.

Changes in v6:
Address Daniel Vetter <dan...@ffwll.ch>'s comments.


Please don't just list the names, but what you've changed. As-is this
isn't very informative ... Also, in drm we prefer the patch changelog
above the --- line, for more credit to the review process.

oops, sorry, the --- line and changelogs are ordered by patman tool, 
i'll try to check did i config that wrong.



A few questions below.
-Daniel



Changes in v5:
Fix wrong git account.

Changes in v2:
Fix some commit messages.

  drivers/gpu/drm/drm_drv.c | 8 
  drivers/gpu/drm/udl/udl_drv.c | 2 +-
  include/drm/drmP.h| 5 +++--
  3 files changed, 8 insertions(+), 7 deletions(-)

diff --git a/drivers/gpu/drm/drm_drv.c b/drivers/gpu/drm/drm_drv.c
index b5c6bb4..ad13e20 100644
--- a/drivers/gpu/drm/drm_drv.c
+++ b/drivers/gpu/drm/drm_drv.c
@@ -357,12 +357,9 @@ EXPORT_SYMBOL(drm_put_dev);

  void drm_unplug_dev(struct drm_device *dev)


I think this function can now be unexported and made static?

there's a patch v8, which removed this function :)



  {
-/* for a USB device */
-drm_dev_unregister(dev);
-
  mutex_lock(_global_mutex);

-drm_device_set_unplugged(dev);
+drm_device_set_plug_state(dev, false);

  if (dev->open_count == 0) {
  drm_put_dev(dev);
@@ -787,6 +784,8 @@ int drm_dev_register(struct drm_device *dev,
unsigned long flags)
  if (drm_core_check_feature(dev, DRIVER_MODESET))
  drm_modeset_register_all(dev);

+drm_device_set_plug_state(dev, true);
+
  ret = 0;

  DRM_INFO("Initialized %s %d.%d.%d %s for %s on minor %d\n",
@@ -826,6 +825,7 @@ void drm_dev_unregister(struct drm_device *dev)
  drm_lastclose(dev);

  dev->registered = false;
+drm_unplug_dev(dev);

  if (drm_core_check_feature(dev, DRIVER_MODESET))
  drm_modeset_unregister_all(dev);
diff --git a/drivers/gpu/drm/udl/udl_drv.c
b/drivers/gpu/drm/udl/udl_drv.c
index cd8b017..5dbd916 100644
--- a/drivers/gpu/drm/udl/udl_drv.c
+++ b/drivers/gpu/drm/udl/udl_drv.c
@@ -108,7 +108,7 @@ static void udl_usb_disconnect(struct
usb_interface *interface)
  drm_kms_helper_poll_disable(dev);
  udl_fbdev_unplug(dev);
  udl_drop_usb(dev);
-drm_unplug_dev(dev);
+drm_dev_unregister(dev);
  }

  /*
diff --git a/include/drm/drmP.h b/include/drm/drmP.h
index 3bfafcd..a9a5a64 100644
--- a/include/drm/drmP.h
+++ b/include/drm/drmP.h
@@ -488,10 +488,11 @@ static __inline__ int
drm_core_check_feature(struct drm_device *dev,
  return ((dev->driver->driver_features & feature) ? 1 : 0);
  }

-static inline void drm_device_set_unplugged(struct drm_device *dev)
+static inline void drm_device_set_plug_state(struct drm_device *dev,
+ bool plugged)


Why this change here? I thought the plan was to just unplug _all_ devices
at unregister time? Also, I think we want to make this into a static
function in drm_drv.c

calling drm_unplug_dev when unregistering drm device may cause
hang(drm_unplug_dev will try to put drm dev when open_count is 0).

so i think we only need to update the unplug state at that time?

maybe put drm_device_set_plug_state into drm_drv.c(because no one else
would use it)?



  {
  smp_wmb();
-atomic_set(>unplugged, 1);
+atomic_set(>unplugged, !plugged);
  }

  static inline int drm_device_is_unplugged(struct drm_device *dev)
--
2.1.4


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







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


[PATCH v7 1/2] drm: Unplug drm device when unregistering it

2017-04-11 Thread Jeffy Chen
After unbinding drm, the user space may still owns the drm dev fd,
and may still be able to call drm ioctl.

We're using an unplugged state to prevent something like that, so
let's reuse it here.

Signed-off-by: Jeffy Chen <jeffy.c...@rock-chips.com>
Reviewed-by: Sean Paul <seanp...@chromium.org>

---

Changes in v7:
Address Sean Paul <seanp...@chromium.org>'s comments.

Changes in v6:
Address Daniel Vetter <dan...@ffwll.ch>'s comments.

Changes in v5:
Fix wrong git account.

Changes in v2:
Fix some commit messages.

 drivers/gpu/drm/drm_drv.c | 8 
 drivers/gpu/drm/udl/udl_drv.c | 2 +-
 include/drm/drmP.h| 5 +++--
 3 files changed, 8 insertions(+), 7 deletions(-)

diff --git a/drivers/gpu/drm/drm_drv.c b/drivers/gpu/drm/drm_drv.c
index b5c6bb4..ad13e20 100644
--- a/drivers/gpu/drm/drm_drv.c
+++ b/drivers/gpu/drm/drm_drv.c
@@ -357,12 +357,9 @@ EXPORT_SYMBOL(drm_put_dev);
 
 void drm_unplug_dev(struct drm_device *dev)
 {
-   /* for a USB device */
-   drm_dev_unregister(dev);
-
mutex_lock(_global_mutex);
 
-   drm_device_set_unplugged(dev);
+   drm_device_set_plug_state(dev, false);
 
if (dev->open_count == 0) {
drm_put_dev(dev);
@@ -787,6 +784,8 @@ int drm_dev_register(struct drm_device *dev, unsigned long 
flags)
if (drm_core_check_feature(dev, DRIVER_MODESET))
drm_modeset_register_all(dev);
 
+   drm_device_set_plug_state(dev, true);
+
ret = 0;
 
DRM_INFO("Initialized %s %d.%d.%d %s for %s on minor %d\n",
@@ -826,6 +825,7 @@ void drm_dev_unregister(struct drm_device *dev)
drm_lastclose(dev);
 
dev->registered = false;
+   drm_unplug_dev(dev);
 
if (drm_core_check_feature(dev, DRIVER_MODESET))
drm_modeset_unregister_all(dev);
diff --git a/drivers/gpu/drm/udl/udl_drv.c b/drivers/gpu/drm/udl/udl_drv.c
index cd8b017..5dbd916 100644
--- a/drivers/gpu/drm/udl/udl_drv.c
+++ b/drivers/gpu/drm/udl/udl_drv.c
@@ -108,7 +108,7 @@ static void udl_usb_disconnect(struct usb_interface 
*interface)
drm_kms_helper_poll_disable(dev);
udl_fbdev_unplug(dev);
udl_drop_usb(dev);
-   drm_unplug_dev(dev);
+   drm_dev_unregister(dev);
 }
 
 /*
diff --git a/include/drm/drmP.h b/include/drm/drmP.h
index 3bfafcd..a9a5a64 100644
--- a/include/drm/drmP.h
+++ b/include/drm/drmP.h
@@ -488,10 +488,11 @@ static __inline__ int drm_core_check_feature(struct 
drm_device *dev,
return ((dev->driver->driver_features & feature) ? 1 : 0);
 }
 
-static inline void drm_device_set_unplugged(struct drm_device *dev)
+static inline void drm_device_set_plug_state(struct drm_device *dev,
+bool plugged)
 {
smp_wmb();
-   atomic_set(>unplugged, 1);
+   atomic_set(>unplugged, !plugged);
 }
 
 static inline int drm_device_is_unplugged(struct drm_device *dev)
-- 
2.1.4


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


[PATCH] drm: Fixup hang when unregistering drm dev with open_count 0

2017-04-11 Thread Jeffy Chen
My previous patch (c5d8fac2bf  drm: Unplug drm device when unregistering
it) calls drm_unplug_dev when unregistering drm dev. But if open_count
is 0, the unplug will try to unregister the drm dev again and cause
deadlock.

Fix it by dropping drm_unplug_dev and use drm_device_set_plug_state
directly.

Signed-off-by: Jeffy Chen <jeffy.c...@rock-chips.com>

---

 drivers/gpu/drm/drm_drv.c | 15 +--
 include/drm/drm_drv.h |  1 -
 2 files changed, 1 insertion(+), 15 deletions(-)

diff --git a/drivers/gpu/drm/drm_drv.c b/drivers/gpu/drm/drm_drv.c
index ad13e20..cc2d018 100644
--- a/drivers/gpu/drm/drm_drv.c
+++ b/drivers/gpu/drm/drm_drv.c
@@ -355,19 +355,6 @@ void drm_put_dev(struct drm_device *dev)
 }
 EXPORT_SYMBOL(drm_put_dev);
 
-void drm_unplug_dev(struct drm_device *dev)
-{
-   mutex_lock(_global_mutex);
-
-   drm_device_set_plug_state(dev, false);
-
-   if (dev->open_count == 0) {
-   drm_put_dev(dev);
-   }
-   mutex_unlock(_global_mutex);
-}
-EXPORT_SYMBOL(drm_unplug_dev);
-
 /*
  * DRM internal mount
  * We want to be able to allocate our own "struct address_space" to control
@@ -825,7 +812,7 @@ void drm_dev_unregister(struct drm_device *dev)
drm_lastclose(dev);
 
dev->registered = false;
-   drm_unplug_dev(dev);
+   drm_device_set_plug_state(dev, false);
 
if (drm_core_check_feature(dev, DRIVER_MODESET))
drm_modeset_unregister_all(dev);
diff --git a/include/drm/drm_drv.h b/include/drm/drm_drv.h
index 0fefc3f..eb63078 100644
--- a/include/drm/drm_drv.h
+++ b/include/drm/drm_drv.h
@@ -544,7 +544,6 @@ void drm_dev_unregister(struct drm_device *dev);
 void drm_dev_ref(struct drm_device *dev);
 void drm_dev_unref(struct drm_device *dev);
 void drm_put_dev(struct drm_device *dev);
-void drm_unplug_dev(struct drm_device *dev);
 
 int drm_dev_set_unique(struct drm_device *dev, const char *name);
 
-- 
2.1.4


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


Re: [PATCH v6 0/2] drm: rockchip: Fix rockchip drm unbind crash error

2017-04-11 Thread jeffy

Hi Sean,

On 04/11/2017 03:26 AM, Sean Paul wrote:

On Mon, Apr 10, 2017 at 06:00:43PM +0800, Jeffy Chen wrote:

Hi Jeffy,
Thanks for sending this up again.



Verified on rk3399 chromebook kevin, no more crashes during unbind/bind drm.


I'm assuming this is on the chromeos-4.4 kernel? If so, you should probably
mention that when you're posting upstream.


right, will do in next version.

Sean




Changes in v6:
Address Daniel Vetter <dan...@ffwll.ch>'s comments.

Changes in v5:
Fix wrong git account.

Changes in v2:
Fix some commit messages.

Jeffy Chen (2):
   drm: Unplug drm device when unregistering it
   drm: Prevent release fb after cleanup mode config

  drivers/gpu/drm/drm_drv.c | 6 +++---
  drivers/gpu/drm/drm_framebuffer.c | 5 +
  drivers/gpu/drm/udl/udl_drv.c | 2 +-
  include/drm/drmP.h| 6 ++
  4 files changed, 15 insertions(+), 4 deletions(-)

--
2.1.4






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


[PATCH v7 0/2] drm: rockchip: Fix rockchip drm unbind crash error

2017-04-11 Thread Jeffy Chen

Verified on rk3399 chromebook kevin(with cros 4.4 kernel), no more crashes 
during unbind/bind drm.

Changes in v7:
Address Sean Paul <seanp...@chromium.org>'s comments.
Update commit message.

Changes in v6:
Address Daniel Vetter <dan...@ffwll.ch>'s comments.

Changes in v5:
Fix wrong git account.

Changes in v2:
Fix some commit messages.

Jeffy Chen (2):
  drm: Unplug drm device when unregistering it
  drm: Prevent release fb after cleanup drm_mode_config

 drivers/gpu/drm/drm_drv.c | 8 
 drivers/gpu/drm/drm_framebuffer.c | 5 +
 drivers/gpu/drm/udl/udl_drv.c | 2 +-
 include/drm/drmP.h| 5 +++--
 4 files changed, 13 insertions(+), 7 deletions(-)

-- 
2.1.4


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


[PATCH v7 2/2] drm: Prevent release fb after cleanup drm_mode_config

2017-04-11 Thread Jeffy Chen
We are freeing all framebuffers in drm_mode_config_cleanup without
sync the drm_file's fbs list.

So if someone try to unbind drm before release drm dev fd, the fbs
list would remain some invalid fb references. And that would cause
crash later in drm_fb_release.

Add a sanity check to prevent that.

Signed-off-by: Jeffy Chen <jeffy.c...@rock-chips.com>

---

Changes in v7:
Update commit message.

Changes in v6: None
Changes in v5: None
Changes in v2: None

 drivers/gpu/drm/drm_framebuffer.c | 5 +
 1 file changed, 5 insertions(+)

diff --git a/drivers/gpu/drm/drm_framebuffer.c 
b/drivers/gpu/drm/drm_framebuffer.c
index e8f9c13..03c1632 100644
--- a/drivers/gpu/drm/drm_framebuffer.c
+++ b/drivers/gpu/drm/drm_framebuffer.c
@@ -583,6 +583,11 @@ void drm_fb_release(struct drm_file *priv)
 {
struct drm_framebuffer *fb, *tfb;
struct drm_mode_rmfb_work arg;
+   struct drm_minor *minor = priv->minor;
+   struct drm_device *dev = minor->dev;
+
+   if (WARN_ON(!dev->mode_config.num_fb && !list_empty(>fbs)))
+   return;
 
INIT_LIST_HEAD();
 
-- 
2.1.4


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


Re: [PATCH v6 2/2] drm: Prevent release fb after cleanup mode config

2017-04-11 Thread jeffy

Hi Sean,

On 04/11/2017 04:31 AM, Sean Paul wrote:

On Mon, Apr 10, 2017 at 06:00:45PM +0800, Jeffy Chen wrote:

After unbinding drm, the user space may still owns the drm dev fd,
and may trigger fb release after cleanup mode config.

Add a sanity check to prevent that.

Signed-off-by: Jeffy Chen <jeffy.c...@rock-chips.com>
---

Changes in v6: None
Changes in v5: None
Changes in v2: None

  drivers/gpu/drm/drm_framebuffer.c | 5 +
  1 file changed, 5 insertions(+)

diff --git a/drivers/gpu/drm/drm_framebuffer.c 
b/drivers/gpu/drm/drm_framebuffer.c
index e8f9c13..03c1632 100644
--- a/drivers/gpu/drm/drm_framebuffer.c
+++ b/drivers/gpu/drm/drm_framebuffer.c
@@ -583,6 +583,11 @@ void drm_fb_release(struct drm_file *priv)
  {
struct drm_framebuffer *fb, *tfb;
struct drm_mode_rmfb_work arg;
+   struct drm_minor *minor = priv->minor;
+   struct drm_device *dev = minor->dev;
+
+   if (WARN_ON(!dev->mode_config.num_fb && !list_empty(>fbs)))


Have you actually seen this happen? num_fb should be tightly couple to
priv->fbs, so it seems like this could only result from a driver bug (or I'm not
reading the code correctly).

yes, 100% repro by:
1/ start display server
2/ unbind drm
3/ stop display server

the num_fb would be decreased(with a warning in 
drm_mode_config_cleanup's fb_list check) in 
drm_mode_config_cleanup->drm_framebuffer_free->rockchip_drm_fb_destroy->drm_framebuffer_cleanup


this flow would not modify the priv->fbs at the same time. so it would 
still remains the pointer of those freed fb.




Sean


+   return;

INIT_LIST_HEAD();

--
2.1.4






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


[PATCH v6 2/2] drm: Prevent release fb after cleanup mode config

2017-04-10 Thread Jeffy Chen
After unbinding drm, the user space may still owns the drm dev fd,
and may trigger fb release after cleanup mode config.

Add a sanity check to prevent that.

Signed-off-by: Jeffy Chen <jeffy.c...@rock-chips.com>
---

Changes in v6: None
Changes in v5: None
Changes in v2: None

 drivers/gpu/drm/drm_framebuffer.c | 5 +
 1 file changed, 5 insertions(+)

diff --git a/drivers/gpu/drm/drm_framebuffer.c 
b/drivers/gpu/drm/drm_framebuffer.c
index e8f9c13..03c1632 100644
--- a/drivers/gpu/drm/drm_framebuffer.c
+++ b/drivers/gpu/drm/drm_framebuffer.c
@@ -583,6 +583,11 @@ void drm_fb_release(struct drm_file *priv)
 {
struct drm_framebuffer *fb, *tfb;
struct drm_mode_rmfb_work arg;
+   struct drm_minor *minor = priv->minor;
+   struct drm_device *dev = minor->dev;
+
+   if (WARN_ON(!dev->mode_config.num_fb && !list_empty(>fbs)))
+   return;
 
INIT_LIST_HEAD();
 
-- 
2.1.4


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


[PATCH v6 0/2] drm: rockchip: Fix rockchip drm unbind crash error

2017-04-10 Thread Jeffy Chen

Verified on rk3399 chromebook kevin, no more crashes during unbind/bind drm.

Changes in v6:
Address Daniel Vetter <dan...@ffwll.ch>'s comments.

Changes in v5:
Fix wrong git account.

Changes in v2:
Fix some commit messages.

Jeffy Chen (2):
  drm: Unplug drm device when unregistering it
  drm: Prevent release fb after cleanup mode config

 drivers/gpu/drm/drm_drv.c | 6 +++---
 drivers/gpu/drm/drm_framebuffer.c | 5 +
 drivers/gpu/drm/udl/udl_drv.c | 2 +-
 include/drm/drmP.h| 6 ++
 4 files changed, 15 insertions(+), 4 deletions(-)

-- 
2.1.4


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


[PATCH v6 1/2] drm: Unplug drm device when unregistering it

2017-04-10 Thread Jeffy Chen
After unbinding drm, the user space may still owns the drm dev fd,
and may still be able to call drm ioctl.

We're using an unplugged state to prevent something like that, so
let's reuse it here.

Signed-off-by: Jeffy Chen <jeffy.c...@rock-chips.com>
---

Changes in v6:
Address Daniel Vetter <dan...@ffwll.ch>'s comments.

Changes in v5:
Fix wrong git account.

Changes in v2:
Fix some commit messages.

 drivers/gpu/drm/drm_drv.c | 6 +++---
 drivers/gpu/drm/udl/udl_drv.c | 2 +-
 include/drm/drmP.h| 6 ++
 3 files changed, 10 insertions(+), 4 deletions(-)

diff --git a/drivers/gpu/drm/drm_drv.c b/drivers/gpu/drm/drm_drv.c
index b5c6bb4..f38de26 100644
--- a/drivers/gpu/drm/drm_drv.c
+++ b/drivers/gpu/drm/drm_drv.c
@@ -357,9 +357,6 @@ EXPORT_SYMBOL(drm_put_dev);
 
 void drm_unplug_dev(struct drm_device *dev)
 {
-   /* for a USB device */
-   drm_dev_unregister(dev);
-
mutex_lock(_global_mutex);
 
drm_device_set_unplugged(dev);
@@ -787,6 +784,8 @@ int drm_dev_register(struct drm_device *dev, unsigned long 
flags)
if (drm_core_check_feature(dev, DRIVER_MODESET))
drm_modeset_register_all(dev);
 
+   drm_device_set_plugged(dev);
+
ret = 0;
 
DRM_INFO("Initialized %s %d.%d.%d %s for %s on minor %d\n",
@@ -826,6 +825,7 @@ void drm_dev_unregister(struct drm_device *dev)
drm_lastclose(dev);
 
dev->registered = false;
+   drm_unplug_dev(dev);
 
if (drm_core_check_feature(dev, DRIVER_MODESET))
drm_modeset_unregister_all(dev);
diff --git a/drivers/gpu/drm/udl/udl_drv.c b/drivers/gpu/drm/udl/udl_drv.c
index cd8b017..5dbd916 100644
--- a/drivers/gpu/drm/udl/udl_drv.c
+++ b/drivers/gpu/drm/udl/udl_drv.c
@@ -108,7 +108,7 @@ static void udl_usb_disconnect(struct usb_interface 
*interface)
drm_kms_helper_poll_disable(dev);
udl_fbdev_unplug(dev);
udl_drop_usb(dev);
-   drm_unplug_dev(dev);
+   drm_dev_unregister(dev);
 }
 
 /*
diff --git a/include/drm/drmP.h b/include/drm/drmP.h
index 3bfafcd..c930a77 100644
--- a/include/drm/drmP.h
+++ b/include/drm/drmP.h
@@ -488,6 +488,12 @@ static __inline__ int drm_core_check_feature(struct 
drm_device *dev,
return ((dev->driver->driver_features & feature) ? 1 : 0);
 }
 
+static inline void drm_device_set_plugged(struct drm_device *dev)
+{
+   smp_wmb();
+   atomic_set(>unplugged, 0);
+}
+
 static inline void drm_device_set_unplugged(struct drm_device *dev)
 {
smp_wmb();
-- 
2.1.4


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


Re: [PATCH v5 12/12] drm/drm_ioctl.c: Break ioctl when drm device not registered

2017-04-07 Thread jeffy

Hi Daniel,

On 04/07/2017 03:16 PM, Daniel Vetter wrote:

On Thu, Apr 06, 2017 at 08:31:25PM +0800, Jeffy Chen wrote:

After unbinding drm, the user space may still owns the drm dev fd,
and may still be able to call drm ioctl.

Add a sanity check here to prevent that from happening.

Signed-off-by: Jeffy Chen <jeffy.c...@rock-chips.com>
---

Changes in v5: None
Changes in v4: None
Changes in v3: None
Changes in v2: None

  drivers/gpu/drm/drm_ioctl.c | 2 +-
  1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/drivers/gpu/drm/drm_ioctl.c b/drivers/gpu/drm/drm_ioctl.c
index 7d6deaa..15beb11 100644
--- a/drivers/gpu/drm/drm_ioctl.c
+++ b/drivers/gpu/drm/drm_ioctl.c
@@ -674,7 +674,7 @@ long drm_ioctl(struct file *filp,

dev = file_priv->minor->dev;

-   if (drm_device_is_unplugged(dev))
+   if (drm_device_is_unplugged(dev) || !dev->registered)


Shouldn't we instead automatically unplug the device in
drm_dev_unregister, instead of sprinkling tons of drm_device_is_unplugged
|| !registered all over the place?


it looks like the drm_unplug_dev would call drm_dev_unregister...
maybe we can:
1/ replace the dev_unplug_dev in udl_drv.c to drm_dev_unregister
2/ call dev_unplug_dev in drm_dev_unregister, and remove 
drm_dev_unregister in dev_unplug_dev
3/ add a drm_plug_dev or drm_device_set_plugged, and call it in 
drm_dev_register



That should catch a few more issues where userspace might creep into the
driver after unregistering ...
-Daniel


return -ENODEV;

is_driver_ioctl = nr >= DRM_COMMAND_BASE && nr < DRM_COMMAND_END;
--
2.1.4


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





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


Re: [PATCH v3 8/9] drm/rockchip: gem: Don't alloc/free gem buf when dev_private is invalid

2017-04-07 Thread jeffy

Hi Daniel,

On 04/07/2017 02:30 PM, Daniel Vetter wrote:

On Thu, Apr 6, 2017 at 1:09 PM, jeffy <jeffy.c...@rock-chips.com> wrote:


On 04/06/2017 04:26 PM, Daniel Vetter wrote:


On Wed, Apr 05, 2017 at 12:28:40PM -0400, Sean Paul wrote:


On Wed, Apr 05, 2017 at 04:29:26PM +0800, Jeffy Chen wrote:


After unbinding drm, the userspace may still has a chance to access
gem buf.

Add a sanity check for a NULL dev_private to prevent that from
happening.



I still don't understand how this is happening. You're saying that these
hooks
can be called after rockchip_drm_unbind() has finished?



Yeah this is supposed to be impossible. If it isn't, we need to debug and
fix this properly. This smells like pretty bad duct-tape ...



it looks like after unbind, the user space may still own drm dev fd, and
could be able to call ioctl:
lrwx--. 1 chronos chronos 64 Mar 15 12:53 28 -> /dev/dri/card1 (deleted)

and the drm_unplug_dev may help it, maybe we should call it in unbind? or
just break drm_ioctl when drm_dev not registered?


Yes, by default unbind while userspace is running is totally broken in
drm. drm_unplug_dev would be the fix, but it's only used by udl and
not many use that. You might need to fix infrastructure up a bit.

please check this patch:
9667071 New  [v5,12/12] drm/drm_ioctl.c: Break ioctl when drm 
device not registered


For normal module unload the module reference will prevent unloading.
So why exactly do you care about the unbind use-case?

sometimes we use unbind/bind for testing ;)

-Daniel




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


[PATCH v5 10/12] drm/rockchip: Reoder drm bind/unbind sequence

2017-04-06 Thread Jeffy Chen
Current drm bind/unbind sequence would cause some memory issues.
For example we should not cleanup iommu before cleanup mode config.

Reorder bind/unbind sequence, follow exynos drm.

Signed-off-by: Jeffy Chen <jeffy.c...@rock-chips.com>
---

Changes in v5: None
Changes in v4: None
Changes in v3:
Address Sean Paul <seanp...@chromium.org>'s comments.
Update commit message.

Changes in v2: None

 drivers/gpu/drm/rockchip/rockchip_drm_drv.c | 49 +++--
 1 file changed, 26 insertions(+), 23 deletions(-)

diff --git a/drivers/gpu/drm/rockchip/rockchip_drm_drv.c 
b/drivers/gpu/drm/rockchip/rockchip_drm_drv.c
index cd7d02e1..f24968f 100644
--- a/drivers/gpu/drm/rockchip/rockchip_drm_drv.c
+++ b/drivers/gpu/drm/rockchip/rockchip_drm_drv.c
@@ -136,21 +136,24 @@ static int rockchip_drm_bind(struct device *dev)
INIT_LIST_HEAD(>psr_list);
spin_lock_init(>psr_list_lock);
 
+   ret = rockchip_drm_init_iommu(drm_dev);
+   if (ret)
+   goto err_free;
+
drm_mode_config_init(drm_dev);
 
rockchip_drm_mode_config_init(drm_dev);
 
-   ret = rockchip_drm_init_iommu(drm_dev);
-   if (ret)
-   goto err_config_cleanup;
-
/* Try to bind all sub drivers. */
ret = component_bind_all(dev, drm_dev);
if (ret)
-   goto err_iommu_cleanup;
+   goto err_mode_config_cleanup;
 
-   /* init kms poll for handling hpd */
-   drm_kms_helper_poll_init(drm_dev);
+   ret = drm_vblank_init(drm_dev, drm_dev->mode_config.num_crtc);
+   if (ret)
+   goto err_unbind_all;
+
+   drm_mode_config_reset(drm_dev);
 
/*
 * enable drm irq mode.
@@ -158,15 +161,12 @@ static int rockchip_drm_bind(struct device *dev)
 */
drm_dev->irq_enabled = true;
 
-   ret = drm_vblank_init(drm_dev, ROCKCHIP_MAX_CRTC);
-   if (ret)
-   goto err_kms_helper_poll_fini;
-
-   drm_mode_config_reset(drm_dev);
+   /* init kms poll for handling hpd */
+   drm_kms_helper_poll_init(drm_dev);
 
ret = rockchip_drm_fbdev_init(drm_dev);
if (ret)
-   goto err_vblank_cleanup;
+   goto err_kms_helper_poll_fini;
 
ret = drm_dev_register(drm_dev, 0);
if (ret)
@@ -175,17 +175,17 @@ static int rockchip_drm_bind(struct device *dev)
return 0;
 err_fbdev_fini:
rockchip_drm_fbdev_fini(drm_dev);
-err_vblank_cleanup:
-   drm_vblank_cleanup(drm_dev);
 err_kms_helper_poll_fini:
drm_kms_helper_poll_fini(drm_dev);
+   drm_vblank_cleanup(drm_dev);
+err_unbind_all:
component_unbind_all(dev, drm_dev);
-err_iommu_cleanup:
-   rockchip_iommu_cleanup(drm_dev);
-err_config_cleanup:
+err_mode_config_cleanup:
drm_mode_config_cleanup(drm_dev);
-   drm_dev->dev_private = NULL;
+   rockchip_iommu_cleanup(drm_dev);
 err_free:
+   drm_dev->dev_private = NULL;
+   dev_set_drvdata(dev, NULL);
drm_dev_unref(drm_dev);
return ret;
 }
@@ -194,16 +194,19 @@ static void rockchip_drm_unbind(struct device *dev)
 {
struct drm_device *drm_dev = dev_get_drvdata(dev);
 
+   drm_dev_unregister(drm_dev);
+
rockchip_drm_fbdev_fini(drm_dev);
-   drm_vblank_cleanup(drm_dev);
drm_kms_helper_poll_fini(drm_dev);
+
+   drm_vblank_cleanup(drm_dev);
component_unbind_all(dev, drm_dev);
-   rockchip_iommu_cleanup(drm_dev);
drm_mode_config_cleanup(drm_dev);
+   rockchip_iommu_cleanup(drm_dev);
+
drm_dev->dev_private = NULL;
-   drm_dev_unregister(drm_dev);
-   drm_dev_unref(drm_dev);
dev_set_drvdata(dev, NULL);
+   drm_dev_unref(drm_dev);
 }
 
 static void rockchip_drm_lastclose(struct drm_device *dev)
-- 
2.1.4


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


Re: [PATCH v3 8/9] drm/rockchip: gem: Don't alloc/free gem buf when dev_private is invalid

2017-04-06 Thread jeffy

Hi Sean,

On 04/06/2017 08:26 PM, Sean Paul wrote:

On Thu, Apr 06, 2017 at 10:47:59AM +0800, jeffy wrote:

Hi Sean,

On 04/06/2017 12:28 AM, Sean Paul wrote:

On Wed, Apr 05, 2017 at 04:29:26PM +0800, Jeffy Chen wrote:

After unbinding drm, the userspace may still has a chance to access
gem buf.

Add a sanity check for a NULL dev_private to prevent that from
happening.


I still don't understand how this is happening. You're saying that these hooks
can be called after rockchip_drm_unbind() has finished?


yes, tested on chromebook rk3399 kevin with kernel 4.4, if trigger unbind
without killing display service(ui or frecon):

[   31.276889] [] dump_backtrace+0x0/0x164
[   31.282288] [] show_stack+0x24/0x30
[   31.287338] [] dump_stack+0x98/0xb8
[   31.292389] [] rockchip_gem_create_object+0x6c/0x2ec
[   31.298910] []
rockchip_gem_create_with_handle+0x38/0x10c
[   31.305868] [] rockchip_gem_create_ioctl+0x38/0x50
[   31.312221] [] drm_ioctl+0x2bc/0x438
[   31.317359] [] drm_compat_ioctl+0x3c/0x70
[   31.322935] [] compat_SyS_ioctl+0x134/0x1048
[   31.328766] [] __sys_trace_return+0x0/0x4


Hi Jeffy,
I'm not suggesting this doesn't happen, I believe you :-). I'd really like to
know *why* it happens.

Are you sure that unbind has completely finished before this trace occurs?
Perhaps this is results from a race between unbind and gem allocate?
yes, that unbind is finished. and it looks like the display server still 
holds drm dev fd(even it been deleted after unbind).


sometimes i can see it trigger ioctl even seconds later.

i'll send a patch to break drm_ioctl after unbind.


Sean




Sean



Signed-off-by: Jeffy Chen <jeffy.c...@rock-chips.com>
---

Changes in v3:
Address Daniel Vetter <dan...@ffwll.ch>'s comments.
Update commit message.

Changes in v2: None

   drivers/gpu/drm/rockchip/rockchip_drm_gem.c | 8 
   1 file changed, 8 insertions(+)

diff --git a/drivers/gpu/drm/rockchip/rockchip_drm_gem.c 
b/drivers/gpu/drm/rockchip/rockchip_drm_gem.c
index df9e570..205a3dc 100644
--- a/drivers/gpu/drm/rockchip/rockchip_drm_gem.c
+++ b/drivers/gpu/drm/rockchip/rockchip_drm_gem.c
@@ -184,6 +184,9 @@ static int rockchip_gem_alloc_buf(struct 
rockchip_gem_object *rk_obj,
struct drm_device *drm = obj->dev;
struct rockchip_drm_private *private = drm->dev_private;

+   if (!private)
+   return -ENODEV;
+
if (private->domain)
return rockchip_gem_alloc_iommu(rk_obj, alloc_kmap);
else
@@ -208,6 +211,11 @@ static void rockchip_gem_free_dma(struct 
rockchip_gem_object *rk_obj)

   static void rockchip_gem_free_buf(struct rockchip_gem_object *rk_obj)
   {
+   struct drm_device *drm = rk_obj->base.dev;
+
+   if (!drm->dev_private)
+   return;
+
if (rk_obj->pages)
rockchip_gem_free_iommu(rk_obj);
else
--
2.1.4










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


[PATCH v5 01/12] drm: bridge: analogix: Detach panel when unbinding analogix dp

2017-04-06 Thread Jeffy Chen
The panel is attached when binding analogix dp.

Signed-off-by: Jeffy Chen <jeffy.c...@rock-chips.com>
Reviewed-by: Andrzej Hajda <a.ha...@samsung.com>
---

Changes in v5:
Fix wrong git account.

Changes in v4: None
Changes in v3: None
Changes in v2:
Fix some commit messages.

 drivers/gpu/drm/bridge/analogix/analogix_dp_core.c | 2 ++
 1 file changed, 2 insertions(+)

diff --git a/drivers/gpu/drm/bridge/analogix/analogix_dp_core.c 
b/drivers/gpu/drm/bridge/analogix/analogix_dp_core.c
index c26997a..28144a1 100644
--- a/drivers/gpu/drm/bridge/analogix/analogix_dp_core.c
+++ b/drivers/gpu/drm/bridge/analogix/analogix_dp_core.c
@@ -1443,6 +1443,8 @@ void analogix_dp_unbind(struct device *dev, struct device 
*master,
if (dp->plat_data->panel) {
if (drm_panel_unprepare(dp->plat_data->panel))
DRM_ERROR("failed to turnoff the panel\n");
+   if (drm_panel_detach(dp->plat_data->panel))
+   DRM_ERROR("failed to detach the panel\n");
}
 
pm_runtime_disable(dev);
-- 
2.1.4


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


[PATCH v5 03/12] drm: bridge: analogix: Disable clock when unbinding

2017-04-06 Thread Jeffy Chen
The clock is enabled when binding analogix dp.

Signed-off-by: Jeffy Chen <jeffy.c...@rock-chips.com>
---

Changes in v5: None
Changes in v4: None
Changes in v3: None
Changes in v2: None

 drivers/gpu/drm/bridge/analogix/analogix_dp_core.c | 1 +
 1 file changed, 1 insertion(+)

diff --git a/drivers/gpu/drm/bridge/analogix/analogix_dp_core.c 
b/drivers/gpu/drm/bridge/analogix/analogix_dp_core.c
index 7b75f82..d05ade4 100644
--- a/drivers/gpu/drm/bridge/analogix/analogix_dp_core.c
+++ b/drivers/gpu/drm/bridge/analogix/analogix_dp_core.c
@@ -1449,6 +1449,7 @@ void analogix_dp_unbind(struct device *dev, struct device 
*master,
 
drm_dp_aux_unregister(>aux);
pm_runtime_disable(dev);
+   clk_disable_unprepare(dp->clock);
 }
 EXPORT_SYMBOL_GPL(analogix_dp_unbind);
 
-- 
2.1.4


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


[PATCH v5 08/12] drm/rockchip: vop: Unprepare clocks when unbinding

2017-04-06 Thread Jeffy Chen
The clocks are prepared when binding vop.

Signed-off-by: Jeffy Chen <jeffy.c...@rock-chips.com>
---

Changes in v5: None
Changes in v4: None
Changes in v3: None
Changes in v2: None

 drivers/gpu/drm/rockchip/rockchip_drm_vop.c | 4 
 1 file changed, 4 insertions(+)

diff --git a/drivers/gpu/drm/rockchip/rockchip_drm_vop.c 
b/drivers/gpu/drm/rockchip/rockchip_drm_vop.c
index b65b296..3f7a82d 100644
--- a/drivers/gpu/drm/rockchip/rockchip_drm_vop.c
+++ b/drivers/gpu/drm/rockchip/rockchip_drm_vop.c
@@ -1634,6 +1634,10 @@ static void vop_unbind(struct device *dev, struct device 
*master, void *data)
 
pm_runtime_disable(dev);
vop_destroy_crtc(vop);
+
+   clk_unprepare(vop->aclk);
+   clk_unprepare(vop->hclk);
+   clk_unprepare(vop->dclk);
 }
 
 const struct component_ops vop_component_ops = {
-- 
2.1.4


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


[PATCH v5 07/12] drm/rockchip: vop: Enable pm domain before vop_initial

2017-04-06 Thread Jeffy Chen
We're trying to access vop registers here, so need to make sure
the pm domain is on.

Normally it should be enabled by the bootloader, but there's no
guarantee of it. And if we wanna do unbind/bind, it would also
cause the device to hang.

And this patch also does these:
1/ move vop_initial to the end of vop_bind for eaiser error handling.
2/ correct the err_put_pm_runtime of vop_enable.

Signed-off-by: Jeffy Chen <jeffy.c...@rock-chips.com>
---

Changes in v5: None
Changes in v4: None
Changes in v3:
Address Sean Paul <seanp...@chromium.org>'s comments.
Update commit message.

Changes in v2: None

 drivers/gpu/drm/rockchip/rockchip_drm_vop.c | 29 +
 1 file changed, 21 insertions(+), 8 deletions(-)

diff --git a/drivers/gpu/drm/rockchip/rockchip_drm_vop.c 
b/drivers/gpu/drm/rockchip/rockchip_drm_vop.c
index 2151e1c..b65b296 100644
--- a/drivers/gpu/drm/rockchip/rockchip_drm_vop.c
+++ b/drivers/gpu/drm/rockchip/rockchip_drm_vop.c
@@ -506,7 +506,7 @@ static int vop_enable(struct drm_crtc *crtc)
ret = pm_runtime_get_sync(vop->dev);
if (ret < 0) {
dev_err(vop->dev, "failed to get pm runtime: %d\n", ret);
-   goto err_put_pm_runtime;
+   return ret;
}
 
ret = clk_enable(vop->hclk);
@@ -1405,10 +1405,16 @@ static int vop_initial(struct vop *vop)
return PTR_ERR(vop->dclk);
}
 
+   ret = pm_runtime_get_sync(vop->dev);
+   if (ret < 0) {
+   dev_err(vop->dev, "failed to get pm runtime: %d\n", ret);
+   return ret;
+   }
+
ret = clk_prepare(vop->dclk);
if (ret < 0) {
dev_err(vop->dev, "failed to prepare dclk\n");
-   return ret;
+   goto err_put_pm_runtime;
}
 
/* Enable both the hclk and aclk to setup the vop */
@@ -1468,6 +1474,8 @@ static int vop_initial(struct vop *vop)
 
vop->is_enabled = false;
 
+   pm_runtime_put_sync(vop->dev);
+
return 0;
 
 err_disable_aclk:
@@ -1476,6 +1484,8 @@ static int vop_initial(struct vop *vop)
clk_disable_unprepare(vop->hclk);
 err_unprepare_dclk:
clk_unprepare(vop->dclk);
+err_put_pm_runtime:
+   pm_runtime_put_sync(vop->dev);
return ret;
 }
 
@@ -1576,12 +1586,6 @@ static int vop_bind(struct device *dev, struct device 
*master, void *data)
if (!vop->regsbak)
return -ENOMEM;
 
-   ret = vop_initial(vop);
-   if (ret < 0) {
-   dev_err(>dev, "cannot initial vop dev - err %d\n", ret);
-   return ret;
-   }
-
irq = platform_get_irq(pdev, 0);
if (irq < 0) {
dev_err(dev, "cannot find irq for vop\n");
@@ -1608,8 +1612,17 @@ static int vop_bind(struct device *dev, struct device 
*master, void *data)
 
pm_runtime_enable(>dev);
 
+   ret = vop_initial(vop);
+   if (ret < 0) {
+   dev_err(>dev, "cannot initial vop dev - err %d\n", ret);
+   goto err_disable_pm_runtime;
+   }
+
return 0;
 
+err_disable_pm_runtime:
+   pm_runtime_disable(>dev);
+   vop_destroy_crtc(vop);
 err_enable_irq:
enable_irq(vop->irq); /* To balance out the disable_irq above */
return ret;
-- 
2.1.4


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


[PATCH v5 06/12] drm/rockchip: cdn-dp: Don't unregister audio dev when unbinding

2017-04-06 Thread Jeffy Chen
After snd_soc_unregister_codec, the dai link would remain bound to
the invalid codec. That would cause crashes after unbind dp driver.

Let's unregister audio codec when removing dp driver to prevent that.

Signed-off-by: Jeffy Chen <jeffy.c...@rock-chips.com>
---

Changes in v5: None
Changes in v4: None
Changes in v3:
Update commit message.

Changes in v2: None

 drivers/gpu/drm/rockchip/cdn-dp-core.c | 6 +++---
 1 file changed, 3 insertions(+), 3 deletions(-)

diff --git a/drivers/gpu/drm/rockchip/cdn-dp-core.c 
b/drivers/gpu/drm/rockchip/cdn-dp-core.c
index ee4195d..a2169dd 100644
--- a/drivers/gpu/drm/rockchip/cdn-dp-core.c
+++ b/drivers/gpu/drm/rockchip/cdn-dp-core.c
@@ -1092,8 +1092,6 @@ static int cdn_dp_bind(struct device *dev, struct device 
*master, void *data)
goto err_free_connector;
}
 
-   cdn_dp_audio_codec_init(dp, dev);
-
for (i = 0; i < dp->ports; i++) {
port = dp->port[i];
 
@@ -1128,7 +1126,6 @@ static void cdn_dp_unbind(struct device *dev, struct 
device *master, void *data)
struct drm_connector *connector = >connector;
 
cancel_work_sync(>event_work);
-   platform_device_unregister(dp->audio_pdev);
cdn_dp_encoder_disable(encoder);
encoder->funcs->destroy(encoder);
connector->funcs->destroy(connector);
@@ -1221,6 +1218,8 @@ static int cdn_dp_probe(struct platform_device *pdev)
mutex_init(>lock);
dev_set_drvdata(dev, dp);
 
+   cdn_dp_audio_codec_init(dp, dev);
+
return component_add(dev, _dp_component_ops);
 }
 
@@ -1228,6 +1227,7 @@ static int cdn_dp_remove(struct platform_device *pdev)
 {
struct cdn_dp_device *dp = platform_get_drvdata(pdev);
 
+   platform_device_unregister(dp->audio_pdev);
cdn_dp_suspend(dp->dev);
component_del(>dev, _dp_component_ops);
 
-- 
2.1.4


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


[PATCH v5 11/12] drm/rockchip: Shutdown all crtcs when unbinding drm

2017-04-06 Thread Jeffy Chen
Signed-off-by: Jeffy Chen <jeffy.c...@rock-chips.com>
---

Changes in v5: None
Changes in v4: None
Changes in v3:
Address Daniel Vetter <dan...@ffwll.ch>'s comments.
Update commit message.

Changes in v2: None

 drivers/gpu/drm/rockchip/rockchip_drm_drv.c | 1 +
 1 file changed, 1 insertion(+)

diff --git a/drivers/gpu/drm/rockchip/rockchip_drm_drv.c 
b/drivers/gpu/drm/rockchip/rockchip_drm_drv.c
index f24968f..c6b1b7f 100644
--- a/drivers/gpu/drm/rockchip/rockchip_drm_drv.c
+++ b/drivers/gpu/drm/rockchip/rockchip_drm_drv.c
@@ -199,6 +199,7 @@ static void rockchip_drm_unbind(struct device *dev)
rockchip_drm_fbdev_fini(drm_dev);
drm_kms_helper_poll_fini(drm_dev);
 
+   drm_atomic_helper_shutdown(drm_dev);
drm_vblank_cleanup(drm_dev);
component_unbind_all(dev, drm_dev);
drm_mode_config_cleanup(drm_dev);
-- 
2.1.4


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


  1   2   >