Merge tag 'cxl-for-6.0' of git://git.kernel.org/pub/scm/linux/kernel/git/cxl/cxl
Pull cxl updates from Dan Williams: "Compute Express Link (CXL) updates for 6.0: - Introduce a 'struct cxl_region' object with support for provisioning and assembling persistent memory regions. - Introduce alloc_free_mem_region() to accompany the existing request_free_mem_region() as a method to allocate physical memory capacity out of an existing resource. - Export insert_resource_expand_to_fit() for the CXL subsystem to late-publish CXL platform windows in iomem_resource. - Add a polled mode PCI DOE (Data Object Exchange) driver service and use it in cxl_pci to retrieve the CDAT (Coherent Device Attribute Table)" * tag 'cxl-for-6.0' of git://git.kernel.org/pub/scm/linux/kernel/git/cxl/cxl: (74 commits) cxl/hdm: Fix skip allocations vs multiple pmem allocations cxl/region: Disallow region granularity != window granularity cxl/region: Fix x1 interleave to greater than x1 interleave routing cxl/region: Move HPA setup to cxl_region_attach() cxl/region: Fix decoder interleave programming Documentation: cxl: remove dangling kernel-doc reference cxl/region: describe targets and nr_targets members of cxl_region_params cxl/regions: add padding for cxl_rr_ep_add nested lists cxl/region: Fix IS_ERR() vs NULL check cxl/region: Fix region reference target accounting cxl/region: Fix region commit uninitialized variable warning cxl/region: Fix port setup uninitialized variable warnings cxl/region: Stop initializing interleave granularity cxl/hdm: Fix DPA reservation vs cxl_endpoint_decoder lifetime cxl/acpi: Minimize granularity for x1 interleaves cxl/region: Delete 'region' attribute from root decoders cxl/acpi: Autoload driver for 'cxl_acpi' test devices cxl/region: decrement ->nr_targets on error in cxl_region_attach() cxl/region: prevent underflow in ways_to_cxl() cxl/region: uninitialized variable in alloc_hpa() ...
This commit is contained in:
@ -47,6 +47,7 @@ cxl_core-y += $(CXL_CORE_SRC)/memdev.o
|
||||
cxl_core-y += $(CXL_CORE_SRC)/mbox.o
|
||||
cxl_core-y += $(CXL_CORE_SRC)/pci.o
|
||||
cxl_core-y += $(CXL_CORE_SRC)/hdm.o
|
||||
cxl_core-$(CONFIG_CXL_REGION) += $(CXL_CORE_SRC)/region.o
|
||||
cxl_core-y += config_check.o
|
||||
|
||||
obj-m += test/
|
||||
|
@ -14,7 +14,7 @@
|
||||
#define NR_CXL_HOST_BRIDGES 2
|
||||
#define NR_CXL_ROOT_PORTS 2
|
||||
#define NR_CXL_SWITCH_PORTS 2
|
||||
#define NR_CXL_PORT_DECODERS 2
|
||||
#define NR_CXL_PORT_DECODERS 8
|
||||
|
||||
static struct platform_device *cxl_acpi;
|
||||
static struct platform_device *cxl_host_bridge[NR_CXL_HOST_BRIDGES];
|
||||
@ -118,7 +118,7 @@ static struct {
|
||||
.restrictions = ACPI_CEDT_CFMWS_RESTRICT_TYPE3 |
|
||||
ACPI_CEDT_CFMWS_RESTRICT_VOLATILE,
|
||||
.qtg_id = 0,
|
||||
.window_size = SZ_256M,
|
||||
.window_size = SZ_256M * 4UL,
|
||||
},
|
||||
.target = { 0 },
|
||||
},
|
||||
@ -133,7 +133,7 @@ static struct {
|
||||
.restrictions = ACPI_CEDT_CFMWS_RESTRICT_TYPE3 |
|
||||
ACPI_CEDT_CFMWS_RESTRICT_VOLATILE,
|
||||
.qtg_id = 1,
|
||||
.window_size = SZ_256M * 2,
|
||||
.window_size = SZ_256M * 8UL,
|
||||
},
|
||||
.target = { 0, 1, },
|
||||
},
|
||||
@ -148,7 +148,7 @@ static struct {
|
||||
.restrictions = ACPI_CEDT_CFMWS_RESTRICT_TYPE3 |
|
||||
ACPI_CEDT_CFMWS_RESTRICT_PMEM,
|
||||
.qtg_id = 2,
|
||||
.window_size = SZ_256M,
|
||||
.window_size = SZ_256M * 4UL,
|
||||
},
|
||||
.target = { 0 },
|
||||
},
|
||||
@ -163,7 +163,7 @@ static struct {
|
||||
.restrictions = ACPI_CEDT_CFMWS_RESTRICT_TYPE3 |
|
||||
ACPI_CEDT_CFMWS_RESTRICT_PMEM,
|
||||
.qtg_id = 3,
|
||||
.window_size = SZ_256M * 2,
|
||||
.window_size = SZ_256M * 8UL,
|
||||
},
|
||||
.target = { 0, 1, },
|
||||
},
|
||||
@ -429,6 +429,50 @@ static int map_targets(struct device *dev, void *data)
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int mock_decoder_commit(struct cxl_decoder *cxld)
|
||||
{
|
||||
struct cxl_port *port = to_cxl_port(cxld->dev.parent);
|
||||
int id = cxld->id;
|
||||
|
||||
if (cxld->flags & CXL_DECODER_F_ENABLE)
|
||||
return 0;
|
||||
|
||||
dev_dbg(&port->dev, "%s commit\n", dev_name(&cxld->dev));
|
||||
if (port->commit_end + 1 != id) {
|
||||
dev_dbg(&port->dev,
|
||||
"%s: out of order commit, expected decoder%d.%d\n",
|
||||
dev_name(&cxld->dev), port->id, port->commit_end + 1);
|
||||
return -EBUSY;
|
||||
}
|
||||
|
||||
port->commit_end++;
|
||||
cxld->flags |= CXL_DECODER_F_ENABLE;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int mock_decoder_reset(struct cxl_decoder *cxld)
|
||||
{
|
||||
struct cxl_port *port = to_cxl_port(cxld->dev.parent);
|
||||
int id = cxld->id;
|
||||
|
||||
if ((cxld->flags & CXL_DECODER_F_ENABLE) == 0)
|
||||
return 0;
|
||||
|
||||
dev_dbg(&port->dev, "%s reset\n", dev_name(&cxld->dev));
|
||||
if (port->commit_end != id) {
|
||||
dev_dbg(&port->dev,
|
||||
"%s: out of order reset, expected decoder%d.%d\n",
|
||||
dev_name(&cxld->dev), port->id, port->commit_end);
|
||||
return -EBUSY;
|
||||
}
|
||||
|
||||
port->commit_end--;
|
||||
cxld->flags &= ~CXL_DECODER_F_ENABLE;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int mock_cxl_enumerate_decoders(struct cxl_hdm *cxlhdm)
|
||||
{
|
||||
struct cxl_port *port = cxlhdm->port;
|
||||
@ -451,25 +495,39 @@ static int mock_cxl_enumerate_decoders(struct cxl_hdm *cxlhdm)
|
||||
struct cxl_decoder *cxld;
|
||||
int rc;
|
||||
|
||||
if (target_count)
|
||||
cxld = cxl_switch_decoder_alloc(port, target_count);
|
||||
else
|
||||
cxld = cxl_endpoint_decoder_alloc(port);
|
||||
if (IS_ERR(cxld)) {
|
||||
dev_warn(&port->dev,
|
||||
"Failed to allocate the decoder\n");
|
||||
return PTR_ERR(cxld);
|
||||
if (target_count) {
|
||||
struct cxl_switch_decoder *cxlsd;
|
||||
|
||||
cxlsd = cxl_switch_decoder_alloc(port, target_count);
|
||||
if (IS_ERR(cxlsd)) {
|
||||
dev_warn(&port->dev,
|
||||
"Failed to allocate the decoder\n");
|
||||
return PTR_ERR(cxlsd);
|
||||
}
|
||||
cxld = &cxlsd->cxld;
|
||||
} else {
|
||||
struct cxl_endpoint_decoder *cxled;
|
||||
|
||||
cxled = cxl_endpoint_decoder_alloc(port);
|
||||
|
||||
if (IS_ERR(cxled)) {
|
||||
dev_warn(&port->dev,
|
||||
"Failed to allocate the decoder\n");
|
||||
return PTR_ERR(cxled);
|
||||
}
|
||||
cxld = &cxled->cxld;
|
||||
}
|
||||
|
||||
cxld->decoder_range = (struct range) {
|
||||
cxld->hpa_range = (struct range) {
|
||||
.start = 0,
|
||||
.end = -1,
|
||||
};
|
||||
|
||||
cxld->flags = CXL_DECODER_F_ENABLE;
|
||||
cxld->interleave_ways = min_not_zero(target_count, 1);
|
||||
cxld->interleave_granularity = SZ_4K;
|
||||
cxld->target_type = CXL_DECODER_EXPANDER;
|
||||
cxld->commit = mock_decoder_commit;
|
||||
cxld->reset = mock_decoder_reset;
|
||||
|
||||
if (target_count) {
|
||||
rc = device_for_each_child(port->uport, &ctx,
|
||||
@ -569,44 +627,6 @@ static void mock_companion(struct acpi_device *adev, struct device *dev)
|
||||
#define SZ_512G (SZ_64G * 8)
|
||||
#endif
|
||||
|
||||
static struct platform_device *alloc_memdev(int id)
|
||||
{
|
||||
struct resource res[] = {
|
||||
[0] = {
|
||||
.flags = IORESOURCE_MEM,
|
||||
},
|
||||
[1] = {
|
||||
.flags = IORESOURCE_MEM,
|
||||
.desc = IORES_DESC_PERSISTENT_MEMORY,
|
||||
},
|
||||
};
|
||||
struct platform_device *pdev;
|
||||
int i, rc;
|
||||
|
||||
for (i = 0; i < ARRAY_SIZE(res); i++) {
|
||||
struct cxl_mock_res *r = alloc_mock_res(SZ_256M);
|
||||
|
||||
if (!r)
|
||||
return NULL;
|
||||
res[i].start = r->range.start;
|
||||
res[i].end = r->range.end;
|
||||
}
|
||||
|
||||
pdev = platform_device_alloc("cxl_mem", id);
|
||||
if (!pdev)
|
||||
return NULL;
|
||||
|
||||
rc = platform_device_add_resources(pdev, res, ARRAY_SIZE(res));
|
||||
if (rc)
|
||||
goto err;
|
||||
|
||||
return pdev;
|
||||
|
||||
err:
|
||||
platform_device_put(pdev);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
static __init int cxl_test_init(void)
|
||||
{
|
||||
int rc, i;
|
||||
@ -619,7 +639,8 @@ static __init int cxl_test_init(void)
|
||||
goto err_gen_pool_create;
|
||||
}
|
||||
|
||||
rc = gen_pool_add(cxl_mock_pool, SZ_512G, SZ_64G, NUMA_NO_NODE);
|
||||
rc = gen_pool_add(cxl_mock_pool, iomem_resource.end + 1 - SZ_64G,
|
||||
SZ_64G, NUMA_NO_NODE);
|
||||
if (rc)
|
||||
goto err_gen_pool_add;
|
||||
|
||||
@ -708,7 +729,7 @@ static __init int cxl_test_init(void)
|
||||
struct platform_device *dport = cxl_switch_dport[i];
|
||||
struct platform_device *pdev;
|
||||
|
||||
pdev = alloc_memdev(i);
|
||||
pdev = platform_device_alloc("cxl_mem", i);
|
||||
if (!pdev)
|
||||
goto err_mem;
|
||||
pdev->dev.parent = &dport->dev;
|
||||
|
@ -10,6 +10,7 @@
|
||||
#include <cxlmem.h>
|
||||
|
||||
#define LSA_SIZE SZ_128K
|
||||
#define DEV_SIZE SZ_2G
|
||||
#define EFFECT(x) (1U << x)
|
||||
|
||||
static struct cxl_cel_entry mock_cel[] = {
|
||||
@ -25,6 +26,10 @@ static struct cxl_cel_entry mock_cel[] = {
|
||||
.opcode = cpu_to_le16(CXL_MBOX_OP_GET_LSA),
|
||||
.effect = cpu_to_le16(0),
|
||||
},
|
||||
{
|
||||
.opcode = cpu_to_le16(CXL_MBOX_OP_GET_PARTITION_INFO),
|
||||
.effect = cpu_to_le16(0),
|
||||
},
|
||||
{
|
||||
.opcode = cpu_to_le16(CXL_MBOX_OP_SET_LSA),
|
||||
.effect = cpu_to_le16(EFFECT(1) | EFFECT(2)),
|
||||
@ -97,46 +102,41 @@ static int mock_get_log(struct cxl_dev_state *cxlds, struct cxl_mbox_cmd *cmd)
|
||||
|
||||
static int mock_id(struct cxl_dev_state *cxlds, struct cxl_mbox_cmd *cmd)
|
||||
{
|
||||
struct platform_device *pdev = to_platform_device(cxlds->dev);
|
||||
struct cxl_mbox_identify id = {
|
||||
.fw_revision = { "mock fw v1 " },
|
||||
.lsa_size = cpu_to_le32(LSA_SIZE),
|
||||
/* FIXME: Add partition support */
|
||||
.partition_align = cpu_to_le64(0),
|
||||
.partition_align =
|
||||
cpu_to_le64(SZ_256M / CXL_CAPACITY_MULTIPLIER),
|
||||
.total_capacity =
|
||||
cpu_to_le64(DEV_SIZE / CXL_CAPACITY_MULTIPLIER),
|
||||
};
|
||||
u64 capacity = 0;
|
||||
int i;
|
||||
|
||||
if (cmd->size_out < sizeof(id))
|
||||
return -EINVAL;
|
||||
|
||||
for (i = 0; i < 2; i++) {
|
||||
struct resource *res;
|
||||
|
||||
res = platform_get_resource(pdev, IORESOURCE_MEM, i);
|
||||
if (!res)
|
||||
break;
|
||||
|
||||
capacity += resource_size(res) / CXL_CAPACITY_MULTIPLIER;
|
||||
|
||||
if (le64_to_cpu(id.partition_align))
|
||||
continue;
|
||||
|
||||
if (res->desc == IORES_DESC_PERSISTENT_MEMORY)
|
||||
id.persistent_capacity = cpu_to_le64(
|
||||
resource_size(res) / CXL_CAPACITY_MULTIPLIER);
|
||||
else
|
||||
id.volatile_capacity = cpu_to_le64(
|
||||
resource_size(res) / CXL_CAPACITY_MULTIPLIER);
|
||||
}
|
||||
|
||||
id.total_capacity = cpu_to_le64(capacity);
|
||||
|
||||
memcpy(cmd->payload_out, &id, sizeof(id));
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int mock_partition_info(struct cxl_dev_state *cxlds,
|
||||
struct cxl_mbox_cmd *cmd)
|
||||
{
|
||||
struct cxl_mbox_get_partition_info pi = {
|
||||
.active_volatile_cap =
|
||||
cpu_to_le64(DEV_SIZE / 2 / CXL_CAPACITY_MULTIPLIER),
|
||||
.active_persistent_cap =
|
||||
cpu_to_le64(DEV_SIZE / 2 / CXL_CAPACITY_MULTIPLIER),
|
||||
};
|
||||
|
||||
if (cmd->size_out < sizeof(pi))
|
||||
return -EINVAL;
|
||||
|
||||
memcpy(cmd->payload_out, &pi, sizeof(pi));
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int mock_get_lsa(struct cxl_dev_state *cxlds, struct cxl_mbox_cmd *cmd)
|
||||
{
|
||||
struct cxl_mbox_get_lsa *get_lsa = cmd->payload_in;
|
||||
@ -221,6 +221,9 @@ static int cxl_mock_mbox_send(struct cxl_dev_state *cxlds, struct cxl_mbox_cmd *
|
||||
case CXL_MBOX_OP_GET_LSA:
|
||||
rc = mock_get_lsa(cxlds, cmd);
|
||||
break;
|
||||
case CXL_MBOX_OP_GET_PARTITION_INFO:
|
||||
rc = mock_partition_info(cxlds, cmd);
|
||||
break;
|
||||
case CXL_MBOX_OP_SET_LSA:
|
||||
rc = mock_set_lsa(cxlds, cmd);
|
||||
break;
|
||||
@ -282,7 +285,7 @@ static int cxl_mock_mem_probe(struct platform_device *pdev)
|
||||
if (IS_ERR(cxlmd))
|
||||
return PTR_ERR(cxlmd);
|
||||
|
||||
if (range_len(&cxlds->pmem_range) && IS_ENABLED(CONFIG_CXL_PMEM))
|
||||
if (resource_size(&cxlds->pmem_res) && IS_ENABLED(CONFIG_CXL_PMEM))
|
||||
rc = devm_cxl_add_nvdimm(dev, cxlmd);
|
||||
|
||||
return 0;
|
||||
|
@ -208,13 +208,15 @@ int __wrap_cxl_await_media_ready(struct cxl_dev_state *cxlds)
|
||||
}
|
||||
EXPORT_SYMBOL_NS_GPL(__wrap_cxl_await_media_ready, CXL);
|
||||
|
||||
bool __wrap_cxl_hdm_decode_init(struct cxl_dev_state *cxlds,
|
||||
struct cxl_hdm *cxlhdm)
|
||||
int __wrap_cxl_hdm_decode_init(struct cxl_dev_state *cxlds,
|
||||
struct cxl_hdm *cxlhdm)
|
||||
{
|
||||
int rc = 0, index;
|
||||
struct cxl_mock_ops *ops = get_cxl_mock_ops(&index);
|
||||
|
||||
if (!ops || !ops->is_mock_dev(cxlds->dev))
|
||||
if (ops && ops->is_mock_dev(cxlds->dev))
|
||||
rc = 0;
|
||||
else
|
||||
rc = cxl_hdm_decode_init(cxlds, cxlhdm);
|
||||
put_cxl_mock_ops(index);
|
||||
|
||||
|
Reference in New Issue
Block a user