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 */
dm_test_crtc_modeset_required_active_mode_changed(struct kunit * test)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 */
dm_test_crtc_modeset_required_active_active_changed(struct kunit * test)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 */
dm_test_crtc_modeset_required_active_connectors_changed(struct kunit * test)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 */
dm_test_crtc_modeset_required_inactive(struct kunit * test)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 */
dm_test_crtc_modeset_required_no_changes(struct kunit * test)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 */
dm_test_crtc_vrr_active_irq_variable(struct kunit * test)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 */
dm_test_crtc_vrr_active_irq_fixed(struct kunit * test)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 */
dm_test_crtc_vrr_active_irq_inactive(struct kunit * test)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 */
dm_test_crtc_vrr_active_irq_disabled(struct kunit * test)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 */
dm_test_crtc_vrr_active_irq_unsupported(struct kunit * test)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 */
dm_test_crtc_vrr_active_variable(struct kunit * test)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 */
dm_test_crtc_vrr_active_fixed(struct kunit * test)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 */
dm_test_crtc_vrr_active_inactive(struct kunit * test)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 */
dm_test_crtc_vrr_active_disabled(struct kunit * test)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 */
dm_test_crtc_vrr_active_unsupported(struct kunit * test)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
dm_test_add_connector(struct drm_device * dev,struct drm_connector * connector,int connector_type,enum drm_connector_status status)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 */
dm_test_crtc_is_headless_null_adev(struct kunit * test)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 */
dm_test_crtc_is_headless_no_connectors(struct kunit * test)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 */
dm_test_crtc_is_headless_writeback_only(struct kunit * test)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 */
dm_test_crtc_is_headless_disconnected_display(struct kunit * test)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 */
dm_test_crtc_is_headless_connected_display(struct kunit * test)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 */
dm_test_crtc_is_headless_mixed_connectors(struct kunit * test)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 */
dm_test_crtc_helper_mode_fixup_returns_true(struct kunit * test)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 */
dm_test_crtc_set_vupdate_irq_no_otg(struct kunit * test)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 */
dm_test_crtc_set_vupdate_irq_dc_busy(struct kunit * test)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. */
dm_test_vupdate_irq_src_set(struct irq_service * irq_service,const struct irq_source_info * info,bool enable)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
dm_test_vupdate_irq_src_ack(struct irq_service * irq_service,const struct irq_source_info * info)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. */
dm_test_vupdate_irq_src_set_busy(struct irq_service * irq_service,const struct irq_source_info * info,bool enable)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 */
dm_test_crtc_set_vupdate_irq_enable(struct kunit * test)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 */
dm_test_idle_create_workqueue(struct kunit * test)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 */
dm_test_idle_worker_disabled_clears_running(struct kunit * test)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 */
dm_test_idle_worker_enabled_breaks_when_idle_disallowed(struct kunit * test)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 */
dm_test_idle_worker_enabled_breaks_when_not_headless(struct kunit * test)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 */
dm_test_idle_apply_flip(struct dc * dc,bool enable)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 */
dm_test_idle_worker_enabled_runs_body(struct kunit * test)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 */
dm_test_crtc_set_static_screen_optimze_no_sr_entry(struct kunit * test)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 */
dm_test_crtc_set_static_screen_optimze_sr_entry_psr(struct kunit * test)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 */
dm_test_crtc_set_static_screen_optimze_psr_su_skips(struct kunit * test)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 */
dm_test_crtc_enable_vblank_rejects_unconfigured(struct kunit * test)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. */
dm_test_crtc_irq_src_set(struct amdgpu_device * adev,struct amdgpu_irq_src * source,unsigned int type,enum amdgpu_interrupt_state state)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 */
dm_test_crtc_get_vblank_timestamp(struct drm_crtc * crtc,int * max_error,ktime_t * vblank_time,bool in_vblank_irq)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 */
dm_test_crtc_arm_irq_src(struct kunit * test,struct amdgpu_irq_src * src,int count)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 *
dm_test_crtc_setup_enable(struct kunit * test,struct amdgpu_device ** adev_out,enum dce_version dce_version)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 */
dm_test_crtc_enable_vblank_full_path(struct kunit * test)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 */
dm_test_crtc_enable_vblank_vupdate_busy(struct kunit * test)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 */
dm_test_crtc_enable_vblank_crtc_irq_error(struct kunit * test)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 */
dm_test_crtc_enable_vblank_in_reset(struct kunit * test)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 */
dm_test_crtc_enable_vblank_queues_work(struct kunit * test)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 */
dm_test_crtc_enable_vblank_ips_restore(struct kunit * test)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 */
dm_test_crtc_enable_vblank_ips_restore_replay(struct kunit * test)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 */
dm_test_crtc_update_active_planes_no_stream(struct kunit * test)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
dm_test_add_plane(struct drm_device * dev,struct drm_plane * plane,unsigned int index,enum drm_plane_type type)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 */
dm_test_count_crtc_active_planes_none(struct kunit * test)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 */
dm_test_count_crtc_active_planes_mixed(struct kunit * test)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 */
dm_test_crtc_duplicate_state_copies_fields(struct kunit * test)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 */
dm_test_crtc_reset_state_allocates_state(struct kunit * test)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 */
dm_test_crtc_destroy_state_no_stream(struct kunit * test)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 */
dm_test_crtc_destroy_state_releases_stream(struct kunit * test)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 */
dm_test_crtc_handle_vblank_no_event(struct kunit * test)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 */
dm_test_crtc_handle_vblank_skips_when_flip_submitted(struct kunit * test)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 */
dm_test_crtc_handle_vblank_completes_cursor_only(struct kunit * test)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 *
dm_test_vblank_control_worker_setup(struct kunit * test,bool enable,uint32_t count)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 */
dm_test_vblank_control_worker_enable_increments(struct kunit * test)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 */
dm_test_vblank_control_worker_disable_decrements(struct kunit * test)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 */
dm_test_vblank_control_worker_disable_clamps_zero(struct kunit * test)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 */
dm_test_crtc_disable_vblank_no_irq_installed(struct kunit * test)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 */
dm_test_crtc_disable_vblank_vrr(struct kunit * test)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 */
dm_test_crtc_disable_vblank_queues_work(struct kunit * test)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