Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit cdd77d3e authored by Dan Williams's avatar Dan Williams
Browse files

nfit, libnvdimm: deprecate the generic SMART ioctl

The kernel's ND_IOCTL_SMART_THRESHOLD command is based on a payload
definition that has become broken / out-of-sync with recent versions of
the NVDIMM_FAMILY_INTEL definition. Deprecate the use of the
ND_IOCTL_SMART_THRESHOLD command in favor of the ND_CMD_CALL approach
taken by NVDIMM_FAMILY_{HPE,MSFT}, where we can manage the per-vendor
variance in userspace.

In a couple years, when the new scheme is widely deployed in userspace
packages, the ND_IOCTL_SMART_THRESHOLD support can be removed. For now
we prevent new binaries from compiling against the kernel header
definitions, but kernel still compatible with old binaries. The
libndctl.h [1] header is now the authoritative interface definition for
NVDIMM SMART.

[1]: https://github.com/pmem/ndctl


Signed-off-by: default avatarDan Williams <dan.j.williams@intel.com>
parent ae64f9bd
Loading
Loading
Loading
Loading
+0 −3
Original line number Diff line number Diff line
@@ -1142,9 +1142,6 @@ int __init nvdimm_bus_init(void)
{
	int rc;

	BUILD_BUG_ON(sizeof(struct nd_smart_payload) != 128);
	BUILD_BUG_ON(sizeof(struct nd_smart_threshold_payload) != 8);

	rc = bus_register(&nvdimm_bus_type);
	if (rc)
		return rc;
+0 −54
Original line number Diff line number Diff line
@@ -15,54 +15,6 @@

#include <linux/types.h>

struct nd_cmd_smart {
	__u32 status;
	__u8 data[128];
} __packed;

#define ND_SMART_HEALTH_VALID	(1 << 0)
#define ND_SMART_SPARES_VALID	(1 << 1)
#define ND_SMART_USED_VALID	(1 << 2)
#define ND_SMART_TEMP_VALID 	(1 << 3)
#define ND_SMART_CTEMP_VALID 	(1 << 4)
#define ND_SMART_ALARM_VALID	(1 << 9)
#define ND_SMART_SHUTDOWN_VALID	(1 << 10)
#define ND_SMART_VENDOR_VALID	(1 << 11)
#define ND_SMART_SPARE_TRIP	(1 << 0)
#define ND_SMART_TEMP_TRIP	(1 << 1)
#define ND_SMART_CTEMP_TRIP	(1 << 2)
#define ND_SMART_NON_CRITICAL_HEALTH	(1 << 0)
#define ND_SMART_CRITICAL_HEALTH	(1 << 1)
#define ND_SMART_FATAL_HEALTH		(1 << 2)

struct nd_smart_payload {
	__u32 flags;
	__u8 reserved0[4];
	__u8 health;
	__u8 spares;
	__u8 life_used;
	__u8 alarm_flags;
	__u16 temperature;
	__u16 ctrl_temperature;
	__u8 reserved1[15];
	__u8 shutdown_state;
	__u32 vendor_size;
	__u8 vendor_data[92];
} __packed;

struct nd_cmd_smart_threshold {
	__u32 status;
	__u8 data[8];
} __packed;

struct nd_smart_threshold_payload {
	__u8 alarm_control;
	__u8 reserved0;
	__u16 temperature;
	__u8 spares;
	__u8 reserved[3];
} __packed;

struct nd_cmd_dimm_flags {
	__u32 status;
	__u32 flags;
@@ -211,12 +163,6 @@ static inline const char *nvdimm_cmd_name(unsigned cmd)

#define ND_IOCTL 'N'

#define ND_IOCTL_SMART			_IOWR(ND_IOCTL, ND_CMD_SMART,\
					struct nd_cmd_smart)

#define ND_IOCTL_SMART_THRESHOLD	_IOWR(ND_IOCTL, ND_CMD_SMART_THRESHOLD,\
					struct nd_cmd_smart_threshold)

#define ND_IOCTL_DIMM_FLAGS		_IOWR(ND_IOCTL, ND_CMD_DIMM_FLAGS,\
					struct nd_cmd_dimm_flags)

+25 −14
Original line number Diff line number Diff line
@@ -440,39 +440,50 @@ static int nfit_test_cmd_translate_spa(struct nvdimm_bus *bus,
	return 0;
}

static int nfit_test_cmd_smart(struct nd_cmd_smart *smart, unsigned int buf_len)
static int nfit_test_cmd_smart(struct nd_intel_smart *smart, unsigned int buf_len)
{
	static const struct nd_smart_payload smart_data = {
		.flags = ND_SMART_HEALTH_VALID | ND_SMART_TEMP_VALID
			| ND_SMART_SPARES_VALID | ND_SMART_ALARM_VALID
			| ND_SMART_USED_VALID | ND_SMART_SHUTDOWN_VALID,
		.health = ND_SMART_NON_CRITICAL_HEALTH,
		.temperature = 23 * 16,
	static const struct nd_intel_smart smart_data = {
		.flags = ND_INTEL_SMART_HEALTH_VALID
			| ND_INTEL_SMART_SPARES_VALID
			| ND_INTEL_SMART_ALARM_VALID
			| ND_INTEL_SMART_USED_VALID
			| ND_INTEL_SMART_SHUTDOWN_VALID
			| ND_INTEL_SMART_MTEMP_VALID,
		.health = ND_INTEL_SMART_NON_CRITICAL_HEALTH,
		.media_temperature = 23 * 16,
		.ctrl_temperature = 30 * 16,
		.pmic_temperature = 40 * 16,
		.spares = 75,
		.alarm_flags = ND_SMART_SPARE_TRIP | ND_SMART_TEMP_TRIP,
		.alarm_flags = ND_INTEL_SMART_SPARE_TRIP
			| ND_INTEL_SMART_TEMP_TRIP,
		.ait_status = 1,
		.life_used = 5,
		.shutdown_state = 0,
		.vendor_size = 0,
		.shutdown_count = 100,
	};

	if (buf_len < sizeof(*smart))
		return -EINVAL;
	memcpy(smart->data, &smart_data, sizeof(smart_data));
	memcpy(smart, &smart_data, sizeof(smart_data));
	return 0;
}

static int nfit_test_cmd_smart_threshold(struct nd_cmd_smart_threshold *smart_t,
static int nfit_test_cmd_smart_threshold(
		struct nd_intel_smart_threshold *smart_t,
		unsigned int buf_len)
{
	static const struct nd_smart_threshold_payload smart_t_data = {
		.alarm_control = ND_SMART_SPARE_TRIP | ND_SMART_TEMP_TRIP,
		.temperature = 40 * 16,
	static const struct nd_intel_smart_threshold smart_t_data = {
		.alarm_control = ND_INTEL_SMART_SPARE_TRIP
			| ND_INTEL_SMART_TEMP_TRIP,
		.media_temperature = 40 * 16,
		.ctrl_temperature = 30 * 16,
		.spares = 5,
	};

	if (buf_len < sizeof(*smart_t))
		return -EINVAL;
	memcpy(smart_t->data, &smart_t_data, sizeof(smart_t_data));
	memcpy(smart_t, &smart_t_data, sizeof(smart_t_data));
	return 0;
}

+59 −0
Original line number Diff line number Diff line
@@ -84,6 +84,65 @@ struct nd_cmd_ars_err_inj_stat {
	} __packed record[0];
} __packed;

#define ND_INTEL_SMART 1
#define ND_INTEL_SMART_THRESHOLD 2

#define ND_INTEL_SMART_HEALTH_VALID             (1 << 0)
#define ND_INTEL_SMART_SPARES_VALID             (1 << 1)
#define ND_INTEL_SMART_USED_VALID               (1 << 2)
#define ND_INTEL_SMART_MTEMP_VALID              (1 << 3)
#define ND_INTEL_SMART_CTEMP_VALID              (1 << 4)
#define ND_INTEL_SMART_SHUTDOWN_COUNT_VALID     (1 << 5)
#define ND_INTEL_SMART_AIT_STATUS_VALID         (1 << 6)
#define ND_INTEL_SMART_PTEMP_VALID              (1 << 7)
#define ND_INTEL_SMART_ALARM_VALID              (1 << 9)
#define ND_INTEL_SMART_SHUTDOWN_VALID           (1 << 10)
#define ND_INTEL_SMART_VENDOR_VALID             (1 << 11)
#define ND_INTEL_SMART_SPARE_TRIP               (1 << 0)
#define ND_INTEL_SMART_TEMP_TRIP                (1 << 1)
#define ND_INTEL_SMART_CTEMP_TRIP               (1 << 2)
#define ND_INTEL_SMART_NON_CRITICAL_HEALTH      (1 << 0)
#define ND_INTEL_SMART_CRITICAL_HEALTH          (1 << 1)
#define ND_INTEL_SMART_FATAL_HEALTH             (1 << 2)

struct nd_intel_smart {
	__u32 status;
	union {
		struct {
			__u32 flags;
			__u8 reserved0[4];
			__u8 health;
			__u8 spares;
			__u8 life_used;
			__u8 alarm_flags;
			__u16 media_temperature;
			__u16 ctrl_temperature;
			__u32 shutdown_count;
			__u8 ait_status;
			__u16 pmic_temperature;
			__u8 reserved1[8];
			__u8 shutdown_state;
			__u32 vendor_size;
			__u8 vendor_data[92];
		} __packed;
		__u8 data[128];
	};
} __packed;

struct nd_intel_smart_threshold {
	__u32 status;
	union {
		struct {
			__u16 alarm_control;
			__u8 spares;
			__u16 media_temperature;
			__u16 ctrl_temperature;
			__u8 reserved[1];
		} __packed;
		__u8 data[8];
	};
} __packed;

union acpi_object;
typedef void *acpi_handle;