Linux Documentation
 help / color / mirror / Atom feed
* [PATCH v2 0/2] AMD PROM21 xHCI temperature hwmon support
       [not found] <20260506032939.92351-1-hurryman2212@gmail.com>
@ 2026-05-06 20:40 ` Jihong Min
  2026-05-06 20:40   ` [PATCH v2 1/2] usb: xhci-pci: add generic auxiliary device interface Jihong Min
  2026-05-06 20:40   ` [PATCH v2 2/2] hwmon: add initial support for AMD PROM21 xHCI temperature sensor Jihong Min
  0 siblings, 2 replies; 16+ messages in thread
From: Jihong Min @ 2026-05-06 20:40 UTC (permalink / raw)
  To: Greg Kroah-Hartman, Mathias Nyman
  Cc: Guenter Roeck, Jonathan Corbet, Shuah Khan, Mario Limonciello,
	Basavaraj Natikar, linux-usb, linux-hwmon, linux-doc, linux-pci,
	linux-kernel, Jihong Min

Hi,

This series adds hwmon support for the temperature sensor exposed by AMD
PROM21 xHCI controllers. The temperature value is read through a
vendor-specific index/data register pair in the xHCI PCI MMIO BAR.

v1 implemented this directly under drivers/usb/host. Based on review
feedback, v2 splits the support into a generic xhci-pci auxiliary-device
interface and a standalone hwmon driver under drivers/hwmon. xhci-pci
creates the auxiliary child only for PCI IDs matched by its internal table,
currently only AMD 1022:43fd, and the hwmon driver binds to that child
through the auxiliary bus.

The PROM21 hwmon driver registers the hwmon device under the parent PCI
function so userspace reports it as a PCI adapter. The auxiliary driver
still owns the lifetime and unregisters the hwmon device before xhci-pci
tears down the HCD.

I tested register access while the parent xHCI PCI function was suspended.
The temperature register did not return a valid value without
runtime-resuming the device. v2 therefore keeps the default behavior of
allowing a temperature read to wake the xHCI PCI device, and adds
allow_pm_switch=N for users who prefer reads not to wake the device. In
that mode a read returns -EAGAIN while the device is suspended.

Changes in v2:
- split the original single patch into a two-patch series
- add a generic xhci-pci auxiliary-device interface
- move PROM21 hwmon support to drivers/hwmon as an auxiliary driver
- avoid linking hwmon-specific code into xhci-hcd
- add Documentation/hwmon/prom21-hwmon.rst
- document register offsets, conversion formula, sysfs attributes, and
  allow_pm_switch behavior

Sincerely,
Jihong Min

Jihong Min (2):
  usb: xhci-pci: add generic auxiliary device interface
  hwmon: add initial support for AMD PROM21 xHCI temperature sensor

 Documentation/hwmon/index.rst        |   1 +
 Documentation/hwmon/prom21-hwmon.rst |  84 ++++++++
 drivers/hwmon/Kconfig                |  11 +
 drivers/hwmon/Makefile               |   1 +
 drivers/hwmon/prom21-hwmon.c         | 300 +++++++++++++++++++++++++++
 drivers/usb/host/Kconfig             |  10 +
 drivers/usb/host/xhci-pci.c          | 114 ++++++++++
 7 files changed, 521 insertions(+)
 create mode 100644 Documentation/hwmon/prom21-hwmon.rst
 create mode 100644 drivers/hwmon/prom21-hwmon.c

-- 
2.53.0

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

* [PATCH v2 1/2] usb: xhci-pci: add generic auxiliary device interface
  2026-05-06 20:40 ` [PATCH v2 0/2] AMD PROM21 xHCI temperature hwmon support Jihong Min
@ 2026-05-06 20:40   ` Jihong Min
  2026-05-06 20:53     ` Mario Limonciello
  2026-05-06 21:15     ` Michal Pecio
  2026-05-06 20:40   ` [PATCH v2 2/2] hwmon: add initial support for AMD PROM21 xHCI temperature sensor Jihong Min
  1 sibling, 2 replies; 16+ messages in thread
From: Jihong Min @ 2026-05-06 20:40 UTC (permalink / raw)
  To: Greg Kroah-Hartman, Mathias Nyman
  Cc: Guenter Roeck, Jonathan Corbet, Shuah Khan, Mario Limonciello,
	Basavaraj Natikar, linux-usb, linux-hwmon, linux-doc, linux-pci,
	linux-kernel, Jihong Min

Some xHCI PCI controllers expose controller-specific functionality that is
not part of generic xHCI operation and is better handled by optional child
drivers in other subsystems. Add a small auxiliary device registration path
for selected xHCI PCI controllers.

The initial table creates an xhci_pci.hwmon auxiliary device for AMD
1022:43fd controllers. Store the created auxiliary device in devres so the
xhci-pci remove path destroys it before HCD teardown. Use a
PCI-domain-qualified id so auxiliary device names remain unique across PCI
domains.

This keeps xhci-pci responsible only for publishing selected controller
functions while allowing subsystem-specific drivers to bind through the
auxiliary bus.

Assisted-by: Codex:gpt-5.5
Signed-off-by: Jihong Min <hurryman2212@gmail.com>
---
 drivers/usb/host/Kconfig    |  10 ++++
 drivers/usb/host/xhci-pci.c | 114 ++++++++++++++++++++++++++++++++++++
 2 files changed, 124 insertions(+)

diff --git a/drivers/usb/host/Kconfig b/drivers/usb/host/Kconfig
index 0a277a07cf70..e0c2c7ac5c97 100644
--- a/drivers/usb/host/Kconfig
+++ b/drivers/usb/host/Kconfig
@@ -42,6 +42,16 @@ config USB_XHCI_PCI
 	depends on USB_PCI
 	default y
 
+config USB_XHCI_PCI_AUXDEV
+	bool "xHCI PCI auxiliary device support"
+	depends on USB_XHCI_PCI
+	select AUXILIARY_BUS
+	help
+	  This enables xHCI PCI support for registering auxiliary devices
+	  for selected controllers. It is used by optional child drivers
+	  that bind to xHCI PCI controller-specific functionality through
+	  the auxiliary bus.
+
 config USB_XHCI_PCI_RENESAS
 	tristate "Support for additional Renesas xHCI controller with firmware"
 	depends on USB_XHCI_PCI
diff --git a/drivers/usb/host/xhci-pci.c b/drivers/usb/host/xhci-pci.c
index 585b2f3117b0..1ab27d2182eb 100644
--- a/drivers/usb/host/xhci-pci.c
+++ b/drivers/usb/host/xhci-pci.c
@@ -8,6 +8,8 @@
  * Some code borrowed from the Linux EHCI driver.
  */
 
+#include <linux/auxiliary_bus.h>
+#include <linux/device/devres.h>
 #include <linux/pci.h>
 #include <linux/slab.h>
 #include <linux/module.h>
@@ -103,6 +105,114 @@ static int xhci_pci_run(struct usb_hcd *hcd);
 static int xhci_pci_update_hub_device(struct usb_hcd *hcd, struct usb_device *hdev,
 				      struct usb_tt *tt, gfp_t mem_flags);
 
+#if IS_ENABLED(CONFIG_USB_XHCI_PCI_AUXDEV)
+static const struct {
+	struct pci_device_id id;
+	const char *aux_dev_name;
+} pci_ids_have_aux[] = {
+	{
+		.id = { PCI_DEVICE(PCI_VENDOR_ID_AMD, 0x43fd) }, /* PROM21 xHCI */
+		.aux_dev_name = "hwmon",
+	},
+	{ /* end: all zeroes */ }
+};
+
+struct xhci_pci_aux_devres {
+	struct auxiliary_device *auxdev;
+};
+
+static bool xhci_pci_aux_match_id(const struct pci_device_id *id,
+				  const struct pci_dev *pdev)
+{
+	if (id->vendor != PCI_ANY_ID && id->vendor != pdev->vendor)
+		return false;
+	if (id->device != PCI_ANY_ID && id->device != pdev->device)
+		return false;
+	if (id->subvendor != PCI_ANY_ID &&
+	    id->subvendor != pdev->subsystem_vendor)
+		return false;
+	if (id->subdevice != PCI_ANY_ID &&
+	    id->subdevice != pdev->subsystem_device)
+		return false;
+
+	return !((id->class ^ pdev->class) & id->class_mask);
+}
+
+static const char *xhci_pci_aux_dev_name(struct pci_dev *pdev)
+{
+	int i;
+
+	for (i = 0; pci_ids_have_aux[i].aux_dev_name; i++) {
+		if (xhci_pci_aux_match_id(&pci_ids_have_aux[i].id, pdev))
+			return pci_ids_have_aux[i].aux_dev_name;
+	}
+
+	return NULL;
+}
+
+static void xhci_pci_aux_devres_release(struct device *dev, void *res)
+{
+	struct xhci_pci_aux_devres *devres = res;
+
+	if (devres->auxdev)
+		auxiliary_device_destroy(devres->auxdev);
+}
+
+static void xhci_pci_try_add_aux_device(struct pci_dev *pdev)
+{
+	struct xhci_pci_aux_devres *devres;
+	struct auxiliary_device *auxdev;
+	const char *aux_dev_name;
+
+	aux_dev_name = xhci_pci_aux_dev_name(pdev);
+	if (!aux_dev_name)
+		return;
+
+	devres = devres_alloc(xhci_pci_aux_devres_release, sizeof(*devres),
+			      GFP_KERNEL);
+	if (!devres) {
+		dev_warn(&pdev->dev,
+			 "failed to allocate auxiliary device state\n");
+		return;
+	}
+
+	auxdev = auxiliary_device_create(&pdev->dev, KBUILD_MODNAME,
+					 aux_dev_name, NULL,
+					 (pci_domain_nr(pdev->bus) << 16) |
+						 pci_dev_id(pdev));
+	if (!auxdev) {
+		devres_free(devres);
+		dev_warn(&pdev->dev, "failed to add %s auxiliary device\n",
+			 aux_dev_name);
+		return;
+	}
+
+	devres->auxdev = auxdev;
+	devres_add(&pdev->dev, devres);
+}
+
+static void xhci_pci_try_remove_aux_device(struct pci_dev *pdev)
+{
+	struct xhci_pci_aux_devres *devres;
+
+	devres = devres_find(&pdev->dev, xhci_pci_aux_devres_release, NULL,
+			     NULL);
+	if (!devres || !devres->auxdev)
+		return;
+
+	auxiliary_device_destroy(devres->auxdev);
+	devres->auxdev = NULL;
+}
+#else
+static inline void xhci_pci_try_add_aux_device(struct pci_dev *pdev)
+{
+}
+
+static inline void xhci_pci_try_remove_aux_device(struct pci_dev *pdev)
+{
+}
+#endif
+
 static const struct xhci_driver_overrides xhci_pci_overrides __initconst = {
 	.reset = xhci_pci_setup,
 	.start = xhci_pci_run,
@@ -677,6 +787,8 @@ int xhci_pci_common_probe(struct pci_dev *dev, const struct pci_device_id *id)
 	if (device_property_read_bool(&dev->dev, "ti,pwron-active-high"))
 		pci_clear_and_set_config_dword(dev, 0xE0, 0, 1 << 22);
 
+	xhci_pci_try_add_aux_device(dev);
+
 	return 0;
 
 put_usb3_hcd:
@@ -713,6 +825,8 @@ void xhci_pci_remove(struct pci_dev *dev)
 	xhci = hcd_to_xhci(pci_get_drvdata(dev));
 	set_power_d3 = xhci->quirks & XHCI_SPURIOUS_WAKEUP;
 
+	xhci_pci_try_remove_aux_device(dev);
+
 	xhci->xhc_state |= XHCI_STATE_REMOVING;
 
 	if (pci_choose_state(dev, PMSG_SUSPEND) == PCI_D0)
-- 
2.53.0


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

* [PATCH v2 2/2] hwmon: add initial support for AMD PROM21 xHCI temperature sensor
  2026-05-06 20:40 ` [PATCH v2 0/2] AMD PROM21 xHCI temperature hwmon support Jihong Min
  2026-05-06 20:40   ` [PATCH v2 1/2] usb: xhci-pci: add generic auxiliary device interface Jihong Min
@ 2026-05-06 20:40   ` Jihong Min
  2026-05-06 21:33     ` Michal Pecio
  2026-05-06 22:17     ` Randy Dunlap
  1 sibling, 2 replies; 16+ messages in thread
From: Jihong Min @ 2026-05-06 20:40 UTC (permalink / raw)
  To: Greg Kroah-Hartman, Mathias Nyman
  Cc: Guenter Roeck, Jonathan Corbet, Shuah Khan, Mario Limonciello,
	Basavaraj Natikar, linux-usb, linux-hwmon, linux-doc, linux-pci,
	linux-kernel, Jihong Min

AMD PROM21 xHCI controllers expose an 8-bit temperature value
through a vendor-specific index/data register pair in the xHCI PCI
MMIO BAR region. Add an auxiliary hwmon driver for AMD 1022:43fd
controllers and bind it to the xhci_pci.hwmon auxiliary device
created by xhci-pci.

The read path verifies the parent PCI function and uses the
initialized xHCI HCD MMIO mapping. The vendor index register is at
byte offset 0x3000 from the xHCI MMIO BAR base and the vendor data
register is at byte offset 0x3008. The driver writes register selector
0x0001e520 to the index register, reads the raw temperature value from
the low 8 bits of the data register, and restores the previous index
before returning. Expose temp1_input and an xHCI label through hwmon.

Register the hwmon device under the parent PCI function so userspace
reports it as a PCI adapter, while the auxiliary driver still owns the
hwmon lifetime and unregisters it from the auxiliary remove path.

No public AMD reference is available for this value. The conversion
formula is derived from observed temperature readings:

  temp[C] = raw * 0.9066 - 78.624

The temperature register did not return a valid value while the xHCI
PCI function was suspended in testing. Keep the existing behavior by
default and allow temperature reads to wake the xHCI PCI device. Add an
allow_pm_switch module parameter so users can disable that behavior;
when disabled, reads do not wake the device and return -EAGAIN if it is
suspended.

Document the supported device, register access, conversion formula,
module parameter, sysfs attributes, and sysfs lookup method.

Assisted-by: Codex:gpt-5.5
Signed-off-by: Jihong Min <hurryman2212@gmail.com>
---
 Documentation/hwmon/index.rst        |   1 +
 Documentation/hwmon/prom21-hwmon.rst |  84 ++++++++
 drivers/hwmon/Kconfig                |  11 +
 drivers/hwmon/Makefile               |   1 +
 drivers/hwmon/prom21-hwmon.c         | 300 +++++++++++++++++++++++++++
 5 files changed, 397 insertions(+)
 create mode 100644 Documentation/hwmon/prom21-hwmon.rst
 create mode 100644 drivers/hwmon/prom21-hwmon.c

diff --git a/Documentation/hwmon/index.rst b/Documentation/hwmon/index.rst
index 8b655e5d6b68..0d85b78596cf 100644
--- a/Documentation/hwmon/index.rst
+++ b/Documentation/hwmon/index.rst
@@ -215,6 +215,7 @@ Hardware Monitoring Kernel Drivers
    peci-dimmtemp
    pmbus
    powerz
+   prom21-hwmon
    powr1220
    pt5161l
    pxe1610
diff --git a/Documentation/hwmon/prom21-hwmon.rst b/Documentation/hwmon/prom21-hwmon.rst
new file mode 100644
index 000000000000..965a50595b47
--- /dev/null
+++ b/Documentation/hwmon/prom21-hwmon.rst
@@ -0,0 +1,84 @@
+.. SPDX-License-Identifier: GPL-2.0
+
+Kernel driver prom21-hwmon
+==========================
+
+Supported chips:
+
+  * AMD PROM21 xHCI
+
+    Prefix: 'prom21_hwmon'
+
+    PCI ID: 1022:43fd
+
+Author:
+
+  - Jihong Min <hurryman2212@gmail.com>
+
+Description
+-----------
+
+This driver exposes the temperature sensor in AMD PROM21 xHCI controllers.
+
+The driver binds to an auxiliary device created by the xHCI PCI driver for
+supported controllers. The sensor value is accessed through a vendor-specific
+index/data register pair in the controller's PCI MMIO BAR.
+
+Since the xHCI controllers are integrated in PROM21, this temperature can also
+be used as a monitor for a temperature close to the AMD chipset temperature.
+
+Register access
+---------------
+
+The temperature value is read through a vendor-specific index/data register
+pair in the xHCI PCI MMIO BAR. The driver uses the following byte offsets from
+the MMIO BAR base:
+
+======================= =====================================================
+0x3000			Vendor index register
+0x3008			Vendor data register
+======================= =====================================================
+
+The driver saves the current vendor index register value, writes the
+temperature selector ``0x0001e520`` to the vendor index register, reads the
+vendor data register, and restores the previous vendor index value before
+returning. The raw temperature value is the low 8 bits of the vendor data
+register value.
+
+No public AMD reference is available for the raw value. The temperature
+conversion formula is derived from observed PROM21 xHCI temperature readings:
+
+  temp[C] = raw * 0.9066 - 78.624
+
+Module parameters
+-----------------
+
+allow_pm_switch: bool
+  Allow temperature reads to wake the xHCI PCI device. This is enabled by
+  default. If disabled, the driver does not wake the xHCI PCI device from a
+  temperature read. It reads the temperature only when the device is not
+  suspended. A read from a suspended device returns ``-EAGAIN``.
+
+Sysfs entries
+-------------
+
+======================= =====================================================
+temp1_input		Temperature in millidegrees Celsius
+temp1_label		"xHCI"
+======================= =====================================================
+
+The hwmon device name is ``prom21_hwmon``. The sysfs path depends on the hwmon
+device number assigned by the kernel. Userspace can locate the device by
+matching the ``name`` attribute:
+
+.. code-block:: sh
+
+   for hwmon in /sys/class/hwmon/hwmon*; do
+           [ "$(cat "$hwmon/name")" = "prom21_hwmon" ] || continue
+           cat "$hwmon/temp1_label"
+           cat "$hwmon/temp1_input"
+   done
+
+``temp1_input`` reports millidegrees Celsius, so a value of ``50113`` means
+50.113 degrees Celsius. If the raw register value is invalid, ``temp1_input``
+returns ``-ENODATA``.
diff --git a/drivers/hwmon/Kconfig b/drivers/hwmon/Kconfig
index 14e4cea48acc..da2266807f06 100644
--- a/drivers/hwmon/Kconfig
+++ b/drivers/hwmon/Kconfig
@@ -940,6 +940,17 @@ config SENSORS_POWERZ
 	  This driver can also be built as a module. If so, the module
 	  will be called powerz.
 
+config SENSORS_PROM21
+	tristate "AMD PROM21 xHCI temperature sensor"
+	depends on USB_XHCI_PCI
+	select USB_XHCI_PCI_AUXDEV
+	help
+	  If you say yes here you get support for the AMD PROM21 xHCI
+	  temperature sensor.
+
+	  This driver can also be built as a module. If so, the module
+	  will be called prom21-hwmon.
+
 config SENSORS_POWR1220
 	tristate "Lattice POWR1220 Power Monitoring"
 	depends on I2C
diff --git a/drivers/hwmon/Makefile b/drivers/hwmon/Makefile
index 4788996aa137..7693ed3b3f72 100644
--- a/drivers/hwmon/Makefile
+++ b/drivers/hwmon/Makefile
@@ -196,6 +196,7 @@ obj-$(CONFIG_SENSORS_PC87427)	+= pc87427.o
 obj-$(CONFIG_SENSORS_PCF8591)	+= pcf8591.o
 obj-$(CONFIG_SENSORS_POWERZ)	+= powerz.o
 obj-$(CONFIG_SENSORS_POWR1220)  += powr1220.o
+obj-$(CONFIG_SENSORS_PROM21)	+= prom21-hwmon.o
 obj-$(CONFIG_SENSORS_PT5161L)	+= pt5161l.o
 obj-$(CONFIG_SENSORS_PWM_FAN)	+= pwm-fan.o
 obj-$(CONFIG_SENSORS_QNAP_MCU_HWMON)	+= qnap-mcu-hwmon.o
diff --git a/drivers/hwmon/prom21-hwmon.c b/drivers/hwmon/prom21-hwmon.c
new file mode 100644
index 000000000000..179d2f206c7d
--- /dev/null
+++ b/drivers/hwmon/prom21-hwmon.c
@@ -0,0 +1,300 @@
+// SPDX-License-Identifier: GPL-2.0
+/*
+ * AMD PROM21 xHCI Hwmon Implementation
+ * (only temperature monitoring is supported)
+ *
+ * This can be effectively used as the alternative chipset temperature monitor.
+ *
+ * Copyright (C) 2026 Jihong Min <hurryman2212@gmail.com>
+ */
+
+#include <linux/auxiliary_bus.h>
+#include <linux/device.h>
+#include <linux/err.h>
+#include <linux/errno.h>
+#include <linux/hwmon.h>
+#include <linux/io.h>
+#include <linux/math.h>
+#include <linux/module.h>
+#include <linux/mutex.h>
+#include <linux/pci.h>
+#include <linux/pm_runtime.h>
+#include <linux/slab.h>
+#include <linux/usb.h>
+#include <linux/usb/hcd.h>
+
+#define PCI_DEVICE_ID_AMD_PROM21_XHCI 0x43fd
+
+#define PROM21_INDEX 0x3000
+#define PROM21_DATA 0x3008
+#define PROM21_TEMP_REG 0x0001e520
+
+#define PROM21_HWMON_NAME "prom21_hwmon"
+#define PROM21_TEMP_LABEL "xHCI"
+
+struct prom21_hwmon {
+	struct pci_dev *pdev;
+	struct device *hwmon_dev;
+	void __iomem *regs;
+	bool removing;
+	struct mutex lock; /* protects removing and the index/data registers */
+};
+
+static bool allow_pm_switch = true;
+module_param(allow_pm_switch, bool, 0444);
+MODULE_PARM_DESC(allow_pm_switch,
+		 "Allow temperature reads to wake the xHCI PCI device");
+
+static void prom21_hwmon_invalidate(struct prom21_hwmon *hwmon)
+{
+	mutex_lock(&hwmon->lock);
+	hwmon->removing = true;
+	mutex_unlock(&hwmon->lock);
+}
+
+static int prom21_hwmon_pm_get(struct prom21_hwmon *hwmon, bool *pm_ref)
+{
+	struct device *dev = &hwmon->pdev->dev;
+	int ret;
+
+	*pm_ref = false;
+
+	/*
+	 * PROM21 temperature register access does not return a valid value while
+	 * the parent xHCI PCI function is suspended. By default, resume the xHC
+	 * before touching MMIO. If allow_pm_switch=N, do not resume the xHC from
+	 * a hwmon sysfs read; only read when runtime PM reports it as active, or
+	 * when runtime PM is disabled and the device is not marked as suspended.
+	 */
+	if (allow_pm_switch) {
+		ret = pm_runtime_resume_and_get(dev);
+		if (ret < 0)
+			return ret;
+
+		*pm_ref = true;
+		return 0;
+	}
+
+	ret = pm_runtime_get_if_active(dev);
+	if (ret > 0) {
+		*pm_ref = true;
+		return 0;
+	}
+
+	if (!ret || pm_runtime_status_suspended(dev))
+		return -EAGAIN;
+
+	if (ret == -EINVAL)
+		return 0;
+
+	return ret;
+}
+
+/*
+ * This is not a pure MMIO read. The PROM21 vendor data register is selected
+ * by temporarily writing PROM21_TEMP_REG to the vendor index register. Keep
+ * the sequence short and restore the previous index before returning.
+ */
+static int prom21_hwmon_read_temp_raw_restore_index(struct prom21_hwmon *hwmon,
+						    u8 *raw)
+{
+	struct device *dev = &hwmon->pdev->dev;
+	bool pm_ref;
+	u32 index;
+	u32 data;
+	int ret;
+
+	/*
+	 * The xHCI PCI remove path destroys the auxiliary device before HCD
+	 * teardown. Keep runtime PM and MMIO inside the critical section so a
+	 * sysfs read cannot use the vendor register pair after remove starts.
+	 */
+	mutex_lock(&hwmon->lock);
+	if (hwmon->removing) {
+		mutex_unlock(&hwmon->lock);
+		return -ENODEV;
+	}
+
+	ret = prom21_hwmon_pm_get(hwmon, &pm_ref);
+	if (ret) {
+		mutex_unlock(&hwmon->lock);
+		return ret;
+	}
+
+	index = readl(hwmon->regs + PROM21_INDEX);
+	/* Select the PROM21 temperature register through the vendor index. */
+	writel(PROM21_TEMP_REG, hwmon->regs + PROM21_INDEX);
+	data = readl(hwmon->regs + PROM21_DATA);
+	/* Restore the previous vendor index register value. */
+	writel(index, hwmon->regs + PROM21_INDEX);
+	readl(hwmon->regs + PROM21_INDEX);
+
+	if (pm_ref) {
+		/*
+		 * Use autosuspend so repeated sysfs reads do not suspend the
+		 * controller immediately after each successful register access.
+		 */
+		pm_runtime_mark_last_busy(dev);
+		pm_runtime_put_autosuspend(dev);
+	}
+	mutex_unlock(&hwmon->lock);
+
+	*raw = data & 0xff;
+	if (!*raw || *raw == 0xff)
+		return -ENODATA;
+
+	return 0;
+}
+
+static long prom21_hwmon_raw_to_millicelsius(u8 raw)
+{
+	/*
+	 * No public AMD reference is available for this value.
+	 * The scale was derived from observed PROM21 xHCI temperature readings:
+	 *  temp[C] = raw * 0.9066 - 78.624
+	 */
+	return DIV_ROUND_CLOSEST(raw * 9066, 10) - 78624;
+}
+
+static umode_t prom21_hwmon_is_visible(const void *drvdata,
+				       enum hwmon_sensor_types type, u32 attr,
+				       int channel)
+{
+	if (type != hwmon_temp || channel)
+		return 0;
+
+	switch (attr) {
+	case hwmon_temp_input:
+	case hwmon_temp_label:
+		return 0444;
+	default:
+		return 0;
+	}
+}
+
+static int prom21_hwmon_read(struct device *dev, enum hwmon_sensor_types type,
+			     u32 attr, int channel, long *val)
+{
+	struct prom21_hwmon *hwmon = dev_get_drvdata(dev);
+	u8 raw;
+	int ret;
+
+	if (type != hwmon_temp || attr != hwmon_temp_input || channel)
+		return -EOPNOTSUPP;
+
+	ret = prom21_hwmon_read_temp_raw_restore_index(hwmon, &raw);
+	if (ret)
+		return ret;
+
+	*val = prom21_hwmon_raw_to_millicelsius(raw);
+	return 0;
+}
+
+static int prom21_hwmon_read_string(struct device *dev,
+				    enum hwmon_sensor_types type, u32 attr,
+				    int channel, const char **str)
+{
+	if (type != hwmon_temp || attr != hwmon_temp_label || channel)
+		return -EOPNOTSUPP;
+
+	*str = PROM21_TEMP_LABEL;
+	return 0;
+}
+
+static const struct hwmon_ops prom21_hwmon_ops = {
+	.is_visible = prom21_hwmon_is_visible,
+	.read = prom21_hwmon_read,
+	.read_string = prom21_hwmon_read_string,
+};
+
+static const struct hwmon_channel_info *const prom21_hwmon_info[] = {
+	HWMON_CHANNEL_INFO(temp, HWMON_T_INPUT | HWMON_T_LABEL),
+	NULL,
+};
+
+static const struct hwmon_chip_info prom21_hwmon_chip_info = {
+	.ops = &prom21_hwmon_ops,
+	.info = prom21_hwmon_info,
+};
+
+static int prom21_hwmon_probe(struct auxiliary_device *auxdev,
+			      const struct auxiliary_device_id *id)
+{
+	struct device *dev = &auxdev->dev;
+	struct device *parent = dev->parent;
+	struct prom21_hwmon *hwmon;
+	struct pci_dev *pdev;
+	struct usb_hcd *hcd;
+	int ret;
+
+	if (!parent || !dev_is_pci(parent))
+		return -ENODEV;
+
+	pdev = to_pci_dev(parent);
+	if (pdev->vendor != PCI_VENDOR_ID_AMD ||
+	    pdev->device != PCI_DEVICE_ID_AMD_PROM21_XHCI)
+		return -ENODEV;
+
+	hcd = pci_get_drvdata(pdev);
+	if (!hcd)
+		return dev_err_probe(dev, -ENODEV,
+				     "xHCI HCD data unavailable\n");
+
+	if (!hcd->regs || hcd->rsrc_len < PROM21_DATA + sizeof(u32))
+		return dev_err_probe(dev, -ENODEV, "invalid MMIO resource\n");
+
+	hwmon = devm_kzalloc(dev, sizeof(*hwmon), GFP_KERNEL);
+	if (!hwmon)
+		return -ENOMEM;
+
+	ret = devm_mutex_init(dev, &hwmon->lock);
+	if (ret)
+		return ret;
+
+	hwmon->pdev = pdev;
+	hwmon->regs = hcd->regs;
+	auxiliary_set_drvdata(auxdev, hwmon);
+
+	/*
+	 * Use the PCI function as the hwmon parent so user space reports it as
+	 * a PCI adapter. Lifetime is still owned by this auxiliary driver;
+	 * remove() unregisters the hwmon device before xhci-pci tears down the
+	 * HCD.
+	 */
+	hwmon->hwmon_dev =
+		hwmon_device_register_with_info(&pdev->dev, PROM21_HWMON_NAME,
+						hwmon, &prom21_hwmon_chip_info,
+						NULL);
+	if (IS_ERR(hwmon->hwmon_dev))
+		return PTR_ERR(hwmon->hwmon_dev);
+
+	return 0;
+}
+
+static void prom21_hwmon_remove(struct auxiliary_device *auxdev)
+{
+	struct prom21_hwmon *hwmon = auxiliary_get_drvdata(auxdev);
+
+	if (hwmon) {
+		prom21_hwmon_invalidate(hwmon);
+		hwmon_device_unregister(hwmon->hwmon_dev);
+	}
+}
+
+static const struct auxiliary_device_id prom21_hwmon_id_table[] = {
+	{ .name = "xhci_pci.hwmon" },
+	{}
+};
+MODULE_DEVICE_TABLE(auxiliary, prom21_hwmon_id_table);
+
+static struct auxiliary_driver prom21_hwmon_driver = {
+	.name = "prom21-hwmon",
+	.probe = prom21_hwmon_probe,
+	.remove = prom21_hwmon_remove,
+	.id_table = prom21_hwmon_id_table,
+};
+module_auxiliary_driver(prom21_hwmon_driver);
+
+MODULE_AUTHOR("Jihong Min <hurryman2212@gmail.com>");
+MODULE_DESCRIPTION("AMD PROM21 xHCI hwmon driver");
+MODULE_LICENSE("GPL");
-- 
2.53.0


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

* Re: [PATCH v2 1/2] usb: xhci-pci: add generic auxiliary device interface
  2026-05-06 20:40   ` [PATCH v2 1/2] usb: xhci-pci: add generic auxiliary device interface Jihong Min
@ 2026-05-06 20:53     ` Mario Limonciello
  2026-05-06 21:09       ` Jihong Min
  2026-05-06 21:15     ` Michal Pecio
  1 sibling, 1 reply; 16+ messages in thread
From: Mario Limonciello @ 2026-05-06 20:53 UTC (permalink / raw)
  To: Jihong Min, Greg Kroah-Hartman, Mathias Nyman
  Cc: Guenter Roeck, Jonathan Corbet, Shuah Khan, Basavaraj Natikar,
	linux-usb, linux-hwmon, linux-doc, linux-pci, linux-kernel



On 5/6/26 15:40, Jihong Min wrote:
> [You don't often get email from hurryman2212@gmail.com. Learn why this is important at https://aka.ms/LearnAboutSenderIdentification ]
> 
> Some xHCI PCI controllers expose controller-specific functionality that is
> not part of generic xHCI operation and is better handled by optional child
> drivers in other subsystems. Add a small auxiliary device registration path
> for selected xHCI PCI controllers.
> 
> The initial table creates an xhci_pci.hwmon auxiliary device for AMD
> 1022:43fd controllers. Store the created auxiliary device in devres so the
> xhci-pci remove path destroys it before HCD teardown. Use a
> PCI-domain-qualified id so auxiliary device names remain unique across PCI
> domains.
> 
> This keeps xhci-pci responsible only for publishing selected controller
> functions while allowing subsystem-specific drivers to bind through the
> auxiliary bus.
> 
> Assisted-by: Codex:gpt-5.5
> Signed-off-by: Jihong Min <hurryman2212@gmail.com>
> ---
>   drivers/usb/host/Kconfig    |  10 ++++
>   drivers/usb/host/xhci-pci.c | 114 ++++++++++++++++++++++++++++++++++++
>   2 files changed, 124 insertions(+)
> 
> diff --git a/drivers/usb/host/Kconfig b/drivers/usb/host/Kconfig
> index 0a277a07cf70..e0c2c7ac5c97 100644
> --- a/drivers/usb/host/Kconfig
> +++ b/drivers/usb/host/Kconfig
> @@ -42,6 +42,16 @@ config USB_XHCI_PCI
>          depends on USB_PCI
>          default y
> 
> +config USB_XHCI_PCI_AUXDEV
> +       bool "xHCI PCI auxiliary device support"
> +       depends on USB_XHCI_PCI
> +       select AUXILIARY_BUS
> +       help
> +         This enables xHCI PCI support for registering auxiliary devices
> +         for selected controllers. It is used by optional child drivers
> +         that bind to xHCI PCI controller-specific functionality through
> +         the auxiliary bus.
> +
>   config USB_XHCI_PCI_RENESAS
>          tristate "Support for additional Renesas xHCI controller with firmware"
>          depends on USB_XHCI_PCI
> diff --git a/drivers/usb/host/xhci-pci.c b/drivers/usb/host/xhci-pci.c
> index 585b2f3117b0..1ab27d2182eb 100644
> --- a/drivers/usb/host/xhci-pci.c
> +++ b/drivers/usb/host/xhci-pci.c
> @@ -8,6 +8,8 @@
>    * Some code borrowed from the Linux EHCI driver.
>    */
> 
> +#include <linux/auxiliary_bus.h>
> +#include <linux/device/devres.h>
>   #include <linux/pci.h>
>   #include <linux/slab.h>
>   #include <linux/module.h>
> @@ -103,6 +105,114 @@ static int xhci_pci_run(struct usb_hcd *hcd);
>   static int xhci_pci_update_hub_device(struct usb_hcd *hcd, struct usb_device *hdev,
>                                        struct usb_tt *tt, gfp_t mem_flags);
> 
> +#if IS_ENABLED(CONFIG_USB_XHCI_PCI_AUXDEV)
> +static const struct {
> +       struct pci_device_id id;
> +       const char *aux_dev_name;
> +} pci_ids_have_aux[] = {
> +       {
> +               .id = { PCI_DEVICE(PCI_VENDOR_ID_AMD, 0x43fd) }, /* PROM21 xHCI */
> +               .aux_dev_name = "hwmon",
> +       },
> +       { /* end: all zeroes */ }
> +};
> +
> +struct xhci_pci_aux_devres {
> +       struct auxiliary_device *auxdev;
> +};
> +
> +static bool xhci_pci_aux_match_id(const struct pci_device_id *id,
> +                                 const struct pci_dev *pdev)
> +{
> +       if (id->vendor != PCI_ANY_ID && id->vendor != pdev->vendor)
> +               return false;
> +       if (id->device != PCI_ANY_ID && id->device != pdev->device)
> +               return false;
> +       if (id->subvendor != PCI_ANY_ID &&
> +           id->subvendor != pdev->subsystem_vendor)
> +               return false;
> +       if (id->subdevice != PCI_ANY_ID &&
> +           id->subdevice != pdev->subsystem_device)
> +               return false;
> +
> +       return !((id->class ^ pdev->class) & id->class_mask);

What's wrong with pci_match_id()?

> +}
> +
> +static const char *xhci_pci_aux_dev_name(struct pci_dev *pdev)
> +{
> +       int i;
> +
> +       for (i = 0; pci_ids_have_aux[i].aux_dev_name; i++) {
> +               if (xhci_pci_aux_match_id(&pci_ids_have_aux[i].id, pdev))
> +                       return pci_ids_have_aux[i].aux_dev_name;
> +       }
> +
> +       return NULL;
> +}
> +
> +static void xhci_pci_aux_devres_release(struct device *dev, void *res)
> +{
> +       struct xhci_pci_aux_devres *devres = res;
> +
> +       if (devres->auxdev)
> +               auxiliary_device_destroy(devres->auxdev);
> +}
> +
> +static void xhci_pci_try_add_aux_device(struct pci_dev *pdev)
> +{
> +       struct xhci_pci_aux_devres *devres;
> +       struct auxiliary_device *auxdev;
> +       const char *aux_dev_name;
> +
> +       aux_dev_name = xhci_pci_aux_dev_name(pdev);
> +       if (!aux_dev_name)
> +               return;
> +
> +       devres = devres_alloc(xhci_pci_aux_devres_release, sizeof(*devres),
> +                             GFP_KERNEL);
> +       if (!devres) {
> +               dev_warn(&pdev->dev,
> +                        "failed to allocate auxiliary device state\n");
> +               return;
> +       }
> +
> +       auxdev = auxiliary_device_create(&pdev->dev, KBUILD_MODNAME,
> +                                        aux_dev_name, NULL,
> +                                        (pci_domain_nr(pdev->bus) << 16) |
> +                                                pci_dev_id(pdev));
> +       if (!auxdev) {
> +               devres_free(devres);
> +               dev_warn(&pdev->dev, "failed to add %s auxiliary device\n",
> +                        aux_dev_name);
> +               return;
> +       }
> +
> +       devres->auxdev = auxdev;
> +       devres_add(&pdev->dev, devres);
> +}
> +
> +static void xhci_pci_try_remove_aux_device(struct pci_dev *pdev)
> +{
> +       struct xhci_pci_aux_devres *devres;
> +
> +       devres = devres_find(&pdev->dev, xhci_pci_aux_devres_release, NULL,
> +                            NULL);
> +       if (!devres || !devres->auxdev)
> +               return;
> +
> +       auxiliary_device_destroy(devres->auxdev);
> +       devres->auxdev = NULL;
> +}
> +#else
> +static inline void xhci_pci_try_add_aux_device(struct pci_dev *pdev)
> +{
> +}
> +
> +static inline void xhci_pci_try_remove_aux_device(struct pci_dev *pdev)
> +{
> +}
> +#endif
> +
>   static const struct xhci_driver_overrides xhci_pci_overrides __initconst = {
>          .reset = xhci_pci_setup,
>          .start = xhci_pci_run,
> @@ -677,6 +787,8 @@ int xhci_pci_common_probe(struct pci_dev *dev, const struct pci_device_id *id)
>          if (device_property_read_bool(&dev->dev, "ti,pwron-active-high"))
>                  pci_clear_and_set_config_dword(dev, 0xE0, 0, 1 << 22);
> 
> +       xhci_pci_try_add_aux_device(dev);
> +
>          return 0;
> 
>   put_usb3_hcd:
> @@ -713,6 +825,8 @@ void xhci_pci_remove(struct pci_dev *dev)
>          xhci = hcd_to_xhci(pci_get_drvdata(dev));
>          set_power_d3 = xhci->quirks & XHCI_SPURIOUS_WAKEUP;
> 
> +       xhci_pci_try_remove_aux_device(dev);
> +
>          xhci->xhc_state |= XHCI_STATE_REMOVING;
> 
>          if (pci_choose_state(dev, PMSG_SUSPEND) == PCI_D0)
> --
> 2.53.0
> 


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

* Re: [PATCH v2 1/2] usb: xhci-pci: add generic auxiliary device interface
  2026-05-06 20:53     ` Mario Limonciello
@ 2026-05-06 21:09       ` Jihong Min
  0 siblings, 0 replies; 16+ messages in thread
From: Jihong Min @ 2026-05-06 21:09 UTC (permalink / raw)
  To: Mario Limonciello, Jihong Min, Greg Kroah-Hartman, Mathias Nyman
  Cc: Guenter Roeck, Jonathan Corbet, Shuah Khan, Basavaraj Natikar,
	linux-usb, linux-hwmon, linux-doc, linux-pci, linux-kernel

I refactored the auxiliary device table to use PCI_DEVICE_DATA(), store the
auxiliary device name in driver_data, and use pci_match_id() inside
xhci_pci_aux_dev_name(). The relevant change is:

#define PCI_DEVICE_ID_AMD_PROM21_XHCI            0x43fd
...
static const struct pci_device_id pci_ids_have_aux[] = {
     { PCI_DEVICE_DATA(AMD, PROM21_XHCI, "hwmon") },
     { /* end: all zeroes */ }
};
...
static const char *xhci_pci_aux_dev_name(struct pci_dev *pdev)
{
     const struct pci_device_id *id;

     id = pci_match_id(pci_ids_have_aux, pdev);
     if (!id)
         return NULL;

     return (const char *)id->driver_data;
}

I will include this in v3.

Thank you,
Jihong Min

On 5/7/26 05:53, Mario Limonciello wrote:
>
>
> On 5/6/26 15:40, Jihong Min wrote:
>> [You don't often get email from hurryman2212@gmail.com. Learn why 
>> this is important at https://aka.ms/LearnAboutSenderIdentification ]
>>
>> Some xHCI PCI controllers expose controller-specific functionality 
>> that is
>> not part of generic xHCI operation and is better handled by optional 
>> child
>> drivers in other subsystems. Add a small auxiliary device 
>> registration path
>> for selected xHCI PCI controllers.
>>
>> The initial table creates an xhci_pci.hwmon auxiliary device for AMD
>> 1022:43fd controllers. Store the created auxiliary device in devres 
>> so the
>> xhci-pci remove path destroys it before HCD teardown. Use a
>> PCI-domain-qualified id so auxiliary device names remain unique 
>> across PCI
>> domains.
>>
>> This keeps xhci-pci responsible only for publishing selected controller
>> functions while allowing subsystem-specific drivers to bind through the
>> auxiliary bus.
>>
>> Assisted-by: Codex:gpt-5.5
>> Signed-off-by: Jihong Min <hurryman2212@gmail.com>
>> ---
>>   drivers/usb/host/Kconfig    |  10 ++++
>>   drivers/usb/host/xhci-pci.c | 114 ++++++++++++++++++++++++++++++++++++
>>   2 files changed, 124 insertions(+)
>>
>> diff --git a/drivers/usb/host/Kconfig b/drivers/usb/host/Kconfig
>> index 0a277a07cf70..e0c2c7ac5c97 100644
>> --- a/drivers/usb/host/Kconfig
>> +++ b/drivers/usb/host/Kconfig
>> @@ -42,6 +42,16 @@ config USB_XHCI_PCI
>>          depends on USB_PCI
>>          default y
>>
>> +config USB_XHCI_PCI_AUXDEV
>> +       bool "xHCI PCI auxiliary device support"
>> +       depends on USB_XHCI_PCI
>> +       select AUXILIARY_BUS
>> +       help
>> +         This enables xHCI PCI support for registering auxiliary 
>> devices
>> +         for selected controllers. It is used by optional child drivers
>> +         that bind to xHCI PCI controller-specific functionality 
>> through
>> +         the auxiliary bus.
>> +
>>   config USB_XHCI_PCI_RENESAS
>>          tristate "Support for additional Renesas xHCI controller 
>> with firmware"
>>          depends on USB_XHCI_PCI
>> diff --git a/drivers/usb/host/xhci-pci.c b/drivers/usb/host/xhci-pci.c
>> index 585b2f3117b0..1ab27d2182eb 100644
>> --- a/drivers/usb/host/xhci-pci.c
>> +++ b/drivers/usb/host/xhci-pci.c
>> @@ -8,6 +8,8 @@
>>    * Some code borrowed from the Linux EHCI driver.
>>    */
>>
>> +#include <linux/auxiliary_bus.h>
>> +#include <linux/device/devres.h>
>>   #include <linux/pci.h>
>>   #include <linux/slab.h>
>>   #include <linux/module.h>
>> @@ -103,6 +105,114 @@ static int xhci_pci_run(struct usb_hcd *hcd);
>>   static int xhci_pci_update_hub_device(struct usb_hcd *hcd, struct 
>> usb_device *hdev,
>>                                        struct usb_tt *tt, gfp_t 
>> mem_flags);
>>
>> +#if IS_ENABLED(CONFIG_USB_XHCI_PCI_AUXDEV)
>> +static const struct {
>> +       struct pci_device_id id;
>> +       const char *aux_dev_name;
>> +} pci_ids_have_aux[] = {
>> +       {
>> +               .id = { PCI_DEVICE(PCI_VENDOR_ID_AMD, 0x43fd) }, /* 
>> PROM21 xHCI */
>> +               .aux_dev_name = "hwmon",
>> +       },
>> +       { /* end: all zeroes */ }
>> +};
>> +
>> +struct xhci_pci_aux_devres {
>> +       struct auxiliary_device *auxdev;
>> +};
>> +
>> +static bool xhci_pci_aux_match_id(const struct pci_device_id *id,
>> +                                 const struct pci_dev *pdev)
>> +{
>> +       if (id->vendor != PCI_ANY_ID && id->vendor != pdev->vendor)
>> +               return false;
>> +       if (id->device != PCI_ANY_ID && id->device != pdev->device)
>> +               return false;
>> +       if (id->subvendor != PCI_ANY_ID &&
>> +           id->subvendor != pdev->subsystem_vendor)
>> +               return false;
>> +       if (id->subdevice != PCI_ANY_ID &&
>> +           id->subdevice != pdev->subsystem_device)
>> +               return false;
>> +
>> +       return !((id->class ^ pdev->class) & id->class_mask);
>
> What's wrong with pci_match_id()?
>
>> +}
>> +
>> +static const char *xhci_pci_aux_dev_name(struct pci_dev *pdev)
>> +{
>> +       int i;
>> +
>> +       for (i = 0; pci_ids_have_aux[i].aux_dev_name; i++) {
>> +               if (xhci_pci_aux_match_id(&pci_ids_have_aux[i].id, 
>> pdev))
>> +                       return pci_ids_have_aux[i].aux_dev_name;
>> +       }
>> +
>> +       return NULL;
>> +}
>> +
>> +static void xhci_pci_aux_devres_release(struct device *dev, void *res)
>> +{
>> +       struct xhci_pci_aux_devres *devres = res;
>> +
>> +       if (devres->auxdev)
>> +               auxiliary_device_destroy(devres->auxdev);
>> +}
>> +
>> +static void xhci_pci_try_add_aux_device(struct pci_dev *pdev)
>> +{
>> +       struct xhci_pci_aux_devres *devres;
>> +       struct auxiliary_device *auxdev;
>> +       const char *aux_dev_name;
>> +
>> +       aux_dev_name = xhci_pci_aux_dev_name(pdev);
>> +       if (!aux_dev_name)
>> +               return;
>> +
>> +       devres = devres_alloc(xhci_pci_aux_devres_release, 
>> sizeof(*devres),
>> +                             GFP_KERNEL);
>> +       if (!devres) {
>> +               dev_warn(&pdev->dev,
>> +                        "failed to allocate auxiliary device state\n");
>> +               return;
>> +       }
>> +
>> +       auxdev = auxiliary_device_create(&pdev->dev, KBUILD_MODNAME,
>> +                                        aux_dev_name, NULL,
>> + (pci_domain_nr(pdev->bus) << 16) |
>> + pci_dev_id(pdev));
>> +       if (!auxdev) {
>> +               devres_free(devres);
>> +               dev_warn(&pdev->dev, "failed to add %s auxiliary 
>> device\n",
>> +                        aux_dev_name);
>> +               return;
>> +       }
>> +
>> +       devres->auxdev = auxdev;
>> +       devres_add(&pdev->dev, devres);
>> +}
>> +
>> +static void xhci_pci_try_remove_aux_device(struct pci_dev *pdev)
>> +{
>> +       struct xhci_pci_aux_devres *devres;
>> +
>> +       devres = devres_find(&pdev->dev, xhci_pci_aux_devres_release, 
>> NULL,
>> +                            NULL);
>> +       if (!devres || !devres->auxdev)
>> +               return;
>> +
>> +       auxiliary_device_destroy(devres->auxdev);
>> +       devres->auxdev = NULL;
>> +}
>> +#else
>> +static inline void xhci_pci_try_add_aux_device(struct pci_dev *pdev)
>> +{
>> +}
>> +
>> +static inline void xhci_pci_try_remove_aux_device(struct pci_dev *pdev)
>> +{
>> +}
>> +#endif
>> +
>>   static const struct xhci_driver_overrides xhci_pci_overrides 
>> __initconst = {
>>          .reset = xhci_pci_setup,
>>          .start = xhci_pci_run,
>> @@ -677,6 +787,8 @@ int xhci_pci_common_probe(struct pci_dev *dev, 
>> const struct pci_device_id *id)
>>          if (device_property_read_bool(&dev->dev, 
>> "ti,pwron-active-high"))
>>                  pci_clear_and_set_config_dword(dev, 0xE0, 0, 1 << 22);
>>
>> +       xhci_pci_try_add_aux_device(dev);
>> +
>>          return 0;
>>
>>   put_usb3_hcd:
>> @@ -713,6 +825,8 @@ void xhci_pci_remove(struct pci_dev *dev)
>>          xhci = hcd_to_xhci(pci_get_drvdata(dev));
>>          set_power_d3 = xhci->quirks & XHCI_SPURIOUS_WAKEUP;
>>
>> +       xhci_pci_try_remove_aux_device(dev);
>> +
>>          xhci->xhc_state |= XHCI_STATE_REMOVING;
>>
>>          if (pci_choose_state(dev, PMSG_SUSPEND) == PCI_D0)
>> -- 
>> 2.53.0
>>
>

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

* Re: [PATCH v2 1/2] usb: xhci-pci: add generic auxiliary device interface
  2026-05-06 20:40   ` [PATCH v2 1/2] usb: xhci-pci: add generic auxiliary device interface Jihong Min
  2026-05-06 20:53     ` Mario Limonciello
@ 2026-05-06 21:15     ` Michal Pecio
  2026-05-06 21:42       ` Jihong Min
  1 sibling, 1 reply; 16+ messages in thread
From: Michal Pecio @ 2026-05-06 21:15 UTC (permalink / raw)
  To: Jihong Min
  Cc: Greg Kroah-Hartman, Mathias Nyman, Guenter Roeck, Jonathan Corbet,
	Shuah Khan, Mario Limonciello, Basavaraj Natikar, linux-usb,
	linux-hwmon, linux-doc, linux-pci, linux-kernel

On Thu,  7 May 2026 05:40:33 +0900, Jihong Min wrote:
> Some xHCI PCI controllers expose controller-specific functionality that is
> not part of generic xHCI operation and is better handled by optional child
> drivers in other subsystems. Add a small auxiliary device registration path
> for selected xHCI PCI controllers.
> 
> The initial table creates an xhci_pci.hwmon auxiliary device for AMD
> 1022:43fd controllers. Store the created auxiliary device in devres so the
> xhci-pci remove path destroys it before HCD teardown. Use a
> PCI-domain-qualified id so auxiliary device names remain unique across PCI
> domains.
> 
> This keeps xhci-pci responsible only for publishing selected controller
> functions while allowing subsystem-specific drivers to bind through the
> auxiliary bus.
> 
> Assisted-by: Codex:gpt-5.5
> Signed-off-by: Jihong Min <hurryman2212@gmail.com>
> ---
>  drivers/usb/host/Kconfig    |  10 ++++
>  drivers/usb/host/xhci-pci.c | 114 ++++++++++++++++++++++++++++++++++++
>  2 files changed, 124 insertions(+)
> 
> diff --git a/drivers/usb/host/Kconfig b/drivers/usb/host/Kconfig
> index 0a277a07cf70..e0c2c7ac5c97 100644
> --- a/drivers/usb/host/Kconfig
> +++ b/drivers/usb/host/Kconfig
> @@ -42,6 +42,16 @@ config USB_XHCI_PCI
>  	depends on USB_PCI
>  	default y
>  
> +config USB_XHCI_PCI_AUXDEV
> +	bool "xHCI PCI auxiliary device support"
> +	depends on USB_XHCI_PCI
> +	select AUXILIARY_BUS
> +	help
> +	  This enables xHCI PCI support for registering auxiliary devices
> +	  for selected controllers. It is used by optional child drivers
> +	  that bind to xHCI PCI controller-specific functionality through
> +	  the auxiliary bus.
> +
>  config USB_XHCI_PCI_RENESAS
>  	tristate "Support for additional Renesas xHCI controller with firmware"
>  	depends on USB_XHCI_PCI
> diff --git a/drivers/usb/host/xhci-pci.c b/drivers/usb/host/xhci-pci.c
> index 585b2f3117b0..1ab27d2182eb 100644
> --- a/drivers/usb/host/xhci-pci.c
> +++ b/drivers/usb/host/xhci-pci.c
> @@ -8,6 +8,8 @@
>   * Some code borrowed from the Linux EHCI driver.
>   */
>  
> +#include <linux/auxiliary_bus.h>
> +#include <linux/device/devres.h>
>  #include <linux/pci.h>
>  #include <linux/slab.h>
>  #include <linux/module.h>
> @@ -103,6 +105,114 @@ static int xhci_pci_run(struct usb_hcd *hcd);
>  static int xhci_pci_update_hub_device(struct usb_hcd *hcd, struct usb_device *hdev,
>  				      struct usb_tt *tt, gfp_t mem_flags);
>  
> +#if IS_ENABLED(CONFIG_USB_XHCI_PCI_AUXDEV)
> +static const struct {
> +	struct pci_device_id id;
> +	const char *aux_dev_name;
> +} pci_ids_have_aux[] = {
> +	{
> +		.id = { PCI_DEVICE(PCI_VENDOR_ID_AMD, 0x43fd) }, /* PROM21 xHCI */
> +		.aux_dev_name = "hwmon",
> +	},
> +	{ /* end: all zeroes */ }
> +};
> +
> +struct xhci_pci_aux_devres {
> +	struct auxiliary_device *auxdev;
> +};
> +
> +static bool xhci_pci_aux_match_id(const struct pci_device_id *id,
> +				  const struct pci_dev *pdev)
> +{
> +	if (id->vendor != PCI_ANY_ID && id->vendor != pdev->vendor)
> +		return false;
> +	if (id->device != PCI_ANY_ID && id->device != pdev->device)
> +		return false;
> +	if (id->subvendor != PCI_ANY_ID &&
> +	    id->subvendor != pdev->subsystem_vendor)
> +		return false;
> +	if (id->subdevice != PCI_ANY_ID &&
> +	    id->subdevice != pdev->subsystem_device)
> +		return false;
> +
> +	return !((id->class ^ pdev->class) & id->class_mask);
> +}
> +
> +static const char *xhci_pci_aux_dev_name(struct pci_dev *pdev)
> +{
> +	int i;
> +
> +	for (i = 0; pci_ids_have_aux[i].aux_dev_name; i++) {
> +		if (xhci_pci_aux_match_id(&pci_ids_have_aux[i].id, pdev))
> +			return pci_ids_have_aux[i].aux_dev_name;
> +	}
> +
> +	return NULL;
> +}
> +
> +static void xhci_pci_aux_devres_release(struct device *dev, void *res)
> +{
> +	struct xhci_pci_aux_devres *devres = res;
> +
> +	if (devres->auxdev)
> +		auxiliary_device_destroy(devres->auxdev);
> +}
> +
> +static void xhci_pci_try_add_aux_device(struct pci_dev *pdev)
> +{
> +	struct xhci_pci_aux_devres *devres;
> +	struct auxiliary_device *auxdev;
> +	const char *aux_dev_name;
> +
> +	aux_dev_name = xhci_pci_aux_dev_name(pdev);
> +	if (!aux_dev_name)
> +		return;
> +
> +	devres = devres_alloc(xhci_pci_aux_devres_release, sizeof(*devres),
> +			      GFP_KERNEL);
> +	if (!devres) {
> +		dev_warn(&pdev->dev,
> +			 "failed to allocate auxiliary device state\n");
> +		return;
> +	}
> +
> +	auxdev = auxiliary_device_create(&pdev->dev, KBUILD_MODNAME,
> +					 aux_dev_name, NULL,
> +					 (pci_domain_nr(pdev->bus) << 16) |
> +						 pci_dev_id(pdev));
> +	if (!auxdev) {
> +		devres_free(devres);
> +		dev_warn(&pdev->dev, "failed to add %s auxiliary device\n",
> +			 aux_dev_name);
> +		return;
> +	}
> +
> +	devres->auxdev = auxdev;
> +	devres_add(&pdev->dev, devres);
> +}
> +
> +static void xhci_pci_try_remove_aux_device(struct pci_dev *pdev)
> +{
> +	struct xhci_pci_aux_devres *devres;
> +
> +	devres = devres_find(&pdev->dev, xhci_pci_aux_devres_release, NULL,
> +			     NULL);
> +	if (!devres || !devres->auxdev)
> +		return;
> +
> +	auxiliary_device_destroy(devres->auxdev);
> +	devres->auxdev = NULL;
> +}
> +#else
> +static inline void xhci_pci_try_add_aux_device(struct pci_dev *pdev)
> +{
> +}
> +
> +static inline void xhci_pci_try_remove_aux_device(struct pci_dev *pdev)
> +{
> +}
> +#endif
> +
>  static const struct xhci_driver_overrides xhci_pci_overrides __initconst = {
>  	.reset = xhci_pci_setup,
>  	.start = xhci_pci_run,
> @@ -677,6 +787,8 @@ int xhci_pci_common_probe(struct pci_dev *dev, const struct pci_device_id *id)
>  	if (device_property_read_bool(&dev->dev, "ti,pwron-active-high"))
>  		pci_clear_and_set_config_dword(dev, 0xE0, 0, 1 << 22);
>  
> +	xhci_pci_try_add_aux_device(dev);

Is it considered acceptable to add

	if (IS_ENABLED(CONFIG_USB_XHCI_PCI_AUXDEV))

before this call, remove #ifdef around the definitions of the auxdev
functions and rely on dead code elimination to clean them up?

We already have a similar trick with CONFIG_USB_XHCI_PCI_RENESAS here
and it seemed to be working, though the amount of conditional code is
much lower and so is the potential risk.

The reason for doing it this way was because Greg doesn't like #ifdefs
in .c files, and neither do static analyzers like them.

> +
>  	return 0;
>  
>  put_usb3_hcd:
> @@ -713,6 +825,8 @@ void xhci_pci_remove(struct pci_dev *dev)
>  	xhci = hcd_to_xhci(pci_get_drvdata(dev));
>  	set_power_d3 = xhci->quirks & XHCI_SPURIOUS_WAKEUP;
>  
> +	xhci_pci_try_remove_aux_device(dev);
> +
>  	xhci->xhc_state |= XHCI_STATE_REMOVING;
>  
>  	if (pci_choose_state(dev, PMSG_SUSPEND) == PCI_D0)
> -- 
> 2.53.0
> 

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

* Re: [PATCH v2 2/2] hwmon: add initial support for AMD PROM21 xHCI temperature sensor
  2026-05-06 20:40   ` [PATCH v2 2/2] hwmon: add initial support for AMD PROM21 xHCI temperature sensor Jihong Min
@ 2026-05-06 21:33     ` Michal Pecio
  2026-05-06 21:36       ` Mario Limonciello
  2026-05-06 22:41       ` Jihong Min
  2026-05-06 22:17     ` Randy Dunlap
  1 sibling, 2 replies; 16+ messages in thread
From: Michal Pecio @ 2026-05-06 21:33 UTC (permalink / raw)
  To: Jihong Min
  Cc: Greg Kroah-Hartman, Mathias Nyman, Guenter Roeck, Jonathan Corbet,
	Shuah Khan, Mario Limonciello, Basavaraj Natikar, linux-usb,
	linux-hwmon, linux-doc, linux-pci, linux-kernel

On Thu,  7 May 2026 05:40:34 +0900, Jihong Min wrote:
> AMD PROM21 xHCI controllers expose an 8-bit temperature value

I think this commit message and certainly the Kconfig help text should
include full name of the chip and perhaps its official marketing names
too, so that people better understand what hardware is supported.

So: "AMD Promontory 21 chipset" and "AM5 6xx/8xx series chipsets", or
whatever they are called by AMD and motherboard vendors.

> through a vendor-specific index/data register pair in the xHCI PCI
> MMIO BAR region. Add an auxiliary hwmon driver for AMD 1022:43fd
> controllers and bind it to the xhci_pci.hwmon auxiliary device
> created by xhci-pci.
> 
> The read path verifies the parent PCI function and uses the
> initialized xHCI HCD MMIO mapping. The vendor index register is at
> byte offset 0x3000 from the xHCI MMIO BAR base and the vendor data
> register is at byte offset 0x3008. The driver writes register selector
> 0x0001e520 to the index register, reads the raw temperature value from
> the low 8 bits of the data register, and restores the previous index
> before returning. Expose temp1_input and an xHCI label through hwmon.
> 
> Register the hwmon device under the parent PCI function so userspace
> reports it as a PCI adapter, while the auxiliary driver still owns the
> hwmon lifetime and unregisters it from the auxiliary remove path.
> 
> No public AMD reference is available for this value.

Is there any documentation of the index/data registers themselves?

Any potential danger that something else (FW? SMM?) uses them too?

> The conversion formula is derived from observed temperature readings:
> 
>   temp[C] = raw * 0.9066 - 78.624

Could make sense to describe methodology, particularly in case some
people would come and question the formula.

How was actual chip temperature measured?
Was the output compared with any other (Windows?) utilities?

People will be comparing these results and possibly trying to draw
some conclusions, like OMG Linux runs this chip 8°C hotter, should
I demand a full refund of my free Ubuntu download????!!!?

> The temperature register did not return a valid value while the xHCI
> PCI function was suspended in testing. Keep the existing behavior by
> default and allow temperature reads to wake the xHCI PCI device. Add an
> allow_pm_switch module parameter so users can disable that behavior;
> when disabled, reads do not wake the device and return -EAGAIN if it is
> suspended.

Is such behavior useful?

Maybe the driver could just disable runtime PM while it's loaded.

> 
> Document the supported device, register access, conversion formula,
> module parameter, sysfs attributes, and sysfs lookup method.
> 
> Assisted-by: Codex:gpt-5.5
> Signed-off-by: Jihong Min <hurryman2212@gmail.com>

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

* Re: [PATCH v2 2/2] hwmon: add initial support for AMD PROM21 xHCI temperature sensor
  2026-05-06 21:33     ` Michal Pecio
@ 2026-05-06 21:36       ` Mario Limonciello
  2026-05-07  9:08         ` Michal Pecio
  2026-05-06 22:41       ` Jihong Min
  1 sibling, 1 reply; 16+ messages in thread
From: Mario Limonciello @ 2026-05-06 21:36 UTC (permalink / raw)
  To: Michal Pecio, Jihong Min
  Cc: Greg Kroah-Hartman, Mathias Nyman, Guenter Roeck, Jonathan Corbet,
	Shuah Khan, Basavaraj Natikar, linux-usb, linux-hwmon, linux-doc,
	linux-pci, linux-kernel



On 5/6/26 16:33, Michal Pecio wrote:
> On Thu,  7 May 2026 05:40:34 +0900, Jihong Min wrote:
>> AMD PROM21 xHCI controllers expose an 8-bit temperature value
> 
> I think this commit message and certainly the Kconfig help text should
> include full name of the chip and perhaps its official marketing names
> too, so that people better understand what hardware is supported.
> 
> So: "AMD Promontory 21 chipset" and "AM5 6xx/8xx series chipsets", or
> whatever they are called by AMD and motherboard vendors.
> 
>> through a vendor-specific index/data register pair in the xHCI PCI
>> MMIO BAR region. Add an auxiliary hwmon driver for AMD 1022:43fd
>> controllers and bind it to the xhci_pci.hwmon auxiliary device
>> created by xhci-pci.
>>
>> The read path verifies the parent PCI function and uses the
>> initialized xHCI HCD MMIO mapping. The vendor index register is at
>> byte offset 0x3000 from the xHCI MMIO BAR base and the vendor data
>> register is at byte offset 0x3008. The driver writes register selector
>> 0x0001e520 to the index register, reads the raw temperature value from
>> the low 8 bits of the data register, and restores the previous index
>> before returning. Expose temp1_input and an xHCI label through hwmon.
>>
>> Register the hwmon device under the parent PCI function so userspace
>> reports it as a PCI adapter, while the auxiliary driver still owns the
>> hwmon lifetime and unregisters it from the auxiliary remove path.
>>
>> No public AMD reference is available for this value.
> 
> Is there any documentation of the index/data registers themselves?
> 
> Any potential danger that something else (FW? SMM?) uses them too?
> 
>> The conversion formula is derived from observed temperature readings:
>>
>>    temp[C] = raw * 0.9066 - 78.624
> 
> Could make sense to describe methodology, particularly in case some
> people would come and question the formula.
> 
> How was actual chip temperature measured?
> Was the output compared with any other (Windows?) utilities?
> 
> People will be comparing these results and possibly trying to draw
> some conclusions, like OMG Linux runs this chip 8°C hotter, should
> I demand a full refund of my free Ubuntu download????!!!?
> 
>> The temperature register did not return a valid value while the xHCI
>> PCI function was suspended in testing. Keep the existing behavior by
>> default and allow temperature reads to wake the xHCI PCI device. Add an
>> allow_pm_switch module parameter so users can disable that behavior;
>> when disabled, reads do not wake the device and return -EAGAIN if it is
>> suspended.
> 
> Is such behavior useful?
> 
> Maybe the driver could just disable runtime PM while it's loaded.

I'd encourage what we do in amdgpu for dGPUs. The hwmon files will 
return an error code (I forget which code) when the device is in runtime 
PM when called.  Don't explicitly wake it otherwise.

This prevents someone installing a sensor monitoring application and 
that application "being the only thing" keeping the dGPU awake.  If it's 
awake already for other reasons (like being used) then return valid data 
to the applications.

> 
>>
>> Document the supported device, register access, conversion formula,
>> module parameter, sysfs attributes, and sysfs lookup method.
>>
>> Assisted-by: Codex:gpt-5.5
>> Signed-off-by: Jihong Min <hurryman2212@gmail.com>


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

* Re: [PATCH v2 1/2] usb: xhci-pci: add generic auxiliary device interface
  2026-05-06 21:15     ` Michal Pecio
@ 2026-05-06 21:42       ` Jihong Min
  0 siblings, 0 replies; 16+ messages in thread
From: Jihong Min @ 2026-05-06 21:42 UTC (permalink / raw)
  To: Michal Pecio, Jihong Min
  Cc: Greg Kroah-Hartman, Mathias Nyman, Guenter Roeck, Jonathan Corbet,
	Shuah Khan, Mario Limonciello, Basavaraj Natikar, linux-usb,
	linux-hwmon, linux-doc, linux-pci, linux-kernel

Thank you.

I've changed the code by removing the preprocessor macros and protecting 
the two entry points with `if (IS_ENABLED(CONFIG_USB_XHCI_PCI_AUXDEV))`, 
for v3.


Jihong Min

On 5/7/26 06:15, Michal Pecio wrote:
> On Thu,  7 May 2026 05:40:33 +0900, Jihong Min wrote:
>> Some xHCI PCI controllers expose controller-specific functionality that is
>> not part of generic xHCI operation and is better handled by optional child
>> drivers in other subsystems. Add a small auxiliary device registration path
>> for selected xHCI PCI controllers.
>>
>> The initial table creates an xhci_pci.hwmon auxiliary device for AMD
>> 1022:43fd controllers. Store the created auxiliary device in devres so the
>> xhci-pci remove path destroys it before HCD teardown. Use a
>> PCI-domain-qualified id so auxiliary device names remain unique across PCI
>> domains.
>>
>> This keeps xhci-pci responsible only for publishing selected controller
>> functions while allowing subsystem-specific drivers to bind through the
>> auxiliary bus.
>>
>> Assisted-by: Codex:gpt-5.5
>> Signed-off-by: Jihong Min <hurryman2212@gmail.com>
>> ---
>>   drivers/usb/host/Kconfig    |  10 ++++
>>   drivers/usb/host/xhci-pci.c | 114 ++++++++++++++++++++++++++++++++++++
>>   2 files changed, 124 insertions(+)
>>
>> diff --git a/drivers/usb/host/Kconfig b/drivers/usb/host/Kconfig
>> index 0a277a07cf70..e0c2c7ac5c97 100644
>> --- a/drivers/usb/host/Kconfig
>> +++ b/drivers/usb/host/Kconfig
>> @@ -42,6 +42,16 @@ config USB_XHCI_PCI
>>   	depends on USB_PCI
>>   	default y
>>   
>> +config USB_XHCI_PCI_AUXDEV
>> +	bool "xHCI PCI auxiliary device support"
>> +	depends on USB_XHCI_PCI
>> +	select AUXILIARY_BUS
>> +	help
>> +	  This enables xHCI PCI support for registering auxiliary devices
>> +	  for selected controllers. It is used by optional child drivers
>> +	  that bind to xHCI PCI controller-specific functionality through
>> +	  the auxiliary bus.
>> +
>>   config USB_XHCI_PCI_RENESAS
>>   	tristate "Support for additional Renesas xHCI controller with firmware"
>>   	depends on USB_XHCI_PCI
>> diff --git a/drivers/usb/host/xhci-pci.c b/drivers/usb/host/xhci-pci.c
>> index 585b2f3117b0..1ab27d2182eb 100644
>> --- a/drivers/usb/host/xhci-pci.c
>> +++ b/drivers/usb/host/xhci-pci.c
>> @@ -8,6 +8,8 @@
>>    * Some code borrowed from the Linux EHCI driver.
>>    */
>>   
>> +#include <linux/auxiliary_bus.h>
>> +#include <linux/device/devres.h>
>>   #include <linux/pci.h>
>>   #include <linux/slab.h>
>>   #include <linux/module.h>
>> @@ -103,6 +105,114 @@ static int xhci_pci_run(struct usb_hcd *hcd);
>>   static int xhci_pci_update_hub_device(struct usb_hcd *hcd, struct usb_device *hdev,
>>   				      struct usb_tt *tt, gfp_t mem_flags);
>>   
>> +#if IS_ENABLED(CONFIG_USB_XHCI_PCI_AUXDEV)
>> +static const struct {
>> +	struct pci_device_id id;
>> +	const char *aux_dev_name;
>> +} pci_ids_have_aux[] = {
>> +	{
>> +		.id = { PCI_DEVICE(PCI_VENDOR_ID_AMD, 0x43fd) }, /* PROM21 xHCI */
>> +		.aux_dev_name = "hwmon",
>> +	},
>> +	{ /* end: all zeroes */ }
>> +};
>> +
>> +struct xhci_pci_aux_devres {
>> +	struct auxiliary_device *auxdev;
>> +};
>> +
>> +static bool xhci_pci_aux_match_id(const struct pci_device_id *id,
>> +				  const struct pci_dev *pdev)
>> +{
>> +	if (id->vendor != PCI_ANY_ID && id->vendor != pdev->vendor)
>> +		return false;
>> +	if (id->device != PCI_ANY_ID && id->device != pdev->device)
>> +		return false;
>> +	if (id->subvendor != PCI_ANY_ID &&
>> +	    id->subvendor != pdev->subsystem_vendor)
>> +		return false;
>> +	if (id->subdevice != PCI_ANY_ID &&
>> +	    id->subdevice != pdev->subsystem_device)
>> +		return false;
>> +
>> +	return !((id->class ^ pdev->class) & id->class_mask);
>> +}
>> +
>> +static const char *xhci_pci_aux_dev_name(struct pci_dev *pdev)
>> +{
>> +	int i;
>> +
>> +	for (i = 0; pci_ids_have_aux[i].aux_dev_name; i++) {
>> +		if (xhci_pci_aux_match_id(&pci_ids_have_aux[i].id, pdev))
>> +			return pci_ids_have_aux[i].aux_dev_name;
>> +	}
>> +
>> +	return NULL;
>> +}
>> +
>> +static void xhci_pci_aux_devres_release(struct device *dev, void *res)
>> +{
>> +	struct xhci_pci_aux_devres *devres = res;
>> +
>> +	if (devres->auxdev)
>> +		auxiliary_device_destroy(devres->auxdev);
>> +}
>> +
>> +static void xhci_pci_try_add_aux_device(struct pci_dev *pdev)
>> +{
>> +	struct xhci_pci_aux_devres *devres;
>> +	struct auxiliary_device *auxdev;
>> +	const char *aux_dev_name;
>> +
>> +	aux_dev_name = xhci_pci_aux_dev_name(pdev);
>> +	if (!aux_dev_name)
>> +		return;
>> +
>> +	devres = devres_alloc(xhci_pci_aux_devres_release, sizeof(*devres),
>> +			      GFP_KERNEL);
>> +	if (!devres) {
>> +		dev_warn(&pdev->dev,
>> +			 "failed to allocate auxiliary device state\n");
>> +		return;
>> +	}
>> +
>> +	auxdev = auxiliary_device_create(&pdev->dev, KBUILD_MODNAME,
>> +					 aux_dev_name, NULL,
>> +					 (pci_domain_nr(pdev->bus) << 16) |
>> +						 pci_dev_id(pdev));
>> +	if (!auxdev) {
>> +		devres_free(devres);
>> +		dev_warn(&pdev->dev, "failed to add %s auxiliary device\n",
>> +			 aux_dev_name);
>> +		return;
>> +	}
>> +
>> +	devres->auxdev = auxdev;
>> +	devres_add(&pdev->dev, devres);
>> +}
>> +
>> +static void xhci_pci_try_remove_aux_device(struct pci_dev *pdev)
>> +{
>> +	struct xhci_pci_aux_devres *devres;
>> +
>> +	devres = devres_find(&pdev->dev, xhci_pci_aux_devres_release, NULL,
>> +			     NULL);
>> +	if (!devres || !devres->auxdev)
>> +		return;
>> +
>> +	auxiliary_device_destroy(devres->auxdev);
>> +	devres->auxdev = NULL;
>> +}
>> +#else
>> +static inline void xhci_pci_try_add_aux_device(struct pci_dev *pdev)
>> +{
>> +}
>> +
>> +static inline void xhci_pci_try_remove_aux_device(struct pci_dev *pdev)
>> +{
>> +}
>> +#endif
>> +
>>   static const struct xhci_driver_overrides xhci_pci_overrides __initconst = {
>>   	.reset = xhci_pci_setup,
>>   	.start = xhci_pci_run,
>> @@ -677,6 +787,8 @@ int xhci_pci_common_probe(struct pci_dev *dev, const struct pci_device_id *id)
>>   	if (device_property_read_bool(&dev->dev, "ti,pwron-active-high"))
>>   		pci_clear_and_set_config_dword(dev, 0xE0, 0, 1 << 22);
>>   
>> +	xhci_pci_try_add_aux_device(dev);
> Is it considered acceptable to add
>
> 	if (IS_ENABLED(CONFIG_USB_XHCI_PCI_AUXDEV))
>
> before this call, remove #ifdef around the definitions of the auxdev
> functions and rely on dead code elimination to clean them up?
>
> We already have a similar trick with CONFIG_USB_XHCI_PCI_RENESAS here
> and it seemed to be working, though the amount of conditional code is
> much lower and so is the potential risk.
>
> The reason for doing it this way was because Greg doesn't like #ifdefs
> in .c files, and neither do static analyzers like them.
>
>> +
>>   	return 0;
>>   
>>   put_usb3_hcd:
>> @@ -713,6 +825,8 @@ void xhci_pci_remove(struct pci_dev *dev)
>>   	xhci = hcd_to_xhci(pci_get_drvdata(dev));
>>   	set_power_d3 = xhci->quirks & XHCI_SPURIOUS_WAKEUP;
>>   
>> +	xhci_pci_try_remove_aux_device(dev);
>> +
>>   	xhci->xhc_state |= XHCI_STATE_REMOVING;
>>   
>>   	if (pci_choose_state(dev, PMSG_SUSPEND) == PCI_D0)
>> -- 
>> 2.53.0
>>

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

* Re: [PATCH v2 2/2] hwmon: add initial support for AMD PROM21 xHCI temperature sensor
  2026-05-06 20:40   ` [PATCH v2 2/2] hwmon: add initial support for AMD PROM21 xHCI temperature sensor Jihong Min
  2026-05-06 21:33     ` Michal Pecio
@ 2026-05-06 22:17     ` Randy Dunlap
  2026-05-06 22:52       ` Jihong Min
  1 sibling, 1 reply; 16+ messages in thread
From: Randy Dunlap @ 2026-05-06 22:17 UTC (permalink / raw)
  To: Jihong Min, Greg Kroah-Hartman, Mathias Nyman
  Cc: Guenter Roeck, Jonathan Corbet, Shuah Khan, Mario Limonciello,
	Basavaraj Natikar, linux-usb, linux-hwmon, linux-doc, linux-pci,
	linux-kernel



On 5/6/26 1:40 PM, Jihong Min wrote:
> diff --git a/Documentation/hwmon/index.rst b/Documentation/hwmon/index.rst
> index 8b655e5d6b68..0d85b78596cf 100644
> --- a/Documentation/hwmon/index.rst
> +++ b/Documentation/hwmon/index.rst
> @@ -215,6 +215,7 @@ Hardware Monitoring Kernel Drivers
>     peci-dimmtemp
>     pmbus
>     powerz
> +   prom21-hwmon
>     powr1220
>     pt5161l
>     pxe1610

It sorta looks like these entries are supposed to be maintained in alphabetical
order, but that new entry is not.

-- 
~Randy


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

* Re: [PATCH v2 2/2] hwmon: add initial support for AMD PROM21 xHCI temperature sensor
  2026-05-06 21:33     ` Michal Pecio
  2026-05-06 21:36       ` Mario Limonciello
@ 2026-05-06 22:41       ` Jihong Min
  2026-05-07  8:51         ` Michal Pecio
  1 sibling, 1 reply; 16+ messages in thread
From: Jihong Min @ 2026-05-06 22:41 UTC (permalink / raw)
  To: Michal Pecio, Jihong Min, Mario Limonciello
  Cc: Greg Kroah-Hartman, Mathias Nyman, Guenter Roeck, Jonathan Corbet,
	Shuah Khan, Basavaraj Natikar, linux-usb, linux-hwmon, linux-doc,
	linux-pci, linux-kernel

 > I think this commit message and certainly the Kconfig help text should
 > include full name of the chip and perhaps its official marketing names
 > too, so that people better understand what hardware is supported.
 >
 > So: "AMD Promontory 21 chipset" and "AM5 6xx/8xx series chipsets", or
 > whatever they are called by AMD and motherboard vendors.

Addressed locally for v3. I changed the commit message, Kconfig prompt/help
text, and hwmon documentation to use the full name, "AMD Promontory 21
(PROM21)".

I avoided putting chipset marketing names directly into the Kconfig text and
commit subject because some AMD 6xx/8xx series chipsets can be built 
from more
than one PROM21 IP in a daisy-chained configuration, including more than one
PROM21 xHCI controller. I described that relationship in the hwmon
documentation instead.

 > Is there any documentation of the index/data registers themselves?

I am not aware of public AMD documentation for the PROM21 vendor index/data
registers or the temperature selector.

For my initial validation on an X870E system with two PROM21 xHCI 
controllers,
I passed one PROM21 xHCI controller through to a Windows VM, left USB 
traffic
idle, and let a Windows monitoring utility poll the controller temperature.
 From the Linux host I monitored that controller's PCI MMIO BAR with 
read-only
accesses. The vendor index register repeatedly held the same selector value,
and the adjacent data register exposed a stable low 8-bit value. That value
matched the reported PROM21 xHCI temperature after the conversion formula
below.

 > Any potential danger that something else (FW? SMM?) uses them too?

I did not find any other in-kernel user of this PROM21 vendor index/data
register pair or the temperature selector.

The driver only serializes its own accesses. It saves the previous index,
selects the temperature register, reads the data register, restores the
previous index, and keeps the sequence short. This avoids leaving the vendor
index/data pair in a different state for other OS code.

This cannot synchronize against firmware or SMM. I cannot rule out such 
access
without AMD documentation or confirmation, so I would appreciate AMD 
feedback
on whether this PROM21 vendor index/data register pair is safe for OS 
polling.

I also tested concurrent temperature reads while USB traffic was active 
on the
same controller, including fio against an external USB storage device and
isochronous USB audio playback/capture. I did not observe USB transfer 
errors
or audio glitches in those tests.

 > Could make sense to describe methodology, particularly in case some
 > people would come and question the formula.
 >
 > How was actual chip temperature measured?
 > Was the output compared with any other (Windows?) utilities?
 >
 > People will be comparing these results and possibly trying to draw
 > some conclusions, like OMG Linux runs this chip 8°C hotter, should
 > I demand a full refund of my free Ubuntu download????!!!?

After identifying the register pair, I used the same validation setup to 
derive
the conversion formula by comparing the observed raw MMIO register value
against HWiNFO64's reported PROM21 xHCI temperature on Windows.

This worked because the PROM21 xHCI temperature is very stable at idle 
and the
sensor appears to have low resolution, so the value usually stays unchanged
long enough to compare both sides reliably.

 > Is such behavior useful?
 >
 > Maybe the driver could just disable runtime PM while it's loaded.

and:

 > I'd encourage what we do in amdgpu for dGPUs. The hwmon files will
 > return an error code (I forget which code) when the device is in runtime
 > PM when called.  Don't explicitly wake it otherwise.
 >
 > This prevents someone installing a sensor monitoring application and
 > that application "being the only thing" keeping the dGPU awake.  If it's
 > awake already for other reasons (like being used) then return valid data
 > to the applications.

I changed the local v3 branch to follow the amdgpu-style behavior by 
default.
The driver now does not wake the xHCI PCI device for a normal hwmon read. If
the device is already active, the read returns valid data. If the device is
suspended, the read returns -EPERM, matching the error code currently 
returned
by amdgpu's pm_runtime_get_if_active() based path. I used -EPERM to 
match the
current amdgpu precedent, but I can change the errno if maintainers prefer a
different one for this driver.

I kept the allow_pm_switch module parameter for now, but changed its 
default to
false. With the default setting, hwmon reads do not change the device 
runtime PM
state. Setting allow_pm_switch=Y explicitly opts into waking the xHCI PCI
device for temperature reads.

Thank you,
Jihong Min

On 5/7/26 06:33, Michal Pecio wrote:
> On Thu,  7 May 2026 05:40:34 +0900, Jihong Min wrote:
>> AMD PROM21 xHCI controllers expose an 8-bit temperature value
> I think this commit message and certainly the Kconfig help text should
> include full name of the chip and perhaps its official marketing names
> too, so that people better understand what hardware is supported.
>
> So: "AMD Promontory 21 chipset" and "AM5 6xx/8xx series chipsets", or
> whatever they are called by AMD and motherboard vendors.
>
>> through a vendor-specific index/data register pair in the xHCI PCI
>> MMIO BAR region. Add an auxiliary hwmon driver for AMD 1022:43fd
>> controllers and bind it to the xhci_pci.hwmon auxiliary device
>> created by xhci-pci.
>>
>> The read path verifies the parent PCI function and uses the
>> initialized xHCI HCD MMIO mapping. The vendor index register is at
>> byte offset 0x3000 from the xHCI MMIO BAR base and the vendor data
>> register is at byte offset 0x3008. The driver writes register selector
>> 0x0001e520 to the index register, reads the raw temperature value from
>> the low 8 bits of the data register, and restores the previous index
>> before returning. Expose temp1_input and an xHCI label through hwmon.
>>
>> Register the hwmon device under the parent PCI function so userspace
>> reports it as a PCI adapter, while the auxiliary driver still owns the
>> hwmon lifetime and unregisters it from the auxiliary remove path.
>>
>> No public AMD reference is available for this value.
> Is there any documentation of the index/data registers themselves?
>
> Any potential danger that something else (FW? SMM?) uses them too?
>
>> The conversion formula is derived from observed temperature readings:
>>
>>    temp[C] = raw * 0.9066 - 78.624
> Could make sense to describe methodology, particularly in case some
> people would come and question the formula.
>
> How was actual chip temperature measured?
> Was the output compared with any other (Windows?) utilities?
>
> People will be comparing these results and possibly trying to draw
> some conclusions, like OMG Linux runs this chip 8°C hotter, should
> I demand a full refund of my free Ubuntu download????!!!?
>
>> The temperature register did not return a valid value while the xHCI
>> PCI function was suspended in testing. Keep the existing behavior by
>> default and allow temperature reads to wake the xHCI PCI device. Add an
>> allow_pm_switch module parameter so users can disable that behavior;
>> when disabled, reads do not wake the device and return -EAGAIN if it is
>> suspended.
> Is such behavior useful?
>
> Maybe the driver could just disable runtime PM while it's loaded.
>
>> Document the supported device, register access, conversion formula,
>> module parameter, sysfs attributes, and sysfs lookup method.
>>
>> Assisted-by: Codex:gpt-5.5
>> Signed-off-by: Jihong Min <hurryman2212@gmail.com>

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

* Re: [PATCH v2 2/2] hwmon: add initial support for AMD PROM21 xHCI temperature sensor
  2026-05-06 22:17     ` Randy Dunlap
@ 2026-05-06 22:52       ` Jihong Min
  2026-05-07  3:29         ` Jihong Min
  0 siblings, 1 reply; 16+ messages in thread
From: Jihong Min @ 2026-05-06 22:52 UTC (permalink / raw)
  To: Randy Dunlap, Jihong Min, Greg Kroah-Hartman, Mathias Nyman
  Cc: Guenter Roeck, Jonathan Corbet, Shuah Khan, Mario Limonciello,
	Basavaraj Natikar, linux-usb, linux-hwmon, linux-doc, linux-pci,
	linux-kernel

 > It sorta looks like these entries are supposed to be maintained in
 > alphabetical order, but that new entry is not.

Yes, you are right. I also noticed that but it seems I pasted it in the 
wrong place.
Fixed this locally for v3 by moving prom21-hwmon after powr1220 and next 
to pt5161l.

Thank you,
Jihong Min

On 5/7/26 07:17, Randy Dunlap wrote:
>
> On 5/6/26 1:40 PM, Jihong Min wrote:
>> diff --git a/Documentation/hwmon/index.rst b/Documentation/hwmon/index.rst
>> index 8b655e5d6b68..0d85b78596cf 100644
>> --- a/Documentation/hwmon/index.rst
>> +++ b/Documentation/hwmon/index.rst
>> @@ -215,6 +215,7 @@ Hardware Monitoring Kernel Drivers
>>      peci-dimmtemp
>>      pmbus
>>      powerz
>> +   prom21-hwmon
>>      powr1220
>>      pt5161l
>>      pxe1610
> It sorta looks like these entries are supposed to be maintained in alphabetical
> order, but that new entry is not.
>

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

* Re: [PATCH v2 2/2] hwmon: add initial support for AMD PROM21 xHCI temperature sensor
  2026-05-06 22:52       ` Jihong Min
@ 2026-05-07  3:29         ` Jihong Min
  0 siblings, 0 replies; 16+ messages in thread
From: Jihong Min @ 2026-05-07  3:29 UTC (permalink / raw)
  To: Randy Dunlap, Jihong Min, Greg Kroah-Hartman, Mathias Nyman
  Cc: Guenter Roeck, Jonathan Corbet, Shuah Khan, Mario Limonciello,
	Basavaraj Natikar, linux-usb, linux-hwmon, linux-doc, linux-pci,
	linux-kernel

I noticed that my v2 series was accidentally sent as a reply to the v1
discussion, which made the patch series harder to track. It also appears
that Sashiko did not pick up v2 as a separate patchset because of the
threading.

I will send v3 as a clean new thread with the review feedback addressed so
far.

Thank you,
Jihong Min

On 5/7/26 07:52, Jihong Min wrote:
> > It sorta looks like these entries are supposed to be maintained in
> > alphabetical order, but that new entry is not.
>
> Yes, you are right. I also noticed that but it seems I pasted it in 
> the wrong place.
> Fixed this locally for v3 by moving prom21-hwmon after powr1220 and 
> next to pt5161l.
>
> Thank you,
> Jihong Min
>
> On 5/7/26 07:17, Randy Dunlap wrote:
>>
>> On 5/6/26 1:40 PM, Jihong Min wrote:
>>> diff --git a/Documentation/hwmon/index.rst 
>>> b/Documentation/hwmon/index.rst
>>> index 8b655e5d6b68..0d85b78596cf 100644
>>> --- a/Documentation/hwmon/index.rst
>>> +++ b/Documentation/hwmon/index.rst
>>> @@ -215,6 +215,7 @@ Hardware Monitoring Kernel Drivers
>>>      peci-dimmtemp
>>>      pmbus
>>>      powerz
>>> +   prom21-hwmon
>>>      powr1220
>>>      pt5161l
>>>      pxe1610
>> It sorta looks like these entries are supposed to be maintained in 
>> alphabetical
>> order, but that new entry is not.
>>

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

* Re: [PATCH v2 2/2] hwmon: add initial support for AMD PROM21 xHCI temperature sensor
  2026-05-06 22:41       ` Jihong Min
@ 2026-05-07  8:51         ` Michal Pecio
  0 siblings, 0 replies; 16+ messages in thread
From: Michal Pecio @ 2026-05-07  8:51 UTC (permalink / raw)
  To: Jihong Min
  Cc: Jihong Min, Mario Limonciello, Greg Kroah-Hartman, Mathias Nyman,
	Guenter Roeck, Jonathan Corbet, Shuah Khan, Basavaraj Natikar,
	linux-usb, linux-hwmon, linux-doc, linux-pci, linux-kernel

On Thu, 7 May 2026 07:41:28 +0900, Jihong Min wrote:
> > I think this commit message and certainly the Kconfig help text
> > should include full name of the chip and perhaps its official
> > marketing names too, so that people better understand what hardware
> > is supported.
> >
> > So: "AMD Promontory 21 chipset" and "AM5 6xx/8xx series chipsets",
> > or whatever they are called by AMD and motherboard vendors.  
> 
> Addressed locally for v3. I changed the commit message, Kconfig
> prompt/help text, and hwmon documentation to use the full name, "AMD
> Promontory 21 (PROM21)".
> 
> I avoided putting chipset marketing names directly into the Kconfig
> text and commit subject because some AMD 6xx/8xx series chipsets can
> be built from more than one PROM21 IP in a daisy-chained
> configuration, including more than one PROM21 xHCI controller.

Not sure how is this a problem?
The driver is still applicable to those daisy-chained chipsets.

Configuring the kernel is tedious enough already, the help text should
ideally tell me whether I need this driver or not without searching
for obscure code names.

I would even go as far as to mention that it's for AM5 chipsets,
because AMD recycles chipset numbers every few generations.

>  > Is there any documentation of the index/data registers themselves?
> 
> I am not aware of public AMD documentation for the PROM21 vendor
> index/data registers or the temperature selector.
> 
> For my initial validation on an X870E system with two decade or
> so.PROM21 xHCI controllers, I passed one PROM21 xHCI controller
> through to a Windows VM, left USB traffic idle, and let a Windows
> monitoring utility poll the controller temperature. From the Linux
> host I monitored that controller's PCI MMIO BAR with read-only
> accesses.
>
> The vendor index register repeatedly held the same selector value,
> and the adjacent data register exposed a stable low 8-bit value.
> [...]
>
> After identifying the register pair, I used the same validation setup
> to derive the conversion formula by comparing the observed raw MMIO
> register value against HWiNFO64's reported PROM21 xHCI temperature on
> Windows.

Looks good, unless there are gotchas like the actual formula being
dependent on other factors you haven't noticed HWiNFO reading.

It would be good idea to record this methodology in the commit message
or docs so that others can repeat your experiment in case of issues.

Regards,
Michal

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

* Re: [PATCH v2 2/2] hwmon: add initial support for AMD PROM21 xHCI temperature sensor
  2026-05-06 21:36       ` Mario Limonciello
@ 2026-05-07  9:08         ` Michal Pecio
  2026-05-07 13:24           ` Mario Limonciello
  0 siblings, 1 reply; 16+ messages in thread
From: Michal Pecio @ 2026-05-07  9:08 UTC (permalink / raw)
  To: Mario Limonciello
  Cc: Jihong Min, Greg Kroah-Hartman, Mathias Nyman, Guenter Roeck,
	Jonathan Corbet, Shuah Khan, Basavaraj Natikar, linux-usb,
	linux-hwmon, linux-doc, linux-pci, linux-kernel

On Wed, 6 May 2026 16:36:49 -0500, Mario Limonciello wrote:
> > > The temperature register did not return a valid value while the
> > > xHCI PCI function was suspended in testing. Keep the existing
> > > behavior by default and allow temperature reads to wake the xHCI
> > > PCI device. Add an allow_pm_switch module parameter so users can
> > > disable that behavior; when disabled, reads do not wake the
> > > device and return -EAGAIN if it is suspended.  
> > 
> > Is such behavior useful?
> > 
> > Maybe the driver could just disable runtime PM while it's loaded.  
> 
> I'd encourage what we do in amdgpu for dGPUs. The hwmon files will 
> return an error code (I forget which code) when the device is in
> runtime PM when called.  Don't explicitly wake it otherwise.
> 
> This prevents someone installing a sensor monitoring application and 
> that application "being the only thing" keeping the dGPU awake.  If
> it's awake already for other reasons (like being used) then return
> valid data to the applications

Well, that's not a dGPU but an xHCI controller embedded in the chipset,
which chipset is more or less active all the time (includes bridges to
PCIe ports, some SATA controllers and mabe other things I forgot).
Is the saving from disabling xHCI significant for a desktop system?

Users may be interested in monitoring chipset temperature even while
not actively using USB.

I don't know what are the conditions to put GPUs into runtime suspend,
but a USB HC will be going in and out quite randomly, depending on
connected devices and their workload. You may end up needing to answer
people why their sensor only works when they turn on a webcam :)

Alternatively, would it be possible to bring a suspendend HC into D0,
read the temperature register and then put it back into D3hot without
bothering the USB layer to fully resume and suspend xHCI logic?

Regards,
Michal

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

* Re: [PATCH v2 2/2] hwmon: add initial support for AMD PROM21 xHCI temperature sensor
  2026-05-07  9:08         ` Michal Pecio
@ 2026-05-07 13:24           ` Mario Limonciello
  0 siblings, 0 replies; 16+ messages in thread
From: Mario Limonciello @ 2026-05-07 13:24 UTC (permalink / raw)
  To: Michal Pecio
  Cc: Jihong Min, Greg Kroah-Hartman, Mathias Nyman, Guenter Roeck,
	Jonathan Corbet, Shuah Khan, Basavaraj Natikar, linux-usb,
	linux-hwmon, linux-doc, linux-pci, linux-kernel



On 5/7/26 04:08, Michal Pecio wrote:
> On Wed, 6 May 2026 16:36:49 -0500, Mario Limonciello wrote:
>>>> The temperature register did not return a valid value while the
>>>> xHCI PCI function was suspended in testing. Keep the existing
>>>> behavior by default and allow temperature reads to wake the xHCI
>>>> PCI device. Add an allow_pm_switch module parameter so users can
>>>> disable that behavior; when disabled, reads do not wake the
>>>> device and return -EAGAIN if it is suspended.
>>>
>>> Is such behavior useful?
>>>
>>> Maybe the driver could just disable runtime PM while it's loaded.
>>
>> I'd encourage what we do in amdgpu for dGPUs. The hwmon files will
>> return an error code (I forget which code) when the device is in
>> runtime PM when called.  Don't explicitly wake it otherwise.
>>
>> This prevents someone installing a sensor monitoring application and
>> that application "being the only thing" keeping the dGPU awake.  If
>> it's awake already for other reasons (like being used) then return
>> valid data to the applications
> 
> Well, that's not a dGPU but an xHCI controller embedded in the chipset,
> which chipset is more or less active all the time (includes bridges to
> PCIe ports, some SATA controllers and mabe other things I forgot).
> Is the saving from disabling xHCI significant for a desktop system?
> 
> Users may be interested in monitoring chipset temperature even while
> not actively using USB.
> 
> I don't know what are the conditions to put GPUs into runtime suspend,
> but a USB HC will be going in and out quite randomly, depending on
> connected devices and their workload. You may end up needing to answer
> people why their sensor only works when they turn on a webcam :)

Heh.  You have a good point here.  The reason for this policy in dGPUs 
came from a lot of people using them "headless" (for example plugging in 
a display to the iGPU on the board) and wondering why randomly their 
power shot up and fans spun up on the GPU.  It took a while to narrow 
down that it was specifically sensor software doing it.

For a sensor accessed through registers on XHCI this is a lot less of a 
big deal for all the reasons you point out.

> 
> Alternatively, would it be possible to bring a suspendend HC into D0,
> read the temperature register and then put it back into D3hot without
> bothering the USB layer to fully resume and suspend xHCI logic?
> 
This sounds better to me if it's feasible.

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

end of thread, other threads:[~2026-05-07 13:25 UTC | newest]

Thread overview: 16+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
     [not found] <20260506032939.92351-1-hurryman2212@gmail.com>
2026-05-06 20:40 ` [PATCH v2 0/2] AMD PROM21 xHCI temperature hwmon support Jihong Min
2026-05-06 20:40   ` [PATCH v2 1/2] usb: xhci-pci: add generic auxiliary device interface Jihong Min
2026-05-06 20:53     ` Mario Limonciello
2026-05-06 21:09       ` Jihong Min
2026-05-06 21:15     ` Michal Pecio
2026-05-06 21:42       ` Jihong Min
2026-05-06 20:40   ` [PATCH v2 2/2] hwmon: add initial support for AMD PROM21 xHCI temperature sensor Jihong Min
2026-05-06 21:33     ` Michal Pecio
2026-05-06 21:36       ` Mario Limonciello
2026-05-07  9:08         ` Michal Pecio
2026-05-07 13:24           ` Mario Limonciello
2026-05-06 22:41       ` Jihong Min
2026-05-07  8:51         ` Michal Pecio
2026-05-06 22:17     ` Randy Dunlap
2026-05-06 22:52       ` Jihong Min
2026-05-07  3:29         ` Jihong Min

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