162306a36Sopenharmony_ci// SPDX-License-Identifier: GPL-2.0 262306a36Sopenharmony_ci/* 362306a36Sopenharmony_ci * KUnit tests 462306a36Sopenharmony_ci * 562306a36Sopenharmony_ci * Copyright (C) 2020, Intel Corporation 662306a36Sopenharmony_ci * Author: Mika Westerberg <mika.westerberg@linux.intel.com> 762306a36Sopenharmony_ci */ 862306a36Sopenharmony_ci 962306a36Sopenharmony_ci#include <kunit/test.h> 1062306a36Sopenharmony_ci#include <linux/idr.h> 1162306a36Sopenharmony_ci 1262306a36Sopenharmony_ci#include "tb.h" 1362306a36Sopenharmony_ci#include "tunnel.h" 1462306a36Sopenharmony_ci 1562306a36Sopenharmony_cistatic int __ida_init(struct kunit_resource *res, void *context) 1662306a36Sopenharmony_ci{ 1762306a36Sopenharmony_ci struct ida *ida = context; 1862306a36Sopenharmony_ci 1962306a36Sopenharmony_ci ida_init(ida); 2062306a36Sopenharmony_ci res->data = ida; 2162306a36Sopenharmony_ci return 0; 2262306a36Sopenharmony_ci} 2362306a36Sopenharmony_ci 2462306a36Sopenharmony_cistatic void __ida_destroy(struct kunit_resource *res) 2562306a36Sopenharmony_ci{ 2662306a36Sopenharmony_ci struct ida *ida = res->data; 2762306a36Sopenharmony_ci 2862306a36Sopenharmony_ci ida_destroy(ida); 2962306a36Sopenharmony_ci} 3062306a36Sopenharmony_ci 3162306a36Sopenharmony_cistatic void kunit_ida_init(struct kunit *test, struct ida *ida) 3262306a36Sopenharmony_ci{ 3362306a36Sopenharmony_ci kunit_alloc_resource(test, __ida_init, __ida_destroy, GFP_KERNEL, ida); 3462306a36Sopenharmony_ci} 3562306a36Sopenharmony_ci 3662306a36Sopenharmony_cistatic struct tb_switch *alloc_switch(struct kunit *test, u64 route, 3762306a36Sopenharmony_ci u8 upstream_port, u8 max_port_number) 3862306a36Sopenharmony_ci{ 3962306a36Sopenharmony_ci struct tb_switch *sw; 4062306a36Sopenharmony_ci size_t size; 4162306a36Sopenharmony_ci int i; 4262306a36Sopenharmony_ci 4362306a36Sopenharmony_ci sw = kunit_kzalloc(test, sizeof(*sw), GFP_KERNEL); 4462306a36Sopenharmony_ci if (!sw) 4562306a36Sopenharmony_ci return NULL; 4662306a36Sopenharmony_ci 4762306a36Sopenharmony_ci sw->config.upstream_port_number = upstream_port; 4862306a36Sopenharmony_ci sw->config.depth = tb_route_length(route); 4962306a36Sopenharmony_ci sw->config.route_hi = upper_32_bits(route); 5062306a36Sopenharmony_ci sw->config.route_lo = lower_32_bits(route); 5162306a36Sopenharmony_ci sw->config.enabled = 0; 5262306a36Sopenharmony_ci sw->config.max_port_number = max_port_number; 5362306a36Sopenharmony_ci 5462306a36Sopenharmony_ci size = (sw->config.max_port_number + 1) * sizeof(*sw->ports); 5562306a36Sopenharmony_ci sw->ports = kunit_kzalloc(test, size, GFP_KERNEL); 5662306a36Sopenharmony_ci if (!sw->ports) 5762306a36Sopenharmony_ci return NULL; 5862306a36Sopenharmony_ci 5962306a36Sopenharmony_ci for (i = 0; i <= sw->config.max_port_number; i++) { 6062306a36Sopenharmony_ci sw->ports[i].sw = sw; 6162306a36Sopenharmony_ci sw->ports[i].port = i; 6262306a36Sopenharmony_ci sw->ports[i].config.port_number = i; 6362306a36Sopenharmony_ci if (i) { 6462306a36Sopenharmony_ci kunit_ida_init(test, &sw->ports[i].in_hopids); 6562306a36Sopenharmony_ci kunit_ida_init(test, &sw->ports[i].out_hopids); 6662306a36Sopenharmony_ci } 6762306a36Sopenharmony_ci } 6862306a36Sopenharmony_ci 6962306a36Sopenharmony_ci return sw; 7062306a36Sopenharmony_ci} 7162306a36Sopenharmony_ci 7262306a36Sopenharmony_cistatic struct tb_switch *alloc_host(struct kunit *test) 7362306a36Sopenharmony_ci{ 7462306a36Sopenharmony_ci struct tb_switch *sw; 7562306a36Sopenharmony_ci 7662306a36Sopenharmony_ci sw = alloc_switch(test, 0, 7, 13); 7762306a36Sopenharmony_ci if (!sw) 7862306a36Sopenharmony_ci return NULL; 7962306a36Sopenharmony_ci 8062306a36Sopenharmony_ci sw->config.vendor_id = 0x8086; 8162306a36Sopenharmony_ci sw->config.device_id = 0x9a1b; 8262306a36Sopenharmony_ci 8362306a36Sopenharmony_ci sw->ports[0].config.type = TB_TYPE_PORT; 8462306a36Sopenharmony_ci sw->ports[0].config.max_in_hop_id = 7; 8562306a36Sopenharmony_ci sw->ports[0].config.max_out_hop_id = 7; 8662306a36Sopenharmony_ci 8762306a36Sopenharmony_ci sw->ports[1].config.type = TB_TYPE_PORT; 8862306a36Sopenharmony_ci sw->ports[1].config.max_in_hop_id = 19; 8962306a36Sopenharmony_ci sw->ports[1].config.max_out_hop_id = 19; 9062306a36Sopenharmony_ci sw->ports[1].total_credits = 60; 9162306a36Sopenharmony_ci sw->ports[1].ctl_credits = 2; 9262306a36Sopenharmony_ci sw->ports[1].dual_link_port = &sw->ports[2]; 9362306a36Sopenharmony_ci 9462306a36Sopenharmony_ci sw->ports[2].config.type = TB_TYPE_PORT; 9562306a36Sopenharmony_ci sw->ports[2].config.max_in_hop_id = 19; 9662306a36Sopenharmony_ci sw->ports[2].config.max_out_hop_id = 19; 9762306a36Sopenharmony_ci sw->ports[2].total_credits = 60; 9862306a36Sopenharmony_ci sw->ports[2].ctl_credits = 2; 9962306a36Sopenharmony_ci sw->ports[2].dual_link_port = &sw->ports[1]; 10062306a36Sopenharmony_ci sw->ports[2].link_nr = 1; 10162306a36Sopenharmony_ci 10262306a36Sopenharmony_ci sw->ports[3].config.type = TB_TYPE_PORT; 10362306a36Sopenharmony_ci sw->ports[3].config.max_in_hop_id = 19; 10462306a36Sopenharmony_ci sw->ports[3].config.max_out_hop_id = 19; 10562306a36Sopenharmony_ci sw->ports[3].total_credits = 60; 10662306a36Sopenharmony_ci sw->ports[3].ctl_credits = 2; 10762306a36Sopenharmony_ci sw->ports[3].dual_link_port = &sw->ports[4]; 10862306a36Sopenharmony_ci 10962306a36Sopenharmony_ci sw->ports[4].config.type = TB_TYPE_PORT; 11062306a36Sopenharmony_ci sw->ports[4].config.max_in_hop_id = 19; 11162306a36Sopenharmony_ci sw->ports[4].config.max_out_hop_id = 19; 11262306a36Sopenharmony_ci sw->ports[4].total_credits = 60; 11362306a36Sopenharmony_ci sw->ports[4].ctl_credits = 2; 11462306a36Sopenharmony_ci sw->ports[4].dual_link_port = &sw->ports[3]; 11562306a36Sopenharmony_ci sw->ports[4].link_nr = 1; 11662306a36Sopenharmony_ci 11762306a36Sopenharmony_ci sw->ports[5].config.type = TB_TYPE_DP_HDMI_IN; 11862306a36Sopenharmony_ci sw->ports[5].config.max_in_hop_id = 9; 11962306a36Sopenharmony_ci sw->ports[5].config.max_out_hop_id = 9; 12062306a36Sopenharmony_ci sw->ports[5].cap_adap = -1; 12162306a36Sopenharmony_ci 12262306a36Sopenharmony_ci sw->ports[6].config.type = TB_TYPE_DP_HDMI_IN; 12362306a36Sopenharmony_ci sw->ports[6].config.max_in_hop_id = 9; 12462306a36Sopenharmony_ci sw->ports[6].config.max_out_hop_id = 9; 12562306a36Sopenharmony_ci sw->ports[6].cap_adap = -1; 12662306a36Sopenharmony_ci 12762306a36Sopenharmony_ci sw->ports[7].config.type = TB_TYPE_NHI; 12862306a36Sopenharmony_ci sw->ports[7].config.max_in_hop_id = 11; 12962306a36Sopenharmony_ci sw->ports[7].config.max_out_hop_id = 11; 13062306a36Sopenharmony_ci sw->ports[7].config.nfc_credits = 0x41800000; 13162306a36Sopenharmony_ci 13262306a36Sopenharmony_ci sw->ports[8].config.type = TB_TYPE_PCIE_DOWN; 13362306a36Sopenharmony_ci sw->ports[8].config.max_in_hop_id = 8; 13462306a36Sopenharmony_ci sw->ports[8].config.max_out_hop_id = 8; 13562306a36Sopenharmony_ci 13662306a36Sopenharmony_ci sw->ports[9].config.type = TB_TYPE_PCIE_DOWN; 13762306a36Sopenharmony_ci sw->ports[9].config.max_in_hop_id = 8; 13862306a36Sopenharmony_ci sw->ports[9].config.max_out_hop_id = 8; 13962306a36Sopenharmony_ci 14062306a36Sopenharmony_ci sw->ports[10].disabled = true; 14162306a36Sopenharmony_ci sw->ports[11].disabled = true; 14262306a36Sopenharmony_ci 14362306a36Sopenharmony_ci sw->ports[12].config.type = TB_TYPE_USB3_DOWN; 14462306a36Sopenharmony_ci sw->ports[12].config.max_in_hop_id = 8; 14562306a36Sopenharmony_ci sw->ports[12].config.max_out_hop_id = 8; 14662306a36Sopenharmony_ci 14762306a36Sopenharmony_ci sw->ports[13].config.type = TB_TYPE_USB3_DOWN; 14862306a36Sopenharmony_ci sw->ports[13].config.max_in_hop_id = 8; 14962306a36Sopenharmony_ci sw->ports[13].config.max_out_hop_id = 8; 15062306a36Sopenharmony_ci 15162306a36Sopenharmony_ci return sw; 15262306a36Sopenharmony_ci} 15362306a36Sopenharmony_ci 15462306a36Sopenharmony_cistatic struct tb_switch *alloc_host_usb4(struct kunit *test) 15562306a36Sopenharmony_ci{ 15662306a36Sopenharmony_ci struct tb_switch *sw; 15762306a36Sopenharmony_ci 15862306a36Sopenharmony_ci sw = alloc_host(test); 15962306a36Sopenharmony_ci if (!sw) 16062306a36Sopenharmony_ci return NULL; 16162306a36Sopenharmony_ci 16262306a36Sopenharmony_ci sw->generation = 4; 16362306a36Sopenharmony_ci sw->credit_allocation = true; 16462306a36Sopenharmony_ci sw->max_usb3_credits = 32; 16562306a36Sopenharmony_ci sw->min_dp_aux_credits = 1; 16662306a36Sopenharmony_ci sw->min_dp_main_credits = 0; 16762306a36Sopenharmony_ci sw->max_pcie_credits = 64; 16862306a36Sopenharmony_ci sw->max_dma_credits = 14; 16962306a36Sopenharmony_ci 17062306a36Sopenharmony_ci return sw; 17162306a36Sopenharmony_ci} 17262306a36Sopenharmony_ci 17362306a36Sopenharmony_cistatic struct tb_switch *alloc_host_br(struct kunit *test) 17462306a36Sopenharmony_ci{ 17562306a36Sopenharmony_ci struct tb_switch *sw; 17662306a36Sopenharmony_ci 17762306a36Sopenharmony_ci sw = alloc_host_usb4(test); 17862306a36Sopenharmony_ci if (!sw) 17962306a36Sopenharmony_ci return NULL; 18062306a36Sopenharmony_ci 18162306a36Sopenharmony_ci sw->ports[10].config.type = TB_TYPE_DP_HDMI_IN; 18262306a36Sopenharmony_ci sw->ports[10].config.max_in_hop_id = 9; 18362306a36Sopenharmony_ci sw->ports[10].config.max_out_hop_id = 9; 18462306a36Sopenharmony_ci sw->ports[10].cap_adap = -1; 18562306a36Sopenharmony_ci sw->ports[10].disabled = false; 18662306a36Sopenharmony_ci 18762306a36Sopenharmony_ci return sw; 18862306a36Sopenharmony_ci} 18962306a36Sopenharmony_ci 19062306a36Sopenharmony_cistatic struct tb_switch *alloc_dev_default(struct kunit *test, 19162306a36Sopenharmony_ci struct tb_switch *parent, 19262306a36Sopenharmony_ci u64 route, bool bonded) 19362306a36Sopenharmony_ci{ 19462306a36Sopenharmony_ci struct tb_port *port, *upstream_port; 19562306a36Sopenharmony_ci struct tb_switch *sw; 19662306a36Sopenharmony_ci 19762306a36Sopenharmony_ci sw = alloc_switch(test, route, 1, 19); 19862306a36Sopenharmony_ci if (!sw) 19962306a36Sopenharmony_ci return NULL; 20062306a36Sopenharmony_ci 20162306a36Sopenharmony_ci sw->config.vendor_id = 0x8086; 20262306a36Sopenharmony_ci sw->config.device_id = 0x15ef; 20362306a36Sopenharmony_ci 20462306a36Sopenharmony_ci sw->ports[0].config.type = TB_TYPE_PORT; 20562306a36Sopenharmony_ci sw->ports[0].config.max_in_hop_id = 8; 20662306a36Sopenharmony_ci sw->ports[0].config.max_out_hop_id = 8; 20762306a36Sopenharmony_ci 20862306a36Sopenharmony_ci sw->ports[1].config.type = TB_TYPE_PORT; 20962306a36Sopenharmony_ci sw->ports[1].config.max_in_hop_id = 19; 21062306a36Sopenharmony_ci sw->ports[1].config.max_out_hop_id = 19; 21162306a36Sopenharmony_ci sw->ports[1].total_credits = 60; 21262306a36Sopenharmony_ci sw->ports[1].ctl_credits = 2; 21362306a36Sopenharmony_ci sw->ports[1].dual_link_port = &sw->ports[2]; 21462306a36Sopenharmony_ci 21562306a36Sopenharmony_ci sw->ports[2].config.type = TB_TYPE_PORT; 21662306a36Sopenharmony_ci sw->ports[2].config.max_in_hop_id = 19; 21762306a36Sopenharmony_ci sw->ports[2].config.max_out_hop_id = 19; 21862306a36Sopenharmony_ci sw->ports[2].total_credits = 60; 21962306a36Sopenharmony_ci sw->ports[2].ctl_credits = 2; 22062306a36Sopenharmony_ci sw->ports[2].dual_link_port = &sw->ports[1]; 22162306a36Sopenharmony_ci sw->ports[2].link_nr = 1; 22262306a36Sopenharmony_ci 22362306a36Sopenharmony_ci sw->ports[3].config.type = TB_TYPE_PORT; 22462306a36Sopenharmony_ci sw->ports[3].config.max_in_hop_id = 19; 22562306a36Sopenharmony_ci sw->ports[3].config.max_out_hop_id = 19; 22662306a36Sopenharmony_ci sw->ports[3].total_credits = 60; 22762306a36Sopenharmony_ci sw->ports[3].ctl_credits = 2; 22862306a36Sopenharmony_ci sw->ports[3].dual_link_port = &sw->ports[4]; 22962306a36Sopenharmony_ci 23062306a36Sopenharmony_ci sw->ports[4].config.type = TB_TYPE_PORT; 23162306a36Sopenharmony_ci sw->ports[4].config.max_in_hop_id = 19; 23262306a36Sopenharmony_ci sw->ports[4].config.max_out_hop_id = 19; 23362306a36Sopenharmony_ci sw->ports[4].total_credits = 60; 23462306a36Sopenharmony_ci sw->ports[4].ctl_credits = 2; 23562306a36Sopenharmony_ci sw->ports[4].dual_link_port = &sw->ports[3]; 23662306a36Sopenharmony_ci sw->ports[4].link_nr = 1; 23762306a36Sopenharmony_ci 23862306a36Sopenharmony_ci sw->ports[5].config.type = TB_TYPE_PORT; 23962306a36Sopenharmony_ci sw->ports[5].config.max_in_hop_id = 19; 24062306a36Sopenharmony_ci sw->ports[5].config.max_out_hop_id = 19; 24162306a36Sopenharmony_ci sw->ports[5].total_credits = 60; 24262306a36Sopenharmony_ci sw->ports[5].ctl_credits = 2; 24362306a36Sopenharmony_ci sw->ports[5].dual_link_port = &sw->ports[6]; 24462306a36Sopenharmony_ci 24562306a36Sopenharmony_ci sw->ports[6].config.type = TB_TYPE_PORT; 24662306a36Sopenharmony_ci sw->ports[6].config.max_in_hop_id = 19; 24762306a36Sopenharmony_ci sw->ports[6].config.max_out_hop_id = 19; 24862306a36Sopenharmony_ci sw->ports[6].total_credits = 60; 24962306a36Sopenharmony_ci sw->ports[6].ctl_credits = 2; 25062306a36Sopenharmony_ci sw->ports[6].dual_link_port = &sw->ports[5]; 25162306a36Sopenharmony_ci sw->ports[6].link_nr = 1; 25262306a36Sopenharmony_ci 25362306a36Sopenharmony_ci sw->ports[7].config.type = TB_TYPE_PORT; 25462306a36Sopenharmony_ci sw->ports[7].config.max_in_hop_id = 19; 25562306a36Sopenharmony_ci sw->ports[7].config.max_out_hop_id = 19; 25662306a36Sopenharmony_ci sw->ports[7].total_credits = 60; 25762306a36Sopenharmony_ci sw->ports[7].ctl_credits = 2; 25862306a36Sopenharmony_ci sw->ports[7].dual_link_port = &sw->ports[8]; 25962306a36Sopenharmony_ci 26062306a36Sopenharmony_ci sw->ports[8].config.type = TB_TYPE_PORT; 26162306a36Sopenharmony_ci sw->ports[8].config.max_in_hop_id = 19; 26262306a36Sopenharmony_ci sw->ports[8].config.max_out_hop_id = 19; 26362306a36Sopenharmony_ci sw->ports[8].total_credits = 60; 26462306a36Sopenharmony_ci sw->ports[8].ctl_credits = 2; 26562306a36Sopenharmony_ci sw->ports[8].dual_link_port = &sw->ports[7]; 26662306a36Sopenharmony_ci sw->ports[8].link_nr = 1; 26762306a36Sopenharmony_ci 26862306a36Sopenharmony_ci sw->ports[9].config.type = TB_TYPE_PCIE_UP; 26962306a36Sopenharmony_ci sw->ports[9].config.max_in_hop_id = 8; 27062306a36Sopenharmony_ci sw->ports[9].config.max_out_hop_id = 8; 27162306a36Sopenharmony_ci 27262306a36Sopenharmony_ci sw->ports[10].config.type = TB_TYPE_PCIE_DOWN; 27362306a36Sopenharmony_ci sw->ports[10].config.max_in_hop_id = 8; 27462306a36Sopenharmony_ci sw->ports[10].config.max_out_hop_id = 8; 27562306a36Sopenharmony_ci 27662306a36Sopenharmony_ci sw->ports[11].config.type = TB_TYPE_PCIE_DOWN; 27762306a36Sopenharmony_ci sw->ports[11].config.max_in_hop_id = 8; 27862306a36Sopenharmony_ci sw->ports[11].config.max_out_hop_id = 8; 27962306a36Sopenharmony_ci 28062306a36Sopenharmony_ci sw->ports[12].config.type = TB_TYPE_PCIE_DOWN; 28162306a36Sopenharmony_ci sw->ports[12].config.max_in_hop_id = 8; 28262306a36Sopenharmony_ci sw->ports[12].config.max_out_hop_id = 8; 28362306a36Sopenharmony_ci 28462306a36Sopenharmony_ci sw->ports[13].config.type = TB_TYPE_DP_HDMI_OUT; 28562306a36Sopenharmony_ci sw->ports[13].config.max_in_hop_id = 9; 28662306a36Sopenharmony_ci sw->ports[13].config.max_out_hop_id = 9; 28762306a36Sopenharmony_ci sw->ports[13].cap_adap = -1; 28862306a36Sopenharmony_ci 28962306a36Sopenharmony_ci sw->ports[14].config.type = TB_TYPE_DP_HDMI_OUT; 29062306a36Sopenharmony_ci sw->ports[14].config.max_in_hop_id = 9; 29162306a36Sopenharmony_ci sw->ports[14].config.max_out_hop_id = 9; 29262306a36Sopenharmony_ci sw->ports[14].cap_adap = -1; 29362306a36Sopenharmony_ci 29462306a36Sopenharmony_ci sw->ports[15].disabled = true; 29562306a36Sopenharmony_ci 29662306a36Sopenharmony_ci sw->ports[16].config.type = TB_TYPE_USB3_UP; 29762306a36Sopenharmony_ci sw->ports[16].config.max_in_hop_id = 8; 29862306a36Sopenharmony_ci sw->ports[16].config.max_out_hop_id = 8; 29962306a36Sopenharmony_ci 30062306a36Sopenharmony_ci sw->ports[17].config.type = TB_TYPE_USB3_DOWN; 30162306a36Sopenharmony_ci sw->ports[17].config.max_in_hop_id = 8; 30262306a36Sopenharmony_ci sw->ports[17].config.max_out_hop_id = 8; 30362306a36Sopenharmony_ci 30462306a36Sopenharmony_ci sw->ports[18].config.type = TB_TYPE_USB3_DOWN; 30562306a36Sopenharmony_ci sw->ports[18].config.max_in_hop_id = 8; 30662306a36Sopenharmony_ci sw->ports[18].config.max_out_hop_id = 8; 30762306a36Sopenharmony_ci 30862306a36Sopenharmony_ci sw->ports[19].config.type = TB_TYPE_USB3_DOWN; 30962306a36Sopenharmony_ci sw->ports[19].config.max_in_hop_id = 8; 31062306a36Sopenharmony_ci sw->ports[19].config.max_out_hop_id = 8; 31162306a36Sopenharmony_ci 31262306a36Sopenharmony_ci if (!parent) 31362306a36Sopenharmony_ci return sw; 31462306a36Sopenharmony_ci 31562306a36Sopenharmony_ci /* Link them */ 31662306a36Sopenharmony_ci upstream_port = tb_upstream_port(sw); 31762306a36Sopenharmony_ci port = tb_port_at(route, parent); 31862306a36Sopenharmony_ci port->remote = upstream_port; 31962306a36Sopenharmony_ci upstream_port->remote = port; 32062306a36Sopenharmony_ci if (port->dual_link_port && upstream_port->dual_link_port) { 32162306a36Sopenharmony_ci port->dual_link_port->remote = upstream_port->dual_link_port; 32262306a36Sopenharmony_ci upstream_port->dual_link_port->remote = port->dual_link_port; 32362306a36Sopenharmony_ci 32462306a36Sopenharmony_ci if (bonded) { 32562306a36Sopenharmony_ci /* Bonding is used */ 32662306a36Sopenharmony_ci port->bonded = true; 32762306a36Sopenharmony_ci port->total_credits *= 2; 32862306a36Sopenharmony_ci port->dual_link_port->bonded = true; 32962306a36Sopenharmony_ci port->dual_link_port->total_credits = 0; 33062306a36Sopenharmony_ci upstream_port->bonded = true; 33162306a36Sopenharmony_ci upstream_port->total_credits *= 2; 33262306a36Sopenharmony_ci upstream_port->dual_link_port->bonded = true; 33362306a36Sopenharmony_ci upstream_port->dual_link_port->total_credits = 0; 33462306a36Sopenharmony_ci } 33562306a36Sopenharmony_ci } 33662306a36Sopenharmony_ci 33762306a36Sopenharmony_ci return sw; 33862306a36Sopenharmony_ci} 33962306a36Sopenharmony_ci 34062306a36Sopenharmony_cistatic struct tb_switch *alloc_dev_with_dpin(struct kunit *test, 34162306a36Sopenharmony_ci struct tb_switch *parent, 34262306a36Sopenharmony_ci u64 route, bool bonded) 34362306a36Sopenharmony_ci{ 34462306a36Sopenharmony_ci struct tb_switch *sw; 34562306a36Sopenharmony_ci 34662306a36Sopenharmony_ci sw = alloc_dev_default(test, parent, route, bonded); 34762306a36Sopenharmony_ci if (!sw) 34862306a36Sopenharmony_ci return NULL; 34962306a36Sopenharmony_ci 35062306a36Sopenharmony_ci sw->ports[13].config.type = TB_TYPE_DP_HDMI_IN; 35162306a36Sopenharmony_ci sw->ports[13].config.max_in_hop_id = 9; 35262306a36Sopenharmony_ci sw->ports[13].config.max_out_hop_id = 9; 35362306a36Sopenharmony_ci 35462306a36Sopenharmony_ci sw->ports[14].config.type = TB_TYPE_DP_HDMI_IN; 35562306a36Sopenharmony_ci sw->ports[14].config.max_in_hop_id = 9; 35662306a36Sopenharmony_ci sw->ports[14].config.max_out_hop_id = 9; 35762306a36Sopenharmony_ci 35862306a36Sopenharmony_ci return sw; 35962306a36Sopenharmony_ci} 36062306a36Sopenharmony_ci 36162306a36Sopenharmony_cistatic struct tb_switch *alloc_dev_without_dp(struct kunit *test, 36262306a36Sopenharmony_ci struct tb_switch *parent, 36362306a36Sopenharmony_ci u64 route, bool bonded) 36462306a36Sopenharmony_ci{ 36562306a36Sopenharmony_ci struct tb_switch *sw; 36662306a36Sopenharmony_ci int i; 36762306a36Sopenharmony_ci 36862306a36Sopenharmony_ci sw = alloc_dev_default(test, parent, route, bonded); 36962306a36Sopenharmony_ci if (!sw) 37062306a36Sopenharmony_ci return NULL; 37162306a36Sopenharmony_ci /* 37262306a36Sopenharmony_ci * Device with: 37362306a36Sopenharmony_ci * 2x USB4 Adapters (adapters 1,2 and 3,4), 37462306a36Sopenharmony_ci * 1x PCIe Upstream (adapter 9), 37562306a36Sopenharmony_ci * 1x PCIe Downstream (adapter 10), 37662306a36Sopenharmony_ci * 1x USB3 Upstream (adapter 16), 37762306a36Sopenharmony_ci * 1x USB3 Downstream (adapter 17) 37862306a36Sopenharmony_ci */ 37962306a36Sopenharmony_ci for (i = 5; i <= 8; i++) 38062306a36Sopenharmony_ci sw->ports[i].disabled = true; 38162306a36Sopenharmony_ci 38262306a36Sopenharmony_ci for (i = 11; i <= 14; i++) 38362306a36Sopenharmony_ci sw->ports[i].disabled = true; 38462306a36Sopenharmony_ci 38562306a36Sopenharmony_ci sw->ports[13].cap_adap = 0; 38662306a36Sopenharmony_ci sw->ports[14].cap_adap = 0; 38762306a36Sopenharmony_ci 38862306a36Sopenharmony_ci for (i = 18; i <= 19; i++) 38962306a36Sopenharmony_ci sw->ports[i].disabled = true; 39062306a36Sopenharmony_ci 39162306a36Sopenharmony_ci sw->generation = 4; 39262306a36Sopenharmony_ci sw->credit_allocation = true; 39362306a36Sopenharmony_ci sw->max_usb3_credits = 109; 39462306a36Sopenharmony_ci sw->min_dp_aux_credits = 0; 39562306a36Sopenharmony_ci sw->min_dp_main_credits = 0; 39662306a36Sopenharmony_ci sw->max_pcie_credits = 30; 39762306a36Sopenharmony_ci sw->max_dma_credits = 1; 39862306a36Sopenharmony_ci 39962306a36Sopenharmony_ci return sw; 40062306a36Sopenharmony_ci} 40162306a36Sopenharmony_ci 40262306a36Sopenharmony_cistatic struct tb_switch *alloc_dev_usb4(struct kunit *test, 40362306a36Sopenharmony_ci struct tb_switch *parent, 40462306a36Sopenharmony_ci u64 route, bool bonded) 40562306a36Sopenharmony_ci{ 40662306a36Sopenharmony_ci struct tb_switch *sw; 40762306a36Sopenharmony_ci 40862306a36Sopenharmony_ci sw = alloc_dev_default(test, parent, route, bonded); 40962306a36Sopenharmony_ci if (!sw) 41062306a36Sopenharmony_ci return NULL; 41162306a36Sopenharmony_ci 41262306a36Sopenharmony_ci sw->generation = 4; 41362306a36Sopenharmony_ci sw->credit_allocation = true; 41462306a36Sopenharmony_ci sw->max_usb3_credits = 14; 41562306a36Sopenharmony_ci sw->min_dp_aux_credits = 1; 41662306a36Sopenharmony_ci sw->min_dp_main_credits = 18; 41762306a36Sopenharmony_ci sw->max_pcie_credits = 32; 41862306a36Sopenharmony_ci sw->max_dma_credits = 14; 41962306a36Sopenharmony_ci 42062306a36Sopenharmony_ci return sw; 42162306a36Sopenharmony_ci} 42262306a36Sopenharmony_ci 42362306a36Sopenharmony_cistatic void tb_test_path_basic(struct kunit *test) 42462306a36Sopenharmony_ci{ 42562306a36Sopenharmony_ci struct tb_port *src_port, *dst_port, *p; 42662306a36Sopenharmony_ci struct tb_switch *host; 42762306a36Sopenharmony_ci 42862306a36Sopenharmony_ci host = alloc_host(test); 42962306a36Sopenharmony_ci 43062306a36Sopenharmony_ci src_port = &host->ports[5]; 43162306a36Sopenharmony_ci dst_port = src_port; 43262306a36Sopenharmony_ci 43362306a36Sopenharmony_ci p = tb_next_port_on_path(src_port, dst_port, NULL); 43462306a36Sopenharmony_ci KUNIT_EXPECT_PTR_EQ(test, p, dst_port); 43562306a36Sopenharmony_ci 43662306a36Sopenharmony_ci p = tb_next_port_on_path(src_port, dst_port, p); 43762306a36Sopenharmony_ci KUNIT_EXPECT_TRUE(test, !p); 43862306a36Sopenharmony_ci} 43962306a36Sopenharmony_ci 44062306a36Sopenharmony_cistatic void tb_test_path_not_connected_walk(struct kunit *test) 44162306a36Sopenharmony_ci{ 44262306a36Sopenharmony_ci struct tb_port *src_port, *dst_port, *p; 44362306a36Sopenharmony_ci struct tb_switch *host, *dev; 44462306a36Sopenharmony_ci 44562306a36Sopenharmony_ci host = alloc_host(test); 44662306a36Sopenharmony_ci /* No connection between host and dev */ 44762306a36Sopenharmony_ci dev = alloc_dev_default(test, NULL, 3, true); 44862306a36Sopenharmony_ci 44962306a36Sopenharmony_ci src_port = &host->ports[12]; 45062306a36Sopenharmony_ci dst_port = &dev->ports[16]; 45162306a36Sopenharmony_ci 45262306a36Sopenharmony_ci p = tb_next_port_on_path(src_port, dst_port, NULL); 45362306a36Sopenharmony_ci KUNIT_EXPECT_PTR_EQ(test, p, src_port); 45462306a36Sopenharmony_ci 45562306a36Sopenharmony_ci p = tb_next_port_on_path(src_port, dst_port, p); 45662306a36Sopenharmony_ci KUNIT_EXPECT_PTR_EQ(test, p, &host->ports[3]); 45762306a36Sopenharmony_ci 45862306a36Sopenharmony_ci p = tb_next_port_on_path(src_port, dst_port, p); 45962306a36Sopenharmony_ci KUNIT_EXPECT_TRUE(test, !p); 46062306a36Sopenharmony_ci 46162306a36Sopenharmony_ci /* Other direction */ 46262306a36Sopenharmony_ci 46362306a36Sopenharmony_ci p = tb_next_port_on_path(dst_port, src_port, NULL); 46462306a36Sopenharmony_ci KUNIT_EXPECT_PTR_EQ(test, p, dst_port); 46562306a36Sopenharmony_ci 46662306a36Sopenharmony_ci p = tb_next_port_on_path(dst_port, src_port, p); 46762306a36Sopenharmony_ci KUNIT_EXPECT_PTR_EQ(test, p, &dev->ports[1]); 46862306a36Sopenharmony_ci 46962306a36Sopenharmony_ci p = tb_next_port_on_path(dst_port, src_port, p); 47062306a36Sopenharmony_ci KUNIT_EXPECT_TRUE(test, !p); 47162306a36Sopenharmony_ci} 47262306a36Sopenharmony_ci 47362306a36Sopenharmony_cistruct port_expectation { 47462306a36Sopenharmony_ci u64 route; 47562306a36Sopenharmony_ci u8 port; 47662306a36Sopenharmony_ci enum tb_port_type type; 47762306a36Sopenharmony_ci}; 47862306a36Sopenharmony_ci 47962306a36Sopenharmony_cistatic void tb_test_path_single_hop_walk(struct kunit *test) 48062306a36Sopenharmony_ci{ 48162306a36Sopenharmony_ci /* 48262306a36Sopenharmony_ci * Walks from Host PCIe downstream port to Device #1 PCIe 48362306a36Sopenharmony_ci * upstream port. 48462306a36Sopenharmony_ci * 48562306a36Sopenharmony_ci * [Host] 48662306a36Sopenharmony_ci * 1 | 48762306a36Sopenharmony_ci * 1 | 48862306a36Sopenharmony_ci * [Device] 48962306a36Sopenharmony_ci */ 49062306a36Sopenharmony_ci static const struct port_expectation test_data[] = { 49162306a36Sopenharmony_ci { .route = 0x0, .port = 8, .type = TB_TYPE_PCIE_DOWN }, 49262306a36Sopenharmony_ci { .route = 0x0, .port = 1, .type = TB_TYPE_PORT }, 49362306a36Sopenharmony_ci { .route = 0x1, .port = 1, .type = TB_TYPE_PORT }, 49462306a36Sopenharmony_ci { .route = 0x1, .port = 9, .type = TB_TYPE_PCIE_UP }, 49562306a36Sopenharmony_ci }; 49662306a36Sopenharmony_ci struct tb_port *src_port, *dst_port, *p; 49762306a36Sopenharmony_ci struct tb_switch *host, *dev; 49862306a36Sopenharmony_ci int i; 49962306a36Sopenharmony_ci 50062306a36Sopenharmony_ci host = alloc_host(test); 50162306a36Sopenharmony_ci dev = alloc_dev_default(test, host, 1, true); 50262306a36Sopenharmony_ci 50362306a36Sopenharmony_ci src_port = &host->ports[8]; 50462306a36Sopenharmony_ci dst_port = &dev->ports[9]; 50562306a36Sopenharmony_ci 50662306a36Sopenharmony_ci /* Walk both directions */ 50762306a36Sopenharmony_ci 50862306a36Sopenharmony_ci i = 0; 50962306a36Sopenharmony_ci tb_for_each_port_on_path(src_port, dst_port, p) { 51062306a36Sopenharmony_ci KUNIT_EXPECT_TRUE(test, i < ARRAY_SIZE(test_data)); 51162306a36Sopenharmony_ci KUNIT_EXPECT_EQ(test, tb_route(p->sw), test_data[i].route); 51262306a36Sopenharmony_ci KUNIT_EXPECT_EQ(test, p->port, test_data[i].port); 51362306a36Sopenharmony_ci KUNIT_EXPECT_EQ(test, (enum tb_port_type)p->config.type, 51462306a36Sopenharmony_ci test_data[i].type); 51562306a36Sopenharmony_ci i++; 51662306a36Sopenharmony_ci } 51762306a36Sopenharmony_ci 51862306a36Sopenharmony_ci KUNIT_EXPECT_EQ(test, i, ARRAY_SIZE(test_data)); 51962306a36Sopenharmony_ci 52062306a36Sopenharmony_ci i = ARRAY_SIZE(test_data) - 1; 52162306a36Sopenharmony_ci tb_for_each_port_on_path(dst_port, src_port, p) { 52262306a36Sopenharmony_ci KUNIT_EXPECT_TRUE(test, i < ARRAY_SIZE(test_data)); 52362306a36Sopenharmony_ci KUNIT_EXPECT_EQ(test, tb_route(p->sw), test_data[i].route); 52462306a36Sopenharmony_ci KUNIT_EXPECT_EQ(test, p->port, test_data[i].port); 52562306a36Sopenharmony_ci KUNIT_EXPECT_EQ(test, (enum tb_port_type)p->config.type, 52662306a36Sopenharmony_ci test_data[i].type); 52762306a36Sopenharmony_ci i--; 52862306a36Sopenharmony_ci } 52962306a36Sopenharmony_ci 53062306a36Sopenharmony_ci KUNIT_EXPECT_EQ(test, i, -1); 53162306a36Sopenharmony_ci} 53262306a36Sopenharmony_ci 53362306a36Sopenharmony_cistatic void tb_test_path_daisy_chain_walk(struct kunit *test) 53462306a36Sopenharmony_ci{ 53562306a36Sopenharmony_ci /* 53662306a36Sopenharmony_ci * Walks from Host DP IN to Device #2 DP OUT. 53762306a36Sopenharmony_ci * 53862306a36Sopenharmony_ci * [Host] 53962306a36Sopenharmony_ci * 1 | 54062306a36Sopenharmony_ci * 1 | 54162306a36Sopenharmony_ci * [Device #1] 54262306a36Sopenharmony_ci * 3 / 54362306a36Sopenharmony_ci * 1 / 54462306a36Sopenharmony_ci * [Device #2] 54562306a36Sopenharmony_ci */ 54662306a36Sopenharmony_ci static const struct port_expectation test_data[] = { 54762306a36Sopenharmony_ci { .route = 0x0, .port = 5, .type = TB_TYPE_DP_HDMI_IN }, 54862306a36Sopenharmony_ci { .route = 0x0, .port = 1, .type = TB_TYPE_PORT }, 54962306a36Sopenharmony_ci { .route = 0x1, .port = 1, .type = TB_TYPE_PORT }, 55062306a36Sopenharmony_ci { .route = 0x1, .port = 3, .type = TB_TYPE_PORT }, 55162306a36Sopenharmony_ci { .route = 0x301, .port = 1, .type = TB_TYPE_PORT }, 55262306a36Sopenharmony_ci { .route = 0x301, .port = 13, .type = TB_TYPE_DP_HDMI_OUT }, 55362306a36Sopenharmony_ci }; 55462306a36Sopenharmony_ci struct tb_port *src_port, *dst_port, *p; 55562306a36Sopenharmony_ci struct tb_switch *host, *dev1, *dev2; 55662306a36Sopenharmony_ci int i; 55762306a36Sopenharmony_ci 55862306a36Sopenharmony_ci host = alloc_host(test); 55962306a36Sopenharmony_ci dev1 = alloc_dev_default(test, host, 0x1, true); 56062306a36Sopenharmony_ci dev2 = alloc_dev_default(test, dev1, 0x301, true); 56162306a36Sopenharmony_ci 56262306a36Sopenharmony_ci src_port = &host->ports[5]; 56362306a36Sopenharmony_ci dst_port = &dev2->ports[13]; 56462306a36Sopenharmony_ci 56562306a36Sopenharmony_ci /* Walk both directions */ 56662306a36Sopenharmony_ci 56762306a36Sopenharmony_ci i = 0; 56862306a36Sopenharmony_ci tb_for_each_port_on_path(src_port, dst_port, p) { 56962306a36Sopenharmony_ci KUNIT_EXPECT_TRUE(test, i < ARRAY_SIZE(test_data)); 57062306a36Sopenharmony_ci KUNIT_EXPECT_EQ(test, tb_route(p->sw), test_data[i].route); 57162306a36Sopenharmony_ci KUNIT_EXPECT_EQ(test, p->port, test_data[i].port); 57262306a36Sopenharmony_ci KUNIT_EXPECT_EQ(test, (enum tb_port_type)p->config.type, 57362306a36Sopenharmony_ci test_data[i].type); 57462306a36Sopenharmony_ci i++; 57562306a36Sopenharmony_ci } 57662306a36Sopenharmony_ci 57762306a36Sopenharmony_ci KUNIT_EXPECT_EQ(test, i, ARRAY_SIZE(test_data)); 57862306a36Sopenharmony_ci 57962306a36Sopenharmony_ci i = ARRAY_SIZE(test_data) - 1; 58062306a36Sopenharmony_ci tb_for_each_port_on_path(dst_port, src_port, p) { 58162306a36Sopenharmony_ci KUNIT_EXPECT_TRUE(test, i < ARRAY_SIZE(test_data)); 58262306a36Sopenharmony_ci KUNIT_EXPECT_EQ(test, tb_route(p->sw), test_data[i].route); 58362306a36Sopenharmony_ci KUNIT_EXPECT_EQ(test, p->port, test_data[i].port); 58462306a36Sopenharmony_ci KUNIT_EXPECT_EQ(test, (enum tb_port_type)p->config.type, 58562306a36Sopenharmony_ci test_data[i].type); 58662306a36Sopenharmony_ci i--; 58762306a36Sopenharmony_ci } 58862306a36Sopenharmony_ci 58962306a36Sopenharmony_ci KUNIT_EXPECT_EQ(test, i, -1); 59062306a36Sopenharmony_ci} 59162306a36Sopenharmony_ci 59262306a36Sopenharmony_cistatic void tb_test_path_simple_tree_walk(struct kunit *test) 59362306a36Sopenharmony_ci{ 59462306a36Sopenharmony_ci /* 59562306a36Sopenharmony_ci * Walks from Host DP IN to Device #3 DP OUT. 59662306a36Sopenharmony_ci * 59762306a36Sopenharmony_ci * [Host] 59862306a36Sopenharmony_ci * 1 | 59962306a36Sopenharmony_ci * 1 | 60062306a36Sopenharmony_ci * [Device #1] 60162306a36Sopenharmony_ci * 3 / | 5 \ 7 60262306a36Sopenharmony_ci * 1 / | \ 1 60362306a36Sopenharmony_ci * [Device #2] | [Device #4] 60462306a36Sopenharmony_ci * | 1 60562306a36Sopenharmony_ci * [Device #3] 60662306a36Sopenharmony_ci */ 60762306a36Sopenharmony_ci static const struct port_expectation test_data[] = { 60862306a36Sopenharmony_ci { .route = 0x0, .port = 5, .type = TB_TYPE_DP_HDMI_IN }, 60962306a36Sopenharmony_ci { .route = 0x0, .port = 1, .type = TB_TYPE_PORT }, 61062306a36Sopenharmony_ci { .route = 0x1, .port = 1, .type = TB_TYPE_PORT }, 61162306a36Sopenharmony_ci { .route = 0x1, .port = 5, .type = TB_TYPE_PORT }, 61262306a36Sopenharmony_ci { .route = 0x501, .port = 1, .type = TB_TYPE_PORT }, 61362306a36Sopenharmony_ci { .route = 0x501, .port = 13, .type = TB_TYPE_DP_HDMI_OUT }, 61462306a36Sopenharmony_ci }; 61562306a36Sopenharmony_ci struct tb_port *src_port, *dst_port, *p; 61662306a36Sopenharmony_ci struct tb_switch *host, *dev1, *dev3; 61762306a36Sopenharmony_ci int i; 61862306a36Sopenharmony_ci 61962306a36Sopenharmony_ci host = alloc_host(test); 62062306a36Sopenharmony_ci dev1 = alloc_dev_default(test, host, 0x1, true); 62162306a36Sopenharmony_ci alloc_dev_default(test, dev1, 0x301, true); 62262306a36Sopenharmony_ci dev3 = alloc_dev_default(test, dev1, 0x501, true); 62362306a36Sopenharmony_ci alloc_dev_default(test, dev1, 0x701, true); 62462306a36Sopenharmony_ci 62562306a36Sopenharmony_ci src_port = &host->ports[5]; 62662306a36Sopenharmony_ci dst_port = &dev3->ports[13]; 62762306a36Sopenharmony_ci 62862306a36Sopenharmony_ci /* Walk both directions */ 62962306a36Sopenharmony_ci 63062306a36Sopenharmony_ci i = 0; 63162306a36Sopenharmony_ci tb_for_each_port_on_path(src_port, dst_port, p) { 63262306a36Sopenharmony_ci KUNIT_EXPECT_TRUE(test, i < ARRAY_SIZE(test_data)); 63362306a36Sopenharmony_ci KUNIT_EXPECT_EQ(test, tb_route(p->sw), test_data[i].route); 63462306a36Sopenharmony_ci KUNIT_EXPECT_EQ(test, p->port, test_data[i].port); 63562306a36Sopenharmony_ci KUNIT_EXPECT_EQ(test, (enum tb_port_type)p->config.type, 63662306a36Sopenharmony_ci test_data[i].type); 63762306a36Sopenharmony_ci i++; 63862306a36Sopenharmony_ci } 63962306a36Sopenharmony_ci 64062306a36Sopenharmony_ci KUNIT_EXPECT_EQ(test, i, ARRAY_SIZE(test_data)); 64162306a36Sopenharmony_ci 64262306a36Sopenharmony_ci i = ARRAY_SIZE(test_data) - 1; 64362306a36Sopenharmony_ci tb_for_each_port_on_path(dst_port, src_port, p) { 64462306a36Sopenharmony_ci KUNIT_EXPECT_TRUE(test, i < ARRAY_SIZE(test_data)); 64562306a36Sopenharmony_ci KUNIT_EXPECT_EQ(test, tb_route(p->sw), test_data[i].route); 64662306a36Sopenharmony_ci KUNIT_EXPECT_EQ(test, p->port, test_data[i].port); 64762306a36Sopenharmony_ci KUNIT_EXPECT_EQ(test, (enum tb_port_type)p->config.type, 64862306a36Sopenharmony_ci test_data[i].type); 64962306a36Sopenharmony_ci i--; 65062306a36Sopenharmony_ci } 65162306a36Sopenharmony_ci 65262306a36Sopenharmony_ci KUNIT_EXPECT_EQ(test, i, -1); 65362306a36Sopenharmony_ci} 65462306a36Sopenharmony_ci 65562306a36Sopenharmony_cistatic void tb_test_path_complex_tree_walk(struct kunit *test) 65662306a36Sopenharmony_ci{ 65762306a36Sopenharmony_ci /* 65862306a36Sopenharmony_ci * Walks from Device #3 DP IN to Device #9 DP OUT. 65962306a36Sopenharmony_ci * 66062306a36Sopenharmony_ci * [Host] 66162306a36Sopenharmony_ci * 1 | 66262306a36Sopenharmony_ci * 1 | 66362306a36Sopenharmony_ci * [Device #1] 66462306a36Sopenharmony_ci * 3 / | 5 \ 7 66562306a36Sopenharmony_ci * 1 / | \ 1 66662306a36Sopenharmony_ci * [Device #2] | [Device #5] 66762306a36Sopenharmony_ci * 5 | | 1 \ 7 66862306a36Sopenharmony_ci * 1 | [Device #4] \ 1 66962306a36Sopenharmony_ci * [Device #3] [Device #6] 67062306a36Sopenharmony_ci * 3 / 67162306a36Sopenharmony_ci * 1 / 67262306a36Sopenharmony_ci * [Device #7] 67362306a36Sopenharmony_ci * 3 / | 5 67462306a36Sopenharmony_ci * 1 / | 67562306a36Sopenharmony_ci * [Device #8] | 1 67662306a36Sopenharmony_ci * [Device #9] 67762306a36Sopenharmony_ci */ 67862306a36Sopenharmony_ci static const struct port_expectation test_data[] = { 67962306a36Sopenharmony_ci { .route = 0x50301, .port = 13, .type = TB_TYPE_DP_HDMI_IN }, 68062306a36Sopenharmony_ci { .route = 0x50301, .port = 1, .type = TB_TYPE_PORT }, 68162306a36Sopenharmony_ci { .route = 0x301, .port = 5, .type = TB_TYPE_PORT }, 68262306a36Sopenharmony_ci { .route = 0x301, .port = 1, .type = TB_TYPE_PORT }, 68362306a36Sopenharmony_ci { .route = 0x1, .port = 3, .type = TB_TYPE_PORT }, 68462306a36Sopenharmony_ci { .route = 0x1, .port = 7, .type = TB_TYPE_PORT }, 68562306a36Sopenharmony_ci { .route = 0x701, .port = 1, .type = TB_TYPE_PORT }, 68662306a36Sopenharmony_ci { .route = 0x701, .port = 7, .type = TB_TYPE_PORT }, 68762306a36Sopenharmony_ci { .route = 0x70701, .port = 1, .type = TB_TYPE_PORT }, 68862306a36Sopenharmony_ci { .route = 0x70701, .port = 3, .type = TB_TYPE_PORT }, 68962306a36Sopenharmony_ci { .route = 0x3070701, .port = 1, .type = TB_TYPE_PORT }, 69062306a36Sopenharmony_ci { .route = 0x3070701, .port = 5, .type = TB_TYPE_PORT }, 69162306a36Sopenharmony_ci { .route = 0x503070701, .port = 1, .type = TB_TYPE_PORT }, 69262306a36Sopenharmony_ci { .route = 0x503070701, .port = 14, .type = TB_TYPE_DP_HDMI_OUT }, 69362306a36Sopenharmony_ci }; 69462306a36Sopenharmony_ci struct tb_switch *host, *dev1, *dev2, *dev3, *dev5, *dev6, *dev7, *dev9; 69562306a36Sopenharmony_ci struct tb_port *src_port, *dst_port, *p; 69662306a36Sopenharmony_ci int i; 69762306a36Sopenharmony_ci 69862306a36Sopenharmony_ci host = alloc_host(test); 69962306a36Sopenharmony_ci dev1 = alloc_dev_default(test, host, 0x1, true); 70062306a36Sopenharmony_ci dev2 = alloc_dev_default(test, dev1, 0x301, true); 70162306a36Sopenharmony_ci dev3 = alloc_dev_with_dpin(test, dev2, 0x50301, true); 70262306a36Sopenharmony_ci alloc_dev_default(test, dev1, 0x501, true); 70362306a36Sopenharmony_ci dev5 = alloc_dev_default(test, dev1, 0x701, true); 70462306a36Sopenharmony_ci dev6 = alloc_dev_default(test, dev5, 0x70701, true); 70562306a36Sopenharmony_ci dev7 = alloc_dev_default(test, dev6, 0x3070701, true); 70662306a36Sopenharmony_ci alloc_dev_default(test, dev7, 0x303070701, true); 70762306a36Sopenharmony_ci dev9 = alloc_dev_default(test, dev7, 0x503070701, true); 70862306a36Sopenharmony_ci 70962306a36Sopenharmony_ci src_port = &dev3->ports[13]; 71062306a36Sopenharmony_ci dst_port = &dev9->ports[14]; 71162306a36Sopenharmony_ci 71262306a36Sopenharmony_ci /* Walk both directions */ 71362306a36Sopenharmony_ci 71462306a36Sopenharmony_ci i = 0; 71562306a36Sopenharmony_ci tb_for_each_port_on_path(src_port, dst_port, p) { 71662306a36Sopenharmony_ci KUNIT_EXPECT_TRUE(test, i < ARRAY_SIZE(test_data)); 71762306a36Sopenharmony_ci KUNIT_EXPECT_EQ(test, tb_route(p->sw), test_data[i].route); 71862306a36Sopenharmony_ci KUNIT_EXPECT_EQ(test, p->port, test_data[i].port); 71962306a36Sopenharmony_ci KUNIT_EXPECT_EQ(test, (enum tb_port_type)p->config.type, 72062306a36Sopenharmony_ci test_data[i].type); 72162306a36Sopenharmony_ci i++; 72262306a36Sopenharmony_ci } 72362306a36Sopenharmony_ci 72462306a36Sopenharmony_ci KUNIT_EXPECT_EQ(test, i, ARRAY_SIZE(test_data)); 72562306a36Sopenharmony_ci 72662306a36Sopenharmony_ci i = ARRAY_SIZE(test_data) - 1; 72762306a36Sopenharmony_ci tb_for_each_port_on_path(dst_port, src_port, p) { 72862306a36Sopenharmony_ci KUNIT_EXPECT_TRUE(test, i < ARRAY_SIZE(test_data)); 72962306a36Sopenharmony_ci KUNIT_EXPECT_EQ(test, tb_route(p->sw), test_data[i].route); 73062306a36Sopenharmony_ci KUNIT_EXPECT_EQ(test, p->port, test_data[i].port); 73162306a36Sopenharmony_ci KUNIT_EXPECT_EQ(test, (enum tb_port_type)p->config.type, 73262306a36Sopenharmony_ci test_data[i].type); 73362306a36Sopenharmony_ci i--; 73462306a36Sopenharmony_ci } 73562306a36Sopenharmony_ci 73662306a36Sopenharmony_ci KUNIT_EXPECT_EQ(test, i, -1); 73762306a36Sopenharmony_ci} 73862306a36Sopenharmony_ci 73962306a36Sopenharmony_cistatic void tb_test_path_max_length_walk(struct kunit *test) 74062306a36Sopenharmony_ci{ 74162306a36Sopenharmony_ci struct tb_switch *host, *dev1, *dev2, *dev3, *dev4, *dev5, *dev6; 74262306a36Sopenharmony_ci struct tb_switch *dev7, *dev8, *dev9, *dev10, *dev11, *dev12; 74362306a36Sopenharmony_ci struct tb_port *src_port, *dst_port, *p; 74462306a36Sopenharmony_ci int i; 74562306a36Sopenharmony_ci 74662306a36Sopenharmony_ci /* 74762306a36Sopenharmony_ci * Walks from Device #6 DP IN to Device #12 DP OUT. 74862306a36Sopenharmony_ci * 74962306a36Sopenharmony_ci * [Host] 75062306a36Sopenharmony_ci * 1 / \ 3 75162306a36Sopenharmony_ci * 1 / \ 1 75262306a36Sopenharmony_ci * [Device #1] [Device #7] 75362306a36Sopenharmony_ci * 3 | | 3 75462306a36Sopenharmony_ci * 1 | | 1 75562306a36Sopenharmony_ci * [Device #2] [Device #8] 75662306a36Sopenharmony_ci * 3 | | 3 75762306a36Sopenharmony_ci * 1 | | 1 75862306a36Sopenharmony_ci * [Device #3] [Device #9] 75962306a36Sopenharmony_ci * 3 | | 3 76062306a36Sopenharmony_ci * 1 | | 1 76162306a36Sopenharmony_ci * [Device #4] [Device #10] 76262306a36Sopenharmony_ci * 3 | | 3 76362306a36Sopenharmony_ci * 1 | | 1 76462306a36Sopenharmony_ci * [Device #5] [Device #11] 76562306a36Sopenharmony_ci * 3 | | 3 76662306a36Sopenharmony_ci * 1 | | 1 76762306a36Sopenharmony_ci * [Device #6] [Device #12] 76862306a36Sopenharmony_ci */ 76962306a36Sopenharmony_ci static const struct port_expectation test_data[] = { 77062306a36Sopenharmony_ci { .route = 0x30303030301, .port = 13, .type = TB_TYPE_DP_HDMI_IN }, 77162306a36Sopenharmony_ci { .route = 0x30303030301, .port = 1, .type = TB_TYPE_PORT }, 77262306a36Sopenharmony_ci { .route = 0x303030301, .port = 3, .type = TB_TYPE_PORT }, 77362306a36Sopenharmony_ci { .route = 0x303030301, .port = 1, .type = TB_TYPE_PORT }, 77462306a36Sopenharmony_ci { .route = 0x3030301, .port = 3, .type = TB_TYPE_PORT }, 77562306a36Sopenharmony_ci { .route = 0x3030301, .port = 1, .type = TB_TYPE_PORT }, 77662306a36Sopenharmony_ci { .route = 0x30301, .port = 3, .type = TB_TYPE_PORT }, 77762306a36Sopenharmony_ci { .route = 0x30301, .port = 1, .type = TB_TYPE_PORT }, 77862306a36Sopenharmony_ci { .route = 0x301, .port = 3, .type = TB_TYPE_PORT }, 77962306a36Sopenharmony_ci { .route = 0x301, .port = 1, .type = TB_TYPE_PORT }, 78062306a36Sopenharmony_ci { .route = 0x1, .port = 3, .type = TB_TYPE_PORT }, 78162306a36Sopenharmony_ci { .route = 0x1, .port = 1, .type = TB_TYPE_PORT }, 78262306a36Sopenharmony_ci { .route = 0x0, .port = 1, .type = TB_TYPE_PORT }, 78362306a36Sopenharmony_ci { .route = 0x0, .port = 3, .type = TB_TYPE_PORT }, 78462306a36Sopenharmony_ci { .route = 0x3, .port = 1, .type = TB_TYPE_PORT }, 78562306a36Sopenharmony_ci { .route = 0x3, .port = 3, .type = TB_TYPE_PORT }, 78662306a36Sopenharmony_ci { .route = 0x303, .port = 1, .type = TB_TYPE_PORT }, 78762306a36Sopenharmony_ci { .route = 0x303, .port = 3, .type = TB_TYPE_PORT }, 78862306a36Sopenharmony_ci { .route = 0x30303, .port = 1, .type = TB_TYPE_PORT }, 78962306a36Sopenharmony_ci { .route = 0x30303, .port = 3, .type = TB_TYPE_PORT }, 79062306a36Sopenharmony_ci { .route = 0x3030303, .port = 1, .type = TB_TYPE_PORT }, 79162306a36Sopenharmony_ci { .route = 0x3030303, .port = 3, .type = TB_TYPE_PORT }, 79262306a36Sopenharmony_ci { .route = 0x303030303, .port = 1, .type = TB_TYPE_PORT }, 79362306a36Sopenharmony_ci { .route = 0x303030303, .port = 3, .type = TB_TYPE_PORT }, 79462306a36Sopenharmony_ci { .route = 0x30303030303, .port = 1, .type = TB_TYPE_PORT }, 79562306a36Sopenharmony_ci { .route = 0x30303030303, .port = 13, .type = TB_TYPE_DP_HDMI_OUT }, 79662306a36Sopenharmony_ci }; 79762306a36Sopenharmony_ci 79862306a36Sopenharmony_ci host = alloc_host(test); 79962306a36Sopenharmony_ci dev1 = alloc_dev_default(test, host, 0x1, true); 80062306a36Sopenharmony_ci dev2 = alloc_dev_default(test, dev1, 0x301, true); 80162306a36Sopenharmony_ci dev3 = alloc_dev_default(test, dev2, 0x30301, true); 80262306a36Sopenharmony_ci dev4 = alloc_dev_default(test, dev3, 0x3030301, true); 80362306a36Sopenharmony_ci dev5 = alloc_dev_default(test, dev4, 0x303030301, true); 80462306a36Sopenharmony_ci dev6 = alloc_dev_with_dpin(test, dev5, 0x30303030301, true); 80562306a36Sopenharmony_ci dev7 = alloc_dev_default(test, host, 0x3, true); 80662306a36Sopenharmony_ci dev8 = alloc_dev_default(test, dev7, 0x303, true); 80762306a36Sopenharmony_ci dev9 = alloc_dev_default(test, dev8, 0x30303, true); 80862306a36Sopenharmony_ci dev10 = alloc_dev_default(test, dev9, 0x3030303, true); 80962306a36Sopenharmony_ci dev11 = alloc_dev_default(test, dev10, 0x303030303, true); 81062306a36Sopenharmony_ci dev12 = alloc_dev_default(test, dev11, 0x30303030303, true); 81162306a36Sopenharmony_ci 81262306a36Sopenharmony_ci src_port = &dev6->ports[13]; 81362306a36Sopenharmony_ci dst_port = &dev12->ports[13]; 81462306a36Sopenharmony_ci 81562306a36Sopenharmony_ci /* Walk both directions */ 81662306a36Sopenharmony_ci 81762306a36Sopenharmony_ci i = 0; 81862306a36Sopenharmony_ci tb_for_each_port_on_path(src_port, dst_port, p) { 81962306a36Sopenharmony_ci KUNIT_EXPECT_TRUE(test, i < ARRAY_SIZE(test_data)); 82062306a36Sopenharmony_ci KUNIT_EXPECT_EQ(test, tb_route(p->sw), test_data[i].route); 82162306a36Sopenharmony_ci KUNIT_EXPECT_EQ(test, p->port, test_data[i].port); 82262306a36Sopenharmony_ci KUNIT_EXPECT_EQ(test, (enum tb_port_type)p->config.type, 82362306a36Sopenharmony_ci test_data[i].type); 82462306a36Sopenharmony_ci i++; 82562306a36Sopenharmony_ci } 82662306a36Sopenharmony_ci 82762306a36Sopenharmony_ci KUNIT_EXPECT_EQ(test, i, ARRAY_SIZE(test_data)); 82862306a36Sopenharmony_ci 82962306a36Sopenharmony_ci i = ARRAY_SIZE(test_data) - 1; 83062306a36Sopenharmony_ci tb_for_each_port_on_path(dst_port, src_port, p) { 83162306a36Sopenharmony_ci KUNIT_EXPECT_TRUE(test, i < ARRAY_SIZE(test_data)); 83262306a36Sopenharmony_ci KUNIT_EXPECT_EQ(test, tb_route(p->sw), test_data[i].route); 83362306a36Sopenharmony_ci KUNIT_EXPECT_EQ(test, p->port, test_data[i].port); 83462306a36Sopenharmony_ci KUNIT_EXPECT_EQ(test, (enum tb_port_type)p->config.type, 83562306a36Sopenharmony_ci test_data[i].type); 83662306a36Sopenharmony_ci i--; 83762306a36Sopenharmony_ci } 83862306a36Sopenharmony_ci 83962306a36Sopenharmony_ci KUNIT_EXPECT_EQ(test, i, -1); 84062306a36Sopenharmony_ci} 84162306a36Sopenharmony_ci 84262306a36Sopenharmony_cistatic void tb_test_path_not_connected(struct kunit *test) 84362306a36Sopenharmony_ci{ 84462306a36Sopenharmony_ci struct tb_switch *host, *dev1, *dev2; 84562306a36Sopenharmony_ci struct tb_port *down, *up; 84662306a36Sopenharmony_ci struct tb_path *path; 84762306a36Sopenharmony_ci 84862306a36Sopenharmony_ci host = alloc_host(test); 84962306a36Sopenharmony_ci dev1 = alloc_dev_default(test, host, 0x3, false); 85062306a36Sopenharmony_ci /* Not connected to anything */ 85162306a36Sopenharmony_ci dev2 = alloc_dev_default(test, NULL, 0x303, false); 85262306a36Sopenharmony_ci 85362306a36Sopenharmony_ci down = &dev1->ports[10]; 85462306a36Sopenharmony_ci up = &dev2->ports[9]; 85562306a36Sopenharmony_ci 85662306a36Sopenharmony_ci path = tb_path_alloc(NULL, down, 8, up, 8, 0, "PCIe Down"); 85762306a36Sopenharmony_ci KUNIT_ASSERT_NULL(test, path); 85862306a36Sopenharmony_ci path = tb_path_alloc(NULL, down, 8, up, 8, 1, "PCIe Down"); 85962306a36Sopenharmony_ci KUNIT_ASSERT_NULL(test, path); 86062306a36Sopenharmony_ci} 86162306a36Sopenharmony_ci 86262306a36Sopenharmony_cistruct hop_expectation { 86362306a36Sopenharmony_ci u64 route; 86462306a36Sopenharmony_ci u8 in_port; 86562306a36Sopenharmony_ci enum tb_port_type in_type; 86662306a36Sopenharmony_ci u8 out_port; 86762306a36Sopenharmony_ci enum tb_port_type out_type; 86862306a36Sopenharmony_ci}; 86962306a36Sopenharmony_ci 87062306a36Sopenharmony_cistatic void tb_test_path_not_bonded_lane0(struct kunit *test) 87162306a36Sopenharmony_ci{ 87262306a36Sopenharmony_ci /* 87362306a36Sopenharmony_ci * PCIe path from host to device using lane 0. 87462306a36Sopenharmony_ci * 87562306a36Sopenharmony_ci * [Host] 87662306a36Sopenharmony_ci * 3 |: 4 87762306a36Sopenharmony_ci * 1 |: 2 87862306a36Sopenharmony_ci * [Device] 87962306a36Sopenharmony_ci */ 88062306a36Sopenharmony_ci static const struct hop_expectation test_data[] = { 88162306a36Sopenharmony_ci { 88262306a36Sopenharmony_ci .route = 0x0, 88362306a36Sopenharmony_ci .in_port = 9, 88462306a36Sopenharmony_ci .in_type = TB_TYPE_PCIE_DOWN, 88562306a36Sopenharmony_ci .out_port = 3, 88662306a36Sopenharmony_ci .out_type = TB_TYPE_PORT, 88762306a36Sopenharmony_ci }, 88862306a36Sopenharmony_ci { 88962306a36Sopenharmony_ci .route = 0x3, 89062306a36Sopenharmony_ci .in_port = 1, 89162306a36Sopenharmony_ci .in_type = TB_TYPE_PORT, 89262306a36Sopenharmony_ci .out_port = 9, 89362306a36Sopenharmony_ci .out_type = TB_TYPE_PCIE_UP, 89462306a36Sopenharmony_ci }, 89562306a36Sopenharmony_ci }; 89662306a36Sopenharmony_ci struct tb_switch *host, *dev; 89762306a36Sopenharmony_ci struct tb_port *down, *up; 89862306a36Sopenharmony_ci struct tb_path *path; 89962306a36Sopenharmony_ci int i; 90062306a36Sopenharmony_ci 90162306a36Sopenharmony_ci host = alloc_host(test); 90262306a36Sopenharmony_ci dev = alloc_dev_default(test, host, 0x3, false); 90362306a36Sopenharmony_ci 90462306a36Sopenharmony_ci down = &host->ports[9]; 90562306a36Sopenharmony_ci up = &dev->ports[9]; 90662306a36Sopenharmony_ci 90762306a36Sopenharmony_ci path = tb_path_alloc(NULL, down, 8, up, 8, 0, "PCIe Down"); 90862306a36Sopenharmony_ci KUNIT_ASSERT_NOT_NULL(test, path); 90962306a36Sopenharmony_ci KUNIT_ASSERT_EQ(test, path->path_length, ARRAY_SIZE(test_data)); 91062306a36Sopenharmony_ci for (i = 0; i < ARRAY_SIZE(test_data); i++) { 91162306a36Sopenharmony_ci const struct tb_port *in_port, *out_port; 91262306a36Sopenharmony_ci 91362306a36Sopenharmony_ci in_port = path->hops[i].in_port; 91462306a36Sopenharmony_ci out_port = path->hops[i].out_port; 91562306a36Sopenharmony_ci 91662306a36Sopenharmony_ci KUNIT_EXPECT_EQ(test, tb_route(in_port->sw), test_data[i].route); 91762306a36Sopenharmony_ci KUNIT_EXPECT_EQ(test, in_port->port, test_data[i].in_port); 91862306a36Sopenharmony_ci KUNIT_EXPECT_EQ(test, (enum tb_port_type)in_port->config.type, 91962306a36Sopenharmony_ci test_data[i].in_type); 92062306a36Sopenharmony_ci KUNIT_EXPECT_EQ(test, tb_route(out_port->sw), test_data[i].route); 92162306a36Sopenharmony_ci KUNIT_EXPECT_EQ(test, out_port->port, test_data[i].out_port); 92262306a36Sopenharmony_ci KUNIT_EXPECT_EQ(test, (enum tb_port_type)out_port->config.type, 92362306a36Sopenharmony_ci test_data[i].out_type); 92462306a36Sopenharmony_ci } 92562306a36Sopenharmony_ci tb_path_free(path); 92662306a36Sopenharmony_ci} 92762306a36Sopenharmony_ci 92862306a36Sopenharmony_cistatic void tb_test_path_not_bonded_lane1(struct kunit *test) 92962306a36Sopenharmony_ci{ 93062306a36Sopenharmony_ci /* 93162306a36Sopenharmony_ci * DP Video path from host to device using lane 1. Paths like 93262306a36Sopenharmony_ci * these are only used with Thunderbolt 1 devices where lane 93362306a36Sopenharmony_ci * bonding is not possible. USB4 specifically does not allow 93462306a36Sopenharmony_ci * paths like this (you either use lane 0 where lane 1 is 93562306a36Sopenharmony_ci * disabled or both lanes are bonded). 93662306a36Sopenharmony_ci * 93762306a36Sopenharmony_ci * [Host] 93862306a36Sopenharmony_ci * 1 :| 2 93962306a36Sopenharmony_ci * 1 :| 2 94062306a36Sopenharmony_ci * [Device] 94162306a36Sopenharmony_ci */ 94262306a36Sopenharmony_ci static const struct hop_expectation test_data[] = { 94362306a36Sopenharmony_ci { 94462306a36Sopenharmony_ci .route = 0x0, 94562306a36Sopenharmony_ci .in_port = 5, 94662306a36Sopenharmony_ci .in_type = TB_TYPE_DP_HDMI_IN, 94762306a36Sopenharmony_ci .out_port = 2, 94862306a36Sopenharmony_ci .out_type = TB_TYPE_PORT, 94962306a36Sopenharmony_ci }, 95062306a36Sopenharmony_ci { 95162306a36Sopenharmony_ci .route = 0x1, 95262306a36Sopenharmony_ci .in_port = 2, 95362306a36Sopenharmony_ci .in_type = TB_TYPE_PORT, 95462306a36Sopenharmony_ci .out_port = 13, 95562306a36Sopenharmony_ci .out_type = TB_TYPE_DP_HDMI_OUT, 95662306a36Sopenharmony_ci }, 95762306a36Sopenharmony_ci }; 95862306a36Sopenharmony_ci struct tb_switch *host, *dev; 95962306a36Sopenharmony_ci struct tb_port *in, *out; 96062306a36Sopenharmony_ci struct tb_path *path; 96162306a36Sopenharmony_ci int i; 96262306a36Sopenharmony_ci 96362306a36Sopenharmony_ci host = alloc_host(test); 96462306a36Sopenharmony_ci dev = alloc_dev_default(test, host, 0x1, false); 96562306a36Sopenharmony_ci 96662306a36Sopenharmony_ci in = &host->ports[5]; 96762306a36Sopenharmony_ci out = &dev->ports[13]; 96862306a36Sopenharmony_ci 96962306a36Sopenharmony_ci path = tb_path_alloc(NULL, in, 9, out, 9, 1, "Video"); 97062306a36Sopenharmony_ci KUNIT_ASSERT_NOT_NULL(test, path); 97162306a36Sopenharmony_ci KUNIT_ASSERT_EQ(test, path->path_length, ARRAY_SIZE(test_data)); 97262306a36Sopenharmony_ci for (i = 0; i < ARRAY_SIZE(test_data); i++) { 97362306a36Sopenharmony_ci const struct tb_port *in_port, *out_port; 97462306a36Sopenharmony_ci 97562306a36Sopenharmony_ci in_port = path->hops[i].in_port; 97662306a36Sopenharmony_ci out_port = path->hops[i].out_port; 97762306a36Sopenharmony_ci 97862306a36Sopenharmony_ci KUNIT_EXPECT_EQ(test, tb_route(in_port->sw), test_data[i].route); 97962306a36Sopenharmony_ci KUNIT_EXPECT_EQ(test, in_port->port, test_data[i].in_port); 98062306a36Sopenharmony_ci KUNIT_EXPECT_EQ(test, (enum tb_port_type)in_port->config.type, 98162306a36Sopenharmony_ci test_data[i].in_type); 98262306a36Sopenharmony_ci KUNIT_EXPECT_EQ(test, tb_route(out_port->sw), test_data[i].route); 98362306a36Sopenharmony_ci KUNIT_EXPECT_EQ(test, out_port->port, test_data[i].out_port); 98462306a36Sopenharmony_ci KUNIT_EXPECT_EQ(test, (enum tb_port_type)out_port->config.type, 98562306a36Sopenharmony_ci test_data[i].out_type); 98662306a36Sopenharmony_ci } 98762306a36Sopenharmony_ci tb_path_free(path); 98862306a36Sopenharmony_ci} 98962306a36Sopenharmony_ci 99062306a36Sopenharmony_cistatic void tb_test_path_not_bonded_lane1_chain(struct kunit *test) 99162306a36Sopenharmony_ci{ 99262306a36Sopenharmony_ci /* 99362306a36Sopenharmony_ci * DP Video path from host to device 3 using lane 1. 99462306a36Sopenharmony_ci * 99562306a36Sopenharmony_ci * [Host] 99662306a36Sopenharmony_ci * 1 :| 2 99762306a36Sopenharmony_ci * 1 :| 2 99862306a36Sopenharmony_ci * [Device #1] 99962306a36Sopenharmony_ci * 7 :| 8 100062306a36Sopenharmony_ci * 1 :| 2 100162306a36Sopenharmony_ci * [Device #2] 100262306a36Sopenharmony_ci * 5 :| 6 100362306a36Sopenharmony_ci * 1 :| 2 100462306a36Sopenharmony_ci * [Device #3] 100562306a36Sopenharmony_ci */ 100662306a36Sopenharmony_ci static const struct hop_expectation test_data[] = { 100762306a36Sopenharmony_ci { 100862306a36Sopenharmony_ci .route = 0x0, 100962306a36Sopenharmony_ci .in_port = 5, 101062306a36Sopenharmony_ci .in_type = TB_TYPE_DP_HDMI_IN, 101162306a36Sopenharmony_ci .out_port = 2, 101262306a36Sopenharmony_ci .out_type = TB_TYPE_PORT, 101362306a36Sopenharmony_ci }, 101462306a36Sopenharmony_ci { 101562306a36Sopenharmony_ci .route = 0x1, 101662306a36Sopenharmony_ci .in_port = 2, 101762306a36Sopenharmony_ci .in_type = TB_TYPE_PORT, 101862306a36Sopenharmony_ci .out_port = 8, 101962306a36Sopenharmony_ci .out_type = TB_TYPE_PORT, 102062306a36Sopenharmony_ci }, 102162306a36Sopenharmony_ci { 102262306a36Sopenharmony_ci .route = 0x701, 102362306a36Sopenharmony_ci .in_port = 2, 102462306a36Sopenharmony_ci .in_type = TB_TYPE_PORT, 102562306a36Sopenharmony_ci .out_port = 6, 102662306a36Sopenharmony_ci .out_type = TB_TYPE_PORT, 102762306a36Sopenharmony_ci }, 102862306a36Sopenharmony_ci { 102962306a36Sopenharmony_ci .route = 0x50701, 103062306a36Sopenharmony_ci .in_port = 2, 103162306a36Sopenharmony_ci .in_type = TB_TYPE_PORT, 103262306a36Sopenharmony_ci .out_port = 13, 103362306a36Sopenharmony_ci .out_type = TB_TYPE_DP_HDMI_OUT, 103462306a36Sopenharmony_ci }, 103562306a36Sopenharmony_ci }; 103662306a36Sopenharmony_ci struct tb_switch *host, *dev1, *dev2, *dev3; 103762306a36Sopenharmony_ci struct tb_port *in, *out; 103862306a36Sopenharmony_ci struct tb_path *path; 103962306a36Sopenharmony_ci int i; 104062306a36Sopenharmony_ci 104162306a36Sopenharmony_ci host = alloc_host(test); 104262306a36Sopenharmony_ci dev1 = alloc_dev_default(test, host, 0x1, false); 104362306a36Sopenharmony_ci dev2 = alloc_dev_default(test, dev1, 0x701, false); 104462306a36Sopenharmony_ci dev3 = alloc_dev_default(test, dev2, 0x50701, false); 104562306a36Sopenharmony_ci 104662306a36Sopenharmony_ci in = &host->ports[5]; 104762306a36Sopenharmony_ci out = &dev3->ports[13]; 104862306a36Sopenharmony_ci 104962306a36Sopenharmony_ci path = tb_path_alloc(NULL, in, 9, out, 9, 1, "Video"); 105062306a36Sopenharmony_ci KUNIT_ASSERT_NOT_NULL(test, path); 105162306a36Sopenharmony_ci KUNIT_ASSERT_EQ(test, path->path_length, ARRAY_SIZE(test_data)); 105262306a36Sopenharmony_ci for (i = 0; i < ARRAY_SIZE(test_data); i++) { 105362306a36Sopenharmony_ci const struct tb_port *in_port, *out_port; 105462306a36Sopenharmony_ci 105562306a36Sopenharmony_ci in_port = path->hops[i].in_port; 105662306a36Sopenharmony_ci out_port = path->hops[i].out_port; 105762306a36Sopenharmony_ci 105862306a36Sopenharmony_ci KUNIT_EXPECT_EQ(test, tb_route(in_port->sw), test_data[i].route); 105962306a36Sopenharmony_ci KUNIT_EXPECT_EQ(test, in_port->port, test_data[i].in_port); 106062306a36Sopenharmony_ci KUNIT_EXPECT_EQ(test, (enum tb_port_type)in_port->config.type, 106162306a36Sopenharmony_ci test_data[i].in_type); 106262306a36Sopenharmony_ci KUNIT_EXPECT_EQ(test, tb_route(out_port->sw), test_data[i].route); 106362306a36Sopenharmony_ci KUNIT_EXPECT_EQ(test, out_port->port, test_data[i].out_port); 106462306a36Sopenharmony_ci KUNIT_EXPECT_EQ(test, (enum tb_port_type)out_port->config.type, 106562306a36Sopenharmony_ci test_data[i].out_type); 106662306a36Sopenharmony_ci } 106762306a36Sopenharmony_ci tb_path_free(path); 106862306a36Sopenharmony_ci} 106962306a36Sopenharmony_ci 107062306a36Sopenharmony_cistatic void tb_test_path_not_bonded_lane1_chain_reverse(struct kunit *test) 107162306a36Sopenharmony_ci{ 107262306a36Sopenharmony_ci /* 107362306a36Sopenharmony_ci * DP Video path from device 3 to host using lane 1. 107462306a36Sopenharmony_ci * 107562306a36Sopenharmony_ci * [Host] 107662306a36Sopenharmony_ci * 1 :| 2 107762306a36Sopenharmony_ci * 1 :| 2 107862306a36Sopenharmony_ci * [Device #1] 107962306a36Sopenharmony_ci * 7 :| 8 108062306a36Sopenharmony_ci * 1 :| 2 108162306a36Sopenharmony_ci * [Device #2] 108262306a36Sopenharmony_ci * 5 :| 6 108362306a36Sopenharmony_ci * 1 :| 2 108462306a36Sopenharmony_ci * [Device #3] 108562306a36Sopenharmony_ci */ 108662306a36Sopenharmony_ci static const struct hop_expectation test_data[] = { 108762306a36Sopenharmony_ci { 108862306a36Sopenharmony_ci .route = 0x50701, 108962306a36Sopenharmony_ci .in_port = 13, 109062306a36Sopenharmony_ci .in_type = TB_TYPE_DP_HDMI_IN, 109162306a36Sopenharmony_ci .out_port = 2, 109262306a36Sopenharmony_ci .out_type = TB_TYPE_PORT, 109362306a36Sopenharmony_ci }, 109462306a36Sopenharmony_ci { 109562306a36Sopenharmony_ci .route = 0x701, 109662306a36Sopenharmony_ci .in_port = 6, 109762306a36Sopenharmony_ci .in_type = TB_TYPE_PORT, 109862306a36Sopenharmony_ci .out_port = 2, 109962306a36Sopenharmony_ci .out_type = TB_TYPE_PORT, 110062306a36Sopenharmony_ci }, 110162306a36Sopenharmony_ci { 110262306a36Sopenharmony_ci .route = 0x1, 110362306a36Sopenharmony_ci .in_port = 8, 110462306a36Sopenharmony_ci .in_type = TB_TYPE_PORT, 110562306a36Sopenharmony_ci .out_port = 2, 110662306a36Sopenharmony_ci .out_type = TB_TYPE_PORT, 110762306a36Sopenharmony_ci }, 110862306a36Sopenharmony_ci { 110962306a36Sopenharmony_ci .route = 0x0, 111062306a36Sopenharmony_ci .in_port = 2, 111162306a36Sopenharmony_ci .in_type = TB_TYPE_PORT, 111262306a36Sopenharmony_ci .out_port = 5, 111362306a36Sopenharmony_ci .out_type = TB_TYPE_DP_HDMI_IN, 111462306a36Sopenharmony_ci }, 111562306a36Sopenharmony_ci }; 111662306a36Sopenharmony_ci struct tb_switch *host, *dev1, *dev2, *dev3; 111762306a36Sopenharmony_ci struct tb_port *in, *out; 111862306a36Sopenharmony_ci struct tb_path *path; 111962306a36Sopenharmony_ci int i; 112062306a36Sopenharmony_ci 112162306a36Sopenharmony_ci host = alloc_host(test); 112262306a36Sopenharmony_ci dev1 = alloc_dev_default(test, host, 0x1, false); 112362306a36Sopenharmony_ci dev2 = alloc_dev_default(test, dev1, 0x701, false); 112462306a36Sopenharmony_ci dev3 = alloc_dev_with_dpin(test, dev2, 0x50701, false); 112562306a36Sopenharmony_ci 112662306a36Sopenharmony_ci in = &dev3->ports[13]; 112762306a36Sopenharmony_ci out = &host->ports[5]; 112862306a36Sopenharmony_ci 112962306a36Sopenharmony_ci path = tb_path_alloc(NULL, in, 9, out, 9, 1, "Video"); 113062306a36Sopenharmony_ci KUNIT_ASSERT_NOT_NULL(test, path); 113162306a36Sopenharmony_ci KUNIT_ASSERT_EQ(test, path->path_length, ARRAY_SIZE(test_data)); 113262306a36Sopenharmony_ci for (i = 0; i < ARRAY_SIZE(test_data); i++) { 113362306a36Sopenharmony_ci const struct tb_port *in_port, *out_port; 113462306a36Sopenharmony_ci 113562306a36Sopenharmony_ci in_port = path->hops[i].in_port; 113662306a36Sopenharmony_ci out_port = path->hops[i].out_port; 113762306a36Sopenharmony_ci 113862306a36Sopenharmony_ci KUNIT_EXPECT_EQ(test, tb_route(in_port->sw), test_data[i].route); 113962306a36Sopenharmony_ci KUNIT_EXPECT_EQ(test, in_port->port, test_data[i].in_port); 114062306a36Sopenharmony_ci KUNIT_EXPECT_EQ(test, (enum tb_port_type)in_port->config.type, 114162306a36Sopenharmony_ci test_data[i].in_type); 114262306a36Sopenharmony_ci KUNIT_EXPECT_EQ(test, tb_route(out_port->sw), test_data[i].route); 114362306a36Sopenharmony_ci KUNIT_EXPECT_EQ(test, out_port->port, test_data[i].out_port); 114462306a36Sopenharmony_ci KUNIT_EXPECT_EQ(test, (enum tb_port_type)out_port->config.type, 114562306a36Sopenharmony_ci test_data[i].out_type); 114662306a36Sopenharmony_ci } 114762306a36Sopenharmony_ci tb_path_free(path); 114862306a36Sopenharmony_ci} 114962306a36Sopenharmony_ci 115062306a36Sopenharmony_cistatic void tb_test_path_mixed_chain(struct kunit *test) 115162306a36Sopenharmony_ci{ 115262306a36Sopenharmony_ci /* 115362306a36Sopenharmony_ci * DP Video path from host to device 4 where first and last link 115462306a36Sopenharmony_ci * is bonded. 115562306a36Sopenharmony_ci * 115662306a36Sopenharmony_ci * [Host] 115762306a36Sopenharmony_ci * 1 | 115862306a36Sopenharmony_ci * 1 | 115962306a36Sopenharmony_ci * [Device #1] 116062306a36Sopenharmony_ci * 7 :| 8 116162306a36Sopenharmony_ci * 1 :| 2 116262306a36Sopenharmony_ci * [Device #2] 116362306a36Sopenharmony_ci * 5 :| 6 116462306a36Sopenharmony_ci * 1 :| 2 116562306a36Sopenharmony_ci * [Device #3] 116662306a36Sopenharmony_ci * 3 | 116762306a36Sopenharmony_ci * 1 | 116862306a36Sopenharmony_ci * [Device #4] 116962306a36Sopenharmony_ci */ 117062306a36Sopenharmony_ci static const struct hop_expectation test_data[] = { 117162306a36Sopenharmony_ci { 117262306a36Sopenharmony_ci .route = 0x0, 117362306a36Sopenharmony_ci .in_port = 5, 117462306a36Sopenharmony_ci .in_type = TB_TYPE_DP_HDMI_IN, 117562306a36Sopenharmony_ci .out_port = 1, 117662306a36Sopenharmony_ci .out_type = TB_TYPE_PORT, 117762306a36Sopenharmony_ci }, 117862306a36Sopenharmony_ci { 117962306a36Sopenharmony_ci .route = 0x1, 118062306a36Sopenharmony_ci .in_port = 1, 118162306a36Sopenharmony_ci .in_type = TB_TYPE_PORT, 118262306a36Sopenharmony_ci .out_port = 8, 118362306a36Sopenharmony_ci .out_type = TB_TYPE_PORT, 118462306a36Sopenharmony_ci }, 118562306a36Sopenharmony_ci { 118662306a36Sopenharmony_ci .route = 0x701, 118762306a36Sopenharmony_ci .in_port = 2, 118862306a36Sopenharmony_ci .in_type = TB_TYPE_PORT, 118962306a36Sopenharmony_ci .out_port = 6, 119062306a36Sopenharmony_ci .out_type = TB_TYPE_PORT, 119162306a36Sopenharmony_ci }, 119262306a36Sopenharmony_ci { 119362306a36Sopenharmony_ci .route = 0x50701, 119462306a36Sopenharmony_ci .in_port = 2, 119562306a36Sopenharmony_ci .in_type = TB_TYPE_PORT, 119662306a36Sopenharmony_ci .out_port = 3, 119762306a36Sopenharmony_ci .out_type = TB_TYPE_PORT, 119862306a36Sopenharmony_ci }, 119962306a36Sopenharmony_ci { 120062306a36Sopenharmony_ci .route = 0x3050701, 120162306a36Sopenharmony_ci .in_port = 1, 120262306a36Sopenharmony_ci .in_type = TB_TYPE_PORT, 120362306a36Sopenharmony_ci .out_port = 13, 120462306a36Sopenharmony_ci .out_type = TB_TYPE_DP_HDMI_OUT, 120562306a36Sopenharmony_ci }, 120662306a36Sopenharmony_ci }; 120762306a36Sopenharmony_ci struct tb_switch *host, *dev1, *dev2, *dev3, *dev4; 120862306a36Sopenharmony_ci struct tb_port *in, *out; 120962306a36Sopenharmony_ci struct tb_path *path; 121062306a36Sopenharmony_ci int i; 121162306a36Sopenharmony_ci 121262306a36Sopenharmony_ci host = alloc_host(test); 121362306a36Sopenharmony_ci dev1 = alloc_dev_default(test, host, 0x1, true); 121462306a36Sopenharmony_ci dev2 = alloc_dev_default(test, dev1, 0x701, false); 121562306a36Sopenharmony_ci dev3 = alloc_dev_default(test, dev2, 0x50701, false); 121662306a36Sopenharmony_ci dev4 = alloc_dev_default(test, dev3, 0x3050701, true); 121762306a36Sopenharmony_ci 121862306a36Sopenharmony_ci in = &host->ports[5]; 121962306a36Sopenharmony_ci out = &dev4->ports[13]; 122062306a36Sopenharmony_ci 122162306a36Sopenharmony_ci path = tb_path_alloc(NULL, in, 9, out, 9, 1, "Video"); 122262306a36Sopenharmony_ci KUNIT_ASSERT_NOT_NULL(test, path); 122362306a36Sopenharmony_ci KUNIT_ASSERT_EQ(test, path->path_length, ARRAY_SIZE(test_data)); 122462306a36Sopenharmony_ci for (i = 0; i < ARRAY_SIZE(test_data); i++) { 122562306a36Sopenharmony_ci const struct tb_port *in_port, *out_port; 122662306a36Sopenharmony_ci 122762306a36Sopenharmony_ci in_port = path->hops[i].in_port; 122862306a36Sopenharmony_ci out_port = path->hops[i].out_port; 122962306a36Sopenharmony_ci 123062306a36Sopenharmony_ci KUNIT_EXPECT_EQ(test, tb_route(in_port->sw), test_data[i].route); 123162306a36Sopenharmony_ci KUNIT_EXPECT_EQ(test, in_port->port, test_data[i].in_port); 123262306a36Sopenharmony_ci KUNIT_EXPECT_EQ(test, (enum tb_port_type)in_port->config.type, 123362306a36Sopenharmony_ci test_data[i].in_type); 123462306a36Sopenharmony_ci KUNIT_EXPECT_EQ(test, tb_route(out_port->sw), test_data[i].route); 123562306a36Sopenharmony_ci KUNIT_EXPECT_EQ(test, out_port->port, test_data[i].out_port); 123662306a36Sopenharmony_ci KUNIT_EXPECT_EQ(test, (enum tb_port_type)out_port->config.type, 123762306a36Sopenharmony_ci test_data[i].out_type); 123862306a36Sopenharmony_ci } 123962306a36Sopenharmony_ci tb_path_free(path); 124062306a36Sopenharmony_ci} 124162306a36Sopenharmony_ci 124262306a36Sopenharmony_cistatic void tb_test_path_mixed_chain_reverse(struct kunit *test) 124362306a36Sopenharmony_ci{ 124462306a36Sopenharmony_ci /* 124562306a36Sopenharmony_ci * DP Video path from device 4 to host where first and last link 124662306a36Sopenharmony_ci * is bonded. 124762306a36Sopenharmony_ci * 124862306a36Sopenharmony_ci * [Host] 124962306a36Sopenharmony_ci * 1 | 125062306a36Sopenharmony_ci * 1 | 125162306a36Sopenharmony_ci * [Device #1] 125262306a36Sopenharmony_ci * 7 :| 8 125362306a36Sopenharmony_ci * 1 :| 2 125462306a36Sopenharmony_ci * [Device #2] 125562306a36Sopenharmony_ci * 5 :| 6 125662306a36Sopenharmony_ci * 1 :| 2 125762306a36Sopenharmony_ci * [Device #3] 125862306a36Sopenharmony_ci * 3 | 125962306a36Sopenharmony_ci * 1 | 126062306a36Sopenharmony_ci * [Device #4] 126162306a36Sopenharmony_ci */ 126262306a36Sopenharmony_ci static const struct hop_expectation test_data[] = { 126362306a36Sopenharmony_ci { 126462306a36Sopenharmony_ci .route = 0x3050701, 126562306a36Sopenharmony_ci .in_port = 13, 126662306a36Sopenharmony_ci .in_type = TB_TYPE_DP_HDMI_OUT, 126762306a36Sopenharmony_ci .out_port = 1, 126862306a36Sopenharmony_ci .out_type = TB_TYPE_PORT, 126962306a36Sopenharmony_ci }, 127062306a36Sopenharmony_ci { 127162306a36Sopenharmony_ci .route = 0x50701, 127262306a36Sopenharmony_ci .in_port = 3, 127362306a36Sopenharmony_ci .in_type = TB_TYPE_PORT, 127462306a36Sopenharmony_ci .out_port = 2, 127562306a36Sopenharmony_ci .out_type = TB_TYPE_PORT, 127662306a36Sopenharmony_ci }, 127762306a36Sopenharmony_ci { 127862306a36Sopenharmony_ci .route = 0x701, 127962306a36Sopenharmony_ci .in_port = 6, 128062306a36Sopenharmony_ci .in_type = TB_TYPE_PORT, 128162306a36Sopenharmony_ci .out_port = 2, 128262306a36Sopenharmony_ci .out_type = TB_TYPE_PORT, 128362306a36Sopenharmony_ci }, 128462306a36Sopenharmony_ci { 128562306a36Sopenharmony_ci .route = 0x1, 128662306a36Sopenharmony_ci .in_port = 8, 128762306a36Sopenharmony_ci .in_type = TB_TYPE_PORT, 128862306a36Sopenharmony_ci .out_port = 1, 128962306a36Sopenharmony_ci .out_type = TB_TYPE_PORT, 129062306a36Sopenharmony_ci }, 129162306a36Sopenharmony_ci { 129262306a36Sopenharmony_ci .route = 0x0, 129362306a36Sopenharmony_ci .in_port = 1, 129462306a36Sopenharmony_ci .in_type = TB_TYPE_PORT, 129562306a36Sopenharmony_ci .out_port = 5, 129662306a36Sopenharmony_ci .out_type = TB_TYPE_DP_HDMI_IN, 129762306a36Sopenharmony_ci }, 129862306a36Sopenharmony_ci }; 129962306a36Sopenharmony_ci struct tb_switch *host, *dev1, *dev2, *dev3, *dev4; 130062306a36Sopenharmony_ci struct tb_port *in, *out; 130162306a36Sopenharmony_ci struct tb_path *path; 130262306a36Sopenharmony_ci int i; 130362306a36Sopenharmony_ci 130462306a36Sopenharmony_ci host = alloc_host(test); 130562306a36Sopenharmony_ci dev1 = alloc_dev_default(test, host, 0x1, true); 130662306a36Sopenharmony_ci dev2 = alloc_dev_default(test, dev1, 0x701, false); 130762306a36Sopenharmony_ci dev3 = alloc_dev_default(test, dev2, 0x50701, false); 130862306a36Sopenharmony_ci dev4 = alloc_dev_default(test, dev3, 0x3050701, true); 130962306a36Sopenharmony_ci 131062306a36Sopenharmony_ci in = &dev4->ports[13]; 131162306a36Sopenharmony_ci out = &host->ports[5]; 131262306a36Sopenharmony_ci 131362306a36Sopenharmony_ci path = tb_path_alloc(NULL, in, 9, out, 9, 1, "Video"); 131462306a36Sopenharmony_ci KUNIT_ASSERT_NOT_NULL(test, path); 131562306a36Sopenharmony_ci KUNIT_ASSERT_EQ(test, path->path_length, ARRAY_SIZE(test_data)); 131662306a36Sopenharmony_ci for (i = 0; i < ARRAY_SIZE(test_data); i++) { 131762306a36Sopenharmony_ci const struct tb_port *in_port, *out_port; 131862306a36Sopenharmony_ci 131962306a36Sopenharmony_ci in_port = path->hops[i].in_port; 132062306a36Sopenharmony_ci out_port = path->hops[i].out_port; 132162306a36Sopenharmony_ci 132262306a36Sopenharmony_ci KUNIT_EXPECT_EQ(test, tb_route(in_port->sw), test_data[i].route); 132362306a36Sopenharmony_ci KUNIT_EXPECT_EQ(test, in_port->port, test_data[i].in_port); 132462306a36Sopenharmony_ci KUNIT_EXPECT_EQ(test, (enum tb_port_type)in_port->config.type, 132562306a36Sopenharmony_ci test_data[i].in_type); 132662306a36Sopenharmony_ci KUNIT_EXPECT_EQ(test, tb_route(out_port->sw), test_data[i].route); 132762306a36Sopenharmony_ci KUNIT_EXPECT_EQ(test, out_port->port, test_data[i].out_port); 132862306a36Sopenharmony_ci KUNIT_EXPECT_EQ(test, (enum tb_port_type)out_port->config.type, 132962306a36Sopenharmony_ci test_data[i].out_type); 133062306a36Sopenharmony_ci } 133162306a36Sopenharmony_ci tb_path_free(path); 133262306a36Sopenharmony_ci} 133362306a36Sopenharmony_ci 133462306a36Sopenharmony_cistatic void tb_test_tunnel_pcie(struct kunit *test) 133562306a36Sopenharmony_ci{ 133662306a36Sopenharmony_ci struct tb_switch *host, *dev1, *dev2; 133762306a36Sopenharmony_ci struct tb_tunnel *tunnel1, *tunnel2; 133862306a36Sopenharmony_ci struct tb_port *down, *up; 133962306a36Sopenharmony_ci 134062306a36Sopenharmony_ci /* 134162306a36Sopenharmony_ci * Create PCIe tunnel between host and two devices. 134262306a36Sopenharmony_ci * 134362306a36Sopenharmony_ci * [Host] 134462306a36Sopenharmony_ci * 1 | 134562306a36Sopenharmony_ci * 1 | 134662306a36Sopenharmony_ci * [Device #1] 134762306a36Sopenharmony_ci * 5 | 134862306a36Sopenharmony_ci * 1 | 134962306a36Sopenharmony_ci * [Device #2] 135062306a36Sopenharmony_ci */ 135162306a36Sopenharmony_ci host = alloc_host(test); 135262306a36Sopenharmony_ci dev1 = alloc_dev_default(test, host, 0x1, true); 135362306a36Sopenharmony_ci dev2 = alloc_dev_default(test, dev1, 0x501, true); 135462306a36Sopenharmony_ci 135562306a36Sopenharmony_ci down = &host->ports[8]; 135662306a36Sopenharmony_ci up = &dev1->ports[9]; 135762306a36Sopenharmony_ci tunnel1 = tb_tunnel_alloc_pci(NULL, up, down); 135862306a36Sopenharmony_ci KUNIT_ASSERT_NOT_NULL(test, tunnel1); 135962306a36Sopenharmony_ci KUNIT_EXPECT_EQ(test, tunnel1->type, TB_TUNNEL_PCI); 136062306a36Sopenharmony_ci KUNIT_EXPECT_PTR_EQ(test, tunnel1->src_port, down); 136162306a36Sopenharmony_ci KUNIT_EXPECT_PTR_EQ(test, tunnel1->dst_port, up); 136262306a36Sopenharmony_ci KUNIT_ASSERT_EQ(test, tunnel1->npaths, 2); 136362306a36Sopenharmony_ci KUNIT_ASSERT_EQ(test, tunnel1->paths[0]->path_length, 2); 136462306a36Sopenharmony_ci KUNIT_EXPECT_PTR_EQ(test, tunnel1->paths[0]->hops[0].in_port, down); 136562306a36Sopenharmony_ci KUNIT_EXPECT_PTR_EQ(test, tunnel1->paths[0]->hops[1].out_port, up); 136662306a36Sopenharmony_ci KUNIT_ASSERT_EQ(test, tunnel1->paths[1]->path_length, 2); 136762306a36Sopenharmony_ci KUNIT_EXPECT_PTR_EQ(test, tunnel1->paths[1]->hops[0].in_port, up); 136862306a36Sopenharmony_ci KUNIT_EXPECT_PTR_EQ(test, tunnel1->paths[1]->hops[1].out_port, down); 136962306a36Sopenharmony_ci 137062306a36Sopenharmony_ci down = &dev1->ports[10]; 137162306a36Sopenharmony_ci up = &dev2->ports[9]; 137262306a36Sopenharmony_ci tunnel2 = tb_tunnel_alloc_pci(NULL, up, down); 137362306a36Sopenharmony_ci KUNIT_ASSERT_NOT_NULL(test, tunnel2); 137462306a36Sopenharmony_ci KUNIT_EXPECT_EQ(test, tunnel2->type, TB_TUNNEL_PCI); 137562306a36Sopenharmony_ci KUNIT_EXPECT_PTR_EQ(test, tunnel2->src_port, down); 137662306a36Sopenharmony_ci KUNIT_EXPECT_PTR_EQ(test, tunnel2->dst_port, up); 137762306a36Sopenharmony_ci KUNIT_ASSERT_EQ(test, tunnel2->npaths, 2); 137862306a36Sopenharmony_ci KUNIT_ASSERT_EQ(test, tunnel2->paths[0]->path_length, 2); 137962306a36Sopenharmony_ci KUNIT_EXPECT_PTR_EQ(test, tunnel2->paths[0]->hops[0].in_port, down); 138062306a36Sopenharmony_ci KUNIT_EXPECT_PTR_EQ(test, tunnel2->paths[0]->hops[1].out_port, up); 138162306a36Sopenharmony_ci KUNIT_ASSERT_EQ(test, tunnel2->paths[1]->path_length, 2); 138262306a36Sopenharmony_ci KUNIT_EXPECT_PTR_EQ(test, tunnel2->paths[1]->hops[0].in_port, up); 138362306a36Sopenharmony_ci KUNIT_EXPECT_PTR_EQ(test, tunnel2->paths[1]->hops[1].out_port, down); 138462306a36Sopenharmony_ci 138562306a36Sopenharmony_ci tb_tunnel_free(tunnel2); 138662306a36Sopenharmony_ci tb_tunnel_free(tunnel1); 138762306a36Sopenharmony_ci} 138862306a36Sopenharmony_ci 138962306a36Sopenharmony_cistatic void tb_test_tunnel_dp(struct kunit *test) 139062306a36Sopenharmony_ci{ 139162306a36Sopenharmony_ci struct tb_switch *host, *dev; 139262306a36Sopenharmony_ci struct tb_port *in, *out; 139362306a36Sopenharmony_ci struct tb_tunnel *tunnel; 139462306a36Sopenharmony_ci 139562306a36Sopenharmony_ci /* 139662306a36Sopenharmony_ci * Create DP tunnel between Host and Device 139762306a36Sopenharmony_ci * 139862306a36Sopenharmony_ci * [Host] 139962306a36Sopenharmony_ci * 1 | 140062306a36Sopenharmony_ci * 1 | 140162306a36Sopenharmony_ci * [Device] 140262306a36Sopenharmony_ci */ 140362306a36Sopenharmony_ci host = alloc_host(test); 140462306a36Sopenharmony_ci dev = alloc_dev_default(test, host, 0x3, true); 140562306a36Sopenharmony_ci 140662306a36Sopenharmony_ci in = &host->ports[5]; 140762306a36Sopenharmony_ci out = &dev->ports[13]; 140862306a36Sopenharmony_ci 140962306a36Sopenharmony_ci tunnel = tb_tunnel_alloc_dp(NULL, in, out, 1, 0, 0); 141062306a36Sopenharmony_ci KUNIT_ASSERT_NOT_NULL(test, tunnel); 141162306a36Sopenharmony_ci KUNIT_EXPECT_EQ(test, tunnel->type, TB_TUNNEL_DP); 141262306a36Sopenharmony_ci KUNIT_EXPECT_PTR_EQ(test, tunnel->src_port, in); 141362306a36Sopenharmony_ci KUNIT_EXPECT_PTR_EQ(test, tunnel->dst_port, out); 141462306a36Sopenharmony_ci KUNIT_ASSERT_EQ(test, tunnel->npaths, 3); 141562306a36Sopenharmony_ci KUNIT_ASSERT_EQ(test, tunnel->paths[0]->path_length, 2); 141662306a36Sopenharmony_ci KUNIT_EXPECT_PTR_EQ(test, tunnel->paths[0]->hops[0].in_port, in); 141762306a36Sopenharmony_ci KUNIT_EXPECT_PTR_EQ(test, tunnel->paths[0]->hops[1].out_port, out); 141862306a36Sopenharmony_ci KUNIT_ASSERT_EQ(test, tunnel->paths[1]->path_length, 2); 141962306a36Sopenharmony_ci KUNIT_EXPECT_PTR_EQ(test, tunnel->paths[1]->hops[0].in_port, in); 142062306a36Sopenharmony_ci KUNIT_EXPECT_PTR_EQ(test, tunnel->paths[1]->hops[1].out_port, out); 142162306a36Sopenharmony_ci KUNIT_ASSERT_EQ(test, tunnel->paths[2]->path_length, 2); 142262306a36Sopenharmony_ci KUNIT_EXPECT_PTR_EQ(test, tunnel->paths[2]->hops[0].in_port, out); 142362306a36Sopenharmony_ci KUNIT_EXPECT_PTR_EQ(test, tunnel->paths[2]->hops[1].out_port, in); 142462306a36Sopenharmony_ci tb_tunnel_free(tunnel); 142562306a36Sopenharmony_ci} 142662306a36Sopenharmony_ci 142762306a36Sopenharmony_cistatic void tb_test_tunnel_dp_chain(struct kunit *test) 142862306a36Sopenharmony_ci{ 142962306a36Sopenharmony_ci struct tb_switch *host, *dev1, *dev4; 143062306a36Sopenharmony_ci struct tb_port *in, *out; 143162306a36Sopenharmony_ci struct tb_tunnel *tunnel; 143262306a36Sopenharmony_ci 143362306a36Sopenharmony_ci /* 143462306a36Sopenharmony_ci * Create DP tunnel from Host DP IN to Device #4 DP OUT. 143562306a36Sopenharmony_ci * 143662306a36Sopenharmony_ci * [Host] 143762306a36Sopenharmony_ci * 1 | 143862306a36Sopenharmony_ci * 1 | 143962306a36Sopenharmony_ci * [Device #1] 144062306a36Sopenharmony_ci * 3 / | 5 \ 7 144162306a36Sopenharmony_ci * 1 / | \ 1 144262306a36Sopenharmony_ci * [Device #2] | [Device #4] 144362306a36Sopenharmony_ci * | 1 144462306a36Sopenharmony_ci * [Device #3] 144562306a36Sopenharmony_ci */ 144662306a36Sopenharmony_ci host = alloc_host(test); 144762306a36Sopenharmony_ci dev1 = alloc_dev_default(test, host, 0x1, true); 144862306a36Sopenharmony_ci alloc_dev_default(test, dev1, 0x301, true); 144962306a36Sopenharmony_ci alloc_dev_default(test, dev1, 0x501, true); 145062306a36Sopenharmony_ci dev4 = alloc_dev_default(test, dev1, 0x701, true); 145162306a36Sopenharmony_ci 145262306a36Sopenharmony_ci in = &host->ports[5]; 145362306a36Sopenharmony_ci out = &dev4->ports[14]; 145462306a36Sopenharmony_ci 145562306a36Sopenharmony_ci tunnel = tb_tunnel_alloc_dp(NULL, in, out, 1, 0, 0); 145662306a36Sopenharmony_ci KUNIT_ASSERT_NOT_NULL(test, tunnel); 145762306a36Sopenharmony_ci KUNIT_EXPECT_EQ(test, tunnel->type, TB_TUNNEL_DP); 145862306a36Sopenharmony_ci KUNIT_EXPECT_PTR_EQ(test, tunnel->src_port, in); 145962306a36Sopenharmony_ci KUNIT_EXPECT_PTR_EQ(test, tunnel->dst_port, out); 146062306a36Sopenharmony_ci KUNIT_ASSERT_EQ(test, tunnel->npaths, 3); 146162306a36Sopenharmony_ci KUNIT_ASSERT_EQ(test, tunnel->paths[0]->path_length, 3); 146262306a36Sopenharmony_ci KUNIT_EXPECT_PTR_EQ(test, tunnel->paths[0]->hops[0].in_port, in); 146362306a36Sopenharmony_ci KUNIT_EXPECT_PTR_EQ(test, tunnel->paths[0]->hops[2].out_port, out); 146462306a36Sopenharmony_ci KUNIT_ASSERT_EQ(test, tunnel->paths[1]->path_length, 3); 146562306a36Sopenharmony_ci KUNIT_EXPECT_PTR_EQ(test, tunnel->paths[1]->hops[0].in_port, in); 146662306a36Sopenharmony_ci KUNIT_EXPECT_PTR_EQ(test, tunnel->paths[1]->hops[2].out_port, out); 146762306a36Sopenharmony_ci KUNIT_ASSERT_EQ(test, tunnel->paths[2]->path_length, 3); 146862306a36Sopenharmony_ci KUNIT_EXPECT_PTR_EQ(test, tunnel->paths[2]->hops[0].in_port, out); 146962306a36Sopenharmony_ci KUNIT_EXPECT_PTR_EQ(test, tunnel->paths[2]->hops[2].out_port, in); 147062306a36Sopenharmony_ci tb_tunnel_free(tunnel); 147162306a36Sopenharmony_ci} 147262306a36Sopenharmony_ci 147362306a36Sopenharmony_cistatic void tb_test_tunnel_dp_tree(struct kunit *test) 147462306a36Sopenharmony_ci{ 147562306a36Sopenharmony_ci struct tb_switch *host, *dev1, *dev2, *dev3, *dev5; 147662306a36Sopenharmony_ci struct tb_port *in, *out; 147762306a36Sopenharmony_ci struct tb_tunnel *tunnel; 147862306a36Sopenharmony_ci 147962306a36Sopenharmony_ci /* 148062306a36Sopenharmony_ci * Create DP tunnel from Device #2 DP IN to Device #5 DP OUT. 148162306a36Sopenharmony_ci * 148262306a36Sopenharmony_ci * [Host] 148362306a36Sopenharmony_ci * 3 | 148462306a36Sopenharmony_ci * 1 | 148562306a36Sopenharmony_ci * [Device #1] 148662306a36Sopenharmony_ci * 3 / | 5 \ 7 148762306a36Sopenharmony_ci * 1 / | \ 1 148862306a36Sopenharmony_ci * [Device #2] | [Device #4] 148962306a36Sopenharmony_ci * | 1 149062306a36Sopenharmony_ci * [Device #3] 149162306a36Sopenharmony_ci * | 5 149262306a36Sopenharmony_ci * | 1 149362306a36Sopenharmony_ci * [Device #5] 149462306a36Sopenharmony_ci */ 149562306a36Sopenharmony_ci host = alloc_host(test); 149662306a36Sopenharmony_ci dev1 = alloc_dev_default(test, host, 0x3, true); 149762306a36Sopenharmony_ci dev2 = alloc_dev_with_dpin(test, dev1, 0x303, true); 149862306a36Sopenharmony_ci dev3 = alloc_dev_default(test, dev1, 0x503, true); 149962306a36Sopenharmony_ci alloc_dev_default(test, dev1, 0x703, true); 150062306a36Sopenharmony_ci dev5 = alloc_dev_default(test, dev3, 0x50503, true); 150162306a36Sopenharmony_ci 150262306a36Sopenharmony_ci in = &dev2->ports[13]; 150362306a36Sopenharmony_ci out = &dev5->ports[13]; 150462306a36Sopenharmony_ci 150562306a36Sopenharmony_ci tunnel = tb_tunnel_alloc_dp(NULL, in, out, 1, 0, 0); 150662306a36Sopenharmony_ci KUNIT_ASSERT_NOT_NULL(test, tunnel); 150762306a36Sopenharmony_ci KUNIT_EXPECT_EQ(test, tunnel->type, TB_TUNNEL_DP); 150862306a36Sopenharmony_ci KUNIT_EXPECT_PTR_EQ(test, tunnel->src_port, in); 150962306a36Sopenharmony_ci KUNIT_EXPECT_PTR_EQ(test, tunnel->dst_port, out); 151062306a36Sopenharmony_ci KUNIT_ASSERT_EQ(test, tunnel->npaths, 3); 151162306a36Sopenharmony_ci KUNIT_ASSERT_EQ(test, tunnel->paths[0]->path_length, 4); 151262306a36Sopenharmony_ci KUNIT_EXPECT_PTR_EQ(test, tunnel->paths[0]->hops[0].in_port, in); 151362306a36Sopenharmony_ci KUNIT_EXPECT_PTR_EQ(test, tunnel->paths[0]->hops[3].out_port, out); 151462306a36Sopenharmony_ci KUNIT_ASSERT_EQ(test, tunnel->paths[1]->path_length, 4); 151562306a36Sopenharmony_ci KUNIT_EXPECT_PTR_EQ(test, tunnel->paths[1]->hops[0].in_port, in); 151662306a36Sopenharmony_ci KUNIT_EXPECT_PTR_EQ(test, tunnel->paths[1]->hops[3].out_port, out); 151762306a36Sopenharmony_ci KUNIT_ASSERT_EQ(test, tunnel->paths[2]->path_length, 4); 151862306a36Sopenharmony_ci KUNIT_EXPECT_PTR_EQ(test, tunnel->paths[2]->hops[0].in_port, out); 151962306a36Sopenharmony_ci KUNIT_EXPECT_PTR_EQ(test, tunnel->paths[2]->hops[3].out_port, in); 152062306a36Sopenharmony_ci tb_tunnel_free(tunnel); 152162306a36Sopenharmony_ci} 152262306a36Sopenharmony_ci 152362306a36Sopenharmony_cistatic void tb_test_tunnel_dp_max_length(struct kunit *test) 152462306a36Sopenharmony_ci{ 152562306a36Sopenharmony_ci struct tb_switch *host, *dev1, *dev2, *dev3, *dev4, *dev5, *dev6; 152662306a36Sopenharmony_ci struct tb_switch *dev7, *dev8, *dev9, *dev10, *dev11, *dev12; 152762306a36Sopenharmony_ci struct tb_port *in, *out; 152862306a36Sopenharmony_ci struct tb_tunnel *tunnel; 152962306a36Sopenharmony_ci 153062306a36Sopenharmony_ci /* 153162306a36Sopenharmony_ci * Creates DP tunnel from Device #6 to Device #12. 153262306a36Sopenharmony_ci * 153362306a36Sopenharmony_ci * [Host] 153462306a36Sopenharmony_ci * 1 / \ 3 153562306a36Sopenharmony_ci * 1 / \ 1 153662306a36Sopenharmony_ci * [Device #1] [Device #7] 153762306a36Sopenharmony_ci * 3 | | 3 153862306a36Sopenharmony_ci * 1 | | 1 153962306a36Sopenharmony_ci * [Device #2] [Device #8] 154062306a36Sopenharmony_ci * 3 | | 3 154162306a36Sopenharmony_ci * 1 | | 1 154262306a36Sopenharmony_ci * [Device #3] [Device #9] 154362306a36Sopenharmony_ci * 3 | | 3 154462306a36Sopenharmony_ci * 1 | | 1 154562306a36Sopenharmony_ci * [Device #4] [Device #10] 154662306a36Sopenharmony_ci * 3 | | 3 154762306a36Sopenharmony_ci * 1 | | 1 154862306a36Sopenharmony_ci * [Device #5] [Device #11] 154962306a36Sopenharmony_ci * 3 | | 3 155062306a36Sopenharmony_ci * 1 | | 1 155162306a36Sopenharmony_ci * [Device #6] [Device #12] 155262306a36Sopenharmony_ci */ 155362306a36Sopenharmony_ci host = alloc_host(test); 155462306a36Sopenharmony_ci dev1 = alloc_dev_default(test, host, 0x1, true); 155562306a36Sopenharmony_ci dev2 = alloc_dev_default(test, dev1, 0x301, true); 155662306a36Sopenharmony_ci dev3 = alloc_dev_default(test, dev2, 0x30301, true); 155762306a36Sopenharmony_ci dev4 = alloc_dev_default(test, dev3, 0x3030301, true); 155862306a36Sopenharmony_ci dev5 = alloc_dev_default(test, dev4, 0x303030301, true); 155962306a36Sopenharmony_ci dev6 = alloc_dev_with_dpin(test, dev5, 0x30303030301, true); 156062306a36Sopenharmony_ci dev7 = alloc_dev_default(test, host, 0x3, true); 156162306a36Sopenharmony_ci dev8 = alloc_dev_default(test, dev7, 0x303, true); 156262306a36Sopenharmony_ci dev9 = alloc_dev_default(test, dev8, 0x30303, true); 156362306a36Sopenharmony_ci dev10 = alloc_dev_default(test, dev9, 0x3030303, true); 156462306a36Sopenharmony_ci dev11 = alloc_dev_default(test, dev10, 0x303030303, true); 156562306a36Sopenharmony_ci dev12 = alloc_dev_default(test, dev11, 0x30303030303, true); 156662306a36Sopenharmony_ci 156762306a36Sopenharmony_ci in = &dev6->ports[13]; 156862306a36Sopenharmony_ci out = &dev12->ports[13]; 156962306a36Sopenharmony_ci 157062306a36Sopenharmony_ci tunnel = tb_tunnel_alloc_dp(NULL, in, out, 1, 0, 0); 157162306a36Sopenharmony_ci KUNIT_ASSERT_NOT_NULL(test, tunnel); 157262306a36Sopenharmony_ci KUNIT_EXPECT_EQ(test, tunnel->type, TB_TUNNEL_DP); 157362306a36Sopenharmony_ci KUNIT_EXPECT_PTR_EQ(test, tunnel->src_port, in); 157462306a36Sopenharmony_ci KUNIT_EXPECT_PTR_EQ(test, tunnel->dst_port, out); 157562306a36Sopenharmony_ci KUNIT_ASSERT_EQ(test, tunnel->npaths, 3); 157662306a36Sopenharmony_ci KUNIT_ASSERT_EQ(test, tunnel->paths[0]->path_length, 13); 157762306a36Sopenharmony_ci /* First hop */ 157862306a36Sopenharmony_ci KUNIT_EXPECT_PTR_EQ(test, tunnel->paths[0]->hops[0].in_port, in); 157962306a36Sopenharmony_ci /* Middle */ 158062306a36Sopenharmony_ci KUNIT_EXPECT_PTR_EQ(test, tunnel->paths[0]->hops[6].in_port, 158162306a36Sopenharmony_ci &host->ports[1]); 158262306a36Sopenharmony_ci KUNIT_EXPECT_PTR_EQ(test, tunnel->paths[0]->hops[6].out_port, 158362306a36Sopenharmony_ci &host->ports[3]); 158462306a36Sopenharmony_ci /* Last */ 158562306a36Sopenharmony_ci KUNIT_EXPECT_PTR_EQ(test, tunnel->paths[0]->hops[12].out_port, out); 158662306a36Sopenharmony_ci KUNIT_ASSERT_EQ(test, tunnel->paths[1]->path_length, 13); 158762306a36Sopenharmony_ci KUNIT_EXPECT_PTR_EQ(test, tunnel->paths[1]->hops[0].in_port, in); 158862306a36Sopenharmony_ci KUNIT_EXPECT_PTR_EQ(test, tunnel->paths[1]->hops[6].in_port, 158962306a36Sopenharmony_ci &host->ports[1]); 159062306a36Sopenharmony_ci KUNIT_EXPECT_PTR_EQ(test, tunnel->paths[1]->hops[6].out_port, 159162306a36Sopenharmony_ci &host->ports[3]); 159262306a36Sopenharmony_ci KUNIT_EXPECT_PTR_EQ(test, tunnel->paths[1]->hops[12].out_port, out); 159362306a36Sopenharmony_ci KUNIT_ASSERT_EQ(test, tunnel->paths[2]->path_length, 13); 159462306a36Sopenharmony_ci KUNIT_EXPECT_PTR_EQ(test, tunnel->paths[2]->hops[0].in_port, out); 159562306a36Sopenharmony_ci KUNIT_EXPECT_PTR_EQ(test, tunnel->paths[2]->hops[6].in_port, 159662306a36Sopenharmony_ci &host->ports[3]); 159762306a36Sopenharmony_ci KUNIT_EXPECT_PTR_EQ(test, tunnel->paths[2]->hops[6].out_port, 159862306a36Sopenharmony_ci &host->ports[1]); 159962306a36Sopenharmony_ci KUNIT_EXPECT_PTR_EQ(test, tunnel->paths[2]->hops[12].out_port, in); 160062306a36Sopenharmony_ci tb_tunnel_free(tunnel); 160162306a36Sopenharmony_ci} 160262306a36Sopenharmony_ci 160362306a36Sopenharmony_cistatic void tb_test_tunnel_3dp(struct kunit *test) 160462306a36Sopenharmony_ci{ 160562306a36Sopenharmony_ci struct tb_switch *host, *dev1, *dev2, *dev3, *dev4, *dev5; 160662306a36Sopenharmony_ci struct tb_port *in1, *in2, *in3, *out1, *out2, *out3; 160762306a36Sopenharmony_ci struct tb_tunnel *tunnel1, *tunnel2, *tunnel3; 160862306a36Sopenharmony_ci 160962306a36Sopenharmony_ci /* 161062306a36Sopenharmony_ci * Create 3 DP tunnels from Host to Devices #2, #5 and #4. 161162306a36Sopenharmony_ci * 161262306a36Sopenharmony_ci * [Host] 161362306a36Sopenharmony_ci * 3 | 161462306a36Sopenharmony_ci * 1 | 161562306a36Sopenharmony_ci * [Device #1] 161662306a36Sopenharmony_ci * 3 / | 5 \ 7 161762306a36Sopenharmony_ci * 1 / | \ 1 161862306a36Sopenharmony_ci * [Device #2] | [Device #4] 161962306a36Sopenharmony_ci * | 1 162062306a36Sopenharmony_ci * [Device #3] 162162306a36Sopenharmony_ci * | 5 162262306a36Sopenharmony_ci * | 1 162362306a36Sopenharmony_ci * [Device #5] 162462306a36Sopenharmony_ci */ 162562306a36Sopenharmony_ci host = alloc_host_br(test); 162662306a36Sopenharmony_ci dev1 = alloc_dev_default(test, host, 0x3, true); 162762306a36Sopenharmony_ci dev2 = alloc_dev_default(test, dev1, 0x303, true); 162862306a36Sopenharmony_ci dev3 = alloc_dev_default(test, dev1, 0x503, true); 162962306a36Sopenharmony_ci dev4 = alloc_dev_default(test, dev1, 0x703, true); 163062306a36Sopenharmony_ci dev5 = alloc_dev_default(test, dev3, 0x50503, true); 163162306a36Sopenharmony_ci 163262306a36Sopenharmony_ci in1 = &host->ports[5]; 163362306a36Sopenharmony_ci in2 = &host->ports[6]; 163462306a36Sopenharmony_ci in3 = &host->ports[10]; 163562306a36Sopenharmony_ci 163662306a36Sopenharmony_ci out1 = &dev2->ports[13]; 163762306a36Sopenharmony_ci out2 = &dev5->ports[13]; 163862306a36Sopenharmony_ci out3 = &dev4->ports[14]; 163962306a36Sopenharmony_ci 164062306a36Sopenharmony_ci tunnel1 = tb_tunnel_alloc_dp(NULL, in1, out1, 1, 0, 0); 164162306a36Sopenharmony_ci KUNIT_ASSERT_TRUE(test, tunnel1 != NULL); 164262306a36Sopenharmony_ci KUNIT_EXPECT_EQ(test, tunnel1->type, TB_TUNNEL_DP); 164362306a36Sopenharmony_ci KUNIT_EXPECT_PTR_EQ(test, tunnel1->src_port, in1); 164462306a36Sopenharmony_ci KUNIT_EXPECT_PTR_EQ(test, tunnel1->dst_port, out1); 164562306a36Sopenharmony_ci KUNIT_ASSERT_EQ(test, tunnel1->npaths, 3); 164662306a36Sopenharmony_ci KUNIT_ASSERT_EQ(test, tunnel1->paths[0]->path_length, 3); 164762306a36Sopenharmony_ci 164862306a36Sopenharmony_ci tunnel2 = tb_tunnel_alloc_dp(NULL, in2, out2, 1, 0, 0); 164962306a36Sopenharmony_ci KUNIT_ASSERT_TRUE(test, tunnel2 != NULL); 165062306a36Sopenharmony_ci KUNIT_EXPECT_EQ(test, tunnel2->type, TB_TUNNEL_DP); 165162306a36Sopenharmony_ci KUNIT_EXPECT_PTR_EQ(test, tunnel2->src_port, in2); 165262306a36Sopenharmony_ci KUNIT_EXPECT_PTR_EQ(test, tunnel2->dst_port, out2); 165362306a36Sopenharmony_ci KUNIT_ASSERT_EQ(test, tunnel2->npaths, 3); 165462306a36Sopenharmony_ci KUNIT_ASSERT_EQ(test, tunnel2->paths[0]->path_length, 4); 165562306a36Sopenharmony_ci 165662306a36Sopenharmony_ci tunnel3 = tb_tunnel_alloc_dp(NULL, in3, out3, 1, 0, 0); 165762306a36Sopenharmony_ci KUNIT_ASSERT_TRUE(test, tunnel3 != NULL); 165862306a36Sopenharmony_ci KUNIT_EXPECT_EQ(test, tunnel3->type, TB_TUNNEL_DP); 165962306a36Sopenharmony_ci KUNIT_EXPECT_PTR_EQ(test, tunnel3->src_port, in3); 166062306a36Sopenharmony_ci KUNIT_EXPECT_PTR_EQ(test, tunnel3->dst_port, out3); 166162306a36Sopenharmony_ci KUNIT_ASSERT_EQ(test, tunnel3->npaths, 3); 166262306a36Sopenharmony_ci KUNIT_ASSERT_EQ(test, tunnel3->paths[0]->path_length, 3); 166362306a36Sopenharmony_ci 166462306a36Sopenharmony_ci tb_tunnel_free(tunnel2); 166562306a36Sopenharmony_ci tb_tunnel_free(tunnel1); 166662306a36Sopenharmony_ci} 166762306a36Sopenharmony_ci 166862306a36Sopenharmony_cistatic void tb_test_tunnel_usb3(struct kunit *test) 166962306a36Sopenharmony_ci{ 167062306a36Sopenharmony_ci struct tb_switch *host, *dev1, *dev2; 167162306a36Sopenharmony_ci struct tb_tunnel *tunnel1, *tunnel2; 167262306a36Sopenharmony_ci struct tb_port *down, *up; 167362306a36Sopenharmony_ci 167462306a36Sopenharmony_ci /* 167562306a36Sopenharmony_ci * Create USB3 tunnel between host and two devices. 167662306a36Sopenharmony_ci * 167762306a36Sopenharmony_ci * [Host] 167862306a36Sopenharmony_ci * 1 | 167962306a36Sopenharmony_ci * 1 | 168062306a36Sopenharmony_ci * [Device #1] 168162306a36Sopenharmony_ci * \ 7 168262306a36Sopenharmony_ci * \ 1 168362306a36Sopenharmony_ci * [Device #2] 168462306a36Sopenharmony_ci */ 168562306a36Sopenharmony_ci host = alloc_host(test); 168662306a36Sopenharmony_ci dev1 = alloc_dev_default(test, host, 0x1, true); 168762306a36Sopenharmony_ci dev2 = alloc_dev_default(test, dev1, 0x701, true); 168862306a36Sopenharmony_ci 168962306a36Sopenharmony_ci down = &host->ports[12]; 169062306a36Sopenharmony_ci up = &dev1->ports[16]; 169162306a36Sopenharmony_ci tunnel1 = tb_tunnel_alloc_usb3(NULL, up, down, 0, 0); 169262306a36Sopenharmony_ci KUNIT_ASSERT_NOT_NULL(test, tunnel1); 169362306a36Sopenharmony_ci KUNIT_EXPECT_EQ(test, tunnel1->type, TB_TUNNEL_USB3); 169462306a36Sopenharmony_ci KUNIT_EXPECT_PTR_EQ(test, tunnel1->src_port, down); 169562306a36Sopenharmony_ci KUNIT_EXPECT_PTR_EQ(test, tunnel1->dst_port, up); 169662306a36Sopenharmony_ci KUNIT_ASSERT_EQ(test, tunnel1->npaths, 2); 169762306a36Sopenharmony_ci KUNIT_ASSERT_EQ(test, tunnel1->paths[0]->path_length, 2); 169862306a36Sopenharmony_ci KUNIT_EXPECT_PTR_EQ(test, tunnel1->paths[0]->hops[0].in_port, down); 169962306a36Sopenharmony_ci KUNIT_EXPECT_PTR_EQ(test, tunnel1->paths[0]->hops[1].out_port, up); 170062306a36Sopenharmony_ci KUNIT_ASSERT_EQ(test, tunnel1->paths[1]->path_length, 2); 170162306a36Sopenharmony_ci KUNIT_EXPECT_PTR_EQ(test, tunnel1->paths[1]->hops[0].in_port, up); 170262306a36Sopenharmony_ci KUNIT_EXPECT_PTR_EQ(test, tunnel1->paths[1]->hops[1].out_port, down); 170362306a36Sopenharmony_ci 170462306a36Sopenharmony_ci down = &dev1->ports[17]; 170562306a36Sopenharmony_ci up = &dev2->ports[16]; 170662306a36Sopenharmony_ci tunnel2 = tb_tunnel_alloc_usb3(NULL, up, down, 0, 0); 170762306a36Sopenharmony_ci KUNIT_ASSERT_NOT_NULL(test, tunnel2); 170862306a36Sopenharmony_ci KUNIT_EXPECT_EQ(test, tunnel2->type, TB_TUNNEL_USB3); 170962306a36Sopenharmony_ci KUNIT_EXPECT_PTR_EQ(test, tunnel2->src_port, down); 171062306a36Sopenharmony_ci KUNIT_EXPECT_PTR_EQ(test, tunnel2->dst_port, up); 171162306a36Sopenharmony_ci KUNIT_ASSERT_EQ(test, tunnel2->npaths, 2); 171262306a36Sopenharmony_ci KUNIT_ASSERT_EQ(test, tunnel2->paths[0]->path_length, 2); 171362306a36Sopenharmony_ci KUNIT_EXPECT_PTR_EQ(test, tunnel2->paths[0]->hops[0].in_port, down); 171462306a36Sopenharmony_ci KUNIT_EXPECT_PTR_EQ(test, tunnel2->paths[0]->hops[1].out_port, up); 171562306a36Sopenharmony_ci KUNIT_ASSERT_EQ(test, tunnel2->paths[1]->path_length, 2); 171662306a36Sopenharmony_ci KUNIT_EXPECT_PTR_EQ(test, tunnel2->paths[1]->hops[0].in_port, up); 171762306a36Sopenharmony_ci KUNIT_EXPECT_PTR_EQ(test, tunnel2->paths[1]->hops[1].out_port, down); 171862306a36Sopenharmony_ci 171962306a36Sopenharmony_ci tb_tunnel_free(tunnel2); 172062306a36Sopenharmony_ci tb_tunnel_free(tunnel1); 172162306a36Sopenharmony_ci} 172262306a36Sopenharmony_ci 172362306a36Sopenharmony_cistatic void tb_test_tunnel_port_on_path(struct kunit *test) 172462306a36Sopenharmony_ci{ 172562306a36Sopenharmony_ci struct tb_switch *host, *dev1, *dev2, *dev3, *dev4, *dev5; 172662306a36Sopenharmony_ci struct tb_port *in, *out, *port; 172762306a36Sopenharmony_ci struct tb_tunnel *dp_tunnel; 172862306a36Sopenharmony_ci 172962306a36Sopenharmony_ci /* 173062306a36Sopenharmony_ci * [Host] 173162306a36Sopenharmony_ci * 3 | 173262306a36Sopenharmony_ci * 1 | 173362306a36Sopenharmony_ci * [Device #1] 173462306a36Sopenharmony_ci * 3 / | 5 \ 7 173562306a36Sopenharmony_ci * 1 / | \ 1 173662306a36Sopenharmony_ci * [Device #2] | [Device #4] 173762306a36Sopenharmony_ci * | 1 173862306a36Sopenharmony_ci * [Device #3] 173962306a36Sopenharmony_ci * | 5 174062306a36Sopenharmony_ci * | 1 174162306a36Sopenharmony_ci * [Device #5] 174262306a36Sopenharmony_ci */ 174362306a36Sopenharmony_ci host = alloc_host(test); 174462306a36Sopenharmony_ci dev1 = alloc_dev_default(test, host, 0x3, true); 174562306a36Sopenharmony_ci dev2 = alloc_dev_with_dpin(test, dev1, 0x303, true); 174662306a36Sopenharmony_ci dev3 = alloc_dev_default(test, dev1, 0x503, true); 174762306a36Sopenharmony_ci dev4 = alloc_dev_default(test, dev1, 0x703, true); 174862306a36Sopenharmony_ci dev5 = alloc_dev_default(test, dev3, 0x50503, true); 174962306a36Sopenharmony_ci 175062306a36Sopenharmony_ci in = &dev2->ports[13]; 175162306a36Sopenharmony_ci out = &dev5->ports[13]; 175262306a36Sopenharmony_ci 175362306a36Sopenharmony_ci dp_tunnel = tb_tunnel_alloc_dp(NULL, in, out, 1, 0, 0); 175462306a36Sopenharmony_ci KUNIT_ASSERT_NOT_NULL(test, dp_tunnel); 175562306a36Sopenharmony_ci 175662306a36Sopenharmony_ci KUNIT_EXPECT_TRUE(test, tb_tunnel_port_on_path(dp_tunnel, in)); 175762306a36Sopenharmony_ci KUNIT_EXPECT_TRUE(test, tb_tunnel_port_on_path(dp_tunnel, out)); 175862306a36Sopenharmony_ci 175962306a36Sopenharmony_ci port = &host->ports[8]; 176062306a36Sopenharmony_ci KUNIT_EXPECT_FALSE(test, tb_tunnel_port_on_path(dp_tunnel, port)); 176162306a36Sopenharmony_ci 176262306a36Sopenharmony_ci port = &host->ports[3]; 176362306a36Sopenharmony_ci KUNIT_EXPECT_FALSE(test, tb_tunnel_port_on_path(dp_tunnel, port)); 176462306a36Sopenharmony_ci 176562306a36Sopenharmony_ci port = &dev1->ports[1]; 176662306a36Sopenharmony_ci KUNIT_EXPECT_FALSE(test, tb_tunnel_port_on_path(dp_tunnel, port)); 176762306a36Sopenharmony_ci 176862306a36Sopenharmony_ci port = &dev1->ports[3]; 176962306a36Sopenharmony_ci KUNIT_EXPECT_TRUE(test, tb_tunnel_port_on_path(dp_tunnel, port)); 177062306a36Sopenharmony_ci 177162306a36Sopenharmony_ci port = &dev1->ports[5]; 177262306a36Sopenharmony_ci KUNIT_EXPECT_TRUE(test, tb_tunnel_port_on_path(dp_tunnel, port)); 177362306a36Sopenharmony_ci 177462306a36Sopenharmony_ci port = &dev1->ports[7]; 177562306a36Sopenharmony_ci KUNIT_EXPECT_FALSE(test, tb_tunnel_port_on_path(dp_tunnel, port)); 177662306a36Sopenharmony_ci 177762306a36Sopenharmony_ci port = &dev3->ports[1]; 177862306a36Sopenharmony_ci KUNIT_EXPECT_TRUE(test, tb_tunnel_port_on_path(dp_tunnel, port)); 177962306a36Sopenharmony_ci 178062306a36Sopenharmony_ci port = &dev5->ports[1]; 178162306a36Sopenharmony_ci KUNIT_EXPECT_TRUE(test, tb_tunnel_port_on_path(dp_tunnel, port)); 178262306a36Sopenharmony_ci 178362306a36Sopenharmony_ci port = &dev4->ports[1]; 178462306a36Sopenharmony_ci KUNIT_EXPECT_FALSE(test, tb_tunnel_port_on_path(dp_tunnel, port)); 178562306a36Sopenharmony_ci 178662306a36Sopenharmony_ci tb_tunnel_free(dp_tunnel); 178762306a36Sopenharmony_ci} 178862306a36Sopenharmony_ci 178962306a36Sopenharmony_cistatic void tb_test_tunnel_dma(struct kunit *test) 179062306a36Sopenharmony_ci{ 179162306a36Sopenharmony_ci struct tb_port *nhi, *port; 179262306a36Sopenharmony_ci struct tb_tunnel *tunnel; 179362306a36Sopenharmony_ci struct tb_switch *host; 179462306a36Sopenharmony_ci 179562306a36Sopenharmony_ci /* 179662306a36Sopenharmony_ci * Create DMA tunnel from NHI to port 1 and back. 179762306a36Sopenharmony_ci * 179862306a36Sopenharmony_ci * [Host 1] 179962306a36Sopenharmony_ci * 1 ^ In HopID 1 -> Out HopID 8 180062306a36Sopenharmony_ci * | 180162306a36Sopenharmony_ci * v In HopID 8 -> Out HopID 1 180262306a36Sopenharmony_ci * ............ Domain border 180362306a36Sopenharmony_ci * | 180462306a36Sopenharmony_ci * [Host 2] 180562306a36Sopenharmony_ci */ 180662306a36Sopenharmony_ci host = alloc_host(test); 180762306a36Sopenharmony_ci nhi = &host->ports[7]; 180862306a36Sopenharmony_ci port = &host->ports[1]; 180962306a36Sopenharmony_ci 181062306a36Sopenharmony_ci tunnel = tb_tunnel_alloc_dma(NULL, nhi, port, 8, 1, 8, 1); 181162306a36Sopenharmony_ci KUNIT_ASSERT_NOT_NULL(test, tunnel); 181262306a36Sopenharmony_ci KUNIT_EXPECT_EQ(test, tunnel->type, TB_TUNNEL_DMA); 181362306a36Sopenharmony_ci KUNIT_EXPECT_PTR_EQ(test, tunnel->src_port, nhi); 181462306a36Sopenharmony_ci KUNIT_EXPECT_PTR_EQ(test, tunnel->dst_port, port); 181562306a36Sopenharmony_ci KUNIT_ASSERT_EQ(test, tunnel->npaths, 2); 181662306a36Sopenharmony_ci /* RX path */ 181762306a36Sopenharmony_ci KUNIT_ASSERT_EQ(test, tunnel->paths[0]->path_length, 1); 181862306a36Sopenharmony_ci KUNIT_EXPECT_PTR_EQ(test, tunnel->paths[0]->hops[0].in_port, port); 181962306a36Sopenharmony_ci KUNIT_EXPECT_EQ(test, tunnel->paths[0]->hops[0].in_hop_index, 8); 182062306a36Sopenharmony_ci KUNIT_EXPECT_PTR_EQ(test, tunnel->paths[0]->hops[0].out_port, nhi); 182162306a36Sopenharmony_ci KUNIT_EXPECT_EQ(test, tunnel->paths[0]->hops[0].next_hop_index, 1); 182262306a36Sopenharmony_ci /* TX path */ 182362306a36Sopenharmony_ci KUNIT_ASSERT_EQ(test, tunnel->paths[1]->path_length, 1); 182462306a36Sopenharmony_ci KUNIT_EXPECT_PTR_EQ(test, tunnel->paths[1]->hops[0].in_port, nhi); 182562306a36Sopenharmony_ci KUNIT_EXPECT_EQ(test, tunnel->paths[1]->hops[0].in_hop_index, 1); 182662306a36Sopenharmony_ci KUNIT_EXPECT_PTR_EQ(test, tunnel->paths[1]->hops[0].out_port, port); 182762306a36Sopenharmony_ci KUNIT_EXPECT_EQ(test, tunnel->paths[1]->hops[0].next_hop_index, 8); 182862306a36Sopenharmony_ci 182962306a36Sopenharmony_ci tb_tunnel_free(tunnel); 183062306a36Sopenharmony_ci} 183162306a36Sopenharmony_ci 183262306a36Sopenharmony_cistatic void tb_test_tunnel_dma_rx(struct kunit *test) 183362306a36Sopenharmony_ci{ 183462306a36Sopenharmony_ci struct tb_port *nhi, *port; 183562306a36Sopenharmony_ci struct tb_tunnel *tunnel; 183662306a36Sopenharmony_ci struct tb_switch *host; 183762306a36Sopenharmony_ci 183862306a36Sopenharmony_ci /* 183962306a36Sopenharmony_ci * Create DMA RX tunnel from port 1 to NHI. 184062306a36Sopenharmony_ci * 184162306a36Sopenharmony_ci * [Host 1] 184262306a36Sopenharmony_ci * 1 ^ 184362306a36Sopenharmony_ci * | 184462306a36Sopenharmony_ci * | In HopID 15 -> Out HopID 2 184562306a36Sopenharmony_ci * ............ Domain border 184662306a36Sopenharmony_ci * | 184762306a36Sopenharmony_ci * [Host 2] 184862306a36Sopenharmony_ci */ 184962306a36Sopenharmony_ci host = alloc_host(test); 185062306a36Sopenharmony_ci nhi = &host->ports[7]; 185162306a36Sopenharmony_ci port = &host->ports[1]; 185262306a36Sopenharmony_ci 185362306a36Sopenharmony_ci tunnel = tb_tunnel_alloc_dma(NULL, nhi, port, -1, -1, 15, 2); 185462306a36Sopenharmony_ci KUNIT_ASSERT_NOT_NULL(test, tunnel); 185562306a36Sopenharmony_ci KUNIT_EXPECT_EQ(test, tunnel->type, TB_TUNNEL_DMA); 185662306a36Sopenharmony_ci KUNIT_EXPECT_PTR_EQ(test, tunnel->src_port, nhi); 185762306a36Sopenharmony_ci KUNIT_EXPECT_PTR_EQ(test, tunnel->dst_port, port); 185862306a36Sopenharmony_ci KUNIT_ASSERT_EQ(test, tunnel->npaths, 1); 185962306a36Sopenharmony_ci /* RX path */ 186062306a36Sopenharmony_ci KUNIT_ASSERT_EQ(test, tunnel->paths[0]->path_length, 1); 186162306a36Sopenharmony_ci KUNIT_EXPECT_PTR_EQ(test, tunnel->paths[0]->hops[0].in_port, port); 186262306a36Sopenharmony_ci KUNIT_EXPECT_EQ(test, tunnel->paths[0]->hops[0].in_hop_index, 15); 186362306a36Sopenharmony_ci KUNIT_EXPECT_PTR_EQ(test, tunnel->paths[0]->hops[0].out_port, nhi); 186462306a36Sopenharmony_ci KUNIT_EXPECT_EQ(test, tunnel->paths[0]->hops[0].next_hop_index, 2); 186562306a36Sopenharmony_ci 186662306a36Sopenharmony_ci tb_tunnel_free(tunnel); 186762306a36Sopenharmony_ci} 186862306a36Sopenharmony_ci 186962306a36Sopenharmony_cistatic void tb_test_tunnel_dma_tx(struct kunit *test) 187062306a36Sopenharmony_ci{ 187162306a36Sopenharmony_ci struct tb_port *nhi, *port; 187262306a36Sopenharmony_ci struct tb_tunnel *tunnel; 187362306a36Sopenharmony_ci struct tb_switch *host; 187462306a36Sopenharmony_ci 187562306a36Sopenharmony_ci /* 187662306a36Sopenharmony_ci * Create DMA TX tunnel from NHI to port 1. 187762306a36Sopenharmony_ci * 187862306a36Sopenharmony_ci * [Host 1] 187962306a36Sopenharmony_ci * 1 | In HopID 2 -> Out HopID 15 188062306a36Sopenharmony_ci * | 188162306a36Sopenharmony_ci * v 188262306a36Sopenharmony_ci * ............ Domain border 188362306a36Sopenharmony_ci * | 188462306a36Sopenharmony_ci * [Host 2] 188562306a36Sopenharmony_ci */ 188662306a36Sopenharmony_ci host = alloc_host(test); 188762306a36Sopenharmony_ci nhi = &host->ports[7]; 188862306a36Sopenharmony_ci port = &host->ports[1]; 188962306a36Sopenharmony_ci 189062306a36Sopenharmony_ci tunnel = tb_tunnel_alloc_dma(NULL, nhi, port, 15, 2, -1, -1); 189162306a36Sopenharmony_ci KUNIT_ASSERT_NOT_NULL(test, tunnel); 189262306a36Sopenharmony_ci KUNIT_EXPECT_EQ(test, tunnel->type, TB_TUNNEL_DMA); 189362306a36Sopenharmony_ci KUNIT_EXPECT_PTR_EQ(test, tunnel->src_port, nhi); 189462306a36Sopenharmony_ci KUNIT_EXPECT_PTR_EQ(test, tunnel->dst_port, port); 189562306a36Sopenharmony_ci KUNIT_ASSERT_EQ(test, tunnel->npaths, 1); 189662306a36Sopenharmony_ci /* TX path */ 189762306a36Sopenharmony_ci KUNIT_ASSERT_EQ(test, tunnel->paths[0]->path_length, 1); 189862306a36Sopenharmony_ci KUNIT_EXPECT_PTR_EQ(test, tunnel->paths[0]->hops[0].in_port, nhi); 189962306a36Sopenharmony_ci KUNIT_EXPECT_EQ(test, tunnel->paths[0]->hops[0].in_hop_index, 2); 190062306a36Sopenharmony_ci KUNIT_EXPECT_PTR_EQ(test, tunnel->paths[0]->hops[0].out_port, port); 190162306a36Sopenharmony_ci KUNIT_EXPECT_EQ(test, tunnel->paths[0]->hops[0].next_hop_index, 15); 190262306a36Sopenharmony_ci 190362306a36Sopenharmony_ci tb_tunnel_free(tunnel); 190462306a36Sopenharmony_ci} 190562306a36Sopenharmony_ci 190662306a36Sopenharmony_cistatic void tb_test_tunnel_dma_chain(struct kunit *test) 190762306a36Sopenharmony_ci{ 190862306a36Sopenharmony_ci struct tb_switch *host, *dev1, *dev2; 190962306a36Sopenharmony_ci struct tb_port *nhi, *port; 191062306a36Sopenharmony_ci struct tb_tunnel *tunnel; 191162306a36Sopenharmony_ci 191262306a36Sopenharmony_ci /* 191362306a36Sopenharmony_ci * Create DMA tunnel from NHI to Device #2 port 3 and back. 191462306a36Sopenharmony_ci * 191562306a36Sopenharmony_ci * [Host 1] 191662306a36Sopenharmony_ci * 1 ^ In HopID 1 -> Out HopID x 191762306a36Sopenharmony_ci * | 191862306a36Sopenharmony_ci * 1 | In HopID x -> Out HopID 1 191962306a36Sopenharmony_ci * [Device #1] 192062306a36Sopenharmony_ci * 7 \ 192162306a36Sopenharmony_ci * 1 \ 192262306a36Sopenharmony_ci * [Device #2] 192362306a36Sopenharmony_ci * 3 | In HopID x -> Out HopID 8 192462306a36Sopenharmony_ci * | 192562306a36Sopenharmony_ci * v In HopID 8 -> Out HopID x 192662306a36Sopenharmony_ci * ............ Domain border 192762306a36Sopenharmony_ci * | 192862306a36Sopenharmony_ci * [Host 2] 192962306a36Sopenharmony_ci */ 193062306a36Sopenharmony_ci host = alloc_host(test); 193162306a36Sopenharmony_ci dev1 = alloc_dev_default(test, host, 0x1, true); 193262306a36Sopenharmony_ci dev2 = alloc_dev_default(test, dev1, 0x701, true); 193362306a36Sopenharmony_ci 193462306a36Sopenharmony_ci nhi = &host->ports[7]; 193562306a36Sopenharmony_ci port = &dev2->ports[3]; 193662306a36Sopenharmony_ci tunnel = tb_tunnel_alloc_dma(NULL, nhi, port, 8, 1, 8, 1); 193762306a36Sopenharmony_ci KUNIT_ASSERT_NOT_NULL(test, tunnel); 193862306a36Sopenharmony_ci KUNIT_EXPECT_EQ(test, tunnel->type, TB_TUNNEL_DMA); 193962306a36Sopenharmony_ci KUNIT_EXPECT_PTR_EQ(test, tunnel->src_port, nhi); 194062306a36Sopenharmony_ci KUNIT_EXPECT_PTR_EQ(test, tunnel->dst_port, port); 194162306a36Sopenharmony_ci KUNIT_ASSERT_EQ(test, tunnel->npaths, 2); 194262306a36Sopenharmony_ci /* RX path */ 194362306a36Sopenharmony_ci KUNIT_ASSERT_EQ(test, tunnel->paths[0]->path_length, 3); 194462306a36Sopenharmony_ci KUNIT_EXPECT_PTR_EQ(test, tunnel->paths[0]->hops[0].in_port, port); 194562306a36Sopenharmony_ci KUNIT_EXPECT_EQ(test, tunnel->paths[0]->hops[0].in_hop_index, 8); 194662306a36Sopenharmony_ci KUNIT_EXPECT_PTR_EQ(test, tunnel->paths[0]->hops[0].out_port, 194762306a36Sopenharmony_ci &dev2->ports[1]); 194862306a36Sopenharmony_ci KUNIT_EXPECT_PTR_EQ(test, tunnel->paths[0]->hops[1].in_port, 194962306a36Sopenharmony_ci &dev1->ports[7]); 195062306a36Sopenharmony_ci KUNIT_EXPECT_PTR_EQ(test, tunnel->paths[0]->hops[1].out_port, 195162306a36Sopenharmony_ci &dev1->ports[1]); 195262306a36Sopenharmony_ci KUNIT_EXPECT_PTR_EQ(test, tunnel->paths[0]->hops[2].in_port, 195362306a36Sopenharmony_ci &host->ports[1]); 195462306a36Sopenharmony_ci KUNIT_EXPECT_PTR_EQ(test, tunnel->paths[0]->hops[2].out_port, nhi); 195562306a36Sopenharmony_ci KUNIT_EXPECT_EQ(test, tunnel->paths[0]->hops[2].next_hop_index, 1); 195662306a36Sopenharmony_ci /* TX path */ 195762306a36Sopenharmony_ci KUNIT_ASSERT_EQ(test, tunnel->paths[1]->path_length, 3); 195862306a36Sopenharmony_ci KUNIT_EXPECT_PTR_EQ(test, tunnel->paths[1]->hops[0].in_port, nhi); 195962306a36Sopenharmony_ci KUNIT_EXPECT_EQ(test, tunnel->paths[1]->hops[0].in_hop_index, 1); 196062306a36Sopenharmony_ci KUNIT_EXPECT_PTR_EQ(test, tunnel->paths[1]->hops[1].in_port, 196162306a36Sopenharmony_ci &dev1->ports[1]); 196262306a36Sopenharmony_ci KUNIT_EXPECT_PTR_EQ(test, tunnel->paths[1]->hops[1].out_port, 196362306a36Sopenharmony_ci &dev1->ports[7]); 196462306a36Sopenharmony_ci KUNIT_EXPECT_PTR_EQ(test, tunnel->paths[1]->hops[2].in_port, 196562306a36Sopenharmony_ci &dev2->ports[1]); 196662306a36Sopenharmony_ci KUNIT_EXPECT_PTR_EQ(test, tunnel->paths[1]->hops[2].out_port, port); 196762306a36Sopenharmony_ci KUNIT_EXPECT_EQ(test, tunnel->paths[1]->hops[2].next_hop_index, 8); 196862306a36Sopenharmony_ci 196962306a36Sopenharmony_ci tb_tunnel_free(tunnel); 197062306a36Sopenharmony_ci} 197162306a36Sopenharmony_ci 197262306a36Sopenharmony_cistatic void tb_test_tunnel_dma_match(struct kunit *test) 197362306a36Sopenharmony_ci{ 197462306a36Sopenharmony_ci struct tb_port *nhi, *port; 197562306a36Sopenharmony_ci struct tb_tunnel *tunnel; 197662306a36Sopenharmony_ci struct tb_switch *host; 197762306a36Sopenharmony_ci 197862306a36Sopenharmony_ci host = alloc_host(test); 197962306a36Sopenharmony_ci nhi = &host->ports[7]; 198062306a36Sopenharmony_ci port = &host->ports[1]; 198162306a36Sopenharmony_ci 198262306a36Sopenharmony_ci tunnel = tb_tunnel_alloc_dma(NULL, nhi, port, 15, 1, 15, 1); 198362306a36Sopenharmony_ci KUNIT_ASSERT_NOT_NULL(test, tunnel); 198462306a36Sopenharmony_ci 198562306a36Sopenharmony_ci KUNIT_ASSERT_TRUE(test, tb_tunnel_match_dma(tunnel, 15, 1, 15, 1)); 198662306a36Sopenharmony_ci KUNIT_ASSERT_FALSE(test, tb_tunnel_match_dma(tunnel, 8, 1, 15, 1)); 198762306a36Sopenharmony_ci KUNIT_ASSERT_TRUE(test, tb_tunnel_match_dma(tunnel, -1, -1, 15, 1)); 198862306a36Sopenharmony_ci KUNIT_ASSERT_TRUE(test, tb_tunnel_match_dma(tunnel, 15, 1, -1, -1)); 198962306a36Sopenharmony_ci KUNIT_ASSERT_TRUE(test, tb_tunnel_match_dma(tunnel, 15, -1, -1, -1)); 199062306a36Sopenharmony_ci KUNIT_ASSERT_TRUE(test, tb_tunnel_match_dma(tunnel, -1, 1, -1, -1)); 199162306a36Sopenharmony_ci KUNIT_ASSERT_TRUE(test, tb_tunnel_match_dma(tunnel, -1, -1, 15, -1)); 199262306a36Sopenharmony_ci KUNIT_ASSERT_TRUE(test, tb_tunnel_match_dma(tunnel, -1, -1, -1, 1)); 199362306a36Sopenharmony_ci KUNIT_ASSERT_TRUE(test, tb_tunnel_match_dma(tunnel, -1, -1, -1, -1)); 199462306a36Sopenharmony_ci KUNIT_ASSERT_FALSE(test, tb_tunnel_match_dma(tunnel, 8, -1, 8, -1)); 199562306a36Sopenharmony_ci 199662306a36Sopenharmony_ci tb_tunnel_free(tunnel); 199762306a36Sopenharmony_ci 199862306a36Sopenharmony_ci tunnel = tb_tunnel_alloc_dma(NULL, nhi, port, 15, 1, -1, -1); 199962306a36Sopenharmony_ci KUNIT_ASSERT_NOT_NULL(test, tunnel); 200062306a36Sopenharmony_ci KUNIT_ASSERT_TRUE(test, tb_tunnel_match_dma(tunnel, 15, 1, -1, -1)); 200162306a36Sopenharmony_ci KUNIT_ASSERT_TRUE(test, tb_tunnel_match_dma(tunnel, 15, -1, -1, -1)); 200262306a36Sopenharmony_ci KUNIT_ASSERT_TRUE(test, tb_tunnel_match_dma(tunnel, -1, 1, -1, -1)); 200362306a36Sopenharmony_ci KUNIT_ASSERT_TRUE(test, tb_tunnel_match_dma(tunnel, -1, -1, -1, -1)); 200462306a36Sopenharmony_ci KUNIT_ASSERT_FALSE(test, tb_tunnel_match_dma(tunnel, 15, 1, 15, 1)); 200562306a36Sopenharmony_ci KUNIT_ASSERT_FALSE(test, tb_tunnel_match_dma(tunnel, -1, -1, 15, 1)); 200662306a36Sopenharmony_ci KUNIT_ASSERT_FALSE(test, tb_tunnel_match_dma(tunnel, 15, 11, -1, -1)); 200762306a36Sopenharmony_ci 200862306a36Sopenharmony_ci tb_tunnel_free(tunnel); 200962306a36Sopenharmony_ci 201062306a36Sopenharmony_ci tunnel = tb_tunnel_alloc_dma(NULL, nhi, port, -1, -1, 15, 11); 201162306a36Sopenharmony_ci KUNIT_ASSERT_NOT_NULL(test, tunnel); 201262306a36Sopenharmony_ci KUNIT_ASSERT_TRUE(test, tb_tunnel_match_dma(tunnel, -1, -1, 15, 11)); 201362306a36Sopenharmony_ci KUNIT_ASSERT_TRUE(test, tb_tunnel_match_dma(tunnel, -1, -1, 15, -1)); 201462306a36Sopenharmony_ci KUNIT_ASSERT_TRUE(test, tb_tunnel_match_dma(tunnel, -1, -1, -1, 11)); 201562306a36Sopenharmony_ci KUNIT_ASSERT_TRUE(test, tb_tunnel_match_dma(tunnel, -1, -1, -1, -1)); 201662306a36Sopenharmony_ci KUNIT_ASSERT_FALSE(test, tb_tunnel_match_dma(tunnel, -1, -1, 15, 1)); 201762306a36Sopenharmony_ci KUNIT_ASSERT_FALSE(test, tb_tunnel_match_dma(tunnel, -1, -1, 10, 11)); 201862306a36Sopenharmony_ci KUNIT_ASSERT_FALSE(test, tb_tunnel_match_dma(tunnel, 15, 11, -1, -1)); 201962306a36Sopenharmony_ci 202062306a36Sopenharmony_ci tb_tunnel_free(tunnel); 202162306a36Sopenharmony_ci} 202262306a36Sopenharmony_ci 202362306a36Sopenharmony_cistatic void tb_test_credit_alloc_legacy_not_bonded(struct kunit *test) 202462306a36Sopenharmony_ci{ 202562306a36Sopenharmony_ci struct tb_switch *host, *dev; 202662306a36Sopenharmony_ci struct tb_port *up, *down; 202762306a36Sopenharmony_ci struct tb_tunnel *tunnel; 202862306a36Sopenharmony_ci struct tb_path *path; 202962306a36Sopenharmony_ci 203062306a36Sopenharmony_ci host = alloc_host(test); 203162306a36Sopenharmony_ci dev = alloc_dev_default(test, host, 0x1, false); 203262306a36Sopenharmony_ci 203362306a36Sopenharmony_ci down = &host->ports[8]; 203462306a36Sopenharmony_ci up = &dev->ports[9]; 203562306a36Sopenharmony_ci tunnel = tb_tunnel_alloc_pci(NULL, up, down); 203662306a36Sopenharmony_ci KUNIT_ASSERT_NOT_NULL(test, tunnel); 203762306a36Sopenharmony_ci KUNIT_ASSERT_EQ(test, tunnel->npaths, (size_t)2); 203862306a36Sopenharmony_ci 203962306a36Sopenharmony_ci path = tunnel->paths[0]; 204062306a36Sopenharmony_ci KUNIT_ASSERT_EQ(test, path->path_length, 2); 204162306a36Sopenharmony_ci KUNIT_EXPECT_EQ(test, path->hops[0].nfc_credits, 0U); 204262306a36Sopenharmony_ci KUNIT_EXPECT_EQ(test, path->hops[0].initial_credits, 7U); 204362306a36Sopenharmony_ci KUNIT_EXPECT_EQ(test, path->hops[1].nfc_credits, 0U); 204462306a36Sopenharmony_ci KUNIT_EXPECT_EQ(test, path->hops[1].initial_credits, 16U); 204562306a36Sopenharmony_ci 204662306a36Sopenharmony_ci path = tunnel->paths[1]; 204762306a36Sopenharmony_ci KUNIT_ASSERT_EQ(test, path->path_length, 2); 204862306a36Sopenharmony_ci KUNIT_EXPECT_EQ(test, path->hops[0].nfc_credits, 0U); 204962306a36Sopenharmony_ci KUNIT_EXPECT_EQ(test, path->hops[0].initial_credits, 7U); 205062306a36Sopenharmony_ci KUNIT_EXPECT_EQ(test, path->hops[1].nfc_credits, 0U); 205162306a36Sopenharmony_ci KUNIT_EXPECT_EQ(test, path->hops[1].initial_credits, 16U); 205262306a36Sopenharmony_ci 205362306a36Sopenharmony_ci tb_tunnel_free(tunnel); 205462306a36Sopenharmony_ci} 205562306a36Sopenharmony_ci 205662306a36Sopenharmony_cistatic void tb_test_credit_alloc_legacy_bonded(struct kunit *test) 205762306a36Sopenharmony_ci{ 205862306a36Sopenharmony_ci struct tb_switch *host, *dev; 205962306a36Sopenharmony_ci struct tb_port *up, *down; 206062306a36Sopenharmony_ci struct tb_tunnel *tunnel; 206162306a36Sopenharmony_ci struct tb_path *path; 206262306a36Sopenharmony_ci 206362306a36Sopenharmony_ci host = alloc_host(test); 206462306a36Sopenharmony_ci dev = alloc_dev_default(test, host, 0x1, true); 206562306a36Sopenharmony_ci 206662306a36Sopenharmony_ci down = &host->ports[8]; 206762306a36Sopenharmony_ci up = &dev->ports[9]; 206862306a36Sopenharmony_ci tunnel = tb_tunnel_alloc_pci(NULL, up, down); 206962306a36Sopenharmony_ci KUNIT_ASSERT_NOT_NULL(test, tunnel); 207062306a36Sopenharmony_ci KUNIT_ASSERT_EQ(test, tunnel->npaths, (size_t)2); 207162306a36Sopenharmony_ci 207262306a36Sopenharmony_ci path = tunnel->paths[0]; 207362306a36Sopenharmony_ci KUNIT_ASSERT_EQ(test, path->path_length, 2); 207462306a36Sopenharmony_ci KUNIT_EXPECT_EQ(test, path->hops[0].nfc_credits, 0U); 207562306a36Sopenharmony_ci KUNIT_EXPECT_EQ(test, path->hops[0].initial_credits, 7U); 207662306a36Sopenharmony_ci KUNIT_EXPECT_EQ(test, path->hops[1].nfc_credits, 0U); 207762306a36Sopenharmony_ci KUNIT_EXPECT_EQ(test, path->hops[1].initial_credits, 32U); 207862306a36Sopenharmony_ci 207962306a36Sopenharmony_ci path = tunnel->paths[1]; 208062306a36Sopenharmony_ci KUNIT_ASSERT_EQ(test, path->path_length, 2); 208162306a36Sopenharmony_ci KUNIT_EXPECT_EQ(test, path->hops[0].nfc_credits, 0U); 208262306a36Sopenharmony_ci KUNIT_EXPECT_EQ(test, path->hops[0].initial_credits, 7U); 208362306a36Sopenharmony_ci KUNIT_EXPECT_EQ(test, path->hops[1].nfc_credits, 0U); 208462306a36Sopenharmony_ci KUNIT_EXPECT_EQ(test, path->hops[1].initial_credits, 32U); 208562306a36Sopenharmony_ci 208662306a36Sopenharmony_ci tb_tunnel_free(tunnel); 208762306a36Sopenharmony_ci} 208862306a36Sopenharmony_ci 208962306a36Sopenharmony_cistatic void tb_test_credit_alloc_pcie(struct kunit *test) 209062306a36Sopenharmony_ci{ 209162306a36Sopenharmony_ci struct tb_switch *host, *dev; 209262306a36Sopenharmony_ci struct tb_port *up, *down; 209362306a36Sopenharmony_ci struct tb_tunnel *tunnel; 209462306a36Sopenharmony_ci struct tb_path *path; 209562306a36Sopenharmony_ci 209662306a36Sopenharmony_ci host = alloc_host_usb4(test); 209762306a36Sopenharmony_ci dev = alloc_dev_usb4(test, host, 0x1, true); 209862306a36Sopenharmony_ci 209962306a36Sopenharmony_ci down = &host->ports[8]; 210062306a36Sopenharmony_ci up = &dev->ports[9]; 210162306a36Sopenharmony_ci tunnel = tb_tunnel_alloc_pci(NULL, up, down); 210262306a36Sopenharmony_ci KUNIT_ASSERT_NOT_NULL(test, tunnel); 210362306a36Sopenharmony_ci KUNIT_ASSERT_EQ(test, tunnel->npaths, (size_t)2); 210462306a36Sopenharmony_ci 210562306a36Sopenharmony_ci path = tunnel->paths[0]; 210662306a36Sopenharmony_ci KUNIT_ASSERT_EQ(test, path->path_length, 2); 210762306a36Sopenharmony_ci KUNIT_EXPECT_EQ(test, path->hops[0].nfc_credits, 0U); 210862306a36Sopenharmony_ci KUNIT_EXPECT_EQ(test, path->hops[0].initial_credits, 7U); 210962306a36Sopenharmony_ci KUNIT_EXPECT_EQ(test, path->hops[1].nfc_credits, 0U); 211062306a36Sopenharmony_ci KUNIT_EXPECT_EQ(test, path->hops[1].initial_credits, 32U); 211162306a36Sopenharmony_ci 211262306a36Sopenharmony_ci path = tunnel->paths[1]; 211362306a36Sopenharmony_ci KUNIT_ASSERT_EQ(test, path->path_length, 2); 211462306a36Sopenharmony_ci KUNIT_EXPECT_EQ(test, path->hops[0].nfc_credits, 0U); 211562306a36Sopenharmony_ci KUNIT_EXPECT_EQ(test, path->hops[0].initial_credits, 7U); 211662306a36Sopenharmony_ci KUNIT_EXPECT_EQ(test, path->hops[1].nfc_credits, 0U); 211762306a36Sopenharmony_ci KUNIT_EXPECT_EQ(test, path->hops[1].initial_credits, 64U); 211862306a36Sopenharmony_ci 211962306a36Sopenharmony_ci tb_tunnel_free(tunnel); 212062306a36Sopenharmony_ci} 212162306a36Sopenharmony_ci 212262306a36Sopenharmony_cistatic void tb_test_credit_alloc_without_dp(struct kunit *test) 212362306a36Sopenharmony_ci{ 212462306a36Sopenharmony_ci struct tb_switch *host, *dev; 212562306a36Sopenharmony_ci struct tb_port *up, *down; 212662306a36Sopenharmony_ci struct tb_tunnel *tunnel; 212762306a36Sopenharmony_ci struct tb_path *path; 212862306a36Sopenharmony_ci 212962306a36Sopenharmony_ci host = alloc_host_usb4(test); 213062306a36Sopenharmony_ci dev = alloc_dev_without_dp(test, host, 0x1, true); 213162306a36Sopenharmony_ci 213262306a36Sopenharmony_ci /* 213362306a36Sopenharmony_ci * The device has no DP therefore baMinDPmain = baMinDPaux = 0 213462306a36Sopenharmony_ci * 213562306a36Sopenharmony_ci * Create PCIe path with buffers less than baMaxPCIe. 213662306a36Sopenharmony_ci * 213762306a36Sopenharmony_ci * For a device with buffers configurations: 213862306a36Sopenharmony_ci * baMaxUSB3 = 109 213962306a36Sopenharmony_ci * baMinDPaux = 0 214062306a36Sopenharmony_ci * baMinDPmain = 0 214162306a36Sopenharmony_ci * baMaxPCIe = 30 214262306a36Sopenharmony_ci * baMaxHI = 1 214362306a36Sopenharmony_ci * Remaining Buffers = Total - (CP + DP) = 120 - (2 + 0) = 118 214462306a36Sopenharmony_ci * PCIe Credits = Max(6, Min(baMaxPCIe, Remaining Buffers - baMaxUSB3) 214562306a36Sopenharmony_ci * = Max(6, Min(30, 9) = 9 214662306a36Sopenharmony_ci */ 214762306a36Sopenharmony_ci down = &host->ports[8]; 214862306a36Sopenharmony_ci up = &dev->ports[9]; 214962306a36Sopenharmony_ci tunnel = tb_tunnel_alloc_pci(NULL, up, down); 215062306a36Sopenharmony_ci KUNIT_ASSERT_TRUE(test, tunnel != NULL); 215162306a36Sopenharmony_ci KUNIT_ASSERT_EQ(test, tunnel->npaths, (size_t)2); 215262306a36Sopenharmony_ci 215362306a36Sopenharmony_ci /* PCIe downstream path */ 215462306a36Sopenharmony_ci path = tunnel->paths[0]; 215562306a36Sopenharmony_ci KUNIT_ASSERT_EQ(test, path->path_length, 2); 215662306a36Sopenharmony_ci KUNIT_EXPECT_EQ(test, path->hops[0].nfc_credits, 0U); 215762306a36Sopenharmony_ci KUNIT_EXPECT_EQ(test, path->hops[0].initial_credits, 7U); 215862306a36Sopenharmony_ci KUNIT_EXPECT_EQ(test, path->hops[1].nfc_credits, 0U); 215962306a36Sopenharmony_ci KUNIT_EXPECT_EQ(test, path->hops[1].initial_credits, 9U); 216062306a36Sopenharmony_ci 216162306a36Sopenharmony_ci /* PCIe upstream path */ 216262306a36Sopenharmony_ci path = tunnel->paths[1]; 216362306a36Sopenharmony_ci KUNIT_ASSERT_EQ(test, path->path_length, 2); 216462306a36Sopenharmony_ci KUNIT_EXPECT_EQ(test, path->hops[0].nfc_credits, 0U); 216562306a36Sopenharmony_ci KUNIT_EXPECT_EQ(test, path->hops[0].initial_credits, 7U); 216662306a36Sopenharmony_ci KUNIT_EXPECT_EQ(test, path->hops[1].nfc_credits, 0U); 216762306a36Sopenharmony_ci KUNIT_EXPECT_EQ(test, path->hops[1].initial_credits, 64U); 216862306a36Sopenharmony_ci 216962306a36Sopenharmony_ci tb_tunnel_free(tunnel); 217062306a36Sopenharmony_ci} 217162306a36Sopenharmony_ci 217262306a36Sopenharmony_cistatic void tb_test_credit_alloc_dp(struct kunit *test) 217362306a36Sopenharmony_ci{ 217462306a36Sopenharmony_ci struct tb_switch *host, *dev; 217562306a36Sopenharmony_ci struct tb_port *in, *out; 217662306a36Sopenharmony_ci struct tb_tunnel *tunnel; 217762306a36Sopenharmony_ci struct tb_path *path; 217862306a36Sopenharmony_ci 217962306a36Sopenharmony_ci host = alloc_host_usb4(test); 218062306a36Sopenharmony_ci dev = alloc_dev_usb4(test, host, 0x1, true); 218162306a36Sopenharmony_ci 218262306a36Sopenharmony_ci in = &host->ports[5]; 218362306a36Sopenharmony_ci out = &dev->ports[14]; 218462306a36Sopenharmony_ci 218562306a36Sopenharmony_ci tunnel = tb_tunnel_alloc_dp(NULL, in, out, 1, 0, 0); 218662306a36Sopenharmony_ci KUNIT_ASSERT_NOT_NULL(test, tunnel); 218762306a36Sopenharmony_ci KUNIT_ASSERT_EQ(test, tunnel->npaths, (size_t)3); 218862306a36Sopenharmony_ci 218962306a36Sopenharmony_ci /* Video (main) path */ 219062306a36Sopenharmony_ci path = tunnel->paths[0]; 219162306a36Sopenharmony_ci KUNIT_ASSERT_EQ(test, path->path_length, 2); 219262306a36Sopenharmony_ci KUNIT_EXPECT_EQ(test, path->hops[0].nfc_credits, 12U); 219362306a36Sopenharmony_ci KUNIT_EXPECT_EQ(test, path->hops[0].initial_credits, 0U); 219462306a36Sopenharmony_ci KUNIT_EXPECT_EQ(test, path->hops[1].nfc_credits, 18U); 219562306a36Sopenharmony_ci KUNIT_EXPECT_EQ(test, path->hops[1].initial_credits, 0U); 219662306a36Sopenharmony_ci 219762306a36Sopenharmony_ci /* AUX TX */ 219862306a36Sopenharmony_ci path = tunnel->paths[1]; 219962306a36Sopenharmony_ci KUNIT_ASSERT_EQ(test, path->path_length, 2); 220062306a36Sopenharmony_ci KUNIT_EXPECT_EQ(test, path->hops[0].nfc_credits, 0U); 220162306a36Sopenharmony_ci KUNIT_EXPECT_EQ(test, path->hops[0].initial_credits, 1U); 220262306a36Sopenharmony_ci KUNIT_EXPECT_EQ(test, path->hops[1].nfc_credits, 0U); 220362306a36Sopenharmony_ci KUNIT_EXPECT_EQ(test, path->hops[1].initial_credits, 1U); 220462306a36Sopenharmony_ci 220562306a36Sopenharmony_ci /* AUX RX */ 220662306a36Sopenharmony_ci path = tunnel->paths[2]; 220762306a36Sopenharmony_ci KUNIT_ASSERT_EQ(test, path->path_length, 2); 220862306a36Sopenharmony_ci KUNIT_EXPECT_EQ(test, path->hops[0].nfc_credits, 0U); 220962306a36Sopenharmony_ci KUNIT_EXPECT_EQ(test, path->hops[0].initial_credits, 1U); 221062306a36Sopenharmony_ci KUNIT_EXPECT_EQ(test, path->hops[1].nfc_credits, 0U); 221162306a36Sopenharmony_ci KUNIT_EXPECT_EQ(test, path->hops[1].initial_credits, 1U); 221262306a36Sopenharmony_ci 221362306a36Sopenharmony_ci tb_tunnel_free(tunnel); 221462306a36Sopenharmony_ci} 221562306a36Sopenharmony_ci 221662306a36Sopenharmony_cistatic void tb_test_credit_alloc_usb3(struct kunit *test) 221762306a36Sopenharmony_ci{ 221862306a36Sopenharmony_ci struct tb_switch *host, *dev; 221962306a36Sopenharmony_ci struct tb_port *up, *down; 222062306a36Sopenharmony_ci struct tb_tunnel *tunnel; 222162306a36Sopenharmony_ci struct tb_path *path; 222262306a36Sopenharmony_ci 222362306a36Sopenharmony_ci host = alloc_host_usb4(test); 222462306a36Sopenharmony_ci dev = alloc_dev_usb4(test, host, 0x1, true); 222562306a36Sopenharmony_ci 222662306a36Sopenharmony_ci down = &host->ports[12]; 222762306a36Sopenharmony_ci up = &dev->ports[16]; 222862306a36Sopenharmony_ci tunnel = tb_tunnel_alloc_usb3(NULL, up, down, 0, 0); 222962306a36Sopenharmony_ci KUNIT_ASSERT_NOT_NULL(test, tunnel); 223062306a36Sopenharmony_ci KUNIT_ASSERT_EQ(test, tunnel->npaths, (size_t)2); 223162306a36Sopenharmony_ci 223262306a36Sopenharmony_ci path = tunnel->paths[0]; 223362306a36Sopenharmony_ci KUNIT_ASSERT_EQ(test, path->path_length, 2); 223462306a36Sopenharmony_ci KUNIT_EXPECT_EQ(test, path->hops[0].nfc_credits, 0U); 223562306a36Sopenharmony_ci KUNIT_EXPECT_EQ(test, path->hops[0].initial_credits, 7U); 223662306a36Sopenharmony_ci KUNIT_EXPECT_EQ(test, path->hops[1].nfc_credits, 0U); 223762306a36Sopenharmony_ci KUNIT_EXPECT_EQ(test, path->hops[1].initial_credits, 14U); 223862306a36Sopenharmony_ci 223962306a36Sopenharmony_ci path = tunnel->paths[1]; 224062306a36Sopenharmony_ci KUNIT_ASSERT_EQ(test, path->path_length, 2); 224162306a36Sopenharmony_ci KUNIT_EXPECT_EQ(test, path->hops[0].nfc_credits, 0U); 224262306a36Sopenharmony_ci KUNIT_EXPECT_EQ(test, path->hops[0].initial_credits, 7U); 224362306a36Sopenharmony_ci KUNIT_EXPECT_EQ(test, path->hops[1].nfc_credits, 0U); 224462306a36Sopenharmony_ci KUNIT_EXPECT_EQ(test, path->hops[1].initial_credits, 32U); 224562306a36Sopenharmony_ci 224662306a36Sopenharmony_ci tb_tunnel_free(tunnel); 224762306a36Sopenharmony_ci} 224862306a36Sopenharmony_ci 224962306a36Sopenharmony_cistatic void tb_test_credit_alloc_dma(struct kunit *test) 225062306a36Sopenharmony_ci{ 225162306a36Sopenharmony_ci struct tb_switch *host, *dev; 225262306a36Sopenharmony_ci struct tb_port *nhi, *port; 225362306a36Sopenharmony_ci struct tb_tunnel *tunnel; 225462306a36Sopenharmony_ci struct tb_path *path; 225562306a36Sopenharmony_ci 225662306a36Sopenharmony_ci host = alloc_host_usb4(test); 225762306a36Sopenharmony_ci dev = alloc_dev_usb4(test, host, 0x1, true); 225862306a36Sopenharmony_ci 225962306a36Sopenharmony_ci nhi = &host->ports[7]; 226062306a36Sopenharmony_ci port = &dev->ports[3]; 226162306a36Sopenharmony_ci 226262306a36Sopenharmony_ci tunnel = tb_tunnel_alloc_dma(NULL, nhi, port, 8, 1, 8, 1); 226362306a36Sopenharmony_ci KUNIT_ASSERT_NOT_NULL(test, tunnel); 226462306a36Sopenharmony_ci KUNIT_ASSERT_EQ(test, tunnel->npaths, (size_t)2); 226562306a36Sopenharmony_ci 226662306a36Sopenharmony_ci /* DMA RX */ 226762306a36Sopenharmony_ci path = tunnel->paths[0]; 226862306a36Sopenharmony_ci KUNIT_ASSERT_EQ(test, path->path_length, 2); 226962306a36Sopenharmony_ci KUNIT_EXPECT_EQ(test, path->hops[0].nfc_credits, 0U); 227062306a36Sopenharmony_ci KUNIT_EXPECT_EQ(test, path->hops[0].initial_credits, 14U); 227162306a36Sopenharmony_ci KUNIT_EXPECT_EQ(test, path->hops[1].nfc_credits, 0U); 227262306a36Sopenharmony_ci KUNIT_EXPECT_EQ(test, path->hops[1].initial_credits, 14U); 227362306a36Sopenharmony_ci 227462306a36Sopenharmony_ci /* DMA TX */ 227562306a36Sopenharmony_ci path = tunnel->paths[1]; 227662306a36Sopenharmony_ci KUNIT_ASSERT_EQ(test, path->path_length, 2); 227762306a36Sopenharmony_ci KUNIT_EXPECT_EQ(test, path->hops[0].nfc_credits, 0U); 227862306a36Sopenharmony_ci KUNIT_EXPECT_EQ(test, path->hops[0].initial_credits, 0U); 227962306a36Sopenharmony_ci KUNIT_EXPECT_EQ(test, path->hops[1].nfc_credits, 0U); 228062306a36Sopenharmony_ci KUNIT_EXPECT_EQ(test, path->hops[1].initial_credits, 14U); 228162306a36Sopenharmony_ci 228262306a36Sopenharmony_ci tb_tunnel_free(tunnel); 228362306a36Sopenharmony_ci} 228462306a36Sopenharmony_ci 228562306a36Sopenharmony_cistatic void tb_test_credit_alloc_dma_multiple(struct kunit *test) 228662306a36Sopenharmony_ci{ 228762306a36Sopenharmony_ci struct tb_tunnel *tunnel1, *tunnel2, *tunnel3; 228862306a36Sopenharmony_ci struct tb_switch *host, *dev; 228962306a36Sopenharmony_ci struct tb_port *nhi, *port; 229062306a36Sopenharmony_ci struct tb_path *path; 229162306a36Sopenharmony_ci 229262306a36Sopenharmony_ci host = alloc_host_usb4(test); 229362306a36Sopenharmony_ci dev = alloc_dev_usb4(test, host, 0x1, true); 229462306a36Sopenharmony_ci 229562306a36Sopenharmony_ci nhi = &host->ports[7]; 229662306a36Sopenharmony_ci port = &dev->ports[3]; 229762306a36Sopenharmony_ci 229862306a36Sopenharmony_ci /* 229962306a36Sopenharmony_ci * Create three DMA tunnels through the same ports. With the 230062306a36Sopenharmony_ci * default buffers we should be able to create two and the last 230162306a36Sopenharmony_ci * one fails. 230262306a36Sopenharmony_ci * 230362306a36Sopenharmony_ci * For default host we have following buffers for DMA: 230462306a36Sopenharmony_ci * 230562306a36Sopenharmony_ci * 120 - (2 + 2 * (1 + 0) + 32 + 64 + spare) = 20 230662306a36Sopenharmony_ci * 230762306a36Sopenharmony_ci * For device we have following: 230862306a36Sopenharmony_ci * 230962306a36Sopenharmony_ci * 120 - (2 + 2 * (1 + 18) + 14 + 32 + spare) = 34 231062306a36Sopenharmony_ci * 231162306a36Sopenharmony_ci * spare = 14 + 1 = 15 231262306a36Sopenharmony_ci * 231362306a36Sopenharmony_ci * So on host the first tunnel gets 14 and the second gets the 231462306a36Sopenharmony_ci * remaining 1 and then we run out of buffers. 231562306a36Sopenharmony_ci */ 231662306a36Sopenharmony_ci tunnel1 = tb_tunnel_alloc_dma(NULL, nhi, port, 8, 1, 8, 1); 231762306a36Sopenharmony_ci KUNIT_ASSERT_NOT_NULL(test, tunnel1); 231862306a36Sopenharmony_ci KUNIT_ASSERT_EQ(test, tunnel1->npaths, (size_t)2); 231962306a36Sopenharmony_ci 232062306a36Sopenharmony_ci path = tunnel1->paths[0]; 232162306a36Sopenharmony_ci KUNIT_ASSERT_EQ(test, path->path_length, 2); 232262306a36Sopenharmony_ci KUNIT_EXPECT_EQ(test, path->hops[0].nfc_credits, 0U); 232362306a36Sopenharmony_ci KUNIT_EXPECT_EQ(test, path->hops[0].initial_credits, 14U); 232462306a36Sopenharmony_ci KUNIT_EXPECT_EQ(test, path->hops[1].nfc_credits, 0U); 232562306a36Sopenharmony_ci KUNIT_EXPECT_EQ(test, path->hops[1].initial_credits, 14U); 232662306a36Sopenharmony_ci 232762306a36Sopenharmony_ci path = tunnel1->paths[1]; 232862306a36Sopenharmony_ci KUNIT_ASSERT_EQ(test, path->path_length, 2); 232962306a36Sopenharmony_ci KUNIT_EXPECT_EQ(test, path->hops[0].nfc_credits, 0U); 233062306a36Sopenharmony_ci KUNIT_EXPECT_EQ(test, path->hops[0].initial_credits, 0U); 233162306a36Sopenharmony_ci KUNIT_EXPECT_EQ(test, path->hops[1].nfc_credits, 0U); 233262306a36Sopenharmony_ci KUNIT_EXPECT_EQ(test, path->hops[1].initial_credits, 14U); 233362306a36Sopenharmony_ci 233462306a36Sopenharmony_ci tunnel2 = tb_tunnel_alloc_dma(NULL, nhi, port, 9, 2, 9, 2); 233562306a36Sopenharmony_ci KUNIT_ASSERT_NOT_NULL(test, tunnel2); 233662306a36Sopenharmony_ci KUNIT_ASSERT_EQ(test, tunnel2->npaths, (size_t)2); 233762306a36Sopenharmony_ci 233862306a36Sopenharmony_ci path = tunnel2->paths[0]; 233962306a36Sopenharmony_ci KUNIT_ASSERT_EQ(test, path->path_length, 2); 234062306a36Sopenharmony_ci KUNIT_EXPECT_EQ(test, path->hops[0].nfc_credits, 0U); 234162306a36Sopenharmony_ci KUNIT_EXPECT_EQ(test, path->hops[0].initial_credits, 14U); 234262306a36Sopenharmony_ci KUNIT_EXPECT_EQ(test, path->hops[1].nfc_credits, 0U); 234362306a36Sopenharmony_ci KUNIT_EXPECT_EQ(test, path->hops[1].initial_credits, 1U); 234462306a36Sopenharmony_ci 234562306a36Sopenharmony_ci path = tunnel2->paths[1]; 234662306a36Sopenharmony_ci KUNIT_ASSERT_EQ(test, path->path_length, 2); 234762306a36Sopenharmony_ci KUNIT_EXPECT_EQ(test, path->hops[0].nfc_credits, 0U); 234862306a36Sopenharmony_ci KUNIT_EXPECT_EQ(test, path->hops[0].initial_credits, 0U); 234962306a36Sopenharmony_ci KUNIT_EXPECT_EQ(test, path->hops[1].nfc_credits, 0U); 235062306a36Sopenharmony_ci KUNIT_EXPECT_EQ(test, path->hops[1].initial_credits, 1U); 235162306a36Sopenharmony_ci 235262306a36Sopenharmony_ci tunnel3 = tb_tunnel_alloc_dma(NULL, nhi, port, 10, 3, 10, 3); 235362306a36Sopenharmony_ci KUNIT_ASSERT_NULL(test, tunnel3); 235462306a36Sopenharmony_ci 235562306a36Sopenharmony_ci /* 235662306a36Sopenharmony_ci * Release the first DMA tunnel. That should make 14 buffers 235762306a36Sopenharmony_ci * available for the next tunnel. 235862306a36Sopenharmony_ci */ 235962306a36Sopenharmony_ci tb_tunnel_free(tunnel1); 236062306a36Sopenharmony_ci 236162306a36Sopenharmony_ci tunnel3 = tb_tunnel_alloc_dma(NULL, nhi, port, 10, 3, 10, 3); 236262306a36Sopenharmony_ci KUNIT_ASSERT_NOT_NULL(test, tunnel3); 236362306a36Sopenharmony_ci 236462306a36Sopenharmony_ci path = tunnel3->paths[0]; 236562306a36Sopenharmony_ci KUNIT_ASSERT_EQ(test, path->path_length, 2); 236662306a36Sopenharmony_ci KUNIT_EXPECT_EQ(test, path->hops[0].nfc_credits, 0U); 236762306a36Sopenharmony_ci KUNIT_EXPECT_EQ(test, path->hops[0].initial_credits, 14U); 236862306a36Sopenharmony_ci KUNIT_EXPECT_EQ(test, path->hops[1].nfc_credits, 0U); 236962306a36Sopenharmony_ci KUNIT_EXPECT_EQ(test, path->hops[1].initial_credits, 14U); 237062306a36Sopenharmony_ci 237162306a36Sopenharmony_ci path = tunnel3->paths[1]; 237262306a36Sopenharmony_ci KUNIT_ASSERT_EQ(test, path->path_length, 2); 237362306a36Sopenharmony_ci KUNIT_EXPECT_EQ(test, path->hops[0].nfc_credits, 0U); 237462306a36Sopenharmony_ci KUNIT_EXPECT_EQ(test, path->hops[0].initial_credits, 0U); 237562306a36Sopenharmony_ci KUNIT_EXPECT_EQ(test, path->hops[1].nfc_credits, 0U); 237662306a36Sopenharmony_ci KUNIT_EXPECT_EQ(test, path->hops[1].initial_credits, 14U); 237762306a36Sopenharmony_ci 237862306a36Sopenharmony_ci tb_tunnel_free(tunnel3); 237962306a36Sopenharmony_ci tb_tunnel_free(tunnel2); 238062306a36Sopenharmony_ci} 238162306a36Sopenharmony_ci 238262306a36Sopenharmony_cistatic struct tb_tunnel *TB_TEST_PCIE_TUNNEL(struct kunit *test, 238362306a36Sopenharmony_ci struct tb_switch *host, struct tb_switch *dev) 238462306a36Sopenharmony_ci{ 238562306a36Sopenharmony_ci struct tb_port *up, *down; 238662306a36Sopenharmony_ci struct tb_tunnel *pcie_tunnel; 238762306a36Sopenharmony_ci struct tb_path *path; 238862306a36Sopenharmony_ci 238962306a36Sopenharmony_ci down = &host->ports[8]; 239062306a36Sopenharmony_ci up = &dev->ports[9]; 239162306a36Sopenharmony_ci pcie_tunnel = tb_tunnel_alloc_pci(NULL, up, down); 239262306a36Sopenharmony_ci KUNIT_ASSERT_NOT_NULL(test, pcie_tunnel); 239362306a36Sopenharmony_ci KUNIT_ASSERT_EQ(test, pcie_tunnel->npaths, (size_t)2); 239462306a36Sopenharmony_ci 239562306a36Sopenharmony_ci path = pcie_tunnel->paths[0]; 239662306a36Sopenharmony_ci KUNIT_ASSERT_EQ(test, path->path_length, 2); 239762306a36Sopenharmony_ci KUNIT_EXPECT_EQ(test, path->hops[0].nfc_credits, 0U); 239862306a36Sopenharmony_ci KUNIT_EXPECT_EQ(test, path->hops[0].initial_credits, 7U); 239962306a36Sopenharmony_ci KUNIT_EXPECT_EQ(test, path->hops[1].nfc_credits, 0U); 240062306a36Sopenharmony_ci KUNIT_EXPECT_EQ(test, path->hops[1].initial_credits, 32U); 240162306a36Sopenharmony_ci 240262306a36Sopenharmony_ci path = pcie_tunnel->paths[1]; 240362306a36Sopenharmony_ci KUNIT_ASSERT_EQ(test, path->path_length, 2); 240462306a36Sopenharmony_ci KUNIT_EXPECT_EQ(test, path->hops[0].nfc_credits, 0U); 240562306a36Sopenharmony_ci KUNIT_EXPECT_EQ(test, path->hops[0].initial_credits, 7U); 240662306a36Sopenharmony_ci KUNIT_EXPECT_EQ(test, path->hops[1].nfc_credits, 0U); 240762306a36Sopenharmony_ci KUNIT_EXPECT_EQ(test, path->hops[1].initial_credits, 64U); 240862306a36Sopenharmony_ci 240962306a36Sopenharmony_ci return pcie_tunnel; 241062306a36Sopenharmony_ci} 241162306a36Sopenharmony_ci 241262306a36Sopenharmony_cistatic struct tb_tunnel *TB_TEST_DP_TUNNEL1(struct kunit *test, 241362306a36Sopenharmony_ci struct tb_switch *host, struct tb_switch *dev) 241462306a36Sopenharmony_ci{ 241562306a36Sopenharmony_ci struct tb_port *in, *out; 241662306a36Sopenharmony_ci struct tb_tunnel *dp_tunnel1; 241762306a36Sopenharmony_ci struct tb_path *path; 241862306a36Sopenharmony_ci 241962306a36Sopenharmony_ci in = &host->ports[5]; 242062306a36Sopenharmony_ci out = &dev->ports[13]; 242162306a36Sopenharmony_ci dp_tunnel1 = tb_tunnel_alloc_dp(NULL, in, out, 1, 0, 0); 242262306a36Sopenharmony_ci KUNIT_ASSERT_NOT_NULL(test, dp_tunnel1); 242362306a36Sopenharmony_ci KUNIT_ASSERT_EQ(test, dp_tunnel1->npaths, (size_t)3); 242462306a36Sopenharmony_ci 242562306a36Sopenharmony_ci path = dp_tunnel1->paths[0]; 242662306a36Sopenharmony_ci KUNIT_ASSERT_EQ(test, path->path_length, 2); 242762306a36Sopenharmony_ci KUNIT_EXPECT_EQ(test, path->hops[0].nfc_credits, 12U); 242862306a36Sopenharmony_ci KUNIT_EXPECT_EQ(test, path->hops[0].initial_credits, 0U); 242962306a36Sopenharmony_ci KUNIT_EXPECT_EQ(test, path->hops[1].nfc_credits, 18U); 243062306a36Sopenharmony_ci KUNIT_EXPECT_EQ(test, path->hops[1].initial_credits, 0U); 243162306a36Sopenharmony_ci 243262306a36Sopenharmony_ci path = dp_tunnel1->paths[1]; 243362306a36Sopenharmony_ci KUNIT_ASSERT_EQ(test, path->path_length, 2); 243462306a36Sopenharmony_ci KUNIT_EXPECT_EQ(test, path->hops[0].nfc_credits, 0U); 243562306a36Sopenharmony_ci KUNIT_EXPECT_EQ(test, path->hops[0].initial_credits, 1U); 243662306a36Sopenharmony_ci KUNIT_EXPECT_EQ(test, path->hops[1].nfc_credits, 0U); 243762306a36Sopenharmony_ci KUNIT_EXPECT_EQ(test, path->hops[1].initial_credits, 1U); 243862306a36Sopenharmony_ci 243962306a36Sopenharmony_ci path = dp_tunnel1->paths[2]; 244062306a36Sopenharmony_ci KUNIT_ASSERT_EQ(test, path->path_length, 2); 244162306a36Sopenharmony_ci KUNIT_EXPECT_EQ(test, path->hops[0].nfc_credits, 0U); 244262306a36Sopenharmony_ci KUNIT_EXPECT_EQ(test, path->hops[0].initial_credits, 1U); 244362306a36Sopenharmony_ci KUNIT_EXPECT_EQ(test, path->hops[1].nfc_credits, 0U); 244462306a36Sopenharmony_ci KUNIT_EXPECT_EQ(test, path->hops[1].initial_credits, 1U); 244562306a36Sopenharmony_ci 244662306a36Sopenharmony_ci return dp_tunnel1; 244762306a36Sopenharmony_ci} 244862306a36Sopenharmony_ci 244962306a36Sopenharmony_cistatic struct tb_tunnel *TB_TEST_DP_TUNNEL2(struct kunit *test, 245062306a36Sopenharmony_ci struct tb_switch *host, struct tb_switch *dev) 245162306a36Sopenharmony_ci{ 245262306a36Sopenharmony_ci struct tb_port *in, *out; 245362306a36Sopenharmony_ci struct tb_tunnel *dp_tunnel2; 245462306a36Sopenharmony_ci struct tb_path *path; 245562306a36Sopenharmony_ci 245662306a36Sopenharmony_ci in = &host->ports[6]; 245762306a36Sopenharmony_ci out = &dev->ports[14]; 245862306a36Sopenharmony_ci dp_tunnel2 = tb_tunnel_alloc_dp(NULL, in, out, 1, 0, 0); 245962306a36Sopenharmony_ci KUNIT_ASSERT_NOT_NULL(test, dp_tunnel2); 246062306a36Sopenharmony_ci KUNIT_ASSERT_EQ(test, dp_tunnel2->npaths, (size_t)3); 246162306a36Sopenharmony_ci 246262306a36Sopenharmony_ci path = dp_tunnel2->paths[0]; 246362306a36Sopenharmony_ci KUNIT_ASSERT_EQ(test, path->path_length, 2); 246462306a36Sopenharmony_ci KUNIT_EXPECT_EQ(test, path->hops[0].nfc_credits, 12U); 246562306a36Sopenharmony_ci KUNIT_EXPECT_EQ(test, path->hops[0].initial_credits, 0U); 246662306a36Sopenharmony_ci KUNIT_EXPECT_EQ(test, path->hops[1].nfc_credits, 18U); 246762306a36Sopenharmony_ci KUNIT_EXPECT_EQ(test, path->hops[1].initial_credits, 0U); 246862306a36Sopenharmony_ci 246962306a36Sopenharmony_ci path = dp_tunnel2->paths[1]; 247062306a36Sopenharmony_ci KUNIT_ASSERT_EQ(test, path->path_length, 2); 247162306a36Sopenharmony_ci KUNIT_EXPECT_EQ(test, path->hops[0].nfc_credits, 0U); 247262306a36Sopenharmony_ci KUNIT_EXPECT_EQ(test, path->hops[0].initial_credits, 1U); 247362306a36Sopenharmony_ci KUNIT_EXPECT_EQ(test, path->hops[1].nfc_credits, 0U); 247462306a36Sopenharmony_ci KUNIT_EXPECT_EQ(test, path->hops[1].initial_credits, 1U); 247562306a36Sopenharmony_ci 247662306a36Sopenharmony_ci path = dp_tunnel2->paths[2]; 247762306a36Sopenharmony_ci KUNIT_ASSERT_EQ(test, path->path_length, 2); 247862306a36Sopenharmony_ci KUNIT_EXPECT_EQ(test, path->hops[0].nfc_credits, 0U); 247962306a36Sopenharmony_ci KUNIT_EXPECT_EQ(test, path->hops[0].initial_credits, 1U); 248062306a36Sopenharmony_ci KUNIT_EXPECT_EQ(test, path->hops[1].nfc_credits, 0U); 248162306a36Sopenharmony_ci KUNIT_EXPECT_EQ(test, path->hops[1].initial_credits, 1U); 248262306a36Sopenharmony_ci 248362306a36Sopenharmony_ci return dp_tunnel2; 248462306a36Sopenharmony_ci} 248562306a36Sopenharmony_ci 248662306a36Sopenharmony_cistatic struct tb_tunnel *TB_TEST_USB3_TUNNEL(struct kunit *test, 248762306a36Sopenharmony_ci struct tb_switch *host, struct tb_switch *dev) 248862306a36Sopenharmony_ci{ 248962306a36Sopenharmony_ci struct tb_port *up, *down; 249062306a36Sopenharmony_ci struct tb_tunnel *usb3_tunnel; 249162306a36Sopenharmony_ci struct tb_path *path; 249262306a36Sopenharmony_ci 249362306a36Sopenharmony_ci down = &host->ports[12]; 249462306a36Sopenharmony_ci up = &dev->ports[16]; 249562306a36Sopenharmony_ci usb3_tunnel = tb_tunnel_alloc_usb3(NULL, up, down, 0, 0); 249662306a36Sopenharmony_ci KUNIT_ASSERT_NOT_NULL(test, usb3_tunnel); 249762306a36Sopenharmony_ci KUNIT_ASSERT_EQ(test, usb3_tunnel->npaths, (size_t)2); 249862306a36Sopenharmony_ci 249962306a36Sopenharmony_ci path = usb3_tunnel->paths[0]; 250062306a36Sopenharmony_ci KUNIT_ASSERT_EQ(test, path->path_length, 2); 250162306a36Sopenharmony_ci KUNIT_EXPECT_EQ(test, path->hops[0].nfc_credits, 0U); 250262306a36Sopenharmony_ci KUNIT_EXPECT_EQ(test, path->hops[0].initial_credits, 7U); 250362306a36Sopenharmony_ci KUNIT_EXPECT_EQ(test, path->hops[1].nfc_credits, 0U); 250462306a36Sopenharmony_ci KUNIT_EXPECT_EQ(test, path->hops[1].initial_credits, 14U); 250562306a36Sopenharmony_ci 250662306a36Sopenharmony_ci path = usb3_tunnel->paths[1]; 250762306a36Sopenharmony_ci KUNIT_ASSERT_EQ(test, path->path_length, 2); 250862306a36Sopenharmony_ci KUNIT_EXPECT_EQ(test, path->hops[0].nfc_credits, 0U); 250962306a36Sopenharmony_ci KUNIT_EXPECT_EQ(test, path->hops[0].initial_credits, 7U); 251062306a36Sopenharmony_ci KUNIT_EXPECT_EQ(test, path->hops[1].nfc_credits, 0U); 251162306a36Sopenharmony_ci KUNIT_EXPECT_EQ(test, path->hops[1].initial_credits, 32U); 251262306a36Sopenharmony_ci 251362306a36Sopenharmony_ci return usb3_tunnel; 251462306a36Sopenharmony_ci} 251562306a36Sopenharmony_ci 251662306a36Sopenharmony_cistatic struct tb_tunnel *TB_TEST_DMA_TUNNEL1(struct kunit *test, 251762306a36Sopenharmony_ci struct tb_switch *host, struct tb_switch *dev) 251862306a36Sopenharmony_ci{ 251962306a36Sopenharmony_ci struct tb_port *nhi, *port; 252062306a36Sopenharmony_ci struct tb_tunnel *dma_tunnel1; 252162306a36Sopenharmony_ci struct tb_path *path; 252262306a36Sopenharmony_ci 252362306a36Sopenharmony_ci nhi = &host->ports[7]; 252462306a36Sopenharmony_ci port = &dev->ports[3]; 252562306a36Sopenharmony_ci dma_tunnel1 = tb_tunnel_alloc_dma(NULL, nhi, port, 8, 1, 8, 1); 252662306a36Sopenharmony_ci KUNIT_ASSERT_NOT_NULL(test, dma_tunnel1); 252762306a36Sopenharmony_ci KUNIT_ASSERT_EQ(test, dma_tunnel1->npaths, (size_t)2); 252862306a36Sopenharmony_ci 252962306a36Sopenharmony_ci path = dma_tunnel1->paths[0]; 253062306a36Sopenharmony_ci KUNIT_ASSERT_EQ(test, path->path_length, 2); 253162306a36Sopenharmony_ci KUNIT_EXPECT_EQ(test, path->hops[0].nfc_credits, 0U); 253262306a36Sopenharmony_ci KUNIT_EXPECT_EQ(test, path->hops[0].initial_credits, 14U); 253362306a36Sopenharmony_ci KUNIT_EXPECT_EQ(test, path->hops[1].nfc_credits, 0U); 253462306a36Sopenharmony_ci KUNIT_EXPECT_EQ(test, path->hops[1].initial_credits, 14U); 253562306a36Sopenharmony_ci 253662306a36Sopenharmony_ci path = dma_tunnel1->paths[1]; 253762306a36Sopenharmony_ci KUNIT_ASSERT_EQ(test, path->path_length, 2); 253862306a36Sopenharmony_ci KUNIT_EXPECT_EQ(test, path->hops[0].nfc_credits, 0U); 253962306a36Sopenharmony_ci KUNIT_EXPECT_EQ(test, path->hops[0].initial_credits, 0U); 254062306a36Sopenharmony_ci KUNIT_EXPECT_EQ(test, path->hops[1].nfc_credits, 0U); 254162306a36Sopenharmony_ci KUNIT_EXPECT_EQ(test, path->hops[1].initial_credits, 14U); 254262306a36Sopenharmony_ci 254362306a36Sopenharmony_ci return dma_tunnel1; 254462306a36Sopenharmony_ci} 254562306a36Sopenharmony_ci 254662306a36Sopenharmony_cistatic struct tb_tunnel *TB_TEST_DMA_TUNNEL2(struct kunit *test, 254762306a36Sopenharmony_ci struct tb_switch *host, struct tb_switch *dev) 254862306a36Sopenharmony_ci{ 254962306a36Sopenharmony_ci struct tb_port *nhi, *port; 255062306a36Sopenharmony_ci struct tb_tunnel *dma_tunnel2; 255162306a36Sopenharmony_ci struct tb_path *path; 255262306a36Sopenharmony_ci 255362306a36Sopenharmony_ci nhi = &host->ports[7]; 255462306a36Sopenharmony_ci port = &dev->ports[3]; 255562306a36Sopenharmony_ci dma_tunnel2 = tb_tunnel_alloc_dma(NULL, nhi, port, 9, 2, 9, 2); 255662306a36Sopenharmony_ci KUNIT_ASSERT_NOT_NULL(test, dma_tunnel2); 255762306a36Sopenharmony_ci KUNIT_ASSERT_EQ(test, dma_tunnel2->npaths, (size_t)2); 255862306a36Sopenharmony_ci 255962306a36Sopenharmony_ci path = dma_tunnel2->paths[0]; 256062306a36Sopenharmony_ci KUNIT_ASSERT_EQ(test, path->path_length, 2); 256162306a36Sopenharmony_ci KUNIT_EXPECT_EQ(test, path->hops[0].nfc_credits, 0U); 256262306a36Sopenharmony_ci KUNIT_EXPECT_EQ(test, path->hops[0].initial_credits, 14U); 256362306a36Sopenharmony_ci KUNIT_EXPECT_EQ(test, path->hops[1].nfc_credits, 0U); 256462306a36Sopenharmony_ci KUNIT_EXPECT_EQ(test, path->hops[1].initial_credits, 1U); 256562306a36Sopenharmony_ci 256662306a36Sopenharmony_ci path = dma_tunnel2->paths[1]; 256762306a36Sopenharmony_ci KUNIT_ASSERT_EQ(test, path->path_length, 2); 256862306a36Sopenharmony_ci KUNIT_EXPECT_EQ(test, path->hops[0].nfc_credits, 0U); 256962306a36Sopenharmony_ci KUNIT_EXPECT_EQ(test, path->hops[0].initial_credits, 0U); 257062306a36Sopenharmony_ci KUNIT_EXPECT_EQ(test, path->hops[1].nfc_credits, 0U); 257162306a36Sopenharmony_ci KUNIT_EXPECT_EQ(test, path->hops[1].initial_credits, 1U); 257262306a36Sopenharmony_ci 257362306a36Sopenharmony_ci return dma_tunnel2; 257462306a36Sopenharmony_ci} 257562306a36Sopenharmony_ci 257662306a36Sopenharmony_cistatic void tb_test_credit_alloc_all(struct kunit *test) 257762306a36Sopenharmony_ci{ 257862306a36Sopenharmony_ci struct tb_tunnel *pcie_tunnel, *dp_tunnel1, *dp_tunnel2, *usb3_tunnel; 257962306a36Sopenharmony_ci struct tb_tunnel *dma_tunnel1, *dma_tunnel2; 258062306a36Sopenharmony_ci struct tb_switch *host, *dev; 258162306a36Sopenharmony_ci 258262306a36Sopenharmony_ci /* 258362306a36Sopenharmony_ci * Create PCIe, 2 x DP, USB 3.x and two DMA tunnels from host to 258462306a36Sopenharmony_ci * device. Expectation is that all these can be established with 258562306a36Sopenharmony_ci * the default credit allocation found in Intel hardware. 258662306a36Sopenharmony_ci */ 258762306a36Sopenharmony_ci 258862306a36Sopenharmony_ci host = alloc_host_usb4(test); 258962306a36Sopenharmony_ci dev = alloc_dev_usb4(test, host, 0x1, true); 259062306a36Sopenharmony_ci 259162306a36Sopenharmony_ci pcie_tunnel = TB_TEST_PCIE_TUNNEL(test, host, dev); 259262306a36Sopenharmony_ci dp_tunnel1 = TB_TEST_DP_TUNNEL1(test, host, dev); 259362306a36Sopenharmony_ci dp_tunnel2 = TB_TEST_DP_TUNNEL2(test, host, dev); 259462306a36Sopenharmony_ci usb3_tunnel = TB_TEST_USB3_TUNNEL(test, host, dev); 259562306a36Sopenharmony_ci dma_tunnel1 = TB_TEST_DMA_TUNNEL1(test, host, dev); 259662306a36Sopenharmony_ci dma_tunnel2 = TB_TEST_DMA_TUNNEL2(test, host, dev); 259762306a36Sopenharmony_ci 259862306a36Sopenharmony_ci tb_tunnel_free(dma_tunnel2); 259962306a36Sopenharmony_ci tb_tunnel_free(dma_tunnel1); 260062306a36Sopenharmony_ci tb_tunnel_free(usb3_tunnel); 260162306a36Sopenharmony_ci tb_tunnel_free(dp_tunnel2); 260262306a36Sopenharmony_ci tb_tunnel_free(dp_tunnel1); 260362306a36Sopenharmony_ci tb_tunnel_free(pcie_tunnel); 260462306a36Sopenharmony_ci} 260562306a36Sopenharmony_ci 260662306a36Sopenharmony_cistatic const u32 root_directory[] = { 260762306a36Sopenharmony_ci 0x55584401, /* "UXD" v1 */ 260862306a36Sopenharmony_ci 0x00000018, /* Root directory length */ 260962306a36Sopenharmony_ci 0x76656e64, /* "vend" */ 261062306a36Sopenharmony_ci 0x6f726964, /* "orid" */ 261162306a36Sopenharmony_ci 0x76000001, /* "v" R 1 */ 261262306a36Sopenharmony_ci 0x00000a27, /* Immediate value, ! Vendor ID */ 261362306a36Sopenharmony_ci 0x76656e64, /* "vend" */ 261462306a36Sopenharmony_ci 0x6f726964, /* "orid" */ 261562306a36Sopenharmony_ci 0x74000003, /* "t" R 3 */ 261662306a36Sopenharmony_ci 0x0000001a, /* Text leaf offset, (“Apple Inc.”) */ 261762306a36Sopenharmony_ci 0x64657669, /* "devi" */ 261862306a36Sopenharmony_ci 0x63656964, /* "ceid" */ 261962306a36Sopenharmony_ci 0x76000001, /* "v" R 1 */ 262062306a36Sopenharmony_ci 0x0000000a, /* Immediate value, ! Device ID */ 262162306a36Sopenharmony_ci 0x64657669, /* "devi" */ 262262306a36Sopenharmony_ci 0x63656964, /* "ceid" */ 262362306a36Sopenharmony_ci 0x74000003, /* "t" R 3 */ 262462306a36Sopenharmony_ci 0x0000001d, /* Text leaf offset, (“Macintosh”) */ 262562306a36Sopenharmony_ci 0x64657669, /* "devi" */ 262662306a36Sopenharmony_ci 0x63657276, /* "cerv" */ 262762306a36Sopenharmony_ci 0x76000001, /* "v" R 1 */ 262862306a36Sopenharmony_ci 0x80000100, /* Immediate value, Device Revision */ 262962306a36Sopenharmony_ci 0x6e657477, /* "netw" */ 263062306a36Sopenharmony_ci 0x6f726b00, /* "ork" */ 263162306a36Sopenharmony_ci 0x44000014, /* "D" R 20 */ 263262306a36Sopenharmony_ci 0x00000021, /* Directory data offset, (Network Directory) */ 263362306a36Sopenharmony_ci 0x4170706c, /* "Appl" */ 263462306a36Sopenharmony_ci 0x6520496e, /* "e In" */ 263562306a36Sopenharmony_ci 0x632e0000, /* "c." ! */ 263662306a36Sopenharmony_ci 0x4d616369, /* "Maci" */ 263762306a36Sopenharmony_ci 0x6e746f73, /* "ntos" */ 263862306a36Sopenharmony_ci 0x68000000, /* "h" */ 263962306a36Sopenharmony_ci 0x00000000, /* padding */ 264062306a36Sopenharmony_ci 0xca8961c6, /* Directory UUID, Network Directory */ 264162306a36Sopenharmony_ci 0x9541ce1c, /* Directory UUID, Network Directory */ 264262306a36Sopenharmony_ci 0x5949b8bd, /* Directory UUID, Network Directory */ 264362306a36Sopenharmony_ci 0x4f5a5f2e, /* Directory UUID, Network Directory */ 264462306a36Sopenharmony_ci 0x70727463, /* "prtc" */ 264562306a36Sopenharmony_ci 0x69640000, /* "id" */ 264662306a36Sopenharmony_ci 0x76000001, /* "v" R 1 */ 264762306a36Sopenharmony_ci 0x00000001, /* Immediate value, Network Protocol ID */ 264862306a36Sopenharmony_ci 0x70727463, /* "prtc" */ 264962306a36Sopenharmony_ci 0x76657273, /* "vers" */ 265062306a36Sopenharmony_ci 0x76000001, /* "v" R 1 */ 265162306a36Sopenharmony_ci 0x00000001, /* Immediate value, Network Protocol Version */ 265262306a36Sopenharmony_ci 0x70727463, /* "prtc" */ 265362306a36Sopenharmony_ci 0x72657673, /* "revs" */ 265462306a36Sopenharmony_ci 0x76000001, /* "v" R 1 */ 265562306a36Sopenharmony_ci 0x00000001, /* Immediate value, Network Protocol Revision */ 265662306a36Sopenharmony_ci 0x70727463, /* "prtc" */ 265762306a36Sopenharmony_ci 0x73746e73, /* "stns" */ 265862306a36Sopenharmony_ci 0x76000001, /* "v" R 1 */ 265962306a36Sopenharmony_ci 0x00000000, /* Immediate value, Network Protocol Settings */ 266062306a36Sopenharmony_ci}; 266162306a36Sopenharmony_ci 266262306a36Sopenharmony_cistatic const uuid_t network_dir_uuid = 266362306a36Sopenharmony_ci UUID_INIT(0xc66189ca, 0x1cce, 0x4195, 266462306a36Sopenharmony_ci 0xbd, 0xb8, 0x49, 0x59, 0x2e, 0x5f, 0x5a, 0x4f); 266562306a36Sopenharmony_ci 266662306a36Sopenharmony_cistatic void tb_test_property_parse(struct kunit *test) 266762306a36Sopenharmony_ci{ 266862306a36Sopenharmony_ci struct tb_property_dir *dir, *network_dir; 266962306a36Sopenharmony_ci struct tb_property *p; 267062306a36Sopenharmony_ci 267162306a36Sopenharmony_ci dir = tb_property_parse_dir(root_directory, ARRAY_SIZE(root_directory)); 267262306a36Sopenharmony_ci KUNIT_ASSERT_NOT_NULL(test, dir); 267362306a36Sopenharmony_ci 267462306a36Sopenharmony_ci p = tb_property_find(dir, "foo", TB_PROPERTY_TYPE_TEXT); 267562306a36Sopenharmony_ci KUNIT_ASSERT_NULL(test, p); 267662306a36Sopenharmony_ci 267762306a36Sopenharmony_ci p = tb_property_find(dir, "vendorid", TB_PROPERTY_TYPE_TEXT); 267862306a36Sopenharmony_ci KUNIT_ASSERT_NOT_NULL(test, p); 267962306a36Sopenharmony_ci KUNIT_EXPECT_STREQ(test, p->value.text, "Apple Inc."); 268062306a36Sopenharmony_ci 268162306a36Sopenharmony_ci p = tb_property_find(dir, "vendorid", TB_PROPERTY_TYPE_VALUE); 268262306a36Sopenharmony_ci KUNIT_ASSERT_NOT_NULL(test, p); 268362306a36Sopenharmony_ci KUNIT_EXPECT_EQ(test, p->value.immediate, 0xa27); 268462306a36Sopenharmony_ci 268562306a36Sopenharmony_ci p = tb_property_find(dir, "deviceid", TB_PROPERTY_TYPE_TEXT); 268662306a36Sopenharmony_ci KUNIT_ASSERT_NOT_NULL(test, p); 268762306a36Sopenharmony_ci KUNIT_EXPECT_STREQ(test, p->value.text, "Macintosh"); 268862306a36Sopenharmony_ci 268962306a36Sopenharmony_ci p = tb_property_find(dir, "deviceid", TB_PROPERTY_TYPE_VALUE); 269062306a36Sopenharmony_ci KUNIT_ASSERT_NOT_NULL(test, p); 269162306a36Sopenharmony_ci KUNIT_EXPECT_EQ(test, p->value.immediate, 0xa); 269262306a36Sopenharmony_ci 269362306a36Sopenharmony_ci p = tb_property_find(dir, "missing", TB_PROPERTY_TYPE_DIRECTORY); 269462306a36Sopenharmony_ci KUNIT_ASSERT_NULL(test, p); 269562306a36Sopenharmony_ci 269662306a36Sopenharmony_ci p = tb_property_find(dir, "network", TB_PROPERTY_TYPE_DIRECTORY); 269762306a36Sopenharmony_ci KUNIT_ASSERT_NOT_NULL(test, p); 269862306a36Sopenharmony_ci 269962306a36Sopenharmony_ci network_dir = p->value.dir; 270062306a36Sopenharmony_ci KUNIT_EXPECT_TRUE(test, uuid_equal(network_dir->uuid, &network_dir_uuid)); 270162306a36Sopenharmony_ci 270262306a36Sopenharmony_ci p = tb_property_find(network_dir, "prtcid", TB_PROPERTY_TYPE_VALUE); 270362306a36Sopenharmony_ci KUNIT_ASSERT_NOT_NULL(test, p); 270462306a36Sopenharmony_ci KUNIT_EXPECT_EQ(test, p->value.immediate, 0x1); 270562306a36Sopenharmony_ci 270662306a36Sopenharmony_ci p = tb_property_find(network_dir, "prtcvers", TB_PROPERTY_TYPE_VALUE); 270762306a36Sopenharmony_ci KUNIT_ASSERT_NOT_NULL(test, p); 270862306a36Sopenharmony_ci KUNIT_EXPECT_EQ(test, p->value.immediate, 0x1); 270962306a36Sopenharmony_ci 271062306a36Sopenharmony_ci p = tb_property_find(network_dir, "prtcrevs", TB_PROPERTY_TYPE_VALUE); 271162306a36Sopenharmony_ci KUNIT_ASSERT_NOT_NULL(test, p); 271262306a36Sopenharmony_ci KUNIT_EXPECT_EQ(test, p->value.immediate, 0x1); 271362306a36Sopenharmony_ci 271462306a36Sopenharmony_ci p = tb_property_find(network_dir, "prtcstns", TB_PROPERTY_TYPE_VALUE); 271562306a36Sopenharmony_ci KUNIT_ASSERT_NOT_NULL(test, p); 271662306a36Sopenharmony_ci KUNIT_EXPECT_EQ(test, p->value.immediate, 0x0); 271762306a36Sopenharmony_ci 271862306a36Sopenharmony_ci p = tb_property_find(network_dir, "deviceid", TB_PROPERTY_TYPE_VALUE); 271962306a36Sopenharmony_ci KUNIT_EXPECT_TRUE(test, !p); 272062306a36Sopenharmony_ci p = tb_property_find(network_dir, "deviceid", TB_PROPERTY_TYPE_TEXT); 272162306a36Sopenharmony_ci KUNIT_EXPECT_TRUE(test, !p); 272262306a36Sopenharmony_ci 272362306a36Sopenharmony_ci tb_property_free_dir(dir); 272462306a36Sopenharmony_ci} 272562306a36Sopenharmony_ci 272662306a36Sopenharmony_cistatic void tb_test_property_format(struct kunit *test) 272762306a36Sopenharmony_ci{ 272862306a36Sopenharmony_ci struct tb_property_dir *dir; 272962306a36Sopenharmony_ci ssize_t block_len; 273062306a36Sopenharmony_ci u32 *block; 273162306a36Sopenharmony_ci int ret, i; 273262306a36Sopenharmony_ci 273362306a36Sopenharmony_ci dir = tb_property_parse_dir(root_directory, ARRAY_SIZE(root_directory)); 273462306a36Sopenharmony_ci KUNIT_ASSERT_NOT_NULL(test, dir); 273562306a36Sopenharmony_ci 273662306a36Sopenharmony_ci ret = tb_property_format_dir(dir, NULL, 0); 273762306a36Sopenharmony_ci KUNIT_ASSERT_EQ(test, ret, ARRAY_SIZE(root_directory)); 273862306a36Sopenharmony_ci 273962306a36Sopenharmony_ci block_len = ret; 274062306a36Sopenharmony_ci 274162306a36Sopenharmony_ci block = kunit_kzalloc(test, block_len * sizeof(u32), GFP_KERNEL); 274262306a36Sopenharmony_ci KUNIT_ASSERT_NOT_NULL(test, block); 274362306a36Sopenharmony_ci 274462306a36Sopenharmony_ci ret = tb_property_format_dir(dir, block, block_len); 274562306a36Sopenharmony_ci KUNIT_EXPECT_EQ(test, ret, 0); 274662306a36Sopenharmony_ci 274762306a36Sopenharmony_ci for (i = 0; i < ARRAY_SIZE(root_directory); i++) 274862306a36Sopenharmony_ci KUNIT_EXPECT_EQ(test, root_directory[i], block[i]); 274962306a36Sopenharmony_ci 275062306a36Sopenharmony_ci tb_property_free_dir(dir); 275162306a36Sopenharmony_ci} 275262306a36Sopenharmony_ci 275362306a36Sopenharmony_cistatic void compare_dirs(struct kunit *test, struct tb_property_dir *d1, 275462306a36Sopenharmony_ci struct tb_property_dir *d2) 275562306a36Sopenharmony_ci{ 275662306a36Sopenharmony_ci struct tb_property *p1, *p2, *tmp; 275762306a36Sopenharmony_ci int n1, n2, i; 275862306a36Sopenharmony_ci 275962306a36Sopenharmony_ci if (d1->uuid) { 276062306a36Sopenharmony_ci KUNIT_ASSERT_NOT_NULL(test, d2->uuid); 276162306a36Sopenharmony_ci KUNIT_ASSERT_TRUE(test, uuid_equal(d1->uuid, d2->uuid)); 276262306a36Sopenharmony_ci } else { 276362306a36Sopenharmony_ci KUNIT_ASSERT_NULL(test, d2->uuid); 276462306a36Sopenharmony_ci } 276562306a36Sopenharmony_ci 276662306a36Sopenharmony_ci n1 = 0; 276762306a36Sopenharmony_ci tb_property_for_each(d1, tmp) 276862306a36Sopenharmony_ci n1++; 276962306a36Sopenharmony_ci KUNIT_ASSERT_NE(test, n1, 0); 277062306a36Sopenharmony_ci 277162306a36Sopenharmony_ci n2 = 0; 277262306a36Sopenharmony_ci tb_property_for_each(d2, tmp) 277362306a36Sopenharmony_ci n2++; 277462306a36Sopenharmony_ci KUNIT_ASSERT_NE(test, n2, 0); 277562306a36Sopenharmony_ci 277662306a36Sopenharmony_ci KUNIT_ASSERT_EQ(test, n1, n2); 277762306a36Sopenharmony_ci 277862306a36Sopenharmony_ci p1 = NULL; 277962306a36Sopenharmony_ci p2 = NULL; 278062306a36Sopenharmony_ci for (i = 0; i < n1; i++) { 278162306a36Sopenharmony_ci p1 = tb_property_get_next(d1, p1); 278262306a36Sopenharmony_ci KUNIT_ASSERT_NOT_NULL(test, p1); 278362306a36Sopenharmony_ci p2 = tb_property_get_next(d2, p2); 278462306a36Sopenharmony_ci KUNIT_ASSERT_NOT_NULL(test, p2); 278562306a36Sopenharmony_ci 278662306a36Sopenharmony_ci KUNIT_ASSERT_STREQ(test, &p1->key[0], &p2->key[0]); 278762306a36Sopenharmony_ci KUNIT_ASSERT_EQ(test, p1->type, p2->type); 278862306a36Sopenharmony_ci KUNIT_ASSERT_EQ(test, p1->length, p2->length); 278962306a36Sopenharmony_ci 279062306a36Sopenharmony_ci switch (p1->type) { 279162306a36Sopenharmony_ci case TB_PROPERTY_TYPE_DIRECTORY: 279262306a36Sopenharmony_ci KUNIT_ASSERT_NOT_NULL(test, p1->value.dir); 279362306a36Sopenharmony_ci KUNIT_ASSERT_NOT_NULL(test, p2->value.dir); 279462306a36Sopenharmony_ci compare_dirs(test, p1->value.dir, p2->value.dir); 279562306a36Sopenharmony_ci break; 279662306a36Sopenharmony_ci 279762306a36Sopenharmony_ci case TB_PROPERTY_TYPE_DATA: 279862306a36Sopenharmony_ci KUNIT_ASSERT_NOT_NULL(test, p1->value.data); 279962306a36Sopenharmony_ci KUNIT_ASSERT_NOT_NULL(test, p2->value.data); 280062306a36Sopenharmony_ci KUNIT_ASSERT_TRUE(test, 280162306a36Sopenharmony_ci !memcmp(p1->value.data, p2->value.data, 280262306a36Sopenharmony_ci p1->length * 4) 280362306a36Sopenharmony_ci ); 280462306a36Sopenharmony_ci break; 280562306a36Sopenharmony_ci 280662306a36Sopenharmony_ci case TB_PROPERTY_TYPE_TEXT: 280762306a36Sopenharmony_ci KUNIT_ASSERT_NOT_NULL(test, p1->value.text); 280862306a36Sopenharmony_ci KUNIT_ASSERT_NOT_NULL(test, p2->value.text); 280962306a36Sopenharmony_ci KUNIT_ASSERT_STREQ(test, p1->value.text, p2->value.text); 281062306a36Sopenharmony_ci break; 281162306a36Sopenharmony_ci 281262306a36Sopenharmony_ci case TB_PROPERTY_TYPE_VALUE: 281362306a36Sopenharmony_ci KUNIT_ASSERT_EQ(test, p1->value.immediate, 281462306a36Sopenharmony_ci p2->value.immediate); 281562306a36Sopenharmony_ci break; 281662306a36Sopenharmony_ci default: 281762306a36Sopenharmony_ci KUNIT_FAIL(test, "unexpected property type"); 281862306a36Sopenharmony_ci break; 281962306a36Sopenharmony_ci } 282062306a36Sopenharmony_ci } 282162306a36Sopenharmony_ci} 282262306a36Sopenharmony_ci 282362306a36Sopenharmony_cistatic void tb_test_property_copy(struct kunit *test) 282462306a36Sopenharmony_ci{ 282562306a36Sopenharmony_ci struct tb_property_dir *src, *dst; 282662306a36Sopenharmony_ci u32 *block; 282762306a36Sopenharmony_ci int ret, i; 282862306a36Sopenharmony_ci 282962306a36Sopenharmony_ci src = tb_property_parse_dir(root_directory, ARRAY_SIZE(root_directory)); 283062306a36Sopenharmony_ci KUNIT_ASSERT_NOT_NULL(test, src); 283162306a36Sopenharmony_ci 283262306a36Sopenharmony_ci dst = tb_property_copy_dir(src); 283362306a36Sopenharmony_ci KUNIT_ASSERT_NOT_NULL(test, dst); 283462306a36Sopenharmony_ci 283562306a36Sopenharmony_ci /* Compare the structures */ 283662306a36Sopenharmony_ci compare_dirs(test, src, dst); 283762306a36Sopenharmony_ci 283862306a36Sopenharmony_ci /* Compare the resulting property block */ 283962306a36Sopenharmony_ci ret = tb_property_format_dir(dst, NULL, 0); 284062306a36Sopenharmony_ci KUNIT_ASSERT_EQ(test, ret, ARRAY_SIZE(root_directory)); 284162306a36Sopenharmony_ci 284262306a36Sopenharmony_ci block = kunit_kzalloc(test, sizeof(root_directory), GFP_KERNEL); 284362306a36Sopenharmony_ci KUNIT_ASSERT_NOT_NULL(test, block); 284462306a36Sopenharmony_ci 284562306a36Sopenharmony_ci ret = tb_property_format_dir(dst, block, ARRAY_SIZE(root_directory)); 284662306a36Sopenharmony_ci KUNIT_EXPECT_TRUE(test, !ret); 284762306a36Sopenharmony_ci 284862306a36Sopenharmony_ci for (i = 0; i < ARRAY_SIZE(root_directory); i++) 284962306a36Sopenharmony_ci KUNIT_EXPECT_EQ(test, root_directory[i], block[i]); 285062306a36Sopenharmony_ci 285162306a36Sopenharmony_ci tb_property_free_dir(dst); 285262306a36Sopenharmony_ci tb_property_free_dir(src); 285362306a36Sopenharmony_ci} 285462306a36Sopenharmony_ci 285562306a36Sopenharmony_cistatic struct kunit_case tb_test_cases[] = { 285662306a36Sopenharmony_ci KUNIT_CASE(tb_test_path_basic), 285762306a36Sopenharmony_ci KUNIT_CASE(tb_test_path_not_connected_walk), 285862306a36Sopenharmony_ci KUNIT_CASE(tb_test_path_single_hop_walk), 285962306a36Sopenharmony_ci KUNIT_CASE(tb_test_path_daisy_chain_walk), 286062306a36Sopenharmony_ci KUNIT_CASE(tb_test_path_simple_tree_walk), 286162306a36Sopenharmony_ci KUNIT_CASE(tb_test_path_complex_tree_walk), 286262306a36Sopenharmony_ci KUNIT_CASE(tb_test_path_max_length_walk), 286362306a36Sopenharmony_ci KUNIT_CASE(tb_test_path_not_connected), 286462306a36Sopenharmony_ci KUNIT_CASE(tb_test_path_not_bonded_lane0), 286562306a36Sopenharmony_ci KUNIT_CASE(tb_test_path_not_bonded_lane1), 286662306a36Sopenharmony_ci KUNIT_CASE(tb_test_path_not_bonded_lane1_chain), 286762306a36Sopenharmony_ci KUNIT_CASE(tb_test_path_not_bonded_lane1_chain_reverse), 286862306a36Sopenharmony_ci KUNIT_CASE(tb_test_path_mixed_chain), 286962306a36Sopenharmony_ci KUNIT_CASE(tb_test_path_mixed_chain_reverse), 287062306a36Sopenharmony_ci KUNIT_CASE(tb_test_tunnel_pcie), 287162306a36Sopenharmony_ci KUNIT_CASE(tb_test_tunnel_dp), 287262306a36Sopenharmony_ci KUNIT_CASE(tb_test_tunnel_dp_chain), 287362306a36Sopenharmony_ci KUNIT_CASE(tb_test_tunnel_dp_tree), 287462306a36Sopenharmony_ci KUNIT_CASE(tb_test_tunnel_dp_max_length), 287562306a36Sopenharmony_ci KUNIT_CASE(tb_test_tunnel_3dp), 287662306a36Sopenharmony_ci KUNIT_CASE(tb_test_tunnel_port_on_path), 287762306a36Sopenharmony_ci KUNIT_CASE(tb_test_tunnel_usb3), 287862306a36Sopenharmony_ci KUNIT_CASE(tb_test_tunnel_dma), 287962306a36Sopenharmony_ci KUNIT_CASE(tb_test_tunnel_dma_rx), 288062306a36Sopenharmony_ci KUNIT_CASE(tb_test_tunnel_dma_tx), 288162306a36Sopenharmony_ci KUNIT_CASE(tb_test_tunnel_dma_chain), 288262306a36Sopenharmony_ci KUNIT_CASE(tb_test_tunnel_dma_match), 288362306a36Sopenharmony_ci KUNIT_CASE(tb_test_credit_alloc_legacy_not_bonded), 288462306a36Sopenharmony_ci KUNIT_CASE(tb_test_credit_alloc_legacy_bonded), 288562306a36Sopenharmony_ci KUNIT_CASE(tb_test_credit_alloc_pcie), 288662306a36Sopenharmony_ci KUNIT_CASE(tb_test_credit_alloc_without_dp), 288762306a36Sopenharmony_ci KUNIT_CASE(tb_test_credit_alloc_dp), 288862306a36Sopenharmony_ci KUNIT_CASE(tb_test_credit_alloc_usb3), 288962306a36Sopenharmony_ci KUNIT_CASE(tb_test_credit_alloc_dma), 289062306a36Sopenharmony_ci KUNIT_CASE(tb_test_credit_alloc_dma_multiple), 289162306a36Sopenharmony_ci KUNIT_CASE(tb_test_credit_alloc_all), 289262306a36Sopenharmony_ci KUNIT_CASE(tb_test_property_parse), 289362306a36Sopenharmony_ci KUNIT_CASE(tb_test_property_format), 289462306a36Sopenharmony_ci KUNIT_CASE(tb_test_property_copy), 289562306a36Sopenharmony_ci { } 289662306a36Sopenharmony_ci}; 289762306a36Sopenharmony_ci 289862306a36Sopenharmony_cistatic struct kunit_suite tb_test_suite = { 289962306a36Sopenharmony_ci .name = "thunderbolt", 290062306a36Sopenharmony_ci .test_cases = tb_test_cases, 290162306a36Sopenharmony_ci}; 290262306a36Sopenharmony_ci 290362306a36Sopenharmony_cikunit_test_suite(tb_test_suite); 2904