Re: [PATCH 1/3] bits: introduce fixed-type genmasks

2024-01-23 Thread Jani Nikula
On Tue, 23 Jan 2024, Lucas De Marchi  wrote:
> From: Yury Norov 
>
> Generalize __GENMASK() to support different types, and implement
> fixed-types versions of GENMASK() based on it. The fixed-type version
> allows more strict checks to the min/max values accepted, which is
> useful for defining registers like implemented by i915 and xe drivers
> with their REG_GENMASK*() macros.

Mmh, the commit message says the fixed-type version allows more strict
checks, but none are actually added. GENMASK_INPUT_CHECK() remains the
same.

Compared to the i915 and xe versions, this is more lax now. You could
specify GENMASK_U32(63,32) without complaints.


BR,
Jani.

>
> Signed-off-by: Yury Norov 
> ---
>  include/linux/bitops.h |  1 -
>  include/linux/bits.h   | 22 --
>  2 files changed, 12 insertions(+), 11 deletions(-)
>
> diff --git a/include/linux/bitops.h b/include/linux/bitops.h
> index 2ba557e067fe..1db50c69cfdb 100644
> --- a/include/linux/bitops.h
> +++ b/include/linux/bitops.h
> @@ -15,7 +15,6 @@
>  #  define aligned_byte_mask(n) (~0xffUL << (BITS_PER_LONG - 8 - 8*(n)))
>  #endif
>  
> -#define BITS_PER_TYPE(type)  (sizeof(type) * BITS_PER_BYTE)
>  #define BITS_TO_LONGS(nr)__KERNEL_DIV_ROUND_UP(nr, BITS_PER_TYPE(long))
>  #define BITS_TO_U64(nr)  __KERNEL_DIV_ROUND_UP(nr, 
> BITS_PER_TYPE(u64))
>  #define BITS_TO_U32(nr)  __KERNEL_DIV_ROUND_UP(nr, 
> BITS_PER_TYPE(u32))
> diff --git a/include/linux/bits.h b/include/linux/bits.h
> index 7c0cf5031abe..cb94128171b2 100644
> --- a/include/linux/bits.h
> +++ b/include/linux/bits.h
> @@ -6,6 +6,8 @@
>  #include 
>  #include 
>  
> +#define BITS_PER_TYPE(type)  (sizeof(type) * BITS_PER_BYTE)
> +
>  #define BIT_MASK(nr) (UL(1) << ((nr) % BITS_PER_LONG))
>  #define BIT_WORD(nr) ((nr) / BITS_PER_LONG)
>  #define BIT_ULL_MASK(nr) (ULL(1) << ((nr) % BITS_PER_LONG_LONG))
> @@ -30,16 +32,16 @@
>  #define GENMASK_INPUT_CHECK(h, l) 0
>  #endif
>  
> -#define __GENMASK(h, l) \
> - (((~UL(0)) - (UL(1) << (l)) + 1) & \
> -  (~UL(0) >> (BITS_PER_LONG - 1 - (h
> -#define GENMASK(h, l) \
> - (GENMASK_INPUT_CHECK(h, l) + __GENMASK(h, l))
> +#define __GENMASK(t, h, l) \
> + (GENMASK_INPUT_CHECK(h, l) + \
> +  (((t)~0ULL - ((t)(1) << (l)) + 1) & \
> +  ((t)~0ULL >> (BITS_PER_TYPE(t) - 1 - (h)
>  
> -#define __GENMASK_ULL(h, l) \
> - (((~ULL(0)) - (ULL(1) << (l)) + 1) & \
> -  (~ULL(0) >> (BITS_PER_LONG_LONG - 1 - (h
> -#define GENMASK_ULL(h, l) \
> - (GENMASK_INPUT_CHECK(h, l) + __GENMASK_ULL(h, l))
> +#define GENMASK(h, l)__GENMASK(unsigned long,  h, l)
> +#define GENMASK_ULL(h, l)__GENMASK(unsigned long long, h, l)
> +#define GENMASK_U8(h, l) __GENMASK(u8,  h, l)
> +#define GENMASK_U16(h, l)__GENMASK(u16, h, l)
> +#define GENMASK_U32(h, l)__GENMASK(u32, h, l)
> +#define GENMASK_U64(h, l)__GENMASK(u64, h, l)
>  
>  #endif   /* __LINUX_BITS_H */

-- 
Jani Nikula, Intel


Re: [PATCH] mm: Remove double faults once write a device pfn

2024-01-23 Thread Christian König

Am 24.01.24 um 03:43 schrieb Zhou, Xianrong:

[AMD Official Use Only - General]


The vmf_insert_pfn_prot could cause unnecessary double faults on a
device pfn. Because currently the vmf_insert_pfn_prot does not make
the pfn writable so the pte entry is normally read-only or dirty
catching.

What? How do you got to this conclusion?

Sorry. I did not mention that this problem only exists on arm64 platform.

Ok, that makes at least a little bit more sense.


Because on arm64 platform the PTE_RDONLY is automatically attached to
the userspace pte entries even through VM_WRITE + VM_SHARE.
The  PTE_RDONLY needs to be cleared in vmf_insert_pfn_prot. However
vmf_insert_pfn_prot do not make the pte writable passing false
@mkwrite to insert_pfn.

Question is why is arm64 doing this? As far as I can see they must have some
hardware reason for that.

The mkwrite parameter to insert_pfn() was added by commit
b2770da642540 to make insert_pfn() look more like insert_pfn_pmd() so that
the DAX code can insert PTEs which are writable and dirty at the same time.


This is one scenario to do so. In fact on arm64 there are many scenarios could
be to do so. So we can let vmf_insert_pfn_prot supporting @mkwrite for drivers
at core layer and let drivers to decide whether or not to make writable and 
dirty
at one time. The patch did this. Otherwise double faults on arm64 when call
vmf_insert_pfn_prot.


Well, that doesn't answer my question why arm64 is double faulting in 
the first place,.


So as long as this isn't sorted out I'm going to reject this patch.

Regards,
Christian.




This is a completely different use case to what you try to use it here for and
that looks extremely fishy to me.

Regards,
Christian.


The first fault only sets up the pte entry which actually is dirty
catching. And the second immediate fault to the pfn due to first
dirty catching when the cpu re-execute the store instruction.

It could be that this is done to work around some hw behavior, but
not because of dirty catching.


Normally if the drivers call vmf_insert_pfn_prot and also supply
'pfn_mkwrite' callback within vm_operations_struct which requires
the pte to be dirty catching then the vmf_insert_pfn_prot and the
double fault are reasonable. It is not a problem.

Well, as far as I can see that behavior absolutely doesn't make sense.

When pfn_mkwrite is requested then the driver should use PAGE_COPY,
which is exactly what VMWGFX (the only driver using dirty tracking) is

doing.

Everybody else uses PAGE_SHARED which should make the pte writeable
immediately.

Regards,
Christian.


However the most of drivers calling vmf_insert_pfn_prot do not
supply the 'pfn_mkwrite' callback so that the second fault is unnecessary.

So just like vmf_insert_mixed and vmf_insert_mixed_mkwrite pair, we
should also supply vmf_insert_pfn_mkwrite for drivers as well.

Signed-off-by: Xianrong Zhou 
---
arch/x86/entry/vdso/vma.c  |  3 ++-
drivers/gpu/drm/amd/amdgpu/amdgpu_gem.c|  2 +-
drivers/gpu/drm/i915/gem/i915_gem_ttm.c|  2 +-
drivers/gpu/drm/nouveau/nouveau_gem.c  |  2 +-
drivers/gpu/drm/radeon/radeon_gem.c|  2 +-
drivers/gpu/drm/ttm/ttm_bo_vm.c|  8 +---
drivers/gpu/drm/vmwgfx/vmwgfx_page_dirty.c |  8 +---
include/drm/ttm/ttm_bo.h   |  3 ++-
include/linux/mm.h |  2 +-
mm/memory.c| 14 +++---
10 files changed, 30 insertions(+), 16 deletions(-)

diff --git a/arch/x86/entry/vdso/vma.c b/arch/x86/entry/vdso/vma.c
index 7645730dc228..dd2431c2975f 100644
--- a/arch/x86/entry/vdso/vma.c
+++ b/arch/x86/entry/vdso/vma.c
@@ -185,7 +185,8 @@ static vm_fault_t vvar_fault(const struct

vm_special_mapping *sm,

  if (pvti && vclock_was_used(VDSO_CLOCKMODE_PVCLOCK))

{

  return vmf_insert_pfn_prot(vma, vmf->address,
  __pa(pvti) >> PAGE_SHIFT,
-   pgprot_decrypted(vma-
vm_page_prot));
+   pgprot_decrypted(vma-
vm_page_prot),
+   true);
  }
  } else if (sym_offset == image->sym_hvclock_page) {
  pfn = hv_get_tsc_pfn(); diff --git
a/drivers/gpu/drm/amd/amdgpu/amdgpu_gem.c
b/drivers/gpu/drm/amd/amdgpu/amdgpu_gem.c
index 49a5f1c73b3e..adcb20d9e624 100644
--- a/drivers/gpu/drm/amd/amdgpu/amdgpu_gem.c
+++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_gem.c
@@ -64,7 +64,7 @@ static vm_fault_t amdgpu_gem_fault(struct

vm_fault

*vmf)

  }

  ret = ttm_bo_vm_fault_reserved(vmf, vmf->vma-
vm_page_prot,
-  TTM_BO_VM_NUM_PREFAULT);
+  TTM_BO_VM_NUM_PREFAULT,

true);

  drm_dev_exit(idx);
  } else {
diff --git a/drivers/gpu/drm/i915/gem/i915_gem_ttm.c
b/drivers/gpu/drm/i915/gem/i915_gem_ttm.c
index 

Re: Making drm_gpuvm work across gpu devices

2024-01-23 Thread Christian König

Am 24.01.24 um 05:14 schrieb Zeng, Oak:

Danilo,

Maybe before I give up, I should also ask, currently drm_gpuvm is designed for 
BO-centric world. Is it easy to make the va range split/merge work simply for 
va range, but without BO? Conceptually this should work as we are 
merge/splitting virtual address range which can be decoupled completely from BO.


At least AMD GPUs have a similar requirement to manage virtual ranges 
which are not backed by a BO. For example PRT ranges.


I expect that we can still use drm_gpuvm for this and the BO is simply 
NULL in that case.


Regards,
Christian.




-Original Message-
From: dri-devel  On Behalf Of Zeng,
Oak
Sent: Tuesday, January 23, 2024 10:57 PM
To: Danilo Krummrich ; Christian König
; Dave Airlie ; Daniel Vetter
; Felix Kuehling ; Welty, Brian

Cc: Brost, Matthew ;
thomas.hellst...@linux.intel.com; dri-devel@lists.freedesktop.org; Ghimiray,
Himal Prasad ; Gupta, saurabhg
; Bommu, Krishnaiah
; Vishwanathapura, Niranjana
; intel...@lists.freedesktop.org
Subject: RE: Making drm_gpuvm work across gpu devices

Thanks a lot Danilo.

Maybe I wasn't clear enough. In the solution I proposed, each device still have
separate vm/page tables. Each device still need to manage the mapping, page
table flags etc. It is just in svm use case, all devices share one drm_gpuvm
instance. As I understand it, drm_gpuvm's main function is the va range split 
and
merging. I don't see why it doesn't work across gpu devices.

But I read more about drm_gpuvm. Its split merge function takes a
drm_gem_object parameter, see drm_gpuvm_sm_map_ops_create and
drm_gpuvm_sm_map. Actually the whole drm_gpuvm is designed for BO-centric
driver, for example, it has a drm_gpuvm_bo concept to keep track of the
1BO:Ngpuva mapping. The whole purpose of leveraging drm_gpuvm is to re-use
the va split/merge functions for SVM. But in our SVM implementation, there is no
buffer object at all. So I don't think our SVM codes can leverage drm_gpuvm.

I will give up this approach, unless Matt or Brian can see a way.

A few replies inline @Welty, Brian I had more thoughts inline to one of your
original question


-Original Message-
From: Danilo Krummrich 
Sent: Tuesday, January 23, 2024 6:57 PM
To: Zeng, Oak ; Christian König
; Dave Airlie ; Daniel Vetter
; Felix Kuehling 
Cc: Welty, Brian ; dri-devel@lists.freedesktop.org;

intel-

x...@lists.freedesktop.org; Bommu, Krishnaiah ;
Ghimiray, Himal Prasad ;
thomas.hellst...@linux.intel.com; Vishwanathapura, Niranjana
; Brost, Matthew
; Gupta, saurabhg 
Subject: Re: Making drm_gpuvm work across gpu devices

Hi Oak,

On 1/23/24 20:37, Zeng, Oak wrote:

Thanks Christian. I have some comment inline below.

Danilo, can you also take a look and give your feedback? Thanks.

I agree with everything Christian already wrote. Except for the KFD parts, which
I'm simply not familiar with, I had exactly the same thoughts after reading your
initial mail.

Please find some more comments below.


-Original Message-
From: Christian König 
Sent: Tuesday, January 23, 2024 6:13 AM
To: Zeng, Oak ; Danilo Krummrich

;

Dave Airlie ; Daniel Vetter 
Cc: Welty, Brian ; dri-devel@lists.freedesktop.org;

intel-

x...@lists.freedesktop.org; Bommu, Krishnaiah

;

Ghimiray, Himal Prasad ;
thomas.hellst...@linux.intel.com; Vishwanathapura, Niranjana
; Brost, Matthew

Subject: Re: Making drm_gpuvm work across gpu devices

Hi Oak,

Am 23.01.24 um 04:21 schrieb Zeng, Oak:

Hi Danilo and all,

During the work of Intel's SVM code, we came up the idea of making

drm_gpuvm to work across multiple gpu devices. See some discussion here:
https://lore.kernel.org/dri-


devel/PH7PR11MB70049E7E6A2F40BF6282ECC292742@PH7PR11MB7004.namprd

11.prod.outlook.com/

The reason we try to do this is, for a SVM (shared virtual memory across

cpu

program and all gpu program on all gpu devices) process, the address space

has

to be across all gpu devices. So if we make drm_gpuvm to work across

devices,

then our SVM code can leverage drm_gpuvm as well.

At a first look, it seems feasible because drm_gpuvm doesn't really use the

drm_device *drm pointer a lot. This param is used only for printing/warning.

So I

think maybe we can delete this drm field from drm_gpuvm.

This way, on a multiple gpu device system, for one process, we can have

only

one drm_gpuvm instance, instead of multiple drm_gpuvm instances (one

for

each gpu device).

What do you think?

Well from the GPUVM side I don't think it would make much difference if
we have the drm device or not.

But the experience we had with the KFD I think I should mention that we
should absolutely *not* deal with multiple devices at the same time in
the UAPI or VM objects inside the driver.

The background is that all the APIs inside the Linux kernel are build
around the idea that they work with only one device at a time. This
accounts for both low level APIs like the DMA API as well as pretty high
level things like for example file 

Re: [PATCH v3 3/3] dt-bindings: mfd: atmel,hlcdc: Convert to DT schema format

2024-01-23 Thread Dharma.B
Hi Conor & All,

On 22/01/24 2:46 pm, Conor Dooley wrote:
> On Mon, Jan 22, 2024 at 03:38:41AM +,dharm...@microchip.com  wrote:
>> Hi Conor,
>> On 19/01/24 5:33 pm, Conor Dooley - M52691 wrote:
>>> On Fri, Jan 19, 2024 at 03:32:49AM +,dharm...@microchip.com  wrote:
 On 18/01/24 9:10 pm, Conor Dooley wrote:
> On Thu, Jan 18, 2024 at 02:56:12PM +0530, Dharma Balasubiramani wrote:
>> Convert the atmel,hlcdc binding to DT schema format.
>>
>> Adjust the clock-names property to clarify that the LCD controller 
>> expects
>> one of these clocks (either sys_clk or lvds_pll_clk to be present but not
>> both) along with the slow_clk and periph_clk. This alignment with the 
>> actual
>> hardware requirements will enable accurate device tree configuration for
>> systems using the HLCDC IP.
>>
>> Signed-off-by: Dharma Balasubiramani
>> ---
>> changelog
>> v2 -> v3
>> - Rename hlcdc-display-controller and hlcdc-pwm to generic names.
>> - Modify the description by removing the unwanted comments and '|'.
>> - Modify clock-names simpler.
>> v1 -> v2
>> - Remove the explicit copyrights.
>> - Modify title (not include words like binding/driver).
>> - Modify description actually describing the hardware and not the driver.
>> - Add details of lvds_pll addition in commit message.
>> - Ref endpoint and not endpoint-base.
>> - Fix coding style.
>> ...
>> .../devicetree/bindings/mfd/atmel,hlcdc.yaml  | 97 
>> +++
>> .../devicetree/bindings/mfd/atmel-hlcdc.txt   | 56 ---
>> 2 files changed, 97 insertions(+), 56 deletions(-)
>> create mode 100644 
>> Documentation/devicetree/bindings/mfd/atmel,hlcdc.yaml
>> delete mode 100644 
>> Documentation/devicetree/bindings/mfd/atmel-hlcdc.txt
>>
>> diff --git a/Documentation/devicetree/bindings/mfd/atmel,hlcdc.yaml 
>> b/Documentation/devicetree/bindings/mfd/atmel,hlcdc.yaml
>> new file mode 100644
>> index ..eccc998ac42c
>> --- /dev/null
>> +++ b/Documentation/devicetree/bindings/mfd/atmel,hlcdc.yaml
>> @@ -0,0 +1,97 @@
>> +# SPDX-License-Identifier: (GPL-2.0 OR BSD-2-Clause)
>> +%YAML 1.2
>> +---
>> +$id:http://devicetree.org/schemas/mfd/atmel,hlcdc.yaml#
>> +$schema:http://devicetree.org/meta-schemas/core.yaml#
>> +
>> +title: Atmel's HLCD Controller
>> +
>> +maintainers:
>> +  - Nicolas Ferre
>> +  - Alexandre Belloni
>> +  - Claudiu Beznea
>> +
>> +description:
>> +  The Atmel HLCDC (HLCD Controller) IP available on Atmel SoCs exposes 
>> two
>> +  subdevices, a PWM chip and a Display Controller.
>> +
>> +properties:
>> +  compatible:
>> +enum:
>> +  - atmel,at91sam9n12-hlcdc
>> +  - atmel,at91sam9x5-hlcdc
>> +  - atmel,sama5d2-hlcdc
>> +  - atmel,sama5d3-hlcdc
>> +  - atmel,sama5d4-hlcdc
>> +  - microchip,sam9x60-hlcdc
>> +  - microchip,sam9x75-xlcdc
>> +
>> +  reg:
>> +maxItems: 1
>> +
>> +  interrupts:
>> +maxItems: 1
>> +
>> +  clocks:
>> +maxItems: 3
> Hmm, one thing I probably should have said on the previous version, but
> I missed somehow: It would be good to add an items list to the clocks
> property here to explain what the 3 clocks are/are used for - especially
> since there is additional complexity being added here to use either the
> sys or lvds clocks.
 May I inquire if this approach is likely to be effective?

  clocks:
items:
  - description: peripheral clock
  - description: generic clock or lvds pll clock
  Once the LVDS PLL is enabled, the pixel clock is used as the
  clock for LCDC, so its GCLK is no longer needed.
  - description: slow clock
maxItems: 3
>>> Hmm that sounds very suspect to me. "Once the lvdspll is enabled the
>>> generic clock is no longer needed" sounds like both clocks can be provided
>>> to the IP on different pins and their provision is not mutually
>>> exclusive, just that the IP will only actually use one at a time. If
>>> that is the case, then this patch is nott correct and the binding should
>>> allow for 4 clocks, with both the generic clock and the lvds pll being
>>> present in the DT at the same time.
>>>
>>> I vaguely recall internal discussion about this problem some time back
>>> but the details all escape me.
>> Let's delve deeper into the clock configuration for LCDC_PCK.
>>
>> Considering the flexibility of the design, it appears that both clocks,
>> sys_clk (generic clock) and lvds_pll_clk, can indeed be provided to the
>> IP simultaneously. The crucial aspect, however, is that the IP will
>> utilize only one of these clocks at any given time. This aligns with the
>> specific 

[PATCH 3/3] drm/i915: Convert REG_GENMASK* to fixed-width GENMASK_*

2024-01-23 Thread Lucas De Marchi
Now that include/linux/bits.h implements fixed-width GENMASK_*, use them
to implement the i915/xe specific macros. Converting each driver to use
the generic macros are left for later, when/if other driver-specific
macros are also generalized.

Signed-off-by: Lucas De Marchi 
---
 drivers/gpu/drm/i915/i915_reg_defs.h | 108 +++
 1 file changed, 11 insertions(+), 97 deletions(-)

diff --git a/drivers/gpu/drm/i915/i915_reg_defs.h 
b/drivers/gpu/drm/i915/i915_reg_defs.h
index a685db1e815d..52f99eb96f86 100644
--- a/drivers/gpu/drm/i915/i915_reg_defs.h
+++ b/drivers/gpu/drm/i915/i915_reg_defs.h
@@ -9,76 +9,19 @@
 #include 
 #include 
 
-/**
- * REG_BIT() - Prepare a u32 bit value
- * @__n: 0-based bit number
- *
- * Local wrapper for BIT() to force u32, with compile time checks.
- *
- * @return: Value with bit @__n set.
- */
-#define REG_BIT(__n)   \
-   ((u32)(BIT(__n) +   \
-  BUILD_BUG_ON_ZERO(__is_constexpr(__n) && \
-((__n) < 0 || (__n) > 31
-
-/**
- * REG_BIT8() - Prepare a u8 bit value
- * @__n: 0-based bit number
- *
- * Local wrapper for BIT() to force u8, with compile time checks.
- *
- * @return: Value with bit @__n set.
- */
-#define REG_BIT8(__n)   \
-   ((u8)(BIT(__n) +\
-  BUILD_BUG_ON_ZERO(__is_constexpr(__n) && \
-((__n) < 0 || (__n) > 7
-
-/**
- * REG_GENMASK() - Prepare a continuous u32 bitmask
- * @__high: 0-based high bit
- * @__low: 0-based low bit
- *
- * Local wrapper for GENMASK() to force u32, with compile time checks.
- *
- * @return: Continuous bitmask from @__high to @__low, inclusive.
- */
-#define REG_GENMASK(__high, __low) \
-   ((u32)(GENMASK(__high, __low) + \
-  BUILD_BUG_ON_ZERO(__is_constexpr(__high) &&  \
-__is_constexpr(__low) &&   \
-((__low) < 0 || (__high) > 31 || (__low) > 
(__high)
-
-/**
- * REG_GENMASK64() - Prepare a continuous u64 bitmask
- * @__high: 0-based high bit
- * @__low: 0-based low bit
- *
- * Local wrapper for GENMASK_ULL() to force u64, with compile time checks.
- *
- * @return: Continuous bitmask from @__high to @__low, inclusive.
+/*
+ * Wrappers over the generic BIT_* and GENMASK_* implementations,
+ * for compatibility reasons with previous implementation
  */
-#define REG_GENMASK64(__high, __low)   \
-   ((u64)(GENMASK_ULL(__high, __low) + \
-  BUILD_BUG_ON_ZERO(__is_constexpr(__high) &&  \
-__is_constexpr(__low) &&   \
-((__low) < 0 || (__high) > 63 || (__low) > 
(__high)
+#define REG_GENMASK(__high, __low) GENMASK_U32(__high, __low)
+#define REG_GENMASK64(__high, __low)   GENMASK_U64(__high, __low)
+#define REG_GENMASK16(__high, __low)   GENMASK_U16(__high, __low)
+#define REG_GENMASK8(__high, __low)GENMASK_U8(__high, __low)
 
-/**
- * REG_GENMASK8() - Prepare a continuous u8 bitmask
- * @__high: 0-based high bit
- * @__low: 0-based low bit
- *
- * Local wrapper for GENMASK() to force u8, with compile time checks.
- *
- * @return: Continuous bitmask from @__high to @__low, inclusive.
- */
-#define REG_GENMASK8(__high, __low) \
-   ((u8)(GENMASK(__high, __low) +  \
-  BUILD_BUG_ON_ZERO(__is_constexpr(__high) &&  \
-__is_constexpr(__low) &&   \
-((__low) < 0 || (__high) > 7 || (__low) > 
(__high)
+#define REG_BIT(__n)   BIT_U32(__n)
+#define REG_BIT64(__n) BIT_U64(__n)
+#define REG_BIT16(__n) BIT_U16(__n)
+#define REG_BIT8(__n)  BIT_U8(__n)
 
 /*
  * Local integer constant expression version of is_power_of_2().
@@ -143,35 +86,6 @@
  */
 #define REG_FIELD_GET64(__mask, __val) ((u64)FIELD_GET(__mask, __val))
 
-/**
- * REG_BIT16() - Prepare a u16 bit value
- * @__n: 0-based bit number
- *
- * Local wrapper for BIT() to force u16, with compile time
- * checks.
- *
- * @return: Value with bit @__n set.
- */
-#define REG_BIT16(__n)   \
-   ((u16)(BIT(__n) +\
-  BUILD_BUG_ON_ZERO(__is_constexpr(__n) && \
-((__n) < 0 || (__n) > 15
-
-/**
- * REG_GENMASK16() - Prepare a continuous u8 bitmask
- * @__high: 0-based high bit
- * @__low: 0-based low bit
- *
- * Local wrapper for GENMASK() to force u16, with compile 

[PATCH 0/3] Fixed-type GENMASK/BIT

2024-01-23 Thread Lucas De Marchi
Move the implementation of REG_GENMASK/REG_BIT to a more appropriate
place to be shared by i915, xe and possibly other parts of the kernel.

For now this re-defines the old macros. In future we may start using the
new macros directly, but that's a more intrusive search-and-replace.

Yury, I added a little bit more information to the commit message in
patch 1. First 2 patches may go through your tree. For the last one we
may have potential conflicts, so I'm not sure. +Jani from i915 side to
chime in.

v1: 
https://lore.kernel.org/intel-xe/20230509051403.2748545-1-lucas.demar...@intel.com/

Lucas De Marchi (2):
  bits: Introduce fixed-type BIT
  drm/i915: Convert REG_GENMASK* to fixed-width GENMASK_*

Yury Norov (1):
  bits: introduce fixed-type genmasks

 drivers/gpu/drm/i915/i915_reg_defs.h | 108 +++
 include/linux/bitops.h   |   1 -
 include/linux/bits.h |  33 +---
 3 files changed, 33 insertions(+), 109 deletions(-)

-- 
2.43.0



[PATCH 1/3] bits: introduce fixed-type genmasks

2024-01-23 Thread Lucas De Marchi
From: Yury Norov 

Generalize __GENMASK() to support different types, and implement
fixed-types versions of GENMASK() based on it. The fixed-type version
allows more strict checks to the min/max values accepted, which is
useful for defining registers like implemented by i915 and xe drivers
with their REG_GENMASK*() macros.

Signed-off-by: Yury Norov 
---
 include/linux/bitops.h |  1 -
 include/linux/bits.h   | 22 --
 2 files changed, 12 insertions(+), 11 deletions(-)

diff --git a/include/linux/bitops.h b/include/linux/bitops.h
index 2ba557e067fe..1db50c69cfdb 100644
--- a/include/linux/bitops.h
+++ b/include/linux/bitops.h
@@ -15,7 +15,6 @@
 #  define aligned_byte_mask(n) (~0xffUL << (BITS_PER_LONG - 8 - 8*(n)))
 #endif
 
-#define BITS_PER_TYPE(type)(sizeof(type) * BITS_PER_BYTE)
 #define BITS_TO_LONGS(nr)  __KERNEL_DIV_ROUND_UP(nr, BITS_PER_TYPE(long))
 #define BITS_TO_U64(nr)__KERNEL_DIV_ROUND_UP(nr, 
BITS_PER_TYPE(u64))
 #define BITS_TO_U32(nr)__KERNEL_DIV_ROUND_UP(nr, 
BITS_PER_TYPE(u32))
diff --git a/include/linux/bits.h b/include/linux/bits.h
index 7c0cf5031abe..cb94128171b2 100644
--- a/include/linux/bits.h
+++ b/include/linux/bits.h
@@ -6,6 +6,8 @@
 #include 
 #include 
 
+#define BITS_PER_TYPE(type)(sizeof(type) * BITS_PER_BYTE)
+
 #define BIT_MASK(nr)   (UL(1) << ((nr) % BITS_PER_LONG))
 #define BIT_WORD(nr)   ((nr) / BITS_PER_LONG)
 #define BIT_ULL_MASK(nr)   (ULL(1) << ((nr) % BITS_PER_LONG_LONG))
@@ -30,16 +32,16 @@
 #define GENMASK_INPUT_CHECK(h, l) 0
 #endif
 
-#define __GENMASK(h, l) \
-   (((~UL(0)) - (UL(1) << (l)) + 1) & \
-(~UL(0) >> (BITS_PER_LONG - 1 - (h
-#define GENMASK(h, l) \
-   (GENMASK_INPUT_CHECK(h, l) + __GENMASK(h, l))
+#define __GENMASK(t, h, l) \
+   (GENMASK_INPUT_CHECK(h, l) + \
+(((t)~0ULL - ((t)(1) << (l)) + 1) & \
+((t)~0ULL >> (BITS_PER_TYPE(t) - 1 - (h)
 
-#define __GENMASK_ULL(h, l) \
-   (((~ULL(0)) - (ULL(1) << (l)) + 1) & \
-(~ULL(0) >> (BITS_PER_LONG_LONG - 1 - (h
-#define GENMASK_ULL(h, l) \
-   (GENMASK_INPUT_CHECK(h, l) + __GENMASK_ULL(h, l))
+#define GENMASK(h, l)  __GENMASK(unsigned long,  h, l)
+#define GENMASK_ULL(h, l)  __GENMASK(unsigned long long, h, l)
+#define GENMASK_U8(h, l)   __GENMASK(u8,  h, l)
+#define GENMASK_U16(h, l)  __GENMASK(u16, h, l)
+#define GENMASK_U32(h, l)  __GENMASK(u32, h, l)
+#define GENMASK_U64(h, l)  __GENMASK(u64, h, l)
 
 #endif /* __LINUX_BITS_H */
-- 
2.43.0



[PATCH 2/3] bits: Introduce fixed-type BIT

2024-01-23 Thread Lucas De Marchi
Implement fixed-type BIT() to help drivers add stricter checks, like was
done for GENMASK.

Signed-off-by: Lucas De Marchi 
---
 include/linux/bits.h | 9 +
 1 file changed, 9 insertions(+)

diff --git a/include/linux/bits.h b/include/linux/bits.h
index cb94128171b2..5754a1251078 100644
--- a/include/linux/bits.h
+++ b/include/linux/bits.h
@@ -24,12 +24,16 @@
 #define GENMASK_INPUT_CHECK(h, l) \
(BUILD_BUG_ON_ZERO(__builtin_choose_expr( \
__is_constexpr((l) > (h)), (l) > (h), 0)))
+#define BIT_INPUT_CHECK(type, b) \
+   ((BUILD_BUG_ON_ZERO(__builtin_choose_expr( \
+   __is_constexpr(b), (b) >= BITS_PER_TYPE(type), 0
 #else
 /*
  * BUILD_BUG_ON_ZERO is not available in h files included from asm files,
  * disable the input check if that is the case.
  */
 #define GENMASK_INPUT_CHECK(h, l) 0
+#define BIT_INPUT_CHECK(type, b) 0
 #endif
 
 #define __GENMASK(t, h, l) \
@@ -44,4 +48,9 @@
 #define GENMASK_U32(h, l)  __GENMASK(u32, h, l)
 #define GENMASK_U64(h, l)  __GENMASK(u64, h, l)
 
+#define BIT_U8(b)  ((u8)(BIT_INPUT_CHECK(u8, b) + BIT(b)))
+#define BIT_U16(b) ((u16)(BIT_INPUT_CHECK(u16, b) + BIT(b)))
+#define BIT_U32(b) ((u32)(BIT_INPUT_CHECK(u32, b) + BIT(b)))
+#define BIT_U64(b) ((u64)(BIT_INPUT_CHECK(u64, b) + BIT(b)))
+
 #endif /* __LINUX_BITS_H */
-- 
2.43.0



RE: Making drm_gpuvm work across gpu devices

2024-01-23 Thread Zeng, Oak
Danilo,

Maybe before I give up, I should also ask, currently drm_gpuvm is designed for 
BO-centric world. Is it easy to make the va range split/merge work simply for 
va range, but without BO? Conceptually this should work as we are 
merge/splitting virtual address range which can be decoupled completely from 
BO. 

> -Original Message-
> From: dri-devel  On Behalf Of Zeng,
> Oak
> Sent: Tuesday, January 23, 2024 10:57 PM
> To: Danilo Krummrich ; Christian König
> ; Dave Airlie ; Daniel Vetter
> ; Felix Kuehling ; Welty, Brian
> 
> Cc: Brost, Matthew ;
> thomas.hellst...@linux.intel.com; dri-devel@lists.freedesktop.org; Ghimiray,
> Himal Prasad ; Gupta, saurabhg
> ; Bommu, Krishnaiah
> ; Vishwanathapura, Niranjana
> ; intel...@lists.freedesktop.org
> Subject: RE: Making drm_gpuvm work across gpu devices
> 
> Thanks a lot Danilo.
> 
> Maybe I wasn't clear enough. In the solution I proposed, each device still 
> have
> separate vm/page tables. Each device still need to manage the mapping, page
> table flags etc. It is just in svm use case, all devices share one drm_gpuvm
> instance. As I understand it, drm_gpuvm's main function is the va range split 
> and
> merging. I don't see why it doesn't work across gpu devices.
> 
> But I read more about drm_gpuvm. Its split merge function takes a
> drm_gem_object parameter, see drm_gpuvm_sm_map_ops_create and
> drm_gpuvm_sm_map. Actually the whole drm_gpuvm is designed for BO-centric
> driver, for example, it has a drm_gpuvm_bo concept to keep track of the
> 1BO:Ngpuva mapping. The whole purpose of leveraging drm_gpuvm is to re-use
> the va split/merge functions for SVM. But in our SVM implementation, there is 
> no
> buffer object at all. So I don't think our SVM codes can leverage drm_gpuvm.
> 
> I will give up this approach, unless Matt or Brian can see a way.
> 
> A few replies inline @Welty, Brian I had more thoughts inline to one of 
> your
> original question
> 
> > -Original Message-
> > From: Danilo Krummrich 
> > Sent: Tuesday, January 23, 2024 6:57 PM
> > To: Zeng, Oak ; Christian König
> > ; Dave Airlie ; Daniel Vetter
> > ; Felix Kuehling 
> > Cc: Welty, Brian ; dri-devel@lists.freedesktop.org;
> intel-
> > x...@lists.freedesktop.org; Bommu, Krishnaiah ;
> > Ghimiray, Himal Prasad ;
> > thomas.hellst...@linux.intel.com; Vishwanathapura, Niranjana
> > ; Brost, Matthew
> > ; Gupta, saurabhg 
> > Subject: Re: Making drm_gpuvm work across gpu devices
> >
> > Hi Oak,
> >
> > On 1/23/24 20:37, Zeng, Oak wrote:
> > > Thanks Christian. I have some comment inline below.
> > >
> > > Danilo, can you also take a look and give your feedback? Thanks.
> >
> > I agree with everything Christian already wrote. Except for the KFD parts, 
> > which
> > I'm simply not familiar with, I had exactly the same thoughts after reading 
> > your
> > initial mail.
> >
> > Please find some more comments below.
> >
> > >
> > >> -Original Message-
> > >> From: Christian König 
> > >> Sent: Tuesday, January 23, 2024 6:13 AM
> > >> To: Zeng, Oak ; Danilo Krummrich
> ;
> > >> Dave Airlie ; Daniel Vetter 
> > >> Cc: Welty, Brian ; 
> > >> dri-devel@lists.freedesktop.org;
> > intel-
> > >> x...@lists.freedesktop.org; Bommu, Krishnaiah
> > ;
> > >> Ghimiray, Himal Prasad ;
> > >> thomas.hellst...@linux.intel.com; Vishwanathapura, Niranjana
> > >> ; Brost, Matthew
> > >> 
> > >> Subject: Re: Making drm_gpuvm work across gpu devices
> > >>
> > >> Hi Oak,
> > >>
> > >> Am 23.01.24 um 04:21 schrieb Zeng, Oak:
> > >>> Hi Danilo and all,
> > >>>
> > >>> During the work of Intel's SVM code, we came up the idea of making
> > >> drm_gpuvm to work across multiple gpu devices. See some discussion here:
> > >> https://lore.kernel.org/dri-
> > >>
> >
> devel/PH7PR11MB70049E7E6A2F40BF6282ECC292742@PH7PR11MB7004.namprd
> > >> 11.prod.outlook.com/
> > >>>
> > >>> The reason we try to do this is, for a SVM (shared virtual memory across
> cpu
> > >> program and all gpu program on all gpu devices) process, the address 
> > >> space
> > has
> > >> to be across all gpu devices. So if we make drm_gpuvm to work across
> devices,
> > >> then our SVM code can leverage drm_gpuvm as well.
> > >>>
> > >>> At a first look, it seems feasible because drm_gpuvm doesn't really use 
> > >>> the
> > >> drm_device *drm pointer a lot. This param is used only for 
> > >> printing/warning.
> > So I
> > >> think maybe we can delete this drm field from drm_gpuvm.
> > >>>
> > >>> This way, on a multiple gpu device system, for one process, we can have
> only
> > >> one drm_gpuvm instance, instead of multiple drm_gpuvm instances (one
> for
> > >> each gpu device).
> > >>>
> > >>> What do you think?
> > >>
> > >> Well from the GPUVM side I don't think it would make much difference if
> > >> we have the drm device or not.
> > >>
> > >> But the experience we had with the KFD I think I should mention that we
> > >> should absolutely *not* deal with multiple devices at the same time in
> > >> the UAPI or VM 

Re: Re: [PATCH] drm/xe: Remove PVC from xe_wa kunit tests

2024-01-23 Thread Lucas De Marchi

On Tue, Jan 23, 2024 at 07:55:38PM -0800, Matt Roper wrote:

On Mon, Jan 22, 2024 at 07:12:42PM -0800, Lucas De Marchi wrote:

Since the PCI IDs for PVC were added to the xe driver, the xe_wa tests


This first line doesn't seem to be worded right.  I think you meant
either "weren't added" or "were only added to topic/xe-for-CI."


yep, I meant "weren't".


Assuming you can reword that,

Reviewed-by: Matt Roper 


I will fix that up while pushing. Thanks.
Lucas De Marchi


RE: Making drm_gpuvm work across gpu devices

2024-01-23 Thread Zeng, Oak
Thanks a lot Danilo.

Maybe I wasn't clear enough. In the solution I proposed, each device still have 
separate vm/page tables. Each device still need to manage the mapping, page 
table flags etc. It is just in svm use case, all devices share one drm_gpuvm 
instance. As I understand it, drm_gpuvm's main function is the va range split 
and merging. I don't see why it doesn't work across gpu devices. 

But I read more about drm_gpuvm. Its split merge function takes a 
drm_gem_object parameter, see drm_gpuvm_sm_map_ops_create and drm_gpuvm_sm_map. 
Actually the whole drm_gpuvm is designed for BO-centric driver, for example, it 
has a drm_gpuvm_bo concept to keep track of the 1BO:Ngpuva mapping. The whole 
purpose of leveraging drm_gpuvm is to re-use the va split/merge functions for 
SVM. But in our SVM implementation, there is no buffer object at all. So I 
don't think our SVM codes can leverage drm_gpuvm.

I will give up this approach, unless Matt or Brian can see a way.

A few replies inline @Welty, Brian I had more thoughts inline to one of 
your original question

> -Original Message-
> From: Danilo Krummrich 
> Sent: Tuesday, January 23, 2024 6:57 PM
> To: Zeng, Oak ; Christian König
> ; Dave Airlie ; Daniel Vetter
> ; Felix Kuehling 
> Cc: Welty, Brian ; dri-devel@lists.freedesktop.org; 
> intel-
> x...@lists.freedesktop.org; Bommu, Krishnaiah ;
> Ghimiray, Himal Prasad ;
> thomas.hellst...@linux.intel.com; Vishwanathapura, Niranjana
> ; Brost, Matthew
> ; Gupta, saurabhg 
> Subject: Re: Making drm_gpuvm work across gpu devices
> 
> Hi Oak,
> 
> On 1/23/24 20:37, Zeng, Oak wrote:
> > Thanks Christian. I have some comment inline below.
> >
> > Danilo, can you also take a look and give your feedback? Thanks.
> 
> I agree with everything Christian already wrote. Except for the KFD parts, 
> which
> I'm simply not familiar with, I had exactly the same thoughts after reading 
> your
> initial mail.
> 
> Please find some more comments below.
> 
> >
> >> -Original Message-
> >> From: Christian König 
> >> Sent: Tuesday, January 23, 2024 6:13 AM
> >> To: Zeng, Oak ; Danilo Krummrich ;
> >> Dave Airlie ; Daniel Vetter 
> >> Cc: Welty, Brian ; dri-devel@lists.freedesktop.org;
> intel-
> >> x...@lists.freedesktop.org; Bommu, Krishnaiah
> ;
> >> Ghimiray, Himal Prasad ;
> >> thomas.hellst...@linux.intel.com; Vishwanathapura, Niranjana
> >> ; Brost, Matthew
> >> 
> >> Subject: Re: Making drm_gpuvm work across gpu devices
> >>
> >> Hi Oak,
> >>
> >> Am 23.01.24 um 04:21 schrieb Zeng, Oak:
> >>> Hi Danilo and all,
> >>>
> >>> During the work of Intel's SVM code, we came up the idea of making
> >> drm_gpuvm to work across multiple gpu devices. See some discussion here:
> >> https://lore.kernel.org/dri-
> >>
> devel/PH7PR11MB70049E7E6A2F40BF6282ECC292742@PH7PR11MB7004.namprd
> >> 11.prod.outlook.com/
> >>>
> >>> The reason we try to do this is, for a SVM (shared virtual memory across 
> >>> cpu
> >> program and all gpu program on all gpu devices) process, the address space
> has
> >> to be across all gpu devices. So if we make drm_gpuvm to work across 
> >> devices,
> >> then our SVM code can leverage drm_gpuvm as well.
> >>>
> >>> At a first look, it seems feasible because drm_gpuvm doesn't really use 
> >>> the
> >> drm_device *drm pointer a lot. This param is used only for 
> >> printing/warning.
> So I
> >> think maybe we can delete this drm field from drm_gpuvm.
> >>>
> >>> This way, on a multiple gpu device system, for one process, we can have 
> >>> only
> >> one drm_gpuvm instance, instead of multiple drm_gpuvm instances (one for
> >> each gpu device).
> >>>
> >>> What do you think?
> >>
> >> Well from the GPUVM side I don't think it would make much difference if
> >> we have the drm device or not.
> >>
> >> But the experience we had with the KFD I think I should mention that we
> >> should absolutely *not* deal with multiple devices at the same time in
> >> the UAPI or VM objects inside the driver.
> >>
> >> The background is that all the APIs inside the Linux kernel are build
> >> around the idea that they work with only one device at a time. This
> >> accounts for both low level APIs like the DMA API as well as pretty high
> >> level things like for example file system address space etc...
> >
> > Yes most API are per device based.
> >
> > One exception I know is actually the kfd SVM API. If you look at the 
> > svm_ioctl
> function, it is per-process based. Each kfd_process represent a process 
> across N
> gpu devices. Cc Felix.
> >
> > Need to say, kfd SVM represent a shared virtual address space across CPU and
> all GPU devices on the system. This is by the definition of SVM (shared 
> virtual
> memory). This is very different from our legacy gpu *device* driver which 
> works
> for only one device (i.e., if you want one device to access another device's
> memory, you will have to use dma-buf export/import etc).
> >
> > We have the same design requirement of SVM. For anyone who 

Re: [PATCH] drm/xe: Remove PVC from xe_wa kunit tests

2024-01-23 Thread Matt Roper
On Mon, Jan 22, 2024 at 07:12:42PM -0800, Lucas De Marchi wrote:
> Since the PCI IDs for PVC were added to the xe driver, the xe_wa tests

This first line doesn't seem to be worded right.  I think you meant
either "weren't added" or "were only added to topic/xe-for-CI."

Assuming you can reword that,

Reviewed-by: Matt Roper 

> should not try to create a fake PVC device since they can't find
> the right PCI ID. Fix bugs when running kunit:
> 
>   # xe_wa_gt: ASSERTION FAILED at 
> drivers/gpu/drm/xe/tests/xe_wa_test.c:111
>   Expected ret == 0, but
>   ret == -19 (0xffed)
>   [FAILED] PVC (B0)
>   # xe_wa_gt: ASSERTION FAILED at 
> drivers/gpu/drm/xe/tests/xe_wa_test.c:111
>   Expected ret == 0, but
>   ret == -19 (0xffed)
>   [FAILED] PVC (B1)
>   # xe_wa_gt: ASSERTION FAILED at 
> drivers/gpu/drm/xe/tests/xe_wa_test.c:111
>   Expected ret == 0, but
>   ret == -19 (0xffed)
>   [FAILED] PVC (C0)
> 
> Fixes: dd08ebf6c352 ("drm/xe: Introduce a new DRM driver for Intel GPUs")
> Signed-off-by: Lucas De Marchi 
> ---
>  drivers/gpu/drm/xe/tests/xe_wa_test.c | 3 ---
>  1 file changed, 3 deletions(-)
> 
> diff --git a/drivers/gpu/drm/xe/tests/xe_wa_test.c 
> b/drivers/gpu/drm/xe/tests/xe_wa_test.c
> index 439477593faf..44570d888355 100644
> --- a/drivers/gpu/drm/xe/tests/xe_wa_test.c
> +++ b/drivers/gpu/drm/xe/tests/xe_wa_test.c
> @@ -69,9 +69,6 @@ static const struct platform_test_case cases[] = {
>   SUBPLATFORM_CASE(DG2, G10, C0),
>   SUBPLATFORM_CASE(DG2, G11, B1),
>   SUBPLATFORM_CASE(DG2, G12, A1),
> - PLATFORM_CASE(PVC, B0),
> - PLATFORM_CASE(PVC, B1),
> - PLATFORM_CASE(PVC, C0),
>   GMDID_CASE(METEORLAKE, 1270, A0, 1300, A0),
>   GMDID_CASE(METEORLAKE, 1271, A0, 1300, A0),
>   GMDID_CASE(LUNARLAKE, 2004, A0, 2000, A0),
> -- 
> 2.43.0
> 

-- 
Matt Roper
Graphics Software Engineer
Linux GPU Platform Enablement
Intel Corporation


[linux-next:master] BUILD REGRESSION 774551425799cb5bbac94e1768fd69eec4f78dd4

2024-01-23 Thread kernel test robot
tree/branch: 
https://git.kernel.org/pub/scm/linux/kernel/git/next/linux-next.git master
branch HEAD: 774551425799cb5bbac94e1768fd69eec4f78dd4  Add linux-next specific 
files for 20240123

Error/Warning reports:

https://lore.kernel.org/oe-kbuild-all/202401231518.8q9ld8n7-...@intel.com
https://lore.kernel.org/oe-kbuild-all/202401240123.wbsfom3z-...@intel.com

Error/Warning: (recently discovered and may have been fixed)

drivers/dma/at_hdmac.c:255: warning: Enum value 'ATC_IS_CYCLIC' not described 
in enum 'atc_status'
drivers/dma/at_hdmac.c:255: warning: Enum value 'ATC_IS_PAUSED' not described 
in enum 'atc_status'

Error/Warning ids grouped by kconfigs:

gcc_recent_errors
|-- arc-randconfig-r062-20240123
|   `-- drivers-gpu-drm-etnaviv-etnaviv_drv.c:ERROR:probable-double-put.
|-- arm-multi_v5_defconfig
|   |-- 
drivers-dma-at_hdmac.c:warning:Enum-value-ATC_IS_CYCLIC-not-described-in-enum-atc_status
|   `-- 
drivers-dma-at_hdmac.c:warning:Enum-value-ATC_IS_PAUSED-not-described-in-enum-atc_status
|-- i386-randconfig-051-20240123
|   `-- drivers-gpu-drm-etnaviv-etnaviv_drv.c:ERROR:probable-double-put.
|-- i386-randconfig-054-20240123
|   `-- drivers-gpu-drm-etnaviv-etnaviv_drv.c:ERROR:probable-double-put.
|-- i386-randconfig-062-20240123
|   |-- 
drivers-usb-gadget-function-f_ncm.c:sparse:sparse:incorrect-type-in-assignment-(different-base-types)-expected-unsigned-short-usertype-max_segment_size-got-restricted-__le16-usertype
|   `-- 
lib-checksum_kunit.c:sparse:sparse:incorrect-type-in-argument-(different-base-types)-expected-restricted-__wsum-usertype-sum-got-unsigned-int-assigned-csum
|-- i386-randconfig-141-20240123
|   |-- 
fs-bcachefs-btree_locking.c-bch2_trans_relock()-warn:passing-zero-to-PTR_ERR
|   |-- 
fs-bcachefs-buckets.c-bch2_trans_account_disk_usage_change()-error:we-previously-assumed-trans-disk_res-could-be-null-(see-line-)
|   `-- 
mm-huge_memory.c-thpsize_create()-warn:Calling-kobject_put-get-with-state-initialized-unset-from-line:
|-- microblaze-randconfig-r064-20240123
|   `-- drivers-gpu-drm-etnaviv-etnaviv_drv.c:ERROR:probable-double-put.
|-- microblaze-randconfig-r123-20240123
|   `-- 
drivers-regulator-qcom_smd-regulator.c:sparse:sparse:symbol-smd_vreg_rpm-was-not-declared.-Should-it-be-static
|-- mips-allyesconfig
|   |-- 
(.ref.text):relocation-truncated-to-fit:R_MIPS_26-against-start_secondary
|   `-- (.text):relocation-truncated-to-fit:R_MIPS_26-against-kernel_entry
|-- nios2-randconfig-r052-20240123
|   `-- drivers-gpu-drm-etnaviv-etnaviv_drv.c:ERROR:probable-double-put.
|-- nios2-randconfig-r054-20240123
|   `-- drivers-gpu-drm-etnaviv-etnaviv_drv.c:ERROR:probable-double-put.
|-- openrisc-randconfig-r131-20240123
|   `-- 
lib-checksum_kunit.c:sparse:sparse:incorrect-type-in-argument-(different-base-types)-expected-restricted-__wsum-usertype-csum-got-unsigned-int-assigned-csum
|-- sh-randconfig-r133-20240123
|   `-- 
lib-checksum_kunit.c:sparse:sparse:incorrect-type-in-argument-(different-base-types)-expected-restricted-__wsum-usertype-sum-got-unsigned-int-assigned-csum
|-- x86_64-randconfig-101-20240123
|   `-- drivers-gpu-drm-etnaviv-etnaviv_drv.c:ERROR:probable-double-put.
|-- x86_64-randconfig-102-20240123
|   `-- drivers-gpu-drm-etnaviv-etnaviv_drv.c:ERROR:probable-double-put.
`-- x86_64-randconfig-161-20240123
|-- 
mm-huge_memory.c-thpsize_create()-warn:Calling-kobject_put-get-with-state-initialized-unset-from-line:
|-- 
mm-kasan-kasan_test.c-mempool_double_free_helper()-error:double-free-of-elem
`-- 
mm-kasan-kasan_test.c-mempool_uaf_helper()-warn:passing-freed-memory-elem
clang_recent_errors
|-- x86_64-randconfig-121-20240123
|   `-- 
lib-checksum_kunit.c:sparse:sparse:incorrect-type-in-argument-(different-base-types)-expected-restricted-__wsum-usertype-csum-got-unsigned-int-assigned-csum
`-- x86_64-randconfig-r132-20240123
`-- 
lib-checksum_kunit.c:sparse:sparse:incorrect-type-in-argument-(different-base-types)-expected-restricted-__wsum-usertype-csum-got-unsigned-int-assigned-csum

elapsed time: 1483m

configs tested: 177
configs skipped: 3

tested configs:
alpha allnoconfig   gcc  
alphaallyesconfig   gcc  
alpha   defconfig   gcc  
arc  allmodconfig   gcc  
arc   allnoconfig   gcc  
arc  allyesconfig   gcc  
arc defconfig   gcc  
arc   randconfig-001-20240123   gcc  
arc   randconfig-002-20240123   gcc  
arm  allmodconfig   gcc  
arm   allnoconfig   gcc  
arm  allyesconfig   gcc  
arm   aspeed_g5_defconfig   gcc  
arm defconfig   clang
arm  ixp4xx_defconfig   clang
armmps2_defconfig   gcc  
armmvebu_v7_defconfig

[PATCH v2 8/8] drm/lima: standardize debug messages by ip name

2024-01-23 Thread Erico Nunes
Some debug messages carried the ip name, or included "lima", or
included both the ip name and then the numbered ip name again.
Make the messages more consistent by always looking up and showing
the ip name first.

Signed-off-by: Erico Nunes 
---
 drivers/gpu/drm/lima/lima_gp.c   | 20 +++-
 drivers/gpu/drm/lima/lima_l2_cache.c |  6 --
 drivers/gpu/drm/lima/lima_mmu.c  | 18 +-
 drivers/gpu/drm/lima/lima_pmu.c  |  3 ++-
 drivers/gpu/drm/lima/lima_pp.c   | 19 ++-
 5 files changed, 36 insertions(+), 30 deletions(-)

diff --git a/drivers/gpu/drm/lima/lima_gp.c b/drivers/gpu/drm/lima/lima_gp.c
index 4355fa7b17f4..6b354e2fb61d 100644
--- a/drivers/gpu/drm/lima/lima_gp.c
+++ b/drivers/gpu/drm/lima/lima_gp.c
@@ -34,11 +34,11 @@ static irqreturn_t lima_gp_irq_handler(int irq, void *data)
if (state & LIMA_GP_IRQ_MASK_ERROR) {
if ((state & LIMA_GP_IRQ_MASK_ERROR) ==
LIMA_GP_IRQ_PLBU_OUT_OF_MEM) {
-   dev_dbg(dev->dev, "gp out of heap irq status=%x\n",
-   status);
+   dev_dbg(dev->dev, "%s out of heap irq status=%x\n",
+   lima_ip_name(ip), status);
} else {
-   dev_err(dev->dev, "gp error irq state=%x status=%x\n",
-   state, status);
+   dev_err(dev->dev, "%s error irq state=%x status=%x\n",
+   lima_ip_name(ip), state, status);
if (task)
task->recoverable = false;
}
@@ -89,7 +89,8 @@ static int lima_gp_soft_reset_async_wait(struct lima_ip *ip)
 v & LIMA_GP_IRQ_RESET_COMPLETED,
 0, 100);
if (err) {
-   dev_err(dev->dev, "gp soft reset time out\n");
+   dev_err(dev->dev, "%s soft reset time out\n",
+   lima_ip_name(ip));
return err;
}
 
@@ -194,7 +195,7 @@ static int lima_gp_hard_reset(struct lima_ip *ip)
gp_write(LIMA_GP_CMD, LIMA_GP_CMD_RESET);
ret = lima_poll_timeout(ip, lima_gp_hard_reset_poll, 10, 100);
if (ret) {
-   dev_err(dev->dev, "gp hard reset timeout\n");
+   dev_err(dev->dev, "%s hard reset timeout\n", lima_ip_name(ip));
return ret;
}
 
@@ -220,8 +221,9 @@ static void lima_gp_task_error(struct lima_sched_pipe *pipe)
 {
struct lima_ip *ip = pipe->processor[0];
 
-   dev_err(ip->dev->dev, "gp task error int_state=%x status=%x\n",
-   gp_read(LIMA_GP_INT_STAT), gp_read(LIMA_GP_STATUS));
+   dev_err(ip->dev->dev, "%s task error int_state=%x status=%x\n",
+   lima_ip_name(ip), gp_read(LIMA_GP_INT_STAT),
+   gp_read(LIMA_GP_STATUS));
 
lima_gp_hard_reset(ip);
 }
@@ -324,7 +326,7 @@ int lima_gp_init(struct lima_ip *ip)
err = devm_request_irq(dev->dev, ip->irq, lima_gp_irq_handler,
   IRQF_SHARED, lima_ip_name(ip), ip);
if (err) {
-   dev_err(dev->dev, "gp %s fail to request irq\n",
+   dev_err(dev->dev, "%s fail to request irq\n",
lima_ip_name(ip));
return err;
}
diff --git a/drivers/gpu/drm/lima/lima_l2_cache.c 
b/drivers/gpu/drm/lima/lima_l2_cache.c
index c4080a02957b..184106ce55f8 100644
--- a/drivers/gpu/drm/lima/lima_l2_cache.c
+++ b/drivers/gpu/drm/lima/lima_l2_cache.c
@@ -21,7 +21,8 @@ static int lima_l2_cache_wait_idle(struct lima_ip *ip)
 !(v & LIMA_L2_CACHE_STATUS_COMMAND_BUSY),
 0, 1000);
if (err) {
-   dev_err(dev->dev, "l2 cache wait command timeout\n");
+   dev_err(dev->dev, "%s wait command timeout\n",
+   lima_ip_name(ip));
return err;
}
return 0;
@@ -83,7 +84,8 @@ int lima_l2_cache_init(struct lima_ip *ip)
spin_lock_init(>data.lock);
 
size = l2_cache_read(LIMA_L2_CACHE_SIZE);
-   dev_info(dev->dev, "l2 cache %uK, %u-way, %ubyte cache line, %ubit 
external bus\n",
+   dev_info(dev->dev, "%s %uK, %u-way, %ubyte cache line, %ubit external 
bus\n",
+lima_ip_name(ip),
 1 << (((size >> 16) & 0xff) - 10),
 1 << ((size >> 8) & 0xff),
 1 << (size & 0xff),
diff --git a/drivers/gpu/drm/lima/lima_mmu.c b/drivers/gpu/drm/lima/lima_mmu.c
index a1ae6c252dc2..e18317c5ca8c 100644
--- a/drivers/gpu/drm/lima/lima_mmu.c
+++ b/drivers/gpu/drm/lima/lima_mmu.c
@@ -22,7 +22,8 @@
  cond, 0, 100); \
if (__ret)   \
dev_err(dev->dev,\
-   "mmu command %x timeout\n", 

[PATCH v2 5/8] drm/lima: handle spurious timeouts due to high irq latency

2024-01-23 Thread Erico Nunes
There are several unexplained and unreproduced cases of rendering
timeouts with lima, for which one theory is high IRQ latency coming from
somewhere else in the system.
This kind of occurrence may cause applications to trigger unnecessary
resets of the GPU or even applications to hang if it hits an issue in
the recovery path.
Panfrost already does some special handling to account for such
"spurious timeouts", it makes sense to have this in lima too to reduce
the chance that it hit users.

Signed-off-by: Erico Nunes 
---
 drivers/gpu/drm/lima/lima_sched.c | 31 ---
 1 file changed, 28 insertions(+), 3 deletions(-)

diff --git a/drivers/gpu/drm/lima/lima_sched.c 
b/drivers/gpu/drm/lima/lima_sched.c
index c3bf8cda8498..814428564637 100644
--- a/drivers/gpu/drm/lima/lima_sched.c
+++ b/drivers/gpu/drm/lima/lima_sched.c
@@ -1,6 +1,7 @@
 // SPDX-License-Identifier: GPL-2.0 OR MIT
 /* Copyright 2017-2019 Qiang Yu  */
 
+#include 
 #include 
 #include 
 #include 
@@ -401,9 +402,35 @@ static enum drm_gpu_sched_stat 
lima_sched_timedout_job(struct drm_sched_job *job
struct lima_sched_pipe *pipe = to_lima_pipe(job->sched);
struct lima_sched_task *task = to_lima_task(job);
struct lima_device *ldev = pipe->ldev;
+   struct lima_ip *ip = pipe->processor[0];
+   int i;
+
+   /*
+* If the GPU managed to complete this jobs fence, the timeout is
+* spurious. Bail out.
+*/
+   if (dma_fence_is_signaled(task->fence)) {
+   DRM_WARN("%s spurious timeout\n", lima_ip_name(ip));
+   return DRM_GPU_SCHED_STAT_NOMINAL;
+   }
+
+   /*
+* Lima IRQ handler may take a long time to process an interrupt
+* if there is another IRQ handler hogging the processing.
+* In order to catch such cases and not report spurious Lima job
+* timeouts, synchronize the IRQ handler and re-check the fence
+* status.
+*/
+   for (i = 0; i < pipe->num_processor; i++)
+   synchronize_irq(pipe->processor[i]->irq);
+
+   if (dma_fence_is_signaled(task->fence)) {
+   DRM_WARN("%s unexpectedly high interrupt latency\n", 
lima_ip_name(ip));
+   return DRM_GPU_SCHED_STAT_NOMINAL;
+   }
 
if (!pipe->error)
-   DRM_ERROR("lima job timeout\n");
+   DRM_ERROR("%s job timeout\n", lima_ip_name(ip));
 
drm_sched_stop(>base, >base);
 
@@ -417,8 +444,6 @@ static enum drm_gpu_sched_stat 
lima_sched_timedout_job(struct drm_sched_job *job
if (pipe->bcast_mmu)
lima_mmu_page_fault_resume(pipe->bcast_mmu);
else {
-   int i;
-
for (i = 0; i < pipe->num_mmu; i++)
lima_mmu_page_fault_resume(pipe->mmu[i]);
}
-- 
2.43.0



[PATCH v2 7/8] drm/lima: increase default job timeout to 10s

2024-01-23 Thread Erico Nunes
The previous 500ms default timeout was fairly optimistic and could be
hit by real world applications. Many distributions targeting devices
with a Mali-4xx already bumped this timeout to a higher limit.
We can be generous here with a high value as 10s since this should
mostly catch buggy jobs like infinite loop shaders, and these don't
seem to happen very often in real applications.

Signed-off-by: Erico Nunes 
---
 drivers/gpu/drm/lima/lima_sched.c | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/drivers/gpu/drm/lima/lima_sched.c 
b/drivers/gpu/drm/lima/lima_sched.c
index c2e78605e43e..00b19adfc888 100644
--- a/drivers/gpu/drm/lima/lima_sched.c
+++ b/drivers/gpu/drm/lima/lima_sched.c
@@ -505,7 +505,7 @@ static void lima_sched_recover_work(struct work_struct 
*work)
 int lima_sched_pipe_init(struct lima_sched_pipe *pipe, const char *name)
 {
unsigned int timeout = lima_sched_timeout_ms > 0 ?
-  lima_sched_timeout_ms : 500;
+  lima_sched_timeout_ms : 1;
 
pipe->fence_context = dma_fence_context_alloc(1);
spin_lock_init(>fence_lock);
-- 
2.43.0



[PATCH v2 4/8] drm/lima: set gp bus_stop bit before hard reset

2024-01-23 Thread Erico Nunes
This is required for reliable hard resets. Otherwise, doing a hard reset
while a task is still running (such as a task which is being stopped by
the drm_sched timeout handler) may result in random mmu write timeouts
or lockups which cause the entire gpu to hang.

Signed-off-by: Erico Nunes 
---
 drivers/gpu/drm/lima/lima_gp.c | 12 
 1 file changed, 12 insertions(+)

diff --git a/drivers/gpu/drm/lima/lima_gp.c b/drivers/gpu/drm/lima/lima_gp.c
index b9a06e701a33..4355fa7b17f4 100644
--- a/drivers/gpu/drm/lima/lima_gp.c
+++ b/drivers/gpu/drm/lima/lima_gp.c
@@ -166,6 +166,11 @@ static void lima_gp_task_run(struct lima_sched_pipe *pipe,
gp_write(LIMA_GP_CMD, cmd);
 }
 
+static int lima_gp_bus_stop_poll(struct lima_ip *ip)
+{
+   return !!(gp_read(LIMA_GP_STATUS) & LIMA_GP_STATUS_BUS_STOPPED);
+}
+
 static int lima_gp_hard_reset_poll(struct lima_ip *ip)
 {
gp_write(LIMA_GP_PERF_CNT_0_LIMIT, 0xC01A);
@@ -179,6 +184,13 @@ static int lima_gp_hard_reset(struct lima_ip *ip)
 
gp_write(LIMA_GP_PERF_CNT_0_LIMIT, 0xC0FFE000);
gp_write(LIMA_GP_INT_MASK, 0);
+
+   gp_write(LIMA_GP_CMD, LIMA_GP_CMD_STOP_BUS);
+   ret = lima_poll_timeout(ip, lima_gp_bus_stop_poll, 10, 100);
+   if (ret) {
+   dev_err(dev->dev, "%s bus stop timeout\n", lima_ip_name(ip));
+   return ret;
+   }
gp_write(LIMA_GP_CMD, LIMA_GP_CMD_RESET);
ret = lima_poll_timeout(ip, lima_gp_hard_reset_poll, 10, 100);
if (ret) {
-- 
2.43.0



[PATCH v2 2/8] drm/lima: reset async_reset on gp hard reset

2024-01-23 Thread Erico Nunes
Lima gp jobs use an async reset to avoid having to wait for the soft
reset right after a job. The soft reset is done at the end of a job and
a reset_complete flag is expected to be set at the next job.
However, in case the user runs into a job timeout from any application,
a hard reset is issued to the hardware. This hard reset clears the
reset_complete flag, which causes an error message to show up before the
next job.
This is probably harmless for the execution but can be very confusing to
debug, as it blames a reset timeout on the next application to submit a
job.
Reset the async_reset flag when doing the hard reset so that we don't
get that message.

Signed-off-by: Erico Nunes 
---
 drivers/gpu/drm/lima/lima_gp.c | 7 +++
 1 file changed, 7 insertions(+)

diff --git a/drivers/gpu/drm/lima/lima_gp.c b/drivers/gpu/drm/lima/lima_gp.c
index 8dd501b7a3d0..b9a06e701a33 100644
--- a/drivers/gpu/drm/lima/lima_gp.c
+++ b/drivers/gpu/drm/lima/lima_gp.c
@@ -189,6 +189,13 @@ static int lima_gp_hard_reset(struct lima_ip *ip)
gp_write(LIMA_GP_PERF_CNT_0_LIMIT, 0);
gp_write(LIMA_GP_INT_CLEAR, LIMA_GP_IRQ_MASK_ALL);
gp_write(LIMA_GP_INT_MASK, LIMA_GP_IRQ_MASK_USED);
+
+   /*
+* if there was an async soft reset queued,
+* don't wait for it in the next job
+*/
+   ip->data.async_reset = false;
+
return 0;
 }
 
-- 
2.43.0



[PATCH v2 6/8] drm/lima: remove guilty drm_sched context handling

2024-01-23 Thread Erico Nunes
Marking the context as guilty currently only makes the application which
hits a single timeout problem to stop its rendering context entirely.
All jobs submitted later are dropped from the guilty context.

Lima runs on fairly underpowered hardware for modern standards and it is
not entirely unreasonable that a rendering job may time out occasionally
due to high system load or too demanding application stack. In this case
it would be generally preferred to report the error but try to keep the
application going.

Other similar embedded GPU drivers don't make use of the guilty context
flag. Now that there are reliability improvements to the lima timeout
recovery handling, drop the guilty contexts to let the application keep
running in this case.

Signed-off-by: Erico Nunes 
Acked-by: Christian König 
Reviewed-by: Vasily Khoruzhick 
---
 drivers/gpu/drm/lima/lima_ctx.c   | 2 +-
 drivers/gpu/drm/lima/lima_ctx.h   | 1 -
 drivers/gpu/drm/lima/lima_sched.c | 5 ++---
 drivers/gpu/drm/lima/lima_sched.h | 3 +--
 4 files changed, 4 insertions(+), 7 deletions(-)

diff --git a/drivers/gpu/drm/lima/lima_ctx.c b/drivers/gpu/drm/lima/lima_ctx.c
index 8389f2d7d021..0e668fc1e0f9 100644
--- a/drivers/gpu/drm/lima/lima_ctx.c
+++ b/drivers/gpu/drm/lima/lima_ctx.c
@@ -19,7 +19,7 @@ int lima_ctx_create(struct lima_device *dev, struct 
lima_ctx_mgr *mgr, u32 *id)
kref_init(>refcnt);
 
for (i = 0; i < lima_pipe_num; i++) {
-   err = lima_sched_context_init(dev->pipe + i, ctx->context + i, 
>guilty);
+   err = lima_sched_context_init(dev->pipe + i, ctx->context + i);
if (err)
goto err_out0;
}
diff --git a/drivers/gpu/drm/lima/lima_ctx.h b/drivers/gpu/drm/lima/lima_ctx.h
index 74e2be09090f..5b1063ce968b 100644
--- a/drivers/gpu/drm/lima/lima_ctx.h
+++ b/drivers/gpu/drm/lima/lima_ctx.h
@@ -13,7 +13,6 @@ struct lima_ctx {
struct kref refcnt;
struct lima_device *dev;
struct lima_sched_context context[lima_pipe_num];
-   atomic_t guilty;
 
/* debug info */
char pname[TASK_COMM_LEN];
diff --git a/drivers/gpu/drm/lima/lima_sched.c 
b/drivers/gpu/drm/lima/lima_sched.c
index 814428564637..c2e78605e43e 100644
--- a/drivers/gpu/drm/lima/lima_sched.c
+++ b/drivers/gpu/drm/lima/lima_sched.c
@@ -154,13 +154,12 @@ void lima_sched_task_fini(struct lima_sched_task *task)
 }
 
 int lima_sched_context_init(struct lima_sched_pipe *pipe,
-   struct lima_sched_context *context,
-   atomic_t *guilty)
+   struct lima_sched_context *context)
 {
struct drm_gpu_scheduler *sched = >base;
 
return drm_sched_entity_init(>base, DRM_SCHED_PRIORITY_NORMAL,
-, 1, guilty);
+, 1, NULL);
 }
 
 void lima_sched_context_fini(struct lima_sched_pipe *pipe,
diff --git a/drivers/gpu/drm/lima/lima_sched.h 
b/drivers/gpu/drm/lima/lima_sched.h
index 6a11764d87b3..6bd4f3b70109 100644
--- a/drivers/gpu/drm/lima/lima_sched.h
+++ b/drivers/gpu/drm/lima/lima_sched.h
@@ -91,8 +91,7 @@ int lima_sched_task_init(struct lima_sched_task *task,
 void lima_sched_task_fini(struct lima_sched_task *task);
 
 int lima_sched_context_init(struct lima_sched_pipe *pipe,
-   struct lima_sched_context *context,
-   atomic_t *guilty);
+   struct lima_sched_context *context);
 void lima_sched_context_fini(struct lima_sched_pipe *pipe,
 struct lima_sched_context *context);
 struct dma_fence *lima_sched_context_queue_task(struct lima_sched_task *task);
-- 
2.43.0



[PATCH v2 3/8] drm/lima: set pp bus_stop bit before hard reset

2024-01-23 Thread Erico Nunes
This is required for reliable hard resets. Otherwise, doing a hard reset
while a task is still running (such as a task which is being stopped by
the drm_sched timeout handler) may result in random mmu write timeouts
or lockups which cause the entire gpu to hang.

Signed-off-by: Erico Nunes 
Reviewed-by: Vasily Khoruzhick 
---
 drivers/gpu/drm/lima/lima_pp.c | 13 +
 1 file changed, 13 insertions(+)

diff --git a/drivers/gpu/drm/lima/lima_pp.c b/drivers/gpu/drm/lima/lima_pp.c
index a8f8f63b8295..ac097dd75072 100644
--- a/drivers/gpu/drm/lima/lima_pp.c
+++ b/drivers/gpu/drm/lima/lima_pp.c
@@ -168,6 +168,11 @@ static void lima_pp_write_frame(struct lima_ip *ip, u32 
*frame, u32 *wb)
}
 }
 
+static int lima_pp_bus_stop_poll(struct lima_ip *ip)
+{
+   return !!(pp_read(LIMA_PP_STATUS) & LIMA_PP_STATUS_BUS_STOPPED);
+}
+
 static int lima_pp_hard_reset_poll(struct lima_ip *ip)
 {
pp_write(LIMA_PP_PERF_CNT_0_LIMIT, 0xC01A);
@@ -181,6 +186,14 @@ static int lima_pp_hard_reset(struct lima_ip *ip)
 
pp_write(LIMA_PP_PERF_CNT_0_LIMIT, 0xC0FFE000);
pp_write(LIMA_PP_INT_MASK, 0);
+
+   pp_write(LIMA_PP_CTRL, LIMA_PP_CTRL_STOP_BUS);
+   ret = lima_poll_timeout(ip, lima_pp_bus_stop_poll, 10, 100);
+   if (ret) {
+   dev_err(dev->dev, "pp %s bus stop timeout\n", lima_ip_name(ip));
+   return ret;
+   }
+
pp_write(LIMA_PP_CTRL, LIMA_PP_CTRL_FORCE_RESET);
ret = lima_poll_timeout(ip, lima_pp_hard_reset_poll, 10, 100);
if (ret) {
-- 
2.43.0



[PATCH v2 0/8] drm/lima: fixes and improvements to error recovery

2024-01-23 Thread Erico Nunes
v1 reference:
https://patchwork.kernel.org/project/dri-devel/cover/20240117031212.1104034-1-nunes.er...@gmail.com/

Changes v1 -> v2:
- Dropped patch 1 which aimed to fix
https://gitlab.freedesktop.org/mesa/mesa/-/issues/8415 .
That will require more testing and an actual fix to the irq/timeout
handler race. It can be solved separately so I am deferring it to a
followup patch and keeping that issue open.

- Added patches 2 and 4 to cover "reset time out" and bus stop bit to
hard reset in gp as well.

- Added handling of all processors in synchronize_irq in patch 5 to
cover multiple pp. Dropped unnecessary duplicate fence in patch 5.

- Added patch 7 in v2. After some discussion in patch 4 (v1), it seems
to be reasonable to bump our timeout value so that we further decrease
the chance of users actually hitting any of these timeouts by default.

- Reworked patch 8 in v2. Since I broadened the work to not only focus
in pp anymore, I also included the change to the other blocks as well.

- Collected some reviews and acks in unmodified patches.


Erico Nunes (8):
  drm/lima: reset async_reset on pp hard reset
  drm/lima: reset async_reset on gp hard reset
  drm/lima: set pp bus_stop bit before hard reset
  drm/lima: set gp bus_stop bit before hard reset
  drm/lima: handle spurious timeouts due to high irq latency
  drm/lima: remove guilty drm_sched context handling
  drm/lima: increase default job timeout to 10s
  drm/lima: standardize debug messages by ip name

 drivers/gpu/drm/lima/lima_ctx.c  |  2 +-
 drivers/gpu/drm/lima/lima_ctx.h  |  1 -
 drivers/gpu/drm/lima/lima_gp.c   | 39 +---
 drivers/gpu/drm/lima/lima_l2_cache.c |  6 +++--
 drivers/gpu/drm/lima/lima_mmu.c  | 18 ++---
 drivers/gpu/drm/lima/lima_pmu.c  |  3 ++-
 drivers/gpu/drm/lima/lima_pp.c   | 37 --
 drivers/gpu/drm/lima/lima_sched.c| 38 ++-
 drivers/gpu/drm/lima/lima_sched.h|  3 +--
 9 files changed, 107 insertions(+), 40 deletions(-)

-- 
2.43.0



[PATCH v2 1/8] drm/lima: reset async_reset on pp hard reset

2024-01-23 Thread Erico Nunes
Lima pp jobs use an async reset to avoid having to wait for the soft
reset right after a job. The soft reset is done at the end of a job and
a reset_complete flag is expected to be set at the next job.
However, in case the user runs into a job timeout from any application,
a hard reset is issued to the hardware. This hard reset clears the
reset_complete flag, which causes an error message to show up before the
next job.
This is probably harmless for the execution but can be very confusing to
debug, as it blames a reset timeout on the next application to submit a
job.
Reset the async_reset flag when doing the hard reset so that we don't
get that message.

Signed-off-by: Erico Nunes 
Reviewed-by: Vasily Khoruzhick 
---
 drivers/gpu/drm/lima/lima_pp.c | 7 +++
 1 file changed, 7 insertions(+)

diff --git a/drivers/gpu/drm/lima/lima_pp.c b/drivers/gpu/drm/lima/lima_pp.c
index a5c95bed08c0..a8f8f63b8295 100644
--- a/drivers/gpu/drm/lima/lima_pp.c
+++ b/drivers/gpu/drm/lima/lima_pp.c
@@ -191,6 +191,13 @@ static int lima_pp_hard_reset(struct lima_ip *ip)
pp_write(LIMA_PP_PERF_CNT_0_LIMIT, 0);
pp_write(LIMA_PP_INT_CLEAR, LIMA_PP_IRQ_MASK_ALL);
pp_write(LIMA_PP_INT_MASK, LIMA_PP_IRQ_MASK_USED);
+
+   /*
+* if there was an async soft reset queued,
+* don't wait for it in the next job
+*/
+   ip->data.async_reset = false;
+
return 0;
 }
 
-- 
2.43.0



Re: [PATCH] drm/Makefile: Move tiny drivers before native drivers

2024-01-23 Thread Huacai Chen
Hi, Javier and Thomas,

On Wed, Jan 24, 2024 at 5:21 AM Jaak Ristioja  wrote:
>
> Hi,
>
> I apologize for not finding the time to test this earlier.
>
> On 11.12.23 05:08, Huacai Chen wrote:
> > And Jaak, could you please test with the below patch (but keep the
> > original order in Makefile) and then give me the dmesg output?
> >
> > diff --git a/drivers/video/aperture.c b/drivers/video/aperture.c
> > index 561be8feca96..cc2e39fb98f5 100644
> > --- a/drivers/video/aperture.c
> > +++ b/drivers/video/aperture.c
> > @@ -350,21 +350,29 @@ int
> > aperture_remove_conflicting_pci_devices(struct pci_dev *pdev, const
> > char *na
> >  resource_size_t base, size;
> >  int bar, ret = 0;
> >
> > -   if (pdev == vga_default_device())
> > +   printk("DEBUG: remove 1\n");
> > +
> > +   if (pdev == vga_default_device()) {
> > +   printk("DEBUG: primary = true\n");
> >  primary = true;
> > +   }
> >
> > -   if (primary)
> > +   if (primary) {
> > +   printk("DEBUG: disable sysfb\n");
> >  sysfb_disable();
> > +   }
> >
> >  for (bar = 0; bar < PCI_STD_NUM_BARS; ++bar) {
> >  if (!(pci_resource_flags(pdev, bar) & IORESOURCE_MEM))
> >  continue;
> >
> > +   printk("DEBUG: remove 2\n");
> >  base = pci_resource_start(pdev, bar);
> >  size = pci_resource_len(pdev, bar);
> >  aperture_detach_devices(base, size);
> >  }
> >
> > +   printk("DEBUG: remove 3\n");
> >  /*
> >   * If this is the primary adapter, there could be a VGA device
> >   * that consumes the VGA framebuffer I/O range. Remove this
> >
> > [1]  
> > https://lore.kernel.org/lkml/170222766284.86103.11020060769330721...@leemhuis.info/T/#u
>
> Copy-pasting this from the e-mail body didn't work well, but I applied
> the changes manually to a 6.5.9 kernel without any of the other patches.
> Here's the relevant dmesg output on the Lenovo L570:
>
> ...
> [2.953405] ACPI: bus type drm_connector registered
> [2.954014] i915 :00:02.0: [drm] VT-d active for gfx access
> [2.954018] DEBUG: remove 1
> [2.954020] DEBUG: remove 2
> [2.954021] DEBUG: remove 2
> [2.954023] DEBUG: remove 3

My tmp patch is as follows:

diff --git a/drivers/video/aperture.c b/drivers/video/aperture.c
index 561be8feca96..cc2e39fb98f5 100644
--- a/drivers/video/aperture.c
+++ b/drivers/video/aperture.c
@@ -350,21 +350,29 @@ int
aperture_remove_conflicting_pci_devices(struct pci_dev *pdev, const
char *na
resource_size_t base, size;
int bar, ret = 0;

-   if (pdev == vga_default_device())
+   printk("DEBUG: remove 1\n");
+
+   if (pdev == vga_default_device()) {
+   printk("DEBUG: primary = true\n");
primary = true;
+   }

-   if (primary)
+   if (primary) {
+   printk("DEBUG: disable sysfb\n");
sysfb_disable();
+   }

for (bar = 0; bar < PCI_STD_NUM_BARS; ++bar) {
if (!(pci_resource_flags(pdev, bar) & IORESOURCE_MEM))
continue;

+   printk("DEBUG: remove 2\n");
base = pci_resource_start(pdev, bar);
size = pci_resource_len(pdev, bar);
aperture_detach_devices(base, size);
}

+   printk("DEBUG: remove 3\n");
/*
 * If this is the primary adapter, there could be a VGA device
 * that consumes the VGA framebuffer I/O range. Remove this

>From the Jaak's dmesg, it is obvious that "pdev ==
vga_default_device()" is false, which causes sysfb_disable() to be not
called. And I think the simple-drm device is not provided by the i915
device in this case. So, can we unconditionally call sysfb_disable()
here, which is the same as aperture_remove_conflicting_devices()?

Huacai

> [2.954029] resource: resource sanity check: requesting [mem
> 0xe000-0xefff], which spans more than BOOTFB
> [mem 0xe000-0xe012bfff]
> [2.954035] caller i915_ggtt_init_hw+0x88/0x120 mapping multiple BARs
> [2.954061] i915 :00:02.0: [drm] Using Transparent Hugepages
> [2.955103] Loading firmware: i915/kbl_dmc_ver1_04.bin
> [2.955384] i915 :00:02.0: [drm] Finished loading DMC firmware
> i915/kbl_dmc_ver1_04.bin (v1.4)
> ...
> [4.145013] [drm] Initialized i915 1.6.0 20201103 for :00:02.0 on
> minor 0
> [4.147101] ACPI: video: Video Device [GFX0] (multi-head: yes  rom:
> no  post: no)
> [4.147244] input: Video Bus as
> /devices/LNXSYSTM:00/LNXSYBUS:00/PNP0A08:00/LNXVIDEO:00/input/input4
> [4.147410] [drm] Initialized vgem 1.0.0 20120112 for vgem on minor 1
> [4.147420] usbcore: registered new interface driver udl
> [4.147500] [drm] Initialized simpledrm 1.0.0 20200625 for
> simple-framebuffer.0 on minor 2
> [4.148643] Console: switching to colour frame 

[PATCH v3 5/5] drm: xlnx: zynqmp_dpsub: Set live video in format

2024-01-23 Thread Anatoliy Klymenko
ZynqMP DPSUB supports 2 modes of operations in regard to video data
input.

In the first mode, DPSUB uses DMA engine to pull video data from memory
buffers. To support this the driver implements CRTC and DRM bridge
representing DP encoder.

In the second mode, DPSUB acquires video data pushed from FPGA and
passes it downstream to DP output. This mode of operation is modeled in
the driver as a DRM bridge that should be attached to some external
CRTC. DPSUB supports multiple input data formats. In order to properly
operate exact media bus format should be negotiated between external
CRTC and DPSUB bridge. DRM framework provides a mechanism to negotiate
media bus formats between bridges connected into a chain, but not
between CRTC and encoder (first bridge in the chain). This change
mitigates the issue for FPGA based CRTC, which would typically have a
single fixed media bus format.

Expect live video input format to be set as "bus-format" property in
connected remote endpoint.

Set display layer mode in the layer creation context.

Signed-off-by: Anatoliy Klymenko 
---
 drivers/gpu/drm/xlnx/zynqmp_disp.c  | 109 ++--
 drivers/gpu/drm/xlnx/zynqmp_disp.h  |   3 +-
 drivers/gpu/drm/xlnx/zynqmp_disp_regs.h |   8 +-
 drivers/gpu/drm/xlnx/zynqmp_dp.c|   2 +-
 drivers/gpu/drm/xlnx/zynqmp_kms.c   |   2 +-
 5 files changed, 107 insertions(+), 17 deletions(-)

diff --git a/drivers/gpu/drm/xlnx/zynqmp_disp.c 
b/drivers/gpu/drm/xlnx/zynqmp_disp.c
index 8a39b3accce5..a7115321b3fb 100644
--- a/drivers/gpu/drm/xlnx/zynqmp_disp.c
+++ b/drivers/gpu/drm/xlnx/zynqmp_disp.c
@@ -18,8 +18,10 @@
 #include 
 #include 
 #include 
+#include 
 #include 
 #include 
+#include 
 #include 
 #include 
 
@@ -67,12 +69,16 @@
 /**
  * struct zynqmp_disp_format - Display subsystem format information
  * @drm_fmt: DRM format (4CC)
+ * @bus_fmt: Live video media bus format
  * @buf_fmt: AV buffer format
  * @swap: Flag to swap R & B for RGB formats, and U & V for YUV formats
  * @sf: Scaling factors for color components
  */
 struct zynqmp_disp_format {
-   u32 drm_fmt;
+   union {
+   u32 drm_fmt;
+   u32 bus_fmt;
+   };
u32 buf_fmt;
bool swap;
const u32 *sf;
@@ -354,6 +360,16 @@ static const struct zynqmp_disp_format avbuf_gfx_fmts[] = {
},
 };
 
+/* TODO: add support for different formats */
+static const struct zynqmp_disp_format avbuf_live_vid_fmts[] = {
+   {
+   .bus_fmt= MEDIA_BUS_FMT_UYVY8_1X16,
+   .buf_fmt= ZYNQMP_DISP_AV_BUF_LIVE_CONFIG_BPC_8 |
+ ZYNQMP_DISP_AV_BUF_LIVE_CONFIG_FMT_YUV422,
+   .sf = scaling_factors_888,
+   }
+};
+
 static u32 zynqmp_disp_avbuf_read(struct zynqmp_disp *disp, int reg)
 {
return readl(disp->avbuf.base + reg);
@@ -369,6 +385,34 @@ static bool zynqmp_disp_layer_is_video(const struct 
zynqmp_disp_layer *layer)
return layer->id == ZYNQMP_DPSUB_LAYER_VID;
 }
 
+/**
+ * zynqmp_disp_avbuf_set_live_format - Set live input format for a layer
+ * @disp: Display controller
+ * @layer: The layer
+ * @fmt: The format information
+ *
+ * Set the live video input format for @layer to @fmt.
+ */
+static void zynqmp_disp_avbuf_set_live_format(struct zynqmp_disp *disp,
+ struct zynqmp_disp_layer *layer,
+ const struct zynqmp_disp_format 
*fmt)
+{
+   u32 reg, i;
+
+   reg = zynqmp_disp_layer_is_video(layer)
+   ? ZYNQMP_DISP_AV_BUF_LIVE_VID_CONFIG
+   : ZYNQMP_DISP_AV_BUF_LIVE_GFX_CONFIG;
+   zynqmp_disp_avbuf_write(disp, reg, fmt->buf_fmt);
+
+   for (i = 0; i < ZYNQMP_DISP_AV_BUF_NUM_SF; ++i) {
+   reg = zynqmp_disp_layer_is_video(layer)
+   ? ZYNQMP_DISP_AV_BUF_LIVD_VID_COMP_SF(i)
+   : ZYNQMP_DISP_AV_BUF_LIVD_GFX_COMP_SF(i);
+   zynqmp_disp_avbuf_write(disp, reg, fmt->sf[i]);
+   }
+   layer->disp_fmt = fmt;
+}
+
 /**
  * zynqmp_disp_avbuf_set_format - Set the input format for a layer
  * @disp: Display controller
@@ -902,15 +946,12 @@ u32 *zynqmp_disp_layer_drm_formats(struct 
zynqmp_disp_layer *layer,
 /**
  * zynqmp_disp_layer_enable - Enable a layer
  * @layer: The layer
- * @mode: Operating mode of layer
  *
  * Enable the @layer in the audio/video buffer manager and the blender. DMA
  * channels are started separately by zynqmp_disp_layer_update().
  */
-void zynqmp_disp_layer_enable(struct zynqmp_disp_layer *layer,
- enum zynqmp_dpsub_layer_mode mode)
+void zynqmp_disp_layer_enable(struct zynqmp_disp_layer *layer)
 {
-   layer->mode = mode;
zynqmp_disp_avbuf_enable_video(layer->disp, layer);
zynqmp_disp_blend_layer_enable(layer->disp, layer);
 }
@@ -950,11 +991,12 @@ void zynqmp_disp_layer_set_format(struct 
zynqmp_disp_layer *layer,
layer->disp_fmt = 

[PATCH v3 3/5] drm: xlnx: zynqmp_dpsub: Clear status register ASAP

2024-01-23 Thread Anatoliy Klymenko
Clear status register as soon as we read it.

Addressing comments from
https://lore.kernel.org/dri-devel/beb551c7-bb7e-4cd0-b166-e9aad90c4...@ideasonboard.com/

Signed-off-by: Anatoliy Klymenko 
---
 drivers/gpu/drm/xlnx/zynqmp_dp.c | 4 ++--
 1 file changed, 2 insertions(+), 2 deletions(-)

diff --git a/drivers/gpu/drm/xlnx/zynqmp_dp.c b/drivers/gpu/drm/xlnx/zynqmp_dp.c
index d60b7431603f..5a3335e1fffa 100644
--- a/drivers/gpu/drm/xlnx/zynqmp_dp.c
+++ b/drivers/gpu/drm/xlnx/zynqmp_dp.c
@@ -1624,6 +1624,8 @@ static irqreturn_t zynqmp_dp_irq_handler(int irq, void 
*data)
u32 status, mask;
 
status = zynqmp_dp_read(dp, ZYNQMP_DP_INT_STATUS);
+   /* clear status register as soon as we read it */
+   zynqmp_dp_write(dp, ZYNQMP_DP_INT_STATUS, status);
mask = zynqmp_dp_read(dp, ZYNQMP_DP_INT_MASK);
if (!(status & ~mask))
return IRQ_NONE;
@@ -1634,8 +1636,6 @@ static irqreturn_t zynqmp_dp_irq_handler(int irq, void 
*data)
if (status & ZYNQMP_DP_INT_CHBUF_OVERFLW_MASK)
dev_dbg_ratelimited(dp->dev, "overflow interrupt\n");
 
-   zynqmp_dp_write(dp, ZYNQMP_DP_INT_STATUS, status);
-
if (status & ZYNQMP_DP_INT_VBLANK_START)
zynqmp_dpsub_drm_handle_vblank(dp->dpsub);
 
-- 
2.25.1



[PATCH v3 2/5] drm: xlnx: zynqmp_dpsub: Fix timing for live mode

2024-01-23 Thread Anatoliy Klymenko
Expect external video timing in live video input mode, program
DPSUB acordingly.

Reviewed-by: Tomi Valkeinen 

Signed-off-by: Anatoliy Klymenko 
---
 drivers/gpu/drm/xlnx/zynqmp_disp.c | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/drivers/gpu/drm/xlnx/zynqmp_disp.c 
b/drivers/gpu/drm/xlnx/zynqmp_disp.c
index 407bc07cec69..8a39b3accce5 100644
--- a/drivers/gpu/drm/xlnx/zynqmp_disp.c
+++ b/drivers/gpu/drm/xlnx/zynqmp_disp.c
@@ -1166,7 +1166,7 @@ void zynqmp_disp_enable(struct zynqmp_disp *disp)
/* Choose clock source based on the DT clock handle. */
zynqmp_disp_avbuf_set_clocks_sources(disp, disp->dpsub->vid_clk_from_ps,
 disp->dpsub->aud_clk_from_ps,
-true);
+disp->dpsub->vid_clk_from_ps);
zynqmp_disp_avbuf_enable_channels(disp);
zynqmp_disp_avbuf_enable_audio(disp);
 
-- 
2.25.1



[PATCH v3 0/5] Fixing live video input in ZynqMP DPSUB

2024-01-23 Thread Anatoliy Klymenko
Add few missing pieces to support ZynqMP DPSUB live video in mode.

ZynqMP DPSUB supports 2 modes of operations in regard to video data
input.

In the first mode, DPSUB uses DMA engine to pull video data from memory
buffers. To support this the driver implements CRTC and DRM bridge
representing DP encoder.

In the second mode, DPSUB acquires video data pushed from FPGA and 
passes it downstream to DP output. This mode of operation is modeled in
the driver as a DRM bridge that should be attached to some external
CRTC.

Patches 1/5,2/5,3/5,4/5 are minor fixes.

DPSUB requires input live video format to be configured.
Patch 5/5: The DP Subsystem requires the input live video format to be
configured. In this patch, we are assuming that the CRTC's bus format is
fixed (typical for FPGA CRTC) and comes from the device tree. This is a
proposed solution, as there is no API to query CRTC output bus format
or negotiate it in any other way.

Changes in v2: 
- Address reviewers' comments:
  - More elaborate and consistent comments / commit messages
  - Fix includes' order
  - Replace of_property_read_u32_index() with of_property_read_u32()

Changes in v3:
- Split patch #3 into 3) moving status register clear immediately after
  read; 4) masking status against interrupts' mask

Link to v1: 
https://lore.kernel.org/all/20240112234222.913138-1-anatoliy.klyme...@amd.com/
Link to v2: 
https://lore.kernel.org/all/20240119055437.2549149-1-anatoliy.klyme...@amd.com/

Anatoliy Klymenko (5):
  drm: xlnx: zynqmp_dpsub: Make drm bridge discoverable
  drm: xlnx: zynqmp_dpsub: Fix timing for live mode
  drm: xlnx: zynqmp_dpsub: Clear status register ASAP
  drm: xlnx: zynqmp_dpsub: Filter interrupts against mask
  drm: xlnx: zynqmp_dpsub: Set live video in format

 drivers/gpu/drm/xlnx/zynqmp_disp.c  | 111 +---
 drivers/gpu/drm/xlnx/zynqmp_disp.h  |   3 +-
 drivers/gpu/drm/xlnx/zynqmp_disp_regs.h |   8 +-
 drivers/gpu/drm/xlnx/zynqmp_dp.c|  16 +++-
 drivers/gpu/drm/xlnx/zynqmp_kms.c   |   2 +-
 5 files changed, 119 insertions(+), 21 deletions(-)

-- 
2.25.1



[PATCH v3 1/5] drm: xlnx: zynqmp_dpsub: Make drm bridge discoverable

2024-01-23 Thread Anatoliy Klymenko
ZynqMP DPSUB supports 2 input modes: DMA based and live video.

In the first mode, the driver implements CRTC and DP encoder DRM bridge
to model the complete display pipeline. In this case, DRM bridge is
being directly instantiated within the driver, not using any bridge
discovery mechanisms.

In the live video input mode video signal is generated by FPGA fabric
and passed into DPSUB over the connected bus. In this mode driver
exposes the DP encoder as a DRM bridge, expecting external CRTC to
discover it via drm_of_find_panel_or_bridge() or a similar call. This
discovery relies on drm_bridge.of_node being properly set.

Assign device OF node to the bridge prior to registering it. This will
make said bridge discoverable by an external CRTC driver.

Reviewed-by: Tomi Valkeinen 
Reviewed-by: Laurent Pinchart 

Signed-off-by: Anatoliy Klymenko 
---
 drivers/gpu/drm/xlnx/zynqmp_dp.c | 1 +
 1 file changed, 1 insertion(+)

diff --git a/drivers/gpu/drm/xlnx/zynqmp_dp.c b/drivers/gpu/drm/xlnx/zynqmp_dp.c
index a0606fab0e22..d60b7431603f 100644
--- a/drivers/gpu/drm/xlnx/zynqmp_dp.c
+++ b/drivers/gpu/drm/xlnx/zynqmp_dp.c
@@ -1721,6 +1721,7 @@ int zynqmp_dp_probe(struct zynqmp_dpsub *dpsub)
bridge->ops = DRM_BRIDGE_OP_DETECT | DRM_BRIDGE_OP_EDID
| DRM_BRIDGE_OP_HPD;
bridge->type = DRM_MODE_CONNECTOR_DisplayPort;
+   bridge->of_node = dp->dev->of_node;
dpsub->bridge = bridge;
 
/*
-- 
2.25.1



[PATCH v3 4/5] drm: xlnx: zynqmp_dpsub: Filter interrupts against mask

2024-01-23 Thread Anatoliy Klymenko
Filter out status register against the interrupts' mask.

Some events are being reported via DP status register, even if
corresponding interrupts have been disabled. One instance of such event
leads to generation of VBLANK when the driver is in DRM bridge mode,
which in turn results in NULL pointer dereferencing. We should avoid
processing such events in an interrupt handler context.

This problem is less noticeable when the driver operates in DMA mode, as
in this case we have DRM CRTC object instantiated and DRM framework
simply discards unwanted VBLANKs in drm_handle_vblank().

Signed-off-by: Anatoliy Klymenko 
---
 drivers/gpu/drm/xlnx/zynqmp_dp.c | 9 -
 1 file changed, 8 insertions(+), 1 deletion(-)

diff --git a/drivers/gpu/drm/xlnx/zynqmp_dp.c b/drivers/gpu/drm/xlnx/zynqmp_dp.c
index 5a3335e1fffa..9f48e5bbcdec 100644
--- a/drivers/gpu/drm/xlnx/zynqmp_dp.c
+++ b/drivers/gpu/drm/xlnx/zynqmp_dp.c
@@ -1627,7 +1627,14 @@ static irqreturn_t zynqmp_dp_irq_handler(int irq, void 
*data)
/* clear status register as soon as we read it */
zynqmp_dp_write(dp, ZYNQMP_DP_INT_STATUS, status);
mask = zynqmp_dp_read(dp, ZYNQMP_DP_INT_MASK);
-   if (!(status & ~mask))
+
+   /*
+* Status register may report some events, which corresponding 
interrupts
+* have been disabled. Filter out those events against interrupts' mask.
+*/
+   status &= ~mask;
+
+   if (!status)
return IRQ_NONE;
 
/* dbg for diagnostic, but not much that the driver can do */
-- 
2.25.1



RE: [PATCH] mm: Remove double faults once write a device pfn

2024-01-23 Thread Zhou, Xianrong
[AMD Official Use Only - General]

> >>> The vmf_insert_pfn_prot could cause unnecessary double faults on a
> >>> device pfn. Because currently the vmf_insert_pfn_prot does not make
> >>> the pfn writable so the pte entry is normally read-only or dirty
> >>> catching.
> >> What? How do you got to this conclusion?
> > Sorry. I did not mention that this problem only exists on arm64 platform.
>
> Ok, that makes at least a little bit more sense.
>
> > Because on arm64 platform the PTE_RDONLY is automatically attached to
> > the userspace pte entries even through VM_WRITE + VM_SHARE.
> > The  PTE_RDONLY needs to be cleared in vmf_insert_pfn_prot. However
> > vmf_insert_pfn_prot do not make the pte writable passing false
> > @mkwrite to insert_pfn.
>
> Question is why is arm64 doing this? As far as I can see they must have some
> hardware reason for that.
>
> The mkwrite parameter to insert_pfn() was added by commit
> b2770da642540 to make insert_pfn() look more like insert_pfn_pmd() so that
> the DAX code can insert PTEs which are writable and dirty at the same time.
>

This is one scenario to do so. In fact on arm64 there are many scenarios could
be to do so. So we can let vmf_insert_pfn_prot supporting @mkwrite for drivers
at core layer and let drivers to decide whether or not to make writable and 
dirty
at one time. The patch did this. Otherwise double faults on arm64 when call
vmf_insert_pfn_prot.

> This is a completely different use case to what you try to use it here for and
> that looks extremely fishy to me.
>
> Regards,
> Christian.
>
> >
> >>> The first fault only sets up the pte entry which actually is dirty
> >>> catching. And the second immediate fault to the pfn due to first
> >>> dirty catching when the cpu re-execute the store instruction.
> >> It could be that this is done to work around some hw behavior, but
> >> not because of dirty catching.
> >>
> >>> Normally if the drivers call vmf_insert_pfn_prot and also supply
> >>> 'pfn_mkwrite' callback within vm_operations_struct which requires
> >>> the pte to be dirty catching then the vmf_insert_pfn_prot and the
> >>> double fault are reasonable. It is not a problem.
> >> Well, as far as I can see that behavior absolutely doesn't make sense.
> >>
> >> When pfn_mkwrite is requested then the driver should use PAGE_COPY,
> >> which is exactly what VMWGFX (the only driver using dirty tracking) is
> doing.
> >>
> >> Everybody else uses PAGE_SHARED which should make the pte writeable
> >> immediately.
> >>
> >> Regards,
> >> Christian.
> >>
> >>> However the most of drivers calling vmf_insert_pfn_prot do not
> >>> supply the 'pfn_mkwrite' callback so that the second fault is unnecessary.
> >>>
> >>> So just like vmf_insert_mixed and vmf_insert_mixed_mkwrite pair, we
> >>> should also supply vmf_insert_pfn_mkwrite for drivers as well.
> >>>
> >>> Signed-off-by: Xianrong Zhou 
> >>> ---
> >>>arch/x86/entry/vdso/vma.c  |  3 ++-
> >>>drivers/gpu/drm/amd/amdgpu/amdgpu_gem.c|  2 +-
> >>>drivers/gpu/drm/i915/gem/i915_gem_ttm.c|  2 +-
> >>>drivers/gpu/drm/nouveau/nouveau_gem.c  |  2 +-
> >>>drivers/gpu/drm/radeon/radeon_gem.c|  2 +-
> >>>drivers/gpu/drm/ttm/ttm_bo_vm.c|  8 +---
> >>>drivers/gpu/drm/vmwgfx/vmwgfx_page_dirty.c |  8 +---
> >>>include/drm/ttm/ttm_bo.h   |  3 ++-
> >>>include/linux/mm.h |  2 +-
> >>>mm/memory.c| 14 +++---
> >>>10 files changed, 30 insertions(+), 16 deletions(-)
> >>>
> >>> diff --git a/arch/x86/entry/vdso/vma.c b/arch/x86/entry/vdso/vma.c
> >>> index 7645730dc228..dd2431c2975f 100644
> >>> --- a/arch/x86/entry/vdso/vma.c
> >>> +++ b/arch/x86/entry/vdso/vma.c
> >>> @@ -185,7 +185,8 @@ static vm_fault_t vvar_fault(const struct
> >> vm_special_mapping *sm,
> >>>  if (pvti && vclock_was_used(VDSO_CLOCKMODE_PVCLOCK))
> >> {
> >>>  return vmf_insert_pfn_prot(vma, vmf->address,
> >>>  __pa(pvti) >> PAGE_SHIFT,
> >>> -   pgprot_decrypted(vma-
> >>> vm_page_prot));
> >>> +   pgprot_decrypted(vma-
> >>> vm_page_prot),
> >>> +   true);
> >>>  }
> >>>  } else if (sym_offset == image->sym_hvclock_page) {
> >>>  pfn = hv_get_tsc_pfn(); diff --git
> >>> a/drivers/gpu/drm/amd/amdgpu/amdgpu_gem.c
> >>> b/drivers/gpu/drm/amd/amdgpu/amdgpu_gem.c
> >>> index 49a5f1c73b3e..adcb20d9e624 100644
> >>> --- a/drivers/gpu/drm/amd/amdgpu/amdgpu_gem.c
> >>> +++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_gem.c
> >>> @@ -64,7 +64,7 @@ static vm_fault_t amdgpu_gem_fault(struct
> vm_fault
> >> *vmf)
> >>>  }
> >>>
> >>>  ret = ttm_bo_vm_fault_reserved(vmf, vmf->vma-
> >>> vm_page_prot,
> >>> -  TTM_BO_VM_NUM_PREFAULT);
> >>> +

Re: [PATCH RFC 1/4] drm/panel: add driver for simulated panel

2024-01-23 Thread Dmitry Baryshkov
On Wed, 17 Jan 2024 at 00:31, Jessica Zhang  wrote:
>
> Add a driver for simulating panels. This module also supports a mode
> parameter for users to specify a custom mode. If no custom mode is set,
> it will fall back to a custom, hard-coded mode.
>
> Signed-off-by: Jessica Zhang 
> ---
>  drivers/gpu/drm/panel/Kconfig|   9 ++
>  drivers/gpu/drm/panel/Makefile   |   1 +
>  drivers/gpu/drm/panel/panel-simulation.c | 147 
> +++
>  3 files changed, 157 insertions(+)
>
> diff --git a/drivers/gpu/drm/panel/Kconfig b/drivers/gpu/drm/panel/Kconfig
> index 99e14dc212ecb..d711ec170c586 100644
> --- a/drivers/gpu/drm/panel/Kconfig
> +++ b/drivers/gpu/drm/panel/Kconfig
> @@ -107,6 +107,15 @@ config DRM_PANEL_SIMPLE
>   that it can be automatically turned off when the panel goes into a
>   low power state.
>
> +config DRM_PANEL_SIMULATION
> +   tristate "support for simulation panels"
> +   depends on DRM_MIPI_DSI
> +   help
> + DRM panel driver for simulated DSI panels. Enabling this config will
> + cause the physical panel driver to not be attached to the DT panel
> + node. After the kernel boots, users can load the module and specify 
> a
> + custom mode using the driver modparams.
> +
>  config DRM_PANEL_EDP
> tristate "support for simple Embedded DisplayPort panels"
> depends on OF
> diff --git a/drivers/gpu/drm/panel/Makefile b/drivers/gpu/drm/panel/Makefile
> index d10c3de51c6db..5bc55357714ad 100644
> --- a/drivers/gpu/drm/panel/Makefile
> +++ b/drivers/gpu/drm/panel/Makefile
> @@ -9,6 +9,7 @@ obj-$(CONFIG_DRM_PANEL_BOE_TV101WUM_NL6) += 
> panel-boe-tv101wum-nl6.o
>  obj-$(CONFIG_DRM_PANEL_DSI_CM) += panel-dsi-cm.o
>  obj-$(CONFIG_DRM_PANEL_LVDS) += panel-lvds.o
>  obj-$(CONFIG_DRM_PANEL_SIMPLE) += panel-simple.o
> +obj-$(CONFIG_DRM_PANEL_SIMULATION) += panel-simulation.o
>  obj-$(CONFIG_DRM_PANEL_EDP) += panel-edp.o
>  obj-$(CONFIG_DRM_PANEL_EBBG_FT8719) += panel-ebbg-ft8719.o
>  obj-$(CONFIG_DRM_PANEL_ELIDA_KD35T133) += panel-elida-kd35t133.o
> diff --git a/drivers/gpu/drm/panel/panel-simulation.c 
> b/drivers/gpu/drm/panel/panel-simulation.c
> new file mode 100644
> index 0..081c03bea188d
> --- /dev/null
> +++ b/drivers/gpu/drm/panel/panel-simulation.c
> @@ -0,0 +1,147 @@
> +// SPDX-License-Identifier: GPL-2.0-only
> +// Copyright (c) 2024 Qualcomm Innovation Center, Inc. All rights reserved.
> +
> +#include 
> +#include 
> +
> +#include 
> +#include 
> +#include 
> +#include 
> +#include 
> +
> +static char sim_panel_mode[PATH_MAX];
> +
> +module_param_string(mode, sim_panel_mode, sizeof(sim_panel_mode), 0644);
> +MODULE_PARM_DESC(mode, "Sim panel mode");
> +
> +struct panel_simulation {
> +   struct drm_panel base;
> +   struct platform_device *platform;
> +} *sim_panel;
> +
> +static struct drm_display_mode panel_simulation_mode = {
> +   .clock = 345830,
> +   .hdisplay = 1080,
> +   .hsync_start = 1175,
> +   .hsync_end = 1176,
> +   .htotal = 1216,
> +   .vdisplay = 2340,
> +   .vsync_start = 2365,
> +   .vsync_end = 2366,
> +   .vtotal = 2370,
> +   .width_mm = 0,
> +   .height_mm = 0,
> +   .type = DRM_MODE_TYPE_DRIVER,
> +};
> +
> +static int panel_simulation_parse_mode(void)
> +{
> +   int count;
> +   struct drm_display_mode user_mode = { 0 };
> +   unsigned int vrefresh;
> +
> +   if (sim_panel_mode[0] == '\0')
> +   return 0;
> +
> +   count = sscanf(sim_panel_mode, "%hu,%hu,%hu,%hu,%hu,%hu,%hu,%hu-%u",
> +_mode.hdisplay, _mode.hsync_start,
> +_mode.hsync_end, _mode.htotal,
> +_mode.vdisplay, _mode.vsync_start,
> +_mode.vsync_end, _mode.vtotal, 
> );
> +
> +   if (count != 9)
> +   return -EINVAL;
> +
> +   user_mode.clock = user_mode.htotal * user_mode.vtotal * vrefresh / 
> 1000;

Does this compile / work on 32-bit platforms?

> +   memcpy(_simulation_mode, _mode, sizeof(struct 
> drm_display_mode));

We probably should set dpi through the modparam and calculate width_mm
/ height_mm here

> +
> +   return 0;
> +}
> +
> +static int panel_simulation_get_modes(struct drm_panel *panel,
> +   struct drm_connector *connector)
> +{
> +   struct drm_display_mode *mode;
> +   int ret;
> +
> +   ret = panel_simulation_parse_mode();
> +
> +   mode = drm_mode_duplicate(connector->dev, _simulation_mode);
> +   if (!mode)
> +   return -ENOMEM;
> +
> +   drm_mode_set_name(mode);
> +   mode->type = DRM_MODE_TYPE_DRIVER | DRM_MODE_TYPE_PREFERRED;
> +   connector->display_info.width_mm = mode->width_mm;
> +   connector->display_info.height_mm = mode->height_mm;
> +   drm_mode_probed_add(connector, mode);


drm_connector_helper_get_modes_fixed() ?

> +
> +   return 

[PATCH v4 3/3] dt-bindings: soc: mediatek: Change mediatek, gce-events to refernece

2024-01-23 Thread Jason-JH . Lin
Change mediatek,gce-events property to reference mediatek,gce-props.yaml
instead of defining itself.

Signed-off-by: Jason-JH.Lin 
Reviewed-by: Conor Dooley 
---
 .../bindings/soc/mediatek/mediatek,ccorr.yaml| 12 
 .../bindings/soc/mediatek/mediatek,mutex.yaml| 11 +++
 .../bindings/soc/mediatek/mediatek,wdma.yaml | 12 
 3 files changed, 11 insertions(+), 24 deletions(-)

diff --git a/Documentation/devicetree/bindings/soc/mediatek/mediatek,ccorr.yaml 
b/Documentation/devicetree/bindings/soc/mediatek/mediatek,ccorr.yaml
index 4380b98b0dfe..305f2cd9f865 100644
--- a/Documentation/devicetree/bindings/soc/mediatek/mediatek,ccorr.yaml
+++ b/Documentation/devicetree/bindings/soc/mediatek/mediatek,ccorr.yaml
@@ -34,13 +34,6 @@ properties:
   4 arguments defined in this property. Each GCE subsys id is mapping to
   a client defined in the header include/dt-bindings/gce/-gce.h.
 
-  mediatek,gce-events:
-description:
-  The event id which is mapping to the specific hardware event signal
-  to gce. The event id is defined in the gce header
-  include/dt-bindings/gce/-gce.h of each chips.
-$ref: /schemas/types.yaml#/definitions/uint32-array
-
   clocks:
 minItems: 1
 
@@ -51,7 +44,10 @@ required:
   - mediatek,gce-events
   - clocks
 
-additionalProperties: false
+allOf:
+  - $ref: /schemas/mailbox/mediatek,gce-props.yaml#
+
+unevaluatedProperties: false
 
 examples:
   - |
diff --git a/Documentation/devicetree/bindings/soc/mediatek/mediatek,mutex.yaml 
b/Documentation/devicetree/bindings/soc/mediatek/mediatek,mutex.yaml
index ba2014a8725c..61cf16ce8b0b 100644
--- a/Documentation/devicetree/bindings/soc/mediatek/mediatek,mutex.yaml
+++ b/Documentation/devicetree/bindings/soc/mediatek/mediatek,mutex.yaml
@@ -53,13 +53,6 @@ properties:
 items:
   - description: MUTEX Clock
 
-  mediatek,gce-events:
-description:
-  The event id which is mapping to the specific hardware event signal
-  to gce. The event id is defined in the gce header
-  include/dt-bindings/gce/-gce.h of each chips.
-$ref: /schemas/types.yaml#/definitions/uint32-array
-
   mediatek,gce-client-reg:
 $ref: /schemas/types.yaml#/definitions/phandle-array
 items:
@@ -73,6 +66,8 @@ properties:
   a client defined in the header include/dt-bindings/gce/-gce.h.
 
 allOf:
+  - $ref: /schemas/mailbox/mediatek,gce-props.yaml#
+
   - if:
   properties:
 compatible:
@@ -97,7 +92,7 @@ required:
   - interrupts
   - power-domains
 
-additionalProperties: false
+unevaluatedProperties: false
 
 examples:
   - |
diff --git a/Documentation/devicetree/bindings/soc/mediatek/mediatek,wdma.yaml 
b/Documentation/devicetree/bindings/soc/mediatek/mediatek,wdma.yaml
index 69afb329e5f4..d9dd4428c036 100644
--- a/Documentation/devicetree/bindings/soc/mediatek/mediatek,wdma.yaml
+++ b/Documentation/devicetree/bindings/soc/mediatek/mediatek,wdma.yaml
@@ -35,13 +35,6 @@ properties:
   4 arguments defined in this property. Each GCE subsys id is mapping to
   a client defined in the header include/dt-bindings/gce/-gce.h.
 
-  mediatek,gce-events:
-description:
-  The event id which is mapping to the specific hardware event signal
-  to gce. The event id is defined in the gce header
-  include/dt-bindings/gce/-gce.h of each chips.
-$ref: /schemas/types.yaml#/definitions/uint32-array
-
   power-domains:
 maxItems: 1
 
@@ -60,7 +53,10 @@ required:
   - clocks
   - iommus
 
-additionalProperties: false
+allOf:
+  - $ref: /schemas/mailbox/mediatek,gce-props.yaml#
+
+unevaluatedProperties: false
 
 examples:
   - |
-- 
2.18.0



[PATCH v4 2/3] dt-bindings: media: mediatek: mdp: Change mediatek, gce-events to reference

2024-01-23 Thread Jason-JH . Lin
Change mediatek,gce-events property to reference mediatek,gce-props.yaml
instead of defining itself.

Signed-off-by: Jason-JH.Lin 
Reviewed-by: Conor Dooley 
---
 .../bindings/media/mediatek,mdp3-rdma.yaml   | 11 +++
 .../devicetree/bindings/media/mediatek,mdp3-rsz.yaml | 12 
 .../bindings/media/mediatek,mdp3-wrot.yaml   | 12 
 3 files changed, 11 insertions(+), 24 deletions(-)

diff --git a/Documentation/devicetree/bindings/media/mediatek,mdp3-rdma.yaml 
b/Documentation/devicetree/bindings/media/mediatek,mdp3-rdma.yaml
index 59db8306485b..4a286d46c8ee 100644
--- a/Documentation/devicetree/bindings/media/mediatek,mdp3-rdma.yaml
+++ b/Documentation/devicetree/bindings/media/mediatek,mdp3-rdma.yaml
@@ -44,13 +44,6 @@ properties:
   4 arguments defined in this property. Each GCE subsys id is mapping to
   a client defined in the header include/dt-bindings/gce/-gce.h.
 
-  mediatek,gce-events:
-description:
-  The event id which is mapping to the specific hardware event signal
-  to gce. The event id is defined in the gce header
-  include/dt-bindings/gce/-gce.h of each chips.
-$ref: /schemas/types.yaml#/definitions/uint32-array
-
   mediatek,scp:
 $ref: /schemas/types.yaml#/definitions/phandle
 description:
@@ -96,6 +89,8 @@ required:
   - '#dma-cells'
 
 allOf:
+  - $ref: /schemas/mailbox/mediatek,gce-props.yaml
+
   - if:
   properties:
 compatible:
@@ -142,7 +137,7 @@ allOf:
 clocks:
   maxItems: 1
 
-additionalProperties: false
+unevaluatedProperties: false
 
 examples:
   - |
diff --git a/Documentation/devicetree/bindings/media/mediatek,mdp3-rsz.yaml 
b/Documentation/devicetree/bindings/media/mediatek,mdp3-rsz.yaml
index f5676bec4326..4774fdde1a1b 100644
--- a/Documentation/devicetree/bindings/media/mediatek,mdp3-rsz.yaml
+++ b/Documentation/devicetree/bindings/media/mediatek,mdp3-rsz.yaml
@@ -38,13 +38,6 @@ properties:
   4 arguments defined in this property. Each GCE subsys id is mapping to
   a client defined in the header include/dt-bindings/gce/-gce.h.
 
-  mediatek,gce-events:
-description:
-  The event id which is mapping to the specific hardware event signal
-  to gce. The event id is defined in the gce header
-  include/dt-bindings/gce/-gce.h of each chips.
-$ref: /schemas/types.yaml#/definitions/uint32-array
-
   clocks:
 minItems: 1
 
@@ -55,7 +48,10 @@ required:
   - mediatek,gce-events
   - clocks
 
-additionalProperties: false
+allOf:
+  - $ref: /schemas/mailbox/mediatek,gce-props.yaml
+
+unevaluatedProperties: false
 
 examples:
   - |
diff --git a/Documentation/devicetree/bindings/media/mediatek,mdp3-wrot.yaml 
b/Documentation/devicetree/bindings/media/mediatek,mdp3-wrot.yaml
index 53a679338402..a31f3f5aea96 100644
--- a/Documentation/devicetree/bindings/media/mediatek,mdp3-wrot.yaml
+++ b/Documentation/devicetree/bindings/media/mediatek,mdp3-wrot.yaml
@@ -38,13 +38,6 @@ properties:
   4 arguments defined in this property. Each GCE subsys id is mapping to
   a client defined in the header include/dt-bindings/gce/-gce.h.
 
-  mediatek,gce-events:
-description:
-  The event id which is mapping to the specific hardware event signal
-  to gce. The event id is defined in the gce header
-  include/dt-bindings/gce/-gce.h of each chips.
-$ref: /schemas/types.yaml#/definitions/uint32-array
-
   power-domains:
 maxItems: 1
 
@@ -67,7 +60,10 @@ required:
   - iommus
   - '#dma-cells'
 
-additionalProperties: false
+allOf:
+  - $ref: /schemas/mailbox/mediatek,gce-props.yaml
+
+unevaluatedProperties: false
 
 examples:
   - |
-- 
2.18.0



[PATCH v4 0/3] Add mediatek, gce-props.yaml for other bindings reference

2024-01-23 Thread Jason-JH . Lin
From: Jason-jh Lin 

The property "mediatek,gce-events" is used for GCE event ID corresponding
to a hardware event signal sent by the hardware or a software driver.
If the mailbox providers or consumers want to manipulate the value of
the event ID, they need to know the specific event ID.

Since mediatek,gce-events property is used for both mailbox producers
and consumers, we add a mediatek,gce-props.yaml to place the common GCE
properties like mediatek,gce-events.

Change in v4:
1. Fix some typo.
2. Change maxItems of gce-events from 1024 to 32.

Change in v3:
1. Add more description and fix typo and grammar.
2. Fix $ref as full path.

Change in v2:
1. Add mediatek,gce-props.yaml for other binding reference.

Jason-JH.Lin (3):
  dt-bindings: mailbox: Add mediatek,gce-props.yaml
  dt-bindings: media: mediatek: mdp: Change mediatek,gce-events to
reference
  dt-bindings: soc: mediatek: Change mediatek,gce-events to refernece

 .../bindings/mailbox/mediatek,gce-props.yaml  | 52 +++
 .../bindings/media/mediatek,mdp3-rdma.yaml| 11 ++--
 .../bindings/media/mediatek,mdp3-rsz.yaml | 12 ++---
 .../bindings/media/mediatek,mdp3-wrot.yaml| 12 ++---
 .../bindings/soc/mediatek/mediatek,ccorr.yaml | 12 ++---
 .../bindings/soc/mediatek/mediatek,mutex.yaml | 11 ++--
 .../bindings/soc/mediatek/mediatek,wdma.yaml  | 12 ++---
 7 files changed, 74 insertions(+), 48 deletions(-)
 create mode 100644 
Documentation/devicetree/bindings/mailbox/mediatek,gce-props.yaml

-- 
2.18.0



[PATCH v4 1/3] dt-bindings: mailbox: Add mediatek,gce-props.yaml

2024-01-23 Thread Jason-JH . Lin
Add mediatek,gce-props.yaml for common GCE properties that is used for
both mailbox providers and consumers. We place the common property
"mediatek,gce-events" in this binding currently.

The property "mediatek,gce-events" is used for GCE event ID corresponding
to a hardware event signal sent by the hardware or a software driver.
If the mailbox providers or consumers want to manipulate the value of
the event ID, they need to know the specific event ID.

Signed-off-by: Jason-JH.Lin 
Reviewed-by: Conor Dooley 
---
 .../bindings/mailbox/mediatek,gce-props.yaml  | 52 +++
 1 file changed, 52 insertions(+)
 create mode 100644 
Documentation/devicetree/bindings/mailbox/mediatek,gce-props.yaml

diff --git a/Documentation/devicetree/bindings/mailbox/mediatek,gce-props.yaml 
b/Documentation/devicetree/bindings/mailbox/mediatek,gce-props.yaml
new file mode 100644
index ..c25eed4606fe
--- /dev/null
+++ b/Documentation/devicetree/bindings/mailbox/mediatek,gce-props.yaml
@@ -0,0 +1,52 @@
+# SPDX-License-Identifier: (GPL-2.0-only OR BSD-2-Clause)
+%YAML 1.2
+---
+$id: http://devicetree.org/schemas/mailbox/mediatek,gce-props.yaml#
+$schema: http://devicetree.org/meta-schemas/core.yaml#
+
+title: MediaTek Global Command Engine Common Properties
+
+maintainers:
+  - Houlong Wei 
+
+description:
+  The Global Command Engine (GCE) is an instruction based, multi-threaded,
+  single-core command dispatcher for MediaTek hardware. The Command Queue
+  (CMDQ) mailbox driver is a driver for GCE, implemented using the Linux
+  mailbox framework. It is used to receive messages from mailbox consumers
+  and configure GCE to execute the specified instruction set in the message.
+  We use mediatek,gce-mailbox.yaml to define the properties for CMDQ mailbox
+  driver. A device driver that uses the CMDQ driver to configure its hardware
+  registers is a mailbox consumer. The mailbox consumer can request a mailbox
+  channel corresponding to a GCE hardware thread to send a message, specifying
+  that the GCE thread to configure its hardware. The mailbox provider can also
+  reserve a mailbox channel to configure GCE hardware register by the specific
+  GCE thread. This binding defines the common GCE properties for both mailbox
+  provider and consumers.
+
+properties:
+  mediatek,gce-events:
+description:
+  GCE has an event table in SRAM, consisting of 1024 event IDs (0~1023).
+  Each event ID has a boolean event value with the default value 0.
+  The property mediatek,gce-events is used to obtain the event IDs.
+  Some gce-events are hardware-bound and cannot be changed by software.
+  For instance, in MT8195, when VDO0_MUTEX is stream done, VDO_MUTEX will
+  send an event signal to GCE, setting the value of event ID 597 to 1.
+  Similarly, in MT8188, the value of event ID 574 will be set to 1 when
+  VOD0_MUTEX is stream done.
+  On the other hand, some gce-events are not hardware-bound and can be
+  changed by software. For example, in MT8188, we can set the value of
+  event ID 855, which is not bound to any hardware, to 1 when the driver
+  in the secure world completes a task. However, in MT8195, event ID 855
+  is already bound to VDEC_LAT1, so we need to select another event ID to
+  achieve the same purpose. This event ID can be any ID that is not bound
+  to any hardware and is not yet used in any software driver.
+  To determine if the event ID is bound to the hardware or used by a
+  software driver, refer to the GCE header
+  include/dt-bindings/gce/-gce.h of each chip.
+$ref: /schemas/types.yaml#/definitions/uint32-array
+minItems: 1
+maxItems: 32
+
+additionalProperties: true
-- 
2.18.0



Re: [PATCH v1 1/6] drm/lima: fix devfreq refcount imbalance for job timeouts

2024-01-23 Thread Qiang Yu
On Wed, Jan 24, 2024 at 7:19 AM Erico Nunes  wrote:
>
> On Fri, Jan 19, 2024 at 2:50 AM Qiang Yu  wrote:
> >
> > On Thu, Jan 18, 2024 at 7:14 PM Erico Nunes  wrote:
> > >
> > > On Thu, Jan 18, 2024 at 2:36 AM Qiang Yu  wrote:
> > > >
> > > > So this is caused by same job trigger both done and timeout handling?
> > > > I think a better way to solve this is to make sure only one handler
> > > > (done or timeout) process the job instead of just making lima_pm_idle()
> > > > unique.
> > >
> > > It's not very clear to me how to best ensure that, with the drm_sched
> > > software timeout and the irq happening potentially at the same time.
> > This could be done by stopping scheduler run more job and disable
> > GP/PP interrupt. Then after sync irq, there should be no more new
> > irq gets in when we handling timeout.
> >
> > > I think patch 4 in this series describes and covers the most common
> > > case that this would be hit. So maybe now this patch could be dropped
> > > in favour of just that one.
> > Yes.
>
> After dropping the patch while testing to send v2, I managed to
> reproduce this issue again.
> Looking at a trace it seems that this actually happened with the test 
> workload:
> lima_sched_timedout_job -> (fence by is not signaled and new fence
> check is passed) -> irq happens preempting lima_sched_timedout_job,
> fence is signaled and lima_pm_idle called once at
> lima_sched_pipe_task_done -> lima_sched_timedout_job continues and
> calls lima_pm_idle again
>
> So I think we still need this patch to at least prevent the bug with
> the current software timeout. If we move to the hardware watchdog
> timeout later we might be able to remove it anyway, but that will
> still require separate work and testing.
>
Then you do need to solve the IRQ and reset race by disabling GP/PP
IRQ and sync irq after drm_sched_stop(). I mean you may keep the
patch 4 for spurious timeout, and add a new patch for solving the IRQ
and reset race.

Disable pm idle does not solve the race completely, other reset logic
may also conflict if not sequence the IRQ and reset .


Re: Making drm_gpuvm work across gpu devices

2024-01-23 Thread Danilo Krummrich

Hi Oak,

On 1/23/24 20:37, Zeng, Oak wrote:

Thanks Christian. I have some comment inline below.

Danilo, can you also take a look and give your feedback? Thanks.


I agree with everything Christian already wrote. Except for the KFD parts, which
I'm simply not familiar with, I had exactly the same thoughts after reading your
initial mail.

Please find some more comments below.




-Original Message-
From: Christian König 
Sent: Tuesday, January 23, 2024 6:13 AM
To: Zeng, Oak ; Danilo Krummrich ;
Dave Airlie ; Daniel Vetter 
Cc: Welty, Brian ; dri-devel@lists.freedesktop.org; 
intel-
x...@lists.freedesktop.org; Bommu, Krishnaiah ;
Ghimiray, Himal Prasad ;
thomas.hellst...@linux.intel.com; Vishwanathapura, Niranjana
; Brost, Matthew

Subject: Re: Making drm_gpuvm work across gpu devices

Hi Oak,

Am 23.01.24 um 04:21 schrieb Zeng, Oak:

Hi Danilo and all,

During the work of Intel's SVM code, we came up the idea of making

drm_gpuvm to work across multiple gpu devices. See some discussion here:
https://lore.kernel.org/dri-
devel/PH7PR11MB70049E7E6A2F40BF6282ECC292742@PH7PR11MB7004.namprd
11.prod.outlook.com/


The reason we try to do this is, for a SVM (shared virtual memory across cpu

program and all gpu program on all gpu devices) process, the address space has
to be across all gpu devices. So if we make drm_gpuvm to work across devices,
then our SVM code can leverage drm_gpuvm as well.


At a first look, it seems feasible because drm_gpuvm doesn't really use the

drm_device *drm pointer a lot. This param is used only for printing/warning. So 
I
think maybe we can delete this drm field from drm_gpuvm.


This way, on a multiple gpu device system, for one process, we can have only

one drm_gpuvm instance, instead of multiple drm_gpuvm instances (one for
each gpu device).


What do you think?


Well from the GPUVM side I don't think it would make much difference if
we have the drm device or not.

But the experience we had with the KFD I think I should mention that we
should absolutely *not* deal with multiple devices at the same time in
the UAPI or VM objects inside the driver.

The background is that all the APIs inside the Linux kernel are build
around the idea that they work with only one device at a time. This
accounts for both low level APIs like the DMA API as well as pretty high
level things like for example file system address space etc...


Yes most API are per device based.

One exception I know is actually the kfd SVM API. If you look at the svm_ioctl 
function, it is per-process based. Each kfd_process represent a process across 
N gpu devices. Cc Felix.

Need to say, kfd SVM represent a shared virtual address space across CPU and 
all GPU devices on the system. This is by the definition of SVM (shared virtual 
memory). This is very different from our legacy gpu *device* driver which works 
for only one device (i.e., if you want one device to access another device's 
memory, you will have to use dma-buf export/import etc).

We have the same design requirement of SVM. For anyone who want to implement 
the SVM concept, this is a hard requirement. Since now drm has the drm_gpuvm 
concept which strictly speaking is designed for one device, I want to see 
whether we can extend drm_gpuvm to make it work for both single device (as used 
in xe) and multipe devices (will be used in the SVM code). That is why I 
brought up this topic.



So when you have multiple GPUs you either have an inseparable cluster of
them which case you would also only have one drm_device. Or you have
separated drm_device which also results in separate drm render nodes and
separate virtual address spaces and also eventually separate IOMMU
domains which gives you separate dma_addresses for the same page and so
separate GPUVM page tables


I am thinking we can still make each device has its separate drm_device/render 
node/iommu domains/gpu page table. Just as what we have today. I am not plan to 
change this picture.

But the virtual address space will support two modes of operation:
1. one drm_gpuvm per device. This is when svm is not in the picture
2. all devices in the process share one single drm_gpuvm, when svm is in the 
picture. In xe driver design, we have to support a mixture use of legacy mode 
(such as gem_create and vm_bind) and svm (such as malloc'ed memory for gpu 
submission). So whenever SVM is in the picture, we want one single process 
address space across all devices. Drm_gpuvm doesn't need to be aware of those 
two operation modes. It is driver's responsibility to use different mode.

For example, in mode #1, a driver's vm structure (such as xe_vm) can inherit 
from drm_gpuvm. In mode #2, a driver's svm structure (xe_svm in this series: 
https://lore.kernel.org/dri-devel/20240117221223.18540-1-oak.z...@intel.com/) 
can inherit from drm_gpuvm while each xe_vm (still a per-device based struct) 
will just have a pointer to the drm_gpuvm structure. This way when svm is in 
play, we build a 1 process:1 

Re: [PATCH v1 1/6] drm/lima: fix devfreq refcount imbalance for job timeouts

2024-01-23 Thread Erico Nunes
On Fri, Jan 19, 2024 at 2:50 AM Qiang Yu  wrote:
>
> On Thu, Jan 18, 2024 at 7:14 PM Erico Nunes  wrote:
> >
> > On Thu, Jan 18, 2024 at 2:36 AM Qiang Yu  wrote:
> > >
> > > So this is caused by same job trigger both done and timeout handling?
> > > I think a better way to solve this is to make sure only one handler
> > > (done or timeout) process the job instead of just making lima_pm_idle()
> > > unique.
> >
> > It's not very clear to me how to best ensure that, with the drm_sched
> > software timeout and the irq happening potentially at the same time.
> This could be done by stopping scheduler run more job and disable
> GP/PP interrupt. Then after sync irq, there should be no more new
> irq gets in when we handling timeout.
>
> > I think patch 4 in this series describes and covers the most common
> > case that this would be hit. So maybe now this patch could be dropped
> > in favour of just that one.
> Yes.

After dropping the patch while testing to send v2, I managed to
reproduce this issue again.
Looking at a trace it seems that this actually happened with the test workload:
lima_sched_timedout_job -> (fence by is not signaled and new fence
check is passed) -> irq happens preempting lima_sched_timedout_job,
fence is signaled and lima_pm_idle called once at
lima_sched_pipe_task_done -> lima_sched_timedout_job continues and
calls lima_pm_idle again

So I think we still need this patch to at least prevent the bug with
the current software timeout. If we move to the hardware watchdog
timeout later we might be able to remove it anyway, but that will
still require separate work and testing.

Erico


Re: [PATCH v4 1/3] pm: runtime: Simplify pm_runtime_get_if_active() usage

2024-01-23 Thread Sakari Ailus
On Tue, Jan 23, 2024 at 03:48:01PM -0600, Bjorn Helgaas wrote:
> On Tue, Jan 23, 2024 at 08:44:04PM +, Sakari Ailus wrote:
> > On Tue, Jan 23, 2024 at 11:24:23AM -0600, Bjorn Helgaas wrote:
> > ...
> 
> > > - I don't know whether it's feasible, but it would be nice if the
> > >   intel_pm_runtime_pm.c rework could be done in one shot instead of
> > >   being split between patches 1/3 and 2/3.
> > > 
> > >   Maybe it could be a preliminary patch that uses the existing
> > >   if_active/if_in_use interfaces, followed by the trivial if_active
> > >   updates in this patch.  I think that would make the history easier
> > >   to read than having the transitory pm_runtime_get_conditional() in
> > >   the middle.
> > 
> > I think I'd merge the two patches. The second patch is fairly small, after
> > all, and both deal with largely the same code.
> 
> I'm not sure which two patches you mean, but the fact that two patches
> deal with largely the same code is not necessarily an argument for
> merging them.  From a reviewing perspective, it's nice if a patch like

Patches 1 and 2. The third patch introduces a new Runtime PM API function.

> 1/3, where it's largely mechanical and easy to review, is separated
> from patches that make more substantive changes.
> 
> That's why I think it'd be nice if the "interesting"
> intel_pm_runtime_pm.c changes were all in the same patch, and ideally,
> if that patch *only* touched intel_pm_runtime_pm.c.

I don't think squashing the second patch to the first really changes this
meaningfully: the i915 driver simply needs both
pm_runtime_get_if_{active,in_use}, and this is what the patch does to other
drivers already. Making the pm_runtime_get_conditional static would also
fit for the first patch if the desire is to not to introduce it at all.

-- 
Sakari Ailus


Re: [PATCH v4 1/3] drm/i915/vma: Fix UAF on destroy against retire race

2024-01-23 Thread Rodrigo Vivi
On Tue, Jan 23, 2024 at 11:51:15AM +0100, Janusz Krzysztofik wrote:
> Hi Rodrigo,
> 
> Thank you for review.
> 
> On Monday, 22 January 2024 22:09:38 CET Rodrigo Vivi wrote:
> > On Mon, Jan 22, 2024 at 03:04:42PM +0100, Janusz Krzysztofik wrote:
> > > Object debugging tools were sporadically reporting illegal attempts to
> > > free a still active i915 VMA object when parking a GPU tile believed to be
> > > idle.
> > > 
> > > [161.359441] ODEBUG: free active (active state 0) object: 
> > > 88811643b958 object type: i915_active hint: 
> > > __i915_vma_active+0x0/0x50 [i915]
> > > [161.360082] WARNING: CPU: 5 PID: 276 at lib/debugobjects.c:514 
> > > debug_print_object+0x80/0xb0
> > > ...
> > > [161.360304] CPU: 5 PID: 276 Comm: kworker/5:2 Not tainted 
> > > 6.5.0-rc1-CI_DRM_13375-g003f860e5577+ #1
> > > [161.360314] Hardware name: Intel Corporation Rocket Lake Client 
> > > Platform/RocketLake S UDIMM 6L RVP, BIOS RKLSFWI1.R00.3173.A03.2204210138 
> > > 04/21/2022
> > > [161.360322] Workqueue: i915-unordered __intel_wakeref_put_work [i915]
> > > [161.360592] RIP: 0010:debug_print_object+0x80/0xb0
> > > ...
> > > [161.361347] debug_object_free+0xeb/0x110
> > > [161.361362] i915_active_fini+0x14/0x130 [i915]
> > > [161.361866] release_references+0xfe/0x1f0 [i915]
> > > [161.362543] i915_vma_parked+0x1db/0x380 [i915]
> > > [161.363129] __gt_park+0x121/0x230 [i915]
> > > [161.363515] intel_wakeref_put_last+0x1f/0x70 [i915]
> > > 
> > > That has been tracked down to be happening when another thread is
> > > deactivating the VMA inside __active_retire() helper, after the VMA's
> > > active counter has been already decremented to 0, but before deactivation
> > > of the VMA's object is reported to the object debugging tool.
> > > 
> > > We could prevent from that race by serializing i915_active_fini() with
> > > __active_retire() via ref->tree_lock, but that wouldn't stop the VMA from
> > > being used, e.g. from __i915_vma_retire() called at the end of
> > > __active_retire(), after that VMA has been already freed by a concurrent
> > > i915_vma_destroy() on return from the i915_active_fini().  Then, we should
> > > rather fix the issue at the VMA level, not in i915_active.
> > > 
> > > Since __i915_vma_parked() is called from __gt_park() on last put of the
> > > GT's wakeref, the issue could be addressed by holding the GT wakeref long
> > > enough for __active_retire() to complete before that wakeref is released
> > > and the GT parked.
> > > 
> > > A VMA associated with a request doesn't acquire a GT wakeref by itself.
> > > Instead, it depends on a wakeref held directly by the request's active
> > > intel_context for a GT associated with its VM, and indirectly on that
> > > intel_context's engine wakeref if the engine belongs to the same GT as the
> > > VMA's VM.  In case of single-tile platforms, at least one of those
> > > wakerefs is usually held long enough for the request's VMA to be
> > > deactivated on time, before it is destroyed on last put of its VM GT
> > > wakeref.  However, on multi-tile platforms, a request may use a VMA from a
> > > tile other than the one that hosts the request's engine, then it is
> > > protected only with the intel_context's VM GT wakeref.
> > > 
> > > There was an attempt to fix this issue on 2-tile Meteor Lake by acquiring
> > 
> > please do not confuse the terminology here. MTL is 1-tile platform,
> > with multiple GTs (1 for Render/Compute and 1 for Media).
> 
> I didn't realize that "tile" is not the same as "GT".  I can review the whole 
> description and replace all occurrences of "tile" with "GT".

yeap, in i915 it is a 1-1 map... a tile is implemented within the intel_gt.
In Xe there's a good split and a good doc picture is here:
https://dri.freedesktop.org/docs/drm/gpu/driver-uapi.html#drm-xe-uapi

> 
> > 
> > Also you could probably avoid mentioning the other case here when
> > you are actively trying to resolve the RKL's single GT case.
> 
> OK, but let me keep that part of commit description in the cover letter then, 
> because:
> - historically, the issue was more frequently reproduced in CI on MTL than on 
>   other platforms, and that was the initial scope I started working on,
> - the full description as is better reflects phases of my process of 
>   reproduction and root cause analysis of the issue,
> - the MTL case was specifically addressed by the former insufficient 
>   workaround which now I'm now proposing to drop.
> 
> > > an extra wakeref for a Primary GT from i915_gem_do_execbuffer() -- see
> > > commit f56fe3e91787 ("drm/i915: Fix a VMA UAF for multi-gt platform").
> > > However, it occurred insufficient -- the issue was still reported by CI.
> > > That wakeref was released on exit from i915_gem_do_execbuffer(), then
> > > potentially before completion of the request and deactivation of its
> > > associated VMAs.
> > > 
> > > OTOH, CI reports indicate that single-tile platforms also suffer
> > > sporadically from the same race.
> > > 
> > > 

Re: [PATCH v3 4/5] drm/msm/dpu: move writeback's atomic_check to dpu_writeback.c

2024-01-23 Thread Abhinav Kumar




On 12/25/2023 5:08 AM, Dmitry Baryshkov wrote:

dpu_encoder_phys_wb is the only user of encoder's atomic_check callback.
Move corresponding checks to drm_writeback_connector's implementation
and drop the dpu_encoder_phys_wb_atomic_check() function.

Signed-off-by: Dmitry Baryshkov 
---
  .../drm/msm/disp/dpu1/dpu_encoder_phys_wb.c   | 54 --
  drivers/gpu/drm/msm/disp/dpu1/dpu_kms.c   |  9 ++-
  drivers/gpu/drm/msm/disp/dpu1/dpu_writeback.c | 57 ++-
  drivers/gpu/drm/msm/disp/dpu1/dpu_writeback.h |  3 +-
  4 files changed, 64 insertions(+), 59 deletions(-)



While validating this change with kms_writeback, we found that this is 
breaking back to back validate of kms_writeback with a NULL ptr 
dereference in below stack:


[   86.701062] Call trace:
[   86.701067]  dpu_wb_conn_atomic_check+0x118/0x18c
[   86.701076]  drm_atomic_helper_check_modeset+0x2d8/0x688
[   86.701084]  drm_atomic_helper_check+0x24/0x98
[   86.701095]  msm_atomic_check+0x90/0x9c
[   86.701103]  drm_atomic_check_only+0x4f4/0x8e8
[   86.70]  drm_atomic_commit+0x64/0xd8
[   86.701120]  drm_mode_atomic_ioctl+0xbfc/0xe74
[   86.701129]  drm_ioctl_kernel+0xd4/0x114
[   86.701137]  drm_ioctl+0x274/0x508
[   86.701143]  __arm64_sys_ioctl+0x98/0xd0
[   86.701152]  invoke_syscall+0x48/0xfc
[   86.701161]  el0_svc_common+0x88/0xe4
[   86.701167]  do_el0_svc+0x24/0x30
[   86.701175]  el0_svc+0x34/0x80
[   86.701184]  el0t_64_sync_handler+0x44/0xec
[   86.701192]  el0t_64_sync+0x1a8/0x1ac
[   86.701200] ---[ end trace  ]---

We analysed this and found why. Please see below.


diff --git a/drivers/gpu/drm/msm/disp/dpu1/dpu_encoder_phys_wb.c 
b/drivers/gpu/drm/msm/disp/dpu1/dpu_encoder_phys_wb.c
index a0a28230fc31..8220cd920e6f 100644
--- a/drivers/gpu/drm/msm/disp/dpu1/dpu_encoder_phys_wb.c
+++ b/drivers/gpu/drm/msm/disp/dpu1/dpu_encoder_phys_wb.c
@@ -354,59 +354,6 @@ static void dpu_encoder_helper_phys_setup_cdm(struct 
dpu_encoder_phys *phys_enc)
}
  }
  
-/**

- * dpu_encoder_phys_wb_atomic_check - verify and fixup given atomic states
- * @phys_enc:  Pointer to physical encoder
- * @crtc_state:Pointer to CRTC atomic state
- * @conn_state:Pointer to connector atomic state
- */
-static int dpu_encoder_phys_wb_atomic_check(
-   struct dpu_encoder_phys *phys_enc,
-   struct drm_crtc_state *crtc_state,
-   struct drm_connector_state *conn_state)
-{
-   struct drm_framebuffer *fb;
-   const struct drm_display_mode *mode = _state->mode;
-
-   DPU_DEBUG("[atomic_check:%d, \"%s\",%d,%d]\n",
-   phys_enc->hw_wb->idx, mode->name, mode->hdisplay, 
mode->vdisplay);
-
-   if (!conn_state || !conn_state->connector) {
-   DPU_ERROR("invalid connector state\n");
-   return -EINVAL;
-   } else if (conn_state->connector->status !=
-   connector_status_connected) {
-   DPU_ERROR("connector not connected %d\n",
-   conn_state->connector->status);
-   return -EINVAL;
-   }
-
-   if (!conn_state->writeback_job || !conn_state->writeback_job->fb)
-   return 0;
-
-   fb = conn_state->writeback_job->fb;
-
-   DPU_DEBUG("[fb_id:%u][fb:%u,%u]\n", fb->base.id,
-   fb->width, fb->height);
-
-   if (fb->width != mode->hdisplay) {
-   DPU_ERROR("invalid fb w=%d, mode w=%d\n", fb->width,
-   mode->hdisplay);
-   return -EINVAL;
-   } else if (fb->height != mode->vdisplay) {
-   DPU_ERROR("invalid fb h=%d, mode h=%d\n", fb->height,
- mode->vdisplay);
-   return -EINVAL;
-   } else if (fb->width > phys_enc->hw_wb->caps->maxlinewidth) {
-   DPU_ERROR("invalid fb w=%d, maxlinewidth=%u\n",
- fb->width, 
phys_enc->hw_wb->caps->maxlinewidth);
-   return -EINVAL;
-   }
-
-   return drm_atomic_helper_check_wb_connector_state(conn_state->connector, 
conn_state->state);
-}
-
-
  /**
   * _dpu_encoder_phys_wb_update_flush - flush hardware update
   * @phys_enc: Pointer to physical encoder
@@ -777,7 +724,6 @@ static void dpu_encoder_phys_wb_init_ops(struct 
dpu_encoder_phys_ops *ops)
ops->is_master = dpu_encoder_phys_wb_is_master;
ops->enable = dpu_encoder_phys_wb_enable;
ops->disable = dpu_encoder_phys_wb_disable;
-   ops->atomic_check = dpu_encoder_phys_wb_atomic_check;
ops->wait_for_commit_done = dpu_encoder_phys_wb_wait_for_commit_done;
ops->prepare_for_kickoff = dpu_encoder_phys_wb_prepare_for_kickoff;
ops->handle_post_kickoff = dpu_encoder_phys_wb_handle_post_kickoff;
diff --git a/drivers/gpu/drm/msm/disp/dpu1/dpu_kms.c 
b/drivers/gpu/drm/msm/disp/dpu1/dpu_kms.c
index 723cc1d82143..48728be27e15 100644
--- a/drivers/gpu/drm/msm/disp/dpu1/dpu_kms.c
+++ 

[PATCH 2/3] udmabuf: Sync buffer mappings for attached devices

2024-01-23 Thread Andrew Davis
Currently this driver creates a SGT table using the CPU as the
target device, then performs the dma_sync operations against
that SGT. This is backwards to how DMA-BUFs are supposed to behave.
This may have worked for the case where these buffers were given
only back to the same CPU that produced them as in the QEMU case.
And only then because the original author had the dma_sync
operations also backwards, syncing for the "device" on begin_cpu.
This was noticed and "fixed" in this patch[0].

That then meant we were sync'ing from the CPU to the CPU using
a pseudo-device "miscdevice". Which then caused another issue
due to the miscdevice not having a proper DMA mask (and why should
it, the CPU is not a DMA device). The fix for that was an even
more egregious hack[1] that declares the CPU is coherent with
itself and can access its own memory space..

Unwind all this and perform the correct action by doing the dma_sync
operations for each device currently attached to the backing buffer.

[0] commit 1ffe09590121 ("udmabuf: fix dma-buf cpu access")
[1] commit 9e9fa6a9198b ("udmabuf: Set the DMA mask for the udmabuf device 
(v2)")

Signed-off-by: Andrew Davis 
---
 drivers/dma-buf/udmabuf.c | 41 +++
 1 file changed, 16 insertions(+), 25 deletions(-)

diff --git a/drivers/dma-buf/udmabuf.c b/drivers/dma-buf/udmabuf.c
index 3a23f0a7d112a..ab6764322523c 100644
--- a/drivers/dma-buf/udmabuf.c
+++ b/drivers/dma-buf/udmabuf.c
@@ -26,8 +26,6 @@ MODULE_PARM_DESC(size_limit_mb, "Max size of a dmabuf, in 
megabytes. Default is
 struct udmabuf {
pgoff_t pagecount;
struct page **pages;
-   struct sg_table *sg;
-   struct miscdevice *device;
struct list_head attachments;
struct mutex lock;
 };
@@ -169,12 +167,8 @@ static void unmap_udmabuf(struct dma_buf_attachment *at,
 static void release_udmabuf(struct dma_buf *buf)
 {
struct udmabuf *ubuf = buf->priv;
-   struct device *dev = ubuf->device->this_device;
pgoff_t pg;
 
-   if (ubuf->sg)
-   put_sg_table(dev, ubuf->sg, DMA_BIDIRECTIONAL);
-
for (pg = 0; pg < ubuf->pagecount; pg++)
put_page(ubuf->pages[pg]);
kfree(ubuf->pages);
@@ -185,33 +179,31 @@ static int begin_cpu_udmabuf(struct dma_buf *buf,
 enum dma_data_direction direction)
 {
struct udmabuf *ubuf = buf->priv;
-   struct device *dev = ubuf->device->this_device;
-   int ret = 0;
-
-   if (!ubuf->sg) {
-   ubuf->sg = get_sg_table(dev, buf, direction);
-   if (IS_ERR(ubuf->sg)) {
-   ret = PTR_ERR(ubuf->sg);
-   ubuf->sg = NULL;
-   }
-   } else {
-   dma_sync_sg_for_cpu(dev, ubuf->sg->sgl, ubuf->sg->nents,
-   direction);
-   }
+   struct udmabuf_attachment *a;
 
-   return ret;
+   mutex_lock(>lock);
+
+   list_for_each_entry(a, >attachments, list)
+   dma_sync_sgtable_for_cpu(a->dev, a->table, direction);
+
+   mutex_unlock(>lock);
+
+   return 0;
 }
 
 static int end_cpu_udmabuf(struct dma_buf *buf,
   enum dma_data_direction direction)
 {
struct udmabuf *ubuf = buf->priv;
-   struct device *dev = ubuf->device->this_device;
+   struct udmabuf_attachment *a;
 
-   if (!ubuf->sg)
-   return -EINVAL;
+   mutex_lock(>lock);
+
+   list_for_each_entry(a, >attachments, list)
+   dma_sync_sgtable_for_device(a->dev, a->table, direction);
+
+   mutex_unlock(>lock);
 
-   dma_sync_sg_for_device(dev, ubuf->sg->sgl, ubuf->sg->nents, direction);
return 0;
 }
 
@@ -307,7 +299,6 @@ static long udmabuf_create(struct miscdevice *device,
exp_info.priv = ubuf;
exp_info.flags = O_RDWR;
 
-   ubuf->device = device;
buf = dma_buf_export(_info);
if (IS_ERR(buf)) {
ret = PTR_ERR(buf);
-- 
2.39.2



[PATCH 3/3] udmabuf: Use module_misc_device() to register this device

2024-01-23 Thread Andrew Davis
Now that we do not need to call dma_coerce_mask_and_coherent() on our
miscdevice device, use the module_misc_device() helper for registering
and module init/exit.

Signed-off-by: Andrew Davis 
---
 drivers/dma-buf/udmabuf.c | 30 +-
 1 file changed, 1 insertion(+), 29 deletions(-)

diff --git a/drivers/dma-buf/udmabuf.c b/drivers/dma-buf/udmabuf.c
index ab6764322523c..3028ac3fd9f6a 100644
--- a/drivers/dma-buf/udmabuf.c
+++ b/drivers/dma-buf/udmabuf.c
@@ -392,34 +392,6 @@ static struct miscdevice udmabuf_misc = {
.name   = "udmabuf",
.fops   = _fops,
 };
-
-static int __init udmabuf_dev_init(void)
-{
-   int ret;
-
-   ret = misc_register(_misc);
-   if (ret < 0) {
-   pr_err("Could not initialize udmabuf device\n");
-   return ret;
-   }
-
-   ret = dma_coerce_mask_and_coherent(udmabuf_misc.this_device,
-  DMA_BIT_MASK(64));
-   if (ret < 0) {
-   pr_err("Could not setup DMA mask for udmabuf device\n");
-   misc_deregister(_misc);
-   return ret;
-   }
-
-   return 0;
-}
-
-static void __exit udmabuf_dev_exit(void)
-{
-   misc_deregister(_misc);
-}
-
-module_init(udmabuf_dev_init)
-module_exit(udmabuf_dev_exit)
+module_misc_device(udmabuf_misc);
 
 MODULE_AUTHOR("Gerd Hoffmann ");
-- 
2.39.2



[PATCH 1/3] udmabuf: Keep track current device mappings

2024-01-23 Thread Andrew Davis
When a device attaches to and maps our buffer we need to keep track
of this mapping/device. This is needed for synchronization with these
devices when beginning and ending CPU access for instance. Add a list
that tracks device mappings as part of {map,unmap}_udmabuf().

Signed-off-by: Andrew Davis 
---
 drivers/dma-buf/udmabuf.c | 43 +--
 1 file changed, 41 insertions(+), 2 deletions(-)

diff --git a/drivers/dma-buf/udmabuf.c b/drivers/dma-buf/udmabuf.c
index c406459996489..3a23f0a7d112a 100644
--- a/drivers/dma-buf/udmabuf.c
+++ b/drivers/dma-buf/udmabuf.c
@@ -28,6 +28,14 @@ struct udmabuf {
struct page **pages;
struct sg_table *sg;
struct miscdevice *device;
+   struct list_head attachments;
+   struct mutex lock;
+};
+
+struct udmabuf_attachment {
+   struct device *dev;
+   struct sg_table *table;
+   struct list_head list;
 };
 
 static vm_fault_t udmabuf_vm_fault(struct vm_fault *vmf)
@@ -120,14 +128,42 @@ static void put_sg_table(struct device *dev, struct 
sg_table *sg,
 static struct sg_table *map_udmabuf(struct dma_buf_attachment *at,
enum dma_data_direction direction)
 {
-   return get_sg_table(at->dev, at->dmabuf, direction);
+   struct udmabuf *ubuf = at->dmabuf->priv;
+   struct udmabuf_attachment *a;
+
+   a = kzalloc(sizeof(*a), GFP_KERNEL);
+   if (!a)
+   return ERR_PTR(-ENOMEM);
+
+   a->table = get_sg_table(at->dev, at->dmabuf, direction);
+   if (IS_ERR(a->table)) {
+   kfree(a);
+   return a->table;
+   }
+
+   a->dev = at->dev;
+
+   mutex_lock(>lock);
+   list_add(>list, >attachments);
+   mutex_unlock(>lock);
+
+   return a->table;
 }
 
 static void unmap_udmabuf(struct dma_buf_attachment *at,
  struct sg_table *sg,
  enum dma_data_direction direction)
 {
-   return put_sg_table(at->dev, sg, direction);
+   struct udmabuf_attachment *a = at->priv;
+   struct udmabuf *ubuf = at->dmabuf->priv;
+
+   mutex_lock(>lock);
+   list_del(>list);
+   mutex_unlock(>lock);
+
+   put_sg_table(at->dev, sg, direction);
+
+   kfree(a);
 }
 
 static void release_udmabuf(struct dma_buf *buf)
@@ -263,6 +299,9 @@ static long udmabuf_create(struct miscdevice *device,
memfd = NULL;
}
 
+   INIT_LIST_HEAD(>attachments);
+   mutex_init(>lock);
+
exp_info.ops  = _ops;
exp_info.size = ubuf->pagecount << PAGE_SHIFT;
exp_info.priv = ubuf;
-- 
2.39.2



Re: linux-next: Tree for Jan 23 (drm/xe/)

2024-01-23 Thread Randy Dunlap


On 1/22/24 18:29, Stephen Rothwell wrote:
> Hi all,
> 
> News: there will be no linux-next release on Friday
> 
> Changes since 20240122:
> 

on ARM64, when
DRM_I915 is not set
DRM_XE=m
DEBUG_FS is not set

../drivers/gpu/drm/i915/display/intel_display_debugfs.c:1091:6: error: 
redefinition of 'intel_display_debugfs_register'
 1091 | void intel_display_debugfs_register(struct drm_i915_private *i915)
  |  ^~
In file included from 
../drivers/gpu/drm/i915/display/intel_display_debugfs.c:19:
../drivers/gpu/drm/i915/display/intel_display_debugfs.h:18:20: note: previous 
definition of 'intel_display_debugfs_register' with type 'void(struct xe_device 
*)'
   18 | static inline void intel_display_debugfs_register(struct 
drm_i915_private *i915) {}
  |^~
../drivers/gpu/drm/i915/display/intel_display_debugfs.c:1571:6: error: 
redefinition of 'intel_connector_debugfs_add'
 1571 | void intel_connector_debugfs_add(struct intel_connector *connector)
  |  ^~~
../drivers/gpu/drm/i915/display/intel_display_debugfs.h:19:20: note: previous 
definition of 'intel_connector_debugfs_add' with type 'void(struct 
intel_connector *)'
   19 | static inline void intel_connector_debugfs_add(struct intel_connector 
*connector) {}
  |^~~
../drivers/gpu/drm/i915/display/intel_display_debugfs.c:1626:6: error: 
redefinition of 'intel_crtc_debugfs_add'
 1626 | void intel_crtc_debugfs_add(struct intel_crtc *crtc)
  |  ^~
../drivers/gpu/drm/i915/display/intel_display_debugfs.h:20:20: note: previous 
definition of 'intel_crtc_debugfs_add' with type 'void(struct intel_crtc *)'
   20 | static inline void intel_crtc_debugfs_add(struct intel_crtc *crtc) {}
  |^~
../drivers/gpu/drm/i915/display/intel_pipe_crc.c:437:6: error: redefinition of 
'intel_crtc_crc_init'
  437 | void intel_crtc_crc_init(struct intel_crtc *crtc)
  |  ^~~
In file included from ../drivers/gpu/drm/i915/display/intel_pipe_crc.c:36:
../drivers/gpu/drm/i915/display/intel_pipe_crc.h:25:20: note: previous 
definition of 'intel_crtc_crc_init' with type 'void(struct intel_crtc *)'
   25 | static inline void intel_crtc_crc_init(struct intel_crtc *crtc) {}
  |^~~
../drivers/gpu/drm/i915/display/intel_pipe_crc.c: In function 
'intel_crtc_crc_init':
../drivers/gpu/drm/i915/display/intel_pipe_crc.c:439:48: error: 'struct 
intel_crtc' has no member named 'pipe_crc'
  439 | struct intel_pipe_crc *pipe_crc = >pipe_crc;
  |^~
In file included from ../include/uapi/linux/posix_types.h:5,
 from ../include/uapi/linux/types.h:14,
 from ../include/linux/types.h:6,
 from ../include/linux/kasan-checks.h:5,
 from ../include/asm-generic/rwonce.h:26,
 from ../arch/arm64/include/asm/rwonce.h:71,
 from ../include/linux/compiler.h:251,
 from ../include/linux/ctype.h:5,
 from ../drivers/gpu/drm/i915/display/intel_pipe_crc.c:27:
../drivers/gpu/drm/i915/display/intel_pipe_crc.c: At top level:
../include/linux/stddef.h:8:16: error: expected identifier or '(' before 'void'
8 | #define NULL ((void *)0)
  |^~~~
../drivers/gpu/drm/i915/display/intel_pipe_crc.h:28:36: note: in expansion of 
macro 'NULL'
   28 | #define intel_crtc_get_crc_sources NULL
  |^~~~
../drivers/gpu/drm/i915/display/intel_pipe_crc.c:549:20: note: in expansion of 
macro 'intel_crtc_get_crc_sources'
  549 | const char *const *intel_crtc_get_crc_sources(struct drm_crtc *crtc,
  |^~
../include/linux/stddef.h:8:23: error: expected ')' before numeric constant
8 | #define NULL ((void *)0)
  |   ^
../drivers/gpu/drm/i915/display/intel_pipe_crc.h:28:36: note: in expansion of 
macro 'NULL'
   28 | #define intel_crtc_get_crc_sources NULL
  |^~~~
../drivers/gpu/drm/i915/display/intel_pipe_crc.c:549:20: note: in expansion of 
macro 'intel_crtc_get_crc_sources'
  549 | const char *const *intel_crtc_get_crc_sources(struct drm_crtc *crtc,
  |^~
../include/linux/stddef.h:8:16: error: expected identifier or '(' before 'void'
8 | #define NULL ((void *)0)
  |^~~~
../drivers/gpu/drm/i915/display/intel_pipe_crc.h:27:38: note: in expansion of 
macro 'NULL'
   27 | #define intel_crtc_verify_crc_source NULL
  |  ^~~~
../drivers/gpu/drm/i915/display/intel_pipe_crc.c:556:5: note: in expansion of 
macro 'intel_crtc_verify_crc_source'
  556 | int intel_crtc_verify_crc_source(struct drm_crtc *crtc, 

Re: [PATCH v4 1/3] pm: runtime: Simplify pm_runtime_get_if_active() usage

2024-01-23 Thread Bjorn Helgaas
On Tue, Jan 23, 2024 at 08:44:04PM +, Sakari Ailus wrote:
> On Tue, Jan 23, 2024 at 11:24:23AM -0600, Bjorn Helgaas wrote:
> ...

> > - I don't know whether it's feasible, but it would be nice if the
> >   intel_pm_runtime_pm.c rework could be done in one shot instead of
> >   being split between patches 1/3 and 2/3.
> > 
> >   Maybe it could be a preliminary patch that uses the existing
> >   if_active/if_in_use interfaces, followed by the trivial if_active
> >   updates in this patch.  I think that would make the history easier
> >   to read than having the transitory pm_runtime_get_conditional() in
> >   the middle.
> 
> I think I'd merge the two patches. The second patch is fairly small, after
> all, and both deal with largely the same code.

I'm not sure which two patches you mean, but the fact that two patches
deal with largely the same code is not necessarily an argument for
merging them.  From a reviewing perspective, it's nice if a patch like
1/3, where it's largely mechanical and easy to review, is separated
from patches that make more substantive changes.

That's why I think it'd be nice if the "interesting"
intel_pm_runtime_pm.c changes were all in the same patch, and ideally,
if that patch *only* touched intel_pm_runtime_pm.c.

Bjorn


Re: [PATCH] doc: admin-guide/kernel-parameters: remove useless comment

2024-01-23 Thread Jonathan Corbet
Vegard Nossum  writes:

> This comment about DRM drivers has been there since the first git
> commit. It simply doesn't belong in kernel-parameters; remove it.
>
> Signed-off-by: Vegard Nossum 
> ---
>  Documentation/admin-guide/kernel-parameters.rst | 5 -
>  1 file changed, 5 deletions(-)
>
> diff --git a/Documentation/admin-guide/kernel-parameters.rst 
> b/Documentation/admin-guide/kernel-parameters.rst
> index 102937bc8443..4410384596a9 100644
> --- a/Documentation/admin-guide/kernel-parameters.rst
> +++ b/Documentation/admin-guide/kernel-parameters.rst
> @@ -218,8 +218,3 @@ bytes respectively. Such letter suffixes can also be 
> entirely omitted:
>  
>  .. include:: kernel-parameters.txt
> :literal:
> -
> -Todo
> -
> -
> - Add more DRM drivers.
> -- 

Applied, thanks.

jon


Re: [PATCH] docs/accel: correct links to mailing list archives

2024-01-23 Thread Jonathan Corbet
Hu Haowen <2023002...@link.tyut.edu.cn> writes:

> Since the mailing archive list lkml.org is obsolete, change the links into
> lore.kernel.org's ones.
>
> Signed-off-by: Hu Haowen <2023002...@link.tyut.edu.cn>
> ---
>  Documentation/accel/introduction.rst | 4 ++--
>  1 file changed, 2 insertions(+), 2 deletions(-)
>
> diff --git a/Documentation/accel/introduction.rst 
> b/Documentation/accel/introduction.rst
> index 89984dfececf..ae3030136637 100644
> --- a/Documentation/accel/introduction.rst
> +++ b/Documentation/accel/introduction.rst
> @@ -101,8 +101,8 @@ External References
>  email threads
>  -
>  
> -* `Initial discussion on the New subsystem for acceleration devices 
> `_ - Oded Gabbay (2022)
> -* `patch-set to add the new subsystem 
> `_ - Oded Gabbay (2022)
> +* `Initial discussion on the New subsystem for acceleration devices 
> `_
>  - Oded Gabbay (2022)
> +* `patch-set to add the new subsystem 
> `_ - 
> Oded Gabbay (2022)

Applied, thanks.

jon


Re: [PATCH] drm/Makefile: Move tiny drivers before native drivers

2024-01-23 Thread Jaak Ristioja

Hi,

I apologize for not finding the time to test this earlier.

On 11.12.23 05:08, Huacai Chen wrote:

And Jaak, could you please test with the below patch (but keep the
original order in Makefile) and then give me the dmesg output?

diff --git a/drivers/video/aperture.c b/drivers/video/aperture.c
index 561be8feca96..cc2e39fb98f5 100644
--- a/drivers/video/aperture.c
+++ b/drivers/video/aperture.c
@@ -350,21 +350,29 @@ int
aperture_remove_conflicting_pci_devices(struct pci_dev *pdev, const
char *na
 resource_size_t base, size;
 int bar, ret = 0;

-   if (pdev == vga_default_device())
+   printk("DEBUG: remove 1\n");
+
+   if (pdev == vga_default_device()) {
+   printk("DEBUG: primary = true\n");
 primary = true;
+   }

-   if (primary)
+   if (primary) {
+   printk("DEBUG: disable sysfb\n");
 sysfb_disable();
+   }

 for (bar = 0; bar < PCI_STD_NUM_BARS; ++bar) {
 if (!(pci_resource_flags(pdev, bar) & IORESOURCE_MEM))
 continue;

+   printk("DEBUG: remove 2\n");
 base = pci_resource_start(pdev, bar);
 size = pci_resource_len(pdev, bar);
 aperture_detach_devices(base, size);
 }

+   printk("DEBUG: remove 3\n");
 /*
  * If this is the primary adapter, there could be a VGA device
  * that consumes the VGA framebuffer I/O range. Remove this

[1]  
https://lore.kernel.org/lkml/170222766284.86103.11020060769330721...@leemhuis.info/T/#u


Copy-pasting this from the e-mail body didn't work well, but I applied 
the changes manually to a 6.5.9 kernel without any of the other patches. 
Here's the relevant dmesg output on the Lenovo L570:


...
[2.953405] ACPI: bus type drm_connector registered
[2.954014] i915 :00:02.0: [drm] VT-d active for gfx access
[2.954018] DEBUG: remove 1
[2.954020] DEBUG: remove 2
[2.954021] DEBUG: remove 2
[2.954023] DEBUG: remove 3
[2.954029] resource: resource sanity check: requesting [mem 
0xe000-0xefff], which spans more than BOOTFB 
[mem 0xe000-0xe012bfff]

[2.954035] caller i915_ggtt_init_hw+0x88/0x120 mapping multiple BARs
[2.954061] i915 :00:02.0: [drm] Using Transparent Hugepages
[2.955103] Loading firmware: i915/kbl_dmc_ver1_04.bin
[2.955384] i915 :00:02.0: [drm] Finished loading DMC firmware 
i915/kbl_dmc_ver1_04.bin (v1.4)

...
[4.145013] [drm] Initialized i915 1.6.0 20201103 for :00:02.0 on 
minor 0
[4.147101] ACPI: video: Video Device [GFX0] (multi-head: yes  rom: 
no  post: no)
[4.147244] input: Video Bus as 
/devices/LNXSYSTM:00/LNXSYBUS:00/PNP0A08:00/LNXVIDEO:00/input/input4

[4.147410] [drm] Initialized vgem 1.0.0 20120112 for vgem on minor 1
[4.147420] usbcore: registered new interface driver udl
[4.147500] [drm] Initialized simpledrm 1.0.0 20200625 for 
simple-framebuffer.0 on minor 2

[4.148643] Console: switching to colour frame buffer device 80x30
[4.153216] simple-framebuffer simple-framebuffer.0: [drm] fb0: 
simpledrmdrmfb frame buffer device

[4.154043] loop: module loaded
[4.156017] ahci :00:17.0: version 3.0
[4.157373] i915 :00:02.0: [drm] fb1: i915drmfb frame buffer device
...

J



Re: [bug report] drm/amdkfd: Export DMABufs from KFD using GEM handles

2024-01-23 Thread Felix Kuehling

On 2024-01-23 5:21, Dan Carpenter wrote:

Hello Felix Kuehling,

The patch 1819200166ce: "drm/amdkfd: Export DMABufs from KFD using
GEM handles" from Aug 24, 2023 (linux-next), leads to the following
Smatch static checker warning:

drivers/dma-buf/dma-buf.c:729 dma_buf_get()
warn: fd used after fd_install() 'fd'

drivers/gpu/drm/amd/amdgpu/amdgpu_amdkfd_gpuvm.c
809  static int kfd_mem_export_dmabuf(struct kgd_mem *mem)
810  {
811  if (!mem->dmabuf) {
812  struct amdgpu_device *bo_adev;
813  struct dma_buf *dmabuf;
814  int r, fd;
815
816  bo_adev = amdgpu_ttm_adev(mem->bo->tbo.bdev);
817  r = drm_gem_prime_handle_to_fd(_adev->ddev, 
bo_adev->kfd.client.file,
818 mem->gem_handle,
819  mem->alloc_flags & 
KFD_IOC_ALLOC_MEM_FLAGS_WRITABLE ?
820 DRM_RDWR : 0, );
  ^^^
The drm_gem_prime_handle_to_fd() function does an fd_install() and
returns the result as "fd".

821  if (r)
822  return r;
823  dmabuf = dma_buf_get(fd);
  ^^
Then we do another fget() inside dma_buf_get().  I'm not an expert,
but this looks wrong.  We can't assume that the dmabuf here is the
same one from drm_gem_prime_handle_to_fd() because the user could
change it after the fd_install().  I suspect drm_gem_prime_handle_to_fd()
should pass the dmabuf back instead.

We had several CVEs similar to this such as CVE-2022-1998.


That CVE is a system crash. I don't think that can happen here. It's 
true that user mode can close the fd. But then dma_buf_get would return 
an error that we'd catch with "WARN_ON_ONCE(IS_ERR(dmabuf))" below.


It's possible that a different DMABuf gets bound to the fd by a 
malicious user mode. That said, we're treating this fd as if it had come 
from user mode. dma_buf_get and the subsequent check on the dmabuf 
should be robust against any user mode messing with the file descriptor 
in the meantime.


Regards,
  Felix




824  close_fd(fd);
825  if (WARN_ON_ONCE(IS_ERR(dmabuf)))
826  return PTR_ERR(dmabuf);
827  mem->dmabuf = dmabuf;
828  }
829
830  return 0;
831  }

regards,
dan carpenter


Re: [PATCH v4 1/3] pm: runtime: Simplify pm_runtime_get_if_active() usage

2024-01-23 Thread Sakari Ailus
Hi Bjorn,

Thanks for the review.

On Tue, Jan 23, 2024 at 11:24:23AM -0600, Bjorn Helgaas wrote:
> On Tue, Jan 23, 2024 at 11:56:42AM +0200, Sakari Ailus wrote:
> > There are two ways to opportunistically increment a device's runtime PM
> > usage count, calling either pm_runtime_get_if_active() or
> > pm_runtime_get_if_in_use(). The former has an argument to tell whether to
> > ignore the usage count or not, and the latter simply calls the former with
> > ign_usage_count set to false. The other users that want to ignore the
> > usage_count will have to explitly set that argument to true which is a bit
> > cumbersome.
> > 
> > To make this function more practical to use, remove the ign_usage_count
> > argument from the function. The main implementation is renamed as
> > pm_runtime_get_conditional().
> > 
> > Signed-off-by: Sakari Ailus 
> > Reviewed-by: Alex Elder  # drivers/net/ipa/ipa_smp2p.c
> > Reviewed-by: Laurent Pinchart 
> > Acked-by: Takashi Iwai  # sound/
> > Reviewed-by: Jacek Lawrynowicz  # 
> > drivers/accel/ivpu/
> > Acked-by: Rodrigo Vivi  # drivers/gpu/drm/i915/
> > Reviewed-by: Rodrigo Vivi 
> 
> Acked-by: Bjorn Helgaas  # drivers/pci/
> 
> - Previous PM history uses "PM: " in the subject lines (not "pm: ").

Oops. I'm not sure why I used lower case. (Maybe I've written too many
times "media:" prefix to the subject?) I'll fix this in v5.

> 
> - I don't know whether it's feasible, but it would be nice if the
>   intel_pm_runtime_pm.c rework could be done in one shot instead of
>   being split between patches 1/3 and 2/3.
> 
>   Maybe it could be a preliminary patch that uses the existing
>   if_active/if_in_use interfaces, followed by the trivial if_active
>   updates in this patch.  I think that would make the history easier
>   to read than having the transitory pm_runtime_get_conditional() in
>   the middle.

I think I'd merge the two patches. The second patch is fairly small, after
all, and both deal with largely the same code.

> 
> - Similarly, it would be nice if pm_runtime_get_conditional() never
>   had to be published in pm_runtime.h, instead of being temporarily
>   added there by this patch and then immediately made private by 2/3.
>   Maybe that's not practical, I dunno.

-- 
Regards,

Sakari Ailus


Re: [PATCH v2 2/2] drm/amdgpu: Implement check_async_props for planes

2024-01-23 Thread Harry Wentland



On 2024-01-23 13:02, Xaver Hugl wrote:
> Am Mo., 22. Jan. 2024 um 16:50 Uhr schrieb Harry Wentland
> :
>>
>>
>>
>> On 2024-01-19 13:25, Ville Syrjälä wrote:
>>> On Fri, Jan 19, 2024 at 03:12:35PM -0300, André Almeida wrote:
 AMD GPUs can do async flips with changes on more properties than just
 the FB ID, so implement a custom check_async_props for AMD planes.

 Allow amdgpu to do async flips with IN_FENCE_ID and FB_DAMAGE_CLIPS
 properties. For userspace to check if a driver support this two
 properties, the strategy for now is to use TEST_ONLY commits.

 Signed-off-by: André Almeida 
 ---
 v2: Drop overlay plane option for now

   .../amd/display/amdgpu_dm/amdgpu_dm_plane.c   | 29 +++
   1 file changed, 29 insertions(+)

 diff --git a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_plane.c 
 b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_plane.c
 index 116121e647ca..7afe8c1b62d4 100644
 --- a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_plane.c
 +++ b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_plane.c
 @@ -25,6 +25,7 @@
*/

   #include 
 +#include 
   #include 
   #include 
   #include 
 @@ -1430,6 +1431,33 @@ static void 
 amdgpu_dm_plane_drm_plane_destroy_state(struct drm_plane *plane,
  drm_atomic_helper_plane_destroy_state(plane, state);
   }

 +static int amdgpu_dm_plane_check_async_props(struct drm_property *prop,
 +  struct drm_plane *plane,
 +  struct drm_plane_state *plane_state,
 +  struct drm_mode_object *obj,
 +  u64 prop_value, u64 old_val)
 +{
 +struct drm_mode_config *config = >dev->mode_config;
 +int ret;
 +
 +if (prop != config->prop_fb_id &&
 +prop != config->prop_in_fence_fd &&
>>>
>>> IN_FENCE should just be allowed always.
>>>
 +prop != config->prop_fb_damage_clips) {
>>>
>>> This seems a bit dubious to me. How is amdgpu using the damage
>>> information during async flips?
>>
>> Yeah, I'm also not sure this is right. Has anyone tested this
>> with a PSR SU panel?
>>
>> Harry
> 
> I attempted to, but according to
> /sys/kernel/debug/dri/1/eDP-1/psr_state, PSR never kicks in on my
> laptop at all. The only reason I wanted this property though is to
> reduce the number of special cases for async pageflips compositors
> have to implement; as it's not necessary for any functionality I think
> it's also fine to leave it out.
> 

Yeah, PSR panels aren't super common. PSR SU (Selective Update) panels
even less so.

I'd prefer to keep the damage clips out of async for now unless we
can actually test it with a PSR SU panel.

Harry

 +ret = drm_atomic_plane_get_property(plane, plane_state,
 +prop, _val);
 +return drm_atomic_check_prop_changes(ret, old_val, 
 prop_value, prop);
 +}
 +
 +if (plane_state->plane->type != DRM_PLANE_TYPE_PRIMARY) {
 +drm_dbg_atomic(prop->dev,
 +   "[OBJECT:%d] Only primary planes can be 
 changed during async flip\n",
 +   obj->id);
 +return -EINVAL;
 +}
 +
 +return 0;
 +}
 +
   static const struct drm_plane_funcs dm_plane_funcs = {
  .update_plane   = drm_atomic_helper_update_plane,
  .disable_plane  = drm_atomic_helper_disable_plane,
 @@ -1438,6 +1466,7 @@ static const struct drm_plane_funcs dm_plane_funcs = 
 {
  .atomic_duplicate_state = amdgpu_dm_plane_drm_plane_duplicate_state,
  .atomic_destroy_state = amdgpu_dm_plane_drm_plane_destroy_state,
  .format_mod_supported = amdgpu_dm_plane_format_mod_supported,
 +.check_async_props = amdgpu_dm_plane_check_async_props,
   };

   int amdgpu_dm_plane_init(struct amdgpu_display_manager *dm,
 --
 2.43.0
>>>



Re: Making drm_gpuvm work across gpu devices

2024-01-23 Thread Felix Kuehling

On 2024-01-23 14:37, Zeng, Oak wrote:

Thanks Christian. I have some comment inline below.

Danilo, can you also take a look and give your feedback? Thanks.


Sorry, just catching up with this thread now. I'm also not familiar with 
drm_gpuvm.


Some general observations based on my experience with KFD, amdgpu and 
SVM. With SVM we have a single virtual address space managed in user 
mode (basically using mmap) with attributes per virtual address range 
maintained in the kernel mode driver. Different devices get their 
mappings of pieces of that address space using the same virtual 
addresses. We also support migration to different DEVICE_PRIVATE memory 
spaces.


However, we still have page tables managed per device. Each device can 
have different page table formats and layout (e.g. different GPU 
generations in the same system) and the same memory may be mapped with 
different flags on different devices in order to get the right coherence 
behaviour. We also need to maintain per-device DMA mappings somewhere. 
That means, as far as the device page tables are concerned, we still 
have separate address spaces. SVM only adds a layer on top, which 
coordinates these separate device virtual address spaces so that some 
parts of them provide the appearance of a shared virtual address space.


At some point you need to decide, where you draw the boundary between 
managing a per-process shared virtual address space and managing 
per-device virtual address spaces. In amdgpu that boundary is currently 
where kfd_svm code calls amdgpu_vm code to manage the per-device page 
tables.


In the amdgpu driver, we still have the traditional memory management 
APIs in the render nodes that don't do SVM. They share the device 
virtual address spaces with SVM. We have to be careful that we don't try 
to manage the same device virtual address ranges with these two 
different memory managers. In practice, we let the non-SVM APIs use the 
upper half of the canonical address space, while the lower half can be 
used almost entirely for SVM.


Regards,
  Felix





-Original Message-
From: Christian König 
Sent: Tuesday, January 23, 2024 6:13 AM
To: Zeng, Oak ; Danilo Krummrich ;
Dave Airlie ; Daniel Vetter 
Cc: Welty, Brian ; dri-devel@lists.freedesktop.org; 
intel-
x...@lists.freedesktop.org; Bommu, Krishnaiah ;
Ghimiray, Himal Prasad ;
thomas.hellst...@linux.intel.com; Vishwanathapura, Niranjana
; Brost, Matthew

Subject: Re: Making drm_gpuvm work across gpu devices

Hi Oak,

Am 23.01.24 um 04:21 schrieb Zeng, Oak:

Hi Danilo and all,

During the work of Intel's SVM code, we came up the idea of making

drm_gpuvm to work across multiple gpu devices. See some discussion here:
https://lore.kernel.org/dri-
devel/PH7PR11MB70049E7E6A2F40BF6282ECC292742@PH7PR11MB7004.namprd
11.prod.outlook.com/

The reason we try to do this is, for a SVM (shared virtual memory across cpu

program and all gpu program on all gpu devices) process, the address space has
to be across all gpu devices. So if we make drm_gpuvm to work across devices,
then our SVM code can leverage drm_gpuvm as well.

At a first look, it seems feasible because drm_gpuvm doesn't really use the

drm_device *drm pointer a lot. This param is used only for printing/warning. So 
I
think maybe we can delete this drm field from drm_gpuvm.

This way, on a multiple gpu device system, for one process, we can have only

one drm_gpuvm instance, instead of multiple drm_gpuvm instances (one for
each gpu device).

What do you think?

Well from the GPUVM side I don't think it would make much difference if
we have the drm device or not.

But the experience we had with the KFD I think I should mention that we
should absolutely *not* deal with multiple devices at the same time in
the UAPI or VM objects inside the driver.

The background is that all the APIs inside the Linux kernel are build
around the idea that they work with only one device at a time. This
accounts for both low level APIs like the DMA API as well as pretty high
level things like for example file system address space etc...

Yes most API are per device based.

One exception I know is actually the kfd SVM API. If you look at the svm_ioctl 
function, it is per-process based. Each kfd_process represent a process across 
N gpu devices. Cc Felix.

Need to say, kfd SVM represent a shared virtual address space across CPU and 
all GPU devices on the system. This is by the definition of SVM (shared virtual 
memory). This is very different from our legacy gpu *device* driver which works 
for only one device (i.e., if you want one device to access another device's 
memory, you will have to use dma-buf export/import etc).

We have the same design requirement of SVM. For anyone who want to implement 
the SVM concept, this is a hard requirement. Since now drm has the drm_gpuvm 
concept which strictly speaking is designed for one device, I want to see 
whether we can extend drm_gpuvm to make it work for both single device (as used 

[PATCH v3 39/39] drm/bridge: remove ->get_edid callback

2024-01-23 Thread Jani Nikula
There are no more users of the ->get_edid callback left. They've all
been converted to ->edid_read. Remove the callback, and the fallback in
drm_bridge_edid_read().

Signed-off-by: Jani Nikula 
---
 drivers/gpu/drm/drm_bridge.c | 19 ---
 include/drm/drm_bridge.h | 30 --
 2 files changed, 49 deletions(-)

diff --git a/drivers/gpu/drm/drm_bridge.c b/drivers/gpu/drm/drm_bridge.c
index a3065d4aa3d6..521a71c61b16 100644
--- a/drivers/gpu/drm/drm_bridge.c
+++ b/drivers/gpu/drm/drm_bridge.c
@@ -1216,9 +1216,6 @@ EXPORT_SYMBOL_GPL(drm_bridge_get_modes);
  * DRM_BRIDGE_OP_EDID bridge ops flag, call _bridge_funcs.edid_read to get
  * the EDID and return it. Otherwise return NULL.
  *
- * If _bridge_funcs.edid_read is not set, fall back to using
- * _bridge_funcs.get_edid and wrapping it in struct drm_edid.
- *
  * RETURNS:
  * The retrieved EDID on success, or NULL otherwise.
  */
@@ -1228,22 +1225,6 @@ const struct drm_edid *drm_bridge_edid_read(struct 
drm_bridge *bridge,
if (!(bridge->ops & DRM_BRIDGE_OP_EDID))
return NULL;
 
-   /* Transitional: Fall back to ->get_edid. */
-   if (!bridge->funcs->edid_read) {
-   const struct drm_edid *drm_edid;
-   struct edid *edid;
-
-   edid = bridge->funcs->get_edid(bridge, connector);
-   if (!edid)
-   return NULL;
-
-   drm_edid = drm_edid_alloc(edid, (edid->extensions + 1) * 
EDID_LENGTH);
-
-   kfree(edid);
-
-   return drm_edid;
-   }
-
return bridge->funcs->edid_read(bridge, connector);
 }
 EXPORT_SYMBOL_GPL(drm_bridge_edid_read);
diff --git a/include/drm/drm_bridge.h b/include/drm/drm_bridge.h
index ee12f829aaf7..7293c02e17c5 100644
--- a/include/drm/drm_bridge.h
+++ b/include/drm/drm_bridge.h
@@ -588,36 +588,6 @@ struct drm_bridge_funcs {
const struct drm_edid *(*edid_read)(struct drm_bridge *bridge,
struct drm_connector *connector);
 
-   /**
-* @get_edid:
-*
-* Read and parse the EDID data of the connected display.
-*
-* The @get_edid callback is the preferred way of reporting mode
-* information for a display connected to the bridge output. Bridges
-* that support reading EDID shall implement this callback and leave
-* the @get_modes callback unimplemented.
-*
-* The caller of this operation shall first verify the output
-* connection status and refrain from reading EDID from a disconnected
-* output.
-*
-* This callback is optional. Bridges that implement it shall set the
-* DRM_BRIDGE_OP_EDID flag in their _bridge->ops.
-*
-* The connector parameter shall be used for the sole purpose of EDID
-* retrieval and parsing, and shall not be stored internally by bridge
-* drivers for future usage.
-*
-* RETURNS:
-*
-* An edid structure newly allocated with kmalloc() (or similar) on
-* success, or NULL otherwise. The caller is responsible for freeing
-* the returned edid structure with kfree().
-*/
-   struct edid *(*get_edid)(struct drm_bridge *bridge,
-struct drm_connector *connector);
-
/**
 * @hpd_notify:
 *
-- 
2.39.2



[PATCH v3 38/39] drm/bridge: ti-sn65dsi86: switch to ->edid_read callback

2024-01-23 Thread Jani Nikula
Prefer using the struct drm_edid based callback and functions.

Signed-off-by: Jani Nikula 
---
 drivers/gpu/drm/bridge/ti-sn65dsi86.c | 8 
 1 file changed, 4 insertions(+), 4 deletions(-)

diff --git a/drivers/gpu/drm/bridge/ti-sn65dsi86.c 
b/drivers/gpu/drm/bridge/ti-sn65dsi86.c
index 62cc3893dca5..61dc6f063fb4 100644
--- a/drivers/gpu/drm/bridge/ti-sn65dsi86.c
+++ b/drivers/gpu/drm/bridge/ti-sn65dsi86.c
@@ -1207,19 +1207,19 @@ static enum drm_connector_status 
ti_sn_bridge_detect(struct drm_bridge *bridge)
 : connector_status_disconnected;
 }
 
-static struct edid *ti_sn_bridge_get_edid(struct drm_bridge *bridge,
- struct drm_connector *connector)
+static const struct drm_edid *ti_sn_bridge_edid_read(struct drm_bridge *bridge,
+struct drm_connector 
*connector)
 {
struct ti_sn65dsi86 *pdata = bridge_to_ti_sn65dsi86(bridge);
 
-   return drm_get_edid(connector, >aux.ddc);
+   return drm_edid_read_ddc(connector, >aux.ddc);
 }
 
 static const struct drm_bridge_funcs ti_sn_bridge_funcs = {
.attach = ti_sn_bridge_attach,
.detach = ti_sn_bridge_detach,
.mode_valid = ti_sn_bridge_mode_valid,
-   .get_edid = ti_sn_bridge_get_edid,
+   .edid_read = ti_sn_bridge_edid_read,
.detect = ti_sn_bridge_detect,
.atomic_pre_enable = ti_sn_bridge_atomic_pre_enable,
.atomic_enable = ti_sn_bridge_atomic_enable,
-- 
2.39.2



[PATCH v3 37/39] drm/bridge: tc358767: switch to ->edid_read callback

2024-01-23 Thread Jani Nikula
Prefer using the struct drm_edid based callback and functions.

Signed-off-by: Jani Nikula 
---
 drivers/gpu/drm/bridge/tc358767.c | 18 +-
 1 file changed, 9 insertions(+), 9 deletions(-)

diff --git a/drivers/gpu/drm/bridge/tc358767.c 
b/drivers/gpu/drm/bridge/tc358767.c
index 37b1353cf2e3..166f9a3e9622 100644
--- a/drivers/gpu/drm/bridge/tc358767.c
+++ b/drivers/gpu/drm/bridge/tc358767.c
@@ -1651,19 +1651,19 @@ static void tc_bridge_mode_set(struct drm_bridge 
*bridge,
drm_mode_copy(>mode, mode);
 }
 
-static struct edid *tc_get_edid(struct drm_bridge *bridge,
-   struct drm_connector *connector)
+static const struct drm_edid *tc_edid_read(struct drm_bridge *bridge,
+  struct drm_connector *connector)
 {
struct tc_data *tc = bridge_to_tc(bridge);
 
-   return drm_get_edid(connector, >aux.ddc);
+   return drm_edid_read_ddc(connector, >aux.ddc);
 }
 
 static int tc_connector_get_modes(struct drm_connector *connector)
 {
struct tc_data *tc = connector_to_tc(connector);
int num_modes;
-   struct edid *edid;
+   const struct drm_edid *drm_edid;
int ret;
 
ret = tc_get_display_props(tc);
@@ -1678,10 +1678,10 @@ static int tc_connector_get_modes(struct drm_connector 
*connector)
return num_modes;
}
 
-   edid = tc_get_edid(>bridge, connector);
-   drm_connector_update_edid_property(connector, edid);
-   num_modes = drm_add_edid_modes(connector, edid);
-   kfree(edid);
+   drm_edid = tc_edid_read(>bridge, connector);
+   drm_edid_connector_update(connector, drm_edid);
+   num_modes = drm_edid_connector_add_modes(connector);
+   drm_edid_free(drm_edid);
 
return num_modes;
 }
@@ -1850,7 +1850,7 @@ static const struct drm_bridge_funcs tc_edp_bridge_funcs 
= {
.atomic_enable = tc_edp_bridge_atomic_enable,
.atomic_disable = tc_edp_bridge_atomic_disable,
.detect = tc_bridge_detect,
-   .get_edid = tc_get_edid,
+   .edid_read = tc_edid_read,
.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,
-- 
2.39.2



[PATCH v3 35/39] drm: bridge: dw_hdmi: clear the EDID property and CEC address on failures

2024-01-23 Thread Jani Nikula
If EDID read fails, clear the EDID property and CEC address.

Signed-off-by: Jani Nikula 
---
 drivers/gpu/drm/bridge/synopsys/dw-hdmi.c | 2 --
 1 file changed, 2 deletions(-)

diff --git a/drivers/gpu/drm/bridge/synopsys/dw-hdmi.c 
b/drivers/gpu/drm/bridge/synopsys/dw-hdmi.c
index 4a2e3f9c1dfd..0e59b30d5227 100644
--- a/drivers/gpu/drm/bridge/synopsys/dw-hdmi.c
+++ b/drivers/gpu/drm/bridge/synopsys/dw-hdmi.c
@@ -2505,8 +2505,6 @@ static int dw_hdmi_connector_get_modes(struct 
drm_connector *connector)
int ret;
 
drm_edid = dw_hdmi_edid_read(hdmi, connector);
-   if (!drm_edid)
-   return 0;
 
drm_edid_connector_update(connector, drm_edid);
cec_notifier_set_phys_addr(hdmi->cec_notifier,
-- 
2.39.2



[PATCH v3 36/39] drm/bridge: tc358767: update the EDID property

2024-01-23 Thread Jani Nikula
The EDID property should be updated between reading the EDID and adding
the modes.

Signed-off-by: Jani Nikula 
---
 drivers/gpu/drm/bridge/tc358767.c | 1 +
 1 file changed, 1 insertion(+)

diff --git a/drivers/gpu/drm/bridge/tc358767.c 
b/drivers/gpu/drm/bridge/tc358767.c
index f10ba91dc252..37b1353cf2e3 100644
--- a/drivers/gpu/drm/bridge/tc358767.c
+++ b/drivers/gpu/drm/bridge/tc358767.c
@@ -1679,6 +1679,7 @@ static int tc_connector_get_modes(struct drm_connector 
*connector)
}
 
edid = tc_get_edid(>bridge, connector);
+   drm_connector_update_edid_property(connector, edid);
num_modes = drm_add_edid_modes(connector, edid);
kfree(edid);
 
-- 
2.39.2



[PATCH v3 34/39] drm: bridge: dw_hdmi: switch to ->edid_read callback

2024-01-23 Thread Jani Nikula
Prefer using the struct drm_edid based callback and functions.

v2: Fix -Wuninitialized (kernel test robot)

Signed-off-by: Jani Nikula 
---
 drivers/gpu/drm/bridge/synopsys/dw-hdmi.c | 43 ++-
 1 file changed, 26 insertions(+), 17 deletions(-)

diff --git a/drivers/gpu/drm/bridge/synopsys/dw-hdmi.c 
b/drivers/gpu/drm/bridge/synopsys/dw-hdmi.c
index ca74a20015b3..4a2e3f9c1dfd 100644
--- a/drivers/gpu/drm/bridge/synopsys/dw-hdmi.c
+++ b/drivers/gpu/drm/bridge/synopsys/dw-hdmi.c
@@ -2454,27 +2454,35 @@ static enum drm_connector_status dw_hdmi_detect(struct 
dw_hdmi *hdmi)
return result;
 }
 
-static struct edid *dw_hdmi_get_edid(struct dw_hdmi *hdmi,
-struct drm_connector *connector)
+static const struct drm_edid *dw_hdmi_edid_read(struct dw_hdmi *hdmi,
+   struct drm_connector *connector)
 {
-   struct edid *edid;
+   const struct drm_edid *drm_edid;
+   const struct edid *edid;
 
if (!hdmi->ddc)
return NULL;
 
-   edid = drm_get_edid(connector, hdmi->ddc);
-   if (!edid) {
+   drm_edid = drm_edid_read_ddc(connector, hdmi->ddc);
+   if (!drm_edid) {
dev_dbg(hdmi->dev, "failed to get edid\n");
return NULL;
}
 
+   /*
+* FIXME: This should use connector->display_info.is_hdmi and
+* connector->display_info.has_audio from a path that has read the EDID
+* and called drm_edid_connector_update().
+*/
+   edid = drm_edid_raw(drm_edid);
+
dev_dbg(hdmi->dev, "got edid: width[%d] x height[%d]\n",
edid->width_cm, edid->height_cm);
 
hdmi->sink_is_hdmi = drm_detect_hdmi_monitor(edid);
hdmi->sink_has_audio = drm_detect_monitor_audio(edid);
 
-   return edid;
+   return drm_edid;
 }
 
 /* 
-
@@ -2493,17 +2501,18 @@ static int dw_hdmi_connector_get_modes(struct 
drm_connector *connector)
 {
struct dw_hdmi *hdmi = container_of(connector, struct dw_hdmi,
 connector);
-   struct edid *edid;
+   const struct drm_edid *drm_edid;
int ret;
 
-   edid = dw_hdmi_get_edid(hdmi, connector);
-   if (!edid)
+   drm_edid = dw_hdmi_edid_read(hdmi, connector);
+   if (!drm_edid)
return 0;
 
-   drm_connector_update_edid_property(connector, edid);
-   cec_notifier_set_phys_addr_from_edid(hdmi->cec_notifier, edid);
-   ret = drm_add_edid_modes(connector, edid);
-   kfree(edid);
+   drm_edid_connector_update(connector, drm_edid);
+   cec_notifier_set_phys_addr(hdmi->cec_notifier,
+  
connector->display_info.source_physical_address);
+   ret = drm_edid_connector_add_modes(connector);
+   drm_edid_free(drm_edid);
 
return ret;
 }
@@ -2980,12 +2989,12 @@ static enum drm_connector_status 
dw_hdmi_bridge_detect(struct drm_bridge *bridge
return dw_hdmi_detect(hdmi);
 }
 
-static struct edid *dw_hdmi_bridge_get_edid(struct drm_bridge *bridge,
-   struct drm_connector *connector)
+static const struct drm_edid *dw_hdmi_bridge_edid_read(struct drm_bridge 
*bridge,
+  struct drm_connector 
*connector)
 {
struct dw_hdmi *hdmi = bridge->driver_private;
 
-   return dw_hdmi_get_edid(hdmi, connector);
+   return dw_hdmi_edid_read(hdmi, connector);
 }
 
 static const struct drm_bridge_funcs dw_hdmi_bridge_funcs = {
@@ -3002,7 +3011,7 @@ static const struct drm_bridge_funcs dw_hdmi_bridge_funcs 
= {
.mode_set = dw_hdmi_bridge_mode_set,
.mode_valid = dw_hdmi_bridge_mode_valid,
.detect = dw_hdmi_bridge_detect,
-   .get_edid = dw_hdmi_bridge_get_edid,
+   .edid_read = dw_hdmi_bridge_edid_read,
 };
 
 /* 
-
-- 
2.39.2



[PATCH v3 33/39] drm: adv7511: switch to ->edid_read callback

2024-01-23 Thread Jani Nikula
Prefer using the struct drm_edid based callback and functions.

Signed-off-by: Jani Nikula 
---
 drivers/gpu/drm/bridge/adv7511/adv7511_drv.c | 47 +---
 1 file changed, 30 insertions(+), 17 deletions(-)

diff --git a/drivers/gpu/drm/bridge/adv7511/adv7511_drv.c 
b/drivers/gpu/drm/bridge/adv7511/adv7511_drv.c
index 8be235144f6d..1e40d451ce8c 100644
--- a/drivers/gpu/drm/bridge/adv7511/adv7511_drv.c
+++ b/drivers/gpu/drm/bridge/adv7511/adv7511_drv.c
@@ -604,10 +604,10 @@ static int adv7511_get_edid_block(void *data, u8 *buf, 
unsigned int block,
  * ADV75xx helpers
  */
 
-static struct edid *adv7511_get_edid(struct adv7511 *adv7511,
-struct drm_connector *connector)
+static const struct drm_edid *adv7511_edid_read(struct adv7511 *adv7511,
+   struct drm_connector *connector)
 {
-   struct edid *edid;
+   const struct drm_edid *drm_edid;
 
/* Reading the EDID only works if the device is powered */
if (!adv7511->powered) {
@@ -621,31 +621,44 @@ static struct edid *adv7511_get_edid(struct adv7511 
*adv7511,
 edid_i2c_addr);
}
 
-   edid = drm_do_get_edid(connector, adv7511_get_edid_block, adv7511);
+   drm_edid = drm_edid_read_custom(connector, adv7511_get_edid_block, 
adv7511);
 
if (!adv7511->powered)
__adv7511_power_off(adv7511);
 
-   adv7511_set_config_csc(adv7511, connector, adv7511->rgb,
-  drm_detect_hdmi_monitor(edid));
+   if (drm_edid) {
+   /*
+* FIXME: The CEC physical address should be set using
+* cec_s_phys_addr(adap,
+* connector->display_info.source_physical_address, false) from
+* a path that has read the EDID and called
+* drm_edid_connector_update().
+*/
+   const struct edid *edid = drm_edid_raw(drm_edid);
+
+   adv7511_set_config_csc(adv7511, connector, adv7511->rgb,
+  drm_detect_hdmi_monitor(edid));
 
-   cec_s_phys_addr_from_edid(adv7511->cec_adap, edid);
+   cec_s_phys_addr_from_edid(adv7511->cec_adap, edid);
+   } else {
+   cec_s_phys_addr_from_edid(adv7511->cec_adap, NULL);
+   }
 
-   return edid;
+   return drm_edid;
 }
 
 static int adv7511_get_modes(struct adv7511 *adv7511,
 struct drm_connector *connector)
 {
-   struct edid *edid;
+   const struct drm_edid *drm_edid;
unsigned int count;
 
-   edid = adv7511_get_edid(adv7511, connector);
+   drm_edid = adv7511_edid_read(adv7511, connector);
 
-   drm_connector_update_edid_property(connector, edid);
-   count = drm_add_edid_modes(connector, edid);
+   drm_edid_connector_update(connector, drm_edid);
+   count = drm_edid_connector_add_modes(connector);
 
-   kfree(edid);
+   drm_edid_free(drm_edid);
 
return count;
 }
@@ -953,12 +966,12 @@ static enum drm_connector_status 
adv7511_bridge_detect(struct drm_bridge *bridge
return adv7511_detect(adv, NULL);
 }
 
-static struct edid *adv7511_bridge_get_edid(struct drm_bridge *bridge,
-   struct drm_connector *connector)
+static const struct drm_edid *adv7511_bridge_edid_read(struct drm_bridge 
*bridge,
+  struct drm_connector 
*connector)
 {
struct adv7511 *adv = bridge_to_adv7511(bridge);
 
-   return adv7511_get_edid(adv, connector);
+   return adv7511_edid_read(adv, connector);
 }
 
 static void adv7511_bridge_hpd_notify(struct drm_bridge *bridge,
@@ -977,7 +990,7 @@ static const struct drm_bridge_funcs adv7511_bridge_funcs = 
{
.mode_valid = adv7511_bridge_mode_valid,
.attach = adv7511_bridge_attach,
.detect = adv7511_bridge_detect,
-   .get_edid = adv7511_bridge_get_edid,
+   .edid_read = adv7511_bridge_edid_read,
.hpd_notify = adv7511_bridge_hpd_notify,
 };
 
-- 
2.39.2



[PATCH v3 31/39] drm/omap/hdmi5: switch to ->edid_read callback

2024-01-23 Thread Jani Nikula
Prefer using the struct drm_edid based callback and functions.

Signed-off-by: Jani Nikula 
---
 drivers/gpu/drm/omapdrm/dss/hdmi5.c | 12 ++--
 1 file changed, 6 insertions(+), 6 deletions(-)

diff --git a/drivers/gpu/drm/omapdrm/dss/hdmi5.c 
b/drivers/gpu/drm/omapdrm/dss/hdmi5.c
index e6611c683857..c7ae2235ae99 100644
--- a/drivers/gpu/drm/omapdrm/dss/hdmi5.c
+++ b/drivers/gpu/drm/omapdrm/dss/hdmi5.c
@@ -425,11 +425,11 @@ static void hdmi5_bridge_disable(struct drm_bridge 
*bridge,
mutex_unlock(>lock);
 }
 
-static struct edid *hdmi5_bridge_get_edid(struct drm_bridge *bridge,
- struct drm_connector *connector)
+static const struct drm_edid *hdmi5_bridge_edid_read(struct drm_bridge *bridge,
+struct drm_connector 
*connector)
 {
struct omap_hdmi *hdmi = drm_bridge_to_hdmi(bridge);
-   struct edid *edid;
+   const struct drm_edid *drm_edid;
bool need_enable;
int idlemode;
int r;
@@ -452,7 +452,7 @@ static struct edid *hdmi5_bridge_get_edid(struct drm_bridge 
*bridge,
 
hdmi5_core_ddc_init(>core);
 
-   edid = drm_do_get_edid(connector, hdmi5_core_ddc_read, >core);
+   drm_edid = drm_edid_read_custom(connector, hdmi5_core_ddc_read, 
>core);
 
hdmi5_core_ddc_uninit(>core);
 
@@ -464,7 +464,7 @@ static struct edid *hdmi5_bridge_get_edid(struct drm_bridge 
*bridge,
if (need_enable)
hdmi_core_disable(hdmi);
 
-   return (struct edid *)edid;
+   return drm_edid;
 }
 
 static const struct drm_bridge_funcs hdmi5_bridge_funcs = {
@@ -475,7 +475,7 @@ static const struct drm_bridge_funcs hdmi5_bridge_funcs = {
.atomic_reset = drm_atomic_helper_bridge_reset,
.atomic_enable = hdmi5_bridge_enable,
.atomic_disable = hdmi5_bridge_disable,
-   .get_edid = hdmi5_bridge_get_edid,
+   .edid_read = hdmi5_bridge_edid_read,
 };
 
 static void hdmi5_bridge_init(struct omap_hdmi *hdmi)
-- 
2.39.2



[PATCH v3 32/39] drm: xlnx: zynqmp_dpsub: switch to ->edid_read callback

2024-01-23 Thread Jani Nikula
Prefer using the struct drm_edid based callback and functions.

Signed-off-by: Jani Nikula 
---
 drivers/gpu/drm/xlnx/zynqmp_dp.c | 8 
 1 file changed, 4 insertions(+), 4 deletions(-)

diff --git a/drivers/gpu/drm/xlnx/zynqmp_dp.c b/drivers/gpu/drm/xlnx/zynqmp_dp.c
index a0606fab0e22..24213eaa38d0 100644
--- a/drivers/gpu/drm/xlnx/zynqmp_dp.c
+++ b/drivers/gpu/drm/xlnx/zynqmp_dp.c
@@ -1560,12 +1560,12 @@ static enum drm_connector_status 
zynqmp_dp_bridge_detect(struct drm_bridge *brid
return connector_status_disconnected;
 }
 
-static struct edid *zynqmp_dp_bridge_get_edid(struct drm_bridge *bridge,
- struct drm_connector *connector)
+static const struct drm_edid *zynqmp_dp_bridge_edid_read(struct drm_bridge 
*bridge,
+struct drm_connector 
*connector)
 {
struct zynqmp_dp *dp = bridge_to_dp(bridge);
 
-   return drm_get_edid(connector, >aux.ddc);
+   return drm_edid_read_ddc(connector, >aux.ddc);
 }
 
 static const struct drm_bridge_funcs zynqmp_dp_bridge_funcs = {
@@ -1579,7 +1579,7 @@ static const struct drm_bridge_funcs 
zynqmp_dp_bridge_funcs = {
.atomic_reset = drm_atomic_helper_bridge_reset,
.atomic_check = zynqmp_dp_bridge_atomic_check,
.detect = zynqmp_dp_bridge_detect,
-   .get_edid = zynqmp_dp_bridge_get_edid,
+   .edid_read = zynqmp_dp_bridge_edid_read,
 };
 
 /* 
-
-- 
2.39.2



[PATCH v3 30/39] drm/omap/hdmi4: switch to ->edid_read callback

2024-01-23 Thread Jani Nikula
Prefer using the struct drm_edid based callback and functions.

Signed-off-by: Jani Nikula 
---
 drivers/gpu/drm/omapdrm/dss/hdmi4.c | 22 +++---
 1 file changed, 15 insertions(+), 7 deletions(-)

diff --git a/drivers/gpu/drm/omapdrm/dss/hdmi4.c 
b/drivers/gpu/drm/omapdrm/dss/hdmi4.c
index a26b77d99d52..9b8747d83ee8 100644
--- a/drivers/gpu/drm/omapdrm/dss/hdmi4.c
+++ b/drivers/gpu/drm/omapdrm/dss/hdmi4.c
@@ -436,11 +436,11 @@ static void hdmi4_bridge_hpd_notify(struct drm_bridge 
*bridge,
hdmi4_cec_set_phys_addr(>core, CEC_PHYS_ADDR_INVALID);
 }
 
-static struct edid *hdmi4_bridge_get_edid(struct drm_bridge *bridge,
- struct drm_connector *connector)
+static const struct drm_edid *hdmi4_bridge_edid_read(struct drm_bridge *bridge,
+struct drm_connector 
*connector)
 {
struct omap_hdmi *hdmi = drm_bridge_to_hdmi(bridge);
-   struct edid *edid = NULL;
+   const struct drm_edid *drm_edid = NULL;
unsigned int cec_addr;
bool need_enable;
int r;
@@ -461,13 +461,21 @@ static struct edid *hdmi4_bridge_get_edid(struct 
drm_bridge *bridge,
if (r)
goto done;
 
-   edid = drm_do_get_edid(connector, hdmi4_core_ddc_read, >core);
+   drm_edid = drm_edid_read_custom(connector, hdmi4_core_ddc_read, 
>core);
 
 done:
hdmi_runtime_put(hdmi);
mutex_unlock(>lock);
 
-   if (edid && edid->extensions) {
+   if (drm_edid) {
+   /*
+* FIXME: The CEC physical address should be set using
+* hdmi4_cec_set_phys_addr(>core,
+* connector->display_info.source_physical_address) from a path
+* that has read the EDID and called
+* drm_edid_connector_update().
+*/
+   const struct edid *edid = drm_edid_raw(drm_edid);
unsigned int len = (edid->extensions + 1) * EDID_LENGTH;
 
cec_addr = cec_get_edid_phys_addr((u8 *)edid, len, NULL);
@@ -480,7 +488,7 @@ static struct edid *hdmi4_bridge_get_edid(struct drm_bridge 
*bridge,
if (need_enable)
hdmi4_core_disable(>core);
 
-   return edid;
+   return drm_edid;
 }
 
 static const struct drm_bridge_funcs hdmi4_bridge_funcs = {
@@ -492,7 +500,7 @@ static const struct drm_bridge_funcs hdmi4_bridge_funcs = {
.atomic_enable = hdmi4_bridge_enable,
.atomic_disable = hdmi4_bridge_disable,
.hpd_notify = hdmi4_bridge_hpd_notify,
-   .get_edid = hdmi4_bridge_get_edid,
+   .edid_read = hdmi4_bridge_edid_read,
 };
 
 static void hdmi4_bridge_init(struct omap_hdmi *hdmi)
-- 
2.39.2



[PATCH v3 28/39] drm/msm/hdmi: fix indent

2024-01-23 Thread Jani Nikula
Remove the excess leading tabs.

Signed-off-by: Jani Nikula 
---
 drivers/gpu/drm/msm/hdmi/hdmi_bridge.c | 12 ++--
 1 file changed, 6 insertions(+), 6 deletions(-)

diff --git a/drivers/gpu/drm/msm/hdmi/hdmi_bridge.c 
b/drivers/gpu/drm/msm/hdmi/hdmi_bridge.c
index f5e01471b0b0..f28c61570533 100644
--- a/drivers/gpu/drm/msm/hdmi/hdmi_bridge.c
+++ b/drivers/gpu/drm/msm/hdmi/hdmi_bridge.c
@@ -290,12 +290,12 @@ static enum drm_mode_status 
msm_hdmi_bridge_mode_valid(struct drm_bridge *bridge
 }
 
 static const struct drm_bridge_funcs msm_hdmi_bridge_funcs = {
-   .pre_enable = msm_hdmi_bridge_pre_enable,
-   .post_disable = msm_hdmi_bridge_post_disable,
-   .mode_set = msm_hdmi_bridge_mode_set,
-   .mode_valid = msm_hdmi_bridge_mode_valid,
-   .get_edid = msm_hdmi_bridge_get_edid,
-   .detect = msm_hdmi_bridge_detect,
+   .pre_enable = msm_hdmi_bridge_pre_enable,
+   .post_disable = msm_hdmi_bridge_post_disable,
+   .mode_set = msm_hdmi_bridge_mode_set,
+   .mode_valid = msm_hdmi_bridge_mode_valid,
+   .get_edid = msm_hdmi_bridge_get_edid,
+   .detect = msm_hdmi_bridge_detect,
 };
 
 static void
-- 
2.39.2



[PATCH v3 29/39] drm/msm/hdmi: switch to ->edid_read callback

2024-01-23 Thread Jani Nikula
Prefer using the struct drm_edid based callback and functions.

Signed-off-by: Jani Nikula 
---
 drivers/gpu/drm/msm/hdmi/hdmi_bridge.c | 23 ---
 1 file changed, 16 insertions(+), 7 deletions(-)

diff --git a/drivers/gpu/drm/msm/hdmi/hdmi_bridge.c 
b/drivers/gpu/drm/msm/hdmi/hdmi_bridge.c
index f28c61570533..4a5b5112227f 100644
--- a/drivers/gpu/drm/msm/hdmi/hdmi_bridge.c
+++ b/drivers/gpu/drm/msm/hdmi/hdmi_bridge.c
@@ -236,24 +236,33 @@ static void msm_hdmi_bridge_mode_set(struct drm_bridge 
*bridge,
msm_hdmi_audio_update(hdmi);
 }
 
-static struct edid *msm_hdmi_bridge_get_edid(struct drm_bridge *bridge,
-   struct drm_connector *connector)
+static const struct drm_edid *msm_hdmi_bridge_edid_read(struct drm_bridge 
*bridge,
+   struct drm_connector 
*connector)
 {
struct hdmi_bridge *hdmi_bridge = to_hdmi_bridge(bridge);
struct hdmi *hdmi = hdmi_bridge->hdmi;
-   struct edid *edid;
+   const struct drm_edid *drm_edid;
uint32_t hdmi_ctrl;
 
hdmi_ctrl = hdmi_read(hdmi, REG_HDMI_CTRL);
hdmi_write(hdmi, REG_HDMI_CTRL, hdmi_ctrl | HDMI_CTRL_ENABLE);
 
-   edid = drm_get_edid(connector, hdmi->i2c);
+   drm_edid = drm_edid_read_ddc(connector, hdmi->i2c);
 
hdmi_write(hdmi, REG_HDMI_CTRL, hdmi_ctrl);
 
-   hdmi->hdmi_mode = drm_detect_hdmi_monitor(edid);
+   if (drm_edid) {
+   /*
+* FIXME: This should use connector->display_info.is_hdmi from a
+* path that has read the EDID and called
+* drm_edid_connector_update().
+*/
+   const struct edid *edid = drm_edid_raw(drm_edid);
 
-   return edid;
+   hdmi->hdmi_mode = drm_detect_hdmi_monitor(edid);
+   }
+
+   return drm_edid;
 }
 
 static enum drm_mode_status msm_hdmi_bridge_mode_valid(struct drm_bridge 
*bridge,
@@ -294,7 +303,7 @@ static const struct drm_bridge_funcs msm_hdmi_bridge_funcs 
= {
.post_disable = msm_hdmi_bridge_post_disable,
.mode_set = msm_hdmi_bridge_mode_set,
.mode_valid = msm_hdmi_bridge_mode_valid,
-   .get_edid = msm_hdmi_bridge_get_edid,
+   .edid_read = msm_hdmi_bridge_edid_read,
.detect = msm_hdmi_bridge_detect,
 };
 
-- 
2.39.2



[PATCH v3 27/39] drm/mediatek/hdmi: switch to ->edid_read callback

2024-01-23 Thread Jani Nikula
Prefer using the struct drm_edid based callback and functions.

Signed-off-by: Jani Nikula 
---
 drivers/gpu/drm/mediatek/mtk_hdmi.c | 26 +-
 1 file changed, 17 insertions(+), 9 deletions(-)

diff --git a/drivers/gpu/drm/mediatek/mtk_hdmi.c 
b/drivers/gpu/drm/mediatek/mtk_hdmi.c
index 86133bf16326..c6bdc565e4a9 100644
--- a/drivers/gpu/drm/mediatek/mtk_hdmi.c
+++ b/drivers/gpu/drm/mediatek/mtk_hdmi.c
@@ -1265,19 +1265,27 @@ static enum drm_connector_status 
mtk_hdmi_bridge_detect(struct drm_bridge *bridg
return mtk_hdmi_detect(hdmi);
 }
 
-static struct edid *mtk_hdmi_bridge_get_edid(struct drm_bridge *bridge,
-struct drm_connector *connector)
+static const struct drm_edid *mtk_hdmi_bridge_edid_read(struct drm_bridge 
*bridge,
+   struct drm_connector 
*connector)
 {
struct mtk_hdmi *hdmi = hdmi_ctx_from_bridge(bridge);
-   struct edid *edid;
+   const struct drm_edid *drm_edid;
 
if (!hdmi->ddc_adpt)
return NULL;
-   edid = drm_get_edid(connector, hdmi->ddc_adpt);
-   if (!edid)
-   return NULL;
-   hdmi->dvi_mode = !drm_detect_monitor_audio(edid);
-   return edid;
+   drm_edid = drm_edid_read_ddc(connector, hdmi->ddc_adpt);
+   if (drm_edid) {
+   /*
+* FIXME: This should use !connector->display_info.has_audio (or
+* !connector->display_info.is_hdmi) from a path that has read
+* the EDID and called drm_edid_connector_update().
+*/
+   const struct edid *edid = drm_edid_raw(drm_edid);
+
+   hdmi->dvi_mode = !drm_detect_monitor_audio(edid);
+   }
+
+   return drm_edid;
 }
 
 static int mtk_hdmi_bridge_attach(struct drm_bridge *bridge,
@@ -1417,7 +1425,7 @@ static const struct drm_bridge_funcs 
mtk_hdmi_bridge_funcs = {
.atomic_pre_enable = mtk_hdmi_bridge_atomic_pre_enable,
.atomic_enable = mtk_hdmi_bridge_atomic_enable,
.detect = mtk_hdmi_bridge_detect,
-   .get_edid = mtk_hdmi_bridge_get_edid,
+   .edid_read = mtk_hdmi_bridge_edid_read,
 };
 
 static int mtk_hdmi_dt_parse_pdata(struct mtk_hdmi *hdmi,
-- 
2.39.2



[PATCH v3 26/39] drm/mediatek/dp: switch to ->edid_read callback

2024-01-23 Thread Jani Nikula
Prefer using the struct drm_edid based callback and functions.

Signed-off-by: Jani Nikula 
---
 drivers/gpu/drm/mediatek/mtk_dp.c | 31 ---
 1 file changed, 20 insertions(+), 11 deletions(-)

diff --git a/drivers/gpu/drm/mediatek/mtk_dp.c 
b/drivers/gpu/drm/mediatek/mtk_dp.c
index 2136a596efa1..0ba72102636a 100644
--- a/drivers/gpu/drm/mediatek/mtk_dp.c
+++ b/drivers/gpu/drm/mediatek/mtk_dp.c
@@ -2042,12 +2042,12 @@ static enum drm_connector_status 
mtk_dp_bdg_detect(struct drm_bridge *bridge)
return ret;
 }
 
-static struct edid *mtk_dp_get_edid(struct drm_bridge *bridge,
-   struct drm_connector *connector)
+static const struct drm_edid *mtk_dp_edid_read(struct drm_bridge *bridge,
+  struct drm_connector *connector)
 {
struct mtk_dp *mtk_dp = mtk_dp_from_bridge(bridge);
bool enabled = mtk_dp->enabled;
-   struct edid *new_edid = NULL;
+   const struct drm_edid *drm_edid;
struct mtk_dp_audio_cfg *audio_caps = _dp->info.audio_cur_cfg;
 
if (!enabled) {
@@ -2055,7 +2055,7 @@ static struct edid *mtk_dp_get_edid(struct drm_bridge 
*bridge,
mtk_dp_aux_panel_poweron(mtk_dp, true);
}
 
-   new_edid = drm_get_edid(connector, _dp->aux.ddc);
+   drm_edid = drm_edid_read_ddc(connector, _dp->aux.ddc);
 
/*
 * Parse capability here to let atomic_get_input_bus_fmts and
@@ -2063,17 +2063,26 @@ static struct edid *mtk_dp_get_edid(struct drm_bridge 
*bridge,
 */
if (mtk_dp_parse_capabilities(mtk_dp)) {
drm_err(mtk_dp->drm_dev, "Can't parse capabilities\n");
-   kfree(new_edid);
-   new_edid = NULL;
+   drm_edid_free(drm_edid);
+   drm_edid = NULL;
}
 
-   if (new_edid) {
+   if (drm_edid) {
+   /*
+* FIXME: get rid of drm_edid_raw()
+*/
+   const struct edid *edid = drm_edid_raw(drm_edid);
struct cea_sad *sads;
 
-   audio_caps->sad_count = drm_edid_to_sad(new_edid, );
+   audio_caps->sad_count = drm_edid_to_sad(edid, );
kfree(sads);
 
-   audio_caps->detect_monitor = drm_detect_monitor_audio(new_edid);
+   /*
+* FIXME: This should use connector->display_info.has_audio from
+* a path that has read the EDID and called
+* drm_edid_connector_update().
+*/
+   audio_caps->detect_monitor = drm_detect_monitor_audio(edid);
}
 
if (!enabled) {
@@ -2081,7 +2090,7 @@ static struct edid *mtk_dp_get_edid(struct drm_bridge 
*bridge,
drm_atomic_bridge_chain_post_disable(bridge, 
connector->state->state);
}
 
-   return new_edid;
+   return drm_edid;
 }
 
 static ssize_t mtk_dp_aux_transfer(struct drm_dp_aux *mtk_aux,
@@ -2433,7 +2442,7 @@ static const struct drm_bridge_funcs mtk_dp_bridge_funcs 
= {
.atomic_enable = mtk_dp_bridge_atomic_enable,
.atomic_disable = mtk_dp_bridge_atomic_disable,
.mode_valid = mtk_dp_bridge_mode_valid,
-   .get_edid = mtk_dp_get_edid,
+   .edid_read = mtk_dp_edid_read,
.detect = mtk_dp_bdg_detect,
 };
 
-- 
2.39.2



[PATCH v3 25/39] drm/bridge: sii902x: switch to ->edid_read callback

2024-01-23 Thread Jani Nikula
Prefer using the struct drm_edid based callback and functions.

Signed-off-by: Jani Nikula 
---
 drivers/gpu/drm/bridge/sii902x.c | 30 +++---
 1 file changed, 15 insertions(+), 15 deletions(-)

diff --git a/drivers/gpu/drm/bridge/sii902x.c b/drivers/gpu/drm/bridge/sii902x.c
index d59e668498c3..8f84e98249c7 100644
--- a/drivers/gpu/drm/bridge/sii902x.c
+++ b/drivers/gpu/drm/bridge/sii902x.c
@@ -278,31 +278,31 @@ static const struct drm_connector_funcs 
sii902x_connector_funcs = {
.atomic_destroy_state = drm_atomic_helper_connector_destroy_state,
 };
 
-static struct edid *sii902x_get_edid(struct sii902x *sii902x,
-struct drm_connector *connector)
+static const struct drm_edid *sii902x_edid_read(struct sii902x *sii902x,
+   struct drm_connector *connector)
 {
-   struct edid *edid;
+   const struct drm_edid *drm_edid;
 
mutex_lock(>mutex);
 
-   edid = drm_get_edid(connector, sii902x->i2cmux->adapter[0]);
+   drm_edid = drm_edid_read_ddc(connector, sii902x->i2cmux->adapter[0]);
 
mutex_unlock(>mutex);
 
-   return edid;
+   return drm_edid;
 }
 
 static int sii902x_get_modes(struct drm_connector *connector)
 {
struct sii902x *sii902x = connector_to_sii902x(connector);
-   struct edid *edid;
+   const struct drm_edid *drm_edid;
int num = 0;
 
-   edid = sii902x_get_edid(sii902x, connector);
-   drm_connector_update_edid_property(connector, edid);
-   if (edid) {
-   num = drm_add_edid_modes(connector, edid);
-   kfree(edid);
+   drm_edid = sii902x_edid_read(sii902x, connector);
+   drm_edid_connector_update(connector, drm_edid);
+   if (drm_edid) {
+   num = drm_edid_connector_add_modes(connector);
+   drm_edid_free(drm_edid);
}
 
sii902x->sink_is_hdmi = connector->display_info.is_hdmi;
@@ -461,12 +461,12 @@ static enum drm_connector_status 
sii902x_bridge_detect(struct drm_bridge *bridge
return sii902x_detect(sii902x);
 }
 
-static struct edid *sii902x_bridge_get_edid(struct drm_bridge *bridge,
-   struct drm_connector *connector)
+static const struct drm_edid *sii902x_bridge_edid_read(struct drm_bridge 
*bridge,
+  struct drm_connector 
*connector)
 {
struct sii902x *sii902x = bridge_to_sii902x(bridge);
 
-   return sii902x_get_edid(sii902x, connector);
+   return sii902x_edid_read(sii902x, connector);
 }
 
 static u32 *sii902x_bridge_atomic_get_input_bus_fmts(struct drm_bridge *bridge,
@@ -510,7 +510,7 @@ static const struct drm_bridge_funcs sii902x_bridge_funcs = 
{
.disable = sii902x_bridge_disable,
.enable = sii902x_bridge_enable,
.detect = sii902x_bridge_detect,
-   .get_edid = sii902x_bridge_get_edid,
+   .edid_read = sii902x_bridge_edid_read,
.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.39.2



[PATCH v3 24/39] drm/bridge: sii902x: use display info is_hdmi

2024-01-23 Thread Jani Nikula
Use the pre-parsed information instead of parsing EDID again.

Signed-off-by: Jani Nikula 
---
 drivers/gpu/drm/bridge/sii902x.c | 8 ++--
 1 file changed, 2 insertions(+), 6 deletions(-)

diff --git a/drivers/gpu/drm/bridge/sii902x.c b/drivers/gpu/drm/bridge/sii902x.c
index 4560ae9cbce1..d59e668498c3 100644
--- a/drivers/gpu/drm/bridge/sii902x.c
+++ b/drivers/gpu/drm/bridge/sii902x.c
@@ -286,12 +286,6 @@ static struct edid *sii902x_get_edid(struct sii902x 
*sii902x,
mutex_lock(>mutex);
 
edid = drm_get_edid(connector, sii902x->i2cmux->adapter[0]);
-   if (edid) {
-   if (drm_detect_hdmi_monitor(edid))
-   sii902x->sink_is_hdmi = true;
-   else
-   sii902x->sink_is_hdmi = false;
-   }
 
mutex_unlock(>mutex);
 
@@ -311,6 +305,8 @@ static int sii902x_get_modes(struct drm_connector 
*connector)
kfree(edid);
}
 
+   sii902x->sink_is_hdmi = connector->display_info.is_hdmi;
+
return num;
 }
 
-- 
2.39.2



[PATCH v3 23/39] drm/bridge: nxp-ptn3460: switch to ->edid_read callback

2024-01-23 Thread Jani Nikula
Prefer using the struct drm_edid based callback and functions.

v2: Fix -Wsometimes-uninitialized (kernel test robot)

Signed-off-by: Jani Nikula 
---
 drivers/gpu/drm/bridge/nxp-ptn3460.c | 22 --
 1 file changed, 12 insertions(+), 10 deletions(-)

diff --git a/drivers/gpu/drm/bridge/nxp-ptn3460.c 
b/drivers/gpu/drm/bridge/nxp-ptn3460.c
index 7c0076e49953..ed93fd4c3265 100644
--- a/drivers/gpu/drm/bridge/nxp-ptn3460.c
+++ b/drivers/gpu/drm/bridge/nxp-ptn3460.c
@@ -154,10 +154,11 @@ static void ptn3460_disable(struct drm_bridge *bridge)
 }
 
 
-static struct edid *ptn3460_get_edid(struct drm_bridge *bridge,
-struct drm_connector *connector)
+static const struct drm_edid *ptn3460_edid_read(struct drm_bridge *bridge,
+   struct drm_connector *connector)
 {
struct ptn3460_bridge *ptn_bridge = bridge_to_ptn3460(bridge);
+   const struct drm_edid *drm_edid = NULL;
bool power_off;
u8 *edid;
int ret;
@@ -175,27 +176,28 @@ static struct edid *ptn3460_get_edid(struct drm_bridge 
*bridge,
 EDID_LENGTH);
if (ret) {
kfree(edid);
-   edid = NULL;
goto out;
}
 
+   drm_edid = drm_edid_alloc(edid, EDID_LENGTH);
+
 out:
if (power_off)
ptn3460_disable(_bridge->bridge);
 
-   return (struct edid *)edid;
+   return drm_edid;
 }
 
 static int ptn3460_connector_get_modes(struct drm_connector *connector)
 {
struct ptn3460_bridge *ptn_bridge = connector_to_ptn3460(connector);
-   struct edid *edid;
+   const struct drm_edid *drm_edid;
int num_modes;
 
-   edid = ptn3460_get_edid(_bridge->bridge, connector);
-   drm_connector_update_edid_property(connector, edid);
-   num_modes = drm_add_edid_modes(connector, edid);
-   kfree(edid);
+   drm_edid = ptn3460_edid_read(_bridge->bridge, connector);
+   drm_edid_connector_update(connector, drm_edid);
+   num_modes = drm_edid_connector_add_modes(connector);
+   drm_edid_free(drm_edid);
 
return num_modes;
 }
@@ -254,7 +256,7 @@ static const struct drm_bridge_funcs ptn3460_bridge_funcs = 
{
.pre_enable = ptn3460_pre_enable,
.disable = ptn3460_disable,
.attach = ptn3460_bridge_attach,
-   .get_edid = ptn3460_get_edid,
+   .edid_read = ptn3460_edid_read,
 };
 
 static int ptn3460_probe(struct i2c_client *client)
-- 
2.39.2



[PATCH v3 22/39] drm/bridge: megachips: switch to ->edid_read callback

2024-01-23 Thread Jani Nikula
Prefer using the struct drm_edid based callback and functions.

Signed-off-by: Jani Nikula 
---
 .../bridge/megachips-stdp-ge-b850v3-fw.c   | 18 +-
 1 file changed, 9 insertions(+), 9 deletions(-)

diff --git a/drivers/gpu/drm/bridge/megachips-stdp-ge-b850v3-fw.c 
b/drivers/gpu/drm/bridge/megachips-stdp-ge-b850v3-fw.c
index e93083bbec9d..4480523244e4 100644
--- a/drivers/gpu/drm/bridge/megachips-stdp-ge-b850v3-fw.c
+++ b/drivers/gpu/drm/bridge/megachips-stdp-ge-b850v3-fw.c
@@ -91,26 +91,26 @@ static int stdp2690_read_block(void *context, u8 *buf, 
unsigned int block, size_
return 0;
 }
 
-static struct edid *ge_b850v3_lvds_get_edid(struct drm_bridge *bridge,
-   struct drm_connector *connector)
+static const struct drm_edid *ge_b850v3_lvds_edid_read(struct drm_bridge 
*bridge,
+  struct drm_connector 
*connector)
 {
struct i2c_client *client;
 
client = ge_b850v3_lvds_ptr->stdp2690_i2c;
 
-   return drm_do_get_edid(connector, stdp2690_read_block, client);
+   return drm_edid_read_custom(connector, stdp2690_read_block, client);
 }
 
 static int ge_b850v3_lvds_get_modes(struct drm_connector *connector)
 {
-   struct edid *edid;
+   const struct drm_edid *drm_edid;
int num_modes;
 
-   edid = ge_b850v3_lvds_get_edid(_b850v3_lvds_ptr->bridge, connector);
+   drm_edid = ge_b850v3_lvds_edid_read(_b850v3_lvds_ptr->bridge, 
connector);
 
-   drm_connector_update_edid_property(connector, edid);
-   num_modes = drm_add_edid_modes(connector, edid);
-   kfree(edid);
+   drm_edid_connector_update(connector, drm_edid);
+   num_modes = drm_edid_connector_add_modes(connector);
+   drm_edid_free(drm_edid);
 
return num_modes;
 }
@@ -226,7 +226,7 @@ static int ge_b850v3_lvds_attach(struct drm_bridge *bridge,
 static const struct drm_bridge_funcs ge_b850v3_lvds_funcs = {
.attach = ge_b850v3_lvds_attach,
.detect = ge_b850v3_lvds_bridge_detect,
-   .get_edid = ge_b850v3_lvds_get_edid,
+   .edid_read = ge_b850v3_lvds_edid_read,
 };
 
 static int ge_b850v3_lvds_init(struct device *dev)
-- 
2.39.2



[PATCH v3 21/39] drm/bridge: lt9611uxc: switch to ->edid_read callback

2024-01-23 Thread Jani Nikula
Prefer using the struct drm_edid based callback and functions.

Signed-off-by: Jani Nikula 
---
 drivers/gpu/drm/bridge/lontium-lt9611uxc.c | 8 
 1 file changed, 4 insertions(+), 4 deletions(-)

diff --git a/drivers/gpu/drm/bridge/lontium-lt9611uxc.c 
b/drivers/gpu/drm/bridge/lontium-lt9611uxc.c
index 4eaf99618749..bcf8bccd86d6 100644
--- a/drivers/gpu/drm/bridge/lontium-lt9611uxc.c
+++ b/drivers/gpu/drm/bridge/lontium-lt9611uxc.c
@@ -495,8 +495,8 @@ static int lt9611uxc_get_edid_block(void *data, u8 *buf, 
unsigned int block, siz
return 0;
 };
 
-static struct edid *lt9611uxc_bridge_get_edid(struct drm_bridge *bridge,
- struct drm_connector *connector)
+static const struct drm_edid *lt9611uxc_bridge_edid_read(struct drm_bridge 
*bridge,
+struct drm_connector 
*connector)
 {
struct lt9611uxc *lt9611uxc = bridge_to_lt9611uxc(bridge);
int ret;
@@ -510,7 +510,7 @@ static struct edid *lt9611uxc_bridge_get_edid(struct 
drm_bridge *bridge,
return NULL;
}
 
-   return drm_do_get_edid(connector, lt9611uxc_get_edid_block, lt9611uxc);
+   return drm_edid_read_custom(connector, lt9611uxc_get_edid_block, 
lt9611uxc);
 }
 
 static const struct drm_bridge_funcs lt9611uxc_bridge_funcs = {
@@ -518,7 +518,7 @@ static const struct drm_bridge_funcs lt9611uxc_bridge_funcs 
= {
.mode_valid = lt9611uxc_bridge_mode_valid,
.mode_set = lt9611uxc_bridge_mode_set,
.detect = lt9611uxc_bridge_detect,
-   .get_edid = lt9611uxc_bridge_get_edid,
+   .edid_read = lt9611uxc_bridge_edid_read,
 };
 
 static int lt9611uxc_parse_dt(struct device *dev,
-- 
2.39.2



[PATCH v3 20/39] drm/bridge: lt9611: switch to ->edid_read callback

2024-01-23 Thread Jani Nikula
Prefer using the struct drm_edid based callback and functions.

Signed-off-by: Jani Nikula 
---
 drivers/gpu/drm/bridge/lontium-lt9611.c | 8 
 1 file changed, 4 insertions(+), 4 deletions(-)

diff --git a/drivers/gpu/drm/bridge/lontium-lt9611.c 
b/drivers/gpu/drm/bridge/lontium-lt9611.c
index b9205d14d943..a9c7e2b07ea1 100644
--- a/drivers/gpu/drm/bridge/lontium-lt9611.c
+++ b/drivers/gpu/drm/bridge/lontium-lt9611.c
@@ -847,13 +847,13 @@ lt9611_bridge_atomic_post_disable(struct drm_bridge 
*bridge,
lt9611_sleep_setup(lt9611);
 }
 
-static struct edid *lt9611_bridge_get_edid(struct drm_bridge *bridge,
-  struct drm_connector *connector)
+static const struct drm_edid *lt9611_bridge_edid_read(struct drm_bridge 
*bridge,
+ struct drm_connector 
*connector)
 {
struct lt9611 *lt9611 = bridge_to_lt9611(bridge);
 
lt9611_power_on(lt9611);
-   return drm_do_get_edid(connector, lt9611_get_edid_block, lt9611);
+   return drm_edid_read_custom(connector, lt9611_get_edid_block, lt9611);
 }
 
 static void lt9611_bridge_hpd_enable(struct drm_bridge *bridge)
@@ -893,7 +893,7 @@ static const struct drm_bridge_funcs lt9611_bridge_funcs = {
.attach = lt9611_bridge_attach,
.mode_valid = lt9611_bridge_mode_valid,
.detect = lt9611_bridge_detect,
-   .get_edid = lt9611_bridge_get_edid,
+   .edid_read = lt9611_bridge_edid_read,
.hpd_enable = lt9611_bridge_hpd_enable,
 
.atomic_pre_enable = lt9611_bridge_atomic_pre_enable,
-- 
2.39.2



[PATCH v3 19/39] drm: bridge: it66121: switch to ->edid_read callback

2024-01-23 Thread Jani Nikula
Prefer using the struct drm_edid based callback and functions.

Signed-off-by: Jani Nikula 
---
 drivers/gpu/drm/bridge/ite-it66121.c | 16 
 1 file changed, 8 insertions(+), 8 deletions(-)

diff --git a/drivers/gpu/drm/bridge/ite-it66121.c 
b/drivers/gpu/drm/bridge/ite-it66121.c
index 1cf3fb1f13dc..1c3433b5e366 100644
--- a/drivers/gpu/drm/bridge/ite-it66121.c
+++ b/drivers/gpu/drm/bridge/ite-it66121.c
@@ -874,33 +874,33 @@ static void it66121_bridge_hpd_disable(struct drm_bridge 
*bridge)
dev_err(ctx->dev, "failed to disable HPD IRQ\n");
 }
 
-static struct edid *it66121_bridge_get_edid(struct drm_bridge *bridge,
-   struct drm_connector *connector)
+static const struct drm_edid *it66121_bridge_edid_read(struct drm_bridge 
*bridge,
+  struct drm_connector 
*connector)
 {
struct it66121_ctx *ctx = container_of(bridge, struct it66121_ctx, 
bridge);
-   struct edid *edid;
+   const struct drm_edid *drm_edid;
int ret;
 
mutex_lock(>lock);
ret = it66121_preamble_ddc(ctx);
if (ret) {
-   edid = NULL;
+   drm_edid = NULL;
goto out_unlock;
}
 
ret = regmap_write(ctx->regmap, IT66121_DDC_HEADER_REG,
   IT66121_DDC_HEADER_EDID);
if (ret) {
-   edid = NULL;
+   drm_edid = NULL;
goto out_unlock;
}
 
-   edid = drm_do_get_edid(connector, it66121_get_edid_block, ctx);
+   drm_edid = drm_edid_read_custom(connector, it66121_get_edid_block, ctx);
 
 out_unlock:
mutex_unlock(>lock);
 
-   return edid;
+   return drm_edid;
 }
 
 static const struct drm_bridge_funcs it66121_bridge_funcs = {
@@ -916,7 +916,7 @@ static const struct drm_bridge_funcs it66121_bridge_funcs = 
{
.mode_set = it66121_bridge_mode_set,
.mode_valid = it66121_bridge_mode_valid,
.detect = it66121_bridge_detect,
-   .get_edid = it66121_bridge_get_edid,
+   .edid_read = it66121_bridge_edid_read,
.hpd_enable = it66121_bridge_hpd_enable,
.hpd_disable = it66121_bridge_hpd_disable,
 };
-- 
2.39.2



[PATCH v3 18/39] drm/bridge: it6505: switch to ->edid_read callback

2024-01-23 Thread Jani Nikula
Prefer using the struct drm_edid based callback and functions.

Signed-off-by: Jani Nikula 
---
 drivers/gpu/drm/bridge/ite-it6505.c | 17 +
 1 file changed, 9 insertions(+), 8 deletions(-)

diff --git a/drivers/gpu/drm/bridge/ite-it6505.c 
b/drivers/gpu/drm/bridge/ite-it6505.c
index b589136ca6da..27334173e911 100644
--- a/drivers/gpu/drm/bridge/ite-it6505.c
+++ b/drivers/gpu/drm/bridge/ite-it6505.c
@@ -458,7 +458,7 @@ struct it6505 {
/* it6505 driver hold option */
bool enable_drv_hold;
 
-   struct edid *cached_edid;
+   const struct drm_edid *cached_edid;
 };
 
 struct it6505_step_train_para {
@@ -2263,7 +2263,7 @@ static void it6505_plugged_status_to_codec(struct it6505 
*it6505)
 
 static void it6505_remove_edid(struct it6505 *it6505)
 {
-   kfree(it6505->cached_edid);
+   drm_edid_free(it6505->cached_edid);
it6505->cached_edid = NULL;
 }
 
@@ -3034,15 +3034,16 @@ it6505_bridge_detect(struct drm_bridge *bridge)
return it6505_detect(it6505);
 }
 
-static struct edid *it6505_bridge_get_edid(struct drm_bridge *bridge,
-  struct drm_connector *connector)
+static const struct drm_edid *it6505_bridge_edid_read(struct drm_bridge 
*bridge,
+ struct drm_connector 
*connector)
 {
struct it6505 *it6505 = bridge_to_it6505(bridge);
struct device *dev = it6505->dev;
 
if (!it6505->cached_edid) {
-   it6505->cached_edid = drm_do_get_edid(connector, 
it6505_get_edid_block,
- it6505);
+   it6505->cached_edid = drm_edid_read_custom(connector,
+  
it6505_get_edid_block,
+  it6505);
 
if (!it6505->cached_edid) {
DRM_DEV_DEBUG_DRIVER(dev, "failed to get edid!");
@@ -3050,7 +3051,7 @@ static struct edid *it6505_bridge_get_edid(struct 
drm_bridge *bridge,
}
}
 
-   return drm_edid_duplicate(it6505->cached_edid);
+   return drm_edid_dup(it6505->cached_edid);
 }
 
 static const struct drm_bridge_funcs it6505_bridge_funcs = {
@@ -3065,7 +3066,7 @@ static const struct drm_bridge_funcs it6505_bridge_funcs 
= {
.atomic_pre_enable = it6505_bridge_atomic_pre_enable,
.atomic_post_disable = it6505_bridge_atomic_post_disable,
.detect = it6505_bridge_detect,
-   .get_edid = it6505_bridge_get_edid,
+   .edid_read = it6505_bridge_edid_read,
 };
 
 static __maybe_unused int it6505_bridge_resume(struct device *dev)
-- 
2.39.2



[PATCH v3 17/39] drm/bridge: display-connector: switch to ->edid_read callback

2024-01-23 Thread Jani Nikula
Prefer using the struct drm_edid based callback and functions.

Signed-off-by: Jani Nikula 
---
 drivers/gpu/drm/bridge/display-connector.c | 8 
 1 file changed, 4 insertions(+), 4 deletions(-)

diff --git a/drivers/gpu/drm/bridge/display-connector.c 
b/drivers/gpu/drm/bridge/display-connector.c
index 08bd5695ddae..ab8e00baf3f1 100644
--- a/drivers/gpu/drm/bridge/display-connector.c
+++ b/drivers/gpu/drm/bridge/display-connector.c
@@ -81,12 +81,12 @@ display_connector_detect(struct drm_bridge *bridge)
}
 }
 
-static struct edid *display_connector_get_edid(struct drm_bridge *bridge,
-  struct drm_connector *connector)
+static const struct drm_edid *display_connector_edid_read(struct drm_bridge 
*bridge,
+ struct drm_connector 
*connector)
 {
struct display_connector *conn = to_display_connector(bridge);
 
-   return drm_get_edid(connector, conn->bridge.ddc);
+   return drm_edid_read_ddc(connector, conn->bridge.ddc);
 }
 
 /*
@@ -172,7 +172,7 @@ static u32 *display_connector_get_input_bus_fmts(struct 
drm_bridge *bridge,
 static const struct drm_bridge_funcs display_connector_bridge_funcs = {
.attach = display_connector_attach,
.detect = display_connector_detect,
-   .get_edid = display_connector_get_edid,
+   .edid_read = display_connector_edid_read,
.atomic_get_output_bus_fmts = display_connector_get_output_bus_fmts,
.atomic_get_input_bus_fmts = display_connector_get_input_bus_fmts,
.atomic_duplicate_state = drm_atomic_helper_bridge_duplicate_state,
-- 
2.39.2



[PATCH v3 16/39] drm/bridge: cdns-mhdp8546: clear the EDID property on failures

2024-01-23 Thread Jani Nikula
If EDID read fails, clear the EDID property.

Signed-off-by: Jani Nikula 
---
 drivers/gpu/drm/bridge/cadence/cdns-mhdp8546-core.c | 4 +++-
 1 file changed, 3 insertions(+), 1 deletion(-)

diff --git a/drivers/gpu/drm/bridge/cadence/cdns-mhdp8546-core.c 
b/drivers/gpu/drm/bridge/cadence/cdns-mhdp8546-core.c
index e44cb89c33f0..e226acc5c15e 100644
--- a/drivers/gpu/drm/bridge/cadence/cdns-mhdp8546-core.c
+++ b/drivers/gpu/drm/bridge/cadence/cdns-mhdp8546-core.c
@@ -1524,12 +1524,14 @@ static int cdns_mhdp_get_modes(struct drm_connector 
*connector)
return 0;
 
drm_edid = cdns_mhdp_edid_read(mhdp, connector);
+
+   drm_edid_connector_update(connector, drm_edid);
+
if (!drm_edid) {
dev_err(mhdp->dev, "Failed to read EDID\n");
return 0;
}
 
-   drm_edid_connector_update(connector, drm_edid);
num_modes = drm_edid_connector_add_modes(connector);
drm_edid_free(drm_edid);
 
-- 
2.39.2



[PATCH v3 15/39] drm/bridge: cdns-mhdp8546: switch to ->edid_read callback

2024-01-23 Thread Jani Nikula
Prefer using the struct drm_edid based callback and functions.

Signed-off-by: Jani Nikula 
---
 .../drm/bridge/cadence/cdns-mhdp8546-core.c   | 26 +--
 1 file changed, 13 insertions(+), 13 deletions(-)

diff --git a/drivers/gpu/drm/bridge/cadence/cdns-mhdp8546-core.c 
b/drivers/gpu/drm/bridge/cadence/cdns-mhdp8546-core.c
index 7d470527455b..e44cb89c33f0 100644
--- a/drivers/gpu/drm/bridge/cadence/cdns-mhdp8546-core.c
+++ b/drivers/gpu/drm/bridge/cadence/cdns-mhdp8546-core.c
@@ -1505,33 +1505,33 @@ static void cdns_mhdp_link_down(struct cdns_mhdp_device 
*mhdp)
mhdp->link_up = false;
 }
 
-static struct edid *cdns_mhdp_get_edid(struct cdns_mhdp_device *mhdp,
-  struct drm_connector *connector)
+static const struct drm_edid *cdns_mhdp_edid_read(struct cdns_mhdp_device 
*mhdp,
+ struct drm_connector 
*connector)
 {
if (!mhdp->plugged)
return NULL;
 
-   return drm_do_get_edid(connector, cdns_mhdp_get_edid_block, mhdp);
+   return drm_edid_read_custom(connector, cdns_mhdp_get_edid_block, mhdp);
 }
 
 static int cdns_mhdp_get_modes(struct drm_connector *connector)
 {
struct cdns_mhdp_device *mhdp = connector_to_mhdp(connector);
-   struct edid *edid;
+   const struct drm_edid *drm_edid;
int num_modes;
 
if (!mhdp->plugged)
return 0;
 
-   edid = cdns_mhdp_get_edid(mhdp, connector);
-   if (!edid) {
+   drm_edid = cdns_mhdp_edid_read(mhdp, connector);
+   if (!drm_edid) {
dev_err(mhdp->dev, "Failed to read EDID\n");
return 0;
}
 
-   drm_connector_update_edid_property(connector, edid);
-   num_modes = drm_add_edid_modes(connector, edid);
-   kfree(edid);
+   drm_edid_connector_update(connector, drm_edid);
+   num_modes = drm_edid_connector_add_modes(connector);
+   drm_edid_free(drm_edid);
 
/*
 * HACK: Warn about unsupported display formats until we deal
@@ -2220,12 +2220,12 @@ static enum drm_connector_status 
cdns_mhdp_bridge_detect(struct drm_bridge *brid
return cdns_mhdp_detect(mhdp);
 }
 
-static struct edid *cdns_mhdp_bridge_get_edid(struct drm_bridge *bridge,
- struct drm_connector *connector)
+static const struct drm_edid *cdns_mhdp_bridge_edid_read(struct drm_bridge 
*bridge,
+struct drm_connector 
*connector)
 {
struct cdns_mhdp_device *mhdp = bridge_to_mhdp(bridge);
 
-   return cdns_mhdp_get_edid(mhdp, connector);
+   return cdns_mhdp_edid_read(mhdp, connector);
 }
 
 static const struct drm_bridge_funcs cdns_mhdp_bridge_funcs = {
@@ -2239,7 +2239,7 @@ static const struct drm_bridge_funcs 
cdns_mhdp_bridge_funcs = {
.atomic_reset = cdns_mhdp_bridge_atomic_reset,
.atomic_get_input_bus_fmts = cdns_mhdp_get_input_bus_fmts,
.detect = cdns_mhdp_bridge_detect,
-   .get_edid = cdns_mhdp_bridge_get_edid,
+   .edid_read = cdns_mhdp_bridge_edid_read,
.hpd_enable = cdns_mhdp_bridge_hpd_enable,
.hpd_disable = cdns_mhdp_bridge_hpd_disable,
 };
-- 
2.39.2



[PATCH v3 14/39] drm/bridge: anx7625: switch to ->edid_read callback

2024-01-23 Thread Jani Nikula
Prefer using the struct drm_edid based callback.

v2: Fix build (goto out;)

Signed-off-by: Jani Nikula 
---
 drivers/gpu/drm/bridge/analogix/anx7625.c | 30 ---
 1 file changed, 10 insertions(+), 20 deletions(-)

diff --git a/drivers/gpu/drm/bridge/analogix/anx7625.c 
b/drivers/gpu/drm/bridge/analogix/anx7625.c
index 29d91493b101..9d96d28d6fe8 100644
--- a/drivers/gpu/drm/bridge/analogix/anx7625.c
+++ b/drivers/gpu/drm/bridge/analogix/anx7625.c
@@ -1784,24 +1784,14 @@ static ssize_t anx7625_aux_transfer(struct drm_dp_aux 
*aux,
return ret;
 }
 
-static struct edid *anx7625_get_edid(struct anx7625_data *ctx)
+static const struct drm_edid *anx7625_edid_read(struct anx7625_data *ctx)
 {
struct device *dev = ctx->dev;
struct s_edid_data *p_edid = >slimport_edid_p;
int edid_num;
-   u8 *edid;
 
-   edid = kmalloc(FOUR_BLOCK_SIZE, GFP_KERNEL);
-   if (!edid) {
-   DRM_DEV_ERROR(dev, "Fail to allocate buffer\n");
-   return NULL;
-   }
-
-   if (ctx->slimport_edid_p.edid_block_num > 0) {
-   memcpy(edid, ctx->slimport_edid_p.edid_raw_data,
-  FOUR_BLOCK_SIZE);
-   return (struct edid *)edid;
-   }
+   if (ctx->slimport_edid_p.edid_block_num > 0)
+   goto out;
 
pm_runtime_get_sync(dev);
_anx7625_hpd_polling(ctx, 5000 * 100);
@@ -1810,14 +1800,14 @@ static struct edid *anx7625_get_edid(struct 
anx7625_data *ctx)
 
if (edid_num < 1) {
DRM_DEV_ERROR(dev, "Fail to read EDID: %d\n", edid_num);
-   kfree(edid);
return NULL;
}
 
p_edid->edid_block_num = edid_num;
 
-   memcpy(edid, ctx->slimport_edid_p.edid_raw_data, FOUR_BLOCK_SIZE);
-   return (struct edid *)edid;
+out:
+   return drm_edid_alloc(ctx->slimport_edid_p.edid_raw_data,
+ FOUR_BLOCK_SIZE);
 }
 
 static enum drm_connector_status anx7625_sink_detect(struct anx7625_data *ctx)
@@ -2492,15 +2482,15 @@ anx7625_bridge_detect(struct drm_bridge *bridge)
return anx7625_sink_detect(ctx);
 }
 
-static struct edid *anx7625_bridge_get_edid(struct drm_bridge *bridge,
-   struct drm_connector *connector)
+static const struct drm_edid *anx7625_bridge_edid_read(struct drm_bridge 
*bridge,
+  struct drm_connector 
*connector)
 {
struct anx7625_data *ctx = bridge_to_anx7625(bridge);
struct device *dev = ctx->dev;
 
DRM_DEV_DEBUG_DRIVER(dev, "drm bridge get edid\n");
 
-   return anx7625_get_edid(ctx);
+   return anx7625_edid_read(ctx);
 }
 
 static const struct drm_bridge_funcs anx7625_bridge_funcs = {
@@ -2515,7 +2505,7 @@ static const struct drm_bridge_funcs anx7625_bridge_funcs 
= {
.atomic_destroy_state = drm_atomic_helper_bridge_destroy_state,
.atomic_reset = drm_atomic_helper_bridge_reset,
.detect = anx7625_bridge_detect,
-   .get_edid = anx7625_bridge_get_edid,
+   .edid_read = anx7625_bridge_edid_read,
 };
 
 static int anx7625_register_i2c_dummy_clients(struct anx7625_data *ctx,
-- 
2.39.2



[PATCH v3 13/39] drm/bridge: remove drm_bridge_get_edid() in favour of drm_bridge_edid_read()

2024-01-23 Thread Jani Nikula
All users of drm_bridge_get_edid() have been converted to use
drm_bridge_edid_read(). Remove drm_bridge_get_edid().

Signed-off-by: Jani Nikula 
---
 drivers/gpu/drm/drm_bridge.c | 28 ++--
 include/drm/drm_bridge.h |  2 --
 2 files changed, 2 insertions(+), 28 deletions(-)

diff --git a/drivers/gpu/drm/drm_bridge.c b/drivers/gpu/drm/drm_bridge.c
index 4f6f8c662d3f..a3065d4aa3d6 100644
--- a/drivers/gpu/drm/drm_bridge.c
+++ b/drivers/gpu/drm/drm_bridge.c
@@ -1217,7 +1217,7 @@ EXPORT_SYMBOL_GPL(drm_bridge_get_modes);
  * the EDID and return it. Otherwise return NULL.
  *
  * If _bridge_funcs.edid_read is not set, fall back to using
- * drm_bridge_get_edid() and wrapping it in struct drm_edid.
+ * _bridge_funcs.get_edid and wrapping it in struct drm_edid.
  *
  * RETURNS:
  * The retrieved EDID on success, or NULL otherwise.
@@ -1233,7 +1233,7 @@ const struct drm_edid *drm_bridge_edid_read(struct 
drm_bridge *bridge,
const struct drm_edid *drm_edid;
struct edid *edid;
 
-   edid = drm_bridge_get_edid(bridge, connector);
+   edid = bridge->funcs->get_edid(bridge, connector);
if (!edid)
return NULL;
 
@@ -1248,30 +1248,6 @@ const struct drm_edid *drm_bridge_edid_read(struct 
drm_bridge *bridge,
 }
 EXPORT_SYMBOL_GPL(drm_bridge_edid_read);
 
-/**
- * drm_bridge_get_edid - get the EDID data of the connected display
- * @bridge: bridge control structure
- * @connector: the connector to read EDID for
- *
- * If the bridge supports output EDID retrieval, as reported by the
- * DRM_BRIDGE_OP_EDID bridge ops flag, call _bridge_funcs.get_edid to
- * get the EDID and return it. Otherwise return NULL.
- *
- * Deprecated. Prefer using drm_bridge_edid_read().
- *
- * RETURNS:
- * The retrieved EDID on success, or NULL otherwise.
- */
-struct edid *drm_bridge_get_edid(struct drm_bridge *bridge,
-struct drm_connector *connector)
-{
-   if (!(bridge->ops & DRM_BRIDGE_OP_EDID))
-   return NULL;
-
-   return bridge->funcs->get_edid(bridge, connector);
-}
-EXPORT_SYMBOL_GPL(drm_bridge_get_edid);
-
 /**
  * drm_bridge_hpd_enable - enable hot plug detection for the bridge
  * @bridge: bridge control structure
diff --git a/include/drm/drm_bridge.h b/include/drm/drm_bridge.h
index b7aed3ead705..ee12f829aaf7 100644
--- a/include/drm/drm_bridge.h
+++ b/include/drm/drm_bridge.h
@@ -921,8 +921,6 @@ int drm_bridge_get_modes(struct drm_bridge *bridge,
 struct drm_connector *connector);
 const struct drm_edid *drm_bridge_edid_read(struct drm_bridge *bridge,
struct drm_connector *connector);
-struct edid *drm_bridge_get_edid(struct drm_bridge *bridge,
-struct drm_connector *connector);
 void drm_bridge_hpd_enable(struct drm_bridge *bridge,
   void (*cb)(void *data,
  enum drm_connector_status status),
-- 
2.39.2



[PATCH v3 12/39] drm/meson: switch to drm_bridge_edid_read()

2024-01-23 Thread Jani Nikula
Prefer using the struct drm_edid based functions.

Not ideal, should use source physical address from connector info.

Signed-off-by: Jani Nikula 
---
 drivers/gpu/drm/meson/meson_encoder_hdmi.c | 20 
 1 file changed, 16 insertions(+), 4 deletions(-)

diff --git a/drivers/gpu/drm/meson/meson_encoder_hdmi.c 
b/drivers/gpu/drm/meson/meson_encoder_hdmi.c
index 25ea76558690..fff6ce394f98 100644
--- a/drivers/gpu/drm/meson/meson_encoder_hdmi.c
+++ b/drivers/gpu/drm/meson/meson_encoder_hdmi.c
@@ -323,19 +323,31 @@ static void meson_encoder_hdmi_hpd_notify(struct 
drm_bridge *bridge,
  enum drm_connector_status status)
 {
struct meson_encoder_hdmi *encoder_hdmi = 
bridge_to_meson_encoder_hdmi(bridge);
-   struct edid *edid;
 
if (!encoder_hdmi->cec_notifier)
return;
 
if (status == connector_status_connected) {
-   edid = drm_bridge_get_edid(encoder_hdmi->next_bridge, 
encoder_hdmi->connector);
-   if (!edid)
+   const struct drm_edid *drm_edid;
+   const struct edid *edid;
+
+   drm_edid = drm_bridge_edid_read(encoder_hdmi->next_bridge,
+   encoder_hdmi->connector);
+   if (!drm_edid)
return;
 
+   /*
+* FIXME: The CEC physical address should be set using
+* cec_notifier_set_phys_addr(encoder_hdmi->cec_notifier,
+* connector->display_info.source_physical_address) from a path
+* that has read the EDID and called
+* drm_edid_connector_update().
+*/
+   edid = drm_edid_raw(drm_edid);
+

cec_notifier_set_phys_addr_from_edid(encoder_hdmi->cec_notifier, edid);
 
-   kfree(edid);
+   drm_edid_free(drm_edid);
} else
cec_notifier_phys_addr_invalidate(encoder_hdmi->cec_notifier);
 }
-- 
2.39.2



[PATCH v3 11/39] drm/bridge: tfp410: clear the EDID property on failures

2024-01-23 Thread Jani Nikula
If EDID read fails, clear the EDID property.

Cc: Andrzej Hajda 
Cc: Neil Armstrong 
Cc: Robert Foss 
Cc: Laurent Pinchart 
Cc: Jonas Karlman 
Cc: Jernej Skrabec 
Signed-off-by: Jani Nikula 
---
 drivers/gpu/drm/bridge/ti-tfp410.c | 4 ++--
 1 file changed, 2 insertions(+), 2 deletions(-)

diff --git a/drivers/gpu/drm/bridge/ti-tfp410.c 
b/drivers/gpu/drm/bridge/ti-tfp410.c
index dd14731eb03e..c7bef5c23927 100644
--- a/drivers/gpu/drm/bridge/ti-tfp410.c
+++ b/drivers/gpu/drm/bridge/ti-tfp410.c
@@ -61,6 +61,8 @@ static int tfp410_get_modes(struct drm_connector *connector)
drm_edid = NULL;
}
 
+   drm_edid_connector_update(connector, drm_edid);
+
if (!drm_edid) {
/*
 * No EDID, fallback on the XGA standard modes and prefer a mode
@@ -71,8 +73,6 @@ static int tfp410_get_modes(struct drm_connector *connector)
return ret;
}
 
-   drm_edid_connector_update(connector, drm_edid);
-
ret = drm_edid_connector_add_modes(connector);
 
drm_edid_free(drm_edid);
-- 
2.39.2



[PATCH v3 10/39] drm/bridge: tfp410: use drm_bridge_edid_read()

2024-01-23 Thread Jani Nikula
Prefer using the struct drm_edid based functions.

Cc: Andrzej Hajda 
Cc: Neil Armstrong 
Cc: Robert Foss 
Cc: Laurent Pinchart 
Cc: Jonas Karlman 
Cc: Jernej Skrabec 
Signed-off-by: Jani Nikula 
---
 drivers/gpu/drm/bridge/ti-tfp410.c | 16 
 1 file changed, 8 insertions(+), 8 deletions(-)

diff --git a/drivers/gpu/drm/bridge/ti-tfp410.c 
b/drivers/gpu/drm/bridge/ti-tfp410.c
index 28848a8eb42e..dd14731eb03e 100644
--- a/drivers/gpu/drm/bridge/ti-tfp410.c
+++ b/drivers/gpu/drm/bridge/ti-tfp410.c
@@ -50,18 +50,18 @@ drm_connector_to_tfp410(struct drm_connector *connector)
 static int tfp410_get_modes(struct drm_connector *connector)
 {
struct tfp410 *dvi = drm_connector_to_tfp410(connector);
-   struct edid *edid;
+   const struct drm_edid *drm_edid;
int ret;
 
if (dvi->next_bridge->ops & DRM_BRIDGE_OP_EDID) {
-   edid = drm_bridge_get_edid(dvi->next_bridge, connector);
-   if (!edid)
+   drm_edid = drm_bridge_edid_read(dvi->next_bridge, connector);
+   if (!drm_edid)
DRM_INFO("EDID read failed. Fallback to standard 
modes\n");
} else {
-   edid = NULL;
+   drm_edid = NULL;
}
 
-   if (!edid) {
+   if (!drm_edid) {
/*
 * No EDID, fallback on the XGA standard modes and prefer a mode
 * pretty much anything can handle.
@@ -71,11 +71,11 @@ static int tfp410_get_modes(struct drm_connector *connector)
return ret;
}
 
-   drm_connector_update_edid_property(connector, edid);
+   drm_edid_connector_update(connector, drm_edid);
 
-   ret = drm_add_edid_modes(connector, edid);
+   ret = drm_edid_connector_add_modes(connector);
 
-   kfree(edid);
+   drm_edid_free(drm_edid);
 
return ret;
 }
-- 
2.39.2



[PATCH v3 09/39] drm: bridge: simple-bridge: clear the EDID property on failures

2024-01-23 Thread Jani Nikula
If EDID read fails, clear the EDID property.

Cc: Andrzej Hajda 
Cc: Neil Armstrong 
Cc: Robert Foss 
Cc: Laurent Pinchart 
Cc: Jonas Karlman 
Cc: Jernej Skrabec 
Signed-off-by: Jani Nikula 
---
 drivers/gpu/drm/bridge/simple-bridge.c | 3 ++-
 1 file changed, 2 insertions(+), 1 deletion(-)

diff --git a/drivers/gpu/drm/bridge/simple-bridge.c 
b/drivers/gpu/drm/bridge/simple-bridge.c
index e0cf7721bb8c..5813a2c4fc5e 100644
--- a/drivers/gpu/drm/bridge/simple-bridge.c
+++ b/drivers/gpu/drm/bridge/simple-bridge.c
@@ -62,6 +62,8 @@ static int simple_bridge_get_modes(struct drm_connector 
*connector)
drm_edid = NULL;
}
 
+   drm_edid_connector_update(connector, drm_edid);
+
if (!drm_edid) {
/*
 * In case we cannot retrieve the EDIDs (missing or broken DDC
@@ -73,7 +75,6 @@ static int simple_bridge_get_modes(struct drm_connector 
*connector)
return ret;
}
 
-   drm_edid_connector_update(connector, drm_edid);
ret = drm_edid_connector_add_modes(connector);
drm_edid_free(drm_edid);
 
-- 
2.39.2



[PATCH v3 08/39] drm: bridge: simple-bridge: use drm_bridge_edid_read()

2024-01-23 Thread Jani Nikula
Prefer using the struct drm_edid based functions.

Cc: Andrzej Hajda 
Cc: Neil Armstrong 
Cc: Robert Foss 
Cc: Laurent Pinchart 
Cc: Jonas Karlman 
Cc: Jernej Skrabec 
Signed-off-by: Jani Nikula 
---
 drivers/gpu/drm/bridge/simple-bridge.c | 16 
 1 file changed, 8 insertions(+), 8 deletions(-)

diff --git a/drivers/gpu/drm/bridge/simple-bridge.c 
b/drivers/gpu/drm/bridge/simple-bridge.c
index cbe8e778d7c7..e0cf7721bb8c 100644
--- a/drivers/gpu/drm/bridge/simple-bridge.c
+++ b/drivers/gpu/drm/bridge/simple-bridge.c
@@ -51,18 +51,18 @@ drm_connector_to_simple_bridge(struct drm_connector 
*connector)
 static int simple_bridge_get_modes(struct drm_connector *connector)
 {
struct simple_bridge *sbridge = 
drm_connector_to_simple_bridge(connector);
-   struct edid *edid;
+   const struct drm_edid *drm_edid;
int ret;
 
if (sbridge->next_bridge->ops & DRM_BRIDGE_OP_EDID) {
-   edid = drm_bridge_get_edid(sbridge->next_bridge, connector);
-   if (!edid)
+   drm_edid = drm_bridge_edid_read(sbridge->next_bridge, 
connector);
+   if (!drm_edid)
DRM_INFO("EDID read failed. Fallback to standard 
modes\n");
} else {
-   edid = NULL;
+   drm_edid = NULL;
}
 
-   if (!edid) {
+   if (!drm_edid) {
/*
 * In case we cannot retrieve the EDIDs (missing or broken DDC
 * bus from the next bridge), fallback on the XGA standards and
@@ -73,9 +73,9 @@ static int simple_bridge_get_modes(struct drm_connector 
*connector)
return ret;
}
 
-   drm_connector_update_edid_property(connector, edid);
-   ret = drm_add_edid_modes(connector, edid);
-   kfree(edid);
+   drm_edid_connector_update(connector, drm_edid);
+   ret = drm_edid_connector_add_modes(connector);
+   drm_edid_free(drm_edid);
 
return ret;
 }
-- 
2.39.2



[PATCH v3 07/39] drm/bridge: lt9611uxc: use drm_bridge_read_edid()

2024-01-23 Thread Jani Nikula
Prefer using the struct drm_edid based functions.

Cc: Andrzej Hajda 
Cc: Neil Armstrong 
Cc: Robert Foss 
Cc: Laurent Pinchart 
Cc: Jonas Karlman 
Cc: Jernej Skrabec 
Signed-off-by: Jani Nikula 
---
 drivers/gpu/drm/bridge/lontium-lt9611uxc.c | 10 +-
 1 file changed, 5 insertions(+), 5 deletions(-)

diff --git a/drivers/gpu/drm/bridge/lontium-lt9611uxc.c 
b/drivers/gpu/drm/bridge/lontium-lt9611uxc.c
index f3f130c1ef0a..4eaf99618749 100644
--- a/drivers/gpu/drm/bridge/lontium-lt9611uxc.c
+++ b/drivers/gpu/drm/bridge/lontium-lt9611uxc.c
@@ -295,12 +295,12 @@ static int lt9611uxc_connector_get_modes(struct 
drm_connector *connector)
 {
struct lt9611uxc *lt9611uxc = connector_to_lt9611uxc(connector);
unsigned int count;
-   struct edid *edid;
+   const struct drm_edid *drm_edid;
 
-   edid = drm_bridge_get_edid(>bridge, connector);
-   drm_connector_update_edid_property(connector, edid);
-   count = drm_add_edid_modes(connector, edid);
-   kfree(edid);
+   drm_edid = drm_bridge_edid_read(>bridge, connector);
+   drm_edid_connector_update(connector, drm_edid);
+   count = drm_edid_connector_add_modes(connector);
+   drm_edid_free(drm_edid);
 
return count;
 }
-- 
2.39.2



[PATCH v3 06/39] drm/bridge: lt8912b: use ->edid_read callback

2024-01-23 Thread Jani Nikula
Prefer using the struct drm_edid based functions.

Cc: Adrien Grassein 
Cc: Andrzej Hajda 
Cc: Neil Armstrong 
Cc: Robert Foss 
Cc: Laurent Pinchart 
Cc: Jonas Karlman 
Cc: Jernej Skrabec 
Signed-off-by: Jani Nikula 
---
 drivers/gpu/drm/bridge/lontium-lt8912b.c | 8 
 1 file changed, 4 insertions(+), 4 deletions(-)

diff --git a/drivers/gpu/drm/bridge/lontium-lt8912b.c 
b/drivers/gpu/drm/bridge/lontium-lt8912b.c
index 9c0ffc1c6fac..e7c4bef74aa4 100644
--- a/drivers/gpu/drm/bridge/lontium-lt8912b.c
+++ b/drivers/gpu/drm/bridge/lontium-lt8912b.c
@@ -620,8 +620,8 @@ lt8912_bridge_detect(struct drm_bridge *bridge)
return lt8912_check_cable_status(lt);
 }
 
-static struct edid *lt8912_bridge_get_edid(struct drm_bridge *bridge,
-  struct drm_connector *connector)
+static const struct drm_edid *lt8912_bridge_edid_read(struct drm_bridge 
*bridge,
+ struct drm_connector 
*connector)
 {
struct lt8912 *lt = bridge_to_lt8912(bridge);
 
@@ -630,7 +630,7 @@ static struct edid *lt8912_bridge_get_edid(struct 
drm_bridge *bridge,
 * given to the hdmi connector node.
 */
if (lt->hdmi_port->ops & DRM_BRIDGE_OP_EDID)
-   return drm_bridge_get_edid(lt->hdmi_port, connector);
+   return drm_bridge_edid_read(lt->hdmi_port, connector);
 
dev_warn(lt->dev, "The connected bridge does not supports 
DRM_BRIDGE_OP_EDID\n");
return NULL;
@@ -642,7 +642,7 @@ static const struct drm_bridge_funcs lt8912_bridge_funcs = {
.mode_set = lt8912_bridge_mode_set,
.enable = lt8912_bridge_enable,
.detect = lt8912_bridge_detect,
-   .get_edid = lt8912_bridge_get_edid,
+   .edid_read = lt8912_bridge_edid_read,
 };
 
 static int lt8912_bridge_resume(struct device *dev)
-- 
2.39.2



[PATCH v3 05/39] drm/bridge: lt8912b: clear the EDID property on failures

2024-01-23 Thread Jani Nikula
If EDID read fails, clear the EDID property.

Cc: Adrien Grassein 
Cc: Andrzej Hajda 
Cc: Neil Armstrong 
Cc: Robert Foss 
Cc: Laurent Pinchart 
Cc: Jonas Karlman 
Cc: Jernej Skrabec 
Signed-off-by: Jani Nikula 
---
 drivers/gpu/drm/bridge/lontium-lt8912b.c | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/drivers/gpu/drm/bridge/lontium-lt8912b.c 
b/drivers/gpu/drm/bridge/lontium-lt8912b.c
index 4dc748d5d1ee..9c0ffc1c6fac 100644
--- a/drivers/gpu/drm/bridge/lontium-lt8912b.c
+++ b/drivers/gpu/drm/bridge/lontium-lt8912b.c
@@ -447,8 +447,8 @@ static int lt8912_connector_get_modes(struct drm_connector 
*connector)
u32 bus_format = MEDIA_BUS_FMT_RGB888_1X24;
 
drm_edid = drm_bridge_edid_read(lt->hdmi_port, connector);
+   drm_edid_connector_update(connector, drm_edid);
if (drm_edid) {
-   drm_edid_connector_update(connector, drm_edid);
num = drm_edid_connector_add_modes(connector);
} else {
return ret;
-- 
2.39.2



[PATCH v3 04/39] drm/bridge: lt8912b: use drm_bridge_read_edid()

2024-01-23 Thread Jani Nikula
Prefer using the struct drm_edid based functions.

cc: Adrien Grassein 
Cc: Andrzej Hajda 
Cc: Neil Armstrong 
Cc: Robert Foss 
Cc: Laurent Pinchart 
Cc: Jonas Karlman 
Cc: Jernej Skrabec 
Signed-off-by: Jani Nikula 
---
 drivers/gpu/drm/bridge/lontium-lt8912b.c | 12 ++--
 1 file changed, 6 insertions(+), 6 deletions(-)

diff --git a/drivers/gpu/drm/bridge/lontium-lt8912b.c 
b/drivers/gpu/drm/bridge/lontium-lt8912b.c
index 273157428c82..4dc748d5d1ee 100644
--- a/drivers/gpu/drm/bridge/lontium-lt8912b.c
+++ b/drivers/gpu/drm/bridge/lontium-lt8912b.c
@@ -440,16 +440,16 @@ lt8912_connector_mode_valid(struct drm_connector 
*connector,
 
 static int lt8912_connector_get_modes(struct drm_connector *connector)
 {
-   struct edid *edid;
+   const struct drm_edid *drm_edid;
int ret = -1;
int num = 0;
struct lt8912 *lt = connector_to_lt8912(connector);
u32 bus_format = MEDIA_BUS_FMT_RGB888_1X24;
 
-   edid = drm_bridge_get_edid(lt->hdmi_port, connector);
-   if (edid) {
-   drm_connector_update_edid_property(connector, edid);
-   num = drm_add_edid_modes(connector, edid);
+   drm_edid = drm_bridge_edid_read(lt->hdmi_port, connector);
+   if (drm_edid) {
+   drm_edid_connector_update(connector, drm_edid);
+   num = drm_edid_connector_add_modes(connector);
} else {
return ret;
}
@@ -459,7 +459,7 @@ static int lt8912_connector_get_modes(struct drm_connector 
*connector)
if (ret)
num = ret;
 
-   kfree(edid);
+   drm_edid_free(drm_edid);
return num;
 }
 
-- 
2.39.2



[PATCH v3 03/39] drm/bridge: chrontel-ch7033: switch to drm_bridge_read_edid()

2024-01-23 Thread Jani Nikula
Prefer using the struct drm_edid based functions.

Cc: Andrzej Hajda 
Cc: Neil Armstrong 
Cc: Robert Foss 
Cc: Laurent Pinchart 
Cc: Jonas Karlman 
Cc: Jernej Skrabec 
Signed-off-by: Jani Nikula 
---
 drivers/gpu/drm/bridge/chrontel-ch7033.c | 12 ++--
 1 file changed, 6 insertions(+), 6 deletions(-)

diff --git a/drivers/gpu/drm/bridge/chrontel-ch7033.c 
b/drivers/gpu/drm/bridge/chrontel-ch7033.c
index 483c28c7fc99..c83486cf6b15 100644
--- a/drivers/gpu/drm/bridge/chrontel-ch7033.c
+++ b/drivers/gpu/drm/bridge/chrontel-ch7033.c
@@ -230,14 +230,14 @@ static const struct drm_connector_funcs 
ch7033_connector_funcs = {
 static int ch7033_connector_get_modes(struct drm_connector *connector)
 {
struct ch7033_priv *priv = conn_to_ch7033_priv(connector);
-   struct edid *edid;
+   const struct drm_edid *drm_edid;
int ret;
 
-   edid = drm_bridge_get_edid(priv->next_bridge, connector);
-   drm_connector_update_edid_property(connector, edid);
-   if (edid) {
-   ret = drm_add_edid_modes(connector, edid);
-   kfree(edid);
+   drm_edid = drm_bridge_edid_read(priv->next_bridge, connector);
+   drm_edid_connector_update(connector, drm_edid);
+   if (drm_edid) {
+   ret = drm_edid_connector_add_modes(connector);
+   drm_edid_free(drm_edid);
} else {
ret = drm_add_modes_noedid(connector, 1920, 1080);
drm_set_preferred_mode(connector, 1024, 768);
-- 
2.39.2



[PATCH v3 01/39] drm/bridge: add ->edid_read hook and drm_bridge_edid_read()

2024-01-23 Thread Jani Nikula
Add new struct drm_edid based ->edid_read hook and
drm_bridge_edid_read() function to call the hook.

v2: Include drm/drm_edid.h

Signed-off-by: Jani Nikula 
---
 drivers/gpu/drm/drm_bridge.c | 46 +++-
 include/drm/drm_bridge.h | 33 ++
 2 files changed, 78 insertions(+), 1 deletion(-)

diff --git a/drivers/gpu/drm/drm_bridge.c b/drivers/gpu/drm/drm_bridge.c
index cee3188adf3d..4f6f8c662d3f 100644
--- a/drivers/gpu/drm/drm_bridge.c
+++ b/drivers/gpu/drm/drm_bridge.c
@@ -27,8 +27,9 @@
 #include 
 
 #include 
-#include 
 #include 
+#include 
+#include 
 #include 
 #include 
 #include 
@@ -1206,6 +1207,47 @@ int drm_bridge_get_modes(struct drm_bridge *bridge,
 }
 EXPORT_SYMBOL_GPL(drm_bridge_get_modes);
 
+/**
+ * drm_bridge_edid_read - read the EDID data of the connected display
+ * @bridge: bridge control structure
+ * @connector: the connector to read EDID for
+ *
+ * If the bridge supports output EDID retrieval, as reported by the
+ * DRM_BRIDGE_OP_EDID bridge ops flag, call _bridge_funcs.edid_read to get
+ * the EDID and return it. Otherwise return NULL.
+ *
+ * If _bridge_funcs.edid_read is not set, fall back to using
+ * drm_bridge_get_edid() and wrapping it in struct drm_edid.
+ *
+ * RETURNS:
+ * The retrieved EDID on success, or NULL otherwise.
+ */
+const struct drm_edid *drm_bridge_edid_read(struct drm_bridge *bridge,
+   struct drm_connector *connector)
+{
+   if (!(bridge->ops & DRM_BRIDGE_OP_EDID))
+   return NULL;
+
+   /* Transitional: Fall back to ->get_edid. */
+   if (!bridge->funcs->edid_read) {
+   const struct drm_edid *drm_edid;
+   struct edid *edid;
+
+   edid = drm_bridge_get_edid(bridge, connector);
+   if (!edid)
+   return NULL;
+
+   drm_edid = drm_edid_alloc(edid, (edid->extensions + 1) * 
EDID_LENGTH);
+
+   kfree(edid);
+
+   return drm_edid;
+   }
+
+   return bridge->funcs->edid_read(bridge, connector);
+}
+EXPORT_SYMBOL_GPL(drm_bridge_edid_read);
+
 /**
  * drm_bridge_get_edid - get the EDID data of the connected display
  * @bridge: bridge control structure
@@ -1215,6 +1257,8 @@ EXPORT_SYMBOL_GPL(drm_bridge_get_modes);
  * DRM_BRIDGE_OP_EDID bridge ops flag, call _bridge_funcs.get_edid to
  * get the EDID and return it. Otherwise return NULL.
  *
+ * Deprecated. Prefer using drm_bridge_edid_read().
+ *
  * RETURNS:
  * The retrieved EDID on success, or NULL otherwise.
  */
diff --git a/include/drm/drm_bridge.h b/include/drm/drm_bridge.h
index e39da5807ba7..b7aed3ead705 100644
--- a/include/drm/drm_bridge.h
+++ b/include/drm/drm_bridge.h
@@ -557,6 +557,37 @@ struct drm_bridge_funcs {
int (*get_modes)(struct drm_bridge *bridge,
 struct drm_connector *connector);
 
+   /**
+* @edid_read:
+*
+* Read the EDID data of the connected display.
+*
+* The @edid_read callback is the preferred way of reporting mode
+* information for a display connected to the bridge output. Bridges
+* that support reading EDID shall implement this callback and leave
+* the @get_modes callback unimplemented.
+*
+* The caller of this operation shall first verify the output
+* connection status and refrain from reading EDID from a disconnected
+* output.
+*
+* This callback is optional. Bridges that implement it shall set the
+* DRM_BRIDGE_OP_EDID flag in their _bridge->ops.
+*
+* The connector parameter shall be used for the sole purpose of EDID
+* retrieval, and shall not be stored internally by bridge drivers for
+* future usage.
+*
+* RETURNS:
+*
+* An edid structure newly allocated with drm_edid_alloc() or returned
+* from drm_edid_read() family of functions on success, or NULL
+* otherwise. The caller is responsible for freeing the returned edid
+* structure with drm_edid_free().
+*/
+   const struct drm_edid *(*edid_read)(struct drm_bridge *bridge,
+   struct drm_connector *connector);
+
/**
 * @get_edid:
 *
@@ -888,6 +919,8 @@ drm_atomic_helper_bridge_propagate_bus_fmt(struct 
drm_bridge *bridge,
 enum drm_connector_status drm_bridge_detect(struct drm_bridge *bridge);
 int drm_bridge_get_modes(struct drm_bridge *bridge,
 struct drm_connector *connector);
+const struct drm_edid *drm_bridge_edid_read(struct drm_bridge *bridge,
+   struct drm_connector *connector);
 struct edid *drm_bridge_get_edid(struct drm_bridge *bridge,
 struct drm_connector *connector);
 void drm_bridge_hpd_enable(struct drm_bridge *bridge,
-- 
2.39.2



[PATCH v3 02/39] drm/bridge: switch to drm_bridge_read_edid()

2024-01-23 Thread Jani Nikula
Prefer using the struct drm_edid based functions.

Signed-off-by: Jani Nikula 
---
 drivers/gpu/drm/drm_bridge_connector.c | 16 
 1 file changed, 8 insertions(+), 8 deletions(-)

diff --git a/drivers/gpu/drm/drm_bridge_connector.c 
b/drivers/gpu/drm/drm_bridge_connector.c
index 3acd67021ec6..982552c9f92c 100644
--- a/drivers/gpu/drm/drm_bridge_connector.c
+++ b/drivers/gpu/drm/drm_bridge_connector.c
@@ -239,27 +239,27 @@ static int drm_bridge_connector_get_modes_edid(struct 
drm_connector *connector,
   struct drm_bridge *bridge)
 {
enum drm_connector_status status;
-   struct edid *edid;
+   const struct drm_edid *drm_edid;
int n;
 
status = drm_bridge_connector_detect(connector, false);
if (status != connector_status_connected)
goto no_edid;
 
-   edid = drm_bridge_get_edid(bridge, connector);
-   if (!drm_edid_is_valid(edid)) {
-   kfree(edid);
+   drm_edid = drm_bridge_edid_read(bridge, connector);
+   if (!drm_edid_valid(drm_edid)) {
+   drm_edid_free(drm_edid);
goto no_edid;
}
 
-   drm_connector_update_edid_property(connector, edid);
-   n = drm_add_edid_modes(connector, edid);
+   drm_edid_connector_update(connector, drm_edid);
+   n = drm_edid_connector_add_modes(connector);
 
-   kfree(edid);
+   drm_edid_free(drm_edid);
return n;
 
 no_edid:
-   drm_connector_update_edid_property(connector, NULL);
+   drm_edid_connector_update(connector, NULL);
return 0;
 }
 
-- 
2.39.2



[PATCH v3 00/39] drm/bridge: switch to struct drm_edid

2024-01-23 Thread Jani Nikula
v3 of [1] with a couple of patches fixed.

BR,
Jani.

[1] https://patchwork.freedesktop.org/series/128149/


Jani Nikula (39):
  drm/bridge: add ->edid_read hook and drm_bridge_edid_read()
  drm/bridge: switch to drm_bridge_read_edid()
  drm/bridge: chrontel-ch7033: switch to drm_bridge_read_edid()
  drm/bridge: lt8912b: use drm_bridge_read_edid()
  drm/bridge: lt8912b: clear the EDID property on failures
  drm/bridge: lt8912b: use ->edid_read callback
  drm/bridge: lt9611uxc: use drm_bridge_read_edid()
  drm: bridge: simple-bridge: use drm_bridge_edid_read()
  drm: bridge: simple-bridge: clear the EDID property on failures
  drm/bridge: tfp410: use drm_bridge_edid_read()
  drm/bridge: tfp410: clear the EDID property on failures
  drm/meson: switch to drm_bridge_edid_read()
  drm/bridge: remove drm_bridge_get_edid() in favour of
drm_bridge_edid_read()
  drm/bridge: anx7625: switch to ->edid_read callback
  drm/bridge: cdns-mhdp8546: switch to ->edid_read callback
  drm/bridge: cdns-mhdp8546: clear the EDID property on failures
  drm/bridge: display-connector: switch to ->edid_read callback
  drm/bridge: it6505: switch to ->edid_read callback
  drm: bridge: it66121: switch to ->edid_read callback
  drm/bridge: lt9611: switch to ->edid_read callback
  drm/bridge: lt9611uxc: switch to ->edid_read callback
  drm/bridge: megachips: switch to ->edid_read callback
  drm/bridge: nxp-ptn3460: switch to ->edid_read callback
  drm/bridge: sii902x: use display info is_hdmi
  drm/bridge: sii902x: switch to ->edid_read callback
  drm/mediatek/dp: switch to ->edid_read callback
  drm/mediatek/hdmi: switch to ->edid_read callback
  drm/msm/hdmi: fix indent
  drm/msm/hdmi: switch to ->edid_read callback
  drm/omap/hdmi4: switch to ->edid_read callback
  drm/omap/hdmi5: switch to ->edid_read callback
  drm: xlnx: zynqmp_dpsub: switch to ->edid_read callback
  drm: adv7511: switch to ->edid_read callback
  drm: bridge: dw_hdmi: switch to ->edid_read callback
  drm: bridge: dw_hdmi: clear the EDID property and CEC address on
failures
  drm/bridge: tc358767: update the EDID property
  drm/bridge: tc358767: switch to ->edid_read callback
  drm/bridge: ti-sn65dsi86: switch to ->edid_read callback
  drm/bridge: remove ->get_edid callback

 drivers/gpu/drm/bridge/adv7511/adv7511_drv.c  | 47 ---
 drivers/gpu/drm/bridge/analogix/anx7625.c | 30 
 .../drm/bridge/cadence/cdns-mhdp8546-core.c   | 28 ++-
 drivers/gpu/drm/bridge/chrontel-ch7033.c  | 12 ++---
 drivers/gpu/drm/bridge/display-connector.c|  8 ++--
 drivers/gpu/drm/bridge/ite-it6505.c   | 17 +++
 drivers/gpu/drm/bridge/ite-it66121.c  | 16 +++
 drivers/gpu/drm/bridge/lontium-lt8912b.c  | 20 
 drivers/gpu/drm/bridge/lontium-lt9611.c   |  8 ++--
 drivers/gpu/drm/bridge/lontium-lt9611uxc.c| 18 +++
 .../bridge/megachips-stdp-ge-b850v3-fw.c  | 18 +++
 drivers/gpu/drm/bridge/nxp-ptn3460.c  | 22 +
 drivers/gpu/drm/bridge/sii902x.c  | 38 +++
 drivers/gpu/drm/bridge/simple-bridge.c| 17 +++
 drivers/gpu/drm/bridge/synopsys/dw-hdmi.c | 43 ++---
 drivers/gpu/drm/bridge/tc358767.c | 17 +++
 drivers/gpu/drm/bridge/ti-sn65dsi86.c |  8 ++--
 drivers/gpu/drm/bridge/ti-tfp410.c| 18 +++
 drivers/gpu/drm/drm_bridge.c  | 17 +++
 drivers/gpu/drm/drm_bridge_connector.c| 16 +++
 drivers/gpu/drm/mediatek/mtk_dp.c | 31 +++-
 drivers/gpu/drm/mediatek/mtk_hdmi.c   | 26 ++
 drivers/gpu/drm/meson/meson_encoder_hdmi.c| 20 ++--
 drivers/gpu/drm/msm/hdmi/hdmi_bridge.c| 33 -
 drivers/gpu/drm/omapdrm/dss/hdmi4.c   | 22 ++---
 drivers/gpu/drm/omapdrm/dss/hdmi5.c   | 12 ++---
 drivers/gpu/drm/xlnx/zynqmp_dp.c  |  8 ++--
 include/drm/drm_bridge.h  | 25 +-
 28 files changed, 328 insertions(+), 267 deletions(-)

-- 
2.39.2



RE: Making drm_gpuvm work across gpu devices

2024-01-23 Thread Zeng, Oak
Thanks Christian. I have some comment inline below.

Danilo, can you also take a look and give your feedback? Thanks.

> -Original Message-
> From: Christian König 
> Sent: Tuesday, January 23, 2024 6:13 AM
> To: Zeng, Oak ; Danilo Krummrich ;
> Dave Airlie ; Daniel Vetter 
> Cc: Welty, Brian ; dri-devel@lists.freedesktop.org; 
> intel-
> x...@lists.freedesktop.org; Bommu, Krishnaiah ;
> Ghimiray, Himal Prasad ;
> thomas.hellst...@linux.intel.com; Vishwanathapura, Niranjana
> ; Brost, Matthew
> 
> Subject: Re: Making drm_gpuvm work across gpu devices
> 
> Hi Oak,
> 
> Am 23.01.24 um 04:21 schrieb Zeng, Oak:
> > Hi Danilo and all,
> >
> > During the work of Intel's SVM code, we came up the idea of making
> drm_gpuvm to work across multiple gpu devices. See some discussion here:
> https://lore.kernel.org/dri-
> devel/PH7PR11MB70049E7E6A2F40BF6282ECC292742@PH7PR11MB7004.namprd
> 11.prod.outlook.com/
> >
> > The reason we try to do this is, for a SVM (shared virtual memory across cpu
> program and all gpu program on all gpu devices) process, the address space has
> to be across all gpu devices. So if we make drm_gpuvm to work across devices,
> then our SVM code can leverage drm_gpuvm as well.
> >
> > At a first look, it seems feasible because drm_gpuvm doesn't really use the
> drm_device *drm pointer a lot. This param is used only for printing/warning. 
> So I
> think maybe we can delete this drm field from drm_gpuvm.
> >
> > This way, on a multiple gpu device system, for one process, we can have only
> one drm_gpuvm instance, instead of multiple drm_gpuvm instances (one for
> each gpu device).
> >
> > What do you think?
> 
> Well from the GPUVM side I don't think it would make much difference if
> we have the drm device or not.
> 
> But the experience we had with the KFD I think I should mention that we
> should absolutely *not* deal with multiple devices at the same time in
> the UAPI or VM objects inside the driver.
> 
> The background is that all the APIs inside the Linux kernel are build
> around the idea that they work with only one device at a time. This
> accounts for both low level APIs like the DMA API as well as pretty high
> level things like for example file system address space etc...

Yes most API are per device based.

One exception I know is actually the kfd SVM API. If you look at the svm_ioctl 
function, it is per-process based. Each kfd_process represent a process across 
N gpu devices. Cc Felix.

Need to say, kfd SVM represent a shared virtual address space across CPU and 
all GPU devices on the system. This is by the definition of SVM (shared virtual 
memory). This is very different from our legacy gpu *device* driver which works 
for only one device (i.e., if you want one device to access another device's 
memory, you will have to use dma-buf export/import etc).

We have the same design requirement of SVM. For anyone who want to implement 
the SVM concept, this is a hard requirement. Since now drm has the drm_gpuvm 
concept which strictly speaking is designed for one device, I want to see 
whether we can extend drm_gpuvm to make it work for both single device (as used 
in xe) and multipe devices (will be used in the SVM code). That is why I 
brought up this topic.

> 
> So when you have multiple GPUs you either have an inseparable cluster of
> them which case you would also only have one drm_device. Or you have
> separated drm_device which also results in separate drm render nodes and
> separate virtual address spaces and also eventually separate IOMMU
> domains which gives you separate dma_addresses for the same page and so
> separate GPUVM page tables

I am thinking we can still make each device has its separate drm_device/render 
node/iommu domains/gpu page table. Just as what we have today. I am not plan to 
change this picture.

But the virtual address space will support two modes of operation: 
1. one drm_gpuvm per device. This is when svm is not in the picture
2. all devices in the process share one single drm_gpuvm, when svm is in the 
picture. In xe driver design, we have to support a mixture use of legacy mode 
(such as gem_create and vm_bind) and svm (such as malloc'ed memory for gpu 
submission). So whenever SVM is in the picture, we want one single process 
address space across all devices. Drm_gpuvm doesn't need to be aware of those 
two operation modes. It is driver's responsibility to use different mode. 

For example, in mode #1, a driver's vm structure (such as xe_vm) can inherit 
from drm_gpuvm. In mode #2, a driver's svm structure (xe_svm in this series: 
https://lore.kernel.org/dri-devel/20240117221223.18540-1-oak.z...@intel.com/) 
can inherit from drm_gpuvm while each xe_vm (still a per-device based struct) 
will just have a pointer to the drm_gpuvm structure. This way when svm is in 
play, we build a 1 process:1 mm_struct:1 xe_svm:N xe_vm correlations which 
means shared address space across gpu devices.

This requires some changes of drm_gpuvm design:

Re: [PATCH] Revert "drivers/firmware: Move sysfb_init() from device_initcall to subsys_initcall_sync"

2024-01-23 Thread Jani Nikula
On Tue, 23 Jan 2024, Jani Nikula  wrote:
> On Tue, 23 Jan 2024, Thomas Zimmermann  wrote:
>> This reverts commit 60aebc9559492cea6a9625f514a8041717e3a2e4.
>>
>> Commit 60aebc9559492cea ("drivers/firmware: Move sysfb_init() from
>> device_initcall to subsys_initcall_sync") messes up initialization order
>> of the graphics drivers and leads to blank displays on some systems. So
>> revert the commit.
>>
>> To make the display drivers fully independent from initialization
>> order requires to track framebuffer memory by device and independently
>> from the loaded drivers. The kernel currently lacks the infrastructure
>> to do so.
>>
>> Reported-by: Jaak Ristioja 
>> Closes: 
>> https://lore.kernel.org/dri-devel/ZUnNi3q3yB3zZfTl@P70.localdomain/T/#t
>> Reported-by: Huacai Chen 
>> Closes: 
>> https://lore.kernel.org/dri-devel/20231108024613.2898921-1-chenhua...@loongson.cn/
>> Closes: https://gitlab.freedesktop.org/drm/intel/-/issues/10133
>
> FWIW,
>
> Acked-by: Jani Nikula 
>
> but would be great to get a Tested-by from Jaak or from the gitlab issue
> reporter.

The revert works for the gitlab issue reporter.

BR,
Jani.



-- 
Jani Nikula, Intel


Re: [PATCH] drm: apple: mark local functions static

2024-01-23 Thread Janne Grunau
Hej Arnd,

On Tue, Jan 23, 2024, at 08:34, Arnd Bergmann wrote:
> On Mon, Jan 22, 2024, at 21:50, Janne Grunau wrote:
>> On Wed, Jan 17, 2024, at 11:44, Arnd Bergmann wrote:
>>> 
>>> -int parse_sample_rate_bit(struct dcp_parse_ctx *handle, unsigned int 
>>> *ratebit)
>>> +static int parse_sample_rate_bit(struct dcp_parse_ctx *handle, 
>>> unsigned int *ratebit)
>>>  {
>>> s64 rate;
>>> int ret = parse_int(handle, );
>>> @@ -715,7 +715,7 @@ int parse_sample_rate_bit(struct dcp_parse_ctx 
>>> *handle, unsigned int *ratebit)
>>> return 0;
>>>  }
>>> 
>>> -int parse_sample_fmtbit(struct dcp_parse_ctx *handle, u64 *fmtbit)
>>> +static int parse_sample_fmtbit(struct dcp_parse_ctx *handle, u64 *fmtbit)
>>>  {
>>> s64 sample_size;
>>> int ret = parse_int(handle, _size);
>>
>> thanks, patch included in my dev branch and will be in the next pull 
>> request I'll send to Hector.
>>
>> I suppose the recipients are generated by an automated 
>> get_maintainers.pl invocation. Is that desired for out of tree drivers?
>
> I was wondering about that as well, as I don't usually send
> patches for code that isn't at least in linux-next yet.
>
> I ended up using what is in the MAINTAINERS file for this driver
> in the branch as that is is all I have at this point:
>
> APPLE DRM DISPLAY DRIVER
> M:  Alyssa Rosenzweig 
> L:  dri-devel@lists.freedesktop.org
> S:  Maintained
> T:  git git://anongit.freedesktop.org/drm/drm-misc
> F:  drivers/gpu/drm/apple/
>
> I left out the drivers/gpu/ maintainer addresses though.

oops, answered to the wrong patch. The strscpy one has the drivers/gpu/ 
maintainers and the question. I replied here first assuming it has the same 
recipient list. I'd consider the recipients for this mail reasonable.

Janne


[PATCH RESEND] drm/virtio: set segment size for virtio_gpu device

2024-01-23 Thread Sebastian Ott

Hej,

debug dma code is not happy with virtio gpu (arm64 VM):

[  305.881733] [ cut here ]
[  305.883117] DMA-API: virtio-pci :07:00.0: mapping sg segment longer than 
device claims to support [len=262144] [max=65536]
[  305.885976] WARNING: CPU: 8 PID: 2002 at kernel/dma/debug.c:1177 
check_sg_segment+0x2d0/0x420
[  305.888038] Modules linked in: crct10dif_ce(+) polyval_ce polyval_generic 
ghash_ce virtio_gpu(+) virtio_net net_failover virtio_blk(+) virtio_dma_buf 
virtio_console failover virtio_mmio scsi_dh_r dac scsi_dh_emc scsi_dh_alua 
dm_multipath qemu_fw_cfg
[  305.893496] CPU: 8 PID: 2002 Comm: (udev-worker) Not tainted 6.7.0 #1
[  305.895070] Hardware name: QEMU KVM Virtual Machine, BIOS 
edk2-20230524-3.fc37 05/24/2023
[  305.897112] pstate: 6045 (nZCv daif +PAN -UAO -TCO -DIT -SSBS BTYPE=--)
[  305.897129] pc : check_sg_segment+0x2d0/0x420
[  305.897139] lr : check_sg_segment+0x2d0/0x420
[  305.897145] sp : 80008ffc69d0
[  305.897149] x29: 80008ffc69d0 x28: dfff8000 x27: b0232879e578
[  305.897167] x26:  x25: b0232778c060 x24: 19ee9b2060c0
[  305.897181] x23:  x22: b0232ab9ce10 x21: 19eece5c64ac
[  305.906942] x20: 0001 x19: 19eece5c64a0 x18: 19eec36fc304
[  305.908633] x17: 6e61687420726567 x16: 6e6f6c20746e656d x15: 6765732067732067
[  305.910352] x14: f1f1f1f1 x13: 0001 x12: 700011ff8cc3
[  305.912044] x11: 100011ff8cc2 x10: 700011ff8cc2 x9 : b02324a70e54
[  305.913751] x8 : 8fffee00733e x7 : 80008ffc6617 x6 : 0001
[  305.915451] x5 : 80008ffc6610 x4 : 1fffe33e70564622 x3 : dfff8000
[  305.917158] x2 :  x1 :  x0 : 19f382b23100
[  305.918864] Call trace:
[  305.919474]  check_sg_segment+0x2d0/0x420
[  305.920443]  debug_dma_map_sg+0x2a0/0x428
[  305.921402]  __dma_map_sg_attrs+0xf4/0x1a8
[  305.922388]  dma_map_sgtable+0x7c/0x100
[  305.923318]  drm_gem_shmem_get_pages_sgt+0x15c/0x328
[  305.924500]  virtio_gpu_object_shmem_init.constprop.0.isra.0+0x50/0x628 
[virtio_gpu]
[  305.926390]  virtio_gpu_object_create+0x198/0x478 [virtio_gpu]
[  305.927802]  virtio_gpu_mode_dumb_create+0x2a0/0x4c8 [virtio_gpu]
[  305.929272]  drm_mode_create_dumb+0x1c0/0x280
[  305.930327]  drm_client_framebuffer_create+0x140/0x328
[  305.931555]  drm_fbdev_generic_helper_fb_probe+0x1bc/0x5c0
[  305.932871]  __drm_fb_helper_initial_config_and_unlock+0x1e0/0x630
[  305.934372]  drm_fb_helper_initial_config+0x50/0x68
[  305.935540]  drm_fbdev_generic_client_hotplug+0x148/0x200
[  305.936819]  drm_client_register+0x130/0x200
[  305.937856]  drm_fbdev_generic_setup+0xe8/0x320
[  305.938932]  virtio_gpu_probe+0x13c/0x2d0 [virtio_gpu]
[  305.940190]  virtio_dev_probe+0x38c/0x600
[  305.941153]  really_probe+0x334/0x9c8
[  305.942047]  __driver_probe_device+0x164/0x3d8
[  305.943102]  driver_probe_device+0x64/0x180
[  305.944094]  __driver_attach+0x1d4/0x488
[  305.945045]  bus_for_each_dev+0x104/0x198
[  305.946008]  driver_attach+0x44/0x68
[  305.946892]  bus_add_driver+0x23c/0x4a8
[  305.947838]  driver_register+0xf8/0x3d0
[  305.948770]  register_virtio_driver+0x74/0xc8
[  305.949836]  virtio_gpu_driver_init+0x20/0xff8 [virtio_gpu]
[  305.951237]  do_one_initcall+0x17c/0x8c0
[  305.952182]  do_init_module+0x1dc/0x630
[  305.953106]  load_module+0x10c0/0x1638
[  305.954012]  init_module_from_file+0xe0/0x140
[  305.955058]  idempotent_init_module+0x2c0/0x590
[  305.956174]  __arm64_sys_finit_module+0xb4/0x140
[  305.957282]  invoke_syscall+0xd8/0x258
[  305.958187]  el0_svc_common.constprop.0+0x16c/0x240
[  305.959526]  do_el0_svc+0x48/0x68
[  305.960456]  el0_svc+0x58/0x118
[  305.961310]  el0t_64_sync_handler+0x120/0x130
[  305.962510]  el0t_64_sync+0x194/0x198
[  305.963509] irq event stamp: 37944
[  305.964412] hardirqs last  enabled at (37943): [] 
console_unlock+0x1a4/0x1c8
[  305.966602] hardirqs last disabled at (37944): [] 
el1_dbg+0x24/0xa0
[  305.968535] softirqs last  enabled at (37930): [] 
__do_softirq+0x8e4/0xe1c
[  305.970781] softirqs last disabled at (37925): [] 
do_softirq+0x18/0x30
[  305.972937] ---[ end trace  ]---

The 64K max_segment size of the device seems to be inherited by PCIs default.
The sg list is crated via this drm helper:

struct sg_table *drm_prime_pages_to_sg(struct drm_device *dev,
   struct page **pages, unsigned int 
nr_pages)
{
...
if (dev)
max_segment = dma_max_mapping_size(dev->dev);
if (max_segment == 0)
max_segment = UINT_MAX;
err = sg_alloc_table_from_pages_segment(sg, pages, nr_pages, 0,
nr_pages << PAGE_SHIFT,
max_segment, GFP_KERNEL);
...
}

I'm a bit puzzled why this uses dma_max_mapping_size() and not
dma_get_max_seg_size(). But since this is 

Re: [PATCH v2 2/2] drm/amdgpu: Implement check_async_props for planes

2024-01-23 Thread Xaver Hugl
Am Mo., 22. Jan. 2024 um 16:50 Uhr schrieb Harry Wentland
:
>
>
>
> On 2024-01-19 13:25, Ville Syrjälä wrote:
> > On Fri, Jan 19, 2024 at 03:12:35PM -0300, André Almeida wrote:
> >> AMD GPUs can do async flips with changes on more properties than just
> >> the FB ID, so implement a custom check_async_props for AMD planes.
> >>
> >> Allow amdgpu to do async flips with IN_FENCE_ID and FB_DAMAGE_CLIPS
> >> properties. For userspace to check if a driver support this two
> >> properties, the strategy for now is to use TEST_ONLY commits.
> >>
> >> Signed-off-by: André Almeida 
> >> ---
> >> v2: Drop overlay plane option for now
> >>
> >>   .../amd/display/amdgpu_dm/amdgpu_dm_plane.c   | 29 +++
> >>   1 file changed, 29 insertions(+)
> >>
> >> diff --git a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_plane.c 
> >> b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_plane.c
> >> index 116121e647ca..7afe8c1b62d4 100644
> >> --- a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_plane.c
> >> +++ b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_plane.c
> >> @@ -25,6 +25,7 @@
> >>*/
> >>
> >>   #include 
> >> +#include 
> >>   #include 
> >>   #include 
> >>   #include 
> >> @@ -1430,6 +1431,33 @@ static void 
> >> amdgpu_dm_plane_drm_plane_destroy_state(struct drm_plane *plane,
> >>  drm_atomic_helper_plane_destroy_state(plane, state);
> >>   }
> >>
> >> +static int amdgpu_dm_plane_check_async_props(struct drm_property *prop,
> >> +  struct drm_plane *plane,
> >> +  struct drm_plane_state *plane_state,
> >> +  struct drm_mode_object *obj,
> >> +  u64 prop_value, u64 old_val)
> >> +{
> >> +struct drm_mode_config *config = >dev->mode_config;
> >> +int ret;
> >> +
> >> +if (prop != config->prop_fb_id &&
> >> +prop != config->prop_in_fence_fd &&
> >
> > IN_FENCE should just be allowed always.
> >
> >> +prop != config->prop_fb_damage_clips) {
> >
> > This seems a bit dubious to me. How is amdgpu using the damage
> > information during async flips?
>
> Yeah, I'm also not sure this is right. Has anyone tested this
> with a PSR SU panel?
>
> Harry

I attempted to, but according to
/sys/kernel/debug/dri/1/eDP-1/psr_state, PSR never kicks in on my
laptop at all. The only reason I wanted this property though is to
reduce the number of special cases for async pageflips compositors
have to implement; as it's not necessary for any functionality I think
it's also fine to leave it out.

> >> +ret = drm_atomic_plane_get_property(plane, plane_state,
> >> +prop, _val);
> >> +return drm_atomic_check_prop_changes(ret, old_val, 
> >> prop_value, prop);
> >> +}
> >> +
> >> +if (plane_state->plane->type != DRM_PLANE_TYPE_PRIMARY) {
> >> +drm_dbg_atomic(prop->dev,
> >> +   "[OBJECT:%d] Only primary planes can be 
> >> changed during async flip\n",
> >> +   obj->id);
> >> +return -EINVAL;
> >> +}
> >> +
> >> +return 0;
> >> +}
> >> +
> >>   static const struct drm_plane_funcs dm_plane_funcs = {
> >>  .update_plane   = drm_atomic_helper_update_plane,
> >>  .disable_plane  = drm_atomic_helper_disable_plane,
> >> @@ -1438,6 +1466,7 @@ static const struct drm_plane_funcs dm_plane_funcs = 
> >> {
> >>  .atomic_duplicate_state = amdgpu_dm_plane_drm_plane_duplicate_state,
> >>  .atomic_destroy_state = amdgpu_dm_plane_drm_plane_destroy_state,
> >>  .format_mod_supported = amdgpu_dm_plane_format_mod_supported,
> >> +.check_async_props = amdgpu_dm_plane_check_async_props,
> >>   };
> >>
> >>   int amdgpu_dm_plane_init(struct amdgpu_display_manager *dm,
> >> --
> >> 2.43.0
> >


Re: [RFC] Revert "drm/sched: Split free_job into own work item"

2024-01-23 Thread Mario Limonciello

On 1/22/2024 20:11, Mario Limonciello wrote:

commit f7fe64ad0f22 ("drm/sched: Split free_job into own work item")
causes graphics hangs at GDM or right after logging in on a
Framework 13 AMD laptop (containing a Phoenix APU).

This reverts commit f7fe64ad0f22ff034f8ebcfbd7299ee9cc9b57d7.

Fixes: f7fe64ad0f22 ("drm/sched: Split free_job into own work item")
Signed-off-by: Mario Limonciello 
---
This is a regression introduced in 6.8-rc1, bisected from 6.7.
This revert done on top of 6.8-rc1 fixes the issue.

I'm happy to gather any data to use to properly debug if that is
preferable to a revert.


BTW - nothing in kernel log when this happens.
I did catch an ftrace with all the GPU scheduler trace events though:

https://gist.github.com/superm1/1d3fc752a414f324fbde526052573acd


---
  drivers/gpu/drm/scheduler/sched_main.c | 133 +
  include/drm/gpu_scheduler.h|   4 +-
  2 files changed, 48 insertions(+), 89 deletions(-)

diff --git a/drivers/gpu/drm/scheduler/sched_main.c 
b/drivers/gpu/drm/scheduler/sched_main.c
index 550492a7a031..91c96ab53fb5 100644
--- a/drivers/gpu/drm/scheduler/sched_main.c
+++ b/drivers/gpu/drm/scheduler/sched_main.c
@@ -369,32 +369,6 @@ static void drm_sched_run_job_queue(struct 
drm_gpu_scheduler *sched)
queue_work(sched->submit_wq, >work_run_job);
  }
  
-/**

- * __drm_sched_run_free_queue - enqueue free-job work
- * @sched: scheduler instance
- */
-static void __drm_sched_run_free_queue(struct drm_gpu_scheduler *sched)
-{
-   if (!READ_ONCE(sched->pause_submit))
-   queue_work(sched->submit_wq, >work_free_job);
-}
-
-/**
- * drm_sched_run_free_queue - enqueue free-job work if ready
- * @sched: scheduler instance
- */
-static void drm_sched_run_free_queue(struct drm_gpu_scheduler *sched)
-{
-   struct drm_sched_job *job;
-
-   spin_lock(>job_list_lock);
-   job = list_first_entry_or_null(>pending_list,
-  struct drm_sched_job, list);
-   if (job && dma_fence_is_signaled(>s_fence->finished))
-   __drm_sched_run_free_queue(sched);
-   spin_unlock(>job_list_lock);
-}
-
  /**
   * drm_sched_job_done - complete a job
   * @s_job: pointer to the job which is done
@@ -414,7 +388,7 @@ static void drm_sched_job_done(struct drm_sched_job *s_job, 
int result)
dma_fence_get(_fence->finished);
drm_sched_fence_finished(s_fence, result);
dma_fence_put(_fence->finished);
-   __drm_sched_run_free_queue(sched);
+   drm_sched_run_job_queue(sched);
  }
  
  /**

@@ -1092,10 +1066,8 @@ drm_sched_get_finished_job(struct drm_gpu_scheduler 
*sched)
typeof(*next), list);
  
  		if (next) {

-   if (test_bit(DMA_FENCE_FLAG_TIMESTAMP_BIT,
->s_fence->scheduled.flags))
-   next->s_fence->scheduled.timestamp =
-   
dma_fence_timestamp(>s_fence->finished);
+   next->s_fence->scheduled.timestamp =
+   dma_fence_timestamp(>s_fence->finished);
/* start TO timer for next job */
drm_sched_start_timeout(sched);
}
@@ -1145,29 +1117,7 @@ drm_sched_pick_best(struct drm_gpu_scheduler 
**sched_list,
  EXPORT_SYMBOL(drm_sched_pick_best);
  
  /**

- * drm_sched_free_job_work - worker to call free_job
- *
- * @w: free job work
- */
-static void drm_sched_free_job_work(struct work_struct *w)
-{
-   struct drm_gpu_scheduler *sched =
-   container_of(w, struct drm_gpu_scheduler, work_free_job);
-   struct drm_sched_job *job;
-
-   if (READ_ONCE(sched->pause_submit))
-   return;
-
-   job = drm_sched_get_finished_job(sched);
-   if (job)
-   sched->ops->free_job(job);
-
-   drm_sched_run_free_queue(sched);
-   drm_sched_run_job_queue(sched);
-}
-
-/**
- * drm_sched_run_job_work - worker to call run_job
+ * drm_sched_run_job_work - main scheduler thread
   *
   * @w: run job work
   */
@@ -1176,50 +1126,64 @@ static void drm_sched_run_job_work(struct work_struct 
*w)
struct drm_gpu_scheduler *sched =
container_of(w, struct drm_gpu_scheduler, work_run_job);
struct drm_sched_entity *entity;
-   struct dma_fence *fence;
-   struct drm_sched_fence *s_fence;
-   struct drm_sched_job *sched_job;
+   struct drm_sched_job *cleanup_job;
int r;
  
  	if (READ_ONCE(sched->pause_submit))

return;
  
+	cleanup_job = drm_sched_get_finished_job(sched);

entity = drm_sched_select_entity(sched);
-   if (!entity)
-   return;
  
-	sched_job = drm_sched_entity_pop_job(entity);

-   if (!sched_job) {
-   complete_all(>entity_idle);
+   if (!entity && !cleanup_job)
return; /* No more work */
-   }
  
-	s_fence 

fb_defio and page->mapping

2024-01-23 Thread Matthew Wilcox
We're currently trying to remove page->mapping from the entire kernel.
This has me interested in fb_defio and since I made such a mess of it
with commits ccf953d8f3d6 / 0b78f8bcf495, I'd like to discuss what to
do before diving in.

Folios continue to have a mapping.  So we can effectively do
page_folio(page)->mapping (today that's calling compound_head() to get
to the head page; eventually it's a separate allocation).

But now I look at commit 56c134f7f1b5, I'm a little scared.
Apparently pages are being allocated from shmem and being mapped by
fb_deferred_io_fault()?  This line:

page->mapping = vmf->vma->vm_file->f_mapping;

initially appears harmless for shmem files (because that's presumably
a noop), but it's only a noop for head pages.  If shmem allocates a
compound page (ie a 2MB THP today), you'll overlay some information
stored in the second and third pages; looks like _entire_mapcount
and _deferred_list.prev (but we do shift those fields around without
regard to what the fb_defio driver is doing).  Even if you've disabled
THP today, setting page->mapping to NULL in fb_deferred_io_lastclose()
for a shmem page is a really bad idea.

I'd like to avoid fb_defio playing with page->mapping at all.
As I understand it, the only reason to set page->mapping is so that
page_mkclean() works.  But there are all kinds of assumptions in
page_mkclean() (now essentially folio_mkclean()) that we're dealing with
file-backed or anonymous memory.  I wonder if we might be better off
calling pfn_mkclean_range() for each VMA which maps these allocations?
You'd have to keep track of each VMA yourself (I think?)  but it would
avoid messing with page->mapping.

Anyway, I don't know enough about DRM.  There might be something
unutterably obvious we could do to fix this.


  1   2   >