xref: /linux/drivers/gpu/drm/amd/display/amdgpu_dm/tests/amdgpu_dm_irq_test.c (revision 40288c9206c17eb66a603262e06a58d300d0f279)
1 // SPDX-License-Identifier: GPL-2.0 OR MIT
2 /*
3  * KUnit tests for amdgpu_dm_irq.c
4  *
5  * Copyright 2026 Advanced Micro Devices, Inc.
6  */
7 
8 #include <kunit/test.h>
9 #include <drm/drm_kunit_helpers.h>
10 #include <drm/drm_atomic_helper.h>
11 #include <drm/drm_probe_helper.h>
12 
13 #include "dc.h"
14 #include "inc/core_types.h"
15 #include "irq/irq_service.h"
16 #include "amdgpu.h"
17 #include "amdgpu_mode.h"
18 #include "amdgpu_dm.h"
19 #include "amdgpu_dm_irq.h"
20 #include "amdgpu_dm_kunit_test_helpers.h"
21 #include "dc_dmub_srv.h"
22 #include "ivsrcid/ivsrcid_vislands30.h"
23 #include "ivsrcid/dcn/irqsrcs_dcn_1_0.h"
24 #include "link_service.h"
25 #include "dmub/dmub_srv.h"
26 #include "dal_asic_id.h"
27 #include "../../amdgpu/amdgpu_reset.h"
28 
dm_test_irq_handler(void * arg)29 static void dm_test_irq_handler(void *arg)
30 {
31 }
32 
dm_test_irq_handler_alt(void * arg)33 static void dm_test_irq_handler_alt(void *arg)
34 {
35 }
36 
dm_test_irq_handler_count(void * arg)37 static void dm_test_irq_handler_count(void *arg)
38 {
39 	int *count = arg;
40 
41 	if (count)
42 		(*count)++;
43 }
44 
dm_test_detect_connection_none(struct dc_link * link,enum dc_connection_type * type)45 static bool dm_test_detect_connection_none(struct dc_link *link,
46 					   enum dc_connection_type *type)
47 {
48 	*type = dc_connection_none;
49 
50 	return true;
51 }
52 
dm_test_detect_link_false(struct dc_link * link,enum dc_detect_reason reason)53 static bool dm_test_detect_link_false(struct dc_link *link,
54 				      enum dc_detect_reason reason)
55 {
56 	return false;
57 }
58 
dm_test_detect_connection_single(struct dc_link * link,enum dc_connection_type * type)59 static bool dm_test_detect_connection_single(struct dc_link *link,
60 					     enum dc_connection_type *type)
61 {
62 	*type = dc_connection_single;
63 
64 	return true;
65 }
66 
67 /* Recording stubs for the dm_handle_hpd_rx_offload_work() DP-IRQ branches. */
68 static int dm_test_automated_test_count;
69 static int dm_test_handle_link_loss_count;
70 
dm_test_dp_handle_automated_test(struct dc_link * link)71 static void dm_test_dp_handle_automated_test(struct dc_link *link)
72 {
73 	dm_test_automated_test_count++;
74 }
75 
dm_test_dp_handle_link_loss(struct dc_link * link)76 static void dm_test_dp_handle_link_loss(struct dc_link *link)
77 {
78 	dm_test_handle_link_loss_count++;
79 }
80 
dm_test_dp_parse_link_loss_true(struct dc_link * link,union hpd_irq_data * hpd_irq_dpcd_data)81 static bool dm_test_dp_parse_link_loss_true(struct dc_link *link,
82 					    union hpd_irq_data *hpd_irq_dpcd_data)
83 {
84 	return true;
85 }
86 
dm_test_dp_should_allow_hpd_rx_irq_true(const struct dc_link * link)87 static bool dm_test_dp_should_allow_hpd_rx_irq_true(const struct dc_link *link)
88 {
89 	return true;
90 }
91 
dm_test_dp_read_hpd_rx_irq_data_ok(struct dc_link * link,union hpd_irq_data * irq_data)92 static enum dc_status dm_test_dp_read_hpd_rx_irq_data_ok(struct dc_link *link,
93 							 union hpd_irq_data *irq_data)
94 {
95 	return DC_OK;
96 }
97 
98 /*
99  * Allocate a refcounted dc_sink for tests without pulling in the DC-core
100  * dc_sink_create()/dc_sink_release() symbols. Production code under test still
101  * uses dc_sink_retain()/dc_sink_release() (resolved inside the amdgpu module).
102  * Use kzalloc (not kunit_kzalloc) so the final kref_put frees it exactly once.
103  */
dm_test_sink_create(struct dc_link * link)104 static struct dc_sink *dm_test_sink_create(struct dc_link *link)
105 {
106 	struct dc_sink *sink = kzalloc_obj(*sink);
107 
108 	if (!sink)
109 		return NULL;
110 
111 	sink->link = link;
112 	sink->ctx = link->ctx;
113 	kref_init(&sink->refcount);
114 
115 	return sink;
116 }
117 
dm_test_sink_free(struct kref * kref)118 static void dm_test_sink_free(struct kref *kref)
119 {
120 	struct dc_sink *sink = container_of(kref, struct dc_sink, refcount);
121 
122 	kfree(sink->dc_container_id);
123 	kfree(sink);
124 }
125 
dm_test_sink_release(struct dc_sink * sink)126 static void dm_test_sink_release(struct dc_sink *sink)
127 {
128 	kref_put(&sink->refcount, dm_test_sink_free);
129 }
130 
dm_test_handle_hpd_rx_no_work(struct dc_link * link,union hpd_irq_data * hpd_irq_data,bool * link_loss,bool defer_handling,bool * has_left_work)131 static bool dm_test_handle_hpd_rx_no_work(struct dc_link *link,
132 					  union hpd_irq_data *hpd_irq_data,
133 					  bool *link_loss,
134 					  bool defer_handling,
135 					  bool *has_left_work)
136 {
137 	*link_loss = false;
138 	*has_left_work = false;
139 
140 	return false;
141 }
142 
dm_test_handle_hpd_rx_automated(struct dc_link * link,union hpd_irq_data * hpd_irq_data,bool * link_loss,bool defer_handling,bool * has_left_work)143 static bool dm_test_handle_hpd_rx_automated(struct dc_link *link,
144 					    union hpd_irq_data *hpd_irq_data,
145 					    bool *link_loss,
146 					    bool defer_handling,
147 					    bool *has_left_work)
148 {
149 	*link_loss = false;
150 	*has_left_work = true;
151 	hpd_irq_data->bytes.device_service_irq.bits.AUTOMATED_TEST = 1;
152 
153 	return false;
154 }
155 
dm_test_handle_hpd_rx_msg_rdy(struct dc_link * link,union hpd_irq_data * hpd_irq_data,bool * link_loss,bool defer_handling,bool * has_left_work)156 static bool dm_test_handle_hpd_rx_msg_rdy(struct dc_link *link,
157 					  union hpd_irq_data *hpd_irq_data,
158 					  bool *link_loss,
159 					  bool defer_handling,
160 					  bool *has_left_work)
161 {
162 	*link_loss = false;
163 	*has_left_work = true;
164 	hpd_irq_data->bytes.device_service_irq.bits.UP_REQ_MSG_RDY = 1;
165 
166 	return false;
167 }
168 
dm_test_handle_hpd_rx_link_loss(struct dc_link * link,union hpd_irq_data * hpd_irq_data,bool * link_loss,bool defer_handling,bool * has_left_work)169 static bool dm_test_handle_hpd_rx_link_loss(struct dc_link *link,
170 					    union hpd_irq_data *hpd_irq_data,
171 					    bool *link_loss,
172 					    bool defer_handling,
173 					    bool *has_left_work)
174 {
175 	*link_loss = true;
176 	*has_left_work = true;
177 
178 	return false;
179 }
180 
dm_test_allow_hpd_rx_irq_true(const struct dc_link * link)181 static bool dm_test_allow_hpd_rx_irq_true(const struct dc_link *link)
182 {
183 	return true;
184 }
185 
186 
dm_test_dmub_get_outbox0_wptr(struct dmub_srv * dmub)187 static uint32_t dm_test_dmub_get_outbox0_wptr(struct dmub_srv *dmub)
188 {
189 	return 0;
190 }
191 
dm_test_dmub_get_outbox1_wptr(struct dmub_srv * dmub)192 static uint32_t dm_test_dmub_get_outbox1_wptr(struct dmub_srv *dmub)
193 {
194 	return 0;
195 }
196 
197 static int dm_test_dmub_notify_count;
198 
dm_test_dmub_notify_callback(struct amdgpu_device * adev,struct dmub_notification * notify)199 static void dm_test_dmub_notify_callback(struct amdgpu_device *adev,
200 					 struct dmub_notification *notify)
201 {
202 	dm_test_dmub_notify_count++;
203 }
204 
dm_test_to_dal_irq_source_dce110(struct irq_service * irq_service,uint32_t src_id,uint32_t ext_id)205 static enum dc_irq_source dm_test_to_dal_irq_source_dce110(
206 		struct irq_service *irq_service,
207 		uint32_t src_id,
208 		uint32_t ext_id)
209 {
210 	switch (src_id) {
211 	case VISLANDS30_IV_SRCID_D1_VERTICAL_INTERRUPT0:
212 		return DC_IRQ_SOURCE_VBLANK1;
213 	case VISLANDS30_IV_SRCID_D1_V_UPDATE_INT:
214 		return DC_IRQ_SOURCE_VUPDATE1;
215 	case VISLANDS30_IV_SRCID_D1_GRPH_PFLIP:
216 		return DC_IRQ_SOURCE_PFLIP1;
217 	case VISLANDS30_IV_SRCID_D1_GRPH_PFLIP + 2:
218 		return DC_IRQ_SOURCE_PFLIP2;
219 	case VISLANDS30_IV_SRCID_D1_GRPH_PFLIP + 4:
220 		return DC_IRQ_SOURCE_PFLIP3;
221 	case VISLANDS30_IV_SRCID_D1_GRPH_PFLIP + 6:
222 		return DC_IRQ_SOURCE_PFLIP4;
223 	case VISLANDS30_IV_SRCID_D1_GRPH_PFLIP + 8:
224 		return DC_IRQ_SOURCE_PFLIP5;
225 	case VISLANDS30_IV_SRCID_D1_GRPH_PFLIP + 10:
226 		return DC_IRQ_SOURCE_PFLIP6;
227 	default:
228 		return DC_IRQ_SOURCE_INVALID;
229 	}
230 }
231 
232 static const struct irq_service_funcs dm_test_irq_service_funcs_dce110 = {
233 	.to_dal_irq_source = dm_test_to_dal_irq_source_dce110
234 };
235 
dm_test_to_dal_irq_source_dcn10(struct irq_service * irq_service,uint32_t src_id,uint32_t ext_id)236 static enum dc_irq_source dm_test_to_dal_irq_source_dcn10(
237 		struct irq_service *irq_service,
238 		uint32_t src_id,
239 		uint32_t ext_id)
240 {
241 	switch (src_id) {
242 	case DCN_1_0__SRCID__DC_D1_OTG_VSTARTUP:
243 		return DC_IRQ_SOURCE_VBLANK1;
244 	case DCN_1_0__SRCID__OTG0_IHC_V_UPDATE_NO_LOCK_INTERRUPT:
245 		return DC_IRQ_SOURCE_VUPDATE1;
246 	case DCN_1_0__SRCID__HUBP0_FLIP_INTERRUPT:
247 		return DC_IRQ_SOURCE_PFLIP1;
248 	case DCN_1_0__SRCID__DMCUB_OUTBOX_LOW_PRIORITY_READY_INT:
249 		return DC_IRQ_SOURCE_DMCUB_OUTBOX;
250 	default:
251 		return DC_IRQ_SOURCE_INVALID;
252 	}
253 }
254 
255 static const struct irq_service_funcs dm_test_irq_service_funcs_dcn10 = {
256 	.to_dal_irq_source = dm_test_to_dal_irq_source_dcn10
257 };
258 
dm_test_irq_src_set(struct irq_service * irq_service,const struct irq_source_info * info,bool enable)259 static bool dm_test_irq_src_set(struct irq_service *irq_service,
260 				const struct irq_source_info *info, bool enable)
261 {
262 	return true;
263 }
264 
dm_test_irq_src_ack(struct irq_service * irq_service,const struct irq_source_info * info)265 static bool dm_test_irq_src_ack(struct irq_service *irq_service,
266 				const struct irq_source_info *info)
267 {
268 	return true;
269 }
270 
271 /* Per-source funcs let amdgpu_dm_irq_set() succeed without register access. */
272 static struct irq_source_info_funcs dm_test_irq_src_funcs = {
273 	.set = dm_test_irq_src_set,
274 	.ack = dm_test_irq_src_ack,
275 };
276 
dm_test_alloc_dc_with_irq_service(struct kunit * test,const struct irq_service_funcs * funcs)277 static struct dc *dm_test_alloc_dc_with_irq_service(struct kunit *test,
278 						    const struct irq_service_funcs *funcs)
279 {
280 	struct irq_source_info *info;
281 	struct resource_pool *res_pool;
282 	struct irq_service *irqs;
283 	struct dc *dc;
284 	int i;
285 
286 	dc = dm_kunit_alloc_dc_with_ctx(test);
287 	res_pool = kunit_kzalloc(test, sizeof(*res_pool), GFP_KERNEL);
288 	KUNIT_ASSERT_NOT_ERR_OR_NULL(test, res_pool);
289 	irqs = kunit_kzalloc(test, sizeof(*irqs), GFP_KERNEL);
290 	KUNIT_ASSERT_NOT_ERR_OR_NULL(test, irqs);
291 
292 	/*
293 	 * Populate the per-source info table so amdgpu_dm_irq_set()/_ack()
294 	 * succeed without touching hardware registers.
295 	 */
296 	info = kunit_kzalloc(test, sizeof(*info) * DAL_IRQ_SOURCES_NUMBER,
297 			     GFP_KERNEL);
298 	KUNIT_ASSERT_NOT_ERR_OR_NULL(test, info);
299 	for (i = 0; i < DAL_IRQ_SOURCES_NUMBER; i++)
300 		info[i].funcs = &dm_test_irq_src_funcs;
301 
302 	irqs->funcs = funcs;
303 	irqs->info = info;
304 	res_pool->irqs = irqs;
305 	dc->res_pool = res_pool;
306 
307 	return dc;
308 }
309 
dm_test_free_irq_sources(void * data)310 static void dm_test_free_irq_sources(void *data)
311 {
312 	struct amdgpu_device *adev = data;
313 	int i;
314 
315 	for (i = 0; i < AMDGPU_IRQ_CLIENTID_MAX; i++) {
316 		kfree(adev->irq.client[i].sources);
317 		adev->irq.client[i].sources = NULL;
318 	}
319 
320 	kfree(adev->crtc_irq.enabled_types);
321 	adev->crtc_irq.enabled_types = NULL;
322 	kfree(adev->vline0_irq.enabled_types);
323 	adev->vline0_irq.enabled_types = NULL;
324 	kfree(adev->vupdate_irq.enabled_types);
325 	adev->vupdate_irq.enabled_types = NULL;
326 	kfree(adev->pageflip_irq.enabled_types);
327 	adev->pageflip_irq.enabled_types = NULL;
328 	kfree(adev->dmub_outbox_irq.enabled_types);
329 	adev->dmub_outbox_irq.enabled_types = NULL;
330 	kfree(adev->dmub_trace_irq.enabled_types);
331 	adev->dmub_trace_irq.enabled_types = NULL;
332 	kfree(adev->hpd_irq.enabled_types);
333 	adev->hpd_irq.enabled_types = NULL;
334 }
335 
dm_test_crtc_list_del(void * data)336 static void dm_test_crtc_list_del(void *data)
337 {
338 	struct amdgpu_crtc *acrtc = data;
339 
340 	list_del_init(&acrtc->base.head);
341 }
342 
343 struct dm_test_hpd_rx_wq_ctx {
344 	struct hpd_rx_irq_offload_work_queue *wq;
345 	int count;
346 };
347 
dm_test_destroy_hpd_rx_wq(void * data)348 static void dm_test_destroy_hpd_rx_wq(void *data)
349 {
350 	struct dm_test_hpd_rx_wq_ctx *ctx = data;
351 	int i;
352 
353 	for (i = 0; i < ctx->count; i++)
354 		if (ctx->wq[i].wq)
355 			destroy_workqueue(ctx->wq[i].wq);
356 	kfree(ctx->wq);
357 }
358 
359 static const struct drm_connector_funcs dm_test_connector_funcs = {
360 	.reset = drm_atomic_helper_connector_reset,
361 	.atomic_duplicate_state = drm_atomic_helper_connector_duplicate_state,
362 	.atomic_destroy_state = drm_atomic_helper_connector_destroy_state,
363 	.fill_modes = drm_helper_probe_single_connector_modes,
364 	.destroy = drm_connector_cleanup,
365 };
366 
dm_test_connector_cleanup(void * data)367 static void dm_test_connector_cleanup(void *data)
368 {
369 	drm_connector_cleanup(data);
370 }
371 
372 /* Tests for amdgpu_dm_hpd_to_dal_irq_source() */
373 
374 /**
375  * dm_test_hpd_to_dal_irq_source_hpd1 - Test Hpd to dal irq source hpd1
376  * @test: The KUnit test context
377  */
dm_test_hpd_to_dal_irq_source_hpd1(struct kunit * test)378 static void dm_test_hpd_to_dal_irq_source_hpd1(struct kunit *test)
379 {
380 	KUNIT_EXPECT_EQ(test, (int)amdgpu_dm_hpd_to_dal_irq_source(AMDGPU_HPD_1),
381 			(int)DC_IRQ_SOURCE_HPD1);
382 }
383 
384 /**
385  * dm_test_hpd_to_dal_irq_source_hpd2 - Test Hpd to dal irq source hpd2
386  * @test: The KUnit test context
387  */
dm_test_hpd_to_dal_irq_source_hpd2(struct kunit * test)388 static void dm_test_hpd_to_dal_irq_source_hpd2(struct kunit *test)
389 {
390 	KUNIT_EXPECT_EQ(test, (int)amdgpu_dm_hpd_to_dal_irq_source(AMDGPU_HPD_2),
391 			(int)DC_IRQ_SOURCE_HPD2);
392 }
393 
394 /**
395  * dm_test_hpd_to_dal_irq_source_hpd3 - Test Hpd to dal irq source hpd3
396  * @test: The KUnit test context
397  */
dm_test_hpd_to_dal_irq_source_hpd3(struct kunit * test)398 static void dm_test_hpd_to_dal_irq_source_hpd3(struct kunit *test)
399 {
400 	KUNIT_EXPECT_EQ(test, (int)amdgpu_dm_hpd_to_dal_irq_source(AMDGPU_HPD_3),
401 			(int)DC_IRQ_SOURCE_HPD3);
402 }
403 
404 /**
405  * dm_test_hpd_to_dal_irq_source_hpd4 - Test Hpd to dal irq source hpd4
406  * @test: The KUnit test context
407  */
dm_test_hpd_to_dal_irq_source_hpd4(struct kunit * test)408 static void dm_test_hpd_to_dal_irq_source_hpd4(struct kunit *test)
409 {
410 	KUNIT_EXPECT_EQ(test, (int)amdgpu_dm_hpd_to_dal_irq_source(AMDGPU_HPD_4),
411 			(int)DC_IRQ_SOURCE_HPD4);
412 }
413 
414 /**
415  * dm_test_hpd_to_dal_irq_source_hpd5 - Test Hpd to dal irq source hpd5
416  * @test: The KUnit test context
417  */
dm_test_hpd_to_dal_irq_source_hpd5(struct kunit * test)418 static void dm_test_hpd_to_dal_irq_source_hpd5(struct kunit *test)
419 {
420 	KUNIT_EXPECT_EQ(test, (int)amdgpu_dm_hpd_to_dal_irq_source(AMDGPU_HPD_5),
421 			(int)DC_IRQ_SOURCE_HPD5);
422 }
423 
424 /**
425  * dm_test_hpd_to_dal_irq_source_hpd6 - Test Hpd to dal irq source hpd6
426  * @test: The KUnit test context
427  */
dm_test_hpd_to_dal_irq_source_hpd6(struct kunit * test)428 static void dm_test_hpd_to_dal_irq_source_hpd6(struct kunit *test)
429 {
430 	KUNIT_EXPECT_EQ(test, (int)amdgpu_dm_hpd_to_dal_irq_source(AMDGPU_HPD_6),
431 			(int)DC_IRQ_SOURCE_HPD6);
432 }
433 
434 /**
435  * dm_test_hpd_to_dal_irq_source_invalid - Test Hpd to dal irq source invalid
436  * @test: The KUnit test context
437  */
dm_test_hpd_to_dal_irq_source_invalid(struct kunit * test)438 static void dm_test_hpd_to_dal_irq_source_invalid(struct kunit *test)
439 {
440 	KUNIT_EXPECT_EQ(test, (int)amdgpu_dm_hpd_to_dal_irq_source(AMDGPU_HPD_NONE),
441 			(int)DC_IRQ_SOURCE_INVALID);
442 }
443 
444 /**
445  * dm_test_hpd_to_dal_irq_source_out_of_range - Test Hpd to dal irq source out of range
446  * @test: The KUnit test context
447  */
dm_test_hpd_to_dal_irq_source_out_of_range(struct kunit * test)448 static void dm_test_hpd_to_dal_irq_source_out_of_range(struct kunit *test)
449 {
450 	KUNIT_EXPECT_EQ(test, (int)amdgpu_dm_hpd_to_dal_irq_source(99),
451 			(int)DC_IRQ_SOURCE_INVALID);
452 }
453 
454 /* Tests for are_sinks_equal() */
455 
456 /**
457  * dm_test_are_sinks_equal_both_null - Test Are sinks equal both null
458  * @test: The KUnit test context
459  */
dm_test_are_sinks_equal_both_null(struct kunit * test)460 static void dm_test_are_sinks_equal_both_null(struct kunit *test)
461 {
462 	KUNIT_EXPECT_FALSE(test, are_sinks_equal(NULL, NULL));
463 }
464 
465 /**
466  * dm_test_are_sinks_equal_first_null - Test Are sinks equal first null
467  * @test: The KUnit test context
468  */
dm_test_are_sinks_equal_first_null(struct kunit * test)469 static void dm_test_are_sinks_equal_first_null(struct kunit *test)
470 {
471 	struct dc_sink *sink2;
472 
473 	sink2 = kunit_kzalloc(test, sizeof(*sink2), GFP_KERNEL);
474 	KUNIT_ASSERT_NOT_ERR_OR_NULL(test, sink2);
475 
476 	KUNIT_EXPECT_FALSE(test, are_sinks_equal(NULL, sink2));
477 }
478 
479 /**
480  * dm_test_are_sinks_equal_second_null - Test Are sinks equal second null
481  * @test: The KUnit test context
482  */
dm_test_are_sinks_equal_second_null(struct kunit * test)483 static void dm_test_are_sinks_equal_second_null(struct kunit *test)
484 {
485 	struct dc_sink *sink1;
486 
487 	sink1 = kunit_kzalloc(test, sizeof(*sink1), GFP_KERNEL);
488 	KUNIT_ASSERT_NOT_ERR_OR_NULL(test, sink1);
489 
490 	KUNIT_EXPECT_FALSE(test, are_sinks_equal(sink1, NULL));
491 }
492 
493 /**
494  * dm_test_are_sinks_equal_different_signal - Test Are sinks equal different signal
495  * @test: The KUnit test context
496  */
dm_test_are_sinks_equal_different_signal(struct kunit * test)497 static void dm_test_are_sinks_equal_different_signal(struct kunit *test)
498 {
499 	struct dc_sink *sink1, *sink2;
500 
501 	sink1 = kunit_kzalloc(test, sizeof(*sink1), GFP_KERNEL);
502 	KUNIT_ASSERT_NOT_ERR_OR_NULL(test, sink1);
503 	sink2 = kunit_kzalloc(test, sizeof(*sink2), GFP_KERNEL);
504 	KUNIT_ASSERT_NOT_ERR_OR_NULL(test, sink2);
505 
506 	sink1->sink_signal = SIGNAL_TYPE_HDMI_TYPE_A;
507 	sink2->sink_signal = SIGNAL_TYPE_DISPLAY_PORT;
508 
509 	KUNIT_EXPECT_FALSE(test, are_sinks_equal(sink1, sink2));
510 }
511 
512 /**
513  * dm_test_are_sinks_equal_different_edid_length - Test Are sinks equal different edid length
514  * @test: The KUnit test context
515  */
dm_test_are_sinks_equal_different_edid_length(struct kunit * test)516 static void dm_test_are_sinks_equal_different_edid_length(struct kunit *test)
517 {
518 	struct dc_sink *sink1, *sink2;
519 
520 	sink1 = kunit_kzalloc(test, sizeof(*sink1), GFP_KERNEL);
521 	KUNIT_ASSERT_NOT_ERR_OR_NULL(test, sink1);
522 	sink2 = kunit_kzalloc(test, sizeof(*sink2), GFP_KERNEL);
523 	KUNIT_ASSERT_NOT_ERR_OR_NULL(test, sink2);
524 
525 	sink1->sink_signal = SIGNAL_TYPE_HDMI_TYPE_A;
526 	sink2->sink_signal = SIGNAL_TYPE_HDMI_TYPE_A;
527 	sink1->dc_edid.length = 128;
528 	sink2->dc_edid.length = 256;
529 
530 	KUNIT_EXPECT_FALSE(test, are_sinks_equal(sink1, sink2));
531 }
532 
533 /**
534  * dm_test_are_sinks_equal_different_edid_data - Test Are sinks equal different edid data
535  * @test: The KUnit test context
536  */
dm_test_are_sinks_equal_different_edid_data(struct kunit * test)537 static void dm_test_are_sinks_equal_different_edid_data(struct kunit *test)
538 {
539 	struct dc_sink *sink1, *sink2;
540 
541 	sink1 = kunit_kzalloc(test, sizeof(*sink1), GFP_KERNEL);
542 	KUNIT_ASSERT_NOT_ERR_OR_NULL(test, sink1);
543 	sink2 = kunit_kzalloc(test, sizeof(*sink2), GFP_KERNEL);
544 	KUNIT_ASSERT_NOT_ERR_OR_NULL(test, sink2);
545 
546 	sink1->sink_signal = SIGNAL_TYPE_HDMI_TYPE_A;
547 	sink2->sink_signal = SIGNAL_TYPE_HDMI_TYPE_A;
548 	sink1->dc_edid.length = 4;
549 	sink2->dc_edid.length = 4;
550 	memset(sink1->dc_edid.raw_edid, 0xAA, 4);
551 	memset(sink2->dc_edid.raw_edid, 0xBB, 4);
552 
553 	KUNIT_EXPECT_FALSE(test, are_sinks_equal(sink1, sink2));
554 }
555 
556 /**
557  * dm_test_are_sinks_equal_identical - Test Are sinks equal identical
558  * @test: The KUnit test context
559  */
dm_test_are_sinks_equal_identical(struct kunit * test)560 static void dm_test_are_sinks_equal_identical(struct kunit *test)
561 {
562 	struct dc_sink *sink1, *sink2;
563 
564 	sink1 = kunit_kzalloc(test, sizeof(*sink1), GFP_KERNEL);
565 	KUNIT_ASSERT_NOT_ERR_OR_NULL(test, sink1);
566 	sink2 = kunit_kzalloc(test, sizeof(*sink2), GFP_KERNEL);
567 	KUNIT_ASSERT_NOT_ERR_OR_NULL(test, sink2);
568 
569 	sink1->sink_signal = SIGNAL_TYPE_HDMI_TYPE_A;
570 	sink2->sink_signal = SIGNAL_TYPE_HDMI_TYPE_A;
571 	sink1->dc_edid.length = 4;
572 	sink2->dc_edid.length = 4;
573 	memset(sink1->dc_edid.raw_edid, 0xAA, 4);
574 	memset(sink2->dc_edid.raw_edid, 0xAA, 4);
575 
576 	KUNIT_EXPECT_TRUE(test, are_sinks_equal(sink1, sink2));
577 }
578 
579 /**
580  * dm_test_are_sinks_equal_zero_length - Test Are sinks equal zero length
581  * @test: The KUnit test context
582  */
dm_test_are_sinks_equal_zero_length(struct kunit * test)583 static void dm_test_are_sinks_equal_zero_length(struct kunit *test)
584 {
585 	struct dc_sink *sink1, *sink2;
586 
587 	sink1 = kunit_kzalloc(test, sizeof(*sink1), GFP_KERNEL);
588 	KUNIT_ASSERT_NOT_ERR_OR_NULL(test, sink1);
589 	sink2 = kunit_kzalloc(test, sizeof(*sink2), GFP_KERNEL);
590 	KUNIT_ASSERT_NOT_ERR_OR_NULL(test, sink2);
591 
592 	sink1->sink_signal = SIGNAL_TYPE_DISPLAY_PORT;
593 	sink2->sink_signal = SIGNAL_TYPE_DISPLAY_PORT;
594 	sink1->dc_edid.length = 0;
595 	sink2->dc_edid.length = 0;
596 
597 	KUNIT_EXPECT_TRUE(test, are_sinks_equal(sink1, sink2));
598 }
599 
600 /**
601  * dm_test_are_sinks_equal_full_edid_identical - Test Are sinks equal full edid identical
602  * @test: The KUnit test context
603  */
dm_test_are_sinks_equal_full_edid_identical(struct kunit * test)604 static void dm_test_are_sinks_equal_full_edid_identical(struct kunit *test)
605 {
606 	struct dc_sink *sink1, *sink2;
607 
608 	sink1 = kunit_kzalloc(test, sizeof(*sink1), GFP_KERNEL);
609 	KUNIT_ASSERT_NOT_ERR_OR_NULL(test, sink1);
610 	sink2 = kunit_kzalloc(test, sizeof(*sink2), GFP_KERNEL);
611 	KUNIT_ASSERT_NOT_ERR_OR_NULL(test, sink2);
612 
613 	sink1->sink_signal = SIGNAL_TYPE_HDMI_TYPE_A;
614 	sink2->sink_signal = SIGNAL_TYPE_HDMI_TYPE_A;
615 	sink1->dc_edid.length = 128;
616 	sink2->dc_edid.length = 128;
617 	memset(sink1->dc_edid.raw_edid, 0x5A, 128);
618 	memset(sink2->dc_edid.raw_edid, 0x5A, 128);
619 
620 	KUNIT_EXPECT_TRUE(test, are_sinks_equal(sink1, sink2));
621 }
622 
623 /**
624  * dm_test_are_sinks_equal_full_edid_last_byte_differs - Test Are sinks equal last byte differs
625  * @test: The KUnit test context
626  */
dm_test_are_sinks_equal_full_edid_last_byte_differs(struct kunit * test)627 static void dm_test_are_sinks_equal_full_edid_last_byte_differs(struct kunit *test)
628 {
629 	struct dc_sink *sink1, *sink2;
630 
631 	sink1 = kunit_kzalloc(test, sizeof(*sink1), GFP_KERNEL);
632 	KUNIT_ASSERT_NOT_ERR_OR_NULL(test, sink1);
633 	sink2 = kunit_kzalloc(test, sizeof(*sink2), GFP_KERNEL);
634 	KUNIT_ASSERT_NOT_ERR_OR_NULL(test, sink2);
635 
636 	sink1->sink_signal = SIGNAL_TYPE_HDMI_TYPE_A;
637 	sink2->sink_signal = SIGNAL_TYPE_HDMI_TYPE_A;
638 	sink1->dc_edid.length = 128;
639 	sink2->dc_edid.length = 128;
640 	memset(sink1->dc_edid.raw_edid, 0x5A, 128);
641 	memset(sink2->dc_edid.raw_edid, 0x5A, 128);
642 	sink2->dc_edid.raw_edid[127] = 0x5B;
643 
644 	KUNIT_EXPECT_FALSE(test, are_sinks_equal(sink1, sink2));
645 }
646 
647 /* Tests for dmub_notification_type_str() */
648 
649 /**
650  * dm_test_notification_str_no_data - Test Notification str no data
651  * @test: The KUnit test context
652  */
dm_test_notification_str_no_data(struct kunit * test)653 static void dm_test_notification_str_no_data(struct kunit *test)
654 {
655 	KUNIT_EXPECT_STREQ(test, dmub_notification_type_str(DMUB_NOTIFICATION_NO_DATA), "NO_DATA");
656 }
657 
658 /**
659  * dm_test_notification_str_aux_reply - Test Notification str aux reply
660  * @test: The KUnit test context
661  */
dm_test_notification_str_aux_reply(struct kunit * test)662 static void dm_test_notification_str_aux_reply(struct kunit *test)
663 {
664 	KUNIT_EXPECT_STREQ(test, dmub_notification_type_str(DMUB_NOTIFICATION_AUX_REPLY), "AUX_REPLY");
665 }
666 
667 /**
668  * dm_test_notification_str_hpd - Test Notification str hpd
669  * @test: The KUnit test context
670  */
dm_test_notification_str_hpd(struct kunit * test)671 static void dm_test_notification_str_hpd(struct kunit *test)
672 {
673 	KUNIT_EXPECT_STREQ(test, dmub_notification_type_str(DMUB_NOTIFICATION_HPD), "HPD");
674 }
675 
676 /**
677  * dm_test_notification_str_hpd_irq - Test Notification str hpd irq
678  * @test: The KUnit test context
679  */
dm_test_notification_str_hpd_irq(struct kunit * test)680 static void dm_test_notification_str_hpd_irq(struct kunit *test)
681 {
682 	KUNIT_EXPECT_STREQ(test, dmub_notification_type_str(DMUB_NOTIFICATION_HPD_IRQ), "HPD_IRQ");
683 }
684 
685 /**
686  * dm_test_notification_str_set_config - Test Notification str set config
687  * @test: The KUnit test context
688  */
dm_test_notification_str_set_config(struct kunit * test)689 static void dm_test_notification_str_set_config(struct kunit *test)
690 {
691 	KUNIT_EXPECT_STREQ(test, dmub_notification_type_str(DMUB_NOTIFICATION_SET_CONFIG_REPLY),
692 			   "SET_CONFIG_REPLY");
693 }
694 
695 /**
696  * dm_test_notification_str_dpia - Test Notification str dpia
697  * @test: The KUnit test context
698  */
dm_test_notification_str_dpia(struct kunit * test)699 static void dm_test_notification_str_dpia(struct kunit *test)
700 {
701 	KUNIT_EXPECT_STREQ(test, dmub_notification_type_str(DMUB_NOTIFICATION_DPIA_NOTIFICATION),
702 			   "DPIA_NOTIFICATION");
703 }
704 
705 /**
706  * dm_test_notification_str_hpd_sense - Test Notification str hpd sense
707  * @test: The KUnit test context
708  */
dm_test_notification_str_hpd_sense(struct kunit * test)709 static void dm_test_notification_str_hpd_sense(struct kunit *test)
710 {
711 	KUNIT_EXPECT_STREQ(test, dmub_notification_type_str(DMUB_NOTIFICATION_HPD_SENSE_NOTIFY),
712 			   "HPD_SENSE_NOTIFY");
713 }
714 
715 /**
716  * dm_test_notification_str_fused_io - Test Notification str fused io
717  * @test: The KUnit test context
718  */
dm_test_notification_str_fused_io(struct kunit * test)719 static void dm_test_notification_str_fused_io(struct kunit *test)
720 {
721 	KUNIT_EXPECT_STREQ(test, dmub_notification_type_str(DMUB_NOTIFICATION_FUSED_IO),
722 			   "FUSED_IO");
723 }
724 
725 /**
726  * dm_test_notification_str_unknown - Test Notification str unknown
727  * @test: The KUnit test context
728  */
dm_test_notification_str_unknown(struct kunit * test)729 static void dm_test_notification_str_unknown(struct kunit *test)
730 {
731 	KUNIT_EXPECT_STREQ(test, dmub_notification_type_str(DMUB_NOTIFICATION_MAX), "<unknown>");
732 }
733 
734 /* Tests for amdgpu_dm_irq_init() */
735 
736 /**
737  * dm_test_irq_init_initializes_lists - Test irq init initializes list heads
738  * @test: The KUnit test context
739  */
dm_test_irq_init_initializes_lists(struct kunit * test)740 static void dm_test_irq_init_initializes_lists(struct kunit *test)
741 {
742 	struct amdgpu_device *adev;
743 	int src;
744 
745 	adev = kunit_kzalloc(test, sizeof(*adev), GFP_KERNEL);
746 	KUNIT_ASSERT_NOT_ERR_OR_NULL(test, adev);
747 
748 	KUNIT_EXPECT_EQ(test, amdgpu_dm_irq_init(adev), 0);
749 
750 	for (src = 0; src < DAL_IRQ_SOURCES_NUMBER; src++) {
751 		KUNIT_EXPECT_TRUE(test,
752 				  list_empty(&adev->dm.irq_handler_list_low_tab[src]));
753 		KUNIT_EXPECT_TRUE(test,
754 				  list_empty(&adev->dm.irq_handler_list_high_tab[src]));
755 	}
756 }
757 
758 /* Tests for amdgpu_dm_irq_register_interrupt() */
759 
760 /**
761  * dm_test_irq_register_rejects_null_params - Test register rejects null params
762  * @test: The KUnit test context
763  */
dm_test_irq_register_rejects_null_params(struct kunit * test)764 static void dm_test_irq_register_rejects_null_params(struct kunit *test)
765 {
766 	struct amdgpu_device *adev;
767 	struct dc_interrupt_params int_params = { 0 };
768 
769 	adev = kunit_kzalloc(test, sizeof(*adev), GFP_KERNEL);
770 	KUNIT_ASSERT_NOT_ERR_OR_NULL(test, adev);
771 
772 	int_params.int_context = INTERRUPT_LOW_IRQ_CONTEXT;
773 	int_params.irq_source = DC_IRQ_SOURCE_HPD1;
774 
775 	KUNIT_EXPECT_NULL(test,
776 		amdgpu_dm_irq_register_interrupt(adev, NULL,
777 						   dm_test_irq_handler, NULL));
778 	KUNIT_EXPECT_NULL(test,
779 		amdgpu_dm_irq_register_interrupt(adev, &int_params, NULL, NULL));
780 }
781 
782 /**
783  * dm_test_irq_register_rejects_invalid_context - Test register rejects context
784  * @test: The KUnit test context
785  */
dm_test_irq_register_rejects_invalid_context(struct kunit * test)786 static void dm_test_irq_register_rejects_invalid_context(struct kunit *test)
787 {
788 	struct amdgpu_device *adev;
789 	struct dc_interrupt_params int_params = { 0 };
790 
791 	adev = kunit_kzalloc(test, sizeof(*adev), GFP_KERNEL);
792 	KUNIT_ASSERT_NOT_ERR_OR_NULL(test, adev);
793 
794 	int_params.int_context = INTERRUPT_CONTEXT_NUMBER;
795 	int_params.irq_source = DC_IRQ_SOURCE_HPD1;
796 
797 	KUNIT_EXPECT_NULL(test,
798 		amdgpu_dm_irq_register_interrupt(adev, &int_params,
799 						   dm_test_irq_handler, NULL));
800 }
801 
802 /**
803  * dm_test_irq_register_rejects_invalid_source - Test register rejects source
804  * @test: The KUnit test context
805  */
dm_test_irq_register_rejects_invalid_source(struct kunit * test)806 static void dm_test_irq_register_rejects_invalid_source(struct kunit *test)
807 {
808 	struct amdgpu_device *adev;
809 	struct dc_interrupt_params int_params = { 0 };
810 
811 	adev = kunit_kzalloc(test, sizeof(*adev), GFP_KERNEL);
812 	KUNIT_ASSERT_NOT_ERR_OR_NULL(test, adev);
813 
814 	int_params.int_context = INTERRUPT_LOW_IRQ_CONTEXT;
815 	int_params.irq_source = DC_IRQ_SOURCE_INVALID;
816 
817 	KUNIT_EXPECT_NULL(test,
818 		amdgpu_dm_irq_register_interrupt(adev, &int_params,
819 						   dm_test_irq_handler, NULL));
820 }
821 
822 /**
823  * dm_test_irq_register_adds_low_context_handler - Test register adds low handler
824  * @test: The KUnit test context
825  */
dm_test_irq_register_adds_low_context_handler(struct kunit * test)826 static void dm_test_irq_register_adds_low_context_handler(struct kunit *test)
827 {
828 	struct amdgpu_device *adev;
829 	struct dc_interrupt_params int_params = { 0 };
830 	void *handler;
831 
832 	adev = kunit_kzalloc(test, sizeof(*adev), GFP_KERNEL);
833 	KUNIT_ASSERT_NOT_ERR_OR_NULL(test, adev);
834 	KUNIT_ASSERT_EQ(test, amdgpu_dm_irq_init(adev), 0);
835 
836 	int_params.int_context = INTERRUPT_LOW_IRQ_CONTEXT;
837 	int_params.irq_source = DC_IRQ_SOURCE_HPD1;
838 
839 	handler = amdgpu_dm_irq_register_interrupt(adev, &int_params,
840 						    dm_test_irq_handler, adev);
841 
842 	KUNIT_ASSERT_NOT_ERR_OR_NULL(test, handler);
843 	KUNIT_EXPECT_FALSE(test,
844 			   list_empty(&adev->dm.irq_handler_list_low_tab[DC_IRQ_SOURCE_HPD1]));
845 	KUNIT_EXPECT_TRUE(test,
846 			  list_empty(&adev->dm.irq_handler_list_high_tab[DC_IRQ_SOURCE_HPD1]));
847 
848 	amdgpu_dm_irq_unregister_interrupt(adev, DC_IRQ_SOURCE_HPD1,
849 						dm_test_irq_handler);
850 	KUNIT_EXPECT_TRUE(test,
851 			  list_empty(&adev->dm.irq_handler_list_low_tab[DC_IRQ_SOURCE_HPD1]));
852 }
853 
854 /**
855  * dm_test_irq_register_adds_high_context_handler - Test register adds high handler
856  * @test: The KUnit test context
857  */
dm_test_irq_register_adds_high_context_handler(struct kunit * test)858 static void dm_test_irq_register_adds_high_context_handler(struct kunit *test)
859 {
860 	struct amdgpu_device *adev;
861 	struct dc_interrupt_params int_params = { 0 };
862 	void *handler;
863 
864 	adev = kunit_kzalloc(test, sizeof(*adev), GFP_KERNEL);
865 	KUNIT_ASSERT_NOT_ERR_OR_NULL(test, adev);
866 	KUNIT_ASSERT_EQ(test, amdgpu_dm_irq_init(adev), 0);
867 
868 	int_params.int_context = INTERRUPT_HIGH_IRQ_CONTEXT;
869 	int_params.irq_source = DC_IRQ_SOURCE_HPD2;
870 
871 	handler = amdgpu_dm_irq_register_interrupt(adev, &int_params,
872 						    dm_test_irq_handler, adev);
873 
874 	KUNIT_ASSERT_NOT_ERR_OR_NULL(test, handler);
875 	KUNIT_EXPECT_FALSE(test,
876 			   list_empty(&adev->dm.irq_handler_list_high_tab[DC_IRQ_SOURCE_HPD2]));
877 	KUNIT_EXPECT_TRUE(test,
878 			  list_empty(&adev->dm.irq_handler_list_low_tab[DC_IRQ_SOURCE_HPD2]));
879 
880 	amdgpu_dm_irq_unregister_interrupt(adev, DC_IRQ_SOURCE_HPD2,
881 						dm_test_irq_handler);
882 	KUNIT_EXPECT_TRUE(test,
883 			  list_empty(&adev->dm.irq_handler_list_high_tab[DC_IRQ_SOURCE_HPD2]));
884 }
885 
886 /**
887  * dm_test_irq_register_multiple_handlers - Test register keeps multiple handlers
888  * @test: The KUnit test context
889  */
dm_test_irq_register_multiple_handlers(struct kunit * test)890 static void dm_test_irq_register_multiple_handlers(struct kunit *test)
891 {
892 	struct amdgpu_device *adev;
893 	struct dc_interrupt_params int_params = { 0 };
894 	struct list_head *hnd_list;
895 	void *handler1, *handler2;
896 
897 	adev = kunit_kzalloc(test, sizeof(*adev), GFP_KERNEL);
898 	KUNIT_ASSERT_NOT_ERR_OR_NULL(test, adev);
899 	KUNIT_ASSERT_EQ(test, amdgpu_dm_irq_init(adev), 0);
900 
901 	int_params.int_context = INTERRUPT_LOW_IRQ_CONTEXT;
902 	int_params.irq_source = DC_IRQ_SOURCE_HPD1;
903 
904 	handler1 = amdgpu_dm_irq_register_interrupt(adev, &int_params,
905 						    dm_test_irq_handler, adev);
906 	KUNIT_ASSERT_NOT_ERR_OR_NULL(test, handler1);
907 	handler2 = amdgpu_dm_irq_register_interrupt(adev, &int_params,
908 						    dm_test_irq_handler_alt, adev);
909 	KUNIT_ASSERT_NOT_ERR_OR_NULL(test, handler2);
910 
911 	hnd_list = &adev->dm.irq_handler_list_low_tab[DC_IRQ_SOURCE_HPD1];
912 	KUNIT_EXPECT_EQ(test, list_count_nodes(hnd_list), 2);
913 
914 	amdgpu_dm_irq_unregister_interrupt(adev, DC_IRQ_SOURCE_HPD1,
915 						dm_test_irq_handler);
916 	amdgpu_dm_irq_unregister_interrupt(adev, DC_IRQ_SOURCE_HPD1,
917 						dm_test_irq_handler_alt);
918 	KUNIT_EXPECT_TRUE(test, list_empty(hnd_list));
919 }
920 
921 /**
922  * dm_test_irq_register_separate_contexts - Test register same source in two contexts
923  * @test: The KUnit test context
924  */
dm_test_irq_register_separate_contexts(struct kunit * test)925 static void dm_test_irq_register_separate_contexts(struct kunit *test)
926 {
927 	struct amdgpu_device *adev;
928 	struct dc_interrupt_params int_params = { 0 };
929 	void *handler;
930 
931 	adev = kunit_kzalloc(test, sizeof(*adev), GFP_KERNEL);
932 	KUNIT_ASSERT_NOT_ERR_OR_NULL(test, adev);
933 	KUNIT_ASSERT_EQ(test, amdgpu_dm_irq_init(adev), 0);
934 
935 	int_params.irq_source = DC_IRQ_SOURCE_HPD5;
936 
937 	int_params.int_context = INTERRUPT_LOW_IRQ_CONTEXT;
938 	handler = amdgpu_dm_irq_register_interrupt(adev, &int_params,
939 						    dm_test_irq_handler, adev);
940 	KUNIT_ASSERT_NOT_ERR_OR_NULL(test, handler);
941 
942 	int_params.int_context = INTERRUPT_HIGH_IRQ_CONTEXT;
943 	handler = amdgpu_dm_irq_register_interrupt(adev, &int_params,
944 						    dm_test_irq_handler, adev);
945 	KUNIT_ASSERT_NOT_ERR_OR_NULL(test, handler);
946 
947 	KUNIT_EXPECT_FALSE(test,
948 			   list_empty(&adev->dm.irq_handler_list_low_tab[DC_IRQ_SOURCE_HPD5]));
949 	KUNIT_EXPECT_FALSE(test,
950 			   list_empty(&adev->dm.irq_handler_list_high_tab[DC_IRQ_SOURCE_HPD5]));
951 
952 	/*
953 	 * A single unregister call stops at the first context where the handler
954 	 * is found (low context), leaving the high context handler in place.
955 	 */
956 	amdgpu_dm_irq_unregister_interrupt(adev, DC_IRQ_SOURCE_HPD5,
957 						dm_test_irq_handler);
958 
959 	KUNIT_EXPECT_TRUE(test,
960 			  list_empty(&adev->dm.irq_handler_list_low_tab[DC_IRQ_SOURCE_HPD5]));
961 	KUNIT_EXPECT_FALSE(test,
962 			   list_empty(&adev->dm.irq_handler_list_high_tab[DC_IRQ_SOURCE_HPD5]));
963 
964 	/* A second call removes the remaining high context handler. */
965 	amdgpu_dm_irq_unregister_interrupt(adev, DC_IRQ_SOURCE_HPD5,
966 						dm_test_irq_handler);
967 
968 	KUNIT_EXPECT_TRUE(test,
969 			  list_empty(&adev->dm.irq_handler_list_high_tab[DC_IRQ_SOURCE_HPD5]));
970 }
971 
972 /* Tests for amdgpu_dm_irq_unregister_interrupt() */
973 
974 /**
975  * dm_test_irq_unregister_rejects_invalid_source - Test unregister rejects source
976  * @test: The KUnit test context
977  */
dm_test_irq_unregister_rejects_invalid_source(struct kunit * test)978 static void dm_test_irq_unregister_rejects_invalid_source(struct kunit *test)
979 {
980 	struct amdgpu_device *adev;
981 
982 	adev = kunit_kzalloc(test, sizeof(*adev), GFP_KERNEL);
983 	KUNIT_ASSERT_NOT_ERR_OR_NULL(test, adev);
984 	KUNIT_ASSERT_EQ(test, amdgpu_dm_irq_init(adev), 0);
985 
986 	amdgpu_dm_irq_unregister_interrupt(adev, DC_IRQ_SOURCE_INVALID,
987 						dm_test_irq_handler);
988 
989 	KUNIT_EXPECT_TRUE(test,
990 			  list_empty(&adev->dm.irq_handler_list_low_tab[DC_IRQ_SOURCE_HPD1]));
991 	KUNIT_EXPECT_TRUE(test,
992 			  list_empty(&adev->dm.irq_handler_list_high_tab[DC_IRQ_SOURCE_HPD1]));
993 }
994 
995 /**
996  * dm_test_irq_unregister_rejects_null_handler - Test unregister rejects handler
997  * @test: The KUnit test context
998  */
dm_test_irq_unregister_rejects_null_handler(struct kunit * test)999 static void dm_test_irq_unregister_rejects_null_handler(struct kunit *test)
1000 {
1001 	struct amdgpu_device *adev;
1002 
1003 	adev = kunit_kzalloc(test, sizeof(*adev), GFP_KERNEL);
1004 	KUNIT_ASSERT_NOT_ERR_OR_NULL(test, adev);
1005 	KUNIT_ASSERT_EQ(test, amdgpu_dm_irq_init(adev), 0);
1006 
1007 	amdgpu_dm_irq_unregister_interrupt(adev, DC_IRQ_SOURCE_HPD1,
1008 						DAL_INVALID_IRQ_HANDLER_IDX);
1009 
1010 	KUNIT_EXPECT_TRUE(test,
1011 			  list_empty(&adev->dm.irq_handler_list_low_tab[DC_IRQ_SOURCE_HPD1]));
1012 	KUNIT_EXPECT_TRUE(test,
1013 			  list_empty(&adev->dm.irq_handler_list_high_tab[DC_IRQ_SOURCE_HPD1]));
1014 }
1015 
1016 /**
1017  * dm_test_irq_unregister_handler_not_found - Test unregister keeps unmatched handler
1018  * @test: The KUnit test context
1019  */
dm_test_irq_unregister_handler_not_found(struct kunit * test)1020 static void dm_test_irq_unregister_handler_not_found(struct kunit *test)
1021 {
1022 	struct amdgpu_device *adev;
1023 	struct dc_interrupt_params int_params = { 0 };
1024 	void *handler;
1025 
1026 	adev = kunit_kzalloc(test, sizeof(*adev), GFP_KERNEL);
1027 	KUNIT_ASSERT_NOT_ERR_OR_NULL(test, adev);
1028 	KUNIT_ASSERT_EQ(test, amdgpu_dm_irq_init(adev), 0);
1029 
1030 	int_params.int_context = INTERRUPT_LOW_IRQ_CONTEXT;
1031 	int_params.irq_source = DC_IRQ_SOURCE_HPD1;
1032 	handler = amdgpu_dm_irq_register_interrupt(adev, &int_params,
1033 						    dm_test_irq_handler, adev);
1034 	KUNIT_ASSERT_NOT_ERR_OR_NULL(test, handler);
1035 
1036 	/* Unregister a handler that was never registered for this source. */
1037 	amdgpu_dm_irq_unregister_interrupt(adev, DC_IRQ_SOURCE_HPD1,
1038 						dm_test_irq_handler_alt);
1039 
1040 	/* The originally registered handler must still be present. */
1041 	KUNIT_EXPECT_FALSE(test,
1042 			   list_empty(&adev->dm.irq_handler_list_low_tab[DC_IRQ_SOURCE_HPD1]));
1043 
1044 	amdgpu_dm_irq_unregister_interrupt(adev, DC_IRQ_SOURCE_HPD1,
1045 						dm_test_irq_handler);
1046 	KUNIT_EXPECT_TRUE(test,
1047 			  list_empty(&adev->dm.irq_handler_list_low_tab[DC_IRQ_SOURCE_HPD1]));
1048 }
1049 
1050 /* Tests for amdgpu_dm_irq_fini() */
1051 
1052 /**
1053  * dm_test_irq_fini_removes_registered_handlers - Test fini removes handlers
1054  * @test: The KUnit test context
1055  */
dm_test_irq_fini_removes_registered_handlers(struct kunit * test)1056 static void dm_test_irq_fini_removes_registered_handlers(struct kunit *test)
1057 {
1058 	struct amdgpu_device *adev;
1059 	struct dc_interrupt_params int_params = { 0 };
1060 	void *handler;
1061 
1062 	adev = kunit_kzalloc(test, sizeof(*adev), GFP_KERNEL);
1063 	KUNIT_ASSERT_NOT_ERR_OR_NULL(test, adev);
1064 	KUNIT_ASSERT_EQ(test, amdgpu_dm_irq_init(adev), 0);
1065 
1066 	int_params.int_context = INTERRUPT_LOW_IRQ_CONTEXT;
1067 	int_params.irq_source = DC_IRQ_SOURCE_HPD3;
1068 	handler = amdgpu_dm_irq_register_interrupt(adev, &int_params,
1069 						    dm_test_irq_handler, adev);
1070 	KUNIT_ASSERT_NOT_ERR_OR_NULL(test, handler);
1071 
1072 	int_params.int_context = INTERRUPT_HIGH_IRQ_CONTEXT;
1073 	int_params.irq_source = DC_IRQ_SOURCE_HPD4;
1074 	handler = amdgpu_dm_irq_register_interrupt(adev, &int_params,
1075 						    dm_test_irq_handler, adev);
1076 	KUNIT_ASSERT_NOT_ERR_OR_NULL(test, handler);
1077 
1078 	amdgpu_dm_irq_fini(adev);
1079 
1080 	KUNIT_EXPECT_TRUE(test,
1081 			  list_empty(&adev->dm.irq_handler_list_low_tab[DC_IRQ_SOURCE_HPD3]));
1082 	KUNIT_EXPECT_TRUE(test,
1083 			  list_empty(&adev->dm.irq_handler_list_high_tab[DC_IRQ_SOURCE_HPD4]));
1084 }
1085 
1086 /**
1087  * dm_test_irq_fini_on_empty_tables - Test fini on tables with no handlers
1088  * @test: The KUnit test context
1089  */
dm_test_irq_fini_on_empty_tables(struct kunit * test)1090 static void dm_test_irq_fini_on_empty_tables(struct kunit *test)
1091 {
1092 	struct amdgpu_device *adev;
1093 	int src;
1094 
1095 	adev = kunit_kzalloc(test, sizeof(*adev), GFP_KERNEL);
1096 	KUNIT_ASSERT_NOT_ERR_OR_NULL(test, adev);
1097 	KUNIT_ASSERT_EQ(test, amdgpu_dm_irq_init(adev), 0);
1098 
1099 	amdgpu_dm_irq_fini(adev);
1100 
1101 	for (src = 0; src < DAL_IRQ_SOURCES_NUMBER; src++) {
1102 		KUNIT_EXPECT_TRUE(test,
1103 				  list_empty(&adev->dm.irq_handler_list_low_tab[src]));
1104 		KUNIT_EXPECT_TRUE(test,
1105 				  list_empty(&adev->dm.irq_handler_list_high_tab[src]));
1106 	}
1107 }
1108 
1109 /* Tests for amdgpu_dm_get_crtc_by_otg_inst() */
1110 
1111 /**
1112  * dm_test_get_crtc_by_otg_inst_returns_match - Test CRTC lookup by OTG instance
1113  * @test: The KUnit test context
1114  */
dm_test_get_crtc_by_otg_inst_returns_match(struct kunit * test)1115 static void dm_test_get_crtc_by_otg_inst_returns_match(struct kunit *test)
1116 {
1117 	struct amdgpu_crtc *acrtc_a, *acrtc_b;
1118 	struct amdgpu_device *adev;
1119 	struct drm_device *drm;
1120 
1121 	adev = dm_kunit_alloc_adev(test);
1122 	drm = &adev->ddev;
1123 
1124 	acrtc_a = kunit_kzalloc(test, sizeof(*acrtc_a), GFP_KERNEL);
1125 	KUNIT_ASSERT_NOT_ERR_OR_NULL(test, acrtc_a);
1126 	acrtc_b = kunit_kzalloc(test, sizeof(*acrtc_b), GFP_KERNEL);
1127 	KUNIT_ASSERT_NOT_ERR_OR_NULL(test, acrtc_b);
1128 
1129 	INIT_LIST_HEAD(&acrtc_a->base.head);
1130 	INIT_LIST_HEAD(&acrtc_b->base.head);
1131 	acrtc_a->otg_inst = 1;
1132 	acrtc_b->otg_inst = 3;
1133 
1134 	list_add_tail(&acrtc_a->base.head, &drm->mode_config.crtc_list);
1135 	KUNIT_ASSERT_EQ(test, kunit_add_action_or_reset(test, dm_test_crtc_list_del, acrtc_a), 0);
1136 	list_add_tail(&acrtc_b->base.head, &drm->mode_config.crtc_list);
1137 	KUNIT_ASSERT_EQ(test, kunit_add_action_or_reset(test, dm_test_crtc_list_del, acrtc_b), 0);
1138 
1139 	KUNIT_EXPECT_PTR_EQ(test, amdgpu_dm_get_crtc_by_otg_inst(adev, 3), acrtc_b);
1140 }
1141 
1142 /**
1143  * dm_test_get_crtc_by_otg_inst_returns_null - Test CRTC lookup misses unknown OTG
1144  * @test: The KUnit test context
1145  */
dm_test_get_crtc_by_otg_inst_returns_null(struct kunit * test)1146 static void dm_test_get_crtc_by_otg_inst_returns_null(struct kunit *test)
1147 {
1148 	struct amdgpu_crtc *acrtc;
1149 	struct amdgpu_device *adev;
1150 	struct drm_device *drm;
1151 
1152 	adev = dm_kunit_alloc_adev(test);
1153 	drm = &adev->ddev;
1154 
1155 	acrtc = kunit_kzalloc(test, sizeof(*acrtc), GFP_KERNEL);
1156 	KUNIT_ASSERT_NOT_ERR_OR_NULL(test, acrtc);
1157 
1158 	INIT_LIST_HEAD(&acrtc->base.head);
1159 	acrtc->otg_inst = 2;
1160 
1161 	list_add_tail(&acrtc->base.head, &drm->mode_config.crtc_list);
1162 	KUNIT_ASSERT_EQ(test, kunit_add_action_or_reset(test, dm_test_crtc_list_del, acrtc), 0);
1163 
1164 	KUNIT_EXPECT_NULL(test, amdgpu_dm_get_crtc_by_otg_inst(adev, 5));
1165 }
1166 
1167 /**
1168  * dm_test_get_crtc_by_otg_inst_empty_list - Test CRTC lookup on empty CRTC list
1169  * @test: The KUnit test context
1170  */
dm_test_get_crtc_by_otg_inst_empty_list(struct kunit * test)1171 static void dm_test_get_crtc_by_otg_inst_empty_list(struct kunit *test)
1172 {
1173 	struct amdgpu_device *adev;
1174 
1175 	adev = dm_kunit_alloc_adev(test);
1176 
1177 	KUNIT_EXPECT_NULL(test, amdgpu_dm_get_crtc_by_otg_inst(adev, 0));
1178 }
1179 
1180 /* Tests for amdgpu_dm_set_irq_funcs() */
1181 
1182 /**
1183  * dm_test_set_irq_funcs - Test irq src funcs and counts are populated
1184  * @test: The KUnit test context
1185  */
dm_test_set_irq_funcs(struct kunit * test)1186 static void dm_test_set_irq_funcs(struct kunit *test)
1187 {
1188 	struct amdgpu_device *adev;
1189 
1190 	adev = kunit_kzalloc(test, sizeof(*adev), GFP_KERNEL);
1191 	KUNIT_ASSERT_NOT_ERR_OR_NULL(test, adev);
1192 
1193 	adev->mode_info.num_crtc = 6;
1194 	adev->mode_info.num_hpd = 4;
1195 
1196 	amdgpu_dm_set_irq_funcs(adev);
1197 
1198 	KUNIT_EXPECT_EQ(test, adev->crtc_irq.num_types, 6);
1199 	KUNIT_EXPECT_EQ(test, adev->vline0_irq.num_types, 6);
1200 	KUNIT_EXPECT_EQ(test, adev->vupdate_irq.num_types, 6);
1201 	KUNIT_EXPECT_EQ(test, adev->pageflip_irq.num_types, 6);
1202 	KUNIT_EXPECT_EQ(test, adev->dmub_outbox_irq.num_types, 1);
1203 	KUNIT_EXPECT_EQ(test, adev->dmub_trace_irq.num_types, 1);
1204 	KUNIT_EXPECT_EQ(test, adev->hpd_irq.num_types, 4);
1205 
1206 	KUNIT_EXPECT_TRUE(test, adev->crtc_irq.funcs != NULL);
1207 	KUNIT_EXPECT_TRUE(test, adev->vline0_irq.funcs != NULL);
1208 	KUNIT_EXPECT_TRUE(test, adev->dmub_outbox_irq.funcs != NULL);
1209 	KUNIT_EXPECT_TRUE(test, adev->vupdate_irq.funcs != NULL);
1210 	KUNIT_EXPECT_TRUE(test, adev->dmub_trace_irq.funcs != NULL);
1211 	KUNIT_EXPECT_TRUE(test, adev->pageflip_irq.funcs != NULL);
1212 	KUNIT_EXPECT_TRUE(test, adev->hpd_irq.funcs != NULL);
1213 }
1214 
1215 /* Tests for amdgpu_dm_irq_suspend()/resume_early()/resume_late() */
1216 
1217 /**
1218  * dm_test_irq_suspend_empty - Test suspend walks empty handler tables safely
1219  * @test: The KUnit test context
1220  */
dm_test_irq_suspend_empty(struct kunit * test)1221 static void dm_test_irq_suspend_empty(struct kunit *test)
1222 {
1223 	struct amdgpu_device *adev;
1224 	int src;
1225 
1226 	adev = dm_kunit_alloc_adev(test);
1227 	KUNIT_ASSERT_EQ(test, amdgpu_dm_irq_init(adev), 0);
1228 
1229 	/*
1230 	 * With no registered handlers the amdgpu_dm_irq_set() calls are
1231 	 * skipped, so suspend must complete without touching the (absent) DC.
1232 	 */
1233 	amdgpu_dm_irq_suspend(adev);
1234 
1235 	for (src = 0; src < DAL_IRQ_SOURCES_NUMBER; src++) {
1236 		KUNIT_EXPECT_TRUE(test, list_empty(&adev->dm.irq_handler_list_low_tab[src]));
1237 		KUNIT_EXPECT_TRUE(test, list_empty(&adev->dm.irq_handler_list_high_tab[src]));
1238 	}
1239 }
1240 
1241 /**
1242  * dm_test_irq_resume_early_empty - Test early resume walks empty tables safely
1243  * @test: The KUnit test context
1244  */
dm_test_irq_resume_early_empty(struct kunit * test)1245 static void dm_test_irq_resume_early_empty(struct kunit *test)
1246 {
1247 	struct amdgpu_device *adev;
1248 	int src;
1249 
1250 	adev = dm_kunit_alloc_adev(test);
1251 	KUNIT_ASSERT_EQ(test, amdgpu_dm_irq_init(adev), 0);
1252 
1253 	amdgpu_dm_irq_resume_early(adev);
1254 
1255 	for (src = 0; src < DAL_IRQ_SOURCES_NUMBER; src++)
1256 		KUNIT_EXPECT_TRUE(test, list_empty(&adev->dm.irq_handler_list_high_tab[src]));
1257 }
1258 
1259 /**
1260  * dm_test_irq_resume_late_empty - Test late resume walks empty tables safely
1261  * @test: The KUnit test context
1262  */
dm_test_irq_resume_late_empty(struct kunit * test)1263 static void dm_test_irq_resume_late_empty(struct kunit *test)
1264 {
1265 	struct amdgpu_device *adev;
1266 	int src;
1267 
1268 	adev = dm_kunit_alloc_adev(test);
1269 	KUNIT_ASSERT_EQ(test, amdgpu_dm_irq_init(adev), 0);
1270 
1271 	amdgpu_dm_irq_resume_late(adev);
1272 
1273 	for (src = 0; src < DAL_IRQ_SOURCES_NUMBER; src++)
1274 		KUNIT_EXPECT_TRUE(test, list_empty(&adev->dm.irq_handler_list_low_tab[src]));
1275 }
1276 
1277 /**
1278  * dm_test_irq_suspend_registered - Test suspend reaches the irq set path
1279  * @test: The KUnit test context
1280  *
1281  * Registers a low-context HPD handler so the handler list is non-empty,
1282  * forcing amdgpu_dm_irq_suspend() to call amdgpu_dm_irq_set() (NULL-safe with
1283  * no DC) and flush_work() on the registered handler.
1284  */
dm_test_irq_suspend_registered(struct kunit * test)1285 static void dm_test_irq_suspend_registered(struct kunit *test)
1286 {
1287 	struct dc_interrupt_params int_params = { 0 };
1288 	struct amdgpu_device *adev;
1289 	void *handler;
1290 
1291 	adev = dm_kunit_alloc_adev(test);
1292 	KUNIT_ASSERT_EQ(test, amdgpu_dm_irq_init(adev), 0);
1293 
1294 	int_params.int_context = INTERRUPT_LOW_IRQ_CONTEXT;
1295 	int_params.irq_source = DC_IRQ_SOURCE_HPD1;
1296 	handler = amdgpu_dm_irq_register_interrupt(adev, &int_params,
1297 						   dm_test_irq_handler, adev);
1298 	KUNIT_ASSERT_NOT_ERR_OR_NULL(test, handler);
1299 
1300 	amdgpu_dm_irq_suspend(adev);
1301 
1302 	amdgpu_dm_irq_unregister_interrupt(adev, DC_IRQ_SOURCE_HPD1,
1303 					   dm_test_irq_handler);
1304 }
1305 
1306 /**
1307  * dm_test_irq_suspend_disables_polling - Test suspend disables KMS polling
1308  * @test: The KUnit test context
1309  *
1310  * With KMS polling active, suspend must take the poll-disable branch.
1311  * drm_kms_helper_poll_disable() only cancels the poll work; it leaves the
1312  * poll_enabled flag set (cleared later by drm_kms_helper_poll_fini()).
1313  */
dm_test_irq_suspend_disables_polling(struct kunit * test)1314 static void dm_test_irq_suspend_disables_polling(struct kunit *test)
1315 {
1316 	struct amdgpu_device *adev;
1317 
1318 	adev = dm_kunit_alloc_adev(test);
1319 	KUNIT_ASSERT_EQ(test, amdgpu_dm_irq_init(adev), 0);
1320 
1321 	/* Enable KMS polling so suspend takes the poll-disable branch. */
1322 	drm_kms_helper_poll_init(&adev->ddev);
1323 	KUNIT_ASSERT_TRUE(test, adev->ddev.mode_config.poll_enabled);
1324 
1325 	amdgpu_dm_irq_suspend(adev);
1326 
1327 	KUNIT_EXPECT_TRUE(test, adev->ddev.mode_config.poll_enabled);
1328 
1329 	drm_kms_helper_poll_fini(&adev->ddev);
1330 }
1331 
1332 /**
1333  * dm_test_irq_resume_early_registered - Test early resume reaches irq set
1334  * @test: The KUnit test context
1335  *
1336  * Registers a low-context HPD RX handler so early resume calls
1337  * amdgpu_dm_irq_set() for the short-pulse interrupt source.
1338  */
dm_test_irq_resume_early_registered(struct kunit * test)1339 static void dm_test_irq_resume_early_registered(struct kunit *test)
1340 {
1341 	struct dc_interrupt_params int_params = { 0 };
1342 	struct amdgpu_device *adev;
1343 	void *handler;
1344 
1345 	adev = dm_kunit_alloc_adev(test);
1346 	KUNIT_ASSERT_EQ(test, amdgpu_dm_irq_init(adev), 0);
1347 
1348 	int_params.int_context = INTERRUPT_LOW_IRQ_CONTEXT;
1349 	int_params.irq_source = DC_IRQ_SOURCE_HPD1RX;
1350 	handler = amdgpu_dm_irq_register_interrupt(adev, &int_params,
1351 						   dm_test_irq_handler, adev);
1352 	KUNIT_ASSERT_NOT_ERR_OR_NULL(test, handler);
1353 
1354 	amdgpu_dm_irq_resume_early(adev);
1355 
1356 	amdgpu_dm_irq_unregister_interrupt(adev, DC_IRQ_SOURCE_HPD1RX,
1357 					   dm_test_irq_handler);
1358 }
1359 
1360 /**
1361  * dm_test_irq_resume_late_registered - Test late resume reaches irq set
1362  * @test: The KUnit test context
1363  *
1364  * Registers a low-context HPD handler so late resume calls amdgpu_dm_irq_set()
1365  * for the HPD interrupt source.
1366  */
dm_test_irq_resume_late_registered(struct kunit * test)1367 static void dm_test_irq_resume_late_registered(struct kunit *test)
1368 {
1369 	struct dc_interrupt_params int_params = { 0 };
1370 	struct amdgpu_device *adev;
1371 	void *handler;
1372 
1373 	adev = dm_kunit_alloc_adev(test);
1374 	KUNIT_ASSERT_EQ(test, amdgpu_dm_irq_init(adev), 0);
1375 
1376 	int_params.int_context = INTERRUPT_LOW_IRQ_CONTEXT;
1377 	int_params.irq_source = DC_IRQ_SOURCE_HPD1;
1378 	handler = amdgpu_dm_irq_register_interrupt(adev, &int_params,
1379 						   dm_test_irq_handler, adev);
1380 	KUNIT_ASSERT_NOT_ERR_OR_NULL(test, handler);
1381 
1382 	amdgpu_dm_irq_resume_late(adev);
1383 
1384 	amdgpu_dm_irq_unregister_interrupt(adev, DC_IRQ_SOURCE_HPD1,
1385 					   dm_test_irq_handler);
1386 }
1387 
1388 /**
1389  * dm_test_irq_resume_late_enables_polling - Test late resume re-enables polling
1390  * @test: The KUnit test context
1391  *
1392  * With KMS polling active, late resume must take the poll-enable branch and
1393  * leave polling enabled.
1394  */
dm_test_irq_resume_late_enables_polling(struct kunit * test)1395 static void dm_test_irq_resume_late_enables_polling(struct kunit *test)
1396 {
1397 	struct amdgpu_device *adev;
1398 
1399 	adev = dm_kunit_alloc_adev(test);
1400 	KUNIT_ASSERT_EQ(test, amdgpu_dm_irq_init(adev), 0);
1401 
1402 	/* Enable KMS polling so resume_late takes the poll-enable branch. */
1403 	drm_kms_helper_poll_init(&adev->ddev);
1404 	KUNIT_ASSERT_TRUE(test, adev->ddev.mode_config.poll_enabled);
1405 
1406 	amdgpu_dm_irq_resume_late(adev);
1407 
1408 	KUNIT_EXPECT_TRUE(test, adev->ddev.mode_config.poll_enabled);
1409 
1410 	drm_kms_helper_poll_fini(&adev->ddev);
1411 }
1412 
1413 /* Tests for amdgpu_dm_hpd_rx_irq_create_workqueue() */
1414 
1415 /**
1416  * dm_test_hpd_rx_irq_create_workqueue - Test workqueue array creation
1417  * @test: The KUnit test context
1418  */
dm_test_hpd_rx_irq_create_workqueue(struct kunit * test)1419 static void dm_test_hpd_rx_irq_create_workqueue(struct kunit *test)
1420 {
1421 	struct dm_test_hpd_rx_wq_ctx *ctx;
1422 	struct amdgpu_device *adev;
1423 	struct dc *dc;
1424 	int i;
1425 
1426 	adev = dm_kunit_alloc_adev(test);
1427 
1428 	dc = kunit_kzalloc(test, sizeof(*dc), GFP_KERNEL);
1429 	KUNIT_ASSERT_NOT_ERR_OR_NULL(test, dc);
1430 	dc->caps.max_links = 4;
1431 	adev->dm.dc = dc;
1432 
1433 	ctx = kunit_kzalloc(test, sizeof(*ctx), GFP_KERNEL);
1434 	KUNIT_ASSERT_NOT_ERR_OR_NULL(test, ctx);
1435 
1436 	ctx->wq = amdgpu_dm_hpd_rx_irq_create_workqueue(adev);
1437 	KUNIT_ASSERT_NOT_NULL(test, ctx->wq);
1438 	ctx->count = dc->caps.max_links;
1439 	KUNIT_ASSERT_EQ(test, kunit_add_action_or_reset(test, dm_test_destroy_hpd_rx_wq, ctx), 0);
1440 
1441 	for (i = 0; i < dc->caps.max_links; i++)
1442 		KUNIT_EXPECT_TRUE(test, ctx->wq[i].wq != NULL);
1443 }
1444 
1445 /* Tests for amdgpu_dm_hpd_rx_irq_work_suspend() */
1446 
1447 /**
1448  * dm_test_hpd_rx_irq_work_suspend_null - Test suspend with no work queue
1449  * @test: The KUnit test context
1450  */
dm_test_hpd_rx_irq_work_suspend_null(struct kunit * test)1451 static void dm_test_hpd_rx_irq_work_suspend_null(struct kunit *test)
1452 {
1453 	struct amdgpu_display_manager *dm;
1454 
1455 	dm = kunit_kzalloc(test, sizeof(*dm), GFP_KERNEL);
1456 	KUNIT_ASSERT_NOT_ERR_OR_NULL(test, dm);
1457 
1458 	/* A NULL hpd_rx_offload_wq must be a safe no-op (DC untouched). */
1459 	amdgpu_dm_hpd_rx_irq_work_suspend(dm);
1460 }
1461 
1462 /**
1463  * dm_test_hpd_rx_irq_work_suspend_flushes - Test suspend flushes queues
1464  * @test: The KUnit test context
1465  */
dm_test_hpd_rx_irq_work_suspend_flushes(struct kunit * test)1466 static void dm_test_hpd_rx_irq_work_suspend_flushes(struct kunit *test)
1467 {
1468 	struct dm_test_hpd_rx_wq_ctx *ctx;
1469 	struct amdgpu_device *adev;
1470 	struct dc *dc;
1471 
1472 	adev = dm_kunit_alloc_adev(test);
1473 
1474 	dc = kunit_kzalloc(test, sizeof(*dc), GFP_KERNEL);
1475 	KUNIT_ASSERT_NOT_ERR_OR_NULL(test, dc);
1476 	dc->caps.max_links = 2;
1477 	adev->dm.dc = dc;
1478 
1479 	ctx = kunit_kzalloc(test, sizeof(*ctx), GFP_KERNEL);
1480 	KUNIT_ASSERT_NOT_ERR_OR_NULL(test, ctx);
1481 
1482 	ctx->wq = amdgpu_dm_hpd_rx_irq_create_workqueue(adev);
1483 	KUNIT_ASSERT_NOT_NULL(test, ctx->wq);
1484 	ctx->count = dc->caps.max_links;
1485 	KUNIT_ASSERT_EQ(test, kunit_add_action_or_reset(test, dm_test_destroy_hpd_rx_wq, ctx), 0);
1486 
1487 	adev->dm.hpd_rx_offload_wq = ctx->wq;
1488 
1489 	amdgpu_dm_hpd_rx_irq_work_suspend(&adev->dm);
1490 }
1491 
1492 /* Tests for CRTC-based irq state callbacks (no-CRTC early return) */
1493 
1494 /**
1495  * dm_test_set_crtc_irq_state_no_crtc - Test crtc irq state with missing CRTC
1496  * @test: The KUnit test context
1497  */
dm_test_set_crtc_irq_state_no_crtc(struct kunit * test)1498 static void dm_test_set_crtc_irq_state_no_crtc(struct kunit *test)
1499 {
1500 	struct amdgpu_device *adev;
1501 
1502 	adev = kunit_kzalloc(test, sizeof(*adev), GFP_KERNEL);
1503 	KUNIT_ASSERT_NOT_ERR_OR_NULL(test, adev);
1504 
1505 	/* mode_info.crtcs[0] is NULL -> returns 0 without dereferencing DC. */
1506 	KUNIT_EXPECT_EQ(test,
1507 			amdgpu_dm_set_crtc_irq_state(adev, NULL, 0, AMDGPU_IRQ_STATE_ENABLE), 0);
1508 }
1509 
1510 /**
1511  * dm_test_set_pflip_irq_state_no_crtc - Test pflip irq state with missing CRTC
1512  * @test: The KUnit test context
1513  */
dm_test_set_pflip_irq_state_no_crtc(struct kunit * test)1514 static void dm_test_set_pflip_irq_state_no_crtc(struct kunit *test)
1515 {
1516 	struct amdgpu_device *adev;
1517 
1518 	adev = kunit_kzalloc(test, sizeof(*adev), GFP_KERNEL);
1519 	KUNIT_ASSERT_NOT_ERR_OR_NULL(test, adev);
1520 
1521 	KUNIT_EXPECT_EQ(test,
1522 			amdgpu_dm_set_pflip_irq_state(adev, NULL, 0, AMDGPU_IRQ_STATE_DISABLE), 0);
1523 }
1524 
1525 /**
1526  * dm_test_set_vline0_irq_state_no_crtc - Test vline0 irq state with missing CRTC
1527  * @test: The KUnit test context
1528  */
dm_test_set_vline0_irq_state_no_crtc(struct kunit * test)1529 static void dm_test_set_vline0_irq_state_no_crtc(struct kunit *test)
1530 {
1531 	struct amdgpu_device *adev;
1532 
1533 	adev = kunit_kzalloc(test, sizeof(*adev), GFP_KERNEL);
1534 	KUNIT_ASSERT_NOT_ERR_OR_NULL(test, adev);
1535 
1536 	KUNIT_EXPECT_EQ(test,
1537 			amdgpu_dm_set_vline0_irq_state(adev, NULL, 0, AMDGPU_IRQ_STATE_ENABLE), 0);
1538 }
1539 
1540 /**
1541  * dm_test_set_vupdate_irq_state_no_crtc - Test vupdate irq state with missing CRTC
1542  * @test: The KUnit test context
1543  */
dm_test_set_vupdate_irq_state_no_crtc(struct kunit * test)1544 static void dm_test_set_vupdate_irq_state_no_crtc(struct kunit *test)
1545 {
1546 	struct amdgpu_device *adev;
1547 
1548 	adev = kunit_kzalloc(test, sizeof(*adev), GFP_KERNEL);
1549 	KUNIT_ASSERT_NOT_ERR_OR_NULL(test, adev);
1550 
1551 	KUNIT_EXPECT_EQ(test,
1552 			amdgpu_dm_set_vupdate_irq_state(adev, NULL, 0, AMDGPU_IRQ_STATE_ENABLE), 0);
1553 }
1554 
1555 /* Tests for CRTC-based irq state callbacks (dm_irq_state happy path) */
1556 
1557 /**
1558  * dm_test_set_crtc_irq_state_otg_disabled - Test crtc irq state with disabled OTG
1559  * @test: The KUnit test context
1560  */
dm_test_set_crtc_irq_state_otg_disabled(struct kunit * test)1561 static void dm_test_set_crtc_irq_state_otg_disabled(struct kunit *test)
1562 {
1563 	struct amdgpu_device *adev;
1564 	struct amdgpu_crtc *acrtc;
1565 
1566 	adev = kunit_kzalloc(test, sizeof(*adev), GFP_KERNEL);
1567 	KUNIT_ASSERT_NOT_ERR_OR_NULL(test, adev);
1568 	acrtc = kunit_kzalloc(test, sizeof(*acrtc), GFP_KERNEL);
1569 	KUNIT_ASSERT_NOT_ERR_OR_NULL(test, acrtc);
1570 
1571 	/* otg_inst == -1 short-circuits before computing the irq source. */
1572 	acrtc->otg_inst = -1;
1573 	adev->mode_info.crtcs[0] = acrtc;
1574 
1575 	KUNIT_EXPECT_EQ(test,
1576 			amdgpu_dm_set_crtc_irq_state(adev, NULL, 0, AMDGPU_IRQ_STATE_ENABLE), 0);
1577 }
1578 
1579 /**
1580  * dm_test_set_crtc_irq_state_enable - Test crtc irq state reaches DC (enable)
1581  * @test: The KUnit test context
1582  */
dm_test_set_crtc_irq_state_enable(struct kunit * test)1583 static void dm_test_set_crtc_irq_state_enable(struct kunit *test)
1584 {
1585 	struct amdgpu_device *adev;
1586 	struct amdgpu_crtc *acrtc;
1587 
1588 	adev = kunit_kzalloc(test, sizeof(*adev), GFP_KERNEL);
1589 	KUNIT_ASSERT_NOT_ERR_OR_NULL(test, adev);
1590 	acrtc = kunit_kzalloc(test, sizeof(*acrtc), GFP_KERNEL);
1591 	KUNIT_ASSERT_NOT_ERR_OR_NULL(test, acrtc);
1592 
1593 	/*
1594 	 * otg_inst >= 0 computes the irq source and reaches the NULL-safe
1595 	 * amdgpu_dm_irq_set(); the ips_support branch is skipped (dc == NULL).
1596 	 */
1597 	acrtc->otg_inst = 3;
1598 	adev->mode_info.crtcs[0] = acrtc;
1599 
1600 	KUNIT_EXPECT_EQ(test,
1601 			amdgpu_dm_set_crtc_irq_state(adev, NULL, 0, AMDGPU_IRQ_STATE_ENABLE), 0);
1602 }
1603 
1604 /**
1605  * dm_test_set_pflip_irq_state_disable - Test pflip irq state reaches DC (disable)
1606  * @test: The KUnit test context
1607  */
dm_test_set_pflip_irq_state_disable(struct kunit * test)1608 static void dm_test_set_pflip_irq_state_disable(struct kunit *test)
1609 {
1610 	struct amdgpu_device *adev;
1611 	struct amdgpu_crtc *acrtc;
1612 
1613 	adev = kunit_kzalloc(test, sizeof(*adev), GFP_KERNEL);
1614 	KUNIT_ASSERT_NOT_ERR_OR_NULL(test, adev);
1615 	acrtc = kunit_kzalloc(test, sizeof(*acrtc), GFP_KERNEL);
1616 	KUNIT_ASSERT_NOT_ERR_OR_NULL(test, acrtc);
1617 
1618 	/* The disable state exercises the st == false path. */
1619 	acrtc->otg_inst = 1;
1620 	adev->mode_info.crtcs[0] = acrtc;
1621 
1622 	KUNIT_EXPECT_EQ(test,
1623 			amdgpu_dm_set_pflip_irq_state(adev, NULL, 0, AMDGPU_IRQ_STATE_DISABLE), 0);
1624 }
1625 
1626 /**
1627  * dm_test_set_vline0_irq_state_enable - Test vline0 irq state reaches DC (enable)
1628  * @test: The KUnit test context
1629  */
dm_test_set_vline0_irq_state_enable(struct kunit * test)1630 static void dm_test_set_vline0_irq_state_enable(struct kunit *test)
1631 {
1632 	struct amdgpu_device *adev;
1633 	struct amdgpu_crtc *acrtc;
1634 
1635 	adev = kunit_kzalloc(test, sizeof(*adev), GFP_KERNEL);
1636 	KUNIT_ASSERT_NOT_ERR_OR_NULL(test, adev);
1637 	acrtc = kunit_kzalloc(test, sizeof(*acrtc), GFP_KERNEL);
1638 	KUNIT_ASSERT_NOT_ERR_OR_NULL(test, acrtc);
1639 
1640 	acrtc->otg_inst = 0;
1641 	adev->mode_info.crtcs[0] = acrtc;
1642 
1643 	KUNIT_EXPECT_EQ(test,
1644 			amdgpu_dm_set_vline0_irq_state(adev, NULL, 0, AMDGPU_IRQ_STATE_ENABLE), 0);
1645 }
1646 
1647 /**
1648  * dm_test_set_vupdate_irq_state_enable - Test vupdate irq state reaches DC (enable)
1649  * @test: The KUnit test context
1650  */
dm_test_set_vupdate_irq_state_enable(struct kunit * test)1651 static void dm_test_set_vupdate_irq_state_enable(struct kunit *test)
1652 {
1653 	struct amdgpu_device *adev;
1654 	struct amdgpu_crtc *acrtc;
1655 
1656 	adev = kunit_kzalloc(test, sizeof(*adev), GFP_KERNEL);
1657 	KUNIT_ASSERT_NOT_ERR_OR_NULL(test, adev);
1658 	acrtc = kunit_kzalloc(test, sizeof(*acrtc), GFP_KERNEL);
1659 	KUNIT_ASSERT_NOT_ERR_OR_NULL(test, acrtc);
1660 
1661 	acrtc->otg_inst = 2;
1662 	adev->mode_info.crtcs[0] = acrtc;
1663 
1664 	KUNIT_EXPECT_EQ(test,
1665 			amdgpu_dm_set_vupdate_irq_state(adev, NULL, 0, AMDGPU_IRQ_STATE_ENABLE), 0);
1666 }
1667 
1668 /**
1669  * dm_test_set_crtc_irq_state_allows_idle - Test the idle-optimization branch
1670  * @test: The KUnit test context
1671  *
1672  * With a non-NULL DC that advertises IPS support and currently allows idle
1673  * optimizations, dm_irq_state() must call dc_allow_idle_optimizations() before
1674  * amdgpu_dm_irq_set(). disable_idle_power_optimizations makes that call a safe
1675  * early return, and per-source stub funcs let amdgpu_dm_irq_set() succeed.
1676  */
dm_test_set_crtc_irq_state_allows_idle(struct kunit * test)1677 static void dm_test_set_crtc_irq_state_allows_idle(struct kunit *test)
1678 {
1679 	struct amdgpu_device *adev;
1680 	struct amdgpu_crtc *acrtc;
1681 	struct dal_logger *logger;
1682 	struct dc *dc;
1683 
1684 	adev = dm_kunit_alloc_adev(test);
1685 	acrtc = kunit_kzalloc(test, sizeof(*acrtc), GFP_KERNEL);
1686 	KUNIT_ASSERT_NOT_ERR_OR_NULL(test, acrtc);
1687 
1688 	dc = dm_test_alloc_dc_with_irq_service(test, &dm_test_irq_service_funcs_dcn10);
1689 
1690 	/* DC_LOG_* dereferences ctx->logger->dev, so wire a real drm device. */
1691 	logger = kunit_kzalloc(test, sizeof(*logger), GFP_KERNEL);
1692 	KUNIT_ASSERT_NOT_ERR_OR_NULL(test, logger);
1693 	logger->dev = &adev->ddev;
1694 	dc->ctx->logger = logger;
1695 
1696 	dc->caps.ips_support = true;
1697 	dc->idle_optimizations_allowed = true;
1698 	/* Keep dc_allow_idle_optimizations() a safe early return. */
1699 	dc->debug.disable_idle_power_optimizations = true;
1700 	adev->dm.dc = dc;
1701 
1702 	acrtc->otg_inst = 0;
1703 	adev->mode_info.crtcs[0] = acrtc;
1704 
1705 	KUNIT_EXPECT_EQ(test,
1706 			amdgpu_dm_set_crtc_irq_state(adev, NULL, 0, AMDGPU_IRQ_STATE_ENABLE), 0);
1707 }
1708 
1709 /* Tests for amdgpu_dm_irq_immediate_work() */
1710 
1711 /**
1712  * dm_test_irq_immediate_work_empty - Test immediate work on empty high table
1713  * @test: The KUnit test context
1714  */
dm_test_irq_immediate_work_empty(struct kunit * test)1715 static void dm_test_irq_immediate_work_empty(struct kunit *test)
1716 {
1717 	struct amdgpu_device *adev;
1718 
1719 	adev = kunit_kzalloc(test, sizeof(*adev), GFP_KERNEL);
1720 	KUNIT_ASSERT_NOT_ERR_OR_NULL(test, adev);
1721 	KUNIT_ASSERT_EQ(test, amdgpu_dm_irq_init(adev), 0);
1722 
1723 	/* No registered high-context handlers: must be a safe no-op. */
1724 	amdgpu_dm_irq_immediate_work(adev, DC_IRQ_SOURCE_HPD1);
1725 }
1726 
1727 /**
1728  * dm_test_irq_immediate_work_invokes_handler - Test immediate work calls handler
1729  * @test: The KUnit test context
1730  */
dm_test_irq_immediate_work_invokes_handler(struct kunit * test)1731 static void dm_test_irq_immediate_work_invokes_handler(struct kunit *test)
1732 {
1733 	struct amdgpu_device *adev;
1734 	struct dc_interrupt_params int_params = { 0 };
1735 	int count = 0;
1736 	void *handler;
1737 
1738 	adev = kunit_kzalloc(test, sizeof(*adev), GFP_KERNEL);
1739 	KUNIT_ASSERT_NOT_ERR_OR_NULL(test, adev);
1740 	KUNIT_ASSERT_EQ(test, amdgpu_dm_irq_init(adev), 0);
1741 
1742 	int_params.int_context = INTERRUPT_HIGH_IRQ_CONTEXT;
1743 	int_params.irq_source = DC_IRQ_SOURCE_HPD1;
1744 	handler = amdgpu_dm_irq_register_interrupt(adev, &int_params,
1745 						   dm_test_irq_handler_count, &count);
1746 	KUNIT_ASSERT_NOT_ERR_OR_NULL(test, handler);
1747 
1748 	/* High-context handlers are invoked synchronously, in-place. */
1749 	amdgpu_dm_irq_immediate_work(adev, DC_IRQ_SOURCE_HPD1);
1750 	KUNIT_EXPECT_EQ(test, count, 1);
1751 
1752 	amdgpu_dm_irq_unregister_interrupt(adev, DC_IRQ_SOURCE_HPD1, dm_test_irq_handler_count);
1753 }
1754 
1755 /**
1756  * dm_test_irq_immediate_work_invokes_all - Test immediate work calls all handlers
1757  * @test: The KUnit test context
1758  */
dm_test_irq_immediate_work_invokes_all(struct kunit * test)1759 static void dm_test_irq_immediate_work_invokes_all(struct kunit *test)
1760 {
1761 	struct amdgpu_device *adev;
1762 	struct dc_interrupt_params int_params = { 0 };
1763 	int count = 0;
1764 	void *handler;
1765 
1766 	adev = kunit_kzalloc(test, sizeof(*adev), GFP_KERNEL);
1767 	KUNIT_ASSERT_NOT_ERR_OR_NULL(test, adev);
1768 	KUNIT_ASSERT_EQ(test, amdgpu_dm_irq_init(adev), 0);
1769 
1770 	int_params.int_context = INTERRUPT_HIGH_IRQ_CONTEXT;
1771 	int_params.irq_source = DC_IRQ_SOURCE_HPD2;
1772 	handler = amdgpu_dm_irq_register_interrupt(adev, &int_params,
1773 						   dm_test_irq_handler_count, &count);
1774 	KUNIT_ASSERT_NOT_ERR_OR_NULL(test, handler);
1775 	handler = amdgpu_dm_irq_register_interrupt(adev, &int_params,
1776 						   dm_test_irq_handler_count, &count);
1777 	KUNIT_ASSERT_NOT_ERR_OR_NULL(test, handler);
1778 
1779 	/* Both registered high-context handlers must run. */
1780 	amdgpu_dm_irq_immediate_work(adev, DC_IRQ_SOURCE_HPD2);
1781 	KUNIT_EXPECT_EQ(test, count, 2);
1782 
1783 	amdgpu_dm_irq_unregister_interrupt(adev, DC_IRQ_SOURCE_HPD2, dm_test_irq_handler_count);
1784 	amdgpu_dm_irq_unregister_interrupt(adev, DC_IRQ_SOURCE_HPD2, dm_test_irq_handler_count);
1785 }
1786 
1787 /* Tests for amdgpu_dm_irq_schedule_work() */
1788 
1789 /**
1790  * dm_test_irq_schedule_work_empty - Test schedule work on empty low table
1791  * @test: The KUnit test context
1792  */
dm_test_irq_schedule_work_empty(struct kunit * test)1793 static void dm_test_irq_schedule_work_empty(struct kunit *test)
1794 {
1795 	struct amdgpu_device *adev;
1796 
1797 	adev = kunit_kzalloc(test, sizeof(*adev), GFP_KERNEL);
1798 	KUNIT_ASSERT_NOT_ERR_OR_NULL(test, adev);
1799 	KUNIT_ASSERT_EQ(test, amdgpu_dm_irq_init(adev), 0);
1800 
1801 	/* Empty handler list: schedule_work returns immediately. */
1802 	amdgpu_dm_irq_schedule_work(adev, DC_IRQ_SOURCE_HPD1);
1803 }
1804 
1805 /**
1806  * dm_test_irq_schedule_work_queues_handler - Test schedule work runs handler
1807  * @test: The KUnit test context
1808  */
dm_test_irq_schedule_work_queues_handler(struct kunit * test)1809 static void dm_test_irq_schedule_work_queues_handler(struct kunit *test)
1810 {
1811 	struct amdgpu_device *adev;
1812 	struct dc_interrupt_params int_params = { 0 };
1813 	int count = 0;
1814 	void *handler;
1815 
1816 	adev = kunit_kzalloc(test, sizeof(*adev), GFP_KERNEL);
1817 	KUNIT_ASSERT_NOT_ERR_OR_NULL(test, adev);
1818 	KUNIT_ASSERT_EQ(test, amdgpu_dm_irq_init(adev), 0);
1819 
1820 	int_params.int_context = INTERRUPT_LOW_IRQ_CONTEXT;
1821 	int_params.irq_source = DC_IRQ_SOURCE_HPD1;
1822 	handler = amdgpu_dm_irq_register_interrupt(adev, &int_params,
1823 						   dm_test_irq_handler_count, &count);
1824 	KUNIT_ASSERT_NOT_ERR_OR_NULL(test, handler);
1825 
1826 	amdgpu_dm_irq_schedule_work(adev, DC_IRQ_SOURCE_HPD1);
1827 
1828 	/*
1829 	 * Low-context work runs asynchronously on the DM IRQ workqueue.
1830 	 * Flush it so the handler completes before we check the count;
1831 	 * amdgpu_dm_irq_fini() cancels (rather than runs) any work that is
1832 	 * still pending, so the flush must happen first.
1833 	 */
1834 	flush_workqueue(adev->dm.irq_wq);
1835 	KUNIT_EXPECT_EQ(test, count, 1);
1836 
1837 	amdgpu_dm_irq_fini(adev);
1838 }
1839 
1840 /**
1841  * dm_test_irq_schedule_work_requeue_fallback - Test the re-queue fallback path
1842  * @test: The KUnit test context
1843  *
1844  * The first schedule queues the handler's work item. Issuing a second
1845  * schedule before the work has run makes queue_work() fail for the
1846  * still-pending item, forcing amdgpu_dm_irq_schedule_work() into the fallback
1847  * that allocates and queues a fresh handler copy. Both work items run when
1848  * the DM IRQ workqueue is flushed, so the handler fires twice.
1849  */
dm_test_irq_schedule_work_requeue_fallback(struct kunit * test)1850 static void dm_test_irq_schedule_work_requeue_fallback(struct kunit *test)
1851 {
1852 	struct dc_interrupt_params int_params = { 0 };
1853 	struct amdgpu_device *adev;
1854 	int count = 0;
1855 	void *handler;
1856 
1857 	adev = kunit_kzalloc(test, sizeof(*adev), GFP_KERNEL);
1858 	KUNIT_ASSERT_NOT_ERR_OR_NULL(test, adev);
1859 	KUNIT_ASSERT_EQ(test, amdgpu_dm_irq_init(adev), 0);
1860 
1861 	int_params.int_context = INTERRUPT_LOW_IRQ_CONTEXT;
1862 	int_params.irq_source = DC_IRQ_SOURCE_HPD1;
1863 	handler = amdgpu_dm_irq_register_interrupt(adev, &int_params,
1864 						   dm_test_irq_handler_count, &count);
1865 	KUNIT_ASSERT_NOT_ERR_OR_NULL(test, handler);
1866 
1867 	amdgpu_dm_irq_schedule_work(adev, DC_IRQ_SOURCE_HPD1);
1868 	amdgpu_dm_irq_schedule_work(adev, DC_IRQ_SOURCE_HPD1);
1869 
1870 	/*
1871 	 * Flush the DM IRQ workqueue so both work items run before we check
1872 	 * the count; amdgpu_dm_irq_fini() would cancel any still-pending work
1873 	 * instead of running it.
1874 	 */
1875 	flush_workqueue(adev->dm.irq_wq);
1876 	KUNIT_EXPECT_EQ(test, count, 2);
1877 
1878 	amdgpu_dm_irq_fini(adev);
1879 }
1880 
1881 /* Tests for amdgpu_dm_set_hpd_irq_state() */
1882 
1883 /**
1884  * dm_test_set_hpd_irq_state_null_dc - Test HPD irq state with no DC
1885  * @test: The KUnit test context
1886  */
dm_test_set_hpd_irq_state_null_dc(struct kunit * test)1887 static void dm_test_set_hpd_irq_state_null_dc(struct kunit *test)
1888 {
1889 	struct amdgpu_device *adev;
1890 
1891 	adev = kunit_kzalloc(test, sizeof(*adev), GFP_KERNEL);
1892 	KUNIT_ASSERT_NOT_ERR_OR_NULL(test, adev);
1893 
1894 	/* amdgpu_dm_irq_set() is a no-op when dc is NULL, so both states
1895 	 * return 0 without dereferencing the (absent) DC.
1896 	 */
1897 	KUNIT_EXPECT_EQ(test, amdgpu_dm_set_hpd_irq_state(adev, NULL, AMDGPU_HPD_1,
1898 							  AMDGPU_IRQ_STATE_ENABLE), 0);
1899 	KUNIT_EXPECT_EQ(test, amdgpu_dm_set_hpd_irq_state(adev, NULL, AMDGPU_HPD_1,
1900 							  AMDGPU_IRQ_STATE_DISABLE), 0);
1901 }
1902 
1903 /* Tests for amdgpu_dm_set_dmub_outbox_irq_state() */
1904 
1905 /**
1906  * dm_test_set_dmub_outbox_irq_state_null_dc - Test outbox irq state with no DC
1907  * @test: The KUnit test context
1908  */
dm_test_set_dmub_outbox_irq_state_null_dc(struct kunit * test)1909 static void dm_test_set_dmub_outbox_irq_state_null_dc(struct kunit *test)
1910 {
1911 	struct amdgpu_device *adev;
1912 
1913 	adev = kunit_kzalloc(test, sizeof(*adev), GFP_KERNEL);
1914 	KUNIT_ASSERT_NOT_ERR_OR_NULL(test, adev);
1915 
1916 	KUNIT_EXPECT_EQ(test, amdgpu_dm_set_dmub_outbox_irq_state(adev, NULL, 0,
1917 								  AMDGPU_IRQ_STATE_ENABLE), 0);
1918 	KUNIT_EXPECT_EQ(test, amdgpu_dm_set_dmub_outbox_irq_state(adev, NULL, 0,
1919 								  AMDGPU_IRQ_STATE_DISABLE), 0);
1920 }
1921 
1922 /* Tests for amdgpu_dm_set_dmub_trace_irq_state() */
1923 
1924 /**
1925  * dm_test_set_dmub_trace_irq_state_null_dc - Test trace irq state with no DC
1926  * @test: The KUnit test context
1927  */
dm_test_set_dmub_trace_irq_state_null_dc(struct kunit * test)1928 static void dm_test_set_dmub_trace_irq_state_null_dc(struct kunit *test)
1929 {
1930 	struct amdgpu_device *adev;
1931 
1932 	adev = kunit_kzalloc(test, sizeof(*adev), GFP_KERNEL);
1933 	KUNIT_ASSERT_NOT_ERR_OR_NULL(test, adev);
1934 
1935 	KUNIT_EXPECT_EQ(test, amdgpu_dm_set_dmub_trace_irq_state(adev, NULL, 0,
1936 								 AMDGPU_IRQ_STATE_ENABLE), 0);
1937 	KUNIT_EXPECT_EQ(test, amdgpu_dm_set_dmub_trace_irq_state(adev, NULL, 0,
1938 								 AMDGPU_IRQ_STATE_DISABLE), 0);
1939 }
1940 
1941 /* Tests for amdgpu_dm_outbox_init() */
1942 
1943 /**
1944  * dm_test_outbox_init_null_dc - Test outbox init is a safe no-op with no DC
1945  * @test: The KUnit test context
1946  */
dm_test_outbox_init_null_dc(struct kunit * test)1947 static void dm_test_outbox_init_null_dc(struct kunit *test)
1948 {
1949 	struct amdgpu_device *adev;
1950 
1951 	adev = kunit_kzalloc(test, sizeof(*adev), GFP_KERNEL);
1952 	KUNIT_ASSERT_NOT_ERR_OR_NULL(test, adev);
1953 
1954 	/* Single amdgpu_dm_irq_set() call must be skipped when dc is NULL. */
1955 	amdgpu_dm_outbox_init(adev);
1956 }
1957 
1958 /* Tests for amdgpu_dm_hpd_init()/amdgpu_dm_hpd_fini() */
1959 
1960 /**
1961  * dm_test_hpd_init_empty_connectors - Test HPD init with no connectors
1962  * @test: The KUnit test context
1963  */
dm_test_hpd_init_empty_connectors(struct kunit * test)1964 static void dm_test_hpd_init_empty_connectors(struct kunit *test)
1965 {
1966 	struct amdgpu_device *adev;
1967 
1968 	adev = dm_kunit_alloc_adev(test);
1969 
1970 	/*
1971 	 * With an empty connector list the per-connector loop is skipped and
1972 	 * the initial clear loop relies on amdgpu_dm_irq_set() being a no-op
1973 	 * for a NULL dc, so init must complete without touching the DC.
1974 	 */
1975 	amdgpu_dm_hpd_init(adev);
1976 }
1977 
1978 /**
1979  * dm_test_hpd_fini_empty_connectors - Test HPD fini with no connectors
1980  * @test: The KUnit test context
1981  */
dm_test_hpd_fini_empty_connectors(struct kunit * test)1982 static void dm_test_hpd_fini_empty_connectors(struct kunit *test)
1983 {
1984 	struct amdgpu_device *adev;
1985 
1986 	adev = dm_kunit_alloc_adev(test);
1987 
1988 	/* Empty connector list and disabled polling: fini is a safe no-op. */
1989 	amdgpu_dm_hpd_fini(adev);
1990 }
1991 
1992 /**
1993  * dm_test_hpd_init_fini_with_connectors - Test HPD init/fini walk connectors
1994  * @test: The KUnit test context
1995  */
dm_test_hpd_init_fini_with_connectors(struct kunit * test)1996 static void dm_test_hpd_init_fini_with_connectors(struct kunit *test)
1997 {
1998 	struct amdgpu_dm_connector *aconn;
1999 	struct drm_connector *wbconn;
2000 	struct amdgpu_device *adev;
2001 	struct dc_link *link;
2002 
2003 	adev = dm_kunit_alloc_adev(test);
2004 
2005 	/*
2006 	 * num_hpd = 0 forces irq_type >= num_hpd so the loop takes the HW
2007 	 * fallback (amdgpu_dm_irq_set()) instead of amdgpu_irq_get(); with a
2008 	 * NULL dc that fallback is a safe no-op.
2009 	 */
2010 	adev->mode_info.num_hpd = 0;
2011 
2012 	/* A writeback connector must be skipped by the per-connector loop. */
2013 	wbconn = kunit_kzalloc(test, sizeof(*wbconn), GFP_KERNEL);
2014 	KUNIT_ASSERT_NOT_ERR_OR_NULL(test, wbconn);
2015 	KUNIT_ASSERT_EQ(test, drm_connector_init(&adev->ddev, wbconn, &dm_test_connector_funcs,
2016 						 DRM_MODE_CONNECTOR_WRITEBACK), 0);
2017 	KUNIT_ASSERT_EQ(test,
2018 			kunit_add_action_or_reset(test, dm_test_connector_cleanup, wbconn), 0);
2019 
2020 	/* A DisplayPort connector with a dc_link exercises the loop body. */
2021 	aconn = kunit_kzalloc(test, sizeof(*aconn), GFP_KERNEL);
2022 	KUNIT_ASSERT_NOT_ERR_OR_NULL(test, aconn);
2023 	KUNIT_ASSERT_EQ(test, drm_connector_init(&adev->ddev, &aconn->base,
2024 						 &dm_test_connector_funcs,
2025 						 DRM_MODE_CONNECTOR_DisplayPort), 0);
2026 	KUNIT_ASSERT_EQ(test,
2027 			kunit_add_action_or_reset(test, dm_test_connector_cleanup, &aconn->base), 0);
2028 
2029 	link = kunit_kzalloc(test, sizeof(*link), GFP_KERNEL);
2030 	KUNIT_ASSERT_NOT_ERR_OR_NULL(test, link);
2031 	link->irq_source_hpd = DC_IRQ_SOURCE_HPD1;
2032 	link->irq_source_hpd_rx = DC_IRQ_SOURCE_HPD1RX;
2033 	aconn->dc_link = link;
2034 
2035 	/* DC is absent (NULL), so the HW writes are NULL-safe no-ops. */
2036 	amdgpu_dm_hpd_init(adev);
2037 	amdgpu_dm_hpd_fini(adev);
2038 }
2039 
2040 /**
2041  * dm_test_hpd_init_fini_analog_connector - Test HPD init/fini analog polling path
2042  * @test: The KUnit test context
2043  */
dm_test_hpd_init_fini_analog_connector(struct kunit * test)2044 static void dm_test_hpd_init_fini_analog_connector(struct kunit *test)
2045 {
2046 	struct amdgpu_dm_connector *aconn;
2047 	struct amdgpu_device *adev;
2048 	struct dc_link *link;
2049 
2050 	adev = dm_kunit_alloc_adev(test);
2051 	adev->mode_info.num_hpd = 0;
2052 
2053 	aconn = kunit_kzalloc(test, sizeof(*aconn), GFP_KERNEL);
2054 	KUNIT_ASSERT_NOT_ERR_OR_NULL(test, aconn);
2055 	KUNIT_ASSERT_EQ(test, drm_connector_init(&adev->ddev, &aconn->base,
2056 						 &dm_test_connector_funcs,
2057 						 DRM_MODE_CONNECTOR_VGA), 0);
2058 	KUNIT_ASSERT_EQ(test,
2059 			kunit_add_action_or_reset(test, dm_test_connector_cleanup, &aconn->base), 0);
2060 
2061 	link = kunit_kzalloc(test, sizeof(*link), GFP_KERNEL);
2062 	KUNIT_ASSERT_NOT_ERR_OR_NULL(test, link);
2063 	link->irq_source_hpd = DC_IRQ_SOURCE_HPD1;
2064 	link->irq_source_hpd_rx = DC_IRQ_SOURCE_HPD1RX;
2065 	/* An analog connector id makes the loop request polling. */
2066 	link->link_id.id = CONNECTOR_ID_VGA;
2067 	aconn->dc_link = link;
2068 
2069 	/* use_polling becomes true, so init must enable KMS polling. */
2070 	amdgpu_dm_hpd_init(adev);
2071 	KUNIT_EXPECT_TRUE(test, adev->ddev.mode_config.poll_enabled);
2072 
2073 	/* fini must tear the polling back down. */
2074 	amdgpu_dm_hpd_fini(adev);
2075 	KUNIT_EXPECT_FALSE(test, adev->ddev.mode_config.poll_enabled);
2076 }
2077 
2078 /**
2079  * dm_test_hpd_init_fini_irq_ref - Test HPD init/fini base-driver irq ref path
2080  * @test: The KUnit test context
2081  */
dm_test_hpd_init_fini_irq_ref(struct kunit * test)2082 static void dm_test_hpd_init_fini_irq_ref(struct kunit *test)
2083 {
2084 	struct amdgpu_dm_connector *aconn;
2085 	struct amdgpu_device *adev;
2086 	struct dc_link *link;
2087 
2088 	adev = dm_kunit_alloc_adev(test);
2089 
2090 	/*
2091 	 * num_hpd >= 1 makes irq_type (0) < num_hpd, so the loop takes the
2092 	 * amdgpu_irq_get()/amdgpu_irq_put() branch instead of the
2093 	 * amdgpu_dm_irq_set() fallback. The mock device has irq.installed ==
2094 	 * false, so both calls fail early with -ENOENT (logging an error)
2095 	 * without touching the base-driver irq state.
2096 	 */
2097 	adev->mode_info.num_hpd = 1;
2098 
2099 	aconn = kunit_kzalloc(test, sizeof(*aconn), GFP_KERNEL);
2100 	KUNIT_ASSERT_NOT_ERR_OR_NULL(test, aconn);
2101 	KUNIT_ASSERT_EQ(test, drm_connector_init(&adev->ddev, &aconn->base,
2102 						 &dm_test_connector_funcs,
2103 						 DRM_MODE_CONNECTOR_DisplayPort), 0);
2104 	KUNIT_ASSERT_EQ(test,
2105 			kunit_add_action_or_reset(test, dm_test_connector_cleanup, &aconn->base), 0);
2106 
2107 	link = kunit_kzalloc(test, sizeof(*link), GFP_KERNEL);
2108 	KUNIT_ASSERT_NOT_ERR_OR_NULL(test, link);
2109 	link->irq_source_hpd = DC_IRQ_SOURCE_HPD1;
2110 	link->irq_source_hpd_rx = DC_IRQ_SOURCE_INVALID;
2111 	aconn->dc_link = link;
2112 
2113 	amdgpu_dm_hpd_init(adev);
2114 	amdgpu_dm_hpd_fini(adev);
2115 }
2116 
2117 /* Tests for dm_handle_hpd_rx_offload_work() */
2118 
2119 /**
2120  * dm_test_hpd_rx_offload_work_no_connector - Test missing connector early exit
2121  * @test: The KUnit test context
2122  */
dm_test_hpd_rx_offload_work_no_connector(struct kunit * test)2123 static void dm_test_hpd_rx_offload_work_no_connector(struct kunit *test)
2124 {
2125 	struct hpd_rx_irq_offload_work_queue *offload_wq;
2126 	struct hpd_rx_irq_offload_work *offload_work;
2127 	struct amdgpu_device *adev;
2128 
2129 	adev = dm_kunit_alloc_adev(test);
2130 
2131 	offload_wq = kunit_kzalloc(test, sizeof(*offload_wq), GFP_KERNEL);
2132 	KUNIT_ASSERT_NOT_ERR_OR_NULL(test, offload_wq);
2133 
2134 	offload_work = kzalloc_obj(*offload_work);
2135 	KUNIT_ASSERT_NOT_ERR_OR_NULL(test, offload_work);
2136 	offload_work->offload_wq = offload_wq;
2137 	offload_work->adev = adev;
2138 	INIT_WORK(&offload_work->work, dm_handle_hpd_rx_offload_work);
2139 
2140 	dm_handle_hpd_rx_offload_work(&offload_work->work);
2141 }
2142 
2143 /**
2144  * dm_test_hpd_rx_offload_work_no_connection - Test no connection early exit
2145  * @test: The KUnit test context
2146  */
dm_test_hpd_rx_offload_work_no_connection(struct kunit * test)2147 static void dm_test_hpd_rx_offload_work_no_connection(struct kunit *test)
2148 {
2149 	struct hpd_rx_irq_offload_work_queue *offload_wq;
2150 	struct hpd_rx_irq_offload_work *offload_work;
2151 	struct amdgpu_dm_connector *aconn;
2152 	struct link_service *link_srv;
2153 	struct amdgpu_device *adev;
2154 	struct dc_link *link;
2155 	struct dc *dc;
2156 
2157 	adev = dm_kunit_alloc_adev(test);
2158 	mutex_init(&adev->dm.dc_lock);
2159 
2160 	offload_wq = kunit_kzalloc(test, sizeof(*offload_wq), GFP_KERNEL);
2161 	KUNIT_ASSERT_NOT_ERR_OR_NULL(test, offload_wq);
2162 
2163 	aconn = dm_kunit_alloc_connector(test, adev, NULL);
2164 	mutex_init(&aconn->hpd_lock);
2165 	offload_wq->aconnector = aconn;
2166 
2167 	dc = kunit_kzalloc(test, sizeof(*dc), GFP_KERNEL);
2168 	KUNIT_ASSERT_NOT_ERR_OR_NULL(test, dc);
2169 
2170 	link_srv = kunit_kzalloc(test, sizeof(*link_srv), GFP_KERNEL);
2171 	KUNIT_ASSERT_NOT_ERR_OR_NULL(test, link_srv);
2172 	link_srv->detect_connection_type = dm_test_detect_connection_none;
2173 	dc->link_srv = link_srv;
2174 
2175 	link = kunit_kzalloc(test, sizeof(*link), GFP_KERNEL);
2176 	KUNIT_ASSERT_NOT_ERR_OR_NULL(test, link);
2177 	link->dc = dc;
2178 	aconn->dc_link = link;
2179 
2180 	offload_work = kzalloc_obj(*offload_work);
2181 	KUNIT_ASSERT_NOT_ERR_OR_NULL(test, offload_work);
2182 	offload_work->offload_wq = offload_wq;
2183 	offload_work->adev = adev;
2184 	INIT_WORK(&offload_work->work, dm_handle_hpd_rx_offload_work);
2185 
2186 	dm_handle_hpd_rx_offload_work(&offload_work->work);
2187 }
2188 
2189 /**
2190  * dm_test_hpd_rx_offload_work_automated_test - Test AUTOMATED_TEST branch
2191  * @test: The KUnit test context
2192  *
2193  * With a present connection and the AUTOMATED_TEST service-IRQ bit set, the
2194  * worker runs dc_link_dp_handle_automated_test() (stubbed via link_srv) and
2195  * writes the test response with core_link_write_dpcd(). timing_changed is left
2196  * false so force_connector_state() (which needs a registered DRM device) is
2197  * skipped, and aux_access_disabled makes the DPCD write a safe no-op.
2198  */
dm_test_hpd_rx_offload_work_automated_test(struct kunit * test)2199 static void dm_test_hpd_rx_offload_work_automated_test(struct kunit *test)
2200 {
2201 	struct hpd_rx_irq_offload_work_queue *offload_wq;
2202 	struct hpd_rx_irq_offload_work *offload_work;
2203 	struct amdgpu_dm_connector *aconn;
2204 	struct link_service *link_srv;
2205 	struct amdgpu_device *adev;
2206 	struct dc_context *ctx;
2207 	struct dc_link *link;
2208 	struct dc *dc;
2209 
2210 	dm_test_automated_test_count = 0;
2211 
2212 	adev = dm_kunit_alloc_adev(test);
2213 	mutex_init(&adev->dm.dc_lock);
2214 	adev->reset_domain = kunit_kzalloc(test, sizeof(*adev->reset_domain),
2215 					   GFP_KERNEL);
2216 	KUNIT_ASSERT_NOT_ERR_OR_NULL(test, adev->reset_domain);
2217 
2218 	offload_wq = kunit_kzalloc(test, sizeof(*offload_wq), GFP_KERNEL);
2219 	KUNIT_ASSERT_NOT_ERR_OR_NULL(test, offload_wq);
2220 	spin_lock_init(&offload_wq->offload_lock);
2221 
2222 	aconn = dm_kunit_alloc_connector(test, adev, NULL);
2223 	mutex_init(&aconn->hpd_lock);
2224 	aconn->timing_changed = false;
2225 	offload_wq->aconnector = aconn;
2226 
2227 	dc = kunit_kzalloc(test, sizeof(*dc), GFP_KERNEL);
2228 	KUNIT_ASSERT_NOT_ERR_OR_NULL(test, dc);
2229 	ctx = kunit_kzalloc(test, sizeof(*ctx), GFP_KERNEL);
2230 	KUNIT_ASSERT_NOT_ERR_OR_NULL(test, ctx);
2231 	link_srv = kunit_kzalloc(test, sizeof(*link_srv), GFP_KERNEL);
2232 	KUNIT_ASSERT_NOT_ERR_OR_NULL(test, link_srv);
2233 	link = kunit_kzalloc(test, sizeof(*link), GFP_KERNEL);
2234 	KUNIT_ASSERT_NOT_ERR_OR_NULL(test, link);
2235 
2236 	link_srv->detect_connection_type = dm_test_detect_connection_single;
2237 	link_srv->dp_handle_automated_test = dm_test_dp_handle_automated_test;
2238 	dc->link_srv = link_srv;
2239 	dc->ctx = ctx;
2240 	ctx->dc = dc;
2241 	link->dc = dc;
2242 	link->ctx = ctx;
2243 	link->aux_access_disabled = true;
2244 	link->connector_signal = SIGNAL_TYPE_DISPLAY_PORT;
2245 	aconn->dc_link = link;
2246 
2247 	offload_work = kzalloc_obj(*offload_work);
2248 	KUNIT_ASSERT_NOT_ERR_OR_NULL(test, offload_work);
2249 	offload_work->offload_wq = offload_wq;
2250 	offload_work->adev = adev;
2251 	offload_work->data.bytes.device_service_irq.bits.AUTOMATED_TEST = 1;
2252 	INIT_WORK(&offload_work->work, dm_handle_hpd_rx_offload_work);
2253 
2254 	dm_handle_hpd_rx_offload_work(&offload_work->work);
2255 
2256 	KUNIT_EXPECT_EQ(test, dm_test_automated_test_count, 1);
2257 }
2258 
2259 /**
2260  * dm_test_hpd_rx_offload_work_link_loss - Test link-loss branch
2261  * @test: The KUnit test context
2262  *
2263  * With a present non-eDP connection and no service-IRQ bits set, the worker
2264  * takes the else-if link-loss path: dc_link_check_link_loss_status() and
2265  * dc_link_dp_allow_hpd_rx_irq() gate entry, then dc_link_dp_read_hpd_rx_irq_data()
2266  * returns DC_OK and a second link-loss check triggers dc_link_dp_handle_link_loss().
2267  * All four are stubbed via link_srv.
2268  */
dm_test_hpd_rx_offload_work_link_loss(struct kunit * test)2269 static void dm_test_hpd_rx_offload_work_link_loss(struct kunit *test)
2270 {
2271 	struct hpd_rx_irq_offload_work_queue *offload_wq;
2272 	struct hpd_rx_irq_offload_work *offload_work;
2273 	struct amdgpu_dm_connector *aconn;
2274 	struct link_service *link_srv;
2275 	struct amdgpu_device *adev;
2276 	struct dc_context *ctx;
2277 	struct dc_link *link;
2278 	struct dc *dc;
2279 
2280 	dm_test_handle_link_loss_count = 0;
2281 
2282 	adev = dm_kunit_alloc_adev(test);
2283 	mutex_init(&adev->dm.dc_lock);
2284 	adev->reset_domain = kunit_kzalloc(test, sizeof(*adev->reset_domain),
2285 					   GFP_KERNEL);
2286 	KUNIT_ASSERT_NOT_ERR_OR_NULL(test, adev->reset_domain);
2287 
2288 	offload_wq = kunit_kzalloc(test, sizeof(*offload_wq), GFP_KERNEL);
2289 	KUNIT_ASSERT_NOT_ERR_OR_NULL(test, offload_wq);
2290 	spin_lock_init(&offload_wq->offload_lock);
2291 
2292 	aconn = dm_kunit_alloc_connector(test, adev, NULL);
2293 	mutex_init(&aconn->hpd_lock);
2294 	offload_wq->aconnector = aconn;
2295 
2296 	dc = kunit_kzalloc(test, sizeof(*dc), GFP_KERNEL);
2297 	KUNIT_ASSERT_NOT_ERR_OR_NULL(test, dc);
2298 	ctx = kunit_kzalloc(test, sizeof(*ctx), GFP_KERNEL);
2299 	KUNIT_ASSERT_NOT_ERR_OR_NULL(test, ctx);
2300 	link_srv = kunit_kzalloc(test, sizeof(*link_srv), GFP_KERNEL);
2301 	KUNIT_ASSERT_NOT_ERR_OR_NULL(test, link_srv);
2302 	link = kunit_kzalloc(test, sizeof(*link), GFP_KERNEL);
2303 	KUNIT_ASSERT_NOT_ERR_OR_NULL(test, link);
2304 
2305 	link_srv->detect_connection_type = dm_test_detect_connection_single;
2306 	link_srv->dp_parse_link_loss_status = dm_test_dp_parse_link_loss_true;
2307 	link_srv->dp_should_allow_hpd_rx_irq = dm_test_dp_should_allow_hpd_rx_irq_true;
2308 	link_srv->dp_read_hpd_rx_irq_data = dm_test_dp_read_hpd_rx_irq_data_ok;
2309 	link_srv->dp_handle_link_loss = dm_test_dp_handle_link_loss;
2310 	dc->link_srv = link_srv;
2311 	dc->ctx = ctx;
2312 	ctx->dc = dc;
2313 	link->dc = dc;
2314 	link->ctx = ctx;
2315 	link->connector_signal = SIGNAL_TYPE_DISPLAY_PORT;
2316 	aconn->dc_link = link;
2317 
2318 	offload_work = kzalloc_obj(*offload_work);
2319 	KUNIT_ASSERT_NOT_ERR_OR_NULL(test, offload_work);
2320 	offload_work->offload_wq = offload_wq;
2321 	offload_work->adev = adev;
2322 	INIT_WORK(&offload_work->work, dm_handle_hpd_rx_offload_work);
2323 
2324 	dm_handle_hpd_rx_offload_work(&offload_work->work);
2325 
2326 	KUNIT_EXPECT_EQ(test, dm_test_handle_link_loss_count, 1);
2327 }
2328 
2329 /* Tests for amdgpu_dm_hdmi_hpd_debounce_work() */
2330 
2331 /**
2332  * dm_test_hdmi_hpd_debounce_detect_false - Test debounce false detect path
2333  * @test: The KUnit test context
2334  */
dm_test_hdmi_hpd_debounce_detect_false(struct kunit * test)2335 static void dm_test_hdmi_hpd_debounce_detect_false(struct kunit *test)
2336 {
2337 	struct amdgpu_dm_connector *aconn;
2338 	struct link_service *link_srv;
2339 	struct amdgpu_device *adev;
2340 	struct dc_context *ctx;
2341 	struct dc_link *link;
2342 	struct dc *dc;
2343 
2344 	adev = dm_kunit_alloc_adev(test);
2345 	mutex_init(&adev->dm.dc_lock);
2346 
2347 	aconn = dm_kunit_alloc_connector(test, adev, NULL);
2348 	mutex_init(&aconn->hpd_lock);
2349 	INIT_DELAYED_WORK(&aconn->hdmi_hpd_debounce_work,
2350 			  amdgpu_dm_hdmi_hpd_debounce_work);
2351 
2352 	dc = kunit_kzalloc(test, sizeof(*dc), GFP_KERNEL);
2353 	KUNIT_ASSERT_NOT_ERR_OR_NULL(test, dc);
2354 	ctx = kunit_kzalloc(test, sizeof(*ctx), GFP_KERNEL);
2355 	KUNIT_ASSERT_NOT_ERR_OR_NULL(test, ctx);
2356 	link_srv = kunit_kzalloc(test, sizeof(*link_srv), GFP_KERNEL);
2357 	KUNIT_ASSERT_NOT_ERR_OR_NULL(test, link_srv);
2358 	link = kunit_kzalloc(test, sizeof(*link), GFP_KERNEL);
2359 	KUNIT_ASSERT_NOT_ERR_OR_NULL(test, link);
2360 
2361 	link_srv->detect_link = dm_test_detect_link_false;
2362 	dc->ctx = ctx;
2363 	dc->link_srv = link_srv;
2364 	ctx->dc = dc;
2365 	link->dc = dc;
2366 	link->ctx = ctx;
2367 	aconn->dc_link = link;
2368 
2369 	amdgpu_dm_hdmi_hpd_debounce_work(&aconn->hdmi_hpd_debounce_work.work);
2370 	KUNIT_EXPECT_NULL(test, aconn->hdmi_prev_sink);
2371 }
2372 
2373 /**
2374  * dm_test_hdmi_hpd_debounce_reallow_idle - Test debounce idle/sink-release tail
2375  * @test: The KUnit test context
2376  *
2377  * With detection stubbed to return false, the if (ret) block is skipped, but
2378  * the function tail is still exercised: IPS support plus an idle-allowed dmub
2379  * makes reallow_idle true so dc_allow_idle_optimizations() runs on both entry
2380  * and exit (disable_idle_power_optimizations keeps those safe early returns),
2381  * and a cached hdmi_prev_sink is released and cleared.
2382  */
dm_test_hdmi_hpd_debounce_reallow_idle(struct kunit * test)2383 static void dm_test_hdmi_hpd_debounce_reallow_idle(struct kunit *test)
2384 {
2385 	struct amdgpu_dm_connector *aconn;
2386 	struct link_service *link_srv;
2387 	struct dc_dmub_srv *dmub_srv;
2388 	struct amdgpu_device *adev;
2389 	struct dal_logger *logger;
2390 	struct dc_context *ctx;
2391 	struct dc_link *link;
2392 	struct dc *dc;
2393 
2394 	adev = dm_kunit_alloc_adev(test);
2395 	mutex_init(&adev->dm.dc_lock);
2396 
2397 	aconn = dm_kunit_alloc_connector(test, adev, NULL);
2398 	mutex_init(&aconn->hpd_lock);
2399 	INIT_DELAYED_WORK(&aconn->hdmi_hpd_debounce_work,
2400 			  amdgpu_dm_hdmi_hpd_debounce_work);
2401 
2402 	dc = kunit_kzalloc(test, sizeof(*dc), GFP_KERNEL);
2403 	KUNIT_ASSERT_NOT_ERR_OR_NULL(test, dc);
2404 	ctx = kunit_kzalloc(test, sizeof(*ctx), GFP_KERNEL);
2405 	KUNIT_ASSERT_NOT_ERR_OR_NULL(test, ctx);
2406 	link_srv = kunit_kzalloc(test, sizeof(*link_srv), GFP_KERNEL);
2407 	KUNIT_ASSERT_NOT_ERR_OR_NULL(test, link_srv);
2408 	link = kunit_kzalloc(test, sizeof(*link), GFP_KERNEL);
2409 	KUNIT_ASSERT_NOT_ERR_OR_NULL(test, link);
2410 	logger = kunit_kzalloc(test, sizeof(*logger), GFP_KERNEL);
2411 	KUNIT_ASSERT_NOT_ERR_OR_NULL(test, logger);
2412 	dmub_srv = kunit_kzalloc(test, sizeof(*dmub_srv), GFP_KERNEL);
2413 	KUNIT_ASSERT_NOT_ERR_OR_NULL(test, dmub_srv);
2414 
2415 	link_srv->detect_link = dm_test_detect_link_false;
2416 	dc->ctx = ctx;
2417 	dc->link_srv = link_srv;
2418 	ctx->dc = dc;
2419 	link->dc = dc;
2420 	link->ctx = ctx;
2421 	aconn->dc_link = link;
2422 
2423 	/* DC_LOG_* dereferences ctx->logger->dev, so wire a real drm device. */
2424 	logger->dev = &adev->ddev;
2425 	dc->ctx->logger = logger;
2426 
2427 	/* Make reallow_idle true and keep dc_allow_idle*() a safe early return. */
2428 	dmub_srv->idle_allowed = true;
2429 	dc->ctx->dmub_srv = dmub_srv;
2430 	dc->caps.ips_support = true;
2431 	dc->debug.disable_idle_power_optimizations = true;
2432 
2433 	/* A cached previous sink must be released and cleared. */
2434 	aconn->hdmi_prev_sink = dm_test_sink_create(link);
2435 	KUNIT_ASSERT_NOT_ERR_OR_NULL(test, aconn->hdmi_prev_sink);
2436 
2437 	amdgpu_dm_hdmi_hpd_debounce_work(&aconn->hdmi_hpd_debounce_work.work);
2438 	KUNIT_EXPECT_NULL(test, aconn->hdmi_prev_sink);
2439 }
2440 
2441 /* Tests for handle_hpd_irq()/handle_hpd_irq_helper() */
2442 
2443 /**
2444  * dm_test_handle_hpd_irq_disabled - Test HPD helper returns when disabled
2445  * @test: The KUnit test context
2446  */
dm_test_handle_hpd_irq_disabled(struct kunit * test)2447 static void dm_test_handle_hpd_irq_disabled(struct kunit *test)
2448 {
2449 	struct amdgpu_dm_connector *aconn;
2450 	struct dm_connector_state *state;
2451 	struct amdgpu_device *adev;
2452 	struct dc_context *ctx;
2453 	struct dc_link *link;
2454 	struct dc *dc;
2455 
2456 	adev = dm_kunit_alloc_adev(test);
2457 	adev->dm.disable_hpd_irq = true;
2458 
2459 	aconn = dm_kunit_alloc_connector(test, adev, NULL);
2460 	state = kunit_kzalloc(test, sizeof(*state), GFP_KERNEL);
2461 	KUNIT_ASSERT_NOT_ERR_OR_NULL(test, state);
2462 	aconn->base.state = &state->base;
2463 
2464 	dc = kunit_kzalloc(test, sizeof(*dc), GFP_KERNEL);
2465 	KUNIT_ASSERT_NOT_ERR_OR_NULL(test, dc);
2466 	ctx = kunit_kzalloc(test, sizeof(*ctx), GFP_KERNEL);
2467 	KUNIT_ASSERT_NOT_ERR_OR_NULL(test, ctx);
2468 	link = kunit_kzalloc(test, sizeof(*link), GFP_KERNEL);
2469 	KUNIT_ASSERT_NOT_ERR_OR_NULL(test, link);
2470 
2471 	dc->ctx = ctx;
2472 	ctx->dc = dc;
2473 	link->ctx = ctx;
2474 	aconn->dc_link = link;
2475 	aconn->fake_enable = true;
2476 
2477 	handle_hpd_irq_helper(aconn, DETECT_REASON_HPD);
2478 	KUNIT_EXPECT_TRUE(test, aconn->fake_enable);
2479 
2480 	handle_hpd_irq(aconn);
2481 	KUNIT_EXPECT_TRUE(test, aconn->fake_enable);
2482 }
2483 
2484 /**
2485  * dm_test_handle_hpd_irq_helper_debounce_schedule - Test HDMI debounce branch
2486  * @test: The KUnit test context
2487  *
2488  * An HDMI link reporting a disconnect (connection type none) with a non-zero
2489  * debounce delay and a cached local_sink must take the debounce branch: it
2490  * caches local_sink in hdmi_prev_sink and schedules the delayed debounce work
2491  * instead of detecting immediately.
2492  */
dm_test_handle_hpd_irq_helper_debounce_schedule(struct kunit * test)2493 static void dm_test_handle_hpd_irq_helper_debounce_schedule(struct kunit *test)
2494 {
2495 	struct amdgpu_dm_connector *aconn;
2496 	struct dm_connector_state *state;
2497 	struct link_service *link_srv;
2498 	struct amdgpu_device *adev;
2499 	struct dc_context *ctx;
2500 	struct dc_link *link;
2501 	struct dc *dc;
2502 
2503 	adev = dm_kunit_alloc_adev(test);
2504 
2505 	aconn = dm_kunit_alloc_connector(test, adev, NULL);
2506 	mutex_init(&aconn->hpd_lock);
2507 	INIT_DELAYED_WORK(&aconn->hdmi_hpd_debounce_work,
2508 			  amdgpu_dm_hdmi_hpd_debounce_work);
2509 
2510 	state = kunit_kzalloc(test, sizeof(*state), GFP_KERNEL);
2511 	KUNIT_ASSERT_NOT_ERR_OR_NULL(test, state);
2512 	aconn->base.state = &state->base;
2513 
2514 	dc = kunit_kzalloc(test, sizeof(*dc), GFP_KERNEL);
2515 	KUNIT_ASSERT_NOT_ERR_OR_NULL(test, dc);
2516 	ctx = kunit_kzalloc(test, sizeof(*ctx), GFP_KERNEL);
2517 	KUNIT_ASSERT_NOT_ERR_OR_NULL(test, ctx);
2518 	link_srv = kunit_kzalloc(test, sizeof(*link_srv), GFP_KERNEL);
2519 	KUNIT_ASSERT_NOT_ERR_OR_NULL(test, link_srv);
2520 	link = kunit_kzalloc(test, sizeof(*link), GFP_KERNEL);
2521 	KUNIT_ASSERT_NOT_ERR_OR_NULL(test, link);
2522 
2523 	link_srv->detect_connection_type = dm_test_detect_connection_none;
2524 	dc->ctx = ctx;
2525 	dc->link_srv = link_srv;
2526 	ctx->dc = dc;
2527 	link->dc = dc;
2528 	link->ctx = ctx;
2529 	aconn->dc_link = link;
2530 
2531 	/* HDMI signal + debounce delay + cached sink -> debounce branch. */
2532 	aconn->hdmi_hpd_debounce_delay_ms = 100;
2533 	link->connector_signal = SIGNAL_TYPE_HDMI_TYPE_A;
2534 	link->local_sink = dm_test_sink_create(link);
2535 	KUNIT_ASSERT_NOT_ERR_OR_NULL(test, link->local_sink);
2536 
2537 	handle_hpd_irq_helper(aconn, DETECT_REASON_HPD);
2538 
2539 	/* local_sink is cached for later comparison by the debounce work. */
2540 	KUNIT_EXPECT_PTR_EQ(test, aconn->hdmi_prev_sink, link->local_sink);
2541 
2542 	cancel_delayed_work_sync(&aconn->hdmi_hpd_debounce_work);
2543 	dm_test_sink_release(aconn->hdmi_prev_sink);
2544 	dm_test_sink_release(link->local_sink);
2545 }
2546 
2547 /**
2548  * dm_test_handle_hpd_irq_helper_debounce_release_prev - Test stale prev_sink
2549  * @test: The KUnit test context
2550  *
2551  * When the debounce branch is taken and a stale hdmi_prev_sink is already
2552  * cached from a previous HPD, it must be released before caching the current
2553  * local_sink. This exercises the dc_sink_release() of the previous sink.
2554  */
dm_test_handle_hpd_irq_helper_debounce_release_prev(struct kunit * test)2555 static void dm_test_handle_hpd_irq_helper_debounce_release_prev(struct kunit *test)
2556 {
2557 	struct amdgpu_dm_connector *aconn;
2558 	struct dm_connector_state *state;
2559 	struct link_service *link_srv;
2560 	struct amdgpu_device *adev;
2561 	struct dc_context *ctx;
2562 	struct dc_link *link;
2563 	struct dc *dc;
2564 
2565 	adev = dm_kunit_alloc_adev(test);
2566 
2567 	aconn = dm_kunit_alloc_connector(test, adev, NULL);
2568 	mutex_init(&aconn->hpd_lock);
2569 	INIT_DELAYED_WORK(&aconn->hdmi_hpd_debounce_work,
2570 			  amdgpu_dm_hdmi_hpd_debounce_work);
2571 
2572 	state = kunit_kzalloc(test, sizeof(*state), GFP_KERNEL);
2573 	KUNIT_ASSERT_NOT_ERR_OR_NULL(test, state);
2574 	aconn->base.state = &state->base;
2575 
2576 	dc = kunit_kzalloc(test, sizeof(*dc), GFP_KERNEL);
2577 	KUNIT_ASSERT_NOT_ERR_OR_NULL(test, dc);
2578 	ctx = kunit_kzalloc(test, sizeof(*ctx), GFP_KERNEL);
2579 	KUNIT_ASSERT_NOT_ERR_OR_NULL(test, ctx);
2580 	link_srv = kunit_kzalloc(test, sizeof(*link_srv), GFP_KERNEL);
2581 	KUNIT_ASSERT_NOT_ERR_OR_NULL(test, link_srv);
2582 	link = kunit_kzalloc(test, sizeof(*link), GFP_KERNEL);
2583 	KUNIT_ASSERT_NOT_ERR_OR_NULL(test, link);
2584 
2585 	link_srv->detect_connection_type = dm_test_detect_connection_none;
2586 	dc->ctx = ctx;
2587 	dc->link_srv = link_srv;
2588 	ctx->dc = dc;
2589 	link->dc = dc;
2590 	link->ctx = ctx;
2591 	aconn->dc_link = link;
2592 
2593 	/* HDMI signal + debounce delay + cached sink -> debounce branch. */
2594 	aconn->hdmi_hpd_debounce_delay_ms = 100;
2595 	link->connector_signal = SIGNAL_TYPE_HDMI_TYPE_A;
2596 	link->local_sink = dm_test_sink_create(link);
2597 	KUNIT_ASSERT_NOT_ERR_OR_NULL(test, link->local_sink);
2598 
2599 	/* Stale sink from a previous HPD must be released by the helper. */
2600 	aconn->hdmi_prev_sink = dm_test_sink_create(link);
2601 	KUNIT_ASSERT_NOT_ERR_OR_NULL(test, aconn->hdmi_prev_sink);
2602 	KUNIT_ASSERT_PTR_NE(test, aconn->hdmi_prev_sink, link->local_sink);
2603 
2604 	handle_hpd_irq_helper(aconn, DETECT_REASON_HPD);
2605 
2606 	/* Stale sink replaced by the current local_sink. */
2607 	KUNIT_EXPECT_PTR_EQ(test, aconn->hdmi_prev_sink, link->local_sink);
2608 
2609 	cancel_delayed_work_sync(&aconn->hdmi_hpd_debounce_work);
2610 	dm_test_sink_release(aconn->hdmi_prev_sink);
2611 	dm_test_sink_release(link->local_sink);
2612 }
2613 
2614 /**
2615  * dm_test_handle_hpd_irq_helper_detect_false - Test immediate detect branch
2616  * @test: The KUnit test context
2617  *
2618  * With no force, no debounce, and detection stubbed to report no connection,
2619  * the helper takes the else branch: dc_exit_ips_for_hw_access() is a safe
2620  * no-op (no IPS support) and dc_link_detect() returns false, so the connected
2621  * if (ret) block is skipped. fake_enable must still be cleared.
2622  */
dm_test_handle_hpd_irq_helper_detect_false(struct kunit * test)2623 static void dm_test_handle_hpd_irq_helper_detect_false(struct kunit *test)
2624 {
2625 	struct amdgpu_dm_connector *aconn;
2626 	struct dm_connector_state *state;
2627 	struct link_service *link_srv;
2628 	struct amdgpu_device *adev;
2629 	struct dc_context *ctx;
2630 	struct dc_link *link;
2631 	struct dc *dc;
2632 
2633 	adev = dm_kunit_alloc_adev(test);
2634 	mutex_init(&adev->dm.dc_lock);
2635 
2636 	aconn = dm_kunit_alloc_connector(test, adev, NULL);
2637 	mutex_init(&aconn->hpd_lock);
2638 	INIT_DELAYED_WORK(&aconn->hdmi_hpd_debounce_work,
2639 			  amdgpu_dm_hdmi_hpd_debounce_work);
2640 
2641 	state = kunit_kzalloc(test, sizeof(*state), GFP_KERNEL);
2642 	KUNIT_ASSERT_NOT_ERR_OR_NULL(test, state);
2643 	aconn->base.state = &state->base;
2644 
2645 	dc = kunit_kzalloc(test, sizeof(*dc), GFP_KERNEL);
2646 	KUNIT_ASSERT_NOT_ERR_OR_NULL(test, dc);
2647 	ctx = kunit_kzalloc(test, sizeof(*ctx), GFP_KERNEL);
2648 	KUNIT_ASSERT_NOT_ERR_OR_NULL(test, ctx);
2649 	link_srv = kunit_kzalloc(test, sizeof(*link_srv), GFP_KERNEL);
2650 	KUNIT_ASSERT_NOT_ERR_OR_NULL(test, link_srv);
2651 	link = kunit_kzalloc(test, sizeof(*link), GFP_KERNEL);
2652 	KUNIT_ASSERT_NOT_ERR_OR_NULL(test, link);
2653 
2654 	link_srv->detect_connection_type = dm_test_detect_connection_none;
2655 	link_srv->detect_link = dm_test_detect_link_false;
2656 	dc->ctx = ctx;
2657 	dc->link_srv = link_srv;
2658 	ctx->dc = dc;
2659 	link->dc = dc;
2660 	link->ctx = ctx;
2661 	aconn->dc_link = link;
2662 	aconn->fake_enable = true;
2663 
2664 	/* No debounce delay and no force -> immediate-detect else branch. */
2665 	handle_hpd_irq_helper(aconn, DETECT_REASON_HPD);
2666 
2667 	KUNIT_EXPECT_FALSE(test, aconn->fake_enable);
2668 }
2669 
2670 /* Tests for handle_hpd_rx_irq()/schedule_hpd_rx_offload_work() */
2671 
2672 /**
2673  * dm_test_handle_hpd_rx_irq_disabled - Test HPDRX handler returns when disabled
2674  * @test: The KUnit test context
2675  */
dm_test_handle_hpd_rx_irq_disabled(struct kunit * test)2676 static void dm_test_handle_hpd_rx_irq_disabled(struct kunit *test)
2677 {
2678 	struct hpd_rx_irq_offload_work_queue *offload_wq;
2679 	struct amdgpu_dm_connector *aconn;
2680 	struct link_service *link_srv;
2681 	struct amdgpu_device *adev;
2682 	struct dc_context *ctx;
2683 	struct dc_link *link;
2684 	struct dc *dc;
2685 
2686 	adev = dm_kunit_alloc_adev(test);
2687 	adev->dm.disable_hpd_irq = true;
2688 
2689 	offload_wq = kunit_kzalloc(test, sizeof(*offload_wq), GFP_KERNEL);
2690 	KUNIT_ASSERT_NOT_ERR_OR_NULL(test, offload_wq);
2691 	adev->dm.hpd_rx_offload_wq = offload_wq;
2692 
2693 	aconn = dm_kunit_alloc_connector(test, adev, NULL);
2694 
2695 	dc = kunit_kzalloc(test, sizeof(*dc), GFP_KERNEL);
2696 	KUNIT_ASSERT_NOT_ERR_OR_NULL(test, dc);
2697 	ctx = kunit_kzalloc(test, sizeof(*ctx), GFP_KERNEL);
2698 	KUNIT_ASSERT_NOT_ERR_OR_NULL(test, ctx);
2699 	link_srv = kunit_kzalloc(test, sizeof(*link_srv), GFP_KERNEL);
2700 	KUNIT_ASSERT_NOT_ERR_OR_NULL(test, link_srv);
2701 	link = kunit_kzalloc(test, sizeof(*link), GFP_KERNEL);
2702 	KUNIT_ASSERT_NOT_ERR_OR_NULL(test, link);
2703 
2704 	link_srv->dp_handle_hpd_rx_irq = dm_test_handle_hpd_rx_no_work;
2705 	dc->ctx = ctx;
2706 	dc->link_srv = link_srv;
2707 	ctx->dc = dc;
2708 	link->dc = dc;
2709 	link->ctx = ctx;
2710 	link->link_index = 0;
2711 	aconn->dc_link = link;
2712 
2713 	handle_hpd_rx_irq(aconn);
2714 }
2715 
2716 /**
2717  * dm_test_schedule_hpd_rx_offload_work - Test offload work is queued
2718  * @test: The KUnit test context
2719  */
dm_test_schedule_hpd_rx_offload_work(struct kunit * test)2720 static void dm_test_schedule_hpd_rx_offload_work(struct kunit *test)
2721 {
2722 	struct hpd_rx_irq_offload_work_queue *offload_wq;
2723 	struct amdgpu_device *adev;
2724 	union hpd_irq_data data = { 0 };
2725 
2726 	adev = dm_kunit_alloc_adev(test);
2727 
2728 	offload_wq = kunit_kzalloc(test, sizeof(*offload_wq), GFP_KERNEL);
2729 	KUNIT_ASSERT_NOT_ERR_OR_NULL(test, offload_wq);
2730 	offload_wq->wq = create_singlethread_workqueue("dm_irq_test_hpd_rx");
2731 	KUNIT_ASSERT_NOT_NULL(test, offload_wq->wq);
2732 
2733 	schedule_hpd_rx_offload_work(adev, offload_wq, data);
2734 	flush_workqueue(offload_wq->wq);
2735 	destroy_workqueue(offload_wq->wq);
2736 }
2737 
dm_test_destroy_offload_wq(void * data)2738 static void dm_test_destroy_offload_wq(void *data)
2739 {
2740 	struct workqueue_struct *wq = data;
2741 
2742 	flush_workqueue(wq);
2743 	destroy_workqueue(wq);
2744 }
2745 
2746 /*
2747  * Build an aconnector wired for handle_hpd_rx_irq(): HPD enabled, an MST-root
2748  * connector on an MST-branch link so the post-detect block and drm_dp_cec_irq
2749  * are skipped, and a flushed offload work queue. Caller sets the link_srv
2750  * stubs (dp_handle_hpd_rx_irq and, if needed, dp_should_allow_hpd_rx_irq).
2751  */
dm_test_setup_hpd_rx_irq(struct kunit * test,struct link_service ** link_srv_out)2752 static struct amdgpu_dm_connector *dm_test_setup_hpd_rx_irq(struct kunit *test,
2753 							    struct link_service **link_srv_out)
2754 {
2755 	struct hpd_rx_irq_offload_work_queue *offload_wq;
2756 	struct amdgpu_dm_connector *aconn;
2757 	struct link_service *link_srv;
2758 	struct amdgpu_device *adev;
2759 	struct dc_context *ctx;
2760 	struct dc_link *link;
2761 	struct dc *dc;
2762 
2763 	adev = dm_kunit_alloc_adev(test);
2764 	mutex_init(&adev->dm.dc_lock);
2765 
2766 	offload_wq = kunit_kzalloc(test, sizeof(*offload_wq), GFP_KERNEL);
2767 	KUNIT_ASSERT_NOT_ERR_OR_NULL(test, offload_wq);
2768 	spin_lock_init(&offload_wq->offload_lock);
2769 	offload_wq->wq = create_singlethread_workqueue("dm_irq_test_hpd_rx");
2770 	KUNIT_ASSERT_NOT_NULL(test, offload_wq->wq);
2771 	KUNIT_ASSERT_EQ(test, kunit_add_action_or_reset(test, dm_test_destroy_offload_wq,
2772 							offload_wq->wq), 0);
2773 	adev->dm.hpd_rx_offload_wq = offload_wq;
2774 
2775 	aconn = dm_kunit_alloc_connector(test, adev, NULL);
2776 	mutex_init(&aconn->hpd_lock);
2777 	aconn->mst_mgr.mst_state = true;
2778 
2779 	dc = kunit_kzalloc(test, sizeof(*dc), GFP_KERNEL);
2780 	KUNIT_ASSERT_NOT_ERR_OR_NULL(test, dc);
2781 	ctx = kunit_kzalloc(test, sizeof(*ctx), GFP_KERNEL);
2782 	KUNIT_ASSERT_NOT_ERR_OR_NULL(test, ctx);
2783 	link_srv = kunit_kzalloc(test, sizeof(*link_srv), GFP_KERNEL);
2784 	KUNIT_ASSERT_NOT_ERR_OR_NULL(test, link_srv);
2785 	link = kunit_kzalloc(test, sizeof(*link), GFP_KERNEL);
2786 	KUNIT_ASSERT_NOT_ERR_OR_NULL(test, link);
2787 
2788 	dc->ctx = ctx;
2789 	dc->link_srv = link_srv;
2790 	ctx->dc = dc;
2791 	link->dc = dc;
2792 	link->ctx = ctx;
2793 	link->link_index = 0;
2794 	link->type = dc_connection_mst_branch;
2795 	aconn->dc_link = link;
2796 
2797 	*link_srv_out = link_srv;
2798 
2799 	return aconn;
2800 }
2801 
2802 /**
2803  * dm_test_handle_hpd_rx_irq_no_left_work - Test HPDRX early out (no left work)
2804  * @test: The KUnit test context
2805  *
2806  * When dc_link_handle_hpd_rx_irq() reports no left-over work, the handler
2807  * jumps to out and returns without scheduling any offload work.
2808  */
dm_test_handle_hpd_rx_irq_no_left_work(struct kunit * test)2809 static void dm_test_handle_hpd_rx_irq_no_left_work(struct kunit *test)
2810 {
2811 	struct amdgpu_dm_connector *aconn;
2812 	struct link_service *link_srv;
2813 
2814 	aconn = dm_test_setup_hpd_rx_irq(test, &link_srv);
2815 	link_srv->dp_handle_hpd_rx_irq = dm_test_handle_hpd_rx_no_work;
2816 
2817 	handle_hpd_rx_irq(aconn);
2818 }
2819 
2820 /**
2821  * dm_test_handle_hpd_rx_irq_automated_test - Test HPDRX automated-test path
2822  * @test: The KUnit test context
2823  *
2824  * The AUTOMATED_TEST device-service bit must schedule offload work and jump to
2825  * out before the allow-hpd-rx-irq checks.
2826  */
dm_test_handle_hpd_rx_irq_automated_test(struct kunit * test)2827 static void dm_test_handle_hpd_rx_irq_automated_test(struct kunit *test)
2828 {
2829 	struct amdgpu_dm_connector *aconn;
2830 	struct link_service *link_srv;
2831 
2832 	aconn = dm_test_setup_hpd_rx_irq(test, &link_srv);
2833 	link_srv->dp_handle_hpd_rx_irq = dm_test_handle_hpd_rx_automated;
2834 
2835 	handle_hpd_rx_irq(aconn);
2836 }
2837 
2838 /**
2839  * dm_test_handle_hpd_rx_irq_msg_rdy - Test HPDRX MST message-ready path
2840  * @test: The KUnit test context
2841  *
2842  * With HPD RX IRQs allowed and an UP_REQ_MSG_RDY bit set, the handler must take
2843  * the MST message-ready branch, mark is_handling_mst_msg_rdy_event and schedule
2844  * offload work.
2845  */
dm_test_handle_hpd_rx_irq_msg_rdy(struct kunit * test)2846 static void dm_test_handle_hpd_rx_irq_msg_rdy(struct kunit *test)
2847 {
2848 	struct amdgpu_dm_connector *aconn;
2849 	struct link_service *link_srv;
2850 
2851 	aconn = dm_test_setup_hpd_rx_irq(test, &link_srv);
2852 	link_srv->dp_handle_hpd_rx_irq = dm_test_handle_hpd_rx_msg_rdy;
2853 	link_srv->dp_should_allow_hpd_rx_irq = dm_test_allow_hpd_rx_irq_true;
2854 
2855 	handle_hpd_rx_irq(aconn);
2856 
2857 	KUNIT_EXPECT_TRUE(test, drm_to_adev(aconn->base.dev)
2858 				->dm.hpd_rx_offload_wq->is_handling_mst_msg_rdy_event);
2859 }
2860 
2861 /**
2862  * dm_test_handle_hpd_rx_irq_link_loss - Test HPDRX link-loss path
2863  * @test: The KUnit test context
2864  *
2865  * With HPD RX IRQs allowed and a reported link loss (no message-ready bits),
2866  * the handler must take the link-loss branch, mark is_handling_link_loss and
2867  * schedule offload work.
2868  */
dm_test_handle_hpd_rx_irq_link_loss(struct kunit * test)2869 static void dm_test_handle_hpd_rx_irq_link_loss(struct kunit *test)
2870 {
2871 	struct amdgpu_dm_connector *aconn;
2872 	struct link_service *link_srv;
2873 
2874 	aconn = dm_test_setup_hpd_rx_irq(test, &link_srv);
2875 	link_srv->dp_handle_hpd_rx_irq = dm_test_handle_hpd_rx_link_loss;
2876 	link_srv->dp_should_allow_hpd_rx_irq = dm_test_allow_hpd_rx_irq_true;
2877 
2878 	handle_hpd_rx_irq(aconn);
2879 
2880 	KUNIT_EXPECT_TRUE(test, drm_to_adev(aconn->base.dev)
2881 				->dm.hpd_rx_offload_wq->is_handling_link_loss);
2882 }
2883 
2884 /* Tests for dmub_hpd_callback()/dmub_hpd_sense_callback() */
2885 
2886 /**
2887  * dm_test_dmub_hpd_callback_null_inputs - Test DMUB callback null inputs
2888  * @test: The KUnit test context
2889  */
dm_test_dmub_hpd_callback_null_inputs(struct kunit * test)2890 static void dm_test_dmub_hpd_callback_null_inputs(struct kunit *test)
2891 {
2892 	struct amdgpu_device *adev;
2893 
2894 	adev = dm_kunit_alloc_adev(test);
2895 
2896 	dmub_hpd_callback(NULL, NULL);
2897 	dmub_hpd_callback(adev, NULL);
2898 }
2899 
2900 /**
2901  * dm_test_dmub_hpd_callback_invalid_index - Test DMUB callback index check
2902  * @test: The KUnit test context
2903  */
dm_test_dmub_hpd_callback_invalid_index(struct kunit * test)2904 static void dm_test_dmub_hpd_callback_invalid_index(struct kunit *test)
2905 {
2906 	struct dmub_notification notify = { 0 };
2907 	struct amdgpu_device *adev;
2908 	struct dc *dc;
2909 
2910 	adev = dm_kunit_alloc_adev(test);
2911 	dc = kunit_kzalloc(test, sizeof(*dc), GFP_KERNEL);
2912 	KUNIT_ASSERT_NOT_ERR_OR_NULL(test, dc);
2913 	adev->dm.dc = dc;
2914 	notify.link_index = 1;
2915 
2916 	dmub_hpd_callback(adev, &notify);
2917 }
2918 
2919 /**
2920  * dm_test_dmub_hpd_callback_empty_connectors - Test DMUB callback without match
2921  * @test: The KUnit test context
2922  */
dm_test_dmub_hpd_callback_empty_connectors(struct kunit * test)2923 static void dm_test_dmub_hpd_callback_empty_connectors(struct kunit *test)
2924 {
2925 	struct dmub_notification notify = { 0 };
2926 	struct amdgpu_device *adev;
2927 	struct dc *dc;
2928 
2929 	adev = dm_kunit_alloc_adev(test);
2930 	dc = kunit_kzalloc(test, sizeof(*dc), GFP_KERNEL);
2931 	KUNIT_ASSERT_NOT_ERR_OR_NULL(test, dc);
2932 	adev->dm.dc = dc;
2933 	adev->dm.ddev = &adev->ddev;
2934 	dc->link_count = 1;
2935 	notify.type = DMUB_NOTIFICATION_HPD_SENSE_NOTIFY;
2936 
2937 	dmub_hpd_callback(adev, &notify);
2938 	dmub_hpd_sense_callback(adev, &notify);
2939 }
2940 
2941 /**
2942  * dm_test_dmub_hpd_callback_unknown_type_match - Test DMUB callback matched
2943  *						   connector, unknown type
2944  * @test: The KUnit test context
2945  *
2946  * A writeback connector must be skipped (continue) and a non-writeback
2947  * connector whose dc_link matches the notification link must be selected.
2948  * An unrecognized notification type takes the "unknown" warn branch, and the
2949  * post-loop dispatch is a no-op (neither HPD nor HPD_IRQ), so no real DC/MST
2950  * handler runs.
2951  */
dm_test_dmub_hpd_callback_unknown_type_match(struct kunit * test)2952 static void dm_test_dmub_hpd_callback_unknown_type_match(struct kunit *test)
2953 {
2954 	struct dmub_notification notify = { 0 };
2955 	struct amdgpu_dm_connector *aconn;
2956 	struct drm_connector *wbconn;
2957 	struct amdgpu_device *adev;
2958 	struct dc_link *link;
2959 	struct dc *dc;
2960 
2961 	adev = dm_kunit_alloc_adev(test);
2962 	dc = kunit_kzalloc(test, sizeof(*dc), GFP_KERNEL);
2963 	KUNIT_ASSERT_NOT_ERR_OR_NULL(test, dc);
2964 	adev->dm.dc = dc;
2965 	adev->dm.ddev = &adev->ddev;
2966 	dc->link_count = 1;
2967 
2968 	link = kunit_kzalloc(test, sizeof(*link), GFP_KERNEL);
2969 	KUNIT_ASSERT_NOT_ERR_OR_NULL(test, link);
2970 	dc->links[0] = link;
2971 
2972 	/* A writeback connector must be skipped by the loop. */
2973 	wbconn = kunit_kzalloc(test, sizeof(*wbconn), GFP_KERNEL);
2974 	KUNIT_ASSERT_NOT_ERR_OR_NULL(test, wbconn);
2975 	KUNIT_ASSERT_EQ(test, drm_connector_init(&adev->ddev, wbconn, &dm_test_connector_funcs,
2976 						 DRM_MODE_CONNECTOR_WRITEBACK), 0);
2977 	KUNIT_ASSERT_EQ(test, kunit_add_action_or_reset(test, dm_test_connector_cleanup, wbconn), 0);
2978 
2979 	/* A DisplayPort connector whose dc_link matches drives the match branch. */
2980 	aconn = kunit_kzalloc(test, sizeof(*aconn), GFP_KERNEL);
2981 	KUNIT_ASSERT_NOT_ERR_OR_NULL(test, aconn);
2982 	KUNIT_ASSERT_EQ(test, drm_connector_init(&adev->ddev, &aconn->base,
2983 						 &dm_test_connector_funcs,
2984 						 DRM_MODE_CONNECTOR_DisplayPort), 0);
2985 	KUNIT_ASSERT_EQ(test,
2986 			kunit_add_action_or_reset(test, dm_test_connector_cleanup, &aconn->base), 0);
2987 	aconn->dc_link = link;
2988 
2989 	notify.link_index = 0;
2990 	notify.type = DMUB_NOTIFICATION_HPD_SENSE_NOTIFY;
2991 
2992 	dmub_hpd_callback(adev, &notify);
2993 }
2994 
2995 /**
2996  * dm_test_dmub_hpd_callback_hpd_type - Test DMUB callback HPD type dispatch
2997  * @test: The KUnit test context
2998  *
2999  * A matched connector with notification type DMUB_NOTIFICATION_HPD logs the
3000  * HPD callback and dispatches to handle_hpd_irq_helper(). Detection is stubbed
3001  * to report no connection and link detect to fail, so the connected branches
3002  * are skipped and no real DC/DRM hotplug path runs.
3003  */
dm_test_dmub_hpd_callback_hpd_type(struct kunit * test)3004 static void dm_test_dmub_hpd_callback_hpd_type(struct kunit *test)
3005 {
3006 	struct dmub_notification notify = { 0 };
3007 	struct amdgpu_dm_connector *aconn;
3008 	struct link_service *link_srv;
3009 	struct amdgpu_device *adev;
3010 	struct dc_context *ctx;
3011 	struct dc_link *link;
3012 	struct dc *dc;
3013 
3014 	adev = dm_kunit_alloc_adev(test);
3015 	mutex_init(&adev->dm.dc_lock);
3016 
3017 	dc = kunit_kzalloc(test, sizeof(*dc), GFP_KERNEL);
3018 	KUNIT_ASSERT_NOT_ERR_OR_NULL(test, dc);
3019 	ctx = kunit_kzalloc(test, sizeof(*ctx), GFP_KERNEL);
3020 	KUNIT_ASSERT_NOT_ERR_OR_NULL(test, ctx);
3021 	link_srv = kunit_kzalloc(test, sizeof(*link_srv), GFP_KERNEL);
3022 	KUNIT_ASSERT_NOT_ERR_OR_NULL(test, link_srv);
3023 	link = kunit_kzalloc(test, sizeof(*link), GFP_KERNEL);
3024 	KUNIT_ASSERT_NOT_ERR_OR_NULL(test, link);
3025 
3026 	link_srv->detect_connection_type = dm_test_detect_connection_none;
3027 	link_srv->detect_link = dm_test_detect_link_false;
3028 	dc->ctx = ctx;
3029 	dc->link_srv = link_srv;
3030 	ctx->dc = dc;
3031 	link->dc = dc;
3032 	link->ctx = ctx;
3033 
3034 	adev->dm.dc = dc;
3035 	adev->dm.ddev = &adev->ddev;
3036 	dc->link_count = 1;
3037 	dc->links[0] = link;
3038 
3039 	aconn = kunit_kzalloc(test, sizeof(*aconn), GFP_KERNEL);
3040 	KUNIT_ASSERT_NOT_ERR_OR_NULL(test, aconn);
3041 	KUNIT_ASSERT_EQ(test, drm_connector_init(&adev->ddev, &aconn->base,
3042 						 &dm_test_connector_funcs,
3043 						 DRM_MODE_CONNECTOR_DisplayPort), 0);
3044 	KUNIT_ASSERT_EQ(test,
3045 			kunit_add_action_or_reset(test, dm_test_connector_cleanup, &aconn->base), 0);
3046 	mutex_init(&aconn->hpd_lock);
3047 	INIT_DELAYED_WORK(&aconn->hdmi_hpd_debounce_work,
3048 			  amdgpu_dm_hdmi_hpd_debounce_work);
3049 	aconn->dc_link = link;
3050 
3051 	notify.link_index = 0;
3052 	notify.type = DMUB_NOTIFICATION_HPD;
3053 
3054 	dmub_hpd_callback(adev, &notify);
3055 }
3056 
3057 /**
3058  * dm_test_dmub_hpd_callback_hpd_irq_type - Test DMUB callback HPD_IRQ dispatch
3059  * @test: The KUnit test context
3060  *
3061  * A matched connector with notification type DMUB_NOTIFICATION_HPD_IRQ logs
3062  * the HPD RX callback and dispatches to handle_hpd_rx_irq(). The HPD RX handler
3063  * stub reports no left work, so the function returns through the early goto
3064  * without scheduling offload work; an MST-branch link skips the trailing
3065  * drm_dp_cec_irq().
3066  */
dm_test_dmub_hpd_callback_hpd_irq_type(struct kunit * test)3067 static void dm_test_dmub_hpd_callback_hpd_irq_type(struct kunit *test)
3068 {
3069 	struct hpd_rx_irq_offload_work_queue *offload_wq;
3070 	struct dmub_notification notify = { 0 };
3071 	struct amdgpu_dm_connector *aconn;
3072 	struct link_service *link_srv;
3073 	struct amdgpu_device *adev;
3074 	struct dc_context *ctx;
3075 	struct dc_link *link;
3076 	struct dc *dc;
3077 
3078 	adev = dm_kunit_alloc_adev(test);
3079 	mutex_init(&adev->dm.dc_lock);
3080 
3081 	offload_wq = kunit_kzalloc(test, sizeof(*offload_wq), GFP_KERNEL);
3082 	KUNIT_ASSERT_NOT_ERR_OR_NULL(test, offload_wq);
3083 	spin_lock_init(&offload_wq->offload_lock);
3084 	adev->dm.hpd_rx_offload_wq = offload_wq;
3085 
3086 	dc = kunit_kzalloc(test, sizeof(*dc), GFP_KERNEL);
3087 	KUNIT_ASSERT_NOT_ERR_OR_NULL(test, dc);
3088 	ctx = kunit_kzalloc(test, sizeof(*ctx), GFP_KERNEL);
3089 	KUNIT_ASSERT_NOT_ERR_OR_NULL(test, ctx);
3090 	link_srv = kunit_kzalloc(test, sizeof(*link_srv), GFP_KERNEL);
3091 	KUNIT_ASSERT_NOT_ERR_OR_NULL(test, link_srv);
3092 	link = kunit_kzalloc(test, sizeof(*link), GFP_KERNEL);
3093 	KUNIT_ASSERT_NOT_ERR_OR_NULL(test, link);
3094 
3095 	link_srv->dp_handle_hpd_rx_irq = dm_test_handle_hpd_rx_no_work;
3096 	dc->ctx = ctx;
3097 	dc->link_srv = link_srv;
3098 	ctx->dc = dc;
3099 	link->dc = dc;
3100 	link->ctx = ctx;
3101 	link->link_index = 0;
3102 	link->type = dc_connection_mst_branch;
3103 
3104 	adev->dm.dc = dc;
3105 	adev->dm.ddev = &adev->ddev;
3106 	dc->link_count = 1;
3107 	dc->links[0] = link;
3108 
3109 	aconn = kunit_kzalloc(test, sizeof(*aconn), GFP_KERNEL);
3110 	KUNIT_ASSERT_NOT_ERR_OR_NULL(test, aconn);
3111 	KUNIT_ASSERT_EQ(test, drm_connector_init(&adev->ddev, &aconn->base,
3112 						 &dm_test_connector_funcs,
3113 						 DRM_MODE_CONNECTOR_DisplayPort), 0);
3114 	KUNIT_ASSERT_EQ(test,
3115 			kunit_add_action_or_reset(test, dm_test_connector_cleanup, &aconn->base), 0);
3116 	mutex_init(&aconn->hpd_lock);
3117 	aconn->mst_mgr.mst_state = true;
3118 	aconn->dc_link = link;
3119 
3120 	notify.link_index = 0;
3121 	notify.type = DMUB_NOTIFICATION_HPD_IRQ;
3122 
3123 	dmub_hpd_callback(adev, &notify);
3124 }
3125 
3126 /* Tests for amdgpu_dm_register_hpd_handlers() */
3127 
3128 /**
3129  * dm_test_register_hpd_handlers_empty - Test HPD registration with no connectors
3130  * @test: The KUnit test context
3131  */
dm_test_register_hpd_handlers_empty(struct kunit * test)3132 static void dm_test_register_hpd_handlers_empty(struct kunit *test)
3133 {
3134 	struct amdgpu_device *adev;
3135 	struct dc *dc;
3136 
3137 	adev = dm_kunit_alloc_adev(test);
3138 	dc = kunit_kzalloc(test, sizeof(*dc), GFP_KERNEL);
3139 	KUNIT_ASSERT_NOT_ERR_OR_NULL(test, dc);
3140 	adev->dm.dc = dc;
3141 
3142 	KUNIT_EXPECT_EQ(test, amdgpu_dm_register_hpd_handlers(adev), 0);
3143 }
3144 
3145 /**
3146  * dm_test_register_hpd_handlers_valid - Test HPD/HPDRX registration succeeds
3147  * @test: The KUnit test context
3148  */
dm_test_register_hpd_handlers_valid(struct kunit * test)3149 static void dm_test_register_hpd_handlers_valid(struct kunit *test)
3150 {
3151 	struct amdgpu_dm_connector *aconn;
3152 	struct amdgpu_device *adev;
3153 	struct dc_link *link;
3154 	struct dc *dc;
3155 
3156 	adev = dm_kunit_alloc_adev(test);
3157 	KUNIT_ASSERT_EQ(test, amdgpu_dm_irq_init(adev), 0);
3158 	dc = kunit_kzalloc(test, sizeof(*dc), GFP_KERNEL);
3159 	KUNIT_ASSERT_NOT_ERR_OR_NULL(test, dc);
3160 	adev->dm.dc = dc;
3161 
3162 	aconn = kunit_kzalloc(test, sizeof(*aconn), GFP_KERNEL);
3163 	KUNIT_ASSERT_NOT_ERR_OR_NULL(test, aconn);
3164 	KUNIT_ASSERT_EQ(test, drm_connector_init(&adev->ddev, &aconn->base,
3165 						 &dm_test_connector_funcs,
3166 						 DRM_MODE_CONNECTOR_DisplayPort), 0);
3167 	KUNIT_ASSERT_EQ(test,
3168 			kunit_add_action_or_reset(test, dm_test_connector_cleanup, &aconn->base), 0);
3169 
3170 	link = kunit_kzalloc(test, sizeof(*link), GFP_KERNEL);
3171 	KUNIT_ASSERT_NOT_ERR_OR_NULL(test, link);
3172 	link->irq_source_hpd = DC_IRQ_SOURCE_HPD1;
3173 	link->irq_source_hpd_rx = DC_IRQ_SOURCE_HPD1RX;
3174 	aconn->dc_link = link;
3175 
3176 	KUNIT_EXPECT_EQ(test, amdgpu_dm_register_hpd_handlers(adev), 0);
3177 	KUNIT_EXPECT_FALSE(test,
3178 			   list_empty(&adev->dm.irq_handler_list_low_tab[DC_IRQ_SOURCE_HPD1]));
3179 	KUNIT_EXPECT_FALSE(test,
3180 			   list_empty(&adev->dm.irq_handler_list_low_tab[DC_IRQ_SOURCE_HPD1RX]));
3181 
3182 	amdgpu_dm_irq_fini(adev);
3183 }
3184 
3185 /**
3186  * dm_test_register_hpd_handlers_invalid_hpd - Test invalid HPD source fails
3187  * @test: The KUnit test context
3188  */
dm_test_register_hpd_handlers_invalid_hpd(struct kunit * test)3189 static void dm_test_register_hpd_handlers_invalid_hpd(struct kunit *test)
3190 {
3191 	struct amdgpu_dm_connector *aconn;
3192 	struct amdgpu_device *adev;
3193 	struct dc_link *link;
3194 	struct dc *dc;
3195 
3196 	adev = dm_kunit_alloc_adev(test);
3197 	KUNIT_ASSERT_EQ(test, amdgpu_dm_irq_init(adev), 0);
3198 	dc = kunit_kzalloc(test, sizeof(*dc), GFP_KERNEL);
3199 	KUNIT_ASSERT_NOT_ERR_OR_NULL(test, dc);
3200 	adev->dm.dc = dc;
3201 
3202 	aconn = kunit_kzalloc(test, sizeof(*aconn), GFP_KERNEL);
3203 	KUNIT_ASSERT_NOT_ERR_OR_NULL(test, aconn);
3204 	KUNIT_ASSERT_EQ(test, drm_connector_init(&adev->ddev, &aconn->base,
3205 						 &dm_test_connector_funcs,
3206 						 DRM_MODE_CONNECTOR_DisplayPort), 0);
3207 	KUNIT_ASSERT_EQ(test,
3208 			kunit_add_action_or_reset(test, dm_test_connector_cleanup, &aconn->base), 0);
3209 
3210 	link = kunit_kzalloc(test, sizeof(*link), GFP_KERNEL);
3211 	KUNIT_ASSERT_NOT_ERR_OR_NULL(test, link);
3212 	link->irq_source_hpd = DC_IRQ_SOURCE_HPD1RX;
3213 	link->irq_source_hpd_rx = DC_IRQ_SOURCE_INVALID;
3214 	aconn->dc_link = link;
3215 
3216 	KUNIT_EXPECT_EQ(test, amdgpu_dm_register_hpd_handlers(adev), -EINVAL);
3217 	amdgpu_dm_irq_fini(adev);
3218 }
3219 
3220 /**
3221  * dm_test_register_hpd_handlers_invalid_hpd_rx - Test invalid HPDRX source fails
3222  * @test: The KUnit test context
3223  */
dm_test_register_hpd_handlers_invalid_hpd_rx(struct kunit * test)3224 static void dm_test_register_hpd_handlers_invalid_hpd_rx(struct kunit *test)
3225 {
3226 	struct amdgpu_dm_connector *aconn;
3227 	struct amdgpu_device *adev;
3228 	struct dc_link *link;
3229 	struct dc *dc;
3230 
3231 	adev = dm_kunit_alloc_adev(test);
3232 	KUNIT_ASSERT_EQ(test, amdgpu_dm_irq_init(adev), 0);
3233 	dc = kunit_kzalloc(test, sizeof(*dc), GFP_KERNEL);
3234 	KUNIT_ASSERT_NOT_ERR_OR_NULL(test, dc);
3235 	adev->dm.dc = dc;
3236 
3237 	aconn = kunit_kzalloc(test, sizeof(*aconn), GFP_KERNEL);
3238 	KUNIT_ASSERT_NOT_ERR_OR_NULL(test, aconn);
3239 	KUNIT_ASSERT_EQ(test, drm_connector_init(&adev->ddev, &aconn->base,
3240 						 &dm_test_connector_funcs,
3241 						 DRM_MODE_CONNECTOR_DisplayPort), 0);
3242 	KUNIT_ASSERT_EQ(test,
3243 			kunit_add_action_or_reset(test, dm_test_connector_cleanup, &aconn->base), 0);
3244 
3245 	link = kunit_kzalloc(test, sizeof(*link), GFP_KERNEL);
3246 	KUNIT_ASSERT_NOT_ERR_OR_NULL(test, link);
3247 	link->irq_source_hpd = DC_IRQ_SOURCE_INVALID;
3248 	link->irq_source_hpd_rx = DC_IRQ_SOURCE_HPD1;
3249 	aconn->dc_link = link;
3250 
3251 	KUNIT_EXPECT_EQ(test, amdgpu_dm_register_hpd_handlers(adev), -EINVAL);
3252 	amdgpu_dm_irq_fini(adev);
3253 }
3254 
3255 /**
3256  * dm_test_register_hpd_handlers_dmub_outbox - Test DMUB outbox callbacks register
3257  * @test: The KUnit test context
3258  *
3259  * Enables DMUB outbox support so dc_is_dmub_outbox_supported() returns true,
3260  * exercising the dm_register_dmub_notify_callback() block. Asserts that the
3261  * HPD, HPD_IRQ and HPD_SENSE_NOTIFY callbacks are registered.
3262  */
dm_test_register_hpd_handlers_dmub_outbox(struct kunit * test)3263 static void dm_test_register_hpd_handlers_dmub_outbox(struct kunit *test)
3264 {
3265 	struct amdgpu_device *adev;
3266 	struct dc *dc;
3267 
3268 	adev = dm_kunit_alloc_adev(test);
3269 	KUNIT_ASSERT_EQ(test, amdgpu_dm_irq_init(adev), 0);
3270 	dc = dm_kunit_alloc_dc_with_ctx(test);
3271 	adev->dm.dc = dc;
3272 
3273 	/* Make dc_is_dmub_outbox_supported() return true. */
3274 	dc->caps.dmcub_support = true;
3275 	dc->ctx->asic_id.chip_family = AMDGPU_FAMILY_GC_11_0_1;
3276 
3277 	KUNIT_EXPECT_EQ(test, amdgpu_dm_register_hpd_handlers(adev), 0);
3278 	KUNIT_EXPECT_PTR_EQ(test, adev->dm.dmub_callback[DMUB_NOTIFICATION_HPD],
3279 			    (dmub_notify_interrupt_callback_t)dmub_hpd_callback);
3280 	KUNIT_EXPECT_PTR_EQ(test, adev->dm.dmub_callback[DMUB_NOTIFICATION_HPD_IRQ],
3281 			    (dmub_notify_interrupt_callback_t)dmub_hpd_callback);
3282 	KUNIT_EXPECT_PTR_EQ(test,
3283 			    adev->dm.dmub_callback[DMUB_NOTIFICATION_HPD_SENSE_NOTIFY],
3284 			    (dmub_notify_interrupt_callback_t)dmub_hpd_sense_callback);
3285 
3286 	amdgpu_dm_irq_fini(adev);
3287 }
3288 
3289 /* Tests for CRTC/pflip/vupdate high IRQ callbacks */
3290 
3291 /**
3292  * dm_test_pflip_high_irq_no_crtc - Test pflip high IRQ with no matching CRTC
3293  * @test: The KUnit test context
3294  */
dm_test_pflip_high_irq_no_crtc(struct kunit * test)3295 static void dm_test_pflip_high_irq_no_crtc(struct kunit *test)
3296 {
3297 	struct common_irq_params params = { 0 };
3298 	struct amdgpu_device *adev;
3299 
3300 	adev = dm_kunit_alloc_adev(test);
3301 	params.adev = adev;
3302 	params.irq_src = (enum dc_irq_source)IRQ_TYPE_PFLIP;
3303 
3304 	dm_pflip_high_irq(&params);
3305 }
3306 
3307 /**
3308  * dm_test_pflip_high_irq_not_submitted - Test pflip high IRQ early status exit
3309  * @test: The KUnit test context
3310  */
dm_test_pflip_high_irq_not_submitted(struct kunit * test)3311 static void dm_test_pflip_high_irq_not_submitted(struct kunit *test)
3312 {
3313 	struct common_irq_params params = { 0 };
3314 	struct amdgpu_crtc *acrtc;
3315 	struct amdgpu_device *adev;
3316 
3317 	adev = dm_kunit_alloc_adev(test);
3318 	acrtc = kunit_kzalloc(test, sizeof(*acrtc), GFP_KERNEL);
3319 	KUNIT_ASSERT_NOT_ERR_OR_NULL(test, acrtc);
3320 
3321 	INIT_LIST_HEAD(&acrtc->base.head);
3322 	acrtc->base.dev = &adev->ddev;
3323 	acrtc->otg_inst = 0;
3324 	acrtc->pflip_status = AMDGPU_FLIP_NONE;
3325 	list_add_tail(&acrtc->base.head, &adev->ddev.mode_config.crtc_list);
3326 	KUNIT_ASSERT_EQ(test, kunit_add_action_or_reset(test,
3327 				dm_test_crtc_list_del, acrtc), 0);
3328 
3329 	params.adev = adev;
3330 	params.irq_src = (enum dc_irq_source)IRQ_TYPE_PFLIP;
3331 
3332 	dm_pflip_high_irq(&params);
3333 	KUNIT_EXPECT_EQ(test, acrtc->pflip_status, AMDGPU_FLIP_NONE);
3334 }
3335 
3336 /**
3337  * dm_test_vupdate_high_irq_no_crtc - Test vupdate high IRQ with no CRTC
3338  * @test: The KUnit test context
3339  */
dm_test_vupdate_high_irq_no_crtc(struct kunit * test)3340 static void dm_test_vupdate_high_irq_no_crtc(struct kunit *test)
3341 {
3342 	struct common_irq_params params = { 0 };
3343 	struct amdgpu_device *adev;
3344 
3345 	adev = dm_kunit_alloc_adev(test);
3346 	params.adev = adev;
3347 	params.irq_src = (enum dc_irq_source)IRQ_TYPE_VUPDATE;
3348 
3349 	dm_vupdate_high_irq(&params);
3350 }
3351 
3352 /**
3353  * dm_test_crtc_high_irq_no_crtc - Test crtc high IRQ with no CRTC
3354  * @test: The KUnit test context
3355  */
dm_test_crtc_high_irq_no_crtc(struct kunit * test)3356 static void dm_test_crtc_high_irq_no_crtc(struct kunit *test)
3357 {
3358 	struct common_irq_params params = { 0 };
3359 	struct amdgpu_device *adev;
3360 
3361 	adev = dm_kunit_alloc_adev(test);
3362 	params.adev = adev;
3363 	params.irq_src = (enum dc_irq_source)IRQ_TYPE_VBLANK;
3364 
3365 	dm_crtc_high_irq(&params);
3366 }
3367 
3368 /**
3369  * dm_test_crtc_high_irq_vrr_pre_ai - Test crtc high IRQ VRR path on pre-AI ASIC
3370  * @test: The KUnit test context
3371  *
3372  * With a matching CRTC, no writeback, VRR active (so the !vrr_active vblank
3373  * handler is skipped) and a pre-AI family, the handler runs through CRC
3374  * handling and returns before the freesync section.
3375  */
dm_test_crtc_high_irq_vrr_pre_ai(struct kunit * test)3376 static void dm_test_crtc_high_irq_vrr_pre_ai(struct kunit *test)
3377 {
3378 	struct common_irq_params params = { 0 };
3379 	struct amdgpu_crtc *acrtc;
3380 	struct amdgpu_device *adev;
3381 
3382 	adev = dm_kunit_alloc_adev(test);
3383 	acrtc = kunit_kzalloc(test, sizeof(*acrtc), GFP_KERNEL);
3384 	KUNIT_ASSERT_NOT_ERR_OR_NULL(test, acrtc);
3385 
3386 	INIT_LIST_HEAD(&acrtc->base.head);
3387 	acrtc->base.dev = &adev->ddev;
3388 	acrtc->otg_inst = 0;
3389 	/* VRR active so the !vrr_active vblank handler is skipped. */
3390 	acrtc->dm_irq_params.freesync_config.state = VRR_STATE_ACTIVE_VARIABLE;
3391 	list_add_tail(&acrtc->base.head, &adev->ddev.mode_config.crtc_list);
3392 	KUNIT_ASSERT_EQ(test, kunit_add_action_or_reset(test,
3393 				dm_test_crtc_list_del, acrtc), 0);
3394 
3395 	/* Pre-AI family returns right after CRC handling. */
3396 	adev->family = AMDGPU_FAMILY_SI;
3397 
3398 	params.adev = adev;
3399 	params.irq_src = (enum dc_irq_source)IRQ_TYPE_VBLANK;
3400 
3401 	dm_crtc_high_irq(&params);
3402 }
3403 
3404 /**
3405  * dm_test_crtc_high_irq_vrr_ai_no_stream - Test crtc high IRQ AI path, no stream
3406  * @test: The KUnit test context
3407  *
3408  * On an AI+ family the handler runs the post-CRC freesync section. With no
3409  * stream and no pending flip, both inner blocks are skipped and the handler
3410  * completes through the event-lock critical section, leaving pflip_status
3411  * untouched.
3412  */
dm_test_crtc_high_irq_vrr_ai_no_stream(struct kunit * test)3413 static void dm_test_crtc_high_irq_vrr_ai_no_stream(struct kunit *test)
3414 {
3415 	struct common_irq_params params = { 0 };
3416 	struct amdgpu_crtc *acrtc;
3417 	struct amdgpu_device *adev;
3418 
3419 	adev = dm_kunit_alloc_adev(test);
3420 	acrtc = kunit_kzalloc(test, sizeof(*acrtc), GFP_KERNEL);
3421 	KUNIT_ASSERT_NOT_ERR_OR_NULL(test, acrtc);
3422 
3423 	INIT_LIST_HEAD(&acrtc->base.head);
3424 	acrtc->base.dev = &adev->ddev;
3425 	acrtc->otg_inst = 0;
3426 	acrtc->pflip_status = AMDGPU_FLIP_NONE;
3427 	/* VRR active so the !vrr_active vblank handler is skipped. */
3428 	acrtc->dm_irq_params.freesync_config.state = VRR_STATE_ACTIVE_VARIABLE;
3429 	list_add_tail(&acrtc->base.head, &adev->ddev.mode_config.crtc_list);
3430 	KUNIT_ASSERT_EQ(test, kunit_add_action_or_reset(test,
3431 				dm_test_crtc_list_del, acrtc), 0);
3432 
3433 	/* AI+ family runs the freesync section; no stream skips it. */
3434 	adev->family = AMDGPU_FAMILY_AI;
3435 
3436 	params.adev = adev;
3437 	params.irq_src = (enum dc_irq_source)IRQ_TYPE_VBLANK;
3438 
3439 	dm_crtc_high_irq(&params);
3440 	KUNIT_EXPECT_EQ(test, acrtc->pflip_status, AMDGPU_FLIP_NONE);
3441 }
3442 
3443 /* Tests for dm_handle_hpd_work() */
3444 
3445 /**
3446  * dm_test_handle_hpd_work_out_of_range - Test HPD work frees unknown notification
3447  * @test: The KUnit test context
3448  */
dm_test_handle_hpd_work_out_of_range(struct kunit * test)3449 static void dm_test_handle_hpd_work_out_of_range(struct kunit *test)
3450 {
3451 	struct dmub_hpd_work *hpd_work;
3452 	struct amdgpu_device *adev;
3453 
3454 	adev = dm_kunit_alloc_adev(test);
3455 	hpd_work = kzalloc_obj(*hpd_work);
3456 	KUNIT_ASSERT_NOT_ERR_OR_NULL(test, hpd_work);
3457 	hpd_work->dmub_notify = kzalloc_obj(*hpd_work->dmub_notify);
3458 	KUNIT_ASSERT_NOT_ERR_OR_NULL(test, hpd_work->dmub_notify);
3459 	hpd_work->dmub_notify->type =
3460 		(enum dmub_notification_type)ARRAY_SIZE(adev->dm.dmub_callback);
3461 	hpd_work->adev = adev;
3462 	INIT_WORK(&hpd_work->handle_hpd_work, dm_handle_hpd_work);
3463 
3464 	dm_handle_hpd_work(&hpd_work->handle_hpd_work);
3465 }
3466 
3467 /* Tests for dm_dmub_outbox1_low_irq() */
3468 
3469 /**
3470  * dm_test_dmub_outbox1_low_irq_empty - Test outbox low IRQ with empty trace queue
3471  * @test: The KUnit test context
3472  */
dm_test_dmub_outbox1_low_irq_empty(struct kunit * test)3473 static void dm_test_dmub_outbox1_low_irq_empty(struct kunit *test)
3474 {
3475 	struct common_irq_params params = { 0 };
3476 	struct dc_dmub_srv *dc_dmub_srv;
3477 	struct amdgpu_device *adev;
3478 	struct dmub_srv *dmub;
3479 	struct dc *dc;
3480 
3481 	adev = dm_kunit_alloc_adev(test);
3482 	dc = dm_kunit_alloc_dc_with_ctx(test);
3483 	dc_dmub_srv = kunit_kzalloc(test, sizeof(*dc_dmub_srv), GFP_KERNEL);
3484 	KUNIT_ASSERT_NOT_ERR_OR_NULL(test, dc_dmub_srv);
3485 	dmub = kunit_kzalloc(test, sizeof(*dmub), GFP_KERNEL);
3486 	KUNIT_ASSERT_NOT_ERR_OR_NULL(test, dmub);
3487 
3488 	dmub->hw_funcs.get_outbox0_wptr = dm_test_dmub_get_outbox0_wptr;
3489 	dc_dmub_srv->dmub = dmub;
3490 	dc->ctx->dmub_srv = dc_dmub_srv;
3491 	adev->dm.dc = dc;
3492 	params.adev = adev;
3493 	params.irq_src = DC_IRQ_SOURCE_DMCUB_OUTBOX;
3494 
3495 	dm_dmub_outbox1_low_irq(&params);
3496 }
3497 
3498 /*
3499  * dm_test_alloc_adev_outbox_notify - Build an adev wired for DMUB outbox
3500  * notification handling.
3501  *
3502  * Configures dc/dc_dmub_srv/dmub so that the trace queue is empty and
3503  * dc_enable_dmub_notifications() returns true, allowing the notification
3504  * handling block of dm_dmub_outbox1_low_irq() to execute. The outbox1 ring
3505  * buffer is left empty, so each notification read returns
3506  * DMUB_NOTIFICATION_NO_DATA with no pending notification.
3507  */
dm_test_alloc_adev_outbox_notify(struct kunit * test)3508 static struct amdgpu_device *dm_test_alloc_adev_outbox_notify(struct kunit *test)
3509 {
3510 	struct dc_dmub_srv *dc_dmub_srv;
3511 	struct amdgpu_device *adev;
3512 	struct dmub_srv *dmub;
3513 	struct dc *dc;
3514 
3515 	adev = dm_kunit_alloc_adev(test);
3516 	dc = dm_kunit_alloc_dc_with_ctx(test);
3517 	dc_dmub_srv = kunit_kzalloc(test, sizeof(*dc_dmub_srv), GFP_KERNEL);
3518 	KUNIT_ASSERT_NOT_ERR_OR_NULL(test, dc_dmub_srv);
3519 	dmub = kunit_kzalloc(test, sizeof(*dmub), GFP_KERNEL);
3520 	KUNIT_ASSERT_NOT_ERR_OR_NULL(test, dmub);
3521 
3522 	dmub->hw_init = true;
3523 	dmub->hw_funcs.get_outbox0_wptr = dm_test_dmub_get_outbox0_wptr;
3524 	dmub->hw_funcs.get_outbox1_wptr = dm_test_dmub_get_outbox1_wptr;
3525 	dc_dmub_srv->dmub = dmub;
3526 	dc->ctx->dmub_srv = dc_dmub_srv;
3527 
3528 	/* Make dc_enable_dmub_notifications() return true. */
3529 	dc->caps.dmcub_support = true;
3530 	dc->ctx->asic_id.chip_family = AMDGPU_FAMILY_GC_11_0_1;
3531 
3532 	adev->dm.dc = dc;
3533 
3534 	return adev;
3535 }
3536 
3537 /**
3538  * dm_test_dmub_outbox1_low_irq_no_handler - Test notification with no handler
3539  * @test: The KUnit test context
3540  *
3541  * Notifications are enabled but no callback is registered for the returned
3542  * notification type, exercising the skip-with-warning path.
3543  */
dm_test_dmub_outbox1_low_irq_no_handler(struct kunit * test)3544 static void dm_test_dmub_outbox1_low_irq_no_handler(struct kunit *test)
3545 {
3546 	struct common_irq_params params = { 0 };
3547 	struct amdgpu_device *adev;
3548 
3549 	adev = dm_test_alloc_adev_outbox_notify(test);
3550 	params.adev = adev;
3551 	params.irq_src = DC_IRQ_SOURCE_DMCUB_OUTBOX;
3552 
3553 	dm_dmub_outbox1_low_irq(&params);
3554 }
3555 
3556 /**
3557  * dm_test_dmub_outbox1_low_irq_direct_callback - Test direct callback dispatch
3558  * @test: The KUnit test context
3559  *
3560  * Notifications are enabled with a registered callback and thread offload
3561  * disabled, so the callback is invoked directly from the IRQ handler.
3562  */
dm_test_dmub_outbox1_low_irq_direct_callback(struct kunit * test)3563 static void dm_test_dmub_outbox1_low_irq_direct_callback(struct kunit *test)
3564 {
3565 	struct common_irq_params params = { 0 };
3566 	struct amdgpu_device *adev;
3567 
3568 	adev = dm_test_alloc_adev_outbox_notify(test);
3569 	adev->dm.dmub_callback[DMUB_NOTIFICATION_NO_DATA] = dm_test_dmub_notify_callback;
3570 	adev->dm.dmub_thread_offload[DMUB_NOTIFICATION_NO_DATA] = false;
3571 	params.adev = adev;
3572 	params.irq_src = DC_IRQ_SOURCE_DMCUB_OUTBOX;
3573 
3574 	dm_test_dmub_notify_count = 0;
3575 
3576 	dm_dmub_outbox1_low_irq(&params);
3577 
3578 	KUNIT_EXPECT_EQ(test, dm_test_dmub_notify_count, 1);
3579 }
3580 
3581 /**
3582  * dm_test_dmub_outbox1_low_irq_offload - Test offloaded callback dispatch
3583  * @test: The KUnit test context
3584  *
3585  * Notifications are enabled with a registered callback and thread offload
3586  * enabled, so the callback is dispatched via the delayed HPD work queue.
3587  */
dm_test_dmub_outbox1_low_irq_offload(struct kunit * test)3588 static void dm_test_dmub_outbox1_low_irq_offload(struct kunit *test)
3589 {
3590 	struct common_irq_params params = { 0 };
3591 	struct amdgpu_device *adev;
3592 
3593 	adev = dm_test_alloc_adev_outbox_notify(test);
3594 	adev->dm.dmub_callback[DMUB_NOTIFICATION_NO_DATA] = dm_test_dmub_notify_callback;
3595 	adev->dm.dmub_thread_offload[DMUB_NOTIFICATION_NO_DATA] = true;
3596 	adev->dm.delayed_hpd_wq = create_singlethread_workqueue("dm_irq_test_outbox");
3597 	KUNIT_ASSERT_NOT_NULL(test, adev->dm.delayed_hpd_wq);
3598 	params.adev = adev;
3599 	params.irq_src = DC_IRQ_SOURCE_DMCUB_OUTBOX;
3600 
3601 	dm_test_dmub_notify_count = 0;
3602 
3603 	dm_dmub_outbox1_low_irq(&params);
3604 
3605 	flush_workqueue(adev->dm.delayed_hpd_wq);
3606 	destroy_workqueue(adev->dm.delayed_hpd_wq);
3607 
3608 	KUNIT_EXPECT_EQ(test, dm_test_dmub_notify_count, 1);
3609 }
3610 
3611 
3612 /**
3613  * dm_test_dce110_register_irq_handlers_rejects_uninitialized_sources - Test DCE110 error
3614  * @test: The KUnit test context
3615  */
dm_test_dce110_register_irq_handlers_rejects_uninitialized_sources(struct kunit * test)3616 static void dm_test_dce110_register_irq_handlers_rejects_uninitialized_sources(struct kunit *test)
3617 {
3618 	struct amdgpu_device *adev;
3619 	struct dc *dc;
3620 
3621 	adev = dm_kunit_alloc_adev(test);
3622 	dc = dm_kunit_alloc_dc_with_ctx(test);
3623 	adev->dm.dc = dc;
3624 
3625 	KUNIT_EXPECT_EQ(test, amdgpu_dm_dce110_register_irq_handlers(adev), -EINVAL);
3626 }
3627 
3628 /**
3629  * dm_test_dce110_register_irq_handlers_one_crtc - Test DCE110 with 1 CRTC
3630  * @test: The KUnit test context
3631  *
3632  * Exercises the VBLANK, VUPDATE, PFLIP and HPD for-loop bodies with a
3633  * fake IRQ service that maps source IDs to DC IRQ sources.
3634  */
dm_test_dce110_register_irq_handlers_one_crtc(struct kunit * test)3635 static void dm_test_dce110_register_irq_handlers_one_crtc(struct kunit *test)
3636 {
3637 	struct amdgpu_device *adev;
3638 	struct dc *dc;
3639 
3640 	adev = dm_kunit_alloc_adev(test);
3641 	KUNIT_ASSERT_EQ(test, kunit_add_action_or_reset(test, dm_test_free_irq_sources,
3642 							 adev), 0);
3643 	dc = dm_test_alloc_dc_with_irq_service(test, &dm_test_irq_service_funcs_dce110);
3644 	dc->ctx->dce_version = DCE_VERSION_11_0;
3645 	adev->dm.dc = dc;
3646 	adev->mode_info.num_crtc = 1;
3647 	adev->mode_info.num_hpd = 1;
3648 	amdgpu_dm_set_irq_funcs(adev);
3649 	KUNIT_ASSERT_EQ(test, amdgpu_dm_irq_init(adev), 0);
3650 
3651 	KUNIT_EXPECT_EQ(test, amdgpu_dm_dce110_register_irq_handlers(adev), 0);
3652 
3653 	/* Verify VBLANK params were populated */
3654 	KUNIT_EXPECT_EQ(test, (int)adev->dm.vblank_params[0].irq_src,
3655 			(int)DC_IRQ_SOURCE_VBLANK1);
3656 	KUNIT_EXPECT_PTR_EQ(test, adev->dm.vblank_params[0].adev, adev);
3657 
3658 	/* Verify VUPDATE params were populated (VRR supported on DCE 11) */
3659 	KUNIT_EXPECT_EQ(test, (int)adev->dm.vupdate_params[0].irq_src,
3660 			(int)DC_IRQ_SOURCE_VUPDATE1);
3661 
3662 	/* Verify PFLIP params were populated (6 fixed entries) */
3663 	KUNIT_EXPECT_EQ(test, (int)adev->dm.pflip_params[0].irq_src,
3664 			(int)DC_IRQ_SOURCE_PFLIP1);
3665 	KUNIT_EXPECT_EQ(test, (int)adev->dm.pflip_params[5].irq_src,
3666 			(int)DC_IRQ_SOURCE_PFLIP6);
3667 
3668 	amdgpu_dm_irq_fini(adev);
3669 }
3670 
3671 /**
3672  * dm_test_dcn10_register_irq_handlers_zero_crtc - Test DCN10 zero-CRTC registration
3673  * @test: The KUnit test context
3674  */
dm_test_dcn10_register_irq_handlers_zero_crtc(struct kunit * test)3675 static void dm_test_dcn10_register_irq_handlers_zero_crtc(struct kunit *test)
3676 {
3677 	struct amdgpu_device *adev;
3678 	struct dc *dc;
3679 
3680 	adev = dm_kunit_alloc_adev(test);
3681 	KUNIT_ASSERT_EQ(test, kunit_add_action_or_reset(test, dm_test_free_irq_sources,
3682 							 adev), 0);
3683 	dc = dm_kunit_alloc_dc_with_ctx(test);
3684 	adev->dm.dc = dc;
3685 	adev->mode_info.num_hpd = 1;
3686 	amdgpu_dm_set_irq_funcs(adev);
3687 
3688 	KUNIT_EXPECT_EQ(test, amdgpu_dm_dcn10_register_irq_handlers(adev), 0);
3689 	KUNIT_ASSERT_NOT_NULL(test, adev->irq.client[SOC15_IH_CLIENTID_DCE].sources);
3690 	KUNIT_EXPECT_PTR_EQ(test,
3691 		adev->irq.client[SOC15_IH_CLIENTID_DCE].sources[DCN_1_0__SRCID__DC_HPD1_INT],
3692 		&adev->hpd_irq);
3693 }
3694 
3695 /**
3696  * dm_test_dcn10_register_irq_handlers_one_crtc - Test DCN10 with 1 CRTC
3697  * @test: The KUnit test context
3698  *
3699  * Exercises the VUPDATE_NO_LOCK for-loop bodies with a fake IRQ service, and
3700  * that it's the only one populated (other than VLINE0, for secure display).
3701  */
dm_test_dcn10_register_irq_handlers_one_crtc(struct kunit * test)3702 static void dm_test_dcn10_register_irq_handlers_one_crtc(struct kunit *test)
3703 {
3704 	struct amdgpu_device *adev;
3705 	struct dc *dc;
3706 
3707 	adev = dm_kunit_alloc_adev(test);
3708 	KUNIT_ASSERT_EQ(test, kunit_add_action_or_reset(test, dm_test_free_irq_sources,
3709 							 adev), 0);
3710 	dc = dm_test_alloc_dc_with_irq_service(test, &dm_test_irq_service_funcs_dcn10);
3711 	adev->dm.dc = dc;
3712 	adev->mode_info.num_crtc = 1;
3713 	adev->mode_info.num_hpd = 1;
3714 	dc->caps.max_otg_num = 1;
3715 	amdgpu_dm_set_irq_funcs(adev);
3716 	KUNIT_ASSERT_EQ(test, amdgpu_dm_irq_init(adev), 0);
3717 
3718 	KUNIT_EXPECT_EQ(test, amdgpu_dm_dcn10_register_irq_handlers(adev), 0);
3719 
3720 	/* Verify VBLANK params were *not* populated */
3721 	KUNIT_EXPECT_EQ(test, (int)adev->dm.vblank_params[0].irq_src, 0);
3722 	KUNIT_EXPECT_NULL(test, adev->dm.vblank_params[0].adev);
3723 
3724 	/* Verify VUPDATE params were populated */
3725 	KUNIT_EXPECT_EQ(test, (int)adev->dm.vupdate_params[0].irq_src,
3726 			(int)DC_IRQ_SOURCE_VUPDATE1);
3727 
3728 	/* Verify PFLIP params were *not* populated */
3729 	KUNIT_EXPECT_EQ(test, (int)adev->dm.pflip_params[0].irq_src, 0);
3730 
3731 	amdgpu_dm_irq_fini(adev);
3732 }
3733 
3734 /**
3735  * dm_test_register_outbox_irq_handlers_without_dmub - Test outbox registration without DMUB
3736  * @test: The KUnit test context
3737  */
dm_test_register_outbox_irq_handlers_without_dmub(struct kunit * test)3738 static void dm_test_register_outbox_irq_handlers_without_dmub(struct kunit *test)
3739 {
3740 	struct amdgpu_device *adev;
3741 	struct dc *dc;
3742 
3743 	adev = dm_kunit_alloc_adev(test);
3744 	KUNIT_ASSERT_EQ(test, kunit_add_action_or_reset(test, dm_test_free_irq_sources,
3745 							 adev), 0);
3746 	dc = dm_kunit_alloc_dc_with_ctx(test);
3747 	adev->dm.dc = dc;
3748 	amdgpu_dm_set_irq_funcs(adev);
3749 
3750 	KUNIT_EXPECT_EQ(test, amdgpu_dm_register_outbox_irq_handlers(adev), 0);
3751 	KUNIT_ASSERT_NOT_NULL(test, adev->irq.client[SOC15_IH_CLIENTID_DCE].sources);
3752 	KUNIT_EXPECT_PTR_EQ(test,
3753 		adev->irq.client[SOC15_IH_CLIENTID_DCE].sources[
3754 			DCN_1_0__SRCID__DMCUB_OUTBOX_LOW_PRIORITY_READY_INT],
3755 		&adev->dmub_outbox_irq);
3756 }
3757 
3758 /**
3759  * dm_test_register_outbox_irq_handlers_with_dmub - Test outbox registration with DMUB
3760  * @test: The KUnit test context
3761  *
3762  * Exercises the dc->ctx->dmub_srv branch which maps the outbox source and
3763  * registers dm_dmub_outbox1_low_irq in the low IRQ context table.
3764  */
dm_test_register_outbox_irq_handlers_with_dmub(struct kunit * test)3765 static void dm_test_register_outbox_irq_handlers_with_dmub(struct kunit *test)
3766 {
3767 	struct dc_dmub_srv *dc_dmub_srv;
3768 	struct amdgpu_device *adev;
3769 	struct list_head *hnd_list;
3770 	struct dc *dc;
3771 
3772 	adev = dm_kunit_alloc_adev(test);
3773 	KUNIT_ASSERT_EQ(test, kunit_add_action_or_reset(test, dm_test_free_irq_sources,
3774 							 adev), 0);
3775 	dc = dm_test_alloc_dc_with_irq_service(test, &dm_test_irq_service_funcs_dcn10);
3776 	dc_dmub_srv = kunit_kzalloc(test, sizeof(*dc_dmub_srv), GFP_KERNEL);
3777 	KUNIT_ASSERT_NOT_ERR_OR_NULL(test, dc_dmub_srv);
3778 	dc->ctx->dmub_srv = dc_dmub_srv;
3779 	adev->dm.dc = dc;
3780 	amdgpu_dm_set_irq_funcs(adev);
3781 	KUNIT_ASSERT_EQ(test, amdgpu_dm_irq_init(adev), 0);
3782 
3783 	KUNIT_EXPECT_EQ(test, amdgpu_dm_register_outbox_irq_handlers(adev), 0);
3784 
3785 	/* Verify the outbox IRQ params were populated */
3786 	KUNIT_EXPECT_EQ(test, (int)adev->dm.dmub_outbox_params[0].irq_src,
3787 			(int)DC_IRQ_SOURCE_DMCUB_OUTBOX);
3788 	KUNIT_EXPECT_PTR_EQ(test, adev->dm.dmub_outbox_params[0].adev, adev);
3789 
3790 	/* Verify a low-context handler was registered for the outbox source */
3791 	hnd_list = &adev->dm.irq_handler_list_low_tab[DC_IRQ_SOURCE_DMCUB_OUTBOX];
3792 	KUNIT_EXPECT_FALSE(test, list_empty(hnd_list));
3793 
3794 	amdgpu_dm_irq_fini(adev);
3795 }
3796 
3797 /* Tests for amdgpu_dm_irq_handler() */
3798 
3799 /**
3800  * dm_test_irq_handler_dispatches_work - Test the top-level IRQ handler
3801  * @test: The KUnit test context
3802  *
3803  * amdgpu_dm_irq_handler() translates the hardware IRQ entry to a DC IRQ
3804  * source, acknowledges it, then dispatches to the high-context (immediate)
3805  * and low-context (scheduled) handler lists. A fake dc with a stubbed
3806  * irq_service maps the source id to DC_IRQ_SOURCE_VBLANK1 and lets the ack
3807  * succeed without touching hardware registers.
3808  */
dm_test_irq_handler_dispatches_work(struct kunit * test)3809 static void dm_test_irq_handler_dispatches_work(struct kunit *test)
3810 {
3811 	struct dc_interrupt_params int_params = { 0 };
3812 	struct amdgpu_iv_entry entry = { 0 };
3813 	struct amdgpu_device *adev;
3814 	int high_count = 0;
3815 	int low_count = 0;
3816 	void *handler;
3817 	struct dc *dc;
3818 
3819 	adev = kunit_kzalloc(test, sizeof(*adev), GFP_KERNEL);
3820 	KUNIT_ASSERT_NOT_ERR_OR_NULL(test, adev);
3821 	KUNIT_ASSERT_EQ(test, amdgpu_dm_irq_init(adev), 0);
3822 
3823 	dc = dm_test_alloc_dc_with_irq_service(test,
3824 					       &dm_test_irq_service_funcs_dce110);
3825 	adev->dm.dc = dc;
3826 
3827 	/* High-context (immediate) handler on VBLANK1. */
3828 	int_params.int_context = INTERRUPT_HIGH_IRQ_CONTEXT;
3829 	int_params.irq_source = DC_IRQ_SOURCE_VBLANK1;
3830 	handler = amdgpu_dm_irq_register_interrupt(adev, &int_params,
3831 						   dm_test_irq_handler_count,
3832 						   &high_count);
3833 	KUNIT_ASSERT_NOT_ERR_OR_NULL(test, handler);
3834 
3835 	/* Low-context (scheduled) handler on VBLANK1. */
3836 	int_params.int_context = INTERRUPT_LOW_IRQ_CONTEXT;
3837 	handler = amdgpu_dm_irq_register_interrupt(adev, &int_params,
3838 						   dm_test_irq_handler_count,
3839 						   &low_count);
3840 	KUNIT_ASSERT_NOT_ERR_OR_NULL(test, handler);
3841 
3842 	/* src_id maps to DC_IRQ_SOURCE_VBLANK1 via the dce110 stub. */
3843 	entry.src_id = VISLANDS30_IV_SRCID_D1_VERTICAL_INTERRUPT0;
3844 	entry.src_data[0] = 0;
3845 
3846 	KUNIT_EXPECT_EQ(test, amdgpu_dm_irq_handler(adev, NULL, &entry), 0);
3847 
3848 	/* High-context handler runs synchronously in-place. */
3849 	KUNIT_EXPECT_EQ(test, high_count, 1);
3850 
3851 	/*
3852 	 * Low-context work runs asynchronously; flush the DM IRQ workqueue so
3853 	 * it completes before we check the count. amdgpu_dm_irq_fini() cancels
3854 	 * any still-pending work rather than running it.
3855 	 */
3856 	flush_workqueue(adev->dm.irq_wq);
3857 	KUNIT_EXPECT_EQ(test, low_count, 1);
3858 
3859 	amdgpu_dm_irq_fini(adev);
3860 }
3861 
3862 /* Tests for dm_handle_vmin_vmax_update() */
3863 
3864 /**
3865  * dm_test_handle_vmin_vmax_update - Test the deferred vmin/vmax worker
3866  * @test: The KUnit test context
3867  *
3868  * The worker applies the cached timing adjust to the stream via
3869  * dc_stream_adjust_vmin_vmax(), drops the stream reference taken when the
3870  * work was scheduled, and frees the work and its adjust copy. A fake dc with
3871  * a current_state lets the adjust walk an empty pipe list without touching
3872  * hardware. The work and adjust are kmalloc'd because the worker frees them.
3873  */
dm_test_handle_vmin_vmax_update(struct kunit * test)3874 static void dm_test_handle_vmin_vmax_update(struct kunit *test)
3875 {
3876 	struct dc_crtc_timing_adjust *adjust;
3877 	struct vupdate_offload_work *work;
3878 	struct dc_stream_state *stream;
3879 	struct amdgpu_device *adev;
3880 	struct dc *dc;
3881 
3882 	adev = kunit_kzalloc(test, sizeof(*adev), GFP_KERNEL);
3883 	KUNIT_ASSERT_NOT_ERR_OR_NULL(test, adev);
3884 	mutex_init(&adev->dm.dc_lock);
3885 
3886 	dc = dm_kunit_alloc_dc_with_ctx(test);
3887 	dc->current_state = kunit_kzalloc(test, sizeof(*dc->current_state),
3888 					  GFP_KERNEL);
3889 	KUNIT_ASSERT_NOT_ERR_OR_NULL(test, dc->current_state);
3890 	adev->dm.dc = dc;
3891 
3892 	stream = kunit_kzalloc(test, sizeof(*stream), GFP_KERNEL);
3893 	KUNIT_ASSERT_NOT_ERR_OR_NULL(test, stream);
3894 	/*
3895 	 * Start at two references: the worker's dc_stream_release() drops one,
3896 	 * leaving the kunit-managed allocation intact (no kfree).
3897 	 */
3898 	kref_init(&stream->refcount);
3899 	kref_get(&stream->refcount);
3900 
3901 	/* The worker kfree()s both, so they must come from the slab. */
3902 	work = kzalloc_obj(*work);
3903 	KUNIT_ASSERT_NOT_ERR_OR_NULL(test, work);
3904 	adjust = kzalloc_obj(*adjust);
3905 	KUNIT_ASSERT_NOT_ERR_OR_NULL(test, adjust);
3906 
3907 	work->adev = adev;
3908 	work->stream = stream;
3909 	work->adjust = adjust;
3910 	adjust->v_total_min = 1000;
3911 	adjust->v_total_max = 1100;
3912 
3913 	dm_handle_vmin_vmax_update(&work->work);
3914 
3915 	/* The adjust was applied and one stream reference was dropped. */
3916 	KUNIT_EXPECT_EQ(test, stream->adjust.v_total_min, 1000);
3917 	KUNIT_EXPECT_EQ(test, stream->adjust.v_total_max, 1100);
3918 	KUNIT_EXPECT_EQ(test, kref_read(&stream->refcount), 1);
3919 }
3920 
3921 static struct kunit_case amdgpu_dm_irq_tests[] = {
3922 	/* amdgpu_dm_hpd_to_dal_irq_source */
3923 	KUNIT_CASE(dm_test_hpd_to_dal_irq_source_hpd1),
3924 	KUNIT_CASE(dm_test_hpd_to_dal_irq_source_hpd2),
3925 	KUNIT_CASE(dm_test_hpd_to_dal_irq_source_hpd3),
3926 	KUNIT_CASE(dm_test_hpd_to_dal_irq_source_hpd4),
3927 	KUNIT_CASE(dm_test_hpd_to_dal_irq_source_hpd5),
3928 	KUNIT_CASE(dm_test_hpd_to_dal_irq_source_hpd6),
3929 	KUNIT_CASE(dm_test_hpd_to_dal_irq_source_invalid),
3930 	KUNIT_CASE(dm_test_hpd_to_dal_irq_source_out_of_range),
3931 	/* are_sinks_equal */
3932 	KUNIT_CASE(dm_test_are_sinks_equal_both_null),
3933 	KUNIT_CASE(dm_test_are_sinks_equal_first_null),
3934 	KUNIT_CASE(dm_test_are_sinks_equal_second_null),
3935 	KUNIT_CASE(dm_test_are_sinks_equal_different_signal),
3936 	KUNIT_CASE(dm_test_are_sinks_equal_different_edid_length),
3937 	KUNIT_CASE(dm_test_are_sinks_equal_different_edid_data),
3938 	KUNIT_CASE(dm_test_are_sinks_equal_identical),
3939 	KUNIT_CASE(dm_test_are_sinks_equal_zero_length),
3940 	KUNIT_CASE(dm_test_are_sinks_equal_full_edid_identical),
3941 	KUNIT_CASE(dm_test_are_sinks_equal_full_edid_last_byte_differs),
3942 	/* dmub_notification_type_str */
3943 	KUNIT_CASE(dm_test_notification_str_no_data),
3944 	KUNIT_CASE(dm_test_notification_str_aux_reply),
3945 	KUNIT_CASE(dm_test_notification_str_hpd),
3946 	KUNIT_CASE(dm_test_notification_str_hpd_irq),
3947 	KUNIT_CASE(dm_test_notification_str_set_config),
3948 	KUNIT_CASE(dm_test_notification_str_dpia),
3949 	KUNIT_CASE(dm_test_notification_str_hpd_sense),
3950 	KUNIT_CASE(dm_test_notification_str_fused_io),
3951 	KUNIT_CASE(dm_test_notification_str_unknown),
3952 	/* amdgpu_dm_irq_init */
3953 	KUNIT_CASE(dm_test_irq_init_initializes_lists),
3954 	/* amdgpu_dm_irq_register_interrupt */
3955 	KUNIT_CASE(dm_test_irq_register_rejects_null_params),
3956 	KUNIT_CASE(dm_test_irq_register_rejects_invalid_context),
3957 	KUNIT_CASE(dm_test_irq_register_rejects_invalid_source),
3958 	KUNIT_CASE(dm_test_irq_register_adds_low_context_handler),
3959 	KUNIT_CASE(dm_test_irq_register_adds_high_context_handler),
3960 	KUNIT_CASE(dm_test_irq_register_multiple_handlers),
3961 	KUNIT_CASE(dm_test_irq_register_separate_contexts),
3962 	/* amdgpu_dm_irq_unregister_interrupt */
3963 	KUNIT_CASE(dm_test_irq_unregister_rejects_invalid_source),
3964 	KUNIT_CASE(dm_test_irq_unregister_rejects_null_handler),
3965 	KUNIT_CASE(dm_test_irq_unregister_handler_not_found),
3966 	/* amdgpu_dm_irq_fini */
3967 	KUNIT_CASE(dm_test_irq_fini_removes_registered_handlers),
3968 	KUNIT_CASE(dm_test_irq_fini_on_empty_tables),
3969 	/* amdgpu_dm_get_crtc_by_otg_inst */
3970 	KUNIT_CASE(dm_test_get_crtc_by_otg_inst_returns_match),
3971 	KUNIT_CASE(dm_test_get_crtc_by_otg_inst_returns_null),
3972 	KUNIT_CASE(dm_test_get_crtc_by_otg_inst_empty_list),
3973 	/* amdgpu_dm_set_irq_funcs */
3974 	KUNIT_CASE(dm_test_set_irq_funcs),
3975 	/* amdgpu_dm_irq_suspend/resume_early/resume_late */
3976 	KUNIT_CASE(dm_test_irq_suspend_empty),
3977 	KUNIT_CASE(dm_test_irq_resume_early_empty),
3978 	KUNIT_CASE(dm_test_irq_resume_late_empty),
3979 	KUNIT_CASE(dm_test_irq_suspend_registered),
3980 	KUNIT_CASE(dm_test_irq_suspend_disables_polling),
3981 	KUNIT_CASE(dm_test_irq_resume_early_registered),
3982 	KUNIT_CASE(dm_test_irq_resume_late_registered),
3983 	KUNIT_CASE(dm_test_irq_resume_late_enables_polling),
3984 	/* amdgpu_dm_hpd_rx_irq_create_workqueue */
3985 	KUNIT_CASE(dm_test_hpd_rx_irq_create_workqueue),
3986 	/* amdgpu_dm_hpd_rx_irq_work_suspend */
3987 	KUNIT_CASE(dm_test_hpd_rx_irq_work_suspend_null),
3988 	KUNIT_CASE(dm_test_hpd_rx_irq_work_suspend_flushes),
3989 	/* CRTC-based irq state callbacks (no-CRTC early return) */
3990 	KUNIT_CASE(dm_test_set_crtc_irq_state_no_crtc),
3991 	KUNIT_CASE(dm_test_set_pflip_irq_state_no_crtc),
3992 	KUNIT_CASE(dm_test_set_vline0_irq_state_no_crtc),
3993 	KUNIT_CASE(dm_test_set_vupdate_irq_state_no_crtc),
3994 	/* CRTC-based irq state callbacks (dm_irq_state happy path) */
3995 	KUNIT_CASE(dm_test_set_crtc_irq_state_otg_disabled),
3996 	KUNIT_CASE(dm_test_set_crtc_irq_state_enable),
3997 	KUNIT_CASE(dm_test_set_pflip_irq_state_disable),
3998 	KUNIT_CASE(dm_test_set_vline0_irq_state_enable),
3999 	KUNIT_CASE(dm_test_set_vupdate_irq_state_enable),
4000 	KUNIT_CASE(dm_test_set_crtc_irq_state_allows_idle),
4001 	/* amdgpu_dm_irq_immediate_work */
4002 	KUNIT_CASE(dm_test_irq_immediate_work_empty),
4003 	KUNIT_CASE(dm_test_irq_immediate_work_invokes_handler),
4004 	KUNIT_CASE(dm_test_irq_immediate_work_invokes_all),
4005 	/* amdgpu_dm_irq_schedule_work */
4006 	KUNIT_CASE(dm_test_irq_schedule_work_empty),
4007 	KUNIT_CASE(dm_test_irq_schedule_work_queues_handler),
4008 	KUNIT_CASE(dm_test_irq_schedule_work_requeue_fallback),
4009 	/* amdgpu_dm_set_hpd_irq_state */
4010 	KUNIT_CASE(dm_test_set_hpd_irq_state_null_dc),
4011 	/* amdgpu_dm_set_dmub_outbox_irq_state */
4012 	KUNIT_CASE(dm_test_set_dmub_outbox_irq_state_null_dc),
4013 	/* amdgpu_dm_set_dmub_trace_irq_state */
4014 	KUNIT_CASE(dm_test_set_dmub_trace_irq_state_null_dc),
4015 	/* amdgpu_dm_outbox_init */
4016 	KUNIT_CASE(dm_test_outbox_init_null_dc),
4017 	/* amdgpu_dm_hpd_init/amdgpu_dm_hpd_fini */
4018 	KUNIT_CASE(dm_test_hpd_init_empty_connectors),
4019 	KUNIT_CASE(dm_test_hpd_fini_empty_connectors),
4020 	KUNIT_CASE(dm_test_hpd_init_fini_with_connectors),
4021 	KUNIT_CASE(dm_test_hpd_init_fini_analog_connector),
4022 	KUNIT_CASE(dm_test_hpd_init_fini_irq_ref),
4023 	/* dm_handle_hpd_rx_offload_work */
4024 	KUNIT_CASE(dm_test_hpd_rx_offload_work_no_connector),
4025 	KUNIT_CASE(dm_test_hpd_rx_offload_work_no_connection),
4026 	KUNIT_CASE(dm_test_hpd_rx_offload_work_automated_test),
4027 	KUNIT_CASE(dm_test_hpd_rx_offload_work_link_loss),
4028 	/* amdgpu_dm_hdmi_hpd_debounce_work */
4029 	KUNIT_CASE(dm_test_hdmi_hpd_debounce_detect_false),
4030 	KUNIT_CASE(dm_test_hdmi_hpd_debounce_reallow_idle),
4031 	/* handle_hpd_irq/handle_hpd_irq_helper */
4032 	KUNIT_CASE(dm_test_handle_hpd_irq_disabled),
4033 	KUNIT_CASE(dm_test_handle_hpd_irq_helper_debounce_schedule),
4034 	KUNIT_CASE(dm_test_handle_hpd_irq_helper_debounce_release_prev),
4035 	KUNIT_CASE(dm_test_handle_hpd_irq_helper_detect_false),
4036 	/* handle_hpd_rx_irq/schedule_hpd_rx_offload_work */
4037 	KUNIT_CASE(dm_test_handle_hpd_rx_irq_disabled),
4038 	KUNIT_CASE(dm_test_handle_hpd_rx_irq_no_left_work),
4039 	KUNIT_CASE(dm_test_handle_hpd_rx_irq_automated_test),
4040 	KUNIT_CASE(dm_test_handle_hpd_rx_irq_msg_rdy),
4041 	KUNIT_CASE(dm_test_handle_hpd_rx_irq_link_loss),
4042 	KUNIT_CASE(dm_test_schedule_hpd_rx_offload_work),
4043 	/* dmub_hpd_callback/dmub_hpd_sense_callback */
4044 	KUNIT_CASE(dm_test_dmub_hpd_callback_null_inputs),
4045 	KUNIT_CASE(dm_test_dmub_hpd_callback_invalid_index),
4046 	KUNIT_CASE(dm_test_dmub_hpd_callback_empty_connectors),
4047 	KUNIT_CASE(dm_test_dmub_hpd_callback_unknown_type_match),
4048 	KUNIT_CASE(dm_test_dmub_hpd_callback_hpd_type),
4049 	KUNIT_CASE(dm_test_dmub_hpd_callback_hpd_irq_type),
4050 	/* amdgpu_dm_register_hpd_handlers */
4051 	KUNIT_CASE(dm_test_register_hpd_handlers_empty),
4052 	KUNIT_CASE(dm_test_register_hpd_handlers_valid),
4053 	KUNIT_CASE(dm_test_register_hpd_handlers_invalid_hpd),
4054 	KUNIT_CASE(dm_test_register_hpd_handlers_invalid_hpd_rx),
4055 	KUNIT_CASE(dm_test_register_hpd_handlers_dmub_outbox),
4056 	/* pflip/vupdate/crtc high IRQ callbacks */
4057 	KUNIT_CASE(dm_test_pflip_high_irq_no_crtc),
4058 	KUNIT_CASE(dm_test_pflip_high_irq_not_submitted),
4059 	KUNIT_CASE(dm_test_vupdate_high_irq_no_crtc),
4060 	KUNIT_CASE(dm_test_crtc_high_irq_no_crtc),
4061 	KUNIT_CASE(dm_test_crtc_high_irq_vrr_pre_ai),
4062 	KUNIT_CASE(dm_test_crtc_high_irq_vrr_ai_no_stream),
4063 	/* dm_handle_hpd_work */
4064 	KUNIT_CASE(dm_test_handle_hpd_work_out_of_range),
4065 	/* dm_dmub_outbox1_low_irq */
4066 	KUNIT_CASE(dm_test_dmub_outbox1_low_irq_empty),
4067 	KUNIT_CASE(dm_test_dmub_outbox1_low_irq_no_handler),
4068 	KUNIT_CASE(dm_test_dmub_outbox1_low_irq_direct_callback),
4069 	KUNIT_CASE(dm_test_dmub_outbox1_low_irq_offload),
4070 	/* IRQ handler registration helpers */
4071 	KUNIT_CASE(dm_test_dce110_register_irq_handlers_rejects_uninitialized_sources),
4072 	KUNIT_CASE(dm_test_dce110_register_irq_handlers_one_crtc),
4073 	KUNIT_CASE(dm_test_dcn10_register_irq_handlers_zero_crtc),
4074 	KUNIT_CASE(dm_test_dcn10_register_irq_handlers_one_crtc),
4075 	KUNIT_CASE(dm_test_register_outbox_irq_handlers_without_dmub),
4076 	KUNIT_CASE(dm_test_register_outbox_irq_handlers_with_dmub),
4077 	/* amdgpu_dm_irq_handler */
4078 	KUNIT_CASE(dm_test_irq_handler_dispatches_work),
4079 	/* dm_handle_vmin_vmax_update */
4080 	KUNIT_CASE(dm_test_handle_vmin_vmax_update),
4081 	{}
4082 };
4083 
4084 static struct kunit_suite amdgpu_dm_irq_test_suite = {
4085 	.name = "amdgpu_dm_irq",
4086 	.test_cases = amdgpu_dm_irq_tests,
4087 };
4088 
4089 kunit_test_suite(amdgpu_dm_irq_test_suite);
4090 
4091 MODULE_AUTHOR("AMD");
4092 MODULE_DESCRIPTION("KUnit tests for amdgpu_dm_irq");
4093 MODULE_LICENSE("Dual MIT/GPL");
4094