137df9043SVimal Agrawal // SPDX-License-Identifier: GPL-2.0
237df9043SVimal Agrawal #include <kunit/test.h>
337df9043SVimal Agrawal #include <kunit/test-bug.h>
437df9043SVimal Agrawal #include <linux/module.h>
537df9043SVimal Agrawal #include <linux/miscdevice.h>
674d8361bSThadeu Lima de Souza Cascardo #include <linux/fs.h>
774d8361bSThadeu Lima de Souza Cascardo #include <linux/file.h>
874d8361bSThadeu Lima de Souza Cascardo #include <linux/init_syscalls.h>
937df9043SVimal Agrawal
1037df9043SVimal Agrawal /* static minor (LCD_MINOR) */
1137df9043SVimal Agrawal static struct miscdevice dev_static_minor = {
1237df9043SVimal Agrawal .minor = LCD_MINOR,
1337df9043SVimal Agrawal .name = "dev_static_minor",
1437df9043SVimal Agrawal };
1537df9043SVimal Agrawal
1637df9043SVimal Agrawal /* misc dynamic minor */
1737df9043SVimal Agrawal static struct miscdevice dev_misc_dynamic_minor = {
1837df9043SVimal Agrawal .minor = MISC_DYNAMIC_MINOR,
1937df9043SVimal Agrawal .name = "dev_misc_dynamic_minor",
2037df9043SVimal Agrawal };
2137df9043SVimal Agrawal
kunit_static_minor(struct kunit * test)2237df9043SVimal Agrawal static void kunit_static_minor(struct kunit *test)
2337df9043SVimal Agrawal {
2437df9043SVimal Agrawal int ret;
2537df9043SVimal Agrawal
2637df9043SVimal Agrawal ret = misc_register(&dev_static_minor);
2737df9043SVimal Agrawal KUNIT_EXPECT_EQ(test, 0, ret);
2837df9043SVimal Agrawal KUNIT_EXPECT_EQ(test, LCD_MINOR, dev_static_minor.minor);
2937df9043SVimal Agrawal misc_deregister(&dev_static_minor);
3037df9043SVimal Agrawal }
3137df9043SVimal Agrawal
kunit_misc_dynamic_minor(struct kunit * test)3237df9043SVimal Agrawal static void kunit_misc_dynamic_minor(struct kunit *test)
3337df9043SVimal Agrawal {
3437df9043SVimal Agrawal int ret;
3537df9043SVimal Agrawal
3637df9043SVimal Agrawal ret = misc_register(&dev_misc_dynamic_minor);
3737df9043SVimal Agrawal KUNIT_EXPECT_EQ(test, 0, ret);
3837df9043SVimal Agrawal misc_deregister(&dev_misc_dynamic_minor);
3937df9043SVimal Agrawal }
4037df9043SVimal Agrawal
4174d8361bSThadeu Lima de Souza Cascardo struct miscdev_test_case {
4274d8361bSThadeu Lima de Souza Cascardo const char *str;
4374d8361bSThadeu Lima de Souza Cascardo int minor;
4474d8361bSThadeu Lima de Souza Cascardo };
4574d8361bSThadeu Lima de Souza Cascardo
4674d8361bSThadeu Lima de Souza Cascardo static struct miscdev_test_case miscdev_test_ranges[] = {
4774d8361bSThadeu Lima de Souza Cascardo {
4874d8361bSThadeu Lima de Souza Cascardo .str = "lower static range, top",
4974d8361bSThadeu Lima de Souza Cascardo .minor = 15,
5074d8361bSThadeu Lima de Souza Cascardo },
5174d8361bSThadeu Lima de Souza Cascardo {
5274d8361bSThadeu Lima de Souza Cascardo .str = "upper static range, bottom",
5374d8361bSThadeu Lima de Souza Cascardo .minor = 130,
5474d8361bSThadeu Lima de Souza Cascardo },
5574d8361bSThadeu Lima de Souza Cascardo {
5674d8361bSThadeu Lima de Souza Cascardo .str = "lower static range, bottom",
5774d8361bSThadeu Lima de Souza Cascardo .minor = 0,
5874d8361bSThadeu Lima de Souza Cascardo },
5974d8361bSThadeu Lima de Souza Cascardo {
6074d8361bSThadeu Lima de Souza Cascardo .str = "upper static range, top",
6174d8361bSThadeu Lima de Souza Cascardo .minor = MISC_DYNAMIC_MINOR - 1,
6274d8361bSThadeu Lima de Souza Cascardo },
6374d8361bSThadeu Lima de Souza Cascardo };
6474d8361bSThadeu Lima de Souza Cascardo
6574d8361bSThadeu Lima de Souza Cascardo KUNIT_ARRAY_PARAM_DESC(miscdev, miscdev_test_ranges, str);
6674d8361bSThadeu Lima de Souza Cascardo
miscdev_find_minors(struct kunit_suite * suite)6774d8361bSThadeu Lima de Souza Cascardo static int miscdev_find_minors(struct kunit_suite *suite)
6874d8361bSThadeu Lima de Souza Cascardo {
6974d8361bSThadeu Lima de Souza Cascardo int ret;
7074d8361bSThadeu Lima de Souza Cascardo struct miscdevice miscstat = {
7174d8361bSThadeu Lima de Souza Cascardo .name = "miscstat",
7274d8361bSThadeu Lima de Souza Cascardo };
7374d8361bSThadeu Lima de Souza Cascardo int i;
7474d8361bSThadeu Lima de Souza Cascardo
7574d8361bSThadeu Lima de Souza Cascardo for (i = 15; i >= 0; i--) {
7674d8361bSThadeu Lima de Souza Cascardo miscstat.minor = i;
7774d8361bSThadeu Lima de Souza Cascardo ret = misc_register(&miscstat);
7874d8361bSThadeu Lima de Souza Cascardo if (ret == 0)
7974d8361bSThadeu Lima de Souza Cascardo break;
8074d8361bSThadeu Lima de Souza Cascardo }
8174d8361bSThadeu Lima de Souza Cascardo
8274d8361bSThadeu Lima de Souza Cascardo if (ret == 0) {
8374d8361bSThadeu Lima de Souza Cascardo kunit_info(suite, "found misc device minor %d available\n",
8474d8361bSThadeu Lima de Souza Cascardo miscstat.minor);
8574d8361bSThadeu Lima de Souza Cascardo miscdev_test_ranges[0].minor = miscstat.minor;
8674d8361bSThadeu Lima de Souza Cascardo misc_deregister(&miscstat);
8774d8361bSThadeu Lima de Souza Cascardo } else {
8874d8361bSThadeu Lima de Souza Cascardo return ret;
8974d8361bSThadeu Lima de Souza Cascardo }
9074d8361bSThadeu Lima de Souza Cascardo
9174d8361bSThadeu Lima de Souza Cascardo for (i = 128; i < MISC_DYNAMIC_MINOR; i++) {
9274d8361bSThadeu Lima de Souza Cascardo miscstat.minor = i;
9374d8361bSThadeu Lima de Souza Cascardo ret = misc_register(&miscstat);
9474d8361bSThadeu Lima de Souza Cascardo if (ret == 0)
9574d8361bSThadeu Lima de Souza Cascardo break;
9674d8361bSThadeu Lima de Souza Cascardo }
9774d8361bSThadeu Lima de Souza Cascardo
9874d8361bSThadeu Lima de Souza Cascardo if (ret == 0) {
9974d8361bSThadeu Lima de Souza Cascardo kunit_info(suite, "found misc device minor %d available\n",
10074d8361bSThadeu Lima de Souza Cascardo miscstat.minor);
10174d8361bSThadeu Lima de Souza Cascardo miscdev_test_ranges[1].minor = miscstat.minor;
10274d8361bSThadeu Lima de Souza Cascardo misc_deregister(&miscstat);
10374d8361bSThadeu Lima de Souza Cascardo } else {
10474d8361bSThadeu Lima de Souza Cascardo return ret;
10574d8361bSThadeu Lima de Souza Cascardo }
10674d8361bSThadeu Lima de Souza Cascardo
10774d8361bSThadeu Lima de Souza Cascardo for (i = 0; i < miscdev_test_ranges[0].minor; i++) {
10874d8361bSThadeu Lima de Souza Cascardo miscstat.minor = i;
10974d8361bSThadeu Lima de Souza Cascardo ret = misc_register(&miscstat);
11074d8361bSThadeu Lima de Souza Cascardo if (ret == 0)
11174d8361bSThadeu Lima de Souza Cascardo break;
11274d8361bSThadeu Lima de Souza Cascardo }
11374d8361bSThadeu Lima de Souza Cascardo
11474d8361bSThadeu Lima de Souza Cascardo if (ret == 0) {
11574d8361bSThadeu Lima de Souza Cascardo kunit_info(suite, "found misc device minor %d available\n",
11674d8361bSThadeu Lima de Souza Cascardo miscstat.minor);
11774d8361bSThadeu Lima de Souza Cascardo miscdev_test_ranges[2].minor = miscstat.minor;
11874d8361bSThadeu Lima de Souza Cascardo misc_deregister(&miscstat);
11974d8361bSThadeu Lima de Souza Cascardo } else {
12074d8361bSThadeu Lima de Souza Cascardo return ret;
12174d8361bSThadeu Lima de Souza Cascardo }
12274d8361bSThadeu Lima de Souza Cascardo
12374d8361bSThadeu Lima de Souza Cascardo for (i = MISC_DYNAMIC_MINOR - 1; i > miscdev_test_ranges[1].minor; i--) {
12474d8361bSThadeu Lima de Souza Cascardo miscstat.minor = i;
12574d8361bSThadeu Lima de Souza Cascardo ret = misc_register(&miscstat);
12674d8361bSThadeu Lima de Souza Cascardo if (ret == 0)
12774d8361bSThadeu Lima de Souza Cascardo break;
12874d8361bSThadeu Lima de Souza Cascardo }
12974d8361bSThadeu Lima de Souza Cascardo
13074d8361bSThadeu Lima de Souza Cascardo if (ret == 0) {
13174d8361bSThadeu Lima de Souza Cascardo kunit_info(suite, "found misc device minor %d available\n",
13274d8361bSThadeu Lima de Souza Cascardo miscstat.minor);
13374d8361bSThadeu Lima de Souza Cascardo miscdev_test_ranges[3].minor = miscstat.minor;
13474d8361bSThadeu Lima de Souza Cascardo misc_deregister(&miscstat);
13574d8361bSThadeu Lima de Souza Cascardo }
13674d8361bSThadeu Lima de Souza Cascardo
13774d8361bSThadeu Lima de Souza Cascardo return ret;
13874d8361bSThadeu Lima de Souza Cascardo }
13974d8361bSThadeu Lima de Souza Cascardo
is_valid_dynamic_minor(int minor)14074d8361bSThadeu Lima de Souza Cascardo static bool is_valid_dynamic_minor(int minor)
14174d8361bSThadeu Lima de Souza Cascardo {
14274d8361bSThadeu Lima de Souza Cascardo if (minor < 0)
14374d8361bSThadeu Lima de Souza Cascardo return false;
144f4e47affSZijun Hu return minor > MISC_DYNAMIC_MINOR;
14574d8361bSThadeu Lima de Souza Cascardo }
14674d8361bSThadeu Lima de Souza Cascardo
miscdev_test_open(struct inode * inode,struct file * file)14774d8361bSThadeu Lima de Souza Cascardo static int miscdev_test_open(struct inode *inode, struct file *file)
14874d8361bSThadeu Lima de Souza Cascardo {
14974d8361bSThadeu Lima de Souza Cascardo return 0;
15074d8361bSThadeu Lima de Souza Cascardo }
15174d8361bSThadeu Lima de Souza Cascardo
15274d8361bSThadeu Lima de Souza Cascardo static const struct file_operations miscdev_test_fops = {
15374d8361bSThadeu Lima de Souza Cascardo .open = miscdev_test_open,
15474d8361bSThadeu Lima de Souza Cascardo };
15574d8361bSThadeu Lima de Souza Cascardo
miscdev_test_can_open(struct kunit * test,struct miscdevice * misc)15674d8361bSThadeu Lima de Souza Cascardo static void __init miscdev_test_can_open(struct kunit *test, struct miscdevice *misc)
15774d8361bSThadeu Lima de Souza Cascardo {
15874d8361bSThadeu Lima de Souza Cascardo int ret;
15974d8361bSThadeu Lima de Souza Cascardo struct file *filp;
16074d8361bSThadeu Lima de Souza Cascardo char *devname;
16174d8361bSThadeu Lima de Souza Cascardo
16274d8361bSThadeu Lima de Souza Cascardo devname = kasprintf(GFP_KERNEL, "/dev/%s", misc->name);
16374d8361bSThadeu Lima de Souza Cascardo ret = init_mknod(devname, S_IFCHR | 0600,
16474d8361bSThadeu Lima de Souza Cascardo new_encode_dev(MKDEV(MISC_MAJOR, misc->minor)));
16574d8361bSThadeu Lima de Souza Cascardo if (ret != 0)
16674d8361bSThadeu Lima de Souza Cascardo KUNIT_FAIL(test, "failed to create node\n");
16774d8361bSThadeu Lima de Souza Cascardo
16874d8361bSThadeu Lima de Souza Cascardo filp = filp_open(devname, O_RDONLY, 0);
16974d8361bSThadeu Lima de Souza Cascardo if (IS_ERR_OR_NULL(filp))
17074d8361bSThadeu Lima de Souza Cascardo KUNIT_FAIL(test, "failed to open misc device: %ld\n", PTR_ERR(filp));
17174d8361bSThadeu Lima de Souza Cascardo else
17274d8361bSThadeu Lima de Souza Cascardo fput(filp);
17374d8361bSThadeu Lima de Souza Cascardo
17474d8361bSThadeu Lima de Souza Cascardo init_unlink(devname);
17574d8361bSThadeu Lima de Souza Cascardo kfree(devname);
17674d8361bSThadeu Lima de Souza Cascardo }
17774d8361bSThadeu Lima de Souza Cascardo
miscdev_test_static_basic(struct kunit * test)17874d8361bSThadeu Lima de Souza Cascardo static void __init miscdev_test_static_basic(struct kunit *test)
17974d8361bSThadeu Lima de Souza Cascardo {
18074d8361bSThadeu Lima de Souza Cascardo struct miscdevice misc_test = {
18174d8361bSThadeu Lima de Souza Cascardo .name = "misc_test",
18274d8361bSThadeu Lima de Souza Cascardo .fops = &miscdev_test_fops,
18374d8361bSThadeu Lima de Souza Cascardo };
18474d8361bSThadeu Lima de Souza Cascardo int ret;
18574d8361bSThadeu Lima de Souza Cascardo const struct miscdev_test_case *params = test->param_value;
18674d8361bSThadeu Lima de Souza Cascardo
18774d8361bSThadeu Lima de Souza Cascardo misc_test.minor = params->minor;
18874d8361bSThadeu Lima de Souza Cascardo
18974d8361bSThadeu Lima de Souza Cascardo ret = misc_register(&misc_test);
19074d8361bSThadeu Lima de Souza Cascardo KUNIT_EXPECT_EQ(test, ret, 0);
19174d8361bSThadeu Lima de Souza Cascardo KUNIT_EXPECT_EQ(test, misc_test.minor, params->minor);
19274d8361bSThadeu Lima de Souza Cascardo
19374d8361bSThadeu Lima de Souza Cascardo if (ret == 0) {
19474d8361bSThadeu Lima de Souza Cascardo miscdev_test_can_open(test, &misc_test);
19574d8361bSThadeu Lima de Souza Cascardo misc_deregister(&misc_test);
19674d8361bSThadeu Lima de Souza Cascardo }
19774d8361bSThadeu Lima de Souza Cascardo }
19874d8361bSThadeu Lima de Souza Cascardo
miscdev_test_dynamic_basic(struct kunit * test)19974d8361bSThadeu Lima de Souza Cascardo static void __init miscdev_test_dynamic_basic(struct kunit *test)
20074d8361bSThadeu Lima de Souza Cascardo {
20174d8361bSThadeu Lima de Souza Cascardo struct miscdevice misc_test = {
20274d8361bSThadeu Lima de Souza Cascardo .minor = MISC_DYNAMIC_MINOR,
20374d8361bSThadeu Lima de Souza Cascardo .name = "misc_test",
20474d8361bSThadeu Lima de Souza Cascardo .fops = &miscdev_test_fops,
20574d8361bSThadeu Lima de Souza Cascardo };
20674d8361bSThadeu Lima de Souza Cascardo int ret;
20774d8361bSThadeu Lima de Souza Cascardo
20874d8361bSThadeu Lima de Souza Cascardo ret = misc_register(&misc_test);
20974d8361bSThadeu Lima de Souza Cascardo KUNIT_EXPECT_EQ(test, ret, 0);
21074d8361bSThadeu Lima de Souza Cascardo KUNIT_EXPECT_TRUE(test, is_valid_dynamic_minor(misc_test.minor));
21174d8361bSThadeu Lima de Souza Cascardo
21274d8361bSThadeu Lima de Souza Cascardo if (ret == 0) {
21374d8361bSThadeu Lima de Souza Cascardo miscdev_test_can_open(test, &misc_test);
21474d8361bSThadeu Lima de Souza Cascardo misc_deregister(&misc_test);
21574d8361bSThadeu Lima de Souza Cascardo }
21674d8361bSThadeu Lima de Souza Cascardo }
21774d8361bSThadeu Lima de Souza Cascardo
miscdev_test_twice(struct kunit * test)21874d8361bSThadeu Lima de Souza Cascardo static void miscdev_test_twice(struct kunit *test)
21974d8361bSThadeu Lima de Souza Cascardo {
22074d8361bSThadeu Lima de Souza Cascardo struct miscdevice misc_test = {
22174d8361bSThadeu Lima de Souza Cascardo .name = "misc_test",
22274d8361bSThadeu Lima de Souza Cascardo .fops = &miscdev_test_fops,
22374d8361bSThadeu Lima de Souza Cascardo };
22474d8361bSThadeu Lima de Souza Cascardo int ret;
22574d8361bSThadeu Lima de Souza Cascardo const struct miscdev_test_case *params = test->param_value;
22674d8361bSThadeu Lima de Souza Cascardo
22774d8361bSThadeu Lima de Souza Cascardo misc_test.minor = params->minor;
22874d8361bSThadeu Lima de Souza Cascardo
22974d8361bSThadeu Lima de Souza Cascardo ret = misc_register(&misc_test);
23074d8361bSThadeu Lima de Souza Cascardo KUNIT_EXPECT_EQ(test, ret, 0);
23174d8361bSThadeu Lima de Souza Cascardo KUNIT_EXPECT_EQ(test, misc_test.minor, params->minor);
23274d8361bSThadeu Lima de Souza Cascardo if (ret == 0)
23374d8361bSThadeu Lima de Souza Cascardo misc_deregister(&misc_test);
23474d8361bSThadeu Lima de Souza Cascardo
23574d8361bSThadeu Lima de Souza Cascardo ret = misc_register(&misc_test);
23674d8361bSThadeu Lima de Souza Cascardo KUNIT_EXPECT_EQ(test, ret, 0);
23774d8361bSThadeu Lima de Souza Cascardo KUNIT_EXPECT_EQ(test, misc_test.minor, params->minor);
23874d8361bSThadeu Lima de Souza Cascardo if (ret == 0)
23974d8361bSThadeu Lima de Souza Cascardo misc_deregister(&misc_test);
24074d8361bSThadeu Lima de Souza Cascardo }
24174d8361bSThadeu Lima de Souza Cascardo
miscdev_test_duplicate_minor(struct kunit * test)24274d8361bSThadeu Lima de Souza Cascardo static void miscdev_test_duplicate_minor(struct kunit *test)
24374d8361bSThadeu Lima de Souza Cascardo {
24474d8361bSThadeu Lima de Souza Cascardo struct miscdevice misc1 = {
24574d8361bSThadeu Lima de Souza Cascardo .name = "misc1",
24674d8361bSThadeu Lima de Souza Cascardo .fops = &miscdev_test_fops,
24774d8361bSThadeu Lima de Souza Cascardo };
24874d8361bSThadeu Lima de Souza Cascardo struct miscdevice misc2 = {
24974d8361bSThadeu Lima de Souza Cascardo .name = "misc2",
25074d8361bSThadeu Lima de Souza Cascardo .fops = &miscdev_test_fops,
25174d8361bSThadeu Lima de Souza Cascardo };
25274d8361bSThadeu Lima de Souza Cascardo int ret;
25374d8361bSThadeu Lima de Souza Cascardo const struct miscdev_test_case *params = test->param_value;
25474d8361bSThadeu Lima de Souza Cascardo
25574d8361bSThadeu Lima de Souza Cascardo misc1.minor = params->minor;
25674d8361bSThadeu Lima de Souza Cascardo misc2.minor = params->minor;
25774d8361bSThadeu Lima de Souza Cascardo
25874d8361bSThadeu Lima de Souza Cascardo ret = misc_register(&misc1);
25974d8361bSThadeu Lima de Souza Cascardo KUNIT_EXPECT_EQ(test, ret, 0);
26074d8361bSThadeu Lima de Souza Cascardo KUNIT_EXPECT_EQ(test, misc1.minor, params->minor);
26174d8361bSThadeu Lima de Souza Cascardo
26274d8361bSThadeu Lima de Souza Cascardo ret = misc_register(&misc2);
26374d8361bSThadeu Lima de Souza Cascardo KUNIT_EXPECT_EQ(test, ret, -EBUSY);
26474d8361bSThadeu Lima de Souza Cascardo if (ret == 0)
26574d8361bSThadeu Lima de Souza Cascardo misc_deregister(&misc2);
26674d8361bSThadeu Lima de Souza Cascardo
26774d8361bSThadeu Lima de Souza Cascardo misc_deregister(&misc1);
26874d8361bSThadeu Lima de Souza Cascardo }
26974d8361bSThadeu Lima de Souza Cascardo
miscdev_test_duplicate_name(struct kunit * test)27074d8361bSThadeu Lima de Souza Cascardo static void miscdev_test_duplicate_name(struct kunit *test)
27174d8361bSThadeu Lima de Souza Cascardo {
27274d8361bSThadeu Lima de Souza Cascardo struct miscdevice misc1 = {
27374d8361bSThadeu Lima de Souza Cascardo .minor = MISC_DYNAMIC_MINOR,
27474d8361bSThadeu Lima de Souza Cascardo .name = "misc1",
27574d8361bSThadeu Lima de Souza Cascardo .fops = &miscdev_test_fops,
27674d8361bSThadeu Lima de Souza Cascardo };
27774d8361bSThadeu Lima de Souza Cascardo struct miscdevice misc2 = {
27874d8361bSThadeu Lima de Souza Cascardo .minor = MISC_DYNAMIC_MINOR,
27974d8361bSThadeu Lima de Souza Cascardo .name = "misc1",
28074d8361bSThadeu Lima de Souza Cascardo .fops = &miscdev_test_fops,
28174d8361bSThadeu Lima de Souza Cascardo };
28274d8361bSThadeu Lima de Souza Cascardo int ret;
28374d8361bSThadeu Lima de Souza Cascardo
28474d8361bSThadeu Lima de Souza Cascardo ret = misc_register(&misc1);
28574d8361bSThadeu Lima de Souza Cascardo KUNIT_EXPECT_EQ(test, ret, 0);
28674d8361bSThadeu Lima de Souza Cascardo KUNIT_EXPECT_TRUE(test, is_valid_dynamic_minor(misc1.minor));
28774d8361bSThadeu Lima de Souza Cascardo
28874d8361bSThadeu Lima de Souza Cascardo ret = misc_register(&misc2);
28974d8361bSThadeu Lima de Souza Cascardo KUNIT_EXPECT_EQ(test, ret, -EEXIST);
29074d8361bSThadeu Lima de Souza Cascardo if (ret == 0)
29174d8361bSThadeu Lima de Souza Cascardo misc_deregister(&misc2);
29274d8361bSThadeu Lima de Souza Cascardo
29374d8361bSThadeu Lima de Souza Cascardo misc_deregister(&misc1);
29474d8361bSThadeu Lima de Souza Cascardo }
29574d8361bSThadeu Lima de Souza Cascardo
29674d8361bSThadeu Lima de Souza Cascardo /*
29774d8361bSThadeu Lima de Souza Cascardo * Test that after a duplicate name failure, the reserved minor number is
29874d8361bSThadeu Lima de Souza Cascardo * freed to be allocated next.
29974d8361bSThadeu Lima de Souza Cascardo */
miscdev_test_duplicate_name_leak(struct kunit * test)30074d8361bSThadeu Lima de Souza Cascardo static void miscdev_test_duplicate_name_leak(struct kunit *test)
30174d8361bSThadeu Lima de Souza Cascardo {
30274d8361bSThadeu Lima de Souza Cascardo struct miscdevice misc1 = {
30374d8361bSThadeu Lima de Souza Cascardo .minor = MISC_DYNAMIC_MINOR,
30474d8361bSThadeu Lima de Souza Cascardo .name = "misc1",
30574d8361bSThadeu Lima de Souza Cascardo .fops = &miscdev_test_fops,
30674d8361bSThadeu Lima de Souza Cascardo };
30774d8361bSThadeu Lima de Souza Cascardo struct miscdevice misc2 = {
30874d8361bSThadeu Lima de Souza Cascardo .minor = MISC_DYNAMIC_MINOR,
30974d8361bSThadeu Lima de Souza Cascardo .name = "misc1",
31074d8361bSThadeu Lima de Souza Cascardo .fops = &miscdev_test_fops,
31174d8361bSThadeu Lima de Souza Cascardo };
31274d8361bSThadeu Lima de Souza Cascardo struct miscdevice misc3 = {
31374d8361bSThadeu Lima de Souza Cascardo .minor = MISC_DYNAMIC_MINOR,
31474d8361bSThadeu Lima de Souza Cascardo .name = "misc3",
31574d8361bSThadeu Lima de Souza Cascardo .fops = &miscdev_test_fops,
31674d8361bSThadeu Lima de Souza Cascardo };
31774d8361bSThadeu Lima de Souza Cascardo int ret;
31874d8361bSThadeu Lima de Souza Cascardo int dyn_minor;
31974d8361bSThadeu Lima de Souza Cascardo
32074d8361bSThadeu Lima de Souza Cascardo ret = misc_register(&misc1);
32174d8361bSThadeu Lima de Souza Cascardo KUNIT_EXPECT_EQ(test, ret, 0);
32274d8361bSThadeu Lima de Souza Cascardo KUNIT_EXPECT_TRUE(test, is_valid_dynamic_minor(misc1.minor));
32374d8361bSThadeu Lima de Souza Cascardo
32474d8361bSThadeu Lima de Souza Cascardo /*
32574d8361bSThadeu Lima de Souza Cascardo * Find out what is the next minor number available.
32674d8361bSThadeu Lima de Souza Cascardo */
32774d8361bSThadeu Lima de Souza Cascardo ret = misc_register(&misc3);
32874d8361bSThadeu Lima de Souza Cascardo KUNIT_EXPECT_EQ(test, ret, 0);
32974d8361bSThadeu Lima de Souza Cascardo KUNIT_EXPECT_TRUE(test, is_valid_dynamic_minor(misc3.minor));
33074d8361bSThadeu Lima de Souza Cascardo dyn_minor = misc3.minor;
33174d8361bSThadeu Lima de Souza Cascardo misc_deregister(&misc3);
33274d8361bSThadeu Lima de Souza Cascardo misc3.minor = MISC_DYNAMIC_MINOR;
33374d8361bSThadeu Lima de Souza Cascardo
33474d8361bSThadeu Lima de Souza Cascardo ret = misc_register(&misc2);
33574d8361bSThadeu Lima de Souza Cascardo KUNIT_EXPECT_EQ(test, ret, -EEXIST);
33674d8361bSThadeu Lima de Souza Cascardo if (ret == 0)
33774d8361bSThadeu Lima de Souza Cascardo misc_deregister(&misc2);
33874d8361bSThadeu Lima de Souza Cascardo
33974d8361bSThadeu Lima de Souza Cascardo /*
34074d8361bSThadeu Lima de Souza Cascardo * Now check that we can still get the same minor we found before.
34174d8361bSThadeu Lima de Souza Cascardo */
34274d8361bSThadeu Lima de Souza Cascardo ret = misc_register(&misc3);
34374d8361bSThadeu Lima de Souza Cascardo KUNIT_EXPECT_EQ(test, ret, 0);
34474d8361bSThadeu Lima de Souza Cascardo KUNIT_EXPECT_TRUE(test, is_valid_dynamic_minor(misc3.minor));
34574d8361bSThadeu Lima de Souza Cascardo KUNIT_EXPECT_EQ(test, misc3.minor, dyn_minor);
34674d8361bSThadeu Lima de Souza Cascardo misc_deregister(&misc3);
34774d8361bSThadeu Lima de Souza Cascardo
34874d8361bSThadeu Lima de Souza Cascardo misc_deregister(&misc1);
34974d8361bSThadeu Lima de Souza Cascardo }
35074d8361bSThadeu Lima de Souza Cascardo
35174d8361bSThadeu Lima de Souza Cascardo /*
35274d8361bSThadeu Lima de Souza Cascardo * Try to register a static minor with a duplicate name. That might not
35374d8361bSThadeu Lima de Souza Cascardo * deallocate the minor, preventing it from being used again.
35474d8361bSThadeu Lima de Souza Cascardo */
miscdev_test_duplicate_error(struct kunit * test)35574d8361bSThadeu Lima de Souza Cascardo static void miscdev_test_duplicate_error(struct kunit *test)
35674d8361bSThadeu Lima de Souza Cascardo {
35774d8361bSThadeu Lima de Souza Cascardo struct miscdevice miscdyn = {
35874d8361bSThadeu Lima de Souza Cascardo .minor = MISC_DYNAMIC_MINOR,
35974d8361bSThadeu Lima de Souza Cascardo .name = "name1",
36074d8361bSThadeu Lima de Souza Cascardo .fops = &miscdev_test_fops,
36174d8361bSThadeu Lima de Souza Cascardo };
36274d8361bSThadeu Lima de Souza Cascardo struct miscdevice miscstat = {
36374d8361bSThadeu Lima de Souza Cascardo .name = "name1",
36474d8361bSThadeu Lima de Souza Cascardo .fops = &miscdev_test_fops,
36574d8361bSThadeu Lima de Souza Cascardo };
36674d8361bSThadeu Lima de Souza Cascardo struct miscdevice miscnew = {
36774d8361bSThadeu Lima de Souza Cascardo .name = "name2",
36874d8361bSThadeu Lima de Souza Cascardo .fops = &miscdev_test_fops,
36974d8361bSThadeu Lima de Souza Cascardo };
37074d8361bSThadeu Lima de Souza Cascardo int ret;
37174d8361bSThadeu Lima de Souza Cascardo const struct miscdev_test_case *params = test->param_value;
37274d8361bSThadeu Lima de Souza Cascardo
37374d8361bSThadeu Lima de Souza Cascardo miscstat.minor = params->minor;
37474d8361bSThadeu Lima de Souza Cascardo miscnew.minor = params->minor;
37574d8361bSThadeu Lima de Souza Cascardo
37674d8361bSThadeu Lima de Souza Cascardo ret = misc_register(&miscdyn);
37774d8361bSThadeu Lima de Souza Cascardo KUNIT_EXPECT_EQ(test, ret, 0);
37874d8361bSThadeu Lima de Souza Cascardo KUNIT_EXPECT_TRUE(test, is_valid_dynamic_minor(miscdyn.minor));
37974d8361bSThadeu Lima de Souza Cascardo
38074d8361bSThadeu Lima de Souza Cascardo ret = misc_register(&miscstat);
38174d8361bSThadeu Lima de Souza Cascardo KUNIT_EXPECT_EQ(test, ret, -EEXIST);
38274d8361bSThadeu Lima de Souza Cascardo if (ret == 0)
38374d8361bSThadeu Lima de Souza Cascardo misc_deregister(&miscstat);
38474d8361bSThadeu Lima de Souza Cascardo
38574d8361bSThadeu Lima de Souza Cascardo ret = misc_register(&miscnew);
38674d8361bSThadeu Lima de Souza Cascardo KUNIT_EXPECT_EQ(test, ret, 0);
38774d8361bSThadeu Lima de Souza Cascardo KUNIT_EXPECT_EQ(test, miscnew.minor, params->minor);
38874d8361bSThadeu Lima de Souza Cascardo if (ret == 0)
38974d8361bSThadeu Lima de Souza Cascardo misc_deregister(&miscnew);
39074d8361bSThadeu Lima de Souza Cascardo
39174d8361bSThadeu Lima de Souza Cascardo misc_deregister(&miscdyn);
39274d8361bSThadeu Lima de Souza Cascardo }
39374d8361bSThadeu Lima de Souza Cascardo
miscdev_test_dynamic_only_range(struct kunit * test)39474d8361bSThadeu Lima de Souza Cascardo static void __init miscdev_test_dynamic_only_range(struct kunit *test)
39574d8361bSThadeu Lima de Souza Cascardo {
39674d8361bSThadeu Lima de Souza Cascardo int ret;
39774d8361bSThadeu Lima de Souza Cascardo struct miscdevice *miscdev;
39874d8361bSThadeu Lima de Souza Cascardo const int dynamic_minors = 256;
39974d8361bSThadeu Lima de Souza Cascardo int i;
40074d8361bSThadeu Lima de Souza Cascardo
40174d8361bSThadeu Lima de Souza Cascardo miscdev = kunit_kmalloc_array(test, dynamic_minors,
40274d8361bSThadeu Lima de Souza Cascardo sizeof(struct miscdevice),
40374d8361bSThadeu Lima de Souza Cascardo GFP_KERNEL | __GFP_ZERO);
40474d8361bSThadeu Lima de Souza Cascardo
40574d8361bSThadeu Lima de Souza Cascardo for (i = 0; i < dynamic_minors; i++) {
40674d8361bSThadeu Lima de Souza Cascardo miscdev[i].minor = MISC_DYNAMIC_MINOR;
40774d8361bSThadeu Lima de Souza Cascardo miscdev[i].name = kasprintf(GFP_KERNEL, "misc_test%d", i);
40874d8361bSThadeu Lima de Souza Cascardo miscdev[i].fops = &miscdev_test_fops;
40974d8361bSThadeu Lima de Souza Cascardo ret = misc_register(&miscdev[i]);
41074d8361bSThadeu Lima de Souza Cascardo if (ret != 0)
41174d8361bSThadeu Lima de Souza Cascardo break;
41274d8361bSThadeu Lima de Souza Cascardo /*
41374d8361bSThadeu Lima de Souza Cascardo * This is the bug we are looking for!
41474d8361bSThadeu Lima de Souza Cascardo * We asked for a dynamic minor and got a minor in the static range space.
41574d8361bSThadeu Lima de Souza Cascardo */
41674d8361bSThadeu Lima de Souza Cascardo if (miscdev[i].minor >= 0 && miscdev[i].minor <= 15) {
41774d8361bSThadeu Lima de Souza Cascardo KUNIT_FAIL(test, "misc_register allocated minor %d\n", miscdev[i].minor);
41874d8361bSThadeu Lima de Souza Cascardo i++;
41974d8361bSThadeu Lima de Souza Cascardo break;
42074d8361bSThadeu Lima de Souza Cascardo }
42174d8361bSThadeu Lima de Souza Cascardo KUNIT_EXPECT_TRUE(test, is_valid_dynamic_minor(miscdev[i].minor));
42274d8361bSThadeu Lima de Souza Cascardo }
42374d8361bSThadeu Lima de Souza Cascardo
42474d8361bSThadeu Lima de Souza Cascardo for (i--; i >= 0; i--) {
42574d8361bSThadeu Lima de Souza Cascardo miscdev_test_can_open(test, &miscdev[i]);
42674d8361bSThadeu Lima de Souza Cascardo misc_deregister(&miscdev[i]);
42774d8361bSThadeu Lima de Souza Cascardo kfree_const(miscdev[i].name);
42874d8361bSThadeu Lima de Souza Cascardo }
42974d8361bSThadeu Lima de Souza Cascardo
43074d8361bSThadeu Lima de Souza Cascardo KUNIT_EXPECT_EQ(test, ret, 0);
43174d8361bSThadeu Lima de Souza Cascardo }
43274d8361bSThadeu Lima de Souza Cascardo
miscdev_test_collision(struct kunit * test)43374d8361bSThadeu Lima de Souza Cascardo static void __init miscdev_test_collision(struct kunit *test)
43474d8361bSThadeu Lima de Souza Cascardo {
43574d8361bSThadeu Lima de Souza Cascardo int ret;
43674d8361bSThadeu Lima de Souza Cascardo struct miscdevice *miscdev;
43774d8361bSThadeu Lima de Souza Cascardo struct miscdevice miscstat = {
43874d8361bSThadeu Lima de Souza Cascardo .name = "miscstat",
43974d8361bSThadeu Lima de Souza Cascardo .fops = &miscdev_test_fops,
44074d8361bSThadeu Lima de Souza Cascardo };
44174d8361bSThadeu Lima de Souza Cascardo const int dynamic_minors = 256;
44274d8361bSThadeu Lima de Souza Cascardo int i;
44374d8361bSThadeu Lima de Souza Cascardo
44474d8361bSThadeu Lima de Souza Cascardo miscdev = kunit_kmalloc_array(test, dynamic_minors,
44574d8361bSThadeu Lima de Souza Cascardo sizeof(struct miscdevice),
44674d8361bSThadeu Lima de Souza Cascardo GFP_KERNEL | __GFP_ZERO);
44774d8361bSThadeu Lima de Souza Cascardo
44874d8361bSThadeu Lima de Souza Cascardo miscstat.minor = miscdev_test_ranges[0].minor;
44974d8361bSThadeu Lima de Souza Cascardo ret = misc_register(&miscstat);
45074d8361bSThadeu Lima de Souza Cascardo KUNIT_ASSERT_EQ(test, ret, 0);
45174d8361bSThadeu Lima de Souza Cascardo KUNIT_EXPECT_EQ(test, miscstat.minor, miscdev_test_ranges[0].minor);
45274d8361bSThadeu Lima de Souza Cascardo
45374d8361bSThadeu Lima de Souza Cascardo for (i = 0; i < dynamic_minors; i++) {
45474d8361bSThadeu Lima de Souza Cascardo miscdev[i].minor = MISC_DYNAMIC_MINOR;
45574d8361bSThadeu Lima de Souza Cascardo miscdev[i].name = kasprintf(GFP_KERNEL, "misc_test%d", i);
45674d8361bSThadeu Lima de Souza Cascardo miscdev[i].fops = &miscdev_test_fops;
45774d8361bSThadeu Lima de Souza Cascardo ret = misc_register(&miscdev[i]);
45874d8361bSThadeu Lima de Souza Cascardo if (ret != 0)
45974d8361bSThadeu Lima de Souza Cascardo break;
46074d8361bSThadeu Lima de Souza Cascardo KUNIT_EXPECT_TRUE(test, is_valid_dynamic_minor(miscdev[i].minor));
46174d8361bSThadeu Lima de Souza Cascardo }
46274d8361bSThadeu Lima de Souza Cascardo
46374d8361bSThadeu Lima de Souza Cascardo for (i--; i >= 0; i--) {
46474d8361bSThadeu Lima de Souza Cascardo miscdev_test_can_open(test, &miscdev[i]);
46574d8361bSThadeu Lima de Souza Cascardo misc_deregister(&miscdev[i]);
46674d8361bSThadeu Lima de Souza Cascardo kfree_const(miscdev[i].name);
46774d8361bSThadeu Lima de Souza Cascardo }
46874d8361bSThadeu Lima de Souza Cascardo
46974d8361bSThadeu Lima de Souza Cascardo misc_deregister(&miscstat);
47074d8361bSThadeu Lima de Souza Cascardo
47174d8361bSThadeu Lima de Souza Cascardo KUNIT_EXPECT_EQ(test, ret, 0);
47274d8361bSThadeu Lima de Souza Cascardo }
47374d8361bSThadeu Lima de Souza Cascardo
miscdev_test_collision_reverse(struct kunit * test)47474d8361bSThadeu Lima de Souza Cascardo static void __init miscdev_test_collision_reverse(struct kunit *test)
47574d8361bSThadeu Lima de Souza Cascardo {
47674d8361bSThadeu Lima de Souza Cascardo int ret;
47774d8361bSThadeu Lima de Souza Cascardo struct miscdevice *miscdev;
47874d8361bSThadeu Lima de Souza Cascardo struct miscdevice miscstat = {
47974d8361bSThadeu Lima de Souza Cascardo .name = "miscstat",
48074d8361bSThadeu Lima de Souza Cascardo .fops = &miscdev_test_fops,
48174d8361bSThadeu Lima de Souza Cascardo };
48274d8361bSThadeu Lima de Souza Cascardo const int dynamic_minors = 256;
48374d8361bSThadeu Lima de Souza Cascardo int i;
48474d8361bSThadeu Lima de Souza Cascardo
48574d8361bSThadeu Lima de Souza Cascardo miscdev = kunit_kmalloc_array(test, dynamic_minors,
48674d8361bSThadeu Lima de Souza Cascardo sizeof(struct miscdevice),
48774d8361bSThadeu Lima de Souza Cascardo GFP_KERNEL | __GFP_ZERO);
48874d8361bSThadeu Lima de Souza Cascardo
48974d8361bSThadeu Lima de Souza Cascardo for (i = 0; i < dynamic_minors; i++) {
49074d8361bSThadeu Lima de Souza Cascardo miscdev[i].minor = MISC_DYNAMIC_MINOR;
49174d8361bSThadeu Lima de Souza Cascardo miscdev[i].name = kasprintf(GFP_KERNEL, "misc_test%d", i);
49274d8361bSThadeu Lima de Souza Cascardo miscdev[i].fops = &miscdev_test_fops;
49374d8361bSThadeu Lima de Souza Cascardo ret = misc_register(&miscdev[i]);
49474d8361bSThadeu Lima de Souza Cascardo if (ret != 0)
49574d8361bSThadeu Lima de Souza Cascardo break;
49674d8361bSThadeu Lima de Souza Cascardo KUNIT_EXPECT_TRUE(test, is_valid_dynamic_minor(miscdev[i].minor));
49774d8361bSThadeu Lima de Souza Cascardo }
49874d8361bSThadeu Lima de Souza Cascardo
49974d8361bSThadeu Lima de Souza Cascardo KUNIT_EXPECT_EQ(test, ret, 0);
50074d8361bSThadeu Lima de Souza Cascardo
50174d8361bSThadeu Lima de Souza Cascardo miscstat.minor = miscdev_test_ranges[0].minor;
50274d8361bSThadeu Lima de Souza Cascardo ret = misc_register(&miscstat);
50374d8361bSThadeu Lima de Souza Cascardo KUNIT_EXPECT_EQ(test, ret, 0);
50474d8361bSThadeu Lima de Souza Cascardo KUNIT_EXPECT_EQ(test, miscstat.minor, miscdev_test_ranges[0].minor);
50574d8361bSThadeu Lima de Souza Cascardo if (ret == 0)
50674d8361bSThadeu Lima de Souza Cascardo misc_deregister(&miscstat);
50774d8361bSThadeu Lima de Souza Cascardo
50874d8361bSThadeu Lima de Souza Cascardo for (i--; i >= 0; i--) {
50974d8361bSThadeu Lima de Souza Cascardo miscdev_test_can_open(test, &miscdev[i]);
51074d8361bSThadeu Lima de Souza Cascardo misc_deregister(&miscdev[i]);
51174d8361bSThadeu Lima de Souza Cascardo kfree_const(miscdev[i].name);
51274d8361bSThadeu Lima de Souza Cascardo }
51374d8361bSThadeu Lima de Souza Cascardo }
51474d8361bSThadeu Lima de Souza Cascardo
miscdev_test_conflict(struct kunit * test)51574d8361bSThadeu Lima de Souza Cascardo static void __init miscdev_test_conflict(struct kunit *test)
51674d8361bSThadeu Lima de Souza Cascardo {
51774d8361bSThadeu Lima de Souza Cascardo int ret;
51874d8361bSThadeu Lima de Souza Cascardo struct miscdevice miscdyn = {
51974d8361bSThadeu Lima de Souza Cascardo .name = "miscdyn",
52074d8361bSThadeu Lima de Souza Cascardo .minor = MISC_DYNAMIC_MINOR,
52174d8361bSThadeu Lima de Souza Cascardo .fops = &miscdev_test_fops,
52274d8361bSThadeu Lima de Souza Cascardo };
52374d8361bSThadeu Lima de Souza Cascardo struct miscdevice miscstat = {
52474d8361bSThadeu Lima de Souza Cascardo .name = "miscstat",
52574d8361bSThadeu Lima de Souza Cascardo .fops = &miscdev_test_fops,
52674d8361bSThadeu Lima de Souza Cascardo };
52774d8361bSThadeu Lima de Souza Cascardo
52874d8361bSThadeu Lima de Souza Cascardo ret = misc_register(&miscdyn);
52974d8361bSThadeu Lima de Souza Cascardo KUNIT_ASSERT_EQ(test, ret, 0);
53074d8361bSThadeu Lima de Souza Cascardo KUNIT_EXPECT_TRUE(test, is_valid_dynamic_minor(miscdyn.minor));
53174d8361bSThadeu Lima de Souza Cascardo
53274d8361bSThadeu Lima de Souza Cascardo /*
53374d8361bSThadeu Lima de Souza Cascardo * Try to register a static minor with the same minor as the
53474d8361bSThadeu Lima de Souza Cascardo * dynamic one.
53574d8361bSThadeu Lima de Souza Cascardo */
53674d8361bSThadeu Lima de Souza Cascardo miscstat.minor = miscdyn.minor;
53774d8361bSThadeu Lima de Souza Cascardo ret = misc_register(&miscstat);
538f4e47affSZijun Hu KUNIT_EXPECT_EQ(test, ret, -EINVAL);
53974d8361bSThadeu Lima de Souza Cascardo if (ret == 0)
54074d8361bSThadeu Lima de Souza Cascardo misc_deregister(&miscstat);
54174d8361bSThadeu Lima de Souza Cascardo
54274d8361bSThadeu Lima de Souza Cascardo miscdev_test_can_open(test, &miscdyn);
54374d8361bSThadeu Lima de Souza Cascardo
54474d8361bSThadeu Lima de Souza Cascardo misc_deregister(&miscdyn);
54574d8361bSThadeu Lima de Souza Cascardo }
54674d8361bSThadeu Lima de Souza Cascardo
miscdev_test_conflict_reverse(struct kunit * test)54774d8361bSThadeu Lima de Souza Cascardo static void __init miscdev_test_conflict_reverse(struct kunit *test)
54874d8361bSThadeu Lima de Souza Cascardo {
54974d8361bSThadeu Lima de Souza Cascardo int ret;
55074d8361bSThadeu Lima de Souza Cascardo struct miscdevice miscdyn = {
55174d8361bSThadeu Lima de Souza Cascardo .name = "miscdyn",
55274d8361bSThadeu Lima de Souza Cascardo .minor = MISC_DYNAMIC_MINOR,
55374d8361bSThadeu Lima de Souza Cascardo .fops = &miscdev_test_fops,
55474d8361bSThadeu Lima de Souza Cascardo };
55574d8361bSThadeu Lima de Souza Cascardo struct miscdevice miscstat = {
55674d8361bSThadeu Lima de Souza Cascardo .name = "miscstat",
55774d8361bSThadeu Lima de Souza Cascardo .fops = &miscdev_test_fops,
55874d8361bSThadeu Lima de Souza Cascardo };
55974d8361bSThadeu Lima de Souza Cascardo
56074d8361bSThadeu Lima de Souza Cascardo /*
56174d8361bSThadeu Lima de Souza Cascardo * Find the first available dynamic minor to use it as a static
56274d8361bSThadeu Lima de Souza Cascardo * minor later on.
56374d8361bSThadeu Lima de Souza Cascardo */
56474d8361bSThadeu Lima de Souza Cascardo ret = misc_register(&miscdyn);
56574d8361bSThadeu Lima de Souza Cascardo KUNIT_ASSERT_EQ(test, ret, 0);
56674d8361bSThadeu Lima de Souza Cascardo KUNIT_EXPECT_TRUE(test, is_valid_dynamic_minor(miscdyn.minor));
56774d8361bSThadeu Lima de Souza Cascardo miscstat.minor = miscdyn.minor;
56874d8361bSThadeu Lima de Souza Cascardo misc_deregister(&miscdyn);
56974d8361bSThadeu Lima de Souza Cascardo
57074d8361bSThadeu Lima de Souza Cascardo ret = misc_register(&miscstat);
571f4e47affSZijun Hu KUNIT_EXPECT_EQ(test, ret, -EINVAL);
572f4e47affSZijun Hu if (ret == 0)
573f4e47affSZijun Hu misc_deregister(&miscstat);
57474d8361bSThadeu Lima de Souza Cascardo
57574d8361bSThadeu Lima de Souza Cascardo /*
57674d8361bSThadeu Lima de Souza Cascardo * Try to register a dynamic minor after registering a static minor
57774d8361bSThadeu Lima de Souza Cascardo * within the dynamic range. It should work but get a different
57874d8361bSThadeu Lima de Souza Cascardo * minor.
57974d8361bSThadeu Lima de Souza Cascardo */
58074d8361bSThadeu Lima de Souza Cascardo miscdyn.minor = MISC_DYNAMIC_MINOR;
58174d8361bSThadeu Lima de Souza Cascardo ret = misc_register(&miscdyn);
58274d8361bSThadeu Lima de Souza Cascardo KUNIT_EXPECT_EQ(test, ret, 0);
583f4e47affSZijun Hu KUNIT_EXPECT_EQ(test, miscdyn.minor, miscstat.minor);
58474d8361bSThadeu Lima de Souza Cascardo KUNIT_EXPECT_TRUE(test, is_valid_dynamic_minor(miscdyn.minor));
58574d8361bSThadeu Lima de Souza Cascardo if (ret == 0)
58674d8361bSThadeu Lima de Souza Cascardo misc_deregister(&miscdyn);
587f4e47affSZijun Hu }
58874d8361bSThadeu Lima de Souza Cascardo
589f4e47affSZijun Hu /* Take minor(> MISC_DYNAMIC_MINOR) as invalid when register miscdevice */
miscdev_test_invalid_input(struct kunit * test)590f4e47affSZijun Hu static void miscdev_test_invalid_input(struct kunit *test)
591f4e47affSZijun Hu {
592f4e47affSZijun Hu struct miscdevice misc_test = {
593f4e47affSZijun Hu .minor = MISC_DYNAMIC_MINOR + 1,
594f4e47affSZijun Hu .name = "misc_test",
595f4e47affSZijun Hu .fops = &miscdev_test_fops,
596f4e47affSZijun Hu };
597f4e47affSZijun Hu int ret;
59874d8361bSThadeu Lima de Souza Cascardo
599f4e47affSZijun Hu ret = misc_register(&misc_test);
600f4e47affSZijun Hu KUNIT_EXPECT_EQ(test, ret, -EINVAL);
601f4e47affSZijun Hu if (ret == 0)
602f4e47affSZijun Hu misc_deregister(&misc_test);
60374d8361bSThadeu Lima de Souza Cascardo }
60474d8361bSThadeu Lima de Souza Cascardo
605*2334668aSZijun Hu /*
606*2334668aSZijun Hu * Verify if @miscdyn_a can still be registered successfully without
607*2334668aSZijun Hu * reinitialization even if its minor ever owned was requested by
608*2334668aSZijun Hu * another miscdevice such as @miscdyn_b.
609*2334668aSZijun Hu */
miscdev_test_dynamic_reentry(struct kunit * test)610*2334668aSZijun Hu static void miscdev_test_dynamic_reentry(struct kunit *test)
611*2334668aSZijun Hu {
612*2334668aSZijun Hu struct miscdevice miscdyn_a = {
613*2334668aSZijun Hu .name = "miscdyn_a",
614*2334668aSZijun Hu .minor = MISC_DYNAMIC_MINOR,
615*2334668aSZijun Hu .fops = &miscdev_test_fops,
616*2334668aSZijun Hu };
617*2334668aSZijun Hu struct miscdevice miscdyn_b = {
618*2334668aSZijun Hu .name = "miscdyn_b",
619*2334668aSZijun Hu .minor = MISC_DYNAMIC_MINOR,
620*2334668aSZijun Hu .fops = &miscdev_test_fops,
621*2334668aSZijun Hu };
622*2334668aSZijun Hu int ret, minor_a;
623*2334668aSZijun Hu
624*2334668aSZijun Hu ret = misc_register(&miscdyn_a);
625*2334668aSZijun Hu KUNIT_ASSERT_EQ(test, ret, 0);
626*2334668aSZijun Hu KUNIT_EXPECT_TRUE(test, is_valid_dynamic_minor(miscdyn_a.minor));
627*2334668aSZijun Hu minor_a = miscdyn_a.minor;
628*2334668aSZijun Hu if (ret != 0)
629*2334668aSZijun Hu return;
630*2334668aSZijun Hu misc_deregister(&miscdyn_a);
631*2334668aSZijun Hu
632*2334668aSZijun Hu ret = misc_register(&miscdyn_b);
633*2334668aSZijun Hu KUNIT_ASSERT_EQ(test, ret, 0);
634*2334668aSZijun Hu KUNIT_EXPECT_EQ(test, miscdyn_b.minor, minor_a);
635*2334668aSZijun Hu if (ret != 0)
636*2334668aSZijun Hu return;
637*2334668aSZijun Hu
638*2334668aSZijun Hu ret = misc_register(&miscdyn_a);
639*2334668aSZijun Hu KUNIT_ASSERT_EQ(test, ret, 0);
640*2334668aSZijun Hu KUNIT_EXPECT_TRUE(test, is_valid_dynamic_minor(miscdyn_a.minor));
641*2334668aSZijun Hu KUNIT_EXPECT_NE(test, miscdyn_a.minor, miscdyn_b.minor);
642*2334668aSZijun Hu if (ret == 0)
643*2334668aSZijun Hu misc_deregister(&miscdyn_a);
644*2334668aSZijun Hu
645*2334668aSZijun Hu misc_deregister(&miscdyn_b);
646*2334668aSZijun Hu }
647*2334668aSZijun Hu
64837df9043SVimal Agrawal static struct kunit_case test_cases[] = {
64937df9043SVimal Agrawal KUNIT_CASE(kunit_static_minor),
65037df9043SVimal Agrawal KUNIT_CASE(kunit_misc_dynamic_minor),
651f4e47affSZijun Hu KUNIT_CASE(miscdev_test_invalid_input),
65274d8361bSThadeu Lima de Souza Cascardo KUNIT_CASE_PARAM(miscdev_test_twice, miscdev_gen_params),
65374d8361bSThadeu Lima de Souza Cascardo KUNIT_CASE_PARAM(miscdev_test_duplicate_minor, miscdev_gen_params),
65474d8361bSThadeu Lima de Souza Cascardo KUNIT_CASE(miscdev_test_duplicate_name),
65574d8361bSThadeu Lima de Souza Cascardo KUNIT_CASE(miscdev_test_duplicate_name_leak),
65674d8361bSThadeu Lima de Souza Cascardo KUNIT_CASE_PARAM(miscdev_test_duplicate_error, miscdev_gen_params),
657*2334668aSZijun Hu KUNIT_CASE(miscdev_test_dynamic_reentry),
65837df9043SVimal Agrawal {}
65937df9043SVimal Agrawal };
66037df9043SVimal Agrawal
66137df9043SVimal Agrawal static struct kunit_suite test_suite = {
66274d8361bSThadeu Lima de Souza Cascardo .name = "miscdev",
66374d8361bSThadeu Lima de Souza Cascardo .suite_init = miscdev_find_minors,
66437df9043SVimal Agrawal .test_cases = test_cases,
66537df9043SVimal Agrawal };
66637df9043SVimal Agrawal kunit_test_suite(test_suite);
66737df9043SVimal Agrawal
66874d8361bSThadeu Lima de Souza Cascardo static struct kunit_case __refdata test_init_cases[] = {
66974d8361bSThadeu Lima de Souza Cascardo KUNIT_CASE_PARAM(miscdev_test_static_basic, miscdev_gen_params),
67074d8361bSThadeu Lima de Souza Cascardo KUNIT_CASE(miscdev_test_dynamic_basic),
67174d8361bSThadeu Lima de Souza Cascardo KUNIT_CASE(miscdev_test_dynamic_only_range),
67274d8361bSThadeu Lima de Souza Cascardo KUNIT_CASE(miscdev_test_collision),
67374d8361bSThadeu Lima de Souza Cascardo KUNIT_CASE(miscdev_test_collision_reverse),
67474d8361bSThadeu Lima de Souza Cascardo KUNIT_CASE(miscdev_test_conflict),
67574d8361bSThadeu Lima de Souza Cascardo KUNIT_CASE(miscdev_test_conflict_reverse),
67674d8361bSThadeu Lima de Souza Cascardo {}
67774d8361bSThadeu Lima de Souza Cascardo };
67874d8361bSThadeu Lima de Souza Cascardo
67974d8361bSThadeu Lima de Souza Cascardo static struct kunit_suite test_init_suite = {
68074d8361bSThadeu Lima de Souza Cascardo .name = "miscdev_init",
68174d8361bSThadeu Lima de Souza Cascardo .suite_init = miscdev_find_minors,
68274d8361bSThadeu Lima de Souza Cascardo .test_cases = test_init_cases,
68374d8361bSThadeu Lima de Souza Cascardo };
68474d8361bSThadeu Lima de Souza Cascardo kunit_test_init_section_suite(test_init_suite);
68574d8361bSThadeu Lima de Souza Cascardo
68637df9043SVimal Agrawal MODULE_LICENSE("GPL");
68737df9043SVimal Agrawal MODULE_AUTHOR("Vimal Agrawal");
68874d8361bSThadeu Lima de Souza Cascardo MODULE_AUTHOR("Thadeu Lima de Souza Cascardo <cascardo@igalia.com>");
68974d8361bSThadeu Lima de Souza Cascardo MODULE_DESCRIPTION("Test module for misc character devices");
690