Linux Hardware Monitor development
 help / color / mirror / Atom feed
* [PATCH net-next v2 3/9] bnxt_en: Move hwmon functions into a dedicated file
       [not found] <20230927035734.42816-1-michael.chan@broadcom.com>
@ 2023-09-27  3:57 ` Michael Chan
  2023-09-27 13:55   ` Guenter Roeck
  2023-09-27  3:57 ` [PATCH net-next v2 4/9] bnxt_en: Modify the driver to use hwmon_device_register_with_info Michael Chan
                   ` (2 subsequent siblings)
  3 siblings, 1 reply; 8+ messages in thread
From: Michael Chan @ 2023-09-27  3:57 UTC (permalink / raw)
  To: davem
  Cc: netdev, edumazet, kuba, pabeni, gospo, Kalesh AP, Andy Gospodarek,
	Jean Delvare, Guenter Roeck, linux-hwmon

[-- Attachment #1: Type: text/plain, Size: 7304 bytes --]

From: Kalesh AP <kalesh-anakkur.purayil@broadcom.com>

This is in preparation for upcoming patches in the series.
Driver has to expose more threshold temperatures through the
hwmon sysfs interface. More code will be added and do not
want to overload bnxt.c.

Reviewed-by: Andy Gospodarek <andrew.gospodarek@broadcom.com>
Cc: Jean Delvare <jdelvare@suse.com>
Cc: Guenter Roeck <linux@roeck-us.net>
Cc: linux-hwmon@vger.kernel.org
Signed-off-by: Kalesh AP <kalesh-anakkur.purayil@broadcom.com>
Signed-off-by: Michael Chan <michael.chan@broadcom.com>
---
 drivers/net/ethernet/broadcom/bnxt/Makefile   |  1 +
 drivers/net/ethernet/broadcom/bnxt/bnxt.c     | 76 +----------------
 .../net/ethernet/broadcom/bnxt/bnxt_hwmon.c   | 82 +++++++++++++++++++
 .../net/ethernet/broadcom/bnxt/bnxt_hwmon.h   | 25 ++++++
 4 files changed, 109 insertions(+), 75 deletions(-)
 create mode 100644 drivers/net/ethernet/broadcom/bnxt/bnxt_hwmon.c
 create mode 100644 drivers/net/ethernet/broadcom/bnxt/bnxt_hwmon.h

diff --git a/drivers/net/ethernet/broadcom/bnxt/Makefile b/drivers/net/ethernet/broadcom/bnxt/Makefile
index 2bc2b707d6ee..ba6c239d52fa 100644
--- a/drivers/net/ethernet/broadcom/bnxt/Makefile
+++ b/drivers/net/ethernet/broadcom/bnxt/Makefile
@@ -4,3 +4,4 @@ obj-$(CONFIG_BNXT) += bnxt_en.o
 bnxt_en-y := bnxt.o bnxt_hwrm.o bnxt_sriov.o bnxt_ethtool.o bnxt_dcb.o bnxt_ulp.o bnxt_xdp.o bnxt_ptp.o bnxt_vfr.o bnxt_devlink.o bnxt_dim.o bnxt_coredump.o
 bnxt_en-$(CONFIG_BNXT_FLOWER_OFFLOAD) += bnxt_tc.o
 bnxt_en-$(CONFIG_DEBUG_FS) += bnxt_debugfs.o
+bnxt_en-$(CONFIG_BNXT_HWMON) += bnxt_hwmon.o
diff --git a/drivers/net/ethernet/broadcom/bnxt/bnxt.c b/drivers/net/ethernet/broadcom/bnxt/bnxt.c
index 785084147994..b83f8de0a015 100644
--- a/drivers/net/ethernet/broadcom/bnxt/bnxt.c
+++ b/drivers/net/ethernet/broadcom/bnxt/bnxt.c
@@ -52,8 +52,6 @@
 #include <linux/cpu_rmap.h>
 #include <linux/cpumask.h>
 #include <net/pkt_cls.h>
-#include <linux/hwmon.h>
-#include <linux/hwmon-sysfs.h>
 #include <net/page_pool/helpers.h>
 #include <linux/align.h>
 #include <net/netdev_queues.h>
@@ -71,6 +69,7 @@
 #include "bnxt_tc.h"
 #include "bnxt_devlink.h"
 #include "bnxt_debugfs.h"
+#include "bnxt_hwmon.h"
 
 #define BNXT_TX_TIMEOUT		(5 * HZ)
 #define BNXT_DEF_MSG_ENABLE	(NETIF_MSG_DRV | NETIF_MSG_HW | \
@@ -10250,79 +10249,6 @@ static void bnxt_get_wol_settings(struct bnxt *bp)
 	} while (handle && handle != 0xffff);
 }
 
-#ifdef CONFIG_BNXT_HWMON
-static ssize_t bnxt_show_temp(struct device *dev,
-			      struct device_attribute *devattr, char *buf)
-{
-	struct hwrm_temp_monitor_query_output *resp;
-	struct hwrm_temp_monitor_query_input *req;
-	struct bnxt *bp = dev_get_drvdata(dev);
-	u32 len = 0;
-	int rc;
-
-	rc = hwrm_req_init(bp, req, HWRM_TEMP_MONITOR_QUERY);
-	if (rc)
-		return rc;
-	resp = hwrm_req_hold(bp, req);
-	rc = hwrm_req_send(bp, req);
-	if (!rc)
-		len = sprintf(buf, "%u\n", resp->temp * 1000); /* display millidegree */
-	hwrm_req_drop(bp, req);
-	if (rc)
-		return rc;
-	return len;
-}
-static SENSOR_DEVICE_ATTR(temp1_input, 0444, bnxt_show_temp, NULL, 0);
-
-static struct attribute *bnxt_attrs[] = {
-	&sensor_dev_attr_temp1_input.dev_attr.attr,
-	NULL
-};
-ATTRIBUTE_GROUPS(bnxt);
-
-static void bnxt_hwmon_uninit(struct bnxt *bp)
-{
-	if (bp->hwmon_dev) {
-		hwmon_device_unregister(bp->hwmon_dev);
-		bp->hwmon_dev = NULL;
-	}
-}
-
-static void bnxt_hwmon_init(struct bnxt *bp)
-{
-	struct hwrm_temp_monitor_query_input *req;
-	struct pci_dev *pdev = bp->pdev;
-	int rc;
-
-	rc = hwrm_req_init(bp, req, HWRM_TEMP_MONITOR_QUERY);
-	if (!rc)
-		rc = hwrm_req_send_silent(bp, req);
-	if (rc == -EACCES || rc == -EOPNOTSUPP) {
-		bnxt_hwmon_uninit(bp);
-		return;
-	}
-
-	if (bp->hwmon_dev)
-		return;
-
-	bp->hwmon_dev = hwmon_device_register_with_groups(&pdev->dev,
-							  DRV_MODULE_NAME, bp,
-							  bnxt_groups);
-	if (IS_ERR(bp->hwmon_dev)) {
-		bp->hwmon_dev = NULL;
-		dev_warn(&pdev->dev, "Cannot register hwmon device\n");
-	}
-}
-#else
-static void bnxt_hwmon_uninit(struct bnxt *bp)
-{
-}
-
-static void bnxt_hwmon_init(struct bnxt *bp)
-{
-}
-#endif
-
 static bool bnxt_eee_config_ok(struct bnxt *bp)
 {
 	struct ethtool_eee *eee = &bp->eee;
diff --git a/drivers/net/ethernet/broadcom/bnxt/bnxt_hwmon.c b/drivers/net/ethernet/broadcom/bnxt/bnxt_hwmon.c
new file mode 100644
index 000000000000..476616d97071
--- /dev/null
+++ b/drivers/net/ethernet/broadcom/bnxt/bnxt_hwmon.c
@@ -0,0 +1,82 @@
+/* Broadcom NetXtreme-C/E network driver.
+ *
+ * Copyright (c) 2023 Broadcom Limited
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation.
+ */
+
+#include <linux/dev_printk.h>
+#include <linux/errno.h>
+#include <linux/hwmon.h>
+#include <linux/hwmon-sysfs.h>
+#include <linux/pci.h>
+
+#include "bnxt_hsi.h"
+#include "bnxt.h"
+#include "bnxt_hwrm.h"
+#include "bnxt_hwmon.h"
+
+static ssize_t bnxt_show_temp(struct device *dev,
+			      struct device_attribute *devattr, char *buf)
+{
+	struct hwrm_temp_monitor_query_output *resp;
+	struct hwrm_temp_monitor_query_input *req;
+	struct bnxt *bp = dev_get_drvdata(dev);
+	u32 len = 0;
+	int rc;
+
+	rc = hwrm_req_init(bp, req, HWRM_TEMP_MONITOR_QUERY);
+	if (rc)
+		return rc;
+	resp = hwrm_req_hold(bp, req);
+	rc = hwrm_req_send(bp, req);
+	if (!rc)
+		len = sprintf(buf, "%u\n", resp->temp * 1000); /* display millidegree */
+	hwrm_req_drop(bp, req);
+	if (rc)
+		return rc;
+	return len;
+}
+static SENSOR_DEVICE_ATTR(temp1_input, 0444, bnxt_show_temp, NULL, 0);
+
+static struct attribute *bnxt_attrs[] = {
+	&sensor_dev_attr_temp1_input.dev_attr.attr,
+	NULL
+};
+ATTRIBUTE_GROUPS(bnxt);
+
+void bnxt_hwmon_uninit(struct bnxt *bp)
+{
+	if (bp->hwmon_dev) {
+		hwmon_device_unregister(bp->hwmon_dev);
+		bp->hwmon_dev = NULL;
+	}
+}
+
+void bnxt_hwmon_init(struct bnxt *bp)
+{
+	struct hwrm_temp_monitor_query_input *req;
+	struct pci_dev *pdev = bp->pdev;
+	int rc;
+
+	rc = hwrm_req_init(bp, req, HWRM_TEMP_MONITOR_QUERY);
+	if (!rc)
+		rc = hwrm_req_send_silent(bp, req);
+	if (rc == -EACCES || rc == -EOPNOTSUPP) {
+		bnxt_hwmon_uninit(bp);
+		return;
+	}
+
+	if (bp->hwmon_dev)
+		return;
+
+	bp->hwmon_dev = hwmon_device_register_with_groups(&pdev->dev,
+							  DRV_MODULE_NAME, bp,
+							  bnxt_groups);
+	if (IS_ERR(bp->hwmon_dev)) {
+		bp->hwmon_dev = NULL;
+		dev_warn(&pdev->dev, "Cannot register hwmon device\n");
+	}
+}
diff --git a/drivers/net/ethernet/broadcom/bnxt/bnxt_hwmon.h b/drivers/net/ethernet/broadcom/bnxt/bnxt_hwmon.h
new file mode 100644
index 000000000000..af310066687c
--- /dev/null
+++ b/drivers/net/ethernet/broadcom/bnxt/bnxt_hwmon.h
@@ -0,0 +1,25 @@
+/* Broadcom NetXtreme-C/E network driver.
+ *
+ * Copyright (c) 2023 Broadcom Limited
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation.
+ */
+
+#ifndef BNXT_HWMON_H
+#define BNXT_HWMON_H
+
+#ifdef CONFIG_BNXT_HWMON
+void bnxt_hwmon_uninit(struct bnxt *bp);
+void bnxt_hwmon_init(struct bnxt *bp);
+#else
+static inline void bnxt_hwmon_uninit(struct bnxt *bp)
+{
+}
+
+static inline void bnxt_hwmon_init(struct bnxt *bp)
+{
+}
+#endif
+#endif
-- 
2.30.1


[-- Attachment #2: S/MIME Cryptographic Signature --]
[-- Type: application/pkcs7-signature, Size: 4209 bytes --]

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

* [PATCH net-next v2 4/9] bnxt_en: Modify the driver to use hwmon_device_register_with_info
       [not found] <20230927035734.42816-1-michael.chan@broadcom.com>
  2023-09-27  3:57 ` [PATCH net-next v2 3/9] bnxt_en: Move hwmon functions into a dedicated file Michael Chan
@ 2023-09-27  3:57 ` Michael Chan
  2023-09-27 13:56   ` Guenter Roeck
  2023-09-27  3:57 ` [PATCH net-next v2 5/9] bnxt_en: Expose threshold temperatures through hwmon Michael Chan
  2023-09-27  3:57 ` [PATCH net-next v2 7/9] bnxt_en: Event handler for Thermal event Michael Chan
  3 siblings, 1 reply; 8+ messages in thread
From: Michael Chan @ 2023-09-27  3:57 UTC (permalink / raw)
  To: davem
  Cc: netdev, edumazet, kuba, pabeni, gospo, Kalesh AP, Jean Delvare,
	Guenter Roeck, linux-hwmon

[-- Attachment #1: Type: text/plain, Size: 3511 bytes --]

From: Kalesh AP <kalesh-anakkur.purayil@broadcom.com>

The use of hwmon_device_register_with_groups() is deprecated.
Modified the driver to use hwmon_device_register_with_info().

Driver currently exports only temp1_input through hwmon sysfs
interface. But FW has been modified to report more threshold
temperatures and driver want to report them through the
hwmon interface.

Cc: Jean Delvare <jdelvare@suse.com>
Cc: Guenter Roeck <linux@roeck-us.net>
Cc: linux-hwmon@vger.kernel.org
Signed-off-by: Kalesh AP <kalesh-anakkur.purayil@broadcom.com>
Signed-off-by: Michael Chan <michael.chan@broadcom.com>
---
 .../net/ethernet/broadcom/bnxt/bnxt_hwmon.c   | 71 ++++++++++++++-----
 1 file changed, 55 insertions(+), 16 deletions(-)

diff --git a/drivers/net/ethernet/broadcom/bnxt/bnxt_hwmon.c b/drivers/net/ethernet/broadcom/bnxt/bnxt_hwmon.c
index 476616d97071..05e3d75f3c43 100644
--- a/drivers/net/ethernet/broadcom/bnxt/bnxt_hwmon.c
+++ b/drivers/net/ethernet/broadcom/bnxt/bnxt_hwmon.c
@@ -18,34 +18,73 @@
 #include "bnxt_hwrm.h"
 #include "bnxt_hwmon.h"
 
-static ssize_t bnxt_show_temp(struct device *dev,
-			      struct device_attribute *devattr, char *buf)
+static int bnxt_hwrm_temp_query(struct bnxt *bp, u8 *temp)
 {
 	struct hwrm_temp_monitor_query_output *resp;
 	struct hwrm_temp_monitor_query_input *req;
-	struct bnxt *bp = dev_get_drvdata(dev);
-	u32 len = 0;
 	int rc;
 
 	rc = hwrm_req_init(bp, req, HWRM_TEMP_MONITOR_QUERY);
 	if (rc)
 		return rc;
 	resp = hwrm_req_hold(bp, req);
-	rc = hwrm_req_send(bp, req);
-	if (!rc)
-		len = sprintf(buf, "%u\n", resp->temp * 1000); /* display millidegree */
-	hwrm_req_drop(bp, req);
+	rc = hwrm_req_send_silent(bp, req);
 	if (rc)
+		goto drop_req;
+
+	*temp = resp->temp;
+
+drop_req:
+	hwrm_req_drop(bp, req);
+	return rc;
+}
+
+static umode_t bnxt_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_input:
+		return 0444;
+	default:
+		return 0;
+	}
+}
+
+static int bnxt_hwmon_read(struct device *dev, enum hwmon_sensor_types type, u32 attr,
+			   int channel, long *val)
+{
+	struct bnxt *bp = dev_get_drvdata(dev);
+	u8 temp = 0;
+	int rc;
+
+	switch (attr) {
+	case hwmon_temp_input:
+		rc = bnxt_hwrm_temp_query(bp, &temp);
+		if (!rc)
+			*val = temp * 1000;
 		return rc;
-	return len;
+	default:
+		return -EOPNOTSUPP;
+	}
 }
-static SENSOR_DEVICE_ATTR(temp1_input, 0444, bnxt_show_temp, NULL, 0);
 
-static struct attribute *bnxt_attrs[] = {
-	&sensor_dev_attr_temp1_input.dev_attr.attr,
+static const struct hwmon_channel_info *bnxt_hwmon_info[] = {
+	HWMON_CHANNEL_INFO(temp, HWMON_T_INPUT),
 	NULL
 };
-ATTRIBUTE_GROUPS(bnxt);
+
+static const struct hwmon_ops bnxt_hwmon_ops = {
+	.is_visible     = bnxt_hwmon_is_visible,
+	.read           = bnxt_hwmon_read,
+};
+
+static const struct hwmon_chip_info bnxt_hwmon_chip_info = {
+	.ops    = &bnxt_hwmon_ops,
+	.info   = bnxt_hwmon_info,
+};
 
 void bnxt_hwmon_uninit(struct bnxt *bp)
 {
@@ -72,9 +111,9 @@ void bnxt_hwmon_init(struct bnxt *bp)
 	if (bp->hwmon_dev)
 		return;
 
-	bp->hwmon_dev = hwmon_device_register_with_groups(&pdev->dev,
-							  DRV_MODULE_NAME, bp,
-							  bnxt_groups);
+	bp->hwmon_dev = hwmon_device_register_with_info(&pdev->dev,
+							DRV_MODULE_NAME, bp,
+							&bnxt_hwmon_chip_info, NULL);
 	if (IS_ERR(bp->hwmon_dev)) {
 		bp->hwmon_dev = NULL;
 		dev_warn(&pdev->dev, "Cannot register hwmon device\n");
-- 
2.30.1


[-- Attachment #2: S/MIME Cryptographic Signature --]
[-- Type: application/pkcs7-signature, Size: 4209 bytes --]

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

* [PATCH net-next v2 5/9] bnxt_en: Expose threshold temperatures through hwmon
       [not found] <20230927035734.42816-1-michael.chan@broadcom.com>
  2023-09-27  3:57 ` [PATCH net-next v2 3/9] bnxt_en: Move hwmon functions into a dedicated file Michael Chan
  2023-09-27  3:57 ` [PATCH net-next v2 4/9] bnxt_en: Modify the driver to use hwmon_device_register_with_info Michael Chan
@ 2023-09-27  3:57 ` Michael Chan
  2023-09-27 14:04   ` Guenter Roeck
  2023-09-27  3:57 ` [PATCH net-next v2 7/9] bnxt_en: Event handler for Thermal event Michael Chan
  3 siblings, 1 reply; 8+ messages in thread
From: Michael Chan @ 2023-09-27  3:57 UTC (permalink / raw)
  To: davem
  Cc: netdev, edumazet, kuba, pabeni, gospo, Kalesh AP, Jean Delvare,
	Guenter Roeck, linux-hwmon

[-- Attachment #1: Type: text/plain, Size: 5094 bytes --]

From: Kalesh AP <kalesh-anakkur.purayil@broadcom.com>

HWRM_TEMP_MONITOR_QUERY response now indicates various
threshold temperatures. Expose these threshold temperatures
through the hwmon sysfs using this mapping:

hwmon_temp_max : bp->warn_thresh_temp
hwmon_temp_crit : bp->crit_thresh_temp
hwmon_temp_emergency : bp->fatal_thresh_temp

hwmon_temp_max_alarm : temp >= bp->warn_thresh_temp
hwmon_temp_crit_alarm : temp >= bp->crit_thresh_temp
hwmon_temp_emergency_alarm : temp >= bp->fatal_thresh_temp

Link: https://lore.kernel.org/netdev/20230815045658.80494-12-michael.chan@broadcom.com/
Cc: Jean Delvare <jdelvare@suse.com>
Cc: Guenter Roeck <linux@roeck-us.net>
Cc: linux-hwmon@vger.kernel.org
Signed-off-by: Kalesh AP <kalesh-anakkur.purayil@broadcom.com>
Signed-off-by: Michael Chan <michael.chan@broadcom.com>
---
v2:
bnxt_hwrm_temp_query() now stores the static threshold values once.
Use new hwmon temperature mappings shown above and remove hwmon_temp_lcrit.

---
 drivers/net/ethernet/broadcom/bnxt/bnxt.h     |  7 +++
 .../net/ethernet/broadcom/bnxt/bnxt_hwmon.c   | 57 ++++++++++++++++---
 2 files changed, 57 insertions(+), 7 deletions(-)

diff --git a/drivers/net/ethernet/broadcom/bnxt/bnxt.h b/drivers/net/ethernet/broadcom/bnxt/bnxt.h
index 84cbcfa61bc1..43a07d84f815 100644
--- a/drivers/net/ethernet/broadcom/bnxt/bnxt.h
+++ b/drivers/net/ethernet/broadcom/bnxt/bnxt.h
@@ -2013,6 +2013,7 @@ struct bnxt {
 	#define BNXT_FW_CAP_RING_MONITOR		BIT_ULL(30)
 	#define BNXT_FW_CAP_DBG_QCAPS			BIT_ULL(31)
 	#define BNXT_FW_CAP_PTP				BIT_ULL(32)
+	#define BNXT_FW_CAP_THRESHOLD_TEMP_SUPPORTED	BIT_ULL(33)
 
 	u32			fw_dbg_cap;
 
@@ -2185,7 +2186,13 @@ struct bnxt {
 	struct bnxt_tc_info	*tc_info;
 	struct list_head	tc_indr_block_list;
 	struct dentry		*debugfs_pdev;
+#ifdef CONFIG_BNXT_HWMON
 	struct device		*hwmon_dev;
+	u8			warn_thresh_temp;
+	u8			crit_thresh_temp;
+	u8			fatal_thresh_temp;
+	u8			shutdown_thresh_temp;
+#endif
 	enum board_idx		board_idx;
 };
 
diff --git a/drivers/net/ethernet/broadcom/bnxt/bnxt_hwmon.c b/drivers/net/ethernet/broadcom/bnxt/bnxt_hwmon.c
index 05e3d75f3c43..6a2cad5cc159 100644
--- a/drivers/net/ethernet/broadcom/bnxt/bnxt_hwmon.c
+++ b/drivers/net/ethernet/broadcom/bnxt/bnxt_hwmon.c
@@ -32,8 +32,16 @@ static int bnxt_hwrm_temp_query(struct bnxt *bp, u8 *temp)
 	if (rc)
 		goto drop_req;
 
-	*temp = resp->temp;
-
+	if (temp) {
+		*temp = resp->temp;
+	} else if (resp->flags &
+		   TEMP_MONITOR_QUERY_RESP_FLAGS_THRESHOLD_VALUES_AVAILABLE) {
+		bp->fw_cap |= BNXT_FW_CAP_THRESHOLD_TEMP_SUPPORTED;
+		bp->warn_thresh_temp = resp->warn_threshold;
+		bp->crit_thresh_temp = resp->critical_threshold;
+		bp->fatal_thresh_temp = resp->fatal_threshold;
+		bp->shutdown_thresh_temp = resp->shutdown_threshold;
+	}
 drop_req:
 	hwrm_req_drop(bp, req);
 	return rc;
@@ -42,12 +50,23 @@ static int bnxt_hwrm_temp_query(struct bnxt *bp, u8 *temp)
 static umode_t bnxt_hwmon_is_visible(const void *_data, enum hwmon_sensor_types type,
 				     u32 attr, int channel)
 {
+	const struct bnxt *bp = _data;
+
 	if (type != hwmon_temp)
 		return 0;
 
 	switch (attr) {
 	case hwmon_temp_input:
 		return 0444;
+	case hwmon_temp_max:
+	case hwmon_temp_crit:
+	case hwmon_temp_emergency:
+	case hwmon_temp_max_alarm:
+	case hwmon_temp_crit_alarm:
+	case hwmon_temp_emergency_alarm:
+		if (!(bp->fw_cap & BNXT_FW_CAP_THRESHOLD_TEMP_SUPPORTED))
+			return 0;
+		return 0444;
 	default:
 		return 0;
 	}
@@ -66,13 +85,39 @@ static int bnxt_hwmon_read(struct device *dev, enum hwmon_sensor_types type, u32
 		if (!rc)
 			*val = temp * 1000;
 		return rc;
+	case hwmon_temp_max:
+		*val = bp->warn_thresh_temp * 1000;
+		return 0;
+	case hwmon_temp_crit:
+		*val = bp->crit_thresh_temp * 1000;
+		return 0;
+	case hwmon_temp_emergency:
+		*val = bp->fatal_thresh_temp * 1000;
+		return 0;
+	case hwmon_temp_max_alarm:
+		rc = bnxt_hwrm_temp_query(bp, &temp);
+		if (!rc)
+			*val = temp >= bp->warn_thresh_temp;
+		return rc;
+	case hwmon_temp_crit_alarm:
+		rc = bnxt_hwrm_temp_query(bp, &temp);
+		if (!rc)
+			*val = temp >= bp->crit_thresh_temp;
+		return rc;
+	case hwmon_temp_emergency_alarm:
+		rc = bnxt_hwrm_temp_query(bp, &temp);
+		if (!rc)
+			*val = temp >= bp->fatal_thresh_temp;
+		return rc;
 	default:
 		return -EOPNOTSUPP;
 	}
 }
 
 static const struct hwmon_channel_info *bnxt_hwmon_info[] = {
-	HWMON_CHANNEL_INFO(temp, HWMON_T_INPUT),
+	HWMON_CHANNEL_INFO(temp, HWMON_T_INPUT | HWMON_T_MAX | HWMON_T_CRIT |
+			   HWMON_T_EMERGENCY | HWMON_T_MAX_ALARM |
+			   HWMON_T_CRIT_ALARM | HWMON_T_EMERGENCY_ALARM),
 	NULL
 };
 
@@ -96,13 +141,11 @@ void bnxt_hwmon_uninit(struct bnxt *bp)
 
 void bnxt_hwmon_init(struct bnxt *bp)
 {
-	struct hwrm_temp_monitor_query_input *req;
 	struct pci_dev *pdev = bp->pdev;
 	int rc;
 
-	rc = hwrm_req_init(bp, req, HWRM_TEMP_MONITOR_QUERY);
-	if (!rc)
-		rc = hwrm_req_send_silent(bp, req);
+	/* temp1_xxx is only sensor, ensure not registered if it will fail */
+	rc = bnxt_hwrm_temp_query(bp, NULL);
 	if (rc == -EACCES || rc == -EOPNOTSUPP) {
 		bnxt_hwmon_uninit(bp);
 		return;
-- 
2.30.1


[-- Attachment #2: S/MIME Cryptographic Signature --]
[-- Type: application/pkcs7-signature, Size: 4209 bytes --]

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

* [PATCH net-next v2 7/9] bnxt_en: Event handler for Thermal event
       [not found] <20230927035734.42816-1-michael.chan@broadcom.com>
                   ` (2 preceding siblings ...)
  2023-09-27  3:57 ` [PATCH net-next v2 5/9] bnxt_en: Expose threshold temperatures through hwmon Michael Chan
@ 2023-09-27  3:57 ` Michael Chan
  2023-09-27 14:05   ` Guenter Roeck
  3 siblings, 1 reply; 8+ messages in thread
From: Michael Chan @ 2023-09-27  3:57 UTC (permalink / raw)
  To: davem
  Cc: netdev, edumazet, kuba, pabeni, gospo, Kalesh AP, Jean Delvare,
	Guenter Roeck, linux-hwmon

[-- Attachment #1: Type: text/plain, Size: 5480 bytes --]

From: Kalesh AP <kalesh-anakkur.purayil@broadcom.com>

Newer FW will send a new async event when it detects that
the chip's temperature has crossed the configured threshold value.
The driver will now notify hwmon and will log a warning message.

Link: https://lore.kernel.org/netdev/20230815045658.80494-13-michael.chan@broadcom.com/
Cc: Jean Delvare <jdelvare@suse.com>
Cc: Guenter Roeck <linux@roeck-us.net>
Cc: linux-hwmon@vger.kernel.org
Signed-off-by: Kalesh AP <kalesh-anakkur.purayil@broadcom.com>
Signed-off-by: Michael Chan <michael.chan@broadcom.com>
---
v2:
Remove hwmon dependencies from bnxt.c.

---
 drivers/net/ethernet/broadcom/bnxt/bnxt.c     | 52 +++++++++++++++++++
 .../net/ethernet/broadcom/bnxt/bnxt_hwmon.c   | 25 +++++++++
 .../net/ethernet/broadcom/bnxt/bnxt_hwmon.h   |  5 ++
 3 files changed, 82 insertions(+)

diff --git a/drivers/net/ethernet/broadcom/bnxt/bnxt.c b/drivers/net/ethernet/broadcom/bnxt/bnxt.c
index b83f8de0a015..7104237272de 100644
--- a/drivers/net/ethernet/broadcom/bnxt/bnxt.c
+++ b/drivers/net/ethernet/broadcom/bnxt/bnxt.c
@@ -2129,6 +2129,24 @@ static u16 bnxt_agg_ring_id_to_grp_idx(struct bnxt *bp, u16 ring_id)
 	return INVALID_HW_RING_ID;
 }
 
+#define BNXT_EVENT_THERMAL_CURRENT_TEMP(data2)				\
+	((data2) &							\
+	  ASYNC_EVENT_CMPL_ERROR_REPORT_THERMAL_EVENT_DATA2_CURRENT_TEMP_MASK)
+
+#define BNXT_EVENT_THERMAL_THRESHOLD_TEMP(data2)			\
+	(((data2) &							\
+	  ASYNC_EVENT_CMPL_ERROR_REPORT_THERMAL_EVENT_DATA2_THRESHOLD_TEMP_MASK) >>\
+	 ASYNC_EVENT_CMPL_ERROR_REPORT_THERMAL_EVENT_DATA2_THRESHOLD_TEMP_SFT)
+
+#define EVENT_DATA1_THERMAL_THRESHOLD_TYPE(data1)			\
+	((data1) &							\
+	 ASYNC_EVENT_CMPL_ERROR_REPORT_THERMAL_EVENT_DATA1_THRESHOLD_TYPE_MASK)
+
+#define EVENT_DATA1_THERMAL_THRESHOLD_DIR_INCREASING(data1)		\
+	(((data1) &							\
+	  ASYNC_EVENT_CMPL_ERROR_REPORT_THERMAL_EVENT_DATA1_TRANSITION_DIR) ==\
+	 ASYNC_EVENT_CMPL_ERROR_REPORT_THERMAL_EVENT_DATA1_TRANSITION_DIR_INCREASING)
+
 static void bnxt_event_error_report(struct bnxt *bp, u32 data1, u32 data2)
 {
 	u32 err_type = BNXT_EVENT_ERROR_REPORT_TYPE(data1);
@@ -2144,6 +2162,40 @@ static void bnxt_event_error_report(struct bnxt *bp, u32 data1, u32 data2)
 	case ASYNC_EVENT_CMPL_ERROR_REPORT_BASE_EVENT_DATA1_ERROR_TYPE_DOORBELL_DROP_THRESHOLD:
 		netdev_warn(bp->dev, "One or more MMIO doorbells dropped by the device!\n");
 		break;
+	case ASYNC_EVENT_CMPL_ERROR_REPORT_BASE_EVENT_DATA1_ERROR_TYPE_THERMAL_THRESHOLD: {
+		u32 type = EVENT_DATA1_THERMAL_THRESHOLD_TYPE(data1);
+		char *threshold_type;
+		char *dir_str;
+
+		switch (type) {
+		case ASYNC_EVENT_CMPL_ERROR_REPORT_THERMAL_EVENT_DATA1_THRESHOLD_TYPE_WARN:
+			threshold_type = "warning";
+			break;
+		case ASYNC_EVENT_CMPL_ERROR_REPORT_THERMAL_EVENT_DATA1_THRESHOLD_TYPE_CRITICAL:
+			threshold_type = "critical";
+			break;
+		case ASYNC_EVENT_CMPL_ERROR_REPORT_THERMAL_EVENT_DATA1_THRESHOLD_TYPE_FATAL:
+			threshold_type = "fatal";
+			break;
+		case ASYNC_EVENT_CMPL_ERROR_REPORT_THERMAL_EVENT_DATA1_THRESHOLD_TYPE_SHUTDOWN:
+			threshold_type = "shutdown";
+			break;
+		default:
+			netdev_err(bp->dev, "Unknown Thermal threshold type event\n");
+			return;
+		}
+		if (EVENT_DATA1_THERMAL_THRESHOLD_DIR_INCREASING(data1))
+			dir_str = "above";
+		else
+			dir_str = "below";
+		netdev_warn(bp->dev, "Chip temperature has gone %s the %s thermal threshold!\n",
+			    dir_str, threshold_type);
+		netdev_warn(bp->dev, "Temperature (In Celsius), Current: %lu, threshold: %lu\n",
+			    BNXT_EVENT_THERMAL_CURRENT_TEMP(data2),
+			    BNXT_EVENT_THERMAL_THRESHOLD_TEMP(data2));
+		bnxt_hwmon_notify_event(bp, type);
+		break;
+	}
 	default:
 		netdev_err(bp->dev, "FW reported unknown error type %u\n",
 			   err_type);
diff --git a/drivers/net/ethernet/broadcom/bnxt/bnxt_hwmon.c b/drivers/net/ethernet/broadcom/bnxt/bnxt_hwmon.c
index 6d36158df26e..e48094043c3b 100644
--- a/drivers/net/ethernet/broadcom/bnxt/bnxt_hwmon.c
+++ b/drivers/net/ethernet/broadcom/bnxt/bnxt_hwmon.c
@@ -18,6 +18,31 @@
 #include "bnxt_hwrm.h"
 #include "bnxt_hwmon.h"
 
+void bnxt_hwmon_notify_event(struct bnxt *bp, u32 type)
+{
+	u32 attr;
+
+	if (!bp->hwmon_dev)
+		return;
+
+	switch (type) {
+	case ASYNC_EVENT_CMPL_ERROR_REPORT_THERMAL_EVENT_DATA1_THRESHOLD_TYPE_WARN:
+		attr = hwmon_temp_max_alarm;
+		break;
+	case ASYNC_EVENT_CMPL_ERROR_REPORT_THERMAL_EVENT_DATA1_THRESHOLD_TYPE_CRITICAL:
+		attr = hwmon_temp_crit_alarm;
+		break;
+	case ASYNC_EVENT_CMPL_ERROR_REPORT_THERMAL_EVENT_DATA1_THRESHOLD_TYPE_FATAL:
+	case ASYNC_EVENT_CMPL_ERROR_REPORT_THERMAL_EVENT_DATA1_THRESHOLD_TYPE_SHUTDOWN:
+		attr = hwmon_temp_emergency_alarm;
+		break;
+	default:
+		return;
+	}
+
+	hwmon_notify_event(&bp->pdev->dev, hwmon_temp, attr, 0);
+}
+
 static int bnxt_hwrm_temp_query(struct bnxt *bp, u8 *temp)
 {
 	struct hwrm_temp_monitor_query_output *resp;
diff --git a/drivers/net/ethernet/broadcom/bnxt/bnxt_hwmon.h b/drivers/net/ethernet/broadcom/bnxt/bnxt_hwmon.h
index af310066687c..76d9f599ebc0 100644
--- a/drivers/net/ethernet/broadcom/bnxt/bnxt_hwmon.h
+++ b/drivers/net/ethernet/broadcom/bnxt/bnxt_hwmon.h
@@ -11,9 +11,14 @@
 #define BNXT_HWMON_H
 
 #ifdef CONFIG_BNXT_HWMON
+void bnxt_hwmon_notify_event(struct bnxt *bp, u32 type);
 void bnxt_hwmon_uninit(struct bnxt *bp);
 void bnxt_hwmon_init(struct bnxt *bp);
 #else
+static inline void bnxt_hwmon_notify_event(struct bnxt *bp, u32 type)
+{
+}
+
 static inline void bnxt_hwmon_uninit(struct bnxt *bp)
 {
 }
-- 
2.30.1


[-- Attachment #2: S/MIME Cryptographic Signature --]
[-- Type: application/pkcs7-signature, Size: 4209 bytes --]

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

* Re: [PATCH net-next v2 3/9] bnxt_en: Move hwmon functions into a dedicated file
  2023-09-27  3:57 ` [PATCH net-next v2 3/9] bnxt_en: Move hwmon functions into a dedicated file Michael Chan
@ 2023-09-27 13:55   ` Guenter Roeck
  0 siblings, 0 replies; 8+ messages in thread
From: Guenter Roeck @ 2023-09-27 13:55 UTC (permalink / raw)
  To: Michael Chan
  Cc: davem, netdev, edumazet, kuba, pabeni, gospo, Kalesh AP,
	Andy Gospodarek, Jean Delvare, linux-hwmon

On Tue, Sep 26, 2023 at 08:57:28PM -0700, Michael Chan wrote:
> From: Kalesh AP <kalesh-anakkur.purayil@broadcom.com>
> 
> This is in preparation for upcoming patches in the series.
> Driver has to expose more threshold temperatures through the
> hwmon sysfs interface. More code will be added and do not
> want to overload bnxt.c.
> 
> Reviewed-by: Andy Gospodarek <andrew.gospodarek@broadcom.com>
> Cc: Jean Delvare <jdelvare@suse.com>
> Cc: Guenter Roeck <linux@roeck-us.net>
> Cc: linux-hwmon@vger.kernel.org
> Signed-off-by: Kalesh AP <kalesh-anakkur.purayil@broadcom.com>
> Signed-off-by: Michael Chan <michael.chan@broadcom.com>

Acked-by: Guenter Roeck <linux@roeck-us.net>

> ---
>  drivers/net/ethernet/broadcom/bnxt/Makefile   |  1 +
>  drivers/net/ethernet/broadcom/bnxt/bnxt.c     | 76 +----------------
>  .../net/ethernet/broadcom/bnxt/bnxt_hwmon.c   | 82 +++++++++++++++++++
>  .../net/ethernet/broadcom/bnxt/bnxt_hwmon.h   | 25 ++++++
>  4 files changed, 109 insertions(+), 75 deletions(-)
>  create mode 100644 drivers/net/ethernet/broadcom/bnxt/bnxt_hwmon.c
>  create mode 100644 drivers/net/ethernet/broadcom/bnxt/bnxt_hwmon.h
> 
> diff --git a/drivers/net/ethernet/broadcom/bnxt/Makefile b/drivers/net/ethernet/broadcom/bnxt/Makefile
> index 2bc2b707d6ee..ba6c239d52fa 100644
> --- a/drivers/net/ethernet/broadcom/bnxt/Makefile
> +++ b/drivers/net/ethernet/broadcom/bnxt/Makefile
> @@ -4,3 +4,4 @@ obj-$(CONFIG_BNXT) += bnxt_en.o
>  bnxt_en-y := bnxt.o bnxt_hwrm.o bnxt_sriov.o bnxt_ethtool.o bnxt_dcb.o bnxt_ulp.o bnxt_xdp.o bnxt_ptp.o bnxt_vfr.o bnxt_devlink.o bnxt_dim.o bnxt_coredump.o
>  bnxt_en-$(CONFIG_BNXT_FLOWER_OFFLOAD) += bnxt_tc.o
>  bnxt_en-$(CONFIG_DEBUG_FS) += bnxt_debugfs.o
> +bnxt_en-$(CONFIG_BNXT_HWMON) += bnxt_hwmon.o
> diff --git a/drivers/net/ethernet/broadcom/bnxt/bnxt.c b/drivers/net/ethernet/broadcom/bnxt/bnxt.c
> index 785084147994..b83f8de0a015 100644
> --- a/drivers/net/ethernet/broadcom/bnxt/bnxt.c
> +++ b/drivers/net/ethernet/broadcom/bnxt/bnxt.c
> @@ -52,8 +52,6 @@
>  #include <linux/cpu_rmap.h>
>  #include <linux/cpumask.h>
>  #include <net/pkt_cls.h>
> -#include <linux/hwmon.h>
> -#include <linux/hwmon-sysfs.h>
>  #include <net/page_pool/helpers.h>
>  #include <linux/align.h>
>  #include <net/netdev_queues.h>
> @@ -71,6 +69,7 @@
>  #include "bnxt_tc.h"
>  #include "bnxt_devlink.h"
>  #include "bnxt_debugfs.h"
> +#include "bnxt_hwmon.h"
>  
>  #define BNXT_TX_TIMEOUT		(5 * HZ)
>  #define BNXT_DEF_MSG_ENABLE	(NETIF_MSG_DRV | NETIF_MSG_HW | \
> @@ -10250,79 +10249,6 @@ static void bnxt_get_wol_settings(struct bnxt *bp)
>  	} while (handle && handle != 0xffff);
>  }
>  
> -#ifdef CONFIG_BNXT_HWMON
> -static ssize_t bnxt_show_temp(struct device *dev,
> -			      struct device_attribute *devattr, char *buf)
> -{
> -	struct hwrm_temp_monitor_query_output *resp;
> -	struct hwrm_temp_monitor_query_input *req;
> -	struct bnxt *bp = dev_get_drvdata(dev);
> -	u32 len = 0;
> -	int rc;
> -
> -	rc = hwrm_req_init(bp, req, HWRM_TEMP_MONITOR_QUERY);
> -	if (rc)
> -		return rc;
> -	resp = hwrm_req_hold(bp, req);
> -	rc = hwrm_req_send(bp, req);
> -	if (!rc)
> -		len = sprintf(buf, "%u\n", resp->temp * 1000); /* display millidegree */
> -	hwrm_req_drop(bp, req);
> -	if (rc)
> -		return rc;
> -	return len;
> -}
> -static SENSOR_DEVICE_ATTR(temp1_input, 0444, bnxt_show_temp, NULL, 0);
> -
> -static struct attribute *bnxt_attrs[] = {
> -	&sensor_dev_attr_temp1_input.dev_attr.attr,
> -	NULL
> -};
> -ATTRIBUTE_GROUPS(bnxt);
> -
> -static void bnxt_hwmon_uninit(struct bnxt *bp)
> -{
> -	if (bp->hwmon_dev) {
> -		hwmon_device_unregister(bp->hwmon_dev);
> -		bp->hwmon_dev = NULL;
> -	}
> -}
> -
> -static void bnxt_hwmon_init(struct bnxt *bp)
> -{
> -	struct hwrm_temp_monitor_query_input *req;
> -	struct pci_dev *pdev = bp->pdev;
> -	int rc;
> -
> -	rc = hwrm_req_init(bp, req, HWRM_TEMP_MONITOR_QUERY);
> -	if (!rc)
> -		rc = hwrm_req_send_silent(bp, req);
> -	if (rc == -EACCES || rc == -EOPNOTSUPP) {
> -		bnxt_hwmon_uninit(bp);
> -		return;
> -	}
> -
> -	if (bp->hwmon_dev)
> -		return;
> -
> -	bp->hwmon_dev = hwmon_device_register_with_groups(&pdev->dev,
> -							  DRV_MODULE_NAME, bp,
> -							  bnxt_groups);
> -	if (IS_ERR(bp->hwmon_dev)) {
> -		bp->hwmon_dev = NULL;
> -		dev_warn(&pdev->dev, "Cannot register hwmon device\n");
> -	}
> -}
> -#else
> -static void bnxt_hwmon_uninit(struct bnxt *bp)
> -{
> -}
> -
> -static void bnxt_hwmon_init(struct bnxt *bp)
> -{
> -}
> -#endif
> -
>  static bool bnxt_eee_config_ok(struct bnxt *bp)
>  {
>  	struct ethtool_eee *eee = &bp->eee;
> diff --git a/drivers/net/ethernet/broadcom/bnxt/bnxt_hwmon.c b/drivers/net/ethernet/broadcom/bnxt/bnxt_hwmon.c
> new file mode 100644
> index 000000000000..476616d97071
> --- /dev/null
> +++ b/drivers/net/ethernet/broadcom/bnxt/bnxt_hwmon.c
> @@ -0,0 +1,82 @@
> +/* Broadcom NetXtreme-C/E network driver.
> + *
> + * Copyright (c) 2023 Broadcom Limited
> + *
> + * This program is free software; you can redistribute it and/or modify
> + * it under the terms of the GNU General Public License as published by
> + * the Free Software Foundation.
> + */
> +
> +#include <linux/dev_printk.h>
> +#include <linux/errno.h>
> +#include <linux/hwmon.h>
> +#include <linux/hwmon-sysfs.h>
> +#include <linux/pci.h>
> +
> +#include "bnxt_hsi.h"
> +#include "bnxt.h"
> +#include "bnxt_hwrm.h"
> +#include "bnxt_hwmon.h"
> +
> +static ssize_t bnxt_show_temp(struct device *dev,
> +			      struct device_attribute *devattr, char *buf)
> +{
> +	struct hwrm_temp_monitor_query_output *resp;
> +	struct hwrm_temp_monitor_query_input *req;
> +	struct bnxt *bp = dev_get_drvdata(dev);
> +	u32 len = 0;
> +	int rc;
> +
> +	rc = hwrm_req_init(bp, req, HWRM_TEMP_MONITOR_QUERY);
> +	if (rc)
> +		return rc;
> +	resp = hwrm_req_hold(bp, req);
> +	rc = hwrm_req_send(bp, req);
> +	if (!rc)
> +		len = sprintf(buf, "%u\n", resp->temp * 1000); /* display millidegree */
> +	hwrm_req_drop(bp, req);
> +	if (rc)
> +		return rc;
> +	return len;
> +}
> +static SENSOR_DEVICE_ATTR(temp1_input, 0444, bnxt_show_temp, NULL, 0);
> +
> +static struct attribute *bnxt_attrs[] = {
> +	&sensor_dev_attr_temp1_input.dev_attr.attr,
> +	NULL
> +};
> +ATTRIBUTE_GROUPS(bnxt);
> +
> +void bnxt_hwmon_uninit(struct bnxt *bp)
> +{
> +	if (bp->hwmon_dev) {
> +		hwmon_device_unregister(bp->hwmon_dev);
> +		bp->hwmon_dev = NULL;
> +	}
> +}
> +
> +void bnxt_hwmon_init(struct bnxt *bp)
> +{
> +	struct hwrm_temp_monitor_query_input *req;
> +	struct pci_dev *pdev = bp->pdev;
> +	int rc;
> +
> +	rc = hwrm_req_init(bp, req, HWRM_TEMP_MONITOR_QUERY);
> +	if (!rc)
> +		rc = hwrm_req_send_silent(bp, req);
> +	if (rc == -EACCES || rc == -EOPNOTSUPP) {
> +		bnxt_hwmon_uninit(bp);
> +		return;
> +	}
> +
> +	if (bp->hwmon_dev)
> +		return;
> +
> +	bp->hwmon_dev = hwmon_device_register_with_groups(&pdev->dev,
> +							  DRV_MODULE_NAME, bp,
> +							  bnxt_groups);
> +	if (IS_ERR(bp->hwmon_dev)) {
> +		bp->hwmon_dev = NULL;
> +		dev_warn(&pdev->dev, "Cannot register hwmon device\n");
> +	}
> +}
> diff --git a/drivers/net/ethernet/broadcom/bnxt/bnxt_hwmon.h b/drivers/net/ethernet/broadcom/bnxt/bnxt_hwmon.h
> new file mode 100644
> index 000000000000..af310066687c
> --- /dev/null
> +++ b/drivers/net/ethernet/broadcom/bnxt/bnxt_hwmon.h
> @@ -0,0 +1,25 @@
> +/* Broadcom NetXtreme-C/E network driver.
> + *
> + * Copyright (c) 2023 Broadcom Limited
> + *
> + * This program is free software; you can redistribute it and/or modify
> + * it under the terms of the GNU General Public License as published by
> + * the Free Software Foundation.
> + */
> +
> +#ifndef BNXT_HWMON_H
> +#define BNXT_HWMON_H
> +
> +#ifdef CONFIG_BNXT_HWMON
> +void bnxt_hwmon_uninit(struct bnxt *bp);
> +void bnxt_hwmon_init(struct bnxt *bp);
> +#else
> +static inline void bnxt_hwmon_uninit(struct bnxt *bp)
> +{
> +}
> +
> +static inline void bnxt_hwmon_init(struct bnxt *bp)
> +{
> +}
> +#endif
> +#endif
> -- 
> 2.30.1
> 



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

* Re: [PATCH net-next v2 4/9] bnxt_en: Modify the driver to use hwmon_device_register_with_info
  2023-09-27  3:57 ` [PATCH net-next v2 4/9] bnxt_en: Modify the driver to use hwmon_device_register_with_info Michael Chan
@ 2023-09-27 13:56   ` Guenter Roeck
  0 siblings, 0 replies; 8+ messages in thread
From: Guenter Roeck @ 2023-09-27 13:56 UTC (permalink / raw)
  To: Michael Chan
  Cc: davem, netdev, edumazet, kuba, pabeni, gospo, Kalesh AP,
	Jean Delvare, linux-hwmon

On Tue, Sep 26, 2023 at 08:57:29PM -0700, Michael Chan wrote:
> From: Kalesh AP <kalesh-anakkur.purayil@broadcom.com>
> 
> The use of hwmon_device_register_with_groups() is deprecated.
> Modified the driver to use hwmon_device_register_with_info().
> 
> Driver currently exports only temp1_input through hwmon sysfs
> interface. But FW has been modified to report more threshold
> temperatures and driver want to report them through the
> hwmon interface.
> 
> Cc: Jean Delvare <jdelvare@suse.com>
> Cc: Guenter Roeck <linux@roeck-us.net>
> Cc: linux-hwmon@vger.kernel.org
> Signed-off-by: Kalesh AP <kalesh-anakkur.purayil@broadcom.com>
> Signed-off-by: Michael Chan <michael.chan@broadcom.com>

Acked-by: Guenter Roeck <linux@roeck-us.net>

> ---
>  .../net/ethernet/broadcom/bnxt/bnxt_hwmon.c   | 71 ++++++++++++++-----
>  1 file changed, 55 insertions(+), 16 deletions(-)
> 
> diff --git a/drivers/net/ethernet/broadcom/bnxt/bnxt_hwmon.c b/drivers/net/ethernet/broadcom/bnxt/bnxt_hwmon.c
> index 476616d97071..05e3d75f3c43 100644
> --- a/drivers/net/ethernet/broadcom/bnxt/bnxt_hwmon.c
> +++ b/drivers/net/ethernet/broadcom/bnxt/bnxt_hwmon.c
> @@ -18,34 +18,73 @@
>  #include "bnxt_hwrm.h"
>  #include "bnxt_hwmon.h"
>  
> -static ssize_t bnxt_show_temp(struct device *dev,
> -			      struct device_attribute *devattr, char *buf)
> +static int bnxt_hwrm_temp_query(struct bnxt *bp, u8 *temp)
>  {
>  	struct hwrm_temp_monitor_query_output *resp;
>  	struct hwrm_temp_monitor_query_input *req;
> -	struct bnxt *bp = dev_get_drvdata(dev);
> -	u32 len = 0;
>  	int rc;
>  
>  	rc = hwrm_req_init(bp, req, HWRM_TEMP_MONITOR_QUERY);
>  	if (rc)
>  		return rc;
>  	resp = hwrm_req_hold(bp, req);
> -	rc = hwrm_req_send(bp, req);
> -	if (!rc)
> -		len = sprintf(buf, "%u\n", resp->temp * 1000); /* display millidegree */
> -	hwrm_req_drop(bp, req);
> +	rc = hwrm_req_send_silent(bp, req);
>  	if (rc)
> +		goto drop_req;
> +
> +	*temp = resp->temp;
> +
> +drop_req:
> +	hwrm_req_drop(bp, req);
> +	return rc;
> +}
> +
> +static umode_t bnxt_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_input:
> +		return 0444;
> +	default:
> +		return 0;
> +	}
> +}
> +
> +static int bnxt_hwmon_read(struct device *dev, enum hwmon_sensor_types type, u32 attr,
> +			   int channel, long *val)
> +{
> +	struct bnxt *bp = dev_get_drvdata(dev);
> +	u8 temp = 0;
> +	int rc;
> +
> +	switch (attr) {
> +	case hwmon_temp_input:
> +		rc = bnxt_hwrm_temp_query(bp, &temp);
> +		if (!rc)
> +			*val = temp * 1000;
>  		return rc;
> -	return len;
> +	default:
> +		return -EOPNOTSUPP;
> +	}
>  }
> -static SENSOR_DEVICE_ATTR(temp1_input, 0444, bnxt_show_temp, NULL, 0);
>  
> -static struct attribute *bnxt_attrs[] = {
> -	&sensor_dev_attr_temp1_input.dev_attr.attr,
> +static const struct hwmon_channel_info *bnxt_hwmon_info[] = {
> +	HWMON_CHANNEL_INFO(temp, HWMON_T_INPUT),
>  	NULL
>  };
> -ATTRIBUTE_GROUPS(bnxt);
> +
> +static const struct hwmon_ops bnxt_hwmon_ops = {
> +	.is_visible     = bnxt_hwmon_is_visible,
> +	.read           = bnxt_hwmon_read,
> +};
> +
> +static const struct hwmon_chip_info bnxt_hwmon_chip_info = {
> +	.ops    = &bnxt_hwmon_ops,
> +	.info   = bnxt_hwmon_info,
> +};
>  
>  void bnxt_hwmon_uninit(struct bnxt *bp)
>  {
> @@ -72,9 +111,9 @@ void bnxt_hwmon_init(struct bnxt *bp)
>  	if (bp->hwmon_dev)
>  		return;
>  
> -	bp->hwmon_dev = hwmon_device_register_with_groups(&pdev->dev,
> -							  DRV_MODULE_NAME, bp,
> -							  bnxt_groups);
> +	bp->hwmon_dev = hwmon_device_register_with_info(&pdev->dev,
> +							DRV_MODULE_NAME, bp,
> +							&bnxt_hwmon_chip_info, NULL);
>  	if (IS_ERR(bp->hwmon_dev)) {
>  		bp->hwmon_dev = NULL;
>  		dev_warn(&pdev->dev, "Cannot register hwmon device\n");
> -- 
> 2.30.1
> 



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

* Re: [PATCH net-next v2 5/9] bnxt_en: Expose threshold temperatures through hwmon
  2023-09-27  3:57 ` [PATCH net-next v2 5/9] bnxt_en: Expose threshold temperatures through hwmon Michael Chan
@ 2023-09-27 14:04   ` Guenter Roeck
  0 siblings, 0 replies; 8+ messages in thread
From: Guenter Roeck @ 2023-09-27 14:04 UTC (permalink / raw)
  To: Michael Chan
  Cc: davem, netdev, edumazet, kuba, pabeni, gospo, Kalesh AP,
	Jean Delvare, linux-hwmon

On Tue, Sep 26, 2023 at 08:57:30PM -0700, Michael Chan wrote:
> From: Kalesh AP <kalesh-anakkur.purayil@broadcom.com>
> 
> HWRM_TEMP_MONITOR_QUERY response now indicates various
> threshold temperatures. Expose these threshold temperatures
> through the hwmon sysfs using this mapping:
> 
> hwmon_temp_max : bp->warn_thresh_temp
> hwmon_temp_crit : bp->crit_thresh_temp
> hwmon_temp_emergency : bp->fatal_thresh_temp
> 
> hwmon_temp_max_alarm : temp >= bp->warn_thresh_temp
> hwmon_temp_crit_alarm : temp >= bp->crit_thresh_temp
> hwmon_temp_emergency_alarm : temp >= bp->fatal_thresh_temp
> 
> Link: https://lore.kernel.org/netdev/20230815045658.80494-12-michael.chan@broadcom.com/
> Cc: Jean Delvare <jdelvare@suse.com>
> Cc: Guenter Roeck <linux@roeck-us.net>
> Cc: linux-hwmon@vger.kernel.org
> Signed-off-by: Kalesh AP <kalesh-anakkur.purayil@broadcom.com>
> Signed-off-by: Michael Chan <michael.chan@broadcom.com>

Acked-by: Guenter Roeck <linux@roeck-us.net>

> ---
> v2:
> bnxt_hwrm_temp_query() now stores the static threshold values once.
> Use new hwmon temperature mappings shown above and remove hwmon_temp_lcrit.
> 
> ---
>  drivers/net/ethernet/broadcom/bnxt/bnxt.h     |  7 +++
>  .../net/ethernet/broadcom/bnxt/bnxt_hwmon.c   | 57 ++++++++++++++++---
>  2 files changed, 57 insertions(+), 7 deletions(-)
> 
> diff --git a/drivers/net/ethernet/broadcom/bnxt/bnxt.h b/drivers/net/ethernet/broadcom/bnxt/bnxt.h
> index 84cbcfa61bc1..43a07d84f815 100644
> --- a/drivers/net/ethernet/broadcom/bnxt/bnxt.h
> +++ b/drivers/net/ethernet/broadcom/bnxt/bnxt.h
> @@ -2013,6 +2013,7 @@ struct bnxt {
>  	#define BNXT_FW_CAP_RING_MONITOR		BIT_ULL(30)
>  	#define BNXT_FW_CAP_DBG_QCAPS			BIT_ULL(31)
>  	#define BNXT_FW_CAP_PTP				BIT_ULL(32)
> +	#define BNXT_FW_CAP_THRESHOLD_TEMP_SUPPORTED	BIT_ULL(33)
>  
>  	u32			fw_dbg_cap;
>  
> @@ -2185,7 +2186,13 @@ struct bnxt {
>  	struct bnxt_tc_info	*tc_info;
>  	struct list_head	tc_indr_block_list;
>  	struct dentry		*debugfs_pdev;
> +#ifdef CONFIG_BNXT_HWMON
>  	struct device		*hwmon_dev;
> +	u8			warn_thresh_temp;
> +	u8			crit_thresh_temp;
> +	u8			fatal_thresh_temp;
> +	u8			shutdown_thresh_temp;
> +#endif
>  	enum board_idx		board_idx;
>  };
>  
> diff --git a/drivers/net/ethernet/broadcom/bnxt/bnxt_hwmon.c b/drivers/net/ethernet/broadcom/bnxt/bnxt_hwmon.c
> index 05e3d75f3c43..6a2cad5cc159 100644
> --- a/drivers/net/ethernet/broadcom/bnxt/bnxt_hwmon.c
> +++ b/drivers/net/ethernet/broadcom/bnxt/bnxt_hwmon.c
> @@ -32,8 +32,16 @@ static int bnxt_hwrm_temp_query(struct bnxt *bp, u8 *temp)
>  	if (rc)
>  		goto drop_req;
>  
> -	*temp = resp->temp;
> -
> +	if (temp) {
> +		*temp = resp->temp;
> +	} else if (resp->flags &
> +		   TEMP_MONITOR_QUERY_RESP_FLAGS_THRESHOLD_VALUES_AVAILABLE) {
> +		bp->fw_cap |= BNXT_FW_CAP_THRESHOLD_TEMP_SUPPORTED;
> +		bp->warn_thresh_temp = resp->warn_threshold;
> +		bp->crit_thresh_temp = resp->critical_threshold;
> +		bp->fatal_thresh_temp = resp->fatal_threshold;
> +		bp->shutdown_thresh_temp = resp->shutdown_threshold;
> +	}
>  drop_req:
>  	hwrm_req_drop(bp, req);
>  	return rc;
> @@ -42,12 +50,23 @@ static int bnxt_hwrm_temp_query(struct bnxt *bp, u8 *temp)
>  static umode_t bnxt_hwmon_is_visible(const void *_data, enum hwmon_sensor_types type,
>  				     u32 attr, int channel)
>  {
> +	const struct bnxt *bp = _data;
> +
>  	if (type != hwmon_temp)
>  		return 0;
>  
>  	switch (attr) {
>  	case hwmon_temp_input:
>  		return 0444;
> +	case hwmon_temp_max:
> +	case hwmon_temp_crit:
> +	case hwmon_temp_emergency:
> +	case hwmon_temp_max_alarm:
> +	case hwmon_temp_crit_alarm:
> +	case hwmon_temp_emergency_alarm:
> +		if (!(bp->fw_cap & BNXT_FW_CAP_THRESHOLD_TEMP_SUPPORTED))
> +			return 0;
> +		return 0444;
>  	default:
>  		return 0;
>  	}
> @@ -66,13 +85,39 @@ static int bnxt_hwmon_read(struct device *dev, enum hwmon_sensor_types type, u32
>  		if (!rc)
>  			*val = temp * 1000;
>  		return rc;
> +	case hwmon_temp_max:
> +		*val = bp->warn_thresh_temp * 1000;
> +		return 0;
> +	case hwmon_temp_crit:
> +		*val = bp->crit_thresh_temp * 1000;
> +		return 0;
> +	case hwmon_temp_emergency:
> +		*val = bp->fatal_thresh_temp * 1000;
> +		return 0;
> +	case hwmon_temp_max_alarm:
> +		rc = bnxt_hwrm_temp_query(bp, &temp);
> +		if (!rc)
> +			*val = temp >= bp->warn_thresh_temp;
> +		return rc;
> +	case hwmon_temp_crit_alarm:
> +		rc = bnxt_hwrm_temp_query(bp, &temp);
> +		if (!rc)
> +			*val = temp >= bp->crit_thresh_temp;
> +		return rc;
> +	case hwmon_temp_emergency_alarm:
> +		rc = bnxt_hwrm_temp_query(bp, &temp);
> +		if (!rc)
> +			*val = temp >= bp->fatal_thresh_temp;
> +		return rc;
>  	default:
>  		return -EOPNOTSUPP;
>  	}
>  }
>  
>  static const struct hwmon_channel_info *bnxt_hwmon_info[] = {
> -	HWMON_CHANNEL_INFO(temp, HWMON_T_INPUT),
> +	HWMON_CHANNEL_INFO(temp, HWMON_T_INPUT | HWMON_T_MAX | HWMON_T_CRIT |
> +			   HWMON_T_EMERGENCY | HWMON_T_MAX_ALARM |
> +			   HWMON_T_CRIT_ALARM | HWMON_T_EMERGENCY_ALARM),
>  	NULL
>  };
>  
> @@ -96,13 +141,11 @@ void bnxt_hwmon_uninit(struct bnxt *bp)
>  
>  void bnxt_hwmon_init(struct bnxt *bp)
>  {
> -	struct hwrm_temp_monitor_query_input *req;
>  	struct pci_dev *pdev = bp->pdev;
>  	int rc;
>  
> -	rc = hwrm_req_init(bp, req, HWRM_TEMP_MONITOR_QUERY);
> -	if (!rc)
> -		rc = hwrm_req_send_silent(bp, req);
> +	/* temp1_xxx is only sensor, ensure not registered if it will fail */
> +	rc = bnxt_hwrm_temp_query(bp, NULL);
>  	if (rc == -EACCES || rc == -EOPNOTSUPP) {
>  		bnxt_hwmon_uninit(bp);
>  		return;
> -- 
> 2.30.1
> 



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

* Re: [PATCH net-next v2 7/9] bnxt_en: Event handler for Thermal event
  2023-09-27  3:57 ` [PATCH net-next v2 7/9] bnxt_en: Event handler for Thermal event Michael Chan
@ 2023-09-27 14:05   ` Guenter Roeck
  0 siblings, 0 replies; 8+ messages in thread
From: Guenter Roeck @ 2023-09-27 14:05 UTC (permalink / raw)
  To: Michael Chan
  Cc: davem, netdev, edumazet, kuba, pabeni, gospo, Kalesh AP,
	Jean Delvare, linux-hwmon

On Tue, Sep 26, 2023 at 08:57:32PM -0700, Michael Chan wrote:
> From: Kalesh AP <kalesh-anakkur.purayil@broadcom.com>
> 
> Newer FW will send a new async event when it detects that
> the chip's temperature has crossed the configured threshold value.
> The driver will now notify hwmon and will log a warning message.
> 
> Link: https://lore.kernel.org/netdev/20230815045658.80494-13-michael.chan@broadcom.com/
> Cc: Jean Delvare <jdelvare@suse.com>
> Cc: Guenter Roeck <linux@roeck-us.net>
> Cc: linux-hwmon@vger.kernel.org
> Signed-off-by: Kalesh AP <kalesh-anakkur.purayil@broadcom.com>
> Signed-off-by: Michael Chan <michael.chan@broadcom.com>

Acked-by: Guenter Roeck <linux@roeck-us.net>

> ---
> v2:
> Remove hwmon dependencies from bnxt.c.
> 
> ---
>  drivers/net/ethernet/broadcom/bnxt/bnxt.c     | 52 +++++++++++++++++++
>  .../net/ethernet/broadcom/bnxt/bnxt_hwmon.c   | 25 +++++++++
>  .../net/ethernet/broadcom/bnxt/bnxt_hwmon.h   |  5 ++
>  3 files changed, 82 insertions(+)
> 
> diff --git a/drivers/net/ethernet/broadcom/bnxt/bnxt.c b/drivers/net/ethernet/broadcom/bnxt/bnxt.c
> index b83f8de0a015..7104237272de 100644
> --- a/drivers/net/ethernet/broadcom/bnxt/bnxt.c
> +++ b/drivers/net/ethernet/broadcom/bnxt/bnxt.c
> @@ -2129,6 +2129,24 @@ static u16 bnxt_agg_ring_id_to_grp_idx(struct bnxt *bp, u16 ring_id)
>  	return INVALID_HW_RING_ID;
>  }
>  
> +#define BNXT_EVENT_THERMAL_CURRENT_TEMP(data2)				\
> +	((data2) &							\
> +	  ASYNC_EVENT_CMPL_ERROR_REPORT_THERMAL_EVENT_DATA2_CURRENT_TEMP_MASK)
> +
> +#define BNXT_EVENT_THERMAL_THRESHOLD_TEMP(data2)			\
> +	(((data2) &							\
> +	  ASYNC_EVENT_CMPL_ERROR_REPORT_THERMAL_EVENT_DATA2_THRESHOLD_TEMP_MASK) >>\
> +	 ASYNC_EVENT_CMPL_ERROR_REPORT_THERMAL_EVENT_DATA2_THRESHOLD_TEMP_SFT)
> +
> +#define EVENT_DATA1_THERMAL_THRESHOLD_TYPE(data1)			\
> +	((data1) &							\
> +	 ASYNC_EVENT_CMPL_ERROR_REPORT_THERMAL_EVENT_DATA1_THRESHOLD_TYPE_MASK)
> +
> +#define EVENT_DATA1_THERMAL_THRESHOLD_DIR_INCREASING(data1)		\
> +	(((data1) &							\
> +	  ASYNC_EVENT_CMPL_ERROR_REPORT_THERMAL_EVENT_DATA1_TRANSITION_DIR) ==\
> +	 ASYNC_EVENT_CMPL_ERROR_REPORT_THERMAL_EVENT_DATA1_TRANSITION_DIR_INCREASING)
> +
>  static void bnxt_event_error_report(struct bnxt *bp, u32 data1, u32 data2)
>  {
>  	u32 err_type = BNXT_EVENT_ERROR_REPORT_TYPE(data1);
> @@ -2144,6 +2162,40 @@ static void bnxt_event_error_report(struct bnxt *bp, u32 data1, u32 data2)
>  	case ASYNC_EVENT_CMPL_ERROR_REPORT_BASE_EVENT_DATA1_ERROR_TYPE_DOORBELL_DROP_THRESHOLD:
>  		netdev_warn(bp->dev, "One or more MMIO doorbells dropped by the device!\n");
>  		break;
> +	case ASYNC_EVENT_CMPL_ERROR_REPORT_BASE_EVENT_DATA1_ERROR_TYPE_THERMAL_THRESHOLD: {
> +		u32 type = EVENT_DATA1_THERMAL_THRESHOLD_TYPE(data1);
> +		char *threshold_type;
> +		char *dir_str;
> +
> +		switch (type) {
> +		case ASYNC_EVENT_CMPL_ERROR_REPORT_THERMAL_EVENT_DATA1_THRESHOLD_TYPE_WARN:
> +			threshold_type = "warning";
> +			break;
> +		case ASYNC_EVENT_CMPL_ERROR_REPORT_THERMAL_EVENT_DATA1_THRESHOLD_TYPE_CRITICAL:
> +			threshold_type = "critical";
> +			break;
> +		case ASYNC_EVENT_CMPL_ERROR_REPORT_THERMAL_EVENT_DATA1_THRESHOLD_TYPE_FATAL:
> +			threshold_type = "fatal";
> +			break;
> +		case ASYNC_EVENT_CMPL_ERROR_REPORT_THERMAL_EVENT_DATA1_THRESHOLD_TYPE_SHUTDOWN:
> +			threshold_type = "shutdown";
> +			break;
> +		default:
> +			netdev_err(bp->dev, "Unknown Thermal threshold type event\n");
> +			return;
> +		}
> +		if (EVENT_DATA1_THERMAL_THRESHOLD_DIR_INCREASING(data1))
> +			dir_str = "above";
> +		else
> +			dir_str = "below";
> +		netdev_warn(bp->dev, "Chip temperature has gone %s the %s thermal threshold!\n",
> +			    dir_str, threshold_type);
> +		netdev_warn(bp->dev, "Temperature (In Celsius), Current: %lu, threshold: %lu\n",
> +			    BNXT_EVENT_THERMAL_CURRENT_TEMP(data2),
> +			    BNXT_EVENT_THERMAL_THRESHOLD_TEMP(data2));
> +		bnxt_hwmon_notify_event(bp, type);
> +		break;
> +	}
>  	default:
>  		netdev_err(bp->dev, "FW reported unknown error type %u\n",
>  			   err_type);
> diff --git a/drivers/net/ethernet/broadcom/bnxt/bnxt_hwmon.c b/drivers/net/ethernet/broadcom/bnxt/bnxt_hwmon.c
> index 6d36158df26e..e48094043c3b 100644
> --- a/drivers/net/ethernet/broadcom/bnxt/bnxt_hwmon.c
> +++ b/drivers/net/ethernet/broadcom/bnxt/bnxt_hwmon.c
> @@ -18,6 +18,31 @@
>  #include "bnxt_hwrm.h"
>  #include "bnxt_hwmon.h"
>  
> +void bnxt_hwmon_notify_event(struct bnxt *bp, u32 type)
> +{
> +	u32 attr;
> +
> +	if (!bp->hwmon_dev)
> +		return;
> +
> +	switch (type) {
> +	case ASYNC_EVENT_CMPL_ERROR_REPORT_THERMAL_EVENT_DATA1_THRESHOLD_TYPE_WARN:
> +		attr = hwmon_temp_max_alarm;
> +		break;
> +	case ASYNC_EVENT_CMPL_ERROR_REPORT_THERMAL_EVENT_DATA1_THRESHOLD_TYPE_CRITICAL:
> +		attr = hwmon_temp_crit_alarm;
> +		break;
> +	case ASYNC_EVENT_CMPL_ERROR_REPORT_THERMAL_EVENT_DATA1_THRESHOLD_TYPE_FATAL:
> +	case ASYNC_EVENT_CMPL_ERROR_REPORT_THERMAL_EVENT_DATA1_THRESHOLD_TYPE_SHUTDOWN:
> +		attr = hwmon_temp_emergency_alarm;
> +		break;
> +	default:
> +		return;
> +	}
> +
> +	hwmon_notify_event(&bp->pdev->dev, hwmon_temp, attr, 0);
> +}
> +
>  static int bnxt_hwrm_temp_query(struct bnxt *bp, u8 *temp)
>  {
>  	struct hwrm_temp_monitor_query_output *resp;
> diff --git a/drivers/net/ethernet/broadcom/bnxt/bnxt_hwmon.h b/drivers/net/ethernet/broadcom/bnxt/bnxt_hwmon.h
> index af310066687c..76d9f599ebc0 100644
> --- a/drivers/net/ethernet/broadcom/bnxt/bnxt_hwmon.h
> +++ b/drivers/net/ethernet/broadcom/bnxt/bnxt_hwmon.h
> @@ -11,9 +11,14 @@
>  #define BNXT_HWMON_H
>  
>  #ifdef CONFIG_BNXT_HWMON
> +void bnxt_hwmon_notify_event(struct bnxt *bp, u32 type);
>  void bnxt_hwmon_uninit(struct bnxt *bp);
>  void bnxt_hwmon_init(struct bnxt *bp);
>  #else
> +static inline void bnxt_hwmon_notify_event(struct bnxt *bp, u32 type)
> +{
> +}
> +
>  static inline void bnxt_hwmon_uninit(struct bnxt *bp)
>  {
>  }
> -- 
> 2.30.1
> 



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

end of thread, other threads:[~2023-09-27 14:05 UTC | newest]

Thread overview: 8+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
     [not found] <20230927035734.42816-1-michael.chan@broadcom.com>
2023-09-27  3:57 ` [PATCH net-next v2 3/9] bnxt_en: Move hwmon functions into a dedicated file Michael Chan
2023-09-27 13:55   ` Guenter Roeck
2023-09-27  3:57 ` [PATCH net-next v2 4/9] bnxt_en: Modify the driver to use hwmon_device_register_with_info Michael Chan
2023-09-27 13:56   ` Guenter Roeck
2023-09-27  3:57 ` [PATCH net-next v2 5/9] bnxt_en: Expose threshold temperatures through hwmon Michael Chan
2023-09-27 14:04   ` Guenter Roeck
2023-09-27  3:57 ` [PATCH net-next v2 7/9] bnxt_en: Event handler for Thermal event Michael Chan
2023-09-27 14:05   ` Guenter Roeck

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox