Commit 5908f3ed authored by Dave Jiang's avatar Dave Jiang Committed by Jason Gunthorpe
Browse files

cxl: Add support to handle user feature commands for get feature

Add helper function to parse the user data from fwctl RPC ioctl and
send the parsed input parameters to cxl_get_feature() call.

Link: https://patch.msgid.link/r/20250307205648.1021626-5-dave.jiang@intel.com


Reviewed-by: default avatarJonathan Cameron <Jonathan.Cameron@huawei.com>
Reviewed-by: default avatarDan Williams <dan.j.williams@intel.com>
Reviewed-by: default avatarLi Ming <ming.li@zohomail.com>
Signed-off-by: default avatarDave Jiang <dave.jiang@intel.com>
Signed-off-by: default avatarJason Gunthorpe <jgg@nvidia.com>
parent 4d1c09ce
Loading
Loading
Loading
Loading
+44 −0
Original line number Diff line number Diff line
@@ -427,6 +427,47 @@ 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;
	const 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);

	feat_in = &rpc_in->get_feat_in;
	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_hw_command(struct cxl_features_state *cxlfs,
				       const struct fwctl_rpc_cxl *rpc_in,
				       enum fwctl_rpc_scope scope,
@@ -436,6 +477,7 @@ static bool cxlctl_validate_hw_command(struct cxl_features_state *cxlfs,

	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)
@@ -453,6 +495,8 @@ static void *cxlctl_handle_commands(struct cxl_features_state *cxlfs,
	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:
		return cxlctl_get_feature(cxlfs, rpc_in, out_len);
	default:
		return ERR_PTR(-EOPNOTSUPP);
	}
+10 −2
Original line number Diff line number Diff line
@@ -18,6 +18,7 @@
 * @op_size: Size of input payload.
 * @reserved1: Reserved. Must be 0s.
 * @get_sup_feats_in: Get Supported Features input
 * @get_feat_in: Get Feature input
 */
struct fwctl_rpc_cxl {
	__struct_group(fwctl_rpc_cxl_hdr, hdr, /* no attrs */,
@@ -26,7 +27,10 @@ struct fwctl_rpc_cxl {
		__u32 op_size;
		__u32 reserved1;
	);
	union {
		struct cxl_mbox_get_sup_feats_in get_sup_feats_in;
		struct cxl_mbox_get_feat_in get_feat_in;
	};
};

/**
@@ -34,13 +38,17 @@ struct fwctl_rpc_cxl {
 * @size: Size of the output payload
 * @retval: Return value from device
 * @get_sup_feats_out: Get Supported Features output
 * @payload: raw byte stream of payload
 */
struct fwctl_rpc_cxl_out {
	__struct_group(fwctl_rpc_cxl_out_hdr, hdr, /* no attrs */,
		__u32 size;
		__u32 retval;
	);
	union {
		struct cxl_mbox_get_sup_feats_out get_sup_feats_out;
		__DECLARE_FLEX_ARRAY(__u8, payload);
	};
};

#endif