linux-cxl.vger.kernel.org archive mirror
 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 07/16] cxl/core: Set up isolation interrupts
Date: Wed, 30 Jul 2025 16:47:09 -0500	[thread overview]
Message-ID: <20250730214718.10679-8-Benjamin.Cheatham@amd.com> (raw)
In-Reply-To: <20250730214718.10679-1-Benjamin.Cheatham@amd.com>

Register a CXL isolation interrupt handler as part of cxl_dport set up.
Only CXL-capable PCIe Root Ports have CXL.mem isolation interrupt support.
The interrupts are left masked and will be unmasked in a later commit.

A CXL-capable PCIe Root Port that has CXL.mem isolation support and no
interrupt support will have any isolation support enabled. If
isolation were enabled without interrupts CXL.mem transactions could
return poisoned data. This could cause data/system corruption if left
unhandled, so the capability is left disabled in this case.

CXL endpoint drivers can add an isolation handler for a device through
the isolation_handler member of struct cxl_dev_state. If this handler
is not present, the system will panic. If the handler opts to not panic
(i.e. returns "CXL_ERR_NONE"), the endpoint driver is charged with
maintaining system reliability (cleaning up CXL memory, disabling device
state, etc.).

Signed-off-by: Ben Cheatham <Benjamin.Cheatham@amd.com>
---
 drivers/cxl/core/port.c | 113 ++++++++++++++++++++++++++++++++++++++--
 drivers/cxl/cxl.h       |   1 +
 drivers/cxl/cxlmem.h    |   4 ++
 include/cxl/isolation.h |  10 ++++
 4 files changed, 125 insertions(+), 3 deletions(-)

diff --git a/drivers/cxl/core/port.c b/drivers/cxl/core/port.c
index 71e954ebc5aa..a36440e85647 100644
--- a/drivers/cxl/core/port.c
+++ b/drivers/cxl/core/port.c
@@ -1174,15 +1174,117 @@ static void cxl_dport_unlink(void *data)
 	sysfs_remove_link(&port->dev.kobj, link_name);
 }
 
+struct isolation_intr_data {
+	struct cxl_dport *dport;
+	struct cxl_port *port;
+};
+
+static irqreturn_t cxl_isolation_thread(int irq, void *_data)
+{
+	struct isolation_intr_data *data = _data;
+	struct cxl_dport *dport = data->dport;
+	struct cxl_port *port = data->port;
+	enum cxl_err_results res, acc;
+	struct cxl_dev_state *cxlds;
+	struct cxl_memdev *cxlmd;
+	struct cxl_dport *iter;
+	unsigned long index;
+	struct cxl_ep *ep;
+	bool lnk_down;
+	u32 status;
+
+	if (!dport || !port)
+		return IRQ_NONE;
+
+	guard(device)(&port->dev);
+	if (!dport->regs.isolation)
+		goto panic;
+
+	status = readl(dport->regs.isolation + CXL_ISOLATION_STATUS_OFFSET);
+	lnk_down = FIELD_GET(CXL_ISOLATION_STAT_LNK_DOWN, status);
+
+	acc = CXL_ERR_NONE;
+	xa_for_each(&port->endpoints, index, ep) {
+		iter = ep->dport;
+		while (iter && (&iter->port->dev != &port->dev))
+			iter = iter->port->parent_dport;
+
+		res = CXL_ERR_PANIC;
+		if (iter->dport_dev == dport->dport_dev) {
+			cxlmd = to_cxl_memdev(ep->ep);
+			cxlds = cxlmd->cxlds;
+
+			if (cxlds && cxlds->isolation_handler)
+				res = cxlds->isolation_handler(cxlds, lnk_down);
+		}
+
+		acc = max(res, acc);
+	}
+
+	if (acc == CXL_ERR_NONE)
+		return IRQ_HANDLED;
+
+panic:
+	panic("%s: downstream devices could not recover from CXL.mem link down\n",
+	      dev_name(dport->dport_dev));
+	return IRQ_NONE;
+}
+
+static void cxl_dport_free_interrupts(void *data)
+{
+	struct cxl_isolation_info *info;
+	struct cxl_dport *dport = data;
+	struct pci_dev *pdev = to_pci_dev(dport->dport_dev);
+
+	info = pcie_cxl_dport_get_isolation_info(pdev);
+	if (!info)
+		return;
+
+	devm_free_irq(info->dev, info->irq, dport);
+}
+
+static int cxl_dport_setup_interrupts(struct device *host,
+				      struct cxl_dport *dport)
+{
+	struct isolation_intr_data *data;
+	struct cxl_isolation_info *info;
+	u32 cap;
+	int rc;
+
+	cap = readl(dport->regs.isolation + CXL_ISOLATION_CAPABILITY_OFFSET);
+	if (!(cap & CXL_ISOLATION_CAP_INTR_SUPP))
+		return -ENXIO;
+
+	info = pcie_cxl_dport_get_isolation_info(to_pci_dev(dport->dport_dev));
+	if (!info)
+		return -ENXIO;
+
+	data = devm_kmalloc(host, sizeof(*data), GFP_KERNEL);
+	if (!data)
+		return -ENOMEM;
+	data->port = dport->port;
+	data->dport = dport;
+
+	rc = devm_request_threaded_irq(info->dev, info->irq, NULL,
+				       cxl_isolation_thread,
+				       IRQF_SHARED | IRQF_ONESHOT,
+				       "cxl_isolation", data);
+	if (rc)
+		return rc;
+
+	return devm_add_action_or_reset(host, cxl_dport_free_interrupts, dport);
+}
+
 /**
  * cxl_dport_enable_isolation - Enable CXL Isolation for a CXL dport. This is
  * an optional capability only supported by PCIe Root Ports.
- *
+ * @host: Host device for @dport
  * @dport: CXL-capable PCIe Root Port
  *
  * Returns 0 if capability unsupported, or when enabled.
  */
-static int cxl_dport_enable_isolation(struct cxl_dport *dport)
+static int cxl_dport_enable_isolation(struct device *host,
+				      struct cxl_dport *dport)
 {
 	u32 cap;
 	int rc;
@@ -1199,6 +1301,10 @@ static int cxl_dport_enable_isolation(struct cxl_dport *dport)
 	if (!(cap & CXL_ISOLATION_CAP_MEM_ISO_SUPP))
 		return 0;
 
+	rc = cxl_dport_setup_interrupts(host, dport);
+	if (rc)
+		return rc == -ENXIO ? 0 : rc;
+
 	cxl_enable_isolation(dport);
 	return 0;
 }
@@ -1266,7 +1372,7 @@ __devm_cxl_add_dport(struct cxl_port *port, struct device *dport_dev,
 			&component_reg_phys);
 
 	if (IS_ENABLED(CONFIG_CXL_ISOLATION)) {
-		rc = cxl_dport_enable_isolation(dport);
+		rc = cxl_dport_enable_isolation(host, dport);
 		if (rc)
 			return ERR_PTR(rc);
 	}
@@ -1543,6 +1649,7 @@ static void reap_dport(struct cxl_port *port, struct cxl_dport *dport)
 {
 	devm_release_action(&port->dev, cxl_dport_unlink, dport);
 	devm_release_action(&port->dev, cxl_dport_remove, dport);
+	devm_release_action(&port->dev, cxl_dport_free_interrupts, dport);
 	devm_kfree(&port->dev, dport);
 }
 
diff --git a/drivers/cxl/cxl.h b/drivers/cxl/cxl.h
index 999ffa05b68f..9e3ca754251d 100644
--- a/drivers/cxl/cxl.h
+++ b/drivers/cxl/cxl.h
@@ -143,6 +143,7 @@ static inline int ways_to_eiw(unsigned int ways, u8 *eiw)
 #define   CXL_ISOLATION_CTRL_MEM_ISO_ENABLE BIT(16)
 #define CXL_ISOLATION_STATUS_OFFSET 0xC
 #define   CXL_ISOLATION_STAT_MEM_ISO BIT(8)
+#define   CXL_ISOLATION_STAT_LNK_DOWN BIT(9)
 #define   CXL_ISOLATION_STAT_RP_BUSY BIT(14)
 #define CXL_ISOLATION_CAPABILITY_LENGTH 0x10
 
diff --git a/drivers/cxl/cxlmem.h b/drivers/cxl/cxlmem.h
index 551b0ba2caa1..fbe64c580785 100644
--- a/drivers/cxl/cxlmem.h
+++ b/drivers/cxl/cxlmem.h
@@ -9,6 +9,7 @@
 #include <linux/node.h>
 #include <cxl/event.h>
 #include <cxl/mailbox.h>
+#include <cxl/isolation.h>
 #include "cxl.h"
 
 /* CXL 2.0 8.2.8.5.1.1 Memory Device Status Register */
@@ -426,6 +427,7 @@ struct cxl_dpa_partition {
  * @type: Generic Memory Class device or Vendor Specific Memory device
  * @cxl_mbox: CXL mailbox context
  * @cxlfs: CXL features context
+ * @isolation_handler: CXL isolation CXL.mem link down handler
  */
 struct cxl_dev_state {
 	struct device *dev;
@@ -444,6 +446,8 @@ struct cxl_dev_state {
 #ifdef CONFIG_CXL_FEATURES
 	struct cxl_features_state *cxlfs;
 #endif
+	enum cxl_err_results (*isolation_handler)(struct cxl_dev_state *cxlds,
+						  bool lnk_down);
 };
 
 static inline resource_size_t cxl_pmem_size(struct cxl_dev_state *cxlds)
diff --git a/include/cxl/isolation.h b/include/cxl/isolation.h
index 429501a655dd..3ad05ccc5e01 100644
--- a/include/cxl/isolation.h
+++ b/include/cxl/isolation.h
@@ -4,6 +4,16 @@
 
 #include <linux/pci.h>
 
+/**
+ * enum cxl_err_results - Possible results of an CXL isolation handler
+ * @CXL_ERR_NONE: Device can recover without CXL core intervention
+ * @CXL_ERR_PANIC: Device can't recover
+ */
+enum cxl_err_results {
+	CXL_ERR_NONE = 0,
+	CXL_ERR_PANIC,
+};
+
 /**
  * struct cxl_isolation_info - Information for mapping CXL Isolation interrupts
  * @dev: PCIe portdrv service device associated with IRQ
-- 
2.34.1


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

Thread overview: 24+ 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-07-30 21:47 ` [PATCH 02/16] cxl/regs: Add CXL Isolation capability mapping Ben Cheatham
2025-07-30 21:47 ` [PATCH 03/16] PCI: PCIe portdrv: Add CXL Isolation service driver Ben Cheatham
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-07-30 21:47 ` Ben Cheatham [this message]
2025-07-30 21:47 ` [PATCH 08/16] cxl/core: Enable CXL isolation interrupts 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 ` [PATCH 12/16] PCI: PCIe portdrv: Add cxl_isolation sysfs attributes Ben Cheatham
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-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-8-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 a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).