realtek: 6.12: relocate R4K deactivation to late CPU init

To avoid unneeded interrupts the R4K timer is deactivated during
secondary cpu initialization. This is currently done during
phase init_secondary(). With the upgrade to 6.12 the kernel runs
a primary/secondary cpu timer/counter synchronization to verify the
proper setup in synchronise_count_slave(). That runs at a later
point in time and expects the secondary counter to be fully
functional. Finding a deactivated counter results in the following
messages:

WARNING: CPU: 1 PID: 0 at arch/mips/kernel/sync-r4k.c:99 check_counter_warp+0x220/0x254
Warning: zero counter calibration delta: 0 [max: 6500000]
Counter synchronization [CPU#0 -> CPU#1]:
Measured 278760029 cycles counter warp between CPUs

Relocate the deactivation to smp_finsh() at the end of the cpu
startup sequence. Additionally polish the startup code and remove
all unneeded parts.

Signed-off-by: Markus Stockhausen <markus.stockhausen@gmx.de>
Link: https://github.com/openwrt/openwrt/pull/18935
Signed-off-by: Robert Marko <robimarko@gmail.com>
This commit is contained in:
Markus Stockhausen 2025-05-28 13:41:32 -04:00 committed by Robert Marko
parent 09440d9858
commit e124859587

View file

@ -9,66 +9,69 @@
* *
*/ */
#include <linux/init.h>
#include <linux/kernel.h>
#include <linux/string.h>
#include <linux/of_fdt.h>
#include <linux/libfdt.h>
#include <asm/bootinfo.h>
#include <asm/addrspace.h>
#include <asm/page.h>
#include <asm/cpu.h>
#include <asm/fw/fw.h> #include <asm/fw/fw.h>
#include <asm/mips-cps.h>
#include <asm/prom.h> #include <asm/prom.h>
#include <asm/smp-ops.h> #include <asm/smp-ops.h>
#include <asm/mips-cps.h>
#include <mach-rtl83xx.h> #include <mach-rtl83xx.h>
extern char arcs_cmdline[];
struct rtl83xx_soc_info soc_info; struct rtl83xx_soc_info soc_info;
const void *fdt; const void *fdt;
#ifdef CONFIG_MIPS_MT_SMP #ifdef CONFIG_MIPS_MT_SMP
extern const struct plat_smp_ops vsmp_smp_ops;
static struct plat_smp_ops rtl_smp_ops;
static void rtl_init_secondary(void) extern const struct plat_smp_ops vsmp_smp_ops;
static struct plat_smp_ops rtlops;
static void rtlsmp_init_secondary(void)
{ {
#ifndef CONFIG_CEVT_R4K
/* /*
* These devices are low on resources. There might be the chance that CEVT_R4K * Enable all CPU interrupts, as everything is managed by the external controller.
* is not enabled in kernel build. Nevertheless the timer and interrupt 7 might * TODO: Standard vsmp_init_secondary() has special treatment for Malta if external
* be active by default after startup of secondary VPE. With no registered * GIC is available. Maybe we need this too.
* handler that leads to continuous unhandeled interrupts. In this case disable
* counting (DC) in the core and confirm a pending interrupt.
*/
write_c0_cause(read_c0_cause() | CAUSEF_DC);
write_c0_compare(0);
#endif /* CONFIG_CEVT_R4K */
/*
* Enable all CPU interrupts, as everything is managed by the external
* controller. TODO: Standard vsmp_init_secondary() has special treatment for
* Malta if external GIC is available. Maybe we need this too.
*/ */
if (mips_gic_present()) if (mips_gic_present())
pr_warn("%s: GIC present. Maybe interrupt enabling required.\n", __func__); pr_warn("%s: GIC present. Maybe interrupt enabling required.\n", __func__);
else else
set_c0_status(ST0_IM); set_c0_status(ST0_IM);
} }
#endif /* CONFIG_MIPS_MT_SMP */
const char *get_system_type(void) static void rtlsmp_finish(void)
{ {
return soc_info.name; /* These devices are low on resources. There might be the chance that CEVT_R4K is
* not enabled in kernel build. Nevertheless the timer and interrupt 7 might be
* active by default after startup of secondary VPE. With no registered handler
* that leads to continuous unhandeled interrupts. In this case disable counting
* (DC) in the core and confirm a pending interrupt.
*/
if (!IS_ENABLED(CONFIG_CEVT_R4K)) {
write_c0_cause(read_c0_cause() | CAUSEF_DC);
write_c0_compare(0);
} }
void __init prom_free_prom_memory(void) local_irq_enable();
{
} }
static int rtlsmp_register(void)
{
if (!cpu_has_mipsmt)
return 1;
rtlops = vsmp_smp_ops;
rtlops.init_secondary = rtlsmp_init_secondary;
rtlops.smp_finish = rtlsmp_finish;
register_smp_ops(&rtlops);
return 0;
}
#else /* !CONFIG_MIPS_MT_SMP */
#define rtlsmp_register() (1)
#endif
void __init device_tree_init(void) void __init device_tree_init(void)
{ {
if (!fdt_check_header(&__appended_dtb)) { if (!fdt_check_header(&__appended_dtb)) {
@ -84,18 +87,17 @@ void __init device_tree_init(void)
if (!register_cps_smp_ops()) if (!register_cps_smp_ops())
return; return;
#ifdef CONFIG_MIPS_MT_SMP if (!rtlsmp_register())
if (cpu_has_mipsmt) {
rtl_smp_ops = vsmp_smp_ops;
rtl_smp_ops.init_secondary = rtl_init_secondary;
register_smp_ops(&rtl_smp_ops);
return; return;
}
#endif
register_up_smp_ops(); register_up_smp_ops();
} }
const char *get_system_type(void)
{
return soc_info.name;
}
static void __init identify_rtl9302(void) static void __init identify_rtl9302(void)
{ {
switch (sw_r32(RTL93XX_MODEL_NAME_INFO) & 0xfffffff0) { switch (sw_r32(RTL93XX_MODEL_NAME_INFO) & 0xfffffff0) {