* [PATCH v2 1/3] cxl: support Type2 when initializing cxl_dev_state
2026-02-25 12:14 [PATCH v2 0/3] type2 support preparation alejandro.lucero-palau
@ 2026-02-25 12:14 ` alejandro.lucero-palau
2026-02-25 15:43 ` Gregory Price
2026-02-27 12:14 ` Jonathan Cameron
2026-02-25 12:14 ` [PATCH v2 2/3] cxl: export internal structs for external Type2 drivers alejandro.lucero-palau
2026-02-25 12:14 ` [PATCH v2 3/3] cxl: Move pci generic code alejandro.lucero-palau
2 siblings, 2 replies; 16+ messages in thread
From: alejandro.lucero-palau @ 2026-02-25 12:14 UTC (permalink / raw)
To: linux-cxl, dan.j.williams, dave.jiang; +Cc: Alejandro Lucero, Alison Schofield
From: Alejandro Lucero <alucerop@amd.com>
In preparation for type2 drivers add function and macro for
differentiating CXL memory expanders (type 3) from CXL device
accelerators (type 2) helping accel drivers to embed cxl_dev_state
inside a private struct.
Update type3 driver for using this same initialization.
Signed-off-by: Alejandro Lucero <alucerop@amd.com>
Reviewed-by: Dave Jiang <dave.jiang@intel.com>
Reviewed-by: Alison Schofield <alison.schofield@intel.com>
---
drivers/cxl/core/mbox.c | 12 +++++-------
drivers/cxl/core/memdev.c | 24 ++++++++++++++++++++++++
drivers/cxl/cxlmem.h | 34 +++++++++++++++++++++++++++++++++-
drivers/cxl/pci.c | 14 +++++++-------
tools/testing/cxl/test/mem.c | 3 +--
5 files changed, 70 insertions(+), 17 deletions(-)
diff --git a/drivers/cxl/core/mbox.c b/drivers/cxl/core/mbox.c
index fa6dd0c94656..bee84d0101d1 100644
--- a/drivers/cxl/core/mbox.c
+++ b/drivers/cxl/core/mbox.c
@@ -1514,23 +1514,21 @@ int cxl_mailbox_init(struct cxl_mailbox *cxl_mbox, struct device *host)
}
EXPORT_SYMBOL_NS_GPL(cxl_mailbox_init, "CXL");
-struct cxl_memdev_state *cxl_memdev_state_create(struct device *dev)
+struct cxl_memdev_state *cxl_memdev_state_create(struct device *dev, u64 serial,
+ u16 dvsec)
{
struct cxl_memdev_state *mds;
int rc;
- mds = devm_kzalloc(dev, sizeof(*mds), GFP_KERNEL);
+ mds = devm_cxl_dev_state_create(dev, CXL_DEVTYPE_CLASSMEM, serial,
+ dvsec, struct cxl_memdev_state, cxlds,
+ true);
if (!mds) {
dev_err(dev, "No memory available\n");
return ERR_PTR(-ENOMEM);
}
mutex_init(&mds->event.log_lock);
- mds->cxlds.dev = dev;
- mds->cxlds.reg_map.host = dev;
- mds->cxlds.cxl_mbox.host = dev;
- mds->cxlds.reg_map.resource = CXL_RESOURCE_NONE;
- mds->cxlds.type = CXL_DEVTYPE_CLASSMEM;
rc = devm_cxl_register_mce_notifier(dev, &mds->mce_notifier);
if (rc == -EOPNOTSUPP)
diff --git a/drivers/cxl/core/memdev.c b/drivers/cxl/core/memdev.c
index f547d8ac34c7..5b4988870b74 100644
--- a/drivers/cxl/core/memdev.c
+++ b/drivers/cxl/core/memdev.c
@@ -656,6 +656,30 @@ static void detach_memdev(struct work_struct *work)
static struct lock_class_key cxl_memdev_key;
+struct cxl_dev_state *_devm_cxl_dev_state_create(struct device *dev,
+ enum cxl_devtype type,
+ u64 serial, u16 dvsec,
+ size_t size, bool has_mbox)
+{
+ struct cxl_dev_state *cxlds = devm_kzalloc(dev, size, GFP_KERNEL);
+
+ if (!cxlds)
+ return NULL;
+
+ cxlds->dev = dev;
+ cxlds->type = type;
+ cxlds->serial = serial;
+ cxlds->cxl_dvsec = dvsec;
+ cxlds->reg_map.host = dev;
+ cxlds->reg_map.resource = CXL_RESOURCE_NONE;
+
+ if (has_mbox)
+ cxlds->cxl_mbox.host = dev;
+
+ return cxlds;
+}
+EXPORT_SYMBOL_NS_GPL(_devm_cxl_dev_state_create, "CXL");
+
static struct cxl_memdev *cxl_memdev_alloc(struct cxl_dev_state *cxlds,
const struct file_operations *fops,
const struct cxl_memdev_attach *attach)
diff --git a/drivers/cxl/cxlmem.h b/drivers/cxl/cxlmem.h
index e21d744d639b..9daf4bc42692 100644
--- a/drivers/cxl/cxlmem.h
+++ b/drivers/cxl/cxlmem.h
@@ -523,6 +523,37 @@ to_cxl_memdev_state(struct cxl_dev_state *cxlds)
return container_of(cxlds, struct cxl_memdev_state, cxlds);
}
+struct cxl_dev_state *_devm_cxl_dev_state_create(struct device *dev,
+ enum cxl_devtype type,
+ u64 serial, u16 dvsec,
+ size_t size, bool has_mbox);
+
+/**
+ * cxl_dev_state_create - safely create and cast a cxl dev state embedded in a
+ * driver specific struct.
+ *
+ * @parent: device behind the request
+ * @type: CXL device type
+ * @serial: device identification
+ * @dvsec: dvsec capability offset
+ * @drv_struct: driver struct embedding a cxl_dev_state struct
+ * @member: drv_struct member as cxl_dev_state
+ * @mbox: true if mailbox supported
+ *
+ * Returns a pointer to the drv_struct allocated and embedding a cxl_dev_state
+ * struct initialized.
+ *
+ * Introduced for Type2 driver support.
+ */
+#define devm_cxl_dev_state_create(parent, type, serial, dvsec, drv_struct, member, mbox) \
+ ({ \
+ static_assert(__same_type(struct cxl_dev_state, \
+ ((drv_struct *)NULL)->member)); \
+ static_assert(offsetof(drv_struct, member) == 0); \
+ (drv_struct *)_devm_cxl_dev_state_create(parent, type, serial, dvsec, \
+ sizeof(drv_struct), mbox); \
+ })
+
enum cxl_opcode {
CXL_MBOX_OP_INVALID = 0x0000,
CXL_MBOX_OP_RAW = CXL_MBOX_OP_INVALID,
@@ -858,7 +889,8 @@ int cxl_dev_state_identify(struct cxl_memdev_state *mds);
int cxl_await_media_ready(struct cxl_dev_state *cxlds);
int cxl_enumerate_cmds(struct cxl_memdev_state *mds);
int cxl_mem_dpa_fetch(struct cxl_memdev_state *mds, struct cxl_dpa_info *info);
-struct cxl_memdev_state *cxl_memdev_state_create(struct device *dev);
+struct cxl_memdev_state *cxl_memdev_state_create(struct device *dev, u64 serial,
+ u16 dvsec);
void set_exclusive_cxl_commands(struct cxl_memdev_state *mds,
unsigned long *cmds);
void clear_exclusive_cxl_commands(struct cxl_memdev_state *mds,
diff --git a/drivers/cxl/pci.c b/drivers/cxl/pci.c
index fbb300a01830..a42f273ff72b 100644
--- a/drivers/cxl/pci.c
+++ b/drivers/cxl/pci.c
@@ -865,25 +865,25 @@ static int cxl_pci_probe(struct pci_dev *pdev, const struct pci_device_id *id)
int rc, pmu_count;
unsigned int i;
bool irq_avail;
+ u16 dvsec;
rc = pcim_enable_device(pdev);
if (rc)
return rc;
pci_set_master(pdev);
- mds = cxl_memdev_state_create(&pdev->dev);
+ dvsec = pci_find_dvsec_capability(pdev, PCI_VENDOR_ID_CXL,
+ PCI_DVSEC_CXL_DEVICE);
+ if (!dvsec)
+ pci_warn(pdev, "Device DVSEC not present, skip CXL.mem init\n");
+
+ mds = cxl_memdev_state_create(&pdev->dev, pci_get_dsn(pdev), dvsec);
if (IS_ERR(mds))
return PTR_ERR(mds);
cxlds = &mds->cxlds;
pci_set_drvdata(pdev, cxlds);
cxlds->rcd = is_cxl_restricted(pdev);
- cxlds->serial = pci_get_dsn(pdev);
- cxlds->cxl_dvsec = pci_find_dvsec_capability(
- pdev, PCI_VENDOR_ID_CXL, PCI_DVSEC_CXL_DEVICE);
- if (!cxlds->cxl_dvsec)
- dev_warn(&pdev->dev,
- "Device DVSEC not present, skip CXL.mem init\n");
rc = cxl_pci_setup_regs(pdev, CXL_REGLOC_RBI_MEMDEV, &map);
if (rc)
diff --git a/tools/testing/cxl/test/mem.c b/tools/testing/cxl/test/mem.c
index cb87e8c0e63c..79f42f4474d4 100644
--- a/tools/testing/cxl/test/mem.c
+++ b/tools/testing/cxl/test/mem.c
@@ -1716,7 +1716,7 @@ static int cxl_mock_mem_probe(struct platform_device *pdev)
if (rc)
return rc;
- mds = cxl_memdev_state_create(dev);
+ mds = cxl_memdev_state_create(dev, pdev->id + 1, 0);
if (IS_ERR(mds))
return PTR_ERR(mds);
@@ -1732,7 +1732,6 @@ static int cxl_mock_mem_probe(struct platform_device *pdev)
mds->event.buf = (struct cxl_get_event_payload *) mdata->event_buf;
INIT_DELAYED_WORK(&mds->security.poll_dwork, cxl_mockmem_sanitize_work);
- cxlds->serial = pdev->id + 1;
if (is_rcd(pdev))
cxlds->rcd = true;
--
2.34.1
^ permalink raw reply related [flat|nested] 16+ messages in thread* Re: [PATCH v2 1/3] cxl: support Type2 when initializing cxl_dev_state
2026-02-25 12:14 ` [PATCH v2 1/3] cxl: support Type2 when initializing cxl_dev_state alejandro.lucero-palau
@ 2026-02-25 15:43 ` Gregory Price
2026-02-27 19:54 ` Alejandro Lucero Palau
2026-02-27 12:14 ` Jonathan Cameron
1 sibling, 1 reply; 16+ messages in thread
From: Gregory Price @ 2026-02-25 15:43 UTC (permalink / raw)
To: alejandro.lucero-palau
Cc: linux-cxl, dan.j.williams, dave.jiang, Alejandro Lucero,
Alison Schofield
On Wed, Feb 25, 2026 at 12:14:28PM +0000, alejandro.lucero-palau@amd.com wrote:
> From: Alejandro Lucero <alucerop@amd.com>
>
Just some nits
Reviewed-by: Gregory Price <gourry@gourry.net>
> In preparation for type2 drivers add function and macro for
> differentiating CXL memory expanders (type 3) from CXL device
> accelerators (type 2) helping accel drivers to embed cxl_dev_state
> inside a private struct.
>
> Update type3 driver for using this same initialization.
>
I think this generalizes to just
helping drivers built from public headers to embed
cxl_dev_state inside a private struct.
Obviously the immediate use-case is type2.
... snip ...
> +/**
> + * cxl_dev_state_create - safely create and cast a cxl dev state embedded in a
> + * driver specific struct.
... snip ...
> + * Introduced for Type2 driver support.
^^^ I don't think this comment is needed
~Gregory
^ permalink raw reply [flat|nested] 16+ messages in thread* Re: [PATCH v2 1/3] cxl: support Type2 when initializing cxl_dev_state
2026-02-25 15:43 ` Gregory Price
@ 2026-02-27 19:54 ` Alejandro Lucero Palau
0 siblings, 0 replies; 16+ messages in thread
From: Alejandro Lucero Palau @ 2026-02-27 19:54 UTC (permalink / raw)
To: Gregory Price, alejandro.lucero-palau
Cc: linux-cxl, dan.j.williams, dave.jiang, Alison Schofield
On 2/25/26 15:43, Gregory Price wrote:
> On Wed, Feb 25, 2026 at 12:14:28PM +0000, alejandro.lucero-palau@amd.com wrote:
>> From: Alejandro Lucero <alucerop@amd.com>
>>
> Just some nits
>
> Reviewed-by: Gregory Price <gourry@gourry.net>
>
>> In preparation for type2 drivers add function and macro for
>> differentiating CXL memory expanders (type 3) from CXL device
>> accelerators (type 2) helping accel drivers to embed cxl_dev_state
>> inside a private struct.
>>
>> Update type3 driver for using this same initialization.
>>
> I think this generalizes to just
>
> helping drivers built from public headers to embed
> cxl_dev_state inside a private struct.
OK.
> Obviously the immediate use-case is type2.
>
> ... snip ...
>
>> +/**
>> + * cxl_dev_state_create - safely create and cast a cxl dev state embedded in a
>> + * driver specific struct.
> ... snip ...
>
>> + * Introduced for Type2 driver support.
> ^^^ I don't think this comment is needed
I will drop it.
Thanks!
>
> ~Gregory
^ permalink raw reply [flat|nested] 16+ messages in thread
* Re: [PATCH v2 1/3] cxl: support Type2 when initializing cxl_dev_state
2026-02-25 12:14 ` [PATCH v2 1/3] cxl: support Type2 when initializing cxl_dev_state alejandro.lucero-palau
2026-02-25 15:43 ` Gregory Price
@ 2026-02-27 12:14 ` Jonathan Cameron
2026-02-27 20:00 ` Alejandro Lucero Palau
1 sibling, 1 reply; 16+ messages in thread
From: Jonathan Cameron @ 2026-02-27 12:14 UTC (permalink / raw)
To: alejandro.lucero-palau
Cc: linux-cxl, dan.j.williams, dave.jiang, Alejandro Lucero,
Alison Schofield
On Wed, 25 Feb 2026 12:14:28 +0000
alejandro.lucero-palau@amd.com wrote:
> From: Alejandro Lucero <alucerop@amd.com>
>
> In preparation for type2 drivers add function and macro for
> differentiating CXL memory expanders (type 3) from CXL device
> accelerators (type 2) helping accel drivers to embed cxl_dev_state
Slight preference for
"to embed struct cxl_dev_state"
> inside a private struct.
I'd be tempted to call this "a driver specific structure".
private is a little too much of a guide to how this 'might' be used
in the long run.
>
> Update type3 driver for using this same initialization.
>
> Signed-off-by: Alejandro Lucero <alucerop@amd.com>
> Reviewed-by: Dave Jiang <dave.jiang@intel.com>
> Reviewed-by: Alison Schofield <alison.schofield@intel.com>
One minor wording comment below.
Reviewed-by: Jonathan Cameron <jonathan.cameron@huawei.com>
> diff --git a/drivers/cxl/cxlmem.h b/drivers/cxl/cxlmem.h
> index e21d744d639b..9daf4bc42692 100644
> --- a/drivers/cxl/cxlmem.h
> +++ b/drivers/cxl/cxlmem.h
> @@ -523,6 +523,37 @@ to_cxl_memdev_state(struct cxl_dev_state *cxlds)
> return container_of(cxlds, struct cxl_memdev_state, cxlds);
> }
>
> +struct cxl_dev_state *_devm_cxl_dev_state_create(struct device *dev,
> + enum cxl_devtype type,
> + u64 serial, u16 dvsec,
> + size_t size, bool has_mbox);
> +
> +/**
> + * cxl_dev_state_create - safely create and cast a cxl dev state embedded in a
> + * driver specific struct.
> + *
> + * @parent: device behind the request
> + * @type: CXL device type
> + * @serial: device identification
> + * @dvsec: dvsec capability offset
> + * @drv_struct: driver struct embedding a cxl_dev_state struct
> + * @member: drv_struct member as cxl_dev_state
* @member: name of the struct cxl_dev_state member in drv_struct
("as" to me implies a cast, which had me briefly confused).
> + * @mbox: true if mailbox supported
> + *
> + * Returns a pointer to the drv_struct allocated and embedding a cxl_dev_state
> + * struct initialized.
> + *
> + * Introduced for Type2 driver support.
> + */
> +#define devm_cxl_dev_state_create(parent, type, serial, dvsec, drv_struct, member, mbox) \
> + ({ \
> + static_assert(__same_type(struct cxl_dev_state, \
> + ((drv_struct *)NULL)->member)); \
> + static_assert(offsetof(drv_struct, member) == 0); \
> + (drv_struct *)_devm_cxl_dev_state_create(parent, type, serial, dvsec, \
> + sizeof(drv_struct), mbox); \
> + })
> +
^ permalink raw reply [flat|nested] 16+ messages in thread* Re: [PATCH v2 1/3] cxl: support Type2 when initializing cxl_dev_state
2026-02-27 12:14 ` Jonathan Cameron
@ 2026-02-27 20:00 ` Alejandro Lucero Palau
0 siblings, 0 replies; 16+ messages in thread
From: Alejandro Lucero Palau @ 2026-02-27 20:00 UTC (permalink / raw)
To: Jonathan Cameron, alejandro.lucero-palau
Cc: linux-cxl, dan.j.williams, dave.jiang, Alison Schofield
On 2/27/26 12:14, Jonathan Cameron wrote:
> On Wed, 25 Feb 2026 12:14:28 +0000
> alejandro.lucero-palau@amd.com wrote:
>
>> From: Alejandro Lucero <alucerop@amd.com>
>>
>> In preparation for type2 drivers add function and macro for
>> differentiating CXL memory expanders (type 3) from CXL device
>> accelerators (type 2) helping accel drivers to embed cxl_dev_state
> Slight preference for
>
> "to embed struct cxl_dev_state"
Right.
>> inside a private struct.
> I'd be tempted to call this "a driver specific structure".
>
> private is a little too much of a guide to how this 'might' be used
> in the long run.
I'll change it.
>
>> Update type3 driver for using this same initialization.
>>
>> Signed-off-by: Alejandro Lucero <alucerop@amd.com>
>> Reviewed-by: Dave Jiang <dave.jiang@intel.com>
>> Reviewed-by: Alison Schofield <alison.schofield@intel.com>
> One minor wording comment below.
>
> Reviewed-by: Jonathan Cameron <jonathan.cameron@huawei.com>
>
>> diff --git a/drivers/cxl/cxlmem.h b/drivers/cxl/cxlmem.h
>> index e21d744d639b..9daf4bc42692 100644
>> --- a/drivers/cxl/cxlmem.h
>> +++ b/drivers/cxl/cxlmem.h
>> @@ -523,6 +523,37 @@ to_cxl_memdev_state(struct cxl_dev_state *cxlds)
>> return container_of(cxlds, struct cxl_memdev_state, cxlds);
>> }
>>
>> +struct cxl_dev_state *_devm_cxl_dev_state_create(struct device *dev,
>> + enum cxl_devtype type,
>> + u64 serial, u16 dvsec,
>> + size_t size, bool has_mbox);
>> +
>> +/**
>> + * cxl_dev_state_create - safely create and cast a cxl dev state embedded in a
>> + * driver specific struct.
>> + *
>> + * @parent: device behind the request
>> + * @type: CXL device type
>> + * @serial: device identification
>> + * @dvsec: dvsec capability offset
>> + * @drv_struct: driver struct embedding a cxl_dev_state struct
>> + * @member: drv_struct member as cxl_dev_state
> * @member: name of the struct cxl_dev_state member in drv_struct
>
> ("as" to me implies a cast, which had me briefly confused).
yes, that seems better.
Thank you!
>
>> + * @mbox: true if mailbox supported
>> + *
>> + * Returns a pointer to the drv_struct allocated and embedding a cxl_dev_state
>> + * struct initialized.
>> + *
>> + * Introduced for Type2 driver support.
>> + */
>> +#define devm_cxl_dev_state_create(parent, type, serial, dvsec, drv_struct, member, mbox) \
>> + ({ \
>> + static_assert(__same_type(struct cxl_dev_state, \
>> + ((drv_struct *)NULL)->member)); \
>> + static_assert(offsetof(drv_struct, member) == 0); \
>> + (drv_struct *)_devm_cxl_dev_state_create(parent, type, serial, dvsec, \
>> + sizeof(drv_struct), mbox); \
>> + })
>> +
^ permalink raw reply [flat|nested] 16+ messages in thread
* [PATCH v2 2/3] cxl: export internal structs for external Type2 drivers
2026-02-25 12:14 [PATCH v2 0/3] type2 support preparation alejandro.lucero-palau
2026-02-25 12:14 ` [PATCH v2 1/3] cxl: support Type2 when initializing cxl_dev_state alejandro.lucero-palau
@ 2026-02-25 12:14 ` alejandro.lucero-palau
2026-02-25 15:35 ` Gregory Price
2026-02-27 12:21 ` Jonathan Cameron
2026-02-25 12:14 ` [PATCH v2 3/3] cxl: Move pci generic code alejandro.lucero-palau
2 siblings, 2 replies; 16+ messages in thread
From: alejandro.lucero-palau @ 2026-02-25 12:14 UTC (permalink / raw)
To: linux-cxl, dan.j.williams, dave.jiang; +Cc: Alejandro Lucero, Alison Schofield
From: Alejandro Lucero <alucerop@amd.com>
In preparation for type2 support, move structs and functions a type2
driver will need to access to into a new shared header file.
Differentiate between public and private data to be preserved by type2
drivers.
Signed-off-by: Alejandro Lucero <alucerop@amd.com>
Reviewed-by: Dave Jiang <dave.jiang@intel.com>
Tested-by: Alison Schofield <alison.schofield@intel.com>
---
drivers/cxl/cxl.h | 97 +------------------
drivers/cxl/cxlmem.h | 114 ----------------------
include/cxl/cxl.h | 226 +++++++++++++++++++++++++++++++++++++++++++
3 files changed, 227 insertions(+), 210 deletions(-)
create mode 100644 include/cxl/cxl.h
diff --git a/drivers/cxl/cxl.h b/drivers/cxl/cxl.h
index 04c673e7cdb0..0d350b69f1c8 100644
--- a/drivers/cxl/cxl.h
+++ b/drivers/cxl/cxl.h
@@ -12,6 +12,7 @@
#include <linux/node.h>
#include <linux/io.h>
#include <linux/range.h>
+#include <cxl/cxl.h>
extern const struct nvdimm_security_ops *cxl_security_ops;
@@ -201,97 +202,6 @@ static inline int ways_to_eiw(unsigned int ways, u8 *eiw)
#define CXLDEV_MBOX_BG_CMD_COMMAND_VENDOR_MASK GENMASK_ULL(63, 48)
#define CXLDEV_MBOX_PAYLOAD_OFFSET 0x20
-/*
- * Using struct_group() allows for per register-block-type helper routines,
- * without requiring block-type agnostic code to include the prefix.
- */
-struct cxl_regs {
- /*
- * Common set of CXL Component register block base pointers
- * @hdm_decoder: CXL 2.0 8.2.5.12 CXL HDM Decoder Capability Structure
- * @ras: CXL 2.0 8.2.5.9 CXL RAS Capability Structure
- */
- struct_group_tagged(cxl_component_regs, component,
- void __iomem *hdm_decoder;
- void __iomem *ras;
- );
- /*
- * Common set of CXL Device register block base pointers
- * @status: CXL 2.0 8.2.8.3 Device Status Registers
- * @mbox: CXL 2.0 8.2.8.4 Mailbox Registers
- * @memdev: CXL 2.0 8.2.8.5 Memory Device Registers
- */
- struct_group_tagged(cxl_device_regs, device_regs,
- void __iomem *status, *mbox, *memdev;
- );
-
- struct_group_tagged(cxl_pmu_regs, pmu_regs,
- void __iomem *pmu;
- );
-
- /*
- * RCH downstream port specific RAS register
- * @aer: CXL 3.0 8.2.1.1 RCH Downstream Port RCRB
- */
- struct_group_tagged(cxl_rch_regs, rch_regs,
- void __iomem *dport_aer;
- );
-
- /*
- * RCD upstream port specific PCIe cap register
- * @pcie_cap: CXL 3.0 8.2.1.2 RCD Upstream Port RCRB
- */
- struct_group_tagged(cxl_rcd_regs, rcd_regs,
- void __iomem *rcd_pcie_cap;
- );
-};
-
-struct cxl_reg_map {
- bool valid;
- int id;
- unsigned long offset;
- unsigned long size;
-};
-
-struct cxl_component_reg_map {
- struct cxl_reg_map hdm_decoder;
- struct cxl_reg_map ras;
-};
-
-struct cxl_device_reg_map {
- struct cxl_reg_map status;
- struct cxl_reg_map mbox;
- struct cxl_reg_map memdev;
-};
-
-struct cxl_pmu_reg_map {
- struct cxl_reg_map pmu;
-};
-
-/**
- * struct cxl_register_map - DVSEC harvested register block mapping parameters
- * @host: device for devm operations and logging
- * @base: virtual base of the register-block-BAR + @block_offset
- * @resource: physical resource base of the register block
- * @max_size: maximum mapping size to perform register search
- * @reg_type: see enum cxl_regloc_type
- * @component_map: cxl_reg_map for component registers
- * @device_map: cxl_reg_maps for device registers
- * @pmu_map: cxl_reg_maps for CXL Performance Monitoring Units
- */
-struct cxl_register_map {
- struct device *host;
- void __iomem *base;
- resource_size_t resource;
- resource_size_t max_size;
- u8 reg_type;
- union {
- struct cxl_component_reg_map component_map;
- struct cxl_device_reg_map device_map;
- struct cxl_pmu_reg_map pmu_map;
- };
-};
-
void cxl_probe_component_regs(struct device *dev, void __iomem *base,
struct cxl_component_reg_map *map);
void cxl_probe_device_regs(struct device *dev, void __iomem *base,
@@ -497,11 +407,6 @@ struct cxl_region_params {
resource_size_t cache_size;
};
-enum cxl_partition_mode {
- CXL_PARTMODE_RAM,
- CXL_PARTMODE_PMEM,
-};
-
/*
* Indicate whether this region has been assembled by autodetection or
* userspace assembly. Prevent endpoint decoders outside of automatic
diff --git a/drivers/cxl/cxlmem.h b/drivers/cxl/cxlmem.h
index 9daf4bc42692..281546de426e 100644
--- a/drivers/cxl/cxlmem.h
+++ b/drivers/cxl/cxlmem.h
@@ -113,8 +113,6 @@ int devm_cxl_dpa_reserve(struct cxl_endpoint_decoder *cxled,
resource_size_t base, resource_size_t len,
resource_size_t skipped);
-#define CXL_NR_PARTITIONS_MAX 2
-
struct cxl_dpa_info {
u64 size;
struct cxl_dpa_part_info {
@@ -373,87 +371,6 @@ struct cxl_security_state {
struct kernfs_node *sanitize_node;
};
-/*
- * enum cxl_devtype - delineate type-2 from a generic type-3 device
- * @CXL_DEVTYPE_DEVMEM - Vendor specific CXL Type-2 device implementing HDM-D or
- * HDM-DB, no requirement that this device implements a
- * mailbox, or other memory-device-standard manageability
- * flows.
- * @CXL_DEVTYPE_CLASSMEM - Common class definition of a CXL Type-3 device with
- * HDM-H and class-mandatory memory device registers
- */
-enum cxl_devtype {
- CXL_DEVTYPE_DEVMEM,
- CXL_DEVTYPE_CLASSMEM,
-};
-
-/**
- * struct cxl_dpa_perf - DPA performance property entry
- * @dpa_range: range for DPA address
- * @coord: QoS performance data (i.e. latency, bandwidth)
- * @cdat_coord: raw QoS performance data from CDAT
- * @qos_class: QoS Class cookies
- */
-struct cxl_dpa_perf {
- struct range dpa_range;
- struct access_coordinate coord[ACCESS_COORDINATE_MAX];
- struct access_coordinate cdat_coord[ACCESS_COORDINATE_MAX];
- int qos_class;
-};
-
-/**
- * struct cxl_dpa_partition - DPA partition descriptor
- * @res: shortcut to the partition in the DPA resource tree (cxlds->dpa_res)
- * @perf: performance attributes of the partition from CDAT
- * @mode: operation mode for the DPA capacity, e.g. ram, pmem, dynamic...
- */
-struct cxl_dpa_partition {
- struct resource res;
- struct cxl_dpa_perf perf;
- enum cxl_partition_mode mode;
-};
-
-/**
- * struct cxl_dev_state - The driver device state
- *
- * cxl_dev_state represents the CXL driver/device state. It provides an
- * interface to mailbox commands as well as some cached data about the device.
- * Currently only memory devices are represented.
- *
- * @dev: The device associated with this CXL state
- * @cxlmd: The device representing the CXL.mem capabilities of @dev
- * @reg_map: component and ras register mapping parameters
- * @regs: Class device "Device" registers
- * @cxl_dvsec: Offset to the PCIe device DVSEC
- * @rcd: operating in RCD mode (CXL 3.0 9.11.8 CXL Devices Attached to an RCH)
- * @media_ready: Indicate whether the device media is usable
- * @dpa_res: Overall DPA resource tree for the device
- * @part: DPA partition array
- * @nr_partitions: Number of DPA partitions
- * @serial: PCIe Device Serial Number
- * @type: Generic Memory Class device or Vendor Specific Memory device
- * @cxl_mbox: CXL mailbox context
- * @cxlfs: CXL features context
- */
-struct cxl_dev_state {
- struct device *dev;
- struct cxl_memdev *cxlmd;
- struct cxl_register_map reg_map;
- struct cxl_device_regs regs;
- int cxl_dvsec;
- bool rcd;
- bool media_ready;
- struct resource dpa_res;
- struct cxl_dpa_partition part[CXL_NR_PARTITIONS_MAX];
- unsigned int nr_partitions;
- u64 serial;
- enum cxl_devtype type;
- struct cxl_mailbox cxl_mbox;
-#ifdef CONFIG_CXL_FEATURES
- struct cxl_features_state *cxlfs;
-#endif
-};
-
static inline resource_size_t cxl_pmem_size(struct cxl_dev_state *cxlds)
{
/*
@@ -523,37 +440,6 @@ to_cxl_memdev_state(struct cxl_dev_state *cxlds)
return container_of(cxlds, struct cxl_memdev_state, cxlds);
}
-struct cxl_dev_state *_devm_cxl_dev_state_create(struct device *dev,
- enum cxl_devtype type,
- u64 serial, u16 dvsec,
- size_t size, bool has_mbox);
-
-/**
- * cxl_dev_state_create - safely create and cast a cxl dev state embedded in a
- * driver specific struct.
- *
- * @parent: device behind the request
- * @type: CXL device type
- * @serial: device identification
- * @dvsec: dvsec capability offset
- * @drv_struct: driver struct embedding a cxl_dev_state struct
- * @member: drv_struct member as cxl_dev_state
- * @mbox: true if mailbox supported
- *
- * Returns a pointer to the drv_struct allocated and embedding a cxl_dev_state
- * struct initialized.
- *
- * Introduced for Type2 driver support.
- */
-#define devm_cxl_dev_state_create(parent, type, serial, dvsec, drv_struct, member, mbox) \
- ({ \
- static_assert(__same_type(struct cxl_dev_state, \
- ((drv_struct *)NULL)->member)); \
- static_assert(offsetof(drv_struct, member) == 0); \
- (drv_struct *)_devm_cxl_dev_state_create(parent, type, serial, dvsec, \
- sizeof(drv_struct), mbox); \
- })
-
enum cxl_opcode {
CXL_MBOX_OP_INVALID = 0x0000,
CXL_MBOX_OP_RAW = CXL_MBOX_OP_INVALID,
diff --git a/include/cxl/cxl.h b/include/cxl/cxl.h
new file mode 100644
index 000000000000..11f76d61c9f1
--- /dev/null
+++ b/include/cxl/cxl.h
@@ -0,0 +1,226 @@
+/* SPDX-License-Identifier: GPL-2.0 */
+/* Copyright(c) 2020 Intel Corporation. */
+/* Copyright(c) 2026 Advanced Micro Devices, Inc. */
+
+#ifndef __CXL_CXL_H__
+#define __CXL_CXL_H__
+
+#include <linux/node.h>
+#include <linux/ioport.h>
+#include <cxl/mailbox.h>
+
+/**
+ * enum cxl_devtype - delineate type-2 from a generic type-3 device
+ * @CXL_DEVTYPE_DEVMEM: Vendor specific CXL Type-2 device implementing HDM-D or
+ * HDM-DB, no requirement that this device implements a
+ * mailbox, or other memory-device-standard manageability
+ * flows.
+ * @CXL_DEVTYPE_CLASSMEM: Common class definition of a CXL Type-3 device with
+ * HDM-H and class-mandatory memory device registers
+ */
+enum cxl_devtype {
+ CXL_DEVTYPE_DEVMEM,
+ CXL_DEVTYPE_CLASSMEM,
+};
+
+struct device;
+
+/*
+ * Using struct_group() allows for per register-block-type helper routines,
+ * without requiring block-type agnostic code to include the prefix.
+ */
+struct cxl_regs {
+ /*
+ * Common set of CXL Component register block base pointers
+ * @hdm_decoder: CXL 2.0 8.2.5.12 CXL HDM Decoder Capability Structure
+ * @ras: CXL 2.0 8.2.5.9 CXL RAS Capability Structure
+ */
+ struct_group_tagged(cxl_component_regs, component,
+ void __iomem *hdm_decoder;
+ void __iomem *ras;
+ );
+ /*
+ * Common set of CXL Device register block base pointers
+ * @status: CXL 2.0 8.2.8.3 Device Status Registers
+ * @mbox: CXL 2.0 8.2.8.4 Mailbox Registers
+ * @memdev: CXL 2.0 8.2.8.5 Memory Device Registers
+ */
+ struct_group_tagged(cxl_device_regs, device_regs,
+ void __iomem *status, *mbox, *memdev;
+ );
+
+ struct_group_tagged(cxl_pmu_regs, pmu_regs,
+ void __iomem *pmu;
+ );
+
+ /*
+ * RCH downstream port specific RAS register
+ * @aer: CXL 3.0 8.2.1.1 RCH Downstream Port RCRB
+ */
+ struct_group_tagged(cxl_rch_regs, rch_regs,
+ void __iomem *dport_aer;
+ );
+
+ /*
+ * RCD upstream port specific PCIe cap register
+ * @pcie_cap: CXL 3.0 8.2.1.2 RCD Upstream Port RCRB
+ */
+ struct_group_tagged(cxl_rcd_regs, rcd_regs,
+ void __iomem *rcd_pcie_cap;
+ );
+};
+
+struct cxl_reg_map {
+ bool valid;
+ int id;
+ unsigned long offset;
+ unsigned long size;
+};
+
+struct cxl_component_reg_map {
+ struct cxl_reg_map hdm_decoder;
+ struct cxl_reg_map ras;
+};
+
+struct cxl_device_reg_map {
+ struct cxl_reg_map status;
+ struct cxl_reg_map mbox;
+ struct cxl_reg_map memdev;
+};
+
+struct cxl_pmu_reg_map {
+ struct cxl_reg_map pmu;
+};
+
+/**
+ * struct cxl_register_map - DVSEC harvested register block mapping parameters
+ * @host: device for devm operations and logging
+ * @base: virtual base of the register-block-BAR + @block_offset
+ * @resource: physical resource base of the register block
+ * @max_size: maximum mapping size to perform register search
+ * @reg_type: see enum cxl_regloc_type
+ * @component_map: cxl_reg_map for component registers
+ * @device_map: cxl_reg_maps for device registers
+ * @pmu_map: cxl_reg_maps for CXL Performance Monitoring Units
+ */
+struct cxl_register_map {
+ struct device *host;
+ void __iomem *base;
+ resource_size_t resource;
+ resource_size_t max_size;
+ u8 reg_type;
+ union {
+ struct cxl_component_reg_map component_map;
+ struct cxl_device_reg_map device_map;
+ struct cxl_pmu_reg_map pmu_map;
+ };
+};
+
+/**
+ * struct cxl_dpa_perf - DPA performance property entry
+ * @dpa_range: range for DPA address
+ * @coord: QoS performance data (i.e. latency, bandwidth)
+ * @cdat_coord: raw QoS performance data from CDAT
+ * @qos_class: QoS Class cookies
+ */
+struct cxl_dpa_perf {
+ struct range dpa_range;
+ struct access_coordinate coord[ACCESS_COORDINATE_MAX];
+ struct access_coordinate cdat_coord[ACCESS_COORDINATE_MAX];
+ int qos_class;
+};
+
+enum cxl_partition_mode {
+ CXL_PARTMODE_RAM,
+ CXL_PARTMODE_PMEM,
+};
+
+/**
+ * struct cxl_dpa_partition - DPA partition descriptor
+ * @res: shortcut to the partition in the DPA resource tree (cxlds->dpa_res)
+ * @perf: performance attributes of the partition from CDAT
+ * @mode: operation mode for the DPA capacity, e.g. ram, pmem, dynamic...
+ */
+struct cxl_dpa_partition {
+ struct resource res;
+ struct cxl_dpa_perf perf;
+ enum cxl_partition_mode mode;
+};
+
+#define CXL_NR_PARTITIONS_MAX 2
+
+/**
+ * struct cxl_dev_state - The driver device state
+ *
+ * cxl_dev_state represents the CXL driver/device state. It provides an
+ * interface to mailbox commands as well as some cached data about the device.
+ * Currently only memory devices are represented.
+ *
+ * @dev: The device associated with this CXL state
+ * @cxlmd: The device representing the CXL.mem capabilities of @dev
+ * @reg_map: component and ras register mapping parameters
+ * @regs: Parsed register blocks
+ * @cxl_dvsec: Offset to the PCIe device DVSEC
+ * @rcd: operating in RCD mode (CXL 3.0 9.11.8 CXL Devices Attached to an RCH)
+ * @media_ready: Indicate whether the device media is usable
+ * @dpa_res: Overall DPA resource tree for the device
+ * @part: DPA partition array
+ * @nr_partitions: Number of DPA partitions
+ * @serial: PCIe Device Serial Number
+ * @type: Generic Memory Class device or Vendor Specific Memory device
+ * @cxl_mbox: CXL mailbox context
+ * @cxlfs: CXL features context
+ */
+struct cxl_dev_state {
+ /* public for Type2 drivers */
+ struct device *dev;
+ struct cxl_memdev *cxlmd;
+
+ /* private for Type2 drivers */
+ struct cxl_register_map reg_map;
+ struct cxl_device_regs regs;
+ int cxl_dvsec;
+ bool rcd;
+ bool media_ready;
+ struct resource dpa_res;
+ struct cxl_dpa_partition part[CXL_NR_PARTITIONS_MAX];
+ unsigned int nr_partitions;
+ u64 serial;
+ enum cxl_devtype type;
+ struct cxl_mailbox cxl_mbox;
+#ifdef CONFIG_CXL_FEATURES
+ struct cxl_features_state *cxlfs;
+#endif
+};
+
+struct cxl_dev_state *_devm_cxl_dev_state_create(struct device *dev,
+ enum cxl_devtype type,
+ u64 serial, u16 dvsec,
+ size_t size, bool has_mbox);
+
+/**
+ * cxl_dev_state_create - safely create and cast a cxl dev state embedded in a
+ * driver specific struct.
+ *
+ * @parent: device behind the request
+ * @type: CXL device type
+ * @serial: device identification
+ * @dvsec: dvsec capability offset
+ * @drv_struct: driver struct embedding a cxl_dev_state struct
+ * @member: drv_struct member as cxl_dev_state
+ * @mbox: true if mailbox supported
+ *
+ * Returns a pointer to the drv_struct allocated and embedding a cxl_dev_state
+ * struct initialized.
+ *
+ * Introduced for Type2 driver support.
+ */
+#define devm_cxl_dev_state_create(parent, type, serial, dvsec, drv_struct, member, mbox) \
+ ({ \
+ static_assert(__same_type(struct cxl_dev_state, \
+ ((drv_struct *)NULL)->member)); \
+ static_assert(offsetof(drv_struct, member) == 0); \
+ (drv_struct *)_devm_cxl_dev_state_create(parent, type, serial, dvsec, \
+ sizeof(drv_struct), mbox); \
+ })
+#endif /* __CXL_CXL_H__ */
--
2.34.1
^ permalink raw reply related [flat|nested] 16+ messages in thread* Re: [PATCH v2 2/3] cxl: export internal structs for external Type2 drivers
2026-02-25 12:14 ` [PATCH v2 2/3] cxl: export internal structs for external Type2 drivers alejandro.lucero-palau
@ 2026-02-25 15:35 ` Gregory Price
2026-02-27 19:53 ` Alejandro Lucero Palau
2026-02-27 12:21 ` Jonathan Cameron
1 sibling, 1 reply; 16+ messages in thread
From: Gregory Price @ 2026-02-25 15:35 UTC (permalink / raw)
To: alejandro.lucero-palau
Cc: linux-cxl, dan.j.williams, dave.jiang, Alejandro Lucero,
Alison Schofield
On Wed, Feb 25, 2026 at 12:14:29PM +0000, alejandro.lucero-palau@amd.com wrote:
> From: Alejandro Lucero <alucerop@amd.com>
>
Mostly two nits
Reviewed-by: Gregory Price <gourry@gourry.net>
> diff --git a/drivers/cxl/cxl.h b/drivers/cxl/cxl.h
> index 04c673e7cdb0..0d350b69f1c8 100644
> --- a/drivers/cxl/cxl.h
> +++ b/drivers/cxl/cxl.h
> @@ -12,6 +12,7 @@
> #include <linux/node.h>
> #include <linux/io.h>
> #include <linux/range.h>
> +#include <cxl/cxl.h>
>
... snip ...
> diff --git a/include/cxl/cxl.h b/include/cxl/cxl.h
> --- /dev/null
> +++ b/include/cxl/cxl.h
... snip ...
> +#include <linux/node.h>
> +#include <linux/ioport.h>
> +#include <cxl/mailbox.h>
... snip ...
> +struct cxl_dpa_perf {
> + struct range dpa_range;
You dropped linux/range.h from the move.
Probably still builds in most cases since range is likely included
somewhere else deep in the stack, but correctness etc etc.
One other nit, you mention Type2 drivers a lot in comments:
+struct cxl_dev_state {
+ /* public for Type2 drivers */
+ struct device *dev;
+ struct cxl_memdev *cxlmd;
+
+ /* private for Type2 drivers */
+ struct cxl_register_map reg_map;
+ struct cxl_device_regs regs;
Is it reasonable to think that these would be public/private for *any*
*any* driver building from the public headers?
^ permalink raw reply [flat|nested] 16+ messages in thread* Re: [PATCH v2 2/3] cxl: export internal structs for external Type2 drivers
2026-02-25 15:35 ` Gregory Price
@ 2026-02-27 19:53 ` Alejandro Lucero Palau
0 siblings, 0 replies; 16+ messages in thread
From: Alejandro Lucero Palau @ 2026-02-27 19:53 UTC (permalink / raw)
To: Gregory Price, alejandro.lucero-palau
Cc: linux-cxl, dan.j.williams, dave.jiang, Alison Schofield
On 2/25/26 15:35, Gregory Price wrote:
> On Wed, Feb 25, 2026 at 12:14:29PM +0000, alejandro.lucero-palau@amd.com wrote:
>> From: Alejandro Lucero <alucerop@amd.com>
>>
> Mostly two nits
>
> Reviewed-by: Gregory Price <gourry@gourry.net>
>
>> diff --git a/drivers/cxl/cxl.h b/drivers/cxl/cxl.h
>> index 04c673e7cdb0..0d350b69f1c8 100644
>> --- a/drivers/cxl/cxl.h
>> +++ b/drivers/cxl/cxl.h
>> @@ -12,6 +12,7 @@
>> #include <linux/node.h>
>> #include <linux/io.h>
>> #include <linux/range.h>
>> +#include <cxl/cxl.h>
>>
> ... snip ...
>
>> diff --git a/include/cxl/cxl.h b/include/cxl/cxl.h
>> --- /dev/null
>> +++ b/include/cxl/cxl.h
> ... snip ...
>
>> +#include <linux/node.h>
>> +#include <linux/ioport.h>
>> +#include <cxl/mailbox.h>
> ... snip ...
>
>> +struct cxl_dpa_perf {
>> + struct range dpa_range;
> You dropped linux/range.h from the move.
>
> Probably still builds in most cases since range is likely included
> somewhere else deep in the stack, but correctness etc etc.
That is right. I remember some issues with this. I will add it again.
>
> One other nit, you mention Type2 drivers a lot in comments:
>
> +struct cxl_dev_state {
> + /* public for Type2 drivers */
> + struct device *dev;
> + struct cxl_memdev *cxlmd;
> +
> + /* private for Type2 drivers */
> + struct cxl_register_map reg_map;
> + struct cxl_device_regs regs;
>
> Is it reasonable to think that these would be public/private for *any*
> *any* driver building from the public headers?
>
Those comments were explicitly added by Dan. Any external driver to cxl
core should not use the private ones.
Thank you
^ permalink raw reply [flat|nested] 16+ messages in thread
* Re: [PATCH v2 2/3] cxl: export internal structs for external Type2 drivers
2026-02-25 12:14 ` [PATCH v2 2/3] cxl: export internal structs for external Type2 drivers alejandro.lucero-palau
2026-02-25 15:35 ` Gregory Price
@ 2026-02-27 12:21 ` Jonathan Cameron
2026-02-27 20:02 ` Alejandro Lucero Palau
1 sibling, 1 reply; 16+ messages in thread
From: Jonathan Cameron @ 2026-02-27 12:21 UTC (permalink / raw)
To: alejandro.lucero-palau
Cc: linux-cxl, dan.j.williams, dave.jiang, Alejandro Lucero,
Alison Schofield
On Wed, 25 Feb 2026 12:14:29 +0000
alejandro.lucero-palau@amd.com wrote:
> From: Alejandro Lucero <alucerop@amd.com>
>
> In preparation for type2 support, move structs and functions a type2
> driver will need to access to into a new shared header file.
>
> Differentiate between public and private data to be preserved by type2
> drivers.
>
> Signed-off-by: Alejandro Lucero <alucerop@amd.com>
> Reviewed-by: Dave Jiang <dave.jiang@intel.com>
> Tested-by: Alison Schofield <alison.schofield@intel.com>
> ---
> drivers/cxl/cxl.h | 97 +------------------
> drivers/cxl/cxlmem.h | 114 ----------------------
> include/cxl/cxl.h | 226 +++++++++++++++++++++++++++++++++++++++++++
I'm a tiny bit dubious that this has 'yet' reached the state where the copyright
notice in cxl.h is appropriate. This patch for instance is just code movement
which I'd not consider sufficient.
Meh, it'll be valid in the end!
Trivial follow through from the earlier patch.
Reviewed-by: Jonathan Cameron <jonathan.cameron@huawei.com>
> diff --git a/include/cxl/cxl.h b/include/cxl/cxl.h
> new file mode 100644
> index 000000000000..11f76d61c9f1
> --- /dev/null
> +++ b/include/cxl/cxl.h
> +/**
> + * cxl_dev_state_create - safely create and cast a cxl dev state embedded in a
> + * driver specific struct.
> + *
> + * @parent: device behind the request
> + * @type: CXL device type
> + * @serial: device identification
> + * @dvsec: dvsec capability offset
> + * @drv_struct: driver struct embedding a cxl_dev_state struct
> + * @member: drv_struct member as cxl_dev_state
Follow through from previous...
> + * @mbox: true if mailbox supported
> + *
^ permalink raw reply [flat|nested] 16+ messages in thread
* Re: [PATCH v2 2/3] cxl: export internal structs for external Type2 drivers
2026-02-27 12:21 ` Jonathan Cameron
@ 2026-02-27 20:02 ` Alejandro Lucero Palau
0 siblings, 0 replies; 16+ messages in thread
From: Alejandro Lucero Palau @ 2026-02-27 20:02 UTC (permalink / raw)
To: Jonathan Cameron, alejandro.lucero-palau
Cc: linux-cxl, dan.j.williams, dave.jiang, Alison Schofield
On 2/27/26 12:21, Jonathan Cameron wrote:
> On Wed, 25 Feb 2026 12:14:29 +0000
> alejandro.lucero-palau@amd.com wrote:
>
>> From: Alejandro Lucero <alucerop@amd.com>
>>
>> In preparation for type2 support, move structs and functions a type2
>> driver will need to access to into a new shared header file.
>>
>> Differentiate between public and private data to be preserved by type2
>> drivers.
>>
>> Signed-off-by: Alejandro Lucero <alucerop@amd.com>
>> Reviewed-by: Dave Jiang <dave.jiang@intel.com>
>> Tested-by: Alison Schofield <alison.schofield@intel.com>
>> ---
>> drivers/cxl/cxl.h | 97 +------------------
>> drivers/cxl/cxlmem.h | 114 ----------------------
>> include/cxl/cxl.h | 226 +++++++++++++++++++++++++++++++++++++++++++
> I'm a tiny bit dubious that this has 'yet' reached the state where the copyright
> notice in cxl.h is appropriate. This patch for instance is just code movement
> which I'd not consider sufficient.
>
> Meh, it'll be valid in the end!
>
> Trivial follow through from the earlier patch.
>
> Reviewed-by: Jonathan Cameron <jonathan.cameron@huawei.com>
>> diff --git a/include/cxl/cxl.h b/include/cxl/cxl.h
>> new file mode 100644
>> index 000000000000..11f76d61c9f1
>> --- /dev/null
>> +++ b/include/cxl/cxl.h
>> +/**
>> + * cxl_dev_state_create - safely create and cast a cxl dev state embedded in a
>> + * driver specific struct.
>> + *
>> + * @parent: device behind the request
>> + * @type: CXL device type
>> + * @serial: device identification
>> + * @dvsec: dvsec capability offset
>> + * @drv_struct: driver struct embedding a cxl_dev_state struct
>> + * @member: drv_struct member as cxl_dev_state
> Follow through from previous...
Sure.
Thanks!
>
>> + * @mbox: true if mailbox supported
>> + *
^ permalink raw reply [flat|nested] 16+ messages in thread
* [PATCH v2 3/3] cxl: Move pci generic code
2026-02-25 12:14 [PATCH v2 0/3] type2 support preparation alejandro.lucero-palau
2026-02-25 12:14 ` [PATCH v2 1/3] cxl: support Type2 when initializing cxl_dev_state alejandro.lucero-palau
2026-02-25 12:14 ` [PATCH v2 2/3] cxl: export internal structs for external Type2 drivers alejandro.lucero-palau
@ 2026-02-25 12:14 ` alejandro.lucero-palau
2026-02-25 16:00 ` Gregory Price
2026-02-27 12:24 ` Jonathan Cameron
2 siblings, 2 replies; 16+ messages in thread
From: alejandro.lucero-palau @ 2026-02-25 12:14 UTC (permalink / raw)
To: linux-cxl, dan.j.williams, dave.jiang; +Cc: Alejandro Lucero
From: Alejandro Lucero <alucerop@amd.com>
Inside cxl/core/pci.c there are helpers for CXL PCIe initialization
meanwhile cxl/pci_drv.c implements the functionality for a Type3 device
initialization.
In preparation for type2 support, move helper functions from cxl/pci.c to
cxl/core/pci.c in order to be exported and used by type2 drivers.
Signed-off-by: Alejandro Lucero <alucerop@amd.com>
Reviewed-by: Dave Jiang <dave.jiang@intel.com>
---
drivers/cxl/core/core.h | 2 ++
drivers/cxl/core/pci.c | 62 ++++++++++++++++++++++++++++++++++++
drivers/cxl/core/regs.c | 1 -
drivers/cxl/cxl.h | 2 --
drivers/cxl/cxlpci.h | 13 ++++++++
drivers/cxl/pci.c | 70 -----------------------------------------
6 files changed, 77 insertions(+), 73 deletions(-)
diff --git a/drivers/cxl/core/core.h b/drivers/cxl/core/core.h
index 007b8aff0238..19494a8615d3 100644
--- a/drivers/cxl/core/core.h
+++ b/drivers/cxl/core/core.h
@@ -206,4 +206,6 @@ int cxl_set_feature(struct cxl_mailbox *cxl_mbox, const uuid_t *feat_uuid,
u16 *return_code);
#endif
+resource_size_t cxl_rcd_component_reg_phys(struct device *dev,
+ struct cxl_dport *dport);
#endif /* __CXL_CORE_H__ */
diff --git a/drivers/cxl/core/pci.c b/drivers/cxl/core/pci.c
index f96ce884a213..c32cc62c501d 100644
--- a/drivers/cxl/core/pci.c
+++ b/drivers/cxl/core/pci.c
@@ -696,6 +696,68 @@ bool cxl_endpoint_decoder_reset_detected(struct cxl_port *port)
}
EXPORT_SYMBOL_NS_GPL(cxl_endpoint_decoder_reset_detected, "CXL");
+static int cxl_rcrb_get_comp_regs(struct pci_dev *pdev,
+ struct cxl_register_map *map,
+ struct cxl_dport *dport)
+{
+ resource_size_t component_reg_phys;
+
+ *map = (struct cxl_register_map) {
+ .host = &pdev->dev,
+ .resource = CXL_RESOURCE_NONE,
+ };
+
+ struct cxl_port *port __free(put_cxl_port) =
+ cxl_pci_find_port(pdev, &dport);
+ if (!port)
+ return -EPROBE_DEFER;
+
+ component_reg_phys = cxl_rcd_component_reg_phys(&pdev->dev, dport);
+ if (component_reg_phys == CXL_RESOURCE_NONE)
+ return -ENXIO;
+
+ map->resource = component_reg_phys;
+ map->reg_type = CXL_REGLOC_RBI_COMPONENT;
+ map->max_size = CXL_COMPONENT_REG_BLOCK_SIZE;
+
+ return 0;
+}
+
+int cxl_pci_setup_regs(struct pci_dev *pdev, enum cxl_regloc_type type,
+ struct cxl_register_map *map)
+{
+ int rc;
+
+ rc = cxl_find_regblock(pdev, type, map);
+
+ /*
+ * If the Register Locator DVSEC does not exist, check if it
+ * is an RCH and try to extract the Component Registers from
+ * an RCRB.
+ */
+ if (rc && type == CXL_REGLOC_RBI_COMPONENT && is_cxl_restricted(pdev)) {
+ struct cxl_dport *dport;
+ struct cxl_port *port __free(put_cxl_port) =
+ cxl_pci_find_port(pdev, &dport);
+ if (!port)
+ return -EPROBE_DEFER;
+
+ rc = cxl_rcrb_get_comp_regs(pdev, map, dport);
+ if (rc)
+ return rc;
+
+ rc = cxl_dport_map_rcd_linkcap(pdev, dport);
+ if (rc)
+ return rc;
+
+ } else if (rc) {
+ return rc;
+ }
+
+ return cxl_setup_regs(map);
+}
+EXPORT_SYMBOL_NS_GPL(cxl_pci_setup_regs, "CXL");
+
int cxl_pci_get_bandwidth(struct pci_dev *pdev, struct access_coordinate *c)
{
int speed, bw;
diff --git a/drivers/cxl/core/regs.c b/drivers/cxl/core/regs.c
index a010b3214342..93710cf4f0a6 100644
--- a/drivers/cxl/core/regs.c
+++ b/drivers/cxl/core/regs.c
@@ -641,4 +641,3 @@ resource_size_t cxl_rcd_component_reg_phys(struct device *dev,
return CXL_RESOURCE_NONE;
return __rcrb_to_component(dev, &dport->rcrb, CXL_RCRB_UPSTREAM);
}
-EXPORT_SYMBOL_NS_GPL(cxl_rcd_component_reg_phys, "CXL");
diff --git a/drivers/cxl/cxl.h b/drivers/cxl/cxl.h
index 0d350b69f1c8..031846eab02c 100644
--- a/drivers/cxl/cxl.h
+++ b/drivers/cxl/cxl.h
@@ -222,8 +222,6 @@ int cxl_find_regblock(struct pci_dev *pdev, enum cxl_regloc_type type,
struct cxl_register_map *map);
int cxl_setup_regs(struct cxl_register_map *map);
struct cxl_dport;
-resource_size_t cxl_rcd_component_reg_phys(struct device *dev,
- struct cxl_dport *dport);
int cxl_dport_map_rcd_linkcap(struct pci_dev *pdev, struct cxl_dport *dport);
#define CXL_RESOURCE_NONE ((resource_size_t) -1)
diff --git a/drivers/cxl/cxlpci.h b/drivers/cxl/cxlpci.h
index 0cf64218aa16..b826eb53cf7b 100644
--- a/drivers/cxl/cxlpci.h
+++ b/drivers/cxl/cxlpci.h
@@ -74,6 +74,17 @@ static inline bool cxl_pci_flit_256(struct pci_dev *pdev)
return lnksta2 & PCI_EXP_LNKSTA2_FLIT;
}
+/*
+ * Assume that the caller has already validated that @pdev has CXL
+ * capabilities, any RCiEP with CXL capabilities is treated as a
+ * Restricted CXL Device (RCD) and finds upstream port and endpoint
+ * registers in a Root Complex Register Block (RCRB).
+ */
+static inline bool is_cxl_restricted(struct pci_dev *pdev)
+{
+ return pci_pcie_type(pdev) == PCI_EXP_TYPE_RC_END;
+}
+
struct cxl_dev_state;
void read_cdat_data(struct cxl_port *port);
@@ -101,4 +112,6 @@ static inline void devm_cxl_port_ras_setup(struct cxl_port *port)
}
#endif
+int cxl_pci_setup_regs(struct pci_dev *pdev, enum cxl_regloc_type type,
+ struct cxl_register_map *map);
#endif /* __CXL_PCI_H__ */
diff --git a/drivers/cxl/pci.c b/drivers/cxl/pci.c
index a42f273ff72b..adc7c4bcb03a 100644
--- a/drivers/cxl/pci.c
+++ b/drivers/cxl/pci.c
@@ -465,76 +465,6 @@ static int cxl_pci_setup_mailbox(struct cxl_memdev_state *mds, bool irq_avail)
return 0;
}
-/*
- * Assume that any RCIEP that emits the CXL memory expander class code
- * is an RCD
- */
-static bool is_cxl_restricted(struct pci_dev *pdev)
-{
- return pci_pcie_type(pdev) == PCI_EXP_TYPE_RC_END;
-}
-
-static int cxl_rcrb_get_comp_regs(struct pci_dev *pdev,
- struct cxl_register_map *map,
- struct cxl_dport *dport)
-{
- resource_size_t component_reg_phys;
-
- *map = (struct cxl_register_map) {
- .host = &pdev->dev,
- .resource = CXL_RESOURCE_NONE,
- };
-
- struct cxl_port *port __free(put_cxl_port) =
- cxl_pci_find_port(pdev, &dport);
- if (!port)
- return -EPROBE_DEFER;
-
- component_reg_phys = cxl_rcd_component_reg_phys(&pdev->dev, dport);
- if (component_reg_phys == CXL_RESOURCE_NONE)
- return -ENXIO;
-
- map->resource = component_reg_phys;
- map->reg_type = CXL_REGLOC_RBI_COMPONENT;
- map->max_size = CXL_COMPONENT_REG_BLOCK_SIZE;
-
- return 0;
-}
-
-static int cxl_pci_setup_regs(struct pci_dev *pdev, enum cxl_regloc_type type,
- struct cxl_register_map *map)
-{
- int rc;
-
- rc = cxl_find_regblock(pdev, type, map);
-
- /*
- * If the Register Locator DVSEC does not exist, check if it
- * is an RCH and try to extract the Component Registers from
- * an RCRB.
- */
- if (rc && type == CXL_REGLOC_RBI_COMPONENT && is_cxl_restricted(pdev)) {
- struct cxl_dport *dport;
- struct cxl_port *port __free(put_cxl_port) =
- cxl_pci_find_port(pdev, &dport);
- if (!port)
- return -EPROBE_DEFER;
-
- rc = cxl_rcrb_get_comp_regs(pdev, map, dport);
- if (rc)
- return rc;
-
- rc = cxl_dport_map_rcd_linkcap(pdev, dport);
- if (rc)
- return rc;
-
- } else if (rc) {
- return rc;
- }
-
- return cxl_setup_regs(map);
-}
-
static void free_event_buf(void *buf)
{
kvfree(buf);
--
2.34.1
^ permalink raw reply related [flat|nested] 16+ messages in thread* Re: [PATCH v2 3/3] cxl: Move pci generic code
2026-02-25 12:14 ` [PATCH v2 3/3] cxl: Move pci generic code alejandro.lucero-palau
@ 2026-02-25 16:00 ` Gregory Price
2026-02-27 19:59 ` Alejandro Lucero Palau
2026-02-27 12:24 ` Jonathan Cameron
1 sibling, 1 reply; 16+ messages in thread
From: Gregory Price @ 2026-02-25 16:00 UTC (permalink / raw)
To: alejandro.lucero-palau
Cc: linux-cxl, dan.j.williams, dave.jiang, Alejandro Lucero
On Wed, Feb 25, 2026 at 12:14:30PM +0000, alejandro.lucero-palau@amd.com wrote:
> From: Alejandro Lucero <alucerop@amd.com>
>
> Inside cxl/core/pci.c there are helpers for CXL PCIe initialization
> meanwhile cxl/pci_drv.c implements the functionality for a Type3 device
> initialization.
>
> In preparation for type2 support, move helper functions from cxl/pci.c to
> cxl/core/pci.c in order to be exported and used by type2 drivers.
>
> Signed-off-by: Alejandro Lucero <alucerop@amd.com>
> Reviewed-by: Dave Jiang <dave.jiang@intel.com>
One note for existing code so not a blocker (not really a bug)
Reviewed-by: Gregory Price <gourry@gourry.net>
> +static int cxl_rcrb_get_comp_regs(struct pci_dev *pdev,
> + struct cxl_register_map *map,
> + struct cxl_dport *dport)
> +{
... snip ...
> +
> + struct cxl_port *port __free(put_cxl_port) =
> + cxl_pci_find_port(pdev, &dport);
> + if (!port)
> + return -EPROBE_DEFER;
> +
... snip ...
> +
> +int cxl_pci_setup_regs(struct pci_dev *pdev, enum cxl_regloc_type type,
> + struct cxl_register_map *map)
> +{
... snip ...
> + if (rc && type == CXL_REGLOC_RBI_COMPONENT && is_cxl_restricted(pdev)) {
> + struct cxl_dport *dport;
> + struct cxl_port *port __free(put_cxl_port) =
> + cxl_pci_find_port(pdev, &dport);
> + if (!port)
> + return -EPROBE_DEFER;
> +
> + rc = cxl_rcrb_get_comp_regs(pdev, map, dport);
> + if (rc)
> + return rc;
> +
we call cxl_pci_find_port() here twice on the same pdev and pass the
dport into the second caller.
Can something actually change between these two secnarios? Seems like
we can just drop the check in cxl_rcrb_get_comp_regs?
~Gregory
---
cxl/pci: Remove redundant cxl_pci_find_port() call in cxl_rcrb_get_comp_regs()
Remove the redundant port lookup from cxl_rcrb_get_comp_regs() and use the
dport parameter directly. The caller has already validated the port is
non-NULL before invoking this function.
Signed-off-by: Gregory Price <gourry@gourry.net>
diff --git a/drivers/cxl/core/pci.c b/drivers/cxl/core/pci.c
index c32cc62c501d..d1f487b3d809 100644
--- a/drivers/cxl/core/pci.c
+++ b/drivers/cxl/core/pci.c
@@ -707,11 +707,6 @@ static int cxl_rcrb_get_comp_regs(struct pci_dev *pdev,
.resource = CXL_RESOURCE_NONE,
};
- struct cxl_port *port __free(put_cxl_port) =
- cxl_pci_find_port(pdev, &dport);
- if (!port)
- return -EPROBE_DEFER;
-
component_reg_phys = cxl_rcd_component_reg_phys(&pdev->dev, dport);
if (component_reg_phys == CXL_RESOURCE_NONE)
return -ENXIO;
^ permalink raw reply related [flat|nested] 16+ messages in thread* Re: [PATCH v2 3/3] cxl: Move pci generic code
2026-02-25 16:00 ` Gregory Price
@ 2026-02-27 19:59 ` Alejandro Lucero Palau
2026-02-27 23:07 ` Gregory Price
0 siblings, 1 reply; 16+ messages in thread
From: Alejandro Lucero Palau @ 2026-02-27 19:59 UTC (permalink / raw)
To: Gregory Price, alejandro.lucero-palau
Cc: linux-cxl, dan.j.williams, dave.jiang
On 2/25/26 16:00, Gregory Price wrote:
> On Wed, Feb 25, 2026 at 12:14:30PM +0000, alejandro.lucero-palau@amd.com wrote:
>> From: Alejandro Lucero <alucerop@amd.com>
>>
>> Inside cxl/core/pci.c there are helpers for CXL PCIe initialization
>> meanwhile cxl/pci_drv.c implements the functionality for a Type3 device
>> initialization.
>>
>> In preparation for type2 support, move helper functions from cxl/pci.c to
>> cxl/core/pci.c in order to be exported and used by type2 drivers.
>>
>> Signed-off-by: Alejandro Lucero <alucerop@amd.com>
>> Reviewed-by: Dave Jiang <dave.jiang@intel.com>
> One note for existing code so not a blocker (not really a bug)
>
> Reviewed-by: Gregory Price <gourry@gourry.net>
>
>> +static int cxl_rcrb_get_comp_regs(struct pci_dev *pdev,
>> + struct cxl_register_map *map,
>> + struct cxl_dport *dport)
>> +{
> ... snip ...
>> +
>> + struct cxl_port *port __free(put_cxl_port) =
>> + cxl_pci_find_port(pdev, &dport);
>> + if (!port)
>> + return -EPROBE_DEFER;
>> +
> ... snip ...
>> +
>> +int cxl_pci_setup_regs(struct pci_dev *pdev, enum cxl_regloc_type type,
>> + struct cxl_register_map *map)
>> +{
> ... snip ...
>> + if (rc && type == CXL_REGLOC_RBI_COMPONENT && is_cxl_restricted(pdev)) {
>> + struct cxl_dport *dport;
>> + struct cxl_port *port __free(put_cxl_port) =
>> + cxl_pci_find_port(pdev, &dport);
>> + if (!port)
>> + return -EPROBE_DEFER;
>> +
>> + rc = cxl_rcrb_get_comp_regs(pdev, map, dport);
>> + if (rc)
>> + return rc;
>> +
> we call cxl_pci_find_port() here twice on the same pdev and pass the
> dport into the second caller.
>
> Can something actually change between these two secnarios? Seems like
> we can just drop the check in cxl_rcrb_get_comp_regs?
Uhmm, I do not think we need the second one inside cxl_rcrb_get_comp_regs?
I will drop it and mention that in the commit.
Thank you
> ~Gregory
>
> ---
>
> cxl/pci: Remove redundant cxl_pci_find_port() call in cxl_rcrb_get_comp_regs()
>
> Remove the redundant port lookup from cxl_rcrb_get_comp_regs() and use the
> dport parameter directly. The caller has already validated the port is
> non-NULL before invoking this function.
>
> Signed-off-by: Gregory Price <gourry@gourry.net>
>
> diff --git a/drivers/cxl/core/pci.c b/drivers/cxl/core/pci.c
> index c32cc62c501d..d1f487b3d809 100644
> --- a/drivers/cxl/core/pci.c
> +++ b/drivers/cxl/core/pci.c
> @@ -707,11 +707,6 @@ static int cxl_rcrb_get_comp_regs(struct pci_dev *pdev,
> .resource = CXL_RESOURCE_NONE,
> };
>
> - struct cxl_port *port __free(put_cxl_port) =
> - cxl_pci_find_port(pdev, &dport);
> - if (!port)
> - return -EPROBE_DEFER;
> -
> component_reg_phys = cxl_rcd_component_reg_phys(&pdev->dev, dport);
> if (component_reg_phys == CXL_RESOURCE_NONE)
> return -ENXIO;
>
^ permalink raw reply [flat|nested] 16+ messages in thread* Re: [PATCH v2 3/3] cxl: Move pci generic code
2026-02-27 19:59 ` Alejandro Lucero Palau
@ 2026-02-27 23:07 ` Gregory Price
0 siblings, 0 replies; 16+ messages in thread
From: Gregory Price @ 2026-02-27 23:07 UTC (permalink / raw)
To: Alejandro Lucero Palau
Cc: alejandro.lucero-palau, linux-cxl, dan.j.williams, dave.jiang
On Fri, Feb 27, 2026 at 07:59:19PM +0000, Alejandro Lucero Palau wrote:
> > we call cxl_pci_find_port() here twice on the same pdev and pass the
> > dport into the second caller.
> >
> > Can something actually change between these two secnarios? Seems like
> > we can just drop the check in cxl_rcrb_get_comp_regs?
>
>
> Uhmm, I do not think we need the second one inside cxl_rcrb_get_comp_regs?
>
> I will drop it and mention that in the commit.
>
>
Since this is existing code, i would just use the patch i provided below
as an add-on. That way if something breaks later it can be bisected
cleanly without affecting your original movement commit.
~Gregory
> Thank you
>
>
> > ~Gregory
> >
> > ---
> >
> > cxl/pci: Remove redundant cxl_pci_find_port() call in cxl_rcrb_get_comp_regs()
> >
> > Remove the redundant port lookup from cxl_rcrb_get_comp_regs() and use the
> > dport parameter directly. The caller has already validated the port is
> > non-NULL before invoking this function.
> >
> > Signed-off-by: Gregory Price <gourry@gourry.net>
> >
> > diff --git a/drivers/cxl/core/pci.c b/drivers/cxl/core/pci.c
> > index c32cc62c501d..d1f487b3d809 100644
> > --- a/drivers/cxl/core/pci.c
> > +++ b/drivers/cxl/core/pci.c
> > @@ -707,11 +707,6 @@ static int cxl_rcrb_get_comp_regs(struct pci_dev *pdev,
> > .resource = CXL_RESOURCE_NONE,
> > };
> >
> > - struct cxl_port *port __free(put_cxl_port) =
> > - cxl_pci_find_port(pdev, &dport);
> > - if (!port)
> > - return -EPROBE_DEFER;
> > -
> > component_reg_phys = cxl_rcd_component_reg_phys(&pdev->dev, dport);
> > if (component_reg_phys == CXL_RESOURCE_NONE)
> > return -ENXIO;
> >
^ permalink raw reply [flat|nested] 16+ messages in thread
* Re: [PATCH v2 3/3] cxl: Move pci generic code
2026-02-25 12:14 ` [PATCH v2 3/3] cxl: Move pci generic code alejandro.lucero-palau
2026-02-25 16:00 ` Gregory Price
@ 2026-02-27 12:24 ` Jonathan Cameron
1 sibling, 0 replies; 16+ messages in thread
From: Jonathan Cameron @ 2026-02-27 12:24 UTC (permalink / raw)
To: alejandro.lucero-palau
Cc: linux-cxl, dan.j.williams, dave.jiang, Alejandro Lucero
On Wed, 25 Feb 2026 12:14:30 +0000
alejandro.lucero-palau@amd.com wrote:
> From: Alejandro Lucero <alucerop@amd.com>
>
> Inside cxl/core/pci.c there are helpers for CXL PCIe initialization
> meanwhile cxl/pci_drv.c implements the functionality for a Type3 device
> initialization.
>
> In preparation for type2 support, move helper functions from cxl/pci.c to
> cxl/core/pci.c in order to be exported and used by type2 drivers.
>
> Signed-off-by: Alejandro Lucero <alucerop@amd.com>
> Reviewed-by: Dave Jiang <dave.jiang@intel.com>
LGTM
Reviewed-by: Jonathan Cameron <jonathan.cameron@huawei.com>
^ permalink raw reply [flat|nested] 16+ messages in thread