Skip to content

Commit

Permalink
cxl: Add FWCTL support to CXL
Browse files Browse the repository at this point in the history
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 devm_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.

Link: https://patch.msgid.link/r/20250307205648.1021626-2-dave.jiang@intel.com
Signed-off-by: Dave Jiang <dave.jiang@intel.com>
Reviewed-by: Li Ming <ming.li@zohomail.com>
Reviewed-by: Jonathan Cameron <Jonathan.Cameron@huawei.com>
Signed-off-by: Jason Gunthorpe <jgg@nvidia.com>
  • Loading branch information
Dave Jiang authored and Jason Gunthorpe committed Mar 17, 2025
1 parent 15a26c2 commit 858ce2f
Show file tree
Hide file tree
Showing 6 changed files with 90 additions and 0 deletions.
1 change: 1 addition & 0 deletions drivers/cxl/Kconfig
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@ menuconfig CXL_BUS
select PCI_DOE
select FIRMWARE_TABLE
select NUMA_KEEP_MEMINFO if NUMA_MEMBLKS
select FWCTL if CXL_FEATURES
help
CXL is a bus that is electrically compatible with PCI Express, but
layers three protocols on that signalling (CXL.io, CXL.cache, and
Expand Down
72 changes: 72 additions & 0 deletions drivers/cxl/core/features.c
Original file line number Diff line number Diff line change
@@ -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>
Expand Down Expand Up @@ -331,3 +332,74 @@ int cxl_set_feature(struct cxl_mailbox *cxl_mbox,
}
} while (true);
}

/* FWCTL support */

static inline struct cxl_memdev *fwctl_to_memdev(struct fwctl_device *fwctl_dev)
{
return to_cxl_memdev(fwctl_dev->dev.parent);
}

static int cxlctl_open_uctx(struct fwctl_uctx *uctx)
{
return 0;
}

static void cxlctl_close_uctx(struct fwctl_uctx *uctx)
{
}

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,
.fw_rpc = cxlctl_fw_rpc,
};

DEFINE_FREE(free_fwctl_dev, struct fwctl_device *, if (_T) fwctl_put(_T))

static void free_memdev_fwctl(void *_fwctl_dev)
{
struct fwctl_device *fwctl_dev = _fwctl_dev;

fwctl_unregister(fwctl_dev);
fwctl_put(fwctl_dev);
}

int devm_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 fwctl_device *fwctl_dev __free(free_fwctl_dev) =
_fwctl_alloc_device(&cxlmd->dev, &cxlctl_ops, sizeof(*fwctl_dev));
if (!fwctl_dev)
return -ENOMEM;

rc = fwctl_register(fwctl_dev);
if (rc)
return rc;

return devm_add_action_or_reset(&cxlmd->dev, free_memdev_fwctl,
no_free_ptr(fwctl_dev));
}
EXPORT_SYMBOL_NS_GPL(devm_cxl_setup_fwctl, "CXL");

MODULE_IMPORT_NS("FWCTL");
4 changes: 4 additions & 0 deletions drivers/cxl/pci.c
Original file line number Diff line number Diff line change
Expand Up @@ -1013,6 +1013,10 @@ static int cxl_pci_probe(struct pci_dev *pdev, const struct pci_device_id *id)
if (rc)
return rc;

rc = devm_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;
Expand Down
8 changes: 8 additions & 0 deletions include/cxl/features.h
Original file line number Diff line number Diff line change
Expand Up @@ -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 \
Expand Down Expand Up @@ -173,9 +174,11 @@ struct cxl_features_state {
};

struct cxl_mailbox;
struct cxl_memdev;
#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 devm_cxl_setup_fwctl(struct cxl_memdev *cxlmd);
#else
static inline struct cxl_features_state *to_cxlfs(struct cxl_dev_state *cxlds)
{
Expand All @@ -186,6 +189,11 @@ static inline int devm_cxl_setup_features(struct cxl_dev_state *cxlds)
{
return -EOPNOTSUPP;
}

static inline int devm_cxl_setup_fwctl(struct cxl_memdev *cxlmd)
{
return -EOPNOTSUPP;
}
#endif

#endif
1 change: 1 addition & 0 deletions include/uapi/fwctl/fwctl.h
Original file line number Diff line number Diff line change
Expand Up @@ -43,6 +43,7 @@ enum {
enum fwctl_device_type {
FWCTL_DEVICE_TYPE_ERROR = 0,
FWCTL_DEVICE_TYPE_MLX5 = 1,
FWCTL_DEVICE_TYPE_CXL = 2,
};

/**
Expand Down
4 changes: 4 additions & 0 deletions tools/testing/cxl/test/mem.c
Original file line number Diff line number Diff line change
Expand Up @@ -1646,6 +1646,10 @@ static int cxl_mock_mem_probe(struct platform_device *pdev)
if (rc)
return rc;

rc = devm_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;
Expand Down

0 comments on commit 858ce2f

Please sign in to comment.