* Re: [PATCH v2 04/14] mm: add VM_UFFD_RWP VMA flag
From: Kiryl Shutsemau @ 2026-05-22 10:54 UTC (permalink / raw)
To: SeongJae Park
Cc: akpm, rppt, peterx, david, ljs, surenb, vbabka, Liam.Howlett, ziy,
corbet, skhan, seanjc, pbonzini, jthoughton, aarcange, usama.arif,
linux-mm, linux-kernel, linux-doc, linux-kselftest, kvm,
kernel-team
In-Reply-To: <20260515002932.124892-1-sj@kernel.org>
On Thu, May 14, 2026 at 05:29:31PM -0700, SeongJae Park wrote:
> On Fri, 8 May 2026 16:55:16 +0100 "Kiryl Shutsemau (Meta)" <kas@kernel.org> wrote:
>
> > Preparatory patch for userfaultfd read-write protection (RWP). RWP
> > extends userfaultfd protection from plain write-protection (WP) to
> > full read-write protection: accesses to an RWP-protected range --
> > reads as well as writes -- trap through userfaultfd.
> >
> > RWP marks ranges by combining PAGE_NONE with the uffd PTE bit, so
> > the flag is only meaningful when both primitives exist. A new
> > CONFIG_USERFAULTFD_RWP Kconfig symbol auto-selects when CONFIG_64BIT,
> > CONFIG_ARCH_HAS_PTE_PROTNONE, and CONFIG_HAVE_ARCH_USERFAULTFD_WP
> > are all set; call sites that gate on the flag depend on the symbol.
> > Elsewhere VM_UFFD_RWP aliases VM_NONE and every downstream check
> > folds to dead code.
> >
> > Nothing sets the flag yet.
> >
> > Signed-off-by: Kiryl Shutsemau <kas@kernel.org>
> > Assisted-by: Claude:claude-opus-4-6
>
> A silly but loud thought. Would it make more sense to put Signed-off-by: after
> Assisted-by: ?
I am not sure. I see it both ways in git log. And I don't have strong
opinion on the order here. Keeping as is.
> > ---
> > Documentation/filesystems/proc.rst | 1 +
> > fs/proc/task_mmu.c | 3 +++
> > include/linux/mm.h | 28 +++++++++++++++++----------
> > include/linux/userfaultfd_k.h | 31 +++++++++++++++++++++++++-----
> > include/trace/events/mmflags.h | 7 +++++++
> > mm/Kconfig | 9 +++++++++
> > 6 files changed, 64 insertions(+), 15 deletions(-)
> >
> > diff --git a/Documentation/filesystems/proc.rst b/Documentation/filesystems/proc.rst
> > index db6167befb7b..db28207c5290 100644
> > --- a/Documentation/filesystems/proc.rst
> > +++ b/Documentation/filesystems/proc.rst
> > @@ -607,6 +607,7 @@ encoded manner. The codes are the following:
> > um userfaultfd missing tracking
> > uw userfaultfd wr-protect tracking
> > ui userfaultfd minor fault
> > + ur userfaultfd read-write-protect tracking
>
> Yet another silly but loud thought. My first feeling on this was that this
> reads like 'u'serfaultfd 'r'ead-protect. And was further thinking 'uf' for
> just 'u'seffaultfd 'f'ault or 'up' for 'u'serfault-'p'rotect might make sense.
> But ended up thinking this is too trivial and ain't really matter.
I will keep it. It's "u" + the first distinguishing letter of the mode
name. r distinguishes RWP from WP cleanly.
> [...]
> > diff --git a/mm/Kconfig b/mm/Kconfig
> > index e8bf1e9e6ad9..ccf534a8cbc9 100644
> > --- a/mm/Kconfig
> > +++ b/mm/Kconfig
> > @@ -1347,6 +1347,15 @@ config HAVE_ARCH_USERFAULTFD_MINOR
> > help
> > Arch has userfaultfd minor fault support
> >
> > +config USERFAULTFD_RWP
> > + def_bool y
> > + depends on 64BIT && ARCH_HAS_PTE_PROTNONE && HAVE_ARCH_USERFAULTFD_WP
> > + help
> > + Userfaultfd read-write protection (UFFDIO_RWPROTECT) delivers a
>
> Seems UFFDIO_RWPROTECT will be introduced later. Would it make more sense to
> add this config together with the patch?
Okay, I will move later in the patchset.
> > + userfaultfd notification on every access -- read or write -- to a
> > + protected range, letting userspace observe the working set of a
> > + process.
> > +
> > menuconfig USERFAULTFD
> > bool "Enable userfaultfd() system call"
> > depends on MMU
> > --
> > 2.51.2
> >
> >
>
> None of my comments is a blocker.
>
> Reviewed-by: SeongJae Park <sj@kernel.org>
Thanks!
--
Kiryl Shutsemau / Kirill A. Shutemov
^ permalink raw reply
* Re: [PATCH v2 04/14] mm: add VM_UFFD_RWP VMA flag
From: Kiryl Shutsemau @ 2026-05-22 10:39 UTC (permalink / raw)
To: Mike Rapoport
Cc: akpm, peterx, david, ljs, surenb, vbabka, Liam.Howlett, ziy,
corbet, skhan, seanjc, pbonzini, jthoughton, aarcange, sj,
usama.arif, linux-mm, linux-kernel, linux-doc, linux-kselftest,
kvm, kernel-team
In-Reply-To: <agNZ-Q7A0rfY66gj@kernel.org>
On Tue, May 12, 2026 at 07:48:57PM +0300, Mike Rapoport wrote:
> On Fri, May 08, 2026 at 04:55:16PM +0100, Kiryl Shutsemau (Meta) wrote:
> > Preparatory patch for userfaultfd read-write protection (RWP). RWP
> > extends userfaultfd protection from plain write-protection (WP) to
> > full read-write protection: accesses to an RWP-protected range --
> > reads as well as writes -- trap through userfaultfd.
> >
> > RWP marks ranges by combining PAGE_NONE with the uffd PTE bit, so
> > the flag is only meaningful when both primitives exist. A new
> > CONFIG_USERFAULTFD_RWP Kconfig symbol auto-selects when CONFIG_64BIT,
> > CONFIG_ARCH_HAS_PTE_PROTNONE, and CONFIG_HAVE_ARCH_USERFAULTFD_WP
> > are all set; call sites that gate on the flag depend on the symbol.
> > Elsewhere VM_UFFD_RWP aliases VM_NONE and every downstream check
> > folds to dead code.
> >
> > Nothing sets the flag yet.
>
> And nothing check for it as well, am I right?
Yep.
> Worth noting here, IMHO.
Will do.
>
> > Signed-off-by: Kiryl Shutsemau <kas@kernel.org>
> > Assisted-by: Claude:claude-opus-4-6
> > ---
> > Documentation/filesystems/proc.rst | 1 +
> > fs/proc/task_mmu.c | 3 +++
> > include/linux/mm.h | 28 +++++++++++++++++----------
> > include/linux/userfaultfd_k.h | 31 +++++++++++++++++++++++++-----
> > include/trace/events/mmflags.h | 7 +++++++
> > mm/Kconfig | 9 +++++++++
> > 6 files changed, 64 insertions(+), 15 deletions(-)
> >
> > diff --git a/include/linux/userfaultfd_k.h b/include/linux/userfaultfd_k.h
> > index 98f546e83cd2..fcf308dba311 100644
> > --- a/include/linux/userfaultfd_k.h
> > +++ b/include/linux/userfaultfd_k.h
> > @@ -21,10 +21,11 @@
> > #include <linux/hugetlb_inline.h>
> >
> > /* The set of all possible UFFD-related VM flags. */
> > -#define __VM_UFFD_FLAGS (VM_UFFD_MISSING | VM_UFFD_WP | VM_UFFD_MINOR)
> > +#define __VM_UFFD_FLAGS (VM_UFFD_MISSING | VM_UFFD_WP | VM_UFFD_MINOR | \
> > + VM_UFFD_RWP)
>
> Nit: can we keep mode bits together and protection bits together here and
> in the below changes?
Yep, make sense.
> Otherwise looks good to me
>
> Reviewed-by: Mike Rapoport (Microsoft) <rppt@kernel.org>
Thanks!
--
Kiryl Shutsemau / Kirill A. Shutemov
^ permalink raw reply
* Re: [PATCH v2 03/14] mm: rename uffd-wp PTE accessors to uffd
From: Kiryl Shutsemau @ 2026-05-22 10:33 UTC (permalink / raw)
To: SeongJae Park
Cc: akpm, rppt, peterx, david, ljs, surenb, vbabka, Liam.Howlett, ziy,
corbet, skhan, seanjc, pbonzini, jthoughton, aarcange, usama.arif,
linux-mm, linux-kernel, linux-doc, linux-kselftest, kvm,
kernel-team
In-Reply-To: <20260514013127.148945-1-sj@kernel.org>
On Wed, May 13, 2026 at 06:31:27PM -0700, SeongJae Park wrote:
> On Fri, 8 May 2026 16:55:15 +0100 "Kiryl Shutsemau (Meta)" <kas@kernel.org> wrote:
>
> > Userfaultfd RWP will reuse the uffd-wp PTE bit to mark access-tracking
> > PTEs, alongside the write-protected ones it already marks. The bit's
> > meaning now depends on the VMA flag (WP or RWP), not on its name.
> >
> > Rename the kernel-internal names that describe the bit:
> >
> > - pte/pmd/huge_pte accessors (and swap variants)
> > - pgtable_supports_uffd() capability query
> > - SCAN_PTE_UFFD khugepaged enum
> >
> > The ftrace string emitted by mm_khugepaged_scan_pmd for this enum is
> > kept as "pte_uffd_wp" so existing trace-based tooling keeps matching.
> >
> > Pure mechanical rename -- no behavior change.
> >
> > Signed-off-by: Kiryl Shutsemau <kas@kernel.org>
> > Assisted-by: Claude:claude-opus-4-6
> > Reviewed-by: Mike Rapoport (Microsoft) <rppt@kernel.org>
>
> Reviewed-by: SeongJae Park <sj@kernel.org>
Thanks!
> [...]
> > @@ -4934,10 +4934,10 @@ int copy_hugetlb_page_range(struct mm_struct *dst, struct mm_struct *src,
> > softleaf = softleaf_from_pte(entry);
> > if (unlikely(softleaf_is_hwpoison(softleaf))) {
> > if (!userfaultfd_wp(dst_vma))
> > - entry = huge_pte_clear_uffd_wp(entry);
> > + entry = huge_pte_clear_uffd(entry);
> > set_huge_pte_at(dst, addr, dst_pte, entry, sz);
> > } else if (unlikely(softleaf_is_migration(softleaf))) {
> > - bool uffd_wp = pte_swp_uffd_wp(entry);
> > + bool uffd_wp = pte_swp_uffd(entry);
>
> Just curious. Is the variable name intentionally kept to avoid unnecessary
> change?
No, I've missed this. Will fix.
--
Kiryl Shutsemau / Kirill A. Shutemov
^ permalink raw reply
* [PATCH] platform/x86: thinkpad_acpi: Add USB-C Security (USCS) support
From: Vishnu Sankar @ 2026-05-22 10:07 UTC (permalink / raw)
To: mpearson-lenovo, skhan, hmh, hansg, corbet, derekjohn.clark,
ilpo.jarvinen
Cc: linux-kernel, ibm-acpi-devel, linux-doc, platform-driver-x86,
vsankar, Vishnu Sankar
Newer ThinkPad systems expose a USB-C Security (Restricted Mode) feature.
When active, USB-C data connections are disabled while power delivery is
preserved. This is useful for kiosk and physically-secured deployments.
Hardware interface:
The HKEY device exposes a read-only ACPI method USCS():
Return value bit layout:
Bit 16 : Capability flag (1 = feature present on this SKU)
Bit 0 : Current state (0 = security OFF, 1 = security ON)
The sysfs attribute is read-only.
The Fn+U followed by Fn+S hotkey chord is the only way to toggle the
hardware state.
Hotkey:
Fn+U followed by Fn+S generates HKEY event 0x131e.
sysfs interface:
/sys/devices/platform/thinkpad_acpi/usb_c_security (read-only)
"enabled\n" -- data connections are currently blocked
"disabled\n" -- data connections are currently allowed
The attribute is hidden on SKUs where the USCS capability bit (bit 16)
is not set, so there is no ABI impact on unsupported hardware.
Suggested-by: Mark Pearson <mpearson-lenovo@squebb.ca>
Signed-off-by: Vishnu Sankar <vishnuocv@gmail.com>
---
.../admin-guide/laptops/thinkpad-acpi.rst | 24 ++++
drivers/platform/x86/lenovo/thinkpad_acpi.c | 115 ++++++++++++++++++
2 files changed, 139 insertions(+)
diff --git a/Documentation/admin-guide/laptops/thinkpad-acpi.rst b/Documentation/admin-guide/laptops/thinkpad-acpi.rst
index f874db31801d..db4588af0278 100644
--- a/Documentation/admin-guide/laptops/thinkpad-acpi.rst
+++ b/Documentation/admin-guide/laptops/thinkpad-acpi.rst
@@ -1543,6 +1543,30 @@ Values:
This setting can also be toggled via the Fn+doubletap hotkey.
+USB-C Security
+--------------
+
+sysfs: usb_c_security
+
+Reports the current state of the USB-C Security (Restricted Mode) feature
+on supported ThinkPad systems. When enabled, USB-C data connections are
+disabled while power delivery is preserved.
+
+The available command is::
+
+ cat /sys/devices/platform/thinkpad_acpi/usb_c_security
+
+Values:
+
+ * ``enabled`` - USB-C data connections are currently blocked
+ * ``disabled`` - USB-C data connections are currently allowed
+
+The attribute is read-only. The USB-C Security state can only be toggled
+via the Fn+U followed by Fn+S hotkey chord.
+
+The sysfs attribute is not created on platforms that do not support this
+feature.
+
Auxmac
------
diff --git a/drivers/platform/x86/lenovo/thinkpad_acpi.c b/drivers/platform/x86/lenovo/thinkpad_acpi.c
index e1cee42a1683..889db802185a 100644
--- a/drivers/platform/x86/lenovo/thinkpad_acpi.c
+++ b/drivers/platform/x86/lenovo/thinkpad_acpi.c
@@ -185,6 +185,7 @@ enum tpacpi_hkey_event_t {
TP_HKEY_EV_AMT_TOGGLE = 0x131a, /* Toggle AMT on/off */
TP_HKEY_EV_CAMERASHUTTER_TOGGLE = 0x131b, /* Toggle Camera Shutter */
TP_HKEY_EV_DOUBLETAP_TOGGLE = 0x131c, /* Toggle trackpoint doubletap on/off */
+ TP_HKEY_EV_USB_C_SECURITY = 0x131e, /* Toggle USB C Security ON/OFF */
TP_HKEY_EV_PROFILE_TOGGLE = 0x131f, /* Toggle platform profile in 2024 systems */
TP_HKEY_EV_PROFILE_TOGGLE2 = 0x1401, /* Toggle platform profile in 2025 + systems */
@@ -373,6 +374,8 @@ static struct {
u32 has_adaptive_kbd:1;
u32 kbd_lang:1;
u32 trackpoint_doubletap_enable:1;
+ u32 usbc_security_supported:1;
+ u32 usbc_security_enabled:1;
struct quirk_entry *quirks;
} tp_features;
@@ -11265,6 +11268,111 @@ static struct ibm_struct hwdd_driver_data = {
.name = "hwdd",
};
+/*************************************************************************
+ * USB-C Security subdriver
+ *
+ * HKEY.USCS(0) is a read-only ACPI method; its argument is ignored.
+ * It always returns:
+ * bit 16 - USB-C security capability present on this SKU or not
+ * bit 0 - USB-C Security state (enable or disable)
+ *
+ * Hotkey
+ * ------
+ * 0x131e (Fn+U, Fn+S): firmware toggles USBS before firing the event.
+ * The driver reads back the new state and notifies the sysfs attribute.
+ *
+ */
+
+/* USCS() return word bit layout */
+#define USCS_CAP_BIT BIT(16) /* capability: feature present on SKU */
+#define USCS_STATUS_BIT BIT(0) /* current security state */
+
+static DEFINE_MUTEX(usbc_security_mutex);
+
+/*
+ * usbc_security_query - read current USB-C security state via USCS()
+ * @enabled: out - true when security is ON (data connections blocked)
+ *
+ * Returns true if the feature is supported and query succeeded,
+ * false otherwise (feature absent or ACPI call failed).
+ */
+static bool usbc_security_query(bool *enabled)
+{
+ int status;
+
+ mutex_lock(&usbc_security_mutex);
+ if (!acpi_evalf(hkey_handle, &status, "USCS", "dd", 0)) {
+ mutex_unlock(&usbc_security_mutex);
+ return false;
+ }
+ mutex_unlock(&usbc_security_mutex);
+
+ if (!(status & USCS_CAP_BIT)) {
+ pr_debug("USCS cap bit absent (raw=0x%x)\n", status);
+ return false;
+ }
+
+ *enabled = !!(status & USCS_STATUS_BIT);
+ return true;
+}
+
+/* sysfs: /sys/devices/platform/thinkpad_acpi/usb_c_security ---------- */
+static ssize_t usb_c_security_show(struct device *dev,
+ struct device_attribute *attr,
+ char *buf)
+{
+ return sysfs_emit(buf, "%s\n",
+ tp_features.usbc_security_enabled ? "enabled" : "disabled");
+}
+
+static DEVICE_ATTR_RO(usb_c_security);
+
+static struct attribute *usbc_security_attributes[] = {
+ &dev_attr_usb_c_security.attr,
+ NULL,
+};
+
+static umode_t usbc_security_attr_is_visible(struct kobject *kobj,
+ struct attribute *attr, int n)
+{
+ return tp_features.usbc_security_supported ? attr->mode : 0;
+}
+
+static const struct attribute_group usbc_security_attr_group = {
+ .is_visible = usbc_security_attr_is_visible,
+ .attrs = usbc_security_attributes,
+};
+
+static int tpacpi_usbc_security_init(struct ibm_init_struct *iibm)
+{
+ bool enabled;
+
+ tp_features.usbc_security_supported =
+ usbc_security_query(&enabled);
+ tp_features.usbc_security_enabled = enabled;
+ return 0;
+}
+
+/* tpacpi_usbc_security_hotkey - handle Fn+U Fn+S hotkey (0x131e) */
+static bool tpacpi_usbc_security_hotkey(void)
+{
+ bool enabled;
+
+ if (!tp_features.usbc_security_supported)
+ return false;
+
+ if (!usbc_security_query(&enabled))
+ return false;
+
+ tp_features.usbc_security_enabled = enabled;
+ sysfs_notify(&tpacpi_pdev->dev.kobj, NULL, "usb_c_security");
+ return true;
+}
+
+static struct ibm_struct usbc_security_driver_data = {
+ .name = "usbc_security",
+};
+
/* --------------------------------------------------------------------- */
static struct attribute *tpacpi_driver_attributes[] = {
@@ -11325,6 +11433,7 @@ static const struct attribute_group *tpacpi_groups[] = {
&dprc_attr_group,
&auxmac_attr_group,
&hwdd_attr_group,
+ &usbc_security_attr_group,
NULL,
};
@@ -11479,6 +11588,8 @@ static bool tpacpi_driver_event(const unsigned int hkey_event)
case TP_HKEY_EV_PROFILE_TOGGLE2:
platform_profile_cycle();
return true;
+ case TP_HKEY_EV_USB_C_SECURITY:
+ return tpacpi_usbc_security_hotkey();
}
return false;
@@ -11930,6 +12041,10 @@ static struct ibm_init_struct ibms_init[] __initdata = {
.init = tpacpi_hwdd_init,
.data = &hwdd_driver_data,
},
+ {
+ .init = tpacpi_usbc_security_init,
+ .data = &usbc_security_driver_data,
+ },
};
static int __init set_ibm_param(const char *val, const struct kernel_param *kp)
--
2.51.0
^ permalink raw reply related
* Re: [PATCH v5 14/28] mtd: spi-nor: swp: Create helpers for building the SR register
From: Tudor Ambarus @ 2026-05-22 9:56 UTC (permalink / raw)
To: Miquel Raynal, Pratyush Yadav, Michael Walle, Takahiro Kuwano,
Richard Weinberger, Vignesh Raghavendra, Jonathan Corbet,
Shuah Khan
Cc: Sean Anderson, Thomas Petazzoni, Steam Lin, linux-mtd,
linux-kernel, linux-doc
In-Reply-To: <20260507-winbond-v6-18-rc1-spi-nor-swp-v5-14-93453e1a9597@bootlin.com>
On 5/7/26 7:46 PM, Miquel Raynal wrote:
> The status register contains 3 or 4 BP (Block Protect) bits, 0 or 1
> TB (Top/Bottom) bit, soon 0 or 1 CMP (Complement) bit. The last BP bit
> and the TB bit locations change between vendors. The whole logic of
> buildling the content of the status register based on some input
> conditions is used two times and soon will be used 4 times.
>
> Create dedicated helpers for these steps.
>
> Signed-off-by: Miquel Raynal <miquel.raynal@bootlin.com>
> ---
> drivers/mtd/spi-nor/swp.c | 83 +++++++++++++++++++++++++++++------------------
> 1 file changed, 51 insertions(+), 32 deletions(-)
>
> diff --git a/drivers/mtd/spi-nor/swp.c b/drivers/mtd/spi-nor/swp.c
> index 540cd221c455..8aa0fe297188 100644
> --- a/drivers/mtd/spi-nor/swp.c
> +++ b/drivers/mtd/spi-nor/swp.c
> @@ -125,6 +125,43 @@ static bool spi_nor_is_unlocked_sr(struct spi_nor *nor, loff_t ofs, u64 len,
> return spi_nor_check_lock_status_sr(nor, ofs, len, sr, false);
> }
>
> +static int spi_nor_sr_set_bp_mask(struct spi_nor *nor, u8 *sr, u8 pow)
> +{
> + u8 mask = spi_nor_get_sr_bp_mask(nor);
> + u8 val = pow << SR_BP_SHIFT;
> +
> + if (nor->flags & SNOR_F_HAS_SR_BP3_BIT6 && val & SR_BP3)
> + val = (val & ~SR_BP3) | SR_BP3_BIT6;
> +
> + if (val & ~mask)
> + return -EINVAL;
> +
> + sr[0] = val;
As sashiko already noticed, I think too this should have been sr[0] |= val
^ permalink raw reply
* Re: [PATCH v5 13/28] mtd: spi-nor: swp: Create a TB intermediate variable
From: Tudor Ambarus @ 2026-05-22 9:39 UTC (permalink / raw)
To: Miquel Raynal, Pratyush Yadav, Michael Walle, Takahiro Kuwano,
Richard Weinberger, Vignesh Raghavendra, Jonathan Corbet,
Shuah Khan
Cc: Sean Anderson, Thomas Petazzoni, Steam Lin, linux-mtd,
linux-kernel, linux-doc
In-Reply-To: <20260507-winbond-v6-18-rc1-spi-nor-swp-v5-13-93453e1a9597@bootlin.com>
On 5/7/26 7:46 PM, Miquel Raynal wrote:
> Ease the future reuse of the tb (Top/Bottom) boolean by creating an
> intermediate variable.
Please squash this in the patch that needs it.
>
> Signed-off-by: Miquel Raynal <miquel.raynal@bootlin.com>
> ---
> drivers/mtd/spi-nor/swp.c | 3 ++-
> 1 file changed, 2 insertions(+), 1 deletion(-)
>
> diff --git a/drivers/mtd/spi-nor/swp.c b/drivers/mtd/spi-nor/swp.c
> index 07269e09370a..540cd221c455 100644
> --- a/drivers/mtd/spi-nor/swp.c
> +++ b/drivers/mtd/spi-nor/swp.c
> @@ -62,6 +62,7 @@ static void spi_nor_get_locked_range_sr(struct spi_nor *nor, const u8 *sr, loff_
> u8 bp_mask = spi_nor_get_sr_bp_mask(nor);
> u8 tb_mask = spi_nor_get_sr_tb_mask(nor);
> u8 bp, val = sr[0] & bp_mask;
> + bool tb = (nor->flags & SNOR_F_HAS_SR_TB) ? sr[0] & tb_mask : 0;
>
> if (nor->flags & SNOR_F_HAS_SR_BP3_BIT6 && val & SR_BP3_BIT6)
> val = (val & ~SR_BP3_BIT6) | SR_BP3;
> @@ -81,7 +82,7 @@ static void spi_nor_get_locked_range_sr(struct spi_nor *nor, const u8 *sr, loff_
> if (*len > nor->params->size)
> *len = nor->params->size;
>
> - if (nor->flags & SNOR_F_HAS_SR_TB && sr[0] & tb_mask)
> + if (tb)
> *ofs = 0;
> else
> *ofs = nor->params->size - *len;
>
^ permalink raw reply
* Re: [PATCH v5 12/28] mtd: spi-nor: swp: Rename a mask
From: Tudor Ambarus @ 2026-05-22 9:37 UTC (permalink / raw)
To: Miquel Raynal, Pratyush Yadav, Michael Walle, Takahiro Kuwano,
Richard Weinberger, Vignesh Raghavendra, Jonathan Corbet,
Shuah Khan
Cc: Sean Anderson, Thomas Petazzoni, Steam Lin, linux-mtd,
linux-kernel, linux-doc
In-Reply-To: <20260507-winbond-v6-18-rc1-spi-nor-swp-v5-12-93453e1a9597@bootlin.com>
Reviewed-by: Tudor Ambarus <tudor.ambarus@linaro.org>
^ permalink raw reply
* Re: [PATCH v5 04/28] mtd: spi-nor: swp: Improve locking user experience
From: Tudor Ambarus @ 2026-05-22 9:10 UTC (permalink / raw)
To: Miquel Raynal, Pratyush Yadav, Michael Walle, Takahiro Kuwano,
Richard Weinberger, Vignesh Raghavendra, Jonathan Corbet,
Shuah Khan
Cc: Sean Anderson, Thomas Petazzoni, Steam Lin, linux-mtd,
linux-kernel, linux-doc, stable
In-Reply-To: <20260507-winbond-v6-18-rc1-spi-nor-swp-v5-4-93453e1a9597@bootlin.com>
On 5/7/26 7:46 PM, Miquel Raynal wrote:
> Fixes: 3dd8012a8eeb ("mtd: spi-nor: add TB (Top/Bottom) protect support")
> Cc: stable@kernel.org
Fixes shall be the first patches in the set.
^ permalink raw reply
* Re: [PATCH v5 00/28] mtd: spi-nor: Enhance software protection
From: Tudor Ambarus @ 2026-05-22 9:07 UTC (permalink / raw)
To: Miquel Raynal, Pratyush Yadav, Michael Walle, Takahiro Kuwano,
Richard Weinberger, Vignesh Raghavendra, Jonathan Corbet,
Shuah Khan
Cc: Sean Anderson, Thomas Petazzoni, Steam Lin, linux-mtd,
linux-kernel, linux-doc, stable
In-Reply-To: <20260507-winbond-v6-18-rc1-spi-nor-swp-v5-0-93453e1a9597@bootlin.com>
Hi, Miquel,
Please consider sashiko's review feedback and let us know whether there's
going to be a v6 or this set is good as it is:
https://sashiko.dev/#/patchset/20260507-winbond-v6-18-rc1-spi-nor-swp-v5-0-93453e1a9597%40bootlin.com
Cheers,
ta
^ permalink raw reply
* Re: [PATCH bpf-next v2] bpf, docs: add LOAD_ACQUIRE and STORE_RELEASE instructions
From: Alexis Lothoré @ 2026-05-22 8:35 UTC (permalink / raw)
To: David Vernet, Alexis Lothoré (eBPF Foundation)
Cc: Alexei Starovoitov, Daniel Borkmann, Andrii Nakryiko,
Martin KaFai Lau, Eduard Zingerman, Kumar Kartikeya Dwivedi,
Song Liu, Yonghong Song, Jiri Olsa, Jonathan Corbet, Shuah Khan,
ebpf, Bastien Curutchet, Thomas Petazzoni, bpf, bpf, linux-doc,
linux-kernel
In-Reply-To: <iulf7fwwvfrvvspg4e5xyx3tcxe2yonfjllnze2phgfgpynrlh@kodf3fy3l32q>
Hi David,
On Thu May 21, 2026 at 4:17 AM CEST, David Vernet wrote:
> On Thu, May 21, 2026 at 12:09:11AM +0200, Alexis Lothoré (eBPF Foundation) wrote:
>
> Hi Alexis,
>
> Thanks for working on this.
>
>> Commit 880442305a39 ("bpf: Introduce load-acquire and store-release
>> instructions") instroduced the LOAD_ACQUIRE and STORE_RELEASE atomic
>
> introduced
>
>> instructions modifiers. Those are currently not described in the
>> documentation, despite being used in the verifier and the various JIT
>> compilers supporting them.
>>
>> Add the missing entries in the instruction set documentation.
>>
>> Signed-off-by: Alexis Lothoré (eBPF Foundation) <alexis.lothore@bootlin.com>
>
> Alexei et al -- if you plan to do a subsequent RFC, it will influence
> how this document needs to be structured. [0] explains the process for
> adding new instructions. To quote:
>
>> Once a conformance group is registered with a set of instructions, no
>> further instructions can be added to that conformance group. A
>> specification should instead create a new conformance group that
>> includes the original conformance group, plus any newly added
>> instructions. Inclusion of the original conformance group is done via
>> the "includes" column of the BPF Instruction Conformance Groups
>> registry, and inclusion of newly added instructions is done via the
>> "groups" column of the BPF Instruction Set registry.
>
> So you would have to create a new conformance group for these new
> atomics -- you can't just add them to the existing one. In general it
> might be easier / advised to snapshot this file to RFC 9669 and create a
> new one for the new instructions to make it easier to tease this stuff
> apart later. If that's something you want, I'm happy to get us started
> with a skeleton file. Again, though, that's only necessary if you plan
> to submit a new document to the IETF WG.
>
> [0]: https://www.rfc-editor.org/rfc/rfc9669.html#name-adding-instructions
I don't know how heavy/long the process is to submit this kind of RFC
update, but your point makes it sound like it makes more sense to just
go directly for the proper way, ie adding the conformance group and then
adding those new ops in there, rather than updating the kernel doc as my
series is proposing, and then later reverting to a proper conformance
group.
--
Alexis Lothoré, Bootlin
Embedded Linux and Kernel engineering
https://bootlin.com
^ permalink raw reply
* Re: [PATCH] dcache: add fs.dentry-limit sysctl with negative-first reaper
From: Amir Goldstein @ 2026-05-22 8:27 UTC (permalink / raw)
To: NeilBrown
Cc: Ian Kent, Jan Kara, Horst Birthelmer, Miklos Szeredi,
Jonathan Corbet, Shuah Khan, Alexander Viro, Christian Brauner,
linux-doc, linux-kernel, linux-fsdevel, Horst Birthelmer
In-Reply-To: <177942337499.2234587.15757857859187727669@noble.neil.brown.name>
On Fri, May 22, 2026 at 6:16 AM NeilBrown <neilb@ownmail.net> wrote:
>
> On Wed, 20 May 2026, Amir Goldstein wrote:
> > On Wed, May 20, 2026 at 9:16 AM Ian Kent <raven@themaw.net> wrote:
> > >
> > > On 19/5/26 17:12, Jan Kara wrote:
> > > > On Mon 18-05-26 21:39:13, Ian Kent wrote:
> > > >> On 18/5/26 16:19, Jan Kara wrote:
> > > >>> Hi Ian,
> > > >>>
> > > >>> On Mon 18-05-26 10:55:43, Ian Kent wrote:
> > > >>>> On 18/5/26 07:55, NeilBrown wrote:
> > > >>>>> On Fri, 15 May 2026, Horst Birthelmer wrote:
> > > >>>>> According to the email you linked, a problem arises when a directory has
> > > >>>>> a great many negative children. Code which walks the list of children
> > > >>>>> (such as fsnotify) while holding a lock can suffer unpredictable delays
> > > >>>>> and result in long lock-hold times. So maybe a limit on negative
> > > >>>>> dentries for any parent is what we really want. That would be clumsy to
> > > >>>>> implement I imagine.
> > > >>>> But the notion of dropping the dentry in ->d_delete() on last dput() is
> > > >>>> simple enough but did see regressions (the only other place in the VFS
> > > >>>> besides dentry_kill() that the inode is unlinked from the dentry on
> > > >>>> dput()). I wonder if the regression was related to the test itself
> > > >>>> deliberately recreating deleted files and if that really is normal
> > > >>>> behaviour. By itself that should prevent almost all negative dentries
> > > >>>> being retained. Although file systems could do this as well (think XFS
> > > >>>> inode recycling) it should be reasonable to require it be left to the
> > > >>>> VFS.
> > > >>>>
> > > >>>> But even that's not enough given that, in my case, there would still be
> > > >>>> around 4 million dentries in the LRU cache and in fsnotify there are
> > > >>>> directory child traversals holding the parent i_lock "spinlock" that are
> > > >>>> going to cause problems.
> > > >>> Do you mean there are very many positive children of a directory?
> > > >> Didn't quantify that.
> > > >>
> > > >> The symptom is the "Spinlock held for more than ... seconds" occurring in
> > > >> the log. So there are certainly a lot of children in the list, but it's
> > > >> an assumption the ratio of positive to negative entries is roughly the
> > > >> same as the overall ratio in the dcache.
> > > > OK, but that's not necessarily true. I have seen these complaints from the
> > > > kernel but in all the cases I remember it was due to negative dentries
> > > > accumultating in a particular directory. There are certain apps such as
> > > > ElasticSearch which really do like creating huge amounts of negative
> > > > dentries in one directory - they use hashes as filenames and use directory
> > > > lookup instead of a DB table lookup and lookup lots of non-existent keys...
> > >
> > > Umm ... that's a good point, I hadn't paid much attention to ENOENT result
> > >
> > > lookups, I'll need to check on the like cycle of those, I think they do get
> > >
> > > hashed. That has to be the other source of negative dentries that I've
> > >
> > > neglected ...
> > >
> >
> > Yes, it has been claimed that some real life workloads create a lot of those.
> >
> > If we can keep those at the tail of the children list, it will be best
> > for the fsnotify
> > iteration, which only cares about positive dentries.
> >
> > > >
> > > >>>> so why is this traversal even retained in fsnotify?
> > > >>> Not sure which traversal you mean but if you set watch on a parent, you
> > > >>> have to walk all children to set PARENT_WATCHED flag so that you don't miss
> > > >>> events on children...
> > > >> Yes, that traversal is what I'm questioning ... again thanks.
> > > >>
> > > >> I think the function name is still fsnotify_set_children_dentry_flags()
> > > >> in recent kernels, the subject of commit 172e422ffea2 I mentioned above.
> > > > OK, thanks.
> > > >
> > > >> When you say miss events are you saying that accessing the parent dentry to
> > > >> work out if the child needs to respond to an event is quite expensive in the
> > > >> overall event processing context, that might make more sense to me ... or do
> > > >> I completely not yet understand the reasoning behind the need for the flag?
> > > > Close but not quite. The cost is the overhead of dget_parent() in
> > > > fsnotify_parent() which is often a couple of cache cold loads and atomic
> > > > instructions to find out we don't need to send any event for the current
> > > > write(2) or read(2) call. It gets worse if there are many IOs happening to
> > > > dentries in the same directory from multiple CPUs because instead of
> > > > cache-cold loads you get a cacheline contention on the parent.
> > > >
> > > >>>>> But what if we move dentries to the end of the list when they become
> > > >>>>> negative, and to the start of the list when they become positive? Then
> > > >>>>> code which walks the child list could simply abort on the first
> > > >>>>> negative.
> > > >>>>>
> > > >>>>> I doubt that would be quite as easy as it sounds, but it would at least
> > > >>>>> be more focused on the observed symptom rather than some whole-system
> > > >>>>> number which only vaguely correlates with the observed symptom.
> > > >>>>>
> > > >>>>> Maybe a completely different approach: change children-walking code to
> > > >>>>> drop and retake the lock (with appropriate validation) periodically.
> > > >>>>> What too would address the specific symptom.
> > > >>>> Another good question.
> > > >>>>
> > > >>>> I have assumed that dropping and re-taking the lock cannot be done but
> > > >>>> this is a question I would like answered as well. Dropping and re-taking
> > > >>>> lock would require, as Miklos pointed out to me off-list, recording the
> > > >>>> list position with say a cursor, introducing unwanted complexity when it
> > > >>>> would be better to accept the cost of a single extra access to the parent
> > > >>>> flags (which I assume is one reason to set the flag in the child).
> > > >>> The parent access is actually more expensive than you might think. Based on
> > > >>> experience with past fsnotify related performance regression I expect some
> > > >>> 20% performance hit for small tmpfs writes if you add unconditional parent
> > > >>> access to the write path.
> > > >> That sounds like a lot for what should be a memory access of an already in
> > > >> memory structure since the parent must be accessed to traverse the list of
> > > >> child entries. I clearly don't fully understand the implications of what
> > > >> I'm saying but there has been mention of another context ...
> > > > Parent dentry is of course in memory but often cache cold - you don't need
> > > > the parent to do e.g. write(2) to an already open file. You seem to be
> > > > somewhat confused about the child dentry list traversal (or maybe I'm
> > > > misunderstanding) - that happens only when placing the notification mark
> > > > but definitely not for each IO operation.
> > >
> > > LOL, confusion is a pretty common state of mind for me!
> > >
> > >
> > > I do get your point though and I am confusing the traversal with other
> > >
> > > operations. I think this answers the question I've been asking (maybe
> > >
> > > that wasn't obvious) about the reason for the traversal (ie. the reason
> > >
> > > to maintain a flag in the child).
> > >
> > >
> > > While I have looked at the code here I haven't absorbed it and I
> > >
> > > definitely don't understand it, your continued patience is appreciated
> > >
> > > and will be beneficial when I get time to look at it a bit closer. I
> > >
> > > do still need to use a notifications mechanism to match up with Miklos's
> > >
> > > statmount implementation to get the full benefit of that in user space,
> > >
> > > if I ever get a chance to work on that again.
> > >
> > >
> > > So it sounds like it would be worth while considering a traversal that's
> > >
> > > based on taking a reference on each dentry rather than a spinlock for
> > >
> > > the duration. It would be tricky though, for obvious reasons, like
> > >
> > > children added during the traversal, added overhead of getting the next
> > >
> > > entry reference, etc.
> >
> > Didn't look closely, but it feels like RCU traversal should be
> > possible if entries are added to the tail, or to the END_OF_POSITIVE
> > location.
> >
> > When we discussed the "negavites at tail" at LSFMM
> > it was said that managing the transitions positive<->negative
> > would be challenging, but I don't know that anyone tried to look closer at this.
>
> I had a quick look. Most users of d_sib walk from the parent->d_children
> with the parent ->d_lock held, so they shouldn't notice a movement in
> the list.
> The two exceptions I could find are d_walk() and the readdir code in
> libfs.c.
> I think the main problem case would be if they were holding a dentry as
> a cursor which transitioned when the parent d_lock is dropped and retaken.
>
> d_walk already needs to cope with a concurrent rename messing with
> its cursor so possibly something similar could be used to trigger a
> restart.
>
> libfs readdir walks from a DCACHE_DENTRY_CURSOR which will never
> transition and so won't move spontaneously. That is exactly as safe as
> walking from the parent.
>
> So I think d_walk() might need some help to avoid getting lost. It could
> probably simply check if its cursor changed ->d_inode between dropping
> ->d_lock and retaking it. If it did, then restart.
>
> It isn't clear to me that we can track a "end of positive" location. I
> think we would need to move negatives to the end and positives to the
> start. Can you see a down-side with doing that?
>
One of the intentions (that may be lost in this conversations) was to
avoid holding the parent inode lock over the entire children iteration in
fsnotify_set_children_dentry_flags().
This function only needs to go over all positive children.
That's why I thought about moving new positive to the end of positives.
Maybe this works if we keep positives at tail and negatives at head
and also have dentry shrinkers work on the negative dentries at the head
first.
Possibly, we can make sure to set DCACHE_FSNOTIFY_PARENT_WATCHED
if needed when making a dentry positive, to avoid some races.
NOTE that DCACHE_FSNOTIFY_PARENT_WATCHED can allow false
positives. It's an optimization flag that is auto cleared with
fsnotify_clear_child_dentry_flag() in case of false positive.
Also, it is possible to set DCACHE_FSNOTIFY_PARENT_WATCHED
*before* dentry is made positive, for example on start_creating()
because whether a negative dentry has DCACHE_FSNOTIFY_PARENT_WATCHED
or not is insignificant.
Thanks,
Amir.
^ permalink raw reply
* [PATCH v4 4/4] hwmon: (pmbus/tps25990): Add TPS1689 support
From: Stoyan Bogdanov @ 2026-05-22 8:23 UTC (permalink / raw)
To: jbrunet, linux, robh, krzk+dt, conor+dt, corbet, skhan
Cc: linux-hwmon, devicetree, linux-doc, linux-kernel, Stoyan Bogdanov
In-Reply-To: <20260522082349.2749970-1-sbogdanov@baylibre.com>
Extend the existing TPS25990 driver to support the TPS1689 eFuse,
as both devices share the same command interface and functionality.
Update the documentation to include TPS1689 support.
Signed-off-by: Stoyan Bogdanov <sbogdanov@baylibre.com>
---
Documentation/hwmon/tps25990.rst | 15 +++++---
drivers/hwmon/pmbus/tps25990.c | 66 +++++++++++++++++++++++++++++++-
2 files changed, 74 insertions(+), 7 deletions(-)
diff --git a/Documentation/hwmon/tps25990.rst b/Documentation/hwmon/tps25990.rst
index 04faec780d26..e8bc9a550bda 100644
--- a/Documentation/hwmon/tps25990.rst
+++ b/Documentation/hwmon/tps25990.rst
@@ -9,26 +9,31 @@ Supported chips:
Prefix: 'tps25990'
- * Datasheet
+ Datasheet: Publicly available at Texas Instruments website: https://www.ti.com/lit/gpn/tps25990
- Publicly available at Texas Instruments website: https://www.ti.com/lit/gpn/tps25990
+ * TI TPS1689
+
+ Prefix: 'tps1689'
+
+ Datasheet: Publicly available at Texas Instruments website: https://www.ti.com/lit/gpn/tps1689
Author:
Jerome Brunet <jbrunet@baylibre.com>
+ Stoyan Bogdanov <sbogdanov@baylibre.com>
Description
-----------
-This driver implements support for TI TPS25990 eFuse.
+This driver implements support for TI TPS25990 and TI TPS1689 eFuse chips.
This is an integrated, high-current circuit protection and power
management device with PMBUS interface
-Device compliant with:
+Devices are compliant with:
- PMBus rev 1.3 interface.
-Device supports direct format for reading input voltages,
+Devices supports direct format for reading input voltages,
output voltage, input current, input power and temperature.
Due to the specificities of the chip, all history reset attributes
diff --git a/drivers/hwmon/pmbus/tps25990.c b/drivers/hwmon/pmbus/tps25990.c
index 1e252844217b..720e134f1892 100644
--- a/drivers/hwmon/pmbus/tps25990.c
+++ b/drivers/hwmon/pmbus/tps25990.c
@@ -42,6 +42,7 @@
PK_MIN_AVG_RST_MIN)
enum chips {
+ tps1689,
tps25990,
};
@@ -286,7 +287,6 @@ static int tps25990_write_word_data(struct i2c_client *client,
value = clamp_val(value, 0, 0xff);
ret = pmbus_write_word_data(client, page, reg, value);
break;
-
case PMBUS_VIN_OV_FAULT_LIMIT:
value = tps25990_data2reg_direct(client, TPS25990_VIN_OVF, value);
value = clamp_val(value, 0, 0xf);
@@ -376,6 +376,14 @@ static const struct regulator_desc tps25990_reg_desc[] = {
#endif
static struct tps25990_local_direct_value tps25990_local_info[] = {
+ [tps1689] = {
+ .m[TPS25990_VIN_OVF] = 3984,
+ .b[TPS25990_VIN_OVF] = -63750,
+ .R[TPS25990_VIN_OVF] = -3,
+ .m[TPS25990_IIN_OCF] = 7111,
+ .b[TPS25990_IIN_OCF] = -2133,
+ .R[TPS25990_IIN_OCF] = -2,
+ },
[tps25990] = {
.m[TPS25990_VIN_OVF] = 10163,
.b[TPS25990_VIN_OVF] = -30081,
@@ -387,6 +395,59 @@ static struct tps25990_local_direct_value tps25990_local_info[] = {
};
static struct pmbus_driver_info tps25990_base_info[] = {
+ [tps1689] = {
+ .pages = 1,
+ .format[PSC_VOLTAGE_IN] = direct,
+ .m[PSC_VOLTAGE_IN] = 1166,
+ .b[PSC_VOLTAGE_IN] = 0,
+ .R[PSC_VOLTAGE_IN] = -2,
+ .format[PSC_VOLTAGE_OUT] = direct,
+ .m[PSC_VOLTAGE_OUT] = 1166,
+ .b[PSC_VOLTAGE_OUT] = 0,
+ .R[PSC_VOLTAGE_OUT] = -2,
+ .format[PSC_TEMPERATURE] = direct,
+ .m[PSC_TEMPERATURE] = 140,
+ .b[PSC_TEMPERATURE] = 32103,
+ .R[PSC_TEMPERATURE] = -2,
+ /*
+ * Current and Power measurement depends on the ohm value
+ * of Rimon. m is multiplied by 1000 below to have an integer
+ * and -3 is added to R to compensate.
+ */
+ .format[PSC_CURRENT_IN] = direct,
+ .m[PSC_CURRENT_IN] = 9548,
+ .b[PSC_CURRENT_IN] = 0,
+ .R[PSC_CURRENT_IN] = -6,
+ .format[PSC_CURRENT_OUT] = direct,
+ .m[PSC_CURRENT_OUT] = 24347,
+ .b[PSC_CURRENT_OUT] = 0,
+ .R[PSC_CURRENT_OUT] = -3,
+ .format[PSC_POWER] = direct,
+ .m[PSC_POWER] = 2775,
+ .b[PSC_POWER] = 0,
+ .R[PSC_POWER] = -4,
+ .func[0] = (PMBUS_HAVE_VIN |
+ PMBUS_HAVE_VOUT |
+ PMBUS_HAVE_VMON |
+ PMBUS_HAVE_IIN |
+ PMBUS_HAVE_PIN |
+ PMBUS_HAVE_TEMP |
+ PMBUS_HAVE_STATUS_VOUT |
+ PMBUS_HAVE_STATUS_IOUT |
+ PMBUS_HAVE_STATUS_INPUT |
+ PMBUS_HAVE_STATUS_TEMP |
+ PMBUS_HAVE_SAMPLES),
+
+ .read_word_data = tps25990_read_word_data,
+ .write_word_data = tps25990_write_word_data,
+ .read_byte_data = tps25990_read_byte_data,
+ .write_byte_data = tps25990_write_byte_data,
+
+#if IS_ENABLED(CONFIG_SENSORS_TPS25990_REGULATOR)
+ .reg_desc = tps25990_reg_desc,
+ .num_regulators = ARRAY_SIZE(tps25990_reg_desc),
+#endif
+ },
[tps25990] = {
.pages = 1,
.format[PSC_VOLTAGE_IN] = direct,
@@ -429,7 +490,6 @@ static struct pmbus_driver_info tps25990_base_info[] = {
.write_word_data = tps25990_write_word_data,
.read_byte_data = tps25990_read_byte_data,
.write_byte_data = tps25990_write_byte_data,
-
#if IS_ENABLED(CONFIG_SENSORS_TPS25990_REGULATOR)
.reg_desc = tps25990_reg_desc,
.num_regulators = ARRAY_SIZE(tps25990_reg_desc),
@@ -438,12 +498,14 @@ static struct pmbus_driver_info tps25990_base_info[] = {
};
static const struct i2c_device_id tps25990_i2c_id[] = {
+ { "tps1689", tps1689 },
{ "tps25990", tps25990 },
{}
};
MODULE_DEVICE_TABLE(i2c, tps25990_i2c_id);
static const struct of_device_id tps25990_of_match[] = {
+ { .compatible = "ti,tps1689", .data = (void *)tps1689 },
{ .compatible = "ti,tps25990", .data = (void *)tps25990 },
{}
};
--
2.43.0
^ permalink raw reply related
* [PATCH v4 3/4] dt-bindings: hwmon: pmbus/tps25990: Add TPS1689
From: Stoyan Bogdanov @ 2026-05-22 8:23 UTC (permalink / raw)
To: jbrunet, linux, robh, krzk+dt, conor+dt, corbet, skhan
Cc: linux-hwmon, devicetree, linux-doc, linux-kernel, Stoyan Bogdanov,
Krzysztof Kozlowski
In-Reply-To: <20260522082349.2749970-1-sbogdanov@baylibre.com>
Add device compatible support for TPS1689
Signed-off-by: Stoyan Bogdanov <sbogdanov@baylibre.com>
Acked-by: Krzysztof Kozlowski <krzysztof.kozlowski@oss.qualcomm.com>
---
.../devicetree/bindings/hwmon/pmbus/ti,tps25990.yaml | 8 +++++---
1 file changed, 5 insertions(+), 3 deletions(-)
diff --git a/Documentation/devicetree/bindings/hwmon/pmbus/ti,tps25990.yaml b/Documentation/devicetree/bindings/hwmon/pmbus/ti,tps25990.yaml
index f4115870e450..63ccb67576df 100644
--- a/Documentation/devicetree/bindings/hwmon/pmbus/ti,tps25990.yaml
+++ b/Documentation/devicetree/bindings/hwmon/pmbus/ti,tps25990.yaml
@@ -5,18 +5,20 @@
$id: http://devicetree.org/schemas/hwmon/pmbus/ti,tps25990.yaml#
$schema: http://devicetree.org/meta-schemas/core.yaml#
-title: Texas Instruments TPS25990 Stackable eFuse
+title: Texas Instruments Stackable eFuses
maintainers:
- Jerome Brunet <jbrunet@baylibre.com>
description:
- The TI TPS25990 is an integrated, high-current circuit
+ The TI TPS25990 and TPS1689 are integrated, high-current circuit
protection and power management device with PMBUS interface
properties:
compatible:
- const: ti,tps25990
+ enum:
+ - ti,tps1689
+ - ti,tps25990
reg:
maxItems: 1
--
2.43.0
^ permalink raw reply related
* [PATCH v4 2/4] hwmon: (pmbus/tps25990): Rework TPS25990 direct conversion handling
From: Stoyan Bogdanov @ 2026-05-22 8:23 UTC (permalink / raw)
To: jbrunet, linux, robh, krzk+dt, conor+dt, corbet, skhan
Cc: linux-hwmon, devicetree, linux-doc, linux-kernel, Stoyan Bogdanov
In-Reply-To: <20260522082349.2749970-1-sbogdanov@baylibre.com>
Rework the existing implementation of direct format conversion for
TPS25990 non-standard parameters to improve code reusability and
integration with the PMBus direct conversion helpers.
Changes include:
- Add an enum describing the supported parameters
- Add structure to hold m, b, R per-device coefficients
- Add data structures for pmbus_driver_info and local direct values
- Use the generic PMBus conversion helpers:
pmbus_reg2data_direct_calc()
pmbus_data2reg_direct_calc()
- Replace previously used defines with structured data
This reduces duplicated conversion logic and makes handling of
non-standard parameters more maintainable.
Signed-off-by: Stoyan Bogdanov <sbogdanov@baylibre.com>
---
drivers/hwmon/pmbus/tps25990.c | 197 +++++++++++++++++++++------------
1 file changed, 127 insertions(+), 70 deletions(-)
diff --git a/drivers/hwmon/pmbus/tps25990.c b/drivers/hwmon/pmbus/tps25990.c
index 05c6288ecafc..1e252844217b 100644
--- a/drivers/hwmon/pmbus/tps25990.c
+++ b/drivers/hwmon/pmbus/tps25990.c
@@ -36,17 +36,63 @@
#define TPS25990_UNLOCKED BIT(7)
#define TPS25990_8B_SHIFT 2
-#define TPS25990_VIN_OVF_NUM 525100
-#define TPS25990_VIN_OVF_DIV 10163
-#define TPS25990_VIN_OVF_OFF 155
-#define TPS25990_IIN_OCF_NUM 953800
-#define TPS25990_IIN_OCF_DIV 129278
-#define TPS25990_IIN_OCF_OFF 157
#define PK_MIN_AVG_RST_MASK (PK_MIN_AVG_RST_PEAK | \
PK_MIN_AVG_RST_AVG | \
PK_MIN_AVG_RST_MIN)
+enum chips {
+ tps25990,
+};
+
+enum tps25990_parameters {
+ TPS25990_VIN_OVF = 0, /* VIN over volatage fault */
+ TPS25990_IIN_OCF, /* IIN Over currect fault */
+ TPS25990_DIRECT_VALUES_COUNT,
+};
+
+struct tps25990_local_direct_value {
+ int m[TPS25990_DIRECT_VALUES_COUNT]; /* mantissa */
+ int b[TPS25990_DIRECT_VALUES_COUNT]; /* offset */
+ int R[TPS25990_DIRECT_VALUES_COUNT]; /* exponent */
+};
+
+struct tps25990_data {
+ struct pmbus_driver_info info;
+ struct tps25990_local_direct_value info_local;
+};
+
+static s64 tps25990_reg2data_direct(struct i2c_client *client, int param, s32 raw)
+{
+ struct pmbus_driver_info *info = i2c_get_clientdata(client);
+ struct tps25990_data *data = container_of(info, struct tps25990_data, info);
+ struct tps25990_local_direct_value *info_local = &data->info_local;
+ s64 b, val;
+ s32 m, R;
+
+ val = (s16)raw;
+ m = info_local->m[param];
+ b = info_local->b[param];
+ R = info_local->R[param];
+
+ return pmbus_reg2data_direct_calc(val, b, m, R);
+}
+
+static u16 tps25990_data2reg_direct(struct i2c_client *client, int param, s64 val)
+{
+ struct pmbus_driver_info *info = i2c_get_clientdata(client);
+ struct tps25990_data *data = container_of(info, struct tps25990_data, info);
+ struct tps25990_local_direct_value *info_local = &data->info_local;
+ s32 m, R;
+ s64 b;
+
+ m = info_local->m[param];
+ b = info_local->b[param];
+ R = info_local->R[param];
+
+ return pmbus_data2reg_direct_calc(val, b, m, R);
+}
+
/*
* Arbitrary default Rimon value: 1kOhm
* This correspond to an overcurrent limit of 55A, close to the specified limit
@@ -184,9 +230,7 @@ static int tps25990_read_word_data(struct i2c_client *client,
ret = pmbus_read_word_data(client, page, phase, reg);
if (ret < 0)
break;
- ret = DIV_ROUND_CLOSEST(ret * TPS25990_VIN_OVF_NUM,
- TPS25990_VIN_OVF_DIV);
- ret += TPS25990_VIN_OVF_OFF;
+ ret = tps25990_reg2data_direct(client, TPS25990_VIN_OVF, ret);
break;
case PMBUS_IIN_OC_FAULT_LIMIT:
@@ -198,9 +242,7 @@ static int tps25990_read_word_data(struct i2c_client *client,
ret = pmbus_read_byte_data(client, page, TPS25990_VIREF);
if (ret < 0)
break;
- ret = DIV_ROUND_CLOSEST(ret * TPS25990_IIN_OCF_NUM,
- TPS25990_IIN_OCF_DIV);
- ret += TPS25990_IIN_OCF_OFF;
+ ret = tps25990_reg2data_direct(client, TPS25990_IIN_OCF, ret);
break;
case PMBUS_VIRT_SAMPLES:
@@ -246,17 +288,13 @@ static int tps25990_write_word_data(struct i2c_client *client,
break;
case PMBUS_VIN_OV_FAULT_LIMIT:
- value -= TPS25990_VIN_OVF_OFF;
- value = DIV_ROUND_CLOSEST(((unsigned int)value) * TPS25990_VIN_OVF_DIV,
- TPS25990_VIN_OVF_NUM);
+ value = tps25990_data2reg_direct(client, TPS25990_VIN_OVF, value);
value = clamp_val(value, 0, 0xf);
ret = pmbus_write_word_data(client, page, reg, value);
break;
case PMBUS_IIN_OC_FAULT_LIMIT:
- value -= TPS25990_IIN_OCF_OFF;
- value = DIV_ROUND_CLOSEST(((unsigned int)value) * TPS25990_IIN_OCF_DIV,
- TPS25990_IIN_OCF_NUM);
+ value = tps25990_data2reg_direct(client, TPS25990_IIN_OCF, value);
value = clamp_val(value, 0, 0x3f);
ret = pmbus_write_byte_data(client, page, TPS25990_VIREF, value);
break;
@@ -337,63 +375,76 @@ static const struct regulator_desc tps25990_reg_desc[] = {
};
#endif
-static const struct pmbus_driver_info tps25990_base_info = {
- .pages = 1,
- .format[PSC_VOLTAGE_IN] = direct,
- .m[PSC_VOLTAGE_IN] = 5251,
- .b[PSC_VOLTAGE_IN] = 0,
- .R[PSC_VOLTAGE_IN] = -2,
- .format[PSC_VOLTAGE_OUT] = direct,
- .m[PSC_VOLTAGE_OUT] = 5251,
- .b[PSC_VOLTAGE_OUT] = 0,
- .R[PSC_VOLTAGE_OUT] = -2,
- .format[PSC_TEMPERATURE] = direct,
- .m[PSC_TEMPERATURE] = 140,
- .b[PSC_TEMPERATURE] = 32100,
- .R[PSC_TEMPERATURE] = -2,
- /*
- * Current and Power measurement depends on the ohm value
- * of Rimon. m is multiplied by 1000 below to have an integer
- * and -3 is added to R to compensate.
- */
- .format[PSC_CURRENT_IN] = direct,
- .m[PSC_CURRENT_IN] = 9538,
- .b[PSC_CURRENT_IN] = 0,
- .R[PSC_CURRENT_IN] = -6,
- .format[PSC_POWER] = direct,
- .m[PSC_POWER] = 4901,
- .b[PSC_POWER] = 0,
- .R[PSC_POWER] = -7,
- .func[0] = (PMBUS_HAVE_VIN |
- PMBUS_HAVE_VOUT |
- PMBUS_HAVE_VMON |
- PMBUS_HAVE_IIN |
- PMBUS_HAVE_PIN |
- PMBUS_HAVE_TEMP |
- PMBUS_HAVE_STATUS_VOUT |
- PMBUS_HAVE_STATUS_IOUT |
- PMBUS_HAVE_STATUS_INPUT |
- PMBUS_HAVE_STATUS_TEMP |
- PMBUS_HAVE_SAMPLES),
- .read_word_data = tps25990_read_word_data,
- .write_word_data = tps25990_write_word_data,
- .read_byte_data = tps25990_read_byte_data,
- .write_byte_data = tps25990_write_byte_data,
+static struct tps25990_local_direct_value tps25990_local_info[] = {
+ [tps25990] = {
+ .m[TPS25990_VIN_OVF] = 10163,
+ .b[TPS25990_VIN_OVF] = -30081,
+ .R[TPS25990_VIN_OVF] = -4,
+ .m[TPS25990_IIN_OCF] = 9538,
+ .b[TPS25990_IIN_OCF] = 0,
+ .R[TPS25990_IIN_OCF] = -6,
+ },
+};
+
+static struct pmbus_driver_info tps25990_base_info[] = {
+ [tps25990] = {
+ .pages = 1,
+ .format[PSC_VOLTAGE_IN] = direct,
+ .m[PSC_VOLTAGE_IN] = 5251,
+ .b[PSC_VOLTAGE_IN] = 0,
+ .R[PSC_VOLTAGE_IN] = -2,
+ .format[PSC_VOLTAGE_OUT] = direct,
+ .m[PSC_VOLTAGE_OUT] = 5251,
+ .b[PSC_VOLTAGE_OUT] = 0,
+ .R[PSC_VOLTAGE_OUT] = -2,
+ .format[PSC_TEMPERATURE] = direct,
+ .m[PSC_TEMPERATURE] = 140,
+ .b[PSC_TEMPERATURE] = 32100,
+ .R[PSC_TEMPERATURE] = -2,
+ /*
+ * Current and Power measurement depends on the ohm value
+ * of Rimon. m is multiplied by 1000 below to have an integer
+ * and -3 is added to R to compensate.
+ */
+ .format[PSC_CURRENT_IN] = direct,
+ .m[PSC_CURRENT_IN] = 9538,
+ .b[PSC_CURRENT_IN] = 0,
+ .R[PSC_CURRENT_IN] = -6,
+ .format[PSC_POWER] = direct,
+ .m[PSC_POWER] = 4901,
+ .b[PSC_POWER] = 0,
+ .R[PSC_POWER] = -7,
+ .func[0] = (PMBUS_HAVE_VIN |
+ PMBUS_HAVE_VOUT |
+ PMBUS_HAVE_VMON |
+ PMBUS_HAVE_IIN |
+ PMBUS_HAVE_PIN |
+ PMBUS_HAVE_TEMP |
+ PMBUS_HAVE_STATUS_VOUT |
+ PMBUS_HAVE_STATUS_IOUT |
+ PMBUS_HAVE_STATUS_INPUT |
+ PMBUS_HAVE_STATUS_TEMP |
+ PMBUS_HAVE_SAMPLES),
+ .read_word_data = tps25990_read_word_data,
+ .write_word_data = tps25990_write_word_data,
+ .read_byte_data = tps25990_read_byte_data,
+ .write_byte_data = tps25990_write_byte_data,
#if IS_ENABLED(CONFIG_SENSORS_TPS25990_REGULATOR)
- .reg_desc = tps25990_reg_desc,
- .num_regulators = ARRAY_SIZE(tps25990_reg_desc),
+ .reg_desc = tps25990_reg_desc,
+ .num_regulators = ARRAY_SIZE(tps25990_reg_desc),
#endif
+ },
};
static const struct i2c_device_id tps25990_i2c_id[] = {
- { "tps25990" },
+ { "tps25990", tps25990 },
{}
};
MODULE_DEVICE_TABLE(i2c, tps25990_i2c_id);
static const struct of_device_id tps25990_of_match[] = {
- { .compatible = "ti,tps25990" },
+ { .compatible = "ti,tps25990", .data = (void *)tps25990 },
{}
};
MODULE_DEVICE_TABLE(of, tps25990_of_match);
@@ -401,8 +452,9 @@ MODULE_DEVICE_TABLE(of, tps25990_of_match);
static int tps25990_probe(struct i2c_client *client)
{
struct device *dev = &client->dev;
- struct pmbus_driver_info *info;
+ struct tps25990_data *data;
const char *propname;
+ enum chips chip_id;
u32 rimon;
int ret;
@@ -415,15 +467,20 @@ static int tps25990_probe(struct i2c_client *client)
rimon = TPS25990_DEFAULT_RIMON;
}
- info = devm_kmemdup(dev, &tps25990_base_info, sizeof(*info), GFP_KERNEL);
- if (!info)
+ chip_id = (enum chips)(unsigned long)i2c_get_match_data(client);
+
+ data = devm_kzalloc(dev, sizeof(struct tps25990_data), GFP_KERNEL);
+ if (!data)
return -ENOMEM;
+ data->info = tps25990_base_info[chip_id];
+ data->info_local = tps25990_local_info[chip_id];
+
/* Adapt the current and power scale for each instance */
- tps25990_set_m(&info->m[PSC_CURRENT_IN], rimon);
- tps25990_set_m(&info->m[PSC_POWER], rimon);
+ tps25990_set_m(&data->info.m[PSC_CURRENT_IN], rimon);
+ tps25990_set_m(&data->info.m[PSC_POWER], rimon);
- return pmbus_do_probe(client, info);
+ return pmbus_do_probe(client, &data->info);
}
static struct i2c_driver tps25990_driver = {
--
2.43.0
^ permalink raw reply related
* [PATCH v4 1/4] hwmon: (pmbus) Add and export direct conversion calculation helpers
From: Stoyan Bogdanov @ 2026-05-22 8:23 UTC (permalink / raw)
To: jbrunet, linux, robh, krzk+dt, conor+dt, corbet, skhan
Cc: linux-hwmon, devicetree, linux-doc, linux-kernel, Stoyan Bogdanov
In-Reply-To: <20260522082349.2749970-1-sbogdanov@baylibre.com>
TPS25990 and upcoming TPS1689 need common computation APIs but
the current implementation is static to TPS25990. As a preparation for
TPS1689 support, split the math-only parts of pmbus_reg2data_direct() and
pmbus_data2reg_direct() into separate helper functions:
- pmbus_reg2data_direct_calc()
- pmbus_data2reg_direct_calc()
export them so the upcoming TPS1689 can use the same APIs.
This has no behavioral change on TPS25990 while allowing TPS1689
to use the same.
Signed-off-by: Stoyan Bogdanov <sbogdanov@baylibre.com>
---
drivers/hwmon/pmbus/pmbus.h | 2 ++
drivers/hwmon/pmbus/pmbus_core.c | 59 +++++++++++++++++++-------------
2 files changed, 38 insertions(+), 23 deletions(-)
diff --git a/drivers/hwmon/pmbus/pmbus.h b/drivers/hwmon/pmbus/pmbus.h
index 23e3eda58870..dd4fe7d9821d 100644
--- a/drivers/hwmon/pmbus/pmbus.h
+++ b/drivers/hwmon/pmbus/pmbus.h
@@ -578,5 +578,7 @@ DEFINE_GUARD(pmbus_lock, struct i2c_client *, pmbus_lock(_T), pmbus_unlock(_T))
int pmbus_update_fan(struct i2c_client *client, int page, int id,
u8 config, u8 mask, u16 command);
struct dentry *pmbus_get_debugfs_dir(struct i2c_client *client);
+s64 pmbus_reg2data_direct_calc(s64 val, s64 b, s32 m, s32 R);
+u16 pmbus_data2reg_direct_calc(s64 val, s64 b, s32 m, s32 R);
#endif /* PMBUS_H */
diff --git a/drivers/hwmon/pmbus/pmbus_core.c b/drivers/hwmon/pmbus/pmbus_core.c
index e8fdd799c71c..2eaac337eeab 100644
--- a/drivers/hwmon/pmbus/pmbus_core.c
+++ b/drivers/hwmon/pmbus/pmbus_core.c
@@ -817,6 +817,22 @@ static s64 pmbus_reg2data_linear(struct pmbus_data *data,
return val;
}
+s64 pmbus_reg2data_direct_calc(s64 val, s64 b, s32 m, s32 R)
+{
+ while (R > 0) {
+ val *= 10;
+ R--;
+ }
+ while (R < 0) {
+ val = div_s64(val + 5LL, 10L); /* round closest */
+ R++;
+ }
+
+ val = div_s64(val - b, m);
+ return val;
+}
+EXPORT_SYMBOL_NS_GPL(pmbus_reg2data_direct_calc, "PMBUS");
+
/*
* Convert direct sensor values to milli- or micro-units
* depending on sensor type.
@@ -824,7 +840,7 @@ static s64 pmbus_reg2data_linear(struct pmbus_data *data,
static s64 pmbus_reg2data_direct(struct pmbus_data *data,
struct pmbus_sensor *sensor)
{
- s64 b, val = (s16)sensor->data;
+ s64 b;
s32 m, R;
m = data->info->m[sensor->class];
@@ -848,17 +864,7 @@ static s64 pmbus_reg2data_direct(struct pmbus_data *data,
b *= 1000;
}
- while (R > 0) {
- val *= 10;
- R--;
- }
- while (R < 0) {
- val = div_s64(val + 5LL, 10L); /* round closest */
- R++;
- }
-
- val = div_s64(val - b, m);
- return val;
+ return pmbus_reg2data_direct_calc((s16)sensor->data, b, m, R);
}
/*
@@ -1057,6 +1063,23 @@ static u16 pmbus_data2reg_linear(struct pmbus_data *data,
return (mantissa & 0x7ff) | ((exponent << 11) & 0xf800);
}
+u16 pmbus_data2reg_direct_calc(s64 val, s64 b, s32 m, s32 R)
+{
+ val = val * m + b;
+
+ while (R > 0) {
+ val *= 10;
+ R--;
+ }
+ while (R < 0) {
+ val = div_s64(val + 5LL, 10L); /* round closest */
+ R++;
+ }
+
+ return (u16)clamp_val(val, S16_MIN, S16_MAX);
+}
+EXPORT_SYMBOL_NS_GPL(pmbus_data2reg_direct_calc, "PMBUS");
+
static u16 pmbus_data2reg_direct(struct pmbus_data *data,
struct pmbus_sensor *sensor, s64 val)
{
@@ -1078,18 +1101,8 @@ static u16 pmbus_data2reg_direct(struct pmbus_data *data,
R -= 3; /* Adjust R and b for data in milli-units */
b *= 1000;
}
- val = val * m + b;
- while (R > 0) {
- val *= 10;
- R--;
- }
- while (R < 0) {
- val = div_s64(val + 5LL, 10L); /* round closest */
- R++;
- }
-
- return (u16)clamp_val(val, S16_MIN, S16_MAX);
+ return pmbus_data2reg_direct_calc(val, b, m, R);
}
static u16 pmbus_data2reg_vid(struct pmbus_data *data,
--
2.43.0
^ permalink raw reply related
* [PATCH v4 0/4] Rework TPS25990 direct conversions and add TPS1689 support
From: Stoyan Bogdanov @ 2026-05-22 8:23 UTC (permalink / raw)
To: jbrunet, linux, robh, krzk+dt, conor+dt, corbet, skhan
Cc: linux-hwmon, devicetree, linux-doc, linux-kernel, Stoyan Bogdanov
This series reworks the TPS25990 PMBus driver direct conversion
handling to provide a unified and maintainable approach for devices
using non-standard direct format conversions.
The existing TPS25990-specific conversion defines are replaced with a
generic parameter enumeration and conversion descriptor using the PMBus
direct format coefficients (m, b, R). A new local structure combines
pmbus_driver_info with direct conversion data, simplifying support
for related devices sharing the same conversion model.
To avoid duplicated conversion logic in drivers, this series also adds
and exports generic helper functions from the PMBus core:
pmbus_reg2data_direct_calc() and
pmbus_data2reg_direct_calc().
With the conversion handling generalized, support for TPS1689 is added
to the TPS25990 driver. Both devices share most internal functionality,
differing mainly in supported voltage and current operating ranges.
Link to V3 at [1]
v4:
- Fix non-devicetree support as reported by Guenter Roeck
- Rework direct conversion handling to use exported PMBus core helpers
instead of driver-local implementations
- Update dt-bindings commit message and ti,tps25990.yaml
- Clarify commit messages to better reflect the final implementation
- Add and export direct conversion helpers from pmbus_core
- Eliminate duplicated conversion code in the driver
V3:
- Fix error detected from kernel test bot regarding division
Tests:
- Test builds for x86_64, arm64, i386
- Retest driver on arm64
- Validate driver direct conversion functions manualy
V2:
- Fix error detected from kernel test bot
- Add Acked-by to dt-bindings commit
- Drop "support" from dt-bindings commit subject
[1] https://lore.kernel.org/all/20260217081203.1792025-1-sbogdanov@baylibre.com/
Stoyan Bogdanov (4):
hwmon: (pmbus) Add and export direct conversion calculation helpers
hwmon: (pmbus/tps25990): Rework TPS25990 direct conversion handling
dt-bindings: hwmon: pmbus/tps25990: Add TPS1689
hwmon: (pmbus/tps25990): Add TPS1689 support
.../bindings/hwmon/pmbus/ti,tps25990.yaml | 8 +-
Documentation/hwmon/tps25990.rst | 15 +-
drivers/hwmon/pmbus/pmbus.h | 2 +
drivers/hwmon/pmbus/pmbus_core.c | 59 ++--
drivers/hwmon/pmbus/tps25990.c | 261 +++++++++++++-----
5 files changed, 243 insertions(+), 102 deletions(-)
--
2.43.0
^ permalink raw reply
* [PATCH] docs/zh_CN: fix KASAN SW_TAGS mode description
From: chengyaqiang @ 2026-05-22 7:57 UTC (permalink / raw)
To: alexs, si.yanteng
Cc: dzm91, corbet, skhan, linux-doc, linux-kernel, chengyaqiang
From: chengyaqiang <chengyaqiang@tsinghua.edu.cn>
CONFIG_KASAN_SW_TAGS enables Software Tag-Based KASAN mode, not Hardware
Tag-Based mode. Fix the incorrect translation in the Chinese documentation.
The original text incorrectly described both CONFIG_KASAN_SW_TAGS and
CONFIG_KASAN_HW_TAGS as "基于硬件标签" (hardware tag-based). Correct
CONFIG_KASAN_SW_TAGS to "基于软件标签" (software tag-based).
Signed-off-by: chengyaqiang <chengyaqiang@tsinghua.edu.cn>
---
Documentation/translations/zh_CN/dev-tools/kasan.rst | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/Documentation/translations/zh_CN/dev-tools/kasan.rst b/Documentation/translations/zh_CN/dev-tools/kasan.rst
index fd2e3afbdfad..767b280d8af0 100644
--- a/Documentation/translations/zh_CN/dev-tools/kasan.rst
+++ b/Documentation/translations/zh_CN/dev-tools/kasan.rst
@@ -79,7 +79,7 @@ KASAN只支持SLUB。
CONFIG_KASAN=y
同时在 ``CONFIG_KASAN_GENERIC`` (启用通用KASAN模式), ``CONFIG_KASAN_SW_TAGS``
-(启用基于硬件标签的KASAN模式),和 ``CONFIG_KASAN_HW_TAGS`` (启用基于硬件标签
+(启用基于软件标签的KASAN模式),和 ``CONFIG_KASAN_HW_TAGS`` (启用基于硬件标签
的KASAN模式)之间进行选择。
对于软件模式,还可以在 ``CONFIG_KASAN_OUTLINE`` 和 ``CONFIG_KASAN_INLINE``
--
2.39.5
^ permalink raw reply related
* Re: [PATCH] ARM: zte: clean up zx297520v3 doc. warnings
From: Stefan Dösinger @ 2026-05-22 7:09 UTC (permalink / raw)
To: linux-kernel, Randy Dunlap
Cc: Randy Dunlap, Linus Walleij, Krzysztof Kozlowski,
linux-arm-kernel, Jonathan Corbet, Shuah Khan, linux-doc
In-Reply-To: <20260521191458.177046-1-rdunlap@infradead.org>
[-- Attachment #1: Type: text/plain, Size: 470 bytes --]
Hi,
Am Donnerstag, 21. Mai 2026, 22:14:57 Ostafrikanische Zeit schrieben Sie:
> Fix multiple documentation build warnings.
> Improve punctuation and formatting of the rendered output.
>
> Documentation/arch/arm/zte/zx297520v3.rst:66: WARNING: Title underline too
> short. 3. Building for built-in U-Boot
I am sorry for the mess. I'll look into doc building before I send clock
documentation...
Reviewed-by: Stefan Dösinger <stefandoesinger@gmail.com>
[-- Attachment #2: This is a digitally signed message part. --]
[-- Type: application/pgp-signature, Size: 870 bytes --]
^ permalink raw reply
* Re: [PATCH] tpm: tpm_tis: Add optional delay after relinquish
From: Jim Broadus @ 2026-05-22 6:03 UTC (permalink / raw)
To: Jarkko Sakkinen; +Cc: linux-integrity, linux-kernel, linux-doc, peterhuewe, jgg
In-Reply-To: <ag-ZuEt4uXnrO8AK@kernel.org>
Thank you Jarkko. I'll do that.
Jim
On Thu, May 21, 2026 at 4:48 PM Jarkko Sakkinen <jarkko@kernel.org> wrote:
>
> On Mon, May 18, 2026 at 11:09:26PM -0700, Jim Broadus wrote:
> > Some TPMs fail to grant locality when requested immediately after being
> > relinquished. In this case, the TPM_ACCESS_REQUEST_USE bit of the
> > TPM_ACCESS register is cleared immediately without setting
> > TPM_ACCESS_ACTIVE_LOCALITY.
> >
> > This issue can be seen at boot since tpm_chip_start, called right
> > after locality is relinquished, fails. This causes the probe to fail:
> >
> > tpm_tis MSFT0101:00: probe with driver tpm_tis failed with error -1
> >
> > This occurs on some older Dell Latitudes and maybe others. To work
> > around this, add a "settle" boolean param to tpm_tis. When this is
> > enabled, a delay is added after locality is relinquished.
> >
> > Signed-off-by: Jim Broadus <jbroadus@gmail.com>
>
> It would be better idea first to replace priv->manufacturer_id with
> priv->did_vid, and make necessary changes to sites where it is used.
>
> Then in the if-statement compare DID/VID of the device to priv->did_vid
> and apply quirk only if it matches.
>
> > ---
> > Documentation/admin-guide/kernel-parameters.txt | 7 +++++++
> > drivers/char/tpm/tpm_tis.c | 7 +++++++
> > drivers/char/tpm/tpm_tis_core.c | 3 +++
> > drivers/char/tpm/tpm_tis_core.h | 1 +
> > 4 files changed, 18 insertions(+)
> >
> > diff --git a/Documentation/admin-guide/kernel-parameters.txt b/Documentation/admin-guide/kernel-parameters.txt
> > index 4d0f545fb3ec..5b7111033fbb 100644
> > --- a/Documentation/admin-guide/kernel-parameters.txt
> > +++ b/Documentation/admin-guide/kernel-parameters.txt
> > @@ -7651,6 +7651,13 @@ Kernel parameters
> > defined by Trusted Computing Group (TCG) see
> > https://trustedcomputinggroup.org/resource/pc-client-platform-tpm-profile-ptp-specification/
> >
> > + tpm_tis.settle= [HW,TPM]
> > + Format: <bool>
> > + When enabled, this adds a delay after locality is
> > + relinquished. Some TPMs will fail to grant locality if
> > + requested immediately after being relinquished. This
> > + causes the probe to fail.
> > +
> > tp_printk [FTRACE]
> > Have the tracepoints sent to printk as well as the
> > tracing ring buffer. This is useful for early boot up
> > diff --git a/drivers/char/tpm/tpm_tis.c b/drivers/char/tpm/tpm_tis.c
> > index 9aa230a63616..8ac0ea78570e 100644
> > --- a/drivers/char/tpm/tpm_tis.c
> > +++ b/drivers/char/tpm/tpm_tis.c
> > @@ -101,6 +101,10 @@ module_param(force, bool, 0444);
> > MODULE_PARM_DESC(force, "Force device probe rather than using ACPI entry");
> > #endif
> >
> > +static bool settle;
> > +module_param(settle, bool, 0444);
> > +MODULE_PARM_DESC(settle, "Add settle time after relinquish");
> > +
> > #if defined(CONFIG_PNP) && defined(CONFIG_ACPI)
> > static int has_hid(struct acpi_device *dev, const char *hid)
> > {
> > @@ -242,6 +246,9 @@ static int tpm_tis_init(struct device *dev, struct tpm_info *tpm_info)
> > if (itpm || is_itpm(ACPI_COMPANION(dev)))
> > set_bit(TPM_TIS_ITPM_WORKAROUND, &phy->priv.flags);
> >
> > + if (settle)
> > + set_bit(TPM_TIS_SETTLE_AFTER_RELINQUISH, &phy->priv.flags);
> > +
> > return tpm_tis_core_init(dev, &phy->priv, irq, &tpm_tcg,
> > ACPI_HANDLE(dev));
> > }
> > diff --git a/drivers/char/tpm/tpm_tis_core.c b/drivers/char/tpm/tpm_tis_core.c
> > index 21d79ad3b164..68be26fa5817 100644
> > --- a/drivers/char/tpm/tpm_tis_core.c
> > +++ b/drivers/char/tpm/tpm_tis_core.c
> > @@ -184,6 +184,9 @@ static int tpm_tis_relinquish_locality(struct tpm_chip *chip, int l)
> > __tpm_tis_relinquish_locality(priv, l);
> > mutex_unlock(&priv->locality_count_mutex);
> >
> > + if (test_bit(TPM_TIS_SETTLE_AFTER_RELINQUISH, &priv->flags))
> > + tpm_msleep(TPM_TIMEOUT);
> > +
> > return 0;
> > }
> >
> > diff --git a/drivers/char/tpm/tpm_tis_core.h b/drivers/char/tpm/tpm_tis_core.h
> > index 6c3aa480396b..413cac5e0f31 100644
> > --- a/drivers/char/tpm/tpm_tis_core.h
> > +++ b/drivers/char/tpm/tpm_tis_core.h
> > @@ -90,6 +90,7 @@ enum tpm_tis_flags {
> > TPM_TIS_DEFAULT_CANCELLATION = 2,
> > TPM_TIS_IRQ_TESTED = 3,
> > TPM_TIS_STATUS_VALID_RETRY = 4,
> > + TPM_TIS_SETTLE_AFTER_RELINQUISH = 5,
> > };
> >
> > struct tpm_tis_data {
> > --
> > 2.54.0
> >
>
> BR, Jarkko
^ permalink raw reply
* Re: [PATCH v10 19/30] KVM: arm64: Provide assembly for SME register access
From: Marc Zyngier @ 2026-05-22 5:52 UTC (permalink / raw)
To: Mark Rutland
Cc: Mark Brown, Oliver Upton, Joey Gouly, Catalin Marinas,
Suzuki K Poulose, Will Deacon, Paolo Bonzini, Jonathan Corbet,
Shuah Khan, Dave Martin, Fuad Tabba, Ben Horgan, linux-arm-kernel,
kvmarm, linux-kernel, kvm, linux-doc, linux-kselftest,
Peter Maydell, Eric Auger
In-Reply-To: <ag8b7oq4SFpdmlP_@J2N7QTR9R3>
On Thu, 21 May 2026 15:51:26 +0100,
Mark Rutland <mark.rutland@arm.com> wrote:
>
> On Fri, Mar 06, 2026 at 05:01:11PM +0000, Mark Brown wrote:
> > Provide versions of the SME state save and restore functions for the
> > hypervisor to allow it to restore ZA and ZT for guests.
> >
> > Signed-off-by: Mark Brown <broonie@kernel.org>
> > ---
> > arch/arm64/include/asm/kvm_hyp.h | 2 ++
> > arch/arm64/kvm/hyp/fpsimd.S | 23 +++++++++++++++++++++++
> > 2 files changed, 25 insertions(+)
>
> While this specific instance is simple enough, I don't think we should
> continue to duplicate the low level save/restore routines between the
> main kernel and KVM hyp code.
>
> I've sent a series that avoids the need for this, and cleans up some
> other bits):
>
> https://lore.kernel.org/linux-arm-kernel/20260521132556.584676-1-mark.rutland@arm.com/
>
> Assuming Marc and Oliver are on board, I'd prefer that we do that
> cleanup first, and build the KVM SME support atop.
Absolutely. The whole FP/SVE is still way too complicated, full of
esoteric constructs, hard to audit, and I would really like to see it
cleaned-up before stacking another layer on top.
I've quickly eyeballed the KVM-specific patches yesterday, and nothing
seem outlandish, so there is a good chance some of that could make it
into 7.2. I plan to look at it again shortly.
Thanks,
M.
--
Jazz isn't dead. It just smells funny.
^ permalink raw reply
* Re: [PATCH v2 0/4] cpufreq: Set policy->min and max as real QoS constraints
From: Viresh Kumar @ 2026-05-22 5:45 UTC (permalink / raw)
To: Pierre Gondois
Cc: linux-kernel, Jie Zhan, Lifeng Zheng, Ionela Voinescu,
Sumit Gupta, Zhongqiu Han, Rafael J. Wysocki, Jonathan Corbet,
Shuah Khan, Huang Rui, Mario Limonciello, Perry Yuan,
K Prateek Nayak, Srinivas Pandruvada, Len Brown, Saravana Kannan,
linux-pm, linux-doc
In-Reply-To: <20260511135538.522653-1-pierre.gondois@arm.com>
On 11-05-26, 15:55, Pierre Gondois wrote:
> This patch is a follow-up from the serie:
> - [PATCH v6 0/4] cpufreq: Introduce boost frequency QoS
> https://lore.kernel.org/lkml/20260317101753.2284763-1-pierre.gondois@arm.com/
Apart from a minor change in patch 2, looks fine now.
--
viresh
^ permalink raw reply
* Re: [PATCH v2 4/4] cpufreq: Use policy->min/max init as QoS request
From: Viresh Kumar @ 2026-05-22 5:44 UTC (permalink / raw)
To: Pierre Gondois
Cc: linux-kernel, Jie Zhan, Lifeng Zheng, Ionela Voinescu,
Sumit Gupta, Zhongqiu Han, Rafael J. Wysocki, Jonathan Corbet,
Shuah Khan, Huang Rui, Mario Limonciello, Perry Yuan,
K Prateek Nayak, Srinivas Pandruvada, Len Brown, Saravana Kannan,
linux-pm, linux-doc
In-Reply-To: <99eb1963-dadc-44e6-9e67-814ed7089379@arm.com>
On 21-05-26, 13:58, Pierre Gondois wrote:
> Sorry if I misunderstand, but if we do:
> This would bring us to what the following patch tried to solve:
> 521223d8b3ec ("cpufreq: Fix initialization of min and max
> frequency QoS requests")
I missed this patch, that's all.
--
viresh
^ permalink raw reply
* Re: [PATCH v2 2/4] cpufreq: Set default policy->min/max values for all drivers
From: Viresh Kumar @ 2026-05-22 5:43 UTC (permalink / raw)
To: Pierre Gondois
Cc: linux-kernel, Jie Zhan, Lifeng Zheng, Ionela Voinescu,
Sumit Gupta, Zhongqiu Han, Rafael J. Wysocki, Jonathan Corbet,
Shuah Khan, Huang Rui, Mario Limonciello, Perry Yuan,
K Prateek Nayak, Srinivas Pandruvada, Len Brown, Saravana Kannan,
linux-pm, linux-doc
In-Reply-To: <20260511135538.522653-3-pierre.gondois@arm.com>
On 11-05-26, 15:55, Pierre Gondois wrote:
> Some drivers set policy->min/max in their .init() callback.
> cpufreq_set_policy() will ultimately override them through:
> cpufreq_policy_online()
> \-cpufreq_init_policy()
> \-cpufreq_set_policy()
> \-/* Set policy->min/max */
> Thus the policy min/max values provided are only temporary.
>
> There is an exception if CPUFREQ_NEED_INITIAL_FREQ_CHECK is set and:
> cpufreq_policy_online()
> \-__cpufreq_driver_target()
> \-cpufreq_driver->target()
>
> To prepare for a following patch that will remove all
> policy->min/max initialization in the driver .init() callback
> if the min/max value is equal to the cpuinfo.min/max_freq,
> set a default policy->min/max value for all drivers.
>
> Signed-off-by: Pierre Gondois <pierre.gondois@arm.com>
> ---
> drivers/cpufreq/cpufreq.c | 7 +++++++
> 1 file changed, 7 insertions(+)
>
> diff --git a/drivers/cpufreq/cpufreq.c b/drivers/cpufreq/cpufreq.c
> index 034603c2af325..9e2d9d3fc5351 100644
> --- a/drivers/cpufreq/cpufreq.c
> +++ b/drivers/cpufreq/cpufreq.c
> @@ -1401,6 +1401,13 @@ static int cpufreq_policy_init_qos(struct cpufreq_policy *policy)
> {
> int ret;
>
> + /*
> + * If the driver didn't set policy->min/max, set them as
> + * they are used to clamp frequency requests.
> + */
> + policy->min = policy->min ? policy->min : policy->cpuinfo.min_freq;
> + policy->max = policy->max ? policy->max : policy->cpuinfo.max_freq;
> +
This has nothing to do with qos-init, we should do it along with:
cpumask_copy(policy->related_cpus, policy->cpus);
in cpufreq_policy_online().
--
viresh
^ permalink raw reply
* [PATCH v4 4/4] Documentation: PCI: Add documentation for DOE endpoint support
From: Aksh Garg @ 2026-05-22 5:24 UTC (permalink / raw)
To: linux-pci, linux-doc, mani, kwilczynski, bhelgaas, corbet, kishon,
skhan, lukas, cassel, alistair
Cc: linux-arm-kernel, linux-kernel, s-vadapalli, danishanwar, srk,
a-garg7
In-Reply-To: <20260522052434.802034-1-a-garg7@ti.com>
Document the architecture and implementation details for the Data Object
Exchange (DOE) framework for PCIe Endpoint devices.
Co-developed-by: Siddharth Vadapalli <s-vadapalli@ti.com>
Signed-off-by: Siddharth Vadapalli <s-vadapalli@ti.com>
Signed-off-by: Aksh Garg <a-garg7@ti.com>
---
Changes from v3 to v4:
- Updated the maximum size of the DOE object from 256KB to 1MB,
as per PCIe spec.
- Updated the DOE setup and cleanup sections.
Changes from v2 to v3:
- Rebased on 7.1-rc1.
Changes since v1:
- Squashed the patches [1] and [2], and moved the documentation file
to Documentation/PCI/endpoint/pci-endpoint-doe.rst to match the existing
naming scheme, as suggested by Niklas Cassel
- Updated the documentation as per the design and implementaion changes
made to previous patches in this series:
* Updated for static protocol array instead of dynamic registration
* Documented asynchronous callback model
* Updated request/response flow with new callback signature
* Updated memory ownership: DOE core frees request, driver frees response
* Updated initialization and cleanup sections for new APIs
v3: https://lore.kernel.org/all/20260427051725.223704-5-a-garg7@ti.com/
v2: https://lore.kernel.org/all/20260401073022.215805-5-a-garg7@ti.com/
v1: [1] https://lore.kernel.org/all/20260213123603.420941-2-a-garg7@ti.com/
[2] https://lore.kernel.org/all/20260213123603.420941-5-a-garg7@ti.com/
Documentation/PCI/endpoint/index.rst | 1 +
.../PCI/endpoint/pci-endpoint-doe.rst | 329 ++++++++++++++++++
2 files changed, 330 insertions(+)
create mode 100644 Documentation/PCI/endpoint/pci-endpoint-doe.rst
diff --git a/Documentation/PCI/endpoint/index.rst b/Documentation/PCI/endpoint/index.rst
index dd1f62e731c9..7c03d5abd2ef 100644
--- a/Documentation/PCI/endpoint/index.rst
+++ b/Documentation/PCI/endpoint/index.rst
@@ -9,6 +9,7 @@ PCI Endpoint Framework
pci-endpoint
pci-endpoint-cfs
+ pci-endpoint-doe
pci-test-function
pci-test-howto
pci-ntb-function
diff --git a/Documentation/PCI/endpoint/pci-endpoint-doe.rst b/Documentation/PCI/endpoint/pci-endpoint-doe.rst
new file mode 100644
index 000000000000..a424a0a3add6
--- /dev/null
+++ b/Documentation/PCI/endpoint/pci-endpoint-doe.rst
@@ -0,0 +1,329 @@
+.. SPDX-License-Identifier: GPL-2.0-only OR MIT
+
+.. include:: <isonum.txt>
+
+=============================================
+Data Object Exchange (DOE) for PCIe Endpoint
+=============================================
+
+:Copyright: |copy| 2026 Texas Instruments Incorporated
+:Author: Aksh Garg <a-garg7@ti.com>
+:Co-Author: Siddharth Vadapalli <s-vadapalli@ti.com>
+
+Overview
+========
+
+DOE (Data Object Exchange) is a standard PCIe extended capability feature
+introduced in the Data Object Exchange (DOE) ECN for PCIe r5.0. It is an optional
+mechanism for system firmware/software running on root complex (host) to perform
+:ref:`data object <data-object-term>` exchanges with an endpoint function. Each
+data object is uniquely identified by the Vendor ID of the vendor publishing the
+data object definition and a Data Object Type value assigned by that vendor.
+
+Think of DOE as a sophisticated mailbox system built into PCIe. The root complex
+can send structured requests to the endpoint device through DOE mailboxes, and
+the endpoint device responds with appropriate data. DOE mailboxes are implemented
+as PCIe Extended Capabilities in endpoint devices, allowing multiple mailboxes
+per function, each potentially supporting different data object protocols.
+
+The DOE support for root complex devices has already been implemented in
+``drivers/pci/doe.c``.
+
+How DOE Works
+=============
+
+The DOE mailbox operates through a simple request-response model:
+
+1. **Host sends request**: The root complex writes a data object (vendor ID, type,
+ and payload) to the DOE write mailbox register (one DWORD at a time) of the
+ endpoint function's config space and sets the GO bit in the DOE Control register
+ to indicate that a request is ready for processing.
+2. **Endpoint processes**: The endpoint function reads the request from DOE write
+ mailbox register, sets the BUSY bit in the DOE Status register, identifies the
+ protocol of the data object, and executes the appropriate handler.
+3. **Endpoint responds**: The endpoint function writes the response data object to the
+ DOE read mailbox register (one DWORD at a time), and sets the READY bit in the DOE
+ Status register to indicate that the response is ready. If an error occurs during
+ request processing (such as unsupported protocol or handler failure), the endpoint
+ sets the ERROR bit in the DOE Status register instead of the READY bit.
+4. **Host reads response**: The root complex retrieves the response data from the DOE read
+ mailbox register once the READY bit is set in the DOE Status register, and then writes
+ any value to this register to indicate a successful read. If the ERROR bit was set,
+ the root complex discards the response and performs error handling as needed.
+
+Each mailbox operates independently and can handle one transaction at a time. The
+DOE specification supports data objects of size up to 1MB (2\ :sup:`18` dwords).
+
+For complete DOE capability details, refer to `PCI Express Base Specification Revision 7.0,
+Section 6.30 - Data Object Exchange (DOE)`.
+
+Key Terminologies
+=================
+
+.. _data-object-term:
+
+**Data Object**
+ A structured, vendor-defined, or standard-defined message exchanged between
+ root complex and endpoint function via DOE capability registers in configuration
+ space of the function.
+
+**Mailbox**
+ A DOE capability on the endpoint device, where each physical function can have
+ multiple mailboxes.
+
+**Protocol**
+ A specific type of DOE communication data object identified by a Vendor ID and Type.
+
+**Handler**
+ A function that processes DOE requests of a specific protocol and generates responses.
+
+Architecture of DOE Implementation for Endpoint
+===============================================
+
+.. code-block:: text
+
+ +------------------+
+ | |
+ | Root Complex |
+ | |
+ +--------^---------+
+ |
+ | Config space access
+ | over PCIe link
+ |
+ +----------v-----------+
+ | |
+ | PCIe Controller |
+ | as Endpoint |
+ | |
+ | +-----------------+ |
+ | | DOE Mailbox | |
+ | +-------^---------+ |
+ +----------|-----------+
+ +-----------|---------------------------------------------------------------+
+ | | +--------------------+ |
+ | +---------v--------+ Allocate | +--------------+ | |
+ | | |-------------------------------->| Request | | |
+ | | EP Controller | +--->| Buffer | | |
+ | | Driver | Free | | +--------------+ | |
+ | | |--------------------------+ | | | |
+ | +--------^---------+ | | | | |
+ | | | | | | |
+ | | | | | | |
+ | | pci_ep_doe_process_request() | | | | |
+ | | | | | | |
+ | +--------v---------+ Free | | | | |
+ | | |----------------------------+ | DDR | |
+ | | DOE EP Core |<----+ | | | |
+ | | (doe-ep.c) | | Discovery | | | |
+ | | |-----+ Protocol Handler | | | |
+ | +--------^---------+ | | | |
+ | | | | | |
+ | | protocol_handler() | | | |
+ | | | | | |
+ | +--------v---------+ | | | |
+ | | | | | +--------------+ | |
+ | | Protocol Handler | +----->| Response | | |
+ | | Module |-------------------------------->| Buffer | | |
+ | | (CMA/SPDM/Other) | Allocate | +--------------+ | |
+ | | | | | |
+ | +------------------+ | | |
+ | +--------------------+ |
+ +---------------------------------------------------------------------------+
+
+Initialization and Cleanup
+--------------------------
+
+**Framework Initialization and DOE Setup**
+
+The EPC core automatically initializes and sets up DOE mailboxes through the
+``pci_epc_init_capabilities()`` internal function, which is invoked during
+``pci_epc_init_notify()`` when the controller driver calls this API.
+Controller drivers do not need to explicitly handle DOE initialization,
+rather the EPC core manages this transparently.
+
+DOE initialization only occurs when the EPC driver reports DOE capability
+through the ``doe_capable`` flag in its ``pci_epc_features``.
+
+This internal function performs the following steps:
+
+1. Calls ``pci_ep_doe_init(epc)`` to initialize the xarray data structure
+ (a resizable array data structure defined in linux) named ``doe_mbs`` that
+ stores metadata of DOE mailboxes for the controller in ``struct pci_epc``.
+2. Calls ``pci_epc_doe_setup(epc)`` to discover all DOE capabilities in the
+ endpoint function's configuration space for each function. For each
+ discovered DOE capability, calls ``pci_ep_doe_add_mailbox(epc, func_no,
+ cap_offset)`` to register the mailbox.
+
+Each DOE mailbox structure created by ``pci_ep_doe_add_mailbox()`` gets an
+ordered workqueue allocated for processing DOE requests sequentially for that
+mailbox, enabling concurrent request handling across different mailboxes. Each
+mailbox is uniquely identified by the combination of physical function number
+and capability offset for that controller.
+
+**Cleanup**
+
+The EPC core automatically cleans up DOE mailboxes through the
+``pci_epc_deinit_capabilities()`` internal function, which is invoked during
+``pci_epc_deinit_notify()`` when the controller driver calls this API.
+Controller drivers do not need to explicitly handle DOE cleanup, rather
+the EPC core manages this transparently.
+
+DOE cleanup only occurs when the EPC device reported DOE capability
+through the ``doe_capable`` flag in its ``pci_epc_features``.
+
+This internal function calls ``pci_ep_doe_destroy(epc)``, which destroys all
+registered mailboxes, cancels any pending tasks, flushes and destroys the
+workqueues, and frees all memory allocated to the mailboxes.
+
+Protocol Handler Support
+------------------------
+
+Protocol implementations (such as CMA, SPDM, or vendor-specific protocols) are
+supported through a static array of protocol handlers.
+
+When a new DOE protocol library is introduced, its handler function is added to
+the static ``pci_doe_protocols`` array in ``drivers/pci/endpoint/pci-ep-doe.c``.
+The discovery protocol (VID = 0x0001 (PCI-SIG vendor ID), Type = 0x00 (discovery
+protocol)) is included in this static array and handled internally by the
+DOE EP core.
+
+Request Handling
+----------------
+
+The complete flow of a DOE request from the root complex to the response:
+
+**Step 1: Root Complex → EP Controller Driver**
+
+The root complex writes a DOE request (Vendor ID, Type, and Payload) to the
+DOE write mailbox register in the endpoint function's configuration space and sets
+the GO bit in the DOE Control register, indicating that the request is ready for
+processing.
+
+**Step 2: EP Controller Driver → DOE EP Core**
+
+The controller driver reads the request header to determine the data object
+length. Based on this length field, it allocates a request buffer in memory
+(DDR) of the appropriate size. The driver then reads the complete request
+payload from the DOE write mailbox register and converts the data from
+little-endian format (the format followed in the PCIe transactions over the
+link) to CPU-native format using ``le32_to_cpu()``. The driver defines a
+completion callback function with signature ``void (*complete)(struct pci_epc *epc,
+u8 func_no, u16 cap_offset, int status, u16 vendor, u8 type, void *response_pl,
+size_t response_pl_sz)`` to be invoked when the request processing completes.
+The driver then calls ``pci_ep_doe_process_request(epc, func_no, cap_offset,
+vendor, type, request, request_sz, complete)`` to hand off the request to the
+DOE EP core. This function returns immediately after queuing the work
+(without blocking), and the driver sets the BUSY bit in the DOE Status register.
+
+**Step 3: DOE EP Core Processing**
+
+The DOE EP core creates a task structure and submits it to the mailbox's ordered
+workqueue. This ensures that requests for each mailbox are processed
+sequentially, one at a time, as required by the DOE specification. It looks up
+the protocol handler based on the Vendor ID and Type from the request header,
+and executes the handler function.
+
+**Step 4: Protocol Handler Execution**
+
+The workqueue executes the task by calling the registered protocol handler:
+``handler(request, request_sz, &response, &response_sz)``. The handler processes
+the request, allocates a response buffer in memory (DDR), builds the response
+data, and returns the response pointer and size. For the discovery protocol,
+the DOE EP core handles this directly without invoking an external handler.
+
+**Step 5: DOE EP Core → EP Controller Driver**
+
+After the protocol handler completes, the DOE EP core frees the request buffer,
+and invokes the completion callback provided by the controller driver asynchronously.
+The callback receives the struct pci_epc, function number, capability offset (to
+identify the mailbox), status code indicating the result of request processing,
+vendor ID and type of the data object, the response buffer, and its size.
+
+**Step 6: EP Controller Driver → Root Complex**
+
+The controller driver converts the response from CPU-native format to
+little-endian format using ``cpu_to_le32()``, writes the response to DOE read
+mailbox register, and sets the READY bit in the DOE Status register. The root
+complex then reads the response from the read mailbox register. Finally, the controller
+driver frees the response buffer (which the handler allocated).
+
+Asynchronous Request Processing
+-------------------------------
+
+The DOE-EP framework implements asynchronous request processing because an
+endpoint function can have multiple instances of DOE mailboxes, and requests may
+be interleaved across these mailboxes. Request processing of one mailbox should
+not result in blocking request processing of other mailboxes. Hence, requests
+on each mailbox need to be handled in parallel for optimization.
+
+For the EP controller driver to handle requests on multiple mailboxes in
+parallel, ``pci_ep_doe_process_request()`` must be asynchronous. The function
+returns immediately after submitting the request to the mailbox's workqueue,
+without waiting for the request to complete. A completion callback provided by
+the controller driver is invoked asynchronously when request processing
+finishes. This asynchronous design enables concurrent processing of requests
+across different mailboxes.
+
+Abort Handling
+--------------
+
+The DOE specification allows the root complex to abort ongoing DOE operations
+by setting the ABORT bit in the DOE Control register.
+
+**Trigger**
+
+When the root complex sets the ABORT bit, the EP controller driver detects this
+condition (typically in an interrupt handler or register polling routine). The
+action taken depends on the timing of the abort:
+
+- **ABORT during request transfer**: If the ABORT bit is set while the root complex
+ is still transferring the request to the mailbox registers, the controller driver
+ discards the request and no call to ``pci_ep_doe_abort()`` is needed.
+
+- **ABORT after request submission**: If the ABORT bit is set after the request
+ has been fully received and submitted to the DOE EP core via
+ ``pci_ep_doe_process_request()``, the controller driver must call
+ ``pci_ep_doe_abort(epc, func_no, cap_offset)`` for the affected mailbox to
+ perform abort sequence in the DOE EP core.
+
+**Abort Sequence**
+
+The abort function performs the following actions:
+
+1. Sets the CANCEL flag on the mailbox to prevent queued requests from starting
+2. Flushes the workqueue to wait for any currently executing handler to complete
+ (handlers cannot be interrupted mid-execution)
+3. Clears the CANCEL flag to allow the mailbox to accept new requests
+
+Queued requests that have not started execution will be aborted with an error
+status. The currently executing request will complete normally, and the controller
+will reject the response if it arrives after the abort sequence has been triggered.
+
+.. note::
+ Independent of when the ABORT bit is triggered, the controller driver must
+ clear the ERROR, BUSY, and READY bits in the DOE Status register after
+ completing the abort operation to reset the mailbox to an idle state.
+
+Error Handling
+--------------
+
+Errors can occur during DOE request processing for various reasons, such as
+unsupported protocols, handler failures, or memory allocation failures.
+
+**Error Detection**
+
+When an error occurs during DOE request processing, the DOE EP core propagates this error
+back to the controller driver either through the ``pci_ep_doe_process_request()`` return value,
+or the status code passed to the completion callback.
+
+**Error Response**
+
+When the controller driver receives an error code, it sets the ERROR bit in the DOE Status
+register instead of writing a response to the read mailbox register, and frees the buffers.
+
+API Reference
+=============
+
+.. kernel-doc:: drivers/pci/endpoint/pci-ep-doe.c
+ :export:
--
2.34.1
^ permalink raw reply related
* [PATCH v4 3/4] PCI: endpoint: Add support for DOE initialization and setup in EPC core
From: Aksh Garg @ 2026-05-22 5:24 UTC (permalink / raw)
To: linux-pci, linux-doc, mani, kwilczynski, bhelgaas, corbet, kishon,
skhan, lukas, cassel, alistair
Cc: linux-arm-kernel, linux-kernel, s-vadapalli, danishanwar, srk,
a-garg7
In-Reply-To: <20260522052434.802034-1-a-garg7@ti.com>
Add pci_epc_init_capabilities() in EPC core driver to initialize and
setup the capabilities supported by the EPC driver. This calls
pci_epc_doe_setup() to setup the DOE framework for an endpoint controller,
which discovers the DOE capabilities (extended capability ID 0x2E), and
registers each discovered DOE mailbox for all the functions in the
endpoint controller.
Add pci_epc_deinit_capabilities() in EPC core driver for cleanup of the
resources used by the capabilities of the EPC driver. This calls
pci_ep_doe_destroy() to destroy all DOE mailboxes and free associated
resources.
Co-developed-by: Siddharth Vadapalli <s-vadapalli@ti.com>
Signed-off-by: Siddharth Vadapalli <s-vadapalli@ti.com>
Signed-off-by: Aksh Garg <a-garg7@ti.com>
---
Changes from v3 to v4:
- Call DOE setup and destroy APIs directly within the EPC core, instead of
relying on the EPC drivers to call them individually. EPC drivers do not
need to explicitly handle DOE setup, rather the EPC core manages this
transparently. (Suggested by Manivannan Sadhasivam).
- Removed pci_epc_doe_destroy() API, which was just calling pci_ep_doe_destroy().
Instead, called pci_ep_doe_destroy() directly during cleanup.
- Called pci_ep_doe_init() before the "!epc->ops->find_ext_capability" check,
because if doe-capable=1 and find_ext_capability() op is undefined, this
would not initialize the epc->doe_mbs xarray. However during cleanup, the
check "!epc->ops->find_ext_capability" would be unnecessary, and it will
try to destroy the epc->doe_mbs xarray even when it was not initialized.
Changes from v2 to v3:
- Rebased on 7.1-rc1.
Changes since v1:
- New patch added to v2 (not present in v1)
v3: https://lore.kernel.org/all/20260427051725.223704-4-a-garg7@ti.com/
v2: https://lore.kernel.org/all/20260401073022.215805-4-a-garg7@ti.com/
This patch is introduced based on the feedback provided by Manivannan
Sadhasivam at [1].
[1]: https://lore.kernel.org/all/p57x6jleaim5w7t2k3v7tioujnaxuovfpj5euop5ogefvw23se@y5fw3che5p5d/
drivers/pci/endpoint/pci-epc-core.c | 92 +++++++++++++++++++++++++++++
include/linux/pci-epc.h | 6 ++
2 files changed, 98 insertions(+)
diff --git a/drivers/pci/endpoint/pci-epc-core.c b/drivers/pci/endpoint/pci-epc-core.c
index 6c3c58185fc5..af7889b541c0 100644
--- a/drivers/pci/endpoint/pci-epc-core.c
+++ b/drivers/pci/endpoint/pci-epc-core.c
@@ -14,6 +14,8 @@
#include <linux/pci-epf.h>
#include <linux/pci-ep-cfs.h>
+#include "../pci.h"
+
static const struct class pci_epc_class = {
.name = "pci_epc",
};
@@ -842,6 +844,71 @@ void pci_epc_linkdown(struct pci_epc *epc)
}
EXPORT_SYMBOL_GPL(pci_epc_linkdown);
+/**
+ * pci_epc_doe_setup() - Discover and setup DOE mailboxes for all functions
+ * @epc: the EPC device on which DOE mailboxes has to be setup
+ *
+ * Discover DOE (Data Object Exchange) capabilities for all physical functions
+ * in the endpoint controller and register DOE mailboxes.
+ *
+ * Returns: 0 on success, -errno on failure
+ */
+static int pci_epc_doe_setup(struct pci_epc *epc)
+{
+ u16 cap_offset = 0;
+ u8 func_no;
+ int ret;
+
+ if (!epc->ops || !epc->ops->find_ext_capability)
+ return -EINVAL;
+
+ /* Discover DOE capabilities for all functions */
+ for (func_no = 0; func_no < epc->max_functions; func_no++) {
+ while ((cap_offset = epc->ops->find_ext_capability(epc, func_no, 0,
+ cap_offset,
+ PCI_EXT_CAP_ID_DOE))) {
+ /* Register this DOE mailbox */
+ ret = pci_ep_doe_add_mailbox(epc, func_no, cap_offset);
+ if (ret) {
+ dev_warn(&epc->dev,
+ "[pf%d:offset %x] failed to add DOE mailbox\n",
+ func_no, cap_offset);
+ }
+ }
+ }
+
+ dev_dbg(&epc->dev, "DOE mailboxes setup complete\n");
+ return 0;
+}
+
+/**
+ * pci_epc_init_capabilities() - Initialize EPC capabilities
+ * @epc: the EPC device whose capabilities need to be initialized
+ *
+ * Invoke to initialize capabilities supported by the EPC device.
+ */
+static void pci_epc_init_capabilities(struct pci_epc *epc)
+{
+ const struct pci_epc_features *epc_features;
+ int ret;
+
+ epc_features = pci_epc_get_features(epc, 0, 0);
+ if (!epc_features)
+ return;
+
+ if (IS_ENABLED(CONFIG_PCI_ENDPOINT_DOE) && epc_features->doe_capable) {
+ ret = pci_ep_doe_init(epc);
+ if (ret) {
+ dev_warn(&epc->dev, "DOE initialization failed: %d\n", ret);
+ return;
+ }
+
+ ret = pci_epc_doe_setup(epc);
+ if (ret)
+ dev_warn(&epc->dev, "DOE setup failed: %d\n", ret);
+ }
+}
+
/**
* pci_epc_init_notify() - Notify the EPF device that EPC device initialization
* is completed.
@@ -857,6 +924,8 @@ void pci_epc_init_notify(struct pci_epc *epc)
if (IS_ERR_OR_NULL(epc))
return;
+ pci_epc_init_capabilities(epc);
+
mutex_lock(&epc->list_lock);
list_for_each_entry(epf, &epc->pci_epf, list) {
mutex_lock(&epf->lock);
@@ -890,6 +959,27 @@ void pci_epc_notify_pending_init(struct pci_epc *epc, struct pci_epf *epf)
}
EXPORT_SYMBOL_GPL(pci_epc_notify_pending_init);
+/**
+ * pci_epc_deinit_capabilities() - Cleanup EPC capabilities
+ * @epc: the EPC device whose capabilities need to be cleaned up
+ *
+ * Invoke to cleanup capabilities supported by the EPC device,
+ * and free the associated resources.
+ */
+static void pci_epc_deinit_capabilities(struct pci_epc *epc)
+{
+ const struct pci_epc_features *epc_features;
+
+ epc_features = pci_epc_get_features(epc, 0, 0);
+ if (!epc_features)
+ return;
+
+ if (IS_ENABLED(CONFIG_PCI_ENDPOINT_DOE) && epc_features->doe_capable) {
+ pci_ep_doe_destroy(epc);
+ dev_dbg(&epc->dev, "DOE mailboxes destroyed\n");
+ }
+}
+
/**
* pci_epc_deinit_notify() - Notify the EPF device about EPC deinitialization
* @epc: the EPC device whose deinitialization is completed
@@ -903,6 +993,8 @@ void pci_epc_deinit_notify(struct pci_epc *epc)
if (IS_ERR_OR_NULL(epc))
return;
+ pci_epc_deinit_capabilities(epc);
+
mutex_lock(&epc->list_lock);
list_for_each_entry(epf, &epc->pci_epf, list) {
mutex_lock(&epf->lock);
diff --git a/include/linux/pci-epc.h b/include/linux/pci-epc.h
index dd26294c8175..11474e337db3 100644
--- a/include/linux/pci-epc.h
+++ b/include/linux/pci-epc.h
@@ -84,6 +84,8 @@ struct pci_epc_map {
* @start: ops to start the PCI link
* @stop: ops to stop the PCI link
* @get_features: ops to get the features supported by the EPC
+ * @find_ext_capability: ops to find extended capability offset for a function
+ * in endpoint controller
* @owner: the module owner containing the ops
*/
struct pci_epc_ops {
@@ -115,6 +117,8 @@ struct pci_epc_ops {
void (*stop)(struct pci_epc *epc);
const struct pci_epc_features* (*get_features)(struct pci_epc *epc,
u8 func_no, u8 vfunc_no);
+ u16 (*find_ext_capability)(struct pci_epc *epc, u8 func_no,
+ u8 vfunc_no, u16 start, u8 cap);
struct module *owner;
};
@@ -270,6 +274,7 @@ struct pci_epc_bar_desc {
* @msi_capable: indicate if the endpoint function has MSI capability
* @msix_capable: indicate if the endpoint function has MSI-X capability
* @intx_capable: indicate if the endpoint can raise INTx interrupts
+ * @doe_capable: indicate if the endpoint function has DOE capability
* @bar: array specifying the hardware description for each BAR
* @align: alignment size required for BAR buffer allocation
*/
@@ -280,6 +285,7 @@ struct pci_epc_features {
unsigned int msi_capable : 1;
unsigned int msix_capable : 1;
unsigned int intx_capable : 1;
+ unsigned int doe_capable : 1;
struct pci_epc_bar_desc bar[PCI_STD_NUM_BARS];
size_t align;
};
--
2.34.1
^ 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