Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
torvalds
GitHub Repository: torvalds/linux
Path: blob/master/drivers/base/test/test_async_driver_probe.c
26444 views
1
// SPDX-License-Identifier: GPL-2.0
2
/*
3
* Copyright (C) 2014 Google, Inc.
4
*/
5
6
#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
7
8
#include <linux/delay.h>
9
#include <linux/init.h>
10
#include <linux/hrtimer.h>
11
#include <linux/module.h>
12
#include <linux/platform_device.h>
13
#include <linux/time.h>
14
#include <linux/numa.h>
15
#include <linux/nodemask.h>
16
#include <linux/topology.h>
17
18
#define TEST_PROBE_DELAY (5 * 1000) /* 5 sec */
19
#define TEST_PROBE_THRESHOLD (TEST_PROBE_DELAY / 2)
20
21
static atomic_t warnings, errors, timeout, async_completed;
22
23
static int test_probe(struct platform_device *pdev)
24
{
25
struct device *dev = &pdev->dev;
26
27
/*
28
* Determine if we have hit the "timeout" limit for the test if we
29
* have then report it as an error, otherwise we wil sleep for the
30
* required amount of time and then report completion.
31
*/
32
if (atomic_read(&timeout)) {
33
dev_err(dev, "async probe took too long\n");
34
atomic_inc(&errors);
35
} else {
36
dev_dbg(&pdev->dev, "sleeping for %d msecs in probe\n",
37
TEST_PROBE_DELAY);
38
msleep(TEST_PROBE_DELAY);
39
dev_dbg(&pdev->dev, "done sleeping\n");
40
}
41
42
/*
43
* Report NUMA mismatch if device node is set and we are not
44
* performing an async init on that node.
45
*/
46
if (dev->driver->probe_type == PROBE_PREFER_ASYNCHRONOUS) {
47
if (IS_ENABLED(CONFIG_NUMA) &&
48
dev_to_node(dev) != numa_node_id()) {
49
dev_warn(dev, "NUMA node mismatch %d != %d\n",
50
dev_to_node(dev), numa_node_id());
51
atomic_inc(&warnings);
52
}
53
54
atomic_inc(&async_completed);
55
}
56
57
return 0;
58
}
59
60
static struct platform_driver async_driver = {
61
.driver = {
62
.name = "test_async_driver",
63
.probe_type = PROBE_PREFER_ASYNCHRONOUS,
64
},
65
.probe = test_probe,
66
};
67
68
static struct platform_driver sync_driver = {
69
.driver = {
70
.name = "test_sync_driver",
71
.probe_type = PROBE_FORCE_SYNCHRONOUS,
72
},
73
.probe = test_probe,
74
};
75
76
static struct platform_device *async_dev[NR_CPUS * 2];
77
static struct platform_device *sync_dev[2];
78
79
static struct platform_device *
80
test_platform_device_register_node(char *name, int id, int nid)
81
{
82
struct platform_device *pdev;
83
int ret;
84
85
pdev = platform_device_alloc(name, id);
86
if (!pdev)
87
return ERR_PTR(-ENOMEM);
88
89
if (nid != NUMA_NO_NODE)
90
set_dev_node(&pdev->dev, nid);
91
92
ret = platform_device_add(pdev);
93
if (ret) {
94
platform_device_put(pdev);
95
return ERR_PTR(ret);
96
}
97
98
return pdev;
99
100
}
101
102
static int __init test_async_probe_init(void)
103
{
104
struct platform_device **pdev = NULL;
105
int async_id = 0, sync_id = 0;
106
unsigned long long duration;
107
ktime_t calltime;
108
int err, nid, cpu;
109
110
pr_info("registering first set of asynchronous devices...\n");
111
112
for_each_online_cpu(cpu) {
113
nid = cpu_to_node(cpu);
114
pdev = &async_dev[async_id];
115
*pdev = test_platform_device_register_node("test_async_driver",
116
async_id,
117
nid);
118
if (IS_ERR(*pdev)) {
119
err = PTR_ERR(*pdev);
120
*pdev = NULL;
121
pr_err("failed to create async_dev: %d\n", err);
122
goto err_unregister_async_devs;
123
}
124
125
async_id++;
126
}
127
128
pr_info("registering asynchronous driver...\n");
129
calltime = ktime_get();
130
err = platform_driver_register(&async_driver);
131
if (err) {
132
pr_err("Failed to register async_driver: %d\n", err);
133
goto err_unregister_async_devs;
134
}
135
136
duration = (unsigned long long)ktime_ms_delta(ktime_get(), calltime);
137
pr_info("registration took %lld msecs\n", duration);
138
if (duration > TEST_PROBE_THRESHOLD) {
139
pr_err("test failed: probe took too long\n");
140
err = -ETIMEDOUT;
141
goto err_unregister_async_driver;
142
}
143
144
pr_info("registering second set of asynchronous devices...\n");
145
calltime = ktime_get();
146
for_each_online_cpu(cpu) {
147
nid = cpu_to_node(cpu);
148
pdev = &async_dev[async_id];
149
150
*pdev = test_platform_device_register_node("test_async_driver",
151
async_id,
152
nid);
153
if (IS_ERR(*pdev)) {
154
err = PTR_ERR(*pdev);
155
*pdev = NULL;
156
pr_err("failed to create async_dev: %d\n", err);
157
goto err_unregister_async_driver;
158
}
159
160
async_id++;
161
}
162
163
duration = (unsigned long long)ktime_ms_delta(ktime_get(), calltime);
164
dev_info(&(*pdev)->dev,
165
"registration took %lld msecs\n", duration);
166
if (duration > TEST_PROBE_THRESHOLD) {
167
dev_err(&(*pdev)->dev,
168
"test failed: probe took too long\n");
169
err = -ETIMEDOUT;
170
goto err_unregister_async_driver;
171
}
172
173
174
pr_info("registering first synchronous device...\n");
175
nid = cpu_to_node(cpu);
176
pdev = &sync_dev[sync_id];
177
178
*pdev = test_platform_device_register_node("test_sync_driver",
179
sync_id,
180
NUMA_NO_NODE);
181
if (IS_ERR(*pdev)) {
182
err = PTR_ERR(*pdev);
183
*pdev = NULL;
184
pr_err("failed to create sync_dev: %d\n", err);
185
goto err_unregister_async_driver;
186
}
187
188
sync_id++;
189
190
pr_info("registering synchronous driver...\n");
191
calltime = ktime_get();
192
err = platform_driver_register(&sync_driver);
193
if (err) {
194
pr_err("Failed to register async_driver: %d\n", err);
195
goto err_unregister_sync_devs;
196
}
197
198
duration = (unsigned long long)ktime_ms_delta(ktime_get(), calltime);
199
pr_info("registration took %lld msecs\n", duration);
200
if (duration < TEST_PROBE_THRESHOLD) {
201
dev_err(&(*pdev)->dev,
202
"test failed: probe was too quick\n");
203
err = -ETIMEDOUT;
204
goto err_unregister_sync_driver;
205
}
206
207
pr_info("registering second synchronous device...\n");
208
pdev = &sync_dev[sync_id];
209
calltime = ktime_get();
210
211
*pdev = test_platform_device_register_node("test_sync_driver",
212
sync_id,
213
NUMA_NO_NODE);
214
if (IS_ERR(*pdev)) {
215
err = PTR_ERR(*pdev);
216
*pdev = NULL;
217
pr_err("failed to create sync_dev: %d\n", err);
218
goto err_unregister_sync_driver;
219
}
220
221
sync_id++;
222
223
duration = (unsigned long long)ktime_ms_delta(ktime_get(), calltime);
224
dev_info(&(*pdev)->dev,
225
"registration took %lld msecs\n", duration);
226
if (duration < TEST_PROBE_THRESHOLD) {
227
dev_err(&(*pdev)->dev,
228
"test failed: probe was too quick\n");
229
err = -ETIMEDOUT;
230
goto err_unregister_sync_driver;
231
}
232
233
/*
234
* The async events should have completed while we were taking care
235
* of the synchronous events. We will now terminate any outstanding
236
* asynchronous probe calls remaining by forcing timeout and remove
237
* the driver before we return which should force the flush of the
238
* pending asynchronous probe calls.
239
*
240
* Otherwise if they completed without errors or warnings then
241
* report successful completion.
242
*/
243
if (atomic_read(&async_completed) != async_id) {
244
pr_err("async events still pending, forcing timeout\n");
245
atomic_inc(&timeout);
246
err = -ETIMEDOUT;
247
} else if (!atomic_read(&errors) && !atomic_read(&warnings)) {
248
pr_info("completed successfully\n");
249
return 0;
250
}
251
252
err_unregister_sync_driver:
253
platform_driver_unregister(&sync_driver);
254
err_unregister_sync_devs:
255
while (sync_id--)
256
platform_device_unregister(sync_dev[sync_id]);
257
err_unregister_async_driver:
258
platform_driver_unregister(&async_driver);
259
err_unregister_async_devs:
260
while (async_id--)
261
platform_device_unregister(async_dev[async_id]);
262
263
/*
264
* If err is already set then count that as an additional error for
265
* the test. Otherwise we will report an invalid argument error and
266
* not count that as we should have reached here as a result of
267
* errors or warnings being reported by the probe routine.
268
*/
269
if (err)
270
atomic_inc(&errors);
271
else
272
err = -EINVAL;
273
274
pr_err("Test failed with %d errors and %d warnings\n",
275
atomic_read(&errors), atomic_read(&warnings));
276
277
return err;
278
}
279
module_init(test_async_probe_init);
280
281
static void __exit test_async_probe_exit(void)
282
{
283
int id = 2;
284
285
platform_driver_unregister(&async_driver);
286
platform_driver_unregister(&sync_driver);
287
288
while (id--)
289
platform_device_unregister(sync_dev[id]);
290
291
id = NR_CPUS * 2;
292
while (id--)
293
platform_device_unregister(async_dev[id]);
294
}
295
module_exit(test_async_probe_exit);
296
297
MODULE_DESCRIPTION("Test module for asynchronous driver probing");
298
MODULE_AUTHOR("Dmitry Torokhov <[email protected]>");
299
MODULE_LICENSE("GPL");
300
301