Lines Matching +full:data +full:- +full:transfer

1 // SPDX-License-Identifier: GPL-2.0-only
4 #include <linux/io-64-nonatomic-lo-hi.h>
29 ida_free(&cxl_memdev_ida, cxlmd->id); in cxl_memdev_release()
43 struct cxl_dev_state *cxlds = cxlmd->cxlds; in firmware_version_show()
48 return sysfs_emit(buf, "%.16s\n", mds->firmware_version); in firmware_version_show()
56 struct cxl_dev_state *cxlds = cxlmd->cxlds; in payload_max_show()
61 return sysfs_emit(buf, "%zu\n", mds->payload_size); in payload_max_show()
69 struct cxl_dev_state *cxlds = cxlmd->cxlds; in label_storage_size_show()
74 return sysfs_emit(buf, "%zu\n", mds->lsa_size); in label_storage_size_show()
82 struct cxl_dev_state *cxlds = cxlmd->cxlds; in ram_size_show()
83 unsigned long long len = resource_size(&cxlds->ram_res); in ram_size_show()
95 struct cxl_dev_state *cxlds = cxlmd->cxlds; in pmem_size_show()
96 unsigned long long len = resource_size(&cxlds->pmem_res); in pmem_size_show()
108 struct cxl_dev_state *cxlds = cxlmd->cxlds; in serial_show()
110 return sysfs_emit(buf, "%#llx\n", cxlds->serial); in serial_show()
126 struct cxl_dev_state *cxlds = cxlmd->cxlds; in security_state_show()
128 u64 reg = readq(cxlds->regs.mbox + CXLDEV_MBOX_BG_CMD_STATUS_OFFSET); in security_state_show()
131 unsigned long state = mds->security.state; in security_state_show()
155 struct cxl_memdev_state *mds = to_cxl_memdev_state(cxlmd->cxlds); in security_sanitize_store()
156 struct cxl_port *port = cxlmd->endpoint; in security_sanitize_store()
161 return -EINVAL; in security_sanitize_store()
164 return -EINVAL; in security_sanitize_store()
167 if (port->commit_end != -1) in security_sanitize_store()
168 return -EBUSY; in security_sanitize_store()
182 struct cxl_memdev_state *mds = to_cxl_memdev_state(cxlmd->cxlds); in security_erase_store()
183 struct cxl_port *port = cxlmd->endpoint; in security_erase_store()
188 return -EINVAL; in security_erase_store()
191 return -EINVAL; in security_erase_store()
194 if (port->commit_end != -1) in security_erase_store()
195 return -EBUSY; in security_erase_store()
206 struct cxl_dev_state *cxlds = cxlmd->cxlds; in cxl_get_poison_by_memdev()
211 if (resource_size(&cxlds->pmem_res)) { in cxl_get_poison_by_memdev()
212 offset = cxlds->pmem_res.start; in cxl_get_poison_by_memdev()
213 length = resource_size(&cxlds->pmem_res); in cxl_get_poison_by_memdev()
218 if (resource_size(&cxlds->ram_res)) { in cxl_get_poison_by_memdev()
219 offset = cxlds->ram_res.start; in cxl_get_poison_by_memdev()
220 length = resource_size(&cxlds->ram_res); in cxl_get_poison_by_memdev()
226 if (rc == -EFAULT) in cxl_get_poison_by_memdev()
237 port = cxlmd->endpoint; in cxl_trigger_poison_list()
239 return -EINVAL; in cxl_trigger_poison_list()
245 if (port->commit_end == -1) { in cxl_trigger_poison_list()
267 u64 dpa = ctx->dpa; in __cxl_dpa_to_region()
273 if (!cxled->dpa_res || !resource_size(cxled->dpa_res)) in __cxl_dpa_to_region()
276 if (dpa > cxled->dpa_res->end || dpa < cxled->dpa_res->start) in __cxl_dpa_to_region()
280 dev_name(&cxled->cxld.region->dev)); in __cxl_dpa_to_region()
282 ctx->cxlr = cxled->cxld.region; in __cxl_dpa_to_region()
295 port = cxlmd->endpoint; in cxl_dpa_to_region()
296 if (port && is_cxl_endpoint(port) && port->commit_end != -1) in cxl_dpa_to_region()
297 device_for_each_child(&port->dev, &ctx, __cxl_dpa_to_region); in cxl_dpa_to_region()
304 struct cxl_dev_state *cxlds = cxlmd->cxlds; in cxl_validate_poison_dpa()
309 if (!resource_size(&cxlds->dpa_res)) { in cxl_validate_poison_dpa()
310 dev_dbg(cxlds->dev, "device has no dpa resource\n"); in cxl_validate_poison_dpa()
311 return -EINVAL; in cxl_validate_poison_dpa()
313 if (dpa < cxlds->dpa_res.start || dpa > cxlds->dpa_res.end) { in cxl_validate_poison_dpa()
314 dev_dbg(cxlds->dev, "dpa:0x%llx not in resource:%pR\n", in cxl_validate_poison_dpa()
315 dpa, &cxlds->dpa_res); in cxl_validate_poison_dpa()
316 return -EINVAL; in cxl_validate_poison_dpa()
319 dev_dbg(cxlds->dev, "dpa:0x%llx is not 64-byte aligned\n", dpa); in cxl_validate_poison_dpa()
320 return -EINVAL; in cxl_validate_poison_dpa()
328 struct cxl_memdev_state *mds = to_cxl_memdev_state(cxlmd->cxlds); in cxl_inject_poison()
358 dev_warn_once(mds->cxlds.dev, in cxl_inject_poison()
360 dev_name(&cxlr->dev)); in cxl_inject_poison()
376 struct cxl_memdev_state *mds = to_cxl_memdev_state(cxlmd->cxlds); in cxl_clear_poison()
396 * is defined to accept 64 bytes of write-data, along with the in cxl_clear_poison()
397 * address to clear. This driver uses zeroes as write-data. in cxl_clear_poison()
415 dev_warn_once(mds->cxlds.dev, in cxl_clear_poison()
417 dev_name(&cxlr->dev)); in cxl_clear_poison()
462 return a->mode; in cxl_memdev_visible()
485 struct cxl_memdev_state *mds = to_cxl_memdev_state(cxlmd->cxlds); in cxl_memdev_security_visible()
488 !test_bit(CXL_SEC_ENABLED_SANITIZE, mds->security.enabled_cmds)) in cxl_memdev_security_visible()
492 !test_bit(CXL_SEC_ENABLED_SECURE_ERASE, mds->security.enabled_cmds)) in cxl_memdev_security_visible()
495 return a->mode; in cxl_memdev_security_visible()
521 return dev->type == &cxl_memdev_type; in is_cxl_memdev()
526 * set_exclusive_cxl_commands() - atomically disable user cxl commands
530 * Grab the cxl_memdev_rwsem in write mode to flush in-flight
538 bitmap_or(mds->exclusive_cmds, mds->exclusive_cmds, cmds, in set_exclusive_cxl_commands()
545 * clear_exclusive_cxl_commands() - atomically enable user cxl commands
553 bitmap_andnot(mds->exclusive_cmds, mds->exclusive_cmds, cmds, in clear_exclusive_cxl_commands()
562 struct cxl_memdev_state *mds = to_cxl_memdev_state(cxlmd->cxlds); in cxl_memdev_security_shutdown()
564 if (mds->security.poll) in cxl_memdev_security_shutdown()
565 cancel_delayed_work_sync(&mds->security.poll_dwork); in cxl_memdev_security_shutdown()
574 cxlmd->cxlds = NULL; in cxl_memdev_shutdown()
581 struct device *dev = &cxlmd->dev; in cxl_memdev_unregister()
584 cdev_device_del(&cxlmd->cdev, dev); in cxl_memdev_unregister()
593 device_release_driver(&cxlmd->dev); in detach_memdev()
594 put_device(&cxlmd->dev); in detach_memdev()
609 return ERR_PTR(-ENOMEM); in cxl_memdev_alloc()
611 rc = ida_alloc_max(&cxl_memdev_ida, CXL_MEM_MAX_DEVS - 1, GFP_KERNEL); in cxl_memdev_alloc()
614 cxlmd->id = rc; in cxl_memdev_alloc()
615 cxlmd->depth = -1; in cxl_memdev_alloc()
617 dev = &cxlmd->dev; in cxl_memdev_alloc()
619 lockdep_set_class(&dev->mutex, &cxl_memdev_key); in cxl_memdev_alloc()
620 dev->parent = cxlds->dev; in cxl_memdev_alloc()
621 dev->bus = &cxl_bus_type; in cxl_memdev_alloc()
622 dev->devt = MKDEV(cxl_mem_major, cxlmd->id); in cxl_memdev_alloc()
623 dev->type = &cxl_memdev_type; in cxl_memdev_alloc()
625 INIT_WORK(&cxlmd->detach_work, detach_memdev); in cxl_memdev_alloc()
627 cdev = &cxlmd->cdev; in cxl_memdev_alloc()
645 return -ENOTTY; in __cxl_memdev_ioctl()
652 struct cxl_memdev *cxlmd = file->private_data; in cxl_memdev_ioctl()
654 int rc = -ENXIO; in cxl_memdev_ioctl()
657 cxlds = cxlmd->cxlds; in cxl_memdev_ioctl()
658 if (cxlds && cxlds->type == CXL_DEVTYPE_CLASSMEM) in cxl_memdev_ioctl()
668 container_of(inode->i_cdev, typeof(*cxlmd), cdev); in cxl_memdev_open()
670 get_device(&cxlmd->dev); in cxl_memdev_open()
671 file->private_data = cxlmd; in cxl_memdev_open()
679 container_of(inode->i_cdev, typeof(*cxlmd), cdev); in cxl_memdev_release_file()
681 put_device(&cxlmd->dev); in cxl_memdev_release_file()
687 * cxl_mem_get_fw_info - Get Firmware info
688 * @mds: The device data for the operation
694 * See CXL-3.0 8.2.9.3.1 Get FW Info
712 mds->fw.num_slots = info.num_slots; in cxl_mem_get_fw_info()
713 mds->fw.cur_slot = FIELD_GET(CXL_FW_INFO_SLOT_INFO_CUR_MASK, in cxl_mem_get_fw_info()
720 * cxl_mem_activate_fw - Activate Firmware
721 * @mds: The device data for the operation
728 * See CXL-3.0 8.2.9.3.3 Activate FW
735 if (slot == 0 || slot > mds->fw.num_slots) in cxl_mem_activate_fw()
736 return -EINVAL; in cxl_mem_activate_fw()
752 * cxl_mem_abort_fw_xfer - Abort an in-progress FW transfer
753 * @mds: The device data for the operation
755 * Abort an in-progress firmware transfer for the device specified.
759 * See CXL-3.0 8.2.9.3.2 Transfer FW
763 struct cxl_mbox_transfer_fw *transfer; in cxl_mem_abort_fw_xfer() local
767 transfer = kzalloc(struct_size(transfer, data, 0), GFP_KERNEL); in cxl_mem_abort_fw_xfer()
768 if (!transfer) in cxl_mem_abort_fw_xfer()
769 return -ENOMEM; in cxl_mem_abort_fw_xfer()
774 .size_in = sizeof(*transfer), in cxl_mem_abort_fw_xfer()
775 .payload_in = transfer, in cxl_mem_abort_fw_xfer()
780 transfer->action = CXL_FW_TRANSFER_ACTION_ABORT; in cxl_mem_abort_fw_xfer()
783 kfree(transfer); in cxl_mem_abort_fw_xfer()
789 struct cxl_memdev_state *mds = fwl->dd_handle; in cxl_fw_cleanup()
791 mds->fw.next_slot = 0; in cxl_fw_cleanup()
796 struct cxl_memdev_state *mds = fwl->dd_handle; in cxl_fw_do_cancel()
797 struct cxl_dev_state *cxlds = &mds->cxlds; in cxl_fw_do_cancel()
798 struct cxl_memdev *cxlmd = cxlds->cxlmd; in cxl_fw_do_cancel()
803 dev_err(&cxlmd->dev, "Error aborting FW transfer: %d\n", rc); in cxl_fw_do_cancel()
808 static enum fw_upload_err cxl_fw_prepare(struct fw_upload *fwl, const u8 *data, in cxl_fw_prepare() argument
811 struct cxl_memdev_state *mds = fwl->dd_handle; in cxl_fw_prepare()
812 struct cxl_mbox_transfer_fw *transfer; in cxl_fw_prepare() local
817 mds->fw.oneshot = struct_size(transfer, data, size) < in cxl_fw_prepare()
818 mds->payload_size; in cxl_fw_prepare()
827 if (test_and_clear_bit(CXL_FW_CANCEL, mds->fw.state)) in cxl_fw_prepare()
833 static enum fw_upload_err cxl_fw_write(struct fw_upload *fwl, const u8 *data, in cxl_fw_write() argument
836 struct cxl_memdev_state *mds = fwl->dd_handle; in cxl_fw_write()
837 struct cxl_dev_state *cxlds = &mds->cxlds; in cxl_fw_write()
838 struct cxl_memdev *cxlmd = cxlds->cxlmd; in cxl_fw_write()
839 struct cxl_mbox_transfer_fw *transfer; in cxl_fw_write() local
847 /* Offset has to be aligned to 128B (CXL-3.0 8.2.9.3.2 Table 8-57) */ in cxl_fw_write()
849 dev_err(&cxlmd->dev, in cxl_fw_write()
850 "misaligned offset for FW transfer slice (%u)\n", in cxl_fw_write()
856 * Pick transfer size based on mds->payload_size @size must bw 128-byte in cxl_fw_write()
857 * aligned, ->payload_size is a power of 2 starting at 256 bytes, and in cxl_fw_write()
858 * sizeof(*transfer) is 128. These constraints imply that @cur_size in cxl_fw_write()
861 cur_size = min_t(size_t, size, mds->payload_size - sizeof(*transfer)); in cxl_fw_write()
863 remaining = size - cur_size; in cxl_fw_write()
864 size_in = struct_size(transfer, data, cur_size); in cxl_fw_write()
866 if (test_and_clear_bit(CXL_FW_CANCEL, mds->fw.state)) in cxl_fw_write()
870 * Slot numbers are 1-indexed in cxl_fw_write()
871 * cur_slot is the 0-indexed next_slot (i.e. 'cur_slot - 1 + 1') in cxl_fw_write()
872 * Check for rollover using modulo, and 1-index it by adding 1 in cxl_fw_write()
874 mds->fw.next_slot = (mds->fw.cur_slot % mds->fw.num_slots) + 1; in cxl_fw_write()
876 /* Do the transfer via mailbox cmd */ in cxl_fw_write()
877 transfer = kzalloc(size_in, GFP_KERNEL); in cxl_fw_write()
878 if (!transfer) in cxl_fw_write()
881 transfer->offset = cpu_to_le32(offset / CXL_FW_TRANSFER_ALIGNMENT); in cxl_fw_write()
882 memcpy(transfer->data, data + offset, cur_size); in cxl_fw_write()
883 if (mds->fw.oneshot) { in cxl_fw_write()
884 transfer->action = CXL_FW_TRANSFER_ACTION_FULL; in cxl_fw_write()
885 transfer->slot = mds->fw.next_slot; in cxl_fw_write()
888 transfer->action = CXL_FW_TRANSFER_ACTION_INITIATE; in cxl_fw_write()
890 transfer->action = CXL_FW_TRANSFER_ACTION_END; in cxl_fw_write()
891 transfer->slot = mds->fw.next_slot; in cxl_fw_write()
893 transfer->action = CXL_FW_TRANSFER_ACTION_CONTINUE; in cxl_fw_write()
900 .payload_in = transfer, in cxl_fw_write()
914 if (mds->fw.oneshot || remaining == 0) { in cxl_fw_write()
915 dev_dbg(&cxlmd->dev, "Activating firmware slot: %d\n", in cxl_fw_write()
916 mds->fw.next_slot); in cxl_fw_write()
917 rc = cxl_mem_activate_fw(mds, mds->fw.next_slot); in cxl_fw_write()
919 dev_err(&cxlmd->dev, "Error activating firmware: %d\n", in cxl_fw_write()
929 kfree(transfer); in cxl_fw_write()
935 struct cxl_memdev_state *mds = fwl->dd_handle; in cxl_fw_poll_complete()
939 * No need to wait for completions here - any errors would've been in cxl_fw_poll_complete()
940 * reported and handled during the ->write() call(s). in cxl_fw_poll_complete()
943 if (test_and_clear_bit(CXL_FW_CANCEL, mds->fw.state)) in cxl_fw_poll_complete()
951 struct cxl_memdev_state *mds = fwl->dd_handle; in cxl_fw_cancel()
953 set_bit(CXL_FW_CANCEL, mds->fw.state); in cxl_fw_cancel()
971 struct cxl_dev_state *cxlds = &mds->cxlds; in cxl_memdev_setup_fw_upload()
972 struct device *dev = &cxlds->cxlmd->dev; in cxl_memdev_setup_fw_upload()
976 if (!test_bit(CXL_MEM_COMMAND_ID_GET_FW_INFO, mds->enabled_cmds)) in cxl_memdev_setup_fw_upload()
985 rc = devm_add_action_or_reset(cxlds->dev, devm_cxl_remove_fw_upload, in cxl_memdev_setup_fw_upload()
1005 static void put_sanitize(void *data) in put_sanitize() argument
1007 struct cxl_memdev_state *mds = data; in put_sanitize()
1009 sysfs_put(mds->security.sanitize_node); in put_sanitize()
1014 struct cxl_dev_state *cxlds = cxlmd->cxlds; in cxl_memdev_security_init()
1016 struct device *dev = &cxlmd->dev; in cxl_memdev_security_init()
1019 sec = sysfs_get_dirent(dev->kobj.sd, "security"); in cxl_memdev_security_init()
1022 return -ENODEV; in cxl_memdev_security_init()
1024 mds->security.sanitize_node = sysfs_get_dirent(sec, "state"); in cxl_memdev_security_init()
1026 if (!mds->security.sanitize_node) { in cxl_memdev_security_init()
1028 return -ENODEV; in cxl_memdev_security_init()
1031 return devm_add_action_or_reset(cxlds->dev, put_sanitize, mds); in cxl_memdev_security_init()
1045 dev = &cxlmd->dev; in devm_cxl_add_memdev()
1046 rc = dev_set_name(dev, "mem%d", cxlmd->id); in devm_cxl_add_memdev()
1054 cxlmd->cxlds = cxlds; in devm_cxl_add_memdev()
1055 cxlds->cxlmd = cxlmd; in devm_cxl_add_memdev()
1057 cdev = &cxlmd->cdev; in devm_cxl_add_memdev()
1066 rc = devm_add_action_or_reset(cxlds->dev, cxl_memdev_unregister, cxlmd); in devm_cxl_add_memdev()