* [PATCH v4 00/15] cxl: Add CXL feature commands support via fwctl
@ 2025-02-07 23:37 Dave Jiang
2025-02-07 23:37 ` [PATCH v4 01/15] cxl: Enumerate feature commands Dave Jiang
` (14 more replies)
0 siblings, 15 replies; 45+ messages in thread
From: Dave Jiang @ 2025-02-07 23:37 UTC (permalink / raw)
To: linux-cxl
Cc: dan.j.williams, ira.weiny, vishal.l.verma, alison.schofield,
Jonathan.Cameron, dave, jgg, shiju.jose
v4:
- Rebase to FWCTL series v4 based on v6.14-rc1
- Merge patch 1/16 from v3 into cxl/next ahead. (Jonathan)
- Move everything to core/features.c and behind CONFIG_CXL_FEATURES. (Dan)
- Split the registration of features into 2 parts. Do the registration in
PCI probe. One before memdev enumeration to enable kernel feature support,
and one after memdev enumeration to support FWCTL. (Dan)
- Fix incrememt of pointer after copying feature data. (Ming)
- Add check for no immediate change effect and no reset change effects. (Dan, Jonathan)
- Remove IDs and use opcodes directly. (Dan)
- See individual patches for detailed changes from v3.
v3:
- Rearrange code and shift code forward to reduce diffs. (Jonathan)
- Use struct_size() in appropriate locations. (Jonathan)
- Remove usage of __weak and refactor accordingly. (Jason)
- Return NULL for allocation functions. (Jonathan)
- See individual patches for detailed changes from v2.
v2:
- Drop features device and driver. Move features enabling to cxl_memdev. (Dan)
- Drop sysfs attribute of number of features. (Dan)
- Drop moving of include/uapi/linux/cxl_mem.h. (Dan)
- Set get driver info ioctl to return reserved 32bit. Set behavior of issue
ioctl successful as indicating Feature commands supported.
- Set 'Set Feature Size' to 0 for kernel exclusive Features.
- See individual patches for detailed changes from v1.
- Hide FWCTL bits behind CONFIG_CXL_FWCTL. (Dan)
v1:
- Create a CXL features driver to handle all feature command related bits
including FWCTL support. (Dan)
- Tested against CXL CLI unit tests for FWCTL.
- See individual patches for detailed changes from RFC v2.
RFC v2:
- Dropped 1/13 and 2/13 from previous version. Merged upstream already.
- Combined changes from Shiju for "get supported features"
- Addressed comments from Jonathan and Jason
- See specific changes in individual patch revision history
- Added hardware command info to FWCTL
- Added filtering to set feature command
- Added documentation
This series add support for CXL feature commands using the FWCTL framework [1].
The code has been tested with CXL CLI unit tests for FWCTL.
Patches 1-6 are shared with EDAC series [1] and there will be an immutable branch
once accepted post review.
CXL Features support is added behind the CXL mem driver. The 3 mailbox commands
"Get Supported Features", "Get Feature", and "Set Feature" are implemented. The
"Get" commands are under the FWCTL_RPC_CONFIGURATION policy, the "Set" command
checks the policy depending on the set effects of the feature defined by the
device via the Feature set effects field. All mailbox commands for CXL provides
an effects table that describes the effects of a command when performed on the
device. For CXL features, there is also an effects field that describes the
effects a feature set operation has on the device per feature. The security
policy is checked against this feature specific effects field.
The code is based off of v4 of FWCTL series [2] posted by Jason and rebased on top of
v6.14-rc1 plus 1 patch in
cxl/next 43ca2463df9d ("cxl: Refactor user ioctl command path from mds to mailbox").
A kernel branch [3] is provided for convience of testing and review.
[1]: https://lore.kernel.org/linux-cxl/20250106121017.1620-1-shiju.jose@huawei.com/T/#t
[2]: https://lore.kernel.org/linux-cxl/0-v3-960f17f90f17+516-fwctl_jgg@nvidia.com/#r
[3]: https://git.kernel.org/pub/scm/linux/kernel/git/djiang/linux.git/log/?h=cxl/fwctl
---
Dave Jiang (13):
cxl: Enumerate feature commands
cxl: Add Get Supported Features command for kernel usage
cxl/test: Add Get Supported Features mailbox command support
cxl: Setup exclusive CXL features that are reserved for the kernel
cxl: Add FWCTL support to CXL
cxl: Add support for FWCTL get driver information callback
cxl: Move cxl feature command structs to user header
cxl: Add support for fwctl RPC command to enable CXL feature commands
cxl: Add support to handle user feature commands for get feature
cxl: Add support to handle user feature commands for set feature
cxl/test: Add Get Feature support to cxl_test
cxl/test: Add Set Feature support to cxl_test
fwctl/cxl: Add documentation to FWCTL CXL
Shiju Jose (2):
cxl/mbox: Add GET_FEATURE mailbox command
cxl/mbox: Add SET_FEATURE mailbox command
Documentation/userspace-api/fwctl/fwctl-cxl.rst | 137 +++++++++
Documentation/userspace-api/fwctl/index.rst | 1 +
MAINTAINERS | 1 +
drivers/cxl/Kconfig | 11 +
drivers/cxl/core/Makefile | 1 +
drivers/cxl/core/features.c | 736 ++++++++++++++++++++++++++++++++++++++++++++
drivers/cxl/core/mbox.c | 36 ++-
drivers/cxl/cxlmem.h | 7 +
drivers/cxl/pci.c | 8 +
include/cxl/features.h | 121 ++++++++
include/cxl/mailbox.h | 4 +
include/uapi/cxl/features.h | 128 ++++++++
include/uapi/fwctl/cxl.h | 56 ++++
include/uapi/fwctl/fwctl.h | 1 +
tools/testing/cxl/Kbuild | 1 +
tools/testing/cxl/test/mem.c | 184 +++++++++++
16 files changed, 1432 insertions(+), 1 deletion(-)
^ permalink raw reply [flat|nested] 45+ messages in thread
* [PATCH v4 01/15] cxl: Enumerate feature commands
2025-02-07 23:37 [PATCH v4 00/15] cxl: Add CXL feature commands support via fwctl Dave Jiang
@ 2025-02-07 23:37 ` Dave Jiang
2025-02-07 23:47 ` Dan Williams
` (2 more replies)
2025-02-07 23:37 ` [PATCH v4 02/15] cxl: Add Get Supported Features command for kernel usage Dave Jiang
` (13 subsequent siblings)
14 siblings, 3 replies; 45+ messages in thread
From: Dave Jiang @ 2025-02-07 23:37 UTC (permalink / raw)
To: linux-cxl
Cc: dan.j.williams, ira.weiny, vishal.l.verma, alison.schofield,
Jonathan.Cameron, dave, jgg, shiju.jose
Add feature commands enumeration code in order to detect and enumerate
the 3 feature related commands "get supported features", "get feature",
and "set feature". The enumeration will help determine whether the driver
can issue any of the 3 commands to the device.
Signed-off-by: Dave Jiang <dave.jiang@intel.com>
---
v4:
- Move features cap to mbox. (Dan)
- Drop features_cmds bitmap. (Dan)
- Move setup of cxlfs to next patch since there's nothing to do here.
---
drivers/cxl/core/mbox.c | 36 +++++++++++++++++++++++++++++++++++-
drivers/cxl/cxlmem.h | 3 +++
include/cxl/features.h | 13 +++++++++++++
include/cxl/mailbox.h | 3 +++
4 files changed, 54 insertions(+), 1 deletion(-)
create mode 100644 include/cxl/features.h
diff --git a/drivers/cxl/core/mbox.c b/drivers/cxl/core/mbox.c
index 9c1b9e353e3e..5f8f5945cc02 100644
--- a/drivers/cxl/core/mbox.c
+++ b/drivers/cxl/core/mbox.c
@@ -706,6 +706,35 @@ static int cxl_xfer_log(struct cxl_memdev_state *mds, uuid_t *uuid,
return 0;
}
+static int check_features_opcodes(u16 opcode, int *ro_cmds, int *wr_cmds)
+{
+ switch (opcode) {
+ case CXL_MBOX_OP_GET_SUPPORTED_FEATURES:
+ case CXL_MBOX_OP_GET_FEATURE:
+ (*ro_cmds)++;
+ return 1;
+ case CXL_MBOX_OP_SET_FEATURE:
+ (*wr_cmds)++;
+ return 1;
+ default:
+ return 0;
+ }
+}
+
+/* 'Get Supported Features' and 'Get Feature' */
+#define MAX_FEATURES_READ_CMDS 2
+static void set_features_cap(struct cxl_mailbox *cxl_mbox,
+ int ro_cmds, int wr_cmds)
+{
+ /* Setting up Features capability while walking the CEL */
+ if (ro_cmds == MAX_FEATURES_READ_CMDS) {
+ if (wr_cmds)
+ cxl_mbox->feat_cap = CXL_FEATURES_RW;
+ else
+ cxl_mbox->feat_cap = CXL_FEATURES_RO;
+ }
+}
+
/**
* cxl_walk_cel() - Walk through the Command Effects Log.
* @mds: The driver data for the operation
@@ -721,7 +750,7 @@ 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;
+ int i, ro_cmds = 0, wr_cmds = 0;
cel_entry = (struct cxl_cel_entry *) cel;
@@ -733,6 +762,9 @@ static void cxl_walk_cel(struct cxl_memdev_state *mds, size_t size, u8 *cel)
if (cmd) {
set_bit(cmd->info.id, cxl_mbox->enabled_cmds);
enabled++;
+ } else {
+ enabled += check_features_opcodes(opcode, &ro_cmds,
+ &wr_cmds);
}
if (cxl_is_poison_command(opcode)) {
@@ -748,6 +780,8 @@ static void cxl_walk_cel(struct cxl_memdev_state *mds, size_t size, u8 *cel)
dev_dbg(dev, "Opcode 0x%04x %s\n", opcode,
enabled ? "enabled" : "unsupported by driver");
}
+
+ set_features_cap(cxl_mbox, ro_cmds, wr_cmds);
}
static struct cxl_mbox_get_supported_logs *cxl_get_gsl(struct cxl_memdev_state *mds)
diff --git a/drivers/cxl/cxlmem.h b/drivers/cxl/cxlmem.h
index a0a49809cd76..55c55685cb39 100644
--- a/drivers/cxl/cxlmem.h
+++ b/drivers/cxl/cxlmem.h
@@ -490,6 +490,9 @@ enum cxl_opcode {
CXL_MBOX_OP_GET_LOG_CAPS = 0x0402,
CXL_MBOX_OP_CLEAR_LOG = 0x0403,
CXL_MBOX_OP_GET_SUP_LOG_SUBLIST = 0x0405,
+ CXL_MBOX_OP_GET_SUPPORTED_FEATURES = 0x0500,
+ CXL_MBOX_OP_GET_FEATURE = 0x0501,
+ CXL_MBOX_OP_SET_FEATURE = 0x0502,
CXL_MBOX_OP_IDENTIFY = 0x4000,
CXL_MBOX_OP_GET_PARTITION_INFO = 0x4100,
CXL_MBOX_OP_SET_PARTITION_INFO = 0x4101,
diff --git a/include/cxl/features.h b/include/cxl/features.h
new file mode 100644
index 000000000000..357d3acf8429
--- /dev/null
+++ b/include/cxl/features.h
@@ -0,0 +1,13 @@
+/* SPDX-License-Identifier: GPL-2.0-only */
+/* Copyright(c) 2024-2025 Intel Corporation. */
+#ifndef __CXL_FEATURES_H__
+#define __CXL_FEATURES_H__
+
+/* Feature commands capability supported by a device */
+enum cxl_features_capability {
+ CXL_FEATURES_NONE = 0,
+ CXL_FEATURES_RO,
+ CXL_FEATURES_RW,
+};
+
+#endif
diff --git a/include/cxl/mailbox.h b/include/cxl/mailbox.h
index cc894f07a435..c4e99e2e3a9d 100644
--- a/include/cxl/mailbox.h
+++ b/include/cxl/mailbox.h
@@ -3,6 +3,7 @@
#ifndef __CXL_MBOX_H__
#define __CXL_MBOX_H__
#include <linux/rcuwait.h>
+#include <cxl/features.h>
#include <uapi/linux/cxl_mem.h>
/**
@@ -51,6 +52,7 @@ struct cxl_mbox_cmd {
* @mbox_mutex: mutex protects device mailbox and firmware
* @mbox_wait: rcuwait for mailbox
* @mbox_send: @dev specific transport for transmitting mailbox commands
+ * @feat_cap: Features capability
*/
struct cxl_mailbox {
struct device *host;
@@ -60,6 +62,7 @@ struct cxl_mailbox {
struct mutex mbox_mutex; /* lock to protect mailbox context */
struct rcuwait mbox_wait;
int (*mbox_send)(struct cxl_mailbox *cxl_mbox, struct cxl_mbox_cmd *cmd);
+ enum cxl_features_capability feat_cap;
};
int cxl_mailbox_init(struct cxl_mailbox *cxl_mbox, struct device *host);
--
2.48.1
^ permalink raw reply related [flat|nested] 45+ messages in thread
* [PATCH v4 02/15] cxl: Add Get Supported Features command for kernel usage
2025-02-07 23:37 [PATCH v4 00/15] cxl: Add CXL feature commands support via fwctl Dave Jiang
2025-02-07 23:37 ` [PATCH v4 01/15] cxl: Enumerate feature commands Dave Jiang
@ 2025-02-07 23:37 ` Dave Jiang
2025-02-07 23:56 ` Dan Williams
2025-02-08 6:13 ` Li Ming
2025-02-07 23:37 ` [PATCH v4 03/15] cxl/test: Add Get Supported Features mailbox command support Dave Jiang
` (12 subsequent siblings)
14 siblings, 2 replies; 45+ messages in thread
From: Dave Jiang @ 2025-02-07 23:37 UTC (permalink / raw)
To: linux-cxl
Cc: dan.j.williams, ira.weiny, vishal.l.verma, alison.schofield,
Jonathan.Cameron, dave, jgg, shiju.jose
CXL spec r3.2 8.2.9.6.1 Get Supported Features (Opcode 0500h)
The command retrieve the list of supported device-specific features
(identified by UUID) and general information about each Feature.
The driver will retrieve the Feature entries in order to make checks and
provide information for the Get Feature and Set Feature command. One of
the main piece of information retrieved are the effects a Set Feature
command would have for a particular feature. The retrieved Feature
entries are stored in the cxl_mailbox context.
The setup of Features is initiated via devm_cxl_setup_features() during the
pci probe function before the cxl_memdev is enumerated.
Reviewed-by: Jonathan Cameron <Jonathan.Cameron@huawei.com>
Signed-off-by: Dave Jiang <dave.jiang@intel.com>
---
v4:
- Add allocation and setup of the CXL features state.
- Fail the allocation if there are no features discovere. (Dan)
- Increment by number of entries copied. (Ming)
---
drivers/cxl/Kconfig | 11 +++
drivers/cxl/core/Makefile | 1 +
drivers/cxl/core/features.c | 179 +++++++++++++++++++++++++++++++++++
drivers/cxl/cxlmem.h | 4 +
drivers/cxl/pci.c | 4 +
include/cxl/features.h | 86 +++++++++++++++++
tools/testing/cxl/Kbuild | 1 +
tools/testing/cxl/test/mem.c | 4 +
8 files changed, 290 insertions(+)
create mode 100644 drivers/cxl/core/features.c
diff --git a/drivers/cxl/Kconfig b/drivers/cxl/Kconfig
index 876469e23f7a..ad2e796e4ac6 100644
--- a/drivers/cxl/Kconfig
+++ b/drivers/cxl/Kconfig
@@ -102,6 +102,17 @@ config CXL_MEM
If unsure say 'm'.
+config CXL_FEATURES
+ bool "CXL: Features"
+ depends on CXL_PCI
+ help
+ Enable support for CXL Features. A CXL device that includes a mailbox
+ supports commands that allows listing, getting, and setting of
+ optionally defined features such as memory sparing or post package
+ sparing. Vendors may define custom features for the device.
+
+ If unsure say 'n'
+
config CXL_PORT
default CXL_BUS
tristate
diff --git a/drivers/cxl/core/Makefile b/drivers/cxl/core/Makefile
index 9259bcc6773c..b0bfbd9eac9b 100644
--- a/drivers/cxl/core/Makefile
+++ b/drivers/cxl/core/Makefile
@@ -16,3 +16,4 @@ cxl_core-y += pmu.o
cxl_core-y += cdat.o
cxl_core-$(CONFIG_TRACING) += trace.o
cxl_core-$(CONFIG_CXL_REGION) += region.o
+cxl_core-$(CONFIG_CXL_FEATURES) += features.o
diff --git a/drivers/cxl/core/features.c b/drivers/cxl/core/features.c
new file mode 100644
index 000000000000..77a0bf3a4916
--- /dev/null
+++ b/drivers/cxl/core/features.c
@@ -0,0 +1,179 @@
+// SPDX-License-Identifier: GPL-2.0-only
+/* Copyright(c) 2024-2025 Intel Corporation. All rights reserved. */
+#include <linux/device.h>
+#include <cxl/mailbox.h>
+#include <cxl/features.h>
+#include "cxl.h"
+#include "cxlmem.h"
+
+inline struct cxl_features_state *to_cxlfs(struct cxl_dev_state *cxlds)
+{
+ return cxlds->cxlfs;
+}
+EXPORT_SYMBOL_NS_GPL(to_cxlfs, "CXL");
+
+static int cxl_get_supported_features_count(struct cxl_mailbox *cxl_mbox)
+{
+ struct cxl_mbox_get_sup_feats_out mbox_out;
+ struct cxl_mbox_get_sup_feats_in mbox_in;
+ struct cxl_mbox_cmd mbox_cmd;
+ int rc;
+
+ memset(&mbox_in, 0, sizeof(mbox_in));
+ mbox_in.count = cpu_to_le32(sizeof(mbox_out));
+ memset(&mbox_out, 0, sizeof(mbox_out));
+ mbox_cmd = (struct cxl_mbox_cmd) {
+ .opcode = CXL_MBOX_OP_GET_SUPPORTED_FEATURES,
+ .size_in = sizeof(mbox_in),
+ .payload_in = &mbox_in,
+ .size_out = sizeof(mbox_out),
+ .payload_out = &mbox_out,
+ .min_out = sizeof(mbox_out),
+ };
+ rc = cxl_internal_send_cmd(cxl_mbox, &mbox_cmd);
+ if (rc < 0)
+ return rc;
+
+ return le16_to_cpu(mbox_out.supported_feats);
+}
+
+static struct cxl_feat_entries *
+get_supported_features(struct cxl_features_state *cxlfs)
+{
+ int remain_feats, max_size, max_feats, start, rc, hdr_size;
+ struct cxl_mailbox *cxl_mbox = &cxlfs->cxlds->cxl_mbox;
+ int feat_size = sizeof(struct cxl_feat_entry);
+ struct cxl_mbox_get_sup_feats_in mbox_in;
+ struct cxl_feat_entry *entry;
+ struct cxl_mbox_cmd mbox_cmd;
+ int count;
+
+ count = cxl_get_supported_features_count(cxl_mbox);
+ if (count <= 0)
+ return NULL;
+
+ struct cxl_feat_entries *entries __free(kvfree) =
+ kvmalloc(struct_size(entries, ent, count), GFP_KERNEL);
+ if (!entries)
+ return NULL;
+
+ struct cxl_mbox_get_sup_feats_out *mbox_out __free(kvfree) =
+ kvmalloc(cxl_mbox->payload_size, GFP_KERNEL);
+ if (!mbox_out)
+ return NULL;
+
+ hdr_size = struct_size(mbox_out, ents, 0);
+ max_size = cxl_mbox->payload_size - hdr_size;
+ /* max feat entries that can fit in mailbox max payload size */
+ max_feats = max_size / feat_size;
+ entry = entries->ent;
+
+ start = 0;
+ remain_feats = count;
+ do {
+ int retrieved, alloc_size, copy_feats;
+ int num_entries;
+
+ if (remain_feats > max_feats) {
+ alloc_size = struct_size(mbox_out, ents, max_feats);
+ remain_feats = remain_feats - max_feats;
+ copy_feats = max_feats;
+ } else {
+ alloc_size = struct_size(mbox_out, ents, remain_feats);
+ copy_feats = remain_feats;
+ remain_feats = 0;
+ }
+
+ memset(&mbox_in, 0, sizeof(mbox_in));
+ mbox_in.count = cpu_to_le32(alloc_size);
+ mbox_in.start_idx = cpu_to_le16(start);
+ memset(mbox_out, 0, alloc_size);
+ mbox_cmd = (struct cxl_mbox_cmd) {
+ .opcode = CXL_MBOX_OP_GET_SUPPORTED_FEATURES,
+ .size_in = sizeof(mbox_in),
+ .payload_in = &mbox_in,
+ .size_out = alloc_size,
+ .payload_out = mbox_out,
+ .min_out = hdr_size,
+ };
+ rc = cxl_internal_send_cmd(cxl_mbox, &mbox_cmd);
+ if (rc < 0)
+ return ERR_PTR(rc);
+
+ if (mbox_cmd.size_out <= hdr_size)
+ return NULL;
+
+ /*
+ * Make sure retrieved out buffer is multiple of feature
+ * entries.
+ */
+ retrieved = mbox_cmd.size_out - hdr_size;
+ if (retrieved % feat_size)
+ return NULL;
+
+ num_entries = le16_to_cpu(mbox_out->num_entries);
+ /*
+ * If the reported output entries * defined entry size !=
+ * retrieved output bytes, then the output package is incorrect.
+ */
+ if (num_entries * feat_size != retrieved)
+ return NULL;
+
+ memcpy(entry, mbox_out->ents, retrieved);
+ entry += num_entries;
+ /*
+ * If the number of output entries is less than expected, add the
+ * remaining entries to the next batch.
+ */
+ remain_feats += copy_feats - num_entries;
+ start += num_entries;
+ } while (remain_feats);
+
+ entries->num_features = count;
+
+ return no_free_ptr(entries);
+}
+
+static void free_cxlfs(void *_cxlfs)
+{
+ struct cxl_features_state *cxlfs = _cxlfs;
+ struct cxl_dev_state *cxlds = cxlfs->cxlds;
+
+ cxlds->cxlfs = NULL;
+ kvfree(cxlfs->entries);
+ kfree(cxlfs);
+}
+
+/**
+ * devm_cxl_setup_features() - Allocate and initialize features context
+ * @cxlds: CXL device context
+ *
+ * Return 0 on success or -errno on failure.
+ */
+int devm_cxl_setup_features(struct cxl_dev_state *cxlds)
+{
+ struct cxl_mailbox *cxl_mbox = &cxlds->cxl_mbox;
+ int rc;
+
+ if (cxl_mbox->feat_cap < CXL_FEATURES_RO)
+ return -ENODEV;
+
+ struct cxl_features_state *cxlfs __free(kfree) =
+ kzalloc(sizeof(*cxlfs), GFP_KERNEL);
+ if (!cxlfs)
+ return -ENOMEM;
+
+ cxlfs->cxlds = cxlds;
+
+ cxlfs->entries = get_supported_features(cxlfs);
+ if (!cxlfs->entries)
+ return -ENOMEM;
+
+ cxlds->cxlfs = cxlfs;
+ rc = devm_add_action_or_reset(cxlds->dev, free_cxlfs, no_free_ptr(cxlfs));
+ if (rc)
+ return rc;
+
+ return 0;
+}
+EXPORT_SYMBOL_NS_GPL(devm_cxl_setup_features, "CXL");
diff --git a/drivers/cxl/cxlmem.h b/drivers/cxl/cxlmem.h
index 55c55685cb39..0dc2682eb379 100644
--- a/drivers/cxl/cxlmem.h
+++ b/drivers/cxl/cxlmem.h
@@ -392,6 +392,7 @@ struct cxl_dpa_perf {
* @serial: PCIe Device Serial Number
* @type: Generic Memory Class device or Vendor Specific Memory device
* @cxl_mbox: CXL mailbox context
+ * @cxl_features: CXL features context
*/
struct cxl_dev_state {
struct device *dev;
@@ -407,6 +408,9 @@ struct cxl_dev_state {
u64 serial;
enum cxl_devtype type;
struct cxl_mailbox cxl_mbox;
+#ifdef CONFIG_CXL_FEATURES
+ struct cxl_features_state *cxlfs;
+#endif
};
static inline struct cxl_dev_state *mbox_to_cxlds(struct cxl_mailbox *cxl_mbox)
diff --git a/drivers/cxl/pci.c b/drivers/cxl/pci.c
index a96e54c6259e..3e666ec51580 100644
--- a/drivers/cxl/pci.c
+++ b/drivers/cxl/pci.c
@@ -997,6 +997,10 @@ static int cxl_pci_probe(struct pci_dev *pdev, const struct pci_device_id *id)
if (rc)
return rc;
+ rc = devm_cxl_setup_features(cxlds);
+ if (rc)
+ dev_dbg(&pdev->dev, "No CXL Features discovered\n");
+
cxlmd = devm_cxl_add_memdev(&pdev->dev, cxlds);
if (IS_ERR(cxlmd))
return PTR_ERR(cxlmd);
diff --git a/include/cxl/features.h b/include/cxl/features.h
index 357d3acf8429..e8861e690701 100644
--- a/include/cxl/features.h
+++ b/include/cxl/features.h
@@ -3,6 +3,8 @@
#ifndef __CXL_FEATURES_H__
#define __CXL_FEATURES_H__
+#include <linux/uuid.h>
+
/* Feature commands capability supported by a device */
enum cxl_features_capability {
CXL_FEATURES_NONE = 0,
@@ -10,4 +12,88 @@ enum cxl_features_capability {
CXL_FEATURES_RW,
};
+/* Get Supported Features (0x500h) CXL r3.2 8.2.9.6.1 */
+struct cxl_mbox_get_sup_feats_in {
+ __le32 count;
+ __le16 start_idx;
+ u8 reserved[2];
+} __packed;
+
+/* CXL spec r3.2 Table 8-87 command effects */
+#define CXL_CMD_CONFIG_CHANGE_COLD_RESET BIT(0)
+#define CXL_CMD_CONFIG_CHANGE_IMMEDIATE BIT(1)
+#define CXL_CMD_DATA_CHANGE_IMMEDIATE BIT(2)
+#define CXL_CMD_POLICY_CHANGE_IMMEDIATE BIT(3)
+#define CXL_CMD_LOG_CHANGE_IMMEDIATE BIT(4)
+#define CXL_CMD_SECURITY_STATE_CHANGE BIT(5)
+#define CXL_CMD_BACKGROUND BIT(6)
+#define CXL_CMD_BGCMD_ABORT_SUPPORTED BIT(7)
+#define CXL_CMD_EFFECTS_VALID BIT(9)
+#define CXL_CMD_CONFIG_CHANGE_CONV_RESET BIT(10)
+#define CXL_CMD_CONFIG_CHANGE_CXL_RESET BIT(11)
+
+/*
+ * CXL spec r3.2 Table 8-109
+ * Get Supported Features Supported Feature Entry
+ */
+struct cxl_feat_entry {
+ uuid_t uuid;
+ __le16 id;
+ __le16 get_feat_size;
+ __le16 set_feat_size;
+ __le32 flags;
+ u8 get_feat_ver;
+ u8 set_feat_ver;
+ __le16 effects;
+ u8 reserved[18];
+} __packed;
+
+/* @flags field for 'struct cxl_feat_entry' */
+#define CXL_FEATURE_F_CHANGEABLE BIT(0)
+#define CXL_FEATURE_F_PERSIST_FW_UPDATE BIT(4)
+#define CXL_FEATURE_F_DEFAULT_SEL BIT(5)
+#define CXL_FEATURE_F_SAVED_SEL BIT(6)
+
+/*
+ * CXL spec r3.2 Table 8-108
+ * Get supported Features Output Payload
+ */
+struct cxl_mbox_get_sup_feats_out {
+ __le16 num_entries;
+ __le16 supported_feats;
+ u8 reserved[4];
+ struct cxl_feat_entry ents[] __counted_by_le(num_entries);
+} __packed;
+
+/**
+ * struct cxl_features_state - The Features state for the device
+ * @cxlds: Pointer to CXL device state
+ * @cap: Feature commands capability
+ * @entries: CXl feature entry context
+ * @num_features: total Features supported by the device
+ * @ent: Flex array of Feature detail entries from the device
+ */
+struct cxl_features_state {
+ struct cxl_dev_state *cxlds;
+ struct cxl_feat_entries {
+ int num_features;
+ struct cxl_feat_entry ent[] __counted_by(num_features);
+ } *entries;
+};
+
+#ifdef CONFIG_CXL_FEATURES
+inline struct cxl_features_state *to_cxlfs(struct cxl_dev_state *cxlds);
+int devm_cxl_setup_features(struct cxl_dev_state *cxlds);
+#else
+static inline struct cxl_features_state *to_cxlfs(struct cxl_dev_state *cxlds)
+{
+ return NULL;
+}
+
+static inline int devm_cxl_setup_features(struct cxl_dev_state *cxlds)
+{
+ return -EOPNOTSUPP;
+}
+#endif
+
#endif
diff --git a/tools/testing/cxl/Kbuild b/tools/testing/cxl/Kbuild
index b1256fee3567..0a6572ab6f37 100644
--- a/tools/testing/cxl/Kbuild
+++ b/tools/testing/cxl/Kbuild
@@ -63,6 +63,7 @@ cxl_core-y += $(CXL_CORE_SRC)/pmu.o
cxl_core-y += $(CXL_CORE_SRC)/cdat.o
cxl_core-$(CONFIG_TRACING) += $(CXL_CORE_SRC)/trace.o
cxl_core-$(CONFIG_CXL_REGION) += $(CXL_CORE_SRC)/region.o
+cxl_core-$(CONFIG_CXL_FEATURES) += $(CXL_CORE_SRC)/features.o
cxl_core-y += config_check.o
cxl_core-y += cxl_core_test.o
cxl_core-y += cxl_core_exports.o
diff --git a/tools/testing/cxl/test/mem.c b/tools/testing/cxl/test/mem.c
index 8d731bd63988..e9494cd446ef 100644
--- a/tools/testing/cxl/test/mem.c
+++ b/tools/testing/cxl/test/mem.c
@@ -1558,6 +1558,10 @@ static int cxl_mock_mem_probe(struct platform_device *pdev)
if (rc)
return rc;
+ rc = devm_cxl_setup_features(cxlds);
+ if (rc)
+ dev_dbg(dev, "No CXL Features discovered\n");
+
cxl_mock_add_event_logs(&mdata->mes);
cxlmd = devm_cxl_add_memdev(&pdev->dev, cxlds);
--
2.48.1
^ permalink raw reply related [flat|nested] 45+ messages in thread
* [PATCH v4 03/15] cxl/test: Add Get Supported Features mailbox command support
2025-02-07 23:37 [PATCH v4 00/15] cxl: Add CXL feature commands support via fwctl Dave Jiang
2025-02-07 23:37 ` [PATCH v4 01/15] cxl: Enumerate feature commands Dave Jiang
2025-02-07 23:37 ` [PATCH v4 02/15] cxl: Add Get Supported Features command for kernel usage Dave Jiang
@ 2025-02-07 23:37 ` Dave Jiang
2025-02-07 23:37 ` [PATCH v4 04/15] cxl/mbox: Add GET_FEATURE mailbox command Dave Jiang
` (11 subsequent siblings)
14 siblings, 0 replies; 45+ messages in thread
From: Dave Jiang @ 2025-02-07 23:37 UTC (permalink / raw)
To: linux-cxl
Cc: dan.j.williams, ira.weiny, vishal.l.verma, alison.schofield,
Jonathan.Cameron, dave, jgg, shiju.jose, Li Ming
Add cxl-test emulation of Get Supported Features mailbox command.
Currently only adding a test feature with feature identifier of
all f's for testing.
Reviewed-by: Jonathan Cameron <Jonathan.Cameron@huawei.com>
Acked-by: Dan Williams <dan.j.williams@intel.com>
Reviewed-by: Li Ming <ming.li@zohomail.com>
Signed-off-by: Dave Jiang <dave.jiang@intel.com>
---
tools/testing/cxl/test/mem.c | 70 ++++++++++++++++++++++++++++++++++++
1 file changed, 70 insertions(+)
diff --git a/tools/testing/cxl/test/mem.c b/tools/testing/cxl/test/mem.c
index e9494cd446ef..4809a90ff9b6 100644
--- a/tools/testing/cxl/test/mem.c
+++ b/tools/testing/cxl/test/mem.c
@@ -44,6 +44,10 @@ static struct cxl_cel_entry mock_cel[] = {
.opcode = cpu_to_le16(CXL_MBOX_OP_GET_SUPPORTED_LOGS),
.effect = CXL_CMD_EFFECT_NONE,
},
+ {
+ .opcode = cpu_to_le16(CXL_MBOX_OP_GET_SUPPORTED_FEATURES),
+ .effect = CXL_CMD_EFFECT_NONE,
+ },
{
.opcode = cpu_to_le16(CXL_MBOX_OP_IDENTIFY),
.effect = CXL_CMD_EFFECT_NONE,
@@ -1354,6 +1358,69 @@ static int mock_activate_fw(struct cxl_mockmem_data *mdata,
return -EINVAL;
}
+#define CXL_VENDOR_FEATURE_TEST \
+ UUID_INIT(0xffffffff, 0xffff, 0xffff, 0xff, 0xff, 0xff, 0xff, 0xff, \
+ 0xff, 0xff, 0xff)
+
+static void fill_feature_vendor_test(struct cxl_feat_entry *feat)
+{
+ feat->uuid = CXL_VENDOR_FEATURE_TEST;
+ feat->id = 0;
+ feat->get_feat_size = cpu_to_le16(0x4);
+ feat->set_feat_size = cpu_to_le16(0x4);
+ feat->flags = cpu_to_le32(CXL_FEATURE_F_CHANGEABLE |
+ CXL_FEATURE_F_DEFAULT_SEL |
+ CXL_FEATURE_F_SAVED_SEL);
+ feat->get_feat_ver = 1;
+ feat->set_feat_ver = 1;
+ feat->effects = cpu_to_le16(CXL_CMD_CONFIG_CHANGE_COLD_RESET |
+ CXL_CMD_EFFECTS_VALID);
+}
+
+#define MAX_CXL_TEST_FEATS 1
+
+static int mock_get_supported_features(struct cxl_mockmem_data *mdata,
+ struct cxl_mbox_cmd *cmd)
+{
+ struct cxl_mbox_get_sup_feats_in *in = cmd->payload_in;
+ struct cxl_mbox_get_sup_feats_out *out = cmd->payload_out;
+ struct cxl_feat_entry *feat;
+ u16 start_idx, count;
+
+ if (cmd->size_out < sizeof(*out)) {
+ cmd->return_code = CXL_MBOX_CMD_RC_PAYLOADLEN;
+ return -EINVAL;
+ }
+
+ /*
+ * Current emulation only supports 1 feature
+ */
+ start_idx = le16_to_cpu(in->start_idx);
+ if (start_idx != 0) {
+ cmd->return_code = CXL_MBOX_CMD_RC_INPUT;
+ return -EINVAL;
+ }
+
+ count = le16_to_cpu(in->count);
+ if (count < struct_size(out, ents, 0)) {
+ cmd->return_code = CXL_MBOX_CMD_RC_PAYLOADLEN;
+ return -EINVAL;
+ }
+
+ out->supported_feats = cpu_to_le16(MAX_CXL_TEST_FEATS);
+ cmd->return_code = 0;
+ if (count < struct_size(out, ents, MAX_CXL_TEST_FEATS)) {
+ out->num_entries = 0;
+ return 0;
+ }
+
+ out->num_entries = cpu_to_le16(MAX_CXL_TEST_FEATS);
+ feat = out->ents;
+ fill_feature_vendor_test(feat);
+
+ return 0;
+}
+
static int cxl_mock_mbox_send(struct cxl_mailbox *cxl_mbox,
struct cxl_mbox_cmd *cmd)
{
@@ -1439,6 +1506,9 @@ static int cxl_mock_mbox_send(struct cxl_mailbox *cxl_mbox,
case CXL_MBOX_OP_ACTIVATE_FW:
rc = mock_activate_fw(mdata, cmd);
break;
+ case CXL_MBOX_OP_GET_SUPPORTED_FEATURES:
+ rc = mock_get_supported_features(mdata, cmd);
+ break;
default:
break;
}
--
2.48.1
^ permalink raw reply related [flat|nested] 45+ messages in thread
* [PATCH v4 04/15] cxl/mbox: Add GET_FEATURE mailbox command
2025-02-07 23:37 [PATCH v4 00/15] cxl: Add CXL feature commands support via fwctl Dave Jiang
` (2 preceding siblings ...)
2025-02-07 23:37 ` [PATCH v4 03/15] cxl/test: Add Get Supported Features mailbox command support Dave Jiang
@ 2025-02-07 23:37 ` Dave Jiang
2025-02-08 0:12 ` Dan Williams
2025-02-07 23:37 ` [PATCH v4 05/15] cxl/mbox: Add SET_FEATURE " Dave Jiang
` (10 subsequent siblings)
14 siblings, 1 reply; 45+ messages in thread
From: Dave Jiang @ 2025-02-07 23:37 UTC (permalink / raw)
To: linux-cxl
Cc: dan.j.williams, ira.weiny, vishal.l.verma, alison.schofield,
Jonathan.Cameron, dave, jgg, shiju.jose, Li Ming
From: Shiju Jose <shiju.jose@huawei.com>
Add support for GET_FEATURE mailbox command.
CXL spec r3.2 section 8.2.9.6 describes optional device specific features.
The settings of a feature can be retrieved using Get Feature command.
CXL spec r3.2 section 8.2.9.6.2 describes Get Feature command.
Reviewed-by: Jonathan Cameron <Jonathan.Cameron@huawei.com>
Reviewed-by: Li Ming <ming.li@zohomail.com>
Signed-off-by: Shiju Jose <shiju.jose@huawei.com>
Signed-off-by: Dave Jiang <dave.jiang@intel.com>
---
drivers/cxl/core/features.c | 50 +++++++++++++++++++++++++++++++++++++
include/cxl/features.h | 37 +++++++++++++++++++++++++++
2 files changed, 87 insertions(+)
diff --git a/drivers/cxl/core/features.c b/drivers/cxl/core/features.c
index 77a0bf3a4916..262e4b1cb7fc 100644
--- a/drivers/cxl/core/features.c
+++ b/drivers/cxl/core/features.c
@@ -177,3 +177,53 @@ int devm_cxl_setup_features(struct cxl_dev_state *cxlds)
return 0;
}
EXPORT_SYMBOL_NS_GPL(devm_cxl_setup_features, "CXL");
+
+size_t cxl_get_feature(struct cxl_mailbox *cxl_mbox, const uuid_t *feat_uuid,
+ enum cxl_get_feat_selection selection,
+ void *feat_out, size_t feat_out_size, u16 offset,
+ u16 *return_code)
+{
+ size_t data_to_rd_size, size_out;
+ struct cxl_mbox_get_feat_in pi;
+ struct cxl_mbox_cmd mbox_cmd;
+ size_t data_rcvd_size = 0;
+ int rc;
+
+ if (return_code)
+ *return_code = CXL_MBOX_CMD_RC_INPUT;
+
+ if (!feat_out || !feat_out_size)
+ return 0;
+
+ size_out = min(feat_out_size, cxl_mbox->payload_size);
+ uuid_copy(&pi.uuid, feat_uuid);
+ pi.selection = selection;
+ do {
+ data_to_rd_size = min(feat_out_size - data_rcvd_size,
+ cxl_mbox->payload_size);
+ pi.offset = cpu_to_le16(offset + data_rcvd_size);
+ pi.count = cpu_to_le16(data_to_rd_size);
+
+ mbox_cmd = (struct cxl_mbox_cmd) {
+ .opcode = CXL_MBOX_OP_GET_FEATURE,
+ .size_in = sizeof(pi),
+ .payload_in = &pi,
+ .size_out = size_out,
+ .payload_out = feat_out + data_rcvd_size,
+ .min_out = data_to_rd_size,
+ };
+ rc = cxl_internal_send_cmd(cxl_mbox, &mbox_cmd);
+ if (rc < 0 || !mbox_cmd.size_out) {
+ if (return_code)
+ *return_code = mbox_cmd.return_code;
+ return 0;
+ }
+ data_rcvd_size += mbox_cmd.size_out;
+ } while (data_rcvd_size < feat_out_size);
+
+ if (return_code)
+ *return_code = CXL_MBOX_CMD_RC_SUCCESS;
+
+ return data_rcvd_size;
+}
+EXPORT_SYMBOL_NS_GPL(cxl_get_feature, "CXL");
diff --git a/include/cxl/features.h b/include/cxl/features.h
index e8861e690701..85036604fdba 100644
--- a/include/cxl/features.h
+++ b/include/cxl/features.h
@@ -65,6 +65,29 @@ struct cxl_mbox_get_sup_feats_out {
struct cxl_feat_entry ents[] __counted_by_le(num_entries);
} __packed;
+/*
+ * Get Feature CXL spec r3.2 Spec 8.2.9.6.2
+ */
+
+/*
+ * Get Feature input payload
+ * CXL spec r3.2 section 8.2.9.6.2 Table 8-99
+ */
+struct cxl_mbox_get_feat_in {
+ uuid_t uuid;
+ __le16 offset;
+ __le16 count;
+ u8 selection;
+} __packed;
+
+/* Selection field for 'struct cxl_mbox_get_feat_in' */
+enum cxl_get_feat_selection {
+ CXL_GET_FEAT_SEL_CURRENT_VALUE,
+ CXL_GET_FEAT_SEL_DEFAULT_VALUE,
+ CXL_GET_FEAT_SEL_SAVED_VALUE,
+ CXL_GET_FEAT_SEL_MAX
+};
+
/**
* struct cxl_features_state - The Features state for the device
* @cxlds: Pointer to CXL device state
@@ -81,9 +104,14 @@ struct cxl_features_state {
} *entries;
};
+struct cxl_mailbox;
#ifdef CONFIG_CXL_FEATURES
inline struct cxl_features_state *to_cxlfs(struct cxl_dev_state *cxlds);
int devm_cxl_setup_features(struct cxl_dev_state *cxlds);
+size_t cxl_get_feature(struct cxl_mailbox *cxl_mbox, const uuid_t *feat_uuid,
+ enum cxl_get_feat_selection selection,
+ void *feat_out, size_t feat_out_size, u16 offset,
+ u16 *return_code);
#else
static inline struct cxl_features_state *to_cxlfs(struct cxl_dev_state *cxlds)
{
@@ -94,6 +122,15 @@ static inline int devm_cxl_setup_features(struct cxl_dev_state *cxlds)
{
return -EOPNOTSUPP;
}
+
+static inline size_t cxl_get_feature(struct cxl_mailbox *cxl_mbox,
+ const uuid_t *feat_uuid,
+ enum cxl_get_feat_selection selection,
+ void *feat_out, size_t feat_out_size,
+ u16 offset, u16 *return_code)
+{
+ return 0;
+}
#endif
#endif
--
2.48.1
^ permalink raw reply related [flat|nested] 45+ messages in thread
* [PATCH v4 05/15] cxl/mbox: Add SET_FEATURE mailbox command
2025-02-07 23:37 [PATCH v4 00/15] cxl: Add CXL feature commands support via fwctl Dave Jiang
` (3 preceding siblings ...)
2025-02-07 23:37 ` [PATCH v4 04/15] cxl/mbox: Add GET_FEATURE mailbox command Dave Jiang
@ 2025-02-07 23:37 ` Dave Jiang
2025-02-08 0:21 ` Dan Williams
2025-02-08 6:17 ` Li Ming
2025-02-07 23:37 ` [PATCH v4 06/15] cxl: Setup exclusive CXL features that are reserved for the kernel Dave Jiang
` (9 subsequent siblings)
14 siblings, 2 replies; 45+ messages in thread
From: Dave Jiang @ 2025-02-07 23:37 UTC (permalink / raw)
To: linux-cxl
Cc: dan.j.williams, ira.weiny, vishal.l.verma, alison.schofield,
Jonathan.Cameron, dave, jgg, shiju.jose
From: Shiju Jose <shiju.jose@huawei.com>
Add support for SET_FEATURE mailbox command.
CXL spec r3.2 section 8.2.9.6 describes optional device specific features.
CXL devices supports features with changeable attributes.
The settings of a feature can be optionally modified using Set Feature
command.
CXL spec r3.2 section 8.2.9.6.3 describes Set Feature command.
Reviewed-by: Jonathan Cameron <Jonathan.Cameron@huawei.com>
Signed-off-by: Shiju Jose <shiju.jose@huawei.com>
Signed-off-by: Dave Jiang <dave.jiang@intel.com>
---
drivers/cxl/core/features.c | 81 +++++++++++++++++++++++++++++++++++++
include/cxl/features.h | 42 +++++++++++++++++++
2 files changed, 123 insertions(+)
diff --git a/drivers/cxl/core/features.c b/drivers/cxl/core/features.c
index 262e4b1cb7fc..d337224158fa 100644
--- a/drivers/cxl/core/features.c
+++ b/drivers/cxl/core/features.c
@@ -227,3 +227,84 @@ size_t cxl_get_feature(struct cxl_mailbox *cxl_mbox, const uuid_t *feat_uuid,
return data_rcvd_size;
}
EXPORT_SYMBOL_NS_GPL(cxl_get_feature, "CXL");
+
+/*
+ * FEAT_DATA_MIN_PAYLOAD_SIZE - min extra number of bytes should be
+ * available in the mailbox for storing the actual feature data so that
+ * the feature data transfer would work as expected.
+ */
+#define FEAT_DATA_MIN_PAYLOAD_SIZE 10
+int cxl_set_feature(struct cxl_mailbox *cxl_mbox,
+ const uuid_t *feat_uuid, u8 feat_version,
+ void *feat_data, size_t feat_data_size,
+ u32 feat_flag, u16 offset, u16 *return_code)
+{
+ struct cxl_memdev_set_feat_pi {
+ struct cxl_mbox_set_feat_hdr hdr;
+ u8 feat_data[];
+ } __packed;
+ size_t data_in_size, data_sent_size = 0;
+ struct cxl_mbox_cmd mbox_cmd;
+ size_t hdr_size;
+ int rc = 0;
+
+ if (return_code)
+ *return_code = CXL_MBOX_CMD_RC_INPUT;
+
+ struct cxl_memdev_set_feat_pi *pi __free(kfree) =
+ kzalloc(cxl_mbox->payload_size, GFP_KERNEL);
+ uuid_copy(&pi->hdr.uuid, feat_uuid);
+ pi->hdr.version = feat_version;
+ feat_flag &= ~CXL_SET_FEAT_FLAG_DATA_TRANSFER_MASK;
+ feat_flag |= CXL_SET_FEAT_FLAG_DATA_SAVED_ACROSS_RESET;
+ hdr_size = sizeof(pi->hdr);
+ /*
+ * Check minimum mbox payload size is available for
+ * the feature data transfer.
+ */
+ if (hdr_size + FEAT_DATA_MIN_PAYLOAD_SIZE > cxl_mbox->payload_size)
+ return -ENOMEM;
+
+ if (hdr_size + feat_data_size <= cxl_mbox->payload_size) {
+ pi->hdr.flags = cpu_to_le32(feat_flag |
+ CXL_SET_FEAT_FLAG_FULL_DATA_TRANSFER);
+ data_in_size = feat_data_size;
+ } else {
+ pi->hdr.flags = cpu_to_le32(feat_flag |
+ CXL_SET_FEAT_FLAG_INITIATE_DATA_TRANSFER);
+ data_in_size = cxl_mbox->payload_size - hdr_size;
+ }
+
+ do {
+ pi->hdr.offset = cpu_to_le16(offset + data_sent_size);
+ memcpy(pi->feat_data, feat_data + data_sent_size, data_in_size);
+ mbox_cmd = (struct cxl_mbox_cmd) {
+ .opcode = CXL_MBOX_OP_SET_FEATURE,
+ .size_in = hdr_size + data_in_size,
+ .payload_in = pi,
+ };
+ rc = cxl_internal_send_cmd(cxl_mbox, &mbox_cmd);
+ if (rc < 0) {
+ if (return_code)
+ *return_code = mbox_cmd.return_code;
+ return rc;
+ }
+
+ data_sent_size += data_in_size;
+ if (data_sent_size >= feat_data_size) {
+ if (return_code)
+ *return_code = CXL_MBOX_CMD_RC_SUCCESS;
+ return 0;
+ }
+
+ if ((feat_data_size - data_sent_size) <= (cxl_mbox->payload_size - hdr_size)) {
+ data_in_size = feat_data_size - data_sent_size;
+ pi->hdr.flags = cpu_to_le32(feat_flag |
+ CXL_SET_FEAT_FLAG_FINISH_DATA_TRANSFER);
+ } else {
+ pi->hdr.flags = cpu_to_le32(feat_flag |
+ CXL_SET_FEAT_FLAG_CONTINUE_DATA_TRANSFER);
+ }
+ } while (true);
+}
+EXPORT_SYMBOL_NS_GPL(cxl_set_feature, "CXL");
diff --git a/include/cxl/features.h b/include/cxl/features.h
index 85036604fdba..4e3527ba8a1d 100644
--- a/include/cxl/features.h
+++ b/include/cxl/features.h
@@ -88,6 +88,36 @@ enum cxl_get_feat_selection {
CXL_GET_FEAT_SEL_MAX
};
+/*
+ * Set Feature CXL spec r3.2 8.2.9.6.3
+ */
+
+/*
+ * Set Feature input payload
+ * CXL spec r3.2 section 8.2.9.6.3 Table 8-101
+ */
+struct cxl_mbox_set_feat_hdr {
+ uuid_t uuid;
+ __le32 flags;
+ __le16 offset;
+ u8 version;
+ u8 rsvd[9];
+} __packed;
+
+/* Set Feature flags field */
+enum cxl_set_feat_flag_data_transfer {
+ CXL_SET_FEAT_FLAG_FULL_DATA_TRANSFER = 0,
+ CXL_SET_FEAT_FLAG_INITIATE_DATA_TRANSFER,
+ CXL_SET_FEAT_FLAG_CONTINUE_DATA_TRANSFER,
+ CXL_SET_FEAT_FLAG_FINISH_DATA_TRANSFER,
+ CXL_SET_FEAT_FLAG_ABORT_DATA_TRANSFER,
+ CXL_SET_FEAT_FLAG_DATA_TRANSFER_MAX
+};
+
+#define CXL_SET_FEAT_FLAG_DATA_TRANSFER_MASK GENMASK(2, 0)
+
+#define CXL_SET_FEAT_FLAG_DATA_SAVED_ACROSS_RESET BIT(3)
+
/**
* struct cxl_features_state - The Features state for the device
* @cxlds: Pointer to CXL device state
@@ -112,6 +142,9 @@ size_t cxl_get_feature(struct cxl_mailbox *cxl_mbox, const uuid_t *feat_uuid,
enum cxl_get_feat_selection selection,
void *feat_out, size_t feat_out_size, u16 offset,
u16 *return_code);
+int cxl_set_feature(struct cxl_mailbox *cxl_mbox, const uuid_t *feat_uuid,
+ u8 feat_version, void *feat_data, size_t feat_data_size,
+ u32 feat_flag, u16 offset, u16 *return_code);
#else
static inline struct cxl_features_state *to_cxlfs(struct cxl_dev_state *cxlds)
{
@@ -131,6 +164,15 @@ static inline size_t cxl_get_feature(struct cxl_mailbox *cxl_mbox,
{
return 0;
}
+
+static inline int cxl_set_feature(struct cxl_mailbox *cxl_mbox,
+ const uuid_t *feat_uuid,
+ u8 feat_version, void *feat_data,
+ size_t feat_data_size, u32 feat_flag,
+ u16 offset, u16 *return_code)
+{
+ return -EOPNOTSUPP;
+}
#endif
#endif
--
2.48.1
^ permalink raw reply related [flat|nested] 45+ messages in thread
* [PATCH v4 06/15] cxl: Setup exclusive CXL features that are reserved for the kernel
2025-02-07 23:37 [PATCH v4 00/15] cxl: Add CXL feature commands support via fwctl Dave Jiang
` (4 preceding siblings ...)
2025-02-07 23:37 ` [PATCH v4 05/15] cxl/mbox: Add SET_FEATURE " Dave Jiang
@ 2025-02-07 23:37 ` Dave Jiang
2025-02-08 1:10 ` Dan Williams
2025-02-08 6:22 ` Li Ming
2025-02-07 23:37 ` [PATCH v4 07/15] cxl: Add FWCTL support to CXL Dave Jiang
` (8 subsequent siblings)
14 siblings, 2 replies; 45+ messages in thread
From: Dave Jiang @ 2025-02-07 23:37 UTC (permalink / raw)
To: linux-cxl
Cc: dan.j.williams, ira.weiny, vishal.l.verma, alison.schofield,
Jonathan.Cameron, dave, jgg, shiju.jose
Certain features will be exclusively used by components such as in
kernel RAS driver. Setup an exclusion list that can be later filtered
out before exposing to user space.
Reviewed-by: Jonathan Cameron <Jonathan.Cameron@huawei.com>
Reviewed-by: Dan Williams <dan.j.williams@intel.com>
Signed-off-by: Dave Jiang <dave.jiang@intel.com>
---
drivers/cxl/core/features.c | 26 ++++++++++++++++++++++++++
include/cxl/features.h | 34 ++++++++++++++++++++++++++++++++++
2 files changed, 60 insertions(+)
diff --git a/drivers/cxl/core/features.c b/drivers/cxl/core/features.c
index d337224158fa..82f21f64452a 100644
--- a/drivers/cxl/core/features.c
+++ b/drivers/cxl/core/features.c
@@ -6,6 +6,28 @@
#include "cxl.h"
#include "cxlmem.h"
+/* All the features below are exclusive to the kernel */
+static const uuid_t cxl_exclusive_feats[] = {
+ CXL_FEAT_PATROL_SCRUB_UUID,
+ CXL_FEAT_ECS_UUID,
+ CXL_FEAT_SPPR_UUID,
+ CXL_FEAT_HPPR_UUID,
+ CXL_FEAT_CACHELINE_SPARING_UUID,
+ CXL_FEAT_ROW_SPARING_UUID,
+ CXL_FEAT_BANK_SPARING_UUID,
+ CXL_FEAT_RANK_SPARING_UUID,
+};
+
+static bool is_cxl_feature_exclusive(struct cxl_feat_entry *entry)
+{
+ for (int i = 0; i < ARRAY_SIZE(cxl_exclusive_feats); i++) {
+ if (uuid_equal(&entry->uuid, &cxl_exclusive_feats[i]))
+ return true;
+ }
+
+ return false;
+}
+
inline struct cxl_features_state *to_cxlfs(struct cxl_dev_state *cxlds)
{
return cxlds->cxlfs;
@@ -46,6 +68,7 @@ get_supported_features(struct cxl_features_state *cxlfs)
struct cxl_mbox_get_sup_feats_in mbox_in;
struct cxl_feat_entry *entry;
struct cxl_mbox_cmd mbox_cmd;
+ int user_feats = 0;
int count;
count = cxl_get_supported_features_count(cxl_mbox);
@@ -120,6 +143,8 @@ get_supported_features(struct cxl_features_state *cxlfs)
return NULL;
memcpy(entry, mbox_out->ents, retrieved);
+ if (!is_cxl_feature_exclusive(entry))
+ user_feats++;
entry += num_entries;
/*
* If the number of output entries is less than expected, add the
@@ -130,6 +155,7 @@ get_supported_features(struct cxl_features_state *cxlfs)
} while (remain_feats);
entries->num_features = count;
+ entries->num_user_features = user_feats;
return no_free_ptr(entries);
}
diff --git a/include/cxl/features.h b/include/cxl/features.h
index 4e3527ba8a1d..1ab97e676c03 100644
--- a/include/cxl/features.h
+++ b/include/cxl/features.h
@@ -5,6 +5,39 @@
#include <linux/uuid.h>
+/* Feature UUIDs used by the kernel */
+#define CXL_FEAT_PATROL_SCRUB_UUID \
+ UUID_INIT(0x96dad7d6, 0xfde8, 0x482b, 0xa7, 0x33, 0x75, 0x77, 0x4e, \
+ 0x06, 0xdb, 0x8a)
+
+#define CXL_FEAT_ECS_UUID \
+ UUID_INIT(0xe5b13f22, 0x2328, 0x4a14, 0xb8, 0xba, 0xb9, 0x69, 0x1e, \
+ 0x89, 0x33, 0x86)
+
+#define CXL_FEAT_SPPR_UUID \
+ UUID_INIT(0x892ba475, 0xfad8, 0x474e, 0x9d, 0x3e, 0x69, 0x2c, 0x91, \
+ 0x75, 0x68, 0xbb)
+
+#define CXL_FEAT_HPPR_UUID \
+ UUID_INIT(0x80ea4521, 0x786f, 0x4127, 0xaf, 0xb1, 0xec, 0x74, 0x59, \
+ 0xfb, 0x0e, 0x24)
+
+#define CXL_FEAT_CACHELINE_SPARING_UUID \
+ UUID_INIT(0x96C33386, 0x91dd, 0x44c7, 0x9e, 0xcb, 0xfd, 0xaf, 0x65, \
+ 0x03, 0xba, 0xc4)
+
+#define CXL_FEAT_ROW_SPARING_UUID \
+ UUID_INIT(0x450ebf67, 0xb135, 0x4f97, 0xa4, 0x98, 0xc2, 0xd5, 0x7f, \
+ 0x27, 0x9b, 0xed)
+
+#define CXL_FEAT_BANK_SPARING_UUID \
+ UUID_INIT(0x78b79636, 0x90ac, 0x4b64, 0xa4, 0xef, 0xfa, 0xac, 0x5d, \
+ 0x18, 0xa8, 0x63)
+
+#define CXL_FEAT_RANK_SPARING_UUID \
+ UUID_INIT(0x34dbaff5, 0x0552, 0x4281, 0x8f, 0x76, 0xda, 0x0b, 0x5e, \
+ 0x7a, 0x76, 0xa7)
+
/* Feature commands capability supported by a device */
enum cxl_features_capability {
CXL_FEATURES_NONE = 0,
@@ -130,6 +163,7 @@ struct cxl_features_state {
struct cxl_dev_state *cxlds;
struct cxl_feat_entries {
int num_features;
+ int num_user_features;
struct cxl_feat_entry ent[] __counted_by(num_features);
} *entries;
};
--
2.48.1
^ permalink raw reply related [flat|nested] 45+ messages in thread
* [PATCH v4 07/15] cxl: Add FWCTL support to CXL
2025-02-07 23:37 [PATCH v4 00/15] cxl: Add CXL feature commands support via fwctl Dave Jiang
` (5 preceding siblings ...)
2025-02-07 23:37 ` [PATCH v4 06/15] cxl: Setup exclusive CXL features that are reserved for the kernel Dave Jiang
@ 2025-02-07 23:37 ` Dave Jiang
2025-02-08 1:24 ` Dan Williams
2025-02-07 23:37 ` [PATCH v4 08/15] cxl: Add support for FWCTL get driver information callback Dave Jiang
` (7 subsequent siblings)
14 siblings, 1 reply; 45+ messages in thread
From: Dave Jiang @ 2025-02-07 23:37 UTC (permalink / raw)
To: linux-cxl
Cc: dan.j.williams, ira.weiny, vishal.l.verma, alison.schofield,
Jonathan.Cameron, dave, jgg, shiju.jose
Add fwctl support code to allow sending of CXL feature commands from
userspace through as ioctls via FWCTL. Provide initial setup bits. The
CXL PCI probe function will call cxl_setup_fwctl() after the cxl_memdev
has been enumerated in order to setup FWCTL char device under the
cxl_memdev like the existing memdev char device for issuing CXL raw
mailbox commands from userspace via ioctls.
Signed-off-by: Dave Jiang <dave.jiang@intel.com>
---
drivers/cxl/core/features.c | 74 ++++++++++++++++++++++++++++++++++++
drivers/cxl/pci.c | 4 ++
include/cxl/features.h | 14 +++++++
include/uapi/fwctl/fwctl.h | 1 +
tools/testing/cxl/test/mem.c | 4 ++
5 files changed, 97 insertions(+)
diff --git a/drivers/cxl/core/features.c b/drivers/cxl/core/features.c
index 82f21f64452a..81e8ff66c12e 100644
--- a/drivers/cxl/core/features.c
+++ b/drivers/cxl/core/features.c
@@ -1,5 +1,6 @@
// SPDX-License-Identifier: GPL-2.0-only
/* Copyright(c) 2024-2025 Intel Corporation. All rights reserved. */
+#include <linux/fwctl.h>
#include <linux/device.h>
#include <cxl/mailbox.h>
#include <cxl/features.h>
@@ -167,6 +168,13 @@ static void free_cxlfs(void *_cxlfs)
cxlds->cxlfs = NULL;
kvfree(cxlfs->entries);
+
+ if (cxlfs->cxl_fwctl) {
+ struct cxl_fwctl *fwctl = cxlfs->cxl_fwctl;
+
+ fwctl_unregister(&fwctl->fwctl_dev);
+ fwctl_put(&fwctl->fwctl_dev);
+ }
kfree(cxlfs);
}
@@ -334,3 +342,69 @@ int cxl_set_feature(struct cxl_mailbox *cxl_mbox,
} while (true);
}
EXPORT_SYMBOL_NS_GPL(cxl_set_feature, "CXL");
+
+static int cxlctl_open_uctx(struct fwctl_uctx *uctx)
+{
+ return 0;
+}
+
+static void cxlctl_close_uctx(struct fwctl_uctx *uctx)
+{
+}
+
+static void *cxlctl_info(struct fwctl_uctx *uctx, size_t *length)
+{
+ /* Place holder */
+ return ERR_PTR(-EOPNOTSUPP);
+}
+
+static void *cxlctl_fw_rpc(struct fwctl_uctx *uctx, enum fwctl_rpc_scope scope,
+ void *in, size_t in_len, size_t *out_len)
+{
+ /* Place holder */
+ return ERR_PTR(-EOPNOTSUPP);
+}
+
+static const struct fwctl_ops cxlctl_ops = {
+ .device_type = FWCTL_DEVICE_TYPE_CXL,
+ .uctx_size = sizeof(struct fwctl_uctx),
+ .open_uctx = cxlctl_open_uctx,
+ .close_uctx = cxlctl_close_uctx,
+ .info = cxlctl_info,
+ .fw_rpc = cxlctl_fw_rpc,
+};
+
+DEFINE_FREE(free_fwctl, struct cxl_fwctl *, if (_T) fwctl_put(&_T->fwctl_dev))
+
+int cxl_setup_fwctl(struct cxl_memdev *cxlmd)
+{
+ struct cxl_dev_state *cxlds = cxlmd->cxlds;
+ struct cxl_features_state *cxlfs;
+ int rc;
+
+ cxlfs = to_cxlfs(cxlds);
+ if (!cxlfs)
+ return -ENODEV;
+
+ /* No need to setup FWCTL if there are no user allowed features found */
+ if (!cxlfs->entries->num_user_features)
+ return -ENODEV;
+
+ struct cxl_fwctl *fwctl __free(free_fwctl) =
+ fwctl_alloc_device(&cxlmd->dev, &cxlctl_ops,
+ struct cxl_fwctl, fwctl_dev);
+ if (!fwctl)
+ return -ENOMEM;
+
+ fwctl->cxlmd = cxlmd;
+ rc = fwctl_register(&fwctl->fwctl_dev);
+ if (rc)
+ return rc;
+
+ cxlfs->cxl_fwctl = no_free_ptr(fwctl);
+
+ return 0;
+}
+EXPORT_SYMBOL_NS_GPL(cxl_setup_fwctl, "CXL");
+
+MODULE_IMPORT_NS("FWCTL");
diff --git a/drivers/cxl/pci.c b/drivers/cxl/pci.c
index 3e666ec51580..b093cb16de3e 100644
--- a/drivers/cxl/pci.c
+++ b/drivers/cxl/pci.c
@@ -1013,6 +1013,10 @@ static int cxl_pci_probe(struct pci_dev *pdev, const struct pci_device_id *id)
if (rc)
return rc;
+ rc = cxl_setup_fwctl(cxlmd);
+ if (rc)
+ dev_dbg(&pdev->dev, "No CXL FWCTL setup\n");
+
pmu_count = cxl_count_regblock(pdev, CXL_REGLOC_RBI_PMU);
if (pmu_count < 0)
return pmu_count;
diff --git a/include/cxl/features.h b/include/cxl/features.h
index 1ab97e676c03..d0c94756e452 100644
--- a/include/cxl/features.h
+++ b/include/cxl/features.h
@@ -4,6 +4,7 @@
#define __CXL_FEATURES_H__
#include <linux/uuid.h>
+#include <linux/fwctl.h>
/* Feature UUIDs used by the kernel */
#define CXL_FEAT_PATROL_SCRUB_UUID \
@@ -158,6 +159,9 @@ enum cxl_set_feat_flag_data_transfer {
* @entries: CXl feature entry context
* @num_features: total Features supported by the device
* @ent: Flex array of Feature detail entries from the device
+ * @fwctl: CXL Firmware Control context
+ * @fwctl_dev: Firmware Control device
+ * @cxlfs: Pointer to CXL Features state
*/
struct cxl_features_state {
struct cxl_dev_state *cxlds;
@@ -166,12 +170,17 @@ struct cxl_features_state {
int num_user_features;
struct cxl_feat_entry ent[] __counted_by(num_features);
} *entries;
+ struct cxl_fwctl {
+ struct fwctl_device fwctl_dev;
+ struct cxl_memdev *cxlmd;
+ } *cxl_fwctl;
};
struct cxl_mailbox;
#ifdef CONFIG_CXL_FEATURES
inline struct cxl_features_state *to_cxlfs(struct cxl_dev_state *cxlds);
int devm_cxl_setup_features(struct cxl_dev_state *cxlds);
+int cxl_setup_fwctl(struct cxl_memdev *cxlmd);
size_t cxl_get_feature(struct cxl_mailbox *cxl_mbox, const uuid_t *feat_uuid,
enum cxl_get_feat_selection selection,
void *feat_out, size_t feat_out_size, u16 offset,
@@ -190,6 +199,11 @@ static inline int devm_cxl_setup_features(struct cxl_dev_state *cxlds)
return -EOPNOTSUPP;
}
+static inline int cxl_setup_fwctl(struct cxl_memdev *cxlmd)
+{
+ return -EOPNOTSUPP;
+}
+
static inline size_t cxl_get_feature(struct cxl_mailbox *cxl_mbox,
const uuid_t *feat_uuid,
enum cxl_get_feat_selection selection,
diff --git a/include/uapi/fwctl/fwctl.h b/include/uapi/fwctl/fwctl.h
index 518f054f02d2..f57f6d86b12f 100644
--- a/include/uapi/fwctl/fwctl.h
+++ b/include/uapi/fwctl/fwctl.h
@@ -43,6 +43,7 @@ enum {
enum fwctl_device_type {
FWCTL_DEVICE_TYPE_ERROR = 0,
FWCTL_DEVICE_TYPE_MLX5 = 1,
+ FWCTL_DEVICE_TYPE_CXL = 2,
FWCTL_DEVICE_TYPE_BNXT = 3,
};
diff --git a/tools/testing/cxl/test/mem.c b/tools/testing/cxl/test/mem.c
index 4809a90ff9b6..53ae16282541 100644
--- a/tools/testing/cxl/test/mem.c
+++ b/tools/testing/cxl/test/mem.c
@@ -1646,6 +1646,10 @@ static int cxl_mock_mem_probe(struct platform_device *pdev)
if (rc)
return rc;
+ rc = cxl_setup_fwctl(cxlmd);
+ if (rc)
+ dev_dbg(dev, "No CXL FWCTL setup\n");
+
cxl_mem_get_event_records(mds, CXLDEV_EVENT_STATUS_ALL);
return 0;
--
2.48.1
^ permalink raw reply related [flat|nested] 45+ messages in thread
* [PATCH v4 08/15] cxl: Add support for FWCTL get driver information callback
2025-02-07 23:37 [PATCH v4 00/15] cxl: Add CXL feature commands support via fwctl Dave Jiang
` (6 preceding siblings ...)
2025-02-07 23:37 ` [PATCH v4 07/15] cxl: Add FWCTL support to CXL Dave Jiang
@ 2025-02-07 23:37 ` Dave Jiang
2025-02-08 1:25 ` Dan Williams
2025-02-10 6:21 ` Li Ming
2025-02-07 23:37 ` [PATCH v4 09/15] cxl: Move cxl feature command structs to user header Dave Jiang
` (6 subsequent siblings)
14 siblings, 2 replies; 45+ messages in thread
From: Dave Jiang @ 2025-02-07 23:37 UTC (permalink / raw)
To: linux-cxl
Cc: dan.j.williams, ira.weiny, vishal.l.verma, alison.schofield,
Jonathan.Cameron, dave, jgg, shiju.jose
Add definition for fwctl_ops->info() to return driver information. The
function will return a data structure with a reserved u32. This is setup
for future usages.
Reviewed-by: Jonathan Cameron <Jonathan.Cameron@huawei.com>
Signed-off-by: Dave Jiang <dave.jiang@intel.com>
---
v4:
- Remove entries check as it is not needed. (Dan)
---
drivers/cxl/core/features.c | 11 +++++++++--
include/cxl/mailbox.h | 1 +
include/uapi/fwctl/cxl.h | 19 +++++++++++++++++++
3 files changed, 29 insertions(+), 2 deletions(-)
create mode 100644 include/uapi/fwctl/cxl.h
diff --git a/drivers/cxl/core/features.c b/drivers/cxl/core/features.c
index 81e8ff66c12e..b2836b951360 100644
--- a/drivers/cxl/core/features.c
+++ b/drivers/cxl/core/features.c
@@ -354,8 +354,15 @@ static void cxlctl_close_uctx(struct fwctl_uctx *uctx)
static void *cxlctl_info(struct fwctl_uctx *uctx, size_t *length)
{
- /* Place holder */
- return ERR_PTR(-EOPNOTSUPP);
+ struct fwctl_info_cxl *info;
+
+ info = kzalloc(sizeof(*info), GFP_KERNEL);
+ if (!info)
+ return ERR_PTR(-ENOMEM);
+
+ *length = sizeof(*info);
+
+ return info;
}
static void *cxlctl_fw_rpc(struct fwctl_uctx *uctx, enum fwctl_rpc_scope scope,
diff --git a/include/cxl/mailbox.h b/include/cxl/mailbox.h
index c4e99e2e3a9d..60a26a0d8f1f 100644
--- a/include/cxl/mailbox.h
+++ b/include/cxl/mailbox.h
@@ -4,6 +4,7 @@
#define __CXL_MBOX_H__
#include <linux/rcuwait.h>
#include <cxl/features.h>
+#include <uapi/fwctl/cxl.h>
#include <uapi/linux/cxl_mem.h>
/**
diff --git a/include/uapi/fwctl/cxl.h b/include/uapi/fwctl/cxl.h
new file mode 100644
index 000000000000..d21fd6b80c20
--- /dev/null
+++ b/include/uapi/fwctl/cxl.h
@@ -0,0 +1,19 @@
+/* SPDX-License-Identifier: GPL-2.0 WITH Linux-syscall-note */
+/*
+ * Copyright (c) 2024, Intel Corporation
+ *
+ * These are definitions for the mailbox command interface of CXL subsystem.
+ */
+#ifndef _UAPI_FWCTL_CXL_H_
+#define _UAPI_FWCTL_CXL_H_
+
+#include <linux/types.h>
+
+/**
+ * struct fwctl_info_cxl - ioctl(FWCTL_INFO) out_device_data
+ * @reserved: zero
+ */
+struct fwctl_info_cxl {
+ __u32 reserved;
+};
+#endif
--
2.48.1
^ permalink raw reply related [flat|nested] 45+ messages in thread
* [PATCH v4 09/15] cxl: Move cxl feature command structs to user header
2025-02-07 23:37 [PATCH v4 00/15] cxl: Add CXL feature commands support via fwctl Dave Jiang
` (7 preceding siblings ...)
2025-02-07 23:37 ` [PATCH v4 08/15] cxl: Add support for FWCTL get driver information callback Dave Jiang
@ 2025-02-07 23:37 ` Dave Jiang
2025-02-07 23:37 ` [PATCH v4 10/15] cxl: Add support for fwctl RPC command to enable CXL feature commands Dave Jiang
` (5 subsequent siblings)
14 siblings, 0 replies; 45+ messages in thread
From: Dave Jiang @ 2025-02-07 23:37 UTC (permalink / raw)
To: linux-cxl
Cc: dan.j.williams, ira.weiny, vishal.l.verma, alison.schofield,
Jonathan.Cameron, dave, jgg, shiju.jose
In preparation for cxl fwctl enabling, move data structures related to
cxl feature commands to a user header file.
Reviewed-by; Jonathan Cameron <Jonathan.Cameron@huawei.com>
Reviewed-by: Dan Williams <dan.j.williams@intel.com>
Signed-off-by: Dave Jiang <dave.jiang@intel.com>
---
include/cxl/features.h | 107 +------------------------------
include/uapi/cxl/features.h | 122 ++++++++++++++++++++++++++++++++++++
2 files changed, 123 insertions(+), 106 deletions(-)
create mode 100644 include/uapi/cxl/features.h
diff --git a/include/cxl/features.h b/include/cxl/features.h
index d0c94756e452..651f2333a77a 100644
--- a/include/cxl/features.h
+++ b/include/cxl/features.h
@@ -5,6 +5,7 @@
#include <linux/uuid.h>
#include <linux/fwctl.h>
+#include <uapi/cxl/features.h>
/* Feature UUIDs used by the kernel */
#define CXL_FEAT_PATROL_SCRUB_UUID \
@@ -46,112 +47,6 @@ enum cxl_features_capability {
CXL_FEATURES_RW,
};
-/* Get Supported Features (0x500h) CXL r3.2 8.2.9.6.1 */
-struct cxl_mbox_get_sup_feats_in {
- __le32 count;
- __le16 start_idx;
- u8 reserved[2];
-} __packed;
-
-/* CXL spec r3.2 Table 8-87 command effects */
-#define CXL_CMD_CONFIG_CHANGE_COLD_RESET BIT(0)
-#define CXL_CMD_CONFIG_CHANGE_IMMEDIATE BIT(1)
-#define CXL_CMD_DATA_CHANGE_IMMEDIATE BIT(2)
-#define CXL_CMD_POLICY_CHANGE_IMMEDIATE BIT(3)
-#define CXL_CMD_LOG_CHANGE_IMMEDIATE BIT(4)
-#define CXL_CMD_SECURITY_STATE_CHANGE BIT(5)
-#define CXL_CMD_BACKGROUND BIT(6)
-#define CXL_CMD_BGCMD_ABORT_SUPPORTED BIT(7)
-#define CXL_CMD_EFFECTS_VALID BIT(9)
-#define CXL_CMD_CONFIG_CHANGE_CONV_RESET BIT(10)
-#define CXL_CMD_CONFIG_CHANGE_CXL_RESET BIT(11)
-
-/*
- * CXL spec r3.2 Table 8-109
- * Get Supported Features Supported Feature Entry
- */
-struct cxl_feat_entry {
- uuid_t uuid;
- __le16 id;
- __le16 get_feat_size;
- __le16 set_feat_size;
- __le32 flags;
- u8 get_feat_ver;
- u8 set_feat_ver;
- __le16 effects;
- u8 reserved[18];
-} __packed;
-
-/* @flags field for 'struct cxl_feat_entry' */
-#define CXL_FEATURE_F_CHANGEABLE BIT(0)
-#define CXL_FEATURE_F_PERSIST_FW_UPDATE BIT(4)
-#define CXL_FEATURE_F_DEFAULT_SEL BIT(5)
-#define CXL_FEATURE_F_SAVED_SEL BIT(6)
-
-/*
- * CXL spec r3.2 Table 8-108
- * Get supported Features Output Payload
- */
-struct cxl_mbox_get_sup_feats_out {
- __le16 num_entries;
- __le16 supported_feats;
- u8 reserved[4];
- struct cxl_feat_entry ents[] __counted_by_le(num_entries);
-} __packed;
-
-/*
- * Get Feature CXL spec r3.2 Spec 8.2.9.6.2
- */
-
-/*
- * Get Feature input payload
- * CXL spec r3.2 section 8.2.9.6.2 Table 8-99
- */
-struct cxl_mbox_get_feat_in {
- uuid_t uuid;
- __le16 offset;
- __le16 count;
- u8 selection;
-} __packed;
-
-/* Selection field for 'struct cxl_mbox_get_feat_in' */
-enum cxl_get_feat_selection {
- CXL_GET_FEAT_SEL_CURRENT_VALUE,
- CXL_GET_FEAT_SEL_DEFAULT_VALUE,
- CXL_GET_FEAT_SEL_SAVED_VALUE,
- CXL_GET_FEAT_SEL_MAX
-};
-
-/*
- * Set Feature CXL spec r3.2 8.2.9.6.3
- */
-
-/*
- * Set Feature input payload
- * CXL spec r3.2 section 8.2.9.6.3 Table 8-101
- */
-struct cxl_mbox_set_feat_hdr {
- uuid_t uuid;
- __le32 flags;
- __le16 offset;
- u8 version;
- u8 rsvd[9];
-} __packed;
-
-/* Set Feature flags field */
-enum cxl_set_feat_flag_data_transfer {
- CXL_SET_FEAT_FLAG_FULL_DATA_TRANSFER = 0,
- CXL_SET_FEAT_FLAG_INITIATE_DATA_TRANSFER,
- CXL_SET_FEAT_FLAG_CONTINUE_DATA_TRANSFER,
- CXL_SET_FEAT_FLAG_FINISH_DATA_TRANSFER,
- CXL_SET_FEAT_FLAG_ABORT_DATA_TRANSFER,
- CXL_SET_FEAT_FLAG_DATA_TRANSFER_MAX
-};
-
-#define CXL_SET_FEAT_FLAG_DATA_TRANSFER_MASK GENMASK(2, 0)
-
-#define CXL_SET_FEAT_FLAG_DATA_SAVED_ACROSS_RESET BIT(3)
-
/**
* struct cxl_features_state - The Features state for the device
* @cxlds: Pointer to CXL device state
diff --git a/include/uapi/cxl/features.h b/include/uapi/cxl/features.h
new file mode 100644
index 000000000000..2e98efb9abf1
--- /dev/null
+++ b/include/uapi/cxl/features.h
@@ -0,0 +1,122 @@
+/* SPDX-License-Identifier: GPL-2.0 WITH Linux-syscall-note */
+/*
+ * Copyright (c) 2024,2025, Intel Corporation
+ *
+ * These are definitions for the mailbox command interface of CXL subsystem.
+ */
+#ifndef _UAPI_CXL_FEATURES_H_
+#define _UAPI_CXL_FEATURES_H_
+
+#include <linux/types.h>
+#ifndef __KERNEL__
+#include <uuid/uuid.h>
+#else
+#include <linux/uuid.h>
+#endif
+
+/* Get Supported Features (0x500h) CXL r3.2 8.2.9.6.1 */
+struct cxl_mbox_get_sup_feats_in {
+ __le32 count;
+ __le16 start_idx;
+ __u8 reserved[2];
+} __attribute__ ((__packed__));
+
+/* CXL spec r3.2 Table 8-87 command effects */
+#define CXL_CMD_CONFIG_CHANGE_COLD_RESET BIT(0)
+#define CXL_CMD_CONFIG_CHANGE_IMMEDIATE BIT(1)
+#define CXL_CMD_DATA_CHANGE_IMMEDIATE BIT(2)
+#define CXL_CMD_POLICY_CHANGE_IMMEDIATE BIT(3)
+#define CXL_CMD_LOG_CHANGE_IMMEDIATE BIT(4)
+#define CXL_CMD_SECURITY_STATE_CHANGE BIT(5)
+#define CXL_CMD_BACKGROUND BIT(6)
+#define CXL_CMD_BGCMD_ABORT_SUPPORTED BIT(7)
+#define CXL_CMD_EFFECTS_VALID BIT(9)
+#define CXL_CMD_CONFIG_CHANGE_CONV_RESET BIT(10)
+#define CXL_CMD_CONFIG_CHANGE_CXL_RESET BIT(11)
+
+/*
+ * CXL spec r3.2 Table 8-109
+ * Get Supported Features Supported Feature Entry
+ */
+struct cxl_feat_entry {
+ uuid_t uuid;
+ __le16 id;
+ __le16 get_feat_size;
+ __le16 set_feat_size;
+ __le32 flags;
+ __u8 get_feat_ver;
+ __u8 set_feat_ver;
+ __le16 effects;
+ __u8 reserved[18];
+} __attribute__ ((__packed__));
+
+/* @flags field for 'struct cxl_feat_entry' */
+#define CXL_FEATURE_F_CHANGEABLE BIT(0)
+#define CXL_FEATURE_F_PERSIST_FW_UPDATE BIT(4)
+#define CXL_FEATURE_F_DEFAULT_SEL BIT(5)
+#define CXL_FEATURE_F_SAVED_SEL BIT(6)
+
+/*
+ * CXL spec r3.2 Table 8-108
+ * Get supported Features Output Payload
+ */
+struct cxl_mbox_get_sup_feats_out {
+ __le16 num_entries;
+ __le16 supported_feats;
+ __u8 reserved[4];
+ struct cxl_feat_entry ents[] __counted_by_le(num_entries);
+} __attribute__ ((__packed__));
+
+/*
+ * Get Feature CXL spec r3.2 Spec 8.2.9.6.2
+ */
+
+/*
+ * Get Feature input payload
+ * CXL spec r3.2 section 8.2.9.6.2 Table 8-99
+ */
+struct cxl_mbox_get_feat_in {
+ uuid_t uuid;
+ __le16 offset;
+ __le16 count;
+ __u8 selection;
+} __attribute__ ((__packed__));
+
+/* Selection field for 'struct cxl_mbox_get_feat_in' */
+enum cxl_get_feat_selection {
+ CXL_GET_FEAT_SEL_CURRENT_VALUE,
+ CXL_GET_FEAT_SEL_DEFAULT_VALUE,
+ CXL_GET_FEAT_SEL_SAVED_VALUE,
+ CXL_GET_FEAT_SEL_MAX
+};
+
+/*
+ * Set Feature CXL spec r3.2 8.2.9.6.3
+ */
+
+/*
+ * Set Feature input payload
+ * CXL spec r3.2 section 8.2.9.6.3 Table 8-101
+ */
+struct cxl_mbox_set_feat_hdr {
+ uuid_t uuid;
+ __le32 flags;
+ __le16 offset;
+ __u8 version;
+ __u8 rsvd[9];
+} __attribute__ ((__packed__));
+
+/* Set Feature flags field */
+enum cxl_set_feat_flag_data_transfer {
+ CXL_SET_FEAT_FLAG_FULL_DATA_TRANSFER = 0,
+ CXL_SET_FEAT_FLAG_INITIATE_DATA_TRANSFER,
+ CXL_SET_FEAT_FLAG_CONTINUE_DATA_TRANSFER,
+ CXL_SET_FEAT_FLAG_FINISH_DATA_TRANSFER,
+ CXL_SET_FEAT_FLAG_ABORT_DATA_TRANSFER,
+ CXL_SET_FEAT_FLAG_DATA_TRANSFER_MAX
+};
+
+#define CXL_SET_FEAT_FLAG_DATA_TRANSFER_MASK GENMASK(2, 0)
+#define CXL_SET_FEAT_FLAG_DATA_SAVED_ACROSS_RESET BIT(3)
+
+#endif
--
2.48.1
^ permalink raw reply related [flat|nested] 45+ messages in thread
* [PATCH v4 10/15] cxl: Add support for fwctl RPC command to enable CXL feature commands
2025-02-07 23:37 [PATCH v4 00/15] cxl: Add CXL feature commands support via fwctl Dave Jiang
` (8 preceding siblings ...)
2025-02-07 23:37 ` [PATCH v4 09/15] cxl: Move cxl feature command structs to user header Dave Jiang
@ 2025-02-07 23:37 ` Dave Jiang
2025-02-08 1:29 ` Dan Williams
` (2 more replies)
2025-02-07 23:37 ` [PATCH v4 11/15] cxl: Add support to handle user feature commands for get feature Dave Jiang
` (4 subsequent siblings)
14 siblings, 3 replies; 45+ messages in thread
From: Dave Jiang @ 2025-02-07 23:37 UTC (permalink / raw)
To: linux-cxl
Cc: dan.j.williams, ira.weiny, vishal.l.verma, alison.schofield,
Jonathan.Cameron, dave, jgg, shiju.jose
fwctl provides a fwctl_ops->fw_rpc() callback in order to issue ioctls
to a device. The cxl fwctl driver will start by supporting the CXL
Feature commands: Get Supported Features, Get Feature, and Set Feature.
The fw_rpc() callback provides 'enum fwctl_rpc_scope' parameter where
it indicates the security scope of the call. The Get Supported Features
and Get Feature calls can be executed with the scope of
FWCTL_RPC_CONFIGRATION. The Set Feature call is gated by the effects
of the Feature reported by Get Supported Features call for the specific
Feature.
Only "Get Supported Features" is supported in this patch. Additional
commands will be added in follow on patches. "Get Supported Features"
will filter the Features that are exclusive to the kernel. The flag
field of the Feature details will be cleared of the "Changeable"
field and the "set feat size" will be set to 0 to indicate that
the feature is not changeable.
Signed-off-by: Dave Jiang <dave.jiang@intel.com>
---
v4:
- Use opcode directly instead of command ids. (Dan)
- Add check for no immediate effects and no reset effects. (Dan, Jonathan)
- Add check for Set Features to have CXL_FEATURES_RW cap.
- Add clearing of the "Changeable" bit in the flags for exclusive features.
---
drivers/cxl/core/features.c | 221 +++++++++++++++++++++++++++++++++++-
include/uapi/cxl/features.h | 1 +
include/uapi/fwctl/cxl.h | 37 ++++++
3 files changed, 257 insertions(+), 2 deletions(-)
diff --git a/drivers/cxl/core/features.c b/drivers/cxl/core/features.c
index b2836b951360..2682067dd2d7 100644
--- a/drivers/cxl/core/features.c
+++ b/drivers/cxl/core/features.c
@@ -365,11 +365,228 @@ static void *cxlctl_info(struct fwctl_uctx *uctx, size_t *length)
return info;
}
+static struct cxl_feat_entry *
+get_support_feature_info(struct cxl_features_state *cxlfs,
+ const struct fwctl_rpc_cxl *rpc_in)
+{
+ struct cxl_feat_entry *feat;
+ uuid_t uuid;
+
+ if (rpc_in->op_size < sizeof(uuid))
+ return ERR_PTR(-EINVAL);
+
+ if (copy_from_user(&uuid, u64_to_user_ptr(rpc_in->in_payload),
+ sizeof(uuid)))
+ return ERR_PTR(-EFAULT);
+
+ for (int i = 0; i < cxlfs->entries->num_features; i++) {
+ feat = &cxlfs->entries->ent[i];
+ if (uuid_equal(&uuid, &feat->uuid))
+ return feat;
+ }
+
+ return ERR_PTR(-EINVAL);
+}
+
+static void *cxlctl_get_supported_features(struct cxl_features_state *cxlfs,
+ const struct fwctl_rpc_cxl *rpc_in,
+ size_t *out_len)
+{
+ struct cxl_mbox_get_sup_feats_out *feat_out;
+ struct cxl_mbox_get_sup_feats_in feat_in;
+ struct cxl_feat_entry *pos;
+ size_t out_size;
+ int requested;
+ u32 count;
+ u16 start;
+ int i;
+
+ if (rpc_in->op_size != sizeof(feat_in))
+ return ERR_PTR(-EINVAL);
+
+ if (copy_from_user(&feat_in, u64_to_user_ptr(rpc_in->in_payload),
+ rpc_in->op_size))
+ return ERR_PTR(-EFAULT);
+
+ count = le32_to_cpu(feat_in.count);
+ start = le16_to_cpu(feat_in.start_idx);
+ requested = count / sizeof(*pos);
+
+ /*
+ * Make sure that the total requested number of entries is not greater
+ * than the total number of supported features allowed for userspace.
+ */
+ if (start >= cxlfs->entries->num_features)
+ return ERR_PTR(-EINVAL);
+
+ requested = min_t(int, requested, cxlfs->entries->num_features - start);
+
+ out_size = sizeof(struct fwctl_rpc_cxl_out) +
+ struct_size(feat_out, ents, requested);
+
+ struct fwctl_rpc_cxl_out *rpc_out __free(kvfree) =
+ kvzalloc(out_size, GFP_KERNEL);
+ if (!rpc_out)
+ return ERR_PTR(-ENOMEM);
+
+ rpc_out->size = struct_size(feat_out, ents, requested);
+ feat_out = (struct cxl_mbox_get_sup_feats_out *)rpc_out->payload;
+ if (requested == 0) {
+ feat_out->num_entries = cpu_to_le16(requested);
+ feat_out->supported_feats =
+ cpu_to_le16(cxlfs->entries->num_features);
+ rpc_out->retval = CXL_MBOX_CMD_RC_SUCCESS;
+ *out_len = out_size;
+ return no_free_ptr(rpc_out);
+ }
+
+ for (i = 0, pos = &feat_out->ents[0];
+ i < cxlfs->entries->num_features; i++, pos++) {
+ if (i == requested)
+ break;
+
+ memcpy(pos, &cxlfs->entries->ent[i], sizeof(*pos));
+ /*
+ * If the feature is exclusive, set the set_feat_size to 0 to
+ * indicate that the feature is not changeable.
+ */
+ if (is_cxl_feature_exclusive(pos)) {
+ u32 flags;
+
+ pos->set_feat_size = 0;
+ flags = le32_to_cpu(pos->flags);
+ flags &= ~CXL_FEATURE_F_CHANGEABLE;
+ pos->flags = cpu_to_le32(flags);
+ }
+ }
+
+ feat_out->num_entries = cpu_to_le16(requested);
+ feat_out->supported_feats = cpu_to_le16(cxlfs->entries->num_features);
+ rpc_out->retval = CXL_MBOX_CMD_RC_SUCCESS;
+ *out_len = out_size;
+
+ return no_free_ptr(rpc_out);
+}
+
+static bool cxlctl_validate_set_features(struct cxl_features_state *cxlfs,
+ const struct fwctl_rpc_cxl *rpc_in,
+ enum fwctl_rpc_scope scope)
+{
+ u16 effects, imm_mask, reset_mask;
+ struct cxl_feat_entry *feat;
+ u32 flags;
+
+ feat = get_support_feature_info(cxlfs, rpc_in);
+ if (IS_ERR(feat))
+ return false;
+
+ /* Ensure that the attribute is changeable */
+ flags = le32_to_cpu(feat->flags);
+ if (!(flags & CXL_FEATURE_F_CHANGEABLE))
+ return false;
+
+ effects = le16_to_cpu(feat->effects);
+
+ /*
+ * Reserved bits are set, rejecting since the effects is not
+ * comprehended by the driver.
+ */
+ if (effects & CXL_CMD_EFFECTS_RESERVED) {
+ dev_warn_once(cxlfs->cxlds->dev,
+ "Reserved bits set in the Feature effects field!\n");
+ return false;
+ }
+
+ /* Currently no user background command support */
+ if (effects & CXL_CMD_BACKGROUND)
+ return false;
+
+ /* Effects cause immediate change, highest security scope is needed */
+ imm_mask = CXL_CMD_CONFIG_CHANGE_IMMEDIATE |
+ CXL_CMD_DATA_CHANGE_IMMEDIATE |
+ CXL_CMD_POLICY_CHANGE_IMMEDIATE |
+ CXL_CMD_LOG_CHANGE_IMMEDIATE;
+
+ reset_mask = CXL_CMD_CONFIG_CHANGE_COLD_RESET |
+ CXL_CMD_CONFIG_CHANGE_CONV_RESET |
+ CXL_CMD_CONFIG_CHANGE_CXL_RESET;
+
+ /* If no immediate or reset effect set, The hardware has a bug */
+ if (!(effects & imm_mask) && !(effects & reset_mask))
+ return false;
+
+ /*
+ * If the Feature setting causes immediate configuration change
+ * then we need the full write permission policy.
+ */
+ if (effects & imm_mask && scope >= FWCTL_RPC_DEBUG_WRITE_FULL)
+ return true;
+
+ /*
+ * If the Feature setting only causes configuration change
+ * after a reset, then the lesser level of write permission
+ * policy is ok.
+ */
+ if (!(effects & imm_mask) && scope >= FWCTL_RPC_DEBUG_WRITE)
+ return true;
+
+ return false;
+}
+
+static bool cxlctl_validate_hw_command(struct cxl_features_state *cxlfs,
+ const struct fwctl_rpc_cxl *rpc_in,
+ enum fwctl_rpc_scope scope,
+ u16 opcode)
+{
+ struct cxl_mailbox *cxl_mbox = &cxlfs->cxlds->cxl_mbox;
+
+ switch (opcode) {
+ case CXL_MBOX_OP_GET_SUPPORTED_FEATURES:
+ case CXL_MBOX_OP_GET_FEATURE:
+ if (cxl_mbox->feat_cap < CXL_FEATURES_RO)
+ return false;
+ if (scope >= FWCTL_RPC_CONFIGURATION)
+ return true;
+ return false;
+ case CXL_MBOX_OP_SET_FEATURE:
+ if (cxl_mbox->feat_cap < CXL_FEATURES_RW)
+ return false;
+ return cxlctl_validate_set_features(cxlfs, rpc_in, scope);
+ default:
+ return false;
+ }
+}
+
+static void *cxlctl_handle_commands(struct cxl_features_state *cxlfs,
+ const struct fwctl_rpc_cxl *rpc_in,
+ size_t *out_len, u16 opcode)
+{
+ switch (opcode) {
+ case CXL_MBOX_OP_GET_SUPPORTED_FEATURES:
+ return cxlctl_get_supported_features(cxlfs, rpc_in, out_len);
+ case CXL_MBOX_OP_GET_FEATURE:
+ case CXL_MBOX_OP_SET_FEATURE:
+ default:
+ return ERR_PTR(-EOPNOTSUPP);
+ }
+}
+
+#define to_cxl_fwctl(fwctl_dev) container_of(fwctl_dev, struct cxl_fwctl, fwctl_dev)
+
static void *cxlctl_fw_rpc(struct fwctl_uctx *uctx, enum fwctl_rpc_scope scope,
void *in, size_t in_len, size_t *out_len)
{
- /* Place holder */
- return ERR_PTR(-EOPNOTSUPP);
+ struct fwctl_device *fwctl_dev = uctx->fwctl;
+ struct cxl_fwctl *cxl_fwctl = to_cxl_fwctl(fwctl_dev);
+ struct cxl_memdev *cxlmd = cxl_fwctl->cxlmd;
+ struct cxl_features_state *cxlfs = to_cxlfs(cxlmd->cxlds);
+ const struct fwctl_rpc_cxl *rpc_in = in;
+ u16 opcode = rpc_in->opcode;
+
+ if (!cxlctl_validate_hw_command(cxlfs, rpc_in, scope, opcode))
+ return ERR_PTR(-EINVAL);
+
+ return cxlctl_handle_commands(cxlfs, rpc_in, out_len, opcode);
}
static const struct fwctl_ops cxlctl_ops = {
diff --git a/include/uapi/cxl/features.h b/include/uapi/cxl/features.h
index 2e98efb9abf1..05c8a06a5dff 100644
--- a/include/uapi/cxl/features.h
+++ b/include/uapi/cxl/features.h
@@ -33,6 +33,7 @@ struct cxl_mbox_get_sup_feats_in {
#define CXL_CMD_EFFECTS_VALID BIT(9)
#define CXL_CMD_CONFIG_CHANGE_CONV_RESET BIT(10)
#define CXL_CMD_CONFIG_CHANGE_CXL_RESET BIT(11)
+#define CXL_CMD_EFFECTS_RESERVED GENMASK(15, 12)
/*
* CXL spec r3.2 Table 8-109
diff --git a/include/uapi/fwctl/cxl.h b/include/uapi/fwctl/cxl.h
index d21fd6b80c20..04568203cacd 100644
--- a/include/uapi/fwctl/cxl.h
+++ b/include/uapi/fwctl/cxl.h
@@ -16,4 +16,41 @@
struct fwctl_info_cxl {
__u32 reserved;
};
+
+/**
+ * struct fwctl_rpc_cxl - ioctl(FWCTL_RPC) input for CXL
+ * @opcode: CXL mailbox command opcode
+ * @flags: Flags for the command (input).
+ * @op_size: Size of input payload.
+ * @reserved1: Reserved. Must be 0s.
+ * @in_payload: User address of the hardware op input structure
+ */
+struct fwctl_rpc_cxl {
+ __u32 opcode;
+ __u32 flags;
+ __u32 op_size;
+ __u32 reserved1;
+ __aligned_u64 in_payload;
+};
+
+/* command_id for CXL mailbox Feature commands */
+enum feature_cmds {
+ CXL_FEATURE_ID_GET_SUPPORTED_FEATURES = 0,
+ CXL_FEATURE_ID_GET_FEATURE,
+ CXL_FEATURE_ID_SET_FEATURE,
+ CXL_FEATURE_ID_MAX
+};
+
+/**
+ * struct fwctl_rpc_cxl_out - ioctl(FWCTL_RPC) output for CXL
+ * @size: Size of the output payload
+ * @retval: Return value from device
+ * @payload: Return data from device
+ */
+struct fwctl_rpc_cxl_out {
+ __u32 size;
+ __u32 retval;
+ __u8 payload[] __counted_by(size);
+};
+
#endif
--
2.48.1
^ permalink raw reply related [flat|nested] 45+ messages in thread
* [PATCH v4 11/15] cxl: Add support to handle user feature commands for get feature
2025-02-07 23:37 [PATCH v4 00/15] cxl: Add CXL feature commands support via fwctl Dave Jiang
` (9 preceding siblings ...)
2025-02-07 23:37 ` [PATCH v4 10/15] cxl: Add support for fwctl RPC command to enable CXL feature commands Dave Jiang
@ 2025-02-07 23:37 ` Dave Jiang
2025-02-10 6:41 ` Li Ming
2025-02-07 23:37 ` [PATCH v4 12/15] cxl: Add support to handle user feature commands for set feature Dave Jiang
` (3 subsequent siblings)
14 siblings, 1 reply; 45+ messages in thread
From: Dave Jiang @ 2025-02-07 23:37 UTC (permalink / raw)
To: linux-cxl
Cc: dan.j.williams, ira.weiny, vishal.l.verma, alison.schofield,
Jonathan.Cameron, dave, jgg, shiju.jose
Add helper function to parse the user data from fwctl RPC ioctl and
send the parsed input parameters to cxl_get_feature() call.
Reviewed-by: Jonathan Cameron <Jonathan.Cameron@huawei.com>
Reviewed-by: Dan Williams <dan.j.williams@intel.com>
Signed-off-by: Dave Jiang <dave.jiang@intel.com>
---
drivers/cxl/core/features.c | 45 +++++++++++++++++++++++++++++++++++++
1 file changed, 45 insertions(+)
diff --git a/drivers/cxl/core/features.c b/drivers/cxl/core/features.c
index 2682067dd2d7..b359353fd4d2 100644
--- a/drivers/cxl/core/features.c
+++ b/drivers/cxl/core/features.c
@@ -468,6 +468,50 @@ static void *cxlctl_get_supported_features(struct cxl_features_state *cxlfs,
return no_free_ptr(rpc_out);
}
+static void *cxlctl_get_feature(struct cxl_features_state *cxlfs,
+ const struct fwctl_rpc_cxl *rpc_in,
+ size_t *out_len)
+{
+ struct cxl_mailbox *cxl_mbox = &cxlfs->cxlds->cxl_mbox;
+ struct cxl_mbox_get_feat_in feat_in;
+ u16 offset, count, return_code;
+ size_t out_size = *out_len;
+
+ if (rpc_in->op_size != sizeof(feat_in))
+ return ERR_PTR(-EINVAL);
+
+ if (copy_from_user(&feat_in, u64_to_user_ptr(rpc_in->in_payload),
+ rpc_in->op_size))
+ return ERR_PTR(-EFAULT);
+
+ offset = le16_to_cpu(feat_in.offset);
+ count = le16_to_cpu(feat_in.count);
+
+ if (!count)
+ return ERR_PTR(-EINVAL);
+
+ struct fwctl_rpc_cxl_out *rpc_out __free(kvfree) =
+ kvzalloc(out_size, GFP_KERNEL);
+ if (!rpc_out)
+ return ERR_PTR(-ENOMEM);
+
+ out_size = cxl_get_feature(cxl_mbox, &feat_in.uuid,
+ feat_in.selection, rpc_out->payload,
+ count, offset, &return_code);
+ *out_len = sizeof(struct fwctl_rpc_cxl_out);
+ if (!out_size) {
+ rpc_out->size = 0;
+ rpc_out->retval = return_code;
+ return no_free_ptr(rpc_out);
+ }
+
+ rpc_out->size = out_size;
+ rpc_out->retval = CXL_MBOX_CMD_RC_SUCCESS;
+ *out_len += out_size;
+
+ return no_free_ptr(rpc_out);
+}
+
static bool cxlctl_validate_set_features(struct cxl_features_state *cxlfs,
const struct fwctl_rpc_cxl *rpc_in,
enum fwctl_rpc_scope scope)
@@ -565,6 +609,7 @@ static void *cxlctl_handle_commands(struct cxl_features_state *cxlfs,
case CXL_MBOX_OP_GET_SUPPORTED_FEATURES:
return cxlctl_get_supported_features(cxlfs, rpc_in, out_len);
case CXL_MBOX_OP_GET_FEATURE:
+ return cxlctl_get_feature(cxlfs, rpc_in, out_len);
case CXL_MBOX_OP_SET_FEATURE:
default:
return ERR_PTR(-EOPNOTSUPP);
--
2.48.1
^ permalink raw reply related [flat|nested] 45+ messages in thread
* [PATCH v4 12/15] cxl: Add support to handle user feature commands for set feature
2025-02-07 23:37 [PATCH v4 00/15] cxl: Add CXL feature commands support via fwctl Dave Jiang
` (10 preceding siblings ...)
2025-02-07 23:37 ` [PATCH v4 11/15] cxl: Add support to handle user feature commands for get feature Dave Jiang
@ 2025-02-07 23:37 ` Dave Jiang
2025-02-10 6:43 ` Li Ming
2025-02-07 23:37 ` [PATCH v4 13/15] cxl/test: Add Get Feature support to cxl_test Dave Jiang
` (2 subsequent siblings)
14 siblings, 1 reply; 45+ messages in thread
From: Dave Jiang @ 2025-02-07 23:37 UTC (permalink / raw)
To: linux-cxl
Cc: dan.j.williams, ira.weiny, vishal.l.verma, alison.schofield,
Jonathan.Cameron, dave, jgg, shiju.jose
Add helper function to parse the user data from fwctl RPC ioctl and
send the parsed input parameters to cxl_set_feature() call.
Reviewed-by: Jonathan Cameron <Jonathan.Cameron@huawei.com>
Reviewed-by: Dan Williams <dan.j.williams@intel.com>
Signed-off-by: Dave Jiang <dave.jiang@intel.com>
---
drivers/cxl/core/features.c | 61 +++++++++++++++++++++++++++++++++++--
include/uapi/cxl/features.h | 5 +++
2 files changed, 64 insertions(+), 2 deletions(-)
diff --git a/drivers/cxl/core/features.c b/drivers/cxl/core/features.c
index b359353fd4d2..6b409c2ca897 100644
--- a/drivers/cxl/core/features.c
+++ b/drivers/cxl/core/features.c
@@ -19,16 +19,21 @@ static const uuid_t cxl_exclusive_feats[] = {
CXL_FEAT_RANK_SPARING_UUID,
};
-static bool is_cxl_feature_exclusive(struct cxl_feat_entry *entry)
+static bool is_cxl_feature_exclusive_by_uuid(uuid_t *uuid)
{
for (int i = 0; i < ARRAY_SIZE(cxl_exclusive_feats); i++) {
- if (uuid_equal(&entry->uuid, &cxl_exclusive_feats[i]))
+ if (uuid_equal(uuid, &cxl_exclusive_feats[i]))
return true;
}
return false;
}
+static bool is_cxl_feature_exclusive(struct cxl_feat_entry *entry)
+{
+ return is_cxl_feature_exclusive_by_uuid(&entry->uuid);
+}
+
inline struct cxl_features_state *to_cxlfs(struct cxl_dev_state *cxlds)
{
return cxlds->cxlfs;
@@ -512,6 +517,57 @@ static void *cxlctl_get_feature(struct cxl_features_state *cxlfs,
return no_free_ptr(rpc_out);
}
+static void *cxlctl_set_feature(struct cxl_features_state *cxlfs,
+ const struct fwctl_rpc_cxl *rpc_in,
+ size_t *out_len)
+{
+ struct cxl_mailbox *cxl_mbox = &cxlfs->cxlds->cxl_mbox;
+ size_t out_size, data_size;
+ u16 offset, return_code;
+ u32 flags;
+ int rc;
+
+ if (rpc_in->op_size <= sizeof(struct cxl_mbox_set_feat_hdr))
+ return ERR_PTR(-EINVAL);
+
+ struct cxl_mbox_set_feat_in *feat_in __free(kvfree) =
+ kvzalloc(rpc_in->op_size, GFP_KERNEL);
+ if (!feat_in)
+ return ERR_PTR(-ENOMEM);
+
+ if (copy_from_user(feat_in, u64_to_user_ptr(rpc_in->in_payload),
+ rpc_in->op_size))
+ return ERR_PTR(-EFAULT);
+
+ if (is_cxl_feature_exclusive_by_uuid(&feat_in->hdr.uuid))
+ return ERR_PTR(-EPERM);
+
+ offset = le16_to_cpu(feat_in->hdr.offset);
+ flags = le32_to_cpu(feat_in->hdr.flags);
+ out_size = *out_len;
+
+ struct fwctl_rpc_cxl_out *rpc_out __free(kvfree) =
+ kvzalloc(out_size, GFP_KERNEL);
+ if (!rpc_out)
+ return ERR_PTR(-ENOMEM);
+
+ rpc_out->size = 0;
+
+ data_size = rpc_in->op_size - sizeof(feat_in->hdr);
+ rc = cxl_set_feature(cxl_mbox, &feat_in->hdr.uuid,
+ feat_in->hdr.version, feat_in->data,
+ data_size, flags, offset, &return_code);
+ if (rc) {
+ rpc_out->retval = return_code;
+ return no_free_ptr(rpc_out);
+ }
+
+ rpc_out->retval = CXL_MBOX_CMD_RC_SUCCESS;
+ *out_len = sizeof(*rpc_out);
+
+ return no_free_ptr(rpc_out);
+}
+
static bool cxlctl_validate_set_features(struct cxl_features_state *cxlfs,
const struct fwctl_rpc_cxl *rpc_in,
enum fwctl_rpc_scope scope)
@@ -611,6 +667,7 @@ static void *cxlctl_handle_commands(struct cxl_features_state *cxlfs,
case CXL_MBOX_OP_GET_FEATURE:
return cxlctl_get_feature(cxlfs, rpc_in, out_len);
case CXL_MBOX_OP_SET_FEATURE:
+ return cxlctl_set_feature(cxlfs, rpc_in, out_len);
default:
return ERR_PTR(-EOPNOTSUPP);
}
diff --git a/include/uapi/cxl/features.h b/include/uapi/cxl/features.h
index 05c8a06a5dff..30138506b286 100644
--- a/include/uapi/cxl/features.h
+++ b/include/uapi/cxl/features.h
@@ -107,6 +107,11 @@ struct cxl_mbox_set_feat_hdr {
__u8 rsvd[9];
} __attribute__ ((__packed__));
+struct cxl_mbox_set_feat_in {
+ struct cxl_mbox_set_feat_hdr hdr;
+ __u8 data[];
+} __attribute__ ((__packed__));
+
/* Set Feature flags field */
enum cxl_set_feat_flag_data_transfer {
CXL_SET_FEAT_FLAG_FULL_DATA_TRANSFER = 0,
--
2.48.1
^ permalink raw reply related [flat|nested] 45+ messages in thread
* [PATCH v4 13/15] cxl/test: Add Get Feature support to cxl_test
2025-02-07 23:37 [PATCH v4 00/15] cxl: Add CXL feature commands support via fwctl Dave Jiang
` (11 preceding siblings ...)
2025-02-07 23:37 ` [PATCH v4 12/15] cxl: Add support to handle user feature commands for set feature Dave Jiang
@ 2025-02-07 23:37 ` Dave Jiang
2025-02-10 6:44 ` Li Ming
2025-02-07 23:37 ` [PATCH v4 14/15] cxl/test: Add Set " Dave Jiang
2025-02-07 23:37 ` [PATCH v4 15/15] fwctl/cxl: Add documentation to FWCTL CXL Dave Jiang
14 siblings, 1 reply; 45+ messages in thread
From: Dave Jiang @ 2025-02-07 23:37 UTC (permalink / raw)
To: linux-cxl
Cc: dan.j.williams, ira.weiny, vishal.l.verma, alison.schofield,
Jonathan.Cameron, dave, jgg, shiju.jose
Add emulation of Get Feature command to cxl_test. The feature for
device patrol scrub is returned by the emulation code. This is
the only feature currently supported by cxl_test. It returns
the information for the device patrol scrub feature.
Reviewed-by: Jonathan Cameron <Jonathan.Cameron@huawei.com>
Reviewed-by: Dan Williams <dan.j.williams@intel.com>
Signed-off-by: Dave Jiang <dave.jiang@intel.com>
---
tools/testing/cxl/test/mem.c | 56 ++++++++++++++++++++++++++++++++++++
1 file changed, 56 insertions(+)
diff --git a/tools/testing/cxl/test/mem.c b/tools/testing/cxl/test/mem.c
index 53ae16282541..0ada4a747bf3 100644
--- a/tools/testing/cxl/test/mem.c
+++ b/tools/testing/cxl/test/mem.c
@@ -48,6 +48,10 @@ static struct cxl_cel_entry mock_cel[] = {
.opcode = cpu_to_le16(CXL_MBOX_OP_GET_SUPPORTED_FEATURES),
.effect = CXL_CMD_EFFECT_NONE,
},
+ {
+ .opcode = cpu_to_le16(CXL_MBOX_OP_GET_FEATURE),
+ .effect = CXL_CMD_EFFECT_NONE,
+ },
{
.opcode = cpu_to_le16(CXL_MBOX_OP_IDENTIFY),
.effect = CXL_CMD_EFFECT_NONE,
@@ -149,6 +153,10 @@ struct mock_event_store {
u32 ev_status;
};
+struct vendor_test_feat {
+ __le32 data;
+} __packed;
+
struct cxl_mockmem_data {
void *lsa;
void *fw;
@@ -165,6 +173,7 @@ struct cxl_mockmem_data {
u8 event_buf[SZ_4K];
u64 timestamp;
unsigned long sanitize_timeout;
+ struct vendor_test_feat test_feat;
};
static struct mock_event_log *event_find_log(struct device *dev, int log_type)
@@ -1379,6 +1388,44 @@ static void fill_feature_vendor_test(struct cxl_feat_entry *feat)
#define MAX_CXL_TEST_FEATS 1
+static int mock_get_test_feature(struct cxl_mockmem_data *mdata,
+ struct cxl_mbox_cmd *cmd)
+{
+ struct vendor_test_feat *output = cmd->payload_out;
+ struct cxl_mbox_get_feat_in *input = cmd->payload_in;
+ u16 offset = le16_to_cpu(input->offset);
+ u16 count = le16_to_cpu(input->count);
+ u8 *ptr;
+
+ if (offset > sizeof(*output)) {
+ cmd->return_code = CXL_MBOX_CMD_RC_INPUT;
+ return -EINVAL;
+ }
+
+ if (offset + count > sizeof(*output)) {
+ cmd->return_code = CXL_MBOX_CMD_RC_INPUT;
+ return -EINVAL;
+ }
+
+ ptr = (u8 *)&mdata->test_feat + offset;
+ memcpy((u8 *)output + offset, ptr, count);
+
+ return 0;
+}
+
+static int mock_get_feature(struct cxl_mockmem_data *mdata,
+ struct cxl_mbox_cmd *cmd)
+{
+ struct cxl_mbox_get_feat_in *input = cmd->payload_in;
+
+ if (uuid_equal(&input->uuid, &CXL_VENDOR_FEATURE_TEST))
+ return mock_get_test_feature(mdata, cmd);
+
+ cmd->return_code = CXL_MBOX_CMD_RC_UNSUPPORTED;
+
+ return -EOPNOTSUPP;
+}
+
static int mock_get_supported_features(struct cxl_mockmem_data *mdata,
struct cxl_mbox_cmd *cmd)
{
@@ -1509,6 +1556,9 @@ static int cxl_mock_mbox_send(struct cxl_mailbox *cxl_mbox,
case CXL_MBOX_OP_GET_SUPPORTED_FEATURES:
rc = mock_get_supported_features(mdata, cmd);
break;
+ case CXL_MBOX_OP_GET_FEATURE:
+ rc = mock_get_feature(mdata, cmd);
+ break;
default:
break;
}
@@ -1556,6 +1606,11 @@ static int cxl_mock_mailbox_create(struct cxl_dev_state *cxlds)
return 0;
}
+static void cxl_mock_test_feat_init(struct cxl_mockmem_data *mdata)
+{
+ mdata->test_feat.data = cpu_to_le32(0xdeadbeef);
+}
+
static int cxl_mock_mem_probe(struct platform_device *pdev)
{
struct device *dev = &pdev->dev;
@@ -1651,6 +1706,7 @@ static int cxl_mock_mem_probe(struct platform_device *pdev)
dev_dbg(dev, "No CXL FWCTL setup\n");
cxl_mem_get_event_records(mds, CXLDEV_EVENT_STATUS_ALL);
+ cxl_mock_test_feat_init(mdata);
return 0;
}
--
2.48.1
^ permalink raw reply related [flat|nested] 45+ messages in thread
* [PATCH v4 14/15] cxl/test: Add Set Feature support to cxl_test
2025-02-07 23:37 [PATCH v4 00/15] cxl: Add CXL feature commands support via fwctl Dave Jiang
` (12 preceding siblings ...)
2025-02-07 23:37 ` [PATCH v4 13/15] cxl/test: Add Get Feature support to cxl_test Dave Jiang
@ 2025-02-07 23:37 ` Dave Jiang
2025-02-10 6:44 ` Li Ming
2025-02-07 23:37 ` [PATCH v4 15/15] fwctl/cxl: Add documentation to FWCTL CXL Dave Jiang
14 siblings, 1 reply; 45+ messages in thread
From: Dave Jiang @ 2025-02-07 23:37 UTC (permalink / raw)
To: linux-cxl
Cc: dan.j.williams, ira.weiny, vishal.l.verma, alison.schofield,
Jonathan.Cameron, dave, jgg, shiju.jose
Add emulation to support Set Feature mailbox command to cxl_test.
The only feature supported is the device patrol scrub feature. The
set feature allows activation of patrol scrub for the cxl_test
emulated device. The command does not support partial data transfer
even though the spec allows it. This restriction is to reduce complexity
of the emulation given the patrol scrub feature is very minimal.
Reviewed-by: Jonathan Cameron <Jonathan.Cameron@huawei.com>
Reviewed-by: Dan Williams <dan.j.williams@intel.com>
Signed-off-by: Dave Jiang <dave.jiang@intel.com>
---
tools/testing/cxl/test/mem.c | 50 ++++++++++++++++++++++++++++++++++++
1 file changed, 50 insertions(+)
diff --git a/tools/testing/cxl/test/mem.c b/tools/testing/cxl/test/mem.c
index 0ada4a747bf3..0fc45d46ba69 100644
--- a/tools/testing/cxl/test/mem.c
+++ b/tools/testing/cxl/test/mem.c
@@ -52,6 +52,10 @@ static struct cxl_cel_entry mock_cel[] = {
.opcode = cpu_to_le16(CXL_MBOX_OP_GET_FEATURE),
.effect = CXL_CMD_EFFECT_NONE,
},
+ {
+ .opcode = cpu_to_le16(CXL_MBOX_OP_SET_FEATURE),
+ .effect = cpu_to_le16(EFFECT(CONF_CHANGE_IMMEDIATE)),
+ },
{
.opcode = cpu_to_le16(CXL_MBOX_OP_IDENTIFY),
.effect = CXL_CMD_EFFECT_NONE,
@@ -1426,6 +1430,49 @@ static int mock_get_feature(struct cxl_mockmem_data *mdata,
return -EOPNOTSUPP;
}
+static int mock_set_test_feature(struct cxl_mockmem_data *mdata,
+ struct cxl_mbox_cmd *cmd)
+{
+ struct cxl_mbox_set_feat_in *input = cmd->payload_in;
+ struct vendor_test_feat *test = (struct vendor_test_feat *)input->data;
+ u32 action;
+
+ action = FIELD_GET(CXL_SET_FEAT_FLAG_DATA_TRANSFER_MASK,
+ le32_to_cpu(input->hdr.flags));
+ /*
+ * While it is spec compliant to support other set actions, it is not
+ * necessary to add the complication in the emulation currently. Reject
+ * anything besides full xfer.
+ */
+ if (action != CXL_SET_FEAT_FLAG_FULL_DATA_TRANSFER) {
+ cmd->return_code = CXL_MBOX_CMD_RC_INPUT;
+ return -EINVAL;
+ }
+
+ /* Offset should be reserved when doing full transfer */
+ if (input->hdr.offset) {
+ cmd->return_code = CXL_MBOX_CMD_RC_INPUT;
+ return -EINVAL;
+ }
+
+ memcpy(&mdata->test_feat.data, &test->data, sizeof(u32));
+
+ return 0;
+}
+
+static int mock_set_feature(struct cxl_mockmem_data *mdata,
+ struct cxl_mbox_cmd *cmd)
+{
+ struct cxl_mbox_set_feat_in *input = cmd->payload_in;
+
+ if (uuid_equal(&input->hdr.uuid, &CXL_VENDOR_FEATURE_TEST))
+ return mock_set_test_feature(mdata, cmd);
+
+ cmd->return_code = CXL_MBOX_CMD_RC_UNSUPPORTED;
+
+ return -EOPNOTSUPP;
+}
+
static int mock_get_supported_features(struct cxl_mockmem_data *mdata,
struct cxl_mbox_cmd *cmd)
{
@@ -1559,6 +1606,9 @@ static int cxl_mock_mbox_send(struct cxl_mailbox *cxl_mbox,
case CXL_MBOX_OP_GET_FEATURE:
rc = mock_get_feature(mdata, cmd);
break;
+ case CXL_MBOX_OP_SET_FEATURE:
+ rc = mock_set_feature(mdata, cmd);
+ break;
default:
break;
}
--
2.48.1
^ permalink raw reply related [flat|nested] 45+ messages in thread
* [PATCH v4 15/15] fwctl/cxl: Add documentation to FWCTL CXL
2025-02-07 23:37 [PATCH v4 00/15] cxl: Add CXL feature commands support via fwctl Dave Jiang
` (13 preceding siblings ...)
2025-02-07 23:37 ` [PATCH v4 14/15] cxl/test: Add Set " Dave Jiang
@ 2025-02-07 23:37 ` Dave Jiang
2025-02-08 1:38 ` Dan Williams
14 siblings, 1 reply; 45+ messages in thread
From: Dave Jiang @ 2025-02-07 23:37 UTC (permalink / raw)
To: linux-cxl
Cc: dan.j.williams, ira.weiny, vishal.l.verma, alison.schofield,
Jonathan.Cameron, dave, jgg, shiju.jose
Add policy and operational documentation for FWCTL CXL.
Reviewed-by: Jonathan Cameron <Jonathan.Cameron@huawei.com>
Signed-off-by: Dave Jiang <dave.jiang@intel.com>
---
v4:
- Use imperative tone. (Dan)
---
.../userspace-api/fwctl/fwctl-cxl.rst | 137 ++++++++++++++++++
Documentation/userspace-api/fwctl/index.rst | 1 +
MAINTAINERS | 1 +
3 files changed, 139 insertions(+)
create mode 100644 Documentation/userspace-api/fwctl/fwctl-cxl.rst
diff --git a/Documentation/userspace-api/fwctl/fwctl-cxl.rst b/Documentation/userspace-api/fwctl/fwctl-cxl.rst
new file mode 100644
index 000000000000..84619d15c479
--- /dev/null
+++ b/Documentation/userspace-api/fwctl/fwctl-cxl.rst
@@ -0,0 +1,137 @@
+.. SPDX-License-Identifier: GPL-2.0
+
+================
+fwctl cxl driver
+================
+
+:Author: Dave Jiang
+
+Overview
+========
+
+The CXL spec defines a set of commands that can be issued to the mailbox of a
+CXL device or switch. It also left room for vendor specific commands to be
+issued to the mailbox as well. fwctl provides a path to issue a set of allowed
+mailbox commands from user space to the device moderated by the kernel driver.
+
+The following 3 commands will be used to support CXL Features:
+CXL spec r3.1 8.2.9.6.1 Get Supported Features (Opcode 0500h)
+CXL spec r3.1 8.2.9.6.2 Get Feature (Opcode 0501h)
+CXL spec r3.1 8.2.9.6.3 Set Feature (Opcode 0502h)
+
+The "Get Supported Features" return data may be filtered by the kernel driver to
+drop any features that are forbidden by the kernel or being exclusively used by
+the kernel. The driver will set the "Set Feature Size" of the "Get Supported
+Features Supported Feature Entry" to 0 to indicate that the Feature cannot be
+modified. The "Get Supported Features" command and the "Get Features" falls
+under the fwctl policy of FWCTL_RPC_CONFIGURATION.
+
+For "Set Feature" command, the access policy currently is broken down into two
+categories depending on the Set Feature effects reported by the device. If the
+Set Feature will cause immediate change to the device, the fwctl access policy
+must be FWCTL_RPC_DEBUG_WRITE_FULL. The effects for this level are
+"immediate config change", "immediate data change", "immediate policy change",
+or "immediate log change" for the set effects mask. If the effects are "config
+change with cold reset" or "config change with conventional reset", then the
+fwctl access policy must be FWCTL_RPC_DEBUG_WRITE or higher.
+
+fwctl cxl User API
+==================
+
+.. kernel-doc:: include/uapi/fwctl/cxl.h
+.. kernel-doc:: include/uapi/cxl/features.h
+
+1. Driver info query
+--------------------
+
+First step for the app is to issue the ioctl(FWCTL_CMD_INFO). Successful
+invocation of the ioctl implies the Features capability is operational and
+returns an all zeros 32bit payload. A ``struct fwctl_info`` needs to be filled
+out with the ``fwctl_info.out_device_type`` set to ``FWCTL_DEVICE_TYPE_CXL``.
+The return data should be ``struct fwctl_info_cxl`` that contains a reserved
+32bit field that should be all zeros.
+
+2. Send hardware commands
+-------------------------
+
+Next step is to send the 'Get Supported Features' command to the driver from
+user space via ioctl(FWCTL_RPC). A ``struct fwctl_rpc_cxl`` is pointed to
+by ``fwctl_rpc.in``. ``struct fwctl_rpc_cxl.in_payload`` points to
+the hardware input structure that is defined by the CXL spec. ``fwctl_rpc.out``
+points to the buffer that contains a ``struct fwctl_rpc_cxl_out`` that includes
+the hardware output data inlined as ``fwctl_rpc_cxl_out.payload``. This command
+is called twice. First time to retrieve the number of features supported.
+A second time to retrieve the specific feature details as the output data.
+
+After getting the specific feature details, a Get/Set Feature command can be
+appropriately programmed and sent. For a "Set Feature" command, the retrieved
+feature info contains an effects field that details the resulting
+"Set Feature" command will trigger. That will inform the user whether
+the system is configured to allowed the "Set Feature" command or not.
+
+Code example of a Get Feature
+~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+
+.. code-block:: c
+
+ static int cxl_fwctl_rpc_get_test_feature(int fd, struct test_feature *feat_ctx,
+ const uint32_t expected_data)
+ {
+ struct cxl_mbox_get_feat_in feat_in __attribute__((aligned(16))) = {0};
+ struct fwctl_rpc_cxl in __attribute__((aligned(16))) = {0};
+ struct fwctl_rpc_cxl_out *out;
+ struct fwctl_rpc rpc = {0};
+ size_t out_size;
+ uint32_t val;
+ void *data;
+ int rc;
+
+ uuid_copy(feat_in.uuid, feat_ctx->uuid);
+ feat_in.count = feat_ctx->get_size;
+
+ out_size = sizeof(*out) + feat_in.count;
+ out = aligned_alloc(16, out_size);
+ if (!out)
+ return -ENOMEM;
+
+ memset(out, 0, out_size);
+ data = out->payload;
+
+ in.opcode = CXL_MBOX_OPCODE_GET_FEATURE;
+ in.op_size = sizeof(feat_in);
+ in.in_payload = (uint64_t)(uint64_t *)&feat_in;
+
+ rpc.size = sizeof(rpc);
+ rpc.scope = FWCTL_RPC_CONFIGURATION;
+ rpc.in_len = sizeof(in);
+ rpc.out_len = out_size;
+ rpc.in = (uint64_t)(uint64_t *)∈
+ rpc.out = (uint64_t)(uint64_t *)out;
+
+ rc = send_command(fd, &rpc, out);
+ if (rc)
+ goto out;
+
+ val = le32toh(*(__le32 *)data);
+ if (memcmp(&val, &expected_data, sizeof(val)) != 0) {
+ rc = -ENXIO;
+ goto out;
+ }
+
+ out:
+ free(out);
+ return rc;
+ }
+
+Take a look at CXL CLI test directory
+<https://github.com/pmem/ndctl/tree/main/test/fwctl.c> for a detailed user code
+for examples on how to exercise this path.
+
+
+fwctl cxl Kernel API
+====================
+
+.. kernel-doc:: drivers/cxl/core/features.c
+.. kernel-doc:: drivers/cxl/features.c
+ :export:
+.. kernel-doc:: include/cxl/features.h
diff --git a/Documentation/userspace-api/fwctl/index.rst b/Documentation/userspace-api/fwctl/index.rst
index 06959fbf1547..d9d40a468a31 100644
--- a/Documentation/userspace-api/fwctl/index.rst
+++ b/Documentation/userspace-api/fwctl/index.rst
@@ -10,3 +10,4 @@ to securely construct and execute RPCs inside device firmware.
:maxdepth: 1
fwctl
+ fwctl-cxl
diff --git a/MAINTAINERS b/MAINTAINERS
index 413ab79bf2f4..b450c960687c 100644
--- a/MAINTAINERS
+++ b/MAINTAINERS
@@ -5837,6 +5837,7 @@ M: Dan Williams <dan.j.williams@intel.com>
L: linux-cxl@vger.kernel.org
S: Maintained
F: Documentation/driver-api/cxl
+F: Documentation/userspace-api/fwctl/fwctl-cxl.rst
F: drivers/cxl/
F: include/cxl/
F: include/uapi/linux/cxl_mem.h
--
2.48.1
^ permalink raw reply related [flat|nested] 45+ messages in thread
* Re: [PATCH v4 01/15] cxl: Enumerate feature commands
2025-02-07 23:37 ` [PATCH v4 01/15] cxl: Enumerate feature commands Dave Jiang
@ 2025-02-07 23:47 ` Dan Williams
2025-02-08 6:00 ` Li Ming
2025-02-11 17:05 ` Jonathan Cameron
2 siblings, 0 replies; 45+ messages in thread
From: Dan Williams @ 2025-02-07 23:47 UTC (permalink / raw)
To: Dave Jiang, linux-cxl
Cc: dan.j.williams, ira.weiny, vishal.l.verma, alison.schofield,
Jonathan.Cameron, dave, jgg, shiju.jose
Dave Jiang wrote:
> Add feature commands enumeration code in order to detect and enumerate
> the 3 feature related commands "get supported features", "get feature",
> and "set feature". The enumeration will help determine whether the driver
> can issue any of the 3 commands to the device.
>
> Signed-off-by: Dave Jiang <dave.jiang@intel.com>
Looks good to me.
Reviewed-by: Dan Williams <dan.j.williams@intel.com>
^ permalink raw reply [flat|nested] 45+ messages in thread
* Re: [PATCH v4 02/15] cxl: Add Get Supported Features command for kernel usage
2025-02-07 23:37 ` [PATCH v4 02/15] cxl: Add Get Supported Features command for kernel usage Dave Jiang
@ 2025-02-07 23:56 ` Dan Williams
2025-02-10 17:03 ` Dave Jiang
2025-02-08 6:13 ` Li Ming
1 sibling, 1 reply; 45+ messages in thread
From: Dan Williams @ 2025-02-07 23:56 UTC (permalink / raw)
To: Dave Jiang, linux-cxl
Cc: dan.j.williams, ira.weiny, vishal.l.verma, alison.schofield,
Jonathan.Cameron, dave, jgg, shiju.jose
Dave Jiang wrote:
> CXL spec r3.2 8.2.9.6.1 Get Supported Features (Opcode 0500h)
> The command retrieve the list of supported device-specific features
> (identified by UUID) and general information about each Feature.
>
> The driver will retrieve the Feature entries in order to make checks and
> provide information for the Get Feature and Set Feature command. One of
> the main piece of information retrieved are the effects a Set Feature
> command would have for a particular feature. The retrieved Feature
> entries are stored in the cxl_mailbox context.
>
> The setup of Features is initiated via devm_cxl_setup_features() during the
> pci probe function before the cxl_memdev is enumerated.
>
> Reviewed-by: Jonathan Cameron <Jonathan.Cameron@huawei.com>
> Signed-off-by: Dave Jiang <dave.jiang@intel.com>
[..]
> +/**
> + * devm_cxl_setup_features() - Allocate and initialize features context
> + * @cxlds: CXL device context
> + *
> + * Return 0 on success or -errno on failure.
> + */
> +int devm_cxl_setup_features(struct cxl_dev_state *cxlds)
> +{
> + struct cxl_mailbox *cxl_mbox = &cxlds->cxl_mbox;
> + int rc;
> +
> + if (cxl_mbox->feat_cap < CXL_FEATURES_RO)
> + return -ENODEV;
> +
> + struct cxl_features_state *cxlfs __free(kfree) =
> + kzalloc(sizeof(*cxlfs), GFP_KERNEL);
> + if (!cxlfs)
> + return -ENOMEM;
> +
> + cxlfs->cxlds = cxlds;
> +
> + cxlfs->entries = get_supported_features(cxlfs);
> + if (!cxlfs->entries)
> + return -ENOMEM;
> +
> + cxlds->cxlfs = cxlfs;
> + rc = devm_add_action_or_reset(cxlds->dev, free_cxlfs, no_free_ptr(cxlfs));
> + if (rc)
> + return rc;
> +
> + return 0;
One small cleanup you can do here when applying is reduce these last 5
lines to:
return devm_add_action_or_reset(cxlds->dev, free_cxlfs,
no_free_ptr(cxlfs));
[..]
> +/**
> + * struct cxl_features_state - The Features state for the device
> + * @cxlds: Pointer to CXL device state
> + * @cap: Feature commands capability
> + * @entries: CXl feature entry context
> + * @num_features: total Features supported by the device
> + * @ent: Flex array of Feature detail entries from the device
> + */
> +struct cxl_features_state {
> + struct cxl_dev_state *cxlds;
> + struct cxl_feat_entries {
> + int num_features;
> + struct cxl_feat_entry ent[] __counted_by(num_features);
> + } *entries;
> +};
> +
> +#ifdef CONFIG_CXL_FEATURES
> +inline struct cxl_features_state *to_cxlfs(struct cxl_dev_state *cxlds);
Shouldn't this be:
static inline struct cxl_features_state *to_cxlfs(struct cxl_dev_state *cxlds)
{
return cxlds->cxlfs;
}
...no need to do an out of line function for this.
Another small fixup you can do when applying.
Otherwise, this now all looks good to me:
Reviewed-by: Dan Williams <dan.j.williams@intel.com>
^ permalink raw reply [flat|nested] 45+ messages in thread
* Re: [PATCH v4 04/15] cxl/mbox: Add GET_FEATURE mailbox command
2025-02-07 23:37 ` [PATCH v4 04/15] cxl/mbox: Add GET_FEATURE mailbox command Dave Jiang
@ 2025-02-08 0:12 ` Dan Williams
0 siblings, 0 replies; 45+ messages in thread
From: Dan Williams @ 2025-02-08 0:12 UTC (permalink / raw)
To: Dave Jiang, linux-cxl
Cc: dan.j.williams, ira.weiny, vishal.l.verma, alison.schofield,
Jonathan.Cameron, dave, jgg, shiju.jose, Li Ming
Dave Jiang wrote:
> From: Shiju Jose <shiju.jose@huawei.com>
>
> Add support for GET_FEATURE mailbox command.
>
> CXL spec r3.2 section 8.2.9.6 describes optional device specific features.
> The settings of a feature can be retrieved using Get Feature command.
> CXL spec r3.2 section 8.2.9.6.2 describes Get Feature command.
>
> Reviewed-by: Jonathan Cameron <Jonathan.Cameron@huawei.com>
> Reviewed-by: Li Ming <ming.li@zohomail.com>
> Signed-off-by: Shiju Jose <shiju.jose@huawei.com>
> Signed-off-by: Dave Jiang <dave.jiang@intel.com>
> ---
> drivers/cxl/core/features.c | 50 +++++++++++++++++++++++++++++++++++++
> include/cxl/features.h | 37 +++++++++++++++++++++++++++
> 2 files changed, 87 insertions(+)
>
> diff --git a/drivers/cxl/core/features.c b/drivers/cxl/core/features.c
> index 77a0bf3a4916..262e4b1cb7fc 100644
> --- a/drivers/cxl/core/features.c
> +++ b/drivers/cxl/core/features.c
> @@ -177,3 +177,53 @@ int devm_cxl_setup_features(struct cxl_dev_state *cxlds)
> return 0;
> }
> EXPORT_SYMBOL_NS_GPL(devm_cxl_setup_features, "CXL");
> +
> +size_t cxl_get_feature(struct cxl_mailbox *cxl_mbox, const uuid_t *feat_uuid,
> + enum cxl_get_feat_selection selection,
> + void *feat_out, size_t feat_out_size, u16 offset,
> + u16 *return_code)
> +{
> + size_t data_to_rd_size, size_out;
> + struct cxl_mbox_get_feat_in pi;
> + struct cxl_mbox_cmd mbox_cmd;
> + size_t data_rcvd_size = 0;
> + int rc;
> +
> + if (return_code)
> + *return_code = CXL_MBOX_CMD_RC_INPUT;
> +
> + if (!feat_out || !feat_out_size)
> + return 0;
> +
> + size_out = min(feat_out_size, cxl_mbox->payload_size);
> + uuid_copy(&pi.uuid, feat_uuid);
> + pi.selection = selection;
> + do {
> + data_to_rd_size = min(feat_out_size - data_rcvd_size,
> + cxl_mbox->payload_size);
> + pi.offset = cpu_to_le16(offset + data_rcvd_size);
> + pi.count = cpu_to_le16(data_to_rd_size);
> +
> + mbox_cmd = (struct cxl_mbox_cmd) {
> + .opcode = CXL_MBOX_OP_GET_FEATURE,
> + .size_in = sizeof(pi),
> + .payload_in = &pi,
> + .size_out = size_out,
> + .payload_out = feat_out + data_rcvd_size,
> + .min_out = data_to_rd_size,
> + };
> + rc = cxl_internal_send_cmd(cxl_mbox, &mbox_cmd);
> + if (rc < 0 || !mbox_cmd.size_out) {
> + if (return_code)
> + *return_code = mbox_cmd.return_code;
> + return 0;
> + }
> + data_rcvd_size += mbox_cmd.size_out;
> + } while (data_rcvd_size < feat_out_size);
> +
> + if (return_code)
> + *return_code = CXL_MBOX_CMD_RC_SUCCESS;
> +
> + return data_rcvd_size;
> +}
> +EXPORT_SYMBOL_NS_GPL(cxl_get_feature, "CXL");
I don't think this needs to be exported. The only consumer in this
series is within drivers/cxl/core/features.c, and the EDAC consumer will
also be from within drivers/cxl/core/features.c with new exports for the
cxl_mem and cxl_region drivers to registers with EDAC.
> diff --git a/include/cxl/features.h b/include/cxl/features.h
> index e8861e690701..85036604fdba 100644
> --- a/include/cxl/features.h
> +++ b/include/cxl/features.h
> @@ -65,6 +65,29 @@ struct cxl_mbox_get_sup_feats_out {
> struct cxl_feat_entry ents[] __counted_by_le(num_entries);
> } __packed;
>
> +/*
> + * Get Feature CXL spec r3.2 Spec 8.2.9.6.2
> + */
> +
> +/*
> + * Get Feature input payload
> + * CXL spec r3.2 section 8.2.9.6.2 Table 8-99
> + */
> +struct cxl_mbox_get_feat_in {
> + uuid_t uuid;
> + __le16 offset;
> + __le16 count;
> + u8 selection;
> +} __packed;
> +
> +/* Selection field for 'struct cxl_mbox_get_feat_in' */
> +enum cxl_get_feat_selection {
> + CXL_GET_FEAT_SEL_CURRENT_VALUE,
> + CXL_GET_FEAT_SEL_DEFAULT_VALUE,
> + CXL_GET_FEAT_SEL_SAVED_VALUE,
> + CXL_GET_FEAT_SEL_MAX
> +};
> +
> /**
> * struct cxl_features_state - The Features state for the device
> * @cxlds: Pointer to CXL device state
> @@ -81,9 +104,14 @@ struct cxl_features_state {
> } *entries;
> };
>
> +struct cxl_mailbox;
> #ifdef CONFIG_CXL_FEATURES
> inline struct cxl_features_state *to_cxlfs(struct cxl_dev_state *cxlds);
> int devm_cxl_setup_features(struct cxl_dev_state *cxlds);
> +size_t cxl_get_feature(struct cxl_mailbox *cxl_mbox, const uuid_t *feat_uuid,
> + enum cxl_get_feat_selection selection,
> + void *feat_out, size_t feat_out_size, u16 offset,
> + u16 *return_code);
> #else
> static inline struct cxl_features_state *to_cxlfs(struct cxl_dev_state *cxlds)
> {
> @@ -94,6 +122,15 @@ static inline int devm_cxl_setup_features(struct cxl_dev_state *cxlds)
> {
> return -EOPNOTSUPP;
> }
> +
> +static inline size_t cxl_get_feature(struct cxl_mailbox *cxl_mbox,
> + const uuid_t *feat_uuid,
> + enum cxl_get_feat_selection selection,
> + void *feat_out, size_t feat_out_size,
> + u16 offset, u16 *return_code)
> +{
> + return 0;
> +}
With no callers external to drivers/cxl/core/features.c, this can also
go away.
I am fine if you just fix this up locally on applying.
Reviewed-by: Dan Williams <dan.j.williams@intel.com>
^ permalink raw reply [flat|nested] 45+ messages in thread
* Re: [PATCH v4 05/15] cxl/mbox: Add SET_FEATURE mailbox command
2025-02-07 23:37 ` [PATCH v4 05/15] cxl/mbox: Add SET_FEATURE " Dave Jiang
@ 2025-02-08 0:21 ` Dan Williams
2025-02-08 6:17 ` Li Ming
1 sibling, 0 replies; 45+ messages in thread
From: Dan Williams @ 2025-02-08 0:21 UTC (permalink / raw)
To: Dave Jiang, linux-cxl
Cc: dan.j.williams, ira.weiny, vishal.l.verma, alison.schofield,
Jonathan.Cameron, dave, jgg, shiju.jose
Dave Jiang wrote:
> From: Shiju Jose <shiju.jose@huawei.com>
>
> Add support for SET_FEATURE mailbox command.
>
> CXL spec r3.2 section 8.2.9.6 describes optional device specific features.
> CXL devices supports features with changeable attributes.
> The settings of a feature can be optionally modified using Set Feature
> command.
> CXL spec r3.2 section 8.2.9.6.3 describes Set Feature command.
>
> Reviewed-by: Jonathan Cameron <Jonathan.Cameron@huawei.com>
> Signed-off-by: Shiju Jose <shiju.jose@huawei.com>
> Signed-off-by: Dave Jiang <dave.jiang@intel.com>
> ---
> drivers/cxl/core/features.c | 81 +++++++++++++++++++++++++++++++++++++
> include/cxl/features.h | 42 +++++++++++++++++++
> 2 files changed, 123 insertions(+)
>
> diff --git a/drivers/cxl/core/features.c b/drivers/cxl/core/features.c
> index 262e4b1cb7fc..d337224158fa 100644
> --- a/drivers/cxl/core/features.c
> +++ b/drivers/cxl/core/features.c
> @@ -227,3 +227,84 @@ size_t cxl_get_feature(struct cxl_mailbox *cxl_mbox, const uuid_t *feat_uuid,
> return data_rcvd_size;
> }
> EXPORT_SYMBOL_NS_GPL(cxl_get_feature, "CXL");
> +
> +/*
> + * FEAT_DATA_MIN_PAYLOAD_SIZE - min extra number of bytes should be
> + * available in the mailbox for storing the actual feature data so that
> + * the feature data transfer would work as expected.
> + */
> +#define FEAT_DATA_MIN_PAYLOAD_SIZE 10
> +int cxl_set_feature(struct cxl_mailbox *cxl_mbox,
> + const uuid_t *feat_uuid, u8 feat_version,
> + void *feat_data, size_t feat_data_size,
> + u32 feat_flag, u16 offset, u16 *return_code)
> +{
> + struct cxl_memdev_set_feat_pi {
> + struct cxl_mbox_set_feat_hdr hdr;
> + u8 feat_data[];
> + } __packed;
> + size_t data_in_size, data_sent_size = 0;
> + struct cxl_mbox_cmd mbox_cmd;
> + size_t hdr_size;
> + int rc = 0;
> +
> + if (return_code)
> + *return_code = CXL_MBOX_CMD_RC_INPUT;
> +
> + struct cxl_memdev_set_feat_pi *pi __free(kfree) =
> + kzalloc(cxl_mbox->payload_size, GFP_KERNEL);
Missing NULL check on @pi?
[..]
> +}
> +EXPORT_SYMBOL_NS_GPL(cxl_set_feature, "CXL");
Same, "no need to export" comment as Get Feature.
Minor things to fixup, so feel free to add:
Reviewed-by: Dan Williams <dan.j.williams@intel.com>
^ permalink raw reply [flat|nested] 45+ messages in thread
* Re: [PATCH v4 06/15] cxl: Setup exclusive CXL features that are reserved for the kernel
2025-02-07 23:37 ` [PATCH v4 06/15] cxl: Setup exclusive CXL features that are reserved for the kernel Dave Jiang
@ 2025-02-08 1:10 ` Dan Williams
2025-02-08 1:16 ` Dave Jiang
2025-02-08 6:22 ` Li Ming
1 sibling, 1 reply; 45+ messages in thread
From: Dan Williams @ 2025-02-08 1:10 UTC (permalink / raw)
To: Dave Jiang, linux-cxl
Cc: dan.j.williams, ira.weiny, vishal.l.verma, alison.schofield,
Jonathan.Cameron, dave, jgg, shiju.jose
Dave Jiang wrote:
> Certain features will be exclusively used by components such as in
> kernel RAS driver. Setup an exclusion list that can be later filtered
> out before exposing to user space.
This last comment is stale, the list is not filtered in v4.
Other than that my tag still stands.
^ permalink raw reply [flat|nested] 45+ messages in thread
* Re: [PATCH v4 06/15] cxl: Setup exclusive CXL features that are reserved for the kernel
2025-02-08 1:10 ` Dan Williams
@ 2025-02-08 1:16 ` Dave Jiang
0 siblings, 0 replies; 45+ messages in thread
From: Dave Jiang @ 2025-02-08 1:16 UTC (permalink / raw)
To: Dan Williams, linux-cxl
Cc: ira.weiny, vishal.l.verma, alison.schofield, Jonathan.Cameron,
dave, jgg, shiju.jose
On 2/7/25 6:10 PM, Dan Williams wrote:
> Dave Jiang wrote:
>> Certain features will be exclusively used by components such as in
>> kernel RAS driver. Setup an exclusion list that can be later filtered
>> out before exposing to user space.
>
> This last comment is stale, the list is not filtered in v4.
I'll change it. In my mind, altering the entry is also filtering it.
>
> Other than that my tag still stands.
^ permalink raw reply [flat|nested] 45+ messages in thread
* Re: [PATCH v4 07/15] cxl: Add FWCTL support to CXL
2025-02-07 23:37 ` [PATCH v4 07/15] cxl: Add FWCTL support to CXL Dave Jiang
@ 2025-02-08 1:24 ` Dan Williams
0 siblings, 0 replies; 45+ messages in thread
From: Dan Williams @ 2025-02-08 1:24 UTC (permalink / raw)
To: Dave Jiang, linux-cxl
Cc: dan.j.williams, ira.weiny, vishal.l.verma, alison.schofield,
Jonathan.Cameron, dave, jgg, shiju.jose
Dave Jiang wrote:
> Add fwctl support code to allow sending of CXL feature commands from
> userspace through as ioctls via FWCTL. Provide initial setup bits. The
> CXL PCI probe function will call cxl_setup_fwctl() after the cxl_memdev
> has been enumerated in order to setup FWCTL char device under the
> cxl_memdev like the existing memdev char device for issuing CXL raw
> mailbox commands from userspace via ioctls.
>
> Signed-off-by: Dave Jiang <dave.jiang@intel.com>
> ---
> drivers/cxl/core/features.c | 74 ++++++++++++++++++++++++++++++++++++
> drivers/cxl/pci.c | 4 ++
> include/cxl/features.h | 14 +++++++
> include/uapi/fwctl/fwctl.h | 1 +
> tools/testing/cxl/test/mem.c | 4 ++
> 5 files changed, 97 insertions(+)
>
> diff --git a/drivers/cxl/core/features.c b/drivers/cxl/core/features.c
> index 82f21f64452a..81e8ff66c12e 100644
> --- a/drivers/cxl/core/features.c
> +++ b/drivers/cxl/core/features.c
> @@ -1,5 +1,6 @@
> // SPDX-License-Identifier: GPL-2.0-only
> /* Copyright(c) 2024-2025 Intel Corporation. All rights reserved. */
> +#include <linux/fwctl.h>
> #include <linux/device.h>
> #include <cxl/mailbox.h>
> #include <cxl/features.h>
> @@ -167,6 +168,13 @@ static void free_cxlfs(void *_cxlfs)
>
> cxlds->cxlfs = NULL;
> kvfree(cxlfs->entries);
> +
> + if (cxlfs->cxl_fwctl) {
> + struct cxl_fwctl *fwctl = cxlfs->cxl_fwctl;
> +
> + fwctl_unregister(&fwctl->fwctl_dev);
> + fwctl_put(&fwctl->fwctl_dev);
> + }
I think this is going to lead to use after free bugs.
Consider that this free_cxlfs() call is a devm action that was
registered *before* devm_cxl_add_memdev(). That means that the memdev
gets destroyed before fwctl is unregistered. That sounds like a recipe
for use after free bugs because userspace could still be using the fwctl
interface after the memdev has been unregistered.
More below...
[..]
> +DEFINE_FREE(free_fwctl, struct cxl_fwctl *, if (_T) fwctl_put(&_T->fwctl_dev))
> +
> +int cxl_setup_fwctl(struct cxl_memdev *cxlmd)
This needs to be devm_...
> +{
> + struct cxl_dev_state *cxlds = cxlmd->cxlds;
> + struct cxl_features_state *cxlfs;
> + int rc;
> +
> + cxlfs = to_cxlfs(cxlds);
> + if (!cxlfs)
> + return -ENODEV;
> +
> + /* No need to setup FWCTL if there are no user allowed features found */
> + if (!cxlfs->entries->num_user_features)
> + return -ENODEV;
> +
> + struct cxl_fwctl *fwctl __free(free_fwctl) =
> + fwctl_alloc_device(&cxlmd->dev, &cxlctl_ops,
> + struct cxl_fwctl, fwctl_dev);
> + if (!fwctl)
> + return -ENOMEM;
> +
> + fwctl->cxlmd = cxlmd;
> + rc = fwctl_register(&fwctl->fwctl_dev);
> + if (rc)
> + return rc;
...and a devm action needs to be registered here to make sure fwctl is
torn down before the memdev is torn down.
> +
> + cxlfs->cxl_fwctl = no_free_ptr(fwctl);
> +
> + return 0;
> +}
> +EXPORT_SYMBOL_NS_GPL(cxl_setup_fwctl, "CXL");
> +
> +MODULE_IMPORT_NS("FWCTL");
> diff --git a/drivers/cxl/pci.c b/drivers/cxl/pci.c
> index 3e666ec51580..b093cb16de3e 100644
> --- a/drivers/cxl/pci.c
> +++ b/drivers/cxl/pci.c
> @@ -1013,6 +1013,10 @@ static int cxl_pci_probe(struct pci_dev *pdev, const struct pci_device_id *id)
> if (rc)
> return rc;
>
> + rc = cxl_setup_fwctl(cxlmd);
> + if (rc)
> + dev_dbg(&pdev->dev, "No CXL FWCTL setup\n");
> +
> pmu_count = cxl_count_regblock(pdev, CXL_REGLOC_RBI_PMU);
> if (pmu_count < 0)
> return pmu_count;
> diff --git a/include/cxl/features.h b/include/cxl/features.h
> index 1ab97e676c03..d0c94756e452 100644
> --- a/include/cxl/features.h
> +++ b/include/cxl/features.h
> @@ -4,6 +4,7 @@
> #define __CXL_FEATURES_H__
>
> #include <linux/uuid.h>
> +#include <linux/fwctl.h>
>
> /* Feature UUIDs used by the kernel */
> #define CXL_FEAT_PATROL_SCRUB_UUID \
> @@ -158,6 +159,9 @@ enum cxl_set_feat_flag_data_transfer {
> * @entries: CXl feature entry context
> * @num_features: total Features supported by the device
> * @ent: Flex array of Feature detail entries from the device
> + * @fwctl: CXL Firmware Control context
> + * @fwctl_dev: Firmware Control device
> + * @cxlfs: Pointer to CXL Features state
> */
> struct cxl_features_state {
> struct cxl_dev_state *cxlds;
> @@ -166,12 +170,17 @@ struct cxl_features_state {
> int num_user_features;
> struct cxl_feat_entry ent[] __counted_by(num_features);
> } *entries;
> + struct cxl_fwctl {
> + struct fwctl_device fwctl_dev;
> + struct cxl_memdev *cxlmd;
Is this backpointer necessary?
Just look it up from the fwctl dev.
static inline struct cxl_memdev *fwctl_to_memdev(struct fwctl_device *fwctl_dev)
{
return to_cxl_memdev(fwctl_dev->dev.parent);
}
...then no need for 'struct cxl_fwctl' definition.
^ permalink raw reply [flat|nested] 45+ messages in thread
* Re: [PATCH v4 08/15] cxl: Add support for FWCTL get driver information callback
2025-02-07 23:37 ` [PATCH v4 08/15] cxl: Add support for FWCTL get driver information callback Dave Jiang
@ 2025-02-08 1:25 ` Dan Williams
2025-02-10 6:21 ` Li Ming
1 sibling, 0 replies; 45+ messages in thread
From: Dan Williams @ 2025-02-08 1:25 UTC (permalink / raw)
To: Dave Jiang, linux-cxl
Cc: dan.j.williams, ira.weiny, vishal.l.verma, alison.schofield,
Jonathan.Cameron, dave, jgg, shiju.jose
Dave Jiang wrote:
> Add definition for fwctl_ops->info() to return driver information. The
> function will return a data structure with a reserved u32. This is setup
> for future usages.
>
> Reviewed-by: Jonathan Cameron <Jonathan.Cameron@huawei.com>
> Signed-off-by: Dave Jiang <dave.jiang@intel.com>
LGTM
Reviewed-by: Dan Williams <dan.j.williams@intel.com>
^ permalink raw reply [flat|nested] 45+ messages in thread
* Re: [PATCH v4 10/15] cxl: Add support for fwctl RPC command to enable CXL feature commands
2025-02-07 23:37 ` [PATCH v4 10/15] cxl: Add support for fwctl RPC command to enable CXL feature commands Dave Jiang
@ 2025-02-08 1:29 ` Dan Williams
2025-02-08 1:34 ` Dan Williams
2025-02-08 7:09 ` Li Ming
2 siblings, 0 replies; 45+ messages in thread
From: Dan Williams @ 2025-02-08 1:29 UTC (permalink / raw)
To: Dave Jiang, linux-cxl
Cc: dan.j.williams, ira.weiny, vishal.l.verma, alison.schofield,
Jonathan.Cameron, dave, jgg, shiju.jose
Dave Jiang wrote:
> fwctl provides a fwctl_ops->fw_rpc() callback in order to issue ioctls
> to a device. The cxl fwctl driver will start by supporting the CXL
> Feature commands: Get Supported Features, Get Feature, and Set Feature.
>
> The fw_rpc() callback provides 'enum fwctl_rpc_scope' parameter where
> it indicates the security scope of the call. The Get Supported Features
> and Get Feature calls can be executed with the scope of
> FWCTL_RPC_CONFIGRATION. The Set Feature call is gated by the effects
> of the Feature reported by Get Supported Features call for the specific
> Feature.
>
> Only "Get Supported Features" is supported in this patch. Additional
> commands will be added in follow on patches. "Get Supported Features"
> will filter the Features that are exclusive to the kernel. The flag
> field of the Feature details will be cleared of the "Changeable"
> field and the "set feat size" will be set to 0 to indicate that
> the feature is not changeable.
>
> Signed-off-by: Dave Jiang <dave.jiang@intel.com>
This looks good now.
Reviewed-by: Dan Williams <dan.j.williams@intel.com>
^ permalink raw reply [flat|nested] 45+ messages in thread
* Re: [PATCH v4 10/15] cxl: Add support for fwctl RPC command to enable CXL feature commands
2025-02-07 23:37 ` [PATCH v4 10/15] cxl: Add support for fwctl RPC command to enable CXL feature commands Dave Jiang
2025-02-08 1:29 ` Dan Williams
@ 2025-02-08 1:34 ` Dan Williams
2025-02-08 7:09 ` Li Ming
2 siblings, 0 replies; 45+ messages in thread
From: Dan Williams @ 2025-02-08 1:34 UTC (permalink / raw)
To: Dave Jiang, linux-cxl
Cc: dan.j.williams, ira.weiny, vishal.l.verma, alison.schofield,
Jonathan.Cameron, dave, jgg, shiju.jose
Dave Jiang wrote:
> fwctl provides a fwctl_ops->fw_rpc() callback in order to issue ioctls
> to a device. The cxl fwctl driver will start by supporting the CXL
> Feature commands: Get Supported Features, Get Feature, and Set Feature.
>
> The fw_rpc() callback provides 'enum fwctl_rpc_scope' parameter where
> it indicates the security scope of the call. The Get Supported Features
> and Get Feature calls can be executed with the scope of
> FWCTL_RPC_CONFIGRATION. The Set Feature call is gated by the effects
> of the Feature reported by Get Supported Features call for the specific
> Feature.
>
> Only "Get Supported Features" is supported in this patch. Additional
> commands will be added in follow on patches. "Get Supported Features"
> will filter the Features that are exclusive to the kernel. The flag
> field of the Feature details will be cleared of the "Changeable"
> field and the "set feat size" will be set to 0 to indicate that
> the feature is not changeable.
>
> Signed-off-by: Dave Jiang <dave.jiang@intel.com>
[..]
> +/* command_id for CXL mailbox Feature commands */
> +enum feature_cmds {
> + CXL_FEATURE_ID_GET_SUPPORTED_FEATURES = 0,
> + CXL_FEATURE_ID_GET_FEATURE,
> + CXL_FEATURE_ID_SET_FEATURE,
> + CXL_FEATURE_ID_MAX
> +};
Btw, these values are unused now.
^ permalink raw reply [flat|nested] 45+ messages in thread
* Re: [PATCH v4 15/15] fwctl/cxl: Add documentation to FWCTL CXL
2025-02-07 23:37 ` [PATCH v4 15/15] fwctl/cxl: Add documentation to FWCTL CXL Dave Jiang
@ 2025-02-08 1:38 ` Dan Williams
0 siblings, 0 replies; 45+ messages in thread
From: Dan Williams @ 2025-02-08 1:38 UTC (permalink / raw)
To: Dave Jiang, linux-cxl
Cc: dan.j.williams, ira.weiny, vishal.l.verma, alison.schofield,
Jonathan.Cameron, dave, jgg, shiju.jose
Dave Jiang wrote:
> Add policy and operational documentation for FWCTL CXL.
>
> Reviewed-by: Jonathan Cameron <Jonathan.Cameron@huawei.com>
> Signed-off-by: Dave Jiang <dave.jiang@intel.com>
[..]
> +Code example of a Get Feature
> +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
> +
> +.. code-block:: c
> +
> + static int cxl_fwctl_rpc_get_test_feature(int fd, struct test_feature *feat_ctx,
> + const uint32_t expected_data)
> + {
> + struct cxl_mbox_get_feat_in feat_in __attribute__((aligned(16))) = {0};
> + struct fwctl_rpc_cxl in __attribute__((aligned(16))) = {0};
> + struct fwctl_rpc_cxl_out *out;
> + struct fwctl_rpc rpc = {0};
> + size_t out_size;
> + uint32_t val;
> + void *data;
> + int rc;
> +
> + uuid_copy(feat_in.uuid, feat_ctx->uuid);
> + feat_in.count = feat_ctx->get_size;
> +
> + out_size = sizeof(*out) + feat_in.count;
> + out = aligned_alloc(16, out_size);
> + if (!out)
> + return -ENOMEM;
> +
> + memset(out, 0, out_size);
> + data = out->payload;
> +
> + in.opcode = CXL_MBOX_OPCODE_GET_FEATURE;
Oh, this went a bit further than I expected, but I think its fine to not
have fwctl command ids to wrap the Feature opcodes.
You can add:
Reviewed-by: Dan Williams <dan.j.williams@intel.com>
...and if we ever decide to expand the operations that fwctl supports
just need to be careful about aliasing.
^ permalink raw reply [flat|nested] 45+ messages in thread
* Re: [PATCH v4 01/15] cxl: Enumerate feature commands
2025-02-07 23:37 ` [PATCH v4 01/15] cxl: Enumerate feature commands Dave Jiang
2025-02-07 23:47 ` Dan Williams
@ 2025-02-08 6:00 ` Li Ming
2025-02-11 17:05 ` Jonathan Cameron
2 siblings, 0 replies; 45+ messages in thread
From: Li Ming @ 2025-02-08 6:00 UTC (permalink / raw)
To: Dave Jiang, linux-cxl
Cc: dan.j.williams, ira.weiny, vishal.l.verma, alison.schofield,
Jonathan.Cameron, dave, jgg, shiju.jose
On 2/8/2025 7:37 AM, Dave Jiang wrote:
> Add feature commands enumeration code in order to detect and enumerate
> the 3 feature related commands "get supported features", "get feature",
> and "set feature". The enumeration will help determine whether the driver
> can issue any of the 3 commands to the device.
>
> Signed-off-by: Dave Jiang <dave.jiang@intel.com>
Reviewed-by: Li Ming <ming.li@zohomail.com>
^ permalink raw reply [flat|nested] 45+ messages in thread
* Re: [PATCH v4 02/15] cxl: Add Get Supported Features command for kernel usage
2025-02-07 23:37 ` [PATCH v4 02/15] cxl: Add Get Supported Features command for kernel usage Dave Jiang
2025-02-07 23:56 ` Dan Williams
@ 2025-02-08 6:13 ` Li Ming
2025-02-10 17:06 ` Dave Jiang
1 sibling, 1 reply; 45+ messages in thread
From: Li Ming @ 2025-02-08 6:13 UTC (permalink / raw)
To: Dave Jiang, linux-cxl
Cc: dan.j.williams, ira.weiny, vishal.l.verma, alison.schofield,
Jonathan.Cameron, dave, jgg, shiju.jose
On 2/8/2025 7:37 AM, Dave Jiang wrote:
> CXL spec r3.2 8.2.9.6.1 Get Supported Features (Opcode 0500h)
> The command retrieve the list of supported device-specific features
> (identified by UUID) and general information about each Feature.
>
> The driver will retrieve the Feature entries in order to make checks and
> provide information for the Get Feature and Set Feature command. One of
> the main piece of information retrieved are the effects a Set Feature
> command would have for a particular feature. The retrieved Feature
> entries are stored in the cxl_mailbox context.
>
> The setup of Features is initiated via devm_cxl_setup_features() during the
> pci probe function before the cxl_memdev is enumerated.
>
> Reviewed-by: Jonathan Cameron <Jonathan.Cameron@huawei.com>
> Signed-off-by: Dave Jiang <dave.jiang@intel.com>
[...]
> +static struct cxl_feat_entries *
> +get_supported_features(struct cxl_features_state *cxlfs)
> +{
> + int remain_feats, max_size, max_feats, start, rc, hdr_size;
> + struct cxl_mailbox *cxl_mbox = &cxlfs->cxlds->cxl_mbox;
> + int feat_size = sizeof(struct cxl_feat_entry);
> + struct cxl_mbox_get_sup_feats_in mbox_in;
> + struct cxl_feat_entry *entry;
> + struct cxl_mbox_cmd mbox_cmd;
> + int count;
> +
> + count = cxl_get_supported_features_count(cxl_mbox);
> + if (count <= 0)
> + return NULL;
> +
> + struct cxl_feat_entries *entries __free(kvfree) =
> + kvmalloc(struct_size(entries, ent, count), GFP_KERNEL);
> + if (!entries)
> + return NULL;
> +
> + struct cxl_mbox_get_sup_feats_out *mbox_out __free(kvfree) =
> + kvmalloc(cxl_mbox->payload_size, GFP_KERNEL);
> + if (!mbox_out)
> + return NULL;
> +
> + hdr_size = struct_size(mbox_out, ents, 0);
> + max_size = cxl_mbox->payload_size - hdr_size;
> + /* max feat entries that can fit in mailbox max payload size */
> + max_feats = max_size / feat_size;
> + entry = entries->ent;
> +
> + start = 0;
> + remain_feats = count;
> + do {
> + int retrieved, alloc_size, copy_feats;
> + int num_entries;
> +
> + if (remain_feats > max_feats) {
> + alloc_size = struct_size(mbox_out, ents, max_feats);
> + remain_feats = remain_feats - max_feats;
> + copy_feats = max_feats;
> + } else {
> + alloc_size = struct_size(mbox_out, ents, remain_feats);
> + copy_feats = remain_feats;
> + remain_feats = 0;
> + }
> +
> + memset(&mbox_in, 0, sizeof(mbox_in));
> + mbox_in.count = cpu_to_le32(alloc_size);
> + mbox_in.start_idx = cpu_to_le16(start);
> + memset(mbox_out, 0, alloc_size);
> + mbox_cmd = (struct cxl_mbox_cmd) {
> + .opcode = CXL_MBOX_OP_GET_SUPPORTED_FEATURES,
> + .size_in = sizeof(mbox_in),
> + .payload_in = &mbox_in,
> + .size_out = alloc_size,
> + .payload_out = mbox_out,
> + .min_out = hdr_size,
> + };
> + rc = cxl_internal_send_cmd(cxl_mbox, &mbox_cmd);
> + if (rc < 0)
> + return ERR_PTR(rc);
Should return NULL here?
> +
> + if (mbox_cmd.size_out <= hdr_size)
> + return NULL;
> +
> + /*
> + * Make sure retrieved out buffer is multiple of feature
> + * entries.
> + */
> + retrieved = mbox_cmd.size_out - hdr_size;
> + if (retrieved % feat_size)
> + return NULL;
> +
> + num_entries = le16_to_cpu(mbox_out->num_entries);
> + /*
> + * If the reported output entries * defined entry size !=
> + * retrieved output bytes, then the output package is incorrect.
> + */
> + if (num_entries * feat_size != retrieved)
> + return NULL;
> +
> + memcpy(entry, mbox_out->ents, retrieved);
> + entry += num_entries;
> + /*
> + * If the number of output entries is less than expected, add the
> + * remaining entries to the next batch.
> + */
> + remain_feats += copy_feats - num_entries;
> + start += num_entries;
> + } while (remain_feats);
> +
> + entries->num_features = count;
> +
> + return no_free_ptr(entries);
> +}
> +
> +static void free_cxlfs(void *_cxlfs)
> +{
> + struct cxl_features_state *cxlfs = _cxlfs;
> + struct cxl_dev_state *cxlds = cxlfs->cxlds;
> +
> + cxlds->cxlfs = NULL;
> + kvfree(cxlfs->entries);
> + kfree(cxlfs);
> +}
> +
> +/**
> + * devm_cxl_setup_features() - Allocate and initialize features context
> + * @cxlds: CXL device context
> + *
> + * Return 0 on success or -errno on failure.
> + */
> +int devm_cxl_setup_features(struct cxl_dev_state *cxlds)
> +{
> + struct cxl_mailbox *cxl_mbox = &cxlds->cxl_mbox;
> + int rc;
> +
> + if (cxl_mbox->feat_cap < CXL_FEATURES_RO)
> + return -ENODEV;
> +
> + struct cxl_features_state *cxlfs __free(kfree) =
> + kzalloc(sizeof(*cxlfs), GFP_KERNEL);
> + if (!cxlfs)
> + return -ENOMEM;
> +
> + cxlfs->cxlds = cxlds;
> +
> + cxlfs->entries = get_supported_features(cxlfs);
> + if (!cxlfs->entries)
> + return -ENOMEM;
It will be a problem if the above cxl_internal_send_cmd() in get_supported_features() returns a "ERR_PTR(rc)". My understanding is the cxl_internal_send_cmd() should return a NULL in failure cases.
Other looks good to me.
Reviewed-by: Li Ming <ming.li@zohomail.com>
^ permalink raw reply [flat|nested] 45+ messages in thread
* Re: [PATCH v4 05/15] cxl/mbox: Add SET_FEATURE mailbox command
2025-02-07 23:37 ` [PATCH v4 05/15] cxl/mbox: Add SET_FEATURE " Dave Jiang
2025-02-08 0:21 ` Dan Williams
@ 2025-02-08 6:17 ` Li Ming
1 sibling, 0 replies; 45+ messages in thread
From: Li Ming @ 2025-02-08 6:17 UTC (permalink / raw)
To: Dave Jiang, linux-cxl
Cc: dan.j.williams, ira.weiny, vishal.l.verma, alison.schofield,
Jonathan.Cameron, dave, jgg, shiju.jose
On 2/8/2025 7:37 AM, Dave Jiang wrote:
> From: Shiju Jose <shiju.jose@huawei.com>
>
> Add support for SET_FEATURE mailbox command.
>
> CXL spec r3.2 section 8.2.9.6 describes optional device specific features.
> CXL devices supports features with changeable attributes.
> The settings of a feature can be optionally modified using Set Feature
> command.
> CXL spec r3.2 section 8.2.9.6.3 describes Set Feature command.
>
> Reviewed-by: Jonathan Cameron <Jonathan.Cameron@huawei.com>
> Signed-off-by: Shiju Jose <shiju.jose@huawei.com>
> Signed-off-by: Dave Jiang <dave.jiang@intel.com>
Reviewed-by: Li Ming <ming.li@zohomail.com>
^ permalink raw reply [flat|nested] 45+ messages in thread
* Re: [PATCH v4 06/15] cxl: Setup exclusive CXL features that are reserved for the kernel
2025-02-07 23:37 ` [PATCH v4 06/15] cxl: Setup exclusive CXL features that are reserved for the kernel Dave Jiang
2025-02-08 1:10 ` Dan Williams
@ 2025-02-08 6:22 ` Li Ming
2025-02-10 17:40 ` Dave Jiang
2025-02-10 17:50 ` Dave Jiang
1 sibling, 2 replies; 45+ messages in thread
From: Li Ming @ 2025-02-08 6:22 UTC (permalink / raw)
To: Dave Jiang, linux-cxl
Cc: dan.j.williams, ira.weiny, vishal.l.verma, alison.schofield,
Jonathan.Cameron, dave, jgg, shiju.jose
On 2/8/2025 7:37 AM, Dave Jiang wrote:
> Certain features will be exclusively used by components such as in
> kernel RAS driver. Setup an exclusion list that can be later filtered
> out before exposing to user space.
>
> Reviewed-by: Jonathan Cameron <Jonathan.Cameron@huawei.com>
> Reviewed-by: Dan Williams <dan.j.williams@intel.com>
> Signed-off-by: Dave Jiang <dave.jiang@intel.com>
> ---
> drivers/cxl/core/features.c | 26 ++++++++++++++++++++++++++
> include/cxl/features.h | 34 ++++++++++++++++++++++++++++++++++
> 2 files changed, 60 insertions(+)
>
> diff --git a/drivers/cxl/core/features.c b/drivers/cxl/core/features.c
> index d337224158fa..82f21f64452a 100644
> --- a/drivers/cxl/core/features.c
> +++ b/drivers/cxl/core/features.c
> @@ -6,6 +6,28 @@
> #include "cxl.h"
> #include "cxlmem.h"
>
> +/* All the features below are exclusive to the kernel */
> +static const uuid_t cxl_exclusive_feats[] = {
> + CXL_FEAT_PATROL_SCRUB_UUID,
> + CXL_FEAT_ECS_UUID,
> + CXL_FEAT_SPPR_UUID,
> + CXL_FEAT_HPPR_UUID,
> + CXL_FEAT_CACHELINE_SPARING_UUID,
> + CXL_FEAT_ROW_SPARING_UUID,
> + CXL_FEAT_BANK_SPARING_UUID,
> + CXL_FEAT_RANK_SPARING_UUID,
> +};
> +
> +static bool is_cxl_feature_exclusive(struct cxl_feat_entry *entry)
> +{
> + for (int i = 0; i < ARRAY_SIZE(cxl_exclusive_feats); i++) {
> + if (uuid_equal(&entry->uuid, &cxl_exclusive_feats[i]))
> + return true;
> + }
> +
> + return false;
> +}
> +
> inline struct cxl_features_state *to_cxlfs(struct cxl_dev_state *cxlds)
> {
> return cxlds->cxlfs;
> @@ -46,6 +68,7 @@ get_supported_features(struct cxl_features_state *cxlfs)
> struct cxl_mbox_get_sup_feats_in mbox_in;
> struct cxl_feat_entry *entry;
> struct cxl_mbox_cmd mbox_cmd;
> + int user_feats = 0;
> int count;
>
> count = cxl_get_supported_features_count(cxl_mbox);
> @@ -120,6 +143,8 @@ get_supported_features(struct cxl_features_state *cxlfs)
> return NULL;
>
> memcpy(entry, mbox_out->ents, retrieved);
> + if (!is_cxl_feature_exclusive(entry))
> + user_feats++;
I guess that here should check all entries copied from mbox_out->ents, so it should be
for (int i = 0; i < num_entries; i++)
if (!is_cxl_feature_exclusive(entry + i))
user_feats++;
Other looks good to me.
Reviewed-by: Li Ming <ming.li@zohomail.com>
> entry += num_entries;
> /*
> * If the number of output entries is less than expected, add the
> @@ -130,6 +155,7 @@ get_supported_features(struct cxl_features_state *cxlfs)
> } while (remain_feats);
>
> entries->num_features = count;
> + entries->num_user_features = user_feats;
>
> return no_free_ptr(entries);
> }
^ permalink raw reply [flat|nested] 45+ messages in thread
* Re: [PATCH v4 10/15] cxl: Add support for fwctl RPC command to enable CXL feature commands
2025-02-07 23:37 ` [PATCH v4 10/15] cxl: Add support for fwctl RPC command to enable CXL feature commands Dave Jiang
2025-02-08 1:29 ` Dan Williams
2025-02-08 1:34 ` Dan Williams
@ 2025-02-08 7:09 ` Li Ming
2025-02-10 22:31 ` Dave Jiang
2 siblings, 1 reply; 45+ messages in thread
From: Li Ming @ 2025-02-08 7:09 UTC (permalink / raw)
To: Dave Jiang, linux-cxl
Cc: dan.j.williams, ira.weiny, vishal.l.verma, alison.schofield,
Jonathan.Cameron, dave, jgg, shiju.jose
On 2/8/2025 7:37 AM, Dave Jiang wrote:
> fwctl provides a fwctl_ops->fw_rpc() callback in order to issue ioctls
> to a device. The cxl fwctl driver will start by supporting the CXL
> Feature commands: Get Supported Features, Get Feature, and Set Feature.
>
> The fw_rpc() callback provides 'enum fwctl_rpc_scope' parameter where
> it indicates the security scope of the call. The Get Supported Features
> and Get Feature calls can be executed with the scope of
> FWCTL_RPC_CONFIGRATION. The Set Feature call is gated by the effects
> of the Feature reported by Get Supported Features call for the specific
> Feature.
>
> Only "Get Supported Features" is supported in this patch. Additional
> commands will be added in follow on patches. "Get Supported Features"
> will filter the Features that are exclusive to the kernel. The flag
> field of the Feature details will be cleared of the "Changeable"
> field and the "set feat size" will be set to 0 to indicate that
> the feature is not changeable.
>
> Signed-off-by: Dave Jiang <dave.jiang@intel.com>
> ---
> v4:
> - Use opcode directly instead of command ids. (Dan)
> - Add check for no immediate effects and no reset effects. (Dan, Jonathan)
> - Add check for Set Features to have CXL_FEATURES_RW cap.
> - Add clearing of the "Changeable" bit in the flags for exclusive features.
> ---
> drivers/cxl/core/features.c | 221 +++++++++++++++++++++++++++++++++++-
> include/uapi/cxl/features.h | 1 +
> include/uapi/fwctl/cxl.h | 37 ++++++
> 3 files changed, 257 insertions(+), 2 deletions(-)
>
> diff --git a/drivers/cxl/core/features.c b/drivers/cxl/core/features.c
> index b2836b951360..2682067dd2d7 100644
> --- a/drivers/cxl/core/features.c
> +++ b/drivers/cxl/core/features.c
> @@ -365,11 +365,228 @@ static void *cxlctl_info(struct fwctl_uctx *uctx, size_t *length)
> return info;
> }
>
> +static struct cxl_feat_entry *
> +get_support_feature_info(struct cxl_features_state *cxlfs,
> + const struct fwctl_rpc_cxl *rpc_in)
> +{
> + struct cxl_feat_entry *feat;
> + uuid_t uuid;
> +
> + if (rpc_in->op_size < sizeof(uuid))
> + return ERR_PTR(-EINVAL);
> +
> + if (copy_from_user(&uuid, u64_to_user_ptr(rpc_in->in_payload),
> + sizeof(uuid)))
> + return ERR_PTR(-EFAULT);
> +
> + for (int i = 0; i < cxlfs->entries->num_features; i++) {
> + feat = &cxlfs->entries->ent[i];
> + if (uuid_equal(&uuid, &feat->uuid))
> + return feat;
> + }
> +
> + return ERR_PTR(-EINVAL);
> +}
> +
> +static void *cxlctl_get_supported_features(struct cxl_features_state *cxlfs,
> + const struct fwctl_rpc_cxl *rpc_in,
> + size_t *out_len)
> +{
> + struct cxl_mbox_get_sup_feats_out *feat_out;
> + struct cxl_mbox_get_sup_feats_in feat_in;
> + struct cxl_feat_entry *pos;
> + size_t out_size;
> + int requested;
> + u32 count;
> + u16 start;
> + int i;
> +
> + if (rpc_in->op_size != sizeof(feat_in))
> + return ERR_PTR(-EINVAL);
> +
> + if (copy_from_user(&feat_in, u64_to_user_ptr(rpc_in->in_payload),
> + rpc_in->op_size))
> + return ERR_PTR(-EFAULT);
> +
> + count = le32_to_cpu(feat_in.count);
> + start = le16_to_cpu(feat_in.start_idx);
> + requested = count / sizeof(*pos);
> +
> + /*
> + * Make sure that the total requested number of entries is not greater
> + * than the total number of supported features allowed for userspace.
> + */
> + if (start >= cxlfs->entries->num_features)
> + return ERR_PTR(-EINVAL);
> +
> + requested = min_t(int, requested, cxlfs->entries->num_features - start);
> +
> + out_size = sizeof(struct fwctl_rpc_cxl_out) +
> + struct_size(feat_out, ents, requested);
> +
> + struct fwctl_rpc_cxl_out *rpc_out __free(kvfree) =
> + kvzalloc(out_size, GFP_KERNEL);
> + if (!rpc_out)
> + return ERR_PTR(-ENOMEM);
> +
> + rpc_out->size = struct_size(feat_out, ents, requested);
> + feat_out = (struct cxl_mbox_get_sup_feats_out *)rpc_out->payload;
> + if (requested == 0) {
> + feat_out->num_entries = cpu_to_le16(requested);
> + feat_out->supported_feats =
> + cpu_to_le16(cxlfs->entries->num_features);
> + rpc_out->retval = CXL_MBOX_CMD_RC_SUCCESS;
> + *out_len = out_size;
> + return no_free_ptr(rpc_out);
> + }
> +
> + for (i = 0, pos = &feat_out->ents[0];
> + i < cxlfs->entries->num_features; i++, pos++) {
My understanding is that 'i' should start from the value of the 'start' got from 'feat_in.start_idx'.
Please correct me if I'm wrong.
Ming
> + if (i == requested)
> + break;
> +
> + memcpy(pos, &cxlfs->entries->ent[i], sizeof(*pos));
> + /*
> + * If the feature is exclusive, set the set_feat_size to 0 to
> + * indicate that the feature is not changeable.
> + */
> + if (is_cxl_feature_exclusive(pos)) {
> + u32 flags;
> +
> + pos->set_feat_size = 0;
> + flags = le32_to_cpu(pos->flags);
> + flags &= ~CXL_FEATURE_F_CHANGEABLE;
> + pos->flags = cpu_to_le32(flags);
> + }
> + }
> +
> + feat_out->num_entries = cpu_to_le16(requested);
> + feat_out->supported_feats = cpu_to_le16(cxlfs->entries->num_features);
> + rpc_out->retval = CXL_MBOX_CMD_RC_SUCCESS;
> + *out_len = out_size;
> +
> + return no_free_ptr(rpc_out);
> +}
> +
[...]
^ permalink raw reply [flat|nested] 45+ messages in thread
* Re: [PATCH v4 08/15] cxl: Add support for FWCTL get driver information callback
2025-02-07 23:37 ` [PATCH v4 08/15] cxl: Add support for FWCTL get driver information callback Dave Jiang
2025-02-08 1:25 ` Dan Williams
@ 2025-02-10 6:21 ` Li Ming
1 sibling, 0 replies; 45+ messages in thread
From: Li Ming @ 2025-02-10 6:21 UTC (permalink / raw)
To: Dave Jiang, linux-cxl
Cc: dan.j.williams, ira.weiny, vishal.l.verma, alison.schofield,
Jonathan.Cameron, dave, jgg, shiju.jose
On 2/8/2025 7:37 AM, Dave Jiang wrote:
> Add definition for fwctl_ops->info() to return driver information. The
> function will return a data structure with a reserved u32. This is setup
> for future usages.
>
> Reviewed-by: Jonathan Cameron <Jonathan.Cameron@huawei.com>
> Signed-off-by: Dave Jiang <dave.jiang@intel.com>
Reviewed-by: Li Ming <ming.li@zohomail.com>
^ permalink raw reply [flat|nested] 45+ messages in thread
* Re: [PATCH v4 11/15] cxl: Add support to handle user feature commands for get feature
2025-02-07 23:37 ` [PATCH v4 11/15] cxl: Add support to handle user feature commands for get feature Dave Jiang
@ 2025-02-10 6:41 ` Li Ming
0 siblings, 0 replies; 45+ messages in thread
From: Li Ming @ 2025-02-10 6:41 UTC (permalink / raw)
To: Dave Jiang
Cc: dan.j.williams, ira.weiny, vishal.l.verma, alison.schofield,
Jonathan.Cameron, dave, jgg, shiju.jose, linux-cxl
On 2/8/2025 7:37 AM, Dave Jiang wrote:
> Add helper function to parse the user data from fwctl RPC ioctl and
> send the parsed input parameters to cxl_get_feature() call.
>
> Reviewed-by: Jonathan Cameron <Jonathan.Cameron@huawei.com>
> Reviewed-by: Dan Williams <dan.j.williams@intel.com>
> Signed-off-by: Dave Jiang <dave.jiang@intel.com>
Reviewed-by: Li Ming <ming.li@zohomail.com>
^ permalink raw reply [flat|nested] 45+ messages in thread
* Re: [PATCH v4 12/15] cxl: Add support to handle user feature commands for set feature
2025-02-07 23:37 ` [PATCH v4 12/15] cxl: Add support to handle user feature commands for set feature Dave Jiang
@ 2025-02-10 6:43 ` Li Ming
0 siblings, 0 replies; 45+ messages in thread
From: Li Ming @ 2025-02-10 6:43 UTC (permalink / raw)
To: Dave Jiang
Cc: dan.j.williams, ira.weiny, vishal.l.verma, alison.schofield,
Jonathan.Cameron, dave, jgg, shiju.jose, linux-cxl
On 2/8/2025 7:37 AM, Dave Jiang wrote:
> Add helper function to parse the user data from fwctl RPC ioctl and
> send the parsed input parameters to cxl_set_feature() call.
>
> Reviewed-by: Jonathan Cameron <Jonathan.Cameron@huawei.com>
> Reviewed-by: Dan Williams <dan.j.williams@intel.com>
> Signed-off-by: Dave Jiang <dave.jiang@intel.com>
Reviewed-by: Li Ming <ming.li@zohomail.com>
^ permalink raw reply [flat|nested] 45+ messages in thread
* Re: [PATCH v4 13/15] cxl/test: Add Get Feature support to cxl_test
2025-02-07 23:37 ` [PATCH v4 13/15] cxl/test: Add Get Feature support to cxl_test Dave Jiang
@ 2025-02-10 6:44 ` Li Ming
0 siblings, 0 replies; 45+ messages in thread
From: Li Ming @ 2025-02-10 6:44 UTC (permalink / raw)
To: Dave Jiang
Cc: dan.j.williams, ira.weiny, vishal.l.verma, alison.schofield,
Jonathan.Cameron, dave, jgg, shiju.jose, linux-cxl
On 2/8/2025 7:37 AM, Dave Jiang wrote:
> Add emulation of Get Feature command to cxl_test. The feature for
> device patrol scrub is returned by the emulation code. This is
> the only feature currently supported by cxl_test. It returns
> the information for the device patrol scrub feature.
>
> Reviewed-by: Jonathan Cameron <Jonathan.Cameron@huawei.com>
> Reviewed-by: Dan Williams <dan.j.williams@intel.com>
> Signed-off-by: Dave Jiang <dave.jiang@intel.com>
Reviewed-by: Li Ming <ming.li@zohomail.com>
^ permalink raw reply [flat|nested] 45+ messages in thread
* Re: [PATCH v4 14/15] cxl/test: Add Set Feature support to cxl_test
2025-02-07 23:37 ` [PATCH v4 14/15] cxl/test: Add Set " Dave Jiang
@ 2025-02-10 6:44 ` Li Ming
0 siblings, 0 replies; 45+ messages in thread
From: Li Ming @ 2025-02-10 6:44 UTC (permalink / raw)
To: Dave Jiang
Cc: dan.j.williams, ira.weiny, vishal.l.verma, alison.schofield,
Jonathan.Cameron, dave, jgg, shiju.jose, linux-cxl
On 2/8/2025 7:37 AM, Dave Jiang wrote:
> Add emulation to support Set Feature mailbox command to cxl_test.
> The only feature supported is the device patrol scrub feature. The
> set feature allows activation of patrol scrub for the cxl_test
> emulated device. The command does not support partial data transfer
> even though the spec allows it. This restriction is to reduce complexity
> of the emulation given the patrol scrub feature is very minimal.
>
> Reviewed-by: Jonathan Cameron <Jonathan.Cameron@huawei.com>
> Reviewed-by: Dan Williams <dan.j.williams@intel.com>
> Signed-off-by: Dave Jiang <dave.jiang@intel.com>
Reviewed-by: Li Ming <ming.li@zohomail.com>
^ permalink raw reply [flat|nested] 45+ messages in thread
* Re: [PATCH v4 02/15] cxl: Add Get Supported Features command for kernel usage
2025-02-07 23:56 ` Dan Williams
@ 2025-02-10 17:03 ` Dave Jiang
0 siblings, 0 replies; 45+ messages in thread
From: Dave Jiang @ 2025-02-10 17:03 UTC (permalink / raw)
To: Dan Williams, linux-cxl
Cc: ira.weiny, vishal.l.verma, alison.schofield, Jonathan.Cameron,
dave, jgg, shiju.jose
On 2/7/25 4:56 PM, Dan Williams wrote:
> Dave Jiang wrote:
>> CXL spec r3.2 8.2.9.6.1 Get Supported Features (Opcode 0500h)
>> The command retrieve the list of supported device-specific features
>> (identified by UUID) and general information about each Feature.
>>
>> The driver will retrieve the Feature entries in order to make checks and
>> provide information for the Get Feature and Set Feature command. One of
>> the main piece of information retrieved are the effects a Set Feature
>> command would have for a particular feature. The retrieved Feature
>> entries are stored in the cxl_mailbox context.
>>
>> The setup of Features is initiated via devm_cxl_setup_features() during the
>> pci probe function before the cxl_memdev is enumerated.
>>
>> Reviewed-by: Jonathan Cameron <Jonathan.Cameron@huawei.com>
>> Signed-off-by: Dave Jiang <dave.jiang@intel.com>
> [..]
>> +/**
>> + * devm_cxl_setup_features() - Allocate and initialize features context
>> + * @cxlds: CXL device context
>> + *
>> + * Return 0 on success or -errno on failure.
>> + */
>> +int devm_cxl_setup_features(struct cxl_dev_state *cxlds)
>> +{
>> + struct cxl_mailbox *cxl_mbox = &cxlds->cxl_mbox;
>> + int rc;
>> +
>> + if (cxl_mbox->feat_cap < CXL_FEATURES_RO)
>> + return -ENODEV;
>> +
>> + struct cxl_features_state *cxlfs __free(kfree) =
>> + kzalloc(sizeof(*cxlfs), GFP_KERNEL);
>> + if (!cxlfs)
>> + return -ENOMEM;
>> +
>> + cxlfs->cxlds = cxlds;
>> +
>> + cxlfs->entries = get_supported_features(cxlfs);
>> + if (!cxlfs->entries)
>> + return -ENOMEM;
>> +
>> + cxlds->cxlfs = cxlfs;
>> + rc = devm_add_action_or_reset(cxlds->dev, free_cxlfs, no_free_ptr(cxlfs));
>> + if (rc)
>> + return rc;
>> +
>> + return 0;
>
> One small cleanup you can do here when applying is reduce these last 5
> lines to:
>
> return devm_add_action_or_reset(cxlds->dev, free_cxlfs,
> no_free_ptr(cxlfs));
>
> [..]
>> +/**
>> + * struct cxl_features_state - The Features state for the device
>> + * @cxlds: Pointer to CXL device state
>> + * @cap: Feature commands capability
>> + * @entries: CXl feature entry context
>> + * @num_features: total Features supported by the device
>> + * @ent: Flex array of Feature detail entries from the device
>> + */
>> +struct cxl_features_state {
>> + struct cxl_dev_state *cxlds;
>> + struct cxl_feat_entries {
>> + int num_features;
>> + struct cxl_feat_entry ent[] __counted_by(num_features);
>> + } *entries;
>> +};
>> +
>> +#ifdef CONFIG_CXL_FEATURES
>> +inline struct cxl_features_state *to_cxlfs(struct cxl_dev_state *cxlds);
>
> Shouldn't this be:
>
> static inline struct cxl_features_state *to_cxlfs(struct cxl_dev_state *cxlds)
> {
> return cxlds->cxlfs;
> }
>
> ...no need to do an out of line function for this.
So the reason it is an out of line function is to not expose 'struct cxl_dev_state' globally. Otherwise it needs to be in a public header in include/cxl/ to work.
DJ
>
> Another small fixup you can do when applying.
>
> Otherwise, this now all looks good to me:
>
> Reviewed-by: Dan Williams <dan.j.williams@intel.com>
^ permalink raw reply [flat|nested] 45+ messages in thread
* Re: [PATCH v4 02/15] cxl: Add Get Supported Features command for kernel usage
2025-02-08 6:13 ` Li Ming
@ 2025-02-10 17:06 ` Dave Jiang
0 siblings, 0 replies; 45+ messages in thread
From: Dave Jiang @ 2025-02-10 17:06 UTC (permalink / raw)
To: Li Ming, linux-cxl
Cc: dan.j.williams, ira.weiny, vishal.l.verma, alison.schofield,
Jonathan.Cameron, dave, jgg, shiju.jose
On 2/7/25 11:13 PM, Li Ming wrote:
> On 2/8/2025 7:37 AM, Dave Jiang wrote:
>> CXL spec r3.2 8.2.9.6.1 Get Supported Features (Opcode 0500h)
>> The command retrieve the list of supported device-specific features
>> (identified by UUID) and general information about each Feature.
>>
>> The driver will retrieve the Feature entries in order to make checks and
>> provide information for the Get Feature and Set Feature command. One of
>> the main piece of information retrieved are the effects a Set Feature
>> command would have for a particular feature. The retrieved Feature
>> entries are stored in the cxl_mailbox context.
>>
>> The setup of Features is initiated via devm_cxl_setup_features() during the
>> pci probe function before the cxl_memdev is enumerated.
>>
>> Reviewed-by: Jonathan Cameron <Jonathan.Cameron@huawei.com>
>> Signed-off-by: Dave Jiang <dave.jiang@intel.com>
> [...]
>> +static struct cxl_feat_entries *
>> +get_supported_features(struct cxl_features_state *cxlfs)
>> +{
>> + int remain_feats, max_size, max_feats, start, rc, hdr_size;
>> + struct cxl_mailbox *cxl_mbox = &cxlfs->cxlds->cxl_mbox;
>> + int feat_size = sizeof(struct cxl_feat_entry);
>> + struct cxl_mbox_get_sup_feats_in mbox_in;
>> + struct cxl_feat_entry *entry;
>> + struct cxl_mbox_cmd mbox_cmd;
>> + int count;
>> +
>> + count = cxl_get_supported_features_count(cxl_mbox);
>> + if (count <= 0)
>> + return NULL;
>> +
>> + struct cxl_feat_entries *entries __free(kvfree) =
>> + kvmalloc(struct_size(entries, ent, count), GFP_KERNEL);
>> + if (!entries)
>> + return NULL;
>> +
>> + struct cxl_mbox_get_sup_feats_out *mbox_out __free(kvfree) =
>> + kvmalloc(cxl_mbox->payload_size, GFP_KERNEL);
>> + if (!mbox_out)
>> + return NULL;
>> +
>> + hdr_size = struct_size(mbox_out, ents, 0);
>> + max_size = cxl_mbox->payload_size - hdr_size;
>> + /* max feat entries that can fit in mailbox max payload size */
>> + max_feats = max_size / feat_size;
>> + entry = entries->ent;
>> +
>> + start = 0;
>> + remain_feats = count;
>> + do {
>> + int retrieved, alloc_size, copy_feats;
>> + int num_entries;
>> +
>> + if (remain_feats > max_feats) {
>> + alloc_size = struct_size(mbox_out, ents, max_feats);
>> + remain_feats = remain_feats - max_feats;
>> + copy_feats = max_feats;
>> + } else {
>> + alloc_size = struct_size(mbox_out, ents, remain_feats);
>> + copy_feats = remain_feats;
>> + remain_feats = 0;
>> + }
>> +
>> + memset(&mbox_in, 0, sizeof(mbox_in));
>> + mbox_in.count = cpu_to_le32(alloc_size);
>> + mbox_in.start_idx = cpu_to_le16(start);
>> + memset(mbox_out, 0, alloc_size);
>> + mbox_cmd = (struct cxl_mbox_cmd) {
>> + .opcode = CXL_MBOX_OP_GET_SUPPORTED_FEATURES,
>> + .size_in = sizeof(mbox_in),
>> + .payload_in = &mbox_in,
>> + .size_out = alloc_size,
>> + .payload_out = mbox_out,
>> + .min_out = hdr_size,
>> + };
>> + rc = cxl_internal_send_cmd(cxl_mbox, &mbox_cmd);
>> + if (rc < 0)
>> + return ERR_PTR(rc);
> Should return NULL here?
Thanks for the catch. I missed that one.
DJ
>> +
>> + if (mbox_cmd.size_out <= hdr_size)
>> + return NULL;
>> +
>> + /*
>> + * Make sure retrieved out buffer is multiple of feature
>> + * entries.
>> + */
>> + retrieved = mbox_cmd.size_out - hdr_size;
>> + if (retrieved % feat_size)
>> + return NULL;
>> +
>> + num_entries = le16_to_cpu(mbox_out->num_entries);
>> + /*
>> + * If the reported output entries * defined entry size !=
>> + * retrieved output bytes, then the output package is incorrect.
>> + */
>> + if (num_entries * feat_size != retrieved)
>> + return NULL;
>> +
>> + memcpy(entry, mbox_out->ents, retrieved);
>> + entry += num_entries;
>> + /*
>> + * If the number of output entries is less than expected, add the
>> + * remaining entries to the next batch.
>> + */
>> + remain_feats += copy_feats - num_entries;
>> + start += num_entries;
>> + } while (remain_feats);
>> +
>> + entries->num_features = count;
>> +
>> + return no_free_ptr(entries);
>> +}
>> +
>> +static void free_cxlfs(void *_cxlfs)
>> +{
>> + struct cxl_features_state *cxlfs = _cxlfs;
>> + struct cxl_dev_state *cxlds = cxlfs->cxlds;
>> +
>> + cxlds->cxlfs = NULL;
>> + kvfree(cxlfs->entries);
>> + kfree(cxlfs);
>> +}
>> +
>> +/**
>> + * devm_cxl_setup_features() - Allocate and initialize features context
>> + * @cxlds: CXL device context
>> + *
>> + * Return 0 on success or -errno on failure.
>> + */
>> +int devm_cxl_setup_features(struct cxl_dev_state *cxlds)
>> +{
>> + struct cxl_mailbox *cxl_mbox = &cxlds->cxl_mbox;
>> + int rc;
>> +
>> + if (cxl_mbox->feat_cap < CXL_FEATURES_RO)
>> + return -ENODEV;
>> +
>> + struct cxl_features_state *cxlfs __free(kfree) =
>> + kzalloc(sizeof(*cxlfs), GFP_KERNEL);
>> + if (!cxlfs)
>> + return -ENOMEM;
>> +
>> + cxlfs->cxlds = cxlds;
>> +
>> + cxlfs->entries = get_supported_features(cxlfs);
>> + if (!cxlfs->entries)
>> + return -ENOMEM;
>
> It will be a problem if the above cxl_internal_send_cmd() in get_supported_features() returns a "ERR_PTR(rc)". My understanding is the cxl_internal_send_cmd() should return a NULL in failure cases.
>
> Other looks good to me.
>
> Reviewed-by: Li Ming <ming.li@zohomail.com>
>
>
^ permalink raw reply [flat|nested] 45+ messages in thread
* Re: [PATCH v4 06/15] cxl: Setup exclusive CXL features that are reserved for the kernel
2025-02-08 6:22 ` Li Ming
@ 2025-02-10 17:40 ` Dave Jiang
2025-02-10 17:50 ` Dave Jiang
1 sibling, 0 replies; 45+ messages in thread
From: Dave Jiang @ 2025-02-10 17:40 UTC (permalink / raw)
To: Li Ming, linux-cxl
Cc: dan.j.williams, ira.weiny, vishal.l.verma, alison.schofield,
Jonathan.Cameron, dave, jgg, shiju.jose
On 2/7/25 11:22 PM, Li Ming wrote:
> On 2/8/2025 7:37 AM, Dave Jiang wrote:
>> Certain features will be exclusively used by components such as in
>> kernel RAS driver. Setup an exclusion list that can be later filtered
>> out before exposing to user space.
>>
>> Reviewed-by: Jonathan Cameron <Jonathan.Cameron@huawei.com>
>> Reviewed-by: Dan Williams <dan.j.williams@intel.com>
>> Signed-off-by: Dave Jiang <dave.jiang@intel.com>
>> ---
>> drivers/cxl/core/features.c | 26 ++++++++++++++++++++++++++
>> include/cxl/features.h | 34 ++++++++++++++++++++++++++++++++++
>> 2 files changed, 60 insertions(+)
>>
>> diff --git a/drivers/cxl/core/features.c b/drivers/cxl/core/features.c
>> index d337224158fa..82f21f64452a 100644
>> --- a/drivers/cxl/core/features.c
>> +++ b/drivers/cxl/core/features.c
>> @@ -6,6 +6,28 @@
>> #include "cxl.h"
>> #include "cxlmem.h"
>>
>> +/* All the features below are exclusive to the kernel */
>> +static const uuid_t cxl_exclusive_feats[] = {
>> + CXL_FEAT_PATROL_SCRUB_UUID,
>> + CXL_FEAT_ECS_UUID,
>> + CXL_FEAT_SPPR_UUID,
>> + CXL_FEAT_HPPR_UUID,
>> + CXL_FEAT_CACHELINE_SPARING_UUID,
>> + CXL_FEAT_ROW_SPARING_UUID,
>> + CXL_FEAT_BANK_SPARING_UUID,
>> + CXL_FEAT_RANK_SPARING_UUID,
>> +};
>> +
>> +static bool is_cxl_feature_exclusive(struct cxl_feat_entry *entry)
>> +{
>> + for (int i = 0; i < ARRAY_SIZE(cxl_exclusive_feats); i++) {
>> + if (uuid_equal(&entry->uuid, &cxl_exclusive_feats[i]))
>> + return true;
>> + }
>> +
>> + return false;
>> +}
>> +
>> inline struct cxl_features_state *to_cxlfs(struct cxl_dev_state *cxlds)
>> {
>> return cxlds->cxlfs;
>> @@ -46,6 +68,7 @@ get_supported_features(struct cxl_features_state *cxlfs)
>> struct cxl_mbox_get_sup_feats_in mbox_in;
>> struct cxl_feat_entry *entry;
>> struct cxl_mbox_cmd mbox_cmd;
>> + int user_feats = 0;
>> int count;
>>
>> count = cxl_get_supported_features_count(cxl_mbox);
>> @@ -120,6 +143,8 @@ get_supported_features(struct cxl_features_state *cxlfs)
>> return NULL;
>>
>> memcpy(entry, mbox_out->ents, retrieved);
>> + if (!is_cxl_feature_exclusive(entry))
>> + user_feats++;
>
> I guess that here should check all entries copied from mbox_out->ents, so it should be
>
>
> for (int i = 0; i < num_entries; i++)
>
> if (!is_cxl_feature_exclusive(entry + i))
>
> user_feats++;
>
Yes I'll fix. The copying multiple entries really threw everything off. Thanks for the catch.
DJ
>
> Other looks good to me.
>
> Reviewed-by: Li Ming <ming.li@zohomail.com>
>
>
>> entry += num_entries;
>> /*
>> * If the number of output entries is less than expected, add the
>> @@ -130,6 +155,7 @@ get_supported_features(struct cxl_features_state *cxlfs)
>> } while (remain_feats);
>>
>> entries->num_features = count;
>> + entries->num_user_features = user_feats;
>>
>> return no_free_ptr(entries);
>> }
^ permalink raw reply [flat|nested] 45+ messages in thread
* Re: [PATCH v4 06/15] cxl: Setup exclusive CXL features that are reserved for the kernel
2025-02-08 6:22 ` Li Ming
2025-02-10 17:40 ` Dave Jiang
@ 2025-02-10 17:50 ` Dave Jiang
2025-02-11 5:46 ` Li Ming
1 sibling, 1 reply; 45+ messages in thread
From: Dave Jiang @ 2025-02-10 17:50 UTC (permalink / raw)
To: Li Ming, linux-cxl
Cc: dan.j.williams, ira.weiny, vishal.l.verma, alison.schofield,
Jonathan.Cameron, dave, jgg, shiju.jose
On 2/7/25 11:22 PM, Li Ming wrote:
> On 2/8/2025 7:37 AM, Dave Jiang wrote:
>> Certain features will be exclusively used by components such as in
>> kernel RAS driver. Setup an exclusion list that can be later filtered
>> out before exposing to user space.
>>
>> Reviewed-by: Jonathan Cameron <Jonathan.Cameron@huawei.com>
>> Reviewed-by: Dan Williams <dan.j.williams@intel.com>
>> Signed-off-by: Dave Jiang <dave.jiang@intel.com>
>> ---
>> drivers/cxl/core/features.c | 26 ++++++++++++++++++++++++++
>> include/cxl/features.h | 34 ++++++++++++++++++++++++++++++++++
>> 2 files changed, 60 insertions(+)
>>
>> diff --git a/drivers/cxl/core/features.c b/drivers/cxl/core/features.c
>> index d337224158fa..82f21f64452a 100644
>> --- a/drivers/cxl/core/features.c
>> +++ b/drivers/cxl/core/features.c
>> @@ -6,6 +6,28 @@
>> #include "cxl.h"
>> #include "cxlmem.h"
>>
>> +/* All the features below are exclusive to the kernel */
>> +static const uuid_t cxl_exclusive_feats[] = {
>> + CXL_FEAT_PATROL_SCRUB_UUID,
>> + CXL_FEAT_ECS_UUID,
>> + CXL_FEAT_SPPR_UUID,
>> + CXL_FEAT_HPPR_UUID,
>> + CXL_FEAT_CACHELINE_SPARING_UUID,
>> + CXL_FEAT_ROW_SPARING_UUID,
>> + CXL_FEAT_BANK_SPARING_UUID,
>> + CXL_FEAT_RANK_SPARING_UUID,
>> +};
>> +
>> +static bool is_cxl_feature_exclusive(struct cxl_feat_entry *entry)
>> +{
>> + for (int i = 0; i < ARRAY_SIZE(cxl_exclusive_feats); i++) {
>> + if (uuid_equal(&entry->uuid, &cxl_exclusive_feats[i]))
>> + return true;
>> + }
>> +
>> + return false;
>> +}
>> +
>> inline struct cxl_features_state *to_cxlfs(struct cxl_dev_state *cxlds)
>> {
>> return cxlds->cxlfs;
>> @@ -46,6 +68,7 @@ get_supported_features(struct cxl_features_state *cxlfs)
>> struct cxl_mbox_get_sup_feats_in mbox_in;
>> struct cxl_feat_entry *entry;
>> struct cxl_mbox_cmd mbox_cmd;
>> + int user_feats = 0;
>> int count;
>>
>> count = cxl_get_supported_features_count(cxl_mbox);
>> @@ -120,6 +143,8 @@ get_supported_features(struct cxl_features_state *cxlfs)
>> return NULL;
>>
>> memcpy(entry, mbox_out->ents, retrieved);
While you are pointing out the issue with copying multiple entries, I noticed that this needs to be fixed in patch2 as well. It should be:
memcpy(entry, mbox_out->ents + start, retrieved);
DJ
>> + if (!is_cxl_feature_exclusive(entry))
>> + user_feats++;
>
> I guess that here should check all entries copied from mbox_out->ents, so it should be
>
>
> for (int i = 0; i < num_entries; i++)
>
> if (!is_cxl_feature_exclusive(entry + i))
>
> user_feats++;
>
>
> Other looks good to me.
>
> Reviewed-by: Li Ming <ming.li@zohomail.com>
>
>
>> entry += num_entries;
>> /*
>> * If the number of output entries is less than expected, add the
>> @@ -130,6 +155,7 @@ get_supported_features(struct cxl_features_state *cxlfs)
>> } while (remain_feats);
>>
>> entries->num_features = count;
>> + entries->num_user_features = user_feats;
>>
>> return no_free_ptr(entries);
>> }
^ permalink raw reply [flat|nested] 45+ messages in thread
* Re: [PATCH v4 10/15] cxl: Add support for fwctl RPC command to enable CXL feature commands
2025-02-08 7:09 ` Li Ming
@ 2025-02-10 22:31 ` Dave Jiang
0 siblings, 0 replies; 45+ messages in thread
From: Dave Jiang @ 2025-02-10 22:31 UTC (permalink / raw)
To: Li Ming, linux-cxl
Cc: dan.j.williams, ira.weiny, vishal.l.verma, alison.schofield,
Jonathan.Cameron, dave, jgg, shiju.jose
On 2/8/25 12:09 AM, Li Ming wrote:
> On 2/8/2025 7:37 AM, Dave Jiang wrote:
>> fwctl provides a fwctl_ops->fw_rpc() callback in order to issue ioctls
>> to a device. The cxl fwctl driver will start by supporting the CXL
>> Feature commands: Get Supported Features, Get Feature, and Set Feature.
>>
>> The fw_rpc() callback provides 'enum fwctl_rpc_scope' parameter where
>> it indicates the security scope of the call. The Get Supported Features
>> and Get Feature calls can be executed with the scope of
>> FWCTL_RPC_CONFIGRATION. The Set Feature call is gated by the effects
>> of the Feature reported by Get Supported Features call for the specific
>> Feature.
>>
>> Only "Get Supported Features" is supported in this patch. Additional
>> commands will be added in follow on patches. "Get Supported Features"
>> will filter the Features that are exclusive to the kernel. The flag
>> field of the Feature details will be cleared of the "Changeable"
>> field and the "set feat size" will be set to 0 to indicate that
>> the feature is not changeable.
>>
>> Signed-off-by: Dave Jiang <dave.jiang@intel.com>
>> ---
>> v4:
>> - Use opcode directly instead of command ids. (Dan)
>> - Add check for no immediate effects and no reset effects. (Dan, Jonathan)
>> - Add check for Set Features to have CXL_FEATURES_RW cap.
>> - Add clearing of the "Changeable" bit in the flags for exclusive features.
>> ---
>> drivers/cxl/core/features.c | 221 +++++++++++++++++++++++++++++++++++-
>> include/uapi/cxl/features.h | 1 +
>> include/uapi/fwctl/cxl.h | 37 ++++++
>> 3 files changed, 257 insertions(+), 2 deletions(-)
>>
>> diff --git a/drivers/cxl/core/features.c b/drivers/cxl/core/features.c
>> index b2836b951360..2682067dd2d7 100644
>> --- a/drivers/cxl/core/features.c
>> +++ b/drivers/cxl/core/features.c
>> @@ -365,11 +365,228 @@ static void *cxlctl_info(struct fwctl_uctx *uctx, size_t *length)
>> return info;
>> }
>>
>> +static struct cxl_feat_entry *
>> +get_support_feature_info(struct cxl_features_state *cxlfs,
>> + const struct fwctl_rpc_cxl *rpc_in)
>> +{
>> + struct cxl_feat_entry *feat;
>> + uuid_t uuid;
>> +
>> + if (rpc_in->op_size < sizeof(uuid))
>> + return ERR_PTR(-EINVAL);
>> +
>> + if (copy_from_user(&uuid, u64_to_user_ptr(rpc_in->in_payload),
>> + sizeof(uuid)))
>> + return ERR_PTR(-EFAULT);
>> +
>> + for (int i = 0; i < cxlfs->entries->num_features; i++) {
>> + feat = &cxlfs->entries->ent[i];
>> + if (uuid_equal(&uuid, &feat->uuid))
>> + return feat;
>> + }
>> +
>> + return ERR_PTR(-EINVAL);
>> +}
>> +
>> +static void *cxlctl_get_supported_features(struct cxl_features_state *cxlfs,
>> + const struct fwctl_rpc_cxl *rpc_in,
>> + size_t *out_len)
>> +{
>> + struct cxl_mbox_get_sup_feats_out *feat_out;
>> + struct cxl_mbox_get_sup_feats_in feat_in;
>> + struct cxl_feat_entry *pos;
>> + size_t out_size;
>> + int requested;
>> + u32 count;
>> + u16 start;
>> + int i;
>> +
>> + if (rpc_in->op_size != sizeof(feat_in))
>> + return ERR_PTR(-EINVAL);
>> +
>> + if (copy_from_user(&feat_in, u64_to_user_ptr(rpc_in->in_payload),
>> + rpc_in->op_size))
>> + return ERR_PTR(-EFAULT);
>> +
>> + count = le32_to_cpu(feat_in.count);
>> + start = le16_to_cpu(feat_in.start_idx);
>> + requested = count / sizeof(*pos);
>> +
>> + /*
>> + * Make sure that the total requested number of entries is not greater
>> + * than the total number of supported features allowed for userspace.
>> + */
>> + if (start >= cxlfs->entries->num_features)
>> + return ERR_PTR(-EINVAL);
>> +
>> + requested = min_t(int, requested, cxlfs->entries->num_features - start);
>> +
>> + out_size = sizeof(struct fwctl_rpc_cxl_out) +
>> + struct_size(feat_out, ents, requested);
>> +
>> + struct fwctl_rpc_cxl_out *rpc_out __free(kvfree) =
>> + kvzalloc(out_size, GFP_KERNEL);
>> + if (!rpc_out)
>> + return ERR_PTR(-ENOMEM);
>> +
>> + rpc_out->size = struct_size(feat_out, ents, requested);
>> + feat_out = (struct cxl_mbox_get_sup_feats_out *)rpc_out->payload;
>> + if (requested == 0) {
>> + feat_out->num_entries = cpu_to_le16(requested);
>> + feat_out->supported_feats =
>> + cpu_to_le16(cxlfs->entries->num_features);
>> + rpc_out->retval = CXL_MBOX_CMD_RC_SUCCESS;
>> + *out_len = out_size;
>> + return no_free_ptr(rpc_out);
>> + }
>> +
>> + for (i = 0, pos = &feat_out->ents[0];
>> + i < cxlfs->entries->num_features; i++, pos++) {
>
> My understanding is that 'i' should start from the value of the 'start' got from 'feat_in.start_idx'.
>
> Please correct me if I'm wrong.
You are correct. It needs to be
for (i = start, pos = &feat_out->ents[0];
i < cxlfs->entries->num_features; i++; pos++) {
if (i - start == requested)
break;
...
}
Thanks for catching that.
DJ
>
>
> Ming
>
>> + if (i == requested)
>> + break;
>> +
>> + memcpy(pos, &cxlfs->entries->ent[i], sizeof(*pos));
>> + /*
>> + * If the feature is exclusive, set the set_feat_size to 0 to
>> + * indicate that the feature is not changeable.
>> + */
>> + if (is_cxl_feature_exclusive(pos)) {
>> + u32 flags;
>> +
>> + pos->set_feat_size = 0;
>> + flags = le32_to_cpu(pos->flags);
>> + flags &= ~CXL_FEATURE_F_CHANGEABLE;
>> + pos->flags = cpu_to_le32(flags);
>> + }
>> + }
>> +
>> + feat_out->num_entries = cpu_to_le16(requested);
>> + feat_out->supported_feats = cpu_to_le16(cxlfs->entries->num_features);
>> + rpc_out->retval = CXL_MBOX_CMD_RC_SUCCESS;
>> + *out_len = out_size;
>> +
>> + return no_free_ptr(rpc_out);
>> +}
>> +
> [...]
^ permalink raw reply [flat|nested] 45+ messages in thread
* Re: [PATCH v4 06/15] cxl: Setup exclusive CXL features that are reserved for the kernel
2025-02-10 17:50 ` Dave Jiang
@ 2025-02-11 5:46 ` Li Ming
2025-02-11 16:13 ` Dave Jiang
0 siblings, 1 reply; 45+ messages in thread
From: Li Ming @ 2025-02-11 5:46 UTC (permalink / raw)
To: Dave Jiang, linux-cxl
Cc: dan.j.williams, ira.weiny, vishal.l.verma, alison.schofield,
Jonathan.Cameron, dave, jgg, shiju.jose
On 2/11/2025 1:50 AM, Dave Jiang wrote:
>
> On 2/7/25 11:22 PM, Li Ming wrote:
>> On 2/8/2025 7:37 AM, Dave Jiang wrote:
>>> Certain features will be exclusively used by components such as in
>>> kernel RAS driver. Setup an exclusion list that can be later filtered
>>> out before exposing to user space.
>>>
>>> Reviewed-by: Jonathan Cameron <Jonathan.Cameron@huawei.com>
>>> Reviewed-by: Dan Williams <dan.j.williams@intel.com>
>>> Signed-off-by: Dave Jiang <dave.jiang@intel.com>
>>> ---
>>> drivers/cxl/core/features.c | 26 ++++++++++++++++++++++++++
>>> include/cxl/features.h | 34 ++++++++++++++++++++++++++++++++++
>>> 2 files changed, 60 insertions(+)
>>>
>>> diff --git a/drivers/cxl/core/features.c b/drivers/cxl/core/features.c
>>> index d337224158fa..82f21f64452a 100644
>>> --- a/drivers/cxl/core/features.c
>>> +++ b/drivers/cxl/core/features.c
>>> @@ -6,6 +6,28 @@
>>> #include "cxl.h"
>>> #include "cxlmem.h"
>>>
>>> +/* All the features below are exclusive to the kernel */
>>> +static const uuid_t cxl_exclusive_feats[] = {
>>> + CXL_FEAT_PATROL_SCRUB_UUID,
>>> + CXL_FEAT_ECS_UUID,
>>> + CXL_FEAT_SPPR_UUID,
>>> + CXL_FEAT_HPPR_UUID,
>>> + CXL_FEAT_CACHELINE_SPARING_UUID,
>>> + CXL_FEAT_ROW_SPARING_UUID,
>>> + CXL_FEAT_BANK_SPARING_UUID,
>>> + CXL_FEAT_RANK_SPARING_UUID,
>>> +};
>>> +
>>> +static bool is_cxl_feature_exclusive(struct cxl_feat_entry *entry)
>>> +{
>>> + for (int i = 0; i < ARRAY_SIZE(cxl_exclusive_feats); i++) {
>>> + if (uuid_equal(&entry->uuid, &cxl_exclusive_feats[i]))
>>> + return true;
>>> + }
>>> +
>>> + return false;
>>> +}
>>> +
>>> inline struct cxl_features_state *to_cxlfs(struct cxl_dev_state *cxlds)
>>> {
>>> return cxlds->cxlfs;
>>> @@ -46,6 +68,7 @@ get_supported_features(struct cxl_features_state *cxlfs)
>>> struct cxl_mbox_get_sup_feats_in mbox_in;
>>> struct cxl_feat_entry *entry;
>>> struct cxl_mbox_cmd mbox_cmd;
>>> + int user_feats = 0;
>>> int count;
>>>
>>> count = cxl_get_supported_features_count(cxl_mbox);
>>> @@ -120,6 +143,8 @@ get_supported_features(struct cxl_features_state *cxlfs)
>>> return NULL;
>>>
>>> memcpy(entry, mbox_out->ents, retrieved);
> While you are pointing out the issue with copying multiple entries, I noticed that this needs to be fixed in patch2 as well. It should be:
> memcpy(entry, mbox_out->ents + start, retrieved);
>
> DJ
I noticed there is a 'mbox_in.start_idx = cpu_to_le16(start)' before sending GET_SUPPORTED_FEATURES command every time.
I think the 'mbox_out->ents[0]' is the first feature info starting from 'start', so the change you mentioned is not needed?
Ming
^ permalink raw reply [flat|nested] 45+ messages in thread
* Re: [PATCH v4 06/15] cxl: Setup exclusive CXL features that are reserved for the kernel
2025-02-11 5:46 ` Li Ming
@ 2025-02-11 16:13 ` Dave Jiang
0 siblings, 0 replies; 45+ messages in thread
From: Dave Jiang @ 2025-02-11 16:13 UTC (permalink / raw)
To: Li Ming, linux-cxl
Cc: dan.j.williams, ira.weiny, vishal.l.verma, alison.schofield,
Jonathan.Cameron, dave, jgg, shiju.jose
On 2/10/25 10:46 PM, Li Ming wrote:
> On 2/11/2025 1:50 AM, Dave Jiang wrote:
>>
>> On 2/7/25 11:22 PM, Li Ming wrote:
>>> On 2/8/2025 7:37 AM, Dave Jiang wrote:
>>>> Certain features will be exclusively used by components such as in
>>>> kernel RAS driver. Setup an exclusion list that can be later filtered
>>>> out before exposing to user space.
>>>>
>>>> Reviewed-by: Jonathan Cameron <Jonathan.Cameron@huawei.com>
>>>> Reviewed-by: Dan Williams <dan.j.williams@intel.com>
>>>> Signed-off-by: Dave Jiang <dave.jiang@intel.com>
>>>> ---
>>>> drivers/cxl/core/features.c | 26 ++++++++++++++++++++++++++
>>>> include/cxl/features.h | 34 ++++++++++++++++++++++++++++++++++
>>>> 2 files changed, 60 insertions(+)
>>>>
>>>> diff --git a/drivers/cxl/core/features.c b/drivers/cxl/core/features.c
>>>> index d337224158fa..82f21f64452a 100644
>>>> --- a/drivers/cxl/core/features.c
>>>> +++ b/drivers/cxl/core/features.c
>>>> @@ -6,6 +6,28 @@
>>>> #include "cxl.h"
>>>> #include "cxlmem.h"
>>>>
>>>> +/* All the features below are exclusive to the kernel */
>>>> +static const uuid_t cxl_exclusive_feats[] = {
>>>> + CXL_FEAT_PATROL_SCRUB_UUID,
>>>> + CXL_FEAT_ECS_UUID,
>>>> + CXL_FEAT_SPPR_UUID,
>>>> + CXL_FEAT_HPPR_UUID,
>>>> + CXL_FEAT_CACHELINE_SPARING_UUID,
>>>> + CXL_FEAT_ROW_SPARING_UUID,
>>>> + CXL_FEAT_BANK_SPARING_UUID,
>>>> + CXL_FEAT_RANK_SPARING_UUID,
>>>> +};
>>>> +
>>>> +static bool is_cxl_feature_exclusive(struct cxl_feat_entry *entry)
>>>> +{
>>>> + for (int i = 0; i < ARRAY_SIZE(cxl_exclusive_feats); i++) {
>>>> + if (uuid_equal(&entry->uuid, &cxl_exclusive_feats[i]))
>>>> + return true;
>>>> + }
>>>> +
>>>> + return false;
>>>> +}
>>>> +
>>>> inline struct cxl_features_state *to_cxlfs(struct cxl_dev_state *cxlds)
>>>> {
>>>> return cxlds->cxlfs;
>>>> @@ -46,6 +68,7 @@ get_supported_features(struct cxl_features_state *cxlfs)
>>>> struct cxl_mbox_get_sup_feats_in mbox_in;
>>>> struct cxl_feat_entry *entry;
>>>> struct cxl_mbox_cmd mbox_cmd;
>>>> + int user_feats = 0;
>>>> int count;
>>>>
>>>> count = cxl_get_supported_features_count(cxl_mbox);
>>>> @@ -120,6 +143,8 @@ get_supported_features(struct cxl_features_state *cxlfs)
>>>> return NULL;
>>>>
>>>> memcpy(entry, mbox_out->ents, retrieved);
>> While you are pointing out the issue with copying multiple entries, I noticed that this needs to be fixed in patch2 as well. It should be:
>> memcpy(entry, mbox_out->ents + start, retrieved);
>>
>> DJ
>
> I noticed there is a 'mbox_in.start_idx = cpu_to_le16(start)' before sending GET_SUPPORTED_FEATURES command every time.
>
> I think the 'mbox_out->ents[0]' is the first feature info starting from 'start', so the change you mentioned is not needed?
Ah yep. Thanks.
>
>
> Ming
>
^ permalink raw reply [flat|nested] 45+ messages in thread
* Re: [PATCH v4 01/15] cxl: Enumerate feature commands
2025-02-07 23:37 ` [PATCH v4 01/15] cxl: Enumerate feature commands Dave Jiang
2025-02-07 23:47 ` Dan Williams
2025-02-08 6:00 ` Li Ming
@ 2025-02-11 17:05 ` Jonathan Cameron
2 siblings, 0 replies; 45+ messages in thread
From: Jonathan Cameron @ 2025-02-11 17:05 UTC (permalink / raw)
To: Dave Jiang
Cc: linux-cxl, dan.j.williams, ira.weiny, vishal.l.verma,
alison.schofield, dave, jgg, shiju.jose
On Fri, 7 Feb 2025 16:37:41 -0700
Dave Jiang <dave.jiang@intel.com> wrote:
> Add feature commands enumeration code in order to detect and enumerate
> the 3 feature related commands "get supported features", "get feature",
> and "set feature". The enumeration will help determine whether the driver
> can issue any of the 3 commands to the device.
>
> Signed-off-by: Dave Jiang <dave.jiang@intel.com>
One trivial comment inline. Either way LGTM
Reviewed-by: Jonathan Cameron <Jonathan.Cameron@huawei.com>
> ---
> v4:
> - Move features cap to mbox. (Dan)
> - Drop features_cmds bitmap. (Dan)
> - Move setup of cxlfs to next patch since there's nothing to do here.
> ---
> drivers/cxl/core/mbox.c | 36 +++++++++++++++++++++++++++++++++++-
> drivers/cxl/cxlmem.h | 3 +++
> include/cxl/features.h | 13 +++++++++++++
> include/cxl/mailbox.h | 3 +++
> 4 files changed, 54 insertions(+), 1 deletion(-)
> create mode 100644 include/cxl/features.h
>
> diff --git a/drivers/cxl/core/mbox.c b/drivers/cxl/core/mbox.c
> index 9c1b9e353e3e..5f8f5945cc02 100644
> --- a/drivers/cxl/core/mbox.c
> +++ b/drivers/cxl/core/mbox.c
> @@ -706,6 +706,35 @@ static int cxl_xfer_log(struct cxl_memdev_state *mds, uuid_t *uuid,
> return 0;
> }
>
> +static int check_features_opcodes(u16 opcode, int *ro_cmds, int *wr_cmds)
> +{
> + switch (opcode) {
> + case CXL_MBOX_OP_GET_SUPPORTED_FEATURES:
> + case CXL_MBOX_OP_GET_FEATURE:
> + (*ro_cmds)++;
> + return 1;
> + case CXL_MBOX_OP_SET_FEATURE:
> + (*wr_cmds)++;
> + return 1;
> + default:
> + return 0;
> + }
> +}
> +
> +/* 'Get Supported Features' and 'Get Feature' */
> +#define MAX_FEATURES_READ_CMDS 2
> +static void set_features_cap(struct cxl_mailbox *cxl_mbox,
> + int ro_cmds, int wr_cmds)
> +{
> + /* Setting up Features capability while walking the CEL */
> + if (ro_cmds == MAX_FEATURES_READ_CMDS) {
> + if (wr_cmds)
> + cxl_mbox->feat_cap = CXL_FEATURES_RW;
> + else
> + cxl_mbox->feat_cap = CXL_FEATURES_RO;
> + }
> +}
> +
> /**
> * cxl_walk_cel() - Walk through the Command Effects Log.
> * @mds: The driver data for the operation
> @@ -721,7 +750,7 @@ 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;
> + int i, ro_cmds = 0, wr_cmds = 0;
>
> cel_entry = (struct cxl_cel_entry *) cel;
>
> @@ -733,6 +762,9 @@ static void cxl_walk_cel(struct cxl_memdev_state *mds, size_t size, u8 *cel)
> if (cmd) {
> set_bit(cmd->info.id, cxl_mbox->enabled_cmds);
> enabled++;
> + } else {
All the following (is poison etc) are also effectively 'else' cases for this
if (cmd) but for simplicity of code that's not checked.
So maybe this should not be an else either?
> + enabled += check_features_opcodes(opcode, &ro_cmds,
> + &wr_cmds);
> }
>
> if (cxl_is_poison_command(opcode)) {
> @@ -748,6 +780,8 @@ static void cxl_walk_cel(struct cxl_memdev_state *mds, size_t size, u8 *cel)
> dev_dbg(dev, "Opcode 0x%04x %s\n", opcode,
> enabled ? "enabled" : "unsupported by driver");
> }
> +
> + set_features_cap(cxl_mbox, ro_cmds, wr_cmds);
> }
>
^ permalink raw reply [flat|nested] 45+ messages in thread
end of thread, other threads:[~2025-02-11 17:05 UTC | newest]
Thread overview: 45+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2025-02-07 23:37 [PATCH v4 00/15] cxl: Add CXL feature commands support via fwctl Dave Jiang
2025-02-07 23:37 ` [PATCH v4 01/15] cxl: Enumerate feature commands Dave Jiang
2025-02-07 23:47 ` Dan Williams
2025-02-08 6:00 ` Li Ming
2025-02-11 17:05 ` Jonathan Cameron
2025-02-07 23:37 ` [PATCH v4 02/15] cxl: Add Get Supported Features command for kernel usage Dave Jiang
2025-02-07 23:56 ` Dan Williams
2025-02-10 17:03 ` Dave Jiang
2025-02-08 6:13 ` Li Ming
2025-02-10 17:06 ` Dave Jiang
2025-02-07 23:37 ` [PATCH v4 03/15] cxl/test: Add Get Supported Features mailbox command support Dave Jiang
2025-02-07 23:37 ` [PATCH v4 04/15] cxl/mbox: Add GET_FEATURE mailbox command Dave Jiang
2025-02-08 0:12 ` Dan Williams
2025-02-07 23:37 ` [PATCH v4 05/15] cxl/mbox: Add SET_FEATURE " Dave Jiang
2025-02-08 0:21 ` Dan Williams
2025-02-08 6:17 ` Li Ming
2025-02-07 23:37 ` [PATCH v4 06/15] cxl: Setup exclusive CXL features that are reserved for the kernel Dave Jiang
2025-02-08 1:10 ` Dan Williams
2025-02-08 1:16 ` Dave Jiang
2025-02-08 6:22 ` Li Ming
2025-02-10 17:40 ` Dave Jiang
2025-02-10 17:50 ` Dave Jiang
2025-02-11 5:46 ` Li Ming
2025-02-11 16:13 ` Dave Jiang
2025-02-07 23:37 ` [PATCH v4 07/15] cxl: Add FWCTL support to CXL Dave Jiang
2025-02-08 1:24 ` Dan Williams
2025-02-07 23:37 ` [PATCH v4 08/15] cxl: Add support for FWCTL get driver information callback Dave Jiang
2025-02-08 1:25 ` Dan Williams
2025-02-10 6:21 ` Li Ming
2025-02-07 23:37 ` [PATCH v4 09/15] cxl: Move cxl feature command structs to user header Dave Jiang
2025-02-07 23:37 ` [PATCH v4 10/15] cxl: Add support for fwctl RPC command to enable CXL feature commands Dave Jiang
2025-02-08 1:29 ` Dan Williams
2025-02-08 1:34 ` Dan Williams
2025-02-08 7:09 ` Li Ming
2025-02-10 22:31 ` Dave Jiang
2025-02-07 23:37 ` [PATCH v4 11/15] cxl: Add support to handle user feature commands for get feature Dave Jiang
2025-02-10 6:41 ` Li Ming
2025-02-07 23:37 ` [PATCH v4 12/15] cxl: Add support to handle user feature commands for set feature Dave Jiang
2025-02-10 6:43 ` Li Ming
2025-02-07 23:37 ` [PATCH v4 13/15] cxl/test: Add Get Feature support to cxl_test Dave Jiang
2025-02-10 6:44 ` Li Ming
2025-02-07 23:37 ` [PATCH v4 14/15] cxl/test: Add Set " Dave Jiang
2025-02-10 6:44 ` Li Ming
2025-02-07 23:37 ` [PATCH v4 15/15] fwctl/cxl: Add documentation to FWCTL CXL Dave Jiang
2025-02-08 1:38 ` Dan Williams
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox