* Re: [PATCH] fprobe: Add unregister_fprobe_sync() for synchronous unregistration
From: Masami Hiramatsu @ 2026-05-07 1:48 UTC (permalink / raw)
To: Steven Rostedt
Cc: Mathieu Desnoyers, Jonathan Corbet, linux-kernel,
linux-trace-kernel, linux-doc
In-Reply-To: <20260428142736.11f5211a@gandalf.local.home>
On Tue, 28 Apr 2026 14:27:36 -0400
Steven Rostedt <rostedt@goodmis.org> wrote:
> On Mon, 27 Apr 2026 21:09:58 +0900
> "Masami Hiramatsu (Google)" <mhiramat@kernel.org> wrote:
>
> > +/**
> > + * unregister_fprobe_sync() - Unregister fprobe synchronously with RCU grace period.
> > + * @fp: A fprobe data structure to be unregistered.
> > + *
> > + * Unregister fprobe (and remove ftrace hooks from the function entries) and
> > + * wait for the RCU grace period to finish. This is useful for preventing
> > + * the fprobe from being used after it is unregistered.
> > + *
> > + * Return 0 if @fp is unregistered successfully, -errno if not.
> > + */
> > +int unregister_fprobe_sync(struct fprobe *fp)
> > +{
> > + int ret;
> > +
> > + guard(mutex)(&fprobe_mutex);
> > + if (!fp || !fprobe_registered(fp))
> > + return -EINVAL;
> > +
> > + ret = unregister_fprobe_nolock(fp);
> > + if (ret)
> > + return ret;
> > +
> > + synchronize_rcu();
>
> Hmm, do we really need to hold the fprobe_mutex when doing the
> synchronize_rcu()? This could cause other updates to have to wait longer
> too.
Good catch! Indeed, there is no need to hold the mutex.
OK, let me update it.
Thanks,
>
> -- Steve
>
>
> > + return 0;
> > +}
> > +EXPORT_SYMBOL_GPL(unregister_fprobe_sync);
>
--
Masami Hiramatsu (Google) <mhiramat@kernel.org>
^ permalink raw reply
* Re: [PATCH net-next v3 1/2] dpll: add fractional frequency offset to pin-parent-device
From: Jakub Kicinski @ 2026-05-07 1:33 UTC (permalink / raw)
To: Ivan Vecera
Cc: netdev, Jiri Pirko, Andrew Lunn, Arkadiusz Kubalewski,
David S. Miller, Donald Hunter, Eric Dumazet, Jonathan Corbet,
Leon Romanovsky, Mark Bloch, Michal Schmidt, Paolo Abeni,
Pasi Vaananen, Petr Oros, Prathosh Satish, Saeed Mahameed,
Shuah Khan, Simon Horman, Tariq Toukan, Vadim Fedorenko,
linux-doc, linux-kernel, linux-rdma
In-Reply-To: <20260504155340.411063-2-ivecera@redhat.com>
On Mon, 4 May 2026 17:53:39 +0200 Ivan Vecera wrote:
> + At top level this represents the RX vs TX symbol rate
> + offset on the media associated with the pin.
Isn't this a hacky hack? I'd think that pin is in or out.
Having a freq offset between two pins or pin and parent's
ref lock makes sense. This new interpretation sounds like
we are trying to shove a difference between two pins into one?
> @@ -299,6 +299,10 @@ zl3073x_dpll_input_pin_ffo_get(const struct dpll_pin *dpll_pin, void *pin_priv,
> {
> struct zl3073x_dpll_pin *pin = pin_priv;
>
> + /* Only rx vs tx symbol rate FFO is supported */
> + if (dpll)
> + return -ENODATA;
> +
> *ffo = pin->freq_offset;
It's easy for driver authors to forget this sort of validation.
We should fail close, so it's better to have some "capability"
bits or something for the driver to opt into getting given format
of the call.
^ permalink raw reply
* Re: [PATCH] Documentation: fix typo and formattting in security/credentials.rst
From: Randy Dunlap @ 2026-05-07 0:36 UTC (permalink / raw)
To: Mayank Gite, Paul Moore
Cc: Serge Hallyn, Jonathan Corbet, Shuah Khan, linux-security-module,
linux-doc, linux-kernel
In-Reply-To: <20260506225925.271163-1-drapl0n.kernel@gmail.com>
Hi,
On 5/6/26 3:59 PM, Mayank Gite wrote:
> - Fixes a typo in "Keys and keyrings" section. Replaces "keying" with
> "keyring".
> - Updates formatting of keyring types.
>
> Signed-off-by: Mayank Gite <drapl0n.kernel@gmail.com>
Acked-by: Randy Dunlap <rdunlap@infradead.org>
Tested-by: Randy Dunlap <rdunlap@infradead.org>
> ---
In the future, right here, after that "---" line, it should say
something like
v2: use 'git send-email' so that that patch isn't corrupted
and in the Subject: it should say
[PATCH v2] ...
Thanks.
> Documentation/security/credentials.rst | 6 +++---
> 1 file changed, 3 insertions(+), 3 deletions(-)
>
> diff --git a/Documentation/security/credentials.rst b/Documentation/security/credentials.rst
> index d0191c8b8060..4996838491b1 100644
> --- a/Documentation/security/credentials.rst
> +++ b/Documentation/security/credentials.rst
> @@ -189,9 +189,9 @@ The Linux kernel supports the following types of credentials:
> be searched for the desired key. Each process may subscribe to a number
> of keyrings:
>
> - Per-thread keying
> - Per-process keyring
> - Per-session keyring
> + - Per-thread keyring
> + - Per-process keyring
> + - Per-session keyring
>
> When a process accesses a key, if not already present, it will normally be
> cached on one of these keyrings for future accesses to find.
--
~Randy
^ permalink raw reply
* [PATCH] Documentation: fix typo and formattting in security/credentials.rst
From: Mayank Gite @ 2026-05-06 22:59 UTC (permalink / raw)
To: Paul Moore
Cc: Mayank Gite, Serge Hallyn, Jonathan Corbet, Shuah Khan,
linux-security-module, linux-doc, linux-kernel
- Fixes a typo in "Keys and keyrings" section. Replaces "keying" with
"keyring".
- Updates formatting of keyring types.
Signed-off-by: Mayank Gite <drapl0n.kernel@gmail.com>
---
Documentation/security/credentials.rst | 6 +++---
1 file changed, 3 insertions(+), 3 deletions(-)
diff --git a/Documentation/security/credentials.rst b/Documentation/security/credentials.rst
index d0191c8b8060..4996838491b1 100644
--- a/Documentation/security/credentials.rst
+++ b/Documentation/security/credentials.rst
@@ -189,9 +189,9 @@ The Linux kernel supports the following types of credentials:
be searched for the desired key. Each process may subscribe to a number
of keyrings:
- Per-thread keying
- Per-process keyring
- Per-session keyring
+ - Per-thread keyring
+ - Per-process keyring
+ - Per-session keyring
When a process accesses a key, if not already present, it will normally be
cached on one of these keyrings for future accesses to find.
--
2.53.0
^ permalink raw reply related
* Re: [PATCH v2 2/2] hwmon: add initial support for AMD PROM21 xHCI temperature sensor
From: Jihong Min @ 2026-05-06 22:52 UTC (permalink / raw)
To: Randy Dunlap, Jihong Min, Greg Kroah-Hartman, Mathias Nyman
Cc: Guenter Roeck, Jonathan Corbet, Shuah Khan, Mario Limonciello,
Basavaraj Natikar, linux-usb, linux-hwmon, linux-doc, linux-pci,
linux-kernel
In-Reply-To: <5a61ad36-d754-4ab9-8a56-83bccc1397f2@infradead.org>
> It sorta looks like these entries are supposed to be maintained in
> alphabetical order, but that new entry is not.
Yes, you are right. I also noticed that but it seems I pasted it in the
wrong place.
Fixed this locally for v3 by moving prom21-hwmon after powr1220 and next
to pt5161l.
Thank you,
Jihong Min
On 5/7/26 07:17, Randy Dunlap wrote:
>
> On 5/6/26 1:40 PM, Jihong Min wrote:
>> diff --git a/Documentation/hwmon/index.rst b/Documentation/hwmon/index.rst
>> index 8b655e5d6b68..0d85b78596cf 100644
>> --- a/Documentation/hwmon/index.rst
>> +++ b/Documentation/hwmon/index.rst
>> @@ -215,6 +215,7 @@ Hardware Monitoring Kernel Drivers
>> peci-dimmtemp
>> pmbus
>> powerz
>> + prom21-hwmon
>> powr1220
>> pt5161l
>> pxe1610
> It sorta looks like these entries are supposed to be maintained in alphabetical
> order, but that new entry is not.
>
^ permalink raw reply
* Re: [PATCH v2] scripts/kernel-doc: Detect mismatched inline member documentation tags
From: Randy Dunlap @ 2026-05-06 22:51 UTC (permalink / raw)
To: Shuicheng Lin, linux-doc; +Cc: Jani Nikula, linux-kernel, intel-xe
In-Reply-To: <20260501160800.4043276-1-shuicheng.lin@intel.com>
Hi,
On 5/1/26 9:08 AM, Shuicheng Lin wrote:
> Add validation in check_sections() to verify that inline member
> documentation tags (/** @member: description */) match actual struct/union
> member names. Previously, kernel-doc only validated section headers against
> the parameter list, but inline doc tags stored in parameterdescs were never
> cross-checked, allowing stale or mistyped member names to go undetected.
>
> The new check iterates over parameterdescs keys and warns about any that
> don't appear in the parameter list, catching issues like renamed struct
> members where the documentation tag was not updated to match.
>
> This catches real issues such as:
> - xe_bo_types.h: @atomic_access (missing struct prefix, should be
> @attr.atomic_access)
> - xe_device_types.h: @usm.asid (member is actually asid_to_vm)
>
> Variadic arguments documented as ``@args...:`` are stored in
> parameterdescs under the unstripped key (e.g. ``args...``), while
> push_parameter() strips the trailing ``...`` before appending to
> parameterlist (e.g. ``args``). Treat the stripped form as a match so
> the new loop doesn't emit a false-positive excess-parameter warning for
> a properly documented named variadic parameter. The bare ``@...:`` form
> is unaffected because push_parameter() does not strip when the name is
> exactly three characters.
>
> v2: Skip variadic parameters whose documented key ends with ``...`` and
> whose stripped name is in parameterlist, to avoid false-positive
> "Excess function parameter 'args...'" warnings on macros like
> ``#define foo(fmt, args...)`` documented with ``@args...:``.
>
> Assisted-by: Claude:claude-opus-4.6
> Signed-off-by: Shuicheng Lin <shuicheng.lin@intel.com>
> ---
> Cc: Jani Nikula <jani.nikula@linux.intel.com>
> Cc: linux-doc@vger.kernel.org
> Cc: linux-kernel@vger.kernel.org
> Cc: intel-xe@lists.freedesktop.org
> ---
This patch mostly works for me. I do see one issue, but maybe it wasn't
meant to be addressed by this patch:
If I modify kthread_create() in include/linux/kthread.h to change
its @arg: to @args:, and then run scripts/kernel-doc -none -Wall, I get:
Warning: init/megaexcess.h:63 Excess function parameter 'args' description in 'kthread_create'
(that part is good)
but I would also expect to get a warning about @arg not being described.
> tools/lib/python/kdoc/kdoc_parser.py | 36 ++++++++++++++++++++++++++++
> 1 file changed, 36 insertions(+)
>
> diff --git a/tools/lib/python/kdoc/kdoc_parser.py b/tools/lib/python/kdoc/kdoc_parser.py
> index ca00695b47b3..884c6bf56d25 100644
> --- a/tools/lib/python/kdoc/kdoc_parser.py
> +++ b/tools/lib/python/kdoc/kdoc_parser.py
> @@ -673,6 +673,42 @@ class KernelDoc:
> self.emit_msg(ln,
> f"Excess {dname} '{section}' description in '{decl_name}'")
>
> + #
> + # Check that documented parameter names (from doc comments, including
> + # inline ``/** @member: */`` tags) actually match real members in
> + # the declaration. This catches mismatched or stale kernel-doc
> + # member tags that don't correspond to any actual struct/union
> + # member or function parameter.
> + #
> + for param_name, desc in self.entry.parameterdescs.items():
> + # Skip auto-generated entries from push_parameter()
> + if desc == self.undescribed:
> + continue
> + if desc in ("no arguments", "anonymous\n", "variable arguments"):
> + continue
> + if param_name.startswith("{unnamed_"):
> + continue
> + if param_name in self.entry.parameterlist:
> + continue
> + #
> + # Variadic arguments documented as ``@args...:`` are stored in
> + # parameterdescs under the unstripped key (e.g. ``args...``),
> + # while push_parameter() strips the trailing ``...`` before
> + # appending to parameterlist (e.g. ``args``). Treat the
> + # stripped form as a match so this loop doesn't emit a false
> + # positive for a properly documented variadic parameter.
> + #
> + if param_name.endswith("...") and \
> + param_name[:-3] in self.entry.parameterlist:
> + continue
> +
> + if decl_type == 'function':
> + dname = f"{decl_type} parameter"
> + else:
> + dname = f"{decl_type} member"
> + self.emit_msg(ln,
> + f"Excess {dname} '{param_name}' description in '{decl_name}'")
> +
> def check_return_section(self, ln, declaration_name, return_type):
> """
> If the function doesn't return void, warns about the lack of a
--
~Randy
^ permalink raw reply
* Re: [PATCH v2 2/2] hwmon: add initial support for AMD PROM21 xHCI temperature sensor
From: Jihong Min @ 2026-05-06 22:41 UTC (permalink / raw)
To: Michal Pecio, Jihong Min, Mario Limonciello
Cc: Greg Kroah-Hartman, Mathias Nyman, Guenter Roeck, Jonathan Corbet,
Shuah Khan, Basavaraj Natikar, linux-usb, linux-hwmon, linux-doc,
linux-pci, linux-kernel
In-Reply-To: <20260506233332.664f220c.michal.pecio@gmail.com>
> I think this commit message and certainly the Kconfig help text should
> include full name of the chip and perhaps its official marketing names
> too, so that people better understand what hardware is supported.
>
> So: "AMD Promontory 21 chipset" and "AM5 6xx/8xx series chipsets", or
> whatever they are called by AMD and motherboard vendors.
Addressed locally for v3. I changed the commit message, Kconfig prompt/help
text, and hwmon documentation to use the full name, "AMD Promontory 21
(PROM21)".
I avoided putting chipset marketing names directly into the Kconfig text and
commit subject because some AMD 6xx/8xx series chipsets can be built
from more
than one PROM21 IP in a daisy-chained configuration, including more than one
PROM21 xHCI controller. I described that relationship in the hwmon
documentation instead.
> Is there any documentation of the index/data registers themselves?
I am not aware of public AMD documentation for the PROM21 vendor index/data
registers or the temperature selector.
For my initial validation on an X870E system with two PROM21 xHCI
controllers,
I passed one PROM21 xHCI controller through to a Windows VM, left USB
traffic
idle, and let a Windows monitoring utility poll the controller temperature.
From the Linux host I monitored that controller's PCI MMIO BAR with
read-only
accesses. The vendor index register repeatedly held the same selector value,
and the adjacent data register exposed a stable low 8-bit value. That value
matched the reported PROM21 xHCI temperature after the conversion formula
below.
> Any potential danger that something else (FW? SMM?) uses them too?
I did not find any other in-kernel user of this PROM21 vendor index/data
register pair or the temperature selector.
The driver only serializes its own accesses. It saves the previous index,
selects the temperature register, reads the data register, restores the
previous index, and keeps the sequence short. This avoids leaving the vendor
index/data pair in a different state for other OS code.
This cannot synchronize against firmware or SMM. I cannot rule out such
access
without AMD documentation or confirmation, so I would appreciate AMD
feedback
on whether this PROM21 vendor index/data register pair is safe for OS
polling.
I also tested concurrent temperature reads while USB traffic was active
on the
same controller, including fio against an external USB storage device and
isochronous USB audio playback/capture. I did not observe USB transfer
errors
or audio glitches in those tests.
> Could make sense to describe methodology, particularly in case some
> people would come and question the formula.
>
> How was actual chip temperature measured?
> Was the output compared with any other (Windows?) utilities?
>
> People will be comparing these results and possibly trying to draw
> some conclusions, like OMG Linux runs this chip 8°C hotter, should
> I demand a full refund of my free Ubuntu download????!!!?
After identifying the register pair, I used the same validation setup to
derive
the conversion formula by comparing the observed raw MMIO register value
against HWiNFO64's reported PROM21 xHCI temperature on Windows.
This worked because the PROM21 xHCI temperature is very stable at idle
and the
sensor appears to have low resolution, so the value usually stays unchanged
long enough to compare both sides reliably.
> Is such behavior useful?
>
> Maybe the driver could just disable runtime PM while it's loaded.
and:
> I'd encourage what we do in amdgpu for dGPUs. The hwmon files will
> return an error code (I forget which code) when the device is in runtime
> PM when called. Don't explicitly wake it otherwise.
>
> This prevents someone installing a sensor monitoring application and
> that application "being the only thing" keeping the dGPU awake. If it's
> awake already for other reasons (like being used) then return valid data
> to the applications.
I changed the local v3 branch to follow the amdgpu-style behavior by
default.
The driver now does not wake the xHCI PCI device for a normal hwmon read. If
the device is already active, the read returns valid data. If the device is
suspended, the read returns -EPERM, matching the error code currently
returned
by amdgpu's pm_runtime_get_if_active() based path. I used -EPERM to
match the
current amdgpu precedent, but I can change the errno if maintainers prefer a
different one for this driver.
I kept the allow_pm_switch module parameter for now, but changed its
default to
false. With the default setting, hwmon reads do not change the device
runtime PM
state. Setting allow_pm_switch=Y explicitly opts into waking the xHCI PCI
device for temperature reads.
Thank you,
Jihong Min
On 5/7/26 06:33, Michal Pecio wrote:
> On Thu, 7 May 2026 05:40:34 +0900, Jihong Min wrote:
>> AMD PROM21 xHCI controllers expose an 8-bit temperature value
> I think this commit message and certainly the Kconfig help text should
> include full name of the chip and perhaps its official marketing names
> too, so that people better understand what hardware is supported.
>
> So: "AMD Promontory 21 chipset" and "AM5 6xx/8xx series chipsets", or
> whatever they are called by AMD and motherboard vendors.
>
>> through a vendor-specific index/data register pair in the xHCI PCI
>> MMIO BAR region. Add an auxiliary hwmon driver for AMD 1022:43fd
>> controllers and bind it to the xhci_pci.hwmon auxiliary device
>> created by xhci-pci.
>>
>> The read path verifies the parent PCI function and uses the
>> initialized xHCI HCD MMIO mapping. The vendor index register is at
>> byte offset 0x3000 from the xHCI MMIO BAR base and the vendor data
>> register is at byte offset 0x3008. The driver writes register selector
>> 0x0001e520 to the index register, reads the raw temperature value from
>> the low 8 bits of the data register, and restores the previous index
>> before returning. Expose temp1_input and an xHCI label through hwmon.
>>
>> Register the hwmon device under the parent PCI function so userspace
>> reports it as a PCI adapter, while the auxiliary driver still owns the
>> hwmon lifetime and unregisters it from the auxiliary remove path.
>>
>> No public AMD reference is available for this value.
> Is there any documentation of the index/data registers themselves?
>
> Any potential danger that something else (FW? SMM?) uses them too?
>
>> The conversion formula is derived from observed temperature readings:
>>
>> temp[C] = raw * 0.9066 - 78.624
> Could make sense to describe methodology, particularly in case some
> people would come and question the formula.
>
> How was actual chip temperature measured?
> Was the output compared with any other (Windows?) utilities?
>
> People will be comparing these results and possibly trying to draw
> some conclusions, like OMG Linux runs this chip 8°C hotter, should
> I demand a full refund of my free Ubuntu download????!!!?
>
>> The temperature register did not return a valid value while the xHCI
>> PCI function was suspended in testing. Keep the existing behavior by
>> default and allow temperature reads to wake the xHCI PCI device. Add an
>> allow_pm_switch module parameter so users can disable that behavior;
>> when disabled, reads do not wake the device and return -EAGAIN if it is
>> suspended.
> Is such behavior useful?
>
> Maybe the driver could just disable runtime PM while it's loaded.
>
>> Document the supported device, register access, conversion formula,
>> module parameter, sysfs attributes, and sysfs lookup method.
>>
>> Assisted-by: Codex:gpt-5.5
>> Signed-off-by: Jihong Min <hurryman2212@gmail.com>
^ permalink raw reply
* Re: [PATCH RFC] printk: remove BOOT_PRINTK_DELAY
From: Andrew Murray @ 2026-05-06 22:37 UTC (permalink / raw)
To: Petr Mladek
Cc: Jonathan Corbet, Shuah Khan, Russell King, Florian Fainelli,
Ray Jui, Scott Branden, Broadcom internal kernel review list,
Steven Rostedt, John Ogness, Sergey Senozhatsky, Andrew Morton,
Sebastian Andrzej Siewior, Randy Dunlap, Clark Williams,
linux-doc, linux-kernel, linux-arm-kernel, linux-rpi-kernel,
linux-rt-devel, Linus Torvalds
In-Reply-To: <afn-H1EQJxnDs0BZ@pathway.suse.cz>
On Tue, 5 May 2026 at 15:26, Petr Mladek <pmladek@suse.com> wrote:
>
> On Tue 2026-05-05 14:45:00, Andrew Murray wrote:
> > The CONFIG_BOOT_PRINTK_DELAY option enables support for the boot_delay
> > kernel parameter, this allows for a configurable delay to be added before
> > each and every printk is emitted. This is DEBUG_KERNEL option that is
> > helpful for debugging as kernel output can be slowed down during boot
> > allowing messages to be seen before scrolling off the screen, or to
> > correlate timing between some physical event and console output.
> >
> > However, since the introduction of nbcon and the legacy printer thread for
> > PREEMPT_RT kernels, printk records are now emited to the console
> > asynchronously to the caller of printk and its boot_delay. The delay added
> > by boot_delay continues to slow down the calling process, but may not have
> > any impact to the rate in which records are emited to the console. For
> > example, if delay_use is set to 100ms, and the printer thread has a
> > backlog of more than 100ms, perhaps due to a slow serial console, then the
> > records will appear to be printed without any delay between them.
> >
> > It would be unhelpful to add a delay to the printer thread, and it would
> > not be possible to disallow selection of CONFIG_BOOT_PRINTK_DELAY at build
> > time as it's not possible to detect which consoles are nbcon enabled at
> > build time. Therefore, let's remove this feature.
>
> Heh, Randy proposed to remove "boot_delay" few days ago.
> This RFC goes even further and remove both "boot_delay" and
> "printk_delay".
Apologies, I didn't see this. I'll co-ordinate with Randy.
>
> Honestly, I do not feel comfortable by this. The delay seems to
> be handy when there is only graphical console. I would suggest
> to do:
>
> 1. Obsolete "boot_delay" with "printk_delay" as
> proposed in Randy's thread, see
> https://lore.kernel.org/all/afn2sYKKsqG4QBVX@pathway.suse.cz/
Your suggestion was:
" 1. Add "printk_delay" early_param() which would allow
to set "printk_delay_msec" via command line."
And I assume the intent is to replicate the functionality of
boot_delay, by allowing printk_delay to be used to introduce delays
from early_param time? Thus deprecating delay_use.
" 2. Modify boot_delay_setup() to set "printk_delay_msec" as well.
In addition, it might print a message that it has been
obsoleted by "printk_delay" and will be removed."
Given the intent may be to deprecate boot_delay, I'm not sure that
setting printk_delay_msec as well would be beneficial, as this would
extend its functionality to add delays beyond SYSTEM_RUNNING which is
where boot_delay stops. Unless you mean to use boot_delay as an alias
to an early_param hook for printk_delay?
It seems that there are also differences in behavior between
printk_delay and boot_use, with printk_delay unconditionally adding
delays to all printks, and delay_use which considers the loglevel.
With this approach, existing delay_use users will have the
inconvenience of having printk delays post SYSTEM_RUNNING. However, as
this is a DEBUG_KERNEL feature, maybe we don't need to preserve
behavior. Additionally, with the proposed changes for moving the
delays from printk time to console_flush_one_record time, the impact
for an uninformed user isn't as drastic.
>
> 2. Move printk_delay() from vprintk_emit() to
> console_emit_next_record() and nbcon_emit_next_record().
>
> For nbcon console, even better would be to use a sleeping
> wait in nbcon_kthread_func(). But it would need some
> changes to call it only when a record was really emitted.
> Also we would need to use the busy wait in
> __nbcon_atomic_flush_pending_con().
This makes sense.
If the use case (in a post kthread printk thread world), is only
relevant for graphical consoles, then I do wonder if printk_delay and
boot_delay can be replaced with a more specific solution? Now that we
have printk threads, the time in which a printk is presented to the
user may not relate to when it was created, and I fear people may
continue to debug issues that rely on that assumption.
I think the most pragmatic solution for now is:
- Move the printk delay to the point where the printk is actually
printed (e.g. console_flush_one_record and descendants)
- Add an early_param to allow for printk_delay_msec to be set
- Deprecate boot_delay, by using it as an alias for setting
printk_delay_msec, and include a user mesage that it is being
deprecated and that it now extends to beyond boot (which could impact
performance on non PREEMPT_RT and non nbcon systems)
- Update printk_delay function to use the appropiate mechanism to
delay based on stage of boot and using printk_delay_msec instead of
boot_delay.
If that makes sense I can fashion a patchset.
>
> IMHO, the only drawback might be that the delay might be multiplied
> when more consoles are registered. But I would ignore it. People
> would use this option only when the graphical console is the only
> one. It does not make sense for serial or network consoles.
>
> Best Regards,
> Petr
Thanks,
Andrew Murray
^ permalink raw reply
* Re: [PATCH] docs: kernel-doc: python: strip __counted_by_ptr macro
From: Randy Dunlap @ 2026-05-06 22:24 UTC (permalink / raw)
To: Tudor Ambarus, Mauro Carvalho Chehab, Kees Cook,
Gustavo A. R. Silva
Cc: linux-kernel, linux-doc, linux-hardening, peter.griffin,
andre.draszik, willmcvicker, jyescas, krzk, kernel-team
In-Reply-To: <20260506-kdoc-__counted_by_ptr-v1-1-70763486871f@linaro.org>
On 5/6/26 4:04 AM, Tudor Ambarus wrote:
> The `__counted_by_ptr` macro was recently introduced [1] to extend
> bounds checking semantics to standard dynamically allocated pointers.
>
> However, the new Python implementation of kernel-doc does not currently
> recognize it as a compiler attribute. When kernel-doc encounters a
> struct member annotated with this macro, it fails to parse the variable
> name correctly, resulting in false-positive warnings like:
>
> Warning: ... struct member '__counted_by_ptr(cmdcnt' not described
>
> Add `__counted_by_ptr` to the `struct_xforms` regex list so it gets
> safely stripped out during the parsing phase, mirroring the existing
> behavior for `__counted_by`. Update the corresponding unit tests.
>
> Link: https://git.kernel.org/torvalds/c/150a04d817d8 [1]
> Signed-off-by: Tudor Ambarus <tudor.ambarus@linaro.org>
Acked-by: Randy Dunlap <rdunlap@infradead.org>
Tested-by: Randy Dunlap <rdunlap@infradead.org>
Thanks.
> ---
> tools/lib/python/kdoc/xforms_lists.py | 1 +
> tools/unittests/test_cmatch.py | 1 +
> 2 files changed, 2 insertions(+)
>
> diff --git a/tools/lib/python/kdoc/xforms_lists.py b/tools/lib/python/kdoc/xforms_lists.py
> index f6ea9efb11ae..118156ea8cd2 100644
> --- a/tools/lib/python/kdoc/xforms_lists.py
> +++ b/tools/lib/python/kdoc/xforms_lists.py
> @@ -29,6 +29,7 @@ class CTransforms:
> (CMatch("__aligned"), ""),
> (CMatch("__counted_by"), ""),
> (CMatch("__counted_by_(le|be)"), ""),
> + (CMatch("__counted_by_ptr"), ""),
> (CMatch("__guarded_by"), ""),
> (CMatch("__pt_guarded_by"), ""),
> (CMatch("__packed"), ""),
> diff --git a/tools/unittests/test_cmatch.py b/tools/unittests/test_cmatch.py
> index 7b996f83784d..109141cd2ab8 100755
> --- a/tools/unittests/test_cmatch.py
> +++ b/tools/unittests/test_cmatch.py
> @@ -320,6 +320,7 @@ class TestSubWithLocalXforms(TestCaseDiff):
> (CMatch('__aligned'), ' '),
> (CMatch('__counted_by'), ' '),
> (CMatch('__counted_by_(le|be)'), ' '),
> + (CMatch('__counted_by_ptr'), ' '),
> (CMatch('__guarded_by'), ' '),
> (CMatch('__pt_guarded_by'), ' '),
>
>
> ---
> base-commit: 254f49634ee16a731174d2ae34bc50bd5f45e731
> change-id: 20260506-kdoc-__counted_by_ptr-1e206f3f1dc1
>
> Best regards,
--
~Randy
^ permalink raw reply
* Re: [PATCH v2 2/2] hwmon: add initial support for AMD PROM21 xHCI temperature sensor
From: Randy Dunlap @ 2026-05-06 22:17 UTC (permalink / raw)
To: Jihong Min, Greg Kroah-Hartman, Mathias Nyman
Cc: Guenter Roeck, Jonathan Corbet, Shuah Khan, Mario Limonciello,
Basavaraj Natikar, linux-usb, linux-hwmon, linux-doc, linux-pci,
linux-kernel
In-Reply-To: <2e2ea249b30168a2eab62fc110c226a511f21bf2.1778099627.git.hurryman2212@gmail.com>
On 5/6/26 1:40 PM, Jihong Min wrote:
> diff --git a/Documentation/hwmon/index.rst b/Documentation/hwmon/index.rst
> index 8b655e5d6b68..0d85b78596cf 100644
> --- a/Documentation/hwmon/index.rst
> +++ b/Documentation/hwmon/index.rst
> @@ -215,6 +215,7 @@ Hardware Monitoring Kernel Drivers
> peci-dimmtemp
> pmbus
> powerz
> + prom21-hwmon
> powr1220
> pt5161l
> pxe1610
It sorta looks like these entries are supposed to be maintained in alphabetical
order, but that new entry is not.
--
~Randy
^ permalink raw reply
* Re: [PATCH v2 1/2] usb: xhci-pci: add generic auxiliary device interface
From: Jihong Min @ 2026-05-06 21:42 UTC (permalink / raw)
To: Michal Pecio, Jihong Min
Cc: Greg Kroah-Hartman, Mathias Nyman, Guenter Roeck, Jonathan Corbet,
Shuah Khan, Mario Limonciello, Basavaraj Natikar, linux-usb,
linux-hwmon, linux-doc, linux-pci, linux-kernel
In-Reply-To: <20260506231541.32f88ce1.michal.pecio@gmail.com>
Thank you.
I've changed the code by removing the preprocessor macros and protecting
the two entry points with `if (IS_ENABLED(CONFIG_USB_XHCI_PCI_AUXDEV))`,
for v3.
Jihong Min
On 5/7/26 06:15, Michal Pecio wrote:
> On Thu, 7 May 2026 05:40:33 +0900, Jihong Min wrote:
>> Some xHCI PCI controllers expose controller-specific functionality that is
>> not part of generic xHCI operation and is better handled by optional child
>> drivers in other subsystems. Add a small auxiliary device registration path
>> for selected xHCI PCI controllers.
>>
>> The initial table creates an xhci_pci.hwmon auxiliary device for AMD
>> 1022:43fd controllers. Store the created auxiliary device in devres so the
>> xhci-pci remove path destroys it before HCD teardown. Use a
>> PCI-domain-qualified id so auxiliary device names remain unique across PCI
>> domains.
>>
>> This keeps xhci-pci responsible only for publishing selected controller
>> functions while allowing subsystem-specific drivers to bind through the
>> auxiliary bus.
>>
>> Assisted-by: Codex:gpt-5.5
>> Signed-off-by: Jihong Min <hurryman2212@gmail.com>
>> ---
>> drivers/usb/host/Kconfig | 10 ++++
>> drivers/usb/host/xhci-pci.c | 114 ++++++++++++++++++++++++++++++++++++
>> 2 files changed, 124 insertions(+)
>>
>> diff --git a/drivers/usb/host/Kconfig b/drivers/usb/host/Kconfig
>> index 0a277a07cf70..e0c2c7ac5c97 100644
>> --- a/drivers/usb/host/Kconfig
>> +++ b/drivers/usb/host/Kconfig
>> @@ -42,6 +42,16 @@ config USB_XHCI_PCI
>> depends on USB_PCI
>> default y
>>
>> +config USB_XHCI_PCI_AUXDEV
>> + bool "xHCI PCI auxiliary device support"
>> + depends on USB_XHCI_PCI
>> + select AUXILIARY_BUS
>> + help
>> + This enables xHCI PCI support for registering auxiliary devices
>> + for selected controllers. It is used by optional child drivers
>> + that bind to xHCI PCI controller-specific functionality through
>> + the auxiliary bus.
>> +
>> config USB_XHCI_PCI_RENESAS
>> tristate "Support for additional Renesas xHCI controller with firmware"
>> depends on USB_XHCI_PCI
>> diff --git a/drivers/usb/host/xhci-pci.c b/drivers/usb/host/xhci-pci.c
>> index 585b2f3117b0..1ab27d2182eb 100644
>> --- a/drivers/usb/host/xhci-pci.c
>> +++ b/drivers/usb/host/xhci-pci.c
>> @@ -8,6 +8,8 @@
>> * Some code borrowed from the Linux EHCI driver.
>> */
>>
>> +#include <linux/auxiliary_bus.h>
>> +#include <linux/device/devres.h>
>> #include <linux/pci.h>
>> #include <linux/slab.h>
>> #include <linux/module.h>
>> @@ -103,6 +105,114 @@ static int xhci_pci_run(struct usb_hcd *hcd);
>> static int xhci_pci_update_hub_device(struct usb_hcd *hcd, struct usb_device *hdev,
>> struct usb_tt *tt, gfp_t mem_flags);
>>
>> +#if IS_ENABLED(CONFIG_USB_XHCI_PCI_AUXDEV)
>> +static const struct {
>> + struct pci_device_id id;
>> + const char *aux_dev_name;
>> +} pci_ids_have_aux[] = {
>> + {
>> + .id = { PCI_DEVICE(PCI_VENDOR_ID_AMD, 0x43fd) }, /* PROM21 xHCI */
>> + .aux_dev_name = "hwmon",
>> + },
>> + { /* end: all zeroes */ }
>> +};
>> +
>> +struct xhci_pci_aux_devres {
>> + struct auxiliary_device *auxdev;
>> +};
>> +
>> +static bool xhci_pci_aux_match_id(const struct pci_device_id *id,
>> + const struct pci_dev *pdev)
>> +{
>> + if (id->vendor != PCI_ANY_ID && id->vendor != pdev->vendor)
>> + return false;
>> + if (id->device != PCI_ANY_ID && id->device != pdev->device)
>> + return false;
>> + if (id->subvendor != PCI_ANY_ID &&
>> + id->subvendor != pdev->subsystem_vendor)
>> + return false;
>> + if (id->subdevice != PCI_ANY_ID &&
>> + id->subdevice != pdev->subsystem_device)
>> + return false;
>> +
>> + return !((id->class ^ pdev->class) & id->class_mask);
>> +}
>> +
>> +static const char *xhci_pci_aux_dev_name(struct pci_dev *pdev)
>> +{
>> + int i;
>> +
>> + for (i = 0; pci_ids_have_aux[i].aux_dev_name; i++) {
>> + if (xhci_pci_aux_match_id(&pci_ids_have_aux[i].id, pdev))
>> + return pci_ids_have_aux[i].aux_dev_name;
>> + }
>> +
>> + return NULL;
>> +}
>> +
>> +static void xhci_pci_aux_devres_release(struct device *dev, void *res)
>> +{
>> + struct xhci_pci_aux_devres *devres = res;
>> +
>> + if (devres->auxdev)
>> + auxiliary_device_destroy(devres->auxdev);
>> +}
>> +
>> +static void xhci_pci_try_add_aux_device(struct pci_dev *pdev)
>> +{
>> + struct xhci_pci_aux_devres *devres;
>> + struct auxiliary_device *auxdev;
>> + const char *aux_dev_name;
>> +
>> + aux_dev_name = xhci_pci_aux_dev_name(pdev);
>> + if (!aux_dev_name)
>> + return;
>> +
>> + devres = devres_alloc(xhci_pci_aux_devres_release, sizeof(*devres),
>> + GFP_KERNEL);
>> + if (!devres) {
>> + dev_warn(&pdev->dev,
>> + "failed to allocate auxiliary device state\n");
>> + return;
>> + }
>> +
>> + auxdev = auxiliary_device_create(&pdev->dev, KBUILD_MODNAME,
>> + aux_dev_name, NULL,
>> + (pci_domain_nr(pdev->bus) << 16) |
>> + pci_dev_id(pdev));
>> + if (!auxdev) {
>> + devres_free(devres);
>> + dev_warn(&pdev->dev, "failed to add %s auxiliary device\n",
>> + aux_dev_name);
>> + return;
>> + }
>> +
>> + devres->auxdev = auxdev;
>> + devres_add(&pdev->dev, devres);
>> +}
>> +
>> +static void xhci_pci_try_remove_aux_device(struct pci_dev *pdev)
>> +{
>> + struct xhci_pci_aux_devres *devres;
>> +
>> + devres = devres_find(&pdev->dev, xhci_pci_aux_devres_release, NULL,
>> + NULL);
>> + if (!devres || !devres->auxdev)
>> + return;
>> +
>> + auxiliary_device_destroy(devres->auxdev);
>> + devres->auxdev = NULL;
>> +}
>> +#else
>> +static inline void xhci_pci_try_add_aux_device(struct pci_dev *pdev)
>> +{
>> +}
>> +
>> +static inline void xhci_pci_try_remove_aux_device(struct pci_dev *pdev)
>> +{
>> +}
>> +#endif
>> +
>> static const struct xhci_driver_overrides xhci_pci_overrides __initconst = {
>> .reset = xhci_pci_setup,
>> .start = xhci_pci_run,
>> @@ -677,6 +787,8 @@ int xhci_pci_common_probe(struct pci_dev *dev, const struct pci_device_id *id)
>> if (device_property_read_bool(&dev->dev, "ti,pwron-active-high"))
>> pci_clear_and_set_config_dword(dev, 0xE0, 0, 1 << 22);
>>
>> + xhci_pci_try_add_aux_device(dev);
> Is it considered acceptable to add
>
> if (IS_ENABLED(CONFIG_USB_XHCI_PCI_AUXDEV))
>
> before this call, remove #ifdef around the definitions of the auxdev
> functions and rely on dead code elimination to clean them up?
>
> We already have a similar trick with CONFIG_USB_XHCI_PCI_RENESAS here
> and it seemed to be working, though the amount of conditional code is
> much lower and so is the potential risk.
>
> The reason for doing it this way was because Greg doesn't like #ifdefs
> in .c files, and neither do static analyzers like them.
>
>> +
>> return 0;
>>
>> put_usb3_hcd:
>> @@ -713,6 +825,8 @@ void xhci_pci_remove(struct pci_dev *dev)
>> xhci = hcd_to_xhci(pci_get_drvdata(dev));
>> set_power_d3 = xhci->quirks & XHCI_SPURIOUS_WAKEUP;
>>
>> + xhci_pci_try_remove_aux_device(dev);
>> +
>> xhci->xhc_state |= XHCI_STATE_REMOVING;
>>
>> if (pci_choose_state(dev, PMSG_SUSPEND) == PCI_D0)
>> --
>> 2.53.0
>>
^ permalink raw reply
* Re: [PATCH v2 2/2] hwmon: add initial support for AMD PROM21 xHCI temperature sensor
From: Mario Limonciello @ 2026-05-06 21:36 UTC (permalink / raw)
To: Michal Pecio, Jihong Min
Cc: Greg Kroah-Hartman, Mathias Nyman, Guenter Roeck, Jonathan Corbet,
Shuah Khan, Basavaraj Natikar, linux-usb, linux-hwmon, linux-doc,
linux-pci, linux-kernel
In-Reply-To: <20260506233332.664f220c.michal.pecio@gmail.com>
On 5/6/26 16:33, Michal Pecio wrote:
> On Thu, 7 May 2026 05:40:34 +0900, Jihong Min wrote:
>> AMD PROM21 xHCI controllers expose an 8-bit temperature value
>
> I think this commit message and certainly the Kconfig help text should
> include full name of the chip and perhaps its official marketing names
> too, so that people better understand what hardware is supported.
>
> So: "AMD Promontory 21 chipset" and "AM5 6xx/8xx series chipsets", or
> whatever they are called by AMD and motherboard vendors.
>
>> through a vendor-specific index/data register pair in the xHCI PCI
>> MMIO BAR region. Add an auxiliary hwmon driver for AMD 1022:43fd
>> controllers and bind it to the xhci_pci.hwmon auxiliary device
>> created by xhci-pci.
>>
>> The read path verifies the parent PCI function and uses the
>> initialized xHCI HCD MMIO mapping. The vendor index register is at
>> byte offset 0x3000 from the xHCI MMIO BAR base and the vendor data
>> register is at byte offset 0x3008. The driver writes register selector
>> 0x0001e520 to the index register, reads the raw temperature value from
>> the low 8 bits of the data register, and restores the previous index
>> before returning. Expose temp1_input and an xHCI label through hwmon.
>>
>> Register the hwmon device under the parent PCI function so userspace
>> reports it as a PCI adapter, while the auxiliary driver still owns the
>> hwmon lifetime and unregisters it from the auxiliary remove path.
>>
>> No public AMD reference is available for this value.
>
> Is there any documentation of the index/data registers themselves?
>
> Any potential danger that something else (FW? SMM?) uses them too?
>
>> The conversion formula is derived from observed temperature readings:
>>
>> temp[C] = raw * 0.9066 - 78.624
>
> Could make sense to describe methodology, particularly in case some
> people would come and question the formula.
>
> How was actual chip temperature measured?
> Was the output compared with any other (Windows?) utilities?
>
> People will be comparing these results and possibly trying to draw
> some conclusions, like OMG Linux runs this chip 8°C hotter, should
> I demand a full refund of my free Ubuntu download????!!!?
>
>> The temperature register did not return a valid value while the xHCI
>> PCI function was suspended in testing. Keep the existing behavior by
>> default and allow temperature reads to wake the xHCI PCI device. Add an
>> allow_pm_switch module parameter so users can disable that behavior;
>> when disabled, reads do not wake the device and return -EAGAIN if it is
>> suspended.
>
> Is such behavior useful?
>
> Maybe the driver could just disable runtime PM while it's loaded.
I'd encourage what we do in amdgpu for dGPUs. The hwmon files will
return an error code (I forget which code) when the device is in runtime
PM when called. Don't explicitly wake it otherwise.
This prevents someone installing a sensor monitoring application and
that application "being the only thing" keeping the dGPU awake. If it's
awake already for other reasons (like being used) then return valid data
to the applications.
>
>>
>> Document the supported device, register access, conversion formula,
>> module parameter, sysfs attributes, and sysfs lookup method.
>>
>> Assisted-by: Codex:gpt-5.5
>> Signed-off-by: Jihong Min <hurryman2212@gmail.com>
^ permalink raw reply
* Re: [PATCH v2 2/2] hwmon: add initial support for AMD PROM21 xHCI temperature sensor
From: Michal Pecio @ 2026-05-06 21:33 UTC (permalink / raw)
To: Jihong Min
Cc: Greg Kroah-Hartman, Mathias Nyman, Guenter Roeck, Jonathan Corbet,
Shuah Khan, Mario Limonciello, Basavaraj Natikar, linux-usb,
linux-hwmon, linux-doc, linux-pci, linux-kernel
In-Reply-To: <2e2ea249b30168a2eab62fc110c226a511f21bf2.1778099627.git.hurryman2212@gmail.com>
On Thu, 7 May 2026 05:40:34 +0900, Jihong Min wrote:
> AMD PROM21 xHCI controllers expose an 8-bit temperature value
I think this commit message and certainly the Kconfig help text should
include full name of the chip and perhaps its official marketing names
too, so that people better understand what hardware is supported.
So: "AMD Promontory 21 chipset" and "AM5 6xx/8xx series chipsets", or
whatever they are called by AMD and motherboard vendors.
> through a vendor-specific index/data register pair in the xHCI PCI
> MMIO BAR region. Add an auxiliary hwmon driver for AMD 1022:43fd
> controllers and bind it to the xhci_pci.hwmon auxiliary device
> created by xhci-pci.
>
> The read path verifies the parent PCI function and uses the
> initialized xHCI HCD MMIO mapping. The vendor index register is at
> byte offset 0x3000 from the xHCI MMIO BAR base and the vendor data
> register is at byte offset 0x3008. The driver writes register selector
> 0x0001e520 to the index register, reads the raw temperature value from
> the low 8 bits of the data register, and restores the previous index
> before returning. Expose temp1_input and an xHCI label through hwmon.
>
> Register the hwmon device under the parent PCI function so userspace
> reports it as a PCI adapter, while the auxiliary driver still owns the
> hwmon lifetime and unregisters it from the auxiliary remove path.
>
> No public AMD reference is available for this value.
Is there any documentation of the index/data registers themselves?
Any potential danger that something else (FW? SMM?) uses them too?
> The conversion formula is derived from observed temperature readings:
>
> temp[C] = raw * 0.9066 - 78.624
Could make sense to describe methodology, particularly in case some
people would come and question the formula.
How was actual chip temperature measured?
Was the output compared with any other (Windows?) utilities?
People will be comparing these results and possibly trying to draw
some conclusions, like OMG Linux runs this chip 8°C hotter, should
I demand a full refund of my free Ubuntu download????!!!?
> The temperature register did not return a valid value while the xHCI
> PCI function was suspended in testing. Keep the existing behavior by
> default and allow temperature reads to wake the xHCI PCI device. Add an
> allow_pm_switch module parameter so users can disable that behavior;
> when disabled, reads do not wake the device and return -EAGAIN if it is
> suspended.
Is such behavior useful?
Maybe the driver could just disable runtime PM while it's loaded.
>
> Document the supported device, register access, conversion formula,
> module parameter, sysfs attributes, and sysfs lookup method.
>
> Assisted-by: Codex:gpt-5.5
> Signed-off-by: Jihong Min <hurryman2212@gmail.com>
^ permalink raw reply
* Re: [PATCH v25 5/7] firmware: drivers: imx: adds miscdev
From: Arnd Bergmann @ 2026-05-06 21:18 UTC (permalink / raw)
To: Pankaj Gupta, Jonathan Corbet, Rob Herring, Krzysztof Kozlowski,
Conor Dooley, Shawn Guo, Sascha Hauer, Pengutronix Kernel Team,
Fabio Estevam
Cc: linux-doc, linux-kernel, devicetree, imx, linux-arm-kernel,
Frank Li
In-Reply-To: <20260122-imx-se-if-v25-5-5c3e3e3b69a8@nxp.com>
On Thu, Jan 22, 2026, at 12:49, Pankaj Gupta wrote:
> +/* IOCTL definitions. */
> +
> +struct se_ioctl_setup_iobuf {
> + void __user *user_buf;
> + __u32 length;
> + __u32 flags;
> + __u64 ele_addr;
> +};
> +
> +struct se_ioctl_cmd_snd_rcv_rsp_info {
> + __u32 __user *tx_buf;
> + int tx_buf_sz;
> + __u32 __user *rx_buf;
> + int rx_buf_sz;
These just showed up in linux-next and triggered warnings
in my (still private) uapi checks:
./usr/include/linux/se_ioctl.h:22:15: error: padding struct to align 'ele_addr' [-Werror=padded]
22 | __u64 ele_addr;
| ^~~~~~~~
./usr/include/linux/se_ioctl.h:45:16: error: padding struct to align 'rx_buf' [-Werror=padded]
45 | __u32 *rx_buf;
| ^~~~~~
./usr/include/linux/se_ioctl.h:47:1: error: padding struct size to alignment boundary with 4 bytes [-Werror=padded]
47 | };
The problem here is the use of indirect pointers, which are nor
recommended in ABI structures because of the implied padding and
the need for compat mode handlers, see
Documentation/driver-api/ioctl.rst.
I think the fixup below should address all of this, but I
have not reviewed the driver in detail to see if thats's all.
I also noticed that the __user annotations are inconsistent,
so please also run this through 'make C=1' and fix up the
warnings you get.
Arnd
diff --git a/drivers/firmware/imx/se_ctrl.c b/drivers/firmware/imx/se_ctrl.c
index 2ba0a6988a39..d0e3d981d1e0 100644
--- a/drivers/firmware/imx/se_ctrl.c
+++ b/drivers/firmware/imx/se_ctrl.c
@@ -384,7 +384,7 @@ static int add_b_desc_to_pending_list(void *shared_ptr_with_pos,
return -ENOMEM;
b_desc->shared_buf_ptr = shared_ptr_with_pos;
- b_desc->usr_buf_ptr = io->user_buf;
+ b_desc->usr_buf_ptr = u64_to_user_ptr(io->user_buf);
b_desc->size = io->length;
if (io->flags & SE_IO_BUF_FLAGS_IS_INPUT) {
@@ -526,13 +526,13 @@ static int se_ioctl_cmd_snd_rcv_rsp_handler(struct se_if_device_ctx *dev_ctx,
}
if (cmd_snd_rcv_rsp_info.tx_buf_sz < SE_MU_HDR_SZ) {
- dev_err(priv->dev, "%s: User buffer too small(%d < %d)",
+ dev_err(priv->dev, "%s: User buffer too small(%lld < %d)",
dev_ctx->devname, cmd_snd_rcv_rsp_info.tx_buf_sz, SE_MU_HDR_SZ);
se_ioctl_cmd_snd_rcv_cleanup(dev_ctx, uarg, &cmd_snd_rcv_rsp_info);
return -ENOSPC;
}
- err = se_chk_tx_msg_hdr(priv, (struct se_msg_hdr *)cmd_snd_rcv_rsp_info.tx_buf);
+ err = se_chk_tx_msg_hdr(priv, u64_to_user_ptr(cmd_snd_rcv_rsp_info.tx_buf));
if (err) {
se_ioctl_cmd_snd_rcv_cleanup(dev_ctx, uarg, &cmd_snd_rcv_rsp_info);
return err;
@@ -546,7 +546,7 @@ static int se_ioctl_cmd_snd_rcv_rsp_handler(struct se_if_device_ctx *dev_ctx,
}
struct se_api_msg *tx_msg __free(kfree) =
- memdup_user(cmd_snd_rcv_rsp_info.tx_buf,
+ memdup_user(u64_to_user_ptr(cmd_snd_rcv_rsp_info.tx_buf),
cmd_snd_rcv_rsp_info.tx_buf_sz);
if (IS_ERR(tx_msg)) {
err = PTR_ERR(tx_msg);
@@ -593,8 +593,8 @@ static int se_ioctl_cmd_snd_rcv_rsp_handler(struct se_if_device_ctx *dev_ctx,
print_hex_dump_debug("to user ", DUMP_PREFIX_OFFSET, 4, 4, rx_msg,
cmd_snd_rcv_rsp_info.rx_buf_sz, false);
- if (copy_to_user(cmd_snd_rcv_rsp_info.rx_buf, rx_msg,
- cmd_snd_rcv_rsp_info.rx_buf_sz)) {
+ if (copy_to_user(u64_to_user_ptr(cmd_snd_rcv_rsp_info.rx_buf),
+ rx_msg, cmd_snd_rcv_rsp_info.rx_buf_sz)) {
dev_err(priv->dev, "%s: Failed to copy to user.", dev_ctx->devname);
err = -EFAULT;
}
@@ -655,7 +655,7 @@ static int se_ioctl_setup_iobuf_handler(struct se_if_device_ctx *dev_ctx,
return -EFAULT;
}
- dev_dbg(dev_ctx->priv->dev, "%s: io [buf: %p(%d) flag: %x].", dev_ctx->devname,
+ dev_dbg(dev_ctx->priv->dev, "%s: io [buf: %llx(%d) flag: %x].", dev_ctx->devname,
io.user_buf, io.length, io.flags);
if (io.length == 0 || !io.user_buf) {
@@ -696,7 +696,8 @@ static int se_ioctl_setup_iobuf_handler(struct se_if_device_ctx *dev_ctx,
* buffer is input:
* copy data from user space to this allocated buffer.
*/
- if (copy_from_user(shared_mem->ptr + pos, io.user_buf, io.length)) {
+ if (copy_from_user(shared_mem->ptr + pos,
+ u64_to_user_ptr(io.user_buf), io.length)) {
dev_err(dev_ctx->priv->dev,
"%s: Failed copy data to shared memory.",
dev_ctx->devname);
diff --git a/include/uapi/linux/se_ioctl.h b/include/uapi/linux/se_ioctl.h
index 0c948bdc8c26..9fb81cb72b94 100644
--- a/include/uapi/linux/se_ioctl.h
+++ b/include/uapi/linux/se_ioctl.h
@@ -16,7 +16,7 @@
/* IOCTL definitions. */
struct se_ioctl_setup_iobuf {
- void __user *user_buf;
+ __u64 user_buf;
__u32 length;
__u32 flags;
__u64 ele_addr;
@@ -40,10 +40,10 @@ struct se_ioctl_get_if_info {
};
struct se_ioctl_cmd_snd_rcv_rsp_info {
- __u32 __user *tx_buf;
- int tx_buf_sz;
- __u32 __user *rx_buf;
- int rx_buf_sz;
+ __u64 tx_buf;
+ __u64 tx_buf_sz;
+ __u64 rx_buf;
+ __u64 rx_buf_sz;
};
struct se_ioctl_get_soc_info {
^ permalink raw reply related
* Re: [PATCH v2 1/2] usb: xhci-pci: add generic auxiliary device interface
From: Michal Pecio @ 2026-05-06 21:15 UTC (permalink / raw)
To: Jihong Min
Cc: Greg Kroah-Hartman, Mathias Nyman, Guenter Roeck, Jonathan Corbet,
Shuah Khan, Mario Limonciello, Basavaraj Natikar, linux-usb,
linux-hwmon, linux-doc, linux-pci, linux-kernel
In-Reply-To: <3f26994ebb5f0e4e653a8108a9626bc793148679.1778099627.git.hurryman2212@gmail.com>
On Thu, 7 May 2026 05:40:33 +0900, Jihong Min wrote:
> Some xHCI PCI controllers expose controller-specific functionality that is
> not part of generic xHCI operation and is better handled by optional child
> drivers in other subsystems. Add a small auxiliary device registration path
> for selected xHCI PCI controllers.
>
> The initial table creates an xhci_pci.hwmon auxiliary device for AMD
> 1022:43fd controllers. Store the created auxiliary device in devres so the
> xhci-pci remove path destroys it before HCD teardown. Use a
> PCI-domain-qualified id so auxiliary device names remain unique across PCI
> domains.
>
> This keeps xhci-pci responsible only for publishing selected controller
> functions while allowing subsystem-specific drivers to bind through the
> auxiliary bus.
>
> Assisted-by: Codex:gpt-5.5
> Signed-off-by: Jihong Min <hurryman2212@gmail.com>
> ---
> drivers/usb/host/Kconfig | 10 ++++
> drivers/usb/host/xhci-pci.c | 114 ++++++++++++++++++++++++++++++++++++
> 2 files changed, 124 insertions(+)
>
> diff --git a/drivers/usb/host/Kconfig b/drivers/usb/host/Kconfig
> index 0a277a07cf70..e0c2c7ac5c97 100644
> --- a/drivers/usb/host/Kconfig
> +++ b/drivers/usb/host/Kconfig
> @@ -42,6 +42,16 @@ config USB_XHCI_PCI
> depends on USB_PCI
> default y
>
> +config USB_XHCI_PCI_AUXDEV
> + bool "xHCI PCI auxiliary device support"
> + depends on USB_XHCI_PCI
> + select AUXILIARY_BUS
> + help
> + This enables xHCI PCI support for registering auxiliary devices
> + for selected controllers. It is used by optional child drivers
> + that bind to xHCI PCI controller-specific functionality through
> + the auxiliary bus.
> +
> config USB_XHCI_PCI_RENESAS
> tristate "Support for additional Renesas xHCI controller with firmware"
> depends on USB_XHCI_PCI
> diff --git a/drivers/usb/host/xhci-pci.c b/drivers/usb/host/xhci-pci.c
> index 585b2f3117b0..1ab27d2182eb 100644
> --- a/drivers/usb/host/xhci-pci.c
> +++ b/drivers/usb/host/xhci-pci.c
> @@ -8,6 +8,8 @@
> * Some code borrowed from the Linux EHCI driver.
> */
>
> +#include <linux/auxiliary_bus.h>
> +#include <linux/device/devres.h>
> #include <linux/pci.h>
> #include <linux/slab.h>
> #include <linux/module.h>
> @@ -103,6 +105,114 @@ static int xhci_pci_run(struct usb_hcd *hcd);
> static int xhci_pci_update_hub_device(struct usb_hcd *hcd, struct usb_device *hdev,
> struct usb_tt *tt, gfp_t mem_flags);
>
> +#if IS_ENABLED(CONFIG_USB_XHCI_PCI_AUXDEV)
> +static const struct {
> + struct pci_device_id id;
> + const char *aux_dev_name;
> +} pci_ids_have_aux[] = {
> + {
> + .id = { PCI_DEVICE(PCI_VENDOR_ID_AMD, 0x43fd) }, /* PROM21 xHCI */
> + .aux_dev_name = "hwmon",
> + },
> + { /* end: all zeroes */ }
> +};
> +
> +struct xhci_pci_aux_devres {
> + struct auxiliary_device *auxdev;
> +};
> +
> +static bool xhci_pci_aux_match_id(const struct pci_device_id *id,
> + const struct pci_dev *pdev)
> +{
> + if (id->vendor != PCI_ANY_ID && id->vendor != pdev->vendor)
> + return false;
> + if (id->device != PCI_ANY_ID && id->device != pdev->device)
> + return false;
> + if (id->subvendor != PCI_ANY_ID &&
> + id->subvendor != pdev->subsystem_vendor)
> + return false;
> + if (id->subdevice != PCI_ANY_ID &&
> + id->subdevice != pdev->subsystem_device)
> + return false;
> +
> + return !((id->class ^ pdev->class) & id->class_mask);
> +}
> +
> +static const char *xhci_pci_aux_dev_name(struct pci_dev *pdev)
> +{
> + int i;
> +
> + for (i = 0; pci_ids_have_aux[i].aux_dev_name; i++) {
> + if (xhci_pci_aux_match_id(&pci_ids_have_aux[i].id, pdev))
> + return pci_ids_have_aux[i].aux_dev_name;
> + }
> +
> + return NULL;
> +}
> +
> +static void xhci_pci_aux_devres_release(struct device *dev, void *res)
> +{
> + struct xhci_pci_aux_devres *devres = res;
> +
> + if (devres->auxdev)
> + auxiliary_device_destroy(devres->auxdev);
> +}
> +
> +static void xhci_pci_try_add_aux_device(struct pci_dev *pdev)
> +{
> + struct xhci_pci_aux_devres *devres;
> + struct auxiliary_device *auxdev;
> + const char *aux_dev_name;
> +
> + aux_dev_name = xhci_pci_aux_dev_name(pdev);
> + if (!aux_dev_name)
> + return;
> +
> + devres = devres_alloc(xhci_pci_aux_devres_release, sizeof(*devres),
> + GFP_KERNEL);
> + if (!devres) {
> + dev_warn(&pdev->dev,
> + "failed to allocate auxiliary device state\n");
> + return;
> + }
> +
> + auxdev = auxiliary_device_create(&pdev->dev, KBUILD_MODNAME,
> + aux_dev_name, NULL,
> + (pci_domain_nr(pdev->bus) << 16) |
> + pci_dev_id(pdev));
> + if (!auxdev) {
> + devres_free(devres);
> + dev_warn(&pdev->dev, "failed to add %s auxiliary device\n",
> + aux_dev_name);
> + return;
> + }
> +
> + devres->auxdev = auxdev;
> + devres_add(&pdev->dev, devres);
> +}
> +
> +static void xhci_pci_try_remove_aux_device(struct pci_dev *pdev)
> +{
> + struct xhci_pci_aux_devres *devres;
> +
> + devres = devres_find(&pdev->dev, xhci_pci_aux_devres_release, NULL,
> + NULL);
> + if (!devres || !devres->auxdev)
> + return;
> +
> + auxiliary_device_destroy(devres->auxdev);
> + devres->auxdev = NULL;
> +}
> +#else
> +static inline void xhci_pci_try_add_aux_device(struct pci_dev *pdev)
> +{
> +}
> +
> +static inline void xhci_pci_try_remove_aux_device(struct pci_dev *pdev)
> +{
> +}
> +#endif
> +
> static const struct xhci_driver_overrides xhci_pci_overrides __initconst = {
> .reset = xhci_pci_setup,
> .start = xhci_pci_run,
> @@ -677,6 +787,8 @@ int xhci_pci_common_probe(struct pci_dev *dev, const struct pci_device_id *id)
> if (device_property_read_bool(&dev->dev, "ti,pwron-active-high"))
> pci_clear_and_set_config_dword(dev, 0xE0, 0, 1 << 22);
>
> + xhci_pci_try_add_aux_device(dev);
Is it considered acceptable to add
if (IS_ENABLED(CONFIG_USB_XHCI_PCI_AUXDEV))
before this call, remove #ifdef around the definitions of the auxdev
functions and rely on dead code elimination to clean them up?
We already have a similar trick with CONFIG_USB_XHCI_PCI_RENESAS here
and it seemed to be working, though the amount of conditional code is
much lower and so is the potential risk.
The reason for doing it this way was because Greg doesn't like #ifdefs
in .c files, and neither do static analyzers like them.
> +
> return 0;
>
> put_usb3_hcd:
> @@ -713,6 +825,8 @@ void xhci_pci_remove(struct pci_dev *dev)
> xhci = hcd_to_xhci(pci_get_drvdata(dev));
> set_power_d3 = xhci->quirks & XHCI_SPURIOUS_WAKEUP;
>
> + xhci_pci_try_remove_aux_device(dev);
> +
> xhci->xhc_state |= XHCI_STATE_REMOVING;
>
> if (pci_choose_state(dev, PMSG_SUSPEND) == PCI_D0)
> --
> 2.53.0
>
^ permalink raw reply
* Re: [PATCH v2 1/2] usb: xhci-pci: add generic auxiliary device interface
From: Jihong Min @ 2026-05-06 21:09 UTC (permalink / raw)
To: Mario Limonciello, Jihong Min, Greg Kroah-Hartman, Mathias Nyman
Cc: Guenter Roeck, Jonathan Corbet, Shuah Khan, Basavaraj Natikar,
linux-usb, linux-hwmon, linux-doc, linux-pci, linux-kernel
In-Reply-To: <bb047320-594d-46de-9522-1098e784ebc1@amd.com>
I refactored the auxiliary device table to use PCI_DEVICE_DATA(), store the
auxiliary device name in driver_data, and use pci_match_id() inside
xhci_pci_aux_dev_name(). The relevant change is:
#define PCI_DEVICE_ID_AMD_PROM21_XHCI 0x43fd
...
static const struct pci_device_id pci_ids_have_aux[] = {
{ PCI_DEVICE_DATA(AMD, PROM21_XHCI, "hwmon") },
{ /* end: all zeroes */ }
};
...
static const char *xhci_pci_aux_dev_name(struct pci_dev *pdev)
{
const struct pci_device_id *id;
id = pci_match_id(pci_ids_have_aux, pdev);
if (!id)
return NULL;
return (const char *)id->driver_data;
}
I will include this in v3.
Thank you,
Jihong Min
On 5/7/26 05:53, Mario Limonciello wrote:
>
>
> On 5/6/26 15:40, Jihong Min wrote:
>> [You don't often get email from hurryman2212@gmail.com. Learn why
>> this is important at https://aka.ms/LearnAboutSenderIdentification ]
>>
>> Some xHCI PCI controllers expose controller-specific functionality
>> that is
>> not part of generic xHCI operation and is better handled by optional
>> child
>> drivers in other subsystems. Add a small auxiliary device
>> registration path
>> for selected xHCI PCI controllers.
>>
>> The initial table creates an xhci_pci.hwmon auxiliary device for AMD
>> 1022:43fd controllers. Store the created auxiliary device in devres
>> so the
>> xhci-pci remove path destroys it before HCD teardown. Use a
>> PCI-domain-qualified id so auxiliary device names remain unique
>> across PCI
>> domains.
>>
>> This keeps xhci-pci responsible only for publishing selected controller
>> functions while allowing subsystem-specific drivers to bind through the
>> auxiliary bus.
>>
>> Assisted-by: Codex:gpt-5.5
>> Signed-off-by: Jihong Min <hurryman2212@gmail.com>
>> ---
>> drivers/usb/host/Kconfig | 10 ++++
>> drivers/usb/host/xhci-pci.c | 114 ++++++++++++++++++++++++++++++++++++
>> 2 files changed, 124 insertions(+)
>>
>> diff --git a/drivers/usb/host/Kconfig b/drivers/usb/host/Kconfig
>> index 0a277a07cf70..e0c2c7ac5c97 100644
>> --- a/drivers/usb/host/Kconfig
>> +++ b/drivers/usb/host/Kconfig
>> @@ -42,6 +42,16 @@ config USB_XHCI_PCI
>> depends on USB_PCI
>> default y
>>
>> +config USB_XHCI_PCI_AUXDEV
>> + bool "xHCI PCI auxiliary device support"
>> + depends on USB_XHCI_PCI
>> + select AUXILIARY_BUS
>> + help
>> + This enables xHCI PCI support for registering auxiliary
>> devices
>> + for selected controllers. It is used by optional child drivers
>> + that bind to xHCI PCI controller-specific functionality
>> through
>> + the auxiliary bus.
>> +
>> config USB_XHCI_PCI_RENESAS
>> tristate "Support for additional Renesas xHCI controller
>> with firmware"
>> depends on USB_XHCI_PCI
>> diff --git a/drivers/usb/host/xhci-pci.c b/drivers/usb/host/xhci-pci.c
>> index 585b2f3117b0..1ab27d2182eb 100644
>> --- a/drivers/usb/host/xhci-pci.c
>> +++ b/drivers/usb/host/xhci-pci.c
>> @@ -8,6 +8,8 @@
>> * Some code borrowed from the Linux EHCI driver.
>> */
>>
>> +#include <linux/auxiliary_bus.h>
>> +#include <linux/device/devres.h>
>> #include <linux/pci.h>
>> #include <linux/slab.h>
>> #include <linux/module.h>
>> @@ -103,6 +105,114 @@ static int xhci_pci_run(struct usb_hcd *hcd);
>> static int xhci_pci_update_hub_device(struct usb_hcd *hcd, struct
>> usb_device *hdev,
>> struct usb_tt *tt, gfp_t
>> mem_flags);
>>
>> +#if IS_ENABLED(CONFIG_USB_XHCI_PCI_AUXDEV)
>> +static const struct {
>> + struct pci_device_id id;
>> + const char *aux_dev_name;
>> +} pci_ids_have_aux[] = {
>> + {
>> + .id = { PCI_DEVICE(PCI_VENDOR_ID_AMD, 0x43fd) }, /*
>> PROM21 xHCI */
>> + .aux_dev_name = "hwmon",
>> + },
>> + { /* end: all zeroes */ }
>> +};
>> +
>> +struct xhci_pci_aux_devres {
>> + struct auxiliary_device *auxdev;
>> +};
>> +
>> +static bool xhci_pci_aux_match_id(const struct pci_device_id *id,
>> + const struct pci_dev *pdev)
>> +{
>> + if (id->vendor != PCI_ANY_ID && id->vendor != pdev->vendor)
>> + return false;
>> + if (id->device != PCI_ANY_ID && id->device != pdev->device)
>> + return false;
>> + if (id->subvendor != PCI_ANY_ID &&
>> + id->subvendor != pdev->subsystem_vendor)
>> + return false;
>> + if (id->subdevice != PCI_ANY_ID &&
>> + id->subdevice != pdev->subsystem_device)
>> + return false;
>> +
>> + return !((id->class ^ pdev->class) & id->class_mask);
>
> What's wrong with pci_match_id()?
>
>> +}
>> +
>> +static const char *xhci_pci_aux_dev_name(struct pci_dev *pdev)
>> +{
>> + int i;
>> +
>> + for (i = 0; pci_ids_have_aux[i].aux_dev_name; i++) {
>> + if (xhci_pci_aux_match_id(&pci_ids_have_aux[i].id,
>> pdev))
>> + return pci_ids_have_aux[i].aux_dev_name;
>> + }
>> +
>> + return NULL;
>> +}
>> +
>> +static void xhci_pci_aux_devres_release(struct device *dev, void *res)
>> +{
>> + struct xhci_pci_aux_devres *devres = res;
>> +
>> + if (devres->auxdev)
>> + auxiliary_device_destroy(devres->auxdev);
>> +}
>> +
>> +static void xhci_pci_try_add_aux_device(struct pci_dev *pdev)
>> +{
>> + struct xhci_pci_aux_devres *devres;
>> + struct auxiliary_device *auxdev;
>> + const char *aux_dev_name;
>> +
>> + aux_dev_name = xhci_pci_aux_dev_name(pdev);
>> + if (!aux_dev_name)
>> + return;
>> +
>> + devres = devres_alloc(xhci_pci_aux_devres_release,
>> sizeof(*devres),
>> + GFP_KERNEL);
>> + if (!devres) {
>> + dev_warn(&pdev->dev,
>> + "failed to allocate auxiliary device state\n");
>> + return;
>> + }
>> +
>> + auxdev = auxiliary_device_create(&pdev->dev, KBUILD_MODNAME,
>> + aux_dev_name, NULL,
>> + (pci_domain_nr(pdev->bus) << 16) |
>> + pci_dev_id(pdev));
>> + if (!auxdev) {
>> + devres_free(devres);
>> + dev_warn(&pdev->dev, "failed to add %s auxiliary
>> device\n",
>> + aux_dev_name);
>> + return;
>> + }
>> +
>> + devres->auxdev = auxdev;
>> + devres_add(&pdev->dev, devres);
>> +}
>> +
>> +static void xhci_pci_try_remove_aux_device(struct pci_dev *pdev)
>> +{
>> + struct xhci_pci_aux_devres *devres;
>> +
>> + devres = devres_find(&pdev->dev, xhci_pci_aux_devres_release,
>> NULL,
>> + NULL);
>> + if (!devres || !devres->auxdev)
>> + return;
>> +
>> + auxiliary_device_destroy(devres->auxdev);
>> + devres->auxdev = NULL;
>> +}
>> +#else
>> +static inline void xhci_pci_try_add_aux_device(struct pci_dev *pdev)
>> +{
>> +}
>> +
>> +static inline void xhci_pci_try_remove_aux_device(struct pci_dev *pdev)
>> +{
>> +}
>> +#endif
>> +
>> static const struct xhci_driver_overrides xhci_pci_overrides
>> __initconst = {
>> .reset = xhci_pci_setup,
>> .start = xhci_pci_run,
>> @@ -677,6 +787,8 @@ int xhci_pci_common_probe(struct pci_dev *dev,
>> const struct pci_device_id *id)
>> if (device_property_read_bool(&dev->dev,
>> "ti,pwron-active-high"))
>> pci_clear_and_set_config_dword(dev, 0xE0, 0, 1 << 22);
>>
>> + xhci_pci_try_add_aux_device(dev);
>> +
>> return 0;
>>
>> put_usb3_hcd:
>> @@ -713,6 +825,8 @@ void xhci_pci_remove(struct pci_dev *dev)
>> xhci = hcd_to_xhci(pci_get_drvdata(dev));
>> set_power_d3 = xhci->quirks & XHCI_SPURIOUS_WAKEUP;
>>
>> + xhci_pci_try_remove_aux_device(dev);
>> +
>> xhci->xhc_state |= XHCI_STATE_REMOVING;
>>
>> if (pci_choose_state(dev, PMSG_SUSPEND) == PCI_D0)
>> --
>> 2.53.0
>>
>
^ permalink raw reply
* Re: [PATCH v2 1/2] usb: xhci-pci: add generic auxiliary device interface
From: Mario Limonciello @ 2026-05-06 20:53 UTC (permalink / raw)
To: Jihong Min, Greg Kroah-Hartman, Mathias Nyman
Cc: Guenter Roeck, Jonathan Corbet, Shuah Khan, Basavaraj Natikar,
linux-usb, linux-hwmon, linux-doc, linux-pci, linux-kernel
In-Reply-To: <3f26994ebb5f0e4e653a8108a9626bc793148679.1778099627.git.hurryman2212@gmail.com>
On 5/6/26 15:40, Jihong Min wrote:
> [You don't often get email from hurryman2212@gmail.com. Learn why this is important at https://aka.ms/LearnAboutSenderIdentification ]
>
> Some xHCI PCI controllers expose controller-specific functionality that is
> not part of generic xHCI operation and is better handled by optional child
> drivers in other subsystems. Add a small auxiliary device registration path
> for selected xHCI PCI controllers.
>
> The initial table creates an xhci_pci.hwmon auxiliary device for AMD
> 1022:43fd controllers. Store the created auxiliary device in devres so the
> xhci-pci remove path destroys it before HCD teardown. Use a
> PCI-domain-qualified id so auxiliary device names remain unique across PCI
> domains.
>
> This keeps xhci-pci responsible only for publishing selected controller
> functions while allowing subsystem-specific drivers to bind through the
> auxiliary bus.
>
> Assisted-by: Codex:gpt-5.5
> Signed-off-by: Jihong Min <hurryman2212@gmail.com>
> ---
> drivers/usb/host/Kconfig | 10 ++++
> drivers/usb/host/xhci-pci.c | 114 ++++++++++++++++++++++++++++++++++++
> 2 files changed, 124 insertions(+)
>
> diff --git a/drivers/usb/host/Kconfig b/drivers/usb/host/Kconfig
> index 0a277a07cf70..e0c2c7ac5c97 100644
> --- a/drivers/usb/host/Kconfig
> +++ b/drivers/usb/host/Kconfig
> @@ -42,6 +42,16 @@ config USB_XHCI_PCI
> depends on USB_PCI
> default y
>
> +config USB_XHCI_PCI_AUXDEV
> + bool "xHCI PCI auxiliary device support"
> + depends on USB_XHCI_PCI
> + select AUXILIARY_BUS
> + help
> + This enables xHCI PCI support for registering auxiliary devices
> + for selected controllers. It is used by optional child drivers
> + that bind to xHCI PCI controller-specific functionality through
> + the auxiliary bus.
> +
> config USB_XHCI_PCI_RENESAS
> tristate "Support for additional Renesas xHCI controller with firmware"
> depends on USB_XHCI_PCI
> diff --git a/drivers/usb/host/xhci-pci.c b/drivers/usb/host/xhci-pci.c
> index 585b2f3117b0..1ab27d2182eb 100644
> --- a/drivers/usb/host/xhci-pci.c
> +++ b/drivers/usb/host/xhci-pci.c
> @@ -8,6 +8,8 @@
> * Some code borrowed from the Linux EHCI driver.
> */
>
> +#include <linux/auxiliary_bus.h>
> +#include <linux/device/devres.h>
> #include <linux/pci.h>
> #include <linux/slab.h>
> #include <linux/module.h>
> @@ -103,6 +105,114 @@ static int xhci_pci_run(struct usb_hcd *hcd);
> static int xhci_pci_update_hub_device(struct usb_hcd *hcd, struct usb_device *hdev,
> struct usb_tt *tt, gfp_t mem_flags);
>
> +#if IS_ENABLED(CONFIG_USB_XHCI_PCI_AUXDEV)
> +static const struct {
> + struct pci_device_id id;
> + const char *aux_dev_name;
> +} pci_ids_have_aux[] = {
> + {
> + .id = { PCI_DEVICE(PCI_VENDOR_ID_AMD, 0x43fd) }, /* PROM21 xHCI */
> + .aux_dev_name = "hwmon",
> + },
> + { /* end: all zeroes */ }
> +};
> +
> +struct xhci_pci_aux_devres {
> + struct auxiliary_device *auxdev;
> +};
> +
> +static bool xhci_pci_aux_match_id(const struct pci_device_id *id,
> + const struct pci_dev *pdev)
> +{
> + if (id->vendor != PCI_ANY_ID && id->vendor != pdev->vendor)
> + return false;
> + if (id->device != PCI_ANY_ID && id->device != pdev->device)
> + return false;
> + if (id->subvendor != PCI_ANY_ID &&
> + id->subvendor != pdev->subsystem_vendor)
> + return false;
> + if (id->subdevice != PCI_ANY_ID &&
> + id->subdevice != pdev->subsystem_device)
> + return false;
> +
> + return !((id->class ^ pdev->class) & id->class_mask);
What's wrong with pci_match_id()?
> +}
> +
> +static const char *xhci_pci_aux_dev_name(struct pci_dev *pdev)
> +{
> + int i;
> +
> + for (i = 0; pci_ids_have_aux[i].aux_dev_name; i++) {
> + if (xhci_pci_aux_match_id(&pci_ids_have_aux[i].id, pdev))
> + return pci_ids_have_aux[i].aux_dev_name;
> + }
> +
> + return NULL;
> +}
> +
> +static void xhci_pci_aux_devres_release(struct device *dev, void *res)
> +{
> + struct xhci_pci_aux_devres *devres = res;
> +
> + if (devres->auxdev)
> + auxiliary_device_destroy(devres->auxdev);
> +}
> +
> +static void xhci_pci_try_add_aux_device(struct pci_dev *pdev)
> +{
> + struct xhci_pci_aux_devres *devres;
> + struct auxiliary_device *auxdev;
> + const char *aux_dev_name;
> +
> + aux_dev_name = xhci_pci_aux_dev_name(pdev);
> + if (!aux_dev_name)
> + return;
> +
> + devres = devres_alloc(xhci_pci_aux_devres_release, sizeof(*devres),
> + GFP_KERNEL);
> + if (!devres) {
> + dev_warn(&pdev->dev,
> + "failed to allocate auxiliary device state\n");
> + return;
> + }
> +
> + auxdev = auxiliary_device_create(&pdev->dev, KBUILD_MODNAME,
> + aux_dev_name, NULL,
> + (pci_domain_nr(pdev->bus) << 16) |
> + pci_dev_id(pdev));
> + if (!auxdev) {
> + devres_free(devres);
> + dev_warn(&pdev->dev, "failed to add %s auxiliary device\n",
> + aux_dev_name);
> + return;
> + }
> +
> + devres->auxdev = auxdev;
> + devres_add(&pdev->dev, devres);
> +}
> +
> +static void xhci_pci_try_remove_aux_device(struct pci_dev *pdev)
> +{
> + struct xhci_pci_aux_devres *devres;
> +
> + devres = devres_find(&pdev->dev, xhci_pci_aux_devres_release, NULL,
> + NULL);
> + if (!devres || !devres->auxdev)
> + return;
> +
> + auxiliary_device_destroy(devres->auxdev);
> + devres->auxdev = NULL;
> +}
> +#else
> +static inline void xhci_pci_try_add_aux_device(struct pci_dev *pdev)
> +{
> +}
> +
> +static inline void xhci_pci_try_remove_aux_device(struct pci_dev *pdev)
> +{
> +}
> +#endif
> +
> static const struct xhci_driver_overrides xhci_pci_overrides __initconst = {
> .reset = xhci_pci_setup,
> .start = xhci_pci_run,
> @@ -677,6 +787,8 @@ int xhci_pci_common_probe(struct pci_dev *dev, const struct pci_device_id *id)
> if (device_property_read_bool(&dev->dev, "ti,pwron-active-high"))
> pci_clear_and_set_config_dword(dev, 0xE0, 0, 1 << 22);
>
> + xhci_pci_try_add_aux_device(dev);
> +
> return 0;
>
> put_usb3_hcd:
> @@ -713,6 +825,8 @@ void xhci_pci_remove(struct pci_dev *dev)
> xhci = hcd_to_xhci(pci_get_drvdata(dev));
> set_power_d3 = xhci->quirks & XHCI_SPURIOUS_WAKEUP;
>
> + xhci_pci_try_remove_aux_device(dev);
> +
> xhci->xhc_state |= XHCI_STATE_REMOVING;
>
> if (pci_choose_state(dev, PMSG_SUSPEND) == PCI_D0)
> --
> 2.53.0
>
^ permalink raw reply
* [PATCH v2 2/2] hwmon: add initial support for AMD PROM21 xHCI temperature sensor
From: Jihong Min @ 2026-05-06 20:40 UTC (permalink / raw)
To: Greg Kroah-Hartman, Mathias Nyman
Cc: Guenter Roeck, Jonathan Corbet, Shuah Khan, Mario Limonciello,
Basavaraj Natikar, linux-usb, linux-hwmon, linux-doc, linux-pci,
linux-kernel, Jihong Min
In-Reply-To: <cover.1778099627.git.hurryman2212@gmail.com>
AMD PROM21 xHCI controllers expose an 8-bit temperature value
through a vendor-specific index/data register pair in the xHCI PCI
MMIO BAR region. Add an auxiliary hwmon driver for AMD 1022:43fd
controllers and bind it to the xhci_pci.hwmon auxiliary device
created by xhci-pci.
The read path verifies the parent PCI function and uses the
initialized xHCI HCD MMIO mapping. The vendor index register is at
byte offset 0x3000 from the xHCI MMIO BAR base and the vendor data
register is at byte offset 0x3008. The driver writes register selector
0x0001e520 to the index register, reads the raw temperature value from
the low 8 bits of the data register, and restores the previous index
before returning. Expose temp1_input and an xHCI label through hwmon.
Register the hwmon device under the parent PCI function so userspace
reports it as a PCI adapter, while the auxiliary driver still owns the
hwmon lifetime and unregisters it from the auxiliary remove path.
No public AMD reference is available for this value. The conversion
formula is derived from observed temperature readings:
temp[C] = raw * 0.9066 - 78.624
The temperature register did not return a valid value while the xHCI
PCI function was suspended in testing. Keep the existing behavior by
default and allow temperature reads to wake the xHCI PCI device. Add an
allow_pm_switch module parameter so users can disable that behavior;
when disabled, reads do not wake the device and return -EAGAIN if it is
suspended.
Document the supported device, register access, conversion formula,
module parameter, sysfs attributes, and sysfs lookup method.
Assisted-by: Codex:gpt-5.5
Signed-off-by: Jihong Min <hurryman2212@gmail.com>
---
Documentation/hwmon/index.rst | 1 +
Documentation/hwmon/prom21-hwmon.rst | 84 ++++++++
drivers/hwmon/Kconfig | 11 +
drivers/hwmon/Makefile | 1 +
drivers/hwmon/prom21-hwmon.c | 300 +++++++++++++++++++++++++++
5 files changed, 397 insertions(+)
create mode 100644 Documentation/hwmon/prom21-hwmon.rst
create mode 100644 drivers/hwmon/prom21-hwmon.c
diff --git a/Documentation/hwmon/index.rst b/Documentation/hwmon/index.rst
index 8b655e5d6b68..0d85b78596cf 100644
--- a/Documentation/hwmon/index.rst
+++ b/Documentation/hwmon/index.rst
@@ -215,6 +215,7 @@ Hardware Monitoring Kernel Drivers
peci-dimmtemp
pmbus
powerz
+ prom21-hwmon
powr1220
pt5161l
pxe1610
diff --git a/Documentation/hwmon/prom21-hwmon.rst b/Documentation/hwmon/prom21-hwmon.rst
new file mode 100644
index 000000000000..965a50595b47
--- /dev/null
+++ b/Documentation/hwmon/prom21-hwmon.rst
@@ -0,0 +1,84 @@
+.. SPDX-License-Identifier: GPL-2.0
+
+Kernel driver prom21-hwmon
+==========================
+
+Supported chips:
+
+ * AMD PROM21 xHCI
+
+ Prefix: 'prom21_hwmon'
+
+ PCI ID: 1022:43fd
+
+Author:
+
+ - Jihong Min <hurryman2212@gmail.com>
+
+Description
+-----------
+
+This driver exposes the temperature sensor in AMD PROM21 xHCI controllers.
+
+The driver binds to an auxiliary device created by the xHCI PCI driver for
+supported controllers. The sensor value is accessed through a vendor-specific
+index/data register pair in the controller's PCI MMIO BAR.
+
+Since the xHCI controllers are integrated in PROM21, this temperature can also
+be used as a monitor for a temperature close to the AMD chipset temperature.
+
+Register access
+---------------
+
+The temperature value is read through a vendor-specific index/data register
+pair in the xHCI PCI MMIO BAR. The driver uses the following byte offsets from
+the MMIO BAR base:
+
+======================= =====================================================
+0x3000 Vendor index register
+0x3008 Vendor data register
+======================= =====================================================
+
+The driver saves the current vendor index register value, writes the
+temperature selector ``0x0001e520`` to the vendor index register, reads the
+vendor data register, and restores the previous vendor index value before
+returning. The raw temperature value is the low 8 bits of the vendor data
+register value.
+
+No public AMD reference is available for the raw value. The temperature
+conversion formula is derived from observed PROM21 xHCI temperature readings:
+
+ temp[C] = raw * 0.9066 - 78.624
+
+Module parameters
+-----------------
+
+allow_pm_switch: bool
+ Allow temperature reads to wake the xHCI PCI device. This is enabled by
+ default. If disabled, the driver does not wake the xHCI PCI device from a
+ temperature read. It reads the temperature only when the device is not
+ suspended. A read from a suspended device returns ``-EAGAIN``.
+
+Sysfs entries
+-------------
+
+======================= =====================================================
+temp1_input Temperature in millidegrees Celsius
+temp1_label "xHCI"
+======================= =====================================================
+
+The hwmon device name is ``prom21_hwmon``. The sysfs path depends on the hwmon
+device number assigned by the kernel. Userspace can locate the device by
+matching the ``name`` attribute:
+
+.. code-block:: sh
+
+ for hwmon in /sys/class/hwmon/hwmon*; do
+ [ "$(cat "$hwmon/name")" = "prom21_hwmon" ] || continue
+ cat "$hwmon/temp1_label"
+ cat "$hwmon/temp1_input"
+ done
+
+``temp1_input`` reports millidegrees Celsius, so a value of ``50113`` means
+50.113 degrees Celsius. If the raw register value is invalid, ``temp1_input``
+returns ``-ENODATA``.
diff --git a/drivers/hwmon/Kconfig b/drivers/hwmon/Kconfig
index 14e4cea48acc..da2266807f06 100644
--- a/drivers/hwmon/Kconfig
+++ b/drivers/hwmon/Kconfig
@@ -940,6 +940,17 @@ config SENSORS_POWERZ
This driver can also be built as a module. If so, the module
will be called powerz.
+config SENSORS_PROM21
+ tristate "AMD PROM21 xHCI temperature sensor"
+ depends on USB_XHCI_PCI
+ select USB_XHCI_PCI_AUXDEV
+ help
+ If you say yes here you get support for the AMD PROM21 xHCI
+ temperature sensor.
+
+ This driver can also be built as a module. If so, the module
+ will be called prom21-hwmon.
+
config SENSORS_POWR1220
tristate "Lattice POWR1220 Power Monitoring"
depends on I2C
diff --git a/drivers/hwmon/Makefile b/drivers/hwmon/Makefile
index 4788996aa137..7693ed3b3f72 100644
--- a/drivers/hwmon/Makefile
+++ b/drivers/hwmon/Makefile
@@ -196,6 +196,7 @@ obj-$(CONFIG_SENSORS_PC87427) += pc87427.o
obj-$(CONFIG_SENSORS_PCF8591) += pcf8591.o
obj-$(CONFIG_SENSORS_POWERZ) += powerz.o
obj-$(CONFIG_SENSORS_POWR1220) += powr1220.o
+obj-$(CONFIG_SENSORS_PROM21) += prom21-hwmon.o
obj-$(CONFIG_SENSORS_PT5161L) += pt5161l.o
obj-$(CONFIG_SENSORS_PWM_FAN) += pwm-fan.o
obj-$(CONFIG_SENSORS_QNAP_MCU_HWMON) += qnap-mcu-hwmon.o
diff --git a/drivers/hwmon/prom21-hwmon.c b/drivers/hwmon/prom21-hwmon.c
new file mode 100644
index 000000000000..179d2f206c7d
--- /dev/null
+++ b/drivers/hwmon/prom21-hwmon.c
@@ -0,0 +1,300 @@
+// SPDX-License-Identifier: GPL-2.0
+/*
+ * AMD PROM21 xHCI Hwmon Implementation
+ * (only temperature monitoring is supported)
+ *
+ * This can be effectively used as the alternative chipset temperature monitor.
+ *
+ * Copyright (C) 2026 Jihong Min <hurryman2212@gmail.com>
+ */
+
+#include <linux/auxiliary_bus.h>
+#include <linux/device.h>
+#include <linux/err.h>
+#include <linux/errno.h>
+#include <linux/hwmon.h>
+#include <linux/io.h>
+#include <linux/math.h>
+#include <linux/module.h>
+#include <linux/mutex.h>
+#include <linux/pci.h>
+#include <linux/pm_runtime.h>
+#include <linux/slab.h>
+#include <linux/usb.h>
+#include <linux/usb/hcd.h>
+
+#define PCI_DEVICE_ID_AMD_PROM21_XHCI 0x43fd
+
+#define PROM21_INDEX 0x3000
+#define PROM21_DATA 0x3008
+#define PROM21_TEMP_REG 0x0001e520
+
+#define PROM21_HWMON_NAME "prom21_hwmon"
+#define PROM21_TEMP_LABEL "xHCI"
+
+struct prom21_hwmon {
+ struct pci_dev *pdev;
+ struct device *hwmon_dev;
+ void __iomem *regs;
+ bool removing;
+ struct mutex lock; /* protects removing and the index/data registers */
+};
+
+static bool allow_pm_switch = true;
+module_param(allow_pm_switch, bool, 0444);
+MODULE_PARM_DESC(allow_pm_switch,
+ "Allow temperature reads to wake the xHCI PCI device");
+
+static void prom21_hwmon_invalidate(struct prom21_hwmon *hwmon)
+{
+ mutex_lock(&hwmon->lock);
+ hwmon->removing = true;
+ mutex_unlock(&hwmon->lock);
+}
+
+static int prom21_hwmon_pm_get(struct prom21_hwmon *hwmon, bool *pm_ref)
+{
+ struct device *dev = &hwmon->pdev->dev;
+ int ret;
+
+ *pm_ref = false;
+
+ /*
+ * PROM21 temperature register access does not return a valid value while
+ * the parent xHCI PCI function is suspended. By default, resume the xHC
+ * before touching MMIO. If allow_pm_switch=N, do not resume the xHC from
+ * a hwmon sysfs read; only read when runtime PM reports it as active, or
+ * when runtime PM is disabled and the device is not marked as suspended.
+ */
+ if (allow_pm_switch) {
+ ret = pm_runtime_resume_and_get(dev);
+ if (ret < 0)
+ return ret;
+
+ *pm_ref = true;
+ return 0;
+ }
+
+ ret = pm_runtime_get_if_active(dev);
+ if (ret > 0) {
+ *pm_ref = true;
+ return 0;
+ }
+
+ if (!ret || pm_runtime_status_suspended(dev))
+ return -EAGAIN;
+
+ if (ret == -EINVAL)
+ return 0;
+
+ return ret;
+}
+
+/*
+ * This is not a pure MMIO read. The PROM21 vendor data register is selected
+ * by temporarily writing PROM21_TEMP_REG to the vendor index register. Keep
+ * the sequence short and restore the previous index before returning.
+ */
+static int prom21_hwmon_read_temp_raw_restore_index(struct prom21_hwmon *hwmon,
+ u8 *raw)
+{
+ struct device *dev = &hwmon->pdev->dev;
+ bool pm_ref;
+ u32 index;
+ u32 data;
+ int ret;
+
+ /*
+ * The xHCI PCI remove path destroys the auxiliary device before HCD
+ * teardown. Keep runtime PM and MMIO inside the critical section so a
+ * sysfs read cannot use the vendor register pair after remove starts.
+ */
+ mutex_lock(&hwmon->lock);
+ if (hwmon->removing) {
+ mutex_unlock(&hwmon->lock);
+ return -ENODEV;
+ }
+
+ ret = prom21_hwmon_pm_get(hwmon, &pm_ref);
+ if (ret) {
+ mutex_unlock(&hwmon->lock);
+ return ret;
+ }
+
+ index = readl(hwmon->regs + PROM21_INDEX);
+ /* Select the PROM21 temperature register through the vendor index. */
+ writel(PROM21_TEMP_REG, hwmon->regs + PROM21_INDEX);
+ data = readl(hwmon->regs + PROM21_DATA);
+ /* Restore the previous vendor index register value. */
+ writel(index, hwmon->regs + PROM21_INDEX);
+ readl(hwmon->regs + PROM21_INDEX);
+
+ if (pm_ref) {
+ /*
+ * Use autosuspend so repeated sysfs reads do not suspend the
+ * controller immediately after each successful register access.
+ */
+ pm_runtime_mark_last_busy(dev);
+ pm_runtime_put_autosuspend(dev);
+ }
+ mutex_unlock(&hwmon->lock);
+
+ *raw = data & 0xff;
+ if (!*raw || *raw == 0xff)
+ return -ENODATA;
+
+ return 0;
+}
+
+static long prom21_hwmon_raw_to_millicelsius(u8 raw)
+{
+ /*
+ * No public AMD reference is available for this value.
+ * The scale was derived from observed PROM21 xHCI temperature readings:
+ * temp[C] = raw * 0.9066 - 78.624
+ */
+ return DIV_ROUND_CLOSEST(raw * 9066, 10) - 78624;
+}
+
+static umode_t prom21_hwmon_is_visible(const void *drvdata,
+ enum hwmon_sensor_types type, u32 attr,
+ int channel)
+{
+ if (type != hwmon_temp || channel)
+ return 0;
+
+ switch (attr) {
+ case hwmon_temp_input:
+ case hwmon_temp_label:
+ return 0444;
+ default:
+ return 0;
+ }
+}
+
+static int prom21_hwmon_read(struct device *dev, enum hwmon_sensor_types type,
+ u32 attr, int channel, long *val)
+{
+ struct prom21_hwmon *hwmon = dev_get_drvdata(dev);
+ u8 raw;
+ int ret;
+
+ if (type != hwmon_temp || attr != hwmon_temp_input || channel)
+ return -EOPNOTSUPP;
+
+ ret = prom21_hwmon_read_temp_raw_restore_index(hwmon, &raw);
+ if (ret)
+ return ret;
+
+ *val = prom21_hwmon_raw_to_millicelsius(raw);
+ return 0;
+}
+
+static int prom21_hwmon_read_string(struct device *dev,
+ enum hwmon_sensor_types type, u32 attr,
+ int channel, const char **str)
+{
+ if (type != hwmon_temp || attr != hwmon_temp_label || channel)
+ return -EOPNOTSUPP;
+
+ *str = PROM21_TEMP_LABEL;
+ return 0;
+}
+
+static const struct hwmon_ops prom21_hwmon_ops = {
+ .is_visible = prom21_hwmon_is_visible,
+ .read = prom21_hwmon_read,
+ .read_string = prom21_hwmon_read_string,
+};
+
+static const struct hwmon_channel_info *const prom21_hwmon_info[] = {
+ HWMON_CHANNEL_INFO(temp, HWMON_T_INPUT | HWMON_T_LABEL),
+ NULL,
+};
+
+static const struct hwmon_chip_info prom21_hwmon_chip_info = {
+ .ops = &prom21_hwmon_ops,
+ .info = prom21_hwmon_info,
+};
+
+static int prom21_hwmon_probe(struct auxiliary_device *auxdev,
+ const struct auxiliary_device_id *id)
+{
+ struct device *dev = &auxdev->dev;
+ struct device *parent = dev->parent;
+ struct prom21_hwmon *hwmon;
+ struct pci_dev *pdev;
+ struct usb_hcd *hcd;
+ int ret;
+
+ if (!parent || !dev_is_pci(parent))
+ return -ENODEV;
+
+ pdev = to_pci_dev(parent);
+ if (pdev->vendor != PCI_VENDOR_ID_AMD ||
+ pdev->device != PCI_DEVICE_ID_AMD_PROM21_XHCI)
+ return -ENODEV;
+
+ hcd = pci_get_drvdata(pdev);
+ if (!hcd)
+ return dev_err_probe(dev, -ENODEV,
+ "xHCI HCD data unavailable\n");
+
+ if (!hcd->regs || hcd->rsrc_len < PROM21_DATA + sizeof(u32))
+ return dev_err_probe(dev, -ENODEV, "invalid MMIO resource\n");
+
+ hwmon = devm_kzalloc(dev, sizeof(*hwmon), GFP_KERNEL);
+ if (!hwmon)
+ return -ENOMEM;
+
+ ret = devm_mutex_init(dev, &hwmon->lock);
+ if (ret)
+ return ret;
+
+ hwmon->pdev = pdev;
+ hwmon->regs = hcd->regs;
+ auxiliary_set_drvdata(auxdev, hwmon);
+
+ /*
+ * Use the PCI function as the hwmon parent so user space reports it as
+ * a PCI adapter. Lifetime is still owned by this auxiliary driver;
+ * remove() unregisters the hwmon device before xhci-pci tears down the
+ * HCD.
+ */
+ hwmon->hwmon_dev =
+ hwmon_device_register_with_info(&pdev->dev, PROM21_HWMON_NAME,
+ hwmon, &prom21_hwmon_chip_info,
+ NULL);
+ if (IS_ERR(hwmon->hwmon_dev))
+ return PTR_ERR(hwmon->hwmon_dev);
+
+ return 0;
+}
+
+static void prom21_hwmon_remove(struct auxiliary_device *auxdev)
+{
+ struct prom21_hwmon *hwmon = auxiliary_get_drvdata(auxdev);
+
+ if (hwmon) {
+ prom21_hwmon_invalidate(hwmon);
+ hwmon_device_unregister(hwmon->hwmon_dev);
+ }
+}
+
+static const struct auxiliary_device_id prom21_hwmon_id_table[] = {
+ { .name = "xhci_pci.hwmon" },
+ {}
+};
+MODULE_DEVICE_TABLE(auxiliary, prom21_hwmon_id_table);
+
+static struct auxiliary_driver prom21_hwmon_driver = {
+ .name = "prom21-hwmon",
+ .probe = prom21_hwmon_probe,
+ .remove = prom21_hwmon_remove,
+ .id_table = prom21_hwmon_id_table,
+};
+module_auxiliary_driver(prom21_hwmon_driver);
+
+MODULE_AUTHOR("Jihong Min <hurryman2212@gmail.com>");
+MODULE_DESCRIPTION("AMD PROM21 xHCI hwmon driver");
+MODULE_LICENSE("GPL");
--
2.53.0
^ permalink raw reply related
* [PATCH v2 1/2] usb: xhci-pci: add generic auxiliary device interface
From: Jihong Min @ 2026-05-06 20:40 UTC (permalink / raw)
To: Greg Kroah-Hartman, Mathias Nyman
Cc: Guenter Roeck, Jonathan Corbet, Shuah Khan, Mario Limonciello,
Basavaraj Natikar, linux-usb, linux-hwmon, linux-doc, linux-pci,
linux-kernel, Jihong Min
In-Reply-To: <cover.1778099627.git.hurryman2212@gmail.com>
Some xHCI PCI controllers expose controller-specific functionality that is
not part of generic xHCI operation and is better handled by optional child
drivers in other subsystems. Add a small auxiliary device registration path
for selected xHCI PCI controllers.
The initial table creates an xhci_pci.hwmon auxiliary device for AMD
1022:43fd controllers. Store the created auxiliary device in devres so the
xhci-pci remove path destroys it before HCD teardown. Use a
PCI-domain-qualified id so auxiliary device names remain unique across PCI
domains.
This keeps xhci-pci responsible only for publishing selected controller
functions while allowing subsystem-specific drivers to bind through the
auxiliary bus.
Assisted-by: Codex:gpt-5.5
Signed-off-by: Jihong Min <hurryman2212@gmail.com>
---
drivers/usb/host/Kconfig | 10 ++++
drivers/usb/host/xhci-pci.c | 114 ++++++++++++++++++++++++++++++++++++
2 files changed, 124 insertions(+)
diff --git a/drivers/usb/host/Kconfig b/drivers/usb/host/Kconfig
index 0a277a07cf70..e0c2c7ac5c97 100644
--- a/drivers/usb/host/Kconfig
+++ b/drivers/usb/host/Kconfig
@@ -42,6 +42,16 @@ config USB_XHCI_PCI
depends on USB_PCI
default y
+config USB_XHCI_PCI_AUXDEV
+ bool "xHCI PCI auxiliary device support"
+ depends on USB_XHCI_PCI
+ select AUXILIARY_BUS
+ help
+ This enables xHCI PCI support for registering auxiliary devices
+ for selected controllers. It is used by optional child drivers
+ that bind to xHCI PCI controller-specific functionality through
+ the auxiliary bus.
+
config USB_XHCI_PCI_RENESAS
tristate "Support for additional Renesas xHCI controller with firmware"
depends on USB_XHCI_PCI
diff --git a/drivers/usb/host/xhci-pci.c b/drivers/usb/host/xhci-pci.c
index 585b2f3117b0..1ab27d2182eb 100644
--- a/drivers/usb/host/xhci-pci.c
+++ b/drivers/usb/host/xhci-pci.c
@@ -8,6 +8,8 @@
* Some code borrowed from the Linux EHCI driver.
*/
+#include <linux/auxiliary_bus.h>
+#include <linux/device/devres.h>
#include <linux/pci.h>
#include <linux/slab.h>
#include <linux/module.h>
@@ -103,6 +105,114 @@ static int xhci_pci_run(struct usb_hcd *hcd);
static int xhci_pci_update_hub_device(struct usb_hcd *hcd, struct usb_device *hdev,
struct usb_tt *tt, gfp_t mem_flags);
+#if IS_ENABLED(CONFIG_USB_XHCI_PCI_AUXDEV)
+static const struct {
+ struct pci_device_id id;
+ const char *aux_dev_name;
+} pci_ids_have_aux[] = {
+ {
+ .id = { PCI_DEVICE(PCI_VENDOR_ID_AMD, 0x43fd) }, /* PROM21 xHCI */
+ .aux_dev_name = "hwmon",
+ },
+ { /* end: all zeroes */ }
+};
+
+struct xhci_pci_aux_devres {
+ struct auxiliary_device *auxdev;
+};
+
+static bool xhci_pci_aux_match_id(const struct pci_device_id *id,
+ const struct pci_dev *pdev)
+{
+ if (id->vendor != PCI_ANY_ID && id->vendor != pdev->vendor)
+ return false;
+ if (id->device != PCI_ANY_ID && id->device != pdev->device)
+ return false;
+ if (id->subvendor != PCI_ANY_ID &&
+ id->subvendor != pdev->subsystem_vendor)
+ return false;
+ if (id->subdevice != PCI_ANY_ID &&
+ id->subdevice != pdev->subsystem_device)
+ return false;
+
+ return !((id->class ^ pdev->class) & id->class_mask);
+}
+
+static const char *xhci_pci_aux_dev_name(struct pci_dev *pdev)
+{
+ int i;
+
+ for (i = 0; pci_ids_have_aux[i].aux_dev_name; i++) {
+ if (xhci_pci_aux_match_id(&pci_ids_have_aux[i].id, pdev))
+ return pci_ids_have_aux[i].aux_dev_name;
+ }
+
+ return NULL;
+}
+
+static void xhci_pci_aux_devres_release(struct device *dev, void *res)
+{
+ struct xhci_pci_aux_devres *devres = res;
+
+ if (devres->auxdev)
+ auxiliary_device_destroy(devres->auxdev);
+}
+
+static void xhci_pci_try_add_aux_device(struct pci_dev *pdev)
+{
+ struct xhci_pci_aux_devres *devres;
+ struct auxiliary_device *auxdev;
+ const char *aux_dev_name;
+
+ aux_dev_name = xhci_pci_aux_dev_name(pdev);
+ if (!aux_dev_name)
+ return;
+
+ devres = devres_alloc(xhci_pci_aux_devres_release, sizeof(*devres),
+ GFP_KERNEL);
+ if (!devres) {
+ dev_warn(&pdev->dev,
+ "failed to allocate auxiliary device state\n");
+ return;
+ }
+
+ auxdev = auxiliary_device_create(&pdev->dev, KBUILD_MODNAME,
+ aux_dev_name, NULL,
+ (pci_domain_nr(pdev->bus) << 16) |
+ pci_dev_id(pdev));
+ if (!auxdev) {
+ devres_free(devres);
+ dev_warn(&pdev->dev, "failed to add %s auxiliary device\n",
+ aux_dev_name);
+ return;
+ }
+
+ devres->auxdev = auxdev;
+ devres_add(&pdev->dev, devres);
+}
+
+static void xhci_pci_try_remove_aux_device(struct pci_dev *pdev)
+{
+ struct xhci_pci_aux_devres *devres;
+
+ devres = devres_find(&pdev->dev, xhci_pci_aux_devres_release, NULL,
+ NULL);
+ if (!devres || !devres->auxdev)
+ return;
+
+ auxiliary_device_destroy(devres->auxdev);
+ devres->auxdev = NULL;
+}
+#else
+static inline void xhci_pci_try_add_aux_device(struct pci_dev *pdev)
+{
+}
+
+static inline void xhci_pci_try_remove_aux_device(struct pci_dev *pdev)
+{
+}
+#endif
+
static const struct xhci_driver_overrides xhci_pci_overrides __initconst = {
.reset = xhci_pci_setup,
.start = xhci_pci_run,
@@ -677,6 +787,8 @@ int xhci_pci_common_probe(struct pci_dev *dev, const struct pci_device_id *id)
if (device_property_read_bool(&dev->dev, "ti,pwron-active-high"))
pci_clear_and_set_config_dword(dev, 0xE0, 0, 1 << 22);
+ xhci_pci_try_add_aux_device(dev);
+
return 0;
put_usb3_hcd:
@@ -713,6 +825,8 @@ void xhci_pci_remove(struct pci_dev *dev)
xhci = hcd_to_xhci(pci_get_drvdata(dev));
set_power_d3 = xhci->quirks & XHCI_SPURIOUS_WAKEUP;
+ xhci_pci_try_remove_aux_device(dev);
+
xhci->xhc_state |= XHCI_STATE_REMOVING;
if (pci_choose_state(dev, PMSG_SUSPEND) == PCI_D0)
--
2.53.0
^ permalink raw reply related
* [PATCH v2 0/2] AMD PROM21 xHCI temperature hwmon support
From: Jihong Min @ 2026-05-06 20:40 UTC (permalink / raw)
To: Greg Kroah-Hartman, Mathias Nyman
Cc: Guenter Roeck, Jonathan Corbet, Shuah Khan, Mario Limonciello,
Basavaraj Natikar, linux-usb, linux-hwmon, linux-doc, linux-pci,
linux-kernel, Jihong Min
In-Reply-To: <20260506032939.92351-1-hurryman2212@gmail.com>
Hi,
This series adds hwmon support for the temperature sensor exposed by AMD
PROM21 xHCI controllers. The temperature value is read through a
vendor-specific index/data register pair in the xHCI PCI MMIO BAR.
v1 implemented this directly under drivers/usb/host. Based on review
feedback, v2 splits the support into a generic xhci-pci auxiliary-device
interface and a standalone hwmon driver under drivers/hwmon. xhci-pci
creates the auxiliary child only for PCI IDs matched by its internal table,
currently only AMD 1022:43fd, and the hwmon driver binds to that child
through the auxiliary bus.
The PROM21 hwmon driver registers the hwmon device under the parent PCI
function so userspace reports it as a PCI adapter. The auxiliary driver
still owns the lifetime and unregisters the hwmon device before xhci-pci
tears down the HCD.
I tested register access while the parent xHCI PCI function was suspended.
The temperature register did not return a valid value without
runtime-resuming the device. v2 therefore keeps the default behavior of
allowing a temperature read to wake the xHCI PCI device, and adds
allow_pm_switch=N for users who prefer reads not to wake the device. In
that mode a read returns -EAGAIN while the device is suspended.
Changes in v2:
- split the original single patch into a two-patch series
- add a generic xhci-pci auxiliary-device interface
- move PROM21 hwmon support to drivers/hwmon as an auxiliary driver
- avoid linking hwmon-specific code into xhci-hcd
- add Documentation/hwmon/prom21-hwmon.rst
- document register offsets, conversion formula, sysfs attributes, and
allow_pm_switch behavior
Sincerely,
Jihong Min
Jihong Min (2):
usb: xhci-pci: add generic auxiliary device interface
hwmon: add initial support for AMD PROM21 xHCI temperature sensor
Documentation/hwmon/index.rst | 1 +
Documentation/hwmon/prom21-hwmon.rst | 84 ++++++++
drivers/hwmon/Kconfig | 11 +
drivers/hwmon/Makefile | 1 +
drivers/hwmon/prom21-hwmon.c | 300 +++++++++++++++++++++++++++
drivers/usb/host/Kconfig | 10 +
drivers/usb/host/xhci-pci.c | 114 ++++++++++
7 files changed, 521 insertions(+)
create mode 100644 Documentation/hwmon/prom21-hwmon.rst
create mode 100644 drivers/hwmon/prom21-hwmon.c
--
2.53.0
^ permalink raw reply
* Re: [PATCH v11 02/11] lib: kstrtox: add kstrtoudec64() and kstrtodec64()
From: Randy Dunlap @ 2026-05-06 20:07 UTC (permalink / raw)
To: rodrigo.alencar, linux-kernel, linux-iio, devicetree, linux-doc
Cc: Jonathan Cameron, David Lechner, Andy Shevchenko,
Lars-Peter Clausen, Michael Hennerich, Rob Herring,
Krzysztof Kozlowski, Conor Dooley, Jonathan Corbet, Andrew Morton,
Petr Mladek, Steven Rostedt, Andy Shevchenko, Rasmus Villemoes,
Sergey Senozhatsky, Shuah Khan
In-Reply-To: <20260506-adf41513-iio-driver-v11-2-2b7e99cfe8f2@analog.com>
On 5/6/26 7:08 AM, Rodrigo Alencar via B4 Relay wrote:
> +/**
> + * kstrtoudec64 - convert a string to an unsigned 64-bit decimal number
> + * @s: The start of the string. The string must be null-terminated, and may also
> + * include a single newline before its terminating null. The first character
> + * may also be a plus sign, but not a minus sign. Digits beyond the specified
> + * scale are ignored.
> + * @scale: The number of digits to the right of the decimal point. For example,
> + * a scale of 2 would mean the number is represented with two decimal places,
> + * so "123.45" would be represented as 12345.
> + * @res: Where to write the result of the conversion on success.
> + *
> + * Returns 0 on success, -ERANGE on overflow and -EINVAL on parsing error.
Use
* Return:
or
* Returns:
please.
> + */
> +noinline
> +int kstrtoudec64(const char *s, unsigned int scale, u64 *res)
> +{
> + if (s[0] == '+')
> + s++;
> + return _kstrtoudec64(s, scale, res);
> +}
> +EXPORT_SYMBOL(kstrtoudec64);
> +
> +/**
> + * kstrtodec64 - convert a string to a signed 64-bit decimal number
> + * @s: The start of the string. The string must be null-terminated, and may also
> + * include a single newline before its terminating null. The first character
> + * may also be a plus sign or a minus sign. Digits beyond the specified
> + * scale are ignored.
> + * @scale: The number of digits to the right of the decimal point. For example,
> + * a scale of 5 would mean the number is represented with five decimal places,
> + * so "-3.141592" would be represented as -314159.
> + * @res: Where to write the result of the conversion on success.
> + *
> + * Returns 0 on success, -ERANGE on overflow and -EINVAL on parsing error.
Same here.
> + */
> +noinline
> +int kstrtodec64(const char *s, unsigned int scale, s64 *res)
> +{
--
~Randy
^ permalink raw reply
* [PATCH v8 6/6] ARM: zte: defconfig: Add a zx29 defconfig file
From: Stefan Dösinger @ 2026-05-06 19:33 UTC (permalink / raw)
To: Jonathan Corbet, Shuah Khan, Russell King, Rob Herring,
Krzysztof Kozlowski, Conor Dooley, Arnd Bergmann,
Krzysztof Kozlowski, Alexandre Belloni, Linus Walleij,
Drew Fustini, Greg Kroah-Hartman, Jiri Slaby
Cc: linux-doc, linux-kernel, linux-arm-kernel, devicetree, soc,
linux-serial, Stefan Dösinger
In-Reply-To: <20260506-send-v8-0-f1bdf3243b34@gmail.com>
This enables existing drivers for hardware that is present on this board
even if it is not present in the DT yet.
Reviewed-by: Linus Walleij <linusw@kernel.org>
Signed-off-by: Stefan Dösinger <stefandoesinger@gmail.com>
---
Changes: v8: Remove BINFMT_FLAT. I have no idea how that slipped in (Sashiko)
Changes: v5 to v6: Regenerate the file with make savedefconfig.
An open question: What's the appropriate name? zx29_defconfig?
zte_defconfig? zte_zx29_defconfig? There's e.g. stm32_defconfig without
an extra mention of STMicro in the name.
---
MAINTAINERS | 1 +
arch/arm/configs/zx29_defconfig | 53 +++++++++++++++++++++++++++++++++++++++++
2 files changed, 54 insertions(+)
diff --git a/MAINTAINERS b/MAINTAINERS
index b0b774aace55..0b392a364e32 100644
--- a/MAINTAINERS
+++ b/MAINTAINERS
@@ -3777,6 +3777,7 @@ M: Stefan Dösinger <stefandoesinger@gmail.com>
F: Documentation/arch/arm/zte/
F: Documentation/devicetree/bindings/arm/zte.yaml
F: arch/arm/boot/dts/zte/
+F: arch/arm/configs/zx29_defconfig
F: arch/arm/mach-zte/
ARM/ZYNQ ARCHITECTURE
diff --git a/arch/arm/configs/zx29_defconfig b/arch/arm/configs/zx29_defconfig
new file mode 100644
index 000000000000..b7f77e7a618f
--- /dev/null
+++ b/arch/arm/configs/zx29_defconfig
@@ -0,0 +1,53 @@
+CONFIG_SYSVIPC=y
+CONFIG_BLK_DEV_INITRD=y
+# CONFIG_RD_BZIP2 is not set
+# CONFIG_RD_LZMA is not set
+# CONFIG_RD_XZ is not set
+# CONFIG_RD_LZ4 is not set
+CONFIG_EXPERT=y
+CONFIG_KALLSYMS_ALL=y
+CONFIG_ARCH_ZTE=y
+CONFIG_ARM_PSCI=y
+CONFIG_ARM_APPENDED_DTB=y
+CONFIG_CMDLINE="console=ttyAMA0 earlyprintk root=/dev/ram rw"
+CONFIG_CPU_FREQ=y
+CONFIG_CPUFREQ_DT_PLATDEV=y
+# CONFIG_SUSPEND is not set
+CONFIG_PM=y
+CONFIG_NET=y
+CONFIG_PACKET=y
+CONFIG_UNIX=y
+CONFIG_INET=y
+# CONFIG_STANDALONE is not set
+# CONFIG_PREVENT_FIRMWARE_BUILD is not set
+# CONFIG_ALLOW_DEV_COREDUMP is not set
+CONFIG_MTD=y
+CONFIG_MTD_BLOCK=y
+CONFIG_BLK_DEV_RAM=y
+CONFIG_BLK_DEV_RAM_COUNT=4
+CONFIG_SRAM=y
+CONFIG_KEYBOARD_GPIO_POLLED=y
+# CONFIG_INPUT_MOUSE is not set
+CONFIG_VT_HW_CONSOLE_BINDING=y
+CONFIG_SERIAL_AMBA_PL011=y
+CONFIG_SERIAL_AMBA_PL011_CONSOLE=y
+CONFIG_SERIAL_DEV_BUS=y
+# CONFIG_HW_RANDOM is not set
+CONFIG_PINCTRL=y
+CONFIG_GPIOLIB=y
+CONFIG_GPIO_GENERIC_PLATFORM=y
+CONFIG_POWER_RESET=y
+CONFIG_MFD_SYSCON=y
+CONFIG_REGULATOR=y
+CONFIG_REGULATOR_FIXED_VOLTAGE=y
+# CONFIG_HID is not set
+CONFIG_USB_DWC2=y
+CONFIG_USB_GADGET=y
+CONFIG_MMC=y
+CONFIG_MMC_DW=y
+CONFIG_RESET_CONTROLLER=y
+CONFIG_RESET_SIMPLE=y
+CONFIG_JFFS2_FS=y
+CONFIG_PRINTK_TIME=y
+CONFIG_DEBUG_LL=y
+CONFIG_EARLY_PRINTK=y
--
2.53.0
^ permalink raw reply related
* [PATCH v8 5/6] ARM: dts: zte: Add D-Link DWR-932M support
From: Stefan Dösinger @ 2026-05-06 19:33 UTC (permalink / raw)
To: Jonathan Corbet, Shuah Khan, Russell King, Rob Herring,
Krzysztof Kozlowski, Conor Dooley, Arnd Bergmann,
Krzysztof Kozlowski, Alexandre Belloni, Linus Walleij,
Drew Fustini, Greg Kroah-Hartman, Jiri Slaby
Cc: linux-doc, linux-kernel, linux-arm-kernel, devicetree, soc,
linux-serial, Stefan Dösinger
In-Reply-To: <20260506-send-v8-0-f1bdf3243b34@gmail.com>
This adds base DT definition for zx297520v3 and one board that consumes it.
The stock kernel does not use the armv7 timer, but it seems to work
fine. The board has other board-specific timers that would need a driver
and I see no reason to bother with them since the arm standard timer
works.
The caveat is the non-standard GIC setup needed to handle the timer's
level-low PPI. This is the responsibility of the boot loader and
documented in Documentation/arch/arm/zte/zx297520v3.rst.
Reviewed-by: Linus Walleij <linusw@kernel.org>
Signed-off-by: Stefan Dösinger <stefandoesinger@gmail.com>
---
Changes in
v8: Remove redundant label, use "arm,pl011" for uart0 and 2 too.
v6: Squash board + timer + uart patches into one
v5: Prepend the SoC name in the device specific DTS filename.
v4:
Declare all uarts
Remove the UART aliases for now. I can revisit this when I get my
hands on a board that exposes two UARTs.
---
MAINTAINERS | 1 +
arch/arm/boot/dts/Makefile | 1 +
arch/arm/boot/dts/zte/Makefile | 3 +
arch/arm/boot/dts/zte/zx297520v3-dlink-dwr932m.dts | 22 +++++
arch/arm/boot/dts/zte/zx297520v3.dtsi | 103 +++++++++++++++++++++
5 files changed, 130 insertions(+)
diff --git a/MAINTAINERS b/MAINTAINERS
index 697287d1b372..b0b774aace55 100644
--- a/MAINTAINERS
+++ b/MAINTAINERS
@@ -3776,6 +3776,7 @@ ARM/ZTE ZX29 SOC SUPPORT
M: Stefan Dösinger <stefandoesinger@gmail.com>
F: Documentation/arch/arm/zte/
F: Documentation/devicetree/bindings/arm/zte.yaml
+F: arch/arm/boot/dts/zte/
F: arch/arm/mach-zte/
ARM/ZYNQ ARCHITECTURE
diff --git a/arch/arm/boot/dts/Makefile b/arch/arm/boot/dts/Makefile
index efe38eb25301..28fba538d552 100644
--- a/arch/arm/boot/dts/Makefile
+++ b/arch/arm/boot/dts/Makefile
@@ -39,3 +39,4 @@ subdir-y += unisoc
subdir-y += vt8500
subdir-y += xen
subdir-y += xilinx
+subdir-y += zte
diff --git a/arch/arm/boot/dts/zte/Makefile b/arch/arm/boot/dts/zte/Makefile
new file mode 100644
index 000000000000..f052cfbd636c
--- /dev/null
+++ b/arch/arm/boot/dts/zte/Makefile
@@ -0,0 +1,3 @@
+# SPDX-License-Identifier: GPL-2.0-only
+dtb-$(CONFIG_SOC_ZX297520V3) += \
+ zx297520v3-dlink-dwr932m.dtb
diff --git a/arch/arm/boot/dts/zte/zx297520v3-dlink-dwr932m.dts b/arch/arm/boot/dts/zte/zx297520v3-dlink-dwr932m.dts
new file mode 100644
index 000000000000..1700f46aba86
--- /dev/null
+++ b/arch/arm/boot/dts/zte/zx297520v3-dlink-dwr932m.dts
@@ -0,0 +1,22 @@
+// SPDX-License-Identifier: GPL-2.0-only
+/*
+ * Copyright (c) 2026 Stefan Dösinger <stefandoesinger@gmail.com>
+ */
+
+/dts-v1/;
+
+#include "zx297520v3.dtsi"
+
+/ {
+ model = "D-Link DWR-932M";
+ compatible = "dlink,dwr932m", "zte,zx297520v3";
+
+ memory@20000000 {
+ device_type = "memory";
+ reg = <0x20000000 0x04000000>;
+ };
+};
+
+&uart1 {
+ status = "okay";
+};
diff --git a/arch/arm/boot/dts/zte/zx297520v3.dtsi b/arch/arm/boot/dts/zte/zx297520v3.dtsi
new file mode 100644
index 000000000000..a16c30a164bb
--- /dev/null
+++ b/arch/arm/boot/dts/zte/zx297520v3.dtsi
@@ -0,0 +1,103 @@
+// SPDX-License-Identifier: GPL-2.0-only
+/*
+ * Copyright (c) 2026 Stefan Dösinger <stefandoesinger@gmail.com>
+ */
+
+#include <dt-bindings/interrupt-controller/arm-gic.h>
+
+/ {
+ #address-cells = <1>;
+ #size-cells = <1>;
+
+ cpus {
+ #address-cells = <1>;
+ #size-cells = <0>;
+
+ cpu@0 {
+ device_type = "cpu";
+ compatible = "arm,cortex-a53";
+ reg = <0>;
+ };
+ };
+
+ /* Base bus clock and default for the UART. It will be replaced once a clock driver has
+ * been added.
+ */
+ uartclk: uartclk-26000000 {
+ #clock-cells = <0>;
+ compatible = "fixed-clock";
+ clock-frequency = <26000000>;
+ };
+
+ timer {
+ compatible = "arm,armv7-timer";
+ interrupts = <GIC_PPI 13 IRQ_TYPE_LEVEL_LOW>,
+ <GIC_PPI 14 IRQ_TYPE_LEVEL_LOW>,
+ <GIC_PPI 11 IRQ_TYPE_LEVEL_LOW>,
+ <GIC_PPI 10 IRQ_TYPE_LEVEL_LOW>;
+ clock-frequency = <26000000>;
+ interrupt-parent = <&gic>;
+ /* I don't think uboot sets CNTVOFF and the stock kernel doesn't use the
+ * arm timer at all. Since this is a single CPU system I don't think it
+ * really matters that the offset is random though.
+ */
+ arm,cpu-registers-not-fw-configured;
+ };
+
+ soc {
+ #address-cells = <1>;
+ #size-cells = <1>;
+ compatible = "simple-bus";
+ interrupt-parent = <&gic>;
+ ranges;
+
+ /* The GIC has a non-standard way of configuring ints between level-low/level
+ * high or rising edge/falling edge at 0xf2202070 and onwards. See AP_INT_MODE_BASE
+ * and AP_PPI_MODE_REG in the ZTE kernel, although the offsets in the kernel source
+ * seem wrong.
+ *
+ * Everything defaults to active-high/rising edge, but the timer is active-low. We
+ * currently rely on the boot loader to change timer IRQs to active-low for us for
+ * now.
+ */
+ gic: interrupt-controller@f2000000 {
+ compatible = "arm,gic-v3";
+ interrupt-controller;
+ #interrupt-cells = <3>;
+ #address-cells = <1>;
+ #size-cells = <1>;
+ reg = <0xf2000000 0x10000>,
+ <0xf2040000 0x20000>;
+ };
+
+ uart0: serial@131000 {
+ compatible = "arm,pl011", "arm,primecell";
+ arm,primecell-periphid = <0x0018c011>;
+ reg = <0x00131000 0x1000>;
+ interrupts = <GIC_SPI 0 IRQ_TYPE_LEVEL_HIGH>;
+ clocks = <&uartclk>, <&uartclk>;
+ clock-names = "uartclk", "apb_pclk";
+ status = "disabled";
+ };
+
+ uart1: serial@1408000 {
+ compatible = "arm,pl011", "arm,primecell";
+ arm,primecell-periphid = <0x0018c011>;
+ reg = <0x01408000 0x1000>;
+ interrupts = <GIC_SPI 1 IRQ_TYPE_LEVEL_HIGH>;
+ clocks = <&uartclk>, <&uartclk>;
+ clock-names = "uartclk", "apb_pclk";
+ status = "disabled";
+ };
+
+ uart2: serial@140d000 {
+ compatible = "arm,pl011", "arm,primecell";
+ arm,primecell-periphid = <0x0018c011>;
+ reg = <0x0140d000 0x1000>;
+ interrupts = <GIC_SPI 2 IRQ_TYPE_LEVEL_HIGH>;
+ clocks = <&uartclk>, <&uartclk>;
+ clock-names = "uartclk", "apb_pclk";
+ status = "disabled";
+ };
+ };
+};
--
2.53.0
^ permalink raw reply related
* [PATCH v8 4/6] amba/serial: amba-pl011: Bring back zx29 UART support
From: Stefan Dösinger @ 2026-05-06 19:33 UTC (permalink / raw)
To: Jonathan Corbet, Shuah Khan, Russell King, Rob Herring,
Krzysztof Kozlowski, Conor Dooley, Arnd Bergmann,
Krzysztof Kozlowski, Alexandre Belloni, Linus Walleij,
Drew Fustini, Greg Kroah-Hartman, Jiri Slaby
Cc: linux-doc, linux-kernel, linux-arm-kernel, devicetree, soc,
linux-serial, Stefan Dösinger
In-Reply-To: <20260506-send-v8-0-f1bdf3243b34@gmail.com>
This is based on code removed in commit 89d4f98ae90d ("ARM: remove zte
zx platform"). I did not bring back the zx29-uart .compatible as the
arm,primecell-periphid does the job.
Reviewed-by: Linus Walleij <linusw@kernel.org>
Signed-off-by: Stefan Dösinger <stefandoesinger@gmail.com>
---
Changes since v4:
Use ZTE's JEDEC ID instead of 0xfe for the DT-Provided AMBA ID.
---
drivers/tty/serial/amba-pl011.c | 42 +++++++++++++++++++++++++++++++++++++++++
1 file changed, 42 insertions(+)
diff --git a/drivers/tty/serial/amba-pl011.c b/drivers/tty/serial/amba-pl011.c
index 7f17d288c807..f24cc403d9e0 100644
--- a/drivers/tty/serial/amba-pl011.c
+++ b/drivers/tty/serial/amba-pl011.c
@@ -216,6 +216,38 @@ static struct vendor_data vendor_st = {
.get_fifosize = get_fifosize_st,
};
+static const u16 pl011_zte_offsets[REG_ARRAY_SIZE] = {
+ [REG_DR] = ZX_UART011_DR,
+ [REG_FR] = ZX_UART011_FR,
+ [REG_LCRH_RX] = ZX_UART011_LCRH,
+ [REG_LCRH_TX] = ZX_UART011_LCRH,
+ [REG_IBRD] = ZX_UART011_IBRD,
+ [REG_FBRD] = ZX_UART011_FBRD,
+ [REG_CR] = ZX_UART011_CR,
+ [REG_IFLS] = ZX_UART011_IFLS,
+ [REG_IMSC] = ZX_UART011_IMSC,
+ [REG_RIS] = ZX_UART011_RIS,
+ [REG_MIS] = ZX_UART011_MIS,
+ [REG_ICR] = ZX_UART011_ICR,
+ [REG_DMACR] = ZX_UART011_DMACR,
+};
+
+static unsigned int get_fifosize_zte(struct amba_device *dev)
+{
+ return 16;
+}
+
+static struct vendor_data vendor_zte = {
+ .reg_offset = pl011_zte_offsets,
+ .access_32b = true,
+ .ifls = UART011_IFLS_RX4_8 | UART011_IFLS_TX4_8,
+ .fr_busy = ZX_UART01x_FR_BUSY,
+ .fr_dsr = ZX_UART01x_FR_DSR,
+ .fr_cts = ZX_UART01x_FR_CTS,
+ .fr_ri = ZX_UART011_FR_RI,
+ .get_fifosize = get_fifosize_zte,
+};
+
/* Deals with DMA transactions */
struct pl011_dmabuf {
@@ -3081,6 +3113,16 @@ static const struct amba_id pl011_ids[] = {
.mask = 0x00ffffff,
.data = &vendor_st,
},
+ {
+ /* This is an invented ID. The actual hardware that contains
+ * these ZTE UARTs (zx29 boards) has no AMBA PIDs stored. ZTE
+ * JEDEC ID (ignoring banks) and the "011" part number as used
+ * by ARM.
+ */
+ .id = 0x0008c011,
+ .mask = 0x000fffff,
+ .data = &vendor_zte,
+ },
{ 0, 0 },
};
--
2.53.0
^ permalink raw reply related
* [PATCH v8 3/6] ARM: zte: Add support for zx29 low level debug
From: Stefan Dösinger @ 2026-05-06 19:33 UTC (permalink / raw)
To: Jonathan Corbet, Shuah Khan, Russell King, Rob Herring,
Krzysztof Kozlowski, Conor Dooley, Arnd Bergmann,
Krzysztof Kozlowski, Alexandre Belloni, Linus Walleij,
Drew Fustini, Greg Kroah-Hartman, Jiri Slaby
Cc: linux-doc, linux-kernel, linux-arm-kernel, devicetree, soc,
linux-serial, Stefan Dösinger
In-Reply-To: <20260506-send-v8-0-f1bdf3243b34@gmail.com>
This is based on the removed zx29 code. A separate (more complicated)
patch will re-add the register map to the pl011 serial driver.
Reviewed-by: Linus Walleij <linusw@kernel.org>
Signed-off-by: Stefan Dösinger <stefandoesinger@gmail.com>
---
Patch changelog:
v8: Adjust UART01x_FR_BUSY to match the different ZX UART registers
(Sashiko). I am unsure about UART01x_FR_TXFF and my boards do not expose
flow control pins to allow me to test if it works.
I am unsure about the virtual address. It doesn't seem to matter, as
long as it is a valid address. This address is based on the old removed
code. Is there a rule-of-thumb physical to virtual mapping I can use to
give a sensible default value?
---
arch/arm/Kconfig.debug | 12 ++++++++++++
arch/arm/include/debug/pl01x.S | 9 +++++++++
2 files changed, 21 insertions(+)
diff --git a/arch/arm/Kconfig.debug b/arch/arm/Kconfig.debug
index 366f162e147d..98d8a5a60048 100644
--- a/arch/arm/Kconfig.debug
+++ b/arch/arm/Kconfig.debug
@@ -1331,6 +1331,16 @@ choice
This option selects UART0 on VIA/Wondermedia System-on-a-chip
devices, including VT8500, WM8505, WM8650 and WM8850.
+ config DEBUG_ZTE_ZX
+ bool "Kernel low-level debugging via zx29 UART"
+ select DEBUG_UART_PL01X
+ depends on ARCH_ZTE
+ help
+ Say Y here if you are enabling ZTE zx297520v3 SOC and need
+ debug UART support. This UART is a PL011 with different
+ register addresses. The UART for boot messages on zx29 boards
+ is usually UART1 and is operating at 921600 8N1.
+
config DEBUG_ZYNQ_UART0
bool "Kernel low-level debugging on Xilinx Zynq using UART0"
depends on ARCH_ZYNQ
@@ -1545,6 +1555,7 @@ config DEBUG_UART_8250
config DEBUG_UART_PHYS
hex "Physical base address of debug UART"
+ default 0x01408000 if DEBUG_ZTE_ZX
default 0x01c28000 if DEBUG_SUNXI_UART0
default 0x01c28400 if DEBUG_SUNXI_UART1
default 0x01d0c000 if DEBUG_DAVINCI_DA8XX_UART1
@@ -1701,6 +1712,7 @@ config DEBUG_UART_VIRT
default 0xf31004c0 if DEBUG_MESON_UARTAO
default 0xf4090000 if DEBUG_LPC32XX
default 0xf4200000 if DEBUG_GEMINI
+ default 0xf4708000 if DEBUG_ZTE_ZX
default 0xf6200000 if DEBUG_PXA_UART1
default 0xf7000000 if DEBUG_SUN9I_UART0
default 0xf7000000 if DEBUG_S3C64XX_UART && DEBUG_S3C_UART0
diff --git a/arch/arm/include/debug/pl01x.S b/arch/arm/include/debug/pl01x.S
index c7e02d0628bf..9dcdeed2357d 100644
--- a/arch/arm/include/debug/pl01x.S
+++ b/arch/arm/include/debug/pl01x.S
@@ -8,6 +8,15 @@
*/
#include <linux/amba/serial.h>
+#ifdef CONFIG_DEBUG_ZTE_ZX
+#undef UART01x_DR
+#undef UART01x_FR
+#undef UART01x_FR_BUSY
+#define UART01x_DR 0x04
+#define UART01x_FR 0x14
+#define UART01x_FR_BUSY (1<<8)
+#endif
+
#ifdef CONFIG_DEBUG_UART_PHYS
.macro addruart, rp, rv, tmp
ldr \rp, =CONFIG_DEBUG_UART_PHYS
--
2.53.0
^ permalink raw reply related
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