11770d39dSTakashi Sakamoto // SPDX-License-Identifier: GPL-2.0-only
21770d39dSTakashi Sakamoto //
31770d39dSTakashi Sakamoto // device-attribute-test.c - An application of Kunit to test implementation for device attributes.
41770d39dSTakashi Sakamoto //
51770d39dSTakashi Sakamoto // Copyright (c) 2023 Takashi Sakamoto
61770d39dSTakashi Sakamoto //
71770d39dSTakashi Sakamoto // This file can not be built independently since it is intentionally included in core-device.c.
81770d39dSTakashi Sakamoto 
91770d39dSTakashi Sakamoto #include <kunit/test.h>
101770d39dSTakashi Sakamoto 
111c8506d6STakashi Sakamoto // Configuration ROM for AV/C Devices 1.0 (Dec. 12, 2000, 1394 Trading Association)
121c8506d6STakashi Sakamoto // Annex C:Configuration ROM example(informative)
131c8506d6STakashi Sakamoto // C.1 Simple AV/C device
141c8506d6STakashi Sakamoto //
151c8506d6STakashi Sakamoto // Copied from the documentation.
161c8506d6STakashi Sakamoto static const u32 simple_avc_config_rom[] = {
171c8506d6STakashi Sakamoto 	0x0404eabf,
181c8506d6STakashi Sakamoto 	0x31333934,
191c8506d6STakashi Sakamoto 	0xe0646102,
201c8506d6STakashi Sakamoto 	0xffffffff,
211c8506d6STakashi Sakamoto 	0xffffffff,
221c8506d6STakashi Sakamoto 	0x00063287, // root directory.
231c8506d6STakashi Sakamoto 	0x03ffffff,
241c8506d6STakashi Sakamoto 	0x8100000a,
251c8506d6STakashi Sakamoto 	0x17ffffff,
261c8506d6STakashi Sakamoto 	0x8100000e,
271c8506d6STakashi Sakamoto 	0x0c0083c0,
281c8506d6STakashi Sakamoto 	0xd1000001,
291c8506d6STakashi Sakamoto 	0x0004442d, // unit 0 directory.
301c8506d6STakashi Sakamoto 	0x1200a02d,
311c8506d6STakashi Sakamoto 	0x13010001,
321c8506d6STakashi Sakamoto 	0x17ffffff,
331c8506d6STakashi Sakamoto 	0x81000007,
341c8506d6STakashi Sakamoto 	0x0005c915, // leaf for textual descriptor.
351c8506d6STakashi Sakamoto 	0x00000000,
361c8506d6STakashi Sakamoto 	0x00000000,
371c8506d6STakashi Sakamoto 	0x56656e64,
381c8506d6STakashi Sakamoto 	0x6f72204e,
391c8506d6STakashi Sakamoto 	0x616d6500,
401c8506d6STakashi Sakamoto 	0x00057f16, // leaf for textual descriptor.
411c8506d6STakashi Sakamoto 	0x00000000,
421c8506d6STakashi Sakamoto 	0x00000000,
431c8506d6STakashi Sakamoto 	0x4d6f6465,
441c8506d6STakashi Sakamoto 	0x6c204e61,
451c8506d6STakashi Sakamoto 	0x6d650000,
461c8506d6STakashi Sakamoto };
471c8506d6STakashi Sakamoto 
4858aae0a0STakashi Sakamoto // Ibid.
4958aae0a0STakashi Sakamoto // Annex A:Consideration for configuration ROM reader design (informative)
5058aae0a0STakashi Sakamoto // A.1 Vendor directory
5158aae0a0STakashi Sakamoto //
5258aae0a0STakashi Sakamoto // Written by hand.
5358aae0a0STakashi Sakamoto static const u32 legacy_avc_config_rom[] = {
5458aae0a0STakashi Sakamoto 	0x04199fe7,
5558aae0a0STakashi Sakamoto 	0x31333934,
5658aae0a0STakashi Sakamoto 	0xe0644000,
5758aae0a0STakashi Sakamoto 	0x00112233,
5858aae0a0STakashi Sakamoto 	0x44556677,
5958aae0a0STakashi Sakamoto 	0x0005dace, // root directory.
6058aae0a0STakashi Sakamoto 	0x03012345,
6158aae0a0STakashi Sakamoto 	0x0c0083c0,
6258aae0a0STakashi Sakamoto 	0x8d000009,
6358aae0a0STakashi Sakamoto 	0xd1000002,
6458aae0a0STakashi Sakamoto 	0xc3000004,
6558aae0a0STakashi Sakamoto 	0x0002e107, // unit 0 directory.
6658aae0a0STakashi Sakamoto 	0x12abcdef,
6758aae0a0STakashi Sakamoto 	0x13543210,
6858aae0a0STakashi Sakamoto 	0x0002cb73, // vendor directory.
6958aae0a0STakashi Sakamoto 	0x17fedcba,
7058aae0a0STakashi Sakamoto 	0x81000004,
7158aae0a0STakashi Sakamoto 	0x00026dc1, // leaf for EUI-64.
7258aae0a0STakashi Sakamoto 	0x00112233,
7358aae0a0STakashi Sakamoto 	0x44556677,
7458aae0a0STakashi Sakamoto 	0x00050e84, // leaf for textual descriptor.
7558aae0a0STakashi Sakamoto 	0x00000000,
7658aae0a0STakashi Sakamoto 	0x00000000,
7758aae0a0STakashi Sakamoto 	0x41424344,
7858aae0a0STakashi Sakamoto 	0x45464748,
7958aae0a0STakashi Sakamoto 	0x494a0000,
8058aae0a0STakashi Sakamoto };
8158aae0a0STakashi Sakamoto 
device_attr_simple_avc(struct kunit * test)821c8506d6STakashi Sakamoto static void device_attr_simple_avc(struct kunit *test)
831c8506d6STakashi Sakamoto {
841c8506d6STakashi Sakamoto 	static const struct fw_device node = {
851c8506d6STakashi Sakamoto 		.device = {
861c8506d6STakashi Sakamoto 			.type = &fw_device_type,
871c8506d6STakashi Sakamoto 		},
881c8506d6STakashi Sakamoto 		.config_rom = simple_avc_config_rom,
891c8506d6STakashi Sakamoto 		.config_rom_length = sizeof(simple_avc_config_rom),
901c8506d6STakashi Sakamoto 	};
911c8506d6STakashi Sakamoto 	static const struct fw_unit unit0 = {
921c8506d6STakashi Sakamoto 		.device = {
931c8506d6STakashi Sakamoto 			.type = &fw_unit_type,
941c8506d6STakashi Sakamoto 			.parent = (struct device *)&node.device,
951c8506d6STakashi Sakamoto 		},
961c8506d6STakashi Sakamoto 		.directory = &simple_avc_config_rom[12],
971c8506d6STakashi Sakamoto 	};
981c8506d6STakashi Sakamoto 	struct device *node_dev = (struct device *)&node.device;
991c8506d6STakashi Sakamoto 	struct device *unit0_dev = (struct device *)&unit0.device;
1001c8506d6STakashi Sakamoto 	static const int unit0_expected_ids[] = {0x00ffffff, 0x00ffffff, 0x0000a02d, 0x00010001};
1011c8506d6STakashi Sakamoto 	char *buf = kunit_kzalloc(test, PAGE_SIZE, GFP_KERNEL);
102*352fafe9SCharles Han 	KUNIT_ASSERT_NOT_ERR_OR_NULL(test, buf);
1031c8506d6STakashi Sakamoto 	int ids[4] = {0, 0, 0, 0};
1041c8506d6STakashi Sakamoto 
1051c8506d6STakashi Sakamoto 	// Ensure associations for node and unit devices.
1061c8506d6STakashi Sakamoto 
1071c8506d6STakashi Sakamoto 	KUNIT_ASSERT_TRUE(test, is_fw_device(node_dev));
1081c8506d6STakashi Sakamoto 	KUNIT_ASSERT_FALSE(test, is_fw_unit(node_dev));
1091c8506d6STakashi Sakamoto 	KUNIT_ASSERT_PTR_EQ(test, fw_device(node_dev), &node);
1101c8506d6STakashi Sakamoto 
1111c8506d6STakashi Sakamoto 	KUNIT_ASSERT_FALSE(test, is_fw_device(unit0_dev));
1121c8506d6STakashi Sakamoto 	KUNIT_ASSERT_TRUE(test, is_fw_unit(unit0_dev));
1131c8506d6STakashi Sakamoto 	KUNIT_ASSERT_PTR_EQ(test, fw_parent_device((&unit0)), &node);
1141c8506d6STakashi Sakamoto 	KUNIT_ASSERT_PTR_EQ(test, fw_unit(unit0_dev), &unit0);
1151c8506d6STakashi Sakamoto 
1161c8506d6STakashi Sakamoto 	// For entries in root directory.
1171c8506d6STakashi Sakamoto 
1181c8506d6STakashi Sakamoto 	// Vendor immediate entry is found.
1191c8506d6STakashi Sakamoto 	KUNIT_EXPECT_GT(test, show_immediate(node_dev, &config_rom_attributes[0].attr, buf), 0);
1201c8506d6STakashi Sakamoto 	KUNIT_EXPECT_STREQ(test, buf, "0xffffff\n");
1211c8506d6STakashi Sakamoto 
1221c8506d6STakashi Sakamoto 	// Model immediate entry is found.
1231c8506d6STakashi Sakamoto 	KUNIT_EXPECT_GT(test, show_immediate(node_dev, &config_rom_attributes[4].attr, buf), 0);
1241c8506d6STakashi Sakamoto 	KUNIT_EXPECT_STREQ(test, buf, "0xffffff\n");
1251c8506d6STakashi Sakamoto 
1261c8506d6STakashi Sakamoto 	// Descriptor leaf entry for vendor is found.
1271c8506d6STakashi Sakamoto 	KUNIT_EXPECT_GT(test, show_text_leaf(node_dev, &config_rom_attributes[5].attr, buf), 0);
1281c8506d6STakashi Sakamoto 	KUNIT_EXPECT_STREQ(test, buf, "Vendor Name\n");
1291c8506d6STakashi Sakamoto 
1301c8506d6STakashi Sakamoto 	// Descriptor leaf entry for model is found.
1311c8506d6STakashi Sakamoto 	KUNIT_EXPECT_GT(test, show_text_leaf(node_dev, &config_rom_attributes[6].attr, buf), 0);
1321c8506d6STakashi Sakamoto 	KUNIT_EXPECT_STREQ(test, buf, "Model Name\n");
1331c8506d6STakashi Sakamoto 
1341c8506d6STakashi Sakamoto 	// For entries in unit 0 directory.
1351c8506d6STakashi Sakamoto 
1361c8506d6STakashi Sakamoto 	// Vendor immediate entry is not found.
1371c8506d6STakashi Sakamoto 	KUNIT_EXPECT_LT(test, show_immediate(unit0_dev, &config_rom_attributes[0].attr, buf), 0);
1381c8506d6STakashi Sakamoto 
1391c8506d6STakashi Sakamoto 	// Model immediate entry is found.
1401c8506d6STakashi Sakamoto 	KUNIT_EXPECT_GT(test, show_immediate(unit0_dev, &config_rom_attributes[4].attr, buf), 0);
1411c8506d6STakashi Sakamoto 	KUNIT_EXPECT_STREQ(test, buf, "0xffffff\n");
1421c8506d6STakashi Sakamoto 
1431c8506d6STakashi Sakamoto 	// Descriptor leaf entry for vendor is not found.
1441c8506d6STakashi Sakamoto 	KUNIT_EXPECT_LT(test, show_text_leaf(unit0_dev, &config_rom_attributes[5].attr, buf), 0);
1451c8506d6STakashi Sakamoto 
1461c8506d6STakashi Sakamoto 	// Descriptor leaf entry for model is found.
1471c8506d6STakashi Sakamoto 	KUNIT_EXPECT_GT(test, show_text_leaf(unit0_dev, &config_rom_attributes[6].attr, buf), 0);
1481c8506d6STakashi Sakamoto 	KUNIT_EXPECT_STREQ(test, buf, "Model Name\n");
1491c8506d6STakashi Sakamoto 
1501c8506d6STakashi Sakamoto 	// Specifier_ID immediate entry is found.
1511c8506d6STakashi Sakamoto 	KUNIT_EXPECT_GT(test, show_immediate(unit0_dev, &config_rom_attributes[2].attr, buf), 0);
1521c8506d6STakashi Sakamoto 	KUNIT_EXPECT_STREQ(test, buf, "0x00a02d\n");
1531c8506d6STakashi Sakamoto 
1541c8506d6STakashi Sakamoto 	// Version immediate entry is found.
1551c8506d6STakashi Sakamoto 	KUNIT_EXPECT_GT(test, show_immediate(unit0_dev, &config_rom_attributes[3].attr, buf), 0);
1561c8506d6STakashi Sakamoto 	KUNIT_EXPECT_STREQ(test, buf, "0x010001\n");
1571c8506d6STakashi Sakamoto 
1581c8506d6STakashi Sakamoto 	kunit_kfree(test, buf);
1591c8506d6STakashi Sakamoto 
1601c8506d6STakashi Sakamoto 	get_modalias_ids(&unit0, ids);
1611c8506d6STakashi Sakamoto 	KUNIT_EXPECT_MEMEQ(test, ids, unit0_expected_ids, sizeof(ids));
1621c8506d6STakashi Sakamoto }
1631c8506d6STakashi Sakamoto 
device_attr_legacy_avc(struct kunit * test)16458aae0a0STakashi Sakamoto static void device_attr_legacy_avc(struct kunit *test)
16558aae0a0STakashi Sakamoto {
16658aae0a0STakashi Sakamoto 	static const struct fw_device node = {
16758aae0a0STakashi Sakamoto 		.device = {
16858aae0a0STakashi Sakamoto 			.type = &fw_device_type,
16958aae0a0STakashi Sakamoto 		},
17058aae0a0STakashi Sakamoto 		.config_rom = legacy_avc_config_rom,
17158aae0a0STakashi Sakamoto 		.config_rom_length = sizeof(legacy_avc_config_rom),
17258aae0a0STakashi Sakamoto 	};
17358aae0a0STakashi Sakamoto 	static const struct fw_unit unit0 = {
17458aae0a0STakashi Sakamoto 		.device = {
17558aae0a0STakashi Sakamoto 			.type = &fw_unit_type,
17658aae0a0STakashi Sakamoto 			.parent = (struct device *)&node.device,
17758aae0a0STakashi Sakamoto 		},
17858aae0a0STakashi Sakamoto 		.directory = &legacy_avc_config_rom[11],
17958aae0a0STakashi Sakamoto 	};
18058aae0a0STakashi Sakamoto 	struct device *node_dev = (struct device *)&node.device;
18158aae0a0STakashi Sakamoto 	struct device *unit0_dev = (struct device *)&unit0.device;
182986c20bbSTakashi Sakamoto 	static const int unit0_expected_ids[] = {0x00012345, 0x00fedcba, 0x00abcdef, 0x00543210};
18358aae0a0STakashi Sakamoto 	char *buf = kunit_kzalloc(test, PAGE_SIZE, GFP_KERNEL);
184*352fafe9SCharles Han 	KUNIT_ASSERT_NOT_ERR_OR_NULL(test, buf);
18558aae0a0STakashi Sakamoto 	int ids[4] = {0, 0, 0, 0};
18658aae0a0STakashi Sakamoto 
18758aae0a0STakashi Sakamoto 	// Ensure associations for node and unit devices.
18858aae0a0STakashi Sakamoto 
18958aae0a0STakashi Sakamoto 	KUNIT_ASSERT_TRUE(test, is_fw_device(node_dev));
19058aae0a0STakashi Sakamoto 	KUNIT_ASSERT_FALSE(test, is_fw_unit(node_dev));
19158aae0a0STakashi Sakamoto 	KUNIT_ASSERT_PTR_EQ(test, fw_device((node_dev)), &node);
19258aae0a0STakashi Sakamoto 
19358aae0a0STakashi Sakamoto 	KUNIT_ASSERT_FALSE(test, is_fw_device(unit0_dev));
19458aae0a0STakashi Sakamoto 	KUNIT_ASSERT_TRUE(test, is_fw_unit(unit0_dev));
19558aae0a0STakashi Sakamoto 	KUNIT_ASSERT_PTR_EQ(test, fw_parent_device((&unit0)), &node);
19658aae0a0STakashi Sakamoto 	KUNIT_ASSERT_PTR_EQ(test, fw_unit(unit0_dev), &unit0);
19758aae0a0STakashi Sakamoto 
19858aae0a0STakashi Sakamoto 	// For entries in root directory.
19958aae0a0STakashi Sakamoto 
20058aae0a0STakashi Sakamoto 	// Vendor immediate entry is found.
20158aae0a0STakashi Sakamoto 	KUNIT_EXPECT_GT(test, show_immediate(node_dev, &config_rom_attributes[0].attr, buf), 0);
20258aae0a0STakashi Sakamoto 	KUNIT_EXPECT_STREQ(test, buf, "0x012345\n");
20358aae0a0STakashi Sakamoto 
204b6a38057STakashi Sakamoto 	// Model immediate entry is found.
205b6a38057STakashi Sakamoto 	KUNIT_EXPECT_GT(test, show_immediate(node_dev, &config_rom_attributes[4].attr, buf), 0);
206b6a38057STakashi Sakamoto 	KUNIT_EXPECT_STREQ(test, buf, "0xfedcba\n");
20758aae0a0STakashi Sakamoto 
20858aae0a0STakashi Sakamoto 	// Descriptor leaf entry for vendor is not found.
20958aae0a0STakashi Sakamoto 	KUNIT_EXPECT_LT(test, show_text_leaf(node_dev, &config_rom_attributes[5].attr, buf), 0);
21058aae0a0STakashi Sakamoto 
2112eab8bc0STakashi Sakamoto 	// Descriptor leaf entry for model is found.
2122eab8bc0STakashi Sakamoto 	KUNIT_EXPECT_GT(test, show_text_leaf(node_dev, &config_rom_attributes[6].attr, buf), 0);
2132eab8bc0STakashi Sakamoto 	KUNIT_EXPECT_STREQ(test, buf, "ABCDEFGHIJ\n");
21458aae0a0STakashi Sakamoto 
21558aae0a0STakashi Sakamoto 	// For entries in unit 0 directory.
21658aae0a0STakashi Sakamoto 
21758aae0a0STakashi Sakamoto 	// Vendor immediate entry is not found.
21858aae0a0STakashi Sakamoto 	KUNIT_EXPECT_LT(test, show_immediate(unit0_dev, &config_rom_attributes[0].attr, buf), 0);
21958aae0a0STakashi Sakamoto 
22058aae0a0STakashi Sakamoto 	// Model immediate entry is not found.
22158aae0a0STakashi Sakamoto 	KUNIT_EXPECT_LT(test, show_immediate(unit0_dev, &config_rom_attributes[4].attr, buf), 0);
22258aae0a0STakashi Sakamoto 
22358aae0a0STakashi Sakamoto 	// Descriptor leaf entry for vendor is not found.
22458aae0a0STakashi Sakamoto 	KUNIT_EXPECT_LT(test, show_text_leaf(unit0_dev, &config_rom_attributes[5].attr, buf), 0);
22558aae0a0STakashi Sakamoto 
22658aae0a0STakashi Sakamoto 	// Descriptor leaf entry for model is not found.
22758aae0a0STakashi Sakamoto 	KUNIT_EXPECT_LT(test, show_text_leaf(unit0_dev, &config_rom_attributes[6].attr, buf), 0);
22858aae0a0STakashi Sakamoto 
22958aae0a0STakashi Sakamoto 	// Specifier_ID immediate entry is found.
23058aae0a0STakashi Sakamoto 	KUNIT_EXPECT_GT(test, show_immediate(unit0_dev, &config_rom_attributes[2].attr, buf), 0);
23158aae0a0STakashi Sakamoto 	KUNIT_EXPECT_STREQ(test, buf, "0xabcdef\n");
23258aae0a0STakashi Sakamoto 
23358aae0a0STakashi Sakamoto 	// Version immediate entry is found.
23458aae0a0STakashi Sakamoto 	KUNIT_EXPECT_GT(test, show_immediate(unit0_dev, &config_rom_attributes[3].attr, buf), 0);
23558aae0a0STakashi Sakamoto 	KUNIT_EXPECT_STREQ(test, buf, "0x543210\n");
23658aae0a0STakashi Sakamoto 
23758aae0a0STakashi Sakamoto 	kunit_kfree(test, buf);
23858aae0a0STakashi Sakamoto 
23958aae0a0STakashi Sakamoto 	get_modalias_ids(&unit0, ids);
24058aae0a0STakashi Sakamoto 	KUNIT_EXPECT_MEMEQ(test, ids, unit0_expected_ids, sizeof(ids));
24158aae0a0STakashi Sakamoto }
24258aae0a0STakashi Sakamoto 
2431770d39dSTakashi Sakamoto static struct kunit_case device_attr_test_cases[] = {
2441c8506d6STakashi Sakamoto 	KUNIT_CASE(device_attr_simple_avc),
24558aae0a0STakashi Sakamoto 	KUNIT_CASE(device_attr_legacy_avc),
2461770d39dSTakashi Sakamoto 	{}
2471770d39dSTakashi Sakamoto };
2481770d39dSTakashi Sakamoto 
2491770d39dSTakashi Sakamoto static struct kunit_suite device_attr_test_suite = {
2501770d39dSTakashi Sakamoto 	.name = "firewire-device-attribute",
2511770d39dSTakashi Sakamoto 	.test_cases = device_attr_test_cases,
2521770d39dSTakashi Sakamoto };
2531770d39dSTakashi Sakamoto kunit_test_suite(device_attr_test_suite);
254