RE: [PATCH v2 2/2] vfio: Replace the iommu notifier with a device list

2022-06-07 Thread Tian, Kevin
> From: Jason Gunthorpe
> Sent: Wednesday, June 8, 2022 7:02 AM
> 
> Instead of bouncing the function call to the driver op through a blocking
> notifier just have the iommu layer call it directly.
> 
> Register each device that is being attached to the iommu with the lower
> driver which then threads them on a linked list and calls the appropriate
> driver op at the right time.
> 
> Currently the only use is if dma_unmap() is defined.
> 
> Also, fully lock all the debugging tests on the pinning path that a
> dma_unmap is registered.
>
... 
> Signed-off-by: Jason Gunthorpe 
> diff --git a/drivers/vfio/vfio_iommu_type1.c
> b/drivers/vfio/vfio_iommu_type1.c
> index c13b9290e35759..4ddb1f1abd238b 100644
> --- a/drivers/vfio/vfio_iommu_type1.c
> +++ b/drivers/vfio/vfio_iommu_type1.c
> @@ -67,7 +67,8 @@ struct vfio_iommu {
>   struct list_headiova_list;
>   struct mutexlock;
>   struct rb_root  dma_list;
> - struct blocking_notifier_head notifier;
> + struct list_headdevice_list;
> + struct mutexdevice_list_lock;

emulated_device_list or unmap_device_list, to be more accurate?

btw a few lines downward there is already a emulated_iommu_groups.
the two sounds a bit overlapping given mdev's iommu group is faked
and singleton. Wonder whether it's cleaner to just reuse the existing field...


RE: [PATCH v2 1/2] vfio: Replace the DMA unmapping notifier with a callback

2022-06-07 Thread Tian, Kevin
> From: Jason Gunthorpe
> Sent: Wednesday, June 8, 2022 7:02 AM
> 
> Instead of having drivers register the notifier with explicit code just
> have them provide a dma_unmap callback op in their driver ops and rely on
> the core code to wire it up.
> 
> Suggested-by: Christoph Hellwig 
> Reviewed-by: Christoph Hellwig 
> Signed-off-by: Jason Gunthorpe 

Reviewed-by: Kevin Tian 

> ---
>  drivers/gpu/drm/i915/gvt/gvt.h|   1 -
>  drivers/gpu/drm/i915/gvt/kvmgt.c  |  75 ---
>  drivers/s390/cio/vfio_ccw_ops.c   |  41 ++---
>  drivers/s390/cio/vfio_ccw_private.h   |   1 -
>  drivers/s390/crypto/vfio_ap_ops.c |  53 ++-
>  drivers/s390/crypto/vfio_ap_private.h |   3 -
>  drivers/vfio/vfio.c   | 126 +-
>  drivers/vfio/vfio.h   |   5 +
>  include/linux/vfio.h  |  21 +
>  9 files changed, 87 insertions(+), 239 deletions(-)
> 
> diff --git a/drivers/gpu/drm/i915/gvt/gvt.h b/drivers/gpu/drm/i915/gvt/gvt.h
> index aee1a45da74bcb..705689e6401197 100644
> --- a/drivers/gpu/drm/i915/gvt/gvt.h
> +++ b/drivers/gpu/drm/i915/gvt/gvt.h
> @@ -226,7 +226,6 @@ struct intel_vgpu {
>   unsigned long nr_cache_entries;
>   struct mutex cache_lock;
> 
> - struct notifier_block iommu_notifier;
>   atomic_t released;
> 
>   struct kvm_page_track_notifier_node track_node;
> diff --git a/drivers/gpu/drm/i915/gvt/kvmgt.c
> b/drivers/gpu/drm/i915/gvt/kvmgt.c
> index e2f6c56ab3420c..ecd5bb37b63a2a 100644
> --- a/drivers/gpu/drm/i915/gvt/kvmgt.c
> +++ b/drivers/gpu/drm/i915/gvt/kvmgt.c
> @@ -729,34 +729,25 @@ int intel_gvt_set_edid(struct intel_vgpu *vgpu, int
> port_num)
>   return ret;
>  }
> 
> -static int intel_vgpu_iommu_notifier(struct notifier_block *nb,
> -  unsigned long action, void *data)
> +static void intel_vgpu_dma_unmap(struct vfio_device *vfio_dev, u64 iova,
> +  u64 length)
>  {
> - struct intel_vgpu *vgpu =
> - container_of(nb, struct intel_vgpu, iommu_notifier);
> -
> - if (action == VFIO_IOMMU_NOTIFY_DMA_UNMAP) {
> - struct vfio_iommu_type1_dma_unmap *unmap = data;
> - struct gvt_dma *entry;
> - unsigned long iov_pfn, end_iov_pfn;
> + struct intel_vgpu *vgpu = vfio_dev_to_vgpu(vfio_dev);
> + struct gvt_dma *entry;
> + u64 iov_pfn = iova >> PAGE_SHIFT;
> + u64 end_iov_pfn = iov_pfn + length / PAGE_SIZE;
> 
> - iov_pfn = unmap->iova >> PAGE_SHIFT;
> - end_iov_pfn = iov_pfn + unmap->size / PAGE_SIZE;
> + mutex_lock(>cache_lock);
> + for (; iov_pfn < end_iov_pfn; iov_pfn++) {
> + entry = __gvt_cache_find_gfn(vgpu, iov_pfn);
> + if (!entry)
> + continue;
> 
> - mutex_lock(>cache_lock);
> - for (; iov_pfn < end_iov_pfn; iov_pfn++) {
> - entry = __gvt_cache_find_gfn(vgpu, iov_pfn);
> - if (!entry)
> - continue;
> -
> - gvt_dma_unmap_page(vgpu, entry->gfn, entry-
> >dma_addr,
> -entry->size);
> - __gvt_cache_remove_entry(vgpu, entry);
> - }
> - mutex_unlock(>cache_lock);
> + gvt_dma_unmap_page(vgpu, entry->gfn, entry->dma_addr,
> +entry->size);
> + __gvt_cache_remove_entry(vgpu, entry);
>   }
> -
> - return NOTIFY_OK;
> + mutex_unlock(>cache_lock);
>  }
> 
>  static bool __kvmgt_vgpu_exist(struct intel_vgpu *vgpu)
> @@ -783,36 +774,20 @@ static bool __kvmgt_vgpu_exist(struct intel_vgpu
> *vgpu)
>  static int intel_vgpu_open_device(struct vfio_device *vfio_dev)
>  {
>   struct intel_vgpu *vgpu = vfio_dev_to_vgpu(vfio_dev);
> - unsigned long events;
> - int ret;
> -
> - vgpu->iommu_notifier.notifier_call = intel_vgpu_iommu_notifier;
> 
> - events = VFIO_IOMMU_NOTIFY_DMA_UNMAP;
> - ret = vfio_register_notifier(vfio_dev, VFIO_IOMMU_NOTIFY, ,
> -  >iommu_notifier);
> - if (ret != 0) {
> - gvt_vgpu_err("vfio_register_notifier for iommu failed: %d\n",
> - ret);
> - goto out;
> - }
> -
> - ret = -EEXIST;
>   if (vgpu->attached)
> - goto undo_iommu;
> + return -EEXIST;
> 
> - ret = -ESRCH;
>   if (!vgpu->vfio_device.kvm ||
>   vgpu->vfio_device.kvm->mm != current->mm) {
>   gvt_vgpu_err("KVM is required to use Intel vGPU\n");
> - goto undo_iommu;
> + return -ESRCH;
>   }
> 
>   kvm_get_kvm(vgpu->vfio_device.kvm);
> 
> - ret = -EEXIST;
>   if (__kvmgt_vgpu_exist(vgpu))
> - goto undo_iommu;
> + return -EEXIST;
> 
>   vgpu->attached = true;
> 
> @@ -831,12 +806,6 @@ static int intel_vgpu_open_device(struct 

[PATCH] drm/panel-edp: Add LQ140M1JW48 edp panel entry

2022-06-07 Thread Bjorn Andersson
Add panel identification entry for the Sharp LQ140M1JW48 eDP panel.

Due to lacking documentation, a delay similar to those for the
LQ140M1JW46 numbers are picked for now.

Signed-off-by: Bjorn Andersson 
---
 drivers/gpu/drm/panel/panel-edp.c | 1 +
 1 file changed, 1 insertion(+)

diff --git a/drivers/gpu/drm/panel/panel-edp.c 
b/drivers/gpu/drm/panel/panel-edp.c
index c96014464355..fe3897b86665 100644
--- a/drivers/gpu/drm/panel/panel-edp.c
+++ b/drivers/gpu/drm/panel/panel-edp.c
@@ -1860,6 +1860,7 @@ static const struct edp_panel_entry edp_panels[] = {
EDP_PANEL_ENTRY('K', 'D', 'B', 0x0624, 
_kd116n21_30nv_a010.delay, "116N21-30NV-A010"),
EDP_PANEL_ENTRY('K', 'D', 'B', 0x1120, _200_500_e80_d50, 
"116N29-30NK-C007"),
 
+   EDP_PANEL_ENTRY('S', 'H', 'P', 0x1511, _200_500_e50, 
"LQ140M1JW48"),
EDP_PANEL_ENTRY('S', 'H', 'P', 0x1523, _lq140m1jw46.delay, 
"LQ140M1JW46"),
EDP_PANEL_ENTRY('S', 'H', 'P', 0x154c, _200_500_p2e100, 
"LQ116M1JW10"),
 
-- 
2.35.1



[RFC 3/3] drm/amd/display: Introduce KUnit tests to the bw_fixed library

2022-06-07 Thread Maíra Canal
From: Magali Lemes 

The bw_fixed library performs a lot of the mathematical operations
involving fixed-point arithmetic and the conversion of integers to
fixed-point representation.

As fixed-point representation is the base foundation of the DML calcs
operations, this unit tests intend to assure the proper functioning of
the basic mathematical operations of fixed-point arithmetic, such as
multiplication, conversion from fractional to fixed-point number, and more.

Co-developed-by: Tales Aparecida 
Signed-off-by: Tales Aparecida 
Signed-off-by: Magali Lemes 
Co-developed-by: Maíra Canal 
Signed-off-by: Maíra Canal 
---
 .../drm/amd/display/amdgpu_dm/tests/Kconfig   |  12 +
 .../drm/amd/display/amdgpu_dm/tests/Makefile  |   4 +
 .../amdgpu_dm/tests/calcs/bw_fixed_test.c | 322 ++
 .../amd/display/amdgpu_dm/tests/dml_test.c|   3 +
 .../amd/display/amdgpu_dm/tests/dml_test.h|   8 +
 5 files changed, 349 insertions(+)
 create mode 100644 
drivers/gpu/drm/amd/display/amdgpu_dm/tests/calcs/bw_fixed_test.c

diff --git a/drivers/gpu/drm/amd/display/amdgpu_dm/tests/Kconfig 
b/drivers/gpu/drm/amd/display/amdgpu_dm/tests/Kconfig
index bd1d971d4452..540b2f79f971 100644
--- a/drivers/gpu/drm/amd/display/amdgpu_dm/tests/Kconfig
+++ b/drivers/gpu/drm/amd/display/amdgpu_dm/tests/Kconfig
@@ -2,6 +2,18 @@
 menu "DML Unit Tests"
depends on DRM_AMD_DC && KUNIT=m
 
+config BW_FIXED_KUNIT_TEST
+   bool "Enable unit tests for dml/calcs/bw_fixed" if !DML_KUNIT_TEST
+   default y if DML_KUNIT_TEST
+   help
+   Enables unit tests for the dml/calcs/bw_fixed. Only useful for 
kernel
+   devs running KUnit.
+
+   For more information on KUnit and unit tests in general please 
refer to
+   the KUnit documentation in Documentation/dev-tools/kunit/.
+
+   If unsure, say N.
+
 config DISPLAY_MODE_LIB_KUNIT_TEST
bool "Enable unit tests for dml/display_mode_lib" if !DML_KUNIT_TEST
default y if DML_KUNIT_TEST
diff --git a/drivers/gpu/drm/amd/display/amdgpu_dm/tests/Makefile 
b/drivers/gpu/drm/amd/display/amdgpu_dm/tests/Makefile
index 53b38e340564..23109e51cf32 100644
--- a/drivers/gpu/drm/amd/display/amdgpu_dm/tests/Makefile
+++ b/drivers/gpu/drm/amd/display/amdgpu_dm/tests/Makefile
@@ -5,6 +5,10 @@
 
 DML_TESTS = dml_test.o
 
+ifdef CONFIG_BW_FIXED_KUNIT_TEST
+DML_TESTS += calcs/bw_fixed_test.o
+endif
+
 ifdef CONFIG_DISPLAY_MODE_LIB_KUNIT_TEST
 DML_TESTS += display_mode_lib_test.o
 endif
diff --git a/drivers/gpu/drm/amd/display/amdgpu_dm/tests/calcs/bw_fixed_test.c 
b/drivers/gpu/drm/amd/display/amdgpu_dm/tests/calcs/bw_fixed_test.c
new file mode 100644
index ..344c1517745e
--- /dev/null
+++ b/drivers/gpu/drm/amd/display/amdgpu_dm/tests/calcs/bw_fixed_test.c
@@ -0,0 +1,322 @@
+// SPDX-License-Identifier: MIT
+/*
+ * KUnit tests for dml/calcs/bw_fixed.h
+ *
+ * Copyright (C) 2022, Magali Lemes 
+ * Copyright (C) 2022, Maíra Canal 
+ * Copyright (C) 2022, Tales Aparecida 
+ */
+
+#include 
+#include "../../../dc/inc/bw_fixed.h"
+#include "../dml_test.h"
+
+/**
+ * DOC: Unit tests for AMDGPU DML calcs/bw_fixed.h
+ *
+ * bw_fixed.h performs a lot of the mathematical operations involving
+ * fixed-point arithmetic and the conversion of integers to fixed-point
+ * representation.
+ *
+ * As fixed-point representation is the base foundation of the DML calcs
+ * operations, these tests intend to assure the proper functioning of the
+ * basic mathematical operations of fixed-point arithmetic, such as
+ * multiplication, conversion from fractional to fixed-point number, and more.
+ *
+ */
+
+static void abs_i64_test(struct kunit *test)
+{
+   KUNIT_EXPECT_EQ(test, 0ULL, abs_i64(0LL));
+
+   /* Argument type limits */
+   KUNIT_EXPECT_EQ(test, (uint64_t)MAX_I64, abs_i64(MAX_I64));
+   KUNIT_EXPECT_EQ(test, (uint64_t)MAX_I64 + 1, abs_i64(MIN_I64));
+}
+
+static void bw_int_to_fixed_nonconst_test(struct kunit *test)
+{
+   struct bw_fixed res;
+
+   /* Add BW_FIXED_BITS_PER_FRACTIONAL_PART trailing 0s to binary number */
+   res = bw_int_to_fixed_nonconst(1000);  /* 0x3E8 */
+   KUNIT_EXPECT_EQ(test, 16777216000, res.value); /* 0x3E800 */
+
+   res = bw_int_to_fixed_nonconst(-1000);  /* -0x3E8 */
+   KUNIT_EXPECT_EQ(test, -16777216000, res.value); /* -0x3E800 */
+
+   res = bw_int_to_fixed_nonconst(0LL);
+   KUNIT_EXPECT_EQ(test, 0, res.value);
+
+   /**
+* Test corner cases, as the function's argument has to be an int64_t
+* between BW_FIXED_MIN_I32 and BW_FIXED_MAX_I32.
+*/
+   res = bw_int_to_fixed_nonconst(BW_FIXED_MAX_I32 - 1);  /* 0x7E 
*/
+   KUNIT_EXPECT_EQ(test, 9223372036821221376, res.value); /* 
0x7E00 */
+
+   res = bw_int_to_fixed_nonconst(BW_FIXED_MIN_I32 + 1);   /* 
-0x7F */
+   KUNIT_EXPECT_EQ(test, -9223372036837998592, res.value); /* 
-0x7F00 */

[RFC 2/3] drm/amd/display: Move bw_fixed macros to header file

2022-06-07 Thread Maíra Canal
The macros defined at bw_fixed are important mathematical definitions,
specifying masks to get the fractional part and the maximum and minimum
values of I64. In order to enable unit tests for bw_fixed, it is
relevant to have access to those macros. This commit moves the macros to
the header file, making it accessible to future unit tests.

Signed-off-by: Maíra Canal 
---
 .../gpu/drm/amd/display/dc/dml/calcs/bw_fixed.c| 14 +-
 drivers/gpu/drm/amd/display/dc/inc/bw_fixed.h  | 14 ++
 2 files changed, 15 insertions(+), 13 deletions(-)

diff --git a/drivers/gpu/drm/amd/display/dc/dml/calcs/bw_fixed.c 
b/drivers/gpu/drm/amd/display/dc/dml/calcs/bw_fixed.c
index 6ca288fb5fb9..d944570e5695 100644
--- a/drivers/gpu/drm/amd/display/dc/dml/calcs/bw_fixed.c
+++ b/drivers/gpu/drm/amd/display/dc/dml/calcs/bw_fixed.c
@@ -26,19 +26,7 @@
 #include "bw_fixed.h"
 
 
-#define MIN_I64 \
-   (int64_t)(-(1LL << 63))
-
-#define MAX_I64 \
-   (int64_t)((1ULL << 63) - 1)
-
-#define FRACTIONAL_PART_MASK \
-   ((1ULL << BW_FIXED_BITS_PER_FRACTIONAL_PART) - 1)
-
-#define GET_FRACTIONAL_PART(x) \
-   (FRACTIONAL_PART_MASK & (x))
-
-static uint64_t abs_i64(int64_t arg)
+uint64_t abs_i64(int64_t arg)
 {
if (arg >= 0)
return (uint64_t)(arg);
diff --git a/drivers/gpu/drm/amd/display/dc/inc/bw_fixed.h 
b/drivers/gpu/drm/amd/display/dc/inc/bw_fixed.h
index d1656c9d50df..064839425b96 100644
--- a/drivers/gpu/drm/amd/display/dc/inc/bw_fixed.h
+++ b/drivers/gpu/drm/amd/display/dc/inc/bw_fixed.h
@@ -33,12 +33,26 @@ struct bw_fixed {
int64_t value;
 };
 
+#define MIN_I64 \
+   (int64_t)(-(1ULL << 63))
+
+#define MAX_I64 \
+   (int64_t)((1ULL << 63) - 1)
+
+#define FRACTIONAL_PART_MASK \
+   ((1ULL << BW_FIXED_BITS_PER_FRACTIONAL_PART) - 1)
+
+#define GET_FRACTIONAL_PART(x) \
+   (FRACTIONAL_PART_MASK & (x))
+
 #define BW_FIXED_MIN_I32 \
(int64_t)(-(1LL << (63 - BW_FIXED_BITS_PER_FRACTIONAL_PART)))
 
 #define BW_FIXED_MAX_I32 \
(int64_t)((1ULL << (63 - BW_FIXED_BITS_PER_FRACTIONAL_PART)) - 1)
 
+uint64_t abs_i64(int64_t arg);
+
 static inline struct bw_fixed bw_min2(const struct bw_fixed arg1,
  const struct bw_fixed arg2)
 {
-- 
2.36.1



[RFC 1/3] drm/amd/display: Introduce KUnit to DML

2022-06-07 Thread Maíra Canal
KUnit unifies the test structure and provides helper tools that simplify
the development. Basic use case allows running tests as regular
processes, which makes easier to run unit tests on a development machine
and to integrate the tests in a CI system.

This commit introduce a basic unit test to one part of the Display Mode
Library: display_mode_lib, in order to introduce the basic structure of the
tests on the DML.

Signed-off-by: Maíra Canal 
---
 drivers/gpu/drm/amd/display/Kconfig   |  1 +
 .../gpu/drm/amd/display/amdgpu_dm/Makefile|  5 ++
 .../gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c |  3 +
 .../gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.h |  3 +
 .../drm/amd/display/amdgpu_dm/tests/Kconfig   | 29 +++
 .../drm/amd/display/amdgpu_dm/tests/Makefile  | 14 
 .../amdgpu_dm/tests/display_mode_lib_test.c   | 83 +++
 .../amd/display/amdgpu_dm/tests/dml_test.c| 23 +
 .../amd/display/amdgpu_dm/tests/dml_test.h| 13 +++
 9 files changed, 174 insertions(+)
 create mode 100644 drivers/gpu/drm/amd/display/amdgpu_dm/tests/Kconfig
 create mode 100644 drivers/gpu/drm/amd/display/amdgpu_dm/tests/Makefile
 create mode 100644 
drivers/gpu/drm/amd/display/amdgpu_dm/tests/display_mode_lib_test.c
 create mode 100644 drivers/gpu/drm/amd/display/amdgpu_dm/tests/dml_test.c
 create mode 100644 drivers/gpu/drm/amd/display/amdgpu_dm/tests/dml_test.h

diff --git a/drivers/gpu/drm/amd/display/Kconfig 
b/drivers/gpu/drm/amd/display/Kconfig
index 127667e549c1..83042e2e4d22 100644
--- a/drivers/gpu/drm/amd/display/Kconfig
+++ b/drivers/gpu/drm/amd/display/Kconfig
@@ -53,5 +53,6 @@ config DRM_AMD_SECURE_DISPLAY
 of crc of specific region via debugfs.
 Cooperate with specific DMCU FW.
 
+source "drivers/gpu/drm/amd/display/amdgpu_dm/tests/Kconfig"
 
 endmenu
diff --git a/drivers/gpu/drm/amd/display/amdgpu_dm/Makefile 
b/drivers/gpu/drm/amd/display/amdgpu_dm/Makefile
index 718e123a3230..d25b63566640 100644
--- a/drivers/gpu/drm/amd/display/amdgpu_dm/Makefile
+++ b/drivers/gpu/drm/amd/display/amdgpu_dm/Makefile
@@ -24,6 +24,11 @@
 # It provides the control and status of dm blocks.
 
 
+AMDGPU_DM_LIBS = tests
+
+AMD_DM = $(addsuffix /Makefile, $(addprefix 
$(FULL_AMD_DISPLAY_PATH)/amdgpu_dm/,$(AMDGPU_DM_LIBS)))
+
+include $(AMD_DM)
 
 AMDGPUDM = amdgpu_dm.o amdgpu_dm_irq.o amdgpu_dm_mst_types.o amdgpu_dm_color.o
 
diff --git a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c 
b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c
index cb1e9bb60db2..f73da1e0088f 100644
--- a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c
+++ b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c
@@ -1655,6 +1655,7 @@ static int amdgpu_dm_init(struct amdgpu_device *adev)
goto error;
}
 
+   amdgpu_dml_test_init();
 
DRM_DEBUG_DRIVER("KMS initialized.\n");
 
@@ -1678,6 +1679,8 @@ static void amdgpu_dm_fini(struct amdgpu_device *adev)
 {
int i;
 
+   amdgpu_dml_test_exit();
+
if (adev->dm.vblank_control_workqueue) {
destroy_workqueue(adev->dm.vblank_control_workqueue);
adev->dm.vblank_control_workqueue = NULL;
diff --git a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.h 
b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.h
index 3cc5c15303e6..e586d3a3d2f0 100644
--- a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.h
+++ b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.h
@@ -749,4 +749,7 @@ int dm_atomic_get_state(struct drm_atomic_state *state,
 struct amdgpu_dm_connector *
 amdgpu_dm_find_first_crtc_matching_connector(struct drm_atomic_state *state,
 struct drm_crtc *crtc);
+
+int amdgpu_dml_test_init(void);
+void amdgpu_dml_test_exit(void);
 #endif /* __AMDGPU_DM_H__ */
diff --git a/drivers/gpu/drm/amd/display/amdgpu_dm/tests/Kconfig 
b/drivers/gpu/drm/amd/display/amdgpu_dm/tests/Kconfig
new file mode 100644
index ..bd1d971d4452
--- /dev/null
+++ b/drivers/gpu/drm/amd/display/amdgpu_dm/tests/Kconfig
@@ -0,0 +1,29 @@
+# SPDX-License-Identifier: MIT
+menu "DML Unit Tests"
+   depends on DRM_AMD_DC && KUNIT=m
+
+config DISPLAY_MODE_LIB_KUNIT_TEST
+   bool "Enable unit tests for dml/display_mode_lib" if !DML_KUNIT_TEST
+   default y if DML_KUNIT_TEST
+   help
+   Enables unit tests for the dml/display_mode_lib. Only useful 
for kernel
+   devs running KUnit.
+
+   For more information on KUnit and unit tests in general please 
refer to
+   the KUnit documentation in Documentation/dev-tools/kunit/.
+
+   If unsure, say N.
+
+config DML_KUNIT_TEST
+   bool "Run all unit tests for DML" if !KUNIT_ALL_TESTS
+   default KUNIT_ALL_TESTS
+   help
+   Enables unit tests for the Display Mode Library. Only useful 
for kernel
+   devs running KUnit.
+
+   For more information on KUnit and unit tests in general please 
refer to
+ 

[RFC 0/3] drm/amd/display: Introduce KUnit to Display Mode Library

2022-06-07 Thread Maíra Canal
This RFC is a preview of the work being developed by Isabella Basso [1],
Maíra Canal [2], and Tales Lelo [3], as part of their Google Summer of Code
projects [4], and Magali Lemes [5], as part of her capstone project.

Our main goal is to bring unit testing to the AMDPGU driver; in particular,
we'll focus on the Display Mode Library (DML) for DCN2.0 and some of the DCE
functions. The modern AMD Linux kernel graphics driver is the single largest
driver in the mainline Linux codebase [6]. As AMD releases new GPU models,
the size of AMDGPU drivers is only becoming even larger.

Assuring the drivers' quality and reliability becomes a complex task without
systematic testing, especially for graphic drivers - which usually involve
tons of complex calculations. Also, keeping bugs away becomes an increasingly
hard task with the introduction of new code. Moreover, developers might want
to refactor old code without fear of the introduction of new issues.

In that sense, it is possible to argue for the benefits of implementing unit
testing at the AMDGPU drivers. This implementation will help developers to
recognize bugs before they are merged into the mainline and also makes it
possible for future code refactors of the AMDGPU driver.

When analyzing the AMDGPU driver, a particular part of the driver highlights
itself as a good candidate for the implementation of unit tests: the Display
Mode Library (DML), as it is focused on mathematical operations.

For the implementation of the tests, we decided to go with the Kernel Unit
Testing Framework (KUnit). KUnit makes it possible to run test suites on
kernel boot or load the tests as a module. It reports all test case results
through a TAP (Test Anything Protocol) in the kernel log.

Moreover, KUnit unifies the test structure and provides tools to simplify the
testing for developers and CI systems.

That said, we developed a little snippet on what we intend to develop in our
summer. We planned the basic structure on how the tests will be introduced
into the codebase and, on the concern of the CI systems, developed a structure
where the unit tests can be introduced as modules and run on IGT (the IGT patch
will be introduced soon).

The way the modules are implemented might seem a little unusual for KUnit
developers. We need to call the KUnit init function inside the AMDGPU stack,
otherwise, the test won't compile as a module. So, the solution to this
problem was based on the unit tests for the Thunderbolt driver, which uses
KUnit and also tests a physical driver.

As kunit_test_suites() defines itself as an init_module(), it conflicts with
the existing one at amdgpu_drv. So, if we use kunit_test_suites(), we won't
be able to compile the tests as modules and, therefore, won't be able to use
IGT to run the tests. This problem with kunit_test_suites() was already
discussed in the KUnit mailing list, as can be seen in [7].

The first patch configures the basic structure of the KUnit Tests, setting the
proper Makefile, Kconfig, and init function. It also contains a simple test
involving DML logging, which is the pretext for building the testing structure.

The second patch adds KUnit tests to bw_fixed functions. This patch represents
what we intend to do on the rest of the DML modules: systematic testing of the
public functions of the DML, especially mathematically complicated functions.
Also, it shows how simple it is to add new tests to the DML with the structure
we built.

Any feedback or ideas for the project are welcome!

[1] https://crosscat.me
[2] https://mairacanal.github.io
[3] https://tales-aparecida.github.io/
[4] 
https://summerofcode.withgoogle.com/programs/2022/organizations/xorg-foundation
[5] https://magalilemes.github.io/
[6] https://www.phoronix.com/scan.php?page=news_item=AMDGPU-Closing-4-Million
[7] https://groups.google.com/g/kunit-dev/c/hbJbh8L37FU/m/EmszZE9qBAAJ

- Isabella Basso, Magali Lemes, Maíra Canal, and Tales Lelo

Magali Lemes (1):
  drm/amd/display: Introduce KUnit tests to the bw_fixed library

Maíra Canal (2):
  drm/amd/display: Introduce KUnit to DML
  drm/amd/display: Move bw_fixed macros to header file

 drivers/gpu/drm/amd/display/Kconfig   |   1 +
 .../gpu/drm/amd/display/amdgpu_dm/Makefile|   5 +
 .../gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c |   3 +
 .../gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.h |   3 +
 .../drm/amd/display/amdgpu_dm/tests/Kconfig   |  41 +++
 .../drm/amd/display/amdgpu_dm/tests/Makefile  |  18 +
 .../amdgpu_dm/tests/calcs/bw_fixed_test.c | 322 ++
 .../amdgpu_dm/tests/display_mode_lib_test.c   |  83 +
 .../amd/display/amdgpu_dm/tests/dml_test.c|  26 ++
 .../amd/display/amdgpu_dm/tests/dml_test.h|  21 ++
 .../drm/amd/display/dc/dml/calcs/bw_fixed.c   |  14 +-
 drivers/gpu/drm/amd/display/dc/inc/bw_fixed.h |  14 +
 12 files changed, 538 insertions(+), 13 deletions(-)
 create mode 100644 drivers/gpu/drm/amd/display/amdgpu_dm/tests/Kconfig
 create mode 100644 

[PATCH] drm/i915: More PVC+DG2 workarounds

2022-06-07 Thread Matt Roper
A new PVC+DG2 workaround has appeared recently:
 - Wa_16015675438

And a couple existing DG2 workarounds have been extended to PVC:
 - Wa_14015795083
 - Wa_18018781329

Note that Wa_16015675438 asks us to program a register that is in the
0x2xxx range typically associated with the RCS engine, even though PVC
does not have an RCS.  By default the GuC will think we've made a
mistake and throw an exception when it sees this register on a CCS
engine's save/restore list, so we need to pass an extra GuC control flag
to tell it that this is expected and not a problem.

Signed-off-by: Anshuman Gupta 
Signed-off-by: Badal Nilawar 
Signed-off-by: Prathap Kumar Valsan 
Signed-off-by: Matt Roper 
---
 drivers/gpu/drm/i915/gt/intel_gt_regs.h |  1 +
 drivers/gpu/drm/i915/gt/intel_workarounds.c | 24 +++--
 drivers/gpu/drm/i915/gt/uc/intel_guc.c  |  4 
 drivers/gpu/drm/i915/gt/uc/intel_guc_fwif.h |  1 +
 4 files changed, 23 insertions(+), 7 deletions(-)

diff --git a/drivers/gpu/drm/i915/gt/intel_gt_regs.h 
b/drivers/gpu/drm/i915/gt/intel_gt_regs.h
index c8129a351731..226557018037 100644
--- a/drivers/gpu/drm/i915/gt/intel_gt_regs.h
+++ b/drivers/gpu/drm/i915/gt/intel_gt_regs.h
@@ -140,6 +140,7 @@
 #define FF_SLICE_CS_CHICKEN2   _MMIO(0x20e4)
 #define   GEN9_TSG_BARRIER_ACK_DISABLE (1 << 8)
 #define   GEN9_POOLED_EU_LOAD_BALANCING_FIX_DISABLE(1 << 10)
+#define   GEN12_PERF_FIX_BALANCING_CFE_DISABLE REG_BIT(15)
 
 #define GEN9_CS_DEBUG_MODE1_MMIO(0x20ec)
 #define   FF_DOP_CLOCK_GATE_DISABLEREG_BIT(1)
diff --git a/drivers/gpu/drm/i915/gt/intel_workarounds.c 
b/drivers/gpu/drm/i915/gt/intel_workarounds.c
index 1e7ca3863f20..e1e70eff9aac 100644
--- a/drivers/gpu/drm/i915/gt/intel_workarounds.c
+++ b/drivers/gpu/drm/i915/gt/intel_workarounds.c
@@ -1491,13 +1491,20 @@ dg2_gt_workarounds_init(struct intel_gt *gt, struct 
i915_wa_list *wal)
wa_write_clr(wal, GEN7_MISCCPCTL, GEN12_DOP_CLOCK_GATE_RENDER_ENABLE);
 }
 
+static void
+pvc_gt_workarounds_init(struct intel_gt *gt, struct i915_wa_list *wal)
+{
+   /* Wa_14015795083 */
+   wa_write_clr(wal, GEN7_MISCCPCTL, GEN12_DOP_CLOCK_GATE_RENDER_ENABLE);
+}
+
 static void
 gt_init_workarounds(struct intel_gt *gt, struct i915_wa_list *wal)
 {
struct drm_i915_private *i915 = gt->i915;
 
if (IS_PONTEVECCHIO(i915))
-   ; /* none yet */
+   pvc_gt_workarounds_init(gt, wal);
else if (IS_DG2(i915))
dg2_gt_workarounds_init(gt, wal);
else if (IS_XEHPSDV(i915))
@@ -2082,12 +2089,6 @@ rcs_engine_wa_init(struct intel_engine_cs *engine, 
struct i915_wa_list *wal)
 * performance guide section.
 */
wa_write_or(wal, XEHP_L3SCQREG7, BLEND_FILL_CACHING_OPT_DIS);
-
-   /* Wa_18018781329:dg2 */
-   wa_write_or(wal, RENDER_MOD_CTRL, FORCE_MISS_FTLB);
-   wa_write_or(wal, COMP_MOD_CTRL, FORCE_MISS_FTLB);
-   wa_write_or(wal, VDBX_MOD_CTRL, FORCE_MISS_FTLB);
-   wa_write_or(wal, VEBX_MOD_CTRL, FORCE_MISS_FTLB);
}
 
if (IS_DG2_GRAPHICS_STEP(i915, G11, STEP_A0, STEP_B0)) {
@@ -2700,6 +2701,15 @@ general_render_compute_wa_init(struct intel_engine_cs 
*engine, struct i915_wa_li
 
/* Wa_22014226127:dg2,pvc */
wa_write_or(wal, LSC_CHICKEN_BIT_0, DISABLE_D8_D16_COASLESCE);
+
+   /* Wa_16015675438:dg2,pvc */
+   wa_masked_en(wal, FF_SLICE_CS_CHICKEN2, 
GEN12_PERF_FIX_BALANCING_CFE_DISABLE);
+
+   /* Wa_18018781329:dg2,pvc */
+   wa_write_or(wal, RENDER_MOD_CTRL, FORCE_MISS_FTLB);
+   wa_write_or(wal, COMP_MOD_CTRL, FORCE_MISS_FTLB);
+   wa_write_or(wal, VDBX_MOD_CTRL, FORCE_MISS_FTLB);
+   wa_write_or(wal, VEBX_MOD_CTRL, FORCE_MISS_FTLB);
}
 }
 
diff --git a/drivers/gpu/drm/i915/gt/uc/intel_guc.c 
b/drivers/gpu/drm/i915/gt/uc/intel_guc.c
index 2c4ad4a65089..35887cb53201 100644
--- a/drivers/gpu/drm/i915/gt/uc/intel_guc.c
+++ b/drivers/gpu/drm/i915/gt/uc/intel_guc.c
@@ -327,6 +327,10 @@ static u32 guc_ctl_wa_flags(struct intel_guc *guc)
IS_DG2_GRAPHICS_STEP(gt->i915, G11, STEP_A0, STEP_FOREVER))
flags |= GUC_WA_CONTEXT_ISOLATION;
 
+   /* Wa_16015675438 */
+   if (!RCS_MASK(gt))
+   flags |= GUC_WA_RCS_REGS_IN_CCS_REGS_LIST;
+
return flags;
 }
 
diff --git a/drivers/gpu/drm/i915/gt/uc/intel_guc_fwif.h 
b/drivers/gpu/drm/i915/gt/uc/intel_guc_fwif.h
index 42cb7a9a6199..b3c9a9327f76 100644
--- a/drivers/gpu/drm/i915/gt/uc/intel_guc_fwif.h
+++ b/drivers/gpu/drm/i915/gt/uc/intel_guc_fwif.h
@@ -105,6 +105,7 @@
 #define   GUC_WA_PRE_PARSERBIT(14)
 #define   GUC_WA_HOLD_CCS_SWITCHOUTBIT(17)
 #define   GUC_WA_POLLCSBIT(18)
+#define   GUC_WA_RCS_REGS_IN_CCS_REGS_LIST BIT(21)
 
 #define GUC_CTL_FEATURE   

linux-next: manual merge of the drm-intel tree with Linus' tree

2022-06-07 Thread Stephen Rothwell
Hi all,

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

  drivers/gpu/drm/i915/gt/intel_rps.c

between commit:

  56758cc45955 ("drm/i915/rps: Centralize computation of freq caps")

from Linus' tree and commit:

  ee421bb4cb95 ("drm/i915/pcode: Extend pcode functions for multiple gt's")

from the drm-intel tree.

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

-- 
Cheers,
Stephen Rothwell

diff --cc drivers/gpu/drm/i915/gt/intel_rps.c
index 3476a11f294c,ce61ceb07114..
--- a/drivers/gpu/drm/i915/gt/intel_rps.c
+++ b/drivers/gpu/drm/i915/gt/intel_rps.c
@@@ -1138,15 -1095,13 +1138,16 @@@ static void gen6_rps_init(struct intel_
if (IS_HASWELL(i915) || IS_BROADWELL(i915) ||
IS_GEN9_BC(i915) || GRAPHICS_VER(i915) >= 11) {
u32 ddcc_status = 0;
 +  u32 mult = 1;
  
 +  if (IS_GEN9_BC(i915) || GRAPHICS_VER(i915) >= 11)
 +  mult = GEN9_FREQ_SCALER;
-   if (snb_pcode_read(i915, HSW_PCODE_DYNAMIC_DUTY_CYCLE_CONTROL,
+   if (snb_pcode_read(rps_to_gt(rps)->uncore,
+  HSW_PCODE_DYNAMIC_DUTY_CYCLE_CONTROL,
   _status, NULL) == 0)
rps->efficient_freq =
 -  clamp_t(u8,
 -  (ddcc_status >> 8) & 0xff,
 +  clamp_t(u32,
 +  ((ddcc_status >> 8) & 0xff) * mult,
rps->min_freq,
rps->max_freq);
}


pgphlUyewqPBe.pgp
Description: OpenPGP digital signature


linux-next: manual merge of the drm-intel tree with Linus' tree

2022-06-07 Thread Stephen Rothwell
Hi all,

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

  drivers/gpu/drm/i915/display/intel_dmc_regs.h

between commit:

  2518f226c60d ("Merge tag 'drm-next-2022-05-25' of 
git://anongit.freedesktop.org/drm/drm")

from Linus' tree and commit:

  21c47196aec3 ("drm/i915/dmc: Add MMIO range restrictions")

from the drm-intel tree.

I fixed it up (these were only white space differences, so I just used
the version from Linus' tree) and can carry the fix as necessary. This
is now fixed as far as linux-next is concerned, but any non trivial
conflicts should be mentioned to your upstream maintainer when your tree
is submitted for merging.  You may also want to consider cooperating
with the maintainer of the conflicting tree to minimise any particularly
complex conflicts.

-- 
Cheers,
Stephen Rothwell


pgpkkNnqqyfdT.pgp
Description: OpenPGP digital signature


Re: [PATCH] drm/i915/guc/slpc: Use non-blocking H2G for waitboost

2022-06-07 Thread John Harrison

On 6/7/2022 15:29, Dixit, Ashutosh wrote:

On Sat, 14 May 2022 23:05:06 -0700, Vinay Belgaumkar wrote:

SLPC min/max frequency updates require H2G calls. We are seeing
timeouts when GuC channel is backed up and it is unable to respond
in a timely fashion causing warnings and affecting CI.

This is seen when waitboosting happens during a stress test.
this patch updates the waitboost path to use a non-blocking
H2G call instead, which returns as soon as the message is
successfully transmitted.

Overall I think this patch is trying to paper over problems in the blocking
H2G CT interface (specifically the 1 second timeout in
wait_for_ct_request_update()). So I think we should address that problem in
the interface directly rather than having each client (SLPC and any future
client) work around the problem. Following points:

1. This patch seems to assume that it is 'ok' to ignore the return code
from FW for a waitboost request (arguing waitboost is best effort so
it's ok to 'fire and forget'). But the return code is still useful
e.g. in cases where we see performance issues and want to go back and
investigate if FW rejected any waitboost requests.
You still get errors reported in the GuC log. Indeed, some errors (or at 
least error reasons) are only visible in the log not in the return code.




2. We are already seeing that a 1 second timeout is not sufficient. So why
not simply increase that timeout?

3. In fact if we are saying that the CT interface is a "reliable" interface
(implying no message loss), to ensure reliability that timeout should
not simply be increased, it should be made "infinite" (in quotes).

4. Maybe it would have been best to not have a "blocking" H2G interface at
all (with the wait in wait_for_ct_request_update()). Just have an
asynchronous interface (which mirrors the actual interface between FW
and i915) in which clients register callbacks which are invoked when FW
responds. If this is too big a change we can probably continue with the
current blocking interface after increasing the timeout as mentioned
above.

5. Finally, the waitboost request is just the most likely to get stuck at
the back of a full CT queue since it happens during normal
operation. Actually any request, say one initiated from sysfs, can also
get similarly stuck at the back of a full queue. So any solution should
also address that situation (where the return code is needed and
similarly for a future client of the "blocking" (REQUEST/RESPONSE)
interface).
The blocking interface is only intended for init time operations, not 
runtime. Stuff where the operation is meant to be synchronous and the 
KMD should not proceed until it has an ack back from the GuC that the 
update has taken place. All runtime operations are expected to be 
asynchronous. If a response is required, then it should be sent via an 
async callback. E.g. context de-registration is a 'fire and forget' H2G 
call but gets a 'deregistration complete' G2H notification when it is 
safe for the KMD to free up the associated storage.


There is an 'errors only' H2G mechanism. That will not send an ack back 
in the case of a successful H2G but will send back an error notification 
in the case of a failure. All async H2Gs should really be using that 
mechanism. I think Michal W did post a patch for it and I was meant to 
be reviewing it but it dropped of my radar due to other higher priorities.


John.



Thanks.
--
Ashutosh




[PATCH 2/2] video: fbdev: skeletonfb: Convert to generic power management

2022-06-07 Thread Bjorn Helgaas
From: Bjorn Helgaas 

PCI-specific power management (pci_driver.suspend and pci_driver.resume) is
deprecated.  If drivers implement power management, they should use the
generic power management framework, not the PCI-specific hooks.

Convert the sample code to use the generic power management framework.

Signed-off-by: Bjorn Helgaas 
---
 drivers/video/fbdev/skeletonfb.c | 13 +++--
 1 file changed, 7 insertions(+), 6 deletions(-)

diff --git a/drivers/video/fbdev/skeletonfb.c b/drivers/video/fbdev/skeletonfb.c
index bcacfb6934fa..70ba78450837 100644
--- a/drivers/video/fbdev/skeletonfb.c
+++ b/drivers/video/fbdev/skeletonfb.c
@@ -838,9 +838,9 @@ static void xxxfb_remove(struct pci_dev *dev)
  *
  *  See Documentation/driver-api/pm/devices.rst for more information
  */
-static int xxxfb_suspend(struct pci_dev *dev, pm_message_t msg)
+static int xxxfb_suspend(struct device *dev)
 {
-   struct fb_info *info = pci_get_drvdata(dev);
+   struct fb_info *info = dev_get_drvdata(dev);
struct xxxfb_par *par = info->par;
 
/* suspend here */
@@ -853,9 +853,9 @@ static int xxxfb_suspend(struct pci_dev *dev, pm_message_t 
msg)
  *
  *  See Documentation/driver-api/pm/devices.rst for more information
  */
-static int xxxfb_resume(struct pci_dev *dev)
+static int xxxfb_resume(struct device *dev)
 {
-   struct fb_info *info = pci_get_drvdata(dev);
+   struct fb_info *info = dev_get_drvdata(dev);
struct xxxfb_par *par = info->par;
 
/* resume here */
@@ -873,14 +873,15 @@ static const struct pci_device_id xxxfb_id_table[] = {
{ 0, }
 };
 
+static SIMPLE_DEV_PM_OPS(xxxfb_pm_ops, xxxfb_suspend, xxxfb_resume);
+
 /* For PCI drivers */
 static struct pci_driver xxxfb_driver = {
.name = "xxxfb",
.id_table = xxxfb_id_table,
.probe =xxxfb_probe,
.remove =   xxxfb_remove,
-   .suspend =  xxxfb_suspend, /* optional but recommended */
-   .resume =   xxxfb_resume,  /* optional but recommended */
+   .driver.pm =xxxfb_pm_ops, /* optional but recommended */
 };
 
 MODULE_DEVICE_TABLE(pci, xxxfb_id_table);
-- 
2.25.1



[PATCH 1/2] video: fbdev: cirrusfb: Remove useless reference to PCI power management

2022-06-07 Thread Bjorn Helgaas
From: Bjorn Helgaas 

PCI-specific power management (pci_driver.suspend and pci_driver.resume) is
deprecated.  The cirrusfb driver has never implemented power management at
all, but if it ever does, it should use the generic power management
framework, not the PCI-specific hooks.

Remove the commented-out references to the PCI-specific power management
hooks.

Signed-off-by: Bjorn Helgaas 
---
 drivers/video/fbdev/cirrusfb.c | 6 --
 1 file changed, 6 deletions(-)

diff --git a/drivers/video/fbdev/cirrusfb.c b/drivers/video/fbdev/cirrusfb.c
index 3d47c347b897..51e072c03e1c 100644
--- a/drivers/video/fbdev/cirrusfb.c
+++ b/drivers/video/fbdev/cirrusfb.c
@@ -2184,12 +2184,6 @@ static struct pci_driver cirrusfb_pci_driver = {
.id_table   = cirrusfb_pci_table,
.probe  = cirrusfb_pci_register,
.remove = cirrusfb_pci_unregister,
-#ifdef CONFIG_PM
-#if 0
-   .suspend= cirrusfb_pci_suspend,
-   .resume = cirrusfb_pci_resume,
-#endif
-#endif
 };
 #endif /* CONFIG_PCI */
 
-- 
2.25.1



[PATCH 0/2] video: fbdev: Convert from PCI to generic power management

2022-06-07 Thread Bjorn Helgaas
From: Bjorn Helgaas 

PCI-specific power management (pci_driver.suspend and pci_driver.resume) is
deprecated.  If drivers implement power management, they should use the
generic power management framework, not the PCI-specific hooks.

No fbdev drivers actually implement PCI power management, but there are a
cirrusfb has some commented-out references to it and skeletonfb has
examples of it.  Remove these.

Bjorn Helgaas (2):
  video: fbdev: cirrusfb: Remove useless reference to PCI power
management
  video: fbdev: skeletonfb: Convert to generic power management

 drivers/video/fbdev/cirrusfb.c   |  6 --
 drivers/video/fbdev/skeletonfb.c | 13 +++--
 2 files changed, 7 insertions(+), 12 deletions(-)

-- 
2.25.1



Re: [Intel-gfx] [PATCH] drm/i915/guc/slpc: Use non-blocking H2G for waitboost

2022-06-07 Thread John Harrison

On 6/7/2022 16:02, John Harrison wrote:

On 5/16/2022 00:59, Jani Nikula wrote:

On Sat, 14 May 2022, Vinay Belgaumkar  wrote:

SLPC min/max frequency updates require H2G calls. We are seeing
timeouts when GuC channel is backed up and it is unable to respond
in a timely fashion causing warnings and affecting CI.

This is seen when waitboosting happens during a stress test.
this patch updates the waitboost path to use a non-blocking
H2G call instead, which returns as soon as the message is
successfully transmitted.

v2: Use drm_notice to report any errors that might occur while
sending the waitboost H2G request (Tvrtko)

Signed-off-by: Vinay Belgaumkar
---
  drivers/gpu/drm/i915/gt/uc/intel_guc_slpc.c | 44 +
  1 file changed, 36 insertions(+), 8 deletions(-)

diff --git a/drivers/gpu/drm/i915/gt/uc/intel_guc_slpc.c 
b/drivers/gpu/drm/i915/gt/uc/intel_guc_slpc.c
index 1db833da42df..e5e869c96262 100644
--- a/drivers/gpu/drm/i915/gt/uc/intel_guc_slpc.c
+++ b/drivers/gpu/drm/i915/gt/uc/intel_guc_slpc.c
@@ -98,6 +98,30 @@ static u32 slpc_get_state(struct intel_guc_slpc *slpc)
return data->header.global_state;
  }
  
+static int guc_action_slpc_set_param_nb(struct intel_guc *guc, u8 id, u32 value)

+{
+   u32 request[] = {

static const


+   GUC_ACTION_HOST2GUC_PC_SLPC_REQUEST,
+   SLPC_EVENT(SLPC_EVENT_PARAMETER_SET, 2),
+   id,
+   value,
+   };
+   int ret;
+
+   ret = intel_guc_send_nb(guc, request, ARRAY_SIZE(request), 0);
+
+   return ret > 0 ? -EPROTO : ret;
+}
+
+static int slpc_set_param_nb(struct intel_guc_slpc *slpc, u8 id, u32 value)
+{
+   struct intel_guc *guc = slpc_to_guc(slpc);
+
+   GEM_BUG_ON(id >= SLPC_MAX_PARAM);
+
+   return guc_action_slpc_set_param_nb(guc, id, value);
+}
+
  static int guc_action_slpc_set_param(struct intel_guc *guc, u8 id, u32 value)
  {
u32 request[] = {

Ditto here, and the whole gt/uc directory seems to have tons of these
u32 action/request array variables on stack, with the required
initialization, that could be in rodata.

Please fix all of them.

BR,
Jani.
But the only constant is the action code. Everything else is 
parameters and will be different on each call.

...


Oops. Just saw your follow up message. No worries!

John.



Re: [Intel-gfx] [PATCH] drm/i915/guc/slpc: Use non-blocking H2G for waitboost

2022-06-07 Thread John Harrison

On 5/16/2022 00:59, Jani Nikula wrote:

On Sat, 14 May 2022, Vinay Belgaumkar  wrote:

SLPC min/max frequency updates require H2G calls. We are seeing
timeouts when GuC channel is backed up and it is unable to respond
in a timely fashion causing warnings and affecting CI.

This is seen when waitboosting happens during a stress test.
this patch updates the waitboost path to use a non-blocking
H2G call instead, which returns as soon as the message is
successfully transmitted.

v2: Use drm_notice to report any errors that might occur while
sending the waitboost H2G request (Tvrtko)

Signed-off-by: Vinay Belgaumkar
---
  drivers/gpu/drm/i915/gt/uc/intel_guc_slpc.c | 44 +
  1 file changed, 36 insertions(+), 8 deletions(-)

diff --git a/drivers/gpu/drm/i915/gt/uc/intel_guc_slpc.c 
b/drivers/gpu/drm/i915/gt/uc/intel_guc_slpc.c
index 1db833da42df..e5e869c96262 100644
--- a/drivers/gpu/drm/i915/gt/uc/intel_guc_slpc.c
+++ b/drivers/gpu/drm/i915/gt/uc/intel_guc_slpc.c
@@ -98,6 +98,30 @@ static u32 slpc_get_state(struct intel_guc_slpc *slpc)
return data->header.global_state;
  }
  
+static int guc_action_slpc_set_param_nb(struct intel_guc *guc, u8 id, u32 value)

+{
+   u32 request[] = {

static const


+   GUC_ACTION_HOST2GUC_PC_SLPC_REQUEST,
+   SLPC_EVENT(SLPC_EVENT_PARAMETER_SET, 2),
+   id,
+   value,
+   };
+   int ret;
+
+   ret = intel_guc_send_nb(guc, request, ARRAY_SIZE(request), 0);
+
+   return ret > 0 ? -EPROTO : ret;
+}
+
+static int slpc_set_param_nb(struct intel_guc_slpc *slpc, u8 id, u32 value)
+{
+   struct intel_guc *guc = slpc_to_guc(slpc);
+
+   GEM_BUG_ON(id >= SLPC_MAX_PARAM);
+
+   return guc_action_slpc_set_param_nb(guc, id, value);
+}
+
  static int guc_action_slpc_set_param(struct intel_guc *guc, u8 id, u32 value)
  {
u32 request[] = {

Ditto here, and the whole gt/uc directory seems to have tons of these
u32 action/request array variables on stack, with the required
initialization, that could be in rodata.

Please fix all of them.

BR,
Jani.
But the only constant is the action code. Everything else is parameters 
and will be different on each call.


You mean something like this?

   static const u32 template[] = {
    action,
   };
   u32 *request = kmalloc_array(sizeof(*request), 4);
   memcpy(request, template, sizeof(*request) * 1);
   request[1] = param0;
   request[2] = param1;
   request[3] = param2;
   ret = send(request);
   kfree(request);
   return ret;


Not seeing how that would be an improvement. It's a lot more code, a lot 
less readable, more prone to bugs due to incorrect structure sizes 
and/or params in the wrong place. The current version is easy to read 
and therefore to maintain, almost impossible to get wrong, and only puts 
a few words on the stack. I think the largest request is region of 15 
words? I'm not seeing what the problem is.


John.



@@ -208,12 +232,10 @@ static int slpc_force_min_freq(struct intel_guc_slpc 
*slpc, u32 freq)
 */
  
  	with_intel_runtime_pm(>runtime_pm, wakeref) {

-   ret = slpc_set_param(slpc,
-SLPC_PARAM_GLOBAL_MIN_GT_UNSLICE_FREQ_MHZ,
-freq);
-   if (ret)
-   i915_probe_error(i915, "Unable to force min freq to %u: 
%d",
-freq, ret);
+   /* Non-blocking request will avoid stalls */
+   ret = slpc_set_param_nb(slpc,
+   
SLPC_PARAM_GLOBAL_MIN_GT_UNSLICE_FREQ_MHZ,
+   freq);
}
  
  	return ret;

@@ -222,6 +244,8 @@ static int slpc_force_min_freq(struct intel_guc_slpc *slpc, 
u32 freq)
  static void slpc_boost_work(struct work_struct *work)
  {
struct intel_guc_slpc *slpc = container_of(work, typeof(*slpc), 
boost_work);
+   struct drm_i915_private *i915 = slpc_to_i915(slpc);
+   int err;
  
  	/*

 * Raise min freq to boost. It's possible that
@@ -231,8 +255,12 @@ static void slpc_boost_work(struct work_struct *work)
 */
mutex_lock(>lock);
if (atomic_read(>num_waiters)) {
-   slpc_force_min_freq(slpc, slpc->boost_freq);
-   slpc->num_boosts++;
+   err = slpc_force_min_freq(slpc, slpc->boost_freq);
+   if (!err)
+   slpc->num_boosts++;
+   else
+   drm_notice(>drm, "Failed to send waitboost request 
(%d)\n",
+  err);
}
mutex_unlock(>lock);
  }


[PATCH v2 1/2] vfio: Replace the DMA unmapping notifier with a callback

2022-06-07 Thread Jason Gunthorpe
Instead of having drivers register the notifier with explicit code just
have them provide a dma_unmap callback op in their driver ops and rely on
the core code to wire it up.

Suggested-by: Christoph Hellwig 
Reviewed-by: Christoph Hellwig 
Signed-off-by: Jason Gunthorpe 
---
 drivers/gpu/drm/i915/gvt/gvt.h|   1 -
 drivers/gpu/drm/i915/gvt/kvmgt.c  |  75 ---
 drivers/s390/cio/vfio_ccw_ops.c   |  41 ++---
 drivers/s390/cio/vfio_ccw_private.h   |   1 -
 drivers/s390/crypto/vfio_ap_ops.c |  53 ++-
 drivers/s390/crypto/vfio_ap_private.h |   3 -
 drivers/vfio/vfio.c   | 126 +-
 drivers/vfio/vfio.h   |   5 +
 include/linux/vfio.h  |  21 +
 9 files changed, 87 insertions(+), 239 deletions(-)

diff --git a/drivers/gpu/drm/i915/gvt/gvt.h b/drivers/gpu/drm/i915/gvt/gvt.h
index aee1a45da74bcb..705689e6401197 100644
--- a/drivers/gpu/drm/i915/gvt/gvt.h
+++ b/drivers/gpu/drm/i915/gvt/gvt.h
@@ -226,7 +226,6 @@ struct intel_vgpu {
unsigned long nr_cache_entries;
struct mutex cache_lock;
 
-   struct notifier_block iommu_notifier;
atomic_t released;
 
struct kvm_page_track_notifier_node track_node;
diff --git a/drivers/gpu/drm/i915/gvt/kvmgt.c b/drivers/gpu/drm/i915/gvt/kvmgt.c
index e2f6c56ab3420c..ecd5bb37b63a2a 100644
--- a/drivers/gpu/drm/i915/gvt/kvmgt.c
+++ b/drivers/gpu/drm/i915/gvt/kvmgt.c
@@ -729,34 +729,25 @@ int intel_gvt_set_edid(struct intel_vgpu *vgpu, int 
port_num)
return ret;
 }
 
-static int intel_vgpu_iommu_notifier(struct notifier_block *nb,
-unsigned long action, void *data)
+static void intel_vgpu_dma_unmap(struct vfio_device *vfio_dev, u64 iova,
+u64 length)
 {
-   struct intel_vgpu *vgpu =
-   container_of(nb, struct intel_vgpu, iommu_notifier);
-
-   if (action == VFIO_IOMMU_NOTIFY_DMA_UNMAP) {
-   struct vfio_iommu_type1_dma_unmap *unmap = data;
-   struct gvt_dma *entry;
-   unsigned long iov_pfn, end_iov_pfn;
+   struct intel_vgpu *vgpu = vfio_dev_to_vgpu(vfio_dev);
+   struct gvt_dma *entry;
+   u64 iov_pfn = iova >> PAGE_SHIFT;
+   u64 end_iov_pfn = iov_pfn + length / PAGE_SIZE;
 
-   iov_pfn = unmap->iova >> PAGE_SHIFT;
-   end_iov_pfn = iov_pfn + unmap->size / PAGE_SIZE;
+   mutex_lock(>cache_lock);
+   for (; iov_pfn < end_iov_pfn; iov_pfn++) {
+   entry = __gvt_cache_find_gfn(vgpu, iov_pfn);
+   if (!entry)
+   continue;
 
-   mutex_lock(>cache_lock);
-   for (; iov_pfn < end_iov_pfn; iov_pfn++) {
-   entry = __gvt_cache_find_gfn(vgpu, iov_pfn);
-   if (!entry)
-   continue;
-
-   gvt_dma_unmap_page(vgpu, entry->gfn, entry->dma_addr,
-  entry->size);
-   __gvt_cache_remove_entry(vgpu, entry);
-   }
-   mutex_unlock(>cache_lock);
+   gvt_dma_unmap_page(vgpu, entry->gfn, entry->dma_addr,
+  entry->size);
+   __gvt_cache_remove_entry(vgpu, entry);
}
-
-   return NOTIFY_OK;
+   mutex_unlock(>cache_lock);
 }
 
 static bool __kvmgt_vgpu_exist(struct intel_vgpu *vgpu)
@@ -783,36 +774,20 @@ static bool __kvmgt_vgpu_exist(struct intel_vgpu *vgpu)
 static int intel_vgpu_open_device(struct vfio_device *vfio_dev)
 {
struct intel_vgpu *vgpu = vfio_dev_to_vgpu(vfio_dev);
-   unsigned long events;
-   int ret;
-
-   vgpu->iommu_notifier.notifier_call = intel_vgpu_iommu_notifier;
 
-   events = VFIO_IOMMU_NOTIFY_DMA_UNMAP;
-   ret = vfio_register_notifier(vfio_dev, VFIO_IOMMU_NOTIFY, ,
->iommu_notifier);
-   if (ret != 0) {
-   gvt_vgpu_err("vfio_register_notifier for iommu failed: %d\n",
-   ret);
-   goto out;
-   }
-
-   ret = -EEXIST;
if (vgpu->attached)
-   goto undo_iommu;
+   return -EEXIST;
 
-   ret = -ESRCH;
if (!vgpu->vfio_device.kvm ||
vgpu->vfio_device.kvm->mm != current->mm) {
gvt_vgpu_err("KVM is required to use Intel vGPU\n");
-   goto undo_iommu;
+   return -ESRCH;
}
 
kvm_get_kvm(vgpu->vfio_device.kvm);
 
-   ret = -EEXIST;
if (__kvmgt_vgpu_exist(vgpu))
-   goto undo_iommu;
+   return -EEXIST;
 
vgpu->attached = true;
 
@@ -831,12 +806,6 @@ static int intel_vgpu_open_device(struct vfio_device 
*vfio_dev)
 
atomic_set(>released, 0);
return 0;
-
-undo_iommu:
-   vfio_unregister_notifier(vfio_dev, VFIO_IOMMU_NOTIFY,
-

[PATCH v2 0/2] Remove the VFIO_IOMMU_NOTIFY_DMA_UNMAP notifier

2022-06-07 Thread Jason Gunthorpe
This is the last notifier toward the drivers, replace it with a simple op
callback in the vfio_device_ops.

v2:
 - Declare and initialize variables in intel_vgpu_dma_unmap()
 - Remove 'vendor' when touching comments
 - Remove kdoc for vfio dma_unmap notifier
 - Add WARN_ON to vfio_register_emulated_iommu_dev() since dma_unmap is
   mandatory
 - Move dma_unmap call loop to vfio_notify_dma_unmap()
 - Document why the double mutex is being used and why the mutex lock is
   dropped when calling dma_unmap
v1: 
https://lore.kernel.org/r/0-v1-896844109f36+a-vfio_unmap_notif_...@nvidia.com

Signed-off-by: Jason Gunthorpe 

Jason Gunthorpe (2):
  vfio: Replace the DMA unmapping notifier with a callback
  vfio: Replace the iommu notifier with a device list

 drivers/gpu/drm/i915/gvt/gvt.h|   1 -
 drivers/gpu/drm/i915/gvt/kvmgt.c  |  75 +-
 drivers/s390/cio/vfio_ccw_ops.c   |  41 +++---
 drivers/s390/cio/vfio_ccw_private.h   |   1 -
 drivers/s390/crypto/vfio_ap_ops.c |  53 ++---
 drivers/s390/crypto/vfio_ap_private.h |   3 -
 drivers/vfio/vfio.c   | 108 ++
 drivers/vfio/vfio.h   |   9 +--
 drivers/vfio/vfio_iommu_type1.c   | 103 +++-
 include/linux/vfio.h  |  21 +
 10 files changed, 134 insertions(+), 281 deletions(-)


base-commit: f2906aa863381afb0015a9eb7fefad885d4e5a56
-- 
2.36.1



[PATCH v2 2/2] vfio: Replace the iommu notifier with a device list

2022-06-07 Thread Jason Gunthorpe
Instead of bouncing the function call to the driver op through a blocking
notifier just have the iommu layer call it directly.

Register each device that is being attached to the iommu with the lower
driver which then threads them on a linked list and calls the appropriate
driver op at the right time.

Currently the only use is if dma_unmap() is defined.

Also, fully lock all the debugging tests on the pinning path that a
dma_unmap is registered.

Signed-off-by: Jason Gunthorpe 
---
 drivers/vfio/vfio.c |  42 -
 drivers/vfio/vfio.h |  14 ++---
 drivers/vfio/vfio_iommu_type1.c | 103 
 include/linux/vfio.h|   2 +-
 4 files changed, 83 insertions(+), 78 deletions(-)

diff --git a/drivers/vfio/vfio.c b/drivers/vfio/vfio.c
index f005b644ab9e69..065b57e601bff7 100644
--- a/drivers/vfio/vfio.c
+++ b/drivers/vfio/vfio.c
@@ -619,6 +619,9 @@ EXPORT_SYMBOL_GPL(vfio_register_group_dev);
  */
 int vfio_register_emulated_iommu_dev(struct vfio_device *device)
 {
+   if (WARN_ON(!device->ops->dma_unmap))
+   return -EINVAL;
+
return __vfio_register_dev(device,
vfio_noiommu_group_alloc(device->dev, VFIO_EMULATED_IOMMU));
 }
@@ -1077,17 +1080,6 @@ static void vfio_device_unassign_container(struct 
vfio_device *device)
up_write(>group->group_rwsem);
 }
 
-static int vfio_iommu_notifier(struct notifier_block *nb, unsigned long action,
-  void *data)
-{
-   struct vfio_device *vfio_device =
-   container_of(nb, struct vfio_device, iommu_nb);
-   struct vfio_iommu_type1_dma_unmap *unmap = data;
-
-   vfio_device->ops->dma_unmap(vfio_device, unmap->iova, unmap->size);
-   return NOTIFY_OK;
-}
-
 static struct file *vfio_device_open(struct vfio_device *device)
 {
struct vfio_iommu_driver *iommu_driver;
@@ -1123,15 +1115,9 @@ static struct file *vfio_device_open(struct vfio_device 
*device)
}
 
iommu_driver = device->group->container->iommu_driver;
-   if (device->ops->dma_unmap && iommu_driver &&
-   iommu_driver->ops->register_notifier) {
-   unsigned long events = VFIO_IOMMU_NOTIFY_DMA_UNMAP;
-
-   device->iommu_nb.notifier_call = vfio_iommu_notifier;
-   iommu_driver->ops->register_notifier(
-   device->group->container->iommu_data, ,
-   >iommu_nb);
-   }
+   if (iommu_driver && iommu_driver->ops->register_device)
+   iommu_driver->ops->register_device(
+   device->group->container->iommu_data, device);
 
up_read(>group->group_rwsem);
}
@@ -1171,11 +1157,9 @@ static struct file *vfio_device_open(struct vfio_device 
*device)
device->ops->close_device(device);
 
iommu_driver = device->group->container->iommu_driver;
-   if (device->ops->dma_unmap && iommu_driver &&
-   iommu_driver->ops->register_notifier)
-   iommu_driver->ops->unregister_notifier(
-   device->group->container->iommu_data,
-   >iommu_nb);
+   if (iommu_driver && iommu_driver->ops->register_device)
+   iommu_driver->ops->unregister_device(
+   device->group->container->iommu_data, device);
}
 err_undo_count:
device->open_count--;
@@ -1380,11 +1364,9 @@ static int vfio_device_fops_release(struct inode *inode, 
struct file *filep)
device->ops->close_device(device);
 
iommu_driver = device->group->container->iommu_driver;
-   if (device->ops->dma_unmap && iommu_driver &&
-   iommu_driver->ops->register_notifier)
-   iommu_driver->ops->unregister_notifier(
-   device->group->container->iommu_data,
-   >iommu_nb);
+   if (iommu_driver && iommu_driver->ops->unregister_device)
+   iommu_driver->ops->unregister_device(
+   device->group->container->iommu_data, device);
up_read(>group->group_rwsem);
device->open_count--;
if (device->open_count == 0)
diff --git a/drivers/vfio/vfio.h b/drivers/vfio/vfio.h
index cb2e4e9baa8fe8..4a7db1f3c33e7e 100644
--- a/drivers/vfio/vfio.h
+++ b/drivers/vfio/vfio.h
@@ -33,11 +33,6 @@ enum vfio_iommu_notify_type {
VFIO_IOMMU_CONTAINER_CLOSE = 0,
 };
 
-/* events for register_notifier() */
-enum {
-   VFIO_IOMMU_NOTIFY_DMA_UNMAP = 1,
-};
-
 /**
  * struct vfio_iommu_driver_ops - VFIO IOMMU driver callbacks
  */
@@ -60,11 +55,10 @@ struct vfio_iommu_driver_ops {
 unsigned long *phys_pfn);
int (*unpin_pages)(void *iommu_data,
   

Re: [Intel-gfx] [PATCH 32/33] drm/i915/guc: Implement GuC priority management

2022-06-07 Thread John Harrison

On 6/7/2022 06:58, Tvrtko Ursulin wrote:


A blast from the past..

On 27/07/2021 01:23, Matthew Brost wrote:

Implement a simple static mapping algorithm of the i915 priority levels
(int, -1k to 1k exposed to user) to the 4 GuC levels. Mapping is as
follows:

i915 level < 0  -> GuC low level (3)
i915 level == 0 -> GuC normal level  (2)
i915 level < INT_MAX    -> GuC high level    (1)
i915 level == INT_MAX   -> GuC highest level (0)

We believe this mapping should cover the UMD use cases (3 distinct user
levels + 1 kernel level).


I've noticed Vulkan has VK_EXT_global_priority and AFAICT Mesa 
implementation maps those priorities to i915 uapi:


    VK_QUEUE_GLOBAL_PRIORITY_LOW_KHR = -512
    VK_QUEUE_GLOBAL_PRIORITY_MEDIUM_KHR = 0
    VK_QUEUE_GLOBAL_PRIORITY_HIGH_KHR = +512
    VK_QUEUE_GLOBAL_PRIORITY_REALTIME_KHR = +1023

Wasn't aware of the REALTIME option. Does Mesa have that as well? Pretty 
sure it only had low/medium/high last I time looked but that was quite a 
while ago.



GuC as per this patch remaps to:

    VK_QUEUE_GLOBAL_PRIORITY_LOW_KHR = GUC_CLIENT_PRIORITY_NORMAL
    VK_QUEUE_GLOBAL_PRIORITY_MEDIUM_KHR = GUC_CLIENT_PRIORITY_KMD_NORMAL
    VK_QUEUE_GLOBAL_PRIORITY_HIGH_KHR = GUC_CLIENT_PRIORITY_HIGH
    VK_QUEUE_GLOBAL_PRIORITY_REALTIME_KHR = GUC_CLIENT_PRIORITY_HIGH

Last two being the same, so we lose one level. I don't think it is a 
problem according to VK spec, which is very loose, so considered fine 
for us and just unfortunate?
My recollection is that both Vulkan and Mesa describe the priority as 
merely a hint. The implementation is free to obey or ignore as it 
desires (or as it is capable). So while it would be good to support what 
we can, we don't actually fail any compatibility rules if we don't. And 
I think the idea was to reserve the highest priority for KMD only tasks 
such as the heartbeat.




Also, given drm/sched has three priorities - what is the plan to 
connect GuC's four into those three? I ask because I noticed the 
I guess the plan there is a straight 1:1 for low/medium/high. Matthew 
would be the person with more idea on the drm/scheduler, though.


fixed three levels does not really fit with some other drivers like 
msm for instance. There are up to four hardware priorities there and 
currently an odd mapping scheme is implemented. So I am getting a 
feeling drm/sched should rather be extended to allow more flexibility 
for drivers.


And finally a side question on this particular patch - shouldn't GuC 
map I915_PRIORITY_HEARTBEAT to GUC_CLIENT_PRIORITY_KMD_HIGH (highest)? 
I'd say yes - we certainly want heartbeats to preempt maximum user 
priority.
Hmm. Not sure what the point of the HEARTBEAT define is. The heartbeat 
pulse itself starts at minimum priority and then bumps upwards on each 
time period until it hits the max. So eventually, it will run at higher 
than maximum user priority. The HEARTBEAT prio itself seems to be the 
mid-point. So we don't want that to be super-high. It would even maybe 
make more sense for it to match NORMAL.


John.





Regards,

Tvrtko


In addition to static mapping, a simple counter system is attached to
each context tracking the number of requests inflight on the context at
each level. This is needed as the GuC levels are per context while in
the i915 levels are per request.

v2:
  (Daniele)
   - Add BUILD_BUG_ON to enforce ordering of priority levels
   - Add missing lockdep to guc_prio_fini
   - Check for return before setting context registered flag
   - Map DISPLAY priority or higher to highest guc prio
   - Update comment for guc_prio

Signed-off-by: Matthew Brost 
Cc: Daniele Ceraolo Spurio 
Reviewed-by: Daniele Ceraolo Spurio 
---
  drivers/gpu/drm/i915/gt/intel_breadcrumbs.c   |   3 +
  drivers/gpu/drm/i915/gt/intel_context_types.h |   9 +-
  drivers/gpu/drm/i915/gt/intel_engine_user.c   |   4 +
  .../gpu/drm/i915/gt/uc/intel_guc_submission.c | 212 +-
  drivers/gpu/drm/i915/i915_request.c   |   5 +
  drivers/gpu/drm/i915/i915_request.h   |   9 +
  drivers/gpu/drm/i915/i915_scheduler.c |   7 +
  drivers/gpu/drm/i915/i915_scheduler_types.h   |  12 +
  drivers/gpu/drm/i915/i915_trace.h |  17 +-
  include/uapi/drm/i915_drm.h   |   9 +
  10 files changed, 282 insertions(+), 5 deletions(-)

diff --git a/drivers/gpu/drm/i915/gt/intel_breadcrumbs.c 
b/drivers/gpu/drm/i915/gt/intel_breadcrumbs.c

index 2007dc6f6b99..209cf265bf74 100644
--- a/drivers/gpu/drm/i915/gt/intel_breadcrumbs.c
+++ b/drivers/gpu/drm/i915/gt/intel_breadcrumbs.c
@@ -245,6 +245,9 @@ static void signal_irq_work(struct irq_work *work)
  llist_entry(signal, typeof(*rq), signal_node);
  struct list_head cb_list;
  +    if (rq->engine->sched_engine->retire_inflight_request_prio)
+ rq->engine->sched_engine->retire_inflight_request_prio(rq);
+
  spin_lock(>lock);
  list_replace(>fence.cb_list, _list);
  

Re: [PATCH 1/2] vfio: Replace the DMA unmapping notifier with a callback

2022-06-07 Thread Jason Gunthorpe
On Tue, Jun 07, 2022 at 08:57:52AM -0300, Jason Gunthorpe wrote:
> On Tue, Jun 07, 2022 at 07:39:55AM +0200, Christoph Hellwig wrote:
> 
> > > +static int vfio_iommu_notifier(struct notifier_block *nb, unsigned long 
> > > action,
> > > +void *data)
> > > +{
> > > + struct vfio_device *vfio_device =
> > > + container_of(nb, struct vfio_device, iommu_nb);
> > > + struct vfio_iommu_type1_dma_unmap *unmap = data;
> > 
> > Using the iommu type 1 UAPI structure in the core vfio code for a
> > subset of its field is kinda weird.  But we can fix this later.
> 
> Ah, I did type this in at one point.. It was small lets include it in
> this patch

Oh I got this explanation mixed up - forgot about this vesitgual bit

The patch is split in two: this patch removes the
vfio_iommu_type1_dma_unmap from all the drivers but leaves the type1
code as-is and bridges it here, the next patch changes the type1 code
to direcly call the op and deletes this function. So this weirdness is
fully deleted by the end of the series.

Jason


Re: [PATCH] drm/i915/guc/slpc: Use non-blocking H2G for waitboost

2022-06-07 Thread Dixit, Ashutosh
On Sat, 14 May 2022 23:05:06 -0700, Vinay Belgaumkar wrote:
>
> SLPC min/max frequency updates require H2G calls. We are seeing
> timeouts when GuC channel is backed up and it is unable to respond
> in a timely fashion causing warnings and affecting CI.
>
> This is seen when waitboosting happens during a stress test.
> this patch updates the waitboost path to use a non-blocking
> H2G call instead, which returns as soon as the message is
> successfully transmitted.

Overall I think this patch is trying to paper over problems in the blocking
H2G CT interface (specifically the 1 second timeout in
wait_for_ct_request_update()). So I think we should address that problem in
the interface directly rather than having each client (SLPC and any future
client) work around the problem. Following points:

1. This patch seems to assume that it is 'ok' to ignore the return code
   from FW for a waitboost request (arguing waitboost is best effort so
   it's ok to 'fire and forget'). But the return code is still useful
   e.g. in cases where we see performance issues and want to go back and
   investigate if FW rejected any waitboost requests.

2. We are already seeing that a 1 second timeout is not sufficient. So why
   not simply increase that timeout?

3. In fact if we are saying that the CT interface is a "reliable" interface
   (implying no message loss), to ensure reliability that timeout should
   not simply be increased, it should be made "infinite" (in quotes).

4. Maybe it would have been best to not have a "blocking" H2G interface at
   all (with the wait in wait_for_ct_request_update()). Just have an
   asynchronous interface (which mirrors the actual interface between FW
   and i915) in which clients register callbacks which are invoked when FW
   responds. If this is too big a change we can probably continue with the
   current blocking interface after increasing the timeout as mentioned
   above.

5. Finally, the waitboost request is just the most likely to get stuck at
   the back of a full CT queue since it happens during normal
   operation. Actually any request, say one initiated from sysfs, can also
   get similarly stuck at the back of a full queue. So any solution should
   also address that situation (where the return code is needed and
   similarly for a future client of the "blocking" (REQUEST/RESPONSE)
   interface).

Thanks.
--
Ashutosh


Re: [PATCH] drm/i915/guc: Use drm_err instead of pr_err

2022-06-07 Thread Dixit, Ashutosh
On Tue, 07 Jun 2022 15:23:17 -0700, John Harrison wrote:
>
> On 6/7/2022 15:07, Dixit, Ashutosh wrote:
> > On Tue, 07 Jun 2022 14:51:03 -0700, john.c.harri...@intel.com wrote:
> >> From: John Harrison 
> >>
> >> Don't use pr_err in places where we have access to a struct_drm.
> > Seem to be many more pr_err's in selftests. Is there a reason why drm_err's
> > cannot be used in selftests (especially those using an i915 device)?
> > Thanks.
> I figured I'd start small and just do the gt/uc ones to being with as those
> are the ones that affect me.
>
> It sounds like the only reason to use pr_err is in the mock selftests where
> there is no easy access to a DRM structure. For everything else, there is
> no reason that I am aware of.

Fair enough:

Reviewed-by: Ashutosh Dixit 


Re: [PATCH] drm/i915/guc: Use drm_err instead of pr_err

2022-06-07 Thread John Harrison

On 6/7/2022 15:07, Dixit, Ashutosh wrote:

On Tue, 07 Jun 2022 14:51:03 -0700, john.c.harri...@intel.com wrote:

From: John Harrison 

Don't use pr_err in places where we have access to a struct_drm.

Seem to be many more pr_err's in selftests. Is there a reason why drm_err's
cannot be used in selftests (especially those using an i915 device)?
Thanks.
I figured I'd start small and just do the gt/uc ones to being with as 
those are the ones that affect me.


It sounds like the only reason to use pr_err is in the mock selftests 
where there is no easy access to a DRM structure. For everything else, 
there is no reason that I am aware of.


John.



Re: [PATCH] drm/i915/guc: Use drm_err instead of pr_err

2022-06-07 Thread Dixit, Ashutosh
On Tue, 07 Jun 2022 14:51:03 -0700, john.c.harri...@intel.com wrote:
>
> From: John Harrison 
>
> Don't use pr_err in places where we have access to a struct_drm.

Seem to be many more pr_err's in selftests. Is there a reason why drm_err's
cannot be used in selftests (especially those using an i915 device)?
Thanks.


[PATCH] drm/i915/guc: Use drm_err instead of pr_err

2022-06-07 Thread John . C . Harrison
From: John Harrison 

Don't use pr_err in places where we have access to a struct_drm.

Signed-off-by: John Harrison 
---
 drivers/gpu/drm/i915/gt/uc/intel_uc_fw.c  | 10 ++---
 drivers/gpu/drm/i915/gt/uc/selftest_guc.c | 38 +--
 .../drm/i915/gt/uc/selftest_guc_multi_lrc.c   | 10 ++---
 3 files changed, 29 insertions(+), 29 deletions(-)

diff --git a/drivers/gpu/drm/i915/gt/uc/intel_uc_fw.c 
b/drivers/gpu/drm/i915/gt/uc/intel_uc_fw.c
index 9361532726d6c..6d1b82da91bd9 100644
--- a/drivers/gpu/drm/i915/gt/uc/intel_uc_fw.c
+++ b/drivers/gpu/drm/i915/gt/uc/intel_uc_fw.c
@@ -186,11 +186,11 @@ __uc_fw_auto_select(struct drm_i915_private *i915, struct 
intel_uc_fw *uc_fw)
fw_blobs[i].rev < fw_blobs[i - 1].rev)
continue;
 
-   pr_err("invalid FW blob order: %s r%u comes before %s 
r%u\n",
-  intel_platform_name(fw_blobs[i - 1].p),
-  fw_blobs[i - 1].rev,
-  intel_platform_name(fw_blobs[i].p),
-  fw_blobs[i].rev);
+   drm_err(>drm, "invalid FW blob order: %s r%u 
comes before %s r%u\n",
+   intel_platform_name(fw_blobs[i - 1].p),
+   fw_blobs[i - 1].rev,
+   intel_platform_name(fw_blobs[i].p),
+   fw_blobs[i].rev);
 
uc_fw->path = NULL;
}
diff --git a/drivers/gpu/drm/i915/gt/uc/selftest_guc.c 
b/drivers/gpu/drm/i915/gt/uc/selftest_guc.c
index 1df71d0796aec..a720f0388e8ce 100644
--- a/drivers/gpu/drm/i915/gt/uc/selftest_guc.c
+++ b/drivers/gpu/drm/i915/gt/uc/selftest_guc.c
@@ -62,7 +62,7 @@ static int intel_guc_scrub_ctbs(void *arg)
ce = intel_context_create(engine);
if (IS_ERR(ce)) {
ret = PTR_ERR(ce);
-   pr_err("Failed to create context, %d: %d\n", i, ret);
+   drm_err(>i915->drm, "Failed to create context, %d: 
%d\n", i, ret);
goto err;
}
 
@@ -83,7 +83,7 @@ static int intel_guc_scrub_ctbs(void *arg)
 
if (IS_ERR(rq)) {
ret = PTR_ERR(rq);
-   pr_err("Failed to create request, %d: %d\n", i, ret);
+   drm_err(>i915->drm, "Failed to create request, %d: 
%d\n", i, ret);
goto err;
}
 
@@ -93,7 +93,7 @@ static int intel_guc_scrub_ctbs(void *arg)
for (i = 0; i < 3; ++i) {
ret = i915_request_wait(last[i], 0, HZ);
if (ret < 0) {
-   pr_err("Last request failed to complete: %d\n", ret);
+   drm_err(>i915->drm, "Last request failed to 
complete: %d\n", ret);
goto err;
}
i915_request_put(last[i]);
@@ -110,7 +110,7 @@ static int intel_guc_scrub_ctbs(void *arg)
/* GT will not idle if G2H are lost */
ret = intel_gt_wait_for_idle(gt, HZ);
if (ret < 0) {
-   pr_err("GT failed to idle: %d\n", ret);
+   drm_err(>i915->drm, "GT failed to idle: %d\n", ret);
goto err;
}
 
@@ -150,7 +150,7 @@ static int intel_guc_steal_guc_ids(void *arg)
 
ce = kcalloc(GUC_MAX_CONTEXT_ID, sizeof(*ce), GFP_KERNEL);
if (!ce) {
-   pr_err("Context array allocation failed\n");
+   drm_err(>i915->drm, "Context array allocation failed\n");
return -ENOMEM;
}
 
@@ -164,24 +164,24 @@ static int intel_guc_steal_guc_ids(void *arg)
if (IS_ERR(ce[context_index])) {
ret = PTR_ERR(ce[context_index]);
ce[context_index] = NULL;
-   pr_err("Failed to create context: %d\n", ret);
+   drm_err(>i915->drm, "Failed to create context: %d\n", ret);
goto err_wakeref;
}
ret = igt_spinner_init(, engine->gt);
if (ret) {
-   pr_err("Failed to create spinner: %d\n", ret);
+   drm_err(>i915->drm, "Failed to create spinner: %d\n", ret);
goto err_contexts;
}
spin_rq = igt_spinner_create_request(, ce[context_index],
 MI_ARB_CHECK);
if (IS_ERR(spin_rq)) {
ret = PTR_ERR(spin_rq);
-   pr_err("Failed to create spinner request: %d\n", ret);
+   drm_err(>i915->drm, "Failed to create spinner request: 
%d\n", ret);
goto err_contexts;
}
ret = request_add_spin(spin_rq, );
if (ret) {
-   pr_err("Failed to add Spinner request: %d\n", ret);
+   drm_err(>i915->drm, "Failed to add Spinner request: %d\n", 
ret);
goto err_spin_rq;
}
 
@@ -191,7 +191,7 @@ static int 

[PATCH 1/4] backlight: aat2870: Use backlight helper

2022-06-07 Thread Stephen Kitt
Instead of retrieving the backlight brightness in struct
backlight_properties manually, and then checking whether the backlight
should be on at all, use backlight_get_brightness() which does all
this and insulates this from future changes.

Signed-off-by: Stephen Kitt 
Cc: Lee Jones 
Cc: Daniel Thompson 
Cc: Jingoo Han 
Cc: Helge Deller 
Cc: dri-devel@lists.freedesktop.org
Cc: linux-fb...@vger.kernel.org
---
 drivers/video/backlight/aat2870_bl.c | 7 +--
 1 file changed, 1 insertion(+), 6 deletions(-)

diff --git a/drivers/video/backlight/aat2870_bl.c 
b/drivers/video/backlight/aat2870_bl.c
index a7af9adafad6..1cbb303e9c88 100644
--- a/drivers/video/backlight/aat2870_bl.c
+++ b/drivers/video/backlight/aat2870_bl.c
@@ -59,7 +59,7 @@ static int aat2870_bl_update_status(struct backlight_device 
*bd)
struct aat2870_bl_driver_data *aat2870_bl = bl_get_data(bd);
struct aat2870_data *aat2870 =
dev_get_drvdata(aat2870_bl->pdev->dev.parent);
-   int brightness = bd->props.brightness;
+   int brightness = backlight_get_brightness(bd);
int ret;
 
if ((brightness < 0) || (bd->props.max_brightness < brightness)) {
@@ -70,11 +70,6 @@ static int aat2870_bl_update_status(struct backlight_device 
*bd)
dev_dbg(>dev, "brightness=%d, power=%d, state=%d\n",
 bd->props.brightness, bd->props.power, bd->props.state);
 
-   if ((bd->props.power != FB_BLANK_UNBLANK) ||
-   (bd->props.state & BL_CORE_FBBLANK) ||
-   (bd->props.state & BL_CORE_SUSPENDED))
-   brightness = 0;
-
ret = aat2870->write(aat2870, AAT2870_BLM,
 (u8)aat2870_brightness(aat2870_bl, brightness));
if (ret < 0)
-- 
2.30.2



Re: [Intel-gfx] [RFC v3 1/3] drm/doc/rfc: VM_BIND feature design document

2022-06-07 Thread Niranjana Vishwanathapura

On Tue, Jun 07, 2022 at 11:18:11AM -0700, Niranjana Vishwanathapura wrote:

On Tue, Jun 07, 2022 at 12:12:03PM -0500, Jason Ekstrand wrote:

 On Fri, Jun 3, 2022 at 6:52 PM Niranjana Vishwanathapura
  wrote:

   On Fri, Jun 03, 2022 at 10:20:25AM +0300, Lionel Landwerlin wrote:
   >   On 02/06/2022 23:35, Jason Ekstrand wrote:
   >
   > On Thu, Jun 2, 2022 at 3:11 PM Niranjana Vishwanathapura
   >  wrote:
   >
   >   On Wed, Jun 01, 2022 at 01:28:36PM -0700, Matthew Brost wrote:
   >   >On Wed, Jun 01, 2022 at 05:25:49PM +0300, Lionel Landwerlin
   wrote:
   >   >> On 17/05/2022 21:32, Niranjana Vishwanathapura wrote:
   >   >> > +VM_BIND/UNBIND ioctl will immediately start
   binding/unbinding
   >   the mapping in an
   >   >> > +async worker. The binding and unbinding will work like a
   special
   >   GPU engine.
   >   >> > +The binding and unbinding operations are serialized and
   will
   >   wait on specified
   >   >> > +input fences before the operation and will signal the
   output
   >   fences upon the
   >   >> > +completion of the operation. Due to serialization,
   completion of
   >   an operation
   >   >> > +will also indicate that all previous operations are also
   >   complete.
   >   >>
   >   >> I guess we should avoid saying "will immediately start
   >   binding/unbinding" if
   >   >> there are fences involved.
   >   >>
   >   >> And the fact that it's happening in an async worker seem to
   imply
   >   it's not
   >   >> immediate.
   >   >>
   >
   >   Ok, will fix.
   >   This was added because in earlier design binding was deferred
   until
   >   next execbuff.
   >   But now it is non-deferred (immediate in that sense). But yah,
   this is
   >   confusing
   >   and will fix it.
   >
   >   >>
   >   >> I have a question on the behavior of the bind operation when
   no
   >   input fence
   >   >> is provided. Let say I do :
   >   >>
   >   >> VM_BIND (out_fence=fence1)
   >   >>
   >   >> VM_BIND (out_fence=fence2)
   >   >>
   >   >> VM_BIND (out_fence=fence3)
   >   >>
   >   >>
   >   >> In what order are the fences going to be signaled?
   >   >>
   >   >> In the order of VM_BIND ioctls? Or out of order?
   >   >>
   >   >> Because you wrote "serialized I assume it's : in order
   >   >>
   >
   >   Yes, in the order of VM_BIND/UNBIND ioctls. Note that bind and
   unbind
   >   will use
   >   the same queue and hence are ordered.
   >
   >   >>
   >   >> One thing I didn't realize is that because we only get one
   >   "VM_BIND" engine,
   >   >> there is a disconnect from the Vulkan specification.
   >   >>
   >   >> In Vulkan VM_BIND operations are serialized but per engine.
   >   >>
   >   >> So you could have something like this :
   >   >>
   >   >> VM_BIND (engine=rcs0, in_fence=fence1, out_fence=fence2)
   >   >>
   >   >> VM_BIND (engine=ccs0, in_fence=fence3, out_fence=fence4)
   >   >>
   >   >>
   >   >> fence1 is not signaled
   >   >>
   >   >> fence3 is signaled
   >   >>
   >   >> So the second VM_BIND will proceed before the first VM_BIND.
   >   >>
   >   >>
   >   >> I guess we can deal with that scenario in userspace by doing
   the
   >   wait
   >   >> ourselves in one thread per engines.
   >   >>
   >   >> But then it makes the VM_BIND input fences useless.
   >   >>
   >   >>
   >   >> Daniel : what do you think? Should be rework this or just
   deal with
   >   wait
   >   >> fences in userspace?
   >   >>
   >   >
   >   >My opinion is rework this but make the ordering via an engine
   param
   >   optional.
   >   >
   >   >e.g. A VM can be configured so all binds are ordered within the
   VM
   >   >
   >   >e.g. A VM can be configured so all binds accept an engine
   argument
   >   (in
   >   >the case of the i915 likely this is a gem context handle) and
   binds
   >   >ordered with respect to that engine.
   >   >
   >   >This gives UMDs options as the later likely consumes more KMD
   >   resources
   >   >so if a different UMD can live with binds being ordered within
   the VM
   >   >they can use a mode consuming less resources.
   >   >
   >
   >   I think we need to be careful here if we are looking for some
   out of
   >   (submission) order completion of vm_bind/unbind.
   >   In-order completion means, in a batch of binds and unbinds to be
   >   completed in-order, user only needs to specify in-fence for the
   >   first bind/unbind call and the our-fence for the last
   bind/unbind
   >   call. Also, the VA released by an unbind call can be re-used by
   >   any subsequent bind call in that 

[PATCH RESEND] drm: adv7511: override i2c address of cec before accessing it

2022-06-07 Thread Antonio Borneo
Commit 680532c50bca ("drm: adv7511: Add support for
i2c_new_secondary_device") allows a device tree node to override
the default addresses of the secondary i2c devices. This is useful
for solving address conflicts on the i2c bus.

In adv7511_init_cec_regmap() the new i2c address of cec device is
read from device tree and immediately accessed, well before it is
written in the proper register to override the default address.
This can cause an i2c error during probe and a consequent probe
failure.

Once the new i2c address is read from the device tree, override
the default address before any attempt to access the cec.

Tested with adv7533 and stm32mp157f.

Signed-off-by: Antonio Borneo 
Fixes: 680532c50bca ("drm: adv7511: Add support for i2c_new_secondary_device")
Reviewed-by: Kieran Bingham 

---

This patch got somehow lost, I'm resending it.
Added reviewed by Kieran Bingham.
Rebased on drm-misc-next.

---
 drivers/gpu/drm/bridge/adv7511/adv7511_drv.c | 7 ---
 1 file changed, 4 insertions(+), 3 deletions(-)

diff --git a/drivers/gpu/drm/bridge/adv7511/adv7511_drv.c 
b/drivers/gpu/drm/bridge/adv7511/adv7511_drv.c
index 5bb9300040dd..074c2e650cae 100644
--- a/drivers/gpu/drm/bridge/adv7511/adv7511_drv.c
+++ b/drivers/gpu/drm/bridge/adv7511/adv7511_drv.c
@@ -1065,6 +1065,10 @@ static int adv7511_init_cec_regmap(struct adv7511 *adv)
ADV7511_CEC_I2C_ADDR_DEFAULT);
if (IS_ERR(adv->i2c_cec))
return PTR_ERR(adv->i2c_cec);
+
+   regmap_write(adv->regmap, ADV7511_REG_CEC_I2C_ADDR,
+adv->i2c_cec->addr << 1);
+
i2c_set_clientdata(adv->i2c_cec, adv);
 
adv->regmap_cec = devm_regmap_init_i2c(adv->i2c_cec,
@@ -1271,9 +1275,6 @@ static int adv7511_probe(struct i2c_client *i2c, const 
struct i2c_device_id *id)
if (ret)
goto err_i2c_unregister_packet;
 
-   regmap_write(adv7511->regmap, ADV7511_REG_CEC_I2C_ADDR,
-adv7511->i2c_cec->addr << 1);
-
INIT_WORK(>hpd_work, adv7511_hpd_work);
 
if (i2c->irq) {

base-commit: dfa687bffc8a4a21ed929c7dececf01b8f1f52ee
-- 
2.36.1



Re: [Freedreno] [PATCH] drm/msm: Switch ordering of runpm put vs devfreq_idle

2022-06-07 Thread Rob Clark
On Tue, Sep 28, 2021 at 7:52 AM Akhil P Oommen  wrote:
>
> On 9/27/2021 8:59 PM, Rob Clark wrote:
> > From: Rob Clark 
> >
> > I've seen a few crashes like:
> >
> >  Internal error: synchronous external abort: 9610 [#1] PREEMPT SMP
> >  Modules linked in: snd_seq_dummy snd_seq snd_seq_device bridge stp llc 
> > tun nf_nat_tftp nf_conntrack_tftp nf_nat_ftp nf_conntrack_ftp esp6 ah6 
> > ip6t_REJECT ip6t_ipv6header vhost_vsock vhost 
> > vmw_vsock_virtio_transport_common vsock rfcomm algif_hash algif_skcipher 
> > af_alg uinput veth xt_cgroup xt_MASQUERADE venus_enc venus_dec 
> > videobuf2_dma_contig qcom_spmi_adc5 qcom_spmi_adc_tm5 hci_uart 
> > qcom_vadc_common cros_ec_typec qcom_spmi_temp_alarm typec btqca 
> > snd_soc_rt5682_i2c snd_soc_rt5682 snd_soc_sc7180 bluetooth 
> > snd_soc_qcom_common snd_soc_rl6231 ecdh_generic ecc venus_core v4l2_mem2mem 
> > snd_soc_lpass_sc7180 snd_soc_lpass_hdmi snd_soc_lpass_cpu 
> > snd_soc_lpass_platform snd_soc_max98357a ip6table_nat fuse iio_trig_sysfs 
> > cros_ec_lid_angle cros_ec_sensors cros_ec_sensors_core 
> > industrialio_triggered_buffer kfifo_buf cros_ec_sensorhub lzo_rle 
> > ath10k_snoc lzo_compress ath10k_core ath zram mac80211 cfg80211 
> > ax88179_178a usbnet mii uvcvideo videobuf2_vmalloc joydev
> >  CPU: 3 PID: 212 Comm: A618-worker Tainted: G W 
> > 5.4.139-16300-g88d8e1285982 #1
> >  Hardware name: Google Pompom (rev1) with LTE (DT)
> >  pstate: 60c9 (nZCv daif +PAN +UAO)
> >  pc : a6xx_gmu_set_oob+0x114/0x200
> >  lr : a6xx_gmu_set_oob+0x10c/0x200
> >  sp : ffc011b7bc20
> >  x29: ffc011b7bc20 x28: ffdad27c5000
> >  x27: 0001 x26: ffdad1521044
> >  x25: ffbef7498338 x24: 0018
> >  x23: 0002 x22: 00014648
> >  x21: 033732fe638b x20: 8000
> >  x19: ffbef7433bc8 x18: 4000
> >  x17: 00243508d982 x16: b67e
> >  x15: 90d4 x14: 0024
> >  x13: 0024 x12: 00017521
> >  x11: 0b48 x10: 00326a48
> >  x9 : 1a130d33f6371600 x8 : ffc011e54648
> >  x7 : 614948e5003c x6 : ffbe3cd17e60
> >  x5 : 0040 x4 : 0004
> >  x3 :  x2 : ffbef7488000
> >  x1 : ffbef7488000 x0 : 
> >  Call trace:
> >  a6xx_gmu_set_oob+0x114/0x200
> >  a6xx_gmu_set_freq+0xe0/0x1fc
> >  msm_devfreq_target+0x80/0x13c
> >  msm_devfreq_idle+0x54/0x94
> >  retire_submit+0x170/0x254
> >  retire_submits+0xa4/0xdc
> >  retire_worker+0x1c/0x28
> >  kthread_worker_fn+0xf4/0x1bc
> >  kthread+0x140/0x158
> >  ret_from_fork+0x10/0x18
> >  Code: 52800c81 9415bbe5 f9400a68 8b160108 (b9400108)
> >  ---[ end trace 16b871df2482cd61 ]---
> >  Kernel panic - not syncing: Fatal exception
> >  SMP: stopping secondary CPUs
> >  Kernel Offset: 0x1ac140 from 0xffc01000
> >  PHYS_OFFSET: 0xffc28000
> >  CPU features: 0x88102e,2a80aa38
> >  Memory Limit: none
> >
> > Which smells a lot like touching hw after power collapse.  I'm not
> > *entirely* sure how it could have taken 66ms (the autosuspend delay)
> > before we get to a6xx_gmu_set_oob(), but to be safe we should move
> > the pm_runtime_put_autosuspend() after msm_devfreq_idle().
> https://elixir.bootlin.com/linux/v5.15-rc1/source/drivers/gpu/drm/msm/adreno/a6xx_gmu.c#L132
> We have this check in the gmu freq set path which should avoid this
> scenario. I might be a bit pedantic here, but I feel that the original
> code is more accurate. We should immediately mark last busy and put
> runtime_pm refcount.

So, I've been doing some experiments, changing the _put_autosuspend()
to _put_sync(), in the course of tracking down some remaining "GMU
OOB" timeout type issues and related badness, and discovered things
very quickly die with SError splats like below.  Possibly the issue is
that runpm has some race conditions, but I'm not sure we can trust
pm_runtime_get_if_in_use() quite as much as one would like..

---
[   33.225332] CPU: 0 PID: 216 Comm: A618-worker Tainted: GW
  5.4.196 #7
[   33.225337] Hardware name: Google Wormdingler rev1+ INX panel board (DT)
[   33.225343] pstate: 20c9 (nzCv daif +PAN +UAO)
[   33.225353] pc : msm_readl+0x14/0x34
[   33.225361] lr : a6xx_gpu_busy+0x40/0x80
[   33.225365] sp : ffc011b93ad0
[   33.225371] x29: ffc011b93ad0 x28: ffe77cba3000
[   33.225377] x27: 0001 x26: ffe77bb4c4ac
[   33.225384] x25: ffa2f227dfa0 x24: ffa2f22aab28
[   33.225390] x23:  x22: ffa2f22bf020
[   33.225397] x21: ffa2f22bf000 x20: ffc011b93b10
[   33.225404] x19: ffc011bd4110 x18: 000e
[   33.225410] x17: 0004 x16: 000c
[   33.225416] x15: 01be3a969450 x14: 0400
[   33.225423] x13: 

Re: [Intel-gfx] [RFC v3 3/3] drm/doc/rfc: VM_BIND uapi definition

2022-06-07 Thread Niranjana Vishwanathapura

On Tue, Jun 07, 2022 at 11:42:08AM +0100, Tvrtko Ursulin wrote:


On 03/06/2022 07:53, Niranjana Vishwanathapura wrote:

On Wed, Jun 01, 2022 at 10:08:35PM -0700, Niranjana Vishwanathapura wrote:

On Wed, Jun 01, 2022 at 11:27:17AM +0200, Daniel Vetter wrote:

On Wed, 1 Jun 2022 at 11:03, Dave Airlie  wrote:


On Tue, 24 May 2022 at 05:20, Niranjana Vishwanathapura
 wrote:


On Thu, May 19, 2022 at 04:07:30PM -0700, Zanoni, Paulo R wrote:

On Tue, 2022-05-17 at 11:32 -0700, Niranjana Vishwanathapura wrote:

VM_BIND and related uapi definitions

v2: Ensure proper kernel-doc formatting with cross references.
 Also add new uapi and documentation as per review comments
 from Daniel.

Signed-off-by: Niranjana Vishwanathapura 



---
  Documentation/gpu/rfc/i915_vm_bind.h | 399 

+++

  1 file changed, 399 insertions(+)
  create mode 100644 Documentation/gpu/rfc/i915_vm_bind.h

diff --git a/Documentation/gpu/rfc/i915_vm_bind.h 

b/Documentation/gpu/rfc/i915_vm_bind.h

new file mode 100644
index ..589c0a009107
--- /dev/null
+++ b/Documentation/gpu/rfc/i915_vm_bind.h
@@ -0,0 +1,399 @@
+/* SPDX-License-Identifier: MIT */
+/*
+ * Copyright © 2022 Intel Corporation
+ */
+
+/**
+ * DOC: I915_PARAM_HAS_VM_BIND
+ *
+ * VM_BIND feature availability.
+ * See typedef drm_i915_getparam_t param.
+ */
+#define I915_PARAM_HAS_VM_BIND   57
+
+/**
+ * DOC: I915_VM_CREATE_FLAGS_USE_VM_BIND
+ *
+ * Flag to opt-in for VM_BIND mode of binding during VM creation.
+ * See struct drm_i915_gem_vm_control flags.
+ *
+ * A VM in VM_BIND mode will not support the older 

execbuff mode of binding.
+ * In VM_BIND mode, execbuff ioctl will not accept any 

execlist (ie., the

+ * _i915_gem_execbuffer2.buffer_count must be 0).
+ * Also, _i915_gem_execbuffer2.batch_start_offset and
+ * _i915_gem_execbuffer2.batch_len must be 0.
+ * DRM_I915_GEM_EXECBUFFER_EXT_BATCH_ADDRESSES extension 

must be provided

+ * to pass in the batch buffer addresses.
+ *
+ * Additionally, I915_EXEC_NO_RELOC, I915_EXEC_HANDLE_LUT and
+ * I915_EXEC_BATCH_FIRST of 

_i915_gem_execbuffer2.flags must be 0
+ * (not used) in VM_BIND mode. I915_EXEC_USE_EXTENSIONS 

flag must always be

+ * set (See struct drm_i915_gem_execbuffer_ext_batch_addresses).
+ * The buffers_ptr, buffer_count, batch_start_offset and 

batch_len fields
+ * of struct drm_i915_gem_execbuffer2 are also not used 

and must be 0.

+ */


From that description, it seems we have:

struct drm_i915_gem_execbuffer2 {
    __u64 buffers_ptr;  -> must be 0 (new)
    __u32 buffer_count; -> must be 0 (new)
    __u32 batch_start_offset;   -> must be 0 (new)
    __u32 batch_len;    -> must be 0 (new)
    __u32 DR1;  -> must be 0 (old)
    __u32 DR4;  -> must be 0 (old)
    __u32 num_cliprects; (fences)   -> must be 0 since 

using extensions
    __u64 cliprects_ptr; (fences, extensions) -> 

contains an actual pointer!

    __u64 flags;    -> some flags must be 0 (new)
    __u64 rsvd1; (context info) -> repurposed field (old)
    __u64 rsvd2;    -> unused
};

Based on that, why can't we just get drm_i915_gem_execbuffer3 instead
of adding even more complexity to an already abused interface? While
the Vulkan-like extension thing is really nice, I don't think what
we're doing here is extending the ioctl usage, we're completely
changing how the base struct should be interpreted based on 

how the VM

was created (which is an entirely different ioctl).

From Rusty Russel's API Design grading, drm_i915_gem_execbuffer2 is
already at -6 without these changes. I think after vm_bind we'll need
to create a -11 entry just to deal with this ioctl.



The only change here is removing the execlist support for VM_BIND
mode (other than natual extensions).
Adding a new execbuffer3 was considered, but I think we need 
to be careful
with that as that goes beyond the VM_BIND support, including 
any future

requirements (as we don't want an execbuffer4 after VM_BIND).


Why not? it's not like adding extensions here is really that different
than adding new ioctls.

I definitely think this deserves an execbuffer3 without even
considering future requirements. Just  to burn down the old
requirements and pointless fields.

Make execbuffer3 be vm bind only, no relocs, no legacy bits, leave the
older sw on execbuf2 for ever.


I guess another point in favour of execbuf3 would be that it's less
midlayer. If we share the entry point then there's quite a few vfuncs
needed to cleanly split out the vm_bind paths from the legacy
reloc/softping paths.

If we invert this and do execbuf3, then there's the existing ioctl
vfunc, and then we share code (where it even makes sense, probably
request setup/submit need to be shared, anything else is probably
cleaner to just copypaste) with the usual helper approach.

Also that would guarantee 

Re: [PATCH] drm/bridge: parade-ps8622: Use backlight helper

2022-06-07 Thread Stephen Kitt
On Tue,  7 Jun 2022 20:10:22 +0200, Stephen Kitt  wrote:
> backlight_properties.fb_blank is deprecated. The states it represents
> are handled by other properties; but instead of accessing those
> properties directly, drivers should use the helpers provided by
> backlight.h.

Apologies for the misleading boilerplate, this patch came about as a result
of cleaning up fb_blank usage but doesn't involve fb_blank itself.

> Instead of retrieving the backlight brightness in struct
> backlight_properties manually, and then checking whether the backlight
> should be on at all, use backlight_get_brightness() which does all
> this and insulates this from future changes.
> 
> Signed-off-by: Stephen Kitt 
> Cc: Andrzej Hajda 
> Cc: Neil Armstrong 
> Cc: Robert Foss 
> Cc: Laurent Pinchart 
> Cc: Jonas Karlman 
> Cc: Jernej Skrabec 
> Cc: David Airlie 
> Cc: Daniel Vetter 
> Cc: dri-devel@lists.freedesktop.org
> ---
>  drivers/gpu/drm/bridge/parade-ps8622.c | 6 +-
>  1 file changed, 1 insertion(+), 5 deletions(-)
> 
> diff --git a/drivers/gpu/drm/bridge/parade-ps8622.c
> b/drivers/gpu/drm/bridge/parade-ps8622.c index 37b308850b4e..b5750e5f71d7
> 100644 --- a/drivers/gpu/drm/bridge/parade-ps8622.c
> +++ b/drivers/gpu/drm/bridge/parade-ps8622.c
> @@ -324,11 +324,7 @@ static int ps8622_send_config(struct ps8622_bridge
> *ps8622) static int ps8622_backlight_update(struct backlight_device *bl)
>  {
>   struct ps8622_bridge *ps8622 = dev_get_drvdata(>dev);
> - int ret, brightness = bl->props.brightness;
> -
> - if (bl->props.power != FB_BLANK_UNBLANK ||
> - bl->props.state & (BL_CORE_SUSPENDED | BL_CORE_FBBLANK))
> - brightness = 0;
> + int ret, brightness = backlight_get_brightness(bl);
>  
>   if (!ps8622->enabled)
>   return -EINVAL;
> 
> base-commit: f2906aa863381afb0015a9eb7fefad885d4e5a56
> -- 
> 2.30.2
> 


pgpReenX1czvs.pgp
Description: OpenPGP digital signature


Re: [PATCH] drm: shmobile: Use backlight helper

2022-06-07 Thread Stephen Kitt
On Tue,  7 Jun 2022 20:31:32 +0200, Stephen Kitt  wrote:
> backlight_properties.fb_blank is deprecated. The states it represents
> are handled by other properties; but instead of accessing those
> properties directly, drivers should use the helpers provided by
> backlight.h.

Apologies for the misleading boilerplate, this patch came about as a result
of cleaning up fb_blank usage but doesn't involve fb_blank itself.

> Instead of retrieving the backlight brightness in struct
> backlight_properties manually, and then checking whether the backlight
> should be on at all, use backlight_get_brightness() which does all
> this and insulates this from future changes.
> 
> Signed-off-by: Stephen Kitt 
> Cc: Laurent Pinchart 
> Cc: Kieran Bingham 
> Cc: David Airlie 
> Cc: Daniel Vetter 
> Cc: dri-devel@lists.freedesktop.org
> ---
>  drivers/gpu/drm/shmobile/shmob_drm_backlight.c | 6 +-
>  1 file changed, 1 insertion(+), 5 deletions(-)
> 
> diff --git a/drivers/gpu/drm/shmobile/shmob_drm_backlight.c
> b/drivers/gpu/drm/shmobile/shmob_drm_backlight.c index
> f6628a5ee95f..794573badfe8 100644 ---
> a/drivers/gpu/drm/shmobile/shmob_drm_backlight.c +++
> b/drivers/gpu/drm/shmobile/shmob_drm_backlight.c @@ -18,11 +18,7 @@ static
> int shmob_drm_backlight_update(struct backlight_device *bdev) struct
> shmob_drm_connector *scon = bl_get_data(bdev); struct shmob_drm_device
> *sdev = scon->connector.dev->dev_private; const struct
> shmob_drm_backlight_data *bdata = >pdata->backlight;
> - int brightness = bdev->props.brightness;
> -
> - if (bdev->props.power != FB_BLANK_UNBLANK ||
> - bdev->props.state & BL_CORE_SUSPENDED)
> - brightness = 0;
> + int brightness = backlight_get_brightness(bdev);
>  
>   return bdata->set_brightness(brightness);
>  }
> 
> base-commit: f2906aa863381afb0015a9eb7fefad885d4e5a56
> -- 
> 2.30.2
> 


pgpOJsUpNezJt.pgp
Description: OpenPGP digital signature


Re: [PATCH 0/2] Improve vfio-pci primary GPU assignment behavior

2022-06-07 Thread Alex Williamson
On Tue, 7 Jun 2022 19:40:40 +0200
Javier Martinez Canillas  wrote:

> Hello Alex,
> 
> On 6/6/22 19:53, Alex Williamson wrote:
> > Users attempting to enable vfio PCI device assignment with a GPU will
> > often block the default PCI driver from the device to avoid conflicts
> > with the device initialization or release path.  This means that
> > vfio-pci is sometimes the first PCI driver to bind to the device.  In 
> > the case of assigning the primary graphics device, low-level console
> > drivers may still generate resource conflicts.  Users often employ
> > kernel command line arguments to disable conflicting drivers or
> > perform unbinding in userspace to avoid this, but the actual solution
> > is often distribution/kernel config specific based on the included
> > drivers.
> > 
> > We can instead allow vfio-pci to copy the behavior of
> > drm_aperture_remove_conflicting_pci_framebuffers() in order to remove
> > these low-level drivers with conflicting resources.  vfio-pci is not
> > however a DRM driver, nor does vfio-pci depend on DRM config options,
> > thus we split out and export the necessary DRM apterture support and
> > mirror the framebuffer and VGA support.
> > 
> > I'd be happy to pull this series in through the vfio branch if
> > approved by the DRM maintainers.  Thanks,
> >  
> 
> I understand your issue but I really don't think that using this helper
> is the correct thing to do. We already have some races with the current
> aperture infrastructure As an example you can look at [0].
> 
> The agreement on the mentioned thread is that we want to unify the fbdev
> and DRM drivers apertures into a single list, and ideally moving all to
> the Linux device model to handle the removal of conflicting devices.
> 
> That's why I don't feel that leaking the DRM aperture helper to another
> is desirable since it would make even harder to cleanup this later.

OTOH, this doesn't really make the problem worse and it identifies
another stakeholder to a full solution.
 
> But also, this issue isn't something that only affects graphic devices,
> right? AFAIU from [1] and [2], the same issue happens if a PCI device
> has to be bound to vfio-pci but already was bound to a host driver.

When we're shuffling between PCI drivers, we expect the unbind of the
previous driver to have released all the claimed resources.  If there
were a previously attached PCI graphics driver, then the code added in
patch 2/ is simply redundant since that PCI graphics driver must have
already performed similar actions.  The primary use case of this series
is where there is no previous PCI graphics driver and we have no
visibility to platform drivers carving chunks of the PCI resources into
different subsystems.  AFAIK, this is unique to graphics devices.

> The fact that DRM happens to have some infrastructure to remove devices
> that conflict with an aperture is just a coincidence. Since this is used
> to remove devices bound to drivers that make use of the firmware-provided
> system framebuffer.

It seems not so much a coincidence as an artifact of the exact problem
both PCI graphics drivers and now vfio-pci face.  We've created
platform devices to manage sub-ranges of resources, where the actual
parent of those resources is only discovered later and we don't
automatically resolve the resource conflict between that parent device
and these platform devices when binding the parent driver.
 
> The series [0] mentioned above, adds a sysfb_disable() that disables the
> Generic System Framebuffer logic that is what registers the framebuffer
> devices that are bound to these generic video drivers. On disable, the
> devices registered by sysfb are also unregistered.
> 
> Would be enough for your use case to use that helper function if it lands
> or do you really need to look at the apertures? That is, do you want to
> remove the {vesa,efi,simple}fb and simpledrm drivers or is there a need
> to also remove real fbdev and DRM drivers?

It's not clear to me how this helps.  I infer that sysfb_disable() is
intended to be used by, for example, a PCI console driver which would be
taking over the console and can therefore make a clear decision to end
sysfb support.  The vfio-pci driver is not a console driver so we can't
make any sort of blind assertion regarding sysfb.  We might be binding
to a secondary graphics card which has no sysfb drivers attached.  I'm
a lot more comfortable wielding an interface that intends to disable
drivers/devices relative to the resources of a given device rather than
a blanket means to disable a subsystem.

I wonder if the race issues aren't better solved by avoiding to create
platform devices exposing resource conflicts with known devices,
especially when those existing devices have drivers attached.  Thanks,

Alex



Re: [PATCH 1/1] drm/panfrost: Add support for devcoredump

2022-06-07 Thread Adrián Larumbe
On 18.05.2022 13:54, Rob Clark wrote:
> On Tue, May 17, 2022 at 10:42 AM Adrián Larumbe
>  wrote:
> >
> > In the event of a job timeout, debug dump information will be written into
> > /sys/class/devcoredump.
> >
> > Inspired by etnaviv's similar feature.
> >
> > Signed-off-by: Adrián Larumbe 
> > ---
> >  drivers/gpu/drm/panfrost/Kconfig |   1 +
> >  drivers/gpu/drm/panfrost/Makefile|   3 +-
> >  drivers/gpu/drm/panfrost/panfrost_dump.c | 198 +++
> >  drivers/gpu/drm/panfrost/panfrost_dump.h |  12 ++
> >  drivers/gpu/drm/panfrost/panfrost_job.c  |   3 +
> >  include/uapi/drm/panfrost_drm.h  |  32 
> >  6 files changed, 248 insertions(+), 1 deletion(-)
> >  create mode 100644 drivers/gpu/drm/panfrost/panfrost_dump.c
> >  create mode 100644 drivers/gpu/drm/panfrost/panfrost_dump.h
> >
> > diff --git a/drivers/gpu/drm/panfrost/Kconfig 
> > b/drivers/gpu/drm/panfrost/Kconfig
> > index 86cdc0ce79e6..079600328be1 100644
> > --- a/drivers/gpu/drm/panfrost/Kconfig
> > +++ b/drivers/gpu/drm/panfrost/Kconfig
> > @@ -11,6 +11,7 @@ config DRM_PANFROST
> > select DRM_GEM_SHMEM_HELPER
> > select PM_DEVFREQ
> > select DEVFREQ_GOV_SIMPLE_ONDEMAND
> > +   select WANT_DEV_COREDUMP
> > help
> >   DRM driver for ARM Mali Midgard (T6xx, T7xx, T8xx) and
> >   Bifrost (G3x, G5x, G7x) GPUs.
> > diff --git a/drivers/gpu/drm/panfrost/Makefile 
> > b/drivers/gpu/drm/panfrost/Makefile
> > index b71935862417..7da2b3f02ed9 100644
> > --- a/drivers/gpu/drm/panfrost/Makefile
> > +++ b/drivers/gpu/drm/panfrost/Makefile
> > @@ -9,6 +9,7 @@ panfrost-y := \
> > panfrost_gpu.o \
> > panfrost_job.o \
> > panfrost_mmu.o \
> > -   panfrost_perfcnt.o
> > +   panfrost_perfcnt.o \
> > +   panfrost_dump.o
> >
> >  obj-$(CONFIG_DRM_PANFROST) += panfrost.o
> > diff --git a/drivers/gpu/drm/panfrost/panfrost_dump.c 
> > b/drivers/gpu/drm/panfrost/panfrost_dump.c
> > new file mode 100644
> > index ..a76dcf4acf6f
> > --- /dev/null
> > +++ b/drivers/gpu/drm/panfrost/panfrost_dump.c
> > @@ -0,0 +1,198 @@
> > +// SPDX-License-Identifier: GPL-2.0
> > +/* Copyright 2021 Collabora ltd. */
> > +
> > +#include 
> > +#include 
> > +#include 
> > +#include 
> > +#include 
> > +#include 
> > +#include 
> > +
> > +#include "panfrost_job.h"
> > +#include "panfrost_gem.h"
> > +#include "panfrost_regs.h"
> > +#include "panfrost_dump.h"
> > +#include "panfrost_device.h"
> > +
> > +static bool panfrost_dump_core = true;
> > +module_param_named(dump_core, panfrost_dump_core, bool, 0600);
> > +
> > +struct panfrost_dump_iterator {
> > +   void *start;
> > +   struct panfrost_dump_object_header *hdr;
> > +   void *data;
> > +};
> > +
> > +static const unsigned short panfrost_dump_registers[] = {
> > +   GPU_ID,
> > +   GPU_L2_FEATURES,
> > +   GPU_CORE_FEATURES,
> > +   GPU_TILER_FEATURES,
> > +   GPU_MEM_FEATURES,
> > +   GPU_MMU_FEATURES,
> > +   GPU_AS_PRESENT,
> > +   GPU_JS_PRESENT,
> > +   GPU_INT_RAWSTAT,
> > +   GPU_INT_CLEAR,
> > +   GPU_INT_MASK,
> > +   GPU_INT_STAT,
> > +};
> > +
> > +static void panfrost_core_dump_header(struct panfrost_dump_iterator *iter,
> > +   u32 type, void *data_end)
> > +{
> > +   struct panfrost_dump_object_header *hdr = iter->hdr;
> > +
> > +   hdr->magic = cpu_to_le32(PANFROSTDUMP_MAGIC);
> > +   hdr->type = cpu_to_le32(type);
> > +   hdr->file_offset = cpu_to_le32(iter->data - iter->start);
> > +   hdr->file_size = cpu_to_le32(data_end - iter->data);
> > +
> > +   iter->hdr++;
> > +   iter->data += le32_to_cpu(hdr->file_size);
> > +}
> > +
> > +static void
> > +panfrost_core_dump_registers(struct panfrost_dump_iterator *iter,
> > +struct panfrost_device *pfdev)
> > +{
> > +   struct panfrost_dump_registers *reg = iter->data;
> > +   unsigned int i;
> > +
> > +   for (i = 0; i < ARRAY_SIZE(panfrost_dump_registers); i++, reg++) {
> > +   reg->reg = cpu_to_le32(panfrost_dump_registers[i]);
> > +   reg->value = cpu_to_le32(gpu_read(pfdev, 
> > panfrost_dump_registers[i]));
> > +   }
> > +
> > +   panfrost_core_dump_header(iter, PANFROSTDUMP_BUF_REG, reg);
> > +}
> > +
> > +void panfrost_core_dump(struct panfrost_job *job)
> > +{
> > +   struct panfrost_device *pfdev = job->pfdev;
> > +   struct panfrost_dump_iterator iter;
> > +   struct drm_gem_object *dbo;
> > +   unsigned int n_obj, n_bomap_pages;
> > +   __le64 *bomap, *bomap_start;
> > +   size_t file_size;
> > +   int ret, i;
> > +
> > +   /* Only catch the first event, or when manually re-armed */
> > +   if (!panfrost_dump_core)
> > +   return;
> > +   panfrost_dump_core = false;
> > +
> > +   /* At least, we dump registers and end marker */
> > +   n_obj = 2;
> > +   n_bomap_pages = 0;
> > +   file_size 

Re: [RESEND RFC 17/18] drm/radeon: Drop legacy MST support

2022-06-07 Thread Alex Deucher
On Tue, Jun 7, 2022 at 3:39 PM Lyude Paul  wrote:
>
> Right now, radeon is technically the only non-atomic driver still making
> use of the MST helpers - and thus the final user of all of the legacy MST
> helpers. Originally I was going to look into seeing if we could move legacy
> MST into the radeon driver itself, however:
>
> * SI and CIK both can use amdgpu, which still supports MST
> * It currently doesn't work according to my own testing. I'm sure with some
>   troubleshooting we could likely fix it, but that brings me to point #2:
> * It was never actually enabled by default, and is still marked as
>   experimental in the module parameter description
> * If people were using it, someone probably would have probably seen a bug
>   report about how it is currently not functional by now. That certainly
>   doesn't appear to be the case, since before getting access to my own
>   hardware I had to go out of my way to try finding someone to help test
>   whether this legacy MST code even works - even amongst AMD employees.
> * Getting rid of this code and only having atomic versions of the MST
>   helpers to maintain is likely going to be a lot easier in the long run,
>   and will make it a lot easier for others contributing to this code to
>   follow along with what's happening.
>
> FWIW - if anyone still wants this code to be in the tree and has a good
> idea of how to support this without needing to maintain the legacy MST
> helpers (trying to move them would probably be acceptable), I'm happy to
> suggestions. But my hope is that we can just drop this code and forget
> about it. I've already run this idea by Harry Wentland and Alex Deucher a
> few times as well.
>
> Signed-off-by: Lyude Paul 
> Cc: Wayne Lin 
> Cc: Ville Syrjälä 
> Cc: Fangzhi Zuo 
> Cc: Jani Nikula 
> Cc: Imre Deak 
> Cc: Daniel Vetter 
> Cc: Sean Paul 

Acked-by: Alex Deucher 

> ---
>  drivers/gpu/drm/radeon/Makefile|   2 +-
>  drivers/gpu/drm/radeon/atombios_crtc.c |  11 +-
>  drivers/gpu/drm/radeon/atombios_encoders.c |  59 --
>  drivers/gpu/drm/radeon/radeon_atombios.c   |   2 -
>  drivers/gpu/drm/radeon/radeon_connectors.c |  61 +-
>  drivers/gpu/drm/radeon/radeon_device.c |   1 -
>  drivers/gpu/drm/radeon/radeon_dp_mst.c | 778 -
>  drivers/gpu/drm/radeon/radeon_drv.c|   4 -
>  drivers/gpu/drm/radeon/radeon_encoders.c   |  14 +-
>  drivers/gpu/drm/radeon/radeon_irq_kms.c|  10 +-
>  drivers/gpu/drm/radeon/radeon_mode.h   |  40 --
>  11 files changed, 7 insertions(+), 975 deletions(-)
>  delete mode 100644 drivers/gpu/drm/radeon/radeon_dp_mst.c
>
> diff --git a/drivers/gpu/drm/radeon/Makefile b/drivers/gpu/drm/radeon/Makefile
> index ea5380e24c3c..b783ab39a075 100644
> --- a/drivers/gpu/drm/radeon/Makefile
> +++ b/drivers/gpu/drm/radeon/Makefile
> @@ -49,7 +49,7 @@ radeon-y += radeon_device.o radeon_asic.o radeon_kms.o \
> rv770_smc.o cypress_dpm.o btc_dpm.o sumo_dpm.o sumo_smc.o 
> trinity_dpm.o \
> trinity_smc.o ni_dpm.o si_smc.o si_dpm.o kv_smc.o kv_dpm.o ci_smc.o \
> ci_dpm.o dce6_afmt.o radeon_vm.o radeon_ucode.o radeon_ib.o \
> -   radeon_sync.o radeon_audio.o radeon_dp_auxch.o radeon_dp_mst.o
> +   radeon_sync.o radeon_audio.o radeon_dp_auxch.o
>
>  radeon-$(CONFIG_MMU_NOTIFIER) += radeon_mn.o
>
> diff --git a/drivers/gpu/drm/radeon/atombios_crtc.c 
> b/drivers/gpu/drm/radeon/atombios_crtc.c
> index c94e429e75f9..e27da31d4f62 100644
> --- a/drivers/gpu/drm/radeon/atombios_crtc.c
> +++ b/drivers/gpu/drm/radeon/atombios_crtc.c
> @@ -616,13 +616,6 @@ static u32 atombios_adjust_pll(struct drm_crtc *crtc,
> }
> }
>
> -   if (radeon_encoder->is_mst_encoder) {
> -   struct radeon_encoder_mst *mst_enc = radeon_encoder->enc_priv;
> -   struct radeon_connector_atom_dig *dig_connector = 
> mst_enc->connector->con_priv;
> -
> -   dp_clock = dig_connector->dp_clock;
> -   }
> -
> /* use recommended ref_div for ss */
> if (radeon_encoder->devices & (ATOM_DEVICE_LCD_SUPPORT)) {
> if (radeon_crtc->ss_enabled) {
> @@ -971,9 +964,7 @@ static bool atombios_crtc_prepare_pll(struct drm_crtc 
> *crtc, struct drm_display_
> radeon_crtc->bpc = 8;
> radeon_crtc->ss_enabled = false;
>
> -   if (radeon_encoder->is_mst_encoder) {
> -   radeon_dp_mst_prepare_pll(crtc, mode);
> -   } else if ((radeon_encoder->active_device & (ATOM_DEVICE_LCD_SUPPORT 
> | ATOM_DEVICE_DFP_SUPPORT)) ||
> +   if ((radeon_encoder->active_device & (ATOM_DEVICE_LCD_SUPPORT | 
> ATOM_DEVICE_DFP_SUPPORT)) ||
> (radeon_encoder_get_dp_bridge_encoder_id(radeon_crtc->encoder) != 
> ENCODER_OBJECT_ID_NONE)) {
> struct radeon_encoder_atom_dig *dig = 
> radeon_encoder->enc_priv;
> struct drm_connector *connector =
> diff --git a/drivers/gpu/drm/radeon/atombios_encoders.c 
> 

[PATCH 5/7] fbdev: nvidia: Use backlight helper

2022-06-07 Thread Stephen Kitt
Instead of retrieving the backlight brightness in struct
backlight_properties manually, and then checking whether the backlight
should be on at all, use backlight_get_brightness() which does all
this and insulates this from future changes.

Signed-off-by: Stephen Kitt 
Cc: Antonino Daplas 
Cc: Helge Deller 
Cc: linux-fb...@vger.kernel.org
Cc: dri-devel@lists.freedesktop.org
---
 drivers/video/fbdev/nvidia/nv_backlight.c | 8 +---
 1 file changed, 1 insertion(+), 7 deletions(-)

diff --git a/drivers/video/fbdev/nvidia/nv_backlight.c 
b/drivers/video/fbdev/nvidia/nv_backlight.c
index 2ce53529f636..503a7a683855 100644
--- a/drivers/video/fbdev/nvidia/nv_backlight.c
+++ b/drivers/video/fbdev/nvidia/nv_backlight.c
@@ -49,17 +49,11 @@ static int nvidia_bl_update_status(struct backlight_device 
*bd)
 {
struct nvidia_par *par = bl_get_data(bd);
u32 tmp_pcrt, tmp_pmc, fpcontrol;
-   int level;
+   int level = backlight_get_brightness(bd);
 
if (!par->FlatPanel)
return 0;
 
-   if (bd->props.power != FB_BLANK_UNBLANK ||
-   bd->props.fb_blank != FB_BLANK_UNBLANK)
-   level = 0;
-   else
-   level = bd->props.brightness;
-
tmp_pmc = NV_RD32(par->PMC, 0x10F0) & 0x;
tmp_pcrt = NV_RD32(par->PCRTC0, 0x081C) & 0xFFFC;
fpcontrol = NV_RD32(par->PRAMDAC, 0x0848) & 0xCFCC;
-- 
2.30.2



[PATCH 1/7] fbdev: aty128fb: Use backlight helper

2022-06-07 Thread Stephen Kitt
Instead of retrieving the backlight brightness in struct
backlight_properties manually, and then checking whether the backlight
should be on at all, use backlight_get_brightness() which does all
this and insulates this from future changes.

Signed-off-by: Stephen Kitt 
Cc: Paul Mackerras 
Cc: Helge Deller 
Cc: linux-fb...@vger.kernel.org
Cc: dri-devel@lists.freedesktop.org
---
 drivers/video/fbdev/aty/aty128fb.c | 6 ++
 1 file changed, 2 insertions(+), 4 deletions(-)

diff --git a/drivers/video/fbdev/aty/aty128fb.c 
b/drivers/video/fbdev/aty/aty128fb.c
index b26c81233b6b..a8f9baac3d3f 100644
--- a/drivers/video/fbdev/aty/aty128fb.c
+++ b/drivers/video/fbdev/aty/aty128fb.c
@@ -1765,12 +1765,10 @@ static int aty128_bl_update_status(struct 
backlight_device *bd)
unsigned int reg = aty_ld_le32(LVDS_GEN_CNTL);
int level;
 
-   if (bd->props.power != FB_BLANK_UNBLANK ||
-   bd->props.fb_blank != FB_BLANK_UNBLANK ||
-   !par->lcd_on)
+   if (!par->lcd_on)
level = 0;
else
-   level = bd->props.brightness;
+   level = backlight_get_brightness(bd);
 
reg |= LVDS_BL_MOD_EN | LVDS_BLON;
if (level > 0) {
-- 
2.30.2



Re: [PATCH] staging: ftbft: Use backlight helper

2022-06-07 Thread Andy Shevchenko
On Tue, Jun 07, 2022 at 08:55:16PM +0200, Stephen Kitt wrote:
> backlight_properties.fb_blank is deprecated. The states it represents
> are handled by other properties; but instead of accessing those
> properties directly, drivers should use the helpers provided by
> backlight.h.
> 
> Instead of manually checking the power state in struct
> backlight_properties, use backlight_is_blank().

Reviewed-by: Andy Shevchenko 

> Signed-off-by: Stephen Kitt 
> Cc: Greg Kroah-Hartman 
> Cc: "Noralf Trønnes" 
> Cc: Thomas Zimmermann 
> Cc: Andy Shevchenko 
> Cc: Javier Martinez Canillas 
> Cc: Len Baker 
> Cc: dri-devel@lists.freedesktop.org
> Cc: linux-fb...@vger.kernel.org
> Cc: linux-stag...@lists.linux.dev
> ---
>  drivers/staging/fbtft/fb_ssd1351.c | 3 +--
>  drivers/staging/fbtft/fbtft-core.c | 3 +--
>  2 files changed, 2 insertions(+), 4 deletions(-)
> 
> diff --git a/drivers/staging/fbtft/fb_ssd1351.c 
> b/drivers/staging/fbtft/fb_ssd1351.c
> index 6fd549a424d5..b8d55aa8c5c7 100644
> --- a/drivers/staging/fbtft/fb_ssd1351.c
> +++ b/drivers/staging/fbtft/fb_ssd1351.c
> @@ -196,8 +196,7 @@ static int update_onboard_backlight(struct 
> backlight_device *bd)
> "%s: power=%d, fb_blank=%d\n",
> __func__, bd->props.power, bd->props.fb_blank);
>  
> - on = (bd->props.power == FB_BLANK_UNBLANK) &&
> -  (bd->props.fb_blank == FB_BLANK_UNBLANK);
> + on = !backlight_is_blank(bd);
>   /* Onboard backlight connected to GPIO0 on SSD1351, GPIO1 unused */
>   write_reg(par, 0xB5, on ? 0x03 : 0x02);
>  
> diff --git a/drivers/staging/fbtft/fbtft-core.c 
> b/drivers/staging/fbtft/fbtft-core.c
> index 60b2278d8b16..9b3eaed80cdd 100644
> --- a/drivers/staging/fbtft/fbtft-core.c
> +++ b/drivers/staging/fbtft/fbtft-core.c
> @@ -137,8 +137,7 @@ static int fbtft_backlight_update_status(struct 
> backlight_device *bd)
> "%s: polarity=%d, power=%d, fb_blank=%d\n",
> __func__, polarity, bd->props.power, bd->props.fb_blank);
>  
> - if ((bd->props.power == FB_BLANK_UNBLANK) &&
> - (bd->props.fb_blank == FB_BLANK_UNBLANK))
> + if (!backlight_is_blank(bd))
>   gpiod_set_value(par->gpio.led[0], polarity);
>   else
>   gpiod_set_value(par->gpio.led[0], !polarity);
> 
> base-commit: f2906aa863381afb0015a9eb7fefad885d4e5a56
> -- 
> 2.30.2
> 

-- 
With Best Regards,
Andy Shevchenko




Re: [Intel-gfx] [RFC v3 3/3] drm/doc/rfc: VM_BIND uapi definition

2022-06-07 Thread Niranjana Vishwanathapura

On Tue, Jun 07, 2022 at 11:27:14AM +0100, Tvrtko Ursulin wrote:


On 17/05/2022 19:32, Niranjana Vishwanathapura wrote:

VM_BIND and related uapi definitions

v2: Ensure proper kernel-doc formatting with cross references.
Also add new uapi and documentation as per review comments
from Daniel.

Signed-off-by: Niranjana Vishwanathapura 
---
 Documentation/gpu/rfc/i915_vm_bind.h | 399 +++
 1 file changed, 399 insertions(+)
 create mode 100644 Documentation/gpu/rfc/i915_vm_bind.h

diff --git a/Documentation/gpu/rfc/i915_vm_bind.h 
b/Documentation/gpu/rfc/i915_vm_bind.h
new file mode 100644
index ..589c0a009107
--- /dev/null
+++ b/Documentation/gpu/rfc/i915_vm_bind.h
@@ -0,0 +1,399 @@
+/* SPDX-License-Identifier: MIT */
+/*
+ * Copyright © 2022 Intel Corporation
+ */
+
+/**
+ * DOC: I915_PARAM_HAS_VM_BIND
+ *
+ * VM_BIND feature availability.
+ * See typedef drm_i915_getparam_t param.
+ */
+#define I915_PARAM_HAS_VM_BIND 57
+
+/**
+ * DOC: I915_VM_CREATE_FLAGS_USE_VM_BIND
+ *
+ * Flag to opt-in for VM_BIND mode of binding during VM creation.
+ * See struct drm_i915_gem_vm_control flags.
+ *
+ * A VM in VM_BIND mode will not support the older execbuff mode of binding.
+ * In VM_BIND mode, execbuff ioctl will not accept any execlist (ie., the
+ * _i915_gem_execbuffer2.buffer_count must be 0).
+ * Also, _i915_gem_execbuffer2.batch_start_offset and
+ * _i915_gem_execbuffer2.batch_len must be 0.
+ * DRM_I915_GEM_EXECBUFFER_EXT_BATCH_ADDRESSES extension must be provided
+ * to pass in the batch buffer addresses.
+ *
+ * Additionally, I915_EXEC_NO_RELOC, I915_EXEC_HANDLE_LUT and
+ * I915_EXEC_BATCH_FIRST of _i915_gem_execbuffer2.flags must be 0
+ * (not used) in VM_BIND mode. I915_EXEC_USE_EXTENSIONS flag must always be
+ * set (See struct drm_i915_gem_execbuffer_ext_batch_addresses).
+ * The buffers_ptr, buffer_count, batch_start_offset and batch_len fields
+ * of struct drm_i915_gem_execbuffer2 are also not used and must be 0.
+ */
+#define I915_VM_CREATE_FLAGS_USE_VM_BIND   (1 << 0)
+
+/**
+ * DOC: I915_CONTEXT_CREATE_FLAGS_LONG_RUNNING
+ *
+ * Flag to declare context as long running.
+ * See struct drm_i915_gem_context_create_ext flags.
+ *
+ * Usage of dma-fence expects that they complete in reasonable amount of time.
+ * Compute on the other hand can be long running. Hence it is not appropriate
+ * for compute contexts to export request completion dma-fence to user.
+ * The dma-fence usage will be limited to in-kernel consumption only.
+ * Compute contexts need to use user/memory fence.
+ *
+ * So, long running contexts do not support output fences. Hence,
+ * I915_EXEC_FENCE_OUT (See _i915_gem_execbuffer2.flags and
+ * I915_EXEC_FENCE_SIGNAL (See _i915_gem_exec_fence.flags) are expected
+ * to be not used.
+ *
+ * DRM_I915_GEM_WAIT ioctl call is also not supported for objects mapped
+ * to long running contexts.
+ */
+#define I915_CONTEXT_CREATE_FLAGS_LONG_RUNNING   (1u << 2)
+
+/* VM_BIND related ioctls */
+#define DRM_I915_GEM_VM_BIND   0x3d
+#define DRM_I915_GEM_VM_UNBIND 0x3e
+#define DRM_I915_GEM_WAIT_USER_FENCE   0x3f
+
+#define DRM_IOCTL_I915_GEM_VM_BIND DRM_IOWR(DRM_COMMAND_BASE + 
DRM_I915_GEM_VM_BIND, struct drm_i915_gem_vm_bind)
+#define DRM_IOCTL_I915_GEM_VM_UNBIND   DRM_IOWR(DRM_COMMAND_BASE + 
DRM_I915_GEM_VM_UNBIND, struct drm_i915_gem_vm_bind)
+#define DRM_IOCTL_I915_GEM_WAIT_USER_FENCE DRM_IOWR(DRM_COMMAND_BASE + 
DRM_I915_GEM_WAIT_USER_FENCE, struct drm_i915_gem_wait_user_fence)
+
+/**
+ * struct drm_i915_gem_vm_bind - VA to object mapping to bind.
+ *
+ * This structure is passed to VM_BIND ioctl and specifies the mapping of GPU
+ * virtual address (VA) range to the section of an object that should be bound
+ * in the device page table of the specified address space (VM).
+ * The VA range specified must be unique (ie., not currently bound) and can
+ * be mapped to whole object or a section of the object (partial binding).
+ * Multiple VA mappings can be created to the same section of the object
+ * (aliasing).
+ */
+struct drm_i915_gem_vm_bind {
+   /** @vm_id: VM (address space) id to bind */
+   __u32 vm_id;
+
+   /** @handle: Object handle */
+   __u32 handle;
+
+   /** @start: Virtual Address start to bind */
+   __u64 start;
+
+   /** @offset: Offset in object to bind */
+   __u64 offset;
+
+   /** @length: Length of mapping to bind */
+   __u64 length;


Does it support, or should it, equivalent of EXEC_OBJECT_PAD_TO_SIZE? 
Or if not userspace is expected to map the remainder of the space to a 
dummy object? In which case would there be any alignment/padding 
issues preventing the two bind to be placed next to each other?


I ask because someone from the compute side asked me about a problem 
with their strategy of dealing with overfetch and I suggested pad to 
size.




Thanks Tvrtko,
I think we shouldn't be needing it. As with VM_BIND VA assignment

Re: [PATCH v1 06/13] drm/probe-helper: make .get_modes() optional, add default action

2022-06-07 Thread Ville Syrjälä
On Tue, Jun 07, 2022 at 02:14:54PM +0300, Jani Nikula wrote:
> On Thu, 02 Jun 2022, Ville Syrjälä  wrote:
> > On Tue, May 24, 2022 at 01:39:28PM +0300, Jani Nikula wrote:
> >> Add default action when .get_modes() not set. This also defines what a
> >> .get_modes() hook should do.
> >> 
> >> Cc: David Airlie 
> >> Cc: Daniel Vetter 
> >> Signed-off-by: Jani Nikula 
> >> ---
> >>  drivers/gpu/drm/drm_probe_helper.c   | 14 +-
> >>  include/drm/drm_modeset_helper_vtables.h |  4 
> >>  2 files changed, 17 insertions(+), 1 deletion(-)
> >> 
> >> diff --git a/drivers/gpu/drm/drm_probe_helper.c 
> >> b/drivers/gpu/drm/drm_probe_helper.c
> >> index 836bcd5b4cb6..9df17f0ae225 100644
> >> --- a/drivers/gpu/drm/drm_probe_helper.c
> >> +++ b/drivers/gpu/drm/drm_probe_helper.c
> >> @@ -360,7 +360,19 @@ static int drm_helper_probe_get_modes(struct 
> >> drm_connector *connector)
> >>connector->helper_private;
> >>int count;
> >>  
> >> -  count = connector_funcs->get_modes(connector);
> >> +  if (connector_funcs->get_modes) {
> >> +  count = connector_funcs->get_modes(connector);
> >> +  } else {
> >> +  const struct drm_edid *drm_edid;
> >> +
> >> +  /* Note: This requires connector->ddc is set */
> >> +  drm_edid = drm_edid_read(connector);
> >> +
> >> +  /* Update modes etc. from the EDID */
> >> +  count = drm_edid_connector_update(connector, drm_edid);
> >> +
> >> +  drm_edid_free(drm_edid);
> >> +  }
> >
> > Not really a huge fan of this automagic fallback. I think I'd prefer
> > to keep it mandatory and just provide this as a helper for drivers to
> > plug into the right spot. Otherwise I'm sure I'll forget how this works
> > and then I'll be confused when I see a connector withput any apparent
> > .get_modes() implementation.
> 
> Fair enough.
> 
> I'm not sure how useful that is going to be, though, at least not for
> i915. If we add a .get_edid hook, where would you bolt that? It doesn't
> feel right to set a .get_modes hook to a default function that goes on
> to call a .get_edid hook. Or what do you think?

If .get_modes() remains mandatory do we need the .get_edid() hook?
Ie. would it be called from anywhere else than from .get_modes()?

So we'd just end with
foo_get_modes()
{
edid = foo_get_edid();
drm_edid_connector_update(edid);
}
in drivers than need a custom edid read function.

-- 
Ville Syrjälä
Intel


[PATCH 0/4] video/backlight: Use backlight helpers

2022-06-07 Thread Stephen Kitt
This started with work on the removal of backlight_properties'
deprecated fb_blank field, much of which can be taken care of by using
helper functions provided by backlight.h instead of directly accessing
fields in backlight_properties. This patch series doesn't involve
fb_blank, but it still seems useful to use helper functions where
appropriate.

Stephen Kitt (4):
  backlight: aat2870: Use backlight helper
  backlight: arcxcnn: Use backlight helper
  backlight: ipaq_micro: Use backlight helper
  backlight: tosa: Use backlight helper

 drivers/video/backlight/aat2870_bl.c| 7 +--
 drivers/video/backlight/arcxcnn_bl.c| 5 +
 drivers/video/backlight/ipaq_micro_bl.c | 7 +--
 drivers/video/backlight/tosa_bl.c   | 7 +--
 4 files changed, 4 insertions(+), 22 deletions(-)


base-commit: f2906aa863381afb0015a9eb7fefad885d4e5a56
-- 
2.30.2



Re: [PATCH V2 0/3] DSI host and peripheral initialisation ordering

2022-06-07 Thread Jagan Teki
Hi Marek,

On Wed, May 18, 2022 at 7:35 PM Marek Szyprowski
 wrote:
>
> Hi Dave,
>
> On 11.05.2022 17:47, Dave Stevenson wrote:
> > On Wed, 11 May 2022 at 15:58, Marek Szyprowski  
> > wrote:
> >> On 05.04.2022 13:43, Dave Stevenson wrote:
> >>> On Fri, 18 Mar 2022 at 12:25, Dave Stevenson
> >>>   wrote:
>  On Fri, 4 Mar 2022 at 15:18, Dave Stevenson
>    wrote:
> > Hi All
>  A gentle ping on this series. Any comments on the approach?
>  Thanks.
> >>> I realise the merge window has just closed and therefore folks have
> >>> been busy, but no responses on this after a month?
> >>>
> >>> Do I give up and submit a patch to document that DSI is broken and no one 
> >>> cares?
> >> Thanks for pointing this patchset in the 'drm: bridge: Add Samsung MIPI
> >> DSIM bridge' thread, otherwise I would miss it since I'm not involved
> >> much in the DRM development.
> >>
> >> This resolves most of the issues in the Exynos DSI and its recent
> >> conversion to the drm bridge framework. I've added the needed
> >> prepare_upstream_first flags to the panels and everything works fine
> >> without the bridge chain order hacks.
> >>
> >> Feel free to add:
> >>
> >> Tested-by: Marek Szyprowski 
> > Thanks for testing it. I was almost at the stage of abandoning the patch 
> > set.
> >
> >> The only remaining thing to resolve is the moment of enabling DSI host.
> >> The proper sequence is:
> >>
> >> 1. host power on, 2. device power on, 3. host init, 4. device init, 5.
> >> video enable.
> >>
> >> #1 is done in dsi's pre_enable, #2 is done in panel's prepare. #3 was so
> >> far done in the first host transfer call, which usually happens in
> >> panel's prepare, then the #4 happens. Then video enable is done in the
> >> enable callbacks.
> > What's your definition of host power on and host init here? What state
> > are you defining the DSI interface to be in after each operation?
>
> Well, lets start from the point that I'm not a DSI specialist nor I'm
> not the exynos-dsi author. I just played a bit with the code trying to
> restore proper driver operation on the various Exynos based boards I have.
>
> By the host/device power on I mean enabling their power regulators. By
> host init I mean executing the samsung_dsim_init() function, which
> basically sets the lp-11 state if I understand it right.
>
>
> >> Jagan wants to move it to the dsi host pre_enable() to let it work with
> >> DSI bridges controlled over different interfaces
> >> (https://lore.kernel.org/all/20220504114021.33265-6-ja...@amarulasolutions.com/
> >> ).
> > I think I'm in agreement with Jagan.
> > As documented in patch 4/4:
> > + * A DSI host should keep the PHY powered down until the pre_enable
> > operation is
> > + * called. All lanes are in an undefined idle state up to this point, and 
> > it
> > + * must not be assumed that it is LP-11.
> > + * pre_enable should initialise the PHY, set the data lanes to LP-11, and 
> > the
> > + * clock lane to either LP-11 or HS depending on the mode_flag
> > + * %MIPI_DSI_CLOCK_NON_CONTINUOUS.
>
> Right, this theory makes sense.
>
> However Exynos DSI for some reasons did the host initialization in the
> first call of the samsung_dsim_host_transfer(). If I moved the host
> initialization to pre_enable (before powering the panel on), executing
> DSI commands failed (timeout). This issue happens on all boards I have
> access (Trats, Trats2, Arndale, TM2e), so this must be an issue with
> Exynos DSI host itself not related to particular panel/bridge.
>
> If I call samsung_dsim_init() once again, before issuing the first DSI
> command, then everything works fine. I've tried to check which part of
> that function is needed to be executed before transferring the commands,
> but it turned out that the complete host reset and (re)configuration is
> necessary. It looks that the initialization will need to be done twice,
> first time in the pre_enable to satisfy Jagan case, then on the first
> dsi transfer to make it work with real DSI panels.
>
> Here is a git repo with such change:
> https://github.com/mszyprow/linux/tree/v5.18-next-20220511-dsi-rework-v2

This is worthy check, I will test it on imx8mm and integrate it into
the next version - hope this is fine for you?

Jagan.


[RESEND RFC 18/18] drm/display/dp_mst: Move all payload info into the atomic state

2022-06-07 Thread Lyude Paul
Now that we've finally gotten rid of the non-atomic MST users leftover in
the kernel, we can finally get rid of all of the legacy payload code we
have and move as much as possible into the MST atomic state structs. The
main purpose of this is to make the MST code a lot less confusing to work
on, as there's a lot of duplicated logic that doesn't really need to be
here. As well, this should make introducing features like fallback link
retraining and DSC support far easier.

Since the old payload code was pretty gnarly and there's a Lot of changes
here, I expect this might be a bit difficult to review. So to make things
as easy as possible for reviewers, I'll sum up how both the old and new
code worked here (it took me a while to figure this out too!).

The old MST code basically worked by maintaining two different payload
tables - proposed_vcpis, and payloads. proposed_vcpis would hold the
modified payload we wanted to push to the topology, while payloads held the
payload table that was currently programmed in hardware. Modifications to
proposed_vcpis would be handled through drm_dp_allocate_vcpi(),
drm_dp_mst_deallocate_vcpi(), and drm_dp_mst_reset_vcpi_slots(). Then, they
would be pushed via drm_dp_mst_update_payload_step1() and
drm_dp_mst_update_payload_step2().

Furthermore, it's important to note how adding and removing VC payloads
actually worked with drm_dp_mst_update_payload_step1(). When a VC payload
is removed from the VC table, all VC payloads which come after the removed
VC payload's slots must have their time slots shifted towards the start of
the table. The old code handles this by looping through the entire payload
table and recomputing the start slot for every payload in the topology from
scratch. While very much overkill, this ends up doing the right thing
because we always order the VCPIs for payloads from first to last starting
timeslot.

It's important to also note that drm_dp_mst_update_payload_step2() isn't
actually limited to updating a single payload - the driver can use it to
queue up multiple payload changes so that as many of them can be sent as
possible before waiting for the ACT.

drm_dp_mst_update_payload_step2() is pretty self explanatory and basically
the same between the old and new code, save for the fact we don't have a
second step for deleting payloads anymore -and thus rename it to
drm_dp_mst_add_payload_step2().

The new payload code stores all of the current payload info within the MST
atomic state and computes as much of the state as possible ahead of time.
This has the one exception of the starting timeslots for payloads, which
can't be determined at atomic check time since the starting time slots will
vary depending on what order CRTCs are enabled in the atomic state - which
varies from driver to driver. These are still stored in the atomic MST
state, but are only copied from the old MST state during atomic commit
time. Likewise, this is when new start slots are determined.

Adding/removing payloads now works much more closely to how things are
described in the spec. When we delete a payload, we loop through the
current list of payloads and update the start slots for any payloads whose
time slots came after the payload we just deleted. Determining the starting
time slots for new payloads being added is done by simply keeping track of
where the end of the VC table is in
drm_dp_mst_topology_mgr->next_start_slot. Additionally, it's worth noting
that we no longer have a single update_payload() function. Instead, we now
have drm_dp_mst_add_payload_step1|2() and drm_dp_mst_remove_payload(). As
such, it's now left it up to the driver to figure out when to add or remove
payloads. The driver already knows when it's disabling/enabling CRTCs, so
it also already knows when payloads should be added or removed. And, this
doesn't interfere with the ability to queue up multiple payload changes
before waiting for the ACT.

Signed-off-by: Lyude Paul 
Cc: Wayne Lin 
Cc: Ville Syrjälä 
Cc: Fangzhi Zuo 
Cc: Jani Nikula 
Cc: Imre Deak 
Cc: Daniel Vetter 
Cc: Sean Paul 
---
 .../gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c |  56 +-
 .../amd/display/amdgpu_dm/amdgpu_dm_helpers.c | 107 +--
 .../display/amdgpu_dm/amdgpu_dm_mst_types.c   |  85 +--
 .../amd/display/include/link_service_types.h  |   7 +
 drivers/gpu/drm/display/drm_dp_mst_topology.c | 699 ++
 drivers/gpu/drm/i915/display/intel_dp_mst.c   |  64 +-
 drivers/gpu/drm/i915/display/intel_hdcp.c |  24 +-
 drivers/gpu/drm/nouveau/dispnv50/disp.c   | 163 ++--
 include/drm/display/drm_dp_mst_helper.h   | 178 ++---
 9 files changed, 536 insertions(+), 847 deletions(-)

diff --git a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c 
b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c
index ac8648e3c1c9..93d572ea3c48 100644
--- a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c
+++ b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c
@@ -7378,6 +7378,7 @@ static int dm_encoder_helper_atomic_check(struct 
drm_encoder 

[RESEND RFC 02/18] drm/amdgpu/dm/mst: Rename get_payload_table()

2022-06-07 Thread Lyude Paul
This function isn't too confusing if you see the comment around the
call-site for it, but if you don't then it's not at all obvious this is
meant to copy DRM's payload table over to DC's internal state structs.
Seeing this function before finding that comment definitely threw me into a
loop a few times.

So, let's rename this to make it's purpose more obvious regardless of where
in the code you are.

Signed-off-by: Lyude Paul 
Cc: Wayne Lin 
Cc: Fangzhi Zuo 
---
 drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_helpers.c | 7 ---
 1 file changed, 4 insertions(+), 3 deletions(-)

diff --git a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_helpers.c 
b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_helpers.c
index 1bd70d306c22..1eaacab0334b 100644
--- a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_helpers.c
+++ b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_helpers.c
@@ -153,8 +153,9 @@ enum dc_edid_status dm_helpers_parse_edid_caps(
return result;
 }
 
-static void get_payload_table(struct amdgpu_dm_connector *aconnector,
- struct dc_dp_mst_stream_allocation_table 
*proposed_table)
+static void
+fill_dc_mst_payload_table_from_drm(struct amdgpu_dm_connector *aconnector,
+  struct dc_dp_mst_stream_allocation_table 
*proposed_table)
 {
int i;
struct drm_dp_mst_topology_mgr *mst_mgr =
@@ -252,7 +253,7 @@ bool dm_helpers_dp_mst_write_payload_allocation_table(
 * stream. AMD ASIC stream slot allocation should follow the same
 * sequence. copy DRM MST allocation to dc */
 
-   get_payload_table(aconnector, proposed_table);
+   fill_dc_mst_payload_table_from_drm(aconnector, proposed_table);
 
return true;
 }
-- 
2.35.3



[RESEND RFC 13/18] drm/display/dp_mst: Add helpers for serializing SST <-> MST transitions

2022-06-07 Thread Lyude Paul
There's another kind of situation where we could potentially race with
nonblocking modesets and MST, especially if we were to only use the locking
provided by atomic modesetting:

* Display 1 begins as enabled on DP-1 in SST mode
* Display 1 switches to MST mode, exposes one sink in MST mode
* Userspace does non-blocking modeset to disable the SST display
* Userspace does non-blocking modeset to enable the MST display with a
  different CRTC, but the SST display hasn't been fully taken down yet
* Execution order between the last two commits isn't guaranteed since they
  share no drm resources

We can fix this however, by ensuring that we always pull in the atomic
topology state whenever a connector capable of driving an MST display
performs its atomic check - and then tracking CRTC commits happening on the
SST connector in the MST topology state. So, let's add some simple helpers
for doing that and hook them up in various drivers.

Signed-off-by: Lyude Paul 
Cc: Wayne Lin 
Cc: Ville Syrjälä 
Cc: Fangzhi Zuo 
Cc: Jani Nikula 
Cc: Imre Deak 
Cc: Daniel Vetter 
Cc: Sean Paul 
---
 .../gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c |  7 +++
 drivers/gpu/drm/display/drm_dp_mst_topology.c | 59 +++
 drivers/gpu/drm/i915/display/intel_dp.c   |  9 +++
 drivers/gpu/drm/nouveau/dispnv50/disp.c   |  2 +-
 drivers/gpu/drm/nouveau/dispnv50/disp.h   |  2 +
 drivers/gpu/drm/nouveau/nouveau_connector.c   | 14 +
 include/drm/display/drm_dp_mst_helper.h   |  2 +
 7 files changed, 94 insertions(+), 1 deletion(-)

diff --git a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c 
b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c
index d9c7393ef151..ac8648e3c1c9 100644
--- a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c
+++ b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c
@@ -7177,10 +7177,17 @@ amdgpu_dm_connector_atomic_check(struct drm_connector 
*conn,
drm_atomic_get_old_connector_state(state, conn);
struct drm_crtc *crtc = new_con_state->crtc;
struct drm_crtc_state *new_crtc_state;
+   struct amdgpu_dm_connector *aconn = to_amdgpu_dm_connector(conn);
int ret;
 
trace_amdgpu_dm_connector_atomic_check(new_con_state);
 
+   if (conn->connector_type == DRM_MODE_CONNECTOR_DisplayPort) {
+   ret = drm_dp_mst_root_conn_atomic_check(new_con_state, 
>mst_mgr);
+   if (ret < 0)
+   return ret;
+   }
+
if (!crtc)
return 0;
 
diff --git a/drivers/gpu/drm/display/drm_dp_mst_topology.c 
b/drivers/gpu/drm/display/drm_dp_mst_topology.c
index c5edcf2a26c8..a775f9437868 100644
--- a/drivers/gpu/drm/display/drm_dp_mst_topology.c
+++ b/drivers/gpu/drm/display/drm_dp_mst_topology.c
@@ -4608,6 +4608,65 @@ void drm_dp_mst_atomic_wait_for_dependencies(struct 
drm_atomic_state *state)
 }
 EXPORT_SYMBOL(drm_dp_mst_atomic_wait_for_dependencies);
 
+/**
+ * drm_dp_mst_root_conn_atomic_check() - Serialize CRTC commits on MST-capable 
connectors operating
+ * in SST mode
+ * @new_conn_state: The new connector state of the _connector
+ * @mgr: The MST topology manager for the _connector
+ *
+ * Since MST uses fake _encoder structs, the generic atomic modesetting 
code isn't able to
+ * serialize non-blocking commits happening on the real DP connector of an MST 
topology switching
+ * into/away from MST mode - as the CRTC on the real DP connector and the 
CRTCs on the connector's
+ * MST topology will never share the same _encoder.
+ *
+ * This function takes care of this serialization issue, by checking a root 
MST connector's atomic
+ * state to determine if it is about to have a modeset - and then pulling in 
the MST topology state
+ * if so, along with adding any relevant CRTCs to 
_dp_mst_topology_state.pending_crtc_mask.
+ *
+ * Drivers implementing MST must call this function from the
+ * _connector_helper_funcs.atomic_check hook of any physical DP 
_connector capable of
+ * driving MST sinks.
+ *
+ * Returns:
+ * 0 on success, negative error code otherwise
+ */
+int drm_dp_mst_root_conn_atomic_check(struct drm_connector_state 
*new_conn_state,
+ struct drm_dp_mst_topology_mgr *mgr)
+{
+   struct drm_atomic_state *state = new_conn_state->state;
+   struct drm_connector_state *old_conn_state =
+   drm_atomic_get_old_connector_state(state, 
new_conn_state->connector);
+   struct drm_crtc_state *crtc_state;
+   struct drm_dp_mst_topology_state *mst_state = NULL;
+
+   if (new_conn_state->crtc) {
+   crtc_state = drm_atomic_get_new_crtc_state(state, 
new_conn_state->crtc);
+   if (crtc_state && drm_atomic_crtc_needs_modeset(crtc_state)) {
+   mst_state = drm_atomic_get_mst_topology_state(state, 
mgr);
+   if (IS_ERR(mst_state))
+   return PTR_ERR(mst_state);
+
+   mst_state->pending_crtc_mask |= 

[RESEND RFC 17/18] drm/radeon: Drop legacy MST support

2022-06-07 Thread Lyude Paul
Right now, radeon is technically the only non-atomic driver still making
use of the MST helpers - and thus the final user of all of the legacy MST
helpers. Originally I was going to look into seeing if we could move legacy
MST into the radeon driver itself, however:

* SI and CIK both can use amdgpu, which still supports MST
* It currently doesn't work according to my own testing. I'm sure with some
  troubleshooting we could likely fix it, but that brings me to point #2:
* It was never actually enabled by default, and is still marked as
  experimental in the module parameter description
* If people were using it, someone probably would have probably seen a bug
  report about how it is currently not functional by now. That certainly
  doesn't appear to be the case, since before getting access to my own
  hardware I had to go out of my way to try finding someone to help test
  whether this legacy MST code even works - even amongst AMD employees.
* Getting rid of this code and only having atomic versions of the MST
  helpers to maintain is likely going to be a lot easier in the long run,
  and will make it a lot easier for others contributing to this code to
  follow along with what's happening.

FWIW - if anyone still wants this code to be in the tree and has a good
idea of how to support this without needing to maintain the legacy MST
helpers (trying to move them would probably be acceptable), I'm happy to
suggestions. But my hope is that we can just drop this code and forget
about it. I've already run this idea by Harry Wentland and Alex Deucher a
few times as well.

Signed-off-by: Lyude Paul 
Cc: Wayne Lin 
Cc: Ville Syrjälä 
Cc: Fangzhi Zuo 
Cc: Jani Nikula 
Cc: Imre Deak 
Cc: Daniel Vetter 
Cc: Sean Paul 
---
 drivers/gpu/drm/radeon/Makefile|   2 +-
 drivers/gpu/drm/radeon/atombios_crtc.c |  11 +-
 drivers/gpu/drm/radeon/atombios_encoders.c |  59 --
 drivers/gpu/drm/radeon/radeon_atombios.c   |   2 -
 drivers/gpu/drm/radeon/radeon_connectors.c |  61 +-
 drivers/gpu/drm/radeon/radeon_device.c |   1 -
 drivers/gpu/drm/radeon/radeon_dp_mst.c | 778 -
 drivers/gpu/drm/radeon/radeon_drv.c|   4 -
 drivers/gpu/drm/radeon/radeon_encoders.c   |  14 +-
 drivers/gpu/drm/radeon/radeon_irq_kms.c|  10 +-
 drivers/gpu/drm/radeon/radeon_mode.h   |  40 --
 11 files changed, 7 insertions(+), 975 deletions(-)
 delete mode 100644 drivers/gpu/drm/radeon/radeon_dp_mst.c

diff --git a/drivers/gpu/drm/radeon/Makefile b/drivers/gpu/drm/radeon/Makefile
index ea5380e24c3c..b783ab39a075 100644
--- a/drivers/gpu/drm/radeon/Makefile
+++ b/drivers/gpu/drm/radeon/Makefile
@@ -49,7 +49,7 @@ radeon-y += radeon_device.o radeon_asic.o radeon_kms.o \
rv770_smc.o cypress_dpm.o btc_dpm.o sumo_dpm.o sumo_smc.o trinity_dpm.o 
\
trinity_smc.o ni_dpm.o si_smc.o si_dpm.o kv_smc.o kv_dpm.o ci_smc.o \
ci_dpm.o dce6_afmt.o radeon_vm.o radeon_ucode.o radeon_ib.o \
-   radeon_sync.o radeon_audio.o radeon_dp_auxch.o radeon_dp_mst.o
+   radeon_sync.o radeon_audio.o radeon_dp_auxch.o
 
 radeon-$(CONFIG_MMU_NOTIFIER) += radeon_mn.o
 
diff --git a/drivers/gpu/drm/radeon/atombios_crtc.c 
b/drivers/gpu/drm/radeon/atombios_crtc.c
index c94e429e75f9..e27da31d4f62 100644
--- a/drivers/gpu/drm/radeon/atombios_crtc.c
+++ b/drivers/gpu/drm/radeon/atombios_crtc.c
@@ -616,13 +616,6 @@ static u32 atombios_adjust_pll(struct drm_crtc *crtc,
}
}
 
-   if (radeon_encoder->is_mst_encoder) {
-   struct radeon_encoder_mst *mst_enc = radeon_encoder->enc_priv;
-   struct radeon_connector_atom_dig *dig_connector = 
mst_enc->connector->con_priv;
-
-   dp_clock = dig_connector->dp_clock;
-   }
-
/* use recommended ref_div for ss */
if (radeon_encoder->devices & (ATOM_DEVICE_LCD_SUPPORT)) {
if (radeon_crtc->ss_enabled) {
@@ -971,9 +964,7 @@ static bool atombios_crtc_prepare_pll(struct drm_crtc 
*crtc, struct drm_display_
radeon_crtc->bpc = 8;
radeon_crtc->ss_enabled = false;
 
-   if (radeon_encoder->is_mst_encoder) {
-   radeon_dp_mst_prepare_pll(crtc, mode);
-   } else if ((radeon_encoder->active_device & (ATOM_DEVICE_LCD_SUPPORT | 
ATOM_DEVICE_DFP_SUPPORT)) ||
+   if ((radeon_encoder->active_device & (ATOM_DEVICE_LCD_SUPPORT | 
ATOM_DEVICE_DFP_SUPPORT)) ||
(radeon_encoder_get_dp_bridge_encoder_id(radeon_crtc->encoder) != 
ENCODER_OBJECT_ID_NONE)) {
struct radeon_encoder_atom_dig *dig = radeon_encoder->enc_priv;
struct drm_connector *connector =
diff --git a/drivers/gpu/drm/radeon/atombios_encoders.c 
b/drivers/gpu/drm/radeon/atombios_encoders.c
index 70bd84b7ef2b..597446a8df34 100644
--- a/drivers/gpu/drm/radeon/atombios_encoders.c
+++ b/drivers/gpu/drm/radeon/atombios_encoders.c
@@ -681,15 +681,7 @@ atombios_get_encoder_mode(struct drm_encoder *encoder)
struct drm_connector *connector;

[RESEND RFC 16/18] drm/display/dp_mst: Maintain time slot allocations when deleting payloads

2022-06-07 Thread Lyude Paul
Currently, we set drm_dp_atomic_payload->time_slots to 0 in order to
indicate that we're about to delete a payload in the current atomic state.
Since we're going to be dropping all of the legacy code for handling the
payload table however, we need to be able to ensure that we still keep
track of the current time slot allocations for each payload so we can reuse
this info when asking the root MST hub to delete payloads. We'll also be
using it to recalculate the start slots of each VC.

So, let's keep track of the intent of a payload in drm_dp_atomic_payload by
adding ->delete, which we set whenever we're planning on deleting a payload
during the current atomic commit.

Signed-off-by: Lyude Paul 
Cc: Wayne Lin 
Cc: Ville Syrjälä 
Cc: Fangzhi Zuo 
Cc: Jani Nikula 
Cc: Imre Deak 
Cc: Daniel Vetter 
Cc: Sean Paul 
---
 drivers/gpu/drm/display/drm_dp_mst_topology.c | 14 +++---
 include/drm/display/drm_dp_mst_helper.h   |  5 -
 2 files changed, 11 insertions(+), 8 deletions(-)

diff --git a/drivers/gpu/drm/display/drm_dp_mst_topology.c 
b/drivers/gpu/drm/display/drm_dp_mst_topology.c
index 70adb8db4335..10d26a7e028c 100644
--- a/drivers/gpu/drm/display/drm_dp_mst_topology.c
+++ b/drivers/gpu/drm/display/drm_dp_mst_topology.c
@@ -4410,7 +4410,7 @@ int drm_dp_atomic_find_time_slots(struct drm_atomic_state 
*state,
 * releasing and allocating the same timeslot allocation,
 * which is an error
 */
-   if (WARN_ON(!prev_slots)) {
+   if (drm_WARN_ON(mgr->dev, payload->delete)) {
drm_err(mgr->dev,
"cannot allocate and release time slots on [MST 
PORT:%p] in the same state\n",
port);
@@ -4515,10 +4515,10 @@ int drm_dp_atomic_release_time_slots(struct 
drm_atomic_state *state,
}
 
drm_dbg_atomic(mgr->dev, "[MST PORT:%p] TU %d -> 0\n", port, 
payload->time_slots);
-   if (payload->time_slots) {
+   if (!payload->delete) {
drm_dp_mst_put_port_malloc(port);
-   payload->time_slots = 0;
payload->pbn = 0;
+   payload->delete = true;
}
 
return 0;
@@ -5234,7 +5234,7 @@ drm_dp_mst_duplicate_state(struct drm_private_obj *obj)
 
list_for_each_entry(pos, _state->payloads, next) {
/* Prune leftover freed timeslot allocations */
-   if (!pos->time_slots)
+   if (pos->delete)
continue;
 
payload = kmemdup(pos, sizeof(*payload), GFP_KERNEL);
@@ -5266,8 +5266,8 @@ static void drm_dp_mst_destroy_state(struct 
drm_private_obj *obj,
int i;
 
list_for_each_entry_safe(pos, tmp, _state->payloads, next) {
-   /* We only keep references to ports with non-zero VCPIs */
-   if (pos->time_slots)
+   /* We only keep references to ports with active payloads */
+   if (!pos->delete)
drm_dp_mst_put_port_malloc(pos->port);
kfree(pos);
}
@@ -5395,7 +5395,7 @@ drm_dp_mst_atomic_check_payload_alloc_limits(struct 
drm_dp_mst_topology_mgr *mgr
 
list_for_each_entry(payload, _state->payloads, next) {
/* Releasing payloads is always OK-even if the port is gone */
-   if (!payload->time_slots) {
+   if (payload->delete) {
drm_dbg_atomic(mgr->dev, "[MST PORT:%p] releases all 
time slots\n",
   payload->port);
continue;
diff --git a/include/drm/display/drm_dp_mst_helper.h 
b/include/drm/display/drm_dp_mst_helper.h
index 690ebcabb51f..ecd130028337 100644
--- a/include/drm/display/drm_dp_mst_helper.h
+++ b/include/drm/display/drm_dp_mst_helper.h
@@ -555,8 +555,11 @@ struct drm_dp_mst_atomic_payload {
int time_slots;
/** @pbn: The payload bandwidth for this payload */
int pbn;
+
+   /** @delete: Whether or not we intend to delete this payload during 
this atomic commit */
+   bool delete : 1;
/** @dsc_enabled: Whether or not this payload has DSC enabled */
-   bool dsc_enabled;
+   bool dsc_enabled : 1;
 
/** @next: The list node for this payload */
struct list_head next;
-- 
2.35.3



[RESEND RFC 15/18] drm/display/dp_mst: Skip releasing payloads if last connected port isn't connected

2022-06-07 Thread Lyude Paul
In the past, we've ran into strange issues regarding errors in response to
trying to destroy payloads after a port has been unplugged. We fixed this
back in:

This is intended to replace the workaround that was added here:

commit 3769e4c0af5b ("drm/dp_mst: Avoid to mess up payload table by ports in 
stale topology")

which was intended fix to some of the payload leaks that were observed
before, where we would attempt to determine if the port was still connected
to the topology before updating payloads using
drm_dp_mst_port_downstream_of_branch. This wasn't a particularly good
solution, since one of the points of still having port and mstb validation
is to avoid sending messages to newly disconnected branches wherever
possible - thus the required use of drm_dp_mst_port_downstream_of_branch
would indicate something may be wrong with said validation.

It seems like it may have just been races and luck that made
drm_dp_mst_port_downstream_of_branch work however, as while I was trying to
figure out the true cause of this issue when removing the legacy MST code -
I discovered an important excerpt in section 2.14.2.3.3.6 of the DP 2.0
specs:

"BAD_PARAM - This reply is transmitted when a Message Transaction parameter
is in error; for example, the next port number is invalid or /no device is
connected/ to the port associated with the port number."

Sure enough - removing the calls to drm_dp_mst_port_downstream_of_branch()
and instead checking the ->ddps field of the parent port to see whether we
should release a given payload or not seems to totally fix the issue. This
does actually make sense to me, as it seems the implication is that given a
topology where an MSTB is removed, the payload for the MST parent's port
will be released automatically if that port is also marked as disconnected.
However, if there's another parent in the chain after that which is
connected - payloads must be released there with an ALLOCATE_PAYLOAD
message.

So, let's do that!

Signed-off-by: Lyude Paul 
Cc: Wayne Lin 
Cc: Ville Syrjälä 
Cc: Fangzhi Zuo 
Cc: Jani Nikula 
Cc: Imre Deak 
Cc: Daniel Vetter 
Cc: Sean Paul 
---
 drivers/gpu/drm/display/drm_dp_mst_topology.c | 51 +++
 1 file changed, 17 insertions(+), 34 deletions(-)

diff --git a/drivers/gpu/drm/display/drm_dp_mst_topology.c 
b/drivers/gpu/drm/display/drm_dp_mst_topology.c
index dd314586bac3..70adb8db4335 100644
--- a/drivers/gpu/drm/display/drm_dp_mst_topology.c
+++ b/drivers/gpu/drm/display/drm_dp_mst_topology.c
@@ -3137,7 +3137,7 @@ static struct drm_dp_mst_port 
*drm_dp_get_last_connected_port_to_mstb(struct drm
 static struct drm_dp_mst_branch *
 drm_dp_get_last_connected_port_and_mstb(struct drm_dp_mst_topology_mgr *mgr,
struct drm_dp_mst_branch *mstb,
-   int *port_num)
+   struct drm_dp_mst_port **last_port)
 {
struct drm_dp_mst_branch *rmstb = NULL;
struct drm_dp_mst_port *found_port;
@@ -3153,7 +3153,8 @@ drm_dp_get_last_connected_port_and_mstb(struct 
drm_dp_mst_topology_mgr *mgr,
 
if (drm_dp_mst_topology_try_get_mstb(found_port->parent)) {
rmstb = found_port->parent;
-   *port_num = found_port->port_num;
+   *last_port = found_port;
+   drm_dp_mst_get_port_malloc(found_port);
} else {
/* Search again, starting from this parent */
mstb = found_port->parent;
@@ -3170,7 +3171,7 @@ static int drm_dp_payload_send_msg(struct 
drm_dp_mst_topology_mgr *mgr,
   int pbn)
 {
struct drm_dp_sideband_msg_tx *txmsg;
-   struct drm_dp_mst_branch *mstb;
+   struct drm_dp_mst_branch *mstb = NULL;
int ret, port_num;
u8 sinks[DRM_DP_MAX_SDP_STREAMS];
int i;
@@ -3178,12 +3179,22 @@ static int drm_dp_payload_send_msg(struct 
drm_dp_mst_topology_mgr *mgr,
port_num = port->port_num;
mstb = drm_dp_mst_topology_get_mstb_validated(mgr, port->parent);
if (!mstb) {
-   mstb = drm_dp_get_last_connected_port_and_mstb(mgr,
-  port->parent,
-  _num);
+   struct drm_dp_mst_port *rport = NULL;
+   bool ddps;
 
+   mstb = drm_dp_get_last_connected_port_and_mstb(mgr, 
port->parent, );
if (!mstb)
return -EINVAL;
+
+   ddps = rport->ddps;
+   port_num = rport->port_num;
+   drm_dp_mst_put_port_malloc(rport);
+
+   /* If the port is currently marked as disconnected, don't send 
a payload message */
+   if (!ddps) {
+   ret = -EINVAL;
+   goto fail_put;
+   }
}
 
txmsg = 

[RESEND RFC 14/18] drm/display/dp_mst: Drop all ports from topology on CSNs before queueing link address work

2022-06-07 Thread Lyude Paul
We want to start cutting down on all of the places that we use port
validation, so that ports may be removed from the topology as quickly as
possible to minimize the number of errors we run into as a result of being
out of sync with the current topology status. This isn't a very typical
scenario and I don't think I've ever even run into it - but since the next
commit is going to make some changes to payload updates depending on their
hotplug status I think it's a probably good idea to take precautions.

Let's do this with CSNs by moving some code around so that we only queue
link address probing work at the end of handling all CSNs - allowing us to
make sure we drop as many topology references as we can beforehand.

Signed-off-by: Lyude Paul 
Cc: Wayne Lin 
Cc: Ville Syrjälä 
Cc: Fangzhi Zuo 
Cc: Jani Nikula 
Cc: Imre Deak 
Cc: Daniel Vetter 
Cc: Sean Paul 
---
 drivers/gpu/drm/display/drm_dp_mst_topology.c | 14 --
 1 file changed, 8 insertions(+), 6 deletions(-)

diff --git a/drivers/gpu/drm/display/drm_dp_mst_topology.c 
b/drivers/gpu/drm/display/drm_dp_mst_topology.c
index a775f9437868..dd314586bac3 100644
--- a/drivers/gpu/drm/display/drm_dp_mst_topology.c
+++ b/drivers/gpu/drm/display/drm_dp_mst_topology.c
@@ -2508,7 +2508,7 @@ drm_dp_mst_handle_link_address_port(struct 
drm_dp_mst_branch *mstb,
return ret;
 }
 
-static void
+static int
 drm_dp_mst_handle_conn_stat(struct drm_dp_mst_branch *mstb,
struct drm_dp_connection_status_notify *conn_stat)
 {
@@ -2521,7 +2521,7 @@ drm_dp_mst_handle_conn_stat(struct drm_dp_mst_branch 
*mstb,
 
port = drm_dp_get_port(mstb, conn_stat->port_number);
if (!port)
-   return;
+   return 0;
 
if (port->connector) {
if (!port->input && conn_stat->input_port) {
@@ -2574,8 +2574,7 @@ drm_dp_mst_handle_conn_stat(struct drm_dp_mst_branch 
*mstb,
 
 out:
drm_dp_mst_topology_put_port(port);
-   if (dowork)
-   queue_work(system_long_wq, >mgr->work);
+   return dowork;
 }
 
 static struct drm_dp_mst_branch *drm_dp_get_mst_branch_device(struct 
drm_dp_mst_topology_mgr *mgr,
@@ -4071,7 +4070,7 @@ drm_dp_mst_process_up_req(struct drm_dp_mst_topology_mgr 
*mgr,
struct drm_dp_mst_branch *mstb = NULL;
struct drm_dp_sideband_msg_req_body *msg = _req->msg;
struct drm_dp_sideband_msg_hdr *hdr = _req->hdr;
-   bool hotplug = false;
+   bool hotplug = false, dowork = false;
 
if (hdr->broadcast) {
const u8 *guid = NULL;
@@ -4094,11 +4093,14 @@ drm_dp_mst_process_up_req(struct 
drm_dp_mst_topology_mgr *mgr,
 
/* TODO: Add missing handler for DP_RESOURCE_STATUS_NOTIFY events */
if (msg->req_type == DP_CONNECTION_STATUS_NOTIFY) {
-   drm_dp_mst_handle_conn_stat(mstb, >u.conn_stat);
+   dowork = drm_dp_mst_handle_conn_stat(mstb, >u.conn_stat);
hotplug = true;
}
 
drm_dp_mst_topology_put_mstb(mstb);
+
+   if (dowork)
+   queue_work(system_long_wq, >work);
return hotplug;
 }
 
-- 
2.35.3



[RESEND RFC 09/18] drm/display/dp_mst: Don't open code modeset checks for releasing time slots

2022-06-07 Thread Lyude Paul
I'm not sure why, but at the time I originally wrote the find/release time
slot helpers I thought we should avoid keeping modeset tracking out of the
MST helpers. In retrospect though there's no actual good reason to do
this, and the logic has ended up being identical across all the drivers
using the helpers. Also, it needs to be fixed anyway so we don't break
things when going atomic-only with MST.

So, let's just move this code into drm_dp_atomic_release_time_slots() and
stop open coding it.

Signed-off-by: Lyude Paul 
Cc: Wayne Lin 
Cc: Ville Syrjälä 
Cc: Fangzhi Zuo 
Cc: Jani Nikula 
Cc: Imre Deak 
Cc: Daniel Vetter 
Cc: Sean Paul 
---
 .../display/amdgpu_dm/amdgpu_dm_mst_types.c   | 29 +++
 drivers/gpu/drm/display/drm_dp_mst_topology.c | 21 --
 drivers/gpu/drm/i915/display/intel_dp_mst.c   | 24 +--
 drivers/gpu/drm/nouveau/dispnv50/disp.c   | 21 --
 4 files changed, 23 insertions(+), 72 deletions(-)

diff --git a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_mst_types.c 
b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_mst_types.c
index e40ff51e7be0..b447c453b58d 100644
--- a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_mst_types.c
+++ b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_mst_types.c
@@ -353,34 +353,13 @@ dm_dp_mst_detect(struct drm_connector *connector,
 }
 
 static int dm_dp_mst_atomic_check(struct drm_connector *connector,
-   struct drm_atomic_state *state)
+ struct drm_atomic_state *state)
 {
-   struct drm_connector_state *new_conn_state =
-   drm_atomic_get_new_connector_state(state, connector);
-   struct drm_connector_state *old_conn_state =
-   drm_atomic_get_old_connector_state(state, connector);
struct amdgpu_dm_connector *aconnector = 
to_amdgpu_dm_connector(connector);
-   struct drm_crtc_state *new_crtc_state;
-   struct drm_dp_mst_topology_mgr *mst_mgr;
-   struct drm_dp_mst_port *mst_port;
+   struct drm_dp_mst_topology_mgr *mst_mgr = 
>mst_port->mst_mgr;
+   struct drm_dp_mst_port *mst_port = aconnector->port;
 
-   mst_port = aconnector->port;
-   mst_mgr = >mst_port->mst_mgr;
-
-   if (!old_conn_state->crtc)
-   return 0;
-
-   if (new_conn_state->crtc) {
-   new_crtc_state = drm_atomic_get_new_crtc_state(state, 
new_conn_state->crtc);
-   if (!new_crtc_state ||
-   !drm_atomic_crtc_needs_modeset(new_crtc_state) ||
-   new_crtc_state->enable)
-   return 0;
-   }
-
-   return drm_dp_atomic_release_time_slots(state,
-   mst_mgr,
-   mst_port);
+   return drm_dp_atomic_release_time_slots(state, mst_mgr, mst_port);
 }
 
 static const struct drm_connector_helper_funcs 
dm_dp_mst_connector_helper_funcs = {
diff --git a/drivers/gpu/drm/display/drm_dp_mst_topology.c 
b/drivers/gpu/drm/display/drm_dp_mst_topology.c
index a0ed29f83556..e73b34c0cc9e 100644
--- a/drivers/gpu/drm/display/drm_dp_mst_topology.c
+++ b/drivers/gpu/drm/display/drm_dp_mst_topology.c
@@ -4484,14 +4484,29 @@ int drm_dp_atomic_release_time_slots(struct 
drm_atomic_state *state,
 {
struct drm_dp_mst_topology_state *topology_state;
struct drm_dp_mst_atomic_payload *payload;
-   struct drm_connector_state *conn_state;
+   struct drm_connector_state *old_conn_state, *new_conn_state;
+
+   old_conn_state = drm_atomic_get_old_connector_state(state, 
port->connector);
+   if (!old_conn_state->crtc)
+   return 0;
+
+   /* If the CRTC isn't disabled by this state, don't release it's payload 
*/
+   new_conn_state = drm_atomic_get_new_connector_state(state, 
port->connector);
+   if (new_conn_state->crtc) {
+   struct drm_crtc_state *crtc_state =
+   drm_atomic_get_new_crtc_state(state, 
new_conn_state->crtc);
+
+   if (!crtc_state ||
+   !drm_atomic_crtc_needs_modeset(crtc_state) ||
+   crtc_state->enable)
+   return 0;
+   }
 
topology_state = drm_atomic_get_mst_topology_state(state, mgr);
if (IS_ERR(topology_state))
return PTR_ERR(topology_state);
 
-   conn_state = drm_atomic_get_old_connector_state(state, port->connector);
-   topology_state->pending_crtc_mask |= drm_crtc_mask(conn_state->crtc);
+   topology_state->pending_crtc_mask |= 
drm_crtc_mask(old_conn_state->crtc);
 
payload = drm_atomic_get_mst_payload_state(topology_state, port);
if (WARN_ON(!payload)) {
diff --git a/drivers/gpu/drm/i915/display/intel_dp_mst.c 
b/drivers/gpu/drm/i915/display/intel_dp_mst.c
index 0c922667398a..4b0af3c26176 100644
--- a/drivers/gpu/drm/i915/display/intel_dp_mst.c
+++ 

[PATCH 2/3] drm/panel: panel-dsi-cm: Use backlight helpers

2022-06-07 Thread Stephen Kitt
Instead of retrieving the backlight brightness in struct
backlight_properties manually, and then checking whether the backlight
should be on at all, use backlight_get_brightness() which does all
this and insulates this from future changes.

Instead of setting the power state by manually updating fields in
struct backlight_properties, use backlight_enable() and
backlight_disable(). These also call backlight_update_status() so the
separate call is no longer needed.

Signed-off-by: Stephen Kitt 
Cc: Thierry Reding 
Cc: Sam Ravnborg 
Cc: David Airlie 
Cc: Daniel Vetter 
Cc: dri-devel@lists.freedesktop.org
---
 drivers/gpu/drm/panel/panel-dsi-cm.c | 24 
 1 file changed, 4 insertions(+), 20 deletions(-)

diff --git a/drivers/gpu/drm/panel/panel-dsi-cm.c 
b/drivers/gpu/drm/panel/panel-dsi-cm.c
index b58cb064975f..aa36dc6cedd3 100644
--- a/drivers/gpu/drm/panel/panel-dsi-cm.c
+++ b/drivers/gpu/drm/panel/panel-dsi-cm.c
@@ -86,16 +86,10 @@ static void dsicm_bl_power(struct panel_drv_data *ddata, 
bool enable)
return;
 
if (enable) {
-   backlight->props.fb_blank = FB_BLANK_UNBLANK;
-   backlight->props.state = ~(BL_CORE_FBBLANK | BL_CORE_SUSPENDED);
-   backlight->props.power = FB_BLANK_UNBLANK;
+   backlight_enable(backlight);
} else {
-   backlight->props.fb_blank = FB_BLANK_NORMAL;
-   backlight->props.power = FB_BLANK_POWERDOWN;
-   backlight->props.state |= BL_CORE_FBBLANK | BL_CORE_SUSPENDED;
+   backlight_disable(backlight);
}
-
-   backlight_update_status(backlight);
 }
 
 static void hw_guard_start(struct panel_drv_data *ddata, int guard_msec)
@@ -196,13 +190,7 @@ static int dsicm_bl_update_status(struct backlight_device 
*dev)
 {
struct panel_drv_data *ddata = dev_get_drvdata(>dev);
int r = 0;
-   int level;
-
-   if (dev->props.fb_blank == FB_BLANK_UNBLANK &&
-   dev->props.power == FB_BLANK_UNBLANK)
-   level = dev->props.brightness;
-   else
-   level = 0;
+   int level = backlight_get_brightness(dev);
 
dev_dbg(>dsi->dev, "update brightness to %d\n", level);
 
@@ -219,11 +207,7 @@ static int dsicm_bl_update_status(struct backlight_device 
*dev)
 
 static int dsicm_bl_get_intensity(struct backlight_device *dev)
 {
-   if (dev->props.fb_blank == FB_BLANK_UNBLANK &&
-   dev->props.power == FB_BLANK_UNBLANK)
-   return dev->props.brightness;
-
-   return 0;
+   return backlight_get_brightness(dev);
 }
 
 static const struct backlight_ops dsicm_bl_ops = {
-- 
2.30.2



[RESEND RFC 08/18] drm/display/dp_mst: Add nonblocking helpers for DP MST

2022-06-07 Thread Lyude Paul
As Daniel Vetter pointed out, if we only use the atomic modesetting locks
with MST it's technically possible for a driver with non-blocking modesets
to race when it comes to MST displays - as we make the mistake of not doing
our own CRTC commit tracking in the topology_state object.

This could potentially cause problems if something like this happens:

* User starts non-blocking commit to disable CRTC-1 on MST topology 1
* User starts non-blocking commit to enable CRTC-2 on MST topology 1

There's no guarantee here that the commit for disabling CRTC-2 will only
occur after CRTC-1 has finished, since neither commit shares a CRTC - only
the private modesetting object for MST. Keep in mind this likely isn't a
problem for blocking modesets, only non-blocking.

So, begin fixing this by keeping track of which CRTCs on a topology have
changed by keeping track of which CRTCs we release or allocate timeslots
on. As well, add some helpers for:

* Setting up the drm_crtc_commit structs in the ->commit_setup hook
* Waiting for any CRTC dependencies from the previous topology state

Signed-off-by: Lyude Paul 
Cc: Wayne Lin 
Cc: Ville Syrjälä 
Cc: Fangzhi Zuo 
Cc: Jani Nikula 
Cc: Imre Deak 
Cc: Daniel Vetter 
Cc: Sean Paul 
---
 .../gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c |  9 +-
 drivers/gpu/drm/display/drm_dp_mst_topology.c | 93 +++
 drivers/gpu/drm/i915/display/intel_display.c  | 11 +++
 drivers/gpu/drm/nouveau/dispnv50/disp.c   | 12 +++
 include/drm/display/drm_dp_mst_helper.h   | 15 +++
 5 files changed, 139 insertions(+), 1 deletion(-)

diff --git a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c 
b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c
index f84a4ad736d8..d9c7393ef151 100644
--- a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c
+++ b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c
@@ -211,6 +211,7 @@ static int amdgpu_dm_encoder_init(struct drm_device *dev,
 static int amdgpu_dm_connector_get_modes(struct drm_connector *connector);
 
 static void amdgpu_dm_atomic_commit_tail(struct drm_atomic_state *state);
+static int amdgpu_dm_atomic_setup_commit(struct drm_atomic_state *state);
 
 static int amdgpu_dm_atomic_check(struct drm_device *dev,
  struct drm_atomic_state *state);
@@ -2808,7 +2809,8 @@ static const struct drm_mode_config_funcs 
amdgpu_dm_mode_funcs = {
 };
 
 static struct drm_mode_config_helper_funcs amdgpu_dm_mode_config_helperfuncs = 
{
-   .atomic_commit_tail = amdgpu_dm_atomic_commit_tail
+   .atomic_commit_tail = amdgpu_dm_atomic_commit_tail,
+   .atomic_commit_setup = amdgpu_dm_atomic_setup_commit,
 };
 
 static void update_connector_ext_caps(struct amdgpu_dm_connector *aconnector)
@@ -9558,6 +9560,7 @@ static void amdgpu_dm_atomic_commit_tail(struct 
drm_atomic_state *state)
DRM_ERROR("Waiting for fences timed out!");
 
drm_atomic_helper_update_legacy_modeset_state(dev, state);
+   drm_dp_mst_atomic_wait_for_dependencies(state);
 
dm_state = dm_atomic_get_new_state(state);
if (dm_state && dm_state->context) {
@@ -9958,6 +9961,10 @@ static void amdgpu_dm_atomic_commit_tail(struct 
drm_atomic_state *state)
dc_release_state(dc_state_temp);
 }
 
+static int amdgpu_dm_atomic_setup_commit(struct drm_atomic_state *state)
+{
+   return drm_dp_mst_atomic_setup_commit(state);
+}
 
 static int dm_force_atomic_commit(struct drm_connector *connector)
 {
diff --git a/drivers/gpu/drm/display/drm_dp_mst_topology.c 
b/drivers/gpu/drm/display/drm_dp_mst_topology.c
index 0bc2c7a90c37..a0ed29f83556 100644
--- a/drivers/gpu/drm/display/drm_dp_mst_topology.c
+++ b/drivers/gpu/drm/display/drm_dp_mst_topology.c
@@ -4395,12 +4395,16 @@ int drm_dp_atomic_find_time_slots(struct 
drm_atomic_state *state,
 {
struct drm_dp_mst_topology_state *topology_state;
struct drm_dp_mst_atomic_payload *payload = NULL;
+   struct drm_connector_state *conn_state;
int prev_slots = 0, prev_bw = 0, req_slots;
 
topology_state = drm_atomic_get_mst_topology_state(state, mgr);
if (IS_ERR(topology_state))
return PTR_ERR(topology_state);
 
+   conn_state = drm_atomic_get_new_connector_state(state, port->connector);
+   topology_state->pending_crtc_mask |= drm_crtc_mask(conn_state->crtc);
+
/* Find the current allocation for this port, if any */
payload = drm_atomic_get_mst_payload_state(topology_state, port);
if (payload) {
@@ -4480,11 +4484,15 @@ int drm_dp_atomic_release_time_slots(struct 
drm_atomic_state *state,
 {
struct drm_dp_mst_topology_state *topology_state;
struct drm_dp_mst_atomic_payload *payload;
+   struct drm_connector_state *conn_state;
 
topology_state = drm_atomic_get_mst_topology_state(state, mgr);
if (IS_ERR(topology_state))
return PTR_ERR(topology_state);
 
+   conn_state = drm_atomic_get_old_connector_state(state, 

[RESEND RFC 12/18] drm/nouveau/kms: Pull mst state in for all modesets

2022-06-07 Thread Lyude Paul
Since we're going to be relying on atomic locking for payloads now (and the
MST mgr needs to track CRTCs), pull in the topology state for all modesets
in nv50_msto_atomic_check().

Signed-off-by: Lyude Paul 
---
 drivers/gpu/drm/nouveau/dispnv50/disp.c | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/drivers/gpu/drm/nouveau/dispnv50/disp.c 
b/drivers/gpu/drm/nouveau/dispnv50/disp.c
index 461e5e3345f8..834a5c5b77d5 100644
--- a/drivers/gpu/drm/nouveau/dispnv50/disp.c
+++ b/drivers/gpu/drm/nouveau/dispnv50/disp.c
@@ -1054,7 +1054,7 @@ nv50_msto_atomic_check(struct drm_encoder *encoder,
if (ret)
return ret;
 
-   if (!crtc_state->mode_changed && !crtc_state->connectors_changed)
+   if (!drm_atomic_crtc_needs_modeset(crtc_state))
return 0;
 
/*
-- 
2.35.3



[RESEND RFC 10/18] drm/display/dp_mst: Fix modeset tracking in drm_dp_atomic_release_vcpi_slots()

2022-06-07 Thread Lyude Paul
Currently with the MST helpers we avoid releasing payloads _and_ avoid
pulling in the MST state if there aren't any actual payload changes. While
we want to keep the first step, we need to now make sure that we're always
pulling in the MST state on all modesets that can modify payloads - even if
the resulting payloads in the atomic state are identical to the previous
ones.

This is mainly to make it so that if a CRTC is still assigned to a
connector but is set to DPMS off, the CRTC still holds it's payload
allocation in the atomic state and still appropriately pulls in the MST
state for commit tracking. Otherwise, we'll occasionally forget to update
MST payloads from changes caused by non-atomic DPMS changes. Doing this
also allows us to track bandwidth limitations in a state correctly even
between DPMS changes, so that there's no chance of a simple ->active change
being rejected by the atomic check.

Signed-off-by: Lyude Paul 
Cc: Wayne Lin 
Cc: Ville Syrjälä 
Cc: Fangzhi Zuo 
Cc: Jani Nikula 
Cc: Imre Deak 
Cc: Daniel Vetter 
Cc: Sean Paul 
---
 drivers/gpu/drm/display/drm_dp_mst_topology.c | 11 ---
 1 file changed, 8 insertions(+), 3 deletions(-)

diff --git a/drivers/gpu/drm/display/drm_dp_mst_topology.c 
b/drivers/gpu/drm/display/drm_dp_mst_topology.c
index e73b34c0cc9e..c5edcf2a26c8 100644
--- a/drivers/gpu/drm/display/drm_dp_mst_topology.c
+++ b/drivers/gpu/drm/display/drm_dp_mst_topology.c
@@ -4485,6 +4485,7 @@ int drm_dp_atomic_release_time_slots(struct 
drm_atomic_state *state,
struct drm_dp_mst_topology_state *topology_state;
struct drm_dp_mst_atomic_payload *payload;
struct drm_connector_state *old_conn_state, *new_conn_state;
+   bool update_payload = true;
 
old_conn_state = drm_atomic_get_old_connector_state(state, 
port->connector);
if (!old_conn_state->crtc)
@@ -4496,10 +4497,12 @@ int drm_dp_atomic_release_time_slots(struct 
drm_atomic_state *state,
struct drm_crtc_state *crtc_state =
drm_atomic_get_new_crtc_state(state, 
new_conn_state->crtc);
 
-   if (!crtc_state ||
-   !drm_atomic_crtc_needs_modeset(crtc_state) ||
-   crtc_state->enable)
+   /* No modeset means no payload changes, so it's safe to not 
pull in the MST state */
+   if (!crtc_state || !drm_atomic_crtc_needs_modeset(crtc_state))
return 0;
+
+   if (!crtc_state->mode_changed && 
!crtc_state->connectors_changed)
+   update_payload = false;
}
 
topology_state = drm_atomic_get_mst_topology_state(state, mgr);
@@ -4507,6 +4510,8 @@ int drm_dp_atomic_release_time_slots(struct 
drm_atomic_state *state,
return PTR_ERR(topology_state);
 
topology_state->pending_crtc_mask |= 
drm_crtc_mask(old_conn_state->crtc);
+   if (!update_payload)
+   return 0;
 
payload = drm_atomic_get_mst_payload_state(topology_state, port);
if (WARN_ON(!payload)) {
-- 
2.35.3



[RESEND RFC 11/18] drm/nouveau/kms: Cache DP encoders in nouveau_connector

2022-06-07 Thread Lyude Paul
Post-NV50, the only kind of encoder you'll find for DP connectors on Nvidia
GPUs are SORs (serial output resources). Because SORs have fixed
associations with their connectors, we can correctly assume that any DP
connector on a nvidia GPU will have exactly one SOR encoder routed to it
for DisplayPort.

Since we're going to need to be able to retrieve this fixed SOR DP encoder
much more often as a result of hooking up MST helpers for tracking
SST<->MST transitions in atomic states, let's simply cache this encoder in
nouveau_connector for any DP connectors on the system to avoid looking it
up each time. This isn't safe for NV50 since PIORs then come into play,
however there's no code pre-NV50 that would need to look this up anyhow -
so it's not really an issue.

Signed-off-by: Lyude Paul 
---
 drivers/gpu/drm/nouveau/nouveau_connector.c | 4 +++-
 drivers/gpu/drm/nouveau/nouveau_connector.h | 3 +++
 2 files changed, 6 insertions(+), 1 deletion(-)

diff --git a/drivers/gpu/drm/nouveau/nouveau_connector.c 
b/drivers/gpu/drm/nouveau/nouveau_connector.c
index 22b83a6577eb..ffbd8a9cf2af 100644
--- a/drivers/gpu/drm/nouveau/nouveau_connector.c
+++ b/drivers/gpu/drm/nouveau/nouveau_connector.c
@@ -1368,7 +1368,7 @@ nouveau_connector_create(struct drm_device *dev,
kfree(nv_connector);
return ERR_PTR(ret);
}
-   fallthrough;
+   break;
default:
funcs = _connector_funcs;
break;
@@ -1422,6 +1422,8 @@ nouveau_connector_create(struct drm_device *dev,
 
switch (type) {
case DRM_MODE_CONNECTOR_DisplayPort:
+   nv_connector->dp_encoder = find_encoder(_connector->base, 
DCB_OUTPUT_DP);
+   fallthrough;
case DRM_MODE_CONNECTOR_eDP:
drm_dp_cec_register_connector(_connector->aux, connector);
break;
diff --git a/drivers/gpu/drm/nouveau/nouveau_connector.h 
b/drivers/gpu/drm/nouveau/nouveau_connector.h
index b0773af5a98f..f468c181d9a3 100644
--- a/drivers/gpu/drm/nouveau/nouveau_connector.h
+++ b/drivers/gpu/drm/nouveau/nouveau_connector.h
@@ -127,6 +127,9 @@ struct nouveau_connector {
 
struct drm_dp_aux aux;
 
+   /* The fixed DP encoder for this connector, if there is one */
+   struct nouveau_encoder *dp_encoder;
+
int dithering_mode;
int scaling_mode;
 
-- 
2.35.3



[RESEND RFC 04/18] drm/display/dp_mst: Call them time slots, not VCPI slots

2022-06-07 Thread Lyude Paul
VCPI is only sort of the correct term here, originally the majority of this
code simply referred to timeslots vaguely as "slots" - and since I started
working on it and adding atomic functionality, the name "VCPI slots" has
been used to represent time slots.

Now that we actually have consistent access to the DisplayPort spec thanks
to VESA, I now know this isn't actually the proper term - as the
specification refers to these as time slots.

Since we're trying to make this code as easy to figure out as possible,
let's take this opportunity to correct this nomenclature and call them by
their proper name - timeslots. Likewise, we rename various functions
appropriately, along with replacing references in the kernel documentation
and various debugging messages.

It's important to note that this patch series leaves the legacy MST code
untouched for the most part, which is fine since we'll be removing it soon
anyhow. There should be no functional changes in this series.

Signed-off-by: Lyude Paul 
Cc: Wayne Lin 
Cc: Ville Syrjälä 
Cc: Fangzhi Zuo 
Cc: Jani Nikula 
Cc: Imre Deak 
Cc: Daniel Vetter 
Cc: Sean Paul 
---
 .../gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c |   2 +-
 .../display/amdgpu_dm/amdgpu_dm_mst_types.c   |  28 ++---
 drivers/gpu/drm/display/drm_dp_mst_topology.c | 106 +-
 drivers/gpu/drm/i915/display/intel_dp_mst.c   |   5 +-
 drivers/gpu/drm/nouveau/dispnv50/disp.c   |   4 +-
 include/drm/display/drm_dp_mst_helper.h   |   6 +-
 6 files changed, 75 insertions(+), 76 deletions(-)

diff --git a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c 
b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c
index ad4571190a90..f84a4ad736d8 100644
--- a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c
+++ b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c
@@ -7393,7 +7393,7 @@ static int dm_encoder_helper_atomic_check(struct 
drm_encoder *encoder,
clock = adjusted_mode->clock;
dm_new_connector_state->pbn = drm_dp_calc_pbn_mode(clock, bpp, 
false);
}
-   dm_new_connector_state->vcpi_slots = 
drm_dp_atomic_find_vcpi_slots(state,
+   dm_new_connector_state->vcpi_slots = 
drm_dp_atomic_find_time_slots(state,
   
mst_mgr,
   
mst_port,
   
dm_new_connector_state->pbn,
diff --git a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_mst_types.c 
b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_mst_types.c
index 9221b6690a4a..e40ff51e7be0 100644
--- a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_mst_types.c
+++ b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_mst_types.c
@@ -378,7 +378,7 @@ static int dm_dp_mst_atomic_check(struct drm_connector 
*connector,
return 0;
}
 
-   return drm_dp_atomic_release_vcpi_slots(state,
+   return drm_dp_atomic_release_time_slots(state,
mst_mgr,
mst_port);
 }
@@ -689,7 +689,7 @@ static void increase_dsc_bpp(struct drm_atomic_state *state,
 
if (initial_slack[next_index] > fair_pbn_alloc) {
vars[next_index].pbn += fair_pbn_alloc;
-   if (drm_dp_atomic_find_vcpi_slots(state,
+   if (drm_dp_atomic_find_time_slots(state,
  
params[next_index].port->mgr,
  
params[next_index].port,
  vars[next_index].pbn,
@@ -699,7 +699,7 @@ static void increase_dsc_bpp(struct drm_atomic_state *state,
vars[next_index].bpp_x16 = 
bpp_x16_from_pbn(params[next_index], vars[next_index].pbn);
} else {
vars[next_index].pbn -= fair_pbn_alloc;
-   if (drm_dp_atomic_find_vcpi_slots(state,
+   if (drm_dp_atomic_find_time_slots(state,
  
params[next_index].port->mgr,
  
params[next_index].port,
  
vars[next_index].pbn,
@@ -708,7 +708,7 @@ static void increase_dsc_bpp(struct drm_atomic_state *state,
}
} else {
vars[next_index].pbn += initial_slack[next_index];
-   if (drm_dp_atomic_find_vcpi_slots(state,
+   if (drm_dp_atomic_find_time_slots(state,
  
params[next_index].port->mgr,
  
params[next_index].port,

[RESEND RFC 07/18] drm/display/dp_mst: Add helper for finding payloads in atomic MST state

2022-06-07 Thread Lyude Paul
We already open-code this quite often, and will be iterating through
payloads even more once we've moved all of the payload tracking into the
atomic state. So, let's add a helper for doing this.

Signed-off-by: Lyude Paul 
Cc: Wayne Lin 
Cc: Ville Syrjälä 
Cc: Fangzhi Zuo 
Cc: Jani Nikula 
Cc: Imre Deak 
Cc: Daniel Vetter 
Cc: Sean Paul 
---
 drivers/gpu/drm/display/drm_dp_mst_topology.c | 109 --
 1 file changed, 45 insertions(+), 64 deletions(-)

diff --git a/drivers/gpu/drm/display/drm_dp_mst_topology.c 
b/drivers/gpu/drm/display/drm_dp_mst_topology.c
index ec52f91b1f0e..0bc2c7a90c37 100644
--- a/drivers/gpu/drm/display/drm_dp_mst_topology.c
+++ b/drivers/gpu/drm/display/drm_dp_mst_topology.c
@@ -1737,6 +1737,19 @@ drm_dp_mst_dump_port_topology_history(struct 
drm_dp_mst_port *port) {}
 #define save_port_topology_ref(port, type)
 #endif
 
+static struct drm_dp_mst_atomic_payload *
+drm_atomic_get_mst_payload_state(struct drm_dp_mst_topology_state *state,
+struct drm_dp_mst_port *port)
+{
+   struct drm_dp_mst_atomic_payload *payload;
+
+   list_for_each_entry(payload, >payloads, next)
+   if (payload->port == port)
+   return payload;
+
+   return NULL;
+}
+
 static void drm_dp_destroy_mst_branch_device(struct kref *kref)
 {
struct drm_dp_mst_branch *mstb =
@@ -4381,39 +4394,31 @@ int drm_dp_atomic_find_time_slots(struct 
drm_atomic_state *state,
  int pbn_div)
 {
struct drm_dp_mst_topology_state *topology_state;
-   struct drm_dp_mst_atomic_payload *pos, *payload = NULL;
-   int prev_slots, prev_bw, req_slots;
+   struct drm_dp_mst_atomic_payload *payload = NULL;
+   int prev_slots = 0, prev_bw = 0, req_slots;
 
topology_state = drm_atomic_get_mst_topology_state(state, mgr);
if (IS_ERR(topology_state))
return PTR_ERR(topology_state);
 
/* Find the current allocation for this port, if any */
-   list_for_each_entry(pos, _state->payloads, next) {
-   if (pos->port == port) {
-   payload = pos;
-   prev_slots = payload->time_slots;
-   prev_bw = payload->pbn;
-
-   /*
-* This should never happen, unless the driver tries
-* releasing and allocating the same timeslot 
allocation,
-* which is an error
-*/
-   if (WARN_ON(!prev_slots)) {
-   drm_err(mgr->dev,
-   "cannot allocate and release time slots 
on [MST PORT:%p] in the same state\n",
-   port);
-   return -EINVAL;
-   }
+   payload = drm_atomic_get_mst_payload_state(topology_state, port);
+   if (payload) {
+   prev_slots = payload->time_slots;
+   prev_bw = payload->pbn;
 
-   break;
+   /*
+* This should never happen, unless the driver tries
+* releasing and allocating the same timeslot allocation,
+* which is an error
+*/
+   if (WARN_ON(!prev_slots)) {
+   drm_err(mgr->dev,
+   "cannot allocate and release time slots on [MST 
PORT:%p] in the same state\n",
+   port);
+   return -EINVAL;
}
}
-   if (!payload) {
-   prev_slots = 0;
-   prev_bw = 0;
-   }
 
if (pbn_div <= 0)
pbn_div = mgr->pbn_div;
@@ -4474,30 +4479,24 @@ int drm_dp_atomic_release_time_slots(struct 
drm_atomic_state *state,
 struct drm_dp_mst_port *port)
 {
struct drm_dp_mst_topology_state *topology_state;
-   struct drm_dp_mst_atomic_payload *pos;
-   bool found = false;
+   struct drm_dp_mst_atomic_payload *payload;
 
topology_state = drm_atomic_get_mst_topology_state(state, mgr);
if (IS_ERR(topology_state))
return PTR_ERR(topology_state);
 
-   list_for_each_entry(pos, _state->payloads, next) {
-   if (pos->port == port) {
-   found = true;
-   break;
-   }
-   }
-   if (WARN_ON(!found)) {
+   payload = drm_atomic_get_mst_payload_state(topology_state, port);
+   if (WARN_ON(!payload)) {
drm_err(mgr->dev, "No payload for [MST PORT:%p] found in mst 
state %p\n",
port, _state->base);
return -EINVAL;
}
 
-   drm_dbg_atomic(mgr->dev, "[MST PORT:%p] TU %d -> 0\n", port, 
pos->time_slots);
-   if (pos->time_slots) {
+   drm_dbg_atomic(mgr->dev, "[MST PORT:%p] TU %d -> 0\n", port, 

[RESEND RFC 06/18] drm/display/dp_mst: Add some missing kdocs for atomic MST structs

2022-06-07 Thread Lyude Paul
Since we're about to start adding some stuff here, we may as well fill in
any missing documentation that we forgot to write.

Signed-off-by: Lyude Paul 
Cc: Wayne Lin 
Cc: Ville Syrjälä 
Cc: Fangzhi Zuo 
Cc: Jani Nikula 
Cc: Imre Deak 
Cc: Daniel Vetter 
Cc: Sean Paul 
---
 include/drm/display/drm_dp_mst_helper.h | 24 
 1 file changed, 24 insertions(+)

diff --git a/include/drm/display/drm_dp_mst_helper.h 
b/include/drm/display/drm_dp_mst_helper.h
index 8ab4f14f2344..eb0ea578b227 100644
--- a/include/drm/display/drm_dp_mst_helper.h
+++ b/include/drm/display/drm_dp_mst_helper.h
@@ -542,19 +542,43 @@ struct drm_dp_payload {
 
 #define to_dp_mst_topology_state(x) container_of(x, struct 
drm_dp_mst_topology_state, base)
 
+/**
+ * struct drm_dp_mst_atomic_payload - Atomic state struct for an MST payload
+ *
+ * The primary atomic state structure for a given MST payload. Stores 
information like current
+ * bandwidth allocation, intended action for this payload, etc.
+ */
 struct drm_dp_mst_atomic_payload {
+   /** @port: The MST port assigned to this payload */
struct drm_dp_mst_port *port;
+   /** @time_slots: The number of timeslots allocated to this payload */
int time_slots;
+   /** @pbn: The payload bandwidth for this payload */
int pbn;
+   /** @dsc_enabled: Whether or not this payload has DSC enabled */
bool dsc_enabled;
+
+   /** @next: The list node for this payload */
struct list_head next;
 };
 
+/**
+ * struct drm_dp_mst_topology_state - DisplayPort MST topology atomic state
+ *
+ * This struct represents the atomic state of the toplevel DisplayPort MST 
manager
+ */
 struct drm_dp_mst_topology_state {
+   /** @base: Base private state for atomic */
struct drm_private_state base;
+
+   /** @payloads: The list of payloads being created/destroyed in this 
state */
struct list_head payloads;
+   /** @mgr: The topology manager */
struct drm_dp_mst_topology_mgr *mgr;
+
+   /** @total_avail_slots: The total number of slots this topology can 
handle (63 or 64) */
u8 total_avail_slots;
+   /** @start_slot: The first usable time slot in this topology (1 or 0) */
u8 start_slot;
 };
 
-- 
2.35.3



[RESEND RFC 05/18] drm/display/dp_mst: Fix confusing docs for drm_dp_atomic_release_time_slots()

2022-06-07 Thread Lyude Paul
For some reason we mention returning 0 if "slots have been added back to
drm_dp_mst_topology_state->avail_slots". This is totally misleading,
avail_slots is simply for figuring out the total number of slots available
in total on the topology and has no relation to the current payload
allocations.

So, let's get rid of that comment.

Signed-off-by: Lyude Paul 
Cc: Wayne Lin 
Cc: Ville Syrjälä 
Cc: Fangzhi Zuo 
Cc: Jani Nikula 
Cc: Imre Deak 
Cc: Daniel Vetter 
Cc: Sean Paul 
---
 drivers/gpu/drm/display/drm_dp_mst_topology.c | 3 +--
 1 file changed, 1 insertion(+), 2 deletions(-)

diff --git a/drivers/gpu/drm/display/drm_dp_mst_topology.c 
b/drivers/gpu/drm/display/drm_dp_mst_topology.c
index 702ff5d9ecc7..ec52f91b1f0e 100644
--- a/drivers/gpu/drm/display/drm_dp_mst_topology.c
+++ b/drivers/gpu/drm/display/drm_dp_mst_topology.c
@@ -4467,8 +4467,7 @@ EXPORT_SYMBOL(drm_dp_atomic_find_time_slots);
  * drm_dp_mst_atomic_check()
  *
  * Returns:
- * 0 if all slots for this port were added back to
- * _dp_mst_topology_state.avail_slots or negative error code
+ * 0 on success, negative error code otherwise
  */
 int drm_dp_atomic_release_time_slots(struct drm_atomic_state *state,
 struct drm_dp_mst_topology_mgr *mgr,
-- 
2.35.3



[RESEND RFC 01/18] drm/amdgpu/dc/mst: Rename dp_mst_stream_allocation(_table)

2022-06-07 Thread Lyude Paul
Just to make this more clear to outside contributors that these are
DC-specific structs, as this also threw me into a loop a number of times
before I figured out the purpose of this.

Signed-off-by: Lyude Paul 
Cc: Wayne Lin 
Cc: Fangzhi Zuo 
---
 .../gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_helpers.c |  9 -
 drivers/gpu/drm/amd/display/dc/core/dc_link.c | 10 +-
 drivers/gpu/drm/amd/display/dc/dm_helpers.h   |  4 ++--
 .../gpu/drm/amd/display/include/link_service_types.h  | 11 ---
 4 files changed, 19 insertions(+), 15 deletions(-)

diff --git a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_helpers.c 
b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_helpers.c
index 7c799ddc1d27..1bd70d306c22 100644
--- a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_helpers.c
+++ b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_helpers.c
@@ -153,9 +153,8 @@ enum dc_edid_status dm_helpers_parse_edid_caps(
return result;
 }
 
-static void get_payload_table(
-   struct amdgpu_dm_connector *aconnector,
-   struct dp_mst_stream_allocation_table *proposed_table)
+static void get_payload_table(struct amdgpu_dm_connector *aconnector,
+ struct dc_dp_mst_stream_allocation_table 
*proposed_table)
 {
int i;
struct drm_dp_mst_topology_mgr *mst_mgr =
@@ -177,7 +176,7 @@ static void get_payload_table(
mst_mgr->payloads[i].payload_state ==
DP_PAYLOAD_REMOTE) {
 
-   struct dp_mst_stream_allocation *sa =
+   struct dc_dp_mst_stream_allocation *sa =
_table->stream_allocations[
proposed_table->stream_count];
 
@@ -201,7 +200,7 @@ void dm_helpers_dp_update_branch_info(
 bool dm_helpers_dp_mst_write_payload_allocation_table(
struct dc_context *ctx,
const struct dc_stream_state *stream,
-   struct dp_mst_stream_allocation_table *proposed_table,
+   struct dc_dp_mst_stream_allocation_table *proposed_table,
bool enable)
 {
struct amdgpu_dm_connector *aconnector;
diff --git a/drivers/gpu/drm/amd/display/dc/core/dc_link.c 
b/drivers/gpu/drm/amd/display/dc/core/dc_link.c
index a789ea8af27f..db0f5158a0c2 100644
--- a/drivers/gpu/drm/amd/display/dc/core/dc_link.c
+++ b/drivers/gpu/drm/amd/display/dc/core/dc_link.c
@@ -3424,7 +3424,7 @@ static void update_mst_stream_alloc_table(
struct dc_link *link,
struct stream_encoder *stream_enc,
struct hpo_dp_stream_encoder *hpo_dp_stream_enc, // TODO: Rename 
stream_enc to dio_stream_enc?
-   const struct dp_mst_stream_allocation_table *proposed_table)
+   const struct dc_dp_mst_stream_allocation_table *proposed_table)
 {
struct link_mst_stream_allocation work_table[MAX_CONTROLLER_NUM] = { 0 
};
struct link_mst_stream_allocation *dc_alloc;
@@ -3586,7 +3586,7 @@ enum dc_status dc_link_allocate_mst_payload(struct 
pipe_ctx *pipe_ctx)
 {
struct dc_stream_state *stream = pipe_ctx->stream;
struct dc_link *link = stream->link;
-   struct dp_mst_stream_allocation_table proposed_table = {0};
+   struct dc_dp_mst_stream_allocation_table proposed_table = {0};
struct fixed31_32 avg_time_slots_per_mtp;
struct fixed31_32 pbn;
struct fixed31_32 pbn_per_slot;
@@ -3691,7 +3691,7 @@ enum dc_status dc_link_reduce_mst_payload(struct pipe_ctx 
*pipe_ctx, uint32_t bw
struct fixed31_32 avg_time_slots_per_mtp;
struct fixed31_32 pbn;
struct fixed31_32 pbn_per_slot;
-   struct dp_mst_stream_allocation_table proposed_table = {0};
+   struct dc_dp_mst_stream_allocation_table proposed_table = {0};
uint8_t i;
enum act_return_status ret;
const struct link_hwss *link_hwss = get_link_hwss(link, 
_ctx->link_res);
@@ -3779,7 +3779,7 @@ enum dc_status dc_link_increase_mst_payload(struct 
pipe_ctx *pipe_ctx, uint32_t
struct fixed31_32 pbn;
struct fixed31_32 pbn_per_slot;
struct link_encoder *link_encoder = link->link_enc;
-   struct dp_mst_stream_allocation_table proposed_table = {0};
+   struct dc_dp_mst_stream_allocation_table proposed_table = {0};
uint8_t i;
enum act_return_status ret;
const struct link_hwss *link_hwss = get_link_hwss(link, 
_ctx->link_res);
@@ -3855,7 +3855,7 @@ static enum dc_status deallocate_mst_payload(struct 
pipe_ctx *pipe_ctx)
 {
struct dc_stream_state *stream = pipe_ctx->stream;
struct dc_link *link = stream->link;
-   struct dp_mst_stream_allocation_table proposed_table = {0};
+   struct dc_dp_mst_stream_allocation_table proposed_table = {0};
struct fixed31_32 avg_time_slots_per_mtp = dc_fixpt_from_int(0);
int i;
bool mst_mode = (link->type == dc_connection_mst_branch);
diff --git 

[PATCH 3/7] fbdev: radeon: Use backlight helper

2022-06-07 Thread Stephen Kitt
Instead of retrieving the backlight brightness in struct
backlight_properties manually, and then checking whether the backlight
should be on at all, use backlight_get_brightness() which does all
this and insulates this from future changes.

Signed-off-by: Stephen Kitt 
Cc: Benjamin Herrenschmidt 
Cc: Helge Deller 
Cc: linux-fb...@vger.kernel.org
Cc: dri-devel@lists.freedesktop.org
---
 drivers/video/fbdev/aty/radeon_backlight.c | 6 +-
 1 file changed, 1 insertion(+), 5 deletions(-)

diff --git a/drivers/video/fbdev/aty/radeon_backlight.c 
b/drivers/video/fbdev/aty/radeon_backlight.c
index d2c1263ad260..427adc838f77 100644
--- a/drivers/video/fbdev/aty/radeon_backlight.c
+++ b/drivers/video/fbdev/aty/radeon_backlight.c
@@ -57,11 +57,7 @@ static int radeon_bl_update_status(struct backlight_device 
*bd)
 * backlight. This provides some greater power saving and the display
 * is useless without backlight anyway.
 */
-if (bd->props.power != FB_BLANK_UNBLANK ||
-   bd->props.fb_blank != FB_BLANK_UNBLANK)
-   level = 0;
-   else
-   level = bd->props.brightness;
+   level = backlight_get_brightness(bd);
 
del_timer_sync(>lvds_timer);
radeon_engine_idle();
-- 
2.30.2



[RESEND RFC 03/18] drm/display/dp_mst: Rename drm_dp_mst_vcpi_allocation

2022-06-07 Thread Lyude Paul
In retrospect, the name I chose for this originally is confusing, as
there's a lot more info in here then just the VCPI. This really should be
called a payload. Let's make it more obvious that this is meant to be
related to the atomic state and is about payloads by renaming it to
drm_dp_mst_atomic_payload. Also, rename various variables throughout the
code that use atomic payloads.

Signed-off-by: Lyude Paul 
Cc: Wayne Lin 
Cc: Ville Syrjälä 
Cc: Fangzhi Zuo 
Cc: Jani Nikula 
Cc: Imre Deak 
Cc: Daniel Vetter 
Cc: Sean Paul 
---
 drivers/gpu/drm/display/drm_dp_mst_topology.c | 96 +--
 include/drm/display/drm_dp_mst_helper.h   |  4 +-
 2 files changed, 50 insertions(+), 50 deletions(-)

diff --git a/drivers/gpu/drm/display/drm_dp_mst_topology.c 
b/drivers/gpu/drm/display/drm_dp_mst_topology.c
index 67b3b9697da7..38eecb89e22d 100644
--- a/drivers/gpu/drm/display/drm_dp_mst_topology.c
+++ b/drivers/gpu/drm/display/drm_dp_mst_topology.c
@@ -4381,7 +4381,7 @@ int drm_dp_atomic_find_vcpi_slots(struct drm_atomic_state 
*state,
  int pbn_div)
 {
struct drm_dp_mst_topology_state *topology_state;
-   struct drm_dp_vcpi_allocation *pos, *vcpi = NULL;
+   struct drm_dp_mst_atomic_payload *pos, *payload = NULL;
int prev_slots, prev_bw, req_slots;
 
topology_state = drm_atomic_get_mst_topology_state(state, mgr);
@@ -4389,11 +4389,11 @@ int drm_dp_atomic_find_vcpi_slots(struct 
drm_atomic_state *state,
return PTR_ERR(topology_state);
 
/* Find the current allocation for this port, if any */
-   list_for_each_entry(pos, _state->vcpis, next) {
+   list_for_each_entry(pos, _state->payloads, next) {
if (pos->port == port) {
-   vcpi = pos;
-   prev_slots = vcpi->vcpi;
-   prev_bw = vcpi->pbn;
+   payload = pos;
+   prev_slots = payload->vcpi;
+   prev_bw = payload->pbn;
 
/*
 * This should never happen, unless the driver tries
@@ -4410,7 +4410,7 @@ int drm_dp_atomic_find_vcpi_slots(struct drm_atomic_state 
*state,
break;
}
}
-   if (!vcpi) {
+   if (!payload) {
prev_slots = 0;
prev_bw = 0;
}
@@ -4428,17 +4428,17 @@ int drm_dp_atomic_find_vcpi_slots(struct 
drm_atomic_state *state,
   port, prev_bw, pbn);
 
/* Add the new allocation to the state */
-   if (!vcpi) {
-   vcpi = kzalloc(sizeof(*vcpi), GFP_KERNEL);
-   if (!vcpi)
+   if (!payload) {
+   payload = kzalloc(sizeof(*payload), GFP_KERNEL);
+   if (!payload)
return -ENOMEM;
 
drm_dp_mst_get_port_malloc(port);
-   vcpi->port = port;
-   list_add(>next, _state->vcpis);
+   payload->port = port;
+   list_add(>next, _state->payloads);
}
-   vcpi->vcpi = req_slots;
-   vcpi->pbn = pbn;
+   payload->vcpi = req_slots;
+   payload->pbn = pbn;
 
return req_slots;
 }
@@ -4475,21 +4475,21 @@ int drm_dp_atomic_release_vcpi_slots(struct 
drm_atomic_state *state,
 struct drm_dp_mst_port *port)
 {
struct drm_dp_mst_topology_state *topology_state;
-   struct drm_dp_vcpi_allocation *pos;
+   struct drm_dp_mst_atomic_payload *pos;
bool found = false;
 
topology_state = drm_atomic_get_mst_topology_state(state, mgr);
if (IS_ERR(topology_state))
return PTR_ERR(topology_state);
 
-   list_for_each_entry(pos, _state->vcpis, next) {
+   list_for_each_entry(pos, _state->payloads, next) {
if (pos->port == port) {
found = true;
break;
}
}
if (WARN_ON(!found)) {
-   drm_err(mgr->dev, "no VCPI for [MST PORT:%p] found in mst state 
%p\n",
+   drm_err(mgr->dev, "No payload for [MST PORT:%p] found in mst 
state %p\n",
port, _state->base);
return -EINVAL;
}
@@ -5072,7 +5072,7 @@ drm_dp_mst_duplicate_state(struct drm_private_obj *obj)
 {
struct drm_dp_mst_topology_state *state, *old_state =
to_dp_mst_topology_state(obj->state);
-   struct drm_dp_vcpi_allocation *pos, *vcpi;
+   struct drm_dp_mst_atomic_payload *pos, *payload;
 
state = kmemdup(old_state, sizeof(*state), GFP_KERNEL);
if (!state)
@@ -5080,25 +5080,25 @@ drm_dp_mst_duplicate_state(struct drm_private_obj *obj)
 
__drm_atomic_helper_private_obj_duplicate_state(obj, >base);
 
-   INIT_LIST_HEAD(>vcpis);
+   INIT_LIST_HEAD(>payloads);
 
-   list_for_each_entry(pos, _state->vcpis, next) {
+   list_for_each_entry(pos, 

[PATCH 4/7] fbdev: mx3fb: Use backlight helper

2022-06-07 Thread Stephen Kitt
Instead of retrieving the backlight brightness in struct
backlight_properties manually, and then checking whether the backlight
should be on at all, use backlight_get_brightness() which does all
this and insulates this from future changes.

Signed-off-by: Stephen Kitt 
Cc: Helge Deller 
Cc: linux-fb...@vger.kernel.org
Cc: dri-devel@lists.freedesktop.org
---
 drivers/video/fbdev/mx3fb.c | 7 +--
 1 file changed, 1 insertion(+), 6 deletions(-)

diff --git a/drivers/video/fbdev/mx3fb.c b/drivers/video/fbdev/mx3fb.c
index b945b68984b9..76771e126d0a 100644
--- a/drivers/video/fbdev/mx3fb.c
+++ b/drivers/video/fbdev/mx3fb.c
@@ -283,12 +283,7 @@ static int mx3fb_bl_get_brightness(struct backlight_device 
*bl)
 static int mx3fb_bl_update_status(struct backlight_device *bl)
 {
struct mx3fb_data *fbd = bl_get_data(bl);
-   int brightness = bl->props.brightness;
-
-   if (bl->props.power != FB_BLANK_UNBLANK)
-   brightness = 0;
-   if (bl->props.fb_blank != FB_BLANK_UNBLANK)
-   brightness = 0;
+   int brightness = backlight_get_brightness(bl);
 
fbd->backlight_level = (fbd->backlight_level & ~0xFF) | brightness;
 
-- 
2.30.2



[RESEND RFC 00/18] drm/display/dp_mst: Drop Radeon MST support, make MST atomic-only

2022-06-07 Thread Lyude Paul
Ugh, thanks ./scripts/get_maintainers.pl for confusing and breaking
git-send email <<. Sorry for the resend everyone.

For quite a while we've been carrying around a lot of legacy modesetting
code in the MST helpers that has been rather annoying to keep around,
and very often gets in the way of trying to implement additional
functionality in MST such as fallback link rate retraining, dynamic BPC
management and DSC support, etc. because of the fact that we can't rely
on atomic for everything.

Luckily, we only actually have one user of the legacy MST code in the
kernel - radeon. Originally I was thinking of trying to maintain this
code and keep it around in some form, but I'm pretty unconvinced anyone
is actually using this. My reasoning for that is because I've seen
nearly no issues regarding MST on radeon for quite a while now - despite
the fact my local testing seems to indicate it's quite broken. This
isn't too surprising either, as MST support in radeon.ko is gated behind
a module parameter that isn't enabled by default. This isn't to say I
wouldn't be open to alternative suggestions, but I'd rather not be the
one to have to spend time on that if at all possible! Plus, I already
floated the idea of dropping this code by AMD folks a few times and
didn't get much resistance.

As well, this series has some basic refactoring that I did along the way
and some bugs I had to fix in order to get my atomic-only MST code
working. Most of this is pretty straight forward and simply renaming
things to more closely match the DisplayPort specification, as I think
this will also make maintaining this code a lot easier in the long run
(I've gotten myself confused way too many times because of this).

So far I've tested this on all three MST drivers: amdgpu, i915 and
nouveau, along with making sure that removing the radeon MST code
doesn't break anything else. The one thing I very much could use help
with regarding testing though is making sure that this works with
amdgpu's DSC support on MST.

So, with this we should be using the atomic state as much as possible
with MST modesetting, hooray!

Cc: Wayne Lin 
Cc: Ville Syrjälä 
Cc: Fangzhi Zuo 
Cc: Jani Nikula 
Cc: Imre Deak 
Cc: Daniel Vetter 
Cc: Sean Paul 

Lyude Paul (18):
  drm/amdgpu/dc/mst: Rename dp_mst_stream_allocation(_table)
  drm/amdgpu/dm/mst: Rename get_payload_table()
  drm/display/dp_mst: Rename drm_dp_mst_vcpi_allocation
  drm/display/dp_mst: Call them time slots, not VCPI slots
  drm/display/dp_mst: Fix confusing docs for
drm_dp_atomic_release_time_slots()
  drm/display/dp_mst: Add some missing kdocs for atomic MST structs
  drm/display/dp_mst: Add helper for finding payloads in atomic MST
state
  drm/display/dp_mst: Add nonblocking helpers for DP MST
  drm/display/dp_mst: Don't open code modeset checks for releasing time
slots
  drm/display/dp_mst: Fix modeset tracking in
drm_dp_atomic_release_vcpi_slots()
  drm/nouveau/kms: Cache DP encoders in nouveau_connector
  drm/nouveau/kms: Pull mst state in for all modesets
  drm/display/dp_mst: Add helpers for serializing SST <-> MST
transitions
  drm/display/dp_mst: Drop all ports from topology on CSNs before
queueing link address work
  drm/display/dp_mst: Skip releasing payloads if last connected port
isn't connected
  drm/display/dp_mst: Maintain time slot allocations when deleting
payloads
  drm/radeon: Drop legacy MST support
  drm/display/dp_mst: Move all payload info into the atomic state

 .../gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c |   72 +-
 .../amd/display/amdgpu_dm/amdgpu_dm_helpers.c |  111 +-
 .../display/amdgpu_dm/amdgpu_dm_mst_types.c   |  126 +-
 drivers/gpu/drm/amd/display/dc/core/dc_link.c |   10 +-
 drivers/gpu/drm/amd/display/dc/dm_helpers.h   |4 +-
 .../amd/display/include/link_service_types.h  |   18 +-
 drivers/gpu/drm/display/drm_dp_mst_topology.c | 1160 -
 drivers/gpu/drm/i915/display/intel_display.c  |   11 +
 drivers/gpu/drm/i915/display/intel_dp.c   |9 +
 drivers/gpu/drm/i915/display/intel_dp_mst.c   |   91 +-
 drivers/gpu/drm/i915/display/intel_hdcp.c |   24 +-
 drivers/gpu/drm/nouveau/dispnv50/disp.c   |  202 ++-
 drivers/gpu/drm/nouveau/dispnv50/disp.h   |2 +
 drivers/gpu/drm/nouveau/nouveau_connector.c   |   18 +-
 drivers/gpu/drm/nouveau/nouveau_connector.h   |3 +
 drivers/gpu/drm/radeon/Makefile   |2 +-
 drivers/gpu/drm/radeon/atombios_crtc.c|   11 +-
 drivers/gpu/drm/radeon/atombios_encoders.c|   59 -
 drivers/gpu/drm/radeon/radeon_atombios.c  |2 -
 drivers/gpu/drm/radeon/radeon_connectors.c|   61 +-
 drivers/gpu/drm/radeon/radeon_device.c|1 -
 drivers/gpu/drm/radeon/radeon_dp_mst.c|  778 ---
 drivers/gpu/drm/radeon/radeon_drv.c   |4 -
 drivers/gpu/drm/radeon/radeon_encoders.c  |   14 +-
 drivers/gpu/drm/radeon/radeon_irq_kms.c   |   10 +-
 drivers/gpu/drm/radeon/radeon_mode.h  |   40 -
 

[PATCH 7/7] fbdev: riva: Use backlight helper

2022-06-07 Thread Stephen Kitt
Instead of retrieving the backlight brightness in struct
backlight_properties manually, and then checking whether the backlight
should be on at all, use backlight_get_brightness() which does all
this and insulates this from future changes.

Signed-off-by: Stephen Kitt 
Cc: Antonino Daplas 
Cc: Helge Deller 
Cc: linux-fb...@vger.kernel.org
Cc: dri-devel@lists.freedesktop.org
---
 drivers/video/fbdev/riva/fbdev.c | 8 +---
 1 file changed, 1 insertion(+), 7 deletions(-)

diff --git a/drivers/video/fbdev/riva/fbdev.c b/drivers/video/fbdev/riva/fbdev.c
index 84d5e23ad7d3..534722b38053 100644
--- a/drivers/video/fbdev/riva/fbdev.c
+++ b/drivers/video/fbdev/riva/fbdev.c
@@ -292,13 +292,7 @@ static int riva_bl_update_status(struct backlight_device 
*bd)
 {
struct riva_par *par = bl_get_data(bd);
U032 tmp_pcrt, tmp_pmc;
-   int level;
-
-   if (bd->props.power != FB_BLANK_UNBLANK ||
-   bd->props.fb_blank != FB_BLANK_UNBLANK)
-   level = 0;
-   else
-   level = bd->props.brightness;
+   int level = backlight_get_brightness(bd);
 
tmp_pmc = NV_RD32(par->riva.PMC, 0x10F0) & 0x;
tmp_pcrt = NV_RD32(par->riva.PCRTC0, 0x081C) & 0xFFFC;
-- 
2.30.2



[PATCH 6/7] fbdev: omapfb: panel-dsi-cm: Use backlight helper

2022-06-07 Thread Stephen Kitt
Instead of retrieving the backlight brightness in struct
backlight_properties manually, and then checking whether the backlight
should be on at all, use backlight_get_brightness() which does all
this and insulates this from future changes.

Signed-off-by: Stephen Kitt 
Cc: Helge Deller 
Cc: linux-o...@vger.kernel.org
Cc: linux-fb...@vger.kernel.org
Cc: dri-devel@lists.freedesktop.org
---
 drivers/video/fbdev/omap2/omapfb/displays/panel-dsi-cm.c | 8 +---
 1 file changed, 1 insertion(+), 7 deletions(-)

diff --git a/drivers/video/fbdev/omap2/omapfb/displays/panel-dsi-cm.c 
b/drivers/video/fbdev/omap2/omapfb/displays/panel-dsi-cm.c
index a2c7c5cb1523..236430b5dc52 100644
--- a/drivers/video/fbdev/omap2/omapfb/displays/panel-dsi-cm.c
+++ b/drivers/video/fbdev/omap2/omapfb/displays/panel-dsi-cm.c
@@ -331,13 +331,7 @@ static int dsicm_bl_update_status(struct backlight_device 
*dev)
struct panel_drv_data *ddata = dev_get_drvdata(>dev);
struct omap_dss_device *in = ddata->in;
int r;
-   int level;
-
-   if (dev->props.fb_blank == FB_BLANK_UNBLANK &&
-   dev->props.power == FB_BLANK_UNBLANK)
-   level = dev->props.brightness;
-   else
-   level = 0;
+   int level = backlight_get_brightness(dev);
 
dev_dbg(>pdev->dev, "update brightness to %d\n", level);
 
-- 
2.30.2



[PATCH 2/7] fbdev: atyfb: Use backlight helper

2022-06-07 Thread Stephen Kitt
Instead of retrieving the backlight brightness in struct
backlight_properties manually, and then checking whether the backlight
should be on at all, use backlight_get_brightness() which does all
this and insulates this from future changes.

Signed-off-by: Stephen Kitt 
Cc: Helge Deller 
Cc: linux-fb...@vger.kernel.org
Cc: dri-devel@lists.freedesktop.org
---
 drivers/video/fbdev/aty/atyfb_base.c | 8 +---
 1 file changed, 1 insertion(+), 7 deletions(-)

diff --git a/drivers/video/fbdev/aty/atyfb_base.c 
b/drivers/video/fbdev/aty/atyfb_base.c
index a3e6faed7745..bec2d0c22fb2 100644
--- a/drivers/video/fbdev/aty/atyfb_base.c
+++ b/drivers/video/fbdev/aty/atyfb_base.c
@@ -2218,13 +2218,7 @@ static int aty_bl_update_status(struct backlight_device 
*bd)
 {
struct atyfb_par *par = bl_get_data(bd);
unsigned int reg = aty_ld_lcd(LCD_MISC_CNTL, par);
-   int level;
-
-   if (bd->props.power != FB_BLANK_UNBLANK ||
-   bd->props.fb_blank != FB_BLANK_UNBLANK)
-   level = 0;
-   else
-   level = bd->props.brightness;
+   int level = backlight_get_brightness(bd);
 
reg |= (BLMOD_EN | BIASMOD_EN);
if (level > 0) {
-- 
2.30.2



[PATCH 4/4] backlight: tosa: Use backlight helper

2022-06-07 Thread Stephen Kitt
Instead of retrieving the backlight brightness in struct
backlight_properties manually, and then checking whether the backlight
should be on at all, use backlight_get_brightness() which does all
this and insulates this from future changes.

Signed-off-by: Stephen Kitt 
Cc: Lee Jones 
Cc: Daniel Thompson 
Cc: Jingoo Han 
Cc: Helge Deller 
Cc: dri-devel@lists.freedesktop.org
Cc: linux-fb...@vger.kernel.org
---
 drivers/video/backlight/tosa_bl.c | 7 +--
 1 file changed, 1 insertion(+), 6 deletions(-)

diff --git a/drivers/video/backlight/tosa_bl.c 
b/drivers/video/backlight/tosa_bl.c
index 6df6fcd132e3..5bbb769f9746 100644
--- a/drivers/video/backlight/tosa_bl.c
+++ b/drivers/video/backlight/tosa_bl.c
@@ -50,13 +50,8 @@ static void tosa_bl_set_backlight(struct tosa_bl_data *data, 
int brightness)
 
 static int tosa_bl_update_status(struct backlight_device *dev)
 {
-   struct backlight_properties *props = >props;
struct tosa_bl_data *data = bl_get_data(dev);
-   int power = max(props->power, props->fb_blank);
-   int brightness = props->brightness;
-
-   if (power)
-   brightness = 0;
+   int brightness = backlight_get_brightness(dev);
 
tosa_bl_set_backlight(data, brightness);
 
-- 
2.30.2



[RFC 04/18] drm/display/dp_mst: Call them time slots, not VCPI slots

2022-06-07 Thread Lyude Paul
VCPI is only sort of the correct term here, originally the majority of this
code simply referred to timeslots vaguely as "slots" - and since I started
working on it and adding atomic functionality, the name "VCPI slots" has
been used to represent time slots.

Now that we actually have consistent access to the DisplayPort spec thanks
to VESA, I now know this isn't actually the proper term - as the
specification refers to these as time slots.

Since we're trying to make this code as easy to figure out as possible,
let's take this opportunity to correct this nomenclature and call them by
their proper name - timeslots. Likewise, we rename various functions
appropriately, along with replacing references in the kernel documentation
and various debugging messages.

It's important to note that this patch series leaves the legacy MST code
untouched for the most part, which is fine since we'll be removing it soon
anyhow. There should be no functional changes in this series.

Signed-off-by: Lyude Paul 
Cc: Wayne Lin 
Cc: Ville Syrjälä 
Cc: Fangzhi Zuo 
Cc: Jani Nikula 
Cc: Imre Deak 
Cc: Daniel Vetter 
Cc: Sean Paul 
---
 .../gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c |   2 +-
 .../display/amdgpu_dm/amdgpu_dm_mst_types.c   |  28 ++---
 drivers/gpu/drm/display/drm_dp_mst_topology.c | 106 +-
 drivers/gpu/drm/i915/display/intel_dp_mst.c   |   5 +-
 drivers/gpu/drm/nouveau/dispnv50/disp.c   |   4 +-
 include/drm/display/drm_dp_mst_helper.h   |   6 +-
 6 files changed, 75 insertions(+), 76 deletions(-)

diff --git a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c 
b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c
index ad4571190a90..f84a4ad736d8 100644
--- a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c
+++ b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c
@@ -7393,7 +7393,7 @@ static int dm_encoder_helper_atomic_check(struct 
drm_encoder *encoder,
clock = adjusted_mode->clock;
dm_new_connector_state->pbn = drm_dp_calc_pbn_mode(clock, bpp, 
false);
}
-   dm_new_connector_state->vcpi_slots = 
drm_dp_atomic_find_vcpi_slots(state,
+   dm_new_connector_state->vcpi_slots = 
drm_dp_atomic_find_time_slots(state,
   
mst_mgr,
   
mst_port,
   
dm_new_connector_state->pbn,
diff --git a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_mst_types.c 
b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_mst_types.c
index 9221b6690a4a..e40ff51e7be0 100644
--- a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_mst_types.c
+++ b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_mst_types.c
@@ -378,7 +378,7 @@ static int dm_dp_mst_atomic_check(struct drm_connector 
*connector,
return 0;
}
 
-   return drm_dp_atomic_release_vcpi_slots(state,
+   return drm_dp_atomic_release_time_slots(state,
mst_mgr,
mst_port);
 }
@@ -689,7 +689,7 @@ static void increase_dsc_bpp(struct drm_atomic_state *state,
 
if (initial_slack[next_index] > fair_pbn_alloc) {
vars[next_index].pbn += fair_pbn_alloc;
-   if (drm_dp_atomic_find_vcpi_slots(state,
+   if (drm_dp_atomic_find_time_slots(state,
  
params[next_index].port->mgr,
  
params[next_index].port,
  vars[next_index].pbn,
@@ -699,7 +699,7 @@ static void increase_dsc_bpp(struct drm_atomic_state *state,
vars[next_index].bpp_x16 = 
bpp_x16_from_pbn(params[next_index], vars[next_index].pbn);
} else {
vars[next_index].pbn -= fair_pbn_alloc;
-   if (drm_dp_atomic_find_vcpi_slots(state,
+   if (drm_dp_atomic_find_time_slots(state,
  
params[next_index].port->mgr,
  
params[next_index].port,
  
vars[next_index].pbn,
@@ -708,7 +708,7 @@ static void increase_dsc_bpp(struct drm_atomic_state *state,
}
} else {
vars[next_index].pbn += initial_slack[next_index];
-   if (drm_dp_atomic_find_vcpi_slots(state,
+   if (drm_dp_atomic_find_time_slots(state,
  
params[next_index].port->mgr,
  
params[next_index].port,

[RFC 07/18] drm/display/dp_mst: Add helper for finding payloads in atomic MST state

2022-06-07 Thread Lyude Paul
We already open-code this quite often, and will be iterating through
payloads even more once we've moved all of the payload tracking into the
atomic state. So, let's add a helper for doing this.

Signed-off-by: Lyude Paul 
Cc: Wayne Lin 
Cc: Ville Syrjälä 
Cc: Fangzhi Zuo 
Cc: Jani Nikula 
Cc: Imre Deak 
Cc: Daniel Vetter 
Cc: Sean Paul 
---
 drivers/gpu/drm/display/drm_dp_mst_topology.c | 109 --
 1 file changed, 45 insertions(+), 64 deletions(-)

diff --git a/drivers/gpu/drm/display/drm_dp_mst_topology.c 
b/drivers/gpu/drm/display/drm_dp_mst_topology.c
index ec52f91b1f0e..0bc2c7a90c37 100644
--- a/drivers/gpu/drm/display/drm_dp_mst_topology.c
+++ b/drivers/gpu/drm/display/drm_dp_mst_topology.c
@@ -1737,6 +1737,19 @@ drm_dp_mst_dump_port_topology_history(struct 
drm_dp_mst_port *port) {}
 #define save_port_topology_ref(port, type)
 #endif
 
+static struct drm_dp_mst_atomic_payload *
+drm_atomic_get_mst_payload_state(struct drm_dp_mst_topology_state *state,
+struct drm_dp_mst_port *port)
+{
+   struct drm_dp_mst_atomic_payload *payload;
+
+   list_for_each_entry(payload, >payloads, next)
+   if (payload->port == port)
+   return payload;
+
+   return NULL;
+}
+
 static void drm_dp_destroy_mst_branch_device(struct kref *kref)
 {
struct drm_dp_mst_branch *mstb =
@@ -4381,39 +4394,31 @@ int drm_dp_atomic_find_time_slots(struct 
drm_atomic_state *state,
  int pbn_div)
 {
struct drm_dp_mst_topology_state *topology_state;
-   struct drm_dp_mst_atomic_payload *pos, *payload = NULL;
-   int prev_slots, prev_bw, req_slots;
+   struct drm_dp_mst_atomic_payload *payload = NULL;
+   int prev_slots = 0, prev_bw = 0, req_slots;
 
topology_state = drm_atomic_get_mst_topology_state(state, mgr);
if (IS_ERR(topology_state))
return PTR_ERR(topology_state);
 
/* Find the current allocation for this port, if any */
-   list_for_each_entry(pos, _state->payloads, next) {
-   if (pos->port == port) {
-   payload = pos;
-   prev_slots = payload->time_slots;
-   prev_bw = payload->pbn;
-
-   /*
-* This should never happen, unless the driver tries
-* releasing and allocating the same timeslot 
allocation,
-* which is an error
-*/
-   if (WARN_ON(!prev_slots)) {
-   drm_err(mgr->dev,
-   "cannot allocate and release time slots 
on [MST PORT:%p] in the same state\n",
-   port);
-   return -EINVAL;
-   }
+   payload = drm_atomic_get_mst_payload_state(topology_state, port);
+   if (payload) {
+   prev_slots = payload->time_slots;
+   prev_bw = payload->pbn;
 
-   break;
+   /*
+* This should never happen, unless the driver tries
+* releasing and allocating the same timeslot allocation,
+* which is an error
+*/
+   if (WARN_ON(!prev_slots)) {
+   drm_err(mgr->dev,
+   "cannot allocate and release time slots on [MST 
PORT:%p] in the same state\n",
+   port);
+   return -EINVAL;
}
}
-   if (!payload) {
-   prev_slots = 0;
-   prev_bw = 0;
-   }
 
if (pbn_div <= 0)
pbn_div = mgr->pbn_div;
@@ -4474,30 +4479,24 @@ int drm_dp_atomic_release_time_slots(struct 
drm_atomic_state *state,
 struct drm_dp_mst_port *port)
 {
struct drm_dp_mst_topology_state *topology_state;
-   struct drm_dp_mst_atomic_payload *pos;
-   bool found = false;
+   struct drm_dp_mst_atomic_payload *payload;
 
topology_state = drm_atomic_get_mst_topology_state(state, mgr);
if (IS_ERR(topology_state))
return PTR_ERR(topology_state);
 
-   list_for_each_entry(pos, _state->payloads, next) {
-   if (pos->port == port) {
-   found = true;
-   break;
-   }
-   }
-   if (WARN_ON(!found)) {
+   payload = drm_atomic_get_mst_payload_state(topology_state, port);
+   if (WARN_ON(!payload)) {
drm_err(mgr->dev, "No payload for [MST PORT:%p] found in mst 
state %p\n",
port, _state->base);
return -EINVAL;
}
 
-   drm_dbg_atomic(mgr->dev, "[MST PORT:%p] TU %d -> 0\n", port, 
pos->time_slots);
-   if (pos->time_slots) {
+   drm_dbg_atomic(mgr->dev, "[MST PORT:%p] TU %d -> 0\n", port, 

[RFC 06/18] drm/display/dp_mst: Add some missing kdocs for atomic MST structs

2022-06-07 Thread Lyude Paul
Since we're about to start adding some stuff here, we may as well fill in
any missing documentation that we forgot to write.

Signed-off-by: Lyude Paul 
Cc: Wayne Lin 
Cc: Ville Syrjälä 
Cc: Fangzhi Zuo 
Cc: Jani Nikula 
Cc: Imre Deak 
Cc: Daniel Vetter 
Cc: Sean Paul 
---
 include/drm/display/drm_dp_mst_helper.h | 24 
 1 file changed, 24 insertions(+)

diff --git a/include/drm/display/drm_dp_mst_helper.h 
b/include/drm/display/drm_dp_mst_helper.h
index 8ab4f14f2344..eb0ea578b227 100644
--- a/include/drm/display/drm_dp_mst_helper.h
+++ b/include/drm/display/drm_dp_mst_helper.h
@@ -542,19 +542,43 @@ struct drm_dp_payload {
 
 #define to_dp_mst_topology_state(x) container_of(x, struct 
drm_dp_mst_topology_state, base)
 
+/**
+ * struct drm_dp_mst_atomic_payload - Atomic state struct for an MST payload
+ *
+ * The primary atomic state structure for a given MST payload. Stores 
information like current
+ * bandwidth allocation, intended action for this payload, etc.
+ */
 struct drm_dp_mst_atomic_payload {
+   /** @port: The MST port assigned to this payload */
struct drm_dp_mst_port *port;
+   /** @time_slots: The number of timeslots allocated to this payload */
int time_slots;
+   /** @pbn: The payload bandwidth for this payload */
int pbn;
+   /** @dsc_enabled: Whether or not this payload has DSC enabled */
bool dsc_enabled;
+
+   /** @next: The list node for this payload */
struct list_head next;
 };
 
+/**
+ * struct drm_dp_mst_topology_state - DisplayPort MST topology atomic state
+ *
+ * This struct represents the atomic state of the toplevel DisplayPort MST 
manager
+ */
 struct drm_dp_mst_topology_state {
+   /** @base: Base private state for atomic */
struct drm_private_state base;
+
+   /** @payloads: The list of payloads being created/destroyed in this 
state */
struct list_head payloads;
+   /** @mgr: The topology manager */
struct drm_dp_mst_topology_mgr *mgr;
+
+   /** @total_avail_slots: The total number of slots this topology can 
handle (63 or 64) */
u8 total_avail_slots;
+   /** @start_slot: The first usable time slot in this topology (1 or 0) */
u8 start_slot;
 };
 
-- 
2.35.3



[RFC 05/18] drm/display/dp_mst: Fix confusing docs for drm_dp_atomic_release_time_slots()

2022-06-07 Thread Lyude Paul
For some reason we mention returning 0 if "slots have been added back to
drm_dp_mst_topology_state->avail_slots". This is totally misleading,
avail_slots is simply for figuring out the total number of slots available
in total on the topology and has no relation to the current payload
allocations.

So, let's get rid of that comment.

Signed-off-by: Lyude Paul 
Cc: Wayne Lin 
Cc: Ville Syrjälä 
Cc: Fangzhi Zuo 
Cc: Jani Nikula 
Cc: Imre Deak 
Cc: Daniel Vetter 
Cc: Sean Paul 
---
 drivers/gpu/drm/display/drm_dp_mst_topology.c | 3 +--
 1 file changed, 1 insertion(+), 2 deletions(-)

diff --git a/drivers/gpu/drm/display/drm_dp_mst_topology.c 
b/drivers/gpu/drm/display/drm_dp_mst_topology.c
index 702ff5d9ecc7..ec52f91b1f0e 100644
--- a/drivers/gpu/drm/display/drm_dp_mst_topology.c
+++ b/drivers/gpu/drm/display/drm_dp_mst_topology.c
@@ -4467,8 +4467,7 @@ EXPORT_SYMBOL(drm_dp_atomic_find_time_slots);
  * drm_dp_mst_atomic_check()
  *
  * Returns:
- * 0 if all slots for this port were added back to
- * _dp_mst_topology_state.avail_slots or negative error code
+ * 0 on success, negative error code otherwise
  */
 int drm_dp_atomic_release_time_slots(struct drm_atomic_state *state,
 struct drm_dp_mst_topology_mgr *mgr,
-- 
2.35.3



Re: [git pull] drm for 5.19-rc1

2022-06-07 Thread Geert Uytterhoeven
Hi Linus,

On Tue, Jun 7, 2022 at 8:15 PM Linus Torvalds
 wrote:
> On Tue, Jun 7, 2022 at 3:23 AM Geert Uytterhoeven  
> wrote:
> > These header files are heavy users of large constants lacking the "U"
> > suffix e.g.:
> >
> > #define NB_ADAPTER_ID__SUBSYSTEM_ID_MASK 0xL
>
> As Andreas says, this is not undefined behavior.
>
> A hexadecimal integer constant will always get a type that fits the
> actual value. So on a 32-bit architecture, because 0x doesn't
> fit in 'long', it will automatically become 'unsigned long'.
>
> Now, a C compiler might still warn about such implicit type
> conversions, but I'd be a bit surprised if any version of gcc actually
> would do that, because this behavior for hex constants is *very*
> traditional, and very common.
>
> It's also true that the type of the constant - but not the value -
> will be different on 32-bit and 64-bit architectures (ie on 64-bit, it
> will be plain "long" and never extended to "unsigned long", because
> the hex value obviously fits just fine).
>
> I don't see any normal situation where that really matters, since any
> normal use will have the same result.
>
> The case you point to at
>
>   
> https://lore.kernel.org/r/cak8p3a0qrihbr_2fq7uz5w2jmljv7czfrrarcmmjohvndj3...@mail.gmail.com
>
> is very different, because the constant "1" is always just a plain
> signed "int". So when you do "(1 << 31)", that is now a signed integer
> with the top bit set, and so it will have an actual negative value,
> and that can cause various problems (when right-shifted, or when
> compared to other values).
>
> But hexadecimal constants can be signed types, but they never have
> negative values.

Thank you, I stand corrected.

Gr{oetje,eeting}s,

Geert

--
Geert Uytterhoeven -- There's lots of Linux beyond ia32 -- ge...@linux-m68k.org

In personal conversations with technical people, I call myself a hacker. But
when I'm talking to journalists I just say "programmer" or something like that.
-- Linus Torvalds


[PATCH 7/7] drm/bridge: anx7625: Add typec_mux_set callback function

2022-06-07 Thread Prashant Malani
From: Pin-Yen Lin 

Add the callback function when the driver receives state
changes of the Type-C port. The callback function configures the
crosspoint switch of the anx7625 bridge chip, which can change the
output pins of the signals according to the port state.

Signed-off-by: Pin-Yen Lin 
Signed-off-by: Prashant Malani 
---
 drivers/gpu/drm/bridge/analogix/anx7625.c | 58 +++
 drivers/gpu/drm/bridge/analogix/anx7625.h | 13 +
 2 files changed, 71 insertions(+)

diff --git a/drivers/gpu/drm/bridge/analogix/anx7625.c 
b/drivers/gpu/drm/bridge/analogix/anx7625.c
index d41a21103bd3..2c308d12fab2 100644
--- a/drivers/gpu/drm/bridge/analogix/anx7625.c
+++ b/drivers/gpu/drm/bridge/analogix/anx7625.c
@@ -15,6 +15,7 @@
 #include 
 #include 
 #include 
+#include 
 #include 
 #include 
 
@@ -2582,9 +2583,66 @@ static void anx7625_runtime_disable(void *data)
pm_runtime_disable(data);
 }
 
+static void anx7625_set_crosspoint_switch(struct anx7625_data *ctx,
+ enum typec_orientation orientation)
+{
+   if (orientation == TYPEC_ORIENTATION_NORMAL) {
+   anx7625_reg_write(ctx, ctx->i2c.tcpc_client, TCPC_SWITCH_0,
+ SW_SEL1_SSRX_RX1 | SW_SEL1_DPTX0_RX2);
+   anx7625_reg_write(ctx, ctx->i2c.tcpc_client, TCPC_SWITCH_1,
+ SW_SEL2_SSTX_TX1 | SW_SEL2_DPTX1_TX2);
+   } else if (orientation == TYPEC_ORIENTATION_REVERSE) {
+   anx7625_reg_write(ctx, ctx->i2c.tcpc_client, TCPC_SWITCH_0,
+ SW_SEL1_SSRX_RX2 | SW_SEL1_DPTX0_RX1);
+   anx7625_reg_write(ctx, ctx->i2c.tcpc_client, TCPC_SWITCH_1,
+ SW_SEL2_SSTX_TX2 | SW_SEL2_DPTX1_TX1);
+   }
+}
+
+static void anx7625_typec_two_ports_update(struct anx7625_data *ctx)
+{
+   if (ctx->typec_ports[0].dp_connected && 
ctx->typec_ports[1].dp_connected)
+   /* Both ports available, do nothing to retain the current one. 
*/
+   return;
+   else if (ctx->typec_ports[0].dp_connected)
+   anx7625_set_crosspoint_switch(ctx, TYPEC_ORIENTATION_NORMAL);
+   else if (ctx->typec_ports[1].dp_connected)
+   anx7625_set_crosspoint_switch(ctx, TYPEC_ORIENTATION_REVERSE);
+}
+
 static int anx7625_typec_mux_set(struct typec_mux_dev *mux,
 struct typec_mux_state *state)
 {
+   struct anx7625_port_data *data = typec_mux_get_drvdata(mux);
+   struct anx7625_data *ctx = data->ctx;
+   struct device *dev = >client->dev;
+
+   bool old_dp_connected = (ctx->typec_ports[0].dp_connected ||
+ctx->typec_ports[1].dp_connected);
+   bool new_dp_connected;
+
+   if (ctx->num_typec_switches == 1)
+   return 0;
+
+   dev_dbg(dev, "mux_set dp_connected: c0=%d, c1=%d\n",
+   ctx->typec_ports[0].dp_connected, 
ctx->typec_ports[1].dp_connected);
+
+   data->dp_connected = (state->alt && state->alt->svid == 
USB_TYPEC_DP_SID &&
+ state->alt->mode == USB_TYPEC_DP_MODE);
+
+   new_dp_connected = (ctx->typec_ports[0].dp_connected ||
+   ctx->typec_ports[1].dp_connected);
+
+   /* dp on, power on first */
+   if (!old_dp_connected && new_dp_connected)
+   pm_runtime_get_sync(dev);
+
+   anx7625_typec_two_ports_update(ctx);
+
+   /* dp off, power off last */
+   if (old_dp_connected && !new_dp_connected)
+   pm_runtime_put_sync(dev);
+
return 0;
 }
 
diff --git a/drivers/gpu/drm/bridge/analogix/anx7625.h 
b/drivers/gpu/drm/bridge/analogix/anx7625.h
index 76cfc64f7574..7d6c6fdf9a3a 100644
--- a/drivers/gpu/drm/bridge/analogix/anx7625.h
+++ b/drivers/gpu/drm/bridge/analogix/anx7625.h
@@ -55,6 +55,18 @@
 #define HPD_STATUS_CHANGE 0x80
 #define HPD_STATUS 0x80
 
+#define TCPC_SWITCH_0 0xB4
+#define SW_SEL1_DPTX0_RX2 BIT(0)
+#define SW_SEL1_DPTX0_RX1 BIT(1)
+#define SW_SEL1_SSRX_RX2 BIT(4)
+#define SW_SEL1_SSRX_RX1 BIT(5)
+
+#define TCPC_SWITCH_1 0xB5
+#define SW_SEL2_DPTX1_TX2 BIT(0)
+#define SW_SEL2_DPTX1_TX1 BIT(1)
+#define SW_SEL2_SSTX_TX2 BIT(4)
+#define SW_SEL2_SSTX_TX1 BIT(5)
+
 / END of I2C Address 0x58 /
 
 /***/
@@ -444,6 +456,7 @@ struct anx7625_i2c_client {
 };
 
 struct anx7625_port_data {
+   bool dp_connected;
struct typec_mux_dev *typec_mux;
struct anx7625_data *ctx;
 };
-- 
2.36.1.255.ge46751e96f-goog



[RFC 01/18] drm/amdgpu/dc/mst: Rename dp_mst_stream_allocation(_table)

2022-06-07 Thread Lyude Paul
Just to make this more clear to outside contributors that these are
DC-specific structs, as this also threw me into a loop a number of times
before I figured out the purpose of this.

Signed-off-by: Lyude Paul 
Cc: Wayne Lin 
Cc: Fangzhi Zuo 
---
 .../gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_helpers.c |  9 -
 drivers/gpu/drm/amd/display/dc/core/dc_link.c | 10 +-
 drivers/gpu/drm/amd/display/dc/dm_helpers.h   |  4 ++--
 .../gpu/drm/amd/display/include/link_service_types.h  | 11 ---
 4 files changed, 19 insertions(+), 15 deletions(-)

diff --git a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_helpers.c 
b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_helpers.c
index 7c799ddc1d27..1bd70d306c22 100644
--- a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_helpers.c
+++ b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_helpers.c
@@ -153,9 +153,8 @@ enum dc_edid_status dm_helpers_parse_edid_caps(
return result;
 }
 
-static void get_payload_table(
-   struct amdgpu_dm_connector *aconnector,
-   struct dp_mst_stream_allocation_table *proposed_table)
+static void get_payload_table(struct amdgpu_dm_connector *aconnector,
+ struct dc_dp_mst_stream_allocation_table 
*proposed_table)
 {
int i;
struct drm_dp_mst_topology_mgr *mst_mgr =
@@ -177,7 +176,7 @@ static void get_payload_table(
mst_mgr->payloads[i].payload_state ==
DP_PAYLOAD_REMOTE) {
 
-   struct dp_mst_stream_allocation *sa =
+   struct dc_dp_mst_stream_allocation *sa =
_table->stream_allocations[
proposed_table->stream_count];
 
@@ -201,7 +200,7 @@ void dm_helpers_dp_update_branch_info(
 bool dm_helpers_dp_mst_write_payload_allocation_table(
struct dc_context *ctx,
const struct dc_stream_state *stream,
-   struct dp_mst_stream_allocation_table *proposed_table,
+   struct dc_dp_mst_stream_allocation_table *proposed_table,
bool enable)
 {
struct amdgpu_dm_connector *aconnector;
diff --git a/drivers/gpu/drm/amd/display/dc/core/dc_link.c 
b/drivers/gpu/drm/amd/display/dc/core/dc_link.c
index a789ea8af27f..db0f5158a0c2 100644
--- a/drivers/gpu/drm/amd/display/dc/core/dc_link.c
+++ b/drivers/gpu/drm/amd/display/dc/core/dc_link.c
@@ -3424,7 +3424,7 @@ static void update_mst_stream_alloc_table(
struct dc_link *link,
struct stream_encoder *stream_enc,
struct hpo_dp_stream_encoder *hpo_dp_stream_enc, // TODO: Rename 
stream_enc to dio_stream_enc?
-   const struct dp_mst_stream_allocation_table *proposed_table)
+   const struct dc_dp_mst_stream_allocation_table *proposed_table)
 {
struct link_mst_stream_allocation work_table[MAX_CONTROLLER_NUM] = { 0 
};
struct link_mst_stream_allocation *dc_alloc;
@@ -3586,7 +3586,7 @@ enum dc_status dc_link_allocate_mst_payload(struct 
pipe_ctx *pipe_ctx)
 {
struct dc_stream_state *stream = pipe_ctx->stream;
struct dc_link *link = stream->link;
-   struct dp_mst_stream_allocation_table proposed_table = {0};
+   struct dc_dp_mst_stream_allocation_table proposed_table = {0};
struct fixed31_32 avg_time_slots_per_mtp;
struct fixed31_32 pbn;
struct fixed31_32 pbn_per_slot;
@@ -3691,7 +3691,7 @@ enum dc_status dc_link_reduce_mst_payload(struct pipe_ctx 
*pipe_ctx, uint32_t bw
struct fixed31_32 avg_time_slots_per_mtp;
struct fixed31_32 pbn;
struct fixed31_32 pbn_per_slot;
-   struct dp_mst_stream_allocation_table proposed_table = {0};
+   struct dc_dp_mst_stream_allocation_table proposed_table = {0};
uint8_t i;
enum act_return_status ret;
const struct link_hwss *link_hwss = get_link_hwss(link, 
_ctx->link_res);
@@ -3779,7 +3779,7 @@ enum dc_status dc_link_increase_mst_payload(struct 
pipe_ctx *pipe_ctx, uint32_t
struct fixed31_32 pbn;
struct fixed31_32 pbn_per_slot;
struct link_encoder *link_encoder = link->link_enc;
-   struct dp_mst_stream_allocation_table proposed_table = {0};
+   struct dc_dp_mst_stream_allocation_table proposed_table = {0};
uint8_t i;
enum act_return_status ret;
const struct link_hwss *link_hwss = get_link_hwss(link, 
_ctx->link_res);
@@ -3855,7 +3855,7 @@ static enum dc_status deallocate_mst_payload(struct 
pipe_ctx *pipe_ctx)
 {
struct dc_stream_state *stream = pipe_ctx->stream;
struct dc_link *link = stream->link;
-   struct dp_mst_stream_allocation_table proposed_table = {0};
+   struct dc_dp_mst_stream_allocation_table proposed_table = {0};
struct fixed31_32 avg_time_slots_per_mtp = dc_fixpt_from_int(0);
int i;
bool mst_mode = (link->type == dc_connection_mst_branch);
diff --git 

[RFC 03/18] drm/display/dp_mst: Rename drm_dp_mst_vcpi_allocation

2022-06-07 Thread Lyude Paul
In retrospect, the name I chose for this originally is confusing, as
there's a lot more info in here then just the VCPI. This really should be
called a payload. Let's make it more obvious that this is meant to be
related to the atomic state and is about payloads by renaming it to
drm_dp_mst_atomic_payload. Also, rename various variables throughout the
code that use atomic payloads.

Signed-off-by: Lyude Paul 
Cc: Wayne Lin 
Cc: Ville Syrjälä 
Cc: Fangzhi Zuo 
Cc: Jani Nikula 
Cc: Imre Deak 
Cc: Daniel Vetter 
Cc: Sean Paul 
---
 drivers/gpu/drm/display/drm_dp_mst_topology.c | 96 +--
 include/drm/display/drm_dp_mst_helper.h   |  4 +-
 2 files changed, 50 insertions(+), 50 deletions(-)

diff --git a/drivers/gpu/drm/display/drm_dp_mst_topology.c 
b/drivers/gpu/drm/display/drm_dp_mst_topology.c
index 67b3b9697da7..38eecb89e22d 100644
--- a/drivers/gpu/drm/display/drm_dp_mst_topology.c
+++ b/drivers/gpu/drm/display/drm_dp_mst_topology.c
@@ -4381,7 +4381,7 @@ int drm_dp_atomic_find_vcpi_slots(struct drm_atomic_state 
*state,
  int pbn_div)
 {
struct drm_dp_mst_topology_state *topology_state;
-   struct drm_dp_vcpi_allocation *pos, *vcpi = NULL;
+   struct drm_dp_mst_atomic_payload *pos, *payload = NULL;
int prev_slots, prev_bw, req_slots;
 
topology_state = drm_atomic_get_mst_topology_state(state, mgr);
@@ -4389,11 +4389,11 @@ int drm_dp_atomic_find_vcpi_slots(struct 
drm_atomic_state *state,
return PTR_ERR(topology_state);
 
/* Find the current allocation for this port, if any */
-   list_for_each_entry(pos, _state->vcpis, next) {
+   list_for_each_entry(pos, _state->payloads, next) {
if (pos->port == port) {
-   vcpi = pos;
-   prev_slots = vcpi->vcpi;
-   prev_bw = vcpi->pbn;
+   payload = pos;
+   prev_slots = payload->vcpi;
+   prev_bw = payload->pbn;
 
/*
 * This should never happen, unless the driver tries
@@ -4410,7 +4410,7 @@ int drm_dp_atomic_find_vcpi_slots(struct drm_atomic_state 
*state,
break;
}
}
-   if (!vcpi) {
+   if (!payload) {
prev_slots = 0;
prev_bw = 0;
}
@@ -4428,17 +4428,17 @@ int drm_dp_atomic_find_vcpi_slots(struct 
drm_atomic_state *state,
   port, prev_bw, pbn);
 
/* Add the new allocation to the state */
-   if (!vcpi) {
-   vcpi = kzalloc(sizeof(*vcpi), GFP_KERNEL);
-   if (!vcpi)
+   if (!payload) {
+   payload = kzalloc(sizeof(*payload), GFP_KERNEL);
+   if (!payload)
return -ENOMEM;
 
drm_dp_mst_get_port_malloc(port);
-   vcpi->port = port;
-   list_add(>next, _state->vcpis);
+   payload->port = port;
+   list_add(>next, _state->payloads);
}
-   vcpi->vcpi = req_slots;
-   vcpi->pbn = pbn;
+   payload->vcpi = req_slots;
+   payload->pbn = pbn;
 
return req_slots;
 }
@@ -4475,21 +4475,21 @@ int drm_dp_atomic_release_vcpi_slots(struct 
drm_atomic_state *state,
 struct drm_dp_mst_port *port)
 {
struct drm_dp_mst_topology_state *topology_state;
-   struct drm_dp_vcpi_allocation *pos;
+   struct drm_dp_mst_atomic_payload *pos;
bool found = false;
 
topology_state = drm_atomic_get_mst_topology_state(state, mgr);
if (IS_ERR(topology_state))
return PTR_ERR(topology_state);
 
-   list_for_each_entry(pos, _state->vcpis, next) {
+   list_for_each_entry(pos, _state->payloads, next) {
if (pos->port == port) {
found = true;
break;
}
}
if (WARN_ON(!found)) {
-   drm_err(mgr->dev, "no VCPI for [MST PORT:%p] found in mst state 
%p\n",
+   drm_err(mgr->dev, "No payload for [MST PORT:%p] found in mst 
state %p\n",
port, _state->base);
return -EINVAL;
}
@@ -5072,7 +5072,7 @@ drm_dp_mst_duplicate_state(struct drm_private_obj *obj)
 {
struct drm_dp_mst_topology_state *state, *old_state =
to_dp_mst_topology_state(obj->state);
-   struct drm_dp_vcpi_allocation *pos, *vcpi;
+   struct drm_dp_mst_atomic_payload *pos, *payload;
 
state = kmemdup(old_state, sizeof(*state), GFP_KERNEL);
if (!state)
@@ -5080,25 +5080,25 @@ drm_dp_mst_duplicate_state(struct drm_private_obj *obj)
 
__drm_atomic_helper_private_obj_duplicate_state(obj, >base);
 
-   INIT_LIST_HEAD(>vcpis);
+   INIT_LIST_HEAD(>payloads);
 
-   list_for_each_entry(pos, _state->vcpis, next) {
+   list_for_each_entry(pos, 

[RFC 02/18] drm/amdgpu/dm/mst: Rename get_payload_table()

2022-06-07 Thread Lyude Paul
This function isn't too confusing if you see the comment around the
call-site for it, but if you don't then it's not at all obvious this is
meant to copy DRM's payload table over to DC's internal state structs.
Seeing this function before finding that comment definitely threw me into a
loop a few times.

So, let's rename this to make it's purpose more obvious regardless of where
in the code you are.

Signed-off-by: Lyude Paul 
Cc: Wayne Lin 
Cc: Fangzhi Zuo 
---
 drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_helpers.c | 7 ---
 1 file changed, 4 insertions(+), 3 deletions(-)

diff --git a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_helpers.c 
b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_helpers.c
index 1bd70d306c22..1eaacab0334b 100644
--- a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_helpers.c
+++ b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_helpers.c
@@ -153,8 +153,9 @@ enum dc_edid_status dm_helpers_parse_edid_caps(
return result;
 }
 
-static void get_payload_table(struct amdgpu_dm_connector *aconnector,
- struct dc_dp_mst_stream_allocation_table 
*proposed_table)
+static void
+fill_dc_mst_payload_table_from_drm(struct amdgpu_dm_connector *aconnector,
+  struct dc_dp_mst_stream_allocation_table 
*proposed_table)
 {
int i;
struct drm_dp_mst_topology_mgr *mst_mgr =
@@ -252,7 +253,7 @@ bool dm_helpers_dp_mst_write_payload_allocation_table(
 * stream. AMD ASIC stream slot allocation should follow the same
 * sequence. copy DRM MST allocation to dc */
 
-   get_payload_table(aconnector, proposed_table);
+   fill_dc_mst_payload_table_from_drm(aconnector, proposed_table);
 
return true;
 }
-- 
2.35.3



[PATCH 6/7] drm/bridge: anx7625: Register Type-C mode switches

2022-06-07 Thread Prashant Malani
When the DT node has "switches" available, register a Type-C mode-switch
for each listed "switch". This allows the driver to receive state
information about what operating mode a Type-C port and its connected
peripherals are in, as well as status information (like VDOs) related to
that state.

The callback function is currently a stub, but subsequent patches will
implement the required functionality.

Signed-off-by: Prashant Malani 
---
 drivers/gpu/drm/bridge/analogix/anx7625.c | 73 +++
 drivers/gpu/drm/bridge/analogix/anx7625.h |  6 ++
 2 files changed, 79 insertions(+)

diff --git a/drivers/gpu/drm/bridge/analogix/anx7625.c 
b/drivers/gpu/drm/bridge/analogix/anx7625.c
index 07ed44c6b839..d41a21103bd3 100644
--- a/drivers/gpu/drm/bridge/analogix/anx7625.c
+++ b/drivers/gpu/drm/bridge/analogix/anx7625.c
@@ -15,6 +15,7 @@
 #include 
 #include 
 #include 
+#include 
 #include 
 
 #include 
@@ -2581,9 +2582,59 @@ static void anx7625_runtime_disable(void *data)
pm_runtime_disable(data);
 }
 
+static int anx7625_typec_mux_set(struct typec_mux_dev *mux,
+struct typec_mux_state *state)
+{
+   return 0;
+}
+
+static int anx7625_register_mode_switch(struct device *dev, struct device_node 
*node,
+   struct anx7625_data *ctx)
+{
+   struct anx7625_port_data *port_data;
+   struct typec_mux_desc mux_desc = {};
+   char name[32];
+   u32 port_num;
+   int ret;
+
+   ret = of_property_read_u32(node, "reg", _num);
+   if (ret)
+   return ret;
+
+   if (port_num >= ctx->num_typec_switches) {
+   dev_err(dev, "Invalid port number specified: %d\n", port_num);
+   return -EINVAL;
+   }
+
+   port_data = >typec_ports[port_num];
+   port_data->ctx = ctx;
+   mux_desc.fwnode = >fwnode;
+   mux_desc.drvdata = port_data;
+   snprintf(name, sizeof(name), "%s-%u", node->name, port_num);
+   mux_desc.name = name;
+   mux_desc.set = anx7625_typec_mux_set;
+
+   port_data->typec_mux = typec_mux_register(dev, _desc);
+   if (IS_ERR(port_data->typec_mux)) {
+   ret = PTR_ERR(port_data->typec_mux);
+   dev_err(dev, "Mode switch register for port %d failed: %d", 
port_num, ret);
+   }
+
+   return ret;
+}
+
+static void anx7625_unregister_typec_switches(struct anx7625_data *ctx)
+{
+   int i;
+
+   for (i = 0; i < ctx->num_typec_switches; i++)
+   typec_mux_unregister(ctx->typec_ports[i].typec_mux);
+}
+
 static int anx7625_register_typec_switches(struct device *device, struct 
anx7625_data *ctx)
 {
struct device_node *of = NULL;
+   struct device_node *sw;
int ret = 0;
 
of = of_get_child_by_name(device->of_node, "switches");
@@ -2594,6 +2645,26 @@ static int anx7625_register_typec_switches(struct device 
*device, struct anx7625
if (ctx->num_typec_switches <= 0)
return -ENODEV;
 
+   ctx->typec_ports = devm_kzalloc(device,
+   ctx->num_typec_switches * sizeof(struct 
anx7625_port_data),
+   GFP_KERNEL);
+   if (!ctx->typec_ports)
+   return -ENOMEM;
+
+   /* Register switches for each connector. */
+   for_each_available_child_of_node(of, sw) {
+   if (!of_property_read_bool(sw, "mode-switch"))
+   continue;
+   ret = anx7625_register_mode_switch(device, sw, ctx);
+   if (ret) {
+   dev_err(device, "Failed to register mode switch: %d\n", 
ret);
+   break;
+   }
+   }
+
+   if (ret)
+   anx7625_unregister_typec_switches(ctx);
+
return ret;
 }
 
@@ -2759,6 +2830,8 @@ static int anx7625_i2c_remove(struct i2c_client *client)
 
drm_bridge_remove(>bridge);
 
+   anx7625_unregister_typec_switches(platform);
+
if (platform->pdata.intp_irq)
destroy_workqueue(platform->workqueue);
 
diff --git a/drivers/gpu/drm/bridge/analogix/anx7625.h 
b/drivers/gpu/drm/bridge/analogix/anx7625.h
index d5cbca708842..76cfc64f7574 100644
--- a/drivers/gpu/drm/bridge/analogix/anx7625.h
+++ b/drivers/gpu/drm/bridge/analogix/anx7625.h
@@ -443,6 +443,11 @@ struct anx7625_i2c_client {
struct i2c_client *tcpc_client;
 };
 
+struct anx7625_port_data {
+   struct typec_mux_dev *typec_mux;
+   struct anx7625_data *ctx;
+};
+
 struct anx7625_data {
struct anx7625_platform_data pdata;
struct platform_device *audio_pdev;
@@ -474,6 +479,7 @@ struct anx7625_data {
struct mipi_dsi_device *dsi;
struct drm_dp_aux aux;
int num_typec_switches;
+   struct anx7625_port_data *typec_ports;
 };
 
 #endif  /* __ANX7625_H__ */
-- 
2.36.1.255.ge46751e96f-goog



[PATCH 3/4] backlight: ipaq_micro: Use backlight helper

2022-06-07 Thread Stephen Kitt
Instead of retrieving the backlight brightness in struct
backlight_properties manually, and then checking whether the backlight
should be on at all, use backlight_get_brightness() which does all
this and insulates this from future changes.

Signed-off-by: Stephen Kitt 
Cc: Lee Jones 
Cc: Daniel Thompson 
Cc: Jingoo Han 
Cc: Helge Deller 
Cc: dri-devel@lists.freedesktop.org
Cc: linux-fb...@vger.kernel.org
---
 drivers/video/backlight/ipaq_micro_bl.c | 7 +--
 1 file changed, 1 insertion(+), 6 deletions(-)

diff --git a/drivers/video/backlight/ipaq_micro_bl.c 
b/drivers/video/backlight/ipaq_micro_bl.c
index 85b16cc82878..f595b8c8cbb2 100644
--- a/drivers/video/backlight/ipaq_micro_bl.c
+++ b/drivers/video/backlight/ipaq_micro_bl.c
@@ -16,17 +16,12 @@
 static int micro_bl_update_status(struct backlight_device *bd)
 {
struct ipaq_micro *micro = dev_get_drvdata(>dev);
-   int intensity = bd->props.brightness;
+   int intensity = backlight_get_brightness(bd);
struct ipaq_micro_msg msg = {
.id = MSG_BACKLIGHT,
.tx_len = 3,
};
 
-   if (bd->props.power != FB_BLANK_UNBLANK)
-   intensity = 0;
-   if (bd->props.state & (BL_CORE_FBBLANK | BL_CORE_SUSPENDED))
-   intensity = 0;
-
/*
 * Message format:
 * Byte 0: backlight instance (usually 1)
-- 
2.30.2



[PATCH 2/4] backlight: arcxcnn: Use backlight helper

2022-06-07 Thread Stephen Kitt
Instead of retrieving the backlight brightness in struct
backlight_properties manually, and then checking whether the backlight
should be on at all, use backlight_get_brightness() which does all
this and insulates this from future changes.

Signed-off-by: Stephen Kitt 
Cc: Lee Jones 
Cc: Daniel Thompson 
Cc: Jingoo Han 
Cc: Helge Deller 
Cc: dri-devel@lists.freedesktop.org
Cc: linux-fb...@vger.kernel.org
---
 drivers/video/backlight/arcxcnn_bl.c | 5 +
 1 file changed, 1 insertion(+), 4 deletions(-)

diff --git a/drivers/video/backlight/arcxcnn_bl.c 
b/drivers/video/backlight/arcxcnn_bl.c
index 7b1c0a0e6cad..a706899eb7ac 100644
--- a/drivers/video/backlight/arcxcnn_bl.c
+++ b/drivers/video/backlight/arcxcnn_bl.c
@@ -130,12 +130,9 @@ static int arcxcnn_set_brightness(struct arcxcnn *lp, u32 
brightness)
 static int arcxcnn_bl_update_status(struct backlight_device *bl)
 {
struct arcxcnn *lp = bl_get_data(bl);
-   u32 brightness = bl->props.brightness;
+   u32 brightness = backlight_get_brightness(bl);
int ret;
 
-   if (bl->props.state & (BL_CORE_SUSPENDED | BL_CORE_FBBLANK))
-   brightness = 0;
-
ret = arcxcnn_set_brightness(lp, brightness);
if (ret)
return ret;
-- 
2.30.2



[PATCH 5/7] drm/bridge: anx7625: Register number of Type C switches

2022-06-07 Thread Prashant Malani
Parse the "switches" node, if available, and count and store the number
of Type-C switches within it. Since we currently don't do anything with
this info, no functional changes are expected from this change.

This patch sets a foundation for the actual registering of Type-C
switches with the Type-C connector class framework.

Signed-off-by: Prashant Malani 
---
 drivers/gpu/drm/bridge/analogix/anx7625.c | 20 
 drivers/gpu/drm/bridge/analogix/anx7625.h |  1 +
 2 files changed, 21 insertions(+)

diff --git a/drivers/gpu/drm/bridge/analogix/anx7625.c 
b/drivers/gpu/drm/bridge/analogix/anx7625.c
index 53a5da6c49dd..07ed44c6b839 100644
--- a/drivers/gpu/drm/bridge/analogix/anx7625.c
+++ b/drivers/gpu/drm/bridge/analogix/anx7625.c
@@ -2581,6 +2581,22 @@ static void anx7625_runtime_disable(void *data)
pm_runtime_disable(data);
 }
 
+static int anx7625_register_typec_switches(struct device *device, struct 
anx7625_data *ctx)
+{
+   struct device_node *of = NULL;
+   int ret = 0;
+
+   of = of_get_child_by_name(device->of_node, "switches");
+   if (!of)
+   return -ENODEV;
+
+   ctx->num_typec_switches = of_get_child_count(of);
+   if (ctx->num_typec_switches <= 0)
+   return -ENODEV;
+
+   return ret;
+}
+
 static int anx7625_i2c_probe(struct i2c_client *client,
 const struct i2c_device_id *id)
 {
@@ -2686,6 +2702,10 @@ static int anx7625_i2c_probe(struct i2c_client *client,
if (platform->pdata.intp_irq)
queue_work(platform->workqueue, >work);
 
+   ret = anx7625_register_typec_switches(dev, platform);
+   if (ret)
+   dev_info(dev, "Didn't register Type C switches, err: %d\n", 
ret);
+
platform->bridge.funcs = _bridge_funcs;
platform->bridge.of_node = client->dev.of_node;
if (!anx7625_of_panel_on_aux_bus(>dev))
diff --git a/drivers/gpu/drm/bridge/analogix/anx7625.h 
b/drivers/gpu/drm/bridge/analogix/anx7625.h
index e257a84db962..d5cbca708842 100644
--- a/drivers/gpu/drm/bridge/analogix/anx7625.h
+++ b/drivers/gpu/drm/bridge/analogix/anx7625.h
@@ -473,6 +473,7 @@ struct anx7625_data {
struct drm_connector *connector;
struct mipi_dsi_device *dsi;
struct drm_dp_aux aux;
+   int num_typec_switches;
 };
 
 #endif  /* __ANX7625_H__ */
-- 
2.36.1.255.ge46751e96f-goog



[RFC 00/18] drm/display/dp_mst: Drop Radeon MST support, make MST atomic-only

2022-06-07 Thread Lyude Paul
For quite a while we've been carrying around a lot of legacy modesetting
code in the MST helpers that has been rather annoying to keep around,
and very often gets in the way of trying to implement additional
functionality in MST such as fallback link rate retraining, dynamic BPC
management and DSC support, etc. because of the fact that we can't rely
on atomic for everything.

Luckily, we only actually have one user of the legacy MST code in the
kernel - radeon. Originally I was thinking of trying to maintain this
code and keep it around in some form, but I'm pretty unconvinced anyone
is actually using this. My reasoning for that is because I've seen
nearly no issues regarding MST on radeon for quite a while now - despite
the fact my local testing seems to indicate it's quite broken. This
isn't too surprising either, as MST support in radeon.ko is gated behind
a module parameter that isn't enabled by default. This isn't to say I
wouldn't be open to alternative suggestions, but I'd rather not be the
one to have to spend time on that if at all possible! Plus, I already
floated the idea of dropping this code by AMD folks a few times and
didn't get much resistance.

As well, this series has some basic refactoring that I did along the way
and some bugs I had to fix in order to get my atomic-only MST code
working. Most of this is pretty straight forward and simply renaming
things to more closely match the DisplayPort specification, as I think
this will also make maintaining this code a lot easier in the long run
(I've gotten myself confused way too many times because of this).

So far I've tested this on all three MST drivers: amdgpu, i915 and
nouveau, along with making sure that removing the radeon MST code
doesn't break anything else. The one thing I very much could use help
with regarding testing though is making sure that this works with
amdgpu's DSC support on MST.

So, with this we should be using the atomic state as much as possible
with MST modesetting, hooray!

Cc: Wayne Lin 
Cc: Ville Syrjälä 
Cc: Fangzhi Zuo 
Cc: Jani Nikula 
Cc: Imre Deak 
Cc: Daniel Vetter 
Cc: Sean Paul 

Lyude Paul (18):
  drm/amdgpu/dc/mst: Rename dp_mst_stream_allocation(_table)
  drm/amdgpu/dm/mst: Rename get_payload_table()
  drm/display/dp_mst: Rename drm_dp_mst_vcpi_allocation
  drm/display/dp_mst: Call them time slots, not VCPI slots
  drm/display/dp_mst: Fix confusing docs for
drm_dp_atomic_release_time_slots()
  drm/display/dp_mst: Add some missing kdocs for atomic MST structs
  drm/display/dp_mst: Add helper for finding payloads in atomic MST
state
  drm/display/dp_mst: Add nonblocking helpers for DP MST
  drm/display/dp_mst: Don't open code modeset checks for releasing time
slots
  drm/display/dp_mst: Fix modeset tracking in
drm_dp_atomic_release_vcpi_slots()
  drm/nouveau/kms: Cache DP encoders in nouveau_connector
  drm/nouveau/kms: Pull mst state in for all modesets
  drm/display/dp_mst: Add helpers for serializing SST <-> MST
transitions
  drm/display/dp_mst: Drop all ports from topology on CSNs before
queueing link address work
  drm/display/dp_mst: Skip releasing payloads if last connected port
isn't connected
  drm/display/dp_mst: Maintain time slot allocations when deleting
payloads
  drm/radeon: Drop legacy MST support
  drm/display/dp_mst: Move all payload info into the atomic state

 .../gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c |   72 +-
 .../amd/display/amdgpu_dm/amdgpu_dm_helpers.c |  111 +-
 .../display/amdgpu_dm/amdgpu_dm_mst_types.c   |  126 +-
 drivers/gpu/drm/amd/display/dc/core/dc_link.c |   10 +-
 drivers/gpu/drm/amd/display/dc/dm_helpers.h   |4 +-
 .../amd/display/include/link_service_types.h  |   18 +-
 drivers/gpu/drm/display/drm_dp_mst_topology.c | 1160 -
 drivers/gpu/drm/i915/display/intel_display.c  |   11 +
 drivers/gpu/drm/i915/display/intel_dp.c   |9 +
 drivers/gpu/drm/i915/display/intel_dp_mst.c   |   91 +-
 drivers/gpu/drm/i915/display/intel_hdcp.c |   24 +-
 drivers/gpu/drm/nouveau/dispnv50/disp.c   |  202 ++-
 drivers/gpu/drm/nouveau/dispnv50/disp.h   |2 +
 drivers/gpu/drm/nouveau/nouveau_connector.c   |   18 +-
 drivers/gpu/drm/nouveau/nouveau_connector.h   |3 +
 drivers/gpu/drm/radeon/Makefile   |2 +-
 drivers/gpu/drm/radeon/atombios_crtc.c|   11 +-
 drivers/gpu/drm/radeon/atombios_encoders.c|   59 -
 drivers/gpu/drm/radeon/radeon_atombios.c  |2 -
 drivers/gpu/drm/radeon/radeon_connectors.c|   61 +-
 drivers/gpu/drm/radeon/radeon_device.c|1 -
 drivers/gpu/drm/radeon/radeon_dp_mst.c|  778 ---
 drivers/gpu/drm/radeon/radeon_drv.c   |4 -
 drivers/gpu/drm/radeon/radeon_encoders.c  |   14 +-
 drivers/gpu/drm/radeon/radeon_irq_kms.c   |   10 +-
 drivers/gpu/drm/radeon/radeon_mode.h  |   40 -
 include/drm/display/drm_dp_mst_helper.h   |  230 ++--
 27 files changed, 991 insertions(+), 2082 deletions(-)
 delete mode 

[PATCH] drm/i915/xehp: Correct steering initialization

2022-06-07 Thread Matt Roper
Another mistake during the conversion to DSS bitmaps:  after retrieving
the DSS ID intel_sseu_find_first_xehp_dss() we forgot to modulo it down
to obtain which ID within the current gslice it is.

Fixes: b87d39019651 ("drm/i915/sseu: Disassociate internal subslice mask 
representation from uapi")
Cc: Balasubramani Vivekanandan 
Signed-off-by: Matt Roper 
---
 drivers/gpu/drm/i915/gt/intel_workarounds.c | 4 ++--
 1 file changed, 2 insertions(+), 2 deletions(-)

diff --git a/drivers/gpu/drm/i915/gt/intel_workarounds.c 
b/drivers/gpu/drm/i915/gt/intel_workarounds.c
index b7421f109c13..a5c0508c5b63 100644
--- a/drivers/gpu/drm/i915/gt/intel_workarounds.c
+++ b/drivers/gpu/drm/i915/gt/intel_workarounds.c
@@ -1177,8 +1177,8 @@ xehp_init_mcr(struct intel_gt *gt, struct i915_wa_list 
*wal)
}
 
slice = __ffs(slice_mask);
-   subslice = intel_sseu_find_first_xehp_dss(sseu, GEN_DSS_PER_GSLICE, 
slice);
-   WARN_ON(subslice > GEN_DSS_PER_GSLICE);
+   subslice = intel_sseu_find_first_xehp_dss(sseu, GEN_DSS_PER_GSLICE, 
slice) %
+   GEN_DSS_PER_GSLICE;
 
__add_mcr_wa(gt, wal, slice, subslice);
 
-- 
2.35.3



[PATCH] drm: shmobile: Use backlight helper

2022-06-07 Thread Stephen Kitt
backlight_properties.fb_blank is deprecated. The states it represents
are handled by other properties; but instead of accessing those
properties directly, drivers should use the helpers provided by
backlight.h.

Instead of retrieving the backlight brightness in struct
backlight_properties manually, and then checking whether the backlight
should be on at all, use backlight_get_brightness() which does all
this and insulates this from future changes.

Signed-off-by: Stephen Kitt 
Cc: Laurent Pinchart 
Cc: Kieran Bingham 
Cc: David Airlie 
Cc: Daniel Vetter 
Cc: dri-devel@lists.freedesktop.org
---
 drivers/gpu/drm/shmobile/shmob_drm_backlight.c | 6 +-
 1 file changed, 1 insertion(+), 5 deletions(-)

diff --git a/drivers/gpu/drm/shmobile/shmob_drm_backlight.c 
b/drivers/gpu/drm/shmobile/shmob_drm_backlight.c
index f6628a5ee95f..794573badfe8 100644
--- a/drivers/gpu/drm/shmobile/shmob_drm_backlight.c
+++ b/drivers/gpu/drm/shmobile/shmob_drm_backlight.c
@@ -18,11 +18,7 @@ static int shmob_drm_backlight_update(struct 
backlight_device *bdev)
struct shmob_drm_connector *scon = bl_get_data(bdev);
struct shmob_drm_device *sdev = scon->connector.dev->dev_private;
const struct shmob_drm_backlight_data *bdata = >pdata->backlight;
-   int brightness = bdev->props.brightness;
-
-   if (bdev->props.power != FB_BLANK_UNBLANK ||
-   bdev->props.state & BL_CORE_SUSPENDED)
-   brightness = 0;
+   int brightness = backlight_get_brightness(bdev);
 
return bdata->set_brightness(brightness);
 }

base-commit: f2906aa863381afb0015a9eb7fefad885d4e5a56
-- 
2.30.2



[PATCH 4/7] dt-bindings: drm/bridge: anx7625: Add mode-switch support

2022-06-07 Thread Prashant Malani
Analogix 7625 can be used in systems to switch USB Type-C DisplayPort
alternate mode lane traffic between 2 Type-C ports.

Update the binding to accommodate this usage by introducing a switch
property.

Signed-off-by: Prashant Malani 
---
 .../display/bridge/analogix,anx7625.yaml  | 56 +++
 1 file changed, 56 insertions(+)

diff --git 
a/Documentation/devicetree/bindings/display/bridge/analogix,anx7625.yaml 
b/Documentation/devicetree/bindings/display/bridge/analogix,anx7625.yaml
index 35a48515836e..7e1f655ddfcc 100644
--- a/Documentation/devicetree/bindings/display/bridge/analogix,anx7625.yaml
+++ b/Documentation/devicetree/bindings/display/bridge/analogix,anx7625.yaml
@@ -105,6 +105,26 @@ properties:
   - port@0
   - port@1
 
+  switches:
+type: object
+description: Set of switches controlling DisplayPort traffic on
+  outgoing RX/TX lanes to Type C ports.
+
+properties:
+  switch:
+$ref: /schemas/usb/typec-switch.yaml#
+maxItems: 2
+
+properties:
+  reg:
+maxItems: 1
+
+required:
+  - reg
+
+required:
+  - switch@0
+
 required:
   - compatible
   - reg
@@ -167,5 +187,41 @@ examples:
 };
 };
 };
+switches {
+#address-cells = <1>;
+#size-cells = <0>;
+switch@0 {
+compatible = "typec-switch";
+reg = <0>;
+mode-switch;
+
+ports {
+#address-cells = <1>;
+#size-cells = <0>;
+port@0 {
+reg = <0>;
+anx_typec0: endpoint {
+  remote-endpoint = <_port0>;
+};
+};
+};
+};
+switch@1 {
+compatible = "typec-switch";
+reg = <1>;
+mode-switch;
+
+ports {
+#address-cells = <1>;
+#size-cells = <0>;
+port@0 {
+reg = <0>;
+anx_typec1: endpoint {
+  remote-endpoint = <_port1>;
+};
+};
+};
+};
+};
 };
 };
-- 
2.36.1.255.ge46751e96f-goog



[PATCH 3/7] dt-bindings: usb: Add Type-C switch binding

2022-06-07 Thread Prashant Malani
Introduce a binding which represents a component that can control the
routing of USB Type-C data lines as well as address data line
orientation (based on CC lines' orientation).

Signed-off-by: Prashant Malani 
---
 .../devicetree/bindings/usb/typec-switch.yaml | 76 +++
 1 file changed, 76 insertions(+)
 create mode 100644 Documentation/devicetree/bindings/usb/typec-switch.yaml

diff --git a/Documentation/devicetree/bindings/usb/typec-switch.yaml 
b/Documentation/devicetree/bindings/usb/typec-switch.yaml
new file mode 100644
index ..60a600a63fef
--- /dev/null
+++ b/Documentation/devicetree/bindings/usb/typec-switch.yaml
@@ -0,0 +1,76 @@
+# SPDX-License-Identifier: (GPL-2.0-only OR BSD-2-Clause)
+%YAML 1.2
+---
+$id: http://devicetree.org/schemas/usb/typec-switch.yaml#
+$schema: http://devicetree.org/meta-schemas/core.yaml#
+
+title: USB Type-C Switch
+
+maintainers:
+  - Prashant Malani 
+
+description:
+  A USB Type-C switch represents a component which routes USB Type-C data
+  lines to various protocol host controllers (e.g USB, VESA DisplayPort,
+  Thunderbolt etc.) depending on which mode the Type-C port, port partner
+  and cable are operating in. It can also modify lane routing based on
+  the orientation of a connected Type-C peripheral.
+
+properties:
+  compatible:
+items:
+  - enum:
+  - typec-switch
+
+  mode-switch:
+type: boolean
+description: Specify that this switch can handle alternate mode switching.
+
+  orientation-switch:
+type: boolean
+description: Specify that this switch can handle orientation switching.
+
+  ports:
+$ref: /schemas/graph.yaml#/properties/ports
+description: OF graph binding modelling data lines to the Type-C switch.
+
+properties:
+  port@0:
+$ref: /schemas/graph.yaml#/properties/port
+description: Link between the switch and a Type-C connector.
+
+required:
+  - port@0
+
+required:
+  - compatible
+  - ports
+
+anyOf:
+  - required:
+  - mode-switch
+  - required:
+  - orientation-switch
+
+additionalProperties: true
+
+examples:
+  - |
+anx7625 {
+  typecswitch {
+compatible = "typec-switch";
+mode-switch;
+orientation-switch;
+ports {
+  #address-cells = <1>;
+  #size-cells = <0>;
+
+  port@0 {
+reg = <0>;
+anx_ep: endpoint {
+  remote-endpoint = <_controller>;
+};
+  };
+};
+  };
+};
-- 
2.36.1.255.ge46751e96f-goog



[PATCH 2/7] usb: typec: mux: Add CONFIG guards for functions

2022-06-07 Thread Prashant Malani
There are some drivers that can use the Type C mux API, but don't have
to. Introduce CONFIG guards for the mux functions so that drivers can
include the header file and not run into compilation errors on systems
which don't have CONFIG_TYPEC enabled. When CONFIG_TYPEC is not enabled,
the Type C mux functions will be stub versions of the original calls.

Signed-off-by: Prashant Malani 
---
 include/linux/usb/typec_mux.h | 38 +++
 1 file changed, 38 insertions(+)

diff --git a/include/linux/usb/typec_mux.h b/include/linux/usb/typec_mux.h
index ee57781dcf28..758d34ced1f8 100644
--- a/include/linux/usb/typec_mux.h
+++ b/include/linux/usb/typec_mux.h
@@ -58,6 +58,8 @@ struct typec_mux_desc {
void *drvdata;
 };
 
+#if IS_ENABLED(CONFIG_TYPEC) || IS_MODULE(CONFIG_TYPEC)
+
 struct typec_mux *fwnode_typec_mux_get(struct fwnode_handle *fwnode,
   const struct typec_altmode_desc *desc);
 void typec_mux_put(struct typec_mux *mux);
@@ -76,4 +78,40 @@ void typec_mux_unregister(struct typec_mux_dev *mux);
 void typec_mux_set_drvdata(struct typec_mux_dev *mux, void *data);
 void *typec_mux_get_drvdata(struct typec_mux_dev *mux);
 
+#else
+
+struct typec_mux *fwnode_typec_mux_get(struct fwnode_handle *fwnode,
+  const struct typec_altmode_desc *desc)
+{
+   return ERR_PTR(-EOPNOTSUPP);
+}
+
+void typec_mux_put(struct typec_mux *mux) {}
+
+int typec_mux_set(struct typec_mux *mux, struct typec_mux_state *state)
+{
+   return -EOPNOTSUPP;
+}
+
+static inline struct typec_mux *
+typec_mux_get(struct device *dev, const struct typec_altmode_desc *desc)
+{
+   return ERR_PTR(-EOPNOTSUPP);
+}
+
+struct typec_mux *
+typec_mux_register(struct device *parent, const struct typec_mux_desc *desc)
+{
+   return ERR_PTR(-EOPNOTSUPP);
+}
+void typec_mux_unregister(struct typec_mux *mux) {}
+
+void typec_mux_set_drvdata(struct typec_mux *mux, void *data) {}
+void *typec_mux_get_drvdata(struct typec_mux *mux)
+{
+   return ERR_PTR(-EOPNOTSUPP);
+}
+
+#endif /* CONFIG_TYPEC */
+
 #endif /* __USB_TYPEC_MUX */
-- 
2.36.1.255.ge46751e96f-goog



[PATCH 1/7] usb: typec: mux: Allow muxes to specify mode-switch

2022-06-07 Thread Prashant Malani
Loosen the typec_mux_match() requirements so that searches where an
alt mode is not specified, but the target mux device lists the
"mode-switch" property, return a success.

This is helpful in Type C port drivers which would like to get a pointer
to the mux switch associated with a Type C port, but don't want to
specify a particular alt mode.

Signed-off-by: Prashant Malani 
---
 drivers/usb/typec/mux.c | 8 ++--
 1 file changed, 6 insertions(+), 2 deletions(-)

diff --git a/drivers/usb/typec/mux.c b/drivers/usb/typec/mux.c
index fd55c2c516a5..464330776cd6 100644
--- a/drivers/usb/typec/mux.c
+++ b/drivers/usb/typec/mux.c
@@ -281,9 +281,13 @@ static void *typec_mux_match(struct fwnode_handle *fwnode, 
const char *id,
if (match)
goto find_mux;
 
-   /* Accessory Mode muxes */
if (!desc) {
-   match = fwnode_property_present(fwnode, "accessory");
+   /*
+* Accessory Mode muxes & muxes which explicitly specify
+* the required identifier can avoid SVID matching.
+*/
+   match = fwnode_property_present(fwnode, "accessory") ||
+   fwnode_property_present(fwnode, id);
if (match)
goto find_mux;
return NULL;
-- 
2.36.1.255.ge46751e96f-goog



[PATCH] staging: ftbft: Use backlight helper

2022-06-07 Thread Stephen Kitt
backlight_properties.fb_blank is deprecated. The states it represents
are handled by other properties; but instead of accessing those
properties directly, drivers should use the helpers provided by
backlight.h.

Instead of manually checking the power state in struct
backlight_properties, use backlight_is_blank().

Signed-off-by: Stephen Kitt 
Cc: Greg Kroah-Hartman 
Cc: "Noralf Trønnes" 
Cc: Thomas Zimmermann 
Cc: Andy Shevchenko 
Cc: Javier Martinez Canillas 
Cc: Len Baker 
Cc: dri-devel@lists.freedesktop.org
Cc: linux-fb...@vger.kernel.org
Cc: linux-stag...@lists.linux.dev
---
 drivers/staging/fbtft/fb_ssd1351.c | 3 +--
 drivers/staging/fbtft/fbtft-core.c | 3 +--
 2 files changed, 2 insertions(+), 4 deletions(-)

diff --git a/drivers/staging/fbtft/fb_ssd1351.c 
b/drivers/staging/fbtft/fb_ssd1351.c
index 6fd549a424d5..b8d55aa8c5c7 100644
--- a/drivers/staging/fbtft/fb_ssd1351.c
+++ b/drivers/staging/fbtft/fb_ssd1351.c
@@ -196,8 +196,7 @@ static int update_onboard_backlight(struct backlight_device 
*bd)
  "%s: power=%d, fb_blank=%d\n",
  __func__, bd->props.power, bd->props.fb_blank);
 
-   on = (bd->props.power == FB_BLANK_UNBLANK) &&
-(bd->props.fb_blank == FB_BLANK_UNBLANK);
+   on = !backlight_is_blank(bd);
/* Onboard backlight connected to GPIO0 on SSD1351, GPIO1 unused */
write_reg(par, 0xB5, on ? 0x03 : 0x02);
 
diff --git a/drivers/staging/fbtft/fbtft-core.c 
b/drivers/staging/fbtft/fbtft-core.c
index 60b2278d8b16..9b3eaed80cdd 100644
--- a/drivers/staging/fbtft/fbtft-core.c
+++ b/drivers/staging/fbtft/fbtft-core.c
@@ -137,8 +137,7 @@ static int fbtft_backlight_update_status(struct 
backlight_device *bd)
  "%s: polarity=%d, power=%d, fb_blank=%d\n",
  __func__, polarity, bd->props.power, bd->props.fb_blank);
 
-   if ((bd->props.power == FB_BLANK_UNBLANK) &&
-   (bd->props.fb_blank == FB_BLANK_UNBLANK))
+   if (!backlight_is_blank(bd))
gpiod_set_value(par->gpio.led[0], polarity);
else
gpiod_set_value(par->gpio.led[0], !polarity);

base-commit: f2906aa863381afb0015a9eb7fefad885d4e5a56
-- 
2.30.2



[PATCH 0/7] usb: typec: Introduce typec-switch binding

2022-06-07 Thread Prashant Malani
This series introduces a binding for Type-C data lane switches. These
control the routing and operating modes of USB Type-C data lanes based
on the PD messaging from the Type-C port driver regarding connected peripherals.

The first patch introduces a change to the Type-C mux class mode-switch
matching code, while the second adds a config guard to a Type-C header.
The next couple of patches introduce the new "typec-switch" binding as
well as one user of it (the ANX7625 drm bridge).

The remaining patches add functionality to the anx7625 driver to
register the mode-switches, as well as program its crosspoint
switch depending on which Type-C port has a DisplayPort (DP) peripheral
connected to it.

Pin-Yen Lin (1):
  drm/bridge: anx7625: Add typec_mux_set callback function

Prashant Malani (6):
  usb: typec: mux: Allow muxes to specify mode-switch
  usb: typec: mux: Add CONFIG guards for functions
  dt-bindings: usb: Add Type-C switch binding
  dt-bindings: drm/bridge: anx7625: Add mode-switch support
  drm/bridge: anx7625: Register number of Type C switches
  drm/bridge: anx7625: Register Type-C mode switches

 .../display/bridge/analogix,anx7625.yaml  |  56 +++
 .../devicetree/bindings/usb/typec-switch.yaml |  76 +
 drivers/gpu/drm/bridge/analogix/anx7625.c | 151 ++
 drivers/gpu/drm/bridge/analogix/anx7625.h |  20 +++
 drivers/usb/typec/mux.c   |   8 +-
 include/linux/usb/typec_mux.h |  38 +
 6 files changed, 347 insertions(+), 2 deletions(-)
 create mode 100644 Documentation/devicetree/bindings/usb/typec-switch.yaml

-- 
2.36.1.255.ge46751e96f-goog



[PATCH v1 7/7] drm/msm/hdmi: merge platform config for 8974/8084/8994/8996

2022-06-07 Thread Dmitry Baryshkov
Since there is no more difference between the HDMI platform data
between MSM8974/APQ8084/MSM8994/MSM8996, merge these configs into a
single entry.

Signed-off-by: Dmitry Baryshkov 
---
 drivers/gpu/drm/msm/hdmi/hdmi.c | 27 +++
 1 file changed, 3 insertions(+), 24 deletions(-)

diff --git a/drivers/gpu/drm/msm/hdmi/hdmi.c b/drivers/gpu/drm/msm/hdmi/hdmi.c
index 03d8f97b0cd8..8ae60e97cc94 100644
--- a/drivers/gpu/drm/msm/hdmi/hdmi.c
+++ b/drivers/gpu/drm/msm/hdmi/hdmi.c
@@ -375,27 +375,6 @@ static struct hdmi_platform_config hdmi_tx_8974_config = {
.hpd_freq  = hpd_clk_freq_8x74,
 };
 
-static struct hdmi_platform_config hdmi_tx_8084_config = {
-   HDMI_CFG(pwr_reg, 8x74),
-   HDMI_CFG(pwr_clk, 8x74),
-   HDMI_CFG(hpd_clk, 8x74),
-   .hpd_freq  = hpd_clk_freq_8x74,
-};
-
-static struct hdmi_platform_config hdmi_tx_8994_config = {
-   HDMI_CFG(pwr_reg, 8x74),
-   HDMI_CFG(pwr_clk, 8x74),
-   HDMI_CFG(hpd_clk, 8x74),
-   .hpd_freq  = hpd_clk_freq_8x74,
-};
-
-static struct hdmi_platform_config hdmi_tx_8996_config = {
-   HDMI_CFG(pwr_reg, 8x74),
-   HDMI_CFG(pwr_clk, 8x74),
-   HDMI_CFG(hpd_clk, 8x74),
-   .hpd_freq  = hpd_clk_freq_8x74,
-};
-
 /*
  * HDMI audio codec callbacks
  */
@@ -577,9 +556,9 @@ static int msm_hdmi_dev_remove(struct platform_device *pdev)
 }
 
 static const struct of_device_id msm_hdmi_dt_match[] = {
-   { .compatible = "qcom,hdmi-tx-8996", .data = _tx_8996_config },
-   { .compatible = "qcom,hdmi-tx-8994", .data = _tx_8994_config },
-   { .compatible = "qcom,hdmi-tx-8084", .data = _tx_8084_config },
+   { .compatible = "qcom,hdmi-tx-8996", .data = _tx_8974_config },
+   { .compatible = "qcom,hdmi-tx-8994", .data = _tx_8974_config },
+   { .compatible = "qcom,hdmi-tx-8084", .data = _tx_8974_config },
{ .compatible = "qcom,hdmi-tx-8974", .data = _tx_8974_config },
{ .compatible = "qcom,hdmi-tx-8960", .data = _tx_8960_config },
{ .compatible = "qcom,hdmi-tx-8660", .data = _tx_8660_config },
-- 
2.35.1



[PATCH v1 6/7] drm/msm/hdmi: drop hpd_regs usage on 8x74/8084

2022-06-07 Thread Dmitry Baryshkov
The MSM HDMI driver has support for hpd_regs on 8x74/8084: supply
regulators that are to be enabled for HPD to work. Currently these
regulators contain the hpd_gdsc, which was replaced by the power-domains
support and hpd-5v/hpd-5v-en, which are not used by the chip itself.
They power up the ESD bridge.
However it is a separate device which should be represented separately
in the device tree.
None of upstreamed devices support these properties. Thus drop support
for them from the HDMI driver.

Signed-off-by: Dmitry Baryshkov 
---
 drivers/gpu/drm/msm/hdmi/hdmi.c | 5 -
 1 file changed, 5 deletions(-)

diff --git a/drivers/gpu/drm/msm/hdmi/hdmi.c b/drivers/gpu/drm/msm/hdmi/hdmi.c
index c87a0386647f..03d8f97b0cd8 100644
--- a/drivers/gpu/drm/msm/hdmi/hdmi.c
+++ b/drivers/gpu/drm/msm/hdmi/hdmi.c
@@ -364,24 +364,19 @@ static struct hdmi_platform_config hdmi_tx_8960_config = {
 };
 
 static const char *pwr_reg_names_8x74[] = {"core-vdda", "core-vcc"};
-static const char *hpd_reg_names_8x74[] = {"hpd-gdsc", "hpd-5v"};
 static const char *pwr_clk_names_8x74[] = {"extp", "alt_iface"};
 static const char *hpd_clk_names_8x74[] = {"iface", "core", "mdp_core"};
 static unsigned long hpd_clk_freq_8x74[] = {0, 1920, 0};
 
 static struct hdmi_platform_config hdmi_tx_8974_config = {
HDMI_CFG(pwr_reg, 8x74),
-   HDMI_CFG(hpd_reg, 8x74),
HDMI_CFG(pwr_clk, 8x74),
HDMI_CFG(hpd_clk, 8x74),
.hpd_freq  = hpd_clk_freq_8x74,
 };
 
-static const char *hpd_reg_names_8084[] = {"hpd-gdsc", "hpd-5v", "hpd-5v-en"};
-
 static struct hdmi_platform_config hdmi_tx_8084_config = {
HDMI_CFG(pwr_reg, 8x74),
-   HDMI_CFG(hpd_reg, 8084),
HDMI_CFG(pwr_clk, 8x74),
HDMI_CFG(hpd_clk, 8x74),
.hpd_freq  = hpd_clk_freq_8x74,
-- 
2.35.1



[PATCH 5.18 276/879] drm: bridge: icn6211: Fix HFP_HSW_HBP_HI and HFP_MIN handling

2022-06-07 Thread Greg Kroah-Hartman
From: Marek Vasut 

[ Upstream commit c0ff7a649d62105a9308cc3ac36e52a4669d9cb4 ]

The HFP_HSW_HBP_HI register must be programmed with 2 LSbits of each
Horizontal Front Porch/Sync/Back Porch. Currently the driver programs
this register to 0, which breaks displays with either value above 255.

The HFP_MIN register must be set to the same value as HFP_LI, otherwise
there is visible image distortion, usually in the form of missing lines
at the bottom of the panel.

Fix this by correctly programming the HFP_HSW_HBP_HI and HFP_MIN registers.

Acked-by: Maxime Ripard 
Fixes: ce517f18944e3 ("drm: bridge: Add Chipone ICN6211 MIPI-DSI to RGB bridge")
Signed-off-by: Marek Vasut 
Cc: Jagan Teki 
Cc: Maxime Ripard 
Cc: Robert Foss 
Cc: Sam Ravnborg 
Cc: Thomas Zimmermann 
To: dri-devel@lists.freedesktop.org
Signed-off-by: Robert Foss 
Link: 
https://patchwork.freedesktop.org/patch/msgid/20220331150509.9838-3-ma...@denx.de
Signed-off-by: Sasha Levin 
---
 drivers/gpu/drm/bridge/chipone-icn6211.c | 23 ---
 1 file changed, 16 insertions(+), 7 deletions(-)

diff --git a/drivers/gpu/drm/bridge/chipone-icn6211.c 
b/drivers/gpu/drm/bridge/chipone-icn6211.c
index 376e0f80da5c..c871a90c0b8f 100644
--- a/drivers/gpu/drm/bridge/chipone-icn6211.c
+++ b/drivers/gpu/drm/bridge/chipone-icn6211.c
@@ -35,6 +35,9 @@
 #define HSYNC_LI   0x24
 #define HBP_LI 0x25
 #define HFP_HSW_HBP_HI 0x26
+#define HFP_HSW_HBP_HI_HFP(n)  (((n) & 0x300) >> 4)
+#define HFP_HSW_HBP_HI_HS(n)   (((n) & 0x300) >> 6)
+#define HFP_HSW_HBP_HI_HBP(n)  (((n) & 0x300) >> 8)
 #define VFP0x27
 #define VSYNC  0x28
 #define VBP0x29
@@ -163,6 +166,7 @@ static void chipone_atomic_enable(struct drm_bridge *bridge,
 {
struct chipone *icn = bridge_to_chipone(bridge);
struct drm_display_mode *mode = >mode;
+   u16 hfp, hbp, hsync;
 
ICN6211_DSI(icn, MIPI_CFG_PW, MIPI_CFG_PW_CONFIG_DSI);
 
@@ -178,13 +182,18 @@ static void chipone_atomic_enable(struct drm_bridge 
*bridge,
((mode->hdisplay >> 8) & 0xf) |
(((mode->vdisplay >> 8) & 0xf) << 4));
 
-   ICN6211_DSI(icn, HFP_LI, mode->hsync_start - mode->hdisplay);
+   hfp = mode->hsync_start - mode->hdisplay;
+   hsync = mode->hsync_end - mode->hsync_start;
+   hbp = mode->htotal - mode->hsync_end;
 
-   ICN6211_DSI(icn, HSYNC_LI, mode->hsync_end - mode->hsync_start);
-
-   ICN6211_DSI(icn, HBP_LI, mode->htotal - mode->hsync_end);
-
-   ICN6211_DSI(icn, HFP_HSW_HBP_HI, 0x00);
+   ICN6211_DSI(icn, HFP_LI, hfp & 0xff);
+   ICN6211_DSI(icn, HSYNC_LI, hsync & 0xff);
+   ICN6211_DSI(icn, HBP_LI, hbp & 0xff);
+   /* Top two bits of Horizontal Front porch/Sync/Back porch */
+   ICN6211_DSI(icn, HFP_HSW_HBP_HI,
+   HFP_HSW_HBP_HI_HFP(hfp) |
+   HFP_HSW_HBP_HI_HS(hsync) |
+   HFP_HSW_HBP_HI_HBP(hbp));
 
ICN6211_DSI(icn, VFP, mode->vsync_start - mode->vdisplay);
 
@@ -194,7 +203,7 @@ static void chipone_atomic_enable(struct drm_bridge *bridge,
 
/* dsi specific sequence */
ICN6211_DSI(icn, SYNC_EVENT_DLY, 0x80);
-   ICN6211_DSI(icn, HFP_MIN, 0x28);
+   ICN6211_DSI(icn, HFP_MIN, hfp & 0xff);
ICN6211_DSI(icn, MIPI_PD_CK_LANE, 0xa0);
ICN6211_DSI(icn, PLL_CTRL(12), 0xff);
ICN6211_DSI(icn, BIST_POL, BIST_POL_DE_POL);
-- 
2.35.1





[PATCH v1 5/7] drm/msm/hdmi: drop empty 'none' regulator lists

2022-06-07 Thread Dmitry Baryshkov
Several platform configs use empty 'none' regulator arrays. They are not
necessary, as the code will use corresponding _cnt field and skip the
array completely. Drop them now.

Signed-off-by: Dmitry Baryshkov 
---
 drivers/gpu/drm/msm/hdmi/hdmi.c | 5 -
 1 file changed, 5 deletions(-)

diff --git a/drivers/gpu/drm/msm/hdmi/hdmi.c b/drivers/gpu/drm/msm/hdmi/hdmi.c
index 125712c3fca2..c87a0386647f 100644
--- a/drivers/gpu/drm/msm/hdmi/hdmi.c
+++ b/drivers/gpu/drm/msm/hdmi/hdmi.c
@@ -353,9 +353,6 @@ int msm_hdmi_modeset_init(struct hdmi *hdmi,
.item ## _names = item ##_names_ ## entry, \
.item ## _cnt   = ARRAY_SIZE(item ## _names_ ## entry)
 
-static const char *pwr_reg_names_none[] = {};
-static const char *hpd_reg_names_none[] = {};
-
 static struct hdmi_platform_config hdmi_tx_8660_config;
 
 static const char *hpd_reg_names_8960[] = {"core-vdda", "hdmi-mux"};
@@ -392,7 +389,6 @@ static struct hdmi_platform_config hdmi_tx_8084_config = {
 
 static struct hdmi_platform_config hdmi_tx_8994_config = {
HDMI_CFG(pwr_reg, 8x74),
-   HDMI_CFG(hpd_reg, none),
HDMI_CFG(pwr_clk, 8x74),
HDMI_CFG(hpd_clk, 8x74),
.hpd_freq  = hpd_clk_freq_8x74,
@@ -400,7 +396,6 @@ static struct hdmi_platform_config hdmi_tx_8994_config = {
 
 static struct hdmi_platform_config hdmi_tx_8996_config = {
HDMI_CFG(pwr_reg, 8x74),
-   HDMI_CFG(hpd_reg, none),
HDMI_CFG(pwr_clk, 8x74),
HDMI_CFG(hpd_clk, 8x74),
.hpd_freq  = hpd_clk_freq_8x74,
-- 
2.35.1



[PATCH 3/3] drm/panel: sony-acx565akm: Use backlight helpers

2022-06-07 Thread Stephen Kitt
Instead of retrieving the backlight brightness in struct
backlight_properties manually, and then checking whether the backlight
should be on at all, use backlight_get_brightness() which does all
this and insulates this from future changes.

Instead of manually checking the power state in struct
backlight_properties, use backlight_is_blank().

Signed-off-by: Stephen Kitt 
Cc: Thierry Reding 
Cc: Sam Ravnborg 
Cc: David Airlie 
Cc: Daniel Vetter 
Cc: dri-devel@lists.freedesktop.org
---
 drivers/gpu/drm/panel/panel-sony-acx565akm.c | 11 ++-
 1 file changed, 2 insertions(+), 9 deletions(-)

diff --git a/drivers/gpu/drm/panel/panel-sony-acx565akm.c 
b/drivers/gpu/drm/panel/panel-sony-acx565akm.c
index 0d7541a33f87..a6bc8c8cf6c8 100644
--- a/drivers/gpu/drm/panel/panel-sony-acx565akm.c
+++ b/drivers/gpu/drm/panel/panel-sony-acx565akm.c
@@ -298,13 +298,7 @@ static void acx565akm_set_brightness(struct 
acx565akm_panel *lcd, int level)
 static int acx565akm_bl_update_status_locked(struct backlight_device *dev)
 {
struct acx565akm_panel *lcd = dev_get_drvdata(>dev);
-   int level;
-
-   if (dev->props.fb_blank == FB_BLANK_UNBLANK &&
-   dev->props.power == FB_BLANK_UNBLANK)
-   level = dev->props.brightness;
-   else
-   level = 0;
+   int level = backlight_get_brightness(dev);
 
acx565akm_set_brightness(lcd, level);
 
@@ -330,8 +324,7 @@ static int acx565akm_bl_get_intensity(struct 
backlight_device *dev)
 
mutex_lock(>mutex);
 
-   if (dev->props.fb_blank == FB_BLANK_UNBLANK &&
-   dev->props.power == FB_BLANK_UNBLANK)
+   if (!backlight_is_blank(dev))
intensity = acx565akm_get_actual_brightness(lcd);
else
intensity = 0;
-- 
2.30.2



[PATCH v1 4/7] drm/msm/hdmi: enable core-vcc/core-vdda-supply for 8996 platform

2022-06-07 Thread Dmitry Baryshkov
DB820c makes use of core-vcc-supply and core-vdda-supply, however the
driver code doesn't support these regulators. Enable them for HDMI on
8996 platform.

Fixes: 0afbe59edd3f ("drm/msm/hdmi: Add basic HDMI support for msm8996")
Signed-off-by: Dmitry Baryshkov 
---
 drivers/gpu/drm/msm/hdmi/hdmi.c | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/drivers/gpu/drm/msm/hdmi/hdmi.c b/drivers/gpu/drm/msm/hdmi/hdmi.c
index 6a22d6977ead..125712c3fca2 100644
--- a/drivers/gpu/drm/msm/hdmi/hdmi.c
+++ b/drivers/gpu/drm/msm/hdmi/hdmi.c
@@ -399,7 +399,7 @@ static struct hdmi_platform_config hdmi_tx_8994_config = {
 };
 
 static struct hdmi_platform_config hdmi_tx_8996_config = {
-   HDMI_CFG(pwr_reg, none),
+   HDMI_CFG(pwr_reg, 8x74),
HDMI_CFG(hpd_reg, none),
HDMI_CFG(pwr_clk, 8x74),
HDMI_CFG(hpd_clk, 8x74),
-- 
2.35.1



[PATCH 0/3] drm/panel: Use backlight helpers

2022-06-07 Thread Stephen Kitt
backlight_properties.fb_blank is deprecated. The states it represents
are handled by other properties; but instead of accessing those
properties directly, drivers should use the helpers provided by
backlight.h.

This will ultimately allow fb_blank to be removed.

Stephen Kitt (3):
  drm/panel: Use backlight helper
  drm/panel: panel-dsi-cm: Use backlight helpers
  drm/panel: sony-acx565akm: Use backlight helpers

 .../drm/panel/panel-asus-z00t-tm5p5-n35596.c  |  7 +-
 drivers/gpu/drm/panel/panel-dsi-cm.c  | 24 ---
 drivers/gpu/drm/panel/panel-sony-acx565akm.c  | 11 ++---
 3 files changed, 7 insertions(+), 35 deletions(-)


base-commit: f2906aa863381afb0015a9eb7fefad885d4e5a56
-- 
2.30.2



[PATCH v1 3/7] drm/msm/hdmi: drop unused GPIO support

2022-06-07 Thread Dmitry Baryshkov
The HDMI driver has code to configure extra GPIOs, which predates
pinctrl support. Nowadays all platforms should use pinctrl instead.
Neither of upstreamed Qualcomm pltforms uses these properties, so it's
safe to drop them.

Signed-off-by: Dmitry Baryshkov 
---
 drivers/gpu/drm/msm/hdmi/hdmi.c | 61 +---
 drivers/gpu/drm/msm/hdmi/hdmi.h | 13 +-
 drivers/gpu/drm/msm/hdmi/hdmi_hpd.c | 62 ++---
 3 files changed, 17 insertions(+), 119 deletions(-)

diff --git a/drivers/gpu/drm/msm/hdmi/hdmi.c b/drivers/gpu/drm/msm/hdmi/hdmi.c
index cf24e68864ba..6a22d6977ead 100644
--- a/drivers/gpu/drm/msm/hdmi/hdmi.c
+++ b/drivers/gpu/drm/msm/hdmi/hdmi.c
@@ -406,20 +406,6 @@ static struct hdmi_platform_config hdmi_tx_8996_config = {
.hpd_freq  = hpd_clk_freq_8x74,
 };
 
-static const struct {
-   const char *name;
-   const bool output;
-   const int value;
-   const char *label;
-} msm_hdmi_gpio_pdata[] = {
-   { "qcom,hdmi-tx-ddc-clk", true, 1, "HDMI_DDC_CLK" },
-   { "qcom,hdmi-tx-ddc-data", true, 1, "HDMI_DDC_DATA" },
-   { "qcom,hdmi-tx-hpd", false, 1, "HDMI_HPD" },
-   { "qcom,hdmi-tx-mux-en", true, 1, "HDMI_MUX_EN" },
-   { "qcom,hdmi-tx-mux-sel", true, 0, "HDMI_MUX_SEL" },
-   { "qcom,hdmi-tx-mux-lpm", true, 1, "HDMI_MUX_LPM" },
-};
-
 /*
  * HDMI audio codec callbacks
  */
@@ -531,7 +517,7 @@ static int msm_hdmi_bind(struct device *dev, struct device 
*master, void *data)
struct hdmi_platform_config *hdmi_cfg;
struct hdmi *hdmi;
struct device_node *of_node = dev->of_node;
-   int i, err;
+   int err;
 
hdmi_cfg = (struct hdmi_platform_config *)
of_device_get_match_data(dev);
@@ -543,41 +529,16 @@ static int msm_hdmi_bind(struct device *dev, struct 
device *master, void *data)
hdmi_cfg->mmio_name = "core_physical";
hdmi_cfg->qfprom_mmio_name = "qfprom_physical";
 
-   for (i = 0; i < HDMI_MAX_NUM_GPIO; i++) {
-   const char *name = msm_hdmi_gpio_pdata[i].name;
-   struct gpio_desc *gpiod;
-
-   /*
-* We are fetching the GPIO lines "as is" since the connector
-* code is enabling and disabling the lines. Until that point
-* the power-on default value will be kept.
-*/
-   gpiod = devm_gpiod_get_optional(dev, name, GPIOD_ASIS);
-   /* This will catch e.g. -PROBE_DEFER */
-   if (IS_ERR(gpiod))
-   return PTR_ERR(gpiod);
-   if (!gpiod) {
-   /* Try a second time, stripping down the name */
-   char name3[32];
-
-   /*
-* Try again after stripping out the "qcom,hdmi-tx"
-* prefix. This is mainly to match "hpd-gpios" used
-* in the upstream bindings.
-*/
-   if (sscanf(name, "qcom,hdmi-tx-%s", name3))
-   gpiod = devm_gpiod_get_optional(dev, name3, 
GPIOD_ASIS);
-   if (IS_ERR(gpiod))
-   return PTR_ERR(gpiod);
-   if (!gpiod)
-   DBG("failed to get gpio: %s", name);
-   }
-   hdmi_cfg->gpios[i].gpiod = gpiod;
-   if (gpiod)
-   gpiod_set_consumer_name(gpiod, 
msm_hdmi_gpio_pdata[i].label);
-   hdmi_cfg->gpios[i].output = msm_hdmi_gpio_pdata[i].output;
-   hdmi_cfg->gpios[i].value = msm_hdmi_gpio_pdata[i].value;
-   }
+   hdmi->hpd_gpiod = devm_gpiod_get_optional(dev, "hpd", GPIOD_IN);
+   /* This will catch e.g. -PROBE_DEFER */
+   if (IS_ERR(hdmi->hpd_gpiod))
+   return PTR_ERR(hdmi->hpd_gpiod);
+
+   if (!hdmi->hpd_gpiod)
+   DBG("failed to get HPD gpio");
+
+   if (hdmi->hpd_gpiod)
+   gpiod_set_consumer_name(hdmi->hpd_gpiod, "HDMI_HPD");
 
dev->platform_data = hdmi_cfg;
 
diff --git a/drivers/gpu/drm/msm/hdmi/hdmi.h b/drivers/gpu/drm/msm/hdmi/hdmi.h
index 736f348befb3..a6c88d157bc3 100644
--- a/drivers/gpu/drm/msm/hdmi/hdmi.h
+++ b/drivers/gpu/drm/msm/hdmi/hdmi.h
@@ -19,17 +19,9 @@
 #include "msm_drv.h"
 #include "hdmi.xml.h"
 
-#define HDMI_MAX_NUM_GPIO  6
-
 struct hdmi_phy;
 struct hdmi_platform_config;
 
-struct hdmi_gpio_data {
-   struct gpio_desc *gpiod;
-   bool output;
-   int value;
-};
-
 struct hdmi_audio {
bool enabled;
struct hdmi_audio_infoframe infoframe;
@@ -61,6 +53,8 @@ struct hdmi {
struct clk **hpd_clks;
struct clk **pwr_clks;
 
+   struct gpio_desc *hpd_gpiod;
+
struct hdmi_phy *phy;
struct device *phy_dev;
 
@@ -109,9 +103,6 @@ struct hdmi_platform_config {
/* clks that need to be on for screen pwr (ie pixel 

[PATCH 5.18 275/879] drm: bridge: icn6211: Fix register layout

2022-06-07 Thread Greg Kroah-Hartman
From: Marek Vasut 

[ Upstream commit 2dcec57b3734029cc1adc5cb872f61e21609eed4 ]

The chip register layout has nothing to do with MIPI DCS, the registers
incorrectly marked as MIPI DCS in the driver are regular chip registers
often with completely different function.

Fill in the actual register names and bits from [1] and [2] and add the
entire register layout, since the documentation for this chip is hard to
come by.

[1] 
https://github.com/rockchip-linux/kernel/blob/develop-4.19/drivers/gpu/drm/bridge/icn6211.c
[2] https://github.com/tdjastrzebski/ICN6211-Configurator

Acked-by: Maxime Ripard 
Fixes: ce517f18944e3 ("drm: bridge: Add Chipone ICN6211 MIPI-DSI to RGB bridge")
Signed-off-by: Marek Vasut 
Cc: Jagan Teki 
Cc: Maxime Ripard 
Cc: Robert Foss 
Cc: Sam Ravnborg 
Cc: Thomas Zimmermann 
To: dri-devel@lists.freedesktop.org
Signed-off-by: Robert Foss 
Link: 
https://patchwork.freedesktop.org/patch/msgid/20220331150509.9838-2-ma...@denx.de
Signed-off-by: Sasha Levin 
---
 drivers/gpu/drm/bridge/chipone-icn6211.c | 134 ---
 1 file changed, 117 insertions(+), 17 deletions(-)

diff --git a/drivers/gpu/drm/bridge/chipone-icn6211.c 
b/drivers/gpu/drm/bridge/chipone-icn6211.c
index d9b7f48b99fb..376e0f80da5c 100644
--- a/drivers/gpu/drm/bridge/chipone-icn6211.c
+++ b/drivers/gpu/drm/bridge/chipone-icn6211.c
@@ -15,8 +15,19 @@
 #include 
 #include 
 
-#include 
-
+#define VENDOR_ID  0x00
+#define DEVICE_ID_H0x01
+#define DEVICE_ID_L0x02
+#define VERSION_ID 0x03
+#define FIRMWARE_VERSION   0x08
+#define CONFIG_FINISH  0x09
+#define PD_CTRL(n) (0x0a + ((n) & 0x3)) /* 0..3 */
+#define RST_CTRL(n)(0x0e + ((n) & 0x1)) /* 0..1 */
+#define SYS_CTRL(n)(0x10 + ((n) & 0x7)) /* 0..4 */
+#define RGB_DRV(n) (0x18 + ((n) & 0x3)) /* 0..3 */
+#define RGB_DLY(n) (0x1c + ((n) & 0x1)) /* 0..1 */
+#define RGB_TEST_CTRL  0x1e
+#define ATE_PLL_EN 0x1f
 #define HACTIVE_LI 0x20
 #define VACTIVE_LI 0x21
 #define VACTIVE_HACTIVE_HI 0x22
@@ -27,6 +38,95 @@
 #define VFP0x27
 #define VSYNC  0x28
 #define VBP0x29
+#define BIST_POL   0x2a
+#define BIST_POL_BIST_MODE(n)  (((n) & 0xf) << 4)
+#define BIST_POL_BIST_GEN  BIT(3)
+#define BIST_POL_HSYNC_POL BIT(2)
+#define BIST_POL_VSYNC_POL BIT(1)
+#define BIST_POL_DE_POLBIT(0)
+#define BIST_RED   0x2b
+#define BIST_GREEN 0x2c
+#define BIST_BLUE  0x2d
+#define BIST_CHESS_X   0x2e
+#define BIST_CHESS_Y   0x2f
+#define BIST_CHESS_XY_H0x30
+#define BIST_FRAME_TIME_L  0x31
+#define BIST_FRAME_TIME_H  0x32
+#define FIFO_MAX_ADDR_LOW  0x33
+#define SYNC_EVENT_DLY 0x34
+#define HSW_MIN0x35
+#define HFP_MIN0x36
+#define LOGIC_RST_NUM  0x37
+#define OSC_CTRL(n)(0x48 + ((n) & 0x7)) /* 0..5 */
+#define BG_CTRL0x4e
+#define LDO_PLL0x4f
+#define PLL_CTRL(n)(0x50 + ((n) & 0xf)) /* 0..15 */
+#define PLL_CTRL_6_EXTERNAL0x90
+#define PLL_CTRL_6_MIPI_CLK0x92
+#define PLL_CTRL_6_INTERNAL0x93
+#define PLL_REM(n) (0x60 + ((n) & 0x3)) /* 0..2 */
+#define PLL_DIV(n) (0x63 + ((n) & 0x3)) /* 0..2 */
+#define PLL_FRAC(n)(0x66 + ((n) & 0x3)) /* 0..2 */
+#define PLL_INT(n) (0x69 + ((n) & 0x1)) /* 0..1 */
+#define PLL_REF_DIV0x6b
+#define PLL_REF_DIV_P(n)   ((n) & 0xf)
+#define PLL_REF_DIV_Pe BIT(4)
+#define PLL_REF_DIV_S(n)   (((n) & 0x7) << 5)
+#define PLL_SSC_P(n)   (0x6c + ((n) & 0x3)) /* 0..2 */
+#define PLL_SSC_STEP(n)(0x6f + ((n) & 0x3)) /* 0..2 */
+#define PLL_SSC_OFFSET(n)  (0x72 + ((n) & 0x3)) /* 0..3 */
+#define GPIO_OEN   0x79
+#define MIPI_CFG_PW0x7a
+#define MIPI_CFG_PW_CONFIG_DSI 0xc1
+#define MIPI_CFG_PW_CONFIG_I2C 0x3e
+#define GPIO_SEL(n)(0x7b + ((n) & 0x1)) /* 0..1 */
+#define IRQ_SEL0x7d
+#define DBG_SEL0x7e
+#define DBG_SIGNAL 0x7f
+#define MIPI_ERR_VECTOR_L  0x80
+#define MIPI_ERR_VECTOR_H  0x81
+#define MIPI_ERR_VECTOR_EN_L   0x82
+#define MIPI_ERR_VECTOR_EN_H   0x83
+#define MIPI_MAX_SIZE_L0x84
+#define MIPI_MAX_SIZE_H0x85
+#define DSI_CTRL   0x86
+#define DSI_CTRL_UNKNOWN   0x28
+#define DSI_CTRL_DSI_LANES(n)  ((n) & 0x3)
+#define MIPI_PN_SWAP   0x87
+#define MIPI_PN_SWAP_CLK   BIT(4)
+#define MIPI_PN_SWAP_D(n)  BIT((n) & 0x3)
+#define MIPI_SOT_SYNC_BIT_(n)  (0x88 + ((n) & 0x1)) /* 0..1 */

  1   2   3   >