diff options
Diffstat (limited to 'drivers/thunderbolt/test.c')
| -rw-r--r-- | drivers/thunderbolt/test.c | 492 | 
1 files changed, 492 insertions, 0 deletions
| diff --git a/drivers/thunderbolt/test.c b/drivers/thunderbolt/test.c index 464c2d37b992..5ff5a03bc9ce 100644 --- a/drivers/thunderbolt/test.c +++ b/drivers/thunderbolt/test.c @@ -119,6 +119,7 @@ static struct tb_switch *alloc_host(struct kunit *test)  	sw->ports[7].config.type = TB_TYPE_NHI;  	sw->ports[7].config.max_in_hop_id = 11;  	sw->ports[7].config.max_out_hop_id = 11; +	sw->ports[7].config.nfc_credits = 0x41800000;  	sw->ports[8].config.type = TB_TYPE_PCIE_DOWN;  	sw->ports[8].config.max_in_hop_id = 8; @@ -1594,6 +1595,489 @@ static void tb_test_tunnel_port_on_path(struct kunit *test)  	tb_tunnel_free(dp_tunnel);  } +static void tb_test_tunnel_dma(struct kunit *test) +{ +	struct tb_port *nhi, *port; +	struct tb_tunnel *tunnel; +	struct tb_switch *host; + +	/* +	 * Create DMA tunnel from NHI to port 1 and back. +	 * +	 *   [Host 1] +	 *    1 ^ In HopID 1 -> Out HopID 8 +	 *      | +	 *      v In HopID 8 -> Out HopID 1 +	 * ............ Domain border +	 *      | +	 *   [Host 2] +	 */ +	host = alloc_host(test); +	nhi = &host->ports[7]; +	port = &host->ports[1]; + +	tunnel = tb_tunnel_alloc_dma(NULL, nhi, port, 8, 1, 8, 1); +	KUNIT_ASSERT_TRUE(test, tunnel != NULL); +	KUNIT_EXPECT_EQ(test, tunnel->type, (enum tb_tunnel_type)TB_TUNNEL_DMA); +	KUNIT_EXPECT_PTR_EQ(test, tunnel->src_port, nhi); +	KUNIT_EXPECT_PTR_EQ(test, tunnel->dst_port, port); +	KUNIT_ASSERT_EQ(test, tunnel->npaths, (size_t)2); +	/* RX path */ +	KUNIT_ASSERT_EQ(test, tunnel->paths[0]->path_length, 1); +	KUNIT_EXPECT_PTR_EQ(test, tunnel->paths[0]->hops[0].in_port, port); +	KUNIT_EXPECT_EQ(test, tunnel->paths[0]->hops[0].in_hop_index, 8); +	KUNIT_EXPECT_PTR_EQ(test, tunnel->paths[0]->hops[0].out_port, nhi); +	KUNIT_EXPECT_EQ(test, tunnel->paths[0]->hops[0].next_hop_index, 1); +	/* TX path */ +	KUNIT_ASSERT_EQ(test, tunnel->paths[1]->path_length, 1); +	KUNIT_EXPECT_PTR_EQ(test, tunnel->paths[1]->hops[0].in_port, nhi); +	KUNIT_EXPECT_EQ(test, tunnel->paths[1]->hops[0].in_hop_index, 1); +	KUNIT_EXPECT_PTR_EQ(test, tunnel->paths[1]->hops[0].out_port, port); +	KUNIT_EXPECT_EQ(test, tunnel->paths[1]->hops[0].next_hop_index, 8); + +	tb_tunnel_free(tunnel); +} + +static void tb_test_tunnel_dma_rx(struct kunit *test) +{ +	struct tb_port *nhi, *port; +	struct tb_tunnel *tunnel; +	struct tb_switch *host; + +	/* +	 * Create DMA RX tunnel from port 1 to NHI. +	 * +	 *   [Host 1] +	 *    1 ^ +	 *      | +	 *      | In HopID 15 -> Out HopID 2 +	 * ............ Domain border +	 *      | +	 *   [Host 2] +	 */ +	host = alloc_host(test); +	nhi = &host->ports[7]; +	port = &host->ports[1]; + +	tunnel = tb_tunnel_alloc_dma(NULL, nhi, port, -1, -1, 15, 2); +	KUNIT_ASSERT_TRUE(test, tunnel != NULL); +	KUNIT_EXPECT_EQ(test, tunnel->type, (enum tb_tunnel_type)TB_TUNNEL_DMA); +	KUNIT_EXPECT_PTR_EQ(test, tunnel->src_port, nhi); +	KUNIT_EXPECT_PTR_EQ(test, tunnel->dst_port, port); +	KUNIT_ASSERT_EQ(test, tunnel->npaths, (size_t)1); +	/* RX path */ +	KUNIT_ASSERT_EQ(test, tunnel->paths[0]->path_length, 1); +	KUNIT_EXPECT_PTR_EQ(test, tunnel->paths[0]->hops[0].in_port, port); +	KUNIT_EXPECT_EQ(test, tunnel->paths[0]->hops[0].in_hop_index, 15); +	KUNIT_EXPECT_PTR_EQ(test, tunnel->paths[0]->hops[0].out_port, nhi); +	KUNIT_EXPECT_EQ(test, tunnel->paths[0]->hops[0].next_hop_index, 2); + +	tb_tunnel_free(tunnel); +} + +static void tb_test_tunnel_dma_tx(struct kunit *test) +{ +	struct tb_port *nhi, *port; +	struct tb_tunnel *tunnel; +	struct tb_switch *host; + +	/* +	 * Create DMA TX tunnel from NHI to port 1. +	 * +	 *   [Host 1] +	 *    1 | In HopID 2 -> Out HopID 15 +	 *      | +	 *      v +	 * ............ Domain border +	 *      | +	 *   [Host 2] +	 */ +	host = alloc_host(test); +	nhi = &host->ports[7]; +	port = &host->ports[1]; + +	tunnel = tb_tunnel_alloc_dma(NULL, nhi, port, 15, 2, -1, -1); +	KUNIT_ASSERT_TRUE(test, tunnel != NULL); +	KUNIT_EXPECT_EQ(test, tunnel->type, (enum tb_tunnel_type)TB_TUNNEL_DMA); +	KUNIT_EXPECT_PTR_EQ(test, tunnel->src_port, nhi); +	KUNIT_EXPECT_PTR_EQ(test, tunnel->dst_port, port); +	KUNIT_ASSERT_EQ(test, tunnel->npaths, (size_t)1); +	/* TX path */ +	KUNIT_ASSERT_EQ(test, tunnel->paths[0]->path_length, 1); +	KUNIT_EXPECT_PTR_EQ(test, tunnel->paths[0]->hops[0].in_port, nhi); +	KUNIT_EXPECT_EQ(test, tunnel->paths[0]->hops[0].in_hop_index, 2); +	KUNIT_EXPECT_PTR_EQ(test, tunnel->paths[0]->hops[0].out_port, port); +	KUNIT_EXPECT_EQ(test, tunnel->paths[0]->hops[0].next_hop_index, 15); + +	tb_tunnel_free(tunnel); +} + +static void tb_test_tunnel_dma_chain(struct kunit *test) +{ +	struct tb_switch *host, *dev1, *dev2; +	struct tb_port *nhi, *port; +	struct tb_tunnel *tunnel; + +	/* +	 * Create DMA tunnel from NHI to Device #2 port 3 and back. +	 * +	 *   [Host 1] +	 *    1 ^ In HopID 1 -> Out HopID x +	 *      | +	 *    1 | In HopID x -> Out HopID 1 +	 *  [Device #1] +	 *         7 \ +	 *          1 \ +	 *         [Device #2] +	 *           3 | In HopID x -> Out HopID 8 +	 *             | +	 *             v In HopID 8 -> Out HopID x +	 * ............ Domain border +	 *             | +	 *          [Host 2] +	 */ +	host = alloc_host(test); +	dev1 = alloc_dev_default(test, host, 0x1, true); +	dev2 = alloc_dev_default(test, dev1, 0x701, true); + +	nhi = &host->ports[7]; +	port = &dev2->ports[3]; +	tunnel = tb_tunnel_alloc_dma(NULL, nhi, port, 8, 1, 8, 1); +	KUNIT_ASSERT_TRUE(test, tunnel != NULL); +	KUNIT_EXPECT_EQ(test, tunnel->type, (enum tb_tunnel_type)TB_TUNNEL_DMA); +	KUNIT_EXPECT_PTR_EQ(test, tunnel->src_port, nhi); +	KUNIT_EXPECT_PTR_EQ(test, tunnel->dst_port, port); +	KUNIT_ASSERT_EQ(test, tunnel->npaths, (size_t)2); +	/* RX path */ +	KUNIT_ASSERT_EQ(test, tunnel->paths[0]->path_length, 3); +	KUNIT_EXPECT_PTR_EQ(test, tunnel->paths[0]->hops[0].in_port, port); +	KUNIT_EXPECT_EQ(test, tunnel->paths[0]->hops[0].in_hop_index, 8); +	KUNIT_EXPECT_PTR_EQ(test, tunnel->paths[0]->hops[0].out_port, +			    &dev2->ports[1]); +	KUNIT_EXPECT_PTR_EQ(test, tunnel->paths[0]->hops[1].in_port, +			    &dev1->ports[7]); +	KUNIT_EXPECT_PTR_EQ(test, tunnel->paths[0]->hops[1].out_port, +			    &dev1->ports[1]); +	KUNIT_EXPECT_PTR_EQ(test, tunnel->paths[0]->hops[2].in_port, +			    &host->ports[1]); +	KUNIT_EXPECT_PTR_EQ(test, tunnel->paths[0]->hops[2].out_port, nhi); +	KUNIT_EXPECT_EQ(test, tunnel->paths[0]->hops[2].next_hop_index, 1); +	/* TX path */ +	KUNIT_ASSERT_EQ(test, tunnel->paths[1]->path_length, 3); +	KUNIT_EXPECT_PTR_EQ(test, tunnel->paths[1]->hops[0].in_port, nhi); +	KUNIT_EXPECT_EQ(test, tunnel->paths[1]->hops[0].in_hop_index, 1); +	KUNIT_EXPECT_PTR_EQ(test, tunnel->paths[1]->hops[1].in_port, +			    &dev1->ports[1]); +	KUNIT_EXPECT_PTR_EQ(test, tunnel->paths[1]->hops[1].out_port, +			    &dev1->ports[7]); +	KUNIT_EXPECT_PTR_EQ(test, tunnel->paths[1]->hops[2].in_port, +			    &dev2->ports[1]); +	KUNIT_EXPECT_PTR_EQ(test, tunnel->paths[1]->hops[2].out_port, port); +	KUNIT_EXPECT_EQ(test, tunnel->paths[1]->hops[2].next_hop_index, 8); + +	tb_tunnel_free(tunnel); +} + +static void tb_test_tunnel_dma_match(struct kunit *test) +{ +	struct tb_port *nhi, *port; +	struct tb_tunnel *tunnel; +	struct tb_switch *host; + +	host = alloc_host(test); +	nhi = &host->ports[7]; +	port = &host->ports[1]; + +	tunnel = tb_tunnel_alloc_dma(NULL, nhi, port, 15, 1, 15, 1); +	KUNIT_ASSERT_TRUE(test, tunnel != NULL); + +	KUNIT_ASSERT_TRUE(test, tb_tunnel_match_dma(tunnel, 15, 1, 15, 1)); +	KUNIT_ASSERT_FALSE(test, tb_tunnel_match_dma(tunnel, 8, 1, 15, 1)); +	KUNIT_ASSERT_TRUE(test, tb_tunnel_match_dma(tunnel, -1, -1, 15, 1)); +	KUNIT_ASSERT_TRUE(test, tb_tunnel_match_dma(tunnel, 15, 1, -1, -1)); +	KUNIT_ASSERT_TRUE(test, tb_tunnel_match_dma(tunnel, 15, -1, -1, -1)); +	KUNIT_ASSERT_TRUE(test, tb_tunnel_match_dma(tunnel, -1, 1, -1, -1)); +	KUNIT_ASSERT_TRUE(test, tb_tunnel_match_dma(tunnel, -1, -1, 15, -1)); +	KUNIT_ASSERT_TRUE(test, tb_tunnel_match_dma(tunnel, -1, -1, -1, 1)); +	KUNIT_ASSERT_TRUE(test, tb_tunnel_match_dma(tunnel, -1, -1, -1, -1)); +	KUNIT_ASSERT_FALSE(test, tb_tunnel_match_dma(tunnel, 8, -1, 8, -1)); + +	tb_tunnel_free(tunnel); + +	tunnel = tb_tunnel_alloc_dma(NULL, nhi, port, 15, 1, -1, -1); +	KUNIT_ASSERT_TRUE(test, tunnel != NULL); +	KUNIT_ASSERT_TRUE(test, tb_tunnel_match_dma(tunnel, 15, 1, -1, -1)); +	KUNIT_ASSERT_TRUE(test, tb_tunnel_match_dma(tunnel, 15, -1, -1, -1)); +	KUNIT_ASSERT_TRUE(test, tb_tunnel_match_dma(tunnel, -1, 1, -1, -1)); +	KUNIT_ASSERT_TRUE(test, tb_tunnel_match_dma(tunnel, -1, -1, -1, -1)); +	KUNIT_ASSERT_FALSE(test, tb_tunnel_match_dma(tunnel, 15, 1, 15, 1)); +	KUNIT_ASSERT_FALSE(test, tb_tunnel_match_dma(tunnel, -1, -1, 15, 1)); +	KUNIT_ASSERT_FALSE(test, tb_tunnel_match_dma(tunnel, 15, 11, -1, -1)); + +	tb_tunnel_free(tunnel); + +	tunnel = tb_tunnel_alloc_dma(NULL, nhi, port, -1, -1, 15, 11); +	KUNIT_ASSERT_TRUE(test, tunnel != NULL); +	KUNIT_ASSERT_TRUE(test, tb_tunnel_match_dma(tunnel, -1, -1, 15, 11)); +	KUNIT_ASSERT_TRUE(test, tb_tunnel_match_dma(tunnel, -1, -1, 15, -1)); +	KUNIT_ASSERT_TRUE(test, tb_tunnel_match_dma(tunnel, -1, -1, -1, 11)); +	KUNIT_ASSERT_TRUE(test, tb_tunnel_match_dma(tunnel, -1, -1, -1, -1)); +	KUNIT_ASSERT_FALSE(test, tb_tunnel_match_dma(tunnel, -1, -1, 15, 1)); +	KUNIT_ASSERT_FALSE(test, tb_tunnel_match_dma(tunnel, -1, -1, 10, 11)); +	KUNIT_ASSERT_FALSE(test, tb_tunnel_match_dma(tunnel, 15, 11, -1, -1)); + +	tb_tunnel_free(tunnel); +} + +static const u32 root_directory[] = { +	0x55584401,	/* "UXD" v1 */ +	0x00000018,	/* Root directory length */ +	0x76656e64,	/* "vend" */ +	0x6f726964,	/* "orid" */ +	0x76000001,	/* "v" R 1 */ +	0x00000a27,	/* Immediate value, ! Vendor ID */ +	0x76656e64,	/* "vend" */ +	0x6f726964,	/* "orid" */ +	0x74000003,	/* "t" R 3 */ +	0x0000001a,	/* Text leaf offset, (“Apple Inc.”) */ +	0x64657669,	/* "devi" */ +	0x63656964,	/* "ceid" */ +	0x76000001,	/* "v" R 1 */ +	0x0000000a,	/* Immediate value, ! Device ID */ +	0x64657669,	/* "devi" */ +	0x63656964,	/* "ceid" */ +	0x74000003,	/* "t" R 3 */ +	0x0000001d,	/* Text leaf offset, (“Macintosh”) */ +	0x64657669,	/* "devi" */ +	0x63657276,	/* "cerv" */ +	0x76000001,	/* "v" R 1 */ +	0x80000100,	/* Immediate value, Device Revision */ +	0x6e657477,	/* "netw" */ +	0x6f726b00,	/* "ork" */ +	0x44000014,	/* "D" R 20 */ +	0x00000021,	/* Directory data offset, (Network Directory) */ +	0x4170706c,	/* "Appl" */ +	0x6520496e,	/* "e In" */ +	0x632e0000,	/* "c." ! */ +	0x4d616369,	/* "Maci" */ +	0x6e746f73,	/* "ntos" */ +	0x68000000,	/* "h" */ +	0x00000000,	/* padding */ +	0xca8961c6,	/* Directory UUID, Network Directory */ +	0x9541ce1c,	/* Directory UUID, Network Directory */ +	0x5949b8bd,	/* Directory UUID, Network Directory */ +	0x4f5a5f2e,	/* Directory UUID, Network Directory */ +	0x70727463,	/* "prtc" */ +	0x69640000,	/* "id" */ +	0x76000001,	/* "v" R 1 */ +	0x00000001,	/* Immediate value, Network Protocol ID */ +	0x70727463,	/* "prtc" */ +	0x76657273,	/* "vers" */ +	0x76000001,	/* "v" R 1 */ +	0x00000001,	/* Immediate value, Network Protocol Version */ +	0x70727463,	/* "prtc" */ +	0x72657673,	/* "revs" */ +	0x76000001,	/* "v" R 1 */ +	0x00000001,	/* Immediate value, Network Protocol Revision */ +	0x70727463,	/* "prtc" */ +	0x73746e73,	/* "stns" */ +	0x76000001,	/* "v" R 1 */ +	0x00000000,	/* Immediate value, Network Protocol Settings */ +}; + +static const uuid_t network_dir_uuid = +	UUID_INIT(0xc66189ca, 0x1cce, 0x4195, +		  0xbd, 0xb8, 0x49, 0x59, 0x2e, 0x5f, 0x5a, 0x4f); + +static void tb_test_property_parse(struct kunit *test) +{ +	struct tb_property_dir *dir, *network_dir; +	struct tb_property *p; + +	dir = tb_property_parse_dir(root_directory, ARRAY_SIZE(root_directory)); +	KUNIT_ASSERT_TRUE(test, dir != NULL); + +	p = tb_property_find(dir, "foo", TB_PROPERTY_TYPE_TEXT); +	KUNIT_ASSERT_TRUE(test, !p); + +	p = tb_property_find(dir, "vendorid", TB_PROPERTY_TYPE_TEXT); +	KUNIT_ASSERT_TRUE(test, p != NULL); +	KUNIT_EXPECT_STREQ(test, p->value.text, "Apple Inc."); + +	p = tb_property_find(dir, "vendorid", TB_PROPERTY_TYPE_VALUE); +	KUNIT_ASSERT_TRUE(test, p != NULL); +	KUNIT_EXPECT_EQ(test, p->value.immediate, (u32)0xa27); + +	p = tb_property_find(dir, "deviceid", TB_PROPERTY_TYPE_TEXT); +	KUNIT_ASSERT_TRUE(test, p != NULL); +	KUNIT_EXPECT_STREQ(test, p->value.text, "Macintosh"); + +	p = tb_property_find(dir, "deviceid", TB_PROPERTY_TYPE_VALUE); +	KUNIT_ASSERT_TRUE(test, p != NULL); +	KUNIT_EXPECT_EQ(test, p->value.immediate, (u32)0xa); + +	p = tb_property_find(dir, "missing", TB_PROPERTY_TYPE_DIRECTORY); +	KUNIT_ASSERT_TRUE(test, !p); + +	p = tb_property_find(dir, "network", TB_PROPERTY_TYPE_DIRECTORY); +	KUNIT_ASSERT_TRUE(test, p != NULL); + +	network_dir = p->value.dir; +	KUNIT_EXPECT_TRUE(test, uuid_equal(network_dir->uuid, &network_dir_uuid)); + +	p = tb_property_find(network_dir, "prtcid", TB_PROPERTY_TYPE_VALUE); +	KUNIT_ASSERT_TRUE(test, p != NULL); +	KUNIT_EXPECT_EQ(test, p->value.immediate, (u32)0x1); + +	p = tb_property_find(network_dir, "prtcvers", TB_PROPERTY_TYPE_VALUE); +	KUNIT_ASSERT_TRUE(test, p != NULL); +	KUNIT_EXPECT_EQ(test, p->value.immediate, (u32)0x1); + +	p = tb_property_find(network_dir, "prtcrevs", TB_PROPERTY_TYPE_VALUE); +	KUNIT_ASSERT_TRUE(test, p != NULL); +	KUNIT_EXPECT_EQ(test, p->value.immediate, (u32)0x1); + +	p = tb_property_find(network_dir, "prtcstns", TB_PROPERTY_TYPE_VALUE); +	KUNIT_ASSERT_TRUE(test, p != NULL); +	KUNIT_EXPECT_EQ(test, p->value.immediate, (u32)0x0); + +	p = tb_property_find(network_dir, "deviceid", TB_PROPERTY_TYPE_VALUE); +	KUNIT_EXPECT_TRUE(test, !p); +	p = tb_property_find(network_dir, "deviceid", TB_PROPERTY_TYPE_TEXT); +	KUNIT_EXPECT_TRUE(test, !p); + +	tb_property_free_dir(dir); +} + +static void tb_test_property_format(struct kunit *test) +{ +	struct tb_property_dir *dir; +	ssize_t block_len; +	u32 *block; +	int ret, i; + +	dir = tb_property_parse_dir(root_directory, ARRAY_SIZE(root_directory)); +	KUNIT_ASSERT_TRUE(test, dir != NULL); + +	ret = tb_property_format_dir(dir, NULL, 0); +	KUNIT_ASSERT_EQ(test, ret, (int)ARRAY_SIZE(root_directory)); + +	block_len = ret; + +	block = kunit_kzalloc(test, block_len * sizeof(u32), GFP_KERNEL); +	KUNIT_ASSERT_TRUE(test, block != NULL); + +	ret = tb_property_format_dir(dir, block, block_len); +	KUNIT_EXPECT_EQ(test, ret, 0); + +	for (i = 0; i < ARRAY_SIZE(root_directory); i++) +		KUNIT_EXPECT_EQ(test, root_directory[i], block[i]); + +	tb_property_free_dir(dir); +} + +static void compare_dirs(struct kunit *test, struct tb_property_dir *d1, +			 struct tb_property_dir *d2) +{ +	struct tb_property *p1, *p2, *tmp; +	int n1, n2, i; + +	if (d1->uuid) { +		KUNIT_ASSERT_TRUE(test, d2->uuid != NULL); +		KUNIT_ASSERT_TRUE(test, uuid_equal(d1->uuid, d2->uuid)); +	} else { +		KUNIT_ASSERT_TRUE(test, d2->uuid == NULL); +	} + +	n1 = 0; +	tb_property_for_each(d1, tmp) +		n1++; +	KUNIT_ASSERT_NE(test, n1, 0); + +	n2 = 0; +	tb_property_for_each(d2, tmp) +		n2++; +	KUNIT_ASSERT_NE(test, n2, 0); + +	KUNIT_ASSERT_EQ(test, n1, n2); + +	p1 = NULL; +	p2 = NULL; +	for (i = 0; i < n1; i++) { +		p1 = tb_property_get_next(d1, p1); +		KUNIT_ASSERT_TRUE(test, p1 != NULL); +		p2 = tb_property_get_next(d2, p2); +		KUNIT_ASSERT_TRUE(test, p2 != NULL); + +		KUNIT_ASSERT_STREQ(test, &p1->key[0], &p2->key[0]); +		KUNIT_ASSERT_EQ(test, p1->type, p2->type); +		KUNIT_ASSERT_EQ(test, p1->length, p2->length); + +		switch (p1->type) { +		case TB_PROPERTY_TYPE_DIRECTORY: +			KUNIT_ASSERT_TRUE(test, p1->value.dir != NULL); +			KUNIT_ASSERT_TRUE(test, p2->value.dir != NULL); +			compare_dirs(test, p1->value.dir, p2->value.dir); +			break; + +		case TB_PROPERTY_TYPE_DATA: +			KUNIT_ASSERT_TRUE(test, p1->value.data != NULL); +			KUNIT_ASSERT_TRUE(test, p2->value.data != NULL); +			KUNIT_ASSERT_TRUE(test, +				!memcmp(p1->value.data, p2->value.data, +					p1->length * 4) +			); +			break; + +		case TB_PROPERTY_TYPE_TEXT: +			KUNIT_ASSERT_TRUE(test, p1->value.text != NULL); +			KUNIT_ASSERT_TRUE(test, p2->value.text != NULL); +			KUNIT_ASSERT_STREQ(test, p1->value.text, p2->value.text); +			break; + +		case TB_PROPERTY_TYPE_VALUE: +			KUNIT_ASSERT_EQ(test, p1->value.immediate, +					p2->value.immediate); +			break; +		default: +			KUNIT_FAIL(test, "unexpected property type"); +			break; +		} +	} +} + +static void tb_test_property_copy(struct kunit *test) +{ +	struct tb_property_dir *src, *dst; +	u32 *block; +	int ret, i; + +	src = tb_property_parse_dir(root_directory, ARRAY_SIZE(root_directory)); +	KUNIT_ASSERT_TRUE(test, src != NULL); + +	dst = tb_property_copy_dir(src); +	KUNIT_ASSERT_TRUE(test, dst != NULL); + +	/* Compare the structures */ +	compare_dirs(test, src, dst); + +	/* Compare the resulting property block */ +	ret = tb_property_format_dir(dst, NULL, 0); +	KUNIT_ASSERT_EQ(test, ret, (int)ARRAY_SIZE(root_directory)); + +	block = kunit_kzalloc(test, sizeof(root_directory), GFP_KERNEL); +	KUNIT_ASSERT_TRUE(test, block != NULL); + +	ret = tb_property_format_dir(dst, block, ARRAY_SIZE(root_directory)); +	KUNIT_EXPECT_TRUE(test, !ret); + +	for (i = 0; i < ARRAY_SIZE(root_directory); i++) +		KUNIT_EXPECT_EQ(test, root_directory[i], block[i]); + +	tb_property_free_dir(dst); +	tb_property_free_dir(src); +} +  static struct kunit_case tb_test_cases[] = {  	KUNIT_CASE(tb_test_path_basic),  	KUNIT_CASE(tb_test_path_not_connected_walk), @@ -1616,6 +2100,14 @@ static struct kunit_case tb_test_cases[] = {  	KUNIT_CASE(tb_test_tunnel_dp_max_length),  	KUNIT_CASE(tb_test_tunnel_port_on_path),  	KUNIT_CASE(tb_test_tunnel_usb3), +	KUNIT_CASE(tb_test_tunnel_dma), +	KUNIT_CASE(tb_test_tunnel_dma_rx), +	KUNIT_CASE(tb_test_tunnel_dma_tx), +	KUNIT_CASE(tb_test_tunnel_dma_chain), +	KUNIT_CASE(tb_test_tunnel_dma_match), +	KUNIT_CASE(tb_test_property_parse), +	KUNIT_CASE(tb_test_property_format), +	KUNIT_CASE(tb_test_property_copy),  	{ }  }; | 
