* [PATCH v3 2/3] PM: dpm_watchdog: Allow disabling DPM watchdog by default
From: Tzung-Bi Shih @ 2026-06-08 2:15 UTC (permalink / raw)
To: Jonathan Corbet, Rafael J. Wysocki, Greg Kroah-Hartman,
Danilo Krummrich
Cc: Shuah Khan, Pavel Machek, Len Brown, tzungbi, linux-doc,
linux-kernel, linux-pm, driver-core, tfiga, senozhatsky,
Randy Dunlap
In-Reply-To: <20260608021526.1023248-1-tzungbi@kernel.org>
Introduce the CONFIG_DPM_WATCHDOG_DEFAULT_ENABLED Kconfig option to
allow the device suspend/resume watchdog (DPM watchdog) to be disabled
by default at compile time.
Additionally, introduce the "dpm_watchdog_enabled" module parameter to
allow the watchdog to be enabled or disabled at boot time (via
"power.dpm_watchdog_enabled") and at runtime (via sysfs).
This provides flexibility for systems that want the watchdog code
compiled in but inactive by default, allowing it to be enabled only when
needed.
Signed-off-by: Tzung-Bi Shih <tzungbi@kernel.org>
---
v3:
- Add "PM" tag (was missing).
- Update the format and specify dependencies in kernel-parameters.txt.
- Update the help message in Kconfig to reflect that dpm_watchdog_enabled
can be set at runtime as well.
v2: https://lore.kernel.org/all/20260604090756.2884671-3-tzungbi@kernel.org
- Use module parameter and bool for dpm_watchdog_enabled.
- Use IS_ENABLED().
v1: https://lore.kernel.org/all/20260528103215.505795-1-tzungbi@kernel.org
Documentation/admin-guide/kernel-parameters.txt | 8 ++++++++
drivers/base/power/main.c | 11 +++++++++++
kernel/power/Kconfig | 10 ++++++++++
3 files changed, 29 insertions(+)
diff --git a/Documentation/admin-guide/kernel-parameters.txt b/Documentation/admin-guide/kernel-parameters.txt
index 00375193bd26..f2620764c28e 100644
--- a/Documentation/admin-guide/kernel-parameters.txt
+++ b/Documentation/admin-guide/kernel-parameters.txt
@@ -47,6 +47,7 @@
PCI PCI bus support is enabled.
PCIE PCI Express support is enabled.
PCMCIA The PCMCIA subsystem is enabled.
+ PM Power Management support is enabled.
PNP Plug & Play support is enabled.
PPC PowerPC architecture is enabled.
PPT Parallel port support is enabled.
@@ -5399,6 +5400,13 @@ Kernel parameters
function to NULL. On Idle the CPU just reduces
execution priority.
+ power.dpm_watchdog_enabled=
+ [PM] Enable or disable the device suspend/resume
+ watchdog (DPM watchdog). Requires CONFIG_PM_SLEEP and
+ CONFIG_DPM_WATCHDOG enabled.
+ Format: <bool>
+ Default value is set by CONFIG_DPM_WATCHDOG_DEFAULT_ENABLED.
+
ppc_strict_facility_enable
[PPC,ENABLE] This option catches any kernel floating point,
Altivec, VSX and SPE outside of regions specifically
diff --git a/drivers/base/power/main.c b/drivers/base/power/main.c
index cd864f3a2799..7822c29b7c8d 100644
--- a/drivers/base/power/main.c
+++ b/drivers/base/power/main.c
@@ -534,6 +534,11 @@ module_param(dpm_watchdog_all_cpu_backtrace, bool, 0644);
MODULE_PARM_DESC(dpm_watchdog_all_cpu_backtrace,
"Backtrace all CPUs on DPM watchdog timeout");
+static bool __read_mostly dpm_watchdog_enabled =
+ IS_ENABLED(CONFIG_DPM_WATCHDOG_DEFAULT_ENABLED);
+module_param(dpm_watchdog_enabled, bool, 0644);
+MODULE_PARM_DESC(dpm_watchdog_enabled, "Enable DPM watchdog");
+
/**
* dpm_watchdog_handler - Driver suspend / resume watchdog handler.
* @t: The timer that PM watchdog depends on.
@@ -577,6 +582,9 @@ static void dpm_watchdog_set(struct dpm_watchdog *wd, struct device *dev)
{
struct timer_list *timer = &wd->timer;
+ if (!dpm_watchdog_enabled)
+ return;
+
wd->dev = dev;
wd->tsk = current;
wd->fatal = CONFIG_DPM_WATCHDOG_TIMEOUT == CONFIG_DPM_WATCHDOG_WARNING_TIMEOUT;
@@ -595,6 +603,9 @@ static void dpm_watchdog_clear(struct dpm_watchdog *wd)
{
struct timer_list *timer = &wd->timer;
+ if (!dpm_watchdog_enabled)
+ return;
+
timer_delete_sync(timer);
timer_destroy_on_stack(timer);
}
diff --git a/kernel/power/Kconfig b/kernel/power/Kconfig
index 530c897311d4..b16bd159074a 100644
--- a/kernel/power/Kconfig
+++ b/kernel/power/Kconfig
@@ -268,6 +268,16 @@ config DPM_WATCHDOG
captured in pstore device for inspection in subsequent
boot session.
+config DPM_WATCHDOG_DEFAULT_ENABLED
+ bool "Enable DPM watchdog by default"
+ depends on DPM_WATCHDOG
+ default y
+ help
+ If you say Y here, the DPM watchdog will be enabled by default.
+ If you say N, it will be compiled in but disabled. It can be
+ enabled at boot time via the "power.dpm_watchdog_enabled" kernel
+ parameter or at runtime via sysfs.
+
config DPM_WATCHDOG_TIMEOUT
int "Watchdog timeout to panic in seconds"
range 1 120
--
2.54.0.1099.g489fc7bff1-goog
^ permalink raw reply related
* [PATCH v3 3/3] PM: dpm_watchdog: Add sysctl interface for DPM watchdog timeouts
From: Tzung-Bi Shih @ 2026-06-08 2:15 UTC (permalink / raw)
To: Jonathan Corbet, Rafael J. Wysocki, Greg Kroah-Hartman,
Danilo Krummrich
Cc: Shuah Khan, Pavel Machek, Len Brown, tzungbi, linux-doc,
linux-kernel, linux-pm, driver-core, tfiga, senozhatsky,
Randy Dunlap
In-Reply-To: <20260608021526.1023248-1-tzungbi@kernel.org>
Introduce sysctl knobs to allow configuring DPM watchdog timeouts at
runtime.
Currently, these timeouts are fixed at compile time via
CONFIG_DPM_WATCHDOG_TIMEOUT and CONFIG_DPM_WATCHDOG_WARNING_TIMEOUT.
This limits flexibility if the timeouts need to be adjusted for
different testing scenarios or hardware behaviors without rebuilding
the kernel.
Add the following sysctl files under /proc/sys/kernel/:
- dpm_watchdog_timeout_secs: The total timeout before panic. The
maximum value is capped at CONFIG_DPM_WATCHDOG_TIMEOUT to prevent
unreasonably large timeouts.
- dpm_watchdog_warning_timeout_secs: The warning timeout. The maximum
value is capped at the current dpm_watchdog_timeout_secs.
Both sysctls have a minimum value of 1.
Signed-off-by: Tzung-Bi Shih <tzungbi@kernel.org>
---
v3:
- No changes.
v2: https://lore.kernel.org/all/20260604090756.2884671-4-tzungbi@kernel.org
- New to the series.
v1: Doesn't exist.
drivers/base/power/main.c | 61 ++++++++++++++++++++++++++++++++++++---
1 file changed, 57 insertions(+), 4 deletions(-)
diff --git a/drivers/base/power/main.c b/drivers/base/power/main.c
index 7822c29b7c8d..c1a4b30fafb2 100644
--- a/drivers/base/power/main.c
+++ b/drivers/base/power/main.c
@@ -28,6 +28,7 @@
#include <linux/interrupt.h>
#include <linux/sched.h>
#include <linux/sched/debug.h>
+#include <linux/sysctl.h>
#include <linux/async.h>
#include <linux/suspend.h>
#include <trace/events/power.h>
@@ -539,6 +540,58 @@ static bool __read_mostly dpm_watchdog_enabled =
module_param(dpm_watchdog_enabled, bool, 0644);
MODULE_PARM_DESC(dpm_watchdog_enabled, "Enable DPM watchdog");
+static unsigned int __read_mostly dpm_watchdog_timeout = CONFIG_DPM_WATCHDOG_TIMEOUT;
+static unsigned int __read_mostly dpm_watchdog_warning_timeout =
+ CONFIG_DPM_WATCHDOG_WARNING_TIMEOUT;
+static const unsigned int dpm_watchdog_timeout_max = CONFIG_DPM_WATCHDOG_TIMEOUT;
+
+static int proc_dodpm_watchdog_timeout_secs(const struct ctl_table *table,
+ int write, void *buffer,
+ size_t *lenp, loff_t *ppos)
+{
+ struct ctl_table ctl = *table;
+ unsigned int val = dpm_watchdog_timeout;
+ int ret;
+
+ ctl.data = &val;
+ ret = proc_douintvec_minmax(&ctl, write, buffer, lenp, ppos);
+ if (ret || !write)
+ return ret;
+
+ if (val < dpm_watchdog_warning_timeout)
+ dpm_watchdog_warning_timeout = val;
+ dpm_watchdog_timeout = val;
+
+ return 0;
+}
+
+static const struct ctl_table dpm_watchdog_sysctls[] = {
+ {
+ .procname = "dpm_watchdog_timeout_secs",
+ .maxlen = sizeof(unsigned int),
+ .mode = 0644,
+ .proc_handler = proc_dodpm_watchdog_timeout_secs,
+ .extra1 = SYSCTL_ONE,
+ .extra2 = (void *)&dpm_watchdog_timeout_max,
+ },
+ {
+ .procname = "dpm_watchdog_warning_timeout_secs",
+ .data = &dpm_watchdog_warning_timeout,
+ .maxlen = sizeof(unsigned int),
+ .mode = 0644,
+ .proc_handler = proc_douintvec_minmax,
+ .extra1 = SYSCTL_ONE,
+ .extra2 = (void *)&dpm_watchdog_timeout,
+ },
+};
+
+static int __init dpm_watchdog_sysctl_init(void)
+{
+ register_sysctl_init("kernel", dpm_watchdog_sysctls);
+ return 0;
+}
+subsys_initcall(dpm_watchdog_sysctl_init);
+
/**
* dpm_watchdog_handler - Driver suspend / resume watchdog handler.
* @t: The timer that PM watchdog depends on.
@@ -564,9 +617,9 @@ static void dpm_watchdog_handler(struct timer_list *t)
dev_driver_string(wd->dev), dev_name(wd->dev));
}
- time_left = CONFIG_DPM_WATCHDOG_TIMEOUT - CONFIG_DPM_WATCHDOG_WARNING_TIMEOUT;
+ time_left = dpm_watchdog_timeout - dpm_watchdog_warning_timeout;
dev_warn(wd->dev, "**** DPM device timeout after %u seconds; %u seconds until panic ****\n",
- CONFIG_DPM_WATCHDOG_WARNING_TIMEOUT, time_left);
+ dpm_watchdog_warning_timeout, time_left);
show_stack(wd->tsk, NULL, KERN_WARNING);
wd->fatal = true;
@@ -587,11 +640,11 @@ static void dpm_watchdog_set(struct dpm_watchdog *wd, struct device *dev)
wd->dev = dev;
wd->tsk = current;
- wd->fatal = CONFIG_DPM_WATCHDOG_TIMEOUT == CONFIG_DPM_WATCHDOG_WARNING_TIMEOUT;
+ wd->fatal = dpm_watchdog_timeout == dpm_watchdog_warning_timeout;
timer_setup_on_stack(timer, dpm_watchdog_handler, 0);
/* use same timeout value for both suspend and resume */
- timer->expires = jiffies + HZ * CONFIG_DPM_WATCHDOG_WARNING_TIMEOUT;
+ timer->expires = jiffies + HZ * dpm_watchdog_warning_timeout;
add_timer(timer);
}
--
2.54.0.1099.g489fc7bff1-goog
^ permalink raw reply related
* Re: [PATCH v3 2/6] alloc_tag: add ioctl filters to /proc/allocinfo
From: Hao Ge @ 2026-06-08 2:39 UTC (permalink / raw)
To: Abhishek Bapat, Suren Baghdasaryan, Andrew Morton,
Kent Overstreet
Cc: Shuah Khan, Jonathan Corbet, linux-doc, linux-kernel, linux-mm,
Sourav Panda
In-Reply-To: <6f3b4aa0aa294cd56a73854c631de3ab7c0c5e01.1780701922.git.abhishekbapat@google.com>
Hi Abhishek
Thanks for the new version.
On 2026/6/6 07:36, Abhishek Bapat wrote:
> Extend the capability of the IOCTL mechanism to filter allocations based
> on tag's module name, function name, file name and line number.
>
> Signed-off-by: Abhishek Bapat <abhishekbapat@google.com>
Acked-by: Hao Ge <hao.ge@linux.dev>
> ---
> include/uapi/linux/alloc_tag.h | 26 ++++++++++++-
> lib/alloc_tag.c | 68 ++++++++++++++++++++++++++++++++--
> 2 files changed, 89 insertions(+), 5 deletions(-)
>
> diff --git a/include/uapi/linux/alloc_tag.h b/include/uapi/linux/alloc_tag.h
> index 901199bad514..cffb0c46e0b1 100644
> --- a/include/uapi/linux/alloc_tag.h
> +++ b/include/uapi/linux/alloc_tag.h
> @@ -34,8 +34,32 @@ struct allocinfo_tag_data {
> struct allocinfo_counter counter;
> };
>
> +enum {
> + ALLOCINFO_FILTER_MODNAME,
> + ALLOCINFO_FILTER_FUNCTION,
> + ALLOCINFO_FILTER_FILENAME,
> + ALLOCINFO_FILTER_LINENO,
> + __ALLOCINFO_FILTER_LAST = ALLOCINFO_FILTER_LINENO
> +};
> +
> +#define ALLOCINFO_FILTER_MASK_MODNAME (1 << ALLOCINFO_FILTER_MODNAME)
> +#define ALLOCINFO_FILTER_MASK_FUNCTION (1 << ALLOCINFO_FILTER_FUNCTION)
> +#define ALLOCINFO_FILTER_MASK_FILENAME (1 << ALLOCINFO_FILTER_FILENAME)
> +#define ALLOCINFO_FILTER_MASK_LINENO (1 << ALLOCINFO_FILTER_LINENO)
> +
> +#define ALLOCINFO_FILTER_MASKS \
> + ((1 << (__ALLOCINFO_FILTER_LAST + 1)) - 1)
> +
> +struct allocinfo_filter {
> + __u64 mask; /* bitmask of the filter fields used */
> + struct allocinfo_tag fields;
> +};
> +
> struct allocinfo_get_at {
> - __u64 pos; /* input */
> + /* inputs */
> + __u64 pos;
> + struct allocinfo_filter filter;
> + /* output */
> struct allocinfo_tag_data data;
> };
>
> diff --git a/lib/alloc_tag.c b/lib/alloc_tag.c
> index a0577215eb3d..93bc976ac505 100644
> --- a/lib/alloc_tag.c
> +++ b/lib/alloc_tag.c
> @@ -49,6 +49,7 @@ struct allocinfo_private {
> struct codetag_iterator iter;
> struct codetag_iterator reported_iter;
> bool print_header;
> + struct allocinfo_filter filter;
> /* ioctl uses a separate iterator not to interfere with reads */
> struct codetag_iterator ioctl_iter;
> bool positioned; /* seq_open_private() sets to 0 */
> @@ -184,6 +185,12 @@ static void allocinfo_copy_str(char *dest, const char *src)
> strscpy_pad(dest, allocinfo_str(src), ALLOCINFO_STR_SIZE);
> }
>
> +/* Compare two strings and only consider the trimmed suffix if s1 is too long */
> +static int allocinfo_cmp_str(const char *str, const char *template)
> +{
> + return strncmp(allocinfo_str(str), template, ALLOCINFO_STR_SIZE);
> +}
> +
> /*
> * Populates the UAPI allocinfo_tag_data structure with active runtime
> * profiling counters extracted from the given kernel codetag.
> @@ -223,6 +230,40 @@ static int allocinfo_ioctl_get_content_id(struct seq_file *m, void __user *arg)
> return 0;
> }
>
> +/*
> + * Verifies whether a given codetag satisfies the active filtering criteria by
> + * matching it's characteristics against the specified filter.
nit: s/it's/its/
> + */
> +static bool matches_filter(struct codetag *ct, struct allocinfo_filter *filter)
> +{
> + if (!filter || !filter->mask)
> + return true;
> +
> + if (filter->mask & ALLOCINFO_FILTER_MASK_MODNAME) {
> + /* user wants to filter by modname but ct->modname is NULL */
> + if (!ct->modname) {
> + /* validate if user was attempting to filter for built-in allocations */
> + if (filter->fields.modname[0] != '\0')
> + return false;
> + } else if (allocinfo_cmp_str(ct->modname, filter->fields.modname))
> + return false;
> + }
> +
> + if ((filter->mask & ALLOCINFO_FILTER_MASK_FUNCTION) &&
> + ct->function && (allocinfo_cmp_str(ct->function, filter->fields.function)))
> + return false;
> +
> + if ((filter->mask & ALLOCINFO_FILTER_MASK_FILENAME) &&
> + ct->filename && (allocinfo_cmp_str(ct->filename, filter->fields.filename)))
> + return false;
> +
> + if ((filter->mask & ALLOCINFO_FILTER_MASK_LINENO) &&
> + ct->lineno != filter->fields.lineno)
> + return false;
> +
> + return true;
> +}
> +
> /*
> * Seeks the ioctl iterator to the specified 0-indexed tag position, reads its
> * profiling data and returns it to userspace.
> @@ -231,29 +272,46 @@ static int allocinfo_ioctl_get_at(struct seq_file *m, void __user *arg)
> {
> struct allocinfo_private *priv;
> struct codetag *ct;
> - __u64 pos;
> struct allocinfo_get_at params = {0};
> + __u64 skip_count;
>
> if (copy_from_user(¶ms, arg, sizeof(params)))
> return -EFAULT;
>
> + if (params.filter.mask & ~ALLOCINFO_FILTER_MASKS)
> + return -EINVAL;
> +
> priv = m->private;
> - pos = params.pos;
>
> mutex_lock(&priv->ioctl_lock);
> codetag_lock_module_list(alloc_tag_cttype);
>
> - if (pos >= codetag_get_count(alloc_tag_cttype)) {
> + if (params.pos >= codetag_get_count(alloc_tag_cttype)) {
> codetag_unlock_module_list(alloc_tag_cttype);
> mutex_unlock(&priv->ioctl_lock);
> return -ENOENT;
> }
>
> + skip_count = params.pos;
> +
> + if (params.filter.mask)
> + priv->filter = params.filter;
> + else
> + priv->filter.mask = 0;
> +
> /* Find the codetag */
> priv->ioctl_iter = codetag_get_ct_iter(alloc_tag_cttype);
> ct = codetag_next_ct(&priv->ioctl_iter);
> - while (ct && pos--)
> +
> + while (ct) {
> + if (matches_filter(ct, &priv->filter)) {
> + if (skip_count == 0)
> + break;
> + skip_count--;
> + }
> ct = codetag_next_ct(&priv->ioctl_iter);
> + }
> +
> if (ct) {
> allocinfo_to_params(ct, ¶ms.data);
> priv->positioned = true;
> @@ -294,6 +352,8 @@ static int allocinfo_ioctl_get_next(struct seq_file *m, void __user *arg)
> }
>
> ct = codetag_next_ct(&priv->ioctl_iter);
> + while (ct && !matches_filter(ct, &priv->filter))
> + ct = codetag_next_ct(&priv->ioctl_iter);
> if (ct)
> allocinfo_to_params(ct, ¶ms);
>
^ permalink raw reply
* Re: [PATCH v6 03/11] x86/virt/tdx: Add tdx_alloc/free_control_page() helpers
From: Yan Zhao @ 2026-06-08 2:18 UTC (permalink / raw)
To: Binbin Wu
Cc: Rick Edgecombe, bp, dave.hansen, hpa, kas, kvm, linux-coco,
linux-doc, linux-kernel, mingo, nik.borisov, pbonzini, seanjc,
tglx, vannapurve, x86, chao.gao, kai.huang, Kirill A. Shutemov
In-Reply-To: <50566572-6379-4100-8845-404f695e59cd@linux.intel.com>
On Mon, Jun 08, 2026 at 10:11:58AM +0800, Binbin Wu wrote:
> > diff --git a/arch/x86/include/asm/tdx.h b/arch/x86/include/asm/tdx.h
> > index 82dc27aecf297..74e75db5728c7 100644
> > --- a/arch/x86/include/asm/tdx.h
> > +++ b/arch/x86/include/asm/tdx.h
> > @@ -37,6 +37,7 @@
> >
> > #include <uapi/asm/mce.h>
> > #include <asm/tdx_global_metadata.h>
> > +#include <linux/mm.h>
>
> I think the header is not needed here.
Right. This version does not invoke page_address() in tdx.h for
tdx_alloc_control_page() any more.
Also no need to include mm.h for tdx.c (which has invoked page_address() before
this patch), since tdx.c includes memblock.h which further includes mm.h.
^ permalink raw reply
* Re: [PATCH v4 1/2] dt-bindings: hwmon: pmbus: Add Analog Devices MAX20860A
From: Guenter Roeck @ 2026-06-08 3:08 UTC (permalink / raw)
To: Pradhan, Sanman
Cc: linux-hwmon@vger.kernel.org, robh@kernel.org, krzk+dt@kernel.org,
conor+dt@kernel.org, corbet@lwn.net, skhan@linuxfoundation.org,
devicetree@vger.kernel.org, linux-doc@vger.kernel.org,
linux-kernel@vger.kernel.org, noname.nuno@gmail.com, Syed, Arif,
Sanman Pradhan, Conor Dooley
In-Reply-To: <20260601184516.919488-2-sanman.pradhan@hpe.com>
On Mon, Jun 01, 2026 at 06:45:30PM +0000, Pradhan, Sanman wrote:
> From: Sanman Pradhan <psanman@juniper.net>
>
> Add devicetree binding documentation for the Analog Devices MAX20860A
> step-down DC-DC switching regulator with PMBus interface.
>
> Signed-off-by: Sanman Pradhan <psanman@juniper.net>
> Acked-by: Conor Dooley <conor.dooley@microchip.com>
Applied.
Thanks,
Guenter
^ permalink raw reply
* Re: [PATCH v4 2/2] hwmon: (pmbus/max20860a) Add driver for Analog Devices MAX20860A
From: Guenter Roeck @ 2026-06-08 3:09 UTC (permalink / raw)
To: Pradhan, Sanman
Cc: linux-hwmon@vger.kernel.org, robh@kernel.org, krzk+dt@kernel.org,
conor+dt@kernel.org, corbet@lwn.net, skhan@linuxfoundation.org,
devicetree@vger.kernel.org, linux-doc@vger.kernel.org,
linux-kernel@vger.kernel.org, noname.nuno@gmail.com, Syed, Arif,
Sanman Pradhan
In-Reply-To: <20260601184516.919488-3-sanman.pradhan@hpe.com>
On Mon, Jun 01, 2026 at 06:45:36PM +0000, Pradhan, Sanman wrote:
> From: Syed Arif <arif.syed@hpe.com>
>
> Add a PMBus driver for the Analog Devices MAX20860A step-down DC-DC
> switching regulator. The MAX20860A provides monitoring of input/output
> voltage, output current, and temperature via the PMBus interface using
> linear data format. Optional regulator support is available via
> CONFIG_SENSORS_MAX20860A_REGULATOR.
>
> Signed-off-by: Syed Arif <arif.syed@hpe.com>
> Signed-off-by: Sanman Pradhan <psanman@juniper.net>
Applied.
Thanks,
Guenter
^ permalink raw reply
* Re: [PATCH v2 2/3] hwmon: pmbus: Add support for Silergy SQ24860
From: Guenter Roeck @ 2026-06-08 3:34 UTC (permalink / raw)
To: Ziming Zhu
Cc: Rob Herring, Krzysztof Kozlowski, Conor Dooley, Jonathan Corbet,
Shuah Khan, linux-hwmon, devicetree, linux-kernel, linux-doc,
Ziming Zhu
In-Reply-To: <20260605063042.91776-3-zmzhu0630@163.com>
On Fri, Jun 05, 2026 at 02:30:41PM +0800, Ziming Zhu wrote:
> From: Ziming Zhu <ziming.zhu@silergycorp.com>
>
> Add PMBus hwmon support for the Silergy SQ24860 eFuse.
>
> The driver reports input voltage, output voltage, auxiliary voltage,
> input current, input power, and temperature. It also exposes peak,
> average, and minimum history attributes, sample count configuration,
> and maps the manufacturer-specific VIREF register to the generic input
> over-current fault limit attribute.
>
> The IMON resistor value is read from the silergy,rimon-micro-ohms device
> property and used to configure the input current calibration gain.
>
> Signed-off-by: Ziming Zhu <ziming.zhu@silergycorp.com>
checkpatch --strict says:
total: 0 errors, 3 warnings, 6 checks, 464 lines checked
The MAINTAINERS and the DT warning can be ignored, but I expect the rest
to be fixed.
> ---
> drivers/hwmon/pmbus/Kconfig | 19 ++
> drivers/hwmon/pmbus/Makefile | 1 +
> drivers/hwmon/pmbus/sq24860.c | 432 ++++++++++++++++++++++++++++++++++
> 3 files changed, 452 insertions(+)
> create mode 100644 drivers/hwmon/pmbus/sq24860.c
>
> diff --git a/drivers/hwmon/pmbus/Kconfig b/drivers/hwmon/pmbus/Kconfig
> index 8f4bff375ecb..a905b5af137c 100644
> --- a/drivers/hwmon/pmbus/Kconfig
> +++ b/drivers/hwmon/pmbus/Kconfig
> @@ -612,6 +612,25 @@ config SENSORS_STEF48H28
> This driver can also be built as a module. If so, the module will
> be called stef48h28.
>
> +config SENSORS_SQ24860
> + tristate "Silergy SQ24860"
> + help
> + If you say yes here you get hardware monitoring support for Silergy
> + SQ24860 eFuse.
> +
> + This driver can also be built as a module. If so, the module will
> + be called sq24860.
> +
> +config SENSORS_SQ24860_REGULATOR
> + bool "Regulator support for SQ24860"
> + depends on SENSORS_SQ24860 && REGULATOR
> + default SENSORS_SQ24860
> + help
> + If you say yes here you get regulator support for Silergy SQ24860.
> + The regulator is registered through the PMBus regulator framework and
> + can be used to control the output exposed by the device.
> + This option is only useful if regulator framework support is needed.
> +
> config SENSORS_STPDDC60
> tristate "ST STPDDC60"
> help
> diff --git a/drivers/hwmon/pmbus/Makefile b/drivers/hwmon/pmbus/Makefile
> index 7129b62bc00f..86bc93c6c091 100644
> --- a/drivers/hwmon/pmbus/Makefile
> +++ b/drivers/hwmon/pmbus/Makefile
> @@ -60,6 +60,7 @@ obj-$(CONFIG_SENSORS_PM6764TR) += pm6764tr.o
> obj-$(CONFIG_SENSORS_PXE1610) += pxe1610.o
> obj-$(CONFIG_SENSORS_Q54SJ108A2) += q54sj108a2.o
> obj-$(CONFIG_SENSORS_STEF48H28) += stef48h28.o
> +obj-$(CONFIG_SENSORS_SQ24860) += sq24860.o
> obj-$(CONFIG_SENSORS_STPDDC60) += stpddc60.o
> obj-$(CONFIG_SENSORS_TDA38640) += tda38640.o
> obj-$(CONFIG_SENSORS_TPS25990) += tps25990.o
> diff --git a/drivers/hwmon/pmbus/sq24860.c b/drivers/hwmon/pmbus/sq24860.c
> new file mode 100644
> index 000000000000..43a2cb542169
> --- /dev/null
> +++ b/drivers/hwmon/pmbus/sq24860.c
> @@ -0,0 +1,432 @@
> +// SPDX-License-Identifier: GPL-2.0
> +//
> +// Copyright (c) 2024.
> +// Author: Ziming Zhu <ziming.zhu@silergycorp.com>
Please do not mix C++ and C comments. Yes, I understand that the first
line must be a C++ comment. The rest of the driver must use a consistent
comment style.
> +#include <linux/bitfield.h>
> +#include <linux/debugfs.h>
I do not see where this include file is used.
> +#include <linux/err.h>
> +#include <linux/hwmon-sysfs.h>
I do not see where this include file is used.
> +#include <linux/i2c.h>
> +#include <linux/init.h>
> +#include <linux/kernel.h>
> +#include <linux/module.h>
> +
> +#include "pmbus.h"
> +
> +#define SQ24860_IIN_CAL_GAIN 0x38
> +#define SQ24860_READ_VAUX 0xd0
> +#define SQ24860_READ_VIN_MIN 0xd1
> +#define SQ24860_READ_VIN_PEAK 0xd2
> +#define SQ24860_READ_IIN_PEAK 0xd4
> +#define SQ24860_READ_PIN_PEAK 0xd5
> +#define SQ24860_READ_TEMP_AVG 0xd6
> +#define SQ24860_READ_TEMP_PEAK 0xd7
> +#define SQ24860_READ_VOUT_MIN 0xda
> +#define SQ24860_READ_VIN_AVG 0xdc
> +#define SQ24860_READ_VOUT_AVG 0xdd
> +#define SQ24860_READ_IIN_AVG 0xde
> +#define SQ24860_READ_PIN_AVG 0xdf
> +#define SQ24860_VIREF 0xe0
> +#define SQ24860_PK_MIN_AVG 0xea
> +#define PK_MIN_AVG_RST_PEAK BIT(7)
> +#define PK_MIN_AVG_RST_AVG BIT(6)
> +#define PK_MIN_AVG_RST_MIN BIT(5)
> +#define PK_MIN_AVG_AVG_CNT GENMASK(2, 0)
> +#define SQ24860_MFR_WRITE_PROTECT 0xf8
> +#define SQ24860_UNLOCKED BIT(7)
> +
> +#define SQ24860_8B_SHIFT 2
> +#define SQ24860_IIN_OCF_NUM 1000000
> +#define SQ24860_IIN_OCF_DIV 129278
> +#define SQ24860_IIN_OCF_OFF 165
> +
> +#define PK_MIN_AVG_RST_MASK (PK_MIN_AVG_RST_PEAK | \
> + PK_MIN_AVG_RST_AVG | \
> + PK_MIN_AVG_RST_MIN)
> +#define SQ24860_MAX_SAMPLES BIT(FIELD_MAX(PK_MIN_AVG_AVG_CNT))
> +/*
> + * Arbitrary default Rimon value: 1.6kOhm
> + */
> +#define SQ24860_DEFAULT_RIMON 1600000000
> +#define SQ24860_DEFAULT_GIMON 18180
> +
> +#define SQ24860_VAUX_DIV 20
> +
> +static int sq24860_write_iin_cal_gain(struct i2c_client *client, u32 rimon,
> + u32 gimon)
> +{
> + u64 temp = (u64)6400 * 1000000000 * 1000;
> + u64 denom;
> + u64 word;
> +
> + if (!rimon || !gimon)
> + return -EINVAL;
> +
> + denom = (u64)rimon * gimon;
> + word = div_u64(temp, denom);
> + if (word > U16_MAX)
> + return -ERANGE;
This is not "Math result not representable". Return -EINVAL.
Also, please make sure to fix the problem reported by Sashiko, or explain
why it does not apply.
> +
> + return i2c_smbus_write_word_data(client, SQ24860_IIN_CAL_GAIN,
> + (u16)word);
> +}
> +
> +static int sq24860_mfr_write_protect_set(struct i2c_client *client,
> + u8 protect)
> +{
> + u8 val;
> +
> + switch (protect) {
> + case 0:
> + val = 0xa2;
> + break;
> + case PB_WP_ALL:
> + val = 0x0;
> + break;
> + default:
> + return -EINVAL;
> + }
> +
> + return pmbus_write_byte_data(client, -1, SQ24860_MFR_WRITE_PROTECT,
> + val);
> +}
> +
> +static int sq24860_mfr_write_protect_get(struct i2c_client *client)
> +{
> + int ret = pmbus_read_byte_data(client, -1, SQ24860_MFR_WRITE_PROTECT);
> +
> + if (ret < 0)
> + return ret;
> +
> + return (ret & SQ24860_UNLOCKED) ? 0 : PB_WP_ALL;
> +}
> +
> +static int sq24860_read_word_data(struct i2c_client *client,
> + int page, int phase, int reg)
> +{
> + int ret;
> +
> + switch (reg) {
> + case PMBUS_VIRT_READ_VIN_MAX:
> + ret = pmbus_read_word_data(client, page, phase,
> + SQ24860_READ_VIN_PEAK);
> + break;
> +
> + case PMBUS_VIRT_READ_VIN_MIN:
> + ret = pmbus_read_word_data(client, page, phase,
> + SQ24860_READ_VIN_MIN);
> + break;
> +
> + case PMBUS_VIRT_READ_VIN_AVG:
> + ret = pmbus_read_word_data(client, page, phase,
> + SQ24860_READ_VIN_AVG);
> + break;
> +
> + case PMBUS_VIRT_READ_VOUT_MIN:
> + ret = pmbus_read_word_data(client, page, phase,
> + SQ24860_READ_VOUT_MIN);
> + break;
> +
> + case PMBUS_VIRT_READ_VOUT_AVG:
> + ret = pmbus_read_word_data(client, page, phase,
> + SQ24860_READ_VOUT_AVG);
> + break;
> +
> + case PMBUS_VIRT_READ_IIN_AVG:
> + ret = pmbus_read_word_data(client, page, phase,
> + SQ24860_READ_IIN_AVG);
> + break;
> +
> + case PMBUS_VIRT_READ_IIN_MAX:
> + ret = pmbus_read_word_data(client, page, phase,
> + SQ24860_READ_IIN_PEAK);
> + break;
> +
> + case PMBUS_VIRT_READ_TEMP_AVG:
> + ret = pmbus_read_word_data(client, page, phase,
> + SQ24860_READ_TEMP_AVG);
> + break;
> +
> + case PMBUS_VIRT_READ_TEMP_MAX:
> + ret = pmbus_read_word_data(client, page, phase,
> + SQ24860_READ_TEMP_PEAK);
> + break;
> +
> + case PMBUS_VIRT_READ_PIN_AVG:
> + ret = pmbus_read_word_data(client, page, phase,
> + SQ24860_READ_PIN_AVG);
> + break;
> +
> + case PMBUS_VIRT_READ_PIN_MAX:
> + ret = pmbus_read_word_data(client, page, phase,
> + SQ24860_READ_PIN_PEAK);
> + break;
> +
> + case PMBUS_VIRT_READ_VMON:
> + ret = pmbus_read_word_data(client, page, phase,
> + SQ24860_READ_VAUX);
> + if (ret < 0)
> + break;
> + ret = DIV_ROUND_CLOSEST(ret, SQ24860_VAUX_DIV);
> + break;
> +
> + case PMBUS_VIN_UV_WARN_LIMIT:
> + case PMBUS_VIN_UV_FAULT_LIMIT:
> + case PMBUS_VIN_OV_WARN_LIMIT:
> + case PMBUS_VIN_OV_FAULT_LIMIT:
> + case PMBUS_VOUT_UV_WARN_LIMIT:
> + case PMBUS_IIN_OC_WARN_LIMIT:
> + case PMBUS_OT_WARN_LIMIT:
> + case PMBUS_OT_FAULT_LIMIT:
> + case PMBUS_PIN_OP_WARN_LIMIT:
> + /*
> + * These registers provide an 8 bits value instead of a
> + * 10bits one. Just shifting twice the register value is
> + * enough to make the sensor type conversion work, even
> + * if the datasheet provides different m, b and R for
> + * those.
> + */
> + ret = pmbus_read_word_data(client, page, phase, reg);
> + if (ret < 0)
> + break;
> + ret <<= SQ24860_8B_SHIFT;
> + break;
> +
> + case PMBUS_IIN_OC_FAULT_LIMIT:
> + /*
> + * VIREF directly sets the over-current limit at which the eFuse
> + * will turn the FET off and trigger a fault. Expose it through
> + * this generic property instead of a manufacturer specific one.
> + */
> + ret = pmbus_read_byte_data(client, page, SQ24860_VIREF);
> + if (ret < 0)
> + break;
> + ret = DIV_ROUND_CLOSEST(ret * SQ24860_IIN_OCF_NUM,
> + SQ24860_IIN_OCF_DIV);
> + ret += SQ24860_IIN_OCF_OFF;
> + break;
> +
> + case PMBUS_VIRT_SAMPLES:
> + ret = pmbus_read_byte_data(client, page, SQ24860_PK_MIN_AVG);
> + if (ret < 0)
> + break;
> + ret = BIT(FIELD_GET(PK_MIN_AVG_AVG_CNT, ret));
> + break;
> +
> + case PMBUS_VIRT_RESET_TEMP_HISTORY:
> + case PMBUS_VIRT_RESET_VIN_HISTORY:
> + case PMBUS_VIRT_RESET_IIN_HISTORY:
> + case PMBUS_VIRT_RESET_PIN_HISTORY:
> + case PMBUS_VIRT_RESET_VOUT_HISTORY:
> + ret = 0;
> + break;
> +
> + default:
> + ret = -ENODATA;
> + break;
> + }
> +
> + return ret;
> +}
> +
> +static int sq24860_write_word_data(struct i2c_client *client,
> + int page, int reg, u16 value)
> +{
> + int ret;
> +
> + switch (reg) {
> + case PMBUS_VIN_UV_WARN_LIMIT:
> + case PMBUS_VIN_UV_FAULT_LIMIT:
> + case PMBUS_VIN_OV_WARN_LIMIT:
> + case PMBUS_VIN_OV_FAULT_LIMIT:
> + case PMBUS_VOUT_UV_WARN_LIMIT:
> + case PMBUS_IIN_OC_WARN_LIMIT:
> + case PMBUS_OT_WARN_LIMIT:
> + case PMBUS_OT_FAULT_LIMIT:
> + case PMBUS_PIN_OP_WARN_LIMIT:
> + value >>= SQ24860_8B_SHIFT;
> + value = clamp_val(value, 0, 0xff);
> + ret = pmbus_write_word_data(client, page, reg, value);
> + break;
> +
> + case PMBUS_IIN_OC_FAULT_LIMIT:
> + value -= SQ24860_IIN_OCF_OFF;
What if value is < SQ24860_IIN_OCF_OFF ?
(also reported by Sashiko)
> + value = DIV_ROUND_CLOSEST(((unsigned int)value) * SQ24860_IIN_OCF_DIV,
> + SQ24860_IIN_OCF_NUM);
> + value = clamp_val(value, 0, 0x3f);
> + ret = pmbus_write_byte_data(client, page, SQ24860_VIREF, value);
> + break;
> +
> + case PMBUS_VIRT_SAMPLES:
> + value = clamp_val(value, 1, SQ24860_MAX_SAMPLES);
> + value = ilog2(value);
> + ret = pmbus_update_byte_data(client, page, SQ24860_PK_MIN_AVG,
> + PK_MIN_AVG_AVG_CNT,
> + FIELD_PREP(PK_MIN_AVG_AVG_CNT, value));
> + break;
> +
> + case PMBUS_VIRT_RESET_TEMP_HISTORY:
> + case PMBUS_VIRT_RESET_VIN_HISTORY:
> + case PMBUS_VIRT_RESET_IIN_HISTORY:
> + case PMBUS_VIRT_RESET_PIN_HISTORY:
> + case PMBUS_VIRT_RESET_VOUT_HISTORY:
> + /*
> + * SQ24860 has history resets based on MIN/AVG/PEAK instead of per
> + * sensor type. Exposing this quirk in hwmon is not desirable so
> + * reset MIN, AVG and PEAK together. Even is there effectively only
> + * one reset, which resets everything, expose the 5 entries so
> + * userspace is not required map a sensor type to another to trigger
> + * a reset
> + */
> + ret = pmbus_update_byte_data(client, 0, SQ24860_PK_MIN_AVG,
> + PK_MIN_AVG_RST_MASK,
> + PK_MIN_AVG_RST_MASK);
> + break;
> +
> + default:
> + ret = -ENODATA;
> + break;
> + }
> +
> + return ret;
> +}
> +
> +static int sq24860_read_byte_data(struct i2c_client *client,
> + int page, int reg)
> +{
> + int ret;
> +
> + switch (reg) {
> + case PMBUS_WRITE_PROTECT:
> + ret = sq24860_mfr_write_protect_get(client);
> + break;
> +
> + default:
> + ret = -ENODATA;
> + break;
> + }
> +
> + return ret;
> +}
> +
> +static int sq24860_write_byte_data(struct i2c_client *client,
> + int page, int reg, u8 byte)
> +{
> + int ret;
> +
> + switch (reg) {
> + case PMBUS_WRITE_PROTECT:
> + ret = sq24860_mfr_write_protect_set(client, byte);
> + break;
> +
> + default:
> + ret = -ENODATA;
> + break;
> + }
> +
> + return ret;
> +}
> +
> +#if IS_ENABLED(CONFIG_SENSORS_SQ24860_REGULATOR)
> +static const struct regulator_desc sq24860_reg_desc[] = {
> + PMBUS_REGULATOR_ONE_NODE("vout"),
> +};
> +#endif
> +
> +static const struct pmbus_driver_info sq24860_base_info = {
> + .pages = 1,
> + .format[PSC_VOLTAGE_IN] = direct,
> + .m[PSC_VOLTAGE_IN] = 64,
> + .b[PSC_VOLTAGE_IN] = 0,
> + .R[PSC_VOLTAGE_IN] = 0,
> + .format[PSC_VOLTAGE_OUT] = direct,
> + .m[PSC_VOLTAGE_OUT] = 64,
> + .b[PSC_VOLTAGE_OUT] = 0,
> + .R[PSC_VOLTAGE_OUT] = 0,
> + .format[PSC_TEMPERATURE] = direct,
> + .m[PSC_TEMPERATURE] = 1,
> + .b[PSC_TEMPERATURE] = 0,
> + .R[PSC_TEMPERATURE] = 0,
> + /*
> + * Current and power measurements depend on the calibration gain
> + * programmed from the board-specific IMON resistor value.
> + */
Comment alignment is off (see checkpatch results).
> + .format[PSC_CURRENT_IN] = direct,
> + .m[PSC_CURRENT_IN] = 16,
> + .b[PSC_CURRENT_IN] = 0,
> + .R[PSC_CURRENT_IN] = 0,
> + .format[PSC_POWER] = direct,
> + .m[PSC_POWER] = 2,
> + .b[PSC_POWER] = 0,
> + .R[PSC_POWER] = 0,
> + .func[0] = (PMBUS_HAVE_VIN |
> + PMBUS_HAVE_VOUT |
> + PMBUS_HAVE_VMON |
> + PMBUS_HAVE_IIN |
> + PMBUS_HAVE_PIN |
> + PMBUS_HAVE_TEMP |
> + PMBUS_HAVE_STATUS_VOUT |
> + PMBUS_HAVE_STATUS_IOUT |
> + PMBUS_HAVE_STATUS_INPUT |
> + PMBUS_HAVE_STATUS_TEMP |
> + PMBUS_HAVE_SAMPLES),
Unnecessary ( ).
> + .read_word_data = sq24860_read_word_data,
> + .write_word_data = sq24860_write_word_data,
> + .read_byte_data = sq24860_read_byte_data,
> + .write_byte_data = sq24860_write_byte_data,
> +
> +#if IS_ENABLED(CONFIG_SENSORS_SQ24860_REGULATOR)
> + .reg_desc = sq24860_reg_desc,
> + .num_regulators = ARRAY_SIZE(sq24860_reg_desc),
> +#endif
> +};
> +
> +static const struct i2c_device_id sq24860_i2c_id[] = {
> + { "sq24860" },
> + {}
> +};
> +MODULE_DEVICE_TABLE(i2c, sq24860_i2c_id);
> +
> +static const struct of_device_id sq24860_of_match[] = {
> + { .compatible = "silergy,sq24860" },
> + {}
> +};
> +MODULE_DEVICE_TABLE(of, sq24860_of_match);
> +
> +static int sq24860_probe(struct i2c_client *client)
> +{
> + struct device *dev = &client->dev;
> + struct pmbus_driver_info *info;
> + u32 rimon = SQ24860_DEFAULT_RIMON;
> + u32 gimon = SQ24860_DEFAULT_GIMON;
gimon is a constant. Why pass it as parameter to sq24860_write_iin_cal_gain(),
and why validate it there instead of just using a constant ?
> + int ret;
> +
> + ret = device_property_read_u32(dev, "silergy,rimon-micro-ohms", &rimon);
> + if (ret < 0 && ret != -EINVAL)
> + return dev_err_probe(dev, ret, "failed to get rimon\n");
I am a bit lost here. Why accept -EINVAL (invalid arguments) ?
> +
> + ret = sq24860_write_iin_cal_gain(client, rimon, gimon);
> + if (ret < 0)
> + return dev_err_probe(&client->dev, ret,
> + "Failed to set gain\n");
> + info = devm_kmemdup(dev, &sq24860_base_info, sizeof(*info), GFP_KERNEL);
> + if (!info)
> + return -ENOMEM;
> +
> + return pmbus_do_probe(client, info);
> +}
> +
> +static struct i2c_driver sq24860_driver = {
> + .driver = {
> + .name = "sq24860",
> + .of_match_table = sq24860_of_match,
> + },
> + .probe = sq24860_probe,
> + .id_table = sq24860_i2c_id,
> +};
> +module_i2c_driver(sq24860_driver);
> +
> +MODULE_AUTHOR("Ziming Zhu <ziming.zhu@silergycorp.com>");
> +MODULE_DESCRIPTION("PMBUS driver for SQ24860 eFuse");
> +MODULE_LICENSE("GPL");
> +MODULE_IMPORT_NS("PMBUS");
^ permalink raw reply
* Re: [PATCH v3 3/6] alloc_tag: add size-based filtering to ioctl
From: Hao Ge @ 2026-06-08 4:09 UTC (permalink / raw)
To: Abhishek Bapat, Suren Baghdasaryan, Andrew Morton,
Kent Overstreet
Cc: Shuah Khan, Jonathan Corbet, linux-doc, linux-kernel, linux-mm,
Sourav Panda
In-Reply-To: <ef88e52368463e312086a966f10287a29d0edeca.1780701922.git.abhishekbapat@google.com>
Hi Abhishek
Thanks for the new version.
On 2026/6/6 07:36, Abhishek Bapat wrote:
> Extend the allocinfo filtering mechanism to allow users to filter tags
> based on the total number of bytes allocated [min_size, max_size]. The
> size range is inclusive.
>
> Filtering by size involves retrieving allocinfo per-CPU counters, which
> is an expensive operation. Hence, the performance of size-based
> filtering will be worse than other filters.
>
> Signed-off-by: Abhishek Bapat <abhishekbapat@google.com>
> ---
> include/uapi/linux/alloc_tag.h | 8 +++-
> lib/alloc_tag.c | 68 +++++++++++++++++++++++++++-------
> 2 files changed, 62 insertions(+), 14 deletions(-)
>
> diff --git a/include/uapi/linux/alloc_tag.h b/include/uapi/linux/alloc_tag.h
> index cffb0c46e0b1..0e648192df4d 100644
> --- a/include/uapi/linux/alloc_tag.h
> +++ b/include/uapi/linux/alloc_tag.h
> @@ -39,13 +39,17 @@ enum {
> ALLOCINFO_FILTER_FUNCTION,
> ALLOCINFO_FILTER_FILENAME,
> ALLOCINFO_FILTER_LINENO,
> - __ALLOCINFO_FILTER_LAST = ALLOCINFO_FILTER_LINENO
> + ALLOCINFO_FILTER_MIN_SIZE,
> + ALLOCINFO_FILTER_MAX_SIZE,
> + __ALLOCINFO_FILTER_LAST = ALLOCINFO_FILTER_MAX_SIZE
> };
>
> #define ALLOCINFO_FILTER_MASK_MODNAME (1 << ALLOCINFO_FILTER_MODNAME)
> #define ALLOCINFO_FILTER_MASK_FUNCTION (1 << ALLOCINFO_FILTER_FUNCTION)
> #define ALLOCINFO_FILTER_MASK_FILENAME (1 << ALLOCINFO_FILTER_FILENAME)
> #define ALLOCINFO_FILTER_MASK_LINENO (1 << ALLOCINFO_FILTER_LINENO)
> +#define ALLOCINFO_FILTER_MASK_MIN_SIZE (1 << ALLOCINFO_FILTER_MIN_SIZE)
> +#define ALLOCINFO_FILTER_MASK_MAX_SIZE (1 << ALLOCINFO_FILTER_MAX_SIZE)
>
> #define ALLOCINFO_FILTER_MASKS \
> ((1 << (__ALLOCINFO_FILTER_LAST + 1)) - 1)
> @@ -53,6 +57,8 @@ enum {
> struct allocinfo_filter {
> __u64 mask; /* bitmask of the filter fields used */
> struct allocinfo_tag fields;
> + __u64 min_size;
> + __u64 max_size;
> };
>
> struct allocinfo_get_at {
> diff --git a/lib/alloc_tag.c b/lib/alloc_tag.c
> index 93bc976ac505..ddc6946f56ab 100644
> --- a/lib/alloc_tag.c
> +++ b/lib/alloc_tag.c
> @@ -191,15 +191,26 @@ static int allocinfo_cmp_str(const char *str, const char *template)
> return strncmp(allocinfo_str(str), template, ALLOCINFO_STR_SIZE);
> }
>
> +/* Fetch the per-CPU counters */
> +static inline struct alloc_tag_counters allocinfo_prefetch_counters(struct codetag *ct)
> +{
> + return alloc_tag_read(ct_to_alloc_tag(ct));
> +}
> +
> /*
> * Populates the UAPI allocinfo_tag_data structure with active runtime
> * profiling counters extracted from the given kernel codetag.
> */
> static void allocinfo_to_params(struct codetag *ct,
> - struct allocinfo_tag_data *data)
> + struct allocinfo_tag_data *data,
> + struct alloc_tag_counters *counters)
> {
> - struct alloc_tag *tag = ct_to_alloc_tag(ct);
> - struct alloc_tag_counters counter = alloc_tag_read(tag);
> + struct alloc_tag_counters local_counters;
> +
> + if (!counters) {
> + local_counters = allocinfo_prefetch_counters(ct);
> + counters = &local_counters;
> + }
>
> if (ct->modname)
> allocinfo_copy_str(data->tag.modname, ct->modname);
> @@ -208,9 +219,9 @@ static void allocinfo_to_params(struct codetag *ct,
> allocinfo_copy_str(data->tag.function, ct->function);
> allocinfo_copy_str(data->tag.filename, ct->filename);
> data->tag.lineno = ct->lineno;
> - data->counter.bytes = counter.bytes;
> - data->counter.calls = counter.calls;
> - data->counter.accurate = !alloc_tag_is_inaccurate(tag);
> + data->counter.bytes = counters->bytes;
> + data->counter.calls = counters->calls;
> + data->counter.accurate = !alloc_tag_is_inaccurate(ct_to_alloc_tag(ct));
> }
>
> /*
> @@ -234,7 +245,9 @@ static int allocinfo_ioctl_get_content_id(struct seq_file *m, void __user *arg)
> * Verifies whether a given codetag satisfies the active filtering criteria by
> * matching it's characteristics against the specified filter.
> */
> -static bool matches_filter(struct codetag *ct, struct allocinfo_filter *filter)
> +static bool matches_filter(struct codetag *ct, struct allocinfo_filter *filter,
> + struct alloc_tag_counters *counters,
> + bool *fetched_counters)
> {
> if (!filter || !filter->mask)
> return true;
> @@ -247,20 +260,34 @@ static bool matches_filter(struct codetag *ct, struct allocinfo_filter *filter)
> return false;
> } else if (allocinfo_cmp_str(ct->modname, filter->fields.modname))
> return false;
> + }
It seems an extra } was accidentally added here
> }
>
> if ((filter->mask & ALLOCINFO_FILTER_MASK_FUNCTION) &&
> - ct->function && (allocinfo_cmp_str(ct->function, filter->fields.function)))
> + ct->function && allocinfo_cmp_str(ct->function, filter->fields.function))
> return false;
>
This should be fixed in the second patch; it's unrelated to current
functionality.
> if ((filter->mask & ALLOCINFO_FILTER_MASK_FILENAME) &&
> - ct->filename && (allocinfo_cmp_str(ct->filename, filter->fields.filename)))
> + ct->filename && allocinfo_cmp_str(ct->filename, filter->fields.filename))
> return false;
Ditto
Thanks
Best Regards
Hao
> if ((filter->mask & ALLOCINFO_FILTER_MASK_LINENO) &&
> ct->lineno != filter->fields.lineno)
> return false;
>
> + if (filter->mask & (ALLOCINFO_FILTER_MASK_MIN_SIZE | ALLOCINFO_FILTER_MASK_MAX_SIZE)) {
> + if (!*fetched_counters) {
> + *counters = allocinfo_prefetch_counters(ct);
> + *fetched_counters = true;
> + }
> + if ((filter->mask & ALLOCINFO_FILTER_MASK_MIN_SIZE) &&
> + counters->bytes < filter->min_size)
> + return false;
> + if ((filter->mask & ALLOCINFO_FILTER_MASK_MAX_SIZE) &&
> + counters->bytes > filter->max_size)
> + return false;
> + }
> +
> return true;
> }
>
> @@ -274,6 +301,8 @@ static int allocinfo_ioctl_get_at(struct seq_file *m, void __user *arg)
> struct codetag *ct;
> struct allocinfo_get_at params = {0};
> __u64 skip_count;
> + struct alloc_tag_counters counters;
> + bool fetched_counters;
>
> if (copy_from_user(¶ms, arg, sizeof(params)))
> return -EFAULT;
> @@ -281,6 +310,11 @@ static int allocinfo_ioctl_get_at(struct seq_file *m, void __user *arg)
> if (params.filter.mask & ~ALLOCINFO_FILTER_MASKS)
> return -EINVAL;
>
> + if ((params.filter.mask & ALLOCINFO_FILTER_MASK_MIN_SIZE) &&
> + (params.filter.mask & ALLOCINFO_FILTER_MASK_MAX_SIZE) &&
> + params.filter.min_size > params.filter.max_size)
> + return -EINVAL;
> +
> priv = m->private;
>
> mutex_lock(&priv->ioctl_lock);
> @@ -304,7 +338,8 @@ static int allocinfo_ioctl_get_at(struct seq_file *m, void __user *arg)
> ct = codetag_next_ct(&priv->ioctl_iter);
>
> while (ct) {
> - if (matches_filter(ct, &priv->filter)) {
> + fetched_counters = false;
> + if (matches_filter(ct, &priv->filter, &counters, &fetched_counters)) {
> if (skip_count == 0)
> break;
> skip_count--;
> @@ -313,7 +348,7 @@ static int allocinfo_ioctl_get_at(struct seq_file *m, void __user *arg)
> }
>
> if (ct) {
> - allocinfo_to_params(ct, ¶ms.data);
> + allocinfo_to_params(ct, ¶ms.data, fetched_counters ? &counters : NULL);
> priv->positioned = true;
> }
>
> @@ -339,6 +374,8 @@ static int allocinfo_ioctl_get_next(struct seq_file *m, void __user *arg)
> struct codetag *ct;
> struct allocinfo_tag_data params;
> int ret = 0;
> + struct alloc_tag_counters counters;
> + bool fetched_counters;
>
> memset(¶ms, 0, sizeof(params));
> priv = m->private;
> @@ -352,10 +389,15 @@ static int allocinfo_ioctl_get_next(struct seq_file *m, void __user *arg)
> }
>
> ct = codetag_next_ct(&priv->ioctl_iter);
> - while (ct && !matches_filter(ct, &priv->filter))
> + while (ct) {
> + fetched_counters = false;
> + if (matches_filter(ct, &priv->filter, &counters, &fetched_counters))
> + break;
> ct = codetag_next_ct(&priv->ioctl_iter);
> + }
> +
> if (ct)
> - allocinfo_to_params(ct, ¶ms);
> + allocinfo_to_params(ct, ¶ms, fetched_counters ? &counters : NULL);
>
> if (!ct) {
> priv->positioned = false;
^ permalink raw reply
* Re: [PATCH mm-unstable v19 05/14] mm/khugepaged: require collapse_huge_page to enter/exit with the lock dropped
From: Lance Yang @ 2026-06-08 4:34 UTC (permalink / raw)
To: npache
Cc: linux-doc, linux-kernel, linux-mm, linux-trace-kernel, aarcange,
akpm, anshuman.khandual, apopple, baohua, baolin.wang, byungchul,
catalin.marinas, cl, corbet, dave.hansen, david, dev.jain, gourry,
hannes, hughd, jack, jackmanb, jannh, jglisse, joshua.hahnjy, kas,
lance.yang, liam, ljs, mathieu.desnoyers, matthew.brost, mhiramat,
mhocko, peterx, pfalcato, rakie.kim, raquini, rdunlap,
richard.weiyang, rientjes, rostedt, rppt, ryan.roberts, shivankg,
sunnanyong, surenb, thomas.hellstrom, tiwai, usamaarif642, vbabka,
vishal.moola, wangkefeng.wang, will, willy, yang, ying.huang, ziy,
zokeefe
In-Reply-To: <20260605161422.213817-6-npache@redhat.com>
On Fri, Jun 05, 2026 at 10:14:12AM -0600, Nico Pache wrote:
>Currently the collapse_huge_page function requires the mmap_read_lock to
>enter with it held, and exit with it dropped. This function moves the
>unlock into its parent caller, and changes this semantic to requiring it
>to enter/exit with it always unlocked.
>
>In future patches, we need this expectation, as for in mTHP collapse, we
>may have already dropped the lock, and do not want to conditionally
>check for this by passing through the lock_dropped variable.
>
>No functional change is expected as one of the first things the
>collapse_huge_page function does is drop this lock before allocating the
>hugepage.
>
>Reviewed-by: Lorenzo Stoakes <ljs@kernel.org>
>Acked-by: David Hildenbrand (Arm) <david@kernel.org>
>Signed-off-by: Nico Pache <npache@redhat.com>
>---
Reviewed-by: Lance Yang <lance.yang@linux.dev>
^ permalink raw reply
* Re: [PATCH mm-unstable v19 06/14] mm/khugepaged: generalize collapse_huge_page for mTHP collapse
From: Lance Yang @ 2026-06-08 4:54 UTC (permalink / raw)
To: npache
Cc: linux-doc, linux-kernel, linux-mm, linux-trace-kernel, aarcange,
akpm, anshuman.khandual, apopple, baohua, baolin.wang, byungchul,
catalin.marinas, cl, corbet, dave.hansen, david, dev.jain, gourry,
hannes, hughd, jack, jackmanb, jannh, jglisse, joshua.hahnjy, kas,
lance.yang, liam, ljs, mathieu.desnoyers, matthew.brost, mhiramat,
mhocko, peterx, pfalcato, rakie.kim, raquini, rdunlap,
richard.weiyang, rientjes, rostedt, rppt, ryan.roberts, shivankg,
sunnanyong, surenb, thomas.hellstrom, tiwai, usamaarif642, vbabka,
vishal.moola, wangkefeng.wang, will, willy, yang, ying.huang, ziy,
zokeefe
In-Reply-To: <20260605161422.213817-7-npache@redhat.com>
On Fri, Jun 05, 2026 at 10:14:13AM -0600, Nico Pache wrote:
>Pass an order to collapse_huge_page to support collapsing anon memory to
>arbitrary orders within a PMD. order indicates what mTHP size we are
>attempting to collapse to.
>
>For non-PMD collapse we must leave the anon VMA write locked until after
>we collapse the mTHP-- in the PMD case all the pages are isolated, but in
>the mTHP case this is not true, and we must keep the lock to prevent
>access/changes to the page tables. This can happen if the rmap walkers hit
>a pmd_none while the PMD entry is currently unavailable due to being
>temporarily removed during the collapse phase.
>
>To properly establish the page table hierarchy without violating any
>expectations from certain architectures (e.g. MIPS), we must make sure to
>have the PMD reinstalled before the PTEs, and hold both PTE/PMD locks
>before calling update_mmu_cache_range() (if they are distinct locks).
>
>Signed-off-by: Nico Pache <npache@redhat.com>
>---
Nothing else jumped out at me. Anything left can be sorted out later, as
David and Lorenzo said :)
Reviewed-by: Lance Yang <lance.yang@linux.dev>
^ permalink raw reply
* Re: [PATCH 1/4] block: add a macro to initialize the status table
From: Christoph Hellwig @ 2026-06-08 5:09 UTC (permalink / raw)
To: Matthew Wilcox
Cc: Christoph Hellwig, Jens Axboe, Jonathan Corbet, linux-block,
linux-doc, Keith Busch
In-Reply-To: <aiMZ-PXXQ-NxOHT4@casper.infradead.org>
On Fri, Jun 05, 2026 at 07:48:24PM +0100, Matthew Wilcox wrote:
> On Fri, Jun 05, 2026 at 08:44:27PM +0200, Christoph Hellwig wrote:
> > Prepare for adding a new value to the error table by adding a macro
> > to fill it.
>
> > +#define ENT(_tag, _errno, _desc) \
> > +[BLK_STS_##_tag] = { \
> > + .errno = _errno, \
> > + .name = _desc, \
>
> Bleh. I hate this. Before, I can grep for BLK_STS_NOSPC and find it.
You will still find BLK_STS_NOSPC itself in include/linux/blk_types.h
> After, I can't. Yes, I know we have a lot of such things already, but
> I don't like adding more.
I'm not a huge fan off CPP pasting, and especially thing we should never
use it to define global symbols (hi page/folio flag helpers!), and in
general try to avoid using them as much as possible. But I think here
the need to keep the names in sync with the tags exposed in debugfs is
more important than the grepability. Especially as this sits in _the_
core block file, so it can't be easily missed.
^ permalink raw reply
* RE: [PATCH net-next v4 16/16] Documentation: networking: Add timestamp related APIs to OA TC6 framework
From: Selvamani Rajagopal @ 2026-06-08 5:10 UTC (permalink / raw)
To: Randy Dunlap, Andrew Lunn, Piergiorgio Beruto, Heiner Kallweit,
Russell King, David S. Miller, Eric Dumazet, Jakub Kicinski,
Paolo Abeni, Andrew Lunn, Parthiban Veerasooran, Richard Cochran,
Rob Herring, Krzysztof Kozlowski, Conor Dooley, Simon Horman,
Jonathan Corbet, Shuah Khan
Cc: netdev@vger.kernel.org, linux-kernel@vger.kernel.org,
devicetree@vger.kernel.org, linux-doc@vger.kernel.org, Jerry Ray
In-Reply-To: <CY8PR02MB9249DA24FC3E3292FC2D7628831F2@CY8PR02MB9249.namprd02.prod.outlook.com>
> Subject: RE: [PATCH net-next v4 16/16] Documentation: networking: Add timestamp
> related APIs to OA TC6 framework
>
> >
> > Hi,
> > These needs a few additional blank lines to avoid docs build warnings:
>
> Will do. My bad that I didn't verify with make htmldocs after editing the file.
>
> >
> > Documentation/networking/oa-tc6-framework.rst:554: WARNING: Explicit markup ends
> > without a blank line; unexpected unindent. [docutils]
> > Documentation/networking/oa-tc6-framework.rst:561: WARNING: Explicit markup ends
> > without a blank line; unexpected unindent. [docutils]
> > Documentation/networking/oa-tc6-framework.rst:566: WARNING: Explicit markup ends
> > without a blank line; unexpected unindent. [docutils]
> > Documentation/networking/oa-tc6-framework.rst:573: WARNING: Explicit markup ends
> > without a blank line; unexpected unindent. [docutils]
> >
Randy,
Though I fixed the issues you pointed out, I couldn't reproduce this issue with either "make htmldocs"
or with "sphinx-build" commands.
Am I missing something with respect to how document generation/verification is done?
> > See below.
> >
^ permalink raw reply
* configurable block error injection v3
From: Christoph Hellwig @ 2026-06-08 5:14 UTC (permalink / raw)
To: Jens Axboe
Cc: Jonathan Corbet, Damien Le Moal, Hannes Reinecke, Keith Busch,
linux-block, linux-doc
Hi all,
this series adds a new configurable block error injection facility.
We already have a few to inject block errors, but unfortunately most
of them are either not very useful or hard to use, or both:
- The fail_make_request failure injection point can't distinguish
different commands, different ranges in the file and can only injection
plain I/O errors.
- the should_fail_bio 'dynamic' failure injection has all the same issues
as fail_make_request
- dm-error can only fail all command in the table using BLK_STS_IOERR
and requires setting up a new block device
- dm-flakey and dm-dust allow all kinds of configurability, but still
don't have good error selection, no good support for non-read/write
commands and are limited to the dm table alignment requirements,
which for zoned devices enforces setting them up for an entire zone.
They also once again require setting up a stacked block device,
which is really annoying in harnesses like xfstests
This series adds a new debugfs-based block layer error injection
that allows to configure what operations and ranges the injection
applied to, and what status to return. It also allows to configure a
failure ratio similar to the xfs errortag injection.
Changes since v2:
- improve the documentation a bit
- fix a spelling mistake in a comment
Changes since v1:
- drop the should_fail_bio removal and cleanup depending on it, as it's
used by eBPF programs and thus a hidden UABI.
- as a result split the code out to it's own Kconfig symbol
- various error handling fixed pointed out by Keith
- documentation spelling fixes pointed out by Randy
Diffstat:
Documentation/block/error-injection.rst | 59 ++++++
Documentation/block/index.rst | 1
block/Kconfig | 7
block/Makefile | 1
block/blk-core.c | 86 ++++++--
block/blk-sysfs.c | 4
block/blk.h | 15 +
block/error-injection.c | 308 ++++++++++++++++++++++++++++++++
block/genhd.c | 4
include/linux/blkdev.h | 6
10 files changed, 471 insertions(+), 20 deletions(-)
^ permalink raw reply
* [PATCH 1/4] block: add a macro to initialize the status table
From: Christoph Hellwig @ 2026-06-08 5:14 UTC (permalink / raw)
To: Jens Axboe
Cc: Jonathan Corbet, Damien Le Moal, Hannes Reinecke, Keith Busch,
linux-block, linux-doc, Hannes Reinecke
In-Reply-To: <20260608051416.1205282-1-hch@lst.de>
Prepare for adding a new value to the error table by adding a macro
to fill it.
Signed-off-by: Christoph Hellwig <hch@lst.de>
Reviewed-by: Keith Busch <kbusch@kernel.org>
Reviewed-by: Damien Le Moal <dlemoal@kernel.org>
Reviewed-by: Hannes Reinecke <hare@kernel.org>
---
block/blk-core.c | 45 +++++++++++++++++++++++++--------------------
1 file changed, 25 insertions(+), 20 deletions(-)
diff --git a/block/blk-core.c b/block/blk-core.c
index b0f0a304ea0b..1614323282f1 100644
--- a/block/blk-core.c
+++ b/block/blk-core.c
@@ -132,39 +132,44 @@ inline const char *blk_op_str(enum req_op op)
}
EXPORT_SYMBOL_GPL(blk_op_str);
+#define ENT(_tag, _errno, _desc) \
+[BLK_STS_##_tag] = { \
+ .errno = _errno, \
+ .name = _desc, \
+}
static const struct {
int errno;
const char *name;
} blk_errors[] = {
- [BLK_STS_OK] = { 0, "" },
- [BLK_STS_NOTSUPP] = { -EOPNOTSUPP, "operation not supported" },
- [BLK_STS_TIMEOUT] = { -ETIMEDOUT, "timeout" },
- [BLK_STS_NOSPC] = { -ENOSPC, "critical space allocation" },
- [BLK_STS_TRANSPORT] = { -ENOLINK, "recoverable transport" },
- [BLK_STS_TARGET] = { -EREMOTEIO, "critical target" },
- [BLK_STS_RESV_CONFLICT] = { -EBADE, "reservation conflict" },
- [BLK_STS_MEDIUM] = { -ENODATA, "critical medium" },
- [BLK_STS_PROTECTION] = { -EILSEQ, "protection" },
- [BLK_STS_RESOURCE] = { -ENOMEM, "kernel resource" },
- [BLK_STS_DEV_RESOURCE] = { -EBUSY, "device resource" },
- [BLK_STS_AGAIN] = { -EAGAIN, "nonblocking retry" },
- [BLK_STS_OFFLINE] = { -ENODEV, "device offline" },
+ ENT(OK, 0, ""),
+ ENT(NOTSUPP, -EOPNOTSUPP, "operation not supported"),
+ ENT(TIMEOUT, -ETIMEDOUT, "timeout"),
+ ENT(NOSPC, -ENOSPC, "critical space allocation"),
+ ENT(TRANSPORT, -ENOLINK, "recoverable transport"),
+ ENT(TARGET, -EREMOTEIO, "critical target"),
+ ENT(RESV_CONFLICT, -EBADE, "reservation conflict"),
+ ENT(MEDIUM, -ENODATA, "critical medium"),
+ ENT(PROTECTION, -EILSEQ, "protection"),
+ ENT(RESOURCE, -ENOMEM, "kernel resource"),
+ ENT(DEV_RESOURCE, -EBUSY, "device resource"),
+ ENT(AGAIN, -EAGAIN, "nonblocking retry"),
+ ENT(OFFLINE, -ENODEV, "device offline"),
/* device mapper special case, should not leak out: */
- [BLK_STS_DM_REQUEUE] = { -EREMCHG, "dm internal retry" },
+ ENT(DM_REQUEUE, -EREMCHG, "dm internal retry"),
/* zone device specific errors */
- [BLK_STS_ZONE_OPEN_RESOURCE] = { -ETOOMANYREFS, "open zones exceeded" },
- [BLK_STS_ZONE_ACTIVE_RESOURCE] = { -EOVERFLOW, "active zones exceeded" },
+ ENT(ZONE_OPEN_RESOURCE, -ETOOMANYREFS, "open zones exceeded"),
+ ENT(ZONE_ACTIVE_RESOURCE, -EOVERFLOW, "active zones exceeded"),
/* Command duration limit device-side timeout */
- [BLK_STS_DURATION_LIMIT] = { -ETIME, "duration limit exceeded" },
-
- [BLK_STS_INVAL] = { -EINVAL, "invalid" },
+ ENT(DURATION_LIMIT, -ETIME, "duration limit exceeded"),
+ ENT(INVAL, -EINVAL, "invalid"),
/* everything else not covered above: */
- [BLK_STS_IOERR] = { -EIO, "I/O" },
+ ENT(IOERR, -EIO, "I/O"),
};
+#undef ENT
blk_status_t errno_to_blk_status(int errno)
{
--
2.53.0
^ permalink raw reply related
* [PATCH 2/4] block: add a "tag" for block status codes
From: Christoph Hellwig @ 2026-06-08 5:14 UTC (permalink / raw)
To: Jens Axboe
Cc: Jonathan Corbet, Damien Le Moal, Hannes Reinecke, Keith Busch,
linux-block, linux-doc, Hannes Reinecke
In-Reply-To: <20260608051416.1205282-1-hch@lst.de>
The full name of the status codes is not good for user interfaces as it
can contain white spaces. Add the name of the status code without the
BLK_STS_ prefix as a tag so that it can be used for user interfaces.
Signed-off-by: Christoph Hellwig <hch@lst.de>
Reviewed-by: Keith Busch <kbusch@kernel.org>
Reviewed-by: Damien Le Moal <dlemoal@kernel.org>
Reviewed-by: Hannes Reinecke <hare@kernel.org>
---
block/blk-core.c | 28 ++++++++++++++++++++++++++++
block/blk.h | 2 ++
2 files changed, 30 insertions(+)
diff --git a/block/blk-core.c b/block/blk-core.c
index 1614323282f1..7aa9cd110bdd 100644
--- a/block/blk-core.c
+++ b/block/blk-core.c
@@ -135,10 +135,12 @@ EXPORT_SYMBOL_GPL(blk_op_str);
#define ENT(_tag, _errno, _desc) \
[BLK_STS_##_tag] = { \
.errno = _errno, \
+ .tag = __stringify(_tag), \
.name = _desc, \
}
static const struct {
int errno;
+ const char *tag;
const char *name;
} blk_errors[] = {
ENT(OK, 0, ""),
@@ -203,6 +205,32 @@ const char *blk_status_to_str(blk_status_t status)
return blk_errors[idx].name;
}
+const char *blk_status_to_tag(blk_status_t status)
+{
+ int idx = (__force int)status;
+
+ if (WARN_ON_ONCE(idx >= ARRAY_SIZE(blk_errors)))
+ return "<null>";
+ return blk_errors[idx].tag;
+}
+
+blk_status_t tag_to_blk_status(const char *tag)
+{
+ int i;
+
+ for (i = 0; i < ARRAY_SIZE(blk_errors); i++) {
+ if (blk_errors[i].tag &&
+ !strcmp(blk_errors[i].tag, tag))
+ return (__force blk_status_t)i;
+ }
+
+ /*
+ * Return BLK_STS_OK for mismatches as this function is intended to
+ * parse error status values.
+ */
+ return BLK_STS_OK;
+}
+
/**
* blk_sync_queue - cancel any pending callbacks on a queue
* @q: the queue
diff --git a/block/blk.h b/block/blk.h
index 1a2d9101bba0..0eb8e932ec66 100644
--- a/block/blk.h
+++ b/block/blk.h
@@ -50,6 +50,8 @@ struct blk_flush_queue *blk_alloc_flush_queue(int node, int cmd_size,
void blk_free_flush_queue(struct blk_flush_queue *q);
const char *blk_status_to_str(blk_status_t status);
+const char *blk_status_to_tag(blk_status_t status);
+blk_status_t tag_to_blk_status(const char *tag);
bool __blk_mq_unfreeze_queue(struct request_queue *q, bool force_atomic);
bool blk_queue_start_drain(struct request_queue *q);
--
2.53.0
^ permalink raw reply related
* [PATCH 3/4] block: add a str_to_blk_op helper
From: Christoph Hellwig @ 2026-06-08 5:14 UTC (permalink / raw)
To: Jens Axboe
Cc: Jonathan Corbet, Damien Le Moal, Hannes Reinecke, Keith Busch,
linux-block, linux-doc, Hannes Reinecke
In-Reply-To: <20260608051416.1205282-1-hch@lst.de>
Add a helper to find the REQ_OP_XYZ constant from the "XYZ" string.
This will be used for the error injection debugfs interface.
Signed-off-by: Christoph Hellwig <hch@lst.de>
Reviewed-by: Keith Busch <kbusch@kernel.org>
Reviewed-by: Damien Le Moal <dlemoal@kernel.org>
Reviewed-by: Hannes Reinecke <hare@kernel.org>
---
block/blk-core.c | 10 ++++++++++
block/blk.h | 1 +
2 files changed, 11 insertions(+)
diff --git a/block/blk-core.c b/block/blk-core.c
index 7aa9cd110bdd..aa90aad6da13 100644
--- a/block/blk-core.c
+++ b/block/blk-core.c
@@ -132,6 +132,16 @@ inline const char *blk_op_str(enum req_op op)
}
EXPORT_SYMBOL_GPL(blk_op_str);
+enum req_op str_to_blk_op(const char *op)
+{
+ int i;
+
+ for (i = 0; i < ARRAY_SIZE(blk_op_name); i++)
+ if (blk_op_name[i] && !strcmp(blk_op_name[i], op))
+ return (enum req_op)i;
+ return REQ_OP_LAST;
+}
+
#define ENT(_tag, _errno, _desc) \
[BLK_STS_##_tag] = { \
.errno = _errno, \
diff --git a/block/blk.h b/block/blk.h
index 0eb8e932ec66..e8b7d5517086 100644
--- a/block/blk.h
+++ b/block/blk.h
@@ -52,6 +52,7 @@ void blk_free_flush_queue(struct blk_flush_queue *q);
const char *blk_status_to_str(blk_status_t status);
const char *blk_status_to_tag(blk_status_t status);
blk_status_t tag_to_blk_status(const char *tag);
+enum req_op str_to_blk_op(const char *op);
bool __blk_mq_unfreeze_queue(struct request_queue *q, bool force_atomic);
bool blk_queue_start_drain(struct request_queue *q);
--
2.53.0
^ permalink raw reply related
* [PATCH 4/4] block: add configurable error injection
From: Christoph Hellwig @ 2026-06-08 5:14 UTC (permalink / raw)
To: Jens Axboe
Cc: Jonathan Corbet, Damien Le Moal, Hannes Reinecke, Keith Busch,
linux-block, linux-doc, Hannes Reinecke
In-Reply-To: <20260608051416.1205282-1-hch@lst.de>
Add a new block error injection interface that allows to inject specific
status code for specific ranges.
Signed-off-by: Christoph Hellwig <hch@lst.de>
Reviewed-by: Damien Le Moal <dlemoal@kernel.org>
Reviewed-by: Hannes Reinecke <hare@kernel.org>
---
Documentation/block/error-injection.rst | 59 +++++
Documentation/block/index.rst | 1 +
block/Kconfig | 7 +
block/Makefile | 1 +
block/blk-core.c | 3 +
block/blk-sysfs.c | 4 +
block/blk.h | 12 +
block/error-injection.c | 308 ++++++++++++++++++++++++
block/genhd.c | 4 +
include/linux/blkdev.h | 6 +
10 files changed, 405 insertions(+)
create mode 100644 Documentation/block/error-injection.rst
create mode 100644 block/error-injection.c
diff --git a/Documentation/block/error-injection.rst b/Documentation/block/error-injection.rst
new file mode 100644
index 000000000000..a96b7af362c5
--- /dev/null
+++ b/Documentation/block/error-injection.rst
@@ -0,0 +1,59 @@
+.. SPDX-License-Identifier: GPL-2.0
+
+============================
+Configurable Error Injection
+============================
+
+Overview
+--------
+
+Configurable error injection allows injecting specific block layer status codes
+for ranges of a block device. Errors can be injected unconditionally, or with a
+given probability.
+
+To use configurable error injection, CONFIG_BLK_ERROR_INJECTION must be enabled.
+
+The only interface is the error_injection debugfs file, which is created for
+each registered gendisk. Writes to this file are used to create or delete rules
+and reads return a list of the current error injection sites.
+
+Options
+-------
+
+The following options specify the operations:
+
+=================== =======================================================
+add add a new rule
+removeall remove all existing rules
+=================== =======================================================
+
+The following options specify the details of the rule for the add operation:
+
+=================== =======================================================
+op=<string> block layer operation this rule applies to. This uses
+ the XYZ for each REQ_OP_XYZ operation, e.g. READ, WRITE
+ or DISCARD. Mandatory.
+status=<string> Status to return. This uses XYZ for each BLK_STS_XYZ
+ code, e.g. IOERR or MEDIUM. Mandatory.
+start=<number> First block layer sector the rule applies to.
+ Optional, defaults to 0.
+nr_sectors=<number> Number of sectors this rule applies.
+ Optional, defaults to the remainder of the device.
+chance=<number> Only return a failure with a likelihood of 1/chance.
+ Optional, defaults to 1 (always).
+=================== =======================================================
+
+Example
+-------
+
+Return BLK_STS_IOERR for one in 10 reads of sector 0 of /dev/nvme0n1:
+
+ $ echo 'add,op=READ,start=0,status=IOERR,chance=10' > /sys/kernel/debug/block/nvme0n1/error_injection
+
+Return BLK_STS_MEDIUM for every write to /dev/nvme0n1:
+
+ $ echo 'add,op=WRITE,start=0,status=MEDIUM' > /sys/kernel/debug/block/nvme0n1/error_injection
+
+Remove all rules for /dev/nvme0n1:
+
+ $ echo 'removeall' > /sys/kernel/debug/block/nvme0n1/error_injection
diff --git a/Documentation/block/index.rst b/Documentation/block/index.rst
index 9fea696f9daa..bfa1bbd31ddf 100644
--- a/Documentation/block/index.rst
+++ b/Documentation/block/index.rst
@@ -22,3 +22,4 @@ Block
switching-sched
writeback_cache_control
ublk
+ error-injection
diff --git a/block/Kconfig b/block/Kconfig
index 15027963472d..7651b86eed56 100644
--- a/block/Kconfig
+++ b/block/Kconfig
@@ -221,6 +221,13 @@ config BLOCK_HOLDER_DEPRECATED
config BLK_MQ_STACKING
bool
+config BLK_ERROR_INJECTION
+ bool "Enable block layer error injection"
+ help
+ Enable inserting arbitrary block errors through a debugfs interface.
+
+ See Documentation/block/error-injection.rst for details.
+
source "block/Kconfig.iosched"
endif # BLOCK
diff --git a/block/Makefile b/block/Makefile
index 54130faacc21..e7bd320e3d69 100644
--- a/block/Makefile
+++ b/block/Makefile
@@ -13,6 +13,7 @@ obj-y := bdev.o fops.o bio.o elevator.o blk-core.o blk-sysfs.o \
genhd.o ioprio.o badblocks.o partitions/ blk-rq-qos.o \
disk-events.o blk-ia-ranges.o early-lookup.o
+obj-$(CONFIG_BLK_ERROR_INJECTION) += error-injection.o
obj-$(CONFIG_BLK_DEV_BSG_COMMON) += bsg.o
obj-$(CONFIG_BLK_DEV_BSGLIB) += bsg-lib.o
obj-$(CONFIG_BLK_CGROUP) += blk-cgroup.o
diff --git a/block/blk-core.c b/block/blk-core.c
index aa90aad6da13..268735582ef1 100644
--- a/block/blk-core.c
+++ b/block/blk-core.c
@@ -767,6 +767,9 @@ static void __submit_bio_noacct_mq(struct bio *bio)
void submit_bio_noacct_nocheck(struct bio *bio, bool split)
{
+ if (unlikely(blk_error_inject(bio)))
+ return;
+
blk_cgroup_bio_start(bio);
if (!bio_flagged(bio, BIO_TRACE_COMPLETION)) {
diff --git a/block/blk-sysfs.c b/block/blk-sysfs.c
index f22c1f253eb3..8a0c2be48a31 100644
--- a/block/blk-sysfs.c
+++ b/block/blk-sysfs.c
@@ -933,6 +933,8 @@ static void blk_debugfs_remove(struct gendisk *disk)
blk_debugfs_lock_nomemsave(q);
blk_trace_shutdown(q);
+ if (IS_ENABLED(CONFIG_BLK_ERROR_INJECTION))
+ blk_error_injection_exit(disk);
debugfs_remove_recursive(q->debugfs_dir);
q->debugfs_dir = NULL;
q->sched_debugfs_dir = NULL;
@@ -963,6 +965,8 @@ int blk_register_queue(struct gendisk *disk)
memflags = blk_debugfs_lock(q);
q->debugfs_dir = debugfs_create_dir(disk->disk_name, blk_debugfs_root);
+ if (IS_ENABLED(CONFIG_BLK_ERROR_INJECTION))
+ blk_error_injection_init(disk);
if (queue_is_mq(q))
blk_mq_debugfs_register(q);
blk_debugfs_unlock(q, memflags);
diff --git a/block/blk.h b/block/blk.h
index e8b7d5517086..10df23b2cb90 100644
--- a/block/blk.h
+++ b/block/blk.h
@@ -660,6 +660,18 @@ static inline bool should_fail_request(struct block_device *part,
}
#endif /* CONFIG_FAIL_MAKE_REQUEST */
+void blk_error_injection_init(struct gendisk *disk);
+void blk_error_injection_exit(struct gendisk *disk);
+bool __blk_error_inject(struct bio *bio);
+static inline bool blk_error_inject(struct bio *bio)
+{
+ if (!IS_ENABLED(CONFIG_BLK_ERROR_INJECTION))
+ return false;
+ if (!test_bit(GD_ERROR_INJECT, &bio->bi_bdev->bd_disk->state))
+ return false;
+ return __blk_error_inject(bio);
+}
+
/*
* Optimized request reference counting. Ideally we'd make timeouts be more
* clever, as that's the only reason we need references at all... But until
diff --git a/block/error-injection.c b/block/error-injection.c
new file mode 100644
index 000000000000..3ca4ad297683
--- /dev/null
+++ b/block/error-injection.c
@@ -0,0 +1,308 @@
+// SPDX-License-Identifier: GPL-2.0
+/*
+ * Copyright (c) 2026 Christoph Hellwig.
+ */
+#include <linux/debugfs.h>
+#include <linux/blkdev.h>
+#include <linux/parser.h>
+#include <linux/seq_file.h>
+#include "blk.h"
+
+struct blk_error_inject {
+ struct list_head entry;
+ sector_t start;
+ sector_t end;
+ enum req_op op;
+ blk_status_t status;
+
+ /* only inject every 1 / chance times */
+ unsigned int chance;
+};
+
+bool __blk_error_inject(struct bio *bio)
+{
+ struct gendisk *disk = bio->bi_bdev->bd_disk;
+ struct blk_error_inject *inj;
+
+ rcu_read_lock();
+ list_for_each_entry_rcu(inj, &disk->error_injection_list, entry) {
+ if (bio->bi_iter.bi_sector <= inj->end &&
+ bio_end_sector(bio) > inj->start &&
+ bio_op(bio) == inj->op) {
+ blk_status_t status = inj->status;
+
+ if (inj->chance > 1 &&
+ (get_random_u32() % inj->chance) != 0)
+ continue;
+
+ pr_info_ratelimited("%pg: injecting %s error for %s at sector %llu:%u\n",
+ disk->part0,
+ blk_status_to_str(status),
+ blk_op_str(inj->op),
+ bio->bi_iter.bi_sector,
+ bio_sectors(bio));
+ rcu_read_unlock();
+ bio_endio_status(bio, status);
+ return true;
+ }
+ }
+ rcu_read_unlock();
+ return false;
+}
+
+static int error_inject_add(struct gendisk *disk, enum req_op op,
+ sector_t start, u64 nr_sectors, blk_status_t status,
+ unsigned int chance)
+{
+ struct blk_error_inject *inj;
+ int error = -EINVAL;
+
+ if (op == REQ_OP_LAST)
+ return -EINVAL;
+ if (status == BLK_STS_OK)
+ return -EINVAL;
+
+ inj = kzalloc_obj(*inj);
+ if (!inj)
+ return -ENOMEM;
+
+ if (nr_sectors) {
+ if (U64_MAX - nr_sectors < start)
+ goto out_free_inj;
+ inj->end = start + nr_sectors - 1;
+ } else {
+ inj->end = U64_MAX;
+ }
+
+ inj->op = op;
+ inj->start = start;
+ inj->status = status;
+ inj->chance = chance;
+
+ pr_debug_ratelimited("%pg: adding %s injection for %s at sector %llu:%llu\n",
+ disk->part0, blk_status_to_str(status),
+ blk_op_str(op),
+ start, nr_sectors);
+
+ /*
+ * Add to the front of the list so that newer entries can partially
+ * override other entries. This also intentionally allows duplicate
+ * entries as there is no real reason to reject them.
+ */
+ mutex_lock(&disk->error_injection_lock);
+ if (!disk_live(disk)) {
+ mutex_unlock(&disk->error_injection_lock);
+ error = -ENODEV;
+ goto out_free_inj;
+ }
+ list_add_rcu(&inj->entry, &disk->error_injection_list);
+ set_bit(GD_ERROR_INJECT, &disk->state);
+ mutex_unlock(&disk->error_injection_lock);
+ return 0;
+
+out_free_inj:
+ kfree(inj);
+ return error;
+}
+
+static void error_inject_removall(struct gendisk *disk)
+{
+ struct blk_error_inject *inj;
+
+ mutex_lock(&disk->error_injection_lock);
+ clear_bit(GD_ERROR_INJECT, &disk->state);
+ while ((inj = list_first_entry_or_null(&disk->error_injection_list,
+ struct blk_error_inject, entry))) {
+ list_del_rcu(&inj->entry);
+ mutex_unlock(&disk->error_injection_lock);
+
+ kfree_rcu_mightsleep(inj);
+
+ mutex_lock(&disk->error_injection_lock);
+ }
+ mutex_unlock(&disk->error_injection_lock);
+}
+
+enum options {
+ Opt_add = (1u << 0),
+ Opt_removeall = (1u << 1),
+
+ Opt_op = (1u << 16),
+ Opt_start = (1u << 17),
+ Opt_nr_sectors = (1u << 18),
+ Opt_status = (1u << 19),
+ Opt_chance = (1u << 20),
+
+ Opt_invalid,
+};
+
+static const match_table_t opt_tokens = {
+ { Opt_add, "add", },
+ { Opt_removeall, "removeall", },
+ { Opt_op, "op=%s", },
+ { Opt_start, "start=%u" },
+ { Opt_nr_sectors, "nr_sectors=%u" },
+ { Opt_status, "status=%s" },
+ { Opt_chance, "chance=%u" },
+ { Opt_invalid, NULL, },
+};
+
+static int match_op(substring_t *args, enum req_op *op)
+{
+ const char *tag;
+
+ tag = match_strdup(args);
+ if (!tag)
+ return -ENOMEM;
+ *op = str_to_blk_op(tag);
+ if (*op == REQ_OP_LAST)
+ pr_warn("invalid op '%s'\n", tag);
+ kfree(tag);
+ return 0;
+}
+
+static int match_status(substring_t *args, blk_status_t *status)
+{
+ const char *tag;
+
+ tag = match_strdup(args);
+ if (!tag)
+ return -ENOMEM;
+ *status = tag_to_blk_status(tag);
+ if (!*status)
+ pr_warn("invalid status '%s'\n", tag);
+ kfree(tag);
+ return 0;
+}
+
+static ssize_t blk_error_injection_parse_options(struct gendisk *disk,
+ char *options)
+{
+ enum { Unset, Add, Removeall } action = Unset;
+ unsigned int option_mask = 0, chance = 1;
+ enum req_op op = REQ_OP_LAST;
+ u64 start = 0, nr_sectors = 0;
+ blk_status_t status = BLK_STS_OK;
+ substring_t args[MAX_OPT_ARGS];
+ char *p;
+
+ while ((p = strsep(&options, ",\n")) != NULL) {
+ int error = 0;
+ ssize_t token;
+
+ if (!*p)
+ continue;
+ token = match_token(p, opt_tokens, args);
+ option_mask |= token;
+ switch (token) {
+ case Opt_add:
+ if (action != Unset)
+ return -EINVAL;
+ action = Add;
+ break;
+ case Opt_removeall:
+ if (action != Unset)
+ return -EINVAL;
+ action = Removeall;
+ break;
+ case Opt_op:
+ error = match_op(args, &op);
+ break;
+ case Opt_start:
+ error = match_u64(args, &start);
+ break;
+ case Opt_nr_sectors:
+ error = match_u64(args, &nr_sectors);
+ break;
+ case Opt_status:
+ error = match_status(args, &status);
+ break;
+ case Opt_chance:
+ error = match_uint(args, &chance);
+ if (!error && chance == 0)
+ error = -EINVAL;
+ break;
+ default:
+ pr_warn("unknown parameter or missing value '%s'\n", p);
+ error = -EINVAL;
+ }
+ if (error)
+ return error;
+ }
+
+ switch (action) {
+ case Add:
+ return error_inject_add(disk, op, start, nr_sectors, status,
+ chance);
+ case Removeall:
+ if (option_mask & ~Opt_removeall)
+ return -EINVAL;
+ error_inject_removall(disk);
+ return 0;
+ default:
+ return -EINVAL;
+ }
+}
+
+static ssize_t blk_error_injection_write(struct file *file,
+ const char __user *ubuf, size_t count, loff_t *pos)
+{
+ struct gendisk *disk = file_inode(file)->i_private;
+ char *options;
+ int error;
+
+ options = memdup_user_nul(ubuf, count);
+ if (IS_ERR(options))
+ return PTR_ERR(options);
+ error = blk_error_injection_parse_options(disk, options);
+ kfree(options);
+
+ if (error)
+ return error;
+ return count;
+}
+
+static int blk_error_injection_show(struct seq_file *s, void *private)
+{
+ struct gendisk *disk = s->private;
+ struct blk_error_inject *inj;
+
+ rcu_read_lock();
+ list_for_each_entry_rcu(inj, &disk->error_injection_list, entry) {
+ seq_printf(s, "%llu:%llu status=%s,chance=%u",
+ inj->start, inj->end,
+ blk_status_to_tag(inj->status), inj->chance);
+ seq_putc(s, '\n');
+ }
+ rcu_read_unlock();
+ return 0;
+}
+
+static int blk_error_injection_open(struct inode *inode, struct file *file)
+{
+ return single_open(file, blk_error_injection_show, inode->i_private);
+}
+
+static int blk_error_injection_release(struct inode *inode, struct file *file)
+{
+ return single_release(inode, file);
+}
+
+static const struct file_operations blk_error_injection_fops = {
+ .owner = THIS_MODULE,
+ .write = blk_error_injection_write,
+ .read = seq_read,
+ .open = blk_error_injection_open,
+ .release = blk_error_injection_release,
+};
+
+void blk_error_injection_init(struct gendisk *disk)
+{
+ debugfs_create_file("error_injection", 0600, disk->queue->debugfs_dir,
+ disk, &blk_error_injection_fops);
+}
+
+void blk_error_injection_exit(struct gendisk *disk)
+{
+ error_inject_removall(disk);
+}
diff --git a/block/genhd.c b/block/genhd.c
index 7d6854fd28e9..f84b6a355b57 100644
--- a/block/genhd.c
+++ b/block/genhd.c
@@ -1485,6 +1485,10 @@ struct gendisk *__alloc_disk_node(struct request_queue *q, int node_id,
lockdep_init_map(&disk->lockdep_map, "(bio completion)", lkclass, 0);
#ifdef CONFIG_BLOCK_HOLDER_DEPRECATED
INIT_LIST_HEAD(&disk->slave_bdevs);
+#endif
+#ifdef CONFIG_BLK_ERROR_INJECTION
+ mutex_init(&disk->error_injection_lock);
+ INIT_LIST_HEAD(&disk->error_injection_list);
#endif
mutex_init(&disk->rqos_state_mutex);
kobject_init(&disk->queue_kobj, &blk_queue_ktype);
diff --git a/include/linux/blkdev.h b/include/linux/blkdev.h
index 57e84d59a642..5070851cf924 100644
--- a/include/linux/blkdev.h
+++ b/include/linux/blkdev.h
@@ -176,6 +176,7 @@ struct gendisk {
#define GD_SUPPRESS_PART_SCAN 5
#define GD_OWNS_QUEUE 6
#define GD_ZONE_APPEND_USED 7
+#define GD_ERROR_INJECT 8
struct mutex open_mutex; /* open/close mutex */
unsigned open_partitions; /* number of open partitions */
@@ -227,6 +228,11 @@ struct gendisk {
*/
struct blk_independent_access_ranges *ia_ranges;
+#ifdef CONFIG_BLK_ERROR_INJECTION
+ struct mutex error_injection_lock;
+ struct list_head error_injection_list;
+#endif
+
struct mutex rqos_state_mutex; /* rqos state change mutex */
};
--
2.53.0
^ permalink raw reply related
* Re: [PATCH 11/15] accel/qda: Add PRIME DMA-BUF import support
From: Ekansh Gupta @ 2026-06-08 5:14 UTC (permalink / raw)
To: Christian König, Oded Gabbay, Jonathan Corbet, Shuah Khan,
Joerg Roedel, Will Deacon, Robin Murphy, Maarten Lankhorst,
Maxime Ripard, Thomas Zimmermann, David Airlie, Simona Vetter,
Sumit Semwal
Cc: Bharath Kumar, Chenna Kesava Raju, srini, dmitry.baryshkov,
andersson, konradybcio, robin.clark, linux-kernel, dri-devel,
linux-doc, linux-arm-msm, iommu, linux-media, linaro-mm-sig
In-Reply-To: <0feaad40-8bde-46c4-a251-07a1bd6ac79d@amd.com>
On 03-06-2026 19:10, Christian König wrote:
> On 6/3/26 08:11, Ekansh Gupta wrote:
>> On 19-05-2026 12:25, Christian König wrote:
>>> On 5/19/26 08:16, Ekansh Gupta via B4 Relay wrote:
>>>> From: Ekansh Gupta <ekansh.gupta@oss.qualcomm.com>
> ...
>>>> +static int qda_memory_manager_map_imported(struct qda_memory_manager *mem_mgr,
>>>> + struct qda_gem_obj *gem_obj,
>>>> + struct qda_iommu_device *iommu_dev)
>>>> +{
>>>> + struct scatterlist *sg;
>>>> + dma_addr_t dma_addr;
>>>> +
>>>> + if (!gem_obj->is_imported || !gem_obj->sgt || !iommu_dev) {
>>>> + drm_err(gem_obj->base.dev, "Invalid parameters for imported buffer mapping\n");
>>>> + return -EINVAL;
>>>> + }
>>>> +
>>>> + sg = gem_obj->sgt->sgl;
>>>> + if (!sg) {
>>>> + drm_err(gem_obj->base.dev, "Invalid scatter-gather list for imported buffer\n");
>>>> + return -EINVAL;
>>>> + }
>>>> +
>>>> + gem_obj->iommu_dev = iommu_dev;
>>>> +
>>>> + /*
>>>> + * After dma_buf_map_attachment_unlocked(), sg_dma_address() returns the
>>>> + * IOMMU virtual address, not the physical address. The IOMMU maps the
>>>> + * entire buffer as a contiguous range in the IOMMU address space even if
>>>> + * the underlying physical memory is non-contiguous. Therefore the first
>>>> + * sg entry's DMA address is the start of the complete contiguous
>>>> + * IOMMU-mapped range and is sufficient to describe the buffer to the DSP.
>>>> + */
>>>> + dma_addr = sg_dma_address(sg);
>>>> + dma_addr += ((u64)iommu_dev->sid << 32);
>>>> + gem_obj->dma_addr = dma_addr;
>>>
>>> That handling here is completely broken since it assumes that the exporter maps the buffer as contigious range.
>>>
>>> But that's in no way guaranteed.
>> I'll collect more details and will try to implement this in the right
>> way, maybe by iterating the full sg_table.>
>
> You could also document explicitly that you can only import contiguous buffers (e.g. DMA-buf heap CMA etc....) and then cleanly reject non contiguous buffers here.
>
> We have quite a number of drivers/HW with that limitation, so only accepting contiguous buffers is perfectly ok.
>
> You just can't silently assume that IOMMU would always map the entire buffer as one contiguous range, cause that is certainly not true.
I understand your point Christian, thanks for the suggestion!>
> Regards,
> Christian.
>
>
>>> Regards,
>>> Christian.
^ permalink raw reply
* RE: [PATCH net-next v4 16/16] Documentation: networking: Add timestamp related APIs to OA TC6 framework
From: Selvamani Rajagopal @ 2026-06-08 5:19 UTC (permalink / raw)
To: Randy Dunlap, Andrew Lunn, Piergiorgio Beruto, Heiner Kallweit,
Russell King, David S. Miller, Eric Dumazet, Jakub Kicinski,
Paolo Abeni, Andrew Lunn, Parthiban Veerasooran, Richard Cochran,
Rob Herring, Krzysztof Kozlowski, Conor Dooley, Simon Horman,
Jonathan Corbet, Shuah Khan
Cc: netdev@vger.kernel.org, linux-kernel@vger.kernel.org,
devicetree@vger.kernel.org, linux-doc@vger.kernel.org, Jerry Ray
In-Reply-To: <DM4PR02MB9263A6240C8D09E368B6F980831C2@DM4PR02MB9263.namprd02.prod.outlook.com>
> > Subject: RE: [PATCH net-next v4 16/16] Documentation: networking: Add timestamp
> > related APIs to OA TC6 framework
> >
> > >
> > > Documentation/networking/oa-tc6-framework.rst:554: WARNING: Explicit markup
> ends
>
> Randy,
>
> Though I fixed the issues you pointed out, I couldn't reproduce this issue with either
> "make htmldocs"
> or with "sphinx-build" commands.
>
> Am I missing something with respect to how document generation/verification is done?
>
I see the error now. I don't know why I didn't see earlier. Sorry for asking too soon.
>
>
>
> > > See below.
> > >
^ permalink raw reply
* Re: [PATCH v6 00/11] Dynamic PAMT
From: Tony Lindgren @ 2026-06-08 5:45 UTC (permalink / raw)
To: Rick Edgecombe
Cc: bp, dave.hansen, hpa, kas, kvm, linux-coco, linux-doc,
linux-kernel, mingo, nik.borisov, pbonzini, seanjc, tglx,
vannapurve, x86, chao.gao, yan.y.zhao, kai.huang
In-Reply-To: <20260526023515.288829-1-rick.p.edgecombe@intel.com>
On Mon, May 25, 2026 at 07:35:04PM -0700, Rick Edgecombe wrote:
> For a simple small server with mostly physical contiguous RAM and no CXL
> complications, the basic implementation should be close to optimal anyway.
> And for big servers, an 8GB allocation is going to have less impact. In
> the end Dynamic PAMT *is* an optimization that we will force on as a
> good default option. Even with all the optimizations we could throw at it,
> if the system is 100% TDs, Dynamic PAMT could come out slightly behind. So
> judgment on good defaults is needed regardless.
From usage point of view it's not just a memory optimization though.
These patches make it easier to see what gets allocated for TDX IMO.
This based on rebasing other patches on the dynamic PAMT series a few
times over the past year. So for the series:
Reviewed-by: Tony Lindgren <tony.lindgren@linux.intel.com>
^ permalink raw reply
* [PATCH v2 0/2] docs/zh: update DAMON usage sysfs documentation
From: Doehyun Baek @ 2026-06-08 6:03 UTC (permalink / raw)
To: Alex Shi, Yanteng Si, Hu Haowen
Cc: Dongliang Mu, Jonathan Corbet, Shuah Khan, SeongJae Park,
linux-doc, linux-kernel, damon, Doehyun Baek
In-Reply-To: <20260523094420.741003-1-doehyunbaek@gmail.com>
Changes since v1:
- Revise both commit messages to follow the translation update format
documented in Documentation/translations/zh_CN/how-to.rst.
Doehyun Baek (2):
docs/zh_CN: update DAMON usage Chinese translation
docs/zh_TW: update DAMON usage Traditional Chinese translation
.../zh_CN/admin-guide/mm/damon/usage.rst | 56 +++++++++++++------
.../zh_TW/admin-guide/mm/damon/usage.rst | 56 +++++++++++++------
2 files changed, 80 insertions(+), 32 deletions(-)
base-commit: 4549871118cf616eecdd2d939f78e3b9e1dddc48
--
2.43.0
^ permalink raw reply
* [PATCH v2 1/2] docs/zh_CN: update DAMON usage Chinese translation
From: Doehyun Baek @ 2026-06-08 6:03 UTC (permalink / raw)
To: Alex Shi, Yanteng Si, Hu Haowen
Cc: Dongliang Mu, Jonathan Corbet, Shuah Khan, SeongJae Park,
linux-doc, linux-kernel, damon, Doehyun Baek
In-Reply-To: <20260608060302.1564003-1-doehyunbaek@gmail.com>
Update the translation of .../admin-guide/mm/damon/usage.rst into Chinese.
Update the translation through commit d9cfe515d36e
("Docs/admin-guide/mm/damon/usage: document goal_tuner sysfs file")
Signed-off-by: Doehyun Baek <doehyunbaek@gmail.com>
---
.../zh_CN/admin-guide/mm/damon/usage.rst | 56 +++++++++++++------
1 file changed, 40 insertions(+), 16 deletions(-)
diff --git a/Documentation/translations/zh_CN/admin-guide/mm/damon/usage.rst b/Documentation/translations/zh_CN/admin-guide/mm/damon/usage.rst
index 9d7cb51be493..3fbfa9df9935 100644
--- a/Documentation/translations/zh_CN/admin-guide/mm/damon/usage.rst
+++ b/Documentation/translations/zh_CN/admin-guide/mm/damon/usage.rst
@@ -15,6 +15,10 @@
DAMON 为不同的用户提供了下面这些接口。
+- *专用DAMON模块。*
+ :ref:`这 <damon_modules_special_purpose>` 是为构建、发布或管理带有专用DAMON用法的内
+ 核的用户准备的。使用它,用户可以在构建、启动或运行时以简单的方式为给定目的使用DAMON的主要
+ 功能。
- *DAMON用户空间工具。*
`这 <https://github.com/damonitor/damo>`_ 为有这特权的人, 如系统管理员,希望有一个刚好
可以工作的人性化界面。
@@ -55,14 +59,14 @@ DAMON sysfs接口的文件层次结构如下图所示。在下图中,父子关
/sys/kernel/mm/damon/admin
│ kdamonds/nr_kdamonds
- │ │ 0/state,pid
+ │ │ 0/state,pid,refresh_ms
│ │ │ contexts/nr_contexts
- │ │ │ │ 0/operations
+ │ │ │ │ 0/operations,addr_unit
│ │ │ │ │ monitoring_attrs/
│ │ │ │ │ │ intervals/sample_us,aggr_us,update_us
│ │ │ │ │ │ nr_regions/min,max
│ │ │ │ │ targets/nr_targets
- │ │ │ │ │ │ 0/pid_target
+ │ │ │ │ │ │ 0/pid_target,obsolete_target
│ │ │ │ │ │ │ regions/nr_regions
│ │ │ │ │ │ │ │ 0/start,end
│ │ │ │ │ │ │ │ ...
@@ -73,10 +77,12 @@ DAMON sysfs接口的文件层次结构如下图所示。在下图中,父子关
│ │ │ │ │ │ │ │ sz/min,max
│ │ │ │ │ │ │ │ nr_accesses/min,max
│ │ │ │ │ │ │ │ age/min,max
- │ │ │ │ │ │ │ quotas/ms,bytes,reset_interval_ms
+ │ │ │ │ │ │ │ quotas/ms,bytes,reset_interval_ms,goal_tuner
│ │ │ │ │ │ │ │ weights/sz_permil,nr_accesses_permil,age_permil
+ │ │ │ │ │ │ │ │ goals/nr_goals
+ │ │ │ │ │ │ │ │ │ 0/target_metric,target_value,current_value,nid
│ │ │ │ │ │ │ watermarks/metric,interval_us,high,mid,low
- │ │ │ │ │ │ │ stats/nr_tried,sz_tried,nr_applied,sz_applied,qt_exceeds
+ │ │ │ │ │ │ │ stats/nr_tried,sz_tried,nr_applied,sz_applied,qt_exceeds,nr_snapshots,max_nr_snapshots
│ │ │ │ │ │ │ tried_regions/
│ │ │ │ │ │ │ │ 0/start,end,nr_accesses,age
│ │ │ │ │ │ │ │ ...
@@ -104,7 +110,8 @@ kdamonds/
kdamonds/<N>/
-------------
-在每个kdamond目录中,存在两个文件(``state`` 和 ``pid`` )和一个目录( ``contexts`` )。
+在每个kdamond目录中,存在三个文件(``state``、``pid`` 和 ``refresh_ms``)和一个目录
+(``contexts``)。
读取 ``state`` 时,如果kdamond当前正在运行,则返回 ``on`` ,如果没有运行则返回 ``off`` 。
写入 ``on`` 或 ``off`` 使kdamond处于状态。向 ``state`` 文件写 ``update_schemes_stats`` ,
@@ -117,6 +124,10 @@ kdamonds/<N>/
如果状态为 ``on``,读取 ``pid`` 显示kdamond线程的pid。
+用户可以要求内核通过 ``refresh_ms`` 文件周期性地更新显示自动调优参数和DAMOS统计信息的文件。
+向该文件写入希望的更新时间间隔(毫秒)。如果间隔为零,则禁用周期性更新。读取该文件会显示当前
+设置的时间间隔。
+
``contexts`` 目录包含控制这个kdamond要执行的监测上下文的文件。
kdamonds/<N>/contexts/
@@ -129,8 +140,8 @@ kdamonds/<N>/contexts/
contexts/<N>/
-------------
-在每个上下文目录中,存在一个文件(``operations``)和三个目录(``monitoring_attrs``,
-``targets``, 和 ``schemes``)。
+在每个上下文目录中,存在两个文件(``operations`` 和 ``addr_unit``)和三个目录
+(``monitoring_attrs``、``targets`` 和 ``schemes``)。
DAMON支持多种类型的监测操作,包括对虚拟地址空间和物理地址空间的监测。你可以通过向文件
中写入以下关键词之一,并从文件中读取,来设置和获取DAMON将为上下文使用何种类型的监测操作。
@@ -138,6 +149,8 @@ DAMON支持多种类型的监测操作,包括对虚拟地址空间和物理地
- vaddr: 监测特定进程的虚拟地址空间
- paddr: 监视系统的物理地址空间
+``addr_unit`` 文件用于设置和获取操作集的 :ref:`地址单位 <damon_design_addr_unit>` 参数。
+
contexts/<N>/monitoring_attrs/
------------------------------
@@ -161,11 +174,15 @@ contexts/<N>/targets/
targets/<N>/
------------
-在每个目标目录中,存在一个文件(``pid_target``)和一个目录(``regions``)。
+在每个目标目录中,存在两个文件(``pid_target`` 和 ``obsolete_target``)和一个目录
+(``regions``)。
如果你把 ``vaddr`` 写到 ``contexts/<N>/operations`` 中,每个目标应该是一个进程。你
可以通过将进程的pid写到 ``pid_target`` 文件中来指定DAMON的进程。
+用户可以向 ``obsolete_target`` 文件写入非零值并提交它(向 ``state`` 文件写入 ``commit``),
+从目标数组中间选择性地删除目标。
+
targets/<N>/regions
-------------------
@@ -239,14 +256,20 @@ schemes/<N>/quotas/
当预计超过配额限制时,DAMON会根据 ``目标访问模式`` 的大小、访问频率和年龄,对找到的内存区域
进行优先排序。为了进行个性化的优先排序,用户可以为这三个属性设置权重。
-在 ``quotas`` 目录下,存在三个文件(``ms``, ``bytes``, ``reset_interval_ms``)和一个
-目录(``weights``),其中有三个文件(``sz_permil``, ``nr_accesses_permil``, 和
-``age_permil``)。
+在 ``quotas`` 目录下,存在四个文件(``ms``、``bytes``、``reset_interval_ms`` 和
+``goal_tuner``)和两个目录(``weights`` 和 ``goals``)。
你可以设置以毫秒为单位的 ``时间配额`` ,以字节为单位的 ``大小配额`` ,以及以毫秒为单位的 ``重
置间隔`` ,分别向这三个文件写入数值。你还可以通过向 ``weights`` 目录下的三个文件写入数值来设
置大小、访问频率和年龄的优先权,单位为千分之一。
+你可以通过向 ``goal_tuner`` 文件写入算法名称,设置要使用的基于目标的有效配额自动调优算法。
+读取该文件会返回当前选定的调优器算法。
+
+``goals`` 目录用于设置自动配额调优目标。每个目标目录包含 ``target_metric``、
+``target_value``、``current_value`` 和 ``nid`` 文件。用户可以读写这些文件来设置和获取配额
+自动调优目标的参数。
+
schemes/<N>/watermarks/
-----------------------
@@ -271,10 +294,11 @@ schemes/<N>/stats/
DAMON统计每个方案被尝试应用的区域的总数量和字节数,每个方案被成功应用的区域的两个数字,以及
超过配额限制的总数量。这些统计数据可用于在线分析或调整方案。
-可以通过读取 ``stats`` 目录下的文件(``nr_tried``, ``sz_tried``, ``nr_applied``,
-``sz_applied``, 和 ``qt_exceeds``))分别检索这些统计数据。这些文件不是实时更新的,所以
-你应该要求DAMON sysfs接口通过在相关的 ``kdamonds/<N>/state`` 文件中写入一个特殊的关键字
-``update_schemes_stats`` 来更新统计信息的文件内容。
+可以通过读取 ``stats`` 目录下的文件(``nr_tried``、``sz_tried``、``nr_applied``、
+``sz_applied``、``qt_exceeds``、``nr_snapshots`` 和 ``max_nr_snapshots``)分别检索这些
+统计数据。这些文件默认不是实时更新的。你应该要求DAMON sysfs接口通过 ``refresh_ms`` 周期性地
+更新这些文件,或者通过在相关的 ``kdamonds/<N>/state`` 文件中写入一个特殊的关键字
+``update_schemes_stats`` 来执行一次性更新。
schemes/<N>/tried_regions/
--------------------------
--
2.43.0
^ permalink raw reply related
* [PATCH v2 2/2] docs/zh_TW: update DAMON usage Traditional Chinese translation
From: Doehyun Baek @ 2026-06-08 6:03 UTC (permalink / raw)
To: Alex Shi, Yanteng Si, Hu Haowen
Cc: Dongliang Mu, Jonathan Corbet, Shuah Khan, SeongJae Park,
linux-doc, linux-kernel, damon, Doehyun Baek
In-Reply-To: <20260608060302.1564003-1-doehyunbaek@gmail.com>
Update the translation of .../admin-guide/mm/damon/usage.rst into
Traditional Chinese.
Update the translation through commit d9cfe515d36e
("Docs/admin-guide/mm/damon/usage: document goal_tuner sysfs file")
Signed-off-by: Doehyun Baek <doehyunbaek@gmail.com>
---
.../zh_TW/admin-guide/mm/damon/usage.rst | 56 +++++++++++++------
1 file changed, 40 insertions(+), 16 deletions(-)
diff --git a/Documentation/translations/zh_TW/admin-guide/mm/damon/usage.rst b/Documentation/translations/zh_TW/admin-guide/mm/damon/usage.rst
index d3fd4f850793..debe455723af 100644
--- a/Documentation/translations/zh_TW/admin-guide/mm/damon/usage.rst
+++ b/Documentation/translations/zh_TW/admin-guide/mm/damon/usage.rst
@@ -15,6 +15,10 @@
DAMON 爲不同的用戶提供了下面這些接口。
+- *專用DAMON模塊。*
+ :ref:`這 <damon_modules_special_purpose>` 是爲構建、發佈或管理帶有專用DAMON用法的內
+ 核的用戶準備的。使用它,用戶可以在構建、啓動或運行時以簡單的方式爲給定目的使用DAMON的主要
+ 功能。
- *DAMON用戶空間工具。*
`這 <https://github.com/damonitor/damo>`_ 爲有這特權的人, 如系統管理員,希望有一個剛好
可以工作的人性化界面。
@@ -55,14 +59,14 @@ DAMON sysfs接口的文件層次結構如下圖所示。在下圖中,父子關
/sys/kernel/mm/damon/admin
│ kdamonds/nr_kdamonds
- │ │ 0/state,pid
+ │ │ 0/state,pid,refresh_ms
│ │ │ contexts/nr_contexts
- │ │ │ │ 0/operations
+ │ │ │ │ 0/operations,addr_unit
│ │ │ │ │ monitoring_attrs/
│ │ │ │ │ │ intervals/sample_us,aggr_us,update_us
│ │ │ │ │ │ nr_regions/min,max
│ │ │ │ │ targets/nr_targets
- │ │ │ │ │ │ 0/pid_target
+ │ │ │ │ │ │ 0/pid_target,obsolete_target
│ │ │ │ │ │ │ regions/nr_regions
│ │ │ │ │ │ │ │ 0/start,end
│ │ │ │ │ │ │ │ ...
@@ -73,10 +77,12 @@ DAMON sysfs接口的文件層次結構如下圖所示。在下圖中,父子關
│ │ │ │ │ │ │ │ sz/min,max
│ │ │ │ │ │ │ │ nr_accesses/min,max
│ │ │ │ │ │ │ │ age/min,max
- │ │ │ │ │ │ │ quotas/ms,bytes,reset_interval_ms
+ │ │ │ │ │ │ │ quotas/ms,bytes,reset_interval_ms,goal_tuner
│ │ │ │ │ │ │ │ weights/sz_permil,nr_accesses_permil,age_permil
+ │ │ │ │ │ │ │ │ goals/nr_goals
+ │ │ │ │ │ │ │ │ │ 0/target_metric,target_value,current_value,nid
│ │ │ │ │ │ │ watermarks/metric,interval_us,high,mid,low
- │ │ │ │ │ │ │ stats/nr_tried,sz_tried,nr_applied,sz_applied,qt_exceeds
+ │ │ │ │ │ │ │ stats/nr_tried,sz_tried,nr_applied,sz_applied,qt_exceeds,nr_snapshots,max_nr_snapshots
│ │ │ │ │ │ │ tried_regions/
│ │ │ │ │ │ │ │ 0/start,end,nr_accesses,age
│ │ │ │ │ │ │ │ ...
@@ -104,7 +110,8 @@ kdamonds/
kdamonds/<N>/
-------------
-在每個kdamond目錄中,存在兩個文件(``state`` 和 ``pid`` )和一個目錄( ``contexts`` )。
+在每個kdamond目錄中,存在三個文件(``state``、``pid`` 和 ``refresh_ms``)和一個目錄
+(``contexts``)。
讀取 ``state`` 時,如果kdamond當前正在運行,則返回 ``on`` ,如果沒有運行則返回 ``off`` 。
寫入 ``on`` 或 ``off`` 使kdamond處於狀態。向 ``state`` 文件寫 ``update_schemes_stats`` ,
@@ -117,6 +124,10 @@ kdamonds/<N>/
如果狀態爲 ``on``,讀取 ``pid`` 顯示kdamond線程的pid。
+用戶可以要求內核通過 ``refresh_ms`` 文件週期性地更新顯示自動調優參數和DAMOS統計信息的文件。
+向該文件寫入希望的更新時間間隔(毫秒)。如果間隔爲零,則禁用週期性更新。讀取該文件會顯示當前
+設置的時間間隔。
+
``contexts`` 目錄包含控制這個kdamond要執行的監測上下文的文件。
kdamonds/<N>/contexts/
@@ -129,8 +140,8 @@ kdamonds/<N>/contexts/
contexts/<N>/
-------------
-在每個上下文目錄中,存在一個文件(``operations``)和三個目錄(``monitoring_attrs``,
-``targets``, 和 ``schemes``)。
+在每個上下文目錄中,存在兩個文件(``operations`` 和 ``addr_unit``)和三個目錄
+(``monitoring_attrs``、``targets`` 和 ``schemes``)。
DAMON支持多種類型的監測操作,包括對虛擬地址空間和物理地址空間的監測。你可以通過向文件
中寫入以下關鍵詞之一,並從文件中讀取,來設置和獲取DAMON將爲上下文使用何種類型的監測操作。
@@ -138,6 +149,8 @@ DAMON支持多種類型的監測操作,包括對虛擬地址空間和物理地
- vaddr: 監測特定進程的虛擬地址空間
- paddr: 監視系統的物理地址空間
+``addr_unit`` 文件用於設置和獲取操作集的 :ref:`地址單位 <damon_design_addr_unit>` 參數。
+
contexts/<N>/monitoring_attrs/
------------------------------
@@ -161,11 +174,15 @@ contexts/<N>/targets/
targets/<N>/
------------
-在每個目標目錄中,存在一個文件(``pid_target``)和一個目錄(``regions``)。
+在每個目標目錄中,存在兩個文件(``pid_target`` 和 ``obsolete_target``)和一個目錄
+(``regions``)。
如果你把 ``vaddr`` 寫到 ``contexts/<N>/operations`` 中,每個目標應該是一個進程。你
可以通過將進程的pid寫到 ``pid_target`` 文件中來指定DAMON的進程。
+用戶可以向 ``obsolete_target`` 文件寫入非零值並提交它(向 ``state`` 文件寫入 ``commit``),
+從目標數組中間選擇性地刪除目標。
+
targets/<N>/regions
-------------------
@@ -239,14 +256,20 @@ schemes/<N>/quotas/
當預計超過配額限制時,DAMON會根據 ``目標訪問模式`` 的大小、訪問頻率和年齡,對找到的內存區域
進行優先排序。爲了進行個性化的優先排序,用戶可以爲這三個屬性設置權重。
-在 ``quotas`` 目錄下,存在三個文件(``ms``, ``bytes``, ``reset_interval_ms``)和一個
-目錄(``weights``),其中有三個文件(``sz_permil``, ``nr_accesses_permil``, 和
-``age_permil``)。
+在 ``quotas`` 目錄下,存在四個文件(``ms``、``bytes``、``reset_interval_ms`` 和
+``goal_tuner``)和兩個目錄(``weights`` 和 ``goals``)。
你可以設置以毫秒爲單位的 ``時間配額`` ,以字節爲單位的 ``大小配額`` ,以及以毫秒爲單位的 ``重
置間隔`` ,分別向這三個文件寫入數值。你還可以通過向 ``weights`` 目錄下的三個文件寫入數值來設
置大小、訪問頻率和年齡的優先權,單位爲千分之一。
+你可以通過向 ``goal_tuner`` 文件寫入算法名稱,設置要使用的基於目標的有效配額自動調優算法。
+讀取該文件會返回當前選定的調優器算法。
+
+``goals`` 目錄用於設置自動配額調優目標。每個目標目錄包含 ``target_metric``、
+``target_value``、``current_value`` 和 ``nid`` 文件。用戶可以讀寫這些文件來設置和獲取配額
+自動調優目標的參數。
+
schemes/<N>/watermarks/
-----------------------
@@ -271,10 +294,11 @@ schemes/<N>/stats/
DAMON統計每個方案被嘗試應用的區域的總數量和字節數,每個方案被成功應用的區域的兩個數字,以及
超過配額限制的總數量。這些統計數據可用於在線分析或調整方案。
-可以通過讀取 ``stats`` 目錄下的文件(``nr_tried``, ``sz_tried``, ``nr_applied``,
-``sz_applied``, 和 ``qt_exceeds``))分別檢索這些統計數據。這些文件不是實時更新的,所以
-你應該要求DAMON sysfs接口通過在相關的 ``kdamonds/<N>/state`` 文件中寫入一個特殊的關鍵字
-``update_schemes_stats`` 來更新統計信息的文件內容。
+可以通過讀取 ``stats`` 目錄下的文件(``nr_tried``、``sz_tried``、``nr_applied``、
+``sz_applied``、``qt_exceeds``、``nr_snapshots`` 和 ``max_nr_snapshots``)分別檢索這些
+統計數據。這些文件默認不是實時更新的。你應該要求DAMON sysfs接口通過 ``refresh_ms`` 週期性地
+更新這些文件,或者通過在相關的 ``kdamonds/<N>/state`` 文件中寫入一個特殊的關鍵字
+``update_schemes_stats`` 來執行一次性更新。
schemes/<N>/tried_regions/
--------------------------
--
2.43.0
^ permalink raw reply related
* [PATCH v2] hwmon: (asus-ec-sensors) add ROG MAXIMUS Z790 EXTREME
From: Eugene Shalygin @ 2026-06-08 6:08 UTC (permalink / raw)
To: eugene.shalygin
Cc: Brian Downey, Guenter Roeck, Jonathan Corbet, Shuah Khan,
open list:HARDWARE MONITORING, open list:DOCUMENTATION, open list
From: Brian Downey <bdowne01@gmail.com>
Add support for ROG MAXIMUS Z790 EXTREME
Signed-off-by: Brian Downey <bdowne01@gmail.com>
Signed-off-by: Eugene Shalygin <eugene.shalygin@gmail.com>
---
Documentation/hwmon/asus_ec_sensors.rst | 1 +
drivers/hwmon/asus-ec-sensors.c | 15 +++++++++++++++
2 files changed, 16 insertions(+)
diff --git a/Documentation/hwmon/asus_ec_sensors.rst b/Documentation/hwmon/asus_ec_sensors.rst
index 9ad3f0a57f55..60f1a6036538 100644
--- a/Documentation/hwmon/asus_ec_sensors.rst
+++ b/Documentation/hwmon/asus_ec_sensors.rst
@@ -29,6 +29,7 @@ Supported boards:
* ROG MAXIMUS XI HERO
* ROG MAXIMUS XI HERO (WI-FI)
* ROG MAXIMUS Z690 FORMULA
+ * ROG MAXIMUS Z790 EXTREME
* ROG STRIX B550-E GAMING
* ROG STRIX B550-I GAMING
* ROG STRIX B650E-I GAMING WIFI
diff --git a/drivers/hwmon/asus-ec-sensors.c b/drivers/hwmon/asus-ec-sensors.c
index 070bb368f2b7..0e78750de34a 100644
--- a/drivers/hwmon/asus-ec-sensors.c
+++ b/drivers/hwmon/asus-ec-sensors.c
@@ -399,6 +399,12 @@ static const struct ec_sensor_info sensors_family_intel_700[] = {
[ec_sensor_temp_vrm] = EC_SENSOR("VRM", hwmon_temp, 1, 0x00, 0x33),
[ec_sensor_fan_cpu_opt] =
EC_SENSOR("CPU_Opt", hwmon_fan, 2, 0x00, 0xb0),
+ [ec_sensor_fan_water_flow] =
+ EC_SENSOR("Water_Flow", hwmon_fan, 2, 0x00, 0xbc),
+ [ec_sensor_temp_water_in] =
+ EC_SENSOR("Water_In", hwmon_temp, 1, 0x01, 0x00),
+ [ec_sensor_temp_water_out] =
+ EC_SENSOR("Water_Out", hwmon_temp, 1, 0x01, 0x01),
};
/* Shortcuts for common combinations */
@@ -509,6 +515,13 @@ static const struct ec_board_info board_info_maximus_z690_formula = {
.family = family_intel_600_series,
};
+static const struct ec_board_info board_info_maximus_z790_extreme = {
+ .sensors = SENSOR_TEMP_T_SENSOR | SENSOR_TEMP_VRM |
+ SENSOR_SET_TEMP_WATER | SENSOR_FAN_WATER_FLOW,
+ .mutex_path = ASUS_HW_ACCESS_MUTEX_RMTW_ASMX,
+ .family = family_intel_700_series,
+};
+
static const struct ec_board_info board_info_prime_x470_pro = {
.sensors = SENSOR_SET_TEMP_CHIPSET_CPU_MB |
SENSOR_TEMP_T_SENSOR | SENSOR_TEMP_VRM |
@@ -857,6 +870,8 @@ static const struct dmi_system_id dmi_table[] = {
&board_info_maximus_x_hero),
DMI_EXACT_MATCH_ASUS_BOARD_NAME("ROG MAXIMUS Z690 FORMULA",
&board_info_maximus_z690_formula),
+ DMI_EXACT_MATCH_ASUS_BOARD_NAME("ROG MAXIMUS Z790 EXTREME",
+ &board_info_maximus_z790_extreme),
DMI_EXACT_MATCH_ASUS_BOARD_NAME("ROG STRIX B550-E GAMING",
&board_info_strix_b550_e_gaming),
DMI_EXACT_MATCH_ASUS_BOARD_NAME("ROG STRIX B550-I GAMING",
--
2.54.0
^ permalink raw reply related
* Re: [PATCH v3 4/6] alloc_tag: add accuracy based filtering to ioctl
From: Hao Ge @ 2026-06-08 6:22 UTC (permalink / raw)
To: Abhishek Bapat
Cc: Shuah Khan, Jonathan Corbet, linux-doc, linux-kernel, linux-mm,
Sourav Panda, Suren Baghdasaryan, Andrew Morton, Kent Overstreet
In-Reply-To: <b608a6f7d71e3b728f766dbc6dfa1d1753ddcff5.1780701922.git.abhishekbapat@google.com>
Hi Abhishek
On 2026/6/6 07:36, Abhishek Bapat wrote:
> Extend the allocinfo filtering mechanism to allow users to filter tags
> based on their accuracy.
>
> Signed-off-by: Abhishek Bapat <abhishekbapat@google.com>
> ---
> include/uapi/linux/alloc_tag.h | 3 +++
> lib/alloc_tag.c | 8 ++++++++
> 2 files changed, 11 insertions(+)
>
> diff --git a/include/uapi/linux/alloc_tag.h b/include/uapi/linux/alloc_tag.h
> index 0e648192df4d..42445bdb11c5 100644
> --- a/include/uapi/linux/alloc_tag.h
> +++ b/include/uapi/linux/alloc_tag.h
> @@ -20,6 +20,7 @@ struct allocinfo_tag {
> char function[ALLOCINFO_STR_SIZE];
> char filename[ALLOCINFO_STR_SIZE];
> __u64 lineno;
> + __u64 inaccurate;
I was wondering if it would make sense to define inaccurate as a flags field
(e.g. __u64 flags with ALLOCINFO_TAG_F_INACCURATE (1 <<0)),
so that only bit 0 is used today and the upper bits are reserved for
future use,
aligning with current kernel codebase.
This design also allows for better extensibility if we need to
add new flags for any reason in the future.
We also need to add flag validity checks if we go this route.
Thanks
Best Regards
Hao
> };
>
> /* The alignment ensures 32-bit compatible interfaces are not broken */
> @@ -39,6 +40,7 @@ enum {
> ALLOCINFO_FILTER_FUNCTION,
> ALLOCINFO_FILTER_FILENAME,
> ALLOCINFO_FILTER_LINENO,
> + ALLOCINFO_FILTER_INACCURATE,
> ALLOCINFO_FILTER_MIN_SIZE,
> ALLOCINFO_FILTER_MAX_SIZE,
> __ALLOCINFO_FILTER_LAST = ALLOCINFO_FILTER_MAX_SIZE
> @@ -48,6 +50,7 @@ enum {
> #define ALLOCINFO_FILTER_MASK_FUNCTION (1 << ALLOCINFO_FILTER_FUNCTION)
> #define ALLOCINFO_FILTER_MASK_FILENAME (1 << ALLOCINFO_FILTER_FILENAME)
> #define ALLOCINFO_FILTER_MASK_LINENO (1 << ALLOCINFO_FILTER_LINENO)
> +#define ALLOCINFO_FILTER_MASK_INACCURATE (1 << ALLOCINFO_FILTER_INACCURATE)
> #define ALLOCINFO_FILTER_MASK_MIN_SIZE (1 << ALLOCINFO_FILTER_MIN_SIZE)
> #define ALLOCINFO_FILTER_MASK_MAX_SIZE (1 << ALLOCINFO_FILTER_MAX_SIZE)
>
> diff --git a/lib/alloc_tag.c b/lib/alloc_tag.c
> index ddc6946f56ab..cbcd12c4ef9c 100644
> --- a/lib/alloc_tag.c
> +++ b/lib/alloc_tag.c
> @@ -249,6 +249,8 @@ static bool matches_filter(struct codetag *ct, struct allocinfo_filter *filter,
> struct alloc_tag_counters *counters,
> bool *fetched_counters)
> {
> + bool inaccurate;
> +
> if (!filter || !filter->mask)
> return true;
>
> @@ -275,6 +277,12 @@ static bool matches_filter(struct codetag *ct, struct allocinfo_filter *filter,
> ct->lineno != filter->fields.lineno)
> return false;
>
> + if (filter->mask & ALLOCINFO_FILTER_MASK_INACCURATE) {
> + inaccurate = !!(ct->flags & CODETAG_FLAG_INACCURATE);
> + if (inaccurate != !!(filter->fields.inaccurate))
> + return false;
> + }
> +
> if (filter->mask & (ALLOCINFO_FILTER_MASK_MIN_SIZE | ALLOCINFO_FILTER_MASK_MAX_SIZE)) {
> if (!*fetched_counters) {
> *counters = allocinfo_prefetch_counters(ct);
^ permalink raw reply
page: next (older) | prev (newer) | latest
- recent:[subjects (threaded)|topics (new)|topics (active)]
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox