staticbool is_mock_dev(struct device *dev)
{ int i;
for (i = 0; i < ARRAY_SIZE(cxl_mem); i++) if (dev == &cxl_mem[i]->dev) returntrue; for (i = 0; i < ARRAY_SIZE(cxl_mem_single); i++) if (dev == &cxl_mem_single[i]->dev) returntrue; for (i = 0; i < ARRAY_SIZE(cxl_rcd); i++) if (dev == &cxl_rcd[i]->dev) returntrue; if (dev == &cxl_acpi->dev) returntrue; returnfalse;
}
staticbool is_mock_adev(struct acpi_device *adev)
{ int i;
if (adev == &acpi0017_mock) returntrue;
for (i = 0; i < ARRAY_SIZE(host_bridge); i++) if (adev == &host_bridge[i]) returntrue;
res = alloc_mock_res(size, size); if (!res) return -ENOMEM;
chbs->base = res->range.start;
chbs->length = size;
}
for (i = cfmws_start; i <= cfmws_end; i++) { struct acpi_cedt_cfmws *window = mock_cfmws[i];
res = alloc_mock_res(window->window_size, SZ_256M); if (!res) return -ENOMEM;
window->base_hpa = res->range.start;
}
return 0;
}
staticbool is_mock_port(struct device *dev);
/* * WARNING, this hack assumes the format of 'struct cxl_cfmws_context' * and 'struct cxl_chbs_context' share the property that the first * struct member is a cxl_test device being probed by the cxl_acpi * driver.
*/ struct cxl_cedt_context { struct device *dev;
};
if (!is_mock_port(dev) && !is_mock_dev(dev)) return acpi_table_parse_cedt(id, handler_arg, arg);
if (id == ACPI_CEDT_TYPE_CHBS) for (i = 0; i < ARRAY_SIZE(mock_cedt.chbs); i++) {
h = (union acpi_subtable_headers *)&mock_cedt.chbs[i];
end = (unsignedlong)&mock_cedt.chbs[i + 1];
handler_arg(h, arg, end);
}
if (id == ACPI_CEDT_TYPE_CFMWS) for (i = cfmws_start; i <= cfmws_end; i++) {
h = (union acpi_subtable_headers *) mock_cfmws[i];
end = (unsignedlong) h + mock_cfmws[i]->header.length;
handler_arg(h, arg, end);
}
if (id == ACPI_CEDT_TYPE_CXIMS) for (i = 0; i < ARRAY_SIZE(mock_cxims); i++) {
h = (union acpi_subtable_headers *)mock_cxims[i];
end = (unsignedlong)h + mock_cxims[i]->header.length;
handler_arg(h, arg, end);
}
return 0;
}
staticbool is_mock_bridge(struct device *dev)
{ int i;
for (i = 0; i < ARRAY_SIZE(cxl_host_bridge); i++) if (dev == &cxl_host_bridge[i]->dev) returntrue; for (i = 0; i < ARRAY_SIZE(cxl_hb_single); i++) if (dev == &cxl_hb_single[i]->dev) returntrue; for (i = 0; i < ARRAY_SIZE(cxl_rch); i++) if (dev == &cxl_rch[i]->dev) returntrue;
returnfalse;
}
staticbool is_mock_port(struct device *dev)
{ int i;
if (is_mock_bridge(dev)) returntrue;
for (i = 0; i < ARRAY_SIZE(cxl_root_port); i++) if (dev == &cxl_root_port[i]->dev) returntrue;
for (i = 0; i < ARRAY_SIZE(cxl_switch_uport); i++) if (dev == &cxl_switch_uport[i]->dev) returntrue;
for (i = 0; i < ARRAY_SIZE(cxl_switch_dport); i++) if (dev == &cxl_switch_dport[i]->dev) returntrue;
for (i = 0; i < ARRAY_SIZE(cxl_root_single); i++) if (dev == &cxl_root_single[i]->dev) returntrue;
for (i = 0; i < ARRAY_SIZE(cxl_swu_single); i++) if (dev == &cxl_swu_single[i]->dev) returntrue;
for (i = 0; i < ARRAY_SIZE(cxl_swd_single); i++) if (dev == &cxl_swd_single[i]->dev) returntrue;
if (is_cxl_memdev(dev)) return is_mock_dev(dev->parent);
/* check is endpoint is attach to host-bridge0 */
port = cxled_to_port(cxled); do { if (port->uport_dev == &cxl_host_bridge[0]->dev) {
hb0 = true; break;
} if (is_cxl_port(port->dev.parent))
port = to_cxl_port(port->dev.parent); else
port = NULL;
} while (port);
port = cxled_to_port(cxled);
}
/* * The first decoder on the first 2 devices on the first switch * attached to host-bridge0 mock a fake / static RAM region. All * other decoders are default disabled. Given the round robin * assignment those devices are named cxl_mem.0, and cxl_mem.4. * * See 'cxl list -BMPu -m cxl_mem.0,cxl_mem.4'
*/ if (!hb0 || pdev->id % 4 || pdev->id > 4 || cxld->id > 0) {
default_mock_decoder(cxld); return;
}
base = window->base_hpa;
cxld->hpa_range = (struct range) {
.start = base,
.end = base + size - 1,
};
/* * Now that endpoint decoder is set up, walk up the hierarchy * and setup the switch and root port decoders targeting @cxlmd.
*/
iter = port; for (i = 0; i < 2; i++) {
dport = iter->parent_dport;
iter = dport->port;
dev = device_find_child(&iter->dev, NULL, first_decoder); /* * Ancestor ports are guaranteed to be enumerated before * @port, and all ports have at least one decoder.
*/ if (WARN_ON(!dev)) continue;
cxlsd = to_cxl_switch_decoder(dev); if (i == 0) { /* put cxl_mem.4 second in the decode order */ if (pdev->id == 4)
cxlsd->target[1] = dport; else
cxlsd->target[0] = dport;
} else
cxlsd->target[0] = dport;
cxld = &cxlsd->cxld;
cxld->target_type = CXL_DECODER_HOSTONLYMEM;
cxld->flags = CXL_DECODER_F_ENABLE;
iter->commit_end = 0; /* * Switch targets 2 endpoints, while host bridge targets * one root port
*/ if (i == 0)
cxld->interleave_ways = 2; else
cxld->interleave_ways = 1;
cxld->interleave_granularity = 4096;
cxld->hpa_range = (struct range) {
.start = base,
.end = base + size - 1,
};
put_device(dev);
}
}
err_dport: for (i = ARRAY_SIZE(cxl_swd_single) - 1; i >= 0; i--)
platform_device_unregister(cxl_swd_single[i]);
err_uport: for (i = ARRAY_SIZE(cxl_swu_single) - 1; i >= 0; i--)
platform_device_unregister(cxl_swu_single[i]);
err_port: for (i = ARRAY_SIZE(cxl_root_single) - 1; i >= 0; i--)
platform_device_unregister(cxl_root_single[i]);
err_bridge: for (i = ARRAY_SIZE(cxl_hb_single) - 1; i >= 0; i--) { struct platform_device *pdev = cxl_hb_single[i];
if (!pdev) continue;
sysfs_remove_link(&pdev->dev.kobj, "physical_node");
platform_device_unregister(cxl_hb_single[i]);
}
return rc;
}
staticvoid cxl_single_topo_exit(void)
{ int i;
for (i = ARRAY_SIZE(cxl_swd_single) - 1; i >= 0; i--)
platform_device_unregister(cxl_swd_single[i]); for (i = ARRAY_SIZE(cxl_swu_single) - 1; i >= 0; i--)
platform_device_unregister(cxl_swu_single[i]); for (i = ARRAY_SIZE(cxl_root_single) - 1; i >= 0; i--)
platform_device_unregister(cxl_root_single[i]); for (i = ARRAY_SIZE(cxl_hb_single) - 1; i >= 0; i--) { struct platform_device *pdev = cxl_hb_single[i];
if (!pdev) continue;
sysfs_remove_link(&pdev->dev.kobj, "physical_node");
platform_device_unregister(cxl_hb_single[i]);
}
}
staticvoid cxl_mem_exit(void)
{ int i;
for (i = ARRAY_SIZE(cxl_rcd) - 1; i >= 0; i--)
platform_device_unregister(cxl_rcd[i]); for (i = ARRAY_SIZE(cxl_mem_single) - 1; i >= 0; i--)
platform_device_unregister(cxl_mem_single[i]); for (i = ARRAY_SIZE(cxl_mem) - 1; i >= 0; i--)
platform_device_unregister(cxl_mem[i]);
}
staticint cxl_mem_init(void)
{ int i, rc;
for (i = 0; i < ARRAY_SIZE(cxl_mem); i++) { struct platform_device *dport = cxl_switch_dport[i]; struct platform_device *pdev;
pdev = platform_device_alloc("cxl_mem", i); if (!pdev) goto err_mem;
pdev->dev.parent = &dport->dev;
set_dev_node(&pdev->dev, i % 2);
err_rcd: for (i = ARRAY_SIZE(cxl_rcd) - 1; i >= 0; i--)
platform_device_unregister(cxl_rcd[i]);
err_single: for (i = ARRAY_SIZE(cxl_mem_single) - 1; i >= 0; i--)
platform_device_unregister(cxl_mem_single[i]);
err_mem: for (i = ARRAY_SIZE(cxl_mem) - 1; i >= 0; i--)
platform_device_unregister(cxl_mem[i]); return rc;
}
static __init int cxl_test_init(void)
{ int rc, i; struct range mappable;
rc = platform_device_add(cxl_acpi); if (rc) goto err_root;
rc = cxl_mem_init(); if (rc) goto err_root;
return 0;
err_root:
platform_device_put(cxl_acpi);
err_rch:
cxl_rch_topo_exit();
err_single:
cxl_single_topo_exit();
err_dport: for (i = ARRAY_SIZE(cxl_switch_dport) - 1; i >= 0; i--)
platform_device_unregister(cxl_switch_dport[i]);
err_uport: for (i = ARRAY_SIZE(cxl_switch_uport) - 1; i >= 0; i--)
platform_device_unregister(cxl_switch_uport[i]);
err_port: for (i = ARRAY_SIZE(cxl_root_port) - 1; i >= 0; i--)
platform_device_unregister(cxl_root_port[i]);
err_bridge: for (i = ARRAY_SIZE(cxl_host_bridge) - 1; i >= 0; i--) { struct platform_device *pdev = cxl_host_bridge[i];
cxl_mem_exit();
platform_device_unregister(cxl_acpi);
cxl_rch_topo_exit();
cxl_single_topo_exit(); for (i = ARRAY_SIZE(cxl_switch_dport) - 1; i >= 0; i--)
platform_device_unregister(cxl_switch_dport[i]); for (i = ARRAY_SIZE(cxl_switch_uport) - 1; i >= 0; i--)
platform_device_unregister(cxl_switch_uport[i]); for (i = ARRAY_SIZE(cxl_root_port) - 1; i >= 0; i--)
platform_device_unregister(cxl_root_port[i]); for (i = ARRAY_SIZE(cxl_host_bridge) - 1; i >= 0; i--) { struct platform_device *pdev = cxl_host_bridge[i];
¤ Die Informationen auf dieser Webseite wurden
nach bestem Wissen sorgfältig zusammengestellt. Es wird jedoch weder Vollständigkeit, noch Richtigkeit,
noch Qualität der bereit gestellten Informationen zugesichert.0.12Bemerkung:
¤
Die Informationen auf dieser Webseite wurden
nach bestem Wissen sorgfältig zusammengestellt. Es wird jedoch weder Vollständigkeit, noch Richtigkeit,
noch Qualität der bereit gestellten Informationen zugesichert.
Bemerkung:
Die farbliche Syntaxdarstellung und die Messung sind noch experimentell.