linux-kernel.vger.kernel.org archive mirror
 help / color / mirror / Atom feed
* [PATCH v2 0/2] Add temperature notification support
@ 2021-09-09  6:34 Avri Altman
  2021-09-09  6:34 ` [PATCH v2 1/2] scsi: ufs: Probe for " Avri Altman
  2021-09-09  6:34 ` [PATCH v2 2/2] scsi: ufs: Add temperature notification exception handling Avri Altman
  0 siblings, 2 replies; 9+ messages in thread
From: Avri Altman @ 2021-09-09  6:34 UTC (permalink / raw)
  To: James E . J . Bottomley, Martin K . Petersen
  Cc: linux-scsi, linux-kernel, Bart Van Assche, Adrian Hunter,
	Bean Huo, Guenter Roeck, Avri Altman

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/1582450522-13256-1-git-send-email-avi.shchislowski@wdc.com/

Avri Altman (2):
  scsi: ufs: Probe for temperature notification support
  scsi: ufs: Add temperature notification exception handling

 drivers/scsi/ufs/Kconfig     |  10 ++
 drivers/scsi/ufs/Makefile    |   1 +
 drivers/scsi/ufs/ufs-hwmon.c | 180 +++++++++++++++++++++++++++++++++++
 drivers/scsi/ufs/ufs.h       |   8 ++
 drivers/scsi/ufs/ufshcd.c    |  46 +++++++++
 drivers/scsi/ufs/ufshcd.h    |  18 ++++
 6 files changed, 263 insertions(+)
 create mode 100644 drivers/scsi/ufs/ufs-hwmon.c

-- 
2.17.1


^ permalink raw reply	[flat|nested] 9+ messages in thread

* [PATCH v2 1/2] scsi: ufs: Probe for temperature notification support
  2021-09-09  6:34 [PATCH v2 0/2] Add temperature notification support Avri Altman
@ 2021-09-09  6:34 ` Avri Altman
  2021-09-09 16:26   ` Bart Van Assche
  2021-09-09 16:51   ` Guenter Roeck
  2021-09-09  6:34 ` [PATCH v2 2/2] scsi: ufs: Add temperature notification exception handling Avri Altman
  1 sibling, 2 replies; 9+ messages in thread
From: Avri Altman @ 2021-09-09  6:34 UTC (permalink / raw)
  To: James E . J . Bottomley, Martin K . Petersen
  Cc: linux-scsi, linux-kernel, Bart Van Assche, Adrian Hunter,
	Bean Huo, Guenter Roeck, Avri Altman

Probe the dExtendedUFSFeaturesSupport register for the device's
temperature notification support, and if supported, add a hw monitor
device.

Signed-off-by: Avri Altman <avri.altman@wdc.com>
---
 drivers/scsi/ufs/Kconfig     |  10 ++
 drivers/scsi/ufs/Makefile    |   1 +
 drivers/scsi/ufs/ufs-hwmon.c | 180 +++++++++++++++++++++++++++++++++++
 drivers/scsi/ufs/ufs.h       |   6 ++
 drivers/scsi/ufs/ufshcd.c    |  27 ++++++
 drivers/scsi/ufs/ufshcd.h    |  18 ++++
 6 files changed, 242 insertions(+)
 create mode 100644 drivers/scsi/ufs/ufs-hwmon.c

diff --git a/drivers/scsi/ufs/Kconfig b/drivers/scsi/ufs/Kconfig
index 432df76e6318..b930f29fc375 100644
--- a/drivers/scsi/ufs/Kconfig
+++ b/drivers/scsi/ufs/Kconfig
@@ -199,3 +199,13 @@ config SCSI_UFS_FAULT_INJECTION
 	help
 	  Enable fault injection support in the UFS driver. This makes it easier
 	  to test the UFS error handler and abort handler.
+
+config SCSI_UFS_HWMON
+	bool "UFS  Temperature Notification"
+	depends on SCSI_UFSHCD && HWMON
+	help
+	  This provides support for UFS hardware monitoring. If enabled,
+	  a hardware monitoring device will be created for the UFS device.
+
+	  If unsure, say N.
+
diff --git a/drivers/scsi/ufs/Makefile b/drivers/scsi/ufs/Makefile
index c407da9b5171..966048875b50 100644
--- a/drivers/scsi/ufs/Makefile
+++ b/drivers/scsi/ufs/Makefile
@@ -10,6 +10,7 @@ ufshcd-core-$(CONFIG_SCSI_UFS_BSG)	+= ufs_bsg.o
 ufshcd-core-$(CONFIG_SCSI_UFS_CRYPTO)	+= ufshcd-crypto.o
 ufshcd-core-$(CONFIG_SCSI_UFS_HPB)	+= ufshpb.o
 ufshcd-core-$(CONFIG_SCSI_UFS_FAULT_INJECTION) += ufs-fault-injection.o
+ufshcd-core-$(CONFIG_SCSI_UFS_HWMON) += ufs-hwmon.o
 
 obj-$(CONFIG_SCSI_UFS_DWC_TC_PCI) += tc-dwc-g210-pci.o ufshcd-dwc.o tc-dwc-g210.o
 obj-$(CONFIG_SCSI_UFS_DWC_TC_PLATFORM) += tc-dwc-g210-pltfrm.o ufshcd-dwc.o tc-dwc-g210.o
diff --git a/drivers/scsi/ufs/ufs-hwmon.c b/drivers/scsi/ufs/ufs-hwmon.c
new file mode 100644
index 000000000000..159678ce89ce
--- /dev/null
+++ b/drivers/scsi/ufs/ufs-hwmon.c
@@ -0,0 +1,180 @@
+// SPDX-License-Identifier: GPL-2.0
+/*
+ * UFS hardware monitoring support
+ * Copyright (c) 2021, Western Digital Corporation
+ */
+
+#include <linux/hwmon.h>
+
+#include "ufshcd.h"
+
+struct ufs_hwmon_data {
+	struct ufs_hba *hba;
+	u8 mask;
+};
+
+static bool ufs_temp_enabled(struct ufs_hba *hba, struct ufs_hwmon_data *data)
+{
+	u32 ee_mask;
+
+	if (ufshcd_query_attr(hba, UPIU_QUERY_OPCODE_READ_ATTR,
+			      QUERY_ATTR_IDN_EE_CONTROL, 0, 0, &ee_mask))
+		return false;
+
+	return (data->mask & ee_mask & MASK_EE_TOO_HIGH_TEMP) ||
+		(data->mask & ee_mask & MASK_EE_TOO_LOW_TEMP);
+}
+
+static bool ufs_temp_valid(struct ufs_hba *hba, struct ufs_hwmon_data *data,
+			   enum attr_idn idn, u32 value)
+{
+	return (idn == QUERY_ATTR_IDN_CASE_ROUGH_TEMP && value >= 1 &&
+		value <= 250 && ufs_temp_enabled(hba, data)) ||
+	      (idn == QUERY_ATTR_IDN_HIGH_TEMP_BOUND && value >= 100 &&
+	       value <= 250) ||
+	      (idn == QUERY_ATTR_IDN_LOW_TEMP_BOUND && value >= 1 &&
+	       value <= 80);
+}
+
+static int ufs_get_temp(struct ufs_hba *hba, struct ufs_hwmon_data *data,
+			enum attr_idn idn)
+{
+	u32 value;
+
+	if (ufshcd_query_attr(hba, UPIU_QUERY_OPCODE_READ_ATTR, idn, 0, 0,
+	    &value))
+		return 0;
+
+	if (ufs_temp_valid(hba, data, idn, value))
+		return value - 80;
+
+	return 0;
+}
+
+static int ufs_hwmon_read(struct device *dev, enum hwmon_sensor_types type,
+			   u32 attr, int channel, long *val)
+{
+	struct ufs_hwmon_data *data = dev_get_drvdata(dev);
+	struct ufs_hba *hba = data->hba;
+	int err = 0;
+	bool get_temp = true;
+
+	if (type != hwmon_temp)
+		return 0;
+
+	down(&hba->host_sem);
+
+	if (!ufshcd_is_user_access_allowed(hba)) {
+		up(&hba->host_sem);
+		return -EBUSY;
+	}
+
+	ufshcd_rpm_get_sync(hba);
+
+	switch (attr) {
+	case hwmon_temp_enable:
+		*val = ufs_temp_enabled(hba, data);
+		get_temp = false;
+
+		break;
+	case hwmon_temp_max_alarm:
+		*val = ufs_get_temp(hba, data, QUERY_ATTR_IDN_HIGH_TEMP_BOUND);
+
+		break;
+	case hwmon_temp_min_alarm:
+		*val = ufs_get_temp(hba, data, QUERY_ATTR_IDN_LOW_TEMP_BOUND);
+
+		break;
+	case hwmon_temp_input:
+		*val = ufs_get_temp(hba, data, QUERY_ATTR_IDN_CASE_ROUGH_TEMP);
+
+		break;
+	default:
+		err = -EOPNOTSUPP;
+
+		break;
+	}
+
+	ufshcd_rpm_put_sync(hba);
+
+	up(&hba->host_sem);
+
+	if (get_temp && !err && *val == 0)
+		err = -EINVAL;
+
+	return err;
+}
+
+static umode_t ufs_hwmon_is_visible(const void *_data,
+				     enum hwmon_sensor_types type,
+				     u32 attr, int channel)
+{
+	if (type != hwmon_temp)
+		return 0;
+
+	switch (attr) {
+	case hwmon_temp_enable:
+	case hwmon_temp_max_alarm:
+	case hwmon_temp_min_alarm:
+	case hwmon_temp_input:
+		return 0444;
+	default:
+		break;
+	}
+	return 0;
+}
+
+static const struct hwmon_channel_info *ufs_hwmon_info[] = {
+	HWMON_CHANNEL_INFO(temp, HWMON_T_ENABLE | HWMON_T_INPUT |
+			    HWMON_T_MIN_ALARM | HWMON_T_MAX_ALARM),
+	NULL
+};
+
+static const struct hwmon_ops ufs_hwmon_ops = {
+	.is_visible	= ufs_hwmon_is_visible,
+	.read		= ufs_hwmon_read,
+};
+
+static const struct hwmon_chip_info ufs_hwmon_hba_info = {
+	.ops	= &ufs_hwmon_ops,
+	.info	= ufs_hwmon_info,
+};
+
+int ufs_hwmon_probe(struct ufs_hba *hba, u8 mask)
+{
+	struct device *dev = hba->dev;
+	struct ufs_hwmon_data *data;
+	struct device *hwmon;
+
+	data = kzalloc(sizeof(*data), GFP_KERNEL);
+	if (!data)
+		return 0;
+
+	data->hba = hba;
+	data->mask = mask;
+
+	hwmon = hwmon_device_register_with_info(dev, "ufs",
+						data, &ufs_hwmon_hba_info,
+						NULL);
+	if (IS_ERR(hwmon)) {
+		dev_warn(dev, "Failed to instantiate hwmon device\n");
+		kfree(data);
+		return PTR_ERR(hwmon);
+	}
+
+	hba->hwmon_device = hwmon;
+
+	return 0;
+}
+
+void ufs_hwmon_remove(struct ufs_hba *hba)
+{
+	if (hba->hwmon_device) {
+		struct ufs_hwmon_data *data =
+			dev_get_drvdata(hba->hwmon_device);
+
+		hwmon_device_unregister(hba->hwmon_device);
+		hba->hwmon_device = NULL;
+		kfree(data);
+	}
+}
diff --git a/drivers/scsi/ufs/ufs.h b/drivers/scsi/ufs/ufs.h
index 8c6b38b1b142..171b27be7b1d 100644
--- a/drivers/scsi/ufs/ufs.h
+++ b/drivers/scsi/ufs/ufs.h
@@ -152,6 +152,9 @@ enum attr_idn {
 	QUERY_ATTR_IDN_PSA_STATE		= 0x15,
 	QUERY_ATTR_IDN_PSA_DATA_SIZE		= 0x16,
 	QUERY_ATTR_IDN_REF_CLK_GATING_WAIT_TIME	= 0x17,
+	QUERY_ATTR_IDN_CASE_ROUGH_TEMP          = 0x18,
+	QUERY_ATTR_IDN_HIGH_TEMP_BOUND          = 0x19,
+	QUERY_ATTR_IDN_LOW_TEMP_BOUND           = 0x1A,
 	QUERY_ATTR_IDN_WB_FLUSH_STATUS	        = 0x1C,
 	QUERY_ATTR_IDN_AVAIL_WB_BUFF_SIZE       = 0x1D,
 	QUERY_ATTR_IDN_WB_BUFF_LIFE_TIME_EST    = 0x1E,
@@ -338,6 +341,9 @@ enum {
 
 /* Possible values for dExtendedUFSFeaturesSupport */
 enum {
+	UFS_DEV_LOW_TEMP_NOTIF		= BIT(4),
+	UFS_DEV_HIGH_TEMP_NOTIF		= BIT(5),
+	UFS_DEV_EXT_TEMP_NOTIF		= BIT(6),
 	UFS_DEV_HPB_SUPPORT		= BIT(7),
 	UFS_DEV_WRITE_BOOSTER_SUP	= BIT(8),
 };
diff --git a/drivers/scsi/ufs/ufshcd.c b/drivers/scsi/ufs/ufshcd.c
index 3841ab49f556..fc995bf1f296 100644
--- a/drivers/scsi/ufs/ufshcd.c
+++ b/drivers/scsi/ufs/ufshcd.c
@@ -7469,6 +7469,31 @@ static void ufshcd_wb_probe(struct ufs_hba *hba, u8 *desc_buf)
 	hba->caps &= ~UFSHCD_CAP_WB_EN;
 }
 
+static void ufshcd_temp_notif_probe(struct ufs_hba *hba, u8 *desc_buf)
+{
+	struct ufs_dev_info *dev_info = &hba->dev_info;
+	u32 ext_ufs_feature;
+	u8 mask = 0;
+
+	if (!(hba->caps & UFSHCD_CAP_TEMP_NOTIF) ||
+	    dev_info->wspecversion < 0x300)
+		return;
+
+	ext_ufs_feature = get_unaligned_be32(desc_buf +
+					DEVICE_DESC_PARAM_EXT_UFS_FEATURE_SUP);
+
+	if (ext_ufs_feature & UFS_DEV_LOW_TEMP_NOTIF)
+		mask |= MASK_EE_TOO_LOW_TEMP;
+
+	if (ext_ufs_feature & UFS_DEV_HIGH_TEMP_NOTIF)
+		mask |= MASK_EE_TOO_HIGH_TEMP;
+
+	if (mask) {
+		ufshcd_enable_ee(hba, mask);
+		ufs_hwmon_probe(hba, mask);
+	}
+}
+
 void ufshcd_fixup_dev_quirks(struct ufs_hba *hba, struct ufs_dev_fix *fixups)
 {
 	struct ufs_dev_fix *f;
@@ -7564,6 +7589,8 @@ static int ufs_get_device_desc(struct ufs_hba *hba)
 
 	ufshcd_wb_probe(hba, desc_buf);
 
+	ufshcd_temp_notif_probe(hba, desc_buf);
+
 	/*
 	 * ufshcd_read_string_desc returns size of the string
 	 * reset the error value
diff --git a/drivers/scsi/ufs/ufshcd.h b/drivers/scsi/ufs/ufshcd.h
index 52ea6f350b18..9bc434c4ae71 100644
--- a/drivers/scsi/ufs/ufshcd.h
+++ b/drivers/scsi/ufs/ufshcd.h
@@ -653,6 +653,12 @@ enum ufshcd_caps {
 	 * in order to exit DeepSleep state.
 	 */
 	UFSHCD_CAP_DEEPSLEEP				= 1 << 10,
+
+	/*
+	 * This capability allows the host controller driver to use temperature
+	 * notification if it is supported by the UFS device.
+	 */
+	UFSHCD_CAP_TEMP_NOTIF				= 1 << 11,
 };
 
 struct ufs_hba_variant_params {
@@ -789,6 +795,10 @@ struct ufs_hba {
 	struct scsi_device *sdev_ufs_device;
 	struct scsi_device *sdev_rpmb;
 
+#ifdef CONFIG_SCSI_UFS_HWMON
+	struct device *hwmon_device;
+#endif
+
 	enum ufs_dev_pwr_mode curr_dev_pwr_mode;
 	enum uic_link_state uic_link_state;
 	/* Desired UFS power management level during runtime PM */
@@ -1049,6 +1059,14 @@ static inline u8 ufshcd_wb_get_query_index(struct ufs_hba *hba)
 	return 0;
 }
 
+#ifdef CONFIG_SCSI_UFS_HWMON
+int ufs_hwmon_probe(struct ufs_hba *hba, u8 mask);
+void ufs_hwmon_remove(struct ufs_hba *hba);
+#else
+static inline int ufs_hwmon_probe(struct ufs_hba *hba, u8 mask) { return 0; }
+static inline void nvme_hwmon_remove(struct ufs_hba *hba) {}
+#endif
+
 #ifdef CONFIG_PM
 extern int ufshcd_runtime_suspend(struct device *dev);
 extern int ufshcd_runtime_resume(struct device *dev);
-- 
2.17.1


^ permalink raw reply related	[flat|nested] 9+ messages in thread

* [PATCH v2 2/2] scsi: ufs: Add temperature notification exception handling
  2021-09-09  6:34 [PATCH v2 0/2] Add temperature notification support Avri Altman
  2021-09-09  6:34 ` [PATCH v2 1/2] scsi: ufs: Probe for " Avri Altman
@ 2021-09-09  6:34 ` Avri Altman
  2021-09-09 16:54   ` Guenter Roeck
  1 sibling, 1 reply; 9+ messages in thread
From: Avri Altman @ 2021-09-09  6:34 UTC (permalink / raw)
  To: James E . J . Bottomley, Martin K . Petersen
  Cc: linux-scsi, linux-kernel, Bart Van Assche, Adrian Hunter,
	Bean Huo, Guenter Roeck, Avri Altman

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 <avri.altman@wdc.com>
---
 drivers/scsi/ufs/ufs.h    |  2 ++
 drivers/scsi/ufs/ufshcd.c | 19 +++++++++++++++++++
 2 files changed, 21 insertions(+)

diff --git a/drivers/scsi/ufs/ufs.h b/drivers/scsi/ufs/ufs.h
index 171b27be7b1d..d9bc048c2a71 100644
--- a/drivers/scsi/ufs/ufs.h
+++ b/drivers/scsi/ufs/ufs.h
@@ -377,6 +377,8 @@ enum {
 	MASK_EE_PERFORMANCE_THROTTLING	= BIT(6),
 };
 
+#define MASK_EE_URGENT_TEMP (MASK_EE_TOO_HIGH_TEMP | MASK_EE_TOO_LOW_TEMP)
+
 /* Background operation status */
 enum bkops_status {
 	BKOPS_STATUS_NO_OP               = 0x0,
diff --git a/drivers/scsi/ufs/ufshcd.c b/drivers/scsi/ufs/ufshcd.c
index fc995bf1f296..1f61e8090220 100644
--- a/drivers/scsi/ufs/ufshcd.c
+++ b/drivers/scsi/ufs/ufshcd.c
@@ -5642,6 +5642,22 @@ 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(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);
+
+	/*
+	 * 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 +5837,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);
-- 
2.17.1


^ permalink raw reply related	[flat|nested] 9+ messages in thread

* Re: [PATCH v2 1/2] scsi: ufs: Probe for temperature notification support
  2021-09-09  6:34 ` [PATCH v2 1/2] scsi: ufs: Probe for " Avri Altman
@ 2021-09-09 16:26   ` Bart Van Assche
  2021-09-10 15:58     ` Avri Altman
  2021-09-09 16:51   ` Guenter Roeck
  1 sibling, 1 reply; 9+ messages in thread
From: Bart Van Assche @ 2021-09-09 16:26 UTC (permalink / raw)
  To: Avri Altman, James E . J . Bottomley, Martin K . Petersen
  Cc: linux-scsi, linux-kernel, Adrian Hunter, Bean Huo, Guenter Roeck

On 9/8/21 11:34 PM, Avri Altman wrote:
> +static bool ufs_temp_enabled(struct ufs_hba *hba, struct ufs_hwmon_data *data)
> +{
> +	u32 ee_mask;
> +
> +	if (ufshcd_query_attr(hba, UPIU_QUERY_OPCODE_READ_ATTR,
> +			      QUERY_ATTR_IDN_EE_CONTROL, 0, 0, &ee_mask))
> +		return false;
> +
> +	return (data->mask & ee_mask & MASK_EE_TOO_HIGH_TEMP) ||
> +		(data->mask & ee_mask & MASK_EE_TOO_LOW_TEMP);
> +}

The above function uses data->mask but not data so it's probably better to pass
data->mask directly as the second argument.

> +static bool ufs_temp_valid(struct ufs_hba *hba, struct ufs_hwmon_data *data,
> +			   enum attr_idn idn, u32 value)
> +{
> +	return (idn == QUERY_ATTR_IDN_CASE_ROUGH_TEMP && value >= 1 &&
> +		value <= 250 && ufs_temp_enabled(hba, data)) ||
> +	      (idn == QUERY_ATTR_IDN_HIGH_TEMP_BOUND && value >= 100 &&
> +	       value <= 250) ||
> +	      (idn == QUERY_ATTR_IDN_LOW_TEMP_BOUND && value >= 1 &&
> +	       value <= 80);
> +}

Same comment for this function - if the above comment is addressed 'mask' can be
passed as an argument instead of 'data'.

> +static int ufs_get_temp(struct ufs_hba *hba, struct ufs_hwmon_data *data,
> +			enum attr_idn idn)
> +{
> +	u32 value;
> +
> +	if (ufshcd_query_attr(hba, UPIU_QUERY_OPCODE_READ_ATTR, idn, 0, 0,
> +	    &value))
> +		return 0;
> +
> +	if (ufs_temp_valid(hba, data, idn, value))
> +		return value - 80;
> +
> +	return 0;
> +}

Same comment here.

> +void ufs_hwmon_remove(struct ufs_hba *hba)
> +{
> +	if (hba->hwmon_device) {
> +		struct ufs_hwmon_data *data =
> +			dev_get_drvdata(hba->hwmon_device);
> +
> +		hwmon_device_unregister(hba->hwmon_device);
> +		hba->hwmon_device = NULL;
> +		kfree(data);
> +	}
> +}

Please use the "early return" style since that is the most widely used style
in the Linux kernel (if (!hba->hwmon_device) return).

Thanks,

Bart.

^ permalink raw reply	[flat|nested] 9+ messages in thread

* Re: [PATCH v2 1/2] scsi: ufs: Probe for temperature notification support
  2021-09-09  6:34 ` [PATCH v2 1/2] scsi: ufs: Probe for " Avri Altman
  2021-09-09 16:26   ` Bart Van Assche
@ 2021-09-09 16:51   ` Guenter Roeck
  2021-09-10 16:13     ` Avri Altman
  1 sibling, 1 reply; 9+ messages in thread
From: Guenter Roeck @ 2021-09-09 16:51 UTC (permalink / raw)
  To: Avri Altman
  Cc: James E . J . Bottomley, Martin K . Petersen, linux-scsi,
	linux-kernel, Bart Van Assche, Adrian Hunter, Bean Huo

On Thu, Sep 09, 2021 at 09:34:43AM +0300, Avri Altman wrote:
> Probe the dExtendedUFSFeaturesSupport register for the device's
> temperature notification support, and if supported, add a hw monitor
> device.
> 
> Signed-off-by: Avri Altman <avri.altman@wdc.com>
> ---
>  drivers/scsi/ufs/Kconfig     |  10 ++
>  drivers/scsi/ufs/Makefile    |   1 +
>  drivers/scsi/ufs/ufs-hwmon.c | 180 +++++++++++++++++++++++++++++++++++
>  drivers/scsi/ufs/ufs.h       |   6 ++
>  drivers/scsi/ufs/ufshcd.c    |  27 ++++++
>  drivers/scsi/ufs/ufshcd.h    |  18 ++++
>  6 files changed, 242 insertions(+)
>  create mode 100644 drivers/scsi/ufs/ufs-hwmon.c
> 
> diff --git a/drivers/scsi/ufs/Kconfig b/drivers/scsi/ufs/Kconfig
> index 432df76e6318..b930f29fc375 100644
> --- a/drivers/scsi/ufs/Kconfig
> +++ b/drivers/scsi/ufs/Kconfig
> @@ -199,3 +199,13 @@ config SCSI_UFS_FAULT_INJECTION
>  	help
>  	  Enable fault injection support in the UFS driver. This makes it easier
>  	  to test the UFS error handler and abort handler.
> +
> +config SCSI_UFS_HWMON
> +	bool "UFS  Temperature Notification"
> +	depends on SCSI_UFSHCD && HWMON
> +	help
> +	  This provides support for UFS hardware monitoring. If enabled,
> +	  a hardware monitoring device will be created for the UFS device.
> +
> +	  If unsure, say N.
> +
> diff --git a/drivers/scsi/ufs/Makefile b/drivers/scsi/ufs/Makefile
> index c407da9b5171..966048875b50 100644
> --- a/drivers/scsi/ufs/Makefile
> +++ b/drivers/scsi/ufs/Makefile
> @@ -10,6 +10,7 @@ ufshcd-core-$(CONFIG_SCSI_UFS_BSG)	+= ufs_bsg.o
>  ufshcd-core-$(CONFIG_SCSI_UFS_CRYPTO)	+= ufshcd-crypto.o
>  ufshcd-core-$(CONFIG_SCSI_UFS_HPB)	+= ufshpb.o
>  ufshcd-core-$(CONFIG_SCSI_UFS_FAULT_INJECTION) += ufs-fault-injection.o
> +ufshcd-core-$(CONFIG_SCSI_UFS_HWMON) += ufs-hwmon.o
>  
>  obj-$(CONFIG_SCSI_UFS_DWC_TC_PCI) += tc-dwc-g210-pci.o ufshcd-dwc.o tc-dwc-g210.o
>  obj-$(CONFIG_SCSI_UFS_DWC_TC_PLATFORM) += tc-dwc-g210-pltfrm.o ufshcd-dwc.o tc-dwc-g210.o
> diff --git a/drivers/scsi/ufs/ufs-hwmon.c b/drivers/scsi/ufs/ufs-hwmon.c
> new file mode 100644
> index 000000000000..159678ce89ce
> --- /dev/null
> +++ b/drivers/scsi/ufs/ufs-hwmon.c
> @@ -0,0 +1,180 @@
> +// SPDX-License-Identifier: GPL-2.0
> +/*
> + * UFS hardware monitoring support
> + * Copyright (c) 2021, Western Digital Corporation
> + */
> +
> +#include <linux/hwmon.h>
> +
> +#include "ufshcd.h"
> +
> +struct ufs_hwmon_data {
> +	struct ufs_hba *hba;
> +	u8 mask;
> +};
> +
> +static bool ufs_temp_enabled(struct ufs_hba *hba, struct ufs_hwmon_data *data)
> +{
> +	u32 ee_mask;
> +
> +	if (ufshcd_query_attr(hba, UPIU_QUERY_OPCODE_READ_ATTR,
> +			      QUERY_ATTR_IDN_EE_CONTROL, 0, 0, &ee_mask))
> +		return false;
> +
> +	return (data->mask & ee_mask & MASK_EE_TOO_HIGH_TEMP) ||
> +		(data->mask & ee_mask & MASK_EE_TOO_LOW_TEMP);
> +}
> +
> +static bool ufs_temp_valid(struct ufs_hba *hba, struct ufs_hwmon_data *data,
> +			   enum attr_idn idn, u32 value)
> +{
> +	return (idn == QUERY_ATTR_IDN_CASE_ROUGH_TEMP && value >= 1 &&
> +		value <= 250 && ufs_temp_enabled(hba, data)) ||
> +	      (idn == QUERY_ATTR_IDN_HIGH_TEMP_BOUND && value >= 100 &&
> +	       value <= 250) ||
> +	      (idn == QUERY_ATTR_IDN_LOW_TEMP_BOUND && value >= 1 &&
> +	       value <= 80);
> +}
> +
> +static int ufs_get_temp(struct ufs_hba *hba, struct ufs_hwmon_data *data,
> +			enum attr_idn idn)
> +{
> +	u32 value;
> +
> +	if (ufshcd_query_attr(hba, UPIU_QUERY_OPCODE_READ_ATTR, idn, 0, 0,
> +	    &value))
> +		return 0;
> +
> +	if (ufs_temp_valid(hba, data, idn, value))
> +		return value - 80;
> +
> +	return 0;
> +}
> +
> +static int ufs_hwmon_read(struct device *dev, enum hwmon_sensor_types type,
> +			   u32 attr, int channel, long *val)
> +{
> +	struct ufs_hwmon_data *data = dev_get_drvdata(dev);
> +	struct ufs_hba *hba = data->hba;
> +	int err = 0;
> +	bool get_temp = true;
> +
> +	if (type != hwmon_temp)
> +		return 0;
> +
> +	down(&hba->host_sem);
> +
> +	if (!ufshcd_is_user_access_allowed(hba)) {
> +		up(&hba->host_sem);
> +		return -EBUSY;
> +	}
> +
> +	ufshcd_rpm_get_sync(hba);
> +
> +	switch (attr) {
> +	case hwmon_temp_enable:
> +		*val = ufs_temp_enabled(hba, data);
> +		get_temp = false;
> +
> +		break;
> +	case hwmon_temp_max_alarm:
> +		*val = ufs_get_temp(hba, data, QUERY_ATTR_IDN_HIGH_TEMP_BOUND);
> +
> +		break;
> +	case hwmon_temp_min_alarm:
> +		*val = ufs_get_temp(hba, data, QUERY_ATTR_IDN_LOW_TEMP_BOUND);
> +
> +		break;
> +	case hwmon_temp_input:
> +		*val = ufs_get_temp(hba, data, QUERY_ATTR_IDN_CASE_ROUGH_TEMP);
> +
> +		break;
> +	default:
> +		err = -EOPNOTSUPP;
> +
> +		break;
> +	}
> +
> +	ufshcd_rpm_put_sync(hba);
> +
> +	up(&hba->host_sem);
> +
> +	if (get_temp && !err && *val == 0)
> +		err = -EINVAL;
> +
> +	return err;
> +}
> +
> +static umode_t ufs_hwmon_is_visible(const void *_data,
> +				     enum hwmon_sensor_types type,
> +				     u32 attr, int channel)
> +{
> +	if (type != hwmon_temp)
> +		return 0;
> +
> +	switch (attr) {
> +	case hwmon_temp_enable:
> +	case hwmon_temp_max_alarm:
> +	case hwmon_temp_min_alarm:
> +	case hwmon_temp_input:
> +		return 0444;
> +	default:
> +		break;
> +	}
> +	return 0;
> +}
> +
> +static const struct hwmon_channel_info *ufs_hwmon_info[] = {
> +	HWMON_CHANNEL_INFO(temp, HWMON_T_ENABLE | HWMON_T_INPUT |
> +			    HWMON_T_MIN_ALARM | HWMON_T_MAX_ALARM),
> +	NULL
> +};
> +
> +static const struct hwmon_ops ufs_hwmon_ops = {
> +	.is_visible	= ufs_hwmon_is_visible,
> +	.read		= ufs_hwmon_read,
> +};
> +
> +static const struct hwmon_chip_info ufs_hwmon_hba_info = {
> +	.ops	= &ufs_hwmon_ops,
> +	.info	= ufs_hwmon_info,
> +};
> +
> +int ufs_hwmon_probe(struct ufs_hba *hba, u8 mask)
> +{
> +	struct device *dev = hba->dev;
> +	struct ufs_hwmon_data *data;
> +	struct device *hwmon;
> +
> +	data = kzalloc(sizeof(*data), GFP_KERNEL);
> +	if (!data)
> +		return 0;
> +
> +	data->hba = hba;
> +	data->mask = mask;
> +
> +	hwmon = hwmon_device_register_with_info(dev, "ufs",
> +						data, &ufs_hwmon_hba_info,
> +						NULL);
> +	if (IS_ERR(hwmon)) {
> +		dev_warn(dev, "Failed to instantiate hwmon device\n");
> +		kfree(data);
> +		return PTR_ERR(hwmon);

If the error is ignored by the caller, it doesn't make sense
to return it.

> +	}
> +
> +	hba->hwmon_device = hwmon;
> +
> +	return 0;
> +}
> +
> +void ufs_hwmon_remove(struct ufs_hba *hba)
> +{
> +	if (hba->hwmon_device) {
> +		struct ufs_hwmon_data *data =
> +			dev_get_drvdata(hba->hwmon_device);
> +
> +		hwmon_device_unregister(hba->hwmon_device);
> +		hba->hwmon_device = NULL;
> +		kfree(data);
> +	}
> +}

That function is never called and thus pointless (suggesting that there may be 
some structural problem in the code).

> diff --git a/drivers/scsi/ufs/ufs.h b/drivers/scsi/ufs/ufs.h
> index 8c6b38b1b142..171b27be7b1d 100644
> --- a/drivers/scsi/ufs/ufs.h
> +++ b/drivers/scsi/ufs/ufs.h
> @@ -152,6 +152,9 @@ enum attr_idn {
>  	QUERY_ATTR_IDN_PSA_STATE		= 0x15,
>  	QUERY_ATTR_IDN_PSA_DATA_SIZE		= 0x16,
>  	QUERY_ATTR_IDN_REF_CLK_GATING_WAIT_TIME	= 0x17,
> +	QUERY_ATTR_IDN_CASE_ROUGH_TEMP          = 0x18,
> +	QUERY_ATTR_IDN_HIGH_TEMP_BOUND          = 0x19,
> +	QUERY_ATTR_IDN_LOW_TEMP_BOUND           = 0x1A,
>  	QUERY_ATTR_IDN_WB_FLUSH_STATUS	        = 0x1C,
>  	QUERY_ATTR_IDN_AVAIL_WB_BUFF_SIZE       = 0x1D,
>  	QUERY_ATTR_IDN_WB_BUFF_LIFE_TIME_EST    = 0x1E,
> @@ -338,6 +341,9 @@ enum {
>  
>  /* Possible values for dExtendedUFSFeaturesSupport */
>  enum {
> +	UFS_DEV_LOW_TEMP_NOTIF		= BIT(4),
> +	UFS_DEV_HIGH_TEMP_NOTIF		= BIT(5),
> +	UFS_DEV_EXT_TEMP_NOTIF		= BIT(6),
>  	UFS_DEV_HPB_SUPPORT		= BIT(7),
>  	UFS_DEV_WRITE_BOOSTER_SUP	= BIT(8),
>  };
> diff --git a/drivers/scsi/ufs/ufshcd.c b/drivers/scsi/ufs/ufshcd.c
> index 3841ab49f556..fc995bf1f296 100644
> --- a/drivers/scsi/ufs/ufshcd.c
> +++ b/drivers/scsi/ufs/ufshcd.c
> @@ -7469,6 +7469,31 @@ static void ufshcd_wb_probe(struct ufs_hba *hba, u8 *desc_buf)
>  	hba->caps &= ~UFSHCD_CAP_WB_EN;
>  }
>  
> +static void ufshcd_temp_notif_probe(struct ufs_hba *hba, u8 *desc_buf)
> +{
> +	struct ufs_dev_info *dev_info = &hba->dev_info;
> +	u32 ext_ufs_feature;
> +	u8 mask = 0;
> +
> +	if (!(hba->caps & UFSHCD_CAP_TEMP_NOTIF) ||
> +	    dev_info->wspecversion < 0x300)
> +		return;
> +
> +	ext_ufs_feature = get_unaligned_be32(desc_buf +
> +					DEVICE_DESC_PARAM_EXT_UFS_FEATURE_SUP);
> +
> +	if (ext_ufs_feature & UFS_DEV_LOW_TEMP_NOTIF)
> +		mask |= MASK_EE_TOO_LOW_TEMP;
> +
> +	if (ext_ufs_feature & UFS_DEV_HIGH_TEMP_NOTIF)
> +		mask |= MASK_EE_TOO_HIGH_TEMP;
> +
> +	if (mask) {
> +		ufshcd_enable_ee(hba, mask);
> +		ufs_hwmon_probe(hba, mask);
> +	}
> +}
> +
>  void ufshcd_fixup_dev_quirks(struct ufs_hba *hba, struct ufs_dev_fix *fixups)
>  {
>  	struct ufs_dev_fix *f;
> @@ -7564,6 +7589,8 @@ static int ufs_get_device_desc(struct ufs_hba *hba)
>  
>  	ufshcd_wb_probe(hba, desc_buf);
>  
> +	ufshcd_temp_notif_probe(hba, desc_buf);
> +

Is that the appropriate place to make this call ?

>  	/*
>  	 * ufshcd_read_string_desc returns size of the string
>  	 * reset the error value
> diff --git a/drivers/scsi/ufs/ufshcd.h b/drivers/scsi/ufs/ufshcd.h
> index 52ea6f350b18..9bc434c4ae71 100644
> --- a/drivers/scsi/ufs/ufshcd.h
> +++ b/drivers/scsi/ufs/ufshcd.h
> @@ -653,6 +653,12 @@ enum ufshcd_caps {
>  	 * in order to exit DeepSleep state.
>  	 */
>  	UFSHCD_CAP_DEEPSLEEP				= 1 << 10,
> +
> +	/*
> +	 * This capability allows the host controller driver to use temperature
> +	 * notification if it is supported by the UFS device.
> +	 */
> +	UFSHCD_CAP_TEMP_NOTIF				= 1 << 11,
>  };
>  
>  struct ufs_hba_variant_params {
> @@ -789,6 +795,10 @@ struct ufs_hba {
>  	struct scsi_device *sdev_ufs_device;
>  	struct scsi_device *sdev_rpmb;
>  
> +#ifdef CONFIG_SCSI_UFS_HWMON
> +	struct device *hwmon_device;
> +#endif
> +
>  	enum ufs_dev_pwr_mode curr_dev_pwr_mode;
>  	enum uic_link_state uic_link_state;
>  	/* Desired UFS power management level during runtime PM */
> @@ -1049,6 +1059,14 @@ static inline u8 ufshcd_wb_get_query_index(struct ufs_hba *hba)
>  	return 0;
>  }
>  
> +#ifdef CONFIG_SCSI_UFS_HWMON
> +int ufs_hwmon_probe(struct ufs_hba *hba, u8 mask);
> +void ufs_hwmon_remove(struct ufs_hba *hba);
> +#else
> +static inline int ufs_hwmon_probe(struct ufs_hba *hba, u8 mask) { return 0; }
> +static inline void nvme_hwmon_remove(struct ufs_hba *hba) {}

ufs_hwmon_remove

> +#endif
> +
>  #ifdef CONFIG_PM
>  extern int ufshcd_runtime_suspend(struct device *dev);
>  extern int ufshcd_runtime_resume(struct device *dev);
> -- 
> 2.17.1
> 

^ permalink raw reply	[flat|nested] 9+ messages in thread

* Re: [PATCH v2 2/2] scsi: ufs: Add temperature notification exception handling
  2021-09-09  6:34 ` [PATCH v2 2/2] scsi: ufs: Add temperature notification exception handling Avri Altman
@ 2021-09-09 16:54   ` Guenter Roeck
  2021-09-10 16:32     ` Avri Altman
  0 siblings, 1 reply; 9+ messages in thread
From: Guenter Roeck @ 2021-09-09 16:54 UTC (permalink / raw)
  To: Avri Altman
  Cc: James E . J . Bottomley, Martin K . Petersen, linux-scsi,
	linux-kernel, Bart Van Assche, Adrian Hunter, Bean Huo

On Thu, Sep 09, 2021 at 09:34:44AM +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 <avri.altman@wdc.com>
> ---
>  drivers/scsi/ufs/ufs.h    |  2 ++
>  drivers/scsi/ufs/ufshcd.c | 19 +++++++++++++++++++
>  2 files changed, 21 insertions(+)
> 
> diff --git a/drivers/scsi/ufs/ufs.h b/drivers/scsi/ufs/ufs.h
> index 171b27be7b1d..d9bc048c2a71 100644
> --- a/drivers/scsi/ufs/ufs.h
> +++ b/drivers/scsi/ufs/ufs.h
> @@ -377,6 +377,8 @@ enum {
>  	MASK_EE_PERFORMANCE_THROTTLING	= BIT(6),
>  };
>  
> +#define MASK_EE_URGENT_TEMP (MASK_EE_TOO_HIGH_TEMP | MASK_EE_TOO_LOW_TEMP)
> +
>  /* Background operation status */
>  enum bkops_status {
>  	BKOPS_STATUS_NO_OP               = 0x0,
> diff --git a/drivers/scsi/ufs/ufshcd.c b/drivers/scsi/ufs/ufshcd.c
> index fc995bf1f296..1f61e8090220 100644
> --- a/drivers/scsi/ufs/ufshcd.c
> +++ b/drivers/scsi/ufs/ufshcd.c
> @@ -5642,6 +5642,22 @@ 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(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);
> +

It would probably make sense to call hwmon_notify_event() here.

Guenter

> +	/*
> +	 * 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 +5837,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);
> -- 
> 2.17.1
> 

^ permalink raw reply	[flat|nested] 9+ messages in thread

* RE: [PATCH v2 1/2] scsi: ufs: Probe for temperature notification support
  2021-09-09 16:26   ` Bart Van Assche
@ 2021-09-10 15:58     ` Avri Altman
  0 siblings, 0 replies; 9+ messages in thread
From: Avri Altman @ 2021-09-10 15:58 UTC (permalink / raw)
  To: Bart Van Assche, James E . J . Bottomley, Martin K . Petersen
  Cc: linux-scsi, linux-kernel, Adrian Hunter, Bean Huo, Guenter Roeck

 
> 
> On 9/8/21 11:34 PM, Avri Altman wrote:
> > +static bool ufs_temp_enabled(struct ufs_hba *hba, struct
> > +ufs_hwmon_data *data) {
> > +     u32 ee_mask;
> > +
> > +     if (ufshcd_query_attr(hba, UPIU_QUERY_OPCODE_READ_ATTR,
> > +                           QUERY_ATTR_IDN_EE_CONTROL, 0, 0, &ee_mask))
> > +             return false;
> > +
> > +     return (data->mask & ee_mask & MASK_EE_TOO_HIGH_TEMP) ||
> > +             (data->mask & ee_mask & MASK_EE_TOO_LOW_TEMP); }
> 
> The above function uses data->mask but not data so it's probably better to
> pass
> data->mask directly as the second argument.
Done.

> 
> > +static bool ufs_temp_valid(struct ufs_hba *hba, struct ufs_hwmon_data
> *data,
> > +                        enum attr_idn idn, u32 value) {
> > +     return (idn == QUERY_ATTR_IDN_CASE_ROUGH_TEMP && value >= 1
> &&
> > +             value <= 250 && ufs_temp_enabled(hba, data)) ||
> > +           (idn == QUERY_ATTR_IDN_HIGH_TEMP_BOUND && value >= 100
> &&
> > +            value <= 250) ||
> > +           (idn == QUERY_ATTR_IDN_LOW_TEMP_BOUND && value >= 1 &&
> > +            value <= 80);
> > +}
> 
> Same comment for this function - if the above comment is addressed 'mask'
> can be passed as an argument instead of 'data'.
Done.
 
> > +static int ufs_get_temp(struct ufs_hba *hba, struct ufs_hwmon_data
> *data,
> > +                     enum attr_idn idn) {
> > +     u32 value;
> > +
> > +     if (ufshcd_query_attr(hba, UPIU_QUERY_OPCODE_READ_ATTR, idn, 0,
> 0,
> > +         &value))
> > +             return 0;
> > +
> > +     if (ufs_temp_valid(hba, data, idn, value))
> > +             return value - 80;
> > +
> > +     return 0;
> > +}
> 
> Same comment here.
Done.
 
> > +void ufs_hwmon_remove(struct ufs_hba *hba) {
> > +     if (hba->hwmon_device) {
> > +             struct ufs_hwmon_data *data =
> > +                     dev_get_drvdata(hba->hwmon_device);
> > +
> > +             hwmon_device_unregister(hba->hwmon_device);
> > +             hba->hwmon_device = NULL;
> > +             kfree(data);
> > +     }
> > +}
> 
> Please use the "early return" style since that is the most widely used style in
> the Linux kernel (if (!hba->hwmon_device) return).
Done.


> 
> Thanks,
> 
> Bart.

^ permalink raw reply	[flat|nested] 9+ messages in thread

* RE: [PATCH v2 1/2] scsi: ufs: Probe for temperature notification support
  2021-09-09 16:51   ` Guenter Roeck
@ 2021-09-10 16:13     ` Avri Altman
  0 siblings, 0 replies; 9+ messages in thread
From: Avri Altman @ 2021-09-10 16:13 UTC (permalink / raw)
  To: Guenter Roeck
  Cc: James E . J . Bottomley, Martin K . Petersen, linux-scsi,
	linux-kernel, Bart Van Assche, Adrian Hunter, Bean Huo

> > +     if (IS_ERR(hwmon)) {
> > +             dev_warn(dev, "Failed to instantiate hwmon device\n");
> > +             kfree(data);
> > +             return PTR_ERR(hwmon);
> 
> If the error is ignored by the caller, it doesn't make sense to return it.
Done.

> 
> > +     }
> > +
> > +     hba->hwmon_device = hwmon;
> > +
> > +     return 0;
> > +}
> > +
> > +void ufs_hwmon_remove(struct ufs_hba *hba) {
> > +     if (hba->hwmon_device) {
> > +             struct ufs_hwmon_data *data =
> > +                     dev_get_drvdata(hba->hwmon_device);
> > +
> > +             hwmon_device_unregister(hba->hwmon_device);
> > +             hba->hwmon_device = NULL;
> > +             kfree(data);
> > +     }
> > +}
> 
> That function is never called and thus pointless (suggesting that there may
> be some structural problem in the code).
Yayks... Forgot to call it from ufshcd_remve()
Thanks.

> >
> >       ufshcd_wb_probe(hba, desc_buf);
> >
> > +     ufshcd_temp_notif_probe(hba, desc_buf);
> > +
> 
> Is that the appropriate place to make this call ?
Yes I think so.
This path is on link startup when the host reads the device configuration.

> > +#ifdef CONFIG_SCSI_UFS_HWMON
> > +int ufs_hwmon_probe(struct ufs_hba *hba, u8 mask); void
> > +ufs_hwmon_remove(struct ufs_hba *hba); #else static inline int
> > +ufs_hwmon_probe(struct ufs_hba *hba, u8 mask) { return 0; } static
> > +inline void nvme_hwmon_remove(struct ufs_hba *hba) {}
> 
> ufs_hwmon_remove
Done. Thanks.

^ permalink raw reply	[flat|nested] 9+ messages in thread

* RE: [PATCH v2 2/2] scsi: ufs: Add temperature notification exception handling
  2021-09-09 16:54   ` Guenter Roeck
@ 2021-09-10 16:32     ` Avri Altman
  0 siblings, 0 replies; 9+ messages in thread
From: Avri Altman @ 2021-09-10 16:32 UTC (permalink / raw)
  To: Guenter Roeck
  Cc: James E . J . Bottomley, Martin K . Petersen, linux-scsi,
	linux-kernel, Bart Van Assche, Adrian Hunter, Bean Huo

> > +static void ufshcd_temp_exception_event_handler(struct ufs_hba *hba,
> > +u16 status) {
> > +     u32 value;
> > +
> > +     if (ufshcd_query_attr(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);
> > +
> 
> It would probably make sense to call hwmon_notify_event() here.
Yes.  Thank you.

Thanks,
Avri

> 
> Guenter
> 
> > +     /*
> > +      * 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 +5837,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);
> > --
> > 2.17.1
> >

^ permalink raw reply	[flat|nested] 9+ messages in thread

end of thread, other threads:[~2021-09-10 16:32 UTC | newest]

Thread overview: 9+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2021-09-09  6:34 [PATCH v2 0/2] Add temperature notification support Avri Altman
2021-09-09  6:34 ` [PATCH v2 1/2] scsi: ufs: Probe for " Avri Altman
2021-09-09 16:26   ` Bart Van Assche
2021-09-10 15:58     ` Avri Altman
2021-09-09 16:51   ` Guenter Roeck
2021-09-10 16:13     ` Avri Altman
2021-09-09  6:34 ` [PATCH v2 2/2] scsi: ufs: Add temperature notification exception handling Avri Altman
2021-09-09 16:54   ` Guenter Roeck
2021-09-10 16:32     ` Avri Altman

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).