Commit 7d0ecc0b authored by Davidlohr Bueso's avatar Davidlohr Bueso Committed by Dave Jiang
Browse files

cxl/pmem: Export dirty shutdown count via sysfs



Similar to how the acpi_nfit driver exports Optane dirty shutdown count,
introduce:

  /sys/bus/cxl/devices/nvdimm-bridge0/ndbusX/nmemY/cxl/dirty_shutdown

Under the conditions that 1) dirty shutdown can be set, 2) Device GPF
DVSEC exists, and 3) the count itself can be retrieved.

Suggested-by: default avatarDan Williams <dan.j.williams@intel.com>
Signed-off-by: default avatarDavidlohr Bueso <dave@stgolabs.net>
Reviewed-by: default avatarDave Jiang <dave.jiang@intel.com>
Reviewed-by: default avatarIra Weiny <ira.weiny@intel.com>
Reviewed-by: default avatarJonathan Cameron <Jonathan.Cameron@huawei.com>
Link: https://patch.msgid.link/20250220220235.276831-4-dave@stgolabs.net


Signed-off-by: default avatarDave Jiang <dave.jiang@intel.com>
parent 86349aaa
Loading
Loading
Loading
Loading
+12 −0
Original line number Diff line number Diff line
@@ -586,3 +586,15 @@ Description:
		See Documentation/ABI/stable/sysfs-devices-node. access0 provides
		the number to the closest initiator and access1 provides the
		number to the closest CPU.


What:		/sys/bus/cxl/devices/nvdimm-bridge0/ndbusX/nmemY/cxl/dirty_shutdown
Date:		Feb, 2025
KernelVersion:	v6.15
Contact:	linux-cxl@vger.kernel.org
Description:
		(RO) The device dirty shutdown count value, which is the number
		of times the device could have incurred in potential data loss.
		The count is persistent across power loss and wraps back to 0
		upon overflow. If this file is not present, the device does not
		have the necessary support for dirty tracking.
+1 −1
Original line number Diff line number Diff line
@@ -130,7 +130,7 @@ Mailbox commands
* [0] Switch CCI
* [3] Timestamp
* [1] PMEM labels
* [1] PMEM GPF / Dirty Shutdown
* [3] PMEM GPF / Dirty Shutdown
* [0] Scan Media

PMU
+21 −0
Original line number Diff line number Diff line
@@ -1308,6 +1308,27 @@ int cxl_mem_create_range_info(struct cxl_memdev_state *mds)
}
EXPORT_SYMBOL_NS_GPL(cxl_mem_create_range_info, "CXL");

int cxl_get_dirty_count(struct cxl_memdev_state *mds, u32 *count)
{
	struct cxl_mailbox *cxl_mbox = &mds->cxlds.cxl_mbox;
	struct cxl_mbox_get_health_info_out hi;
	struct cxl_mbox_cmd mbox_cmd;
	int rc;

	mbox_cmd = (struct cxl_mbox_cmd) {
		.opcode = CXL_MBOX_OP_GET_HEALTH_INFO,
		.size_out = sizeof(hi),
		.payload_out = &hi,
	};

	rc = cxl_internal_send_cmd(cxl_mbox, &mbox_cmd);
	if (!rc)
		*count = le32_to_cpu(hi.dirty_shutdown_cnt);

	return rc;
}
EXPORT_SYMBOL_NS_GPL(cxl_get_dirty_count, "CXL");

int cxl_arm_dirty_shutdown(struct cxl_memdev_state *mds)
{
	struct cxl_mailbox *cxl_mbox = &mds->cxlds.cxl_mbox;
+1 −0
Original line number Diff line number Diff line
@@ -563,6 +563,7 @@ struct cxl_nvdimm {
	struct device dev;
	struct cxl_memdev *cxlmd;
	u8 dev_id[CXL_DEV_ID_LEN]; /* for nvdimm, string of 'serial' */
	u64 dirty_shutdowns;
};

struct cxl_pmem_region_mapping {
+13 −0
Original line number Diff line number Diff line
@@ -693,6 +693,18 @@ struct cxl_mbox_set_partition_info {

#define  CXL_SET_PARTITION_IMMEDIATE_FLAG	BIT(0)

/* Get Health Info Output Payload CXL 3.2 Spec 8.2.10.9.3.1 Table 8-148 */
struct cxl_mbox_get_health_info_out {
	u8 health_status;
	u8 media_status;
	u8 additional_status;
	u8 life_used;
	__le16 device_temperature;
	__le32 dirty_shutdown_cnt;
	__le32 corrected_volatile_error_cnt;
	__le32 corrected_persistent_error_cnt;
} __packed;

/* Set Shutdown State Input Payload CXL 3.2 Spec 8.2.10.9.3.5 Table 8-152 */
struct cxl_mbox_set_shutdown_state_in {
	u8 state;
@@ -834,6 +846,7 @@ 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_get_dirty_count(struct cxl_memdev_state *mds, u32 *count);
int cxl_arm_dirty_shutdown(struct cxl_memdev_state *mds);
int cxl_set_timestamp(struct cxl_memdev_state *mds);
int cxl_poison_state_init(struct cxl_memdev_state *mds);
Loading