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