Skip to content

Commit 858ce2f

Browse files
davejiangjgunthorpe
authored andcommitted
cxl: Add FWCTL support to CXL
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/[email protected] Signed-off-by: Dave Jiang <[email protected]> Reviewed-by: Li Ming <[email protected]> Reviewed-by: Jonathan Cameron <[email protected]> Signed-off-by: Jason Gunthorpe <[email protected]>
1 parent 15a26c2 commit 858ce2f

File tree

6 files changed

+90
-0
lines changed

6 files changed

+90
-0
lines changed

drivers/cxl/Kconfig

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,7 @@ menuconfig CXL_BUS
77
select PCI_DOE
88
select FIRMWARE_TABLE
99
select NUMA_KEEP_MEMINFO if NUMA_MEMBLKS
10+
select FWCTL if CXL_FEATURES
1011
help
1112
CXL is a bus that is electrically compatible with PCI Express, but
1213
layers three protocols on that signalling (CXL.io, CXL.cache, and

drivers/cxl/core/features.c

Lines changed: 72 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,6 @@
11
// SPDX-License-Identifier: GPL-2.0-only
22
/* Copyright(c) 2024-2025 Intel Corporation. All rights reserved. */
3+
#include <linux/fwctl.h>
34
#include <linux/device.h>
45
#include <cxl/mailbox.h>
56
#include <cxl/features.h>
@@ -331,3 +332,74 @@ int cxl_set_feature(struct cxl_mailbox *cxl_mbox,
331332
}
332333
} while (true);
333334
}
335+
336+
/* FWCTL support */
337+
338+
static inline struct cxl_memdev *fwctl_to_memdev(struct fwctl_device *fwctl_dev)
339+
{
340+
return to_cxl_memdev(fwctl_dev->dev.parent);
341+
}
342+
343+
static int cxlctl_open_uctx(struct fwctl_uctx *uctx)
344+
{
345+
return 0;
346+
}
347+
348+
static void cxlctl_close_uctx(struct fwctl_uctx *uctx)
349+
{
350+
}
351+
352+
static void *cxlctl_fw_rpc(struct fwctl_uctx *uctx, enum fwctl_rpc_scope scope,
353+
void *in, size_t in_len, size_t *out_len)
354+
{
355+
/* Place holder */
356+
return ERR_PTR(-EOPNOTSUPP);
357+
}
358+
359+
static const struct fwctl_ops cxlctl_ops = {
360+
.device_type = FWCTL_DEVICE_TYPE_CXL,
361+
.uctx_size = sizeof(struct fwctl_uctx),
362+
.open_uctx = cxlctl_open_uctx,
363+
.close_uctx = cxlctl_close_uctx,
364+
.fw_rpc = cxlctl_fw_rpc,
365+
};
366+
367+
DEFINE_FREE(free_fwctl_dev, struct fwctl_device *, if (_T) fwctl_put(_T))
368+
369+
static void free_memdev_fwctl(void *_fwctl_dev)
370+
{
371+
struct fwctl_device *fwctl_dev = _fwctl_dev;
372+
373+
fwctl_unregister(fwctl_dev);
374+
fwctl_put(fwctl_dev);
375+
}
376+
377+
int devm_cxl_setup_fwctl(struct cxl_memdev *cxlmd)
378+
{
379+
struct cxl_dev_state *cxlds = cxlmd->cxlds;
380+
struct cxl_features_state *cxlfs;
381+
int rc;
382+
383+
cxlfs = to_cxlfs(cxlds);
384+
if (!cxlfs)
385+
return -ENODEV;
386+
387+
/* No need to setup FWCTL if there are no user allowed features found */
388+
if (!cxlfs->entries->num_user_features)
389+
return -ENODEV;
390+
391+
struct fwctl_device *fwctl_dev __free(free_fwctl_dev) =
392+
_fwctl_alloc_device(&cxlmd->dev, &cxlctl_ops, sizeof(*fwctl_dev));
393+
if (!fwctl_dev)
394+
return -ENOMEM;
395+
396+
rc = fwctl_register(fwctl_dev);
397+
if (rc)
398+
return rc;
399+
400+
return devm_add_action_or_reset(&cxlmd->dev, free_memdev_fwctl,
401+
no_free_ptr(fwctl_dev));
402+
}
403+
EXPORT_SYMBOL_NS_GPL(devm_cxl_setup_fwctl, "CXL");
404+
405+
MODULE_IMPORT_NS("FWCTL");

drivers/cxl/pci.c

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1013,6 +1013,10 @@ static int cxl_pci_probe(struct pci_dev *pdev, const struct pci_device_id *id)
10131013
if (rc)
10141014
return rc;
10151015

1016+
rc = devm_cxl_setup_fwctl(cxlmd);
1017+
if (rc)
1018+
dev_dbg(&pdev->dev, "No CXL FWCTL setup\n");
1019+
10161020
pmu_count = cxl_count_regblock(pdev, CXL_REGLOC_RBI_PMU);
10171021
if (pmu_count < 0)
10181022
return pmu_count;

include/cxl/features.h

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,7 @@
44
#define __CXL_FEATURES_H__
55

66
#include <linux/uuid.h>
7+
#include <linux/fwctl.h>
78

89
/* Feature UUIDs used by the kernel */
910
#define CXL_FEAT_PATROL_SCRUB_UUID \
@@ -173,9 +174,11 @@ struct cxl_features_state {
173174
};
174175

175176
struct cxl_mailbox;
177+
struct cxl_memdev;
176178
#ifdef CONFIG_CXL_FEATURES
177179
inline struct cxl_features_state *to_cxlfs(struct cxl_dev_state *cxlds);
178180
int devm_cxl_setup_features(struct cxl_dev_state *cxlds);
181+
int devm_cxl_setup_fwctl(struct cxl_memdev *cxlmd);
179182
#else
180183
static inline struct cxl_features_state *to_cxlfs(struct cxl_dev_state *cxlds)
181184
{
@@ -186,6 +189,11 @@ static inline int devm_cxl_setup_features(struct cxl_dev_state *cxlds)
186189
{
187190
return -EOPNOTSUPP;
188191
}
192+
193+
static inline int devm_cxl_setup_fwctl(struct cxl_memdev *cxlmd)
194+
{
195+
return -EOPNOTSUPP;
196+
}
189197
#endif
190198

191199
#endif

include/uapi/fwctl/fwctl.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -43,6 +43,7 @@ enum {
4343
enum fwctl_device_type {
4444
FWCTL_DEVICE_TYPE_ERROR = 0,
4545
FWCTL_DEVICE_TYPE_MLX5 = 1,
46+
FWCTL_DEVICE_TYPE_CXL = 2,
4647
};
4748

4849
/**

tools/testing/cxl/test/mem.c

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1646,6 +1646,10 @@ static int cxl_mock_mem_probe(struct platform_device *pdev)
16461646
if (rc)
16471647
return rc;
16481648

1649+
rc = devm_cxl_setup_fwctl(cxlmd);
1650+
if (rc)
1651+
dev_dbg(dev, "No CXL FWCTL setup\n");
1652+
16491653
cxl_mem_get_event_records(mds, CXLDEV_EVENT_STATUS_ALL);
16501654

16511655
return 0;

0 commit comments

Comments
 (0)