All of lore.kernel.org
 help / color / mirror / Atom feed
From: Ben Cheatham <Benjamin.Cheatham@amd.com>
To: <linux-cxl@vger.kernel.org>, <linux-pci@vger.kernel.org>,
	<linux-acpi@vger.kernel.org>
Cc: Ben Cheatham <Benjamin.Cheatham@amd.com>
Subject: [PATCH 12/16] PCI: PCIe portdrv: Add cxl_isolation sysfs attributes
Date: Wed, 30 Jul 2025 16:47:14 -0500	[thread overview]
Message-ID: <20250730214718.10679-13-Benjamin.Cheatham@amd.com> (raw)
In-Reply-To: <20250730214718.10679-1-Benjamin.Cheatham@amd.com>

Add sysfs attributes to enable/disable CXL isolation and transaction
timeout. The intended use for these attributes is to disable isolation
and/or timeout as part of device maintenance or hotplug.

The attributes are added under a new "cxl_isolation" group on the PCIe
Root Port device.

Signed-off-by: Ben Cheatham <Benjamin.Cheatham@amd.com>
---
 drivers/cxl/core/port.c          |  29 ++++++
 drivers/pci/pci-sysfs.c          |   3 +
 drivers/pci/pci.h                |   4 +
 drivers/pci/pcie/cxl_isolation.c | 158 +++++++++++++++++++++++++++++++
 include/cxl/isolation.h          |   8 ++
 5 files changed, 202 insertions(+)

diff --git a/drivers/cxl/core/port.c b/drivers/cxl/core/port.c
index 6591e83e719c..b5a306341bb2 100644
--- a/drivers/cxl/core/port.c
+++ b/drivers/cxl/core/port.c
@@ -1346,6 +1346,7 @@ static int cxl_dport_enable_timeout_isolation(struct device *host,
 	if (!(cap & CXL_ISOLATION_CAP_MEM_TIME_SUPP))
 		cxl_enable_timeout(dport);
 
+	pcie_update_cxl_isolation_group(dport->dport_dev);
 	return 0;
 }
 
@@ -1598,6 +1599,34 @@ struct cxl_port *find_cxl_port(struct device *dport_dev,
 	return port;
 }
 
+/**
+ * cxl_find_pcie_rp - Find CXL port that contains a CXL-capable PCIe Root Port
+ * @dport_dev: CXL-capable PCIe Root Port device
+ * @rp: Pointer to store found dport in
+ *
+ * Returns CXL port with elevated reference count if @dport_dev is found
+ */
+struct cxl_port *cxl_find_pcie_rp(struct pci_dev *dport_dev,
+				  struct cxl_dport **rp)
+{
+	struct cxl_dport *dport;
+	struct cxl_port *parent;
+
+	struct cxl_port *hb __free(put_cxl_port) =
+		find_cxl_port(&dport_dev->dev, &dport);
+	if (!hb || !dport)
+		return NULL;
+
+	parent = parent_port_of(hb);
+	if (!parent || !is_cxl_root(parent))
+		return NULL;
+
+	if (rp)
+		*rp = dport;
+
+	return_ptr(hb);
+}
+
 static struct cxl_port *find_cxl_port_at(struct cxl_port *parent_port,
 					 struct device *dport_dev,
 					 struct cxl_dport **dport)
diff --git a/drivers/pci/pci-sysfs.c b/drivers/pci/pci-sysfs.c
index 268c69daa4d5..86e8d8d918cf 100644
--- a/drivers/pci/pci-sysfs.c
+++ b/drivers/pci/pci-sysfs.c
@@ -1815,6 +1815,9 @@ const struct attribute_group *pci_dev_attr_groups[] = {
 #endif
 #ifdef CONFIG_PCI_DOE
 	&pci_doe_sysfs_group,
+#endif
+#ifdef CONFIG_CXL_ISOLATION
+	&cxl_isolation_attr_group,
 #endif
 	NULL,
 };
diff --git a/drivers/pci/pci.h b/drivers/pci/pci.h
index c7fc86d93bea..3510a75c880b 100644
--- a/drivers/pci/pci.h
+++ b/drivers/pci/pci.h
@@ -677,6 +677,10 @@ static inline void pci_rcec_exit(struct pci_dev *dev) { }
 static inline void pcie_link_rcec(struct pci_dev *rcec) { }
 #endif
 
+#ifdef CONFIG_CXL_ISOLATION
+extern struct attribute_group cxl_isolation_attr_group;
+#endif
+
 #ifdef CONFIG_PCI_ATS
 /* Address Translation Service */
 void pci_ats_init(struct pci_dev *dev);
diff --git a/drivers/pci/pcie/cxl_isolation.c b/drivers/pci/pcie/cxl_isolation.c
index 5a56a327b599..9d2ad14810e8 100644
--- a/drivers/pci/pcie/cxl_isolation.c
+++ b/drivers/pci/pcie/cxl_isolation.c
@@ -77,6 +77,164 @@ pcie_cxl_dport_get_isolation_info(struct pci_dev *dport_dev)
 	return get_service_data(to_pcie_device(dev));
 }
 
+static ssize_t isolation_ctrl_store(struct device *dev,
+				    struct device_attribute *attr,
+				    const char *buf, size_t n)
+{
+	struct pci_dev *pdev = to_pci_dev(dev);
+	struct cxl_port *port;
+	bool enable;
+	int rc;
+
+	rc = kstrtobool(buf, &enable);
+	if (rc)
+		return rc;
+
+	struct cxl_dport **dport __free(kfree) =
+		kzalloc(sizeof(*dport), GFP_KERNEL);
+	if (!dport)
+		return -ENOMEM;
+
+	port = cxl_find_pcie_rp(pdev, dport);
+	if (!port || !(*dport))
+		return -ENODEV;
+
+	if (enable)
+		cxl_enable_isolation(*dport);
+	else
+		rc = cxl_disable_isolation(*dport);
+
+	put_device(&port->dev);
+	return rc ? rc : n;
+}
+
+static ssize_t isolation_ctrl_show(struct device *dev,
+				   struct device_attribute *attr, char *buf)
+{
+	struct pci_dev *pdev = to_pci_dev(dev);
+	struct cxl_port *port;
+	u32 ctrl;
+
+	struct cxl_dport **dport __free(kfree) =
+		kzalloc(sizeof(*dport), GFP_KERNEL);
+	if (!dport)
+		return -ENOMEM;
+
+	port = cxl_find_pcie_rp(pdev, dport);
+	if (!port || !(*dport))
+		return -ENODEV;
+
+	if (!(*dport)->regs.isolation)
+		return -ENXIO;
+
+	ctrl = readl((*dport)->regs.isolation + CXL_ISOLATION_CTRL_OFFSET);
+	put_device(&port->dev);
+
+	return sysfs_emit(buf, "%lu\n",
+			  FIELD_GET(CXL_ISOLATION_CTRL_MEM_ISO_ENABLE, ctrl));
+}
+DEVICE_ATTR_RW(isolation_ctrl);
+
+static ssize_t timeout_ctrl_store(struct device *dev,
+				  struct device_attribute *attr,
+				  const char *buf, size_t n)
+{
+	struct pci_dev *pdev = to_pci_dev(dev);
+	struct cxl_port *port;
+	bool enable;
+	int rc;
+
+	rc = kstrtobool(buf, &enable);
+	if (rc)
+		return rc;
+
+	struct cxl_dport **dport __free(kfree) =
+		kzalloc(sizeof(*dport), GFP_KERNEL);
+	if (!dport)
+		return -ENOMEM;
+
+	port = cxl_find_pcie_rp(pdev, dport);
+	if (!port || !(*dport))
+		return -ENODEV;
+
+	if (enable)
+		cxl_enable_timeout(*dport);
+	else
+		cxl_disable_timeout(*dport);
+
+	put_device(&port->dev);
+	return n;
+}
+
+static ssize_t timeout_ctrl_show(struct device *dev,
+				 struct device_attribute *attr, char *buf)
+{
+	struct pci_dev *pdev = to_pci_dev(dev);
+	struct cxl_port *port;
+	u32 ctrl;
+
+	struct cxl_dport **dport __free(kfree) =
+		kzalloc(sizeof(*dport), GFP_KERNEL);
+	if (!dport)
+		return -ENOMEM;
+
+	port = cxl_find_pcie_rp(pdev, dport);
+	if (!port || !(*dport))
+		return -ENODEV;
+
+	if (!(*dport)->regs.isolation)
+		return -ENXIO;
+
+	ctrl = readl((*dport)->regs.isolation + CXL_ISOLATION_CTRL_OFFSET);
+	put_device(&port->dev);
+
+	return sysfs_emit(buf, "%lu\n",
+			  FIELD_GET(CXL_ISOLATION_CTRL_MEM_TIME_ENABLE, ctrl));
+}
+DEVICE_ATTR_RW(timeout_ctrl);
+
+static struct attribute *isolation_attrs[] = {
+	&dev_attr_timeout_ctrl.attr,
+	&dev_attr_isolation_ctrl.attr,
+	NULL,
+};
+
+static umode_t cxl_isolation_attrs_visible(struct kobject *kobj,
+					   struct attribute *a, int n)
+{
+	struct device *dev = kobj_to_dev(kobj);
+	struct pci_dev *pdev = to_pci_dev(dev);
+
+	if (!pcie_is_cxl(pdev) || pci_pcie_type(pdev) != PCI_EXP_TYPE_ROOT_PORT)
+		return 0;
+
+	if (pcie_port_find_device(pdev, PCIE_PORT_SERVICE_CXLISO))
+		return a->mode;
+	return 0;
+}
+
+const struct attribute_group cxl_isolation_attr_group = {
+	.name = "cxl_isolation",
+	.attrs = isolation_attrs,
+	.is_visible = cxl_isolation_attrs_visible,
+};
+
+void
+pcie_update_cxl_isolation_group(struct device *dport_dev)
+{
+	struct device *dev;
+
+	if (!dev_is_pci(dport_dev))
+		return;
+
+	dev = pcie_port_find_device(to_pci_dev(dport_dev),
+				    PCIE_PORT_SERVICE_CXLISO);
+	if (!dev)
+		return;
+
+	sysfs_update_group(&dport_dev->kobj, &cxl_isolation_attr_group);
+}
+
 static int cxl_isolation_probe(struct pcie_device *dev)
 {
 	struct cxl_isolation_info *info;
diff --git a/include/cxl/isolation.h b/include/cxl/isolation.h
index 73282ac262a6..0b6e4f0160a8 100644
--- a/include/cxl/isolation.h
+++ b/include/cxl/isolation.h
@@ -31,21 +31,29 @@ int cxl_disable_isolation(struct cxl_dport *dport);
 void cxl_enable_timeout(struct cxl_dport *dport);
 void cxl_disable_timeout(struct cxl_dport *dport);
 
+struct cxl_port *cxl_find_pcie_rp(struct pci_dev *pdev,
+				  struct cxl_dport **dport);
 #else /* !CONFIG_CXL_BUS */
 static inline void cxl_enable_isolation(struct cxl_dport *dport) {}
 static inline int cxl_disable_isolation(struct cxl_dport *dport)
 { return -ENXIO; }
 static inline void cxl_enable_timeout(struct cxl_dport *dport) {}
 static inline void cxl_disable_timeout(struct cxl_dport *dport) {}
+
+static inline struct cxl_port *cxl_find_pcie_rp(struct pci_dev *pdev,
+						struct cxl_dport **dport);
+{ return NULL; }
 #endif /* !CONFIG_CXL_BUS */
 
 #ifdef CONFIG_CXL_ISOLATION
 struct cxl_isolation_info *
 pcie_cxl_dport_get_isolation_info(struct pci_dev *dport_dev);
+void pcie_update_cxl_isolation_group(struct device *dport_dev);
 #else /* !CONFIG_CXL_ISOLATION */
 static inline struct cxl_isolation_info *
 pcie_cxl_dport_get_isolation_info(struct pci_dev *dport_dev)
 { return NULL; }
+static inline void pcie_update_cxl_isolation_group(struct device *dport_dev) {}
 #endif /* !CONFIG_CXL_ISOLATION */
 
 #endif
-- 
2.34.1


  parent reply	other threads:[~2025-07-30 21:50 UTC|newest]

Thread overview: 37+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2025-07-30 21:47 [PATCH 00/16] CXL.mem error isolation support Ben Cheatham
2025-07-30 21:47 ` [PATCH 01/16] cxl/regs: Add cxl_unmap_component_regs() Ben Cheatham
2025-09-12 14:46   ` Jonathan Cameron
2025-09-17 17:26     ` Cheatham, Benjamin
2025-07-30 21:47 ` [PATCH 02/16] cxl/regs: Add CXL Isolation capability mapping Ben Cheatham
2025-09-12 14:47   ` Jonathan Cameron
2025-07-30 21:47 ` [PATCH 03/16] PCI: PCIe portdrv: Add CXL Isolation service driver Ben Cheatham
2025-09-12 15:14   ` Jonathan Cameron
2025-09-17 17:26     ` Cheatham, Benjamin
2025-07-30 21:47 ` [PATCH 04/16] PCI: PCIe portdrv: Allocate CXL isolation MSI/-X vector Ben Cheatham
2025-08-04 21:39   ` Bjorn Helgaas
2025-08-06 17:58     ` Cheatham, Benjamin
2025-07-30 21:47 ` [PATCH 05/16] PCI: PCIe portdrv: Add interface for getting CXL isolation IRQ Ben Cheatham
2025-07-31  5:59   ` Lukas Wunner
2025-07-31 13:13     ` Cheatham, Benjamin
2025-07-30 21:47 ` [PATCH 06/16] cxl/core: Enable CXL.mem isolation Ben Cheatham
2025-09-12 15:21   ` Jonathan Cameron
2025-09-17 17:26     ` Cheatham, Benjamin
2025-07-30 21:47 ` [PATCH 07/16] cxl/core: Set up isolation interrupts Ben Cheatham
2025-09-12 15:25   ` Jonathan Cameron
2025-09-17 17:27     ` Cheatham, Benjamin
2025-07-30 21:47 ` [PATCH 08/16] cxl/core: Enable CXL " Ben Cheatham
2025-07-30 21:47 ` [PATCH 09/16] cxl/core: Prevent onlining CXL memory behind isolated ports Ben Cheatham
2025-07-30 21:47 ` [PATCH 10/16] cxl/core: Enable CXL.mem timeout Ben Cheatham
2025-07-30 21:47 ` [PATCH 11/16] cxl/pci: Add isolation handler Ben Cheatham
2025-07-30 21:47 ` Ben Cheatham [this message]
2025-09-12 15:33   ` [PATCH 12/16] PCI: PCIe portdrv: Add cxl_isolation sysfs attributes Jonathan Cameron
2025-09-17 17:27     ` Cheatham, Benjamin
2025-07-30 21:47 ` [PATCH 13/16] cxl/core, PCI: PCIe portdrv: Add CXL timeout range programming Ben Cheatham
2025-08-04 21:39   ` Bjorn Helgaas
2025-08-06 17:58     ` Cheatham, Benjamin
2025-09-12 15:55   ` Jonathan Cameron
2025-09-17 17:27     ` Cheatham, Benjamin
2025-07-30 21:47 ` [PATCH 14/16] ACPI: Add CXL isolation _OSC fields Ben Cheatham
2025-08-22 19:19   ` Rafael J. Wysocki
2025-07-30 21:47 ` [PATCH 15/16] cxl/core, cxl/acpi: Enable CXL isolation based on _OSC handshake Ben Cheatham
2025-07-30 21:47 ` [PATCH 16/16] cxl/core, cxl/acpi: Add CXL isolation notify handler Ben Cheatham

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=20250730214718.10679-13-Benjamin.Cheatham@amd.com \
    --to=benjamin.cheatham@amd.com \
    --cc=linux-acpi@vger.kernel.org \
    --cc=linux-cxl@vger.kernel.org \
    --cc=linux-pci@vger.kernel.org \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
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.