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 support to handle user feature commands for set feature

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

Link: https://patch.msgid.link/r/20250307205648.1021626-6-dave.jiang@intel.com
Reviewed-by: Jonathan Cameron <Jonathan.Cameron@huawei.com>
Reviewed-by: Dan Williams <dan.j.williams@intel.com>
Reviewed-by: Li Ming <ming.li@zohomail.com>
Signed-off-by: Dave Jiang <dave.jiang@intel.com>
Signed-off-by: Jason Gunthorpe <jgg@nvidia.com>

authored by

Dave Jiang and committed by
Jason Gunthorpe
eb5dfcb9 5908f3ed

+146 -2
+144 -2
drivers/cxl/core/features.c
··· 21 21 CXL_FEAT_RANK_SPARING_UUID, 22 22 }; 23 23 24 - static bool is_cxl_feature_exclusive(struct cxl_feat_entry *entry) 24 + static bool is_cxl_feature_exclusive_by_uuid(const uuid_t *uuid) 25 25 { 26 26 for (int i = 0; i < ARRAY_SIZE(cxl_exclusive_feats); i++) { 27 - if (uuid_equal(&entry->uuid, &cxl_exclusive_feats[i])) 27 + if (uuid_equal(uuid, &cxl_exclusive_feats[i])) 28 28 return true; 29 29 } 30 30 31 31 return false; 32 + } 33 + 34 + static bool is_cxl_feature_exclusive(struct cxl_feat_entry *entry) 35 + { 36 + return is_cxl_feature_exclusive_by_uuid(&entry->uuid); 32 37 } 33 38 34 39 inline struct cxl_features_state *to_cxlfs(struct cxl_dev_state *cxlds) ··· 355 350 { 356 351 } 357 352 353 + static struct cxl_feat_entry * 354 + get_support_feature_info(struct cxl_features_state *cxlfs, 355 + const struct fwctl_rpc_cxl *rpc_in) 356 + { 357 + struct cxl_feat_entry *feat; 358 + const uuid_t *uuid; 359 + 360 + if (rpc_in->op_size < sizeof(uuid)) 361 + return ERR_PTR(-EINVAL); 362 + 363 + uuid = &rpc_in->set_feat_in.uuid; 364 + 365 + for (int i = 0; i < cxlfs->entries->num_features; i++) { 366 + feat = &cxlfs->entries->ent[i]; 367 + if (uuid_equal(uuid, &feat->uuid)) 368 + return feat; 369 + } 370 + 371 + return ERR_PTR(-EINVAL); 372 + } 373 + 358 374 static void *cxlctl_get_supported_features(struct cxl_features_state *cxlfs, 359 375 const struct fwctl_rpc_cxl *rpc_in, 360 376 size_t *out_len) ··· 494 468 return no_free_ptr(rpc_out); 495 469 } 496 470 471 + static void *cxlctl_set_feature(struct cxl_features_state *cxlfs, 472 + const struct fwctl_rpc_cxl *rpc_in, 473 + size_t *out_len) 474 + { 475 + struct cxl_mailbox *cxl_mbox = &cxlfs->cxlds->cxl_mbox; 476 + const struct cxl_mbox_set_feat_in *feat_in; 477 + size_t out_size, data_size; 478 + u16 offset, return_code; 479 + u32 flags; 480 + int rc; 481 + 482 + if (rpc_in->op_size <= sizeof(feat_in->hdr)) 483 + return ERR_PTR(-EINVAL); 484 + 485 + feat_in = &rpc_in->set_feat_in; 486 + 487 + if (is_cxl_feature_exclusive_by_uuid(&feat_in->uuid)) 488 + return ERR_PTR(-EPERM); 489 + 490 + offset = le16_to_cpu(feat_in->offset); 491 + flags = le32_to_cpu(feat_in->flags); 492 + out_size = *out_len; 493 + 494 + struct fwctl_rpc_cxl_out *rpc_out __free(kvfree) = 495 + kvzalloc(out_size, GFP_KERNEL); 496 + if (!rpc_out) 497 + return ERR_PTR(-ENOMEM); 498 + 499 + rpc_out->size = 0; 500 + 501 + data_size = rpc_in->op_size - sizeof(feat_in->hdr); 502 + rc = cxl_set_feature(cxl_mbox, &feat_in->uuid, 503 + feat_in->version, feat_in->feat_data, 504 + data_size, flags, offset, &return_code); 505 + if (rc) { 506 + rpc_out->retval = return_code; 507 + return no_free_ptr(rpc_out); 508 + } 509 + 510 + rpc_out->retval = CXL_MBOX_CMD_RC_SUCCESS; 511 + *out_len = sizeof(*rpc_out); 512 + 513 + return no_free_ptr(rpc_out); 514 + } 515 + 516 + static bool cxlctl_validate_set_features(struct cxl_features_state *cxlfs, 517 + const struct fwctl_rpc_cxl *rpc_in, 518 + enum fwctl_rpc_scope scope) 519 + { 520 + u16 effects, imm_mask, reset_mask; 521 + struct cxl_feat_entry *feat; 522 + u32 flags; 523 + 524 + feat = get_support_feature_info(cxlfs, rpc_in); 525 + if (IS_ERR(feat)) 526 + return false; 527 + 528 + /* Ensure that the attribute is changeable */ 529 + flags = le32_to_cpu(feat->flags); 530 + if (!(flags & CXL_FEATURE_F_CHANGEABLE)) 531 + return false; 532 + 533 + effects = le16_to_cpu(feat->effects); 534 + 535 + /* 536 + * Reserved bits are set, rejecting since the effects is not 537 + * comprehended by the driver. 538 + */ 539 + if (effects & CXL_CMD_EFFECTS_RESERVED) { 540 + dev_warn_once(cxlfs->cxlds->dev, 541 + "Reserved bits set in the Feature effects field!\n"); 542 + return false; 543 + } 544 + 545 + /* Currently no user background command support */ 546 + if (effects & CXL_CMD_BACKGROUND) 547 + return false; 548 + 549 + /* Effects cause immediate change, highest security scope is needed */ 550 + imm_mask = CXL_CMD_CONFIG_CHANGE_IMMEDIATE | 551 + CXL_CMD_DATA_CHANGE_IMMEDIATE | 552 + CXL_CMD_POLICY_CHANGE_IMMEDIATE | 553 + CXL_CMD_LOG_CHANGE_IMMEDIATE; 554 + 555 + reset_mask = CXL_CMD_CONFIG_CHANGE_COLD_RESET | 556 + CXL_CMD_CONFIG_CHANGE_CONV_RESET | 557 + CXL_CMD_CONFIG_CHANGE_CXL_RESET; 558 + 559 + /* If no immediate or reset effect set, The hardware has a bug */ 560 + if (!(effects & imm_mask) && !(effects & reset_mask)) 561 + return false; 562 + 563 + /* 564 + * If the Feature setting causes immediate configuration change 565 + * then we need the full write permission policy. 566 + */ 567 + if (effects & imm_mask && scope >= FWCTL_RPC_DEBUG_WRITE_FULL) 568 + return true; 569 + 570 + /* 571 + * If the Feature setting only causes configuration change 572 + * after a reset, then the lesser level of write permission 573 + * policy is ok. 574 + */ 575 + if (!(effects & imm_mask) && scope >= FWCTL_RPC_DEBUG_WRITE) 576 + return true; 577 + 578 + return false; 579 + } 580 + 497 581 static bool cxlctl_validate_hw_command(struct cxl_features_state *cxlfs, 498 582 const struct fwctl_rpc_cxl *rpc_in, 499 583 enum fwctl_rpc_scope scope, ··· 619 483 if (scope >= FWCTL_RPC_CONFIGURATION) 620 484 return true; 621 485 return false; 486 + case CXL_MBOX_OP_SET_FEATURE: 487 + if (cxl_mbox->feat_cap < CXL_FEATURES_RW) 488 + return false; 489 + return cxlctl_validate_set_features(cxlfs, rpc_in, scope); 622 490 default: 623 491 return false; 624 492 } ··· 637 497 return cxlctl_get_supported_features(cxlfs, rpc_in, out_len); 638 498 case CXL_MBOX_OP_GET_FEATURE: 639 499 return cxlctl_get_feature(cxlfs, rpc_in, out_len); 500 + case CXL_MBOX_OP_SET_FEATURE: 501 + return cxlctl_set_feature(cxlfs, rpc_in, out_len); 640 502 default: 641 503 return ERR_PTR(-EOPNOTSUPP); 642 504 }
+2
include/uapi/fwctl/cxl.h
··· 19 19 * @reserved1: Reserved. Must be 0s. 20 20 * @get_sup_feats_in: Get Supported Features input 21 21 * @get_feat_in: Get Feature input 22 + * @set_feat_in: Set Feature input 22 23 */ 23 24 struct fwctl_rpc_cxl { 24 25 __struct_group(fwctl_rpc_cxl_hdr, hdr, /* no attrs */, ··· 31 30 union { 32 31 struct cxl_mbox_get_sup_feats_in get_sup_feats_in; 33 32 struct cxl_mbox_get_feat_in get_feat_in; 33 + struct cxl_mbox_set_feat_in set_feat_in; 34 34 }; 35 35 }; 36 36