v6 -> v7:
- some more useless initializations
v5 -> v6:
- remove useless initializations
v4 - > v5:
- Fix improper return error values
v3 -> v4:
- Attend Guenter's comments
v2 -> v3:
- Attend Bart's & Guenter's comments
v1 -> v2:
- Add a hw monitor device if both the platform & the device support it
- Remove the sysfs patch: no need to duplicate /sys/class/hwmon
UFS3.0 allows using the ufs device as a temperature sensor. The purpose
of this optional feature is to provide notification to the host of the
UFS device case temperature. It allows reading of a rough estimate
(+-10 degrees centigrade) of the current case temperature, and setting a
lower and upper temperature bounds, in which the device will trigger an
applicable exception event.
A previous attempt [1] tried a comprehensive approach. Still, it was
unsuccessful. Here is a more modest approach that introduces just the
bare minimum to support temperature notification.
Thanks,
Avri
[1] https://lore.kernel.org/lkml/[email protected]/
Avri Altman (2):
scsi: ufs: Probe for temperature notification support
scsi: ufs: Add temperature notification exception handling
drivers/scsi/ufs/Kconfig | 9 ++
drivers/scsi/ufs/Makefile | 1 +
drivers/scsi/ufs/ufs-hwmon.c | 210 +++++++++++++++++++++++++++++++++++
drivers/scsi/ufs/ufs.h | 7 ++
drivers/scsi/ufs/ufshcd.c | 47 ++++++++
drivers/scsi/ufs/ufshcd.h | 20 ++++
6 files changed, 294 insertions(+)
create mode 100644 drivers/scsi/ufs/ufs-hwmon.c
--
2.17.1
The device may notify the host of an extreme temperature by using the
exception event mechanism. The exception can be raised when the device’s
Tcase temperature is either too high or too low.
It is essentially up to the platform to decide what further actions need
to be taken. leave a placeholder for a designated vop for that.
Signed-off-by: Avri Altman <[email protected]>
---
drivers/scsi/ufs/ufs-hwmon.c | 12 ++++++++++++
drivers/scsi/ufs/ufshcd.c | 21 +++++++++++++++++++++
drivers/scsi/ufs/ufshcd.h | 2 ++
3 files changed, 35 insertions(+)
diff --git a/drivers/scsi/ufs/ufs-hwmon.c b/drivers/scsi/ufs/ufs-hwmon.c
index 33b66736aaa4..74855491dc8f 100644
--- a/drivers/scsi/ufs/ufs-hwmon.c
+++ b/drivers/scsi/ufs/ufs-hwmon.c
@@ -196,3 +196,15 @@ void ufs_hwmon_remove(struct ufs_hba *hba)
hba->hwmon_device = NULL;
kfree(data);
}
+
+void ufs_hwmon_notify_event(struct ufs_hba *hba, u8 ee_mask)
+{
+ if (!hba->hwmon_device)
+ return;
+
+ if (ee_mask & MASK_EE_TOO_HIGH_TEMP)
+ hwmon_notify_event(hba->hwmon_device, hwmon_temp, hwmon_temp_max_alarm, 0);
+
+ if (ee_mask & MASK_EE_TOO_LOW_TEMP)
+ hwmon_notify_event(hba->hwmon_device, hwmon_temp, hwmon_temp_min_alarm, 0);
+}
diff --git a/drivers/scsi/ufs/ufshcd.c b/drivers/scsi/ufs/ufshcd.c
index ce22340024ce..debef631c89a 100644
--- a/drivers/scsi/ufs/ufshcd.c
+++ b/drivers/scsi/ufs/ufshcd.c
@@ -5642,6 +5642,24 @@ static void ufshcd_bkops_exception_event_handler(struct ufs_hba *hba)
__func__, err);
}
+static void ufshcd_temp_exception_event_handler(struct ufs_hba *hba, u16 status)
+{
+ u32 value;
+
+ if (ufshcd_query_attr_retry(hba, UPIU_QUERY_OPCODE_READ_ATTR,
+ QUERY_ATTR_IDN_CASE_ROUGH_TEMP, 0, 0, &value))
+ return;
+
+ dev_info(hba->dev, "exception Tcase %d\n", value - 80);
+
+ ufs_hwmon_notify_event(hba, status & MASK_EE_URGENT_TEMP);
+
+ /*
+ * A placeholder for the platform vendors to add whatever additional
+ * steps required
+ */
+}
+
static int __ufshcd_wb_toggle(struct ufs_hba *hba, bool set, enum flag_idn idn)
{
u8 index;
@@ -5821,6 +5839,9 @@ static void ufshcd_exception_event_handler(struct work_struct *work)
if (status & hba->ee_drv_mask & MASK_EE_URGENT_BKOPS)
ufshcd_bkops_exception_event_handler(hba);
+ if (status & hba->ee_drv_mask & MASK_EE_URGENT_TEMP)
+ ufshcd_temp_exception_event_handler(hba, status);
+
ufs_debugfs_exception_event(hba, status);
out:
ufshcd_scsi_unblock_requests(hba);
diff --git a/drivers/scsi/ufs/ufshcd.h b/drivers/scsi/ufs/ufshcd.h
index 021c858955af..92d05329de68 100644
--- a/drivers/scsi/ufs/ufshcd.h
+++ b/drivers/scsi/ufs/ufshcd.h
@@ -1062,9 +1062,11 @@ static inline u8 ufshcd_wb_get_query_index(struct ufs_hba *hba)
#ifdef CONFIG_SCSI_UFS_HWMON
void ufs_hwmon_probe(struct ufs_hba *hba, u8 mask);
void ufs_hwmon_remove(struct ufs_hba *hba);
+void ufs_hwmon_notify_event(struct ufs_hba *hba, u8 ee_mask);
#else
static inline void ufs_hwmon_probe(struct ufs_hba *hba, u8 mask) {}
static inline void ufs_hwmon_remove(struct ufs_hba *hba) {}
+static inline void ufs_hwmon_notify_event(struct ufs_hba *hba, u8 ee_mask) {}
#endif
#ifdef CONFIG_PM
--
2.17.1
On Wed, Sep 15, 2021 at 09:04:07AM +0300, Avri Altman wrote:
> The device may notify the host of an extreme temperature by using the
> exception event mechanism. The exception can be raised when the device’s
> Tcase temperature is either too high or too low.
>
> It is essentially up to the platform to decide what further actions need
> to be taken. leave a placeholder for a designated vop for that.
>
> Signed-off-by: Avri Altman <[email protected]>
Reviewed-by: Guenter Roeck <[email protected]>
> ---
> drivers/scsi/ufs/ufs-hwmon.c | 12 ++++++++++++
> drivers/scsi/ufs/ufshcd.c | 21 +++++++++++++++++++++
> drivers/scsi/ufs/ufshcd.h | 2 ++
> 3 files changed, 35 insertions(+)
>
> diff --git a/drivers/scsi/ufs/ufs-hwmon.c b/drivers/scsi/ufs/ufs-hwmon.c
> index 33b66736aaa4..74855491dc8f 100644
> --- a/drivers/scsi/ufs/ufs-hwmon.c
> +++ b/drivers/scsi/ufs/ufs-hwmon.c
> @@ -196,3 +196,15 @@ void ufs_hwmon_remove(struct ufs_hba *hba)
> hba->hwmon_device = NULL;
> kfree(data);
> }
> +
> +void ufs_hwmon_notify_event(struct ufs_hba *hba, u8 ee_mask)
> +{
> + if (!hba->hwmon_device)
> + return;
> +
> + if (ee_mask & MASK_EE_TOO_HIGH_TEMP)
> + hwmon_notify_event(hba->hwmon_device, hwmon_temp, hwmon_temp_max_alarm, 0);
> +
> + if (ee_mask & MASK_EE_TOO_LOW_TEMP)
> + hwmon_notify_event(hba->hwmon_device, hwmon_temp, hwmon_temp_min_alarm, 0);
> +}
> diff --git a/drivers/scsi/ufs/ufshcd.c b/drivers/scsi/ufs/ufshcd.c
> index ce22340024ce..debef631c89a 100644
> --- a/drivers/scsi/ufs/ufshcd.c
> +++ b/drivers/scsi/ufs/ufshcd.c
> @@ -5642,6 +5642,24 @@ static void ufshcd_bkops_exception_event_handler(struct ufs_hba *hba)
> __func__, err);
> }
>
> +static void ufshcd_temp_exception_event_handler(struct ufs_hba *hba, u16 status)
> +{
> + u32 value;
> +
> + if (ufshcd_query_attr_retry(hba, UPIU_QUERY_OPCODE_READ_ATTR,
> + QUERY_ATTR_IDN_CASE_ROUGH_TEMP, 0, 0, &value))
> + return;
> +
> + dev_info(hba->dev, "exception Tcase %d\n", value - 80);
> +
> + ufs_hwmon_notify_event(hba, status & MASK_EE_URGENT_TEMP);
> +
> + /*
> + * A placeholder for the platform vendors to add whatever additional
> + * steps required
> + */
> +}
> +
> static int __ufshcd_wb_toggle(struct ufs_hba *hba, bool set, enum flag_idn idn)
> {
> u8 index;
> @@ -5821,6 +5839,9 @@ static void ufshcd_exception_event_handler(struct work_struct *work)
> if (status & hba->ee_drv_mask & MASK_EE_URGENT_BKOPS)
> ufshcd_bkops_exception_event_handler(hba);
>
> + if (status & hba->ee_drv_mask & MASK_EE_URGENT_TEMP)
> + ufshcd_temp_exception_event_handler(hba, status);
> +
> ufs_debugfs_exception_event(hba, status);
> out:
> ufshcd_scsi_unblock_requests(hba);
> diff --git a/drivers/scsi/ufs/ufshcd.h b/drivers/scsi/ufs/ufshcd.h
> index 021c858955af..92d05329de68 100644
> --- a/drivers/scsi/ufs/ufshcd.h
> +++ b/drivers/scsi/ufs/ufshcd.h
> @@ -1062,9 +1062,11 @@ static inline u8 ufshcd_wb_get_query_index(struct ufs_hba *hba)
> #ifdef CONFIG_SCSI_UFS_HWMON
> void ufs_hwmon_probe(struct ufs_hba *hba, u8 mask);
> void ufs_hwmon_remove(struct ufs_hba *hba);
> +void ufs_hwmon_notify_event(struct ufs_hba *hba, u8 ee_mask);
> #else
> static inline void ufs_hwmon_probe(struct ufs_hba *hba, u8 mask) {}
> static inline void ufs_hwmon_remove(struct ufs_hba *hba) {}
> +static inline void ufs_hwmon_notify_event(struct ufs_hba *hba, u8 ee_mask) {}
> #endif
>
> #ifdef CONFIG_PM
> --
> 2.17.1
>
On Wed, 2021-09-15 at 09:04 +0300, Avri Altman wrote:
> The device may notify the host of an extreme temperature by using the
>
> exception event mechanism. The exception can be raised when the
> device’s
>
> Tcase temperature is either too high or too low.
>
>
>
> It is essentially up to the platform to decide what further actions
> need
>
> to be taken. leave a placeholder for a designated vop for that.
>
>
>
> Signed-off-by: Avri Altman <[email protected]>
Reviewed-by: Bean Huo <[email protected]>
Hi Avri,
>The device may notify the host of an extreme temperature by using the
>exception event mechanism. The exception can be raised when the device’s
>Tcase temperature is either too high or too low.
>
>It is essentially up to the platform to decide what further actions need
>to be taken. leave a placeholder for a designated vop for that.
>
>Signed-off-by: Avri Altman <[email protected]>
Reviewed-by: Daejun Park <[email protected]>
Avri,
> UFS3.0 allows using the ufs device as a temperature sensor. The purpose
> of this optional feature is to provide notification to the host of the
> UFS device case temperature. It allows reading of a rough estimate
> (+-10 degrees centigrade) of the current case temperature, and setting a
> lower and upper temperature bounds, in which the device will trigger an
> applicable exception event.
Applied to 5.16/scsi-staging, thanks!
--
Martin K. Petersen Oracle Linux Engineering
On Wed, 15 Sep 2021 09:04:05 +0300, Avri Altman wrote:
> v6 -> v7:
> - some more useless initializations
>
> v5 -> v6:
> - remove useless initializations
>
> v4 - > v5:
> - Fix improper return error values
>
> [...]
Applied to 5.16/scsi-queue, thanks!
[1/2] scsi: ufs: Probe for temperature notification support
https://git.kernel.org/mkp/scsi/c/e88e2d32200a
[2/2] scsi: ufs: Add temperature notification exception handling
https://git.kernel.org/mkp/scsi/c/322c4b29ee1f
--
Martin K. Petersen Oracle Linux Engineering