// SPDX-License-Identifier: GPL-2.0/* * KUnit tests * * Copyright (C) 2020, Intel Corporation * Author: Mika Westerberg <mika.westerberg@linux.intel.com> */ #include <kunit/test.h>#include <linux/idr.h> #include "tb.h"#include "tunnel.h" static int __ida_init(struct kunit_resource *res, void *context){ struct ida *ida = context; ida_init(ida); res->data = ida; return 0;} static void __ida_destroy(struct kunit_resource *res){ struct ida *ida = res->data; ida_destroy(ida);} static void kunit_ida_init(struct kunit *test, struct ida *ida){ kunit_alloc_resource(test, __ida_init, __ida_destroy, GFP_KERNEL, ida);} static struct tb_switch *alloc_switch(struct kunit *test, u64 route, u8 upstream_port, u8 max_port_number){ struct tb_switch *sw; size_t size; int i; sw = kunit_kzalloc(test, sizeof(*sw), GFP_KERNEL); if (!sw) return NULL; sw->config.upstream_port_number = upstream_port; sw->config.depth = tb_route_length(route); sw->config.route_hi = upper_32_bits(route); sw->config.route_lo = lower_32_bits(route); sw->config.enabled = 0; sw->config.max_port_number = max_port_number; size = (sw->config.max_port_number + 1) * sizeof(*sw->ports); sw->ports = kunit_kzalloc(test, size, GFP_KERNEL); if (!sw->ports) return NULL; for (i = 0; i <= sw->config.max_port_number; i++) { sw->ports[i].sw = sw; sw->ports[i].port = i; sw->ports[i].config.port_number = i; if (i) { kunit_ida_init(test, &sw->ports[i].in_hopids); kunit_ida_init(test, &sw->ports[i].out_hopids); } } return sw;} static struct tb_switch *alloc_host(struct kunit *test){ struct tb_switch *sw; sw = alloc_switch(test, 0, 7, 13); if (!sw) return NULL; sw->config.vendor_id = 0x8086; sw->config.device_id = 0x9a1b; sw->ports[0].config.type = TB_TYPE_PORT; sw->ports[0].config.max_in_hop_id = 7; sw->ports[0].config.max_out_hop_id = 7; sw->ports[1].config.type = TB_TYPE_PORT; sw->ports[1].config.max_in_hop_id = 19; sw->ports[1].config.max_out_hop_id = 19; sw->ports[1].total_credits = 60; sw->ports[1].ctl_credits = 2; sw->ports[1].dual_link_port = &sw->ports[2]; sw->ports[2].config.type = TB_TYPE_PORT; sw->ports[2].config.max_in_hop_id = 19; sw->ports[2].config.max_out_hop_id = 19; sw->ports[2].total_credits = 60; sw->ports[2].ctl_credits = 2; sw->ports[2].dual_link_port = &sw->ports[1]; sw->ports[2].link_nr = 1; sw->ports[3].config.type = TB_TYPE_PORT; sw->ports[3].config.max_in_hop_id = 19; sw->ports[3].config.max_out_hop_id = 19; sw->ports[3].total_credits = 60; sw->ports[3].ctl_credits = 2; sw->ports[3].dual_link_port = &sw->ports[4]; sw->ports[4].config.type = TB_TYPE_PORT; sw->ports[4].config.max_in_hop_id = 19; sw->ports[4].config.max_out_hop_id = 19; sw->ports[4].total_credits = 60; sw->ports[4].ctl_credits = 2; sw->ports[4].dual_link_port = &sw->ports[3]; sw->ports[4].link_nr = 1; sw->ports[5].config.type = TB_TYPE_DP_HDMI_IN; sw->ports[5].config.max_in_hop_id = 9; sw->ports[5].config.max_out_hop_id = 9; sw->ports[5].cap_adap = -1; sw->ports[6].config.type = TB_TYPE_DP_HDMI_IN; sw->ports[6].config.max_in_hop_id = 9; sw->ports[6].config.max_out_hop_id = 9; sw->ports[6].cap_adap = -1; 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; sw->ports[8].config.max_out_hop_id = 8; sw->ports[9].config.type = TB_TYPE_PCIE_DOWN; sw->ports[9].config.max_in_hop_id = 8; sw->ports[9].config.max_out_hop_id = 8; sw->ports[10].disabled = true; sw->ports[11].disabled = true; sw->ports[12].config.type = TB_TYPE_USB3_DOWN; sw->ports[12].config.max_in_hop_id = 8; sw->ports[12].config.max_out_hop_id = 8; sw->ports[13].config.type = TB_TYPE_USB3_DOWN; sw->ports[13].config.max_in_hop_id = 8; sw->ports[13].config.max_out_hop_id = 8; return sw;} static struct tb_switch *alloc_host_usb4(struct kunit *test){ struct tb_switch *sw; sw = alloc_host(test); if (!sw) return NULL; sw->generation = 4; sw->credit_allocation = true; sw->max_usb3_credits = 32; sw->min_dp_aux_credits = 1; sw->min_dp_main_credits = 0; sw->max_pcie_credits = 64; sw->max_dma_credits = 14; return sw;} static struct tb_switch *alloc_host_br(struct kunit *test){ struct tb_switch *sw; sw = alloc_host_usb4(test); if (!sw) return NULL; sw->ports[10].config.type = TB_TYPE_DP_HDMI_IN; sw->ports[10].config.max_in_hop_id = 9; sw->ports[10].config.max_out_hop_id = 9; sw->ports[10].cap_adap = -1; sw->ports[10].disabled = false; return sw;} static struct tb_switch *alloc_dev_default(struct kunit *test, struct tb_switch *parent, u64 route, bool bonded){ struct tb_port *port, *upstream_port; struct tb_switch *sw; sw = alloc_switch(test, route, 1, 19); if (!sw) return NULL; sw->config.vendor_id = 0x8086; sw->config.device_id = 0x15ef; sw->ports[0].config.type = TB_TYPE_PORT; sw->ports[0].config.max_in_hop_id = 8; sw->ports[0].config.max_out_hop_id = 8; sw->ports[1].config.type = TB_TYPE_PORT; sw->ports[1].config.max_in_hop_id = 19; sw->ports[1].config.max_out_hop_id = 19; sw->ports[1].total_credits = 60; sw->ports[1].ctl_credits = 2; sw->ports[1].dual_link_port = &sw->ports[2]; sw->ports[2].config.type = TB_TYPE_PORT; sw->ports[2].config.max_in_hop_id = 19; sw->ports[2].config.max_out_hop_id = 19; sw->ports[2].total_credits = 60; sw->ports[2].ctl_credits = 2; sw->ports[2].dual_link_port = &sw->ports[1]; sw->ports[2].link_nr = 1; sw->ports[3].config.type = TB_TYPE_PORT; sw->ports[3].config.max_in_hop_id = 19; sw->ports[3].config.max_out_hop_id = 19; sw->ports[3].total_credits = 60; sw->ports[3].ctl_credits = 2; sw->ports[3].dual_link_port = &sw->ports[4]; sw->ports[4].config.type = TB_TYPE_PORT; sw->ports[4].config.max_in_hop_id = 19; sw->ports[4].config.max_out_hop_id = 19; sw->ports[4].total_credits = 60; sw->ports[4].ctl_credits = 2; sw->ports[4].dual_link_port = &sw->ports[3]; sw->ports[4].link_nr = 1; sw->ports[5].config.type = TB_TYPE_PORT; sw->ports[5].config.max_in_hop_id = 19; sw->ports[5].config.max_out_hop_id = 19; sw->ports[5].total_credits = 60; sw->ports[5].ctl_credits = 2; sw->ports[5].dual_link_port = &sw->ports[6]; sw->ports[6].config.type = TB_TYPE_PORT; sw->ports[6].config.max_in_hop_id = 19; sw->ports[6].config.max_out_hop_id = 19; sw->ports[6].total_credits = 60; sw->ports[6].ctl_credits = 2; sw->ports[6].dual_link_port = &sw->ports[5]; sw->ports[6].link_nr = 1; sw->ports[7].config.type = TB_TYPE_PORT; sw->ports[7].config.max_in_hop_id = 19; sw->ports[7].config.max_out_hop_id = 19; sw->ports[7].total_credits = 60; sw->ports[7].ctl_credits = 2; sw->ports[7].dual_link_port = &sw->ports[8]; sw->ports[8].config.type = TB_TYPE_PORT; sw->ports[8].config.max_in_hop_id = 19; sw->ports[8].config.max_out_hop_id = 19; sw->ports[8].total_credits = 60; sw->ports[8].ctl_credits = 2; sw->ports[8].dual_link_port = &sw->ports[7]; sw->ports[8].link_nr = 1; sw->ports[9].config.type = TB_TYPE_PCIE_UP; sw->ports[9].config.max_in_hop_id = 8; sw->ports[9].config.max_out_hop_id = 8; sw->ports[10].config.type = TB_TYPE_PCIE_DOWN; sw->ports[10].config.max_in_hop_id = 8; sw->ports[10].config.max_out_hop_id = 8; sw->ports[11].config.type = TB_TYPE_PCIE_DOWN; sw->ports[11].config.max_in_hop_id = 8; sw->ports[11].config.max_out_hop_id = 8; sw->ports[12].config.type = TB_TYPE_PCIE_DOWN; sw->ports[12].config.max_in_hop_id = 8; sw->ports[12].config.max_out_hop_id = 8; sw->ports[13].config.type = TB_TYPE_DP_HDMI_OUT; sw->ports[13].config.max_in_hop_id = 9; sw->ports[13].config.max_out_hop_id = 9; sw->ports[13].cap_adap = -1; sw->ports[14].config.type = TB_TYPE_DP_HDMI_OUT; sw->ports[14].config.max_in_hop_id = 9; sw->ports[14].config.max_out_hop_id = 9; sw->ports[14].cap_adap = -1; sw->ports[15].disabled = true; sw->ports[16].config.type = TB_TYPE_USB3_UP; sw->ports[16].config.max_in_hop_id = 8; sw->ports[16].config.max_out_hop_id = 8; sw->ports[17].config.type = TB_TYPE_USB3_DOWN; sw->ports[17].config.max_in_hop_id = 8; sw->ports[17].config.max_out_hop_id = 8; sw->ports[18].config.type = TB_TYPE_USB3_DOWN; sw->ports[18].config.max_in_hop_id = 8; sw->ports[18].config.max_out_hop_id = 8; sw->ports[19].config.type = TB_TYPE_USB3_DOWN; sw->ports[19].config.max_in_hop_id = 8; sw->ports[19].config.max_out_hop_id = 8; if (!parent) return sw; /* Link them */ upstream_port = tb_upstream_port(sw); port = tb_port_at(route, parent); port->remote = upstream_port; upstream_port->remote = port; if (port->dual_link_port && upstream_port->dual_link_port) { port->dual_link_port->remote = upstream_port->dual_link_port; upstream_port->dual_link_port->remote = port->dual_link_port; if (bonded) { /* Bonding is used */ port->bonded = true; port->total_credits *= 2; port->dual_link_port->bonded = true; port->dual_link_port->total_credits = 0; upstream_port->bonded = true; upstream_port->total_credits *= 2; upstream_port->dual_link_port->bonded = true; upstream_port->dual_link_port->total_credits = 0; } } return sw;} static struct tb_switch *alloc_dev_with_dpin(struct kunit *test, struct tb_switch *parent, u64 route, bool bonded){ struct tb_switch *sw; sw = alloc_dev_default(test, parent, route, bonded); if (!sw) return NULL; sw->ports[13].config.type = TB_TYPE_DP_HDMI_IN; sw->ports[13].config.max_in_hop_id = 9; sw->ports[13].config.max_out_hop_id = 9; sw->ports[14].config.type = TB_TYPE_DP_HDMI_IN; sw->ports[14].config.max_in_hop_id = 9; sw->ports[14].config.max_out_hop_id = 9; return sw;} static struct tb_switch *alloc_dev_without_dp(struct kunit *test, struct tb_switch *parent, u64 route, bool bonded){ struct tb_switch *sw; int i; sw = alloc_dev_default(test, parent, route, bonded); if (!sw) return NULL; /* * Device with: * 2x USB4 Adapters (adapters 1,2 and 3,4), * 1x PCIe Upstream (adapter 9), * 1x PCIe Downstream (adapter 10), * 1x USB3 Upstream (adapter 16), * 1x USB3 Downstream (adapter 17) */ for (i = 5; i <= 8; i++) sw->ports[i].disabled = true; for (i = 11; i <= 14; i++) sw->ports[i].disabled = true; sw->ports[13].cap_adap = 0; sw->ports[14].cap_adap = 0; for (i = 18; i <= 19; i++) sw->ports[i].disabled = true; sw->generation = 4; sw->credit_allocation = true; sw->max_usb3_credits = 109; sw->min_dp_aux_credits = 0; sw->min_dp_main_credits = 0; sw->max_pcie_credits = 30; sw->max_dma_credits = 1; return sw;} static struct tb_switch *alloc_dev_usb4(struct kunit *test, struct tb_switch *parent, u64 route, bool bonded){ struct tb_switch *sw; sw = alloc_dev_default(test, parent, route, bonded); if (!sw) return NULL; sw->generation = 4; sw->credit_allocation = true; sw->max_usb3_credits = 14; sw->min_dp_aux_credits = 1; sw->min_dp_main_credits = 18; sw->max_pcie_credits = 32; sw->max_dma_credits = 14; return sw;} static void tb_test_path_basic(struct kunit *test){ struct tb_port *src_port, *dst_port, *p; struct tb_switch *host; host = alloc_host(test); src_port = &host->ports[5]; dst_port = src_port; p = tb_next_port_on_path(src_port, dst_port, NULL); KUNIT_EXPECT_PTR_EQ(test, p, dst_port); p = tb_next_port_on_path(src_port, dst_port, p); KUNIT_EXPECT_TRUE(test, !p);} static void tb_test_path_not_connected_walk(struct kunit *test){ struct tb_port *src_port, *dst_port, *p; struct tb_switch *host, *dev; host = alloc_host(test); /* No connection between host and dev */ dev = alloc_dev_default(test, NULL, 3, true); src_port = &host->ports[12]; dst_port = &dev->ports[16]; p = tb_next_port_on_path(src_port, dst_port, NULL); KUNIT_EXPECT_PTR_EQ(test, p, src_port); p = tb_next_port_on_path(src_port, dst_port, p); KUNIT_EXPECT_PTR_EQ(test, p, &host->ports[3]); p = tb_next_port_on_path(src_port, dst_port, p); KUNIT_EXPECT_TRUE(test, !p); /* Other direction */ p = tb_next_port_on_path(dst_port, src_port, NULL); KUNIT_EXPECT_PTR_EQ(test, p, dst_port); p = tb_next_port_on_path(dst_port, src_port, p); KUNIT_EXPECT_PTR_EQ(test, p, &dev->ports[1]); p = tb_next_port_on_path(dst_port, src_port, p); KUNIT_EXPECT_TRUE(test, !p);} struct port_expectation { u64 route; u8 port; enum tb_port_type type;}; static void tb_test_path_single_hop_walk(struct kunit *test){ /* * Walks from Host PCIe downstream port to Device #1 PCIe * upstream port. * * [Host] * 1 | * 1 | * [Device] */ static const struct port_expectation test_data[] = { { .route = 0x0, .port = 8, .type = TB_TYPE_PCIE_DOWN }, { .route = 0x0, .port = 1, .type = TB_TYPE_PORT }, { .route = 0x1, .port = 1, .type = TB_TYPE_PORT }, { .route = 0x1, .port = 9, .type = TB_TYPE_PCIE_UP }, }; struct tb_port *src_port, *dst_port, *p; struct tb_switch *host, *dev; int i; host = alloc_host(test);Lines 1–500 of 3152. Load more
// SPDX-License-Identifier: GPL-2.0 /* * KUnit tests * * Copyright (C) 2020, Intel Corporation * Author: Mika Westerberg <mika.westerberg@linux.intel.com> */ #include <kunit/test.h> #include <linux/idr.h> #include "tb.h" #include "tunnel.h" static int __ida_init(struct kunit_resource *res, void *context) { struct ida *ida = context; ida_init(ida); res->data = ida; return 0; } static void __ida_destroy(struct kunit_resource *res) { struct ida *ida = res->data; ida_destroy(ida); } static void kunit_ida_init(struct kunit *test, struct ida *ida) { kunit_alloc_resource(test, __ida_init, __ida_destroy, GFP_KERNEL, ida); } static struct tb_switch *alloc_switch(struct kunit *test, u64 route, u8 upstream_port, u8 max_port_number) { struct tb_switch *sw; size_t size; int i; sw = kunit_kzalloc(test, sizeof(*sw), GFP_KERNEL); if (!sw) return NULL; sw->config.upstream_port_number = upstream_port; sw->config.depth = tb_route_length(route); sw->config.route_hi = upper_32_bits(route); sw->config.route_lo = lower_32_bits(route); sw->config.enabled = 0; sw->config.max_port_number = max_port_number; size = (sw->config.max_port_number + 1) * sizeof(*sw->ports); sw->ports = kunit_kzalloc(test, size, GFP_KERNEL); if (!sw->ports) return NULL; for (i = 0; i <= sw->config.max_port_number; i++) { sw->ports[i].sw = sw; sw->ports[i].port = i; sw->ports[i].config.port_number = i; if (i) { kunit_ida_init(test, &sw->ports[i].in_hopids); kunit_ida_init(test, &sw->ports[i].out_hopids); } } return sw; } static struct tb_switch *alloc_host(struct kunit *test) { struct tb_switch *sw; sw = alloc_switch(test, 0, 7, 13); if (!sw) return NULL; sw->config.vendor_id = 0x8086; sw->config.device_id = 0x9a1b; sw->ports[0].config.type = TB_TYPE_PORT; sw->ports[0].config.max_in_hop_id = 7; sw->ports[0].config.max_out_hop_id = 7; sw->ports[1].config.type = TB_TYPE_PORT; sw->ports[1].config.max_in_hop_id = 19; sw->ports[1].config.max_out_hop_id = 19; sw->ports[1].total_credits = 60; sw->ports[1].ctl_credits = 2; sw->ports[1].dual_link_port = &sw->ports[2]; sw->ports[2].config.type = TB_TYPE_PORT; sw->ports[2].config.max_in_hop_id = 19; sw->ports[2].config.max_out_hop_id = 19; sw->ports[2].total_credits = 60; sw->ports[2].ctl_credits = 2; sw->ports[2].dual_link_port = &sw->ports[1]; sw->ports[2].link_nr = 1; sw->ports[3].config.type = TB_TYPE_PORT; sw->ports[3].config.max_in_hop_id = 19; sw->ports[3].config.max_out_hop_id = 19; sw->ports[3].total_credits = 60; sw->ports[3].ctl_credits = 2; sw->ports[3].dual_link_port = &sw->ports[4]; sw->ports[4].config.type = TB_TYPE_PORT; sw->ports[4].config.max_in_hop_id = 19; sw->ports[4].config.max_out_hop_id = 19; sw->ports[4].total_credits = 60; sw->ports[4].ctl_credits = 2; sw->ports[4].dual_link_port = &sw->ports[3]; sw->ports[4].link_nr = 1; sw->ports[5].config.type = TB_TYPE_DP_HDMI_IN; sw->ports[5].config.max_in_hop_id = 9; sw->ports[5].config.max_out_hop_id = 9; sw->ports[5].cap_adap = -1; sw->ports[6].config.type = TB_TYPE_DP_HDMI_IN; sw->ports[6].config.max_in_hop_id = 9; sw->ports[6].config.max_out_hop_id = 9; sw->ports[6].cap_adap = -1; 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; sw->ports[8].config.max_out_hop_id = 8; sw->ports[9].config.type = TB_TYPE_PCIE_DOWN; sw->ports[9].config.max_in_hop_id = 8; sw->ports[9].config.max_out_hop_id = 8; sw->ports[10].disabled = true; sw->ports[11].disabled = true; sw->ports[12].config.type = TB_TYPE_USB3_DOWN; sw->ports[12].config.max_in_hop_id = 8; sw->ports[12].config.max_out_hop_id = 8; sw->ports[13].config.type = TB_TYPE_USB3_DOWN; sw->ports[13].config.max_in_hop_id = 8; sw->ports[13].config.max_out_hop_id = 8; return sw; } static struct tb_switch *alloc_host_usb4(struct kunit *test) { struct tb_switch *sw; sw = alloc_host(test); if (!sw) return NULL; sw->generation = 4; sw->credit_allocation = true; sw->max_usb3_credits = 32; sw->min_dp_aux_credits = 1; sw->min_dp_main_credits = 0; sw->max_pcie_credits = 64; sw->max_dma_credits = 14; return sw; } static struct tb_switch *alloc_host_br(struct kunit *test) { struct tb_switch *sw; sw = alloc_host_usb4(test); if (!sw) return NULL; sw->ports[10].config.type = TB_TYPE_DP_HDMI_IN; sw->ports[10].config.max_in_hop_id = 9; sw->ports[10].config.max_out_hop_id = 9; sw->ports[10].cap_adap = -1; sw->ports[10].disabled = false; return sw; } static struct tb_switch *alloc_dev_default(struct kunit *test, struct tb_switch *parent, u64 route, bool bonded) { struct tb_port *port, *upstream_port; struct tb_switch *sw; sw = alloc_switch(test, route, 1, 19); if (!sw) return NULL; sw->config.vendor_id = 0x8086; sw->config.device_id = 0x15ef; sw->ports[0].config.type = TB_TYPE_PORT; sw->ports[0].config.max_in_hop_id = 8; sw->ports[0].config.max_out_hop_id = 8; sw->ports[1].config.type = TB_TYPE_PORT; sw->ports[1].config.max_in_hop_id = 19; sw->ports[1].config.max_out_hop_id = 19; sw->ports[1].total_credits = 60; sw->ports[1].ctl_credits = 2; sw->ports[1].dual_link_port = &sw->ports[2]; sw->ports[2].config.type = TB_TYPE_PORT; sw->ports[2].config.max_in_hop_id = 19; sw->ports[2].config.max_out_hop_id = 19; sw->ports[2].total_credits = 60; sw->ports[2].ctl_credits = 2; sw->ports[2].dual_link_port = &sw->ports[1]; sw->ports[2].link_nr = 1; sw->ports[3].config.type = TB_TYPE_PORT; sw->ports[3].config.max_in_hop_id = 19; sw->ports[3].config.max_out_hop_id = 19; sw->ports[3].total_credits = 60; sw->ports[3].ctl_credits = 2; sw->ports[3].dual_link_port = &sw->ports[4]; sw->ports[4].config.type = TB_TYPE_PORT; sw->ports[4].config.max_in_hop_id = 19; sw->ports[4].config.max_out_hop_id = 19; sw->ports[4].total_credits = 60; sw->ports[4].ctl_credits = 2; sw->ports[4].dual_link_port = &sw->ports[3]; sw->ports[4].link_nr = 1; sw->ports[5].config.type = TB_TYPE_PORT; sw->ports[5].config.max_in_hop_id = 19; sw->ports[5].config.max_out_hop_id = 19; sw->ports[5].total_credits = 60; sw->ports[5].ctl_credits = 2; sw->ports[5].dual_link_port = &sw->ports[6]; sw->ports[6].config.type = TB_TYPE_PORT; sw->ports[6].config.max_in_hop_id = 19; sw->ports[6].config.max_out_hop_id = 19; sw->ports[6].total_credits = 60; sw->ports[6].ctl_credits = 2; sw->ports[6].dual_link_port = &sw->ports[5]; sw->ports[6].link_nr = 1; sw->ports[7].config.type = TB_TYPE_PORT; sw->ports[7].config.max_in_hop_id = 19; sw->ports[7].config.max_out_hop_id = 19; sw->ports[7].total_credits = 60; sw->ports[7].ctl_credits = 2; sw->ports[7].dual_link_port = &sw->ports[8]; sw->ports[8].config.type = TB_TYPE_PORT; sw->ports[8].config.max_in_hop_id = 19; sw->ports[8].config.max_out_hop_id = 19; sw->ports[8].total_credits = 60; sw->ports[8].ctl_credits = 2; sw->ports[8].dual_link_port = &sw->ports[7]; sw->ports[8].link_nr = 1; sw->ports[9].config.type = TB_TYPE_PCIE_UP; sw->ports[9].config.max_in_hop_id = 8; sw->ports[9].config.max_out_hop_id = 8; sw->ports[10].config.type = TB_TYPE_PCIE_DOWN; sw->ports[10].config.max_in_hop_id = 8; sw->ports[10].config.max_out_hop_id = 8; sw->ports[11].config.type = TB_TYPE_PCIE_DOWN; sw->ports[11].config.max_in_hop_id = 8; sw->ports[11].config.max_out_hop_id = 8; sw->ports[12].config.type = TB_TYPE_PCIE_DOWN; sw->ports[12].config.max_in_hop_id = 8; sw->ports[12].config.max_out_hop_id = 8; sw->ports[13].config.type = TB_TYPE_DP_HDMI_OUT; sw->ports[13].config.max_in_hop_id = 9; sw->ports[13].config.max_out_hop_id = 9; sw->ports[13].cap_adap = -1; sw->ports[14].config.type = TB_TYPE_DP_HDMI_OUT; sw->ports[14].config.max_in_hop_id = 9; sw->ports[14].config.max_out_hop_id = 9; sw->ports[14].cap_adap = -1; sw->ports[15].disabled = true; sw->ports[16].config.type = TB_TYPE_USB3_UP; sw->ports[16].config.max_in_hop_id = 8; sw->ports[16].config.max_out_hop_id = 8; sw->ports[17].config.type = TB_TYPE_USB3_DOWN; sw->ports[17].config.max_in_hop_id = 8; sw->ports[17].config.max_out_hop_id = 8; sw->ports[18].config.type = TB_TYPE_USB3_DOWN; sw->ports[18].config.max_in_hop_id = 8; sw->ports[18].config.max_out_hop_id = 8; sw->ports[19].config.type = TB_TYPE_USB3_DOWN; sw->ports[19].config.max_in_hop_id = 8; sw->ports[19].config.max_out_hop_id = 8; if (!parent) return sw; /* Link them */ upstream_port = tb_upstream_port(sw); port = tb_port_at(route, parent); port->remote = upstream_port; upstream_port->remote = port; if (port->dual_link_port && upstream_port->dual_link_port) { port->dual_link_port->remote = upstream_port->dual_link_port; upstream_port->dual_link_port->remote = port->dual_link_port; if (bonded) { /* Bonding is used */ port->bonded = true; port->total_credits *= 2; port->dual_link_port->bonded = true; port->dual_link_port->total_credits = 0; upstream_port->bonded = true; upstream_port->total_credits *= 2; upstream_port->dual_link_port->bonded = true; upstream_port->dual_link_port->total_credits = 0; } } return sw; } static struct tb_switch *alloc_dev_with_dpin(struct kunit *test, struct tb_switch *parent, u64 route, bool bonded) { struct tb_switch *sw; sw = alloc_dev_default(test, parent, route, bonded); if (!sw) return NULL; sw->ports[13].config.type = TB_TYPE_DP_HDMI_IN; sw->ports[13].config.max_in_hop_id = 9; sw->ports[13].config.max_out_hop_id = 9; sw->ports[14].config.type = TB_TYPE_DP_HDMI_IN; sw->ports[14].config.max_in_hop_id = 9; sw->ports[14].config.max_out_hop_id = 9; return sw; } static struct tb_switch *alloc_dev_without_dp(struct kunit *test, struct tb_switch *parent, u64 route, bool bonded) { struct tb_switch *sw; int i; sw = alloc_dev_default(test, parent, route, bonded); if (!sw) return NULL; /* * Device with: * 2x USB4 Adapters (adapters 1,2 and 3,4), * 1x PCIe Upstream (adapter 9), * 1x PCIe Downstream (adapter 10), * 1x USB3 Upstream (adapter 16), * 1x USB3 Downstream (adapter 17) */ for (i = 5; i <= 8; i++) sw->ports[i].disabled = true; for (i = 11; i <= 14; i++) sw->ports[i].disabled = true; sw->ports[13].cap_adap = 0; sw->ports[14].cap_adap = 0; for (i = 18; i <= 19; i++) sw->ports[i].disabled = true; sw->generation = 4; sw->credit_allocation = true; sw->max_usb3_credits = 109; sw->min_dp_aux_credits = 0; sw->min_dp_main_credits = 0; sw->max_pcie_credits = 30; sw->max_dma_credits = 1; return sw; } static struct tb_switch *alloc_dev_usb4(struct kunit *test, struct tb_switch *parent, u64 route, bool bonded) { struct tb_switch *sw; sw = alloc_dev_default(test, parent, route, bonded); if (!sw) return NULL; sw->generation = 4; sw->credit_allocation = true; sw->max_usb3_credits = 14; sw->min_dp_aux_credits = 1; sw->min_dp_main_credits = 18; sw->max_pcie_credits = 32; sw->max_dma_credits = 14; return sw; } static void tb_test_path_basic(struct kunit *test) { struct tb_port *src_port, *dst_port, *p; struct tb_switch *host; host = alloc_host(test); src_port = &host->ports[5]; dst_port = src_port; p = tb_next_port_on_path(src_port, dst_port, NULL); KUNIT_EXPECT_PTR_EQ(test, p, dst_port); p = tb_next_port_on_path(src_port, dst_port, p); KUNIT_EXPECT_TRUE(test, !p); } static void tb_test_path_not_connected_walk(struct kunit *test) { struct tb_port *src_port, *dst_port, *p; struct tb_switch *host, *dev; host = alloc_host(test); /* No connection between host and dev */ dev = alloc_dev_default(test, NULL, 3, true); src_port = &host->ports[12]; dst_port = &dev->ports[16]; p = tb_next_port_on_path(src_port, dst_port, NULL); KUNIT_EXPECT_PTR_EQ(test, p, src_port); p = tb_next_port_on_path(src_port, dst_port, p); KUNIT_EXPECT_PTR_EQ(test, p, &host->ports[3]); p = tb_next_port_on_path(src_port, dst_port, p); KUNIT_EXPECT_TRUE(test, !p); /* Other direction */ p = tb_next_port_on_path(dst_port, src_port, NULL); KUNIT_EXPECT_PTR_EQ(test, p, dst_port); p = tb_next_port_on_path(dst_port, src_port, p); KUNIT_EXPECT_PTR_EQ(test, p, &dev->ports[1]); p = tb_next_port_on_path(dst_port, src_port, p); KUNIT_EXPECT_TRUE(test, !p); } struct port_expectation { u64 route; u8 port; enum tb_port_type type; }; static void tb_test_path_single_hop_walk(struct kunit *test) { /* * Walks from Host PCIe downstream port to Device #1 PCIe * upstream port. * * [Host] * 1 | * 1 | * [Device] */ static const struct port_expectation test_data[] = { { .route = 0x0, .port = 8, .type = TB_TYPE_PCIE_DOWN }, { .route = 0x0, .port = 1, .type = TB_TYPE_PORT }, { .route = 0x1, .port = 1, .type = TB_TYPE_PORT }, { .route = 0x1, .port = 9, .type = TB_TYPE_PCIE_UP }, }; struct tb_port *src_port, *dst_port, *p; struct tb_switch *host, *dev; int i; host = alloc_host(test);