linux-kernel.vger.kernel.org archive mirror
 help / color / mirror / Atom feed
* Re: [PATCH v3 20/20] Documentation: gpu: vc4: Add KUnit Tests Section
       [not found] ` <20221123-rpi-kunit-tests-v3-20-4615a663a84a@cerno.tech>
@ 2022-12-07 13:55   ` Maíra Canal
  0 siblings, 0 replies; 7+ messages in thread
From: Maíra Canal @ 2022-12-07 13:55 UTC (permalink / raw)
  To: Maxime Ripard, Maxime Ripard, Maarten Lankhorst, Daniel Vetter,
	Thomas Zimmermann, David Airlie
  Cc: David Gow, Dave Stevenson, Greg Kroah-Hartman, Maíra Canal,
	Javier Martinez Canillas, dri-devel, linux-kernel, linaro-mm-sig,
	Brendan Higgins, linux-kselftest, kunit-dev, linux-media

On 12/1/22 12:11, Maxime Ripard wrote:
> Now that we have VC4-specific tests in place, let's document them
> properly.
> 
> Signed-off-by: Maxime Ripard <maxime@cerno.tech>

Reviewed-by: Maíra Canal <mcanal@igalia.com>

Just a small nit below.

> ---
>   Documentation/gpu/vc4.rst | 16 ++++++++++++++++
>   1 file changed, 16 insertions(+)
> 
> diff --git a/Documentation/gpu/vc4.rst b/Documentation/gpu/vc4.rst
> index 5df1d98b9544..a2375f1584e6 100644
> --- a/Documentation/gpu/vc4.rst
> +++ b/Documentation/gpu/vc4.rst
> @@ -54,6 +54,22 @@ VEC (Composite TV out) encoder
>   .. kernel-doc:: drivers/gpu/drm/vc4/vc4_vec.c
>      :doc: VC4 SDTV module
>   
> +KUnit Tests
> +===========
> +
> +The VC4 Driver uses KUnit to perform driver-specific unit and
> +integration tests.
> +
> +These tests are using a mock driver and can be ran using the
> +command::
> +	./tools/testing/kunit/kunit.py run \
> +		--kunitconfig=drivers/gpu/drm/vc4/tests/.kunitconfig \
> +		--cross_compile aarch64-linux-gnu- --arch arm64

I believe you could use a code block here, like:

.. code-block:: bash
	
	$ ./tools/testing/kunit/kunit.py run \
		--kunitconfig=drivers/gpu/drm/vc4/tests/.kunitconfig \
		--cross_compile aarch64-linux-gnu- --arch arm64

You could also mention that you can run the tests with --arch arm.

Best Regards,
- Maíra Canal

> +
> +Parts of the driver that are currently covered by tests are:
> + * The HVS to PixelValve dynamic FIFO assignment, for the BCM2835-7
> +   and BCM2711.
> +
>   Memory Management and 3D Command Submission
>   ===========================================
>   
> 

^ permalink raw reply	[flat|nested] 7+ messages in thread

* Re: [PATCH v3 02/20] drm/tests: Introduce a config option for the KUnit helpers
       [not found] ` <20221123-rpi-kunit-tests-v3-2-4615a663a84a@cerno.tech>
@ 2022-12-07 13:57   ` Maíra Canal
  0 siblings, 0 replies; 7+ messages in thread
From: Maíra Canal @ 2022-12-07 13:57 UTC (permalink / raw)
  To: Maxime Ripard, Maxime Ripard, Maarten Lankhorst, Daniel Vetter,
	Thomas Zimmermann, David Airlie
  Cc: David Gow, Dave Stevenson, Greg Kroah-Hartman, Maíra Canal,
	Javier Martinez Canillas, dri-devel, linux-kernel, linaro-mm-sig,
	Brendan Higgins, linux-kselftest, kunit-dev, linux-media

On 12/1/22 12:11, Maxime Ripard wrote:
> Driver-specific tests will need access to the helpers without pulling
> every DRM framework test. Let's create an intermediate Kconfig options
> for the helpers.
> 
> Suggested-by: Maíra Canal <mcanal@igalia.com>
> Signed-off-by: Maxime Ripard <maxime@cerno.tech>

Reviewed-by: Maíra Canal <mcanal@igalia.com>

Best Regards,
- Maíra Canal

> ---
>   drivers/gpu/drm/Kconfig        | 7 +++++++
>   drivers/gpu/drm/Makefile       | 2 +-
>   drivers/gpu/drm/tests/Makefile | 4 +++-
>   3 files changed, 11 insertions(+), 2 deletions(-)
> 
> diff --git a/drivers/gpu/drm/Kconfig b/drivers/gpu/drm/Kconfig
> index 315cbdf61979..9f019cd053e1 100644
> --- a/drivers/gpu/drm/Kconfig
> +++ b/drivers/gpu/drm/Kconfig
> @@ -63,6 +63,12 @@ config DRM_USE_DYNAMIC_DEBUG
>   	  bytes per callsite, the .data costs can be substantial, and
>   	  are therefore configurable.
>   
> +config DRM_KUNIT_TEST_HELPERS
> +	tristate
> +	depends on DRM && KUNIT
> +	help
> +	  KUnit Helpers for KMS drivers.
> +
>   config DRM_KUNIT_TEST
>   	tristate "KUnit tests for DRM" if !KUNIT_ALL_TESTS
>   	depends on DRM && KUNIT
> @@ -73,6 +79,7 @@ config DRM_KUNIT_TEST
>   	select DRM_KMS_HELPER
>   	select DRM_BUDDY
>   	select DRM_EXPORT_FOR_TESTS if m
> +	select DRM_KUNIT_TEST_HELPERS
>   	default KUNIT_ALL_TESTS
>   	help
>   	  This builds unit tests for DRM. This option is not useful for
> diff --git a/drivers/gpu/drm/Makefile b/drivers/gpu/drm/Makefile
> index f92cd7892711..8d61fbdfdfac 100644
> --- a/drivers/gpu/drm/Makefile
> +++ b/drivers/gpu/drm/Makefile
> @@ -125,7 +125,7 @@ obj-$(CONFIG_DRM_KMS_HELPER) += drm_kms_helper.o
>   # Drivers and the rest
>   #
>   
> -obj-$(CONFIG_DRM_KUNIT_TEST) += tests/
> +obj-y			+= tests/
>   
>   obj-$(CONFIG_DRM_MIPI_DBI) += drm_mipi_dbi.o
>   obj-$(CONFIG_DRM_MIPI_DSI) += drm_mipi_dsi.o
> diff --git a/drivers/gpu/drm/tests/Makefile b/drivers/gpu/drm/tests/Makefile
> index 94fe546d937d..ef14bd481139 100644
> --- a/drivers/gpu/drm/tests/Makefile
> +++ b/drivers/gpu/drm/tests/Makefile
> @@ -1,5 +1,8 @@
>   # SPDX-License-Identifier: GPL-2.0
>   
> +obj-$(CONFIG_DRM_KUNIT_TEST_HELPERS) += \
> +	drm_kunit_helpers.o
> +
>   obj-$(CONFIG_DRM_KUNIT_TEST) += \
>   	drm_buddy_test.o \
>   	drm_cmdline_parser_test.o \
> @@ -9,7 +12,6 @@ obj-$(CONFIG_DRM_KUNIT_TEST) += \
>   	drm_format_helper_test.o \
>   	drm_format_test.o \
>   	drm_framebuffer_test.o \
> -	drm_kunit_helpers.o \
>   	drm_mm_test.o \
>   	drm_modes_test.o \
>   	drm_plane_helper_test.o \
> 

^ permalink raw reply	[flat|nested] 7+ messages in thread

* Re: [PATCH v3 04/20] drm/tests: helpers: Switch to EXPORT_SYMBOL_GPL
       [not found] ` <20221123-rpi-kunit-tests-v3-4-4615a663a84a@cerno.tech>
@ 2022-12-07 13:59   ` Maíra Canal
  0 siblings, 0 replies; 7+ messages in thread
From: Maíra Canal @ 2022-12-07 13:59 UTC (permalink / raw)
  To: Maxime Ripard, Maxime Ripard, Maarten Lankhorst, Daniel Vetter,
	Thomas Zimmermann, David Airlie
  Cc: David Gow, Dave Stevenson, Greg Kroah-Hartman, Maíra Canal,
	Javier Martinez Canillas, dri-devel, linux-kernel, linaro-mm-sig,
	Brendan Higgins, linux-kselftest, kunit-dev, linux-media

On 12/1/22 12:11, Maxime Ripard wrote:
> drm_kunit_device_init() among other things will allocate a device and
> wrap around root_device_register. This function is exported with
> EXPORT_SYMBOL_GPL, so we can't really change the license.
> 
> Fixes: 199557fab925 ("drm/tests: helpers: Add missing export")
> Suggested-by: Javier Martinez Canillas <javierm@redhat.com>
> Signed-off-by: Maxime Ripard <maxime@cerno.tech>

Reviewed-by: Maíra Canal <mcanal@igalia.com>

Best Regards,
- Maíra Canal

> ---
>   drivers/gpu/drm/tests/drm_kunit_helpers.c | 2 +-
>   1 file changed, 1 insertion(+), 1 deletion(-)
> 
> diff --git a/drivers/gpu/drm/tests/drm_kunit_helpers.c b/drivers/gpu/drm/tests/drm_kunit_helpers.c
> index 9ed3cfc2ac03..4fe131141718 100644
> --- a/drivers/gpu/drm/tests/drm_kunit_helpers.c
> +++ b/drivers/gpu/drm/tests/drm_kunit_helpers.c
> @@ -82,7 +82,7 @@ struct drm_device *drm_kunit_device_init(struct kunit *test, u32 features, char
>   
>   	return drm;
>   }
> -EXPORT_SYMBOL(drm_kunit_device_init);
> +EXPORT_SYMBOL_GPL(drm_kunit_device_init);
>   
>   MODULE_AUTHOR("Maxime Ripard <maxime@cerno.tech>");
>   MODULE_LICENSE("GPL");
> 

^ permalink raw reply	[flat|nested] 7+ messages in thread

* Re: [PATCH v3 17/20] drm/vc4: tests: Introduce a mocking infrastructure
       [not found] ` <20221123-rpi-kunit-tests-v3-17-4615a663a84a@cerno.tech>
@ 2022-12-07 14:08   ` Maíra Canal
  0 siblings, 0 replies; 7+ messages in thread
From: Maíra Canal @ 2022-12-07 14:08 UTC (permalink / raw)
  To: Maxime Ripard, Maxime Ripard, Maarten Lankhorst, Daniel Vetter,
	Thomas Zimmermann, David Airlie
  Cc: David Gow, Dave Stevenson, Greg Kroah-Hartman,
	Javier Martinez Canillas, dri-devel, linux-kernel, linaro-mm-sig,
	Brendan Higgins, linux-kselftest, kunit-dev, Maíra Canal,
	linux-media

On 12/1/22 12:11, Maxime Ripard wrote:
> In order to test the current atomic_check hooks we need to have a DRM
> device that has roughly the same capabilities and layout that the actual
> hardware. We'll also need a bunch of functions to create arbitrary
> atomic states.
> 
> Let's create some helpers to create a device that behaves like the real
> one, and some helpers to maintain the atomic state we want to check.
> 
> Reviewed-by: Javier Martinez Canillas <javierm@redhat.com>
> Signed-off-by: Maxime Ripard <maxime@cerno.tech>

Reviewed-by: Maíra Canal <mcanal@igalia.com>

But it would be nice if you could fix the checkpatch problems in the 
vc4/tests folder.

Best Regards,
- Maíra Canal

> ---
>   drivers/gpu/drm/vc4/Kconfig                 |  16 +++
>   drivers/gpu/drm/vc4/Makefile                |   6 +
>   drivers/gpu/drm/vc4/tests/.kunitconfig      |  13 ++
>   drivers/gpu/drm/vc4/tests/vc4_mock.c        | 200 ++++++++++++++++++++++++++++
>   drivers/gpu/drm/vc4/tests/vc4_mock.h        |  60 +++++++++
>   drivers/gpu/drm/vc4/tests/vc4_mock_crtc.c   |  41 ++++++
>   drivers/gpu/drm/vc4/tests/vc4_mock_output.c |  99 ++++++++++++++
>   drivers/gpu/drm/vc4/tests/vc4_mock_plane.c  |  47 +++++++
>   drivers/gpu/drm/vc4/vc4_crtc.c              |  20 +--
>   drivers/gpu/drm/vc4/vc4_drv.c               |   4 +-
>   drivers/gpu/drm/vc4/vc4_drv.h               |  16 +++
>   drivers/gpu/drm/vc4/vc4_txp.c               |   2 +-
>   12 files changed, 511 insertions(+), 13 deletions(-)
> 
> diff --git a/drivers/gpu/drm/vc4/Kconfig b/drivers/gpu/drm/vc4/Kconfig
> index 246305d17a52..f423941c028d 100644
> --- a/drivers/gpu/drm/vc4/Kconfig
> +++ b/drivers/gpu/drm/vc4/Kconfig
> @@ -34,3 +34,19 @@ config DRM_VC4_HDMI_CEC
>   	help
>   	  Choose this option if you have a Broadcom VC4 GPU
>   	  and want to use CEC.
> +
> +config DRM_VC4_KUNIT_TEST
> +	bool "KUnit tests for VC4" if !KUNIT_ALL_TESTS
> +	depends on DRM_VC4 && KUNIT
> +	select DRM_KUNIT_TEST_HELPERS
> +	default KUNIT_ALL_TESTS
> +	help
> +	  This builds unit tests for the VC4 DRM/KMS driver. This option is
> +	  not useful for distributions or general kernels, but only for kernel
> +	  developers working on the VC4 driver.
> +
> +	  For more information on KUnit and unit tests in general,
> +	  please refer to the KUnit documentation in
> +	  Documentation/dev-tools/kunit/.
> +
> +	  If in doubt, say "N".
> diff --git a/drivers/gpu/drm/vc4/Makefile b/drivers/gpu/drm/vc4/Makefile
> index d0163e18e9ca..f974a8c80e2f 100644
> --- a/drivers/gpu/drm/vc4/Makefile
> +++ b/drivers/gpu/drm/vc4/Makefile
> @@ -25,6 +25,12 @@ vc4-y := \
>   	vc4_validate.o \
>   	vc4_validate_shaders.o
>   
> +vc4-$(CONFIG_DRM_VC4_KUNIT_TEST) += \
> +	tests/vc4_mock.o \
> +	tests/vc4_mock_crtc.o \
> +	tests/vc4_mock_output.o \
> +	tests/vc4_mock_plane.o
> +
>   vc4-$(CONFIG_DEBUG_FS) += vc4_debugfs.o
>   
>   obj-$(CONFIG_DRM_VC4)  += vc4.o
> diff --git a/drivers/gpu/drm/vc4/tests/.kunitconfig b/drivers/gpu/drm/vc4/tests/.kunitconfig
> new file mode 100644
> index 000000000000..b503e9036c7f
> --- /dev/null
> +++ b/drivers/gpu/drm/vc4/tests/.kunitconfig
> @@ -0,0 +1,13 @@
> +CONFIG_ARCH_BCM=y
> +CONFIG_ARCH_BCM2835=y
> +CONFIG_BCM2835_MBOX=y
> +CONFIG_KUNIT=y
> +CONFIG_DRM=y
> +CONFIG_DRM_VC4=y
> +CONFIG_DRM_VC4_KUNIT_TEST=y
> +CONFIG_MAILBOX=y
> +CONFIG_RASPBERRYPI_FIRMWARE=y
> +CONFIG_SND=y
> +CONFIG_SND_SOC=y
> +CONFIG_SOUND=y
> +CONFIG_COMMON_CLK=y
> diff --git a/drivers/gpu/drm/vc4/tests/vc4_mock.c b/drivers/gpu/drm/vc4/tests/vc4_mock.c
> new file mode 100644
> index 000000000000..a4bed26af32f
> --- /dev/null
> +++ b/drivers/gpu/drm/vc4/tests/vc4_mock.c
> @@ -0,0 +1,200 @@
> +// SPDX-License-Identifier: GPL-2.0
> +
> +#include <drm/drm_drv.h>
> +#include <drm/drm_kunit_helpers.h>
> +
> +#include <kunit/test.h>
> +
> +#include "vc4_mock.h"
> +
> +struct vc4_mock_output_desc {
> +	enum vc4_encoder_type	vc4_encoder_type;
> +	unsigned int		encoder_type;
> +	unsigned int		connector_type;
> +};
> +
> +#define VC4_MOCK_OUTPUT_DESC(_vc4_type, _etype, _ctype)					\
> +	{										\
> +		.vc4_encoder_type = _vc4_type,						\
> +		.encoder_type = _etype,							\
> +		.connector_type = _ctype,						\
> +	}
> +
> +struct vc4_mock_pipe_desc {
> +	const struct vc4_crtc_data *data;
> +	const struct vc4_mock_output_desc *outputs;
> +	unsigned int noutputs;
> +};
> +
> +#define VC4_MOCK_CRTC_DESC(_data, ...)							\
> +	{										\
> +		.data = _data,								\
> +		.outputs = (struct vc4_mock_output_desc[]) { __VA_ARGS__ },		\
> +		.noutputs = sizeof((struct vc4_mock_output_desc[]) { __VA_ARGS__ }) /	\
> +			     sizeof(struct vc4_mock_output_desc),			\
> +	}
> +
> +#define VC4_MOCK_PIXELVALVE_DESC(_data, ...)						\
> +	VC4_MOCK_CRTC_DESC(&(_data)->base, __VA_ARGS__)
> +
> +struct vc4_mock_desc {
> +	const struct vc4_mock_pipe_desc *pipes;
> +	unsigned int npipes;
> +};
> +
> +#define VC4_MOCK_DESC(...)								\
> +	{										\
> +		.pipes = (struct vc4_mock_pipe_desc[]) { __VA_ARGS__ },			\
> +		.npipes = sizeof((struct vc4_mock_pipe_desc[]) { __VA_ARGS__ }) /	\
> +			     sizeof(struct vc4_mock_pipe_desc),				\
> +	}
> +
> +static const struct vc4_mock_desc vc4_mock =
> +	VC4_MOCK_DESC(
> +		VC4_MOCK_CRTC_DESC(&vc4_txp_crtc_data,
> +				   VC4_MOCK_OUTPUT_DESC(VC4_ENCODER_TYPE_TXP,
> +							DRM_MODE_ENCODER_VIRTUAL,
> +							DRM_MODE_CONNECTOR_WRITEBACK)),
> +		VC4_MOCK_PIXELVALVE_DESC(&bcm2835_pv0_data,
> +					 VC4_MOCK_OUTPUT_DESC(VC4_ENCODER_TYPE_DSI0,
> +							      DRM_MODE_ENCODER_DSI,
> +							      DRM_MODE_CONNECTOR_DSI),
> +					 VC4_MOCK_OUTPUT_DESC(VC4_ENCODER_TYPE_DPI,
> +							      DRM_MODE_ENCODER_DPI,
> +							      DRM_MODE_CONNECTOR_DPI)),
> +		VC4_MOCK_PIXELVALVE_DESC(&bcm2835_pv1_data,
> +					 VC4_MOCK_OUTPUT_DESC(VC4_ENCODER_TYPE_DSI1,
> +							      DRM_MODE_ENCODER_DSI,
> +							      DRM_MODE_CONNECTOR_DSI)),
> +		VC4_MOCK_PIXELVALVE_DESC(&bcm2835_pv2_data,
> +					 VC4_MOCK_OUTPUT_DESC(VC4_ENCODER_TYPE_HDMI0,
> +							      DRM_MODE_ENCODER_TMDS,
> +							      DRM_MODE_CONNECTOR_HDMIA),
> +					 VC4_MOCK_OUTPUT_DESC(VC4_ENCODER_TYPE_VEC,
> +							      DRM_MODE_ENCODER_TVDAC,
> +							      DRM_MODE_CONNECTOR_Composite)),
> +);
> +
> +static const struct vc4_mock_desc vc5_mock =
> +	VC4_MOCK_DESC(
> +		VC4_MOCK_CRTC_DESC(&vc4_txp_crtc_data,
> +				   VC4_MOCK_OUTPUT_DESC(VC4_ENCODER_TYPE_TXP,
> +							DRM_MODE_ENCODER_VIRTUAL,
> +							DRM_MODE_CONNECTOR_WRITEBACK)),
> +		VC4_MOCK_PIXELVALVE_DESC(&bcm2711_pv0_data,
> +					 VC4_MOCK_OUTPUT_DESC(VC4_ENCODER_TYPE_DSI0,
> +							      DRM_MODE_ENCODER_DSI,
> +							      DRM_MODE_CONNECTOR_DSI),
> +					 VC4_MOCK_OUTPUT_DESC(VC4_ENCODER_TYPE_DPI,
> +							      DRM_MODE_ENCODER_DPI,
> +							      DRM_MODE_CONNECTOR_DPI)),
> +		VC4_MOCK_PIXELVALVE_DESC(&bcm2711_pv1_data,
> +					 VC4_MOCK_OUTPUT_DESC(VC4_ENCODER_TYPE_DSI1,
> +							      DRM_MODE_ENCODER_DSI,
> +							      DRM_MODE_CONNECTOR_DSI)),
> +		VC4_MOCK_PIXELVALVE_DESC(&bcm2711_pv2_data,
> +					 VC4_MOCK_OUTPUT_DESC(VC4_ENCODER_TYPE_HDMI0,
> +							      DRM_MODE_ENCODER_TMDS,
> +							      DRM_MODE_CONNECTOR_HDMIA)),
> +		VC4_MOCK_PIXELVALVE_DESC(&bcm2711_pv3_data,
> +					 VC4_MOCK_OUTPUT_DESC(VC4_ENCODER_TYPE_VEC,
> +							      DRM_MODE_ENCODER_TVDAC,
> +							      DRM_MODE_CONNECTOR_Composite)),
> +		VC4_MOCK_PIXELVALVE_DESC(&bcm2711_pv4_data,
> +					 VC4_MOCK_OUTPUT_DESC(VC4_ENCODER_TYPE_HDMI1,
> +							      DRM_MODE_ENCODER_TMDS,
> +							      DRM_MODE_CONNECTOR_HDMIA)),
> +);
> +
> +static int __build_one_pipe(struct kunit *test, struct drm_device *drm,
> +			    const struct vc4_mock_pipe_desc *pipe)
> +{
> +	struct vc4_dummy_plane *dummy_plane;
> +	struct drm_plane *plane;
> +	struct vc4_dummy_crtc *dummy_crtc;
> +	struct drm_crtc *crtc;
> +	unsigned int i;
> +
> +	dummy_plane = vc4_dummy_plane(test, drm, DRM_PLANE_TYPE_PRIMARY);
> +	KUNIT_ASSERT_NOT_ERR_OR_NULL(test, dummy_plane);
> +
> +	plane = &dummy_plane->plane.base;
> +	dummy_crtc = vc4_mock_pv(test, drm, plane, pipe->data);
> +	KUNIT_ASSERT_NOT_ERR_OR_NULL(test, dummy_crtc);
> +
> +	crtc = &dummy_crtc->crtc.base;
> +	for (i = 0; i < pipe->noutputs; i++) {
> +		const struct vc4_mock_output_desc *mock_output = &pipe->outputs[i];
> +		struct vc4_dummy_output *dummy_output;
> +
> +		dummy_output = vc4_dummy_output(test, drm, crtc,
> +						mock_output->vc4_encoder_type,
> +						mock_output->encoder_type,
> +						mock_output->connector_type);
> +		KUNIT_ASSERT_NOT_ERR_OR_NULL(test, dummy_output);
> +	}
> +
> +	return 0;
> +}
> +
> +static int __build_mock(struct kunit *test, struct drm_device *drm,
> +			const struct vc4_mock_desc *mock)
> +{
> +	unsigned int i;
> +
> +	for (i = 0; i < mock->npipes; i++) {
> +		const struct vc4_mock_pipe_desc *pipe = &mock->pipes[i];
> +		int ret;
> +
> +		ret = __build_one_pipe(test, drm, pipe);
> +		KUNIT_ASSERT_EQ(test, ret, 0);
> +	}
> +
> +	return 0;
> +}
> +
> +static struct vc4_dev *__mock_device(struct kunit *test, bool is_vc5)
> +{
> +	struct drm_device *drm;
> +	const struct drm_driver *drv = is_vc5 ? &vc5_drm_driver : &vc4_drm_driver;
> +	const struct vc4_mock_desc *desc = is_vc5 ? &vc5_mock : &vc4_mock;
> +	struct vc4_dev *vc4;
> +	struct device *dev;
> +	int ret;
> +
> +	dev = drm_kunit_helper_alloc_device(test);
> +	KUNIT_ASSERT_NOT_ERR_OR_NULL(test, dev);
> +
> +	vc4 = drm_kunit_helper_alloc_drm_device_with_driver(test, dev,
> +							    struct vc4_dev, base,
> +							    drv);
> +	KUNIT_ASSERT_NOT_ERR_OR_NULL(test, vc4);
> +
> +	vc4->dev = dev;
> +	vc4->is_vc5 = is_vc5;
> +
> +	vc4->hvs = __vc4_hvs_alloc(vc4, NULL);
> +	KUNIT_ASSERT_NOT_ERR_OR_NULL(test, vc4->hvs);
> +
> +	drm = &vc4->base;
> +	ret = __build_mock(test, drm, desc);
> +	KUNIT_ASSERT_EQ(test, ret, 0);
> +
> +	ret = vc4_kms_load(drm);
> +	KUNIT_ASSERT_EQ(test, ret, 0);
> +
> +	ret = drm_dev_register(drm, 0);
> +	KUNIT_ASSERT_EQ(test, ret, 0);
> +
> +	return vc4;
> +}
> +
> +struct vc4_dev *vc4_mock_device(struct kunit *test)
> +{
> +	return __mock_device(test, false);
> +}
> +
> +struct vc4_dev *vc5_mock_device(struct kunit *test)
> +{
> +	return __mock_device(test, true);
> +}
> diff --git a/drivers/gpu/drm/vc4/tests/vc4_mock.h b/drivers/gpu/drm/vc4/tests/vc4_mock.h
> new file mode 100644
> index 000000000000..ace5b2e00f4a
> --- /dev/null
> +++ b/drivers/gpu/drm/vc4/tests/vc4_mock.h
> @@ -0,0 +1,60 @@
> +/* SPDX-License-Identifier: GPL-2.0 */
> +
> +#ifndef VC4_MOCK_H_
> +#define VC4_MOCK_H_
> +
> +#include "../vc4_drv.h"
> +
> +static inline
> +struct drm_crtc *vc4_find_crtc_for_encoder(struct kunit *test,
> +					   struct drm_device *drm,
> +					   struct drm_encoder *encoder)
> +{
> +	struct drm_crtc *crtc;
> +
> +	KUNIT_ASSERT_EQ(test, hweight32(encoder->possible_crtcs), 1);
> +
> +	drm_for_each_crtc(crtc, drm)
> +		if (encoder->possible_crtcs & drm_crtc_mask(crtc))
> +			return crtc;
> +
> +	return NULL;
> +}
> +
> +struct vc4_dummy_plane {
> +	struct vc4_plane plane;
> +};
> +
> +struct vc4_dummy_plane *vc4_dummy_plane(struct kunit *test,
> +					struct drm_device *drm,
> +					enum drm_plane_type type);
> +
> +struct vc4_dummy_crtc {
> +	struct vc4_crtc crtc;
> +};
> +
> +struct vc4_dummy_crtc *vc4_mock_pv(struct kunit *test,
> +				   struct drm_device *drm,
> +				   struct drm_plane *plane,
> +				   const struct vc4_crtc_data *data);
> +
> +struct vc4_dummy_output {
> +	struct vc4_encoder encoder;
> +	struct drm_connector connector;
> +};
> +
> +struct vc4_dummy_output *vc4_dummy_output(struct kunit *test,
> +					  struct drm_device *drm,
> +					  struct drm_crtc *crtc,
> +					  enum vc4_encoder_type vc4_encoder_type,
> +					  unsigned int kms_encoder_type,
> +					  unsigned int connector_type);
> +
> +struct vc4_dev *vc4_mock_device(struct kunit *test);
> +struct vc4_dev *vc5_mock_device(struct kunit *test);
> +
> +int vc4_mock_atomic_add_output(struct kunit *test, struct drm_device *drm,
> +			       enum vc4_encoder_type type,
> +			       struct drm_atomic_state *state);
> +
> +#endif // VC4_MOCK_H_
> diff --git a/drivers/gpu/drm/vc4/tests/vc4_mock_crtc.c b/drivers/gpu/drm/vc4/tests/vc4_mock_crtc.c
> new file mode 100644
> index 000000000000..5d12d7beef0e
> --- /dev/null
> +++ b/drivers/gpu/drm/vc4/tests/vc4_mock_crtc.c
> @@ -0,0 +1,41 @@
> +// SPDX-License-Identifier: GPL-2.0
> +
> +#include <drm/drm_atomic_state_helper.h>
> +#include <drm/drm_modeset_helper_vtables.h>
> +
> +#include <kunit/test.h>
> +
> +#include "vc4_mock.h"
> +
> +static const struct drm_crtc_helper_funcs vc4_dummy_crtc_helper_funcs = {
> +	.atomic_check	= vc4_crtc_atomic_check,
> +};
> +
> +static const struct drm_crtc_funcs vc4_dummy_crtc_funcs = {
> +	.atomic_destroy_state	= vc4_crtc_destroy_state,
> +	.atomic_duplicate_state	= vc4_crtc_duplicate_state,
> +	.reset			= vc4_crtc_reset,
> +};
> +
> +struct vc4_dummy_crtc *vc4_mock_pv(struct kunit *test,
> +				   struct drm_device *drm,
> +				   struct drm_plane *plane,
> +				   const struct vc4_crtc_data *data)
> +{
> +	struct vc4_dummy_crtc *dummy_crtc;
> +	struct vc4_crtc *vc4_crtc;
> +	int ret;
> +
> +	dummy_crtc = kunit_kzalloc(test, sizeof(*dummy_crtc), GFP_KERNEL);
> +	KUNIT_ASSERT_NOT_NULL(test, dummy_crtc);
> +
> +	vc4_crtc = &dummy_crtc->crtc;
> +	ret = __vc4_crtc_init(drm, NULL,
> +			      vc4_crtc, data, plane,
> +			      &vc4_dummy_crtc_funcs,
> +			      &vc4_dummy_crtc_helper_funcs,
> +			      false);
> +	KUNIT_ASSERT_EQ(test, ret, 0);
> +
> +	return dummy_crtc;
> +}
> diff --git a/drivers/gpu/drm/vc4/tests/vc4_mock_output.c b/drivers/gpu/drm/vc4/tests/vc4_mock_output.c
> new file mode 100644
> index 000000000000..cb16ab4451f7
> --- /dev/null
> +++ b/drivers/gpu/drm/vc4/tests/vc4_mock_output.c
> @@ -0,0 +1,99 @@
> +// SPDX-License-Identifier: GPL-2.0
> +
> +#include <drm/drm_atomic_state_helper.h>
> +#include <drm/drm_atomic_uapi.h>
> +#include <drm/drm_connector.h>
> +#include <drm/drm_crtc.h>
> +#include <drm/drm_encoder.h>
> +#include <drm/drm_modeset_helper_vtables.h>
> +
> +#include <kunit/test.h>
> +
> +#include "vc4_mock.h"
> +
> +static const struct drm_connector_helper_funcs vc4_dummy_connector_helper_funcs = {
> +};
> +
> +static const struct drm_connector_funcs vc4_dummy_connector_funcs = {
> +	.atomic_destroy_state	= drm_atomic_helper_connector_destroy_state,
> +	.atomic_duplicate_state	= drm_atomic_helper_connector_duplicate_state,
> +	.reset			= drm_atomic_helper_connector_reset,
> +};
> +
> +struct vc4_dummy_output *vc4_dummy_output(struct kunit *test,
> +					  struct drm_device *drm,
> +					  struct drm_crtc *crtc,
> +					  enum vc4_encoder_type vc4_encoder_type,
> +					  unsigned int kms_encoder_type,
> +					  unsigned int connector_type)
> +{
> +	struct vc4_dummy_output *dummy_output;
> +	struct drm_connector *conn;
> +	struct drm_encoder *enc;
> +	int ret;
> +
> +	dummy_output = kunit_kzalloc(test, sizeof(*dummy_output), GFP_KERNEL);
> +	KUNIT_ASSERT_NOT_ERR_OR_NULL(test, dummy_output);
> +	dummy_output->encoder.type = vc4_encoder_type;
> +
> +	enc = &dummy_output->encoder.base;
> +	ret = drmm_encoder_init(drm, enc,
> +				NULL,
> +				kms_encoder_type,
> +				NULL);
> +	KUNIT_ASSERT_EQ(test, ret, 0);
> +	enc->possible_crtcs = drm_crtc_mask(crtc);
> +
> +	conn = &dummy_output->connector;
> +	ret = drmm_connector_init(drm, conn,
> +				  &vc4_dummy_connector_funcs,
> +				  connector_type,
> +				  NULL);
> +	KUNIT_ASSERT_EQ(test, ret, 0);
> +
> +	drm_connector_helper_add(conn, &vc4_dummy_connector_helper_funcs);
> +	drm_connector_attach_encoder(conn, enc);
> +
> +	return dummy_output;
> +}
> +
> +static const struct drm_display_mode default_mode = {
> +	DRM_SIMPLE_MODE(640, 480, 64, 48)
> +};
> +
> +int vc4_mock_atomic_add_output(struct kunit *test, struct drm_device *drm,
> +			       enum vc4_encoder_type type,
> +			       struct drm_atomic_state *state)
> +{
> +	struct vc4_dummy_output *output;
> +	struct drm_connector *conn;
> +	struct drm_connector_state *conn_state;
> +	struct drm_encoder *encoder;
> +	struct drm_crtc *crtc;
> +	struct drm_crtc_state *crtc_state;
> +	int ret;
> +
> +	encoder = vc4_find_encoder_by_type(drm, type);
> +	KUNIT_ASSERT_NOT_ERR_OR_NULL(test, encoder);
> +
> +	crtc = vc4_find_crtc_for_encoder(test, drm, encoder);
> +	KUNIT_ASSERT_NOT_ERR_OR_NULL(test, crtc);
> +
> +	output = container_of(encoder, struct vc4_dummy_output, encoder.base);
> +	conn = &output->connector;
> +	conn_state = drm_atomic_get_connector_state(state, conn);
> +	KUNIT_ASSERT_NOT_ERR_OR_NULL(test, conn_state);
> +
> +	ret = drm_atomic_set_crtc_for_connector(conn_state, crtc);
> +	KUNIT_EXPECT_EQ(test, ret, 0);
> +
> +	crtc_state = drm_atomic_get_crtc_state(state, crtc);
> +	KUNIT_ASSERT_NOT_ERR_OR_NULL(test, crtc_state);
> +
> +	ret = drm_atomic_set_mode_for_crtc(crtc_state, &default_mode);
> +	KUNIT_EXPECT_EQ(test, ret, 0);
> +
> +	crtc_state->active = true;
> +
> +	return 0;
> +}
> diff --git a/drivers/gpu/drm/vc4/tests/vc4_mock_plane.c b/drivers/gpu/drm/vc4/tests/vc4_mock_plane.c
> new file mode 100644
> index 000000000000..62b18f5f41db
> --- /dev/null
> +++ b/drivers/gpu/drm/vc4/tests/vc4_mock_plane.c
> @@ -0,0 +1,47 @@
> +// SPDX-License-Identifier: GPL-2.0
> +
> +#include <drm/drm_atomic_state_helper.h>
> +#include <drm/drm_fourcc.h>
> +#include <drm/drm_modeset_helper_vtables.h>
> +#include <drm/drm_plane.h>
> +
> +#include <kunit/test.h>
> +
> +#include "vc4_mock.h"
> +
> +static const struct drm_plane_helper_funcs vc4_dummy_plane_helper_funcs = {
> +};
> +
> +static const struct drm_plane_funcs vc4_dummy_plane_funcs = {
> +	.atomic_destroy_state	= drm_atomic_helper_plane_destroy_state,
> +	.atomic_duplicate_state	= drm_atomic_helper_plane_duplicate_state,
> +	.reset			= drm_atomic_helper_plane_reset,
> +};
> +
> +static const uint32_t vc4_dummy_plane_formats[] = {
> +	DRM_FORMAT_XRGB8888,
> +};
> +
> +struct vc4_dummy_plane *vc4_dummy_plane(struct kunit *test,
> +					struct drm_device *drm,
> +					enum drm_plane_type type)
> +{
> +	struct vc4_dummy_plane *dummy_plane;
> +	struct drm_plane *plane;
> +
> +	dummy_plane = drmm_universal_plane_alloc(drm,
> +						 struct vc4_dummy_plane, plane.base,
> +						 0,
> +						 &vc4_dummy_plane_funcs,
> +						 vc4_dummy_plane_formats,
> +						 ARRAY_SIZE(vc4_dummy_plane_formats),
> +						 NULL,
> +						 DRM_PLANE_TYPE_PRIMARY,
> +						 NULL);
> +	KUNIT_ASSERT_NOT_ERR_OR_NULL(test, dummy_plane);
> +
> +	plane = &dummy_plane->plane.base;
> +	drm_plane_helper_add(plane, &vc4_dummy_plane_helper_funcs);
> +
> +	return dummy_plane;
> +}
> diff --git a/drivers/gpu/drm/vc4/vc4_crtc.c b/drivers/gpu/drm/vc4/vc4_crtc.c
> index 195d2b61839d..7d1a696477ce 100644
> --- a/drivers/gpu/drm/vc4/vc4_crtc.c
> +++ b/drivers/gpu/drm/vc4/vc4_crtc.c
> @@ -675,8 +675,8 @@ void vc4_crtc_get_margins(struct drm_crtc_state *state,
>   	}
>   }
>   
> -static int vc4_crtc_atomic_check(struct drm_crtc *crtc,
> -				 struct drm_atomic_state *state)
> +int vc4_crtc_atomic_check(struct drm_crtc *crtc,
> +			  struct drm_atomic_state *state)
>   {
>   	struct drm_crtc_state *crtc_state = drm_atomic_get_new_crtc_state(state,
>   									  crtc);
> @@ -1116,7 +1116,7 @@ static const struct drm_crtc_helper_funcs vc4_crtc_helper_funcs = {
>   	.get_scanout_position = vc4_crtc_get_scanout_position,
>   };
>   
> -static const struct vc4_pv_data bcm2835_pv0_data = {
> +const struct vc4_pv_data bcm2835_pv0_data = {
>   	.base = {
>   		.name = "pixelvalve-0",
>   		.debugfs_name = "crtc0_regs",
> @@ -1131,7 +1131,7 @@ static const struct vc4_pv_data bcm2835_pv0_data = {
>   	},
>   };
>   
> -static const struct vc4_pv_data bcm2835_pv1_data = {
> +const struct vc4_pv_data bcm2835_pv1_data = {
>   	.base = {
>   		.name = "pixelvalve-1",
>   		.debugfs_name = "crtc1_regs",
> @@ -1146,7 +1146,7 @@ static const struct vc4_pv_data bcm2835_pv1_data = {
>   	},
>   };
>   
> -static const struct vc4_pv_data bcm2835_pv2_data = {
> +const struct vc4_pv_data bcm2835_pv2_data = {
>   	.base = {
>   		.name = "pixelvalve-2",
>   		.debugfs_name = "crtc2_regs",
> @@ -1161,7 +1161,7 @@ static const struct vc4_pv_data bcm2835_pv2_data = {
>   	},
>   };
>   
> -static const struct vc4_pv_data bcm2711_pv0_data = {
> +const struct vc4_pv_data bcm2711_pv0_data = {
>   	.base = {
>   		.name = "pixelvalve-0",
>   		.debugfs_name = "crtc0_regs",
> @@ -1176,7 +1176,7 @@ static const struct vc4_pv_data bcm2711_pv0_data = {
>   	},
>   };
>   
> -static const struct vc4_pv_data bcm2711_pv1_data = {
> +const struct vc4_pv_data bcm2711_pv1_data = {
>   	.base = {
>   		.name = "pixelvalve-1",
>   		.debugfs_name = "crtc1_regs",
> @@ -1191,7 +1191,7 @@ static const struct vc4_pv_data bcm2711_pv1_data = {
>   	},
>   };
>   
> -static const struct vc4_pv_data bcm2711_pv2_data = {
> +const struct vc4_pv_data bcm2711_pv2_data = {
>   	.base = {
>   		.name = "pixelvalve-2",
>   		.debugfs_name = "crtc2_regs",
> @@ -1205,7 +1205,7 @@ static const struct vc4_pv_data bcm2711_pv2_data = {
>   	},
>   };
>   
> -static const struct vc4_pv_data bcm2711_pv3_data = {
> +const struct vc4_pv_data bcm2711_pv3_data = {
>   	.base = {
>   		.name = "pixelvalve-3",
>   		.debugfs_name = "crtc3_regs",
> @@ -1219,7 +1219,7 @@ static const struct vc4_pv_data bcm2711_pv3_data = {
>   	},
>   };
>   
> -static const struct vc4_pv_data bcm2711_pv4_data = {
> +const struct vc4_pv_data bcm2711_pv4_data = {
>   	.base = {
>   		.name = "pixelvalve-4",
>   		.debugfs_name = "crtc4_regs",
> diff --git a/drivers/gpu/drm/vc4/vc4_drv.c b/drivers/gpu/drm/vc4/vc4_drv.c
> index 5990d8f8c363..3b0ae2c3e33c 100644
> --- a/drivers/gpu/drm/vc4/vc4_drv.c
> +++ b/drivers/gpu/drm/vc4/vc4_drv.c
> @@ -196,7 +196,7 @@ static const struct drm_ioctl_desc vc4_drm_ioctls[] = {
>   	DRM_IOCTL_DEF_DRV(VC4_PERFMON_GET_VALUES, vc4_perfmon_get_values_ioctl, DRM_RENDER_ALLOW),
>   };
>   
> -static const struct drm_driver vc4_drm_driver = {
> +const struct drm_driver vc4_drm_driver = {
>   	.driver_features = (DRIVER_MODESET |
>   			    DRIVER_ATOMIC |
>   			    DRIVER_GEM |
> @@ -225,7 +225,7 @@ static const struct drm_driver vc4_drm_driver = {
>   	.patchlevel = DRIVER_PATCHLEVEL,
>   };
>   
> -static const struct drm_driver vc5_drm_driver = {
> +const struct drm_driver vc5_drm_driver = {
>   	.driver_features = (DRIVER_MODESET |
>   			    DRIVER_ATOMIC |
>   			    DRIVER_GEM),
> diff --git a/drivers/gpu/drm/vc4/vc4_drv.h b/drivers/gpu/drm/vc4/vc4_drv.h
> index e0be7a81a24a..418f4f308e36 100644
> --- a/drivers/gpu/drm/vc4/vc4_drv.h
> +++ b/drivers/gpu/drm/vc4/vc4_drv.h
> @@ -24,6 +24,9 @@
>   struct drm_device;
>   struct drm_gem_object;
>   
> +extern const struct drm_driver vc4_drm_driver;
> +extern const struct drm_driver vc5_drm_driver;
> +
>   /* Don't forget to update vc4_bo.c: bo_type_names[] when adding to
>    * this.
>    */
> @@ -523,6 +526,8 @@ struct vc4_crtc_data {
>   	int hvs_output;
>   };
>   
> +extern const struct vc4_crtc_data vc4_txp_crtc_data;
> +
>   struct vc4_pv_data {
>   	struct vc4_crtc_data	base;
>   
> @@ -535,6 +540,15 @@ struct vc4_pv_data {
>   	enum vc4_encoder_type encoder_types[4];
>   };
>   
> +extern const struct vc4_pv_data bcm2835_pv0_data;
> +extern const struct vc4_pv_data bcm2835_pv1_data;
> +extern const struct vc4_pv_data bcm2835_pv2_data;
> +extern const struct vc4_pv_data bcm2711_pv0_data;
> +extern const struct vc4_pv_data bcm2711_pv1_data;
> +extern const struct vc4_pv_data bcm2711_pv2_data;
> +extern const struct vc4_pv_data bcm2711_pv3_data;
> +extern const struct vc4_pv_data bcm2711_pv4_data;
> +
>   struct vc4_crtc {
>   	struct drm_crtc base;
>   	struct platform_device *pdev;
> @@ -920,6 +934,8 @@ int vc4_page_flip(struct drm_crtc *crtc,
>   		  struct drm_pending_vblank_event *event,
>   		  uint32_t flags,
>   		  struct drm_modeset_acquire_ctx *ctx);
> +int vc4_crtc_atomic_check(struct drm_crtc *crtc,
> +			  struct drm_atomic_state *state);
>   struct drm_crtc_state *vc4_crtc_duplicate_state(struct drm_crtc *crtc);
>   void vc4_crtc_destroy_state(struct drm_crtc *crtc,
>   			    struct drm_crtc_state *state);
> diff --git a/drivers/gpu/drm/vc4/vc4_txp.c b/drivers/gpu/drm/vc4/vc4_txp.c
> index 4f7ce5d3e8ad..2b69454b8534 100644
> --- a/drivers/gpu/drm/vc4/vc4_txp.c
> +++ b/drivers/gpu/drm/vc4/vc4_txp.c
> @@ -479,7 +479,7 @@ static irqreturn_t vc4_txp_interrupt(int irq, void *data)
>   	return IRQ_HANDLED;
>   }
>   
> -static const struct vc4_crtc_data vc4_txp_crtc_data = {
> +const struct vc4_crtc_data vc4_txp_crtc_data = {
>   	.name = "txp",
>   	.debugfs_name = "txp_regs",
>   	.hvs_available_channels = BIT(2),
> 

^ permalink raw reply	[flat|nested] 7+ messages in thread

* Re: [PATCH v3 19/20] drm/vc4: tests: Add unit test suite for the PV muxing
       [not found] ` <20221123-rpi-kunit-tests-v3-19-4615a663a84a@cerno.tech>
@ 2022-12-07 14:24   ` Maíra Canal
  0 siblings, 0 replies; 7+ messages in thread
From: Maíra Canal @ 2022-12-07 14:24 UTC (permalink / raw)
  To: Maxime Ripard, Maxime Ripard, Maarten Lankhorst, Daniel Vetter,
	Thomas Zimmermann, David Airlie
  Cc: David Gow, Dave Stevenson, Greg Kroah-Hartman,
	Javier Martinez Canillas, dri-devel, linux-kernel, linaro-mm-sig,
	Brendan Higgins, linux-kselftest, kunit-dev, Maíra Canal,
	linux-media

On 12/1/22 12:11, Maxime Ripard wrote:
> The HVS to PixelValve muxing code is fairly error prone and has a bunch
> of arbitrary constraints due to the hardware setup.
> 
> Let's create a test suite that makes sure that the possible combinations
> work and the invalid ones don't.
> 
> Reviewed-by: Javier Martinez Canillas <javierm@redhat.com>
> Signed-off-by: Maxime Ripard <maxime@cerno.tech>

Reviewed-by: Maíra Canal <mcanal@igalia.com>

Best Regards,
- Maíra Canal

> ---
>   drivers/gpu/drm/vc4/Makefile                   |    3 +-
>   drivers/gpu/drm/vc4/tests/vc4_mock.h           |    9 +-
>   drivers/gpu/drm/vc4/tests/vc4_mock_output.c    |   49 +-
>   drivers/gpu/drm/vc4/tests/vc4_test_pv_muxing.c | 1039 ++++++++++++++++++++++++
>   4 files changed, 1091 insertions(+), 9 deletions(-)
> 
> diff --git a/drivers/gpu/drm/vc4/Makefile b/drivers/gpu/drm/vc4/Makefile
> index f974a8c80e2f..c41f89a15a55 100644
> --- a/drivers/gpu/drm/vc4/Makefile
> +++ b/drivers/gpu/drm/vc4/Makefile
> @@ -29,7 +29,8 @@ vc4-$(CONFIG_DRM_VC4_KUNIT_TEST) += \
>   	tests/vc4_mock.o \
>   	tests/vc4_mock_crtc.o \
>   	tests/vc4_mock_output.o \
> -	tests/vc4_mock_plane.o
> +	tests/vc4_mock_plane.o \
> +	tests/vc4_test_pv_muxing.o
>   
>   vc4-$(CONFIG_DEBUG_FS) += vc4_debugfs.o
>   
> diff --git a/drivers/gpu/drm/vc4/tests/vc4_mock.h b/drivers/gpu/drm/vc4/tests/vc4_mock.h
> index ace5b2e00f4a..db8e9a141ef8 100644
> --- a/drivers/gpu/drm/vc4/tests/vc4_mock.h
> +++ b/drivers/gpu/drm/vc4/tests/vc4_mock.h
> @@ -53,8 +53,11 @@ struct vc4_dummy_output *vc4_dummy_output(struct kunit *test,
>   struct vc4_dev *vc4_mock_device(struct kunit *test);
>   struct vc4_dev *vc5_mock_device(struct kunit *test);
>   
> -int vc4_mock_atomic_add_output(struct kunit *test, struct drm_device *drm,
> -			       enum vc4_encoder_type type,
> -			       struct drm_atomic_state *state);
> +int vc4_mock_atomic_add_output(struct kunit *test,
> +			       struct drm_atomic_state *state,
> +			       enum vc4_encoder_type type);
> +int vc4_mock_atomic_del_output(struct kunit *test,
> +			       struct drm_atomic_state *state,
> +			       enum vc4_encoder_type type);
>   
>   #endif // VC4_MOCK_H_
> diff --git a/drivers/gpu/drm/vc4/tests/vc4_mock_output.c b/drivers/gpu/drm/vc4/tests/vc4_mock_output.c
> index cb16ab4451f7..8d33be828d9a 100644
> --- a/drivers/gpu/drm/vc4/tests/vc4_mock_output.c
> +++ b/drivers/gpu/drm/vc4/tests/vc4_mock_output.c
> @@ -61,16 +61,17 @@ static const struct drm_display_mode default_mode = {
>   	DRM_SIMPLE_MODE(640, 480, 64, 48)
>   };
>   
> -int vc4_mock_atomic_add_output(struct kunit *test, struct drm_device *drm,
> -			       enum vc4_encoder_type type,
> -			       struct drm_atomic_state *state)
> +int vc4_mock_atomic_add_output(struct kunit *test,
> +			       struct drm_atomic_state *state,
> +			       enum vc4_encoder_type type)
>   {
> +	struct drm_device *drm = state->dev;
> +	struct drm_connector_state *conn_state;
> +	struct drm_crtc_state *crtc_state;
>   	struct vc4_dummy_output *output;
>   	struct drm_connector *conn;
> -	struct drm_connector_state *conn_state;
>   	struct drm_encoder *encoder;
>   	struct drm_crtc *crtc;
> -	struct drm_crtc_state *crtc_state;
>   	int ret;
>   
>   	encoder = vc4_find_encoder_by_type(drm, type);
> @@ -97,3 +98,41 @@ int vc4_mock_atomic_add_output(struct kunit *test, struct drm_device *drm,
>   
>   	return 0;
>   }
> +
> +int vc4_mock_atomic_del_output(struct kunit *test,
> +			       struct drm_atomic_state *state,
> +			       enum vc4_encoder_type type)
> +{
> +	struct drm_device *drm = state->dev;
> +	struct drm_connector_state *conn_state;
> +	struct drm_crtc_state *crtc_state;
> +	struct vc4_dummy_output *output;
> +	struct drm_connector *conn;
> +	struct drm_encoder *encoder;
> +	struct drm_crtc *crtc;
> +	int ret;
> +
> +	encoder = vc4_find_encoder_by_type(drm, type);
> +	KUNIT_ASSERT_NOT_ERR_OR_NULL(test, encoder);
> +
> +	crtc = vc4_find_crtc_for_encoder(test, drm, encoder);
> +	KUNIT_ASSERT_NOT_ERR_OR_NULL(test, crtc);
> +
> +	crtc_state = drm_atomic_get_crtc_state(state, crtc);
> +	KUNIT_ASSERT_NOT_ERR_OR_NULL(test, crtc_state);
> +
> +	crtc_state->active = false;
> +
> +	ret = drm_atomic_set_mode_for_crtc(crtc_state, NULL);
> +	KUNIT_ASSERT_EQ(test, ret, 0);
> +
> +	output = container_of(encoder, struct vc4_dummy_output, encoder.base);
> +	conn = &output->connector;
> +	conn_state = drm_atomic_get_connector_state(state, conn);
> +	KUNIT_ASSERT_NOT_ERR_OR_NULL(test, conn_state);
> +
> +	ret = drm_atomic_set_crtc_for_connector(conn_state, NULL);
> +	KUNIT_ASSERT_EQ(test, ret, 0);
> +
> +	return 0;
> +}
> diff --git a/drivers/gpu/drm/vc4/tests/vc4_test_pv_muxing.c b/drivers/gpu/drm/vc4/tests/vc4_test_pv_muxing.c
> new file mode 100644
> index 000000000000..ae0bd0f81698
> --- /dev/null
> +++ b/drivers/gpu/drm/vc4/tests/vc4_test_pv_muxing.c
> @@ -0,0 +1,1039 @@
> +// SPDX-License-Identifier: GPL-2.0
> +
> +#include <drm/drm_atomic.h>
> +#include <drm/drm_atomic_helper.h>
> +#include <drm/drm_atomic_state_helper.h>
> +#include <drm/drm_atomic_uapi.h>
> +#include <drm/drm_crtc.h>
> +#include <drm/drm_drv.h>
> +#include <drm/drm_fourcc.h>
> +#include <drm/drm_kunit_helpers.h>
> +#include <drm/drm_mode.h>
> +#include <drm/drm_modeset_helper_vtables.h>
> +#include <drm/drm_plane.h>
> +
> +#include <kunit/test.h>
> +
> +#include "../vc4_drv.h"
> +
> +#include "vc4_mock.h"
> +
> +struct pv_muxing_priv {
> +	struct vc4_dev *vc4;
> +	struct drm_modeset_acquire_ctx ctx;
> +	struct drm_atomic_state *state;
> +};
> +
> +static bool check_fifo_conflict(struct kunit *test,
> +				const struct drm_atomic_state *state)
> +{
> +	struct vc4_hvs_state *hvs_state;
> +	unsigned int used_fifos = 0;
> +	unsigned int i;
> +
> +	hvs_state = vc4_hvs_get_new_global_state(state);
> +	KUNIT_ASSERT_NOT_ERR_OR_NULL(test, hvs_state);
> +
> +	for (i = 0; i < HVS_NUM_CHANNELS; i++) {
> +		if (!hvs_state->fifo_state[i].in_use)
> +			continue;
> +
> +		KUNIT_EXPECT_FALSE(test, used_fifos & BIT(i));
> +		used_fifos |= BIT(i);
> +	}
> +
> +	return true;
> +}
> +
> +struct encoder_constraint {
> +	enum vc4_encoder_type type;
> +	unsigned int *channels;
> +	size_t nchannels;
> +};
> +
> +#define ENCODER_CONSTRAINT(_type, ...)					\
> +	{								\
> +		.type = _type,						\
> +		.channels = (unsigned int[]) { __VA_ARGS__ },		\
> +		.nchannels = sizeof((unsigned int[]) { __VA_ARGS__ }) /	\
> +			     sizeof(unsigned int),			\
> +	}
> +
> +static bool __check_encoder_constraints(const struct encoder_constraint *constraints,
> +					size_t nconstraints,
> +					enum vc4_encoder_type type,
> +					unsigned int channel)
> +{
> +	unsigned int i;
> +
> +	for (i = 0; i < nconstraints; i++) {
> +		const struct encoder_constraint *constraint = &constraints[i];
> +		unsigned int j;
> +
> +		if (constraint->type != type)
> +			continue;
> +
> +		for (j = 0; j < constraint->nchannels; j++) {
> +			unsigned int _channel = constraint->channels[j];
> +
> +			if (channel != _channel)
> +				continue;
> +
> +			return true;
> +		}
> +	}
> +
> +	return false;
> +}
> +
> +static const struct encoder_constraint vc4_encoder_constraints[] = {
> +	ENCODER_CONSTRAINT(VC4_ENCODER_TYPE_DPI, 0),
> +	ENCODER_CONSTRAINT(VC4_ENCODER_TYPE_DSI0, 0),
> +	ENCODER_CONSTRAINT(VC4_ENCODER_TYPE_HDMI0, 1),
> +	ENCODER_CONSTRAINT(VC4_ENCODER_TYPE_VEC, 1),
> +	ENCODER_CONSTRAINT(VC4_ENCODER_TYPE_TXP, 2),
> +	ENCODER_CONSTRAINT(VC4_ENCODER_TYPE_DSI1, 2),
> +};
> +
> +static const struct encoder_constraint vc5_encoder_constraints[] = {
> +	ENCODER_CONSTRAINT(VC4_ENCODER_TYPE_DPI, 0),
> +	ENCODER_CONSTRAINT(VC4_ENCODER_TYPE_DSI0, 0),
> +	ENCODER_CONSTRAINT(VC4_ENCODER_TYPE_VEC, 1),
> +	ENCODER_CONSTRAINT(VC4_ENCODER_TYPE_TXP, 0, 2),
> +	ENCODER_CONSTRAINT(VC4_ENCODER_TYPE_DSI1, 0, 1, 2),
> +	ENCODER_CONSTRAINT(VC4_ENCODER_TYPE_HDMI0, 0, 1, 2),
> +	ENCODER_CONSTRAINT(VC4_ENCODER_TYPE_HDMI1, 0, 1, 2),
> +};
> +
> +static bool check_vc4_encoder_constraints(enum vc4_encoder_type type, unsigned int channel)
> +{
> +	return __check_encoder_constraints(vc4_encoder_constraints,
> +					   ARRAY_SIZE(vc4_encoder_constraints),
> +					   type, channel);
> +}
> +
> +static bool check_vc5_encoder_constraints(enum vc4_encoder_type type, unsigned int channel)
> +{
> +	return __check_encoder_constraints(vc5_encoder_constraints,
> +					   ARRAY_SIZE(vc5_encoder_constraints),
> +					   type, channel);
> +}
> +
> +static struct vc4_crtc_state *
> +get_vc4_crtc_state_for_encoder(struct kunit *test,
> +			       const struct drm_atomic_state *state,
> +			       enum vc4_encoder_type type)
> +{
> +	struct drm_device *drm = state->dev;
> +	struct drm_crtc_state *new_crtc_state;
> +	struct drm_encoder *encoder;
> +	struct drm_crtc *crtc;
> +
> +	encoder = vc4_find_encoder_by_type(drm, type);
> +	KUNIT_ASSERT_NOT_ERR_OR_NULL(test, encoder);
> +
> +	crtc = vc4_find_crtc_for_encoder(test, drm, encoder);
> +	KUNIT_ASSERT_NOT_ERR_OR_NULL(test, crtc);
> +
> +	new_crtc_state = drm_atomic_get_new_crtc_state(state, crtc);
> +	if (!new_crtc_state)
> +		return NULL;
> +
> +	return to_vc4_crtc_state(new_crtc_state);
> +}
> +
> +static bool check_channel_for_encoder(struct kunit *test,
> +				      const struct drm_atomic_state *state,
> +				      enum vc4_encoder_type type,
> +				      bool (*check_fn)(enum vc4_encoder_type type, unsigned int channel))
> +{
> +	struct vc4_crtc_state *new_vc4_crtc_state;
> +	struct vc4_hvs_state *new_hvs_state;
> +	unsigned int channel;
> +
> +	new_hvs_state = vc4_hvs_get_new_global_state(state);
> +	KUNIT_ASSERT_NOT_ERR_OR_NULL(test, new_hvs_state);
> +
> +	new_vc4_crtc_state = get_vc4_crtc_state_for_encoder(test, state, type);
> +	KUNIT_ASSERT_NOT_NULL(test, new_vc4_crtc_state);
> +
> +	channel = new_vc4_crtc_state->assigned_channel;
> +	KUNIT_EXPECT_NE(test, channel, VC4_HVS_CHANNEL_DISABLED);
> +
> +	KUNIT_EXPECT_TRUE(test, new_hvs_state->fifo_state[channel].in_use);
> +
> +	KUNIT_EXPECT_TRUE(test, check_fn(type, channel));
> +
> +	return true;
> +}
> +
> +struct pv_muxing_param {
> +	const char *name;
> +	struct vc4_dev *(*mock_fn)(struct kunit *test);
> +	bool (*check_fn)(enum vc4_encoder_type type, unsigned int channel);
> +	enum vc4_encoder_type *encoders;
> +	size_t nencoders;
> +};
> +
> +static void vc4_test_pv_muxing_desc(const struct pv_muxing_param *t, char *desc)
> +{
> +	strscpy(desc, t->name, KUNIT_PARAM_DESC_SIZE);
> +}
> +
> +#define PV_MUXING_TEST(_name, _mock_fn, _check_fn, ...)					\
> +	{										\
> +		.name = _name,								\
> +		.mock_fn = &_mock_fn,							\
> +		.check_fn = &_check_fn,							\
> +		.encoders = (enum vc4_encoder_type[]) { __VA_ARGS__ },			\
> +		.nencoders = sizeof((enum vc4_encoder_type[]) { __VA_ARGS__ }) /	\
> +			     sizeof(enum vc4_encoder_type),				\
> +	}
> +
> +#define VC4_PV_MUXING_TEST(_name, ...)		\
> +	PV_MUXING_TEST(_name, vc4_mock_device, check_vc4_encoder_constraints, __VA_ARGS__)
> +
> +#define VC5_PV_MUXING_TEST(_name, ...)		\
> +	PV_MUXING_TEST(_name, vc5_mock_device, check_vc5_encoder_constraints, __VA_ARGS__)
> +
> +static const struct pv_muxing_param vc4_test_pv_muxing_params[] = {
> +	VC4_PV_MUXING_TEST("1 output: DSI0",
> +			   VC4_ENCODER_TYPE_DSI0),
> +	VC4_PV_MUXING_TEST("1 output: DPI",
> +			   VC4_ENCODER_TYPE_DPI),
> +	VC4_PV_MUXING_TEST("1 output: HDMI0",
> +			   VC4_ENCODER_TYPE_HDMI0),
> +	VC4_PV_MUXING_TEST("1 output: VEC",
> +			   VC4_ENCODER_TYPE_VEC),
> +	VC4_PV_MUXING_TEST("1 output: DSI1",
> +			   VC4_ENCODER_TYPE_DSI1),
> +	VC4_PV_MUXING_TEST("1 output: TXP",
> +			   VC4_ENCODER_TYPE_TXP),
> +	VC4_PV_MUXING_TEST("2 outputs: DSI0, HDMI0",
> +			   VC4_ENCODER_TYPE_DSI0,
> +			   VC4_ENCODER_TYPE_HDMI0),
> +	VC4_PV_MUXING_TEST("2 outputs: DSI0, VEC",
> +			   VC4_ENCODER_TYPE_DSI0,
> +			   VC4_ENCODER_TYPE_VEC),
> +	VC4_PV_MUXING_TEST("2 outputs: DSI0, DSI1",
> +			   VC4_ENCODER_TYPE_DSI0,
> +			   VC4_ENCODER_TYPE_DSI1),
> +	VC4_PV_MUXING_TEST("2 outputs: DSI0, TXP",
> +			   VC4_ENCODER_TYPE_DSI0,
> +			   VC4_ENCODER_TYPE_TXP),
> +	VC4_PV_MUXING_TEST("2 outputs: DPI, HDMI0",
> +			   VC4_ENCODER_TYPE_DPI,
> +			   VC4_ENCODER_TYPE_HDMI0),
> +	VC4_PV_MUXING_TEST("2 outputs: DPI, VEC",
> +			   VC4_ENCODER_TYPE_DPI,
> +			   VC4_ENCODER_TYPE_VEC),
> +	VC4_PV_MUXING_TEST("2 outputs: DPI, DSI1",
> +			   VC4_ENCODER_TYPE_DPI,
> +			   VC4_ENCODER_TYPE_DSI1),
> +	VC4_PV_MUXING_TEST("2 outputs: DPI, TXP",
> +			   VC4_ENCODER_TYPE_DPI,
> +			   VC4_ENCODER_TYPE_TXP),
> +	VC4_PV_MUXING_TEST("2 outputs: HDMI0, DSI1",
> +			   VC4_ENCODER_TYPE_HDMI0,
> +			   VC4_ENCODER_TYPE_DSI1),
> +	VC4_PV_MUXING_TEST("2 outputs: HDMI0, TXP",
> +			   VC4_ENCODER_TYPE_HDMI0,
> +			   VC4_ENCODER_TYPE_TXP),
> +	VC4_PV_MUXING_TEST("2 outputs: VEC, DSI1",
> +			   VC4_ENCODER_TYPE_VEC,
> +			   VC4_ENCODER_TYPE_DSI1),
> +	VC4_PV_MUXING_TEST("2 outputs: VEC, TXP",
> +			   VC4_ENCODER_TYPE_VEC,
> +			   VC4_ENCODER_TYPE_TXP),
> +	VC4_PV_MUXING_TEST("3 outputs: DSI0, HDMI0, DSI1",
> +			   VC4_ENCODER_TYPE_DSI0,
> +			   VC4_ENCODER_TYPE_HDMI0,
> +			   VC4_ENCODER_TYPE_DSI1),
> +	VC4_PV_MUXING_TEST("3 outputs: DSI0, HDMI0, TXP",
> +			   VC4_ENCODER_TYPE_DSI0,
> +			   VC4_ENCODER_TYPE_HDMI0,
> +			   VC4_ENCODER_TYPE_TXP),
> +	VC4_PV_MUXING_TEST("3 outputs: DSI0, VEC, DSI1",
> +			   VC4_ENCODER_TYPE_DSI0,
> +			   VC4_ENCODER_TYPE_VEC,
> +			   VC4_ENCODER_TYPE_DSI1),
> +	VC4_PV_MUXING_TEST("3 outputs: DSI0, VEC, TXP",
> +			   VC4_ENCODER_TYPE_DSI0,
> +			   VC4_ENCODER_TYPE_VEC,
> +			   VC4_ENCODER_TYPE_TXP),
> +	VC4_PV_MUXING_TEST("3 outputs: DPI, HDMI0, DSI1",
> +			   VC4_ENCODER_TYPE_DPI,
> +			   VC4_ENCODER_TYPE_HDMI0,
> +			   VC4_ENCODER_TYPE_DSI1),
> +	VC4_PV_MUXING_TEST("3 outputs: DPI, HDMI0, TXP",
> +			   VC4_ENCODER_TYPE_DPI,
> +			   VC4_ENCODER_TYPE_HDMI0,
> +			   VC4_ENCODER_TYPE_TXP),
> +	VC4_PV_MUXING_TEST("3 outputs: DPI, VEC, DSI1",
> +			   VC4_ENCODER_TYPE_DPI,
> +			   VC4_ENCODER_TYPE_VEC,
> +			   VC4_ENCODER_TYPE_DSI1),
> +	VC4_PV_MUXING_TEST("3 outputs: DPI, VEC, TXP",
> +			   VC4_ENCODER_TYPE_DPI,
> +			   VC4_ENCODER_TYPE_VEC,
> +			   VC4_ENCODER_TYPE_TXP),
> +};
> +
> +KUNIT_ARRAY_PARAM(vc4_test_pv_muxing,
> +		  vc4_test_pv_muxing_params,
> +		  vc4_test_pv_muxing_desc);
> +
> +static const struct pv_muxing_param vc4_test_pv_muxing_invalid_params[] = {
> +	VC4_PV_MUXING_TEST("DPI/DSI0 Conflict",
> +			   VC4_ENCODER_TYPE_DPI,
> +			   VC4_ENCODER_TYPE_DSI0),
> +	VC4_PV_MUXING_TEST("TXP/DSI1 Conflict",
> +			   VC4_ENCODER_TYPE_TXP,
> +			   VC4_ENCODER_TYPE_DSI1),
> +	VC4_PV_MUXING_TEST("HDMI0/VEC Conflict",
> +			   VC4_ENCODER_TYPE_HDMI0,
> +			   VC4_ENCODER_TYPE_VEC),
> +	VC4_PV_MUXING_TEST("More than 3 outputs: DSI0, HDMI0, DSI1, TXP",
> +			   VC4_ENCODER_TYPE_DSI0,
> +			   VC4_ENCODER_TYPE_HDMI0,
> +			   VC4_ENCODER_TYPE_DSI1,
> +			   VC4_ENCODER_TYPE_TXP),
> +	VC4_PV_MUXING_TEST("More than 3 outputs: DSI0, VEC, DSI1, TXP",
> +			   VC4_ENCODER_TYPE_DSI0,
> +			   VC4_ENCODER_TYPE_VEC,
> +			   VC4_ENCODER_TYPE_DSI1,
> +			   VC4_ENCODER_TYPE_TXP),
> +	VC4_PV_MUXING_TEST("More than 3 outputs: DPI, HDMI0, DSI1, TXP",
> +			   VC4_ENCODER_TYPE_DPI,
> +			   VC4_ENCODER_TYPE_HDMI0,
> +			   VC4_ENCODER_TYPE_DSI1,
> +			   VC4_ENCODER_TYPE_TXP),
> +	VC4_PV_MUXING_TEST("More than 3 outputs: DPI, VEC, DSI1, TXP",
> +			   VC4_ENCODER_TYPE_DPI,
> +			   VC4_ENCODER_TYPE_VEC,
> +			   VC4_ENCODER_TYPE_DSI1,
> +			   VC4_ENCODER_TYPE_TXP),
> +};
> +
> +KUNIT_ARRAY_PARAM(vc4_test_pv_muxing_invalid,
> +		  vc4_test_pv_muxing_invalid_params,
> +		  vc4_test_pv_muxing_desc);
> +
> +static const struct pv_muxing_param vc5_test_pv_muxing_params[] = {
> +	VC5_PV_MUXING_TEST("1 output: DPI",
> +			   VC4_ENCODER_TYPE_DPI),
> +	VC5_PV_MUXING_TEST("1 output: DSI0",
> +			   VC4_ENCODER_TYPE_DSI0),
> +	VC5_PV_MUXING_TEST("1 output: DSI1",
> +			   VC4_ENCODER_TYPE_DSI1),
> +	VC5_PV_MUXING_TEST("1 output: HDMI0",
> +			   VC4_ENCODER_TYPE_HDMI0),
> +	VC5_PV_MUXING_TEST("1 output: HDMI1",
> +			   VC4_ENCODER_TYPE_HDMI1),
> +	VC5_PV_MUXING_TEST("1 output: VEC",
> +			   VC4_ENCODER_TYPE_VEC),
> +	VC5_PV_MUXING_TEST("2 outputs: DPI, DSI1",
> +			   VC4_ENCODER_TYPE_DPI,
> +			   VC4_ENCODER_TYPE_DSI1),
> +	VC5_PV_MUXING_TEST("2 outputs: DPI, HDMI0",
> +			   VC4_ENCODER_TYPE_DPI,
> +			   VC4_ENCODER_TYPE_HDMI0),
> +	VC5_PV_MUXING_TEST("2 outputs: DPI, HDMI1",
> +			   VC4_ENCODER_TYPE_DPI,
> +			   VC4_ENCODER_TYPE_HDMI1),
> +	VC5_PV_MUXING_TEST("2 outputs: DPI, TXP",
> +			   VC4_ENCODER_TYPE_DPI,
> +			   VC4_ENCODER_TYPE_TXP),
> +	VC5_PV_MUXING_TEST("2 outputs: DPI, VEC",
> +			   VC4_ENCODER_TYPE_DPI,
> +			   VC4_ENCODER_TYPE_VEC),
> +	VC5_PV_MUXING_TEST("2 outputs: DPI, DSI1",
> +			   VC4_ENCODER_TYPE_DPI,
> +			   VC4_ENCODER_TYPE_DSI1),
> +	VC5_PV_MUXING_TEST("2 outputs: DSI0, DSI1",
> +			   VC4_ENCODER_TYPE_DSI0,
> +			   VC4_ENCODER_TYPE_DSI1),
> +	VC5_PV_MUXING_TEST("2 outputs: DSI0, HDMI0",
> +			   VC4_ENCODER_TYPE_DSI0,
> +			   VC4_ENCODER_TYPE_HDMI0),
> +	VC5_PV_MUXING_TEST("2 outputs: DSI0, HDMI1",
> +			   VC4_ENCODER_TYPE_DSI0,
> +			   VC4_ENCODER_TYPE_HDMI1),
> +	VC5_PV_MUXING_TEST("2 outputs: DSI0, TXP",
> +			   VC4_ENCODER_TYPE_DSI0,
> +			   VC4_ENCODER_TYPE_TXP),
> +	VC5_PV_MUXING_TEST("2 outputs: DSI0, VEC",
> +			   VC4_ENCODER_TYPE_DSI0,
> +			   VC4_ENCODER_TYPE_VEC),
> +	VC5_PV_MUXING_TEST("2 outputs: DSI0, DSI1",
> +			   VC4_ENCODER_TYPE_DSI0,
> +			   VC4_ENCODER_TYPE_DSI1),
> +	VC5_PV_MUXING_TEST("2 outputs: DSI1, VEC",
> +			   VC4_ENCODER_TYPE_DSI1,
> +			   VC4_ENCODER_TYPE_VEC),
> +	VC5_PV_MUXING_TEST("2 outputs: DSI1, TXP",
> +			   VC4_ENCODER_TYPE_DSI1,
> +			   VC4_ENCODER_TYPE_TXP),
> +	VC5_PV_MUXING_TEST("2 outputs: DSI1, HDMI0",
> +			   VC4_ENCODER_TYPE_DSI1,
> +			   VC4_ENCODER_TYPE_HDMI0),
> +	VC5_PV_MUXING_TEST("2 outputs: DSI1, HDMI1",
> +			   VC4_ENCODER_TYPE_DSI1,
> +			   VC4_ENCODER_TYPE_HDMI1),
> +	VC5_PV_MUXING_TEST("2 outputs: HDMI0, VEC",
> +			   VC4_ENCODER_TYPE_HDMI0,
> +			   VC4_ENCODER_TYPE_VEC),
> +	VC5_PV_MUXING_TEST("2 outputs: HDMI0, TXP",
> +			   VC4_ENCODER_TYPE_HDMI0,
> +			   VC4_ENCODER_TYPE_TXP),
> +	VC5_PV_MUXING_TEST("2 outputs: HDMI0, HDMI1",
> +			   VC4_ENCODER_TYPE_HDMI0,
> +			   VC4_ENCODER_TYPE_HDMI1),
> +	VC5_PV_MUXING_TEST("2 outputs: HDMI1, VEC",
> +			   VC4_ENCODER_TYPE_HDMI1,
> +			   VC4_ENCODER_TYPE_VEC),
> +	VC5_PV_MUXING_TEST("2 outputs: HDMI1, TXP",
> +			   VC4_ENCODER_TYPE_HDMI1,
> +			   VC4_ENCODER_TYPE_TXP),
> +	VC5_PV_MUXING_TEST("2 outputs: TXP, VEC",
> +			   VC4_ENCODER_TYPE_TXP,
> +			   VC4_ENCODER_TYPE_VEC),
> +	VC5_PV_MUXING_TEST("3 outputs: DPI, VEC, TXP",
> +			   VC4_ENCODER_TYPE_DPI,
> +			   VC4_ENCODER_TYPE_VEC,
> +			   VC4_ENCODER_TYPE_TXP),
> +	VC5_PV_MUXING_TEST("3 outputs: DPI, VEC, DSI1",
> +			   VC4_ENCODER_TYPE_DPI,
> +			   VC4_ENCODER_TYPE_VEC,
> +			   VC4_ENCODER_TYPE_DSI1),
> +	VC5_PV_MUXING_TEST("3 outputs: DPI, VEC, HDMI0",
> +			   VC4_ENCODER_TYPE_DPI,
> +			   VC4_ENCODER_TYPE_VEC,
> +			   VC4_ENCODER_TYPE_HDMI0),
> +	VC5_PV_MUXING_TEST("3 outputs: DPI, VEC, HDMI1",
> +			   VC4_ENCODER_TYPE_DPI,
> +			   VC4_ENCODER_TYPE_VEC,
> +			   VC4_ENCODER_TYPE_HDMI1),
> +	VC5_PV_MUXING_TEST("3 outputs: DPI, TXP, DSI1",
> +			   VC4_ENCODER_TYPE_DPI,
> +			   VC4_ENCODER_TYPE_TXP,
> +			   VC4_ENCODER_TYPE_DSI1),
> +	VC5_PV_MUXING_TEST("3 outputs: DPI, TXP, HDMI0",
> +			   VC4_ENCODER_TYPE_DPI,
> +			   VC4_ENCODER_TYPE_TXP,
> +			   VC4_ENCODER_TYPE_HDMI0),
> +	VC5_PV_MUXING_TEST("3 outputs: DPI, TXP, HDMI1",
> +			   VC4_ENCODER_TYPE_DPI,
> +			   VC4_ENCODER_TYPE_TXP,
> +			   VC4_ENCODER_TYPE_HDMI1),
> +	VC5_PV_MUXING_TEST("3 outputs: DPI, DSI1, HDMI0",
> +			   VC4_ENCODER_TYPE_DPI,
> +			   VC4_ENCODER_TYPE_DSI1,
> +			   VC4_ENCODER_TYPE_HDMI0),
> +	VC5_PV_MUXING_TEST("3 outputs: DPI, DSI1, HDMI1",
> +			   VC4_ENCODER_TYPE_DPI,
> +			   VC4_ENCODER_TYPE_DSI1,
> +			   VC4_ENCODER_TYPE_HDMI1),
> +	VC5_PV_MUXING_TEST("3 outputs: DPI, HDMI0, HDMI1",
> +			   VC4_ENCODER_TYPE_DPI,
> +			   VC4_ENCODER_TYPE_HDMI0,
> +			   VC4_ENCODER_TYPE_HDMI1),
> +	VC5_PV_MUXING_TEST("3 outputs: DSI0, VEC, TXP",
> +			   VC4_ENCODER_TYPE_DSI0,
> +			   VC4_ENCODER_TYPE_VEC,
> +			   VC4_ENCODER_TYPE_TXP),
> +	VC5_PV_MUXING_TEST("3 outputs: DSI0, VEC, DSI1",
> +			   VC4_ENCODER_TYPE_DSI0,
> +			   VC4_ENCODER_TYPE_VEC,
> +			   VC4_ENCODER_TYPE_DSI1),
> +	VC5_PV_MUXING_TEST("3 outputs: DSI0, VEC, HDMI0",
> +			   VC4_ENCODER_TYPE_DSI0,
> +			   VC4_ENCODER_TYPE_VEC,
> +			   VC4_ENCODER_TYPE_HDMI0),
> +	VC5_PV_MUXING_TEST("3 outputs: DSI0, VEC, HDMI1",
> +			   VC4_ENCODER_TYPE_DSI0,
> +			   VC4_ENCODER_TYPE_VEC,
> +			   VC4_ENCODER_TYPE_HDMI1),
> +	VC5_PV_MUXING_TEST("3 outputs: DSI0, TXP, DSI1",
> +			   VC4_ENCODER_TYPE_DSI0,
> +			   VC4_ENCODER_TYPE_TXP,
> +			   VC4_ENCODER_TYPE_DSI1),
> +	VC5_PV_MUXING_TEST("3 outputs: DSI0, TXP, HDMI0",
> +			   VC4_ENCODER_TYPE_DSI0,
> +			   VC4_ENCODER_TYPE_TXP,
> +			   VC4_ENCODER_TYPE_HDMI0),
> +	VC5_PV_MUXING_TEST("3 outputs: DSI0, TXP, HDMI1",
> +			   VC4_ENCODER_TYPE_DSI0,
> +			   VC4_ENCODER_TYPE_TXP,
> +			   VC4_ENCODER_TYPE_HDMI1),
> +	VC5_PV_MUXING_TEST("3 outputs: DSI0, DSI1, HDMI0",
> +			   VC4_ENCODER_TYPE_DSI0,
> +			   VC4_ENCODER_TYPE_DSI1,
> +			   VC4_ENCODER_TYPE_HDMI0),
> +	VC5_PV_MUXING_TEST("3 outputs: DSI0, DSI1, HDMI1",
> +			   VC4_ENCODER_TYPE_DSI0,
> +			   VC4_ENCODER_TYPE_DSI1,
> +			   VC4_ENCODER_TYPE_HDMI1),
> +	VC5_PV_MUXING_TEST("3 outputs: DSI0, HDMI0, HDMI1",
> +			   VC4_ENCODER_TYPE_DSI0,
> +			   VC4_ENCODER_TYPE_HDMI0,
> +			   VC4_ENCODER_TYPE_HDMI1),
> +};
> +
> +KUNIT_ARRAY_PARAM(vc5_test_pv_muxing,
> +		  vc5_test_pv_muxing_params,
> +		  vc4_test_pv_muxing_desc);
> +
> +static const struct pv_muxing_param vc5_test_pv_muxing_invalid_params[] = {
> +	VC5_PV_MUXING_TEST("DPI/DSI0 Conflict",
> +			   VC4_ENCODER_TYPE_DPI,
> +			   VC4_ENCODER_TYPE_DSI0),
> +	VC5_PV_MUXING_TEST("More than 3 outputs: DPI, VEC, TXP, DSI1",
> +			   VC4_ENCODER_TYPE_DPI,
> +			   VC4_ENCODER_TYPE_VEC,
> +			   VC4_ENCODER_TYPE_TXP,
> +			   VC4_ENCODER_TYPE_DSI1),
> +	VC5_PV_MUXING_TEST("More than 3 outputs: DPI, VEC, TXP, HDMI0",
> +			   VC4_ENCODER_TYPE_DPI,
> +			   VC4_ENCODER_TYPE_VEC,
> +			   VC4_ENCODER_TYPE_TXP,
> +			   VC4_ENCODER_TYPE_HDMI0),
> +	VC5_PV_MUXING_TEST("More than 3 outputs: DPI, VEC, TXP, HDMI1",
> +			   VC4_ENCODER_TYPE_DPI,
> +			   VC4_ENCODER_TYPE_VEC,
> +			   VC4_ENCODER_TYPE_TXP,
> +			   VC4_ENCODER_TYPE_HDMI1),
> +	VC5_PV_MUXING_TEST("More than 3 outputs: DPI, VEC, DSI1, HDMI0",
> +			   VC4_ENCODER_TYPE_DPI,
> +			   VC4_ENCODER_TYPE_VEC,
> +			   VC4_ENCODER_TYPE_DSI1,
> +			   VC4_ENCODER_TYPE_HDMI0),
> +	VC5_PV_MUXING_TEST("More than 3 outputs: DPI, VEC, DSI1, HDMI1",
> +			   VC4_ENCODER_TYPE_DPI,
> +			   VC4_ENCODER_TYPE_VEC,
> +			   VC4_ENCODER_TYPE_DSI1,
> +			   VC4_ENCODER_TYPE_HDMI1),
> +	VC5_PV_MUXING_TEST("More than 3 outputs: DPI, VEC, HDMI0, HDMI1",
> +			   VC4_ENCODER_TYPE_DPI,
> +			   VC4_ENCODER_TYPE_VEC,
> +			   VC4_ENCODER_TYPE_HDMI0,
> +			   VC4_ENCODER_TYPE_HDMI1),
> +	VC5_PV_MUXING_TEST("More than 3 outputs: DPI, TXP, DSI1, HDMI0",
> +			   VC4_ENCODER_TYPE_DPI,
> +			   VC4_ENCODER_TYPE_TXP,
> +			   VC4_ENCODER_TYPE_DSI1,
> +			   VC4_ENCODER_TYPE_HDMI0),
> +	VC5_PV_MUXING_TEST("More than 3 outputs: DPI, TXP, DSI1, HDMI1",
> +			   VC4_ENCODER_TYPE_DPI,
> +			   VC4_ENCODER_TYPE_TXP,
> +			   VC4_ENCODER_TYPE_DSI1,
> +			   VC4_ENCODER_TYPE_HDMI1),
> +	VC5_PV_MUXING_TEST("More than 3 outputs: DPI, TXP, HDMI0, HDMI1",
> +			   VC4_ENCODER_TYPE_DPI,
> +			   VC4_ENCODER_TYPE_TXP,
> +			   VC4_ENCODER_TYPE_HDMI0,
> +			   VC4_ENCODER_TYPE_HDMI1),
> +	VC5_PV_MUXING_TEST("More than 3 outputs: DPI, DSI1, HDMI0, HDMI1",
> +			   VC4_ENCODER_TYPE_DPI,
> +			   VC4_ENCODER_TYPE_DSI1,
> +			   VC4_ENCODER_TYPE_HDMI0,
> +			   VC4_ENCODER_TYPE_HDMI1),
> +	VC5_PV_MUXING_TEST("More than 3 outputs: DPI, VEC, TXP, DSI1, HDMI0",
> +			   VC4_ENCODER_TYPE_DPI,
> +			   VC4_ENCODER_TYPE_VEC,
> +			   VC4_ENCODER_TYPE_TXP,
> +			   VC4_ENCODER_TYPE_DSI1,
> +			   VC4_ENCODER_TYPE_HDMI0),
> +	VC5_PV_MUXING_TEST("More than 3 outputs: DPI, VEC, TXP, DSI1, HDMI1",
> +			   VC4_ENCODER_TYPE_DPI,
> +			   VC4_ENCODER_TYPE_VEC,
> +			   VC4_ENCODER_TYPE_TXP,
> +			   VC4_ENCODER_TYPE_DSI1,
> +			   VC4_ENCODER_TYPE_HDMI1),
> +	VC5_PV_MUXING_TEST("More than 3 outputs: DPI, VEC, TXP, HDMI0, HDMI1",
> +			   VC4_ENCODER_TYPE_DPI,
> +			   VC4_ENCODER_TYPE_VEC,
> +			   VC4_ENCODER_TYPE_TXP,
> +			   VC4_ENCODER_TYPE_HDMI0,
> +			   VC4_ENCODER_TYPE_HDMI1),
> +	VC5_PV_MUXING_TEST("More than 3 outputs: DPI, VEC, DSI1, HDMI0, HDMI1",
> +			   VC4_ENCODER_TYPE_DPI,
> +			   VC4_ENCODER_TYPE_VEC,
> +			   VC4_ENCODER_TYPE_DSI1,
> +			   VC4_ENCODER_TYPE_HDMI0,
> +			   VC4_ENCODER_TYPE_HDMI1),
> +	VC5_PV_MUXING_TEST("More than 3 outputs: DPI, TXP, DSI1, HDMI0, HDMI1",
> +			   VC4_ENCODER_TYPE_DPI,
> +			   VC4_ENCODER_TYPE_TXP,
> +			   VC4_ENCODER_TYPE_DSI1,
> +			   VC4_ENCODER_TYPE_HDMI0,
> +			   VC4_ENCODER_TYPE_HDMI1),
> +	VC5_PV_MUXING_TEST("More than 3 outputs: DSI0, VEC, TXP, DSI1",
> +			   VC4_ENCODER_TYPE_DSI0,
> +			   VC4_ENCODER_TYPE_VEC,
> +			   VC4_ENCODER_TYPE_TXP,
> +			   VC4_ENCODER_TYPE_DSI1),
> +	VC5_PV_MUXING_TEST("More than 3 outputs: DSI0, VEC, TXP, HDMI0",
> +			   VC4_ENCODER_TYPE_DSI0,
> +			   VC4_ENCODER_TYPE_VEC,
> +			   VC4_ENCODER_TYPE_TXP,
> +			   VC4_ENCODER_TYPE_HDMI0),
> +	VC5_PV_MUXING_TEST("More than 3 outputs: DSI0, VEC, TXP, HDMI1",
> +			   VC4_ENCODER_TYPE_DSI0,
> +			   VC4_ENCODER_TYPE_VEC,
> +			   VC4_ENCODER_TYPE_TXP,
> +			   VC4_ENCODER_TYPE_HDMI1),
> +	VC5_PV_MUXING_TEST("More than 3 outputs: DSI0, VEC, DSI1, HDMI0",
> +			   VC4_ENCODER_TYPE_DSI0,
> +			   VC4_ENCODER_TYPE_VEC,
> +			   VC4_ENCODER_TYPE_DSI1,
> +			   VC4_ENCODER_TYPE_HDMI0),
> +	VC5_PV_MUXING_TEST("More than 3 outputs: DSI0, VEC, DSI1, HDMI1",
> +			   VC4_ENCODER_TYPE_DSI0,
> +			   VC4_ENCODER_TYPE_VEC,
> +			   VC4_ENCODER_TYPE_DSI1,
> +			   VC4_ENCODER_TYPE_HDMI1),
> +	VC5_PV_MUXING_TEST("More than 3 outputs: DSI0, VEC, HDMI0, HDMI1",
> +			   VC4_ENCODER_TYPE_DSI0,
> +			   VC4_ENCODER_TYPE_VEC,
> +			   VC4_ENCODER_TYPE_HDMI0,
> +			   VC4_ENCODER_TYPE_HDMI1),
> +	VC5_PV_MUXING_TEST("More than 3 outputs: DSI0, TXP, DSI1, HDMI0",
> +			   VC4_ENCODER_TYPE_DSI0,
> +			   VC4_ENCODER_TYPE_TXP,
> +			   VC4_ENCODER_TYPE_DSI1,
> +			   VC4_ENCODER_TYPE_HDMI0),
> +	VC5_PV_MUXING_TEST("More than 3 outputs: DSI0, TXP, DSI1, HDMI1",
> +			   VC4_ENCODER_TYPE_DSI0,
> +			   VC4_ENCODER_TYPE_TXP,
> +			   VC4_ENCODER_TYPE_DSI1,
> +			   VC4_ENCODER_TYPE_HDMI1),
> +	VC5_PV_MUXING_TEST("More than 3 outputs: DSI0, TXP, HDMI0, HDMI1",
> +			   VC4_ENCODER_TYPE_DSI0,
> +			   VC4_ENCODER_TYPE_TXP,
> +			   VC4_ENCODER_TYPE_HDMI0,
> +			   VC4_ENCODER_TYPE_HDMI1),
> +	VC5_PV_MUXING_TEST("More than 3 outputs: DSI0, DSI1, HDMI0, HDMI1",
> +			   VC4_ENCODER_TYPE_DSI0,
> +			   VC4_ENCODER_TYPE_DSI1,
> +			   VC4_ENCODER_TYPE_HDMI0,
> +			   VC4_ENCODER_TYPE_HDMI1),
> +	VC5_PV_MUXING_TEST("More than 3 outputs: DSI0, VEC, TXP, DSI1, HDMI0",
> +			   VC4_ENCODER_TYPE_DSI0,
> +			   VC4_ENCODER_TYPE_VEC,
> +			   VC4_ENCODER_TYPE_TXP,
> +			   VC4_ENCODER_TYPE_DSI1,
> +			   VC4_ENCODER_TYPE_HDMI0),
> +	VC5_PV_MUXING_TEST("More than 3 outputs: DSI0, VEC, TXP, DSI1, HDMI1",
> +			   VC4_ENCODER_TYPE_DSI0,
> +			   VC4_ENCODER_TYPE_VEC,
> +			   VC4_ENCODER_TYPE_TXP,
> +			   VC4_ENCODER_TYPE_DSI1,
> +			   VC4_ENCODER_TYPE_HDMI1),
> +	VC5_PV_MUXING_TEST("More than 3 outputs: DSI0, VEC, TXP, HDMI0, HDMI1",
> +			   VC4_ENCODER_TYPE_DSI0,
> +			   VC4_ENCODER_TYPE_VEC,
> +			   VC4_ENCODER_TYPE_TXP,
> +			   VC4_ENCODER_TYPE_HDMI0,
> +			   VC4_ENCODER_TYPE_HDMI1),
> +	VC5_PV_MUXING_TEST("More than 3 outputs: DSI0, VEC, DSI1, HDMI0, HDMI1",
> +			   VC4_ENCODER_TYPE_DSI0,
> +			   VC4_ENCODER_TYPE_VEC,
> +			   VC4_ENCODER_TYPE_DSI1,
> +			   VC4_ENCODER_TYPE_HDMI0,
> +			   VC4_ENCODER_TYPE_HDMI1),
> +	VC5_PV_MUXING_TEST("More than 3 outputs: DSI0, TXP, DSI1, HDMI0, HDMI1",
> +			   VC4_ENCODER_TYPE_DSI0,
> +			   VC4_ENCODER_TYPE_TXP,
> +			   VC4_ENCODER_TYPE_DSI1,
> +			   VC4_ENCODER_TYPE_HDMI0,
> +			   VC4_ENCODER_TYPE_HDMI1),
> +	VC5_PV_MUXING_TEST("More than 3 outputs: VEC, TXP, DSI1, HDMI0, HDMI1",
> +			   VC4_ENCODER_TYPE_VEC,
> +			   VC4_ENCODER_TYPE_TXP,
> +			   VC4_ENCODER_TYPE_DSI1,
> +			   VC4_ENCODER_TYPE_HDMI0,
> +			   VC4_ENCODER_TYPE_HDMI1),
> +	VC5_PV_MUXING_TEST("More than 3 outputs: DPI, VEC, TXP, DSI1, HDMI0, HDMI1",
> +			   VC4_ENCODER_TYPE_DPI,
> +			   VC4_ENCODER_TYPE_VEC,
> +			   VC4_ENCODER_TYPE_TXP,
> +			   VC4_ENCODER_TYPE_DSI1,
> +			   VC4_ENCODER_TYPE_HDMI0,
> +			   VC4_ENCODER_TYPE_HDMI1),
> +	VC5_PV_MUXING_TEST("More than 3 outputs: DSI0, VEC, TXP, DSI1, HDMI0, HDMI1",
> +			   VC4_ENCODER_TYPE_DSI0,
> +			   VC4_ENCODER_TYPE_VEC,
> +			   VC4_ENCODER_TYPE_TXP,
> +			   VC4_ENCODER_TYPE_DSI1,
> +			   VC4_ENCODER_TYPE_HDMI0,
> +			   VC4_ENCODER_TYPE_HDMI1),
> +};
> +
> +KUNIT_ARRAY_PARAM(vc5_test_pv_muxing_invalid,
> +		  vc5_test_pv_muxing_invalid_params,
> +		  vc4_test_pv_muxing_desc);
> +
> +static void drm_vc4_test_pv_muxing(struct kunit *test)
> +{
> +	const struct pv_muxing_param *params = test->param_value;
> +	const struct pv_muxing_priv *priv = test->priv;
> +	struct drm_atomic_state *state = priv->state;
> +	unsigned int i;
> +	int ret;
> +
> +	for (i = 0; i < params->nencoders; i++) {
> +		enum vc4_encoder_type enc_type = params->encoders[i];
> +
> +		ret = vc4_mock_atomic_add_output(test, state, enc_type);
> +		KUNIT_ASSERT_EQ(test, ret, 0);
> +	}
> +
> +	ret = drm_atomic_check_only(state);
> +	KUNIT_EXPECT_EQ(test, ret, 0);
> +
> +	KUNIT_EXPECT_TRUE(test,
> +			  check_fifo_conflict(test, state));
> +
> +	for (i = 0; i < params->nencoders; i++) {
> +		enum vc4_encoder_type enc_type = params->encoders[i];
> +
> +		KUNIT_EXPECT_TRUE(test, check_channel_for_encoder(test, state, enc_type,
> +								  params->check_fn));
> +	}
> +}
> +
> +static void drm_vc4_test_pv_muxing_invalid(struct kunit *test)
> +{
> +	const struct pv_muxing_param *params = test->param_value;
> +	const struct pv_muxing_priv *priv = test->priv;
> +	struct drm_atomic_state *state = priv->state;
> +	unsigned int i;
> +	int ret;
> +
> +	for (i = 0; i < params->nencoders; i++) {
> +		enum vc4_encoder_type enc_type = params->encoders[i];
> +
> +		ret = vc4_mock_atomic_add_output(test, state, enc_type);
> +		KUNIT_ASSERT_EQ(test, ret, 0);
> +	}
> +
> +	ret = drm_atomic_check_only(state);
> +	KUNIT_EXPECT_LT(test, ret, 0);
> +}
> +
> +static int vc4_pv_muxing_test_init(struct kunit *test)
> +{
> +	const struct pv_muxing_param *params = test->param_value;
> +	struct drm_atomic_state *state;
> +	struct pv_muxing_priv *priv;
> +	struct drm_device *drm;
> +	struct vc4_dev *vc4;
> +
> +	priv = kunit_kzalloc(test, sizeof(*priv), GFP_KERNEL);
> +	KUNIT_ASSERT_NOT_NULL(test, priv);
> +	test->priv = priv;
> +
> +	vc4 = params->mock_fn(test);
> +	KUNIT_ASSERT_NOT_ERR_OR_NULL(test, vc4);
> +	priv->vc4 = vc4;
> +
> +	drm_modeset_acquire_init(&priv->ctx, 0);
> +
> +	drm = &vc4->base;
> +	state = drm_atomic_state_alloc(drm);
> +	KUNIT_ASSERT_NOT_ERR_OR_NULL(test, state);
> +
> +	state->acquire_ctx = &priv->ctx;
> +
> +	priv->state = state;
> +
> +	return 0;
> +}
> +
> +static void vc4_pv_muxing_test_exit(struct kunit *test)
> +{
> +	struct pv_muxing_priv *priv = test->priv;
> +	struct vc4_dev *vc4 = priv->vc4;
> +	struct drm_device *drm = &vc4->base;
> +	struct drm_atomic_state *state = priv->state;
> +
> +	drm_atomic_state_put(state);
> +	drm_modeset_drop_locks(&priv->ctx);
> +	drm_modeset_acquire_fini(&priv->ctx);
> +	drm_dev_unregister(drm);
> +	drm_kunit_helper_free_device(test, vc4->dev);
> +}
> +
> +static struct kunit_case vc4_pv_muxing_tests[] = {
> +	KUNIT_CASE_PARAM(drm_vc4_test_pv_muxing,
> +			 vc4_test_pv_muxing_gen_params),
> +	KUNIT_CASE_PARAM(drm_vc4_test_pv_muxing_invalid,
> +			 vc4_test_pv_muxing_invalid_gen_params),
> +	{}
> +};
> +
> +static struct kunit_suite vc4_pv_muxing_test_suite = {
> +	.name = "vc4-pv-muxing-combinations",
> +	.init = vc4_pv_muxing_test_init,
> +	.exit = vc4_pv_muxing_test_exit,
> +	.test_cases = vc4_pv_muxing_tests,
> +};
> +
> +static struct kunit_case vc5_pv_muxing_tests[] = {
> +	KUNIT_CASE_PARAM(drm_vc4_test_pv_muxing,
> +			 vc5_test_pv_muxing_gen_params),
> +	KUNIT_CASE_PARAM(drm_vc4_test_pv_muxing_invalid,
> +			 vc5_test_pv_muxing_invalid_gen_params),
> +	{}
> +};
> +
> +static struct kunit_suite vc5_pv_muxing_test_suite = {
> +	.name = "vc5-pv-muxing-combinations",
> +	.init = vc4_pv_muxing_test_init,
> +	.exit = vc4_pv_muxing_test_exit,
> +	.test_cases = vc5_pv_muxing_tests,
> +};
> +
> +/* See
> + * https://lore.kernel.org/all/3e113525-aa89-b1e2-56b7-ca55bd41d057@samsung.com/
> + * and
> + * https://lore.kernel.org/dri-devel/20200917121623.42023-1-maxime@cerno.tech/
> + */
> +static void drm_test_vc5_pv_muxing_bugs_subsequent_crtc_enable(struct kunit *test)
> +{
> +	struct drm_modeset_acquire_ctx ctx;
> +	struct drm_atomic_state *state;
> +	struct vc4_crtc_state *new_vc4_crtc_state;
> +	struct vc4_hvs_state *new_hvs_state;
> +	unsigned int hdmi0_channel;
> +	unsigned int hdmi1_channel;
> +	struct drm_device *drm;
> +	struct vc4_dev *vc4;
> +	int ret;
> +
> +	vc4 = vc5_mock_device(test);
> +	KUNIT_ASSERT_NOT_ERR_OR_NULL(test, vc4);
> +
> +	drm_modeset_acquire_init(&ctx, 0);
> +
> +	drm = &vc4->base;
> +	state = drm_atomic_state_alloc(drm);
> +	KUNIT_ASSERT_NOT_ERR_OR_NULL(test, state);
> +
> +	state->acquire_ctx = &ctx;
> +
> +	ret = vc4_mock_atomic_add_output(test, state, VC4_ENCODER_TYPE_HDMI0);
> +	KUNIT_ASSERT_EQ(test, ret, 0);
> +
> +	ret = drm_atomic_check_only(state);
> +	KUNIT_ASSERT_EQ(test, ret, 0);
> +
> +	new_hvs_state = vc4_hvs_get_new_global_state(state);
> +	KUNIT_ASSERT_NOT_ERR_OR_NULL(test, new_hvs_state);
> +
> +	new_vc4_crtc_state = get_vc4_crtc_state_for_encoder(test, state,
> +							    VC4_ENCODER_TYPE_HDMI0);
> +	KUNIT_ASSERT_NOT_NULL(test, new_vc4_crtc_state);
> +
> +	hdmi0_channel = new_vc4_crtc_state->assigned_channel;
> +	KUNIT_ASSERT_NE(test, hdmi0_channel, VC4_HVS_CHANNEL_DISABLED);
> +	KUNIT_ASSERT_TRUE(test, new_hvs_state->fifo_state[hdmi0_channel].in_use);
> +
> +	ret = drm_atomic_helper_swap_state(state, false);
> +	KUNIT_ASSERT_EQ(test, ret, 0);
> +
> +	drm_atomic_state_put(state);
> +
> +	state = drm_atomic_state_alloc(drm);
> +	KUNIT_ASSERT_NOT_ERR_OR_NULL(test, state);
> +
> +	state->acquire_ctx = &ctx;
> +
> +	ret = vc4_mock_atomic_add_output(test, state, VC4_ENCODER_TYPE_HDMI1);
> +	KUNIT_ASSERT_EQ(test, ret, 0);
> +
> +	ret = drm_atomic_check_only(state);
> +	KUNIT_ASSERT_EQ(test, ret, 0);
> +
> +	new_hvs_state = vc4_hvs_get_new_global_state(state);
> +	KUNIT_ASSERT_NOT_ERR_OR_NULL(test, new_hvs_state);
> +
> +	new_vc4_crtc_state = get_vc4_crtc_state_for_encoder(test, state,
> +							    VC4_ENCODER_TYPE_HDMI1);
> +	KUNIT_ASSERT_NOT_NULL(test, new_vc4_crtc_state);
> +
> +	hdmi1_channel = new_vc4_crtc_state->assigned_channel;
> +	KUNIT_ASSERT_NE(test, hdmi1_channel, VC4_HVS_CHANNEL_DISABLED);
> +	KUNIT_ASSERT_TRUE(test, new_hvs_state->fifo_state[hdmi1_channel].in_use);
> +
> +	KUNIT_EXPECT_NE(test, hdmi0_channel, hdmi1_channel);
> +
> +	drm_atomic_state_put(state);
> +	drm_modeset_drop_locks(&ctx);
> +	drm_modeset_acquire_fini(&ctx);
> +	drm_dev_unregister(drm);
> +	drm_kunit_helper_free_device(test, vc4->dev);
> +}
> +
> +static void drm_test_vc5_pv_muxing_bugs_stable_fifo(struct kunit *test)
> +{
> +	struct drm_modeset_acquire_ctx ctx;
> +	struct drm_atomic_state *state;
> +	struct vc4_crtc_state *new_vc4_crtc_state;
> +	struct vc4_hvs_state *new_hvs_state;
> +	unsigned int old_hdmi0_channel;
> +	unsigned int old_hdmi1_channel;
> +	struct drm_device *drm;
> +	struct vc4_dev *vc4;
> +	int ret;
> +
> +	vc4 = vc5_mock_device(test);
> +	KUNIT_ASSERT_NOT_ERR_OR_NULL(test, vc4);
> +
> +	drm_modeset_acquire_init(&ctx, 0);
> +
> +	drm = &vc4->base;
> +	state = drm_atomic_state_alloc(drm);
> +	KUNIT_ASSERT_NOT_ERR_OR_NULL(test, state);
> +
> +	state->acquire_ctx = &ctx;
> +
> +	ret = vc4_mock_atomic_add_output(test, state, VC4_ENCODER_TYPE_HDMI0);
> +	KUNIT_ASSERT_EQ(test, ret, 0);
> +
> +	ret = vc4_mock_atomic_add_output(test, state, VC4_ENCODER_TYPE_HDMI1);
> +	KUNIT_ASSERT_EQ(test, ret, 0);
> +
> +	ret = drm_atomic_check_only(state);
> +	KUNIT_ASSERT_EQ(test, ret, 0);
> +
> +	new_hvs_state = vc4_hvs_get_new_global_state(state);
> +	KUNIT_ASSERT_NOT_ERR_OR_NULL(test, new_hvs_state);
> +
> +	new_vc4_crtc_state = get_vc4_crtc_state_for_encoder(test, state,
> +							    VC4_ENCODER_TYPE_HDMI0);
> +	KUNIT_ASSERT_NOT_NULL(test, new_vc4_crtc_state);
> +
> +	old_hdmi0_channel = new_vc4_crtc_state->assigned_channel;
> +	KUNIT_ASSERT_NE(test, old_hdmi0_channel, VC4_HVS_CHANNEL_DISABLED);
> +	KUNIT_ASSERT_TRUE(test, new_hvs_state->fifo_state[old_hdmi0_channel].in_use);
> +
> +	new_vc4_crtc_state = get_vc4_crtc_state_for_encoder(test, state,
> +							    VC4_ENCODER_TYPE_HDMI1);
> +	KUNIT_ASSERT_NOT_NULL(test, new_vc4_crtc_state);
> +
> +	old_hdmi1_channel = new_vc4_crtc_state->assigned_channel;
> +	KUNIT_ASSERT_NE(test, old_hdmi1_channel, VC4_HVS_CHANNEL_DISABLED);
> +	KUNIT_ASSERT_TRUE(test, new_hvs_state->fifo_state[old_hdmi1_channel].in_use);
> +
> +	ret = drm_atomic_helper_swap_state(state, false);
> +	KUNIT_ASSERT_EQ(test, ret, 0);
> +
> +	drm_atomic_state_put(state);
> +
> +	state = drm_atomic_state_alloc(drm);
> +	KUNIT_ASSERT_NOT_ERR_OR_NULL(test, state);
> +
> +	state->acquire_ctx = &ctx;
> +
> +	ret = vc4_mock_atomic_del_output(test, state, VC4_ENCODER_TYPE_HDMI0);
> +	KUNIT_ASSERT_EQ(test, ret, 0);
> +
> +	ret = drm_atomic_check_only(state);
> +	KUNIT_ASSERT_EQ(test, ret, 0);
> +
> +	new_hvs_state = vc4_hvs_get_new_global_state(state);
> +	KUNIT_ASSERT_NOT_ERR_OR_NULL(test, new_hvs_state);
> +
> +	new_vc4_crtc_state = get_vc4_crtc_state_for_encoder(test, state,
> +							    VC4_ENCODER_TYPE_HDMI1);
> +
> +	if (new_vc4_crtc_state) {
> +		unsigned int hdmi1_channel;
> +
> +		hdmi1_channel = new_vc4_crtc_state->assigned_channel;
> +		KUNIT_ASSERT_NE(test, hdmi1_channel, VC4_HVS_CHANNEL_DISABLED);
> +		KUNIT_ASSERT_TRUE(test, new_hvs_state->fifo_state[hdmi1_channel].in_use);
> +
> +		KUNIT_EXPECT_EQ(test, old_hdmi1_channel, hdmi1_channel);
> +	}
> +
> +	drm_atomic_state_put(state);
> +	drm_modeset_drop_locks(&ctx);
> +	drm_modeset_acquire_fini(&ctx);
> +	drm_dev_unregister(drm);
> +	drm_kunit_helper_free_device(test, vc4->dev);
> +}
> +
> +static void
> +drm_test_vc5_pv_muxing_bugs_subsequent_crtc_enable_too_many_crtc_state(struct kunit *test)
> +{
> +	struct drm_modeset_acquire_ctx ctx;
> +	struct drm_atomic_state *state;
> +	struct vc4_crtc_state *new_vc4_crtc_state;
> +	struct drm_device *drm;
> +	struct vc4_dev *vc4;
> +	int ret;
> +
> +	vc4 = vc5_mock_device(test);
> +	KUNIT_ASSERT_NOT_ERR_OR_NULL(test, vc4);
> +
> +	drm_modeset_acquire_init(&ctx, 0);
> +
> +	drm = &vc4->base;
> +	state = drm_atomic_state_alloc(drm);
> +	KUNIT_ASSERT_NOT_ERR_OR_NULL(test, state);
> +
> +	state->acquire_ctx = &ctx;
> +
> +	ret = vc4_mock_atomic_add_output(test, state, VC4_ENCODER_TYPE_HDMI0);
> +	KUNIT_ASSERT_EQ(test, ret, 0);
> +
> +	ret = drm_atomic_check_only(state);
> +	KUNIT_ASSERT_EQ(test, ret, 0);
> +
> +	ret = drm_atomic_helper_swap_state(state, false);
> +	KUNIT_ASSERT_EQ(test, ret, 0);
> +
> +	drm_atomic_state_put(state);
> +
> +	state = drm_atomic_state_alloc(drm);
> +	KUNIT_ASSERT_NOT_ERR_OR_NULL(test, state);
> +
> +	state->acquire_ctx = &ctx;
> +
> +	ret = vc4_mock_atomic_add_output(test, state, VC4_ENCODER_TYPE_HDMI1);
> +	KUNIT_ASSERT_EQ(test, ret, 0);
> +
> +	ret = drm_atomic_check_only(state);
> +	KUNIT_ASSERT_EQ(test, ret, 0);
> +
> +	new_vc4_crtc_state = get_vc4_crtc_state_for_encoder(test, state,
> +							    VC4_ENCODER_TYPE_HDMI0);
> +	KUNIT_EXPECT_NULL(test, new_vc4_crtc_state);
> +
> +	drm_atomic_state_put(state);
> +	drm_modeset_drop_locks(&ctx);
> +	drm_modeset_acquire_fini(&ctx);
> +	drm_dev_unregister(drm);
> +	drm_kunit_helper_free_device(test, vc4->dev);
> +}
> +
> +static struct kunit_case vc5_pv_muxing_bugs_tests[] = {
> +	KUNIT_CASE(drm_test_vc5_pv_muxing_bugs_subsequent_crtc_enable),
> +	KUNIT_CASE(drm_test_vc5_pv_muxing_bugs_subsequent_crtc_enable_too_many_crtc_state),
> +	KUNIT_CASE(drm_test_vc5_pv_muxing_bugs_stable_fifo),
> +	{}
> +};
> +
> +static struct kunit_suite vc5_pv_muxing_bugs_test_suite = {
> +	.name = "vc5-pv-muxing-bugs",
> +	.test_cases = vc5_pv_muxing_bugs_tests,
> +};
> +
> +kunit_test_suites(
> +	&vc4_pv_muxing_test_suite,
> +	&vc5_pv_muxing_test_suite,
> +	&vc5_pv_muxing_bugs_test_suite
> +);
> 

^ permalink raw reply	[flat|nested] 7+ messages in thread

* Re: [PATCH v3 18/20] drm/vc4: tests: Fail the current test if we access a register
       [not found] ` <20221123-rpi-kunit-tests-v3-18-4615a663a84a@cerno.tech>
@ 2022-12-07 14:26   ` Maíra Canal
  2022-12-07 16:11     ` Maxime Ripard
  0 siblings, 1 reply; 7+ messages in thread
From: Maíra Canal @ 2022-12-07 14:26 UTC (permalink / raw)
  To: Maxime Ripard, Maxime Ripard, Maarten Lankhorst, Daniel Vetter,
	Thomas Zimmermann, David Airlie
  Cc: David Gow, Dave Stevenson, Greg Kroah-Hartman,
	Javier Martinez Canillas, dri-devel, linux-kernel, linaro-mm-sig,
	Brendan Higgins, linux-kselftest, kunit-dev, Maíra Canal,
	linux-media

On 12/1/22 12:11, Maxime Ripard wrote:
> Accessing a register when running under kunit is a bad idea since our
> device is completely mocked.
> 
> Fail the current test if we ever access any of our hardware registers.
> 
> Reviewed-by: Javier Martinez Canillas <javierm@redhat.com>
> Signed-off-by: Maxime Ripard <maxime@cerno.tech>

Reviewed-by: Maíra Canal <mcanal@igalia.com>

Just a small nit: I believe that macros with multiple statements should 
be enclosed in a do-while block [1], even READ macros. I saw that you 
enclosed the WRITE macros on a do-while block, but not the READ macros.

[1] 
https://www.kernel.org/doc/html/latest/process/coding-style.html#macros-enums-and-rtl

Best Regards,
- Maíra Canal

> ---
>   drivers/gpu/drm/vc4/vc4_crtc.c      | 13 +++++++++++--
>   drivers/gpu/drm/vc4/vc4_dpi.c       | 13 +++++++++++--
>   drivers/gpu/drm/vc4/vc4_drv.h       | 29 +++++++++++++++++++++++++----
>   drivers/gpu/drm/vc4/vc4_dsi.c       |  9 ++++++++-
>   drivers/gpu/drm/vc4/vc4_hdmi_regs.h |  4 ++++
>   drivers/gpu/drm/vc4/vc4_txp.c       | 13 +++++++++++--
>   drivers/gpu/drm/vc4/vc4_vec.c       | 13 +++++++++++--
>   7 files changed, 81 insertions(+), 13 deletions(-)
> 
> diff --git a/drivers/gpu/drm/vc4/vc4_crtc.c b/drivers/gpu/drm/vc4/vc4_crtc.c
> index 7d1a696477ce..a1a3465948c4 100644
> --- a/drivers/gpu/drm/vc4/vc4_crtc.c
> +++ b/drivers/gpu/drm/vc4/vc4_crtc.c
> @@ -50,8 +50,17 @@
>   
>   #define HVS_FIFO_LATENCY_PIX	6
>   
> -#define CRTC_WRITE(offset, val) writel(val, vc4_crtc->regs + (offset))
> -#define CRTC_READ(offset) readl(vc4_crtc->regs + (offset))
> +#define CRTC_WRITE(offset, val)								\
> +	do {										\
> +		kunit_fail_current_test("Accessing a register in a unit test!\n");	\
> +		writel(val, vc4_crtc->regs + (offset));					\
> +	} while (0)
> +
> +#define CRTC_READ(offset)								\
> +	({										\
> +		kunit_fail_current_test("Accessing a register in a unit test!\n");	\
> +		readl(vc4_crtc->regs + (offset));					\
> +	})
>   
>   static const struct debugfs_reg32 crtc_regs[] = {
>   	VC4_REG32(PV_CONTROL),
> diff --git a/drivers/gpu/drm/vc4/vc4_dpi.c b/drivers/gpu/drm/vc4/vc4_dpi.c
> index 1f8f44b7b5a5..0edf3c4c98c8 100644
> --- a/drivers/gpu/drm/vc4/vc4_dpi.c
> +++ b/drivers/gpu/drm/vc4/vc4_dpi.c
> @@ -103,8 +103,17 @@ to_vc4_dpi(struct drm_encoder *encoder)
>   	return container_of(encoder, struct vc4_dpi, encoder.base);
>   }
>   
> -#define DPI_READ(offset) readl(dpi->regs + (offset))
> -#define DPI_WRITE(offset, val) writel(val, dpi->regs + (offset))
> +#define DPI_READ(offset)								\
> +	({										\
> +		kunit_fail_current_test("Accessing a register in a unit test!\n");	\
> +		readl(dpi->regs + (offset));						\
> +	})
> +
> +#define DPI_WRITE(offset, val)								\
> +	do {										\
> +		kunit_fail_current_test("Accessing a register in a unit test!\n");	\
> +		writel(val, dpi->regs + (offset));					\
> +	} while (0)
>   
>   static const struct debugfs_reg32 dpi_regs[] = {
>   	VC4_REG32(DPI_C),
> diff --git a/drivers/gpu/drm/vc4/vc4_drv.h b/drivers/gpu/drm/vc4/vc4_drv.h
> index 418f4f308e36..78fda5332cb3 100644
> --- a/drivers/gpu/drm/vc4/vc4_drv.h
> +++ b/drivers/gpu/drm/vc4/vc4_drv.h
> @@ -19,6 +19,8 @@
>   #include <drm/drm_mm.h>
>   #include <drm/drm_modeset_lock.h>
>   
> +#include <kunit/test-bug.h>
> +
>   #include "uapi/drm/vc4_drm.h"
>   
>   struct drm_device;
> @@ -645,10 +647,29 @@ to_vc4_crtc_state(const struct drm_crtc_state *crtc_state)
>   	return container_of(crtc_state, struct vc4_crtc_state, base);
>   }
>   
> -#define V3D_READ(offset) readl(vc4->v3d->regs + offset)
> -#define V3D_WRITE(offset, val) writel(val, vc4->v3d->regs + offset)
> -#define HVS_READ(offset) readl(hvs->regs + offset)
> -#define HVS_WRITE(offset, val) writel(val, hvs->regs + offset)
> +#define V3D_READ(offset)								\
> +	({										\
> +		kunit_fail_current_test("Accessing a register in a unit test!\n");	\
> +		readl(vc4->v3d->regs + (offset));						\
> +	})
> +
> +#define V3D_WRITE(offset, val)								\
> +	do {										\
> +		kunit_fail_current_test("Accessing a register in a unit test!\n");	\
> +		writel(val, vc4->v3d->regs + (offset));					\
> +	} while (0)
> +
> +#define HVS_READ(offset)								\
> +	({										\
> +		kunit_fail_current_test("Accessing a register in a unit test!\n");	\
> +		readl(hvs->regs + (offset));						\
> +	})
> +
> +#define HVS_WRITE(offset, val)								\
> +	do {										\
> +		kunit_fail_current_test("Accessing a register in a unit test!\n");	\
> +		writel(val, hvs->regs + (offset));					\
> +	} while (0)
>   
>   #define VC4_REG32(reg) { .name = #reg, .offset = reg }
>   
> diff --git a/drivers/gpu/drm/vc4/vc4_dsi.c b/drivers/gpu/drm/vc4/vc4_dsi.c
> index 878e05d79e81..2c9cb27903a0 100644
> --- a/drivers/gpu/drm/vc4/vc4_dsi.c
> +++ b/drivers/gpu/drm/vc4/vc4_dsi.c
> @@ -617,6 +617,8 @@ dsi_dma_workaround_write(struct vc4_dsi *dsi, u32 offset, u32 val)
>   	dma_cookie_t cookie;
>   	int ret;
>   
> +	kunit_fail_current_test("Accessing a register in a unit test!\n");
> +
>   	/* DSI0 should be able to write normally. */
>   	if (!chan) {
>   		writel(val, dsi->regs + offset);
> @@ -645,7 +647,12 @@ dsi_dma_workaround_write(struct vc4_dsi *dsi, u32 offset, u32 val)
>   		DRM_ERROR("Failed to wait for DMA: %d\n", ret);
>   }
>   
> -#define DSI_READ(offset) readl(dsi->regs + (offset))
> +#define DSI_READ(offset)								\
> +	({										\
> +		kunit_fail_current_test("Accessing a register in a unit test!\n");	\
> +		readl(dsi->regs + (offset));						\
> +	})
> +
>   #define DSI_WRITE(offset, val) dsi_dma_workaround_write(dsi, offset, val)
>   #define DSI_PORT_READ(offset) \
>   	DSI_READ(dsi->variant->port ? DSI1_##offset : DSI0_##offset)
> diff --git a/drivers/gpu/drm/vc4/vc4_hdmi_regs.h b/drivers/gpu/drm/vc4/vc4_hdmi_regs.h
> index 48db438550b1..b04b2fc8d831 100644
> --- a/drivers/gpu/drm/vc4/vc4_hdmi_regs.h
> +++ b/drivers/gpu/drm/vc4/vc4_hdmi_regs.h
> @@ -456,6 +456,8 @@ static inline u32 vc4_hdmi_read(struct vc4_hdmi *hdmi,
>   
>   	WARN_ON(pm_runtime_status_suspended(&hdmi->pdev->dev));
>   
> +	kunit_fail_current_test("Accessing an HDMI register in a unit test!\n");
> +
>   	if (reg >= variant->num_registers) {
>   		dev_warn(&hdmi->pdev->dev,
>   			 "Invalid register ID %u\n", reg);
> @@ -486,6 +488,8 @@ static inline void vc4_hdmi_write(struct vc4_hdmi *hdmi,
>   
>   	WARN_ON(pm_runtime_status_suspended(&hdmi->pdev->dev));
>   
> +	kunit_fail_current_test("Accessing an HDMI register in a unit test!\n");
> +
>   	if (reg >= variant->num_registers) {
>   		dev_warn(&hdmi->pdev->dev,
>   			 "Invalid register ID %u\n", reg);
> diff --git a/drivers/gpu/drm/vc4/vc4_txp.c b/drivers/gpu/drm/vc4/vc4_txp.c
> index 2b69454b8534..ef5cab2a3aa9 100644
> --- a/drivers/gpu/drm/vc4/vc4_txp.c
> +++ b/drivers/gpu/drm/vc4/vc4_txp.c
> @@ -145,8 +145,17 @@
>   /* Number of lines received and committed to memory. */
>   #define TXP_PROGRESS		0x10
>   
> -#define TXP_READ(offset) readl(txp->regs + (offset))
> -#define TXP_WRITE(offset, val) writel(val, txp->regs + (offset))
> +#define TXP_READ(offset)								\
> +	({										\
> +		kunit_fail_current_test("Accessing a register in a unit test!\n");	\
> +		readl(txp->regs + (offset));						\
> +	})
> +
> +#define TXP_WRITE(offset, val)								\
> +	do {										\
> +		kunit_fail_current_test("Accessing a register in a unit test!\n");	\
> +		writel(val, txp->regs + (offset));					\
> +	} while (0)
>   
>   struct vc4_txp {
>   	struct vc4_crtc	base;
> diff --git a/drivers/gpu/drm/vc4/vc4_vec.c b/drivers/gpu/drm/vc4/vc4_vec.c
> index e270a4099be3..f589ab918f4d 100644
> --- a/drivers/gpu/drm/vc4/vc4_vec.c
> +++ b/drivers/gpu/drm/vc4/vc4_vec.c
> @@ -207,8 +207,17 @@ struct vc4_vec {
>   	struct debugfs_regset32 regset;
>   };
>   
> -#define VEC_READ(offset) readl(vec->regs + (offset))
> -#define VEC_WRITE(offset, val) writel(val, vec->regs + (offset))
> +#define VEC_READ(offset)								\
> +	({										\
> +		kunit_fail_current_test("Accessing a register in a unit test!\n");	\
> +		readl(vec->regs + (offset));						\
> +	})
> +
> +#define VEC_WRITE(offset, val)								\
> +	do {										\
> +		kunit_fail_current_test("Accessing a register in a unit test!\n");	\
> +		writel(val, vec->regs + (offset));					\
> +	} while (0)
>   
>   static inline struct vc4_vec *
>   encoder_to_vc4_vec(struct drm_encoder *encoder)
> 

^ permalink raw reply	[flat|nested] 7+ messages in thread

* Re: [PATCH v3 18/20] drm/vc4: tests: Fail the current test if we access a register
  2022-12-07 14:26   ` [PATCH v3 18/20] drm/vc4: tests: Fail the current test if we access a register Maíra Canal
@ 2022-12-07 16:11     ` Maxime Ripard
  0 siblings, 0 replies; 7+ messages in thread
From: Maxime Ripard @ 2022-12-07 16:11 UTC (permalink / raw)
  To: Maíra Canal
  Cc: Maarten Lankhorst, Daniel Vetter, Thomas Zimmermann,
	David Airlie, David Gow, Dave Stevenson, Greg Kroah-Hartman,
	Javier Martinez Canillas, dri-devel, linux-kernel, linaro-mm-sig,
	Brendan Higgins, linux-kselftest, kunit-dev, Maíra Canal,
	linux-media

[-- Attachment #1: Type: text/plain, Size: 937 bytes --]

Hi Maíra,

Thanks for your review!

On Wed, Dec 07, 2022 at 11:26:13AM -0300, Maíra Canal wrote:
> On 12/1/22 12:11, Maxime Ripard wrote:
> > Accessing a register when running under kunit is a bad idea since our
> > device is completely mocked.
> > 
> > Fail the current test if we ever access any of our hardware registers.
> > 
> > Reviewed-by: Javier Martinez Canillas <javierm@redhat.com>
> > Signed-off-by: Maxime Ripard <maxime@cerno.tech>
> 
> Reviewed-by: Maíra Canal <mcanal@igalia.com>
> 
> Just a small nit: I believe that macros with multiple statements should be
> enclosed in a do-while block [1], even READ macros. I saw that you enclosed
> the WRITE macros on a do-while block, but not the READ macros.

This is on purpose: do-while blocks don't return a value, but ({ ... })
blocks do. So we can do a write macros with a do-while, but can't for
read since we expect to get a value back.

Maxime

[-- Attachment #2: signature.asc --]
[-- Type: application/pgp-signature, Size: 228 bytes --]

^ permalink raw reply	[flat|nested] 7+ messages in thread

end of thread, other threads:[~2022-12-07 16:12 UTC | newest]

Thread overview: 7+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
     [not found] <20221123-rpi-kunit-tests-v3-0-4615a663a84a@cerno.tech>
     [not found] ` <20221123-rpi-kunit-tests-v3-20-4615a663a84a@cerno.tech>
2022-12-07 13:55   ` [PATCH v3 20/20] Documentation: gpu: vc4: Add KUnit Tests Section Maíra Canal
     [not found] ` <20221123-rpi-kunit-tests-v3-2-4615a663a84a@cerno.tech>
2022-12-07 13:57   ` [PATCH v3 02/20] drm/tests: Introduce a config option for the KUnit helpers Maíra Canal
     [not found] ` <20221123-rpi-kunit-tests-v3-4-4615a663a84a@cerno.tech>
2022-12-07 13:59   ` [PATCH v3 04/20] drm/tests: helpers: Switch to EXPORT_SYMBOL_GPL Maíra Canal
     [not found] ` <20221123-rpi-kunit-tests-v3-17-4615a663a84a@cerno.tech>
2022-12-07 14:08   ` [PATCH v3 17/20] drm/vc4: tests: Introduce a mocking infrastructure Maíra Canal
     [not found] ` <20221123-rpi-kunit-tests-v3-19-4615a663a84a@cerno.tech>
2022-12-07 14:24   ` [PATCH v3 19/20] drm/vc4: tests: Add unit test suite for the PV muxing Maíra Canal
     [not found] ` <20221123-rpi-kunit-tests-v3-18-4615a663a84a@cerno.tech>
2022-12-07 14:26   ` [PATCH v3 18/20] drm/vc4: tests: Fail the current test if we access a register Maíra Canal
2022-12-07 16:11     ` Maxime Ripard

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).