All of lore.kernel.org
 help / color / mirror / Atom feed
* [PATCH v2 00/12] Device memory prep
@ 2023-06-15  1:29 Dan Williams
  2023-06-15  1:29 ` [PATCH v2 01/12] cxl/regs: Clarify when a 'struct cxl_register_map' is input vs output Dan Williams
                   ` (11 more replies)
  0 siblings, 12 replies; 27+ messages in thread
From: Dan Williams @ 2023-06-15  1:29 UTC (permalink / raw)
  To: linux-cxl; +Cc: Jonathan Cameron, Dave Jiang, Jonathan Cameron, Fan Ni

Changes since v1 [1]:
- Drop the region API changes to focus on the cleanups as a standalone
  set
- Added "cxl: Remove leftover attribute documentation..." (Jonathan)
- Added "cxl: Fix kernel-doc warnings" due as an additional cleanup
  prompted by the above
- Undo cxl_get_gsl() clang formatting (Jonathan)
- Clarified that the need for empty strings in the sysfs capacity
  attributes can be deprecated over time.
- s/expectation/requirement/ in CXL_DEVTYPE_DEVMEM kernel-doc (Jonathan)
- s/HOSTMEM/HOSTONLYMEM/ throughout (Jonathan)
- Fix initialization of the default decoder mode, and clarify that the
  default may need to change if, for example, non-class code HDM-H
  devices show up. (Jonathan)
- Fixup cxl_probe_link() to do actual 68B/256B Flit mode detection
  (Jonathan)
- Remove the previous 256B Flit mode detection

[1]: http://lore.kernel.org/r/168592149709.1948938.8663425987110396027.stgit@dwillia2-xfh.jf.intel.com

---

v1 of this patchset included reworks of the region creation APIs to
demonstrate how and accelerator could reuse CXL core APIs to establish a
host-managed device-memory region. These miscellaneous cleanups that
preceded those reworks are now broken out into their own set.

---

Dan Williams (12):
      cxl/regs: Clarify when a 'struct cxl_register_map' is input vs output
      tools/testing/cxl: Remove unused @cxlds argument
      cxl: Fix kernel-doc warnings
      cxl: Remove leftover attribute documentation in 'struct cxl_dev_state'
      cxl/mbox: Move mailbox related driver state to its own data structure
      cxl/memdev: Make mailbox functionality optional
      cxl/port: Rename CXL_DECODER_{EXPANDER, ACCELERATOR} => {HOSTONLYMEM, DEVMEM}
      cxl/hdm: Default CXL_DEVTYPE_DEVMEM decoders to CXL_DECODER_DEVMEM
      cxl/region: Manage decoder target_type at decoder-attach time
      cxl/pci: Unconditionally unmask 256B Flit errors
      cxl/port: Enumerate cxl link capabilities
      cxl/memdev: Formalize endpoint port linkage


 drivers/cxl/acpi.c           |    2 
 drivers/cxl/core/hdm.c       |   44 +++++--
 drivers/cxl/core/mbox.c      |  276 ++++++++++++++++++++++--------------------
 drivers/cxl/core/memdev.c    |   52 +++++---
 drivers/cxl/core/pci.c       |  113 +++++++++++++++++
 drivers/cxl/core/pmem.c      |    2 
 drivers/cxl/core/port.c      |   17 ++-
 drivers/cxl/core/region.c    |   14 ++
 drivers/cxl/core/regs.c      |    8 +
 drivers/cxl/cxl.h            |   17 ++-
 drivers/cxl/cxlmem.h         |  114 +++++++++++------
 drivers/cxl/cxlpci.h         |   24 +++-
 drivers/cxl/mem.c            |   10 +-
 drivers/cxl/pci.c            |  132 ++++++++++----------
 drivers/cxl/pmem.c           |   35 +++--
 drivers/cxl/port.c           |    5 +
 drivers/cxl/security.c       |   24 ++--
 tools/testing/cxl/test/cxl.c |    6 -
 tools/testing/cxl/test/mem.c |  129 ++++++++++----------
 19 files changed, 629 insertions(+), 395 deletions(-)

base-commit: 9561de3a55bed6bdd44a12820ba81ec416e705a7

^ permalink raw reply	[flat|nested] 27+ messages in thread

* [PATCH v2 01/12] cxl/regs: Clarify when a 'struct cxl_register_map' is input vs output
  2023-06-15  1:29 [PATCH v2 00/12] Device memory prep Dan Williams
@ 2023-06-15  1:29 ` Dan Williams
  2023-06-15  1:29 ` [PATCH v2 02/12] tools/testing/cxl: Remove unused @cxlds argument Dan Williams
                   ` (10 subsequent siblings)
  11 siblings, 0 replies; 27+ messages in thread
From: Dan Williams @ 2023-06-15  1:29 UTC (permalink / raw)
  To: linux-cxl; +Cc: Jonathan Cameron, Dave Jiang

The @map parameter to cxl_probe_X_registers() is filled in with the
mapping parameters of the register block. The @map parameter to
cxl_map_X_registers() only reads that information to perform the
mapping. Mark @map const for cxl_map_X_registers() to clarify that it is
only an input to those helpers.

Reviewed-by: Jonathan Cameron <Jonathan.Cameron@huawei.com>
Reviewed-by: Dave Jiang <dave.jiang@intel.com>
Signed-off-by: Dan Williams <dan.j.williams@intel.com>
---
 drivers/cxl/core/regs.c |    8 ++++----
 drivers/cxl/cxl.h       |    4 ++--
 2 files changed, 6 insertions(+), 6 deletions(-)

diff --git a/drivers/cxl/core/regs.c b/drivers/cxl/core/regs.c
index 1476a0299c9b..52d1dbeda527 100644
--- a/drivers/cxl/core/regs.c
+++ b/drivers/cxl/core/regs.c
@@ -200,10 +200,10 @@ void __iomem *devm_cxl_iomap_block(struct device *dev, resource_size_t addr,
 }
 
 int cxl_map_component_regs(struct device *dev, struct cxl_component_regs *regs,
-			   struct cxl_register_map *map, unsigned long map_mask)
+			   const struct cxl_register_map *map, unsigned long map_mask)
 {
 	struct mapinfo {
-		struct cxl_reg_map *rmap;
+		const struct cxl_reg_map *rmap;
 		void __iomem **addr;
 	} mapinfo[] = {
 		{ &map->component_map.hdm_decoder, &regs->hdm_decoder },
@@ -233,11 +233,11 @@ EXPORT_SYMBOL_NS_GPL(cxl_map_component_regs, CXL);
 
 int cxl_map_device_regs(struct device *dev,
 			struct cxl_device_regs *regs,
-			struct cxl_register_map *map)
+			const struct cxl_register_map *map)
 {
 	resource_size_t phys_addr = map->resource;
 	struct mapinfo {
-		struct cxl_reg_map *rmap;
+		const struct cxl_reg_map *rmap;
 		void __iomem **addr;
 	} mapinfo[] = {
 		{ &map->device_map.status, &regs->status, },
diff --git a/drivers/cxl/cxl.h b/drivers/cxl/cxl.h
index f93a28538962..dfc94e76c7d6 100644
--- a/drivers/cxl/cxl.h
+++ b/drivers/cxl/cxl.h
@@ -254,10 +254,10 @@ void cxl_probe_component_regs(struct device *dev, void __iomem *base,
 void cxl_probe_device_regs(struct device *dev, void __iomem *base,
 			   struct cxl_device_reg_map *map);
 int cxl_map_component_regs(struct device *dev, struct cxl_component_regs *regs,
-			   struct cxl_register_map *map,
+			   const struct cxl_register_map *map,
 			   unsigned long map_mask);
 int cxl_map_device_regs(struct device *dev, struct cxl_device_regs *regs,
-			struct cxl_register_map *map);
+			const struct cxl_register_map *map);
 
 enum cxl_regloc_type;
 int cxl_find_regblock(struct pci_dev *pdev, enum cxl_regloc_type type,


^ permalink raw reply related	[flat|nested] 27+ messages in thread

* [PATCH v2 02/12] tools/testing/cxl: Remove unused @cxlds argument
  2023-06-15  1:29 [PATCH v2 00/12] Device memory prep Dan Williams
  2023-06-15  1:29 ` [PATCH v2 01/12] cxl/regs: Clarify when a 'struct cxl_register_map' is input vs output Dan Williams
@ 2023-06-15  1:29 ` Dan Williams
  2023-06-15  1:29 ` [PATCH v2 03/12] cxl: Fix kernel-doc warnings Dan Williams
                   ` (9 subsequent siblings)
  11 siblings, 0 replies; 27+ messages in thread
From: Dan Williams @ 2023-06-15  1:29 UTC (permalink / raw)
  To: linux-cxl; +Cc: Jonathan Cameron, Dave Jiang

In preparation for plumbing a 'struct cxl_memdev_state' as a superset of
a 'struct cxl_dev_state' cleanup the usage of @cxlds in the unit test
infrastructure.

Reviewed-by: Jonathan Cameron <Jonathan.Cameron@huawei.com>
Reviewed-by: Dave Jiang <dave.jiang@intel.com>
Signed-off-by: Dan Williams <dan.j.williams@intel.com>
---
 tools/testing/cxl/test/mem.c |   86 +++++++++++++++++++-----------------------
 1 file changed, 39 insertions(+), 47 deletions(-)

diff --git a/tools/testing/cxl/test/mem.c b/tools/testing/cxl/test/mem.c
index 34b48027b3de..bdaf086d994e 100644
--- a/tools/testing/cxl/test/mem.c
+++ b/tools/testing/cxl/test/mem.c
@@ -180,8 +180,7 @@ static void mes_add_event(struct mock_event_store *mes,
 	log->nr_events++;
 }
 
-static int mock_get_event(struct cxl_dev_state *cxlds,
-			  struct cxl_mbox_cmd *cmd)
+static int mock_get_event(struct device *dev, struct cxl_mbox_cmd *cmd)
 {
 	struct cxl_get_event_payload *pl;
 	struct mock_event_log *log;
@@ -201,7 +200,7 @@ static int mock_get_event(struct cxl_dev_state *cxlds,
 
 	memset(cmd->payload_out, 0, cmd->size_out);
 
-	log = event_find_log(cxlds->dev, log_type);
+	log = event_find_log(dev, log_type);
 	if (!log || event_log_empty(log))
 		return 0;
 
@@ -234,8 +233,7 @@ static int mock_get_event(struct cxl_dev_state *cxlds,
 	return 0;
 }
 
-static int mock_clear_event(struct cxl_dev_state *cxlds,
-			    struct cxl_mbox_cmd *cmd)
+static int mock_clear_event(struct device *dev, struct cxl_mbox_cmd *cmd)
 {
 	struct cxl_mbox_clear_event_payload *pl = cmd->payload_in;
 	struct mock_event_log *log;
@@ -246,7 +244,7 @@ static int mock_clear_event(struct cxl_dev_state *cxlds,
 	if (log_type >= CXL_EVENT_TYPE_MAX)
 		return -EINVAL;
 
-	log = event_find_log(cxlds->dev, log_type);
+	log = event_find_log(dev, log_type);
 	if (!log)
 		return 0; /* No mock data in this log */
 
@@ -256,7 +254,7 @@ static int mock_clear_event(struct cxl_dev_state *cxlds,
 	 * However, this is not good behavior for the host so test it.
 	 */
 	if (log->clear_idx + pl->nr_recs > log->cur_idx) {
-		dev_err(cxlds->dev,
+		dev_err(dev,
 			"Attempting to clear more events than returned!\n");
 		return -EINVAL;
 	}
@@ -266,7 +264,7 @@ static int mock_clear_event(struct cxl_dev_state *cxlds,
 	     nr < pl->nr_recs;
 	     nr++, handle++) {
 		if (handle != le16_to_cpu(pl->handles[nr])) {
-			dev_err(cxlds->dev, "Clearing events out of order\n");
+			dev_err(dev, "Clearing events out of order\n");
 			return -EINVAL;
 		}
 	}
@@ -477,7 +475,7 @@ static int mock_get_log(struct cxl_dev_state *cxlds, struct cxl_mbox_cmd *cmd)
 	return 0;
 }
 
-static int mock_rcd_id(struct cxl_dev_state *cxlds, struct cxl_mbox_cmd *cmd)
+static int mock_rcd_id(struct cxl_mbox_cmd *cmd)
 {
 	struct cxl_mbox_identify id = {
 		.fw_revision = { "mock fw v1 " },
@@ -495,7 +493,7 @@ static int mock_rcd_id(struct cxl_dev_state *cxlds, struct cxl_mbox_cmd *cmd)
 	return 0;
 }
 
-static int mock_id(struct cxl_dev_state *cxlds, struct cxl_mbox_cmd *cmd)
+static int mock_id(struct cxl_mbox_cmd *cmd)
 {
 	struct cxl_mbox_identify id = {
 		.fw_revision = { "mock fw v1 " },
@@ -517,8 +515,7 @@ static int mock_id(struct cxl_dev_state *cxlds, struct cxl_mbox_cmd *cmd)
 	return 0;
 }
 
-static int mock_partition_info(struct cxl_dev_state *cxlds,
-			       struct cxl_mbox_cmd *cmd)
+static int mock_partition_info(struct cxl_mbox_cmd *cmd)
 {
 	struct cxl_mbox_get_partition_info pi = {
 		.active_volatile_cap =
@@ -535,11 +532,9 @@ static int mock_partition_info(struct cxl_dev_state *cxlds,
 	return 0;
 }
 
-static int mock_get_security_state(struct cxl_dev_state *cxlds,
+static int mock_get_security_state(struct cxl_mockmem_data *mdata,
 				   struct cxl_mbox_cmd *cmd)
 {
-	struct cxl_mockmem_data *mdata = dev_get_drvdata(cxlds->dev);
-
 	if (cmd->size_in)
 		return -EINVAL;
 
@@ -569,9 +564,9 @@ static void user_plimit_check(struct cxl_mockmem_data *mdata)
 		mdata->security_state |= CXL_PMEM_SEC_STATE_USER_PLIMIT;
 }
 
-static int mock_set_passphrase(struct cxl_dev_state *cxlds, struct cxl_mbox_cmd *cmd)
+static int mock_set_passphrase(struct cxl_mockmem_data *mdata,
+			       struct cxl_mbox_cmd *cmd)
 {
-	struct cxl_mockmem_data *mdata = dev_get_drvdata(cxlds->dev);
 	struct cxl_set_pass *set_pass;
 
 	if (cmd->size_in != sizeof(*set_pass))
@@ -629,9 +624,9 @@ static int mock_set_passphrase(struct cxl_dev_state *cxlds, struct cxl_mbox_cmd
 	return -EINVAL;
 }
 
-static int mock_disable_passphrase(struct cxl_dev_state *cxlds, struct cxl_mbox_cmd *cmd)
+static int mock_disable_passphrase(struct cxl_mockmem_data *mdata,
+				   struct cxl_mbox_cmd *cmd)
 {
-	struct cxl_mockmem_data *mdata = dev_get_drvdata(cxlds->dev);
 	struct cxl_disable_pass *dis_pass;
 
 	if (cmd->size_in != sizeof(*dis_pass))
@@ -700,10 +695,9 @@ static int mock_disable_passphrase(struct cxl_dev_state *cxlds, struct cxl_mbox_
 	return 0;
 }
 
-static int mock_freeze_security(struct cxl_dev_state *cxlds, struct cxl_mbox_cmd *cmd)
+static int mock_freeze_security(struct cxl_mockmem_data *mdata,
+				struct cxl_mbox_cmd *cmd)
 {
-	struct cxl_mockmem_data *mdata = dev_get_drvdata(cxlds->dev);
-
 	if (cmd->size_in != 0)
 		return -EINVAL;
 
@@ -717,10 +711,9 @@ static int mock_freeze_security(struct cxl_dev_state *cxlds, struct cxl_mbox_cmd
 	return 0;
 }
 
-static int mock_unlock_security(struct cxl_dev_state *cxlds, struct cxl_mbox_cmd *cmd)
+static int mock_unlock_security(struct cxl_mockmem_data *mdata,
+				struct cxl_mbox_cmd *cmd)
 {
-	struct cxl_mockmem_data *mdata = dev_get_drvdata(cxlds->dev);
-
 	if (cmd->size_in != NVDIMM_PASSPHRASE_LEN)
 		return -EINVAL;
 
@@ -759,10 +752,9 @@ static int mock_unlock_security(struct cxl_dev_state *cxlds, struct cxl_mbox_cmd
 	return 0;
 }
 
-static int mock_passphrase_secure_erase(struct cxl_dev_state *cxlds,
+static int mock_passphrase_secure_erase(struct cxl_mockmem_data *mdata,
 					struct cxl_mbox_cmd *cmd)
 {
-	struct cxl_mockmem_data *mdata = dev_get_drvdata(cxlds->dev);
 	struct cxl_pass_erase *erase;
 
 	if (cmd->size_in != sizeof(*erase))
@@ -858,10 +850,10 @@ static int mock_passphrase_secure_erase(struct cxl_dev_state *cxlds,
 	return 0;
 }
 
-static int mock_get_lsa(struct cxl_dev_state *cxlds, struct cxl_mbox_cmd *cmd)
+static int mock_get_lsa(struct cxl_mockmem_data *mdata,
+			struct cxl_mbox_cmd *cmd)
 {
 	struct cxl_mbox_get_lsa *get_lsa = cmd->payload_in;
-	struct cxl_mockmem_data *mdata = dev_get_drvdata(cxlds->dev);
 	void *lsa = mdata->lsa;
 	u32 offset, length;
 
@@ -878,10 +870,10 @@ static int mock_get_lsa(struct cxl_dev_state *cxlds, struct cxl_mbox_cmd *cmd)
 	return 0;
 }
 
-static int mock_set_lsa(struct cxl_dev_state *cxlds, struct cxl_mbox_cmd *cmd)
+static int mock_set_lsa(struct cxl_mockmem_data *mdata,
+			struct cxl_mbox_cmd *cmd)
 {
 	struct cxl_mbox_set_lsa *set_lsa = cmd->payload_in;
-	struct cxl_mockmem_data *mdata = dev_get_drvdata(cxlds->dev);
 	void *lsa = mdata->lsa;
 	u32 offset, length;
 
@@ -896,8 +888,7 @@ static int mock_set_lsa(struct cxl_dev_state *cxlds, struct cxl_mbox_cmd *cmd)
 	return 0;
 }
 
-static int mock_health_info(struct cxl_dev_state *cxlds,
-			    struct cxl_mbox_cmd *cmd)
+static int mock_health_info(struct cxl_mbox_cmd *cmd)
 {
 	struct cxl_mbox_health_info health_info = {
 		/* set flags for maint needed, perf degraded, hw replacement */
@@ -1117,6 +1108,7 @@ ATTRIBUTE_GROUPS(cxl_mock_mem_core);
 static int cxl_mock_mbox_send(struct cxl_dev_state *cxlds, struct cxl_mbox_cmd *cmd)
 {
 	struct device *dev = cxlds->dev;
+	struct cxl_mockmem_data *mdata = dev_get_drvdata(dev);
 	int rc = -EIO;
 
 	switch (cmd->opcode) {
@@ -1131,45 +1123,45 @@ static int cxl_mock_mbox_send(struct cxl_dev_state *cxlds, struct cxl_mbox_cmd *
 		break;
 	case CXL_MBOX_OP_IDENTIFY:
 		if (cxlds->rcd)
-			rc = mock_rcd_id(cxlds, cmd);
+			rc = mock_rcd_id(cmd);
 		else
-			rc = mock_id(cxlds, cmd);
+			rc = mock_id(cmd);
 		break;
 	case CXL_MBOX_OP_GET_LSA:
-		rc = mock_get_lsa(cxlds, cmd);
+		rc = mock_get_lsa(mdata, cmd);
 		break;
 	case CXL_MBOX_OP_GET_PARTITION_INFO:
-		rc = mock_partition_info(cxlds, cmd);
+		rc = mock_partition_info(cmd);
 		break;
 	case CXL_MBOX_OP_GET_EVENT_RECORD:
-		rc = mock_get_event(cxlds, cmd);
+		rc = mock_get_event(dev, cmd);
 		break;
 	case CXL_MBOX_OP_CLEAR_EVENT_RECORD:
-		rc = mock_clear_event(cxlds, cmd);
+		rc = mock_clear_event(dev, cmd);
 		break;
 	case CXL_MBOX_OP_SET_LSA:
-		rc = mock_set_lsa(cxlds, cmd);
+		rc = mock_set_lsa(mdata, cmd);
 		break;
 	case CXL_MBOX_OP_GET_HEALTH_INFO:
-		rc = mock_health_info(cxlds, cmd);
+		rc = mock_health_info(cmd);
 		break;
 	case CXL_MBOX_OP_GET_SECURITY_STATE:
-		rc = mock_get_security_state(cxlds, cmd);
+		rc = mock_get_security_state(mdata, cmd);
 		break;
 	case CXL_MBOX_OP_SET_PASSPHRASE:
-		rc = mock_set_passphrase(cxlds, cmd);
+		rc = mock_set_passphrase(mdata, cmd);
 		break;
 	case CXL_MBOX_OP_DISABLE_PASSPHRASE:
-		rc = mock_disable_passphrase(cxlds, cmd);
+		rc = mock_disable_passphrase(mdata, cmd);
 		break;
 	case CXL_MBOX_OP_FREEZE_SECURITY:
-		rc = mock_freeze_security(cxlds, cmd);
+		rc = mock_freeze_security(mdata, cmd);
 		break;
 	case CXL_MBOX_OP_UNLOCK:
-		rc = mock_unlock_security(cxlds, cmd);
+		rc = mock_unlock_security(mdata, cmd);
 		break;
 	case CXL_MBOX_OP_PASSPHRASE_SECURE_ERASE:
-		rc = mock_passphrase_secure_erase(cxlds, cmd);
+		rc = mock_passphrase_secure_erase(mdata, cmd);
 		break;
 	case CXL_MBOX_OP_GET_POISON:
 		rc = mock_get_poison(cxlds, cmd);


^ permalink raw reply related	[flat|nested] 27+ messages in thread

* [PATCH v2 03/12] cxl: Fix kernel-doc warnings
  2023-06-15  1:29 [PATCH v2 00/12] Device memory prep Dan Williams
  2023-06-15  1:29 ` [PATCH v2 01/12] cxl/regs: Clarify when a 'struct cxl_register_map' is input vs output Dan Williams
  2023-06-15  1:29 ` [PATCH v2 02/12] tools/testing/cxl: Remove unused @cxlds argument Dan Williams
@ 2023-06-15  1:29 ` Dan Williams
  2023-06-15 21:28   ` Dave Jiang
  2023-06-22 13:50   ` Jonathan Cameron
  2023-06-15  1:29 ` [PATCH v2 04/12] cxl: Remove leftover attribute documentation in 'struct cxl_dev_state' Dan Williams
                   ` (8 subsequent siblings)
  11 siblings, 2 replies; 27+ messages in thread
From: Dan Williams @ 2023-06-15  1:29 UTC (permalink / raw)
  To: linux-cxl

After Jonathan noticed [1] that 'struct cxl_dev_state' had a kernel-doc
entry without a corresponding struct attribute I ran the kernel-doc
script to see what else might be broken. Fix these warnings:

drivers/cxl/cxlmem.h:199: warning: This comment starts with '/**', but isn't a kernel-doc comment. Refer Documentation/doc-guide/kernel-doc.rst
 * Event Interrupt Policy
drivers/cxl/cxlmem.h:224: warning: Function parameter or member 'buf' not described in 'cxl_event_state'
drivers/cxl/cxlmem.h:224: warning: Function parameter or member 'log_lock' not described in 'cxl_event_state'

Note that scripts/kernel-doc only finds missing kernel-doc entries. It
does not warn on too many kernel-doc entries, i.e. it did not catch the
fact that @info refers to a not present member.

Link: http://lore.kernel.org/r/20230606121054.000069e1@Huawei.com [1]
Signed-off-by: Dan Williams <dan.j.williams@intel.com>
---
 drivers/cxl/cxlmem.h |    6 +++---
 1 file changed, 3 insertions(+), 3 deletions(-)

diff --git a/drivers/cxl/cxlmem.h b/drivers/cxl/cxlmem.h
index a2845a7a69d8..8e4ba5b52902 100644
--- a/drivers/cxl/cxlmem.h
+++ b/drivers/cxl/cxlmem.h
@@ -195,7 +195,7 @@ static inline int cxl_mbox_cmd_rc2errno(struct cxl_mbox_cmd *mbox_cmd)
  */
 #define CXL_CAPACITY_MULTIPLIER SZ_256M
 
-/**
+/*
  * Event Interrupt Policy
  *
  * CXL rev 3.0 section 8.2.9.2.4; Table 8-52
@@ -215,8 +215,8 @@ struct cxl_event_interrupt_policy {
 /**
  * struct cxl_event_state - Event log driver state
  *
- * @event_buf: Buffer to receive event data
- * @event_log_lock: Serialize event_buf and log use
+ * @buf: Buffer to receive event data
+ * @log_lock: Serialize event_buf and log use
  */
 struct cxl_event_state {
 	struct cxl_get_event_payload *buf;


^ permalink raw reply related	[flat|nested] 27+ messages in thread

* [PATCH v2 04/12] cxl: Remove leftover attribute documentation in 'struct cxl_dev_state'
  2023-06-15  1:29 [PATCH v2 00/12] Device memory prep Dan Williams
                   ` (2 preceding siblings ...)
  2023-06-15  1:29 ` [PATCH v2 03/12] cxl: Fix kernel-doc warnings Dan Williams
@ 2023-06-15  1:29 ` Dan Williams
  2023-06-15 21:29   ` Dave Jiang
  2023-06-15  1:30 ` [PATCH v2 05/12] cxl/mbox: Move mailbox related driver state to its own data structure Dan Williams
                   ` (7 subsequent siblings)
  11 siblings, 1 reply; 27+ messages in thread
From: Dan Williams @ 2023-06-15  1:29 UTC (permalink / raw)
  To: linux-cxl; +Cc: Jonathan Cameron

commit 14d788740774 ("cxl/mem: Consolidate CXL DVSEC Range enumeration
in the core")

...removed @info from 'struct cxl_dev_state', but neglected to remove
the corresponding kernel-doc entry. Complete the removal.

Reported-by: Jonathan Cameron <Jonathan.Cameron@Huawei.com>
Closes: http://lore.kernel.org/r/20230606121054.000069e1@Huawei.com
Signed-off-by: Dan Williams <dan.j.williams@intel.com>
---
 drivers/cxl/cxlmem.h |    1 -
 1 file changed, 1 deletion(-)

diff --git a/drivers/cxl/cxlmem.h b/drivers/cxl/cxlmem.h
index 8e4ba5b52902..66896fc6c43f 100644
--- a/drivers/cxl/cxlmem.h
+++ b/drivers/cxl/cxlmem.h
@@ -287,7 +287,6 @@ struct cxl_poison_state {
  * @next_volatile_bytes: volatile capacity change pending device reset
  * @next_persistent_bytes: persistent capacity change pending device reset
  * @component_reg_phys: register base of component registers
- * @info: Cached DVSEC information about the device.
  * @serial: PCIe Device Serial Number
  * @event: event log driver state
  * @poison: poison driver state info


^ permalink raw reply related	[flat|nested] 27+ messages in thread

* [PATCH v2 05/12] cxl/mbox: Move mailbox related driver state to its own data structure
  2023-06-15  1:29 [PATCH v2 00/12] Device memory prep Dan Williams
                   ` (3 preceding siblings ...)
  2023-06-15  1:29 ` [PATCH v2 04/12] cxl: Remove leftover attribute documentation in 'struct cxl_dev_state' Dan Williams
@ 2023-06-15  1:30 ` Dan Williams
  2023-06-15  1:30 ` [PATCH v2 06/12] cxl/memdev: Make mailbox functionality optional Dan Williams
                   ` (6 subsequent siblings)
  11 siblings, 0 replies; 27+ messages in thread
From: Dan Williams @ 2023-06-15  1:30 UTC (permalink / raw)
  To: linux-cxl; +Cc: Jonathan Cameron, Dave Jiang

'struct cxl_dev_state' makes too many assumptions about the capabilities
of a CXL device. In particular it assumes a CXL device has a mailbox and
all of the infrastructure and state that comes along with that.

In preparation for supporting accelerator / Type-2 devices that may not
have a mailbox and in general maintain a minimal core context structure,
make mailbox functionality a super-set of  'struct cxl_dev_state' with
'struct cxl_memdev_state'.

With this reorganization it allows for CXL devices that support HDM
decoder mapping, but not other general-expander / Type-3 capabilities,
to only enable that subset without the rest of the mailbox
infrastructure coming along for the ride.

Reviewed-by: Jonathan Cameron <Jonathan.Cameron@huawei.com>
Reviewed-by: Dave Jiang <dave.jiang@intel.com>
Signed-off-by: Dan Williams <dan.j.williams@intel.com>
---
 drivers/cxl/core/mbox.c      |  275 ++++++++++++++++++++++--------------------
 drivers/cxl/core/memdev.c    |   38 +++---
 drivers/cxl/cxlmem.h         |   87 ++++++++-----
 drivers/cxl/mem.c            |   10 +-
 drivers/cxl/pci.c            |  114 +++++++++--------
 drivers/cxl/pmem.c           |   35 +++--
 drivers/cxl/security.c       |   24 ++--
 tools/testing/cxl/test/mem.c |   43 ++++---
 8 files changed, 336 insertions(+), 290 deletions(-)

diff --git a/drivers/cxl/core/mbox.c b/drivers/cxl/core/mbox.c
index bea9cf31a12d..ab9d455e8579 100644
--- a/drivers/cxl/core/mbox.c
+++ b/drivers/cxl/core/mbox.c
@@ -182,7 +182,7 @@ static const char *cxl_mem_opcode_to_name(u16 opcode)
 
 /**
  * cxl_internal_send_cmd() - Kernel internal interface to send a mailbox command
- * @cxlds: The device data for the operation
+ * @mds: The driver data for the operation
  * @mbox_cmd: initialized command to execute
  *
  * Context: Any context.
@@ -198,19 +198,19 @@ static const char *cxl_mem_opcode_to_name(u16 opcode)
  * error. While this distinction can be useful for commands from userspace, the
  * kernel will only be able to use results when both are successful.
  */
-int cxl_internal_send_cmd(struct cxl_dev_state *cxlds,
+int cxl_internal_send_cmd(struct cxl_memdev_state *mds,
 			  struct cxl_mbox_cmd *mbox_cmd)
 {
 	size_t out_size, min_out;
 	int rc;
 
-	if (mbox_cmd->size_in > cxlds->payload_size ||
-	    mbox_cmd->size_out > cxlds->payload_size)
+	if (mbox_cmd->size_in > mds->payload_size ||
+	    mbox_cmd->size_out > mds->payload_size)
 		return -E2BIG;
 
 	out_size = mbox_cmd->size_out;
 	min_out = mbox_cmd->min_out;
-	rc = cxlds->mbox_send(cxlds, mbox_cmd);
+	rc = mds->mbox_send(mds, mbox_cmd);
 	/*
 	 * EIO is reserved for a payload size mismatch and mbox_send()
 	 * may not return this error.
@@ -297,7 +297,7 @@ static bool cxl_payload_from_user_allowed(u16 opcode, void *payload_in)
 }
 
 static int cxl_mbox_cmd_ctor(struct cxl_mbox_cmd *mbox,
-			     struct cxl_dev_state *cxlds, u16 opcode,
+			     struct cxl_memdev_state *mds, u16 opcode,
 			     size_t in_size, size_t out_size, u64 in_payload)
 {
 	*mbox = (struct cxl_mbox_cmd) {
@@ -312,7 +312,7 @@ static int cxl_mbox_cmd_ctor(struct cxl_mbox_cmd *mbox,
 			return PTR_ERR(mbox->payload_in);
 
 		if (!cxl_payload_from_user_allowed(opcode, mbox->payload_in)) {
-			dev_dbg(cxlds->dev, "%s: input payload not allowed\n",
+			dev_dbg(mds->cxlds.dev, "%s: input payload not allowed\n",
 				cxl_mem_opcode_to_name(opcode));
 			kvfree(mbox->payload_in);
 			return -EBUSY;
@@ -321,7 +321,7 @@ static int cxl_mbox_cmd_ctor(struct cxl_mbox_cmd *mbox,
 
 	/* Prepare to handle a full payload for variable sized output */
 	if (out_size == CXL_VARIABLE_PAYLOAD)
-		mbox->size_out = cxlds->payload_size;
+		mbox->size_out = mds->payload_size;
 	else
 		mbox->size_out = out_size;
 
@@ -343,7 +343,7 @@ static void cxl_mbox_cmd_dtor(struct cxl_mbox_cmd *mbox)
 
 static int cxl_to_mem_cmd_raw(struct cxl_mem_command *mem_cmd,
 			      const struct cxl_send_command *send_cmd,
-			      struct cxl_dev_state *cxlds)
+			      struct cxl_memdev_state *mds)
 {
 	if (send_cmd->raw.rsvd)
 		return -EINVAL;
@@ -353,13 +353,13 @@ static int cxl_to_mem_cmd_raw(struct cxl_mem_command *mem_cmd,
 	 * gets passed along without further checking, so it must be
 	 * validated here.
 	 */
-	if (send_cmd->out.size > cxlds->payload_size)
+	if (send_cmd->out.size > mds->payload_size)
 		return -EINVAL;
 
 	if (!cxl_mem_raw_command_allowed(send_cmd->raw.opcode))
 		return -EPERM;
 
-	dev_WARN_ONCE(cxlds->dev, true, "raw command path used\n");
+	dev_WARN_ONCE(mds->cxlds.dev, true, "raw command path used\n");
 
 	*mem_cmd = (struct cxl_mem_command) {
 		.info = {
@@ -375,7 +375,7 @@ static int cxl_to_mem_cmd_raw(struct cxl_mem_command *mem_cmd,
 
 static int cxl_to_mem_cmd(struct cxl_mem_command *mem_cmd,
 			  const struct cxl_send_command *send_cmd,
-			  struct cxl_dev_state *cxlds)
+			  struct cxl_memdev_state *mds)
 {
 	struct cxl_mem_command *c = &cxl_mem_commands[send_cmd->id];
 	const struct cxl_command_info *info = &c->info;
@@ -390,11 +390,11 @@ static int cxl_to_mem_cmd(struct cxl_mem_command *mem_cmd,
 		return -EINVAL;
 
 	/* Check that the command is enabled for hardware */
-	if (!test_bit(info->id, cxlds->enabled_cmds))
+	if (!test_bit(info->id, mds->enabled_cmds))
 		return -ENOTTY;
 
 	/* Check that the command is not claimed for exclusive kernel use */
-	if (test_bit(info->id, cxlds->exclusive_cmds))
+	if (test_bit(info->id, mds->exclusive_cmds))
 		return -EBUSY;
 
 	/* Check the input buffer is the expected size */
@@ -423,7 +423,7 @@ static int cxl_to_mem_cmd(struct cxl_mem_command *mem_cmd,
 /**
  * cxl_validate_cmd_from_user() - Check fields for CXL_MEM_SEND_COMMAND.
  * @mbox_cmd: Sanitized and populated &struct cxl_mbox_cmd.
- * @cxlds: The device data for the operation
+ * @mds: The driver data for the operation
  * @send_cmd: &struct cxl_send_command copied in from userspace.
  *
  * Return:
@@ -438,7 +438,7 @@ static int cxl_to_mem_cmd(struct cxl_mem_command *mem_cmd,
  * safe to send to the hardware.
  */
 static int cxl_validate_cmd_from_user(struct cxl_mbox_cmd *mbox_cmd,
-				      struct cxl_dev_state *cxlds,
+				      struct cxl_memdev_state *mds,
 				      const struct cxl_send_command *send_cmd)
 {
 	struct cxl_mem_command mem_cmd;
@@ -452,20 +452,20 @@ static int cxl_validate_cmd_from_user(struct cxl_mbox_cmd *mbox_cmd,
 	 * supports, but output can be arbitrarily large (simply write out as
 	 * much data as the hardware provides).
 	 */
-	if (send_cmd->in.size > cxlds->payload_size)
+	if (send_cmd->in.size > mds->payload_size)
 		return -EINVAL;
 
 	/* Sanitize and construct a cxl_mem_command */
 	if (send_cmd->id == CXL_MEM_COMMAND_ID_RAW)
-		rc = cxl_to_mem_cmd_raw(&mem_cmd, send_cmd, cxlds);
+		rc = cxl_to_mem_cmd_raw(&mem_cmd, send_cmd, mds);
 	else
-		rc = cxl_to_mem_cmd(&mem_cmd, send_cmd, cxlds);
+		rc = cxl_to_mem_cmd(&mem_cmd, send_cmd, mds);
 
 	if (rc)
 		return rc;
 
 	/* Sanitize and construct a cxl_mbox_cmd */
-	return cxl_mbox_cmd_ctor(mbox_cmd, cxlds, mem_cmd.opcode,
+	return cxl_mbox_cmd_ctor(mbox_cmd, mds, mem_cmd.opcode,
 				 mem_cmd.info.size_in, mem_cmd.info.size_out,
 				 send_cmd->in.payload);
 }
@@ -473,6 +473,7 @@ static int cxl_validate_cmd_from_user(struct cxl_mbox_cmd *mbox_cmd,
 int cxl_query_cmd(struct cxl_memdev *cxlmd,
 		  struct cxl_mem_query_commands __user *q)
 {
+	struct cxl_memdev_state *mds = to_cxl_memdev_state(cxlmd->cxlds);
 	struct device *dev = &cxlmd->dev;
 	struct cxl_mem_command *cmd;
 	u32 n_commands;
@@ -494,9 +495,9 @@ int cxl_query_cmd(struct cxl_memdev *cxlmd,
 	cxl_for_each_cmd(cmd) {
 		struct cxl_command_info info = cmd->info;
 
-		if (test_bit(info.id, cxlmd->cxlds->enabled_cmds))
+		if (test_bit(info.id, mds->enabled_cmds))
 			info.flags |= CXL_MEM_COMMAND_FLAG_ENABLED;
-		if (test_bit(info.id, cxlmd->cxlds->exclusive_cmds))
+		if (test_bit(info.id, mds->exclusive_cmds))
 			info.flags |= CXL_MEM_COMMAND_FLAG_EXCLUSIVE;
 
 		if (copy_to_user(&q->commands[j++], &info, sizeof(info)))
@@ -511,7 +512,7 @@ int cxl_query_cmd(struct cxl_memdev *cxlmd,
 
 /**
  * handle_mailbox_cmd_from_user() - Dispatch a mailbox command for userspace.
- * @cxlds: The device data for the operation
+ * @mds: The driver data for the operation
  * @mbox_cmd: The validated mailbox command.
  * @out_payload: Pointer to userspace's output payload.
  * @size_out: (Input) Max payload size to copy out.
@@ -532,12 +533,12 @@ int cxl_query_cmd(struct cxl_memdev *cxlmd,
  *
  * See cxl_send_cmd().
  */
-static int handle_mailbox_cmd_from_user(struct cxl_dev_state *cxlds,
+static int handle_mailbox_cmd_from_user(struct cxl_memdev_state *mds,
 					struct cxl_mbox_cmd *mbox_cmd,
 					u64 out_payload, s32 *size_out,
 					u32 *retval)
 {
-	struct device *dev = cxlds->dev;
+	struct device *dev = mds->cxlds.dev;
 	int rc;
 
 	dev_dbg(dev,
@@ -547,7 +548,7 @@ static int handle_mailbox_cmd_from_user(struct cxl_dev_state *cxlds,
 		cxl_mem_opcode_to_name(mbox_cmd->opcode),
 		mbox_cmd->opcode, mbox_cmd->size_in);
 
-	rc = cxlds->mbox_send(cxlds, mbox_cmd);
+	rc = mds->mbox_send(mds, mbox_cmd);
 	if (rc)
 		goto out;
 
@@ -576,7 +577,7 @@ static int handle_mailbox_cmd_from_user(struct cxl_dev_state *cxlds,
 
 int cxl_send_cmd(struct cxl_memdev *cxlmd, struct cxl_send_command __user *s)
 {
-	struct cxl_dev_state *cxlds = cxlmd->cxlds;
+	struct cxl_memdev_state *mds = to_cxl_memdev_state(cxlmd->cxlds);
 	struct device *dev = &cxlmd->dev;
 	struct cxl_send_command send;
 	struct cxl_mbox_cmd mbox_cmd;
@@ -587,11 +588,11 @@ int cxl_send_cmd(struct cxl_memdev *cxlmd, struct cxl_send_command __user *s)
 	if (copy_from_user(&send, s, sizeof(send)))
 		return -EFAULT;
 
-	rc = cxl_validate_cmd_from_user(&mbox_cmd, cxlmd->cxlds, &send);
+	rc = cxl_validate_cmd_from_user(&mbox_cmd, mds, &send);
 	if (rc)
 		return rc;
 
-	rc = handle_mailbox_cmd_from_user(cxlds, &mbox_cmd, send.out.payload,
+	rc = handle_mailbox_cmd_from_user(mds, &mbox_cmd, send.out.payload,
 					  &send.out.size, &send.retval);
 	if (rc)
 		return rc;
@@ -602,13 +603,14 @@ int cxl_send_cmd(struct cxl_memdev *cxlmd, struct cxl_send_command __user *s)
 	return 0;
 }
 
-static int cxl_xfer_log(struct cxl_dev_state *cxlds, uuid_t *uuid, u32 *size, u8 *out)
+static int cxl_xfer_log(struct cxl_memdev_state *mds, uuid_t *uuid,
+			u32 *size, u8 *out)
 {
 	u32 remaining = *size;
 	u32 offset = 0;
 
 	while (remaining) {
-		u32 xfer_size = min_t(u32, remaining, cxlds->payload_size);
+		u32 xfer_size = min_t(u32, remaining, mds->payload_size);
 		struct cxl_mbox_cmd mbox_cmd;
 		struct cxl_mbox_get_log log;
 		int rc;
@@ -627,7 +629,7 @@ static int cxl_xfer_log(struct cxl_dev_state *cxlds, uuid_t *uuid, u32 *size, u8
 			.payload_out = out,
 		};
 
-		rc = cxl_internal_send_cmd(cxlds, &mbox_cmd);
+		rc = cxl_internal_send_cmd(mds, &mbox_cmd);
 
 		/*
 		 * The output payload length that indicates the number
@@ -654,17 +656,18 @@ static int cxl_xfer_log(struct cxl_dev_state *cxlds, uuid_t *uuid, u32 *size, u8
 
 /**
  * cxl_walk_cel() - Walk through the Command Effects Log.
- * @cxlds: The device data for the operation
+ * @mds: The driver data for the operation
  * @size: Length of the Command Effects Log.
  * @cel: CEL
  *
  * Iterate over each entry in the CEL and determine if the driver supports the
  * command. If so, the command is enabled for the device and can be used later.
  */
-static void cxl_walk_cel(struct cxl_dev_state *cxlds, size_t size, u8 *cel)
+static void cxl_walk_cel(struct cxl_memdev_state *mds, size_t size, u8 *cel)
 {
 	struct cxl_cel_entry *cel_entry;
 	const int cel_entries = size / sizeof(*cel_entry);
+	struct device *dev = mds->cxlds.dev;
 	int i;
 
 	cel_entry = (struct cxl_cel_entry *) cel;
@@ -674,39 +677,39 @@ static void cxl_walk_cel(struct cxl_dev_state *cxlds, size_t size, u8 *cel)
 		struct cxl_mem_command *cmd = cxl_mem_find_command(opcode);
 
 		if (!cmd && !cxl_is_poison_command(opcode)) {
-			dev_dbg(cxlds->dev,
+			dev_dbg(dev,
 				"Opcode 0x%04x unsupported by driver\n", opcode);
 			continue;
 		}
 
 		if (cmd)
-			set_bit(cmd->info.id, cxlds->enabled_cmds);
+			set_bit(cmd->info.id, mds->enabled_cmds);
 
 		if (cxl_is_poison_command(opcode))
-			cxl_set_poison_cmd_enabled(&cxlds->poison, opcode);
+			cxl_set_poison_cmd_enabled(&mds->poison, opcode);
 
-		dev_dbg(cxlds->dev, "Opcode 0x%04x enabled\n", opcode);
+		dev_dbg(dev, "Opcode 0x%04x enabled\n", opcode);
 	}
 }
 
-static struct cxl_mbox_get_supported_logs *cxl_get_gsl(struct cxl_dev_state *cxlds)
+static struct cxl_mbox_get_supported_logs *cxl_get_gsl(struct cxl_memdev_state *mds)
 {
 	struct cxl_mbox_get_supported_logs *ret;
 	struct cxl_mbox_cmd mbox_cmd;
 	int rc;
 
-	ret = kvmalloc(cxlds->payload_size, GFP_KERNEL);
+	ret = kvmalloc(mds->payload_size, GFP_KERNEL);
 	if (!ret)
 		return ERR_PTR(-ENOMEM);
 
 	mbox_cmd = (struct cxl_mbox_cmd) {
 		.opcode = CXL_MBOX_OP_GET_SUPPORTED_LOGS,
-		.size_out = cxlds->payload_size,
+		.size_out = mds->payload_size,
 		.payload_out = ret,
 		/* At least the record number field must be valid */
 		.min_out = 2,
 	};
-	rc = cxl_internal_send_cmd(cxlds, &mbox_cmd);
+	rc = cxl_internal_send_cmd(mds, &mbox_cmd);
 	if (rc < 0) {
 		kvfree(ret);
 		return ERR_PTR(rc);
@@ -729,22 +732,22 @@ static const uuid_t log_uuid[] = {
 
 /**
  * cxl_enumerate_cmds() - Enumerate commands for a device.
- * @cxlds: The device data for the operation
+ * @mds: The driver data for the operation
  *
  * Returns 0 if enumerate completed successfully.
  *
  * CXL devices have optional support for certain commands. This function will
  * determine the set of supported commands for the hardware and update the
- * enabled_cmds bitmap in the @cxlds.
+ * enabled_cmds bitmap in the @mds.
  */
-int cxl_enumerate_cmds(struct cxl_dev_state *cxlds)
+int cxl_enumerate_cmds(struct cxl_memdev_state *mds)
 {
 	struct cxl_mbox_get_supported_logs *gsl;
-	struct device *dev = cxlds->dev;
+	struct device *dev = mds->cxlds.dev;
 	struct cxl_mem_command *cmd;
 	int i, rc;
 
-	gsl = cxl_get_gsl(cxlds);
+	gsl = cxl_get_gsl(mds);
 	if (IS_ERR(gsl))
 		return PTR_ERR(gsl);
 
@@ -765,19 +768,19 @@ int cxl_enumerate_cmds(struct cxl_dev_state *cxlds)
 			goto out;
 		}
 
-		rc = cxl_xfer_log(cxlds, &uuid, &size, log);
+		rc = cxl_xfer_log(mds, &uuid, &size, log);
 		if (rc) {
 			kvfree(log);
 			goto out;
 		}
 
-		cxl_walk_cel(cxlds, size, log);
+		cxl_walk_cel(mds, size, log);
 		kvfree(log);
 
 		/* In case CEL was bogus, enable some default commands. */
 		cxl_for_each_cmd(cmd)
 			if (cmd->flags & CXL_CMD_FLAG_FORCE_ENABLE)
-				set_bit(cmd->info.id, cxlds->enabled_cmds);
+				set_bit(cmd->info.id, mds->enabled_cmds);
 
 		/* Found the required CEL */
 		rc = 0;
@@ -838,7 +841,7 @@ static void cxl_event_trace_record(const struct cxl_memdev *cxlmd,
 	}
 }
 
-static int cxl_clear_event_record(struct cxl_dev_state *cxlds,
+static int cxl_clear_event_record(struct cxl_memdev_state *mds,
 				  enum cxl_event_log_type log,
 				  struct cxl_get_event_payload *get_pl)
 {
@@ -852,9 +855,9 @@ static int cxl_clear_event_record(struct cxl_dev_state *cxlds,
 	int i;
 
 	/* Payload size may limit the max handles */
-	if (pl_size > cxlds->payload_size) {
-		max_handles = (cxlds->payload_size - sizeof(*payload)) /
-				sizeof(__le16);
+	if (pl_size > mds->payload_size) {
+		max_handles = (mds->payload_size - sizeof(*payload)) /
+			      sizeof(__le16);
 		pl_size = struct_size(payload, handles, max_handles);
 	}
 
@@ -879,12 +882,12 @@ static int cxl_clear_event_record(struct cxl_dev_state *cxlds,
 	i = 0;
 	for (cnt = 0; cnt < total; cnt++) {
 		payload->handles[i++] = get_pl->records[cnt].hdr.handle;
-		dev_dbg(cxlds->dev, "Event log '%d': Clearing %u\n",
-			log, le16_to_cpu(payload->handles[i]));
+		dev_dbg(mds->cxlds.dev, "Event log '%d': Clearing %u\n", log,
+			le16_to_cpu(payload->handles[i]));
 
 		if (i == max_handles) {
 			payload->nr_recs = i;
-			rc = cxl_internal_send_cmd(cxlds, &mbox_cmd);
+			rc = cxl_internal_send_cmd(mds, &mbox_cmd);
 			if (rc)
 				goto free_pl;
 			i = 0;
@@ -895,7 +898,7 @@ static int cxl_clear_event_record(struct cxl_dev_state *cxlds,
 	if (i) {
 		payload->nr_recs = i;
 		mbox_cmd.size_in = struct_size(payload, handles, i);
-		rc = cxl_internal_send_cmd(cxlds, &mbox_cmd);
+		rc = cxl_internal_send_cmd(mds, &mbox_cmd);
 		if (rc)
 			goto free_pl;
 	}
@@ -905,32 +908,34 @@ static int cxl_clear_event_record(struct cxl_dev_state *cxlds,
 	return rc;
 }
 
-static void cxl_mem_get_records_log(struct cxl_dev_state *cxlds,
+static void cxl_mem_get_records_log(struct cxl_memdev_state *mds,
 				    enum cxl_event_log_type type)
 {
+	struct cxl_memdev *cxlmd = mds->cxlds.cxlmd;
+	struct device *dev = mds->cxlds.dev;
 	struct cxl_get_event_payload *payload;
 	struct cxl_mbox_cmd mbox_cmd;
 	u8 log_type = type;
 	u16 nr_rec;
 
-	mutex_lock(&cxlds->event.log_lock);
-	payload = cxlds->event.buf;
+	mutex_lock(&mds->event.log_lock);
+	payload = mds->event.buf;
 
 	mbox_cmd = (struct cxl_mbox_cmd) {
 		.opcode = CXL_MBOX_OP_GET_EVENT_RECORD,
 		.payload_in = &log_type,
 		.size_in = sizeof(log_type),
 		.payload_out = payload,
-		.size_out = cxlds->payload_size,
+		.size_out = mds->payload_size,
 		.min_out = struct_size(payload, records, 0),
 	};
 
 	do {
 		int rc, i;
 
-		rc = cxl_internal_send_cmd(cxlds, &mbox_cmd);
+		rc = cxl_internal_send_cmd(mds, &mbox_cmd);
 		if (rc) {
-			dev_err_ratelimited(cxlds->dev,
+			dev_err_ratelimited(dev,
 				"Event log '%d': Failed to query event records : %d",
 				type, rc);
 			break;
@@ -941,27 +946,27 @@ static void cxl_mem_get_records_log(struct cxl_dev_state *cxlds,
 			break;
 
 		for (i = 0; i < nr_rec; i++)
-			cxl_event_trace_record(cxlds->cxlmd, type,
+			cxl_event_trace_record(cxlmd, type,
 					       &payload->records[i]);
 
 		if (payload->flags & CXL_GET_EVENT_FLAG_OVERFLOW)
-			trace_cxl_overflow(cxlds->cxlmd, type, payload);
+			trace_cxl_overflow(cxlmd, type, payload);
 
-		rc = cxl_clear_event_record(cxlds, type, payload);
+		rc = cxl_clear_event_record(mds, type, payload);
 		if (rc) {
-			dev_err_ratelimited(cxlds->dev,
+			dev_err_ratelimited(dev,
 				"Event log '%d': Failed to clear events : %d",
 				type, rc);
 			break;
 		}
 	} while (nr_rec);
 
-	mutex_unlock(&cxlds->event.log_lock);
+	mutex_unlock(&mds->event.log_lock);
 }
 
 /**
  * cxl_mem_get_event_records - Get Event Records from the device
- * @cxlds: The device data for the operation
+ * @mds: The driver data for the operation
  * @status: Event Status register value identifying which events are available.
  *
  * Retrieve all event records available on the device, report them as trace
@@ -970,24 +975,24 @@ static void cxl_mem_get_records_log(struct cxl_dev_state *cxlds,
  * See CXL rev 3.0 @8.2.9.2.2 Get Event Records
  * See CXL rev 3.0 @8.2.9.2.3 Clear Event Records
  */
-void cxl_mem_get_event_records(struct cxl_dev_state *cxlds, u32 status)
+void cxl_mem_get_event_records(struct cxl_memdev_state *mds, u32 status)
 {
-	dev_dbg(cxlds->dev, "Reading event logs: %x\n", status);
+	dev_dbg(mds->cxlds.dev, "Reading event logs: %x\n", status);
 
 	if (status & CXLDEV_EVENT_STATUS_FATAL)
-		cxl_mem_get_records_log(cxlds, CXL_EVENT_TYPE_FATAL);
+		cxl_mem_get_records_log(mds, CXL_EVENT_TYPE_FATAL);
 	if (status & CXLDEV_EVENT_STATUS_FAIL)
-		cxl_mem_get_records_log(cxlds, CXL_EVENT_TYPE_FAIL);
+		cxl_mem_get_records_log(mds, CXL_EVENT_TYPE_FAIL);
 	if (status & CXLDEV_EVENT_STATUS_WARN)
-		cxl_mem_get_records_log(cxlds, CXL_EVENT_TYPE_WARN);
+		cxl_mem_get_records_log(mds, CXL_EVENT_TYPE_WARN);
 	if (status & CXLDEV_EVENT_STATUS_INFO)
-		cxl_mem_get_records_log(cxlds, CXL_EVENT_TYPE_INFO);
+		cxl_mem_get_records_log(mds, CXL_EVENT_TYPE_INFO);
 }
 EXPORT_SYMBOL_NS_GPL(cxl_mem_get_event_records, CXL);
 
 /**
  * cxl_mem_get_partition_info - Get partition info
- * @cxlds: The device data for the operation
+ * @mds: The driver data for the operation
  *
  * Retrieve the current partition info for the device specified.  The active
  * values are the current capacity in bytes.  If not 0, the 'next' values are
@@ -997,7 +1002,7 @@ EXPORT_SYMBOL_NS_GPL(cxl_mem_get_event_records, CXL);
  *
  * See CXL @8.2.9.5.2.1 Get Partition Info
  */
-static int cxl_mem_get_partition_info(struct cxl_dev_state *cxlds)
+static int cxl_mem_get_partition_info(struct cxl_memdev_state *mds)
 {
 	struct cxl_mbox_get_partition_info pi;
 	struct cxl_mbox_cmd mbox_cmd;
@@ -1008,17 +1013,17 @@ static int cxl_mem_get_partition_info(struct cxl_dev_state *cxlds)
 		.size_out = sizeof(pi),
 		.payload_out = &pi,
 	};
-	rc = cxl_internal_send_cmd(cxlds, &mbox_cmd);
+	rc = cxl_internal_send_cmd(mds, &mbox_cmd);
 	if (rc)
 		return rc;
 
-	cxlds->active_volatile_bytes =
+	mds->active_volatile_bytes =
 		le64_to_cpu(pi.active_volatile_cap) * CXL_CAPACITY_MULTIPLIER;
-	cxlds->active_persistent_bytes =
+	mds->active_persistent_bytes =
 		le64_to_cpu(pi.active_persistent_cap) * CXL_CAPACITY_MULTIPLIER;
-	cxlds->next_volatile_bytes =
+	mds->next_volatile_bytes =
 		le64_to_cpu(pi.next_volatile_cap) * CXL_CAPACITY_MULTIPLIER;
-	cxlds->next_persistent_bytes =
+	mds->next_persistent_bytes =
 		le64_to_cpu(pi.next_volatile_cap) * CXL_CAPACITY_MULTIPLIER;
 
 	return 0;
@@ -1026,14 +1031,14 @@ static int cxl_mem_get_partition_info(struct cxl_dev_state *cxlds)
 
 /**
  * cxl_dev_state_identify() - Send the IDENTIFY command to the device.
- * @cxlds: The device data for the operation
+ * @mds: The driver data for the operation
  *
  * Return: 0 if identify was executed successfully or media not ready.
  *
  * This will dispatch the identify command to the device and on success populate
  * structures to be exported to sysfs.
  */
-int cxl_dev_state_identify(struct cxl_dev_state *cxlds)
+int cxl_dev_state_identify(struct cxl_memdev_state *mds)
 {
 	/* See CXL 2.0 Table 175 Identify Memory Device Output Payload */
 	struct cxl_mbox_identify id;
@@ -1041,7 +1046,7 @@ int cxl_dev_state_identify(struct cxl_dev_state *cxlds)
 	u32 val;
 	int rc;
 
-	if (!cxlds->media_ready)
+	if (!mds->cxlds.media_ready)
 		return 0;
 
 	mbox_cmd = (struct cxl_mbox_cmd) {
@@ -1049,25 +1054,26 @@ int cxl_dev_state_identify(struct cxl_dev_state *cxlds)
 		.size_out = sizeof(id),
 		.payload_out = &id,
 	};
-	rc = cxl_internal_send_cmd(cxlds, &mbox_cmd);
+	rc = cxl_internal_send_cmd(mds, &mbox_cmd);
 	if (rc < 0)
 		return rc;
 
-	cxlds->total_bytes =
+	mds->total_bytes =
 		le64_to_cpu(id.total_capacity) * CXL_CAPACITY_MULTIPLIER;
-	cxlds->volatile_only_bytes =
+	mds->volatile_only_bytes =
 		le64_to_cpu(id.volatile_capacity) * CXL_CAPACITY_MULTIPLIER;
-	cxlds->persistent_only_bytes =
+	mds->persistent_only_bytes =
 		le64_to_cpu(id.persistent_capacity) * CXL_CAPACITY_MULTIPLIER;
-	cxlds->partition_align_bytes =
+	mds->partition_align_bytes =
 		le64_to_cpu(id.partition_align) * CXL_CAPACITY_MULTIPLIER;
 
-	cxlds->lsa_size = le32_to_cpu(id.lsa_size);
-	memcpy(cxlds->firmware_version, id.fw_revision, sizeof(id.fw_revision));
+	mds->lsa_size = le32_to_cpu(id.lsa_size);
+	memcpy(mds->firmware_version, id.fw_revision,
+	       sizeof(id.fw_revision));
 
-	if (test_bit(CXL_POISON_ENABLED_LIST, cxlds->poison.enabled_cmds)) {
+	if (test_bit(CXL_POISON_ENABLED_LIST, mds->poison.enabled_cmds)) {
 		val = get_unaligned_le24(id.poison_list_max_mer);
-		cxlds->poison.max_errors = min_t(u32, val, CXL_POISON_LIST_MAX);
+		mds->poison.max_errors = min_t(u32, val, CXL_POISON_LIST_MAX);
 	}
 
 	return 0;
@@ -1100,8 +1106,9 @@ static int add_dpa_res(struct device *dev, struct resource *parent,
 	return 0;
 }
 
-int cxl_mem_create_range_info(struct cxl_dev_state *cxlds)
+int cxl_mem_create_range_info(struct cxl_memdev_state *mds)
 {
+	struct cxl_dev_state *cxlds = &mds->cxlds;
 	struct device *dev = cxlds->dev;
 	int rc;
 
@@ -1113,35 +1120,35 @@ int cxl_mem_create_range_info(struct cxl_dev_state *cxlds)
 	}
 
 	cxlds->dpa_res =
-		(struct resource)DEFINE_RES_MEM(0, cxlds->total_bytes);
+		(struct resource)DEFINE_RES_MEM(0, mds->total_bytes);
 
-	if (cxlds->partition_align_bytes == 0) {
+	if (mds->partition_align_bytes == 0) {
 		rc = add_dpa_res(dev, &cxlds->dpa_res, &cxlds->ram_res, 0,
-				 cxlds->volatile_only_bytes, "ram");
+				 mds->volatile_only_bytes, "ram");
 		if (rc)
 			return rc;
 		return add_dpa_res(dev, &cxlds->dpa_res, &cxlds->pmem_res,
-				   cxlds->volatile_only_bytes,
-				   cxlds->persistent_only_bytes, "pmem");
+				   mds->volatile_only_bytes,
+				   mds->persistent_only_bytes, "pmem");
 	}
 
-	rc = cxl_mem_get_partition_info(cxlds);
+	rc = cxl_mem_get_partition_info(mds);
 	if (rc) {
 		dev_err(dev, "Failed to query partition information\n");
 		return rc;
 	}
 
 	rc = add_dpa_res(dev, &cxlds->dpa_res, &cxlds->ram_res, 0,
-			 cxlds->active_volatile_bytes, "ram");
+			 mds->active_volatile_bytes, "ram");
 	if (rc)
 		return rc;
 	return add_dpa_res(dev, &cxlds->dpa_res, &cxlds->pmem_res,
-			   cxlds->active_volatile_bytes,
-			   cxlds->active_persistent_bytes, "pmem");
+			   mds->active_volatile_bytes,
+			   mds->active_persistent_bytes, "pmem");
 }
 EXPORT_SYMBOL_NS_GPL(cxl_mem_create_range_info, CXL);
 
-int cxl_set_timestamp(struct cxl_dev_state *cxlds)
+int cxl_set_timestamp(struct cxl_memdev_state *mds)
 {
 	struct cxl_mbox_cmd mbox_cmd;
 	struct cxl_mbox_set_timestamp_in pi;
@@ -1154,7 +1161,7 @@ int cxl_set_timestamp(struct cxl_dev_state *cxlds)
 		.payload_in = &pi,
 	};
 
-	rc = cxl_internal_send_cmd(cxlds, &mbox_cmd);
+	rc = cxl_internal_send_cmd(mds, &mbox_cmd);
 	/*
 	 * Command is optional. Devices may have another way of providing
 	 * a timestamp, or may return all 0s in timestamp fields.
@@ -1170,18 +1177,18 @@ EXPORT_SYMBOL_NS_GPL(cxl_set_timestamp, CXL);
 int cxl_mem_get_poison(struct cxl_memdev *cxlmd, u64 offset, u64 len,
 		       struct cxl_region *cxlr)
 {
-	struct cxl_dev_state *cxlds = cxlmd->cxlds;
+	struct cxl_memdev_state *mds = to_cxl_memdev_state(cxlmd->cxlds);
 	struct cxl_mbox_poison_out *po;
 	struct cxl_mbox_poison_in pi;
 	struct cxl_mbox_cmd mbox_cmd;
 	int nr_records = 0;
 	int rc;
 
-	rc = mutex_lock_interruptible(&cxlds->poison.lock);
+	rc = mutex_lock_interruptible(&mds->poison.lock);
 	if (rc)
 		return rc;
 
-	po = cxlds->poison.list_out;
+	po = mds->poison.list_out;
 	pi.offset = cpu_to_le64(offset);
 	pi.length = cpu_to_le64(len / CXL_POISON_LEN_MULT);
 
@@ -1189,13 +1196,13 @@ int cxl_mem_get_poison(struct cxl_memdev *cxlmd, u64 offset, u64 len,
 		.opcode = CXL_MBOX_OP_GET_POISON,
 		.size_in = sizeof(pi),
 		.payload_in = &pi,
-		.size_out = cxlds->payload_size,
+		.size_out = mds->payload_size,
 		.payload_out = po,
 		.min_out = struct_size(po, record, 0),
 	};
 
 	do {
-		rc = cxl_internal_send_cmd(cxlds, &mbox_cmd);
+		rc = cxl_internal_send_cmd(mds, &mbox_cmd);
 		if (rc)
 			break;
 
@@ -1206,14 +1213,14 @@ int cxl_mem_get_poison(struct cxl_memdev *cxlmd, u64 offset, u64 len,
 
 		/* Protect against an uncleared _FLAG_MORE */
 		nr_records = nr_records + le16_to_cpu(po->count);
-		if (nr_records >= cxlds->poison.max_errors) {
+		if (nr_records >= mds->poison.max_errors) {
 			dev_dbg(&cxlmd->dev, "Max Error Records reached: %d\n",
 				nr_records);
 			break;
 		}
 	} while (po->flags & CXL_POISON_FLAG_MORE);
 
-	mutex_unlock(&cxlds->poison.lock);
+	mutex_unlock(&mds->poison.lock);
 	return rc;
 }
 EXPORT_SYMBOL_NS_GPL(cxl_mem_get_poison, CXL);
@@ -1223,52 +1230,52 @@ static void free_poison_buf(void *buf)
 	kvfree(buf);
 }
 
-/* Get Poison List output buffer is protected by cxlds->poison.lock */
-static int cxl_poison_alloc_buf(struct cxl_dev_state *cxlds)
+/* Get Poison List output buffer is protected by mds->poison.lock */
+static int cxl_poison_alloc_buf(struct cxl_memdev_state *mds)
 {
-	cxlds->poison.list_out = kvmalloc(cxlds->payload_size, GFP_KERNEL);
-	if (!cxlds->poison.list_out)
+	mds->poison.list_out = kvmalloc(mds->payload_size, GFP_KERNEL);
+	if (!mds->poison.list_out)
 		return -ENOMEM;
 
-	return devm_add_action_or_reset(cxlds->dev, free_poison_buf,
-					cxlds->poison.list_out);
+	return devm_add_action_or_reset(mds->cxlds.dev, free_poison_buf,
+					mds->poison.list_out);
 }
 
-int cxl_poison_state_init(struct cxl_dev_state *cxlds)
+int cxl_poison_state_init(struct cxl_memdev_state *mds)
 {
 	int rc;
 
-	if (!test_bit(CXL_POISON_ENABLED_LIST, cxlds->poison.enabled_cmds))
+	if (!test_bit(CXL_POISON_ENABLED_LIST, mds->poison.enabled_cmds))
 		return 0;
 
-	rc = cxl_poison_alloc_buf(cxlds);
+	rc = cxl_poison_alloc_buf(mds);
 	if (rc) {
-		clear_bit(CXL_POISON_ENABLED_LIST, cxlds->poison.enabled_cmds);
+		clear_bit(CXL_POISON_ENABLED_LIST, mds->poison.enabled_cmds);
 		return rc;
 	}
 
-	mutex_init(&cxlds->poison.lock);
+	mutex_init(&mds->poison.lock);
 	return 0;
 }
 EXPORT_SYMBOL_NS_GPL(cxl_poison_state_init, CXL);
 
-struct cxl_dev_state *cxl_dev_state_create(struct device *dev)
+struct cxl_memdev_state *cxl_memdev_state_create(struct device *dev)
 {
-	struct cxl_dev_state *cxlds;
+	struct cxl_memdev_state *mds;
 
-	cxlds = devm_kzalloc(dev, sizeof(*cxlds), GFP_KERNEL);
-	if (!cxlds) {
+	mds = devm_kzalloc(dev, sizeof(*mds), GFP_KERNEL);
+	if (!mds) {
 		dev_err(dev, "No memory available\n");
 		return ERR_PTR(-ENOMEM);
 	}
 
-	mutex_init(&cxlds->mbox_mutex);
-	mutex_init(&cxlds->event.log_lock);
-	cxlds->dev = dev;
+	mutex_init(&mds->mbox_mutex);
+	mutex_init(&mds->event.log_lock);
+	mds->cxlds.dev = dev;
 
-	return cxlds;
+	return mds;
 }
-EXPORT_SYMBOL_NS_GPL(cxl_dev_state_create, CXL);
+EXPORT_SYMBOL_NS_GPL(cxl_memdev_state_create, CXL);
 
 void __init cxl_mbox_init(void)
 {
diff --git a/drivers/cxl/core/memdev.c b/drivers/cxl/core/memdev.c
index 057a43267290..15434b1b4909 100644
--- a/drivers/cxl/core/memdev.c
+++ b/drivers/cxl/core/memdev.c
@@ -39,8 +39,9 @@ static ssize_t firmware_version_show(struct device *dev,
 {
 	struct cxl_memdev *cxlmd = to_cxl_memdev(dev);
 	struct cxl_dev_state *cxlds = cxlmd->cxlds;
+	struct cxl_memdev_state *mds = to_cxl_memdev_state(cxlds);
 
-	return sysfs_emit(buf, "%.16s\n", cxlds->firmware_version);
+	return sysfs_emit(buf, "%.16s\n", mds->firmware_version);
 }
 static DEVICE_ATTR_RO(firmware_version);
 
@@ -49,8 +50,9 @@ static ssize_t payload_max_show(struct device *dev,
 {
 	struct cxl_memdev *cxlmd = to_cxl_memdev(dev);
 	struct cxl_dev_state *cxlds = cxlmd->cxlds;
+	struct cxl_memdev_state *mds = to_cxl_memdev_state(cxlds);
 
-	return sysfs_emit(buf, "%zu\n", cxlds->payload_size);
+	return sysfs_emit(buf, "%zu\n", mds->payload_size);
 }
 static DEVICE_ATTR_RO(payload_max);
 
@@ -59,8 +61,9 @@ static ssize_t label_storage_size_show(struct device *dev,
 {
 	struct cxl_memdev *cxlmd = to_cxl_memdev(dev);
 	struct cxl_dev_state *cxlds = cxlmd->cxlds;
+	struct cxl_memdev_state *mds = to_cxl_memdev_state(cxlds);
 
-	return sysfs_emit(buf, "%zu\n", cxlds->lsa_size);
+	return sysfs_emit(buf, "%zu\n", mds->lsa_size);
 }
 static DEVICE_ATTR_RO(label_storage_size);
 
@@ -231,7 +234,7 @@ static int cxl_validate_poison_dpa(struct cxl_memdev *cxlmd, u64 dpa)
 
 int cxl_inject_poison(struct cxl_memdev *cxlmd, u64 dpa)
 {
-	struct cxl_dev_state *cxlds = cxlmd->cxlds;
+	struct cxl_memdev_state *mds = to_cxl_memdev_state(cxlmd->cxlds);
 	struct cxl_mbox_inject_poison inject;
 	struct cxl_poison_record record;
 	struct cxl_mbox_cmd mbox_cmd;
@@ -255,13 +258,13 @@ int cxl_inject_poison(struct cxl_memdev *cxlmd, u64 dpa)
 		.size_in = sizeof(inject),
 		.payload_in = &inject,
 	};
-	rc = cxl_internal_send_cmd(cxlds, &mbox_cmd);
+	rc = cxl_internal_send_cmd(mds, &mbox_cmd);
 	if (rc)
 		goto out;
 
 	cxlr = cxl_dpa_to_region(cxlmd, dpa);
 	if (cxlr)
-		dev_warn_once(cxlds->dev,
+		dev_warn_once(mds->cxlds.dev,
 			      "poison inject dpa:%#llx region: %s\n", dpa,
 			      dev_name(&cxlr->dev));
 
@@ -279,7 +282,7 @@ EXPORT_SYMBOL_NS_GPL(cxl_inject_poison, CXL);
 
 int cxl_clear_poison(struct cxl_memdev *cxlmd, u64 dpa)
 {
-	struct cxl_dev_state *cxlds = cxlmd->cxlds;
+	struct cxl_memdev_state *mds = to_cxl_memdev_state(cxlmd->cxlds);
 	struct cxl_mbox_clear_poison clear;
 	struct cxl_poison_record record;
 	struct cxl_mbox_cmd mbox_cmd;
@@ -312,14 +315,15 @@ int cxl_clear_poison(struct cxl_memdev *cxlmd, u64 dpa)
 		.payload_in = &clear,
 	};
 
-	rc = cxl_internal_send_cmd(cxlds, &mbox_cmd);
+	rc = cxl_internal_send_cmd(mds, &mbox_cmd);
 	if (rc)
 		goto out;
 
 	cxlr = cxl_dpa_to_region(cxlmd, dpa);
 	if (cxlr)
-		dev_warn_once(cxlds->dev, "poison clear dpa:%#llx region: %s\n",
-			      dpa, dev_name(&cxlr->dev));
+		dev_warn_once(mds->cxlds.dev,
+			      "poison clear dpa:%#llx region: %s\n", dpa,
+			      dev_name(&cxlr->dev));
 
 	record = (struct cxl_poison_record) {
 		.address = cpu_to_le64(dpa),
@@ -397,17 +401,18 @@ EXPORT_SYMBOL_NS_GPL(is_cxl_memdev, CXL);
 
 /**
  * set_exclusive_cxl_commands() - atomically disable user cxl commands
- * @cxlds: The device state to operate on
+ * @mds: The device state to operate on
  * @cmds: bitmap of commands to mark exclusive
  *
  * Grab the cxl_memdev_rwsem in write mode to flush in-flight
  * invocations of the ioctl path and then disable future execution of
  * commands with the command ids set in @cmds.
  */
-void set_exclusive_cxl_commands(struct cxl_dev_state *cxlds, unsigned long *cmds)
+void set_exclusive_cxl_commands(struct cxl_memdev_state *mds,
+				unsigned long *cmds)
 {
 	down_write(&cxl_memdev_rwsem);
-	bitmap_or(cxlds->exclusive_cmds, cxlds->exclusive_cmds, cmds,
+	bitmap_or(mds->exclusive_cmds, mds->exclusive_cmds, cmds,
 		  CXL_MEM_COMMAND_ID_MAX);
 	up_write(&cxl_memdev_rwsem);
 }
@@ -415,13 +420,14 @@ EXPORT_SYMBOL_NS_GPL(set_exclusive_cxl_commands, CXL);
 
 /**
  * clear_exclusive_cxl_commands() - atomically enable user cxl commands
- * @cxlds: The device state to modify
+ * @mds: The device state to modify
  * @cmds: bitmap of commands to mark available for userspace
  */
-void clear_exclusive_cxl_commands(struct cxl_dev_state *cxlds, unsigned long *cmds)
+void clear_exclusive_cxl_commands(struct cxl_memdev_state *mds,
+				  unsigned long *cmds)
 {
 	down_write(&cxl_memdev_rwsem);
-	bitmap_andnot(cxlds->exclusive_cmds, cxlds->exclusive_cmds, cmds,
+	bitmap_andnot(mds->exclusive_cmds, mds->exclusive_cmds, cmds,
 		      CXL_MEM_COMMAND_ID_MAX);
 	up_write(&cxl_memdev_rwsem);
 }
diff --git a/drivers/cxl/cxlmem.h b/drivers/cxl/cxlmem.h
index 66896fc6c43f..b1a72e01e4de 100644
--- a/drivers/cxl/cxlmem.h
+++ b/drivers/cxl/cxlmem.h
@@ -267,6 +267,34 @@ struct cxl_poison_state {
  * @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
+ * @pmem_res: Active Persistent memory capacity configuration
+ * @ram_res: Active Volatile memory capacity configuration
+ * @component_reg_phys: register base of component registers
+ * @serial: PCIe Device Serial Number
+ */
+struct cxl_dev_state {
+	struct device *dev;
+	struct cxl_memdev *cxlmd;
+	struct cxl_regs regs;
+	int cxl_dvsec;
+	bool rcd;
+	bool media_ready;
+	struct resource dpa_res;
+	struct resource pmem_res;
+	struct resource ram_res;
+	resource_size_t component_reg_phys;
+	u64 serial;
+};
+
+/**
+ * struct cxl_memdev_state - Generic Type-3 Memory Device Class driver data
+ *
+ * CXL 8.1.12.1 PCI Header - Class Code Register Memory Device defines
+ * common memory device functionality like the presence of a mailbox and
+ * the functionality related to that like Identify Memory Device and Get
+ * Partition Info
+ * @cxlds: Core driver state common across Type-2 and Type-3 devices
  * @payload_size: Size of space for payload
  *                (CXL 2.0 8.2.8.4.3 Mailbox Capabilities Register)
  * @lsa_size: Size of Label Storage Area
@@ -275,9 +303,6 @@ struct cxl_poison_state {
  * @firmware_version: Firmware version for the memory device.
  * @enabled_cmds: Hardware commands found enabled in CEL.
  * @exclusive_cmds: Commands that are kernel-internal only
- * @dpa_res: Overall DPA resource tree for the device
- * @pmem_res: Active Persistent memory capacity configuration
- * @ram_res: Active Volatile memory capacity configuration
  * @total_bytes: sum of all possible capacities
  * @volatile_only_bytes: hard volatile capacity
  * @persistent_only_bytes: hard persistent capacity
@@ -286,53 +311,41 @@ struct cxl_poison_state {
  * @active_persistent_bytes: sum of hard + soft persistent
  * @next_volatile_bytes: volatile capacity change pending device reset
  * @next_persistent_bytes: persistent capacity change pending device reset
- * @component_reg_phys: register base of component registers
- * @serial: PCIe Device Serial Number
  * @event: event log driver state
  * @poison: poison driver state info
  * @mbox_send: @dev specific transport for transmitting mailbox commands
  *
- * See section 8.2.9.5.2 Capacity Configuration and Label Storage for
+ * See CXL 3.0 8.2.9.8.2 Capacity Configuration and Label Storage for
  * details on capacity parameters.
  */
-struct cxl_dev_state {
-	struct device *dev;
-	struct cxl_memdev *cxlmd;
-
-	struct cxl_regs regs;
-	int cxl_dvsec;
-
-	bool rcd;
-	bool media_ready;
+struct cxl_memdev_state {
+	struct cxl_dev_state cxlds;
 	size_t payload_size;
 	size_t lsa_size;
 	struct mutex mbox_mutex; /* Protects device mailbox and firmware */
 	char firmware_version[0x10];
 	DECLARE_BITMAP(enabled_cmds, CXL_MEM_COMMAND_ID_MAX);
 	DECLARE_BITMAP(exclusive_cmds, CXL_MEM_COMMAND_ID_MAX);
-
-	struct resource dpa_res;
-	struct resource pmem_res;
-	struct resource ram_res;
 	u64 total_bytes;
 	u64 volatile_only_bytes;
 	u64 persistent_only_bytes;
 	u64 partition_align_bytes;
-
 	u64 active_volatile_bytes;
 	u64 active_persistent_bytes;
 	u64 next_volatile_bytes;
 	u64 next_persistent_bytes;
-
-	resource_size_t component_reg_phys;
-	u64 serial;
-
 	struct cxl_event_state event;
 	struct cxl_poison_state poison;
-
-	int (*mbox_send)(struct cxl_dev_state *cxlds, struct cxl_mbox_cmd *cmd);
+	int (*mbox_send)(struct cxl_memdev_state *mds,
+			 struct cxl_mbox_cmd *cmd);
 };
 
+static inline struct cxl_memdev_state *
+to_cxl_memdev_state(struct cxl_dev_state *cxlds)
+{
+	return container_of(cxlds, struct cxl_memdev_state, cxlds);
+}
+
 enum cxl_opcode {
 	CXL_MBOX_OP_INVALID		= 0x0000,
 	CXL_MBOX_OP_RAW			= CXL_MBOX_OP_INVALID,
@@ -691,18 +704,20 @@ enum {
 	CXL_PMEM_SEC_PASS_USER,
 };
 
-int cxl_internal_send_cmd(struct cxl_dev_state *cxlds,
+int cxl_internal_send_cmd(struct cxl_memdev_state *mds,
 			  struct cxl_mbox_cmd *cmd);
-int cxl_dev_state_identify(struct cxl_dev_state *cxlds);
+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_dev_state *cxlds);
-int cxl_mem_create_range_info(struct cxl_dev_state *cxlds);
-struct cxl_dev_state *cxl_dev_state_create(struct device *dev);
-void set_exclusive_cxl_commands(struct cxl_dev_state *cxlds, unsigned long *cmds);
-void clear_exclusive_cxl_commands(struct cxl_dev_state *cxlds, unsigned long *cmds);
-void cxl_mem_get_event_records(struct cxl_dev_state *cxlds, u32 status);
-int cxl_set_timestamp(struct cxl_dev_state *cxlds);
-int cxl_poison_state_init(struct cxl_dev_state *cxlds);
+int cxl_enumerate_cmds(struct cxl_memdev_state *mds);
+int cxl_mem_create_range_info(struct cxl_memdev_state *mds);
+struct cxl_memdev_state *cxl_memdev_state_create(struct device *dev);
+void set_exclusive_cxl_commands(struct cxl_memdev_state *mds,
+				unsigned long *cmds);
+void clear_exclusive_cxl_commands(struct cxl_memdev_state *mds,
+				  unsigned long *cmds);
+void cxl_mem_get_event_records(struct cxl_memdev_state *mds, u32 status);
+int cxl_set_timestamp(struct cxl_memdev_state *mds);
+int cxl_poison_state_init(struct cxl_memdev_state *mds);
 int cxl_mem_get_poison(struct cxl_memdev *cxlmd, u64 offset, u64 len,
 		       struct cxl_region *cxlr);
 int cxl_trigger_poison_list(struct cxl_memdev *cxlmd);
diff --git a/drivers/cxl/mem.c b/drivers/cxl/mem.c
index 519edd0eb196..584f9eec57e4 100644
--- a/drivers/cxl/mem.c
+++ b/drivers/cxl/mem.c
@@ -117,6 +117,7 @@ DEFINE_DEBUGFS_ATTRIBUTE(cxl_poison_clear_fops, NULL,
 static int cxl_mem_probe(struct device *dev)
 {
 	struct cxl_memdev *cxlmd = to_cxl_memdev(dev);
+	struct cxl_memdev_state *mds = to_cxl_memdev_state(cxlmd->cxlds);
 	struct cxl_dev_state *cxlds = cxlmd->cxlds;
 	struct device *endpoint_parent;
 	struct cxl_port *parent_port;
@@ -141,10 +142,10 @@ static int cxl_mem_probe(struct device *dev)
 	dentry = cxl_debugfs_create_dir(dev_name(dev));
 	debugfs_create_devm_seqfile(dev, "dpamem", dentry, cxl_mem_dpa_show);
 
-	if (test_bit(CXL_POISON_ENABLED_INJECT, cxlds->poison.enabled_cmds))
+	if (test_bit(CXL_POISON_ENABLED_INJECT, mds->poison.enabled_cmds))
 		debugfs_create_file("inject_poison", 0200, dentry, cxlmd,
 				    &cxl_poison_inject_fops);
-	if (test_bit(CXL_POISON_ENABLED_CLEAR, cxlds->poison.enabled_cmds))
+	if (test_bit(CXL_POISON_ENABLED_CLEAR, mds->poison.enabled_cmds))
 		debugfs_create_file("clear_poison", 0200, dentry, cxlmd,
 				    &cxl_poison_clear_fops);
 
@@ -227,9 +228,12 @@ static umode_t cxl_mem_visible(struct kobject *kobj, struct attribute *a, int n)
 {
 	if (a == &dev_attr_trigger_poison_list.attr) {
 		struct device *dev = kobj_to_dev(kobj);
+		struct cxl_memdev *cxlmd = to_cxl_memdev(dev);
+		struct cxl_memdev_state *mds =
+			to_cxl_memdev_state(cxlmd->cxlds);
 
 		if (!test_bit(CXL_POISON_ENABLED_LIST,
-			      to_cxl_memdev(dev)->cxlds->poison.enabled_cmds))
+			      mds->poison.enabled_cmds))
 			return 0;
 	}
 	return a->mode;
diff --git a/drivers/cxl/pci.c b/drivers/cxl/pci.c
index 0872f2233ed0..4e2845b7331a 100644
--- a/drivers/cxl/pci.c
+++ b/drivers/cxl/pci.c
@@ -86,7 +86,7 @@ static int cxl_pci_mbox_wait_for_doorbell(struct cxl_dev_state *cxlds)
 
 /**
  * __cxl_pci_mbox_send_cmd() - Execute a mailbox command
- * @cxlds: The device state to communicate with.
+ * @mds: The memory device driver data
  * @mbox_cmd: Command to send to the memory device.
  *
  * Context: Any context. Expects mbox_mutex to be held.
@@ -106,16 +106,17 @@ static int cxl_pci_mbox_wait_for_doorbell(struct cxl_dev_state *cxlds)
  * not need to coordinate with each other. The driver only uses the primary
  * mailbox.
  */
-static int __cxl_pci_mbox_send_cmd(struct cxl_dev_state *cxlds,
+static int __cxl_pci_mbox_send_cmd(struct cxl_memdev_state *mds,
 				   struct cxl_mbox_cmd *mbox_cmd)
 {
+	struct cxl_dev_state *cxlds = &mds->cxlds;
 	void __iomem *payload = cxlds->regs.mbox + CXLDEV_MBOX_PAYLOAD_OFFSET;
 	struct device *dev = cxlds->dev;
 	u64 cmd_reg, status_reg;
 	size_t out_len;
 	int rc;
 
-	lockdep_assert_held(&cxlds->mbox_mutex);
+	lockdep_assert_held(&mds->mbox_mutex);
 
 	/*
 	 * Here are the steps from 8.2.8.4 of the CXL 2.0 spec.
@@ -196,8 +197,9 @@ static int __cxl_pci_mbox_send_cmd(struct cxl_dev_state *cxlds,
 		 * have requested less data than the hardware supplied even
 		 * within spec.
 		 */
-		size_t n = min3(mbox_cmd->size_out, cxlds->payload_size, out_len);
+		size_t n;
 
+		n = min3(mbox_cmd->size_out, mds->payload_size, out_len);
 		memcpy_fromio(mbox_cmd->payload_out, payload, n);
 		mbox_cmd->size_out = n;
 	} else {
@@ -207,20 +209,23 @@ static int __cxl_pci_mbox_send_cmd(struct cxl_dev_state *cxlds,
 	return 0;
 }
 
-static int cxl_pci_mbox_send(struct cxl_dev_state *cxlds, struct cxl_mbox_cmd *cmd)
+static int cxl_pci_mbox_send(struct cxl_memdev_state *mds,
+			     struct cxl_mbox_cmd *cmd)
 {
 	int rc;
 
-	mutex_lock_io(&cxlds->mbox_mutex);
-	rc = __cxl_pci_mbox_send_cmd(cxlds, cmd);
-	mutex_unlock(&cxlds->mbox_mutex);
+	mutex_lock_io(&mds->mbox_mutex);
+	rc = __cxl_pci_mbox_send_cmd(mds, cmd);
+	mutex_unlock(&mds->mbox_mutex);
 
 	return rc;
 }
 
-static int cxl_pci_setup_mailbox(struct cxl_dev_state *cxlds)
+static int cxl_pci_setup_mailbox(struct cxl_memdev_state *mds)
 {
+	struct cxl_dev_state *cxlds = &mds->cxlds;
 	const int cap = readl(cxlds->regs.mbox + CXLDEV_MBOX_CAPS_OFFSET);
+	struct device *dev = cxlds->dev;
 	unsigned long timeout;
 	u64 md_status;
 
@@ -234,8 +239,7 @@ static int cxl_pci_setup_mailbox(struct cxl_dev_state *cxlds)
 	} while (!time_after(jiffies, timeout));
 
 	if (!(md_status & CXLMDEV_MBOX_IF_READY)) {
-		cxl_err(cxlds->dev, md_status,
-			"timeout awaiting mailbox ready");
+		cxl_err(dev, md_status, "timeout awaiting mailbox ready");
 		return -ETIMEDOUT;
 	}
 
@@ -246,12 +250,12 @@ static int cxl_pci_setup_mailbox(struct cxl_dev_state *cxlds)
 	 * source for future doorbell busy events.
 	 */
 	if (cxl_pci_mbox_wait_for_doorbell(cxlds) != 0) {
-		cxl_err(cxlds->dev, md_status, "timeout awaiting mailbox idle");
+		cxl_err(dev, md_status, "timeout awaiting mailbox idle");
 		return -ETIMEDOUT;
 	}
 
-	cxlds->mbox_send = cxl_pci_mbox_send;
-	cxlds->payload_size =
+	mds->mbox_send = cxl_pci_mbox_send;
+	mds->payload_size =
 		1 << FIELD_GET(CXLDEV_MBOX_CAP_PAYLOAD_SIZE_MASK, cap);
 
 	/*
@@ -261,15 +265,14 @@ static int cxl_pci_setup_mailbox(struct cxl_dev_state *cxlds)
 	 * there's no point in going forward. If the size is too large, there's
 	 * no harm is soft limiting it.
 	 */
-	cxlds->payload_size = min_t(size_t, cxlds->payload_size, SZ_1M);
-	if (cxlds->payload_size < 256) {
-		dev_err(cxlds->dev, "Mailbox is too small (%zub)",
-			cxlds->payload_size);
+	mds->payload_size = min_t(size_t, mds->payload_size, SZ_1M);
+	if (mds->payload_size < 256) {
+		dev_err(dev, "Mailbox is too small (%zub)",
+			mds->payload_size);
 		return -ENXIO;
 	}
 
-	dev_dbg(cxlds->dev, "Mailbox payload sized %zu",
-		cxlds->payload_size);
+	dev_dbg(dev, "Mailbox payload sized %zu", mds->payload_size);
 
 	return 0;
 }
@@ -433,18 +436,18 @@ static void free_event_buf(void *buf)
 
 /*
  * There is a single buffer for reading event logs from the mailbox.  All logs
- * share this buffer protected by the cxlds->event_log_lock.
+ * share this buffer protected by the mds->event_log_lock.
  */
-static int cxl_mem_alloc_event_buf(struct cxl_dev_state *cxlds)
+static int cxl_mem_alloc_event_buf(struct cxl_memdev_state *mds)
 {
 	struct cxl_get_event_payload *buf;
 
-	buf = kvmalloc(cxlds->payload_size, GFP_KERNEL);
+	buf = kvmalloc(mds->payload_size, GFP_KERNEL);
 	if (!buf)
 		return -ENOMEM;
-	cxlds->event.buf = buf;
+	mds->event.buf = buf;
 
-	return devm_add_action_or_reset(cxlds->dev, free_event_buf, buf);
+	return devm_add_action_or_reset(mds->cxlds.dev, free_event_buf, buf);
 }
 
 static int cxl_alloc_irq_vectors(struct pci_dev *pdev)
@@ -477,6 +480,7 @@ static irqreturn_t cxl_event_thread(int irq, void *id)
 {
 	struct cxl_dev_id *dev_id = id;
 	struct cxl_dev_state *cxlds = dev_id->cxlds;
+	struct cxl_memdev_state *mds = to_cxl_memdev_state(cxlds);
 	u32 status;
 
 	do {
@@ -489,7 +493,7 @@ static irqreturn_t cxl_event_thread(int irq, void *id)
 		status &= CXLDEV_EVENT_STATUS_ALL;
 		if (!status)
 			break;
-		cxl_mem_get_event_records(cxlds, status);
+		cxl_mem_get_event_records(mds, status);
 		cond_resched();
 	} while (status);
 
@@ -522,7 +526,7 @@ static int cxl_event_req_irq(struct cxl_dev_state *cxlds, u8 setting)
 					 dev_id);
 }
 
-static int cxl_event_get_int_policy(struct cxl_dev_state *cxlds,
+static int cxl_event_get_int_policy(struct cxl_memdev_state *mds,
 				    struct cxl_event_interrupt_policy *policy)
 {
 	struct cxl_mbox_cmd mbox_cmd = {
@@ -532,15 +536,15 @@ static int cxl_event_get_int_policy(struct cxl_dev_state *cxlds,
 	};
 	int rc;
 
-	rc = cxl_internal_send_cmd(cxlds, &mbox_cmd);
+	rc = cxl_internal_send_cmd(mds, &mbox_cmd);
 	if (rc < 0)
-		dev_err(cxlds->dev, "Failed to get event interrupt policy : %d",
-			rc);
+		dev_err(mds->cxlds.dev,
+			"Failed to get event interrupt policy : %d", rc);
 
 	return rc;
 }
 
-static int cxl_event_config_msgnums(struct cxl_dev_state *cxlds,
+static int cxl_event_config_msgnums(struct cxl_memdev_state *mds,
 				    struct cxl_event_interrupt_policy *policy)
 {
 	struct cxl_mbox_cmd mbox_cmd;
@@ -559,23 +563,24 @@ static int cxl_event_config_msgnums(struct cxl_dev_state *cxlds,
 		.size_in = sizeof(*policy),
 	};
 
-	rc = cxl_internal_send_cmd(cxlds, &mbox_cmd);
+	rc = cxl_internal_send_cmd(mds, &mbox_cmd);
 	if (rc < 0) {
-		dev_err(cxlds->dev, "Failed to set event interrupt policy : %d",
+		dev_err(mds->cxlds.dev, "Failed to set event interrupt policy : %d",
 			rc);
 		return rc;
 	}
 
 	/* Retrieve final interrupt settings */
-	return cxl_event_get_int_policy(cxlds, policy);
+	return cxl_event_get_int_policy(mds, policy);
 }
 
-static int cxl_event_irqsetup(struct cxl_dev_state *cxlds)
+static int cxl_event_irqsetup(struct cxl_memdev_state *mds)
 {
+	struct cxl_dev_state *cxlds = &mds->cxlds;
 	struct cxl_event_interrupt_policy policy;
 	int rc;
 
-	rc = cxl_event_config_msgnums(cxlds, &policy);
+	rc = cxl_event_config_msgnums(mds, &policy);
 	if (rc)
 		return rc;
 
@@ -614,7 +619,7 @@ static bool cxl_event_int_is_fw(u8 setting)
 }
 
 static int cxl_event_config(struct pci_host_bridge *host_bridge,
-			    struct cxl_dev_state *cxlds)
+			    struct cxl_memdev_state *mds)
 {
 	struct cxl_event_interrupt_policy policy;
 	int rc;
@@ -626,11 +631,11 @@ static int cxl_event_config(struct pci_host_bridge *host_bridge,
 	if (!host_bridge->native_cxl_error)
 		return 0;
 
-	rc = cxl_mem_alloc_event_buf(cxlds);
+	rc = cxl_mem_alloc_event_buf(mds);
 	if (rc)
 		return rc;
 
-	rc = cxl_event_get_int_policy(cxlds, &policy);
+	rc = cxl_event_get_int_policy(mds, &policy);
 	if (rc)
 		return rc;
 
@@ -638,15 +643,16 @@ static int cxl_event_config(struct pci_host_bridge *host_bridge,
 	    cxl_event_int_is_fw(policy.warn_settings) ||
 	    cxl_event_int_is_fw(policy.failure_settings) ||
 	    cxl_event_int_is_fw(policy.fatal_settings)) {
-		dev_err(cxlds->dev, "FW still in control of Event Logs despite _OSC settings\n");
+		dev_err(mds->cxlds.dev,
+			"FW still in control of Event Logs despite _OSC settings\n");
 		return -EBUSY;
 	}
 
-	rc = cxl_event_irqsetup(cxlds);
+	rc = cxl_event_irqsetup(mds);
 	if (rc)
 		return rc;
 
-	cxl_mem_get_event_records(cxlds, CXLDEV_EVENT_STATUS_ALL);
+	cxl_mem_get_event_records(mds, CXLDEV_EVENT_STATUS_ALL);
 
 	return 0;
 }
@@ -654,9 +660,10 @@ static int cxl_event_config(struct pci_host_bridge *host_bridge,
 static int cxl_pci_probe(struct pci_dev *pdev, const struct pci_device_id *id)
 {
 	struct pci_host_bridge *host_bridge = pci_find_host_bridge(pdev->bus);
+	struct cxl_memdev_state *mds;
+	struct cxl_dev_state *cxlds;
 	struct cxl_register_map map;
 	struct cxl_memdev *cxlmd;
-	struct cxl_dev_state *cxlds;
 	int rc;
 
 	/*
@@ -671,9 +678,10 @@ static int cxl_pci_probe(struct pci_dev *pdev, const struct pci_device_id *id)
 		return rc;
 	pci_set_master(pdev);
 
-	cxlds = cxl_dev_state_create(&pdev->dev);
-	if (IS_ERR(cxlds))
-		return PTR_ERR(cxlds);
+	mds = cxl_memdev_state_create(&pdev->dev);
+	if (IS_ERR(mds))
+		return PTR_ERR(mds);
+	cxlds = &mds->cxlds;
 	pci_set_drvdata(pdev, cxlds);
 
 	cxlds->rcd = is_cxl_restricted(pdev);
@@ -714,27 +722,27 @@ static int cxl_pci_probe(struct pci_dev *pdev, const struct pci_device_id *id)
 	else
 		dev_warn(&pdev->dev, "Media not active (%d)\n", rc);
 
-	rc = cxl_pci_setup_mailbox(cxlds);
+	rc = cxl_pci_setup_mailbox(mds);
 	if (rc)
 		return rc;
 
-	rc = cxl_enumerate_cmds(cxlds);
+	rc = cxl_enumerate_cmds(mds);
 	if (rc)
 		return rc;
 
-	rc = cxl_set_timestamp(cxlds);
+	rc = cxl_set_timestamp(mds);
 	if (rc)
 		return rc;
 
-	rc = cxl_poison_state_init(cxlds);
+	rc = cxl_poison_state_init(mds);
 	if (rc)
 		return rc;
 
-	rc = cxl_dev_state_identify(cxlds);
+	rc = cxl_dev_state_identify(mds);
 	if (rc)
 		return rc;
 
-	rc = cxl_mem_create_range_info(cxlds);
+	rc = cxl_mem_create_range_info(mds);
 	if (rc)
 		return rc;
 
@@ -746,7 +754,7 @@ static int cxl_pci_probe(struct pci_dev *pdev, const struct pci_device_id *id)
 	if (IS_ERR(cxlmd))
 		return PTR_ERR(cxlmd);
 
-	rc = cxl_event_config(host_bridge, cxlds);
+	rc = cxl_event_config(host_bridge, mds);
 	if (rc)
 		return rc;
 
diff --git a/drivers/cxl/pmem.c b/drivers/cxl/pmem.c
index 71cfa1fdf902..7cb8994f8809 100644
--- a/drivers/cxl/pmem.c
+++ b/drivers/cxl/pmem.c
@@ -15,9 +15,9 @@ extern const struct nvdimm_security_ops *cxl_security_ops;
 
 static __read_mostly DECLARE_BITMAP(exclusive_cmds, CXL_MEM_COMMAND_ID_MAX);
 
-static void clear_exclusive(void *cxlds)
+static void clear_exclusive(void *mds)
 {
-	clear_exclusive_cxl_commands(cxlds, exclusive_cmds);
+	clear_exclusive_cxl_commands(mds, exclusive_cmds);
 }
 
 static void unregister_nvdimm(void *nvdimm)
@@ -65,13 +65,13 @@ static int cxl_nvdimm_probe(struct device *dev)
 	struct cxl_nvdimm *cxl_nvd = to_cxl_nvdimm(dev);
 	struct cxl_memdev *cxlmd = cxl_nvd->cxlmd;
 	struct cxl_nvdimm_bridge *cxl_nvb = cxlmd->cxl_nvb;
+	struct cxl_memdev_state *mds = to_cxl_memdev_state(cxlmd->cxlds);
 	unsigned long flags = 0, cmd_mask = 0;
-	struct cxl_dev_state *cxlds = cxlmd->cxlds;
 	struct nvdimm *nvdimm;
 	int rc;
 
-	set_exclusive_cxl_commands(cxlds, exclusive_cmds);
-	rc = devm_add_action_or_reset(dev, clear_exclusive, cxlds);
+	set_exclusive_cxl_commands(mds, exclusive_cmds);
+	rc = devm_add_action_or_reset(dev, clear_exclusive, mds);
 	if (rc)
 		return rc;
 
@@ -100,22 +100,23 @@ static struct cxl_driver cxl_nvdimm_driver = {
 	},
 };
 
-static int cxl_pmem_get_config_size(struct cxl_dev_state *cxlds,
+static int cxl_pmem_get_config_size(struct cxl_memdev_state *mds,
 				    struct nd_cmd_get_config_size *cmd,
 				    unsigned int buf_len)
 {
 	if (sizeof(*cmd) > buf_len)
 		return -EINVAL;
 
-	*cmd = (struct nd_cmd_get_config_size) {
-		 .config_size = cxlds->lsa_size,
-		 .max_xfer = cxlds->payload_size - sizeof(struct cxl_mbox_set_lsa),
+	*cmd = (struct nd_cmd_get_config_size){
+		.config_size = mds->lsa_size,
+		.max_xfer =
+			mds->payload_size - sizeof(struct cxl_mbox_set_lsa),
 	};
 
 	return 0;
 }
 
-static int cxl_pmem_get_config_data(struct cxl_dev_state *cxlds,
+static int cxl_pmem_get_config_data(struct cxl_memdev_state *mds,
 				    struct nd_cmd_get_config_data_hdr *cmd,
 				    unsigned int buf_len)
 {
@@ -140,13 +141,13 @@ static int cxl_pmem_get_config_data(struct cxl_dev_state *cxlds,
 		.payload_out = cmd->out_buf,
 	};
 
-	rc = cxl_internal_send_cmd(cxlds, &mbox_cmd);
+	rc = cxl_internal_send_cmd(mds, &mbox_cmd);
 	cmd->status = 0;
 
 	return rc;
 }
 
-static int cxl_pmem_set_config_data(struct cxl_dev_state *cxlds,
+static int cxl_pmem_set_config_data(struct cxl_memdev_state *mds,
 				    struct nd_cmd_set_config_hdr *cmd,
 				    unsigned int buf_len)
 {
@@ -176,7 +177,7 @@ static int cxl_pmem_set_config_data(struct cxl_dev_state *cxlds,
 		.size_in = struct_size(set_lsa, data, cmd->in_length),
 	};
 
-	rc = cxl_internal_send_cmd(cxlds, &mbox_cmd);
+	rc = cxl_internal_send_cmd(mds, &mbox_cmd);
 
 	/*
 	 * Set "firmware" status (4-packed bytes at the end of the input
@@ -194,18 +195,18 @@ static int cxl_pmem_nvdimm_ctl(struct nvdimm *nvdimm, unsigned int cmd,
 	struct cxl_nvdimm *cxl_nvd = nvdimm_provider_data(nvdimm);
 	unsigned long cmd_mask = nvdimm_cmd_mask(nvdimm);
 	struct cxl_memdev *cxlmd = cxl_nvd->cxlmd;
-	struct cxl_dev_state *cxlds = cxlmd->cxlds;
+	struct cxl_memdev_state *mds = to_cxl_memdev_state(cxlmd->cxlds);
 
 	if (!test_bit(cmd, &cmd_mask))
 		return -ENOTTY;
 
 	switch (cmd) {
 	case ND_CMD_GET_CONFIG_SIZE:
-		return cxl_pmem_get_config_size(cxlds, buf, buf_len);
+		return cxl_pmem_get_config_size(mds, buf, buf_len);
 	case ND_CMD_GET_CONFIG_DATA:
-		return cxl_pmem_get_config_data(cxlds, buf, buf_len);
+		return cxl_pmem_get_config_data(mds, buf, buf_len);
 	case ND_CMD_SET_CONFIG_DATA:
-		return cxl_pmem_set_config_data(cxlds, buf, buf_len);
+		return cxl_pmem_set_config_data(mds, buf, buf_len);
 	default:
 		return -ENOTTY;
 	}
diff --git a/drivers/cxl/security.c b/drivers/cxl/security.c
index 4ad4bda2d18e..8c98fc674fa7 100644
--- a/drivers/cxl/security.c
+++ b/drivers/cxl/security.c
@@ -14,7 +14,7 @@ static unsigned long cxl_pmem_get_security_flags(struct nvdimm *nvdimm,
 {
 	struct cxl_nvdimm *cxl_nvd = nvdimm_provider_data(nvdimm);
 	struct cxl_memdev *cxlmd = cxl_nvd->cxlmd;
-	struct cxl_dev_state *cxlds = cxlmd->cxlds;
+	struct cxl_memdev_state *mds = to_cxl_memdev_state(cxlmd->cxlds);
 	unsigned long security_flags = 0;
 	struct cxl_get_security_output {
 		__le32 flags;
@@ -29,7 +29,7 @@ static unsigned long cxl_pmem_get_security_flags(struct nvdimm *nvdimm,
 		.payload_out = &out,
 	};
 
-	rc = cxl_internal_send_cmd(cxlds, &mbox_cmd);
+	rc = cxl_internal_send_cmd(mds, &mbox_cmd);
 	if (rc < 0)
 		return 0;
 
@@ -67,7 +67,7 @@ static int cxl_pmem_security_change_key(struct nvdimm *nvdimm,
 {
 	struct cxl_nvdimm *cxl_nvd = nvdimm_provider_data(nvdimm);
 	struct cxl_memdev *cxlmd = cxl_nvd->cxlmd;
-	struct cxl_dev_state *cxlds = cxlmd->cxlds;
+	struct cxl_memdev_state *mds = to_cxl_memdev_state(cxlmd->cxlds);
 	struct cxl_mbox_cmd mbox_cmd;
 	struct cxl_set_pass set_pass;
 
@@ -84,7 +84,7 @@ static int cxl_pmem_security_change_key(struct nvdimm *nvdimm,
 		.payload_in = &set_pass,
 	};
 
-	return cxl_internal_send_cmd(cxlds, &mbox_cmd);
+	return cxl_internal_send_cmd(mds, &mbox_cmd);
 }
 
 static int __cxl_pmem_security_disable(struct nvdimm *nvdimm,
@@ -93,7 +93,7 @@ static int __cxl_pmem_security_disable(struct nvdimm *nvdimm,
 {
 	struct cxl_nvdimm *cxl_nvd = nvdimm_provider_data(nvdimm);
 	struct cxl_memdev *cxlmd = cxl_nvd->cxlmd;
-	struct cxl_dev_state *cxlds = cxlmd->cxlds;
+	struct cxl_memdev_state *mds = to_cxl_memdev_state(cxlmd->cxlds);
 	struct cxl_disable_pass dis_pass;
 	struct cxl_mbox_cmd mbox_cmd;
 
@@ -109,7 +109,7 @@ static int __cxl_pmem_security_disable(struct nvdimm *nvdimm,
 		.payload_in = &dis_pass,
 	};
 
-	return cxl_internal_send_cmd(cxlds, &mbox_cmd);
+	return cxl_internal_send_cmd(mds, &mbox_cmd);
 }
 
 static int cxl_pmem_security_disable(struct nvdimm *nvdimm,
@@ -128,12 +128,12 @@ static int cxl_pmem_security_freeze(struct nvdimm *nvdimm)
 {
 	struct cxl_nvdimm *cxl_nvd = nvdimm_provider_data(nvdimm);
 	struct cxl_memdev *cxlmd = cxl_nvd->cxlmd;
-	struct cxl_dev_state *cxlds = cxlmd->cxlds;
+	struct cxl_memdev_state *mds = to_cxl_memdev_state(cxlmd->cxlds);
 	struct cxl_mbox_cmd mbox_cmd = {
 		.opcode = CXL_MBOX_OP_FREEZE_SECURITY,
 	};
 
-	return cxl_internal_send_cmd(cxlds, &mbox_cmd);
+	return cxl_internal_send_cmd(mds, &mbox_cmd);
 }
 
 static int cxl_pmem_security_unlock(struct nvdimm *nvdimm,
@@ -141,7 +141,7 @@ static int cxl_pmem_security_unlock(struct nvdimm *nvdimm,
 {
 	struct cxl_nvdimm *cxl_nvd = nvdimm_provider_data(nvdimm);
 	struct cxl_memdev *cxlmd = cxl_nvd->cxlmd;
-	struct cxl_dev_state *cxlds = cxlmd->cxlds;
+	struct cxl_memdev_state *mds = to_cxl_memdev_state(cxlmd->cxlds);
 	u8 pass[NVDIMM_PASSPHRASE_LEN];
 	struct cxl_mbox_cmd mbox_cmd;
 	int rc;
@@ -153,7 +153,7 @@ static int cxl_pmem_security_unlock(struct nvdimm *nvdimm,
 		.payload_in = pass,
 	};
 
-	rc = cxl_internal_send_cmd(cxlds, &mbox_cmd);
+	rc = cxl_internal_send_cmd(mds, &mbox_cmd);
 	if (rc < 0)
 		return rc;
 
@@ -166,7 +166,7 @@ static int cxl_pmem_security_passphrase_erase(struct nvdimm *nvdimm,
 {
 	struct cxl_nvdimm *cxl_nvd = nvdimm_provider_data(nvdimm);
 	struct cxl_memdev *cxlmd = cxl_nvd->cxlmd;
-	struct cxl_dev_state *cxlds = cxlmd->cxlds;
+	struct cxl_memdev_state *mds = to_cxl_memdev_state(cxlmd->cxlds);
 	struct cxl_mbox_cmd mbox_cmd;
 	struct cxl_pass_erase erase;
 	int rc;
@@ -182,7 +182,7 @@ static int cxl_pmem_security_passphrase_erase(struct nvdimm *nvdimm,
 		.payload_in = &erase,
 	};
 
-	rc = cxl_internal_send_cmd(cxlds, &mbox_cmd);
+	rc = cxl_internal_send_cmd(mds, &mbox_cmd);
 	if (rc < 0)
 		return rc;
 
diff --git a/tools/testing/cxl/test/mem.c b/tools/testing/cxl/test/mem.c
index bdaf086d994e..6fb5718588f3 100644
--- a/tools/testing/cxl/test/mem.c
+++ b/tools/testing/cxl/test/mem.c
@@ -102,7 +102,7 @@ struct mock_event_log {
 };
 
 struct mock_event_store {
-	struct cxl_dev_state *cxlds;
+	struct cxl_memdev_state *mds;
 	struct mock_event_log mock_logs[CXL_EVENT_TYPE_MAX];
 	u32 ev_status;
 };
@@ -291,7 +291,7 @@ static void cxl_mock_event_trigger(struct device *dev)
 			event_reset_log(log);
 	}
 
-	cxl_mem_get_event_records(mes->cxlds, mes->ev_status);
+	cxl_mem_get_event_records(mes->mds, mes->ev_status);
 }
 
 struct cxl_event_record_raw maint_needed = {
@@ -451,7 +451,7 @@ static int mock_gsl(struct cxl_mbox_cmd *cmd)
 	return 0;
 }
 
-static int mock_get_log(struct cxl_dev_state *cxlds, struct cxl_mbox_cmd *cmd)
+static int mock_get_log(struct cxl_memdev_state *mds, struct cxl_mbox_cmd *cmd)
 {
 	struct cxl_mbox_get_log *gl = cmd->payload_in;
 	u32 offset = le32_to_cpu(gl->offset);
@@ -461,7 +461,7 @@ static int mock_get_log(struct cxl_dev_state *cxlds, struct cxl_mbox_cmd *cmd)
 
 	if (cmd->size_in < sizeof(*gl))
 		return -EINVAL;
-	if (length > cxlds->payload_size)
+	if (length > mds->payload_size)
 		return -EINVAL;
 	if (offset + length > sizeof(mock_cel))
 		return -EINVAL;
@@ -1105,8 +1105,10 @@ static struct attribute *cxl_mock_mem_core_attrs[] = {
 };
 ATTRIBUTE_GROUPS(cxl_mock_mem_core);
 
-static int cxl_mock_mbox_send(struct cxl_dev_state *cxlds, struct cxl_mbox_cmd *cmd)
+static int cxl_mock_mbox_send(struct cxl_memdev_state *mds,
+			      struct cxl_mbox_cmd *cmd)
 {
+	struct cxl_dev_state *cxlds = &mds->cxlds;
 	struct device *dev = cxlds->dev;
 	struct cxl_mockmem_data *mdata = dev_get_drvdata(dev);
 	int rc = -EIO;
@@ -1119,7 +1121,7 @@ static int cxl_mock_mbox_send(struct cxl_dev_state *cxlds, struct cxl_mbox_cmd *
 		rc = mock_gsl(cmd);
 		break;
 	case CXL_MBOX_OP_GET_LOG:
-		rc = mock_get_log(cxlds, cmd);
+		rc = mock_get_log(mds, cmd);
 		break;
 	case CXL_MBOX_OP_IDENTIFY:
 		if (cxlds->rcd)
@@ -1207,6 +1209,7 @@ static int cxl_mock_mem_probe(struct platform_device *pdev)
 {
 	struct device *dev = &pdev->dev;
 	struct cxl_memdev *cxlmd;
+	struct cxl_memdev_state *mds;
 	struct cxl_dev_state *cxlds;
 	struct cxl_mockmem_data *mdata;
 	int rc;
@@ -1223,48 +1226,50 @@ static int cxl_mock_mem_probe(struct platform_device *pdev)
 	if (rc)
 		return rc;
 
-	cxlds = cxl_dev_state_create(dev);
-	if (IS_ERR(cxlds))
-		return PTR_ERR(cxlds);
+	mds = cxl_memdev_state_create(dev);
+	if (IS_ERR(mds))
+		return PTR_ERR(mds);
+
+	mds->mbox_send = cxl_mock_mbox_send;
+	mds->payload_size = SZ_4K;
+	mds->event.buf = (struct cxl_get_event_payload *) mdata->event_buf;
 
+	cxlds = &mds->cxlds;
 	cxlds->serial = pdev->id;
-	cxlds->mbox_send = cxl_mock_mbox_send;
-	cxlds->payload_size = SZ_4K;
-	cxlds->event.buf = (struct cxl_get_event_payload *) mdata->event_buf;
 	if (is_rcd(pdev)) {
 		cxlds->rcd = true;
 		cxlds->component_reg_phys = CXL_RESOURCE_NONE;
 	}
 
-	rc = cxl_enumerate_cmds(cxlds);
+	rc = cxl_enumerate_cmds(mds);
 	if (rc)
 		return rc;
 
-	rc = cxl_poison_state_init(cxlds);
+	rc = cxl_poison_state_init(mds);
 	if (rc)
 		return rc;
 
-	rc = cxl_set_timestamp(cxlds);
+	rc = cxl_set_timestamp(mds);
 	if (rc)
 		return rc;
 
 	cxlds->media_ready = true;
-	rc = cxl_dev_state_identify(cxlds);
+	rc = cxl_dev_state_identify(mds);
 	if (rc)
 		return rc;
 
-	rc = cxl_mem_create_range_info(cxlds);
+	rc = cxl_mem_create_range_info(mds);
 	if (rc)
 		return rc;
 
-	mdata->mes.cxlds = cxlds;
+	mdata->mes.mds = mds;
 	cxl_mock_add_event_logs(&mdata->mes);
 
 	cxlmd = devm_cxl_add_memdev(cxlds);
 	if (IS_ERR(cxlmd))
 		return PTR_ERR(cxlmd);
 
-	cxl_mem_get_event_records(cxlds, CXLDEV_EVENT_STATUS_ALL);
+	cxl_mem_get_event_records(mds, CXLDEV_EVENT_STATUS_ALL);
 
 	return 0;
 }


^ permalink raw reply related	[flat|nested] 27+ messages in thread

* [PATCH v2 06/12] cxl/memdev: Make mailbox functionality optional
  2023-06-15  1:29 [PATCH v2 00/12] Device memory prep Dan Williams
                   ` (4 preceding siblings ...)
  2023-06-15  1:30 ` [PATCH v2 05/12] cxl/mbox: Move mailbox related driver state to its own data structure Dan Williams
@ 2023-06-15  1:30 ` Dan Williams
  2023-06-15 21:30   ` Dave Jiang
  2023-06-15  1:30 ` [PATCH v2 07/12] cxl/port: Rename CXL_DECODER_{EXPANDER, ACCELERATOR} => {HOSTONLYMEM, DEVMEM} Dan Williams
                   ` (5 subsequent siblings)
  11 siblings, 1 reply; 27+ messages in thread
From: Dan Williams @ 2023-06-15  1:30 UTC (permalink / raw)
  To: linux-cxl

In support of the Linux CXL core scaling for a wider set of CXL devices,
allow for the creation of memdevs with some memory device capabilities
disabled. Specifically, allow for CXL devices outside of those claiming
to be compliant with the generic CXL memory device class code, like
vendor specific Type-2/3 devices that host CXL.mem. This implies, allow
for the creation of memdevs that only support component-registers, not
necessarily memory-device-registers (like mailbox registers). A memdev
derived from a CXL endpoint that does not support generic class code
expectations is tagged "CXL_DEVTYPE_DEVMEM", while a memdev derived from a
class-code compliant endpoint is tagged "CXL_DEVTYPE_CLASSMEM".

The primary assumption of a CXL_DEVTYPE_DEVMEM memdev is that it
optionally may not host a mailbox. Disable the command passthrough ioctl
for memdevs that are not CXL_DEVTYPE_CLASSMEM, and return empty strings
from memdev attributes associated with data retrieved via the
class-device-standard IDENTIFY command. Note that empty strings were
chosen over attribute visibility to maintain compatibility with shipping
versions of cxl-cli that expect those attributes to always be present.
Once cxl-cli has dropped that requirement this workaround can be
deprecated.

Signed-off-by: Dan Williams <dan.j.williams@intel.com>
---
 drivers/cxl/core/mbox.c   |    1 +
 drivers/cxl/core/memdev.c |   10 +++++++++-
 drivers/cxl/cxlmem.h      |   18 ++++++++++++++++++
 3 files changed, 28 insertions(+), 1 deletion(-)

diff --git a/drivers/cxl/core/mbox.c b/drivers/cxl/core/mbox.c
index ab9d455e8579..1990a5940b7c 100644
--- a/drivers/cxl/core/mbox.c
+++ b/drivers/cxl/core/mbox.c
@@ -1272,6 +1272,7 @@ struct cxl_memdev_state *cxl_memdev_state_create(struct device *dev)
 	mutex_init(&mds->mbox_mutex);
 	mutex_init(&mds->event.log_lock);
 	mds->cxlds.dev = dev;
+	mds->cxlds.type = CXL_DEVTYPE_CLASSMEM;
 
 	return mds;
 }
diff --git a/drivers/cxl/core/memdev.c b/drivers/cxl/core/memdev.c
index 15434b1b4909..3f2d54f30548 100644
--- a/drivers/cxl/core/memdev.c
+++ b/drivers/cxl/core/memdev.c
@@ -41,6 +41,8 @@ static ssize_t firmware_version_show(struct device *dev,
 	struct cxl_dev_state *cxlds = cxlmd->cxlds;
 	struct cxl_memdev_state *mds = to_cxl_memdev_state(cxlds);
 
+	if (!mds)
+		return sysfs_emit(buf, "\n");
 	return sysfs_emit(buf, "%.16s\n", mds->firmware_version);
 }
 static DEVICE_ATTR_RO(firmware_version);
@@ -52,6 +54,8 @@ static ssize_t payload_max_show(struct device *dev,
 	struct cxl_dev_state *cxlds = cxlmd->cxlds;
 	struct cxl_memdev_state *mds = to_cxl_memdev_state(cxlds);
 
+	if (!mds)
+		return sysfs_emit(buf, "\n");
 	return sysfs_emit(buf, "%zu\n", mds->payload_size);
 }
 static DEVICE_ATTR_RO(payload_max);
@@ -63,6 +67,8 @@ static ssize_t label_storage_size_show(struct device *dev,
 	struct cxl_dev_state *cxlds = cxlmd->cxlds;
 	struct cxl_memdev_state *mds = to_cxl_memdev_state(cxlds);
 
+	if (!mds)
+		return sysfs_emit(buf, "\n");
 	return sysfs_emit(buf, "%zu\n", mds->lsa_size);
 }
 static DEVICE_ATTR_RO(label_storage_size);
@@ -517,10 +523,12 @@ static long cxl_memdev_ioctl(struct file *file, unsigned int cmd,
 			     unsigned long arg)
 {
 	struct cxl_memdev *cxlmd = file->private_data;
+	struct cxl_dev_state *cxlds;
 	int rc = -ENXIO;
 
 	down_read(&cxl_memdev_rwsem);
-	if (cxlmd->cxlds)
+	cxlds = cxlmd->cxlds;
+	if (cxlds && cxlds->type == CXL_DEVTYPE_CLASSMEM)
 		rc = __cxl_memdev_ioctl(cxlmd, cmd, arg);
 	up_read(&cxl_memdev_rwsem);
 
diff --git a/drivers/cxl/cxlmem.h b/drivers/cxl/cxlmem.h
index b1a72e01e4de..1b39afeb369e 100644
--- a/drivers/cxl/cxlmem.h
+++ b/drivers/cxl/cxlmem.h
@@ -254,6 +254,20 @@ struct cxl_poison_state {
 	struct mutex lock;  /* Protect reads of poison list */
 };
 
+/*
+ * 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_dev_state - The driver device state
  *
@@ -272,6 +286,7 @@ struct cxl_poison_state {
  * @ram_res: Active Volatile memory capacity configuration
  * @component_reg_phys: register base of component registers
  * @serial: PCIe Device Serial Number
+ * @type: Generic Memory Class device or Vendor Specific Memory device
  */
 struct cxl_dev_state {
 	struct device *dev;
@@ -285,6 +300,7 @@ struct cxl_dev_state {
 	struct resource ram_res;
 	resource_size_t component_reg_phys;
 	u64 serial;
+	enum cxl_devtype type;
 };
 
 /**
@@ -343,6 +359,8 @@ struct cxl_memdev_state {
 static inline struct cxl_memdev_state *
 to_cxl_memdev_state(struct cxl_dev_state *cxlds)
 {
+	if (cxlds->type != CXL_DEVTYPE_CLASSMEM)
+		return NULL;
 	return container_of(cxlds, struct cxl_memdev_state, cxlds);
 }
 


^ permalink raw reply related	[flat|nested] 27+ messages in thread

* [PATCH v2 07/12] cxl/port: Rename CXL_DECODER_{EXPANDER, ACCELERATOR} => {HOSTONLYMEM, DEVMEM}
  2023-06-15  1:29 [PATCH v2 00/12] Device memory prep Dan Williams
                   ` (5 preceding siblings ...)
  2023-06-15  1:30 ` [PATCH v2 06/12] cxl/memdev: Make mailbox functionality optional Dan Williams
@ 2023-06-15  1:30 ` Dan Williams
  2023-06-15 21:31   ` Dave Jiang
  2023-06-15  1:30 ` [PATCH v2 08/12] cxl/hdm: Default CXL_DEVTYPE_DEVMEM decoders to CXL_DECODER_DEVMEM Dan Williams
                   ` (4 subsequent siblings)
  11 siblings, 1 reply; 27+ messages in thread
From: Dan Williams @ 2023-06-15  1:30 UTC (permalink / raw)
  To: linux-cxl; +Cc: Jonathan Cameron

In preparation for support for HDM-D and HDM-DB configuration
(device-memory, and device-memory with back-invalidate). Rename the current
type designators to use HOSTONLYMEM and DEVMEM as a suffix.

HDM-DB can be supported by devices that are not accelerators, so DEVMEM is
a more generic term for that case.

Fixup one location where this type value was open coded.

Reviewed-by: Jonathan Cameron <Jonathan.Cameron@huawei.com>
Signed-off-by: Dan Williams <dan.j.williams@intel.com>
---
 drivers/cxl/acpi.c           |    2 +-
 drivers/cxl/core/hdm.c       |   11 ++++++-----
 drivers/cxl/core/port.c      |    6 +++---
 drivers/cxl/core/region.c    |    2 +-
 drivers/cxl/cxl.h            |    4 ++--
 tools/testing/cxl/test/cxl.c |    6 +++---
 6 files changed, 16 insertions(+), 15 deletions(-)

diff --git a/drivers/cxl/acpi.c b/drivers/cxl/acpi.c
index 7e1765b09e04..603e5df8aec0 100644
--- a/drivers/cxl/acpi.c
+++ b/drivers/cxl/acpi.c
@@ -258,7 +258,7 @@ static int cxl_parse_cfmws(union acpi_subtable_headers *header, void *arg,
 
 	cxld = &cxlrd->cxlsd.cxld;
 	cxld->flags = cfmws_to_decoder_flags(cfmws->restrictions);
-	cxld->target_type = CXL_DECODER_EXPANDER;
+	cxld->target_type = CXL_DECODER_HOSTONLYMEM;
 	cxld->hpa_range = (struct range) {
 		.start = res->start,
 		.end = res->end,
diff --git a/drivers/cxl/core/hdm.c b/drivers/cxl/core/hdm.c
index 7889ff203a34..79170de13d89 100644
--- a/drivers/cxl/core/hdm.c
+++ b/drivers/cxl/core/hdm.c
@@ -570,7 +570,8 @@ static void cxld_set_interleave(struct cxl_decoder *cxld, u32 *ctrl)
 
 static void cxld_set_type(struct cxl_decoder *cxld, u32 *ctrl)
 {
-	u32p_replace_bits(ctrl, !!(cxld->target_type == 3),
+	u32p_replace_bits(ctrl,
+			  !!(cxld->target_type == CXL_DECODER_HOSTONLYMEM),
 			  CXL_HDM_DECODER0_CTRL_TYPE);
 }
 
@@ -764,7 +765,7 @@ static int cxl_setup_hdm_decoder_from_dvsec(
 	if (!len)
 		return -ENOENT;
 
-	cxld->target_type = CXL_DECODER_EXPANDER;
+	cxld->target_type = CXL_DECODER_HOSTONLYMEM;
 	cxld->commit = NULL;
 	cxld->reset = NULL;
 	cxld->hpa_range = info->dvsec_range[which];
@@ -838,9 +839,9 @@ static int init_hdm_decoder(struct cxl_port *port, struct cxl_decoder *cxld,
 		if (ctrl & CXL_HDM_DECODER0_CTRL_LOCK)
 			cxld->flags |= CXL_DECODER_F_LOCK;
 		if (FIELD_GET(CXL_HDM_DECODER0_CTRL_TYPE, ctrl))
-			cxld->target_type = CXL_DECODER_EXPANDER;
+			cxld->target_type = CXL_DECODER_HOSTONLYMEM;
 		else
-			cxld->target_type = CXL_DECODER_ACCELERATOR;
+			cxld->target_type = CXL_DECODER_DEVMEM;
 		if (cxld->id != port->commit_end + 1) {
 			dev_warn(&port->dev,
 				 "decoder%d.%d: Committed out of order\n",
@@ -861,7 +862,7 @@ static int init_hdm_decoder(struct cxl_port *port, struct cxl_decoder *cxld,
 			ctrl |= CXL_HDM_DECODER0_CTRL_TYPE;
 			writel(ctrl, hdm + CXL_HDM_DECODER0_CTRL_OFFSET(which));
 		}
-		cxld->target_type = CXL_DECODER_EXPANDER;
+		cxld->target_type = CXL_DECODER_HOSTONLYMEM;
 	}
 	rc = eiw_to_ways(FIELD_GET(CXL_HDM_DECODER0_CTRL_IW_MASK, ctrl),
 			  &cxld->interleave_ways);
diff --git a/drivers/cxl/core/port.c b/drivers/cxl/core/port.c
index e7c284c890bc..6d7811b26b5a 100644
--- a/drivers/cxl/core/port.c
+++ b/drivers/cxl/core/port.c
@@ -117,9 +117,9 @@ static ssize_t target_type_show(struct device *dev,
 	struct cxl_decoder *cxld = to_cxl_decoder(dev);
 
 	switch (cxld->target_type) {
-	case CXL_DECODER_ACCELERATOR:
+	case CXL_DECODER_DEVMEM:
 		return sysfs_emit(buf, "accelerator\n");
-	case CXL_DECODER_EXPANDER:
+	case CXL_DECODER_HOSTONLYMEM:
 		return sysfs_emit(buf, "expander\n");
 	}
 	return -ENXIO;
@@ -1550,7 +1550,7 @@ static int cxl_decoder_init(struct cxl_port *port, struct cxl_decoder *cxld)
 	/* Pre initialize an "empty" decoder */
 	cxld->interleave_ways = 1;
 	cxld->interleave_granularity = PAGE_SIZE;
-	cxld->target_type = CXL_DECODER_EXPANDER;
+	cxld->target_type = CXL_DECODER_HOSTONLYMEM;
 	cxld->hpa_range = (struct range) {
 		.start = 0,
 		.end = -1,
diff --git a/drivers/cxl/core/region.c b/drivers/cxl/core/region.c
index f822de44bee0..6a875f86901b 100644
--- a/drivers/cxl/core/region.c
+++ b/drivers/cxl/core/region.c
@@ -2103,7 +2103,7 @@ static struct cxl_region *__create_region(struct cxl_root_decoder *cxlrd,
 		return ERR_PTR(-EBUSY);
 	}
 
-	return devm_cxl_add_region(cxlrd, id, mode, CXL_DECODER_EXPANDER);
+	return devm_cxl_add_region(cxlrd, id, mode, CXL_DECODER_HOSTONLYMEM);
 }
 
 static ssize_t create_pmem_region_store(struct device *dev,
diff --git a/drivers/cxl/cxl.h b/drivers/cxl/cxl.h
index dfc94e76c7d6..ae0965ac8c5a 100644
--- a/drivers/cxl/cxl.h
+++ b/drivers/cxl/cxl.h
@@ -290,8 +290,8 @@ resource_size_t cxl_rcrb_to_component(struct device *dev,
 #define CXL_DECODER_F_MASK  GENMASK(5, 0)
 
 enum cxl_decoder_type {
-       CXL_DECODER_ACCELERATOR = 2,
-       CXL_DECODER_EXPANDER = 3,
+	CXL_DECODER_DEVMEM = 2,
+	CXL_DECODER_HOSTONLYMEM = 3,
 };
 
 /*
diff --git a/tools/testing/cxl/test/cxl.c b/tools/testing/cxl/test/cxl.c
index bf00dc52fe96..5565164d6658 100644
--- a/tools/testing/cxl/test/cxl.c
+++ b/tools/testing/cxl/test/cxl.c
@@ -713,7 +713,7 @@ static void default_mock_decoder(struct cxl_decoder *cxld)
 
 	cxld->interleave_ways = 1;
 	cxld->interleave_granularity = 256;
-	cxld->target_type = CXL_DECODER_EXPANDER;
+	cxld->target_type = CXL_DECODER_HOSTONLYMEM;
 	cxld->commit = mock_decoder_commit;
 	cxld->reset = mock_decoder_reset;
 }
@@ -787,7 +787,7 @@ static void mock_init_hdm_decoder(struct cxl_decoder *cxld)
 
 	cxld->interleave_ways = 2;
 	eig_to_granularity(window->granularity, &cxld->interleave_granularity);
-	cxld->target_type = CXL_DECODER_EXPANDER;
+	cxld->target_type = CXL_DECODER_HOSTONLYMEM;
 	cxld->flags = CXL_DECODER_F_ENABLE;
 	cxled->state = CXL_DECODER_STATE_AUTO;
 	port->commit_end = cxld->id;
@@ -820,7 +820,7 @@ static void mock_init_hdm_decoder(struct cxl_decoder *cxld)
 		} else
 			cxlsd->target[0] = dport;
 		cxld = &cxlsd->cxld;
-		cxld->target_type = CXL_DECODER_EXPANDER;
+		cxld->target_type = CXL_DECODER_HOSTONLYMEM;
 		cxld->flags = CXL_DECODER_F_ENABLE;
 		iter->commit_end = 0;
 		/*


^ permalink raw reply related	[flat|nested] 27+ messages in thread

* [PATCH v2 08/12] cxl/hdm: Default CXL_DEVTYPE_DEVMEM decoders to CXL_DECODER_DEVMEM
  2023-06-15  1:29 [PATCH v2 00/12] Device memory prep Dan Williams
                   ` (6 preceding siblings ...)
  2023-06-15  1:30 ` [PATCH v2 07/12] cxl/port: Rename CXL_DECODER_{EXPANDER, ACCELERATOR} => {HOSTONLYMEM, DEVMEM} Dan Williams
@ 2023-06-15  1:30 ` Dan Williams
  2023-06-15 21:32   ` Dave Jiang
  2023-06-15  1:30 ` [PATCH v2 09/12] cxl/region: Manage decoder target_type at decoder-attach time Dan Williams
                   ` (3 subsequent siblings)
  11 siblings, 1 reply; 27+ messages in thread
From: Dan Williams @ 2023-06-15  1:30 UTC (permalink / raw)
  To: linux-cxl; +Cc: Jonathan Cameron

In preparation for device-memory region creation, arrange for decoders
of CXL_DEVTYPE_DEVMEM memdevs to default to CXL_DECODER_DEVMEM for their
target type.

Revisit this if a device ever shows up that wants to offer mixed HDM-H
(Host-Only Memory) and HDM-DB support, or an CXL_DEVTYPE_DEVMEM device
that supports HDM-H.

Reviewed-by: Jonathan Cameron <Jonathan.Cameron@huawei.com>
Signed-off-by: Dan Williams <dan.j.williams@intel.com>
---
 drivers/cxl/core/hdm.c |   35 ++++++++++++++++++++++++++---------
 drivers/cxl/cxl.h      |    2 +-
 2 files changed, 27 insertions(+), 10 deletions(-)

diff --git a/drivers/cxl/core/hdm.c b/drivers/cxl/core/hdm.c
index 79170de13d89..715c1f103739 100644
--- a/drivers/cxl/core/hdm.c
+++ b/drivers/cxl/core/hdm.c
@@ -572,7 +572,7 @@ static void cxld_set_type(struct cxl_decoder *cxld, u32 *ctrl)
 {
 	u32p_replace_bits(ctrl,
 			  !!(cxld->target_type == CXL_DECODER_HOSTONLYMEM),
-			  CXL_HDM_DECODER0_CTRL_TYPE);
+			  CXL_HDM_DECODER0_CTRL_HOSTONLY);
 }
 
 static int cxlsd_set_targets(struct cxl_switch_decoder *cxlsd, u64 *tgt)
@@ -794,8 +794,8 @@ static int init_hdm_decoder(struct cxl_port *port, struct cxl_decoder *cxld,
 			    int *target_map, void __iomem *hdm, int which,
 			    u64 *dpa_base, struct cxl_endpoint_dvsec_info *info)
 {
+	struct cxl_endpoint_decoder *cxled = NULL;
 	u64 size, base, skip, dpa_size, lo, hi;
-	struct cxl_endpoint_decoder *cxled;
 	bool committed;
 	u32 remainder;
 	int i, rc;
@@ -828,6 +828,8 @@ static int init_hdm_decoder(struct cxl_port *port, struct cxl_decoder *cxld,
 		return -ENXIO;
 	}
 
+	if (info)
+		cxled = to_cxl_endpoint_decoder(&cxld->dev);
 	cxld->hpa_range = (struct range) {
 		.start = base,
 		.end = base + size - 1,
@@ -838,7 +840,7 @@ static int init_hdm_decoder(struct cxl_port *port, struct cxl_decoder *cxld,
 		cxld->flags |= CXL_DECODER_F_ENABLE;
 		if (ctrl & CXL_HDM_DECODER0_CTRL_LOCK)
 			cxld->flags |= CXL_DECODER_F_LOCK;
-		if (FIELD_GET(CXL_HDM_DECODER0_CTRL_TYPE, ctrl))
+		if (FIELD_GET(CXL_HDM_DECODER0_CTRL_HOSTONLY, ctrl))
 			cxld->target_type = CXL_DECODER_HOSTONLYMEM;
 		else
 			cxld->target_type = CXL_DECODER_DEVMEM;
@@ -857,12 +859,28 @@ static int init_hdm_decoder(struct cxl_port *port, struct cxl_decoder *cxld,
 		}
 		port->commit_end = cxld->id;
 	} else {
-		/* unless / until type-2 drivers arrive, assume type-3 */
-		if (FIELD_GET(CXL_HDM_DECODER0_CTRL_TYPE, ctrl) == 0) {
-			ctrl |= CXL_HDM_DECODER0_CTRL_TYPE;
+		if (cxled) {
+			struct cxl_memdev *cxlmd = cxled_to_memdev(cxled);
+			struct cxl_dev_state *cxlds = cxlmd->cxlds;
+
+			/*
+			 * Default by devtype until a device arrives that needs
+			 * more precision.
+			 */
+			if (cxlds->type == CXL_DEVTYPE_CLASSMEM)
+				cxld->target_type = CXL_DECODER_HOSTONLYMEM;
+			else
+				cxld->target_type = CXL_DECODER_DEVMEM;
+		} else {
+			/* To be overridden by region type at commit time */
+			cxld->target_type = CXL_DECODER_HOSTONLYMEM;
+		}
+
+		if (!FIELD_GET(CXL_HDM_DECODER0_CTRL_HOSTONLY, ctrl) &&
+		    cxld->target_type == CXL_DECODER_HOSTONLYMEM) {
+			ctrl |= CXL_HDM_DECODER0_CTRL_HOSTONLY;
 			writel(ctrl, hdm + CXL_HDM_DECODER0_CTRL_OFFSET(which));
 		}
-		cxld->target_type = CXL_DECODER_HOSTONLYMEM;
 	}
 	rc = eiw_to_ways(FIELD_GET(CXL_HDM_DECODER0_CTRL_IW_MASK, ctrl),
 			  &cxld->interleave_ways);
@@ -881,7 +899,7 @@ static int init_hdm_decoder(struct cxl_port *port, struct cxl_decoder *cxld,
 		port->id, cxld->id, cxld->hpa_range.start, cxld->hpa_range.end,
 		cxld->interleave_ways, cxld->interleave_granularity);
 
-	if (!info) {
+	if (!cxled) {
 		lo = readl(hdm + CXL_HDM_DECODER0_TL_LOW(which));
 		hi = readl(hdm + CXL_HDM_DECODER0_TL_HIGH(which));
 		target_list.value = (hi << 32) + lo;
@@ -904,7 +922,6 @@ static int init_hdm_decoder(struct cxl_port *port, struct cxl_decoder *cxld,
 	lo = readl(hdm + CXL_HDM_DECODER0_SKIP_LOW(which));
 	hi = readl(hdm + CXL_HDM_DECODER0_SKIP_HIGH(which));
 	skip = (hi << 32) + lo;
-	cxled = to_cxl_endpoint_decoder(&cxld->dev);
 	rc = devm_cxl_dpa_reserve(cxled, *dpa_base + skip, dpa_size, skip);
 	if (rc) {
 		dev_err(&port->dev,
diff --git a/drivers/cxl/cxl.h b/drivers/cxl/cxl.h
index ae0965ac8c5a..f309b1387858 100644
--- a/drivers/cxl/cxl.h
+++ b/drivers/cxl/cxl.h
@@ -56,7 +56,7 @@
 #define   CXL_HDM_DECODER0_CTRL_COMMIT BIT(9)
 #define   CXL_HDM_DECODER0_CTRL_COMMITTED BIT(10)
 #define   CXL_HDM_DECODER0_CTRL_COMMIT_ERROR BIT(11)
-#define   CXL_HDM_DECODER0_CTRL_TYPE BIT(12)
+#define   CXL_HDM_DECODER0_CTRL_HOSTONLY BIT(12)
 #define CXL_HDM_DECODER0_TL_LOW(i) (0x20 * (i) + 0x24)
 #define CXL_HDM_DECODER0_TL_HIGH(i) (0x20 * (i) + 0x28)
 #define CXL_HDM_DECODER0_SKIP_LOW(i) CXL_HDM_DECODER0_TL_LOW(i)


^ permalink raw reply related	[flat|nested] 27+ messages in thread

* [PATCH v2 09/12] cxl/region: Manage decoder target_type at decoder-attach time
  2023-06-15  1:29 [PATCH v2 00/12] Device memory prep Dan Williams
                   ` (7 preceding siblings ...)
  2023-06-15  1:30 ` [PATCH v2 08/12] cxl/hdm: Default CXL_DEVTYPE_DEVMEM decoders to CXL_DECODER_DEVMEM Dan Williams
@ 2023-06-15  1:30 ` Dan Williams
  2023-06-15  1:30 ` [PATCH v2 10/12] cxl/pci: Unconditionally unmask 256B Flit errors Dan Williams
                   ` (2 subsequent siblings)
  11 siblings, 0 replies; 27+ messages in thread
From: Dan Williams @ 2023-06-15  1:30 UTC (permalink / raw)
  To: linux-cxl; +Cc: Jonathan Cameron, Dave Jiang

Switch-level (mid-level) decoders between the platform root and an
endpoint can dynamically switch modes between HDM-H and HDM-D[B]
depending on which region they target. Use the region type to fixup each
decoder that gets allocated to map the given region.

Note that endpoint decoders are meant to determine the region type, so
warn if those ever need to be fixed up, but since it is possible to
continue do so.

Reviewed-by: Jonathan Cameron <Jonathan.Cameron@huawei.com>
Reviewed-by: Dave Jiang <dave.jiang@intel.com>
Signed-off-by: Dan Williams <dan.j.williams@intel.com>
---
 drivers/cxl/core/region.c |   12 ++++++++++++
 1 file changed, 12 insertions(+)

diff --git a/drivers/cxl/core/region.c b/drivers/cxl/core/region.c
index 6a875f86901b..013f3656e661 100644
--- a/drivers/cxl/core/region.c
+++ b/drivers/cxl/core/region.c
@@ -809,6 +809,18 @@ static int cxl_rr_alloc_decoder(struct cxl_port *port, struct cxl_region *cxlr,
 		return -EBUSY;
 	}
 
+	/*
+	 * Endpoints should already match the region type, but backstop that
+	 * assumption with an assertion. Switch-decoders change mapping-type
+	 * based on what is mapped when they are assigned to a region.
+	 */
+	dev_WARN_ONCE(&cxlr->dev,
+		      port == cxled_to_port(cxled) &&
+			      cxld->target_type != cxlr->type,
+		      "%s:%s mismatch decoder type %d -> %d\n",
+		      dev_name(&cxled_to_memdev(cxled)->dev),
+		      dev_name(&cxld->dev), cxld->target_type, cxlr->type);
+	cxld->target_type = cxlr->type;
 	cxl_rr->decoder = cxld;
 	return 0;
 }


^ permalink raw reply related	[flat|nested] 27+ messages in thread

* [PATCH v2 10/12] cxl/pci: Unconditionally unmask 256B Flit errors
  2023-06-15  1:29 [PATCH v2 00/12] Device memory prep Dan Williams
                   ` (8 preceding siblings ...)
  2023-06-15  1:30 ` [PATCH v2 09/12] cxl/region: Manage decoder target_type at decoder-attach time Dan Williams
@ 2023-06-15  1:30 ` Dan Williams
  2023-06-15 21:34   ` Dave Jiang
  2023-06-15  1:30 ` [PATCH v2 11/12] cxl/port: Enumerate cxl link capabilities Dan Williams
  2023-06-15  1:30 ` [PATCH v2 12/12] cxl/memdev: Formalize endpoint port linkage Dan Williams
  11 siblings, 1 reply; 27+ messages in thread
From: Dan Williams @ 2023-06-15  1:30 UTC (permalink / raw)
  To: linux-cxl

The current check for 256B Flit mode is incomplete and unnecessary. It
is incomplete because it fails to consider the link speed, or check for
CXL link capabilities. It is unnecessary because unconditionally
unmasking 256B Flit errors is a nop when 256B Flit operation is not
available.

Remove this check in preparation for creating a cxl_probe_link() helper
to centralize this detection.

Signed-off-by: Dan Williams <dan.j.williams@intel.com>
---
 drivers/cxl/pci.c |   18 ++----------------
 1 file changed, 2 insertions(+), 16 deletions(-)

diff --git a/drivers/cxl/pci.c b/drivers/cxl/pci.c
index 4e2845b7331a..3f78082014cc 100644
--- a/drivers/cxl/pci.c
+++ b/drivers/cxl/pci.c
@@ -368,19 +368,6 @@ static bool is_cxl_restricted(struct pci_dev *pdev)
 	return pci_pcie_type(pdev) == PCI_EXP_TYPE_RC_END;
 }
 
-/*
- * CXL v3.0 6.2.3 Table 6-4
- * The table indicates that if PCIe Flit Mode is set, then CXL is in 256B flits
- * mode, otherwise it's 68B flits mode.
- */
-static bool cxl_pci_flit_256(struct pci_dev *pdev)
-{
-	u16 lnksta2;
-
-	pcie_capability_read_word(pdev, PCI_EXP_LNKSTA2, &lnksta2);
-	return lnksta2 & PCI_EXP_LNKSTA2_FLIT;
-}
-
 static int cxl_pci_ras_unmask(struct pci_dev *pdev)
 {
 	struct pci_host_bridge *host_bridge = pci_find_host_bridge(pdev->bus);
@@ -407,9 +394,8 @@ static int cxl_pci_ras_unmask(struct pci_dev *pdev)
 		addr = cxlds->regs.ras + CXL_RAS_UNCORRECTABLE_MASK_OFFSET;
 		orig_val = readl(addr);
 
-		mask = CXL_RAS_UNCORRECTABLE_MASK_MASK;
-		if (!cxl_pci_flit_256(pdev))
-			mask &= ~CXL_RAS_UNCORRECTABLE_MASK_F256B_MASK;
+		mask = CXL_RAS_UNCORRECTABLE_MASK_MASK |
+		       CXL_RAS_UNCORRECTABLE_MASK_F256B_MASK;
 		val = orig_val & ~mask;
 		writel(val, addr);
 		dev_dbg(&pdev->dev,


^ permalink raw reply related	[flat|nested] 27+ messages in thread

* [PATCH v2 11/12] cxl/port: Enumerate cxl link capabilities
  2023-06-15  1:29 [PATCH v2 00/12] Device memory prep Dan Williams
                   ` (9 preceding siblings ...)
  2023-06-15  1:30 ` [PATCH v2 10/12] cxl/pci: Unconditionally unmask 256B Flit errors Dan Williams
@ 2023-06-15  1:30 ` Dan Williams
  2023-06-15 21:37   ` Dave Jiang
  2023-06-16  0:07   ` Dan Williams
  2023-06-15  1:30 ` [PATCH v2 12/12] cxl/memdev: Formalize endpoint port linkage Dan Williams
  11 siblings, 2 replies; 27+ messages in thread
From: Dan Williams @ 2023-06-15  1:30 UTC (permalink / raw)
  To: linux-cxl

Per CXL 3.0 9.14 "Back-Invalidation Configuration", in order to enable
an HDM-DB range (CXL.mem region with device initiated back-invalidation
support), all ports in the path between the endpoint and the host bridge
must be in 256-bit flit-mode.

Even for typical Type-3 class devices it is useful to enumerate link
capabilities through the topology for debug purposes.

See CXL 3.0 Table-64 "256B Flit Mode vs. 68B Flit Mode Operation", for
how to determine 64B vs 256B Flit mode operation.

Signed-off-by: Dan Williams <dan.j.williams@intel.com>
---
 drivers/cxl/core/pci.c  |  113 +++++++++++++++++++++++++++++++++++++++++++++++
 drivers/cxl/core/port.c |    6 ++
 drivers/cxl/cxl.h       |    7 +++
 drivers/cxl/cxlpci.h    |   24 +++++++++-
 drivers/cxl/port.c      |    5 ++
 5 files changed, 153 insertions(+), 2 deletions(-)

diff --git a/drivers/cxl/core/pci.c b/drivers/cxl/core/pci.c
index 67f4ab6daa34..7440f84be6c8 100644
--- a/drivers/cxl/core/pci.c
+++ b/drivers/cxl/core/pci.c
@@ -519,6 +519,119 @@ int cxl_hdm_decode_init(struct cxl_dev_state *cxlds, struct cxl_hdm *cxlhdm,
 }
 EXPORT_SYMBOL_NS_GPL(cxl_hdm_decode_init, CXL);
 
+static struct pci_dev *cxl_port_to_pci(struct cxl_port *port)
+{
+	struct device *dev;
+
+	if (is_cxl_endpoint(port))
+		dev = port->uport->parent;
+	else
+		dev = port->uport;
+
+	if (!dev_is_pci(dev))
+		return NULL;
+
+	return to_pci_dev(dev);
+}
+
+int cxl_probe_link(struct cxl_port *port)
+{
+	u16 cap, en, lnksta, lnksta2, parent_features;
+	struct pci_dev *pdev = cxl_port_to_pci(port);
+	struct cxl_port *parent_port;
+	unsigned long features;
+	struct device *dev;
+	int rc, dvsec;
+	u32 hdr;
+
+	if (!pdev) {
+		/*
+		 * Assume host bridges support all features, the root
+		 * port will dictate the actual enabled set to endpoints.
+		 */
+		return 0;
+	}
+
+	dev = &pdev->dev;
+	dvsec = pci_find_dvsec_capability(pdev, PCI_DVSEC_VENDOR_ID_CXL,
+					  CXL_DVSEC_FLEXBUS_PORT);
+	if (!dvsec) {
+		dev_err(dev, "Failed to enumerate port capabilities\n");
+		return -ENXIO;
+	}
+
+	/*
+	 * Cache the link features for future determination of 256B Flit
+	 * mode dependent operation support e.g. HDM-DB.
+	 */
+	rc = pci_read_config_dword(pdev, dvsec + PCI_DVSEC_HEADER1, &hdr);
+	if (rc)
+		return rc;
+
+	rc = pci_read_config_word(pdev, dvsec + CXL_DVSEC_FLEXBUS_CAP_OFFSET,
+				  &cap);
+	if (rc)
+		return rc;
+
+	rc = pci_read_config_word(pdev, dvsec + CXL_DVSEC_FLEXBUS_STATUS_OFFSET,
+				  &en);
+	if (rc)
+		return rc;
+
+	features = en & cap & CXL_DVSEC_FLEXBUS_ENABLE_MASK;
+	if ((features & CXL_DVSEC_FLEXBUS_CXL_MASK) == 0)
+		goto no_cxl;
+
+	/* Determine flit mode from link speed and CXL active */
+	rc = pcie_capability_read_word(pdev, PCI_EXP_LNKSTA, &lnksta);
+	if (rc)
+		return rc;
+
+	rc = pcie_capability_read_word(pdev, PCI_EXP_LNKSTA2, &lnksta2);
+	if (rc)
+		return rc;
+
+	/* CXL 3.0 Table-64 256B Flit Mode vs. 68B Flit Mode Operation */
+	switch (FIELD_GET(PCI_EXP_LNKSTA_CLS, lnksta)) {
+	case PCI_EXP_LNKSTA_CLS_2_5GB:
+	case PCI_EXP_LNKSTA_CLS_5_0GB:
+		break;
+	case PCI_EXP_LNKSTA_CLS_8_0GB:
+	case PCI_EXP_LNKSTA_CLS_16_0GB:
+	case PCI_EXP_LNKSTA_CLS_32_0GB:
+		if ((lnksta2 & PCI_EXP_LNKSTA2_FLIT) == 0) {
+			features |= CXL_PORT_FEATURE_FLIT68;
+			break;
+		}
+		fallthrough;
+	case PCI_EXP_LNKSTA_CLS_64_0GB:
+	default:
+		features |= CXL_PORT_FEATURE_FLIT256;
+		break;
+	}
+
+no_cxl:
+	parent_port = to_cxl_port(port->dev.parent);
+	parent_features = parent_port->features;
+
+	/* Enforce port features are plumbed through to the host bridge */
+	features &= parent_features;
+
+	dev_dbg(dev, "features:%s%s%s%s%s%s%s%s%s\n",
+		features & CXL_DVSEC_FLEXBUS_CACHE_ENABLED ? " cache" : "",
+		features & CXL_DVSEC_FLEXBUS_IO_ENABLED ? " io" : "",
+		features & CXL_DVSEC_FLEXBUS_MEM_ENABLED ? " mem" : "",
+		features & CXL_DVSEC_FLEXBUS_VH_ENABLED ? " vh" : "",
+		features & CXL_DVSEC_FLEXBUS_MLD_ENABLED ? " mld" : "",
+		features & CXL_DVSEC_FLEXBUS_LATOPT_ENABLED ? " latopt" : "",
+		features & CXL_DVSEC_FLEXBUS_PBR_ENABLED ? " pbr" : "",
+		features & CXL_PORT_FEATURE_FLIT68 ? " flit68" : "",
+		features & CXL_PORT_FEATURE_FLIT256 ? " flit256" : "");
+
+	return 0;
+}
+EXPORT_SYMBOL_NS_GPL(cxl_probe_link, CXL);
+
 #define CXL_DOE_TABLE_ACCESS_REQ_CODE		0x000000ff
 #define   CXL_DOE_TABLE_ACCESS_REQ_CODE_READ	0
 #define CXL_DOE_TABLE_ACCESS_TABLE_TYPE		0x0000ff00
diff --git a/drivers/cxl/core/port.c b/drivers/cxl/core/port.c
index 6d7811b26b5a..bf8f25063914 100644
--- a/drivers/cxl/core/port.c
+++ b/drivers/cxl/core/port.c
@@ -665,6 +665,12 @@ static struct cxl_port *cxl_port_alloc(struct device *uport,
 	} else
 		dev->parent = uport;
 
+	/*
+	 * Assume all CXL link capabilities for root-device-to-host-bridge link,
+	 * cxl_probe_link() will fix this up later in cxl_probe_link() for all
+	 * other ports.
+	 */
+	port->features = CXL_DVSEC_FLEXBUS_ENABLE_MASK;
 	port->component_reg_phys = component_reg_phys;
 	ida_init(&port->decoder_ida);
 	port->hdm_end = -1;
diff --git a/drivers/cxl/cxl.h b/drivers/cxl/cxl.h
index f309b1387858..74548f8f5f4c 100644
--- a/drivers/cxl/cxl.h
+++ b/drivers/cxl/cxl.h
@@ -536,6 +536,10 @@ struct cxl_dax_region {
 	struct range hpa_range;
 };
 
+/* These start after CXL_DVSEC_FLEXBUS_*_ENABLED bits in port->features */
+#define CXL_PORT_FEATURE_FLIT68 BIT(16)
+#define CXL_PORT_FEATURE_FLIT256 BIT(17)
+
 /**
  * struct cxl_port - logical collection of upstream port devices and
  *		     downstream port devices to construct a CXL memory
@@ -557,6 +561,8 @@ struct cxl_dax_region {
  * @depth: How deep this port is relative to the root. depth 0 is the root.
  * @cdat: Cached CDAT data
  * @cdat_available: Should a CDAT attribute be available in sysfs
+ * @features: active link features (see CXL_DVSEC_FLEXBUS_*_ENABLED +
+ *  CXL_PORT_FEATURE_*)
  */
 struct cxl_port {
 	struct device dev;
@@ -579,6 +585,7 @@ struct cxl_port {
 		size_t length;
 	} cdat;
 	bool cdat_available;
+	unsigned long features;
 };
 
 static inline struct cxl_dport *
diff --git a/drivers/cxl/cxlpci.h b/drivers/cxl/cxlpci.h
index 7c02e55b8042..0da6618e0df7 100644
--- a/drivers/cxl/cxlpci.h
+++ b/drivers/cxl/cxlpci.h
@@ -45,8 +45,27 @@
 /* CXL 2.0 8.1.7: GPF DVSEC for CXL Device */
 #define CXL_DVSEC_DEVICE_GPF					5
 
-/* CXL 2.0 8.1.8: PCIe DVSEC for Flex Bus Port */
-#define CXL_DVSEC_PCIE_FLEXBUS_PORT				7
+/* CXL 3.0 8.2.1.3: PCIe DVSEC for Flex Bus Port */
+#define CXL_DVSEC_FLEXBUS_PORT					7
+#define   CXL_DVSEC_FLEXBUS_CAP_OFFSET		0xA
+#define     CXL_DVSEC_FLEXBUS_CACHE_CAPABLE	BIT(0)
+#define     CXL_DVSEC_FLEXBUS_IO_CAPABLE	BIT(1)
+#define     CXL_DVSEC_FLEXBUS_MEM_CAPABLE	BIT(2)
+#define     CXL_DVSEC_FLEXBUS_VH_CAPABLE	BIT(5)
+#define     CXL_DVSEC_FLEXBUS_MLD_CAPABLE	BIT(6)
+#define     CXL_DVSEC_FLEXBUS_LATOPT_CAPABLE	BIT(13)
+#define     CXL_DVSEC_FLEXBUS_PBR_CAPABLE	BIT(14)
+#define   CXL_DVSEC_FLEXBUS_STATUS_OFFSET	0xE
+#define     CXL_DVSEC_FLEXBUS_CACHE_ENABLED	BIT(0)
+#define     CXL_DVSEC_FLEXBUS_IO_ENABLED	BIT(1)
+#define     CXL_DVSEC_FLEXBUS_MEM_ENABLED	BIT(2)
+#define     CXL_DVSEC_FLEXBUS_VH_ENABLED	BIT(5)
+#define     CXL_DVSEC_FLEXBUS_MLD_ENABLED	BIT(6)
+#define     CXL_DVSEC_FLEXBUS_LATOPT_ENABLED	BIT(13)
+#define     CXL_DVSEC_FLEXBUS_PBR_ENABLED	BIT(14)
+#define     CXL_DVSEC_FLEXBUS_ENABLE_MASK \
+	(GENMASK(2, 0) | GENMASK(6, 5) | GENMASK(14, 13))
+#define CXL_DVSEC_FLEXBUS_CXL_MASK GENMASK(2, 0)
 
 /* CXL 2.0 8.1.9: Register Locator DVSEC */
 #define CXL_DVSEC_REG_LOCATOR					8
@@ -88,6 +107,7 @@ int devm_cxl_port_enumerate_dports(struct cxl_port *port);
 struct cxl_dev_state;
 int cxl_hdm_decode_init(struct cxl_dev_state *cxlds, struct cxl_hdm *cxlhdm,
 			struct cxl_endpoint_dvsec_info *info);
+int cxl_probe_link(struct cxl_port *port);
 void read_cdat_data(struct cxl_port *port);
 void cxl_cor_error_detected(struct pci_dev *pdev);
 pci_ers_result_t cxl_error_detected(struct pci_dev *pdev,
diff --git a/drivers/cxl/port.c b/drivers/cxl/port.c
index c23b6164e1c0..5ffe3c7d2f5e 100644
--- a/drivers/cxl/port.c
+++ b/drivers/cxl/port.c
@@ -140,6 +140,11 @@ static int cxl_endpoint_port_probe(struct cxl_port *port)
 static int cxl_port_probe(struct device *dev)
 {
 	struct cxl_port *port = to_cxl_port(dev);
+	int rc;
+
+	rc = cxl_probe_link(port);
+	if (rc)
+		return rc;
 
 	if (is_cxl_endpoint(port))
 		return cxl_endpoint_port_probe(port);


^ permalink raw reply related	[flat|nested] 27+ messages in thread

* [PATCH v2 12/12] cxl/memdev: Formalize endpoint port linkage
  2023-06-15  1:29 [PATCH v2 00/12] Device memory prep Dan Williams
                   ` (10 preceding siblings ...)
  2023-06-15  1:30 ` [PATCH v2 11/12] cxl/port: Enumerate cxl link capabilities Dan Williams
@ 2023-06-15  1:30 ` Dan Williams
  11 siblings, 0 replies; 27+ messages in thread
From: Dan Williams @ 2023-06-15  1:30 UTC (permalink / raw)
  To: linux-cxl; +Cc: Fan Ni, Jonathan Cameron, Dave Jiang

Move the endpoint port that the cxl_mem driver establishes from drvdata
to a first class attribute. This is in preparation for device-memory
drivers reusing the CXL core for memory region management. Those drivers
need a type-safe method to retrieve their CXL port linkage. Leave
drvdata for private usage of the cxl_mem driver not external consumers
of a 'struct cxl_memdev' object.

Reviewed-by: Fan Ni <fan.ni@samsung.com>
Reviewed-by: Jonathan Cameron <Jonathan.Cameron@huawei.com>
Reviewed-by: Dave Jiang <dave.jiang@intel.com>
Signed-off-by: Dan Williams <dan.j.williams@intel.com>
---
 drivers/cxl/core/memdev.c |    4 ++--
 drivers/cxl/core/pmem.c   |    2 +-
 drivers/cxl/core/port.c   |    5 +++--
 drivers/cxl/cxlmem.h      |    2 ++
 4 files changed, 8 insertions(+), 5 deletions(-)

diff --git a/drivers/cxl/core/memdev.c b/drivers/cxl/core/memdev.c
index 3f2d54f30548..65a685e5616f 100644
--- a/drivers/cxl/core/memdev.c
+++ b/drivers/cxl/core/memdev.c
@@ -149,7 +149,7 @@ int cxl_trigger_poison_list(struct cxl_memdev *cxlmd)
 	struct cxl_port *port;
 	int rc;
 
-	port = dev_get_drvdata(&cxlmd->dev);
+	port = cxlmd->endpoint;
 	if (!port || !is_cxl_endpoint(port))
 		return -EINVAL;
 
@@ -207,7 +207,7 @@ static struct cxl_region *cxl_dpa_to_region(struct cxl_memdev *cxlmd, u64 dpa)
 	ctx = (struct cxl_dpa_to_region_context) {
 		.dpa = dpa,
 	};
-	port = dev_get_drvdata(&cxlmd->dev);
+	port = cxlmd->endpoint;
 	if (port && is_cxl_endpoint(port) && port->commit_end != -1)
 		device_for_each_child(&port->dev, &ctx, __cxl_dpa_to_region);
 
diff --git a/drivers/cxl/core/pmem.c b/drivers/cxl/core/pmem.c
index f8c38d997252..fc94f5240327 100644
--- a/drivers/cxl/core/pmem.c
+++ b/drivers/cxl/core/pmem.c
@@ -64,7 +64,7 @@ static int match_nvdimm_bridge(struct device *dev, void *data)
 
 struct cxl_nvdimm_bridge *cxl_find_nvdimm_bridge(struct cxl_memdev *cxlmd)
 {
-	struct cxl_port *port = find_cxl_root(dev_get_drvdata(&cxlmd->dev));
+	struct cxl_port *port = find_cxl_root(cxlmd->endpoint);
 	struct device *dev;
 
 	if (!port)
diff --git a/drivers/cxl/core/port.c b/drivers/cxl/core/port.c
index bf8f25063914..19252ef5ecbc 100644
--- a/drivers/cxl/core/port.c
+++ b/drivers/cxl/core/port.c
@@ -1167,7 +1167,7 @@ static struct device *grandparent(struct device *dev)
 static void delete_endpoint(void *data)
 {
 	struct cxl_memdev *cxlmd = data;
-	struct cxl_port *endpoint = dev_get_drvdata(&cxlmd->dev);
+	struct cxl_port *endpoint = cxlmd->endpoint;
 	struct cxl_port *parent_port;
 	struct device *parent;
 
@@ -1182,6 +1182,7 @@ static void delete_endpoint(void *data)
 		devm_release_action(parent, cxl_unlink_uport, endpoint);
 		devm_release_action(parent, unregister_port, endpoint);
 	}
+	cxlmd->endpoint = NULL;
 	device_unlock(parent);
 	put_device(parent);
 out:
@@ -1193,7 +1194,7 @@ int cxl_endpoint_autoremove(struct cxl_memdev *cxlmd, struct cxl_port *endpoint)
 	struct device *dev = &cxlmd->dev;
 
 	get_device(&endpoint->dev);
-	dev_set_drvdata(dev, endpoint);
+	cxlmd->endpoint = endpoint;
 	cxlmd->depth = endpoint->depth;
 	return devm_add_action_or_reset(dev, delete_endpoint, cxlmd);
 }
diff --git a/drivers/cxl/cxlmem.h b/drivers/cxl/cxlmem.h
index 1b39afeb369e..9aa8876a4eea 100644
--- a/drivers/cxl/cxlmem.h
+++ b/drivers/cxl/cxlmem.h
@@ -38,6 +38,7 @@
  * @detach_work: active memdev lost a port in its ancestry
  * @cxl_nvb: coordinate removal of @cxl_nvd if present
  * @cxl_nvd: optional bridge to an nvdimm if the device supports pmem
+ * @endpoint: connection to the CXL port topology for this memory device
  * @id: id number of this memdev instance.
  * @depth: endpoint port depth
  */
@@ -48,6 +49,7 @@ struct cxl_memdev {
 	struct work_struct detach_work;
 	struct cxl_nvdimm_bridge *cxl_nvb;
 	struct cxl_nvdimm *cxl_nvd;
+	struct cxl_port *endpoint;
 	int id;
 	int depth;
 };


^ permalink raw reply related	[flat|nested] 27+ messages in thread

* Re: [PATCH v2 03/12] cxl: Fix kernel-doc warnings
  2023-06-15  1:29 ` [PATCH v2 03/12] cxl: Fix kernel-doc warnings Dan Williams
@ 2023-06-15 21:28   ` Dave Jiang
  2023-06-22 13:50   ` Jonathan Cameron
  1 sibling, 0 replies; 27+ messages in thread
From: Dave Jiang @ 2023-06-15 21:28 UTC (permalink / raw)
  To: Dan Williams, linux-cxl



On 6/14/23 18:29, Dan Williams wrote:
> After Jonathan noticed [1] that 'struct cxl_dev_state' had a kernel-doc
> entry without a corresponding struct attribute I ran the kernel-doc
> script to see what else might be broken. Fix these warnings:
> 
> drivers/cxl/cxlmem.h:199: warning: This comment starts with '/**', but isn't a kernel-doc comment. Refer Documentation/doc-guide/kernel-doc.rst
>   * Event Interrupt Policy
> drivers/cxl/cxlmem.h:224: warning: Function parameter or member 'buf' not described in 'cxl_event_state'
> drivers/cxl/cxlmem.h:224: warning: Function parameter or member 'log_lock' not described in 'cxl_event_state'
> 
> Note that scripts/kernel-doc only finds missing kernel-doc entries. It
> does not warn on too many kernel-doc entries, i.e. it did not catch the
> fact that @info refers to a not present member.
> 
> Link: http://lore.kernel.org/r/20230606121054.000069e1@Huawei.com [1]
> Signed-off-by: Dan Williams <dan.j.williams@intel.com>

Reviewed-by: Dave Jiang <dave.jiang@intel.com>
> ---
>   drivers/cxl/cxlmem.h |    6 +++---
>   1 file changed, 3 insertions(+), 3 deletions(-)
> 
> diff --git a/drivers/cxl/cxlmem.h b/drivers/cxl/cxlmem.h
> index a2845a7a69d8..8e4ba5b52902 100644
> --- a/drivers/cxl/cxlmem.h
> +++ b/drivers/cxl/cxlmem.h
> @@ -195,7 +195,7 @@ static inline int cxl_mbox_cmd_rc2errno(struct cxl_mbox_cmd *mbox_cmd)
>    */
>   #define CXL_CAPACITY_MULTIPLIER SZ_256M
>   
> -/**
> +/*
>    * Event Interrupt Policy
>    *
>    * CXL rev 3.0 section 8.2.9.2.4; Table 8-52
> @@ -215,8 +215,8 @@ struct cxl_event_interrupt_policy {
>   /**
>    * struct cxl_event_state - Event log driver state
>    *
> - * @event_buf: Buffer to receive event data
> - * @event_log_lock: Serialize event_buf and log use
> + * @buf: Buffer to receive event data
> + * @log_lock: Serialize event_buf and log use
>    */
>   struct cxl_event_state {
>   	struct cxl_get_event_payload *buf;
> 

^ permalink raw reply	[flat|nested] 27+ messages in thread

* Re: [PATCH v2 04/12] cxl: Remove leftover attribute documentation in 'struct cxl_dev_state'
  2023-06-15  1:29 ` [PATCH v2 04/12] cxl: Remove leftover attribute documentation in 'struct cxl_dev_state' Dan Williams
@ 2023-06-15 21:29   ` Dave Jiang
  2023-06-22 13:50     ` Jonathan Cameron
  0 siblings, 1 reply; 27+ messages in thread
From: Dave Jiang @ 2023-06-15 21:29 UTC (permalink / raw)
  To: Dan Williams, linux-cxl; +Cc: Jonathan Cameron



On 6/14/23 18:29, Dan Williams wrote:
> commit 14d788740774 ("cxl/mem: Consolidate CXL DVSEC Range enumeration
> in the core")
> 
> ...removed @info from 'struct cxl_dev_state', but neglected to remove
> the corresponding kernel-doc entry. Complete the removal.
> 
> Reported-by: Jonathan Cameron <Jonathan.Cameron@Huawei.com>
> Closes: http://lore.kernel.org/r/20230606121054.000069e1@Huawei.com
> Signed-off-by: Dan Williams <dan.j.williams@intel.com>
Reviewed-by: Dave Jiang <dave.jiang@intel.com>

> ---
>   drivers/cxl/cxlmem.h |    1 -
>   1 file changed, 1 deletion(-)
> 
> diff --git a/drivers/cxl/cxlmem.h b/drivers/cxl/cxlmem.h
> index 8e4ba5b52902..66896fc6c43f 100644
> --- a/drivers/cxl/cxlmem.h
> +++ b/drivers/cxl/cxlmem.h
> @@ -287,7 +287,6 @@ struct cxl_poison_state {
>    * @next_volatile_bytes: volatile capacity change pending device reset
>    * @next_persistent_bytes: persistent capacity change pending device reset
>    * @component_reg_phys: register base of component registers
> - * @info: Cached DVSEC information about the device.
>    * @serial: PCIe Device Serial Number
>    * @event: event log driver state
>    * @poison: poison driver state info
> 

^ permalink raw reply	[flat|nested] 27+ messages in thread

* Re: [PATCH v2 06/12] cxl/memdev: Make mailbox functionality optional
  2023-06-15  1:30 ` [PATCH v2 06/12] cxl/memdev: Make mailbox functionality optional Dan Williams
@ 2023-06-15 21:30   ` Dave Jiang
  2023-06-22 13:52     ` Jonathan Cameron
  0 siblings, 1 reply; 27+ messages in thread
From: Dave Jiang @ 2023-06-15 21:30 UTC (permalink / raw)
  To: Dan Williams, linux-cxl



On 6/14/23 18:30, Dan Williams wrote:
> In support of the Linux CXL core scaling for a wider set of CXL devices,
> allow for the creation of memdevs with some memory device capabilities
> disabled. Specifically, allow for CXL devices outside of those claiming
> to be compliant with the generic CXL memory device class code, like
> vendor specific Type-2/3 devices that host CXL.mem. This implies, allow
> for the creation of memdevs that only support component-registers, not
> necessarily memory-device-registers (like mailbox registers). A memdev
> derived from a CXL endpoint that does not support generic class code
> expectations is tagged "CXL_DEVTYPE_DEVMEM", while a memdev derived from a
> class-code compliant endpoint is tagged "CXL_DEVTYPE_CLASSMEM".
> 
> The primary assumption of a CXL_DEVTYPE_DEVMEM memdev is that it
> optionally may not host a mailbox. Disable the command passthrough ioctl
> for memdevs that are not CXL_DEVTYPE_CLASSMEM, and return empty strings
> from memdev attributes associated with data retrieved via the
> class-device-standard IDENTIFY command. Note that empty strings were
> chosen over attribute visibility to maintain compatibility with shipping
> versions of cxl-cli that expect those attributes to always be present.
> Once cxl-cli has dropped that requirement this workaround can be
> deprecated.
> 
> Signed-off-by: Dan Williams <dan.j.williams@intel.com>

Reviewed-by: Dave Jiang <dave.jiang@intel.com>
> ---
>   drivers/cxl/core/mbox.c   |    1 +
>   drivers/cxl/core/memdev.c |   10 +++++++++-
>   drivers/cxl/cxlmem.h      |   18 ++++++++++++++++++
>   3 files changed, 28 insertions(+), 1 deletion(-)
> 
> diff --git a/drivers/cxl/core/mbox.c b/drivers/cxl/core/mbox.c
> index ab9d455e8579..1990a5940b7c 100644
> --- a/drivers/cxl/core/mbox.c
> +++ b/drivers/cxl/core/mbox.c
> @@ -1272,6 +1272,7 @@ struct cxl_memdev_state *cxl_memdev_state_create(struct device *dev)
>   	mutex_init(&mds->mbox_mutex);
>   	mutex_init(&mds->event.log_lock);
>   	mds->cxlds.dev = dev;
> +	mds->cxlds.type = CXL_DEVTYPE_CLASSMEM;
>   
>   	return mds;
>   }
> diff --git a/drivers/cxl/core/memdev.c b/drivers/cxl/core/memdev.c
> index 15434b1b4909..3f2d54f30548 100644
> --- a/drivers/cxl/core/memdev.c
> +++ b/drivers/cxl/core/memdev.c
> @@ -41,6 +41,8 @@ static ssize_t firmware_version_show(struct device *dev,
>   	struct cxl_dev_state *cxlds = cxlmd->cxlds;
>   	struct cxl_memdev_state *mds = to_cxl_memdev_state(cxlds);
>   
> +	if (!mds)
> +		return sysfs_emit(buf, "\n");
>   	return sysfs_emit(buf, "%.16s\n", mds->firmware_version);
>   }
>   static DEVICE_ATTR_RO(firmware_version);
> @@ -52,6 +54,8 @@ static ssize_t payload_max_show(struct device *dev,
>   	struct cxl_dev_state *cxlds = cxlmd->cxlds;
>   	struct cxl_memdev_state *mds = to_cxl_memdev_state(cxlds);
>   
> +	if (!mds)
> +		return sysfs_emit(buf, "\n");
>   	return sysfs_emit(buf, "%zu\n", mds->payload_size);
>   }
>   static DEVICE_ATTR_RO(payload_max);
> @@ -63,6 +67,8 @@ static ssize_t label_storage_size_show(struct device *dev,
>   	struct cxl_dev_state *cxlds = cxlmd->cxlds;
>   	struct cxl_memdev_state *mds = to_cxl_memdev_state(cxlds);
>   
> +	if (!mds)
> +		return sysfs_emit(buf, "\n");
>   	return sysfs_emit(buf, "%zu\n", mds->lsa_size);
>   }
>   static DEVICE_ATTR_RO(label_storage_size);
> @@ -517,10 +523,12 @@ static long cxl_memdev_ioctl(struct file *file, unsigned int cmd,
>   			     unsigned long arg)
>   {
>   	struct cxl_memdev *cxlmd = file->private_data;
> +	struct cxl_dev_state *cxlds;
>   	int rc = -ENXIO;
>   
>   	down_read(&cxl_memdev_rwsem);
> -	if (cxlmd->cxlds)
> +	cxlds = cxlmd->cxlds;
> +	if (cxlds && cxlds->type == CXL_DEVTYPE_CLASSMEM)
>   		rc = __cxl_memdev_ioctl(cxlmd, cmd, arg);
>   	up_read(&cxl_memdev_rwsem);
>   
> diff --git a/drivers/cxl/cxlmem.h b/drivers/cxl/cxlmem.h
> index b1a72e01e4de..1b39afeb369e 100644
> --- a/drivers/cxl/cxlmem.h
> +++ b/drivers/cxl/cxlmem.h
> @@ -254,6 +254,20 @@ struct cxl_poison_state {
>   	struct mutex lock;  /* Protect reads of poison list */
>   };
>   
> +/*
> + * 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_dev_state - The driver device state
>    *
> @@ -272,6 +286,7 @@ struct cxl_poison_state {
>    * @ram_res: Active Volatile memory capacity configuration
>    * @component_reg_phys: register base of component registers
>    * @serial: PCIe Device Serial Number
> + * @type: Generic Memory Class device or Vendor Specific Memory device
>    */
>   struct cxl_dev_state {
>   	struct device *dev;
> @@ -285,6 +300,7 @@ struct cxl_dev_state {
>   	struct resource ram_res;
>   	resource_size_t component_reg_phys;
>   	u64 serial;
> +	enum cxl_devtype type;
>   };
>   
>   /**
> @@ -343,6 +359,8 @@ struct cxl_memdev_state {
>   static inline struct cxl_memdev_state *
>   to_cxl_memdev_state(struct cxl_dev_state *cxlds)
>   {
> +	if (cxlds->type != CXL_DEVTYPE_CLASSMEM)
> +		return NULL;
>   	return container_of(cxlds, struct cxl_memdev_state, cxlds);
>   }
>   
> 

^ permalink raw reply	[flat|nested] 27+ messages in thread

* Re: [PATCH v2 07/12] cxl/port: Rename CXL_DECODER_{EXPANDER, ACCELERATOR} => {HOSTONLYMEM, DEVMEM}
  2023-06-15  1:30 ` [PATCH v2 07/12] cxl/port: Rename CXL_DECODER_{EXPANDER, ACCELERATOR} => {HOSTONLYMEM, DEVMEM} Dan Williams
@ 2023-06-15 21:31   ` Dave Jiang
  0 siblings, 0 replies; 27+ messages in thread
From: Dave Jiang @ 2023-06-15 21:31 UTC (permalink / raw)
  To: Dan Williams, linux-cxl; +Cc: Jonathan Cameron



On 6/14/23 18:30, Dan Williams wrote:
> In preparation for support for HDM-D and HDM-DB configuration
> (device-memory, and device-memory with back-invalidate). Rename the current
> type designators to use HOSTONLYMEM and DEVMEM as a suffix.
> 
> HDM-DB can be supported by devices that are not accelerators, so DEVMEM is
> a more generic term for that case.
> 
> Fixup one location where this type value was open coded.
> 
> Reviewed-by: Jonathan Cameron <Jonathan.Cameron@huawei.com>
> Signed-off-by: Dan Williams <dan.j.williams@intel.com>

Reviewed-by: Dave Jiang <dave.jiang@intel.com>
> ---
>   drivers/cxl/acpi.c           |    2 +-
>   drivers/cxl/core/hdm.c       |   11 ++++++-----
>   drivers/cxl/core/port.c      |    6 +++---
>   drivers/cxl/core/region.c    |    2 +-
>   drivers/cxl/cxl.h            |    4 ++--
>   tools/testing/cxl/test/cxl.c |    6 +++---
>   6 files changed, 16 insertions(+), 15 deletions(-)
> 
> diff --git a/drivers/cxl/acpi.c b/drivers/cxl/acpi.c
> index 7e1765b09e04..603e5df8aec0 100644
> --- a/drivers/cxl/acpi.c
> +++ b/drivers/cxl/acpi.c
> @@ -258,7 +258,7 @@ static int cxl_parse_cfmws(union acpi_subtable_headers *header, void *arg,
>   
>   	cxld = &cxlrd->cxlsd.cxld;
>   	cxld->flags = cfmws_to_decoder_flags(cfmws->restrictions);
> -	cxld->target_type = CXL_DECODER_EXPANDER;
> +	cxld->target_type = CXL_DECODER_HOSTONLYMEM;
>   	cxld->hpa_range = (struct range) {
>   		.start = res->start,
>   		.end = res->end,
> diff --git a/drivers/cxl/core/hdm.c b/drivers/cxl/core/hdm.c
> index 7889ff203a34..79170de13d89 100644
> --- a/drivers/cxl/core/hdm.c
> +++ b/drivers/cxl/core/hdm.c
> @@ -570,7 +570,8 @@ static void cxld_set_interleave(struct cxl_decoder *cxld, u32 *ctrl)
>   
>   static void cxld_set_type(struct cxl_decoder *cxld, u32 *ctrl)
>   {
> -	u32p_replace_bits(ctrl, !!(cxld->target_type == 3),
> +	u32p_replace_bits(ctrl,
> +			  !!(cxld->target_type == CXL_DECODER_HOSTONLYMEM),
>   			  CXL_HDM_DECODER0_CTRL_TYPE);
>   }
>   
> @@ -764,7 +765,7 @@ static int cxl_setup_hdm_decoder_from_dvsec(
>   	if (!len)
>   		return -ENOENT;
>   
> -	cxld->target_type = CXL_DECODER_EXPANDER;
> +	cxld->target_type = CXL_DECODER_HOSTONLYMEM;
>   	cxld->commit = NULL;
>   	cxld->reset = NULL;
>   	cxld->hpa_range = info->dvsec_range[which];
> @@ -838,9 +839,9 @@ static int init_hdm_decoder(struct cxl_port *port, struct cxl_decoder *cxld,
>   		if (ctrl & CXL_HDM_DECODER0_CTRL_LOCK)
>   			cxld->flags |= CXL_DECODER_F_LOCK;
>   		if (FIELD_GET(CXL_HDM_DECODER0_CTRL_TYPE, ctrl))
> -			cxld->target_type = CXL_DECODER_EXPANDER;
> +			cxld->target_type = CXL_DECODER_HOSTONLYMEM;
>   		else
> -			cxld->target_type = CXL_DECODER_ACCELERATOR;
> +			cxld->target_type = CXL_DECODER_DEVMEM;
>   		if (cxld->id != port->commit_end + 1) {
>   			dev_warn(&port->dev,
>   				 "decoder%d.%d: Committed out of order\n",
> @@ -861,7 +862,7 @@ static int init_hdm_decoder(struct cxl_port *port, struct cxl_decoder *cxld,
>   			ctrl |= CXL_HDM_DECODER0_CTRL_TYPE;
>   			writel(ctrl, hdm + CXL_HDM_DECODER0_CTRL_OFFSET(which));
>   		}
> -		cxld->target_type = CXL_DECODER_EXPANDER;
> +		cxld->target_type = CXL_DECODER_HOSTONLYMEM;
>   	}
>   	rc = eiw_to_ways(FIELD_GET(CXL_HDM_DECODER0_CTRL_IW_MASK, ctrl),
>   			  &cxld->interleave_ways);
> diff --git a/drivers/cxl/core/port.c b/drivers/cxl/core/port.c
> index e7c284c890bc..6d7811b26b5a 100644
> --- a/drivers/cxl/core/port.c
> +++ b/drivers/cxl/core/port.c
> @@ -117,9 +117,9 @@ static ssize_t target_type_show(struct device *dev,
>   	struct cxl_decoder *cxld = to_cxl_decoder(dev);
>   
>   	switch (cxld->target_type) {
> -	case CXL_DECODER_ACCELERATOR:
> +	case CXL_DECODER_DEVMEM:
>   		return sysfs_emit(buf, "accelerator\n");
> -	case CXL_DECODER_EXPANDER:
> +	case CXL_DECODER_HOSTONLYMEM:
>   		return sysfs_emit(buf, "expander\n");
>   	}
>   	return -ENXIO;
> @@ -1550,7 +1550,7 @@ static int cxl_decoder_init(struct cxl_port *port, struct cxl_decoder *cxld)
>   	/* Pre initialize an "empty" decoder */
>   	cxld->interleave_ways = 1;
>   	cxld->interleave_granularity = PAGE_SIZE;
> -	cxld->target_type = CXL_DECODER_EXPANDER;
> +	cxld->target_type = CXL_DECODER_HOSTONLYMEM;
>   	cxld->hpa_range = (struct range) {
>   		.start = 0,
>   		.end = -1,
> diff --git a/drivers/cxl/core/region.c b/drivers/cxl/core/region.c
> index f822de44bee0..6a875f86901b 100644
> --- a/drivers/cxl/core/region.c
> +++ b/drivers/cxl/core/region.c
> @@ -2103,7 +2103,7 @@ static struct cxl_region *__create_region(struct cxl_root_decoder *cxlrd,
>   		return ERR_PTR(-EBUSY);
>   	}
>   
> -	return devm_cxl_add_region(cxlrd, id, mode, CXL_DECODER_EXPANDER);
> +	return devm_cxl_add_region(cxlrd, id, mode, CXL_DECODER_HOSTONLYMEM);
>   }
>   
>   static ssize_t create_pmem_region_store(struct device *dev,
> diff --git a/drivers/cxl/cxl.h b/drivers/cxl/cxl.h
> index dfc94e76c7d6..ae0965ac8c5a 100644
> --- a/drivers/cxl/cxl.h
> +++ b/drivers/cxl/cxl.h
> @@ -290,8 +290,8 @@ resource_size_t cxl_rcrb_to_component(struct device *dev,
>   #define CXL_DECODER_F_MASK  GENMASK(5, 0)
>   
>   enum cxl_decoder_type {
> -       CXL_DECODER_ACCELERATOR = 2,
> -       CXL_DECODER_EXPANDER = 3,
> +	CXL_DECODER_DEVMEM = 2,
> +	CXL_DECODER_HOSTONLYMEM = 3,
>   };
>   
>   /*
> diff --git a/tools/testing/cxl/test/cxl.c b/tools/testing/cxl/test/cxl.c
> index bf00dc52fe96..5565164d6658 100644
> --- a/tools/testing/cxl/test/cxl.c
> +++ b/tools/testing/cxl/test/cxl.c
> @@ -713,7 +713,7 @@ static void default_mock_decoder(struct cxl_decoder *cxld)
>   
>   	cxld->interleave_ways = 1;
>   	cxld->interleave_granularity = 256;
> -	cxld->target_type = CXL_DECODER_EXPANDER;
> +	cxld->target_type = CXL_DECODER_HOSTONLYMEM;
>   	cxld->commit = mock_decoder_commit;
>   	cxld->reset = mock_decoder_reset;
>   }
> @@ -787,7 +787,7 @@ static void mock_init_hdm_decoder(struct cxl_decoder *cxld)
>   
>   	cxld->interleave_ways = 2;
>   	eig_to_granularity(window->granularity, &cxld->interleave_granularity);
> -	cxld->target_type = CXL_DECODER_EXPANDER;
> +	cxld->target_type = CXL_DECODER_HOSTONLYMEM;
>   	cxld->flags = CXL_DECODER_F_ENABLE;
>   	cxled->state = CXL_DECODER_STATE_AUTO;
>   	port->commit_end = cxld->id;
> @@ -820,7 +820,7 @@ static void mock_init_hdm_decoder(struct cxl_decoder *cxld)
>   		} else
>   			cxlsd->target[0] = dport;
>   		cxld = &cxlsd->cxld;
> -		cxld->target_type = CXL_DECODER_EXPANDER;
> +		cxld->target_type = CXL_DECODER_HOSTONLYMEM;
>   		cxld->flags = CXL_DECODER_F_ENABLE;
>   		iter->commit_end = 0;
>   		/*
> 

^ permalink raw reply	[flat|nested] 27+ messages in thread

* Re: [PATCH v2 08/12] cxl/hdm: Default CXL_DEVTYPE_DEVMEM decoders to CXL_DECODER_DEVMEM
  2023-06-15  1:30 ` [PATCH v2 08/12] cxl/hdm: Default CXL_DEVTYPE_DEVMEM decoders to CXL_DECODER_DEVMEM Dan Williams
@ 2023-06-15 21:32   ` Dave Jiang
  0 siblings, 0 replies; 27+ messages in thread
From: Dave Jiang @ 2023-06-15 21:32 UTC (permalink / raw)
  To: Dan Williams, linux-cxl; +Cc: Jonathan Cameron



On 6/14/23 18:30, Dan Williams wrote:
> In preparation for device-memory region creation, arrange for decoders
> of CXL_DEVTYPE_DEVMEM memdevs to default to CXL_DECODER_DEVMEM for their
> target type.
> 
> Revisit this if a device ever shows up that wants to offer mixed HDM-H
> (Host-Only Memory) and HDM-DB support, or an CXL_DEVTYPE_DEVMEM device
> that supports HDM-H.
> 
> Reviewed-by: Jonathan Cameron <Jonathan.Cameron@huawei.com>
> Signed-off-by: Dan Williams <dan.j.williams@intel.com>

Reviewed-by: Dave Jiang <dave.jiang@intel.com>
> ---
>   drivers/cxl/core/hdm.c |   35 ++++++++++++++++++++++++++---------
>   drivers/cxl/cxl.h      |    2 +-
>   2 files changed, 27 insertions(+), 10 deletions(-)
> 
> diff --git a/drivers/cxl/core/hdm.c b/drivers/cxl/core/hdm.c
> index 79170de13d89..715c1f103739 100644
> --- a/drivers/cxl/core/hdm.c
> +++ b/drivers/cxl/core/hdm.c
> @@ -572,7 +572,7 @@ static void cxld_set_type(struct cxl_decoder *cxld, u32 *ctrl)
>   {
>   	u32p_replace_bits(ctrl,
>   			  !!(cxld->target_type == CXL_DECODER_HOSTONLYMEM),
> -			  CXL_HDM_DECODER0_CTRL_TYPE);
> +			  CXL_HDM_DECODER0_CTRL_HOSTONLY);
>   }
>   
>   static int cxlsd_set_targets(struct cxl_switch_decoder *cxlsd, u64 *tgt)
> @@ -794,8 +794,8 @@ static int init_hdm_decoder(struct cxl_port *port, struct cxl_decoder *cxld,
>   			    int *target_map, void __iomem *hdm, int which,
>   			    u64 *dpa_base, struct cxl_endpoint_dvsec_info *info)
>   {
> +	struct cxl_endpoint_decoder *cxled = NULL;
>   	u64 size, base, skip, dpa_size, lo, hi;
> -	struct cxl_endpoint_decoder *cxled;
>   	bool committed;
>   	u32 remainder;
>   	int i, rc;
> @@ -828,6 +828,8 @@ static int init_hdm_decoder(struct cxl_port *port, struct cxl_decoder *cxld,
>   		return -ENXIO;
>   	}
>   
> +	if (info)
> +		cxled = to_cxl_endpoint_decoder(&cxld->dev);
>   	cxld->hpa_range = (struct range) {
>   		.start = base,
>   		.end = base + size - 1,
> @@ -838,7 +840,7 @@ static int init_hdm_decoder(struct cxl_port *port, struct cxl_decoder *cxld,
>   		cxld->flags |= CXL_DECODER_F_ENABLE;
>   		if (ctrl & CXL_HDM_DECODER0_CTRL_LOCK)
>   			cxld->flags |= CXL_DECODER_F_LOCK;
> -		if (FIELD_GET(CXL_HDM_DECODER0_CTRL_TYPE, ctrl))
> +		if (FIELD_GET(CXL_HDM_DECODER0_CTRL_HOSTONLY, ctrl))
>   			cxld->target_type = CXL_DECODER_HOSTONLYMEM;
>   		else
>   			cxld->target_type = CXL_DECODER_DEVMEM;
> @@ -857,12 +859,28 @@ static int init_hdm_decoder(struct cxl_port *port, struct cxl_decoder *cxld,
>   		}
>   		port->commit_end = cxld->id;
>   	} else {
> -		/* unless / until type-2 drivers arrive, assume type-3 */
> -		if (FIELD_GET(CXL_HDM_DECODER0_CTRL_TYPE, ctrl) == 0) {
> -			ctrl |= CXL_HDM_DECODER0_CTRL_TYPE;
> +		if (cxled) {
> +			struct cxl_memdev *cxlmd = cxled_to_memdev(cxled);
> +			struct cxl_dev_state *cxlds = cxlmd->cxlds;
> +
> +			/*
> +			 * Default by devtype until a device arrives that needs
> +			 * more precision.
> +			 */
> +			if (cxlds->type == CXL_DEVTYPE_CLASSMEM)
> +				cxld->target_type = CXL_DECODER_HOSTONLYMEM;
> +			else
> +				cxld->target_type = CXL_DECODER_DEVMEM;
> +		} else {
> +			/* To be overridden by region type at commit time */
> +			cxld->target_type = CXL_DECODER_HOSTONLYMEM;
> +		}
> +
> +		if (!FIELD_GET(CXL_HDM_DECODER0_CTRL_HOSTONLY, ctrl) &&
> +		    cxld->target_type == CXL_DECODER_HOSTONLYMEM) {
> +			ctrl |= CXL_HDM_DECODER0_CTRL_HOSTONLY;
>   			writel(ctrl, hdm + CXL_HDM_DECODER0_CTRL_OFFSET(which));
>   		}
> -		cxld->target_type = CXL_DECODER_HOSTONLYMEM;
>   	}
>   	rc = eiw_to_ways(FIELD_GET(CXL_HDM_DECODER0_CTRL_IW_MASK, ctrl),
>   			  &cxld->interleave_ways);
> @@ -881,7 +899,7 @@ static int init_hdm_decoder(struct cxl_port *port, struct cxl_decoder *cxld,
>   		port->id, cxld->id, cxld->hpa_range.start, cxld->hpa_range.end,
>   		cxld->interleave_ways, cxld->interleave_granularity);
>   
> -	if (!info) {
> +	if (!cxled) {
>   		lo = readl(hdm + CXL_HDM_DECODER0_TL_LOW(which));
>   		hi = readl(hdm + CXL_HDM_DECODER0_TL_HIGH(which));
>   		target_list.value = (hi << 32) + lo;
> @@ -904,7 +922,6 @@ static int init_hdm_decoder(struct cxl_port *port, struct cxl_decoder *cxld,
>   	lo = readl(hdm + CXL_HDM_DECODER0_SKIP_LOW(which));
>   	hi = readl(hdm + CXL_HDM_DECODER0_SKIP_HIGH(which));
>   	skip = (hi << 32) + lo;
> -	cxled = to_cxl_endpoint_decoder(&cxld->dev);
>   	rc = devm_cxl_dpa_reserve(cxled, *dpa_base + skip, dpa_size, skip);
>   	if (rc) {
>   		dev_err(&port->dev,
> diff --git a/drivers/cxl/cxl.h b/drivers/cxl/cxl.h
> index ae0965ac8c5a..f309b1387858 100644
> --- a/drivers/cxl/cxl.h
> +++ b/drivers/cxl/cxl.h
> @@ -56,7 +56,7 @@
>   #define   CXL_HDM_DECODER0_CTRL_COMMIT BIT(9)
>   #define   CXL_HDM_DECODER0_CTRL_COMMITTED BIT(10)
>   #define   CXL_HDM_DECODER0_CTRL_COMMIT_ERROR BIT(11)
> -#define   CXL_HDM_DECODER0_CTRL_TYPE BIT(12)
> +#define   CXL_HDM_DECODER0_CTRL_HOSTONLY BIT(12)
>   #define CXL_HDM_DECODER0_TL_LOW(i) (0x20 * (i) + 0x24)
>   #define CXL_HDM_DECODER0_TL_HIGH(i) (0x20 * (i) + 0x28)
>   #define CXL_HDM_DECODER0_SKIP_LOW(i) CXL_HDM_DECODER0_TL_LOW(i)
> 

^ permalink raw reply	[flat|nested] 27+ messages in thread

* Re: [PATCH v2 10/12] cxl/pci: Unconditionally unmask 256B Flit errors
  2023-06-15  1:30 ` [PATCH v2 10/12] cxl/pci: Unconditionally unmask 256B Flit errors Dan Williams
@ 2023-06-15 21:34   ` Dave Jiang
  2023-06-22 13:55     ` Jonathan Cameron
  0 siblings, 1 reply; 27+ messages in thread
From: Dave Jiang @ 2023-06-15 21:34 UTC (permalink / raw)
  To: Dan Williams, linux-cxl



On 6/14/23 18:30, Dan Williams wrote:
> The current check for 256B Flit mode is incomplete and unnecessary. It
> is incomplete because it fails to consider the link speed, or check for
> CXL link capabilities. It is unnecessary because unconditionally
> unmasking 256B Flit errors is a nop when 256B Flit operation is not
> available.
> 
> Remove this check in preparation for creating a cxl_probe_link() helper
> to centralize this detection.
> 
> Signed-off-by: Dan Williams <dan.j.williams@intel.com>

Reviewed-by: Dave Jiang <dave.jiang@intel.com>
> ---
>   drivers/cxl/pci.c |   18 ++----------------
>   1 file changed, 2 insertions(+), 16 deletions(-)
> 
> diff --git a/drivers/cxl/pci.c b/drivers/cxl/pci.c
> index 4e2845b7331a..3f78082014cc 100644
> --- a/drivers/cxl/pci.c
> +++ b/drivers/cxl/pci.c
> @@ -368,19 +368,6 @@ static bool is_cxl_restricted(struct pci_dev *pdev)
>   	return pci_pcie_type(pdev) == PCI_EXP_TYPE_RC_END;
>   }
>   
> -/*
> - * CXL v3.0 6.2.3 Table 6-4
> - * The table indicates that if PCIe Flit Mode is set, then CXL is in 256B flits
> - * mode, otherwise it's 68B flits mode.
> - */
> -static bool cxl_pci_flit_256(struct pci_dev *pdev)
> -{
> -	u16 lnksta2;
> -
> -	pcie_capability_read_word(pdev, PCI_EXP_LNKSTA2, &lnksta2);
> -	return lnksta2 & PCI_EXP_LNKSTA2_FLIT;
> -}
> -
>   static int cxl_pci_ras_unmask(struct pci_dev *pdev)
>   {
>   	struct pci_host_bridge *host_bridge = pci_find_host_bridge(pdev->bus);
> @@ -407,9 +394,8 @@ static int cxl_pci_ras_unmask(struct pci_dev *pdev)
>   		addr = cxlds->regs.ras + CXL_RAS_UNCORRECTABLE_MASK_OFFSET;
>   		orig_val = readl(addr);
>   
> -		mask = CXL_RAS_UNCORRECTABLE_MASK_MASK;
> -		if (!cxl_pci_flit_256(pdev))
> -			mask &= ~CXL_RAS_UNCORRECTABLE_MASK_F256B_MASK;
> +		mask = CXL_RAS_UNCORRECTABLE_MASK_MASK |
> +		       CXL_RAS_UNCORRECTABLE_MASK_F256B_MASK;
>   		val = orig_val & ~mask;
>   		writel(val, addr);
>   		dev_dbg(&pdev->dev,
> 

^ permalink raw reply	[flat|nested] 27+ messages in thread

* Re: [PATCH v2 11/12] cxl/port: Enumerate cxl link capabilities
  2023-06-15  1:30 ` [PATCH v2 11/12] cxl/port: Enumerate cxl link capabilities Dan Williams
@ 2023-06-15 21:37   ` Dave Jiang
  2023-06-16  0:07   ` Dan Williams
  1 sibling, 0 replies; 27+ messages in thread
From: Dave Jiang @ 2023-06-15 21:37 UTC (permalink / raw)
  To: Dan Williams, linux-cxl



On 6/14/23 18:30, Dan Williams wrote:
> Per CXL 3.0 9.14 "Back-Invalidation Configuration", in order to enable
> an HDM-DB range (CXL.mem region with device initiated back-invalidation
> support), all ports in the path between the endpoint and the host bridge
> must be in 256-bit flit-mode.
> 
> Even for typical Type-3 class devices it is useful to enumerate link
> capabilities through the topology for debug purposes.
> 
> See CXL 3.0 Table-64 "256B Flit Mode vs. 68B Flit Mode Operation", for
> how to determine 64B vs 256B Flit mode operation.
> 
> Signed-off-by: Dan Williams <dan.j.williams@intel.com>

Reviewed-by: Dave Jiang <dave.jiang@intel.com>
> ---
>   drivers/cxl/core/pci.c  |  113 +++++++++++++++++++++++++++++++++++++++++++++++
>   drivers/cxl/core/port.c |    6 ++
>   drivers/cxl/cxl.h       |    7 +++
>   drivers/cxl/cxlpci.h    |   24 +++++++++-
>   drivers/cxl/port.c      |    5 ++
>   5 files changed, 153 insertions(+), 2 deletions(-)
> 
> diff --git a/drivers/cxl/core/pci.c b/drivers/cxl/core/pci.c
> index 67f4ab6daa34..7440f84be6c8 100644
> --- a/drivers/cxl/core/pci.c
> +++ b/drivers/cxl/core/pci.c
> @@ -519,6 +519,119 @@ int cxl_hdm_decode_init(struct cxl_dev_state *cxlds, struct cxl_hdm *cxlhdm,
>   }
>   EXPORT_SYMBOL_NS_GPL(cxl_hdm_decode_init, CXL);
>   
> +static struct pci_dev *cxl_port_to_pci(struct cxl_port *port)
> +{
> +	struct device *dev;
> +
> +	if (is_cxl_endpoint(port))
> +		dev = port->uport->parent;
> +	else
> +		dev = port->uport;
> +
> +	if (!dev_is_pci(dev))
> +		return NULL;
> +
> +	return to_pci_dev(dev);
> +}
> +
> +int cxl_probe_link(struct cxl_port *port)
> +{
> +	u16 cap, en, lnksta, lnksta2, parent_features;
> +	struct pci_dev *pdev = cxl_port_to_pci(port);
> +	struct cxl_port *parent_port;
> +	unsigned long features;
> +	struct device *dev;
> +	int rc, dvsec;
> +	u32 hdr;
> +
> +	if (!pdev) {
> +		/*
> +		 * Assume host bridges support all features, the root
> +		 * port will dictate the actual enabled set to endpoints.
> +		 */
> +		return 0;
> +	}
> +
> +	dev = &pdev->dev;
> +	dvsec = pci_find_dvsec_capability(pdev, PCI_DVSEC_VENDOR_ID_CXL,
> +					  CXL_DVSEC_FLEXBUS_PORT);
> +	if (!dvsec) {
> +		dev_err(dev, "Failed to enumerate port capabilities\n");
> +		return -ENXIO;
> +	}
> +
> +	/*
> +	 * Cache the link features for future determination of 256B Flit
> +	 * mode dependent operation support e.g. HDM-DB.
> +	 */
> +	rc = pci_read_config_dword(pdev, dvsec + PCI_DVSEC_HEADER1, &hdr);
> +	if (rc)
> +		return rc;
> +
> +	rc = pci_read_config_word(pdev, dvsec + CXL_DVSEC_FLEXBUS_CAP_OFFSET,
> +				  &cap);
> +	if (rc)
> +		return rc;
> +
> +	rc = pci_read_config_word(pdev, dvsec + CXL_DVSEC_FLEXBUS_STATUS_OFFSET,
> +				  &en);
> +	if (rc)
> +		return rc;
> +
> +	features = en & cap & CXL_DVSEC_FLEXBUS_ENABLE_MASK;
> +	if ((features & CXL_DVSEC_FLEXBUS_CXL_MASK) == 0)
> +		goto no_cxl;
> +
> +	/* Determine flit mode from link speed and CXL active */
> +	rc = pcie_capability_read_word(pdev, PCI_EXP_LNKSTA, &lnksta);
> +	if (rc)
> +		return rc;
> +
> +	rc = pcie_capability_read_word(pdev, PCI_EXP_LNKSTA2, &lnksta2);
> +	if (rc)
> +		return rc;
> +
> +	/* CXL 3.0 Table-64 256B Flit Mode vs. 68B Flit Mode Operation */
> +	switch (FIELD_GET(PCI_EXP_LNKSTA_CLS, lnksta)) {
> +	case PCI_EXP_LNKSTA_CLS_2_5GB:
> +	case PCI_EXP_LNKSTA_CLS_5_0GB:
> +		break;
> +	case PCI_EXP_LNKSTA_CLS_8_0GB:
> +	case PCI_EXP_LNKSTA_CLS_16_0GB:
> +	case PCI_EXP_LNKSTA_CLS_32_0GB:
> +		if ((lnksta2 & PCI_EXP_LNKSTA2_FLIT) == 0) {
> +			features |= CXL_PORT_FEATURE_FLIT68;
> +			break;
> +		}
> +		fallthrough;
> +	case PCI_EXP_LNKSTA_CLS_64_0GB:
> +	default:
> +		features |= CXL_PORT_FEATURE_FLIT256;
> +		break;
> +	}
> +
> +no_cxl:
> +	parent_port = to_cxl_port(port->dev.parent);
> +	parent_features = parent_port->features;
> +
> +	/* Enforce port features are plumbed through to the host bridge */
> +	features &= parent_features;
> +
> +	dev_dbg(dev, "features:%s%s%s%s%s%s%s%s%s\n",
> +		features & CXL_DVSEC_FLEXBUS_CACHE_ENABLED ? " cache" : "",
> +		features & CXL_DVSEC_FLEXBUS_IO_ENABLED ? " io" : "",
> +		features & CXL_DVSEC_FLEXBUS_MEM_ENABLED ? " mem" : "",
> +		features & CXL_DVSEC_FLEXBUS_VH_ENABLED ? " vh" : "",
> +		features & CXL_DVSEC_FLEXBUS_MLD_ENABLED ? " mld" : "",
> +		features & CXL_DVSEC_FLEXBUS_LATOPT_ENABLED ? " latopt" : "",
> +		features & CXL_DVSEC_FLEXBUS_PBR_ENABLED ? " pbr" : "",
> +		features & CXL_PORT_FEATURE_FLIT68 ? " flit68" : "",
> +		features & CXL_PORT_FEATURE_FLIT256 ? " flit256" : "");
> +
> +	return 0;
> +}
> +EXPORT_SYMBOL_NS_GPL(cxl_probe_link, CXL);
> +
>   #define CXL_DOE_TABLE_ACCESS_REQ_CODE		0x000000ff
>   #define   CXL_DOE_TABLE_ACCESS_REQ_CODE_READ	0
>   #define CXL_DOE_TABLE_ACCESS_TABLE_TYPE		0x0000ff00
> diff --git a/drivers/cxl/core/port.c b/drivers/cxl/core/port.c
> index 6d7811b26b5a..bf8f25063914 100644
> --- a/drivers/cxl/core/port.c
> +++ b/drivers/cxl/core/port.c
> @@ -665,6 +665,12 @@ static struct cxl_port *cxl_port_alloc(struct device *uport,
>   	} else
>   		dev->parent = uport;
>   
> +	/*
> +	 * Assume all CXL link capabilities for root-device-to-host-bridge link,
> +	 * cxl_probe_link() will fix this up later in cxl_probe_link() for all
> +	 * other ports.
> +	 */
> +	port->features = CXL_DVSEC_FLEXBUS_ENABLE_MASK;
>   	port->component_reg_phys = component_reg_phys;
>   	ida_init(&port->decoder_ida);
>   	port->hdm_end = -1;
> diff --git a/drivers/cxl/cxl.h b/drivers/cxl/cxl.h
> index f309b1387858..74548f8f5f4c 100644
> --- a/drivers/cxl/cxl.h
> +++ b/drivers/cxl/cxl.h
> @@ -536,6 +536,10 @@ struct cxl_dax_region {
>   	struct range hpa_range;
>   };
>   
> +/* These start after CXL_DVSEC_FLEXBUS_*_ENABLED bits in port->features */
> +#define CXL_PORT_FEATURE_FLIT68 BIT(16)
> +#define CXL_PORT_FEATURE_FLIT256 BIT(17)
> +
>   /**
>    * struct cxl_port - logical collection of upstream port devices and
>    *		     downstream port devices to construct a CXL memory
> @@ -557,6 +561,8 @@ struct cxl_dax_region {
>    * @depth: How deep this port is relative to the root. depth 0 is the root.
>    * @cdat: Cached CDAT data
>    * @cdat_available: Should a CDAT attribute be available in sysfs
> + * @features: active link features (see CXL_DVSEC_FLEXBUS_*_ENABLED +
> + *  CXL_PORT_FEATURE_*)
>    */
>   struct cxl_port {
>   	struct device dev;
> @@ -579,6 +585,7 @@ struct cxl_port {
>   		size_t length;
>   	} cdat;
>   	bool cdat_available;
> +	unsigned long features;
>   };
>   
>   static inline struct cxl_dport *
> diff --git a/drivers/cxl/cxlpci.h b/drivers/cxl/cxlpci.h
> index 7c02e55b8042..0da6618e0df7 100644
> --- a/drivers/cxl/cxlpci.h
> +++ b/drivers/cxl/cxlpci.h
> @@ -45,8 +45,27 @@
>   /* CXL 2.0 8.1.7: GPF DVSEC for CXL Device */
>   #define CXL_DVSEC_DEVICE_GPF					5
>   
> -/* CXL 2.0 8.1.8: PCIe DVSEC for Flex Bus Port */
> -#define CXL_DVSEC_PCIE_FLEXBUS_PORT				7
> +/* CXL 3.0 8.2.1.3: PCIe DVSEC for Flex Bus Port */
> +#define CXL_DVSEC_FLEXBUS_PORT					7
> +#define   CXL_DVSEC_FLEXBUS_CAP_OFFSET		0xA
> +#define     CXL_DVSEC_FLEXBUS_CACHE_CAPABLE	BIT(0)
> +#define     CXL_DVSEC_FLEXBUS_IO_CAPABLE	BIT(1)
> +#define     CXL_DVSEC_FLEXBUS_MEM_CAPABLE	BIT(2)
> +#define     CXL_DVSEC_FLEXBUS_VH_CAPABLE	BIT(5)
> +#define     CXL_DVSEC_FLEXBUS_MLD_CAPABLE	BIT(6)
> +#define     CXL_DVSEC_FLEXBUS_LATOPT_CAPABLE	BIT(13)
> +#define     CXL_DVSEC_FLEXBUS_PBR_CAPABLE	BIT(14)
> +#define   CXL_DVSEC_FLEXBUS_STATUS_OFFSET	0xE
> +#define     CXL_DVSEC_FLEXBUS_CACHE_ENABLED	BIT(0)
> +#define     CXL_DVSEC_FLEXBUS_IO_ENABLED	BIT(1)
> +#define     CXL_DVSEC_FLEXBUS_MEM_ENABLED	BIT(2)
> +#define     CXL_DVSEC_FLEXBUS_VH_ENABLED	BIT(5)
> +#define     CXL_DVSEC_FLEXBUS_MLD_ENABLED	BIT(6)
> +#define     CXL_DVSEC_FLEXBUS_LATOPT_ENABLED	BIT(13)
> +#define     CXL_DVSEC_FLEXBUS_PBR_ENABLED	BIT(14)
> +#define     CXL_DVSEC_FLEXBUS_ENABLE_MASK \
> +	(GENMASK(2, 0) | GENMASK(6, 5) | GENMASK(14, 13))
> +#define CXL_DVSEC_FLEXBUS_CXL_MASK GENMASK(2, 0)
>   
>   /* CXL 2.0 8.1.9: Register Locator DVSEC */
>   #define CXL_DVSEC_REG_LOCATOR					8
> @@ -88,6 +107,7 @@ int devm_cxl_port_enumerate_dports(struct cxl_port *port);
>   struct cxl_dev_state;
>   int cxl_hdm_decode_init(struct cxl_dev_state *cxlds, struct cxl_hdm *cxlhdm,
>   			struct cxl_endpoint_dvsec_info *info);
> +int cxl_probe_link(struct cxl_port *port);
>   void read_cdat_data(struct cxl_port *port);
>   void cxl_cor_error_detected(struct pci_dev *pdev);
>   pci_ers_result_t cxl_error_detected(struct pci_dev *pdev,
> diff --git a/drivers/cxl/port.c b/drivers/cxl/port.c
> index c23b6164e1c0..5ffe3c7d2f5e 100644
> --- a/drivers/cxl/port.c
> +++ b/drivers/cxl/port.c
> @@ -140,6 +140,11 @@ static int cxl_endpoint_port_probe(struct cxl_port *port)
>   static int cxl_port_probe(struct device *dev)
>   {
>   	struct cxl_port *port = to_cxl_port(dev);
> +	int rc;
> +
> +	rc = cxl_probe_link(port);
> +	if (rc)
> +		return rc;
>   
>   	if (is_cxl_endpoint(port))
>   		return cxl_endpoint_port_probe(port);
> 

^ permalink raw reply	[flat|nested] 27+ messages in thread

* RE: [PATCH v2 11/12] cxl/port: Enumerate cxl link capabilities
  2023-06-15  1:30 ` [PATCH v2 11/12] cxl/port: Enumerate cxl link capabilities Dan Williams
  2023-06-15 21:37   ` Dave Jiang
@ 2023-06-16  0:07   ` Dan Williams
  2023-06-16 19:16     ` Dan Williams
  1 sibling, 1 reply; 27+ messages in thread
From: Dan Williams @ 2023-06-16  0:07 UTC (permalink / raw)
  To: Dan Williams, linux-cxl

Dan Williams wrote:
> Per CXL 3.0 9.14 "Back-Invalidation Configuration", in order to enable
> an HDM-DB range (CXL.mem region with device initiated back-invalidation
> support), all ports in the path between the endpoint and the host bridge
> must be in 256-bit flit-mode.
> 
> Even for typical Type-3 class devices it is useful to enumerate link
> capabilities through the topology for debug purposes.
> 
> See CXL 3.0 Table-64 "256B Flit Mode vs. 68B Flit Mode Operation", for
> how to determine 64B vs 256B Flit mode operation.
> 
> Signed-off-by: Dan Williams <dan.j.williams@intel.com>
> ---
>  drivers/cxl/core/pci.c  |  113 +++++++++++++++++++++++++++++++++++++++++++++++
>  drivers/cxl/core/port.c |    6 ++
>  drivers/cxl/cxl.h       |    7 +++
>  drivers/cxl/cxlpci.h    |   24 +++++++++-
>  drivers/cxl/port.c      |    5 ++
>  5 files changed, 153 insertions(+), 2 deletions(-)

Going back over this again I noticed that it fails to actually store the
"features" in the port object, and it fails to claim that the root CXL
device can support all the capabilities. Here are those fixups to fold
in:

-- >8 --
diff --git a/drivers/cxl/core/pci.c b/drivers/cxl/core/pci.c
index 7440f84be6c8..659da6cada6c 100644
--- a/drivers/cxl/core/pci.c
+++ b/drivers/cxl/core/pci.c
@@ -555,10 +555,8 @@ int cxl_probe_link(struct cxl_port *port)
 	dev = &pdev->dev;
 	dvsec = pci_find_dvsec_capability(pdev, PCI_DVSEC_VENDOR_ID_CXL,
 					  CXL_DVSEC_FLEXBUS_PORT);
-	if (!dvsec) {
-		dev_err(dev, "Failed to enumerate port capabilities\n");
+	if (!dvsec)
 		return -ENXIO;
-	}
 
 	/*
 	 * Cache the link features for future determination of 256B Flit
@@ -617,7 +615,7 @@ int cxl_probe_link(struct cxl_port *port)
 	/* Enforce port features are plumbed through to the host bridge */
 	features &= parent_features;
 
-	dev_dbg(dev, "features:%s%s%s%s%s%s%s%s%s\n",
+	dev_dbg(&port->dev, "%s: features:%s%s%s%s%s%s%s%s%s\n", dev_name(dev),
 		features & CXL_DVSEC_FLEXBUS_CACHE_ENABLED ? " cache" : "",
 		features & CXL_DVSEC_FLEXBUS_IO_ENABLED ? " io" : "",
 		features & CXL_DVSEC_FLEXBUS_MEM_ENABLED ? " mem" : "",
@@ -628,6 +626,8 @@ int cxl_probe_link(struct cxl_port *port)
 		features & CXL_PORT_FEATURE_FLIT68 ? " flit68" : "",
 		features & CXL_PORT_FEATURE_FLIT256 ? " flit256" : "");
 
+	port->features = features;
+
 	return 0;
 }
 EXPORT_SYMBOL_NS_GPL(cxl_probe_link, CXL);
diff --git a/drivers/cxl/core/port.c b/drivers/cxl/core/port.c
index bf8f25063914..05ec8c6e8a6d 100644
--- a/drivers/cxl/core/port.c
+++ b/drivers/cxl/core/port.c
@@ -670,7 +670,8 @@ static struct cxl_port *cxl_port_alloc(struct device *uport,
 	 * cxl_probe_link() will fix this up later in cxl_probe_link() for all
 	 * other ports.
 	 */
-	port->features = CXL_DVSEC_FLEXBUS_ENABLE_MASK;
+	port->features = CXL_DVSEC_FLEXBUS_ENABLE_MASK |
+			 CXL_PORT_FEATURE_FLIT68 | CXL_PORT_FEATURE_FLIT256;
 	port->component_reg_phys = component_reg_phys;
 	ida_init(&port->decoder_ida);
 	port->hdm_end = -1;
diff --git a/drivers/cxl/port.c b/drivers/cxl/port.c
index 5ffe3c7d2f5e..a2641a3eecec 100644
--- a/drivers/cxl/port.c
+++ b/drivers/cxl/port.c
@@ -143,8 +143,10 @@ static int cxl_port_probe(struct device *dev)
 	int rc;
 
 	rc = cxl_probe_link(port);
-	if (rc)
+	if (rc) {
+		dev_err(dev, "Failed to enumerate port capabilities: %d\n", rc);
 		return rc;
+	}
 
 	if (is_cxl_endpoint(port))
 		return cxl_endpoint_port_probe(port);

^ permalink raw reply related	[flat|nested] 27+ messages in thread

* RE: [PATCH v2 11/12] cxl/port: Enumerate cxl link capabilities
  2023-06-16  0:07   ` Dan Williams
@ 2023-06-16 19:16     ` Dan Williams
  2023-06-22 14:04       ` Jonathan Cameron
  0 siblings, 1 reply; 27+ messages in thread
From: Dan Williams @ 2023-06-16 19:16 UTC (permalink / raw)
  To: Dan Williams, linux-cxl

Dan Williams wrote:
> Dan Williams wrote:
> > Per CXL 3.0 9.14 "Back-Invalidation Configuration", in order to enable
> > an HDM-DB range (CXL.mem region with device initiated back-invalidation
> > support), all ports in the path between the endpoint and the host bridge
> > must be in 256-bit flit-mode.
> > 
> > Even for typical Type-3 class devices it is useful to enumerate link
> > capabilities through the topology for debug purposes.
> > 
> > See CXL 3.0 Table-64 "256B Flit Mode vs. 68B Flit Mode Operation", for
> > how to determine 64B vs 256B Flit mode operation.
> > 
> > Signed-off-by: Dan Williams <dan.j.williams@intel.com>
> > ---
> >  drivers/cxl/core/pci.c  |  113 +++++++++++++++++++++++++++++++++++++++++++++++
> >  drivers/cxl/core/port.c |    6 ++
> >  drivers/cxl/cxl.h       |    7 +++
> >  drivers/cxl/cxlpci.h    |   24 +++++++++-
> >  drivers/cxl/port.c      |    5 ++
> >  5 files changed, 153 insertions(+), 2 deletions(-)
> 
> Going back over this again I noticed that it fails to actually store the
> "features" in the port object, and it fails to claim that the root CXL
> device can support all the capabilities. Here are those fixups to fold
> in:

...and now it occurs to me that this approach falls over for RCH
topologies as the link status registers potentially move into the RCRB
space. So I want to test this on an RCH topology before this moves
forward. The cxl_test RCH topology does not suffice since it only
emulates the topology, not the register behavior, and QEMU is VH only.

^ permalink raw reply	[flat|nested] 27+ messages in thread

* Re: [PATCH v2 03/12] cxl: Fix kernel-doc warnings
  2023-06-15  1:29 ` [PATCH v2 03/12] cxl: Fix kernel-doc warnings Dan Williams
  2023-06-15 21:28   ` Dave Jiang
@ 2023-06-22 13:50   ` Jonathan Cameron
  1 sibling, 0 replies; 27+ messages in thread
From: Jonathan Cameron @ 2023-06-22 13:50 UTC (permalink / raw)
  To: Dan Williams; +Cc: linux-cxl

On Wed, 14 Jun 2023 18:29:51 -0700
Dan Williams <dan.j.williams@intel.com> wrote:

> After Jonathan noticed [1] that 'struct cxl_dev_state' had a kernel-doc
> entry without a corresponding struct attribute I ran the kernel-doc
> script to see what else might be broken. Fix these warnings:
> 
> drivers/cxl/cxlmem.h:199: warning: This comment starts with '/**', but isn't a kernel-doc comment. Refer Documentation/doc-guide/kernel-doc.rst
>  * Event Interrupt Policy
> drivers/cxl/cxlmem.h:224: warning: Function parameter or member 'buf' not described in 'cxl_event_state'
> drivers/cxl/cxlmem.h:224: warning: Function parameter or member 'log_lock' not described in 'cxl_event_state'
> 
> Note that scripts/kernel-doc only finds missing kernel-doc entries. It
> does not warn on too many kernel-doc entries, i.e. it did not catch the
> fact that @info refers to a not present member.
> 
> Link: http://lore.kernel.org/r/20230606121054.000069e1@Huawei.com [1]
> Signed-off-by: Dan Williams <dan.j.williams@intel.com>

FWIW given how trivial this is.

Reviewed-by: Jonathan Cameron <Jonathan.Cameron@huawei.com>

> ---
>  drivers/cxl/cxlmem.h |    6 +++---
>  1 file changed, 3 insertions(+), 3 deletions(-)
> 
> diff --git a/drivers/cxl/cxlmem.h b/drivers/cxl/cxlmem.h
> index a2845a7a69d8..8e4ba5b52902 100644
> --- a/drivers/cxl/cxlmem.h
> +++ b/drivers/cxl/cxlmem.h
> @@ -195,7 +195,7 @@ static inline int cxl_mbox_cmd_rc2errno(struct cxl_mbox_cmd *mbox_cmd)
>   */
>  #define CXL_CAPACITY_MULTIPLIER SZ_256M
>  
> -/**
> +/*
>   * Event Interrupt Policy
>   *
>   * CXL rev 3.0 section 8.2.9.2.4; Table 8-52
> @@ -215,8 +215,8 @@ struct cxl_event_interrupt_policy {
>  /**
>   * struct cxl_event_state - Event log driver state
>   *
> - * @event_buf: Buffer to receive event data
> - * @event_log_lock: Serialize event_buf and log use
> + * @buf: Buffer to receive event data
> + * @log_lock: Serialize event_buf and log use
>   */
>  struct cxl_event_state {
>  	struct cxl_get_event_payload *buf;
> 


^ permalink raw reply	[flat|nested] 27+ messages in thread

* Re: [PATCH v2 04/12] cxl: Remove leftover attribute documentation in 'struct cxl_dev_state'
  2023-06-15 21:29   ` Dave Jiang
@ 2023-06-22 13:50     ` Jonathan Cameron
  0 siblings, 0 replies; 27+ messages in thread
From: Jonathan Cameron @ 2023-06-22 13:50 UTC (permalink / raw)
  To: Dave Jiang; +Cc: Dan Williams, linux-cxl

On Thu, 15 Jun 2023 14:29:08 -0700
Dave Jiang <dave.jiang@intel.com> wrote:

> On 6/14/23 18:29, Dan Williams wrote:
> > commit 14d788740774 ("cxl/mem: Consolidate CXL DVSEC Range enumeration
> > in the core")
> > 
> > ...removed @info from 'struct cxl_dev_state', but neglected to remove
> > the corresponding kernel-doc entry. Complete the removal.
> > 
> > Reported-by: Jonathan Cameron <Jonathan.Cameron@Huawei.com>
> > Closes: http://lore.kernel.org/r/20230606121054.000069e1@Huawei.com
> > Signed-off-by: Dan Williams <dan.j.williams@intel.com>  
> Reviewed-by: Dave Jiang <dave.jiang@intel.com>

Reviewed-by: Jonathan Cameron <Jonathan.Cameron@huawei.com>

> 
> > ---
> >   drivers/cxl/cxlmem.h |    1 -
> >   1 file changed, 1 deletion(-)
> > 
> > diff --git a/drivers/cxl/cxlmem.h b/drivers/cxl/cxlmem.h
> > index 8e4ba5b52902..66896fc6c43f 100644
> > --- a/drivers/cxl/cxlmem.h
> > +++ b/drivers/cxl/cxlmem.h
> > @@ -287,7 +287,6 @@ struct cxl_poison_state {
> >    * @next_volatile_bytes: volatile capacity change pending device reset
> >    * @next_persistent_bytes: persistent capacity change pending device reset
> >    * @component_reg_phys: register base of component registers
> > - * @info: Cached DVSEC information about the device.
> >    * @serial: PCIe Device Serial Number
> >    * @event: event log driver state
> >    * @poison: poison driver state info
> >   


^ permalink raw reply	[flat|nested] 27+ messages in thread

* Re: [PATCH v2 06/12] cxl/memdev: Make mailbox functionality optional
  2023-06-15 21:30   ` Dave Jiang
@ 2023-06-22 13:52     ` Jonathan Cameron
  0 siblings, 0 replies; 27+ messages in thread
From: Jonathan Cameron @ 2023-06-22 13:52 UTC (permalink / raw)
  To: Dave Jiang; +Cc: Dan Williams, linux-cxl

On Thu, 15 Jun 2023 14:30:35 -0700
Dave Jiang <dave.jiang@intel.com> wrote:

> On 6/14/23 18:30, Dan Williams wrote:
> > In support of the Linux CXL core scaling for a wider set of CXL devices,
> > allow for the creation of memdevs with some memory device capabilities
> > disabled. Specifically, allow for CXL devices outside of those claiming
> > to be compliant with the generic CXL memory device class code, like
> > vendor specific Type-2/3 devices that host CXL.mem. This implies, allow
> > for the creation of memdevs that only support component-registers, not
> > necessarily memory-device-registers (like mailbox registers). A memdev
> > derived from a CXL endpoint that does not support generic class code
> > expectations is tagged "CXL_DEVTYPE_DEVMEM", while a memdev derived from a
> > class-code compliant endpoint is tagged "CXL_DEVTYPE_CLASSMEM".
> > 
> > The primary assumption of a CXL_DEVTYPE_DEVMEM memdev is that it
> > optionally may not host a mailbox. Disable the command passthrough ioctl
> > for memdevs that are not CXL_DEVTYPE_CLASSMEM, and return empty strings
> > from memdev attributes associated with data retrieved via the
> > class-device-standard IDENTIFY command. Note that empty strings were
> > chosen over attribute visibility to maintain compatibility with shipping
> > versions of cxl-cli that expect those attributes to always be present.
> > Once cxl-cli has dropped that requirement this workaround can be
> > deprecated.
> > 
> > Signed-off-by: Dan Williams <dan.j.williams@intel.com>  
> 
> Reviewed-by: Dave Jiang <dave.jiang@intel.com>

Reviewed-by: Jonathan Cameron <Jonathan.Cameron@huawei.com>

^ permalink raw reply	[flat|nested] 27+ messages in thread

* Re: [PATCH v2 10/12] cxl/pci: Unconditionally unmask 256B Flit errors
  2023-06-15 21:34   ` Dave Jiang
@ 2023-06-22 13:55     ` Jonathan Cameron
  0 siblings, 0 replies; 27+ messages in thread
From: Jonathan Cameron @ 2023-06-22 13:55 UTC (permalink / raw)
  To: Dave Jiang; +Cc: Dan Williams, linux-cxl

On Thu, 15 Jun 2023 14:34:00 -0700
Dave Jiang <dave.jiang@intel.com> wrote:

> On 6/14/23 18:30, Dan Williams wrote:
> > The current check for 256B Flit mode is incomplete and unnecessary. It
> > is incomplete because it fails to consider the link speed, or check for
> > CXL link capabilities. It is unnecessary because unconditionally
> > unmasking 256B Flit errors is a nop when 256B Flit operation is not
> > available.
> > 
> > Remove this check in preparation for creating a cxl_probe_link() helper
> > to centralize this detection.
> > 
> > Signed-off-by: Dan Williams <dan.j.williams@intel.com>  
> 
> Reviewed-by: Dave Jiang <dave.jiang@intel.com>
Reviewed-by: Jonathan Cameron <Jonathan.Cameron@huawei.com>

^ permalink raw reply	[flat|nested] 27+ messages in thread

* Re: [PATCH v2 11/12] cxl/port: Enumerate cxl link capabilities
  2023-06-16 19:16     ` Dan Williams
@ 2023-06-22 14:04       ` Jonathan Cameron
  0 siblings, 0 replies; 27+ messages in thread
From: Jonathan Cameron @ 2023-06-22 14:04 UTC (permalink / raw)
  To: Dan Williams; +Cc: linux-cxl

On Fri, 16 Jun 2023 12:16:06 -0700
Dan Williams <dan.j.williams@intel.com> wrote:

> Dan Williams wrote:
> > Dan Williams wrote:  
> > > Per CXL 3.0 9.14 "Back-Invalidation Configuration", in order to enable
> > > an HDM-DB range (CXL.mem region with device initiated back-invalidation
> > > support), all ports in the path between the endpoint and the host bridge
> > > must be in 256-bit flit-mode.
> > > 
> > > Even for typical Type-3 class devices it is useful to enumerate link
> > > capabilities through the topology for debug purposes.
> > > 
> > > See CXL 3.0 Table-64 "256B Flit Mode vs. 68B Flit Mode Operation", for
> > > how to determine 64B vs 256B Flit mode operation.
> > > 
> > > Signed-off-by: Dan Williams <dan.j.williams@intel.com>
> > > ---
> > >  drivers/cxl/core/pci.c  |  113 +++++++++++++++++++++++++++++++++++++++++++++++
> > >  drivers/cxl/core/port.c |    6 ++
> > >  drivers/cxl/cxl.h       |    7 +++
> > >  drivers/cxl/cxlpci.h    |   24 +++++++++-
> > >  drivers/cxl/port.c      |    5 ++
> > >  5 files changed, 153 insertions(+), 2 deletions(-)  
> > 
> > Going back over this again I noticed that it fails to actually store the
> > "features" in the port object, and it fails to claim that the root CXL
> > device can support all the capabilities. Here are those fixups to fold
> > in:  
> 
> ...and now it occurs to me that this approach falls over for RCH
> topologies as the link status registers potentially move into the RCRB
> space. So I want to test this on an RCH topology before this moves
> forward. The cxl_test RCH topology does not suffice since it only
> emulates the topology, not the register behavior, and QEMU is VH only.

Indeed awkward to test. Other than that, LGTM but I'll wait for the update
for any tags.

Thanks,

Jonathan

p.s. still open to someone adding an RCH to QEMU if anyone wants to :)

^ permalink raw reply	[flat|nested] 27+ messages in thread

end of thread, other threads:[~2023-06-22 14:05 UTC | newest]

Thread overview: 27+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2023-06-15  1:29 [PATCH v2 00/12] Device memory prep Dan Williams
2023-06-15  1:29 ` [PATCH v2 01/12] cxl/regs: Clarify when a 'struct cxl_register_map' is input vs output Dan Williams
2023-06-15  1:29 ` [PATCH v2 02/12] tools/testing/cxl: Remove unused @cxlds argument Dan Williams
2023-06-15  1:29 ` [PATCH v2 03/12] cxl: Fix kernel-doc warnings Dan Williams
2023-06-15 21:28   ` Dave Jiang
2023-06-22 13:50   ` Jonathan Cameron
2023-06-15  1:29 ` [PATCH v2 04/12] cxl: Remove leftover attribute documentation in 'struct cxl_dev_state' Dan Williams
2023-06-15 21:29   ` Dave Jiang
2023-06-22 13:50     ` Jonathan Cameron
2023-06-15  1:30 ` [PATCH v2 05/12] cxl/mbox: Move mailbox related driver state to its own data structure Dan Williams
2023-06-15  1:30 ` [PATCH v2 06/12] cxl/memdev: Make mailbox functionality optional Dan Williams
2023-06-15 21:30   ` Dave Jiang
2023-06-22 13:52     ` Jonathan Cameron
2023-06-15  1:30 ` [PATCH v2 07/12] cxl/port: Rename CXL_DECODER_{EXPANDER, ACCELERATOR} => {HOSTONLYMEM, DEVMEM} Dan Williams
2023-06-15 21:31   ` Dave Jiang
2023-06-15  1:30 ` [PATCH v2 08/12] cxl/hdm: Default CXL_DEVTYPE_DEVMEM decoders to CXL_DECODER_DEVMEM Dan Williams
2023-06-15 21:32   ` Dave Jiang
2023-06-15  1:30 ` [PATCH v2 09/12] cxl/region: Manage decoder target_type at decoder-attach time Dan Williams
2023-06-15  1:30 ` [PATCH v2 10/12] cxl/pci: Unconditionally unmask 256B Flit errors Dan Williams
2023-06-15 21:34   ` Dave Jiang
2023-06-22 13:55     ` Jonathan Cameron
2023-06-15  1:30 ` [PATCH v2 11/12] cxl/port: Enumerate cxl link capabilities Dan Williams
2023-06-15 21:37   ` Dave Jiang
2023-06-16  0:07   ` Dan Williams
2023-06-16 19:16     ` Dan Williams
2023-06-22 14:04       ` Jonathan Cameron
2023-06-15  1:30 ` [PATCH v2 12/12] cxl/memdev: Formalize endpoint port linkage Dan Williams

This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.