@@ -149,6 +149,7 @@ static umode_t ufs_hwmon_is_visible(const void *data,
static const struct hwmon_channel_info *const ufs_hwmon_info[] = {
HWMON_CHANNEL_INFO(temp, HWMON_T_ENABLE | HWMON_T_INPUT | HWMON_T_CRIT | HWMON_T_LCRIT),
+ HWMON_CHANNEL_INFO(chip, HWMON_C_ALARMS),
NULL
};
@@ -209,4 +210,7 @@ void ufs_hwmon_notify_event(struct ufs_hba *hba, u16 ee_mask)
if (ee_mask & MASK_EE_TOO_LOW_TEMP)
hwmon_notify_event(hba->hwmon_device, hwmon_temp, hwmon_temp_min_alarm, 0);
+
+ if (ee_mask & MASK_EE_HEALTH_CRITICAL)
+ hwmon_notify_event(hba->hwmon_device, hwmon_chip, hwmon_chip_alarms, 0);
}
@@ -6198,6 +6198,9 @@ static void ufshcd_exception_event_handler(struct work_struct *work)
if (status & hba->ee_drv_mask & MASK_EE_URGENT_TEMP)
ufs_hwmon_notify_event(hba, status & MASK_EE_URGENT_TEMP);
+ if (status & hba->ee_drv_mask & MASK_EE_HEALTH_CRITICAL)
+ ufs_hwmon_notify_event(hba, status & MASK_EE_HEALTH_CRITICAL);
+
ufs_debugfs_exception_event(hba, status);
}
@@ -8091,12 +8094,24 @@ static void ufshcd_temp_notif_probe(struct ufs_hba *hba, const u8 *desc_buf, u16
*mask |= MASK_EE_TOO_HIGH_TEMP;
}
+static void ufshcd_critical_health_probe(struct ufs_hba *hba, u16 *mask)
+{
+ struct ufs_dev_info *dev_info = &hba->dev_info;
+
+ if (dev_info->wspecversion < 0x410)
+ return;
+
+ *mask |= MASK_EE_HEALTH_CRITICAL;
+}
+
static void ufshcd_hwmon_probe(struct ufs_hba *hba, const u8 *desc_buf)
{
u16 mask = 0;
ufshcd_temp_notif_probe(hba, desc_buf, &mask);
+ ufshcd_critical_health_probe(hba, &mask);
+
if (mask) {
ufshcd_enable_ee(hba, mask);
ufs_hwmon_probe(hba, mask);
@@ -419,6 +419,7 @@ enum {
MASK_EE_TOO_LOW_TEMP = BIT(4),
MASK_EE_WRITEBOOSTER_EVENT = BIT(5),
MASK_EE_PERFORMANCE_THROTTLING = BIT(6),
+ MASK_EE_HEALTH_CRITICAL = BIT(9),
};
#define MASK_EE_URGENT_TEMP (MASK_EE_TOO_HIGH_TEMP | MASK_EE_TOO_LOW_TEMP)
The UFS 4.1 standard, released on January 8, 2025, introduces several new features, including a new exception event: HEALTH_CRITICAL. This event notifies the host of a device's critical health condition, indicating that the device is approaching the end of its lifetime based on the number of program/erase cycles performed. We utilize the hwmon (hardware monitoring) subsystem to propagate this information via the chip alarm channel. The host can gain further insight into the specific issue by reading one of the following attributes: bPreEOLInfo, bDeviceLifeTimeEstA, bDeviceLifeTimeEstB, bWriteBoosterBufferLifeTimeEst, and bRPMBLifeTimeEst. However, we do not provide the corresponding .read method in the hwmon subsystem. This is intentional: all other end-of-life (EOL) signals are available for reading via the driver's sysfs entries or through an applicable utility. It is up to user-space to read these attributes if needed. It is not the kernel's responsibility to interpret any EOL signals, as they may vary from vendor to vendor. Signed-off-by: Avri Altman <avri.altman@wdc.com> --- drivers/ufs/core/ufs-hwmon.c | 4 ++++ drivers/ufs/core/ufshcd.c | 15 +++++++++++++++ include/ufs/ufs.h | 1 + 3 files changed, 20 insertions(+)