Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux
1
fork

Configure Feed

Select the types of activity you want to include in your feed.

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/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>

authored by

Dave Jiang and committed by
Jason Gunthorpe
858ce2f5 15a26c22

+90
+1
drivers/cxl/Kconfig
··· 7 7 select PCI_DOE 8 8 select FIRMWARE_TABLE 9 9 select NUMA_KEEP_MEMINFO if NUMA_MEMBLKS 10 + select FWCTL if CXL_FEATURES 10 11 help 11 12 CXL is a bus that is electrically compatible with PCI Express, but 12 13 layers three protocols on that signalling (CXL.io, CXL.cache, and
+72
drivers/cxl/core/features.c
··· 1 1 // SPDX-License-Identifier: GPL-2.0-only 2 2 /* Copyright(c) 2024-2025 Intel Corporation. All rights reserved. */ 3 + #include <linux/fwctl.h> 3 4 #include <linux/device.h> 4 5 #include <cxl/mailbox.h> 5 6 #include <cxl/features.h> ··· 332 331 } 333 332 } while (true); 334 333 } 334 + 335 + /* FWCTL support */ 336 + 337 + static inline struct cxl_memdev *fwctl_to_memdev(struct fwctl_device *fwctl_dev) 338 + { 339 + return to_cxl_memdev(fwctl_dev->dev.parent); 340 + } 341 + 342 + static int cxlctl_open_uctx(struct fwctl_uctx *uctx) 343 + { 344 + return 0; 345 + } 346 + 347 + static void cxlctl_close_uctx(struct fwctl_uctx *uctx) 348 + { 349 + } 350 + 351 + static void *cxlctl_fw_rpc(struct fwctl_uctx *uctx, enum fwctl_rpc_scope scope, 352 + void *in, size_t in_len, size_t *out_len) 353 + { 354 + /* Place holder */ 355 + return ERR_PTR(-EOPNOTSUPP); 356 + } 357 + 358 + static const struct fwctl_ops cxlctl_ops = { 359 + .device_type = FWCTL_DEVICE_TYPE_CXL, 360 + .uctx_size = sizeof(struct fwctl_uctx), 361 + .open_uctx = cxlctl_open_uctx, 362 + .close_uctx = cxlctl_close_uctx, 363 + .fw_rpc = cxlctl_fw_rpc, 364 + }; 365 + 366 + DEFINE_FREE(free_fwctl_dev, struct fwctl_device *, if (_T) fwctl_put(_T)) 367 + 368 + static void free_memdev_fwctl(void *_fwctl_dev) 369 + { 370 + struct fwctl_device *fwctl_dev = _fwctl_dev; 371 + 372 + fwctl_unregister(fwctl_dev); 373 + fwctl_put(fwctl_dev); 374 + } 375 + 376 + int devm_cxl_setup_fwctl(struct cxl_memdev *cxlmd) 377 + { 378 + struct cxl_dev_state *cxlds = cxlmd->cxlds; 379 + struct cxl_features_state *cxlfs; 380 + int rc; 381 + 382 + cxlfs = to_cxlfs(cxlds); 383 + if (!cxlfs) 384 + return -ENODEV; 385 + 386 + /* No need to setup FWCTL if there are no user allowed features found */ 387 + if (!cxlfs->entries->num_user_features) 388 + return -ENODEV; 389 + 390 + struct fwctl_device *fwctl_dev __free(free_fwctl_dev) = 391 + _fwctl_alloc_device(&cxlmd->dev, &cxlctl_ops, sizeof(*fwctl_dev)); 392 + if (!fwctl_dev) 393 + return -ENOMEM; 394 + 395 + rc = fwctl_register(fwctl_dev); 396 + if (rc) 397 + return rc; 398 + 399 + return devm_add_action_or_reset(&cxlmd->dev, free_memdev_fwctl, 400 + no_free_ptr(fwctl_dev)); 401 + } 402 + EXPORT_SYMBOL_NS_GPL(devm_cxl_setup_fwctl, "CXL"); 403 + 404 + MODULE_IMPORT_NS("FWCTL");
+4
drivers/cxl/pci.c
··· 1013 1013 if (rc) 1014 1014 return rc; 1015 1015 1016 + rc = devm_cxl_setup_fwctl(cxlmd); 1017 + if (rc) 1018 + dev_dbg(&pdev->dev, "No CXL FWCTL setup\n"); 1019 + 1016 1020 pmu_count = cxl_count_regblock(pdev, CXL_REGLOC_RBI_PMU); 1017 1021 if (pmu_count < 0) 1018 1022 return pmu_count;
+8
include/cxl/features.h
··· 4 4 #define __CXL_FEATURES_H__ 5 5 6 6 #include <linux/uuid.h> 7 + #include <linux/fwctl.h> 7 8 8 9 /* Feature UUIDs used by the kernel */ 9 10 #define CXL_FEAT_PATROL_SCRUB_UUID \ ··· 174 173 }; 175 174 176 175 struct cxl_mailbox; 176 + struct cxl_memdev; 177 177 #ifdef CONFIG_CXL_FEATURES 178 178 inline struct cxl_features_state *to_cxlfs(struct cxl_dev_state *cxlds); 179 179 int devm_cxl_setup_features(struct cxl_dev_state *cxlds); 180 + int devm_cxl_setup_fwctl(struct cxl_memdev *cxlmd); 180 181 #else 181 182 static inline struct cxl_features_state *to_cxlfs(struct cxl_dev_state *cxlds) 182 183 { ··· 186 183 } 187 184 188 185 static inline int devm_cxl_setup_features(struct cxl_dev_state *cxlds) 186 + { 187 + return -EOPNOTSUPP; 188 + } 189 + 190 + static inline int devm_cxl_setup_fwctl(struct cxl_memdev *cxlmd) 189 191 { 190 192 return -EOPNOTSUPP; 191 193 }
+1
include/uapi/fwctl/fwctl.h
··· 43 43 enum fwctl_device_type { 44 44 FWCTL_DEVICE_TYPE_ERROR = 0, 45 45 FWCTL_DEVICE_TYPE_MLX5 = 1, 46 + FWCTL_DEVICE_TYPE_CXL = 2, 46 47 }; 47 48 48 49 /**
+4
tools/testing/cxl/test/mem.c
··· 1646 1646 if (rc) 1647 1647 return rc; 1648 1648 1649 + rc = devm_cxl_setup_fwctl(cxlmd); 1650 + if (rc) 1651 + dev_dbg(dev, "No CXL FWCTL setup\n"); 1652 + 1649 1653 cxl_mem_get_event_records(mds, CXLDEV_EVENT_STATUS_ALL); 1650 1654 1651 1655 return 0;