1*72b24a9dSDave Jiang.. SPDX-License-Identifier: GPL-2.0 2*72b24a9dSDave Jiang 3*72b24a9dSDave Jiang================ 4*72b24a9dSDave Jiangfwctl cxl driver 5*72b24a9dSDave Jiang================ 6*72b24a9dSDave Jiang 7*72b24a9dSDave Jiang:Author: Dave Jiang 8*72b24a9dSDave Jiang 9*72b24a9dSDave JiangOverview 10*72b24a9dSDave Jiang======== 11*72b24a9dSDave Jiang 12*72b24a9dSDave JiangThe CXL spec defines a set of commands that can be issued to the mailbox of a 13*72b24a9dSDave JiangCXL device or switch. It also left room for vendor specific commands to be 14*72b24a9dSDave Jiangissued to the mailbox as well. fwctl provides a path to issue a set of allowed 15*72b24a9dSDave Jiangmailbox commands from user space to the device moderated by the kernel driver. 16*72b24a9dSDave Jiang 17*72b24a9dSDave JiangThe following 3 commands will be used to support CXL Features: 18*72b24a9dSDave JiangCXL spec r3.1 8.2.9.6.1 Get Supported Features (Opcode 0500h) 19*72b24a9dSDave JiangCXL spec r3.1 8.2.9.6.2 Get Feature (Opcode 0501h) 20*72b24a9dSDave JiangCXL spec r3.1 8.2.9.6.3 Set Feature (Opcode 0502h) 21*72b24a9dSDave Jiang 22*72b24a9dSDave JiangThe "Get Supported Features" return data may be filtered by the kernel driver to 23*72b24a9dSDave Jiangdrop any features that are forbidden by the kernel or being exclusively used by 24*72b24a9dSDave Jiangthe kernel. The driver will set the "Set Feature Size" of the "Get Supported 25*72b24a9dSDave JiangFeatures Supported Feature Entry" to 0 to indicate that the Feature cannot be 26*72b24a9dSDave Jiangmodified. The "Get Supported Features" command and the "Get Features" falls 27*72b24a9dSDave Jiangunder the fwctl policy of FWCTL_RPC_CONFIGURATION. 28*72b24a9dSDave Jiang 29*72b24a9dSDave JiangFor "Set Feature" command, the access policy currently is broken down into two 30*72b24a9dSDave Jiangcategories depending on the Set Feature effects reported by the device. If the 31*72b24a9dSDave JiangSet Feature will cause immediate change to the device, the fwctl access policy 32*72b24a9dSDave Jiangmust be FWCTL_RPC_DEBUG_WRITE_FULL. The effects for this level are 33*72b24a9dSDave Jiang"immediate config change", "immediate data change", "immediate policy change", 34*72b24a9dSDave Jiangor "immediate log change" for the set effects mask. If the effects are "config 35*72b24a9dSDave Jiangchange with cold reset" or "config change with conventional reset", then the 36*72b24a9dSDave Jiangfwctl access policy must be FWCTL_RPC_DEBUG_WRITE or higher. 37*72b24a9dSDave Jiang 38*72b24a9dSDave Jiangfwctl cxl User API 39*72b24a9dSDave Jiang================== 40*72b24a9dSDave Jiang 41*72b24a9dSDave Jiang.. kernel-doc:: include/uapi/fwctl/cxl.h 42*72b24a9dSDave Jiang 43*72b24a9dSDave Jiang1. Driver info query 44*72b24a9dSDave Jiang-------------------- 45*72b24a9dSDave Jiang 46*72b24a9dSDave JiangFirst step for the app is to issue the ioctl(FWCTL_CMD_INFO). Successful 47*72b24a9dSDave Jianginvocation of the ioctl implies the Features capability is operational and 48*72b24a9dSDave Jiangreturns an all zeros 32bit payload. A ``struct fwctl_info`` needs to be filled 49*72b24a9dSDave Jiangout with the ``fwctl_info.out_device_type`` set to ``FWCTL_DEVICE_TYPE_CXL``. 50*72b24a9dSDave JiangThe return data should be ``struct fwctl_info_cxl`` that contains a reserved 51*72b24a9dSDave Jiang32bit field that should be all zeros. 52*72b24a9dSDave Jiang 53*72b24a9dSDave Jiang2. Send hardware commands 54*72b24a9dSDave Jiang------------------------- 55*72b24a9dSDave Jiang 56*72b24a9dSDave JiangNext step is to send the 'Get Supported Features' command to the driver from 57*72b24a9dSDave Jianguser space via ioctl(FWCTL_RPC). A ``struct fwctl_rpc_cxl`` is pointed to 58*72b24a9dSDave Jiangby ``fwctl_rpc.in``. ``struct fwctl_rpc_cxl.in_payload`` points to 59*72b24a9dSDave Jiangthe hardware input structure that is defined by the CXL spec. ``fwctl_rpc.out`` 60*72b24a9dSDave Jiangpoints to the buffer that contains a ``struct fwctl_rpc_cxl_out`` that includes 61*72b24a9dSDave Jiangthe hardware output data inlined as ``fwctl_rpc_cxl_out.payload``. This command 62*72b24a9dSDave Jiangis called twice. First time to retrieve the number of features supported. 63*72b24a9dSDave JiangA second time to retrieve the specific feature details as the output data. 64*72b24a9dSDave Jiang 65*72b24a9dSDave JiangAfter getting the specific feature details, a Get/Set Feature command can be 66*72b24a9dSDave Jiangappropriately programmed and sent. For a "Set Feature" command, the retrieved 67*72b24a9dSDave Jiangfeature info contains an effects field that details the resulting 68*72b24a9dSDave Jiang"Set Feature" command will trigger. That will inform the user whether 69*72b24a9dSDave Jiangthe system is configured to allowed the "Set Feature" command or not. 70*72b24a9dSDave Jiang 71*72b24a9dSDave JiangCode example of a Get Feature 72*72b24a9dSDave Jiang~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ 73*72b24a9dSDave Jiang 74*72b24a9dSDave Jiang.. code-block:: c 75*72b24a9dSDave Jiang 76*72b24a9dSDave Jiang static int cxl_fwctl_rpc_get_test_feature(int fd, struct test_feature *feat_ctx, 77*72b24a9dSDave Jiang const uint32_t expected_data) 78*72b24a9dSDave Jiang { 79*72b24a9dSDave Jiang struct cxl_mbox_get_feat_in *feat_in; 80*72b24a9dSDave Jiang struct fwctl_rpc_cxl_out *out; 81*72b24a9dSDave Jiang struct fwctl_rpc rpc = {0}; 82*72b24a9dSDave Jiang struct fwctl_rpc_cxl *in; 83*72b24a9dSDave Jiang size_t out_size, in_size; 84*72b24a9dSDave Jiang uint32_t val; 85*72b24a9dSDave Jiang void *data; 86*72b24a9dSDave Jiang int rc; 87*72b24a9dSDave Jiang 88*72b24a9dSDave Jiang in_size = sizeof(*in) + sizeof(*feat_in); 89*72b24a9dSDave Jiang rc = posix_memalign((void **)&in, 16, in_size); 90*72b24a9dSDave Jiang if (rc) 91*72b24a9dSDave Jiang return -ENOMEM; 92*72b24a9dSDave Jiang memset(in, 0, in_size); 93*72b24a9dSDave Jiang feat_in = &in->get_feat_in; 94*72b24a9dSDave Jiang 95*72b24a9dSDave Jiang uuid_copy(feat_in->uuid, feat_ctx->uuid); 96*72b24a9dSDave Jiang feat_in->count = feat_ctx->get_size; 97*72b24a9dSDave Jiang 98*72b24a9dSDave Jiang out_size = sizeof(*out) + feat_ctx->get_size; 99*72b24a9dSDave Jiang rc = posix_memalign((void **)&out, 16, out_size); 100*72b24a9dSDave Jiang if (rc) 101*72b24a9dSDave Jiang goto free_in; 102*72b24a9dSDave Jiang memset(out, 0, out_size); 103*72b24a9dSDave Jiang 104*72b24a9dSDave Jiang in->opcode = CXL_MBOX_OPCODE_GET_FEATURE; 105*72b24a9dSDave Jiang in->op_size = sizeof(*feat_in); 106*72b24a9dSDave Jiang 107*72b24a9dSDave Jiang rpc.size = sizeof(rpc); 108*72b24a9dSDave Jiang rpc.scope = FWCTL_RPC_CONFIGURATION; 109*72b24a9dSDave Jiang rpc.in_len = in_size; 110*72b24a9dSDave Jiang rpc.out_len = out_size; 111*72b24a9dSDave Jiang rpc.in = (uint64_t)(uint64_t *)in; 112*72b24a9dSDave Jiang rpc.out = (uint64_t)(uint64_t *)out; 113*72b24a9dSDave Jiang 114*72b24a9dSDave Jiang rc = send_command(fd, &rpc, out); 115*72b24a9dSDave Jiang if (rc) 116*72b24a9dSDave Jiang goto free_all; 117*72b24a9dSDave Jiang 118*72b24a9dSDave Jiang data = out->payload; 119*72b24a9dSDave Jiang val = le32toh(*(__le32 *)data); 120*72b24a9dSDave Jiang if (memcmp(&val, &expected_data, sizeof(val)) != 0) { 121*72b24a9dSDave Jiang rc = -ENXIO; 122*72b24a9dSDave Jiang goto free_all; 123*72b24a9dSDave Jiang } 124*72b24a9dSDave Jiang 125*72b24a9dSDave Jiang free_all: 126*72b24a9dSDave Jiang free(out); 127*72b24a9dSDave Jiang free_in: 128*72b24a9dSDave Jiang free(in); 129*72b24a9dSDave Jiang return rc; 130*72b24a9dSDave Jiang } 131*72b24a9dSDave Jiang 132*72b24a9dSDave JiangTake a look at CXL CLI test directory 133*72b24a9dSDave Jiang<https://github.com/pmem/ndctl/tree/main/test/fwctl.c> for a detailed user code 134*72b24a9dSDave Jiangfor examples on how to exercise this path. 135*72b24a9dSDave Jiang 136*72b24a9dSDave Jiang 137*72b24a9dSDave Jiangfwctl cxl Kernel API 138*72b24a9dSDave Jiang==================== 139*72b24a9dSDave Jiang 140*72b24a9dSDave Jiang.. kernel-doc:: drivers/cxl/core/features.c 141*72b24a9dSDave Jiang :export: 142*72b24a9dSDave Jiang.. kernel-doc:: include/cxl/features.h 143