From patchwork Thu Jul 18 21:32:19 2024 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Dave Jiang X-Patchwork-Id: 13736738 Received: from smtp.kernel.org (aws-us-west-2-korg-mail-1.web.codeaurora.org [10.30.226.201]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by smtp.subspace.kernel.org (Postfix) with ESMTPS id 25BF875808 for ; Thu, 18 Jul 2024 21:34:52 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=10.30.226.201 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1721338492; cv=none; b=dy29yrEp7wambr/hEpvb8TNZVJBRih9R4D0o6EgeZUtPaI2/+bt2JaV6RwJ1c8fs3+b0QmqiqCqET7/13cnmdMu95o3WLGWs0KBcySzTLiOoNbpBwbW8DzfcmHwzsS5MnU33fkt325he/LmemWyNOdTrw3rQXPGk+ItlTQi9/HY= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1721338492; c=relaxed/simple; bh=QuTBfNdTVe3plwJUrdNG9xZ4YQCOHibzTtPc1skfEa4=; h=From:To:Cc:Subject:Date:Message-ID:In-Reply-To:References: MIME-Version; b=DvVR0aMO/BSXdoFIYZjFPAZYR1jZCTe4Jzg4gsKCDu1kz26WhrmouRARCjrYaQzDI3m94jGi0SKkvwxZ6l7MD66bVW9GEMgRUyePC16MhfhvOnHCtyNq2RGksNm4a8cJaJkgZhsXLycsRbLd6koSDF9ZKB/JdDrL4cyvxfIi/G8= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; arc=none smtp.client-ip=10.30.226.201 Received: by smtp.kernel.org (Postfix) with ESMTPSA id B8873C4AF09; Thu, 18 Jul 2024 21:34:51 +0000 (UTC) From: Dave Jiang To: linux-cxl@vger.kernel.org Cc: dan.j.williams@intel.com, ira.weiny@intel.com, vishal.l.verma@intel.com, alison.schofield@intel.com, Jonathan.Cameron@huawei.com, dave@stgolabs.net, jgg@nvidia.com, shiju.jose@huawei.com Subject: [RFC PATCH 01/13] cxl: Move mailbox related bits to the same context Date: Thu, 18 Jul 2024 14:32:19 -0700 Message-ID: <20240718213446.1750135-2-dave.jiang@intel.com> X-Mailer: git-send-email 2.45.2 In-Reply-To: <20240718213446.1750135-1-dave.jiang@intel.com> References: <20240718213446.1750135-1-dave.jiang@intel.com> Precedence: bulk X-Mailing-List: linux-cxl@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 Create a new 'struct cxl_mailbox' and move all mailbox related bits to it. This allows isolation of all CXL mailbox data in order to export some of the calls to external caller (fwctl) and avoid exporting of CXL driver specific bits such has device states. Signed-off-by: Dave Jiang --- MAINTAINERS | 1 + drivers/cxl/core/mbox.c | 48 ++++++++++++++++++--------- drivers/cxl/core/memdev.c | 18 +++++++---- drivers/cxl/cxlmem.h | 49 ++-------------------------- drivers/cxl/pci.c | 58 +++++++++++++++++++-------------- drivers/cxl/pmem.c | 4 ++- include/linux/cxl/mailbox.h | 63 ++++++++++++++++++++++++++++++++++++ tools/testing/cxl/test/mem.c | 27 ++++++++++------ 8 files changed, 163 insertions(+), 105 deletions(-) create mode 100644 include/linux/cxl/mailbox.h diff --git a/MAINTAINERS b/MAINTAINERS index 9a8ca772b186..3e1934b7e044 100644 --- a/MAINTAINERS +++ b/MAINTAINERS @@ -5466,6 +5466,7 @@ S: Maintained F: drivers/cxl/ F: include/linux/einj-cxl.h F: include/linux/cxl-event.h +F: include/linux/cxl/ F: include/uapi/linux/cxl_mem.h F: tools/testing/cxl/ diff --git a/drivers/cxl/core/mbox.c b/drivers/cxl/core/mbox.c index 2626f3fff201..783cb5ed823f 100644 --- a/drivers/cxl/core/mbox.c +++ b/drivers/cxl/core/mbox.c @@ -244,16 +244,17 @@ static const char *cxl_mem_opcode_to_name(u16 opcode) int cxl_internal_send_cmd(struct cxl_memdev_state *mds, struct cxl_mbox_cmd *mbox_cmd) { + struct cxl_mailbox *cxl_mbox = &mds->cxlds.cxl_mbox; size_t out_size, min_out; int rc; - if (mbox_cmd->size_in > mds->payload_size || - mbox_cmd->size_out > mds->payload_size) + if (mbox_cmd->size_in > cxl_mbox->payload_size || + mbox_cmd->size_out > cxl_mbox->payload_size) return -E2BIG; out_size = mbox_cmd->size_out; min_out = mbox_cmd->min_out; - rc = mds->mbox_send(mds, mbox_cmd); + rc = cxl_mbox->mbox_send(cxl_mbox, mbox_cmd); /* * EIO is reserved for a payload size mismatch and mbox_send() * may not return this error. @@ -353,6 +354,7 @@ static int cxl_mbox_cmd_ctor(struct cxl_mbox_cmd *mbox, struct cxl_memdev_state *mds, u16 opcode, size_t in_size, size_t out_size, u64 in_payload) { + struct cxl_mailbox *cxl_mbox = &mds->cxlds.cxl_mbox; *mbox = (struct cxl_mbox_cmd) { .opcode = opcode, .size_in = in_size, @@ -374,7 +376,7 @@ static int cxl_mbox_cmd_ctor(struct cxl_mbox_cmd *mbox, /* Prepare to handle a full payload for variable sized output */ if (out_size == CXL_VARIABLE_PAYLOAD) - mbox->size_out = mds->payload_size; + mbox->size_out = cxl_mbox->payload_size; else mbox->size_out = out_size; @@ -398,6 +400,8 @@ static int cxl_to_mem_cmd_raw(struct cxl_mem_command *mem_cmd, const struct cxl_send_command *send_cmd, struct cxl_memdev_state *mds) { + struct cxl_mailbox *cxl_mbox = &mds->cxlds.cxl_mbox; + if (send_cmd->raw.rsvd) return -EINVAL; @@ -406,7 +410,7 @@ static int cxl_to_mem_cmd_raw(struct cxl_mem_command *mem_cmd, * gets passed along without further checking, so it must be * validated here. */ - if (send_cmd->out.size > mds->payload_size) + if (send_cmd->out.size > cxl_mbox->payload_size) return -EINVAL; if (!cxl_mem_raw_command_allowed(send_cmd->raw.opcode)) @@ -494,6 +498,7 @@ static int cxl_validate_cmd_from_user(struct cxl_mbox_cmd *mbox_cmd, struct cxl_memdev_state *mds, const struct cxl_send_command *send_cmd) { + struct cxl_mailbox *cxl_mbox = &mds->cxlds.cxl_mbox; struct cxl_mem_command mem_cmd; int rc; @@ -505,7 +510,7 @@ static int cxl_validate_cmd_from_user(struct cxl_mbox_cmd *mbox_cmd, * supports, but output can be arbitrarily large (simply write out as * much data as the hardware provides). */ - if (send_cmd->in.size > mds->payload_size) + if (send_cmd->in.size > cxl_mbox->payload_size) return -EINVAL; /* Sanitize and construct a cxl_mem_command */ @@ -591,6 +596,7 @@ static int handle_mailbox_cmd_from_user(struct cxl_memdev_state *mds, u64 out_payload, s32 *size_out, u32 *retval) { + struct cxl_mailbox *cxl_mbox = &mds->cxlds.cxl_mbox; struct device *dev = mds->cxlds.dev; int rc; @@ -601,7 +607,7 @@ static int handle_mailbox_cmd_from_user(struct cxl_memdev_state *mds, cxl_mem_opcode_to_name(mbox_cmd->opcode), mbox_cmd->opcode, mbox_cmd->size_in); - rc = mds->mbox_send(mds, mbox_cmd); + rc = cxl_mbox->mbox_send(cxl_mbox, mbox_cmd); if (rc) goto out; @@ -659,11 +665,12 @@ int cxl_send_cmd(struct cxl_memdev *cxlmd, struct cxl_send_command __user *s) static int cxl_xfer_log(struct cxl_memdev_state *mds, uuid_t *uuid, u32 *size, u8 *out) { + struct cxl_mailbox *cxl_mbox = &mds->cxlds.cxl_mbox; u32 remaining = *size; u32 offset = 0; while (remaining) { - u32 xfer_size = min_t(u32, remaining, mds->payload_size); + u32 xfer_size = min_t(u32, remaining, cxl_mbox->payload_size); struct cxl_mbox_cmd mbox_cmd; struct cxl_mbox_get_log log; int rc; @@ -752,17 +759,18 @@ static void cxl_walk_cel(struct cxl_memdev_state *mds, size_t size, u8 *cel) static struct cxl_mbox_get_supported_logs *cxl_get_gsl(struct cxl_memdev_state *mds) { + struct cxl_mailbox *cxl_mbox = &mds->cxlds.cxl_mbox; struct cxl_mbox_get_supported_logs *ret; struct cxl_mbox_cmd mbox_cmd; int rc; - ret = kvmalloc(mds->payload_size, GFP_KERNEL); + ret = kvmalloc(cxl_mbox->payload_size, GFP_KERNEL); if (!ret) return ERR_PTR(-ENOMEM); mbox_cmd = (struct cxl_mbox_cmd) { .opcode = CXL_MBOX_OP_GET_SUPPORTED_LOGS, - .size_out = mds->payload_size, + .size_out = cxl_mbox->payload_size, .payload_out = ret, /* At least the record number field must be valid */ .min_out = 2, @@ -910,6 +918,7 @@ static int cxl_clear_event_record(struct cxl_memdev_state *mds, enum cxl_event_log_type log, struct cxl_get_event_payload *get_pl) { + struct cxl_mailbox *cxl_mbox = &mds->cxlds.cxl_mbox; struct cxl_mbox_clear_event_payload *payload; u16 total = le16_to_cpu(get_pl->record_count); u8 max_handles = CXL_CLEAR_EVENT_MAX_HANDLES; @@ -920,8 +929,8 @@ static int cxl_clear_event_record(struct cxl_memdev_state *mds, int i; /* Payload size may limit the max handles */ - if (pl_size > mds->payload_size) { - max_handles = (mds->payload_size - sizeof(*payload)) / + if (pl_size > cxl_mbox->payload_size) { + max_handles = (cxl_mbox->payload_size - sizeof(*payload)) / sizeof(__le16); pl_size = struct_size(payload, handles, max_handles); } @@ -979,6 +988,7 @@ static int cxl_clear_event_record(struct cxl_memdev_state *mds, static void cxl_mem_get_records_log(struct cxl_memdev_state *mds, enum cxl_event_log_type type) { + struct cxl_mailbox *cxl_mbox = &mds->cxlds.cxl_mbox; struct cxl_memdev *cxlmd = mds->cxlds.cxlmd; struct device *dev = mds->cxlds.dev; struct cxl_get_event_payload *payload; @@ -995,7 +1005,7 @@ static void cxl_mem_get_records_log(struct cxl_memdev_state *mds, .payload_in = &log_type, .size_in = sizeof(log_type), .payload_out = payload, - .size_out = mds->payload_size, + .size_out = cxl_mbox->payload_size, .min_out = struct_size(payload, records, 0), }; @@ -1328,6 +1338,7 @@ int cxl_mem_get_poison(struct cxl_memdev *cxlmd, u64 offset, u64 len, struct cxl_region *cxlr) { struct cxl_memdev_state *mds = to_cxl_memdev_state(cxlmd->cxlds); + struct cxl_mailbox *cxl_mbox = &mds->cxlds.cxl_mbox; struct cxl_mbox_poison_out *po; struct cxl_mbox_poison_in pi; int nr_records = 0; @@ -1346,7 +1357,7 @@ int cxl_mem_get_poison(struct cxl_memdev *cxlmd, u64 offset, u64 len, .opcode = CXL_MBOX_OP_GET_POISON, .size_in = sizeof(pi), .payload_in = &pi, - .size_out = mds->payload_size, + .size_out = cxl_mbox->payload_size, .payload_out = po, .min_out = struct_size(po, record, 0), }; @@ -1382,7 +1393,9 @@ static void free_poison_buf(void *buf) /* Get Poison List output buffer is protected by mds->poison.lock */ static int cxl_poison_alloc_buf(struct cxl_memdev_state *mds) { - mds->poison.list_out = kvmalloc(mds->payload_size, GFP_KERNEL); + struct cxl_mailbox *cxl_mbox = &mds->cxlds.cxl_mbox; + + mds->poison.list_out = kvmalloc(cxl_mbox->payload_size, GFP_KERNEL); if (!mds->poison.list_out) return -ENOMEM; @@ -1411,6 +1424,7 @@ EXPORT_SYMBOL_NS_GPL(cxl_poison_state_init, CXL); struct cxl_memdev_state *cxl_memdev_state_create(struct device *dev) { struct cxl_memdev_state *mds; + struct cxl_mailbox *cxl_mbox; mds = devm_kzalloc(dev, sizeof(*mds), GFP_KERNEL); if (!mds) { @@ -1418,7 +1432,9 @@ struct cxl_memdev_state *cxl_memdev_state_create(struct device *dev) return ERR_PTR(-ENOMEM); } - mutex_init(&mds->mbox_mutex); + cxl_mbox = &mds->cxlds.cxl_mbox; + mutex_init(&cxl_mbox->mbox_mutex); + mutex_init(&mds->event.log_lock); mds->cxlds.dev = dev; mds->cxlds.reg_map.host = dev; diff --git a/drivers/cxl/core/memdev.c b/drivers/cxl/core/memdev.c index 0277726afd04..05bb84cb1274 100644 --- a/drivers/cxl/core/memdev.c +++ b/drivers/cxl/core/memdev.c @@ -58,7 +58,7 @@ static ssize_t payload_max_show(struct device *dev, if (!mds) return sysfs_emit(buf, "\n"); - return sysfs_emit(buf, "%zu\n", mds->payload_size); + return sysfs_emit(buf, "%zu\n", cxlds->cxl_mbox.payload_size); } static DEVICE_ATTR_RO(payload_max); @@ -124,15 +124,16 @@ static ssize_t security_state_show(struct device *dev, { struct cxl_memdev *cxlmd = to_cxl_memdev(dev); struct cxl_dev_state *cxlds = cxlmd->cxlds; + struct cxl_mailbox *cxl_mbox = &cxlds->cxl_mbox; struct cxl_memdev_state *mds = to_cxl_memdev_state(cxlds); unsigned long state = mds->security.state; int rc = 0; /* sync with latest submission state */ - mutex_lock(&mds->mbox_mutex); + mutex_lock(&cxl_mbox->mbox_mutex); if (mds->security.sanitize_active) rc = sysfs_emit(buf, "sanitize\n"); - mutex_unlock(&mds->mbox_mutex); + mutex_unlock(&cxl_mbox->mbox_mutex); if (rc) return rc; @@ -829,12 +830,13 @@ static enum fw_upload_err cxl_fw_prepare(struct fw_upload *fwl, const u8 *data, { struct cxl_memdev_state *mds = fwl->dd_handle; struct cxl_mbox_transfer_fw *transfer; + struct cxl_mailbox *cxl_mbox = &mds->cxlds.cxl_mbox; if (!size) return FW_UPLOAD_ERR_INVALID_SIZE; mds->fw.oneshot = struct_size(transfer, data, size) < - mds->payload_size; + cxl_mbox->payload_size; if (cxl_mem_get_fw_info(mds)) return FW_UPLOAD_ERR_HW_ERROR; @@ -854,6 +856,7 @@ static enum fw_upload_err cxl_fw_write(struct fw_upload *fwl, const u8 *data, { struct cxl_memdev_state *mds = fwl->dd_handle; struct cxl_dev_state *cxlds = &mds->cxlds; + struct cxl_mailbox *cxl_mbox = &cxlds->cxl_mbox; struct cxl_memdev *cxlmd = cxlds->cxlmd; struct cxl_mbox_transfer_fw *transfer; struct cxl_mbox_cmd mbox_cmd; @@ -877,7 +880,7 @@ static enum fw_upload_err cxl_fw_write(struct fw_upload *fwl, const u8 *data, * sizeof(*transfer) is 128. These constraints imply that @cur_size * will always be 128b aligned. */ - cur_size = min_t(size_t, size, mds->payload_size - sizeof(*transfer)); + cur_size = min_t(size_t, size, cxl_mbox->payload_size - sizeof(*transfer)); remaining = size - cur_size; size_in = struct_size(transfer, data, cur_size); @@ -1059,16 +1062,17 @@ EXPORT_SYMBOL_NS_GPL(devm_cxl_add_memdev, CXL); static void sanitize_teardown_notifier(void *data) { struct cxl_memdev_state *mds = data; + struct cxl_mailbox *cxl_mbox = &mds->cxlds.cxl_mbox; struct kernfs_node *state; /* * Prevent new irq triggered invocations of the workqueue and * flush inflight invocations. */ - mutex_lock(&mds->mbox_mutex); + mutex_lock(&cxl_mbox->mbox_mutex); state = mds->security.sanitize_node; mds->security.sanitize_node = NULL; - mutex_unlock(&mds->mbox_mutex); + mutex_unlock(&cxl_mbox->mbox_mutex); cancel_delayed_work_sync(&mds->security.poll_dwork); sysfs_put(state); diff --git a/drivers/cxl/cxlmem.h b/drivers/cxl/cxlmem.h index af8169ccdbc0..8f683fe08410 100644 --- a/drivers/cxl/cxlmem.h +++ b/drivers/cxl/cxlmem.h @@ -8,6 +8,7 @@ #include #include #include +#include #include "cxl.h" /* CXL 2.0 8.2.8.5.1.1 Memory Device Status Register */ @@ -105,42 +106,6 @@ static inline struct cxl_ep *cxl_ep_load(struct cxl_port *port, return xa_load(&port->endpoints, (unsigned long)&cxlmd->dev); } -/** - * struct cxl_mbox_cmd - A command to be submitted to hardware. - * @opcode: (input) The command set and command submitted to hardware. - * @payload_in: (input) Pointer to the input payload. - * @payload_out: (output) Pointer to the output payload. Must be allocated by - * the caller. - * @size_in: (input) Number of bytes to load from @payload_in. - * @size_out: (input) Max number of bytes loaded into @payload_out. - * (output) Number of bytes generated by the device. For fixed size - * outputs commands this is always expected to be deterministic. For - * variable sized output commands, it tells the exact number of bytes - * written. - * @min_out: (input) internal command output payload size validation - * @poll_count: (input) Number of timeouts to attempt. - * @poll_interval_ms: (input) Time between mailbox background command polling - * interval timeouts. - * @return_code: (output) Error code returned from hardware. - * - * This is the primary mechanism used to send commands to the hardware. - * All the fields except @payload_* correspond exactly to the fields described in - * Command Register section of the CXL 2.0 8.2.8.4.5. @payload_in and - * @payload_out are written to, and read from the Command Payload Registers - * defined in CXL 2.0 8.2.8.4.8. - */ -struct cxl_mbox_cmd { - u16 opcode; - void *payload_in; - void *payload_out; - size_t size_in; - size_t size_out; - size_t min_out; - int poll_count; - int poll_interval_ms; - u16 return_code; -}; - /* * Per CXL 3.0 Section 8.2.8.4.5.1 */ @@ -438,6 +403,7 @@ struct cxl_dev_state { struct resource ram_res; u64 serial; enum cxl_devtype type; + struct cxl_mailbox cxl_mbox; }; /** @@ -448,11 +414,8 @@ struct cxl_dev_state { * the functionality related to that like Identify Memory Device and Get * Partition Info * @cxlds: Core driver state common across Type-2 and Type-3 devices - * @payload_size: Size of space for payload - * (CXL 2.0 8.2.8.4.3 Mailbox Capabilities Register) * @lsa_size: Size of Label Storage Area * (CXL 2.0 8.2.9.5.1.1 Identify Memory Device) - * @mbox_mutex: Mutex to synchronize mailbox access. * @firmware_version: Firmware version for the memory device. * @enabled_cmds: Hardware commands found enabled in CEL. * @exclusive_cmds: Commands that are kernel-internal only @@ -470,17 +433,13 @@ struct cxl_dev_state { * @poison: poison driver state info * @security: security driver state info * @fw: firmware upload / activation state - * @mbox_wait: RCU wait for mbox send completely - * @mbox_send: @dev specific transport for transmitting mailbox commands * * See CXL 3.0 8.2.9.8.2 Capacity Configuration and Label Storage for * details on capacity parameters. */ struct cxl_memdev_state { struct cxl_dev_state cxlds; - size_t payload_size; size_t lsa_size; - struct mutex mbox_mutex; /* Protects device mailbox and firmware */ char firmware_version[0x10]; DECLARE_BITMAP(enabled_cmds, CXL_MEM_COMMAND_ID_MAX); DECLARE_BITMAP(exclusive_cmds, CXL_MEM_COMMAND_ID_MAX); @@ -500,10 +459,6 @@ struct cxl_memdev_state { struct cxl_poison_state poison; struct cxl_security_state security; struct cxl_fw_state fw; - - struct rcuwait mbox_wait; - int (*mbox_send)(struct cxl_memdev_state *mds, - struct cxl_mbox_cmd *cmd); }; static inline struct cxl_memdev_state * diff --git a/drivers/cxl/pci.c b/drivers/cxl/pci.c index e53646e9f2fb..45b184b6ef97 100644 --- a/drivers/cxl/pci.c +++ b/drivers/cxl/pci.c @@ -124,6 +124,7 @@ static irqreturn_t cxl_pci_mbox_irq(int irq, void *id) u16 opcode; struct cxl_dev_id *dev_id = id; struct cxl_dev_state *cxlds = dev_id->cxlds; + struct cxl_mailbox *cxl_mbox = &cxlds->cxl_mbox; struct cxl_memdev_state *mds = to_cxl_memdev_state(cxlds); if (!cxl_mbox_background_complete(cxlds)) @@ -132,13 +133,13 @@ static irqreturn_t cxl_pci_mbox_irq(int irq, void *id) reg = readq(cxlds->regs.mbox + CXLDEV_MBOX_BG_CMD_STATUS_OFFSET); opcode = FIELD_GET(CXLDEV_MBOX_BG_CMD_COMMAND_OPCODE_MASK, reg); if (opcode == CXL_MBOX_OP_SANITIZE) { - mutex_lock(&mds->mbox_mutex); + mutex_lock(&cxl_mbox->mbox_mutex); if (mds->security.sanitize_node) mod_delayed_work(system_wq, &mds->security.poll_dwork, 0); - mutex_unlock(&mds->mbox_mutex); + mutex_unlock(&cxl_mbox->mbox_mutex); } else { /* short-circuit the wait in __cxl_pci_mbox_send_cmd() */ - rcuwait_wake_up(&mds->mbox_wait); + rcuwait_wake_up(&cxl_mbox->mbox_wait); } return IRQ_HANDLED; @@ -152,8 +153,9 @@ static void cxl_mbox_sanitize_work(struct work_struct *work) struct cxl_memdev_state *mds = container_of(work, typeof(*mds), security.poll_dwork.work); struct cxl_dev_state *cxlds = &mds->cxlds; + struct cxl_mailbox *cxl_mbox = &cxlds->cxl_mbox; - mutex_lock(&mds->mbox_mutex); + mutex_lock(&cxl_mbox->mbox_mutex); if (cxl_mbox_background_complete(cxlds)) { mds->security.poll_tmo_secs = 0; if (mds->security.sanitize_node) @@ -167,7 +169,7 @@ static void cxl_mbox_sanitize_work(struct work_struct *work) mds->security.poll_tmo_secs = min(15 * 60, timeout); schedule_delayed_work(&mds->security.poll_dwork, timeout * HZ); } - mutex_unlock(&mds->mbox_mutex); + mutex_unlock(&cxl_mbox->mbox_mutex); } /** @@ -192,17 +194,20 @@ static void cxl_mbox_sanitize_work(struct work_struct *work) * not need to coordinate with each other. The driver only uses the primary * mailbox. */ -static int __cxl_pci_mbox_send_cmd(struct cxl_memdev_state *mds, +static int __cxl_pci_mbox_send_cmd(struct cxl_mailbox *cxl_mbox, struct cxl_mbox_cmd *mbox_cmd) { - struct cxl_dev_state *cxlds = &mds->cxlds; + struct cxl_dev_state *cxlds = container_of(cxl_mbox, + struct cxl_dev_state, + cxl_mbox); + struct cxl_memdev_state *mds = to_cxl_memdev_state(cxlds); void __iomem *payload = cxlds->regs.mbox + CXLDEV_MBOX_PAYLOAD_OFFSET; struct device *dev = cxlds->dev; u64 cmd_reg, status_reg; size_t out_len; int rc; - lockdep_assert_held(&mds->mbox_mutex); + lockdep_assert_held(&cxl_mbox->mbox_mutex); /* * Here are the steps from 8.2.8.4 of the CXL 2.0 spec. @@ -315,10 +320,10 @@ static int __cxl_pci_mbox_send_cmd(struct cxl_memdev_state *mds, timeout = mbox_cmd->poll_interval_ms; for (i = 0; i < mbox_cmd->poll_count; i++) { - if (rcuwait_wait_event_timeout(&mds->mbox_wait, - cxl_mbox_background_complete(cxlds), - TASK_UNINTERRUPTIBLE, - msecs_to_jiffies(timeout)) > 0) + if (rcuwait_wait_event_timeout(&cxl_mbox->mbox_wait, + cxl_mbox_background_complete(cxlds), + TASK_UNINTERRUPTIBLE, + msecs_to_jiffies(timeout)) > 0) break; } @@ -360,7 +365,7 @@ static int __cxl_pci_mbox_send_cmd(struct cxl_memdev_state *mds, */ size_t n; - n = min3(mbox_cmd->size_out, mds->payload_size, out_len); + n = min3(mbox_cmd->size_out, cxl_mbox->payload_size, out_len); memcpy_fromio(mbox_cmd->payload_out, payload, n); mbox_cmd->size_out = n; } else { @@ -370,14 +375,14 @@ static int __cxl_pci_mbox_send_cmd(struct cxl_memdev_state *mds, return 0; } -static int cxl_pci_mbox_send(struct cxl_memdev_state *mds, +static int cxl_pci_mbox_send(struct cxl_mailbox *cxl_mbox, struct cxl_mbox_cmd *cmd) { int rc; - mutex_lock_io(&mds->mbox_mutex); - rc = __cxl_pci_mbox_send_cmd(mds, cmd); - mutex_unlock(&mds->mbox_mutex); + mutex_lock_io(&cxl_mbox->mbox_mutex); + rc = __cxl_pci_mbox_send_cmd(cxl_mbox, cmd); + mutex_unlock(&cxl_mbox->mbox_mutex); return rc; } @@ -385,6 +390,7 @@ static int cxl_pci_mbox_send(struct cxl_memdev_state *mds, static int cxl_pci_setup_mailbox(struct cxl_memdev_state *mds, bool irq_avail) { struct cxl_dev_state *cxlds = &mds->cxlds; + struct cxl_mailbox *cxl_mbox = &cxlds->cxl_mbox; const int cap = readl(cxlds->regs.mbox + CXLDEV_MBOX_CAPS_OFFSET); struct device *dev = cxlds->dev; unsigned long timeout; @@ -392,6 +398,7 @@ static int cxl_pci_setup_mailbox(struct cxl_memdev_state *mds, bool irq_avail) u64 md_status; u32 ctrl; + cxl_mbox->host = dev; timeout = jiffies + mbox_ready_timeout * HZ; do { md_status = readq(cxlds->regs.memdev + CXLMDEV_STATUS_OFFSET); @@ -417,8 +424,8 @@ static int cxl_pci_setup_mailbox(struct cxl_memdev_state *mds, bool irq_avail) return -ETIMEDOUT; } - mds->mbox_send = cxl_pci_mbox_send; - mds->payload_size = + cxl_mbox->mbox_send = cxl_pci_mbox_send; + cxl_mbox->payload_size = 1 << FIELD_GET(CXLDEV_MBOX_CAP_PAYLOAD_SIZE_MASK, cap); /* @@ -428,16 +435,16 @@ static int cxl_pci_setup_mailbox(struct cxl_memdev_state *mds, bool irq_avail) * there's no point in going forward. If the size is too large, there's * no harm is soft limiting it. */ - mds->payload_size = min_t(size_t, mds->payload_size, SZ_1M); - if (mds->payload_size < 256) { + cxl_mbox->payload_size = min_t(size_t, cxl_mbox->payload_size, SZ_1M); + if (cxl_mbox->payload_size < 256) { dev_err(dev, "Mailbox is too small (%zub)", - mds->payload_size); + cxl_mbox->payload_size); return -ENXIO; } - dev_dbg(dev, "Mailbox payload sized %zu", mds->payload_size); + dev_dbg(dev, "Mailbox payload sized %zu", cxl_mbox->payload_size); - rcuwait_init(&mds->mbox_wait); + rcuwait_init(&cxl_mbox->mbox_wait); INIT_DELAYED_WORK(&mds->security.poll_dwork, cxl_mbox_sanitize_work); /* background command interrupts are optional */ @@ -578,9 +585,10 @@ static void free_event_buf(void *buf) */ static int cxl_mem_alloc_event_buf(struct cxl_memdev_state *mds) { + struct cxl_mailbox *cxl_mbox = &mds->cxlds.cxl_mbox; struct cxl_get_event_payload *buf; - buf = kvmalloc(mds->payload_size, GFP_KERNEL); + buf = kvmalloc(cxl_mbox->payload_size, GFP_KERNEL); if (!buf) return -ENOMEM; mds->event.buf = buf; diff --git a/drivers/cxl/pmem.c b/drivers/cxl/pmem.c index 2ecdaee63021..9f62dc03c883 100644 --- a/drivers/cxl/pmem.c +++ b/drivers/cxl/pmem.c @@ -102,13 +102,15 @@ static int cxl_pmem_get_config_size(struct cxl_memdev_state *mds, struct nd_cmd_get_config_size *cmd, unsigned int buf_len) { + struct cxl_mailbox *cxl_mbox = &mds->cxlds.cxl_mbox; + if (sizeof(*cmd) > buf_len) return -EINVAL; *cmd = (struct nd_cmd_get_config_size){ .config_size = mds->lsa_size, .max_xfer = - mds->payload_size - sizeof(struct cxl_mbox_set_lsa), + cxl_mbox->payload_size - sizeof(struct cxl_mbox_set_lsa), }; return 0; diff --git a/include/linux/cxl/mailbox.h b/include/linux/cxl/mailbox.h new file mode 100644 index 000000000000..654df6175828 --- /dev/null +++ b/include/linux/cxl/mailbox.h @@ -0,0 +1,63 @@ +/* SPDX-License-Identifier: GPL-2.0-only */ +/* Copyright(c) 2024 Intel Corporation. */ +#ifndef __CXL_MBOX_H__ +#define __CXL_MBOX_H__ + +#include + +/** + * struct cxl_mbox_cmd - A command to be submitted to hardware. + * @opcode: (input) The command set and command submitted to hardware. + * @payload_in: (input) Pointer to the input payload. + * @payload_out: (output) Pointer to the output payload. Must be allocated by + * the caller. + * @size_in: (input) Number of bytes to load from @payload_in. + * @size_out: (input) Max number of bytes loaded into @payload_out. + * (output) Number of bytes generated by the device. For fixed size + * outputs commands this is always expected to be deterministic. For + * variable sized output commands, it tells the exact number of bytes + * written. + * @min_out: (input) internal command output payload size validation + * @poll_count: (input) Number of timeouts to attempt. + * @poll_interval_ms: (input) Time between mailbox background command polling + * interval timeouts. + * @return_code: (output) Error code returned from hardware. + * + * This is the primary mechanism used to send commands to the hardware. + * All the fields except @payload_* correspond exactly to the fields described in + * Command Register section of the CXL 2.0 8.2.8.4.5. @payload_in and + * @payload_out are written to, and read from the Command Payload Registers + * defined in CXL 2.0 8.2.8.4.8. + */ +struct cxl_mbox_cmd { + u16 opcode; + void *payload_in; + void *payload_out; + size_t size_in; + size_t size_out; + size_t min_out; + int poll_count; + int poll_interval_ms; + u16 return_code; +}; + +/** + * struct cxl_mailbox - context for CXL mailbox operations + * @host: device that hosts the mailbox + * @adev: auxiliary device for fw-ctl + * @payload_size: Size of space for payload + * (CXL 3.1 8.2.8.4.3 Mailbox Capabilities Register) + * @mbox_mutex: mutex protects device mailbox and firmware + * @mbox_wait: rcuwait for mailbox + * @mbox_send: @dev specific transport for transmitting mailbox commands + */ +struct cxl_mailbox { + struct device *host; + struct auxiliary_device adev; /* For fw-ctl */ + size_t payload_size; + struct mutex mbox_mutex; /* lock to protect mailbox context */ + struct rcuwait mbox_wait; + int (*mbox_send)(struct cxl_mailbox *cxl_mbox, struct cxl_mbox_cmd *cmd); +}; + +#endif diff --git a/tools/testing/cxl/test/mem.c b/tools/testing/cxl/test/mem.c index eaf091a3d331..20d58f883ca2 100644 --- a/tools/testing/cxl/test/mem.c +++ b/tools/testing/cxl/test/mem.c @@ -8,6 +8,7 @@ #include #include #include +#include #include #include #include @@ -530,6 +531,7 @@ static int mock_gsl(struct cxl_mbox_cmd *cmd) static int mock_get_log(struct cxl_memdev_state *mds, struct cxl_mbox_cmd *cmd) { + struct cxl_mailbox *cxl_mbox = &mds->cxlds.cxl_mbox; struct cxl_mbox_get_log *gl = cmd->payload_in; u32 offset = le32_to_cpu(gl->offset); u32 length = le32_to_cpu(gl->length); @@ -538,7 +540,7 @@ static int mock_get_log(struct cxl_memdev_state *mds, struct cxl_mbox_cmd *cmd) if (cmd->size_in < sizeof(*gl)) return -EINVAL; - if (length > mds->payload_size) + if (length > cxl_mbox->payload_size) return -EINVAL; if (offset + length > sizeof(mock_cel)) return -EINVAL; @@ -613,12 +615,13 @@ void cxl_mockmem_sanitize_work(struct work_struct *work) { struct cxl_memdev_state *mds = container_of(work, typeof(*mds), security.poll_dwork.work); + struct cxl_mailbox *cxl_mbox = &mds->cxlds.cxl_mbox; - mutex_lock(&mds->mbox_mutex); + mutex_lock(&cxl_mbox->mbox_mutex); if (mds->security.sanitize_node) sysfs_notify_dirent(mds->security.sanitize_node); mds->security.sanitize_active = false; - mutex_unlock(&mds->mbox_mutex); + mutex_unlock(&cxl_mbox->mbox_mutex); dev_dbg(mds->cxlds.dev, "sanitize complete\n"); } @@ -627,6 +630,7 @@ static int mock_sanitize(struct cxl_mockmem_data *mdata, struct cxl_mbox_cmd *cmd) { struct cxl_memdev_state *mds = mdata->mds; + struct cxl_mailbox *cxl_mbox = &mds->cxlds.cxl_mbox; int rc = 0; if (cmd->size_in != 0) @@ -644,14 +648,14 @@ static int mock_sanitize(struct cxl_mockmem_data *mdata, return -ENXIO; } - mutex_lock(&mds->mbox_mutex); + mutex_lock(&cxl_mbox->mbox_mutex); if (schedule_delayed_work(&mds->security.poll_dwork, msecs_to_jiffies(mdata->sanitize_timeout))) { mds->security.sanitize_active = true; dev_dbg(mds->cxlds.dev, "sanitize issued\n"); } else rc = -EBUSY; - mutex_unlock(&mds->mbox_mutex); + mutex_unlock(&cxl_mbox->mbox_mutex); return rc; } @@ -1330,10 +1334,13 @@ static int mock_activate_fw(struct cxl_mockmem_data *mdata, return -EINVAL; } -static int cxl_mock_mbox_send(struct cxl_memdev_state *mds, +static int cxl_mock_mbox_send(struct cxl_mailbox *cxl_mbox, struct cxl_mbox_cmd *cmd) { - struct cxl_dev_state *cxlds = &mds->cxlds; + struct cxl_dev_state *cxlds = container_of(cxl_mbox, + struct cxl_dev_state, + cxl_mbox); + struct cxl_memdev_state *mds = to_cxl_memdev_state(cxlds); struct device *dev = cxlds->dev; struct cxl_mockmem_data *mdata = dev_get_drvdata(dev); int rc = -EIO; @@ -1457,6 +1464,7 @@ static int cxl_mock_mem_probe(struct platform_device *pdev) struct cxl_memdev_state *mds; struct cxl_dev_state *cxlds; struct cxl_mockmem_data *mdata; + struct cxl_mailbox *cxl_mbox; int rc; mdata = devm_kzalloc(dev, sizeof(*mdata), GFP_KERNEL); @@ -1484,9 +1492,10 @@ static int cxl_mock_mem_probe(struct platform_device *pdev) if (IS_ERR(mds)) return PTR_ERR(mds); + cxl_mbox = &mds->cxlds.cxl_mbox; mdata->mds = mds; - mds->mbox_send = cxl_mock_mbox_send; - mds->payload_size = SZ_4K; + cxl_mbox->mbox_send = cxl_mock_mbox_send; + cxl_mbox->payload_size = SZ_4K; mds->event.buf = (struct cxl_get_event_payload *) mdata->event_buf; INIT_DELAYED_WORK(&mds->security.poll_dwork, cxl_mockmem_sanitize_work); From patchwork Thu Jul 18 21:32:20 2024 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Dave Jiang X-Patchwork-Id: 13736739 Received: from smtp.kernel.org (aws-us-west-2-korg-mail-1.web.codeaurora.org [10.30.226.201]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by smtp.subspace.kernel.org (Postfix) with ESMTPS id C6AAE75808 for ; Thu, 18 Jul 2024 21:34:53 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=10.30.226.201 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1721338493; cv=none; b=n22/edc0dTLZvzqhatcGiv9+j8UdRMxePukTZ1cqrwD3rOeE4JYpTUd5jSKsB1gsEkWm6CZrTA4V/sc50SeVGUpFGBplE1iBzSeeZ7U8UhXpehmSfTd0K735tLzmjwa4j4o7mvvY0pYrkS5mn7GwasI50fGM/NJF57xE8JyplPY= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1721338493; c=relaxed/simple; bh=HXbv5uF0ShaKaD9/MeONM3gu/hFXMsNVRnLb7uwT9Ug=; h=From:To:Cc:Subject:Date:Message-ID:In-Reply-To:References: MIME-Version; b=cRpEu4hN76BrMOnHc/uU0cQkCk7Hp0EWbbscEG3bBt7YCServ62Cc9kp68WBXG7ZHIf/VzCbRE9L+nlcWRD3UQrc4YMRy29A90mh06L9gGaFmllwCV7DCQz2RZwpf4t4yxvp/fcZrRtcIYVXCdQ3R+TwJDFUQ3He7FE0kf/WTY4= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; arc=none smtp.client-ip=10.30.226.201 Received: by smtp.kernel.org (Postfix) with ESMTPSA id 3CEC0C116B1; Thu, 18 Jul 2024 21:34:53 +0000 (UTC) From: Dave Jiang To: linux-cxl@vger.kernel.org Cc: dan.j.williams@intel.com, ira.weiny@intel.com, vishal.l.verma@intel.com, alison.schofield@intel.com, Jonathan.Cameron@huawei.com, dave@stgolabs.net, jgg@nvidia.com, shiju.jose@huawei.com Subject: [RFC PATCH 02/13] cxl: Fix comment regarding cxl_query_cmd() return data Date: Thu, 18 Jul 2024 14:32:20 -0700 Message-ID: <20240718213446.1750135-3-dave.jiang@intel.com> X-Mailer: git-send-email 2.45.2 In-Reply-To: <20240718213446.1750135-1-dave.jiang@intel.com> References: <20240718213446.1750135-1-dave.jiang@intel.com> Precedence: bulk X-Mailing-List: linux-cxl@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 The code indicates that the min of n_commands and total commands is returned. The comment incorrectly says it's the max(). Correct comment to min(). Signed-off-by: Dave Jiang --- drivers/cxl/core/mbox.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/cxl/core/mbox.c b/drivers/cxl/core/mbox.c index 783cb5ed823f..433819ac36b7 100644 --- a/drivers/cxl/core/mbox.c +++ b/drivers/cxl/core/mbox.c @@ -547,7 +547,7 @@ int cxl_query_cmd(struct cxl_memdev *cxlmd, return put_user(ARRAY_SIZE(cxl_mem_commands), &q->n_commands); /* - * otherwise, return max(n_commands, total commands) cxl_command_info + * otherwise, return min(n_commands, total commands) cxl_command_info * structures. */ cxl_for_each_cmd(cmd) { From patchwork Thu Jul 18 21:32:21 2024 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Dave Jiang X-Patchwork-Id: 13736740 Received: from smtp.kernel.org (aws-us-west-2-korg-mail-1.web.codeaurora.org [10.30.226.201]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by smtp.subspace.kernel.org (Postfix) with ESMTPS id 3C0C281751 for ; Thu, 18 Jul 2024 21:34:54 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=10.30.226.201 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1721338495; cv=none; b=ZtB9ZGl2mfZiXRK3HeVrBMKzIIVNVOqCRJg7eZQ4n/QPcs3alJbVQohU21oSM4xNdSPxKnJWyea63SMMVDLRzp81Os5zrDn6H78ZP8lnZmx22LJtf2osJ+x5x0cc5CzpWPFVhO/A+pTNpq9urDisqgGg5L3ijcm0cUwT5YV475c= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1721338495; c=relaxed/simple; bh=yeyd23qVvPv4q0D/ZFu8IXozQq4BkhyjrolCtygEQ0s=; h=From:To:Cc:Subject:Date:Message-ID:In-Reply-To:References: MIME-Version; b=MFKE/214uEYsutuFKFnjZX+fnRMfVuUtdgPiJdbxpDOlkEqVbTrjq9l6LrsJEasfxDLIuroUHawvRWCigfj46HMq40wbmlz8k4osriXkAPjLUWj4ux8Dsgd2vd3CKvOYRth+he4YSf32e9PmN25ZM0fG8FVeaAM3qGPlRS+NRfk= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; arc=none smtp.client-ip=10.30.226.201 Received: by smtp.kernel.org (Postfix) with ESMTPSA id 93CFEC4AF0B; Thu, 18 Jul 2024 21:34:54 +0000 (UTC) From: Dave Jiang To: linux-cxl@vger.kernel.org Cc: dan.j.williams@intel.com, ira.weiny@intel.com, vishal.l.verma@intel.com, alison.schofield@intel.com, Jonathan.Cameron@huawei.com, dave@stgolabs.net, jgg@nvidia.com, shiju.jose@huawei.com Subject: [RFC PATCH 03/13] cxl: Refactor user ioctl command path from mds to mailbox Date: Thu, 18 Jul 2024 14:32:21 -0700 Message-ID: <20240718213446.1750135-4-dave.jiang@intel.com> X-Mailer: git-send-email 2.45.2 In-Reply-To: <20240718213446.1750135-1-dave.jiang@intel.com> References: <20240718213446.1750135-1-dave.jiang@intel.com> Precedence: bulk X-Mailing-List: linux-cxl@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 With 'struct cxl_mailbox' context introduced, the helper functions cxl_query_cmd() and cxl_send_cmd() can take a cxl_mailbox directly rather than a cxl_memdev parameter. Refactor to use cxl_mailbox directly. Signed-off-by: Dave Jiang --- drivers/cxl/core/core.h | 6 +- drivers/cxl/core/mbox.c | 118 ++++++++++++++++++------------------ drivers/cxl/core/memdev.c | 39 ++++++++---- drivers/cxl/cxlmem.h | 6 +- drivers/cxl/pci.c | 6 +- drivers/cxl/pmem.c | 6 +- drivers/cxl/security.c | 18 ++++-- include/linux/cxl/mailbox.h | 5 ++ 8 files changed, 115 insertions(+), 89 deletions(-) diff --git a/drivers/cxl/core/core.h b/drivers/cxl/core/core.h index 625394486459..7eb33ea07848 100644 --- a/drivers/cxl/core/core.h +++ b/drivers/cxl/core/core.h @@ -4,6 +4,8 @@ #ifndef __CXL_CORE_H__ #define __CXL_CORE_H__ +#include + extern const struct device_type cxl_nvdimm_bridge_type; extern const struct device_type cxl_nvdimm_type; extern const struct device_type cxl_pmu_type; @@ -65,9 +67,9 @@ static inline void cxl_region_exit(void) struct cxl_send_command; struct cxl_mem_query_commands; -int cxl_query_cmd(struct cxl_memdev *cxlmd, +int cxl_query_cmd(struct cxl_mailbox *cxl_mbox, struct cxl_mem_query_commands __user *q); -int cxl_send_cmd(struct cxl_memdev *cxlmd, struct cxl_send_command __user *s); +int cxl_send_cmd(struct cxl_mailbox *cxl_mailbox, struct cxl_send_command __user *s); void __iomem *devm_cxl_iomap_block(struct device *dev, resource_size_t addr, resource_size_t length); diff --git a/drivers/cxl/core/mbox.c b/drivers/cxl/core/mbox.c index 433819ac36b7..b9c64f1837a8 100644 --- a/drivers/cxl/core/mbox.c +++ b/drivers/cxl/core/mbox.c @@ -225,7 +225,7 @@ static const char *cxl_mem_opcode_to_name(u16 opcode) /** * cxl_internal_send_cmd() - Kernel internal interface to send a mailbox command - * @mds: The driver data for the operation + * @cxl_mbox: CXL mailbox context for the operation * @mbox_cmd: initialized command to execute * * Context: Any context. @@ -241,10 +241,9 @@ static const char *cxl_mem_opcode_to_name(u16 opcode) * error. While this distinction can be useful for commands from userspace, the * kernel will only be able to use results when both are successful. */ -int cxl_internal_send_cmd(struct cxl_memdev_state *mds, +int cxl_internal_send_cmd(struct cxl_mailbox *cxl_mbox, struct cxl_mbox_cmd *mbox_cmd) { - struct cxl_mailbox *cxl_mbox = &mds->cxlds.cxl_mbox; size_t out_size, min_out; int rc; @@ -350,40 +349,40 @@ static bool cxl_payload_from_user_allowed(u16 opcode, void *payload_in) return true; } -static int cxl_mbox_cmd_ctor(struct cxl_mbox_cmd *mbox, - struct cxl_memdev_state *mds, u16 opcode, +static int cxl_mbox_cmd_ctor(struct cxl_mbox_cmd *mbox_cmd, + struct cxl_mailbox *cxl_mbox, u16 opcode, size_t in_size, size_t out_size, u64 in_payload) { - struct cxl_mailbox *cxl_mbox = &mds->cxlds.cxl_mbox; - *mbox = (struct cxl_mbox_cmd) { + *mbox_cmd = (struct cxl_mbox_cmd) { .opcode = opcode, .size_in = in_size, }; if (in_size) { - mbox->payload_in = vmemdup_user(u64_to_user_ptr(in_payload), - in_size); - if (IS_ERR(mbox->payload_in)) - return PTR_ERR(mbox->payload_in); + mbox_cmd->payload_in = vmemdup_user(u64_to_user_ptr(in_payload), + in_size); + if (IS_ERR(mbox_cmd->payload_in)) + return PTR_ERR(mbox_cmd->payload_in); - if (!cxl_payload_from_user_allowed(opcode, mbox->payload_in)) { - dev_dbg(mds->cxlds.dev, "%s: input payload not allowed\n", + if (!cxl_payload_from_user_allowed(opcode, + mbox_cmd->payload_in)) { + dev_dbg(cxl_mbox->host, "%s: input payload not allowed\n", cxl_mem_opcode_to_name(opcode)); - kvfree(mbox->payload_in); + kvfree(mbox_cmd->payload_in); return -EBUSY; } } /* Prepare to handle a full payload for variable sized output */ if (out_size == CXL_VARIABLE_PAYLOAD) - mbox->size_out = cxl_mbox->payload_size; + mbox_cmd->size_out = cxl_mbox->payload_size; else - mbox->size_out = out_size; + mbox_cmd->size_out = out_size; - if (mbox->size_out) { - mbox->payload_out = kvzalloc(mbox->size_out, GFP_KERNEL); - if (!mbox->payload_out) { - kvfree(mbox->payload_in); + if (mbox_cmd->size_out) { + mbox_cmd->payload_out = kvzalloc(mbox_cmd->size_out, GFP_KERNEL); + if (!mbox_cmd->payload_out) { + kvfree(mbox_cmd->payload_in); return -ENOMEM; } } @@ -398,10 +397,8 @@ static void cxl_mbox_cmd_dtor(struct cxl_mbox_cmd *mbox) static int cxl_to_mem_cmd_raw(struct cxl_mem_command *mem_cmd, const struct cxl_send_command *send_cmd, - struct cxl_memdev_state *mds) + struct cxl_mailbox *cxl_mbox) { - struct cxl_mailbox *cxl_mbox = &mds->cxlds.cxl_mbox; - if (send_cmd->raw.rsvd) return -EINVAL; @@ -416,7 +413,7 @@ static int cxl_to_mem_cmd_raw(struct cxl_mem_command *mem_cmd, if (!cxl_mem_raw_command_allowed(send_cmd->raw.opcode)) return -EPERM; - dev_WARN_ONCE(mds->cxlds.dev, true, "raw command path used\n"); + dev_WARN_ONCE(cxl_mbox->host, true, "raw command path used\n"); *mem_cmd = (struct cxl_mem_command) { .info = { @@ -432,7 +429,7 @@ static int cxl_to_mem_cmd_raw(struct cxl_mem_command *mem_cmd, static int cxl_to_mem_cmd(struct cxl_mem_command *mem_cmd, const struct cxl_send_command *send_cmd, - struct cxl_memdev_state *mds) + struct cxl_mailbox *cxl_mbox) { struct cxl_mem_command *c = &cxl_mem_commands[send_cmd->id]; const struct cxl_command_info *info = &c->info; @@ -447,11 +444,11 @@ static int cxl_to_mem_cmd(struct cxl_mem_command *mem_cmd, return -EINVAL; /* Check that the command is enabled for hardware */ - if (!test_bit(info->id, mds->enabled_cmds)) + if (!test_bit(info->id, cxl_mbox->enabled_cmds)) return -ENOTTY; /* Check that the command is not claimed for exclusive kernel use */ - if (test_bit(info->id, mds->exclusive_cmds)) + if (test_bit(info->id, cxl_mbox->exclusive_cmds)) return -EBUSY; /* Check the input buffer is the expected size */ @@ -495,10 +492,9 @@ static int cxl_to_mem_cmd(struct cxl_mem_command *mem_cmd, * safe to send to the hardware. */ static int cxl_validate_cmd_from_user(struct cxl_mbox_cmd *mbox_cmd, - struct cxl_memdev_state *mds, + struct cxl_mailbox *cxl_mbox, const struct cxl_send_command *send_cmd) { - struct cxl_mailbox *cxl_mbox = &mds->cxlds.cxl_mbox; struct cxl_mem_command mem_cmd; int rc; @@ -515,24 +511,23 @@ static int cxl_validate_cmd_from_user(struct cxl_mbox_cmd *mbox_cmd, /* Sanitize and construct a cxl_mem_command */ if (send_cmd->id == CXL_MEM_COMMAND_ID_RAW) - rc = cxl_to_mem_cmd_raw(&mem_cmd, send_cmd, mds); + rc = cxl_to_mem_cmd_raw(&mem_cmd, send_cmd, cxl_mbox); else - rc = cxl_to_mem_cmd(&mem_cmd, send_cmd, mds); + rc = cxl_to_mem_cmd(&mem_cmd, send_cmd, cxl_mbox); if (rc) return rc; /* Sanitize and construct a cxl_mbox_cmd */ - return cxl_mbox_cmd_ctor(mbox_cmd, mds, mem_cmd.opcode, + return cxl_mbox_cmd_ctor(mbox_cmd, cxl_mbox, mem_cmd.opcode, mem_cmd.info.size_in, mem_cmd.info.size_out, send_cmd->in.payload); } -int cxl_query_cmd(struct cxl_memdev *cxlmd, +int cxl_query_cmd(struct cxl_mailbox *cxl_mbox, struct cxl_mem_query_commands __user *q) { - struct cxl_memdev_state *mds = to_cxl_memdev_state(cxlmd->cxlds); - struct device *dev = &cxlmd->dev; + struct device *dev = cxl_mbox->host; struct cxl_mem_command *cmd; u32 n_commands; int j = 0; @@ -553,9 +548,9 @@ int cxl_query_cmd(struct cxl_memdev *cxlmd, cxl_for_each_cmd(cmd) { struct cxl_command_info info = cmd->info; - if (test_bit(info.id, mds->enabled_cmds)) + if (test_bit(info.id, cxl_mbox->enabled_cmds)) info.flags |= CXL_MEM_COMMAND_FLAG_ENABLED; - if (test_bit(info.id, mds->exclusive_cmds)) + if (test_bit(info.id, cxl_mbox->exclusive_cmds)) info.flags |= CXL_MEM_COMMAND_FLAG_EXCLUSIVE; if (copy_to_user(&q->commands[j++], &info, sizeof(info))) @@ -570,7 +565,7 @@ int cxl_query_cmd(struct cxl_memdev *cxlmd, /** * handle_mailbox_cmd_from_user() - Dispatch a mailbox command for userspace. - * @mds: The driver data for the operation + * @mailbox: The mailbox context for the operation. * @mbox_cmd: The validated mailbox command. * @out_payload: Pointer to userspace's output payload. * @size_out: (Input) Max payload size to copy out. @@ -591,13 +586,12 @@ int cxl_query_cmd(struct cxl_memdev *cxlmd, * * See cxl_send_cmd(). */ -static int handle_mailbox_cmd_from_user(struct cxl_memdev_state *mds, +static int handle_mailbox_cmd_from_user(struct cxl_mailbox *cxl_mbox, struct cxl_mbox_cmd *mbox_cmd, u64 out_payload, s32 *size_out, u32 *retval) { - struct cxl_mailbox *cxl_mbox = &mds->cxlds.cxl_mbox; - struct device *dev = mds->cxlds.dev; + struct device *dev = cxl_mbox->host; int rc; dev_dbg(dev, @@ -634,10 +628,9 @@ static int handle_mailbox_cmd_from_user(struct cxl_memdev_state *mds, return rc; } -int cxl_send_cmd(struct cxl_memdev *cxlmd, struct cxl_send_command __user *s) +int cxl_send_cmd(struct cxl_mailbox *cxl_mbox, struct cxl_send_command __user *s) { - struct cxl_memdev_state *mds = to_cxl_memdev_state(cxlmd->cxlds); - struct device *dev = &cxlmd->dev; + struct device *dev = cxl_mbox->host; struct cxl_send_command send; struct cxl_mbox_cmd mbox_cmd; int rc; @@ -647,11 +640,11 @@ int cxl_send_cmd(struct cxl_memdev *cxlmd, struct cxl_send_command __user *s) if (copy_from_user(&send, s, sizeof(send))) return -EFAULT; - rc = cxl_validate_cmd_from_user(&mbox_cmd, mds, &send); + rc = cxl_validate_cmd_from_user(&mbox_cmd, cxl_mbox, &send); if (rc) return rc; - rc = handle_mailbox_cmd_from_user(mds, &mbox_cmd, send.out.payload, + rc = handle_mailbox_cmd_from_user(cxl_mbox, &mbox_cmd, send.out.payload, &send.out.size, &send.retval); if (rc) return rc; @@ -689,7 +682,7 @@ static int cxl_xfer_log(struct cxl_memdev_state *mds, uuid_t *uuid, .payload_out = out, }; - rc = cxl_internal_send_cmd(mds, &mbox_cmd); + rc = cxl_internal_send_cmd(cxl_mbox, &mbox_cmd); /* * The output payload length that indicates the number @@ -725,6 +718,7 @@ static int cxl_xfer_log(struct cxl_memdev_state *mds, uuid_t *uuid, */ static void cxl_walk_cel(struct cxl_memdev_state *mds, size_t size, u8 *cel) { + struct cxl_mailbox *cxl_mbox = &mds->cxlds.cxl_mbox; struct cxl_cel_entry *cel_entry; const int cel_entries = size / sizeof(*cel_entry); struct device *dev = mds->cxlds.dev; @@ -738,7 +732,7 @@ static void cxl_walk_cel(struct cxl_memdev_state *mds, size_t size, u8 *cel) int enabled = 0; if (cmd) { - set_bit(cmd->info.id, mds->enabled_cmds); + set_bit(cmd->info.id, cxl_mbox->enabled_cmds); enabled++; } @@ -775,7 +769,7 @@ static struct cxl_mbox_get_supported_logs *cxl_get_gsl(struct cxl_memdev_state * /* At least the record number field must be valid */ .min_out = 2, }; - rc = cxl_internal_send_cmd(mds, &mbox_cmd); + rc = cxl_internal_send_cmd(cxl_mbox, &mbox_cmd); if (rc < 0) { kvfree(ret); return ERR_PTR(rc); @@ -808,6 +802,7 @@ static const uuid_t log_uuid[] = { */ int cxl_enumerate_cmds(struct cxl_memdev_state *mds) { + struct cxl_mailbox *cxl_mbox = &mds->cxlds.cxl_mbox; struct cxl_mbox_get_supported_logs *gsl; struct device *dev = mds->cxlds.dev; struct cxl_mem_command *cmd; @@ -846,7 +841,7 @@ int cxl_enumerate_cmds(struct cxl_memdev_state *mds) /* In case CEL was bogus, enable some default commands. */ cxl_for_each_cmd(cmd) if (cmd->flags & CXL_CMD_FLAG_FORCE_ENABLE) - set_bit(cmd->info.id, mds->enabled_cmds); + set_bit(cmd->info.id, cxl_mbox->enabled_cmds); /* Found the required CEL */ rc = 0; @@ -964,7 +959,7 @@ static int cxl_clear_event_record(struct cxl_memdev_state *mds, if (i == max_handles) { payload->nr_recs = i; - rc = cxl_internal_send_cmd(mds, &mbox_cmd); + rc = cxl_internal_send_cmd(cxl_mbox, &mbox_cmd); if (rc) goto free_pl; i = 0; @@ -975,7 +970,7 @@ static int cxl_clear_event_record(struct cxl_memdev_state *mds, if (i) { payload->nr_recs = i; mbox_cmd.size_in = struct_size(payload, handles, i); - rc = cxl_internal_send_cmd(mds, &mbox_cmd); + rc = cxl_internal_send_cmd(cxl_mbox, &mbox_cmd); if (rc) goto free_pl; } @@ -1009,7 +1004,7 @@ static void cxl_mem_get_records_log(struct cxl_memdev_state *mds, .min_out = struct_size(payload, records, 0), }; - rc = cxl_internal_send_cmd(mds, &mbox_cmd); + rc = cxl_internal_send_cmd(cxl_mbox, &mbox_cmd); if (rc) { dev_err_ratelimited(dev, "Event log '%d': Failed to query event records : %d", @@ -1080,6 +1075,7 @@ EXPORT_SYMBOL_NS_GPL(cxl_mem_get_event_records, CXL); */ static int cxl_mem_get_partition_info(struct cxl_memdev_state *mds) { + struct cxl_mailbox *cxl_mbox = &mds->cxlds.cxl_mbox; struct cxl_mbox_get_partition_info pi; struct cxl_mbox_cmd mbox_cmd; int rc; @@ -1089,7 +1085,7 @@ static int cxl_mem_get_partition_info(struct cxl_memdev_state *mds) .size_out = sizeof(pi), .payload_out = &pi, }; - rc = cxl_internal_send_cmd(mds, &mbox_cmd); + rc = cxl_internal_send_cmd(cxl_mbox, &mbox_cmd); if (rc) return rc; @@ -1116,6 +1112,7 @@ static int cxl_mem_get_partition_info(struct cxl_memdev_state *mds) */ int cxl_dev_state_identify(struct cxl_memdev_state *mds) { + struct cxl_mailbox *cxl_mbox = &mds->cxlds.cxl_mbox; /* See CXL 2.0 Table 175 Identify Memory Device Output Payload */ struct cxl_mbox_identify id; struct cxl_mbox_cmd mbox_cmd; @@ -1130,7 +1127,7 @@ int cxl_dev_state_identify(struct cxl_memdev_state *mds) .size_out = sizeof(id), .payload_out = &id, }; - rc = cxl_internal_send_cmd(mds, &mbox_cmd); + rc = cxl_internal_send_cmd(cxl_mbox, &mbox_cmd); if (rc < 0) return rc; @@ -1170,11 +1167,12 @@ static int __cxl_mem_sanitize(struct cxl_memdev_state *mds, u16 cmd) }; struct cxl_mbox_cmd mbox_cmd = { .opcode = cmd }; struct cxl_dev_state *cxlds = &mds->cxlds; + struct cxl_mailbox *cxl_mbox = &cxlds->cxl_mbox; if (cmd != CXL_MBOX_OP_SANITIZE && cmd != CXL_MBOX_OP_SECURE_ERASE) return -EINVAL; - rc = cxl_internal_send_cmd(mds, &sec_cmd); + rc = cxl_internal_send_cmd(cxl_mbox, &sec_cmd); if (rc < 0) { dev_err(cxlds->dev, "Failed to get security state : %d", rc); return rc; @@ -1193,7 +1191,7 @@ static int __cxl_mem_sanitize(struct cxl_memdev_state *mds, u16 cmd) sec_out & CXL_PMEM_SEC_STATE_LOCKED) return -EINVAL; - rc = cxl_internal_send_cmd(mds, &mbox_cmd); + rc = cxl_internal_send_cmd(cxl_mbox, &mbox_cmd); if (rc < 0) { dev_err(cxlds->dev, "Failed to sanitize device : %d", rc); return rc; @@ -1310,6 +1308,7 @@ EXPORT_SYMBOL_NS_GPL(cxl_mem_create_range_info, CXL); int cxl_set_timestamp(struct cxl_memdev_state *mds) { + struct cxl_mailbox *cxl_mbox = &mds->cxlds.cxl_mbox; struct cxl_mbox_cmd mbox_cmd; struct cxl_mbox_set_timestamp_in pi; int rc; @@ -1321,7 +1320,7 @@ int cxl_set_timestamp(struct cxl_memdev_state *mds) .payload_in = &pi, }; - rc = cxl_internal_send_cmd(mds, &mbox_cmd); + rc = cxl_internal_send_cmd(cxl_mbox, &mbox_cmd); /* * Command is optional. Devices may have another way of providing * a timestamp, or may return all 0s in timestamp fields. @@ -1362,7 +1361,7 @@ int cxl_mem_get_poison(struct cxl_memdev *cxlmd, u64 offset, u64 len, .min_out = struct_size(po, record, 0), }; - rc = cxl_internal_send_cmd(mds, &mbox_cmd); + rc = cxl_internal_send_cmd(cxl_mbox, &mbox_cmd); if (rc) break; @@ -1438,6 +1437,7 @@ struct cxl_memdev_state *cxl_memdev_state_create(struct device *dev) mutex_init(&mds->event.log_lock); mds->cxlds.dev = dev; mds->cxlds.reg_map.host = dev; + mds->cxlds.cxl_mbox.host = dev; mds->cxlds.reg_map.resource = CXL_RESOURCE_NONE; mds->cxlds.type = CXL_DEVTYPE_CLASSMEM; mds->ram_perf.qos_class = CXL_QOS_CLASS_INVALID; diff --git a/drivers/cxl/core/memdev.c b/drivers/cxl/core/memdev.c index 05bb84cb1274..9f0fe698414d 100644 --- a/drivers/cxl/core/memdev.c +++ b/drivers/cxl/core/memdev.c @@ -279,6 +279,7 @@ static int cxl_validate_poison_dpa(struct cxl_memdev *cxlmd, u64 dpa) int cxl_inject_poison(struct cxl_memdev *cxlmd, u64 dpa) { struct cxl_memdev_state *mds = to_cxl_memdev_state(cxlmd->cxlds); + struct cxl_mailbox *cxl_mbox = &mds->cxlds.cxl_mbox; struct cxl_mbox_inject_poison inject; struct cxl_poison_record record; struct cxl_mbox_cmd mbox_cmd; @@ -308,7 +309,7 @@ int cxl_inject_poison(struct cxl_memdev *cxlmd, u64 dpa) .size_in = sizeof(inject), .payload_in = &inject, }; - rc = cxl_internal_send_cmd(mds, &mbox_cmd); + rc = cxl_internal_send_cmd(cxl_mbox, &mbox_cmd); if (rc) goto out; @@ -334,6 +335,7 @@ EXPORT_SYMBOL_NS_GPL(cxl_inject_poison, CXL); int cxl_clear_poison(struct cxl_memdev *cxlmd, u64 dpa) { struct cxl_memdev_state *mds = to_cxl_memdev_state(cxlmd->cxlds); + struct cxl_mailbox *cxl_mbox = &mds->cxlds.cxl_mbox; struct cxl_mbox_clear_poison clear; struct cxl_poison_record record; struct cxl_mbox_cmd mbox_cmd; @@ -372,7 +374,7 @@ int cxl_clear_poison(struct cxl_memdev *cxlmd, u64 dpa) .payload_in = &clear, }; - rc = cxl_internal_send_cmd(mds, &mbox_cmd); + rc = cxl_internal_send_cmd(cxl_mbox, &mbox_cmd); if (rc) goto out; @@ -564,9 +566,11 @@ EXPORT_SYMBOL_NS_GPL(is_cxl_memdev, CXL); void set_exclusive_cxl_commands(struct cxl_memdev_state *mds, unsigned long *cmds) { + struct cxl_mailbox *cxl_mbox = &mds->cxlds.cxl_mbox; + down_write(&cxl_memdev_rwsem); - bitmap_or(mds->exclusive_cmds, mds->exclusive_cmds, cmds, - CXL_MEM_COMMAND_ID_MAX); + bitmap_or(cxl_mbox->exclusive_cmds, cxl_mbox->exclusive_cmds, + cmds, CXL_MEM_COMMAND_ID_MAX); up_write(&cxl_memdev_rwsem); } EXPORT_SYMBOL_NS_GPL(set_exclusive_cxl_commands, CXL); @@ -579,9 +583,11 @@ EXPORT_SYMBOL_NS_GPL(set_exclusive_cxl_commands, CXL); void clear_exclusive_cxl_commands(struct cxl_memdev_state *mds, unsigned long *cmds) { + struct cxl_mailbox *cxl_mbox = &mds->cxlds.cxl_mbox; + down_write(&cxl_memdev_rwsem); - bitmap_andnot(mds->exclusive_cmds, mds->exclusive_cmds, cmds, - CXL_MEM_COMMAND_ID_MAX); + bitmap_andnot(cxl_mbox->exclusive_cmds, cxl_mbox->exclusive_cmds, + cmds, CXL_MEM_COMMAND_ID_MAX); up_write(&cxl_memdev_rwsem); } EXPORT_SYMBOL_NS_GPL(clear_exclusive_cxl_commands, CXL); @@ -656,11 +662,14 @@ static struct cxl_memdev *cxl_memdev_alloc(struct cxl_dev_state *cxlds, static long __cxl_memdev_ioctl(struct cxl_memdev *cxlmd, unsigned int cmd, unsigned long arg) { + struct cxl_memdev_state *mds = to_cxl_memdev_state(cxlmd->cxlds); + struct cxl_mailbox *cxl_mbox = &mds->cxlds.cxl_mbox; + switch (cmd) { case CXL_MEM_QUERY_COMMANDS: - return cxl_query_cmd(cxlmd, (void __user *)arg); + return cxl_query_cmd(cxl_mbox, (void __user *)arg); case CXL_MEM_SEND_COMMAND: - return cxl_send_cmd(cxlmd, (void __user *)arg); + return cxl_send_cmd(cxl_mbox, (void __user *)arg); default: return -ENOTTY; } @@ -715,6 +724,7 @@ static int cxl_memdev_release_file(struct inode *inode, struct file *file) */ static int cxl_mem_get_fw_info(struct cxl_memdev_state *mds) { + struct cxl_mailbox *cxl_mbox = &mds->cxlds.cxl_mbox; struct cxl_mbox_get_fw_info info; struct cxl_mbox_cmd mbox_cmd; int rc; @@ -725,7 +735,7 @@ static int cxl_mem_get_fw_info(struct cxl_memdev_state *mds) .payload_out = &info, }; - rc = cxl_internal_send_cmd(mds, &mbox_cmd); + rc = cxl_internal_send_cmd(cxl_mbox, &mbox_cmd); if (rc < 0) return rc; @@ -749,6 +759,7 @@ static int cxl_mem_get_fw_info(struct cxl_memdev_state *mds) */ static int cxl_mem_activate_fw(struct cxl_memdev_state *mds, int slot) { + struct cxl_mailbox *cxl_mbox = &mds->cxlds.cxl_mbox; struct cxl_mbox_activate_fw activate; struct cxl_mbox_cmd mbox_cmd; @@ -765,7 +776,7 @@ static int cxl_mem_activate_fw(struct cxl_memdev_state *mds, int slot) activate.action = CXL_FW_ACTIVATE_OFFLINE; activate.slot = slot; - return cxl_internal_send_cmd(mds, &mbox_cmd); + return cxl_internal_send_cmd(cxl_mbox, &mbox_cmd); } /** @@ -780,6 +791,7 @@ static int cxl_mem_activate_fw(struct cxl_memdev_state *mds, int slot) */ static int cxl_mem_abort_fw_xfer(struct cxl_memdev_state *mds) { + struct cxl_mailbox *cxl_mbox = &mds->cxlds.cxl_mbox; struct cxl_mbox_transfer_fw *transfer; struct cxl_mbox_cmd mbox_cmd; int rc; @@ -799,7 +811,7 @@ static int cxl_mem_abort_fw_xfer(struct cxl_memdev_state *mds) transfer->action = CXL_FW_TRANSFER_ACTION_ABORT; - rc = cxl_internal_send_cmd(mds, &mbox_cmd); + rc = cxl_internal_send_cmd(cxl_mbox, &mbox_cmd); kfree(transfer); return rc; } @@ -924,7 +936,7 @@ static enum fw_upload_err cxl_fw_write(struct fw_upload *fwl, const u8 *data, .poll_count = 30, }; - rc = cxl_internal_send_cmd(mds, &mbox_cmd); + rc = cxl_internal_send_cmd(cxl_mbox, &mbox_cmd); if (rc < 0) { rc = FW_UPLOAD_ERR_RW_ERROR; goto out_free; @@ -991,10 +1003,11 @@ static void cxl_remove_fw_upload(void *fwl) int devm_cxl_setup_fw_upload(struct device *host, struct cxl_memdev_state *mds) { struct cxl_dev_state *cxlds = &mds->cxlds; + struct cxl_mailbox *cxl_mbox = &cxlds->cxl_mbox; struct device *dev = &cxlds->cxlmd->dev; struct fw_upload *fwl; - if (!test_bit(CXL_MEM_COMMAND_ID_GET_FW_INFO, mds->enabled_cmds)) + if (!test_bit(CXL_MEM_COMMAND_ID_GET_FW_INFO, cxl_mbox->enabled_cmds)) return 0; fwl = firmware_upload_register(THIS_MODULE, dev, dev_name(dev), diff --git a/drivers/cxl/cxlmem.h b/drivers/cxl/cxlmem.h index 8f683fe08410..efdf833f2c51 100644 --- a/drivers/cxl/cxlmem.h +++ b/drivers/cxl/cxlmem.h @@ -417,8 +417,6 @@ struct cxl_dev_state { * @lsa_size: Size of Label Storage Area * (CXL 2.0 8.2.9.5.1.1 Identify Memory Device) * @firmware_version: Firmware version for the memory device. - * @enabled_cmds: Hardware commands found enabled in CEL. - * @exclusive_cmds: Commands that are kernel-internal only * @total_bytes: sum of all possible capacities * @volatile_only_bytes: hard volatile capacity * @persistent_only_bytes: hard persistent capacity @@ -441,8 +439,6 @@ struct cxl_memdev_state { struct cxl_dev_state cxlds; size_t lsa_size; char firmware_version[0x10]; - DECLARE_BITMAP(enabled_cmds, CXL_MEM_COMMAND_ID_MAX); - DECLARE_BITMAP(exclusive_cmds, CXL_MEM_COMMAND_ID_MAX); u64 total_bytes; u64 volatile_only_bytes; u64 persistent_only_bytes; @@ -769,7 +765,7 @@ enum { CXL_PMEM_SEC_PASS_USER, }; -int cxl_internal_send_cmd(struct cxl_memdev_state *mds, +int cxl_internal_send_cmd(struct cxl_mailbox *cxl_mbox, struct cxl_mbox_cmd *cmd); int cxl_dev_state_identify(struct cxl_memdev_state *mds); int cxl_await_media_ready(struct cxl_dev_state *cxlds); diff --git a/drivers/cxl/pci.c b/drivers/cxl/pci.c index 45b184b6ef97..7e26da706921 100644 --- a/drivers/cxl/pci.c +++ b/drivers/cxl/pci.c @@ -661,6 +661,7 @@ static int cxl_event_req_irq(struct cxl_dev_state *cxlds, u8 setting) static int cxl_event_get_int_policy(struct cxl_memdev_state *mds, struct cxl_event_interrupt_policy *policy) { + struct cxl_mailbox *cxl_mbox = &mds->cxlds.cxl_mbox; struct cxl_mbox_cmd mbox_cmd = { .opcode = CXL_MBOX_OP_GET_EVT_INT_POLICY, .payload_out = policy, @@ -668,7 +669,7 @@ static int cxl_event_get_int_policy(struct cxl_memdev_state *mds, }; int rc; - rc = cxl_internal_send_cmd(mds, &mbox_cmd); + rc = cxl_internal_send_cmd(cxl_mbox, &mbox_cmd); if (rc < 0) dev_err(mds->cxlds.dev, "Failed to get event interrupt policy : %d", rc); @@ -679,6 +680,7 @@ static int cxl_event_get_int_policy(struct cxl_memdev_state *mds, static int cxl_event_config_msgnums(struct cxl_memdev_state *mds, struct cxl_event_interrupt_policy *policy) { + struct cxl_mailbox *cxl_mbox = &mds->cxlds.cxl_mbox; struct cxl_mbox_cmd mbox_cmd; int rc; @@ -695,7 +697,7 @@ static int cxl_event_config_msgnums(struct cxl_memdev_state *mds, .size_in = sizeof(*policy), }; - rc = cxl_internal_send_cmd(mds, &mbox_cmd); + rc = cxl_internal_send_cmd(cxl_mbox, &mbox_cmd); if (rc < 0) { dev_err(mds->cxlds.dev, "Failed to set event interrupt policy : %d", rc); diff --git a/drivers/cxl/pmem.c b/drivers/cxl/pmem.c index 9f62dc03c883..6a83f33dde5b 100644 --- a/drivers/cxl/pmem.c +++ b/drivers/cxl/pmem.c @@ -120,6 +120,7 @@ static int cxl_pmem_get_config_data(struct cxl_memdev_state *mds, struct nd_cmd_get_config_data_hdr *cmd, unsigned int buf_len) { + struct cxl_mailbox *cxl_mbox = &mds->cxlds.cxl_mbox; struct cxl_mbox_get_lsa get_lsa; struct cxl_mbox_cmd mbox_cmd; int rc; @@ -141,7 +142,7 @@ static int cxl_pmem_get_config_data(struct cxl_memdev_state *mds, .payload_out = cmd->out_buf, }; - rc = cxl_internal_send_cmd(mds, &mbox_cmd); + rc = cxl_internal_send_cmd(cxl_mbox, &mbox_cmd); cmd->status = 0; return rc; @@ -151,6 +152,7 @@ static int cxl_pmem_set_config_data(struct cxl_memdev_state *mds, struct nd_cmd_set_config_hdr *cmd, unsigned int buf_len) { + struct cxl_mailbox *cxl_mbox = &mds->cxlds.cxl_mbox; struct cxl_mbox_set_lsa *set_lsa; struct cxl_mbox_cmd mbox_cmd; int rc; @@ -177,7 +179,7 @@ static int cxl_pmem_set_config_data(struct cxl_memdev_state *mds, .size_in = struct_size(set_lsa, data, cmd->in_length), }; - rc = cxl_internal_send_cmd(mds, &mbox_cmd); + rc = cxl_internal_send_cmd(cxl_mbox, &mbox_cmd); /* * Set "firmware" status (4-packed bytes at the end of the input diff --git a/drivers/cxl/security.c b/drivers/cxl/security.c index 21856a3f408e..95a92b87c99a 100644 --- a/drivers/cxl/security.c +++ b/drivers/cxl/security.c @@ -15,6 +15,7 @@ static unsigned long cxl_pmem_get_security_flags(struct nvdimm *nvdimm, struct cxl_nvdimm *cxl_nvd = nvdimm_provider_data(nvdimm); struct cxl_memdev *cxlmd = cxl_nvd->cxlmd; struct cxl_memdev_state *mds = to_cxl_memdev_state(cxlmd->cxlds); + struct cxl_mailbox *cxl_mbox = &mds->cxlds.cxl_mbox; unsigned long security_flags = 0; struct cxl_get_security_output { __le32 flags; @@ -29,7 +30,7 @@ static unsigned long cxl_pmem_get_security_flags(struct nvdimm *nvdimm, .payload_out = &out, }; - rc = cxl_internal_send_cmd(mds, &mbox_cmd); + rc = cxl_internal_send_cmd(cxl_mbox, &mbox_cmd); if (rc < 0) return 0; @@ -71,6 +72,7 @@ static int cxl_pmem_security_change_key(struct nvdimm *nvdimm, struct cxl_nvdimm *cxl_nvd = nvdimm_provider_data(nvdimm); struct cxl_memdev *cxlmd = cxl_nvd->cxlmd; struct cxl_memdev_state *mds = to_cxl_memdev_state(cxlmd->cxlds); + struct cxl_mailbox *cxl_mbox = &mds->cxlds.cxl_mbox; struct cxl_mbox_cmd mbox_cmd; struct cxl_set_pass set_pass; @@ -87,7 +89,7 @@ static int cxl_pmem_security_change_key(struct nvdimm *nvdimm, .payload_in = &set_pass, }; - return cxl_internal_send_cmd(mds, &mbox_cmd); + return cxl_internal_send_cmd(cxl_mbox, &mbox_cmd); } static int __cxl_pmem_security_disable(struct nvdimm *nvdimm, @@ -97,6 +99,7 @@ static int __cxl_pmem_security_disable(struct nvdimm *nvdimm, struct cxl_nvdimm *cxl_nvd = nvdimm_provider_data(nvdimm); struct cxl_memdev *cxlmd = cxl_nvd->cxlmd; struct cxl_memdev_state *mds = to_cxl_memdev_state(cxlmd->cxlds); + struct cxl_mailbox *cxl_mbox = &mds->cxlds.cxl_mbox; struct cxl_disable_pass dis_pass; struct cxl_mbox_cmd mbox_cmd; @@ -112,7 +115,7 @@ static int __cxl_pmem_security_disable(struct nvdimm *nvdimm, .payload_in = &dis_pass, }; - return cxl_internal_send_cmd(mds, &mbox_cmd); + return cxl_internal_send_cmd(cxl_mbox, &mbox_cmd); } static int cxl_pmem_security_disable(struct nvdimm *nvdimm, @@ -132,11 +135,12 @@ static int cxl_pmem_security_freeze(struct nvdimm *nvdimm) struct cxl_nvdimm *cxl_nvd = nvdimm_provider_data(nvdimm); struct cxl_memdev *cxlmd = cxl_nvd->cxlmd; struct cxl_memdev_state *mds = to_cxl_memdev_state(cxlmd->cxlds); + struct cxl_mailbox *cxl_mbox = &mds->cxlds.cxl_mbox; struct cxl_mbox_cmd mbox_cmd = { .opcode = CXL_MBOX_OP_FREEZE_SECURITY, }; - return cxl_internal_send_cmd(mds, &mbox_cmd); + return cxl_internal_send_cmd(cxl_mbox, &mbox_cmd); } static int cxl_pmem_security_unlock(struct nvdimm *nvdimm, @@ -145,6 +149,7 @@ static int cxl_pmem_security_unlock(struct nvdimm *nvdimm, struct cxl_nvdimm *cxl_nvd = nvdimm_provider_data(nvdimm); struct cxl_memdev *cxlmd = cxl_nvd->cxlmd; struct cxl_memdev_state *mds = to_cxl_memdev_state(cxlmd->cxlds); + struct cxl_mailbox *cxl_mbox = &mds->cxlds.cxl_mbox; u8 pass[NVDIMM_PASSPHRASE_LEN]; struct cxl_mbox_cmd mbox_cmd; int rc; @@ -156,7 +161,7 @@ static int cxl_pmem_security_unlock(struct nvdimm *nvdimm, .payload_in = pass, }; - rc = cxl_internal_send_cmd(mds, &mbox_cmd); + rc = cxl_internal_send_cmd(cxl_mbox, &mbox_cmd); if (rc < 0) return rc; @@ -170,6 +175,7 @@ static int cxl_pmem_security_passphrase_erase(struct nvdimm *nvdimm, struct cxl_nvdimm *cxl_nvd = nvdimm_provider_data(nvdimm); struct cxl_memdev *cxlmd = cxl_nvd->cxlmd; struct cxl_memdev_state *mds = to_cxl_memdev_state(cxlmd->cxlds); + struct cxl_mailbox *cxl_mbox = &mds->cxlds.cxl_mbox; struct cxl_mbox_cmd mbox_cmd; struct cxl_pass_erase erase; int rc; @@ -185,7 +191,7 @@ static int cxl_pmem_security_passphrase_erase(struct nvdimm *nvdimm, .payload_in = &erase, }; - rc = cxl_internal_send_cmd(mds, &mbox_cmd); + rc = cxl_internal_send_cmd(cxl_mbox, &mbox_cmd); if (rc < 0) return rc; diff --git a/include/linux/cxl/mailbox.h b/include/linux/cxl/mailbox.h index 654df6175828..2380b22d7a12 100644 --- a/include/linux/cxl/mailbox.h +++ b/include/linux/cxl/mailbox.h @@ -3,6 +3,7 @@ #ifndef __CXL_MBOX_H__ #define __CXL_MBOX_H__ +#include #include /** @@ -45,6 +46,8 @@ struct cxl_mbox_cmd { * struct cxl_mailbox - context for CXL mailbox operations * @host: device that hosts the mailbox * @adev: auxiliary device for fw-ctl + * @enabled_cmds: Hardware commands found enabled in CEL. + * @exclusive_cmds: Commands that are kernel-internal only * @payload_size: Size of space for payload * (CXL 3.1 8.2.8.4.3 Mailbox Capabilities Register) * @mbox_mutex: mutex protects device mailbox and firmware @@ -54,6 +57,8 @@ struct cxl_mbox_cmd { struct cxl_mailbox { struct device *host; struct auxiliary_device adev; /* For fw-ctl */ + DECLARE_BITMAP(enabled_cmds, CXL_MEM_COMMAND_ID_MAX); + DECLARE_BITMAP(exclusive_cmds, CXL_MEM_COMMAND_ID_MAX); size_t payload_size; struct mutex mbox_mutex; /* lock to protect mailbox context */ struct rcuwait mbox_wait; From patchwork Thu Jul 18 21:32:22 2024 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Dave Jiang X-Patchwork-Id: 13736741 Received: from smtp.kernel.org (aws-us-west-2-korg-mail-1.web.codeaurora.org [10.30.226.201]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by smtp.subspace.kernel.org (Postfix) with ESMTPS id 4F3BE81751 for ; Thu, 18 Jul 2024 21:34:56 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=10.30.226.201 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1721338496; cv=none; b=X0wfhwB+EpaiSAomDRzYdKegCP2aaMmWGcyyAxEB0PHVaO8Tv0CTLp/XsOohgEcnoTxoF5LkYQh3nuwl58KPl6knxTaqvPaNIpMXVET3Bit/6xoe15JH6aeIy2sgLM2RamafLwbP6dIGtzGxD8c+d2a4jQ/FvC73k+2fhDSrvM0= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1721338496; c=relaxed/simple; bh=Rc0f2EcRGHfaowzw443MmtjctNjslYOuxao5kJ/ColQ=; h=From:To:Cc:Subject:Date:Message-ID:In-Reply-To:References: MIME-Version; b=U7kiDkeefnTAappbTbKoyUdHAtCn7hL7PJdhzXdwNWEf0Y5OYAItqJs62XbyAKfcJ6dGHvf5lRb9Inp1vEVxkHUQ2R6l6QcXuRUTf6L0V7rq6zL2BXnMqBsHM31GSYJ40chE0ADRj/aIZnuhUogQXAOW5kdp2cqf0xvc0Wu2fi8= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; arc=none smtp.client-ip=10.30.226.201 Received: by smtp.kernel.org (Postfix) with ESMTPSA id 184CFC116B1; Thu, 18 Jul 2024 21:34:56 +0000 (UTC) From: Dave Jiang To: linux-cxl@vger.kernel.org Cc: dan.j.williams@intel.com, ira.weiny@intel.com, vishal.l.verma@intel.com, alison.schofield@intel.com, Jonathan.Cameron@huawei.com, dave@stgolabs.net, jgg@nvidia.com, shiju.jose@huawei.com Subject: [RFC PATCH 04/13] cxl: Add Get Supported Features command for kernel usage Date: Thu, 18 Jul 2024 14:32:22 -0700 Message-ID: <20240718213446.1750135-5-dave.jiang@intel.com> X-Mailer: git-send-email 2.45.2 In-Reply-To: <20240718213446.1750135-1-dave.jiang@intel.com> References: <20240718213446.1750135-1-dave.jiang@intel.com> Precedence: bulk X-Mailing-List: linux-cxl@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 CXL spec r3.1 8.2.9.6.1 Get Supported Features (Opcode 0500h) The command retrieve the list of supported device-specific features (identified by UUID) and general information about each Feature. The driver will retrieve the feature entries in order to make checks and provide information for the Get Feature and Set Feature command. One of the main piece of information retrieved are the effects a Set Feature command would have for a particular feature. Signed-off-by: Dave Jiang --- drivers/cxl/core/mbox.c | 151 +++++++++++++++++++++++++++++++++++ drivers/cxl/cxlmem.h | 29 +++++++ drivers/cxl/pci.c | 4 + include/linux/cxl/mailbox.h | 3 + include/uapi/linux/cxl_mem.h | 1 + 5 files changed, 188 insertions(+) diff --git a/drivers/cxl/core/mbox.c b/drivers/cxl/core/mbox.c index b9c64f1837a8..70e3962ed570 100644 --- a/drivers/cxl/core/mbox.c +++ b/drivers/cxl/core/mbox.c @@ -67,6 +67,7 @@ static struct cxl_mem_command cxl_mem_commands[CXL_MEM_COMMAND_ID_MAX] = { CXL_CMD(SET_SHUTDOWN_STATE, 0x1, 0, 0), CXL_CMD(GET_SCAN_MEDIA_CAPS, 0x10, 0x4, 0), CXL_CMD(GET_TIMESTAMP, 0, 0x8, 0), + CXL_CMD(GET_SUPPORTED_FEATURES, 0x8, CXL_VARIABLE_PAYLOAD, 0), }; /* @@ -790,6 +791,156 @@ static const uuid_t log_uuid[] = { [VENDOR_DEBUG_UUID] = DEFINE_CXL_VENDOR_DEBUG_UUID, }; +static void cxl_free_features(void *features) +{ + kvfree(features); +} + +static int cxl_get_supported_features_count(struct cxl_mailbox *cxl_mbox) +{ + struct cxl_mbox_get_sup_feats_out mbox_out; + struct cxl_mbox_get_sup_feats_in mbox_in; + struct cxl_mbox_cmd mbox_cmd; + int rc; + + memset(&mbox_in, 0, sizeof(mbox_in)); + mbox_in.count = sizeof(mbox_out); + memset(&mbox_out, 0, sizeof(mbox_out)); + mbox_cmd = (struct cxl_mbox_cmd) { + .opcode = CXL_MBOX_OP_GET_SUPPORTED_FEATURES, + .size_in = sizeof(mbox_in), + .payload_in = &mbox_in, + .size_out = sizeof(mbox_out), + .payload_out = &mbox_out, + .min_out = sizeof(mbox_out), + }; + rc = cxl_internal_send_cmd(cxl_mbox, &mbox_cmd); + if (rc < 0) + return rc; + + cxl_mbox->num_features = le16_to_cpu(mbox_out.supported_feats); + if (!cxl_mbox->num_features) + return -ENOENT; + + return 0; +} + +int cxl_get_supported_features(struct cxl_mailbox *cxl_mbox) +{ + int remain_feats, max_size, max_feats, start, rc; + int feat_size = sizeof(struct cxl_feat_entry); + struct cxl_mbox_get_sup_feats_out *mbox_out; + struct cxl_mbox_get_sup_feats_in mbox_in; + int hdr_size = sizeof(*mbox_out); + struct cxl_mbox_cmd mbox_cmd; + struct cxl_mem_command *cmd; + void *ptr; + + /* Get supported features is optional, need to check */ + cmd = cxl_mem_find_command(CXL_MBOX_OP_GET_SUPPORTED_FEATURES); + if (!cmd) + return -EOPNOTSUPP; + if (!test_bit(cmd->info.id, cxl_mbox->enabled_cmds)) + return -EOPNOTSUPP; + + rc = cxl_get_supported_features_count(cxl_mbox); + if (rc) + return rc; + + struct cxl_feat_entry *entries __free(kvfree) = + kvmalloc(cxl_mbox->num_features * feat_size, GFP_KERNEL); + + if (!entries) + return -ENOMEM; + + cxl_mbox->entries = no_free_ptr(entries); + rc = devm_add_action_or_reset(cxl_mbox->host, cxl_free_features, + cxl_mbox->entries); + if (rc) + return rc; + + max_size = cxl_mbox->payload_size - hdr_size; + /* max feat entries that can fit in mailbox max payload size */ + max_feats = max_size / feat_size; + ptr = &cxl_mbox->entries[0]; + + mbox_out = kvmalloc(cxl_mbox->payload_size, GFP_KERNEL); + if (!mbox_out) + return -ENOMEM; + + start = 0; + remain_feats = cxl_mbox->num_features; + do { + int retrieved, alloc_size, copy_feats; + + if (remain_feats > max_feats) { + alloc_size = sizeof(*mbox_out) + max_feats * feat_size; + remain_feats = remain_feats - max_feats; + copy_feats = max_feats; + } else { + alloc_size = sizeof(*mbox_out) + remain_feats * feat_size; + copy_feats = remain_feats; + remain_feats = 0; + } + + memset(&mbox_in, 0, sizeof(mbox_in)); + mbox_in.count = alloc_size; + mbox_in.start_idx = start; + memset(mbox_out, 0, alloc_size); + mbox_cmd = (struct cxl_mbox_cmd) { + .opcode = CXL_MBOX_OP_GET_SUPPORTED_FEATURES, + .size_in = sizeof(mbox_in), + .payload_in = &mbox_in, + .size_out = alloc_size, + .payload_out = mbox_out, + .min_out = hdr_size, + }; + rc = cxl_internal_send_cmd(cxl_mbox, &mbox_cmd); + if (rc < 0) + return rc; + + if (mbox_cmd.size_out <= hdr_size) { + rc = -ENXIO; + goto err; + } + + /* + * Make sure retrieved out buffer is multiple of feature + * entries. + */ + retrieved = mbox_cmd.size_out - hdr_size; + if (retrieved % sizeof(struct cxl_feat_entry)) { + rc = -ENXIO; + goto err; + } + + /* + * If the reported output entries * defined entry size != + * retrieved output bytes, then the output package is incorrect. + */ + if (mbox_out->num_entries * feat_size != retrieved) { + rc = -ENXIO; + goto err; + } + + memcpy(ptr, mbox_out->ents, retrieved); + ptr += retrieved; + /* + * If the number of output entries is less than expected, add the + * remaining entries to the next batch. + */ + remain_feats += copy_feats - mbox_out->num_entries; + start += mbox_out->num_entries; + } while (remain_feats); + + return 0; + +err: + cxl_mbox->num_features = 0; + return rc; +} +EXPORT_SYMBOL_NS_GPL(cxl_get_supported_features, CXL); + /** * cxl_enumerate_cmds() - Enumerate commands for a device. * @mds: The driver data for the operation diff --git a/drivers/cxl/cxlmem.h b/drivers/cxl/cxlmem.h index efdf833f2c51..4d3690aa2f3b 100644 --- a/drivers/cxl/cxlmem.h +++ b/drivers/cxl/cxlmem.h @@ -482,6 +482,7 @@ enum cxl_opcode { CXL_MBOX_OP_GET_LOG_CAPS = 0x0402, CXL_MBOX_OP_CLEAR_LOG = 0x0403, CXL_MBOX_OP_GET_SUP_LOG_SUBLIST = 0x0405, + CXL_MBOX_OP_GET_SUPPORTED_FEATURES = 0x0500, CXL_MBOX_OP_IDENTIFY = 0x4000, CXL_MBOX_OP_GET_PARTITION_INFO = 0x4100, CXL_MBOX_OP_SET_PARTITION_INFO = 0x4101, @@ -765,6 +766,32 @@ enum { CXL_PMEM_SEC_PASS_USER, }; +/* Get Supported Features (0x500h) CXL r3.1 8.2.9.6.1 */ +struct cxl_mbox_get_sup_feats_in { + __le32 count; + __le16 start_idx; + __le16 reserved; +} __packed; + +struct cxl_feat_entry { + uuid_t uuid; + __le16 id; + __le16 get_feat_size; + __le16 set_feat_size; + __le32 flags; + u8 get_feat_ver; + u8 set_feat_ver; + __le16 effects; + u8 reserved[18]; +} __packed; + +struct cxl_mbox_get_sup_feats_out { + __le16 num_entries; + __le16 supported_feats; + __le32 reserved; + struct cxl_feat_entry ents[] __counted_by(le32_to_cpu(supported_feats)); +} __packed; + int cxl_internal_send_cmd(struct cxl_mailbox *cxl_mbox, struct cxl_mbox_cmd *cmd); int cxl_dev_state_identify(struct cxl_memdev_state *mds); @@ -824,4 +851,6 @@ struct cxl_hdm { struct seq_file; struct dentry *cxl_debugfs_create_dir(const char *dir); void cxl_dpa_debug(struct seq_file *file, struct cxl_dev_state *cxlds); + +int cxl_get_supported_features(struct cxl_mailbox *cxl_mbox); #endif /* __CXL_MEM_H__ */ diff --git a/drivers/cxl/pci.c b/drivers/cxl/pci.c index 7e26da706921..6a00238446f9 100644 --- a/drivers/cxl/pci.c +++ b/drivers/cxl/pci.c @@ -872,6 +872,10 @@ static int cxl_pci_probe(struct pci_dev *pdev, const struct pci_device_id *id) if (rc) return rc; + rc = cxl_get_supported_features(&cxlds->cxl_mbox); + if (rc) + dev_dbg(&pdev->dev, "No features enumerated.\n"); + rc = cxl_set_timestamp(mds); if (rc) return rc; diff --git a/include/linux/cxl/mailbox.h b/include/linux/cxl/mailbox.h index 2380b22d7a12..570864239b8f 100644 --- a/include/linux/cxl/mailbox.h +++ b/include/linux/cxl/mailbox.h @@ -53,6 +53,7 @@ struct cxl_mbox_cmd { * @mbox_mutex: mutex protects device mailbox and firmware * @mbox_wait: rcuwait for mailbox * @mbox_send: @dev specific transport for transmitting mailbox commands + * @features: number of supported features */ struct cxl_mailbox { struct device *host; @@ -63,6 +64,8 @@ struct cxl_mailbox { struct mutex mbox_mutex; /* lock to protect mailbox context */ struct rcuwait mbox_wait; int (*mbox_send)(struct cxl_mailbox *cxl_mbox, struct cxl_mbox_cmd *cmd); + int num_features; + struct cxl_feat_entry *entries; }; #endif diff --git a/include/uapi/linux/cxl_mem.h b/include/uapi/linux/cxl_mem.h index c6c0fe27495d..bd2535962f70 100644 --- a/include/uapi/linux/cxl_mem.h +++ b/include/uapi/linux/cxl_mem.h @@ -50,6 +50,7 @@ ___C(GET_LOG_CAPS, "Get Log Capabilities"), \ ___C(CLEAR_LOG, "Clear Log"), \ ___C(GET_SUP_LOG_SUBLIST, "Get Supported Logs Sub-List"), \ + ___C(GET_SUPPORTED_FEATURES, "Get Supported Features"), \ ___C(MAX, "invalid / last command") #define ___C(a, b) CXL_MEM_COMMAND_ID_##a From patchwork Thu Jul 18 21:32:23 2024 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Dave Jiang X-Patchwork-Id: 13736742 Received: from smtp.kernel.org (aws-us-west-2-korg-mail-1.web.codeaurora.org [10.30.226.201]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by smtp.subspace.kernel.org (Postfix) with ESMTPS id 65E9D81751 for ; Thu, 18 Jul 2024 21:34:58 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=10.30.226.201 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1721338498; cv=none; b=j9Jx794mj1DALaagyY70PULgWg2rzgC+/8+bXhd9OJGBU8lYsaKbJjYQ6If1fnHp7IMYAIEhf9FDjy9AjjkgVn+7BYBV7hArwBgJBCfaL/O5nXG1a6o77EdQ7IktHiTMAZu+LHVecPGAfK/hfMqsArych3a33EpjEUoupyZcSh0= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1721338498; c=relaxed/simple; bh=cmNAgy0MbiQUno8xCz5h9pGG2UjLl6+Xz6z+JYLrcaQ=; h=From:To:Cc:Subject:Date:Message-ID:In-Reply-To:References: MIME-Version; b=FbIYhJM4ROMoxw0TtN0E2abPOGrFdOAN5LYYuS06vjALjfNHEpwH6PYQyQAb/J4o/30JI35W3e9gQcieVsO1at34c8VDB9Uh2WL17bQeA7ubl24pS12Gl4ymdTLUL0VkmLAwL3ezNUno9B1rM5SDuy8pNAE9e91gCt8GIIBsx6Y= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; arc=none smtp.client-ip=10.30.226.201 Received: by smtp.kernel.org (Postfix) with ESMTPSA id C0DD4C116B1; Thu, 18 Jul 2024 21:34:57 +0000 (UTC) From: Dave Jiang To: linux-cxl@vger.kernel.org Cc: dan.j.williams@intel.com, ira.weiny@intel.com, vishal.l.verma@intel.com, alison.schofield@intel.com, Jonathan.Cameron@huawei.com, dave@stgolabs.net, jgg@nvidia.com, shiju.jose@huawei.com Subject: [RFC PATCH 05/13] cxl/test: Add Get Supported Features mailbox command support Date: Thu, 18 Jul 2024 14:32:23 -0700 Message-ID: <20240718213446.1750135-6-dave.jiang@intel.com> X-Mailer: git-send-email 2.45.2 In-Reply-To: <20240718213446.1750135-1-dave.jiang@intel.com> References: <20240718213446.1750135-1-dave.jiang@intel.com> Precedence: bulk X-Mailing-List: linux-cxl@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 Add cxl-test emulation of Get Supported Features mailbox command. Currently only planning to add the Device Patrol Scrub Control feature as a testing vehicle. CXL spec r3.1 8.2.9.9.11.1 Device Patrol Scrub Control Feature. Signed-off-by: Dave Jiang --- tools/testing/cxl/test/mem.c | 69 ++++++++++++++++++++++++++++++++++++ 1 file changed, 69 insertions(+) diff --git a/tools/testing/cxl/test/mem.c b/tools/testing/cxl/test/mem.c index 20d58f883ca2..c2e04dbc8af6 100644 --- a/tools/testing/cxl/test/mem.c +++ b/tools/testing/cxl/test/mem.c @@ -44,6 +44,10 @@ static struct cxl_cel_entry mock_cel[] = { .opcode = cpu_to_le16(CXL_MBOX_OP_GET_SUPPORTED_LOGS), .effect = CXL_CMD_EFFECT_NONE, }, + { + .opcode = cpu_to_le16(CXL_MBOX_OP_GET_SUPPORTED_FEATURES), + .effect = CXL_CMD_EFFECT_NONE, + }, { .opcode = cpu_to_le16(CXL_MBOX_OP_IDENTIFY), .effect = CXL_CMD_EFFECT_NONE, @@ -1334,6 +1338,64 @@ static int mock_activate_fw(struct cxl_mockmem_data *mdata, return -EINVAL; } +#define DEV_PATROL_SCRUB_FEAT_UUID \ + UUID_INIT(0x96dad7d6, 0xfde8, 0x482b, 0xa7, 0x33, 0x75, 0x77, 0x4e, \ + 0x06, 0xdb, 0x8a) + +static void fill_feature_device_patrol_scrub_control(struct cxl_feat_entry *feat) +{ + feat->uuid = DEV_PATROL_SCRUB_FEAT_UUID; + feat->id = 0; + feat->get_feat_size = cpu_to_le16(4); + feat->set_feat_size = cpu_to_le16(2); + feat->flags = cpu_to_le32(0x21); + feat->get_feat_ver = 1; + feat->set_feat_ver = 1; + feat->effects = cpu_to_le16(0x202); +} + +static int mock_get_supported_features(struct cxl_mockmem_data *mdata, + struct cxl_mbox_cmd *cmd) +{ + struct cxl_mbox_get_sup_feats_in *in = cmd->payload_in; + struct cxl_mbox_get_sup_feats_out *out = cmd->payload_out; + struct cxl_feat_entry *feat; + u16 start_idx, count; + + if (cmd->size_out < sizeof(*out)) { + cmd->return_code = CXL_MBOX_CMD_RC_PAYLOADLEN; + return -EINVAL; + } + + /* + * Current emulation only supports 1 feature + */ + start_idx = le16_to_cpu(in->start_idx); + if (start_idx != 0) { + cmd->return_code = CXL_MBOX_CMD_RC_INPUT; + return -EINVAL; + } + + count = le16_to_cpu(in->count); + if (count < sizeof(*out)) { + cmd->return_code = CXL_MBOX_CMD_RC_PAYLOADLEN; + return -EINVAL; + } + + out->supported_feats = cpu_to_le16(1); + cmd->return_code = 0; + if (count < sizeof(*out) + sizeof(*feat)) { + out->num_entries = 0; + return 0; + } + + out->num_entries = 1; + feat = out->ents; + fill_feature_device_patrol_scrub_control(feat); + + return 0; +} + static int cxl_mock_mbox_send(struct cxl_mailbox *cxl_mbox, struct cxl_mbox_cmd *cmd) { @@ -1421,6 +1483,9 @@ static int cxl_mock_mbox_send(struct cxl_mailbox *cxl_mbox, case CXL_MBOX_OP_ACTIVATE_FW: rc = mock_activate_fw(mdata, cmd); break; + case CXL_MBOX_OP_GET_SUPPORTED_FEATURES: + rc = mock_get_supported_features(mdata, cmd); + break; default: break; } @@ -1508,6 +1573,10 @@ static int cxl_mock_mem_probe(struct platform_device *pdev) if (rc) return rc; + rc = cxl_get_supported_features(&cxlds->cxl_mbox); + if (rc) + dev_dbg(dev, "No features enumerated\n"); + rc = cxl_poison_state_init(mds); if (rc) return rc; From patchwork Thu Jul 18 21:32:24 2024 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Dave Jiang X-Patchwork-Id: 13736743 Received: from smtp.kernel.org (aws-us-west-2-korg-mail-1.web.codeaurora.org [10.30.226.201]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by smtp.subspace.kernel.org (Postfix) with ESMTPS id CEC101459FC for ; Thu, 18 Jul 2024 21:34:59 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=10.30.226.201 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1721338499; cv=none; b=WreqEOzIOg/cTqilebm/VHK50gXgrVgKVXK44e6pbl9f33XZcvMHTCXhJ9BarRdF4Wt6Jzu8SSzyqBaPOuKOi65nPOnH3KEBueRDzaR7ba5WajK9vUHMm7y9waYMdi5U+5rs7hiiUNFtlYxcxEdF1RnHUiYM9QkYmrSRnyyrb/E= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1721338499; c=relaxed/simple; bh=54UW/LOvNEtk5bhVJWRTaXQhqV9sMrplx2nvvXQMxls=; h=From:To:Cc:Subject:Date:Message-ID:In-Reply-To:References: MIME-Version; b=QgG7uzUgqH2dIr+EmLB51D03IzGwrbnohYi154uoCwq3RhR1l3U0TObWeBleKkhODJzbbE60ZaR1NXfBab7YNGSQnVd4PqsQUcxj45ZhLnAL0H41QvZb5Zhx+7TjDJL8LaKloLVK7RcR7YQrVa2uUNDKwcVAepmh017Fn4frx4Y= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; arc=none smtp.client-ip=10.30.226.201 Received: by smtp.kernel.org (Postfix) with ESMTPSA id 445A7C116B1; Thu, 18 Jul 2024 21:34:59 +0000 (UTC) From: Dave Jiang To: linux-cxl@vger.kernel.org Cc: dan.j.williams@intel.com, ira.weiny@intel.com, vishal.l.verma@intel.com, alison.schofield@intel.com, Jonathan.Cameron@huawei.com, dave@stgolabs.net, jgg@nvidia.com, shiju.jose@huawei.com Subject: [RFC PATCH 06/13] cxl: Add Get Feature command support Date: Thu, 18 Jul 2024 14:32:24 -0700 Message-ID: <20240718213446.1750135-7-dave.jiang@intel.com> X-Mailer: git-send-email 2.45.2 In-Reply-To: <20240718213446.1750135-1-dave.jiang@intel.com> References: <20240718213446.1750135-1-dave.jiang@intel.com> Precedence: bulk X-Mailing-List: linux-cxl@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 Add enumeration of Get Feature mailbox command for the kernel to recognize the command being passed in from user space. CXL spec r3.1 8.2.9.6.2 Get Feature (Opcode 0501h) The feature requested is identified by specific UUID. Signed-off-by: Dave Jiang --- drivers/cxl/core/mbox.c | 1 + drivers/cxl/cxlmem.h | 1 + include/uapi/linux/cxl_mem.h | 1 + 3 files changed, 3 insertions(+) diff --git a/drivers/cxl/core/mbox.c b/drivers/cxl/core/mbox.c index 70e3962ed570..b58b8cc517c9 100644 --- a/drivers/cxl/core/mbox.c +++ b/drivers/cxl/core/mbox.c @@ -68,6 +68,7 @@ static struct cxl_mem_command cxl_mem_commands[CXL_MEM_COMMAND_ID_MAX] = { CXL_CMD(GET_SCAN_MEDIA_CAPS, 0x10, 0x4, 0), CXL_CMD(GET_TIMESTAMP, 0, 0x8, 0), CXL_CMD(GET_SUPPORTED_FEATURES, 0x8, CXL_VARIABLE_PAYLOAD, 0), + CXL_CMD(GET_FEATURE, 0x15, CXL_VARIABLE_PAYLOAD, 0), }; /* diff --git a/drivers/cxl/cxlmem.h b/drivers/cxl/cxlmem.h index 4d3690aa2f3b..317cb92b0bfb 100644 --- a/drivers/cxl/cxlmem.h +++ b/drivers/cxl/cxlmem.h @@ -483,6 +483,7 @@ enum cxl_opcode { CXL_MBOX_OP_CLEAR_LOG = 0x0403, CXL_MBOX_OP_GET_SUP_LOG_SUBLIST = 0x0405, CXL_MBOX_OP_GET_SUPPORTED_FEATURES = 0x0500, + CXL_MBOX_OP_GET_FEATURE = 0x0501, CXL_MBOX_OP_IDENTIFY = 0x4000, CXL_MBOX_OP_GET_PARTITION_INFO = 0x4100, CXL_MBOX_OP_SET_PARTITION_INFO = 0x4101, diff --git a/include/uapi/linux/cxl_mem.h b/include/uapi/linux/cxl_mem.h index bd2535962f70..90dcb9723997 100644 --- a/include/uapi/linux/cxl_mem.h +++ b/include/uapi/linux/cxl_mem.h @@ -51,6 +51,7 @@ ___C(CLEAR_LOG, "Clear Log"), \ ___C(GET_SUP_LOG_SUBLIST, "Get Supported Logs Sub-List"), \ ___C(GET_SUPPORTED_FEATURES, "Get Supported Features"), \ + ___C(GET_FEATURE, "Get Feature"), \ ___C(MAX, "invalid / last command") #define ___C(a, b) CXL_MEM_COMMAND_ID_##a From patchwork Thu Jul 18 21:32:25 2024 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Dave Jiang X-Patchwork-Id: 13736744 Received: from smtp.kernel.org (aws-us-west-2-korg-mail-1.web.codeaurora.org [10.30.226.201]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by smtp.subspace.kernel.org (Postfix) with ESMTPS id 257A681751 for ; Thu, 18 Jul 2024 21:35:00 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=10.30.226.201 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1721338501; cv=none; b=brJJ0DHCkwExfODnitKLyBNhmHD93Z10a8LyXBA4ldYsPuaiP0OmkJSJc4x935sbZGvRrysOYQbq9H5iSev1gM4hKiqAo1LNVAgLopF5fcv+cnN4UdmXnnQfnV+vKxSjO0JSnCnJqg4YtMt2Tnq8LPx+EkJjAPiV5k49fdIksms= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1721338501; c=relaxed/simple; bh=7lpqQo20VHbR0ZHrNqOhPq0IIPMIeG77uCSLvt9+9f8=; h=From:To:Cc:Subject:Date:Message-ID:In-Reply-To:References: MIME-Version; b=knJFNXwog/5ED47yixqoqObtWjljc6ndYZZWlBWzwaiOhpwgo1IMQ/37lmb4Rc3NgdWxoMnAinpxGGINeyfcl4bEx/N8Bz6NYPaIvreRrwf181GRNOThXHBbVBelFDGkstd1X8i0bG8BCVljf1GLH6DbnaZIyx66qPf7xmv0vxY= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; arc=none smtp.client-ip=10.30.226.201 Received: by smtp.kernel.org (Postfix) with ESMTPSA id A8FF1C116B1; Thu, 18 Jul 2024 21:35:00 +0000 (UTC) From: Dave Jiang To: linux-cxl@vger.kernel.org Cc: dan.j.williams@intel.com, ira.weiny@intel.com, vishal.l.verma@intel.com, alison.schofield@intel.com, Jonathan.Cameron@huawei.com, dave@stgolabs.net, jgg@nvidia.com, shiju.jose@huawei.com Subject: [RFC PATCH 07/13] cxl: Add Set Feature command support Date: Thu, 18 Jul 2024 14:32:25 -0700 Message-ID: <20240718213446.1750135-8-dave.jiang@intel.com> X-Mailer: git-send-email 2.45.2 In-Reply-To: <20240718213446.1750135-1-dave.jiang@intel.com> References: <20240718213446.1750135-1-dave.jiang@intel.com> Precedence: bulk X-Mailing-List: linux-cxl@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 Add enumeration of Set Feature mailbox command for the kernel to recognize the command being passed in from user space. CXL spec r3.1 8.2.9.6.3 Set Feature (Opcode 0502h) The feature requested is identified by specific UUID. Signed-off-by: Dave Jiang --- drivers/cxl/core/mbox.c | 1 + drivers/cxl/cxlmem.h | 1 + include/uapi/linux/cxl_mem.h | 1 + 3 files changed, 3 insertions(+) diff --git a/drivers/cxl/core/mbox.c b/drivers/cxl/core/mbox.c index b58b8cc517c9..14ebe69c47bf 100644 --- a/drivers/cxl/core/mbox.c +++ b/drivers/cxl/core/mbox.c @@ -69,6 +69,7 @@ static struct cxl_mem_command cxl_mem_commands[CXL_MEM_COMMAND_ID_MAX] = { CXL_CMD(GET_TIMESTAMP, 0, 0x8, 0), CXL_CMD(GET_SUPPORTED_FEATURES, 0x8, CXL_VARIABLE_PAYLOAD, 0), CXL_CMD(GET_FEATURE, 0x15, CXL_VARIABLE_PAYLOAD, 0), + CXL_CMD(SET_FEATURE, CXL_VARIABLE_PAYLOAD, 0, 0), }; /* diff --git a/drivers/cxl/cxlmem.h b/drivers/cxl/cxlmem.h index 317cb92b0bfb..5e190f941e58 100644 --- a/drivers/cxl/cxlmem.h +++ b/drivers/cxl/cxlmem.h @@ -484,6 +484,7 @@ enum cxl_opcode { CXL_MBOX_OP_GET_SUP_LOG_SUBLIST = 0x0405, CXL_MBOX_OP_GET_SUPPORTED_FEATURES = 0x0500, CXL_MBOX_OP_GET_FEATURE = 0x0501, + CXL_MBOX_OP_SET_FEATURE = 0x0502, CXL_MBOX_OP_IDENTIFY = 0x4000, CXL_MBOX_OP_GET_PARTITION_INFO = 0x4100, CXL_MBOX_OP_SET_PARTITION_INFO = 0x4101, diff --git a/include/uapi/linux/cxl_mem.h b/include/uapi/linux/cxl_mem.h index 90dcb9723997..469dd481795f 100644 --- a/include/uapi/linux/cxl_mem.h +++ b/include/uapi/linux/cxl_mem.h @@ -52,6 +52,7 @@ ___C(GET_SUP_LOG_SUBLIST, "Get Supported Logs Sub-List"), \ ___C(GET_SUPPORTED_FEATURES, "Get Supported Features"), \ ___C(GET_FEATURE, "Get Feature"), \ + ___C(SET_FEATURE, "Set Feature"), \ ___C(MAX, "invalid / last command") #define ___C(a, b) CXL_MEM_COMMAND_ID_##a From patchwork Thu Jul 18 21:32:26 2024 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Dave Jiang X-Patchwork-Id: 13736745 Received: from smtp.kernel.org (aws-us-west-2-korg-mail-1.web.codeaurora.org [10.30.226.201]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by smtp.subspace.kernel.org (Postfix) with ESMTPS id 61B4B81219 for ; Thu, 18 Jul 2024 21:35:02 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=10.30.226.201 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1721338502; cv=none; b=CmoDmTLt5SgIt8Xu87e0NJ86IDwZzOcTbVF7rHTjcNpCnjIhOHYSUB+Xhq3x+a3EFf7UeaQGskf1JkQ6IlzJBin2ndo9Qnq2CTf7NNXdjA5NRgtYuV2jf0PJrorRfZbrbDIjT2fOxYEb7q6bqFpRsLQPmZ/zmHJkRrLp7a3Wf+g= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1721338502; c=relaxed/simple; bh=88XMW+ArlhbwSSxJTeIF4sdiTGUwgV2EhkazfHHXUAo=; h=From:To:Cc:Subject:Date:Message-ID:In-Reply-To:References: MIME-Version; b=aOLlBdJsJ44vE/G1/uBbw3X0oXMwgigf6Axn1vWnHOJTrSB95Ow2dPi7wP3XXH5VMuip+1woINGsk3bppki0VQaeUWT+CWi4qI+03LJi38XeQ5/O3f/haMEceN44MUlPd19AlyyyO9UY2choiVAWJqD76NE2n9jj+fPMA2eXZ5s= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; arc=none smtp.client-ip=10.30.226.201 Received: by smtp.kernel.org (Postfix) with ESMTPSA id 282D9C4AF09; Thu, 18 Jul 2024 21:35:02 +0000 (UTC) From: Dave Jiang To: linux-cxl@vger.kernel.org Cc: dan.j.williams@intel.com, ira.weiny@intel.com, vishal.l.verma@intel.com, alison.schofield@intel.com, Jonathan.Cameron@huawei.com, dave@stgolabs.net, jgg@nvidia.com, shiju.jose@huawei.com Subject: [RFC PATCH 08/13] fwctl/cxl: Add driver for CXL mailbox for handling CXL features commands Date: Thu, 18 Jul 2024 14:32:26 -0700 Message-ID: <20240718213446.1750135-9-dave.jiang@intel.com> X-Mailer: git-send-email 2.45.2 In-Reply-To: <20240718213446.1750135-1-dave.jiang@intel.com> References: <20240718213446.1750135-1-dave.jiang@intel.com> Precedence: bulk X-Mailing-List: linux-cxl@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 Add an fwctl (auxiliary bus) driver to allow sending of CXL feature commands from userspace through as ioctls. Create a driver skeleton for initial setup. Signed-off-by: Dave Jiang --- MAINTAINERS | 7 +++ drivers/cxl/core/memdev.c | 19 +++++++ drivers/fwctl/Kconfig | 9 ++++ drivers/fwctl/Makefile | 1 + drivers/fwctl/cxl/Makefile | 4 ++ drivers/fwctl/cxl/cxl.c | 103 +++++++++++++++++++++++++++++++++++++ include/uapi/fwctl/fwctl.h | 1 + 7 files changed, 144 insertions(+) create mode 100644 drivers/fwctl/cxl/Makefile create mode 100644 drivers/fwctl/cxl/cxl.c diff --git a/MAINTAINERS b/MAINTAINERS index 3e1934b7e044..5d6c470c06ea 100644 --- a/MAINTAINERS +++ b/MAINTAINERS @@ -9073,6 +9073,13 @@ L: linux-kernel@vger.kernel.org S: Maintained F: drivers/fwctl/mlx5/ +FWCTL CXL DRIVER +M: Dave Jiang +R: Dan Williams +L: linux-cxl@vger.kernel.org +S: Maintained +F: drivers/fwctl/cxl/ + GALAXYCORE GC0308 CAMERA SENSOR DRIVER M: Sebastian Reichel L: linux-media@vger.kernel.org diff --git a/drivers/cxl/core/memdev.c b/drivers/cxl/core/memdev.c index 9f0fe698414d..0f6ec85ef9c4 100644 --- a/drivers/cxl/core/memdev.c +++ b/drivers/cxl/core/memdev.c @@ -13,6 +13,8 @@ static DECLARE_RWSEM(cxl_memdev_rwsem); +#define CXL_ADEV_NAME "fwctl-cxl" + /* * An entire PCI topology full of devices should be enough for any * config @@ -1030,6 +1032,7 @@ static const struct file_operations cxl_memdev_fops = { struct cxl_memdev *devm_cxl_add_memdev(struct device *host, struct cxl_dev_state *cxlds) { + struct auxiliary_device *adev; struct cxl_memdev *cxlmd; struct device *dev; struct cdev *cdev; @@ -1056,11 +1059,27 @@ struct cxl_memdev *devm_cxl_add_memdev(struct device *host, if (rc) goto err; + adev = &cxlds->cxl_mbox.adev; + adev->id = cxlmd->id; + adev->name = CXL_ADEV_NAME; + adev->dev.parent = dev; + + rc = auxiliary_device_init(adev); + if (rc) + goto err; + + rc = auxiliary_device_add(adev); + if (rc) + goto aux_err; + rc = devm_add_action_or_reset(host, cxl_memdev_unregister, cxlmd); if (rc) return ERR_PTR(rc); return cxlmd; +aux_err: + auxiliary_device_uninit(adev); + err: /* * The cdev was briefly live, shutdown any ioctl operations that diff --git a/drivers/fwctl/Kconfig b/drivers/fwctl/Kconfig index e5ee2d46d431..e49903a9d0d3 100644 --- a/drivers/fwctl/Kconfig +++ b/drivers/fwctl/Kconfig @@ -19,5 +19,14 @@ config FWCTL_MLX5 This will allow configuration and debug tools to work out of the box on mainstream kernel. + If you don't know what to do here, say N. + +config FWCTL_CXL + tristate "CXL fwctl driver" + depends on CXL_BUS + help + CXLCTL provides interface for the user process to access user allowed + mailbox commands for CXL device. + If you don't know what to do here, say N. endif diff --git a/drivers/fwctl/Makefile b/drivers/fwctl/Makefile index 1c535f694d7f..bd356e6f2e5a 100644 --- a/drivers/fwctl/Makefile +++ b/drivers/fwctl/Makefile @@ -1,5 +1,6 @@ # SPDX-License-Identifier: GPL-2.0 obj-$(CONFIG_FWCTL) += fwctl.o obj-$(CONFIG_FWCTL_MLX5) += mlx5/ +obj-$(CONFIG_FWCTL_CXL) += cxl/ fwctl-y += main.o diff --git a/drivers/fwctl/cxl/Makefile b/drivers/fwctl/cxl/Makefile new file mode 100644 index 000000000000..623194521572 --- /dev/null +++ b/drivers/fwctl/cxl/Makefile @@ -0,0 +1,4 @@ +# SPDX-License-Identifier: GPL-2.0 +obj-$(CONFIG_FWCTL_CXL) += cxl_fwctl.o + +cxl_fwctl-y += cxl.o diff --git a/drivers/fwctl/cxl/cxl.c b/drivers/fwctl/cxl/cxl.c new file mode 100644 index 000000000000..518ba2afada8 --- /dev/null +++ b/drivers/fwctl/cxl/cxl.c @@ -0,0 +1,103 @@ +// SPDX-License-Identifier: GPL-2.0-only +/* + * Copyright (c) 2024, Intel Corporation + */ +#include +#include +#include +#include + +struct cxlctl_uctx { + struct fwctl_uctx uctx; + u32 uctx_caps; + u32 uctx_uid; +}; + +struct cxlctl_dev { + struct fwctl_device fwctl; + struct cxl_mailbox *mbox; +}; + +DEFINE_FREE(cxlctl, struct cxlctl_dev *, if (_T) fwctl_put(&_T->fwctl)) + +static int cxlctl_open_uctx(struct fwctl_uctx *uctx) +{ + return 0; +} + +static void cxlctl_close_uctx(struct fwctl_uctx *uctx) +{ +} + +static void *cxlctl_info(struct fwctl_uctx *uctx, size_t *length) +{ + /* Place holder */ + return ERR_PTR(-EOPNOTSUPP); +} + +static void *cxlctl_fw_rpc(struct fwctl_uctx *uctx, enum fwctl_rpc_scope scope, + void *rpc_in, size_t in_len, size_t *out_len) +{ + /* Place holder */ + return ERR_PTR(-EOPNOTSUPP); +} + +static const struct fwctl_ops cxlctl_ops = { + .device_type = FWCTL_DEVICE_TYPE_CXL, + .uctx_size = sizeof(struct cxlctl_uctx), + .open_uctx = cxlctl_open_uctx, + .close_uctx = cxlctl_close_uctx, + .info = cxlctl_info, + .fw_rpc = cxlctl_fw_rpc, +}; + +static int cxlctl_probe(struct auxiliary_device *adev, + const struct auxiliary_device_id *id) +{ + struct cxl_mailbox *mbox = container_of(adev, struct cxl_mailbox, adev); + struct cxlctl_dev *cxlctl __free(cxlctl) = + fwctl_alloc_device(mbox->host, &cxlctl_ops, + struct cxlctl_dev, fwctl); + int rc; + + if (!cxlctl) + return -ENOMEM; + + cxlctl->mbox = mbox; + + rc = fwctl_register(&cxlctl->fwctl); + if (rc) + return rc; + + auxiliary_set_drvdata(adev, no_free_ptr(cxlctl)); + + return 0; +} + +static void cxlctl_remove(struct auxiliary_device *adev) +{ + struct cxlctl_dev *ctldev __free(cxlctl) = auxiliary_get_drvdata(adev); + + fwctl_unregister(&ctldev->fwctl); +} + +static const struct auxiliary_device_id cxlctl_id_table[] = { + { .name = "CXL.fwctl", }, + {}, +}; +MODULE_DEVICE_TABLE(auxiliary, cxlctl_id_table); + +static struct auxiliary_driver cxlctl_driver = { + .name = "cxl_fwctl", + .probe = cxlctl_probe, + .remove = cxlctl_remove, + .id_table = cxlctl_id_table, +}; + +module_auxiliary_driver(cxlctl_driver); + +MODULE_IMPORT_NS(CXL); +MODULE_IMPORT_NS(FWCTL); +MODULE_DESCRIPTION("CXL fwctl driver"); +MODULE_AUTHOR("Intel Corporation"); +MODULE_LICENSE("GPL"); diff --git a/include/uapi/fwctl/fwctl.h b/include/uapi/fwctl/fwctl.h index 49a357e1bc71..6edcc38a6eee 100644 --- a/include/uapi/fwctl/fwctl.h +++ b/include/uapi/fwctl/fwctl.h @@ -43,6 +43,7 @@ enum { enum fwctl_device_type { FWCTL_DEVICE_TYPE_ERROR = 0, FWCTL_DEVICE_TYPE_MLX5 = 1, + FWCTL_DEVICE_TYPE_CXL = 2, }; /** From patchwork Thu Jul 18 21:32:27 2024 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Dave Jiang X-Patchwork-Id: 13736746 Received: from smtp.kernel.org (aws-us-west-2-korg-mail-1.web.codeaurora.org [10.30.226.201]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by smtp.subspace.kernel.org (Postfix) with ESMTPS id 345967F7C7 for ; Thu, 18 Jul 2024 21:35:03 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=10.30.226.201 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1721338504; cv=none; b=WwY1fiL4N9WdSM0TwAxu79zaKlWIJLjIsr+hwN4g4XTXqqHfr4DH8csCAa/EO92RZtIPaBO/kc/ug+BwjD0hMwKi0PA474wSWFmAV1GvtBMG1lGw1WESqpxka1Tmib7Nq07OVPRTx7ivqywt6sbpGMt3biVHfGpWUtlJXYqh0iA= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1721338504; c=relaxed/simple; bh=PpSGVZPVcaZ03xWfeeCBlRVlHzdZxtQDPK2EXDRVE9M=; h=From:To:Cc:Subject:Date:Message-ID:In-Reply-To:References: MIME-Version; b=uwaARfVjGsuPI2f+wrHd87nVZkyemLjQGL0CpVbLlZrWpUH5WmlgAer24lpfFL8qsRrIUE7ZnBG8xN9Od0EjTpPW/S3qKa4HaFOU/gm8r2pj/iCdf5kqzX2J0p/+k4K0671rOTfPPxmKHAshj6uKdOrRiAXIXvZru73iJRf9PPM= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; arc=none smtp.client-ip=10.30.226.201 Received: by smtp.kernel.org (Postfix) with ESMTPSA id 91766C116B1; Thu, 18 Jul 2024 21:35:03 +0000 (UTC) From: Dave Jiang To: linux-cxl@vger.kernel.org Cc: dan.j.williams@intel.com, ira.weiny@intel.com, vishal.l.verma@intel.com, alison.schofield@intel.com, Jonathan.Cameron@huawei.com, dave@stgolabs.net, jgg@nvidia.com, shiju.jose@huawei.com Subject: [RFC PATCH 09/13] fwctl/cxl: Add support for get driver information Date: Thu, 18 Jul 2024 14:32:27 -0700 Message-ID: <20240718213446.1750135-10-dave.jiang@intel.com> X-Mailer: git-send-email 2.45.2 In-Reply-To: <20240718213446.1750135-1-dave.jiang@intel.com> References: <20240718213446.1750135-1-dave.jiang@intel.com> Precedence: bulk X-Mailing-List: linux-cxl@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 Add definition for fwctl_ops->info() to return driver information. The function will return the commands supported by the fwctl char device as a bitmap of enable commands. Signed-off-by: Dave Jiang --- drivers/fwctl/cxl/cxl.c | 20 ++++++++++++++++++-- include/uapi/fwctl/cxl.h | 25 +++++++++++++++++++++++++ 2 files changed, 43 insertions(+), 2 deletions(-) create mode 100644 include/uapi/fwctl/cxl.h diff --git a/drivers/fwctl/cxl/cxl.c b/drivers/fwctl/cxl/cxl.c index 518ba2afada8..22f62034c021 100644 --- a/drivers/fwctl/cxl/cxl.c +++ b/drivers/fwctl/cxl/cxl.c @@ -6,6 +6,7 @@ #include #include #include +#include struct cxlctl_uctx { struct fwctl_uctx uctx; @@ -22,6 +23,12 @@ DEFINE_FREE(cxlctl, struct cxlctl_dev *, if (_T) fwctl_put(&_T->fwctl)) static int cxlctl_open_uctx(struct fwctl_uctx *uctx) { + struct cxlctl_uctx *cxlctl_uctx = + container_of(uctx, struct cxlctl_uctx, uctx); + + cxlctl_uctx->uctx_caps = BIT(FWCTL_CXL_QUERY_COMMANDS) | + BIT(FWCTL_CXL_SEND_COMMAND); + return 0; } @@ -31,8 +38,17 @@ static void cxlctl_close_uctx(struct fwctl_uctx *uctx) static void *cxlctl_info(struct fwctl_uctx *uctx, size_t *length) { - /* Place holder */ - return ERR_PTR(-EOPNOTSUPP); + struct cxlctl_uctx *cxlctl_uctx = + container_of(uctx, struct cxlctl_uctx, uctx); + struct fwctl_info_cxl *info; + + info = kzalloc(sizeof(*info), GFP_KERNEL); + if (!info) + return ERR_PTR(-ENOMEM); + + info->uctx_caps = cxlctl_uctx->uctx_caps; + + return info; } static void *cxlctl_fw_rpc(struct fwctl_uctx *uctx, enum fwctl_rpc_scope scope, diff --git a/include/uapi/fwctl/cxl.h b/include/uapi/fwctl/cxl.h new file mode 100644 index 000000000000..d3a735f1fe4e --- /dev/null +++ b/include/uapi/fwctl/cxl.h @@ -0,0 +1,25 @@ +/* SPDX-License-Identifier: GPL-2.0 WITH Linux-syscall-note */ +/* + * Copyright (c) 2024, Intel Corporation + * + * These are definitions for the mailbox command interface of CXL subsystem. + */ +#ifndef _UAPI_FWCTL_CXL_H_ +#define _UAPI_FWCTL_CXL_H_ + +enum fwctl_cxl_commands { + FWCTL_CXL_QUERY_COMMANDS = 0, + FWCTL_CXL_SEND_COMMAND, +}; + +/** + * struct fwctl_info_cxl - ioctl(FWCTL_INFO) out_device_data + * @uctx_caps: The command capabilities driver accepts. + * + * Return basic information about the FW interface available. + */ +struct fwctl_info_cxl { + __u32 uctx_caps; +}; + +#endif From patchwork Thu Jul 18 21:32:28 2024 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Dave Jiang X-Patchwork-Id: 13736747 Received: from smtp.kernel.org (aws-us-west-2-korg-mail-1.web.codeaurora.org [10.30.226.201]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by smtp.subspace.kernel.org (Postfix) with ESMTPS id 55CA675808 for ; Thu, 18 Jul 2024 21:35:05 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=10.30.226.201 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1721338505; cv=none; b=LEH+XKWAd4RPoD1LmPr6Sfo8ziA8+JXhXYMK8gVCI5/QYN2zE6a94NwKqkmmhXMuo9DNPwbSVsGus7JWCTEyo97bDbMWBVPoOYMC/lc1ofpUYQ+q/NvuVxYgs1KBBLbuhVvdePZIitz5tq3EBEcE6Ro5XW7d6ZRu9qgdwcxGCZs= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1721338505; c=relaxed/simple; bh=u0U8mQPcRfypHwZqgBxtB234+/zIAFI8yDBHTK+vSN8=; h=From:To:Cc:Subject:Date:Message-ID:In-Reply-To:References: MIME-Version; b=QblWfZBlMrtZIL4B1cIOslcjSmM7DXawr0d0eKD3Z6p256VHIerLfSDCrfZrC1dZ9DAu8hw8LVVQmqxBeqzR5W+ZwoSlN139omAGgz6Pqe96rbDB6KbU2N3mMa47Zlfed+H3OptVAFFE537+0gKeEr6P7+FHqNkWQOuKzJENZ3M= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; arc=none smtp.client-ip=10.30.226.201 Received: by smtp.kernel.org (Postfix) with ESMTPSA id 0055BC116B1; Thu, 18 Jul 2024 21:35:04 +0000 (UTC) From: Dave Jiang To: linux-cxl@vger.kernel.org Cc: dan.j.williams@intel.com, ira.weiny@intel.com, vishal.l.verma@intel.com, alison.schofield@intel.com, Jonathan.Cameron@huawei.com, dave@stgolabs.net, jgg@nvidia.com, shiju.jose@huawei.com Subject: [RFC PATCH 10/13] fwctl/cxl: Add support for fwctl RPC command to enable CXL feature commands Date: Thu, 18 Jul 2024 14:32:28 -0700 Message-ID: <20240718213446.1750135-11-dave.jiang@intel.com> X-Mailer: git-send-email 2.45.2 In-Reply-To: <20240718213446.1750135-1-dave.jiang@intel.com> References: <20240718213446.1750135-1-dave.jiang@intel.com> Precedence: bulk X-Mailing-List: linux-cxl@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 fwctl provides a fwctl_ops->fw_rpc() callback in order to issue ioctls to a device. The cxl fwctl driver will start by supporting the CXL feature commands: Get Supported Features, Get Feature, and Set Feature. The fw_rpc() callback provides 'enum fwctl_rpc_scope' parameter where it indicates the security scope of the call. The Get Supported Features and Get Feature calls can be executed with the scope of FWCTL_RPC_DEBUG_READ_ONLY. The Set Feature call is gated by the effects of the feature reported by Get Supported Features call for the specific feature. Signed-off-by: Dave Jiang --- drivers/cxl/core/core.h | 5 +- drivers/cxl/core/mbox.c | 232 ++++++++++++++++++++++++++++++++---- drivers/cxl/core/memdev.c | 4 +- drivers/cxl/cxlmem.h | 83 +------------ drivers/fwctl/cxl/cxl.c | 127 +++++++++++++++++++- include/linux/cxl/mailbox.h | 101 ++++++++++++++++ include/uapi/fwctl/cxl.h | 64 ++++++++++ 7 files changed, 505 insertions(+), 111 deletions(-) diff --git a/drivers/cxl/core/core.h b/drivers/cxl/core/core.h index 7eb33ea07848..f22ee6f84f68 100644 --- a/drivers/cxl/core/core.h +++ b/drivers/cxl/core/core.h @@ -6,6 +6,8 @@ #include +extern struct rw_semaphore cxl_memdev_rwsem; + extern const struct device_type cxl_nvdimm_bridge_type; extern const struct device_type cxl_nvdimm_type; extern const struct device_type cxl_pmu_type; @@ -69,7 +71,8 @@ struct cxl_send_command; struct cxl_mem_query_commands; int cxl_query_cmd(struct cxl_mailbox *cxl_mbox, struct cxl_mem_query_commands __user *q); -int cxl_send_cmd(struct cxl_mailbox *cxl_mailbox, struct cxl_send_command __user *s); +int cxl_send_cmd_from_user(struct cxl_mailbox *cxl_mbox, + struct cxl_send_command __user *s); void __iomem *devm_cxl_iomap_block(struct device *dev, resource_size_t addr, resource_size_t length); diff --git a/drivers/cxl/core/mbox.c b/drivers/cxl/core/mbox.c index 14ebe69c47bf..d77817e347d8 100644 --- a/drivers/cxl/core/mbox.c +++ b/drivers/cxl/core/mbox.c @@ -4,6 +4,7 @@ #include #include #include +#include #include #include #include @@ -215,6 +216,15 @@ static struct cxl_mem_command *cxl_mem_find_command(u16 opcode) return NULL; } +struct cxl_mem_command *cxl_get_mem_command(u32 id) +{ + if (id > CXL_MEM_COMMAND_ID_MAX) + return NULL; + + return &cxl_mem_commands[id]; +} +EXPORT_SYMBOL_NS_GPL(cxl_get_mem_command, CXL); + static const char *cxl_mem_opcode_to_name(u16 opcode) { struct cxl_mem_command *c; @@ -377,10 +387,13 @@ static int cxl_mbox_cmd_ctor(struct cxl_mbox_cmd *mbox_cmd, } /* Prepare to handle a full payload for variable sized output */ - if (out_size == CXL_VARIABLE_PAYLOAD) - mbox_cmd->size_out = cxl_mbox->payload_size; - else + if (out_size == CXL_VARIABLE_PAYLOAD) { + /* Adding extra 8 bytes for FWCTL, should not impact operation */ + mbox_cmd->size_out = cxl_mbox->payload_size + + sizeof(struct fwctl_rpc_cxl_out); + } else { mbox_cmd->size_out = out_size; + } if (mbox_cmd->size_out) { mbox_cmd->payload_out = kvzalloc(mbox_cmd->size_out, GFP_KERNEL); @@ -477,6 +490,73 @@ static int cxl_to_mem_cmd(struct cxl_mem_command *mem_cmd, return 0; } +static int cxl_fwctl_to_mem_cmd(struct cxl_mem_command *mem_cmd, + const struct cxl_send_command *send_cmd, + struct cxl_mailbox *cxl_mbox) +{ + struct cxl_mem_command *c = &cxl_mem_commands[send_cmd->id]; + const struct cxl_command_info *info = &c->info; + + if (send_cmd->flags & ~CXL_MEM_COMMAND_FLAG_MASK) + return -EINVAL; + + if (send_cmd->rsvd) + return -EINVAL; + + if (send_cmd->in.rsvd || send_cmd->out.rsvd) + return -EINVAL; + + /* Check the input buffer is the expected size */ + if (info->size_in != CXL_VARIABLE_PAYLOAD && + info->size_in != send_cmd->in.size) + return -ENOMEM; + + /* Check the output buffer is at least large enough */ + if (info->size_out != CXL_VARIABLE_PAYLOAD && + send_cmd->out.size < info->size_out) + return -ENOMEM; + + *mem_cmd = (struct cxl_mem_command) { + .info = { + .id = info->id, + .flags = info->flags, + .size_in = send_cmd->in.size, + .size_out = send_cmd->out.size, + }, + .opcode = c->opcode + }; + + return 0; +} + +static int verify_send_command(const struct cxl_send_command *send_cmd, + struct cxl_mailbox *cxl_mbox) +{ + if (send_cmd->id == 0 || send_cmd->id >= CXL_MEM_COMMAND_ID_MAX) + return -ENOTTY; + + /* + * The user can never specify an input payload larger than what hardware + * supports, but output can be arbitrarily large (simply write out as + * much data as the hardware provides). + */ + if (send_cmd->in.size > cxl_mbox->payload_size) + return -EINVAL; + + return 0; +} + +/* Sanitize and construct a cxl_mbox_cmd */ +static int construct_mbox_cmd(struct cxl_mbox_cmd *mbox_cmd, + struct cxl_mem_command *mem_cmd, + struct cxl_mailbox *cxl_mbox, + const struct cxl_send_command *send_cmd) +{ + return cxl_mbox_cmd_ctor(mbox_cmd, cxl_mbox, mem_cmd->opcode, + mem_cmd->info.size_in, mem_cmd->info.size_out, + send_cmd->in.payload); +} + /** * cxl_validate_cmd_from_user() - Check fields for CXL_MEM_SEND_COMMAND. * @mbox_cmd: Sanitized and populated &struct cxl_mbox_cmd. @@ -501,16 +581,9 @@ static int cxl_validate_cmd_from_user(struct cxl_mbox_cmd *mbox_cmd, struct cxl_mem_command mem_cmd; int rc; - if (send_cmd->id == 0 || send_cmd->id >= CXL_MEM_COMMAND_ID_MAX) - return -ENOTTY; - - /* - * The user can never specify an input payload larger than what hardware - * supports, but output can be arbitrarily large (simply write out as - * much data as the hardware provides). - */ - if (send_cmd->in.size > cxl_mbox->payload_size) - return -EINVAL; + rc = verify_send_command(send_cmd, cxl_mbox); + if (rc) + return rc; /* Sanitize and construct a cxl_mem_command */ if (send_cmd->id == CXL_MEM_COMMAND_ID_RAW) @@ -521,10 +594,26 @@ static int cxl_validate_cmd_from_user(struct cxl_mbox_cmd *mbox_cmd, if (rc) return rc; - /* Sanitize and construct a cxl_mbox_cmd */ - return cxl_mbox_cmd_ctor(mbox_cmd, cxl_mbox, mem_cmd.opcode, - mem_cmd.info.size_in, mem_cmd.info.size_out, - send_cmd->in.payload); + return construct_mbox_cmd(mbox_cmd, &mem_cmd, cxl_mbox, send_cmd); +} + +static int cxl_validate_cmd_from_fwctl(struct cxl_mbox_cmd *mbox_cmd, + struct cxl_mailbox *cxl_mbox, + const struct cxl_send_command *send_cmd) +{ + struct cxl_mem_command mem_cmd; + int rc; + + rc = verify_send_command(send_cmd, cxl_mbox); + if (rc) + return rc; + + /* Sanitize and construct a cxl_mem_command */ + rc = cxl_fwctl_to_mem_cmd(&mem_cmd, send_cmd, cxl_mbox); + if (rc) + return rc; + + return construct_mbox_cmd(mbox_cmd, &mem_cmd, cxl_mbox, send_cmd); } int cxl_query_cmd(struct cxl_mailbox *cxl_mbox, @@ -631,7 +720,107 @@ static int handle_mailbox_cmd_from_user(struct cxl_mailbox *cxl_mbox, return rc; } -int cxl_send_cmd(struct cxl_mailbox *cxl_mbox, struct cxl_send_command __user *s) +static int cxl_send_cmd(struct cxl_mailbox *cxl_mbox, struct cxl_send_command *send, + struct cxl_mbox_cmd *mbox_cmd) +{ + int rc; + + rc = cxl_validate_cmd_from_user(mbox_cmd, cxl_mbox, send); + if (rc) + return rc; + + rc = handle_mailbox_cmd_from_user(cxl_mbox, mbox_cmd, send->out.payload, + &send->out.size, &send->retval); + if (rc) + return rc; + + return 0; +} + +/** + * handle_mailbox_cmd_from_fwctl() - Dispatch a mailbox command for userspace. + * @mailbox: The mailbox context for the operation. + * @mbox_cmd: The validated mailbox command. + * + * Return: + * * %0 - Mailbox transaction succeeded. This implies the mailbox + * protocol completed successfully not that the operation itself + * was successful. + * * %-ENOMEM - Couldn't allocate a bounce buffer. + * * %-EINTR - Mailbox acquisition interrupted. + * * %-EXXX - Transaction level failures. + * + * Dispatches a mailbox command on behalf of a userspace request. + * The output payload is copied to userspace by fwctl. + * + * See cxl_send_cmd(). + */ +static int handle_mailbox_cmd_from_fwctl(struct cxl_mailbox *cxl_mbox, + struct cxl_mbox_cmd *mbox_cmd) +{ + struct device *dev = cxl_mbox->host; + struct fwctl_rpc_cxl_out *orig_out; + int rc; + + /* + * Save the payload_out pointer and move it to where hardware output + * can be copied to. + */ + orig_out = mbox_cmd->payload_out; + mbox_cmd->payload_out = (void *)orig_out + sizeof(*orig_out); + + dev_dbg(dev, + "Submitting %s command for user\n" + "\topcode: %x\n" + "\tsize: %zx\n", + cxl_mem_opcode_to_name(mbox_cmd->opcode), + mbox_cmd->opcode, mbox_cmd->size_in); + + rc = cxl_mbox->mbox_send(cxl_mbox, mbox_cmd); + if (rc) + return rc; + + orig_out->retval = mbox_cmd->return_code; + mbox_cmd->payload_out = (void *)orig_out; + + return 0; +} + +int cxl_fwctl_send_cmd(struct cxl_mailbox *cxl_mbox, + struct fwctl_cxl_command *fwctl_cmd, + struct cxl_mbox_cmd *mbox_cmd, size_t *out_len) +{ + struct cxl_send_command send_cmd = { + .id = fwctl_cmd->id, + .flags = fwctl_cmd->flags, + .raw.opcode = fwctl_cmd->raw.opcode, + .in.size = fwctl_cmd->in.size, + .in.payload = fwctl_cmd->in.payload, + .out.size = *out_len, + }; + int rc; + + guard(rwsem_read)(&cxl_memdev_rwsem); + rc = cxl_validate_cmd_from_fwctl(mbox_cmd, cxl_mbox, &send_cmd); + if (rc) + return rc; + + rc = handle_mailbox_cmd_from_fwctl(cxl_mbox, mbox_cmd); + if (rc) + return rc; + + rc = cxl_mbox->mbox_send(cxl_mbox, mbox_cmd); + if (rc) + return rc; + + *out_len = mbox_cmd->size_out; + + return 0; +} +EXPORT_SYMBOL_NS_GPL(cxl_fwctl_send_cmd, CXL); + +int cxl_send_cmd_from_user(struct cxl_mailbox *cxl_mbox, + struct cxl_send_command __user *s) { struct device *dev = cxl_mbox->host; struct cxl_send_command send; @@ -643,12 +832,7 @@ int cxl_send_cmd(struct cxl_mailbox *cxl_mbox, struct cxl_send_command __user *s if (copy_from_user(&send, s, sizeof(send))) return -EFAULT; - rc = cxl_validate_cmd_from_user(&mbox_cmd, cxl_mbox, &send); - if (rc) - return rc; - - rc = handle_mailbox_cmd_from_user(cxl_mbox, &mbox_cmd, send.out.payload, - &send.out.size, &send.retval); + rc = cxl_send_cmd(cxl_mbox, &send, &mbox_cmd); if (rc) return rc; diff --git a/drivers/cxl/core/memdev.c b/drivers/cxl/core/memdev.c index 0f6ec85ef9c4..f6f33f0f7337 100644 --- a/drivers/cxl/core/memdev.c +++ b/drivers/cxl/core/memdev.c @@ -11,7 +11,7 @@ #include "trace.h" #include "core.h" -static DECLARE_RWSEM(cxl_memdev_rwsem); +DECLARE_RWSEM(cxl_memdev_rwsem); #define CXL_ADEV_NAME "fwctl-cxl" @@ -671,7 +671,7 @@ static long __cxl_memdev_ioctl(struct cxl_memdev *cxlmd, unsigned int cmd, case CXL_MEM_QUERY_COMMANDS: return cxl_query_cmd(cxl_mbox, (void __user *)arg); case CXL_MEM_SEND_COMMAND: - return cxl_send_cmd(cxl_mbox, (void __user *)arg); + return cxl_send_cmd_from_user(cxl_mbox, (void __user *)arg); default: return -ENOTTY; } diff --git a/drivers/cxl/cxlmem.h b/drivers/cxl/cxlmem.h index 5e190f941e58..736111f5bc31 100644 --- a/drivers/cxl/cxlmem.h +++ b/drivers/cxl/cxlmem.h @@ -465,53 +465,6 @@ to_cxl_memdev_state(struct cxl_dev_state *cxlds) return container_of(cxlds, struct cxl_memdev_state, cxlds); } -enum cxl_opcode { - CXL_MBOX_OP_INVALID = 0x0000, - CXL_MBOX_OP_RAW = CXL_MBOX_OP_INVALID, - CXL_MBOX_OP_GET_EVENT_RECORD = 0x0100, - CXL_MBOX_OP_CLEAR_EVENT_RECORD = 0x0101, - CXL_MBOX_OP_GET_EVT_INT_POLICY = 0x0102, - CXL_MBOX_OP_SET_EVT_INT_POLICY = 0x0103, - CXL_MBOX_OP_GET_FW_INFO = 0x0200, - CXL_MBOX_OP_TRANSFER_FW = 0x0201, - CXL_MBOX_OP_ACTIVATE_FW = 0x0202, - CXL_MBOX_OP_GET_TIMESTAMP = 0x0300, - CXL_MBOX_OP_SET_TIMESTAMP = 0x0301, - CXL_MBOX_OP_GET_SUPPORTED_LOGS = 0x0400, - CXL_MBOX_OP_GET_LOG = 0x0401, - CXL_MBOX_OP_GET_LOG_CAPS = 0x0402, - CXL_MBOX_OP_CLEAR_LOG = 0x0403, - CXL_MBOX_OP_GET_SUP_LOG_SUBLIST = 0x0405, - CXL_MBOX_OP_GET_SUPPORTED_FEATURES = 0x0500, - CXL_MBOX_OP_GET_FEATURE = 0x0501, - CXL_MBOX_OP_SET_FEATURE = 0x0502, - CXL_MBOX_OP_IDENTIFY = 0x4000, - CXL_MBOX_OP_GET_PARTITION_INFO = 0x4100, - CXL_MBOX_OP_SET_PARTITION_INFO = 0x4101, - CXL_MBOX_OP_GET_LSA = 0x4102, - CXL_MBOX_OP_SET_LSA = 0x4103, - CXL_MBOX_OP_GET_HEALTH_INFO = 0x4200, - CXL_MBOX_OP_GET_ALERT_CONFIG = 0x4201, - CXL_MBOX_OP_SET_ALERT_CONFIG = 0x4202, - CXL_MBOX_OP_GET_SHUTDOWN_STATE = 0x4203, - CXL_MBOX_OP_SET_SHUTDOWN_STATE = 0x4204, - CXL_MBOX_OP_GET_POISON = 0x4300, - CXL_MBOX_OP_INJECT_POISON = 0x4301, - CXL_MBOX_OP_CLEAR_POISON = 0x4302, - CXL_MBOX_OP_GET_SCAN_MEDIA_CAPS = 0x4303, - CXL_MBOX_OP_SCAN_MEDIA = 0x4304, - CXL_MBOX_OP_GET_SCAN_MEDIA = 0x4305, - CXL_MBOX_OP_SANITIZE = 0x4400, - CXL_MBOX_OP_SECURE_ERASE = 0x4401, - CXL_MBOX_OP_GET_SECURITY_STATE = 0x4500, - CXL_MBOX_OP_SET_PASSPHRASE = 0x4501, - CXL_MBOX_OP_DISABLE_PASSPHRASE = 0x4502, - CXL_MBOX_OP_UNLOCK = 0x4503, - CXL_MBOX_OP_FREEZE_SECURITY = 0x4504, - CXL_MBOX_OP_PASSPHRASE_SECURE_ERASE = 0x4505, - CXL_MBOX_OP_MAX = 0x10000 -}; - #define DEFINE_CXL_CEL_UUID \ UUID_INIT(0xda9c0b5, 0xbf41, 0x4b78, 0x8f, 0x79, 0x96, 0xb1, 0x62, \ 0x3b, 0x3f, 0x17) @@ -709,30 +662,6 @@ struct cxl_mbox_clear_poison { u8 write_data[CXL_POISON_LEN_MULT]; } __packed; -/** - * struct cxl_mem_command - Driver representation of a memory device command - * @info: Command information as it exists for the UAPI - * @opcode: The actual bits used for the mailbox protocol - * @flags: Set of flags effecting driver behavior. - * - * * %CXL_CMD_FLAG_FORCE_ENABLE: In cases of error, commands with this flag - * will be enabled by the driver regardless of what hardware may have - * advertised. - * - * The cxl_mem_command is the driver's internal representation of commands that - * are supported by the driver. Some of these commands may not be supported by - * the hardware. The driver will use @info to validate the fields passed in by - * the user then submit the @opcode to the hardware. - * - * See struct cxl_command_info. - */ -struct cxl_mem_command { - struct cxl_command_info info; - enum cxl_opcode opcode; - u32 flags; -#define CXL_CMD_FLAG_FORCE_ENABLE BIT(0) -}; - #define CXL_PMEM_SEC_STATE_USER_PASS_SET 0x01 #define CXL_PMEM_SEC_STATE_MASTER_PASS_SET 0x02 #define CXL_PMEM_SEC_STATE_LOCKED 0x04 @@ -775,17 +704,7 @@ struct cxl_mbox_get_sup_feats_in { __le16 reserved; } __packed; -struct cxl_feat_entry { - uuid_t uuid; - __le16 id; - __le16 get_feat_size; - __le16 set_feat_size; - __le32 flags; - u8 get_feat_ver; - u8 set_feat_ver; - __le16 effects; - u8 reserved[18]; -} __packed; +struct cxl_feat_entry; struct cxl_mbox_get_sup_feats_out { __le16 num_entries; diff --git a/drivers/fwctl/cxl/cxl.c b/drivers/fwctl/cxl/cxl.c index 22f62034c021..01f0771148e1 100644 --- a/drivers/fwctl/cxl/cxl.c +++ b/drivers/fwctl/cxl/cxl.c @@ -51,10 +51,133 @@ static void *cxlctl_info(struct fwctl_uctx *uctx, size_t *length) return info; } +static bool cxlctl_validate_set_features(struct cxl_mailbox *cxl_mbox, + const struct fwctl_cxl_command *send_cmd, + enum fwctl_rpc_scope scope) +{ + struct cxl_feat_entry *feat; + bool found = false; + uuid_t uuid; + u16 mask; + + if (send_cmd->in.size < sizeof(struct set_feature_input)) + return false; + + if (copy_from_user(&uuid, u64_to_user_ptr(send_cmd->in.payload), + sizeof(uuid))) + return false; + + for (int i = 0; i < cxl_mbox->num_features; i++) { + feat = &cxl_mbox->entries[i]; + if (uuid_equal(&uuid, &feat->uuid)) { + found = true; + break; + } + } + + if (!found) + return false; + + /* Currently no user background command support */ + if (feat->effects & CXL_CMD_BACKGROUND) + return false; + + mask = CXL_CMD_CONFIG_CHANGE_IMMEDIATE | + CXL_CMD_DATA_CHANGE_IMMEDIATE | + CXL_CMD_POLICY_CHANGE_IMMEDIATE | + CXL_CMD_LOG_CHANGE_IMMEDIATE; + if (feat->effects & mask && scope >= FWCTL_RPC_DEBUG_WRITE) + return true; + + /* These effects supported for all scope */ + if ((feat->effects & CXL_CMD_CONFIG_CHANGE_COLD_RESET || + feat->effects & CXL_CMD_CONFIG_CHANGE_CONV_RESET) && + scope >= FWCTL_RPC_DEBUG_READ_ONLY) + return true; + + return false; +} + +static bool cxlctl_validate_hw_cmds(struct cxl_mailbox *cxl_mbox, + const struct fwctl_cxl_command *send_cmd, + enum fwctl_rpc_scope scope) +{ + struct cxl_mem_command *cmd; + + /* + * Only supporting feature commands. + */ + if (!cxl_mbox->num_features) + return false; + + cmd = cxl_get_mem_command(send_cmd->id); + if (!cmd) + return false; + + if (test_bit(cmd->info.id, cxl_mbox->enabled_cmds)) + return false; + + if (test_bit(cmd->info.id, cxl_mbox->exclusive_cmds)) + return false; + + switch (cmd->opcode) { + case CXL_MBOX_OP_GET_SUPPORTED_FEATURES: + case CXL_MBOX_OP_GET_FEATURE: + if (scope >= FWCTL_RPC_DEBUG_READ_ONLY) + return true; + break; + case CXL_MBOX_OP_SET_FEATURE: + return cxlctl_validate_set_features(cxl_mbox, send_cmd, scope); + default: + return false; + }; + + return false; +} + +static bool cxlctl_validate_rpc(struct fwctl_uctx *uctx, + struct fwctl_rpc_cxl *rpc_in, + enum fwctl_rpc_scope scope) +{ + struct cxlctl_dev *cxlctl = + container_of(uctx->fwctl, struct cxlctl_dev, fwctl); + + if (rpc_in->rpc_cmd != FWCTL_CXL_SEND_COMMAND) + return false; + + return cxlctl_validate_hw_cmds(cxlctl->mbox, &rpc_in->send_cmd, scope); +} + +static void *send_cxl_command(struct cxl_mailbox *cxl_mbox, + struct fwctl_cxl_command *send_cmd, + size_t *out_len) +{ + struct cxl_mbox_cmd mbox_cmd; + int rc; + + rc = cxl_fwctl_send_cmd(cxl_mbox, send_cmd, &mbox_cmd, out_len); + if (rc) + return ERR_PTR(rc); + + *out_len = mbox_cmd.size_out; + + return mbox_cmd.payload_out; +} + static void *cxlctl_fw_rpc(struct fwctl_uctx *uctx, enum fwctl_rpc_scope scope, - void *rpc_in, size_t in_len, size_t *out_len) + void *in, size_t in_len, size_t *out_len) { - /* Place holder */ + struct cxlctl_dev *cxlctl = + container_of(uctx->fwctl, struct cxlctl_dev, fwctl); + struct cxl_mailbox *cxl_mbox = cxlctl->mbox; + struct fwctl_rpc_cxl *rpc_in = in; + + if (!cxlctl_validate_rpc(uctx, rpc_in, scope)) + return ERR_PTR(-EPERM); + + if (rpc_in->rpc_cmd == FWCTL_CXL_SEND_COMMAND) + return send_cxl_command(cxl_mbox, &rpc_in->send_cmd, out_len); + return ERR_PTR(-EOPNOTSUPP); } diff --git a/include/linux/cxl/mailbox.h b/include/linux/cxl/mailbox.h index 570864239b8f..b3c74f3da9a5 100644 --- a/include/linux/cxl/mailbox.h +++ b/include/linux/cxl/mailbox.h @@ -4,6 +4,7 @@ #define __CXL_MBOX_H__ #include +#include #include /** @@ -68,4 +69,104 @@ struct cxl_mailbox { struct cxl_feat_entry *entries; }; +enum cxl_opcode { + CXL_MBOX_OP_INVALID = 0x0000, + CXL_MBOX_OP_RAW = CXL_MBOX_OP_INVALID, + CXL_MBOX_OP_GET_EVENT_RECORD = 0x0100, + CXL_MBOX_OP_CLEAR_EVENT_RECORD = 0x0101, + CXL_MBOX_OP_GET_EVT_INT_POLICY = 0x0102, + CXL_MBOX_OP_SET_EVT_INT_POLICY = 0x0103, + CXL_MBOX_OP_GET_FW_INFO = 0x0200, + CXL_MBOX_OP_TRANSFER_FW = 0x0201, + CXL_MBOX_OP_ACTIVATE_FW = 0x0202, + CXL_MBOX_OP_GET_TIMESTAMP = 0x0300, + CXL_MBOX_OP_SET_TIMESTAMP = 0x0301, + CXL_MBOX_OP_GET_SUPPORTED_LOGS = 0x0400, + CXL_MBOX_OP_GET_LOG = 0x0401, + CXL_MBOX_OP_GET_LOG_CAPS = 0x0402, + CXL_MBOX_OP_CLEAR_LOG = 0x0403, + CXL_MBOX_OP_GET_SUP_LOG_SUBLIST = 0x0405, + CXL_MBOX_OP_GET_SUPPORTED_FEATURES = 0x0500, + CXL_MBOX_OP_GET_FEATURE = 0x0501, + CXL_MBOX_OP_SET_FEATURE = 0x0502, + CXL_MBOX_OP_IDENTIFY = 0x4000, + CXL_MBOX_OP_GET_PARTITION_INFO = 0x4100, + CXL_MBOX_OP_SET_PARTITION_INFO = 0x4101, + CXL_MBOX_OP_GET_LSA = 0x4102, + CXL_MBOX_OP_SET_LSA = 0x4103, + CXL_MBOX_OP_GET_HEALTH_INFO = 0x4200, + CXL_MBOX_OP_GET_ALERT_CONFIG = 0x4201, + CXL_MBOX_OP_SET_ALERT_CONFIG = 0x4202, + CXL_MBOX_OP_GET_SHUTDOWN_STATE = 0x4203, + CXL_MBOX_OP_SET_SHUTDOWN_STATE = 0x4204, + CXL_MBOX_OP_GET_POISON = 0x4300, + CXL_MBOX_OP_INJECT_POISON = 0x4301, + CXL_MBOX_OP_CLEAR_POISON = 0x4302, + CXL_MBOX_OP_GET_SCAN_MEDIA_CAPS = 0x4303, + CXL_MBOX_OP_SCAN_MEDIA = 0x4304, + CXL_MBOX_OP_GET_SCAN_MEDIA = 0x4305, + CXL_MBOX_OP_SANITIZE = 0x4400, + CXL_MBOX_OP_SECURE_ERASE = 0x4401, + CXL_MBOX_OP_GET_SECURITY_STATE = 0x4500, + CXL_MBOX_OP_SET_PASSPHRASE = 0x4501, + CXL_MBOX_OP_DISABLE_PASSPHRASE = 0x4502, + CXL_MBOX_OP_UNLOCK = 0x4503, + CXL_MBOX_OP_FREEZE_SECURITY = 0x4504, + CXL_MBOX_OP_PASSPHRASE_SECURE_ERASE = 0x4505, + CXL_MBOX_OP_MAX = 0x10000 +}; + +#define CXL_CMD_CONFIG_CHANGE_COLD_RESET BIT(0) +#define CXL_CMD_CONFIG_CHANGE_IMMEDIATE BIT(1) +#define CXL_CMD_DATA_CHANGE_IMMEDIATE BIT(2) +#define CXL_CMD_POLICY_CHANGE_IMMEDIATE BIT(3) +#define CXL_CMD_LOG_CHANGE_IMMEDIATE BIT(4) +#define CXL_CMD_SECURITY_STATE_CHANGE BIT(5) +#define CXL_CMD_BACKGROUND BIT(6) +#define CXL_CMD_BGCMD_ABORT_SUPPORTED BIT(7) +#define CXL_CMD_CONFIG_CHANGE_CONV_RESET (BIT(9) | BIT(10)) +#define CXL_CMD_CONFIG_CHANGE_CXL_RESET (BIT(9) | BIT(11)) + +struct cxl_feat_entry { + uuid_t uuid; + __le16 id; + __le16 get_feat_size; + __le16 set_feat_size; + __le32 flags; + u8 get_feat_ver; + u8 set_feat_ver; + __le16 effects; + u8 reserved[18]; +} __packed; + +/** + * struct cxl_mem_command - Driver representation of a memory device command + * @info: Command information as it exists for the UAPI + * @opcode: The actual bits used for the mailbox protocol + * @flags: Set of flags effecting driver behavior. + * + * * %CXL_CMD_FLAG_FORCE_ENABLE: In cases of error, commands with this flag + * will be enabled by the driver regardless of what hardware may have + * advertised. + * + * The cxl_mem_command is the driver's internal representation of commands that + * are supported by the driver. Some of these commands may not be supported by + * the hardware. The driver will use @info to validate the fields passed in by + * the user then submit the @opcode to the hardware. + * + * See struct cxl_command_info. + */ +struct cxl_mem_command { + struct cxl_command_info info; + enum cxl_opcode opcode; + u32 flags; +#define CXL_CMD_FLAG_FORCE_ENABLE BIT(0) +}; + +struct cxl_mem_command *cxl_get_mem_command(u32 id); +int cxl_fwctl_send_cmd(struct cxl_mailbox *cxl_mbox, + struct fwctl_cxl_command *fwctl_cmd, + struct cxl_mbox_cmd *mbox_cmd, + size_t *out_len); + #endif diff --git a/include/uapi/fwctl/cxl.h b/include/uapi/fwctl/cxl.h index d3a735f1fe4e..de8949a28473 100644 --- a/include/uapi/fwctl/cxl.h +++ b/include/uapi/fwctl/cxl.h @@ -22,4 +22,68 @@ struct fwctl_info_cxl { __u32 uctx_caps; }; +/* + * CXL spec r3.1 Table 8-101 Set Feature Input Payload + */ +struct set_feature_input { + uuid_t uuid; + __u32 flags; + __u16 offset; + __u8 version; + __u8 reserved[9]; + __u8 data[]; +} __packed; + +/** + * struct cxl_send_command - Send a command to a memory device. + * @id: The command to send to the memory device. This must be one of the + * commands returned by the query command. + * @flags: Flags for the command (input). + * @raw: Special fields for raw commands + * @raw.opcode: Opcode passed to hardware when using the RAW command. + * @raw.rsvd: Must be zero. + * @rsvd: Must be zero. + * @retval: Return value from the memory device (output). + * @in: Parameters associated with input payload. + * @in.size: Size of the payload to provide to the device (input). + * @in.rsvd: Must be zero. + * @in.payload: Pointer to memory for payload input, payload is little endian. + * + * Output payload is defined with 'struct fwctl_rpc' and is the hardware output + */ +struct fwctl_cxl_command { + __u32 id; + __u32 flags; + union { + struct { + __u16 opcode; + __u16 rsvd; + } raw; + __u32 rsvd; + }; + + struct { + __u32 size; + __u32 rsvd; + __u64 payload; + } in; +}; + +/** + * struct fwctl_rpc_cxl - ioctl(FWCTL_RPC) input + */ +struct fwctl_rpc_cxl { + __u32 rpc_cmd; + __u32 payload_size; + __u32 version; + __u32 rsvd; + struct fwctl_cxl_command send_cmd; +}; + +struct fwctl_rpc_cxl_out { + __u32 retval; + __u32 rsvd; + __u8 payload[]; +}; + #endif From patchwork Thu Jul 18 21:32:29 2024 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Dave Jiang X-Patchwork-Id: 13736748 Received: from smtp.kernel.org (aws-us-west-2-korg-mail-1.web.codeaurora.org [10.30.226.201]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by smtp.subspace.kernel.org (Postfix) with ESMTPS id 05ACC7F7C7 for ; Thu, 18 Jul 2024 21:35:06 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=10.30.226.201 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1721338507; cv=none; b=q0q6QymwyggRThNRarq9T2Sox9GBXPmyDp7T8ILrURPAJWxboC/aGeLjICYbWI22B0W8i6E/Sb9wk/sD3fIcH6QBgJt2UZSkH8Aq5uvGSbJ879iRIGAgq7MdfCLiuAl/XdTMJpNAIoVNS0R+WrkWZZ4k1hqrO/5uM5rwkCY6UqI= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1721338507; c=relaxed/simple; bh=ELhO4Ri5eliG5r3Aan/MfIUGo86krJdj2SlayVcRIPs=; h=From:To:Cc:Subject:Date:Message-ID:In-Reply-To:References: MIME-Version; b=RsgZ/4Yv53IB3cWaQQwx7zL+DwS0YcmPjtI4yRs4g4gt2XE0D1A2U+taW82Q/mjaFacMchyA/cOXdaAFKMqdUVr8xjEY2JqJnO9xZ6DvXDtLSVOuw+RhIX8fT+fPg9p5WgEG+BLjA4Fs37KjdthdPswuNDLQpXesuwtO2jtYah8= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; arc=none smtp.client-ip=10.30.226.201 Received: by smtp.kernel.org (Postfix) with ESMTPSA id 74694C116B1; Thu, 18 Jul 2024 21:35:06 +0000 (UTC) From: Dave Jiang To: linux-cxl@vger.kernel.org Cc: dan.j.williams@intel.com, ira.weiny@intel.com, vishal.l.verma@intel.com, alison.schofield@intel.com, Jonathan.Cameron@huawei.com, dave@stgolabs.net, jgg@nvidia.com, shiju.jose@huawei.com Subject: [RFC PATCH 11/13] fwctl/cxl: Add query commands software command for ->fw_rpc() Date: Thu, 18 Jul 2024 14:32:29 -0700 Message-ID: <20240718213446.1750135-12-dave.jiang@intel.com> X-Mailer: git-send-email 2.45.2 In-Reply-To: <20240718213446.1750135-1-dave.jiang@intel.com> References: <20240718213446.1750135-1-dave.jiang@intel.com> Precedence: bulk X-Mailing-List: linux-cxl@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 Add a software command through the ->fw_rpc() in order for the user to retrieve information about the commands that are supported. In this instance only 3 commands are supported: Get Supported Features, Get Feature, and Set Feature. The expected flow of operation is to send the call first with 0 set to the n_commands parameter to indicate query of total commands available. And then a second call provides the number of commands to retrieve with the appropriate amount of memory allocated to store information about the commands. Signed-off-by: Dave Jiang --- drivers/cxl/core/mbox.c | 80 +++++++++++++++++++++++++++++++++++++ drivers/fwctl/cxl/cxl.c | 42 ++++++++++++++++--- include/linux/cxl/mailbox.h | 3 ++ include/uapi/fwctl/cxl.h | 5 ++- 4 files changed, 124 insertions(+), 6 deletions(-) diff --git a/drivers/cxl/core/mbox.c b/drivers/cxl/core/mbox.c index d77817e347d8..91be8cfbc2bb 100644 --- a/drivers/cxl/core/mbox.c +++ b/drivers/cxl/core/mbox.c @@ -655,6 +655,86 @@ int cxl_query_cmd(struct cxl_mailbox *cxl_mbox, return 0; } +static bool fwctl_supported_commands(u16 opcode) +{ + switch (opcode) { + case CXL_MBOX_OP_GET_SUPPORTED_FEATURES: + case CXL_MBOX_OP_GET_FEATURE: + case CXL_MBOX_OP_SET_FEATURE: + return true; + default: + return false; + } +} + +static int get_fwctl_supported_commands(void) +{ + struct cxl_mem_command *cmd; + int cmds = 0; + + cxl_for_each_cmd(cmd) { + if (fwctl_supported_commands(cmd->opcode)) + cmds++; + } + + return cmds; +} + +void *cxl_query_cmd_from_fwctl(struct cxl_mailbox *cxl_mbox, + struct cxl_mem_query_commands *q, + size_t *out_len) +{ + u32 n_commands = q->n_commands; + struct cxl_mem_command *cmd; + size_t output_size; + int commands; + int j = 0; + + commands = get_fwctl_supported_commands(); + if (n_commands > commands) + return ERR_PTR(-EINVAL); + + output_size = sizeof(struct cxl_mem_query_commands) + + n_commands * sizeof(struct cxl_command_info); + + struct cxl_mem_query_commands *qout __free(kvfree) = + kvzalloc(output_size, GFP_KERNEL); + + if (!qout) + return ERR_PTR(-ENOMEM); + + *out_len = output_size; + if (n_commands == 0) { + qout->n_commands = commands; + return no_free_ptr(qout); + } + + qout->n_commands = n_commands; + + /* + * otherwise, return min(n_commands, total commands) cxl_command_info + * structures. + */ + cxl_for_each_cmd(cmd) { + struct cxl_command_info info = cmd->info; + + if (fwctl_supported_commands(cmd->opcode)) { + if (test_bit(info.id, cxl_mbox->enabled_cmds)) + info.flags |= CXL_MEM_COMMAND_FLAG_ENABLED; + if (test_bit(info.id, cxl_mbox->exclusive_cmds)) + info.flags |= CXL_MEM_COMMAND_FLAG_EXCLUSIVE; + + memcpy(&qout->commands[j++], &info, sizeof(info)); + } + + if (j == n_commands) + break; + } + + return no_free_ptr(qout); +} +EXPORT_SYMBOL_NS_GPL(cxl_query_cmd_from_fwctl, CXL); + /** * handle_mailbox_cmd_from_user() - Dispatch a mailbox command for userspace. * @mailbox: The mailbox context for the operation. diff --git a/drivers/fwctl/cxl/cxl.c b/drivers/fwctl/cxl/cxl.c index 01f0771148e1..8836a806763f 100644 --- a/drivers/fwctl/cxl/cxl.c +++ b/drivers/fwctl/cxl/cxl.c @@ -135,6 +135,24 @@ static bool cxlctl_validate_hw_cmds(struct cxl_mailbox *cxl_mbox, return false; } +static bool cxlctl_validate_query_commands(struct fwctl_rpc_cxl *rpc_in) +{ + int cmds; + + if (rpc_in->payload_size < sizeof(rpc_in->query)) + return false; + + cmds = rpc_in->query.n_commands; + if (cmds) { + int cmds_size = rpc_in->payload_size - sizeof(rpc_in->query); + + if (cmds != cmds_size / sizeof(struct cxl_command_info)) + return false; + } + + return true; +} + static bool cxlctl_validate_rpc(struct fwctl_uctx *uctx, struct fwctl_rpc_cxl *rpc_in, enum fwctl_rpc_scope scope) @@ -142,10 +160,17 @@ static bool cxlctl_validate_rpc(struct fwctl_uctx *uctx, struct cxlctl_dev *cxlctl = container_of(uctx->fwctl, struct cxlctl_dev, fwctl); - if (rpc_in->rpc_cmd != FWCTL_CXL_SEND_COMMAND) + switch (rpc_in->rpc_cmd) { + case FWCTL_CXL_QUERY_COMMANDS: + return cxlctl_validate_query_commands(rpc_in); + + case FWCTL_CXL_SEND_COMMAND: + return cxlctl_validate_hw_cmds(cxlctl->mbox, + &rpc_in->send_cmd, scope); + + default: return false; - - return cxlctl_validate_hw_cmds(cxlctl->mbox, &rpc_in->send_cmd, scope); + } } static void *send_cxl_command(struct cxl_mailbox *cxl_mbox, @@ -175,10 +200,17 @@ static void *cxlctl_fw_rpc(struct fwctl_uctx *uctx, enum fwctl_rpc_scope scope, if (!cxlctl_validate_rpc(uctx, rpc_in, scope)) return ERR_PTR(-EPERM); - if (rpc_in->rpc_cmd == FWCTL_CXL_SEND_COMMAND) + switch (rpc_in->rpc_cmd) { + case FWCTL_CXL_QUERY_COMMANDS: + return cxl_query_cmd_from_fwctl(cxl_mbox, &rpc_in->query, + out_len); + + case FWCTL_CXL_SEND_COMMAND: return send_cxl_command(cxl_mbox, &rpc_in->send_cmd, out_len); - return ERR_PTR(-EOPNOTSUPP); + default: + return ERR_PTR(-EOPNOTSUPP); + } } static const struct fwctl_ops cxlctl_ops = { diff --git a/include/linux/cxl/mailbox.h b/include/linux/cxl/mailbox.h index b3c74f3da9a5..13b5bb6e5bc3 100644 --- a/include/linux/cxl/mailbox.h +++ b/include/linux/cxl/mailbox.h @@ -168,5 +168,8 @@ int cxl_fwctl_send_cmd(struct cxl_mailbox *cxl_mbox, struct fwctl_cxl_command *fwctl_cmd, struct cxl_mbox_cmd *mbox_cmd, size_t *out_len); +void *cxl_query_cmd_from_fwctl(struct cxl_mailbox *cxl_mbox, + struct cxl_mem_query_commands *q, + size_t *out_len); #endif diff --git a/include/uapi/fwctl/cxl.h b/include/uapi/fwctl/cxl.h index de8949a28473..a439f497b889 100644 --- a/include/uapi/fwctl/cxl.h +++ b/include/uapi/fwctl/cxl.h @@ -77,7 +77,10 @@ struct fwctl_rpc_cxl { __u32 payload_size; __u32 version; __u32 rsvd; - struct fwctl_cxl_command send_cmd; + union { + struct cxl_mem_query_commands query; + struct fwctl_cxl_command send_cmd; + }; }; struct fwctl_rpc_cxl_out { From patchwork Thu Jul 18 21:32:30 2024 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Dave Jiang X-Patchwork-Id: 13736749 Received: from smtp.kernel.org (aws-us-west-2-korg-mail-1.web.codeaurora.org [10.30.226.201]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by smtp.subspace.kernel.org (Postfix) with ESMTPS id AC641143C6F for ; Thu, 18 Jul 2024 21:35:08 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=10.30.226.201 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1721338508; cv=none; b=D6drV862Zz0vVn8S3wVvj/CnbZP5O+4HnzsmSwipO8imcOPIg8gxEZHHoL85UOmdJT5kMR6vo2rz+Plap4av15NW8oXsJHQAcw5lyjJy2nlP57oWW9jDhnEyeebjIoiSnp2+io/j82jsDC09ifFMrsqoJdjVZFBlMc4RjjypbMA= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1721338508; c=relaxed/simple; bh=1PbyGhZhue74eMwDpmlWlI5dznv/Vu/2ks5f3ykVvOw=; h=From:To:Cc:Subject:Date:Message-ID:In-Reply-To:References: MIME-Version; b=dr7Ss4crngp7K89XYNMMew4wMYgQE8p8KVwfDvzNja9jd6C2VeXzjAjBCq7OZSqFXD9dRCs8lfMsvM22O95n5cO57LCxtGNho7EuHI0qFCvKJHvYabZ3XX+8o9rL1P/8p627kEfHlKjYOR/URdQl1f/R1Z+qjBNHk3XPdZJPdpc= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; arc=none smtp.client-ip=10.30.226.201 Received: by smtp.kernel.org (Postfix) with ESMTPSA id 10CF9C4AF0E; Thu, 18 Jul 2024 21:35:07 +0000 (UTC) From: Dave Jiang To: linux-cxl@vger.kernel.org Cc: dan.j.williams@intel.com, ira.weiny@intel.com, vishal.l.verma@intel.com, alison.schofield@intel.com, Jonathan.Cameron@huawei.com, dave@stgolabs.net, jgg@nvidia.com, shiju.jose@huawei.com Subject: [RFC PATCH 12/13] cxl/test: Add Get Feature support to cxl_test Date: Thu, 18 Jul 2024 14:32:30 -0700 Message-ID: <20240718213446.1750135-13-dave.jiang@intel.com> X-Mailer: git-send-email 2.45.2 In-Reply-To: <20240718213446.1750135-1-dave.jiang@intel.com> References: <20240718213446.1750135-1-dave.jiang@intel.com> Precedence: bulk X-Mailing-List: linux-cxl@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 Add emulation of Get Feature command to cxl_test. The feature for device patrol scrub is returned by the emulation code. This is the only feature currently supported by cxl_test. It returns the information for the device patrol scrub feature. Signed-off-by: Dave Jiang --- tools/testing/cxl/test/mem.c | 107 +++++++++++++++++++++++++++++++++++ 1 file changed, 107 insertions(+) diff --git a/tools/testing/cxl/test/mem.c b/tools/testing/cxl/test/mem.c index c2e04dbc8af6..c779640cb610 100644 --- a/tools/testing/cxl/test/mem.c +++ b/tools/testing/cxl/test/mem.c @@ -48,6 +48,10 @@ static struct cxl_cel_entry mock_cel[] = { .opcode = cpu_to_le16(CXL_MBOX_OP_GET_SUPPORTED_FEATURES), .effect = CXL_CMD_EFFECT_NONE, }, + { + .opcode = cpu_to_le16(CXL_MBOX_OP_GET_FEATURE), + .effect = CXL_CMD_EFFECT_NONE, + }, { .opcode = cpu_to_le16(CXL_MBOX_OP_IDENTIFY), .effect = CXL_CMD_EFFECT_NONE, @@ -149,6 +153,16 @@ struct mock_event_store { u32 ev_status; }; +struct scrub_patrol_read_feat { + u8 cap; +#define SCRUB_HOURS_CYCLE_DEFAULT 6 +#define SCRUB_HOURS_CYCLE_MASK GENMASK(7, 0) +#define SCRUB_SMALLEST_HOURS_DEFAULT 2 +#define SCRUB_SMALLEST_HOURS_MASK GENMASK(15, 8) + __le16 cycle_support; + u8 flags; +} __packed; + struct cxl_mockmem_data { void *lsa; void *fw; @@ -165,6 +179,7 @@ struct cxl_mockmem_data { u8 event_buf[SZ_4K]; u64 timestamp; unsigned long sanitize_timeout; + struct scrub_patrol_read_feat patrol_feat; }; static struct mock_event_log *event_find_log(struct device *dev, int log_type) @@ -1354,6 +1369,82 @@ static void fill_feature_device_patrol_scrub_control(struct cxl_feat_entry *feat feat->effects = cpu_to_le16(0x202); } +struct get_feat_input { + uuid_t uuid; + __le16 offset; + __le16 count; + u8 selection; +} __packed; + +enum scrub_patrol_selection { + SCRUB_PATROL_CURRENT_VALUE = 0, + SCRUB_PATROL_DEFAULT_VALUE = 1, + SCRUB_PATROL_SAVED_VALUE = 2, +}; + +static int mock_get_patrol_scrub(struct cxl_mockmem_data *mdata, + struct cxl_mbox_cmd *cmd) +{ + struct scrub_patrol_read_feat *output = cmd->payload_out; + struct get_feat_input *input = cmd->payload_in; + struct scrub_patrol_read_feat feat = { 0 }; + u16 offset = le16_to_cpu(input->offset); + u16 count = le16_to_cpu(input->count); + u16 support; + u8 *ptr; + + if (offset > sizeof(*output)) { + cmd->return_code = CXL_MBOX_CMD_RC_INPUT; + return -EINVAL; + } + + if (offset + count > sizeof(*output)) { + cmd->return_code = CXL_MBOX_CMD_RC_INPUT; + return -EINVAL; + } + + /* + * CXL Spec r3.1 Table 8-206 + * Saved selection is not supported + */ + switch (input->selection) { + case SCRUB_PATROL_SAVED_VALUE: + cmd->return_code = CXL_MBOX_CMD_RC_INPUT; + return -EOPNOTSUPP; + case SCRUB_PATROL_DEFAULT_VALUE: + support = FIELD_PREP(SCRUB_HOURS_CYCLE_MASK, + SCRUB_HOURS_CYCLE_DEFAULT) | + FIELD_PREP(SCRUB_SMALLEST_HOURS_MASK, + SCRUB_SMALLEST_HOURS_DEFAULT); + feat.cycle_support = cpu_to_le16(support); + ptr = (u8 *)&feat + offset; + break; + case SCRUB_PATROL_CURRENT_VALUE: + ptr = (u8 *)&mdata->patrol_feat + offset; + break; + default: + cmd->return_code = CXL_MBOX_CMD_RC_INPUT; + return -EINVAL; + } + + memcpy((u8 *)output + offset, ptr, count); + + return 0; +} + +static int mock_get_feature(struct cxl_mockmem_data *mdata, + struct cxl_mbox_cmd *cmd) +{ + struct get_feat_input *input = cmd->payload_in; + + if (uuid_equal(&input->uuid, &DEV_PATROL_SCRUB_FEAT_UUID)) + return mock_get_patrol_scrub(mdata, cmd); + + cmd->return_code = CXL_MBOX_CMD_RC_UNSUPPORTED; + + return -EOPNOTSUPP; +} + static int mock_get_supported_features(struct cxl_mockmem_data *mdata, struct cxl_mbox_cmd *cmd) { @@ -1486,6 +1577,9 @@ static int cxl_mock_mbox_send(struct cxl_mailbox *cxl_mbox, case CXL_MBOX_OP_GET_SUPPORTED_FEATURES: rc = mock_get_supported_features(mdata, cmd); break; + case CXL_MBOX_OP_GET_FEATURE: + rc = mock_get_feature(mdata, cmd); + break; default: break; } @@ -1522,6 +1616,18 @@ static ssize_t event_trigger_store(struct device *dev, } static DEVICE_ATTR_WO(event_trigger); +static void cxl_mock_mem_set_default_feat(struct cxl_mockmem_data *mdata) +{ + u16 support; + + support = FIELD_PREP(SCRUB_HOURS_CYCLE_MASK, + SCRUB_HOURS_CYCLE_DEFAULT) | + FIELD_PREP(SCRUB_SMALLEST_HOURS_MASK, + SCRUB_SMALLEST_HOURS_DEFAULT); + + mdata->patrol_feat.cycle_support = cpu_to_le16(support); +} + static int cxl_mock_mem_probe(struct platform_device *pdev) { struct device *dev = &pdev->dev; @@ -1609,6 +1715,7 @@ static int cxl_mock_mem_probe(struct platform_device *pdev) return rc; cxl_mem_get_event_records(mds, CXLDEV_EVENT_STATUS_ALL); + cxl_mock_mem_set_default_feat(mdata); return 0; } From patchwork Thu Jul 18 21:32:31 2024 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Dave Jiang X-Patchwork-Id: 13736750 Received: from smtp.kernel.org (aws-us-west-2-korg-mail-1.web.codeaurora.org [10.30.226.201]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by smtp.subspace.kernel.org (Postfix) with ESMTPS id 48E96145B26 for ; Thu, 18 Jul 2024 21:35:10 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=10.30.226.201 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1721338510; cv=none; b=J9bdOlNZ6HudJiKIl5Un/imcQcTJAvZ+ToVFhG31HCqB9L5noGajj5t75IX9rLHJ3KtHqU1Xfx5lqYuUnmKbPXkMm27MQifbWvYl8tUqYUty2/+XQWruauvQKli2Azdl4lHkZ2DWRtuuAB/U6VoDguKtlitvO+JMoG8zOjxSRKI= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1721338510; c=relaxed/simple; bh=vcPQBzcVpSJiEq7v3sqykVrw7W2mqBYzGNbbDIDAzk0=; h=From:To:Cc:Subject:Date:Message-ID:In-Reply-To:References: MIME-Version; b=Iy03jQ6wHcBGLQSpIz+0wEiFNGLQobKWAKZX7KDv33ThydzWt6rzWVRRELl5SleE86xmSLh3VizSKW+MA/yfe5WFEm10PTR316kQkvKwuoQevE4UhzBIj7QKim9yeRBKqeYc/Ua5miVpvu4xZR0ombA3i3YmcAUmMQp+TcletEM= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; arc=none smtp.client-ip=10.30.226.201 Received: by smtp.kernel.org (Postfix) with ESMTPSA id BF831C4AF0C; Thu, 18 Jul 2024 21:35:09 +0000 (UTC) From: Dave Jiang To: linux-cxl@vger.kernel.org Cc: dan.j.williams@intel.com, ira.weiny@intel.com, vishal.l.verma@intel.com, alison.schofield@intel.com, Jonathan.Cameron@huawei.com, dave@stgolabs.net, jgg@nvidia.com, shiju.jose@huawei.com Subject: [RFC PATCH 13/13] cxl/test: Add Set Feature support to cxl_test Date: Thu, 18 Jul 2024 14:32:31 -0700 Message-ID: <20240718213446.1750135-14-dave.jiang@intel.com> X-Mailer: git-send-email 2.45.2 In-Reply-To: <20240718213446.1750135-1-dave.jiang@intel.com> References: <20240718213446.1750135-1-dave.jiang@intel.com> Precedence: bulk X-Mailing-List: linux-cxl@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 Add emulation to support Set Feature mailbox command to cxl_test. The only feature supported is the device patrol scrub feature. The set feature allows activation of patrol scrub for the cxl_test emulated device. The command does not support partial data transfer even though the spec allows it. This restriction is to reduce complexity of the emulation given the patrol scrub feature is very minimal. Signed-off-by: Dave Jiang --- tools/testing/cxl/test/mem.c | 89 ++++++++++++++++++++++++++++++++++++ 1 file changed, 89 insertions(+) diff --git a/tools/testing/cxl/test/mem.c b/tools/testing/cxl/test/mem.c index c779640cb610..c2018d894719 100644 --- a/tools/testing/cxl/test/mem.c +++ b/tools/testing/cxl/test/mem.c @@ -52,6 +52,10 @@ static struct cxl_cel_entry mock_cel[] = { .opcode = cpu_to_le16(CXL_MBOX_OP_GET_FEATURE), .effect = CXL_CMD_EFFECT_NONE, }, + { + .opcode = cpu_to_le16(CXL_MBOX_OP_SET_FEATURE), + .effect = cpu_to_le16(EFFECT(CONF_CHANGE_IMMEDIATE)), + }, { .opcode = cpu_to_le16(CXL_MBOX_OP_IDENTIFY), .effect = CXL_CMD_EFFECT_NONE, @@ -1445,6 +1449,88 @@ static int mock_get_feature(struct cxl_mockmem_data *mdata, return -EOPNOTSUPP; } +struct scrub_feat_data { + u8 cycle; +#define SCRUB_DATA_F_ENABLE BIT(0) + u8 flags; +}; +#define SCRUB_DATA_CYCLE_OFFSET 0 +#define SCRUB_DATA_FLAGS_OFFSET 1 + +struct set_feat_input { + uuid_t uuid; + __le32 flags; + __le16 offset; + u8 version; + u8 rsvd[9]; + u8 data[]; +} __packed; + +enum set_feature_flags { + SET_FEATURE_F_FULL_XFER = 0, + SET_FEATURE_F_INIT_XFER, + SET_FEATURE_F_CONT_XFER, + SET_FEATURE_F_FIN_XFER, + SET_FEATURE_F_ABORT_XFER, +}; + +#define SET_FEATURE_F_ACTION_MASK GENMASK(2, 0) + +static int mock_set_patrol_scrub(struct cxl_mockmem_data *mdata, + struct cxl_mbox_cmd *cmd) +{ + struct set_feat_input *input = cmd->payload_in; + struct scrub_feat_data *data; + u32 action; + + action = FIELD_GET(SET_FEATURE_F_ACTION_MASK, + le32_to_cpu(input->flags)); + /* + * While it is spec compliant to support other set actions, it is not + * necessary to add the complication in the emulation currently. Reject + * anything besides full xfer. + */ + if (action != SET_FEATURE_F_FULL_XFER) { + cmd->return_code = CXL_MBOX_CMD_RC_INPUT; + return -EINVAL; + } + + /* Offset should be reserved when doing full transfer */ + if (input->offset) { + cmd->return_code = CXL_MBOX_CMD_RC_INPUT; + return -EINVAL; + } + + data = (struct scrub_feat_data *)input->data; + /* Does not support changing cycle, should be reserved */ + if (data->cycle) { + cmd->return_code = CXL_MBOX_CMD_RC_INPUT; + return -EINVAL; + } + + /* Check reserved fields */ + if (data->flags & ~SCRUB_DATA_F_ENABLE) { + cmd->return_code = CXL_MBOX_CMD_RC_INPUT; + return -EINVAL; + } + mdata->patrol_feat.flags = data->flags & SCRUB_DATA_F_ENABLE; + + return 0; +} + +static int mock_set_feature(struct cxl_mockmem_data *mdata, + struct cxl_mbox_cmd *cmd) +{ + struct set_feat_input *input = cmd->payload_in; + + if (uuid_equal(&input->uuid, &DEV_PATROL_SCRUB_FEAT_UUID)) + return mock_set_patrol_scrub(mdata, cmd); + + cmd->return_code = CXL_MBOX_CMD_RC_UNSUPPORTED; + + return -EOPNOTSUPP; +} + static int mock_get_supported_features(struct cxl_mockmem_data *mdata, struct cxl_mbox_cmd *cmd) { @@ -1580,6 +1666,9 @@ static int cxl_mock_mbox_send(struct cxl_mailbox *cxl_mbox, case CXL_MBOX_OP_GET_FEATURE: rc = mock_get_feature(mdata, cmd); break; + case CXL_MBOX_OP_SET_FEATURE: + rc = mock_set_feature(mdata, cmd); + break; default: break; }