* [PATCH v8 0/3] CXL XOR Interleave Arithmetic
@ 2022-11-22 22:52 alison.schofield
2022-11-22 22:52 ` [PATCH v8 1/3] ACPICA commit 2d8dc0383d3c908389053afbdc329bbd52f009ce alison.schofield
` (2 more replies)
0 siblings, 3 replies; 8+ messages in thread
From: alison.schofield @ 2022-11-22 22:52 UTC (permalink / raw)
To: Dan Williams, Ira Weiny, Vishal Verma, Ben Widawsky, Dave Jiang
Cc: Alison Schofield, linux-cxl
From: Alison Schofield <alison.schofield@intel.com>
Changes in v8:
- Move typedef of cxl_cal_hb_fn in cxl.h earlier for use in cxl_root_decoder
(It's a bit soon, and a bit small, for rev'ing without awaiting review,
but want this to be in sync with the address translation patchset
that follows.)
Changes in v7:
- Set calc_hb only once (DavidL, Dan)
- Refactor to eliminate the decoder_add goto (DavidL)
- dev_err() and fail on unknown interleave arithmetic (DavidL)
- Add NULL check after devm_zalloc() of cximsd (DavidL)
- Rename struct cxims_data cxl_cxims_data
Changes in v6:
- Rebase on 6.1-rc4, merging with Dan's latest cxl_test work.
- ACPI patch is now the 'official' linuxized version, not yet merged.
Changes in v5:
- Add to 'n' for 6 & 12 way. (v3->v4 broke it)
- Clean up x3 index init. (Dan)
- Remove unneeded HB's from cxl_test topology.
- Remove dependency on stale patch in cxl_test.
Changes in v4:
- Use GENMASK_ULL to fix i386 arch build (0-day)
- Use do_div to fix ARM arch build (0-day)
- Update comments in ACPICA patch to reflect new state of the
ACPICA patch - pending again in github.
Changes in v3:
- Fix the 3, 6, 12 way interleave (again).
- Do not look for a CXIMS when not needed for x1 & x3 interleaves
- New cxl_test patch: Add cxl_test module support for this feature
- In a separate ndctl patch, cxl test: cxl_xor_region is added
Changes in v2:
- Use ilog2() of the decoded interleave ways to determine number
of xormaps, instead of using encoded ways directly. This fixes
3, 6, and 12 way interleaves. (Dan)
Add support for the new 'XOR' Interleave Arithmetic as defined
in the CXL 3.0 Specification:
https://www.computeexpresslink.org/download-the-specification
Alison Schofield (3):
ACPICA commit 2d8dc0383d3c908389053afbdc329bbd52f009ce
cxl/acpi: Support CXL XOR Interleave Math (CXIMS)
tools/testing/cxl: Add XOR Math support to cxl_test
drivers/cxl/acpi.c | 126 ++++++++++++++++++++++++++++++++++-
drivers/cxl/core/port.c | 9 ++-
drivers/cxl/cxl.h | 13 +++-
include/acpi/actbl1.h | 35 +++++++++-
tools/testing/cxl/test/cxl.c | 118 +++++++++++++++++++++++++++++++-
5 files changed, 289 insertions(+), 12 deletions(-)
base-commit: f0c4d9fc9cc9462659728d168387191387e903cc
--
2.37.3
^ permalink raw reply [flat|nested] 8+ messages in thread
* [PATCH v8 1/3] ACPICA commit 2d8dc0383d3c908389053afbdc329bbd52f009ce
2022-11-22 22:52 [PATCH v8 0/3] CXL XOR Interleave Arithmetic alison.schofield
@ 2022-11-22 22:52 ` alison.schofield
2022-11-22 22:52 ` [PATCH v8 2/3] cxl/acpi: Support CXL XOR Interleave Math (CXIMS) alison.schofield
2022-11-22 22:52 ` [PATCH v8 3/3] tools/testing/cxl: Add XOR Math support to cxl_test alison.schofield
2 siblings, 0 replies; 8+ messages in thread
From: alison.schofield @ 2022-11-22 22:52 UTC (permalink / raw)
To: Dan Williams, Ira Weiny, Vishal Verma, Ben Widawsky, Dave Jiang
Cc: Alison Schofield, linux-cxl
From: Alison Schofield <alison.schofield@intel.com>
Included for reference only.
The CXL 3.0 Specification [1] adds two new structures to
the CXL Early Discovery Table (CEDT). The CEDT may include
zero or more entries of these types:
CXIMS: CXL XOR Interleave Math Structure
Enables the host to find a targets position in an
Interleave Target List when XOR Math is used.
RDPAS: RCEC Downstream Post Association Structure
Enables the host to locate the Downstream Port(s)
that report errors to a given Root Complex Event
Collector (RCEC).
Link: https://www.computeexpresslink.org/spec-landing # [1]
Link: https://github.com/acpica/acpica/commit/2d8dc038
Signed-off-by: Alison Schofield <alison.schofield@intel.com>
Removed Bob and Rafael SOBs to prevent spamming them on my every rev.
---
include/acpi/actbl1.h | 35 ++++++++++++++++++++++++++++++++++-
1 file changed, 34 insertions(+), 1 deletion(-)
diff --git a/include/acpi/actbl1.h b/include/acpi/actbl1.h
index 15c78678c5d3..2aba6f516e70 100644
--- a/include/acpi/actbl1.h
+++ b/include/acpi/actbl1.h
@@ -329,7 +329,9 @@ struct acpi_cedt_header {
enum acpi_cedt_type {
ACPI_CEDT_TYPE_CHBS = 0,
ACPI_CEDT_TYPE_CFMWS = 1,
- ACPI_CEDT_TYPE_RESERVED = 2,
+ ACPI_CEDT_TYPE_CXIMS = 2,
+ ACPI_CEDT_TYPE_RDPAS = 3,
+ ACPI_CEDT_TYPE_RESERVED = 4,
};
/* Values for version field above */
@@ -380,6 +382,7 @@ struct acpi_cedt_cfmws_target_element {
/* Values for Interleave Arithmetic field above */
#define ACPI_CEDT_CFMWS_ARITHMETIC_MODULO (0)
+#define ACPI_CEDT_CFMWS_ARITHMETIC_XOR (1)
/* Values for Restrictions field above */
@@ -389,6 +392,36 @@ struct acpi_cedt_cfmws_target_element {
#define ACPI_CEDT_CFMWS_RESTRICT_PMEM (1<<3)
#define ACPI_CEDT_CFMWS_RESTRICT_FIXED (1<<4)
+/* 2: CXL XOR Interleave Math Structure */
+
+struct acpi_cedt_cxims {
+ struct acpi_cedt_header header;
+ u16 reserved1;
+ u8 hbig;
+ u8 nr_xormaps;
+ u64 xormap_list[];
+};
+
+/* 3: CXL RCEC Downstream Port Association Structure */
+
+struct acpi_cedt_rdpas {
+ struct acpi_cedt_header header;
+ u8 reserved1;
+ u16 length;
+ u16 segment;
+ u16 bdf;
+ u8 protocol;
+ u64 address;
+};
+
+/* Masks for bdf field above */
+#define ACPI_CEDT_RDPAS_BUS_MASK 0xff00
+#define ACPI_CEDT_RDPAS_DEVICE_MASK 0x00f8
+#define ACPI_CEDT_RDPAS_FUNCTION_MASK 0x0007
+
+#define ACPI_CEDT_RDPAS_PROTOCOL_IO (0)
+#define ACPI_CEDT_RDPAS_PROTOCOL_CACHEMEM (1)
+
/*******************************************************************************
*
* CPEP - Corrected Platform Error Polling table (ACPI 4.0)
--
2.37.3
^ permalink raw reply related [flat|nested] 8+ messages in thread
* [PATCH v8 2/3] cxl/acpi: Support CXL XOR Interleave Math (CXIMS)
2022-11-22 22:52 [PATCH v8 0/3] CXL XOR Interleave Arithmetic alison.schofield
2022-11-22 22:52 ` [PATCH v8 1/3] ACPICA commit 2d8dc0383d3c908389053afbdc329bbd52f009ce alison.schofield
@ 2022-11-22 22:52 ` alison.schofield
2022-11-30 18:14 ` Jonathan Cameron
2022-11-22 22:52 ` [PATCH v8 3/3] tools/testing/cxl: Add XOR Math support to cxl_test alison.schofield
2 siblings, 1 reply; 8+ messages in thread
From: alison.schofield @ 2022-11-22 22:52 UTC (permalink / raw)
To: Dan Williams, Ira Weiny, Vishal Verma, Ben Widawsky, Dave Jiang
Cc: Alison Schofield, linux-cxl
From: Alison Schofield <alison.schofield@intel.com>
When the CFMWS is using XOR math, parse the corresponding
CXIMS structure and store the xormaps in the root decoder
structure. Use the xormaps in a new lookup, cxl_hb_xor(),
to find a targets entry in the host bridge interleave
target list.
Defined in CXL Specfication 3.0 Section: 9.17.1
Signed-off-by: Alison Schofield <alison.schofield@intel.com>
---
drivers/cxl/acpi.c | 126 +++++++++++++++++++++++++++++++++++++++-
drivers/cxl/core/port.c | 9 ++-
drivers/cxl/cxl.h | 13 ++++-
3 files changed, 140 insertions(+), 8 deletions(-)
diff --git a/drivers/cxl/acpi.c b/drivers/cxl/acpi.c
index fb649683dd3a..98c84942ed37 100644
--- a/drivers/cxl/acpi.c
+++ b/drivers/cxl/acpi.c
@@ -6,9 +6,107 @@
#include <linux/kernel.h>
#include <linux/acpi.h>
#include <linux/pci.h>
+#include <asm/div64.h>
#include "cxlpci.h"
#include "cxl.h"
+struct cxl_cxims_data {
+ int nr_maps;
+ u64 xormaps[];
+};
+
+/*
+ * Find a targets entry (n) in the host bridge interleave list.
+ * CXL Specfication 3.0 Table 9-22
+ */
+static struct cxl_dport *cxl_hb_xor(struct cxl_root_decoder *cxlrd, int pos)
+{
+ struct cxl_cxims_data *cximsd = cxlrd->platform_data;
+ struct cxl_switch_decoder *cxlsd = &cxlrd->cxlsd;
+ struct cxl_decoder *cxld = &cxlsd->cxld;
+ int ig = cxld->interleave_granularity;
+ int iw = cxld->interleave_ways;
+ int eiw, i = 0, n = 0;
+ u64 hpa;
+
+ if (dev_WARN_ONCE(&cxld->dev,
+ cxld->interleave_ways != cxlsd->nr_targets,
+ "misconfigured root decoder\n"))
+ return NULL;
+
+ if (iw == 1)
+ /* Entry is always 0 for no interleave */
+ return cxlrd->cxlsd.target[0];
+
+ hpa = cxlrd->res->start + pos * ig;
+
+ if (iw == 3)
+ goto no_map;
+
+ /* IW: 2,4,6,8,12,16 begin building 'n' using xormaps */
+ for (i = 0; i < cximsd->nr_maps; i++)
+ n |= (hweight64(hpa & cximsd->xormaps[i]) & 1) << i;
+
+no_map:
+ /* IW: 3,6,12 add a modulo calculation to 'n' */
+ if (!is_power_of_2(iw)) {
+ eiw = ilog2(iw / 3) + 8;
+ hpa &= GENMASK_ULL(51, eiw + ig);
+ n |= do_div(hpa, 3) << i;
+ }
+ return cxlrd->cxlsd.target[n];
+}
+
+struct cxl_cxims_context {
+ struct device *dev;
+ struct cxl_root_decoder *cxlrd;
+};
+
+static int cxl_parse_cxims(union acpi_subtable_headers *header, void *arg,
+ const unsigned long end)
+{
+ struct acpi_cedt_cxims *cxims = (struct acpi_cedt_cxims *)header;
+ struct cxl_cxims_context *ctx = arg;
+ struct cxl_root_decoder *cxlrd = ctx->cxlrd;
+ struct cxl_decoder *cxld = &cxlrd->cxlsd.cxld;
+ struct device *dev = ctx->dev;
+ struct cxl_cxims_data *cximsd;
+ unsigned int hbig, nr_maps;
+ int rc;
+
+ rc = cxl_to_granularity(cxims->hbig, &hbig);
+ if (rc)
+ return rc;
+
+ if (hbig == cxld->interleave_granularity) {
+ /* IW 1,3 do not use xormaps and skip this parsing entirely */
+
+ if (is_power_of_2(cxld->interleave_ways))
+ /* 2, 4, 8, 16 way */
+ nr_maps = ilog2(cxld->interleave_ways);
+ else
+ /* 6, 12 way */
+ nr_maps = ilog2(cxld->interleave_ways / 3);
+
+ if (cxims->nr_xormaps < nr_maps) {
+ dev_dbg(dev, "CXIMS nr_xormaps[%d] expected[%d]\n",
+ cxims->nr_xormaps, nr_maps);
+ return -ENXIO;
+ }
+
+ cximsd = devm_kzalloc(dev,
+ struct_size(cximsd, xormaps, nr_maps),
+ GFP_KERNEL);
+ if (!cximsd)
+ return -ENOMEM;
+ memcpy(cximsd->xormaps, cxims->xormap_list,
+ nr_maps * sizeof(*cximsd->xormaps));
+ cximsd->nr_maps = nr_maps;
+ cxlrd->platform_data = cximsd;
+ }
+ return 0;
+}
+
static unsigned long cfmws_to_decoder_flags(int restrictions)
{
unsigned long flags = CXL_DECODER_F_ENABLE;
@@ -33,8 +131,10 @@ static int cxl_acpi_cfmws_verify(struct device *dev,
int rc, expected_len;
unsigned int ways;
- if (cfmws->interleave_arithmetic != ACPI_CEDT_CFMWS_ARITHMETIC_MODULO) {
- dev_err(dev, "CFMWS Unsupported Interleave Arithmetic\n");
+ if (cfmws->interleave_arithmetic != ACPI_CEDT_CFMWS_ARITHMETIC_MODULO &&
+ cfmws->interleave_arithmetic != ACPI_CEDT_CFMWS_ARITHMETIC_XOR) {
+ dev_err(dev, "CFMWS Unknown Interleave Arithmetic: %d\n",
+ cfmws->interleave_arithmetic);
return -EINVAL;
}
@@ -84,9 +184,11 @@ static int cxl_parse_cfmws(union acpi_subtable_headers *header, void *arg,
struct cxl_cfmws_context *ctx = arg;
struct cxl_port *root_port = ctx->root_port;
struct resource *cxl_res = ctx->cxl_res;
+ struct cxl_cxims_context cxims_ctx;
struct cxl_root_decoder *cxlrd;
struct device *dev = ctx->dev;
struct acpi_cedt_cfmws *cfmws;
+ cxl_calc_hb_fn cxl_calc_hb;
struct cxl_decoder *cxld;
unsigned int ways, i, ig;
struct resource *res;
@@ -128,7 +230,12 @@ static int cxl_parse_cfmws(union acpi_subtable_headers *header, void *arg,
if (rc)
goto err_insert;
- cxlrd = cxl_root_decoder_alloc(root_port, ways);
+ if (cfmws->interleave_arithmetic == ACPI_CEDT_CFMWS_ARITHMETIC_MODULO)
+ cxl_calc_hb = cxl_hb_modulo;
+ else
+ cxl_calc_hb = cxl_hb_xor;
+
+ cxlrd = cxl_root_decoder_alloc(root_port, ways, cxl_calc_hb);
if (IS_ERR(cxlrd))
return 0;
@@ -148,7 +255,20 @@ static int cxl_parse_cfmws(union acpi_subtable_headers *header, void *arg,
ig = CXL_DECODER_MIN_GRANULARITY;
cxld->interleave_granularity = ig;
+ if (cfmws->interleave_arithmetic == ACPI_CEDT_CFMWS_ARITHMETIC_XOR) {
+ if (ways != 1 && ways != 3) {
+ cxims_ctx = (struct cxl_cxims_context) {
+ .dev = dev,
+ .cxlrd = cxlrd,
+ };
+ rc = acpi_table_parse_cedt(ACPI_CEDT_TYPE_CXIMS,
+ cxl_parse_cxims, &cxims_ctx);
+ if (rc < 0)
+ goto err_xormap;
+ }
+ }
rc = cxl_decoder_add(cxld, target_map);
+err_xormap:
if (rc)
put_device(&cxld->dev);
else
diff --git a/drivers/cxl/core/port.c b/drivers/cxl/core/port.c
index e7556864ea80..42cdf224a85d 100644
--- a/drivers/cxl/core/port.c
+++ b/drivers/cxl/core/port.c
@@ -1428,7 +1428,7 @@ static int decoder_populate_targets(struct cxl_switch_decoder *cxlsd,
return rc;
}
-static struct cxl_dport *cxl_hb_modulo(struct cxl_root_decoder *cxlrd, int pos)
+struct cxl_dport *cxl_hb_modulo(struct cxl_root_decoder *cxlrd, int pos)
{
struct cxl_switch_decoder *cxlsd = &cxlrd->cxlsd;
struct cxl_decoder *cxld = &cxlsd->cxld;
@@ -1441,6 +1441,7 @@ static struct cxl_dport *cxl_hb_modulo(struct cxl_root_decoder *cxlrd, int pos)
return cxlrd->cxlsd.target[pos % iw];
}
+EXPORT_SYMBOL_NS_GPL(cxl_hb_modulo, CXL);
static struct lock_class_key cxl_decoder_key;
@@ -1502,6 +1503,7 @@ static int cxl_switch_decoder_init(struct cxl_port *port,
* cxl_root_decoder_alloc - Allocate a root level decoder
* @port: owning CXL root of this decoder
* @nr_targets: static number of downstream targets
+ * @calc_hb: which host bridge covers the n'th position by granularity
*
* Return: A new cxl decoder to be registered by cxl_decoder_add(). A
* 'CXL root' decoder is one that decodes from a top-level / static platform
@@ -1509,7 +1511,8 @@ static int cxl_switch_decoder_init(struct cxl_port *port,
* topology.
*/
struct cxl_root_decoder *cxl_root_decoder_alloc(struct cxl_port *port,
- unsigned int nr_targets)
+ unsigned int nr_targets,
+ cxl_calc_hb_fn calc_hb)
{
struct cxl_root_decoder *cxlrd;
struct cxl_switch_decoder *cxlsd;
@@ -1531,7 +1534,7 @@ struct cxl_root_decoder *cxl_root_decoder_alloc(struct cxl_port *port,
return ERR_PTR(rc);
}
- cxlrd->calc_hb = cxl_hb_modulo;
+ cxlrd->calc_hb = calc_hb;
cxld = &cxlsd->cxld;
cxld->dev.type = &cxl_decoder_root_type;
diff --git a/drivers/cxl/cxl.h b/drivers/cxl/cxl.h
index ac75554b5d76..d03aa1776fc8 100644
--- a/drivers/cxl/cxl.h
+++ b/drivers/cxl/cxl.h
@@ -324,18 +324,24 @@ struct cxl_switch_decoder {
struct cxl_dport *target[];
};
+struct cxl_root_decoder;
+struct cxl_endpoint_decoder;
+typedef struct cxl_dport *(*cxl_calc_hb_fn)(struct cxl_root_decoder *cxlrd,
+ int pos);
/**
* struct cxl_root_decoder - Static platform CXL address decoder
* @res: host / parent resource for region allocations
* @region_id: region id for next region provisioning event
* @calc_hb: which host bridge covers the n'th position by granularity
+ * @platform_data: platform specific configuration data
* @cxlsd: base cxl switch decoder
*/
struct cxl_root_decoder {
struct resource *res;
atomic_t region_id;
- struct cxl_dport *(*calc_hb)(struct cxl_root_decoder *cxlrd, int pos);
+ cxl_calc_hb_fn calc_hb;
+ void *platform_data;
struct cxl_switch_decoder cxlsd;
};
@@ -580,8 +586,11 @@ struct cxl_root_decoder *to_cxl_root_decoder(struct device *dev);
struct cxl_endpoint_decoder *to_cxl_endpoint_decoder(struct device *dev);
bool is_root_decoder(struct device *dev);
bool is_endpoint_decoder(struct device *dev);
+
struct cxl_root_decoder *cxl_root_decoder_alloc(struct cxl_port *port,
- unsigned int nr_targets);
+ unsigned int nr_targets,
+ cxl_calc_hb_fn calc_hb);
+struct cxl_dport *cxl_hb_modulo(struct cxl_root_decoder *cxlrd, int pos);
struct cxl_switch_decoder *cxl_switch_decoder_alloc(struct cxl_port *port,
unsigned int nr_targets);
int cxl_decoder_add(struct cxl_decoder *cxld, int *target_map);
--
2.37.3
^ permalink raw reply related [flat|nested] 8+ messages in thread
* [PATCH v8 3/3] tools/testing/cxl: Add XOR Math support to cxl_test
2022-11-22 22:52 [PATCH v8 0/3] CXL XOR Interleave Arithmetic alison.schofield
2022-11-22 22:52 ` [PATCH v8 1/3] ACPICA commit 2d8dc0383d3c908389053afbdc329bbd52f009ce alison.schofield
2022-11-22 22:52 ` [PATCH v8 2/3] cxl/acpi: Support CXL XOR Interleave Math (CXIMS) alison.schofield
@ 2022-11-22 22:52 ` alison.schofield
2022-11-30 18:24 ` Jonathan Cameron
2 siblings, 1 reply; 8+ messages in thread
From: alison.schofield @ 2022-11-22 22:52 UTC (permalink / raw)
To: Dan Williams, Ira Weiny, Vishal Verma, Ben Widawsky, Dave Jiang
Cc: Alison Schofield, linux-cxl
From: Alison Schofield <alison.schofield@intel.com>
Expand the cxl_test topology to include CFMWS's that use XOR math
for interleave arithmetic, as defined in the CXL Specification 3.0.
With this expanded topology, cxl_test is useful for testing:
x1,x2,x4 ways with XOR interleave arithmetic.
Define the additional XOR CFMWS entries to appear only with the
module parameter interleave_arithmetic=1. The cxl_test default
continues to be modulo math.
modprobe cxl_test interleave_arithmetic=1
Signed-off-by: Alison Schofield <alison.schofield@intel.com>
---
tools/testing/cxl/test/cxl.c | 118 ++++++++++++++++++++++++++++++++++-
1 file changed, 115 insertions(+), 3 deletions(-)
diff --git a/tools/testing/cxl/test/cxl.c b/tools/testing/cxl/test/cxl.c
index 7edce12fd2ce..97849e9753f5 100644
--- a/tools/testing/cxl/test/cxl.c
+++ b/tools/testing/cxl/test/cxl.c
@@ -11,6 +11,8 @@
#include <cxlmem.h>
#include "mock.h"
+static int interleave_arithmetic;
+
#define NR_CXL_HOST_BRIDGES 2
#define NR_CXL_SINGLE_HOST 1
#define NR_CXL_ROOT_PORTS 2
@@ -122,6 +124,22 @@ static struct {
struct acpi_cedt_cfmws cfmws;
u32 target[1];
} cfmws4;
+ struct {
+ struct acpi_cedt_cfmws cfmws;
+ u32 target[1];
+ } cfmws5;
+ struct {
+ struct acpi_cedt_cfmws cfmws;
+ u32 target[2];
+ } cfmws6;
+ struct {
+ struct acpi_cedt_cfmws cfmws;
+ u32 target[4];
+ } cfmws7;
+ struct {
+ struct acpi_cedt_cxims cxims;
+ u64 xormap_list[2];
+ } cxims0;
} __packed mock_cedt = {
.cedt = {
.header = {
@@ -229,14 +247,89 @@ static struct {
},
.target = { 2 },
},
+ /* .cfmws5,6,7 use XOR Math (interleave_arithmetic == 1) */
+ .cfmws5 = {
+ .cfmws = {
+ .header = {
+ .type = ACPI_CEDT_TYPE_CFMWS,
+ .length = sizeof(mock_cedt.cfmws5),
+ },
+ .interleave_arithmetic = 1,
+ .interleave_ways = 0,
+ .granularity = 4,
+ .restrictions = ACPI_CEDT_CFMWS_RESTRICT_TYPE3 |
+ ACPI_CEDT_CFMWS_RESTRICT_PMEM,
+ .qtg_id = 0,
+ .window_size = SZ_256M * 8UL,
+ },
+ .target = { 0 },
+ },
+ .cfmws6 = {
+ .cfmws = {
+ .header = {
+ .type = ACPI_CEDT_TYPE_CFMWS,
+ .length = sizeof(mock_cedt.cfmws6),
+ },
+ .interleave_arithmetic = 1,
+ .interleave_ways = 1,
+ .granularity = 0,
+ .restrictions = ACPI_CEDT_CFMWS_RESTRICT_TYPE3 |
+ ACPI_CEDT_CFMWS_RESTRICT_PMEM,
+ .qtg_id = 1,
+ .window_size = SZ_256M * 8UL,
+ },
+ .target = { 0, 1, },
+ },
+ .cfmws7 = {
+ .cfmws = {
+ .header = {
+ .type = ACPI_CEDT_TYPE_CFMWS,
+ .length = sizeof(mock_cedt.cfmws7),
+ },
+ .interleave_arithmetic = 1,
+ .interleave_ways = 2,
+ .granularity = 0,
+ .restrictions = ACPI_CEDT_CFMWS_RESTRICT_TYPE3 |
+ ACPI_CEDT_CFMWS_RESTRICT_PMEM,
+ .qtg_id = 0,
+ .window_size = SZ_256M * 16UL,
+ },
+ .target = { 0, 1, 0, 1, },
+ },
+ .cxims0 = {
+ .cxims = {
+ .header = {
+ .type = ACPI_CEDT_TYPE_CXIMS,
+ .length = sizeof(mock_cedt.cxims0),
+ },
+ .hbig = 0,
+ .nr_xormaps = 2,
+ },
+ .xormap_list = { 0x404100, 0x808200 },
+ },
};
-struct acpi_cedt_cfmws *mock_cfmws[] = {
+struct acpi_cedt_cfmws *mock_cfmws[8] = {
[0] = &mock_cedt.cfmws0.cfmws,
[1] = &mock_cedt.cfmws1.cfmws,
[2] = &mock_cedt.cfmws2.cfmws,
[3] = &mock_cedt.cfmws3.cfmws,
[4] = &mock_cedt.cfmws4.cfmws,
+ /* Modulo Math above, XOR Math below */
+ [5] = &mock_cedt.cfmws5.cfmws,
+ [6] = &mock_cedt.cfmws6.cfmws,
+ [7] = &mock_cedt.cfmws7.cfmws,
+};
+
+static int cfmws_start;
+static int cfmws_end;
+#define CFMWS_MOD_ARRAY_START 0
+#define CFMWS_MOD_ARRAY_END 4
+#define CFMWS_XOR_ARRAY_START 5
+#define CFMWS_XOR_ARRAY_END 7
+
+struct acpi_cedt_cxims *mock_cxims[1] = {
+ [0] = &mock_cedt.cxims0.cxims,
};
struct cxl_mock_res {
@@ -308,7 +401,7 @@ static int populate_cedt(void)
chbs->length = size;
}
- for (i = 0; i < ARRAY_SIZE(mock_cfmws); i++) {
+ for (i = cfmws_start; i <= cfmws_end; i++) {
struct acpi_cedt_cfmws *window = mock_cfmws[i];
res = alloc_mock_res(window->window_size);
@@ -351,12 +444,19 @@ static int mock_acpi_table_parse_cedt(enum acpi_cedt_type id,
}
if (id == ACPI_CEDT_TYPE_CFMWS)
- for (i = 0; i < ARRAY_SIZE(mock_cfmws); i++) {
+ for (i = cfmws_start; i <= cfmws_end; i++) {
h = (union acpi_subtable_headers *) mock_cfmws[i];
end = (unsigned long) 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 = (unsigned long)h + mock_cxims[i]->header.length;
+ handler_arg(h, arg, end);
+ }
+
return 0;
}
@@ -897,6 +997,16 @@ static __init int cxl_test_init(void)
if (rc)
goto err_gen_pool_add;
+ if (interleave_arithmetic == 1) {
+ cfmws_start = CFMWS_XOR_ARRAY_START;
+ cfmws_end = CFMWS_XOR_ARRAY_END;
+ dev_dbg(NULL, "cxl_test loading xor math option\n");
+ } else {
+ cfmws_start = CFMWS_MOD_ARRAY_START;
+ cfmws_end = CFMWS_MOD_ARRAY_END;
+ dev_dbg(NULL, "cxl_test loading modulo math option\n");
+ }
+
rc = populate_cedt();
if (rc)
goto err_populate;
@@ -1073,6 +1183,8 @@ static __exit void cxl_test_exit(void)
unregister_cxl_mock_ops(&cxl_mock_ops);
}
+module_param(interleave_arithmetic, int, 0000);
+MODULE_PARM_DESC(interleave_arithmetic, "Modulo:0, XOR:1");
module_init(cxl_test_init);
module_exit(cxl_test_exit);
MODULE_LICENSE("GPL v2");
--
2.37.3
^ permalink raw reply related [flat|nested] 8+ messages in thread
* Re: [PATCH v8 2/3] cxl/acpi: Support CXL XOR Interleave Math (CXIMS)
2022-11-22 22:52 ` [PATCH v8 2/3] cxl/acpi: Support CXL XOR Interleave Math (CXIMS) alison.schofield
@ 2022-11-30 18:14 ` Jonathan Cameron
2022-11-30 18:23 ` Jonathan Cameron
2022-11-30 22:51 ` Alison Schofield
0 siblings, 2 replies; 8+ messages in thread
From: Jonathan Cameron @ 2022-11-30 18:14 UTC (permalink / raw)
To: alison.schofield
Cc: Dan Williams, Ira Weiny, Vishal Verma, Ben Widawsky, Dave Jiang,
linux-cxl
On Tue, 22 Nov 2022 14:52:24 -0800
alison.schofield@intel.com wrote:
> From: Alison Schofield <alison.schofield@intel.com>
>
> When the CFMWS is using XOR math, parse the corresponding
> CXIMS structure and store the xormaps in the root decoder
> structure. Use the xormaps in a new lookup, cxl_hb_xor(),
> to find a targets entry in the host bridge interleave
> target list.
>
> Defined in CXL Specfication 3.0 Section: 9.17.1
>
> Signed-off-by: Alison Schofield <alison.schofield@intel.com>
I've been avoiding reading this because the xormap stuff gives me a headache..
Anyhow, finally looked at it properly and maths looks right to me.
A few queries and minor suggestions inline but nothing important.
With or without dragging the refactoring into here from your new patch series
(to avoid introducing code only to factor a chunk out a few patches later).
Reviewed-by: Jonathan Cameron <Jonathan.Cameron@huawei.com>
> ---
> drivers/cxl/acpi.c | 126 +++++++++++++++++++++++++++++++++++++++-
> drivers/cxl/core/port.c | 9 ++-
> drivers/cxl/cxl.h | 13 ++++-
> 3 files changed, 140 insertions(+), 8 deletions(-)
>
> diff --git a/drivers/cxl/acpi.c b/drivers/cxl/acpi.c
> index fb649683dd3a..98c84942ed37 100644
> --- a/drivers/cxl/acpi.c
> +++ b/drivers/cxl/acpi.c
> @@ -6,9 +6,107 @@
> #include <linux/kernel.h>
> #include <linux/acpi.h>
> #include <linux/pci.h>
> +#include <asm/div64.h>
> #include "cxlpci.h"
> #include "cxl.h"
>
> +struct cxl_cxims_data {
> + int nr_maps;
> + u64 xormaps[];
> +};
> +
> +/*
> + * Find a targets entry (n) in the host bridge interleave list.
> + * CXL Specfication 3.0 Table 9-22
> + */
> +static struct cxl_dport *cxl_hb_xor(struct cxl_root_decoder *cxlrd, int pos)
> +{
> + struct cxl_cxims_data *cximsd = cxlrd->platform_data;
> + struct cxl_switch_decoder *cxlsd = &cxlrd->cxlsd;
> + struct cxl_decoder *cxld = &cxlsd->cxld;
> + int ig = cxld->interleave_granularity;
> + int iw = cxld->interleave_ways;
> + int eiw, i = 0, n = 0;
> + u64 hpa;
> +
> + if (dev_WARN_ONCE(&cxld->dev,
> + cxld->interleave_ways != cxlsd->nr_targets,
> + "misconfigured root decoder\n"))
> + return NULL;
> +
> + if (iw == 1)
> + /* Entry is always 0 for no interleave */
> + return cxlrd->cxlsd.target[0];
> +
> + hpa = cxlrd->res->start + pos * ig;
> +
> + if (iw == 3)
> + goto no_map;
> +
> + /* IW: 2,4,6,8,12,16 begin building 'n' using xormaps */
> + for (i = 0; i < cximsd->nr_maps; i++)
> + n |= (hweight64(hpa & cximsd->xormaps[i]) & 1) << i;
> +
> +no_map:
> + /* IW: 3,6,12 add a modulo calculation to 'n' */
> + if (!is_power_of_2(iw)) {
> + eiw = ilog2(iw / 3) + 8;
Obviously duplicates some checks, but ways_to_cxl() still better here I think
because it documents that it's just the normal switch to eiw.
> + hpa &= GENMASK_ULL(51, eiw + ig);
> + n |= do_div(hpa, 3) << i;
Seeing as we haven't merged this set yet, maybe just factor this out from the
start rather than in your follow on set?
> + }
> + return cxlrd->cxlsd.target[n];
> +}
> +
> +struct cxl_cxims_context {
> + struct device *dev;
> + struct cxl_root_decoder *cxlrd;
> +};
> +
> +static int cxl_parse_cxims(union acpi_subtable_headers *header, void *arg,
> + const unsigned long end)
> +{
> + struct acpi_cedt_cxims *cxims = (struct acpi_cedt_cxims *)header;
> + struct cxl_cxims_context *ctx = arg;
> + struct cxl_root_decoder *cxlrd = ctx->cxlrd;
> + struct cxl_decoder *cxld = &cxlrd->cxlsd.cxld;
> + struct device *dev = ctx->dev;
> + struct cxl_cxims_data *cximsd;
> + unsigned int hbig, nr_maps;
> + int rc;
> +
> + rc = cxl_to_granularity(cxims->hbig, &hbig);
> + if (rc)
> + return rc;
> +
> + if (hbig == cxld->interleave_granularity) {
> + /* IW 1,3 do not use xormaps and skip this parsing entirely */
> +
> + if (is_power_of_2(cxld->interleave_ways))
> + /* 2, 4, 8, 16 way */
> + nr_maps = ilog2(cxld->interleave_ways);
> + else
> + /* 6, 12 way */
> + nr_maps = ilog2(cxld->interleave_ways / 3);
> +
> + if (cxims->nr_xormaps < nr_maps) {
Why is cxims->nr_xormaps > nr_maps not an error?
Whilst we are just going to drop the extra entries it certainly seems
like an oddity we should perhaps report?
> + dev_dbg(dev, "CXIMS nr_xormaps[%d] expected[%d]\n",
> + cxims->nr_xormaps, nr_maps);
> + return -ENXIO;
> + }
> +
> + cximsd = devm_kzalloc(dev,
> + struct_size(cximsd, xormaps, nr_maps),
> + GFP_KERNEL);
> + if (!cximsd)
> + return -ENOMEM;
Trivial, I'd like a blank line here after the error handler.
> + memcpy(cximsd->xormaps, cxims->xormap_list,
> + nr_maps * sizeof(*cximsd->xormaps));
> + cximsd->nr_maps = nr_maps;
> + cxlrd->platform_data = cximsd;
> + }
For local consistency and because it is nicer in general to have
returns separated by a blank line, put one here as well.
> + return 0;
> +}
> +
> diff --git a/drivers/cxl/cxl.h b/drivers/cxl/cxl.h
> index ac75554b5d76..d03aa1776fc8 100644
> --- a/drivers/cxl/cxl.h
> +++ b/drivers/cxl/cxl.h
> @@ -324,18 +324,24 @@ struct cxl_switch_decoder {
> struct cxl_dport *target[];
> };
>
> +struct cxl_root_decoder;
> +struct cxl_endpoint_decoder;
Looks like the cxl_endpoint_decoder is currently defined above this anyway so don't
think this forwards ref is needed.
> +typedef struct cxl_dport *(*cxl_calc_hb_fn)(struct cxl_root_decoder *cxlrd,
> + int pos);
>
> /**
> * struct cxl_root_decoder - Static platform CXL address decoder
> * @res: host / parent resource for region allocations
> * @region_id: region id for next region provisioning event
> * @calc_hb: which host bridge covers the n'th position by granularity
> + * @platform_data: platform specific configuration data
> * @cxlsd: base cxl switch decoder
> */
> struct cxl_root_decoder {
> struct resource *res;
> atomic_t region_id;
> - struct cxl_dport *(*calc_hb)(struct cxl_root_decoder *cxlrd, int pos);
> + cxl_calc_hb_fn calc_hb;
> + void *platform_data;
> struct cxl_switch_decoder cxlsd;
> };
>
> @@ -580,8 +586,11 @@ struct cxl_root_decoder *to_cxl_root_decoder(struct device *dev);
> struct cxl_endpoint_decoder *to_cxl_endpoint_decoder(struct device *dev);
> bool is_root_decoder(struct device *dev);
> bool is_endpoint_decoder(struct device *dev);
> +
trivial, but unrelated whitespace change shouldn't really be in here.
> struct cxl_root_decoder *cxl_root_decoder_alloc(struct cxl_port *port,
> - unsigned int nr_targets);
> + unsigned int nr_targets,
> + cxl_calc_hb_fn calc_hb);
> +struct cxl_dport *cxl_hb_modulo(struct cxl_root_decoder *cxlrd, int pos);
> struct cxl_switch_decoder *cxl_switch_decoder_alloc(struct cxl_port *port,
> unsigned int nr_targets);
> int cxl_decoder_add(struct cxl_decoder *cxld, int *target_map);
^ permalink raw reply [flat|nested] 8+ messages in thread
* Re: [PATCH v8 2/3] cxl/acpi: Support CXL XOR Interleave Math (CXIMS)
2022-11-30 18:14 ` Jonathan Cameron
@ 2022-11-30 18:23 ` Jonathan Cameron
2022-11-30 22:51 ` Alison Schofield
1 sibling, 0 replies; 8+ messages in thread
From: Jonathan Cameron @ 2022-11-30 18:23 UTC (permalink / raw)
To: alison.schofield
Cc: Dan Williams, Ira Weiny, Vishal Verma, Ben Widawsky, Dave Jiang,
linux-cxl
> > +static int cxl_parse_cxims(union acpi_subtable_headers *header, void *arg,
> > + const unsigned long end)
> > +{
> > + struct acpi_cedt_cxims *cxims = (struct acpi_cedt_cxims *)header;
> > + struct cxl_cxims_context *ctx = arg;
> > + struct cxl_root_decoder *cxlrd = ctx->cxlrd;
> > + struct cxl_decoder *cxld = &cxlrd->cxlsd.cxld;
> > + struct device *dev = ctx->dev;
> > + struct cxl_cxims_data *cximsd;
> > + unsigned int hbig, nr_maps;
> > + int rc;
> > +
> > + rc = cxl_to_granularity(cxims->hbig, &hbig);
> > + if (rc)
> > + return rc;
> > +
> > + if (hbig == cxld->interleave_granularity) {
> > + /* IW 1,3 do not use xormaps and skip this parsing entirely */
> > +
> > + if (is_power_of_2(cxld->interleave_ways))
> > + /* 2, 4, 8, 16 way */
> > + nr_maps = ilog2(cxld->interleave_ways);
> > + else
> > + /* 6, 12 way */
> > + nr_maps = ilog2(cxld->interleave_ways / 3);
> > +
> > + if (cxims->nr_xormaps < nr_maps) {
>
> Why is cxims->nr_xormaps > nr_maps not an error?
> Whilst we are just going to drop the extra entries it certainly seems
> like an oddity we should perhaps report?
Ah. I see from your example that a subset can be used so one cxims gets
used for different numbers of iw. I'd missed that detail but it is clear
we only have one of these for each HBIG.
^ permalink raw reply [flat|nested] 8+ messages in thread
* Re: [PATCH v8 3/3] tools/testing/cxl: Add XOR Math support to cxl_test
2022-11-22 22:52 ` [PATCH v8 3/3] tools/testing/cxl: Add XOR Math support to cxl_test alison.schofield
@ 2022-11-30 18:24 ` Jonathan Cameron
0 siblings, 0 replies; 8+ messages in thread
From: Jonathan Cameron @ 2022-11-30 18:24 UTC (permalink / raw)
To: alison.schofield
Cc: Dan Williams, Ira Weiny, Vishal Verma, Ben Widawsky, Dave Jiang,
linux-cxl
On Tue, 22 Nov 2022 14:52:25 -0800
alison.schofield@intel.com wrote:
> From: Alison Schofield <alison.schofield@intel.com>
>
> Expand the cxl_test topology to include CFMWS's that use XOR math
> for interleave arithmetic, as defined in the CXL Specification 3.0.
>
> With this expanded topology, cxl_test is useful for testing:
> x1,x2,x4 ways with XOR interleave arithmetic.
>
> Define the additional XOR CFMWS entries to appear only with the
> module parameter interleave_arithmetic=1. The cxl_test default
> continues to be modulo math.
>
> modprobe cxl_test interleave_arithmetic=1
>
> Signed-off-by: Alison Schofield <alison.schofield@intel.com>
Trivial comments inline, but looks good to me and you can tidy those
up if it makes sense to you.
Reviewed-by: Jonathan Cameron <Jonathan.Cameron@huawei.com>
> ---
> tools/testing/cxl/test/cxl.c | 118 ++++++++++++++++++++++++++++++++++-
> 1 file changed, 115 insertions(+), 3 deletions(-)
>
> diff --git a/tools/testing/cxl/test/cxl.c b/tools/testing/cxl/test/cxl.c
> index 7edce12fd2ce..97849e9753f5 100644
> --- a/tools/testing/cxl/test/cxl.c
> +++ b/tools/testing/cxl/test/cxl.c
> @@ -11,6 +11,8 @@
> #include <cxlmem.h>
> #include "mock.h"
>
> +static int interleave_arithmetic;
> +
> #define NR_CXL_HOST_BRIDGES 2
> #define NR_CXL_SINGLE_HOST 1
> #define NR_CXL_ROOT_PORTS 2
> @@ -122,6 +124,22 @@ static struct {
> struct acpi_cedt_cfmws cfmws;
> u32 target[1];
> } cfmws4;
> + struct {
> + struct acpi_cedt_cfmws cfmws;
> + u32 target[1];
> + } cfmws5;
> + struct {
> + struct acpi_cedt_cfmws cfmws;
> + u32 target[2];
> + } cfmws6;
> + struct {
> + struct acpi_cedt_cfmws cfmws;
> + u32 target[4];
> + } cfmws7;
> + struct {
> + struct acpi_cedt_cxims cxims;
> + u64 xormap_list[2];
> + } cxims0;
> } __packed mock_cedt = {
> .cedt = {
> .header = {
> @@ -229,14 +247,89 @@ static struct {
> },
> .target = { 2 },
> },
> + /* .cfmws5,6,7 use XOR Math (interleave_arithmetic == 1) */
> + .cfmws5 = {
> + .cfmws = {
> + .header = {
> + .type = ACPI_CEDT_TYPE_CFMWS,
> + .length = sizeof(mock_cedt.cfmws5),
> + },
> + .interleave_arithmetic = 1,
Can we either use the defines from patch 1 directly, or carry a local copy in this
file so naming matches up etc?
> + .interleave_ways = 0,
> + .granularity = 4,
> + .restrictions = ACPI_CEDT_CFMWS_RESTRICT_TYPE3 |
> + ACPI_CEDT_CFMWS_RESTRICT_PMEM,
> + .qtg_id = 0,
> + .window_size = SZ_256M * 8UL,
> + },
> + .target = { 0 },
consistency of trailing ,
Don't mind which but nice to do it the same here...
> + },
> + .cfmws6 = {
> + .cfmws = {
> + .header = {
> + .type = ACPI_CEDT_TYPE_CFMWS,
> + .length = sizeof(mock_cedt.cfmws6),
> + },
> + .interleave_arithmetic = 1,
> + .interleave_ways = 1,
> + .granularity = 0,
> + .restrictions = ACPI_CEDT_CFMWS_RESTRICT_TYPE3 |
> + ACPI_CEDT_CFMWS_RESTRICT_PMEM,
> + .qtg_id = 1,
> + .window_size = SZ_256M * 8UL,
> + },
> + .target = { 0, 1, },
and here.
> + },
> + .cfmws7 = {
> + .cfmws = {
> + .header = {
> + .type = ACPI_CEDT_TYPE_CFMWS,
> + .length = sizeof(mock_cedt.cfmws7),
> + },
> + .interleave_arithmetic = 1,
> + .interleave_ways = 2,
> + .granularity = 0,
> + .restrictions = ACPI_CEDT_CFMWS_RESTRICT_TYPE3 |
> + ACPI_CEDT_CFMWS_RESTRICT_PMEM,
> + .qtg_id = 0,
> + .window_size = SZ_256M * 16UL,
> + },
> + .target = { 0, 1, 0, 1, },
> + },
> + .cxims0 = {
> + .cxims = {
> + .header = {
> + .type = ACPI_CEDT_TYPE_CXIMS,
> + .length = sizeof(mock_cedt.cxims0),
> + },
> + .hbig = 0,
> + .nr_xormaps = 2,
> + },
> + .xormap_list = { 0x404100, 0x808200 },
> + },
> };
>
> -struct acpi_cedt_cfmws *mock_cfmws[] = {
> +struct acpi_cedt_cfmws *mock_cfmws[8] = {
> [0] = &mock_cedt.cfmws0.cfmws,
> [1] = &mock_cedt.cfmws1.cfmws,
> [2] = &mock_cedt.cfmws2.cfmws,
> [3] = &mock_cedt.cfmws3.cfmws,
> [4] = &mock_cedt.cfmws4.cfmws,
> + /* Modulo Math above, XOR Math below */
> + [5] = &mock_cedt.cfmws5.cfmws,
> + [6] = &mock_cedt.cfmws6.cfmws,
> + [7] = &mock_cedt.cfmws7.cfmws,
> +};
> +
> +static int cfmws_start;
> +static int cfmws_end;
> +#define CFMWS_MOD_ARRAY_START 0
> +#define CFMWS_MOD_ARRAY_END 4
> +#define CFMWS_XOR_ARRAY_START 5
> +#define CFMWS_XOR_ARRAY_END 7
> +
> +struct acpi_cedt_cxims *mock_cxims[1] = {
> + [0] = &mock_cedt.cxims0.cxims,
> };
>
> struct cxl_mock_res {
> @@ -308,7 +401,7 @@ static int populate_cedt(void)
> chbs->length = size;
> }
>
> - for (i = 0; i < ARRAY_SIZE(mock_cfmws); i++) {
> + for (i = cfmws_start; i <= cfmws_end; i++) {
> struct acpi_cedt_cfmws *window = mock_cfmws[i];
>
> res = alloc_mock_res(window->window_size);
> @@ -351,12 +444,19 @@ static int mock_acpi_table_parse_cedt(enum acpi_cedt_type id,
> }
>
> if (id == ACPI_CEDT_TYPE_CFMWS)
> - for (i = 0; i < ARRAY_SIZE(mock_cfmws); i++) {
> + for (i = cfmws_start; i <= cfmws_end; i++) {
> h = (union acpi_subtable_headers *) mock_cfmws[i];
> end = (unsigned long) 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 = (unsigned long)h + mock_cxims[i]->header.length;
> + handler_arg(h, arg, end);
> + }
> +
> return 0;
> }
>
> @@ -897,6 +997,16 @@ static __init int cxl_test_init(void)
> if (rc)
> goto err_gen_pool_add;
>
> + if (interleave_arithmetic == 1) {
> + cfmws_start = CFMWS_XOR_ARRAY_START;
> + cfmws_end = CFMWS_XOR_ARRAY_END;
> + dev_dbg(NULL, "cxl_test loading xor math option\n");
> + } else {
> + cfmws_start = CFMWS_MOD_ARRAY_START;
> + cfmws_end = CFMWS_MOD_ARRAY_END;
> + dev_dbg(NULL, "cxl_test loading modulo math option\n");
> + }
> +
> rc = populate_cedt();
> if (rc)
> goto err_populate;
> @@ -1073,6 +1183,8 @@ static __exit void cxl_test_exit(void)
> unregister_cxl_mock_ops(&cxl_mock_ops);
> }
>
> +module_param(interleave_arithmetic, int, 0000);
> +MODULE_PARM_DESC(interleave_arithmetic, "Modulo:0, XOR:1");
> module_init(cxl_test_init);
> module_exit(cxl_test_exit);
> MODULE_LICENSE("GPL v2");
^ permalink raw reply [flat|nested] 8+ messages in thread
* Re: [PATCH v8 2/3] cxl/acpi: Support CXL XOR Interleave Math (CXIMS)
2022-11-30 18:14 ` Jonathan Cameron
2022-11-30 18:23 ` Jonathan Cameron
@ 2022-11-30 22:51 ` Alison Schofield
1 sibling, 0 replies; 8+ messages in thread
From: Alison Schofield @ 2022-11-30 22:51 UTC (permalink / raw)
To: Jonathan Cameron
Cc: Dan Williams, Ira Weiny, Vishal Verma, Ben Widawsky, Dave Jiang,
linux-cxl
On Wed, Nov 30, 2022 at 06:14:36PM +0000, Jonathan Cameron wrote:
> On Tue, 22 Nov 2022 14:52:24 -0800
> alison.schofield@intel.com wrote:
>
> > From: Alison Schofield <alison.schofield@intel.com>
> >
> > When the CFMWS is using XOR math, parse the corresponding
> > CXIMS structure and store the xormaps in the root decoder
> > structure. Use the xormaps in a new lookup, cxl_hb_xor(),
> > to find a targets entry in the host bridge interleave
> > target list.
> >
> > Defined in CXL Specfication 3.0 Section: 9.17.1
> >
> > Signed-off-by: Alison Schofield <alison.schofield@intel.com>
>
> I've been avoiding reading this because the xormap stuff gives me a headache..
> Anyhow, finally looked at it properly and maths looks right to me.
> A few queries and minor suggestions inline but nothing important.
>
> With or without dragging the refactoring into here from your new patch series
> (to avoid introducing code only to factor a chunk out a few patches later).
>
> Reviewed-by: Jonathan Cameron <Jonathan.Cameron@huawei.com>
Thanks for the review Jonathan.
I did pull that little refactor fwd to this patch, even though I think
this patch may precede that address translation work for a while.
Pulling that calc out to the separate function just looked better!
I hope it flies.
I tidy'd up per your suggestions. I chose 'trailing' commas because
one should always expect more. (and there wasn't a clear precedence
in the file)
Alison
>
> > ---
> > drivers/cxl/acpi.c | 126 +++++++++++++++++++++++++++++++++++++++-
> > drivers/cxl/core/port.c | 9 ++-
> > drivers/cxl/cxl.h | 13 ++++-
> > 3 files changed, 140 insertions(+), 8 deletions(-)
> >
> > diff --git a/drivers/cxl/acpi.c b/drivers/cxl/acpi.c
> > index fb649683dd3a..98c84942ed37 100644
> > --- a/drivers/cxl/acpi.c
> > +++ b/drivers/cxl/acpi.c
> > @@ -6,9 +6,107 @@
> > #include <linux/kernel.h>
> > #include <linux/acpi.h>
> > #include <linux/pci.h>
> > +#include <asm/div64.h>
> > #include "cxlpci.h"
> > #include "cxl.h"
> >
> > +struct cxl_cxims_data {
> > + int nr_maps;
> > + u64 xormaps[];
> > +};
> > +
> > +/*
> > + * Find a targets entry (n) in the host bridge interleave list.
> > + * CXL Specfication 3.0 Table 9-22
> > + */
> > +static struct cxl_dport *cxl_hb_xor(struct cxl_root_decoder *cxlrd, int pos)
> > +{
> > + struct cxl_cxims_data *cximsd = cxlrd->platform_data;
> > + struct cxl_switch_decoder *cxlsd = &cxlrd->cxlsd;
> > + struct cxl_decoder *cxld = &cxlsd->cxld;
> > + int ig = cxld->interleave_granularity;
> > + int iw = cxld->interleave_ways;
> > + int eiw, i = 0, n = 0;
> > + u64 hpa;
> > +
> > + if (dev_WARN_ONCE(&cxld->dev,
> > + cxld->interleave_ways != cxlsd->nr_targets,
> > + "misconfigured root decoder\n"))
> > + return NULL;
> > +
> > + if (iw == 1)
> > + /* Entry is always 0 for no interleave */
> > + return cxlrd->cxlsd.target[0];
> > +
> > + hpa = cxlrd->res->start + pos * ig;
> > +
> > + if (iw == 3)
> > + goto no_map;
> > +
> > + /* IW: 2,4,6,8,12,16 begin building 'n' using xormaps */
> > + for (i = 0; i < cximsd->nr_maps; i++)
> > + n |= (hweight64(hpa & cximsd->xormaps[i]) & 1) << i;
>
> > +
> > +no_map:
> > + /* IW: 3,6,12 add a modulo calculation to 'n' */
> > + if (!is_power_of_2(iw)) {
> > + eiw = ilog2(iw / 3) + 8;
>
> Obviously duplicates some checks, but ways_to_cxl() still better here I think
> because it documents that it's just the normal switch to eiw.
>
> > + hpa &= GENMASK_ULL(51, eiw + ig);
> > + n |= do_div(hpa, 3) << i;
>
> Seeing as we haven't merged this set yet, maybe just factor this out from the
> start rather than in your follow on set?
>
> > + }
> > + return cxlrd->cxlsd.target[n];
> > +}
> > +
> > +struct cxl_cxims_context {
> > + struct device *dev;
> > + struct cxl_root_decoder *cxlrd;
> > +};
> > +
> > +static int cxl_parse_cxims(union acpi_subtable_headers *header, void *arg,
> > + const unsigned long end)
> > +{
> > + struct acpi_cedt_cxims *cxims = (struct acpi_cedt_cxims *)header;
> > + struct cxl_cxims_context *ctx = arg;
> > + struct cxl_root_decoder *cxlrd = ctx->cxlrd;
> > + struct cxl_decoder *cxld = &cxlrd->cxlsd.cxld;
> > + struct device *dev = ctx->dev;
> > + struct cxl_cxims_data *cximsd;
> > + unsigned int hbig, nr_maps;
> > + int rc;
> > +
> > + rc = cxl_to_granularity(cxims->hbig, &hbig);
> > + if (rc)
> > + return rc;
> > +
> > + if (hbig == cxld->interleave_granularity) {
> > + /* IW 1,3 do not use xormaps and skip this parsing entirely */
> > +
> > + if (is_power_of_2(cxld->interleave_ways))
> > + /* 2, 4, 8, 16 way */
> > + nr_maps = ilog2(cxld->interleave_ways);
> > + else
> > + /* 6, 12 way */
> > + nr_maps = ilog2(cxld->interleave_ways / 3);
> > +
> > + if (cxims->nr_xormaps < nr_maps) {
>
> Why is cxims->nr_xormaps > nr_maps not an error?
> Whilst we are just going to drop the extra entries it certainly seems
> like an oddity we should perhaps report?
>
> > + dev_dbg(dev, "CXIMS nr_xormaps[%d] expected[%d]\n",
> > + cxims->nr_xormaps, nr_maps);
> > + return -ENXIO;
> > + }
> > +
> > + cximsd = devm_kzalloc(dev,
> > + struct_size(cximsd, xormaps, nr_maps),
> > + GFP_KERNEL);
> > + if (!cximsd)
> > + return -ENOMEM;
>
> Trivial, I'd like a blank line here after the error handler.
>
> > + memcpy(cximsd->xormaps, cxims->xormap_list,
> > + nr_maps * sizeof(*cximsd->xormaps));
> > + cximsd->nr_maps = nr_maps;
> > + cxlrd->platform_data = cximsd;
> > + }
>
> For local consistency and because it is nicer in general to have
> returns separated by a blank line, put one here as well.
>
> > + return 0;
> > +}
> > +
>
>
> > diff --git a/drivers/cxl/cxl.h b/drivers/cxl/cxl.h
> > index ac75554b5d76..d03aa1776fc8 100644
> > --- a/drivers/cxl/cxl.h
> > +++ b/drivers/cxl/cxl.h
> > @@ -324,18 +324,24 @@ struct cxl_switch_decoder {
> > struct cxl_dport *target[];
> > };
> >
> > +struct cxl_root_decoder;
> > +struct cxl_endpoint_decoder;
>
> Looks like the cxl_endpoint_decoder is currently defined above this anyway so don't
> think this forwards ref is needed.
>
> > +typedef struct cxl_dport *(*cxl_calc_hb_fn)(struct cxl_root_decoder *cxlrd,
> > + int pos);
> >
> > /**
> > * struct cxl_root_decoder - Static platform CXL address decoder
> > * @res: host / parent resource for region allocations
> > * @region_id: region id for next region provisioning event
> > * @calc_hb: which host bridge covers the n'th position by granularity
> > + * @platform_data: platform specific configuration data
> > * @cxlsd: base cxl switch decoder
> > */
> > struct cxl_root_decoder {
> > struct resource *res;
> > atomic_t region_id;
> > - struct cxl_dport *(*calc_hb)(struct cxl_root_decoder *cxlrd, int pos);
> > + cxl_calc_hb_fn calc_hb;
> > + void *platform_data;
> > struct cxl_switch_decoder cxlsd;
> > };
> >
> > @@ -580,8 +586,11 @@ struct cxl_root_decoder *to_cxl_root_decoder(struct device *dev);
> > struct cxl_endpoint_decoder *to_cxl_endpoint_decoder(struct device *dev);
> > bool is_root_decoder(struct device *dev);
> > bool is_endpoint_decoder(struct device *dev);
> > +
>
> trivial, but unrelated whitespace change shouldn't really be in here.
>
> > struct cxl_root_decoder *cxl_root_decoder_alloc(struct cxl_port *port,
> > - unsigned int nr_targets);
> > + unsigned int nr_targets,
> > + cxl_calc_hb_fn calc_hb);
> > +struct cxl_dport *cxl_hb_modulo(struct cxl_root_decoder *cxlrd, int pos);
> > struct cxl_switch_decoder *cxl_switch_decoder_alloc(struct cxl_port *port,
> > unsigned int nr_targets);
> > int cxl_decoder_add(struct cxl_decoder *cxld, int *target_map);
>
^ permalink raw reply [flat|nested] 8+ messages in thread
end of thread, other threads:[~2022-11-30 22:51 UTC | newest]
Thread overview: 8+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2022-11-22 22:52 [PATCH v8 0/3] CXL XOR Interleave Arithmetic alison.schofield
2022-11-22 22:52 ` [PATCH v8 1/3] ACPICA commit 2d8dc0383d3c908389053afbdc329bbd52f009ce alison.schofield
2022-11-22 22:52 ` [PATCH v8 2/3] cxl/acpi: Support CXL XOR Interleave Math (CXIMS) alison.schofield
2022-11-30 18:14 ` Jonathan Cameron
2022-11-30 18:23 ` Jonathan Cameron
2022-11-30 22:51 ` Alison Schofield
2022-11-22 22:52 ` [PATCH v8 3/3] tools/testing/cxl: Add XOR Math support to cxl_test alison.schofield
2022-11-30 18:24 ` Jonathan Cameron
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox