summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--drivers/thunderbolt/dma_port.c28
-rw-r--r--drivers/thunderbolt/icm.c382
-rw-r--r--drivers/thunderbolt/nhi.c2
-rw-r--r--drivers/thunderbolt/nhi.h5
-rw-r--r--drivers/thunderbolt/switch.c3
-rw-r--r--drivers/thunderbolt/tb_msgs.h141
6 files changed, 546 insertions, 15 deletions
diff --git a/drivers/thunderbolt/dma_port.c b/drivers/thunderbolt/dma_port.c
index af6dde347bee..f2701194f810 100644
--- a/drivers/thunderbolt/dma_port.c
+++ b/drivers/thunderbolt/dma_port.c
@@ -170,24 +170,22 @@ static int dma_port_write(struct tb_ctl *ctl, const void *buffer, u64 route,
static int dma_find_port(struct tb_switch *sw)
{
- int port, ret;
- u32 type;
+ static const int ports[] = { 3, 5, 7 };
+ int i;
/*
- * The DMA (NHI) port is either 3 or 5 depending on the
- * controller. Try both starting from 5 which is more common.
+ * The DMA (NHI) port is either 3, 5 or 7 depending on the
+ * controller. Try all of them.
*/
- port = 5;
- ret = dma_port_read(sw->tb->ctl, &type, tb_route(sw), port, 2, 1,
- DMA_PORT_TIMEOUT);
- if (!ret && (type & 0xffffff) == TB_TYPE_NHI)
- return port;
-
- port = 3;
- ret = dma_port_read(sw->tb->ctl, &type, tb_route(sw), port, 2, 1,
- DMA_PORT_TIMEOUT);
- if (!ret && (type & 0xffffff) == TB_TYPE_NHI)
- return port;
+ for (i = 0; i < ARRAY_SIZE(ports); i++) {
+ u32 type;
+ int ret;
+
+ ret = dma_port_read(sw->tb->ctl, &type, tb_route(sw), ports[i],
+ 2, 1, DMA_PORT_TIMEOUT);
+ if (!ret && (type & 0xffffff) == TB_TYPE_NHI)
+ return ports[i];
+ }
return -ENODEV;
}
diff --git a/drivers/thunderbolt/icm.c b/drivers/thunderbolt/icm.c
index 93a198a17f42..6b1041677604 100644
--- a/drivers/thunderbolt/icm.c
+++ b/drivers/thunderbolt/icm.c
@@ -118,6 +118,12 @@ static inline u64 get_route(u32 route_hi, u32 route_lo)
return (u64)route_hi << 32 | route_lo;
}
+static inline u64 get_parent_route(u64 route)
+{
+ int depth = tb_route_length(route);
+ return depth ? route & ~(0xffULL << (depth - 1) * TB_ROUTE_SHIFT) : 0;
+}
+
static bool icm_match(const struct tb_cfg_request *req,
const struct ctl_pkg *pkg)
{
@@ -749,6 +755,351 @@ icm_fr_xdomain_disconnected(struct tb *tb, const struct icm_pkg_header *hdr)
}
}
+static int
+icm_tr_driver_ready(struct tb *tb, enum tb_security_level *security_level,
+ size_t *nboot_acl)
+{
+ struct icm_tr_pkg_driver_ready_response reply;
+ struct icm_pkg_driver_ready request = {
+ .hdr.code = ICM_DRIVER_READY,
+ };
+ int ret;
+
+ memset(&reply, 0, sizeof(reply));
+ ret = icm_request(tb, &request, sizeof(request), &reply, sizeof(reply),
+ 1, 20000);
+ if (ret)
+ return ret;
+
+ if (security_level)
+ *security_level = reply.info & ICM_TR_INFO_SLEVEL_MASK;
+ if (nboot_acl)
+ *nboot_acl = (reply.info & ICM_TR_INFO_BOOT_ACL_MASK) >>
+ ICM_TR_INFO_BOOT_ACL_SHIFT;
+ return 0;
+}
+
+static int icm_tr_approve_switch(struct tb *tb, struct tb_switch *sw)
+{
+ struct icm_tr_pkg_approve_device request;
+ struct icm_tr_pkg_approve_device reply;
+ int ret;
+
+ memset(&request, 0, sizeof(request));
+ memcpy(&request.ep_uuid, sw->uuid, sizeof(request.ep_uuid));
+ request.hdr.code = ICM_APPROVE_DEVICE;
+ request.route_lo = sw->config.route_lo;
+ request.route_hi = sw->config.route_hi;
+ request.connection_id = sw->connection_id;
+
+ memset(&reply, 0, sizeof(reply));
+ ret = icm_request(tb, &request, sizeof(request), &reply, sizeof(reply),
+ 1, ICM_APPROVE_TIMEOUT);
+ if (ret)
+ return ret;
+
+ if (reply.hdr.flags & ICM_FLAGS_ERROR) {
+ tb_warn(tb, "PCIe tunnel creation failed\n");
+ return -EIO;
+ }
+
+ return 0;
+}
+
+static int icm_tr_add_switch_key(struct tb *tb, struct tb_switch *sw)
+{
+ struct icm_tr_pkg_add_device_key_response reply;
+ struct icm_tr_pkg_add_device_key request;
+ int ret;
+
+ memset(&request, 0, sizeof(request));
+ memcpy(&request.ep_uuid, sw->uuid, sizeof(request.ep_uuid));
+ request.hdr.code = ICM_ADD_DEVICE_KEY;
+ request.route_lo = sw->config.route_lo;
+ request.route_hi = sw->config.route_hi;
+ request.connection_id = sw->connection_id;
+ memcpy(request.key, sw->key, TB_SWITCH_KEY_SIZE);
+
+ memset(&reply, 0, sizeof(reply));
+ ret = icm_request(tb, &request, sizeof(request), &reply, sizeof(reply),
+ 1, ICM_TIMEOUT);
+ if (ret)
+ return ret;
+
+ if (reply.hdr.flags & ICM_FLAGS_ERROR) {
+ tb_warn(tb, "Adding key to switch failed\n");
+ return -EIO;
+ }
+
+ return 0;
+}
+
+static int icm_tr_challenge_switch_key(struct tb *tb, struct tb_switch *sw,
+ const u8 *challenge, u8 *response)
+{
+ struct icm_tr_pkg_challenge_device_response reply;
+ struct icm_tr_pkg_challenge_device request;
+ int ret;
+
+ memset(&request, 0, sizeof(request));
+ memcpy(&request.ep_uuid, sw->uuid, sizeof(request.ep_uuid));
+ request.hdr.code = ICM_CHALLENGE_DEVICE;
+ request.route_lo = sw->config.route_lo;
+ request.route_hi = sw->config.route_hi;
+ request.connection_id = sw->connection_id;
+ memcpy(request.challenge, challenge, TB_SWITCH_KEY_SIZE);
+
+ memset(&reply, 0, sizeof(reply));
+ ret = icm_request(tb, &request, sizeof(request), &reply, sizeof(reply),
+ 1, ICM_TIMEOUT);
+ if (ret)
+ return ret;
+
+ if (reply.hdr.flags & ICM_FLAGS_ERROR)
+ return -EKEYREJECTED;
+ if (reply.hdr.flags & ICM_FLAGS_NO_KEY)
+ return -ENOKEY;
+
+ memcpy(response, reply.response, TB_SWITCH_KEY_SIZE);
+
+ return 0;
+}
+
+static int icm_tr_approve_xdomain_paths(struct tb *tb, struct tb_xdomain *xd)
+{
+ struct icm_tr_pkg_approve_xdomain_response reply;
+ struct icm_tr_pkg_approve_xdomain request;
+ int ret;
+
+ memset(&request, 0, sizeof(request));
+ request.hdr.code = ICM_APPROVE_XDOMAIN;
+ request.route_hi = upper_32_bits(xd->route);
+ request.route_lo = lower_32_bits(xd->route);
+ request.transmit_path = xd->transmit_path;
+ request.transmit_ring = xd->transmit_ring;
+ request.receive_path = xd->receive_path;
+ request.receive_ring = xd->receive_ring;
+ memcpy(&request.remote_uuid, xd->remote_uuid, sizeof(*xd->remote_uuid));
+
+ memset(&reply, 0, sizeof(reply));
+ ret = icm_request(tb, &request, sizeof(request), &reply, sizeof(reply),
+ 1, ICM_TIMEOUT);
+ if (ret)
+ return ret;
+
+ if (reply.hdr.flags & ICM_FLAGS_ERROR)
+ return -EIO;
+
+ return 0;
+}
+
+static int icm_tr_xdomain_tear_down(struct tb *tb, struct tb_xdomain *xd,
+ int stage)
+{
+ struct icm_tr_pkg_disconnect_xdomain_response reply;
+ struct icm_tr_pkg_disconnect_xdomain request;
+ int ret;
+
+ memset(&request, 0, sizeof(request));
+ request.hdr.code = ICM_DISCONNECT_XDOMAIN;
+ request.stage = stage;
+ request.route_hi = upper_32_bits(xd->route);
+ request.route_lo = lower_32_bits(xd->route);
+ memcpy(&request.remote_uuid, xd->remote_uuid, sizeof(*xd->remote_uuid));
+
+ memset(&reply, 0, sizeof(reply));
+ ret = icm_request(tb, &request, sizeof(request), &reply, sizeof(reply),
+ 1, ICM_TIMEOUT);
+ if (ret)
+ return ret;
+
+ if (reply.hdr.flags & ICM_FLAGS_ERROR)
+ return -EIO;
+
+ return 0;
+}
+
+static int icm_tr_disconnect_xdomain_paths(struct tb *tb, struct tb_xdomain *xd)
+{
+ int ret;
+
+ ret = icm_tr_xdomain_tear_down(tb, xd, 1);
+ if (ret)
+ return ret;
+
+ usleep_range(10, 50);
+ return icm_tr_xdomain_tear_down(tb, xd, 2);
+}
+
+static void
+icm_tr_device_connected(struct tb *tb, const struct icm_pkg_header *hdr)
+{
+ const struct icm_tr_event_device_connected *pkg =
+ (const struct icm_tr_event_device_connected *)hdr;
+ enum tb_security_level security_level;
+ struct tb_switch *sw, *parent_sw;
+ struct tb_xdomain *xd;
+ bool authorized, boot;
+ u64 route;
+
+ /*
+ * Currently we don't use the QoS information coming with the
+ * device connected message so simply just ignore that extra
+ * packet for now.
+ */
+ if (pkg->hdr.packet_id)
+ return;
+
+ /*
+ * After NVM upgrade adding root switch device fails because we
+ * initiated reset. During that time ICM might still send device
+ * connected message which we ignore here.
+ */
+ if (!tb->root_switch)
+ return;
+
+ route = get_route(pkg->route_hi, pkg->route_lo);
+ authorized = pkg->link_info & ICM_LINK_INFO_APPROVED;
+ security_level = (pkg->hdr.flags & ICM_FLAGS_SLEVEL_MASK) >>
+ ICM_FLAGS_SLEVEL_SHIFT;
+ boot = pkg->link_info & ICM_LINK_INFO_BOOT;
+
+ if (pkg->link_info & ICM_LINK_INFO_REJECTED) {
+ tb_info(tb, "switch at %llx was rejected by ICM firmware because topology limit exceeded\n",
+ route);
+ return;
+ }
+
+ sw = tb_switch_find_by_uuid(tb, &pkg->ep_uuid);
+ if (sw) {
+ /* Update the switch if it is still in the same place */
+ if (tb_route(sw) == route && !!sw->authorized == authorized) {
+ parent_sw = tb_to_switch(sw->dev.parent);
+ update_switch(parent_sw, sw, route, pkg->connection_id,
+ 0, 0, 0, boot);
+ tb_switch_put(sw);
+ return;
+ }
+
+ remove_switch(sw);
+ tb_switch_put(sw);
+ }
+
+ /* Another switch with the same address */
+ sw = tb_switch_find_by_route(tb, route);
+ if (sw) {
+ remove_switch(sw);
+ tb_switch_put(sw);
+ }
+
+ /* XDomain connection with the same address */
+ xd = tb_xdomain_find_by_route(tb, route);
+ if (xd) {
+ remove_xdomain(xd);
+ tb_xdomain_put(xd);
+ }
+
+ parent_sw = tb_switch_find_by_route(tb, get_parent_route(route));
+ if (!parent_sw) {
+ tb_err(tb, "failed to find parent switch for %llx\n", route);
+ return;
+ }
+
+ add_switch(parent_sw, route, &pkg->ep_uuid, pkg->connection_id,
+ 0, 0, 0, security_level, authorized, boot);
+
+ tb_switch_put(parent_sw);
+}
+
+static void
+icm_tr_device_disconnected(struct tb *tb, const struct icm_pkg_header *hdr)
+{
+ const struct icm_tr_event_device_disconnected *pkg =
+ (const struct icm_tr_event_device_disconnected *)hdr;
+ struct tb_switch *sw;
+ u64 route;
+
+ route = get_route(pkg->route_hi, pkg->route_lo);
+
+ sw = tb_switch_find_by_route(tb, route);
+ if (!sw) {
+ tb_warn(tb, "no switch exists at %llx, ignoring\n", route);
+ return;
+ }
+
+ remove_switch(sw);
+ tb_switch_put(sw);
+}
+
+static void
+icm_tr_xdomain_connected(struct tb *tb, const struct icm_pkg_header *hdr)
+{
+ const struct icm_tr_event_xdomain_connected *pkg =
+ (const struct icm_tr_event_xdomain_connected *)hdr;
+ struct tb_xdomain *xd;
+ struct tb_switch *sw;
+ u64 route;
+
+ if (!tb->root_switch)
+ return;
+
+ route = get_route(pkg->local_route_hi, pkg->local_route_lo);
+
+ xd = tb_xdomain_find_by_uuid(tb, &pkg->remote_uuid);
+ if (xd) {
+ if (xd->route == route) {
+ update_xdomain(xd, route, 0);
+ tb_xdomain_put(xd);
+ return;
+ }
+
+ remove_xdomain(xd);
+ tb_xdomain_put(xd);
+ }
+
+ /* An existing xdomain with the same address */
+ xd = tb_xdomain_find_by_route(tb, route);
+ if (xd) {
+ remove_xdomain(xd);
+ tb_xdomain_put(xd);
+ }
+
+ /*
+ * If the user disconnected a switch during suspend and
+ * connected another host to the same port, remove the switch
+ * first.
+ */
+ sw = get_switch_at_route(tb->root_switch, route);
+ if (sw)
+ remove_switch(sw);
+
+ sw = tb_switch_find_by_route(tb, get_parent_route(route));
+ if (!sw) {
+ tb_warn(tb, "no switch exists at %llx, ignoring\n", route);
+ return;
+ }
+
+ add_xdomain(sw, route, &pkg->local_uuid, &pkg->remote_uuid, 0, 0);
+ tb_switch_put(sw);
+}
+
+static void
+icm_tr_xdomain_disconnected(struct tb *tb, const struct icm_pkg_header *hdr)
+{
+ const struct icm_tr_event_xdomain_disconnected *pkg =
+ (const struct icm_tr_event_xdomain_disconnected *)hdr;
+ struct tb_xdomain *xd;
+ u64 route;
+
+ route = get_route(pkg->route_hi, pkg->route_lo);
+
+ xd = tb_xdomain_find_by_route(tb, route);
+ if (xd) {
+ remove_xdomain(xd);
+ tb_xdomain_put(xd);
+ }
+}
+
static struct pci_dev *get_upstream_port(struct pci_dev *pdev)
{
struct pci_dev *parent;
@@ -1472,6 +1823,24 @@ static const struct tb_cm_ops icm_ar_ops = {
.disconnect_xdomain_paths = icm_fr_disconnect_xdomain_paths,
};
+/* Titan Ridge */
+static const struct tb_cm_ops icm_tr_ops = {
+ .driver_ready = icm_driver_ready,
+ .start = icm_start,
+ .stop = icm_stop,
+ .suspend = icm_suspend,
+ .complete = icm_complete,
+ .handle_event = icm_handle_event,
+ .get_boot_acl = icm_ar_get_boot_acl,
+ .set_boot_acl = icm_ar_set_boot_acl,
+ .approve_switch = icm_tr_approve_switch,
+ .add_switch_key = icm_tr_add_switch_key,
+ .challenge_switch_key = icm_tr_challenge_switch_key,
+ .disconnect_pcie_paths = icm_disconnect_pcie_paths,
+ .approve_xdomain_paths = icm_tr_approve_xdomain_paths,
+ .disconnect_xdomain_paths = icm_tr_disconnect_xdomain_paths,
+};
+
struct tb *icm_probe(struct tb_nhi *nhi)
{
struct icm *icm;
@@ -1514,6 +1883,19 @@ struct tb *icm_probe(struct tb_nhi *nhi)
icm->xdomain_disconnected = icm_fr_xdomain_disconnected;
tb->cm_ops = &icm_ar_ops;
break;
+
+ case PCI_DEVICE_ID_INTEL_TITAN_RIDGE_2C_NHI:
+ case PCI_DEVICE_ID_INTEL_TITAN_RIDGE_4C_NHI:
+ icm->max_boot_acl = ICM_AR_PREBOOT_ACL_ENTRIES;
+ icm->is_supported = icm_ar_is_supported;
+ icm->get_mode = icm_ar_get_mode;
+ icm->driver_ready = icm_tr_driver_ready;
+ icm->device_connected = icm_tr_device_connected;
+ icm->device_disconnected = icm_tr_device_disconnected;
+ icm->xdomain_connected = icm_tr_xdomain_connected;
+ icm->xdomain_disconnected = icm_tr_xdomain_disconnected;
+ tb->cm_ops = &icm_tr_ops;
+ break;
}
if (!icm->is_supported || !icm->is_supported(tb)) {
diff --git a/drivers/thunderbolt/nhi.c b/drivers/thunderbolt/nhi.c
index 9e58d09f6029..f5a33e88e676 100644
--- a/drivers/thunderbolt/nhi.c
+++ b/drivers/thunderbolt/nhi.c
@@ -1111,6 +1111,8 @@ static struct pci_device_id nhi_ids[] = {
{ PCI_VDEVICE(INTEL, PCI_DEVICE_ID_INTEL_ALPINE_RIDGE_C_2C_NHI) },
{ PCI_VDEVICE(INTEL, PCI_DEVICE_ID_INTEL_ALPINE_RIDGE_C_4C_NHI) },
{ PCI_VDEVICE(INTEL, PCI_DEVICE_ID_INTEL_ALPINE_RIDGE_C_USBONLY_NHI) },
+ { PCI_VDEVICE(INTEL, PCI_DEVICE_ID_INTEL_TITAN_RIDGE_2C_NHI) },
+ { PCI_VDEVICE(INTEL, PCI_DEVICE_ID_INTEL_TITAN_RIDGE_4C_NHI) },
{ 0,}
};
diff --git a/drivers/thunderbolt/nhi.h b/drivers/thunderbolt/nhi.h
index 4476ab4cfd0c..1696a4560948 100644
--- a/drivers/thunderbolt/nhi.h
+++ b/drivers/thunderbolt/nhi.h
@@ -45,5 +45,10 @@ enum nhi_fw_mode nhi_mailbox_mode(struct tb_nhi *nhi);
#define PCI_DEVICE_ID_INTEL_ALPINE_RIDGE_LP_USBONLY_NHI 0x15dc
#define PCI_DEVICE_ID_INTEL_ALPINE_RIDGE_USBONLY_NHI 0x15dd
#define PCI_DEVICE_ID_INTEL_ALPINE_RIDGE_C_USBONLY_NHI 0x15de
+#define PCI_DEVICE_ID_INTEL_TITAN_RIDGE_2C_BRIDGE 0x15e7
+#define PCI_DEVICE_ID_INTEL_TITAN_RIDGE_2C_NHI 0x15e8
+#define PCI_DEVICE_ID_INTEL_TITAN_RIDGE_4C_BRIDGE 0x15ea
+#define PCI_DEVICE_ID_INTEL_TITAN_RIDGE_4C_NHI 0x15eb
+#define PCI_DEVICE_ID_INTEL_TITAN_RIDGE_DD_BRIDGE 0x15ef
#endif
diff --git a/drivers/thunderbolt/switch.c b/drivers/thunderbolt/switch.c
index e9e30aaab2a3..25758671ddf4 100644
--- a/drivers/thunderbolt/switch.c
+++ b/drivers/thunderbolt/switch.c
@@ -1051,6 +1051,9 @@ static int tb_switch_get_generation(struct tb_switch *sw)
case PCI_DEVICE_ID_INTEL_ALPINE_RIDGE_4C_BRIDGE:
case PCI_DEVICE_ID_INTEL_ALPINE_RIDGE_C_2C_BRIDGE:
case PCI_DEVICE_ID_INTEL_ALPINE_RIDGE_C_4C_BRIDGE:
+ case PCI_DEVICE_ID_INTEL_TITAN_RIDGE_2C_BRIDGE:
+ case PCI_DEVICE_ID_INTEL_TITAN_RIDGE_4C_BRIDGE:
+ case PCI_DEVICE_ID_INTEL_TITAN_RIDGE_DD_BRIDGE:
return 3;
default:
diff --git a/drivers/thunderbolt/tb_msgs.h b/drivers/thunderbolt/tb_msgs.h
index 496b91f3b579..bc13f8d6b804 100644
--- a/drivers/thunderbolt/tb_msgs.h
+++ b/drivers/thunderbolt/tb_msgs.h
@@ -102,6 +102,7 @@ enum icm_pkg_code {
ICM_ADD_DEVICE_KEY = 0x6,
ICM_GET_ROUTE = 0xa,
ICM_APPROVE_XDOMAIN = 0x10,
+ ICM_DISCONNECT_XDOMAIN = 0x11,
ICM_PREBOOT_ACL = 0x18,
};
@@ -321,6 +322,146 @@ struct icm_ar_pkg_preboot_acl_response {
struct icm_ar_boot_acl_entry acl[ICM_AR_PREBOOT_ACL_ENTRIES];
};
+/* Titan Ridge messages */
+
+struct icm_tr_pkg_driver_ready_response {
+ struct icm_pkg_header hdr;
+ u16 reserved1;
+ u16 info;
+ u32 nvm_version;
+ u16 device_id;
+ u16 reserved2;
+};
+
+#define ICM_TR_INFO_SLEVEL_MASK GENMASK(2, 0)
+#define ICM_TR_INFO_BOOT_ACL_SHIFT 7
+#define ICM_TR_INFO_BOOT_ACL_MASK GENMASK(12, 7)
+
+struct icm_tr_event_device_connected {
+ struct icm_pkg_header hdr;
+ uuid_t ep_uuid;
+ u32 route_hi;
+ u32 route_lo;
+ u8 connection_id;
+ u8 reserved;
+ u16 link_info;
+ u32 ep_name[55];
+};
+
+struct icm_tr_event_device_disconnected {
+ struct icm_pkg_header hdr;
+ u32 route_hi;
+ u32 route_lo;
+};
+
+struct icm_tr_event_xdomain_connected {
+ struct icm_pkg_header hdr;
+ u16 reserved;
+ u16 link_info;
+ uuid_t remote_uuid;
+ uuid_t local_uuid;
+ u32 local_route_hi;
+ u32 local_route_lo;
+ u32 remote_route_hi;
+ u32 remote_route_lo;
+};
+
+struct icm_tr_event_xdomain_disconnected {
+ struct icm_pkg_header hdr;
+ u32 route_hi;
+ u32 route_lo;
+ uuid_t remote_uuid;
+};
+
+struct icm_tr_pkg_approve_device {
+ struct icm_pkg_header hdr;
+ uuid_t ep_uuid;
+ u32 route_hi;
+ u32 route_lo;
+ u8 connection_id;
+ u8 reserved1[3];
+};
+
+struct icm_tr_pkg_add_device_key {
+ struct icm_pkg_header hdr;
+ uuid_t ep_uuid;
+ u32 route_hi;
+ u32 route_lo;
+ u8 connection_id;
+ u8 reserved[3];
+ u32 key[8];
+};
+
+struct icm_tr_pkg_challenge_device {
+ struct icm_pkg_header hdr;
+ uuid_t ep_uuid;
+ u32 route_hi;
+ u32 route_lo;
+ u8 connection_id;
+ u8 reserved[3];
+ u32 challenge[8];
+};
+
+struct icm_tr_pkg_approve_xdomain {
+ struct icm_pkg_header hdr;
+ u32 route_hi;
+ u32 route_lo;
+ uuid_t remote_uuid;
+ u16 transmit_path;
+ u16 transmit_ring;
+ u16 receive_path;
+ u16 receive_ring;
+};
+
+struct icm_tr_pkg_disconnect_xdomain {
+ struct icm_pkg_header hdr;
+ u8 stage;
+ u8 reserved[3];
+ u32 route_hi;
+ u32 route_lo;
+ uuid_t remote_uuid;
+};
+
+struct icm_tr_pkg_challenge_device_response {
+ struct icm_pkg_header hdr;
+ uuid_t ep_uuid;
+ u32 route_hi;
+ u32 route_lo;
+ u8 connection_id;
+ u8 reserved[3];
+ u32 challenge[8];
+ u32 response[8];
+};
+
+struct icm_tr_pkg_add_device_key_response {
+ struct icm_pkg_header hdr;
+ uuid_t ep_uuid;
+ u32 route_hi;
+ u32 route_lo;
+ u8 connection_id;
+ u8 reserved[3];
+};
+
+struct icm_tr_pkg_approve_xdomain_response {
+ struct icm_pkg_header hdr;
+ u32 route_hi;
+ u32 route_lo;
+ uuid_t remote_uuid;
+ u16 transmit_path;
+ u16 transmit_ring;
+ u16 receive_path;
+ u16 receive_ring;
+};
+
+struct icm_tr_pkg_disconnect_xdomain_response {
+ struct icm_pkg_header hdr;
+ u8 stage;
+ u8 reserved[3];
+ u32 route_hi;
+ u32 route_lo;
+ uuid_t remote_uuid;
+};
+
/* XDomain messages */
struct tb_xdomain_header {