aboutsummaryrefslogtreecommitdiff
path: root/hw/cxl
diff options
context:
space:
mode:
authorJonathan Cameron <Jonathan.Cameron@huawei.com>2022-06-16 15:51:25 +0100
committerMichael S. Tsirkin <mst@redhat.com>2022-06-16 12:54:57 -0400
commit18cef1c6a5a37710a2e5876fed2445849f31e321 (patch)
treea89e89a03c491f4f9c83e020b61e639dddf61091 /hw/cxl
parent638b752da30a9daffb0c92166937a0cb777f9e23 (diff)
pci-bridge/cxl_downstream: Add a CXL switch downstream port
Emulation of a simple CXL Switch downstream port. The Device ID has been allocated for this use. Signed-off-by: Jonathan Cameron <Jonathan.Cameron@huawei.com> Message-Id: <20220616145126.8002-3-Jonathan.Cameron@huawei.com> Signed-off-by: Michael S. Tsirkin <mst@redhat.com> Reviewed-by: Michael S. Tsirkin <mst@redhat.com> Signed-off-by: Michael S. Tsirkin <mst@redhat.com>
Diffstat (limited to 'hw/cxl')
-rw-r--r--hw/cxl/cxl-host.c43
1 files changed, 41 insertions, 2 deletions
diff --git a/hw/cxl/cxl-host.c b/hw/cxl/cxl-host.c
index efa14908d8..483d8eb13f 100644
--- a/hw/cxl/cxl-host.c
+++ b/hw/cxl/cxl-host.c
@@ -129,8 +129,9 @@ static bool cxl_hdm_find_target(uint32_t *cache_mem, hwaddr addr,
static PCIDevice *cxl_cfmws_find_device(CXLFixedWindow *fw, hwaddr addr)
{
- CXLComponentState *hb_cstate;
+ CXLComponentState *hb_cstate, *usp_cstate;
PCIHostState *hb;
+ CXLUpstreamPort *usp;
int rb_index;
uint32_t *cache_mem;
uint8_t target;
@@ -164,8 +165,46 @@ static PCIDevice *cxl_cfmws_find_device(CXLFixedWindow *fw, hwaddr addr)
}
d = pci_bridge_get_sec_bus(PCI_BRIDGE(rp))->devices[0];
+ if (!d) {
+ return NULL;
+ }
+
+ if (object_dynamic_cast(OBJECT(d), TYPE_CXL_TYPE3)) {
+ return d;
+ }
+
+ /*
+ * Could also be a switch. Note only one level of switching currently
+ * supported.
+ */
+ if (!object_dynamic_cast(OBJECT(d), TYPE_CXL_USP)) {
+ return NULL;
+ }
+ usp = CXL_USP(d);
+
+ usp_cstate = cxl_usp_to_cstate(usp);
+ if (!usp_cstate) {
+ return NULL;
+ }
+
+ cache_mem = usp_cstate->crb.cache_mem_registers;
+
+ target_found = cxl_hdm_find_target(cache_mem, addr, &target);
+ if (!target_found) {
+ return NULL;
+ }
+
+ d = pcie_find_port_by_pn(&PCI_BRIDGE(d)->sec_bus, target);
+ if (!d) {
+ return NULL;
+ }
+
+ d = pci_bridge_get_sec_bus(PCI_BRIDGE(d))->devices[0];
+ if (!d) {
+ return NULL;
+ }
- if (!d || !object_dynamic_cast(OBJECT(d), TYPE_CXL_TYPE3)) {
+ if (!object_dynamic_cast(OBJECT(d), TYPE_CXL_TYPE3)) {
return NULL;
}