Re: [PATCH] habanalabs: change unused extern decl of hdev to forward decl of hl_device

2023-02-12 Thread Stanislaw Gruszka
On Wed, Feb 08, 2023 at 07:54:50AM -0800, Tom Rix wrote:
> Building with clang W=2 has several similar warnings
> drivers/accel/habanalabs/common/decoder.c:46:51: error: declaration shadows a 
> variable in the global scope [-Werror,-Wshadow]
> static void dec_error_intr_work(struct hl_device *hdev, u32 base_addr, u32 
> core_id)
>   ^
> drivers/accel/habanalabs/common/security.h:13:26: note: previous declaration 
> is here
> extern struct hl_device *hdev;
>  ^
> 
> There is no global definition of hdev, so the extern is not needed.
> Searched with
> grep -r '^struct' . | grep hl_dev
> 
> Change to an forward decl to resolve these issues
> drivers/accel/habanalabs/common/mmu/../security.h:133:40: error: ‘struct 
> hl_device’ declared inside parameter list will not be visible outside of this 
> definition or declaration [-Werror]
>   133 | bool (*skip_block_hook)(struct hl_device *hdev,
>   |^
> 
> Signed-off-by: Tom Rix 
Reviewed-by: Stanislaw Gruszka 

> ---
>  drivers/accel/habanalabs/common/security.h | 2 +-
>  1 file changed, 1 insertion(+), 1 deletion(-)
> 
> diff --git a/drivers/accel/habanalabs/common/security.h 
> b/drivers/accel/habanalabs/common/security.h
> index 234b4a6ed8bc..d7a3b3e82ea4 100644
> --- a/drivers/accel/habanalabs/common/security.h
> +++ b/drivers/accel/habanalabs/common/security.h
> @@ -10,7 +10,7 @@
>  
>  #include 
>  
> -extern struct hl_device *hdev;
> +struct hl_device;
>  
>  /* special blocks */
>  #define HL_MAX_NUM_OF_GLBL_ERR_CAUSE 10
> -- 
> 2.26.3
> 


Re: linux-6.2-rc4+ hangs on poweroff/reboot: Bisected

2023-02-12 Thread Dave Airlie
On Sun, 12 Feb 2023 at 00:43, Chris Clayton  wrote:
>
>
>
> On 10/02/2023 19:33, Linux regression tracking (Thorsten Leemhuis) wrote:
> > On 10.02.23 20:01, Karol Herbst wrote:
> >> On Fri, Feb 10, 2023 at 7:35 PM Linux regression tracking (Thorsten
> >> Leemhuis)  wrote:
> >>>
> >>> On 08.02.23 09:48, Chris Clayton wrote:
> 
>  I'm assuming  that we are not going to see a fix for this regression 
>  before 6.2 is released.
> >>>
> >>> Yeah, looks like it. That's unfortunate, but happens. But there is still
> >>> time to fix it and there is one thing I wonder:
> >>>
> >>> Did any of the nouveau developers look at the netconsole captures Chris
> >>> posted more than a week ago to check if they somehow help to track down
> >>> the root of this problem?
> >>
> >> I did now and I can't spot anything. I think at this point it would
> >> make sense to dump the active tasks/threads via sqsrq keys to see if
> >> any is in a weird state preventing the machine from shutting down.
> >
> > Many thx for looking into it!
>
> Yes, thanks Karol.
>
> Attached is the output from dmesg when this block of code:
>
> /bin/mount /dev/sda7 /mnt/sda7
> /bin/mountpoint /proc || /bin/mount /proc
> /bin/dmesg -w > /mnt/sda7/sysrq.dmesg.log &
> /bin/echo t > /proc/sysrq-trigger
> /bin/sleep 1
> /bin/sync
> /bin/sleep 1
> kill $(pidof dmesg)
> /bin/umount /mnt/sda7
>
> is executed immediately before /sbin/reboot is called as the final step of 
> rebooting my system.
>
> I hope this is what you were looking for, but if not, please let me know what 
> you need

Another shot in the dark, but does nouveau.runpm=0 help at all?

Dave.


[syzbot] memory leak in vma_node_allow

2023-02-12 Thread syzbot
Hello,

syzbot found the following issue on:

HEAD commit:0983f6bf2bfc Merge tag 'devicetree-fixes-for-6.2-2' of git..
git tree:   upstream
console output: https://syzkaller.appspot.com/x/log.txt?x=134dab4d48
kernel config:  https://syzkaller.appspot.com/x/.config?x=9e55e71813900595
dashboard link: https://syzkaller.appspot.com/bug?extid=58ea3177ba8bd0a5d8ee
compiler:   gcc (Debian 10.2.1-6) 10.2.1 20210110, GNU ld (GNU Binutils for 
Debian) 2.35.2
syz repro:  https://syzkaller.appspot.com/x/repro.syz?x=15052a8348
C reproducer:   https://syzkaller.appspot.com/x/repro.c?x=13073cfb48

Downloadable assets:
disk image: 
https://storage.googleapis.com/syzbot-assets/dfe2e2ac7b39/disk-0983f6bf.raw.xz
vmlinux: 
https://storage.googleapis.com/syzbot-assets/bd09e355e210/vmlinux-0983f6bf.xz
kernel image: 
https://storage.googleapis.com/syzbot-assets/8409e5f10fab/bzImage-0983f6bf.xz

IMPORTANT: if you fix the issue, please add the following tag to the commit:
Reported-by: syzbot+58ea3177ba8bd0a5d...@syzkaller.appspotmail.com

Warning: Permanently added '10.128.1.168' (ECDSA) to the list of known hosts.
executing program
executing program
BUG: memory leak
unreferenced object 0x88810f1c75c0 (size 64):
  comm "syz-executor750", pid 5060, jiffies 4294945258 (age 13.860s)
  hex dump (first 32 bytes):
01 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00  
00 00 00 00 00 00 00 00 00 d6 e4 04 81 88 ff ff  
  backtrace:
[] kmalloc_trace+0x24/0x90 mm/slab_common.c:1062
[] kmalloc include/linux/slab.h:580 [inline]
[] vma_node_allow+0x3a/0x150 
drivers/gpu/drm/drm_vma_manager.c:255
[] drm_gem_handle_create_tail+0x10e/0x250 
drivers/gpu/drm/drm_gem.c:377
[] drm_gem_shmem_create_with_handle 
drivers/gpu/drm/drm_gem_shmem_helper.c:432 [inline]
[] drm_gem_shmem_dumb_create+0xbd/0x200 
drivers/gpu/drm/drm_gem_shmem_helper.c:534
[] drm_mode_create_dumb+0x11b/0x150 
drivers/gpu/drm/drm_dumb_buffers.c:96
[] drm_ioctl_kernel+0x148/0x260 
drivers/gpu/drm/drm_ioctl.c:788
[] drm_ioctl+0x2f0/0x500 drivers/gpu/drm/drm_ioctl.c:891
[] vfs_ioctl fs/ioctl.c:51 [inline]
[] __do_sys_ioctl fs/ioctl.c:870 [inline]
[] __se_sys_ioctl fs/ioctl.c:856 [inline]
[] __x64_sys_ioctl+0x100/0x140 fs/ioctl.c:856
[] do_syscall_x64 arch/x86/entry/common.c:50 [inline]
[] do_syscall_64+0x39/0xb0 arch/x86/entry/common.c:80
[] entry_SYSCALL_64_after_hwframe+0x63/0xcd

BUG: memory leak
unreferenced object 0x888109662d80 (size 64):
  comm "syz-executor750", pid 5060, jiffies 4294945258 (age 13.870s)
  hex dump (first 32 bytes):
01 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00  
00 00 00 00 00 00 00 00 00 d6 e4 04 81 88 ff ff  
  backtrace:
[] kmalloc_trace+0x24/0x90 mm/slab_common.c:1062
[] kmalloc include/linux/slab.h:580 [inline]
[] vma_node_allow+0x3a/0x150 
drivers/gpu/drm/drm_vma_manager.c:255
[] drm_gem_handle_create_tail+0x10e/0x250 
drivers/gpu/drm/drm_gem.c:377
[] drm_gem_shmem_create_with_handle 
drivers/gpu/drm/drm_gem_shmem_helper.c:432 [inline]
[] drm_gem_shmem_dumb_create+0xbd/0x200 
drivers/gpu/drm/drm_gem_shmem_helper.c:534
[] drm_mode_create_dumb+0x11b/0x150 
drivers/gpu/drm/drm_dumb_buffers.c:96
[] drm_ioctl_kernel+0x148/0x260 
drivers/gpu/drm/drm_ioctl.c:788
[] drm_ioctl+0x2f0/0x500 drivers/gpu/drm/drm_ioctl.c:891
[] vfs_ioctl fs/ioctl.c:51 [inline]
[] __do_sys_ioctl fs/ioctl.c:870 [inline]
[] __se_sys_ioctl fs/ioctl.c:856 [inline]
[] __x64_sys_ioctl+0x100/0x140 fs/ioctl.c:856
[] do_syscall_x64 arch/x86/entry/common.c:50 [inline]
[] do_syscall_64+0x39/0xb0 arch/x86/entry/common.c:80
[] entry_SYSCALL_64_after_hwframe+0x63/0xcd

BUG: memory leak
unreferenced object 0x888109662900 (size 64):
  comm "syz-executor750", pid 5069, jiffies 4294945834 (age 8.110s)
  hex dump (first 32 bytes):
01 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00  
00 00 00 00 00 00 00 00 00 ce 8f 09 81 88 ff ff  
  backtrace:
[] kmalloc_trace+0x24/0x90 mm/slab_common.c:1062
[] kmalloc include/linux/slab.h:580 [inline]
[] vma_node_allow+0x3a/0x150 
drivers/gpu/drm/drm_vma_manager.c:255
[] drm_gem_handle_create_tail+0x10e/0x250 
drivers/gpu/drm/drm_gem.c:377
[] drm_gem_shmem_create_with_handle 
drivers/gpu/drm/drm_gem_shmem_helper.c:432 [inline]
[] drm_gem_shmem_dumb_create+0xbd/0x200 
drivers/gpu/drm/drm_gem_shmem_helper.c:534
[] drm_mode_create_dumb+0x11b/0x150 
drivers/gpu/drm/drm_dumb_buffers.c:96
[] drm_ioctl_kernel+0x148/0x260 
drivers/gpu/drm/drm_ioctl.c:788
[] drm_ioctl+0x2f0/0x500 drivers/gpu/drm/drm_ioctl.c:891
[] vfs_ioctl fs/ioctl.c:51 [inline]
[] __do_sys_ioctl fs/ioctl.c:870 [inline]
[] __se_sys_ioctl fs/ioctl.c:856 [inline]
[] __x64_sys_ioctl+0x100/0x140 fs/ioctl.c:856
[] do_syscall_x64 arch/x86/entry/common.c:50 [inline]
[] 

linux-next: manual merge of the drm tree with the drm-fixes tree

2023-02-12 Thread Stephen Rothwell
Hi all,

Today's linux-next merge of the drm tree got a conflict in:

  drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c

between commits:

  877f26bf3ca6 ("drm/amd/display: disable S/G display on DCN 2.1.0")
  077e9659581a ("drm/amd/display: disable S/G display on DCN 3.1.2/3")
  7ece674cd946 ("Revert "drm/amd/display: disable S/G display on DCN 3.1.4"")
  9734a75cd99d ("Revert "drm/amd/display: disable S/G display on DCN 3.1.2/3"")
  1b7ac7989ad8 ("Revert "drm/amd/display: disable S/G display on DCN 2.1.0"")
  e7d636476ba7 ("Revert "drm/amd/display: disable S/G display on DCN 3.1.5"")

from the drm-fixes tree and commits:

  2404f9b0ea01 ("drm/amd/display: disable S/G display on DCN 2.1.0")
  f081cd4ca265 ("drm/amd/display: disable S/G display on DCN 3.1.2/3")
  69ed0c5d44d7 ("Revert "drm/amd/display: disable S/G display on DCN 3.1.4"")

from the drm tree.

Git's automatic merge ignored commit 1b7ac7989ad8, since on the HEAD
side it was cancelled out by commit 877f26bf3ca6.  So I have to manually
reapply commit 1b7ac7989ad8.

This is an issue with duplicate patches that you need to keep in mind.

I fixed it up (I used the former changes) and can carry the fix as
necessary. This is now fixed as far as linux-next is concerned, but any
non trivial conflicts should be mentioned to your upstream maintainer
when your tree is submitted for merging.  You may also want to consider
cooperating with the maintainer of the conflicting tree to minimise any
particularly complex conflicts.

-- 
Cheers,
Stephen Rothwell


pgp6Y3c7Kw1lR.pgp
Description: OpenPGP digital signature


[PATCH 27/27] habanalabs: don't trace cpu accessible dma alloc/free

2023-02-12 Thread Oded Gabbay
From: Dafna Hirschfeld 

The cpu accessible dma allocations use the gen_pool api which actually
does not allocate new memory from the system but manages memory already
allocated before. When tracing this together with real dma
allocation/free it cause confusing logs like a '0' dma address and
a cpu address appearing twice etc.

Signed-off-by: Dafna Hirschfeld 
Reviewed-by: Oded Gabbay 
Signed-off-by: Oded Gabbay 
---
 drivers/accel/habanalabs/common/device.c | 29 +++-
 drivers/accel/habanalabs/common/habanalabs.h | 12 ++--
 2 files changed, 12 insertions(+), 29 deletions(-)

diff --git a/drivers/accel/habanalabs/common/device.c 
b/drivers/accel/habanalabs/common/device.c
index 8e71793c6ad1..fefe70bbbede 100644
--- a/drivers/accel/habanalabs/common/device.c
+++ b/drivers/accel/habanalabs/common/device.c
@@ -22,7 +22,6 @@
 
 enum dma_alloc_type {
DMA_ALLOC_COHERENT,
-   DMA_ALLOC_CPU_ACCESSIBLE,
DMA_ALLOC_POOL,
 };
 
@@ -121,9 +120,6 @@ static void *hl_dma_alloc_common(struct hl_device *hdev, 
size_t size, dma_addr_t
case DMA_ALLOC_COHERENT:
ptr = hdev->asic_funcs->asic_dma_alloc_coherent(hdev, size, 
dma_handle, flag);
break;
-   case DMA_ALLOC_CPU_ACCESSIBLE:
-   ptr = hdev->asic_funcs->cpu_accessible_dma_pool_alloc(hdev, 
size, dma_handle);
-   break;
case DMA_ALLOC_POOL:
ptr = hdev->asic_funcs->asic_dma_pool_zalloc(hdev, size, flag, 
dma_handle);
break;
@@ -147,9 +143,6 @@ static void hl_asic_dma_free_common(struct hl_device *hdev, 
size_t size, void *c
case DMA_ALLOC_COHERENT:
hdev->asic_funcs->asic_dma_free_coherent(hdev, size, cpu_addr, 
dma_handle);
break;
-   case DMA_ALLOC_CPU_ACCESSIBLE:
-   hdev->asic_funcs->cpu_accessible_dma_pool_free(hdev, size, 
cpu_addr);
-   break;
case DMA_ALLOC_POOL:
hdev->asic_funcs->asic_dma_pool_free(hdev, cpu_addr, 
dma_handle);
break;
@@ -170,18 +163,6 @@ void hl_asic_dma_free_coherent_caller(struct hl_device 
*hdev, size_t size, void
hl_asic_dma_free_common(hdev, size, cpu_addr, dma_handle, 
DMA_ALLOC_COHERENT, caller);
 }
 
-void *hl_cpu_accessible_dma_pool_alloc_caller(struct hl_device *hdev, size_t 
size,
-   dma_addr_t *dma_handle, const 
char *caller)
-{
-   return hl_dma_alloc_common(hdev, size, dma_handle, 0, 
DMA_ALLOC_CPU_ACCESSIBLE, caller);
-}
-
-void hl_cpu_accessible_dma_pool_free_caller(struct hl_device *hdev, size_t 
size, void *vaddr,
-   const char *caller)
-{
-   hl_asic_dma_free_common(hdev, size, vaddr, 0, DMA_ALLOC_CPU_ACCESSIBLE, 
caller);
-}
-
 void *hl_asic_dma_pool_zalloc_caller(struct hl_device *hdev, size_t size, 
gfp_t mem_flags,
dma_addr_t *dma_handle, const char 
*caller)
 {
@@ -194,6 +175,16 @@ void hl_asic_dma_pool_free_caller(struct hl_device *hdev, 
void *vaddr, dma_addr_
hl_asic_dma_free_common(hdev, 0, vaddr, dma_addr, DMA_ALLOC_POOL, 
caller);
 }
 
+void *hl_cpu_accessible_dma_pool_alloc(struct hl_device *hdev, size_t size, 
dma_addr_t *dma_handle)
+{
+   return hdev->asic_funcs->cpu_accessible_dma_pool_alloc(hdev, size, 
dma_handle);
+}
+
+void hl_cpu_accessible_dma_pool_free(struct hl_device *hdev, size_t size, void 
*vaddr)
+{
+   hdev->asic_funcs->cpu_accessible_dma_pool_free(hdev, size, vaddr);
+}
+
 int hl_dma_map_sgtable(struct hl_device *hdev, struct sg_table *sgt, enum 
dma_data_direction dir)
 {
struct asic_fixed_properties *prop = >asic_prop;
diff --git a/drivers/accel/habanalabs/common/habanalabs.h 
b/drivers/accel/habanalabs/common/habanalabs.h
index ec0879168adf..7b6b4ff20a3b 100644
--- a/drivers/accel/habanalabs/common/habanalabs.h
+++ b/drivers/accel/habanalabs/common/habanalabs.h
@@ -155,18 +155,12 @@ enum hl_mmu_enablement {
 #define hl_asic_dma_alloc_coherent(hdev, size, dma_handle, flags) \
hl_asic_dma_alloc_coherent_caller(hdev, size, dma_handle, flags, 
__func__)
 
-#define hl_cpu_accessible_dma_pool_alloc(hdev, size, dma_handle) \
-   hl_cpu_accessible_dma_pool_alloc_caller(hdev, size, dma_handle, 
__func__)
-
 #define hl_asic_dma_pool_zalloc(hdev, size, mem_flags, dma_handle) \
hl_asic_dma_pool_zalloc_caller(hdev, size, mem_flags, dma_handle, 
__func__)
 
 #define hl_asic_dma_free_coherent(hdev, size, cpu_addr, dma_handle) \
hl_asic_dma_free_coherent_caller(hdev, size, cpu_addr, dma_handle, 
__func__)
 
-#define hl_cpu_accessible_dma_pool_free(hdev, size, vaddr) \
-   hl_cpu_accessible_dma_pool_free_caller(hdev, size, vaddr, __func__)
-
 #define hl_asic_dma_pool_free(hdev, vaddr, dma_addr) \
hl_asic_dma_pool_free_caller(hdev, vaddr, dma_addr, __func__)
 
@@ -3602,14 +3596,12 @@ static inline bool hl_mem_area_crosses_range(u64 
address, u32 size,
 

[PATCH 26/27] habanalabs: in hl_device_reset small refactor for readabilty

2023-02-12 Thread Oded Gabbay
From: Dafna Hirschfeld 

in the out_err flow, combine the two cases of soft-reset since
they have mostly common code. In addition unlock reset_info.lock
after touching reset count.

Signed-off-by: Dafna Hirschfeld 
Reviewed-by: Oded Gabbay 
Signed-off-by: Oded Gabbay 
---
 drivers/accel/habanalabs/common/device.c | 17 -
 1 file changed, 8 insertions(+), 9 deletions(-)

diff --git a/drivers/accel/habanalabs/common/device.c 
b/drivers/accel/habanalabs/common/device.c
index 47ed2fec68bc..8e71793c6ad1 100644
--- a/drivers/accel/habanalabs/common/device.c
+++ b/drivers/accel/habanalabs/common/device.c
@@ -1852,17 +1852,16 @@ int hl_device_reset(struct hl_device *hdev, u32 flags)
"%s Failed to reset! Device is NOT usable\n",
dev_name(&(hdev)->pdev->dev));
hdev->reset_info.hard_reset_cnt++;
-   } else if (reset_upon_device_release) {
-   spin_unlock(>reset_info.lock);
-   dev_err(hdev->dev, "Failed to reset device after user 
release\n");
-   flags |= HL_DRV_RESET_HARD;
-   flags &= ~HL_DRV_RESET_DEV_RELEASE;
-   hard_reset = true;
-   goto escalate_reset_flow;
} else {
+   if (reset_upon_device_release) {
+   dev_err(hdev->dev, "Failed to reset device after user 
release\n");
+   flags &= ~HL_DRV_RESET_DEV_RELEASE;
+   } else {
+   dev_err(hdev->dev, "Failed to do compute reset\n");
+   hdev->reset_info.compute_reset_cnt++;
+   }
+
spin_unlock(>reset_info.lock);
-   dev_err(hdev->dev, "Failed to do compute reset\n");
-   hdev->reset_info.compute_reset_cnt++;
flags |= HL_DRV_RESET_HARD;
hard_reset = true;
goto escalate_reset_flow;
-- 
2.25.1



[PATCH 25/27] habanalabs: in hl_device_reset remove 'hard_instead_of_soft'

2023-02-12 Thread Oded Gabbay
From: Dafna Hirschfeld 

Because this field is only used for debug print,
we can do more precise debug directly instead.

Signed-off-by: Dafna Hirschfeld 
Reviewed-by: Oded Gabbay 
Signed-off-by: Oded Gabbay 
---
 drivers/accel/habanalabs/common/device.c | 13 +
 1 file changed, 5 insertions(+), 8 deletions(-)

diff --git a/drivers/accel/habanalabs/common/device.c 
b/drivers/accel/habanalabs/common/device.c
index 0e405e4c4b32..47ed2fec68bc 100644
--- a/drivers/accel/habanalabs/common/device.c
+++ b/drivers/accel/habanalabs/common/device.c
@@ -1474,9 +1474,8 @@ static void handle_reset_trigger(struct hl_device *hdev, 
u32 flags)
  */
 int hl_device_reset(struct hl_device *hdev, u32 flags)
 {
-   bool hard_reset, from_hard_reset_thread, fw_reset, hard_instead_soft = 
false,
-   reset_upon_device_release, schedule_hard_reset = false,
-   delay_reset, from_dev_release, from_watchdog_thread;
+   bool hard_reset, from_hard_reset_thread, fw_reset, 
reset_upon_device_release,
+   schedule_hard_reset = false, delay_reset, from_dev_release, 
from_watchdog_thread;
u64 idle_mask[HL_BUSY_ENGINES_MASK_EXT_SIZE] = {0};
struct hl_ctx *ctx;
int i, rc;
@@ -1500,7 +1499,7 @@ int hl_device_reset(struct hl_device *hdev, u32 flags)
}
 
if (!hard_reset && !hdev->asic_prop.supports_compute_reset) {
-   hard_instead_soft = true;
+   dev_dbg(hdev->dev, "asic doesn't support compute reset - do 
hard-reset instead\n");
hard_reset = true;
}
 
@@ -1515,13 +1514,11 @@ int hl_device_reset(struct hl_device *hdev, u32 flags)
}
 
if (!hard_reset && !hdev->asic_prop.allow_inference_soft_reset) {
-   hard_instead_soft = true;
+   dev_dbg(hdev->dev,
+   "asic doesn't allow inference soft reset - do 
hard-reset instead\n");
hard_reset = true;
}
 
-   if (hard_instead_soft)
-   dev_dbg(hdev->dev, "Doing hard-reset instead of compute 
reset\n");
-
 do_reset:
/* Re-entry of reset thread */
if (from_hard_reset_thread && hdev->process_kill_trial_cnt)
-- 
2.25.1



[PATCH 17/27] habanalabs/gaudi2: modify events reset policy

2023-02-12 Thread Oded Gabbay
From: Ohad Sharabi 

The policy file of the events reset has been modified.
This change is reflected in the autogenerated file.

Signed-off-by: Ohad Sharabi 
Reviewed-by: Oded Gabbay 
Signed-off-by: Oded Gabbay 
---
 .../gaudi2/gaudi2_async_ids_map_extended.h| 488 +-
 1 file changed, 244 insertions(+), 244 deletions(-)

diff --git 
a/drivers/accel/habanalabs/include/gaudi2/gaudi2_async_ids_map_extended.h 
b/drivers/accel/habanalabs/include/gaudi2/gaudi2_async_ids_map_extended.h
index a161c6a9fd93..da0435581d61 100644
--- a/drivers/accel/habanalabs/include/gaudi2/gaudi2_async_ids_map_extended.h
+++ b/drivers/accel/habanalabs/include/gaudi2/gaudi2_async_ids_map_extended.h
@@ -855,183 +855,183 @@ static struct gaudi2_async_events_ids_map 
gaudi2_irq_map_table[] = {
 .name = "" },
{ .fc_id = 412, .cpu_id = 84, .valid = 1, .msg = 0, .reset = 
EVENT_RESET_TYPE_HARD,
 .name = "PCIE_ADDR_DEC_ERR" },
-   { .fc_id = 413, .cpu_id = 85, .valid = 1, .msg = 0, .reset = 
EVENT_RESET_TYPE_HARD,
+   { .fc_id = 413, .cpu_id = 85, .valid = 1, .msg = 0, .reset = 
EVENT_RESET_TYPE_COMPUTE,
 .name = "TPC0_AXI_ERR_RSP" },
-   { .fc_id = 414, .cpu_id = 85, .valid = 1, .msg = 0, .reset = 
EVENT_RESET_TYPE_HARD,
+   { .fc_id = 414, .cpu_id = 85, .valid = 1, .msg = 0, .reset = 
EVENT_RESET_TYPE_COMPUTE,
 .name = "TPC1_AXI_ERR_RSP" },
-   { .fc_id = 415, .cpu_id = 85, .valid = 1, .msg = 0, .reset = 
EVENT_RESET_TYPE_HARD,
+   { .fc_id = 415, .cpu_id = 85, .valid = 1, .msg = 0, .reset = 
EVENT_RESET_TYPE_COMPUTE,
 .name = "TPC2_AXI_ERR_RSP" },
-   { .fc_id = 416, .cpu_id = 85, .valid = 1, .msg = 0, .reset = 
EVENT_RESET_TYPE_HARD,
+   { .fc_id = 416, .cpu_id = 85, .valid = 1, .msg = 0, .reset = 
EVENT_RESET_TYPE_COMPUTE,
 .name = "TPC3_AXI_ERR_RSP" },
-   { .fc_id = 417, .cpu_id = 85, .valid = 1, .msg = 0, .reset = 
EVENT_RESET_TYPE_HARD,
+   { .fc_id = 417, .cpu_id = 85, .valid = 1, .msg = 0, .reset = 
EVENT_RESET_TYPE_COMPUTE,
 .name = "TPC4_AXI_ERR_RSP" },
-   { .fc_id = 418, .cpu_id = 85, .valid = 1, .msg = 0, .reset = 
EVENT_RESET_TYPE_HARD,
+   { .fc_id = 418, .cpu_id = 85, .valid = 1, .msg = 0, .reset = 
EVENT_RESET_TYPE_COMPUTE,
 .name = "TPC5_AXI_ERR_RSP" },
-   { .fc_id = 419, .cpu_id = 85, .valid = 1, .msg = 0, .reset = 
EVENT_RESET_TYPE_HARD,
+   { .fc_id = 419, .cpu_id = 85, .valid = 1, .msg = 0, .reset = 
EVENT_RESET_TYPE_COMPUTE,
 .name = "TPC6_AXI_ERR_RSP" },
-   { .fc_id = 420, .cpu_id = 85, .valid = 1, .msg = 0, .reset = 
EVENT_RESET_TYPE_HARD,
+   { .fc_id = 420, .cpu_id = 85, .valid = 1, .msg = 0, .reset = 
EVENT_RESET_TYPE_COMPUTE,
 .name = "TPC7_AXI_ERR_RSP" },
-   { .fc_id = 421, .cpu_id = 85, .valid = 1, .msg = 0, .reset = 
EVENT_RESET_TYPE_HARD,
+   { .fc_id = 421, .cpu_id = 85, .valid = 1, .msg = 0, .reset = 
EVENT_RESET_TYPE_COMPUTE,
 .name = "TPC8_AXI_ERR_RSP" },
-   { .fc_id = 422, .cpu_id = 85, .valid = 1, .msg = 0, .reset = 
EVENT_RESET_TYPE_HARD,
+   { .fc_id = 422, .cpu_id = 85, .valid = 1, .msg = 0, .reset = 
EVENT_RESET_TYPE_COMPUTE,
 .name = "TPC9_AXI_ERR_RSP" },
-   { .fc_id = 423, .cpu_id = 85, .valid = 1, .msg = 0, .reset = 
EVENT_RESET_TYPE_HARD,
+   { .fc_id = 423, .cpu_id = 85, .valid = 1, .msg = 0, .reset = 
EVENT_RESET_TYPE_COMPUTE,
 .name = "TPC10_AXI_ERR_RSP" },
-   { .fc_id = 424, .cpu_id = 85, .valid = 1, .msg = 0, .reset = 
EVENT_RESET_TYPE_HARD,
+   { .fc_id = 424, .cpu_id = 85, .valid = 1, .msg = 0, .reset = 
EVENT_RESET_TYPE_COMPUTE,
 .name = "TPC11_AXI_ERR_RSP" },
-   { .fc_id = 425, .cpu_id = 85, .valid = 1, .msg = 0, .reset = 
EVENT_RESET_TYPE_HARD,
+   { .fc_id = 425, .cpu_id = 85, .valid = 1, .msg = 0, .reset = 
EVENT_RESET_TYPE_COMPUTE,
 .name = "TPC12_AXI_ERR_RSP" },
-   { .fc_id = 426, .cpu_id = 85, .valid = 1, .msg = 0, .reset = 
EVENT_RESET_TYPE_HARD,
+   { .fc_id = 426, .cpu_id = 85, .valid = 1, .msg = 0, .reset = 
EVENT_RESET_TYPE_COMPUTE,
 .name = "TPC13_AXI_ERR_RSP" },
-   { .fc_id = 427, .cpu_id = 85, .valid = 1, .msg = 0, .reset = 
EVENT_RESET_TYPE_HARD,
+   { .fc_id = 427, .cpu_id = 85, .valid = 1, .msg = 0, .reset = 
EVENT_RESET_TYPE_COMPUTE,
 .name = "TPC14_AXI_ERR_RSP" },
-   { .fc_id = 428, .cpu_id = 85, .valid = 1, .msg = 0, .reset = 
EVENT_RESET_TYPE_HARD,
+   { .fc_id = 428, .cpu_id = 85, .valid = 1, .msg = 0, .reset = 
EVENT_RESET_TYPE_COMPUTE,
 .name = "TPC15_AXI_ERR_RSP" },
-   { .fc_id = 429, .cpu_id = 85, .valid = 1, .msg = 0, .reset = 
EVENT_RESET_TYPE_HARD,
+   { .fc_id = 429, .cpu_id = 85, .valid = 1, .msg = 0, .reset = 
EVENT_RESET_TYPE_COMPUTE,
 .name = "TPC16_AXI_ERR_RSP" },
-   { 

[PATCH 23/27] habanalabs: tiny refactor of hl_device_reset for readability

2023-02-12 Thread Oded Gabbay
From: Dafna Hirschfeld 

Align assignment of reset_upon_device_release to the convention used
in this function.

Signed-off-by: Dafna Hirschfeld 
Reviewed-by: Oded Gabbay 
Signed-off-by: Oded Gabbay 
---
 drivers/accel/habanalabs/common/device.c | 7 +++
 1 file changed, 3 insertions(+), 4 deletions(-)

diff --git a/drivers/accel/habanalabs/common/device.c 
b/drivers/accel/habanalabs/common/device.c
index 2d496cd935b2..0e405e4c4b32 100644
--- a/drivers/accel/habanalabs/common/device.c
+++ b/drivers/accel/habanalabs/common/device.c
@@ -1475,7 +1475,7 @@ static void handle_reset_trigger(struct hl_device *hdev, 
u32 flags)
 int hl_device_reset(struct hl_device *hdev, u32 flags)
 {
bool hard_reset, from_hard_reset_thread, fw_reset, hard_instead_soft = 
false,
-   reset_upon_device_release = false, schedule_hard_reset 
= false,
+   reset_upon_device_release, schedule_hard_reset = false,
delay_reset, from_dev_release, from_watchdog_thread;
u64 idle_mask[HL_BUSY_ENGINES_MASK_EXT_SIZE] = {0};
struct hl_ctx *ctx;
@@ -1492,6 +1492,7 @@ int hl_device_reset(struct hl_device *hdev, u32 flags)
from_dev_release = !!(flags & HL_DRV_RESET_DEV_RELEASE);
delay_reset = !!(flags & HL_DRV_RESET_DELAY);
from_watchdog_thread = !!(flags & HL_DRV_RESET_FROM_WD_THR);
+   reset_upon_device_release = hdev->reset_upon_device_release && 
from_dev_release;
 
if (!hard_reset && (hl_device_status(hdev) == 
HL_DEVICE_STATUS_MALFUNCTION)) {
dev_dbg(hdev->dev, "soft-reset isn't supported on a 
malfunctioning device\n");
@@ -1503,15 +1504,13 @@ int hl_device_reset(struct hl_device *hdev, u32 flags)
hard_reset = true;
}
 
-   if (hdev->reset_upon_device_release && from_dev_release) {
+   if (reset_upon_device_release) {
if (hard_reset) {
dev_crit(hdev->dev,
"Aborting reset because hard-reset is mutually 
exclusive with reset-on-device-release\n");
return -EINVAL;
}
 
-   reset_upon_device_release = true;
-
goto do_reset;
}
 
-- 
2.25.1



[PATCH 19/27] habanalabs: capture interrupt timestamp in handler

2023-02-12 Thread Oded Gabbay
From: Ofir Bitton 

In order for interrupt timestamp to be more accurate we should
capture it during the interrupt handling rather than in threaded
irq context.

Signed-off-by: Ofir Bitton 
Reviewed-by: Oded Gabbay 
Signed-off-by: Oded Gabbay 
---
 drivers/accel/habanalabs/common/habanalabs.h | 2 ++
 drivers/accel/habanalabs/common/irq.c| 9 ++---
 2 files changed, 8 insertions(+), 3 deletions(-)

diff --git a/drivers/accel/habanalabs/common/habanalabs.h 
b/drivers/accel/habanalabs/common/habanalabs.h
index 5624ea19ec0b..24ad15272040 100644
--- a/drivers/accel/habanalabs/common/habanalabs.h
+++ b/drivers/accel/habanalabs/common/habanalabs.h
@@ -1107,6 +1107,7 @@ enum hl_user_interrupt_type {
  * @type: user interrupt type
  * @wait_list_head: head to the list of user threads pending on this interrupt
  * @wait_list_lock: protects wait_list_head
+ * @timestamp: last timestamp taken upon interrupt
  * @interrupt_id: msix interrupt id
  */
 struct hl_user_interrupt {
@@ -1114,6 +1115,7 @@ struct hl_user_interrupt {
enum hl_user_interrupt_type type;
struct list_headwait_list_head;
spinlock_t  wait_list_lock;
+   ktime_t timestamp;
u32 interrupt_id;
 };
 
diff --git a/drivers/accel/habanalabs/common/irq.c 
b/drivers/accel/habanalabs/common/irq.c
index c61c9a294ab8..716228291b46 100644
--- a/drivers/accel/habanalabs/common/irq.c
+++ b/drivers/accel/habanalabs/common/irq.c
@@ -280,7 +280,6 @@ static void handle_user_interrupt(struct hl_device *hdev, 
struct hl_user_interru
struct list_head *ts_reg_free_list_head = NULL;
struct timestamp_reg_work_obj *job;
bool reg_node_handle_fail = false;
-   ktime_t now = ktime_get();
int rc;
 
/* For registration nodes:
@@ -303,13 +302,13 @@ static void handle_user_interrupt(struct hl_device *hdev, 
struct hl_user_interru
if (pend->ts_reg_info.buf) {
if (!reg_node_handle_fail) {
rc = handle_registration_node(hdev, 
pend,
-   
_reg_free_list_head, now);
+   _reg_free_list_head, 
intr->timestamp);
if (rc)
reg_node_handle_fail = true;
}
} else {
/* Handle wait target value node */
-   pend->fence.timestamp = now;
+   pend->fence.timestamp = intr->timestamp;
complete_all(>fence.completion);
}
}
@@ -335,6 +334,10 @@ static void handle_user_interrupt(struct hl_device *hdev, 
struct hl_user_interru
  */
 irqreturn_t hl_irq_handler_user_interrupt(int irq, void *arg)
 {
+   struct hl_user_interrupt *user_int = arg;
+
+   user_int->timestamp = ktime_get();
+
return IRQ_WAKE_THREAD;
 }
 
-- 
2.25.1



[PATCH 21/27] habanalabs: fix print in hl_irq_handler_eq()

2023-02-12 Thread Oded Gabbay
From: Tomer Tayar 

"eq_base[eq->ci].hdr.ctl" is used directly in a print without a
le32_to_cpu() conversion.

Signed-off-by: Tomer Tayar 
Reviewed-by: Oded Gabbay 
Signed-off-by: Oded Gabbay 
---
 drivers/accel/habanalabs/common/irq.c | 7 +++
 1 file changed, 3 insertions(+), 4 deletions(-)

diff --git a/drivers/accel/habanalabs/common/irq.c 
b/drivers/accel/habanalabs/common/irq.c
index bd0e3413721b..4b062e8520f1 100644
--- a/drivers/accel/habanalabs/common/irq.c
+++ b/drivers/accel/habanalabs/common/irq.c
@@ -439,11 +439,10 @@ irqreturn_t hl_irq_handler_eq(int irq, void *arg)
 
cur_eqe_index = FIELD_GET(EQ_CTL_INDEX_MASK, cur_eqe);
if ((hdev->event_queue.check_eqe_index) &&
-   (((eq->prev_eqe_index + 1) & EQ_CTL_INDEX_MASK)
-   != cur_eqe_index)) {
+   (((eq->prev_eqe_index + 1) & EQ_CTL_INDEX_MASK) 
!= cur_eqe_index)) {
dev_dbg(hdev->dev,
-   "EQE 0x%x in queue is ready but index does not 
match %d!=%d",
-   eq_base[eq->ci].hdr.ctl,
+   "EQE %#x in queue is ready but index does not 
match %d!=%d",
+   cur_eqe,
((eq->prev_eqe_index + 1) & EQ_CTL_INDEX_MASK),
cur_eqe_index);
break;
-- 
2.25.1



[PATCH 18/27] habanalabs: change user interrupt to threaded IRQ

2023-02-12 Thread Oded Gabbay
From: Tal Cohen 

We prefer not to handle the user interrupt job inside the interrupt
context. Instead, use threaded IRQ to handle the user interrupts.
This will allow to avoid disabling interrupts when the user process
registers for a new event and to avoid long handling inside an
interrupt.

Signed-off-by: Tal Cohen 
Reviewed-by: Oded Gabbay 
Signed-off-by: Oded Gabbay 
---
 .../habanalabs/common/command_submission.c| 45 +--
 drivers/accel/habanalabs/common/habanalabs.h  |  1 +
 drivers/accel/habanalabs/common/irq.c | 13 ++
 drivers/accel/habanalabs/gaudi2/gaudi2.c  | 29 +++-
 4 files changed, 53 insertions(+), 35 deletions(-)

diff --git a/drivers/accel/habanalabs/common/command_submission.c 
b/drivers/accel/habanalabs/common/command_submission.c
index 24f3d82ee4cb..6c4d9b1aa5de 100644
--- a/drivers/accel/habanalabs/common/command_submission.c
+++ b/drivers/accel/habanalabs/common/command_submission.c
@@ -1082,9 +1082,8 @@ static void
 wake_pending_user_interrupt_threads(struct hl_user_interrupt *interrupt)
 {
struct hl_user_pending_interrupt *pend, *temp;
-   unsigned long flags;
 
-   spin_lock_irqsave(>wait_list_lock, flags);
+   spin_lock(>wait_list_lock);
list_for_each_entry_safe(pend, temp, >wait_list_head, 
wait_list_node) {
if (pend->ts_reg_info.buf) {
list_del(>wait_list_node);
@@ -1095,7 +1094,7 @@ wake_pending_user_interrupt_threads(struct 
hl_user_interrupt *interrupt)
complete_all(>fence.completion);
}
}
-   spin_unlock_irqrestore(>wait_list_lock, flags);
+   spin_unlock(>wait_list_lock);
 }
 
 void hl_release_pending_user_interrupts(struct hl_device *hdev)
@@ -3159,7 +3158,7 @@ static int ts_buff_get_kernel_ts_record(struct 
hl_mmap_mem_buf *buf,
struct hl_user_pending_interrupt *cb_last =
(struct hl_user_pending_interrupt 
*)ts_buff->kernel_buff_address +
(ts_buff->kernel_buff_size / sizeof(struct 
hl_user_pending_interrupt));
-   unsigned long flags, iter_counter = 0;
+   unsigned long iter_counter = 0;
u64 current_cq_counter;
ktime_t timestamp;
 
@@ -3173,7 +3172,7 @@ static int ts_buff_get_kernel_ts_record(struct 
hl_mmap_mem_buf *buf,
timestamp = ktime_get();
 
 start_over:
-   spin_lock_irqsave(wait_list_lock, flags);
+   spin_lock(wait_list_lock);
 
/* Unregister only if we didn't reach the target value
 * since in this case there will be no handling in irq context
@@ -3184,7 +3183,7 @@ static int ts_buff_get_kernel_ts_record(struct 
hl_mmap_mem_buf *buf,
current_cq_counter = *requested_offset_record->cq_kernel_addr;
if (current_cq_counter < 
requested_offset_record->cq_target_value) {
list_del(_offset_record->wait_list_node);
-   spin_unlock_irqrestore(wait_list_lock, flags);
+   spin_unlock(wait_list_lock);
 

hl_mmap_mem_buf_put(requested_offset_record->ts_reg_info.buf);
hl_cb_put(requested_offset_record->ts_reg_info.cq_cb);
@@ -3195,8 +3194,8 @@ static int ts_buff_get_kernel_ts_record(struct 
hl_mmap_mem_buf *buf,
dev_dbg(buf->mmg->dev,
"ts node in middle of irq handling\n");
 
-   /* irq handling in the middle give it time to finish */
-   spin_unlock_irqrestore(wait_list_lock, flags);
+   /* irq thread handling in the middle give it time to 
finish */
+   spin_unlock(wait_list_lock);
usleep_range(100, 1000);
if (++iter_counter == MAX_TS_ITER_NUM) {
dev_err(buf->mmg->dev,
@@ -3217,7 +3216,7 @@ static int ts_buff_get_kernel_ts_record(struct 
hl_mmap_mem_buf *buf,
(u64 *) cq_cb->kernel_address + cq_offset;
requested_offset_record->cq_target_value = target_value;
 
-   spin_unlock_irqrestore(wait_list_lock, flags);
+   spin_unlock(wait_list_lock);
}
 
*pend = requested_offset_record;
@@ -3237,7 +3236,7 @@ static int _hl_interrupt_wait_ioctl(struct hl_device 
*hdev, struct hl_ctx *ctx,
struct hl_user_pending_interrupt *pend;
struct hl_mmap_mem_buf *buf;
struct hl_cb *cq_cb;
-   unsigned long timeout, flags;
+   unsigned long timeout;
long completion_rc;
int rc = 0;
 
@@ -3284,7 +3283,7 @@ static int _hl_interrupt_wait_ioctl(struct hl_device 
*hdev, struct hl_ctx *ctx,
pend->cq_target_value = target_value;
}
 
-   spin_lock_irqsave(>wait_list_lock, flags);
+   spin_lock(>wait_list_lock);
 
/* We check for completion value as interrupt could have been received
 * before we 

[PATCH 24/27] habanalabs: rename security function parameters

2023-02-12 Thread Oded Gabbay
From: Koby Elbaz 

To match their description above the function

Signed-off-by: Koby Elbaz 
Reviewed-by: Oded Gabbay 
Signed-off-by: Oded Gabbay 
---
 drivers/accel/habanalabs/common/security.c | 6 +++---
 1 file changed, 3 insertions(+), 3 deletions(-)

diff --git a/drivers/accel/habanalabs/common/security.c 
b/drivers/accel/habanalabs/common/security.c
index 5f03ade07ead..297e6e44fd0c 100644
--- a/drivers/accel/habanalabs/common/security.c
+++ b/drivers/accel/habanalabs/common/security.c
@@ -502,7 +502,7 @@ int hl_init_pb_single_dcore(struct hl_device *hdev, u32 
dcore_offset,
 int hl_init_pb_ranges_single_dcore(struct hl_device *hdev, u32 dcore_offset,
u32 num_instances, u32 instance_offset,
const u32 pb_blocks[], u32 blocks_array_size,
-   const struct range *regs_range_array, u32 regs_range_array_size)
+   const struct range *user_regs_range_array, u32 
user_regs_range_array_size)
 {
int i;
struct hl_block_glbl_sec *glbl_sec;
@@ -514,8 +514,8 @@ int hl_init_pb_ranges_single_dcore(struct hl_device *hdev, 
u32 dcore_offset,
return -ENOMEM;
 
hl_secure_block(hdev, glbl_sec, blocks_array_size);
-   hl_unsecure_registers_range(hdev, regs_range_array,
-   regs_range_array_size, 0, pb_blocks, glbl_sec,
+   hl_unsecure_registers_range(hdev, user_regs_range_array,
+   user_regs_range_array_size, 0, pb_blocks, glbl_sec,
blocks_array_size);
 
/* Fill all blocks with the same configuration */
-- 
2.25.1



[PATCH 22/27] habanalabs: remove hl_irq_handler_default()

2023-02-12 Thread Oded Gabbay
From: Tomer Tayar 

hl_irq_handler_default() is not used and can be removed.

Signed-off-by: Tomer Tayar 
Reviewed-by: Oded Gabbay 
Signed-off-by: Oded Gabbay 
---
 drivers/accel/habanalabs/common/habanalabs.h |  1 -
 drivers/accel/habanalabs/common/irq.c| 18 --
 2 files changed, 19 deletions(-)

diff --git a/drivers/accel/habanalabs/common/habanalabs.h 
b/drivers/accel/habanalabs/common/habanalabs.h
index ed6987a0050f..ec0879168adf 100644
--- a/drivers/accel/habanalabs/common/habanalabs.h
+++ b/drivers/accel/habanalabs/common/habanalabs.h
@@ -3656,7 +3656,6 @@ irqreturn_t hl_irq_handler_cq(int irq, void *arg);
 irqreturn_t hl_irq_handler_eq(int irq, void *arg);
 irqreturn_t hl_irq_handler_dec_abnrm(int irq, void *arg);
 irqreturn_t hl_irq_handler_user_interrupt(int irq, void *arg);
-irqreturn_t hl_irq_handler_default(int irq, void *arg);
 irqreturn_t hl_irq_user_interrupt_thread_handler(int irq, void *arg);
 u32 hl_cq_inc_ptr(u32 ptr);
 
diff --git a/drivers/accel/habanalabs/common/irq.c 
b/drivers/accel/habanalabs/common/irq.c
index 4b062e8520f1..8c6705cf958e 100644
--- a/drivers/accel/habanalabs/common/irq.c
+++ b/drivers/accel/habanalabs/common/irq.c
@@ -392,24 +392,6 @@ irqreturn_t hl_irq_user_interrupt_thread_handler(int irq, 
void *arg)
return IRQ_HANDLED;
 }
 
-/**
- * hl_irq_handler_default - default irq handler
- *
- * @irq: irq number
- * @arg: pointer to user interrupt structure
- *
- */
-irqreturn_t hl_irq_handler_default(int irq, void *arg)
-{
-   struct hl_user_interrupt *user_interrupt = arg;
-   struct hl_device *hdev = user_interrupt->hdev;
-   u32 interrupt_id = user_interrupt->interrupt_id;
-
-   dev_err(hdev->dev, "got invalid user interrupt %u", interrupt_id);
-
-   return IRQ_HANDLED;
-}
-
 /**
  * hl_irq_handler_eq - irq handler for event queue
  *
-- 
2.25.1



[PATCH 20/27] habanalabs/gaudi2: add support for TPC assert

2023-02-12 Thread Oded Gabbay
From: Ofir Bitton 

In order to allow TPC engines to raise an assert, we must expose
the relevant MSIX interrupt to the user so he will configure the engine
correctly. In addition, we implement the corresponding interrupt
handler that will notify the user upon such an event.

Signed-off-by: Ofir Bitton 
Reviewed-by: Oded Gabbay 
Signed-off-by: Oded Gabbay 
---
 drivers/accel/habanalabs/common/habanalabs.h  |  5 
 .../habanalabs/common/habanalabs_ioctl.c  |  1 +
 drivers/accel/habanalabs/common/irq.c | 18 +
 drivers/accel/habanalabs/gaudi/gaudi.c|  1 +
 drivers/accel/habanalabs/gaudi2/gaudi2.c  | 25 ---
 drivers/accel/habanalabs/gaudi2/gaudi2P.h |  2 ++
 drivers/accel/habanalabs/goya/goya.c  |  1 +
 include/uapi/drm/habanalabs_accel.h   |  3 ++-
 8 files changed, 52 insertions(+), 4 deletions(-)

diff --git a/drivers/accel/habanalabs/common/habanalabs.h 
b/drivers/accel/habanalabs/common/habanalabs.h
index 24ad15272040..ed6987a0050f 100644
--- a/drivers/accel/habanalabs/common/habanalabs.h
+++ b/drivers/accel/habanalabs/common/habanalabs.h
@@ -665,6 +665,7 @@ struct hl_hints_range {
  * @first_available_cq: first available CQ for the user.
  * @user_interrupt_count: number of user interrupts.
  * @user_dec_intr_count: number of decoder interrupts exposed to user.
+ * @tpc_interrupt_id: interrupt id for TPC to use in order to raise events 
towards the host.
  * @cache_line_size: device cache line size.
  * @server_type: Server type that the ASIC is currently installed in.
  *   The value is according to enum hl_server_type in uapi file.
@@ -791,6 +792,7 @@ struct asic_fixed_properties {
u16 first_available_cq[HL_MAX_DCORES];
u16 user_interrupt_count;
u16 user_dec_intr_count;
+   u16 tpc_interrupt_id;
u16 cache_line_size;
u16 server_type;
u8  completion_queues_count;
@@ -1099,6 +1101,7 @@ struct hl_cq {
 enum hl_user_interrupt_type {
HL_USR_INTERRUPT_CQ = 0,
HL_USR_INTERRUPT_DECODER,
+   HL_USR_INTERRUPT_TPC
 };
 
 /**
@@ -3148,6 +3151,7 @@ struct hl_reset_info {
  * @user_interrupt: array of hl_user_interrupt. upon the corresponding user
  *  interrupt, driver will monitor the list of fences
  *  registered to this interrupt.
+ * @tpc_interrupt: single TPC interrupt for all TPCs.
  * @common_user_cq_interrupt: common user CQ interrupt for all user CQ 
interrupts.
  * upon any user CQ interrupt, driver will monitor the
  * list of fences registered to this common structure.
@@ -3332,6 +3336,7 @@ struct hl_device {
enum hl_asic_type   asic_type;
struct hl_cq*completion_queue;
struct hl_user_interrupt*user_interrupt;
+   struct hl_user_interrupttpc_interrupt;
struct hl_user_interruptcommon_user_cq_interrupt;
struct hl_user_interruptcommon_decoder_interrupt;
struct hl_cs**shadow_cs_queue;
diff --git a/drivers/accel/habanalabs/common/habanalabs_ioctl.c 
b/drivers/accel/habanalabs/common/habanalabs_ioctl.c
index 448cdd2501d8..100282fc82fc 100644
--- a/drivers/accel/habanalabs/common/habanalabs_ioctl.c
+++ b/drivers/accel/habanalabs/common/habanalabs_ioctl.c
@@ -102,6 +102,7 @@ static int hw_ip_info(struct hl_device *hdev, struct 
hl_info_args *args)
hw_ip.mme_master_slave_mode = prop->mme_master_slave_mode;
hw_ip.first_available_interrupt_id = 
prop->first_available_user_interrupt;
hw_ip.number_of_user_interrupts = prop->user_interrupt_count;
+   hw_ip.tpc_interrupt_id = prop->tpc_interrupt_id;
 
hw_ip.edma_enabled_mask = prop->edma_enabled_mask;
hw_ip.server_type = prop->server_type;
diff --git a/drivers/accel/habanalabs/common/irq.c 
b/drivers/accel/habanalabs/common/irq.c
index 716228291b46..bd0e3413721b 100644
--- a/drivers/accel/habanalabs/common/irq.c
+++ b/drivers/accel/habanalabs/common/irq.c
@@ -325,6 +325,21 @@ static void handle_user_interrupt(struct hl_device *hdev, 
struct hl_user_interru
}
 }
 
+static void handle_tpc_interrupt(struct hl_device *hdev)
+{
+   u64 event_mask;
+   u32 flags;
+
+   event_mask = HL_NOTIFIER_EVENT_TPC_ASSERT |
+   HL_NOTIFIER_EVENT_USER_ENGINE_ERR |
+   HL_NOTIFIER_EVENT_DEVICE_RESET;
+
+   flags = HL_DRV_RESET_DELAY;
+
+   dev_err_ratelimited(hdev->dev, "Received TPC assert\n");
+   hl_device_cond_reset(hdev, flags, event_mask);
+}
+
 /**
  * hl_irq_handler_user_interrupt - irq handler for user interrupts
  *
@@ -367,6 +382,9 @@ irqreturn_t hl_irq_user_interrupt_thread_handler(int irq, 
void *arg)
   

[PATCH 13/27] habanalabs: minimize error prints when mem map fails

2023-02-12 Thread Oded Gabbay
From: Moti Haimovski 

This commit minimizes the "chain of errors" displayed when memory
mapping fails.

Signed-off-by: Moti Haimovski 
Reviewed-by: Oded Gabbay 
Signed-off-by: Oded Gabbay 
---
 drivers/accel/habanalabs/common/memory.c | 8 ++--
 1 file changed, 2 insertions(+), 6 deletions(-)

diff --git a/drivers/accel/habanalabs/common/memory.c 
b/drivers/accel/habanalabs/common/memory.c
index 1d318d7240b7..be0cba3b61ab 100644
--- a/drivers/accel/habanalabs/common/memory.c
+++ b/drivers/accel/habanalabs/common/memory.c
@@ -235,10 +235,8 @@ static int dma_map_host_va(struct hl_device *hdev, u64 
addr, u64 size,
}
 
rc = hl_pin_host_memory(hdev, addr, size, userptr);
-   if (rc) {
-   dev_err(hdev->dev, "Failed to pin host memory\n");
+   if (rc)
goto pin_err;
-   }
 
userptr->dma_mapped = true;
userptr->dir = DMA_BIDIRECTIONAL;
@@ -1097,10 +1095,8 @@ static int map_device_va(struct hl_ctx *ctx, struct 
hl_mem_in *args, u64 *device
huge_page_size = hdev->asic_prop.pmmu_huge.page_size;
 
rc = dma_map_host_va(hdev, addr, size, );
-   if (rc) {
-   dev_err(hdev->dev, "failed to get userptr from va\n");
+   if (rc)
return rc;
-   }
 
rc = init_phys_pg_pack_from_userptr(ctx, userptr,
_pg_pack, false);
-- 
2.25.1



[PATCH 14/27] habanalabs: disable PCI when escalating compute to hard-reset

2023-02-12 Thread Oded Gabbay
From: Koby Elbaz 

In case a compute reset has failed or a request for a hard reset has
just arrived, then we escalate current reset procedure from compute
to hard-reset.
In such a case, the FW should be aware of the updated error cause,
and if LKD is the one who performs the reset (rather than the FW),
then we ask the FW to disable PCI access.

We would also like to have relevant debug info and therefore
we print the currently escalating reset type.

Signed-off-by: Koby Elbaz 
Reviewed-by: Oded Gabbay 
Signed-off-by: Oded Gabbay 
---
 drivers/accel/habanalabs/common/device.c | 16 
 1 file changed, 8 insertions(+), 8 deletions(-)

diff --git a/drivers/accel/habanalabs/common/device.c 
b/drivers/accel/habanalabs/common/device.c
index f91f3509336f..d140eaefc840 100644
--- a/drivers/accel/habanalabs/common/device.c
+++ b/drivers/accel/habanalabs/common/device.c
@@ -1452,7 +1452,7 @@ static void handle_reset_trigger(struct hl_device *hdev, 
u32 flags)
 */
if (hl_fw_send_pci_access_msg(hdev, 
CPUCP_PACKET_DISABLE_PCI_ACCESS, 0x0))
dev_warn(hdev->dev,
-   "Failed to disable PCI access by F/W\n");
+   "Failed to disable FW's PCI access\n");
}
 }
 
@@ -1530,14 +1530,14 @@ int hl_device_reset(struct hl_device *hdev, u32 flags)
 
/*
 * Prevent concurrency in this function - only one reset should be
-* done at any given time. Only need to perform this if we didn't
-* get from the dedicated hard reset thread
+* done at any given time. We need to perform this only if we didn't
+* get here from a dedicated hard reset thread.
 */
if (!from_hard_reset_thread) {
/* Block future CS/VM/JOB completion operations */
spin_lock(>reset_info.lock);
if (hdev->reset_info.in_reset) {
-   /* We only allow scheduling of a hard reset during 
compute reset */
+   /* We allow scheduling of a hard reset only during a 
compute reset */
if (hard_reset && hdev->reset_info.in_compute_reset)
hdev->reset_info.hard_reset_schedule_flags = 
flags;
spin_unlock(>reset_info.lock);
@@ -1574,6 +1574,7 @@ int hl_device_reset(struct hl_device *hdev, u32 flags)
if (delay_reset)
usleep_range(HL_RESET_DELAY_USEC, HL_RESET_DELAY_USEC 
<< 1);
 
+escalate_reset_flow:
handle_reset_trigger(hdev, flags);
 
/* This also blocks future CS/VM/JOB completion operations */
@@ -1589,7 +1590,6 @@ int hl_device_reset(struct hl_device *hdev, u32 flags)
dev_dbg(hdev->dev, "Going to reset engines of inference 
device\n");
}
 
-again:
if ((hard_reset) && (!from_hard_reset_thread)) {
hdev->reset_info.hard_reset_pending = true;
 
@@ -1837,7 +1837,7 @@ int hl_device_reset(struct hl_device *hdev, u32 flags)
hdev->disabled = true;
hard_reset = true;
handle_reset_trigger(hdev, flags);
-   goto again;
+   goto escalate_reset_flow;
}
}
 
@@ -1860,14 +1860,14 @@ int hl_device_reset(struct hl_device *hdev, u32 flags)
flags |= HL_DRV_RESET_HARD;
flags &= ~HL_DRV_RESET_DEV_RELEASE;
hard_reset = true;
-   goto again;
+   goto escalate_reset_flow;
} else {
spin_unlock(>reset_info.lock);
dev_err(hdev->dev, "Failed to do compute reset\n");
hdev->reset_info.compute_reset_cnt++;
flags |= HL_DRV_RESET_HARD;
hard_reset = true;
-   goto again;
+   goto escalate_reset_flow;
}
 
hdev->reset_info.in_reset = 0;
-- 
2.25.1



[PATCH 12/27] habanalabs/gaudi2: unsecure CFG_TPC_ID register

2023-02-12 Thread Oded Gabbay
From: Koby Elbaz 

Required to allow the TPC compiler to know on which offset of the index
space it works on.

Signed-off-by: Koby Elbaz 
Reviewed-by: Oded Gabbay 
Signed-off-by: Oded Gabbay 
---
 drivers/accel/habanalabs/gaudi2/gaudi2_security.c | 1 +
 1 file changed, 1 insertion(+)

diff --git a/drivers/accel/habanalabs/gaudi2/gaudi2_security.c 
b/drivers/accel/habanalabs/gaudi2/gaudi2_security.c
index a212f82e6604..694735f9e6e6 100644
--- a/drivers/accel/habanalabs/gaudi2/gaudi2_security.c
+++ b/drivers/accel/habanalabs/gaudi2/gaudi2_security.c
@@ -1595,6 +1595,7 @@ static const u32 gaudi2_pb_dcr0_tpc0_unsecured_regs[] = {
mmDCORE0_TPC0_CFG_KERNEL_SRF_30,
mmDCORE0_TPC0_CFG_KERNEL_SRF_31,
mmDCORE0_TPC0_CFG_TPC_SB_L0CD,
+   mmDCORE0_TPC0_CFG_TPC_ID,
mmDCORE0_TPC0_CFG_QM_KERNEL_ID_INC,
mmDCORE0_TPC0_CFG_QM_TID_BASE_SIZE_HIGH_DIM_0,
mmDCORE0_TPC0_CFG_QM_TID_BASE_SIZE_HIGH_DIM_1,
-- 
2.25.1



[PATCH 09/27] habanalabs: enforce release order of compute device and dma-buf

2023-02-12 Thread Oded Gabbay
From: Tomer Tayar 

When user closes the compute device file descriptor without closing a
dma-buf file descriptor, the device will be considered as in use,
leading to hard reset and killing the user process, to ensure the
release of the dma-buf.
Same thing will happen if user first releases the compute device file
and only then the dma-buf.

The implication of this is the duration of hard reset, during which the
device cannot be reacquired.
Moreover, this behavior adds a constraint on a user process to follow
this order of release operations.

To avoid killing the user process and to remove this constraint, enforce
the correct order of release operations inside the driver, by
incrementing the device file refcount for any dma-buf until it is
released.

Signed-off-by: Tomer Tayar 
Reviewed-by: Oded Gabbay 
Signed-off-by: Oded Gabbay 
---
 drivers/accel/habanalabs/common/memory.c | 10 ++
 1 file changed, 10 insertions(+)

diff --git a/drivers/accel/habanalabs/common/memory.c 
b/drivers/accel/habanalabs/common/memory.c
index e115d264b03b..1d318d7240b7 100644
--- a/drivers/accel/habanalabs/common/memory.c
+++ b/drivers/accel/habanalabs/common/memory.c
@@ -1835,6 +1835,10 @@ static void hl_release_dmabuf(struct dma_buf *dmabuf)
 
atomic_dec(>hdev->dmabuf_export_cnt);
hl_ctx_put(ctx);
+
+   /* Paired with get_file() in export_dmabuf() */
+   fput(ctx->hpriv->filp);
+
kfree(hl_dmabuf);
 }
 
@@ -1875,6 +1879,12 @@ static int export_dmabuf(struct hl_ctx *ctx,
hl_ctx_get(hl_dmabuf->ctx);
atomic_inc(>hdev->dmabuf_export_cnt);
 
+   /* Get compute device file to enforce release order, such that all 
exported dma-buf will be
+* released first and only then the compute device.
+* Paired with fput() in hl_release_dmabuf().
+*/
+   get_file(ctx->hpriv->filp);
+
*dmabuf_fd = fd;
 
return 0;
-- 
2.25.1



[PATCH 15/27] habanalabs: enable graceful reset mechanism for compute-reset

2023-02-12 Thread Oded Gabbay
From: Tomer Tayar 

The graceful reset mechanism is currently enabled only for reset
requests that will end up with hard-reset.
In future, reset requests due to errors in some device engines, are
going to be modified to request compute-reset, as the much longer
hard-reset is not really needed there.
To allow it, enable graceful reset also for compute-reset, and reset
after user releases the device won't be escalated to hard-reset in those
cases.
If watchdog expires and user didn't release the device, hard-reset will
be initiated in any case.

Signed-off-by: Tomer Tayar 
Reviewed-by: Oded Gabbay 
Signed-off-by: Oded Gabbay 
---
 drivers/accel/habanalabs/common/device.c | 26 +++-
 1 file changed, 12 insertions(+), 14 deletions(-)

diff --git a/drivers/accel/habanalabs/common/device.c 
b/drivers/accel/habanalabs/common/device.c
index d140eaefc840..2d496cd935b2 100644
--- a/drivers/accel/habanalabs/common/device.c
+++ b/drivers/accel/habanalabs/common/device.c
@@ -778,14 +778,14 @@ static void device_hard_reset_pending(struct work_struct 
*work)
 
 static void device_release_watchdog_func(struct work_struct *work)
 {
-   struct hl_device_reset_work *device_release_watchdog_work =
-   container_of(work, struct hl_device_reset_work, 
reset_work.work);
-   struct hl_device *hdev = device_release_watchdog_work->hdev;
+   struct hl_device_reset_work *watchdog_work =
+   container_of(work, struct hl_device_reset_work, 
reset_work.work);
+   struct hl_device *hdev = watchdog_work->hdev;
u32 flags;
 
-   dev_dbg(hdev->dev, "Device wasn't released in time. Initiate device 
reset.\n");
+   dev_dbg(hdev->dev, "Device wasn't released in time. Initiate 
hard-reset.\n");
 
-   flags = device_release_watchdog_work->flags | HL_DRV_RESET_FROM_WD_THR;
+   flags = watchdog_work->flags | HL_DRV_RESET_HARD | 
HL_DRV_RESET_FROM_WD_THR;
 
hl_device_reset(hdev, flags);
 }
@@ -1555,15 +1555,17 @@ int hl_device_reset(struct hl_device *hdev, u32 flags)
 
/* Cancel the device release watchdog work if required.
 * In case of reset-upon-device-release while the release 
watchdog work is
-* scheduled, do hard-reset instead of compute-reset.
+* scheduled due to a hard-reset, do hard-reset instead of 
compute-reset.
 */
if ((hard_reset || from_dev_release) && 
hdev->reset_info.watchdog_active) {
+   struct hl_device_reset_work *watchdog_work =
+   >device_release_watchdog_work;
+
hdev->reset_info.watchdog_active = 0;
if (!from_watchdog_thread)
-   cancel_delayed_work_sync(
-   
>device_release_watchdog_work.reset_work);
+   
cancel_delayed_work_sync(_work->reset_work);
 
-   if (from_dev_release) {
+   if (from_dev_release && (watchdog_work->flags & 
HL_DRV_RESET_HARD)) {
hdev->reset_info.in_compute_reset = 0;
flags |= HL_DRV_RESET_HARD;
flags &= ~HL_DRV_RESET_DEV_RELEASE;
@@ -1890,10 +1892,6 @@ int hl_device_cond_reset(struct hl_device *hdev, u32 
flags, u64 event_mask)
 {
struct hl_ctx *ctx = NULL;
 
-   /* Device release watchdog is only for hard reset */
-   if (!(flags & HL_DRV_RESET_HARD) && 
hdev->asic_prop.allow_inference_soft_reset)
-   goto device_reset;
-
/* F/W reset cannot be postponed */
if (flags & HL_DRV_RESET_BYPASS_REQ_TO_FW)
goto device_reset;
@@ -1921,7 +1919,7 @@ int hl_device_cond_reset(struct hl_device *hdev, u32 
flags, u64 event_mask)
goto out;
 
hdev->device_release_watchdog_work.flags = flags;
-   dev_dbg(hdev->dev, "Device is going to be reset in %u sec unless being 
released\n",
+   dev_dbg(hdev->dev, "Device is going to be hard-reset in %u sec unless 
being released\n",
hdev->device_release_watchdog_timeout_sec);
schedule_delayed_work(>device_release_watchdog_work.reset_work,

msecs_to_jiffies(hdev->device_release_watchdog_timeout_sec * 1000));
-- 
2.25.1



[PATCH 08/27] habanalabs: add info when FD released while device still in use

2023-02-12 Thread Oded Gabbay
From: Tomer Tayar 

When user closes the device file descriptor, it is checked whether the
device is still in use, and a message is printed if it is.
To make this message more informative, add to this print also the reason
due to which the device is considered as in use.
The possible reasons which are checked for now are active CS and
exported dma-buf.

Signed-off-by: Tomer Tayar 
Reviewed-by: Oded Gabbay 
Signed-off-by: Oded Gabbay 
---
 .../habanalabs/common/command_submission.c| 16 ++
 drivers/accel/habanalabs/common/device.c  | 51 +--
 drivers/accel/habanalabs/common/habanalabs.h  |  4 +-
 drivers/accel/habanalabs/common/memory.c  |  2 +
 4 files changed, 69 insertions(+), 4 deletions(-)

diff --git a/drivers/accel/habanalabs/common/command_submission.c 
b/drivers/accel/habanalabs/common/command_submission.c
index e313ff8af7cc..24f3d82ee4cb 100644
--- a/drivers/accel/habanalabs/common/command_submission.c
+++ b/drivers/accel/habanalabs/common/command_submission.c
@@ -1168,6 +1168,22 @@ static void cs_completion(struct work_struct *work)
hl_complete_job(hdev, job);
 }
 
+u32 hl_get_active_cs_num(struct hl_device *hdev)
+{
+   u32 active_cs_num = 0;
+   struct hl_cs *cs;
+
+   spin_lock(>cs_mirror_lock);
+
+   list_for_each_entry(cs, >cs_mirror_list, mirror_node)
+   if (!cs->completed)
+   active_cs_num++;
+
+   spin_unlock(>cs_mirror_lock);
+
+   return active_cs_num;
+}
+
 static int validate_queue_index(struct hl_device *hdev,
struct hl_cs_chunk *chunk,
enum hl_queue_type *queue_type,
diff --git a/drivers/accel/habanalabs/common/device.c 
b/drivers/accel/habanalabs/common/device.c
index 194c282d7e55..b8c74185eabd 100644
--- a/drivers/accel/habanalabs/common/device.c
+++ b/drivers/accel/habanalabs/common/device.c
@@ -492,6 +492,52 @@ int hl_hpriv_put(struct hl_fpriv *hpriv)
return kref_put(>refcount, hpriv_release);
 }
 
+static void compose_device_in_use_info(char **buf, size_t *buf_size, const 
char *fmt, ...)
+{
+   struct va_format vaf;
+   va_list args;
+   int size;
+
+   va_start(args, fmt);
+   vaf.fmt = fmt;
+   vaf.va = 
+
+   size = snprintf(*buf, *buf_size, "%pV", );
+   if (size >= *buf_size)
+   size = *buf_size;
+
+   *buf += size;
+   *buf_size -= size;
+
+   va_end(args);
+}
+
+static void print_device_in_use_info(struct hl_device *hdev, const char 
*message)
+{
+   u32 active_cs_num, dmabuf_export_cnt;
+   char buf[64], *buf_ptr = buf;
+   size_t buf_size = sizeof(buf);
+   bool unknown_reason = true;
+
+   active_cs_num = hl_get_active_cs_num(hdev);
+   if (active_cs_num) {
+   unknown_reason = false;
+   compose_device_in_use_info(_ptr, _size, " [%u active 
CS]", active_cs_num);
+   }
+
+   dmabuf_export_cnt = atomic_read(>dmabuf_export_cnt);
+   if (dmabuf_export_cnt) {
+   unknown_reason = false;
+   compose_device_in_use_info(_ptr, _size, " [%u exported 
dma-buf]",
+   dmabuf_export_cnt);
+   }
+
+   if (unknown_reason)
+   compose_device_in_use_info(_ptr, _size, " [unknown 
reason]");
+
+   dev_notice(hdev->dev, "%s%s\n", message, buf);
+}
+
 /*
  * hl_device_release - release function for habanalabs device
  *
@@ -519,12 +565,11 @@ static int hl_device_release(struct inode *inode, struct 
file *filp)
hdev->compute_ctx_in_release = 1;
 
if (!hl_hpriv_put(hpriv)) {
-   dev_notice(hdev->dev, "User process closed FD but device still 
in use\n");
+   print_device_in_use_info(hdev, "User process closed FD but 
device still in use");
hl_device_reset(hdev, HL_DRV_RESET_HARD);
}
 
-   hdev->last_open_session_duration_jif =
-   jiffies - hdev->last_successful_open_jif;
+   hdev->last_open_session_duration_jif = jiffies - 
hdev->last_successful_open_jif;
 
return 0;
 }
diff --git a/drivers/accel/habanalabs/common/habanalabs.h 
b/drivers/accel/habanalabs/common/habanalabs.h
index d98e6c0feb24..afdae5775eaa 100644
--- a/drivers/accel/habanalabs/common/habanalabs.h
+++ b/drivers/accel/habanalabs/common/habanalabs.h
@@ -3200,6 +3200,7 @@ struct hl_reset_info {
  *drams are binned-out
  * @tpc_binning: contains mask of tpc engines that is received from the f/w 
which indicates which
  *   tpc engines are binned-out
+ * @dmabuf_export_cnt: number of dma-buf exporting.
  * @card_type: Various ASICs have several card types. This indicates the card
  * type of the current device.
  * @major: habanalabs kernel driver major.
@@ -3371,7 +3372,7 @@ struct hl_device {
u64 fw_comms_poll_interval_usec;
u64 dram_binning;
  

[PATCH 10/27] habanalabs: add critical-event bit in notifier

2023-02-12 Thread Oded Gabbay
From: Moti Haimovski 

Enhance the existing user notifications by adding a HW and FW critical
event bits to be used when a HW or FW event occur that requires
both SW abort and hard-resetting the chip.

Signed-off-by: Moti Haimovski 
Reviewed-by: Oded Gabbay 
Signed-off-by: Oded Gabbay 
---
 drivers/accel/habanalabs/common/device.c  | 53 +-
 drivers/accel/habanalabs/common/habanalabs.h  | 54 +++
 .../accel/habanalabs/common/habanalabs_drv.c  |  5 +-
 .../habanalabs/common/habanalabs_ioctl.c  | 50 +
 drivers/accel/habanalabs/gaudi/gaudi.c| 10 +++-
 drivers/accel/habanalabs/gaudi2/gaudi2.c  |  4 ++
 include/uapi/drm/habanalabs_accel.h   | 43 +++
 7 files changed, 213 insertions(+), 6 deletions(-)

diff --git a/drivers/accel/habanalabs/common/device.c 
b/drivers/accel/habanalabs/common/device.c
index b8c74185eabd..f91f3509336f 100644
--- a/drivers/accel/habanalabs/common/device.c
+++ b/drivers/accel/habanalabs/common/device.c
@@ -998,6 +998,8 @@ static void hl_device_heartbeat(struct work_struct *work)
 {
struct hl_device *hdev = container_of(work, struct hl_device,
work_heartbeat.work);
+   struct hl_info_fw_err_info info = {0};
+   u64 event_mask = HL_NOTIFIER_EVENT_DEVICE_RESET | 
HL_NOTIFIER_EVENT_DEVICE_UNAVAILABLE;
 
if (!hl_device_operational(hdev, NULL))
goto reschedule;
@@ -1008,7 +1010,10 @@ static void hl_device_heartbeat(struct work_struct *work)
if (hl_device_operational(hdev, NULL))
dev_err(hdev->dev, "Device heartbeat failed!\n");
 
-   hl_device_reset(hdev, HL_DRV_RESET_HARD | HL_DRV_RESET_HEARTBEAT);
+   info.err_type = HL_INFO_FW_HEARTBEAT_ERR;
+   info.event_mask = _mask;
+   hl_handle_fw_err(hdev, );
+   hl_device_cond_reset(hdev, HL_DRV_RESET_HARD | HL_DRV_RESET_HEARTBEAT, 
event_mask);
 
return;
 
@@ -2626,3 +2631,49 @@ void hl_handle_page_fault(struct hl_device *hdev, u64 
addr, u16 eng_id, bool is_
if (event_mask)
*event_mask |=  HL_NOTIFIER_EVENT_PAGE_FAULT;
 }
+
+void hl_capture_hw_err(struct hl_device *hdev, u16 event_id)
+{
+   struct hw_err_info *info = >captured_err_info.hw_err;
+
+   /* Capture only the first HW err */
+   if (atomic_cmpxchg(>event_detected, 0, 1))
+   return;
+
+   info->event.timestamp = ktime_to_ns(ktime_get());
+   info->event.event_id = event_id;
+
+   info->event_info_available = true;
+}
+
+void hl_handle_critical_hw_err(struct hl_device *hdev, u16 event_id, u64 
*event_mask)
+{
+   hl_capture_hw_err(hdev, event_id);
+
+   if (event_mask)
+   *event_mask |= HL_NOTIFIER_EVENT_CRITICL_HW_ERR;
+}
+
+void hl_capture_fw_err(struct hl_device *hdev, struct hl_info_fw_err_info 
*fw_info)
+{
+   struct fw_err_info *info = >captured_err_info.fw_err;
+
+   /* Capture only the first FW error */
+   if (atomic_cmpxchg(>event_detected, 0, 1))
+   return;
+
+   info->event.timestamp = ktime_to_ns(ktime_get());
+   info->event.err_type = fw_info->err_type;
+   if (fw_info->err_type == HL_INFO_FW_REPORTED_ERR)
+   info->event.event_id = fw_info->event_id;
+
+   info->event_info_available = true;
+}
+
+void hl_handle_fw_err(struct hl_device *hdev, struct hl_info_fw_err_info *info)
+{
+   hl_capture_fw_err(hdev, info);
+
+   if (info->event_mask)
+   *info->event_mask |= HL_NOTIFIER_EVENT_CRITICL_FW_ERR;
+}
diff --git a/drivers/accel/habanalabs/common/habanalabs.h 
b/drivers/accel/habanalabs/common/habanalabs.h
index afdae5775eaa..176a2e2c050d 100644
--- a/drivers/accel/habanalabs/common/habanalabs.h
+++ b/drivers/accel/habanalabs/common/habanalabs.h
@@ -3031,18 +3031,56 @@ struct razwi_info {
boolrazwi_info_available;
 };
 
+/**
+ * struct hw_err_info - HW error information.
+ * @event: holds information on the event.
+ * @event_detected: if set as 1, then a HW event was discovered for the
+ *  first time after the driver has finished booting-up.
+ *  currently we assume that only fatal events (that require 
hard-reset) are
+ *  reported so we don't care of the others that might follow 
it.
+ *  so once changed to 1, it will remain that way.
+ *  TODO: support multiple events.
+ * @event_info_available: indicates that a HW event info is now available.
+ */
+struct hw_err_info {
+   struct hl_info_hw_err_event event;
+   atomic_tevent_detected;
+   boolevent_info_available;
+};
+
+/**
+ * struct fw_err_info - FW error information.
+ * @event: holds information on the event.
+ * @event_detected: if set as 1, then a FW event was discovered for the
+ *  first time after the driver has finished booting-up.
+ 

[PATCH 11/27] habanalabs/gaudi2: expose engine core int reg address

2023-02-12 Thread Oded Gabbay
From: Ofir Bitton 

In order for engine cores to raise interrupts towards FW, They need
to know which register the event data should be written to.
Hence, we forward the relevant scratchpad register received during
dynamic regs handshake with FW.

Signed-off-by: Ofir Bitton 
Reviewed-by: Oded Gabbay 
Signed-off-by: Oded Gabbay 
---
 drivers/accel/habanalabs/common/habanalabs.h   | 3 +++
 drivers/accel/habanalabs/common/habanalabs_ioctl.c | 1 +
 drivers/accel/habanalabs/gaudi2/gaudi2.c   | 5 +
 include/uapi/drm/habanalabs_accel.h| 5 +
 4 files changed, 14 insertions(+)

diff --git a/drivers/accel/habanalabs/common/habanalabs.h 
b/drivers/accel/habanalabs/common/habanalabs.h
index 176a2e2c050d..bf81eda88e2e 100644
--- a/drivers/accel/habanalabs/common/habanalabs.h
+++ b/drivers/accel/habanalabs/common/habanalabs.h
@@ -592,6 +592,8 @@ struct hl_hints_range {
  * @host_base_address: host physical start address for host DMA from device
  * @host_end_address: host physical end address for host DMA from device
  * @max_freq_value: current max clk frequency.
+ * @engine_core_interrupt_reg_addr: interrupt register address for engine core 
to use
+ *  in order to raise events toward FW.
  * @clk_pll_index: clock PLL index that specify which PLL determines the clock
  * we display to the user
  * @mmu_pgt_size: MMU page tables total size.
@@ -739,6 +741,7 @@ struct asic_fixed_properties {
u64 host_base_address;
u64 host_end_address;
u64 max_freq_value;
+   u64 engine_core_interrupt_reg_addr;
u32 clk_pll_index;
u32 mmu_pgt_size;
u32 mmu_pte_size;
diff --git a/drivers/accel/habanalabs/common/habanalabs_ioctl.c 
b/drivers/accel/habanalabs/common/habanalabs_ioctl.c
index 13cd5013c72a..448cdd2501d8 100644
--- a/drivers/accel/habanalabs/common/habanalabs_ioctl.c
+++ b/drivers/accel/habanalabs/common/habanalabs_ioctl.c
@@ -107,6 +107,7 @@ static int hw_ip_info(struct hl_device *hdev, struct 
hl_info_args *args)
hw_ip.server_type = prop->server_type;
hw_ip.security_enabled = prop->fw_security_enabled;
hw_ip.revision_id = hdev->pdev->revision;
+   hw_ip.engine_core_interrupt_reg_addr = 
prop->engine_core_interrupt_reg_addr;
 
return copy_to_user(out, _ip,
min((size_t) size, sizeof(hw_ip))) ? -EFAULT : 0;
diff --git a/drivers/accel/habanalabs/gaudi2/gaudi2.c 
b/drivers/accel/habanalabs/gaudi2/gaudi2.c
index 9b41eb3f1380..405d0d37efe5 100644
--- a/drivers/accel/habanalabs/gaudi2/gaudi2.c
+++ b/drivers/accel/habanalabs/gaudi2/gaudi2.c
@@ -2933,6 +2933,7 @@ static bool gaudi2_is_arc_tpc_owned(u64 arc_id)
 
 static void gaudi2_init_arcs(struct hl_device *hdev)
 {
+   struct cpu_dyn_regs *dyn_regs = 
>fw_loader.dynamic_loader.comm_desc.cpu_dyn_regs;
struct gaudi2_device *gaudi2 = hdev->asic_specific;
u64 arc_id;
u32 i;
@@ -2962,6 +2963,10 @@ static void gaudi2_init_arcs(struct hl_device *hdev)
 
gaudi2_set_arc_id_cap(hdev, arc_id);
}
+
+   /* Fetch ARC scratchpad address */
+   hdev->asic_prop.engine_core_interrupt_reg_addr =
+   CFG_BASE + le32_to_cpu(dyn_regs->eng_arc_irq_ctrl);
 }
 
 static int gaudi2_scrub_arc_dccm(struct hl_device *hdev, u32 cpu_id)
diff --git a/include/uapi/drm/habanalabs_accel.h 
b/include/uapi/drm/habanalabs_accel.h
index 3a62652a6452..c1fdbb85d1d5 100644
--- a/include/uapi/drm/habanalabs_accel.h
+++ b/include/uapi/drm/habanalabs_accel.h
@@ -885,6 +885,8 @@ enum hl_server_type {
  * application to use. Relevant for Gaudi2 and 
later.
  * @device_mem_alloc_default_page_size: default page size used in device 
memory allocation.
  * @revision_id: PCI revision ID of the ASIC.
+ * @engine_core_interrupt_reg_addr: interrupt register address for engine core 
to use
+ *  in order to raise events toward FW.
  */
 struct hl_info_hw_ip_info {
__u64 sram_base_address;
@@ -921,6 +923,9 @@ struct hl_info_hw_ip_info {
__u8 reserved8;
__u8 revision_id;
__u8 pad[2];
+   __u32 reserved9;
+   __u8 pad3[4];
+   __u64 engine_core_interrupt_reg_addr;
 };
 
 struct hl_info_dram_usage {
-- 
2.25.1



[PATCH 07/27] habanalabs/gaudi2: fix address decode RAZWI handling

2023-02-12 Thread Oded Gabbay
From: Dani Liberman 

PSOC RAZWI handling code did not took into account single router that
supports several initiators with different XY coordinates. Also, it
ignored XY_HI coordinate. This caused 2 problems:
1. RAZWI handle ignored some initiators.
2. When getting PSOC RAZWI from some routers, there was a lot of
   possible engines which could have caused the RAZWI.

Fixed the above issue by handling PSOC RAZWI with both low and high
XY coordinates. This way driver supports all initiators and in
the worst case there are not more than 2 possible engines for RAZWI.

Signed-off-by: Dani Liberman 
Reviewed-by: Oded Gabbay 
Signed-off-by: Oded Gabbay 
---
 drivers/accel/habanalabs/gaudi2/gaudi2.c | 724 ---
 1 file changed, 371 insertions(+), 353 deletions(-)

diff --git a/drivers/accel/habanalabs/gaudi2/gaudi2.c 
b/drivers/accel/habanalabs/gaudi2/gaudi2.c
index f1f2a58ee68c..af8fe3575aa9 100644
--- a/drivers/accel/habanalabs/gaudi2/gaudi2.c
+++ b/drivers/accel/habanalabs/gaudi2/gaudi2.c
@@ -132,6 +132,282 @@
 
 #define ENGINE_ID_DCORE_OFFSET (GAUDI2_DCORE1_ENGINE_ID_EDMA_0 - 
GAUDI2_DCORE0_ENGINE_ID_EDMA_0)
 
+/* RAZWI initiator coordinates */
+#define RAZWI_GET_AXUSER_XY(x) \
+   ((x & 0xF8001FF0) >> 4)
+
+#define RAZWI_GET_AXUSER_LOW_XY(x) \
+   ((x & 0x1FF0) >> 4)
+
+#define RAZWI_INITIATOR_AXUER_L_X_SHIFT0
+#define RAZWI_INITIATOR_AXUER_L_X_MASK 0x1F
+#define RAZWI_INITIATOR_AXUER_L_Y_SHIFT5
+#define RAZWI_INITIATOR_AXUER_L_Y_MASK 0xF
+
+#define RAZWI_INITIATOR_AXUER_H_X_SHIFT23
+#define RAZWI_INITIATOR_AXUER_H_X_MASK 0x1F
+
+#define RAZWI_INITIATOR_ID_X_Y_LOW(x, y) \
+   y) & RAZWI_INITIATOR_AXUER_L_Y_MASK) << 
RAZWI_INITIATOR_AXUER_L_Y_SHIFT) | \
+   (((x) & RAZWI_INITIATOR_AXUER_L_X_MASK) << 
RAZWI_INITIATOR_AXUER_L_X_SHIFT))
+
+#define RAZWI_INITIATOR_ID_X_HIGH(x) \
+   (((x) & RAZWI_INITIATOR_AXUER_H_X_MASK) << 
RAZWI_INITIATOR_AXUER_H_X_SHIFT)
+
+#define RAZWI_INITIATOR_ID_X_Y(xl, yl, xh) \
+   (RAZWI_INITIATOR_ID_X_Y_LOW(xl, yl) | RAZWI_INITIATOR_ID_X_HIGH(xh))
+
+#define PSOC_RAZWI_ENG_STR_SIZE 128
+#define PSOC_RAZWI_MAX_ENG_PER_RTR 5
+
+struct gaudi2_razwi_info {
+   u32 axuser_xy;
+   u32 rtr_ctrl;
+   u16 eng_id;
+   char *eng_name;
+};
+
+static struct gaudi2_razwi_info common_razwi_info[] = {
+   {RAZWI_INITIATOR_ID_X_Y(2, 4, 0), mmDCORE0_RTR0_CTRL_BASE,
+   GAUDI2_DCORE0_ENGINE_ID_DEC_0, "DEC0"},
+   {RAZWI_INITIATOR_ID_X_Y(2, 4, 4), mmDCORE0_RTR0_CTRL_BASE,
+   GAUDI2_DCORE0_ENGINE_ID_DEC_1, "DEC1"},
+   {RAZWI_INITIATOR_ID_X_Y(17, 4, 18), mmDCORE1_RTR7_CTRL_BASE,
+   GAUDI2_DCORE1_ENGINE_ID_DEC_0, "DEC2"},
+   {RAZWI_INITIATOR_ID_X_Y(17, 4, 14), mmDCORE1_RTR7_CTRL_BASE,
+   GAUDI2_DCORE1_ENGINE_ID_DEC_1, "DEC3"},
+   {RAZWI_INITIATOR_ID_X_Y(2, 11, 0), mmDCORE2_RTR0_CTRL_BASE,
+   GAUDI2_DCORE2_ENGINE_ID_DEC_0, "DEC4"},
+   {RAZWI_INITIATOR_ID_X_Y(2, 11, 4), mmDCORE2_RTR0_CTRL_BASE,
+   GAUDI2_DCORE2_ENGINE_ID_DEC_1, "DEC5"},
+   {RAZWI_INITIATOR_ID_X_Y(17, 11, 18), mmDCORE3_RTR7_CTRL_BASE,
+   GAUDI2_DCORE3_ENGINE_ID_DEC_0, "DEC6"},
+   {RAZWI_INITIATOR_ID_X_Y(17, 11, 14), mmDCORE3_RTR7_CTRL_BASE,
+   GAUDI2_DCORE3_ENGINE_ID_DEC_1, "DEC7"},
+   {RAZWI_INITIATOR_ID_X_Y(2, 4, 6), mmDCORE0_RTR0_CTRL_BASE,
+   GAUDI2_PCIE_ENGINE_ID_DEC_0, "DEC8"},
+   {RAZWI_INITIATOR_ID_X_Y(2, 4, 7), mmDCORE0_RTR0_CTRL_BASE,
+   GAUDI2_PCIE_ENGINE_ID_DEC_0, "DEC9"},
+   {RAZWI_INITIATOR_ID_X_Y(3, 4, 2), mmDCORE0_RTR1_CTRL_BASE,
+   GAUDI2_DCORE0_ENGINE_ID_TPC_0, "TPC0"},
+   {RAZWI_INITIATOR_ID_X_Y(3, 4, 4), mmDCORE0_RTR1_CTRL_BASE,
+   GAUDI2_DCORE0_ENGINE_ID_TPC_1, "TPC1"},
+   {RAZWI_INITIATOR_ID_X_Y(4, 4, 2), mmDCORE0_RTR2_CTRL_BASE,
+   GAUDI2_DCORE0_ENGINE_ID_TPC_2, "TPC2"},
+   {RAZWI_INITIATOR_ID_X_Y(4, 4, 4), mmDCORE0_RTR2_CTRL_BASE,
+   GAUDI2_DCORE0_ENGINE_ID_TPC_3, "TPC3"},
+   {RAZWI_INITIATOR_ID_X_Y(5, 4, 2), mmDCORE0_RTR3_CTRL_BASE,
+   GAUDI2_DCORE0_ENGINE_ID_TPC_4, "TPC4"},
+   {RAZWI_INITIATOR_ID_X_Y(5, 4, 4), mmDCORE0_RTR3_CTRL_BASE,
+   GAUDI2_DCORE0_ENGINE_ID_TPC_5, "TPC5"},
+   {RAZWI_INITIATOR_ID_X_Y(16, 4, 14), mmDCORE1_RTR6_CTRL_BASE,
+   GAUDI2_DCORE1_ENGINE_ID_TPC_0, "TPC6"},
+   {RAZWI_INITIATOR_ID_X_Y(16, 4, 16), mmDCORE1_RTR6_CTRL_BASE,
+ 

[PATCH 04/27] habanalabs: save class in hdev

2023-02-12 Thread Oded Gabbay
It is more concise than to pass it to device init. Once we will add the
accel class, then we won't need to change the function signatures.

Signed-off-by: Oded Gabbay 
---
 drivers/accel/habanalabs/common/device.c | 16 
 drivers/accel/habanalabs/common/habanalabs.h |  4 +++-
 drivers/accel/habanalabs/common/habanalabs_drv.c |  3 ++-
 3 files changed, 13 insertions(+), 10 deletions(-)

diff --git a/drivers/accel/habanalabs/common/device.c 
b/drivers/accel/habanalabs/common/device.c
index ed26b7d20d19..194c282d7e55 100644
--- a/drivers/accel/habanalabs/common/device.c
+++ b/drivers/accel/habanalabs/common/device.c
@@ -617,7 +617,7 @@ static void device_release_func(struct device *dev)
  * device_init_cdev - Initialize cdev and device for habanalabs device
  *
  * @hdev: pointer to habanalabs device structure
- * @hclass: pointer to the class object of the device
+ * @class: pointer to the class object of the device
  * @minor: minor number of the specific device
  * @fpos: file operations to install for this device
  * @name: name of the device as it will appear in the filesystem
@@ -626,7 +626,7 @@ static void device_release_func(struct device *dev)
  *
  * Initialize a cdev and a Linux device for habanalabs's device.
  */
-static int device_init_cdev(struct hl_device *hdev, struct class *hclass,
+static int device_init_cdev(struct hl_device *hdev, struct class *class,
int minor, const struct file_operations *fops,
char *name, struct cdev *cdev,
struct device **dev)
@@ -640,7 +640,7 @@ static int device_init_cdev(struct hl_device *hdev, struct 
class *hclass,
 
device_initialize(*dev);
(*dev)->devt = MKDEV(hdev->major, minor);
-   (*dev)->class = hclass;
+   (*dev)->class = class;
(*dev)->release = device_release_func;
dev_set_drvdata(*dev, hdev);
dev_set_name(*dev, "%s", name);
@@ -1939,7 +1939,7 @@ void hl_notifier_event_send_all(struct hl_device *hdev, 
u64 event_mask)
mutex_unlock(>fpriv_ctrl_list_lock);
 }
 
-static int create_cdev(struct hl_device *hdev, struct class *hclass)
+static int create_cdev(struct hl_device *hdev)
 {
char *name;
int rc;
@@ -1953,7 +1953,7 @@ static int create_cdev(struct hl_device *hdev, struct 
class *hclass)
}
 
/* Initialize cdev and device structures */
-   rc = device_init_cdev(hdev, hclass, hdev->id, _ops, name,
+   rc = device_init_cdev(hdev, hdev->hclass, hdev->id, _ops, name,
>cdev, >dev);
 
kfree(name);
@@ -1968,7 +1968,7 @@ static int create_cdev(struct hl_device *hdev, struct 
class *hclass)
}
 
/* Initialize cdev and device structures for control device */
-   rc = device_init_cdev(hdev, hclass, hdev->id_control, _ctrl_ops,
+   rc = device_init_cdev(hdev, hdev->hclass, hdev->id_control, 
_ctrl_ops,
name, >cdev_ctrl, >dev_ctrl);
 
kfree(name);
@@ -1993,12 +1993,12 @@ static int create_cdev(struct hl_device *hdev, struct 
class *hclass)
  * ASIC specific initialization functions. Finally, create the cdev and the
  * Linux device to expose it to the user
  */
-int hl_device_init(struct hl_device *hdev, struct class *hclass)
+int hl_device_init(struct hl_device *hdev)
 {
int i, rc, cq_cnt, user_interrupt_cnt, cq_ready_cnt;
bool add_cdev_sysfs_on_err = false;
 
-   rc = create_cdev(hdev, hclass);
+   rc = create_cdev(hdev);
if (rc)
goto out_disabled;
 
diff --git a/drivers/accel/habanalabs/common/habanalabs.h 
b/drivers/accel/habanalabs/common/habanalabs.h
index fa05e76d3d21..d98e6c0feb24 100644
--- a/drivers/accel/habanalabs/common/habanalabs.h
+++ b/drivers/accel/habanalabs/common/habanalabs.h
@@ -3090,6 +3090,7 @@ struct hl_reset_info {
  *(required only for PCI address match mode)
  * @pcie_bar: array of available PCIe bars virtual addresses.
  * @rmmio: configuration area address on SRAM.
+ * @hclass: pointer to the habanalabs class.
  * @cdev: related char device.
  * @cdev_ctrl: char device for control operations only (INFO IOCTL)
  * @dev: related kernel basic device structure.
@@ -3274,6 +3275,7 @@ struct hl_device {
u64 pcie_bar_phys[HL_PCI_NUM_BARS];
void __iomem*pcie_bar[HL_PCI_NUM_BARS];
void __iomem*rmmio;
+   struct class*hclass;
struct cdev cdev;
struct cdev cdev_ctrl;
struct device   *dev;
@@ -3612,7 +3614,7 @@ int hl_ctx_get_fences(struct hl_ctx *ctx, u64 *seq_arr,
 void hl_ctx_mgr_init(struct hl_ctx_mgr *mgr);
 void hl_ctx_mgr_fini(struct hl_device *hdev, struct hl_ctx_mgr *mgr);
 
-int hl_device_init(struct hl_device *hdev, struct class *hclass);
+int hl_device_init(struct 

[PATCH 06/27] habanalabs: use memhash_node_export_put() in hl_release_dmabuf()

2023-02-12 Thread Oded Gabbay
From: Tomer Tayar 

The same mutex lock/unlock and counter decrementing in
hl_release_dmabuf() is already done in the memhash_node_export_put()
helper function.

Signed-off-by: Tomer Tayar 
Reviewed-by: Oded Gabbay 
Signed-off-by: Oded Gabbay 
---
 drivers/accel/habanalabs/common/memory.c | 89 
 1 file changed, 43 insertions(+), 46 deletions(-)

diff --git a/drivers/accel/habanalabs/common/memory.c 
b/drivers/accel/habanalabs/common/memory.c
index e6474d38afc4..7b3809853dd5 100644
--- a/drivers/accel/habanalabs/common/memory.c
+++ b/drivers/accel/habanalabs/common/memory.c
@@ -1779,6 +1779,47 @@ static void hl_unmap_dmabuf(struct dma_buf_attachment 
*attachment,
kfree(sgt);
 }
 
+static struct hl_vm_hash_node *memhash_node_export_get(struct hl_ctx *ctx, u64 
addr)
+{
+   struct hl_device *hdev = ctx->hdev;
+   struct hl_vm_hash_node *hnode;
+
+   /* get the memory handle */
+   mutex_lock(>mem_hash_lock);
+   hash_for_each_possible(ctx->mem_hash, hnode, node, (unsigned long)addr)
+   if (addr == hnode->vaddr)
+   break;
+
+   if (!hnode) {
+   mutex_unlock(>mem_hash_lock);
+   dev_dbg(hdev->dev, "map address %#llx not found\n", addr);
+   return ERR_PTR(-EINVAL);
+   }
+
+   if (upper_32_bits(hnode->handle)) {
+   mutex_unlock(>mem_hash_lock);
+   dev_dbg(hdev->dev, "invalid handle %#llx for map address 
%#llx\n",
+   hnode->handle, addr);
+   return ERR_PTR(-EINVAL);
+   }
+
+   /*
+* node found, increase export count so this memory cannot be unmapped
+* and the hash node cannot be deleted.
+*/
+   hnode->export_cnt++;
+   mutex_unlock(>mem_hash_lock);
+
+   return hnode;
+}
+
+static void memhash_node_export_put(struct hl_ctx *ctx, struct hl_vm_hash_node 
*hnode)
+{
+   mutex_lock(>mem_hash_lock);
+   hnode->export_cnt--;
+   mutex_unlock(>mem_hash_lock);
+}
+
 static void hl_release_dmabuf(struct dma_buf *dmabuf)
 {
struct hl_dmabuf_priv *hl_dmabuf = dmabuf->priv;
@@ -1789,11 +1830,8 @@ static void hl_release_dmabuf(struct dma_buf *dmabuf)
 
ctx = hl_dmabuf->ctx;
 
-   if (hl_dmabuf->memhash_hnode) {
-   mutex_lock(>mem_hash_lock);
-   hl_dmabuf->memhash_hnode->export_cnt--;
-   mutex_unlock(>mem_hash_lock);
-   }
+   if (hl_dmabuf->memhash_hnode)
+   memhash_node_export_put(ctx, hl_dmabuf->memhash_hnode);
 
hl_ctx_put(ctx);
kfree(hl_dmabuf);
@@ -1933,47 +1971,6 @@ static int validate_export_params(struct hl_device 
*hdev, u64 device_addr, u64 s
return 0;
 }
 
-static struct hl_vm_hash_node *memhash_node_export_get(struct hl_ctx *ctx, u64 
addr)
-{
-   struct hl_device *hdev = ctx->hdev;
-   struct hl_vm_hash_node *hnode;
-
-   /* get the memory handle */
-   mutex_lock(>mem_hash_lock);
-   hash_for_each_possible(ctx->mem_hash, hnode, node, (unsigned long)addr)
-   if (addr == hnode->vaddr)
-   break;
-
-   if (!hnode) {
-   mutex_unlock(>mem_hash_lock);
-   dev_dbg(hdev->dev, "map address %#llx not found\n", addr);
-   return ERR_PTR(-EINVAL);
-   }
-
-   if (upper_32_bits(hnode->handle)) {
-   mutex_unlock(>mem_hash_lock);
-   dev_dbg(hdev->dev, "invalid handle %#llx for map address 
%#llx\n",
-   hnode->handle, addr);
-   return ERR_PTR(-EINVAL);
-   }
-
-   /*
-* node found, increase export count so this memory cannot be unmapped
-* and the hash node cannot be deleted.
-*/
-   hnode->export_cnt++;
-   mutex_unlock(>mem_hash_lock);
-
-   return hnode;
-}
-
-static void memhash_node_export_put(struct hl_ctx *ctx, struct hl_vm_hash_node 
*hnode)
-{
-   mutex_lock(>mem_hash_lock);
-   hnode->export_cnt--;
-   mutex_unlock(>mem_hash_lock);
-}
-
 static struct hl_vm_phys_pg_pack *get_phys_pg_pack_from_hash_node(struct 
hl_device *hdev,
struct hl_vm_hash_node 
*hnode)
 {
-- 
2.25.1



[PATCH 05/27] habanalabs: refactor debugfs init

2023-02-12 Thread Oded Gabbay
Make it easier to later add support for accel device.

Signed-off-by: Oded Gabbay 
---
 drivers/accel/habanalabs/common/debugfs.c | 129 --
 1 file changed, 68 insertions(+), 61 deletions(-)

diff --git a/drivers/accel/habanalabs/common/debugfs.c 
b/drivers/accel/habanalabs/common/debugfs.c
index 945c0e6758ca..86901ff4aa02 100644
--- a/drivers/accel/habanalabs/common/debugfs.c
+++ b/drivers/accel/habanalabs/common/debugfs.c
@@ -1583,209 +1583,216 @@ static const struct file_operations hl_debugfs_fops = 
{
.release = single_release,
 };
 
-static void add_secured_nodes(struct hl_dbg_device_entry *dev_entry)
+static void add_secured_nodes(struct hl_dbg_device_entry *dev_entry, struct 
dentry *root)
 {
debugfs_create_u8("i2c_bus",
0644,
-   dev_entry->root,
+   root,
_entry->i2c_bus);
 
debugfs_create_u8("i2c_addr",
0644,
-   dev_entry->root,
+   root,
_entry->i2c_addr);
 
debugfs_create_u8("i2c_reg",
0644,
-   dev_entry->root,
+   root,
_entry->i2c_reg);
 
debugfs_create_u8("i2c_len",
0644,
-   dev_entry->root,
+   root,
_entry->i2c_len);
 
debugfs_create_file("i2c_data",
0644,
-   dev_entry->root,
+   root,
dev_entry,
_i2c_data_fops);
 
debugfs_create_file("led0",
0200,
-   dev_entry->root,
+   root,
dev_entry,
_led0_fops);
 
debugfs_create_file("led1",
0200,
-   dev_entry->root,
+   root,
dev_entry,
_led1_fops);
 
debugfs_create_file("led2",
0200,
-   dev_entry->root,
+   root,
dev_entry,
_led2_fops);
 }
 
-void hl_debugfs_add_device(struct hl_device *hdev)
+static void add_files_to_device(struct hl_device *hdev, struct 
hl_dbg_device_entry *dev_entry,
+   struct dentry *root)
 {
-   struct hl_dbg_device_entry *dev_entry = >hl_debugfs;
int count = ARRAY_SIZE(hl_debugfs_list);
struct hl_debugfs_entry *entry;
int i;
 
-   dev_entry->hdev = hdev;
-   dev_entry->entry_arr = kmalloc_array(count,
-   sizeof(struct hl_debugfs_entry),
-   GFP_KERNEL);
-   if (!dev_entry->entry_arr)
-   return;
-
-   dev_entry->data_dma_blob_desc.size = 0;
-   dev_entry->data_dma_blob_desc.data = NULL;
-   dev_entry->mon_dump_blob_desc.size = 0;
-   dev_entry->mon_dump_blob_desc.data = NULL;
-
-   INIT_LIST_HEAD(_entry->file_list);
-   INIT_LIST_HEAD(_entry->cb_list);
-   INIT_LIST_HEAD(_entry->cs_list);
-   INIT_LIST_HEAD(_entry->cs_job_list);
-   INIT_LIST_HEAD(_entry->userptr_list);
-   INIT_LIST_HEAD(_entry->ctx_mem_hash_list);
-   mutex_init(_entry->file_mutex);
-   init_rwsem(_entry->state_dump_sem);
-   spin_lock_init(_entry->cb_spinlock);
-   spin_lock_init(_entry->cs_spinlock);
-   spin_lock_init(_entry->cs_job_spinlock);
-   spin_lock_init(_entry->userptr_spinlock);
-   spin_lock_init(_entry->ctx_mem_hash_spinlock);
-
-   dev_entry->root = debugfs_create_dir(dev_name(hdev->dev),
-   hl_debug_root);
-
debugfs_create_x64("memory_scrub_val",
0644,
-   dev_entry->root,
+   root,
>memory_scrub_val);
 
debugfs_create_file("memory_scrub",
0200,
-   dev_entry->root,
+   root,
dev_entry,
_mem_scrub_fops);
 
debugfs_create_x64("addr",
0644,
-   dev_entry->root,
+   root,
_entry->addr);
 
debugfs_create_file("data32",
0644,
-   

[PATCH 03/27] habanalabs: split cdev creation to separate function

2023-02-12 Thread Oded Gabbay
Move the cdev creation code from the main hdev init function to
a separate function. This will make the code more readable once we
add the accel registration code (instead/in addition to legacy
cdev).

Signed-off-by: Oded Gabbay 
---
 drivers/accel/habanalabs/common/device.c | 49 
 1 file changed, 32 insertions(+), 17 deletions(-)

diff --git a/drivers/accel/habanalabs/common/device.c 
b/drivers/accel/habanalabs/common/device.c
index 9933e5858a36..ed26b7d20d19 100644
--- a/drivers/accel/habanalabs/common/device.c
+++ b/drivers/accel/habanalabs/common/device.c
@@ -1939,27 +1939,17 @@ void hl_notifier_event_send_all(struct hl_device *hdev, 
u64 event_mask)
mutex_unlock(>fpriv_ctrl_list_lock);
 }
 
-/*
- * hl_device_init - main initialization function for habanalabs device
- *
- * @hdev: pointer to habanalabs device structure
- *
- * Allocate an id for the device, do early initialization and then call the
- * ASIC specific initialization functions. Finally, create the cdev and the
- * Linux device to expose it to the user
- */
-int hl_device_init(struct hl_device *hdev, struct class *hclass)
+static int create_cdev(struct hl_device *hdev, struct class *hclass)
 {
-   int i, rc, cq_cnt, user_interrupt_cnt, cq_ready_cnt;
char *name;
-   bool add_cdev_sysfs_on_err = false;
+   int rc;
 
hdev->cdev_idx = hdev->id / 2;
 
name = kasprintf(GFP_KERNEL, "hl%d", hdev->cdev_idx);
if (!name) {
rc = -ENOMEM;
-   goto out_disabled;
+   goto out_err;
}
 
/* Initialize cdev and device structures */
@@ -1969,7 +1959,7 @@ int hl_device_init(struct hl_device *hdev, struct class 
*hclass)
kfree(name);
 
if (rc)
-   goto out_disabled;
+   goto out_err;
 
name = kasprintf(GFP_KERNEL, "hl_controlD%d", hdev->cdev_idx);
if (!name) {
@@ -1986,10 +1976,36 @@ int hl_device_init(struct hl_device *hdev, struct class 
*hclass)
if (rc)
goto free_dev;
 
+   return 0;
+
+free_dev:
+   put_device(hdev->dev);
+out_err:
+   return rc;
+}
+
+/*
+ * hl_device_init - main initialization function for habanalabs device
+ *
+ * @hdev: pointer to habanalabs device structure
+ *
+ * Allocate an id for the device, do early initialization and then call the
+ * ASIC specific initialization functions. Finally, create the cdev and the
+ * Linux device to expose it to the user
+ */
+int hl_device_init(struct hl_device *hdev, struct class *hclass)
+{
+   int i, rc, cq_cnt, user_interrupt_cnt, cq_ready_cnt;
+   bool add_cdev_sysfs_on_err = false;
+
+   rc = create_cdev(hdev, hclass);
+   if (rc)
+   goto out_disabled;
+
/* Initialize ASIC function pointers and perform early init */
rc = device_early_init(hdev);
if (rc)
-   goto free_dev_ctrl;
+   goto free_dev;
 
user_interrupt_cnt = hdev->asic_prop.user_dec_intr_count +
hdev->asic_prop.user_interrupt_count;
@@ -2241,9 +2257,8 @@ int hl_device_init(struct hl_device *hdev, struct class 
*hclass)
kfree(hdev->user_interrupt);
 early_fini:
device_early_fini(hdev);
-free_dev_ctrl:
-   put_device(hdev->dev_ctrl);
 free_dev:
+   put_device(hdev->dev_ctrl);
put_device(hdev->dev);
 out_disabled:
hdev->disabled = true;
-- 
2.25.1



[PATCH 02/27] habanalabs/gaudi: capture RAZWI info only if HW indication detected

2023-02-12 Thread Oded Gabbay
From: Koby Elbaz 

RAZWI handling routine is called from most EQ events,
no matter if a RAZWI happens or not.
This fix is added to verify the handler is called only if
a real RAZWI indication in HW has been detected.

Signed-off-by: Koby Elbaz 
Reviewed-by: Oded Gabbay 
Signed-off-by: Oded Gabbay 
---
 drivers/accel/habanalabs/gaudi/gaudi.c | 9 +
 1 file changed, 5 insertions(+), 4 deletions(-)

diff --git a/drivers/accel/habanalabs/gaudi/gaudi.c 
b/drivers/accel/habanalabs/gaudi/gaudi.c
index 71debe862c86..7475f33734d7 100644
--- a/drivers/accel/habanalabs/gaudi/gaudi.c
+++ b/drivers/accel/habanalabs/gaudi/gaudi.c
@@ -7297,7 +7297,7 @@ static void gaudi_handle_qman_err(struct hl_device *hdev, 
u16 event_type, u64 *e
 }
 
 static void gaudi_print_irq_info(struct hl_device *hdev, u16 event_type,
-   bool razwi, u64 *event_mask)
+   bool check_razwi, u64 *event_mask)
 {
bool is_read = false, is_write = false;
u16 engine_id[2], num_of_razwi_eng = 0;
@@ -7316,7 +7316,7 @@ static void gaudi_print_irq_info(struct hl_device *hdev, 
u16 event_type,
dev_err_ratelimited(hdev->dev, "Received H/W interrupt %d [\"%s\"]\n",
event_type, desc);
 
-   if (razwi) {
+   if (check_razwi) {
gaudi_print_and_get_razwi_info(hdev, _id[0], 
_id[1], _read,
_write);
gaudi_print_and_get_mmu_error_info(hdev, _addr, 
event_mask);
@@ -7333,8 +7333,9 @@ static void gaudi_print_irq_info(struct hl_device *hdev, 
u16 event_type,
num_of_razwi_eng = 1;
}
 
-   hl_handle_razwi(hdev, razwi_addr, engine_id, num_of_razwi_eng, 
razwi_flags,
-   event_mask);
+   if (razwi_flags)
+   hl_handle_razwi(hdev, razwi_addr, engine_id, 
num_of_razwi_eng,
+   razwi_flags, event_mask);
}
 }
 
-- 
2.25.1



[PATCH 01/27] habanalabs/gaudi2: increase user interrupt grace time

2023-02-12 Thread Oded Gabbay
From: Ofir Bitton 

Currently we support scenarios where a timestamp registration request
of a certain offset is received during the interrupt handling of the
same offset. In this case we give a grace period of up to 100us for
the interrupt handler to finish.
It seems that sometimes the interrupt handling takes more than expected,
and therefore this path should be optimized. Until that happens, let's
increase the grace period in order not to reach timeout which will
cause user call to be rejected.

Signed-off-by: Ofir Bitton 
Reviewed-by: Oded Gabbay 
Signed-off-by: Oded Gabbay 
---
 drivers/accel/habanalabs/common/command_submission.c | 12 
 1 file changed, 8 insertions(+), 4 deletions(-)

diff --git a/drivers/accel/habanalabs/common/command_submission.c 
b/drivers/accel/habanalabs/common/command_submission.c
index 8270db0a72a2..e313ff8af7cc 100644
--- a/drivers/accel/habanalabs/common/command_submission.c
+++ b/drivers/accel/habanalabs/common/command_submission.c
@@ -17,7 +17,7 @@
HL_CS_FLAGS_FLUSH_PCI_HBW_WRITES)
 
 
-#define MAX_TS_ITER_NUM 10
+#define MAX_TS_ITER_NUM 100
 
 /**
  * enum hl_cs_wait_status - cs wait status
@@ -3145,6 +3145,7 @@ static int ts_buff_get_kernel_ts_record(struct 
hl_mmap_mem_buf *buf,
(ts_buff->kernel_buff_size / sizeof(struct 
hl_user_pending_interrupt));
unsigned long flags, iter_counter = 0;
u64 current_cq_counter;
+   ktime_t timestamp;
 
/* Validate ts_offset not exceeding last max */
if (requested_offset_record >= cb_last) {
@@ -3153,6 +3154,8 @@ static int ts_buff_get_kernel_ts_record(struct 
hl_mmap_mem_buf *buf,
return -EINVAL;
}
 
+   timestamp = ktime_get();
+
 start_over:
spin_lock_irqsave(wait_list_lock, flags);
 
@@ -3178,11 +3181,12 @@ static int ts_buff_get_kernel_ts_record(struct 
hl_mmap_mem_buf *buf,
 
/* irq handling in the middle give it time to finish */
spin_unlock_irqrestore(wait_list_lock, flags);
-   usleep_range(1, 10);
+   usleep_range(100, 1000);
if (++iter_counter == MAX_TS_ITER_NUM) {
dev_err(buf->mmg->dev,
-   "handling registration interrupt took 
too long!!\n");
-   return -EINVAL;
+   "Timestamp offest processing reached 
timeout of %lld ms\n",
+   ktime_ms_delta(ktime_get(), timestamp));
+   return -EAGAIN;
}
 
goto start_over;
-- 
2.25.1



Re: [PATCH 1/1] drm/panel: st7703: Fix resume of XBD599 panel

2023-02-12 Thread Ondřej Jirman
Hello,

On Sun, Feb 12, 2023 at 06:52:05PM +0100, Frank Oltmanns wrote:
> Hi Ondřej,
> hi Guido,
> 
> Ondřej, thank you very much for your feedback!
> 
> I have a couple of questions.
> 
> Ondřej Jirman  writes:
> 
> > On Sun, Feb 12, 2023 at 01:08:29PM +0100, Frank Oltmanns wrote:
> >> In contrast to the JH057N panel, the XBD599 panel does not require a 20
> >> msec delay after initialization and exiting sleep mode. Therefore, move
> >> the delay into the already existing device specific initialization
> >> function.
> >>
> >> Also, the timing contraints after entering and exiting sleep mode differ
> >> between the two panels:
> >>  - The JH057N requires a shorter delay than the XDB599 after waking up
> >>from sleep mode and before enabling the display.
> >>  - The XDB599 requires a delay in order to drain the display of charge,
> >>which is not required on the JH057N.
> >
> > There’s no difference between the panels here. It’s a controller specified
> > requirement.
> >
> > 
> >
> > 60ms used in the driver between sleep out and display on is just
> > incorrect from the datasheet perspective.
> 
> Please let me point you to the discussion you and Guido had ~2.5 years ago:
> 

Guido references some unspecified datasheet. We only have a st7703 datasheet
to go by, and that requires 120ms and is relevant for both panels.

Also the patch that Guido tested removed a few 20ms delays from the init
sequence for the librem panel. Maybe that broke the init for librem panel and
not the extra few ms after sleep out that the patch added.

> What resonates most with me is the following statement from Guido:
> > > > > Given the amount of ST7703 look alikes i don’t think you can go by the
> > > > > datasheet and hope not to break other panels. The current sleeps cater
> > > > > for the rocktech panel (which suffered from similar issues you 
> > > > > describe
> > > > > when we took other parameters) so you need to make those panel 
> > > > > specific.
> 
> My takeaway is, that neither panel needed the actual 120 msec wait time. But
> Guido was reluctant to change the timing for the Librem 5 devkit panel. That’s
> why I went for the panel specific implementation.
> 
> Of course, we can revisit that decision. Since I don’t have the Librem
> 5 devkit, I have to kindly ask Guido for advise.
> 
> > You also have to wait 120ms after sleep in (or HW reset) and before shutting
> > down the panel. If you don’t, after a bunch of cycles of this incorrect
> > power up/down sequence the panel will start blinking weirdly, and the 
> > incorrect
> > power up/down sequence without delays will not be able to recover it. You’ll
> > have to let the panel sit for 5-10 minutes powered off before it starts to
> > behave itself again.
> >
> > The documentation for sleep in specifies what’s happening during sleep in,
> > and why this delay is necessary after sleep in:
> >
> > 
> 
> I read that screenshot, that we need a 120 msec wait after sleep OUT before we
> can send another sleep in (see the “Restriction” row). I can’t seem to find
> the reference to the 120 msec delay after the sleep IN command. I read the
> flow chart at the bottom as informational about the duration of the whole
> procedure that happens after issuing the sleep in command. The only
> restriction is that we can’t issue any command for 5 msec after sleep in was
> issued.

It's at the bottom, sleep in takes 120ms to execute. Part of the execution is
draining the charge from the panel. You can't shutdown power supplies before
sleep in completes, so you need the delay after sleep in and before regulator
powerdown, otherwise the flow chart will not have the time to execute properly,
and the panel will be left in a bad state.

> > So there needs to be 120ms delay after sleep in and after sleep out,
> > regardless of which panel is driven by this controller, to ensure the panel
> > stays operational even when the user is quickly switching it on/off 
> > repeatedly.
> >
> > So I don’t think you should be doing panel specific quirks here.
> 
> Maybe. I can only say that without the timings in this patch (i.e. the ones
> from your kernel branch) the display on my pinephone is flickering after the
> first (and every subsequent) time the display is turned off. With your new
> timing everything works great on the pinephone. Guido states that the timings
> in your original patch (i.e. the XDB599 specific timings in this patch) the
> Librem 5 devkit panel doesn’t work.

Adding extra delays after sleep in/before sleep out should not break Librem
panel. Previous patches also changed the powerup sequence to hold the reset
before powerup of the power supplies, and rearranged other delays.

They were made before the problem with the panel discharge was properly
understood.

I suggest just going a bit more 

Re: [PATCH 1/1] drm/panel: st7703: Fix resume of XBD599 panel

2023-02-12 Thread Frank Oltmanns
Hi Ondřej,
hi Guido,

Ondřej, thank you very much for your feedback!

I have a couple of questions.

Ondřej Jirman  writes:

> On Sun, Feb 12, 2023 at 01:08:29PM +0100, Frank Oltmanns wrote:
>> In contrast to the JH057N panel, the XBD599 panel does not require a 20
>> msec delay after initialization and exiting sleep mode. Therefore, move
>> the delay into the already existing device specific initialization
>> function.
>>
>> Also, the timing contraints after entering and exiting sleep mode differ
>> between the two panels:
>>  - The JH057N requires a shorter delay than the XDB599 after waking up
>>from sleep mode and before enabling the display.
>>  - The XDB599 requires a delay in order to drain the display of charge,
>>which is not required on the JH057N.
>
> There’s no difference between the panels here. It’s a controller specified
> requirement.
>
> 
>
> 60ms used in the driver between sleep out and display on is just
> incorrect from the datasheet perspective.

Please let me point you to the discussion you and Guido had ~2.5 years ago:


What resonates most with me is the following statement from Guido:
> > > > Given the amount of ST7703 look alikes i don’t think you can go by the
> > > > datasheet and hope not to break other panels. The current sleeps cater
> > > > for the rocktech panel (which suffered from similar issues you describe
> > > > when we took other parameters) so you need to make those panel specific.

My takeaway is, that neither panel needed the actual 120 msec wait time. But 
Guido was reluctant to change the timing for the Librem 5 devkit panel. That’s 
why I went for the panel specific implementation.

Of course, we can revisit that decision. Since I don’t have the Librem 5 
devkit, I have to kindly ask Guido for advise.

> You also have to wait 120ms after sleep in (or HW reset) and before shutting
> down the panel. If you don’t, after a bunch of cycles of this incorrect
> power up/down sequence the panel will start blinking weirdly, and the 
> incorrect
> power up/down sequence without delays will not be able to recover it. You’ll
> have to let the panel sit for 5-10 minutes powered off before it starts to
> behave itself again.
>
> The documentation for sleep in specifies what’s happening during sleep in,
> and why this delay is necessary after sleep in:
>
> 

I read that screenshot, that we need a 120 msec wait after sleep OUT before we 
can send another sleep in (see the “Restriction” row). I can’t seem to find the 
reference to the 120 msec delay after the sleep IN command. I read the flow 
chart at the bottom as informational about the duration of the whole procedure 
that happens after issuing the sleep in command. The only restriction is that 
we can’t issue any command for 5 msec after sleep in was issued.

> So there needs to be 120ms delay after sleep in and after sleep out,
> regardless of which panel is driven by this controller, to ensure the panel
> stays operational even when the user is quickly switching it on/off 
> repeatedly.
>
> So I don’t think you should be doing panel specific quirks here.

Maybe. I can only say that without the timings in this patch (i.e. the ones 
from your kernel branch) the display on my pinephone is flickering after the 
first (and every subsequent) time the display is turned off. With your new 
timing everything works great on the pinephone. Guido states that the timings 
in your original patch (i.e. the XDB599 specific timings in this patch) the 
Librem 5 devkit panel doesn’t work.

Do you have a proposal how to proceed without implementing panel specific 
timings?

Thanks,
  Frank

>
> regards,
>   o.
>
>> Therefore, introduce panel specific functions for the delays.
>>
>> The XDB599 does not require a 20 msec delay between the SETBGP and
>> SETVCOM commands. Therefore, remove the delay from the device specific
>> initialization function.
>>
>> Signed-off-by: Frank Oltmanns 
>> Cc: Ondrej Jirman 
>> Reported-by: Samuel Holland 
>> —
>>  drivers/gpu/drm/panel/panel-sitronix-st7703.c | 40 —
>>  1 file changed, 35 insertions(+), 5 deletions(-)
>>
>> diff –git a/drivers/gpu/drm/panel/panel-sitronix-st7703.c 
>> b/drivers/gpu/drm/panel/panel-sitronix-st7703.c
>> index 6747ca237ced..a149341c4a8b 100644
>> — a/drivers/gpu/drm/panel/panel-sitronix-st7703.c
>> +++ b/drivers/gpu/drm/panel/panel-sitronix-st7703.c
>> @@ -66,6 +66,8 @@ struct st7703_panel_desc {
>>  unsigned long mode_flags;
>>  enum mipi_dsi_pixel_format format;
>>  int (*init_sequence)(struct st7703 *ctx);
>> +void (*wait_after_sleep_out)(void);
>> +void (*drain_charge)(void);
>>  };
>>
>>  static inline struct st7703 *panel_to_st7703(struct drm_panel *panel)
>> @@ -126,10 +128,24 @@ static int jh057n_init_sequence(struct st7703 *ctx)
>> 

Re: [PATCH 0/1] drm/panel: st7703: Fix initialization failures on Xingbangda XBD599

2023-02-12 Thread Frank Oltmanns


[PATCH 0/1] drm/panel: st7703: Fix resume of XBD599 panel

2023-02-12 Thread Frank Oltmanns
This patch fixes flickering after resume from sleep on panel
xingbangda,xbd599 (e.g. used in PinePhone).

It was originally submitted by Ondrej Jirman in July 2020:
https://lore.kernel.org/all/20200716123753.3552425-1-meg...@megous.com/

The original patchset contained two patches. This submission fixes the
patch that broke handling of the JH057N panel of the Purism Librem 5.

In essence, it does not change any behavior towards the JH057N panel,
but only affects the XDB599.

The patch is just a refactoring of Ondřej's original patch, that is
already used today by PinePhone distributions like PostmarketOS.

I was torn between using function pointers and just calling msleep()
with device specific delays. I decided to go with function pointers,
because my understanding is that calling msleep(0), which would be
required for waiting for the JH057N display to discharge, still results
in a delay. The empty function I used has no side effect on that panel.

The patch is based on drm-next.

Ondřej, since this is just a refactoring, I would gladly add your SoB,
if you wish so.

Thanks,
  Frank

Frank Oltmanns (1):
  drm/panel: st7703: Fix resume of XBD599 panel

 drivers/gpu/drm/panel/panel-sitronix-st7703.c | 40 ---
 1 file changed, 35 insertions(+), 5 deletions(-)

-- 
2.39.1



[PATCH 0/1] drm/panel: st7703: Fix initialization failures on Xingbangda XBD599

2023-02-12 Thread Frank Oltmanns
This patch fixes intermittent panel initialization failures and screen
corruption during resume from sleep on panel xingbangda,xbd599 (e.g.
used in PinePhone).

It was originally submitted by Ondrej Jirman in July 2020:
https://lore.kernel.org/all/20200716123753.3552425-1-meg...@megous.com/

The original patchset contained two patches. One of them broke the panel
on the Purism Librem 5.

This is the concluding message from Guido Günther in that thread:
https://lore.kernel.org/all/20200801110409.ga6...@bogon.m.sigxcpu.org/#t

Guido wanted changes to the commit message. I updated it to adress his
requests.

I send this patch in Ondřej's name with his consent.

The patch is based on drm-next.

Please let me know what you think.

Thanks,
  Frank

Ondrej Jirman (1):
  drm/panel: st7703: Pick different reset sequence

 drivers/gpu/drm/panel/panel-sitronix-st7703.c | 25 ++-
 1 file changed, 13 insertions(+), 12 deletions(-)

-- 
2.39.1



[PATCH 1/1] drm/panel: st7703: Fix resume of XBD599 panel

2023-02-12 Thread Frank Oltmanns
In contrast to the JH057N panel, the XBD599 panel does not require a 20
msec delay after initialization and exiting sleep mode. Therefore, move
the delay into the already existing device specific initialization
function.

Also, the timing contraints after entering and exiting sleep mode differ
between the two panels:
 - The JH057N requires a shorter delay than the XDB599 after waking up
   from sleep mode and before enabling the display.
 - The XDB599 requires a delay in order to drain the display of charge,
   which is not required on the JH057N.

Therefore, introduce panel specific functions for the delays.

The XDB599 does not require a 20 msec delay between the SETBGP and
SETVCOM commands. Therefore, remove the delay from the device specific
initialization function.

Signed-off-by: Frank Oltmanns 
Cc: Ondrej Jirman 
Reported-by: Samuel Holland 
---
 drivers/gpu/drm/panel/panel-sitronix-st7703.c | 40 ---
 1 file changed, 35 insertions(+), 5 deletions(-)

diff --git a/drivers/gpu/drm/panel/panel-sitronix-st7703.c 
b/drivers/gpu/drm/panel/panel-sitronix-st7703.c
index 6747ca237ced..a149341c4a8b 100644
--- a/drivers/gpu/drm/panel/panel-sitronix-st7703.c
+++ b/drivers/gpu/drm/panel/panel-sitronix-st7703.c
@@ -66,6 +66,8 @@ struct st7703_panel_desc {
unsigned long mode_flags;
enum mipi_dsi_pixel_format format;
int (*init_sequence)(struct st7703 *ctx);
+   void (*wait_after_sleep_out)(void);
+   void (*drain_charge)(void);
 };
 
 static inline struct st7703 *panel_to_st7703(struct drm_panel *panel)
@@ -126,10 +128,24 @@ static int jh057n_init_sequence(struct st7703 *ctx)
   0x18, 0x00, 0x09, 0x0E, 0x29, 0x2D, 0x3C, 
0x41,
   0x37, 0x07, 0x0B, 0x0D, 0x10, 0x11, 0x0F, 
0x10,
   0x11, 0x18);
+   msleep(20);
 
return 0;
 }
 
+static void jh057n_wait_after_sleep_out(void)
+{
+   /*
+* Panel is operational 120 msec after reset, i.e. 60 msec after
+* sleep out.
+*/
+   msleep(60);
+}
+
+static void jh057n_drain_charge(void)
+{
+}
+
 static const struct drm_display_mode jh057n00900_mode = {
.hdisplay= 720,
.hsync_start = 720 + 90,
@@ -152,6 +168,8 @@ static const struct st7703_panel_desc 
jh057n00900_panel_desc = {
MIPI_DSI_MODE_VIDEO_BURST | MIPI_DSI_MODE_VIDEO_SYNC_PULSE,
.format = MIPI_DSI_FMT_RGB888,
.init_sequence = jh057n_init_sequence,
+   .wait_after_sleep_out = jh057n_wait_after_sleep_out,
+   .drain_charge = jh057n_drain_charge,
 };
 
 static int xbd599_init_sequence(struct st7703 *ctx)
@@ -273,7 +291,6 @@ static int xbd599_init_sequence(struct st7703 *ctx)
mipi_dsi_dcs_write_seq(dsi, ST7703_CMD_SETBGP,
   0x07, /* VREF_SEL = 4.2V */
   0x07  /* NVREF_SEL = 4.2V */);
-   msleep(20);
 
mipi_dsi_dcs_write_seq(dsi, ST7703_CMD_SETVCOM,
   0x2C, /* VCOMDC_F = -0.67V */
@@ -315,6 +332,18 @@ static int xbd599_init_sequence(struct st7703 *ctx)
return 0;
 }
 
+static void xbd599_wait_after_sleep_out(void)
+{
+   msleep(120);
+}
+
+static void xbd599_drain_charge(void)
+{
+   /* Drain diplay of charge, to work correctly on next power on. */
+   msleep(120);
+}
+
+
 static const struct drm_display_mode xbd599_mode = {
.hdisplay= 720,
.hsync_start = 720 + 40,
@@ -336,6 +365,8 @@ static const struct st7703_panel_desc xbd599_desc = {
.mode_flags = MIPI_DSI_MODE_VIDEO | MIPI_DSI_MODE_VIDEO_SYNC_PULSE,
.format = MIPI_DSI_FMT_RGB888,
.init_sequence = xbd599_init_sequence,
+   .wait_after_sleep_out = xbd599_wait_after_sleep_out,
+   .drain_charge = xbd599_drain_charge,
 };
 
 static int st7703_enable(struct drm_panel *panel)
@@ -350,16 +381,13 @@ static int st7703_enable(struct drm_panel *panel)
return ret;
}
 
-   msleep(20);
-
ret = mipi_dsi_dcs_exit_sleep_mode(dsi);
if (ret < 0) {
dev_err(ctx->dev, "Failed to exit sleep mode: %d\n", ret);
return ret;
}
 
-   /* Panel is operational 120 msec after reset */
-   msleep(60);
+   ctx->desc->wait_after_sleep_out();
 
ret = mipi_dsi_dcs_set_display_on(dsi);
if (ret)
@@ -384,6 +412,8 @@ static int st7703_disable(struct drm_panel *panel)
if (ret < 0)
dev_err(ctx->dev, "Failed to enter sleep mode: %d\n", ret);
 
+   ctx->desc->drain_charge();
+
return 0;
 }
 
-- 
2.39.1



[PATCH 1/1] drm/panel: st7703: Pick different reset sequence

2023-02-12 Thread Frank Oltmanns
From: Ondrej Jirman 

Switching to a different reset sequence, enabling IOVCC before enabling
VCC.

There also needs to be a delay after enabling the supplies and before
deasserting the reset. The datasheet specifies 1ms after the supplies
reach the required voltage. Use 10-20ms to also give the power supplies
some time to reach the required voltage, too.

This fixes intermittent panel initialization failures and screen
corruption during resume from sleep on panel xingbangda,xbd599 (e.g.
used in PinePhone).

Signed-off-by: Ondrej Jirman 
Signed-off-by: Frank Oltmanns 
Reported-by: Samuel Holland 
---
 drivers/gpu/drm/panel/panel-sitronix-st7703.c | 25 ++-
 1 file changed, 13 insertions(+), 12 deletions(-)

diff --git a/drivers/gpu/drm/panel/panel-sitronix-st7703.c 
b/drivers/gpu/drm/panel/panel-sitronix-st7703.c
index 6747ca237ced..45695aa51f62 100644
--- a/drivers/gpu/drm/panel/panel-sitronix-st7703.c
+++ b/drivers/gpu/drm/panel/panel-sitronix-st7703.c
@@ -411,29 +411,30 @@ static int st7703_prepare(struct drm_panel *panel)
return 0;
 
dev_dbg(ctx->dev, "Resetting the panel\n");
-   ret = regulator_enable(ctx->vcc);
+   gpiod_set_value_cansleep(ctx->reset_gpio, 1);
+
+   ret = regulator_enable(ctx->iovcc);
if (ret < 0) {
-   dev_err(ctx->dev, "Failed to enable vcc supply: %d\n", ret);
+   dev_err(ctx->dev, "Failed to enable iovcc supply: %d\n", ret);
return ret;
}
-   ret = regulator_enable(ctx->iovcc);
+
+   ret = regulator_enable(ctx->vcc);
if (ret < 0) {
-   dev_err(ctx->dev, "Failed to enable iovcc supply: %d\n", ret);
-   goto disable_vcc;
+   dev_err(ctx->dev, "Failed to enable vcc supply: %d\n", ret);
+   regulator_disable(ctx->iovcc);
+   return ret;
}
 
-   gpiod_set_value_cansleep(ctx->reset_gpio, 1);
-   usleep_range(20, 40);
+   /* Give power supplies time to stabilize before deasserting reset. */
+   usleep_range(1, 2);
+
gpiod_set_value_cansleep(ctx->reset_gpio, 0);
-   msleep(20);
+   usleep_range(15000, 2);
 
ctx->prepared = true;
 
return 0;
-
-disable_vcc:
-   regulator_disable(ctx->vcc);
-   return ret;
 }
 
 static const u32 mantix_bus_formats[] = {
-- 
2.39.1



Re: [PATCH 04/11] drivers/ps3: Read video= option with fb_get_option()

2023-02-12 Thread Geoff Levand
Hi Thomas,

On 2/9/23 05:55, Thomas Zimmermann wrote:
> Get the kernel's global video= parameter with fb_get_option(). Done
> to unexport the internal fbdev state fb_mode_config. No functional
> changes.
> 
> Signed-off-by: Thomas Zimmermann 
> ---
>  drivers/ps3/ps3av.c | 11 +--
>  1 file changed, 9 insertions(+), 2 deletions(-)

I wanted to test these changes on the PS3, but got this
error when trying to apply this patch set to Linux-6.2-rc7:

  Applying: fbdev: Handle video= parameter in video/cmdline.c
  error: patch failed: drivers/gpu/drm/Kconfig:10
  error: drivers/gpu/drm/Kconfig: patch does not apply

Is there a Linux kernel revision that these will apply to,
or is there a git repository I can pull them from?

-Geoff


Re: [PATCH 1/1] drm/panel: st7703: Fix resume of XBD599 panel

2023-02-12 Thread Frank Oltmanns


Re: [PATCH 1/2] dt-bindings: display: simple: Add BOE EV121WXM-N10-1850 panel

2023-02-12 Thread Krzysztof Kozlowski
On 12/02/2023 05:08, Liu Ying wrote:
> Add BOE EV121WXM-N10-1850 12.1" WXGA (1280x800) TFT LCD panel
> compatible string.  The panel has a LVDS display interface.
> 
> The panel's product specification can be found at:
> http://www.onetech.com.tw/files/EV121WXM-N10-1850ProductSpecification_20180801.pdf
> 
> Signed-off-by: Liu Ying 


Acked-by: Krzysztof Kozlowski 

Best regards,
Krzysztof



[PATCH v13 13/13] drm/msm/disp/dpu: update dpu_enc crtc state on crtc enable/disable during self refresh

2023-02-12 Thread Vinod Polimera
Populate the enocder software structure to reflect the updated
crtc appropriately during crtc enable/disable for a new commit
while taking care of the self refresh transitions when crtc
disable is triggered from the drm self refresh library.

Signed-off-by: Vinod Polimera 
---
 drivers/gpu/drm/msm/disp/dpu1/dpu_crtc.c | 29 +
 1 file changed, 25 insertions(+), 4 deletions(-)

diff --git a/drivers/gpu/drm/msm/disp/dpu1/dpu_crtc.c 
b/drivers/gpu/drm/msm/disp/dpu1/dpu_crtc.c
index 60e5984..b1ec0c3 100644
--- a/drivers/gpu/drm/msm/disp/dpu1/dpu_crtc.c
+++ b/drivers/gpu/drm/msm/disp/dpu1/dpu_crtc.c
@@ -1022,8 +1022,17 @@ static void dpu_crtc_disable(struct drm_crtc *crtc,
 
DRM_DEBUG_KMS("crtc%d\n", crtc->base.id);
 
-   if (old_crtc_state->self_refresh_active)
+   /* If disable is triggered while in self refresh mode,
+* reset the encoder software state so that in enable
+* it won't trigger a warn while assigning crtc.
+*/
+   if (old_crtc_state->self_refresh_active) {
+   drm_for_each_encoder_mask(encoder, crtc->dev,
+   old_crtc_state->encoder_mask) {
+   dpu_encoder_assign_crtc(encoder, NULL);
+   }
return;
+   }
 
/* Disable/save vblank irq handling */
drm_crtc_vblank_off(crtc);
@@ -1036,7 +1045,14 @@ static void dpu_crtc_disable(struct drm_crtc *crtc,
 */
if (dpu_encoder_get_intf_mode(encoder) == INTF_MODE_VIDEO)
release_bandwidth = true;
-   dpu_encoder_assign_crtc(encoder, NULL);
+
+   /*
+* If disable is triggered during psr active(e.g: screen dim in 
PSR),
+* we will need encoder->crtc connection to process the device 
sleep &
+* preserve it during psr sequence.
+*/
+   if (!crtc->state->self_refresh_active)
+   dpu_encoder_assign_crtc(encoder, NULL);
}
 
/* wait for frame_event_done completion */
@@ -1084,6 +1100,9 @@ static void dpu_crtc_enable(struct drm_crtc *crtc,
struct dpu_crtc *dpu_crtc = to_dpu_crtc(crtc);
struct drm_encoder *encoder;
bool request_bandwidth = false;
+   struct drm_crtc_state *old_crtc_state;
+
+   old_crtc_state = drm_atomic_get_old_crtc_state(state, crtc);
 
pm_runtime_get_sync(crtc->dev->dev);
 
@@ -1106,8 +1125,10 @@ static void dpu_crtc_enable(struct drm_crtc *crtc,
trace_dpu_crtc_enable(DRMID(crtc), true, dpu_crtc);
dpu_crtc->enabled = true;
 
-   drm_for_each_encoder_mask(encoder, crtc->dev, crtc->state->encoder_mask)
-   dpu_encoder_assign_crtc(encoder, crtc);
+   if (!old_crtc_state->self_refresh_active) {
+   drm_for_each_encoder_mask(encoder, crtc->dev, 
crtc->state->encoder_mask)
+   dpu_encoder_assign_crtc(encoder, crtc);
+   }
 
/* Enable/restore vblank irq handling */
drm_crtc_vblank_on(crtc);
-- 
2.7.4



[PATCH v13 12/13] drm/msm/disp/dpu: add PSR support for eDP interface in dpu driver

2023-02-12 Thread Vinod Polimera
Enable PSR on eDP interface using drm self-refresh librabry.
This patch uses a trigger from self-refresh library to enter/exit
into PSR, when there are no updates from framework.

Signed-off-by: Kalyan Thota 
Signed-off-by: Vinod Polimera 
Reviewed-by: Dmitry Baryshkov 
---
 drivers/gpu/drm/msm/disp/dpu1/dpu_crtc.c| 13 -
 drivers/gpu/drm/msm/disp/dpu1/dpu_encoder.c | 14 ++
 drivers/gpu/drm/msm/disp/dpu1/dpu_kms.c |  2 +-
 3 files changed, 27 insertions(+), 2 deletions(-)

diff --git a/drivers/gpu/drm/msm/disp/dpu1/dpu_crtc.c 
b/drivers/gpu/drm/msm/disp/dpu1/dpu_crtc.c
index f29a339..60e5984 100644
--- a/drivers/gpu/drm/msm/disp/dpu1/dpu_crtc.c
+++ b/drivers/gpu/drm/msm/disp/dpu1/dpu_crtc.c
@@ -21,6 +21,7 @@
 #include 
 #include 
 #include 
+#include 
 
 #include "dpu_kms.h"
 #include "dpu_hw_lm.h"
@@ -1021,6 +1022,9 @@ static void dpu_crtc_disable(struct drm_crtc *crtc,
 
DRM_DEBUG_KMS("crtc%d\n", crtc->base.id);
 
+   if (old_crtc_state->self_refresh_active)
+   return;
+
/* Disable/save vblank irq handling */
drm_crtc_vblank_off(crtc);
 
@@ -1577,7 +1581,7 @@ struct drm_crtc *dpu_crtc_init(struct drm_device *dev, 
struct drm_plane *plane,
 {
struct drm_crtc *crtc = NULL;
struct dpu_crtc *dpu_crtc = NULL;
-   int i;
+   int i, ret;
 
dpu_crtc = kzalloc(sizeof(*dpu_crtc), GFP_KERNEL);
if (!dpu_crtc)
@@ -1614,6 +1618,13 @@ struct drm_crtc *dpu_crtc_init(struct drm_device *dev, 
struct drm_plane *plane,
/* initialize event handling */
spin_lock_init(_crtc->event_lock);
 
+   ret = drm_self_refresh_helper_init(crtc);
+   if (ret) {
+   DPU_ERROR("Failed to initialize %s with self-refresh helpers 
%d\n",
+   crtc->name, ret);
+   return ERR_PTR(ret);
+   }
+
DRM_DEBUG_KMS("%s: successfully initialized crtc\n", dpu_crtc->name);
return crtc;
 }
diff --git a/drivers/gpu/drm/msm/disp/dpu1/dpu_encoder.c 
b/drivers/gpu/drm/msm/disp/dpu1/dpu_encoder.c
index 01b7509..450abb1 100644
--- a/drivers/gpu/drm/msm/disp/dpu1/dpu_encoder.c
+++ b/drivers/gpu/drm/msm/disp/dpu1/dpu_encoder.c
@@ -12,6 +12,7 @@
 #include 
 #include 
 
+#include 
 #include 
 #include 
 #include 
@@ -1212,11 +1213,24 @@ static void dpu_encoder_virt_atomic_disable(struct 
drm_encoder *drm_enc,
struct drm_atomic_state *state)
 {
struct dpu_encoder_virt *dpu_enc = NULL;
+   struct drm_crtc *crtc;
+   struct drm_crtc_state *old_state = NULL;
int i = 0;
 
dpu_enc = to_dpu_encoder_virt(drm_enc);
DPU_DEBUG_ENC(dpu_enc, "\n");
 
+   crtc = drm_atomic_get_old_crtc_for_encoder(state, drm_enc);
+   if (crtc)
+   old_state = drm_atomic_get_old_crtc_state(state, crtc);
+
+   /*
+* The encoder is already disabled if self refresh mode was set earlier,
+* in the old_state for the corresponding crtc.
+*/
+   if (old_state && old_state->self_refresh_active)
+   return;
+
mutex_lock(_enc->enc_lock);
dpu_enc->enabled = false;
 
diff --git a/drivers/gpu/drm/msm/disp/dpu1/dpu_kms.c 
b/drivers/gpu/drm/msm/disp/dpu1/dpu_kms.c
index a683bd9..681dd2e 100644
--- a/drivers/gpu/drm/msm/disp/dpu1/dpu_kms.c
+++ b/drivers/gpu/drm/msm/disp/dpu1/dpu_kms.c
@@ -491,7 +491,7 @@ static void dpu_kms_wait_for_commit_done(struct msm_kms 
*kms,
return;
}
 
-   if (!crtc->state->active) {
+   if (!drm_atomic_crtc_effectively_active(crtc->state)) {
DPU_DEBUG("[crtc:%d] not active\n", crtc->base.id);
return;
}
-- 
2.7.4



[PATCH v13 10/13] drm/msm/dp: use the eDP bridge ops to validate eDP modes

2023-02-12 Thread Vinod Polimera
The eDP and DP interfaces shared the bridge operations and
the eDP specific changes were implemented under is_edp check.
To add psr support for eDP, we started using a new set of eDP
bridge ops. We are moving the eDP specific code in the
dp_bridge_mode_valid function to a new eDP function,
edp_bridge_mode_valid under the eDP bridge ops.

Signed-off-by: Sankeerth Billakanti 
Signed-off-by: Vinod Polimera 
Reviewed-by: Dmitry Baryshkov 
---
 drivers/gpu/drm/msm/dp/dp_display.c |  8 
 drivers/gpu/drm/msm/dp/dp_drm.c | 34 +-
 2 files changed, 33 insertions(+), 9 deletions(-)

diff --git a/drivers/gpu/drm/msm/dp/dp_display.c 
b/drivers/gpu/drm/msm/dp/dp_display.c
index 86ed80c..ffb21a6 100644
--- a/drivers/gpu/drm/msm/dp/dp_display.c
+++ b/drivers/gpu/drm/msm/dp/dp_display.c
@@ -996,14 +996,6 @@ enum drm_mode_status dp_bridge_mode_valid(struct 
drm_bridge *bridge,
return -EINVAL;
}
 
-   /*
-* The eDP controller currently does not have a reliable way of
-* enabling panel power to read sink capabilities. So, we rely
-* on the panel driver to populate only supported modes for now.
-*/
-   if (dp->is_edp)
-   return MODE_OK;
-
if (mode->clock > DP_MAX_PIXEL_CLK_KHZ)
return MODE_CLOCK_HIGH;
 
diff --git a/drivers/gpu/drm/msm/dp/dp_drm.c b/drivers/gpu/drm/msm/dp/dp_drm.c
index 3b38bd9..029e08c 100644
--- a/drivers/gpu/drm/msm/dp/dp_drm.c
+++ b/drivers/gpu/drm/msm/dp/dp_drm.c
@@ -226,12 +226,44 @@ static void edp_bridge_atomic_post_disable(struct 
drm_bridge *drm_bridge,
dp_bridge_atomic_post_disable(drm_bridge, old_bridge_state);
 }
 
+/**
+ * edp_bridge_mode_valid - callback to determine if specified mode is valid
+ * @bridge: Pointer to drm bridge structure
+ * @info: display info
+ * @mode: Pointer to drm mode structure
+ * Returns: Validity status for specified mode
+ */
+static enum drm_mode_status edp_bridge_mode_valid(struct drm_bridge *bridge,
+ const struct drm_display_info *info,
+ const struct drm_display_mode *mode)
+{
+   struct msm_dp *dp;
+   int mode_pclk_khz = mode->clock;
+
+   dp = to_dp_bridge(bridge)->dp_display;
+
+   if (!dp || !mode_pclk_khz || !dp->connector) {
+   DRM_ERROR("invalid params\n");
+   return -EINVAL;
+   }
+
+   if (mode->clock > DP_MAX_PIXEL_CLK_KHZ)
+   return MODE_CLOCK_HIGH;
+
+   /*
+* The eDP controller currently does not have a reliable way of
+* enabling panel power to read sink capabilities. So, we rely
+* on the panel driver to populate only supported modes for now.
+*/
+   return MODE_OK;
+}
+
 static const struct drm_bridge_funcs edp_bridge_ops = {
.atomic_enable = edp_bridge_atomic_enable,
.atomic_disable = edp_bridge_atomic_disable,
.atomic_post_disable = edp_bridge_atomic_post_disable,
.mode_set = dp_bridge_mode_set,
-   .mode_valid = dp_bridge_mode_valid,
+   .mode_valid = edp_bridge_mode_valid,
.atomic_reset = drm_atomic_helper_bridge_reset,
.atomic_duplicate_state = drm_atomic_helper_bridge_duplicate_state,
.atomic_destroy_state = drm_atomic_helper_bridge_destroy_state,
-- 
2.7.4



[PATCH v13 11/13] drm/msm/disp/dpu: use atomic enable/disable callbacks for encoder functions

2023-02-12 Thread Vinod Polimera
Use atomic variants for encoder callback functions such that
certain states like self-refresh can be accessed as part of
enable/disable sequence.

Signed-off-by: Kalyan Thota 
Signed-off-by: Vinod Polimera 
Reviewed-by: Dmitry Baryshkov 
---
 drivers/gpu/drm/msm/disp/dpu1/dpu_encoder.c | 10 ++
 1 file changed, 6 insertions(+), 4 deletions(-)

diff --git a/drivers/gpu/drm/msm/disp/dpu1/dpu_encoder.c 
b/drivers/gpu/drm/msm/disp/dpu1/dpu_encoder.c
index c237003..01b7509 100644
--- a/drivers/gpu/drm/msm/disp/dpu1/dpu_encoder.c
+++ b/drivers/gpu/drm/msm/disp/dpu1/dpu_encoder.c
@@ -1171,7 +1171,8 @@ void dpu_encoder_virt_runtime_resume(struct drm_encoder 
*drm_enc)
mutex_unlock(_enc->enc_lock);
 }
 
-static void dpu_encoder_virt_enable(struct drm_encoder *drm_enc)
+static void dpu_encoder_virt_atomic_enable(struct drm_encoder *drm_enc,
+   struct drm_atomic_state *state)
 {
struct dpu_encoder_virt *dpu_enc = NULL;
int ret = 0;
@@ -1207,7 +1208,8 @@ static void dpu_encoder_virt_enable(struct drm_encoder 
*drm_enc)
mutex_unlock(_enc->enc_lock);
 }
 
-static void dpu_encoder_virt_disable(struct drm_encoder *drm_enc)
+static void dpu_encoder_virt_atomic_disable(struct drm_encoder *drm_enc,
+   struct drm_atomic_state *state)
 {
struct dpu_encoder_virt *dpu_enc = NULL;
int i = 0;
@@ -2388,8 +2390,8 @@ static void dpu_encoder_frame_done_timeout(struct 
timer_list *t)
 
 static const struct drm_encoder_helper_funcs dpu_encoder_helper_funcs = {
.atomic_mode_set = dpu_encoder_virt_atomic_mode_set,
-   .disable = dpu_encoder_virt_disable,
-   .enable = dpu_encoder_virt_enable,
+   .atomic_disable = dpu_encoder_virt_atomic_disable,
+   .atomic_enable = dpu_encoder_virt_atomic_enable,
.atomic_check = dpu_encoder_virt_atomic_check,
 };
 
-- 
2.7.4



[PATCH v13 09/13] drm/msm/dp: Add basic PSR support for eDP

2023-02-12 Thread Vinod Polimera
Add support for basic panel self refresh (PSR) feature for eDP.
Add a new interface to set PSR state in the sink from DPU.
Program the eDP controller to issue PSR enter and exit SDP to
the sink.

Signed-off-by: Sankeerth Billakanti 
Signed-off-by: Vinod Polimera 
Reviewed-by: Dmitry Baryshkov 
---
 drivers/gpu/drm/msm/dp/dp_catalog.c |  80 ++
 drivers/gpu/drm/msm/dp/dp_catalog.h |   4 ++
 drivers/gpu/drm/msm/dp/dp_ctrl.c|  80 ++
 drivers/gpu/drm/msm/dp/dp_ctrl.h|   3 +
 drivers/gpu/drm/msm/dp/dp_display.c |  19 ++
 drivers/gpu/drm/msm/dp/dp_display.h |   2 +
 drivers/gpu/drm/msm/dp/dp_drm.c | 133 +++-
 drivers/gpu/drm/msm/dp/dp_link.c|  36 ++
 drivers/gpu/drm/msm/dp/dp_panel.c   |  22 ++
 drivers/gpu/drm/msm/dp/dp_panel.h   |   6 ++
 drivers/gpu/drm/msm/dp/dp_reg.h |  27 
 11 files changed, 411 insertions(+), 1 deletion(-)

diff --git a/drivers/gpu/drm/msm/dp/dp_catalog.c 
b/drivers/gpu/drm/msm/dp/dp_catalog.c
index 676279d..c12a5d9 100644
--- a/drivers/gpu/drm/msm/dp/dp_catalog.c
+++ b/drivers/gpu/drm/msm/dp/dp_catalog.c
@@ -47,6 +47,14 @@
 #define DP_INTERRUPT_STATUS2_MASK \
(DP_INTERRUPT_STATUS2 << DP_INTERRUPT_STATUS_MASK_SHIFT)
 
+#define DP_INTERRUPT_STATUS4 \
+   (PSR_UPDATE_INT | PSR_CAPTURE_INT | PSR_EXIT_INT | \
+   PSR_UPDATE_ERROR_INT | PSR_WAKE_ERROR_INT)
+
+#define DP_INTERRUPT_MASK4 \
+   (PSR_UPDATE_MASK | PSR_CAPTURE_MASK | PSR_EXIT_MASK | \
+   PSR_UPDATE_ERROR_MASK | PSR_WAKE_ERROR_MASK)
+
 struct dp_catalog_private {
struct device *dev;
struct drm_device *drm_dev;
@@ -359,6 +367,23 @@ void dp_catalog_ctrl_lane_mapping(struct dp_catalog 
*dp_catalog)
ln_mapping);
 }
 
+void dp_catalog_ctrl_psr_mainlink_enable(struct dp_catalog *dp_catalog,
+   bool enable)
+{
+   u32 val;
+   struct dp_catalog_private *catalog = container_of(dp_catalog,
+   struct dp_catalog_private, dp_catalog);
+
+   val = dp_read_link(catalog, REG_DP_MAINLINK_CTRL);
+
+   if (enable)
+   val |= DP_MAINLINK_CTRL_ENABLE;
+   else
+   val &= ~DP_MAINLINK_CTRL_ENABLE;
+
+   dp_write_link(catalog, REG_DP_MAINLINK_CTRL, val);
+}
+
 void dp_catalog_ctrl_mainlink_ctrl(struct dp_catalog *dp_catalog,
bool enable)
 {
@@ -610,6 +635,47 @@ void dp_catalog_ctrl_hpd_config(struct dp_catalog 
*dp_catalog)
dp_write_aux(catalog, REG_DP_DP_HPD_CTRL, DP_DP_HPD_CTRL_HPD_EN);
 }
 
+static void dp_catalog_enable_sdp(struct dp_catalog_private *catalog)
+{
+   /* trigger sdp */
+   dp_write_link(catalog, MMSS_DP_SDP_CFG3, UPDATE_SDP);
+   dp_write_link(catalog, MMSS_DP_SDP_CFG3, 0x0);
+}
+
+void dp_catalog_ctrl_config_psr(struct dp_catalog *dp_catalog)
+{
+   struct dp_catalog_private *catalog = container_of(dp_catalog,
+   struct dp_catalog_private, dp_catalog);
+   u32 config;
+
+   /* enable PSR1 function */
+   config = dp_read_link(catalog, REG_PSR_CONFIG);
+   config |= PSR1_SUPPORTED;
+   dp_write_link(catalog, REG_PSR_CONFIG, config);
+
+   dp_write_ahb(catalog, REG_DP_INTR_MASK4, DP_INTERRUPT_MASK4);
+   dp_catalog_enable_sdp(catalog);
+}
+
+void dp_catalog_ctrl_set_psr(struct dp_catalog *dp_catalog, bool enter)
+{
+   struct dp_catalog_private *catalog = container_of(dp_catalog,
+   struct dp_catalog_private, dp_catalog);
+   u32 cmd;
+
+   cmd = dp_read_link(catalog, REG_PSR_CMD);
+
+   cmd &= ~(PSR_ENTER | PSR_EXIT);
+
+   if (enter)
+   cmd |= PSR_ENTER;
+   else
+   cmd |= PSR_EXIT;
+
+   dp_catalog_enable_sdp(catalog);
+   dp_write_link(catalog, REG_PSR_CMD, cmd);
+}
+
 u32 dp_catalog_link_is_connected(struct dp_catalog *dp_catalog)
 {
struct dp_catalog_private *catalog = container_of(dp_catalog,
@@ -645,6 +711,20 @@ u32 dp_catalog_hpd_get_intr_status(struct dp_catalog 
*dp_catalog)
return isr & (mask | ~DP_DP_HPD_INT_MASK);
 }
 
+u32 dp_catalog_ctrl_read_psr_interrupt_status(struct dp_catalog *dp_catalog)
+{
+   struct dp_catalog_private *catalog = container_of(dp_catalog,
+   struct dp_catalog_private, dp_catalog);
+   u32 intr, intr_ack;
+
+   intr = dp_read_ahb(catalog, REG_DP_INTR_STATUS4);
+   intr_ack = (intr & DP_INTERRUPT_STATUS4)
+   << DP_INTERRUPT_STATUS_ACK_SHIFT;
+   dp_write_ahb(catalog, REG_DP_INTR_STATUS4, intr_ack);
+
+   return intr;
+}
+
 int dp_catalog_ctrl_get_interrupt(struct dp_catalog *dp_catalog)
 {
struct dp_catalog_private *catalog = container_of(dp_catalog,
diff --git a/drivers/gpu/drm/msm/dp/dp_catalog.h 
b/drivers/gpu/drm/msm/dp/dp_catalog.h
index 1f717f4..2174bb5 100644
--- 

[PATCH v13 08/13] drm/msm/dp: use atomic callbacks for DP bridge ops

2023-02-12 Thread Vinod Polimera
Use atomic variants for DP bridge callback functions so that
the atomic state can be accessed in the interface drivers.
The atomic state will help the driver find out if the display
is in self refresh state.

Signed-off-by: Sankeerth Billakanti 
Signed-off-by: Vinod Polimera 
Reviewed-by: Dmitry Baryshkov 
Reviewed-by: Douglas Anderson 
---
 drivers/gpu/drm/msm/dp/dp_display.c | 9 ++---
 drivers/gpu/drm/msm/dp/dp_drm.c | 6 +++---
 drivers/gpu/drm/msm/dp/dp_drm.h | 9 ++---
 3 files changed, 15 insertions(+), 9 deletions(-)

diff --git a/drivers/gpu/drm/msm/dp/dp_display.c 
b/drivers/gpu/drm/msm/dp/dp_display.c
index bde1a7c..985287e 100644
--- a/drivers/gpu/drm/msm/dp/dp_display.c
+++ b/drivers/gpu/drm/msm/dp/dp_display.c
@@ -1652,7 +1652,8 @@ int msm_dp_modeset_init(struct msm_dp *dp_display, struct 
drm_device *dev,
return 0;
 }
 
-void dp_bridge_enable(struct drm_bridge *drm_bridge)
+void dp_bridge_atomic_enable(struct drm_bridge *drm_bridge,
+struct drm_bridge_state *old_bridge_state)
 {
struct msm_dp_bridge *dp_bridge = to_dp_bridge(drm_bridge);
struct msm_dp *dp = dp_bridge->dp_display;
@@ -1707,7 +1708,8 @@ void dp_bridge_enable(struct drm_bridge *drm_bridge)
mutex_unlock(_display->event_mutex);
 }
 
-void dp_bridge_disable(struct drm_bridge *drm_bridge)
+void dp_bridge_atomic_disable(struct drm_bridge *drm_bridge,
+ struct drm_bridge_state *old_bridge_state)
 {
struct msm_dp_bridge *dp_bridge = to_dp_bridge(drm_bridge);
struct msm_dp *dp = dp_bridge->dp_display;
@@ -1718,7 +1720,8 @@ void dp_bridge_disable(struct drm_bridge *drm_bridge)
dp_ctrl_push_idle(dp_display->ctrl);
 }
 
-void dp_bridge_post_disable(struct drm_bridge *drm_bridge)
+void dp_bridge_atomic_post_disable(struct drm_bridge *drm_bridge,
+  struct drm_bridge_state *old_bridge_state)
 {
struct msm_dp_bridge *dp_bridge = to_dp_bridge(drm_bridge);
struct msm_dp *dp = dp_bridge->dp_display;
diff --git a/drivers/gpu/drm/msm/dp/dp_drm.c b/drivers/gpu/drm/msm/dp/dp_drm.c
index 275370f..3252d50 100644
--- a/drivers/gpu/drm/msm/dp/dp_drm.c
+++ b/drivers/gpu/drm/msm/dp/dp_drm.c
@@ -94,9 +94,9 @@ static const struct drm_bridge_funcs dp_bridge_ops = {
.atomic_duplicate_state = drm_atomic_helper_bridge_duplicate_state,
.atomic_destroy_state   = drm_atomic_helper_bridge_destroy_state,
.atomic_reset   = drm_atomic_helper_bridge_reset,
-   .enable   = dp_bridge_enable,
-   .disable  = dp_bridge_disable,
-   .post_disable = dp_bridge_post_disable,
+   .atomic_enable  = dp_bridge_atomic_enable,
+   .atomic_disable = dp_bridge_atomic_disable,
+   .atomic_post_disable= dp_bridge_atomic_post_disable,
.mode_set = dp_bridge_mode_set,
.mode_valid   = dp_bridge_mode_valid,
.get_modes= dp_bridge_get_modes,
diff --git a/drivers/gpu/drm/msm/dp/dp_drm.h b/drivers/gpu/drm/msm/dp/dp_drm.h
index 250f7c6..afe79b8 100644
--- a/drivers/gpu/drm/msm/dp/dp_drm.h
+++ b/drivers/gpu/drm/msm/dp/dp_drm.h
@@ -23,9 +23,12 @@ struct drm_connector *dp_drm_connector_init(struct msm_dp 
*dp_display, struct dr
 struct drm_bridge *dp_bridge_init(struct msm_dp *dp_display, struct drm_device 
*dev,
struct drm_encoder *encoder);
 
-void dp_bridge_enable(struct drm_bridge *drm_bridge);
-void dp_bridge_disable(struct drm_bridge *drm_bridge);
-void dp_bridge_post_disable(struct drm_bridge *drm_bridge);
+void dp_bridge_atomic_enable(struct drm_bridge *drm_bridge,
+struct drm_bridge_state *old_bridge_state);
+void dp_bridge_atomic_disable(struct drm_bridge *drm_bridge,
+ struct drm_bridge_state *old_bridge_state);
+void dp_bridge_atomic_post_disable(struct drm_bridge *drm_bridge,
+  struct drm_bridge_state *old_bridge_state);
 enum drm_mode_status dp_bridge_mode_valid(struct drm_bridge *bridge,
  const struct drm_display_info *info,
  const struct drm_display_mode *mode);
-- 
2.7.4



[PATCH v13 06/13] drm/msm/disp/dpu: wait for extra vsync till timing engine status is disabled

2023-02-12 Thread Vinod Polimera
There can be a race between timing gen disable and vblank irq. The
wait post timing gen disable may return early but intf disable sequence
might not be completed. Ensure that, intf status is disabled before
we retire the function.

Signed-off-by: Vinod Polimera 
Reviewed-by: Dmitry Baryshkov 
---
 .../gpu/drm/msm/disp/dpu1/dpu_encoder_phys_vid.c| 21 +
 1 file changed, 21 insertions(+)

diff --git a/drivers/gpu/drm/msm/disp/dpu1/dpu_encoder_phys_vid.c 
b/drivers/gpu/drm/msm/disp/dpu1/dpu_encoder_phys_vid.c
index 48c4810..0396084 100644
--- a/drivers/gpu/drm/msm/disp/dpu1/dpu_encoder_phys_vid.c
+++ b/drivers/gpu/drm/msm/disp/dpu1/dpu_encoder_phys_vid.c
@@ -523,6 +523,7 @@ static void dpu_encoder_phys_vid_disable(struct 
dpu_encoder_phys *phys_enc)
 {
unsigned long lock_flags;
int ret;
+   struct intf_status intf_status = {0};
 
if (!phys_enc->parent || !phys_enc->parent->dev) {
DPU_ERROR("invalid encoder/device\n");
@@ -567,6 +568,26 @@ static void dpu_encoder_phys_vid_disable(struct 
dpu_encoder_phys *phys_enc)
}
}
 
+   if (phys_enc->hw_intf && phys_enc->hw_intf->ops.get_status)
+   phys_enc->hw_intf->ops.get_status(phys_enc->hw_intf, 
_status);
+
+   /*
+* Wait for a vsync if timing en status is on after timing engine
+* is disabled.
+*/
+   if (intf_status.is_en && dpu_encoder_phys_vid_is_master(phys_enc)) {
+   spin_lock_irqsave(phys_enc->enc_spinlock, lock_flags);
+   dpu_encoder_phys_inc_pending(phys_enc);
+   spin_unlock_irqrestore(phys_enc->enc_spinlock, lock_flags);
+   ret = dpu_encoder_phys_vid_wait_for_vblank(phys_enc);
+   if (ret) {
+   atomic_set(_enc->pending_kickoff_cnt, 0);
+   DRM_ERROR("wait disable failed: id:%u intf:%d ret:%d\n",
+ DRMID(phys_enc->parent),
+ phys_enc->hw_intf->idx - INTF_0, ret);
+   }
+   }
+
phys_enc->enable_state = DPU_ENC_DISABLED;
 }
 
-- 
2.7.4



[PATCH v13 07/13] drm/msm/disp/dpu: reset the datapath after timing engine disable

2023-02-12 Thread Vinod Polimera
Reset the datapath after disabling the timing gen, such that
it can start on a clean slate when the intf is enabled back.
This was a recommended sequence from the DPU HW programming guide.

Signed-off-by: Vinod Polimera 
Reviewed-by: Dmitry Baryshkov 
---
 drivers/gpu/drm/msm/disp/dpu1/dpu_encoder_phys_vid.c | 1 +
 1 file changed, 1 insertion(+)

diff --git a/drivers/gpu/drm/msm/disp/dpu1/dpu_encoder_phys_vid.c 
b/drivers/gpu/drm/msm/disp/dpu1/dpu_encoder_phys_vid.c
index 0396084..3a37429 100644
--- a/drivers/gpu/drm/msm/disp/dpu1/dpu_encoder_phys_vid.c
+++ b/drivers/gpu/drm/msm/disp/dpu1/dpu_encoder_phys_vid.c
@@ -588,6 +588,7 @@ static void dpu_encoder_phys_vid_disable(struct 
dpu_encoder_phys *phys_enc)
}
}
 
+   dpu_encoder_helper_phys_cleanup(phys_enc);
phys_enc->enable_state = DPU_ENC_DISABLED;
 }
 
-- 
2.7.4



[PATCH v13 05/13] drm/msm/disp/dpu: get timing engine status from intf status register

2023-02-12 Thread Vinod Polimera
Recommended way of reading the interface timing gen status is via
status register. Timing gen status register will give a reliable status
of the interface especially during ON/OFF transitions. This support was
added from DPU version 5.0.0.

Signed-off-by: Vinod Polimera 
Reviewed-by: Dmitry Baryshkov 
---
 drivers/gpu/drm/msm/disp/dpu1/dpu_hw_catalog.c |  3 ++-
 drivers/gpu/drm/msm/disp/dpu1/dpu_hw_catalog.h | 12 +++-
 drivers/gpu/drm/msm/disp/dpu1/dpu_hw_intf.c|  8 +++-
 3 files changed, 16 insertions(+), 7 deletions(-)

diff --git a/drivers/gpu/drm/msm/disp/dpu1/dpu_hw_catalog.c 
b/drivers/gpu/drm/msm/disp/dpu1/dpu_hw_catalog.c
index cf053e8..85b29d6 100644
--- a/drivers/gpu/drm/msm/disp/dpu1/dpu_hw_catalog.c
+++ b/drivers/gpu/drm/msm/disp/dpu1/dpu_hw_catalog.c
@@ -78,7 +78,8 @@
 
 #define INTF_SDM845_MASK (0)
 
-#define INTF_SC7180_MASK BIT(DPU_INTF_INPUT_CTRL) | BIT(DPU_INTF_TE)
+#define INTF_SC7180_MASK \
+   (BIT(DPU_INTF_INPUT_CTRL) | BIT(DPU_INTF_TE) | 
BIT(DPU_INTF_STATUS_SUPPORTED))
 
 #define INTF_SC7280_MASK INTF_SC7180_MASK | BIT(DPU_DATA_HCTL_EN)
 
diff --git a/drivers/gpu/drm/msm/disp/dpu1/dpu_hw_catalog.h 
b/drivers/gpu/drm/msm/disp/dpu1/dpu_hw_catalog.h
index ddab9ca..08cd1a1 100644
--- a/drivers/gpu/drm/msm/disp/dpu1/dpu_hw_catalog.h
+++ b/drivers/gpu/drm/msm/disp/dpu1/dpu_hw_catalog.h
@@ -213,17 +213,19 @@ enum {
 
 /**
  * INTF sub-blocks
- * @DPU_INTF_INPUT_CTRL Supports the setting of pp block from which
- *  pixel data arrives to this INTF
- * @DPU_INTF_TE INTF block has TE configuration support
- * @DPU_DATA_HCTL_ENAllows data to be transferred at different rate
-than video timing
+ * @DPU_INTF_INPUT_CTRL Supports the setting of pp block from which
+ *  pixel data arrives to this INTF
+ * @DPU_INTF_TE INTF block has TE configuration support
+ * @DPU_DATA_HCTL_ENAllows data to be transferred at different 
rate
+ *  than video timing
+ * @DPU_INTF_STATUS_SUPPORTED   INTF block has INTF_STATUS register
  * @DPU_INTF_MAX
  */
 enum {
DPU_INTF_INPUT_CTRL = 0x1,
DPU_INTF_TE,
DPU_DATA_HCTL_EN,
+   DPU_INTF_STATUS_SUPPORTED,
DPU_INTF_MAX
 };
 
diff --git a/drivers/gpu/drm/msm/disp/dpu1/dpu_hw_intf.c 
b/drivers/gpu/drm/msm/disp/dpu1/dpu_hw_intf.c
index 7ce66bf..84ee2ef 100644
--- a/drivers/gpu/drm/msm/disp/dpu1/dpu_hw_intf.c
+++ b/drivers/gpu/drm/msm/disp/dpu1/dpu_hw_intf.c
@@ -62,6 +62,7 @@
 #define   INTF_LINE_COUNT   0x0B0
 
 #define   INTF_MUX  0x25C
+#define   INTF_STATUS   0x26C
 
 #define INTF_CFG_ACTIVE_H_EN   BIT(29)
 #define INTF_CFG_ACTIVE_V_EN   BIT(30)
@@ -297,8 +298,13 @@ static void dpu_hw_intf_get_status(
struct intf_status *s)
 {
struct dpu_hw_blk_reg_map *c = >hw;
+   unsigned long cap = intf->cap->features;
+
+   if (cap & BIT(DPU_INTF_STATUS_SUPPORTED))
+   s->is_en = DPU_REG_READ(c, INTF_STATUS) & BIT(0);
+   else
+   s->is_en = DPU_REG_READ(c, INTF_TIMING_ENGINE_EN);
 
-   s->is_en = DPU_REG_READ(c, INTF_TIMING_ENGINE_EN);
s->is_prog_fetch_en = !!(DPU_REG_READ(c, INTF_CONFIG) & BIT(31));
if (s->is_en) {
s->frame_count = DPU_REG_READ(c, INTF_FRAME_COUNT);
-- 
2.7.4



[PATCH v13 04/13] drm/msm/disp/dpu: check for crtc enable rather than crtc active to release shared resources

2023-02-12 Thread Vinod Polimera
According to KMS documentation, The driver must not release any shared
resources if active is set to false but enable still true.

Fixes: ccc862b957c6 ("drm/msm/dpu: Fix reservation failures in modeset")
Signed-off-by: Vinod Polimera 
Reviewed-by: Dmitry Baryshkov 
---
 drivers/gpu/drm/msm/disp/dpu1/dpu_encoder.c | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/drivers/gpu/drm/msm/disp/dpu1/dpu_encoder.c 
b/drivers/gpu/drm/msm/disp/dpu1/dpu_encoder.c
index 758261e..c237003 100644
--- a/drivers/gpu/drm/msm/disp/dpu1/dpu_encoder.c
+++ b/drivers/gpu/drm/msm/disp/dpu1/dpu_encoder.c
@@ -652,7 +652,7 @@ static int dpu_encoder_virt_atomic_check(
if (drm_atomic_crtc_needs_modeset(crtc_state)) {
dpu_rm_release(global_state, drm_enc);
 
-   if (!crtc_state->active_changed || crtc_state->active)
+   if (!crtc_state->active_changed || crtc_state->enable)
ret = dpu_rm_reserve(_kms->rm, global_state,
drm_enc, crtc_state, topology);
}
-- 
2.7.4



[PATCH v13 02/13] drm/bridge: use atomic enable/disable callbacks for panel bridge

2023-02-12 Thread Vinod Polimera
Use atomic variants for panel bridge callback functions such that
certain states like self-refresh can be accessed as part of
enable/disable sequence.

Signed-off-by: Sankeerth Billakanti 
Signed-off-by: Vinod Polimera 
Reviewed-by: Dmitry Baryshkov 
Reviewed-by: Daniel Vetter 
---
 drivers/gpu/drm/bridge/panel.c | 20 
 1 file changed, 12 insertions(+), 8 deletions(-)

diff --git a/drivers/gpu/drm/bridge/panel.c b/drivers/gpu/drm/bridge/panel.c
index e8aae3c..04e9fb0 100644
--- a/drivers/gpu/drm/bridge/panel.c
+++ b/drivers/gpu/drm/bridge/panel.c
@@ -109,28 +109,32 @@ static void panel_bridge_detach(struct drm_bridge *bridge)
drm_connector_cleanup(connector);
 }
 
-static void panel_bridge_pre_enable(struct drm_bridge *bridge)
+static void panel_bridge_atomic_pre_enable(struct drm_bridge *bridge,
+   struct drm_bridge_state *old_bridge_state)
 {
struct panel_bridge *panel_bridge = drm_bridge_to_panel_bridge(bridge);
 
drm_panel_prepare(panel_bridge->panel);
 }
 
-static void panel_bridge_enable(struct drm_bridge *bridge)
+static void panel_bridge_atomic_enable(struct drm_bridge *bridge,
+   struct drm_bridge_state *old_bridge_state)
 {
struct panel_bridge *panel_bridge = drm_bridge_to_panel_bridge(bridge);
 
drm_panel_enable(panel_bridge->panel);
 }
 
-static void panel_bridge_disable(struct drm_bridge *bridge)
+static void panel_bridge_atomic_disable(struct drm_bridge *bridge,
+   struct drm_bridge_state *old_bridge_state)
 {
struct panel_bridge *panel_bridge = drm_bridge_to_panel_bridge(bridge);
 
drm_panel_disable(panel_bridge->panel);
 }
 
-static void panel_bridge_post_disable(struct drm_bridge *bridge)
+static void panel_bridge_atomic_post_disable(struct drm_bridge *bridge,
+   struct drm_bridge_state *old_bridge_state)
 {
struct panel_bridge *panel_bridge = drm_bridge_to_panel_bridge(bridge);
 
@@ -159,10 +163,10 @@ static void panel_bridge_debugfs_init(struct drm_bridge 
*bridge,
 static const struct drm_bridge_funcs panel_bridge_bridge_funcs = {
.attach = panel_bridge_attach,
.detach = panel_bridge_detach,
-   .pre_enable = panel_bridge_pre_enable,
-   .enable = panel_bridge_enable,
-   .disable = panel_bridge_disable,
-   .post_disable = panel_bridge_post_disable,
+   .atomic_pre_enable = panel_bridge_atomic_pre_enable,
+   .atomic_enable = panel_bridge_atomic_enable,
+   .atomic_disable = panel_bridge_atomic_disable,
+   .atomic_post_disable = panel_bridge_atomic_post_disable,
.get_modes = panel_bridge_get_modes,
.atomic_reset = drm_atomic_helper_bridge_reset,
.atomic_duplicate_state = drm_atomic_helper_bridge_duplicate_state,
-- 
2.7.4



[PATCH v13 03/13] drm/bridge: add psr support for panel bridge callbacks

2023-02-12 Thread Vinod Polimera
This change will handle the psr entry exit cases in the panel
bridge atomic callback functions. For example, the panel power
should not turn off if the panel is entering psr.

Signed-off-by: Sankeerth Billakanti 
Signed-off-by: Vinod Polimera 
Reviewed-by: Daniel Vetter 
---
 drivers/gpu/drm/bridge/panel.c | 48 ++
 1 file changed, 48 insertions(+)

diff --git a/drivers/gpu/drm/bridge/panel.c b/drivers/gpu/drm/bridge/panel.c
index 04e9fb0..a2c6f30 100644
--- a/drivers/gpu/drm/bridge/panel.c
+++ b/drivers/gpu/drm/bridge/panel.c
@@ -113,6 +113,18 @@ static void panel_bridge_atomic_pre_enable(struct 
drm_bridge *bridge,
struct drm_bridge_state *old_bridge_state)
 {
struct panel_bridge *panel_bridge = drm_bridge_to_panel_bridge(bridge);
+   struct drm_atomic_state *atomic_state = old_bridge_state->base.state;
+   struct drm_encoder *encoder = bridge->encoder;
+   struct drm_crtc *crtc;
+   struct drm_crtc_state *old_crtc_state;
+
+   crtc = drm_atomic_get_new_crtc_for_encoder(atomic_state, encoder);
+   if (!crtc)
+   return;
+
+   old_crtc_state = drm_atomic_get_old_crtc_state(atomic_state, crtc);
+   if (old_crtc_state && old_crtc_state->self_refresh_active)
+   return;
 
drm_panel_prepare(panel_bridge->panel);
 }
@@ -121,6 +133,18 @@ static void panel_bridge_atomic_enable(struct drm_bridge 
*bridge,
struct drm_bridge_state *old_bridge_state)
 {
struct panel_bridge *panel_bridge = drm_bridge_to_panel_bridge(bridge);
+   struct drm_atomic_state *atomic_state = old_bridge_state->base.state;
+   struct drm_encoder *encoder = bridge->encoder;
+   struct drm_crtc *crtc;
+   struct drm_crtc_state *old_crtc_state;
+
+   crtc = drm_atomic_get_new_crtc_for_encoder(atomic_state, encoder);
+   if (!crtc)
+   return;
+
+   old_crtc_state = drm_atomic_get_old_crtc_state(atomic_state, crtc);
+   if (old_crtc_state && old_crtc_state->self_refresh_active)
+   return;
 
drm_panel_enable(panel_bridge->panel);
 }
@@ -129,6 +153,18 @@ static void panel_bridge_atomic_disable(struct drm_bridge 
*bridge,
struct drm_bridge_state *old_bridge_state)
 {
struct panel_bridge *panel_bridge = drm_bridge_to_panel_bridge(bridge);
+   struct drm_atomic_state *atomic_state = old_bridge_state->base.state;
+   struct drm_encoder *encoder = bridge->encoder;
+   struct drm_crtc *crtc;
+   struct drm_crtc_state *new_crtc_state;
+
+   crtc = drm_atomic_get_old_crtc_for_encoder(atomic_state, encoder);
+   if (!crtc)
+   return;
+
+   new_crtc_state = drm_atomic_get_new_crtc_state(atomic_state, crtc);
+   if (new_crtc_state && new_crtc_state->self_refresh_active)
+   return;
 
drm_panel_disable(panel_bridge->panel);
 }
@@ -137,6 +173,18 @@ static void panel_bridge_atomic_post_disable(struct 
drm_bridge *bridge,
struct drm_bridge_state *old_bridge_state)
 {
struct panel_bridge *panel_bridge = drm_bridge_to_panel_bridge(bridge);
+   struct drm_atomic_state *atomic_state = old_bridge_state->base.state;
+   struct drm_encoder *encoder = bridge->encoder;
+   struct drm_crtc *crtc;
+   struct drm_crtc_state *new_crtc_state;
+
+   crtc = drm_atomic_get_old_crtc_for_encoder(atomic_state, encoder);
+   if (!crtc)
+   return;
+
+   new_crtc_state = drm_atomic_get_new_crtc_state(atomic_state, crtc);
+   if (new_crtc_state && new_crtc_state->self_refresh_active)
+   return;
 
drm_panel_unprepare(panel_bridge->panel);
 }
-- 
2.7.4



[PATCH v13 01/13] drm: add helper functions to retrieve old and new crtc

2023-02-12 Thread Vinod Polimera
Add new helper functions, drm_atomic_get_old_crtc_for_encoder
and drm_atomic_get_new_crtc_for_encoder to retrieve the
corresponding crtc for the encoder.

Signed-off-by: Sankeerth Billakanti 
Signed-off-by: Vinod Polimera 
Reviewed-by: Douglas Anderson 
Reviewed-by: Daniel Vetter 
---
 drivers/gpu/drm/drm_atomic.c | 60 
 include/drm/drm_atomic.h |  7 ++
 2 files changed, 67 insertions(+)

diff --git a/drivers/gpu/drm/drm_atomic.c b/drivers/gpu/drm/drm_atomic.c
index 5457c02..7cc39f6 100644
--- a/drivers/gpu/drm/drm_atomic.c
+++ b/drivers/gpu/drm/drm_atomic.c
@@ -985,6 +985,66 @@ drm_atomic_get_new_connector_for_encoder(const struct 
drm_atomic_state *state,
 EXPORT_SYMBOL(drm_atomic_get_new_connector_for_encoder);
 
 /**
+ * drm_atomic_get_old_crtc_for_encoder - Get old crtc for an encoder
+ * @state: Atomic state
+ * @encoder: The encoder to fetch the crtc state for
+ *
+ * This function finds and returns the crtc that was connected to @encoder
+ * as specified by the @state.
+ *
+ * Returns: The old crtc connected to @encoder, or NULL if the encoder is
+ * not connected.
+ */
+struct drm_crtc *
+drm_atomic_get_old_crtc_for_encoder(struct drm_atomic_state *state,
+   struct drm_encoder *encoder)
+{
+   struct drm_connector *connector;
+   struct drm_connector_state *conn_state;
+
+   connector = drm_atomic_get_old_connector_for_encoder(state, encoder);
+   if (!connector)
+   return NULL;
+
+   conn_state = drm_atomic_get_old_connector_state(state, connector);
+   if (!conn_state)
+   return NULL;
+
+   return conn_state->crtc;
+}
+EXPORT_SYMBOL(drm_atomic_get_old_crtc_for_encoder);
+
+/**
+ * drm_atomic_get_new_crtc_for_encoder - Get new crtc for an encoder
+ * @state: Atomic state
+ * @encoder: The encoder to fetch the crtc state for
+ *
+ * This function finds and returns the crtc that will be connected to @encoder
+ * as specified by the @state.
+ *
+ * Returns: The new crtc connected to @encoder, or NULL if the encoder is
+ * not connected.
+ */
+struct drm_crtc *
+drm_atomic_get_new_crtc_for_encoder(struct drm_atomic_state *state,
+   struct drm_encoder *encoder)
+{
+   struct drm_connector *connector;
+   struct drm_connector_state *conn_state;
+
+   connector = drm_atomic_get_new_connector_for_encoder(state, encoder);
+   if (!connector)
+   return NULL;
+
+   conn_state = drm_atomic_get_new_connector_state(state, connector);
+   if (!conn_state)
+   return NULL;
+
+   return conn_state->crtc;
+}
+EXPORT_SYMBOL(drm_atomic_get_new_crtc_for_encoder);
+
+/**
  * drm_atomic_get_connector_state - get connector state
  * @state: global atomic state object
  * @connector: connector to get state object for
diff --git a/include/drm/drm_atomic.h b/include/drm/drm_atomic.h
index 92586ab..9a022ca 100644
--- a/include/drm/drm_atomic.h
+++ b/include/drm/drm_atomic.h
@@ -528,6 +528,13 @@ struct drm_connector *
 drm_atomic_get_new_connector_for_encoder(const struct drm_atomic_state *state,
 struct drm_encoder *encoder);
 
+struct drm_crtc *
+drm_atomic_get_old_crtc_for_encoder(struct drm_atomic_state *state,
+struct drm_encoder *encoder);
+struct drm_crtc *
+drm_atomic_get_new_crtc_for_encoder(struct drm_atomic_state *state,
+struct drm_encoder *encoder);
+
 /**
  * drm_atomic_get_existing_crtc_state - get CRTC state, if it exists
  * @state: global atomic state object
-- 
2.7.4



[PATCH v13 00/13] Add PSR support for eDP

2023-02-12 Thread Vinod Polimera
Changes in v2:
  - Use dp bridge to set psr entry/exit instead of dpu_enocder.
  - Don't modify whitespaces.
  - Set self refresh aware from atomic_check.
  - Set self refresh aware only if psr is supported.
  - Provide a stub for msm_dp_display_set_psr.
  - Move dp functions to bridge code.

Changes in v3:
  - Change callback names to reflect atomic interfaces.
  - Move bridge callback change to separate patch as suggested by Dmitry.
  - Remove psr function declaration from msm_drv.h.
  - Set self_refresh_aware flag only if psr is supported.
  - Modify the variable names to simpler form.
  - Define bit fields for PSR settings.
  - Add comments explaining the steps to enter/exit psr.
  - Change DRM_INFO to drm_dbg_db. 

Changes in v4:
  - Move the get crtc functions to drm_atomic.
  - Add atomic functions for DP bridge too.
  - Add ternary operator to choose eDP or DP ops.
  - Return true/false instead of 1/0.
  - mode_valid missing in the eDP bridge ops.
  - Move the functions to get crtc into drm_atomic.c.
  - Fix compilation issues.
  - Remove dpu_assign_crtc and get crtc from drm_enc instead of dpu_enc.
  - Check for crtc state enable while reserving resources.

Changes in v5:
  - Move the mode_valid changes into a different patch.
  - Complete psr_op_comp only when isr is set.
  - Move the DP atomic callback changes to a different patch.
  - Get crtc from drm connector state crtc.
  - Move to separate patch for check for crtc state enable while
reserving resources.

Changes in v6:
  - Remove crtc from dpu_encoder_virt struct.
  - fix crtc check during vblank toggle crtc.
  - Misc changes. 

Changes in v7:
  - Add fix for underrun issue on kasan build.

Changes in v8:
  - Drop the enc spinlock as it won't serve any purpose in
protetcing conn state.(Dmitry/Doug)

Changes in v9:
  - Update commit message and fix alignment using spaces.(Marijn)
  - Misc changes.(Marijn)

Changes in v10:
  - Get crtc cached in dpu_enc during obj init.(Dmitry)

Changes in v11:
  - Remove crtc cached in dpu_enc during obj init.
  - Update dpu_enc crtc state on crtc enable/disable during self refresh.

Changes in v12:
  - Update sc7180 intf mask to get intf timing gen status
based on DPU_INTF_STATUS_SUPPORTED bit.(Dmitry)
  - Remove "clear active interface in the datapath cleanup" change
as it is already included.

Changes in v13:
  - Move core changes to top of the series.(Dmitry)
  - Drop self refresh aware disable change after psr entry.(Dmitry)

Vinod Polimera (13):
  drm: add helper functions to retrieve old and new crtc
  drm/bridge: use atomic enable/disable callbacks for panel bridge
  drm/bridge: add psr support for panel bridge callbacks
  drm/msm/disp/dpu: check for crtc enable rather than crtc active to
release shared resources
  drm/msm/disp/dpu: get timing engine status from intf status register
  drm/msm/disp/dpu: wait for extra vsync till timing engine status is
disabled
  drm/msm/disp/dpu: reset the datapath after timing engine disable
  drm/msm/dp: use atomic callbacks for DP bridge ops
  drm/msm/dp: Add basic PSR support for eDP
  drm/msm/dp: use the eDP bridge ops to validate eDP modes
  drm/msm/disp/dpu: use atomic enable/disable callbacks for encoder
functions
  drm/msm/disp/dpu: add PSR support for eDP interface in dpu driver
  drm/msm/disp/dpu: update dpu_enc crtc state on crtc enable/disable
during self refresh

 drivers/gpu/drm/bridge/panel.c |  68 +++-
 drivers/gpu/drm/drm_atomic.c   |  60 
 drivers/gpu/drm/msm/disp/dpu1/dpu_crtc.c   |  40 -
 drivers/gpu/drm/msm/disp/dpu1/dpu_encoder.c|  26 +++-
 .../gpu/drm/msm/disp/dpu1/dpu_encoder_phys_vid.c   |  22 +++
 drivers/gpu/drm/msm/disp/dpu1/dpu_hw_catalog.c |   3 +-
 drivers/gpu/drm/msm/disp/dpu1/dpu_hw_catalog.h |  12 +-
 drivers/gpu/drm/msm/disp/dpu1/dpu_hw_intf.c|   8 +-
 drivers/gpu/drm/msm/disp/dpu1/dpu_kms.c|   2 +-
 drivers/gpu/drm/msm/dp/dp_catalog.c|  80 ++
 drivers/gpu/drm/msm/dp/dp_catalog.h|   4 +
 drivers/gpu/drm/msm/dp/dp_ctrl.c   |  80 ++
 drivers/gpu/drm/msm/dp/dp_ctrl.h   |   3 +
 drivers/gpu/drm/msm/dp/dp_display.c|  36 +++--
 drivers/gpu/drm/msm/dp/dp_display.h|   2 +
 drivers/gpu/drm/msm/dp/dp_drm.c| 171 -
 drivers/gpu/drm/msm/dp/dp_drm.h|   9 +-
 drivers/gpu/drm/msm/dp/dp_link.c   |  36 +
 drivers/gpu/drm/msm/dp/dp_panel.c  |  22 +++
 drivers/gpu/drm/msm/dp/dp_panel.h  |   6 +
 drivers/gpu/drm/msm/dp/dp_reg.h|  27 
 include/drm/drm_atomic.h   |   7 +
 22 files changed, 681 insertions(+), 43 deletions(-)

-- 
2.7.4



Re: [PATCH] drm/edid: Add Vive Pro 2 to non-desktop list

2023-02-12 Thread Dmitry Osipenko
Hi,

On 1/18/22 20:00, Yaroslav Bolyukin wrote:

Add a brief commit message, describing a user-visible effect of this
patch. Tell that this change prevents exposing headset as a regular
display to the system, while it will work with SteamVR.

> Signed-off-by: Yaroslav Bolyukin 
> ---
>  drivers/gpu/drm/drm_edid.c | 3 ++-
>  1 file changed, 2 insertions(+), 1 deletion(-)
> 
> diff --git a/drivers/gpu/drm/drm_edid.c b/drivers/gpu/drm/drm_edid.c
> index 12893e7be..fdb8f0a6f 100644
> --- a/drivers/gpu/drm/drm_edid.c
> +++ b/drivers/gpu/drm/drm_edid.c
> @@ -200,9 +200,10 @@ static const struct edid_quirk {
>   EDID_QUIRK('V', 'L', 'V', 0x91be, EDID_QUIRK_NON_DESKTOP),
>   EDID_QUIRK('V', 'L', 'V', 0x91bf, EDID_QUIRK_NON_DESKTOP),
>  
> - /* HTC Vive and Vive Pro VR Headsets */
> + /* HTC Vive, Vive Pro and Vive Pro 2 VR Headsets */

Nit: I'd keep the original comment, or change it to a generic "HTC VR
Headsets" to prevent further comment changes

>   EDID_QUIRK('H', 'V', 'R', 0xaa01, EDID_QUIRK_NON_DESKTOP),
>   EDID_QUIRK('H', 'V', 'R', 0xaa02, EDID_QUIRK_NON_DESKTOP),
> + EDID_QUIRK('H', 'V', 'R', 0xaa04, EDID_QUIRK_NON_DESKTOP),
>  
>   /* Oculus Rift DK1, DK2, CV1 and Rift S VR Headsets */
>   EDID_QUIRK('O', 'V', 'R', 0x0001, EDID_QUIRK_NON_DESKTOP),
> 
> base-commit: 99613159ad749543621da8238acf1a122880144e

Please send the v2 patch with the added EDID for Cosmos VR and the
addressed comments. Thanks!

-- 
Best regards,
Dmitry



Re: [PATCH 1/1] drm/panel: st7703: Fix resume of XBD599 panel

2023-02-12 Thread Ondřej Jirman
On Sun, Feb 12, 2023 at 01:08:29PM +0100, Frank Oltmanns wrote:
> In contrast to the JH057N panel, the XBD599 panel does not require a 20
> msec delay after initialization and exiting sleep mode. Therefore, move
> the delay into the already existing device specific initialization
> function.
> 
> Also, the timing contraints after entering and exiting sleep mode differ
> between the two panels:
>  - The JH057N requires a shorter delay than the XDB599 after waking up
>from sleep mode and before enabling the display.
>  - The XDB599 requires a delay in order to drain the display of charge,
>which is not required on the JH057N.

There's no difference between the panels here. It's a controller specified
requirement.

https://megous.com/dl/tmp/1ef533ed8a7ce841.png

60ms used in the driver between sleep out and display on is just
incorrect from the datasheet perspective.

You also have to wait 120ms after sleep in (or HW reset) and before shutting
down the panel. If you don't, after a bunch of cycles of this incorrect
power up/down sequence the panel will start blinking weirdly, and the incorrect
power up/down sequence without delays will not be able to recover it. You'll
have to let the panel sit for 5-10 minutes powered off before it starts to
behave itself again.

The documentation for sleep in specifies what's happening during sleep in,
and why this delay is necessary after sleep in:

https://megous.com/dl/tmp/2284b9d0f506b9b8.png

So there needs to be 120ms delay after sleep in and after sleep out,
regardless of which panel is driven by this controller, to ensure the panel
stays operational even when the user is quickly switching it on/off repeatedly.

So I don't think you should be doing panel specific quirks here.

regards,
o.

> Therefore, introduce panel specific functions for the delays.
> 
> The XDB599 does not require a 20 msec delay between the SETBGP and
> SETVCOM commands. Therefore, remove the delay from the device specific
> initialization function.
> 
> Signed-off-by: Frank Oltmanns 
> Cc: Ondrej Jirman 
> Reported-by: Samuel Holland 
> ---
>  drivers/gpu/drm/panel/panel-sitronix-st7703.c | 40 ---
>  1 file changed, 35 insertions(+), 5 deletions(-)
> 
> diff --git a/drivers/gpu/drm/panel/panel-sitronix-st7703.c 
> b/drivers/gpu/drm/panel/panel-sitronix-st7703.c
> index 6747ca237ced..a149341c4a8b 100644
> --- a/drivers/gpu/drm/panel/panel-sitronix-st7703.c
> +++ b/drivers/gpu/drm/panel/panel-sitronix-st7703.c
> @@ -66,6 +66,8 @@ struct st7703_panel_desc {
>   unsigned long mode_flags;
>   enum mipi_dsi_pixel_format format;
>   int (*init_sequence)(struct st7703 *ctx);
> + void (*wait_after_sleep_out)(void);
> + void (*drain_charge)(void);
>  };
>  
>  static inline struct st7703 *panel_to_st7703(struct drm_panel *panel)
> @@ -126,10 +128,24 @@ static int jh057n_init_sequence(struct st7703 *ctx)
>  0x18, 0x00, 0x09, 0x0E, 0x29, 0x2D, 0x3C, 
> 0x41,
>  0x37, 0x07, 0x0B, 0x0D, 0x10, 0x11, 0x0F, 
> 0x10,
>  0x11, 0x18);
> + msleep(20);
>  
>   return 0;
>  }
>  
> +static void jh057n_wait_after_sleep_out(void)
> +{
> + /*
> +  * Panel is operational 120 msec after reset, i.e. 60 msec after
> +  * sleep out.
> +  */
> + msleep(60);
> +}
> +
> +static void jh057n_drain_charge(void)
> +{
> +}
> +
>  static const struct drm_display_mode jh057n00900_mode = {
>   .hdisplay= 720,
>   .hsync_start = 720 + 90,
> @@ -152,6 +168,8 @@ static const struct st7703_panel_desc 
> jh057n00900_panel_desc = {
>   MIPI_DSI_MODE_VIDEO_BURST | MIPI_DSI_MODE_VIDEO_SYNC_PULSE,
>   .format = MIPI_DSI_FMT_RGB888,
>   .init_sequence = jh057n_init_sequence,
> + .wait_after_sleep_out = jh057n_wait_after_sleep_out,
> + .drain_charge = jh057n_drain_charge,
>  };
>  
>  static int xbd599_init_sequence(struct st7703 *ctx)
> @@ -273,7 +291,6 @@ static int xbd599_init_sequence(struct st7703 *ctx)
>   mipi_dsi_dcs_write_seq(dsi, ST7703_CMD_SETBGP,
>  0x07, /* VREF_SEL = 4.2V */
>  0x07  /* NVREF_SEL = 4.2V */);
> - msleep(20);
>  
>   mipi_dsi_dcs_write_seq(dsi, ST7703_CMD_SETVCOM,
>  0x2C, /* VCOMDC_F = -0.67V */
> @@ -315,6 +332,18 @@ static int xbd599_init_sequence(struct st7703 *ctx)
>   return 0;
>  }
>  
> +static void xbd599_wait_after_sleep_out(void)
> +{
> + msleep(120);
> +}
> +
> +static void xbd599_drain_charge(void)
> +{
> + /* Drain diplay of charge, to work correctly on next power on. */
> + msleep(120);
> +}
> +
> +
>  static const struct drm_display_mode xbd599_mode = {
>   .hdisplay= 720,
>   .hsync_start = 720 + 40,
> @@ -336,6 +365,8 @@ static const struct st7703_panel_desc xbd599_desc = {
>   .mode_flags = MIPI_DSI_MODE_VIDEO | MIPI_DSI_MODE_VIDEO_SYNC_PULSE,
>   .format = 

Re: [PATCH 0/1] drm/panel: st7703: Fix initialization failures on Xingbangda XBD599

2023-02-12 Thread Guido Günther
Hi Frank,

Thanks for giving this another spin!

On Sat, Feb 11, 2023 at 06:17:47PM +0100, Frank Oltmanns wrote:
> This patch fixes intermittent panel initialization failures and screen
> corruption during resume from sleep on panel xingbangda,xbd599 (e.g.
> used in PinePhone).
> 
> It was originally submitted by Ondrej Jirman in July 2020:
> https://lore.kernel.org/all/20200716123753.3552425-1-meg...@megous.com/
> 
> The original patchset contained two patches. One of them broke the panel
> on the Purism Librem 5.

Just for completeness: It's the Librem 5 Devkit, the Librem 5 uses the
mantix,mlaf057we51-x panel.

> This is the concluding message from Guido Günther in that thread:
> https://lore.kernel.org/all/20200801110409.ga6...@bogon.m.sigxcpu.org/#t
> 
> Guido wanted changes to the commit message. I updated it to adress his
> requests.
> 
> I send this patch in Ondřej's name with his consent.
> 
> The patch is based on drm-next.
> 
> Please let me know what you think.

I'll retest this on the devkit on the next days, might be a moment until
I get to that.

Cheers,
 -- Guido


[PATCH 2/2] char/agp: introduce asm-generic/agp.h

2023-02-12 Thread Mike Rapoport
From: "Mike Rapoport (IBM)" 

There are several architectures that duplicate definitions of
map_page_into_agp(), unmap_page_from_agp() and flush_agp_cache().

Define those in asm-generic/agp.h and use it instead of duplicated
per-architecture headers.

Signed-off-by: Mike Rapoport (IBM) 
---
 arch/alpha/include/asm/Kbuild |  1 +
 arch/alpha/include/asm/agp.h  | 13 
 arch/ia64/include/asm/Kbuild  |  1 +
 arch/ia64/include/asm/agp.h   | 21 ---
 arch/parisc/include/asm/Kbuild|  1 +
 arch/parisc/include/asm/agp.h | 15 -
 arch/powerpc/include/asm/Kbuild   |  1 +
 arch/sparc/include/asm/Kbuild |  1 +
 arch/sparc/include/asm/agp.h  | 11 --
 .../include/asm => include/asm-generic}/agp.h |  8 +++
 10 files changed, 8 insertions(+), 65 deletions(-)
 delete mode 100644 arch/alpha/include/asm/agp.h
 delete mode 100644 arch/ia64/include/asm/agp.h
 delete mode 100644 arch/parisc/include/asm/agp.h
 delete mode 100644 arch/sparc/include/asm/agp.h
 rename {arch/powerpc/include/asm => include/asm-generic}/agp.h (59%)

diff --git a/arch/alpha/include/asm/Kbuild b/arch/alpha/include/asm/Kbuild
index 42911c8340c7..54f5126628c6 100644
--- a/arch/alpha/include/asm/Kbuild
+++ b/arch/alpha/include/asm/Kbuild
@@ -1,6 +1,7 @@
 # SPDX-License-Identifier: GPL-2.0
 
 generated-y += syscall_table.h
+generic-y += agp.h
 generic-y += export.h
 generic-y += kvm_para.h
 generic-y += mcs_spinlock.h
diff --git a/arch/alpha/include/asm/agp.h b/arch/alpha/include/asm/agp.h
deleted file mode 100644
index 4197b3bc78ee..
--- a/arch/alpha/include/asm/agp.h
+++ /dev/null
@@ -1,13 +0,0 @@
-/* SPDX-License-Identifier: GPL-2.0 */
-#ifndef AGP_H
-#define AGP_H 1
-
-#include 
-
-/* dummy for now */
-
-#define map_page_into_agp(page)do { } while (0)
-#define unmap_page_from_agp(page)  do { } while (0)
-#define flush_agp_cache() mb()
-
-#endif
diff --git a/arch/ia64/include/asm/Kbuild b/arch/ia64/include/asm/Kbuild
index f994c1daf9d4..aefae2efde9f 100644
--- a/arch/ia64/include/asm/Kbuild
+++ b/arch/ia64/include/asm/Kbuild
@@ -1,5 +1,6 @@
 # SPDX-License-Identifier: GPL-2.0
 generated-y += syscall_table.h
+generic-y += agp.h
 generic-y += kvm_para.h
 generic-y += mcs_spinlock.h
 generic-y += vtime.h
diff --git a/arch/ia64/include/asm/agp.h b/arch/ia64/include/asm/agp.h
deleted file mode 100644
index f42c7dcb3d79..
--- a/arch/ia64/include/asm/agp.h
+++ /dev/null
@@ -1,21 +0,0 @@
-/* SPDX-License-Identifier: GPL-2.0 */
-#ifndef _ASM_IA64_AGP_H
-#define _ASM_IA64_AGP_H
-
-/*
- * IA-64 specific AGP definitions.
- *
- * Copyright (C) 2002-2003 Hewlett-Packard Co
- * David Mosberger-Tang 
- */
-
-/*
- * To avoid memory-attribute aliasing issues, we require that the AGPGART 
engine operate
- * in coherent mode, which lets us map the AGP memory as normal (write-back) 
memory
- * (unlike x86, where it gets mapped "write-coalescing").
- */
-#define map_page_into_agp(page)do { } while (0)
-#define unmap_page_from_agp(page)  do { } while (0)
-#define flush_agp_cache()  mb()
-
-#endif /* _ASM_IA64_AGP_H */
diff --git a/arch/parisc/include/asm/Kbuild b/arch/parisc/include/asm/Kbuild
index e6e7f74c8ac9..4fb596d94c89 100644
--- a/arch/parisc/include/asm/Kbuild
+++ b/arch/parisc/include/asm/Kbuild
@@ -1,6 +1,7 @@
 # SPDX-License-Identifier: GPL-2.0
 generated-y += syscall_table_32.h
 generated-y += syscall_table_64.h
+generic-y += agp.h
 generic-y += kvm_para.h
 generic-y += mcs_spinlock.h
 generic-y += user.h
diff --git a/arch/parisc/include/asm/agp.h b/arch/parisc/include/asm/agp.h
deleted file mode 100644
index d193a48490e2..
--- a/arch/parisc/include/asm/agp.h
+++ /dev/null
@@ -1,15 +0,0 @@
-/* SPDX-License-Identifier: GPL-2.0 */
-#ifndef _ASM_PARISC_AGP_H
-#define _ASM_PARISC_AGP_H
-
-/*
- * PARISC specific AGP definitions.
- * Copyright (c) 2006 Kyle McMartin 
- *
- */
-
-#define map_page_into_agp(page)do { } while (0)
-#define unmap_page_from_agp(page)  do { } while (0)
-#define flush_agp_cache()  mb()
-
-#endif /* _ASM_PARISC_AGP_H */
diff --git a/arch/powerpc/include/asm/Kbuild b/arch/powerpc/include/asm/Kbuild
index bcf95ce0964f..419319c4963c 100644
--- a/arch/powerpc/include/asm/Kbuild
+++ b/arch/powerpc/include/asm/Kbuild
@@ -2,6 +2,7 @@
 generated-y += syscall_table_32.h
 generated-y += syscall_table_64.h
 generated-y += syscall_table_spu.h
+generic-y += agp.h
 generic-y += export.h
 generic-y += kvm_types.h
 generic-y += mcs_spinlock.h
diff --git a/arch/sparc/include/asm/Kbuild b/arch/sparc/include/asm/Kbuild
index 0b9d98ced34a..595ca0be286b 100644
--- a/arch/sparc/include/asm/Kbuild
+++ b/arch/sparc/include/asm/Kbuild
@@ -1,6 +1,7 @@
 # SPDX-License-Identifier: GPL-2.0
 generated-y += syscall_table_32.h
 generated-y += syscall_table_64.h

[PATCH 1/2] char/agp: consolidate {alloc,free}_gatt_pages()

2023-02-12 Thread Mike Rapoport
From: "Mike Rapoport (IBM)" 

There is a copy of alloc_gatt_pages() and free_gatt_pages in several
architectures in arch/$ARCH/include/asm/agp.h. All the copies do exactly
the same: alias alloc_gatt_pages() to __get_free_pages(GFP_KERNEL) and
alias free_gatt_pages() to free_pages().

Define alloc_gatt_pages() and free_gatt_pages() in drivers/char/agp/agp.h
and drop per-architecture definitions.

Signed-off-by: Mike Rapoport (IBM) 
---
 arch/alpha/include/asm/agp.h   | 6 --
 arch/ia64/include/asm/agp.h| 6 --
 arch/parisc/include/asm/agp.h  | 6 --
 arch/powerpc/include/asm/agp.h | 6 --
 arch/sparc/include/asm/agp.h   | 6 --
 arch/x86/include/asm/agp.h | 6 --
 drivers/char/agp/agp.h | 6 ++
 7 files changed, 6 insertions(+), 36 deletions(-)

diff --git a/arch/alpha/include/asm/agp.h b/arch/alpha/include/asm/agp.h
index 7874f063d000..4197b3bc78ee 100644
--- a/arch/alpha/include/asm/agp.h
+++ b/arch/alpha/include/asm/agp.h
@@ -10,10 +10,4 @@
 #define unmap_page_from_agp(page)  do { } while (0)
 #define flush_agp_cache() mb()
 
-/* GATT allocation. Returns/accepts GATT kernel virtual address. */
-#define alloc_gatt_pages(order)\
-   ((char *)__get_free_pages(GFP_KERNEL, (order)))
-#define free_gatt_pages(table, order)  \
-   free_pages((unsigned long)(table), (order))
-
 #endif
diff --git a/arch/ia64/include/asm/agp.h b/arch/ia64/include/asm/agp.h
index 0261507dc264..f42c7dcb3d79 100644
--- a/arch/ia64/include/asm/agp.h
+++ b/arch/ia64/include/asm/agp.h
@@ -18,10 +18,4 @@
 #define unmap_page_from_agp(page)  do { } while (0)
 #define flush_agp_cache()  mb()
 
-/* GATT allocation. Returns/accepts GATT kernel virtual address. */
-#define alloc_gatt_pages(order)\
-   ((char *)__get_free_pages(GFP_KERNEL, (order)))
-#define free_gatt_pages(table, order)  \
-   free_pages((unsigned long)(table), (order))
-
 #endif /* _ASM_IA64_AGP_H */
diff --git a/arch/parisc/include/asm/agp.h b/arch/parisc/include/asm/agp.h
index 14ae54cfd368..d193a48490e2 100644
--- a/arch/parisc/include/asm/agp.h
+++ b/arch/parisc/include/asm/agp.h
@@ -12,10 +12,4 @@
 #define unmap_page_from_agp(page)  do { } while (0)
 #define flush_agp_cache()  mb()
 
-/* GATT allocation. Returns/accepts GATT kernel virtual address. */
-#define alloc_gatt_pages(order)\
-   ((char *)__get_free_pages(GFP_KERNEL, (order)))
-#define free_gatt_pages(table, order)  \
-   free_pages((unsigned long)(table), (order))
-
 #endif /* _ASM_PARISC_AGP_H */
diff --git a/arch/powerpc/include/asm/agp.h b/arch/powerpc/include/asm/agp.h
index 6b6485c988dd..e86f2ce476c9 100644
--- a/arch/powerpc/include/asm/agp.h
+++ b/arch/powerpc/include/asm/agp.h
@@ -9,11 +9,5 @@
 #define unmap_page_from_agp(page) do {} while (0)
 #define flush_agp_cache() mb()
 
-/* GATT allocation. Returns/accepts GATT kernel virtual address. */
-#define alloc_gatt_pages(order)\
-   ((char *)__get_free_pages(GFP_KERNEL, (order)))
-#define free_gatt_pages(table, order)  \
-   free_pages((unsigned long)(table), (order))
-
 #endif /* __KERNEL__ */
 #endif /* _ASM_POWERPC_AGP_H */
diff --git a/arch/sparc/include/asm/agp.h b/arch/sparc/include/asm/agp.h
index 2d0ff84cee3f..5186924fa673 100644
--- a/arch/sparc/include/asm/agp.h
+++ b/arch/sparc/include/asm/agp.h
@@ -8,10 +8,4 @@
 #define unmap_page_from_agp(page)  do { } while (0)
 #define flush_agp_cache()  mb()
 
-/* GATT allocation. Returns/accepts GATT kernel virtual address. */
-#define alloc_gatt_pages(order)\
-   ((char *)__get_free_pages(GFP_KERNEL, (order)))
-#define free_gatt_pages(table, order)  \
-   free_pages((unsigned long)(table), (order))
-
 #endif
diff --git a/arch/x86/include/asm/agp.h b/arch/x86/include/asm/agp.h
index cd7b14322035..c8c111d8fbd7 100644
--- a/arch/x86/include/asm/agp.h
+++ b/arch/x86/include/asm/agp.h
@@ -23,10 +23,4 @@
  */
 #define flush_agp_cache() wbinvd()
 
-/* GATT allocation. Returns/accepts GATT kernel virtual address. */
-#define alloc_gatt_pages(order)\
-   ((char *)__get_free_pages(GFP_KERNEL, (order)))
-#define free_gatt_pages(table, order)  \
-   free_pages((unsigned long)(table), (order))
-
 #endif /* _ASM_X86_AGP_H */
diff --git a/drivers/char/agp/agp.h b/drivers/char/agp/agp.h
index bb09d64cd51e..8771dcc9b8e2 100644
--- a/drivers/char/agp/agp.h
+++ b/drivers/char/agp/agp.h
@@ -236,6 +236,12 @@ void agp3_generic_tlbflush(struct agp_memory *mem);
 int agp3_generic_configure(void);
 void agp3_generic_cleanup(void);
 
+/* GATT allocation. Returns/accepts GATT kernel virtual address. */
+#define alloc_gatt_pages(order)\
+   ((char *)__get_free_pages(GFP_KERNEL, (order)))
+#define free_gatt_pages(table, order)  \
+   free_pages((unsigned long)(table), (order))
+
 /* aperture sizes have been standardised since v3 */
 #define AGP_GENERIC_SIZES_ENTRIES 11
 extern 

[PATCH 0/2] char/agp: consolidate asm/agp.h

2023-02-12 Thread Mike Rapoport
From: "Mike Rapoport (IBM)" 

Hi,

asm/agp.h is duplicated in several architectures, with x86 being the
only instance that differs from the rest.

Introduce asm-generic/agp.h and use it instead of per-architecture
headers for the most cases.

I believe that asm-generic is the best tree to pick up this patches.

Mike Rapoport (IBM) (2):
  char/agp: consolidate {alloc,free}_gatt_pages()
  char/agp: introduce asm-generic/agp.h

 arch/alpha/include/asm/Kbuild   |  1 +
 arch/alpha/include/asm/agp.h| 19 ---
 arch/ia64/include/asm/Kbuild|  1 +
 arch/ia64/include/asm/agp.h | 27 ---
 arch/parisc/include/asm/Kbuild  |  1 +
 arch/parisc/include/asm/agp.h   | 21 -
 arch/powerpc/include/asm/Kbuild |  1 +
 arch/powerpc/include/asm/agp.h  | 19 ---
 arch/sparc/include/asm/Kbuild   |  1 +
 arch/sparc/include/asm/agp.h| 17 -
 arch/x86/include/asm/agp.h  |  6 --
 drivers/char/agp/agp.h  |  6 ++
 include/asm-generic/agp.h   | 11 +++
 13 files changed, 22 insertions(+), 109 deletions(-)
 delete mode 100644 arch/alpha/include/asm/agp.h
 delete mode 100644 arch/ia64/include/asm/agp.h
 delete mode 100644 arch/parisc/include/asm/agp.h
 delete mode 100644 arch/powerpc/include/asm/agp.h
 delete mode 100644 arch/sparc/include/asm/agp.h
 create mode 100644 include/asm-generic/agp.h


base-commit: 2241ab53cbb5cdb08a6b2d4688feb13971058f65
-- 
2.35.1