/* SPDX-License-Identifier: GPL-2.0-only */ /* Copyright(c) 2020-2021 Intel Corporation. */ #ifndef __CXL_MEM_H__ #define __CXL_MEM_H__ #include <uapi/linux/cxl_mem.h> #include <linux/cdev.h> #include <linux/uuid.h> #include <linux/rcuwait.h> #include <linux/cxl-event.h> #include <linux/node.h> #include "cxl.h" /* CXL 2.0 8.2.8.5.1.1 Memory Device Status Register */ #define CXLMDEV_STATUS_OFFSET … #define CXLMDEV_DEV_FATAL … #define CXLMDEV_FW_HALT … #define CXLMDEV_STATUS_MEDIA_STATUS_MASK … #define CXLMDEV_MS_NOT_READY … #define CXLMDEV_MS_READY … #define CXLMDEV_MS_ERROR … #define CXLMDEV_MS_DISABLED … #define CXLMDEV_READY(status) … #define CXLMDEV_MBOX_IF_READY … #define CXLMDEV_RESET_NEEDED_MASK … #define CXLMDEV_RESET_NEEDED_NOT … #define CXLMDEV_RESET_NEEDED_COLD … #define CXLMDEV_RESET_NEEDED_WARM … #define CXLMDEV_RESET_NEEDED_HOT … #define CXLMDEV_RESET_NEEDED_CXL … #define CXLMDEV_RESET_NEEDED(status) … /** * struct cxl_memdev - CXL bus object representing a Type-3 Memory Device * @dev: driver core device object * @cdev: char dev core object for ioctl operations * @cxlds: The device state backing this device * @detach_work: active memdev lost a port in its ancestry * @cxl_nvb: coordinate removal of @cxl_nvd if present * @cxl_nvd: optional bridge to an nvdimm if the device supports pmem * @endpoint: connection to the CXL port topology for this memory device * @id: id number of this memdev instance. * @depth: endpoint port depth */ struct cxl_memdev { … }; static inline struct cxl_memdev *to_cxl_memdev(struct device *dev) { … } static inline struct cxl_port *cxled_to_port(struct cxl_endpoint_decoder *cxled) { … } static inline struct cxl_port *cxlrd_to_port(struct cxl_root_decoder *cxlrd) { … } static inline struct cxl_memdev * cxled_to_memdev(struct cxl_endpoint_decoder *cxled) { … } bool is_cxl_memdev(const struct device *dev); static inline bool is_cxl_endpoint(struct cxl_port *port) { … } struct cxl_memdev *devm_cxl_add_memdev(struct device *host, struct cxl_dev_state *cxlds); int devm_cxl_sanitize_setup_notifier(struct device *host, struct cxl_memdev *cxlmd); struct cxl_memdev_state; int devm_cxl_setup_fw_upload(struct device *host, struct cxl_memdev_state *mds); int devm_cxl_dpa_reserve(struct cxl_endpoint_decoder *cxled, resource_size_t base, resource_size_t len, resource_size_t skipped); static inline struct cxl_ep *cxl_ep_load(struct cxl_port *port, struct cxl_memdev *cxlmd) { … } /** * 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 { … }; /* * Per CXL 3.0 Section 8.2.8.4.5.1 */ #define CMD_CMD_RC_TABLE … \ #undef C #define C … enum { … }; #undef C #define C … struct cxl_mbox_cmd_rc { … }; static const struct cxl_mbox_cmd_rc cxl_mbox_cmd_rctable[] = …; #undef C static inline const char *cxl_mbox_cmd_rc2str(struct cxl_mbox_cmd *mbox_cmd) { … } static inline int cxl_mbox_cmd_rc2errno(struct cxl_mbox_cmd *mbox_cmd) { … } /* * CXL 2.0 - Memory capacity multiplier * See Section 8.2.9.5 * * Volatile, Persistent, and Partition capacities are specified to be in * multiples of 256MB - define a multiplier to convert to/from bytes. */ #define CXL_CAPACITY_MULTIPLIER … /* * Event Interrupt Policy * * CXL rev 3.0 section 8.2.9.2.4; Table 8-52 */ enum cxl_event_int_mode { … }; struct cxl_event_interrupt_policy { … } __packed; /** * struct cxl_event_state - Event log driver state * * @buf: Buffer to receive event data * @log_lock: Serialize event_buf and log use */ struct cxl_event_state { … }; /* Device enabled poison commands */ enum poison_cmd_enabled_bits { … }; /* Device enabled security commands */ enum security_cmd_enabled_bits { … }; /** * struct cxl_poison_state - Driver poison state info * * @max_errors: Maximum media error records held in device cache * @enabled_cmds: All poison commands enabled in the CEL * @list_out: The poison list payload returned by device * @lock: Protect reads of the poison list * * Reads of the poison list are synchronized to ensure that a reader * does not get an incomplete list because their request overlapped * (was interrupted or preceded by) another read request of the same * DPA range. CXL Spec 3.0 Section 8.2.9.8.4.1 */ struct cxl_poison_state { … }; /* * Get FW Info * CXL rev 3.0 section 8.2.9.3.1; Table 8-56 */ struct cxl_mbox_get_fw_info { … } __packed; #define CXL_FW_INFO_SLOT_INFO_CUR_MASK … #define CXL_FW_INFO_SLOT_INFO_NEXT_MASK … #define CXL_FW_INFO_SLOT_INFO_NEXT_SHIFT … #define CXL_FW_INFO_ACTIVATION_CAP_HAS_LIVE_ACTIVATE … /* * Transfer FW Input Payload * CXL rev 3.0 section 8.2.9.3.2; Table 8-57 */ struct cxl_mbox_transfer_fw { … } __packed; #define CXL_FW_TRANSFER_ACTION_FULL … #define CXL_FW_TRANSFER_ACTION_INITIATE … #define CXL_FW_TRANSFER_ACTION_CONTINUE … #define CXL_FW_TRANSFER_ACTION_END … #define CXL_FW_TRANSFER_ACTION_ABORT … /* * CXL rev 3.0 section 8.2.9.3.2 mandates 128-byte alignment for FW packages * and for each part transferred in a Transfer FW command. */ #define CXL_FW_TRANSFER_ALIGNMENT … /* * Activate FW Input Payload * CXL rev 3.0 section 8.2.9.3.3; Table 8-58 */ struct cxl_mbox_activate_fw { … } __packed; #define CXL_FW_ACTIVATE_ONLINE … #define CXL_FW_ACTIVATE_OFFLINE … /* FW state bits */ #define CXL_FW_STATE_BITS … #define CXL_FW_CANCEL … /** * struct cxl_fw_state - Firmware upload / activation state * * @state: fw_uploader state bitmask * @oneshot: whether the fw upload fits in a single transfer * @num_slots: Number of FW slots available * @cur_slot: Slot number currently active * @next_slot: Slot number for the new firmware */ struct cxl_fw_state { … }; /** * struct cxl_security_state - Device security state * * @state: state of last security operation * @enabled_cmds: All security commands enabled in the CEL * @poll_tmo_secs: polling timeout * @sanitize_active: sanitize completion pending * @poll_dwork: polling work item * @sanitize_node: sanitation sysfs file to notify */ struct cxl_security_state { … }; /* * enum cxl_devtype - delineate type-2 from a generic type-3 device * @CXL_DEVTYPE_DEVMEM - Vendor specific CXL Type-2 device implementing HDM-D or * HDM-DB, no requirement that this device implements a * mailbox, or other memory-device-standard manageability * flows. * @CXL_DEVTYPE_CLASSMEM - Common class definition of a CXL Type-3 device with * HDM-H and class-mandatory memory device registers */ enum cxl_devtype { … }; /** * struct cxl_dpa_perf - DPA performance property entry * @dpa_range: range for DPA address * @coord: QoS performance data (i.e. latency, bandwidth) * @qos_class: QoS Class cookies */ struct cxl_dpa_perf { … }; /** * struct cxl_dev_state - The driver device state * * cxl_dev_state represents the CXL driver/device state. It provides an * interface to mailbox commands as well as some cached data about the device. * Currently only memory devices are represented. * * @dev: The device associated with this CXL state * @cxlmd: The device representing the CXL.mem capabilities of @dev * @reg_map: component and ras register mapping parameters * @regs: Parsed register blocks * @cxl_dvsec: Offset to the PCIe device DVSEC * @rcd: operating in RCD mode (CXL 3.0 9.11.8 CXL Devices Attached to an RCH) * @media_ready: Indicate whether the device media is usable * @dpa_res: Overall DPA resource tree for the device * @pmem_res: Active Persistent memory capacity configuration * @ram_res: Active Volatile memory capacity configuration * @serial: PCIe Device Serial Number * @type: Generic Memory Class device or Vendor Specific Memory device */ struct cxl_dev_state { … }; /** * struct cxl_memdev_state - Generic Type-3 Memory Device Class driver data * * CXL 8.1.12.1 PCI Header - Class Code Register Memory Device defines * common memory device functionality like the presence of a mailbox and * 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 * @total_bytes: sum of all possible capacities * @volatile_only_bytes: hard volatile capacity * @persistent_only_bytes: hard persistent capacity * @partition_align_bytes: alignment size for partition-able capacity * @active_volatile_bytes: sum of hard + soft volatile * @active_persistent_bytes: sum of hard + soft persistent * @next_volatile_bytes: volatile capacity change pending device reset * @next_persistent_bytes: persistent capacity change pending device reset * @ram_perf: performance data entry matched to RAM partition * @pmem_perf: performance data entry matched to PMEM partition * @event: event log driver 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 { … }; static inline struct cxl_memdev_state * to_cxl_memdev_state(struct cxl_dev_state *cxlds) { … } enum cxl_opcode { … }; #define DEFINE_CXL_CEL_UUID … #define DEFINE_CXL_VENDOR_DEBUG_UUID … struct cxl_mbox_get_supported_logs { … } __packed; struct cxl_cel_entry { … } __packed; struct cxl_mbox_get_log { … } __packed; /* See CXL 2.0 Table 175 Identify Memory Device Output Payload */ struct cxl_mbox_identify { … } __packed; /* * General Media Event Record UUID * CXL rev 3.0 Section 8.2.9.2.1.1; Table 8-43 */ #define CXL_EVENT_GEN_MEDIA_UUID … /* * DRAM Event Record UUID * CXL rev 3.0 section 8.2.9.2.1.2; Table 8-44 */ #define CXL_EVENT_DRAM_UUID … /* * Memory Module Event Record UUID * CXL rev 3.0 section 8.2.9.2.1.3; Table 8-45 */ #define CXL_EVENT_MEM_MODULE_UUID … /* * Get Event Records output payload * CXL rev 3.0 section 8.2.9.2.2; Table 8-50 */ #define CXL_GET_EVENT_FLAG_OVERFLOW … #define CXL_GET_EVENT_FLAG_MORE_RECORDS … struct cxl_get_event_payload { … } __packed; /* * CXL rev 3.0 section 8.2.9.2.2; Table 8-49 */ enum cxl_event_log_type { … }; /* * Clear Event Records input payload * CXL rev 3.0 section 8.2.9.2.3; Table 8-51 */ struct cxl_mbox_clear_event_payload { … } __packed; #define CXL_CLEAR_EVENT_MAX_HANDLES … struct cxl_mbox_get_partition_info { … } __packed; struct cxl_mbox_get_lsa { … } __packed; struct cxl_mbox_set_lsa { … } __packed; struct cxl_mbox_set_partition_info { … } __packed; #define CXL_SET_PARTITION_IMMEDIATE_FLAG … /* Set Timestamp CXL 3.0 Spec 8.2.9.4.2 */ struct cxl_mbox_set_timestamp_in { … } __packed; /* Get Poison List CXL 3.0 Spec 8.2.9.8.4.1 */ struct cxl_mbox_poison_in { … } __packed; struct cxl_mbox_poison_out { … } __packed; /* * Get Poison List address field encodes the starting * address of poison, and the source of the poison. */ #define CXL_POISON_START_MASK … #define CXL_POISON_SOURCE_MASK … /* Get Poison List record length is in units of 64 bytes */ #define CXL_POISON_LEN_MULT … /* Kernel defined maximum for a list of poison errors */ #define CXL_POISON_LIST_MAX … /* Get Poison List: Payload out flags */ #define CXL_POISON_FLAG_MORE … #define CXL_POISON_FLAG_OVERFLOW … #define CXL_POISON_FLAG_SCANNING … /* Get Poison List: Poison Source */ #define CXL_POISON_SOURCE_UNKNOWN … #define CXL_POISON_SOURCE_EXTERNAL … #define CXL_POISON_SOURCE_INTERNAL … #define CXL_POISON_SOURCE_INJECTED … #define CXL_POISON_SOURCE_VENDOR … /* Inject & Clear Poison CXL 3.0 Spec 8.2.9.8.4.2/3 */ struct cxl_mbox_inject_poison { … }; /* Clear Poison CXL 3.0 Spec 8.2.9.8.4.3 */ struct cxl_mbox_clear_poison { … } __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 { … }; #define CXL_PMEM_SEC_STATE_USER_PASS_SET … #define CXL_PMEM_SEC_STATE_MASTER_PASS_SET … #define CXL_PMEM_SEC_STATE_LOCKED … #define CXL_PMEM_SEC_STATE_FROZEN … #define CXL_PMEM_SEC_STATE_USER_PLIMIT … #define CXL_PMEM_SEC_STATE_MASTER_PLIMIT … /* set passphrase input payload */ struct cxl_set_pass { … } __packed; /* disable passphrase input payload */ struct cxl_disable_pass { … } __packed; /* passphrase secure erase payload */ struct cxl_pass_erase { … } __packed; enum { … }; int cxl_internal_send_cmd(struct cxl_memdev_state *mds, 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); int cxl_enumerate_cmds(struct cxl_memdev_state *mds); int cxl_mem_create_range_info(struct cxl_memdev_state *mds); struct cxl_memdev_state *cxl_memdev_state_create(struct device *dev); void set_exclusive_cxl_commands(struct cxl_memdev_state *mds, unsigned long *cmds); void clear_exclusive_cxl_commands(struct cxl_memdev_state *mds, unsigned long *cmds); void cxl_mem_get_event_records(struct cxl_memdev_state *mds, u32 status); void cxl_event_trace_record(const struct cxl_memdev *cxlmd, enum cxl_event_log_type type, enum cxl_event_type event_type, const uuid_t *uuid, union cxl_event *evt); int cxl_set_timestamp(struct cxl_memdev_state *mds); int cxl_poison_state_init(struct cxl_memdev_state *mds); int cxl_mem_get_poison(struct cxl_memdev *cxlmd, u64 offset, u64 len, struct cxl_region *cxlr); int cxl_trigger_poison_list(struct cxl_memdev *cxlmd); int cxl_inject_poison(struct cxl_memdev *cxlmd, u64 dpa); int cxl_clear_poison(struct cxl_memdev *cxlmd, u64 dpa); #ifdef CONFIG_CXL_SUSPEND void cxl_mem_active_inc(void); void cxl_mem_active_dec(void); #else static inline void cxl_mem_active_inc(void) { } static inline void cxl_mem_active_dec(void) { } #endif int cxl_mem_sanitize(struct cxl_memdev *cxlmd, u16 cmd); /** * struct cxl_hdm - HDM Decoder registers and cached / decoded capabilities * @regs: mapped registers, see devm_cxl_setup_hdm() * @decoder_count: number of decoders for this port * @target_count: for switch decoders, max downstream port targets * @interleave_mask: interleave granularity capability, see check_interleave_cap() * @iw_cap_mask: bitmask of supported interleave ways, see check_interleave_cap() * @port: mapped cxl_port, see devm_cxl_setup_hdm() */ 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); #endif /* __CXL_MEM_H__ */