Backlight control broken on UM325 (OLED) on 5.15 (bisected)

2021-11-14 Thread Samuel Čavoj
Hello,

the backlight control no longer works on my ASUS UM325 (Ryzen 5700U)
OLED laptop. I have bisected the breakage to commit 7fd13baeb7a3a48.

commit 7fd13baeb7a3a48cae12c36c52f06bf4e9e7d728 (HEAD, refs/bisect/bad)
Author: Alex Deucher 
Date:   Thu Jul 8 16:31:10 2021 -0400
 
drm/amdgpu/display: add support for multiple backlights

On platforms that support multiple backlights, register
each one separately.  This lets us manage them independently
rather than registering a single backlight and applying the
same settings to both.

v2: fix typo:
Reported-by: kernel test robot 

Reviewed-by: Roman Li 
Signed-off-by: Alex Deucher 

I have encountered another user with the same issue on reddit[0].

The node in /sys/class/backlight exists, writing to it just does
nothing. I would be glad to help debugging the issue. Thank you very
much.

Regards,
Samuel Čavoj

[0]: 
https://www.reddit.com/r/AMDLaptops/comments/qst0fm/after_updating_to_linux_515_my_brightness/


Panic with linus/master and panfrost

2021-11-14 Thread Ondřej Jirman
Hello,

I'm getting some fence refcounting related panics with the current
Linus's master branch:

It happens immediately whenever I start Xorg or sway.

Anyone has any ideas where to start looking? It works fine with v5.15.

(sorry for the interleaved log, it's coming from multiple CPUs at once
I guess)

kind regards,
o.

[ cut here ]
refcount_t: underflow; use-after-free.
WARNING: CPU: 4 PID: 560 at lib/refcount.c:28 refcount_warn_saturate+0xec/0x140
Modules linked in:
CPU: 4 PID: 560 Comm: sway Not tainted 5.15.0-13547-g5169ae41ace0 #24
Hardware name: Pine64 PinePhonePro (DT)
pstate: 4005 (nZcv daif -PAN -UAO -TCO -DIT -SSBS BTYPE=--)
pc : refcount_warn_saturate+0xec/0x140
lr : refcount_warn_saturate+0xec/0x140
sp : 8000127b3be0
x29: 8000127b3be0 x28: 8000127b3d50 x27: 1927e700
x26:  x25: 0001 x24: 0004
x23: 1e31da80 x22: 05497580 x21: 1e31da90
x20: 1e31da80 x19: 1e31da90 x18: 0003
x17:  x16:  x15: 8000127b3b68
x14:  x13: 2e656572662d7265 x12: 7466612d65737520
x11: 3b776f6c66726564 x10: 800011d7e8a0 x9 : 800010178a1c
x8 : efff x7 : 800011dd68a0 x6 : 0001
x5 : f778e788 x4 :  x3 : 0027
x2 : 0023 x1 : f778e790 x0 : 0026
Call trace:
 refcount_warn_saturate+0xec/0x140
 drm_syncobj_replace_fence+0x16c/0x17c
 panfrost_ioctl_submit+0x364/0x440
 drm_ioctl_kernel+0x9c/0x154
 drm_ioctl+0x1f0/0x410
 __arm64_sys_ioctl+0xb4/0xdc
 invoke_syscall+0x4c/0x110
 el0_svc_common.constprop.0+0x48/0xf0
 do_el0_svc+0x2c/0x90
 el0_svc+0x14/0x50
 el0t_64_sync_handler+0x9c/0x120
 el0t_64_sync+0x158/0x15c
---[ end trace 51cdc14807ba9222 ]---
[ cut here ]
Unable to handle kernel write to read-only memory at virtual address 
800010820b10
refcount_t: saturated; leaking memory.
Mem abort info:
WARNING: CPU: 1 PID: 223 at lib/refcount.c:22 refcount_warn_saturate+0x6c/0x140
  ESR = 0x964e
Modules linked in:
  EC = 0x25: DABT (current EL), IL = 32 bits

CPU: 1 PID: 223 Comm: pan_js Tainted: GW 
5.15.0-13547-g5169ae41ace0 #24
  SET = 0, FnV = 0
Hardware name: Pine64 PinePhonePro (DT)
  EA = 0, S1PTW = 0
pstate: 4005 (nZcv daif -PAN -UAO -TCO -DIT -SSBS BTYPE=--)
  FSC = 0x0e: level 2 permission fault
pc : refcount_warn_saturate+0x6c/0x140
Data abort info:
lr : refcount_warn_saturate+0x6c/0x140
  ISV = 0, ISS = 0x004e
sp : 800012a2bd90
  CM = 0, WnR = 1
x29: 800012a2bd90
swapper pgtable: 4k pages, 48-bit VAs, pgdp=019ba000
 x28: 
[800010820b10] pgd=1000f7fff003
 x27: 
, p4d=1000f7fff003

, pud=1000f7ffe003
x26: 
, pmd=004000a00781
 x25: 800011906000

 x24: 13ee7a20
Internal error: Oops: 964e [#1] SMP

Modules linked in:
x23: 8000108211e0

 x22: 800011906000
CPU: 2 PID: 222 Comm: pan_js Tainted: GW 
5.15.0-13547-g5169ae41ace0 #24
 x21: 251ef000
Hardware name: Pine64 PinePhonePro (DT)

pstate: 00c5 (nzcv daIF -PAN -UAO -TCO -DIT -SSBS BTYPE=--)
x20: 05497580
pc : dma_fence_add_callback+0xc8/0x120
 x19: 1532b4c0
lr : dma_fence_add_callback+0x78/0x120
 x18: 
sp : 800012a23d60

x29: 800012a23d60
x17: 00040044
 x28: 
 x16: 0032b5503510
 x27: 
 x15: 


x26: 
x14: 0550c380
 x25: 800011906000
 x13: 2e79726f6d656d20
 x24: 
 x12: 676e696b61656c20


x23: 
x11: 3b64657461727574
 x22: 8000108211e0
 x10: 6173203a745f746e
 x21: 054975d0
 x9 : 80001022e51c


x20: 1532b468
x8 : 0001
 x19: 05497580
 x7 : 0e08
 x18: 
 x6 : 0001


x17: 00040044
x5 : 
 x16: 0032b5503510
 x4 : f773a788
 x15: 
 x3 : f77466f0


x14: 0550d100
x2 : f773a788
 x13: 8000e5e4e000
 x1 : 8000e5e32000
 x12: 34d4d91d
 x0 : 0026


x11: 
Call trace:
 x10: 0002
 refcount_warn_saturate+0x6c/0x140
 x9 : 800010899578
 drm_sched_entity_pop_job+0x418/0x490
 
 drm_sched_main+0xb0/0x41c
x8 : 148dcd60
 kthread+0x14c/0x160
 x7 : 
 ret_from_fork+0x10/0x20
 x6 : 010a4760
---[ end trace 51cdc14807ba9223 ]---

x5 : 13ee79f8 x4 : 0001 x3 : 054975b0
x2 :  x1 : 800010820b10 x0 : 05497590
Call trace:
 dma_fence_add_callback+0xc8/0x120
 drm_sched_entity_pop_job+0xa4/0x490
 drm_sched_main+0xb0/0x41c
 kthread+0x14c/0x160
 ret_from_fork+0x10/0x20
Code: 91004260 f9400e61 f9000e74 a9000680 (f934)
---[ end trace 51cdc14807ba9224 ]---
Kernel panic - not syncing: Oops: 

Re: [PATCH] drm/amd/amdgpu: remove useless break after return

2021-11-14 Thread Joe Perches
On Sun, 2021-11-14 at 23:14 -0800, Bernard Zhao wrote:
> This change is to remove useless break after return.
[]
> diff --git a/drivers/gpu/drm/amd/amdgpu/dce_v8_0.c 
> b/drivers/gpu/drm/amd/amdgpu/dce_v8_0.c
[]
> @@ -2092,22 +2092,18 @@ static int dce_v8_0_pick_dig_encoder(struct 
> drm_encoder *encoder)
>   return 1;
>   else
>   return 0;
> - break;
>   case ENCODER_OBJECT_ID_INTERNAL_UNIPHY1:
>   if (dig->linkb)
>   return 3;
>   else
>   return 2;
> - break;
>   case ENCODER_OBJECT_ID_INTERNAL_UNIPHY2:
>   if (dig->linkb)
>   return 5;
>   else
>   return 4;
> - break;
>   case ENCODER_OBJECT_ID_INTERNAL_UNIPHY3:
>   return 6;
> - break;
>   default:
>   DRM_ERROR("invalid encoder_id: 0x%x\n", 
> amdgpu_encoder->encoder_id);
>   return 0;

Perhaps rewrite to make the sequential numbering more obvious.
---
 drivers/gpu/drm/amd/amdgpu/dce_v8_0.c | 19 +++
 1 file changed, 3 insertions(+), 16 deletions(-)

diff --git a/drivers/gpu/drm/amd/amdgpu/dce_v8_0.c 
b/drivers/gpu/drm/amd/amdgpu/dce_v8_0.c
index b200b9e722d97..7307524b706b4 100644
--- a/drivers/gpu/drm/amd/amdgpu/dce_v8_0.c
+++ b/drivers/gpu/drm/amd/amdgpu/dce_v8_0.c
@@ -2088,26 +2088,13 @@ static int dce_v8_0_pick_dig_encoder(struct drm_encoder 
*encoder)
 
switch (amdgpu_encoder->encoder_id) {
case ENCODER_OBJECT_ID_INTERNAL_UNIPHY:
-   if (dig->linkb)
-   return 1;
-   else
-   return 0;
-   break;
+   return !dig->linkb ? 0 : 1;
case ENCODER_OBJECT_ID_INTERNAL_UNIPHY1:
-   if (dig->linkb)
-   return 3;
-   else
-   return 2;
-   break;
+   return !dig->linkb ? 2 : 3;
case ENCODER_OBJECT_ID_INTERNAL_UNIPHY2:
-   if (dig->linkb)
-   return 5;
-   else
-   return 4;
-   break;
+   return !dig->linkb ? 4 : 5;
case ENCODER_OBJECT_ID_INTERNAL_UNIPHY3:
return 6;
-   break;
default:
DRM_ERROR("invalid encoder_id: 0x%x\n", 
amdgpu_encoder->encoder_id);
return 0;




Re: Questions about KMS flip

2021-11-14 Thread Christian König

Am 12.11.21 um 17:10 schrieb Michel Dänzer:

On 2021-11-12 16:03, Christian König wrote:

Am 12.11.21 um 15:30 schrieb Michel Dänzer:

On 2021-11-12 15:29, Michel Dänzer wrote:

On 2021-11-12 13:47, Christian König wrote:

Anyway this unfortunately turned out to be work for Harray and Nicholas. In detail it's 
about this bug report here: 
https://nam11.safelinks.protection.outlook.com/?url=https%3A%2F%2Fbugzilla.kernel.org%2Fshow_bug.cgi%3Fid%3D214621data=04%7C01%7Cchristian.koenig%40amd.com%7Cca557eab16864ab544a108d9a5f6f288%7C3dd8961fe4884e608e11a82d994e183d%7C0%7C0%7C637723302340621335%7CUnknown%7CTWFpbGZsb3d8eyJWIjoiMC4wLjAwMDAiLCJQIjoiV2luMzIiLCJBTiI6Ik1haWwiLCJXVCI6Mn0%3D%7C1000sdata=pvLGq%2FJRvVy0k5GMGF2UPotCSdbiQNfndtjI14luAUg%3Dreserved=0

Lang was able to reproduce the issue and narrow it down to the pin in 
amdgpu_display_crtc_page_flip_target().

In other words we somehow have an unbalanced pinning of the scanout buffer in 
DC.

DC doesn't use amdgpu_display_crtc_page_flip_target AFAICT. The corresponding 
pin with DC would be in dm_plane_helper_prepare_fb, paired with the unpin in
dm_plane_helper_cleanup_fb.


With non-DC, the pin in amdgpu_display_crtc_page_flip_target is paired with the 
unpin in dm_plane_helper_cleanup_fb

This should say amdgpu_display_unpin_work_func.

Ah! So that is the classic (e.g. non atomic) path?

Presumably.



& dce_v*_crtc_disable. One thing I notice is that the pin is guarded by if 
(!adev->enable_virtual_display), but the unpins seem unconditional. So could this 
be about virtual display, and the problem is actually trying to unpin a BO that was 
never pinned?

Nope, my educated guess is rather that we free up the BO before 
amdgpu_display_unpin_work_func is called.

E.g. not pin unbalance, but rather use after free.

amdgpu_display_crtc_page_flip_target calls amdgpu_bo_ref(work->old_abo), and 
amdgpu_display_unpin_work_func calls amdgpu_bo_unref(>old_abo) only after 
amdgpu_bo_unpin. So what you describe could only happen if there's an imbalance elsewhere such that 
amdgpu_bo_unref is called more often than amdgpu_bo_ref, or maybe if amdgpu_bo_reserve fails in 
amdgpu_display_unpin_work_func (in which case the "failed to reserve buffer after flip" 
error message should appear in dmesg).


Yeah, seen that in the meantime as well.

But we also have a WARN_ON() when the pincount overruns, so that can't 
be it either.


Long story short I have no idea what's going on here.

Regards,
Christian.


[PATCH] drm/exynos: remove useless type conversion

2021-11-14 Thread Bernard Zhao
This change is to cleanup the code a bit.

Signed-off-by: Bernard Zhao 
---
 drivers/gpu/drm/exynos/exynos_drm_fimc.c | 4 ++--
 1 file changed, 2 insertions(+), 2 deletions(-)

diff --git a/drivers/gpu/drm/exynos/exynos_drm_fimc.c 
b/drivers/gpu/drm/exynos/exynos_drm_fimc.c
index ecfd82d0afb7..023f54ee61a8 100644
--- a/drivers/gpu/drm/exynos/exynos_drm_fimc.c
+++ b/drivers/gpu/drm/exynos/exynos_drm_fimc.c
@@ -782,8 +782,8 @@ static int fimc_set_prescaler(struct fimc_context *ctx, 
struct fimc_scaler *sc,
 
sc->hratio = (src_w << 14) / (dst_w << hfactor);
sc->vratio = (src_h << 14) / (dst_h << vfactor);
-   sc->up_h = (dst_w >= src_w) ? true : false;
-   sc->up_v = (dst_h >= src_h) ? true : false;
+   sc->up_h = (dst_w >= src_w);
+   sc->up_v = (dst_h >= src_h);
DRM_DEV_DEBUG_KMS(ctx->dev, "hratio[%d]vratio[%d]up_h[%d]up_v[%d]\n",
  sc->hratio, sc->vratio, sc->up_h, sc->up_v);
 
-- 
2.33.1



Re: [git pull] drm fixes + one missed next for 5.16-rc1

2021-11-14 Thread Thomas Hellström



On 11/14/21 22:19, Linus Torvalds wrote:

On Sun, Nov 14, 2021 at 1:00 PM Dave Airlie  wrote:

i915 will no longer be x86-64 only in theory, since Intel now produces
PCIe graphics cards using the same hw designs.

Well, at least in my tree, it still has the "depends on X86", along
with several other x86-only things (like "select INTEL_GTT", which is
also x86-only)

So by the time that non-x86 theory becomes reality, hopefully the i915
people will also have figured out how to do the cache flushing
properly.

And hopefully that "do it properly" ends up being simply that the
particular configuration that ends up being portable simply doesn't
need to do it at all and can statically just not build it,
sidestepping the issue entirely.

Fingers crossed.


For non-x86 / discrete graphics, plan is only coherent mappings, 
although the "Just not build it" part hasn't been properly figured out 
yet I guess. But point taken.


Thanks,

/Thomas



[PATCH] drm/amd/amdgpu: remove useless break after return

2021-11-14 Thread Bernard Zhao
This change is to remove useless break after return.

Signed-off-by: Bernard Zhao 
---
 drivers/gpu/drm/amd/amdgpu/dce_v8_0.c | 4 
 1 file changed, 4 deletions(-)

diff --git a/drivers/gpu/drm/amd/amdgpu/dce_v8_0.c 
b/drivers/gpu/drm/amd/amdgpu/dce_v8_0.c
index b200b9e722d9..8318ee8339f1 100644
--- a/drivers/gpu/drm/amd/amdgpu/dce_v8_0.c
+++ b/drivers/gpu/drm/amd/amdgpu/dce_v8_0.c
@@ -2092,22 +2092,18 @@ static int dce_v8_0_pick_dig_encoder(struct drm_encoder 
*encoder)
return 1;
else
return 0;
-   break;
case ENCODER_OBJECT_ID_INTERNAL_UNIPHY1:
if (dig->linkb)
return 3;
else
return 2;
-   break;
case ENCODER_OBJECT_ID_INTERNAL_UNIPHY2:
if (dig->linkb)
return 5;
else
return 4;
-   break;
case ENCODER_OBJECT_ID_INTERNAL_UNIPHY3:
return 6;
-   break;
default:
DRM_ERROR("invalid encoder_id: 0x%x\n", 
amdgpu_encoder->encoder_id);
return 0;
-- 
2.33.1



[PATCH] drm/amd/amdgpu: cleanup the code style a bit

2021-11-14 Thread Bernard Zhao
This change is to cleanup the code style a bit.

Signed-off-by: Bernard Zhao 
---
 drivers/gpu/drm/amd/amdgpu/amdgpu_virt.c | 10 ++
 1 file changed, 6 insertions(+), 4 deletions(-)

diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_virt.c 
b/drivers/gpu/drm/amd/amdgpu/amdgpu_virt.c
index 04cf9b207e62..90070b41136a 100644
--- a/drivers/gpu/drm/amd/amdgpu/amdgpu_virt.c
+++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_virt.c
@@ -286,12 +286,14 @@ static int amdgpu_virt_init_ras_err_handler_data(struct 
amdgpu_device *adev)
return -ENOMEM;
 
bps = kmalloc_array(align_space, sizeof((*data)->bps), GFP_KERNEL);
+   if (!bps) {
+   kfree(*data);
+   return -ENOMEM;
+   }
bps_bo = kmalloc_array(align_space, sizeof((*data)->bps_bo), 
GFP_KERNEL);
-
-   if (!bps || !bps_bo) {
-   kfree(bps);
-   kfree(bps_bo);
+   if (!bps_bo) {
kfree(*data);
+   kfree(bps);
return -ENOMEM;
}
 
-- 
2.33.1



Re: [PATCH] fbdev: sh7760fb: document fallthrough cases

2021-11-14 Thread Gustavo A. R. Silva
On Sun, Nov 14, 2021 at 10:32:57PM -0800, Randy Dunlap wrote:
> Fix fallthrough warnings in sh776fb.c:
> 
> ../drivers/video/fbdev/sh7760fb.c: In function 'sh7760fb_get_color_info':
> ../drivers/video/fbdev/sh7760fb.c:138:23: warning: this statement may fall 
> through [-Wimplicit-fallthrough=]
>   138 | lgray = 1;
> ../drivers/video/fbdev/sh7760fb.c:143:23: warning: this statement may fall 
> through [-Wimplicit-fallthrough=]
>   143 | lgray = 1;
> 
> Just document the current state of code execution/flow.
> 
> Fixes: 4a25e41831ee ("video: sh7760fb: SH7760/SH7763 LCDC framebuffer driver")
> Signed-off-by: Randy Dunlap 
> Cc: "Gustavo A. R. Silva" 
> Cc: Nobuhiro Iwamatsu 
> Cc: Manuel Lauss 
> Cc: Yoshinori Sato 
> Cc: Rich Felker 
> Cc: linux...@vger.kernel.org
> Cc: linux-fb...@vger.kernel.org
> Cc: dri-devel@lists.freedesktop.org

Reviewed-by: Gustavo A. R. Silva 

Thanks, Randy.
--
Gustavo

> ---
>  drivers/video/fbdev/sh7760fb.c |2 ++
>  1 file changed, 2 insertions(+)
> 
> --- linux-next-2022.orig/drivers/video/fbdev/sh7760fb.c
> +++ linux-next-2022/drivers/video/fbdev/sh7760fb.c
> @@ -136,11 +136,13 @@ static int sh7760fb_get_color_info(struc
>   break;
>   case LDDFR_4BPP_MONO:
>   lgray = 1;
> + fallthrough;
>   case LDDFR_4BPP:
>   lbpp = 4;
>   break;
>   case LDDFR_6BPP_MONO:
>   lgray = 1;
> + fallthrough;
>   case LDDFR_8BPP:
>   lbpp = 8;
>   break;


[PATCH] fbdev: sh7760fb: document fallthrough cases

2021-11-14 Thread Randy Dunlap
Fix fallthrough warnings in sh776fb.c:

../drivers/video/fbdev/sh7760fb.c: In function 'sh7760fb_get_color_info':
../drivers/video/fbdev/sh7760fb.c:138:23: warning: this statement may fall 
through [-Wimplicit-fallthrough=]
  138 | lgray = 1;
../drivers/video/fbdev/sh7760fb.c:143:23: warning: this statement may fall 
through [-Wimplicit-fallthrough=]
  143 | lgray = 1;

Just document the current state of code execution/flow.

Fixes: 4a25e41831ee ("video: sh7760fb: SH7760/SH7763 LCDC framebuffer driver")
Signed-off-by: Randy Dunlap 
Cc: "Gustavo A. R. Silva" 
Cc: Nobuhiro Iwamatsu 
Cc: Manuel Lauss 
Cc: Yoshinori Sato 
Cc: Rich Felker 
Cc: linux...@vger.kernel.org
Cc: linux-fb...@vger.kernel.org
Cc: dri-devel@lists.freedesktop.org
---
 drivers/video/fbdev/sh7760fb.c |2 ++
 1 file changed, 2 insertions(+)

--- linux-next-2022.orig/drivers/video/fbdev/sh7760fb.c
+++ linux-next-2022/drivers/video/fbdev/sh7760fb.c
@@ -136,11 +136,13 @@ static int sh7760fb_get_color_info(struc
break;
case LDDFR_4BPP_MONO:
lgray = 1;
+   fallthrough;
case LDDFR_4BPP:
lbpp = 4;
break;
case LDDFR_6BPP_MONO:
lgray = 1;
+   fallthrough;
case LDDFR_8BPP:
lbpp = 8;
break;


[PATCH] drm/xen: fix potential memleak in error branch

2021-11-14 Thread Bernard Zhao
In function xen_drm_front_gem_import_sg_table, if in error branch,
there maybe potential memleak if not call gem_free_pages_array.

Signed-off-by: Bernard Zhao 
---
 drivers/gpu/drm/xen/xen_drm_front_gem.c | 8 ++--
 1 file changed, 6 insertions(+), 2 deletions(-)

diff --git a/drivers/gpu/drm/xen/xen_drm_front_gem.c 
b/drivers/gpu/drm/xen/xen_drm_front_gem.c
index b293c67230ef..732c3eec0666 100644
--- a/drivers/gpu/drm/xen/xen_drm_front_gem.c
+++ b/drivers/gpu/drm/xen/xen_drm_front_gem.c
@@ -222,15 +222,19 @@ xen_drm_front_gem_import_sg_table(struct drm_device *dev,
 
ret = drm_prime_sg_to_page_array(sgt, xen_obj->pages,
 xen_obj->num_pages);
-   if (ret < 0)
+   if (ret < 0) {
+   gem_free_pages_array(xen_obj);
return ERR_PTR(ret);
+   }
 
ret = xen_drm_front_dbuf_create(drm_info->front_info,

xen_drm_front_dbuf_to_cookie(_obj->base),
0, 0, 0, size, sgt->sgl->offset,
xen_obj->pages);
-   if (ret < 0)
+   if (ret < 0) {
+   gem_free_pages_array(xen_obj);
return ERR_PTR(ret);
+   }
 
DRM_DEBUG("Imported buffer of size %zu with nents %u\n",
  size, sgt->orig_nents);
-- 
2.33.1



[PATCH] backlight: ili922x: fix kernel-doc warnings & notation

2021-11-14 Thread Randy Dunlap
Convert function-like macro comments to kernel-doc notation and
fix other kernel-doc warnings:

drivers/video/backlight/ili922x.c:85: warning: This comment starts with '/**', 
but isn't a kernel-doc comment. Refer Documentation/doc-guide/kernel-doc.rst
* START_BYTE(id, rs, rw)
drivers/video/backlight/ili922x.c:118: warning: expecting prototype for 
CHECK_FREQ_REG(spi_device s, spi_transfer x)(). Prototype was for 
CHECK_FREQ_REG() instead

ili922x.c:92: warning: contents before sections
ili922x.c:150: warning: No description found for return value of 
'ili922x_read_status'
ili922x.c:193: warning: No description found for return value of 'ili922x_read'
ili922x.c:247: warning: No description found for return value of 'ili922x_write'
ili922x.c:353: warning: No description found for return value of 
'ili922x_poweron'
ili922x.c:382: warning: No description found for return value of 
'ili922x_poweroff'

Fixes: 4cfbfa971478 ("video: backlight: add ili922x lcd driver")
Signed-off-by: Randy Dunlap 
Reported-by: kernel test robot 
Cc: Lee Jones 
Cc: Daniel Thompson 
Cc: Jingoo Han 
Cc: dri-devel@lists.freedesktop.org
Cc: Stefano Babic 
Cc: Anatolij Gustschin 
---
 drivers/video/backlight/ili922x.c |   29 ++--
 1 file changed, 19 insertions(+), 10 deletions(-)

--- linux-next-20211102.orig/drivers/video/backlight/ili922x.c
+++ linux-next-20211102/drivers/video/backlight/ili922x.c
@@ -82,13 +82,7 @@
 #define START_RW_READ  1
 
 /**
- * START_BYTE(id, rs, rw)
- *
- * Set the start byte according to the required operation.
- * The start byte is defined as:
- *   --
- *  | 0 | 1 | 1 | 1 | 0 | ID | RS | RW |
- *   --
+ * START_BYTE() - Set the start byte according to the required operation
  * @id: display's id as set by the manufacturer
  * @rs: operation type bit, one of:
  *   - START_RS_INDEX  set the index register
@@ -96,14 +90,19 @@
  * @rw: read/write operation
  *  - START_RW_WRITE   write
  *  - START_RW_READread
+ *
+ * The start byte is defined as:
+ *   --
+ *  | 0 | 1 | 1 | 1 | 0 | ID | RS | RW |
+ *   --
  */
 #define START_BYTE(id, rs, rw) \
(0x70 | (((id) & 0x01) << 2) | (((rs) & 0x01) << 1) | ((rw) & 0x01))
 
 /**
- * CHECK_FREQ_REG(spi_device s, spi_transfer x) - Check the frequency
- * for the SPI transfer. According to the datasheet, the controller
- * accept higher frequency for the GRAM transfer, but it requires
+ * CHECK_FREQ_REG() - Check the frequency for the SPI transfer
+ * According to the datasheet, the controller
+ * accepts higher frequency for the GRAM transfer, but it requires
  * lower frequency when the registers are read/written.
  * The macro sets the frequency in the spi_transfer structure if
  * the frequency exceeds the maximum value.
@@ -145,6 +144,8 @@ struct ili922x {
  * ili922x_read_status - read status register from display
  * @spi: spi device
  * @rs:  output value
+ *
+ * Return: %0 on success or a negative error code on failure
  */
 static int ili922x_read_status(struct spi_device *spi, u16 *rs)
 {
@@ -188,6 +189,8 @@ static int ili922x_read_status(struct sp
  * @spi: spi device
  * @reg: offset of the register to be read
  * @rx:  output value
+ *
+ * Return: %0 on success or a negative error code on failure
  */
 static int ili922x_read(struct spi_device *spi, u8 reg, u16 *rx)
 {
@@ -242,6 +245,8 @@ static int ili922x_read(struct spi_devic
  * @spi: struct spi_device *
  * @reg: offset of the register to be written
  * @value: value to be written
+ *
+ * Return: %0 on success or a negative error code on failure
  */
 static int ili922x_write(struct spi_device *spi, u8 reg, u16 value)
 {
@@ -348,6 +353,8 @@ static void set_write_to_gram_reg(struct
  * The sequence to turn on the display is taken from
  * the datasheet and/or the example code provided by the
  * manufacturer.
+ *
+ * Return: %0 on success or a negative value on failure
  */
 static int ili922x_poweron(struct spi_device *spi)
 {
@@ -377,6 +384,8 @@ static int ili922x_poweron(struct spi_de
 /**
  * ili922x_poweroff - turn the display off
  * @spi: spi device
+ *
+ * Return: %0 on success or a negative value on failure
  */
 static int ili922x_poweroff(struct spi_device *spi)
 {


[PATCH] drm/amd/amdgpu: fix potential memleak

2021-11-14 Thread Bernard Zhao
In function amdgpu_get_xgmi_hive, when kobject_init_and_add failed
There is a potential memleak if not call kobject_put.

Signed-off-by: Bernard Zhao 
---
 drivers/gpu/drm/amd/amdgpu/amdgpu_xgmi.c | 1 +
 1 file changed, 1 insertion(+)

diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_xgmi.c 
b/drivers/gpu/drm/amd/amdgpu/amdgpu_xgmi.c
index 0fad2bf854ae..567df2db23ac 100644
--- a/drivers/gpu/drm/amd/amdgpu/amdgpu_xgmi.c
+++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_xgmi.c
@@ -386,6 +386,7 @@ struct amdgpu_hive_info *amdgpu_get_xgmi_hive(struct 
amdgpu_device *adev)
"%s", "xgmi_hive_info");
if (ret) {
dev_err(adev->dev, "XGMI: failed initializing kobject for xgmi 
hive\n");
+   kobject_put(>kobj);
kfree(hive);
hive = NULL;
goto pro_end;
-- 
2.33.1



[Bug 211277] sometimes crash at s2ram-wake (Ryzen 3500U): amdgpu, drm, commit_tail, amdgpu_dm_atomic_commit_tail

2021-11-14 Thread bugzilla-daemon
https://bugzilla.kernel.org/show_bug.cgi?id=211277

--- Comment #73 from kolAflash (kolafl...@kolahilft.de) ---
(In reply to Jerome C from comment #72)
> Hi James,
> 
> I noticed the patch that you asked us to try from comment 52 were also
> submitted to kernel 5.14.7
> 
> tested it, all is good for now

Pleased to hear that :-)
I'm just compiling 5.15.2 to run a test myself.

@James
Will those patches be backported to the Linux-5.10 LTS kernel?

master and Linux-5.15
https://git.kernel.org/pub/scm/linux/kernel/git/stable/linux.git/commit/?id=f02abeb0779700c308e661a412451b38962b8a0b
https://git.kernel.org/pub/scm/linux/kernel/git/stable/linux.git/commit/?id=8066008482e533e91934bee49765bf8b4a7c40db
https://git.kernel.org/pub/scm/linux/kernel/git/stable/linux.git/commit/?id=fefc01f042f44ede373ee66773b8238dd8fdcb55

Linux-5.14.7
https://git.kernel.org/pub/scm/linux/kernel/git/stable/linux.git/commit/?id=fe232886fb710a4bf0532f61ebdb87463a780e7e
https://git.kernel.org/pub/scm/linux/kernel/git/stable/linux.git/commit/?id=413a8644966a9b4709b114bdb102f64f505d57ef
https://git.kernel.org/pub/scm/linux/kernel/git/stable/linux.git/commit/?id=64ca7170c9b17042dc63828b56681aaea88ca38e

-- 
You may reply to this email to add a comment.

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

[Bug 215025] [amdgpu] Thinkpad A275 hangs on shutdown / screen does not turn on after reboot

2021-11-14 Thread bugzilla-daemon
https://bugzilla.kernel.org/show_bug.cgi?id=215025

--- Comment #2 from Bjoern Franke (b...@nord-west.org) ---
Tested 5.14.16 - ok
Tried 5.15.0 and 5.15.1 -> don't even boot, the first 3 lines look misarranged.

I will try to bisect between 5.14.16 and 5.15.2.

-- 
You may reply to this email to add a comment.

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

[Bug 215025] [amdgpu] Thinkpad A275 hangs on shutdown / screen does not turn on after reboot

2021-11-14 Thread bugzilla-daemon
https://bugzilla.kernel.org/show_bug.cgi?id=215025

--- Comment #1 from Bjoern Franke (b...@nord-west.org) ---
BTW, iommu is enabled:
[0.739887] perf/amd_iommu: Detected AMD IOMMU #0 (2 banks, 4
counters/bank).

-- 
You may reply to this email to add a comment.

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

[Bug 215025] New: [amdgpu] Thinkpad A275 hangs on shutdown / screen does not turn on after reboot

2021-11-14 Thread bugzilla-daemon
https://bugzilla.kernel.org/show_bug.cgi?id=215025

Bug ID: 215025
   Summary: [amdgpu] Thinkpad A275 hangs on shutdown / screen does
not turn on after reboot
   Product: Drivers
   Version: 2.5
Kernel Version: 5.15.2
  Hardware: All
OS: Linux
  Tree: Mainline
Status: NEW
  Severity: normal
  Priority: P1
 Component: Video(DRI - non Intel)
  Assignee: drivers_video-...@kernel-bugs.osdl.org
  Reporter: b...@nord-west.org
Regression: No

My Thinkpad A275 hangs while going into suspend. The screen turned off, but it
does not really enter suspend mode (according to journalctl it started
suspending). Even after reboots the screen does not turn on again, I have to
power off the Thinkpad and then power it on again. The issue did not exist with
5.14.x.

-- 
You may reply to this email to add a comment.

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

Re: [PATCH v10, 00/19] Support multi hardware decode using of_platform_populate

2021-11-14 Thread Ezequiel Garcia
Hi Yunfei,

On Thu, 11 Nov 2021 at 01:15, Yunfei Dong  wrote:
>
> This series adds support for multi hardware decode into mtk-vcodec, by first 
> adding use
> of_platform_populate to manage each hardware information: interrupt, clock, 
> register
> bases and power. Secondly add core work queue to deal with core hardware 
> message,
> at the same time, add msg queue for different hardware share messages. 
> Lastly, the
> architecture of different specs are not the same, using specs type to 
> separate them.
>
> This series has been tested with both MT8183 and MT8173. Decoding was working 
> for both chips.
>

How are you testing Decoding? If you are running some test suite, it would
be good to add such information.

Are you testing some edge-cases such as parallel/concurrent decoding,
removing the driver while streaming, and so on? This should help catch
some typical issues.

Thanks,
Ezequiel

> Patches 1~3 rewrite get register bases and power on/off interface.
> Patches 4 export decoder pm interfaces.
> Patches 5 add to support 8192.
> Patch 6 support multi hardware.
> Patch 7 separate video encoder and decoder document
> Patch 8-17 add interfaces to support core hardware.
> Patch 18-19 remove mtk_vcodec_release_dec/enc_pm interfaces.
> ---
> changes compared with v9:
> - need not to build ko, just export pm interfaces for patch 04/19.
> - fix comments for patch 06/19
>
> changes compared with v8:
> - add new patch 18~19 to remove mtk_vcodec_release_de/enc_pm interfaces.
> - fix spelling mistakes for patch 17/19
> - fix yaml comments for patch 15/19
>
> Changes compared with v7:
> - add new patch 4 to build decoder pm file as module
> - add new patch 5 to support 8192
> - fix comments for patch 6/17
> - change some logic for using work queue instead of create thread for core 
> hardware decode for patch 10/17
> - using work queue for hardware decode instead of create thread for patch 
> 13/17
> - add returen value for patch 14/17
> - fix yaml check fail 15/17
>
> Changes compared with v6:
> - Use of_platform_populate to manage multi hardware, not component framework 
> for patch 4/15
> - Re-write dtsi document for hardware architecture changed for patch 13/15 
> -The dtsi will write like below in patch 13/15:
> vcodec_dec: vcodec_dec@1600 {
> compatible = "mediatek,mt8192-vcodec-dec";
> #address-cells = <2>;
> #size-cells = <2>;
> ranges;
> reg = <0 0x1600 0 0x1000>;  /* VDEC_SYS */
> mediatek,scp = <>;
> iommus = < M4U_PORT_L4_VDEC_MC_EXT>;
> dma-ranges = <0x1 0x0 0x0 0x4000 0x0 0xfff0>;
> vcodec_lat {
> compatible = "mediatek,mtk-vcodec-lat";
> reg = <0 0x1601 0 0x800>;   /* VDEC_MISC */
> reg-name = "reg-misc";
> interrupts = ;
> iommus = < M4U_PORT_L5_VDEC_LAT0_VLD_EXT>,
>  < M4U_PORT_L5_VDEC_LAT0_VLD2_EXT>,
>  < M4U_PORT_L5_VDEC_LAT0_AVC_MV_EXT>,
>  < M4U_PORT_L5_VDEC_LAT0_PRED_RD_EXT>,
>  < M4U_PORT_L5_VDEC_LAT0_TILE_EXT>,
>  < M4U_PORT_L5_VDEC_LAT0_WDMA_EXT>,
>  < M4U_PORT_L5_VDEC_LAT0_RG_CTRL_DMA_EXT>,
>  < M4U_PORT_L5_VDEC_UFO_ENC_EXT>;
> clocks = < CLK_TOP_VDEC_SEL>,
>  <_soc CLK_VDEC_SOC_VDEC>,
>  <_soc CLK_VDEC_SOC_LAT>,
>  <_soc CLK_VDEC_SOC_LARB1>,
>  < CLK_TOP_MAINPLL_D4>;
> clock-names = "vdec-sel", "vdec-soc-vdec", "vdec-soc-lat",
>   "vdec-vdec", "vdec-top";
> assigned-clocks = < CLK_TOP_VDEC_SEL>;
> assigned-clock-parents = < CLK_TOP_MAINPLL_D4>;
> power-domains = < MT8192_POWER_DOMAIN_VDEC>;
> };
>
> vcodec_core {
> compatible = "mediatek,mtk-vcodec-core";
> reg = <0 0x16025000 0 0x1000>;  /* VDEC_CORE_MISC */
> reg-names = "reg-misc";
> interrupts = ;
> iommus = < M4U_PORT_L4_VDEC_MC_EXT>,
>  < M4U_PORT_L4_VDEC_UFO_EXT>,
>  < M4U_PORT_L4_VDEC_PP_EXT>,
>  < M4U_PORT_L4_VDEC_PRED_RD_EXT>,
>  < M4U_PORT_L4_VDEC_PRED_WR_EXT>,
>  < M4U_PORT_L4_VDEC_PPWRAP_EXT>,
>  < M4U_PORT_L4_VDEC_TILE_EXT>,
>  < M4U_PORT_L4_VDEC_VLD_EXT>,
>  < M4U_PORT_L4_VDEC_VLD2_EXT>,
>  < M4U_PORT_L4_VDEC_AVC_MV_EXT>,
>  < M4U_PORT_L4_VDEC_RG_CTRL_DMA_EXT>;
> clocks = < CLK_TOP_VDEC_SEL>,
>  < CLK_VDEC_VDEC>,
>  < CLK_VDEC_LAT>,
>  < CLK_VDEC_LARB1>,
>  < CLK_TOP_MAINPLL_D4>;
> clock-names = "vdec-sel", "vdec-soc-vdec", "vdec-soc-lat",
>   "vdec-vdec", "vdec-top";
> assigned-clocks = < CLK_TOP_VDEC_SEL>;
> 

Re: [PATCH v10, 15/19] dt-bindings: media: mtk-vcodec: Adds decoder dt-bindings for mt8192

2021-11-14 Thread Ezequiel Garcia
Yunfei,

On Thu, 11 Nov 2021 at 01:15, Yunfei Dong  wrote:
>
> Adds decoder dt-bindings for mt8192.
>
> Signed-off-by: Yunfei Dong 
> ---
>  .../media/mediatek,vcodec-subdev-decoder.yaml | 261 ++
>  1 file changed, 261 insertions(+)
>  create mode 100644 
> Documentation/devicetree/bindings/media/mediatek,vcodec-subdev-decoder.yaml
>
> diff --git 
> a/Documentation/devicetree/bindings/media/mediatek,vcodec-subdev-decoder.yaml 
> b/Documentation/devicetree/bindings/media/mediatek,vcodec-subdev-decoder.yaml
> new file mode 100644
> index ..1886fae6e39d
> --- /dev/null
> +++ 
> b/Documentation/devicetree/bindings/media/mediatek,vcodec-subdev-decoder.yaml
> @@ -0,0 +1,261 @@
> +# SPDX-License-Identifier: (GPL-2.0-only OR BSD-2-Clause)
> +
> +%YAML 1.2
> +---
> +$id: 
> "http://devicetree.org/schemas/media/mediatek,vcodec-subdev-decoder.yaml#;
> +$schema: "http://devicetree.org/meta-schemas/core.yaml#;
> +
> +title: Mediatek Video Decode Accelerator With Multi Hardware
> +
> +maintainers:
> +  - Yunfei Dong 
> +
> +description: |
> +  Mediatek Video Decode is the video decode hardware present in Mediatek
> +  SoCs which supports high resolution decoding functionalities. Required
> +  main and subdev device node.
> +
> +  About the Decoder Hardware Block Diagram, please check below:
> +
> ++-++
> +| ||
> +| input -> lat HW -> lat buffer --|--> lat buffer -> core HW -> output
 |

To be completely honest, I can't really understand what is the meaning
of the blocks
with input -> lat hw -> lat buffer, and how this means lat- and core-
are children of some parent.

> +|||   | || |
> ++||---+-||-+
> + ||   lat thread  |  core thread|| 
> +
> -||-||
> + || || 
> + \/ \/
> +   +--+
> +   |enable/disable|
> +   |   clk powerirqiommu port |
> +   | (lat/lat soc/core0/core1)|
> +   +--+
> +
> +  As above,  mean in main device,  mean in subdev device. The 
> information
> +  of each hardware will be stored in subdev device. There are two workqueues 
> in main device:
> +  lat and core. Enable/disable the lat clk/power/irq when lat need to work 
> through hardware
> +  index, core is the same.
> +
> +  Normally the smi common may not the same for each hardware, can't combine 
> all hardware in
> +  one node, or leading to iommu fault when access dram data.
> +

To what extent the lat- and core- devices are really "children"
or "subdevices" of the  video-codec@1600 device?

I.e. what resources do they share? What are the details of
their bus topology?

> +
> +examples:
> +  - |
> +#include 
> +#include 
> +#include 
> +#include 
> +#include 
> +
> +video-codec@1600 {
> +compatible = "mediatek,mt8192-vcodec-dec";
> +reg = <0x1600 0x1000>; /* VDEC_SYS */
> +mediatek,scp = <>;
> +iommus = < M4U_PORT_L4_VDEC_MC_EXT>;
> +dma-ranges = <0x1 0x0 0x0 0x4000 0x0 0xfff0>;
> +#address-cells = <1>;
> +#size-cells = <1>;
> +ranges;
> +vcodec-lat@1601 {
> +compatible = "mediatek,mtk-vcodec-lat";
> +reg = <0x1601 0x800>;
> +interrupts = ;
> +iommus = < M4U_PORT_L5_VDEC_LAT0_VLD_EXT>,
> +< M4U_PORT_L5_VDEC_LAT0_VLD2_EXT>,
> +< M4U_PORT_L5_VDEC_LAT0_AVC_MV_EXT>,
> +< M4U_PORT_L5_VDEC_LAT0_PRED_RD_EXT>,
> +< M4U_PORT_L5_VDEC_LAT0_TILE_EXT>,
> +< M4U_PORT_L5_VDEC_LAT0_WDMA_EXT>,
> +< M4U_PORT_L5_VDEC_LAT0_RG_CTRL_DMA_EXT>,
> +< M4U_PORT_L5_VDEC_UFO_ENC_EXT>;
> +clocks = < CLK_TOP_VDEC_SEL>,
> +<_soc CLK_VDEC_SOC_VDEC>,
> +<_soc CLK_VDEC_SOC_LAT>,
> +<_soc CLK_VDEC_SOC_LARB1>,
> +< CLK_TOP_MAINPLL_D4>;
> +clock-names = "sel", "soc-vdec", "soc-lat", "vdec", "top";
> +assigned-clocks = < CLK_TOP_VDEC_SEL>;
> +assigned-clock-parents = < CLK_TOP_MAINPLL_D4>;
> +power-domains = < MT8192_POWER_DOMAIN_VDEC>;
> +};
> +
> +vcodec-core@16025000 {
> +compatible = "mediatek,mtk-vcodec-core";
> +reg = <0x16025000 0x1000>;

The children address space might 

Re: [git pull] drm fixes + one missed next for 5.16-rc1

2021-11-14 Thread Linus Torvalds
On Sun, Nov 14, 2021 at 1:00 PM Dave Airlie  wrote:
>
> i915 will no longer be x86-64 only in theory, since Intel now produces
> PCIe graphics cards using the same hw designs.

Well, at least in my tree, it still has the "depends on X86", along
with several other x86-only things (like "select INTEL_GTT", which is
also x86-only)

So by the time that non-x86 theory becomes reality, hopefully the i915
people will also have figured out how to do the cache flushing
properly.

And hopefully that "do it properly" ends up being simply that the
particular configuration that ends up being portable simply doesn't
need to do it at all and can statically just not build it,
sidestepping the issue entirely.

Fingers crossed.

.. of course, I'm also sure some clueless hardware engineer is still
convinced that non-coherent IO is the way to go for graphics, and that
doing cross-CPU IPIs to write back all caches is somehow still a valid
model. Because some people were still convinced about that not _that_
long ago. Hopefully reality (perhaps in the form of Apple) has caused
people to finally reconsider.

 Linus


Re: [git pull] drm fixes + one missed next for 5.16-rc1

2021-11-14 Thread Dave Airlie
On Sat, 13 Nov 2021 at 06:16, Linus Torvalds
 wrote:
>
> On Thu, Nov 11, 2021 at 7:25 PM Dave Airlie  wrote:
> >
> > I missed a drm-misc-next pull for the main pull last week. It wasn't
> > that major and isn't the bulk of this at all. This has a bunch of
> > fixes all over, a lot for amdgpu and i915.
>
> Ugh.
>
> The i915 conflict was trivial, but made me aware of that absolutely
> disgusting "wbinvd_on_all_cpus()" hack.
>
> And that thing is much too ugly to survive. I made my merge resolution
> remove that disgusting thing.
>
> That driver is x86-only anyway, so it all seemed completely bogus in
> the first place.
>
> And if there is some actual non-x86 work in progress for i915, then
> that wbinvd_on_all_cpus() needs to be replaced with something proper
> and architecture-neutral anyway, most definitely involving a name
> change, and almost certainly also involving a range for the cache
> writeback.
>
> Because that "create broken macro on other architectures" thing is
> *NOT* acceptable.
>
> And I sincerely hope to the gods that no cache-incoherent i915 mess
> ever makes it out of the x86 world. Incoherent IO was always a
> historical mistake and should never ever happen again, so we should
> not spread that horrific pattern around.

i915 will no longer be x86-64 only in theory, since Intel now produces
PCIe graphics cards using the same hw designs. These shouldn't AFAIK
require the same incoherent architecture, though PCIe unsnooped
transactions are a thing in the real world.

The thing is the same driver needs to build/work for the integrated
and discrete cards, hence this hack, but I'm sure someone can Intel
can do better.

I'll leave it to Daniel to figure out who/how.

Dave.


[Bug 214921] amdgpu hangs HP Laptop on shutdown

2021-11-14 Thread bugzilla-daemon
https://bugzilla.kernel.org/show_bug.cgi?id=214921

spassw...@web.de changed:

   What|Removed |Added

 Kernel Version|5.15, 5.15.1|5.15, 5.15.1,
   ||5.15.0-next-2022

--- Comment #4 from spassw...@web.de ---
This still bug is still present in the 5.15.0-next-2022 where it breaks
suspend:

static int uvd_v6_0_suspend(void *handle)
{
int r;
struct amdgpu_device *adev = (struct amdgpu_device *)handle;

/*
 * Proper cleanups before halting the HW engine:
 *   - cancel the delayed idle work
 *   - enable powergating
 *   - enable clockgating
 *   - disable dpm
 *
 * TODO: to align with the VCN implementation, move the
 * jobs for clockgating/powergating/dpm setting to
 * ->set_powergating_state().
 */
#if 0
cancel_delayed_work_sync(>uvd.idle_work);

if (adev->pm.dpm_enabled) {
amdgpu_dpm_enable_uvd(adev, false);
} else {
amdgpu_asic_set_uvd_clocks(adev, 0, 0);
/* shutdown the UVD block */
amdgpu_device_ip_set_powergating_state(adev,
AMD_IP_BLOCK_TYPE_UVD,
   AMD_PG_STATE_GATE);
amdgpu_device_ip_set_clockgating_state(adev,
AMD_IP_BLOCK_TYPE_UVD,
   AMD_CG_STATE_GATE);
}
#endif

r = uvd_v6_0_hw_fini(adev);
if (r)
return r;

return amdgpu_uvd_suspend(adev);
}
This makes suspend work again.

-- 
You may reply to this email to add a comment.

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

[PATCH v1 2/2] drm/panel: sharp: lq101r1sx01: Support LQ101R1SX03

2021-11-14 Thread Dmitry Osipenko
From: Anton Bambura 

LQ101R1SX03 is compatible with LQ101R1SX01, add compatible to the driver.

Signed-off-by: Anton Bambura 
---
 drivers/gpu/drm/panel/panel-sharp-lq101r1sx01.c | 1 +
 1 file changed, 1 insertion(+)

diff --git a/drivers/gpu/drm/panel/panel-sharp-lq101r1sx01.c 
b/drivers/gpu/drm/panel/panel-sharp-lq101r1sx01.c
index f8cd2a42ed13..bbd1d889e069 100644
--- a/drivers/gpu/drm/panel/panel-sharp-lq101r1sx01.c
+++ b/drivers/gpu/drm/panel/panel-sharp-lq101r1sx01.c
@@ -304,6 +304,7 @@ static const struct drm_panel_funcs sharp_panel_funcs = {
 
 static const struct of_device_id sharp_of_match[] = {
{ .compatible = "sharp,lq101r1sx01", },
+   { .compatible = "sharp,lq101r1sx03", },
{ }
 };
 MODULE_DEVICE_TABLE(of, sharp_of_match);
-- 
2.33.1



[PATCH v1 0/2] Support Sharp LQ101R1SX03 display panel

2021-11-14 Thread Dmitry Osipenko
Add support for Sharp LQ101R1SX03 display panel used by ASUS Transformer
TF701T tablet device.

Anton Bambura (2):
  dt-bindings: sharp,lq101r1sx01: Add compatible for LQ101R1SX03
  drm/panel: sharp: lq101r1sx01: Support LQ101R1SX03

 .../devicetree/bindings/display/panel/sharp,lq101r1sx01.yaml  | 4 +++-
 drivers/gpu/drm/panel/panel-sharp-lq101r1sx01.c   | 1 +
 2 files changed, 4 insertions(+), 1 deletion(-)

-- 
2.33.1



[PATCH v1 1/2] dt-bindings: sharp, lq101r1sx01: Add compatible for LQ101R1SX03

2021-11-14 Thread Dmitry Osipenko
From: Anton Bambura 

LQ101R1SX03 is compatible with LQ101R1SX01, document it.

Signed-off-by: Anton Bambura 
---
 .../devicetree/bindings/display/panel/sharp,lq101r1sx01.yaml  | 4 +++-
 1 file changed, 3 insertions(+), 1 deletion(-)

diff --git 
a/Documentation/devicetree/bindings/display/panel/sharp,lq101r1sx01.yaml 
b/Documentation/devicetree/bindings/display/panel/sharp,lq101r1sx01.yaml
index a679d3647dbd..f7514eb9ebda 100644
--- a/Documentation/devicetree/bindings/display/panel/sharp,lq101r1sx01.yaml
+++ b/Documentation/devicetree/bindings/display/panel/sharp,lq101r1sx01.yaml
@@ -30,7 +30,9 @@ allOf:
 
 properties:
   compatible:
-const: sharp,lq101r1sx01
+enum:
+  - sharp,lq101r1sx01
+  - sharp,lq101r1sx03
 
   reg: true
   power-supply: true
-- 
2.33.1



[PATCH v1 0/2] Support HannStar HSD101PWW2 display panel

2021-11-14 Thread Dmitry Osipenko
Add support for HannStar HSD101PWW2 display panel used by ASUS Transformer
TF201T tablet device.

Svyatoslav Ryhel (2):
  dt-bindings: display: simple: Add HannStar HSD101PWW2
  drm/panel: simple: Add support for HannStar HSD101PWW2 panel

 .../bindings/display/panel/panel-simple.yaml  |  2 ++
 drivers/gpu/drm/panel/panel-simple.c  | 28 +++
 2 files changed, 30 insertions(+)

-- 
2.33.1



[PATCH v1 1/2] dt-bindings: display: simple: Add HannStar HSD101PWW2

2021-11-14 Thread Dmitry Osipenko
From: Svyatoslav Ryhel 

Add HannStar HSD101PWW2 10.1" WXGA (1280x800) TFT-LCD LVDS panel
to the list of compatibles.

Signed-off-by: Svyatoslav Ryhel 
---
 .../devicetree/bindings/display/panel/panel-simple.yaml | 2 ++
 1 file changed, 2 insertions(+)

diff --git a/Documentation/devicetree/bindings/display/panel/panel-simple.yaml 
b/Documentation/devicetree/bindings/display/panel/panel-simple.yaml
index f3c9395d23b6..ecb9a79c2e78 100644
--- a/Documentation/devicetree/bindings/display/panel/panel-simple.yaml
+++ b/Documentation/devicetree/bindings/display/panel/panel-simple.yaml
@@ -156,6 +156,8 @@ properties:
   - hannstar,hsd070pww1
 # HannStar Display Corp. HSD100PXN1 10.1" XGA LVDS panel
   - hannstar,hsd100pxn1
+# HannStar Display Corp. HSD101PWW2 10.1" WXGA (1280x800) LVDS panel
+  - hannstar,hsd101pww2
 # Hitachi Ltd. Corporation 9" WVGA (800x480) TFT LCD panel
   - hit,tx23d38vm0caa
 # InfoVision Optoelectronics M133NWF4 R0 13.3" FHD (1920x1080) TFT LCD 
panel
-- 
2.33.1



[PATCH v1 2/2] drm/panel: simple: Add support for HannStar HSD101PWW2 panel

2021-11-14 Thread Dmitry Osipenko
From: Svyatoslav Ryhel 

Add definition of the HannStar HSD101PWW2 Rev0-A00/A01 LCD
SuperIPS+ HD panel.

Signed-off-by: Svyatoslav Ryhel 
---
 drivers/gpu/drm/panel/panel-simple.c | 28 
 1 file changed, 28 insertions(+)

diff --git a/drivers/gpu/drm/panel/panel-simple.c 
b/drivers/gpu/drm/panel/panel-simple.c
index eb475a3a774b..8b7033048f83 100644
--- a/drivers/gpu/drm/panel/panel-simple.c
+++ b/drivers/gpu/drm/panel/panel-simple.c
@@ -1927,6 +1927,31 @@ static const struct panel_desc hannstar_hsd100pxn1 = {
.connector_type = DRM_MODE_CONNECTOR_LVDS,
 };
 
+static const struct display_timing hannstar_hsd101pww2_timing = {
+   .pixelclock = { 6430, 7110, 8200 },
+   .hactive = { 1280, 1280, 1280 },
+   .hfront_porch = { 1, 1, 10 },
+   .hback_porch = { 1, 1, 10 },
+   .hsync_len = { 58, 158, 661 },
+   .vactive = { 800, 800, 800 },
+   .vfront_porch = { 1, 1, 10 },
+   .vback_porch = { 1, 1, 10 },
+   .vsync_len = { 1, 21, 203 },
+   .flags = DISPLAY_FLAGS_DE_HIGH,
+};
+
+static const struct panel_desc hannstar_hsd101pww2 = {
+   .timings = _hsd101pww2_timing,
+   .num_timings = 1,
+   .bpc = 8,
+   .size = {
+   .width = 217,
+   .height = 136,
+   },
+   .bus_format = MEDIA_BUS_FMT_RGB888_1X7X4_SPWG,
+   .connector_type = DRM_MODE_CONNECTOR_LVDS,
+};
+
 static const struct drm_display_mode hitachi_tx23d38vm0caa_mode = {
.clock = 3,
.hdisplay = 800,
@@ -3725,6 +3750,9 @@ static const struct of_device_id platform_of_match[] = {
}, {
.compatible = "hannstar,hsd100pxn1",
.data = _hsd100pxn1,
+   }, {
+   .compatible = "hannstar,hsd101pww2",
+   .data = _hsd101pww2,
}, {
.compatible = "hit,tx23d38vm0caa",
.data = _tx23d38vm0caa
-- 
2.33.1



[PATCH v15 14/39] drm/tegra: vic: Stop channel on suspend

2021-11-14 Thread Dmitry Osipenko
CDMA must be stopped before hardware is suspended. Add channel stopping
to RPM suspend callback. Add system level suspend-resume callbacks.

Runtime PM initialization is moved to host1x client init phase because
RPM callback now uses host1x channel that is available only when host1x
client is registered.

Reviewed-by: Ulf Hansson 
Signed-off-by: Dmitry Osipenko 
---
 drivers/gpu/drm/tegra/vic.c | 36 ++--
 1 file changed, 18 insertions(+), 18 deletions(-)

diff --git a/drivers/gpu/drm/tegra/vic.c b/drivers/gpu/drm/tegra/vic.c
index b58e2b99f81a..9622ca96c539 100644
--- a/drivers/gpu/drm/tegra/vic.c
+++ b/drivers/gpu/drm/tegra/vic.c
@@ -151,9 +151,13 @@ static int vic_init(struct host1x_client *client)
goto free_channel;
}
 
+   pm_runtime_enable(client->dev);
+   pm_runtime_use_autosuspend(client->dev);
+   pm_runtime_set_autosuspend_delay(client->dev, 500);
+
err = tegra_drm_register_client(tegra, drm);
if (err < 0)
-   goto free_syncpt;
+   goto disable_rpm;
 
/*
 * Inherit the DMA parameters (such as maximum segment size) from the
@@ -163,7 +167,10 @@ static int vic_init(struct host1x_client *client)
 
return 0;
 
-free_syncpt:
+disable_rpm:
+   pm_runtime_dont_use_autosuspend(client->dev);
+   pm_runtime_force_suspend(client->dev);
+
host1x_syncpt_put(client->syncpts[0]);
 free_channel:
host1x_channel_put(vic->channel);
@@ -188,10 +195,15 @@ static int vic_exit(struct host1x_client *client)
if (err < 0)
return err;
 
+   pm_runtime_dont_use_autosuspend(client->dev);
+   pm_runtime_force_suspend(client->dev);
+
host1x_syncpt_put(client->syncpts[0]);
host1x_channel_put(vic->channel);
host1x_client_iommu_detach(client);
 
+   vic->channel = NULL;
+
if (client->group) {
dma_unmap_single(vic->dev, vic->falcon.firmware.phys,
 vic->falcon.firmware.size, DMA_TO_DEVICE);
@@ -315,6 +327,8 @@ static int vic_runtime_suspend(struct device *dev)
struct vic *vic = dev_get_drvdata(dev);
int err;
 
+   host1x_channel_stop(vic->channel);
+
err = reset_control_assert(vic->rst);
if (err < 0)
return err;
@@ -482,19 +496,8 @@ static int vic_probe(struct platform_device *pdev)
goto exit_falcon;
}
 
-   pm_runtime_enable(>dev);
-   if (!pm_runtime_enabled(>dev)) {
-   err = vic_runtime_resume(>dev);
-   if (err < 0)
-   goto unregister_client;
-   }
-   pm_runtime_set_autosuspend_delay(>dev, 500);
-   pm_runtime_use_autosuspend(>dev);
-
return 0;
 
-unregister_client:
-   host1x_client_unregister(>client.base);
 exit_falcon:
falcon_exit(>falcon);
 
@@ -513,11 +516,6 @@ static int vic_remove(struct platform_device *pdev)
return err;
}
 
-   if (pm_runtime_enabled(>dev))
-   pm_runtime_disable(>dev);
-   else
-   vic_runtime_suspend(>dev);
-
falcon_exit(>falcon);
 
return 0;
@@ -525,6 +523,8 @@ static int vic_remove(struct platform_device *pdev)
 
 static const struct dev_pm_ops vic_pm_ops = {
SET_RUNTIME_PM_OPS(vic_runtime_suspend, vic_runtime_resume, NULL)
+   SET_SYSTEM_SLEEP_PM_OPS(pm_runtime_force_suspend,
+   pm_runtime_force_resume)
 };
 
 struct platform_driver tegra_vic_driver = {
-- 
2.33.1



[PATCH v15 36/39] ARM: tegra: Add OPP tables and power domains to Tegra30 device-trees

2021-11-14 Thread Dmitry Osipenko
Add OPP tables and power domains to all peripheral devices which
support power management on Tegra30 SoC.

Tested-by: Peter Geis  # Ouya T30
Tested-by: Matt Merhar  # Ouya T30
Signed-off-by: Dmitry Osipenko 
---
 arch/arm/boot/dts/tegra20-trimslice.dts   |2 +-
 .../tegra30-asus-nexus7-grouper-common.dtsi   |1 +
 arch/arm/boot/dts/tegra30-beaver.dts  |1 +
 arch/arm/boot/dts/tegra30-cardhu.dtsi |1 +
 arch/arm/boot/dts/tegra30-colibri.dtsi|   17 +-
 arch/arm/boot/dts/tegra30-ouya.dts|1 +
 .../arm/boot/dts/tegra30-peripherals-opp.dtsi | 1227 -
 arch/arm/boot/dts/tegra30.dtsi|  153 ++
 8 files changed, 1398 insertions(+), 5 deletions(-)

diff --git a/arch/arm/boot/dts/tegra20-trimslice.dts 
b/arch/arm/boot/dts/tegra20-trimslice.dts
index 306e5f33e7f8..7646a4a1f2be 100644
--- a/arch/arm/boot/dts/tegra20-trimslice.dts
+++ b/arch/arm/boot/dts/tegra20-trimslice.dts
@@ -445,7 +445,7 @@ pci_vdd_reg: regulator-pcivdd {
regulator-always-on;
};
 
-   vdd_core: regulator@5 {
+   vdd_core: regulator-core {
compatible = "regulator-fixed";
regulator-name = "vdd_core";
regulator-min-microvolt = <130>;
diff --git a/arch/arm/boot/dts/tegra30-asus-nexus7-grouper-common.dtsi 
b/arch/arm/boot/dts/tegra30-asus-nexus7-grouper-common.dtsi
index e6aed19a5f3b..e7a3327e603c 100644
--- a/arch/arm/boot/dts/tegra30-asus-nexus7-grouper-common.dtsi
+++ b/arch/arm/boot/dts/tegra30-asus-nexus7-grouper-common.dtsi
@@ -980,6 +980,7 @@ pmc@7000e400 {
nvidia,core-pwr-off-time = <0>;
nvidia,core-power-req-active-high;
nvidia,sys-clock-req-active-high;
+   core-supply = <_core>;
};
 
ahub@7008 {
diff --git a/arch/arm/boot/dts/tegra30-beaver.dts 
b/arch/arm/boot/dts/tegra30-beaver.dts
index 2ec5e47d9623..24de27a8594e 100644
--- a/arch/arm/boot/dts/tegra30-beaver.dts
+++ b/arch/arm/boot/dts/tegra30-beaver.dts
@@ -1915,6 +1915,7 @@ pmc@7000e400 {
nvidia,core-pwr-off-time = <0>;
nvidia,core-power-req-active-high;
nvidia,sys-clock-req-active-high;
+   core-supply = <_vdd_reg>;
};
 
ahub@7008 {
diff --git a/arch/arm/boot/dts/tegra30-cardhu.dtsi 
b/arch/arm/boot/dts/tegra30-cardhu.dtsi
index d2f6121049a4..506cb747b2db 100644
--- a/arch/arm/boot/dts/tegra30-cardhu.dtsi
+++ b/arch/arm/boot/dts/tegra30-cardhu.dtsi
@@ -391,6 +391,7 @@ pmc@7000e400 {
nvidia,core-pwr-off-time = <0>;
nvidia,core-power-req-active-high;
nvidia,sys-clock-req-active-high;
+   core-supply = <_core>;
};
 
ahub@7008 {
diff --git a/arch/arm/boot/dts/tegra30-colibri.dtsi 
b/arch/arm/boot/dts/tegra30-colibri.dtsi
index 413e35215804..0627b64f044d 100644
--- a/arch/arm/boot/dts/tegra30-colibri.dtsi
+++ b/arch/arm/boot/dts/tegra30-colibri.dtsi
@@ -765,9 +765,14 @@ vdd1_reg: vdd1 {
 
vddctrl_reg: vddctrl {
regulator-name = "+V1.0_VDD_CPU";
-   regulator-min-microvolt = <115>;
-   regulator-max-microvolt = <115>;
+   regulator-min-microvolt = <80>;
+   regulator-max-microvolt = <125>;
+   regulator-coupled-with = <_core>;
+   regulator-coupled-max-spread = <30>;
+   regulator-max-step-microvolt = <10>;
regulator-always-on;
+
+   nvidia,tegra-cpu-regulator;
};
 
reg_1v8_vio: vio {
@@ -890,18 +895,23 @@ temp-sensor@4c {
};
 
/* SW: +V1.2_VDD_CORE */
-   regulator@60 {
+   vdd_core: regulator@60 {
compatible = "ti,tps62362";
reg = <0x60>;
 
regulator-name = "tps62362-vout";
regulator-min-microvolt = <90>;
regulator-max-microvolt = <140>;
+   regulator-coupled-with = <_reg>;
+   regulator-coupled-max-spread = <30>;
+   regulator-max-step-microvolt = <10>;
regulator-boot-on;
regulator-always-on;
ti,vsel0-state-low;
/* VSEL1: EN_CORE_DVFS_N low for DVFS */
ti,vsel1-state-low;
+
+   nvidia,tegra-core-regulator;
};
};
 
@@ -914,6 +924,7 @@ pmc@7000e400 {
nvidia,core-pwr-off-time = <0>;
 

[PATCH v15 34/39] ARM: tegra: Add 500MHz entry to Tegra30 memory OPP table

2021-11-14 Thread Dmitry Osipenko
Extend memory OPPs with 500MHz entry. This clock rate is used by ASUS
Transformer tablets.

Signed-off-by: Dmitry Osipenko 
---
 arch/arm/boot/dts/tegra30-peripherals-opp.dtsi | 18 ++
 1 file changed, 18 insertions(+)

diff --git a/arch/arm/boot/dts/tegra30-peripherals-opp.dtsi 
b/arch/arm/boot/dts/tegra30-peripherals-opp.dtsi
index ff25350869b3..af9640401402 100644
--- a/arch/arm/boot/dts/tegra30-peripherals-opp.dtsi
+++ b/arch/arm/boot/dts/tegra30-peripherals-opp.dtsi
@@ -216,6 +216,18 @@ opp-45000-1250 {
opp-supported-hw = <0x0008>;
};
 
+   opp-5-1200 {
+   opp-microvolt = <120 120 135>;
+   opp-hz = /bits/ 64 <5>;
+   opp-supported-hw = <0x0007>;
+   };
+
+   opp-5-1250 {
+   opp-microvolt = <125 125 135>;
+   opp-hz = /bits/ 64 <5>;
+   opp-supported-hw = <0x0008>;
+   };
+
opp-53300-1200 {
opp-microvolt = <120 120 135>;
opp-hz = /bits/ 64 <53300>;
@@ -347,6 +359,12 @@ opp-45000 {
opp-peak-kBps = <360>;
};
 
+   opp-5 {
+   opp-hz = /bits/ 64 <5>;
+   opp-supported-hw = <0x000F>;
+   opp-peak-kBps = <400>;
+   };
+
opp-53300 {
opp-hz = /bits/ 64 <53300>;
opp-supported-hw = <0x000F>;
-- 
2.33.1



[PATCH v15 39/39] ARM: tegra20/30: Disable unused host1x hardware

2021-11-14 Thread Dmitry Osipenko
MPE, VI, EPP and ISP were never used and we don't have drivers for them.
Since these modules are enabled by default in a device-tree, a device is
created for them, blocking voltage scaling because there is no driver to
bind, and thus, state of PMC driver is never synced. Disable them.

Signed-off-by: Dmitry Osipenko 
---
 arch/arm/boot/dts/tegra20.dtsi | 4 
 arch/arm/boot/dts/tegra30.dtsi | 8 
 2 files changed, 12 insertions(+)

diff --git a/arch/arm/boot/dts/tegra20.dtsi b/arch/arm/boot/dts/tegra20.dtsi
index 7b69ffc57abe..8010b40d7377 100644
--- a/arch/arm/boot/dts/tegra20.dtsi
+++ b/arch/arm/boot/dts/tegra20.dtsi
@@ -59,6 +59,7 @@ mpe@5404 {
reset-names = "mpe";
power-domains = <_mpe>;
operating-points-v2 = <_dvfs_opp_table>;
+   status = "disabled";
};
 
vi@5408 {
@@ -70,6 +71,7 @@ vi@5408 {
reset-names = "vi";
power-domains = <_venc>;
operating-points-v2 = <_dvfs_opp_table>;
+   status = "disabled";
};
 
epp@540c {
@@ -81,6 +83,7 @@ epp@540c {
reset-names = "epp";
power-domains = <_core>;
operating-points-v2 = <_dvfs_opp_table>;
+   status = "disabled";
};
 
isp@5410 {
@@ -91,6 +94,7 @@ isp@5410 {
resets = <_car 23>;
reset-names = "isp";
power-domains = <_venc>;
+   status = "disabled";
};
 
gr2d@5414 {
diff --git a/arch/arm/boot/dts/tegra30.dtsi b/arch/arm/boot/dts/tegra30.dtsi
index c1be136aac7d..d961ce3761e6 100644
--- a/arch/arm/boot/dts/tegra30.dtsi
+++ b/arch/arm/boot/dts/tegra30.dtsi
@@ -145,6 +145,8 @@ mpe@5404 {
operating-points-v2 = <_dvfs_opp_table>;
 
iommus = < TEGRA_SWGROUP_MPE>;
+
+   status = "disabled";
};
 
vi@5408 {
@@ -158,6 +160,8 @@ vi@5408 {
operating-points-v2 = <_dvfs_opp_table>;
 
iommus = < TEGRA_SWGROUP_VI>;
+
+   status = "disabled";
};
 
epp@540c {
@@ -171,6 +175,8 @@ epp@540c {
operating-points-v2 = <_dvfs_opp_table>;
 
iommus = < TEGRA_SWGROUP_EPP>;
+
+   status = "disabled";
};
 
isp@5410 {
@@ -183,6 +189,8 @@ isp@5410 {
power-domains = <_venc>;
 
iommus = < TEGRA_SWGROUP_ISP>;
+
+   status = "disabled";
};
 
gr2d@5414 {
-- 
2.33.1



[PATCH v15 37/39] ARM: tegra: Add Memory Client resets to Tegra20 GR2D, GR3D and Host1x

2021-11-14 Thread Dmitry Osipenko
Memory access must be blocked before hardware reset is asserted and before
power is gated, otherwise a serious hardware fault is inevitable. Add
reset for memory clients to the GR2D, GR3D and Host1x nodes.

Tested-by: Paul Fertser  # PAZ00 T20
Tested-by: Nicolas Chauvet  # PAZ00 T20
Signed-off-by: Dmitry Osipenko 
---
 arch/arm/boot/dts/tegra20.dtsi | 12 ++--
 1 file changed, 6 insertions(+), 6 deletions(-)

diff --git a/arch/arm/boot/dts/tegra20.dtsi b/arch/arm/boot/dts/tegra20.dtsi
index 1898351a099f..7b69ffc57abe 100644
--- a/arch/arm/boot/dts/tegra20.dtsi
+++ b/arch/arm/boot/dts/tegra20.dtsi
@@ -40,8 +40,8 @@ host1x@5000 {
interrupt-names = "syncpt", "host1x";
clocks = <_car TEGRA20_CLK_HOST1X>;
clock-names = "host1x";
-   resets = <_car 28>;
-   reset-names = "host1x";
+   resets = <_car 28>, < TEGRA20_MC_RESET_HC>;
+   reset-names = "host1x", "mc";
power-domains = <_core>;
operating-points-v2 = <_dvfs_opp_table>;
 
@@ -98,8 +98,8 @@ gr2d@5414 {
reg = <0x5414 0x0004>;
interrupts = ;
clocks = <_car TEGRA20_CLK_GR2D>;
-   resets = <_car 21>;
-   reset-names = "2d";
+   resets = <_car 21>, < TEGRA20_MC_RESET_2D>;
+   reset-names = "2d", "mc";
power-domains = <_core>;
operating-points-v2 = <_dvfs_opp_table>;
};
@@ -108,8 +108,8 @@ gr3d@5418 {
compatible = "nvidia,tegra20-gr3d";
reg = <0x5418 0x0004>;
clocks = <_car TEGRA20_CLK_GR3D>;
-   resets = <_car 24>;
-   reset-names = "3d";
+   resets = <_car 24>, < TEGRA20_MC_RESET_3D>;
+   reset-names = "3d", "mc";
power-domains = <_3d>;
operating-points-v2 = <_dvfs_opp_table>;
};
-- 
2.33.1



[PATCH v15 23/39] spi: tegra20-slink: Add OPP support

2021-11-14 Thread Dmitry Osipenko
The SPI on Tegra belongs to the core power domain and we're going to
enable GENPD support for the core domain. Now SPI driver must use OPP
API for driving the controller's clock rate because OPP API takes care
of reconfiguring the domain's performance state in accordance to the
rate. Add OPP support to the driver.

Acked-by: Mark Brown 
Reviewed-by: Ulf Hansson 
Signed-off-by: Dmitry Osipenko 
---
 drivers/spi/spi-tegra20-slink.c | 9 -
 1 file changed, 8 insertions(+), 1 deletion(-)

diff --git a/drivers/spi/spi-tegra20-slink.c b/drivers/spi/spi-tegra20-slink.c
index e8204e155484..2a03739a0c60 100644
--- a/drivers/spi/spi-tegra20-slink.c
+++ b/drivers/spi/spi-tegra20-slink.c
@@ -18,12 +18,15 @@
 #include 
 #include 
 #include 
+#include 
 #include 
 #include 
 #include 
 #include 
 #include 
 
+#include 
+
 #define SLINK_COMMAND  0x000
 #define SLINK_BIT_LENGTH(x)(((x) & 0x1f) << 0)
 #define SLINK_WORD_SIZE(x) (((x) & 0x1f) << 5)
@@ -680,7 +683,7 @@ static int tegra_slink_start_transfer_one(struct spi_device 
*spi,
bits_per_word = t->bits_per_word;
speed = t->speed_hz;
if (speed != tspi->cur_speed) {
-   clk_set_rate(tspi->clk, speed * 4);
+   dev_pm_opp_set_rate(tspi->dev, speed * 4);
tspi->cur_speed = speed;
}
 
@@ -1066,6 +1069,10 @@ static int tegra_slink_probe(struct platform_device 
*pdev)
goto exit_free_master;
}
 
+   ret = devm_tegra_core_dev_init_opp_table_common(>dev);
+   if (ret)
+   goto exit_free_master;
+
tspi->max_buf_size = SLINK_FIFO_DEPTH << 2;
tspi->dma_buf_size = DEFAULT_SPI_DMA_BUF_LEN;
 
-- 
2.33.1



[PATCH v15 30/39] soc/tegra: pmc: Rename 3d power domains

2021-11-14 Thread Dmitry Osipenko
Device-tree schema doesn't allow domain name to start with a number.
We don't use 3d domain yet in device-trees, so rename it to the name
used by Tegra TRMs: TD, TD2.

Reported-by: David Heidelberg 
Reviewed-by: Ulf Hansson 
Signed-off-by: Dmitry Osipenko 
---
 drivers/soc/tegra/pmc.c | 8 
 1 file changed, 4 insertions(+), 4 deletions(-)

diff --git a/drivers/soc/tegra/pmc.c b/drivers/soc/tegra/pmc.c
index 1a55b8319d63..e1fae1a5e36a 100644
--- a/drivers/soc/tegra/pmc.c
+++ b/drivers/soc/tegra/pmc.c
@@ -2992,7 +2992,7 @@ static SIMPLE_DEV_PM_OPS(tegra_pmc_pm_ops, 
tegra_pmc_suspend, tegra_pmc_resume);
 
 static const char * const tegra20_powergates[] = {
[TEGRA_POWERGATE_CPU] = "cpu",
-   [TEGRA_POWERGATE_3D] = "3d",
+   [TEGRA_POWERGATE_3D] = "td",
[TEGRA_POWERGATE_VENC] = "venc",
[TEGRA_POWERGATE_VDEC] = "vdec",
[TEGRA_POWERGATE_PCIE] = "pcie",
@@ -3100,7 +3100,7 @@ static const struct tegra_pmc_soc tegra20_pmc_soc = {
 
 static const char * const tegra30_powergates[] = {
[TEGRA_POWERGATE_CPU] = "cpu0",
-   [TEGRA_POWERGATE_3D] = "3d0",
+   [TEGRA_POWERGATE_3D] = "td",
[TEGRA_POWERGATE_VENC] = "venc",
[TEGRA_POWERGATE_VDEC] = "vdec",
[TEGRA_POWERGATE_PCIE] = "pcie",
@@ -3112,7 +3112,7 @@ static const char * const tegra30_powergates[] = {
[TEGRA_POWERGATE_CPU2] = "cpu2",
[TEGRA_POWERGATE_CPU3] = "cpu3",
[TEGRA_POWERGATE_CELP] = "celp",
-   [TEGRA_POWERGATE_3D1] = "3d1",
+   [TEGRA_POWERGATE_3D1] = "td2",
 };
 
 static const u8 tegra30_cpu_powergates[] = {
@@ -3161,7 +3161,7 @@ static const struct tegra_pmc_soc tegra30_pmc_soc = {
 
 static const char * const tegra114_powergates[] = {
[TEGRA_POWERGATE_CPU] = "crail",
-   [TEGRA_POWERGATE_3D] = "3d",
+   [TEGRA_POWERGATE_3D] = "td",
[TEGRA_POWERGATE_VENC] = "venc",
[TEGRA_POWERGATE_VDEC] = "vdec",
[TEGRA_POWERGATE_MPE] = "mpe",
-- 
2.33.1



[PATCH v15 38/39] ARM: tegra: Add Memory Client resets to Tegra30 GR2D, GR3D and Host1x

2021-11-14 Thread Dmitry Osipenko
Memory access must be blocked before hardware reset is asserted and before
power is gated, otherwise a serious hardware fault is inevitable. Add
reset for memory clients to the GR2D, GR3D and Host1x nodes.

Tested-by: Peter Geis  # Ouya T30
Tested-by: Matt Merhar  # Ouya T30
Signed-off-by: Dmitry Osipenko 
---
 arch/arm/boot/dts/tegra30.dtsi | 14 --
 1 file changed, 8 insertions(+), 6 deletions(-)

diff --git a/arch/arm/boot/dts/tegra30.dtsi b/arch/arm/boot/dts/tegra30.dtsi
index e40d5563778b..c1be136aac7d 100644
--- a/arch/arm/boot/dts/tegra30.dtsi
+++ b/arch/arm/boot/dts/tegra30.dtsi
@@ -123,8 +123,8 @@ host1x@5000 {
interrupt-names = "syncpt", "host1x";
clocks = <_car TEGRA30_CLK_HOST1X>;
clock-names = "host1x";
-   resets = <_car 28>;
-   reset-names = "host1x";
+   resets = <_car 28>, < TEGRA30_MC_RESET_HC>;
+   reset-names = "host1x", "mc";
iommus = < TEGRA_SWGROUP_HC>;
power-domains = <_heg>;
operating-points-v2 = <_dvfs_opp_table>;
@@ -190,8 +190,8 @@ gr2d@5414 {
reg = <0x5414 0x0004>;
interrupts = ;
clocks = <_car TEGRA30_CLK_GR2D>;
-   resets = <_car 21>;
-   reset-names = "2d";
+   resets = <_car 21>, < TEGRA30_MC_RESET_2D>;
+   reset-names = "2d", "mc";
power-domains = <_heg>;
operating-points-v2 = <_dvfs_opp_table>;
 
@@ -205,8 +205,10 @@ gr3d@5418 {
 <_car TEGRA30_CLK_GR3D2>;
clock-names = "3d", "3d2";
resets = <_car 24>,
-<_car 98>;
-   reset-names = "3d", "3d2";
+<_car 98>,
+< TEGRA30_MC_RESET_3D>,
+< TEGRA30_MC_RESET_3D2>;
+   reset-names = "3d", "3d2", "mc", "mc2";
power-domains = <_3d0>, <_3d1>;
power-domain-names = "3d0", "3d1";
operating-points-v2 = <_dvfs_opp_table>;
-- 
2.33.1



[PATCH v15 22/39] mtd: rawnand: tegra: Add runtime PM and OPP support

2021-11-14 Thread Dmitry Osipenko
The NAND on Tegra belongs to the core power domain and we're going to
enable GENPD support for the core domain. Now NAND must be resumed using
runtime PM API in order to initialize the NAND power state. Add runtime PM
and OPP support to the NAND driver.

Reviewed-by: Ulf Hansson 
Acked-by: Miquel Raynal 
Signed-off-by: Dmitry Osipenko 
---
 drivers/mtd/nand/raw/tegra_nand.c | 58 ++-
 1 file changed, 50 insertions(+), 8 deletions(-)

diff --git a/drivers/mtd/nand/raw/tegra_nand.c 
b/drivers/mtd/nand/raw/tegra_nand.c
index 32431bbe69b8..b36e5260ae27 100644
--- a/drivers/mtd/nand/raw/tegra_nand.c
+++ b/drivers/mtd/nand/raw/tegra_nand.c
@@ -17,8 +17,11 @@
 #include 
 #include 
 #include 
+#include 
 #include 
 
+#include 
+
 #define COMMAND0x00
 #define   COMMAND_GO   BIT(31)
 #define   COMMAND_CLE  BIT(30)
@@ -1151,6 +1154,7 @@ static int tegra_nand_probe(struct platform_device *pdev)
return -ENOMEM;
 
ctrl->dev = >dev;
+   platform_set_drvdata(pdev, ctrl);
nand_controller_init(>controller);
ctrl->controller.ops = _nand_controller_ops;
 
@@ -1166,14 +1170,23 @@ static int tegra_nand_probe(struct platform_device 
*pdev)
if (IS_ERR(ctrl->clk))
return PTR_ERR(ctrl->clk);
 
-   err = clk_prepare_enable(ctrl->clk);
+   err = devm_tegra_core_dev_init_opp_table_common(>dev);
+   if (err)
+   return err;
+
+   /*
+* This driver doesn't support active power management yet,
+* so we will simply keep device resumed.
+*/
+   pm_runtime_enable(>dev);
+   err = pm_runtime_resume_and_get(>dev);
if (err)
return err;
 
err = reset_control_reset(rst);
if (err) {
dev_err(ctrl->dev, "Failed to reset HW: %d\n", err);
-   goto err_disable_clk;
+   goto err_put_pm;
}
 
writel_relaxed(HWSTATUS_CMD_DEFAULT, ctrl->regs + HWSTATUS_CMD);
@@ -1188,21 +1201,20 @@ static int tegra_nand_probe(struct platform_device 
*pdev)
   dev_name(>dev), ctrl);
if (err) {
dev_err(ctrl->dev, "Failed to get IRQ: %d\n", err);
-   goto err_disable_clk;
+   goto err_put_pm;
}
 
writel_relaxed(DMA_MST_CTRL_IS_DONE, ctrl->regs + DMA_MST_CTRL);
 
err = tegra_nand_chips_init(ctrl->dev, ctrl);
if (err)
-   goto err_disable_clk;
-
-   platform_set_drvdata(pdev, ctrl);
+   goto err_put_pm;
 
return 0;
 
-err_disable_clk:
-   clk_disable_unprepare(ctrl->clk);
+err_put_pm:
+   pm_runtime_put_sync_suspend(ctrl->dev);
+   pm_runtime_force_suspend(ctrl->dev);
return err;
 }
 
@@ -1219,11 +1231,40 @@ static int tegra_nand_remove(struct platform_device 
*pdev)
 
nand_cleanup(chip);
 
+   pm_runtime_put_sync_suspend(ctrl->dev);
+   pm_runtime_force_suspend(ctrl->dev);
+
+   return 0;
+}
+
+static int __maybe_unused tegra_nand_runtime_resume(struct device *dev)
+{
+   struct tegra_nand_controller *ctrl = dev_get_drvdata(dev);
+   int err;
+
+   err = clk_prepare_enable(ctrl->clk);
+   if (err) {
+   dev_err(dev, "Failed to enable clock: %d\n", err);
+   return err;
+   }
+
+   return 0;
+}
+
+static int __maybe_unused tegra_nand_runtime_suspend(struct device *dev)
+{
+   struct tegra_nand_controller *ctrl = dev_get_drvdata(dev);
+
clk_disable_unprepare(ctrl->clk);
 
return 0;
 }
 
+static const struct dev_pm_ops tegra_nand_pm = {
+   SET_RUNTIME_PM_OPS(tegra_nand_runtime_suspend, 
tegra_nand_runtime_resume,
+  NULL)
+};
+
 static const struct of_device_id tegra_nand_of_match[] = {
{ .compatible = "nvidia,tegra20-nand" },
{ /* sentinel */ }
@@ -1234,6 +1275,7 @@ static struct platform_driver tegra_nand_driver = {
.driver = {
.name = "tegra-nand",
.of_match_table = tegra_nand_of_match,
+   .pm = _nand_pm,
},
.probe = tegra_nand_probe,
.remove = tegra_nand_remove,
-- 
2.33.1



[PATCH v15 35/39] ARM: tegra: Add OPP tables and power domains to Tegra20 device-trees

2021-11-14 Thread Dmitry Osipenko
Add OPP tables and power domains to all peripheral devices which
support power management on Tegra20 SoC.

Tested-by: Paul Fertser  # PAZ00 T20
Tested-by: Nicolas Chauvet  # PAZ00 T20
Signed-off-by: Dmitry Osipenko 
---
 .../boot/dts/tegra20-acer-a500-picasso.dts|   1 +
 arch/arm/boot/dts/tegra20-colibri.dtsi|   3 +-
 arch/arm/boot/dts/tegra20-harmony.dts |   3 +-
 arch/arm/boot/dts/tegra20-paz00.dts   |   1 +
 .../arm/boot/dts/tegra20-peripherals-opp.dtsi | 913 ++
 arch/arm/boot/dts/tegra20-seaboard.dts|   3 +-
 arch/arm/boot/dts/tegra20-tamonten.dtsi   |   3 +-
 arch/arm/boot/dts/tegra20-trimslice.dts   |   9 +
 arch/arm/boot/dts/tegra20-ventana.dts |   1 +
 arch/arm/boot/dts/tegra20.dtsi| 102 +-
 10 files changed, 1034 insertions(+), 5 deletions(-)

diff --git a/arch/arm/boot/dts/tegra20-acer-a500-picasso.dts 
b/arch/arm/boot/dts/tegra20-acer-a500-picasso.dts
index e1b33d25b6e0..db388ddd062f 100644
--- a/arch/arm/boot/dts/tegra20-acer-a500-picasso.dts
+++ b/arch/arm/boot/dts/tegra20-acer-a500-picasso.dts
@@ -716,6 +716,7 @@ pmc@7000e400 {
nvidia,core-pwr-good-time = <3845 3845>;
nvidia,core-pwr-off-time = <458>;
nvidia,sys-clock-req-active-high;
+   core-supply = <_core>;
};
 
usb@c500 {
diff --git a/arch/arm/boot/dts/tegra20-colibri.dtsi 
b/arch/arm/boot/dts/tegra20-colibri.dtsi
index 3f9cb5cd6bd8..eb5b3feb5907 100644
--- a/arch/arm/boot/dts/tegra20-colibri.dtsi
+++ b/arch/arm/boot/dts/tegra20-colibri.dtsi
@@ -495,7 +495,7 @@ reg_3v3_vsys: sys {
regulator-always-on;
};
 
-   sm0 {
+   vdd_core: sm0 {
regulator-name = "VDD_CORE_1.2V";
regulator-min-microvolt = <120>;
regulator-max-microvolt = <120>;
@@ -601,6 +601,7 @@ pmc@7000e400 {
nvidia,core-pwr-good-time = <3845 3845>;
nvidia,core-pwr-off-time = <3875>;
nvidia,sys-clock-req-active-high;
+   core-supply = <_core>;
 
/* Set SLEEP MODE bit in SUPPLYENE register of TPS658643 PMIC */
i2c-thermtrip {
diff --git a/arch/arm/boot/dts/tegra20-harmony.dts 
b/arch/arm/boot/dts/tegra20-harmony.dts
index a8494378c382..b4cc88b0f130 100644
--- a/arch/arm/boot/dts/tegra20-harmony.dts
+++ b/arch/arm/boot/dts/tegra20-harmony.dts
@@ -339,7 +339,7 @@ sys_reg: sys {
regulator-always-on;
};
 
-   sm0 {
+   vdd_core: sm0 {
regulator-name = "vdd_sm0,vdd_core";
regulator-min-microvolt = <120>;
regulator-max-microvolt = <120>;
@@ -565,6 +565,7 @@ pmc@7000e400 {
nvidia,core-pwr-good-time = <3845 3845>;
nvidia,core-pwr-off-time = <3875>;
nvidia,sys-clock-req-active-high;
+   core-supply = <_core>;
};
 
pcie@80003000 {
diff --git a/arch/arm/boot/dts/tegra20-paz00.dts 
b/arch/arm/boot/dts/tegra20-paz00.dts
index 1fd5a7458c7a..f68d37ae6c64 100644
--- a/arch/arm/boot/dts/tegra20-paz00.dts
+++ b/arch/arm/boot/dts/tegra20-paz00.dts
@@ -519,6 +519,7 @@ pmc@7000e400 {
nvidia,core-pwr-good-time = <3845 3845>;
nvidia,core-pwr-off-time = <0>;
nvidia,sys-clock-req-active-high;
+   core-supply = <_vdd_reg>;
};
 
usb@c500 {
diff --git a/arch/arm/boot/dts/tegra20-peripherals-opp.dtsi 
b/arch/arm/boot/dts/tegra20-peripherals-opp.dtsi
index d4d0a5fa7015..e7477b129e34 100644
--- a/arch/arm/boot/dts/tegra20-peripherals-opp.dtsi
+++ b/arch/arm/boot/dts/tegra20-peripherals-opp.dtsi
@@ -1,6 +1,46 @@
 // SPDX-License-Identifier: GPL-2.0
 
 / {
+   core_opp_table: opp-table-core {
+   compatible = "operating-points-v2";
+   opp-shared;
+
+   core_opp_950: opp-95 {
+   opp-microvolt = <95 95 130>;
+   opp-level = <95>;
+   };
+
+   core_opp_1000: opp-100 {
+   opp-microvolt = <100 100 130>;
+   opp-level = <100>;
+   };
+
+   core_opp_1100: opp-110 {
+   opp-microvolt = <110 110 130>;
+   opp-level = <110>;
+   };
+
+   core_opp_1200: opp-120 {
+   opp-microvolt = <120 120 130>;
+   opp-level = <120>;
+   };
+
+   

[PATCH v15 24/39] media: dt: bindings: tegra-vde: Convert to schema

2021-11-14 Thread Dmitry Osipenko
Convert NVIDIA Tegra video decoder binding to schema.

Reviewed-by: Rob Herring 
Acked-by: Hans Verkuil 
Signed-off-by: Dmitry Osipenko 
---
 .../bindings/media/nvidia,tegra-vde.txt   |  64 ---
 .../bindings/media/nvidia,tegra-vde.yaml  | 107 ++
 2 files changed, 107 insertions(+), 64 deletions(-)
 delete mode 100644 Documentation/devicetree/bindings/media/nvidia,tegra-vde.txt
 create mode 100644 
Documentation/devicetree/bindings/media/nvidia,tegra-vde.yaml

diff --git a/Documentation/devicetree/bindings/media/nvidia,tegra-vde.txt 
b/Documentation/devicetree/bindings/media/nvidia,tegra-vde.txt
deleted file mode 100644
index 602169b8aa19..
--- a/Documentation/devicetree/bindings/media/nvidia,tegra-vde.txt
+++ /dev/null
@@ -1,64 +0,0 @@
-NVIDIA Tegra Video Decoder Engine
-
-Required properties:
-- compatible : Must contain one of the following values:
-   - "nvidia,tegra20-vde"
-   - "nvidia,tegra30-vde"
-   - "nvidia,tegra114-vde"
-   - "nvidia,tegra124-vde"
-   - "nvidia,tegra132-vde"
-- reg : Must contain an entry for each entry in reg-names.
-- reg-names : Must include the following entries:
-  - sxe
-  - bsev
-  - mbe
-  - ppe
-  - mce
-  - tfe
-  - ppb
-  - vdma
-  - frameid
-- iram : Must contain phandle to the mmio-sram device node that represents
- IRAM region used by VDE.
-- interrupts : Must contain an entry for each entry in interrupt-names.
-- interrupt-names : Must include the following entries:
-  - sync-token
-  - bsev
-  - sxe
-- clocks : Must include the following entries:
-  - vde
-- resets : Must contain an entry for each entry in reset-names.
-- reset-names : Should include the following entries:
-  - vde
-
-Optional properties:
-- resets : Must contain an entry for each entry in reset-names.
-- reset-names : Must include the following entries:
-  - mc
-- iommus: Must contain phandle to the IOMMU device node.
-
-Example:
-
-video-codec@6001a000 {
-   compatible = "nvidia,tegra20-vde";
-   reg = <0x6001a000 0x1000 /* Syntax Engine */
-  0x6001b000 0x1000 /* Video Bitstream Engine */
-  0x6001c000  0x100 /* Macroblock Engine */
-  0x6001c200  0x100 /* Post-processing Engine */
-  0x6001c400  0x100 /* Motion Compensation Engine */
-  0x6001c600  0x100 /* Transform Engine */
-  0x6001c800  0x100 /* Pixel prediction block */
-  0x6001ca00  0x100 /* Video DMA */
-  0x6001d800  0x300 /* Video frame controls */>;
-   reg-names = "sxe", "bsev", "mbe", "ppe", "mce",
-   "tfe", "ppb", "vdma", "frameid";
-   iram = <_pool>; /* IRAM region */
-   interrupts = , /* Sync token interrupt 
*/
-, /* BSE-V interrupt */
-; /* SXE interrupt */
-   interrupt-names = "sync-token", "bsev", "sxe";
-   clocks = <_car TEGRA20_CLK_VDE>;
-   reset-names = "vde", "mc";
-   resets = <_car 61>, < TEGRA20_MC_RESET_VDE>;
-   iommus = < TEGRA_SWGROUP_VDE>;
-};
diff --git a/Documentation/devicetree/bindings/media/nvidia,tegra-vde.yaml 
b/Documentation/devicetree/bindings/media/nvidia,tegra-vde.yaml
new file mode 100644
index ..c143aaa06346
--- /dev/null
+++ b/Documentation/devicetree/bindings/media/nvidia,tegra-vde.yaml
@@ -0,0 +1,107 @@
+# SPDX-License-Identifier: (GPL-2.0-only OR BSD-2-Clause)
+%YAML 1.2
+---
+$id: http://devicetree.org/schemas/media/nvidia,tegra-vde.yaml#
+$schema: http://devicetree.org/meta-schemas/core.yaml#
+
+title: NVIDIA Tegra Video Decoder Engine
+
+maintainers:
+  - Dmitry Osipenko 
+  - Jon Hunter 
+  - Thierry Reding 
+
+properties:
+  compatible:
+oneOf:
+  - items:
+  - enum:
+  - nvidia,tegra132-vde
+  - nvidia,tegra124-vde
+  - nvidia,tegra114-vde
+  - items:
+  - const: nvidia,tegra30-vde
+  - const: nvidia,tegra20-vde
+  - items:
+  - const: nvidia,tegra20-vde
+
+  reg:
+maxItems: 9
+
+  reg-names:
+items:
+  - const: sxe
+  - const: bsev
+  - const: mbe
+  - const: ppe
+  - const: mce
+  - const: tfe
+  - const: ppb
+  - const: vdma
+  - const: frameid
+
+  clocks:
+maxItems: 1
+
+  resets:
+maxItems: 2
+
+  reset-names:
+items:
+  - const: vde
+  - const: mc
+
+  interrupts:
+maxItems: 3
+
+  interrupt-names:
+items:
+  - const: sync-token
+  - const: bsev
+  - const: sxe
+
+  iommus:
+maxItems: 1
+
+  iram:
+$ref: /schemas/types.yaml#/definitions/phandle
+description:
+  Phandle of the SRAM MMIO node.
+
+required:
+  - compatible
+  - reg
+  - reg-names
+  - clocks
+  - resets
+  - reset-names
+  - interrupts
+  - interrupt-names
+
+additionalProperties: false
+
+examples:
+  - |
+video-codec@6001a000 {
+  compatible = "nvidia,tegra20-vde";
+  reg = <0x6001a000 0x1000>, /* Syntax Engine */
+<0x6001b000 0x1000>, /* Video 

[PATCH v15 21/39] mmc: sdhci-tegra: Add runtime PM and OPP support

2021-11-14 Thread Dmitry Osipenko
The SDHCI on Tegra belongs to the core power domain and we're going to
enable GENPD support for the core domain. Now SDHCI must be resumed using
runtime PM API in order to initialize the SDHCI power state. The SDHCI
clock rate must be changed using OPP API that will reconfigure the power
domain performance state in accordance to the rate. Add runtime PM and OPP
support to the SDHCI driver.

Reviewed-by: Ulf Hansson 
Signed-off-by: Dmitry Osipenko 
---
 drivers/mmc/host/sdhci-tegra.c | 81 +++---
 1 file changed, 65 insertions(+), 16 deletions(-)

diff --git a/drivers/mmc/host/sdhci-tegra.c b/drivers/mmc/host/sdhci-tegra.c
index a5001875876b..6435a75142a6 100644
--- a/drivers/mmc/host/sdhci-tegra.c
+++ b/drivers/mmc/host/sdhci-tegra.c
@@ -15,6 +15,8 @@
 #include 
 #include 
 #include 
+#include 
+#include 
 #include 
 #include 
 #include 
@@ -24,6 +26,8 @@
 #include 
 #include 
 
+#include 
+
 #include "sdhci-pltfm.h"
 #include "cqhci.h"
 
@@ -760,7 +764,9 @@ static void tegra_sdhci_set_clock(struct sdhci_host *host, 
unsigned int clock)
 {
struct sdhci_pltfm_host *pltfm_host = sdhci_priv(host);
struct sdhci_tegra *tegra_host = sdhci_pltfm_priv(pltfm_host);
+   struct device *dev = mmc_dev(host->mmc);
unsigned long host_clk;
+   int err;
 
if (!clock)
return sdhci_set_clock(host, clock);
@@ -778,7 +784,12 @@ static void tegra_sdhci_set_clock(struct sdhci_host *host, 
unsigned int clock)
 * from clk_get_rate() is used.
 */
host_clk = tegra_host->ddr_signaling ? clock * 2 : clock;
-   clk_set_rate(pltfm_host->clk, host_clk);
+
+   err = dev_pm_opp_set_rate(dev, host_clk);
+   if (err)
+   dev_err(dev, "failed to set clk rate to %luHz: %d\n",
+   host_clk, err);
+
tegra_host->curr_clk_rate = host_clk;
if (tegra_host->ddr_signaling)
host->max_clk = host_clk;
@@ -1705,7 +1716,6 @@ static int sdhci_tegra_probe(struct platform_device *pdev)
   "failed to get clock\n");
goto err_clk_get;
}
-   clk_prepare_enable(clk);
pltfm_host->clk = clk;
 
tegra_host->rst = devm_reset_control_get_exclusive(>dev,
@@ -1716,15 +1726,24 @@ static int sdhci_tegra_probe(struct platform_device 
*pdev)
goto err_rst_get;
}
 
-   rc = reset_control_assert(tegra_host->rst);
+   rc = devm_tegra_core_dev_init_opp_table_common(>dev);
if (rc)
goto err_rst_get;
 
+   pm_runtime_enable(>dev);
+   rc = pm_runtime_resume_and_get(>dev);
+   if (rc)
+   goto err_pm_get;
+
+   rc = reset_control_assert(tegra_host->rst);
+   if (rc)
+   goto err_rst_assert;
+
usleep_range(2000, 4000);
 
rc = reset_control_deassert(tegra_host->rst);
if (rc)
-   goto err_rst_get;
+   goto err_rst_assert;
 
usleep_range(2000, 4000);
 
@@ -1736,8 +1755,11 @@ static int sdhci_tegra_probe(struct platform_device 
*pdev)
 
 err_add_host:
reset_control_assert(tegra_host->rst);
+err_rst_assert:
+   pm_runtime_put_sync_suspend(>dev);
+err_pm_get:
+   pm_runtime_disable(>dev);
 err_rst_get:
-   clk_disable_unprepare(pltfm_host->clk);
 err_clk_get:
clk_disable_unprepare(tegra_host->tmclk);
 err_power_req:
@@ -1756,19 +1778,38 @@ static int sdhci_tegra_remove(struct platform_device 
*pdev)
 
reset_control_assert(tegra_host->rst);
usleep_range(2000, 4000);
-   clk_disable_unprepare(pltfm_host->clk);
-   clk_disable_unprepare(tegra_host->tmclk);
 
+   pm_runtime_put_sync_suspend(>dev);
+   pm_runtime_force_suspend(>dev);
+
+   clk_disable_unprepare(tegra_host->tmclk);
sdhci_pltfm_free(pdev);
 
return 0;
 }
 
-#ifdef CONFIG_PM_SLEEP
-static int __maybe_unused sdhci_tegra_suspend(struct device *dev)
+static int __maybe_unused sdhci_tegra_runtime_suspend(struct device *dev)
 {
struct sdhci_host *host = dev_get_drvdata(dev);
struct sdhci_pltfm_host *pltfm_host = sdhci_priv(host);
+
+   clk_disable_unprepare(pltfm_host->clk);
+
+   return 0;
+}
+
+static int __maybe_unused sdhci_tegra_runtime_resume(struct device *dev)
+{
+   struct sdhci_host *host = dev_get_drvdata(dev);
+   struct sdhci_pltfm_host *pltfm_host = sdhci_priv(host);
+
+   return clk_prepare_enable(pltfm_host->clk);
+}
+
+#ifdef CONFIG_PM_SLEEP
+static int sdhci_tegra_suspend(struct device *dev)
+{
+   struct sdhci_host *host = dev_get_drvdata(dev);
int ret;
 
if (host->mmc->caps2 & MMC_CAP2_CQE) {
@@ -1783,17 +1824,22 @@ static int __maybe_unused sdhci_tegra_suspend(struct 
device *dev)
return ret;
}
 
-   clk_disable_unprepare(pltfm_host->clk);
+   ret = pm_runtime_force_suspend(dev);
+   if (ret) {
+   sdhci_resume_host(host);
+ 

[PATCH v15 25/39] media: dt: bindings: tegra-vde: Document OPP and power domain

2021-11-14 Thread Dmitry Osipenko
Document new OPP table and power domain properties of the video decoder
hardware.

Reviewed-by: Rob Herring 
Acked-by: Hans Verkuil 
Signed-off-by: Dmitry Osipenko 
---
 .../devicetree/bindings/media/nvidia,tegra-vde.yaml  | 12 
 1 file changed, 12 insertions(+)

diff --git a/Documentation/devicetree/bindings/media/nvidia,tegra-vde.yaml 
b/Documentation/devicetree/bindings/media/nvidia,tegra-vde.yaml
index c143aaa06346..4ecdee1be37e 100644
--- a/Documentation/devicetree/bindings/media/nvidia,tegra-vde.yaml
+++ b/Documentation/devicetree/bindings/media/nvidia,tegra-vde.yaml
@@ -68,6 +68,16 @@ properties:
 description:
   Phandle of the SRAM MMIO node.
 
+  operating-points-v2:
+description:
+  Should contain freqs and voltages and opp-supported-hw property,
+  which is a bitfield indicating SoC speedo or process ID mask.
+
+  power-domains:
+maxItems: 1
+description:
+  Phandle to the SoC core power domain.
+
 required:
   - compatible
   - reg
@@ -104,4 +114,6 @@ examples:
   reset-names = "vde", "mc";
   resets = < 61>, < 13>;
   iommus = < 15>;
+  operating-points-v2 = <_opp_table>;
+  power-domains = <>;
 };
-- 
2.33.1



[PATCH v15 15/39] drm/tegra: nvdec: Stop channel on suspend

2021-11-14 Thread Dmitry Osipenko
CDMA must be stopped before hardware is suspended. Add channel stopping
to RPM suspend callback. Add system level suspend-resume callbacks.

Runtime PM initialization is moved to host1x client init phase because
RPM callback now uses host1x channel that is available only when host1x
client is registered.

Reviewed-by: Ulf Hansson 
Signed-off-by: Dmitry Osipenko 
---
 drivers/gpu/drm/tegra/nvdec.c | 29 ++---
 1 file changed, 18 insertions(+), 11 deletions(-)

diff --git a/drivers/gpu/drm/tegra/nvdec.c b/drivers/gpu/drm/tegra/nvdec.c
index 791bf1acf5f0..15f036e09e5c 100644
--- a/drivers/gpu/drm/tegra/nvdec.c
+++ b/drivers/gpu/drm/tegra/nvdec.c
@@ -113,9 +113,13 @@ static int nvdec_init(struct host1x_client *client)
goto free_channel;
}
 
+   pm_runtime_enable(client->dev);
+   pm_runtime_use_autosuspend(client->dev);
+   pm_runtime_set_autosuspend_delay(client->dev, 500);
+
err = tegra_drm_register_client(tegra, drm);
if (err < 0)
-   goto free_syncpt;
+   goto disable_rpm;
 
/*
 * Inherit the DMA parameters (such as maximum segment size) from the
@@ -125,7 +129,10 @@ static int nvdec_init(struct host1x_client *client)
 
return 0;
 
-free_syncpt:
+disable_rpm:
+   pm_runtime_dont_use_autosuspend(client->dev);
+   pm_runtime_force_suspend(client->dev);
+
host1x_syncpt_put(client->syncpts[0]);
 free_channel:
host1x_channel_put(nvdec->channel);
@@ -150,10 +157,15 @@ static int nvdec_exit(struct host1x_client *client)
if (err < 0)
return err;
 
+   pm_runtime_dont_use_autosuspend(client->dev);
+   pm_runtime_force_suspend(client->dev);
+
host1x_syncpt_put(client->syncpts[0]);
host1x_channel_put(nvdec->channel);
host1x_client_iommu_detach(client);
 
+   nvdec->channel = NULL;
+
if (client->group) {
dma_unmap_single(nvdec->dev, nvdec->falcon.firmware.phys,
 nvdec->falcon.firmware.size, DMA_TO_DEVICE);
@@ -268,6 +280,8 @@ static __maybe_unused int nvdec_runtime_suspend(struct 
device *dev)
 {
struct nvdec *nvdec = dev_get_drvdata(dev);
 
+   host1x_channel_stop(nvdec->channel);
+
clk_disable_unprepare(nvdec->clk);
 
return 0;
@@ -412,10 +426,6 @@ static int nvdec_probe(struct platform_device *pdev)
goto exit_falcon;
}
 
-   pm_runtime_enable(>dev);
-   pm_runtime_set_autosuspend_delay(>dev, 500);
-   pm_runtime_use_autosuspend(>dev);
-
return 0;
 
 exit_falcon:
@@ -436,11 +446,6 @@ static int nvdec_remove(struct platform_device *pdev)
return err;
}
 
-   if (pm_runtime_enabled(>dev))
-   pm_runtime_disable(>dev);
-   else
-   nvdec_runtime_suspend(>dev);
-
falcon_exit(>falcon);
 
return 0;
@@ -448,6 +453,8 @@ static int nvdec_remove(struct platform_device *pdev)
 
 static const struct dev_pm_ops nvdec_pm_ops = {
SET_RUNTIME_PM_OPS(nvdec_runtime_suspend, nvdec_runtime_resume, NULL)
+   SET_SYSTEM_SLEEP_PM_OPS(pm_runtime_force_suspend,
+   pm_runtime_force_resume)
 };
 
 struct platform_driver tegra_nvdec_driver = {
-- 
2.33.1



[PATCH v15 32/39] soc/tegra: pmc: Enable core domain support for Tegra20 and Tegra30

2021-11-14 Thread Dmitry Osipenko
All device drivers got runtime PM and OPP support. Flip the core domain
support status for Tegra20 and Tegra30 SoCs.

Reviewed-by: Ulf Hansson 
Signed-off-by: Dmitry Osipenko 
---
 drivers/soc/tegra/pmc.c | 4 ++--
 1 file changed, 2 insertions(+), 2 deletions(-)

diff --git a/drivers/soc/tegra/pmc.c b/drivers/soc/tegra/pmc.c
index de6234ec4f9b..585a05968ea9 100644
--- a/drivers/soc/tegra/pmc.c
+++ b/drivers/soc/tegra/pmc.c
@@ -3070,7 +3070,7 @@ static void tegra20_pmc_setup_irq_polarity(struct 
tegra_pmc *pmc,
 }
 
 static const struct tegra_pmc_soc tegra20_pmc_soc = {
-   .supports_core_domain = false,
+   .supports_core_domain = true,
.num_powergates = ARRAY_SIZE(tegra20_powergates),
.powergates = tegra20_powergates,
.num_cpu_powergates = 0,
@@ -3131,7 +3131,7 @@ static const char * const tegra30_reset_sources[] = {
 };
 
 static const struct tegra_pmc_soc tegra30_pmc_soc = {
-   .supports_core_domain = false,
+   .supports_core_domain = true,
.num_powergates = ARRAY_SIZE(tegra30_powergates),
.powergates = tegra30_powergates,
.num_cpu_powergates = ARRAY_SIZE(tegra30_cpu_powergates),
-- 
2.33.1



[PATCH v15 33/39] ARM: tegra: Rename CPU and EMC OPP table device-tree nodes

2021-11-14 Thread Dmitry Osipenko
OPP table name now should start with "opp-table" and OPP entries
shouldn't contain commas and @ signs in accordance to the new schema
requirement. Reorganize CPU and EMC OPP table device-tree nodes.

Signed-off-by: Dmitry Osipenko 
---
 arch/arm/boot/dts/tegra124-apalis-emc.dtsi|   4 +-
 .../arm/boot/dts/tegra124-jetson-tk1-emc.dtsi |   4 +-
 arch/arm/boot/dts/tegra124-nyan-big-emc.dtsi  |   8 +-
 .../arm/boot/dts/tegra124-nyan-blaze-emc.dtsi |   8 +-
 .../boot/dts/tegra124-peripherals-opp.dtsi| 140 -
 .../boot/dts/tegra20-acer-a500-picasso.dts|   4 +-
 arch/arm/boot/dts/tegra20-colibri.dtsi|   2 +-
 .../boot/dts/tegra20-cpu-opp-microvolt.dtsi   |  82 +-
 arch/arm/boot/dts/tegra20-cpu-opp.dtsi|  82 +-
 arch/arm/boot/dts/tegra20-paz00.dts   |   2 +-
 .../arm/boot/dts/tegra20-peripherals-opp.dtsi |  36 ++---
 ...30-asus-nexus7-grouper-memory-timings.dtsi |  12 +-
 .../boot/dts/tegra30-cpu-opp-microvolt.dtsi   | 144 +-
 arch/arm/boot/dts/tegra30-cpu-opp.dtsi| 144 +-
 arch/arm/boot/dts/tegra30-ouya.dts|   4 +-
 .../arm/boot/dts/tegra30-peripherals-opp.dtsi | 128 
 16 files changed, 402 insertions(+), 402 deletions(-)

diff --git a/arch/arm/boot/dts/tegra124-apalis-emc.dtsi 
b/arch/arm/boot/dts/tegra124-apalis-emc.dtsi
index a7ac805eeed5..3d9cf16f233c 100644
--- a/arch/arm/boot/dts/tegra124-apalis-emc.dtsi
+++ b/arch/arm/boot/dts/tegra124-apalis-emc.dtsi
@@ -1467,9 +1467,9 @@ timing-92400 {
 };
 
 _icc_dvfs_opp_table {
-   /delete-node/ opp@12,1100;
+   /delete-node/ opp-12-1100;
 };
 
 _bw_dfs_opp_table {
-   /delete-node/ opp@12;
+   /delete-node/ opp-12;
 };
diff --git a/arch/arm/boot/dts/tegra124-jetson-tk1-emc.dtsi 
b/arch/arm/boot/dts/tegra124-jetson-tk1-emc.dtsi
index df4e463afbd1..bb10cf9fc0f9 100644
--- a/arch/arm/boot/dts/tegra124-jetson-tk1-emc.dtsi
+++ b/arch/arm/boot/dts/tegra124-jetson-tk1-emc.dtsi
@@ -2422,9 +2422,9 @@ timing-92400 {
 };
 
 _icc_dvfs_opp_table {
-   /delete-node/ opp@12,1100;
+   /delete-node/ opp-12-1100;
 };
 
 _bw_dfs_opp_table {
-   /delete-node/ opp@12;
+   /delete-node/ opp-12;
 };
diff --git a/arch/arm/boot/dts/tegra124-nyan-big-emc.dtsi 
b/arch/arm/boot/dts/tegra124-nyan-big-emc.dtsi
index a0f56cc9da5c..6f2ea9469d49 100644
--- a/arch/arm/boot/dts/tegra124-nyan-big-emc.dtsi
+++ b/arch/arm/boot/dts/tegra124-nyan-big-emc.dtsi
@@ -6651,11 +6651,11 @@ timing-79200 {
 };
 
 _icc_dvfs_opp_table {
-   /delete-node/ opp@92400,1100;
-   /delete-node/ opp@12,1100;
+   /delete-node/ opp-92400-1100;
+   /delete-node/ opp-12-1100;
 };
 
 _bw_dfs_opp_table {
-   /delete-node/ opp@92400;
-   /delete-node/ opp@12;
+   /delete-node/ opp-92400;
+   /delete-node/ opp-12;
 };
diff --git a/arch/arm/boot/dts/tegra124-nyan-blaze-emc.dtsi 
b/arch/arm/boot/dts/tegra124-nyan-blaze-emc.dtsi
index 35c98734d35f..d47cdb863f88 100644
--- a/arch/arm/boot/dts/tegra124-nyan-blaze-emc.dtsi
+++ b/arch/arm/boot/dts/tegra124-nyan-blaze-emc.dtsi
@@ -2050,11 +2050,11 @@ timing-79200 {
 };
 
 _icc_dvfs_opp_table {
-   /delete-node/ opp@92400,1100;
-   /delete-node/ opp@12,1100;
+   /delete-node/ opp-92400-1100;
+   /delete-node/ opp-12-1100;
 };
 
 _bw_dfs_opp_table {
-   /delete-node/ opp@92400;
-   /delete-node/ opp@12;
+   /delete-node/ opp-92400;
+   /delete-node/ opp-12;
 };
diff --git a/arch/arm/boot/dts/tegra124-peripherals-opp.dtsi 
b/arch/arm/boot/dts/tegra124-peripherals-opp.dtsi
index 781ac8601030..b262c1289da5 100644
--- a/arch/arm/boot/dts/tegra124-peripherals-opp.dtsi
+++ b/arch/arm/boot/dts/tegra124-peripherals-opp.dtsi
@@ -1,421 +1,421 @@
 // SPDX-License-Identifier: GPL-2.0
 
 / {
-   emc_icc_dvfs_opp_table: emc-dvfs-opp-table {
+   emc_icc_dvfs_opp_table: opp-table-emc {
compatible = "operating-points-v2";
 
-   opp@1275,800 {
+   opp-1275-800 {
opp-microvolt = <80 80 115>;
opp-hz = /bits/ 64 <1275>;
opp-supported-hw = <0x0003>;
};
 
-   opp@1275,950 {
+   opp-1275-950 {
opp-microvolt = <95 95 115>;
opp-hz = /bits/ 64 <1275>;
opp-supported-hw = <0x0008>;
};
 
-   opp@1275,1050 {
+   opp-1275-1050 {
opp-microvolt = <105 105 115>;
opp-hz = /bits/ 64 <1275>;
opp-supported-hw = <0x0010>;
};
 
-   opp@1275,1110 {
+   opp-1275-1110 {

[PATCH v15 31/39] soc/tegra: pmc: Rename core power domain

2021-11-14 Thread Dmitry Osipenko
CORE power domain uses name of device-tree node, which is inconsistent with
the names of PMC domains. Set the name to "core" to make it consistent.

Reviewed-by: Ulf Hansson 
Signed-off-by: Dmitry Osipenko 
---
 drivers/soc/tegra/pmc.c | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/drivers/soc/tegra/pmc.c b/drivers/soc/tegra/pmc.c
index e1fae1a5e36a..de6234ec4f9b 100644
--- a/drivers/soc/tegra/pmc.c
+++ b/drivers/soc/tegra/pmc.c
@@ -1369,7 +1369,7 @@ static int tegra_pmc_core_pd_add(struct tegra_pmc *pmc, 
struct device_node *np)
if (!genpd)
return -ENOMEM;
 
-   genpd->name = np->name;
+   genpd->name = "core";
genpd->set_performance_state = tegra_pmc_core_pd_set_performance_state;
genpd->opp_to_performance_state = 
tegra_pmc_core_pd_opp_to_performance_state;
 
-- 
2.33.1



[PATCH v15 17/39] drm/tegra: submit: Add missing pm_runtime_mark_last_busy()

2021-11-14 Thread Dmitry Osipenko
Runtime PM auto-suspension doesn't work without pm_runtime_mark_last_busy(),
add it.

Reviewed-by: Ulf Hansson 
Signed-off-by: Dmitry Osipenko 
---
 drivers/gpu/drm/tegra/submit.c | 1 +
 1 file changed, 1 insertion(+)

diff --git a/drivers/gpu/drm/tegra/submit.c b/drivers/gpu/drm/tegra/submit.c
index 3bbd8de5711c..6d6dd8c35475 100644
--- a/drivers/gpu/drm/tegra/submit.c
+++ b/drivers/gpu/drm/tegra/submit.c
@@ -504,6 +504,7 @@ static void release_job(struct host1x_job *job)
kfree(job_data->used_mappings);
kfree(job_data);
 
+   pm_runtime_mark_last_busy(client->base.dev);
pm_runtime_put_autosuspend(client->base.dev);
 }
 
-- 
2.33.1



[PATCH v15 20/39] pwm: tegra: Add runtime PM and OPP support

2021-11-14 Thread Dmitry Osipenko
The PWM on Tegra belongs to the core power domain and we're going to
enable GENPD support for the core domain. Now PWM must be resumed using
runtime PM API in order to initialize the PWM power state. The PWM clock
rate must be changed using OPP API that will reconfigure the power domain
performance state in accordance to the rate. Add runtime PM and OPP
support to the PWM driver.

Reviewed-by: Ulf Hansson 
Signed-off-by: Dmitry Osipenko 
---
 drivers/pwm/pwm-tegra.c | 82 -
 1 file changed, 64 insertions(+), 18 deletions(-)

diff --git a/drivers/pwm/pwm-tegra.c b/drivers/pwm/pwm-tegra.c
index 11a10b575ace..18cf974ac776 100644
--- a/drivers/pwm/pwm-tegra.c
+++ b/drivers/pwm/pwm-tegra.c
@@ -42,12 +42,16 @@
 #include 
 #include 
 #include 
+#include 
 #include 
 #include 
 #include 
+#include 
 #include 
 #include 
 
+#include 
+
 #define PWM_ENABLE (1 << 31)
 #define PWM_DUTY_WIDTH 8
 #define PWM_DUTY_SHIFT 16
@@ -145,7 +149,7 @@ static int tegra_pwm_config(struct pwm_chip *chip, struct 
pwm_device *pwm,
required_clk_rate =
(NSEC_PER_SEC / period_ns) << PWM_DUTY_WIDTH;
 
-   err = clk_set_rate(pc->clk, required_clk_rate);
+   err = dev_pm_opp_set_rate(pc->dev, required_clk_rate);
if (err < 0)
return -EINVAL;
 
@@ -181,8 +185,8 @@ static int tegra_pwm_config(struct pwm_chip *chip, struct 
pwm_device *pwm,
 * before writing the register. Otherwise, keep it enabled.
 */
if (!pwm_is_enabled(pwm)) {
-   err = clk_prepare_enable(pc->clk);
-   if (err < 0)
+   err = pm_runtime_resume_and_get(pc->dev);
+   if (err)
return err;
} else
val |= PWM_ENABLE;
@@ -193,7 +197,7 @@ static int tegra_pwm_config(struct pwm_chip *chip, struct 
pwm_device *pwm,
 * If the PWM is not enabled, turn the clock off again to save power.
 */
if (!pwm_is_enabled(pwm))
-   clk_disable_unprepare(pc->clk);
+   pm_runtime_put(pc->dev);
 
return 0;
 }
@@ -204,8 +208,8 @@ static int tegra_pwm_enable(struct pwm_chip *chip, struct 
pwm_device *pwm)
int rc = 0;
u32 val;
 
-   rc = clk_prepare_enable(pc->clk);
-   if (rc < 0)
+   rc = pm_runtime_resume_and_get(pc->dev);
+   if (rc)
return rc;
 
val = pwm_readl(pc, pwm->hwpwm);
@@ -224,7 +228,7 @@ static void tegra_pwm_disable(struct pwm_chip *chip, struct 
pwm_device *pwm)
val &= ~PWM_ENABLE;
pwm_writel(pc, pwm->hwpwm, val);
 
-   clk_disable_unprepare(pc->clk);
+   pm_runtime_put_sync(pc->dev);
 }
 
 static const struct pwm_ops tegra_pwm_ops = {
@@ -256,11 +260,20 @@ static int tegra_pwm_probe(struct platform_device *pdev)
if (IS_ERR(pwm->clk))
return PTR_ERR(pwm->clk);
 
+   ret = devm_tegra_core_dev_init_opp_table_common(>dev);
+   if (ret)
+   return ret;
+
+   pm_runtime_enable(>dev);
+   ret = pm_runtime_resume_and_get(>dev);
+   if (ret)
+   return ret;
+
/* Set maximum frequency of the IP */
-   ret = clk_set_rate(pwm->clk, pwm->soc->max_frequency);
+   ret = dev_pm_opp_set_rate(pwm->dev, pwm->soc->max_frequency);
if (ret < 0) {
dev_err(>dev, "Failed to set max frequency: %d\n", ret);
-   return ret;
+   goto put_pm;
}
 
/*
@@ -278,7 +291,7 @@ static int tegra_pwm_probe(struct platform_device *pdev)
if (IS_ERR(pwm->rst)) {
ret = PTR_ERR(pwm->rst);
dev_err(>dev, "Reset control is not found: %d\n", ret);
-   return ret;
+   goto put_pm;
}
 
reset_control_deassert(pwm->rst);
@@ -291,10 +304,16 @@ static int tegra_pwm_probe(struct platform_device *pdev)
if (ret < 0) {
dev_err(>dev, "pwmchip_add() failed: %d\n", ret);
reset_control_assert(pwm->rst);
-   return ret;
+   goto put_pm;
}
 
+   pm_runtime_put(>dev);
+
return 0;
+put_pm:
+   pm_runtime_put_sync_suspend(>dev);
+   pm_runtime_force_suspend(>dev);
+   return ret;
 }
 
 static int tegra_pwm_remove(struct platform_device *pdev)
@@ -305,20 +324,44 @@ static int tegra_pwm_remove(struct platform_device *pdev)
 
reset_control_assert(pc->rst);
 
+   pm_runtime_force_suspend(>dev);
+
return 0;
 }
 
-#ifdef CONFIG_PM_SLEEP
-static int tegra_pwm_suspend(struct device *dev)
+static int __maybe_unused tegra_pwm_runtime_suspend(struct device *dev)
 {
-   return pinctrl_pm_select_sleep_state(dev);
+   struct tegra_pwm_chip *pc = dev_get_drvdata(dev);
+   int err;
+
+   clk_disable_unprepare(pc->clk);
+
+   err = pinctrl_pm_select_sleep_state(dev);
+   if (err) {
+   

[PATCH v15 19/39] bus: tegra-gmi: Add runtime PM and OPP support

2021-11-14 Thread Dmitry Osipenko
The GMI bus on Tegra belongs to the core power domain and we're going to
enable GENPD support for the core domain. Now GMI must be resumed using
runtime PM API in order to initialize the GMI power state. Add runtime PM
and OPP support to the GMI driver.

Reviewed-by: Ulf Hansson 
Signed-off-by: Dmitry Osipenko 
---
 drivers/bus/tegra-gmi.c | 50 -
 1 file changed, 44 insertions(+), 6 deletions(-)

diff --git a/drivers/bus/tegra-gmi.c b/drivers/bus/tegra-gmi.c
index a6570789f7af..35b59f92fa66 100644
--- a/drivers/bus/tegra-gmi.c
+++ b/drivers/bus/tegra-gmi.c
@@ -13,8 +13,11 @@
 #include 
 #include 
 #include 
+#include 
 #include 
 
+#include 
+
 #define TEGRA_GMI_CONFIG   0x00
 #define TEGRA_GMI_CONFIG_GOBIT(31)
 #define TEGRA_GMI_BUS_WIDTH_32BIT  BIT(30)
@@ -54,9 +57,10 @@ static int tegra_gmi_enable(struct tegra_gmi *gmi)
 {
int err;
 
-   err = clk_prepare_enable(gmi->clk);
-   if (err < 0) {
-   dev_err(gmi->dev, "failed to enable clock: %d\n", err);
+   pm_runtime_enable(gmi->dev);
+   err = pm_runtime_resume_and_get(gmi->dev);
+   if (err) {
+   pm_runtime_disable(gmi->dev);
return err;
}
 
@@ -83,7 +87,9 @@ static void tegra_gmi_disable(struct tegra_gmi *gmi)
writel(config, gmi->base + TEGRA_GMI_CONFIG);
 
reset_control_assert(gmi->rst);
-   clk_disable_unprepare(gmi->clk);
+
+   pm_runtime_put_sync_suspend(gmi->dev);
+   pm_runtime_force_suspend(gmi->dev);
 }
 
 static int tegra_gmi_parse_dt(struct tegra_gmi *gmi)
@@ -213,6 +219,7 @@ static int tegra_gmi_probe(struct platform_device *pdev)
if (!gmi)
return -ENOMEM;
 
+   platform_set_drvdata(pdev, gmi);
gmi->dev = dev;
 
res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
@@ -232,6 +239,10 @@ static int tegra_gmi_probe(struct platform_device *pdev)
return PTR_ERR(gmi->rst);
}
 
+   err = devm_tegra_core_dev_init_opp_table_common(>dev);
+   if (err)
+   return err;
+
err = tegra_gmi_parse_dt(gmi);
if (err)
return err;
@@ -247,8 +258,6 @@ static int tegra_gmi_probe(struct platform_device *pdev)
return err;
}
 
-   platform_set_drvdata(pdev, gmi);
-
return 0;
 }
 
@@ -262,6 +271,34 @@ static int tegra_gmi_remove(struct platform_device *pdev)
return 0;
 }
 
+static int __maybe_unused tegra_gmi_runtime_resume(struct device *dev)
+{
+   struct tegra_gmi *gmi = dev_get_drvdata(dev);
+   int err;
+
+   err = clk_prepare_enable(gmi->clk);
+   if (err < 0) {
+   dev_err(gmi->dev, "failed to enable clock: %d\n", err);
+   return err;
+   }
+
+   return 0;
+}
+
+static int __maybe_unused tegra_gmi_runtime_suspend(struct device *dev)
+{
+   struct tegra_gmi *gmi = dev_get_drvdata(dev);
+
+   clk_disable_unprepare(gmi->clk);
+
+   return 0;
+}
+
+static const struct dev_pm_ops tegra_gmi_pm = {
+   SET_RUNTIME_PM_OPS(tegra_gmi_runtime_suspend, tegra_gmi_runtime_resume,
+  NULL)
+};
+
 static const struct of_device_id tegra_gmi_id_table[] = {
{ .compatible = "nvidia,tegra20-gmi", },
{ .compatible = "nvidia,tegra30-gmi", },
@@ -275,6 +312,7 @@ static struct platform_driver tegra_gmi_driver = {
.driver = {
.name   = "tegra-gmi",
.of_match_table = tegra_gmi_id_table,
+   .pm = _gmi_pm,
},
 };
 module_platform_driver(tegra_gmi_driver);
-- 
2.33.1



[PATCH v15 26/39] media: staging: tegra-vde: Support generic power domain

2021-11-14 Thread Dmitry Osipenko
Currently driver supports legacy power domain API, this patch adds generic
power domain support. This allows us to utilize a modern GENPD API for
newer device-trees.

Reviewed-by: Ulf Hansson 
Tested-by: Peter Geis  # Ouya T30
Tested-by: Paul Fertser  # PAZ00 T20
Tested-by: Nicolas Chauvet  # PAZ00 T20 and TK1 T124
Tested-by: Matt Merhar  # Ouya T30
Acked-by: Hans Verkuil 
Signed-off-by: Dmitry Osipenko 
---
 drivers/staging/media/tegra-vde/vde.c | 63 ++-
 1 file changed, 52 insertions(+), 11 deletions(-)

diff --git a/drivers/staging/media/tegra-vde/vde.c 
b/drivers/staging/media/tegra-vde/vde.c
index ed4c1250b303..859f60a70904 100644
--- a/drivers/staging/media/tegra-vde/vde.c
+++ b/drivers/staging/media/tegra-vde/vde.c
@@ -20,6 +20,7 @@
 #include 
 #include 
 
+#include 
 #include 
 
 #include "uapi.h"
@@ -920,13 +921,17 @@ static __maybe_unused int 
tegra_vde_runtime_suspend(struct device *dev)
struct tegra_vde *vde = dev_get_drvdata(dev);
int err;
 
-   err = tegra_powergate_power_off(TEGRA_POWERGATE_VDEC);
-   if (err) {
-   dev_err(dev, "Failed to power down HW: %d\n", err);
-   return err;
+   if (!dev->pm_domain) {
+   err = tegra_powergate_power_off(TEGRA_POWERGATE_VDEC);
+   if (err) {
+   dev_err(dev, "Failed to power down HW: %d\n", err);
+   return err;
+   }
}
 
clk_disable_unprepare(vde->clk);
+   reset_control_release(vde->rst);
+   reset_control_release(vde->rst_mc);
 
return 0;
 }
@@ -936,14 +941,45 @@ static __maybe_unused int tegra_vde_runtime_resume(struct 
device *dev)
struct tegra_vde *vde = dev_get_drvdata(dev);
int err;
 
-   err = tegra_powergate_sequence_power_up(TEGRA_POWERGATE_VDEC,
-   vde->clk, vde->rst);
+   err = reset_control_acquire(vde->rst_mc);
if (err) {
-   dev_err(dev, "Failed to power up HW : %d\n", err);
+   dev_err(dev, "Failed to acquire mc reset: %d\n", err);
return err;
}
 
+   err = reset_control_acquire(vde->rst);
+   if (err) {
+   dev_err(dev, "Failed to acquire reset: %d\n", err);
+   goto release_mc_reset;
+   }
+
+   if (!dev->pm_domain) {
+   err = tegra_powergate_sequence_power_up(TEGRA_POWERGATE_VDEC,
+   vde->clk, vde->rst);
+   if (err) {
+   dev_err(dev, "Failed to power up HW : %d\n", err);
+   goto release_reset;
+   }
+   } else {
+   /*
+* tegra_powergate_sequence_power_up() leaves clocks enabled,
+* while GENPD not.
+*/
+   err = clk_prepare_enable(vde->clk);
+   if (err) {
+   dev_err(dev, "Failed to enable clock: %d\n", err);
+   goto release_reset;
+   }
+   }
+
return 0;
+
+release_reset:
+   reset_control_release(vde->rst);
+release_mc_reset:
+   reset_control_release(vde->rst_mc);
+
+   return err;
 }
 
 static int tegra_vde_probe(struct platform_device *pdev)
@@ -1001,14 +1037,14 @@ static int tegra_vde_probe(struct platform_device *pdev)
return err;
}
 
-   vde->rst = devm_reset_control_get(dev, NULL);
+   vde->rst = devm_reset_control_get_exclusive_released(dev, NULL);
if (IS_ERR(vde->rst)) {
err = PTR_ERR(vde->rst);
dev_err(dev, "Could not get VDE reset %d\n", err);
return err;
}
 
-   vde->rst_mc = devm_reset_control_get_optional(dev, "mc");
+   vde->rst_mc = devm_reset_control_get_optional_exclusive_released(dev, 
"mc");
if (IS_ERR(vde->rst_mc)) {
err = PTR_ERR(vde->rst_mc);
dev_err(dev, "Could not get MC reset %d\n", err);
@@ -1026,6 +1062,12 @@ static int tegra_vde_probe(struct platform_device *pdev)
return err;
}
 
+   err = devm_tegra_core_dev_init_opp_table_common(dev);
+   if (err) {
+   dev_err(dev, "Could initialize OPP table %d\n", err);
+   return err;
+   }
+
vde->iram_pool = of_gen_pool_get(dev->of_node, "iram", 0);
if (!vde->iram_pool) {
dev_err(dev, "Could not get IRAM pool\n");
@@ -1133,8 +1175,7 @@ static void tegra_vde_shutdown(struct platform_device 
*pdev)
 * On some devices bootloader isn't ready to a power-gated VDE on
 * a warm-reboot, machine will hang in that case.
 */
-   if (pm_runtime_status_suspended(>dev))
-   tegra_vde_runtime_resume(>dev);
+   pm_runtime_get_sync(>dev);
 }
 
 static __maybe_unused int tegra_vde_pm_suspend(struct device *dev)
-- 
2.33.1



[PATCH v15 29/39] soc/tegra: regulators: Prepare for suspend

2021-11-14 Thread Dmitry Osipenko
Depending on hardware version, Tegra SoC may require a higher voltages
during resume from system suspend, otherwise hardware will crash. Set
SoC voltages to a nominal levels during suspend.

Link: 
https://lore.kernel.org/all/a8280b5b-7347-8995-c97b-10b798cdf...@gmail.com/
Reviewed-by: Ulf Hansson 
Signed-off-by: Dmitry Osipenko 
---
 drivers/soc/tegra/regulators-tegra20.c |  99 
 drivers/soc/tegra/regulators-tegra30.c | 122 +
 2 files changed, 221 insertions(+)

diff --git a/drivers/soc/tegra/regulators-tegra20.c 
b/drivers/soc/tegra/regulators-tegra20.c
index b8ce9fd0650d..6a2f90ab9d3e 100644
--- a/drivers/soc/tegra/regulators-tegra20.c
+++ b/drivers/soc/tegra/regulators-tegra20.c
@@ -16,7 +16,9 @@
 #include 
 #include 
 #include 
+#include 
 
+#include 
 #include 
 
 struct tegra_regulator_coupler {
@@ -25,9 +27,12 @@ struct tegra_regulator_coupler {
struct regulator_dev *cpu_rdev;
struct regulator_dev *rtc_rdev;
struct notifier_block reboot_notifier;
+   struct notifier_block suspend_notifier;
int core_min_uV, cpu_min_uV;
bool sys_reboot_mode_req;
bool sys_reboot_mode;
+   bool sys_suspend_mode_req;
+   bool sys_suspend_mode;
 };
 
 static inline struct tegra_regulator_coupler *
@@ -105,6 +110,28 @@ static int tegra20_core_rtc_max_spread(struct 
regulator_dev *core_rdev,
return 15;
 }
 
+static int tegra20_cpu_nominal_uV(void)
+{
+   switch (tegra_sku_info.soc_speedo_id) {
+   case 0:
+   return 110;
+   case 1:
+   return 1025000;
+   default:
+   return 1125000;
+   }
+}
+
+static int tegra20_core_nominal_uV(void)
+{
+   switch (tegra_sku_info.soc_speedo_id) {
+   default:
+   return 1225000;
+   case 2:
+   return 130;
+   }
+}
+
 static int tegra20_core_rtc_update(struct tegra_regulator_coupler *tegra,
   struct regulator_dev *core_rdev,
   struct regulator_dev *rtc_rdev,
@@ -144,6 +171,11 @@ static int tegra20_core_rtc_update(struct 
tegra_regulator_coupler *tegra,
if (err)
return err;
 
+   /* prepare voltage level for suspend */
+   if (tegra->sys_suspend_mode)
+   core_min_uV = clamp(tegra20_core_nominal_uV(),
+   core_min_uV, core_max_uV);
+
core_uV = regulator_get_voltage_rdev(core_rdev);
if (core_uV < 0)
return core_uV;
@@ -279,6 +311,11 @@ static int tegra20_cpu_voltage_update(struct 
tegra_regulator_coupler *tegra,
if (tegra->sys_reboot_mode)
cpu_min_uV = max(cpu_min_uV, tegra->cpu_min_uV);
 
+   /* prepare voltage level for suspend */
+   if (tegra->sys_suspend_mode)
+   cpu_min_uV = clamp(tegra20_cpu_nominal_uV(),
+  cpu_min_uV, cpu_max_uV);
+
if (cpu_min_uV > cpu_uV) {
err = tegra20_core_rtc_update(tegra, core_rdev, rtc_rdev,
  cpu_uV, cpu_min_uV);
@@ -320,6 +357,7 @@ static int tegra20_regulator_balance_voltage(struct 
regulator_coupler *coupler,
}
 
tegra->sys_reboot_mode = READ_ONCE(tegra->sys_reboot_mode_req);
+   tegra->sys_suspend_mode = READ_ONCE(tegra->sys_suspend_mode_req);
 
if (rdev == cpu_rdev)
return tegra20_cpu_voltage_update(tegra, cpu_rdev,
@@ -334,6 +372,63 @@ static int tegra20_regulator_balance_voltage(struct 
regulator_coupler *coupler,
return -EPERM;
 }
 
+static int tegra20_regulator_prepare_suspend(struct tegra_regulator_coupler 
*tegra,
+bool sys_suspend_mode)
+{
+   int err;
+
+   if (!tegra->core_rdev || !tegra->rtc_rdev || !tegra->cpu_rdev)
+   return 0;
+
+   /*
+* All power domains are enabled early during resume from suspend
+* by GENPD core.  Domains like VENC may require a higher voltage
+* when enabled during resume from suspend.  This also prepares
+* hardware for resuming from LP0.
+*/
+
+   WRITE_ONCE(tegra->sys_suspend_mode_req, sys_suspend_mode);
+
+   err = regulator_sync_voltage_rdev(tegra->cpu_rdev);
+   if (err)
+   return err;
+
+   err = regulator_sync_voltage_rdev(tegra->core_rdev);
+   if (err)
+   return err;
+
+   return 0;
+}
+
+static int tegra20_regulator_suspend(struct notifier_block *notifier,
+unsigned long mode, void *arg)
+{
+   struct tegra_regulator_coupler *tegra;
+   int ret = 0;
+
+   tegra = container_of(notifier, struct tegra_regulator_coupler,
+suspend_notifier);
+
+   switch (mode) {
+   case PM_HIBERNATION_PREPARE:
+   case PM_RESTORE_PREPARE:
+   case PM_SUSPEND_PREPARE:
+   ret = 

[PATCH v15 27/39] soc/tegra: fuse: Reset hardware

2021-11-14 Thread Dmitry Osipenko
The FUSE controller is enabled at a boot time. Reset it in order to put
hardware and clock into clean and disabled state.

Reviewed-by: Ulf Hansson 
Signed-off-by: Dmitry Osipenko 
---
 drivers/soc/tegra/fuse/fuse-tegra.c | 25 +
 drivers/soc/tegra/fuse/fuse.h   |  1 +
 2 files changed, 26 insertions(+)

diff --git a/drivers/soc/tegra/fuse/fuse-tegra.c 
b/drivers/soc/tegra/fuse/fuse-tegra.c
index f2151815db58..cc032729a143 100644
--- a/drivers/soc/tegra/fuse/fuse-tegra.c
+++ b/drivers/soc/tegra/fuse/fuse-tegra.c
@@ -14,6 +14,7 @@
 #include 
 #include 
 #include 
+#include 
 #include 
 #include 
 
@@ -243,6 +244,30 @@ static int tegra_fuse_probe(struct platform_device *pdev)
goto restore;
}
 
+   fuse->rst = devm_reset_control_get_optional(>dev, "fuse");
+   if (IS_ERR(fuse->rst)) {
+   err = PTR_ERR(fuse->rst);
+   dev_err(>dev, "failed to get FUSE reset: %pe\n",
+   fuse->rst);
+   goto restore;
+   }
+
+   /*
+* FUSE clock is enabled at a boot time, hence this resume/suspend
+* disables the clock besides the h/w resetting.
+*/
+   err = pm_runtime_resume_and_get(>dev);
+   if (err)
+   goto restore;
+
+   err = reset_control_reset(fuse->rst);
+   pm_runtime_put(>dev);
+
+   if (err < 0) {
+   dev_err(>dev, "failed to reset FUSE: %d\n", err);
+   goto restore;
+   }
+
/* release the early I/O memory mapping */
iounmap(base);
 
diff --git a/drivers/soc/tegra/fuse/fuse.h b/drivers/soc/tegra/fuse/fuse.h
index de58feba0435..1b719d85bd04 100644
--- a/drivers/soc/tegra/fuse/fuse.h
+++ b/drivers/soc/tegra/fuse/fuse.h
@@ -43,6 +43,7 @@ struct tegra_fuse {
void __iomem *base;
phys_addr_t phys;
struct clk *clk;
+   struct reset_control *rst;
 
u32 (*read_early)(struct tegra_fuse *fuse, unsigned int offset);
u32 (*read)(struct tegra_fuse *fuse, unsigned int offset);
-- 
2.33.1



[PATCH v15 28/39] soc/tegra: fuse: Use resource-managed helpers

2021-11-14 Thread Dmitry Osipenko
Use resource-managed helpers to make code cleaner and more correct,
properly releasing all resources in case of driver probe error.

Signed-off-by: Dmitry Osipenko 
---
 drivers/soc/tegra/fuse/fuse-tegra.c   | 32 ++
 drivers/soc/tegra/fuse/fuse-tegra20.c | 33 ---
 2 files changed, 48 insertions(+), 17 deletions(-)

diff --git a/drivers/soc/tegra/fuse/fuse-tegra.c 
b/drivers/soc/tegra/fuse/fuse-tegra.c
index cc032729a143..fe4f935ce73a 100644
--- a/drivers/soc/tegra/fuse/fuse-tegra.c
+++ b/drivers/soc/tegra/fuse/fuse-tegra.c
@@ -182,6 +182,12 @@ static const struct nvmem_cell_info tegra_fuse_cells[] = {
},
 };
 
+static void tegra_fuse_restore(void *base)
+{
+   fuse->clk = NULL;
+   fuse->base = base;
+}
+
 static int tegra_fuse_probe(struct platform_device *pdev)
 {
void __iomem *base = fuse->base;
@@ -189,13 +195,16 @@ static int tegra_fuse_probe(struct platform_device *pdev)
struct resource *res;
int err;
 
+   err = devm_add_action(>dev, tegra_fuse_restore, base);
+   if (err)
+   return err;
+
/* take over the memory region from the early initialization */
res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
fuse->phys = res->start;
fuse->base = devm_ioremap_resource(>dev, res);
if (IS_ERR(fuse->base)) {
err = PTR_ERR(fuse->base);
-   fuse->base = base;
return err;
}
 
@@ -205,19 +214,20 @@ static int tegra_fuse_probe(struct platform_device *pdev)
dev_err(>dev, "failed to get FUSE clock: %ld",
PTR_ERR(fuse->clk));
 
-   fuse->base = base;
return PTR_ERR(fuse->clk);
}
 
platform_set_drvdata(pdev, fuse);
fuse->dev = >dev;
 
-   pm_runtime_enable(>dev);
+   err = devm_pm_runtime_enable(>dev);
+   if (err)
+   return err;
 
if (fuse->soc->probe) {
err = fuse->soc->probe(fuse);
if (err < 0)
-   goto restore;
+   return err;
}
 
memset(, 0, sizeof(nvmem));
@@ -241,7 +251,7 @@ static int tegra_fuse_probe(struct platform_device *pdev)
err = PTR_ERR(fuse->nvmem);
dev_err(>dev, "failed to register NVMEM device: %d\n",
err);
-   goto restore;
+   return err;
}
 
fuse->rst = devm_reset_control_get_optional(>dev, "fuse");
@@ -249,7 +259,7 @@ static int tegra_fuse_probe(struct platform_device *pdev)
err = PTR_ERR(fuse->rst);
dev_err(>dev, "failed to get FUSE reset: %pe\n",
fuse->rst);
-   goto restore;
+   return err;
}
 
/*
@@ -258,26 +268,20 @@ static int tegra_fuse_probe(struct platform_device *pdev)
 */
err = pm_runtime_resume_and_get(>dev);
if (err)
-   goto restore;
+   return err;
 
err = reset_control_reset(fuse->rst);
pm_runtime_put(>dev);
 
if (err < 0) {
dev_err(>dev, "failed to reset FUSE: %d\n", err);
-   goto restore;
+   return err;
}
 
/* release the early I/O memory mapping */
iounmap(base);
 
return 0;
-
-restore:
-   fuse->clk = NULL;
-   fuse->base = base;
-   pm_runtime_disable(>dev);
-   return err;
 }
 
 static int __maybe_unused tegra_fuse_runtime_resume(struct device *dev)
diff --git a/drivers/soc/tegra/fuse/fuse-tegra20.c 
b/drivers/soc/tegra/fuse/fuse-tegra20.c
index 8ec9fc5e5e4b..12503f563e36 100644
--- a/drivers/soc/tegra/fuse/fuse-tegra20.c
+++ b/drivers/soc/tegra/fuse/fuse-tegra20.c
@@ -94,9 +94,28 @@ static bool dma_filter(struct dma_chan *chan, void 
*filter_param)
return of_device_is_compatible(np, "nvidia,tegra20-apbdma");
 }
 
+static void tegra20_fuse_release_channel(void *data)
+{
+   struct tegra_fuse *fuse = data;
+
+   dma_release_channel(fuse->apbdma.chan);
+   fuse->apbdma.chan = NULL;
+}
+
+static void tegra20_fuse_free_coherent(void *data)
+{
+   struct tegra_fuse *fuse = data;
+
+   dma_free_coherent(fuse->dev, sizeof(u32), fuse->apbdma.virt,
+ fuse->apbdma.phys);
+   fuse->apbdma.virt = NULL;
+   fuse->apbdma.phys = 0x0;
+}
+
 static int tegra20_fuse_probe(struct tegra_fuse *fuse)
 {
dma_cap_mask_t mask;
+   int err;
 
dma_cap_zero(mask);
dma_cap_set(DMA_SLAVE, mask);
@@ -105,13 +124,21 @@ static int tegra20_fuse_probe(struct tegra_fuse *fuse)
if (!fuse->apbdma.chan)
return -EPROBE_DEFER;
 
+   err = devm_add_action_or_reset(fuse->dev, tegra20_fuse_release_channel,
+  fuse);
+   if (err)
+   return err;
+
fuse->apbdma.virt = 

[PATCH v15 18/39] usb: chipidea: tegra: Add runtime PM and OPP support

2021-11-14 Thread Dmitry Osipenko
The Tegra USB controller belongs to the core power domain and we're going
to enable GENPD support for the core domain. Now USB controller must be
resumed using runtime PM API in order to initialize the USB power state.
We already support runtime PM for the CI device, but CI's PM is separated
from the RPM managed by tegra-usb driver. Add runtime PM and OPP support
to the driver.

Acked-by: Peter Chen 
Reviewed-by: Ulf Hansson 
Signed-off-by: Dmitry Osipenko 
---
 drivers/usb/chipidea/ci_hdrc_tegra.c | 53 
 1 file changed, 46 insertions(+), 7 deletions(-)

diff --git a/drivers/usb/chipidea/ci_hdrc_tegra.c 
b/drivers/usb/chipidea/ci_hdrc_tegra.c
index 60361141ac04..a72a9474afea 100644
--- a/drivers/usb/chipidea/ci_hdrc_tegra.c
+++ b/drivers/usb/chipidea/ci_hdrc_tegra.c
@@ -7,6 +7,7 @@
 #include 
 #include 
 #include 
+#include 
 #include 
 
 #include 
@@ -15,6 +16,8 @@
 #include 
 #include 
 
+#include 
+
 #include "../host/ehci.h"
 
 #include "ci.h"
@@ -278,6 +281,8 @@ static int tegra_usb_probe(struct platform_device *pdev)
if (!usb)
return -ENOMEM;
 
+   platform_set_drvdata(pdev, usb);
+
soc = of_device_get_match_data(>dev);
if (!soc) {
dev_err(>dev, "failed to match OF data\n");
@@ -296,11 +301,14 @@ static int tegra_usb_probe(struct platform_device *pdev)
return err;
}
 
-   err = clk_prepare_enable(usb->clk);
-   if (err < 0) {
-   dev_err(>dev, "failed to enable clock: %d\n", err);
+   err = devm_tegra_core_dev_init_opp_table_common(>dev);
+   if (err)
+   return err;
+
+   pm_runtime_enable(>dev);
+   err = pm_runtime_resume_and_get(>dev);
+   if (err)
return err;
-   }
 
if (device_property_present(>dev, "nvidia,needs-double-reset"))
usb->needs_double_reset = true;
@@ -320,8 +328,6 @@ static int tegra_usb_probe(struct platform_device *pdev)
if (err)
goto fail_power_off;
 
-   platform_set_drvdata(pdev, usb);
-
/* setup and register ChipIdea HDRC device */
usb->soc = soc;
usb->data.name = "tegra-usb";
@@ -350,7 +356,9 @@ static int tegra_usb_probe(struct platform_device *pdev)
 phy_shutdown:
usb_phy_shutdown(usb->phy);
 fail_power_off:
-   clk_disable_unprepare(usb->clk);
+   pm_runtime_put_sync_suspend(>dev);
+   pm_runtime_force_suspend(>dev);
+
return err;
 }
 
@@ -360,15 +368,46 @@ static int tegra_usb_remove(struct platform_device *pdev)
 
ci_hdrc_remove_device(usb->dev);
usb_phy_shutdown(usb->phy);
+
+   pm_runtime_put_sync_suspend(>dev);
+   pm_runtime_force_suspend(>dev);
+
+   return 0;
+}
+
+static int __maybe_unused tegra_usb_runtime_resume(struct device *dev)
+{
+   struct tegra_usb *usb = dev_get_drvdata(dev);
+   int err;
+
+   err = clk_prepare_enable(usb->clk);
+   if (err < 0) {
+   dev_err(dev, "failed to enable clock: %d\n", err);
+   return err;
+   }
+
+   return 0;
+}
+
+static int __maybe_unused tegra_usb_runtime_suspend(struct device *dev)
+{
+   struct tegra_usb *usb = dev_get_drvdata(dev);
+
clk_disable_unprepare(usb->clk);
 
return 0;
 }
 
+static const struct dev_pm_ops tegra_usb_pm = {
+   SET_RUNTIME_PM_OPS(tegra_usb_runtime_suspend, tegra_usb_runtime_resume,
+  NULL)
+};
+
 static struct platform_driver tegra_usb_driver = {
.driver = {
.name = "tegra-usb",
.of_match_table = tegra_usb_of_match,
+   .pm = _usb_pm,
},
.probe = tegra_usb_probe,
.remove = tegra_usb_remove,
-- 
2.33.1



[PATCH v15 16/39] drm/tegra: submit: Remove pm_runtime_enabled() checks

2021-11-14 Thread Dmitry Osipenko
Runtime PM is now universally available, make it mandatory by removing
the pm_runtime_enabled() checks.

Reviewed-by: Ulf Hansson 
Signed-off-by: Dmitry Osipenko 
---
 drivers/gpu/drm/tegra/submit.c | 13 +
 1 file changed, 5 insertions(+), 8 deletions(-)

diff --git a/drivers/gpu/drm/tegra/submit.c b/drivers/gpu/drm/tegra/submit.c
index c32698404e36..3bbd8de5711c 100644
--- a/drivers/gpu/drm/tegra/submit.c
+++ b/drivers/gpu/drm/tegra/submit.c
@@ -504,8 +504,7 @@ static void release_job(struct host1x_job *job)
kfree(job_data->used_mappings);
kfree(job_data);
 
-   if (pm_runtime_enabled(client->base.dev))
-   pm_runtime_put_autosuspend(client->base.dev);
+   pm_runtime_put_autosuspend(client->base.dev);
 }
 
 int tegra_drm_ioctl_channel_submit(struct drm_device *drm, void *data,
@@ -589,12 +588,10 @@ int tegra_drm_ioctl_channel_submit(struct drm_device 
*drm, void *data,
}
 
/* Boot engine. */
-   if (pm_runtime_enabled(context->client->base.dev)) {
-   err = pm_runtime_resume_and_get(context->client->base.dev);
-   if (err < 0) {
-   SUBMIT_ERR(context, "could not power up engine: %d", 
err);
-   goto unpin_job;
-   }
+   err = pm_runtime_resume_and_get(context->client->base.dev);
+   if (err < 0) {
+   SUBMIT_ERR(context, "could not power up engine: %d", err);
+   goto unpin_job;
}
 
job->user_data = job_data;
-- 
2.33.1



[PATCH v15 09/39] gpu: host1x: Add host1x_channel_stop()

2021-11-14 Thread Dmitry Osipenko
Add host1x_channel_stop() which waits till channel becomes idle and then
stops the channel hardware. This is needed for supporting suspend/resume
by host1x drivers since the hardware state is lost after power-gating,
thus the channel needs to be stopped before client enters into suspend.

Tested-by: Peter Geis  # Ouya T30
Tested-by: Paul Fertser  # PAZ00 T20
Tested-by: Nicolas Chauvet  # PAZ00 T20 and TK1 T124
Tested-by: Matt Merhar  # Ouya T30
Signed-off-by: Dmitry Osipenko 
---
 drivers/gpu/host1x/channel.c | 8 
 include/linux/host1x.h   | 1 +
 2 files changed, 9 insertions(+)

diff --git a/drivers/gpu/host1x/channel.c b/drivers/gpu/host1x/channel.c
index 4cd212bb570d..2a9a3a8d5931 100644
--- a/drivers/gpu/host1x/channel.c
+++ b/drivers/gpu/host1x/channel.c
@@ -75,6 +75,14 @@ struct host1x_channel *host1x_channel_get_index(struct 
host1x *host,
return ch;
 }
 
+void host1x_channel_stop(struct host1x_channel *channel)
+{
+   struct host1x *host = dev_get_drvdata(channel->dev->parent);
+
+   host1x_hw_cdma_stop(host, >cdma);
+}
+EXPORT_SYMBOL(host1x_channel_stop);
+
 static void release_channel(struct kref *kref)
 {
struct host1x_channel *channel =
diff --git a/include/linux/host1x.h b/include/linux/host1x.h
index 2ca53d7ed7ca..e8dc5bc41f79 100644
--- a/include/linux/host1x.h
+++ b/include/linux/host1x.h
@@ -226,6 +226,7 @@ struct host1x_job;
 
 struct host1x_channel *host1x_channel_request(struct host1x_client *client);
 struct host1x_channel *host1x_channel_get(struct host1x_channel *channel);
+void host1x_channel_stop(struct host1x_channel *channel);
 void host1x_channel_put(struct host1x_channel *channel);
 int host1x_job_submit(struct host1x_job *job);
 
-- 
2.33.1



[PATCH v15 06/39] dt-bindings: host1x: Document OPP and power domain properties

2021-11-14 Thread Dmitry Osipenko
Document new DVFS OPP table and power domain properties of the Host1x bus
and devices sitting on the bus.

Reviewed-by: Rob Herring 
Signed-off-by: Dmitry Osipenko 
---
 .../display/tegra/nvidia,tegra20-host1x.txt   | 49 +++
 1 file changed, 49 insertions(+)

diff --git 
a/Documentation/devicetree/bindings/display/tegra/nvidia,tegra20-host1x.txt 
b/Documentation/devicetree/bindings/display/tegra/nvidia,tegra20-host1x.txt
index 8a6d3e1ee306..62861a8fb5c6 100644
--- a/Documentation/devicetree/bindings/display/tegra/nvidia,tegra20-host1x.txt
+++ b/Documentation/devicetree/bindings/display/tegra/nvidia,tegra20-host1x.txt
@@ -20,6 +20,18 @@ Required properties:
 - reset-names: Must include the following entries:
   - host1x
 
+Optional properties:
+- operating-points-v2: See ../bindings/opp/opp.txt for details.
+  - power-domains: Phandle to HEG or core power domain.
+
+For each opp entry in 'operating-points-v2' table of host1x and its modules:
+- opp-supported-hw: One bitfield indicating:
+   On Tegra20: SoC process ID mask
+   On Tegra30+: SoC speedo ID mask
+
+   A bitwise AND is performed against the value and if any bit
+   matches, the OPP gets enabled.
+
 Each host1x client module having to perform DMA through the Memory Controller
 should have the interconnect endpoints set to the Memory Client and External
 Memory respectively.
@@ -45,6 +57,8 @@ of the following host1x client modules:
   - interconnect-names: Must include name of the interconnect path for each
 interconnect entry. Consult TRM documentation for information about
 available memory clients, see MEMORY CONTROLLER section.
+  - operating-points-v2: See ../bindings/opp/opp.txt for details.
+  - power-domains: Phandle to MPE power domain.
 
 - vi: video input
 
@@ -128,6 +142,8 @@ of the following host1x client modules:
   - interconnect-names: Must include name of the interconnect path for each
 interconnect entry. Consult TRM documentation for information about
 available memory clients, see MEMORY CONTROLLER section.
+  - operating-points-v2: See ../bindings/opp/opp.txt for details.
+  - power-domains: Phandle to VENC power domain.
 
 - epp: encoder pre-processor
 
@@ -147,6 +163,8 @@ of the following host1x client modules:
   - interconnect-names: Must include name of the interconnect path for each
 interconnect entry. Consult TRM documentation for information about
 available memory clients, see MEMORY CONTROLLER section.
+  - operating-points-v2: See ../bindings/opp/opp.txt for details.
+  - power-domains: Phandle to HEG or core power domain.
 
 - isp: image signal processor
 
@@ -166,6 +184,7 @@ of the following host1x client modules:
   - interconnect-names: Must include name of the interconnect path for each
 interconnect entry. Consult TRM documentation for information about
 available memory clients, see MEMORY CONTROLLER section.
+  - power-domains: Phandle to VENC or core power domain.
 
 - gr2d: 2D graphics engine
 
@@ -185,6 +204,8 @@ of the following host1x client modules:
   - interconnect-names: Must include name of the interconnect path for each
 interconnect entry. Consult TRM documentation for information about
 available memory clients, see MEMORY CONTROLLER section.
+  - operating-points-v2: See ../bindings/opp/opp.txt for details.
+  - power-domains: Phandle to HEG or core power domain.
 
 - gr3d: 3D graphics engine
 
@@ -209,6 +230,8 @@ of the following host1x client modules:
   - interconnect-names: Must include name of the interconnect path for each
 interconnect entry. Consult TRM documentation for information about
 available memory clients, see MEMORY CONTROLLER section.
+  - operating-points-v2: See ../bindings/opp/opp.txt for details.
+  - power-domains: Phandles to 3D or core power domain.
 
 - dc: display controller
 
@@ -241,6 +264,8 @@ of the following host1x client modules:
   - interconnect-names: Must include name of the interconnect path for each
 interconnect entry. Consult TRM documentation for information about
 available memory clients, see MEMORY CONTROLLER section.
+  - operating-points-v2: See ../bindings/opp/opp.txt for details.
+  - power-domains: Phandle to core power domain.
 
 - hdmi: High Definition Multimedia Interface
 
@@ -267,6 +292,7 @@ of the following host1x client modules:
   - nvidia,hpd-gpio: specifies a GPIO used for hotplug detection
   - nvidia,edid: supplies a binary EDID blob
   - nvidia,panel: phandle of a display panel
+  - operating-points-v2: See ../bindings/opp/opp.txt for details.
 
 - tvo: TV encoder output
 
@@ -277,6 +303,10 @@ of the following host1x client modules:
   - clocks: Must contain one entry, for the module clock.
 See ../clocks/clock-bindings.txt for details.
 
+  Optional properties:
+  - operating-points-v2: See ../bindings/opp/opp.txt for details.
+  - power-domains: Phandle to core power domain.
+
 - dsi: display serial interface
 
   Required properties:
@@ 

[PATCH v15 12/39] drm/tegra: gr2d: Support generic power domain and runtime PM

2021-11-14 Thread Dmitry Osipenko
Add runtime power management and support generic power domains.

Reviewed-by: Ulf Hansson 
Tested-by: Peter Geis  # Ouya T30
Tested-by: Paul Fertser  # PAZ00 T20
Tested-by: Nicolas Chauvet  # PAZ00 T20 and TK1 T124
Tested-by: Matt Merhar  # Ouya T30
Signed-off-by: Dmitry Osipenko 
---
 drivers/gpu/drm/tegra/gr2d.c | 184 ---
 1 file changed, 148 insertions(+), 36 deletions(-)

diff --git a/drivers/gpu/drm/tegra/gr2d.c b/drivers/gpu/drm/tegra/gr2d.c
index ba3722f1b865..b4cd7655b3dc 100644
--- a/drivers/gpu/drm/tegra/gr2d.c
+++ b/drivers/gpu/drm/tegra/gr2d.c
@@ -8,12 +8,21 @@
 #include 
 #include 
 #include 
+#include 
 #include 
 
+#include 
+
 #include "drm.h"
 #include "gem.h"
 #include "gr2d.h"
 
+enum {
+   RST_MC,
+   RST_GR2D,
+   RST_GR2D_MAX,
+};
+
 struct gr2d_soc {
unsigned int version;
 };
@@ -21,9 +30,11 @@ struct gr2d_soc {
 struct gr2d {
struct tegra_drm_client client;
struct host1x_channel *channel;
-   struct reset_control *rst;
struct clk *clk;
 
+   struct reset_control_bulk_data resets[RST_GR2D_MAX];
+   unsigned int nresets;
+
const struct gr2d_soc *soc;
 
DECLARE_BITMAP(addr_regs, GR2D_NUM_REGS);
@@ -59,15 +70,22 @@ static int gr2d_init(struct host1x_client *client)
goto free;
}
 
+   pm_runtime_enable(client->dev);
+   pm_runtime_use_autosuspend(client->dev);
+   pm_runtime_set_autosuspend_delay(client->dev, 200);
+
err = tegra_drm_register_client(dev->dev_private, drm);
if (err < 0) {
dev_err(client->dev, "failed to register client: %d\n", err);
-   goto detach;
+   goto disable_rpm;
}
 
return 0;
 
-detach:
+disable_rpm:
+   pm_runtime_dont_use_autosuspend(client->dev);
+   pm_runtime_force_suspend(client->dev);
+
host1x_client_iommu_detach(client);
 free:
host1x_syncpt_put(client->syncpts[0]);
@@ -88,10 +106,15 @@ static int gr2d_exit(struct host1x_client *client)
if (err < 0)
return err;
 
+   pm_runtime_dont_use_autosuspend(client->dev);
+   pm_runtime_force_suspend(client->dev);
+
host1x_client_iommu_detach(client);
host1x_syncpt_put(client->syncpts[0]);
host1x_channel_put(gr2d->channel);
 
+   gr2d->channel = NULL;
+
return 0;
 }
 
@@ -104,10 +127,17 @@ static int gr2d_open_channel(struct tegra_drm_client 
*client,
 struct tegra_drm_context *context)
 {
struct gr2d *gr2d = to_gr2d(client);
+   int err;
+
+   err = pm_runtime_resume_and_get(client->base.dev);
+   if (err)
+   return err;
 
context->channel = host1x_channel_get(gr2d->channel);
-   if (!context->channel)
+   if (!context->channel) {
+   pm_runtime_put(context->client->base.dev);
return -ENOMEM;
+   }
 
return 0;
 }
@@ -115,6 +145,7 @@ static int gr2d_open_channel(struct tegra_drm_client 
*client,
 static void gr2d_close_channel(struct tegra_drm_context *context)
 {
host1x_channel_put(context->channel);
+   pm_runtime_put(context->client->base.dev);
 }
 
 static int gr2d_is_addr_reg(struct device *dev, u32 class, u32 offset)
@@ -193,6 +224,27 @@ static const u32 gr2d_addr_regs[] = {
GR2D_VA_BASE_ADDR_SB,
 };
 
+static int gr2d_get_resets(struct device *dev, struct gr2d *gr2d)
+{
+   int err;
+
+   gr2d->resets[RST_MC].id = "mc";
+   gr2d->resets[RST_GR2D].id = "2d";
+   gr2d->nresets = RST_GR2D_MAX;
+
+   err = devm_reset_control_bulk_get_optional_exclusive_released(
+   dev, gr2d->nresets, gr2d->resets);
+   if (err) {
+   dev_err(dev, "failed to get reset: %d\n", err);
+   return err;
+   }
+
+   if (WARN_ON(!gr2d->resets[RST_GR2D].rstc))
+   return -ENOENT;
+
+   return 0;
+}
+
 static int gr2d_probe(struct platform_device *pdev)
 {
struct device *dev = >dev;
@@ -205,37 +257,23 @@ static int gr2d_probe(struct platform_device *pdev)
if (!gr2d)
return -ENOMEM;
 
+   platform_set_drvdata(pdev, gr2d);
+
gr2d->soc = of_device_get_match_data(dev);
 
syncpts = devm_kzalloc(dev, sizeof(*syncpts), GFP_KERNEL);
if (!syncpts)
return -ENOMEM;
 
-   gr2d->rst = devm_reset_control_get(dev, NULL);
-   if (IS_ERR(gr2d->rst)) {
-   dev_err(dev, "cannot get reset\n");
-   return PTR_ERR(gr2d->rst);
-   }
-
gr2d->clk = devm_clk_get(dev, NULL);
if (IS_ERR(gr2d->clk)) {
dev_err(dev, "cannot get clock\n");
return PTR_ERR(gr2d->clk);
}
 
-   err = clk_prepare_enable(gr2d->clk);
-   if (err) {
-   dev_err(dev, "cannot turn on clock\n");
+   err = gr2d_get_resets(dev, gr2d);
+   if (err)
return err;

[PATCH v15 04/39] dt-bindings: clock: tegra-car: Document new clock sub-nodes

2021-11-14 Thread Dmitry Osipenko
Document sub-nodes which describe Tegra SoC clocks that require a higher
voltage of the core power domain in order to operate properly on a higher
clock rates.  Each node contains a phandle to OPP table and power domain.

The root PLLs and system clocks don't have any specific device dedicated
to them, clock controller is in charge of managing power for them.

Reviewed-by: Rob Herring 
Signed-off-by: Dmitry Osipenko 
---
 .../bindings/clock/nvidia,tegra20-car.yaml| 37 +++
 1 file changed, 37 insertions(+)

diff --git a/Documentation/devicetree/bindings/clock/nvidia,tegra20-car.yaml 
b/Documentation/devicetree/bindings/clock/nvidia,tegra20-car.yaml
index 459d2a525393..f832abb7f11a 100644
--- a/Documentation/devicetree/bindings/clock/nvidia,tegra20-car.yaml
+++ b/Documentation/devicetree/bindings/clock/nvidia,tegra20-car.yaml
@@ -42,6 +42,36 @@ properties:
   "#reset-cells":
 const: 1
 
+patternProperties:
+  "^(sclk)|(pll-[cem])$":
+type: object
+properties:
+  compatible:
+enum:
+  - nvidia,tegra20-sclk
+  - nvidia,tegra30-sclk
+  - nvidia,tegra30-pllc
+  - nvidia,tegra30-plle
+  - nvidia,tegra30-pllm
+
+  operating-points-v2: true
+
+  clocks:
+items:
+  - description: node's clock
+
+  power-domains:
+maxItems: 1
+description: phandle to the core SoC power domain
+
+required:
+  - compatible
+  - operating-points-v2
+  - clocks
+  - power-domains
+
+additionalProperties: false
+
 required:
   - compatible
   - reg
@@ -59,6 +89,13 @@ examples:
 reg = <0x60006000 0x1000>;
 #clock-cells = <1>;
 #reset-cells = <1>;
+
+sclk {
+compatible = "nvidia,tegra20-sclk";
+operating-points-v2 = <_table>;
+clocks = <_car TEGRA20_CLK_SCLK>;
+power-domains = <>;
+};
 };
 
 usb-controller@c5004000 {
-- 
2.33.1



[PATCH v15 13/39] drm/tegra: gr3d: Support generic power domain and runtime PM

2021-11-14 Thread Dmitry Osipenko
Add runtime power management and support generic power domains.

Reviewed-by: Ulf Hansson 
Tested-by: Peter Geis  # Ouya T30
Tested-by: Paul Fertser  # PAZ00 T20
Tested-by: Nicolas Chauvet  # PAZ00 T20 and TK1 T124
Tested-by: Matt Merhar  # Ouya T30
Signed-off-by: Dmitry Osipenko 
---
 drivers/gpu/drm/tegra/gr3d.c | 363 +--
 1 file changed, 305 insertions(+), 58 deletions(-)

diff --git a/drivers/gpu/drm/tegra/gr3d.c b/drivers/gpu/drm/tegra/gr3d.c
index 24442ade0da3..25f3f9820e92 100644
--- a/drivers/gpu/drm/tegra/gr3d.c
+++ b/drivers/gpu/drm/tegra/gr3d.c
@@ -5,32 +5,47 @@
  */
 
 #include 
+#include 
 #include 
 #include 
 #include 
 #include 
 #include 
+#include 
+#include 
+#include 
 #include 
 
+#include 
 #include 
 
 #include "drm.h"
 #include "gem.h"
 #include "gr3d.h"
 
+enum {
+   RST_MC,
+   RST_GR3D,
+   RST_MC2,
+   RST_GR3D2,
+   RST_GR3D_MAX,
+};
+
 struct gr3d_soc {
unsigned int version;
+   unsigned int num_clocks;
+   unsigned int num_resets;
 };
 
 struct gr3d {
struct tegra_drm_client client;
struct host1x_channel *channel;
-   struct clk *clk_secondary;
-   struct clk *clk;
-   struct reset_control *rst_secondary;
-   struct reset_control *rst;
 
const struct gr3d_soc *soc;
+   struct clk_bulk_data *clocks;
+   unsigned int nclocks;
+   struct reset_control_bulk_data resets[RST_GR3D_MAX];
+   unsigned int nresets;
 
DECLARE_BITMAP(addr_regs, GR3D_NUM_REGS);
 };
@@ -65,15 +80,22 @@ static int gr3d_init(struct host1x_client *client)
goto free;
}
 
+   pm_runtime_enable(client->dev);
+   pm_runtime_use_autosuspend(client->dev);
+   pm_runtime_set_autosuspend_delay(client->dev, 200);
+
err = tegra_drm_register_client(dev->dev_private, drm);
if (err < 0) {
dev_err(client->dev, "failed to register client: %d\n", err);
-   goto detach;
+   goto disable_rpm;
}
 
return 0;
 
-detach:
+disable_rpm:
+   pm_runtime_dont_use_autosuspend(client->dev);
+   pm_runtime_force_suspend(client->dev);
+
host1x_client_iommu_detach(client);
 free:
host1x_syncpt_put(client->syncpts[0]);
@@ -93,10 +115,15 @@ static int gr3d_exit(struct host1x_client *client)
if (err < 0)
return err;
 
+   pm_runtime_dont_use_autosuspend(client->dev);
+   pm_runtime_force_suspend(client->dev);
+
host1x_client_iommu_detach(client);
host1x_syncpt_put(client->syncpts[0]);
host1x_channel_put(gr3d->channel);
 
+   gr3d->channel = NULL;
+
return 0;
 }
 
@@ -109,10 +136,17 @@ static int gr3d_open_channel(struct tegra_drm_client 
*client,
 struct tegra_drm_context *context)
 {
struct gr3d *gr3d = to_gr3d(client);
+   int err;
+
+   err = pm_runtime_resume_and_get(client->base.dev);
+   if (err)
+   return err;
 
context->channel = host1x_channel_get(gr3d->channel);
-   if (!context->channel)
+   if (!context->channel) {
+   pm_runtime_put(context->client->base.dev);
return -ENOMEM;
+   }
 
return 0;
 }
@@ -120,6 +154,7 @@ static int gr3d_open_channel(struct tegra_drm_client 
*client,
 static void gr3d_close_channel(struct tegra_drm_context *context)
 {
host1x_channel_put(context->channel);
+   pm_runtime_put(context->client->base.dev);
 }
 
 static int gr3d_is_addr_reg(struct device *dev, u32 class, u32 offset)
@@ -155,14 +190,20 @@ static const struct tegra_drm_client_ops gr3d_ops = {
 
 static const struct gr3d_soc tegra20_gr3d_soc = {
.version = 0x20,
+   .num_clocks = 1,
+   .num_resets = 2,
 };
 
 static const struct gr3d_soc tegra30_gr3d_soc = {
.version = 0x30,
+   .num_clocks = 2,
+   .num_resets = 4,
 };
 
 static const struct gr3d_soc tegra114_gr3d_soc = {
.version = 0x35,
+   .num_clocks = 1,
+   .num_resets = 2,
 };
 
 static const struct of_device_id tegra_gr3d_match[] = {
@@ -278,69 +319,216 @@ static const u32 gr3d_addr_regs[] = {
GR3D_GLOBAL_SAMP23SURFADDR(15),
 };
 
-static int gr3d_probe(struct platform_device *pdev)
+static int gr3d_power_up_legacy_domain(struct device *dev, const char *name,
+  unsigned int id)
 {
-   struct device_node *np = pdev->dev.of_node;
-   struct host1x_syncpt **syncpts;
-   struct gr3d *gr3d;
+   struct gr3d *gr3d = dev_get_drvdata(dev);
+   struct reset_control *reset;
+   struct clk *clk;
unsigned int i;
int err;
 
-   gr3d = devm_kzalloc(>dev, sizeof(*gr3d), GFP_KERNEL);
-   if (!gr3d)
-   return -ENOMEM;
-
-   gr3d->soc = of_device_get_match_data(>dev);
+   /*
+* Tegra20 device-tree doesn't specify 3d clock name and there is only
+* one clock for Tegra20. 

[PATCH v15 11/39] drm/tegra: hdmi: Add OPP support

2021-11-14 Thread Dmitry Osipenko
The HDMI on Tegra belongs to the core power domain and we're going to
enable GENPD support for the core domain. Now HDMI driver must use
OPP API for driving the controller's clock rate because OPP API takes
care of reconfiguring the domain's performance state based on HDMI clock
rate. Add OPP support to the HDMI driver.

Reviewed-by: Ulf Hansson 
Signed-off-by: Dmitry Osipenko 
---
 drivers/gpu/drm/tegra/hdmi.c | 16 
 1 file changed, 12 insertions(+), 4 deletions(-)

diff --git a/drivers/gpu/drm/tegra/hdmi.c b/drivers/gpu/drm/tegra/hdmi.c
index e5d2a4026028..9a87d351a828 100644
--- a/drivers/gpu/drm/tegra/hdmi.c
+++ b/drivers/gpu/drm/tegra/hdmi.c
@@ -11,10 +11,13 @@
 #include 
 #include 
 #include 
+#include 
 #include 
 #include 
 #include 
 
+#include 
+
 #include 
 #include 
 #include 
@@ -1195,7 +1198,7 @@ static void tegra_hdmi_encoder_enable(struct drm_encoder 
*encoder)
h_back_porch = mode->htotal - mode->hsync_end;
h_front_porch = mode->hsync_start - mode->hdisplay;
 
-   err = clk_set_rate(hdmi->clk, hdmi->pixel_clock);
+   err = dev_pm_opp_set_rate(hdmi->dev, hdmi->pixel_clock);
if (err < 0) {
dev_err(hdmi->dev, "failed to set HDMI clock frequency: %d\n",
err);
@@ -1732,7 +1735,14 @@ static int tegra_hdmi_probe(struct platform_device *pdev)
}
 
platform_set_drvdata(pdev, hdmi);
-   pm_runtime_enable(>dev);
+
+   err = devm_pm_runtime_enable(>dev);
+   if (err)
+   return err;
+
+   err = devm_tegra_core_dev_init_opp_table_common(>dev);
+   if (err)
+   return err;
 
INIT_LIST_HEAD(>client.list);
hdmi->client.ops = _client_ops;
@@ -1753,8 +1763,6 @@ static int tegra_hdmi_remove(struct platform_device *pdev)
struct tegra_hdmi *hdmi = platform_get_drvdata(pdev);
int err;
 
-   pm_runtime_disable(>dev);
-
err = host1x_client_unregister(>client);
if (err < 0) {
dev_err(>dev, "failed to unregister host1x client: %d\n",
-- 
2.33.1



[PATCH v15 08/39] gpu: host1x: Add initial runtime PM and OPP support

2021-11-14 Thread Dmitry Osipenko
Add runtime PM and OPP support to the Host1x driver. For the starter we
will keep host1x always-on because dynamic power management require a major
refactoring of the driver code since lot's of code paths are missing the
RPM handling and we're going to remove some of these paths in the future.

Reviewed-by: Ulf Hansson 
Tested-by: Peter Geis  # Ouya T30
Tested-by: Paul Fertser  # PAZ00 T20
Tested-by: Nicolas Chauvet  # PAZ00 T20 and TK1 T124
Tested-by: Matt Merhar  # Ouya T30
Signed-off-by: Dmitry Osipenko 
---
 drivers/gpu/host1x/debug.c |  15 +++
 drivers/gpu/host1x/dev.c   | 150 +++--
 drivers/gpu/host1x/dev.h   |   3 +-
 drivers/gpu/host1x/hw/channel_hw.c |  44 -
 drivers/gpu/host1x/intr.c  |   3 -
 drivers/gpu/host1x/syncpt.c|   5 +-
 6 files changed, 164 insertions(+), 56 deletions(-)

diff --git a/drivers/gpu/host1x/debug.c b/drivers/gpu/host1x/debug.c
index 8a14880c61bb..18d9c8d206e3 100644
--- a/drivers/gpu/host1x/debug.c
+++ b/drivers/gpu/host1x/debug.c
@@ -7,6 +7,7 @@
  */
 
 #include 
+#include 
 #include 
 #include 
 
@@ -52,6 +53,11 @@ static int show_channel(struct host1x_channel *ch, void 
*data, bool show_fifo)
 {
struct host1x *m = dev_get_drvdata(ch->dev->parent);
struct output *o = data;
+   int err;
+
+   err = pm_runtime_resume_and_get(m->dev);
+   if (err < 0)
+   return err;
 
mutex_lock(>cdma.lock);
mutex_lock(_lock);
@@ -64,6 +70,8 @@ static int show_channel(struct host1x_channel *ch, void 
*data, bool show_fifo)
mutex_unlock(_lock);
mutex_unlock(>cdma.lock);
 
+   pm_runtime_put(m->dev);
+
return 0;
 }
 
@@ -71,9 +79,14 @@ static void show_syncpts(struct host1x *m, struct output *o)
 {
struct list_head *pos;
unsigned int i;
+   int err;
 
host1x_debug_output(o, " syncpts \n");
 
+   err = pm_runtime_resume_and_get(m->dev);
+   if (err < 0)
+   return;
+
for (i = 0; i < host1x_syncpt_nb_pts(m); i++) {
u32 max = host1x_syncpt_read_max(m->syncpt + i);
u32 min = host1x_syncpt_load(m->syncpt + i);
@@ -101,6 +114,8 @@ static void show_syncpts(struct host1x *m, struct output *o)
base_val);
}
 
+   pm_runtime_put(m->dev);
+
host1x_debug_output(o, "\n");
 }
 
diff --git a/drivers/gpu/host1x/dev.c b/drivers/gpu/host1x/dev.c
index 3d4cabdbc78d..c42ab78327e7 100644
--- a/drivers/gpu/host1x/dev.c
+++ b/drivers/gpu/host1x/dev.c
@@ -6,14 +6,18 @@
  */
 
 #include 
+#include 
 #include 
 #include 
 #include 
 #include 
 #include 
 #include 
+#include 
 #include 
 
+#include 
+
 #define CREATE_TRACE_POINTS
 #include 
 #undef CREATE_TRACE_POINTS
@@ -208,6 +212,9 @@ static void host1x_setup_sid_table(struct host1x *host)
const struct host1x_info *info = host->info;
unsigned int i;
 
+   if (!info->has_hypervisor)
+   return;
+
for (i = 0; i < info->num_sid_entries; i++) {
const struct host1x_sid_entry *entry = >sid_table[i];
 
@@ -365,6 +372,27 @@ static void host1x_iommu_exit(struct host1x *host)
}
 }
 
+static int host1x_get_resets(struct host1x *host)
+{
+   int err;
+
+   host->resets[0].id = "mc";
+   host->resets[1].id = "host1x";
+   host->nresets = ARRAY_SIZE(host->resets);
+
+   err = devm_reset_control_bulk_get_optional_exclusive_released(
+   host->dev, host->nresets, host->resets);
+   if (err) {
+   dev_err(host->dev, "failed to get reset: %d\n", err);
+   return err;
+   }
+
+   if (WARN_ON(!host->resets[1].rstc))
+   return -ENOENT;
+
+   return 0;
+}
+
 static int host1x_probe(struct platform_device *pdev)
 {
struct host1x *host;
@@ -442,12 +470,9 @@ static int host1x_probe(struct platform_device *pdev)
return err;
}
 
-   host->rst = devm_reset_control_get(>dev, "host1x");
-   if (IS_ERR(host->rst)) {
-   err = PTR_ERR(host->rst);
-   dev_err(>dev, "failed to get reset: %d\n", err);
+   err = host1x_get_resets(host);
+   if (err)
return err;
-   }
 
err = host1x_iommu_init(host);
if (err < 0) {
@@ -462,22 +487,10 @@ static int host1x_probe(struct platform_device *pdev)
goto iommu_exit;
}
 
-   err = clk_prepare_enable(host->clk);
-   if (err < 0) {
-   dev_err(>dev, "failed to enable clock\n");
-   goto free_channels;
-   }
-
-   err = reset_control_deassert(host->rst);
-   if (err < 0) {
-   dev_err(>dev, "failed to deassert reset: %d\n", err);
-   goto unprepare_disable;
-   }
-
err = host1x_syncpt_init(host);
if (err) {
dev_err(>dev, "failed to initialize syncpts\n");
-   

[PATCH v15 10/39] drm/tegra: dc: Support OPP and SoC core voltage scaling

2021-11-14 Thread Dmitry Osipenko
Add OPP and SoC core voltage scaling support to the display controller
driver. This is required for enabling system-wide DVFS on pre-Tegra186
SoCs.

Reviewed-by: Ulf Hansson 
Tested-by: Peter Geis  # Ouya T30
Tested-by: Paul Fertser  # PAZ00 T20
Tested-by: Nicolas Chauvet  # PAZ00 T20 and TK1 T124
Tested-by: Matt Merhar  # Ouya T30
Signed-off-by: Dmitry Osipenko 
---
 drivers/gpu/drm/tegra/dc.c | 79 ++
 drivers/gpu/drm/tegra/dc.h |  2 +
 2 files changed, 81 insertions(+)

diff --git a/drivers/gpu/drm/tegra/dc.c b/drivers/gpu/drm/tegra/dc.c
index a457ee954a49..eb70eee8992a 100644
--- a/drivers/gpu/drm/tegra/dc.c
+++ b/drivers/gpu/drm/tegra/dc.c
@@ -11,9 +11,12 @@
 #include 
 #include 
 #include 
+#include 
+#include 
 #include 
 #include 
 
+#include 
 #include 
 
 #include 
@@ -1834,6 +1837,52 @@ int tegra_dc_state_setup_clock(struct tegra_dc *dc,
return 0;
 }
 
+static void tegra_dc_update_voltage_state(struct tegra_dc *dc,
+ struct tegra_dc_state *state)
+{
+   unsigned long rate, pstate;
+   struct dev_pm_opp *opp;
+   int err;
+
+   if (!dc->has_opp_table)
+   return;
+
+   /* calculate actual pixel clock rate which depends on internal divider 
*/
+   rate = DIV_ROUND_UP(clk_get_rate(dc->clk) * 2, state->div + 2);
+
+   /* find suitable OPP for the rate */
+   opp = dev_pm_opp_find_freq_ceil(dc->dev, );
+
+   /*
+* Very high resolution modes may results in a clock rate that is
+* above the characterized maximum. In this case it's okay to fall
+* back to the characterized maximum.
+*/
+   if (opp == ERR_PTR(-ERANGE))
+   opp = dev_pm_opp_find_freq_floor(dc->dev, );
+
+   if (IS_ERR(opp)) {
+   dev_err(dc->dev, "failed to find OPP for %luHz: %pe\n",
+   rate, opp);
+   return;
+   }
+
+   pstate = dev_pm_opp_get_required_pstate(opp, 0);
+   dev_pm_opp_put(opp);
+
+   /*
+* The minimum core voltage depends on the pixel clock rate (which
+* depends on internal clock divider of the CRTC) and not on the
+* rate of the display controller clock. This is why we're not using
+* dev_pm_opp_set_rate() API and instead controlling the power domain
+* directly.
+*/
+   err = dev_pm_genpd_set_performance_state(dc->dev, pstate);
+   if (err)
+   dev_err(dc->dev, "failed to set power domain state to %lu: 
%d\n",
+   pstate, err);
+}
+
 static void tegra_dc_set_clock_rate(struct tegra_dc *dc,
struct tegra_dc_state *state)
 {
@@ -1867,6 +1916,8 @@ static void tegra_dc_set_clock_rate(struct tegra_dc *dc,
DRM_DEBUG_KMS("rate: %lu, div: %u\n", clk_get_rate(dc->clk),
  state->div);
DRM_DEBUG_KMS("pclk: %lu\n", state->pclk);
+
+   tegra_dc_update_voltage_state(dc, state);
 }
 
 static void tegra_dc_stop(struct tegra_dc *dc)
@@ -2057,6 +2108,13 @@ static void tegra_crtc_atomic_disable(struct drm_crtc 
*crtc,
err = host1x_client_suspend(>client);
if (err < 0)
dev_err(dc->dev, "failed to suspend: %d\n", err);
+
+   if (dc->has_opp_table) {
+   err = dev_pm_genpd_set_performance_state(dc->dev, 0);
+   if (err)
+   dev_err(dc->dev,
+   "failed to clear power domain state: %d\n", 
err);
+   }
 }
 
 static void tegra_crtc_atomic_enable(struct drm_crtc *crtc,
@@ -3058,6 +3116,23 @@ static int tegra_dc_couple(struct tegra_dc *dc)
return 0;
 }
 
+static int tegra_dc_init_opp_table(struct tegra_dc *dc)
+{
+   struct tegra_core_opp_params opp_params = {};
+   int err;
+
+   err = devm_tegra_core_dev_init_opp_table(dc->dev, _params);
+   if (err && err != -ENODEV)
+   return err;
+
+   if (err)
+   dc->has_opp_table = false;
+   else
+   dc->has_opp_table = true;
+
+   return 0;
+}
+
 static int tegra_dc_probe(struct platform_device *pdev)
 {
u64 dma_mask = dma_get_mask(pdev->dev.parent);
@@ -3123,6 +3198,10 @@ static int tegra_dc_probe(struct platform_device *pdev)
tegra_powergate_power_off(dc->powergate);
}
 
+   err = tegra_dc_init_opp_table(dc);
+   if (err < 0)
+   return err;
+
dc->regs = devm_platform_ioremap_resource(pdev, 0);
if (IS_ERR(dc->regs))
return PTR_ERR(dc->regs);
diff --git a/drivers/gpu/drm/tegra/dc.h b/drivers/gpu/drm/tegra/dc.h
index c9c4c45c0518..3f91a10ea6c7 100644
--- a/drivers/gpu/drm/tegra/dc.h
+++ b/drivers/gpu/drm/tegra/dc.h
@@ -101,6 +101,8 @@ struct tegra_dc {
struct drm_info_list *debugfs_files;
 
const struct tegra_dc_soc_info *soc;
+
+   bool has_opp_table;
 };
 
 static inline struct tegra_dc *
-- 
2.33.1



[PATCH v15 05/39] clk: tegra: Support runtime PM and power domain

2021-11-14 Thread Dmitry Osipenko
The Clock-and-Reset controller resides in a core power domain on NVIDIA
Tegra SoCs.  In order to support voltage scaling of the core power domain,
we hook up DVFS-capable clocks to the core GENPD for managing of the
GENPD's performance state based on the clock changes.

Some clocks don't have any specific physical hardware unit that backs
them, like root PLLs and system clock and they have theirs own voltage
requirements.  This patch adds new clk-device driver that backs the clocks
and provides runtime PM functionality for them.  A virtual clk-device is
created for each such DVFS-capable clock at the clock's registration time
by the new tegra_clk_register() helper.  Driver changes clock's device
GENPD performance state based on clk-rate notifications.

In result we have this sequence of events:

  1. Clock driver creates virtual device for selective clocks, enables
 runtime PM for the created device and registers the clock.
  2. Clk-device driver starts to listen to clock rate changes.
  3. Something changes clk rate or enables/disables clk.
  4. CCF core propagates the change through the clk tree.
  5. Clk-device driver gets clock rate-change notification or GENPD core
 handles prepare/unprepare of the clock.
  6. Clk-device driver changes GENPD performance state on clock rate
 change.
  7. GENPD driver changes voltage regulator state change.
  8. The regulator state is committed to hardware via I2C.

We rely on fact that DVFS is not needed for Tegra I2C and that Tegra I2C
driver already keeps clock always-prepared.  Hence I2C subsystem stays
independent from the clk power management and there are no deadlock spots
in the sequence.

Currently all clocks are registered very early during kernel boot when the
device driver core isn't available yet.  The clk-device can't be created
at that time.  This patch splits the registration of the clocks in two
phases:

  1. Register all essential clocks which don't use RPM and are needed
 during early boot.

  2. Register at a later boot time the rest of clocks.

This patch adds power management support for Tegra20 and Tegra30 clocks.

Reviewed-by: Ulf Hansson 
Tested-by: Peter Geis  # Ouya T30
Tested-by: Paul Fertser  # PAZ00 T20
Tested-by: Nicolas Chauvet  # PAZ00 T20 and TK1 T124
Tested-by: Matt Merhar  # Ouya T30
Signed-off-by: Dmitry Osipenko 
---
 drivers/clk/tegra/Makefile  |   1 +
 drivers/clk/tegra/clk-device.c  | 199 
 drivers/clk/tegra/clk-pll.c |   2 +-
 drivers/clk/tegra/clk-super.c   |   2 +-
 drivers/clk/tegra/clk-tegra20.c |  77 +---
 drivers/clk/tegra/clk-tegra30.c | 116 ++-
 drivers/clk/tegra/clk.c |  75 +++-
 drivers/clk/tegra/clk.h |   2 +
 8 files changed, 420 insertions(+), 54 deletions(-)
 create mode 100644 drivers/clk/tegra/clk-device.c

diff --git a/drivers/clk/tegra/Makefile b/drivers/clk/tegra/Makefile
index 7b1816856eb5..a0715cdfc1a4 100644
--- a/drivers/clk/tegra/Makefile
+++ b/drivers/clk/tegra/Makefile
@@ -1,6 +1,7 @@
 # SPDX-License-Identifier: GPL-2.0
 obj-y  += clk.o
 obj-y  += clk-audio-sync.o
+obj-y  += clk-device.o
 obj-y  += clk-dfll.o
 obj-y  += clk-divider.o
 obj-y  += clk-periph.o
diff --git a/drivers/clk/tegra/clk-device.c b/drivers/clk/tegra/clk-device.c
new file mode 100644
index ..c58beaf8afbc
--- /dev/null
+++ b/drivers/clk/tegra/clk-device.c
@@ -0,0 +1,199 @@
+// SPDX-License-Identifier: GPL-2.0-only
+
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+
+#include 
+
+#include "clk.h"
+
+/*
+ * This driver manages performance state of the core power domain for the
+ * independent PLLs and system clocks.  We created a virtual clock device
+ * for such clocks, see tegra_clk_dev_register().
+ */
+
+struct tegra_clk_device {
+   struct notifier_block clk_nb;
+   struct device *dev;
+   struct clk_hw *hw;
+   struct mutex lock;
+};
+
+static int tegra_clock_set_pd_state(struct tegra_clk_device *clk_dev,
+   unsigned long rate)
+{
+   struct device *dev = clk_dev->dev;
+   struct dev_pm_opp *opp;
+   unsigned int pstate;
+
+   opp = dev_pm_opp_find_freq_ceil(dev, );
+   if (opp == ERR_PTR(-ERANGE)) {
+   /*
+* Some clocks may be unused by a particular board and they
+* may have uninitiated clock rate that is overly high.  In
+* this case clock is expected to be disabled, but still we
+* need to set up performance state of the power domain and
+* not error out clk initialization.  A typical example is
+* a PCIe clock on Android tablets.
+*/
+   dev_dbg(dev, "failed to find ceil 

[PATCH v15 07/39] dt-bindings: host1x: Document Memory Client resets of Host1x, GR2D and GR3D

2021-11-14 Thread Dmitry Osipenko
Memory Client should be blocked before hardware reset is asserted in order
to prevent memory corruption and hanging of memory controller.

Document Memory Client resets of Host1x, GR2D and GR3D hardware units.

Reviewed-by: Rob Herring 
Signed-off-by: Dmitry Osipenko 
---
 .../bindings/display/tegra/nvidia,tegra20-host1x.txt  | 4 
 1 file changed, 4 insertions(+)

diff --git 
a/Documentation/devicetree/bindings/display/tegra/nvidia,tegra20-host1x.txt 
b/Documentation/devicetree/bindings/display/tegra/nvidia,tegra20-host1x.txt
index 62861a8fb5c6..e61999ce54e9 100644
--- a/Documentation/devicetree/bindings/display/tegra/nvidia,tegra20-host1x.txt
+++ b/Documentation/devicetree/bindings/display/tegra/nvidia,tegra20-host1x.txt
@@ -19,6 +19,7 @@ Required properties:
   See ../reset/reset.txt for details.
 - reset-names: Must include the following entries:
   - host1x
+  - mc
 
 Optional properties:
 - operating-points-v2: See ../bindings/opp/opp.txt for details.
@@ -198,6 +199,7 @@ of the following host1x client modules:
 See ../reset/reset.txt for details.
   - reset-names: Must include the following entries:
 - 2d
+- mc
 
   Optional properties:
   - interconnects: Must contain entry for the GR2D memory clients.
@@ -224,6 +226,8 @@ of the following host1x client modules:
   - reset-names: Must include the following entries:
 - 3d
 - 3d2 (Only required on SoCs with two 3D clocks)
+- mc
+- mc2 (Only required on SoCs with two 3D clocks)
 
   Optional properties:
   - interconnects: Must contain entry for the GR3D memory clients.
-- 
2.33.1



[PATCH v15 03/39] soc/tegra: Don't print error message when OPPs not available

2021-11-14 Thread Dmitry Osipenko
Previously we assumed that devm_tegra_core_dev_init_opp_table() will
be used only by drivers that will always have device with OPP table,
but this is not true anymore. For example now Tegra30 will have OPP table
for PWM, but Tegra20 not and both use the same driver. Hence let's not
print the error message about missing OPP table in the common helper,
we can print it elsewhere.

Reviewed-by: Ulf Hansson 
Signed-off-by: Dmitry Osipenko 
---
 drivers/soc/tegra/common.c | 4 +---
 1 file changed, 1 insertion(+), 3 deletions(-)

diff --git a/drivers/soc/tegra/common.c b/drivers/soc/tegra/common.c
index 35c882da55fc..32c346b72635 100644
--- a/drivers/soc/tegra/common.c
+++ b/drivers/soc/tegra/common.c
@@ -136,9 +136,7 @@ int devm_tegra_core_dev_init_opp_table(struct device *dev,
 */
err = devm_pm_opp_of_add_table(dev);
if (err) {
-   if (err == -ENODEV)
-   dev_err_once(dev, "OPP table not found, please update 
device-tree\n");
-   else
+   if (err != -ENODEV)
dev_err(dev, "failed to add OPP table: %d\n", err);
 
return err;
-- 
2.33.1



[PATCH v15 01/39] soc/tegra: Enable runtime PM during OPP state-syncing

2021-11-14 Thread Dmitry Osipenko
GENPD core now can set up domain's performance state properly while device
is RPM-suspended. Runtime PM of a device must be enabled during setup
because GENPD checks whether device is suspended and check doesn't work
while RPM is disabled. Instead of replicating the boilerplate RPM-enable
code around OPP helper for each driver, let's make OPP helper to take care
of enabling it.

Reviewed-by: Ulf Hansson 
Signed-off-by: Dmitry Osipenko 
---
 drivers/soc/tegra/common.c | 25 +
 1 file changed, 25 insertions(+)

diff --git a/drivers/soc/tegra/common.c b/drivers/soc/tegra/common.c
index cd33e99249c3..35c882da55fc 100644
--- a/drivers/soc/tegra/common.c
+++ b/drivers/soc/tegra/common.c
@@ -10,6 +10,7 @@
 #include 
 #include 
 #include 
+#include 
 
 #include 
 #include 
@@ -43,6 +44,7 @@ static int tegra_core_dev_init_opp_state(struct device *dev)
 {
unsigned long rate;
struct clk *clk;
+   bool rpm_enabled;
int err;
 
clk = devm_clk_get(dev, NULL);
@@ -57,8 +59,31 @@ static int tegra_core_dev_init_opp_state(struct device *dev)
return -EINVAL;
}
 
+   /*
+* Runtime PM of the device must be enabled in order to set up
+* GENPD's performance properly because GENPD core checks whether
+* device is suspended and this check doesn't work while RPM is
+* disabled. This makes sure the OPP vote below gets cached in
+* GENPD for the device. Instead, the vote is done the next time
+* the device gets runtime resumed.
+*/
+   rpm_enabled = pm_runtime_enabled(dev);
+   if (!rpm_enabled)
+   pm_runtime_enable(dev);
+
+   /* should never happen in practice */
+   if (!pm_runtime_enabled(dev)) {
+   dev_WARN(dev, "failed to enable runtime PM\n");
+   pm_runtime_disable(dev);
+   return -EINVAL;
+   }
+
/* first dummy rate-setting initializes voltage vote */
err = dev_pm_opp_set_rate(dev, rate);
+
+   if (!rpm_enabled)
+   pm_runtime_disable(dev);
+
if (err) {
dev_err(dev, "failed to initialize OPP clock: %d\n", err);
return err;
-- 
2.33.1



[PATCH v15 02/39] soc/tegra: Add devm_tegra_core_dev_init_opp_table_common()

2021-11-14 Thread Dmitry Osipenko
Only couple drivers need to get the -ENODEV error code and majority of
drivers need to explicitly initialize the performance state. Add new
common helper which sets up OPP table for these drivers.

Reviewed-by: Ulf Hansson 
Signed-off-by: Dmitry Osipenko 
---
 include/soc/tegra/common.h | 15 +++
 1 file changed, 15 insertions(+)

diff --git a/include/soc/tegra/common.h b/include/soc/tegra/common.h
index af41ad80ec21..8ec1ac07fc85 100644
--- a/include/soc/tegra/common.h
+++ b/include/soc/tegra/common.h
@@ -39,4 +39,19 @@ devm_tegra_core_dev_init_opp_table(struct device *dev,
 }
 #endif
 
+static inline int
+devm_tegra_core_dev_init_opp_table_common(struct device *dev)
+{
+   struct tegra_core_opp_params opp_params = {};
+   int err;
+
+   opp_params.init_state = true;
+
+   err = devm_tegra_core_dev_init_opp_table(dev, _params);
+   if (err != -ENODEV)
+   return err;
+
+   return 0;
+}
+
 #endif /* __SOC_TEGRA_COMMON_H__ */
-- 
2.33.1



[PATCH v15 00/39] NVIDIA Tegra power management patches for 5.17

2021-11-14 Thread Dmitry Osipenko
This series adds runtime PM support to Tegra drivers and enables core
voltage scaling for Tegra20/30 SoCs, resolving overheating troubles.

All patches in this series are interdependent and should go via Tegra tree
for simplicity.

Changelog:

v15: - Added r-b from Ulf Hansson to "soc/tegra: Enable runtime PM during
   OPP state-syncing" patch and added extra sanity-check to this patch
   which ensures that RPM is indeed enabled.

 - Fixed double RPM-disable on unbind for drivers that used
   devm_pm_runtime_enable() + pm_runtime_force_suspend().

 - Added link with additional info to commit message of "regulators:
   Prepare for suspend" patch.

v14: - Fixed missing runtime PM syncing on removal of drivers, which was
   spotted by Ulf Hansson in v13.

 - clk-device driver now resumes RPM on system suspend instead of
   preparing clock which it backs. This was suggested by Ulf Hansson.

 - clk-device driver now syncs power domain performance unconditionally
   during driver's probe time since GENPD API allows to do this now.
   It was spotted by Ulf Hansson.

 - Added new "Enable runtime PM during OPP state-syncing" patch, which
   allows drivers to sync state at any time. Previously drivers were
   obligated to take care of enabling RPM at the "right" time.

 - Moved runtime PM initialization/uninitialization of DRM drivers that
   use host1x channel to host1x client init/deinit phase. I noticed that
   there is UAF problem because RPM-suspend callback waits until channel
   is idling and channel is already released/freed during driver's removal
   phase.

 - Added system suspend support to the new NVDEC DRM driver.

 - Added missing pm_runtime_mark_last_busy() to DRM driver.

 - Corrected VDE GENPD patch which previously made video decoder clock
   always-enabled by mistake if legacy PD code path was used. It was
   spotted while we were testing VDE on Tegra114 that doesn't support
   GENPD yet.

 - Added ack from Peter Chen to the USB patch that he gave to v13.

 - Changed OPP table names in accordance to the new naming scheme
   required by the recent core OPP binding.

 - Added 500MHz memory OPP entry used by ASUS Transformer tablets.

v13: - Fixed compile-test error reported by build bot by reverting the
   mmc/ patch to v11. The sdhci_suspend/resume_host() functions aren't
   available with the disabled CONFIG_PM_SLEEP, some code needs the
   ifdef.

 - Added last r-b from Rob Herring for the DT patches.

 - Corrected clk/ PM domain-support patch by not using the
   devm_tegra_core_dev_init_opp_table_common() helper, which I
   utilized in v12. The clk driver implements its own power domain
   state syncing and common helper shouldn't be used. This fixes driver
   probing for some clocks on some devices. It was reported by
   Svyatoslav Ryhel for PLLE OPP error on T30 Asus Transformer tablet.

v12: - Added r-b from Rob Herring to the host1x binding patch.

 - Added acks from Hans Verkuil to the video decoder patches.

 - In the v11 changelog I forgot to mention that the clk-binding
   patch was also changed with a corrected regex pattern and removed
   'clocks' sub-node. This patch needs r-b or ack too.

 - Added new "Rename 3d power domains" patch to match the DT schema
   naming requirement. Thanks to David Heidelberg for spotting this
   problem.

 - Replaced #ifdef CONFIG_PM_SLEEP with maybe_unused in the MMC patch
   to make code cleaner.

v11: - Added acks and r-b from Rob Herring, Mark Brown and Miquel Raynal
   that were given to v8.

 - Corrected order of the new memory controller reset entry in
   device-trees and host1x DT binding patch, which was requested by
   Rob Herring.

 - Switched consumer drivers to use power domain state syncing done
   by new Tegra's common OPP-initialization helper.

 - Made use of new devm_pm_runtime_enable() helper that was added to
   v5.15 kernel, where appropriate.

 - Added "fuse: Use resource-managed helpers" patch.

 - Converted Tegra20/30 clk drivers to a proper platform drivers,
   which was requested by Thierry Reding.

 - Removed clk-bulk API usage from the MMC patch, which was requested
   by Thierry Reding.

 - Changed CORE power domain name to "core" in a new patch
   "Change name of core power domain".

 - Misc small fixes for problems that I found since v8, like couple
   typos in error code paths and restored working RPM for Tegra DRM
   UAPI v1 that was removed in v8 by accident.

v9-v10: Figured out remaining GENPD API changes with Ulf Hansson and
Viresh Kumar. The OPP-sync helper that was used in v8 isn't needed
anymore because GENPD API now allows consumer drivers to
init rpm_pstate of power domains.

v8: - Added new generic dev_pm_opp_sync() helper 

Re: [PATCH] drm: change logs to print connectors in the form CONNECTOR:id:name

2021-11-14 Thread Claudio Suarez
On Sat, Nov 13, 2021 at 09:39:46PM +0100, Sam Ravnborg wrote:
> Hi Claudio,
> 
> On Sat, Nov 13, 2021 at 08:27:30PM +0100, Claudio Suarez wrote:
> > The prefered way to log connectors is [CONNECTOR:id:name]. Change it in
> > drm core programs.
> > 
> > Suggested-by: Ville Syrjälä 
> > Signed-off-by: Claudio Suarez 
> 
> While touching all these logging calls, could you convernt them to the
> newer drm_dbg_kms variants?
> DRM_DEBUG_* are all deprecated.
> 

Yes, I can, but it is recommended to do it in a different patch:

https://www.kernel.org/doc/html/latest/process/submitting-patches.html#separate-your-changes

C:
"Separate your changes
Separate each logical change into a separate patch.
For example, if your changes include both bug fixes and performance 
enhancements..."


I will study and send a new separate patch with your suggestion.

Best regards,
Claudio Suarez





Re: [PATCH] drm: change logs to print connectors in the form CONNECTOR:id:name

2021-11-14 Thread Claudio Suarez
On Sat, Nov 13, 2021 at 08:27:30PM +0100, Claudio Suarez wrote:
> The prefered way to log connectors is [CONNECTOR:id:name]. Change it in
> drm core programs.
> 
> Suggested-by: Ville Syrjälä 
> Signed-off-by: Claudio Suarez 
> ---
>  drivers/gpu/drm/drm_client_modeset.c | 51 ++--
>  drivers/gpu/drm/drm_connector.c  | 12 ---
>  drivers/gpu/drm/drm_edid.c   | 36 ++--
>  drivers/gpu/drm/drm_edid_load.c  | 11 +++---
>  drivers/gpu/drm/drm_mode_config.c|  3 +-
>  5 files changed, 59 insertions(+), 54 deletions(-)
> 
> diff --git a/drivers/gpu/drm/drm_client_modeset.c 
> b/drivers/gpu/drm/drm_client_modeset.c
> index ced09c7c06f9..4f35dc375bdd 100644
> --- a/drivers/gpu/drm/drm_client_modeset.c
> +++ b/drivers/gpu/drm/drm_client_modeset.c
> @@ -240,7 +240,7 @@ static void drm_client_connectors_enabled(struct 
> drm_connector **connectors,
>   for (i = 0; i < connector_count; i++) {
>   connector = connectors[i];
>   enabled[i] = drm_connector_enabled(connector, true);
> - DRM_DEBUG_KMS("connector %d enabled? %s\n", connector->base.id,
> + DRM_DEBUG_KMS("[CONNECTOR:%d;%s] enabled? %s\n", 
> connector->base.id, connector->name,
> connector->display_info.non_desktop ? "non 
> desktop" : enabled[i] ? "yes" : "no");
>  
>   any_enabled |= enabled[i];
> @@ -350,8 +350,8 @@ static int drm_client_get_tile_offsets(struct 
> drm_connector **connectors,
>   continue;
>  
>   if (!modes[i] && (h_idx || v_idx)) {
> - DRM_DEBUG_KMS("no modes for connector tiled %d %d\n", i,
> -   connector->base.id);
> + DRM_DEBUG_KMS("no modes for [CONNECTOR:%d:%s] tiled 
> %d\n",
> +   connector->base.id, connector->name, i);
>   continue;
>   }
>   if (connector->tile_h_loc < h_idx)
> @@ -419,14 +419,15 @@ static bool drm_client_target_preferred(struct 
> drm_connector **connectors,
>   drm_client_get_tile_offsets(connectors, 
> connector_count, modes, offsets, i,
>   connector->tile_h_loc, 
> connector->tile_v_loc);
>   }
> - DRM_DEBUG_KMS("looking for cmdline mode on connector %d\n",
> -   connector->base.id);
> + DRM_DEBUG_KMS("looking for cmdline mode on [CONNECTOR:%d:%s]\n",
> +   connector->base.id, connector->name);
>  
>   /* got for command line mode first */
>   modes[i] = drm_connector_pick_cmdline_mode(connector);
>   if (!modes[i]) {
> - DRM_DEBUG_KMS("looking for preferred mode on connector 
> %d %d\n",
> -   connector->base.id, connector->tile_group 
> ? connector->tile_group->id : 0);
> + DRM_DEBUG_KMS("looking for preferred mode on 
> [CONNECTOR:%d:%s] %d\n",
> +   connector->base.id, connector->name,
> +   connector->tile_group ? 
> connector->tile_group->id : 0);
>   modes[i] = drm_connector_has_preferred_mode(connector, 
> width, height);
>   }
>   /* No preferred modes, pick one off the list */
> @@ -448,8 +449,8 @@ static bool drm_client_target_preferred(struct 
> drm_connector **connectors,
>   (connector->tile_h_loc == 0 &&
>connector->tile_v_loc == 0 &&
>!drm_connector_get_tiled_mode(connector))) {
> - DRM_DEBUG_KMS("Falling back to non tiled mode 
> on Connector %d\n",
> -   connector->base.id);
> + DRM_DEBUG_KMS("Falling back to non tiled mode 
> on [CONNECTOR:%d:%s]\n",
> +   connector->base.id, 
> connector->name);
>   modes[i] = 
> drm_connector_fallback_non_tiled_mode(connector);
>   } else {
>   modes[i] = 
> drm_connector_get_tiled_mode(connector);
> @@ -617,15 +618,15 @@ static bool drm_client_firmware_config(struct 
> drm_client_dev *client,
>   num_connectors_detected++;
>  
>   if (!enabled[i]) {
> - DRM_DEBUG_KMS("connector %s not enabled, skipping\n",
> -   connector->name);
> + DRM_DEBUG_KMS("[CONNECTOR:%d:%s] not enabled, 
> skipping\n",
> +   connector->base.id, connector->name);
>   conn_configured |= BIT(i);
>   continue;
>   }
>  
>   if (connector->force == DRM_FORCE_OFF) {
> - 

Re: [PATCH] drm: change logs to print connectors in the form CONNECTOR:id:name

2021-11-14 Thread Claudio Suarez


+CC: Ville Syrjälä 
+CC: Daniel Vetter 


On Sat, Nov 13, 2021 at 08:27:30PM +0100, Claudio Suarez wrote:
> The prefered way to log connectors is [CONNECTOR:id:name]. Change it in
> drm core programs.
> 
> Suggested-by: Ville Syrjälä 
> Signed-off-by: Claudio Suarez 
> ---
>  drivers/gpu/drm/drm_client_modeset.c | 51 ++--
>  drivers/gpu/drm/drm_connector.c  | 12 ---
>  drivers/gpu/drm/drm_edid.c   | 36 ++--
>  drivers/gpu/drm/drm_edid_load.c  | 11 +++---
>  drivers/gpu/drm/drm_mode_config.c|  3 +-
>  5 files changed, 59 insertions(+), 54 deletions(-)
> 
> diff --git a/drivers/gpu/drm/drm_client_modeset.c 
> b/drivers/gpu/drm/drm_client_modeset.c
> index ced09c7c06f9..4f35dc375bdd 100644
> --- a/drivers/gpu/drm/drm_client_modeset.c
> +++ b/drivers/gpu/drm/drm_client_modeset.c
> @@ -240,7 +240,7 @@ static void drm_client_connectors_enabled(struct 
> drm_connector **connectors,
>   for (i = 0; i < connector_count; i++) {
>   connector = connectors[i];
>   enabled[i] = drm_connector_enabled(connector, true);
> - DRM_DEBUG_KMS("connector %d enabled? %s\n", connector->base.id,
> + DRM_DEBUG_KMS("[CONNECTOR:%d;%s] enabled? %s\n", 
> connector->base.id, connector->name,
> connector->display_info.non_desktop ? "non 
> desktop" : enabled[i] ? "yes" : "no");
>  
>   any_enabled |= enabled[i];
> @@ -350,8 +350,8 @@ static int drm_client_get_tile_offsets(struct 
> drm_connector **connectors,
>   continue;
>  
>   if (!modes[i] && (h_idx || v_idx)) {
> - DRM_DEBUG_KMS("no modes for connector tiled %d %d\n", i,
> -   connector->base.id);
> + DRM_DEBUG_KMS("no modes for [CONNECTOR:%d:%s] tiled 
> %d\n",
> +   connector->base.id, connector->name, i);
>   continue;
>   }
>   if (connector->tile_h_loc < h_idx)
> @@ -419,14 +419,15 @@ static bool drm_client_target_preferred(struct 
> drm_connector **connectors,
>   drm_client_get_tile_offsets(connectors, 
> connector_count, modes, offsets, i,
>   connector->tile_h_loc, 
> connector->tile_v_loc);
>   }
> - DRM_DEBUG_KMS("looking for cmdline mode on connector %d\n",
> -   connector->base.id);
> + DRM_DEBUG_KMS("looking for cmdline mode on [CONNECTOR:%d:%s]\n",
> +   connector->base.id, connector->name);
>  
>   /* got for command line mode first */
>   modes[i] = drm_connector_pick_cmdline_mode(connector);
>   if (!modes[i]) {
> - DRM_DEBUG_KMS("looking for preferred mode on connector 
> %d %d\n",
> -   connector->base.id, connector->tile_group 
> ? connector->tile_group->id : 0);
> + DRM_DEBUG_KMS("looking for preferred mode on 
> [CONNECTOR:%d:%s] %d\n",
> +   connector->base.id, connector->name,
> +   connector->tile_group ? 
> connector->tile_group->id : 0);
>   modes[i] = drm_connector_has_preferred_mode(connector, 
> width, height);
>   }
>   /* No preferred modes, pick one off the list */
> @@ -448,8 +449,8 @@ static bool drm_client_target_preferred(struct 
> drm_connector **connectors,
>   (connector->tile_h_loc == 0 &&
>connector->tile_v_loc == 0 &&
>!drm_connector_get_tiled_mode(connector))) {
> - DRM_DEBUG_KMS("Falling back to non tiled mode 
> on Connector %d\n",
> -   connector->base.id);
> + DRM_DEBUG_KMS("Falling back to non tiled mode 
> on [CONNECTOR:%d:%s]\n",
> +   connector->base.id, 
> connector->name);
>   modes[i] = 
> drm_connector_fallback_non_tiled_mode(connector);
>   } else {
>   modes[i] = 
> drm_connector_get_tiled_mode(connector);
> @@ -617,15 +618,15 @@ static bool drm_client_firmware_config(struct 
> drm_client_dev *client,
>   num_connectors_detected++;
>  
>   if (!enabled[i]) {
> - DRM_DEBUG_KMS("connector %s not enabled, skipping\n",
> -   connector->name);
> + DRM_DEBUG_KMS("[CONNECTOR:%d:%s] not enabled, 
> skipping\n",
> +   connector->base.id, connector->name);
>   conn_configured |= BIT(i);
>   continue;
>   }
>  
>   if (connector->force == DRM_FORCE_OFF) {
> 

Re: AUTOSEL series truncated was -- Re: [PATCH AUTOSEL 5.15 001/146] dma-buf: WARN on dmabuf release with pending attachments

2021-11-14 Thread Sasha Levin

On Tue, Nov 09, 2021 at 08:05:23AM -0800, Randy Dunlap wrote:

On 11/8/21 11:54 PM, Pavel Machek wrote:

Hi!

This series is truncated .. I only got first patches. Similary, 5.10
series is truncated, [PATCH AUTOSEL 5.10 035/101] media: s5p-mfc: Add
checking to s5p_mfc_probe... is last one I got.

I got all the patches before that, so I believe it is not problem on
my side, but I'd not mind someone confirming they are seeing the same
problem...


Yes, several of the patch series were incomplete for me also...


Odd. I'll keep a closer look next time I send a series out to figure out
what's going on.

Thanks for the heads-up!

--
Thanks,
Sasha


[Bug 213823] Broken power management for amdgpu

2021-11-14 Thread bugzilla-daemon
https://bugzilla.kernel.org/show_bug.cgi?id=213823

--- Comment #6 from Bruno Pagani (bruno.n.pag...@gmail.com) ---
So while I still don’t have time to setup bisecting, I’m now affected even on
LTS kernel. Also, I’ve been in touch with other users having a similar laptop
(the XPS version instead of the Precision, but still KabyLake-G), and they
don’t seem affected. Thus I’m not sure anymore this is a kernel issue (and
whether BOCO vs ATPX is relevant). Where should I seek for guidance in
understanding why my dGPU stays stuck in D0 instead of going into D3? Is this
or https://gitlab.freedesktop.org/drm/amd and appropriate place?

-- 
You may reply to this email to add a comment.

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

[PATCH v3 6/6] drm/i915/ttm: Update i915_gem_obj_copy_ttm() to be asynchronous

2021-11-14 Thread Thomas Hellström
Update the copy function i915_gem_obj_copy_ttm() to be asynchronous for
future users and update the only current user to sync the objects
as needed after this function.

Signed-off-by: Thomas Hellström 
---
 drivers/gpu/drm/i915/gem/i915_gem_ttm_move.c | 40 ++--
 drivers/gpu/drm/i915/gem/i915_gem_ttm_pm.c   |  2 +
 2 files changed, 30 insertions(+), 12 deletions(-)

diff --git a/drivers/gpu/drm/i915/gem/i915_gem_ttm_move.c 
b/drivers/gpu/drm/i915/gem/i915_gem_ttm_move.c
index ae2c49fc3500..53ed3972c7be 100644
--- a/drivers/gpu/drm/i915/gem/i915_gem_ttm_move.c
+++ b/drivers/gpu/drm/i915/gem/i915_gem_ttm_move.c
@@ -811,33 +811,49 @@ int i915_gem_obj_copy_ttm(struct drm_i915_gem_object *dst,
.interruptible = intr,
};
struct i915_refct_sgt *dst_rsgt;
-   struct dma_fence *copy_fence;
-   int ret;
+   struct dma_fence *copy_fence, *dep_fence;
+   struct i915_deps deps;
+   int ret, shared_err;
 
assert_object_held(dst);
assert_object_held(src);
+   i915_deps_init(, GFP_KERNEL | __GFP_NORETRY | __GFP_NOWARN);
 
/*
-* Sync for now. This will change with async moves.
+* We plan to add a shared fence only for the source. If that
+* fails, we await all source fences before commencing
+* the copy instead of only the exclusive.
 */
-   ret = ttm_bo_wait_ctx(dst_bo, );
+   shared_err = dma_resv_reserve_shared(src_bo->base.resv, 1);
+   ret = i915_deps_add_resv(, dst_bo->base.resv, true, false, );
if (!ret)
-   ret = ttm_bo_wait_ctx(src_bo, );
+   ret = i915_deps_add_resv(, src_bo->base.resv,
+!!shared_err, false, );
if (ret)
return ret;
 
+   dep_fence = i915_deps_to_fence(, );
+   if (IS_ERR(dep_fence))
+   return PTR_ERR(dep_fence);
+
dst_rsgt = i915_ttm_resource_get_st(dst, dst_bo->resource);
copy_fence = __i915_ttm_move(src_bo, false, dst_bo->resource,
-dst_bo->ttm, dst_rsgt, allow_accel, NULL);
+dst_bo->ttm, dst_rsgt, allow_accel,
+dep_fence);
 
i915_refct_sgt_put(dst_rsgt);
-   if (IS_ERR(copy_fence))
-   return PTR_ERR(copy_fence);
+   if (IS_ERR_OR_NULL(copy_fence))
+   return PTR_ERR_OR_ZERO(copy_fence);
 
-   if (copy_fence) {
-   dma_fence_wait(copy_fence, false);
-   dma_fence_put(copy_fence);
-   }
+   dma_resv_add_excl_fence(dst_bo->base.resv, copy_fence);
+
+   /* If we failed to reserve a shared slot, add an exclusive fence */
+   if (shared_err)
+   dma_resv_add_excl_fence(src_bo->base.resv, copy_fence);
+   else
+   dma_resv_add_shared_fence(src_bo->base.resv, copy_fence);
+
+   dma_fence_put(copy_fence);
 
return 0;
 }
diff --git a/drivers/gpu/drm/i915/gem/i915_gem_ttm_pm.c 
b/drivers/gpu/drm/i915/gem/i915_gem_ttm_pm.c
index 60d10ab55d1e..9aad84059d56 100644
--- a/drivers/gpu/drm/i915/gem/i915_gem_ttm_pm.c
+++ b/drivers/gpu/drm/i915/gem/i915_gem_ttm_pm.c
@@ -80,6 +80,7 @@ static int i915_ttm_backup(struct i915_gem_apply_to_region 
*apply,
 
err = i915_gem_obj_copy_ttm(backup, obj, pm_apply->allow_gpu, false);
GEM_WARN_ON(err);
+   ttm_bo_wait_ctx(backup_bo, );
 
obj->ttm.backup = backup;
return 0;
@@ -170,6 +171,7 @@ static int i915_ttm_restore(struct i915_gem_apply_to_region 
*apply,
err = i915_gem_obj_copy_ttm(obj, backup, pm_apply->allow_gpu,
false);
GEM_WARN_ON(err);
+   ttm_bo_wait_ctx(backup_bo, );
 
obj->ttm.backup = NULL;
err = 0;
-- 
2.31.1



[PATCH v3 5/6] drm/i915/ttm: Implement asynchronous TTM moves

2021-11-14 Thread Thomas Hellström
Don't wait sync while migrating, but rather make the GPU blit await the
dependencies and add a moving fence to the object.

This also enables asynchronous VRAM management in that on eviction,
rather than waiting for the moving fence to expire before freeing VRAM,
it is freed immediately and the fence is stored with the VRAM manager and
handed out to newly allocated objects to await before clears and swapins,
or for kernel objects before setting up gpu vmas or mapping.

To collect dependencies before migrating, add a set of utilities that
coalesce these to a single dma_fence.

What is still missing for fully asynchronous operation is asynchronous vma
unbinding, which is still to be implemented.

This commit substantially reduces execution time in the gem_lmem_swapping
test.

v2:
- Make a couple of functions static.

Signed-off-by: Thomas Hellström 
---
 drivers/gpu/drm/i915/gem/i915_gem_ttm.c  |  10 +
 drivers/gpu/drm/i915/gem/i915_gem_ttm.h  |   2 +-
 drivers/gpu/drm/i915/gem/i915_gem_ttm_move.c | 329 +--
 drivers/gpu/drm/i915/gem/i915_gem_wait.c |   4 +-
 4 files changed, 318 insertions(+), 27 deletions(-)

diff --git a/drivers/gpu/drm/i915/gem/i915_gem_ttm.c 
b/drivers/gpu/drm/i915/gem/i915_gem_ttm.c
index a1df49378a0f..111a4282d779 100644
--- a/drivers/gpu/drm/i915/gem/i915_gem_ttm.c
+++ b/drivers/gpu/drm/i915/gem/i915_gem_ttm.c
@@ -326,6 +326,9 @@ static bool i915_ttm_eviction_valuable(struct 
ttm_buffer_object *bo,
 {
struct drm_i915_gem_object *obj = i915_ttm_to_gem(bo);
 
+   if (!obj)
+   return false;
+
/*
 * EXTERNAL objects should never be swapped out by TTM, instead we need
 * to handle that ourselves. TTM will already skip such objects for us,
@@ -448,6 +451,10 @@ static int i915_ttm_shrinker_release_pages(struct 
drm_i915_gem_object *obj,
if (bo->ttm->page_flags & TTM_TT_FLAG_SWAPPED)
return 0;
 
+   ret = ttm_bo_wait_ctx(bo, );
+   if (ret)
+   return ret;
+
bo->ttm->page_flags |= TTM_TT_FLAG_SWAPPED;
ret = ttm_bo_validate(bo, , );
if (ret) {
@@ -549,6 +556,9 @@ static void i915_ttm_swap_notify(struct ttm_buffer_object 
*bo)
struct drm_i915_gem_object *obj = i915_ttm_to_gem(bo);
int ret = i915_ttm_move_notify(bo);
 
+   if (!obj)
+   return;
+
GEM_WARN_ON(ret);
GEM_WARN_ON(obj->ttm.cached_io_rsgt);
if (!ret && obj->mm.madv != I915_MADV_WILLNEED)
diff --git a/drivers/gpu/drm/i915/gem/i915_gem_ttm.h 
b/drivers/gpu/drm/i915/gem/i915_gem_ttm.h
index 82cdabb542be..9d698ad00853 100644
--- a/drivers/gpu/drm/i915/gem/i915_gem_ttm.h
+++ b/drivers/gpu/drm/i915/gem/i915_gem_ttm.h
@@ -37,7 +37,7 @@ void i915_ttm_bo_destroy(struct ttm_buffer_object *bo);
 static inline struct drm_i915_gem_object *
 i915_ttm_to_gem(struct ttm_buffer_object *bo)
 {
-   if (GEM_WARN_ON(bo->destroy != i915_ttm_bo_destroy))
+   if (bo->destroy != i915_ttm_bo_destroy)
return NULL;
 
return container_of(bo, struct drm_i915_gem_object, __do_not_access);
diff --git a/drivers/gpu/drm/i915/gem/i915_gem_ttm_move.c 
b/drivers/gpu/drm/i915/gem/i915_gem_ttm_move.c
index f35b386c56ca..ae2c49fc3500 100644
--- a/drivers/gpu/drm/i915/gem/i915_gem_ttm_move.c
+++ b/drivers/gpu/drm/i915/gem/i915_gem_ttm_move.c
@@ -3,6 +3,8 @@
  * Copyright © 2021 Intel Corporation
  */
 
+#include 
+
 #include 
 
 #include "i915_drv.h"
@@ -41,6 +43,228 @@ void i915_ttm_migrate_set_failure_modes(bool gpu_migration,
 }
 #endif
 
+/**
+ * DOC: Set of utilities to dynamically collect dependencies and
+ * eventually coalesce them into a single fence which is fed into
+ * the migration code. That single fence is, in the case of dependencies
+ * from multiple contexts, a struct dma_fence_array, since the
+ * i915 request code can break that up and await the individual
+ * fences.
+ *
+ * While collecting the individual dependencies, we store the refcounted
+ * struct dma_fence pointers in a realloc-type-managed pointer array, since
+ * that can be easily fed into a dma_fence_array. Other options are
+ * available, like for example an xarray for similarity with drm/sched.
+ * Can be changed easily if needed.
+ *
+ * We might want to break this out into a separate file as a utility.
+ */
+
+#define I915_DEPS_MIN_ALLOC_CHUNK 8U
+
+/**
+ * struct i915_deps - Collect dependencies into a single dma-fence
+ * @single: Storage for pointer if the collection is a single fence.
+ * @fence: Allocated array of fence pointers if more than a single fence;
+ * otherwise points to the address of @single.
+ * @num_deps: Current number of dependency fences.
+ * @fences_size: Size of the @fences array in number of pointers.
+ * @gfp: Allocation mode.
+ */
+struct i915_deps {
+   struct dma_fence *single;
+   struct dma_fence **fences;
+   unsigned int num_deps;
+   unsigned int fences_size;
+   gfp_t gfp;
+};
+
+static void 

[PATCH v3 4/6] drm/i915/ttm: Break refcounting loops at device region unref time

2021-11-14 Thread Thomas Hellström
There is an interesting refcounting loop:
struct intel_memory_region has a struct ttm_resource_manager,
ttm_resource_manager->move may hold a reference to i915_request,
i915_request may hold a reference to intel_context,
intel_context may hold a reference to drm_i915_gem_object,
drm_i915_gem_object may hold a reference to intel_memory_region.

Break this loop when we drop the device reference count on the
region by putting the region move fence.

Also hold dropping the device reference count until all objects of
the region has been deleted, to avoid issues if proceeding with the
device takedown while the region is still present.

Signed-off-by: Thomas Hellström 
---
 drivers/gpu/drm/i915/gem/i915_gem_ttm.c |  1 +
 drivers/gpu/drm/i915/gt/intel_region_lmem.c |  1 +
 drivers/gpu/drm/i915/intel_memory_region.c  |  5 +++-
 drivers/gpu/drm/i915/intel_memory_region.h  |  1 +
 drivers/gpu/drm/i915/intel_region_ttm.c | 28 +
 drivers/gpu/drm/i915/intel_region_ttm.h |  2 ++
 6 files changed, 37 insertions(+), 1 deletion(-)

diff --git a/drivers/gpu/drm/i915/gem/i915_gem_ttm.c 
b/drivers/gpu/drm/i915/gem/i915_gem_ttm.c
index 537a81445b90..a1df49378a0f 100644
--- a/drivers/gpu/drm/i915/gem/i915_gem_ttm.c
+++ b/drivers/gpu/drm/i915/gem/i915_gem_ttm.c
@@ -1044,6 +1044,7 @@ int __i915_gem_ttm_object_init(struct intel_memory_region 
*mem,
 
 static const struct intel_memory_region_ops ttm_system_region_ops = {
.init_object = __i915_gem_ttm_object_init,
+   .disable = intel_region_ttm_disable,
 };
 
 struct intel_memory_region *
diff --git a/drivers/gpu/drm/i915/gt/intel_region_lmem.c 
b/drivers/gpu/drm/i915/gt/intel_region_lmem.c
index aec838ecb2ef..956916fd21f8 100644
--- a/drivers/gpu/drm/i915/gt/intel_region_lmem.c
+++ b/drivers/gpu/drm/i915/gt/intel_region_lmem.c
@@ -108,6 +108,7 @@ region_lmem_init(struct intel_memory_region *mem)
 static const struct intel_memory_region_ops intel_region_lmem_ops = {
.init = region_lmem_init,
.release = region_lmem_release,
+   .disable = intel_region_ttm_disable,
.init_object = __i915_gem_ttm_object_init,
 };
 
diff --git a/drivers/gpu/drm/i915/intel_memory_region.c 
b/drivers/gpu/drm/i915/intel_memory_region.c
index e7f7e6627750..1f67d2b68c24 100644
--- a/drivers/gpu/drm/i915/intel_memory_region.c
+++ b/drivers/gpu/drm/i915/intel_memory_region.c
@@ -233,8 +233,11 @@ void intel_memory_regions_driver_release(struct 
drm_i915_private *i915)
struct intel_memory_region *region =
fetch_and_zero(>mm.regions[i]);
 
-   if (region)
+   if (region) {
+   if (region->ops->disable)
+   region->ops->disable(region);
intel_memory_region_put(region);
+   }
}
 }
 
diff --git a/drivers/gpu/drm/i915/intel_memory_region.h 
b/drivers/gpu/drm/i915/intel_memory_region.h
index 3feae3353d33..9bb77eacd206 100644
--- a/drivers/gpu/drm/i915/intel_memory_region.h
+++ b/drivers/gpu/drm/i915/intel_memory_region.h
@@ -52,6 +52,7 @@ struct intel_memory_region_ops {
 
int (*init)(struct intel_memory_region *mem);
void (*release)(struct intel_memory_region *mem);
+   void (*disable)(struct intel_memory_region *mem);
 
int (*init_object)(struct intel_memory_region *mem,
   struct drm_i915_gem_object *obj,
diff --git a/drivers/gpu/drm/i915/intel_region_ttm.c 
b/drivers/gpu/drm/i915/intel_region_ttm.c
index 2e901a27e259..4219d83a2b19 100644
--- a/drivers/gpu/drm/i915/intel_region_ttm.c
+++ b/drivers/gpu/drm/i915/intel_region_ttm.c
@@ -114,6 +114,34 @@ void intel_region_ttm_fini(struct intel_memory_region *mem)
mem->region_private = NULL;
 }
 
+/**
+ * intel_region_ttm_disable - A TTM region disable callback helper
+ * @mem: The memory region.
+ *
+ * A helper that ensures that nothing any longer references a region at
+ * device takedown. Breaks refcounting loops and waits for objects in the
+ * region to be deleted.
+ */
+void intel_region_ttm_disable(struct intel_memory_region *mem)
+{
+   struct ttm_resource_manager *man = mem->region_private;
+
+   /*
+* Put the region's move fences. This releases requests that
+* may hold on to contexts and vms that may hold on to buffer
+* objects that may have a refcount on the region. :/
+*/
+   if (man)
+   ttm_resource_manager_cleanup(man);
+
+   /* Flush objects that may just have been freed */
+   i915_gem_flush_free_objects(mem->i915);
+
+   /* Wait until the only region reference left is our own. */
+   while (kref_read(>kref) > 1)
+   msleep(20);
+}
+
 /**
  * intel_region_ttm_resource_to_rsgt -
  * Convert an opaque TTM resource manager resource to a refcounted sg_table.
diff --git a/drivers/gpu/drm/i915/intel_region_ttm.h 
b/drivers/gpu/drm/i915/intel_region_ttm.h
index 7bbe2b46b504..197a8c179370 

[PATCH v3 2/6] drm/i915: Add support for asynchronous moving fence waiting

2021-11-14 Thread Thomas Hellström
From: Maarten Lankhorst 

For now, we will only allow async migration when TTM is used,
so the paths we care about are related to TTM.

The mmap path is handled by having the fence in ttm_bo->moving,
when pinning, the binding only becomes available after the moving
fence is signaled, and pinning a cpu map will only work after
the moving fence signals.

This should close all holes where userspace can read a buffer
before it's fully migrated.

v2:
- Fix a couple of SPARSE warnings
v3:
- Fix a NULL pointer dereference

Co-developed-by: Thomas Hellström 
Signed-off-by: Thomas Hellström 
Signed-off-by: Maarten Lankhorst 
---
 drivers/gpu/drm/i915/display/intel_fbdev.c|  7 ++--
 drivers/gpu/drm/i915/display/intel_overlay.c  |  2 +-
 drivers/gpu/drm/i915/gem/i915_gem_pages.c |  6 +++
 .../i915/gem/selftests/i915_gem_coherency.c   |  4 +-
 .../drm/i915/gem/selftests/i915_gem_mman.c| 22 ++-
 drivers/gpu/drm/i915/i915_vma.c   | 39 ++-
 drivers/gpu/drm/i915/i915_vma.h   |  3 ++
 drivers/gpu/drm/i915/selftests/i915_vma.c |  4 +-
 8 files changed, 69 insertions(+), 18 deletions(-)

diff --git a/drivers/gpu/drm/i915/display/intel_fbdev.c 
b/drivers/gpu/drm/i915/display/intel_fbdev.c
index adc3a81be9f7..5902ad0c2bd8 100644
--- a/drivers/gpu/drm/i915/display/intel_fbdev.c
+++ b/drivers/gpu/drm/i915/display/intel_fbdev.c
@@ -265,11 +265,12 @@ static int intelfb_create(struct drm_fb_helper *helper,
info->fix.smem_len = vma->node.size;
}
 
-   vaddr = i915_vma_pin_iomap(vma);
+   vaddr = i915_vma_pin_iomap_unlocked(vma);
if (IS_ERR(vaddr)) {
-   drm_err(_priv->drm,
-   "Failed to remap framebuffer into virtual memory\n");
ret = PTR_ERR(vaddr);
+   if (ret != -EINTR && ret != -ERESTARTSYS)
+   drm_err(_priv->drm,
+   "Failed to remap framebuffer into virtual 
memory\n");
goto out_unpin;
}
info->screen_base = vaddr;
diff --git a/drivers/gpu/drm/i915/display/intel_overlay.c 
b/drivers/gpu/drm/i915/display/intel_overlay.c
index 7e3f5c6ca484..21593f3f2664 100644
--- a/drivers/gpu/drm/i915/display/intel_overlay.c
+++ b/drivers/gpu/drm/i915/display/intel_overlay.c
@@ -1357,7 +1357,7 @@ static int get_registers(struct intel_overlay *overlay, 
bool use_phys)
overlay->flip_addr = sg_dma_address(obj->mm.pages->sgl);
else
overlay->flip_addr = i915_ggtt_offset(vma);
-   overlay->regs = i915_vma_pin_iomap(vma);
+   overlay->regs = i915_vma_pin_iomap_unlocked(vma);
i915_vma_unpin(vma);
 
if (IS_ERR(overlay->regs)) {
diff --git a/drivers/gpu/drm/i915/gem/i915_gem_pages.c 
b/drivers/gpu/drm/i915/gem/i915_gem_pages.c
index c4f684b7cc51..49c6e55c68ce 100644
--- a/drivers/gpu/drm/i915/gem/i915_gem_pages.c
+++ b/drivers/gpu/drm/i915/gem/i915_gem_pages.c
@@ -418,6 +418,12 @@ void *i915_gem_object_pin_map(struct drm_i915_gem_object 
*obj,
}
 
if (!ptr) {
+   err = i915_gem_object_wait_moving_fence(obj, true);
+   if (err) {
+   ptr = ERR_PTR(err);
+   goto err_unpin;
+   }
+
if (GEM_WARN_ON(type == I915_MAP_WC &&
!static_cpu_has(X86_FEATURE_PAT)))
ptr = ERR_PTR(-ENODEV);
diff --git a/drivers/gpu/drm/i915/gem/selftests/i915_gem_coherency.c 
b/drivers/gpu/drm/i915/gem/selftests/i915_gem_coherency.c
index 13b088cc787e..067c512961ba 100644
--- a/drivers/gpu/drm/i915/gem/selftests/i915_gem_coherency.c
+++ b/drivers/gpu/drm/i915/gem/selftests/i915_gem_coherency.c
@@ -101,7 +101,7 @@ static int gtt_set(struct context *ctx, unsigned long 
offset, u32 v)
 
intel_gt_pm_get(vma->vm->gt);
 
-   map = i915_vma_pin_iomap(vma);
+   map = i915_vma_pin_iomap_unlocked(vma);
i915_vma_unpin(vma);
if (IS_ERR(map)) {
err = PTR_ERR(map);
@@ -134,7 +134,7 @@ static int gtt_get(struct context *ctx, unsigned long 
offset, u32 *v)
 
intel_gt_pm_get(vma->vm->gt);
 
-   map = i915_vma_pin_iomap(vma);
+   map = i915_vma_pin_iomap_unlocked(vma);
i915_vma_unpin(vma);
if (IS_ERR(map)) {
err = PTR_ERR(map);
diff --git a/drivers/gpu/drm/i915/gem/selftests/i915_gem_mman.c 
b/drivers/gpu/drm/i915/gem/selftests/i915_gem_mman.c
index 6d30cdfa80f3..5d54181c2145 100644
--- a/drivers/gpu/drm/i915/gem/selftests/i915_gem_mman.c
+++ b/drivers/gpu/drm/i915/gem/selftests/i915_gem_mman.c
@@ -125,12 +125,13 @@ static int check_partial_mapping(struct 
drm_i915_gem_object *obj,
n = page - view.partial.offset;
GEM_BUG_ON(n >= view.partial.size);
 
-   io = i915_vma_pin_iomap(vma);
+   io = i915_vma_pin_iomap_unlocked(vma);
i915_vma_unpin(vma);
if (IS_ERR(io)) {
-   pr_err("Failed to iomap 

[PATCH v3 3/6] drm/i915/ttm: Move the i915_gem_obj_copy_ttm() function

2021-11-14 Thread Thomas Hellström
Move the i915_gem_obj_copy_ttm() function to i915_gem_ttm_move.h.
This will help keep a number of functions static when introducing
async moves.

Signed-off-by: Thomas Hellström 
---
 drivers/gpu/drm/i915/gem/i915_gem_ttm.c  | 47 ---
 drivers/gpu/drm/i915/gem/i915_gem_ttm.h  |  4 --
 drivers/gpu/drm/i915/gem/i915_gem_ttm_move.c | 63 
 drivers/gpu/drm/i915/gem/i915_gem_ttm_move.h | 10 ++--
 drivers/gpu/drm/i915/gem/i915_gem_ttm_pm.c   |  1 +
 5 files changed, 56 insertions(+), 69 deletions(-)

diff --git a/drivers/gpu/drm/i915/gem/i915_gem_ttm.c 
b/drivers/gpu/drm/i915/gem/i915_gem_ttm.c
index 68cfe6e9ceab..537a81445b90 100644
--- a/drivers/gpu/drm/i915/gem/i915_gem_ttm.c
+++ b/drivers/gpu/drm/i915/gem/i915_gem_ttm.c
@@ -1063,50 +1063,3 @@ i915_gem_ttm_system_setup(struct drm_i915_private *i915,
intel_memory_region_set_name(mr, "system-ttm");
return mr;
 }
-
-/**
- * i915_gem_obj_copy_ttm - Copy the contents of one ttm-based gem object to
- * another
- * @dst: The destination object
- * @src: The source object
- * @allow_accel: Allow using the blitter. Otherwise TTM memcpy is used.
- * @intr: Whether to perform waits interruptible:
- *
- * Note: The caller is responsible for assuring that the underlying
- * TTM objects are populated if needed and locked.
- *
- * Return: Zero on success. Negative error code on error. If @intr == true,
- * then it may return -ERESTARTSYS or -EINTR.
- */
-int i915_gem_obj_copy_ttm(struct drm_i915_gem_object *dst,
- struct drm_i915_gem_object *src,
- bool allow_accel, bool intr)
-{
-   struct ttm_buffer_object *dst_bo = i915_gem_to_ttm(dst);
-   struct ttm_buffer_object *src_bo = i915_gem_to_ttm(src);
-   struct ttm_operation_ctx ctx = {
-   .interruptible = intr,
-   };
-   struct i915_refct_sgt *dst_rsgt;
-   int ret;
-
-   assert_object_held(dst);
-   assert_object_held(src);
-
-   /*
-* Sync for now. This will change with async moves.
-*/
-   ret = ttm_bo_wait_ctx(dst_bo, );
-   if (!ret)
-   ret = ttm_bo_wait_ctx(src_bo, );
-   if (ret)
-   return ret;
-
-   dst_rsgt = i915_ttm_resource_get_st(dst, dst_bo->resource);
-   __i915_ttm_move(src_bo, false, dst_bo->resource, dst_bo->ttm,
-   dst_rsgt, allow_accel);
-
-   i915_refct_sgt_put(dst_rsgt);
-
-   return 0;
-}
diff --git a/drivers/gpu/drm/i915/gem/i915_gem_ttm.h 
b/drivers/gpu/drm/i915/gem/i915_gem_ttm.h
index 074a7c08ff31..82cdabb542be 100644
--- a/drivers/gpu/drm/i915/gem/i915_gem_ttm.h
+++ b/drivers/gpu/drm/i915/gem/i915_gem_ttm.h
@@ -49,10 +49,6 @@ int __i915_gem_ttm_object_init(struct intel_memory_region 
*mem,
   resource_size_t page_size,
   unsigned int flags);
 
-int i915_gem_obj_copy_ttm(struct drm_i915_gem_object *dst,
- struct drm_i915_gem_object *src,
- bool allow_accel, bool intr);
-
 /* Internal I915 TTM declarations and definitions below. */
 
 #define I915_PL_LMEM0 TTM_PL_PRIV
diff --git a/drivers/gpu/drm/i915/gem/i915_gem_ttm_move.c 
b/drivers/gpu/drm/i915/gem/i915_gem_ttm_move.c
index ef22d4ed66ad..f35b386c56ca 100644
--- a/drivers/gpu/drm/i915/gem/i915_gem_ttm_move.c
+++ b/drivers/gpu/drm/i915/gem/i915_gem_ttm_move.c
@@ -378,18 +378,10 @@ i915_ttm_memcpy_work_arm(struct i915_ttm_memcpy_work 
*work,
return >fence;
 }
 
-/**
- * __i915_ttm_move - helper to perform TTM moves or clears.
- * @bo: The source buffer object.
- * @clear: Whether this is a clear operation.
- * @dst_mem: The destination ttm resource.
- * @dst_ttm: The destination ttm page vector.
- * @dst_rsgt: The destination refcounted sg-list.
- * @allow_accel: Whether to allow acceleration.
- */
-void __i915_ttm_move(struct ttm_buffer_object *bo, bool clear,
-struct ttm_resource *dst_mem, struct ttm_tt *dst_ttm,
-struct i915_refct_sgt *dst_rsgt, bool allow_accel)
+static void __i915_ttm_move(struct ttm_buffer_object *bo, bool clear,
+   struct ttm_resource *dst_mem,
+   struct ttm_tt *dst_ttm,
+   struct i915_refct_sgt *dst_rsgt, bool allow_accel)
 {
struct i915_ttm_memcpy_work *copy_work = NULL;
struct i915_ttm_memcpy_arg _arg, *arg = &_arg;
@@ -521,3 +513,50 @@ int i915_ttm_move(struct ttm_buffer_object *bo, bool evict,
i915_ttm_adjust_gem_after_move(obj);
return 0;
 }
+
+/**
+ * i915_gem_obj_copy_ttm - Copy the contents of one ttm-based gem object to
+ * another
+ * @dst: The destination object
+ * @src: The source object
+ * @allow_accel: Allow using the blitter. Otherwise TTM memcpy is used.
+ * @intr: Whether to perform waits interruptible:
+ *
+ * Note: The caller is responsible for assuring that the underlying
+ * TTM objects are populated if 

[PATCH v3 1/6] drm/i915: Add functions to set/get moving fence

2021-11-14 Thread Thomas Hellström
From: Maarten Lankhorst 

We want to get rid of i915_vma tracking to simplify the code and
lifetimes. Add a way to set/put the moving fence, in preparation for
removing the tracking.

Signed-off-by: Maarten Lankhorst 
---
 drivers/gpu/drm/i915/gem/i915_gem_object.c | 37 ++
 drivers/gpu/drm/i915/gem/i915_gem_object.h |  9 ++
 2 files changed, 46 insertions(+)

diff --git a/drivers/gpu/drm/i915/gem/i915_gem_object.c 
b/drivers/gpu/drm/i915/gem/i915_gem_object.c
index 591ee3cb7275..ec4313836597 100644
--- a/drivers/gpu/drm/i915/gem/i915_gem_object.c
+++ b/drivers/gpu/drm/i915/gem/i915_gem_object.c
@@ -33,6 +33,7 @@
 #include "i915_gem_object.h"
 #include "i915_memcpy.h"
 #include "i915_trace.h"
+#include "i915_gem_ttm.h"
 
 static struct kmem_cache *slab_objects;
 
@@ -726,6 +727,42 @@ static const struct drm_gem_object_funcs 
i915_gem_object_funcs = {
.export = i915_gem_prime_export,
 };
 
+struct dma_fence *
+i915_gem_object_get_moving_fence(struct drm_i915_gem_object *obj)
+{
+   return dma_fence_get(i915_gem_to_ttm(obj)->moving);
+}
+
+void i915_gem_object_set_moving_fence(struct drm_i915_gem_object *obj,
+ struct dma_fence *fence)
+{
+   dma_fence_put(i915_gem_to_ttm(obj)->moving);
+
+   i915_gem_to_ttm(obj)->moving = dma_fence_get(fence);
+}
+
+int i915_gem_object_wait_moving_fence(struct drm_i915_gem_object *obj,
+ bool intr)
+{
+   struct dma_fence *fence = i915_gem_to_ttm(obj)->moving;
+   int ret;
+
+   assert_object_held(obj);
+   if (!fence)
+   return 0;
+
+   ret = dma_fence_wait(fence, intr);
+   if (ret)
+   return ret;
+
+   if (fence->error)
+   return fence->error;
+
+   i915_gem_to_ttm(obj)->moving = NULL;
+   dma_fence_put(fence);
+   return 0;
+}
+
 #if IS_ENABLED(CONFIG_DRM_I915_SELFTEST)
 #include "selftests/huge_gem_object.c"
 #include "selftests/huge_pages.c"
diff --git a/drivers/gpu/drm/i915/gem/i915_gem_object.h 
b/drivers/gpu/drm/i915/gem/i915_gem_object.h
index 133963b46135..36bf3e2e602f 100644
--- a/drivers/gpu/drm/i915/gem/i915_gem_object.h
+++ b/drivers/gpu/drm/i915/gem/i915_gem_object.h
@@ -517,6 +517,15 @@ i915_gem_object_finish_access(struct drm_i915_gem_object 
*obj)
i915_gem_object_unpin_pages(obj);
 }
 
+struct dma_fence *
+i915_gem_object_get_moving_fence(struct drm_i915_gem_object *obj);
+
+void i915_gem_object_set_moving_fence(struct drm_i915_gem_object *obj,
+ struct dma_fence *fence);
+
+int i915_gem_object_wait_moving_fence(struct drm_i915_gem_object *obj,
+ bool intr);
+
 void i915_gem_object_set_cache_coherency(struct drm_i915_gem_object *obj,
 unsigned int cache_level);
 bool i915_gem_object_can_bypass_llc(struct drm_i915_gem_object *obj);
-- 
2.31.1



[PATCH v3 0/6] drm/i915/ttm: Async migration

2021-11-14 Thread Thomas Hellström
This patch series deals with async migration and async vram management.
It still leaves an important part out, which is async unbinding which
will reduce latency further, at least when trying to migrate already active
objects.

Patches 1/6 and 2/6 deal with accessing and waiting for the TTM moving
fence from i915 GEM.
Patch 3 is pure code reorganization, no functional change.
Patch 4 breaks a refcounting loop involving the TTM moving fence.
Patch 5 uses TTM to implement the ttm move() callback async, it also
introduces a utility to collect dependencies and turn them into a
single dma_fence, which is needed for the intel_migrate code.
This also affects the gem object migrate code so.
Patch 6 makes the object copy utility async as well, mainly for future
users since the only current user, suspend backup and restore, typically
will want to sync anyway.

v2:
- Fix a couple of SPARSE warnings.
v3:
- Fix a NULL pointer dereference.

Maarten Lankhorst (2):
  drm/i915: Add functions to set/get moving fence
  drm/i915: Add support for asynchronous moving fence waiting

Thomas Hellström (4):
  drm/i915/ttm: Move the i915_gem_obj_copy_ttm() function
  drm/i915/ttm: Break refcounting loops at device region unref time
  drm/i915/ttm: Implement asynchronous TTM moves
  drm/i915/ttm: Update i915_gem_obj_copy_ttm() to be asynchronous

 drivers/gpu/drm/i915/display/intel_fbdev.c|   7 +-
 drivers/gpu/drm/i915/display/intel_overlay.c  |   2 +-
 drivers/gpu/drm/i915/gem/i915_gem_object.c|  37 ++
 drivers/gpu/drm/i915/gem/i915_gem_object.h|   9 +
 drivers/gpu/drm/i915/gem/i915_gem_pages.c |   6 +
 drivers/gpu/drm/i915/gem/i915_gem_ttm.c   |  58 +--
 drivers/gpu/drm/i915/gem/i915_gem_ttm.h   |   6 +-
 drivers/gpu/drm/i915/gem/i915_gem_ttm_move.c  | 396 --
 drivers/gpu/drm/i915/gem/i915_gem_ttm_move.h  |  10 +-
 drivers/gpu/drm/i915/gem/i915_gem_ttm_pm.c|   3 +
 drivers/gpu/drm/i915/gem/i915_gem_wait.c  |   4 +-
 .../i915/gem/selftests/i915_gem_coherency.c   |   4 +-
 .../drm/i915/gem/selftests/i915_gem_mman.c|  22 +-
 drivers/gpu/drm/i915/gt/intel_region_lmem.c   |   1 +
 drivers/gpu/drm/i915/i915_vma.c   |  39 +-
 drivers/gpu/drm/i915/i915_vma.h   |   3 +
 drivers/gpu/drm/i915/intel_memory_region.c|   5 +-
 drivers/gpu/drm/i915/intel_memory_region.h|   1 +
 drivers/gpu/drm/i915/intel_region_ttm.c   |  28 ++
 drivers/gpu/drm/i915/intel_region_ttm.h   |   2 +
 drivers/gpu/drm/i915/selftests/i915_vma.c |   4 +-
 21 files changed, 538 insertions(+), 109 deletions(-)

-- 
2.31.1



Re: [PATCH v10 08/10] dyndbg: add print-to-tracefs, selftest with it - RFC

2021-11-14 Thread Vincent Whitchurch
On Thu, Nov 11, 2021 at 03:02:04PM -0700, Jim Cromie wrote:
> Sean Paul proposed, in:
> https://patchwork.freedesktop.org/series/78133/
> drm/trace: Mirror DRM debug logs to tracefs
> 
> His patchset's objective is to be able to independently steer some of
> the drm.debug stream to an alternate tracing destination, by splitting
> drm_debug_enabled() into syslog & trace flavors, and enabling them
> separately.  2 advantages were identified:
> 
> 1- syslog is heavyweight, tracefs is much lighter
> 2- separate selection of enabled categories means less traffic
> 
> Dynamic-Debug can do 2nd exceedingly well:
> 
> A- all work is behind jump-label's NOOP, zero off cost.
> B- exact site selectivity, precisely the useful traffic.
>can tailor enabled set interactively, at shell.
> 
> Since the tracefs interface is effective for drm (the threads suggest
> so), adding that interface to dynamic-debug has real potential for
> everyone including drm.
> 
> if CONFIG_TRACING:
> 
> Grab Sean's trace_init/cleanup code, use it to provide tracefs
> available by default to all pr_debugs.  This will likely need some
> further per-module treatment; perhaps something reflecting hierarchy
> of module,file,function,line, maybe with a tuned flattening.
> 
> endif CONFIG_TRACING
> 
> Add a new +T flag to enable tracing, independent of +p, and add and
> use 3 macros: dyndbg_site_is_enabled/logging/tracing(), to encapsulate
> the flag checks.  Existing code treats T like other flags.

I posted a patchset a while ago to do something very similar, but that
got stalled for some reason and I unfortunately didn't follow it up:

 
https://lore.kernel.org/lkml/20200825153338.17061-1-vincent.whitchu...@axis.com/

A key difference between that patchset and this patch (besides that
small fact that I used +x instead of +T) was that my patchset allowed
the dyndbg trace to be emitted to the main buffer and did not force them
to be in an instance-specific buffer.

That feature is quite important at least for my use case since I often
use dyndbg combined with function tracing, and the latter doesn't work
on non-main instances according to Documentation/trace/ftrace.rst.

For example, here's a random example of a bootargs from one of my recent
debugging sessions:

 trace_event=printk:* ftrace_filter=_mmc*,mmc*,sd*,dw_mci*,mci*
 ftrace=function trace_buf_size=20M dyndbg="file drivers/mmc/* +x"



[Bug 215003] apple_gmux fails to initialize and iGPU unclaimed on MacBook Pro 16" 2019

2021-11-14 Thread bugzilla-daemon
https://bugzilla.kernel.org/show_bug.cgi?id=215003

--- Comment #7 from Lukas Wunner (lu...@wunner.de) ---
The gpu-switch utility I've linked to above has macOS and Windows versions. You
could try using it from one of those OSes to switch to the iGPU on next boot,
then boot into Linux.

Perhaps you could add a few debug printk's to find out which runtime services
call causes the crash.

In summary, there are two issues here: The EFI issue which prevents you from
switching to the iGPU on Linux, and the GMUX incompatibility.  You may want to
open a separate bug for the former and assign it to the "EFI" Product so that
Ard Biesheuvel and others can take a look.

-- 
You may reply to this email to add a comment.

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

[Bug 215003] apple_gmux fails to initialize and iGPU unclaimed on MacBook Pro 16" 2019

2021-11-14 Thread bugzilla-daemon
https://bugzilla.kernel.org/show_bug.cgi?id=215003

--- Comment #6 from Xiaolei Yu (dreifachst...@gmail.com) ---
(In reply to Lukas Wunner from comment #5)
> Hm, why are runtime services disabled? Are you using "noefi" or
> "efi=noruntime" on the command line or is this perhaps an RT kernel? Could
> you attach full dmesg output?
> 

EFI runtime service is disabled after a firmware page fault during boot. I
pasted the trace in #4.

-- 
You may reply to this email to add a comment.

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