* [PATCH] MIPS: SiByte: Bring back cache initialisation
From: Maciej W. Rozycki @ 2026-03-27 11:38 UTC (permalink / raw)
To: Thomas Bogendoerfer, David Hildenbrand, Andrew Morton,
Arnd Bergmann
Cc: linux-mips, linux-kernel
Bring back cache initialisation for Broadcom SiByte SB1 cores, which has
been removed causing the kernel to hang at bootstrap right after:
Dentry cache hash table entries: 524288 (order: 8, 4194304 bytes, linear)
Inode-cache hash table entries: 262144 (order: 7, 2097152 bytes, linear)
The cause of the problem is R4k cache handlers are also used by Broadcom
SiByte SB1 cores, however with a different cache error exception handler
and therefore not using CPU_R4K_CACHE_TLB:
obj-$(CONFIG_CPU_R4K_CACHE_TLB) += c-r4k.o cex-gen.o tlb-r4k.o
obj-$(CONFIG_CPU_SB1) += c-r4k.o cerr-sb1.o cex-sb1.o tlb-r4k.o
(from arch/mips/mm/Makefile).
Fixes: bbe4f634f48c ("mips: fix r3k_cache_init build regression")
Signed-off-by: Maciej W. Rozycki <macro@orcam.me.uk>
Cc: stable@vger.kernel.org # v6.8+
---
arch/mips/mm/cache.c | 3 ++-
1 file changed, 2 insertions(+), 1 deletion(-)
linux-mips-sibyte-r4k-cache-init.diff
Index: linux-swarm64/arch/mips/mm/cache.c
===================================================================
--- linux-swarm64.orig/arch/mips/mm/cache.c
+++ linux-swarm64/arch/mips/mm/cache.c
@@ -207,7 +207,8 @@ void cpu_cache_init(void)
{
if (IS_ENABLED(CONFIG_CPU_R3000) && cpu_has_3k_cache)
r3k_cache_init();
- if (IS_ENABLED(CONFIG_CPU_R4K_CACHE_TLB) && cpu_has_4k_cache)
+ if ((IS_ENABLED(CONFIG_CPU_R4K_CACHE_TLB) ||
+ IS_ENABLED(CONFIG_CPU_SB1)) && cpu_has_4k_cache)
r4k_cache_init();
if (IS_ENABLED(CONFIG_CPU_CAVIUM_OCTEON) && cpu_has_octeon_cache)
^ permalink raw reply
* Re: [PATCH] lib/crypto: mips: Drop optimized MD5 code
From: Ard Biesheuvel @ 2026-03-27 16:16 UTC (permalink / raw)
To: Eric Biggers, linux-crypto
Cc: linux-kernel, Jason A . Donenfeld, Herbert Xu, linux-mips,
Thomas Bogendoerfer
In-Reply-To: <20260326204824.62010-1-ebiggers@kernel.org>
On Thu, 26 Mar 2026, at 21:48, Eric Biggers wrote:
> MD5 is obsolete. Continuing to maintain architecture-optimized
> implementations of MD5 is unnecessary and risky. It diverts resources
> from the modern algorithms that are actually important.
>
> While there was demand for continuing to maintain the PowerPC optimized
> MD5 code to accommodate userspace programs that are misusing AF_ALG
> (https://lore.kernel.org/linux-crypto/c4191597-341d-4fd7-bc3d-13daf7666c41@csgroup.eu/),
> no such demand has been seen for the MIPS Cavium Octeon optimized MD5
> code. Note that this code runs on only one particular line of SoCs.
>
> Thus, let's drop it and focus effort on the more modern SHA algorithms,
> which already have optimized code for the same SoCs.
>
> Signed-off-by: Eric Biggers <ebiggers@kernel.org>
> ---
>
> This patch is targeting libcrypto-next
>
> lib/crypto/Kconfig | 1 -
> lib/crypto/mips/md5.h | 65 -------------------------------------------
> 2 files changed, 66 deletions(-)
> delete mode 100644 lib/crypto/mips/md5.h
>
Acked-by: Ard Biesheuvel <ardb@kernel.org>
^ permalink raw reply
* [PATCH 0/3] MIPS: Avoid a TLB shutdown induced by a hidden TLB entry bit
From: Maciej W. Rozycki @ 2026-03-27 18:57 UTC (permalink / raw)
To: Thomas Bogendoerfer, Gregory CLEMENT, Thomas Huth,
Philippe Mathieu-Daudé, Keguang Zhang, Jiaxun Yang
Cc: Waldemar Brodkorb, linux-mips, linux-kernel
Hi,
This is a reimplementation of initial TLB entry uniquification so as to
address an issue with processors that implement a hidden TLB entry bit
triggered by commit 9f048fa48740 ("MIPS: mm: Prevent a TLB shutdown on
initial uniquification") for platforms that hand the TLB over unchanged
from reset.
This has been verified across the following systems:
- DECstation 5000/150, R4000SC MIPS III CPU, SEGBITS == 40, 48-entry TLB,
32-bit kernel,
- Broadcom BCM91250A, BCM1250 MIPS64 CPU, SEGBITS == 44, 64-entry TLB,
64-bit kernel,
- MIPS Malta, 74Kf MIPS32r2 CPU, SEGBITS == 31, 64-entry TLB, 32-bit
kernel.
A debug change was used to verify the TLB is initialised as expected.
See individual commit descriptions for details.
I consider this code ready to use, but given the diversity of TLB designs
with MIPS architecture processors I will appreciate verification across
various actual hardware, particularly in preparation for backporting, as
this addresses a serious regression for a subset of systems.
Please apply otherwise. Thank you for patience waiting for this fix.
Maciej
^ permalink raw reply
* [PATCH 1/3] MIPS: Always record SEGBITS in cpu_data.vmbits
From: Maciej W. Rozycki @ 2026-03-27 18:57 UTC (permalink / raw)
To: Thomas Bogendoerfer, Gregory CLEMENT, Thomas Huth,
Philippe Mathieu-Daudé, Keguang Zhang, Jiaxun Yang
Cc: Waldemar Brodkorb, linux-mips, linux-kernel
In-Reply-To: <alpine.DEB.2.21.2603271406020.60268@angie.orcam.me.uk>
With a 32-bit kernel running on 64-bit MIPS hardware the hardcoded value
of `cpu_vmbits' only records the size of compatibility useg and does not
reflect the size of native xuseg or the complete range of values allowed
in the VPN2 field of TLB entries.
An upcoming change will need the actual VPN2 value range permitted even
in 32-bit kernel configurations, so always include the `vmbits' member
in `struct cpuinfo_mips' and probe for SEGBITS when running on 64-bit
hardware and resorting to the currently hardcoded value of 31 on 32-bit
processors. No functional change for users of `cpu_vmbits'.
Signed-off-by: Maciej W. Rozycki <macro@orcam.me.uk>
---
arch/mips/include/asm/cpu-features.h | 1 -
arch/mips/include/asm/cpu-info.h | 2 --
arch/mips/include/asm/mipsregs.h | 2 ++
arch/mips/kernel/cpu-probe.c | 13 ++++++++-----
arch/mips/kernel/cpu-r3k-probe.c | 2 ++
5 files changed, 12 insertions(+), 8 deletions(-)
linux-mips-vmbits.diff
Index: linux-macro/arch/mips/include/asm/cpu-features.h
===================================================================
--- linux-macro.orig/arch/mips/include/asm/cpu-features.h
+++ linux-macro/arch/mips/include/asm/cpu-features.h
@@ -484,7 +484,6 @@
# endif
# ifndef cpu_vmbits
# define cpu_vmbits cpu_data[0].vmbits
-# define __NEED_VMBITS_PROBE
# endif
#endif
Index: linux-macro/arch/mips/include/asm/cpu-info.h
===================================================================
--- linux-macro.orig/arch/mips/include/asm/cpu-info.h
+++ linux-macro/arch/mips/include/asm/cpu-info.h
@@ -80,9 +80,7 @@ struct cpuinfo_mips {
int srsets; /* Shadow register sets */
int package;/* physical package number */
unsigned int globalnumber;
-#ifdef CONFIG_64BIT
int vmbits; /* Virtual memory size in bits */
-#endif
void *data; /* Additional data */
unsigned int watch_reg_count; /* Number that exist */
unsigned int watch_reg_use_cnt; /* Usable by ptrace */
Index: linux-macro/arch/mips/include/asm/mipsregs.h
===================================================================
--- linux-macro.orig/arch/mips/include/asm/mipsregs.h
+++ linux-macro/arch/mips/include/asm/mipsregs.h
@@ -1871,6 +1871,8 @@ do { \
#define read_c0_entryhi() __read_ulong_c0_register($10, 0)
#define write_c0_entryhi(val) __write_ulong_c0_register($10, 0, val)
+#define read_c0_entryhi_64() __read_64bit_c0_register($10, 0)
+#define write_c0_entryhi_64(val) __write_64bit_c0_register($10, 0, val)
#define read_c0_guestctl1() __read_32bit_c0_register($10, 4)
#define write_c0_guestctl1(val) __write_32bit_c0_register($10, 4, val)
Index: linux-macro/arch/mips/kernel/cpu-probe.c
===================================================================
--- linux-macro.orig/arch/mips/kernel/cpu-probe.c
+++ linux-macro/arch/mips/kernel/cpu-probe.c
@@ -210,11 +210,14 @@ static inline void set_elf_base_platform
static inline void cpu_probe_vmbits(struct cpuinfo_mips *c)
{
-#ifdef __NEED_VMBITS_PROBE
- write_c0_entryhi(0x3fffffffffffe000ULL);
- back_to_back_c0_hazard();
- c->vmbits = fls64(read_c0_entryhi() & 0x3fffffffffffe000ULL);
-#endif
+ int vmbits = 31;
+
+ if (cpu_has_64bits) {
+ write_c0_entryhi_64(0x3fffffffffffe000ULL);
+ back_to_back_c0_hazard();
+ vmbits = fls64(read_c0_entryhi_64() & 0x3fffffffffffe000ULL);
+ }
+ c->vmbits = vmbits;
}
static void set_isa(struct cpuinfo_mips *c, unsigned int isa)
Index: linux-macro/arch/mips/kernel/cpu-r3k-probe.c
===================================================================
--- linux-macro.orig/arch/mips/kernel/cpu-r3k-probe.c
+++ linux-macro/arch/mips/kernel/cpu-r3k-probe.c
@@ -137,6 +137,8 @@ void cpu_probe(void)
else
cpu_set_nofpu_opts(c);
+ c->vmbits = 31;
+
reserve_exception_space(0, 0x400);
}
^ permalink raw reply
* [PATCH 2/3] MIPS: mm: Suppress TLB uniquification on EHINV hardware
From: Maciej W. Rozycki @ 2026-03-27 18:57 UTC (permalink / raw)
To: Thomas Bogendoerfer, Gregory CLEMENT, Thomas Huth,
Philippe Mathieu-Daudé, Keguang Zhang, Jiaxun Yang
Cc: Waldemar Brodkorb, linux-mips, linux-kernel
In-Reply-To: <alpine.DEB.2.21.2603271406020.60268@angie.orcam.me.uk>
Hardware that supports the EHINV feature, mandatory for R6 ISA and FTLB
implementation, lets software mark TLB entries invalid, which eliminates
the need to ensure no duplicate matching entries are ever created. This
feature is already used by local_flush_tlb_all(), via the UNIQUE_ENTRYHI
macro, making the preceding call to r4k_tlb_uniquify() superfluous.
The next change will also modify uniquification code such that it'll
become incompatible with the FTLB and MMID features, as well as MIPSr6
CPUs that do not implement 4KiB pages.
Therefore prevent r4k_tlb_uniquify() from being used on EHINV hardware,
as denoted by `cpu_has_tlbinv'.
Signed-off-by: Maciej W. Rozycki <macro@orcam.me.uk>
---
arch/mips/mm/tlb-r4k.c | 3 ++-
1 file changed, 2 insertions(+), 1 deletion(-)
linux-mips-tlb-r4k-uniquify-ehinv.diff
Index: linux-macro/arch/mips/mm/tlb-r4k.c
===================================================================
--- linux-macro.orig/arch/mips/mm/tlb-r4k.c
+++ linux-macro/arch/mips/mm/tlb-r4k.c
@@ -640,7 +640,8 @@ static void r4k_tlb_configure(void)
temp_tlb_entry = current_cpu_data.tlbsize - 1;
/* From this point on the ARC firmware is dead. */
- r4k_tlb_uniquify();
+ if (!cpu_has_tlbinv)
+ r4k_tlb_uniquify();
local_flush_tlb_all();
/* Did I tell you that ARC SUCKS? */
^ permalink raw reply
* [PATCH 3/3] MIPS: mm: Rewrite TLB uniquification for the hidden bit feature
From: Maciej W. Rozycki @ 2026-03-27 18:57 UTC (permalink / raw)
To: Thomas Bogendoerfer, Gregory CLEMENT, Thomas Huth,
Philippe Mathieu-Daudé, Keguang Zhang, Jiaxun Yang
Cc: Waldemar Brodkorb, linux-mips, linux-kernel
In-Reply-To: <alpine.DEB.2.21.2603271406020.60268@angie.orcam.me.uk>
Before the introduction of the EHINV feature, which lets software mark
TLB entries invalid, certain older implementations of the MIPS ISA were
equipped with an analogous bit, as a vendor extension, which however is
hidden from software and only ever set at reset, and then any software
write clears it, making the intended TLB entry valid.
This feature makes it unsafe to read a TLB entry with TLBR, modify the
page mask, and write the entry back with TLBWI, because this operation
will implicitly clear the hidden bit and this may create a duplicate
entry, as with the presence of the hidden bit there is no guarantee all
the entries across the TLB are unique each.
Usually the firmware has already uniquified TLB entries before handing
control over, in which case we only need to guarantee at bootstrap no
clash will happen with the VPN2 values chosen in local_flush_tlb_all().
However with systems such as Mikrotik RB532 we get handed the TLB as at
reset, with the hidden bit set across the entries and possibly duplicate
entries present. This then causes a machine check exception when page
sizes are reset in r4k_tlb_uniquify() and prevents the system from
booting.
Rewrite the algorithm used in r4k_tlb_uniquify() then such as to avoid
the reuse of ASID/VPN values across the TLB. Get rid of global entries
first as they may be blocking the entire address space, e.g. 16 256MiB
pages will exhaust the whole address space of a 32-bit CPU and a single
big page can exhaust the 32-bit compatibility space on a 64-bit CPU.
Details of the algorithm chosen are given across the code itself.
Fixes: 9f048fa48740 ("MIPS: mm: Prevent a TLB shutdown on initial uniquification")
Signed-off-by: Maciej W. Rozycki <macro@orcam.me.uk>
Cc: stable@vger.kernel.org # v6.18+
---
Hi,
I realise this is a little large for backporting, but I think reverting
the original fix isn't a good idea, and neither is going further back,
beyond commit 35ad7e181541 ("MIPS: mm: tlb-r4k: Uniquify TLB entries on
init"), as that'd be fixing one set of systems at the expense of other
systems, and then bringing back random crashes at boot due to clashing TLB
entries.
Maciej
---
arch/mips/mm/tlb-r4k.c | 278 +++++++++++++++++++++++++++++++++++++++----------
1 file changed, 226 insertions(+), 52 deletions(-)
linux-mips-tlb-r4k-uniquify-hidden.diff
Index: linux-macro/arch/mips/mm/tlb-r4k.c
===================================================================
--- linux-macro.orig/arch/mips/mm/tlb-r4k.c
+++ linux-macro/arch/mips/mm/tlb-r4k.c
@@ -13,6 +13,7 @@
#include <linux/sched.h>
#include <linux/smp.h>
#include <linux/memblock.h>
+#include <linux/minmax.h>
#include <linux/mm.h>
#include <linux/hugetlb.h>
#include <linux/export.h>
@@ -24,6 +25,7 @@
#include <asm/hazards.h>
#include <asm/mmu_context.h>
#include <asm/tlb.h>
+#include <asm/tlbdebug.h>
#include <asm/tlbex.h>
#include <asm/tlbmisc.h>
#include <asm/setup.h>
@@ -511,87 +513,259 @@ static int __init set_ntlb(char *str)
__setup("ntlb=", set_ntlb);
-/* Comparison function for EntryHi VPN fields. */
-static int r4k_vpn_cmp(const void *a, const void *b)
+/* The start bit position of VPN2 and Mask in EntryHi/PageMask registers. */
+#define VPN2_SHIFT 13
+
+/* Read full EntryHi even with CONFIG_32BIT. */
+static inline unsigned long long read_c0_entryhi_native(void)
{
- long v = *(unsigned long *)a - *(unsigned long *)b;
- int s = sizeof(long) > sizeof(int) ? sizeof(long) * 8 - 1: 0;
- return s ? (v != 0) | v >> s : v;
+ return cpu_has_64bits ? read_c0_entryhi_64() : read_c0_entryhi();
}
+/* Write full EntryHi even with CONFIG_32BIT. */
+static inline void write_c0_entryhi_native(unsigned long long v)
+{
+ if (cpu_has_64bits)
+ write_c0_entryhi_64(v);
+ else
+ write_c0_entryhi(v);
+}
+
+/* TLB entry state for uniquification. */
+struct tlbent {
+ unsigned long long wired:1;
+ unsigned long long global:1;
+ unsigned long long asid:10;
+ unsigned long long vpn:51;
+ unsigned long long pagesz:5;
+ unsigned long long index:14;
+};
+
/*
- * Initialise all TLB entries with unique values that do not clash with
- * what we have been handed over and what we'll be using ourselves.
+ * Comparison function for TLB entry sorting. Place wired entries first,
+ * then global entries, then order by the increasing VPN/ASID and the
+ * decreasing page size. This lets us avoid clashes with wired entries
+ * easily and get entries for larger pages out of the way first.
+ *
+ * We could group bits so as to reduce the number of comparisons, but this
+ * is seldom executed and not performance-critical, so prefer legibility.
*/
-static void __ref r4k_tlb_uniquify(void)
+static int r4k_entry_cmp(const void *a, const void *b)
{
- int tlbsize = current_cpu_data.tlbsize;
- bool use_slab = slab_is_available();
- int start = num_wired_entries();
- phys_addr_t tlb_vpn_size;
- unsigned long *tlb_vpns;
- unsigned long vpn_mask;
- int cnt, ent, idx, i;
+ struct tlbent ea = *(struct tlbent *)a, eb = *(struct tlbent *)b;
- vpn_mask = GENMASK(cpu_vmbits - 1, 13);
- vpn_mask |= IS_ENABLED(CONFIG_64BIT) ? 3ULL << 62 : 1 << 31;
+ if (ea.wired > eb.wired)
+ return -1;
+ else if (ea.wired < eb.wired)
+ return 1;
+ else if (ea.global > eb.global)
+ return -1;
+ else if (ea.global < eb.global)
+ return 1;
+ else if (ea.vpn < eb.vpn)
+ return -1;
+ else if (ea.vpn > eb.vpn)
+ return 1;
+ else if (ea.asid < eb.asid)
+ return -1;
+ else if (ea.asid > eb.asid)
+ return 1;
+ else if (ea.pagesz > eb.pagesz)
+ return -1;
+ else if (ea.pagesz < eb.pagesz)
+ return 1;
+ else
+ return 0;
+}
- tlb_vpn_size = tlbsize * sizeof(*tlb_vpns);
- tlb_vpns = (use_slab ?
- kmalloc(tlb_vpn_size, GFP_KERNEL) :
- memblock_alloc_raw(tlb_vpn_size, sizeof(*tlb_vpns)));
- if (WARN_ON(!tlb_vpns))
- return; /* Pray local_flush_tlb_all() is good enough. */
+/*
+ * Fetch all the TLB entries. Mask individual VPN values retrieved with
+ * the corresponding page mask and ignoring any 1KiB extension as we'll
+ * be using 4KiB pages for uniquification.
+ */
+static void __ref r4k_tlb_uniquify_read(struct tlbent *tlb_vpns, int tlbsize)
+{
+ int start = num_wired_entries();
+ unsigned long long vpn_mask;
+ bool global;
+ int i;
- htw_stop();
+ vpn_mask = GENMASK(current_cpu_data.vmbits - 1, VPN2_SHIFT);
+ vpn_mask |= cpu_has_64bits ? 3ULL << 62 : 1 << 31;
- for (i = start, cnt = 0; i < tlbsize; i++, cnt++) {
- unsigned long vpn;
+ for (i = 0; i < tlbsize; i++) {
+ unsigned long long entryhi, vpn, mask, asid;
+ unsigned int pagesz;
write_c0_index(i);
mtc0_tlbr_hazard();
tlb_read();
tlb_read_hazard();
- vpn = read_c0_entryhi();
- vpn &= vpn_mask & PAGE_MASK;
- tlb_vpns[cnt] = vpn;
- /* Prevent any large pages from overlapping regular ones. */
- write_c0_pagemask(read_c0_pagemask() & PM_DEFAULT_MASK);
- mtc0_tlbw_hazard();
- tlb_write_indexed();
- tlbw_use_hazard();
+ global = !!(read_c0_entrylo0() & ENTRYLO_G);
+ entryhi = read_c0_entryhi_native();
+ mask = read_c0_pagemask();
+
+ asid = entryhi & cpu_asid_mask(¤t_cpu_data);
+ vpn = (entryhi & vpn_mask & ~mask) >> VPN2_SHIFT;
+ pagesz = ilog2((mask >> VPN2_SHIFT) + 1);
+
+ tlb_vpns[i].global = global;
+ tlb_vpns[i].asid = global ? 0 : asid;
+ tlb_vpns[i].vpn = vpn;
+ tlb_vpns[i].pagesz = pagesz;
+ tlb_vpns[i].wired = i < start;
+ tlb_vpns[i].index = i;
}
+}
- sort(tlb_vpns, cnt, sizeof(tlb_vpns[0]), r4k_vpn_cmp, NULL);
+/*
+ * Write unique values to all but the wired TLB entries each, using
+ * the 4KiB page size. This size might not be supported with R6, but
+ * EHINV is mandatory for R6, so we won't ever be called in that case.
+ *
+ * A sorted table is supplied with any wired entries at the beginning,
+ * followed by any global entries, and then finally regular entries.
+ * We start at the VPN and ASID values of zero and only assign user
+ * addresses, therefore guaranteeing no clash with addresses produced
+ * by UNIQUE_ENTRYHI. We avoid any VPN values used by wired or global
+ * entries, by increasing the VPN value beyond the span of such entry.
+ *
+ * When a VPN/ASID clash is found with a regular entry we increment the
+ * ASID instead until no VPN/ASID clash has been found or the ASID space
+ * has been exhausted, in which case we increase the VPN value beyond
+ * the span of the largest clashing entry.
+ *
+ * We do not need to be concerned about FTLB or MMID configurations as
+ * those are required to implement the EHINV feature.
+ */
+static void __ref r4k_tlb_uniquify_write(struct tlbent *tlb_vpns, int tlbsize)
+{
+ unsigned long long asid, vpn, vpn_size, pagesz;
+ int widx, gidx, idx, sidx, lidx, i;
- write_c0_pagemask(PM_DEFAULT_MASK);
+ vpn_size = 1ULL << (current_cpu_data.vmbits - VPN2_SHIFT);
+ pagesz = ilog2((PM_4K >> VPN2_SHIFT) + 1);
+
+ write_c0_pagemask(PM_4K);
write_c0_entrylo0(0);
write_c0_entrylo1(0);
- idx = 0;
- ent = tlbsize;
- for (i = start; i < tlbsize; i++)
+ asid = 0;
+ vpn = 0;
+ widx = 0;
+ gidx = 0;
+ for (sidx = 0; sidx < tlbsize && tlb_vpns[sidx].wired; sidx++)
+ ;
+ for (lidx = sidx; lidx < tlbsize && tlb_vpns[lidx].global; lidx++)
+ ;
+ idx = gidx = sidx + 1;
+ for (i = sidx; i < tlbsize; i++) {
+ unsigned long long entryhi, vpn_pagesz = 0;
+
while (1) {
- unsigned long entryhi, vpn;
+ if (WARN_ON(vpn >= vpn_size)) {
+ dump_tlb_all();
+ /* Pray local_flush_tlb_all() will cope. */
+ return;
+ }
- entryhi = UNIQUE_ENTRYHI(ent);
- vpn = entryhi & vpn_mask & PAGE_MASK;
+ /* VPN must be below the next wired entry. */
+ if (widx < sidx && vpn >= tlb_vpns[widx].vpn) {
+ vpn = max(vpn,
+ (tlb_vpns[widx].vpn +
+ (1ULL << tlb_vpns[widx].pagesz)));
+ asid = 0;
+ widx++;
+ continue;
+ }
+ /* VPN must be below the next global entry. */
+ if (gidx < lidx && vpn >= tlb_vpns[gidx].vpn) {
+ vpn = max(vpn,
+ (tlb_vpns[gidx].vpn +
+ (1ULL << tlb_vpns[gidx].pagesz)));
+ asid = 0;
+ gidx++;
+ continue;
+ }
+ /* Try to find a free ASID so as to conserve VPNs. */
+ if (idx < tlbsize && vpn == tlb_vpns[idx].vpn &&
+ asid == tlb_vpns[idx].asid) {
+ unsigned long long idx_pagesz;
- if (idx >= cnt || vpn < tlb_vpns[idx]) {
- write_c0_entryhi(entryhi);
- write_c0_index(i);
- mtc0_tlbw_hazard();
- tlb_write_indexed();
- ent++;
- break;
- } else if (vpn == tlb_vpns[idx]) {
- ent++;
- } else {
+ idx_pagesz = tlb_vpns[idx].pagesz;
+ vpn_pagesz = max(vpn_pagesz, idx_pagesz);
+ do
+ idx++;
+ while (idx < tlbsize &&
+ vpn == tlb_vpns[idx].vpn &&
+ asid == tlb_vpns[idx].asid);
+ asid++;
+ if (asid > cpu_asid_mask(¤t_cpu_data)) {
+ vpn += vpn_pagesz;
+ asid = 0;
+ vpn_pagesz = 0;
+ }
+ continue;
+ }
+ /* VPN mustn't be above the next regular entry. */
+ if (idx < tlbsize && vpn > tlb_vpns[idx].vpn) {
+ vpn = max(vpn,
+ (tlb_vpns[idx].vpn +
+ (1ULL << tlb_vpns[idx].pagesz)));
+ asid = 0;
idx++;
+ continue;
}
+ break;
}
+ entryhi = (vpn << VPN2_SHIFT) | asid;
+ write_c0_entryhi_native(entryhi);
+ write_c0_index(tlb_vpns[i].index);
+ mtc0_tlbw_hazard();
+ tlb_write_indexed();
+
+ tlb_vpns[i].asid = asid;
+ tlb_vpns[i].vpn = vpn;
+ tlb_vpns[i].pagesz = pagesz;
+
+ asid++;
+ if (asid > cpu_asid_mask(¤t_cpu_data)) {
+ vpn += 1ULL << pagesz;
+ asid = 0;
+ }
+ }
+}
+
+/*
+ * Initialise all TLB entries with unique values that do not clash with
+ * what we have been handed over and what we'll be using ourselves.
+ */
+static void __ref r4k_tlb_uniquify(void)
+{
+ int tlbsize = current_cpu_data.tlbsize;
+ bool use_slab = slab_is_available();
+ phys_addr_t tlb_vpn_size;
+ struct tlbent *tlb_vpns;
+
+ tlb_vpn_size = tlbsize * sizeof(*tlb_vpns);
+ tlb_vpns = (use_slab ?
+ kmalloc(tlb_vpn_size, GFP_KERNEL) :
+ memblock_alloc_raw(tlb_vpn_size, sizeof(*tlb_vpns)));
+ if (WARN_ON(!tlb_vpns))
+ return; /* Pray local_flush_tlb_all() is good enough. */
+
+ htw_stop();
+
+ r4k_tlb_uniquify_read(tlb_vpns, tlbsize);
+
+ sort(tlb_vpns, tlbsize, sizeof(*tlb_vpns), r4k_entry_cmp, NULL);
+
+ r4k_tlb_uniquify_write(tlb_vpns, tlbsize);
+
+ write_c0_pagemask(PM_DEFAULT_MASK);
+
tlbw_use_hazard();
htw_start();
flush_micro_tlb();
^ permalink raw reply
* Re: [PATCH 0/3] MIPS: Avoid a TLB shutdown induced by a hidden TLB entry bit
From: Waldemar Brodkorb @ 2026-03-27 21:20 UTC (permalink / raw)
To: Maciej W. Rozycki
Cc: Thomas Bogendoerfer, Gregory CLEMENT, Thomas Huth,
Philippe Mathieu-Daudé, Keguang Zhang, Jiaxun Yang,
Waldemar Brodkorb, linux-mips, linux-kernel
In-Reply-To: <alpine.DEB.2.21.2603271406020.60268@angie.orcam.me.uk>
[-- Attachment #1: Type: text/plain, Size: 1851 bytes --]
Hi,
Maciej W. Rozycki wrote,
> Hi,
>
> This is a reimplementation of initial TLB entry uniquification so as to
> address an issue with processors that implement a hidden TLB entry bit
> triggered by commit 9f048fa48740 ("MIPS: mm: Prevent a TLB shutdown on
> initial uniquification") for platforms that hand the TLB over unchanged
> from reset.
>
> This has been verified across the following systems:
>
> - DECstation 5000/150, R4000SC MIPS III CPU, SEGBITS == 40, 48-entry TLB,
> 32-bit kernel,
>
> - Broadcom BCM91250A, BCM1250 MIPS64 CPU, SEGBITS == 44, 64-entry TLB,
> 64-bit kernel,
>
> - MIPS Malta, 74Kf MIPS32r2 CPU, SEGBITS == 31, 64-entry TLB, 32-bit
> kernel.
>
> A debug change was used to verify the TLB is initialised as expected.
>
> See individual commit descriptions for details.
>
> I consider this code ready to use, but given the diversity of TLB designs
> with MIPS architecture processors I will appreciate verification across
> various actual hardware, particularly in preparation for backporting, as
> this addresses a serious regression for a subset of systems.
>
> Please apply otherwise. Thank you for patience waiting for this fix.
>
> Maciej
>
I tested following three devices with success:
Mikrotik RB532
Linksys WRT54GS v1.0
Microchip PIC32MZ Graphics (DA) Starter Kit
I have attached the dmesg output.
For Microchip I had to revert commit ec7c2a107a59a60079eff3308e791a3441231f2e.
It seems there is a Kconfig naming conflict.
I use:
CONFIG_BUILTIN_DTB_NAME="pic32mzda_sk"
CONFIG_BUILTIN_DTB=y
CONFIG_MIPS_NO_APPENDED_DTB=y
Furthermore I had to recognize that ethernet is not working in
Linux, just in u-boot. But that is unrelated to the patches.
You can add my
Tested-by: Waldemar Brodkorb <wbx@openadk.org>
to the patch series.
best regards and thanks very much,
Waldemar
[-- Attachment #2: rb532.txt --]
[-- Type: text/plain, Size: 9628 bytes --]
[ 0.000000] Linux version 7.0.0-rc5+ (wbx@fluor) (mipsel-openadk-linux-uclibc-gcc (GCC) 15.2.0, GNU ld (GNU Binutils) 2.46.0.20260210) #1 Fri Mar 27 20:44:56 CET 2026
[ 0.000000] CPU0 revision is: 0001800a (MIPS 4Kc)
[ 0.000000] User-defined physical RAM map overwrite
[ 0.000000] Primary instruction cache 8kB, VIPT, 4-way, linesize 16 bytes.
[ 0.000000] Primary data cache 8kB, 4-way, VIPT, no aliases, linesize 16 bytes
[ 0.000000] Zone ranges:
[ 0.000000] Normal [mem 0x0000000000000000-0x0000000001ffffff]
[ 0.000000] Movable zone start for each node
[ 0.000000] Early memory node ranges
[ 0.000000] node 0: [mem 0x0000000000000000-0x0000000001ffffff]
[ 0.000000] Initmem setup node 0 [mem 0x0000000000000000-0x0000000001ffffff]
[ 0.000000] pcpu-alloc: s0 r0 d32768 u32768 alloc=1*32768
[ 0.000000] pcpu-alloc: [0] 0
[ 0.000000] Kernel command line: console=ttyS0,115200 gpio=16383 mem=32M kmac=00:0C:42:0A:7D:D3 board=500 boot=1 console=ttyS0,115200 rw root=/dev/nfs ip=dhcp
[ 0.000000] korina mac = 00:0C:42:0A:7D:D3
[ 0.000000] Unknown kernel command line parameters "gpio=16383 board=500 boot=1", will be passed to user space.
[ 0.000000] printk: log buffer data + meta data: 131072 + 409600 = 540672 bytes
[ 0.000000] Dentry cache hash table entries: 4096 (order: 2, 16384 bytes, linear)
[ 0.000000] Inode-cache hash table entries: 2048 (order: 1, 8192 bytes, linear)
[ 0.000000] Built 1 zonelists, mobility grouping on. Total pages: 8192
[ 0.000000] mem auto-init: stack:all(zero), heap alloc:off, heap free:off
[ 0.000000] SLUB: HWalign=16, Order=0-3, MinObjects=0, CPUs=1, Nodes=1
[ 0.000000] NR_IRQS: 256
[ 0.000000] Initializing IRQ's: 168 out of 256
[ 0.000000] calculating r4koff...
[ 0.000000] 000c34f8(799992)
[ 0.000000] CPU frequency 400.00 MHz
[ 0.000000] clocksource: MIPS: mask: 0xffffffff max_cycles: 0xffffffff, max_idle_ns: 9556397797 ns
[ 0.000010] sched_clock: 32 bits at 200MHz, resolution 5ns, wraps every 10737525757ns
[ 0.000238] Calibrating delay loop... 397.82 BogoMIPS (lpj=795648)
[ 0.032129] pid_max: default: 32768 minimum: 301
[ 0.033313] Mount-cache hash table entries: 1024 (order: 0, 4096 bytes, linear)
[ 0.033431] Mountpoint-cache hash table entries: 1024 (order: 0, 4096 bytes, linear)
[ 0.035244] VFS: Finished mounting rootfs on nullfs
[ 0.044672] Memory: 26788K/32768K available (3508K kernel code, 540K rwdata, 488K rodata, 188K init, 188K bss, 5248K reserved, 0K cma-reserved)
[ 0.046628] devtmpfs: initialized
[ 0.055493] clocksource: jiffies: mask: 0xffffffff max_cycles: 0xffffffff, max_idle_ns: 7645041785100000 ns
[ 0.055661] posixtimers hash table entries: 512 (order: 0, 2048 bytes, linear)
[ 0.055769] futex hash table entries: 256 (4096 bytes on 1 NUMA nodes, total 4 KiB, linear).
[ 0.062846] NET: Registered PF_NETLINK/PF_ROUTE protocol family
[ 0.064615] gpio gpiochip0: Static allocation of GPIO base is deprecated, use dynamic allocation.
[ 0.067316] PCI: Initializing PCI
[ 0.073982] SCSI subsystem initialized
[ 0.074986] libata version 3.00 loaded.
[ 0.078000] PCI host bridge to bus 0000:00
[ 0.078065] pci_bus 0000:00: root bus resource [mem 0x50000000-0x5fffffff]
[ 0.078159] pci_bus 0000:00: root bus resource [io 0x18800000-0x188fffff]
[ 0.078244] pci_bus 0000:00: No busn resource found for root bus, will use [bus 00-ff]
[ 0.078396] pci 0000:00:00.0: [111d:0000] type 00 class 0x000000 conventional PCI endpoint
[ 0.078532] pci 0000:00:00.0: BAR 0 [mem 0x00000000-0x07ffffff pref]
[ 0.078626] pci 0000:00:00.0: [Firmware Bug]: BAR 1: invalid; can't size
[ 0.078687] pci 0000:00:00.0: [Firmware Bug]: BAR 2: invalid; can't size
[ 0.105754] pci 0000:00:02.0: [1106:3106] type 00 class 0x020000 conventional PCI endpoint
[ 0.105907] pci 0000:00:02.0: BAR 0 [io 0x0000-0x00ff]
[ 0.106000] pci 0000:00:02.0: BAR 1 [mem 0x00000000-0x000000ff]
[ 0.106192] pci 0000:00:02.0: supports D1 D2
[ 0.106255] pci 0000:00:02.0: PME# supported from D1 D2 D3hot D3cold
[ 0.107022] pci 0000:00:03.0: [1106:3106] type 00 class 0x020000 conventional PCI endpoint
[ 0.107175] pci 0000:00:03.0: BAR 0 [io 0x0000-0x00ff]
[ 0.107268] pci 0000:00:03.0: BAR 1 [mem 0x00000000-0x000000ff]
[ 0.107460] pci 0000:00:03.0: supports D1 D2
[ 0.107524] pci 0000:00:03.0: PME# supported from D1 D2 D3hot D3cold
[ 0.108282] pci 0000:00:04.0: [13a3:0020] type 00 class 0x0b4000 conventional PCI endpoint
[ 0.108435] pci 0000:00:04.0: BAR 0 [mem 0x00000000-0x00000fff]
[ 0.108530] pci 0000:00:04.0: BAR 1 [mem 0x00000000-0x00001fff]
[ 0.108620] pci 0000:00:04.0: BAR 2 [mem 0x00000000-0x00007fff]
[ 0.588562] pci_bus 0000:00: busn_res: [bus 00-ff] end is updated to 00
[ 0.588709] pci 0000:00:04.0: BAR 2 [mem 0x50000000-0x50007fff]: assigned
[ 0.588828] pci 0000:00:04.0: BAR 1 [mem 0x50008000-0x50009fff]: assigned
[ 0.588945] pci 0000:00:04.0: BAR 0 [mem 0x5000a000-0x5000afff]: assigned
[ 0.589061] pci 0000:00:02.0: BAR 0 [io 0x18800000-0x188000ff]: assigned
[ 0.589178] pci 0000:00:02.0: BAR 1 [mem 0x5000b000-0x5000b0ff]: assigned
[ 0.589295] pci 0000:00:03.0: BAR 0 [io 0x18800400-0x188004ff]: assigned
[ 0.589411] pci 0000:00:03.0: BAR 1 [mem 0x5000b100-0x5000b1ff]: assigned
[ 0.590168] clocksource: Switched to clocksource MIPS
[ 0.599236] NET: Registered PF_INET protocol family
[ 0.600633] IP idents hash table entries: 2048 (order: 2, 16384 bytes, linear)
[ 0.603760] tcp_listen_portaddr_hash hash table entries: 1024 (order: 0, 4096 bytes, linear)
[ 0.603892] Table-perturb hash table entries: 65536 (order: 6, 262144 bytes, linear)
[ 0.604075] TCP established hash table entries: 1024 (order: 0, 4096 bytes, linear)
[ 0.604202] TCP bind hash table entries: 1024 (order: 1, 8192 bytes, linear)
[ 0.604384] TCP: Hash tables configured (established 1024 bind 1024)
[ 0.604779] UDP hash table entries: 256 (order: 1, 8192 bytes, linear)
[ 0.604941] UDP-Lite hash table entries: 256 (order: 1, 8192 bytes, linear)
[ 0.606001] NET: Registered PF_UNIX/PF_LOCAL protocol family
[ 0.608962] RPC: Registered named UNIX socket transport module.
[ 0.609013] RPC: Registered udp transport module.
[ 0.609042] RPC: Registered tcp transport module.
[ 0.609071] RPC: Registered tcp-with-tls transport module.
[ 0.609102] RPC: Registered tcp NFSv4.1 backchannel transport module.
[ 0.609236] PCI: CLS 16 bytes, default 16
[ 0.612112] workingset: timestamp_bits=30 max_order=13 bucket_order=0
[ 0.617716] Serial: 8250/16550 driver, 4 ports, IRQ sharing disabled
[ 0.625095] printk: legacy console [ttyS0] disabled
[ 0.626676] serial8250.0: ttyS0 at MMIO 0x18058000 (irq = 104, base_baud = 12499875) is a 16550A
[ 0.626876] printk: legacy console [ttyS0] enabled
[ 1.305205] scsi host0: pata-rb532-cf
[ 1.310727] ata1: PATA max PIO4 irq 149 lpm-pol 0
[ 1.320391] eth0: korina-0.20 15Sep2017
[ 1.325285] via-rhine 0000:00:02.0: enabling device (0080 -> 0083)
[ 1.339809] via-rhine 0000:00:02.0 eth1: VIA Rhine III at (ptrval), 00:0c:42:0a:7d:d4, IRQ 142
[ 1.350430] via-rhine 0000:00:02.0 eth1: MII PHY found at address 1, status 0x7849 advertising 05e1 Link 0000
[ 1.362750] via-rhine 0000:00:03.0: enabling device (0080 -> 0083)
[ 1.377589] via-rhine 0000:00:03.0 eth2: VIA Rhine III at (ptrval), 00:0c:42:0a:7d:d5, IRQ 143
[ 1.388185] via-rhine 0000:00:03.0 eth2: MII PHY found at address 1, status 0x7849 advertising 05e1 Link 0000
[ 1.400158] rc32434_wdt: Stopped watchdog timer
[ 1.406329] rc32434_wdt: Watchdog Timer version 1.0, timer margin: 20 sec
[ 1.415333] NET: Registered PF_PACKET protocol family
[ 1.481057] korina korina eth0: link up, 100Mbps, full-duplex, lpa 0xFFFFFF6F
[ 1.506321] Sending DHCP requests ., OK
[ 1.534742] IP-Config: Got DHCP answer from 192.168.1.254, my address is 192.168.1.9
[ 1.543528] IP-Config: Complete:
[ 1.547275] device=eth0, hwaddr=00:0c:42:0a:7d:d3, ipaddr=192.168.1.9, mask=255.255.255.0, gw=192.168.1.254
[ 1.558747] host=192.168.1.9, domain=, nis-domain=(none)
[ 1.565290] bootserver=192.168.1.254, rootserver=192.168.1.254, rootpath=/srv/nfs/rb532,nfsvers=3
[ 1.565365] nameserver0=192.168.1.254
[ 1.665374] VFS: Mounted root (nfs filesystem) on device 0:14.
[ 1.672918] devtmpfs: mounted
[ 1.676455] VFS: Pivoted into new rootfs
[ 1.681299] Freeing unused kernel image (initmem) memory: 188K
[ 1.687380] This architecture does not have kernel memory protection.
[ 1.694077] Run /sbin/init as init process
[ 1.698478] with arguments:
[ 1.698537] /sbin/init
[ 1.698596] with environment:
[ 1.698647] HOME=/
[ 1.698705] TERM=linux
[ 1.698762] gpio=16383
[ 1.698821] board=500
[ 1.698879] boot=1
[ 1.733382] process '/bin/busybox' started with executable stack
Linux openadk 7.0.0-rc5+ #1 Fri Mar 27 20:44:56 CET 2026 mips GNU/Linux
system type : Mikrotik RB532
machine : Unknown
processor : 0
cpu model : MIPS 4Kc V0.10
BogoMIPS : 397.82
wait instruction : yes
microsecond timers : yes
tlb_entries : 16
extra interrupt vector : yes
hardware watchpoint : yes, count: 1, address/irw mask: [0x0fff]
isa : mips1 mips2 mips32r1
ASEs implemented :
Options implemented : tlb 4kex 4k_cache prefetch mcheck ejtag llsc nan_legacy nan_2008 mm_full
shadow register sets : 1
kscratch registers : 0
package : 0
core : 0
VCED exceptions : not available
VCEI exceptions : not available
[-- Attachment #3: pic32.txt --]
[-- Type: text/plain, Size: 6350 bytes --]
## Loading kernel from FIT Image at 88500000 ...
Using 'conf0' configuration
Trying 'kernel' kernel subimage
Description: Linux kernel
Created: 2026-03-27 20:58:48 UTC
Type: Kernel Image
Compression: lzma compressed
Data Start: 0x885000d0
Data Size: 1574291 Bytes = 1.5 MiB
Architecture: MIPS
OS: Linux
Load Address: 0x88000000
Entry Point: 0x88000000
Verifying Hash Integrity ... OK
## Loading fdt from FIT Image at 88500000 ...
Using 'conf0' configuration
Trying 'fdt' fdt subimage
Description: PIC32 board DTB
Created: 2026-03-27 20:58:48 UTC
Type: Flat Device Tree
Compression: uncompressed
Data Start: 0x88680708
Data Size: 7311 Bytes = 7.1 KiB
Architecture: MIPS
Hash algo: sha256
Hash value: 887d5c29c9694c060696874a30c2ea40370bbc36ca468502a2b760e4bf425022
Verifying Hash Integrity ... sha256+ OK
Booting using the fdt blob at 0x88680708
Uncompressing Kernel Image
Loading Device Tree to 8ff48000, end 8ff4cc8e ... OK
[ 0.000000] Device Id: 0x05f69053, Device Ver: 0x0001
[ 0.000000] OF: reserved mem: Reserved memory: No reserved-memory node in the DT
[ 0.000000] Primary instruction cache 32kB, VIPT, 4-way, linesize 16 bytes.
[ 0.000000] Primary data cache 32kB, 4-way, VIPT, cache aliases, linesize 16 bytes
[ 0.000000] Zone ranges:
[ 0.000000] Normal [mem 0x0000000008000000-0x000000000fffffff]
[ 0.000000] Movable zone start for each node
[ 0.000000] Early memory node ranges
[ 0.000000] node 0: [mem 0x0000000008000000-0x000000000fffffff]
[ 0.000000] Initmem setup node 0 [mem 0x0000000008000000-0x000000000fffffff]
[ 0.000000] Kernel command line: earlyprintk=ttyPIC1,115200n8r console=ttyPIC1,115200n8 console=ttyPIC1,115200 rw root=/dev/nfs ip=dhcp
[ 0.000000] Unknown kernel command line parameters "earlyprintk=ttyPIC1,115200n8r", will be passed to user space.
[ 0.000000] printk: log buffer data + meta data: 131072 + 409600 = 540672 bytes
[ 0.000000] Dentry cache hash table entries: 16384 (order: 4, 65536 bytes, linear)
[ 0.000000] Inode-cache hash table entries: 8192 (order: 3, 32768 bytes, linear)
[ 0.000000] Built 1 zonelists, mobility grouping on. Total pages: 32768
[ 0.000000] mem auto-init: stack:all(zero), heap alloc:off, heap free:off
[ 0.000000] SLUB: HWalign=32, Order=0-3, MinObjects=0, CPUs=1, Nodes=1
[ 0.000000] NR_IRQS: 256
[ 0.000000] CPU Clock: 200MHz
[ 0.000000] clocksource: MIPS: mask: 0xffffffff max_cycles: 0xffffffff, max_idle_ns: 19112604467 ns
[ 0.000010] sched_clock: 32 bits at 100MHz, resolution 10ns, wraps every 21474836475ns
[ 0.007942] Calibrating delay loop... 199.68 BogoMIPS (lpj=399360)
[ 0.045103] pid_max: default: 32768 minimum: 301
[ 0.050804] Mount-cache hash table entries: 1024 (order: 0, 4096 bytes, linear)
[ 0.057499] Mountpoint-cache hash table entries: 1024 (order: 0, 4096 bytes, linear)
[ 0.067409] VFS: Finished mounting rootfs on nullfs
[ 0.085520] Memory: 123656K/131072K available (3662K kernel code, 554K rwdata, 496K rodata, 208K init, 186K bss, 6332K reserved, 0K cma-reserved)
[ 0.102653] devtmpfs: initialized
[ 0.117981] clocksource: jiffies: mask: 0xffffffff max_cycles: 0xffffffff, max_idle_ns: 7645041785100000 ns
[ 0.127284] posixtimers hash table entries: 512 (order: 0, 2048 bytes, linear)
[ 0.134080] futex hash table entries: 256 (4096 bytes on 1 NUMA nodes, total 4 KiB, linear).
[ 0.146965] NET: Registered PF_NETLINK/PF_ROUTE protocol family
[ 0.156118] pic32-clk: dt requests SOSC.
[ 0.191734] gpio gpiochip0: Static allocation of GPIO base is deprecated, use dynamic allocation.
[ 0.201812] gpio gpiochip1: Static allocation of GPIO base is deprecated, use dynamic allocation.
[ 0.211810] gpio gpiochip2: Static allocation of GPIO base is deprecated, use dynamic allocation.
[ 0.221937] gpio gpiochip3: Static allocation of GPIO base is deprecated, use dynamic allocation.
[ 0.231892] gpio gpiochip4: Static allocation of GPIO base is deprecated, use dynamic allocation.
[ 0.241943] gpio gpiochip5: Static allocation of GPIO base is deprecated, use dynamic allocation.
[ 0.251923] gpio gpiochip6: Static allocation of GPIO base is deprecated, use dynamic allocation.
[ 0.262029] gpio gpiochip7: Static allocation of GPIO base is deprecated, use dynamic allocation.
[ 0.272063] gpio gpiochip8: Static allocation of GPIO base is deprecated, use dynamic allocation.
[ 0.282110] gpio gpiochip9: Static allocation of GPIO base is deprecated, use dynamic allocation.
[ 0.295550] 1f822200.serial: ttyPIC1 at MMIO 0x1f822200 (irq = 0, base_baud = 2500000) is a pic32-uart
[ 0.304707] printk: legacy console [ttyPIC1] enabled
[ 0.304707] printk: legacy console [ttyPIC1] enabled
[ 0.314277] printk: legacy bootconsole [early0] disabled
[ 0.472677] NET: Registered PF_UNIX/PF_LOCAL protocol family
[ 0.483342] RPC: Registered named UNIX socket transport module.
[ 0.489820] RPC: Registered udp transport module.
[ 0.494753] RPC: Registered tcp transport module.
[ 0.499719] RPC: Registered tcp-with-tls transport module.
[ 0.505570] RPC: Registered tcp NFSv4.1 backchannel transport module.
[ 0.516264] workingset: timestamp_bits=30 max_order=15 bucket_order=0
[ 0.538271] NET: Registered PF_PACKET protocol family
[ 12.875811] clk: Disabling unused clocks
[ 12.882043] Root-NFS: no NFS server address
[ 12.886683] VFS: Unable to mount root fs via NFS.
[ 12.892208] devtmpfs: mounted
[ 12.895385] VFS: Failed to pivot into new rootfs
[ 12.906115] Freeing unused kernel image (initmem) memory: 208K
[ 12.912383] This architecture does not have kernel memory protection.
[ 12.919176] Run /sbin/init as init process
[ 12.923952] Run /etc/init as init process
[ 12.928796] Run /bin/init as init process
[ 12.933613] Run /bin/sh as init process
[ 12.938264] Kernel panic - not syncing: No working init found. Try passing init= option to kernel. See Linux Documentation/admin-guide/init.rst for guidance.
[ 12.952914] ---[ end Kernel panic - not syncing: No working init found. Try passing init= option to kernel. See Linux Documentation/admin-guide/init.rst for guidance. ]---
[-- Attachment #4: wrt54gs.txt --]
[-- Type: text/plain, Size: 10688 bytes --]
Linux version 6.18.20 (wbx@fluor) (mipsel-freewrt-linux-uclibc-gcc (GCC) 15.2.0, GNU ld (GNU Binutils) 2.46.0.20260210) #1 Fri Mar 27 21:04:53 CET 2026
printk: legacy bootconsole [early0] enabled
CPU0 revision is: 00029007 (Broadcom BMIPS3300)
bcm47xx: Using ssb bus
ssb: Found chip with id 0x4712, rev 0x01 and package 0x00
can not parse nvram name (null)ag0(null) with value 255 got -34
ssb: Sonics Silicon Backplane found at address 0x18000000
Primary instruction cache 8kB, VIPT, 2-way, linesize 16 bytes.
Primary data cache 4kB, 2-way, VIPT, no aliases, linesize 16 bytes
Zone ranges:
Normal [mem 0x0000000000000000-0x0000000001ffffff]
Movable zone start for each node
Early memory node ranges
node 0: [mem 0x0000000000000000-0x0000000001ffffff]
Initmem setup node 0 [mem 0x0000000000000000-0x0000000001ffffff]
pcpu-alloc: s0 r0 d32768 u32768 alloc=1*32768
pcpu-alloc: [0] 0
Kernel command line: root=/dev/mtdblock4 rootfstype=squashfs init=/etc/preinit noinitrd console=ttyS0,115200
Unknown kernel command line parameters "noinitrd", will be passed to user space.
printk: log buffer data + meta data: 131072 + 409600 = 540672 bytes
Dentry cache hash table entries: 4096 (order: 2, 16384 bytes, linear)
Inode-cache hash table entries: 2048 (order: 1, 8192 bytes, linear)
Built 1 zonelists, mobility grouping on. Total pages: 8192
mem auto-init: stack:all(zero), heap alloc:off, heap free:off
SLUB: HWalign=32, Order=0-3, MinObjects=0, CPUs=1, Nodes=1
NR_IRQS: 256
MIPS: machine is Linksys WRT54G/GS/GL
clocksource: MIPS: mask: 0xffffffff max_cycles: 0xffffffff, max_idle_ns: 19112604467 ns
sched_clock: 32 bits at 100MHz, resolution 10ns, wraps every 21474836475ns
Console: colour dummy device 80x25
Calibrating delay loop... 198.65 BogoMIPS (lpj=397312)
pid_max: default: 32768 minimum: 301
Mount-cache hash table entries: 1024 (order: 0, 4096 bytes, linear)
Mountpoint-cache hash table entries: 1024 (order: 0, 4096 bytes, linear)
Memory: 26188K/32768K available (3945K kernel code, 569K rwdata, 948K rodata, 160K init, 267K bss, 6220K reserved, 0K cma-reserved)
devtmpfs: initialized
clocksource: jiffies: mask: 0xffffffff max_cycles: 0xffffffff, max_idle_ns: 7645041785100000 ns
posixtimers hash table entries: 512 (order: 0, 2048 bytes, linear)
futex hash table entries: 256 (4096 bytes on 1 NUMA nodes, total 4 KiB, linear).
NET: Registered PF_NETLINK/PF_ROUTE protocol family
clocksource: Switched to clocksource MIPS
PCI host bridge to bus 0000:00
pci_bus 0000:00: root bus resource [mem 0x40000000-0x7fffffff]
pci_bus 0000:00: root bus resource [io 0x0100-0x07ff]
pci_bus 0000:00: No busn resource found for root bus, will use [bus 00-ff]
pci 0000:00:00.0: PCI: Fixing up bridge 0000:00:00.0
pci 0000:00:00.0: PCI: Fixing up device 0000:00:00.0
pci 0000:00:00.0: PCI: Fixing latency timer of device 0000:00:00.0 to 168
pci 0000:00:00.0: ssb_pcicore_fixup_pcibridge+0x0/0xf8 took 17879 usecs
pci 0000:00:00.0: [14e4:4712] type 00 class 0x060000 conventional PCI endpoint
pci 0000:00:00.0: BAR 0 [mem 0x00000000-0x00001fff]
pci 0000:00:00.0: BAR 1 [mem 0x00000000-0x07ffffff pref]
pci 0000:00:01.0: [14e4:4712] type 00 class 0x060000 conventional PCI endpoint
pci 0000:00:01.0: BAR 0 [mem 0x00000000-0x00001fff]
pci 0000:00:01.0: BAR 1 [mem 0x00000000-0x07ffffff pref]
pci 0000:00:02.0: [14e4:4712] type 00 class 0x060000 conventional PCI endpoint
pci 0000:00:02.0: BAR 0 [mem 0x00000000-0x00001fff]
pci 0000:00:02.0: BAR 1 [mem 0x00000000-0x07ffffff pref]
pci 0000:00:03.0: [14e4:4712] type 00 class 0x060000 conventional PCI endpoint
pci 0000:00:03.0: BAR 0 [mem 0x00000000-0x00001fff]
pci 0000:00:03.0: BAR 1 [mem 0x00000000-0x07ffffff pref]
pci 0000:00:04.0: [14e4:4712] type 00 class 0x060000 conventional PCI endpoint
pci 0000:00:04.0: BAR 0 [mem 0x00000000-0x00001fff]
pci 0000:00:04.0: BAR 1 [mem 0x00000000-0x07ffffff pref]
pci 0000:00:05.0: [14e4:4712] type 00 class 0x060000 conventional PCI endpoint
pci 0000:00:05.0: BAR 0 [mem 0x00000000-0x00001fff]
pci 0000:00:05.0: BAR 1 [mem 0x00000000-0x07ffffff pref]
pci 0000:00:06.0: [14e4:4712] type 00 class 0x060000 conventional PCI endpoint
pci 0000:00:06.0: BAR 0 [mem 0x00000000-0x00001fff]
pci 0000:00:06.0: BAR 1 [mem 0x00000000-0x07ffffff pref]
pci 0000:00:07.0: [14e4:4712] type 00 class 0x060000 conventional PCI endpoint
pci 0000:00:07.0: BAR 0 [mem 0x00000000-0x00001fff]
pci 0000:00:07.0: BAR 1 [mem 0x00000000-0x07ffffff pref]
pci 0000:00:08.0: [14e4:4712] type 00 class 0x060000 conventional PCI endpoint
pci 0000:00:08.0: BAR 0 [mem 0x00000000-0x00001fff]
pci 0000:00:08.0: BAR 1 [mem 0x00000000-0x07ffffff pref]
pci 0000:00:09.0: [14e4:4712] type 00 class 0x060000 conventional PCI endpoint
pci 0000:00:09.0: BAR 0 [mem 0x00000000-0x00001fff]
pci 0000:00:09.0: BAR 1 [mem 0x00000000-0x07ffffff pref]
pci 0000:00:0a.0: [14e4:4712] type 00 class 0x060000 conventional PCI endpoint
pci 0000:00:0a.0: BAR 0 [mem 0x00000000-0x00001fff]
pci 0000:00:0a.0: BAR 1 [mem 0x00000000-0x07ffffff pref]
pci 0000:00:0b.0: [14e4:4712] type 00 class 0x060000 conventional PCI endpoint
pci 0000:00:0b.0: BAR 0 [mem 0x00000000-0x00001fff]
pci 0000:00:0b.0: BAR 1 [mem 0x00000000-0x07ffffff pref]
pci 0000:00:0c.0: [14e4:4712] type 00 class 0x060000 conventional PCI endpoint
pci 0000:00:0c.0: BAR 0 [mem 0x00000000-0x00001fff]
pci 0000:00:0c.0: BAR 1 [mem 0x00000000-0x07ffffff pref]
pci 0000:00:0d.0: [14e4:4712] type 00 class 0x060000 conventional PCI endpoint
pci 0000:00:0d.0: BAR 0 [mem 0x00000000-0x00001fff]
pci 0000:00:0d.0: BAR 1 [mem 0x00000000-0x07ffffff pref]
pci 0000:00:0e.0: [14e4:4712] type 00 class 0x060000 conventional PCI endpoint
pci 0000:00:0e.0: BAR 0 [mem 0x00000000-0x00001fff]
pci 0000:00:0e.0: BAR 1 [mem 0x00000000-0x07ffffff pref]
pci 0000:00:0f.0: [14e4:4712] type 00 class 0x060000 conventional PCI endpoint
pci 0000:00:0f.0: BAR 0 [mem 0x00000000-0x00001fff]
pci 0000:00:0f.0: BAR 1 [mem 0x00000000-0x07ffffff pref]
pci_bus 0000:00: busn_res: [bus 00-ff] end is updated to 00
gpio gpiochip0: Static allocation of GPIO base is deprecated, use dynamic allocation.
NET: Registered PF_INET protocol family
IP idents hash table entries: 2048 (order: 2, 16384 bytes, linear)
tcp_listen_portaddr_hash hash table entries: 1024 (order: 0, 4096 bytes, linear)
Table-perturb hash table entries: 65536 (order: 6, 262144 bytes, linear)
TCP established hash table entries: 1024 (order: 0, 4096 bytes, linear)
TCP bind hash table entries: 1024 (order: 1, 8192 bytes, linear)
TCP: Hash tables configured (established 1024 bind 1024)
UDP hash table entries: 256 (order: 1, 8192 bytes, linear)
UDP-Lite hash table entries: 256 (order: 1, 8192 bytes, linear)
NET: Registered PF_UNIX/PF_LOCAL protocol family
PCI: CLS 0 bytes, default 16
Initialise system trusted keyrings
workingset: timestamp_bits=30 max_order=13 bucket_order=0
squashfs: version 4.0 (2009/01/31) Phillip Lougher
Key type asymmetric registered
Asymmetric key parser 'x509' registered
io scheduler mq-deadline registered
Serial: 8250/16550 driver, 2 ports, IRQ sharing disabled
printk: legacy console [ttyS0] disabled
serial8250.0: ttyS0 at MMIO 0xb8000300 (irq = 3, base_baud = 3125000) is a 16550A
printk: legacy console [ttyS0] enabled
printk: legacy bootconsole [early0] disabled
serial8250.0: ttyS1 at MMIO 0xb8000400 (irq = 3, base_baud = 3125000) is a 16550A
physmap-flash physmap-flash.0: physmap platform flash device: [mem 0x1c000000-0x1e000000]
physmap-flash.0: Found 1 x16 devices at 0x0 in 16-bit bank. Manufacturer ID 0x000089 Chip ID 0x000017
physmap-flash.0: Found an alias at 0x800000 for the chip at 0x0
physmap-flash.0: Found an alias at 0x1000000 for the chip at 0x0
physmap-flash.0: Found an alias at 0x1800000 for the chip at 0x0
Intel/Sharp Extended Query Table at 0x0031
Intel/Sharp Extended Query Table at 0x0031
Using buffer write method
cfi_cmdset_0001: Erase suspend on write enabled
erase region 0: offset=0x0,size=0x20000,blocks=64
4 bcm47xxpart partitions found on MTD device physmap-flash.0
Creating 4 MTD partitions on "physmap-flash.0":
0x000000000000-0x000000040000 : "boot"
0x000000040000-0x0000007c0000 : "firmware"
failed to parse "brcm,trx-magic" DT attribute, using default: -89
3 trx partitions found on MTD device firmware
Creating 3 MTD partitions on "firmware":
0x00000000001c-0x00000000091c : "loader"
mtd: partition "loader" doesn't start on an erase/write block boundary -- force read-only
0x00000000091c-0x0000001bb400 : "linux"
mtd: partition "linux" doesn't start on an erase/write block boundary -- force read-only
0x0000001bb400-0x000000780000 : "rootfs"
mtd: partition "rootfs" doesn't start on an erase/write block boundary -- force read-only
0x0000007c0000-0x0000007e0000 : "fwcf"
0x0000007e0000-0x000000800000 : "nvram"
b44 ssb0:1: could not find PHY at 30, use fixed one
b44: WBX: skip phy completely
b44 ssb0:1 eth0: Broadcom 44xx/47xx 10/100 PCI ethernet driver 00:0f:66:c8:74:47
NET: Registered PF_PACKET protocol family
8021q: 802.1Q VLAN Support v1.8
Loading compiled-in X.509 certificates
input: gpio-keys as /devices/platform/gpio-keys.0/input/input0
check access for rdinit=/init failed: -2, ignoring
VFS: Mounted root (squashfs filesystem) readonly on device 31:4.
devtmpfs: mounted
Freeing unused kernel image (initmem) memory: 160K
This architecture does not have kernel memory protection.
Run /etc/preinit as init process
with arguments:
/etc/preinit
noinitrd
with environment:
HOME=/
TERM=linux
random: crng init done
cfg80211: Loading compiled-in X.509 certificates for regulatory database
Loaded X.509 cert 'sforshee: 00b28ddf47aef9cea7'
Loaded X.509 cert 'wens: 61c038651aabdcf94bd0ac7ff06c7248db18c600'
faux_driver regulatory: Direct firmware load for regulatory.db failed with error -2
cfg80211: failed to load regulatory.db
adm6996: adm6996_gpio: ADM6996L model PHY found.
b43-phy0: Broadcom 4712 WLAN found (core revision 7)
b43-phy0: Found PHY: Analog 2, Type 2 (G), Revision 2
b43-phy0: Found Radio: Manuf 0x17F, ID 0x2050, Revision 2, Version 0
Broadcom 43xx driver loaded [ Features: PL ]
ieee80211 phy0: Selected rate control algorithm 'minstrel_ht'
Linux freewrt 6.18.20 #1 Fri Mar 27 21:04:53 CET 2026 mips GNU/Linux
system type : Broadcom BCM4712
machine : Linksys WRT54G/GS/GL
processor : 0
cpu model : Broadcom BMIPS3300 V0.7
BogoMIPS : 198.65
wait instruction : yes
microsecond timers : yes
tlb_entries : 32
extra interrupt vector : yes
hardware watchpoint : no
isa : mips1 mips2 mips32r1
ASEs implemented :
Options implemented : tlb 4kex 4k_cache prefetch mcheck ejtag llsc
shadow register sets : 1
kscratch registers : 0
package : 0
core : 0
VCED exceptions : not available
VCEI exceptions : not available
^ permalink raw reply
* [PATCH] MIPS: kernel: Remove $0 clobber from `mult_sh_align_mod'
From: Maciej W. Rozycki @ 2026-03-28 14:29 UTC (permalink / raw)
To: Thomas Bogendoerfer; +Cc: linux-mips, linux-kernel
Remove rubbish $0 clobber added to inline asm within `mult_sh_align_mod'
with the removal of support for GCC versions below 3.4 made with commit
57810ecb581a ("MIPS: Remove GCC_IMM_ASM & GCC_REG_ACCUM macros").
Previously a macro was used that, depending on GCC version, expanded to
either `accum' or $0. Since the latter choice was only a placeholder to
keep the syntax consistent and the register referred is hardwired, there
is no point in having it here as it has no effect on code generation.
Signed-off-by: Maciej W. Rozycki <macro@orcam.me.uk>
---
arch/mips/kernel/r4k-bugs64.c | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
linux-mips-cpu-bugs64-gcc-reg-accum-zero.diff
Index: linux-macro/arch/mips/kernel/r4k-bugs64.c
===================================================================
--- linux-macro.orig/arch/mips/kernel/r4k-bugs64.c
+++ linux-macro/arch/mips/kernel/r4k-bugs64.c
@@ -91,7 +91,7 @@ void mult_sh_align_mod(long *v1, long *v
".set pop"
: "=&r" (lv1), "=r" (lw)
: "r" (m1), "r" (m2), "r" (s), "I" (0)
- : "hi", "lo", "$0");
+ : "hi", "lo");
/* We have to use single integers for m1 and m2 and a double
* one for p to be sure the mulsidi3 gcc's RTL multiplication
* instruction has the workaround applied. Older versions of
^ permalink raw reply
* [PATCH 0/3] MIPS: DEC: Rate-limit memory errors
From: Maciej W. Rozycki @ 2026-03-28 15:49 UTC (permalink / raw)
To: Thomas Bogendoerfer; +Cc: linux-mips, linux-kernel
Hi,
A recent failure of one of my systems revealed an issue with memory error
logging where the flood of messages produced, which reported corrected ECC
errors, made the system unusable despite the errors themselves having been
recovered from and the messages serving informational purpose only.
I took the opportunity and actually verified the rate-limiting does its
purpose with the offending system before cleaning memory module contacts,
which has cured the original problem, the third time in ~25 years I've had
the system for -- not too bad, but clearly a recurring issue.
For consistency I have also updated support for the other two DEC memory
system designs, although they're parity-based and therefore memory errors
are fatal and consequently less likely to cause a message flood, although
in principle still possible where a faulty memory location causes a bus
error exception to kill user processes repeatedly. They seem not to have
the issue with memory contacts though, which use the common SIMM design
rather than 0.1"-pitch PCB connectors.
Please apply.
Maciej
^ permalink raw reply
* [PATCH 1/3] MIPS: DEC: Rate-limit memory errors for ECC systems
From: Maciej W. Rozycki @ 2026-03-28 15:49 UTC (permalink / raw)
To: Thomas Bogendoerfer; +Cc: linux-mips, linux-kernel
In-Reply-To: <alpine.DEB.2.21.2603281455390.60268@angie.orcam.me.uk>
Prevent the system from becoming unusable due to a flood of memory error
messages with DECstation and DECsystem models using ECC, that is KN02,
KN03 and KN05 systems. It seems common for gradual oxidation of memory
module contacts to cause memory errors to eventually develop and while
ECC takes care of correcting them and the system affected can continue
operating normally until the contacts have been cleaned, the unlimited
messages make the system spend all its time on producing them, therefore
preventing it from being used.
Rate-limiting removes the load from the system and enables its normal
operation, e.g.:
Bus error interrupt: CPU memory read ECC error at 0x139cfb04
ECC syndrome 0x54 -- corrected single bit error at data bit D3
Bus error interrupt: CPU partial memory write ECC error at 0x138c1f5c
ECC syndrome 0x54 -- corrected single bit error at data bit D3
Bus error interrupt: CPU partial memory write ECC error at 0x138c1f6c
ECC syndrome 0x54 -- corrected single bit error at data bit D3
Bus error interrupt: CPU memory read ECC error at 0x139cff64
ECC syndrome 0x54 -- corrected single bit error at data bit D3
Bus error interrupt: CPU memory read ECC error at 0x136af00c
ECC syndrome 0x54 -- corrected single bit error at data bit D3
Bus error interrupt: CPU memory read ECC error at 0x136af044
ECC syndrome 0x54 -- corrected single bit error at data bit D3
Bus error interrupt: CPU memory read ECC error at 0x136af0cc
ECC syndrome 0x54 -- corrected single bit error at data bit D3
Bus error interrupt: CPU memory read ECC error at 0x136af0cc
ECC syndrome 0x54 -- corrected single bit error at data bit D3
Bus error interrupt: CPU memory read ECC error at 0x136af0e4
ECC syndrome 0x54 -- corrected single bit error at data bit D3
Bus error interrupt: CPU memory read ECC error at 0x136af104
ECC syndrome 0x54 -- corrected single bit error at data bit D3
dec_ecc_be_backend: 34455 callbacks suppressed
Signed-off-by: Maciej W. Rozycki <macro@orcam.me.uk>
---
arch/mips/dec/ecc-berr.c | 16 +++++++++++-----
1 file changed, 11 insertions(+), 5 deletions(-)
linux-mips-dec-berr-ratelimit-ecc.diff
Index: linux-macro/arch/mips/dec/ecc-berr.c
===================================================================
--- linux-macro.orig/arch/mips/dec/ecc-berr.c
+++ linux-macro/arch/mips/dec/ecc-berr.c
@@ -5,12 +5,13 @@
* 5000/240 (KN03), 5000/260 (KN05) and DECsystem 5900 (KN03),
* 5900/260 (KN05) systems.
*
- * Copyright (c) 2003, 2005 Maciej W. Rozycki
+ * Copyright (c) 2003, 2005, 2026 Maciej W. Rozycki
*/
#include <linux/init.h>
#include <linux/interrupt.h>
#include <linux/kernel.h>
+#include <linux/ratelimit.h>
#include <linux/sched.h>
#include <linux/types.h>
@@ -51,6 +52,10 @@ static int dec_ecc_be_backend(struct pt_
static const char overstr[] = "overrun";
static const char eccstr[] = "ECC error";
+ static DEFINE_RATELIMIT_STATE(rs,
+ DEFAULT_RATELIMIT_INTERVAL,
+ DEFAULT_RATELIMIT_BURST);
+
const char *kind, *agent, *cycle, *event;
const char *status = "", *xbit = "", *fmt = "";
unsigned long address;
@@ -70,7 +75,7 @@ static int dec_ecc_be_backend(struct pt_
if (!(erraddr & KN0X_EAR_VALID)) {
/* No idea what happened. */
- printk(KERN_ALERT "Unidentified bus error %s\n", kind);
+ pr_alert_ratelimited("Unidentified bus error %s\n", kind);
return action;
}
@@ -180,12 +185,13 @@ static int dec_ecc_be_backend(struct pt_
}
}
- if (action != MIPS_BE_FIXUP)
+ if (action != MIPS_BE_FIXUP && __ratelimit(&rs)) {
printk(KERN_ALERT "Bus error %s: %s %s %s at %#010lx\n",
kind, agent, cycle, event, address);
- if (action != MIPS_BE_FIXUP && erraddr & KN0X_EAR_ECCERR)
- printk(fmt, " ECC syndrome ", syn, status, xbit, i);
+ if (erraddr & KN0X_EAR_ECCERR)
+ printk(fmt, " ECC syndrome ", syn, status, xbit, i);
+ }
return action;
}
^ permalink raw reply
* [PATCH 2/3] MIPS: DEC: Rate-limit memory errors for KN01 systems
From: Maciej W. Rozycki @ 2026-03-28 15:50 UTC (permalink / raw)
To: Thomas Bogendoerfer; +Cc: linux-mips, linux-kernel
In-Reply-To: <alpine.DEB.2.21.2603281455390.60268@angie.orcam.me.uk>
Similarly to memory errors in ECC systems also rate-limit memory parity
errors for KN01 DECstation and DECsystem models. Unlike with ECC these
events are always fatal and are less likely to cause a message flood,
but handle them the same way for consistency.
Signed-off-by: Maciej W. Rozycki <macro@orcam.me.uk>
---
arch/mips/dec/kn01-berr.c | 6 +++---
1 file changed, 3 insertions(+), 3 deletions(-)
linux-mips-dec-berr-ratelimit-kn01.diff
Index: linux-macro/arch/mips/dec/kn01-berr.c
===================================================================
--- linux-macro.orig/arch/mips/dec/kn01-berr.c
+++ linux-macro/arch/mips/dec/kn01-berr.c
@@ -4,7 +4,7 @@
* and 2100 (KN01) systems equipped with parity error detection
* logic.
*
- * Copyright (c) 2005 Maciej W. Rozycki
+ * Copyright (c) 2005, 2026 Maciej W. Rozycki
*/
#include <linux/init.h>
@@ -134,8 +134,8 @@ static int dec_kn01_be_backend(struct pt
action = MIPS_BE_FIXUP;
if (action != MIPS_BE_FIXUP)
- printk(KERN_ALERT "Bus error %s: %s %s %s at %#010lx\n",
- kind, agent, cycle, event, address);
+ pr_alert_ratelimited("Bus error %s: %s %s %s at %#010lx\n",
+ kind, agent, cycle, event, address);
return action;
}
^ permalink raw reply
* [PATCH 3/3] MIPS: DEC: Rate-limit memory errors for non-KN01 parity systems
From: Maciej W. Rozycki @ 2026-03-28 15:50 UTC (permalink / raw)
To: Thomas Bogendoerfer; +Cc: linux-mips, linux-kernel
In-Reply-To: <alpine.DEB.2.21.2603281455390.60268@angie.orcam.me.uk>
Similarly to memory errors in ECC systems also rate-limit memory parity
errors for KN02-BA, KN02-CA, KN04-BA, KN04-CA DECstation and DECsystem
models. Unlike with ECC these events are always fatal and are less
likely to cause a message flood, but handle them the same way for
consistency.
Signed-off-by: Maciej W. Rozycki <macro@orcam.me.uk>
---
arch/mips/dec/kn02xa-berr.c | 26 ++++++++++++++++----------
1 file changed, 16 insertions(+), 10 deletions(-)
linux-mips-dec-berr-ratelimit-kn02xa.diff
Index: linux-macro/arch/mips/dec/kn02xa-berr.c
===================================================================
--- linux-macro.orig/arch/mips/dec/kn02xa-berr.c
+++ linux-macro/arch/mips/dec/kn02xa-berr.c
@@ -6,12 +6,13 @@
* DECstation/DECsystem 5000/20, /25, /33 (KN02-CA), 5000/50
* (KN04-CA) systems.
*
- * Copyright (c) 2005 Maciej W. Rozycki
+ * Copyright (c) 2005, 2026 Maciej W. Rozycki
*/
#include <linux/init.h>
#include <linux/interrupt.h>
#include <linux/kernel.h>
+#include <linux/ratelimit.h>
#include <linux/types.h>
#include <asm/addrspace.h>
@@ -50,6 +51,10 @@ static int dec_kn02xa_be_backend(struct
static const char paritystr[] = "parity error";
static const char lanestat[][4] = { " OK", "BAD" };
+ static DEFINE_RATELIMIT_STATE(rs,
+ DEFAULT_RATELIMIT_INTERVAL,
+ DEFAULT_RATELIMIT_BURST);
+
const char *kind, *agent, *cycle, *event;
unsigned long address;
@@ -79,18 +84,19 @@ static int dec_kn02xa_be_backend(struct
if (is_fixup)
action = MIPS_BE_FIXUP;
- if (action != MIPS_BE_FIXUP)
+ if (action != MIPS_BE_FIXUP && __ratelimit(&rs)) {
printk(KERN_ALERT "Bus error %s: %s %s %s at %#010lx\n",
kind, agent, cycle, event, address);
- if (action != MIPS_BE_FIXUP && address < 0x10000000)
- printk(KERN_ALERT " Byte lane status %#3x -- "
- "#3: %s, #2: %s, #1: %s, #0: %s\n",
- (mer & KN02XA_MER_BYTERR) >> 8,
- lanestat[(mer & KN02XA_MER_BYTERR_3) != 0],
- lanestat[(mer & KN02XA_MER_BYTERR_2) != 0],
- lanestat[(mer & KN02XA_MER_BYTERR_1) != 0],
- lanestat[(mer & KN02XA_MER_BYTERR_0) != 0]);
+ if (address < 0x10000000)
+ printk(KERN_ALERT " Byte lane status %#3x -- "
+ "#3: %s, #2: %s, #1: %s, #0: %s\n",
+ (mer & KN02XA_MER_BYTERR) >> 8,
+ lanestat[(mer & KN02XA_MER_BYTERR_3) != 0],
+ lanestat[(mer & KN02XA_MER_BYTERR_2) != 0],
+ lanestat[(mer & KN02XA_MER_BYTERR_1) != 0],
+ lanestat[(mer & KN02XA_MER_BYTERR_0) != 0]);
+ }
return action;
}
^ permalink raw reply
* [PATCH 0/2] MIPS RB532 GPIO descriptor conversion
From: Linus Walleij @ 2026-03-28 15:55 UTC (permalink / raw)
To: Thomas Bogendoerfer, Dmitry Torokhov, Bartosz Golaszewski,
Miquel Raynal, Richard Weinberger, Vignesh Raghavendra
Cc: linux-mips, linux-input, linux-gpio, linux-mtd, Linus Walleij
This moves the MIPS Mikrotik RouterBoard RB532 over to using
GPIO descriptors by augmenting the two remaining drivers using
GPIOs to use software nodes and device properties.
This is part of the pull to get rid of the legacy GPIO API
inside the kernel.
It would be nice if someone can test of this actually works,
I've only compile-tested it.
If we can agree on this method to move forward with this machine
it would be nice if the MIPS maintainer could merge the end
result with ACKs from the input and MTD maintainers.
Signed-off-by: Linus Walleij <linusw@kernel.org>
---
Linus Walleij (2):
MIPS/input: Move RB532 button to GPIO descriptors
MIPS/mtd: Handle READY GPIO in generic NAND platform data
arch/mips/rb532/devices.c | 83 ++++++++++++++++++++++++++++-----------
drivers/input/misc/rb532_button.c | 35 ++++++++++++++---
drivers/mtd/nand/raw/plat_nand.c | 24 ++++++++++-
3 files changed, 113 insertions(+), 29 deletions(-)
---
base-commit: 6de23f81a5e08be8fbf5e8d7e9febc72a5b5f27f
change-id: 20260327-mips-input-rb532-button-39e44085a2f9
Best regards,
--
Linus Walleij <linusw@kernel.org>
^ permalink raw reply
* [PATCH 1/2] MIPS/input: Move RB532 button to GPIO descriptors
From: Linus Walleij @ 2026-03-28 15:55 UTC (permalink / raw)
To: Thomas Bogendoerfer, Dmitry Torokhov, Bartosz Golaszewski,
Miquel Raynal, Richard Weinberger, Vignesh Raghavendra
Cc: linux-mips, linux-input, linux-gpio, linux-mtd, Linus Walleij
In-Reply-To: <20260328-mips-input-rb532-button-v1-0-98e201621501@kernel.org>
Convert the Mikrotik RouterBoard RB532 to use GPIO descriptors
by defining a software node for the GPIO chip, then register
the button platform device with full info passing the GPIO
as a device property.
This can be used as a base to move more of the RB532 devices
over to passing GPIOs using device properties.
Use the GPIO_ACTIVE_LOW flag and drop the inversion in the
rb532_button_pressed() function.
Signed-off-by: Linus Walleij <linusw@kernel.org>
---
arch/mips/rb532/devices.c | 47 +++++++++++++++++++++++++++++++++------
drivers/input/misc/rb532_button.c | 35 ++++++++++++++++++++++++-----
2 files changed, 69 insertions(+), 13 deletions(-)
diff --git a/arch/mips/rb532/devices.c b/arch/mips/rb532/devices.c
index 4f027efbf27b..3f56d9feb73a 100644
--- a/arch/mips/rb532/devices.c
+++ b/arch/mips/rb532/devices.c
@@ -16,8 +16,10 @@
#include <linux/mtd/mtd.h>
#include <linux/gpio.h>
#include <linux/gpio/machine.h>
+#include <linux/gpio/property.h>
#include <linux/gpio_keys.h>
#include <linux/input.h>
+#include <linux/property.h>
#include <linux/serial_8250.h>
#include <asm/bootinfo.h>
@@ -38,6 +40,10 @@ extern unsigned int idt_cpu_freq;
static struct mpmc_device dev3;
+static const struct software_node rb532_gpio0_node = {
+ .name = "gpio0",
+};
+
void set_latch_u5(unsigned char or_mask, unsigned char nand_mask)
{
unsigned long flags;
@@ -189,11 +195,6 @@ static struct platform_device rb532_led = {
.id = -1,
};
-static struct platform_device rb532_button = {
- .name = "rb532-button",
- .id = -1,
-};
-
static struct resource rb532_wdt_res[] = {
{
.name = "rb532_wdt_res",
@@ -236,11 +237,23 @@ static struct platform_device *rb532_devs[] = {
&nand_slot0,
&cf_slot0,
&rb532_led,
- &rb532_button,
&rb532_uart,
&rb532_wdt
};
+static const struct property_entry rb532_button_properties[] = {
+ PROPERTY_ENTRY_GPIO("button-gpios", &rb532_gpio0_node,
+ GPIO_BTN_S1, GPIO_ACTIVE_LOW),
+ { }
+};
+
+static const struct platform_device_info rb532_button_info __initconst = {
+ .name = "rb532-button",
+ .id = PLATFORM_DEVID_NONE,
+ .properties = rb532_button_properties,
+};
+
+
/* NAND definitions */
#define NAND_CHIP_DELAY 25
@@ -267,6 +280,9 @@ static void __init rb532_nand_setup(void)
static int __init plat_setup_devices(void)
{
+ struct platform_device *pd;
+ int ret;
+
/* Look for the CF card reader */
if (!readl(IDT434_REG_BASE + DEV1MASK))
rb532_devs[2] = NULL; /* disable cf_slot0 at index 2 */
@@ -295,7 +311,24 @@ static int __init plat_setup_devices(void)
rb532_uart_res[0].uartclk = idt_cpu_freq;
gpiod_add_lookup_table(&cf_slot0_gpio_table);
- return platform_add_devices(rb532_devs, ARRAY_SIZE(rb532_devs));
+ ret = platform_add_devices(rb532_devs, ARRAY_SIZE(rb532_devs));
+ if (ret)
+ return ret;
+
+ /*
+ * Stack devices using full info and properties here, after we
+ * register the node for the GPIO chip.
+ */
+ software_node_register(&rb532_gpio0_node);
+
+ pd = platform_device_register_full(&rb532_button_info);
+ ret = PTR_ERR_OR_ZERO(pd);
+ if (ret) {
+ pr_err("failed to create RB532 button device: %d\n", ret);
+ return ret;
+ }
+
+ return 0;
}
#ifdef CONFIG_NET
diff --git a/drivers/input/misc/rb532_button.c b/drivers/input/misc/rb532_button.c
index 190a80e1e2c1..40173bf7a235 100644
--- a/drivers/input/misc/rb532_button.c
+++ b/drivers/input/misc/rb532_button.c
@@ -8,7 +8,7 @@
#include <linux/input.h>
#include <linux/module.h>
#include <linux/platform_device.h>
-#include <linux/gpio.h>
+#include <linux/gpio/consumer.h>
#include <asm/mach-rc32434/gpio.h>
#include <asm/mach-rc32434/rb.h>
@@ -18,6 +18,14 @@
#define RB532_BTN_RATE 100 /* msec */
#define RB532_BTN_KSYM BTN_0
+/**
+ * struct rb532_button - RB532 button information
+ * @gpio: GPIO connected to the button
+ */
+struct rb532_button {
+ struct gpio_desc *gpio;
+};
+
/* The S1 button state is provided by GPIO pin 1. But as this
* pin is also used for uart input as alternate function, the
* operational modes must be switched first:
@@ -31,35 +39,48 @@
* The GPIO value occurs to be inverted, so pin high means
* button is not pressed.
*/
-static bool rb532_button_pressed(void)
+static bool rb532_button_pressed(struct rb532_button *button)
{
int val;
set_latch_u5(0, LO_FOFF);
- gpio_direction_input(GPIO_BTN_S1);
+ gpiod_direction_input(button->gpio);
- val = gpio_get_value(GPIO_BTN_S1);
+ val = gpiod_get_value(button->gpio);
rb532_gpio_set_func(GPIO_BTN_S1);
set_latch_u5(LO_FOFF, 0);
- return !val;
+ return val;
}
static void rb532_button_poll(struct input_dev *input)
{
- input_report_key(input, RB532_BTN_KSYM, rb532_button_pressed());
+ struct rb532_button *button = input_get_drvdata(input);
+
+ input_report_key(input, RB532_BTN_KSYM, rb532_button_pressed(button));
input_sync(input);
}
static int rb532_button_probe(struct platform_device *pdev)
{
+ struct rb532_button *button;
struct input_dev *input;
int error;
+ button = devm_kzalloc(&pdev->dev, sizeof(*button), GFP_KERNEL);
+ if (!button)
+ return -ENOMEM;
+
+ button->gpio = devm_gpiod_get(&pdev->dev, "button", GPIOD_IN);
+ if (IS_ERR(button->gpio))
+ return dev_err_probe(&pdev->dev, PTR_ERR(button->gpio),
+ "error getting button GPIO\n");
+
input = devm_input_allocate_device(&pdev->dev);
if (!input)
return -ENOMEM;
+ input_set_drvdata(input, button);
input->name = "rb532 button";
input->phys = "rb532/button0";
@@ -77,6 +98,8 @@ static int rb532_button_probe(struct platform_device *pdev)
if (error)
return error;
+ platform_set_drvdata(pdev, button);
+
return 0;
}
--
2.53.0
^ permalink raw reply related
* [PATCH 2/2] MIPS/mtd: Handle READY GPIO in generic NAND platform data
From: Linus Walleij @ 2026-03-28 15:55 UTC (permalink / raw)
To: Thomas Bogendoerfer, Dmitry Torokhov, Bartosz Golaszewski,
Miquel Raynal, Richard Weinberger, Vignesh Raghavendra
Cc: linux-mips, linux-input, linux-gpio, linux-mtd, Linus Walleij
In-Reply-To: <20260328-mips-input-rb532-button-v1-0-98e201621501@kernel.org>
The callbacks into the MIPS RB532 platform to read the GPIO pin
indicating that the NAND chip is ready are oldschool and does
not assign GPIOs as properties to the NAND device.
Add a capability to the generic platform NAND chip driver to use
a GPIO line to detect if a NAND chip is ready and override the
platform-local drv_ready() callback with this check if the GPIO
is present.
This makes it possible to drop the legacy include header
<linux/gpio.h> from the RB532 devices.
Signed-off-by: Linus Walleij <linusw@kernel.org>
---
arch/mips/rb532/devices.c | 36 +++++++++++++++++++++---------------
drivers/mtd/nand/raw/plat_nand.c | 24 +++++++++++++++++++++++-
2 files changed, 44 insertions(+), 16 deletions(-)
diff --git a/arch/mips/rb532/devices.c b/arch/mips/rb532/devices.c
index 3f56d9feb73a..c3d8d96d0ef5 100644
--- a/arch/mips/rb532/devices.c
+++ b/arch/mips/rb532/devices.c
@@ -14,7 +14,6 @@
#include <linux/platform_device.h>
#include <linux/mtd/platnand.h>
#include <linux/mtd/mtd.h>
-#include <linux/gpio.h>
#include <linux/gpio/machine.h>
#include <linux/gpio/property.h>
#include <linux/gpio_keys.h>
@@ -135,12 +134,6 @@ static struct platform_device cf_slot0 = {
.num_resources = ARRAY_SIZE(cf_slot0_res),
};
-/* Resources and device for NAND */
-static int rb532_dev_ready(struct nand_chip *chip)
-{
- return gpio_get_value(GPIO_RDY);
-}
-
static void rb532_cmd_ctrl(struct nand_chip *chip, int cmd, unsigned int ctrl)
{
unsigned char orbits, nandbits;
@@ -166,16 +159,23 @@ static struct resource nand_slot0_res[] = {
};
static struct platform_nand_data rb532_nand_data = {
- .ctrl.dev_ready = rb532_dev_ready,
.ctrl.cmd_ctrl = rb532_cmd_ctrl,
};
-static struct platform_device nand_slot0 = {
- .name = "gen_nand",
- .id = -1,
- .resource = nand_slot0_res,
- .num_resources = ARRAY_SIZE(nand_slot0_res),
- .dev.platform_data = &rb532_nand_data,
+static const struct property_entry nand0_properties[] = {
+ PROPERTY_ENTRY_GPIO("ready-gpios", &rb532_gpio0_node,
+ GPIO_RDY, GPIO_ACTIVE_HIGH),
+ { }
+};
+
+static const struct platform_device_info nand0_info __initconst = {
+ .name = "gen_nand",
+ .id = PLATFORM_DEVID_NONE,
+ .res = nand_slot0_res,
+ .num_res = ARRAY_SIZE(nand_slot0_res),
+ .data = &rb532_nand_data,
+ .size_data = sizeof(struct platform_nand_data),
+ .properties = nand0_properties,
};
static struct mtd_partition rb532_partition_info[] = {
@@ -234,7 +234,6 @@ static struct platform_device rb532_uart = {
static struct platform_device *rb532_devs[] = {
&korina_dev0,
- &nand_slot0,
&cf_slot0,
&rb532_led,
&rb532_uart,
@@ -321,6 +320,13 @@ static int __init plat_setup_devices(void)
*/
software_node_register(&rb532_gpio0_node);
+ pd = platform_device_register_full(&nand0_info);
+ ret = PTR_ERR_OR_ZERO(pd);
+ if (ret) {
+ pr_err("failed to create NAND slot0 device: %d\n", ret);
+ return ret;
+ }
+
pd = platform_device_register_full(&rb532_button_info);
ret = PTR_ERR_OR_ZERO(pd);
if (ret) {
diff --git a/drivers/mtd/nand/raw/plat_nand.c b/drivers/mtd/nand/raw/plat_nand.c
index 0bcd455328ef..fe31551bcf5f 100644
--- a/drivers/mtd/nand/raw/plat_nand.c
+++ b/drivers/mtd/nand/raw/plat_nand.c
@@ -6,6 +6,7 @@
*/
#include <linux/err.h>
+#include <linux/gpio/consumer.h>
#include <linux/io.h>
#include <linux/module.h>
#include <linux/platform_device.h>
@@ -17,6 +18,7 @@ struct plat_nand_data {
struct nand_controller controller;
struct nand_chip chip;
void __iomem *io_base;
+ struct gpio_desc *ready_gpio;
};
static int plat_nand_attach_chip(struct nand_chip *chip)
@@ -32,6 +34,14 @@ static const struct nand_controller_ops plat_nand_ops = {
.attach_chip = plat_nand_attach_chip,
};
+/* Resources and device for NAND */
+static int plat_nand_gpio_dev_ready(struct nand_chip *chip)
+{
+ struct plat_nand_data *data = nand_get_controller_data(chip);
+
+ return gpiod_get_value(data->ready_gpio);
+}
+
/*
* Probe for the NAND device.
*/
@@ -41,6 +51,7 @@ static int plat_nand_probe(struct platform_device *pdev)
struct plat_nand_data *data;
struct mtd_info *mtd;
const char **part_types;
+ struct nand_chip *chip;
int err = 0;
if (!pdata) {
@@ -59,9 +70,17 @@ static int plat_nand_probe(struct platform_device *pdev)
if (!data)
return -ENOMEM;
+ data->ready_gpio = devm_gpiod_get_optional(&pdev->dev, "ready",
+ GPIOD_IN);
+ if (IS_ERR(data->ready_gpio))
+ return dev_err_probe(&pdev->dev, PTR_ERR(data->ready_gpio),
+ "could not get READY GPIO\n");
+
data->controller.ops = &plat_nand_ops;
nand_controller_init(&data->controller);
data->chip.controller = &data->controller;
+ chip = &data->chip;
+ nand_set_controller_data(chip, data);
data->io_base = devm_platform_ioremap_resource(pdev, 0);
if (IS_ERR(data->io_base))
@@ -74,7 +93,10 @@ static int plat_nand_probe(struct platform_device *pdev)
data->chip.legacy.IO_ADDR_R = data->io_base;
data->chip.legacy.IO_ADDR_W = data->io_base;
data->chip.legacy.cmd_ctrl = pdata->ctrl.cmd_ctrl;
- data->chip.legacy.dev_ready = pdata->ctrl.dev_ready;
+ if (data->ready_gpio)
+ data->chip.legacy.dev_ready = plat_nand_gpio_dev_ready;
+ else
+ data->chip.legacy.dev_ready = pdata->ctrl.dev_ready;
data->chip.legacy.select_chip = pdata->ctrl.select_chip;
data->chip.legacy.write_buf = pdata->ctrl.write_buf;
data->chip.legacy.read_buf = pdata->ctrl.read_buf;
--
2.53.0
^ permalink raw reply related
* [PATCH] MIPS: Increase default mmap randomization bits for 64-bit
From: Bingwu Zhang @ 2026-03-28 22:57 UTC (permalink / raw)
To: Thomas Bogendoerfer, Kees Cook, Matt Redfearn
Cc: Yao Zi, Icenowy Zheng, Jiaxun Yang, linux-mips, linux-kernel,
Bingwu Zhang
From: Bingwu Zhang <xtex@astrafall.org>
Increase mmap randomization bits on 64-bit from [12,18] to [18,20] for
better strength.
The original default, 12, means that ASLR offset has only (1 << 12) =
4096 possibilities. On average, it can be brute-forced in 2048 attempts.
If a service is configured to restart automatically or can be started
easily (e.g. execve a suid program), then trying for 4k times can be
done in one day even when each attempt takes 20s.
Increasing it to 18 makes brute-force much more difficult and leaves
more time for operators to find out attacks.
On 64-bit platforms, virtual address space is cheap, so the
randomization bits can be increased safely without disturbing userland.
In 1091458d09e1 ("MIPS: Randomize mmap if randomize_va_space is set")
where mmap randomization was first introduced to MIPS, the randomization
range was 256 MiB, equivalent to 16 randomization bits (if 4K page size).
In 109c32ffd89d ("MIPS: Add support for ARCH_MMAP_RND_{COMPAT_}BITS")
where MIPS begin to use ARCH_MMAP_RND_BITS, commit message claimed:
> The minimum(default) for 64bit is 12bits, again with 4k
> pagesize this is the same as the current 256MB.
which is incorrect. (1 << 12) * page_size is 256 MiB only when page size
is 64 KiB, so the strength of mmap randomization was reduced by 4b.
Fixes: 109c32ffd89d ("MIPS: Add support for ARCH_MMAP_RND_{COMPAT_}BITS")
Signed-off-by: Bingwu Zhang <xtex@astrafall.org>
---
arch/mips/Kconfig | 8 ++++----
1 file changed, 4 insertions(+), 4 deletions(-)
diff --git a/arch/mips/Kconfig b/arch/mips/Kconfig
index e48b62b4dc48..c630dab44419 100644
--- a/arch/mips/Kconfig
+++ b/arch/mips/Kconfig
@@ -3063,11 +3063,11 @@ config MMU
default y
config ARCH_MMAP_RND_BITS_MIN
- default 12 if 64BIT
- default 8
-
-config ARCH_MMAP_RND_BITS_MAX
default 18 if 64BIT
+ default 8
+
+config ARCH_MMAP_RND_BITS_MAX
+ default 20 if 64BIT
default 15
config ARCH_MMAP_RND_COMPAT_BITS_MIN
base-commit: be762d8b6dd7efacb61937d20f8475db8f207655
--
2.52.0
^ permalink raw reply related
* Re: [PATCH net-next v2] declance: Remove IRQF_ONESHOT
From: Maciej W. Rozycki @ 2026-03-29 20:27 UTC (permalink / raw)
To: Sebastian Andrzej Siewior
Cc: netdev, linux-mips, Jakub Kicinski, Andrew Lunn, David S. Miller,
Eric Dumazet, Paolo Abeni
In-Reply-To: <alpine.DEB.2.21.2601271739250.40317@angie.orcam.me.uk>
On Tue, 27 Jan 2026, Maciej W. Rozycki wrote:
> > > I need more data to conclude whether this is the right change to make I'm
> > > afraid. Thank you for looking into it though.
> >
> > Fair enough. Would it work for you if we scratch this from net-next and
> > you route this or something else via the mips tree?
>
> No need to, I think I understand the situation now. Surely the comment
> referring IRQF_ONESHOT in arch/mips/dec/ioasic-irq.c needs to be removed,
> but otherwise this is:
>
> Acked-by: Maciej W. Rozycki <macro@orcam.me.uk>
>
> Thank you for clarifying this to me, and doing the clean-up in the first
> place!
I've now got back to it and while preparing the justification for the
removal of the IRQF_ONESHOT recommendation and having looked through
Documentation/core-api/real-time/differences.rst I became stumped and
need a further clarification after all.
I read in the document that:
"However, on a PREEMPT_RT system, interrupts are forced-threaded and no
longer run in hard IRQ context."
and:
"All interrupts are forced-threaded in a PREEMPT_RT system. The exceptions
are interrupts that are requested with the IRQF_NO_THREAD, IRQF_PERCPU, or
IRQF_ONESHOT flags."
-- do I infer correctly that on a PREEMPT_RT system in the absence of any
flags passed to request_irq() the handler requested such as one concerned
here (i.e. lance_dma_merr_int()) will run with interrupts locally enabled
on the CPU?
If so, then either we need to go back and make sure the originating IRQ
line is masked throughout the execution of the handler (and no standard
irq-flow method provides it), or any IOASIC DMA error interrupt handlers,
including this one, have to use the IRQF_NO_THREAD flag instead or the CPU
will hang looping on the interrupt being retriggered at enable time, as in
the absence of masking the interrupt output of the interrupt controller
remains active until the final EOI action. Have I missed anything?
Mind that this is somewhat theoretical, given that declance.c is only for
systems using the MIPS CPU and arch/mips does not enable ARCH_SUPPORTS_RT,
however should it do sometime, I'd rather all the hell didn't break loose.
And there's previous art already as I can see IRQF_NO_THREAD used through
arch/mips, following commit 5a4a4ad851dd ("MIPS: Mark cascade and low
level interrupts IRQF_NO_THREAD").
Maciej
^ permalink raw reply
* Re: [PATCH 1/2] MIPS/input: Move RB532 button to GPIO descriptors
From: Dmitry Torokhov @ 2026-03-29 22:38 UTC (permalink / raw)
To: Linus Walleij
Cc: Thomas Bogendoerfer, Bartosz Golaszewski, Miquel Raynal,
Richard Weinberger, Vignesh Raghavendra, linux-mips, linux-input,
linux-gpio, linux-mtd
In-Reply-To: <20260328-mips-input-rb532-button-v1-1-98e201621501@kernel.org>
Hi Linus,
On Sat, Mar 28, 2026 at 04:55:47PM +0100, Linus Walleij wrote:
> Convert the Mikrotik RouterBoard RB532 to use GPIO descriptors
> by defining a software node for the GPIO chip, then register
> the button platform device with full info passing the GPIO
> as a device property.
>
> This can be used as a base to move more of the RB532 devices
> over to passing GPIOs using device properties.
>
> Use the GPIO_ACTIVE_LOW flag and drop the inversion in the
> rb532_button_pressed() function.
>
> Signed-off-by: Linus Walleij <linusw@kernel.org>
> ---
> arch/mips/rb532/devices.c | 47 +++++++++++++++++++++++++++++++++------
> drivers/input/misc/rb532_button.c | 35 ++++++++++++++++++++++++-----
> 2 files changed, 69 insertions(+), 13 deletions(-)
>
> diff --git a/arch/mips/rb532/devices.c b/arch/mips/rb532/devices.c
> index 4f027efbf27b..3f56d9feb73a 100644
> --- a/arch/mips/rb532/devices.c
> +++ b/arch/mips/rb532/devices.c
> @@ -16,8 +16,10 @@
> #include <linux/mtd/mtd.h>
> #include <linux/gpio.h>
> #include <linux/gpio/machine.h>
> +#include <linux/gpio/property.h>
> #include <linux/gpio_keys.h>
> #include <linux/input.h>
> +#include <linux/property.h>
> #include <linux/serial_8250.h>
>
> #include <asm/bootinfo.h>
> @@ -38,6 +40,10 @@ extern unsigned int idt_cpu_freq;
>
> static struct mpmc_device dev3;
>
> +static const struct software_node rb532_gpio0_node = {
> + .name = "gpio0",
> +};
You need to move this and registration into arch/mips/rb532/gpio.c,
export it and use it here: Bartosz is against using gpiohip label to
match with software node name and prefers identity matching.
...
> -static bool rb532_button_pressed(void)
> +static bool rb532_button_pressed(struct rb532_button *button)
> {
> int val;
>
> set_latch_u5(0, LO_FOFF);
> - gpio_direction_input(GPIO_BTN_S1);
> + gpiod_direction_input(button->gpio);
>
> - val = gpio_get_value(GPIO_BTN_S1);
> + val = gpiod_get_value(button->gpio);
>
> rb532_gpio_set_func(GPIO_BTN_S1);
> set_latch_u5(LO_FOFF, 0);
>
> - return !val;
> + return val;
> }
I suppose there is no reasonable way of making this work with
gpio-keys...
For input piece:
Acked-by: Dmitry Torokhov <dmitry.torokhov@gmail.com>
Thanks.
--
Dmitry
^ permalink raw reply
* [PATCH] MIPS: Fix the GCC version check for `__multi3' workaround
From: Maciej W. Rozycki @ 2026-03-30 1:54 UTC (permalink / raw)
To: Thomas Bogendoerfer; +Cc: linux-mips, linux-kernel
It was only GCC 10 that fixed a MIPS64r6 code generation issue with a
`__multi3' libcall inefficiently produced to perform 64-bit widening
multiplication while suitable machine instructions exist to do such a
calculation. The fix went in with GCC commit 48b2123f6336 ("re PR
target/82981 (unnecessary __multi3 call for mips64r6 linux kernel)").
Adjust our code accordingly, removing build failures such as:
mips64-linux-ld: lib/math/div64.o: in function `mul_u64_add_u64_div_u64':
div64.c:(.text+0x84): undefined reference to `__multi3'
with the GCC versions affected.
Fixes: ebabcf17bcd7 ("MIPS: Implement __multi3 for GCC7 MIPS64r6 builds")
Reported-by: kernel test robot <lkp@intel.com>
Closes: https://lore.kernel.org/oe-kbuild-all/202601140146.hMLODc6v-lkp@intel.com/
Signed-off-by: Maciej W. Rozycki <macro@orcam.me.uk>
Cc: stable@vger.kernel.org # v4.15+
---
arch/mips/lib/multi3.c | 6 +++---
1 file changed, 3 insertions(+), 3 deletions(-)
linux-mips-multi3-gcc10.diff
Index: linux-macro/arch/mips/lib/multi3.c
===================================================================
--- linux-macro.orig/arch/mips/lib/multi3.c
+++ linux-macro/arch/mips/lib/multi3.c
@@ -4,12 +4,12 @@
#include "libgcc.h"
/*
- * GCC 7 & older can suboptimally generate __multi3 calls for mips64r6, so for
+ * GCC 9 & older can suboptimally generate __multi3 calls for mips64r6, so for
* that specific case only we implement that intrinsic here.
*
* See https://gcc.gnu.org/bugzilla/show_bug.cgi?id=82981
*/
-#if defined(CONFIG_64BIT) && defined(CONFIG_CPU_MIPSR6) && (__GNUC__ < 8)
+#if defined(CONFIG_64BIT) && defined(CONFIG_CPU_MIPSR6) && (__GNUC__ < 10)
/* multiply 64-bit values, low 64-bits returned */
static inline long long notrace dmulu(long long a, long long b)
@@ -51,4 +51,4 @@ ti_type notrace __multi3(ti_type a, ti_t
}
EXPORT_SYMBOL(__multi3);
-#endif /* 64BIT && CPU_MIPSR6 && GCC7 */
+#endif /* 64BIT && CPU_MIPSR6 && GCC9 */
^ permalink raw reply
* Re: [PATCH] drivers: pcmcia: remove obsolete host controller drivers
From: Dominik Brodowski @ 2026-03-30 5:45 UTC (permalink / raw)
To: Ethan Nelson-Moore
Cc: linux-kernel, linux-mips, linux-pci, Thomas Bogendoerfer,
Madhavan Srinivasan, Michael Ellerman, Nicholas Piggin,
Christophe Leroy (CS GROUP), Thomas Gleixner, Ingo Molnar,
Borislav Petkov, Dave Hansen, x86, H. Peter Anvin, Bjorn Helgaas,
Jakub Kicinski, Theodore Ts'o, Eric Biggers, Simon Horman,
Lukas Bulwahn
In-Reply-To: <20260309074226.25937-1-enelsonmoore@gmail.com>
Am Mon, Mar 09, 2026 at 12:41:48AM -0700 schrieb Ethan Nelson-Moore:
> PCMCIA is almost completely obsolete (the last computers supporting it
> natively were from ~2009), and the general consensus [1] seems to be
> that support for it should be gradually removed from the kernel.
>
> In 2023, an initial step of removing all the PCMCIA char drivers was
> taken in commit 9b12f050c76f ("char: pcmcia: remove all the drivers"),
> and that has not been reverted, so it seems logical to continue this
> process by removing more low-hanging fruit.
>
> These host controller drivers have had no meaningful changes since
> their status was discussed in 2022 [2], and are unlikely to have any
> remaining users. Remove them and a couple references to them
> in comments.
>
> The i82365 and tcic drivers are for ISA-attached host controllers,
> which are even less likely to be used nowadays than ones on other buses.
>
> The i82092 driver has almost certainly not been used in over 20 years.
> It was broken by a null pointer dereference since the dawn of Git
> history (2.6.12-rc2 in 2005) until someone fixed it in 2021 in commit
> e39cdacf2f66 ("pcmcia: i82092: fix a null pointer dereference bug").
> From their dmesg log [3], it is clear they were testing in an emulated
> environment and not on real hardware.
>
> i82365.h is used by drivers other than i82365 and is therefore retained.
>
> [1] https://lore.kernel.org/all/c5b39544-a4fb-4796-a046-0b9be9853787@app.fastmail.com/
> [2] https://lore.kernel.org/all/Y07d7rMvd5++85BJ@owl.dominikbrodowski.net/
> [3] https://lore.kernel.org/all/1624345891-4215-1-git-send-email-zheyuma97@gmail.com/
>
> Signed-off-by: Ethan Nelson-Moore <enelsonmoore@gmail.com>
Applied to pcmcia-next.
Thanks,
Dominik
^ permalink raw reply
* Re: [PATCH 2/2] MIPS/mtd: Handle READY GPIO in generic NAND platform data
From: Miquel Raynal @ 2026-03-30 8:04 UTC (permalink / raw)
To: Linus Walleij
Cc: Thomas Bogendoerfer, Dmitry Torokhov, Bartosz Golaszewski,
Richard Weinberger, Vignesh Raghavendra, linux-mips, linux-input,
linux-gpio, linux-mtd
In-Reply-To: <20260328-mips-input-rb532-button-v1-2-98e201621501@kernel.org>
On 28/03/2026 at 16:55:48 +01, Linus Walleij <linusw@kernel.org> wrote:
> The callbacks into the MIPS RB532 platform to read the GPIO pin
> indicating that the NAND chip is ready are oldschool and does
> not assign GPIOs as properties to the NAND device.
>
> Add a capability to the generic platform NAND chip driver to use
> a GPIO line to detect if a NAND chip is ready and override the
> platform-local drv_ready() callback with this check if the GPIO
> is present.
>
> This makes it possible to drop the legacy include header
> <linux/gpio.h> from the RB532 devices.
>
> Signed-off-by: Linus Walleij <linusw@kernel.org>
> ---
> arch/mips/rb532/devices.c | 36 +++++++++++++++++++++---------------
> drivers/mtd/nand/raw/plat_nand.c | 24 +++++++++++++++++++++++-
Fine by me for the MTD bits!
Acked-by: Miquel Raynal <miquel.raynal@bootlin.com>
Thanks,
Miquèl
^ permalink raw reply
* Re: [PATCH 1/2] MIPS/input: Move RB532 button to GPIO descriptors
From: Bartosz Golaszewski @ 2026-03-30 9:12 UTC (permalink / raw)
To: Linus Walleij
Cc: linux-mips, linux-input, linux-gpio, linux-mtd,
Thomas Bogendoerfer, Dmitry Torokhov, Bartosz Golaszewski,
Miquel Raynal, Richard Weinberger, Vignesh Raghavendra
In-Reply-To: <20260328-mips-input-rb532-button-v1-1-98e201621501@kernel.org>
On Sat, 28 Mar 2026 16:55:47 +0100, Linus Walleij <linusw@kernel.org> said:
> Convert the Mikrotik RouterBoard RB532 to use GPIO descriptors
> by defining a software node for the GPIO chip, then register
> the button platform device with full info passing the GPIO
> as a device property.
>
> This can be used as a base to move more of the RB532 devices
> over to passing GPIOs using device properties.
>
> Use the GPIO_ACTIVE_LOW flag and drop the inversion in the
> rb532_button_pressed() function.
>
> Signed-off-by: Linus Walleij <linusw@kernel.org>
> ---
> arch/mips/rb532/devices.c | 47 +++++++++++++++++++++++++++++++++------
> drivers/input/misc/rb532_button.c | 35 ++++++++++++++++++++++++-----
> 2 files changed, 69 insertions(+), 13 deletions(-)
>
> diff --git a/arch/mips/rb532/devices.c b/arch/mips/rb532/devices.c
> index 4f027efbf27b..3f56d9feb73a 100644
> --- a/arch/mips/rb532/devices.c
> +++ b/arch/mips/rb532/devices.c
> @@ -16,8 +16,10 @@
> #include <linux/mtd/mtd.h>
> #include <linux/gpio.h>
> #include <linux/gpio/machine.h>
> +#include <linux/gpio/property.h>
> #include <linux/gpio_keys.h>
> #include <linux/input.h>
> +#include <linux/property.h>
> #include <linux/serial_8250.h>
>
> #include <asm/bootinfo.h>
> @@ -38,6 +40,10 @@ extern unsigned int idt_cpu_freq;
>
> static struct mpmc_device dev3;
>
> +static const struct software_node rb532_gpio0_node = {
> + .name = "gpio0",
> +};
> +
Hi Linus!
I'm seeing patches from you lately using the pattern of "dangling software"
nodes that's documented under Documentation/driver-api/gpio/board.rst as the
recommended approach but which I have been trying to come up with a better
alternetive for and eventually phase out. I will post a series providing a way
to automatically assign software nodes as secondary firmware nodes for devices
and this series will also remove the offending bits from the docs.
As you're dealing with a board file here: could you assign the firmware node
you get after registering this software node to the target GPIO controller
under arch/mips/rb532/gpio.c so that the firmware node lookup can work by
matching the address rather than falling back to the label string matching?
Thanks,
Bartosz
^ permalink raw reply
* Re: [PATCH] MIPS: Fix the GCC version check for `__multi3' workaround
From: David Laight @ 2026-03-30 9:46 UTC (permalink / raw)
To: Maciej W. Rozycki; +Cc: Thomas Bogendoerfer, linux-mips, linux-kernel
In-Reply-To: <alpine.DEB.2.21.2603300218310.60268@angie.orcam.me.uk>
On Mon, 30 Mar 2026 02:54:09 +0100 (BST)
"Maciej W. Rozycki" <macro@orcam.me.uk> wrote:
> It was only GCC 10 that fixed a MIPS64r6 code generation issue with a
> `__multi3' libcall inefficiently produced to perform 64-bit widening
> multiplication while suitable machine instructions exist to do such a
> calculation. The fix went in with GCC commit 48b2123f6336 ("re PR
> target/82981 (unnecessary __multi3 call for mips64r6 linux kernel)").
>
> Adjust our code accordingly, removing build failures such as:
>
> mips64-linux-ld: lib/math/div64.o: in function `mul_u64_add_u64_div_u64':
> div64.c:(.text+0x84): undefined reference to `__multi3'
>
> with the GCC versions affected.
>
> Fixes: ebabcf17bcd7 ("MIPS: Implement __multi3 for GCC7 MIPS64r6 builds")
> Reported-by: kernel test robot <lkp@intel.com>
> Closes: https://lore.kernel.org/oe-kbuild-all/202601140146.hMLODc6v-lkp@intel.com/
> Signed-off-by: Maciej W. Rozycki <macro@orcam.me.uk>
> Cc: stable@vger.kernel.org # v4.15+
Reviewed-by: David Laight <david.laight.linux@gmail.com.
Although it might be worth just deleting the version check.
__multi3 is unconditionally defined for sparc64 and that is a much
more complex function rather than the pretty trivial mips64 version.
> ---
> arch/mips/lib/multi3.c | 6 +++---
> 1 file changed, 3 insertions(+), 3 deletions(-)
>
> linux-mips-multi3-gcc10.diff
> Index: linux-macro/arch/mips/lib/multi3.c
> ===================================================================
> --- linux-macro.orig/arch/mips/lib/multi3.c
> +++ linux-macro/arch/mips/lib/multi3.c
> @@ -4,12 +4,12 @@
> #include "libgcc.h"
>
> /*
> - * GCC 7 & older can suboptimally generate __multi3 calls for mips64r6, so for
> + * GCC 9 & older can suboptimally generate __multi3 calls for mips64r6, so for
> * that specific case only we implement that intrinsic here.
> *
> * See https://gcc.gnu.org/bugzilla/show_bug.cgi?id=82981
> */
> -#if defined(CONFIG_64BIT) && defined(CONFIG_CPU_MIPSR6) && (__GNUC__ < 8)
> +#if defined(CONFIG_64BIT) && defined(CONFIG_CPU_MIPSR6) && (__GNUC__ < 10)
>
> /* multiply 64-bit values, low 64-bits returned */
> static inline long long notrace dmulu(long long a, long long b)
> @@ -51,4 +51,4 @@ ti_type notrace __multi3(ti_type a, ti_t
> }
> EXPORT_SYMBOL(__multi3);
>
> -#endif /* 64BIT && CPU_MIPSR6 && GCC7 */
> +#endif /* 64BIT && CPU_MIPSR6 && GCC9 */
>
^ permalink raw reply
* Re: [PATCH] MIPS: Fix the GCC version check for `__multi3' workaround
From: Maciej W. Rozycki @ 2026-03-30 10:09 UTC (permalink / raw)
To: David Laight; +Cc: Thomas Bogendoerfer, linux-mips, linux-kernel
In-Reply-To: <20260330104644.1da584e1@pumpkin>
On Mon, 30 Mar 2026, David Laight wrote:
> Although it might be worth just deleting the version check.
> __multi3 is unconditionally defined for sparc64 and that is a much
> more complex function rather than the pretty trivial mips64 version.
We want to catch invalid usage or we could just link with libgcc.a.
Maciej
^ permalink raw reply
* Re: [PATCH] MIPS: Fix the GCC version check for `__multi3' workaround
From: David Laight @ 2026-03-30 11:52 UTC (permalink / raw)
To: Maciej W. Rozycki; +Cc: Thomas Bogendoerfer, linux-mips, linux-kernel
In-Reply-To: <alpine.DEB.2.21.2603301108170.60268@angie.orcam.me.uk>
On Mon, 30 Mar 2026 11:09:43 +0100 (BST)
"Maciej W. Rozycki" <macro@orcam.me.uk> wrote:
> On Mon, 30 Mar 2026, David Laight wrote:
>
> > Although it might be worth just deleting the version check.
> > __multi3 is unconditionally defined for sparc64 and that is a much
> > more complex function rather than the pretty trivial mips64 version.
>
> We want to catch invalid usage or we could just link with libgcc.a.
That would pull in all sorts of expensive functions - like divides.
One option would be have a 'u128 mul_u64_u64_u128(u64, u64)' function
that architectures could define, defaulting to (u128)a * b.
Similar definitions exist for mixed u64/u32 arithmetic on 32bit because
gcc tends to make a proverbial 'pig's breakfast' of compiling it.
(I've seen explicit multiplies by constant zeros that have been spilled
to stack!)
I recently improved/optimised the nolibc snprintf() code; that fell over
the same problem (on both mips64 and sparc64) doing the div/rem by 10
using multiply by reciprocal. I'm not sure how the kernel snprintf()
does the conversion - the entire function needs some TLC.
(That would probably speed up things like 'cat /proc/interrupts'.)
David
>
> Maciej
>
^ permalink raw reply
page: next (older) | prev (newer) | latest
- recent:[subjects (threaded)|topics (new)|topics (active)]
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox