xref: /linux/drivers/gpu/drm/amd/display/amdgpu_dm/tests/amdgpu_dm_crtc_test.c (revision 63e19ef3ddab806c472748c825f4dc88dcd994e8)
1 // SPDX-License-Identifier: GPL-2.0 OR MIT
2 /*
3  * KUnit tests for amdgpu_dm_crtc.c
4  *
5  * Copyright 2026 Advanced Micro Devices, Inc.
6  */
7 
8 #include <kunit/test.h>
9 #include <drm/drm_atomic.h>
10 #include <drm/drm_connector.h>
11 #include <drm/drm_kunit_helpers.h>
12 #include <drm/drm_vblank.h>
13 
14 #include "dc.h"
15 #include "inc/core_types.h"
16 #include "irq/irq_service.h"
17 #include "amdgpu.h"
18 #include "amdgpu_mode.h"
19 #include "amdgpu_dm.h"
20 #include "amdgpu_dm_crtc.h"
21 #include "amdgpu_dm_kunit_test_helpers.h"
22 #include "amdgpu_dm_irq_params.h"
23 
24 /* Tests for amdgpu_dm_crtc_modeset_required() */
25 
26 /**
27  * dm_test_crtc_modeset_required_active_mode_changed - Test Crtc modeset required active mode changed
28  * @test: The KUnit test context
29  */
30 static void dm_test_crtc_modeset_required_active_mode_changed(struct kunit *test)
31 {
32 	struct drm_crtc_state state = {};
33 
34 	state.active = true;
35 	state.mode_changed = true;
36 
37 	KUNIT_EXPECT_TRUE(test,
38 			  amdgpu_dm_crtc_modeset_required(&state, NULL, NULL));
39 }
40 
41 /**
42  * dm_test_crtc_modeset_required_active_active_changed - Test Crtc modeset required active active changed
43  * @test: The KUnit test context
44  */
45 static void dm_test_crtc_modeset_required_active_active_changed(struct kunit *test)
46 {
47 	struct drm_crtc_state state = {};
48 
49 	state.active = true;
50 	state.active_changed = true;
51 
52 	KUNIT_EXPECT_TRUE(test,
53 			  amdgpu_dm_crtc_modeset_required(&state, NULL, NULL));
54 }
55 
56 /**
57  * dm_test_crtc_modeset_required_active_connectors_changed - Test Crtc modeset required active connectors changed
58  * @test: The KUnit test context
59  */
60 static void dm_test_crtc_modeset_required_active_connectors_changed(struct kunit *test)
61 {
62 	struct drm_crtc_state state = {};
63 
64 	state.active = true;
65 	state.connectors_changed = true;
66 
67 	KUNIT_EXPECT_TRUE(test,
68 			  amdgpu_dm_crtc_modeset_required(&state, NULL, NULL));
69 }
70 
71 /**
72  * dm_test_crtc_modeset_required_inactive - Test Crtc modeset required inactive
73  * @test: The KUnit test context
74  */
75 static void dm_test_crtc_modeset_required_inactive(struct kunit *test)
76 {
77 	struct drm_crtc_state state = {};
78 
79 	state.active = false;
80 	state.mode_changed = true;
81 
82 	KUNIT_EXPECT_FALSE(test,
83 			   amdgpu_dm_crtc_modeset_required(&state, NULL, NULL));
84 }
85 
86 /**
87  * dm_test_crtc_modeset_required_no_changes - Test Crtc modeset required no changes
88  * @test: The KUnit test context
89  */
90 static void dm_test_crtc_modeset_required_no_changes(struct kunit *test)
91 {
92 	struct drm_crtc_state state = {};
93 
94 	state.active = true;
95 	state.mode_changed = false;
96 	state.active_changed = false;
97 	state.connectors_changed = false;
98 
99 	KUNIT_EXPECT_FALSE(test,
100 			   amdgpu_dm_crtc_modeset_required(&state, NULL, NULL));
101 }
102 
103 /* Tests for amdgpu_dm_crtc_vrr_active_irq() */
104 
105 /**
106  * dm_test_crtc_vrr_active_irq_variable - Test Crtc vrr active irq variable
107  * @test: The KUnit test context
108  */
109 static void dm_test_crtc_vrr_active_irq_variable(struct kunit *test)
110 {
111 	struct amdgpu_crtc *acrtc = kunit_kzalloc(test, sizeof(*acrtc),
112 						  GFP_KERNEL);
113 
114 	KUNIT_ASSERT_NOT_ERR_OR_NULL(test, acrtc);
115 
116 	acrtc->dm_irq_params.freesync_config.state = VRR_STATE_ACTIVE_VARIABLE;
117 
118 	KUNIT_EXPECT_TRUE(test, amdgpu_dm_crtc_vrr_active_irq(acrtc));
119 }
120 
121 /**
122  * dm_test_crtc_vrr_active_irq_fixed - Test Crtc vrr active irq fixed
123  * @test: The KUnit test context
124  */
125 static void dm_test_crtc_vrr_active_irq_fixed(struct kunit *test)
126 {
127 	struct amdgpu_crtc *acrtc = kunit_kzalloc(test, sizeof(*acrtc),
128 						  GFP_KERNEL);
129 
130 	KUNIT_ASSERT_NOT_ERR_OR_NULL(test, acrtc);
131 
132 	acrtc->dm_irq_params.freesync_config.state = VRR_STATE_ACTIVE_FIXED;
133 
134 	KUNIT_EXPECT_TRUE(test, amdgpu_dm_crtc_vrr_active_irq(acrtc));
135 }
136 
137 /**
138  * dm_test_crtc_vrr_active_irq_inactive - Test Crtc vrr active irq inactive
139  * @test: The KUnit test context
140  */
141 static void dm_test_crtc_vrr_active_irq_inactive(struct kunit *test)
142 {
143 	struct amdgpu_crtc *acrtc = kunit_kzalloc(test, sizeof(*acrtc),
144 						  GFP_KERNEL);
145 
146 	KUNIT_ASSERT_NOT_ERR_OR_NULL(test, acrtc);
147 
148 	acrtc->dm_irq_params.freesync_config.state = VRR_STATE_INACTIVE;
149 
150 	KUNIT_EXPECT_FALSE(test, amdgpu_dm_crtc_vrr_active_irq(acrtc));
151 }
152 
153 /**
154  * dm_test_crtc_vrr_active_irq_disabled - Test Crtc vrr active irq disabled
155  * @test: The KUnit test context
156  */
157 static void dm_test_crtc_vrr_active_irq_disabled(struct kunit *test)
158 {
159 	struct amdgpu_crtc *acrtc = kunit_kzalloc(test, sizeof(*acrtc),
160 						  GFP_KERNEL);
161 
162 	KUNIT_ASSERT_NOT_ERR_OR_NULL(test, acrtc);
163 
164 	acrtc->dm_irq_params.freesync_config.state = VRR_STATE_DISABLED;
165 
166 	KUNIT_EXPECT_FALSE(test, amdgpu_dm_crtc_vrr_active_irq(acrtc));
167 }
168 
169 /**
170  * dm_test_crtc_vrr_active_irq_unsupported - Test Crtc vrr active irq unsupported
171  * @test: The KUnit test context
172  */
173 static void dm_test_crtc_vrr_active_irq_unsupported(struct kunit *test)
174 {
175 	struct amdgpu_crtc *acrtc = kunit_kzalloc(test, sizeof(*acrtc),
176 						  GFP_KERNEL);
177 
178 	KUNIT_ASSERT_NOT_ERR_OR_NULL(test, acrtc);
179 
180 	acrtc->dm_irq_params.freesync_config.state = VRR_STATE_UNSUPPORTED;
181 
182 	KUNIT_EXPECT_FALSE(test, amdgpu_dm_crtc_vrr_active_irq(acrtc));
183 }
184 
185 /* Tests for amdgpu_dm_crtc_vrr_active() */
186 
187 /**
188  * dm_test_crtc_vrr_active_variable - Test Crtc vrr active variable
189  * @test: The KUnit test context
190  */
191 static void dm_test_crtc_vrr_active_variable(struct kunit *test)
192 {
193 	struct dm_crtc_state *dm_state = kunit_kzalloc(test,
194 						       sizeof(*dm_state),
195 						       GFP_KERNEL);
196 
197 	KUNIT_ASSERT_NOT_ERR_OR_NULL(test, dm_state);
198 
199 	dm_state->freesync_config.state = VRR_STATE_ACTIVE_VARIABLE;
200 
201 	KUNIT_EXPECT_TRUE(test, amdgpu_dm_crtc_vrr_active(dm_state));
202 }
203 
204 /**
205  * dm_test_crtc_vrr_active_fixed - Test Crtc vrr active fixed
206  * @test: The KUnit test context
207  */
208 static void dm_test_crtc_vrr_active_fixed(struct kunit *test)
209 {
210 	struct dm_crtc_state *dm_state = kunit_kzalloc(test,
211 						       sizeof(*dm_state),
212 						       GFP_KERNEL);
213 
214 	KUNIT_ASSERT_NOT_ERR_OR_NULL(test, dm_state);
215 
216 	dm_state->freesync_config.state = VRR_STATE_ACTIVE_FIXED;
217 
218 	KUNIT_EXPECT_TRUE(test, amdgpu_dm_crtc_vrr_active(dm_state));
219 }
220 
221 /**
222  * dm_test_crtc_vrr_active_inactive - Test Crtc vrr active inactive
223  * @test: The KUnit test context
224  */
225 static void dm_test_crtc_vrr_active_inactive(struct kunit *test)
226 {
227 	struct dm_crtc_state *dm_state = kunit_kzalloc(test,
228 						       sizeof(*dm_state),
229 						       GFP_KERNEL);
230 
231 	KUNIT_ASSERT_NOT_ERR_OR_NULL(test, dm_state);
232 
233 	dm_state->freesync_config.state = VRR_STATE_INACTIVE;
234 
235 	KUNIT_EXPECT_FALSE(test, amdgpu_dm_crtc_vrr_active(dm_state));
236 }
237 
238 /**
239  * dm_test_crtc_vrr_active_disabled - Test Crtc vrr active disabled
240  * @test: The KUnit test context
241  */
242 static void dm_test_crtc_vrr_active_disabled(struct kunit *test)
243 {
244 	struct dm_crtc_state *dm_state = kunit_kzalloc(test,
245 						       sizeof(*dm_state),
246 						       GFP_KERNEL);
247 
248 	KUNIT_ASSERT_NOT_ERR_OR_NULL(test, dm_state);
249 
250 	dm_state->freesync_config.state = VRR_STATE_DISABLED;
251 
252 	KUNIT_EXPECT_FALSE(test, amdgpu_dm_crtc_vrr_active(dm_state));
253 }
254 
255 /**
256  * dm_test_crtc_vrr_active_unsupported - Test Crtc vrr active unsupported
257  * @test: The KUnit test context
258  */
259 static void dm_test_crtc_vrr_active_unsupported(struct kunit *test)
260 {
261 	struct dm_crtc_state *dm_state = kunit_kzalloc(test,
262 						       sizeof(*dm_state),
263 						       GFP_KERNEL);
264 
265 	KUNIT_ASSERT_NOT_ERR_OR_NULL(test, dm_state);
266 
267 	dm_state->freesync_config.state = VRR_STATE_UNSUPPORTED;
268 
269 	KUNIT_EXPECT_FALSE(test, amdgpu_dm_crtc_vrr_active(dm_state));
270 }
271 
272 /* Tests for amdgpu_dm_is_headless() */
273 
274 static void dm_test_add_connector(struct drm_device *dev,
275 				  struct drm_connector *connector,
276 				  int connector_type,
277 				  enum drm_connector_status status)
278 {
279 	INIT_LIST_HEAD(&connector->head);
280 	kref_init(&connector->base.refcount);
281 	connector->connector_type = connector_type;
282 	connector->status = status;
283 	list_add_tail(&connector->head, &dev->mode_config.connector_list);
284 }
285 
286 /**
287  * dm_test_crtc_is_headless_null_adev - Test Crtc is headless null adev
288  * @test: The KUnit test context
289  */
290 static void dm_test_crtc_is_headless_null_adev(struct kunit *test)
291 {
292 	KUNIT_EXPECT_TRUE(test, amdgpu_dm_is_headless(NULL));
293 }
294 
295 /**
296  * dm_test_crtc_is_headless_no_connectors - Test Crtc is headless no connectors
297  * @test: The KUnit test context
298  */
299 static void dm_test_crtc_is_headless_no_connectors(struct kunit *test)
300 {
301 	struct amdgpu_device *adev = kunit_kzalloc(test, sizeof(*adev), GFP_KERNEL);
302 	struct drm_device *dev = dm_kunit_alloc_drm_with_connector_list(test);
303 
304 	KUNIT_ASSERT_NOT_ERR_OR_NULL(test, adev);
305 	adev->dm.ddev = dev;
306 
307 	KUNIT_EXPECT_TRUE(test, amdgpu_dm_is_headless(adev));
308 }
309 
310 /**
311  * dm_test_crtc_is_headless_writeback_only - Test Crtc is headless writeback only
312  * @test: The KUnit test context
313  */
314 static void dm_test_crtc_is_headless_writeback_only(struct kunit *test)
315 {
316 	struct amdgpu_device *adev = kunit_kzalloc(test, sizeof(*adev), GFP_KERNEL);
317 	struct drm_device *dev = dm_kunit_alloc_drm_with_connector_list(test);
318 	struct drm_connector *wb = kunit_kzalloc(test, sizeof(*wb), GFP_KERNEL);
319 
320 	KUNIT_ASSERT_NOT_ERR_OR_NULL(test, adev);
321 	KUNIT_ASSERT_NOT_ERR_OR_NULL(test, wb);
322 	adev->dm.ddev = dev;
323 
324 	dm_test_add_connector(dev, wb, DRM_MODE_CONNECTOR_WRITEBACK,
325 			      connector_status_connected);
326 
327 	KUNIT_EXPECT_TRUE(test, amdgpu_dm_is_headless(adev));
328 }
329 
330 /**
331  * dm_test_crtc_is_headless_disconnected_display - Test Crtc is headless disconnected display
332  * @test: The KUnit test context
333  */
334 static void dm_test_crtc_is_headless_disconnected_display(struct kunit *test)
335 {
336 	struct amdgpu_device *adev = kunit_kzalloc(test, sizeof(*adev), GFP_KERNEL);
337 	struct drm_device *dev = dm_kunit_alloc_drm_with_connector_list(test);
338 	struct drm_connector *display = kunit_kzalloc(test, sizeof(*display), GFP_KERNEL);
339 
340 	KUNIT_ASSERT_NOT_ERR_OR_NULL(test, adev);
341 	KUNIT_ASSERT_NOT_ERR_OR_NULL(test, display);
342 	adev->dm.ddev = dev;
343 
344 	dm_test_add_connector(dev, display, DRM_MODE_CONNECTOR_HDMIA,
345 			      connector_status_disconnected);
346 
347 	KUNIT_EXPECT_TRUE(test, amdgpu_dm_is_headless(adev));
348 }
349 
350 /**
351  * dm_test_crtc_is_headless_connected_display - Test Crtc is headless connected display
352  * @test: The KUnit test context
353  */
354 static void dm_test_crtc_is_headless_connected_display(struct kunit *test)
355 {
356 	struct amdgpu_device *adev = kunit_kzalloc(test, sizeof(*adev), GFP_KERNEL);
357 	struct drm_device *dev = dm_kunit_alloc_drm_with_connector_list(test);
358 	struct drm_connector *display = kunit_kzalloc(test, sizeof(*display), GFP_KERNEL);
359 
360 	KUNIT_ASSERT_NOT_ERR_OR_NULL(test, adev);
361 	KUNIT_ASSERT_NOT_ERR_OR_NULL(test, display);
362 	adev->dm.ddev = dev;
363 
364 	dm_test_add_connector(dev, display, DRM_MODE_CONNECTOR_HDMIA,
365 			      connector_status_connected);
366 
367 	KUNIT_EXPECT_FALSE(test, amdgpu_dm_is_headless(adev));
368 }
369 
370 /**
371  * dm_test_crtc_is_headless_mixed_connectors - Test headless skips WB and finds display
372  * @test: The KUnit test context
373  */
374 static void dm_test_crtc_is_headless_mixed_connectors(struct kunit *test)
375 {
376 	struct amdgpu_device *adev = kunit_kzalloc(test, sizeof(*adev), GFP_KERNEL);
377 	struct drm_device *dev = dm_kunit_alloc_drm_with_connector_list(test);
378 	struct drm_connector *wb = kunit_kzalloc(test, sizeof(*wb), GFP_KERNEL);
379 	struct drm_connector *display = kunit_kzalloc(test, sizeof(*display), GFP_KERNEL);
380 
381 	KUNIT_ASSERT_NOT_ERR_OR_NULL(test, adev);
382 	KUNIT_ASSERT_NOT_ERR_OR_NULL(test, wb);
383 	KUNIT_ASSERT_NOT_ERR_OR_NULL(test, display);
384 	adev->dm.ddev = dev;
385 
386 	dm_test_add_connector(dev, wb, DRM_MODE_CONNECTOR_WRITEBACK,
387 			      connector_status_connected);
388 	dm_test_add_connector(dev, display, DRM_MODE_CONNECTOR_DisplayPort,
389 			      connector_status_connected);
390 
391 	KUNIT_EXPECT_FALSE(test, amdgpu_dm_is_headless(adev));
392 }
393 
394 /* Tests for amdgpu_dm_crtc_helper_mode_fixup() */
395 
396 /**
397  * dm_test_crtc_helper_mode_fixup_returns_true - Test mode_fixup accepts mode
398  * @test: The KUnit test context
399  */
400 static void dm_test_crtc_helper_mode_fixup_returns_true(struct kunit *test)
401 {
402 	struct drm_display_mode mode = { 0 };
403 	struct drm_display_mode adjusted_mode = { 0 };
404 
405 	KUNIT_EXPECT_TRUE(test,
406 			  amdgpu_dm_crtc_helper_mode_fixup(NULL, &mode, &adjusted_mode));
407 }
408 
409 /* Tests for amdgpu_dm_crtc_set_vupdate_irq() */
410 
411 /**
412  * dm_test_crtc_set_vupdate_irq_no_otg - Test vupdate irq with unassigned OTG
413  * @test: The KUnit test context
414  *
415  * When the CRTC has no OTG instance assigned (otg_inst == -1) the function
416  * must return 0 immediately without touching the DC interrupt state.
417  */
418 static void dm_test_crtc_set_vupdate_irq_no_otg(struct kunit *test)
419 {
420 	struct amdgpu_crtc *acrtc;
421 	struct amdgpu_device *adev;
422 
423 	adev = dm_kunit_alloc_adev(test);
424 
425 	acrtc = kunit_kzalloc(test, sizeof(*acrtc), GFP_KERNEL);
426 	KUNIT_ASSERT_NOT_ERR_OR_NULL(test, acrtc);
427 
428 	acrtc->base.dev = &adev->ddev;
429 	acrtc->otg_inst = -1;
430 
431 	KUNIT_EXPECT_EQ(test, amdgpu_dm_crtc_set_vupdate_irq(&acrtc->base, true), 0);
432 	KUNIT_EXPECT_EQ(test, amdgpu_dm_crtc_set_vupdate_irq(&acrtc->base, false), 0);
433 }
434 
435 /**
436  * dm_test_crtc_set_vupdate_irq_dc_busy - Test vupdate irq when DC rejects request
437  * @test: The KUnit test context
438  *
439  * With an OTG instance assigned but no DC attached, amdgpu_dm_irq_set() returns
440  * false and the function must report the request as busy (-EBUSY).
441  */
442 static void dm_test_crtc_set_vupdate_irq_dc_busy(struct kunit *test)
443 {
444 	struct amdgpu_crtc *acrtc;
445 	struct amdgpu_device *adev;
446 
447 	adev = dm_kunit_alloc_adev(test);
448 	KUNIT_ASSERT_NOT_ERR_OR_NULL(test, adev);
449 
450 	acrtc = kunit_kzalloc(test, sizeof(*acrtc), GFP_KERNEL);
451 	KUNIT_ASSERT_NOT_ERR_OR_NULL(test, acrtc);
452 
453 	acrtc->base.dev = &adev->ddev;
454 	acrtc->otg_inst = 0;
455 
456 	/* adev->dm.dc is NULL, so amdgpu_dm_irq_set() returns false. */
457 	KUNIT_EXPECT_EQ(test,
458 			amdgpu_dm_crtc_set_vupdate_irq(&acrtc->base, true), -EBUSY);
459 }
460 
461 /* Per-source funcs let amdgpu_dm_irq_set() succeed without register access. */
462 static bool dm_test_vupdate_irq_src_set(struct irq_service *irq_service,
463 					const struct irq_source_info *info,
464 					bool enable)
465 {
466 	return true;
467 }
468 
469 static bool dm_test_vupdate_irq_src_ack(struct irq_service *irq_service,
470 					const struct irq_source_info *info)
471 {
472 	return true;
473 }
474 
475 static struct irq_source_info_funcs dm_test_vupdate_irq_src_funcs = {
476 	.set = dm_test_vupdate_irq_src_set,
477 	.ack = dm_test_vupdate_irq_src_ack,
478 };
479 
480 /* A .set that fails so amdgpu_dm_irq_set() reports the source as busy. */
481 static bool dm_test_vupdate_irq_src_set_busy(struct irq_service *irq_service,
482 					     const struct irq_source_info *info,
483 					     bool enable)
484 {
485 	return false;
486 }
487 
488 static struct irq_source_info_funcs dm_test_vupdate_irq_src_busy_funcs = {
489 	.set = dm_test_vupdate_irq_src_set_busy,
490 	.ack = dm_test_vupdate_irq_src_ack,
491 };
492 
493 /**
494  * dm_test_crtc_set_vupdate_irq_enable - Test vupdate irq enable/disable success
495  * @test: The KUnit test context
496  *
497  * With an OTG instance assigned and a DC whose IRQ service accepts the request,
498  * enabling and disabling the vupdate IRQ must both succeed (return 0).
499  */
500 static void dm_test_crtc_set_vupdate_irq_enable(struct kunit *test)
501 {
502 	struct irq_source_info *info;
503 	struct resource_pool *res_pool;
504 	struct irq_service *irqs;
505 	struct amdgpu_crtc *acrtc;
506 	struct amdgpu_device *adev;
507 	struct dc *dc;
508 	int i;
509 
510 	adev = dm_kunit_alloc_adev(test);
511 	KUNIT_ASSERT_NOT_ERR_OR_NULL(test, adev);
512 
513 	acrtc = kunit_kzalloc(test, sizeof(*acrtc), GFP_KERNEL);
514 	KUNIT_ASSERT_NOT_ERR_OR_NULL(test, acrtc);
515 
516 	dc = dm_kunit_alloc_dc_with_ctx(test);
517 	res_pool = kunit_kzalloc(test, sizeof(*res_pool), GFP_KERNEL);
518 	KUNIT_ASSERT_NOT_ERR_OR_NULL(test, res_pool);
519 	irqs = kunit_kzalloc(test, sizeof(*irqs), GFP_KERNEL);
520 	KUNIT_ASSERT_NOT_ERR_OR_NULL(test, irqs);
521 
522 	/*
523 	 * Populate the per-source info table so amdgpu_dm_irq_set() succeeds.
524 	 */
525 	info = kunit_kzalloc(test, sizeof(*info) * DAL_IRQ_SOURCES_NUMBER,
526 			     GFP_KERNEL);
527 	KUNIT_ASSERT_NOT_ERR_OR_NULL(test, info);
528 	for (i = 0; i < DAL_IRQ_SOURCES_NUMBER; i++)
529 		info[i].funcs = &dm_test_vupdate_irq_src_funcs;
530 
531 	irqs->info = info;
532 	res_pool->irqs = irqs;
533 	dc->res_pool = res_pool;
534 	adev->dm.dc = dc;
535 
536 	acrtc->base.dev = &adev->ddev;
537 	acrtc->otg_inst = 0;
538 
539 	KUNIT_EXPECT_EQ(test,
540 			amdgpu_dm_crtc_set_vupdate_irq(&acrtc->base, true), 0);
541 	KUNIT_EXPECT_EQ(test,
542 			amdgpu_dm_crtc_set_vupdate_irq(&acrtc->base, false), 0);
543 }
544 
545 /* Tests for idle_create_workqueue() */
546 
547 /**
548  * dm_test_idle_create_workqueue - Test idle workqueue creation
549  * @test: The KUnit test context
550  *
551  * Verify that idle_create_workqueue() allocates an idle workqueue tied to the
552  * device's display manager and initializes it in a disabled, non-running state.
553  */
554 static void dm_test_idle_create_workqueue(struct kunit *test)
555 {
556 	struct amdgpu_device *adev;
557 	struct idle_workqueue *idle_work;
558 
559 	adev = kunit_kzalloc(test, sizeof(*adev), GFP_KERNEL);
560 	KUNIT_ASSERT_NOT_ERR_OR_NULL(test, adev);
561 
562 	idle_work = idle_create_workqueue(adev);
563 	KUNIT_ASSERT_NOT_ERR_OR_NULL(test, idle_work);
564 
565 	KUNIT_EXPECT_PTR_EQ(test, idle_work->dm, &adev->dm);
566 	KUNIT_EXPECT_FALSE(test, idle_work->enable);
567 	KUNIT_EXPECT_FALSE(test, idle_work->running);
568 
569 	kfree(idle_work);
570 }
571 
572 /**
573  * dm_test_idle_worker_disabled_clears_running - Test worker exits when disabled
574  * @test: The KUnit test context
575  *
576  * With the idle workqueue disabled, amdgpu_dm_idle_worker() must skip the idle
577  * optimization loop entirely and leave the shared running flag cleared.
578  */
579 static void dm_test_idle_worker_disabled_clears_running(struct kunit *test)
580 {
581 	struct idle_workqueue *idle_work;
582 	struct amdgpu_device *adev;
583 
584 	adev = dm_kunit_alloc_adev(test);
585 	KUNIT_ASSERT_NOT_ERR_OR_NULL(test, adev);
586 
587 	idle_work = kunit_kzalloc(test, sizeof(*idle_work), GFP_KERNEL);
588 	KUNIT_ASSERT_NOT_ERR_OR_NULL(test, idle_work);
589 
590 	idle_work->dm = &adev->dm;
591 	idle_work->enable = false;
592 	idle_work->running = true;
593 	/* The worker toggles running through dm->idle_workqueue. */
594 	adev->dm.idle_workqueue = idle_work;
595 
596 	amdgpu_dm_idle_worker(&idle_work->work);
597 
598 	KUNIT_EXPECT_FALSE(test, idle_work->running);
599 }
600 
601 /**
602  * dm_test_idle_worker_enabled_breaks_when_idle_disallowed - Test loop entry/exit
603  * @test: The KUnit test context
604  *
605  * With the workqueue enabled but idle optimizations disallowed, the worker enters
606  * the detection loop once, takes the early break, and clears the running flag.
607  */
608 static void dm_test_idle_worker_enabled_breaks_when_idle_disallowed(struct kunit *test)
609 {
610 	struct idle_workqueue *idle_work;
611 	struct amdgpu_device *adev;
612 
613 	adev = dm_kunit_alloc_adev(test);
614 	KUNIT_ASSERT_NOT_ERR_OR_NULL(test, adev);
615 
616 	mutex_init(&adev->dm.dc_lock);
617 	adev->dm.dc = dm_kunit_alloc_dc_with_ctx(test);
618 	KUNIT_ASSERT_NOT_ERR_OR_NULL(test, adev->dm.dc);
619 	/* First loop iteration breaks before any dc_allow_idle_optimizations(). */
620 	adev->dm.dc->idle_optimizations_allowed = false;
621 
622 	idle_work = kunit_kzalloc(test, sizeof(*idle_work), GFP_KERNEL);
623 	KUNIT_ASSERT_NOT_ERR_OR_NULL(test, idle_work);
624 
625 	idle_work->dm = &adev->dm;
626 	idle_work->enable = true;
627 	adev->dm.idle_workqueue = idle_work;
628 
629 	amdgpu_dm_idle_worker(&idle_work->work);
630 
631 	KUNIT_EXPECT_FALSE(test, idle_work->running);
632 }
633 
634 /**
635  * dm_test_idle_worker_enabled_breaks_when_not_headless - Test second break path
636  * @test: The KUnit test context
637  *
638  * With idle optimizations allowed, the worker passes the first branch and runs
639  * dc_allow_idle_optimizations(). A connected display makes the device non-headless
640  * while no PSR is active, so the worker takes the second break and stops running.
641  */
642 static void dm_test_idle_worker_enabled_breaks_when_not_headless(struct kunit *test)
643 {
644 	struct idle_workqueue *idle_work;
645 	struct drm_connector *display;
646 	struct amdgpu_device *adev;
647 
648 	adev = dm_kunit_alloc_adev(test);
649 	KUNIT_ASSERT_NOT_ERR_OR_NULL(test, adev);
650 
651 	mutex_init(&adev->dm.dc_lock);
652 	adev->dm.adev = adev;
653 	adev->dm.ddev = dm_kunit_alloc_drm_with_connector_list(test);
654 	KUNIT_ASSERT_NOT_ERR_OR_NULL(test, adev->dm.ddev);
655 
656 	adev->dm.dc = dm_kunit_alloc_dc_with_ctx(test);
657 	KUNIT_ASSERT_NOT_ERR_OR_NULL(test, adev->dm.dc);
658 	/* Allow idle so the first branch is skipped and dc_allow() is exercised. */
659 	adev->dm.dc->idle_optimizations_allowed = true;
660 	/* is_apu path avoids DC_LOG_DC()'s NULL-logger dereference. */
661 	adev->dm.dc->caps.is_apu = true;
662 	/* Empty stream list -> amdgpu_dm_psr_is_active_allowed() returns false. */
663 	adev->dm.dc->current_state = dm_kunit_alloc_dc_state(test);
664 	KUNIT_ASSERT_NOT_ERR_OR_NULL(test, adev->dm.dc->current_state);
665 
666 	/* A connected display makes amdgpu_dm_is_headless() false. */
667 	display = kunit_kzalloc(test, sizeof(*display), GFP_KERNEL);
668 	KUNIT_ASSERT_NOT_ERR_OR_NULL(test, display);
669 	dm_test_add_connector(adev->dm.ddev, display, DRM_MODE_CONNECTOR_HDMIA,
670 			      connector_status_connected);
671 
672 	idle_work = kunit_kzalloc(test, sizeof(*idle_work), GFP_KERNEL);
673 	KUNIT_ASSERT_NOT_ERR_OR_NULL(test, idle_work);
674 	idle_work->dm = &adev->dm;
675 	idle_work->enable = true;
676 	adev->dm.idle_workqueue = idle_work;
677 
678 	amdgpu_dm_idle_worker(&idle_work->work);
679 
680 	KUNIT_EXPECT_FALSE(test, idle_work->running);
681 }
682 
683 /*
684  * Report success only when disabling idle. dc_allow_idle_optimizations() then
685  * clears dc->idle_optimizations_allowed on the disable call but leaves it clear
686  * on the re-enable call inside the worker's enable-body, so the next loop
687  * iteration breaks at the first branch instead of looping forever.
688  */
689 static bool dm_test_idle_apply_flip(struct dc *dc, bool enable)
690 {
691 	return !enable;
692 }
693 
694 /**
695  * dm_test_idle_worker_enabled_runs_body - Test the enable-body path
696  * @test: The KUnit test context
697  *
698  * A headless device makes the second branch false so the worker runs the
699  * enable-body (dc_post_update_surfaces_to_stream() + re-enable). An injected
700  * hwss.apply_idle_power_optimizations() callback lets dc_allow_idle_optimizations()
701  * clear idle_optimizations_allowed on the disable half, so the following loop
702  * iteration breaks at the first branch and the worker stops.
703  */
704 static void dm_test_idle_worker_enabled_runs_body(struct kunit *test)
705 {
706 	struct idle_workqueue *idle_work;
707 	struct amdgpu_device *adev;
708 	struct dal_logger *logger;
709 
710 	adev = dm_kunit_alloc_adev(test);
711 	KUNIT_ASSERT_NOT_ERR_OR_NULL(test, adev);
712 
713 	mutex_init(&adev->dm.dc_lock);
714 	adev->dm.adev = adev;
715 	/* Empty connector list keeps the device headless -> second branch false. */
716 	adev->dm.ddev = dm_kunit_alloc_drm_with_connector_list(test);
717 	KUNIT_ASSERT_NOT_ERR_OR_NULL(test, adev->dm.ddev);
718 
719 	adev->dm.dc = dm_kunit_alloc_dc_with_ctx(test);
720 	KUNIT_ASSERT_NOT_ERR_OR_NULL(test, adev->dm.dc);
721 	/* Allow idle so the first branch is skipped and dc_allow() is exercised. */
722 	adev->dm.dc->idle_optimizations_allowed = true;
723 	/* is_apu path avoids DC_LOG_DC()'s NULL-logger dereference. */
724 	adev->dm.dc->caps.is_apu = true;
725 	/* dc_allow() logs via DC_LOG_DEBUG() when it flips the flag. */
726 	logger = kunit_kzalloc(test, sizeof(*logger), GFP_KERNEL);
727 	KUNIT_ASSERT_NOT_ERR_OR_NULL(test, logger);
728 	logger->dev = &adev->ddev;
729 	adev->dm.dc->ctx->logger = logger;
730 	/* dc_allow() only flips the flag when clk_mgr and apply() are present. */
731 	adev->dm.dc->clk_mgr = dm_kunit_alloc_clk_mgr(test);
732 	KUNIT_ASSERT_NOT_ERR_OR_NULL(test, adev->dm.dc->clk_mgr);
733 	adev->dm.dc->hwss.apply_idle_power_optimizations = dm_test_idle_apply_flip;
734 
735 	idle_work = kunit_kzalloc(test, sizeof(*idle_work), GFP_KERNEL);
736 	KUNIT_ASSERT_NOT_ERR_OR_NULL(test, idle_work);
737 	idle_work->dm = &adev->dm;
738 	idle_work->enable = true;
739 	adev->dm.idle_workqueue = idle_work;
740 
741 	amdgpu_dm_idle_worker(&idle_work->work);
742 
743 	/* Enable-body ran, then the next iteration disabled idle and stopped. */
744 	KUNIT_EXPECT_FALSE(test, adev->dm.dc->idle_optimizations_allowed);
745 	KUNIT_EXPECT_FALSE(test, idle_work->running);
746 }
747 
748 /* Tests for amdgpu_dm_crtc_set_static_screen_optimze() */
749 
750 /**
751  * dm_test_crtc_set_static_screen_optimze_no_sr_entry - Test early return when SR entry disallowed
752  * @test: The KUnit test context
753  *
754  * When self-refresh entry is not allowed the function must return immediately
755  * without touching replay or PSR events, regardless of the requested SSO state.
756  */
757 static void dm_test_crtc_set_static_screen_optimze_no_sr_entry(struct kunit *test)
758 {
759 	struct amdgpu_display_manager *dm;
760 	struct dc_link *link;
761 	struct dc_stream_state *stream;
762 
763 	dm = kunit_kzalloc(test, sizeof(*dm), GFP_KERNEL);
764 	KUNIT_ASSERT_NOT_ERR_OR_NULL(test, dm);
765 
766 	link = dm_kunit_alloc_link(test);
767 	stream = dm_kunit_alloc_stream(test, link);
768 
769 	/* allow_sr_entry == false -> returns before any event is set. */
770 	amdgpu_dm_crtc_set_static_screen_optimze(dm, stream, true, false);
771 	amdgpu_dm_crtc_set_static_screen_optimze(dm, stream, false, false);
772 }
773 
774 /**
775  * dm_test_crtc_set_static_screen_optimze_sr_entry_psr - Test SSO toggle drives PSR
776  * @test: The KUnit test context
777  *
778  * With self-refresh entry allowed and a PSR version below DC_PSR_VERSION_SU_1,
779  * the function must run both the replay and PSR event updates. The link has no
780  * replay/PSR feature enabled, so both event helpers short-circuit safely. Both
781  * SSO states are exercised to cover the set_vsync_event computation.
782  */
783 static void dm_test_crtc_set_static_screen_optimze_sr_entry_psr(struct kunit *test)
784 {
785 	struct amdgpu_display_manager *dm;
786 	struct dc_link *link;
787 	struct dc_stream_state *stream;
788 
789 	dm = kunit_kzalloc(test, sizeof(*dm), GFP_KERNEL);
790 	KUNIT_ASSERT_NOT_ERR_OR_NULL(test, dm);
791 
792 	link = dm_kunit_alloc_link(test);
793 	stream = dm_kunit_alloc_stream(test, link);
794 
795 	/* psr_version < DC_PSR_VERSION_SU_1 -> PSR event branch is taken. */
796 	link->psr_settings.psr_version = DC_PSR_VERSION_1;
797 
798 	amdgpu_dm_crtc_set_static_screen_optimze(dm, stream, true, true);
799 	amdgpu_dm_crtc_set_static_screen_optimze(dm, stream, false, true);
800 }
801 
802 /**
803  * dm_test_crtc_set_static_screen_optimze_psr_su_skips - Test PSR SU skips PSR event
804  * @test: The KUnit test context
805  *
806  * With self-refresh entry allowed and a PSR version of DC_PSR_VERSION_SU_1, the
807  * function must update the replay event but skip the PSR event update.
808  */
809 static void dm_test_crtc_set_static_screen_optimze_psr_su_skips(struct kunit *test)
810 {
811 	struct amdgpu_display_manager *dm;
812 	struct dc_link *link;
813 	struct dc_stream_state *stream;
814 
815 	dm = kunit_kzalloc(test, sizeof(*dm), GFP_KERNEL);
816 	KUNIT_ASSERT_NOT_ERR_OR_NULL(test, dm);
817 
818 	link = dm_kunit_alloc_link(test);
819 	stream = dm_kunit_alloc_stream(test, link);
820 
821 	/* psr_version >= DC_PSR_VERSION_SU_1 -> PSR event branch is skipped. */
822 	link->psr_settings.psr_version = DC_PSR_VERSION_SU_1;
823 
824 	amdgpu_dm_crtc_set_static_screen_optimze(dm, stream, true, true);
825 }
826 
827 /* Tests for amdgpu_dm_crtc_enable_vblank() */
828 
829 /**
830  * dm_test_crtc_enable_vblank_rejects_unconfigured - Test vblank enable on disabled CRTC
831  * @test: The KUnit test context
832  *
833  * Enabling vblank on a CRTC that is not enabled must be rejected with -EINVAL
834  * before any interrupt state is touched.
835  */
836 static void dm_test_crtc_enable_vblank_rejects_unconfigured(struct kunit *test)
837 {
838 	struct amdgpu_device *adev = dm_kunit_alloc_adev(test);
839 	struct amdgpu_crtc *acrtc;
840 
841 	acrtc = kunit_kzalloc(test, sizeof(*acrtc), GFP_KERNEL);
842 	KUNIT_ASSERT_NOT_ERR_OR_NULL(test, acrtc);
843 
844 	acrtc->base.dev = &adev->ddev;
845 	acrtc->base.enabled = false;
846 
847 	KUNIT_EXPECT_EQ(test, amdgpu_dm_crtc_enable_vblank(&acrtc->base), -EINVAL);
848 }
849 
850 /* Stub IRQ source .set so amdgpu_irq_get()/put() pass their funcs->set check. */
851 static int dm_test_crtc_irq_src_set(struct amdgpu_device *adev,
852 				    struct amdgpu_irq_src *source,
853 				    unsigned int type,
854 				    enum amdgpu_interrupt_state state)
855 {
856 	return 0;
857 }
858 
859 static const struct amdgpu_irq_src_funcs dm_test_crtc_irq_src_funcs = {
860 	.set = dm_test_crtc_irq_src_set,
861 };
862 
863 /*
864  * Stub get_vblank_timestamp so drm_crtc_vblank_restore() finds a non-NULL hook.
865  * The CRTC is not registered on the device, so drm_crtc_from_index() returns
866  * NULL and this callback is never actually invoked; it only satisfies the
867  * WARN_ON_ONCE(!crtc->funcs->get_vblank_timestamp) sanity check.
868  */
869 static bool dm_test_crtc_get_vblank_timestamp(struct drm_crtc *crtc,
870 					      int *max_error,
871 					      ktime_t *vblank_time,
872 					      bool in_vblank_irq)
873 {
874 	return false;
875 }
876 
877 static const struct drm_crtc_funcs dm_test_crtc_funcs = {
878 	.get_vblank_timestamp = dm_test_crtc_get_vblank_timestamp,
879 };
880 
881 /*
882  * dm_test_crtc_arm_irq_src - Prime an IRQ source so get()/put() short-circuit.
883  * @test: The KUnit test context
884  * @src: The amdgpu IRQ source to arm
885  * @count: Initial per-type reference count
886  *
887  * Seeds enabled_types[AMDGPU_CRTC_IRQ_VBLANK1] with @count and installs a
888  * non-NULL funcs->set so amdgpu_irq_get()/amdgpu_irq_put() adjust the refcount
889  * without ever reaching amdgpu_irq_update() (which would touch hardware).
890  */
891 static void dm_test_crtc_arm_irq_src(struct kunit *test,
892 				     struct amdgpu_irq_src *src, int count)
893 {
894 	atomic_t *enabled;
895 
896 	enabled = kunit_kzalloc(test, sizeof(*enabled), GFP_KERNEL);
897 	KUNIT_ASSERT_NOT_ERR_OR_NULL(test, enabled);
898 
899 	atomic_set(enabled, count);
900 	src->num_types = 1;
901 	src->enabled_types = enabled;
902 	src->funcs = &dm_test_crtc_irq_src_funcs;
903 }
904 
905 /*
906  * dm_test_crtc_setup_enable - Build an adev/CRTC primed for the vblank enable path.
907  * @test: The KUnit test context
908  * @adev_out: Receives the allocated device
909  * @dce_version: DCE version stamped on the DC (controls dc_supports_vrr())
910  *
911  * Returns a CRTC whose enable path can run to completion: a configured
912  * (enabled) CRTC with crtc_id 0, an initialized single-pipe vblank array, a DC
913  * with @dce_version, a non-reset reset_domain and a dm_crtc_state carrying a
914  * stream+link. IPS support stays disabled so drm_crtc_vblank_restore() is
915  * skipped, and the IRQ subsystem is left uninstalled for callers to arm.
916  */
917 static struct amdgpu_crtc *
918 dm_test_crtc_setup_enable(struct kunit *test, struct amdgpu_device **adev_out,
919 			  enum dce_version dce_version)
920 {
921 	struct amdgpu_reset_domain *reset_domain;
922 	struct dc_stream_state *stream;
923 	struct dm_crtc_state *dm_state;
924 	struct amdgpu_device *adev;
925 	struct amdgpu_crtc *acrtc;
926 	struct dc_link *link;
927 
928 	adev = dm_kunit_alloc_adev(test);
929 	KUNIT_ASSERT_NOT_ERR_OR_NULL(test, adev);
930 
931 	KUNIT_ASSERT_EQ(test, drm_vblank_init(&adev->ddev, 1), 0);
932 
933 	adev->dm.dc = dm_kunit_alloc_dc_with_ctx(test);
934 	KUNIT_ASSERT_NOT_ERR_OR_NULL(test, adev->dm.dc);
935 	adev->dm.dc->ctx->dce_version = dce_version;
936 
937 	/* crtc_id 0 maps to a valid IRQ type only when a CRTC is registered. */
938 	adev->mode_info.num_crtc = 1;
939 
940 	reset_domain = kunit_kzalloc(test, sizeof(*reset_domain), GFP_KERNEL);
941 	KUNIT_ASSERT_NOT_ERR_OR_NULL(test, reset_domain);
942 	adev->reset_domain = reset_domain;
943 
944 	acrtc = kunit_kzalloc(test, sizeof(*acrtc), GFP_KERNEL);
945 	KUNIT_ASSERT_NOT_ERR_OR_NULL(test, acrtc);
946 	acrtc->base.dev = &adev->ddev;
947 	acrtc->base.enabled = true;
948 	acrtc->crtc_id = 0;
949 
950 	link = dm_kunit_alloc_link(test);
951 	stream = dm_kunit_alloc_stream(test, link);
952 
953 	dm_state = kunit_kzalloc(test, sizeof(*dm_state), GFP_KERNEL);
954 	KUNIT_ASSERT_NOT_ERR_OR_NULL(test, dm_state);
955 	dm_state->stream = stream;
956 	acrtc->base.state = &dm_state->base;
957 
958 	*adev_out = adev;
959 	return acrtc;
960 }
961 
962 /**
963  * dm_test_crtc_enable_vblank_full_path - Test the enable path runs to completion
964  * @test: The KUnit test context
965  *
966  * With a configured CRTC on a VRR-capable DC and both crtc/pageflip IRQ sources
967  * armed, the enable path walks the vupdate-irq branch (VRR active, OTG
968  * unassigned so it returns early), acquires both IRQ references and completes
969  * with no vblank workqueue queued.
970  */
971 static void dm_test_crtc_enable_vblank_full_path(struct kunit *test)
972 {
973 	struct dm_crtc_state *acrtc_state;
974 	struct amdgpu_device *adev;
975 	struct amdgpu_crtc *acrtc;
976 
977 	/* DCE_VERSION_8_0 supports VRR -> the vupdate-irq branch is walked. */
978 	acrtc = dm_test_crtc_setup_enable(test, &adev, DCE_VERSION_8_0);
979 
980 	/* OTG unassigned -> amdgpu_dm_crtc_set_vupdate_irq() returns 0 early. */
981 	acrtc->otg_inst = -1;
982 	/* VRR active so the enable path takes the vupdate-irq branch. */
983 	acrtc_state = to_dm_crtc_state(acrtc->base.state);
984 	acrtc_state->freesync_config.state = VRR_STATE_ACTIVE_VARIABLE;
985 
986 	adev->irq.installed = true;
987 	dm_test_crtc_arm_irq_src(test, &adev->crtc_irq, 1);
988 	dm_test_crtc_arm_irq_src(test, &adev->pageflip_irq, 1);
989 
990 	KUNIT_EXPECT_EQ(test, amdgpu_dm_crtc_enable_vblank(&acrtc->base), 0);
991 }
992 
993 /**
994  * dm_test_crtc_enable_vblank_vupdate_busy - Test vupdate failure aborts enable
995  * @test: The KUnit test context
996  *
997  * When VRR is active and the DC rejects the vupdate IRQ request, the enable
998  * path must propagate the error (-EBUSY) before touching the crtc/pageflip
999  * IRQs.
1000  */
1001 static void dm_test_crtc_enable_vblank_vupdate_busy(struct kunit *test)
1002 {
1003 	struct irq_source_info *info;
1004 	struct resource_pool *res_pool;
1005 	struct dm_crtc_state *acrtc_state;
1006 	struct irq_service *irqs;
1007 	struct amdgpu_device *adev;
1008 	struct amdgpu_crtc *acrtc;
1009 	int i;
1010 
1011 	acrtc = dm_test_crtc_setup_enable(test, &adev, DCE_VERSION_8_0);
1012 
1013 	/* OTG assigned and VRR active so set_vupdate_irq() calls into DC. */
1014 	acrtc->otg_inst = 0;
1015 	acrtc_state = to_dm_crtc_state(acrtc->base.state);
1016 	acrtc_state->freesync_config.state = VRR_STATE_ACTIVE_VARIABLE;
1017 
1018 	res_pool = kunit_kzalloc(test, sizeof(*res_pool), GFP_KERNEL);
1019 	KUNIT_ASSERT_NOT_ERR_OR_NULL(test, res_pool);
1020 	irqs = kunit_kzalloc(test, sizeof(*irqs), GFP_KERNEL);
1021 	KUNIT_ASSERT_NOT_ERR_OR_NULL(test, irqs);
1022 
1023 	/*
1024 	 * Per-source .set fails so amdgpu_dm_irq_set() reports the source busy.
1025 	 */
1026 	info = kunit_kzalloc(test, sizeof(*info) * DAL_IRQ_SOURCES_NUMBER,
1027 			     GFP_KERNEL);
1028 	KUNIT_ASSERT_NOT_ERR_OR_NULL(test, info);
1029 	for (i = 0; i < DAL_IRQ_SOURCES_NUMBER; i++)
1030 		info[i].funcs = &dm_test_vupdate_irq_src_busy_funcs;
1031 
1032 	irqs->info = info;
1033 	res_pool->irqs = irqs;
1034 	adev->dm.dc->res_pool = res_pool;
1035 
1036 	KUNIT_EXPECT_EQ(test,
1037 			amdgpu_dm_crtc_enable_vblank(&acrtc->base), -EBUSY);
1038 }
1039 
1040 /**
1041  * dm_test_crtc_enable_vblank_crtc_irq_error - Test crtc IRQ failure aborts enable
1042  * @test: The KUnit test context
1043  *
1044  * On a non-VRR DC the vupdate-irq branch is skipped. With the IRQ subsystem
1045  * uninstalled, amdgpu_irq_get() on the crtc IRQ returns -ENOENT and the enable
1046  * path must propagate it before touching the pageflip IRQ.
1047  */
1048 static void dm_test_crtc_enable_vblank_crtc_irq_error(struct kunit *test)
1049 {
1050 	struct amdgpu_device *adev;
1051 	struct amdgpu_crtc *acrtc;
1052 
1053 	/* DCE_VERSION_6_0 has no VRR, so the vupdate-irq branch is skipped. */
1054 	acrtc = dm_test_crtc_setup_enable(test, &adev, DCE_VERSION_6_0);
1055 
1056 	/* IRQ subsystem not installed -> amdgpu_irq_get() returns -ENOENT. */
1057 	adev->irq.installed = false;
1058 
1059 	KUNIT_EXPECT_EQ(test,
1060 			amdgpu_dm_crtc_enable_vblank(&acrtc->base), -ENOENT);
1061 }
1062 
1063 /**
1064  * dm_test_crtc_enable_vblank_in_reset - Test enable returns early during GPU reset
1065  * @test: The KUnit test context
1066  *
1067  * After acquiring the IRQ references, an in-progress GPU reset must short the
1068  * enable path so it returns 0 without queuing any vblank control work.
1069  */
1070 static void dm_test_crtc_enable_vblank_in_reset(struct kunit *test)
1071 {
1072 	struct amdgpu_device *adev;
1073 	struct amdgpu_crtc *acrtc;
1074 
1075 	/* DCE_VERSION_6_0 has no VRR, so the vupdate-irq branch is skipped. */
1076 	acrtc = dm_test_crtc_setup_enable(test, &adev, DCE_VERSION_6_0);
1077 
1078 	adev->irq.installed = true;
1079 	dm_test_crtc_arm_irq_src(test, &adev->crtc_irq, 1);
1080 	dm_test_crtc_arm_irq_src(test, &adev->pageflip_irq, 1);
1081 
1082 	/* Mid-reset: return 0 before the vblank workqueue branch is reached. */
1083 	atomic_set(&adev->reset_domain->in_gpu_reset, 1);
1084 
1085 	KUNIT_EXPECT_EQ(test, amdgpu_dm_crtc_enable_vblank(&acrtc->base), 0);
1086 }
1087 
1088 /**
1089  * dm_test_crtc_enable_vblank_queues_work - Test enable queues vblank control work
1090  * @test: The KUnit test context
1091  *
1092  * With a vblank control workqueue installed, the enable path allocates a work
1093  * item, retains the stream and queues the control worker. Draining the queue
1094  * runs the worker, which bumps the active vblank IRQ count. The initial ISM
1095  * state has no EXIT_IDLE_REQUESTED transition, so the worker only exercises the
1096  * vblank accounting (the ISM state machine is covered by its own tests).
1097  */
1098 static void dm_test_crtc_enable_vblank_queues_work(struct kunit *test)
1099 {
1100 	struct dm_crtc_state *acrtc_state;
1101 	struct amdgpu_device *adev;
1102 	struct amdgpu_crtc *acrtc;
1103 
1104 	/* DCE_VERSION_8_0 supports VRR -> the vupdate-irq branch is walked. */
1105 	acrtc = dm_test_crtc_setup_enable(test, &adev, DCE_VERSION_8_0);
1106 
1107 	/* OTG unassigned -> amdgpu_dm_crtc_set_vupdate_irq() returns 0 early. */
1108 	acrtc->otg_inst = -1;
1109 	acrtc_state = to_dm_crtc_state(acrtc->base.state);
1110 	acrtc_state->freesync_config.state = VRR_STATE_ACTIVE_VARIABLE;
1111 
1112 	adev->irq.installed = true;
1113 	dm_test_crtc_arm_irq_src(test, &adev->crtc_irq, 1);
1114 	dm_test_crtc_arm_irq_src(test, &adev->pageflip_irq, 1);
1115 
1116 	/* Real workqueue so the queue_work() branch runs the control worker. */
1117 	mutex_init(&adev->dm.dc_lock);
1118 	adev->dm.vblank_control_workqueue =
1119 		create_singlethread_workqueue("dm_test_vblank");
1120 	KUNIT_ASSERT_NOT_ERR_OR_NULL(test, adev->dm.vblank_control_workqueue);
1121 
1122 	KUNIT_EXPECT_EQ(test, amdgpu_dm_crtc_enable_vblank(&acrtc->base), 0);
1123 
1124 	/* Drain the queued worker before the fixture is torn down, then tidy up. */
1125 	destroy_workqueue(adev->dm.vblank_control_workqueue);
1126 	adev->dm.vblank_control_workqueue = NULL;
1127 
1128 	/* The queued worker ran and accounted the active vblank IRQ. */
1129 	KUNIT_EXPECT_EQ(test, adev->dm.active_vblank_irq_count, 1);
1130 }
1131 
1132 /**
1133  * dm_test_crtc_enable_vblank_ips_restore - Test IPS/self-refresh vblank restore
1134  * @test: The KUnit test context
1135  *
1136  * When the DC advertises IPS support with IPS not fully disabled, self-refresh
1137  * is supported and immediate vblank disable is configured, the enable path must
1138  * call drm_crtc_vblank_restore() to estimate missed vblanks before arming the
1139  * IRQs. The enable path then runs to completion.
1140  */
1141 static void dm_test_crtc_enable_vblank_ips_restore(struct kunit *test)
1142 {
1143 	struct dm_crtc_state *acrtc_state;
1144 	struct drm_vblank_crtc *vblank;
1145 	struct amdgpu_device *adev;
1146 	struct amdgpu_crtc *acrtc;
1147 	struct dc_link *link;
1148 
1149 	/* DCE_VERSION_8_0 supports VRR -> the vupdate-irq branch is walked. */
1150 	acrtc = dm_test_crtc_setup_enable(test, &adev, DCE_VERSION_8_0);
1151 
1152 	/* OTG unassigned -> amdgpu_dm_crtc_set_vupdate_irq() returns 0 early. */
1153 	acrtc->otg_inst = -1;
1154 	acrtc_state = to_dm_crtc_state(acrtc->base.state);
1155 	acrtc_state->freesync_config.state = VRR_STATE_ACTIVE_VARIABLE;
1156 
1157 	/* Non-NULL get_vblank_timestamp keeps drm_crtc_vblank_restore() quiet. */
1158 	acrtc->base.funcs = &dm_test_crtc_funcs;
1159 
1160 	/* IPS enabled and not fully disabled -> first restore condition holds. */
1161 	adev->dm.dc->caps.ips_support = true;
1162 	adev->dm.dc->config.disable_ips = DMUB_IPS_ENABLE;
1163 
1164 	/* Supported PSR version makes self-refresh supported. */
1165 	link = acrtc_state->stream->link;
1166 	link->psr_settings.psr_version = DC_PSR_VERSION_1;
1167 
1168 	/* Immediate vblank disable is the last condition gating the restore. */
1169 	vblank = drm_crtc_vblank_crtc(&acrtc->base);
1170 	vblank->config.disable_immediate = true;
1171 
1172 	adev->irq.installed = true;
1173 	dm_test_crtc_arm_irq_src(test, &adev->crtc_irq, 1);
1174 	dm_test_crtc_arm_irq_src(test, &adev->pageflip_irq, 1);
1175 
1176 	KUNIT_EXPECT_EQ(test, amdgpu_dm_crtc_enable_vblank(&acrtc->base), 0);
1177 }
1178 
1179 /**
1180  * dm_test_crtc_enable_vblank_ips_restore_replay - Test IPS restore via replay support
1181  * @test: The KUnit test context
1182  *
1183  * Same as dm_test_crtc_enable_vblank_ips_restore() but self-refresh support is
1184  * established through replay rather than PSR: the PSR version is unsupported, so
1185  * the sr_supported computation must fall through to pr->config.replay_supported.
1186  * The enable path still calls drm_crtc_vblank_restore() and completes.
1187  */
1188 static void dm_test_crtc_enable_vblank_ips_restore_replay(struct kunit *test)
1189 {
1190 	struct dm_crtc_state *acrtc_state;
1191 	struct drm_vblank_crtc *vblank;
1192 	struct amdgpu_device *adev;
1193 	struct amdgpu_crtc *acrtc;
1194 	struct dc_link *link;
1195 
1196 	/* DCE_VERSION_8_0 supports VRR -> the vupdate-irq branch is walked. */
1197 	acrtc = dm_test_crtc_setup_enable(test, &adev, DCE_VERSION_8_0);
1198 
1199 	/* OTG unassigned -> amdgpu_dm_crtc_set_vupdate_irq() returns 0 early. */
1200 	acrtc->otg_inst = -1;
1201 	acrtc_state = to_dm_crtc_state(acrtc->base.state);
1202 	acrtc_state->freesync_config.state = VRR_STATE_ACTIVE_VARIABLE;
1203 
1204 	/* Non-NULL get_vblank_timestamp keeps drm_crtc_vblank_restore() quiet. */
1205 	acrtc->base.funcs = &dm_test_crtc_funcs;
1206 
1207 	/* IPS enabled and not fully disabled -> first restore condition holds. */
1208 	adev->dm.dc->caps.ips_support = true;
1209 	adev->dm.dc->config.disable_ips = DMUB_IPS_ENABLE;
1210 
1211 	/*
1212 	 * PSR unsupported but replay supported -> sr_supported is driven by the
1213 	 * pr->config.replay_supported side of the OR.
1214 	 */
1215 	link = acrtc_state->stream->link;
1216 	link->psr_settings.psr_version = DC_PSR_VERSION_UNSUPPORTED;
1217 	link->replay_settings.config.replay_supported = true;
1218 
1219 	/* Immediate vblank disable is the last condition gating the restore. */
1220 	vblank = drm_crtc_vblank_crtc(&acrtc->base);
1221 	vblank->config.disable_immediate = true;
1222 
1223 	adev->irq.installed = true;
1224 	dm_test_crtc_arm_irq_src(test, &adev->crtc_irq, 1);
1225 	dm_test_crtc_arm_irq_src(test, &adev->pageflip_irq, 1);
1226 
1227 	KUNIT_EXPECT_EQ(test, amdgpu_dm_crtc_enable_vblank(&acrtc->base), 0);
1228 }
1229 
1230 /* Tests for amdgpu_dm_crtc_update_crtc_active_planes() */
1231 
1232 /**
1233  * dm_test_crtc_update_active_planes_no_stream - Test active plane reset without a stream
1234  * @test: The KUnit test context
1235  *
1236  * Without a DC stream attached the active plane count must be reset to zero
1237  * and the plane-counting path must be skipped.
1238  */
1239 static void dm_test_crtc_update_active_planes_no_stream(struct kunit *test)
1240 {
1241 	struct dm_crtc_state *dm_state;
1242 
1243 	dm_state = kunit_kzalloc(test, sizeof(*dm_state), GFP_KERNEL);
1244 	KUNIT_ASSERT_NOT_ERR_OR_NULL(test, dm_state);
1245 
1246 	dm_state->stream = NULL;
1247 	dm_state->active_planes = 5;
1248 
1249 	amdgpu_dm_crtc_update_crtc_active_planes(NULL, &dm_state->base);
1250 
1251 	KUNIT_EXPECT_EQ(test, dm_state->active_planes, 0);
1252 }
1253 
1254 /* Tests for amdgpu_dm_crtc_count_crtc_active_planes() */
1255 
1256 static void dm_test_add_plane(struct drm_device *dev, struct drm_plane *plane,
1257 			      unsigned int index, enum drm_plane_type type)
1258 {
1259 	INIT_LIST_HEAD(&plane->head);
1260 	plane->index = index;
1261 	plane->type = type;
1262 	list_add_tail(&plane->head, &dev->mode_config.plane_list);
1263 }
1264 
1265 /**
1266  * dm_test_count_crtc_active_planes_none - Test empty plane list counts zero
1267  * @test: The KUnit test context
1268  *
1269  * With no planes attached to the CRTC the active plane count must be zero.
1270  */
1271 static void dm_test_count_crtc_active_planes_none(struct kunit *test)
1272 {
1273 	struct drm_crtc_state *crtc_state;
1274 	struct drm_atomic_commit *state;
1275 	struct drm_device *dev;
1276 
1277 	dev = dm_kunit_alloc_drm_with_connector_list(test);
1278 	KUNIT_ASSERT_NOT_ERR_OR_NULL(test, dev);
1279 	INIT_LIST_HEAD(&dev->mode_config.plane_list);
1280 
1281 	state = kunit_kzalloc(test, sizeof(*state), GFP_KERNEL);
1282 	KUNIT_ASSERT_NOT_ERR_OR_NULL(test, state);
1283 	state->dev = dev;
1284 
1285 	crtc_state = kunit_kzalloc(test, sizeof(*crtc_state), GFP_KERNEL);
1286 	KUNIT_ASSERT_NOT_ERR_OR_NULL(test, crtc_state);
1287 	crtc_state->state = state;
1288 	crtc_state->plane_mask = 0;
1289 
1290 	KUNIT_EXPECT_EQ(test, amdgpu_dm_crtc_count_crtc_active_planes(crtc_state), 0);
1291 }
1292 
1293 /**
1294  * dm_test_count_crtc_active_planes_mixed - Test counting across all plane cases
1295  * @test: The KUnit test context
1296  *
1297  * Exercises every branch of the counting loop: a plane excluded by the mask,
1298  * a cursor plane (skipped), a masked plane with no new state (counted), a
1299  * masked plane with a framebuffer (counted) and a masked plane without a
1300  * framebuffer (not counted). Only two planes should be reported active.
1301  */
1302 static void dm_test_count_crtc_active_planes_mixed(struct kunit *test)
1303 {
1304 	struct drm_plane *plane_no_state;
1305 	struct drm_plane *plane_cursor;
1306 	struct drm_plane *plane_with_fb;
1307 	struct drm_plane *plane_no_fb;
1308 	struct drm_plane *plane_excluded;
1309 	struct drm_plane_state *ps_fb;
1310 	struct drm_plane_state *ps_no_fb;
1311 	struct drm_crtc_state *crtc_state;
1312 	struct drm_atomic_commit *state;
1313 	struct drm_framebuffer *fb;
1314 	struct drm_device *dev;
1315 
1316 	dev = dm_kunit_alloc_drm_with_connector_list(test);
1317 	KUNIT_ASSERT_NOT_ERR_OR_NULL(test, dev);
1318 	INIT_LIST_HEAD(&dev->mode_config.plane_list);
1319 
1320 	plane_no_state = kunit_kzalloc(test, sizeof(*plane_no_state), GFP_KERNEL);
1321 	KUNIT_ASSERT_NOT_ERR_OR_NULL(test, plane_no_state);
1322 	plane_cursor = kunit_kzalloc(test, sizeof(*plane_cursor), GFP_KERNEL);
1323 	KUNIT_ASSERT_NOT_ERR_OR_NULL(test, plane_cursor);
1324 	plane_with_fb = kunit_kzalloc(test, sizeof(*plane_with_fb), GFP_KERNEL);
1325 	KUNIT_ASSERT_NOT_ERR_OR_NULL(test, plane_with_fb);
1326 	plane_no_fb = kunit_kzalloc(test, sizeof(*plane_no_fb), GFP_KERNEL);
1327 	KUNIT_ASSERT_NOT_ERR_OR_NULL(test, plane_no_fb);
1328 	plane_excluded = kunit_kzalloc(test, sizeof(*plane_excluded), GFP_KERNEL);
1329 	KUNIT_ASSERT_NOT_ERR_OR_NULL(test, plane_excluded);
1330 
1331 	dm_test_add_plane(dev, plane_no_state, 0, DRM_PLANE_TYPE_PRIMARY);
1332 	dm_test_add_plane(dev, plane_cursor, 1, DRM_PLANE_TYPE_CURSOR);
1333 	dm_test_add_plane(dev, plane_with_fb, 2, DRM_PLANE_TYPE_PRIMARY);
1334 	dm_test_add_plane(dev, plane_no_fb, 3, DRM_PLANE_TYPE_PRIMARY);
1335 	dm_test_add_plane(dev, plane_excluded, 4, DRM_PLANE_TYPE_PRIMARY);
1336 
1337 	fb = kunit_kzalloc(test, sizeof(*fb), GFP_KERNEL);
1338 	KUNIT_ASSERT_NOT_ERR_OR_NULL(test, fb);
1339 	ps_fb = kunit_kzalloc(test, sizeof(*ps_fb), GFP_KERNEL);
1340 	KUNIT_ASSERT_NOT_ERR_OR_NULL(test, ps_fb);
1341 	ps_fb->fb = fb;
1342 	ps_no_fb = kunit_kzalloc(test, sizeof(*ps_no_fb), GFP_KERNEL);
1343 	KUNIT_ASSERT_NOT_ERR_OR_NULL(test, ps_no_fb);
1344 	ps_no_fb->fb = NULL;
1345 
1346 	state = kunit_kzalloc(test, sizeof(*state), GFP_KERNEL);
1347 	KUNIT_ASSERT_NOT_ERR_OR_NULL(test, state);
1348 	state->dev = dev;
1349 	state->planes = kunit_kzalloc(test, sizeof(*state->planes) * 5, GFP_KERNEL);
1350 	KUNIT_ASSERT_NOT_ERR_OR_NULL(test, state->planes);
1351 	state->planes[0].new_state = NULL;
1352 	state->planes[1].new_state = ps_fb;
1353 	state->planes[2].new_state = ps_fb;
1354 	state->planes[3].new_state = ps_no_fb;
1355 	state->planes[4].new_state = ps_fb;
1356 
1357 	crtc_state = kunit_kzalloc(test, sizeof(*crtc_state), GFP_KERNEL);
1358 	KUNIT_ASSERT_NOT_ERR_OR_NULL(test, crtc_state);
1359 	crtc_state->state = state;
1360 	/* Exclude plane index 4 from the CRTC. */
1361 	crtc_state->plane_mask = BIT(0) | BIT(1) | BIT(2) | BIT(3);
1362 
1363 	KUNIT_EXPECT_EQ(test, amdgpu_dm_crtc_count_crtc_active_planes(crtc_state), 2);
1364 }
1365 
1366 /* Tests for amdgpu_dm_crtc_duplicate_state() */
1367 
1368 /**
1369  * dm_test_crtc_duplicate_state_copies_fields - Test duplicated state carries DM fields
1370  * @test: The KUnit test context
1371  *
1372  * Duplicating a CRTC state without a stream must produce a new state that
1373  * carries over the DM-specific fields from the current state.
1374  */
1375 static void dm_test_crtc_duplicate_state_copies_fields(struct kunit *test)
1376 {
1377 	struct drm_crtc *crtc;
1378 	struct dm_crtc_state *cur;
1379 	struct drm_crtc_state *dup;
1380 	struct dm_crtc_state *dm_dup;
1381 
1382 	crtc = kunit_kzalloc(test, sizeof(*crtc), GFP_KERNEL);
1383 	KUNIT_ASSERT_NOT_ERR_OR_NULL(test, crtc);
1384 	cur = kunit_kzalloc(test, sizeof(*cur), GFP_KERNEL);
1385 	KUNIT_ASSERT_NOT_ERR_OR_NULL(test, cur);
1386 
1387 	cur->abm_level = 3;
1388 	cur->active_planes = 2;
1389 	cur->vrr_supported = true;
1390 	cur->cm_has_degamma = true;
1391 	cur->cm_is_degamma_srgb = true;
1392 	cur->crc_skip_count = 7;
1393 	cur->mpo_requested = true;
1394 	crtc->state = &cur->base;
1395 
1396 	dup = amdgpu_dm_crtc_duplicate_state(crtc);
1397 	KUNIT_ASSERT_NOT_NULL(test, dup);
1398 
1399 	dm_dup = to_dm_crtc_state(dup);
1400 	KUNIT_EXPECT_EQ(test, dm_dup->abm_level, 3);
1401 	KUNIT_EXPECT_EQ(test, dm_dup->active_planes, 2);
1402 	KUNIT_EXPECT_TRUE(test, dm_dup->vrr_supported);
1403 	KUNIT_EXPECT_TRUE(test, dm_dup->cm_has_degamma);
1404 	KUNIT_EXPECT_TRUE(test, dm_dup->cm_is_degamma_srgb);
1405 	KUNIT_EXPECT_EQ(test, dm_dup->crc_skip_count, 7);
1406 	KUNIT_EXPECT_TRUE(test, dm_dup->mpo_requested);
1407 
1408 	amdgpu_dm_crtc_destroy_state(crtc, dup);
1409 }
1410 
1411 /* Tests for amdgpu_dm_crtc_reset_state() */
1412 
1413 /**
1414  * dm_test_crtc_reset_state_allocates_state - Test reset installs a fresh state
1415  * @test: The KUnit test context
1416  *
1417  * Resetting a CRTC with no existing state must allocate and install a new
1418  * drm_crtc_state.
1419  */
1420 static void dm_test_crtc_reset_state_allocates_state(struct kunit *test)
1421 {
1422 	struct amdgpu_device *adev = dm_kunit_alloc_adev(test);
1423 	struct drm_crtc *crtc;
1424 
1425 	crtc = kunit_kzalloc(test, sizeof(*crtc), GFP_KERNEL);
1426 	KUNIT_ASSERT_NOT_ERR_OR_NULL(test, crtc);
1427 	crtc->dev = &adev->ddev;
1428 	crtc->state = NULL;
1429 
1430 	amdgpu_dm_crtc_reset_state(crtc);
1431 
1432 	KUNIT_EXPECT_NOT_NULL(test, crtc->state);
1433 
1434 	if (crtc->state)
1435 		amdgpu_dm_crtc_destroy_state(crtc, crtc->state);
1436 }
1437 
1438 /* Tests for amdgpu_dm_crtc_destroy_state() */
1439 
1440 /**
1441  * dm_test_crtc_destroy_state_no_stream - Test destroy frees a stream-less state
1442  * @test: The KUnit test context
1443  *
1444  * Destroying a CRTC state with no stream attached must free the state without
1445  * attempting to release a DC stream.
1446  */
1447 static void dm_test_crtc_destroy_state_no_stream(struct kunit *test)
1448 {
1449 	struct dm_crtc_state *dm_state;
1450 
1451 	/* destroy_state kfree()s the state, so use a plain (unmanaged) alloc. */
1452 	dm_state = kzalloc_obj(*dm_state);
1453 	KUNIT_ASSERT_NOT_ERR_OR_NULL(test, dm_state);
1454 
1455 	amdgpu_dm_crtc_destroy_state(NULL, &dm_state->base);
1456 }
1457 
1458 /**
1459  * dm_test_crtc_destroy_state_releases_stream - Test destroy releases the stream
1460  * @test: The KUnit test context
1461  *
1462  * When the CRTC state carries a DC stream, destroying the state must release a
1463  * stream reference. An extra reference is taken up front so the release leaves
1464  * the KUnit-managed reference intact rather than freeing the stream here.
1465  */
1466 static void dm_test_crtc_destroy_state_releases_stream(struct kunit *test)
1467 {
1468 	struct dc_stream_state *stream;
1469 	struct dm_crtc_state *dm_state;
1470 	struct dc_link *link;
1471 
1472 	link = dm_kunit_alloc_link(test);
1473 	stream = dm_kunit_alloc_stream(test, link);
1474 
1475 	/*
1476 	 * Take an extra reference so amdgpu_dm_crtc_destroy_state() drops back to
1477 	 * the KUnit-managed reference instead of freeing the stream.
1478 	 */
1479 	kref_get(&stream->refcount);
1480 
1481 	/* destroy_state kfree()s the state, so use a plain (unmanaged) alloc. */
1482 	dm_state = kzalloc_obj(*dm_state);
1483 	KUNIT_ASSERT_NOT_ERR_OR_NULL(test, dm_state);
1484 	dm_state->stream = stream;
1485 
1486 	amdgpu_dm_crtc_destroy_state(NULL, &dm_state->base);
1487 
1488 	/* One reference was dropped, leaving the KUnit-managed one. */
1489 	KUNIT_EXPECT_EQ(test, kref_read(&stream->refcount), 1);
1490 }
1491 
1492 /**
1493  * dm_test_crtc_handle_vblank_no_event - Test vblank handling with no pending event
1494  * @test: The KUnit test context
1495  *
1496  * With no flip event pending, handling a vblank must complete without sending a
1497  * vblank event and must leave acrtc->event untouched (NULL).
1498  */
1499 static void dm_test_crtc_handle_vblank_no_event(struct kunit *test)
1500 {
1501 	struct amdgpu_device *adev;
1502 	struct amdgpu_crtc *acrtc;
1503 
1504 	adev = dm_kunit_alloc_adev(test);
1505 	KUNIT_ASSERT_NOT_ERR_OR_NULL(test, adev);
1506 
1507 	/* Initialise vblank so drm_crtc_handle_vblank() runs cleanly. */
1508 	KUNIT_ASSERT_EQ(test, drm_vblank_init(&adev->ddev, 1), 0);
1509 
1510 	acrtc = kunit_kzalloc(test, sizeof(*acrtc), GFP_KERNEL);
1511 	KUNIT_ASSERT_NOT_ERR_OR_NULL(test, acrtc);
1512 	acrtc->base.dev = &adev->ddev;
1513 	acrtc->event = NULL;
1514 
1515 	amdgpu_dm_crtc_handle_vblank(acrtc);
1516 
1517 	KUNIT_EXPECT_NULL(test, acrtc->event);
1518 }
1519 
1520 /**
1521  * dm_test_crtc_handle_vblank_skips_when_flip_submitted - Test event kept on submit
1522  * @test: The KUnit test context
1523  *
1524  * A pending event whose flip is still AMDGPU_FLIP_SUBMITTED must not be signalled
1525  * on vblank; acrtc->event must remain set for later completion.
1526  */
1527 static void dm_test_crtc_handle_vblank_skips_when_flip_submitted(struct kunit *test)
1528 {
1529 	struct drm_pending_vblank_event *event;
1530 	struct amdgpu_device *adev;
1531 	struct amdgpu_crtc *acrtc;
1532 
1533 	adev = dm_kunit_alloc_adev(test);
1534 	KUNIT_ASSERT_NOT_ERR_OR_NULL(test, adev);
1535 
1536 	KUNIT_ASSERT_EQ(test, drm_vblank_init(&adev->ddev, 1), 0);
1537 
1538 	acrtc = kunit_kzalloc(test, sizeof(*acrtc), GFP_KERNEL);
1539 	KUNIT_ASSERT_NOT_ERR_OR_NULL(test, acrtc);
1540 	event = kunit_kzalloc(test, sizeof(*event), GFP_KERNEL);
1541 	KUNIT_ASSERT_NOT_ERR_OR_NULL(test, event);
1542 
1543 	acrtc->base.dev = &adev->ddev;
1544 	acrtc->event = event;
1545 	acrtc->pflip_status = AMDGPU_FLIP_SUBMITTED;
1546 
1547 	amdgpu_dm_crtc_handle_vblank(acrtc);
1548 
1549 	/* Flip still in-flight: event must be preserved, not signalled. */
1550 	KUNIT_EXPECT_PTR_EQ(test, acrtc->event, event);
1551 }
1552 
1553 /**
1554  * dm_test_crtc_handle_vblank_completes_cursor_only - Test event sent on vblank
1555  * @test: The KUnit test context
1556  *
1557  * A pending event whose flip is not AMDGPU_FLIP_SUBMITTED (a cursor-only commit)
1558  * must be signalled on vblank: the vblank event is sent, the vblank reference is
1559  * dropped and acrtc->event is cleared.
1560  */
1561 static void dm_test_crtc_handle_vblank_completes_cursor_only(struct kunit *test)
1562 {
1563 	struct drm_pending_vblank_event *event;
1564 	struct amdgpu_device *adev;
1565 	struct amdgpu_crtc *acrtc;
1566 
1567 	adev = dm_kunit_alloc_adev(test);
1568 	KUNIT_ASSERT_NOT_ERR_OR_NULL(test, adev);
1569 
1570 	KUNIT_ASSERT_EQ(test, drm_vblank_init(&adev->ddev, 1), 0);
1571 
1572 	acrtc = kunit_kzalloc(test, sizeof(*acrtc), GFP_KERNEL);
1573 	KUNIT_ASSERT_NOT_ERR_OR_NULL(test, acrtc);
1574 
1575 	/* drm_crtc_send_vblank_event() consumes (kfree()s) the event. */
1576 	event = kzalloc_obj(*event);
1577 	KUNIT_ASSERT_NOT_ERR_OR_NULL(test, event);
1578 
1579 	acrtc->base.dev = &adev->ddev;
1580 	acrtc->event = event;
1581 	acrtc->pflip_status = AMDGPU_FLIP_NONE;
1582 
1583 	/*
1584 	 * Take a vblank reference so the handler's drm_crtc_vblank_put() does not
1585 	 * underflow. Mark vblank enabled so the get succeeds without a hardware
1586 	 * enable hook.
1587 	 */
1588 	adev->ddev.vblank[0].enabled = true;
1589 	KUNIT_ASSERT_EQ(test, drm_crtc_vblank_get(&acrtc->base), 0);
1590 
1591 	amdgpu_dm_crtc_handle_vblank(acrtc);
1592 
1593 	/* Cursor-only commit: event was signalled and cleared. */
1594 	KUNIT_EXPECT_NULL(test, acrtc->event);
1595 }
1596 
1597 /**
1598  * dm_test_vblank_control_worker_setup - Build a vblank_control_work for the worker
1599  * @test: The KUnit test context
1600  * @enable: Value for vblank_work->enable
1601  * @count: Initial dm->active_vblank_irq_count
1602  *
1603  * Returns a work item wired to a freshly allocated adev/crtc/stream. The CRTC is
1604  * left without an atomic state so amdgpu_dm_ism_commit_event() short-circuits and
1605  * only the vblank IRQ accounting in the worker runs.
1606  */
1607 static struct vblank_control_work *
1608 dm_test_vblank_control_worker_setup(struct kunit *test, bool enable,
1609 				    uint32_t count)
1610 {
1611 	struct dc_stream_state *stream;
1612 	struct vblank_control_work *work;
1613 	struct amdgpu_device *adev;
1614 	struct amdgpu_crtc *acrtc;
1615 
1616 	adev = dm_kunit_alloc_adev(test);
1617 	KUNIT_ASSERT_NOT_ERR_OR_NULL(test, adev);
1618 
1619 	mutex_init(&adev->dm.dc_lock);
1620 	adev->dm.dc = dm_kunit_alloc_dc_with_ctx(test);
1621 	KUNIT_ASSERT_NOT_ERR_OR_NULL(test, adev->dm.dc);
1622 	adev->dm.active_vblank_irq_count = count;
1623 
1624 	acrtc = kunit_kzalloc(test, sizeof(*acrtc), GFP_KERNEL);
1625 	KUNIT_ASSERT_NOT_ERR_OR_NULL(test, acrtc);
1626 	acrtc->base.dev = &adev->ddev;
1627 	acrtc->base.state = NULL;
1628 
1629 	stream = dm_kunit_alloc_stream(test, NULL);
1630 	KUNIT_ASSERT_NOT_ERR_OR_NULL(test, stream);
1631 	/* Worker releases the stream; keep an extra ref so kunit owns the free. */
1632 	kref_get(&stream->refcount);
1633 
1634 	/* Worker kfree()s the work item, so it must be a plain allocation. */
1635 	work = kzalloc_obj(*work);
1636 	KUNIT_ASSERT_NOT_ERR_OR_NULL(test, work);
1637 	work->dm = &adev->dm;
1638 	work->acrtc = acrtc;
1639 	work->stream = stream;
1640 	work->enable = enable;
1641 
1642 	return work;
1643 }
1644 
1645 /**
1646  * dm_test_vblank_control_worker_enable_increments - Test enable bumps IRQ count
1647  * @test: The KUnit test context
1648  *
1649  * Running the worker with enable set must increment the active vblank IRQ count.
1650  */
1651 static void dm_test_vblank_control_worker_enable_increments(struct kunit *test)
1652 {
1653 	struct vblank_control_work *work;
1654 	struct amdgpu_display_manager *dm;
1655 
1656 	work = dm_test_vblank_control_worker_setup(test, true, 0);
1657 	dm = work->dm;
1658 
1659 	amdgpu_dm_crtc_vblank_control_worker(&work->work);
1660 
1661 	KUNIT_EXPECT_EQ(test, dm->active_vblank_irq_count, 1);
1662 }
1663 
1664 /**
1665  * dm_test_vblank_control_worker_disable_decrements - Test disable drops IRQ count
1666  * @test: The KUnit test context
1667  *
1668  * Running the worker with enable clear must decrement a non-zero active vblank
1669  * IRQ count.
1670  */
1671 static void dm_test_vblank_control_worker_disable_decrements(struct kunit *test)
1672 {
1673 	struct vblank_control_work *work;
1674 	struct amdgpu_display_manager *dm;
1675 
1676 	work = dm_test_vblank_control_worker_setup(test, false, 2);
1677 	dm = work->dm;
1678 
1679 	amdgpu_dm_crtc_vblank_control_worker(&work->work);
1680 
1681 	KUNIT_EXPECT_EQ(test, dm->active_vblank_irq_count, 1);
1682 }
1683 
1684 /**
1685  * dm_test_vblank_control_worker_disable_clamps_zero - Test disable clamps at zero
1686  * @test: The KUnit test context
1687  *
1688  * Disabling when the active vblank IRQ count is already zero must not underflow.
1689  */
1690 static void dm_test_vblank_control_worker_disable_clamps_zero(struct kunit *test)
1691 {
1692 	struct vblank_control_work *work;
1693 	struct amdgpu_display_manager *dm;
1694 
1695 	work = dm_test_vblank_control_worker_setup(test, false, 0);
1696 	dm = work->dm;
1697 
1698 	amdgpu_dm_crtc_vblank_control_worker(&work->work);
1699 
1700 	KUNIT_EXPECT_EQ(test, dm->active_vblank_irq_count, 0);
1701 }
1702 
1703 /**
1704  * dm_test_crtc_disable_vblank_no_irq_installed - Test disable with IRQ uninstalled
1705  * @test: The KUnit test context
1706  *
1707  * Disabling vblank walks amdgpu_dm_crtc_set_vblank()'s disable path. With the
1708  * IRQ subsystem not installed, amdgpu_irq_put() returns early so the routine
1709  * completes without touching the vblank workqueue or the active IRQ count.
1710  */
1711 static void dm_test_crtc_disable_vblank_no_irq_installed(struct kunit *test)
1712 {
1713 	struct amdgpu_device *adev;
1714 	struct amdgpu_crtc *acrtc;
1715 
1716 	adev = dm_kunit_alloc_adev(test);
1717 	KUNIT_ASSERT_NOT_ERR_OR_NULL(test, adev);
1718 
1719 	adev->dm.dc = dm_kunit_alloc_dc_with_ctx(test);
1720 	KUNIT_ASSERT_NOT_ERR_OR_NULL(test, adev->dm.dc);
1721 	/* DCE_VERSION_6_0 has no VRR, so the vupdate-irq branch is skipped. */
1722 	adev->dm.dc->ctx->dce_version = DCE_VERSION_6_0;
1723 	adev->dm.active_vblank_irq_count = 0;
1724 
1725 	/* No CRTCs registered and IRQs not installed -> irq_put returns early. */
1726 	adev->mode_info.num_crtc = 0;
1727 	adev->irq.installed = false;
1728 
1729 	acrtc = kunit_kzalloc(test, sizeof(*acrtc), GFP_KERNEL);
1730 	KUNIT_ASSERT_NOT_ERR_OR_NULL(test, acrtc);
1731 	acrtc->base.dev = &adev->ddev;
1732 	acrtc->crtc_id = 0;
1733 
1734 	amdgpu_dm_crtc_disable_vblank(&acrtc->base);
1735 
1736 	KUNIT_EXPECT_EQ(test, adev->dm.active_vblank_irq_count, 0);
1737 }
1738 
1739 /**
1740  * dm_test_crtc_disable_vblank_vrr - Test disable path releases IRQs on a VRR DC
1741  * @test: The KUnit test context
1742  *
1743  * On a VRR-capable DC the disable path turns the vupdate IRQ off (OTG
1744  * unassigned so it returns early), releases the armed crtc and pageflip IRQ
1745  * references and completes without queuing vblank control work.
1746  */
1747 static void dm_test_crtc_disable_vblank_vrr(struct kunit *test)
1748 {
1749 	struct amdgpu_reset_domain *reset_domain;
1750 	struct amdgpu_device *adev;
1751 	struct amdgpu_crtc *acrtc;
1752 
1753 	adev = dm_kunit_alloc_adev(test);
1754 	KUNIT_ASSERT_NOT_ERR_OR_NULL(test, adev);
1755 
1756 	adev->dm.dc = dm_kunit_alloc_dc_with_ctx(test);
1757 	KUNIT_ASSERT_NOT_ERR_OR_NULL(test, adev->dm.dc);
1758 	/* DCE_VERSION_8_0 supports VRR -> the vupdate-irq branch is walked. */
1759 	adev->dm.dc->ctx->dce_version = DCE_VERSION_8_0;
1760 
1761 	adev->mode_info.num_crtc = 1;
1762 	adev->irq.installed = true;
1763 
1764 	reset_domain = kunit_kzalloc(test, sizeof(*reset_domain), GFP_KERNEL);
1765 	KUNIT_ASSERT_NOT_ERR_OR_NULL(test, reset_domain);
1766 	adev->reset_domain = reset_domain;
1767 
1768 	/* Seed with 2 so amdgpu_irq_put() drops to a non-zero refcount. */
1769 	dm_test_crtc_arm_irq_src(test, &adev->crtc_irq, 2);
1770 	dm_test_crtc_arm_irq_src(test, &adev->pageflip_irq, 2);
1771 
1772 	acrtc = kunit_kzalloc(test, sizeof(*acrtc), GFP_KERNEL);
1773 	KUNIT_ASSERT_NOT_ERR_OR_NULL(test, acrtc);
1774 	acrtc->base.dev = &adev->ddev;
1775 	acrtc->crtc_id = 0;
1776 	/* OTG unassigned -> amdgpu_dm_crtc_set_vupdate_irq() returns 0 early. */
1777 	acrtc->otg_inst = -1;
1778 
1779 	amdgpu_dm_crtc_disable_vblank(&acrtc->base);
1780 
1781 	/* Both IRQ references were released without underflow. */
1782 	KUNIT_EXPECT_EQ(test, atomic_read(&adev->crtc_irq.enabled_types[0]), 1);
1783 	KUNIT_EXPECT_EQ(test, atomic_read(&adev->pageflip_irq.enabled_types[0]), 1);
1784 }
1785 
1786 /**
1787  * dm_test_crtc_disable_vblank_queues_work - Test disable queues work without a stream
1788  * @test: The KUnit test context
1789  *
1790  * With a vblank control workqueue installed and a CRTC state carrying no
1791  * stream, the disable path queues the control worker without retaining a
1792  * stream. Draining the queue runs the worker, which drops the active vblank IRQ
1793  * count. The ISM is seeded in a state with no ENTER_IDLE_REQUESTED transition
1794  * so the worker only exercises the vblank accounting.
1795  */
1796 static void dm_test_crtc_disable_vblank_queues_work(struct kunit *test)
1797 {
1798 	struct amdgpu_reset_domain *reset_domain;
1799 	struct dm_crtc_state *dm_state;
1800 	struct amdgpu_device *adev;
1801 	struct amdgpu_crtc *acrtc;
1802 
1803 	adev = dm_kunit_alloc_adev(test);
1804 	KUNIT_ASSERT_NOT_ERR_OR_NULL(test, adev);
1805 
1806 	adev->dm.dc = dm_kunit_alloc_dc_with_ctx(test);
1807 	KUNIT_ASSERT_NOT_ERR_OR_NULL(test, adev->dm.dc);
1808 	/* DCE_VERSION_6_0 has no VRR, so the vupdate-irq branch is skipped. */
1809 	adev->dm.dc->ctx->dce_version = DCE_VERSION_6_0;
1810 	adev->dm.active_vblank_irq_count = 2;
1811 
1812 	adev->mode_info.num_crtc = 1;
1813 	adev->irq.installed = true;
1814 
1815 	reset_domain = kunit_kzalloc(test, sizeof(*reset_domain), GFP_KERNEL);
1816 	KUNIT_ASSERT_NOT_ERR_OR_NULL(test, reset_domain);
1817 	adev->reset_domain = reset_domain;
1818 
1819 	/* Seed with 2 so amdgpu_irq_put() drops to a non-zero refcount. */
1820 	dm_test_crtc_arm_irq_src(test, &adev->crtc_irq, 2);
1821 	dm_test_crtc_arm_irq_src(test, &adev->pageflip_irq, 2);
1822 
1823 	acrtc = kunit_kzalloc(test, sizeof(*acrtc), GFP_KERNEL);
1824 	KUNIT_ASSERT_NOT_ERR_OR_NULL(test, acrtc);
1825 	acrtc->base.dev = &adev->ddev;
1826 	acrtc->crtc_id = 0;
1827 	acrtc->otg_inst = -1;
1828 	/*
1829 	 * Seed the ISM in a state where ENTER_IDLE_REQUESTED does not transition
1830 	 * so the worker skips the ISM power-state dispatch and its timers.
1831 	 */
1832 	acrtc->ism.current_state = DM_ISM_STATE_HYSTERESIS_WAITING;
1833 
1834 	/* CRTC state with no stream -> the stream-retain branch is skipped. */
1835 	dm_state = kunit_kzalloc(test, sizeof(*dm_state), GFP_KERNEL);
1836 	KUNIT_ASSERT_NOT_ERR_OR_NULL(test, dm_state);
1837 	acrtc->base.state = &dm_state->base;
1838 
1839 	/* Real workqueue so the queue_work() branch runs the control worker. */
1840 	mutex_init(&adev->dm.dc_lock);
1841 	adev->dm.vblank_control_workqueue =
1842 		create_singlethread_workqueue("dm_test_vblank");
1843 	KUNIT_ASSERT_NOT_ERR_OR_NULL(test, adev->dm.vblank_control_workqueue);
1844 
1845 	amdgpu_dm_crtc_disable_vblank(&acrtc->base);
1846 
1847 	/* Drain the queued worker before the fixture is torn down, then tidy up. */
1848 	destroy_workqueue(adev->dm.vblank_control_workqueue);
1849 	adev->dm.vblank_control_workqueue = NULL;
1850 
1851 	/* The queued worker ran and decremented the active vblank IRQ count. */
1852 	KUNIT_EXPECT_EQ(test, adev->dm.active_vblank_irq_count, 1);
1853 }
1854 
1855 static struct kunit_case amdgpu_dm_crtc_tests[] = {
1856 	/* amdgpu_dm_crtc_modeset_required */
1857 	KUNIT_CASE(dm_test_crtc_modeset_required_active_mode_changed),
1858 	KUNIT_CASE(dm_test_crtc_modeset_required_active_active_changed),
1859 	KUNIT_CASE(dm_test_crtc_modeset_required_active_connectors_changed),
1860 	KUNIT_CASE(dm_test_crtc_modeset_required_inactive),
1861 	KUNIT_CASE(dm_test_crtc_modeset_required_no_changes),
1862 	/* amdgpu_dm_crtc_vrr_active_irq */
1863 	KUNIT_CASE(dm_test_crtc_vrr_active_irq_variable),
1864 	KUNIT_CASE(dm_test_crtc_vrr_active_irq_fixed),
1865 	KUNIT_CASE(dm_test_crtc_vrr_active_irq_inactive),
1866 	KUNIT_CASE(dm_test_crtc_vrr_active_irq_disabled),
1867 	KUNIT_CASE(dm_test_crtc_vrr_active_irq_unsupported),
1868 	/* amdgpu_dm_crtc_vrr_active */
1869 	KUNIT_CASE(dm_test_crtc_vrr_active_variable),
1870 	KUNIT_CASE(dm_test_crtc_vrr_active_fixed),
1871 	KUNIT_CASE(dm_test_crtc_vrr_active_inactive),
1872 	KUNIT_CASE(dm_test_crtc_vrr_active_disabled),
1873 	KUNIT_CASE(dm_test_crtc_vrr_active_unsupported),
1874 	/* amdgpu_dm_is_headless */
1875 	KUNIT_CASE(dm_test_crtc_is_headless_null_adev),
1876 	KUNIT_CASE(dm_test_crtc_is_headless_no_connectors),
1877 	KUNIT_CASE(dm_test_crtc_is_headless_writeback_only),
1878 	KUNIT_CASE(dm_test_crtc_is_headless_disconnected_display),
1879 	KUNIT_CASE(dm_test_crtc_is_headless_connected_display),
1880 	KUNIT_CASE(dm_test_crtc_is_headless_mixed_connectors),
1881 	/* amdgpu_dm_crtc_helper_mode_fixup */
1882 	KUNIT_CASE(dm_test_crtc_helper_mode_fixup_returns_true),
1883 	/* amdgpu_dm_crtc_set_vupdate_irq */
1884 	KUNIT_CASE(dm_test_crtc_set_vupdate_irq_no_otg),
1885 	KUNIT_CASE(dm_test_crtc_set_vupdate_irq_dc_busy),
1886 	KUNIT_CASE(dm_test_crtc_set_vupdate_irq_enable),
1887 	/* idle_create_workqueue */
1888 	KUNIT_CASE(dm_test_idle_create_workqueue),
1889 	/* amdgpu_dm_idle_worker */
1890 	KUNIT_CASE(dm_test_idle_worker_disabled_clears_running),
1891 	KUNIT_CASE(dm_test_idle_worker_enabled_breaks_when_idle_disallowed),
1892 	KUNIT_CASE(dm_test_idle_worker_enabled_breaks_when_not_headless),
1893 	KUNIT_CASE(dm_test_idle_worker_enabled_runs_body),
1894 	/* amdgpu_dm_crtc_set_static_screen_optimze */
1895 	KUNIT_CASE(dm_test_crtc_set_static_screen_optimze_no_sr_entry),
1896 	KUNIT_CASE(dm_test_crtc_set_static_screen_optimze_sr_entry_psr),
1897 	KUNIT_CASE(dm_test_crtc_set_static_screen_optimze_psr_su_skips),
1898 	/* amdgpu_dm_crtc_enable_vblank */
1899 	KUNIT_CASE(dm_test_crtc_enable_vblank_rejects_unconfigured),
1900 	KUNIT_CASE(dm_test_crtc_enable_vblank_full_path),
1901 	KUNIT_CASE(dm_test_crtc_enable_vblank_vupdate_busy),
1902 	KUNIT_CASE(dm_test_crtc_enable_vblank_crtc_irq_error),
1903 	KUNIT_CASE(dm_test_crtc_enable_vblank_in_reset),
1904 	KUNIT_CASE(dm_test_crtc_enable_vblank_queues_work),
1905 	KUNIT_CASE(dm_test_crtc_enable_vblank_ips_restore),
1906 	KUNIT_CASE(dm_test_crtc_enable_vblank_ips_restore_replay),
1907 	/* amdgpu_dm_crtc_update_crtc_active_planes */
1908 	KUNIT_CASE(dm_test_crtc_update_active_planes_no_stream),
1909 	/* amdgpu_dm_crtc_count_crtc_active_planes */
1910 	KUNIT_CASE(dm_test_count_crtc_active_planes_none),
1911 	KUNIT_CASE(dm_test_count_crtc_active_planes_mixed),
1912 	/* amdgpu_dm_crtc_duplicate_state */
1913 	KUNIT_CASE(dm_test_crtc_duplicate_state_copies_fields),
1914 	/* amdgpu_dm_crtc_reset_state */
1915 	KUNIT_CASE(dm_test_crtc_reset_state_allocates_state),
1916 	/* amdgpu_dm_crtc_destroy_state */
1917 	KUNIT_CASE(dm_test_crtc_destroy_state_no_stream),
1918 	KUNIT_CASE(dm_test_crtc_destroy_state_releases_stream),
1919 	/* amdgpu_dm_crtc_handle_vblank */
1920 	KUNIT_CASE(dm_test_crtc_handle_vblank_no_event),
1921 	KUNIT_CASE(dm_test_crtc_handle_vblank_skips_when_flip_submitted),
1922 	KUNIT_CASE(dm_test_crtc_handle_vblank_completes_cursor_only),
1923 	/* amdgpu_dm_crtc_vblank_control_worker */
1924 	KUNIT_CASE(dm_test_vblank_control_worker_enable_increments),
1925 	KUNIT_CASE(dm_test_vblank_control_worker_disable_decrements),
1926 	KUNIT_CASE(dm_test_vblank_control_worker_disable_clamps_zero),
1927 	/* amdgpu_dm_crtc_disable_vblank */
1928 	KUNIT_CASE(dm_test_crtc_disable_vblank_no_irq_installed),
1929 	KUNIT_CASE(dm_test_crtc_disable_vblank_vrr),
1930 	KUNIT_CASE(dm_test_crtc_disable_vblank_queues_work),
1931 	{}
1932 };
1933 
1934 static struct kunit_suite amdgpu_dm_crtc_test_suite = {
1935 	.name = "amdgpu_dm_crtc",
1936 	.test_cases = amdgpu_dm_crtc_tests,
1937 };
1938 
1939 kunit_test_suite(amdgpu_dm_crtc_test_suite);
1940 
1941 MODULE_AUTHOR("AMD");
1942 MODULE_DESCRIPTION("KUnit tests for amdgpu_dm_crtc");
1943 MODULE_LICENSE("Dual MIT/GPL");
1944