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 13/16] cxl/core, PCI: PCIe portdrv: Add CXL timeout range programming
Date: Wed, 30 Jul 2025 16:47:15 -0500 [thread overview]
Message-ID: <20250730214718.10679-14-Benjamin.Cheatham@amd.com> (raw)
In-Reply-To: <20250730214718.10679-1-Benjamin.Cheatham@amd.com>
Add functions to enable programming the CXL.mem transaction timeout
range, if supported. Add a sysfs attribute to the "cxl_isolation" group
to allow programming the timeout from userspace.
The attribute can take either the CXL spec-defined hex value for the
associated timeout range (CXL 3.2 8.2.4.24.2 field 3:0) or a
string with the range. The range string is formatted as the range letter
in uppercase or lowercase, with an optional "2" to specify the second
range in the aforementioned spec ref.
For example, to program the port with a timeout of 65ms to 210ms (range B)
the following strings could be specified: "b2"/"B2". Picking the first
portion of range B (16ms to 55ms) would be: "b"/"B".
Signed-off-by: Ben Cheatham <Benjamin.Cheatham@amd.com>
---
drivers/cxl/core/pci.c | 49 +++++++++++++++
drivers/pci/pcie/cxl_isolation.c | 102 +++++++++++++++++++++++++++++++
include/cxl/isolation.h | 3 +
3 files changed, 154 insertions(+)
diff --git a/drivers/cxl/core/pci.c b/drivers/cxl/core/pci.c
index dd6c602d57d3..616c337c818d 100644
--- a/drivers/cxl/core/pci.c
+++ b/drivers/cxl/core/pci.c
@@ -1259,3 +1259,52 @@ void cxl_disable_timeout(struct cxl_dport *dport)
dev_dbg(dport->dport_dev, "Disabled CXL.mem transaction timeout\n");
}
+
+static bool timeout_range_supported(u32 cap, u32 val)
+{
+ u32 supported = FIELD_GET(CXL_ISOLATION_CAP_MEM_TIME_MASK, cap);
+
+ if (!supported)
+ return false;
+
+ /* CXL 3.2 8.2.4.24.1 field 3:0 */
+ switch (val) {
+ /* Range A (default) */
+ case 0x0:
+ case 0x1:
+ case 0x2:
+ return (supported & BIT(0));
+ /* Range B */
+ case 0x5:
+ case 0x6:
+ return (supported & BIT(1));
+ /* Range C */
+ case 0x9:
+ case 0xA:
+ return (supported & BIT(2));
+ case 0xD:
+ case 0xE:
+ /* Range D */
+ return (supported & BIT(3));
+ default:
+ return false;
+ }
+}
+
+int cxl_set_timeout_range(struct cxl_dport *dport, u8 val)
+{
+ u32 cap, ctrl;
+
+ cap = readl(dport->regs.isolation + CXL_ISOLATION_CAPABILITY_OFFSET);
+ if (!(cap & CXL_ISOLATION_CAP_MEM_TIME_SUPP))
+ return -ENXIO;
+
+ if (!timeout_range_supported(cap, val))
+ return -EINVAL;
+
+ ctrl = readl(dport->regs.isolation + CXL_ISOLATION_CTRL_OFFSET);
+ ctrl &= FIELD_PREP(CXL_ISOLATION_CTRL_MEM_TIME_MASK, 0);
+ ctrl |= FIELD_PREP(CXL_ISOLATION_CTRL_MEM_TIME_MASK, val);
+ writel(ctrl, dport->regs.isolation + CXL_ISOLATION_CTRL_OFFSET);
+ return 0;
+}
diff --git a/drivers/pci/pcie/cxl_isolation.c b/drivers/pci/pcie/cxl_isolation.c
index 9d2ad14810e8..107201b5843f 100644
--- a/drivers/pci/pcie/cxl_isolation.c
+++ b/drivers/pci/pcie/cxl_isolation.c
@@ -193,9 +193,111 @@ static ssize_t timeout_ctrl_show(struct device *dev,
}
DEVICE_ATTR_RW(timeout_ctrl);
+/* CXL 3.2 8.2.4.24.2 CXL Timeout & Isolation Control Register, field 3:0 */
+const struct timeout_ranges {
+ char *str;
+ u8 val;
+} ranges[] = {
+ { .str = "a", .val = 0x1 },
+ { .str = "A", .val = 0x1 },
+ { .str = "a2", .val = 0x2 },
+ { .str = "A2", .val = 0x2 },
+ { .str = "b", .val = 0x5 },
+ { .str = "B", .val = 0x5 },
+ { .str = "b2", .val = 0x6 },
+ { .str = "B2", .val = 0x6 },
+ { .str = "c", .val = 0x9 },
+ { .str = "C", .val = 0x9 },
+ { .str = "c2", .val = 0xA },
+ { .str = "C2", .val = 0xA },
+ { .str = "d", .val = 0xD },
+ { .str = "D", .val = 0xD },
+ { .str = "d2", .val = 0xE },
+ { .str = "D2", .val = 0xE },
+};
+
+static int timeout_range_str_to_val(const char *str, u8 *val)
+{
+ char val_buf[32] = { 0 };
+ char *start;
+
+ strscpy(val_buf, str, ARRAY_SIZE(val_buf) - 1);
+ start = strim(val_buf);
+ if (!start)
+ return -EINVAL;
+
+ for (int i = 0; i < ARRAY_SIZE(ranges); i++)
+ if (strcmp(start, ranges[i].str) == 0)
+ return ranges[i].val;
+
+ return -EINVAL;
+}
+
+static ssize_t timeout_range_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;
+ u8 val;
+ int rc;
+
+ rc = kstrtou8(buf, 0, &val);
+ if (rc && timeout_range_str_to_val(buf, &val) < 0)
+ return -EINVAL;
+
+ 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;
+
+ rc = cxl_set_timeout_range(*dport, val);
+ put_device(&port->dev);
+ return rc ? rc : n;
+}
+
+static ssize_t timeout_range_show(struct device *dev,
+ struct device_attribute *attr, char * buf)
+{
+ struct pci_dev *pdev = to_pci_dev(dev);
+ struct cxl_port *port;
+ u32 ctrl, val;
+
+ 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);
+
+ val = FIELD_GET(CXL_ISOLATION_CTRL_MEM_TIME_MASK, ctrl);
+ for (int i = 0; i < ARRAY_SIZE(ranges); i++)
+ if (ranges[i].val == val)
+ return sysfs_emit(buf, "%s\n", ranges[i].str);
+
+ return -ENXIO;
+}
+DEVICE_ATTR_RW(timeout_range);
+
static struct attribute *isolation_attrs[] = {
&dev_attr_timeout_ctrl.attr,
&dev_attr_isolation_ctrl.attr,
+ &dev_attr_timeout_range.attr,
NULL,
};
diff --git a/include/cxl/isolation.h b/include/cxl/isolation.h
index 0b6e4f0160a8..f2c4feb5a42b 100644
--- a/include/cxl/isolation.h
+++ b/include/cxl/isolation.h
@@ -30,6 +30,7 @@ void cxl_enable_isolation(struct cxl_dport *dport);
int cxl_disable_isolation(struct cxl_dport *dport);
void cxl_enable_timeout(struct cxl_dport *dport);
void cxl_disable_timeout(struct cxl_dport *dport);
+int cxl_set_timeout_range(struct cxl_dport *dport, u8 val);
struct cxl_port *cxl_find_pcie_rp(struct pci_dev *pdev,
struct cxl_dport **dport);
@@ -39,6 +40,8 @@ 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 int cxl_set_timeout_range(struct cxl_dport *dport, u8 val)
+{ return -ENXIO; }
static inline struct cxl_port *cxl_find_pcie_rp(struct pci_dev *pdev,
struct cxl_dport **dport);
--
2.34.1
next prev 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 ` [PATCH 12/16] PCI: PCIe portdrv: Add cxl_isolation sysfs attributes Ben Cheatham
2025-09-12 15:33 ` Jonathan Cameron
2025-09-17 17:27 ` Cheatham, Benjamin
2025-07-30 21:47 ` Ben Cheatham [this message]
2025-08-04 21:39 ` [PATCH 13/16] cxl/core, PCI: PCIe portdrv: Add CXL timeout range programming 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-14-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.