summaryrefslogtreecommitdiff
path: root/drivers/gpu/drm/tests/drm_kunit_helpers.c
blob: 9bfd3cb9cde1a2165d7b766229e729b3c3ca4780 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
// SPDX-License-Identifier: GPL-2.0

#include <drm/drm_drv.h>
#include <drm/drm_kunit_helpers.h>
#include <drm/drm_managed.h>

#include <kunit/resource.h>

#include <linux/device.h>
#include <linux/platform_device.h>

#define KUNIT_DEVICE_NAME	"drm-kunit-mock-device"

struct kunit_dev {
	struct drm_device base;
};

static const struct drm_mode_config_funcs drm_mode_config_funcs = {
};

static int fake_probe(struct platform_device *pdev)
{
	return 0;
}

static int fake_remove(struct platform_device *pdev)
{
	return 0;
}

static struct platform_driver fake_platform_driver = {
	.probe	= fake_probe,
	.remove	= fake_remove,
	.driver = {
		.name	= KUNIT_DEVICE_NAME,
	},
};

/**
 * drm_kunit_helper_alloc_device - Allocate a mock device for a KUnit test
 * @test: The test context object
 *
 * This allocates a fake struct &device to create a mock for a KUnit
 * test. The device will also be bound to a fake driver. It will thus be
 * able to leverage the usual infrastructure and most notably the
 * device-managed resources just like a "real" device.
 *
 * Callers need to make sure drm_kunit_helper_free_device() on the
 * device when done.
 *
 * Returns:
 * A pointer to the new device, or an ERR_PTR() otherwise.
 */
struct device *drm_kunit_helper_alloc_device(struct kunit *test)
{
	struct platform_device *pdev;
	int ret;

	ret = platform_driver_register(&fake_platform_driver);
	KUNIT_ASSERT_EQ(test, ret, 0);

	pdev = platform_device_alloc(KUNIT_DEVICE_NAME, PLATFORM_DEVID_NONE);
	KUNIT_ASSERT_NOT_ERR_OR_NULL(test, pdev);

	ret = platform_device_add(pdev);
	KUNIT_ASSERT_EQ(test, ret, 0);

	return &pdev->dev;
}
EXPORT_SYMBOL_GPL(drm_kunit_helper_alloc_device);

/**
 * drm_kunit_helper_free_device - Frees a mock device
 * @test: The test context object
 * @dev: The device to free
 *
 * Frees a device allocated with drm_kunit_helper_alloc_device().
 */
void drm_kunit_helper_free_device(struct kunit *test, struct device *dev)
{
	struct platform_device *pdev = to_platform_device(dev);

	platform_device_unregister(pdev);
	platform_driver_unregister(&fake_platform_driver);
}
EXPORT_SYMBOL_GPL(drm_kunit_helper_free_device);

/**
 * drm_kunit_helper_alloc_drm_device - Allocates a mock DRM device for KUnit tests
 * @test: The test context object
 * @dev: The parent device object
 * @features: Mocked DRM device driver features
 *
 * This function creates a struct &drm_driver and will create a struct
 * &drm_device from @dev and that driver.
 *
 * @dev should be allocated using drm_kunit_helper_alloc_device().
 *
 * The driver is tied to the @test context and will get cleaned at the
 * end of the test. The drm_device is allocated through
 * devm_drm_dev_alloc() and will thus be freed through a device-managed
 * resource.
 *
 * Returns:
 * A pointer to the new drm_device, or an ERR_PTR() otherwise.
 */
struct drm_device *
drm_kunit_helper_alloc_drm_device(struct kunit *test, struct device *dev,
				  u32 features)
{
	struct kunit_dev *kdev;
	struct drm_device *drm;
	struct drm_driver *driver;
	int ret;

	driver = kunit_kzalloc(test, sizeof(*driver), GFP_KERNEL);
	if (!driver)
		return ERR_PTR(-ENOMEM);

	driver->driver_features = features;
	kdev = devm_drm_dev_alloc(dev, driver, struct kunit_dev, base);
	if (IS_ERR(kdev))
		return ERR_CAST(kdev);

	drm = &kdev->base;
	drm->mode_config.funcs = &drm_mode_config_funcs;

	ret = drmm_mode_config_init(drm);
	if (ret)
		return ERR_PTR(ret);

	return drm;
}
EXPORT_SYMBOL_GPL(drm_kunit_helper_alloc_drm_device);

MODULE_AUTHOR("Maxime Ripard <maxime@cerno.tech>");
MODULE_LICENSE("GPL");